UNPKG

@ngtools/webpack

Version:

Webpack plugin that AoT compiles your Angular components and modules.

308 lines • 43.8 kB
"use strict"; /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebpackResourceLoader = void 0; const node_assert_1 = __importDefault(require("node:assert")); const node_buffer_1 = require("node:buffer"); const path = __importStar(require("node:path")); const vm = __importStar(require("node:vm")); const diagnostics_1 = require("./ivy/diagnostics"); const paths_1 = require("./ivy/paths"); const inline_resource_1 = require("./loaders/inline-resource"); const replace_resources_1 = require("./transformers/replace_resources"); class WebpackResourceLoader { constructor(shouldCache) { this._fileDependencies = new Map(); this._reverseDependencies = new Map(); this.modifiedResources = new Set(); this.outputPathCounter = 1; this.inlineDataLoaderPath = inline_resource_1.InlineAngularResourceLoaderPath; if (shouldCache) { this.fileCache = new Map(); this.assetCache = new Map(); } } update(parentCompilation, changedFiles) { this._parentCompilation = parentCompilation; // Update resource cache and modified resources this.modifiedResources.clear(); if (changedFiles) { for (const changedFile of changedFiles) { const changedFileNormalized = (0, paths_1.normalizePath)(changedFile); this.assetCache?.delete(changedFileNormalized); for (const affectedResource of this.getAffectedResources(changedFile)) { const affectedResourceNormalized = (0, paths_1.normalizePath)(affectedResource); this.fileCache?.delete(affectedResourceNormalized); this.modifiedResources.add(affectedResource); for (const effectedDependencies of this.getResourceDependencies(affectedResourceNormalized)) { this.assetCache?.delete((0, paths_1.normalizePath)(effectedDependencies)); } } } } else { this.fileCache?.clear(); this.assetCache?.clear(); } // Re-emit all assets for un-effected files if (this.assetCache) { for (const [, { name, source, info }] of this.assetCache) { this._parentCompilation.emitAsset(name, source, info); } } } clearParentCompilation() { this._parentCompilation = undefined; } getModifiedResourceFiles() { return this.modifiedResources; } getResourceDependencies(filePath) { return this._fileDependencies.get(filePath) || []; } getAffectedResources(file) { return this._reverseDependencies.get(file) || []; } setAffectedResources(file, resources) { this._reverseDependencies.set(file, new Set(resources)); } // eslint-disable-next-line max-lines-per-function async _compile(filePath, data, fileExtension, resourceType, containingFile) { if (!this._parentCompilation) { throw new Error('WebpackResourceLoader cannot be used without parentCompilation'); } const { context, webpack } = this._parentCompilation.compiler; const { EntryPlugin, NormalModule, WebpackError, library, node, sources, util: { createHash }, } = webpack; const getEntry = () => { if (filePath) { return `${filePath}?${replace_resources_1.NG_COMPONENT_RESOURCE_QUERY}`; } else if (resourceType) { return ( // app.component.ts-2.css?ngResource!=!@ngtools/webpack/src/loaders/inline-resource.js!app.component.ts `${containingFile}-${this.outputPathCounter}.${fileExtension}` + `?${replace_resources_1.NG_COMPONENT_RESOURCE_QUERY}!=!${this.inlineDataLoaderPath}!${containingFile}`); } else if (data) { // Create a special URL for reading the resource from memory return `angular-resource:${resourceType},${createHash('xxhash64') .update(data) .digest('hex')}`; } throw new Error(`"filePath", "resourceType" or "data" must be specified.`); }; const entry = getEntry(); // Simple sanity check. if (filePath?.match(/\.[jt]s$/)) { throw new Error(`Cannot use a JavaScript or TypeScript file (${filePath}) in a component's styleUrls or templateUrl.`); } const outputFilePath = filePath || `${containingFile}-angular-inline--${this.outputPathCounter++}.${resourceType === 'template' ? 'html' : 'css'}`; const outputOptions = { filename: outputFilePath, library: { type: 'var', name: 'resource', }, }; const childCompiler = this._parentCompilation.createChildCompiler('angular-compiler:resource', outputOptions, [ new node.NodeTemplatePlugin(outputOptions), new node.NodeTargetPlugin(), new EntryPlugin(context, entry, { name: 'resource' }), new library.EnableLibraryPlugin('var'), ]); childCompiler.hooks.thisCompilation.tap('angular-compiler', (compilation, { normalModuleFactory }) => { // If no data is provided, the resource will be read from the filesystem if (data !== undefined) { normalModuleFactory.hooks.resolveForScheme .for('angular-resource') .tap('angular-compiler', (resourceData) => { if (filePath) { resourceData.path = filePath; resourceData.resource = filePath; } return true; }); NormalModule.getCompilationHooks(compilation) .readResourceForScheme.for('angular-resource') .tap('angular-compiler', () => data); compilation[inline_resource_1.InlineAngularResourceSymbol] = data; } compilation.hooks.additionalAssets.tap('angular-compiler', () => { const asset = compilation.assets[outputFilePath]; if (!asset) { return; } try { const output = this._evaluate(outputFilePath, asset.source().toString()); if (typeof output === 'string') { compilation.assets[outputFilePath] = new sources.RawSource(output); } } catch (error) { (0, node_assert_1.default)(error instanceof Error, 'catch clause variable is not an Error instance'); // Use compilation errors, as otherwise webpack will choke (0, diagnostics_1.addError)(compilation, error.message); } }); }); let finalContent; childCompiler.hooks.compilation.tap('angular-compiler', (childCompilation) => { childCompilation.hooks.processAssets.tap({ name: 'angular-compiler', stage: webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT }, () => { finalContent = childCompilation.assets[outputFilePath]?.source().toString(); for (const { files } of childCompilation.chunks) { for (const file of files) { childCompilation.deleteAsset(file); } } }); }); return new Promise((resolve, reject) => { childCompiler.runAsChild((error, _, childCompilation) => { if (error) { reject(error); return; } else if (!childCompilation) { reject(new Error('Unknown child compilation error')); return; } // Workaround to attempt to reduce memory usage of child compilations. // This removes the child compilation from the main compilation and manually propagates // all dependencies, warnings, and errors. const parent = childCompiler.parentCompilation; if (parent) { parent.children = parent.children.filter((child) => child !== childCompilation); let fileDependencies; for (const dependency of childCompilation.fileDependencies) { // Skip paths that do not appear to be files (have no extension). // `fileDependencies` can contain directories and not just files which can // cause incorrect cache invalidation on rebuilds. if (!path.extname(dependency)) { continue; } if (data && containingFile && dependency.endsWith(entry)) { // use containing file if the resource was inline parent.fileDependencies.add(containingFile); } else { parent.fileDependencies.add(dependency); } // Save the dependencies for this resource. if (filePath) { const resolvedFile = (0, paths_1.normalizePath)(dependency); const entry = this._reverseDependencies.get(resolvedFile); if (entry) { entry.add(filePath); } else { this._reverseDependencies.set(resolvedFile, new Set([filePath])); } if (fileDependencies) { fileDependencies.add(dependency); } else { fileDependencies = new Set([dependency]); this._fileDependencies.set(filePath, fileDependencies); } } } parent.contextDependencies.addAll(childCompilation.contextDependencies); parent.missingDependencies.addAll(childCompilation.missingDependencies); parent.buildDependencies.addAll(childCompilation.buildDependencies); parent.warnings.push(...childCompilation.warnings); parent.errors.push(...childCompilation.errors); if (this.assetCache) { for (const { info, name, source } of childCompilation.getAssets()) { // Use the originating file as the cache key if present // Otherwise, generate a cache key based on the generated name const cacheKey = info.sourceFilename ?? `!![GENERATED]:${name}`; this.assetCache.set(cacheKey, { info, name, source }); } } } resolve({ content: finalContent ?? '', success: childCompilation.errors?.length === 0, }); }); }); } _evaluate(filename, source) { // Evaluate code // css-loader requires the btoa function to exist to correctly generate inline sourcemaps const context = { btoa(input) { return node_buffer_1.Buffer.from(input).toString('base64'); }, }; try { vm.runInNewContext(source, context, { filename }); } catch { // Error are propagated through the child compilation. return null; } if (typeof context.resource === 'string') { return context.resource; } else if (typeof context.resource?.default === 'string') { return context.resource.default; } throw new Error(`The loader "${filename}" didn't return a string.`); } async get(filePath) { const normalizedFile = (0, paths_1.normalizePath)(filePath); let compilationResult = this.fileCache?.get(normalizedFile); if (compilationResult === undefined) { // cache miss so compile resource compilationResult = await this._compile(filePath); // Only cache if compilation was successful if (this.fileCache && compilationResult.success) { this.fileCache.set(normalizedFile, compilationResult); } } return compilationResult.content; } async process(data, fileExtension, resourceType, containingFile) { if (data.trim().length === 0) { return ''; } const compilationResult = await this._compile(undefined, data, fileExtension, resourceType, containingFile); return compilationResult.content; } } exports.WebpackResourceLoader = WebpackResourceLoader; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2VfbG9hZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvbmd0b29scy93ZWJwYWNrL3NyYy9yZXNvdXJjZV9sb2FkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSCw4REFBaUM7QUFDakMsNkNBQXFDO0FBQ3JDLGdEQUFrQztBQUNsQyw0Q0FBOEI7QUFFOUIsbURBQTZDO0FBQzdDLHVDQUE0QztBQUM1QywrREFJbUM7QUFDbkMsd0VBQStFO0FBUS9FLE1BQWEscUJBQXFCO0lBYWhDLFlBQVksV0FBb0I7UUFYeEIsc0JBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7UUFDbkQseUJBQW9CLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7UUFLdEQsc0JBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUN0QyxzQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFFYix5QkFBb0IsR0FBRyxpREFBK0IsQ0FBQztRQUd0RSxJQUFJLFdBQVcsRUFBRTtZQUNmLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7U0FDN0I7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLGlCQUE4QixFQUFFLFlBQStCO1FBQ3BFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQztRQUU1QywrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBRS9CLElBQUksWUFBWSxFQUFFO1lBQ2hCLEtBQUssTUFBTSxXQUFXLElBQUksWUFBWSxFQUFFO2dCQUN0QyxNQUFNLHFCQUFxQixHQUFHLElBQUEscUJBQWEsRUFBQyxXQUFXLENBQUMsQ0FBQztnQkFDekQsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztnQkFFL0MsS0FBSyxNQUFNLGdCQUFnQixJQUFJLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDckUsTUFBTSwwQkFBMEIsR0FBRyxJQUFBLHFCQUFhLEVBQUMsZ0JBQWdCLENBQUMsQ0FBQztvQkFDbkUsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsMEJBQTBCLENBQUMsQ0FBQztvQkFDbkQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO29CQUU3QyxLQUFLLE1BQU0sb0JBQW9CLElBQUksSUFBSSxDQUFDLHVCQUF1QixDQUM3RCwwQkFBMEIsQ0FDM0IsRUFBRTt3QkFDRCxJQUFJLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFBLHFCQUFhLEVBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO3FCQUM5RDtpQkFDRjthQUNGO1NBQ0Y7YUFBTTtZQUNMLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQztTQUMxQjtRQUVELDJDQUEyQztRQUMzQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsS0FBSyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN4RCxJQUFJLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDdkQ7U0FDRjtJQUNILENBQUM7SUFFRCxzQkFBc0I7UUFDcEIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLFNBQVMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsd0JBQXdCO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxRQUFnQjtRQUN0QyxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3BELENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxJQUFZO1FBQy9CLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDbkQsQ0FBQztJQUVELG9CQUFvQixDQUFDLElBQVksRUFBRSxTQUEyQjtRQUM1RCxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzFELENBQUM7SUFFRCxrREFBa0Q7SUFDMUMsS0FBSyxDQUFDLFFBQVEsQ0FDcEIsUUFBaUIsRUFDakIsSUFBYSxFQUNiLGFBQXNCLEVBQ3RCLFlBQW1DLEVBQ25DLGNBQXVCO1FBRXZCLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnRUFBZ0UsQ0FBQyxDQUFDO1NBQ25GO1FBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDO1FBQzlELE1BQU0sRUFDSixXQUFXLEVBQ1gsWUFBWSxFQUNaLFlBQVksRUFDWixPQUFPLEVBQ1AsSUFBSSxFQUNKLE9BQU8sRUFDUCxJQUFJLEVBQUUsRUFBRSxVQUFVLEVBQUUsR0FDckIsR0FBRyxPQUFPLENBQUM7UUFFWixNQUFNLFFBQVEsR0FBRyxHQUFXLEVBQUU7WUFDNUIsSUFBSSxRQUFRLEVBQUU7Z0JBQ1osT0FBTyxHQUFHLFFBQVEsSUFBSSwrQ0FBMkIsRUFBRSxDQUFDO2FBQ3JEO2lCQUFNLElBQUksWUFBWSxFQUFFO2dCQUN2QixPQUFPO2dCQUNMLHVHQUF1RztnQkFDdkcsR0FBRyxjQUFjLElBQUksSUFBSSxDQUFDLGlCQUFpQixJQUFJLGFBQWEsRUFBRTtvQkFDOUQsSUFBSSwrQ0FBMkIsTUFBTSxJQUFJLENBQUMsb0JBQW9CLElBQUksY0FBYyxFQUFFLENBQ25GLENBQUM7YUFDSDtpQkFBTSxJQUFJLElBQUksRUFBRTtnQkFDZiw0REFBNEQ7Z0JBQzVELE9BQU8sb0JBQW9CLFlBQVksSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDO3FCQUM5RCxNQUFNLENBQUMsSUFBSSxDQUFDO3FCQUNaLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2FBQ3BCO1lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO1FBQzdFLENBQUMsQ0FBQztRQUVGLE1BQU0sS0FBSyxHQUFHLFFBQVEsRUFBRSxDQUFDO1FBRXpCLHVCQUF1QjtRQUN2QixJQUFJLFFBQVEsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FDYiwrQ0FBK0MsUUFBUSw4Q0FBOEMsQ0FDdEcsQ0FBQztTQUNIO1FBRUQsTUFBTSxjQUFjLEdBQ2xCLFFBQVE7WUFDUixHQUFHLGNBQWMsb0JBQW9CLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxJQUMzRCxZQUFZLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQ3pDLEVBQUUsQ0FBQztRQUNMLE1BQU0sYUFBYSxHQUFHO1lBQ3BCLFFBQVEsRUFBRSxjQUFjO1lBQ3hCLE9BQU8sRUFBRTtnQkFDUCxJQUFJLEVBQUUsS0FBSztnQkFDWCxJQUFJLEVBQUUsVUFBVTthQUNqQjtTQUNGLENBQUM7UUFFRixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsbUJBQW1CLENBQy9ELDJCQUEyQixFQUMzQixhQUFhLEVBQ2I7WUFDRSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUM7WUFDMUMsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7WUFDM0IsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsQ0FBQztZQUNyRCxJQUFJLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUM7U0FDdkMsQ0FDRixDQUFDO1FBRUYsYUFBYSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUNyQyxrQkFBa0IsRUFDbEIsQ0FBQyxXQUFXLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUU7WUFDdkMsd0VBQXdFO1lBQ3hFLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRTtnQkFDdEIsbUJBQW1CLENBQUMsS0FBSyxDQUFDLGdCQUFnQjtxQkFDdkMsR0FBRyxDQUFDLGtCQUFrQixDQUFDO3FCQUN2QixHQUFHLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxZQUFZLEVBQUUsRUFBRTtvQkFDeEMsSUFBSSxRQUFRLEVBQUU7d0JBQ1osWUFBWSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUM7d0JBQzdCLFlBQVksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO3FCQUNsQztvQkFFRCxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDLENBQUMsQ0FBQztnQkFDTCxZQUFZLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDO3FCQUMxQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUM7cUJBQzdDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFdEMsV0FBb0QsQ0FBQyw2Q0FBMkIsQ0FBQyxHQUFHLElBQUksQ0FBQzthQUMzRjtZQUVELFdBQVcsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtnQkFDOUQsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDakQsSUFBSSxDQUFDLEtBQUssRUFBRTtvQkFDVixPQUFPO2lCQUNSO2dCQUVELElBQUk7b0JBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7b0JBRXpFLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFO3dCQUM5QixXQUFXLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztxQkFDcEU7aUJBQ0Y7Z0JBQUMsT0FBTyxLQUFLLEVBQUU7b0JBQ2QsSUFBQSxxQkFBTSxFQUFDLEtBQUssWUFBWSxLQUFLLEVBQUUsZ0RBQWdELENBQUMsQ0FBQztvQkFDakYsMERBQTBEO29CQUMxRCxJQUFBLHNCQUFRLEVBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztpQkFDdEM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FDRixDQUFDO1FBRUYsSUFBSSxZQUFnQyxDQUFDO1FBQ3JDLGFBQWEsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLGdCQUFnQixFQUFFLEVBQUU7WUFDM0UsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQ3RDLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsV0FBVyxDQUFDLDJCQUEyQixFQUFFLEVBQ3BGLEdBQUcsRUFBRTtnQkFDSCxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUU1RSxLQUFLLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUU7b0JBQy9DLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFO3dCQUN4QixnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7cUJBQ3BDO2lCQUNGO1lBQ0gsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBSSxPQUFPLENBQW9CLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3hELGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLEVBQUU7Z0JBQ3RELElBQUksS0FBSyxFQUFFO29CQUNULE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFZCxPQUFPO2lCQUNSO3FCQUFNLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtvQkFDNUIsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQztvQkFFckQsT0FBTztpQkFDUjtnQkFFRCxzRUFBc0U7Z0JBQ3RFLHVGQUF1RjtnQkFDdkYsMENBQTBDO2dCQUMxQyxNQUFNLE1BQU0sR0FBRyxhQUFhLENBQUMsaUJBQWlCLENBQUM7Z0JBQy9DLElBQUksTUFBTSxFQUFFO29CQUNWLE1BQU0sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssS0FBSyxnQkFBZ0IsQ0FBQyxDQUFDO29CQUNoRixJQUFJLGdCQUF5QyxDQUFDO29CQUU5QyxLQUFLLE1BQU0sVUFBVSxJQUFJLGdCQUFnQixDQUFDLGdCQUFnQixFQUFFO3dCQUMxRCxpRUFBaUU7d0JBQ2pFLDBFQUEwRTt3QkFDMUUsa0RBQWtEO3dCQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRTs0QkFDN0IsU0FBUzt5QkFDVjt3QkFFRCxJQUFJLElBQUksSUFBSSxjQUFjLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTs0QkFDeEQsaURBQWlEOzRCQUNqRCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO3lCQUM3Qzs2QkFBTTs0QkFDTCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO3lCQUN6Qzt3QkFFRCwyQ0FBMkM7d0JBQzNDLElBQUksUUFBUSxFQUFFOzRCQUNaLE1BQU0sWUFBWSxHQUFHLElBQUEscUJBQWEsRUFBQyxVQUFVLENBQUMsQ0FBQzs0QkFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQzs0QkFDMUQsSUFBSSxLQUFLLEVBQUU7Z0NBQ1QsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQzs2QkFDckI7aUNBQU07Z0NBQ0wsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7NkJBQ2xFOzRCQUVELElBQUksZ0JBQWdCLEVBQUU7Z0NBQ3BCLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQzs2QkFDbEM7aUNBQU07Z0NBQ0wsZ0JBQWdCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dDQUN6QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDOzZCQUN4RDt5QkFDRjtxQkFDRjtvQkFFRCxNQUFNLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixDQUFDLENBQUM7b0JBQ3hFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztvQkFDeEUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO29CQUVwRSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUNuRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUUvQyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7d0JBQ25CLEtBQUssTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksZ0JBQWdCLENBQUMsU0FBUyxFQUFFLEVBQUU7NEJBQ2pFLHVEQUF1RDs0QkFDdkQsOERBQThEOzRCQUM5RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsY0FBYyxJQUFJLGlCQUFpQixJQUFJLEVBQUUsQ0FBQzs0QkFFaEUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO3lCQUN2RDtxQkFDRjtpQkFDRjtnQkFFRCxPQUFPLENBQUM7b0JBQ04sT0FBTyxFQUFFLFlBQVksSUFBSSxFQUFFO29CQUMzQixPQUFPLEVBQUUsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLE1BQU0sS0FBSyxDQUFDO2lCQUMvQyxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLFNBQVMsQ0FBQyxRQUFnQixFQUFFLE1BQWM7UUFDaEQsZ0JBQWdCO1FBRWhCLHlGQUF5RjtRQUN6RixNQUFNLE9BQU8sR0FBa0Y7WUFDN0YsSUFBSSxDQUFDLEtBQUs7Z0JBQ1IsT0FBTyxvQkFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDL0MsQ0FBQztTQUNGLENBQUM7UUFFRixJQUFJO1lBQ0YsRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztTQUNuRDtRQUFDLE1BQU07WUFDTixzREFBc0Q7WUFDdEQsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUVELElBQUksT0FBTyxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsRUFBRTtZQUN4QyxPQUFPLE9BQU8sQ0FBQyxRQUFRLENBQUM7U0FDekI7YUFBTSxJQUFJLE9BQU8sT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLEtBQUssUUFBUSxFQUFFO1lBQ3hELE9BQU8sT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7U0FDakM7UUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGVBQWUsUUFBUSwyQkFBMkIsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQWdCO1FBQ3hCLE1BQU0sY0FBYyxHQUFHLElBQUEscUJBQWEsRUFBQyxRQUFRLENBQUMsQ0FBQztRQUMvQyxJQUFJLGlCQUFpQixHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRTVELElBQUksaUJBQWlCLEtBQUssU0FBUyxFQUFFO1lBQ25DLGlDQUFpQztZQUNqQyxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFbEQsMkNBQTJDO1lBQzNDLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxpQkFBaUIsQ0FBQyxPQUFPLEVBQUU7Z0JBQy9DLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2FBQ3ZEO1NBQ0Y7UUFFRCxPQUFPLGlCQUFpQixDQUFDLE9BQU8sQ0FBQztJQUNuQyxDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU8sQ0FDWCxJQUFZLEVBQ1osYUFBaUMsRUFDakMsWUFBa0MsRUFDbEMsY0FBdUI7UUFFdkIsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUM1QixPQUFPLEVBQUUsQ0FBQztTQUNYO1FBRUQsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQzNDLFNBQVMsRUFDVCxJQUFJLEVBQ0osYUFBYSxFQUNiLFlBQVksRUFDWixjQUFjLENBQ2YsQ0FBQztRQUVGLE9BQU8saUJBQWlCLENBQUMsT0FBTyxDQUFDO0lBQ25DLENBQUM7Q0FDRjtBQWpXRCxzREFpV0MiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IGFzc2VydCBmcm9tICdub2RlOmFzc2VydCc7XG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tICdub2RlOmJ1ZmZlcic7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgKiBhcyB2bSBmcm9tICdub2RlOnZtJztcbmltcG9ydCB0eXBlIHsgQXNzZXQsIENvbXBpbGF0aW9uIH0gZnJvbSAnd2VicGFjayc7XG5pbXBvcnQgeyBhZGRFcnJvciB9IGZyb20gJy4vaXZ5L2RpYWdub3N0aWNzJztcbmltcG9ydCB7IG5vcm1hbGl6ZVBhdGggfSBmcm9tICcuL2l2eS9wYXRocyc7XG5pbXBvcnQge1xuICBDb21waWxhdGlvbldpdGhJbmxpbmVBbmd1bGFyUmVzb3VyY2UsXG4gIElubGluZUFuZ3VsYXJSZXNvdXJjZUxvYWRlclBhdGgsXG4gIElubGluZUFuZ3VsYXJSZXNvdXJjZVN5bWJvbCxcbn0gZnJvbSAnLi9sb2FkZXJzL2lubGluZS1yZXNvdXJjZSc7XG5pbXBvcnQgeyBOR19DT01QT05FTlRfUkVTT1VSQ0VfUVVFUlkgfSBmcm9tICcuL3RyYW5zZm9ybWVycy9yZXBsYWNlX3Jlc291cmNlcyc7XG5cbmludGVyZmFjZSBDb21waWxhdGlvbk91dHB1dCB7XG4gIGNvbnRlbnQ6IHN0cmluZztcbiAgbWFwPzogc3RyaW5nO1xuICBzdWNjZXNzOiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgV2VicGFja1Jlc291cmNlTG9hZGVyIHtcbiAgcHJpdmF0ZSBfcGFyZW50Q29tcGlsYXRpb24/OiBDb21waWxhdGlvbjtcbiAgcHJpdmF0ZSBfZmlsZURlcGVuZGVuY2llcyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4oKTtcbiAgcHJpdmF0ZSBfcmV2ZXJzZURlcGVuZGVuY2llcyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4oKTtcblxuICBwcml2YXRlIGZpbGVDYWNoZT86IE1hcDxzdHJpbmcsIENvbXBpbGF0aW9uT3V0cHV0PjtcbiAgcHJpdmF0ZSBhc3NldENhY2hlPzogTWFwPHN0cmluZywgQXNzZXQ+O1xuXG4gIHByaXZhdGUgbW9kaWZpZWRSZXNvdXJjZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSBvdXRwdXRQYXRoQ291bnRlciA9IDE7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBpbmxpbmVEYXRhTG9hZGVyUGF0aCA9IElubGluZUFuZ3VsYXJSZXNvdXJjZUxvYWRlclBhdGg7XG5cbiAgY29uc3RydWN0b3Ioc2hvdWxkQ2FjaGU6IGJvb2xlYW4pIHtcbiAgICBpZiAoc2hvdWxkQ2FjaGUpIHtcbiAgICAgIHRoaXMuZmlsZUNhY2hlID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy5hc3NldENhY2hlID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZShwYXJlbnRDb21waWxhdGlvbjogQ29tcGlsYXRpb24sIGNoYW5nZWRGaWxlcz86IEl0ZXJhYmxlPHN0cmluZz4pIHtcbiAgICB0aGlzLl9wYXJlbnRDb21waWxhdGlvbiA9IHBhcmVudENvbXBpbGF0aW9uO1xuXG4gICAgLy8gVXBkYXRlIHJlc291cmNlIGNhY2hlIGFuZCBtb2RpZmllZCByZXNvdXJjZXNcbiAgICB0aGlzLm1vZGlmaWVkUmVzb3VyY2VzLmNsZWFyKCk7XG5cbiAgICBpZiAoY2hhbmdlZEZpbGVzKSB7XG4gICAgICBmb3IgKGNvbnN0IGNoYW5nZWRGaWxlIG9mIGNoYW5nZWRGaWxlcykge1xuICAgICAgICBjb25zdCBjaGFuZ2VkRmlsZU5vcm1hbGl6ZWQgPSBub3JtYWxpemVQYXRoKGNoYW5nZWRGaWxlKTtcbiAgICAgICAgdGhpcy5hc3NldENhY2hlPy5kZWxldGUoY2hhbmdlZEZpbGVOb3JtYWxpemVkKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGFmZmVjdGVkUmVzb3VyY2Ugb2YgdGhpcy5nZXRBZmZlY3RlZFJlc291cmNlcyhjaGFuZ2VkRmlsZSkpIHtcbiAgICAgICAgICBjb25zdCBhZmZlY3RlZFJlc291cmNlTm9ybWFsaXplZCA9IG5vcm1hbGl6ZVBhdGgoYWZmZWN0ZWRSZXNvdXJjZSk7XG4gICAgICAgICAgdGhpcy5maWxlQ2FjaGU/LmRlbGV0ZShhZmZlY3RlZFJlc291cmNlTm9ybWFsaXplZCk7XG4gICAgICAgICAgdGhpcy5tb2RpZmllZFJlc291cmNlcy5hZGQoYWZmZWN0ZWRSZXNvdXJjZSk7XG5cbiAgICAgICAgICBmb3IgKGNvbnN0IGVmZmVjdGVkRGVwZW5kZW5jaWVzIG9mIHRoaXMuZ2V0UmVzb3VyY2VEZXBlbmRlbmNpZXMoXG4gICAgICAgICAgICBhZmZlY3RlZFJlc291cmNlTm9ybWFsaXplZCxcbiAgICAgICAgICApKSB7XG4gICAgICAgICAgICB0aGlzLmFzc2V0Q2FjaGU/LmRlbGV0ZShub3JtYWxpemVQYXRoKGVmZmVjdGVkRGVwZW5kZW5jaWVzKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmlsZUNhY2hlPy5jbGVhcigpO1xuICAgICAgdGhpcy5hc3NldENhY2hlPy5jbGVhcigpO1xuICAgIH1cblxuICAgIC8vIFJlLWVtaXQgYWxsIGFzc2V0cyBmb3IgdW4tZWZmZWN0ZWQgZmlsZXNcbiAgICBpZiAodGhpcy5hc3NldENhY2hlKSB7XG4gICAgICBmb3IgKGNvbnN0IFssIHsgbmFtZSwgc291cmNlLCBpbmZvIH1dIG9mIHRoaXMuYXNzZXRDYWNoZSkge1xuICAgICAgICB0aGlzLl9wYXJlbnRDb21waWxhdGlvbi5lbWl0QXNzZXQobmFtZSwgc291cmNlLCBpbmZvKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjbGVhclBhcmVudENvbXBpbGF0aW9uKCkge1xuICAgIHRoaXMuX3BhcmVudENvbXBpbGF0aW9uID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgZ2V0TW9kaWZpZWRSZXNvdXJjZUZpbGVzKCkge1xuICAgIHJldHVybiB0aGlzLm1vZGlmaWVkUmVzb3VyY2VzO1xuICB9XG5cbiAgZ2V0UmVzb3VyY2VEZXBlbmRlbmNpZXMoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLl9maWxlRGVwZW5kZW5jaWVzLmdldChmaWxlUGF0aCkgfHwgW107XG4gIH1cblxuICBnZXRBZmZlY3RlZFJlc291cmNlcyhmaWxlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5fcmV2ZXJzZURlcGVuZGVuY2llcy5nZXQoZmlsZSkgfHwgW107XG4gIH1cblxuICBzZXRBZmZlY3RlZFJlc291cmNlcyhmaWxlOiBzdHJpbmcsIHJlc291cmNlczogSXRlcmFibGU8c3RyaW5nPikge1xuICAgIHRoaXMuX3JldmVyc2VEZXBlbmRlbmNpZXMuc2V0KGZpbGUsIG5ldyBTZXQocmVzb3VyY2VzKSk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxpbmVzLXBlci1mdW5jdGlvblxuICBwcml2YXRlIGFzeW5jIF9jb21waWxlKFxuICAgIGZpbGVQYXRoPzogc3RyaW5nLFxuICAgIGRhdGE/OiBzdHJpbmcsXG4gICAgZmlsZUV4dGVuc2lvbj86IHN0cmluZyxcbiAgICByZXNvdXJjZVR5cGU/OiAnc3R5bGUnIHwgJ3RlbXBsYXRlJyxcbiAgICBjb250YWluaW5nRmlsZT86IHN0cmluZyxcbiAgKTogUHJvbWlzZTxDb21waWxhdGlvbk91dHB1dD4ge1xuICAgIGlmICghdGhpcy5fcGFyZW50Q29tcGlsYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignV2VicGFja1Jlc291cmNlTG9hZGVyIGNhbm5vdCBiZSB1c2VkIHdpdGhvdXQgcGFyZW50Q29tcGlsYXRpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGNvbnRleHQsIHdlYnBhY2sgfSA9IHRoaXMuX3BhcmVudENvbXBpbGF0aW9uLmNvbXBpbGVyO1xuICAgIGNvbnN0IHtcbiAgICAgIEVudHJ5UGx1Z2luLFxuICAgICAgTm9ybWFsTW9kdWxlLFxuICAgICAgV2VicGFja0Vycm9yLFxuICAgICAgbGlicmFyeSxcbiAgICAgIG5vZGUsXG4gICAgICBzb3VyY2VzLFxuICAgICAgdXRpbDogeyBjcmVhdGVIYXNoIH0sXG4gICAgfSA9IHdlYnBhY2s7XG5cbiAgICBjb25zdCBnZXRFbnRyeSA9ICgpOiBzdHJpbmcgPT4ge1xuICAgICAgaWYgKGZpbGVQYXRoKSB7XG4gICAgICAgIHJldHVybiBgJHtmaWxlUGF0aH0/JHtOR19DT01QT05FTlRfUkVTT1VSQ0VfUVVFUll9YDtcbiAgICAgIH0gZWxzZSBpZiAocmVzb3VyY2VUeXBlKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgLy8gYXBwLmNvbXBvbmVudC50cy0yLmNzcz9uZ1Jlc291cmNlIT0hQG5ndG9vbHMvd2VicGFjay9zcmMvbG9hZGVycy9pbmxpbmUtcmVzb3VyY2UuanMhYXBwLmNvbXBvbmVudC50c1xuICAgICAgICAgIGAke2NvbnRhaW5pbmdGaWxlfS0ke3RoaXMub3V0cHV0UGF0aENvdW50ZXJ9LiR7ZmlsZUV4dGVuc2lvbn1gICtcbiAgICAgICAgICBgPyR7TkdfQ09NUE9ORU5UX1JFU09VUkNFX1FVRVJZfSE9ISR7dGhpcy5pbmxpbmVEYXRhTG9hZGVyUGF0aH0hJHtjb250YWluaW5nRmlsZX1gXG4gICAgICAgICk7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgc3BlY2lhbCBVUkwgZm9yIHJlYWRpbmcgdGhlIHJlc291cmNlIGZyb20gbWVtb3J5XG4gICAgICAgIHJldHVybiBgYW5ndWxhci1yZXNvdXJjZToke3Jlc291cmNlVHlwZX0sJHtjcmVhdGVIYXNoKCd4eGhhc2g2NCcpXG4gICAgICAgICAgLnVwZGF0ZShkYXRhKVxuICAgICAgICAgIC5kaWdlc3QoJ2hleCcpfWA7XG4gICAgICB9XG5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgXCJmaWxlUGF0aFwiLCBcInJlc291cmNlVHlwZVwiIG9yIFwiZGF0YVwiIG11c3QgYmUgc3BlY2lmaWVkLmApO1xuICAgIH07XG5cbiAgICBjb25zdCBlbnRyeSA9IGdldEVudHJ5KCk7XG5cbiAgICAvLyBTaW1wbGUgc2FuaXR5IGNoZWNrLlxuICAgIGlmIChmaWxlUGF0aD8ubWF0Y2goL1xcLltqdF1zJC8pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgdXNlIGEgSmF2YVNjcmlwdCBvciBUeXBlU2NyaXB0IGZpbGUgKCR7ZmlsZVBhdGh9KSBpbiBhIGNvbXBvbmVudCdzIHN0eWxlVXJscyBvciB0ZW1wbGF0ZVVybC5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXRGaWxlUGF0aCA9XG4gICAgICBmaWxlUGF0aCB8fFxuICAgICAgYCR7Y29udGFpbmluZ0ZpbGV9LWFuZ3VsYXItaW5saW5lLS0ke3RoaXMub3V0cHV0UGF0aENvdW50ZXIrK30uJHtcbiAgICAgICAgcmVzb3VyY2VUeXBlID09PSAndGVtcGxhdGUnID8gJ2h0bWwnIDogJ2NzcydcbiAgICAgIH1gO1xuICAgIGNvbnN0IG91dHB1dE9wdGlvbnMgPSB7XG4gICAgICBmaWxlbmFtZTogb3V0cHV0RmlsZVBhdGgsXG4gICAgICBsaWJyYXJ5OiB7XG4gICAgICAgIHR5cGU6ICd2YXInLFxuICAgICAgICBuYW1lOiAncmVzb3VyY2UnLFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgY29uc3QgY2hpbGRDb21waWxlciA9IHRoaXMuX3BhcmVudENvbXBpbGF0aW9uLmNyZWF0ZUNoaWxkQ29tcGlsZXIoXG4gICAgICAnYW5ndWxhci1jb21waWxlcjpyZXNvdXJjZScsXG4gICAgICBvdXRwdXRPcHRpb25zLFxuICAgICAgW1xuICAgICAgICBuZXcgbm9kZS5Ob2RlVGVtcGxhdGVQbHVnaW4ob3V0cHV0T3B0aW9ucyksXG4gICAgICAgIG5ldyBub2RlLk5vZGVUYXJnZXRQbHVnaW4oKSxcbiAgICAgICAgbmV3IEVudHJ5UGx1Z2luKGNvbnRleHQsIGVudHJ5LCB7IG5hbWU6ICdyZXNvdXJjZScgfSksXG4gICAgICAgIG5ldyBsaWJyYXJ5LkVuYWJsZUxpYnJhcnlQbHVnaW4oJ3ZhcicpLFxuICAgICAgXSxcbiAgICApO1xuXG4gICAgY2hpbGRDb21waWxlci5ob29rcy50aGlzQ29tcGlsYXRpb24udGFwKFxuICAgICAgJ2FuZ3VsYXItY29tcGlsZXInLFxuICAgICAgKGNvbXBpbGF0aW9uLCB7IG5vcm1hbE1vZHVsZUZhY3RvcnkgfSkgPT4ge1xuICAgICAgICAvLyBJZiBubyBkYXRhIGlzIHByb3ZpZGVkLCB0aGUgcmVzb3VyY2Ugd2lsbCBiZSByZWFkIGZyb20gdGhlIGZpbGVzeXN0ZW1cbiAgICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG5vcm1hbE1vZHVsZUZhY3RvcnkuaG9va3MucmVzb2x2ZUZvclNjaGVtZVxuICAgICAgICAgICAgLmZvcignYW5ndWxhci1yZXNvdXJjZScpXG4gICAgICAgICAgICAudGFwKCdhbmd1bGFyLWNvbXBpbGVyJywgKHJlc291cmNlRGF0YSkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZmlsZVBhdGgpIHtcbiAgICAgICAgICAgICAgICByZXNvdXJjZURhdGEucGF0aCA9IGZpbGVQYXRoO1xuICAgICAgICAgICAgICAgIHJlc291cmNlRGF0YS5yZXNvdXJjZSA9IGZpbGVQYXRoO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICBOb3JtYWxNb2R1bGUuZ2V0Q29tcGlsYXRpb25Ib29rcyhjb21waWxhdGlvbilcbiAgICAgICAgICAgIC5yZWFkUmVzb3VyY2VGb3JTY2hlbWUuZm9yKCdhbmd1bGFyLXJlc291cmNlJylcbiAgICAgICAgICAgIC50YXAoJ2FuZ3VsYXItY29tcGlsZXInLCAoKSA9PiBkYXRhKTtcblxuICAgICAgICAgIChjb21waWxhdGlvbiBhcyBDb21waWxhdGlvbldpdGhJbmxpbmVBbmd1bGFyUmVzb3VyY2UpW0lubGluZUFuZ3VsYXJSZXNvdXJjZVN5bWJvbF0gPSBkYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgY29tcGlsYXRpb24uaG9va3MuYWRkaXRpb25hbEFzc2V0cy50YXAoJ2FuZ3VsYXItY29tcGlsZXInLCAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgYXNzZXQgPSBjb21waWxhdGlvbi5hc3NldHNbb3V0cHV0RmlsZVBhdGhdO1xuICAgICAgICAgIGlmICghYXNzZXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5fZXZhbHVhdGUob3V0cHV0RmlsZVBhdGgsIGFzc2V0LnNvdXJjZSgpLnRvU3RyaW5nKCkpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG91dHB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgY29tcGlsYXRpb24uYXNzZXRzW291dHB1dEZpbGVQYXRoXSA9IG5ldyBzb3VyY2VzLlJhd1NvdXJjZShvdXRwdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBhc3NlcnQoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciwgJ2NhdGNoIGNsYXVzZSB2YXJpYWJsZSBpcyBub3QgYW4gRXJyb3IgaW5zdGFuY2UnKTtcbiAgICAgICAgICAgIC8vIFVzZSBjb21waWxhdGlvbiBlcnJvcnMsIGFzIG90aGVyd2lzZSB3ZWJwYWNrIHdpbGwgY2hva2VcbiAgICAgICAgICAgIGFkZEVycm9yKGNvbXBpbGF0aW9uLCBlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICApO1xuXG4gICAgbGV0IGZpbmFsQ29udGVudDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGNoaWxkQ29tcGlsZXIuaG9va3MuY29tcGlsYXRpb24udGFwKCdhbmd1bGFyLWNvbXBpbGVyJywgKGNoaWxkQ29tcGlsYXRpb24pID0+IHtcbiAgICAgIGNoaWxkQ29tcGlsYXRpb24uaG9va3MucHJvY2Vzc0Fzc2V0cy50YXAoXG4gICAgICAgIHsgbmFtZTogJ2FuZ3VsYXItY29tcGlsZXInLCBzdGFnZTogd2VicGFjay5Db21waWxhdGlvbi5QUk9DRVNTX0FTU0VUU19TVEFHRV9SRVBPUlQgfSxcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIGZpbmFsQ29udGVudCA9IGNoaWxkQ29tcGlsYXRpb24uYXNzZXRzW291dHB1dEZpbGVQYXRoXT8uc291cmNlKCkudG9TdHJpbmcoKTtcblxuICAgICAgICAgIGZvciAoY29uc3QgeyBmaWxlcyB9IG9mIGNoaWxkQ29tcGlsYXRpb24uY2h1bmtzKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgICAgICAgICAgY2hpbGRDb21waWxhdGlvbi5kZWxldGVBc3NldChmaWxlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPENvbXBpbGF0aW9uT3V0cHV0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjaGlsZENvbXBpbGVyLnJ1bkFzQ2hpbGQoKGVycm9yLCBfLCBjaGlsZENvbXBpbGF0aW9uKSA9PiB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoIWNoaWxkQ29tcGlsYXRpb24pIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdVbmtub3duIGNoaWxkIGNvbXBpbGF0aW9uIGVycm9yJykpO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV29ya2Fyb3VuZCB0byBhdHRlbXB0IHRvIHJlZHVjZSBtZW1vcnkgdXNhZ2Ugb2YgY2hpbGQgY29tcGlsYXRpb25zLlxuICAgICAgICAvLyBUaGlzIHJlbW92ZXMgdGhlIGNoaWxkIGNvbXBpbGF0aW9uIGZyb20gdGhlIG1haW4gY29tcGlsYXRpb24gYW5kIG1hbnVhbGx5IHByb3BhZ2F0ZXNcbiAgICAgICAgLy8gYWxsIGRlcGVuZGVuY2llcywgd2FybmluZ3MsIGFuZCBlcnJvcnMuXG4gICAgICAgIGNvbnN0IHBhcmVudCA9IGNoaWxkQ29tcGlsZXIucGFyZW50Q29tcGlsYXRpb247XG4gICAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgICBwYXJlbnQuY2hpbGRyZW4gPSBwYXJlbnQuY2hpbGRyZW4uZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQgIT09IGNoaWxkQ29tcGlsYXRpb24pO1xuICAgICAgICAgIGxldCBmaWxlRGVwZW5kZW5jaWVzOiBTZXQ8c3RyaW5nPiB8IHVuZGVmaW5lZDtcblxuICAgICAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBjaGlsZENvbXBpbGF0aW9uLmZpbGVEZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgIC8vIFNraXAgcGF0aHMgdGhhdCBkbyBub3QgYXBwZWFyIHRvIGJlIGZpbGVzIChoYXZlIG5vIGV4dGVuc2lvbikuXG4gICAgICAgICAgICAvLyBgZmlsZURlcGVuZGVuY2llc2AgY2FuIGNvbnRhaW4gZGlyZWN0b3JpZXMgYW5kIG5vdCBqdXN0IGZpbGVzIHdoaWNoIGNhblxuICAgICAgICAgICAgLy8gY2F1c2UgaW5jb3JyZWN0IGNhY2hlIGludmFsaWRhdGlvbiBvbiByZWJ1aWxkcy5cbiAgICAgICAgICAgIGlmICghcGF0aC5leHRuYW1lKGRlcGVuZGVuY3kpKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZGF0YSAmJiBjb250YWluaW5nRmlsZSAmJiBkZXBlbmRlbmN5LmVuZHNXaXRoKGVudHJ5KSkge1xuICAgICAgICAgICAgICAvLyB1c2UgY29udGFpbmluZyBmaWxlIGlmIHRoZSByZXNvdXJjZSB3YXMgaW5saW5lXG4gICAgICAgICAgICAgIHBhcmVudC5maWxlRGVwZW5kZW5jaWVzLmFkZChjb250YWluaW5nRmlsZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwYXJlbnQuZmlsZURlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIGRlcGVuZGVuY2llcyBmb3IgdGhpcyByZXNvdXJjZS5cbiAgICAgICAgICAgIGlmIChmaWxlUGF0aCkge1xuICAgICAgICAgICAgICBjb25zdCByZXNvbHZlZEZpbGUgPSBub3JtYWxpemVQYXRoKGRlcGVuZGVuY3kpO1xuICAgICAgICAgICAgICBjb25zdCBlbnRyeSA9IHRoaXMuX3JldmVyc2VEZXBlbmRlbmNpZXMuZ2V0KHJlc29sdmVkRmlsZSk7XG4gICAgICAgICAgICAgIGlmIChlbnRyeSkge1xuICAgICAgICAgICAgICAgIGVudHJ5LmFkZChmaWxlUGF0aCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmV2ZXJzZURlcGVuZGVuY2llcy5zZXQocmVzb2x2ZWRGaWxlLCBuZXcgU2V0KFtmaWxlUGF0aF0pKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChmaWxlRGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICAgICAgZmlsZURlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmlsZURlcGVuZGVuY2llcyA9IG5ldyBTZXQoW2RlcGVuZGVuY3ldKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9maWxlRGVwZW5kZW5jaWVzLnNldChmaWxlUGF0aCwgZmlsZURlcGVuZGVuY2llcyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwYXJlbnQuY29udGV4dERlcGVuZGVuY2llcy5hZGRBbGwoY2hpbGRDb21waWxhdGlvbi5jb250ZXh0RGVwZW5kZW5jaWVzKTtcbiAgICAgICAgICBwYXJlbnQubWlzc2luZ0RlcGVuZGVuY2llcy5hZGRBbGwoY2hpbGRDb21waWxhdGlvbi5taXNzaW5nRGVwZW5kZW5jaWVzKTtcbiAgICAgICAgICBwYXJlbnQuYnVpbGREZXBlbmRlbmNpZXMuYWRkQWxsKGNoaWxkQ29tcGlsYXRpb24uYnVpbGREZXBlbmRlbmNpZXMpO1xuXG4gICAgICAgICAgcGFyZW50Lndhcm5pbmdzLnB1c2goLi4uY2hpbGRDb21waWxhdGlvbi53YXJuaW5ncyk7XG4gICAgICAgICAgcGFyZW50LmVycm9ycy5wdXNoKC4uLmNoaWxkQ29tcGlsYXRpb24uZXJyb3JzKTtcblxuICAgICAgICAgIGlmICh0aGlzLmFzc2V0Q2FjaGUpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgeyBpbmZvLCBuYW1lLCBzb3VyY2UgfSBvZiBjaGlsZENvbXBpbGF0aW9uLmdldEFzc2V0cygpKSB7XG4gICAgICAgICAgICAgIC8vIFVzZSB0aGUgb3JpZ2luYXRpbmcgZmlsZSBhcyB0aGUgY2FjaGUga2V5IGlmIHByZXNlbnRcbiAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlLCBnZW5lcmF0ZSBhIGNhY2hlIGtleSBiYXNlZCBvbiB0aGUgZ2VuZXJhdGVkIG5hbWVcbiAgICAgICAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBpbmZvLnNvdXJjZUZpbGVuYW1lID8/IGAhIVtHRU5FUkFURURdOiR7bmFtZX1gO1xuXG4gICAgICAgICAgICAgIHRoaXMuYXNzZXRDYWNoZS5zZXQoY2FjaGVLZXksIHsgaW5mbywgbmFtZSwgc291cmNlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgIGNvbnRlbnQ6IGZpbmFsQ29udGVudCA/PyAnJyxcbiAgICAgICAgICBzdWNjZXNzOiBjaGlsZENvbXBpbGF0aW9uLmVycm9ycz8ubGVuZ3RoID09PSAwLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfZXZhbHVhdGUoZmlsZW5hbWU6IHN0cmluZywgc291cmNlOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAvLyBFdmFsdWF0ZSBjb2RlXG5cbiAgICAvLyBjc3MtbG9hZGVyIHJlcXVpcmVzIHRoZSBidG9hIGZ1bmN0aW9uIHRvIGV4aXN0IHRvIGNvcnJlY3RseSBnZW5lcmF0ZSBpbmxpbmUgc291cmNlbWFwc1xuICAgIGNvbnN0IGNvbnRleHQ6IHsgYnRvYTogKGlucHV0OiBzdHJpbmcpID0+IHN0cmluZzsgcmVzb3VyY2U/OiBzdHJpbmcgfCB7IGRlZmF1bHQ/OiBzdHJpbmcgfSB9ID0ge1xuICAgICAgYnRvYShpbnB1dCkge1xuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oaW5wdXQpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIHRyeSB7XG4gICAgICB2bS5ydW5Jbk5ld0NvbnRleHQoc291cmNlLCBjb250ZXh0LCB7IGZpbGVuYW1lIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gRXJyb3IgYXJlIHByb3BhZ2F0ZWQgdGhyb3VnaCB0aGUgY2hpbGQgY29tcGlsYXRpb24uXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNvbnRleHQucmVzb3VyY2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gY29udGV4dC5yZXNvdXJjZTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBjb250ZXh0LnJlc291cmNlPy5kZWZhdWx0ID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIGNvbnRleHQucmVzb3VyY2UuZGVmYXVsdDtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBsb2FkZXIgXCIke2ZpbGVuYW1lfVwiIGRpZG4ndCByZXR1cm4gYSBzdHJpbmcuYCk7XG4gIH1cblxuICBhc3luYyBnZXQoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZEZpbGUgPSBub3JtYWxpemVQYXRoKGZpbGVQYXRoKTtcbiAgICBsZXQgY29tcGlsYXRpb25SZXN1bHQgPSB0aGlzLmZpbGVDYWNoZT8uZ2V0KG5vcm1hbGl6ZWRGaWxlKTtcblxuICAgIGlmIChjb21waWxhdGlvblJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBjYWNoZSBtaXNzIHNvIGNvbXBpbGUgcmVzb3VyY2VcbiAgICAgIGNvbXBpbGF0aW9uUmVzdWx0ID0gYXdhaXQgdGhpcy5fY29tcGlsZShmaWxlUGF0aCk7XG5cbiAgICAgIC8vIE9ubHkgY2FjaGUgaWYgY29tcGlsYXRpb24gd2FzIHN1Y2Nlc3NmdWxcbiAgICAgIGlmICh0aGlzLmZpbGVDYWNoZSAmJiBjb21waWxhdGlvblJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIHRoaXMuZmlsZUNhY2hlLnNldChub3JtYWxpemVkRmlsZSwgY29tcGlsYXRpb25SZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb21waWxhdGlvblJlc3VsdC5jb250ZW50O1xuICB9XG5cbiAgYXN5bmMgcHJvY2VzcyhcbiAgICBkYXRhOiBzdHJpbmcsXG4gICAgZmlsZUV4dGVuc2lvbjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICAgIHJlc291cmNlVHlwZTogJ3RlbXBsYXRlJyB8ICdzdHlsZScsXG4gICAgY29udGFpbmluZ0ZpbGU/OiBzdHJpbmcsXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKGRhdGEudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbXBpbGF0aW9uUmVzdWx0ID0gYXdhaXQgdGhpcy5fY29tcGlsZShcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGRhdGEsXG4gICAgICBmaWxlRXh0ZW5zaW9uLFxuICAgICAgcmVzb3VyY2VUeXBlLFxuICAgICAgY29udGFpbmluZ0ZpbGUsXG4gICAgKTtcblxuICAgIHJldHVybiBjb21waWxhdGlvblJlc3VsdC5jb250ZW50O1xuICB9XG59XG4iXX0=