PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/build/pojoviz.js

https://github.com/artlantis/PojoViz
JavaScript | 1402 lines | 969 code | 178 blank | 255 comment | 99 complexity | b9bb55e10e271b1fcfe24df3da907f2f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.pojoviz=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"dagre":[function(_dereq_,module,exports){
  2. module.exports=_dereq_('JWa/F1');
  3. },{}],"lodash":[function(_dereq_,module,exports){
  4. module.exports=_dereq_('K2RcUv');
  5. },{}],"q":[function(_dereq_,module,exports){
  6. module.exports=_dereq_('qLuPo1');
  7. },{}],4:[function(_dereq_,module,exports){
  8. var HashMap = _dereq_('./util/HashMap'),
  9. hashKey = _dereq_('./util/hashKey'),
  10. _ = _dereq_('lodash');
  11. // utils
  12. function eachObjectAndPrototype(obj, fn) {
  13. fn(obj);
  14. if (obj.hasOwnProperty('prototype')) {
  15. fn(obj.prototype);
  16. }
  17. }
  18. /**
  19. * Wraps a function with another
  20. * @param {Function} fn
  21. * @param {Function} wrapper
  22. * @return {*}
  23. */
  24. function wrapFn(fn, wrapper) {
  25. return function () {
  26. // NOTE: `this` will be the instance
  27. wrapper.call(this);
  28. var args = [].slice.call(arguments);
  29. return fn.apply(this, args);
  30. };
  31. }
  32. function isObjectOrFunction(v) {
  33. return !!(v && (typeof v === 'object' ||
  34. typeof v === 'function'));
  35. }
  36. /**
  37. * Properties forbidden in strict mode
  38. * @type {Array}
  39. */
  40. var forbiddenInStrictMode = [
  41. 'callee', 'caller', 'arguments'
  42. ];
  43. /**
  44. * @constructor
  45. * Object analyz
  46. * @param {[type]} config [description]
  47. */
  48. function Analyzer(config) {
  49. if (!(this instanceof Analyzer)) {
  50. return new Analyzer(config);
  51. }
  52. config = config || {};
  53. /**
  54. * Objects registered in this instance
  55. * @type {HashMap}
  56. */
  57. this.objects = config.objects || new HashMap();
  58. /**
  59. * Forbidden objects
  60. * @type {HashMap}
  61. */
  62. this.forbidden = config.forbidden || new HashMap();
  63. /**
  64. * Cache of properties
  65. * @type {Object}
  66. */
  67. this.__cacheObjects = {};
  68. /**
  69. * Cache of links
  70. * @type {Object}
  71. */
  72. this.__cacheLinks = {};
  73. /**
  74. * Dfs levels
  75. * @type {number}
  76. */
  77. this.levels = Infinity;
  78. /**
  79. * If the analyzer is dirty then it has some pending work
  80. * to do
  81. * @type {boolean}
  82. */
  83. this.dirty = true;
  84. /**
  85. * True to save the properties of the objects analyzed in an
  86. * internal cache
  87. * @type {Boolean}
  88. */
  89. this.cache =
  90. config.hasOwnProperty('cache') ?
  91. config.cache : true;
  92. /**
  93. * True to include function constructors in the analysis graph
  94. * i.e. the functions that have a prototype
  95. * @type {boolean}
  96. */
  97. this.functionConstructors =
  98. config.hasOwnProperty('functionConstructors') ?
  99. config.functionConstructors : false;
  100. /**
  101. * True to include all the functions in the analysis graph
  102. * @type {boolean}
  103. */
  104. this.allFunctions =
  105. config.hasOwnProperty('allFunctions') ?
  106. config.allFunctions : false;
  107. /**
  108. * True to allow HTML nodes
  109. * @type {boolean}
  110. */
  111. this.htmlNode =
  112. config.hasOwnProperty('htmlNode') ?
  113. config.htmlNode : false;
  114. }
  115. Analyzer.prototype = {
  116. constructor: Analyzer,
  117. /**
  118. * Checks if an object is in the forbidden hash
  119. * @param {Object} obj
  120. * @return {boolean}
  121. */
  122. isForbidden: function (obj) {
  123. return this.forbidden.get(obj);
  124. },
  125. isLinkable: function (key, obj) {
  126. if (!obj) {
  127. return false;
  128. }
  129. var v = typeof obj === 'object';
  130. // if (v) {
  131. // if (!this.htmlNode && v instanceof Node) { return false; }
  132. // return true;
  133. // }
  134. // if (!this.htmlNode) {
  135. // v = v && !(v instanceof Node);
  136. // }fdeq1`
  137. // typeof obj === 'function' &&
  138. // console.log(Object.getOwnPropertyNames(obj));
  139. if (!v && this.allFunctions) {
  140. // minimize the nodes created by considering functions
  141. // with more properties than the usual ones
  142. v = typeof obj === 'function';
  143. v = v && Object.getOwnPropertyNames(obj).length > 5;
  144. }
  145. if (!v && this.functionConstructors) {
  146. v = typeof obj === 'function';
  147. v = v && (
  148. obj.name &&
  149. obj.name[0].match(/^[A-Z]/) ||
  150. key[0].match(/^[A-Z]/)
  151. );
  152. }
  153. return v;
  154. },
  155. /**
  156. * Gets the enumerable properties an object discarding
  157. * forbidden ones
  158. *
  159. * @param {Object} obj
  160. * @return {Array} Array of objects, each object has the following
  161. * properties:
  162. *
  163. * - name
  164. * - cls
  165. * - type
  166. * - linkeable (if it's an object this property is set to true)
  167. */
  168. getProperties: function (obj, linkableOnly) {
  169. var me = this,
  170. hk = hashKey(obj),
  171. properties;
  172. if (!obj) {
  173. throw 'this method needs an object to analyze';
  174. }
  175. if (this.cache) {
  176. if (!linkableOnly && this.__cacheObjects[hk]) {
  177. // console.log('objects from cache :)');
  178. return this.__cacheObjects[hk];
  179. }
  180. }
  181. properties = Object.getOwnPropertyNames(obj);
  182. function forbiddenKey(v) {
  183. // forbidden in strict mode
  184. return ~forbiddenInStrictMode.indexOf(v) ||
  185. v.match(/^__.*?__$/) ||
  186. v.match(/^\$\$.*?\$\$$/) ||
  187. v.match(/[:+~!><=//\[\]@\. ]/);
  188. }
  189. properties = _.filter(properties, function (v) {
  190. var good = typeof v === 'string' && !forbiddenKey(v),
  191. r;
  192. if (linkableOnly) {
  193. try {
  194. r = good && me.isLinkable(v, obj[v]);
  195. } catch (e) {
  196. r = false;
  197. // uncomment to see why obj[v] is not allowed
  198. // console.log(e);
  199. } finally {
  200. return r;
  201. }
  202. }
  203. return good;
  204. }).map(function (v) {
  205. var type,
  206. linkeable;
  207. try {
  208. // type = null|string|undefined|number|object
  209. type = typeof obj[v];
  210. linkeable = isObjectOrFunction(obj[v]);
  211. } catch(e) {
  212. type = 'undefined';
  213. linkeable = false;
  214. }
  215. return {
  216. // parent: hashKey(obj),
  217. name: v,
  218. type: type,
  219. linkeable: linkeable
  220. };
  221. });
  222. // special properties
  223. var proto = Object.getPrototypeOf(obj);
  224. if (proto) {
  225. properties.push({
  226. name: '[[Prototype]]',
  227. // cls: hashKey(obj),
  228. type: 'object',
  229. linkeable: true,
  230. hidden: true
  231. });
  232. }
  233. var constructor = obj.hasOwnProperty &&
  234. obj.hasOwnProperty('constructor') &&
  235. typeof obj.constructor === 'function';
  236. if (constructor &&
  237. _.findIndex(properties, { name: 'constructor' }) === -1) {
  238. properties.push({
  239. // cls: hashKey(obj),
  240. name: 'constructor',
  241. type: 'function',
  242. linkeable: true
  243. });
  244. }
  245. if (this.cache && !linkableOnly) {
  246. this.__cacheObjects[hk] = properties;
  247. }
  248. // console.log(properties);
  249. return properties;
  250. },
  251. /**
  252. * Analyzes a list of objects recursively
  253. * @param {Array} objects Array of objects
  254. * @param {number} currentLevel Current dfs level
  255. */
  256. analyzeObjects: function (objects, currentLevel) {
  257. var me = this;
  258. objects.forEach(function (v) {
  259. if (currentLevel <= me.levels && // dfs level
  260. !me.objects.get(v) && // already registered
  261. !me.isForbidden(v) // forbidden check
  262. ) {
  263. // add to the registered object pool
  264. me.objects.put(v);
  265. // dfs to the next level
  266. me.analyzeObjects(
  267. me.getOwnLinks(v).map(function (link) {
  268. return link.to;
  269. }),
  270. currentLevel + 1
  271. );
  272. }
  273. });
  274. },
  275. /**
  276. * Returns a list of links, each link is an object which has the
  277. * following properties:
  278. *
  279. * - from
  280. * - to
  281. * - property (string)
  282. *
  283. * @param {Object} obj
  284. * @return {Array}
  285. */
  286. getOwnLinks: function (obj) {
  287. var me = this,
  288. links = [],
  289. properties,
  290. name = hashKey(obj);
  291. if (this.__cacheLinks[name]) {
  292. // console.log('links from cache :)');
  293. return this.__cacheLinks[name];
  294. }
  295. properties = me.getProperties(obj, true);
  296. function getAugmentedHash(obj, name) {
  297. if (!hashKey.has(obj) &&
  298. name !== 'prototype' &&
  299. name !== 'constructor') {
  300. hashKey.createHashKeysFor(obj, name);
  301. }
  302. return hashKey(obj);
  303. }
  304. if (!name) {
  305. throw 'the object needs to have a hashkey';
  306. }
  307. _.forEach(properties, function (v) {
  308. var ref = obj[v.name];
  309. // because of the levels a reference might not exist
  310. if (!ref) {
  311. return;
  312. }
  313. // if the object doesn't have a hashkey
  314. // let's give it a name equal to the property
  315. // being analyzed
  316. getAugmentedHash(ref, v.name);
  317. if (!me.isForbidden(ref)) {
  318. links.push({
  319. from: obj,
  320. fromHash: hashKey(obj),
  321. to: ref,
  322. toHash: hashKey(ref),
  323. property: v.name
  324. });
  325. }
  326. });
  327. var proto = Object.getPrototypeOf(obj);
  328. if (proto && !me.isForbidden(proto)) {
  329. links.push({
  330. from: obj,
  331. fromHash: hashKey(obj),
  332. to: proto,
  333. toHash: hashKey(proto),
  334. property: '[[Prototype]]'
  335. });
  336. }
  337. if (this.cache) {
  338. this.__cacheLinks[name] = links;
  339. }
  340. return links;
  341. },
  342. makeDirty: function () {
  343. this.dirty = true;
  344. },
  345. setLevels: function (l) {
  346. this.levels = l;
  347. },
  348. setDirty: function (d) {
  349. this.dirty = d;
  350. },
  351. setFunctionConstructors: function (v) {
  352. this.functionConstructors = v;
  353. },
  354. getObjects: function () {
  355. return this.objects;
  356. },
  357. /**
  358. * Stringifies an object properties
  359. * @param obj
  360. * @param toString
  361. * @return {Array}
  362. */
  363. stringifyObjectProperties: function (obj) {
  364. return this.getProperties(obj);
  365. },
  366. /**
  367. * Returns a representation of the links of
  368. * an object
  369. * @return {Array}
  370. */
  371. stringifyObjectLinks: function (obj) {
  372. var me = this;
  373. return me.getOwnLinks(obj).map(function (link) {
  374. // discarded: from, to
  375. return {
  376. from: link.fromHash,
  377. to: link.toHash,
  378. property: link.property
  379. };
  380. });
  381. },
  382. /**
  383. * Stringifies the objects saved in this analyzer
  384. * @return {Object}
  385. */
  386. stringify: function () {
  387. var me = this,
  388. nodes = {},
  389. edges = {};
  390. console.time('stringify');
  391. _(this.objects).forOwn(function (v) {
  392. nodes[hashKey(v)] = me.stringifyObjectProperties(v);
  393. edges[hashKey(v)] = me.stringifyObjectLinks(v);
  394. });
  395. console.timeEnd('stringify');
  396. return {
  397. nodes: nodes,
  398. edges: edges
  399. };
  400. }
  401. };
  402. // aditional objects that need the prototype to exist
  403. var aProto = Analyzer.prototype;
  404. _.merge(aProto, {
  405. /**
  406. * Adds a list of objects to analyze and make the analyzer dirty
  407. * @param {Array<Objects>} objects
  408. * @return {this}
  409. */
  410. add: wrapFn(function (objects) {
  411. console.time('analyze');
  412. this.analyzeObjects(objects, 0);
  413. console.timeEnd('analyze');
  414. return this;
  415. }, aProto.makeDirty),
  416. /**
  417. * Removes a list of objects, if `withPrototype` is true then
  418. * also the prototype is removed
  419. * @param {Array<Objects>} objects
  420. * @param {boolean} withPrototype
  421. * @return {this}
  422. */
  423. remove: wrapFn(function (objects, withPrototype) {
  424. var me = this;
  425. objects.forEach(function (obj) {
  426. me.objects.remove(obj);
  427. if (withPrototype && obj.hasOwnProperty('prototype')) {
  428. me.objects.remove(obj.prototype);
  429. }
  430. });
  431. return me;
  432. }, aProto.makeDirty),
  433. /**
  434. * Forbids a list of objects, if `withPrototype` is true then
  435. * also the prototype is forbidden
  436. * @param {Array<Objects>} objects
  437. * @param {boolean} withPrototype
  438. * @return {this}
  439. */
  440. forbid: wrapFn(function (objects, withPrototype) {
  441. var me = this;
  442. me.remove(objects, withPrototype);
  443. objects.forEach(function (obj) {
  444. me.forbidden.put(obj);
  445. if (withPrototype && obj.hasOwnProperty('prototype')) {
  446. me.forbidden.put(obj.prototype);
  447. }
  448. });
  449. }, aProto.makeDirty),
  450. /**
  451. * Unforbids a list of objects, if `withPrototype` is true then
  452. * also the prototype is unforbidden
  453. * @param {Array<Objects>} objects
  454. * @param {boolean} withPrototype
  455. * @return {this}
  456. */
  457. unforbid: wrapFn(function (objects, withPrototype) {
  458. var me = this;
  459. objects.forEach(function (obj) {
  460. me.forbidden.remove(obj);
  461. if (withPrototype && obj.hasOwnProperty('prototype')) {
  462. me.forbidden.remove(obj.prototype);
  463. }
  464. });
  465. }, aProto.makeDirty)
  466. });
  467. module.exports = Analyzer;
  468. },{"./util/HashMap":12,"./util/hashKey":13,"lodash":"K2RcUv"}],5:[function(_dereq_,module,exports){
  469. 'use strict';
  470. var _ = _dereq_('lodash'),
  471. Generic = _dereq_('./analyzer/GenericAnalyzer'),
  472. Angular = _dereq_('./analyzer/Angular'),
  473. Window = _dereq_('./analyzer/Window'),
  474. PObject = _dereq_('./analyzer/Object'),
  475. BuiltIn = _dereq_('./analyzer/BuiltIn');
  476. var libraries;
  477. var proto = {
  478. createNew: function (global, options) {
  479. console.log('creating a generic container for: ' + global, options);
  480. return (libraries[global] = new Generic(options));
  481. },
  482. all: function (fn) {
  483. _.forOwn(libraries, fn);
  484. },
  485. markDirty: function () {
  486. proto.all(function (v) {
  487. v.markDirty();
  488. });
  489. return proto;
  490. },
  491. setFunctionConstructors: function (newValue) {
  492. proto.all(function (v) {
  493. // this only works on the generic analyzers
  494. if (!v._hasfc) {
  495. v.analyzer.setFunctionConstructors(newValue);
  496. }
  497. });
  498. return proto;
  499. }
  500. };
  501. libraries = Object.create(proto);
  502. _.merge(libraries, {
  503. object: new PObject(),
  504. builtIn: new BuiltIn(),
  505. window: new Window(),
  506. // popular
  507. angular: new Angular(),
  508. // mine
  509. // t3: new Generic({ global: 't3' }),
  510. // huge
  511. three: new Generic({
  512. global: 'THREE',
  513. rendereachtime: true
  514. })
  515. });
  516. // console.log(libraries);
  517. // win max level initially is 0
  518. // libraries.win.preRender = function () {
  519. // libraries.win.getObjects().empty();
  520. // libraries.win.analyzeObjects([window], 0);
  521. // };
  522. // console.log(builtIn.getObjects());
  523. // console.log(win.getObjects());
  524. // console.log(user.getObjects());
  525. module.exports = libraries;
  526. },{"./analyzer/Angular":6,"./analyzer/BuiltIn":7,"./analyzer/GenericAnalyzer":8,"./analyzer/Object":9,"./analyzer/Window":10,"lodash":"K2RcUv"}],6:[function(_dereq_,module,exports){
  527. 'use strict';
  528. var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
  529. hashKey = _dereq_('../util/hashKey');
  530. function Angular() {
  531. GenericAnalyzer.call(this, {
  532. global: 'angular',
  533. displayname: 'AngularJS',
  534. rendereachtime: true
  535. });
  536. this.services = [
  537. '$animate',
  538. '$cacheFactory',
  539. '$compile',
  540. '$controller',
  541. // '$document',
  542. '$exceptionHandler',
  543. '$filter',
  544. '$http',
  545. '$httpBackend',
  546. '$interpolate',
  547. '$interval',
  548. '$locale',
  549. '$log',
  550. '$parse',
  551. '$q',
  552. '$rootScope',
  553. '$sce',
  554. '$sceDelegate',
  555. '$templateCache',
  556. '$timeout',
  557. // '$window'
  558. ].map(function (v) {
  559. return { checked: true, name: v };
  560. });
  561. }
  562. Angular.prototype = Object.create(GenericAnalyzer.prototype);
  563. Angular.prototype.getSelectedServices = function () {
  564. var me = this,
  565. toAnalyze = [];
  566. window.angular.module('app', ['ng']);
  567. this.injector = window.angular.injector(['app']);
  568. me.services.forEach(function (s) {
  569. if (s.checked) {
  570. var obj = me.injector.get(s.name);
  571. hashKey.createHashKeysFor(obj, s.name);
  572. toAnalyze.push(obj);
  573. }
  574. });
  575. return toAnalyze;
  576. };
  577. Angular.prototype.inspectSelf = function () {
  578. console.log('inspecting angular');
  579. hashKey.createHashKeysFor(window.angular, 'angular');
  580. this.analyzer.getObjects().empty();
  581. this.analyzer.add(
  582. [window.angular].concat(this.getSelectedServices())
  583. );
  584. };
  585. module.exports = Angular;
  586. },{"../util/hashKey":13,"./GenericAnalyzer":8}],7:[function(_dereq_,module,exports){
  587. 'use strict';
  588. var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
  589. utils = _dereq_('../util');
  590. var toInspect = [
  591. Object, Function,
  592. Array, Date, Boolean, Number, Math, String, RegExp, JSON,
  593. Error
  594. ];
  595. function BuiltIn() {
  596. GenericAnalyzer.call(this);
  597. }
  598. BuiltIn.prototype = Object.create(GenericAnalyzer.prototype);
  599. BuiltIn.prototype.inspectSelf = function () {
  600. console.log('inspecting builtIn objects');
  601. this.analyzer.add(this.getObjects());
  602. };
  603. BuiltIn.prototype.getObjects = function () {
  604. return toInspect;
  605. };
  606. BuiltIn.prototype.showSearch = function (nodeName, nodeProperty) {
  607. var url = 'https://developer.mozilla.org/en-US/search?' +
  608. utils.toQueryString({
  609. q: encodeURIComponent(nodeName + ' ' + nodeProperty),
  610. });
  611. window.open(url);
  612. };
  613. module.exports = BuiltIn;
  614. },{"../util":14,"./GenericAnalyzer":8}],8:[function(_dereq_,module,exports){
  615. 'use strict';
  616. var Q = _dereq_('q'),
  617. _ = _dereq_('lodash'),
  618. utils = _dereq_('../util/'),
  619. hashKey = _dereq_('../util/hashKey'),
  620. analyzer = _dereq_('../ObjectAnalyzer');
  621. var searchEngine = 'https://duckduckgo.com/?q=';
  622. function GenericAnalyzer(options) {
  623. options = options || {};
  624. // if (!name) {
  625. // throw 'name needs to be defined';
  626. // }
  627. this.global = options.global;
  628. this.displayname = options.displayname;
  629. this.levels = options.hasOwnProperty('levels') ? options.levels : 10;
  630. this.forbidden = options.forbidden || [];
  631. this.src = options.src;
  632. this._hasfc = options.hasOwnProperty('functionconstructors');
  633. this.functionconstructors = this._hasfc ?
  634. options.functionconstructors : GenericAnalyzer.SHOW_FUNCTION_CONSTRUCTORS;
  635. this.rendereachtime = options.hasOwnProperty('rendereachtime') ?
  636. options.rendereachtime : false;
  637. this.allfunctions = options.hasOwnProperty('allfunctions') ?
  638. options.allfunctions : false;
  639. this.inspected = false;
  640. // parse forbid string to array
  641. this.parse();
  642. this.analyzer = analyzer({
  643. functionConstructors: this.functionconstructors,
  644. allFunctions: this.allfunctions
  645. });
  646. }
  647. GenericAnalyzer.SHOW_BUILTIN = false;
  648. GenericAnalyzer.SHOW_FUNCTION_CONSTRUCTORS = true;
  649. GenericAnalyzer.FORBIDDEN = 'pojoviz:window,pojoviz:builtIn,document';
  650. GenericAnalyzer.prototype.init = function () {
  651. var me = this;
  652. console.log('%cPojoViz', 'font-size: 15px; color: ');
  653. return me.fetch()
  654. .then(function () {
  655. if (me.rendereachtime || !me.inspected) {
  656. me.inspect();
  657. }
  658. return me;
  659. });
  660. };
  661. GenericAnalyzer.prototype.parse = function () {
  662. if (typeof this.forbidden === 'string') {
  663. this.forbidden = this.forbidden.split(',');
  664. }
  665. if (typeof this.functionconstructors === 'string') {
  666. this.functionconstructors = this.functionconstructors === 'true';
  667. }
  668. if (typeof this.rendereachtime === 'string') {
  669. this.rendereachtime = this.rendereachtime === 'true';
  670. }
  671. if (typeof this.allfunctions === 'string') {
  672. this.allfunctions = this.allfunctions === 'true';
  673. }
  674. };
  675. GenericAnalyzer.prototype.markDirty = function () {
  676. this.inspected = false;
  677. };
  678. GenericAnalyzer.prototype.inspectSelf = function () {
  679. console.log('analyzing window.' + this.global);
  680. var me = this,
  681. analyzer = this.analyzer,
  682. forbidden = [].concat(this.forbidden);
  683. // set a predefied global
  684. hashKey.createHashKeysFor(window[this.global], this.global);
  685. // clean
  686. analyzer.getObjects().empty();
  687. analyzer.forbidden.empty();
  688. analyzer.setLevels(this.levels);
  689. // settings > show links to built in objects
  690. if (!GenericAnalyzer.SHOW_BUILTIN) {
  691. forbidden = forbidden.concat(
  692. GenericAnalyzer.FORBIDDEN.split(',')
  693. );
  694. }
  695. forbidden.forEach(function(f) {
  696. var arr,
  697. tokens;
  698. if (!f.indexOf('pojoviz:')) {
  699. tokens = f.split(':');
  700. arr = _dereq_('../ObjectHashes')[tokens[1]].getObjects();
  701. } else {
  702. arr = [window[f]];
  703. }
  704. console.log('forbidding: ', arr);
  705. analyzer.forbid(arr, true);
  706. });
  707. analyzer.add([window[this.global]]);
  708. };
  709. GenericAnalyzer.prototype.markInspected = function () {
  710. // mark this container as inspected
  711. this.inspected = true;
  712. return this;
  713. };
  714. GenericAnalyzer.prototype.inspect = function () {
  715. this
  716. .markInspected()
  717. .inspectSelf();
  718. };
  719. GenericAnalyzer.prototype.preRender = function () {
  720. };
  721. GenericAnalyzer.prototype.fetch = function () {
  722. var me = this,
  723. script;
  724. function getValue() {
  725. return window[me.global];
  726. }
  727. function promisify(v) {
  728. return function () {
  729. utils.notification('fetching script ' + v, true);
  730. var deferred = Q.defer();
  731. script = document.createElement('script');
  732. script.src = v;
  733. script.onload = function () {
  734. utils.notification('completed script ' + v, true);
  735. deferred.resolve(getValue());
  736. };
  737. document.head.appendChild(script);
  738. return deferred.promise;
  739. };
  740. }
  741. if (this.src) {
  742. if (getValue()) {
  743. console.log('resource already fetched ' + this.src);
  744. } else {
  745. var srcs = this.src.split('|');
  746. return srcs.reduce(function (prev, current) {
  747. return prev.then(promisify(current));
  748. }, Q('reduce'));
  749. }
  750. }
  751. return Q(true);
  752. };
  753. GenericAnalyzer.prototype.showSearch = function (nodeName, nodeProperty) {
  754. var me = this;
  755. window.open(
  756. _.template('${searchEngine}${lucky}${libraryName} ${nodeName} ${nodeProperty}', {
  757. searchEngine: searchEngine,
  758. lucky: GenericAnalyzer.lucky ? '!ducky' : '',
  759. libraryName: me.displayname || me.global,
  760. nodeName: nodeName,
  761. nodeProperty: nodeProperty
  762. })
  763. );
  764. };
  765. module.exports = GenericAnalyzer;
  766. },{"../ObjectAnalyzer":4,"../ObjectHashes":5,"../util/":14,"../util/hashKey":13,"lodash":"K2RcUv","q":"qLuPo1"}],9:[function(_dereq_,module,exports){
  767. 'use strict';
  768. var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
  769. utils = _dereq_('../util');
  770. function PObject() {
  771. GenericAnalyzer.call(this);
  772. }
  773. PObject.prototype = Object.create(GenericAnalyzer.prototype);
  774. PObject.prototype.inspectSelf = function () {
  775. console.log('inspecting Object objects');
  776. this.analyzer.add(this.getObjects());
  777. };
  778. PObject.prototype.getObjects = function () {
  779. return [Object];
  780. };
  781. module.exports = PObject;
  782. },{"../util":14,"./GenericAnalyzer":8}],10:[function(_dereq_,module,exports){
  783. 'use strict';
  784. var _ = _dereq_('lodash'),
  785. hashKey = _dereq_('../util/hashKey'),
  786. GenericAnalyzer = _dereq_('./GenericAnalyzer');
  787. var toInspect = [window];
  788. function Window() {
  789. GenericAnalyzer.call(this, {
  790. levels: 1,
  791. rendereachtime: true,
  792. functionconstructors: false
  793. });
  794. }
  795. Window.prototype = Object.create(GenericAnalyzer.prototype);
  796. Window.prototype.getObjects = function () {
  797. return toInspect;
  798. };
  799. Window.prototype.inspectSelf = function () {
  800. console.log('inspecting window');
  801. var me = this,
  802. hashes = _dereq_('../ObjectHashes');
  803. _.forOwn(hashes, function (v, k) {
  804. if (v.global && window[v.global]) {
  805. me.analyzer.forbid([window[v.global]], true);
  806. }
  807. });
  808. this.analyzer.getObjects().empty();
  809. this.analyzer.setLevels(this.levels);
  810. this.analyzer.add(me.getObjects());
  811. };
  812. module.exports = Window;
  813. },{"../ObjectHashes":5,"../util/hashKey":13,"./GenericAnalyzer":8,"lodash":"K2RcUv"}],11:[function(_dereq_,module,exports){
  814. var _ = _dereq_('lodash'),
  815. Q = _dereq_('q'),
  816. dagre = _dereq_('dagre'),
  817. utils = _dereq_('./util/'),
  818. ObjectHashes = _dereq_('./ObjectHashes');
  819. // enable long stacks
  820. Q.longStackSupport = true;
  821. var container,
  822. oldContainer,
  823. oldRenderer,
  824. renderer,
  825. pojoviz; // namespace
  826. function process() {
  827. var g = new dagre.Digraph(),
  828. properties,
  829. node,
  830. library = container.analyzer,
  831. str = library.stringify(),
  832. libraryNodes = str.nodes,
  833. libraryEdges = str.edges;
  834. // create the graph
  835. // each element of the graph has
  836. // - label
  837. // - width
  838. // - height
  839. // - properties
  840. _.forOwn(libraryNodes, function (properties, k) {
  841. var label = k.match(/\S*?-(.*)/)[1];
  842. // console.log(k, label.length);
  843. node = {
  844. label: k,
  845. width: label.length * 10
  846. };
  847. // lines + header + padding bottom
  848. node.height = properties.length * 15 + 50;
  849. node.properties = properties;
  850. properties.forEach(function (v) {
  851. node.width = Math.max(node.width, v.name.length * 10);
  852. });
  853. g.addNode(k, node);
  854. });
  855. // build the edges from node to node
  856. _.forOwn(libraryEdges, function (links) {
  857. links.forEach(function (link) {
  858. if (g.hasNode(link.from) && g.hasNode(link.to)) {
  859. g.addEdge(null, link.from, link.to);
  860. }
  861. });
  862. });
  863. // layout of the graph
  864. var layout = dagre.layout()
  865. .nodeSep(30)
  866. // .rankSep(70)
  867. // .rankDir('TB')
  868. .run(g);
  869. var nodes = [],
  870. edges = [],
  871. center = {x: 0, y: 0},
  872. mn = {x: Infinity, y: Infinity},
  873. mx = {x: -Infinity, y: -Infinity},
  874. total = g.nodes().length;
  875. // update the node info of the node adding:
  876. // - x
  877. // - y
  878. // - predecessors
  879. // - successors
  880. layout.eachNode(function (k, layoutInfo) {
  881. var x = layoutInfo.x;
  882. var y = layoutInfo.y;
  883. node = g.node(k);
  884. node.x = x;
  885. node.y = y;
  886. node.predecessors = g.predecessors(k);
  887. node.successors = g.successors(k);
  888. nodes.push(node);
  889. // calculate the bbox of the graph to center the graph
  890. var mnx = x - node.width / 2;
  891. var mny = y - node.height / 2;
  892. var mxx = x + node.width / 2;
  893. var mxy = y + node.height / 2;
  894. center.x += x;
  895. center.y += y;
  896. mn.x = Math.min(mn.x, mnx);
  897. mn.y = Math.min(mn.y, mny);
  898. // console.log(x, y, ' dim ', node.width, node.height);
  899. mx.x = Math.max(mx.x, mxx);
  900. mx.y = Math.max(mx.y, mxy);
  901. });
  902. center.x /= (total || 1);
  903. center.y /= (total || 1);
  904. // create the edges from property to node
  905. _(libraryEdges).forOwn(function (links) {
  906. links.forEach(function (link) {
  907. if (g.hasNode(link.from) && g.hasNode(link.to)) {
  908. edges.push(link);
  909. }
  910. });
  911. });
  912. return {
  913. edges: edges,
  914. nodes: nodes,
  915. center: center,
  916. mn: mn,
  917. mx: mx
  918. };
  919. }
  920. // render
  921. function render() {
  922. var data;
  923. if (container === oldContainer) {
  924. return;
  925. }
  926. utils.notification('processing ' + container.global);
  927. // pre render
  928. oldRenderer && oldRenderer.clean();
  929. renderer.clean();
  930. setTimeout(function () {
  931. container.preRender();
  932. console.log('process & render start: ', new Date());
  933. // data has
  934. // - edges (property -> node)
  935. // - nodes
  936. // - center
  937. //
  938. console.time('process');
  939. data = process();
  940. console.timeEnd('process');
  941. utils.notification('rendering ' + container.global);
  942. console.time('render');
  943. renderer.render(data);
  944. console.timeEnd('render');
  945. utils.notification('complete!');
  946. }, 0);
  947. }
  948. // public api
  949. pojoviz = {
  950. renderers: {},
  951. addRenderers: function (newRenderers) {
  952. _.merge(pojoviz.renderers, newRenderers);
  953. },
  954. nullifyContainer: function () {
  955. oldContainer = container;
  956. container = null;
  957. },
  958. getContainer: function () {
  959. return container;
  960. },
  961. setContainer: function (containerName, options) {
  962. oldContainer = container;
  963. container = ObjectHashes[containerName];
  964. if (!container) {
  965. container = ObjectHashes.createNew(containerName, options);
  966. } else {
  967. // required to fetch external resources
  968. container.src = options.src;
  969. }
  970. return container.init();
  971. },
  972. setRenderer: function (r) {
  973. oldRenderer = renderer;
  974. renderer = pojoviz.renderers[r];
  975. },
  976. getRenderer: function () {
  977. return renderer;
  978. },
  979. render: render,
  980. // expose inner modules
  981. ObjectHashes: _dereq_('./ObjectHashes'),
  982. ObjectAnalyzer: _dereq_('./ObjectAnalyzer'),
  983. analyzer: {
  984. GenericAnalyzer: _dereq_('./analyzer/GenericAnalyzer')
  985. },
  986. utils: _dereq_('./util'),
  987. // user vars
  988. userVariables: []
  989. };
  990. // custom events
  991. document.addEventListener('property-click', function (e) {
  992. var detail = e.detail;
  993. pojoviz
  994. .getContainer()
  995. .showSearch(detail.name, detail.property);
  996. });
  997. module.exports = pojoviz;
  998. },{"./ObjectAnalyzer":4,"./ObjectHashes":5,"./analyzer/GenericAnalyzer":8,"./util":14,"./util/":14,"dagre":"JWa/F1","lodash":"K2RcUv","q":"qLuPo1"}],12:[function(_dereq_,module,exports){
  999. 'use strict';
  1000. var hashKey = _dereq_('./hashKey');
  1001. function HashMap() {
  1002. }
  1003. HashMap.prototype = {
  1004. put: function (key, value) {
  1005. this[hashKey(key)] = (value || key);
  1006. },
  1007. get: function (key) {
  1008. return this[hashKey(key)];
  1009. },
  1010. remove: function (key) {
  1011. var v = this[hashKey(key)];
  1012. delete this[hashKey(key)];
  1013. return v;
  1014. },
  1015. empty: function () {
  1016. var p,
  1017. me = this;
  1018. for (p in me) {
  1019. if (me.hasOwnProperty(p)) {
  1020. delete this[p];
  1021. }
  1022. }
  1023. }
  1024. };
  1025. module.exports = HashMap;
  1026. },{"./hashKey":13}],13:[function(_dereq_,module,exports){
  1027. 'use strict';
  1028. var _ = _dereq_('lodash'),
  1029. assert = _dereq_('./').assert,
  1030. me, hashKey;
  1031. function isObjectOrFunction(v) {
  1032. return v && (typeof v === 'object' || typeof v === 'function');
  1033. }
  1034. /**
  1035. * Gets a store hashkey only if it's an object
  1036. * @param {[type]} obj
  1037. * @return {[type]}
  1038. */
  1039. function get(obj) {
  1040. assert(isObjectOrFunction(obj), 'obj must be an object|function');
  1041. return obj.hasOwnProperty &&
  1042. obj.hasOwnProperty(me.hiddenKey) &&
  1043. obj[me.hiddenKey];
  1044. }
  1045. /**
  1046. * Sets a key on an object
  1047. * @param {[type]} obj [description]
  1048. * @param {[type]} key [description]
  1049. */
  1050. function set(obj, key) {
  1051. assert(isObjectOrFunction(obj), 'obj must be an object|function');
  1052. assert(
  1053. key && typeof key === 'string',
  1054. 'The key needs to be a valid string'
  1055. );
  1056. if (!get(obj)) {
  1057. Object.defineProperty(obj, me.hiddenKey, {
  1058. value: typeof obj + '-' + key
  1059. });
  1060. }
  1061. return me;
  1062. }
  1063. me = hashKey = function (v) {
  1064. var value = v,
  1065. uid = v;
  1066. if (isObjectOrFunction(v)) {
  1067. if (!get(v)) {
  1068. me.createHashKeysFor(v);
  1069. }
  1070. uid = get(v);
  1071. if (!uid) {
  1072. console.err('no hashkey :(', v);
  1073. }
  1074. assert(uid, 'error getting the key');
  1075. return uid;
  1076. }
  1077. // v is a primitive
  1078. return typeof v + '-' + uid;
  1079. };
  1080. me.hiddenKey = '__pojoVizKey__';
  1081. me.createHashKeysFor = function (obj, name) {
  1082. function localToString(obj) {
  1083. var match;
  1084. try {
  1085. match = {}.toString.call(obj).match(/^\[object (\S*?)\]/);
  1086. } catch (e) {
  1087. match = false;
  1088. }
  1089. return match && match[1];
  1090. }
  1091. /**
  1092. * Analyze the internal property [[Class]] to guess the name
  1093. * of this object, e.g. [object Date], [object Math]
  1094. * Many object will give false positives (they will match [object Object])
  1095. * so let's consider Object as the name only if it's equal to
  1096. * Object.prototype
  1097. * @param {Object} obj
  1098. * @return {Boolean}
  1099. */
  1100. function hasAClassName(obj) {
  1101. var match = localToString(obj);
  1102. if (match === 'Object') {
  1103. return obj === Object.prototype && 'Object';
  1104. }
  1105. return match;
  1106. }
  1107. function getName(obj) {
  1108. var name, className;
  1109. // return the already generated hashKey
  1110. if (get(obj)) {
  1111. return get(obj);
  1112. }
  1113. // generate a new key based on
  1114. // - the name if it's a function
  1115. // - a unique id
  1116. name = typeof obj === 'function' &&
  1117. typeof obj.name === 'string' &&
  1118. obj.name;
  1119. className = hasAClassName(obj);
  1120. if (!name && className) {
  1121. name = className;
  1122. }
  1123. name = name || _.uniqueId();
  1124. return name;
  1125. }
  1126. // the name is equal to the passed name or the
  1127. // generated name
  1128. name = name || getName(obj);
  1129. name = name.replace(/[\. ]/img, '-');
  1130. // if the obj is a prototype then try to analyze
  1131. // the constructor first so that the prototype becomes
  1132. // [name].prototype
  1133. // special case: object.constructor = object
  1134. if (obj.hasOwnProperty &&
  1135. obj.hasOwnProperty('constructor') &&
  1136. typeof obj.constructor === 'function' &&
  1137. obj.constructor !== obj) {
  1138. me.createHashKeysFor(obj.constructor);
  1139. }
  1140. // set name on self
  1141. set(obj, name);
  1142. // set name on the prototype
  1143. if (typeof obj === 'function' &&
  1144. obj.hasOwnProperty('prototype')) {
  1145. set(obj.prototype, name + '-prototype');
  1146. }
  1147. };
  1148. me.has = function (v) {
  1149. return v.hasOwnProperty &&
  1150. v.hasOwnProperty(me.hiddenKey);
  1151. };
  1152. module.exports = me;
  1153. },{"./":14,"lodash":"K2RcUv"}],14:[function(_dereq_,module,exports){
  1154. 'use strict';
  1155. var _ = _dereq_('lodash');
  1156. var propertiesTransformation = {
  1157. '[[Prototype]]': '__proto__'
  1158. };
  1159. var utils = {
  1160. assert: function (v, message) {
  1161. if (!v) {
  1162. throw message || 'error';
  1163. }
  1164. },
  1165. translate: function (x, y) {
  1166. return 'translate(' + (x || 0) + ', ' + (y || 0) + ')';
  1167. },
  1168. scale: function (s) {
  1169. return 'scale(' + (s || 1) + ')';
  1170. },
  1171. transform: function (obj) {
  1172. var t = [];
  1173. _.forOwn(obj, function (v, k) {
  1174. t.push(utils[k].apply(utils, v));
  1175. });
  1176. return t.join(' ');
  1177. },
  1178. prefixer: function () {
  1179. var args = [].slice.call(arguments);
  1180. args.unshift('pv');
  1181. return args.join('-');
  1182. },
  1183. transformProperty: function (v) {
  1184. if (propertiesTransformation.hasOwnProperty(v)) {
  1185. return propertiesTransformation[v];
  1186. }
  1187. return v;
  1188. },
  1189. escapeCls: function(v) {
  1190. return v.replace(/\$/g, '_');
  1191. },
  1192. toQueryString: function (obj) {
  1193. var s = '',
  1194. i = 0;
  1195. _.forOwn(obj, function (v, k) {
  1196. if (i) {
  1197. s += '&';
  1198. }
  1199. s += k + '=' + v;
  1200. i += 1;
  1201. });
  1202. return s;
  1203. },
  1204. createEvent: function (eventName, details) {
  1205. return new CustomEvent(eventName, {
  1206. detail: details
  1207. });
  1208. },
  1209. notification: function (message, consoleToo) {
  1210. var ev = utils.createEvent('pojoviz-notification', message);
  1211. consoleToo && console.log(message);
  1212. document.dispatchEvent(ev);
  1213. },
  1214. createJsonpCallback: function (url) {
  1215. var script = document.createElement('script');
  1216. script.src = url;
  1217. document.head.appendChild(script);
  1218. }
  1219. };
  1220. module.exports = utils;
  1221. },{"lodash":"K2RcUv"}]},{},[11])
  1222. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9PYmplY3RBbmFseXplci5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvT2JqZWN0SGFzaGVzLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9Bbmd1bGFyLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9CdWlsdEluLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9HZW5lcmljQW5hbHl6ZXIuanMiLCIvVXNlcnMvbWF1cmljaW8vRG9jdW1lbnRzL3dlYi9tYXVyaXp6emlvLm1lL3Bvam92aXovc3JjL2FuYWx5emVyL09iamVjdC5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvYW5hbHl6ZXIvV2luZG93LmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9pbmRleC5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvdXRpbC9IYXNoTWFwLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy91dGlsL2hhc2hLZXkuanMiLCIvVXNlcnMvbWF1cmljaW8vRG9jdW1lbnRzL3dlYi9tYXVyaXp6emlvLm1lL3Bvam92aXovc3JjL3V0aWwvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgSGFzaE1hcCA9IHJlcXVpcmUoJy4vdXRpbC9IYXNoTWFwJyksXG4gIGhhc2hLZXkgPSByZXF1aXJlKCcuL3V0aWwvaGFzaEtleScpLFxuICBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG5cbi8vIHV0aWxzXG5mdW5jdGlvbiBlYWNoT2JqZWN0QW5kUHJvdG90eXBlKG9iaiwgZm4pIHtcbiAgZm4ob2JqKTtcbiAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eSgncHJvdG90eXBlJykpIHtcbiAgICBmbihvYmoucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyYXBzIGEgZnVuY3Rpb24gd2l0aCBhbm90aGVyXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gZm5cbiAqIEBwYXJhbSAge0Z1bmN0aW9ufSAgIHdyYXBwZXJcbiAqIEByZXR1cm4geyp9XG4gKi9cbmZ1bmN0aW9uIHdyYXBGbihmbiwgd3JhcHBlcikge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIC8vIE5PVEU6IGB0aGlzYCB3aWxsIGJlIHRoZSBpbnN0YW5jZVxuICAgIHdyYXBwZXIuY2FsbCh0aGlzKTtcbiAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0T3JGdW5jdGlvbih2KSB7XG4gIHJldHVybiAhISh2ICYmICh0eXBlb2YgdiA9PT0gJ29iamVjdCcgfHxcbiAgICB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJykpO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yYmlkZGVuIGluIHN0cmljdCBtb2RlXG4gKiBAdHlwZSB7QXJyYXl9XG4gKi9cbnZhciBmb3JiaWRkZW5JblN0cmljdE1vZGUgPSBbXG4gICdjYWxsZWUnLCAnY2FsbGVyJywgJ2FyZ3VtZW50cydcbl07XG5cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKiBPYmplY3QgYW5hbHl6XG4gKiBAcGFyYW0ge1t0eXBlXX0gY29uZmlnIFtkZXNjcmlwdGlvbl1cbiAqL1xuZnVuY3Rpb24gQW5hbHl6ZXIoY29uZmlnKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBBbmFseXplcikpIHtcbiAgICByZXR1cm4gbmV3IEFuYWx5emVyKGNvbmZpZyk7XG4gIH1cbiAgY29uZmlnID0gY29uZmlnIHx8IHt9O1xuXG4gIC8qKlxuICAgKiBPYmplY3RzIHJlZ2lzdGVyZWQgaW4gdGhpcyBpbnN0YW5jZVxuICAgKiBAdHlwZSB7SGFzaE1hcH1cbiAgICovXG4gIHRoaXMub2JqZWN0cyA9IGNvbmZpZy5vYmplY3RzIHx8IG5ldyBIYXNoTWFwKCk7XG4gIC8qKlxuICAgKiBGb3JiaWRkZW4gb2JqZWN0c1xuICAgKiBAdHlwZSB7SGFzaE1hcH1cbiAgICovXG4gIHRoaXMuZm9yYmlkZGVuID0gY29uZmlnLmZvcmJpZGRlbiB8fCBuZXcgSGFzaE1hcCgpO1xuXG4gIC8qKlxuICAgKiBDYWNoZSBvZiBwcm9wZXJ0aWVzXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLl9fY2FjaGVPYmplY3RzID0ge307XG5cbiAgLyoqXG4gICAqIENhY2hlIG9mIGxpbmtzXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLl9fY2FjaGVMaW5rcyA9IHt9O1xuXG4gIC8qKlxuICAgKiBEZnMgbGV2ZWxzXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICB0aGlzLmxldmVscyA9IEluZmluaXR5O1xuICAvKipcbiAgICogSWYgdGhlIGFuYWx5emVyIGlzIGRpcnR5IHRoZW4gaXQgaGFzIHNvbWUgcGVuZGluZyB3b3JrXG4gICAqIHRvIGRvXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgdGhpcy5kaXJ0eSA9IHRydWU7XG5cbiAgLyoqXG4gICAqIFRydWUgdG8gc2F2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgb2JqZWN0cyBhbmFseXplZCBpbiBhblxuICAgKiBpbnRlcm5hbCBjYWNoZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuY2FjaGUgPVxuICAgIGNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnY2FjaGUnKSA/XG4gICAgY29uZmlnLmNhY2hlIDogdHJ1ZTtcbiAgLyoqXG4gICAqIFRydWUgdG8gaW5jbHVkZSBmdW5jdGlvbiBjb25zdHJ1Y3RvcnMgaW4gdGhlIGFuYWx5c2lzIGdyYXBoXG4gICAqIGkuZS4gdGhlIGZ1bmN0aW9ucyB0aGF0IGhhdmUgYSBwcm90b3R5cGVcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqL1xuICB0aGlzLmZ1bmN0aW9uQ29uc3RydWN0b3JzID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2Z1bmN0aW9uQ29uc3RydWN0b3JzJykgP1xuICAgIGNvbmZpZy5mdW5jdGlvbkNvbnN0cnVjdG9ycyA6IGZhbHNlO1xuICAvKipcbiAgICogVHJ1ZSB0byBpbmNsdWRlIGFsbCB0aGUgZnVuY3Rpb25zIGluIHRoZSBhbmFseXNpcyBncmFwaFxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIHRoaXMuYWxsRnVuY3Rpb25zID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2FsbEZ1bmN0aW9ucycpID9cbiAgICBjb25maWcuYWxsRnVuY3Rpb25zIDogZmFsc2U7XG4gIC8qKlxuICAgKiBUcnVlIHRvIGFsbG93IEhUTUwgbm9kZXNcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqL1xuICB0aGlzLmh0bWxOb2RlID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2h0bWxOb2RlJykgP1xuICAgIGNvbmZpZy5odG1sTm9kZSA6IGZhbHNlO1xufVxuXG5BbmFseXplci5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBBbmFseXplcixcblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGFuIG9iamVjdCBpcyBpbiB0aGUgZm9yYmlkZGVuIGhhc2hcbiAgICogQHBhcmFtICB7T2JqZWN0fSAgb2JqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBpc0ZvcmJpZGRlbjogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiB0aGlzLmZvcmJpZGRlbi5nZXQob2JqKTtcbiAgfSxcblxuICBpc0xpbmthYmxlOiBmdW5jdGlvbiAoa2V5LCBvYmopIHtcbiAgICBpZiAoIW9iaikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciB2ID0gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCc7XG5cbiAgICAvLyBpZiAodikge1xuICAgIC8vICAgaWYgKCF0aGlzLmh0bWxOb2RlICYmIHYgaW5zdGFuY2VvZiBOb2RlKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIC8vICAgcmV0dXJuIHRydWU7XG4gICAgLy8gfVxuXG4gICAgLy8gaWYgKCF0aGlzLmh0bWxOb2RlKSB7XG4gICAgLy8gICB2ID0gdiAmJiAhKHYgaW5zdGFuY2VvZiBOb2RlKTtcbiAgICAvLyB9ZmRlcTFgXG5cbiAgICAvLyB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nICYmXG4gICAgLy8gICBjb25zb2xlLmxvZyhPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopKTtcbiAgICBpZiAoIXYgJiYgdGhpcy5hbGxGdW5jdGlvbnMpIHtcbiAgICAgIC8vIG1pbmltaXplIHRoZSBub2RlcyBjcmVhdGVkIGJ5IGNvbnNpZGVyaW5nIGZ1bmN0aW9uc1xuICAgICAgLy8gd2l0aCBtb3JlIHByb3BlcnRpZXMgdGhhbiB0aGUgdXN1YWwgb25lc1xuICAgICAgdiA9IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbic7XG4gICAgICB2ID0gdiAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopLmxlbmd0aCA+IDU7XG4gICAgfVxuICAgIGlmICghdiAmJiB0aGlzLmZ1bmN0aW9uQ29uc3RydWN0b3JzKSB7XG4gICAgICB2I…

Large files files are truncated, but you can click here to view the full file