UNPKG

create-js-app-scripts

Version:
583 lines (461 loc) 48.3 kB
'use strict'; exports.__esModule = true; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.recursivePatternCapture = recursivePatternCapture; var _es6Map = require('es6-map'); var _es6Map2 = _interopRequireDefault(_es6Map); var _fs = require('fs'); var fs = _interopRequireWildcard(_fs); var _crypto = require('crypto'); var _doctrine = require('doctrine'); var doctrine = _interopRequireWildcard(_doctrine); var _debug = require('debug'); var _debug2 = _interopRequireDefault(_debug); var _parse2 = require('./parse'); var _parse3 = _interopRequireDefault(_parse2); var _resolve = require('./resolve'); var _resolve2 = _interopRequireDefault(_resolve); var _ignore = require('./ignore'); var _ignore2 = _interopRequireDefault(_ignore); var _hash = require('./hash'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var log = (0, _debug2.default)('eslint-plugin-import:ExportMap'); var exportCache = new _es6Map2.default(); /** * detect exports without a full parse. * used primarily to ignore the import/ignore setting, iif it looks like * there might be something there (i.e., jsnext:main is set). * @type {RegExp} */ var hasExports = new RegExp('(^|[\\n;])\\s*export\\s[\\w{*]'); var ExportMap = function () { function ExportMap(path) { _classCallCheck(this, ExportMap); this.path = path; this.namespace = new _es6Map2.default(); // todo: restructure to key on path, value is resolver + map of names this.reexports = new _es6Map2.default(); this.dependencies = new _es6Map2.default(); this.errors = []; } ExportMap.get = function get(source, context) { var path = (0, _resolve2.default)(source, context); if (path == null) return null; return ExportMap.for(path, context); }; ExportMap.for = function _for(path, context) { var exportMap = void 0; var cacheKey = (0, _hash.hashObject)((0, _crypto.createHash)('sha256'), { settings: context.settings, parserPath: context.parserPath, parserOptions: context.parserOptions, path: path }).digest('hex'); exportMap = exportCache.get(cacheKey); // return cached ignore if (exportMap === null) return null; var stats = fs.statSync(path); if (exportMap != null) { // date equality check if (exportMap.mtime - stats.mtime === 0) { return exportMap; } // future: check content equality? } // check valid extensions first if (!(0, _ignore.hasValidExtension)(path, context)) { exportCache.set(cacheKey, null); return null; } var content = fs.readFileSync(path, { encoding: 'utf8' }); // check for and cache ignore if ((0, _ignore2.default)(path, context) && !hasExports.test(content)) { exportCache.set(cacheKey, null); return null; } exportMap = ExportMap.parse(path, content, context); exportMap.mtime = stats.mtime; exportCache.set(cacheKey, exportMap); return exportMap; }; ExportMap.parse = function parse(path, content, context) { var m = new ExportMap(path); try { var ast = (0, _parse3.default)(path, content, context); } catch (err) { log('parse error:', path, err); m.errors.push(err); return m; // can't continue } var docstyle = context.settings && context.settings['import/docstyle'] || ['jsdoc']; var docStyleParsers = {}; docstyle.forEach(function (style) { docStyleParsers[style] = availableDocStyleParsers[style]; }); // attempt to collect module doc ast.comments.some(function (c) { if (c.type !== 'Block') return false; try { var doc = doctrine.parse(c.value, { unwrap: true }); if (doc.tags.some(function (t) { return t.title === 'module'; })) { m.doc = doc; return true; } } catch (err) {/* ignore */} return false; }); var namespaces = new _es6Map2.default(); function remotePath(node) { return (0, _resolve.relative)(node.source.value, path, context.settings); } function resolveImport(node) { var rp = remotePath(node); if (rp == null) return null; return ExportMap.for(rp, context); } function getNamespace(identifier) { if (!namespaces.has(identifier.name)) return; return function () { return resolveImport(namespaces.get(identifier.name)); }; } function addNamespace(object, identifier) { var nsfn = getNamespace(identifier); if (nsfn) { Object.defineProperty(object, 'namespace', { get: nsfn }); } return object; } ast.body.forEach(function (n) { if (n.type === 'ExportDefaultDeclaration') { var exportMeta = captureDoc(docStyleParsers, n); if (n.declaration.type === 'Identifier') { addNamespace(exportMeta, n.declaration); } m.namespace.set('default', exportMeta); return; } if (n.type === 'ExportAllDeclaration') { var _ret = function () { var remoteMap = remotePath(n); if (remoteMap == null) return { v: void 0 }; m.dependencies.set(remoteMap, function () { return ExportMap.for(remoteMap, context); }); return { v: void 0 }; }(); if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v; } // capture namespaces in case of later export if (n.type === 'ImportDeclaration') { var ns = void 0; if (n.specifiers.some(function (s) { return s.type === 'ImportNamespaceSpecifier' && (ns = s); })) { namespaces.set(ns.local.name, n); } return; } if (n.type === 'ExportNamedDeclaration') { // capture declaration if (n.declaration != null) { switch (n.declaration.type) { case 'FunctionDeclaration': case 'ClassDeclaration': case 'TypeAlias': // flowtype with babel-eslint parser m.namespace.set(n.declaration.id.name, captureDoc(docStyleParsers, n)); break; case 'VariableDeclaration': n.declaration.declarations.forEach(function (d) { return recursivePatternCapture(d.id, function (id) { return m.namespace.set(id.name, captureDoc(docStyleParsers, d, n)); }); }); break; } } n.specifiers.forEach(function (s) { var exportMeta = {}; var local = void 0; switch (s.type) { case 'ExportDefaultSpecifier': if (!n.source) return; local = 'default'; break; case 'ExportNamespaceSpecifier': m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', { get: function get() { return resolveImport(n); } })); return; case 'ExportSpecifier': if (!n.source) { m.namespace.set(s.exported.name, addNamespace(exportMeta, s.local)); return; } // else falls through default: local = s.local.name; break; } // todo: JSDoc m.reexports.set(s.exported.name, { local: local, getImport: function getImport() { return resolveImport(n); } }); }); } }); return m; }; /** * Note that this does not check explicitly re-exported names for existence * in the base namespace, but it will expand all `export * from '...'` exports * if not found in the explicit namespace. * @param {string} name * @return {Boolean} true if `name` is exported by this module. */ ExportMap.prototype.has = function has(name) { if (this.namespace.has(name)) return true; if (this.reexports.has(name)) return true; // default exports must be explicitly re-exported (#328) var foundInnerMapName = false; if (name !== 'default') { this.dependencies.forEach(function (dep) { if (!foundInnerMapName) { var innerMap = dep(); // todo: report as unresolved? if (innerMap && innerMap.has(name)) foundInnerMapName = true; } }); } return foundInnerMapName; }; /** * ensure that imported name fully resolves. * @param {[type]} name [description] * @return {Boolean} [description] */ ExportMap.prototype.hasDeep = function hasDeep(name) { var _this = this; if (this.namespace.has(name)) return { found: true, path: [this] }; if (this.reexports.has(name)) { var _reexports$get = this.reexports.get(name); var local = _reexports$get.local; var getImport = _reexports$get.getImport; var imported = getImport(); // if import is ignored, return explicit 'null' if (imported == null) return { found: true, path: [this] }; // safeguard against cycles, only if name matches if (imported.path === this.path && local === name) return { found: false, path: [this] }; var deep = imported.hasDeep(local); deep.path.unshift(this); return deep; } // default exports must be explicitly re-exported (#328) var returnValue = { found: false, path: [this] }; if (name !== 'default') { this.dependencies.forEach(function (dep) { if (!returnValue.found) { var innerMap = dep(); // todo: report as unresolved? if (innerMap) { // safeguard against cycles if (innerMap.path !== _this.path) { var innerValue = innerMap.hasDeep(name); if (innerValue.found) { innerValue.path.unshift(_this); returnValue = innerValue; } } } } }); } return returnValue; }; ExportMap.prototype.get = function get(name) { var _this2 = this; if (this.namespace.has(name)) return this.namespace.get(name); if (this.reexports.has(name)) { var _reexports$get2 = this.reexports.get(name); var local = _reexports$get2.local; var getImport = _reexports$get2.getImport; var imported = getImport(); // if import is ignored, return explicit 'null' if (imported == null) return null; // safeguard against cycles, only if name matches if (imported.path === this.path && local === name) return undefined; return imported.get(local); } // default exports must be explicitly re-exported (#328) var returnValue = undefined; if (name !== 'default') { this.dependencies.forEach(function (dep) { if (returnValue === undefined) { var innerMap = dep(); // todo: report as unresolved? if (innerMap) { // safeguard against cycles if (innerMap.path !== _this2.path) { var innerValue = innerMap.get(name); if (innerValue !== undefined) returnValue = innerValue; } } } }); } return returnValue; }; ExportMap.prototype.forEach = function forEach(callback, thisArg) { var _this3 = this; this.namespace.forEach(function (v, n) { return callback.call(thisArg, v, n, _this3); }); this.reexports.forEach(function (_ref, name) { var getImport = _ref.getImport; var local = _ref.local; var reexported = getImport(); // can't look up meta for ignored re-exports (#348) callback.call(thisArg, reexported && reexported.get(local), name, _this3); }); this.dependencies.forEach(function (dep) { return dep().forEach(function (v, n) { return n !== 'default' && callback.call(thisArg, v, n, _this3); }); }); }; // todo: keys, values, entries? ExportMap.prototype.reportErrors = function reportErrors(context, declaration) { context.report({ node: declaration.source, message: 'Parse errors in imported module \'' + declaration.source.value + '\': ' + ('' + this.errors.map(function (e) { return e.message + ' (' + e.lineNumber + ':' + e.column + ')'; }).join(', ')) }); }; _createClass(ExportMap, [{ key: 'hasDefault', get: function get() { return this.get('default') != null; } // stronger than this.has }, { key: 'size', get: function get() { var size = this.namespace.size + this.reexports.size; this.dependencies.forEach(function (dep) { return size += dep().size; }); return size; } }]); return ExportMap; }(); /** * parse docs from the first node that has leading comments * @param {...[type]} nodes [description] * @return {{doc: object}} */ exports.default = ExportMap; function captureDoc(docStyleParsers) { var metadata = {}; // 'some' short-circuits on first 'true' for (var _len = arguments.length, nodes = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { nodes[_key - 1] = arguments[_key]; } nodes.some(function (n) { if (!n.leadingComments) return false; for (var name in docStyleParsers) { var doc = docStyleParsers[name](n.leadingComments); if (doc) { metadata.doc = doc; } } return true; }); return metadata; } var availableDocStyleParsers = { jsdoc: captureJsDoc, tomdoc: captureTomDoc }; /** * parse JSDoc from leading comments * @param {...[type]} comments [description] * @return {{doc: object}} */ function captureJsDoc(comments) { var doc = void 0; // capture XSDoc comments.forEach(function (comment) { // skip non-block comments if (comment.value.slice(0, 4) !== '*\n *') return; try { doc = doctrine.parse(comment.value, { unwrap: true }); } catch (err) { /* don't care, for now? maybe add to `errors?` */ } }); return doc; } /** * parse TomDoc section from comments */ function captureTomDoc(comments) { // collect lines up to first paragraph break var lines = []; for (var i = 0; i < comments.length; i++) { var comment = comments[i]; if (comment.value.match(/^\s*$/)) break; lines.push(comment.value.trim()); } // return doctrine-like object var statusMatch = lines.join(' ').match(/^(Public|Internal|Deprecated):\s*(.+)/); if (statusMatch) { return { description: statusMatch[2], tags: [{ title: statusMatch[1].toLowerCase(), description: statusMatch[2] }] }; } } /** * Traverse a pattern/identifier node, calling 'callback' * for each leaf identifier. * @param {node} pattern * @param {Function} callback * @return {void} */ function recursivePatternCapture(pattern, callback) { switch (pattern.type) { case 'Identifier': // base case callback(pattern); break; case 'ObjectPattern': pattern.properties.forEach(function (_ref2) { var value = _ref2.value; recursivePatternCapture(value, callback); }); break; case 'ArrayPattern': pattern.elements.forEach(function (element) { if (element == null) return; recursivePatternCapture(element, callback); }); break; } } //# sourceMappingURL=data:application/json;base64,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T0FBbkIsQ0FBMkIsaUJBQWU7QUFBQSxZQUFaLEtBQVksU0FBWixLQUFZOztBQUN4QyxnQ0FBd0IsS0FBeEIsRUFBK0IsUUFBL0I7QUFDRCxPQUZEO0FBR0E7O0FBRUYsU0FBSyxjQUFMO0FBQ0UsY0FBUSxRQUFSLENBQWlCLE9BQWpCLENBQXlCLFVBQUMsT0FBRCxFQUFhO0FBQ3BDLFlBQUksV0FBVyxJQUFmLEVBQXFCO0FBQ3JCLGdDQUF3QixPQUF4QixFQUFpQyxRQUFqQztBQUNELE9BSEQ7QUFJQTtBQWhCSjtBQWtCRCIsImZpbGUiOiJjb3JlL2dldEV4cG9ydHMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgTWFwIGZyb20gJ2VzNi1tYXAnXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJ1xuXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJ1xuaW1wb3J0ICogYXMgZG9jdHJpbmUgZnJvbSAnZG9jdHJpbmUnXG5cbmltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1ZydcblxuaW1wb3J0IHBhcnNlIGZyb20gJy4vcGFyc2UnXG5pbXBvcnQgcmVzb2x2ZSwgeyByZWxhdGl2ZSBhcyByZXNvbHZlUmVsYXRpdmUgfSBmcm9tICcuL3Jlc29sdmUnXG5pbXBvcnQgaXNJZ25vcmVkLCB7IGhhc1ZhbGlkRXh0ZW5zaW9uIH0gZnJvbSAnLi9pZ25vcmUnXG5cbmltcG9ydCB7IGhhc2hPYmplY3QgfSBmcm9tICcuL2hhc2gnXG5cbmNvbnN0IGxvZyA9IGRlYnVnKCdlc2xpbnQtcGx1Z2luLWltcG9ydDpFeHBvcnRNYXAnKVxuXG5jb25zdCBleHBvcnRDYWNoZSA9IG5ldyBNYXAoKVxuXG4vKipcbiAqIGRldGVjdCBleHBvcnRzIHdpdGhvdXQgYSBmdWxsIHBhcnNlLlxuICogdXNlZCBwcmltYXJpbHkgdG8gaWdub3JlIHRoZSBpbXBvcnQvaWdub3JlIHNldHRpbmcsIGlpZiBpdCBsb29rcyBsaWtlXG4gKiB0aGVyZSBtaWdodCBiZSBzb21ldGhpbmcgdGhlcmUgKGkuZS4sIGpzbmV4dDptYWluIGlzIHNldCkuXG4gKiBAdHlwZSB7UmVnRXhwfVxuICovXG5jb25zdCBoYXNFeHBvcnRzID0gbmV3IFJlZ0V4cCgnKF58W1xcXFxuO10pXFxcXHMqZXhwb3J0XFxcXHNbXFxcXHd7Kl0nKVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFeHBvcnRNYXAge1xuICBjb25zdHJ1Y3RvcihwYXRoKSB7XG4gICAgdGhpcy5wYXRoID0gcGF0aFxuICAgIHRoaXMubmFtZXNwYWNlID0gbmV3IE1hcCgpXG4gICAgLy8gdG9kbzogcmVzdHJ1Y3R1cmUgdG8ga2V5IG9uIHBhdGgsIHZhbHVlIGlzIHJlc29sdmVyICsgbWFwIG9mIG5hbWVzXG4gICAgdGhpcy5yZWV4cG9ydHMgPSBuZXcgTWFwKClcbiAgICB0aGlzLmRlcGVuZGVuY2llcyA9IG5ldyBNYXAoKVxuICAgIHRoaXMuZXJyb3JzID0gW11cbiAgfVxuXG4gIGdldCBoYXNEZWZhdWx0KCkgeyByZXR1cm4gdGhpcy5nZXQoJ2RlZmF1bHQnKSAhPSBudWxsIH0gLy8gc3Ryb25nZXIgdGhhbiB0aGlzLmhhc1xuXG4gIGdldCBzaXplKCkge1xuICAgIGxldCBzaXplID0gdGhpcy5uYW1lc3BhY2Uuc2l6ZSArIHRoaXMucmVleHBvcnRzLnNpemVcbiAgICB0aGlzLmRlcGVuZGVuY2llcy5mb3JFYWNoKGRlcCA9PiBzaXplICs9IGRlcCgpLnNpemUpXG4gICAgcmV0dXJuIHNpemVcbiAgfVxuXG4gIHN0YXRpYyBnZXQoc291cmNlLCBjb250ZXh0KSB7XG5cbiAgICB2YXIgcGF0aCA9IHJlc29sdmUoc291cmNlLCBjb250ZXh0KVxuICAgIGlmIChwYXRoID09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICByZXR1cm4gRXhwb3J0TWFwLmZvcihwYXRoLCBjb250ZXh0KVxuICB9XG5cbiAgc3RhdGljIGZvcihwYXRoLCBjb250ZXh0KSB7XG4gICAgbGV0IGV4cG9ydE1hcFxuXG4gICAgY29uc3QgY2FjaGVLZXkgPSBoYXNoT2JqZWN0KGNyZWF0ZUhhc2goJ3NoYTI1NicpLCB7XG4gICAgICBzZXR0aW5nczogY29udGV4dC5zZXR0aW5ncyxcbiAgICAgIHBhcnNlclBhdGg6IGNvbnRleHQucGFyc2VyUGF0aCxcbiAgICAgIHBhcnNlck9wdGlvbnM6IGNvbnRleHQucGFyc2VyT3B0aW9ucyxcbiAgICAgIHBhdGgsXG4gICAgfSkuZGlnZXN0KCdoZXgnKVxuXG4gICAgZXhwb3J0TWFwID0gZXhwb3J0Q2FjaGUuZ2V0KGNhY2hlS2V5KVxuXG4gICAgLy8gcmV0dXJuIGNhY2hlZCBpZ25vcmVcbiAgICBpZiAoZXhwb3J0TWFwID09PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgY29uc3Qgc3RhdHMgPSBmcy5zdGF0U3luYyhwYXRoKVxuICAgIGlmIChleHBvcnRNYXAgIT0gbnVsbCkge1xuICAgICAgLy8gZGF0ZSBlcXVhbGl0eSBjaGVja1xuICAgICAgaWYgKGV4cG9ydE1hcC5tdGltZSAtIHN0YXRzLm10aW1lID09PSAwKSB7XG4gICAgICAgIHJldHVybiBleHBvcnRNYXBcbiAgICAgIH1cbiAgICAgIC8vIGZ1dHVyZTogY2hlY2sgY29udGVudCBlcXVhbGl0eT9cbiAgICB9XG5cbiAgICAvLyBjaGVjayB2YWxpZCBleHRlbnNpb25zIGZpcnN0XG4gICAgaWYgKCFoYXNWYWxpZEV4dGVuc2lvbihwYXRoLCBjb250ZXh0KSkge1xuICAgICAgZXhwb3J0Q2FjaGUuc2V0KGNhY2hlS2V5LCBudWxsKVxuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG5cbiAgICBjb25zdCBjb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKHBhdGgsIHsgZW5jb2Rpbmc6ICd1dGY4JyB9KVxuXG4gICAgLy8gY2hlY2sgZm9yIGFuZCBjYWNoZSBpZ25vcmVcbiAgICBpZiAoaXNJZ25vcmVkKHBhdGgsIGNvbnRleHQpICYmICFoYXNFeHBvcnRzLnRlc3QoY29udGVudCkpIHtcbiAgICAgIGV4cG9ydENhY2hlLnNldChjYWNoZUtleSwgbnVsbClcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgZXhwb3J0TWFwID0gRXhwb3J0TWFwLnBhcnNlKHBhdGgsIGNvbnRlbnQsIGNvbnRleHQpXG4gICAgZXhwb3J0TWFwLm10aW1lID0gc3RhdHMubXRpbWVcblxuICAgIGV4cG9ydENhY2hlLnNldChjYWNoZUtleSwgZXhwb3J0TWFwKVxuICAgIHJldHVybiBleHBvcnRNYXBcbiAgfVxuXG4gIHN0YXRpYyBwYXJzZShwYXRoLCBjb250ZW50LCBjb250ZXh0KSB7XG4gICAgdmFyIG0gPSBuZXcgRXhwb3J0TWFwKHBhdGgpXG5cbiAgICB0cnkge1xuICAgICAgdmFyIGFzdCA9IHBhcnNlKHBhdGgsIGNvbnRlbnQsIGNvbnRleHQpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2coJ3BhcnNlIGVycm9yOicsIHBhdGgsIGVycilcbiAgICAgIG0uZXJyb3JzLnB1c2goZXJyKVxuICAgICAgcmV0dXJuIG0gLy8gY2FuJ3QgY29udGludWVcbiAgICB9XG5cbiAgICBjb25zdCBkb2NzdHlsZSA9IChjb250ZXh0LnNldHRpbmdzICYmIGNvbnRleHQuc2V0dGluZ3NbJ2ltcG9ydC9kb2NzdHlsZSddKSB8fCBbJ2pzZG9jJ11cbiAgICBjb25zdCBkb2NTdHlsZVBhcnNlcnMgPSB7fVxuICAgIGRvY3N0eWxlLmZvckVhY2goc3R5bGUgPT4ge1xuICAgICAgZG9jU3R5bGVQYXJzZXJzW3N0eWxlXSA9IGF2YWlsYWJsZURvY1N0eWxlUGFyc2Vyc1tzdHlsZV1cbiAgICB9KVxuXG4gICAgLy8gYXR0ZW1wdCB0byBjb2xsZWN0IG1vZHVsZSBkb2NcbiAgICBhc3QuY29tbWVudHMuc29tZShjID0+IHtcbiAgICAgIGlmIChjLnR5cGUgIT09ICdCbG9jaycpIHJldHVybiBmYWxzZVxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZG9jID0gZG9jdHJpbmUucGFyc2UoYy52YWx1ZSwgeyB1bndyYXA6IHRydWUgfSlcbiAgICAgICAgaWYgKGRvYy50YWdzLnNvbWUodCA9PiB0LnRpdGxlID09PSAnbW9kdWxlJykpIHtcbiAgICAgICAgICBtLmRvYyA9IGRvY1xuICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikgeyAvKiBpZ25vcmUgKi8gfVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfSlcblxuICAgIGNvbnN0IG5hbWVzcGFjZXMgPSBuZXcgTWFwKClcblxuICAgIGZ1bmN0aW9uIHJlbW90ZVBhdGgobm9kZSkge1xuICAgICAgcmV0dXJuIHJlc29sdmVSZWxhdGl2ZShub2RlLnNvdXJjZS52YWx1ZSwgcGF0aCwgY29udGV4dC5zZXR0aW5ncylcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNvbHZlSW1wb3J0KG5vZGUpIHtcbiAgICAgIGNvbnN0IHJwID0gcmVtb3RlUGF0aChub2RlKVxuICAgICAgaWYgKHJwID09IG51bGwpIHJldHVybiBudWxsXG4gICAgICByZXR1cm4gRXhwb3J0TWFwLmZvcihycCwgY29udGV4dClcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXROYW1lc3BhY2UoaWRlbnRpZmllcikge1xuICAgICAgaWYgKCFuYW1lc3BhY2VzLmhhcyhpZGVudGlmaWVyLm5hbWUpKSByZXR1cm5cblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVJbXBvcnQobmFtZXNwYWNlcy5nZXQoaWRlbnRpZmllci5uYW1lKSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGROYW1lc3BhY2Uob2JqZWN0LCBpZGVudGlmaWVyKSB7XG4gICAgICBjb25zdCBuc2ZuID0gZ2V0TmFtZXNwYWNlKGlkZW50aWZpZXIpXG4gICAgICBpZiAobnNmbikge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqZWN0LCAnbmFtZXNwYWNlJywgeyBnZXQ6IG5zZm4gfSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9iamVjdFxuICAgIH1cblxuXG4gICAgYXN0LmJvZHkuZm9yRWFjaChmdW5jdGlvbiAobikge1xuXG4gICAgICBpZiAobi50eXBlID09PSAnRXhwb3J0RGVmYXVsdERlY2xhcmF0aW9uJykge1xuICAgICAgICBjb25zdCBleHBvcnRNZXRhID0gY2FwdHVyZURvYyhkb2NTdHlsZVBhcnNlcnMsIG4pXG4gICAgICAgIGlmIChuLmRlY2xhcmF0aW9uLnR5cGUgPT09ICdJZGVudGlmaWVyJykge1xuICAgICAgICAgIGFkZE5hbWVzcGFjZShleHBvcnRNZXRhLCBuLmRlY2xhcmF0aW9uKVxuICAgICAgICB9XG4gICAgICAgIG0ubmFtZXNwYWNlLnNldCgnZGVmYXVsdCcsIGV4cG9ydE1ldGEpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAobi50eXBlID09PSAnRXhwb3J0QWxsRGVjbGFyYXRpb24nKSB7XG4gICAgICAgIGxldCByZW1vdGVNYXAgPSByZW1vdGVQYXRoKG4pXG4gICAgICAgIGlmIChyZW1vdGVNYXAgPT0gbnVsbCkgcmV0dXJuXG4gICAgICAgIG0uZGVwZW5kZW5jaWVzLnNldChyZW1vdGVNYXAsICgpID0+IEV4cG9ydE1hcC5mb3IocmVtb3RlTWFwLCBjb250ZXh0KSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIC8vIGNhcHR1cmUgbmFtZXNwYWNlcyBpbiBjYXNlIG9mIGxhdGVyIGV4cG9ydFxuICAgICAgaWYgKG4udHlwZSA9PT0gJ0ltcG9ydERlY2xhcmF0aW9uJykge1xuICAgICAgICBsZXQgbnNcbiAgICAgICAgaWYgKG4uc3BlY2lmaWVycy5zb21lKHMgPT4gcy50eXBlID09PSAnSW1wb3J0TmFtZXNwYWNlU3BlY2lmaWVyJyAmJiAobnMgPSBzKSkpIHtcbiAgICAgICAgICBuYW1lc3BhY2VzLnNldChucy5sb2NhbC5uYW1lLCBuKVxuICAgICAgICB9XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAobi50eXBlID09PSAnRXhwb3J0TmFtZWREZWNsYXJhdGlvbicpe1xuICAgICAgICAvLyBjYXB0dXJlIGRlY2xhcmF0aW9uXG4gICAgICAgIGlmIChuLmRlY2xhcmF0aW9uICE9IG51bGwpIHtcbiAgICAgICAgICBzd2l0Y2ggKG4uZGVjbGFyYXRpb24udHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnRnVuY3Rpb25EZWNsYXJhdGlvbic6XG4gICAgICAgICAgICBjYXNlICdDbGFzc0RlY2xhcmF0aW9uJzpcbiAgICAgICAgICAgIGNhc2UgJ1R5cGVBbGlhcyc6IC8vIGZsb3d0eXBlIHdpdGggYmFiZWwtZXNsaW50IHBhcnNlclxuICAgICAgICAgICAgICBtLm5hbWVzcGFjZS5zZXQobi5kZWNsYXJhdGlvbi5pZC5uYW1lLCBjYXB0dXJlRG9jKGRvY1N0eWxlUGFyc2VycywgbikpXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICBjYXNlICdWYXJpYWJsZURlY2xhcmF0aW9uJzpcbiAgICAgICAgICAgICAgbi5kZWNsYXJhdGlvbi5kZWNsYXJhdGlvbnMuZm9yRWFjaCgoZCkgPT5cbiAgICAgICAgICAgICAgICByZWN1cnNpdmVQYXR0ZXJuQ2FwdHVyZShkLmlkLCBpZCA9PlxuICAgICAgICAgICAgICAgICAgbS5uYW1lc3BhY2Uuc2V0KGlkLm5hbWUsIGNhcHR1cmVEb2MoZG9jU3R5bGVQYXJzZXJzLCBkLCBuKSkpKVxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIG4uc3BlY2lmaWVycy5mb3JFYWNoKChzKSA9PiB7XG4gICAgICAgICAgY29uc3QgZXhwb3J0TWV0YSA9IHt9XG4gICAgICAgICAgbGV0IGxvY2FsXG5cbiAgICAgICAgICBzd2l0Y2ggKHMudHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnRXhwb3J0RGVmYXVsdFNwZWNpZmllcic6XG4gICAgICAgICAgICAgIGlmICghbi5zb3VyY2UpIHJldHVyblxuICAgICAgICAgICAgICBsb2NhbCA9ICdkZWZhdWx0J1xuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgY2FzZSAnRXhwb3J0TmFtZXNwYWNlU3BlY2lmaWVyJzpcbiAgICAgICAgICAgICAgbS5uYW1lc3BhY2Uuc2V0KHMuZXhwb3J0ZWQubmFtZSwgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydE1ldGEsICduYW1lc3BhY2UnLCB7XG4gICAgICAgICAgICAgICAgZ2V0KCkgeyByZXR1cm4gcmVzb2x2ZUltcG9ydChuKSB9LFxuICAgICAgICAgICAgICB9KSlcbiAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICBjYXNlICdFeHBvcnRTcGVjaWZpZXInOlxuICAgICAgICAgICAgICBpZiAoIW4uc291cmNlKSB7XG4gICAgICAgICAgICAgICAgbS5uYW1lc3BhY2Uuc2V0KHMuZXhwb3J0ZWQubmFtZSwgYWRkTmFtZXNwYWNlKGV4cG9ydE1ldGEsIHMubG9jYWwpKVxuICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vIGVsc2UgZmFsbHMgdGhyb3VnaFxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgbG9jYWwgPSBzLmxvY2FsLm5hbWVcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyB0b2RvOiBKU0RvY1xuICAgICAgICAgIG0ucmVleHBvcnRzLnNldChzLmV4cG9ydGVkLm5hbWUsIHsgbG9jYWwsIGdldEltcG9ydDogKCkgPT4gcmVzb2x2ZUltcG9ydChuKSB9KVxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH0pXG5cbiAgICByZXR1cm4gbVxuICB9XG5cbiAgLyoqXG4gICAqIE5vdGUgdGhhdCB0aGlzIGRvZXMgbm90IGNoZWNrIGV4cGxpY2l0bHkgcmUtZXhwb3J0ZWQgbmFtZXMgZm9yIGV4aXN0ZW5jZVxuICAgKiBpbiB0aGUgYmFzZSBuYW1lc3BhY2UsIGJ1dCBpdCB3aWxsIGV4cGFuZCBhbGwgYGV4cG9ydCAqIGZyb20gJy4uLidgIGV4cG9ydHNcbiAgICogaWYgbm90IGZvdW5kIGluIHRoZSBleHBsaWNpdCBuYW1lc3BhY2UuXG4gICAqIEBwYXJhbSAge3N0cmluZ30gIG5hbWVcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBgbmFtZWAgaXMgZXhwb3J0ZWQgYnkgdGhpcyBtb2R1bGUuXG4gICAqL1xuICBoYXMobmFtZSkge1xuICAgIGlmICh0aGlzLm5hbWVzcGFjZS5oYXMobmFtZSkpIHJldHVybiB0cnVlXG4gICAgaWYgKHRoaXMucmVleHBvcnRzLmhhcyhuYW1lKSkgcmV0dXJuIHRydWVcblxuICAgIC8vIGRlZmF1bHQgZXhwb3J0cyBtdXN0IGJlIGV4cGxpY2l0bHkgcmUtZXhwb3J0ZWQgKCMzMjgpXG4gICAgbGV0IGZvdW5kSW5uZXJNYXBOYW1lID0gZmFsc2VcbiAgICBpZiAobmFtZSAhPT0gJ2RlZmF1bHQnKSB7XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcy5mb3JFYWNoKChkZXApID0+IHtcbiAgICAgICAgaWYgKCFmb3VuZElubmVyTWFwTmFtZSkge1xuICAgICAgICAgIGxldCBpbm5lck1hcCA9IGRlcCgpXG5cbiAgICAgICAgICAvLyB0b2RvOiByZXBvcnQgYXMgdW5yZXNvbHZlZD9cbiAgICAgICAgICBpZiAoaW5uZXJNYXAgJiYgaW5uZXJNYXAuaGFzKG5hbWUpKSBmb3VuZElubmVyTWFwTmFtZSA9IHRydWVcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG5cbiAgICByZXR1cm4gZm91bmRJbm5lck1hcE5hbWVcbiAgfVxuXG4gIC8qKlxuICAgKiBlbnN1cmUgdGhhdCBpbXBvcnRlZCBuYW1lIGZ1bGx5IHJlc29sdmVzLlxuICAgKiBAcGFyYW0gIHtbdHlwZV19ICBuYW1lIFtkZXNjcmlwdGlvbl1cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gICAgICBbZGVzY3JpcHRpb25dXG4gICAqL1xuICBoYXNEZWVwKG5hbWUpIHtcbiAgICBpZiAodGhpcy5uYW1lc3BhY2UuaGFzKG5hbWUpKSByZXR1cm4geyBmb3VuZDogdHJ1ZSwgcGF0aDogW3RoaXNdIH1cblxuICAgIGlmICh0aGlzLnJlZXhwb3J0cy5oYXMobmFtZSkpIHtcbiAgICAgIGNvbnN0IHsgbG9jYWwsIGdldEltcG9ydCB9ID0gdGhpcy5yZWV4cG9ydHMuZ2V0KG5hbWUpXG4gICAgICAgICAgLCBpbXBvcnRlZCA9IGdldEltcG9ydCgpXG5cbiAgICAgIC8vIGlmIGltcG9ydCBpcyBpZ25vcmVkLCByZXR1cm4gZXhwbGljaXQgJ251bGwnXG4gICAgICBpZiAoaW1wb3J0ZWQgPT0gbnVsbCkgcmV0dXJuIHsgZm91bmQ6IHRydWUsIHBhdGg6IFt0aGlzXSB9XG5cbiAgICAgIC8vIHNhZmVndWFyZCBhZ2FpbnN0IGN5Y2xlcywgb25seSBpZiBuYW1lIG1hdGNoZXNcbiAgICAgIGlmIChpbXBvcnRlZC5wYXRoID09PSB0aGlzLnBhdGggJiYgbG9jYWwgPT09IG5hbWUpIHJldHVybiB7IGZvdW5kOiBmYWxzZSwgcGF0aDogW3RoaXNdIH1cblxuICAgICAgY29uc3QgZGVlcCA9IGltcG9ydGVkLmhhc0RlZXAobG9jYWwpXG4gICAgICBkZWVwLnBhdGgudW5zaGlmdCh0aGlzKVxuXG4gICAgICByZXR1cm4gZGVlcFxuICAgIH1cblxuXG4gICAgLy8gZGVmYXVsdCBleHBvcnRzIG11c3QgYmUgZXhwbGljaXRseSByZS1leHBvcnRlZCAoIzMyOClcbiAgICBsZXQgcmV0dXJuVmFsdWUgPSB7IGZvdW5kOiBmYWxzZSwgcGF0aDogW3RoaXNdIH1cbiAgICBpZiAobmFtZSAhPT0gJ2RlZmF1bHQnKSB7XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcy5mb3JFYWNoKChkZXApID0+IHtcbiAgICAgICAgaWYgKCFyZXR1cm5WYWx1ZS5mb3VuZCkge1xuICAgICAgICAgIGxldCBpbm5lck1hcCA9IGRlcCgpXG4gICAgICAgICAgLy8gdG9kbzogcmVwb3J0IGFzIHVucmVzb2x2ZWQ/XG4gICAgICAgICAgaWYgKGlubmVyTWFwKSB7XG5cbiAgICAgICAgICAgIC8vIHNhZmVndWFyZCBhZ2FpbnN0IGN5Y2xlc1xuICAgICAgICAgICAgaWYgKGlubmVyTWFwLnBhdGggIT09IHRoaXMucGF0aCkge1xuXG4gICAgICAgICAgICAgIGxldCBpbm5lclZhbHVlID0gaW5uZXJNYXAuaGFzRGVlcChuYW1lKVxuICAgICAgICAgICAgICBpZiAoaW5uZXJWYWx1ZS5mb3VuZCkge1xuICAgICAgICAgICAgICAgIGlubmVyVmFsdWUucGF0aC51bnNoaWZ0KHRoaXMpXG4gICAgICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSBpbm5lclZhbHVlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHVyblZhbHVlXG4gIH1cblxuICBnZXQobmFtZSkge1xuICAgIGlmICh0aGlzLm5hbWVzcGFjZS5oYXMobmFtZSkpIHJldHVybiB0aGlzLm5hbWVzcGFjZS5nZXQobmFtZSlcblxuICAgIGlmICh0aGlzLnJlZXhwb3J0cy5oYXMobmFtZSkpIHtcbiAgICAgIGNvbnN0IHsgbG9jYWwsIGdldEltcG9ydCB9ID0gdGhpcy5yZWV4cG9ydHMuZ2V0KG5hbWUpXG4gICAgICAgICAgLCBpbXBvcnRlZCA9IGdldEltcG9ydCgpXG5cbiAgICAgIC8vIGlmIGltcG9ydCBpcyBpZ25vcmVkLCByZXR1cm4gZXhwbGljaXQgJ251bGwnXG4gICAgICBpZiAoaW1wb3J0ZWQgPT0gbnVsbCkgcmV0dXJuIG51bGxcblxuICAgICAgLy8gc2FmZWd1YXJkIGFnYWluc3QgY3ljbGVzLCBvbmx5IGlmIG5hbWUgbWF0Y2hlc1xuICAgICAgaWYgKGltcG9ydGVkLnBhdGggPT09IHRoaXMucGF0aCAmJiBsb2NhbCA9PT0gbmFtZSkgcmV0dXJuIHVuZGVmaW5lZFxuXG4gICAgICByZXR1cm4gaW1wb3J0ZWQuZ2V0KGxvY2FsKVxuICAgIH1cblxuICAgIC8vIGRlZmF1bHQgZXhwb3J0cyBtdXN0IGJlIGV4cGxpY2l0bHkgcmUtZXhwb3J0ZWQgKCMzMjgpXG4gICAgbGV0IHJldHVyblZhbHVlID0gdW5kZWZpbmVkXG4gICAgaWYgKG5hbWUgIT09ICdkZWZhdWx0Jykge1xuICAgICAgdGhpcy5kZXBlbmRlbmNpZXMuZm9yRWFjaCgoZGVwKSA9PiB7XG4gICAgICAgIGlmIChyZXR1cm5WYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbGV0IGlubmVyTWFwID0gZGVwKClcbiAgICAgICAgICAvLyB0b2RvOiByZXBvcnQgYXMgdW5yZXNvbHZlZD9cbiAgICAgICAgICBpZiAoaW5uZXJNYXApIHtcblxuICAgICAgICAgICAgLy8gc2FmZWd1YXJkIGFnYWluc3QgY3ljbGVzXG4gICAgICAgICAgICBpZiAoaW5uZXJNYXAucGF0aCAhPT0gdGhpcy5wYXRoKSB7XG5cbiAgICAgICAgICAgICAgbGV0IGlubmVyVmFsdWUgPSBpbm5lck1hcC5nZXQobmFtZSlcbiAgICAgICAgICAgICAgaWYgKGlubmVyVmFsdWUgIT09IHVuZGVmaW5lZCkgcmV0dXJuVmFsdWUgPSBpbm5lclZhbHVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cblxuICAgIHJldHVybiByZXR1cm5WYWx1ZVxuICB9XG5cbiAgZm9yRWFjaChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgIHRoaXMubmFtZXNwYWNlLmZvckVhY2goKHYsIG4pID0+XG4gICAgICBjYWxsYmFjay5jYWxsKHRoaXNBcmcsIHYsIG4sIHRoaXMpKVxuXG4gICAgdGhpcy5yZWV4cG9ydHMuZm9yRWFjaCgoeyBnZXRJbXBvcnQsIGxvY2FsIH0sIG5hbWUpID0+IHtcbiAgICAgIGNvbnN0IHJlZXhwb3J0ZWQgPSBnZXRJbXBvcnQoKVxuICAgICAgLy8gY2FuJ3QgbG9vayB1cCBtZXRhIGZvciBpZ25vcmVkIHJlLWV4cG9ydHMgKCMzNDgpXG4gICAgICBjYWxsYmFjay5jYWxsKHRoaXNBcmcsIHJlZXhwb3J0ZWQgJiYgcmVleHBvcnRlZC5nZXQobG9jYWwpLCBuYW1lLCB0aGlzKVxuICAgIH0pXG5cbiAgICB0aGlzLmRlcGVuZGVuY2llcy5mb3JFYWNoKGRlcCA9PiBkZXAoKS5mb3JFYWNoKCh2LCBuKSA9PlxuICAgICAgbiAhPT0gJ2RlZmF1bHQnICYmIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdiwgbiwgdGhpcykpKVxuICB9XG5cbiAgLy8gdG9kbzoga2V5cywgdmFsdWVzLCBlbnRyaWVzP1xuXG4gIHJlcG9ydEVycm9ycyhjb250ZXh0LCBkZWNsYXJhdGlvbikge1xuICAgIGNvbnRleHQucmVwb3J0KHtcbiAgICAgIG5vZGU6IGRlY2xhcmF0aW9uLnNvdXJjZSxcbiAgICAgIG1lc3NhZ2U6IGBQYXJzZSBlcnJvcnMgaW4gaW1wb3J0ZWQgbW9kdWxlICcke2RlY2xhcmF0aW9uLnNvdXJjZS52YWx1ZX0nOiBgICtcbiAgICAgICAgICAgICAgICAgIGAke3RoaXMuZXJyb3JzXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKGUgPT4gYCR7ZS5tZXNzYWdlfSAoJHtlLmxpbmVOdW1iZXJ9OiR7ZS5jb2x1bW59KWApXG4gICAgICAgICAgICAgICAgICAgICAgICAuam9pbignLCAnKX1gLFxuICAgIH0pXG4gIH1cbn1cblxuLyoqXG4gKiBwYXJzZSBkb2NzIGZyb20gdGhlIGZpcnN0IG5vZGUgdGhhdCBoYXMgbGVhZGluZyBjb21tZW50c1xuICogQHBhcmFtICB7Li4uW3R5cGVdfSBub2RlcyBbZGVzY3JpcHRpb25dXG4gKiBAcmV0dXJuIHt7ZG9jOiBvYmplY3R9fVxuICovXG5mdW5jdGlvbiBjYXB0dXJlRG9jKGRvY1N0eWxlUGFyc2VycywgLi4ubm9kZXMpIHtcbiAgY29uc3QgbWV0YWRhdGEgPSB7fVxuXG4gIC8vICdzb21lJyBzaG9ydC1jaXJjdWl0cyBvbiBmaXJzdCAndHJ1ZSdcbiAgbm9kZXMuc29tZShuID0+IHtcbiAgICBpZiAoIW4ubGVhZGluZ0NvbW1lbnRzKSByZXR1cm4gZmFsc2VcblxuICAgIGZvciAobGV0IG5hbWUgaW4gZG9jU3R5bGVQYXJzZXJzKSB7XG4gICAgICBjb25zdCBkb2MgPSBkb2NTdHlsZVBhcnNlcnNbbmFtZV0obi5sZWFkaW5nQ29tbWVudHMpXG4gICAgICBpZiAoZG9jKSB7XG4gICAgICAgIG1ldGFkYXRhLmRvYyA9IGRvY1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlXG4gIH0pXG5cbiAgcmV0dXJuIG1ldGFkYXRhXG59XG5cbmNvbnN0IGF2YWlsYWJsZURvY1N0eWxlUGFyc2VycyA9IHtcbiAganNkb2M6IGNhcHR1cmVKc0RvYyxcbiAgdG9tZG9jOiBjYXB0dXJlVG9tRG9jLFxufVxuXG4vKipcbiAqIHBhcnNlIEpTRG9jIGZyb20gbGVhZGluZyBjb21tZW50c1xuICogQHBhcmFtICB7Li4uW3R5cGVdfSBjb21tZW50cyBbZGVzY3JpcHRpb25dXG4gKiBAcmV0dXJuIHt7ZG9jOiBvYmplY3R9fVxuICovXG5mdW5jdGlvbiBjYXB0dXJlSnNEb2MoY29tbWVudHMpIHtcbiAgbGV0IGRvY1xuXG4gIC8vIGNhcHR1cmUgWFNEb2NcbiAgY29tbWVudHMuZm9yRWFjaChjb21tZW50ID0+IHtcbiAgICAvLyBza2lwIG5vbi1ibG9jayBjb21tZW50c1xuICAgIGlmIChjb21tZW50LnZhbHVlLnNsaWNlKDAsIDQpICE9PSAnKlxcbiAqJykgcmV0dXJuXG4gICAgdHJ5IHtcbiAgICAgIGRvYyA9IGRvY3RyaW5lLnBhcnNlKGNvbW1lbnQudmFsdWUsIHsgdW53cmFwOiB0cnVlIH0pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvKiBkb24ndCBjYXJlLCBmb3Igbm93PyBtYXliZSBhZGQgdG8gYGVycm9ycz9gICovXG4gICAgfVxuICB9KVxuXG4gIHJldHVybiBkb2Ncbn1cblxuLyoqXG4gICogcGFyc2UgVG9tRG9jIHNlY3Rpb24gZnJvbSBjb21tZW50c1xuICAqL1xuZnVuY3Rpb24gY2FwdHVyZVRvbURvYyhjb21tZW50cykge1xuICAvLyBjb2xsZWN0IGxpbmVzIHVwIHRvIGZpcnN0IHBhcmFncmFwaCBicmVha1xuICBjb25zdCBsaW5lcyA9IFtdXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY29tbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjb21tZW50ID0gY29tbWVudHNbaV1cbiAgICBpZiAoY29tbWVudC52YWx1ZS5tYXRjaCgvXlxccyokLykpIGJyZWFrXG4gICAgbGluZXMucHVzaChjb21tZW50LnZhbHVlLnRyaW0oKSlcbiAgfVxuXG4gIC8vIHJldHVybiBkb2N0cmluZS1saWtlIG9iamVjdFxuICBjb25zdCBzdGF0dXNNYXRjaCA9IGxpbmVzLmpvaW4oJyAnKS5tYXRjaCgvXihQdWJsaWN8SW50ZXJuYWx8RGVwcmVjYXRlZCk6XFxzKiguKykvKVxuICBpZiAoc3RhdHVzTWF0Y2gpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZGVzY3JpcHRpb246IHN0YXR1c01hdGNoWzJdLFxuICAgICAgdGFnczogW3tcbiAgICAgICAgdGl0bGU6IHN0YXR1c01hdGNoWzFdLnRvTG93ZXJDYXNlKCksXG4gICAgICAgIGRlc2NyaXB0aW9uOiBzdGF0dXNNYXRjaFsyXSxcbiAgICAgIH1dLFxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFRyYXZlcnNlIGEgcGF0dGVybi9pZGVudGlmaWVyIG5vZGUsIGNhbGxpbmcgJ2NhbGxiYWNrJ1xuICogZm9yIGVhY2ggbGVhZiBpZGVudGlmaWVyLlxuICogQHBhcmFtICB7bm9kZX0gICBwYXR0ZXJuXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWN1cnNpdmVQYXR0ZXJuQ2FwdHVyZShwYXR0ZXJuLCBjYWxsYmFjaykge1xuICBzd2l0Y2ggKHBhdHRlcm4udHlwZSkge1xuICAgIGNhc2UgJ0lkZW50aWZpZXInOiAvLyBiYXNlIGNhc2VcbiAgICAgIGNhbGxiYWNrKHBhdHRlcm4pXG4gICAgICBicmVha1xuXG4gICAgY2FzZSAnT2JqZWN0UGF0dGVybic6XG4gICAgICBwYXR0ZXJuLnByb3BlcnRpZXMuZm9yRWFjaCgoeyB2YWx1ZSB9KSA9PiB7XG4gICAgICAgIHJlY3Vyc2l2ZVBhdHRlcm5DYXB0dXJlKHZhbHVlLCBjYWxsYmFjaylcbiAgICAgIH0pXG4gICAgICBicmVha1xuXG4gICAgY2FzZSAnQXJyYXlQYXR0ZXJuJzpcbiAgICAgIHBhdHRlcm4uZWxlbWVudHMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgICBpZiAoZWxlbWVudCA9PSBudWxsKSByZXR1cm5cbiAgICAgICAgcmVjdXJzaXZlUGF0dGVybkNhcHR1cmUoZWxlbWVudCwgY2FsbGJhY2spXG4gICAgICB9KVxuICAgICAgYnJlYWtcbiAgfVxufVxuIl19