UNPKG

electron-compile

Version:

Electron supporting package to compile JS and CSS in Electron applications

520 lines (414 loc) 39.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _stringify = require('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib); var _digestForObject = require('./digest-for-object'); var _digestForObject2 = _interopRequireDefault(_digestForObject); var _promise = require('./promise'); var _mkdirp = require('mkdirp'); var _mkdirp2 = _interopRequireDefault(_mkdirp); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var d = require('debug')('electron-compile:compile-cache'); /** * CompileCache manages getting and setting entries for a single compiler; each * in-use compiler will have an instance of this class, usually created via * {@link createFromCompiler}. * * You usually will not use this class directly, it is an implementation class * for {@link CompileHost}. */ var CompileCache = function () { /** * Creates an instance, usually used for testing only. * * @param {string} cachePath The root directory to use as a cache path * * @param {FileChangedCache} fileChangeCache A file-change cache that is * optionally pre-loaded. */ function CompileCache(cachePath, fileChangeCache) { (0, _classCallCheck3.default)(this, CompileCache); this.cachePath = cachePath; this.fileChangeCache = fileChangeCache; } /** * Creates a CompileCache from a class compatible with the CompilerBase * interface. This method uses the compiler name / version / options to * generate a unique directory name for cached results * * @param {string} cachePath The root path to use for the cache, a directory * representing the hash of the compiler parameters * will be created here. * * @param {CompilerBase} compiler The compiler to use for version / option * information. * * @param {FileChangedCache} fileChangeCache A file-change cache that is * optionally pre-loaded. * * @param {boolean} readOnlyMode Don't attempt to create the cache directory. * * @return {CompileCache} A configured CompileCache instance. */ (0, _createClass3.default)(CompileCache, [{ key: 'get', /** * Returns a file's compiled contents from the cache. * * @param {string} filePath The path to the file. FileChangedCache will look * up the hash and use that as the key in the cache. * * @return {Promise<Object>} An object with all kinds of information * * @property {Object} hashInfo The hash information returned from getHashForPath * @property {string} code The source code if the file was a text file * @property {Buffer} binaryData The file if it was a binary file * @property {string} mimeType The MIME type saved in the cache. * @property {string[]} dependentFiles The dependent files returned from * compiling the file, if any. */ value: function () { var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(filePath) { var hashInfo, code, mimeType, binaryData, dependentFiles, cacheFile, result, info, buf, str; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: d('Fetching ' + filePath + ' from cache'); _context.next = 3; return this.fileChangeCache.getHashForPath(_path2.default.resolve(filePath)); case 3: hashInfo = _context.sent; code = null; mimeType = null; binaryData = null; dependentFiles = null; cacheFile = null; _context.prev = 9; cacheFile = _path2.default.join(this.getCachePath(), hashInfo.hash); result = null; if (!hashInfo.isFileBinary) { _context.next = 31; break; } d("File is binary, reading out info"); _context.t0 = JSON; _context.next = 17; return _promise.pfs.readFile(cacheFile + '.info'); case 17: _context.t1 = _context.sent; info = _context.t0.parse.call(_context.t0, _context.t1); mimeType = info.mimeType; dependentFiles = info.dependentFiles; binaryData = hashInfo.binaryData; if (binaryData) { _context.next = 29; break; } _context.next = 25; return _promise.pfs.readFile(cacheFile); case 25: binaryData = _context.sent; _context.next = 28; return _promise.pzlib.gunzip(binaryData); case 28: binaryData = _context.sent; case 29: _context.next = 41; break; case 31: _context.next = 33; return _promise.pfs.readFile(cacheFile); case 33: buf = _context.sent; _context.next = 36; return _promise.pzlib.gunzip(buf); case 36: str = _context.sent.toString('utf8'); result = JSON.parse(str); code = result.code; mimeType = result.mimeType; dependentFiles = result.dependentFiles; case 41: _context.next = 46; break; case 43: _context.prev = 43; _context.t2 = _context['catch'](9); d('Failed to read cache for ' + filePath + ', looked in ' + cacheFile + ': ' + _context.t2.message); case 46: return _context.abrupt('return', { hashInfo: hashInfo, code: code, mimeType: mimeType, binaryData: binaryData, dependentFiles: dependentFiles }); case 47: case 'end': return _context.stop(); } } }, _callee, this, [[9, 43]]); })); return function get(_x) { return ref.apply(this, arguments); }; }() /** * Saves a compiled result to cache * * @param {Object} hashInfo The hash information returned from getHashForPath * * @param {string / Buffer} codeOrBinaryData The file's contents, either as * a string or a Buffer. * @param {string} mimeType The MIME type returned by the compiler. * * @param {string[]} dependentFiles The list of dependent files returned by * the compiler. * @return {Promise} Completion. */ }, { key: 'save', value: function () { var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(hashInfo, codeOrBinaryData, mimeType, dependentFiles) { var buf, target; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: buf = null; target = _path2.default.join(this.getCachePath(), hashInfo.hash); d('Saving to ' + target); if (!hashInfo.isFileBinary) { _context2.next = 11; break; } _context2.next = 6; return _promise.pzlib.gzip(codeOrBinaryData); case 6: buf = _context2.sent; _context2.next = 9; return _promise.pfs.writeFile(target + '.info', (0, _stringify2.default)({ mimeType: mimeType, dependentFiles: dependentFiles }), 'utf8'); case 9: _context2.next = 14; break; case 11: _context2.next = 13; return _promise.pzlib.gzip(new Buffer((0, _stringify2.default)({ code: codeOrBinaryData, mimeType: mimeType, dependentFiles: dependentFiles }))); case 13: buf = _context2.sent; case 14: _context2.next = 16; return _promise.pfs.writeFile(target, buf); case 16: case 'end': return _context2.stop(); } } }, _callee2, this); })); return function save(_x2, _x3, _x4, _x5) { return ref.apply(this, arguments); }; }() /** * Attempts to first get a key via {@link get}, then if it fails, call a method * to retrieve the contents, then save the result to cache. * * The fetcher parameter is expected to have the signature: * * Promise<Object> fetcher(filePath : string, hashInfo : Object); * * hashInfo is a value returned from getHashForPath * The return value of fetcher must be an Object with the properties: * * mimeType - the MIME type of the data to save * code (optional) - the source code as a string, if file is text * binaryData (optional) - the file contents as a Buffer, if file is binary * dependentFiles - the dependent files returned by the compiler. * * @param {string} filePath The path to the file. FileChangedCache will look * up the hash and use that as the key in the cache. * * @param {Function} fetcher A method which conforms to the description above. * * @return {Promise<Object>} An Object which has the same fields as the * {@link get} method return result. */ }, { key: 'getOrFetch', value: function () { var ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(filePath, fetcher) { var cacheResult, result; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _context3.next = 2; return this.get(filePath); case 2: cacheResult = _context3.sent; if (!(cacheResult.code || cacheResult.binaryData)) { _context3.next = 5; break; } return _context3.abrupt('return', cacheResult); case 5: _context3.next = 7; return fetcher(filePath, cacheResult.hashInfo); case 7: _context3.t0 = _context3.sent; if (_context3.t0) { _context3.next = 10; break; } _context3.t0 = { hashInfo: cacheResult.hashInfo }; case 10: result = _context3.t0; if (!(result.mimeType && !cacheResult.hashInfo.isInNodeModules)) { _context3.next = 15; break; } d('Cache miss: saving out info for ' + filePath); _context3.next = 15; return this.save(cacheResult.hashInfo, result.code || result.binaryData, result.mimeType, result.dependentFiles); case 15: result.hashInfo = cacheResult.hashInfo; return _context3.abrupt('return', result); case 17: case 'end': return _context3.stop(); } } }, _callee3, this); })); return function getOrFetch(_x6, _x7) { return ref.apply(this, arguments); }; }() }, { key: 'getSync', value: function getSync(filePath) { d('Fetching ' + filePath + ' from cache'); var hashInfo = this.fileChangeCache.getHashForPathSync(_path2.default.resolve(filePath)); var code = null; var mimeType = null; var binaryData = null; var dependentFiles = null; try { var cacheFile = _path2.default.join(this.getCachePath(), hashInfo.hash); var _result = null; if (hashInfo.isFileBinary) { d("File is binary, reading out info"); var _info = JSON.parse(_fs2.default.readFileSync(cacheFile + '.info')); mimeType = _info.mimeType; dependentFiles = _info.dependentFiles; binaryData = hashInfo.binaryData; if (!binaryData) { binaryData = _fs2.default.readFileSync(cacheFile); binaryData = _zlib2.default.gunzipSync(binaryData); } } else { var _buf = _fs2.default.readFileSync(cacheFile); var _str = _zlib2.default.gunzipSync(_buf).toString('utf8'); _result = JSON.parse(_str); code = _result.code; mimeType = _result.mimeType; dependentFiles = _result.dependentFiles; } } catch (e) { d('Failed to read cache for ' + filePath); } return { hashInfo: hashInfo, code: code, mimeType: mimeType, binaryData: binaryData, dependentFiles: dependentFiles }; } }, { key: 'saveSync', value: function saveSync(hashInfo, codeOrBinaryData, mimeType, dependentFiles) { var buf = null; var target = _path2.default.join(this.getCachePath(), hashInfo.hash); d('Saving to ' + target); if (hashInfo.isFileBinary) { buf = _zlib2.default.gzipSync(codeOrBinaryData); _fs2.default.writeFileSync(target + '.info', (0, _stringify2.default)({ mimeType: mimeType, dependentFiles: dependentFiles }), 'utf8'); } else { buf = _zlib2.default.gzipSync(new Buffer((0, _stringify2.default)({ code: codeOrBinaryData, mimeType: mimeType, dependentFiles: dependentFiles }))); } _fs2.default.writeFileSync(target, buf); } }, { key: 'getOrFetchSync', value: function getOrFetchSync(filePath, fetcher) { var cacheResult = this.getSync(filePath); if (cacheResult.code || cacheResult.binaryData) return cacheResult; var result = fetcher(filePath, cacheResult.hashInfo) || { hashInfo: cacheResult.hashInfo }; if (result.mimeType && !cacheResult.hashInfo.isInNodeModules) { d('Cache miss: saving out info for ' + filePath); this.saveSync(cacheResult.hashInfo, result.code || result.binaryData, result.mimeType, result.dependentFiles); } result.hashInfo = cacheResult.hashInfo; return result; } /** * @private */ }, { key: 'getCachePath', value: function getCachePath() { // NB: This is an evil hack so that createFromCompiler can stomp it // at will return this.cachePath; } /** * Returns whether a file should not be compiled. Note that this doesn't * necessarily mean it won't end up in the cache, only that its contents are * saved verbatim instead of trying to find an appropriate compiler. * * @param {Object} hashInfo The hash information returned from getHashForPath * * @return {boolean} True if a file should be ignored */ }], [{ key: 'createFromCompiler', value: function createFromCompiler(cachePath, compiler, fileChangeCache) { var readOnlyMode = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3]; var newCachePath = null; var getCachePath = function getCachePath() { if (newCachePath) return newCachePath; var digestObj = { name: compiler.name || (0, _getPrototypeOf2.default)(compiler).constructor.name, version: compiler.getCompilerVersion(), options: compiler.compilerOptions }; newCachePath = _path2.default.join(cachePath, (0, _digestForObject2.default)(digestObj)); d('Path for ' + digestObj.name + ': ' + newCachePath); d('Set up with parameters: ' + (0, _stringify2.default)(digestObj)); if (!readOnlyMode) _mkdirp2.default.sync(newCachePath); return newCachePath; }; var ret = new CompileCache('', fileChangeCache); ret.getCachePath = getCachePath; return ret; } }, { key: 'shouldPassthrough', value: function shouldPassthrough(hashInfo) { return hashInfo.isMinified || hashInfo.isInNodeModules || hashInfo.hasSourceMap || hashInfo.isFileBinary; } }]); return CompileCache; }(); exports.default = CompileCache; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21waWxlLWNhY2hlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQU9BLElBQU0sSUFBSSxRQUFRLE9BQVIsRUFBaUIsZ0NBQWpCLENBQUo7Ozs7Ozs7Ozs7O0lBVWU7Ozs7Ozs7Ozs7QUFTbkIsV0FUbUIsWUFTbkIsQ0FBWSxTQUFaLEVBQXVCLGVBQXZCLEVBQXdDO3dDQVRyQixjQVNxQjs7QUFDdEMsU0FBSyxTQUFMLEdBQWlCLFNBQWpCLENBRHNDO0FBRXRDLFNBQUssZUFBTCxHQUF1QixlQUF2QixDQUZzQztHQUF4Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NkJBVG1COzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs0RkEwRVQ7WUFFSixVQUVBLE1BQ0EsVUFDQSxZQUNBLGdCQUVBLFdBR0UsUUFJRSxNQVVBLEtBQ0E7Ozs7O0FBMUJSLGdDQUFjLHdCQUFkOzt1QkFDcUIsS0FBSyxlQUFMLENBQXFCLGNBQXJCLENBQW9DLGVBQUssT0FBTCxDQUFhLFFBQWIsQ0FBcEM7OztBQUFqQjtBQUVBLHVCQUFPO0FBQ1AsMkJBQVc7QUFDWCw2QkFBYTtBQUNiLGlDQUFpQjtBQUVqQiw0QkFBWTs7O0FBRWQsNEJBQVksZUFBSyxJQUFMLENBQVUsS0FBSyxZQUFMLEVBQVYsRUFBK0IsU0FBUyxJQUFULENBQTNDO0FBQ0kseUJBQVM7O3FCQUVULFNBQVMsWUFBVDs7Ozs7QUFDRixrQkFBRSxrQ0FBRjs4QkFDVzs7dUJBQWlCLGFBQUksUUFBSixDQUFhLFlBQVksT0FBWjs7OztBQUFyQyxtQ0FBWTs7QUFDaEIsMkJBQVcsS0FBSyxRQUFMO0FBQ1gsaUNBQWlCLEtBQUssY0FBTDs7QUFFakIsNkJBQWEsU0FBUyxVQUFUOztvQkFDUjs7Ozs7O3VCQUNnQixhQUFJLFFBQUosQ0FBYSxTQUFiOzs7QUFBbkI7O3VCQUNtQixlQUFNLE1BQU4sQ0FBYSxVQUFiOzs7QUFB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LElBQUwsQ0FBVSxTQUFWLEVBQXFCLCtCQUFzQixTQUF0QixDQUFyQixDQUFmLENBVHVCOztBQVd2Qix3QkFBYyxVQUFVLElBQVYsVUFBbUIsWUFBakMsRUFYdUI7QUFZdkIsdUNBQTZCLHlCQUFlLFNBQWYsQ0FBN0IsRUFadUI7O0FBY3ZCLFlBQUksQ0FBQyxZQUFELEVBQWUsaUJBQU8sSUFBUCxDQUFZLFlBQVosRUFBbkI7QUFDQSxlQUFPLFlBQVAsQ0FmdUI7T0FBTixDQUYrRDs7QUFvQmxGLFVBQUksTUFBTSxJQUFJLFlBQUosQ0FBaUIsRUFBakIsRUFBcUIsZUFBckIsQ0FBTixDQXBCOEU7QUFxQmxGLFVBQUksWUFBSixHQUFtQixZQUFuQixDQXJCa0Y7O0FBdUJsRixhQUFPLEdBQVAsQ0F2QmtGOzs7O3NDQWdQM0QsVUFBVTtBQUNqQyxhQUFPLFNBQVMsVUFBVCxJQUF1QixTQUFTLGVBQVQsSUFBNEIsU0FBUyxZQUFULElBQXlCLFNBQVMsWUFBVCxDQURsRDs7O1NBalJoQiIsImZpbGUiOiJjb21waWxlLWNhY2hlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHpsaWIgZnJvbSAnemxpYic7XG5pbXBvcnQgY3JlYXRlRGlnZXN0Rm9yT2JqZWN0IGZyb20gJy4vZGlnZXN0LWZvci1vYmplY3QnO1xuaW1wb3J0IHtwZnMsIHB6bGlifSBmcm9tICcuL3Byb21pc2UnO1xuaW1wb3J0IG1rZGlycCBmcm9tICdta2RpcnAnO1xuXG5jb25zdCBkID0gcmVxdWlyZSgnZGVidWcnKSgnZWxlY3Ryb24tY29tcGlsZTpjb21waWxlLWNhY2hlJyk7XG5cbi8qKlxuICogQ29tcGlsZUNhY2hlIG1hbmFnZXMgZ2V0dGluZyBhbmQgc2V0dGluZyBlbnRyaWVzIGZvciBhIHNpbmdsZSBjb21waWxlcjsgZWFjaFxuICogaW4tdXNlIGNvbXBpbGVyIHdpbGwgaGF2ZSBhbiBpbnN0YW5jZSBvZiB0aGlzIGNsYXNzLCB1c3VhbGx5IGNyZWF0ZWQgdmlhXG4gKiB7QGxpbmsgY3JlYXRlRnJvbUNvbXBpbGVyfS4gXG4gKiBcbiAqIFlvdSB1c3VhbGx5IHdpbGwgbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LCBpdCBpcyBhbiBpbXBsZW1lbnRhdGlvbiBjbGFzcyBcbiAqIGZvciB7QGxpbmsgQ29tcGlsZUhvc3R9LlxuICovIFxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ29tcGlsZUNhY2hlIHtcbiAgLyoqICBcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSwgdXN1YWxseSB1c2VkIGZvciB0ZXN0aW5nIG9ubHkuXG4gICAqICAgIFxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IGNhY2hlUGF0aCAgVGhlIHJvb3QgZGlyZWN0b3J5IHRvIHVzZSBhcyBhIGNhY2hlIHBhdGhcbiAgICpcbiAgICogQHBhcmFtICB7RmlsZUNoYW5nZWRDYWNoZX0gZmlsZUNoYW5nZUNhY2hlICBBIGZpbGUtY2hhbmdlIGNhY2hlIHRoYXQgaXMgXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxseSBwcmUtbG9hZGVkLlxuICAgKi8gICBcbiAgY29uc3RydWN0b3IoY2FjaGVQYXRoLCBmaWxlQ2hhbmdlQ2FjaGUpIHtcbiAgICB0aGlzLmNhY2hlUGF0aCA9IGNhY2hlUGF0aDtcbiAgICB0aGlzLmZpbGVDaGFuZ2VDYWNoZSA9IGZpbGVDaGFuZ2VDYWNoZTtcbiAgfVxuICBcbiAgLyoqICBcbiAgICogQ3JlYXRlcyBhIENvbXBpbGVDYWNoZSBmcm9tIGEgY2xhc3MgY29tcGF0aWJsZSB3aXRoIHRoZSBDb21waWxlckJhc2UgXG4gICAqIGludGVyZmFjZS4gVGhpcyBtZXRob2QgdXNlcyB0aGUgY29tcGlsZXIgbmFtZSAvIHZlcnNpb24gLyBvcHRpb25zIHRvIFxuICAgKiBnZW5lcmF0ZSBhIHVuaXF1ZSBkaXJlY3RvcnkgbmFtZSBmb3IgY2FjaGVkIHJlc3VsdHNcbiAgICogICAgXG4gICAqIEBwYXJhbSAge3N0cmluZ30gY2FjaGVQYXRoICBUaGUgcm9vdCBwYXRoIHRvIHVzZSBmb3IgdGhlIGNhY2hlLCBhIGRpcmVjdG9yeVxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwcmVzZW50aW5nIHRoZSBoYXNoIG9mIHRoZSBjb21waWxlciBwYXJhbWV0ZXJzXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsIGJlIGNyZWF0ZWQgaGVyZS5cbiAgICpcbiAgICogQHBhcmFtICB7Q29tcGlsZXJCYXNlfSBjb21waWxlciAgVGhlIGNvbXBpbGVyIHRvIHVzZSBmb3IgdmVyc2lvbiAvIG9wdGlvblxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmZvcm1hdGlvbi5cbiAgICpcbiAgICogQHBhcmFtICB7RmlsZUNoYW5nZWRDYWNoZX0gZmlsZUNoYW5nZUNhY2hlICBBIGZpbGUtY2hhbmdlIGNhY2hlIHRoYXQgaXMgXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxseSBwcmUtbG9hZGVkLlxuICAgKlxuICAgKiBAcGFyYW0gIHtib29sZWFufSByZWFkT25seU1vZGUgIERvbid0IGF0dGVtcHQgdG8gY3JlYXRlIHRoZSBjYWNoZSBkaXJlY3RvcnkuXG4gICAqXG4gICAqIEByZXR1cm4ge0NvbXBpbGVDYWNoZX0gIEEgY29uZmlndXJlZCBDb21waWxlQ2FjaGUgaW5zdGFuY2UuXG4gICAqLyAgIFxuICBzdGF0aWMgY3JlYXRlRnJvbUNvbXBpbGVyKGNhY2hlUGF0aCwgY29tcGlsZXIsIGZpbGVDaGFuZ2VDYWNoZSwgcmVhZE9ubHlNb2RlPWZhbHNlKSB7XG4gICAgbGV0IG5ld0NhY2hlUGF0aCA9IG51bGw7XG4gICAgbGV0IGdldENhY2hlUGF0aCA9ICgpID0+IHtcbiAgICAgIGlmIChuZXdDYWNoZVBhdGgpIHJldHVybiBuZXdDYWNoZVBhdGg7XG5cbiAgICAgIGNvbnN0IGRpZ2VzdE9iaiA9IHtcbiAgICAgICAgbmFtZTogY29tcGlsZXIubmFtZSB8fCBPYmplY3QuZ2V0UHJvdG90eXBlT2YoY29tcGlsZXIpLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgICAgIHZlcnNpb246IGNvbXBpbGVyLmdldENvbXBpbGVyVmVyc2lvbigpLFxuICAgICAgICBvcHRpb25zOiBjb21waWxlci5jb21waWxlck9wdGlvbnNcbiAgICAgIH07XG5cbiAgICAgIG5ld0NhY2hlUGF0aCA9IHBhdGguam9pbihjYWNoZVBhdGgsIGNyZWF0ZURpZ2VzdEZvck9iamVjdChkaWdlc3RPYmopKTtcblxuICAgICAgZChgUGF0aCBmb3IgJHtkaWdlc3RPYmoubmFtZX06ICR7bmV3Q2FjaGVQYXRofWApO1xuICAgICAgZChgU2V0IHVwIHdpdGggcGFyYW1ldGVyczogJHtKU09OLnN0cmluZ2lmeShkaWdlc3RPYmopfWApO1xuICAgICAgXG4gICAgICBpZiAoIXJlYWRPbmx5TW9kZSkgbWtkaXJwLnN5bmMobmV3Q2FjaGVQYXRoKTtcbiAgICAgIHJldHVybiBuZXdDYWNoZVBhdGg7XG4gICAgfTtcbiAgICBcbiAgICBsZXQgcmV0ID0gbmV3IENvbXBpbGVDYWNoZSgnJywgZmlsZUNoYW5nZUNhY2hlKTtcbiAgICByZXQuZ2V0Q2FjaGVQYXRoID0gZ2V0Q2FjaGVQYXRoO1xuICAgIFxuICAgIHJldHVybiByZXQ7XG4gIH1cbiAgXG4gIC8qKiAgXG4gICAqIFJldHVybnMgYSBmaWxlJ3MgY29tcGlsZWQgY29udGVudHMgZnJvbSB0aGUgY2FjaGUuXG4gICAqICAgIFxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IGZpbGVQYXRoICBUaGUgcGF0aCB0byB0aGUgZmlsZS4gRmlsZUNoYW5nZWRDYWNoZSB3aWxsIGxvb2tcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXAgdGhlIGhhc2ggYW5kIHVzZSB0aGF0IGFzIHRoZSBrZXkgaW4gdGhlIGNhY2hlLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE9iamVjdD59ICBBbiBvYmplY3Qgd2l0aCBhbGwga2luZHMgb2YgaW5mb3JtYXRpb25cbiAgICpcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IGhhc2hJbmZvICBUaGUgaGFzaCBpbmZvcm1hdGlvbiByZXR1cm5lZCBmcm9tIGdldEhhc2hGb3JQYXRoXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBjb2RlICBUaGUgc291cmNlIGNvZGUgaWYgdGhlIGZpbGUgd2FzIGEgdGV4dCBmaWxlXG4gICAqIEBwcm9wZXJ0eSB7QnVmZmVyfSBiaW5hcnlEYXRhICBUaGUgZmlsZSBpZiBpdCB3YXMgYSBiaW5hcnkgZmlsZVxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gbWltZVR5cGUgIFRoZSBNSU1FIHR5cGUgc2F2ZWQgaW4gdGhlIGNhY2hlLlxuICAgKiBAcHJvcGVydHkge3N0cmluZ1tdfSBkZXBlbmRlbnRGaWxlcyAgVGhlIGRlcGVuZGVudCBmaWxlcyByZXR1cm5lZCBmcm9tIFxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGlsaW5nIHRoZSBmaWxlLCBpZiBhbnkuXG4gICAqLyAgIFxuICBhc3luYyBnZXQoZmlsZVBhdGgpIHtcbiAgICBkKGBGZXRjaGluZyAke2ZpbGVQYXRofSBmcm9tIGNhY2hlYCk7XG4gICAgbGV0IGhhc2hJbmZvID0gYXdhaXQgdGhpcy5maWxlQ2hhbmdlQ2FjaGUuZ2V0SGFzaEZvclBhdGgocGF0aC5yZXNvbHZlKGZpbGVQYXRoKSk7XG4gIFxuICAgIGxldCBjb2RlID0gbnVsbDtcbiAgICBsZXQgbWltZVR5cGUgPSBudWxsO1xuICAgIGxldCBiaW5hcnlEYXRhID0gbnVsbDtcbiAgICBsZXQgZGVwZW5kZW50RmlsZXMgPSBudWxsO1xuICAgIFxuICAgIGxldCBjYWNoZUZpbGUgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICBjYWNoZUZpbGUgPSBwYXRoLmpvaW4odGhpcy5nZXRDYWNoZVBhdGgoKSwgaGFzaEluZm8uaGFzaCk7XG4gICAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKGhhc2hJbmZvLmlzRmlsZUJpbmFyeSkge1xuICAgICAgICBkKFwiRmlsZSBpcyBiaW5hcnksIHJlYWRpbmcgb3V0IGluZm9cIik7XG4gICAgICAgIGxldCBpbmZvID0gSlNPTi5wYXJzZShhd2FpdCBwZnMucmVhZEZpbGUoY2FjaGVGaWxlICsgJy5pbmZvJykpO1xuICAgICAgICBtaW1lVHlwZSA9IGluZm8ubWltZVR5cGU7XG4gICAgICAgIGRlcGVuZGVudEZpbGVzID0gaW5mby5kZXBlbmRlbnRGaWxlcztcbiAgICAgICAgXG4gICAgICAgIGJpbmFyeURhdGEgPSBoYXNoSW5mby5iaW5hcnlEYXRhO1xuICAgICAgICBpZiAoIWJpbmFyeURhdGEpIHtcbiAgICAgICAgICBiaW5hcnlEYXRhID0gYXdhaXQgcGZzLnJlYWRGaWxlKGNhY2hlRmlsZSk7XG4gICAgICAgICAgYmluYXJ5RGF0YSA9IGF3YWl0IHB6bGliLmd1bnppcChiaW5hcnlEYXRhKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IGJ1ZiA9IGF3YWl0IHBmcy5yZWFkRmlsZShjYWNoZUZpbGUpO1xuICAgICAgICBsZXQgc3RyID0gKGF3YWl0IHB6bGliLmd1bnppcChidWYpKS50b1N0cmluZygndXRmOCcpO1xuXG4gICAgICAgIHJlc3VsdCA9IEpTT04ucGFyc2Uoc3RyKTtcbiAgICAgICAgY29kZSA9IHJlc3VsdC5jb2RlO1xuICAgICAgICBtaW1lVHlwZSA9IHJlc3VsdC5taW1lVHlwZTtcbiAgICAgICAgZGVwZW5kZW50RmlsZXMgPSByZXN1bHQuZGVwZW5kZW50RmlsZXM7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZChgRmFpbGVkIHRvIHJlYWQgY2FjaGUgZm9yICR7ZmlsZVBhdGh9LCBsb29rZWQgaW4gJHtjYWNoZUZpbGV9OiAke2UubWVzc2FnZX1gKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHsgaGFzaEluZm8sIGNvZGUsIG1pbWVUeXBlLCBiaW5hcnlEYXRhLCBkZXBlbmRlbnRGaWxlcyB9O1xuICB9XG5cbiAgXG4gIC8qKiAgXG4gICAqIFNhdmVzIGEgY29tcGlsZWQgcmVzdWx0IHRvIGNhY2hlXG4gICAqICAgIFxuICAgKiBAcGFyYW0gIHtPYmplY3R9IGhhc2hJbmZvICBUaGUgaGFzaCBpbmZvcm1hdGlvbiByZXR1cm5lZCBmcm9tIGdldEhhc2hGb3JQYXRoICAgXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZyAvIEJ1ZmZlcn0gY29kZU9yQmluYXJ5RGF0YSAgIFRoZSBmaWxlJ3MgY29udGVudHMsIGVpdGhlciBhc1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhIHN0cmluZyBvciBhIEJ1ZmZlci5cbiAgICogQHBhcmFtICB7c3RyaW5nfSBtaW1lVHlwZSAgVGhlIE1JTUUgdHlwZSByZXR1cm5lZCBieSB0aGUgY29tcGlsZXIuXG4gICAqXG4gICAqIEBwYXJhbSAge3N0cmluZ1tdfSBkZXBlbmRlbnRGaWxlcyAgVGhlIGxpc3Qgb2YgZGVwZW5kZW50IGZpbGVzIHJldHVybmVkIGJ5XG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGNvbXBpbGVyLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSAgQ29tcGxldGlvbi5cbiAgICovICAgXG4gIGFzeW5jIHNhdmUoaGFzaEluZm8sIGNvZGVPckJpbmFyeURhdGEsIG1pbWVUeXBlLCBkZXBlbmRlbnRGaWxlcykge1xuICAgIGxldCBidWYgPSBudWxsO1xuICAgIGxldCB0YXJnZXQgPSBwYXRoLmpvaW4odGhpcy5nZXRDYWNoZVBhdGgoKSwgaGFzaEluZm8uaGFzaCk7XG4gICAgZChgU2F2aW5nIHRvICR7dGFyZ2V0fWApO1xuICAgIFxuICAgIGlmIChoYXNoSW5mby5pc0ZpbGVCaW5hcnkpIHtcbiAgICAgIGJ1ZiA9IGF3YWl0IHB6bGliLmd6aXAoY29kZU9yQmluYXJ5RGF0YSk7XG4gICAgICBhd2FpdCBwZnMud3JpdGVGaWxlKHRhcmdldCArICcuaW5mbycsIEpTT04uc3RyaW5naWZ5KHttaW1lVHlwZSwgZGVwZW5kZW50RmlsZXN9KSwgJ3V0ZjgnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYnVmID0gYXdhaXQgcHpsaWIuZ3ppcChuZXcgQnVmZmVyKEpTT04uc3RyaW5naWZ5KHtjb2RlOiBjb2RlT3JCaW5hcnlEYXRhLCBtaW1lVHlwZSwgZGVwZW5kZW50RmlsZXN9KSkpO1xuICAgIH1cbiAgICBcbiAgICBhd2FpdCBwZnMud3JpdGVGaWxlKHRhcmdldCwgYnVmKTtcbiAgfVxuICBcbiAgLyoqICBcbiAgICogQXR0ZW1wdHMgdG8gZmlyc3QgZ2V0IGEga2V5IHZpYSB7QGxpbmsgZ2V0fSwgdGhlbiBpZiBpdCBmYWlscywgY2FsbCBhIG1ldGhvZFxuICAgKiB0byByZXRyaWV2ZSB0aGUgY29udGVudHMsIHRoZW4gc2F2ZSB0aGUgcmVzdWx0IHRvIGNhY2hlLlxuICAgKiBcbiAgICogVGhlIGZldGNoZXIgcGFyYW1ldGVyIGlzIGV4cGVjdGVkIHRvIGhhdmUgdGhlIHNpZ25hdHVyZTpcbiAgICogXG4gICAqIFByb21pc2U8T2JqZWN0PiBmZXRjaGVyKGZpbGVQYXRoIDogc3RyaW5nLCBoYXNoSW5mbyA6IE9iamVjdCk7XG4gICAqIFxuICAgKiBoYXNoSW5mbyBpcyBhIHZhbHVlIHJldHVybmVkIGZyb20gZ2V0SGFzaEZvclBhdGhcbiAgICogVGhlIHJldHVybiB2YWx1ZSBvZiBmZXRjaGVyIG11c3QgYmUgYW4gT2JqZWN0IHdpdGggdGhlIHByb3BlcnRpZXM6XG4gICAqIFxuICAgKiBtaW1lVHlwZSAtIHRoZSBNSU1FIHR5cGUgb2YgdGhlIGRhdGEgdG8gc2F2ZVxuICAgKiBjb2RlIChvcHRpb25hbCkgLSB0aGUgc291cmNlIGNvZGUgYXMgYSBzdHJpbmcsIGlmIGZpbGUgaXMgdGV4dFxuICAgKiBiaW5hcnlEYXRhIChvcHRpb25hbCkgLSB0aGUgZmlsZSBjb250ZW50cyBhcyBhIEJ1ZmZlciwgaWYgZmlsZSBpcyBiaW5hcnlcbiAgICogZGVwZW5kZW50RmlsZXMgLSB0aGUgZGVwZW5kZW50IGZpbGVzIHJldHVybmVkIGJ5IHRoZSBjb21waWxlci5cbiAgICpcbiAgICogQHBhcmFtICB7c3RyaW5nfSBmaWxlUGF0aCAgVGhlIHBhdGggdG8gdGhlIGZpbGUuIEZpbGVDaGFuZ2VkQ2FjaGUgd2lsbCBsb29rXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwIHRoZSBoYXNoIGFuZCB1c2UgdGhhdCBhcyB0aGUga2V5IGluIHRoZSBjYWNoZS5cbiAgICpcbiAgICogQHBhcmFtICB7RnVuY3Rpb259IGZldGNoZXIgIEEgbWV0aG9kIHdoaWNoIGNvbmZvcm1zIHRvIHRoZSBkZXNjcmlwdGlvbiBhYm92ZS5cbiAgICpcbiAgICogQHJldHVybiB7UHJvbWlzZTxPYmplY3Q+fSAgQW4gT2JqZWN0IHdoaWNoIGhhcyB0aGUgc2FtZSBmaWVsZHMgYXMgdGhlIFxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7QGxpbmsgZ2V0fSBtZXRob2QgcmV0dXJuIHJlc3VsdC5cbiAgICovICAgXG4gIGFzeW5jIGdldE9yRmV0Y2goZmlsZVBhdGgsIGZldGNoZXIpIHtcbiAgICBsZXQgY2FjaGVSZXN1bHQgPSBhd2FpdCB0aGlzLmdldChmaWxlUGF0aCk7XG4gICAgaWYgKGNhY2hlUmVzdWx0LmNvZGUgfHwgY2FjaGVSZXN1bHQuYmluYXJ5RGF0YSkgcmV0dXJuIGNhY2hlUmVzdWx0O1xuICAgIFxuICAgIGxldCByZXN1bHQgPSBhd2FpdCBmZXRjaGVyKGZpbGVQYXRoLCBjYWNoZVJlc3VsdC5oYXNoSW5mbykgfHwgeyBoYXNoSW5mbzogY2FjaGVSZXN1bHQuaGFzaEluZm8gfTtcbiAgICBcbiAgICBpZiAocmVzdWx0Lm1pbWVUeXBlICYmICFjYWNoZVJlc3VsdC5oYXNoSW5mby5pc0luTm9kZU1vZHVsZXMpIHtcbiAgICAgIGQoYENhY2hlIG1pc3M6IHNhdmluZyBvdXQgaW5mbyBmb3IgJHtmaWxlUGF0aH1gKTtcbiAgICAgIGF3YWl0IHRoaXMuc2F2ZShjYWNoZVJlc3VsdC5oYXNoSW5mbywgcmVzdWx0LmNvZGUgfHwgcmVzdWx0LmJpbmFyeURhdGEsIHJlc3VsdC5taW1lVHlwZSwgcmVzdWx0LmRlcGVuZGVudEZpbGVzKTtcbiAgICB9XG4gICAgXG4gICAgcmVzdWx0Lmhhc2hJbmZvID0gY2FjaGVSZXN1bHQuaGFzaEluZm87XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBcbiAgZ2V0U3luYyhmaWxlUGF0aCkge1xuICAgIGQoYEZldGNoaW5nICR7ZmlsZVBhdGh9IGZyb20gY2FjaGVgKTtcbiAgICBsZXQgaGFzaEluZm8gPSB0aGlzLmZpbGVDaGFuZ2VDYWNoZS5nZXRIYXNoRm9yUGF0aFN5bmMocGF0aC5yZXNvbHZlKGZpbGVQYXRoKSk7XG4gIFxuICAgIGxldCBjb2RlID0gbnVsbDtcbiAgICBsZXQgbWltZVR5cGUgPSBudWxsO1xuICAgIGxldCBiaW5hcnlEYXRhID0gbnVsbDtcbiAgICBsZXQgZGVwZW5kZW50RmlsZXMgPSBudWxsO1xuICAgIFxuICAgIHRyeSB7XG4gICAgICBsZXQgY2FjaGVGaWxlID0gcGF0aC5qb2luKHRoaXMuZ2V0Q2FjaGVQYXRoKCksIGhhc2hJbmZvLmhhc2gpO1xuICAgICAgXG4gICAgICBsZXQgcmVzdWx0ID0gbnVsbDtcbiAgICAgIGlmIChoYXNoSW5mby5pc0ZpbGVCaW5hcnkpIHtcbiAgICAgICAgZChcIkZpbGUgaXMgYmluYXJ5LCByZWFkaW5nIG91dCBpbmZvXCIpO1xuICAgICAgICBsZXQgaW5mbyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGNhY2hlRmlsZSArICcuaW5mbycpKTtcbiAgICAgICAgbWltZVR5cGUgPSBpbmZvLm1pbWVUeXBlO1xuICAgICAgICBkZXBlbmRlbnRGaWxlcyA9IGluZm8uZGVwZW5kZW50RmlsZXM7XG4gICAgICAgIFxuICAgICAgICBiaW5hcnlEYXRhID0gaGFzaEluZm8uYmluYXJ5RGF0YTtcbiAgICAgICAgaWYgKCFiaW5hcnlEYXRhKSB7XG4gICAgICAgICAgYmluYXJ5RGF0YSA9IGZzLnJlYWRGaWxlU3luYyhjYWNoZUZpbGUpO1xuICAgICAgICAgIGJpbmFyeURhdGEgPSB6bGliLmd1bnppcFN5bmMoYmluYXJ5RGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBidWYgPSBmcy5yZWFkRmlsZVN5bmMoY2FjaGVGaWxlKTtcbiAgICAgICAgbGV0IHN0ciA9ICh6bGliLmd1bnppcFN5bmMoYnVmKSkudG9TdHJpbmcoJ3V0ZjgnKTtcblxuICAgICAgICByZXN1bHQgPSBKU09OLnBhcnNlKHN0cik7XG4gICAgICAgIGNvZGUgPSByZXN1bHQuY29kZTtcbiAgICAgICAgbWltZVR5cGUgPSByZXN1bHQubWltZVR5cGU7XG4gICAgICAgIGRlcGVuZGVudEZpbGVzID0gcmVzdWx0LmRlcGVuZGVudEZpbGVzO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGQoYEZhaWxlZCB0byByZWFkIGNhY2hlIGZvciAke2ZpbGVQYXRofWApO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4geyBoYXNoSW5mbywgY29kZSwgbWltZVR5cGUsIGJpbmFyeURhdGEsIGRlcGVuZGVudEZpbGVzIH07XG4gIH1cblxuICBzYXZlU3luYyhoYXNoSW5mbywgY29kZU9yQmluYXJ5RGF0YSwgbWltZVR5cGUsIGRlcGVuZGVudEZpbGVzKSB7XG4gICAgbGV0IGJ1ZiA9IG51bGw7XG4gICAgbGV0IHRhcmdldCA9IHBhdGguam9pbih0aGlzLmdldENhY2hlUGF0aCgpLCBoYXNoSW5mby5oYXNoKTtcbiAgICBkKGBTYXZpbmcgdG8gJHt0YXJnZXR9YCk7XG4gICAgXG4gICAgaWYgKGhhc2hJbmZvLmlzRmlsZUJpbmFyeSkge1xuICAgICAgYnVmID0gemxpYi5nemlwU3luYyhjb2RlT3JCaW5hcnlEYXRhKTtcbiAgICAgIGZzLndyaXRlRmlsZVN5bmModGFyZ2V0ICsgJy5pbmZvJywgSlNPTi5zdHJpbmdpZnkoe21pbWVUeXBlLCBkZXBlbmRlbnRGaWxlc30pLCAndXRmOCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBidWYgPSB6bGliLmd6aXBTeW5jKG5ldyBCdWZmZXIoSlNPTi5zdHJpbmdpZnkoe2NvZGU6IGNvZGVPckJpbmFyeURhdGEsIG1pbWVUeXBlLCBkZXBlbmRlbnRGaWxlc30pKSk7XG4gICAgfVxuICAgIFxuICAgIGZzLndyaXRlRmlsZVN5bmModGFyZ2V0LCBidWYpO1xuICB9XG4gIFxuICBnZXRPckZldGNoU3luYyhmaWxlUGF0aCwgZmV0Y2hlcikge1xuICAgIGxldCBjYWNoZVJlc3VsdCA9IHRoaXMuZ2V0U3luYyhmaWxlUGF0aCk7XG4gICAgaWYgKGNhY2hlUmVzdWx0LmNvZGUgfHwgY2FjaGVSZXN1bHQuYmluYXJ5RGF0YSkgcmV0dXJuIGNhY2hlUmVzdWx0O1xuICAgIFxuICAgIGxldCByZXN1bHQgPSBmZXRjaGVyKGZpbGVQYXRoLCBjYWNoZVJlc3VsdC5oYXNoSW5mbykgfHwgeyBoYXNoSW5mbzogY2FjaGVSZXN1bHQuaGFzaEluZm8gfTtcbiAgICBcbiAgICBpZiAocmVzdWx0Lm1pbWVUeXBlICYmICFjYWNoZVJlc3VsdC5oYXNoSW5mby5pc0luTm9kZU1vZHVsZXMpIHtcbiAgICAgIGQoYENhY2hlIG1pc3M6IHNhdmluZyBvdXQgaW5mbyBmb3IgJHtmaWxlUGF0aH1gKTtcbiAgICAgIHRoaXMuc2F2ZVN5bmMoY2FjaGVSZXN1bHQuaGFzaEluZm8sIHJlc3VsdC5jb2RlIHx8IHJlc3VsdC5iaW5hcnlEYXRhLCByZXN1bHQubWltZVR5cGUsIHJlc3VsdC5kZXBlbmRlbnRGaWxlcyk7XG4gICAgfVxuICAgIFxuICAgIHJlc3VsdC5oYXNoSW5mbyA9IGNhY2hlUmVzdWx0Lmhhc2hJbmZvO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgXG4gIFxuICAvKiogIFxuICAgKiBAcHJpdmF0ZVxuICAgKi8gICBcbiAgZ2V0Q2FjaGVQYXRoKCkge1xuICAgIC8vIE5COiBUaGlzIGlzIGFuIGV2aWwgaGFjayBzbyB0aGF0IGNyZWF0ZUZyb21Db21waWxlciBjYW4gc3RvbXAgaXRcbiAgICAvLyBhdCB3aWxsXG4gICAgcmV0dXJuIHRoaXMuY2FjaGVQYXRoO1xuICB9XG4gICAgXG4gICAgXG4gIC8qKiAgICBcbiAgICogUmV0dXJucyB3aGV0aGVyIGEgZmlsZSBzaG91bGQgbm90IGJlIGNvbXBpbGVkLiBOb3RlIHRoYXQgdGhpcyBkb2Vzbid0IFxuICAgKiBuZWNlc3NhcmlseSBtZWFuIGl0IHdvbid0IGVuZCB1cCBpbiB0aGUgY2FjaGUsIG9ubHkgdGhhdCBpdHMgY29udGVudHMgYXJlXG4gICAqIHNhdmVkIHZlcmJhdGltIGluc3RlYWQgb2YgdHJ5aW5nIHRvIGZpbmQgYW4gYXBwcm9wcmlhdGUgY29tcGlsZXIuXG4gICAqICAgIFxuICAgKiBAcGFyYW0gIHtPYmplY3R9IGhhc2hJbmZvICBUaGUgaGFzaCBpbmZvcm1hdGlvbiByZXR1cm5lZCBmcm9tIGdldEhhc2hGb3JQYXRoICAgXG4gICAqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59ICBUcnVlIGlmIGEgZmlsZSBzaG91bGQgYmUgaWdub3JlZFxuICAgKi8gICBcbiAgc3RhdGljIHNob3VsZFBhc3N0aHJvdWdoKGhhc2hJbmZvKSB7XG4gICAgcmV0dXJuIGhhc2hJbmZvLmlzTWluaWZpZWQgfHwgaGFzaEluZm8uaXNJbk5vZGVNb2R1bGVzIHx8IGhhc2hJbmZvLmhhc1NvdXJjZU1hcCB8fCBoYXNoSW5mby5pc0ZpbGVCaW5hcnk7XG4gIH1cbn1cbiJdfQ==