PageRenderTime 33ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/build/pojoviz.js

https://github.com/artlantis/PojoViz
JavaScript | 1402 lines | 969 code | 178 blank | 255 comment | 99 complexity | b9bb55e10e271b1fcfe24df3da907f2f MD5 | raw 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+IDU7XG4gICAgfVxuICAgIGlmICghdiAmJiB0aGlzLmZ1bmN0aW9uQ29uc3RydWN0b3JzKSB7XG4gICAgICB2ID0gdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJztcbiAgICAgIHYgPSB2ICYmIChcbiAgICAgICAgb2JqLm5hbWUgJiZcbiAgICAgICAgb2JqLm5hbWVbMF0ubWF0Y2goL15bQS1aXS8pIHx8XG4gICAgICAgIGtleVswXS5tYXRjaCgvXltBLVpdLylcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB2O1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBlbnVtZXJhYmxlIHByb3BlcnRpZXMgYW4gb2JqZWN0IGRpc2NhcmRpbmdcbiAgICogZm9yYmlkZGVuIG9uZXNcbiAgICpcbiAgICogQHBhcmFtICB7T2JqZWN0fSBvYmpcbiAgICogQHJldHVybiB7QXJyYXl9IEFycmF5IG9mIG9iamVjdHMsIGVhY2ggb2JqZWN0IGhhcyB0aGUgZm9sbG93aW5nXG4gICAqIHByb3BlcnRpZXM6XG4gICAqXG4gICAqIC0gbmFtZVxuICAgKiAtIGNsc1xuICAgKiAtIHR5cGVcbiAgICogLSBsaW5rZWFibGUgKGlmIGl0J3MgYW4gb2JqZWN0IHRoaXMgcHJvcGVydHkgaXMgc2V0IHRvIHRydWUpXG4gICAqL1xuICBnZXRQcm9wZXJ0aWVzOiBmdW5jdGlvbiAob2JqLCBsaW5rYWJsZU9ubHkpIHtcbiAgICB2YXIgbWUgPSB0aGlzLFxuICAgICAgaGsgPSBoYXNoS2V5KG9iaiksXG4gICAgICBwcm9wZXJ0aWVzO1xuXG4gICAgaWYgKCFvYmopIHtcbiAgICAgIHRocm93ICd0aGlzIG1ldGhvZCBuZWVkcyBhbiBvYmplY3QgdG8gYW5hbHl6ZSc7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY2FjaGUpIHtcbiAgICAgIGlmICghbGlua2FibGVPbmx5ICYmIHRoaXMuX19jYWNoZU9iamVjdHNbaGtdKSB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKCdvYmplY3RzIGZyb20gY2FjaGUgOiknKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX19jYWNoZU9iamVjdHNbaGtdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHByb3BlcnRpZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopO1xuXG4gICAgZnVuY3Rpb24gZm9yYmlkZGVuS2V5KHYpIHtcbiAgICAgIC8vIGZvcmJpZGRlbiBpbiBzdHJpY3QgbW9kZVxuICAgICAgcmV0dXJuIH5mb3JiaWRkZW5JblN0cmljdE1vZGUuaW5kZXhPZih2KSB8fFxuICAgICAgICB2Lm1hdGNoKC9eX18uKj9fXyQvKSB8fFxuICAgICAgICB2Lm1hdGNoKC9eXFwkXFwkLio/XFwkXFwkJC8pIHx8XG4gICAgICAgIHYubWF0Y2goL1s6K34hPjw9Ly9cXFtcXF1AXFwuIF0vKTtcbiAgICB9XG5cbiAgICBwcm9wZXJ0aWVzID0gXy5maWx0ZXIocHJvcGVydGllcywgZnVuY3Rpb24gKHYpIHtcbiAgICAgIHZhciBnb29kID0gdHlwZW9mIHYgPT09ICdzdHJpbmcnICYmICFmb3JiaWRkZW5LZXkodiksXG4gICAgICAgICAgcjtcbiAgICAgIGlmIChsaW5rYWJsZU9ubHkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByID0gZ29vZCAmJiBtZS5pc0xpbmthYmxlKHYsIG9ialt2XSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICByID0gZmFsc2U7XG4gICAgICAgICAgLy8gdW5jb21tZW50IHRvIHNlZSB3aHkgb2JqW3ZdIGlzIG5vdCBhbGxvd2VkXG4gICAgICAgICAgLy8gY29uc29sZS5sb2coZSk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBnb29kO1xuICAgIH0pLm1hcChmdW5jdGlvbiAodikge1xuICAgICAgdmFyIHR5cGUsXG4gICAgICAgIGxpbmtlYWJsZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIHR5cGUgPSBudWxsfHN0cmluZ3x1bmRlZmluZWR8bnVtYmVyfG9iamVjdFxuICAgICAgICB0eXBlID0gdHlwZW9mIG9ialt2XTtcbiAgICAgICAgbGlua2VhYmxlID0gaXNPYmplY3RPckZ1bmN0aW9uKG9ialt2XSk7XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgdHlwZSA9ICd1bmRlZmluZWQnO1xuICAgICAgICBsaW5rZWFibGUgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLy8gcGFyZW50OiBoYXNoS2V5KG9iaiksXG4gICAgICAgIG5hbWU6IHYsXG4gICAgICAgIHR5cGU6IHR5cGUsXG4gICAgICAgIGxpbmtlYWJsZTogbGlua2VhYmxlXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gc3BlY2lhbCBwcm9wZXJ0aWVzXG4gICAgdmFyIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iaik7XG4gICAgaWYgKHByb3RvKSB7XG4gICAgICBwcm9wZXJ0aWVzLnB1c2goe1xuICAgICAgICBuYW1lOiAnW1tQcm90b3R5cGVdXScsXG4gICAgICAgIC8vIGNsczogaGFzaEtleShvYmopLFxuICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgbGlua2VhYmxlOiB0cnVlLFxuICAgICAgICBoaWRkZW46IHRydWVcbiAgICAgIH0pO1xuICAgIH1cbiAgICB2YXIgY29uc3RydWN0b3IgPSBvYmouaGFzT3duUHJvcGVydHkgJiZcbiAgICAgIG9iai5oYXNPd25Qcm9wZXJ0eSgnY29uc3RydWN0b3InKSAmJlxuICAgICAgdHlwZW9mIG9iai5jb25zdHJ1Y3RvciA9PT0gJ2Z1bmN0aW9uJztcbiAgICBpZiAoY29uc3RydWN0b3IgJiZcbiAgICAgICAgXy5maW5kSW5kZXgocHJvcGVydGllcywgeyBuYW1lOiAnY29uc3RydWN0b3InIH0pID09PSAtMSkge1xuICAgICAgcHJvcGVydGllcy5wdXNoKHtcbiAgICAgICAgLy8gY2xzOiBoYXNoS2V5KG9iaiksXG4gICAgICAgIG5hbWU6ICdjb25zdHJ1Y3RvcicsXG4gICAgICAgIHR5cGU6ICdmdW5jdGlvbicsXG4gICAgICAgIGxpbmtlYWJsZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY2FjaGUgJiYgIWxpbmthYmxlT25seSkge1xuICAgICAgdGhpcy5fX2NhY2hlT2JqZWN0c1toa10gPSBwcm9wZXJ0aWVzO1xuICAgIH1cblxuICAgIC8vIGNvbnNvbGUubG9nKHByb3BlcnRpZXMpO1xuICAgIHJldHVybiBwcm9wZXJ0aWVzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBBbmFseXplcyBhIGxpc3Qgb2Ygb2JqZWN0cyByZWN1cnNpdmVseVxuICAgKiBAcGFyYW0gIHtBcnJheX0gb2JqZWN0cyAgICAgIEFycmF5IG9mIG9iamVjdHNcbiAgICogQHBhcmFtICB7bnVtYmVyfSBjdXJyZW50TGV2ZWwgQ3VycmVudCBkZnMgbGV2ZWxcbiAgICovXG4gIGFuYWx5emVPYmplY3RzOiBmdW5jdGlvbiAob2JqZWN0cywgY3VycmVudExldmVsKSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICBvYmplY3RzLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgIGlmIChjdXJyZW50TGV2ZWwgPD0gbWUubGV2ZWxzICYmICAgIC8vIGRmcyBsZXZlbFxuICAgICAgICAgICFtZS5vYmplY3RzLmdldCh2KSAmJiAgICAgICAgIC8vIGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAgICAgICFtZS5pc0ZvcmJpZGRlbih2KSAgICAgICAgICAgICAgLy8gZm9yYmlkZGVuIGNoZWNrXG4gICAgICAgICAgKSB7XG5cbiAgICAgICAgLy8gYWRkIHRvIHRoZSByZWdpc3RlcmVkIG9iamVjdCBwb29sXG4gICAgICAgIG1lLm9iamVjdHMucHV0KHYpO1xuXG4gICAgICAgIC8vIGRmcyB0byB0aGUgbmV4dCBsZXZlbFxuICAgICAgICBtZS5hbmFseXplT2JqZWN0cyhcbiAgICAgICAgICBtZS5nZXRPd25MaW5rcyh2KS5tYXAoZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgICAgICAgIHJldHVybiBsaW5rLnRvO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIGN1cnJlbnRMZXZlbCArIDFcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2YgbGlua3MsIGVhY2ggbGluayBpcyBhbiBvYmplY3Qgd2hpY2ggaGFzIHRoZVxuICAgKiBmb2xsb3dpbmcgcHJvcGVydGllczpcbiAgICpcbiAgICogLSBmcm9tXG4gICAqIC0gdG9cbiAgICogLSBwcm9wZXJ0eSAoc3RyaW5nKVxuICAgKlxuICAgKiBAcGFyYW0gIHtPYmplY3R9IG9ialxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIGdldE93bkxpbmtzOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIG1lID0gdGhpcyxcbiAgICAgICAgbGlua3MgPSBbXSxcbiAgICAgICAgcHJvcGVydGllcyxcbiAgICAgICAgbmFtZSA9IGhhc2hLZXkob2JqKTtcblxuICAgIGlmICh0aGlzLl9fY2FjaGVMaW5rc1tuYW1lXSkge1xuICAgICAgLy8gY29uc29sZS5sb2coJ2xpbmtzIGZyb20gY2FjaGUgOiknKTtcbiAgICAgIHJldHVybiB0aGlzLl9fY2FjaGVMaW5rc1tuYW1lXTtcbiAgICB9XG5cbiAgICBwcm9wZXJ0aWVzID0gbWUuZ2V0UHJvcGVydGllcyhvYmosIHRydWUpO1xuXG4gICAgZnVuY3Rpb24gZ2V0QXVnbWVudGVkSGFzaChvYmosIG5hbWUpIHtcbiAgICAgIGlmICghaGFzaEtleS5oYXMob2JqKSAmJlxuICAgICAgICAgIG5hbWUgIT09ICdwcm90b3R5cGUnICYmXG4gICAgICAgICAgbmFtZSAhPT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgICBoYXNoS2V5LmNyZWF0ZUhhc2hLZXlzRm9yKG9iaiwgbmFtZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaGFzaEtleShvYmopO1xuICAgIH1cblxuICAgIGlmICghbmFtZSkge1xuICAgICAgdGhyb3cgJ3RoZSBvYmplY3QgbmVlZHMgdG8gaGF2ZSBhIGhhc2hrZXknO1xuICAgIH1cblxuICAgIF8uZm9yRWFjaChwcm9wZXJ0aWVzLCBmdW5jdGlvbiAodikge1xuICAgICAgdmFyIHJlZiA9IG9ialt2Lm5hbWVdO1xuICAgICAgLy8gYmVjYXVzZSBvZiB0aGUgbGV2ZWxzIGEgcmVmZXJlbmNlIG1pZ2h0IG5vdCBleGlzdFxuICAgICAgaWYgKCFyZWYpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB0aGUgb2JqZWN0IGRvZXNuJ3QgaGF2ZSBhIGhhc2hrZXlcbiAgICAgIC8vIGxldCdzIGdpdmUgaXQgYSBuYW1lIGVxdWFsIHRvIHRoZSBwcm9wZXJ0eVxuICAgICAgLy8gYmVpbmcgYW5hbHl6ZWRcbiAgICAgIGdldEF1Z21lbnRlZEhhc2gocmVmLCB2Lm5hbWUpO1xuXG4gICAgICBpZiAoIW1lLmlzRm9yYmlkZGVuKHJlZikpIHtcbiAgICAgICAgbGlua3MucHVzaCh7XG4gICAgICAgICAgZnJvbTogb2JqLFxuICAgICAgICAgIGZyb21IYXNoOiBoYXNoS2V5KG9iaiksXG4gICAgICAgICAgdG86IHJlZixcbiAgICAgICAgICB0b0hhc2g6IGhhc2hLZXkocmVmKSxcbiAgICAgICAgICBwcm9wZXJ0eTogdi5uYW1lXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iaik7XG4gICAgaWYgKHByb3RvICYmICFtZS5pc0ZvcmJpZGRlbihwcm90bykpIHtcbiAgICAgIGxpbmtzLnB1c2goe1xuICAgICAgICBmcm9tOiBvYmosXG4gICAgICAgIGZyb21IYXNoOiBoYXNoS2V5KG9iaiksXG4gICAgICAgIHRvOiBwcm90byxcbiAgICAgICAgdG9IYXNoOiBoYXNoS2V5KHByb3RvKSxcbiAgICAgICAgcHJvcGVydHk6ICdbW1Byb3RvdHlwZV1dJ1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY2FjaGUpIHtcbiAgICAgIHRoaXMuX19jYWNoZUxpbmtzW25hbWVdID0gbGlua3M7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpbmtzO1xuICB9LFxuXG4gIG1ha2VEaXJ0eTogZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuICB9LFxuXG4gIHNldExldmVsczogZnVuY3Rpb24gKGwpIHtcbiAgICB0aGlzLmxldmVscyA9IGw7XG4gIH0sXG5cbiAgc2V0RGlydHk6IGZ1bmN0aW9uIChkKSB7XG4gICAgdGhpcy5kaXJ0eSA9IGQ7XG4gIH0sXG5cbiAgc2V0RnVuY3Rpb25Db25zdHJ1Y3RvcnM6IGZ1bmN0aW9uICh2KSB7XG4gICAgdGhpcy5mdW5jdGlvbkNvbnN0cnVjdG9ycyA9IHY7XG4gIH0sXG5cbiAgZ2V0T2JqZWN0czogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm9iamVjdHM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFN0cmluZ2lmaWVzIGFuIG9iamVjdCBwcm9wZXJ0aWVzXG4gICAqIEBwYXJhbSAgb2JqXG4gICAqIEBwYXJhbSAgdG9TdHJpbmdcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBzdHJpbmdpZnlPYmplY3RQcm9wZXJ0aWVzOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0UHJvcGVydGllcyhvYmopO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgcmVwcmVzZW50YXRpb24gb2YgdGhlIGxpbmtzIG9mXG4gICAqIGFuIG9iamVjdFxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIHN0cmluZ2lmeU9iamVjdExpbmtzOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICByZXR1cm4gbWUuZ2V0T3duTGlua3Mob2JqKS5tYXAoZnVuY3Rpb24gKGxpbmspIHtcbiAgICAgIC8vIGRpc2NhcmRlZDogZnJvbSwgdG9cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGxpbmsuZnJvbUhhc2gsXG4gICAgICAgIHRvOiBsaW5rLnRvSGFzaCxcbiAgICAgICAgcHJvcGVydHk6IGxpbmsucHJvcGVydHlcbiAgICAgIH07XG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFN0cmluZ2lmaWVzIHRoZSBvYmplY3RzIHNhdmVkIGluIHRoaXMgYW5hbHl6ZXJcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgc3RyaW5naWZ5OiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG1lID0gdGhpcyxcbiAgICAgIG5vZGVzID0ge30sXG4gICAgICBlZGdlcyA9IHt9O1xuICAgIGNvbnNvbGUudGltZSgnc3RyaW5naWZ5Jyk7XG4gICAgXyh0aGlzLm9iamVjdHMpLmZvck93bihmdW5jdGlvbiAodikge1xuICAgICAgbm9kZXNbaGFzaEtleSh2KV0gPSBtZS5zdHJpbmdpZnlPYmplY3RQcm9wZXJ0aWVzKHYpO1xuICAgICAgZWRnZXNbaGFzaEtleSh2KV0gPSBtZS5zdHJpbmdpZnlPYmplY3RMaW5rcyh2KTtcbiAgICB9KTtcbiAgICBjb25zb2xlLnRpbWVFbmQoJ3N0cmluZ2lmeScpO1xuICAgIHJldHVybiB7XG4gICAgICBub2Rlczogbm9kZXMsXG4gICAgICBlZGdlczogZWRnZXNcbiAgICB9O1xuICB9XG59O1xuXG4vLyBhZGl0aW9uYWwgb2JqZWN0cyB0aGF0IG5lZWQgdGhlIHByb3RvdHlwZSB0byBleGlzdFxudmFyIGFQcm90byA9IEFuYWx5emVyLnByb3RvdHlwZTtcbl8ubWVyZ2UoYVByb3RvLCB7XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBsaXN0IG9mIG9iamVjdHMgdG8gYW5hbHl6ZSBhbmQgbWFrZSB0aGUgYW5hbHl6ZXIgZGlydHlcbiAgICogQHBhcmFtICB7QXJyYXk8T2JqZWN0cz59IG9iamVjdHNcbiAgICogQHJldHVybiB7dGhpc31cbiAgICovXG4gIGFkZDogd3JhcEZuKGZ1bmN0aW9uIChvYmplY3RzKSB7XG4gICAgY29uc29sZS50aW1lKCdhbmFseXplJyk7XG4gICAgdGhpcy5hbmFseXplT2JqZWN0cyhvYmplY3RzLCAwKTtcbiAgICBjb25zb2xlLnRpbWVFbmQoJ2FuYWx5emUnKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSwgYVByb3RvLm1ha2VEaXJ0eSksXG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSBsaXN0IG9mIG9iamVjdHMsIGlmIGB3aXRoUHJvdG90eXBlYCBpcyB0cnVlIHRoZW5cbiAgICogYWxzbyB0aGUgcHJvdG90eXBlIGlzIHJlbW92ZWRcbiAgICogQHBhcmFtICB7QXJyYXk8T2JqZWN0cz59IG9iamVjdHNcbiAgICogQHBhcmFtICB7Ym9vbGVhbn0gd2l0aFByb3RvdHlwZVxuICAgKiBAcmV0dXJuIHt0aGlzfVxuICAgKi9cbiAgcmVtb3ZlOiB3cmFwRm4oZnVuY3Rpb24gKG9iamVjdHMsIHdpdGhQcm90b3R5cGUpIHtcbiAgICB2YXIgbWUgPSB0aGlzO1xuICAgIG9iamVjdHMuZm9yRWFjaChmdW5jdGlvbiAob2JqKSB7XG4gICAgICBtZS5vYmplY3RzLnJlbW92ZShvYmopO1xuICAgICAgaWYgKHdpdGhQcm90b3R5cGUgJiYgb2JqLmhhc093blByb3BlcnR5KCdwcm90b3R5cGUnKSkge1xuICAgICAgICBtZS5vYmplY3RzLnJlbW92ZShvYmoucHJvdG90eXBlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gbWU7XG4gIH0sIGFQcm90by5tYWtlRGlydHkpLFxuXG4gIC8qKlxuICAgKiBGb3JiaWRzIGEgbGlzdCBvZiBvYmplY3RzLCBpZiBgd2l0aFByb3RvdHlwZWAgaXMgdHJ1ZSB0aGVuXG4gICAqIGFsc28gdGhlIHByb3RvdHlwZSBpcyBmb3JiaWRkZW5cbiAgICogQHBhcmFtICB7QXJyYXk8T2JqZWN0cz59IG9iamVjdHNcbiAgICogQHBhcmFtICB7Ym9vbGVhbn0gd2l0aFByb3RvdHlwZVxuICAgKiBAcmV0dXJuIHt0aGlzfVxuICAgKi9cbiAgZm9yYmlkOiB3cmFwRm4oZnVuY3Rpb24gKG9iamVjdHMsIHdpdGhQcm90b3R5cGUpIHtcbiAgICB2YXIgbWUgPSB0aGlzO1xuICAgIG1lLnJlbW92ZShvYmplY3RzLCB3aXRoUHJvdG90eXBlKTtcbiAgICBvYmplY3RzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgbWUuZm9yYmlkZGVuLnB1dChvYmopO1xuICAgICAgaWYgKHdpdGhQcm90b3R5cGUgJiYgb2JqLmhhc093blByb3BlcnR5KCdwcm90b3R5cGUnKSkge1xuICAgICAgICBtZS5mb3JiaWRkZW4ucHV0KG9iai5wcm90b3R5cGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9LCBhUHJvdG8ubWFrZURpcnR5KSxcblxuICAvKipcbiAgICogVW5mb3JiaWRzIGEgbGlzdCBvZiBvYmplY3RzLCBpZiBgd2l0aFByb3RvdHlwZWAgaXMgdHJ1ZSB0aGVuXG4gICAqIGFsc28gdGhlIHByb3RvdHlwZSBpcyB1bmZvcmJpZGRlblxuICAgKiBAcGFyYW0gIHtBcnJheTxPYmplY3RzPn0gb2JqZWN0c1xuICAgKiBAcGFyYW0gIHtib29sZWFufSB3aXRoUHJvdG90eXBlXG4gICAqIEByZXR1cm4ge3RoaXN9XG4gICAqL1xuICB1bmZvcmJpZDogd3JhcEZuKGZ1bmN0aW9uIChvYmplY3RzLCB3aXRoUHJvdG90eXBlKSB7XG4gICAgdmFyIG1lID0gdGhpcztcbiAgICBvYmplY3RzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgbWUuZm9yYmlkZGVuLnJlbW92ZShvYmopO1xuICAgICAgaWYgKHdpdGhQcm90b3R5cGUgJiYgb2JqLmhhc093blByb3BlcnR5KCdwcm90b3R5cGUnKSkge1xuICAgICAgICBtZS5mb3JiaWRkZW4ucmVtb3ZlKG9iai5wcm90b3R5cGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9LCBhUHJvdG8ubWFrZURpcnR5KVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gQW5hbHl6ZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gIEdlbmVyaWMgPSByZXF1aXJlKCcuL2FuYWx5emVyL0dlbmVyaWNBbmFseXplcicpLFxuICBBbmd1bGFyID0gcmVxdWlyZSgnLi9hbmFseXplci9Bbmd1bGFyJyksXG4gIFdpbmRvdyA9IHJlcXVpcmUoJy4vYW5hbHl6ZXIvV2luZG93JyksXG4gIFBPYmplY3QgPSByZXF1aXJlKCcuL2FuYWx5emVyL09iamVjdCcpLFxuICBCdWlsdEluID0gcmVxdWlyZSgnLi9hbmFseXplci9CdWlsdEluJyk7XG5cbnZhciBsaWJyYXJpZXM7XG5cbnZhciBwcm90byA9IHtcbiAgY3JlYXRlTmV3OiBmdW5jdGlvbiAoZ2xvYmFsLCBvcHRpb25zKSB7XG4gICAgY29uc29sZS5sb2coJ2NyZWF0aW5nIGEgZ2VuZXJpYyBjb250YWluZXIgZm9yOiAnICsgZ2xvYmFsLCBvcHRpb25zKTtcbiAgICByZXR1cm4gKGxpYnJhcmllc1tnbG9iYWxdID0gbmV3IEdlbmVyaWMob3B0aW9ucykpO1xuICB9LFxuICBhbGw6IGZ1bmN0aW9uIChmbikge1xuICAgIF8uZm9yT3duKGxpYnJhcmllcywgZm4pO1xuICB9LFxuICBtYXJrRGlydHk6IGZ1bmN0aW9uICgpIHtcbiAgICBwcm90by5hbGwoZnVuY3Rpb24gKHYpIHtcbiAgICAgIHYubWFya0RpcnR5KCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHByb3RvO1xuICB9LFxuICBzZXRGdW5jdGlvbkNvbnN0cnVjdG9yczogZnVuY3Rpb24gKG5ld1ZhbHVlKSB7XG4gICAgcHJvdG8uYWxsKGZ1bmN0aW9uICh2KSB7XG4gICAgICAvLyB0aGlzIG9ubHkgd29ya3Mgb24gdGhlIGdlbmVyaWMgYW5hbHl6ZXJzXG4gICAgICBpZiAoIXYuX2hhc2ZjKSB7XG4gICAgICAgIHYuYW5hbHl6ZXIuc2V0RnVuY3Rpb25Db25zdHJ1Y3RvcnMobmV3VmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBwcm90bztcbiAgfVxufTtcblxubGlicmFyaWVzID0gT2JqZWN0LmNyZWF0ZShwcm90byk7XG5fLm1lcmdlKGxpYnJhcmllcywge1xuICBvYmplY3Q6IG5ldyBQT2JqZWN0KCksXG4gIGJ1aWx0SW46IG5ldyBCdWlsdEluKCksXG4gIHdpbmRvdzogbmV3IFdpbmRvdygpLFxuICAvLyBwb3B1bGFyXG4gIGFuZ3VsYXI6IG5ldyBBbmd1bGFyKCksXG4gIC8vIG1pbmVcbiAgLy8gdDM6IG5ldyBHZW5lcmljKHsgZ2xvYmFsOiAndDMnIH0pLFxuICAvLyBodWdlXG4gIHRocmVlOiBuZXcgR2VuZXJpYyh7XG4gICAgZ2xvYmFsOiAnVEhSRUUnLFxuICAgIHJlbmRlcmVhY2h0aW1lOiB0cnVlXG4gIH0pXG59KTtcblxuLy8gY29uc29sZS5sb2cobGlicmFyaWVzKTtcblxuLy8gd2luIG1heCBsZXZlbCBpbml0aWFsbHkgaXMgMFxuLy8gbGlicmFyaWVzLndpbi5wcmVSZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4vLyAgIGxpYnJhcmllcy53aW4uZ2V0T2JqZWN0cygpLmVtcHR5KCk7XG4vLyAgIGxpYnJhcmllcy53aW4uYW5hbHl6ZU9iamVjdHMoW3dpbmRvd10sIDApO1xuLy8gfTtcblxuLy8gY29uc29sZS5sb2coYnVpbHRJbi5nZXRPYmplY3RzKCkpO1xuLy8gY29uc29sZS5sb2cod2luLmdldE9iamVjdHMoKSk7XG4vLyBjb25zb2xlLmxvZyh1c2VyLmdldE9iamVjdHMoKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gbGlicmFyaWVzOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIEdlbmVyaWNBbmFseXplciA9IHJlcXVpcmUoJy4vR2VuZXJpY0FuYWx5emVyJyksXG4gIGhhc2hLZXkgPSByZXF1aXJlKCcuLi91dGlsL2hhc2hLZXknKTtcblxuZnVuY3Rpb24gQW5ndWxhcigpIHtcbiAgR2VuZXJpY0FuYWx5emVyLmNhbGwodGhpcywge1xuICAgIGdsb2JhbDogJ2FuZ3VsYXInLFxuICAgIGRpc3BsYXluYW1lOiAnQW5ndWxhckpTJyxcbiAgICByZW5kZXJlYWNodGltZTogdHJ1ZVxuICB9KTtcblxuICB0aGlzLnNlcnZpY2VzID0gW1xuICAgICckYW5pbWF0ZScsXG4gICAgJyRjYWNoZUZhY3RvcnknLFxuICAgICckY29tcGlsZScsXG4gICAgJyRjb250cm9sbGVyJyxcbiAgICAvLyAnJGRvY3VtZW50JyxcbiAgICAnJGV4Y2VwdGlvbkhhbmRsZXInLFxuICAgICckZmlsdGVyJyxcbiAgICAnJGh0dHAnLFxuICAgICckaHR0cEJhY2tlbmQnLFxuICAgICckaW50ZXJwb2xhdGUnLFxuICAgICckaW50ZXJ2YWwnLFxuICAgICckbG9jYWxlJyxcbiAgICAnJGxvZycsXG4gICAgJyRwYXJzZScsXG4gICAgJyRxJyxcbiAgICAnJHJvb3RTY29wZScsXG4gICAgJyRzY2UnLFxuICAgICckc2NlRGVsZWdhdGUnLFxuICAgICckdGVtcGxhdGVDYWNoZScsXG4gICAgJyR0aW1lb3V0JyxcbiAgICAvLyAnJHdpbmRvdydcbiAgXS5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICByZXR1cm4geyBjaGVja2VkOiB0cnVlLCBuYW1lOiB2IH07XG4gIH0pO1xufVxuXG5Bbmd1bGFyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoR2VuZXJpY0FuYWx5emVyLnByb3RvdHlwZSk7XG5cbkFuZ3VsYXIucHJvdG90eXBlLmdldFNlbGVjdGVkU2VydmljZXMgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBtZSA9IHRoaXMsXG4gICAgdG9BbmFseXplID0gW107XG5cbiAgd2luZG93LmFuZ3VsYXIubW9kdWxlKCdhcHAnLCBbJ25nJ10pO1xuICB0aGlzLmluamVjdG9yID0gd2luZG93LmFuZ3VsYXIuaW5qZWN0b3IoWydhcHAnXSk7XG5cbiAgbWUuc2VydmljZXMuZm9yRWFjaChmdW5jdGlvbiAocykge1xuICAgIGlmIChzLmNoZWNrZWQpIHtcbiAgICAgIHZhciBvYmogPSBtZS5pbmplY3Rvci5nZXQocy5uYW1lKTtcbiAgICAgIGhhc2hLZXkuY3JlYXRlSGFzaEtleXNGb3Iob2JqLCBzLm5hbWUpO1xuICAgICAgdG9BbmFseXplLnB1c2gob2JqKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gdG9BbmFseXplO1xufTtcblxuQW5ndWxhci5wcm90b3R5cGUuaW5zcGVjdFNlbGYgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnNvbGUubG9nKCdpbnNwZWN0aW5nIGFuZ3VsYXInKTtcbiAgaGFzaEtleS5jcmVhdGVIYXNoS2V5c0Zvcih3aW5kb3cuYW5ndWxhciwgJ2FuZ3VsYXInKTtcbiAgdGhpcy5hbmFseXplci5nZXRPYmplY3RzKCkuZW1wdHkoKTtcbiAgdGhpcy5hbmFseXplci5hZGQoXG4gICAgW3dpbmRvdy5hbmd1bGFyXS5jb25jYXQodGhpcy5nZXRTZWxlY3RlZFNlcnZpY2VzKCkpXG4gICk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFuZ3VsYXI7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgR2VuZXJpY0FuYWx5emVyID0gcmVxdWlyZSgnLi9HZW5lcmljQW5hbHl6ZXInKSxcbiAgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbnZhciB0b0luc3BlY3QgPSBbXG4gIE9iamVjdCwgRnVuY3Rpb24sXG4gIEFycmF5LCBEYXRlLCBCb29sZWFuLCBOdW1iZXIsIE1hdGgsIFN0cmluZywgUmVnRXhwLCBKU09OLFxuICBFcnJvclxuXTtcblxuZnVuY3Rpb24gQnVpbHRJbigpIHtcbiAgR2VuZXJpY0FuYWx5emVyLmNhbGwodGhpcyk7XG59XG5cbkJ1aWx0SW4ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHZW5lcmljQW5hbHl6ZXIucHJvdG90eXBlKTtcblxuQnVpbHRJbi5wcm90b3R5cGUuaW5zcGVjdFNlbGYgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnNvbGUubG9nKCdpbnNwZWN0aW5nIGJ1aWx0SW4gb2JqZWN0cycpO1xuICB0aGlzLmFuYWx5emVyLmFkZCh0aGlzLmdldE9iamVjdHMoKSk7XG59O1xuXG5CdWlsdEluLnByb3RvdHlwZS5nZXRPYmplY3RzID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdG9JbnNwZWN0O1xufTtcblxuQnVpbHRJbi5wcm90b3R5cGUuc2hvd1NlYXJjaCA9IGZ1bmN0aW9uIChub2RlTmFtZSwgbm9kZVByb3BlcnR5KSB7XG4gIHZhciB1cmwgPSAnaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvc2VhcmNoPycgK1xuICAgIHV0aWxzLnRvUXVlcnlTdHJpbmcoe1xuICAgICAgcTogZW5jb2RlVVJJQ29tcG9uZW50KG5vZGVOYW1lICsgJyAnICsgbm9kZVByb3BlcnR5KSxcbiAgICB9KTtcbiAgd2luZG93Lm9wZW4odXJsKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQnVpbHRJbjsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBRID0gcmVxdWlyZSgncScpLFxuICBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gIHV0aWxzID0gcmVxdWlyZSgnLi4vdXRpbC8nKSxcbiAgaGFzaEtleSA9IHJlcXVpcmUoJy4uL3V0aWwvaGFzaEtleScpLFxuICBhbmFseXplciA9IHJlcXVpcmUoJy4uL09iamVjdEFuYWx5emVyJyk7XG5cbnZhciBzZWFyY2hFbmdpbmUgPSAnaHR0cHM6Ly9kdWNrZHVja2dvLmNvbS8/cT0nO1xuXG5mdW5jdGlvbiBHZW5lcmljQW5hbHl6ZXIob3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgLy8gaWYgKCFuYW1lKSB7XG4gIC8vICAgdGhyb3cgJ25hbWUgbmVlZHMgdG8gYmUgZGVmaW5lZCc7XG4gIC8vIH1cbiAgdGhpcy5nbG9iYWwgPSBvcHRpb25zLmdsb2JhbDtcbiAgdGhpcy5kaXNwbGF5bmFtZSA9IG9wdGlvbnMuZGlzcGxheW5hbWU7XG4gIHRoaXMubGV2ZWxzID0gb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnbGV2ZWxzJykgPyBvcHRpb25zLmxldmVscyA6IDEwO1xuICB0aGlzLmZvcmJpZGRlbiA9IG9wdGlvbnMuZm9yYmlkZGVuIHx8IFtdO1xuICB0aGlzLnNyYyA9IG9wdGlvbnMuc3JjO1xuICB0aGlzLl9oYXNmYyA9IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2Z1bmN0aW9uY29uc3RydWN0b3JzJyk7XG4gIHRoaXMuZnVuY3Rpb25jb25zdHJ1Y3RvcnMgPSB0aGlzLl9oYXNmYyA/XG4gICAgb3B0aW9ucy5mdW5jdGlvbmNvbnN0cnVjdG9ycyA6IEdlbmVyaWNBbmFseXplci5TSE9XX0ZVTkNUSU9OX0NPTlNUUlVDVE9SUztcbiAgdGhpcy5yZW5kZXJlYWNodGltZSA9IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ3JlbmRlcmVhY2h0aW1lJykgP1xuICAgIG9wdGlvbnMucmVuZGVyZWFjaHRpbWUgOiBmYWxzZTtcbiAgdGhpcy5hbGxmdW5jdGlvbnMgPSBvcHRpb25zLmhhc093blByb3BlcnR5KCdhbGxmdW5jdGlvbnMnKSA/XG4gICAgb3B0aW9ucy5hbGxmdW5jdGlvbnMgOiBmYWxzZTtcblxuICB0aGlzLmluc3BlY3RlZCA9IGZhbHNlO1xuXG4gIC8vIHBhcnNlIGZvcmJpZCBzdHJpbmcgdG8gYXJyYXlcbiAgdGhpcy5wYXJzZSgpO1xuXG4gIHRoaXMuYW5hbHl6ZXIgPSBhbmFseXplcih7XG4gICAgZnVuY3Rpb25Db25zdHJ1Y3RvcnM6IHRoaXMuZnVuY3Rpb25jb25zdHJ1Y3RvcnMsXG4gICAgYWxsRnVuY3Rpb25zOiB0aGlzLmFsbGZ1bmN0aW9uc1xuICB9KTtcbn1cblxuR2VuZXJpY0FuYWx5emVyLlNIT1dfQlVJTFRJTiA9IGZhbHNlO1xuR2VuZXJpY0FuYWx5emVyLlNIT1dfRlVOQ1RJT05fQ09OU1RSVUNUT1JTID0gdHJ1ZTtcbkdlbmVyaWNBbmFseXplci5GT1JCSURERU4gPSAncG9qb3Zpejp3aW5kb3cscG9qb3ZpejpidWlsdEluLGRvY3VtZW50JztcblxuR2VuZXJpY0FuYWx5emVyLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgbWUgPSB0aGlzO1xuICBjb25zb2xlLmxvZygnJWNQb2pvVml6JywgJ2ZvbnQtc2l6ZTogMTVweDsgY29sb3I6ICcpO1xuICByZXR1cm4gbWUuZmV0Y2goKVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChtZS5yZW5kZXJlYWNodGltZSB8fCAhbWUuaW5zcGVjdGVkKSB7XG4gICAgICAgIG1lLmluc3BlY3QoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtZTtcbiAgICB9KTtcbn07XG5cbkdlbmVyaWNBbmFseXplci5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICh0eXBlb2YgdGhpcy5mb3JiaWRkZW4gPT09ICdzdHJpbmcnKSB7XG4gICAgdGhpcy5mb3JiaWRkZW4gPSB0aGlzLmZvcmJpZGRlbi5zcGxpdCgnLCcpO1xuICB9XG4gIGlmICh0eXBlb2YgdGhpcy5mdW5jdGlvbmNvbnN0cnVjdG9ycyA9PT0gJ3N0cmluZycpIHtcbiAgICB0aGlzLmZ1bmN0aW9uY29uc3RydWN0b3JzID0gdGhpcy5mdW5jdGlvbmNvbnN0cnVjdG9ycyA9PT0gJ3RydWUnO1xuICB9XG4gIGlmICh0eXBlb2YgdGhpcy5yZW5kZXJlYWNodGltZSA9PT0gJ3N0cmluZycpIHtcbiAgICB0aGlzLnJlbmRlcmVhY2h0aW1lID0gdGhpcy5yZW5kZXJlYWNodGltZSA9PT0gJ3RydWUnO1xuICB9XG4gIGlmICh0eXBlb2YgdGhpcy5hbGxmdW5jdGlvbnMgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhpcy5hbGxmdW5jdGlvbnMgPSB0aGlzLmFsbGZ1bmN0aW9ucyA9PT0gJ3RydWUnO1xuICB9XG59O1xuXG5HZW5lcmljQW5hbHl6ZXIucHJvdG90eXBlLm1hcmtEaXJ0eSA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5pbnNwZWN0ZWQgPSBmYWxzZTtcbn07XG5cbkdlbmVyaWNBbmFseXplci5wcm90b3R5cGUuaW5zcGVjdFNlbGYgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnNvbGUubG9nKCdhbmFseXppbmcgd2luZG93LicgKyB0aGlzLmdsb2JhbCk7XG4gIHZhciBtZSA9IHRoaXMsXG4gICAgYW5hbHl6ZXIgPSB0aGlzLmFuYWx5emVyLFxuICAgIGZvcmJpZGRlbiA9IFtdLmNvbmNhdCh0aGlzLmZvcmJpZGRlbik7XG4gIC8vIHNldCBhIHByZWRlZmllZCBnbG9iYWxcbiAgaGFzaEtleS5jcmVhdGVIYXNoS2V5c0Zvcih3aW5kb3dbdGhpcy5nbG9iYWxdLCB0aGlzLmdsb2JhbCk7XG4gIC8vIGNsZWFuXG4gIGFuYWx5emVyLmdldE9iamVjdHMoKS5lbXB0eSgpO1xuICBhbmFseXplci5mb3JiaWRkZW4uZW1wdHkoKTtcbiAgYW5hbHl6ZXIuc2V0TGV2ZWxzKHRoaXMubGV2ZWxzKTtcblxuICAvLyBzZXR0aW5ncyA+IHNob3cgbGlua3MgdG8gYnVpbHQgaW4gb2JqZWN0c1xuICBpZiAoIUdlbmVyaWNBbmFseXplci5TSE9XX0JVSUxUSU4pIHtcbiAgICBmb3JiaWRkZW4gPSBmb3JiaWRkZW4uY29uY2F0KFxuICAgICAgR2VuZXJpY0FuYWx5emVyLkZPUkJJRERFTi5zcGxpdCgnLCcpXG4gICAgKTtcbiAgfVxuXG4gIGZvcmJpZGRlbi5mb3JFYWNoKGZ1bmN0aW9uKGYpIHtcbiAgICB2YXIgYXJyLFxuICAgICAgdG9rZW5zO1xuICAgIGlmICghZi5pbmRleE9mKCdwb2pvdml6OicpKSB7XG4gICAgICB0b2tlbnMgPSBmLnNwbGl0KCc6Jyk7XG4gICAgICBhcnIgPSByZXF1aXJlKCcuLi9PYmplY3RIYXNoZXMnKVt0b2tlbnNbMV1dLmdldE9iamVjdHMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXJyID0gW3dpbmRvd1tmXV07XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKCdmb3JiaWRkaW5nOiAnLCBhcnIpO1xuICAgIGFuYWx5emVyLmZvcmJpZChhcnIsIHRydWUpO1xuICB9KTtcblxuICBhbmFseXplci5hZGQoW3dpbmRvd1t0aGlzLmdsb2JhbF1dKTtcblxufTtcblxuR2VuZXJpY0FuYWx5emVyLnByb3RvdHlwZS5tYXJrSW5zcGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAvLyBtYXJrIHRoaXMgY29udGFpbmVyIGFzIGluc3BlY3RlZFxuICB0aGlzLmluc3BlY3RlZCA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuR2VuZXJpY0FuYWx5emVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gKCkge1xuICB0aGlzXG4gICAgLm1hcmtJbnNwZWN0ZWQoKVxuICAgIC5pbnNwZWN0U2VsZigpO1xufTtcblxuR2VuZXJpY0FuYWx5emVyLnByb3RvdHlwZS5wcmVSZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG59O1xuXG5HZW5lcmljQW5hbHl6ZXIucHJvdG90eXBlLmZldGNoID0gZnVuY3Rpb24gKCkge1xuICB2YXIgbWUgPSB0aGlzLFxuICAgIHNjcmlwdDtcblxuICBmdW5jdGlvbiBnZXRWYWx1ZSgpIHtcbiAgICByZXR1cm4gd2luZG93W21lLmdsb2JhbF07XG4gIH1cblxuICBmdW5jdGlvbiBwcm9taXNpZnkodikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICB1dGlscy5ub3RpZmljYXRpb24oJ2ZldGNoaW5nIHNjcmlwdCAnICsgdiwgdHJ1ZSk7XG4gICAgICB2YXIgZGVmZXJyZWQgPSBRLmRlZmVyKCk7XG4gICAgICBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICAgIHNjcmlwdC5zcmMgPSB2O1xuICAgICAgc2NyaXB0Lm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdXRpbHMubm90aWZpY2F0aW9uKCdjb21wbGV0ZWQgc2NyaXB0ICcgKyB2LCB0cnVlKTtcbiAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShnZXRWYWx1ZSgpKTtcbiAgICAgIH07XG4gICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbiAgICB9O1xuICB9XG5cbiAgaWYgKHRoaXMuc3JjKSB7XG4gICAgaWYgKGdldFZhbHVlKCkpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdyZXNvdXJjZSBhbHJlYWR5IGZldGNoZWQgJyArIHRoaXMuc3JjKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHNyY3MgPSB0aGlzLnNyYy5zcGxpdCgnfCcpO1xuICAgICAgcmV0dXJuIHNyY3MucmVkdWNlKGZ1bmN0aW9uIChwcmV2LCBjdXJyZW50KSB7XG4gICAgICAgIHJldHVybiBwcmV2LnRoZW4ocHJvbWlzaWZ5KGN1cnJlbnQpKTtcbiAgICAgIH0sIFEoJ3JlZHVjZScpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gUSh0cnVlKTtcbn07XG5cbkdlbmVyaWNBbmFseXplci5wcm90b3R5cGUuc2hvd1NlYXJjaCA9IGZ1bmN0aW9uIChub2RlTmFtZSwgbm9kZVByb3BlcnR5KSB7XG4gIHZhciBtZSA9IHRoaXM7XG4gIHdpbmRvdy5vcGVuKFxuICAgIF8udGVtcGxhdGUoJyR7c2VhcmNoRW5naW5lfSR7bHVja3l9JHtsaWJyYXJ5TmFtZX0gJHtub2RlTmFtZX0gJHtub2RlUHJvcGVydHl9Jywge1xuICAgICAgc2VhcmNoRW5naW5lOiBzZWFyY2hFbmdpbmUsXG4gICAgICBsdWNreTogR2VuZXJpY0FuYWx5emVyLmx1Y2t5ID8gJyFkdWNreScgOiAnJyxcbiAgICAgIGxpYnJhcnlOYW1lOiBtZS5kaXNwbGF5bmFtZSB8fCBtZS5nbG9iYWwsXG4gICAgICBub2RlTmFtZTogbm9kZU5hbWUsXG4gICAgICBub2RlUHJvcGVydHk6IG5vZGVQcm9wZXJ0eVxuICAgIH0pXG4gICk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdlbmVyaWNBbmFseXplcjsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBHZW5lcmljQW5hbHl6ZXIgPSByZXF1aXJlKCcuL0dlbmVyaWNBbmFseXplcicpLFxuICB1dGlscyA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuZnVuY3Rpb24gUE9iamVjdCgpIHtcbiAgR2VuZXJpY0FuYWx5emVyLmNhbGwodGhpcyk7XG59XG5cblBPYmplY3QucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHZW5lcmljQW5hbHl6ZXIucHJvdG90eXBlKTtcblxuUE9iamVjdC5wcm90b3R5cGUuaW5zcGVjdFNlbGYgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnNvbGUubG9nKCdpbnNwZWN0aW5nIE9iamVjdCBvYmplY3RzJyk7XG4gIHRoaXMuYW5hbHl6ZXIuYWRkKHRoaXMuZ2V0T2JqZWN0cygpKTtcbn07XG5cblBPYmplY3QucHJvdG90eXBlLmdldE9iamVjdHMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBbT2JqZWN0XTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gUE9iamVjdDsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0gcmVxdWlyZSgnbG9kYXNoJyksXG4gIGhhc2hLZXkgPSByZXF1aXJlKCcuLi91dGlsL2hhc2hLZXknKSxcbiAgR2VuZXJpY0FuYWx5emVyID0gcmVxdWlyZSgnLi9HZW5lcmljQW5hbHl6ZXInKTtcblxudmFyIHRvSW5zcGVjdCA9IFt3aW5kb3ddO1xuXG5mdW5jdGlvbiBXaW5kb3coKSB7XG4gIEdlbmVyaWNBbmFseXplci5jYWxsKHRoaXMsIHtcbiAgICBsZXZlbHM6IDEsXG4gICAgcmVuZGVyZWFjaHRpbWU6IHRydWUsXG4gICAgZnVuY3Rpb25jb25zdHJ1Y3RvcnM6IGZhbHNlXG4gIH0pO1xufVxuXG5XaW5kb3cucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHZW5lcmljQW5hbHl6ZXIucHJvdG90eXBlKTtcblxuV2luZG93LnByb3RvdHlwZS5nZXRPYmplY3RzID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdG9JbnNwZWN0O1xufTtcblxuV2luZG93LnByb3RvdHlwZS5pbnNwZWN0U2VsZiA9IGZ1bmN0aW9uICgpIHtcbiAgY29uc29sZS5sb2coJ2luc3BlY3Rpbmcgd2luZG93Jyk7XG4gIHZhciBtZSA9IHRoaXMsXG4gICAgaGFzaGVzID0gcmVxdWlyZSgnLi4vT2JqZWN0SGFzaGVzJyk7XG5cbiAgXy5mb3JPd24oaGFzaGVzLCBmdW5jdGlvbiAodiwgaykge1xuICAgIGlmICh2Lmdsb2JhbCAmJiB3aW5kb3dbdi5nbG9iYWxdKSB7XG4gICAgICBtZS5hbmFseXplci5mb3JiaWQoW3dpbmRvd1t2Lmdsb2JhbF1dLCB0cnVlKTtcbiAgICB9XG4gIH0pO1xuICB0aGlzLmFuYWx5emVyLmdldE9iamVjdHMoKS5lbXB0eSgpO1xuICB0aGlzLmFuYWx5emVyLnNldExldmVscyh0aGlzLmxldmVscyk7XG4gIHRoaXMuYW5hbHl6ZXIuYWRkKG1lLmdldE9iamVjdHMoKSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFdpbmRvdzsiLCJ2YXIgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpLFxuICBRID0gcmVxdWlyZSgncScpLFxuICBkYWdyZSA9IHJlcXVpcmUoJ2RhZ3JlJyksXG4gIHV0aWxzID0gcmVxdWlyZSgnLi91dGlsLycpLFxuICBPYmplY3RIYXNoZXMgPSByZXF1aXJlKCcuL09iamVjdEhhc2hlcycpO1xuXG4vLyBlbmFibGUgbG9uZyBzdGFja3NcblEubG9uZ1N0YWNrU3VwcG9ydCA9IHRydWU7XG5cbnZhciBjb250YWluZXIsXG4gIG9sZENvbnRhaW5lcixcbiAgb2xkUmVuZGVyZXIsXG4gIHJlbmRlcmVyLFxuICBwb2pvdml6OyAgICAgIC8vIG5hbWVzcGFjZVxuXG5mdW5jdGlvbiBwcm9jZXNzKCkge1xuICB2YXIgZyA9IG5ldyBkYWdyZS5EaWdyYXBoKCksXG4gICAgICBwcm9wZXJ0aWVzLFxuICAgICAgbm9kZSxcbiAgICAgIGxpYnJhcnkgPSBjb250YWluZXIuYW5hbHl6ZXIsXG4gICAgICBzdHIgPSBsaWJyYXJ5LnN0cmluZ2lmeSgpLFxuICAgICAgbGlicmFyeU5vZGVzID0gc3RyLm5vZGVzLFxuICAgICAgbGlicmFyeUVkZ2VzID0gc3RyLmVkZ2VzO1xuXG4gIC8vIGNyZWF0ZSB0aGUgZ3JhcGhcbiAgLy8gZWFjaCBlbGVtZW50IG9mIHRoZSBncmFwaCBoYXNcbiAgLy8gLSBsYWJlbFxuICAvLyAtIHdpZHRoXG4gIC8vIC0gaGVpZ2h0XG4gIC8vIC0gcHJvcGVydGllc1xuICBfLmZvck93bihsaWJyYXJ5Tm9kZXMsIGZ1bmN0aW9uIChwcm9wZXJ0aWVzLCBrKSB7XG4gICAgdmFyIGxhYmVsID0gay5tYXRjaCgvXFxTKj8tKC4qKS8pWzFdO1xuICAgIC8vIGNvbnNvbGUubG9nKGssIGxhYmVsLmxlbmd0aCk7XG4gICAgbm9kZSA9IHtcbiAgICAgIGxhYmVsOiBrLFxuICAgICAgd2lkdGg6IGxhYmVsLmxlbmd0aCAqIDEwXG4gICAgfTtcbiAgICAvLyBsaW5lcyArIGhlYWRlciArIHBhZGRpbmcgYm90dG9tXG4gICAgbm9kZS5oZWlnaHQgPSBwcm9wZXJ0aWVzLmxlbmd0aCAqIDE1ICsgNTA7XG4gICAgbm9kZS5wcm9wZXJ0aWVzID0gcHJvcGVydGllcztcbiAgICBwcm9wZXJ0aWVzLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgIG5vZGUud2lkdGggPSBNYXRoLm1heChub2RlLndpZHRoLCB2Lm5hbWUubGVuZ3RoICogMTApO1xuICAgIH0pO1xuICAgIGcuYWRkTm9kZShrLCBub2RlKTtcbiAgfSk7XG5cbiAgLy8gYnVpbGQgdGhlIGVkZ2VzIGZyb20gbm9kZSB0byBub2RlXG4gIF8uZm9yT3duKGxpYnJhcnlFZGdlcywgZnVuY3Rpb24gKGxpbmtzKSB7XG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgaWYgKGcuaGFzTm9kZShsaW5rLmZyb20pICYmIGcuaGFzTm9kZShsaW5rLnRvKSkge1xuICAgICAgICBnLmFkZEVkZ2UobnVsbCwgbGluay5mcm9tLCBsaW5rLnRvKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gbGF5b3V0IG9mIHRoZSBncmFwaFxuICB2YXIgbGF5b3V0ID0gZGFncmUubGF5b3V0KClcbiAgICAubm9kZVNlcCgzMClcbiAgICAvLyAucmFua1NlcCg3MClcbiAgICAvLyAucmFua0RpcignVEInKVxuICAgIC5ydW4oZyk7XG5cbiAgdmFyIG5vZGVzID0gW10sXG4gICAgICBlZGdlcyA9IFtdLFxuICAgICAgY2VudGVyID0ge3g6IDAsIHk6IDB9LFxuICAgICAgbW4gPSB7eDogSW5maW5pdHksIHk6IEluZmluaXR5fSxcbiAgICAgIG14ID0ge3g6IC1JbmZpbml0eSwgeTogLUluZmluaXR5fSxcbiAgICAgIHRvdGFsID0gZy5ub2RlcygpLmxlbmd0aDtcblxuICAvLyB1cGRhdGUgdGhlIG5vZGUgaW5mbyBvZiB0aGUgbm9kZSBhZGRpbmc6XG4gIC8vIC0geFxuICAvLyAtIHlcbiAgLy8gLSBwcmVkZWNlc3NvcnNcbiAgLy8gLSBzdWNjZXNzb3JzXG4gIGxheW91dC5lYWNoTm9kZShmdW5jdGlvbiAoaywgbGF5b3V0SW5mbykge1xuICAgIHZhciB4ID0gbGF5b3V0SW5mby54O1xuICAgIHZhciB5ID0gbGF5b3V0SW5mby55O1xuXG4gICAgbm9kZSA9IGcubm9kZShrKTtcbiAgICBub2RlLnggPSB4O1xuICAgIG5vZGUueSA9IHk7XG4gICAgbm9kZS5wcmVkZWNlc3NvcnMgPSBnLnByZWRlY2Vzc29ycyhrKTtcbiAgICBub2RlLnN1Y2Nlc3NvcnMgPSBnLnN1Y2Nlc3NvcnMoayk7XG4gICAgbm9kZXMucHVzaChub2RlKTtcblxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgYmJveCBvZiB0aGUgZ3JhcGggdG8gY2VudGVyIHRoZSBncmFwaFxuICAgIHZhciBtbnggPSB4IC0gbm9kZS53aWR0aCAvIDI7XG4gICAgdmFyIG1ueSA9IHkgLSBub2RlLmhlaWdodCAvIDI7XG4gICAgdmFyIG14eCA9IHggKyBub2RlLndpZHRoIC8gMjtcbiAgICB2YXIgbXh5ID0geSArIG5vZGUuaGVpZ2h0IC8gMjtcblxuICAgIGNlbnRlci54ICs9IHg7XG4gICAgY2VudGVyLnkgKz0geTtcbiAgICBtbi54ID0gTWF0aC5taW4obW4ueCwgbW54KTtcbiAgICBtbi55ID0gTWF0aC5taW4obW4ueSwgbW55KTtcbiAgICAvLyBjb25zb2xlLmxvZyh4LCB5LCAnIGRpbSAnLCBub2RlLndpZHRoLCBub2RlLmhlaWdodCk7XG4gICAgbXgueCA9IE1hdGgubWF4KG14LngsIG14eCk7XG4gICAgbXgueSA9IE1hdGgubWF4KG14LnksIG14eSk7XG4gIH0pO1xuXG4gIGNlbnRlci54IC89ICh0b3RhbCB8fCAxKTtcbiAgY2VudGVyLnkgLz0gKHRvdGFsIHx8IDEpO1xuXG4gIC8vIGNyZWF0ZSB0aGUgZWRnZXMgZnJvbSBwcm9wZXJ0eSB0byBub2RlXG4gIF8obGlicmFyeUVkZ2VzKS5mb3JPd24oZnVuY3Rpb24gKGxpbmtzKSB7XG4gICAgbGlua3MuZm9yRWFjaChmdW5jdGlvbiAobGluaykge1xuICAgICAgaWYgKGcuaGFzTm9kZShsaW5rLmZyb20pICYmIGcuaGFzTm9kZShsaW5rLnRvKSkge1xuICAgICAgICBlZGdlcy5wdXNoKGxpbmspO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIGVkZ2VzOiBlZGdlcyxcbiAgICBub2Rlczogbm9kZXMsXG4gICAgY2VudGVyOiBjZW50ZXIsXG4gICAgbW46IG1uLFxuICAgIG14OiBteFxuICB9O1xufVxuXG4vLyByZW5kZXJcbmZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgdmFyIGRhdGE7XG5cbiAgaWYgKGNvbnRhaW5lciA9PT0gb2xkQ29udGFpbmVyKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdXRpbHMubm90aWZpY2F0aW9uKCdwcm9jZXNzaW5nICcgKyBjb250YWluZXIuZ2xvYmFsKTtcblxuICAvLyBwcmUgcmVuZGVyXG4gIG9sZFJlbmRlcmVyICYmIG9sZFJlbmRlcmVyLmNsZWFuKCk7XG4gIHJlbmRlcmVyLmNsZWFuKCk7XG5cbiAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgY29udGFpbmVyLnByZVJlbmRlcigpO1xuICAgIGNvbnNvbGUubG9nKCdwcm9jZXNzICYgcmVuZGVyIHN0YXJ0OiAnLCBuZXcgRGF0ZSgpKTtcbiAgICAvLyBkYXRhIGhhc1xuICAgIC8vIC0gZWRnZXMgKHByb3BlcnR5IC0+IG5vZGUpXG4gICAgLy8gLSBub2Rlc1xuICAgIC8vIC0gY2VudGVyXG4gICAgLy9cbiAgICBjb25zb2xlLnRpbWUoJ3Byb2Nlc3MnKTtcbiAgICBkYXRhID0gcHJvY2VzcygpO1xuICAgIGNvbnNvbGUudGltZUVuZCgncHJvY2VzcycpO1xuXG4gICAgdXRpbHMubm90aWZpY2F0aW9uKCdyZW5kZXJpbmcgJyArIGNvbnRhaW5lci5nbG9iYWwpO1xuXG4gICAgY29uc29sZS50aW1lKCdyZW5kZXInKTtcbiAgICByZW5kZXJlci5yZW5kZXIoZGF0YSk7XG4gICAgY29uc29sZS50aW1lRW5kKCdyZW5kZXInKTtcblxuICAgIHV0aWxzLm5vdGlmaWNhdGlvbignY29tcGxldGUhJyk7XG4gIH0sIDApO1xufVxuXG4vLyBwdWJsaWMgYXBpXG5wb2pvdml6ID0ge1xuICByZW5kZXJlcnM6IHt9LFxuICBhZGRSZW5kZXJlcnM6IGZ1bmN0aW9uIChuZXdSZW5kZXJlcnMpIHtcbiAgICBfLm1lcmdlKHBvam92aXoucmVuZGVyZXJzLCBuZXdSZW5kZXJlcnMpO1xuICB9LFxuICBudWxsaWZ5Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgb2xkQ29udGFpbmVyID0gY29udGFpbmVyO1xuICAgIGNvbnRhaW5lciA9IG51bGw7XG4gIH0sXG4gIGdldENvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBjb250YWluZXI7XG4gIH0sXG4gIHNldENvbnRhaW5lcjogZnVuY3Rpb24gKGNvbnRhaW5lck5hbWUsIG9wdGlvbnMpIHtcbiAgICBvbGRDb250YWluZXIgPSBjb250YWluZXI7XG4gICAgY29udGFpbmVyID0gT2JqZWN0SGFzaGVzW2NvbnRhaW5lck5hbWVdO1xuXG4gICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgIGNvbnRhaW5lciA9IE9iamVjdEhhc2hlcy5jcmVhdGVOZXcoY29udGFpbmVyTmFtZSwgb3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHJlcXVpcmVkIHRvIGZldGNoIGV4dGVybmFsIHJlc291cmNlc1xuICAgICAgY29udGFpbmVyLnNyYyA9IG9wdGlvbnMuc3JjO1xuICAgIH1cblxuICAgIHJldHVybiBjb250YWluZXIuaW5pdCgpO1xuICB9LFxuICBzZXRSZW5kZXJlcjogZnVuY3Rpb24gKHIpIHtcbiAgICBvbGRSZW5kZXJlciA9IHJlbmRlcmVyO1xuICAgIHJlbmRlcmVyID0gcG9qb3Zpei5yZW5kZXJlcnNbcl07XG4gIH0sXG4gIGdldFJlbmRlcmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHJlbmRlcmVyO1xuICB9LFxuICByZW5kZXI6IHJlbmRlcixcblxuICAvLyBleHBvc2UgaW5uZXIgbW9kdWxlc1xuICBPYmplY3RIYXNoZXM6IHJlcXVpcmUoJy4vT2JqZWN0SGFzaGVzJyksXG4gIE9iamVjdEFuYWx5emVyOiByZXF1aXJlKCcuL09iamVjdEFuYWx5emVyJyksXG4gIGFuYWx5emVyOiB7XG4gICAgR2VuZXJpY0FuYWx5emVyOiByZXF1aXJlKCcuL2FuYWx5emVyL0dlbmVyaWNBbmFseXplcicpXG4gIH0sXG4gIHV0aWxzOiByZXF1aXJlKCcuL3V0aWwnKSxcblxuICAvLyB1c2VyIHZhcnNcbiAgdXNlclZhcmlhYmxlczogW11cbn07XG5cbi8vIGN1c3RvbSBldmVudHNcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Byb3BlcnR5LWNsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgdmFyIGRldGFpbCA9IGUuZGV0YWlsO1xuICBwb2pvdml6XG4gICAgLmdldENvbnRhaW5lcigpXG4gICAgLnNob3dTZWFyY2goZGV0YWlsLm5hbWUsIGRldGFpbC5wcm9wZXJ0eSk7XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBwb2pvdml6OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGhhc2hLZXkgPSByZXF1aXJlKCcuL2hhc2hLZXknKTtcblxuZnVuY3Rpb24gSGFzaE1hcCgpIHtcbn1cblxuSGFzaE1hcC5wcm90b3R5cGUgPSB7XG4gIHB1dDogZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICB0aGlzW2hhc2hLZXkoa2V5KV0gPSAodmFsdWUgfHwga2V5KTtcbiAgfSxcbiAgZ2V0OiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIHRoaXNbaGFzaEtleShrZXkpXTtcbiAgfSxcbiAgcmVtb3ZlOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIHYgPSB0aGlzW2hhc2hLZXkoa2V5KV07XG4gICAgZGVsZXRlIHRoaXNbaGFzaEtleShrZXkpXTtcbiAgICByZXR1cm4gdjtcbiAgfSxcbiAgZW1wdHk6IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcCxcbiAgICAgICAgbWUgPSB0aGlzO1xuICAgIGZvciAocCBpbiBtZSkge1xuICAgICAgaWYgKG1lLmhhc093blByb3BlcnR5KHApKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzW3BdO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBIYXNoTWFwOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKSxcbiAgYXNzZXJ0ID0gcmVxdWlyZSgnLi8nKS5hc3NlcnQsXG4gIG1lLCBoYXNoS2V5O1xuXG5mdW5jdGlvbiBpc09iamVjdE9yRnVuY3Rpb24odikge1xuICByZXR1cm4gdiAmJiAodHlwZW9mIHYgPT09ICdvYmplY3QnIHx8IHR5cGVvZiB2ID09PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBHZXRzIGEgc3RvcmUgaGFzaGtleSBvbmx5IGlmIGl0J3MgYW4gb2JqZWN0XG4gKiBAcGFyYW0gIHtbdHlwZV19IG9ialxuICogQHJldHVybiB7W3R5cGVdfVxuICovXG5mdW5jdGlvbiBnZXQob2JqKSB7XG4gIGFzc2VydChpc09iamVjdE9yRnVuY3Rpb24ob2JqKSwgJ29iaiBtdXN0IGJlIGFuIG9iamVjdHxmdW5jdGlvbicpO1xuICByZXR1cm4gb2JqLmhhc093blByb3BlcnR5ICYmXG4gICAgb2JqLmhhc093blByb3BlcnR5KG1lLmhpZGRlbktleSkgJiZcbiAgICBvYmpbbWUuaGlkZGVuS2V5XTtcbn1cblxuLyoqXG4gKiBTZXRzIGEga2V5IG9uIGFuIG9iamVjdFxuICogQHBhcmFtIHtbdHlwZV19IG9iaiBbZGVzY3JpcHRpb25dXG4gKiBAcGFyYW0ge1t0eXBlXX0ga2V5IFtkZXNjcmlwdGlvbl1cbiAqL1xuZnVuY3Rpb24gc2V0KG9iaiwga2V5KSB7XG4gIGFzc2VydChpc09iamVjdE9yRnVuY3Rpb24ob2JqKSwgJ29iaiBtdXN0IGJlIGFuIG9iamVjdHxmdW5jdGlvbicpO1xuICBhc3NlcnQoXG4gICAga2V5ICYmIHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnLFxuICAgICdUaGUga2V5IG5lZWRzIHRvIGJlIGEgdmFsaWQgc3RyaW5nJ1xuICApO1xuICBpZiAoIWdldChvYmopKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgbWUuaGlkZGVuS2V5LCB7XG4gICAgICB2YWx1ZTogdHlwZW9mIG9iaiArICctJyArIGtleVxuICAgIH0pO1xuICB9XG4gIHJldHVybiBtZTtcbn1cblxubWUgPSBoYXNoS2V5ID0gZnVuY3Rpb24gKHYpIHtcbiAgdmFyIHZhbHVlID0gdixcbiAgICAgIHVpZCA9IHY7XG5cbiAgaWYgKGlzT2JqZWN0T3JGdW5jdGlvbih2KSkge1xuICAgIGlmICghZ2V0KHYpKSB7XG4gICAgICBtZS5jcmVhdGVIYXNoS2V5c0Zvcih2KTtcbiAgICB9XG4gICAgdWlkID0gZ2V0KHYpO1xuICAgIGlmICghdWlkKSB7XG4gICAgICBjb25zb2xlLmVycignbm8gaGFzaGtleSA6KCcsIHYpO1xuICAgIH1cbiAgICBhc3NlcnQodWlkLCAnZXJyb3IgZ2V0dGluZyB0aGUga2V5Jyk7XG4gICAgcmV0dXJuIHVpZDtcbiAgfVxuXG4gIC8vIHYgaXMgYSBwcmltaXRpdmVcbiAgcmV0dXJuIHR5cGVvZiB2ICsgJy0nICsgdWlkO1xufTtcbm1lLmhpZGRlbktleSA9ICdfX3Bvam9WaXpLZXlfXyc7XG5cbm1lLmNyZWF0ZUhhc2hLZXlzRm9yID0gZnVuY3Rpb24gKG9iaiwgbmFtZSkge1xuXG4gIGZ1bmN0aW9uIGxvY2FsVG9TdHJpbmcob2JqKSB7XG4gICAgdmFyIG1hdGNoO1xuICAgIHRyeSB7XG4gICAgICBtYXRjaCA9IHt9LnRvU3RyaW5nLmNhbGwob2JqKS5tYXRjaCgvXlxcW29iamVjdCAoXFxTKj8pXFxdLyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbWF0Y2ggPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG1hdGNoICYmIG1hdGNoWzFdO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuYWx5emUgdGhlIGludGVybmFsIHByb3BlcnR5IFtbQ2xhc3NdXSB0byBndWVzcyB0aGUgbmFtZVxuICAgKiBvZiB0aGlzIG9iamVjdCwgZS5nLiBbb2JqZWN0IERhdGVdLCBbb2JqZWN0IE1hdGhdXG4gICAqIE1hbnkgb2JqZWN0IHdpbGwgZ2l2ZSBmYWxzZSBwb3NpdGl2ZXMgKHRoZXkgd2lsbCBtYXRjaCBbb2JqZWN0IE9iamVjdF0pXG4gICAqIHNvIGxldCdzIGNvbnNpZGVyIE9iamVjdCBhcyB0aGUgbmFtZSBvbmx5IGlmIGl0J3MgZXF1YWwgdG9cbiAgICogT2JqZWN0LnByb3RvdHlwZVxuICAgKiBAcGFyYW0gIHtPYmplY3R9ICBvYmpcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGZ1bmN0aW9uIGhhc0FDbGFzc05hbWUob2JqKSB7XG4gICAgdmFyIG1hdGNoID0gbG9jYWxUb1N0cmluZyhvYmopO1xuICAgIGlmIChtYXRjaCA9PT0gJ09iamVjdCcpIHtcbiAgICAgIHJldHVybiBvYmogPT09IE9iamVjdC5wcm90b3R5cGUgJiYgJ09iamVjdCc7XG4gICAgfVxuICAgIHJldHVybiBtYXRjaDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldE5hbWUob2JqKSB7XG4gICAgdmFyIG5hbWUsIGNsYXNzTmFtZTtcblxuICAgIC8vIHJldHVybiB0aGUgYWxyZWFkeSBnZW5lcmF0ZWQgaGFzaEtleVxuICAgIGlmIChnZXQob2JqKSkge1xuICAgICAgcmV0dXJuIGdldChvYmopO1xuICAgIH1cblxuICAgIC8vIGdlbmVyYXRlIGEgbmV3IGtleSBiYXNlZCBvblxuICAgIC8vIC0gdGhlIG5hbWUgaWYgaXQncyBhIGZ1bmN0aW9uXG4gICAgLy8gLSBhIHVuaXF1ZSBpZFxuICAgIG5hbWUgPSB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nICYmXG4gICAgICB0eXBlb2Ygb2JqLm5hbWUgPT09ICdzdHJpbmcnICYmXG4gICAgICBvYmoubmFtZTtcblxuICAgIGNsYXNzTmFtZSA9IGhhc0FDbGFzc05hbWUob2JqKTtcbiAgICBpZiAoIW5hbWUgJiYgY2xhc3NOYW1lKSB7XG4gICAgICBuYW1lID0gY2xhc3NOYW1lO1xuICAgIH1cblxuICAgIG5hbWUgPSBuYW1lIHx8IF8udW5pcXVlSWQoKTtcbiAgICByZXR1cm4gbmFtZTtcbiAgfVxuXG4gIC8vIHRoZSBuYW1lIGlzIGVxdWFsIHRvIHRoZSBwYXNzZWQgbmFtZSBvciB0aGVcbiAgLy8gZ2VuZXJhdGVkIG5hbWVcbiAgbmFtZSA9IG5hbWUgfHwgZ2V0TmFtZShvYmopO1xuICBuYW1lID0gbmFtZS5yZXBsYWNlKC9bXFwuIF0vaW1nLCAnLScpO1xuXG4gIC8vIGlmIHRoZSBvYmogaXMgYSBwcm90b3R5cGUgdGhlbiB0cnkgdG8gYW5hbHl6ZVxuICAvLyB0aGUgY29uc3RydWN0b3IgZmlyc3Qgc28gdGhhdCB0aGUgcHJvdG90eXBlIGJlY29tZXNcbiAgLy8gW25hbWVdLnByb3RvdHlwZVxuICAvLyBzcGVjaWFsIGNhc2U6IG9iamVjdC5jb25zdHJ1Y3RvciA9IG9iamVjdFxuICBpZiAob2JqLmhhc093blByb3BlcnR5ICYmXG4gICAgICBvYmouaGFzT3duUHJvcGVydHkoJ2NvbnN0cnVjdG9yJykgJiZcbiAgICAgIHR5cGVvZiBvYmouY29uc3RydWN0b3IgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgIG9iai5jb25zdHJ1Y3RvciAhPT0gb2JqKSB7XG4gICAgbWUuY3JlYXRlSGFzaEtleXNGb3Iob2JqLmNvbnN0cnVjdG9yKTtcbiAgfVxuXG4gIC8vIHNldCBuYW1lIG9uIHNlbGZcbiAgc2V0KG9iaiwgbmFtZSk7XG5cbiAgLy8gc2V0IG5hbWUgb24gdGhlIHByb3RvdHlwZVxuICBpZiAodHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJyAmJlxuICAgICAgb2JqLmhhc093blByb3BlcnR5KCdwcm90b3R5cGUnKSkge1xuICAgIHNldChvYmoucHJvdG90eXBlLCBuYW1lICsgJy1wcm90b3R5cGUnKTtcbiAgfVxufTtcblxubWUuaGFzID0gZnVuY3Rpb24gKHYpIHtcbiAgcmV0dXJuIHYuaGFzT3duUHJvcGVydHkgJiZcbiAgICB2Lmhhc093blByb3BlcnR5KG1lLmhpZGRlbktleSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG1lOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF8gPSByZXF1aXJlKCdsb2Rhc2gnKTtcblxudmFyIHByb3BlcnRpZXNUcmFuc2Zvcm1hdGlvbiA9IHtcbiAgJ1tbUHJvdG90eXBlXV0nOiAnX19wcm90b19fJ1xufTtcblxudmFyIHV0aWxzID0ge1xuICBhc3NlcnQ6IGZ1bmN0aW9uICh2LCBtZXNzYWdlKSB7XG4gICAgaWYgKCF2KSB7XG4gICAgICB0aHJvdyBtZXNzYWdlIHx8ICdlcnJvcic7XG4gICAgfVxuICB9LFxuICB0cmFuc2xhdGU6IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgcmV0dXJuICd0cmFuc2xhdGUoJyArICh4IHx8IDApICsgJywgJyArICh5IHx8IDApICsgJyknO1xuICB9LFxuICBzY2FsZTogZnVuY3Rpb24gKHMpIHtcbiAgICByZXR1cm4gJ3NjYWxlKCcgKyAocyB8fCAxKSArICcpJztcbiAgfSxcbiAgdHJhbnNmb3JtOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIHQgPSBbXTtcbiAgICBfLmZvck93bihvYmosIGZ1bmN0aW9uICh2LCBrKSB7XG4gICAgICB0LnB1c2godXRpbHNba10uYXBwbHkodXRpbHMsIHYpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdC5qb2luKCcgJyk7XG4gIH0sXG4gIHByZWZpeGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgYXJncy51bnNoaWZ0KCdwdicpO1xuICAgIHJldHVybiBhcmdzLmpvaW4oJy0nKTtcbiAgfSxcbiAgdHJhbnNmb3JtUHJvcGVydHk6IGZ1bmN0aW9uICh2KSB7XG4gICAgaWYgKHByb3BlcnRpZXNUcmFuc2Zvcm1hdGlvbi5oYXNPd25Qcm9wZXJ0eSh2KSkge1xuICAgICAgcmV0dXJuIHByb3BlcnRpZXNUcmFuc2Zvcm1hdGlvblt2XTtcbiAgICB9XG4gICAgcmV0dXJuIHY7XG4gIH0sXG4gIGVzY2FwZUNsczogZnVuY3Rpb24odikge1xuICAgIHJldHVybiB2LnJlcGxhY2UoL1xcJC9nLCAnXycpO1xuICB9LFxuICB0b1F1ZXJ5U3RyaW5nOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIHMgPSAnJyxcbiAgICAgICAgaSA9IDA7XG4gICAgXy5mb3JPd24ob2JqLCBmdW5jdGlvbiAodiwgaykge1xuICAgICAgaWYgKGkpIHtcbiAgICAgICAgcyArPSAnJic7XG4gICAgICB9XG4gICAgICBzICs9IGsgKyAnPScgKyB2O1xuICAgICAgaSArPSAxO1xuICAgIH0pO1xuICAgIHJldHVybiBzO1xuICB9LFxuICBjcmVhdGVFdmVudDogZnVuY3Rpb24gKGV2ZW50TmFtZSwgZGV0YWlscykge1xuICAgIHJldHVybiBuZXcgQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7XG4gICAgICBkZXRhaWw6IGRldGFpbHNcbiAgICB9KTtcbiAgfSxcbiAgbm90aWZpY2F0aW9uOiBmdW5jdGlvbiAobWVzc2FnZSwgY29uc29sZVRvbykge1xuICAgIHZhciBldiA9IHV0aWxzLmNyZWF0ZUV2ZW50KCdwb2pvdml6LW5vdGlmaWNhdGlvbicsIG1lc3NhZ2UpO1xuICAgIGNvbnNvbGVUb28gJiYgY29uc29sZS5sb2cobWVzc2FnZSk7XG4gICAgZG9jdW1lbnQuZGlzcGF0Y2hFdmVudChldik7XG4gIH0sXG4gIGNyZWF0ZUpzb25wQ2FsbGJhY2s6IGZ1bmN0aW9uICh1cmwpIHtcbiAgICB2YXIgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgc2NyaXB0LnNyYyA9IHVybDtcbiAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdXRpbHM7Il19
  1223. (11)
  1224. });