/build/pojoviz.js
JavaScript | 1402 lines | 969 code | 178 blank | 255 comment | 99 complexity | b9bb55e10e271b1fcfe24df3da907f2f MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- !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){
- module.exports=_dereq_('JWa/F1');
- },{}],"lodash":[function(_dereq_,module,exports){
- module.exports=_dereq_('K2RcUv');
- },{}],"q":[function(_dereq_,module,exports){
- module.exports=_dereq_('qLuPo1');
- },{}],4:[function(_dereq_,module,exports){
- var HashMap = _dereq_('./util/HashMap'),
- hashKey = _dereq_('./util/hashKey'),
- _ = _dereq_('lodash');
- // utils
- function eachObjectAndPrototype(obj, fn) {
- fn(obj);
- if (obj.hasOwnProperty('prototype')) {
- fn(obj.prototype);
- }
- }
- /**
- * Wraps a function with another
- * @param {Function} fn
- * @param {Function} wrapper
- * @return {*}
- */
- function wrapFn(fn, wrapper) {
- return function () {
- // NOTE: `this` will be the instance
- wrapper.call(this);
- var args = [].slice.call(arguments);
- return fn.apply(this, args);
- };
- }
- function isObjectOrFunction(v) {
- return !!(v && (typeof v === 'object' ||
- typeof v === 'function'));
- }
- /**
- * Properties forbidden in strict mode
- * @type {Array}
- */
- var forbiddenInStrictMode = [
- 'callee', 'caller', 'arguments'
- ];
- /**
- * @constructor
- * Object analyz
- * @param {[type]} config [description]
- */
- function Analyzer(config) {
- if (!(this instanceof Analyzer)) {
- return new Analyzer(config);
- }
- config = config || {};
- /**
- * Objects registered in this instance
- * @type {HashMap}
- */
- this.objects = config.objects || new HashMap();
- /**
- * Forbidden objects
- * @type {HashMap}
- */
- this.forbidden = config.forbidden || new HashMap();
- /**
- * Cache of properties
- * @type {Object}
- */
- this.__cacheObjects = {};
- /**
- * Cache of links
- * @type {Object}
- */
- this.__cacheLinks = {};
- /**
- * Dfs levels
- * @type {number}
- */
- this.levels = Infinity;
- /**
- * If the analyzer is dirty then it has some pending work
- * to do
- * @type {boolean}
- */
- this.dirty = true;
- /**
- * True to save the properties of the objects analyzed in an
- * internal cache
- * @type {Boolean}
- */
- this.cache =
- config.hasOwnProperty('cache') ?
- config.cache : true;
- /**
- * True to include function constructors in the analysis graph
- * i.e. the functions that have a prototype
- * @type {boolean}
- */
- this.functionConstructors =
- config.hasOwnProperty('functionConstructors') ?
- config.functionConstructors : false;
- /**
- * True to include all the functions in the analysis graph
- * @type {boolean}
- */
- this.allFunctions =
- config.hasOwnProperty('allFunctions') ?
- config.allFunctions : false;
- /**
- * True to allow HTML nodes
- * @type {boolean}
- */
- this.htmlNode =
- config.hasOwnProperty('htmlNode') ?
- config.htmlNode : false;
- }
- Analyzer.prototype = {
- constructor: Analyzer,
- /**
- * Checks if an object is in the forbidden hash
- * @param {Object} obj
- * @return {boolean}
- */
- isForbidden: function (obj) {
- return this.forbidden.get(obj);
- },
- isLinkable: function (key, obj) {
- if (!obj) {
- return false;
- }
- var v = typeof obj === 'object';
- // if (v) {
- // if (!this.htmlNode && v instanceof Node) { return false; }
- // return true;
- // }
- // if (!this.htmlNode) {
- // v = v && !(v instanceof Node);
- // }fdeq1`
- // typeof obj === 'function' &&
- // console.log(Object.getOwnPropertyNames(obj));
- if (!v && this.allFunctions) {
- // minimize the nodes created by considering functions
- // with more properties than the usual ones
- v = typeof obj === 'function';
- v = v && Object.getOwnPropertyNames(obj).length > 5;
- }
- if (!v && this.functionConstructors) {
- v = typeof obj === 'function';
- v = v && (
- obj.name &&
- obj.name[0].match(/^[A-Z]/) ||
- key[0].match(/^[A-Z]/)
- );
- }
- return v;
- },
- /**
- * Gets the enumerable properties an object discarding
- * forbidden ones
- *
- * @param {Object} obj
- * @return {Array} Array of objects, each object has the following
- * properties:
- *
- * - name
- * - cls
- * - type
- * - linkeable (if it's an object this property is set to true)
- */
- getProperties: function (obj, linkableOnly) {
- var me = this,
- hk = hashKey(obj),
- properties;
- if (!obj) {
- throw 'this method needs an object to analyze';
- }
- if (this.cache) {
- if (!linkableOnly && this.__cacheObjects[hk]) {
- // console.log('objects from cache :)');
- return this.__cacheObjects[hk];
- }
- }
- properties = Object.getOwnPropertyNames(obj);
- function forbiddenKey(v) {
- // forbidden in strict mode
- return ~forbiddenInStrictMode.indexOf(v) ||
- v.match(/^__.*?__$/) ||
- v.match(/^\$\$.*?\$\$$/) ||
- v.match(/[:+~!><=//\[\]@\. ]/);
- }
- properties = _.filter(properties, function (v) {
- var good = typeof v === 'string' && !forbiddenKey(v),
- r;
- if (linkableOnly) {
- try {
- r = good && me.isLinkable(v, obj[v]);
- } catch (e) {
- r = false;
- // uncomment to see why obj[v] is not allowed
- // console.log(e);
- } finally {
- return r;
- }
- }
- return good;
- }).map(function (v) {
- var type,
- linkeable;
- try {
- // type = null|string|undefined|number|object
- type = typeof obj[v];
- linkeable = isObjectOrFunction(obj[v]);
- } catch(e) {
- type = 'undefined';
- linkeable = false;
- }
- return {
- // parent: hashKey(obj),
- name: v,
- type: type,
- linkeable: linkeable
- };
- });
- // special properties
- var proto = Object.getPrototypeOf(obj);
- if (proto) {
- properties.push({
- name: '[[Prototype]]',
- // cls: hashKey(obj),
- type: 'object',
- linkeable: true,
- hidden: true
- });
- }
- var constructor = obj.hasOwnProperty &&
- obj.hasOwnProperty('constructor') &&
- typeof obj.constructor === 'function';
- if (constructor &&
- _.findIndex(properties, { name: 'constructor' }) === -1) {
- properties.push({
- // cls: hashKey(obj),
- name: 'constructor',
- type: 'function',
- linkeable: true
- });
- }
- if (this.cache && !linkableOnly) {
- this.__cacheObjects[hk] = properties;
- }
- // console.log(properties);
- return properties;
- },
- /**
- * Analyzes a list of objects recursively
- * @param {Array} objects Array of objects
- * @param {number} currentLevel Current dfs level
- */
- analyzeObjects: function (objects, currentLevel) {
- var me = this;
- objects.forEach(function (v) {
- if (currentLevel <= me.levels && // dfs level
- !me.objects.get(v) && // already registered
- !me.isForbidden(v) // forbidden check
- ) {
- // add to the registered object pool
- me.objects.put(v);
- // dfs to the next level
- me.analyzeObjects(
- me.getOwnLinks(v).map(function (link) {
- return link.to;
- }),
- currentLevel + 1
- );
- }
- });
- },
- /**
- * Returns a list of links, each link is an object which has the
- * following properties:
- *
- * - from
- * - to
- * - property (string)
- *
- * @param {Object} obj
- * @return {Array}
- */
- getOwnLinks: function (obj) {
- var me = this,
- links = [],
- properties,
- name = hashKey(obj);
- if (this.__cacheLinks[name]) {
- // console.log('links from cache :)');
- return this.__cacheLinks[name];
- }
- properties = me.getProperties(obj, true);
- function getAugmentedHash(obj, name) {
- if (!hashKey.has(obj) &&
- name !== 'prototype' &&
- name !== 'constructor') {
- hashKey.createHashKeysFor(obj, name);
- }
- return hashKey(obj);
- }
- if (!name) {
- throw 'the object needs to have a hashkey';
- }
- _.forEach(properties, function (v) {
- var ref = obj[v.name];
- // because of the levels a reference might not exist
- if (!ref) {
- return;
- }
- // if the object doesn't have a hashkey
- // let's give it a name equal to the property
- // being analyzed
- getAugmentedHash(ref, v.name);
- if (!me.isForbidden(ref)) {
- links.push({
- from: obj,
- fromHash: hashKey(obj),
- to: ref,
- toHash: hashKey(ref),
- property: v.name
- });
- }
- });
- var proto = Object.getPrototypeOf(obj);
- if (proto && !me.isForbidden(proto)) {
- links.push({
- from: obj,
- fromHash: hashKey(obj),
- to: proto,
- toHash: hashKey(proto),
- property: '[[Prototype]]'
- });
- }
- if (this.cache) {
- this.__cacheLinks[name] = links;
- }
- return links;
- },
- makeDirty: function () {
- this.dirty = true;
- },
- setLevels: function (l) {
- this.levels = l;
- },
- setDirty: function (d) {
- this.dirty = d;
- },
- setFunctionConstructors: function (v) {
- this.functionConstructors = v;
- },
- getObjects: function () {
- return this.objects;
- },
- /**
- * Stringifies an object properties
- * @param obj
- * @param toString
- * @return {Array}
- */
- stringifyObjectProperties: function (obj) {
- return this.getProperties(obj);
- },
- /**
- * Returns a representation of the links of
- * an object
- * @return {Array}
- */
- stringifyObjectLinks: function (obj) {
- var me = this;
- return me.getOwnLinks(obj).map(function (link) {
- // discarded: from, to
- return {
- from: link.fromHash,
- to: link.toHash,
- property: link.property
- };
- });
- },
- /**
- * Stringifies the objects saved in this analyzer
- * @return {Object}
- */
- stringify: function () {
- var me = this,
- nodes = {},
- edges = {};
- console.time('stringify');
- _(this.objects).forOwn(function (v) {
- nodes[hashKey(v)] = me.stringifyObjectProperties(v);
- edges[hashKey(v)] = me.stringifyObjectLinks(v);
- });
- console.timeEnd('stringify');
- return {
- nodes: nodes,
- edges: edges
- };
- }
- };
- // aditional objects that need the prototype to exist
- var aProto = Analyzer.prototype;
- _.merge(aProto, {
- /**
- * Adds a list of objects to analyze and make the analyzer dirty
- * @param {Array<Objects>} objects
- * @return {this}
- */
- add: wrapFn(function (objects) {
- console.time('analyze');
- this.analyzeObjects(objects, 0);
- console.timeEnd('analyze');
- return this;
- }, aProto.makeDirty),
- /**
- * Removes a list of objects, if `withPrototype` is true then
- * also the prototype is removed
- * @param {Array<Objects>} objects
- * @param {boolean} withPrototype
- * @return {this}
- */
- remove: wrapFn(function (objects, withPrototype) {
- var me = this;
- objects.forEach(function (obj) {
- me.objects.remove(obj);
- if (withPrototype && obj.hasOwnProperty('prototype')) {
- me.objects.remove(obj.prototype);
- }
- });
- return me;
- }, aProto.makeDirty),
- /**
- * Forbids a list of objects, if `withPrototype` is true then
- * also the prototype is forbidden
- * @param {Array<Objects>} objects
- * @param {boolean} withPrototype
- * @return {this}
- */
- forbid: wrapFn(function (objects, withPrototype) {
- var me = this;
- me.remove(objects, withPrototype);
- objects.forEach(function (obj) {
- me.forbidden.put(obj);
- if (withPrototype && obj.hasOwnProperty('prototype')) {
- me.forbidden.put(obj.prototype);
- }
- });
- }, aProto.makeDirty),
- /**
- * Unforbids a list of objects, if `withPrototype` is true then
- * also the prototype is unforbidden
- * @param {Array<Objects>} objects
- * @param {boolean} withPrototype
- * @return {this}
- */
- unforbid: wrapFn(function (objects, withPrototype) {
- var me = this;
- objects.forEach(function (obj) {
- me.forbidden.remove(obj);
- if (withPrototype && obj.hasOwnProperty('prototype')) {
- me.forbidden.remove(obj.prototype);
- }
- });
- }, aProto.makeDirty)
- });
- module.exports = Analyzer;
- },{"./util/HashMap":12,"./util/hashKey":13,"lodash":"K2RcUv"}],5:[function(_dereq_,module,exports){
- 'use strict';
- var _ = _dereq_('lodash'),
- Generic = _dereq_('./analyzer/GenericAnalyzer'),
- Angular = _dereq_('./analyzer/Angular'),
- Window = _dereq_('./analyzer/Window'),
- PObject = _dereq_('./analyzer/Object'),
- BuiltIn = _dereq_('./analyzer/BuiltIn');
- var libraries;
- var proto = {
- createNew: function (global, options) {
- console.log('creating a generic container for: ' + global, options);
- return (libraries[global] = new Generic(options));
- },
- all: function (fn) {
- _.forOwn(libraries, fn);
- },
- markDirty: function () {
- proto.all(function (v) {
- v.markDirty();
- });
- return proto;
- },
- setFunctionConstructors: function (newValue) {
- proto.all(function (v) {
- // this only works on the generic analyzers
- if (!v._hasfc) {
- v.analyzer.setFunctionConstructors(newValue);
- }
- });
- return proto;
- }
- };
- libraries = Object.create(proto);
- _.merge(libraries, {
- object: new PObject(),
- builtIn: new BuiltIn(),
- window: new Window(),
- // popular
- angular: new Angular(),
- // mine
- // t3: new Generic({ global: 't3' }),
- // huge
- three: new Generic({
- global: 'THREE',
- rendereachtime: true
- })
- });
- // console.log(libraries);
- // win max level initially is 0
- // libraries.win.preRender = function () {
- // libraries.win.getObjects().empty();
- // libraries.win.analyzeObjects([window], 0);
- // };
- // console.log(builtIn.getObjects());
- // console.log(win.getObjects());
- // console.log(user.getObjects());
- module.exports = libraries;
- },{"./analyzer/Angular":6,"./analyzer/BuiltIn":7,"./analyzer/GenericAnalyzer":8,"./analyzer/Object":9,"./analyzer/Window":10,"lodash":"K2RcUv"}],6:[function(_dereq_,module,exports){
- 'use strict';
- var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
- hashKey = _dereq_('../util/hashKey');
- function Angular() {
- GenericAnalyzer.call(this, {
- global: 'angular',
- displayname: 'AngularJS',
- rendereachtime: true
- });
- this.services = [
- '$animate',
- '$cacheFactory',
- '$compile',
- '$controller',
- // '$document',
- '$exceptionHandler',
- '$filter',
- '$http',
- '$httpBackend',
- '$interpolate',
- '$interval',
- '$locale',
- '$log',
- '$parse',
- '$q',
- '$rootScope',
- '$sce',
- '$sceDelegate',
- '$templateCache',
- '$timeout',
- // '$window'
- ].map(function (v) {
- return { checked: true, name: v };
- });
- }
- Angular.prototype = Object.create(GenericAnalyzer.prototype);
- Angular.prototype.getSelectedServices = function () {
- var me = this,
- toAnalyze = [];
- window.angular.module('app', ['ng']);
- this.injector = window.angular.injector(['app']);
- me.services.forEach(function (s) {
- if (s.checked) {
- var obj = me.injector.get(s.name);
- hashKey.createHashKeysFor(obj, s.name);
- toAnalyze.push(obj);
- }
- });
- return toAnalyze;
- };
- Angular.prototype.inspectSelf = function () {
- console.log('inspecting angular');
- hashKey.createHashKeysFor(window.angular, 'angular');
- this.analyzer.getObjects().empty();
- this.analyzer.add(
- [window.angular].concat(this.getSelectedServices())
- );
- };
- module.exports = Angular;
- },{"../util/hashKey":13,"./GenericAnalyzer":8}],7:[function(_dereq_,module,exports){
- 'use strict';
- var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
- utils = _dereq_('../util');
- var toInspect = [
- Object, Function,
- Array, Date, Boolean, Number, Math, String, RegExp, JSON,
- Error
- ];
- function BuiltIn() {
- GenericAnalyzer.call(this);
- }
- BuiltIn.prototype = Object.create(GenericAnalyzer.prototype);
- BuiltIn.prototype.inspectSelf = function () {
- console.log('inspecting builtIn objects');
- this.analyzer.add(this.getObjects());
- };
- BuiltIn.prototype.getObjects = function () {
- return toInspect;
- };
- BuiltIn.prototype.showSearch = function (nodeName, nodeProperty) {
- var url = 'https://developer.mozilla.org/en-US/search?' +
- utils.toQueryString({
- q: encodeURIComponent(nodeName + ' ' + nodeProperty),
- });
- window.open(url);
- };
- module.exports = BuiltIn;
- },{"../util":14,"./GenericAnalyzer":8}],8:[function(_dereq_,module,exports){
- 'use strict';
- var Q = _dereq_('q'),
- _ = _dereq_('lodash'),
- utils = _dereq_('../util/'),
- hashKey = _dereq_('../util/hashKey'),
- analyzer = _dereq_('../ObjectAnalyzer');
- var searchEngine = 'https://duckduckgo.com/?q=';
- function GenericAnalyzer(options) {
- options = options || {};
- // if (!name) {
- // throw 'name needs to be defined';
- // }
- this.global = options.global;
- this.displayname = options.displayname;
- this.levels = options.hasOwnProperty('levels') ? options.levels : 10;
- this.forbidden = options.forbidden || [];
- this.src = options.src;
- this._hasfc = options.hasOwnProperty('functionconstructors');
- this.functionconstructors = this._hasfc ?
- options.functionconstructors : GenericAnalyzer.SHOW_FUNCTION_CONSTRUCTORS;
- this.rendereachtime = options.hasOwnProperty('rendereachtime') ?
- options.rendereachtime : false;
- this.allfunctions = options.hasOwnProperty('allfunctions') ?
- options.allfunctions : false;
- this.inspected = false;
- // parse forbid string to array
- this.parse();
- this.analyzer = analyzer({
- functionConstructors: this.functionconstructors,
- allFunctions: this.allfunctions
- });
- }
- GenericAnalyzer.SHOW_BUILTIN = false;
- GenericAnalyzer.SHOW_FUNCTION_CONSTRUCTORS = true;
- GenericAnalyzer.FORBIDDEN = 'pojoviz:window,pojoviz:builtIn,document';
- GenericAnalyzer.prototype.init = function () {
- var me = this;
- console.log('%cPojoViz', 'font-size: 15px; color: ');
- return me.fetch()
- .then(function () {
- if (me.rendereachtime || !me.inspected) {
- me.inspect();
- }
- return me;
- });
- };
- GenericAnalyzer.prototype.parse = function () {
- if (typeof this.forbidden === 'string') {
- this.forbidden = this.forbidden.split(',');
- }
- if (typeof this.functionconstructors === 'string') {
- this.functionconstructors = this.functionconstructors === 'true';
- }
- if (typeof this.rendereachtime === 'string') {
- this.rendereachtime = this.rendereachtime === 'true';
- }
- if (typeof this.allfunctions === 'string') {
- this.allfunctions = this.allfunctions === 'true';
- }
- };
- GenericAnalyzer.prototype.markDirty = function () {
- this.inspected = false;
- };
- GenericAnalyzer.prototype.inspectSelf = function () {
- console.log('analyzing window.' + this.global);
- var me = this,
- analyzer = this.analyzer,
- forbidden = [].concat(this.forbidden);
- // set a predefied global
- hashKey.createHashKeysFor(window[this.global], this.global);
- // clean
- analyzer.getObjects().empty();
- analyzer.forbidden.empty();
- analyzer.setLevels(this.levels);
- // settings > show links to built in objects
- if (!GenericAnalyzer.SHOW_BUILTIN) {
- forbidden = forbidden.concat(
- GenericAnalyzer.FORBIDDEN.split(',')
- );
- }
- forbidden.forEach(function(f) {
- var arr,
- tokens;
- if (!f.indexOf('pojoviz:')) {
- tokens = f.split(':');
- arr = _dereq_('../ObjectHashes')[tokens[1]].getObjects();
- } else {
- arr = [window[f]];
- }
- console.log('forbidding: ', arr);
- analyzer.forbid(arr, true);
- });
- analyzer.add([window[this.global]]);
- };
- GenericAnalyzer.prototype.markInspected = function () {
- // mark this container as inspected
- this.inspected = true;
- return this;
- };
- GenericAnalyzer.prototype.inspect = function () {
- this
- .markInspected()
- .inspectSelf();
- };
- GenericAnalyzer.prototype.preRender = function () {
- };
- GenericAnalyzer.prototype.fetch = function () {
- var me = this,
- script;
- function getValue() {
- return window[me.global];
- }
- function promisify(v) {
- return function () {
- utils.notification('fetching script ' + v, true);
- var deferred = Q.defer();
- script = document.createElement('script');
- script.src = v;
- script.onload = function () {
- utils.notification('completed script ' + v, true);
- deferred.resolve(getValue());
- };
- document.head.appendChild(script);
- return deferred.promise;
- };
- }
- if (this.src) {
- if (getValue()) {
- console.log('resource already fetched ' + this.src);
- } else {
- var srcs = this.src.split('|');
- return srcs.reduce(function (prev, current) {
- return prev.then(promisify(current));
- }, Q('reduce'));
- }
- }
- return Q(true);
- };
- GenericAnalyzer.prototype.showSearch = function (nodeName, nodeProperty) {
- var me = this;
- window.open(
- _.template('${searchEngine}${lucky}${libraryName} ${nodeName} ${nodeProperty}', {
- searchEngine: searchEngine,
- lucky: GenericAnalyzer.lucky ? '!ducky' : '',
- libraryName: me.displayname || me.global,
- nodeName: nodeName,
- nodeProperty: nodeProperty
- })
- );
- };
- module.exports = GenericAnalyzer;
- },{"../ObjectAnalyzer":4,"../ObjectHashes":5,"../util/":14,"../util/hashKey":13,"lodash":"K2RcUv","q":"qLuPo1"}],9:[function(_dereq_,module,exports){
- 'use strict';
- var GenericAnalyzer = _dereq_('./GenericAnalyzer'),
- utils = _dereq_('../util');
- function PObject() {
- GenericAnalyzer.call(this);
- }
- PObject.prototype = Object.create(GenericAnalyzer.prototype);
- PObject.prototype.inspectSelf = function () {
- console.log('inspecting Object objects');
- this.analyzer.add(this.getObjects());
- };
- PObject.prototype.getObjects = function () {
- return [Object];
- };
- module.exports = PObject;
- },{"../util":14,"./GenericAnalyzer":8}],10:[function(_dereq_,module,exports){
- 'use strict';
- var _ = _dereq_('lodash'),
- hashKey = _dereq_('../util/hashKey'),
- GenericAnalyzer = _dereq_('./GenericAnalyzer');
- var toInspect = [window];
- function Window() {
- GenericAnalyzer.call(this, {
- levels: 1,
- rendereachtime: true,
- functionconstructors: false
- });
- }
- Window.prototype = Object.create(GenericAnalyzer.prototype);
- Window.prototype.getObjects = function () {
- return toInspect;
- };
- Window.prototype.inspectSelf = function () {
- console.log('inspecting window');
- var me = this,
- hashes = _dereq_('../ObjectHashes');
- _.forOwn(hashes, function (v, k) {
- if (v.global && window[v.global]) {
- me.analyzer.forbid([window[v.global]], true);
- }
- });
- this.analyzer.getObjects().empty();
- this.analyzer.setLevels(this.levels);
- this.analyzer.add(me.getObjects());
- };
- module.exports = Window;
- },{"../ObjectHashes":5,"../util/hashKey":13,"./GenericAnalyzer":8,"lodash":"K2RcUv"}],11:[function(_dereq_,module,exports){
- var _ = _dereq_('lodash'),
- Q = _dereq_('q'),
- dagre = _dereq_('dagre'),
- utils = _dereq_('./util/'),
- ObjectHashes = _dereq_('./ObjectHashes');
- // enable long stacks
- Q.longStackSupport = true;
- var container,
- oldContainer,
- oldRenderer,
- renderer,
- pojoviz; // namespace
- function process() {
- var g = new dagre.Digraph(),
- properties,
- node,
- library = container.analyzer,
- str = library.stringify(),
- libraryNodes = str.nodes,
- libraryEdges = str.edges;
- // create the graph
- // each element of the graph has
- // - label
- // - width
- // - height
- // - properties
- _.forOwn(libraryNodes, function (properties, k) {
- var label = k.match(/\S*?-(.*)/)[1];
- // console.log(k, label.length);
- node = {
- label: k,
- width: label.length * 10
- };
- // lines + header + padding bottom
- node.height = properties.length * 15 + 50;
- node.properties = properties;
- properties.forEach(function (v) {
- node.width = Math.max(node.width, v.name.length * 10);
- });
- g.addNode(k, node);
- });
- // build the edges from node to node
- _.forOwn(libraryEdges, function (links) {
- links.forEach(function (link) {
- if (g.hasNode(link.from) && g.hasNode(link.to)) {
- g.addEdge(null, link.from, link.to);
- }
- });
- });
- // layout of the graph
- var layout = dagre.layout()
- .nodeSep(30)
- // .rankSep(70)
- // .rankDir('TB')
- .run(g);
- var nodes = [],
- edges = [],
- center = {x: 0, y: 0},
- mn = {x: Infinity, y: Infinity},
- mx = {x: -Infinity, y: -Infinity},
- total = g.nodes().length;
- // update the node info of the node adding:
- // - x
- // - y
- // - predecessors
- // - successors
- layout.eachNode(function (k, layoutInfo) {
- var x = layoutInfo.x;
- var y = layoutInfo.y;
- node = g.node(k);
- node.x = x;
- node.y = y;
- node.predecessors = g.predecessors(k);
- node.successors = g.successors(k);
- nodes.push(node);
- // calculate the bbox of the graph to center the graph
- var mnx = x - node.width / 2;
- var mny = y - node.height / 2;
- var mxx = x + node.width / 2;
- var mxy = y + node.height / 2;
- center.x += x;
- center.y += y;
- mn.x = Math.min(mn.x, mnx);
- mn.y = Math.min(mn.y, mny);
- // console.log(x, y, ' dim ', node.width, node.height);
- mx.x = Math.max(mx.x, mxx);
- mx.y = Math.max(mx.y, mxy);
- });
- center.x /= (total || 1);
- center.y /= (total || 1);
- // create the edges from property to node
- _(libraryEdges).forOwn(function (links) {
- links.forEach(function (link) {
- if (g.hasNode(link.from) && g.hasNode(link.to)) {
- edges.push(link);
- }
- });
- });
- return {
- edges: edges,
- nodes: nodes,
- center: center,
- mn: mn,
- mx: mx
- };
- }
- // render
- function render() {
- var data;
- if (container === oldContainer) {
- return;
- }
- utils.notification('processing ' + container.global);
- // pre render
- oldRenderer && oldRenderer.clean();
- renderer.clean();
- setTimeout(function () {
- container.preRender();
- console.log('process & render start: ', new Date());
- // data has
- // - edges (property -> node)
- // - nodes
- // - center
- //
- console.time('process');
- data = process();
- console.timeEnd('process');
- utils.notification('rendering ' + container.global);
- console.time('render');
- renderer.render(data);
- console.timeEnd('render');
- utils.notification('complete!');
- }, 0);
- }
- // public api
- pojoviz = {
- renderers: {},
- addRenderers: function (newRenderers) {
- _.merge(pojoviz.renderers, newRenderers);
- },
- nullifyContainer: function () {
- oldContainer = container;
- container = null;
- },
- getContainer: function () {
- return container;
- },
- setContainer: function (containerName, options) {
- oldContainer = container;
- container = ObjectHashes[containerName];
- if (!container) {
- container = ObjectHashes.createNew(containerName, options);
- } else {
- // required to fetch external resources
- container.src = options.src;
- }
- return container.init();
- },
- setRenderer: function (r) {
- oldRenderer = renderer;
- renderer = pojoviz.renderers[r];
- },
- getRenderer: function () {
- return renderer;
- },
- render: render,
- // expose inner modules
- ObjectHashes: _dereq_('./ObjectHashes'),
- ObjectAnalyzer: _dereq_('./ObjectAnalyzer'),
- analyzer: {
- GenericAnalyzer: _dereq_('./analyzer/GenericAnalyzer')
- },
- utils: _dereq_('./util'),
- // user vars
- userVariables: []
- };
- // custom events
- document.addEventListener('property-click', function (e) {
- var detail = e.detail;
- pojoviz
- .getContainer()
- .showSearch(detail.name, detail.property);
- });
- module.exports = pojoviz;
- },{"./ObjectAnalyzer":4,"./ObjectHashes":5,"./analyzer/GenericAnalyzer":8,"./util":14,"./util/":14,"dagre":"JWa/F1","lodash":"K2RcUv","q":"qLuPo1"}],12:[function(_dereq_,module,exports){
- 'use strict';
- var hashKey = _dereq_('./hashKey');
- function HashMap() {
- }
- HashMap.prototype = {
- put: function (key, value) {
- this[hashKey(key)] = (value || key);
- },
- get: function (key) {
- return this[hashKey(key)];
- },
- remove: function (key) {
- var v = this[hashKey(key)];
- delete this[hashKey(key)];
- return v;
- },
- empty: function () {
- var p,
- me = this;
- for (p in me) {
- if (me.hasOwnProperty(p)) {
- delete this[p];
- }
- }
- }
- };
- module.exports = HashMap;
- },{"./hashKey":13}],13:[function(_dereq_,module,exports){
- 'use strict';
- var _ = _dereq_('lodash'),
- assert = _dereq_('./').assert,
- me, hashKey;
- function isObjectOrFunction(v) {
- return v && (typeof v === 'object' || typeof v === 'function');
- }
- /**
- * Gets a store hashkey only if it's an object
- * @param {[type]} obj
- * @return {[type]}
- */
- function get(obj) {
- assert(isObjectOrFunction(obj), 'obj must be an object|function');
- return obj.hasOwnProperty &&
- obj.hasOwnProperty(me.hiddenKey) &&
- obj[me.hiddenKey];
- }
- /**
- * Sets a key on an object
- * @param {[type]} obj [description]
- * @param {[type]} key [description]
- */
- function set(obj, key) {
- assert(isObjectOrFunction(obj), 'obj must be an object|function');
- assert(
- key && typeof key === 'string',
- 'The key needs to be a valid string'
- );
- if (!get(obj)) {
- Object.defineProperty(obj, me.hiddenKey, {
- value: typeof obj + '-' + key
- });
- }
- return me;
- }
- me = hashKey = function (v) {
- var value = v,
- uid = v;
- if (isObjectOrFunction(v)) {
- if (!get(v)) {
- me.createHashKeysFor(v);
- }
- uid = get(v);
- if (!uid) {
- console.err('no hashkey :(', v);
- }
- assert(uid, 'error getting the key');
- return uid;
- }
- // v is a primitive
- return typeof v + '-' + uid;
- };
- me.hiddenKey = '__pojoVizKey__';
- me.createHashKeysFor = function (obj, name) {
- function localToString(obj) {
- var match;
- try {
- match = {}.toString.call(obj).match(/^\[object (\S*?)\]/);
- } catch (e) {
- match = false;
- }
- return match && match[1];
- }
- /**
- * Analyze the internal property [[Class]] to guess the name
- * of this object, e.g. [object Date], [object Math]
- * Many object will give false positives (they will match [object Object])
- * so let's consider Object as the name only if it's equal to
- * Object.prototype
- * @param {Object} obj
- * @return {Boolean}
- */
- function hasAClassName(obj) {
- var match = localToString(obj);
- if (match === 'Object') {
- return obj === Object.prototype && 'Object';
- }
- return match;
- }
- function getName(obj) {
- var name, className;
- // return the already generated hashKey
- if (get(obj)) {
- return get(obj);
- }
- // generate a new key based on
- // - the name if it's a function
- // - a unique id
- name = typeof obj === 'function' &&
- typeof obj.name === 'string' &&
- obj.name;
- className = hasAClassName(obj);
- if (!name && className) {
- name = className;
- }
- name = name || _.uniqueId();
- return name;
- }
- // the name is equal to the passed name or the
- // generated name
- name = name || getName(obj);
- name = name.replace(/[\. ]/img, '-');
- // if the obj is a prototype then try to analyze
- // the constructor first so that the prototype becomes
- // [name].prototype
- // special case: object.constructor = object
- if (obj.hasOwnProperty &&
- obj.hasOwnProperty('constructor') &&
- typeof obj.constructor === 'function' &&
- obj.constructor !== obj) {
- me.createHashKeysFor(obj.constructor);
- }
- // set name on self
- set(obj, name);
- // set name on the prototype
- if (typeof obj === 'function' &&
- obj.hasOwnProperty('prototype')) {
- set(obj.prototype, name + '-prototype');
- }
- };
- me.has = function (v) {
- return v.hasOwnProperty &&
- v.hasOwnProperty(me.hiddenKey);
- };
- module.exports = me;
- },{"./":14,"lodash":"K2RcUv"}],14:[function(_dereq_,module,exports){
- 'use strict';
- var _ = _dereq_('lodash');
- var propertiesTransformation = {
- '[[Prototype]]': '__proto__'
- };
- var utils = {
- assert: function (v, message) {
- if (!v) {
- throw message || 'error';
- }
- },
- translate: function (x, y) {
- return 'translate(' + (x || 0) + ', ' + (y || 0) + ')';
- },
- scale: function (s) {
- return 'scale(' + (s || 1) + ')';
- },
- transform: function (obj) {
- var t = [];
- _.forOwn(obj, function (v, k) {
- t.push(utils[k].apply(utils, v));
- });
- return t.join(' ');
- },
- prefixer: function () {
- var args = [].slice.call(arguments);
- args.unshift('pv');
- return args.join('-');
- },
- transformProperty: function (v) {
- if (propertiesTransformation.hasOwnProperty(v)) {
- return propertiesTransformation[v];
- }
- return v;
- },
- escapeCls: function(v) {
- return v.replace(/\$/g, '_');
- },
- toQueryString: function (obj) {
- var s = '',
- i = 0;
- _.forOwn(obj, function (v, k) {
- if (i) {
- s += '&';
- }
- s += k + '=' + v;
- i += 1;
- });
- return s;
- },
- createEvent: function (eventName, details) {
- return new CustomEvent(eventName, {
- detail: details
- });
- },
- notification: function (message, consoleToo) {
- var ev = utils.createEvent('pojoviz-notification', message);
- consoleToo && console.log(message);
- document.dispatchEvent(ev);
- },
- createJsonpCallback: function (url) {
- var script = document.createElement('script');
- script.src = url;
- document.head.appendChild(script);
- }
- };
- module.exports = utils;
- },{"lodash":"K2RcUv"}]},{},[11])
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9PYmplY3RBbmFseXplci5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvT2JqZWN0SGFzaGVzLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9Bbmd1bGFyLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9CdWlsdEluLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9hbmFseXplci9HZW5lcmljQW5hbHl6ZXIuanMiLCIvVXNlcnMvbWF1cmljaW8vRG9jdW1lbnRzL3dlYi9tYXVyaXp6emlvLm1lL3Bvam92aXovc3JjL2FuYWx5emVyL09iamVjdC5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvYW5hbHl6ZXIvV2luZG93LmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy9pbmRleC5qcyIsIi9Vc2Vycy9tYXVyaWNpby9Eb2N1bWVudHMvd2ViL21hdXJpenp6aW8ubWUvcG9qb3Zpei9zcmMvdXRpbC9IYXNoTWFwLmpzIiwiL1VzZXJzL21hdXJpY2lvL0RvY3VtZW50cy93ZWIvbWF1cml6enppby5tZS9wb2pvdml6L3NyYy91dGlsL2hhc2hLZXkuanMiLCIvVXNlcnMvbWF1cmljaW8vRG9jdW1lbnRzL3dlYi9tYXVyaXp6emlvLm1lL3Bvam92aXovc3JjL3V0aWwvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgSGFzaE1hcCA9IHJlcXVpcmUoJy4vdXRpbC9IYXNoTWFwJyksXG4gIGhhc2hLZXkgPSByZXF1aXJlKCcuL3V0aWwvaGFzaEtleScpLFxuICBfID0gcmVxdWlyZSgnbG9kYXNoJyk7XG5cbi8vIHV0aWxzXG5mdW5jdGlvbiBlYWNoT2JqZWN0QW5kUHJvdG90eXBlKG9iaiwgZm4pIHtcbiAgZm4ob2JqKTtcbiAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eSgncHJvdG90eXBlJykpIHtcbiAgICBmbihvYmoucHJvdG90eXBlKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyYXBzIGEgZnVuY3Rpb24gd2l0aCBhbm90aGVyXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gZm5cbiAqIEBwYXJhbSAge0Z1bmN0aW9ufSAgIHdyYXBwZXJcbiAqIEByZXR1cm4geyp9XG4gKi9cbmZ1bmN0aW9uIHdyYXBGbihmbiwgd3JhcHBlcikge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIC8vIE5PVEU6IGB0aGlzYCB3aWxsIGJlIHRoZSBpbnN0YW5jZVxuICAgIHdyYXBwZXIuY2FsbCh0aGlzKTtcbiAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0T3JGdW5jdGlvbih2KSB7XG4gIHJldHVybiAhISh2ICYmICh0eXBlb2YgdiA9PT0gJ29iamVjdCcgfHxcbiAgICB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJykpO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yYmlkZGVuIGluIHN0cmljdCBtb2RlXG4gKiBAdHlwZSB7QXJyYXl9XG4gKi9cbnZhciBmb3JiaWRkZW5JblN0cmljdE1vZGUgPSBbXG4gICdjYWxsZWUnLCAnY2FsbGVyJywgJ2FyZ3VtZW50cydcbl07XG5cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKiBPYmplY3QgYW5hbHl6XG4gKiBAcGFyYW0ge1t0eXBlXX0gY29uZmlnIFtkZXNjcmlwdGlvbl1cbiAqL1xuZnVuY3Rpb24gQW5hbHl6ZXIoY29uZmlnKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBBbmFseXplcikpIHtcbiAgICByZXR1cm4gbmV3IEFuYWx5emVyKGNvbmZpZyk7XG4gIH1cbiAgY29uZmlnID0gY29uZmlnIHx8IHt9O1xuXG4gIC8qKlxuICAgKiBPYmplY3RzIHJlZ2lzdGVyZWQgaW4gdGhpcyBpbnN0YW5jZVxuICAgKiBAdHlwZSB7SGFzaE1hcH1cbiAgICovXG4gIHRoaXMub2JqZWN0cyA9IGNvbmZpZy5vYmplY3RzIHx8IG5ldyBIYXNoTWFwKCk7XG4gIC8qKlxuICAgKiBGb3JiaWRkZW4gb2JqZWN0c1xuICAgKiBAdHlwZSB7SGFzaE1hcH1cbiAgICovXG4gIHRoaXMuZm9yYmlkZGVuID0gY29uZmlnLmZvcmJpZGRlbiB8fCBuZXcgSGFzaE1hcCgpO1xuXG4gIC8qKlxuICAgKiBDYWNoZSBvZiBwcm9wZXJ0aWVzXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLl9fY2FjaGVPYmplY3RzID0ge307XG5cbiAgLyoqXG4gICAqIENhY2hlIG9mIGxpbmtzXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLl9fY2FjaGVMaW5rcyA9IHt9O1xuXG4gIC8qKlxuICAgKiBEZnMgbGV2ZWxzXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICB0aGlzLmxldmVscyA9IEluZmluaXR5O1xuICAvKipcbiAgICogSWYgdGhlIGFuYWx5emVyIGlzIGRpcnR5IHRoZW4gaXQgaGFzIHNvbWUgcGVuZGluZyB3b3JrXG4gICAqIHRvIGRvXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgdGhpcy5kaXJ0eSA9IHRydWU7XG5cbiAgLyoqXG4gICAqIFRydWUgdG8gc2F2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgb2JqZWN0cyBhbmFseXplZCBpbiBhblxuICAgKiBpbnRlcm5hbCBjYWNoZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuY2FjaGUgPVxuICAgIGNvbmZpZy5oYXNPd25Qcm9wZXJ0eSgnY2FjaGUnKSA/XG4gICAgY29uZmlnLmNhY2hlIDogdHJ1ZTtcbiAgLyoqXG4gICAqIFRydWUgdG8gaW5jbHVkZSBmdW5jdGlvbiBjb25zdHJ1Y3RvcnMgaW4gdGhlIGFuYWx5c2lzIGdyYXBoXG4gICAqIGkuZS4gdGhlIGZ1bmN0aW9ucyB0aGF0IGhhdmUgYSBwcm90b3R5cGVcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqL1xuICB0aGlzLmZ1bmN0aW9uQ29uc3RydWN0b3JzID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2Z1bmN0aW9uQ29uc3RydWN0b3JzJykgP1xuICAgIGNvbmZpZy5mdW5jdGlvbkNvbnN0cnVjdG9ycyA6IGZhbHNlO1xuICAvKipcbiAgICogVHJ1ZSB0byBpbmNsdWRlIGFsbCB0aGUgZnVuY3Rpb25zIGluIHRoZSBhbmFseXNpcyBncmFwaFxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIHRoaXMuYWxsRnVuY3Rpb25zID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2FsbEZ1bmN0aW9ucycpID9cbiAgICBjb25maWcuYWxsRnVuY3Rpb25zIDogZmFsc2U7XG4gIC8qKlxuICAgKiBUcnVlIHRvIGFsbG93IEhUTUwgbm9kZXNcbiAgICogQHR5cGUge2Jvb2xlYW59XG4gICAqL1xuICB0aGlzLmh0bWxOb2RlID1cbiAgICBjb25maWcuaGFzT3duUHJvcGVydHkoJ2h0bWxOb2RlJykgP1xuICAgIGNvbmZpZy5odG1sTm9kZSA6IGZhbHNlO1xufVxuXG5BbmFseXplci5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBBbmFseXplcixcblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGFuIG9iamVjdCBpcyBpbiB0aGUgZm9yYmlkZGVuIGhhc2hcbiAgICogQHBhcmFtICB7T2JqZWN0fSAgb2JqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBpc0ZvcmJpZGRlbjogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiB0aGlzLmZvcmJpZGRlbi5nZXQob2JqKTtcbiAgfSxcblxuICBpc0xpbmthYmxlOiBmdW5jdGlvbiAoa2V5LCBvYmopIHtcbiAgICBpZiAoIW9iaikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciB2ID0gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCc7XG5cbiAgICAvLyBpZiAodikge1xuICAgIC8vICAgaWYgKCF0aGlzLmh0bWxOb2RlICYmIHYgaW5zdGFuY2VvZiBOb2RlKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIC8vICAgcmV0dXJuIHRydWU7XG4gICAgLy8gfVxuXG4gICAgLy8gaWYgKCF0aGlzLmh0bWxOb2RlKSB7XG4gICAgLy8gICB2ID0gdiAmJiAhKHYgaW5zdGFuY2VvZiBOb2RlKTtcbiAgICAvLyB9ZmRlcTFgXG5cbiAgICAvLyB0eXBlb2Ygb2JqID09PSAnZnVuY3Rpb24nICYmXG4gICAgLy8gICBjb25zb2xlLmxvZyhPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopKTtcbiAgICBpZiAoIXYgJiYgdGhpcy5hbGxGdW5jdGlvbnMpIHtcbiAgICAgIC8vIG1pbmltaXplIHRoZSBub2RlcyBjcmVhdGVkIGJ5IGNvbnNpZGVyaW5nIGZ1bmN0aW9uc1xuICAgICAgLy8gd2l0aCBtb3JlIHByb3BlcnRpZXMgdGhhbiB0aGUgdXN1YWwgb25lc1xuICAgICAgdiA9IHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbic7XG4gICAgICB2ID0gdiAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopLmxlbmd0aCA+IDU7XG4gICAgfVxuICAgIGlmICghdiAmJiB0aGlzLmZ1bmN0aW9uQ29uc3RydWN0b3JzKSB7XG4gICAgICB2I…
Large files files are truncated, but you can click here to view the full file