UNPKG

@ngtools/webpack

Version:

Webpack plugin that AoT compiles your Angular components and modules.

268 lines • 34.9 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NgccProcessor = void 0; const child_process_1 = require("child_process"); const crypto_1 = require("crypto"); const fs_1 = require("fs"); const path = __importStar(require("path")); const benchmark_1 = require("./benchmark"); // We cannot create a plugin for this, because NGTSC requires addition type // information which ngcc creates when processing a package which was compiled with NGC. // Example of such errors: // ERROR in node_modules/@angular/platform-browser/platform-browser.d.ts(42,22): // error TS-996002: Appears in the NgModule.imports of AppModule, // but could not be resolved to an NgModule class // We now transform a package and it's typings when NGTSC is resolving a module. class NgccProcessor { constructor(compilerNgcc, propertiesToConsider, compilationWarnings, compilationErrors, basePath, tsConfigPath, inputFileSystem, resolver) { this.compilerNgcc = compilerNgcc; this.propertiesToConsider = propertiesToConsider; this.compilationWarnings = compilationWarnings; this.compilationErrors = compilationErrors; this.basePath = basePath; this.tsConfigPath = tsConfigPath; this.inputFileSystem = inputFileSystem; this.resolver = resolver; this._processedModules = new Set(); this._logger = new NgccLogger(this.compilationWarnings, this.compilationErrors, compilerNgcc.LogLevel.info); this._nodeModulesDirectory = this.findNodeModulesDirectory(this.basePath); } /** Process the entire node modules tree. */ process() { // Under Bazel when running in sandbox mode parts of the filesystem is read-only, or when using // Yarn PnP there may not be a node_modules directory. ngcc can't run in those cases, so the // processing is skipped. if (process.env.BAZEL_TARGET || !this._nodeModulesDirectory) { return; } // Skip if node_modules are read-only const corePackage = this.tryResolvePackage('@angular/core', this._nodeModulesDirectory); if (corePackage && isReadOnlyFile(corePackage)) { return; } // Perform a ngcc run check to determine if an initial execution is required. // If a run hash file exists that matches the current package manager lock file and the // project's tsconfig, then an initial ngcc run has already been performed. let skipProcessing = false; let runHashFilePath; const runHashBasePath = path.join(this._nodeModulesDirectory, '.cli-ngcc'); const projectBasePath = path.join(this._nodeModulesDirectory, '..'); try { let ngccConfigData; try { ngccConfigData = (0, fs_1.readFileSync)(path.join(projectBasePath, 'ngcc.config.js')); } catch (_a) { ngccConfigData = ''; } const relativeTsconfigPath = path.relative(projectBasePath, this.tsConfigPath); const tsconfigData = (0, fs_1.readFileSync)(this.tsConfigPath); const { lockFileData, lockFilePath } = this.findPackageManagerLockFile(projectBasePath); // Generate a hash that represents the state of the package lock file and used tsconfig const runHash = (0, crypto_1.createHash)('sha256') .update(lockFileData) .update(lockFilePath) .update(ngccConfigData) .update(tsconfigData) .update(relativeTsconfigPath) .digest('hex'); // The hash is used directly in the file name to mitigate potential read/write race // conditions as well as to only require a file existence check runHashFilePath = path.join(runHashBasePath, runHash + '.lock'); // If the run hash lock file exists, then ngcc was already run against this project state if ((0, fs_1.existsSync)(runHashFilePath)) { skipProcessing = true; } } catch (_b) { // Any error means an ngcc execution is needed } if (skipProcessing) { return; } const timeLabel = 'NgccProcessor.process'; (0, benchmark_1.time)(timeLabel); // We spawn instead of using the API because: // - NGCC Async uses clustering which is problematic when used via the API which means // that we cannot setup multiple cluster masters with different options. // - We will not be able to have concurrent builds otherwise Ex: App-Shell, // as NGCC will create a lock file for both builds and it will cause builds to fails. const originalProcessTitle = process.title; try { const { status, error } = (0, child_process_1.spawnSync)(process.execPath, [ this.compilerNgcc.ngccMainFilePath, '--source' /** basePath */, this._nodeModulesDirectory, '--properties' /** propertiesToConsider */, ...this.propertiesToConsider, '--first-only' /** compileAllFormats */, '--create-ivy-entry-points' /** createNewEntryPointFormats */, '--async', '--tsconfig' /** tsConfigPath */, this.tsConfigPath, '--use-program-dependencies', ], { stdio: ['inherit', process.stderr, process.stderr], }); if (status !== 0) { const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || ''; throw new Error(errorMessage + `NGCC failed${errorMessage ? ', see above' : ''}.`); } } finally { process.title = originalProcessTitle; } (0, benchmark_1.timeEnd)(timeLabel); // ngcc was successful so if a run hash was generated, write it for next time if (runHashFilePath) { try { if (!(0, fs_1.existsSync)(runHashBasePath)) { (0, fs_1.mkdirSync)(runHashBasePath, { recursive: true }); } (0, fs_1.writeFileSync)(runHashFilePath, ''); } catch (_c) { // Errors are non-fatal } } } /** Process a module and its dependencies. */ processModule(moduleName, resolvedModule) { var _a, _b; const resolvedFileName = resolvedModule.resolvedFileName; if (!this._nodeModulesDirectory || !resolvedFileName || moduleName.startsWith('.') || this._processedModules.has(resolvedFileName)) { // Skip when module_modules directory is not present, module is unknown, relative or the // NGCC compiler is not found or already processed. return; } const packageJsonPath = this.tryResolvePackage(moduleName, resolvedFileName); // If the package.json is read only we should skip calling NGCC. // With Bazel when running under sandbox the filesystem is read-only. if (!packageJsonPath || isReadOnlyFile(packageJsonPath)) { // add it to processed so the second time round we skip this. this._processedModules.add(resolvedFileName); return; } const timeLabel = `NgccProcessor.processModule.ngcc.process+${moduleName}`; (0, benchmark_1.time)(timeLabel); this.compilerNgcc.process({ basePath: this._nodeModulesDirectory, targetEntryPointPath: path.dirname(packageJsonPath), propertiesToConsider: this.propertiesToConsider, compileAllFormats: false, createNewEntryPointFormats: true, logger: this._logger, tsConfigPath: this.tsConfigPath, }); (0, benchmark_1.timeEnd)(timeLabel); // Purge this file from cache, since NGCC add new mainFields. Ex: module_ivy_ngcc // which are unknown in the cached file. (_b = (_a = this.inputFileSystem).purge) === null || _b === void 0 ? void 0 : _b.call(_a, packageJsonPath); this._processedModules.add(resolvedFileName); } invalidate(fileName) { this._processedModules.delete(fileName); } /** * Try resolve a package.json file from the resolved .d.ts file. */ tryResolvePackage(moduleName, resolvedFileName) { try { const resolvedPath = this.resolver.resolveSync({}, resolvedFileName, `${moduleName}/package.json`); return resolvedPath || undefined; } catch (_a) { // Ex: @angular/compiler/src/i18n/i18n_ast/package.json // or local libraries which don't reside in node_modules const packageJsonPath = path.resolve(resolvedFileName, '../package.json'); return (0, fs_1.existsSync)(packageJsonPath) ? packageJsonPath : undefined; } } findNodeModulesDirectory(startPoint) { let current = startPoint; while (path.dirname(current) !== current) { const nodePath = path.join(current, 'node_modules'); if ((0, fs_1.existsSync)(nodePath)) { return nodePath; } current = path.dirname(current); } return null; } findPackageManagerLockFile(projectBasePath) { for (const lockFile of ['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json']) { const lockFilePath = path.join(projectBasePath, lockFile); try { return { lockFilePath, lockFileData: (0, fs_1.readFileSync)(lockFilePath), }; } catch (_a) { } } throw new Error('Cannot locate a package manager lock file.'); } } exports.NgccProcessor = NgccProcessor; class NgccLogger { constructor(compilationWarnings, compilationErrors, level) { this.compilationWarnings = compilationWarnings; this.compilationErrors = compilationErrors; this.level = level; } // eslint-disable-next-line @typescript-eslint/no-empty-function debug() { } info(...args) { // Log to stderr because it's a progress-like info message. process.stderr.write(`\n${args.join(' ')}\n`); } warn(...args) { this.compilationWarnings.push(args.join(' ')); } error(...args) { this.compilationErrors.push(new Error(args.join(' '))); } } function isReadOnlyFile(fileName) { try { (0, fs_1.accessSync)(fileName, fs_1.constants.W_OK); return false; } catch (_a) { return true; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdjY19wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9uZ3Rvb2xzL3dlYnBhY2svc3JjL25nY2NfcHJvY2Vzc29yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0gsaURBQTBDO0FBQzFDLG1DQUFvQztBQUNwQywyQkFBK0Y7QUFDL0YsMkNBQTZCO0FBRzdCLDJDQUE0QztBQU01QywyRUFBMkU7QUFDM0Usd0ZBQXdGO0FBRXhGLDBCQUEwQjtBQUMxQixnRkFBZ0Y7QUFDaEYsaUVBQWlFO0FBQ2pFLGlEQUFpRDtBQUVqRCxnRkFBZ0Y7QUFFaEYsTUFBYSxhQUFhO0lBS3hCLFlBQ21CLFlBQXlELEVBQ3pELG9CQUE4QixFQUM5QixtQkFBdUMsRUFDdkMsaUJBQXFDLEVBQ3JDLFFBQWdCLEVBQ2hCLFlBQW9CLEVBQ3BCLGVBQWdDLEVBQ2hDLFFBQTZCO1FBUDdCLGlCQUFZLEdBQVosWUFBWSxDQUE2QztRQUN6RCx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQVU7UUFDOUIsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFvQjtRQUN2QyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW9CO1FBQ3JDLGFBQVEsR0FBUixRQUFRLENBQVE7UUFDaEIsaUJBQVksR0FBWixZQUFZLENBQVE7UUFDcEIsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQ2hDLGFBQVEsR0FBUixRQUFRLENBQXFCO1FBWnhDLHNCQUFpQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFjNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLFVBQVUsQ0FDM0IsSUFBSSxDQUFDLG1CQUFtQixFQUN4QixJQUFJLENBQUMsaUJBQWlCLEVBQ3RCLFlBQVksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUMzQixDQUFDO1FBQ0YsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElB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LEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RCxDQUFDO0NBQ0Y7QUFFRCxTQUFTLGNBQWMsQ0FBQyxRQUFnQjtJQUN0QyxJQUFJO1FBQ0YsSUFBQSxlQUFVLEVBQUMsUUFBUSxFQUFFLGNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyQyxPQUFPLEtBQUssQ0FBQztLQUNkO0lBQUMsV0FBTTtRQUNOLE9BQU8sSUFBSSxDQUFDO0tBQ2I7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB0eXBlIHsgTG9nTGV2ZWwsIExvZ2dlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbXBpbGVyLWNsaS9uZ2NjJztcbmltcG9ydCB7IHNwYXduU3luYyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBhY2Nlc3NTeW5jLCBjb25zdGFudHMsIGV4aXN0c1N5bmMsIG1rZGlyU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIHRzIGZyb20gJ3R5cGVzY3JpcHQnO1xuaW1wb3J0IHR5cGUgeyBDb21waWxlciB9IGZyb20gJ3dlYnBhY2snO1xuaW1wb3J0IHsgdGltZSwgdGltZUVuZCB9IGZyb20gJy4vYmVuY2htYXJrJztcbmltcG9ydCB7IElucHV0RmlsZVN5c3RlbSB9IGZyb20gJy4vaXZ5L3N5c3RlbSc7XG5cbi8vIEV4dHJhY3QgUmVzb2x2ZXIgdHlwZSBmcm9tIFdlYnBhY2sgdHlwZXMgc2luY2UgaXQgaXMgbm90IGRpcmVjdGx5IGV4cG9ydGVkXG50eXBlIFJlc29sdmVyV2l0aE9wdGlvbnMgPSBSZXR1cm5UeXBlPENvbXBpbGVyWydyZXNvbHZlckZhY3RvcnknXVsnZ2V0J10+O1xuXG4vLyBXZSBjYW5ub3QgY3JlYXRlIGEgcGx1Z2luIGZvciB0aGlzLCBiZWNhdXNlIE5HVFNDIHJlcXVpcmVzIGFkZGl0aW9uIHR5cGVcbi8vIGluZm9ybWF0aW9uIHdoaWNoIG5nY2MgY3JlYXRlcyB3aGVuIHByb2Nlc3NpbmcgYSBwYWNrYWdlIHdoaWNoIHdhcyBjb21waWxlZCB3aXRoIE5HQy5cblxuLy8gRXhhbXBsZSBvZiBzdWNoIGVycm9yczpcbi8vIEVSUk9SIGluIG5vZGVfbW9kdWxlcy9AYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyL3BsYXRmb3JtLWJyb3dzZXIuZC50cyg0MiwyMik6XG4vLyBlcnJvciBUUy05OTYwMDI6IEFwcGVhcnMgaW4gdGhlIE5nTW9kdWxlLmltcG9ydHMgb2YgQXBwTW9kdWxlLFxuLy8gYnV0IGNvdWxkIG5vdCBiZSByZXNvbHZlZCB0byBhbiBOZ01vZHVsZSBjbGFzc1xuXG4vLyBXZSBub3cgdHJhbnNmb3JtIGEgcGFja2FnZSBhbmQgaXQncyB0eXBpbmdzIHdoZW4gTkdUU0MgaXMgcmVzb2x2aW5nIGEgbW9kdWxlLlxuXG5leHBvcnQgY2xhc3MgTmdjY1Byb2Nlc3NvciB7XG4gIHByaXZhdGUgX3Byb2Nlc3NlZE1vZHVsZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgcHJpdmF0ZSBfbG9nZ2VyOiBOZ2NjTG9nZ2VyO1xuICBwcml2YXRlIF9ub2RlTW9kdWxlc0RpcmVjdG9yeTogc3RyaW5nIHwgbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbXBpbGVyTmdjYzogdHlwZW9mIGltcG9ydCgnQGFuZ3VsYXIvY29tcGlsZXItY2xpL25nY2MnKSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByb3BlcnRpZXNUb0NvbnNpZGVyOiBzdHJpbmdbXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbXBpbGF0aW9uV2FybmluZ3M6IChFcnJvciB8IHN0cmluZylbXSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbXBpbGF0aW9uRXJyb3JzOiAoRXJyb3IgfCBzdHJpbmcpW10sXG4gICAgcHJpdmF0ZSByZWFkb25seSBiYXNlUGF0aDogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdHNDb25maWdQYXRoOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBpbnB1dEZpbGVTeXN0ZW06IElucHV0RmlsZVN5c3RlbSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmVyOiBSZXNvbHZlcldpdGhPcHRpb25zLFxuICApIHtcbiAgICB0aGlzLl9sb2dnZXIgPSBuZXcgTmdjY0xvZ2dlcihcbiAgICAgIHRoaXMuY29tcGlsYXRpb25XYXJuaW5ncyxcbiAgICAgIHRoaXMuY29tcGlsYXRpb25FcnJvcnMsXG4gICAgICBjb21waWxlck5nY2MuTG9nTGV2ZWwuaW5mbyxcbiAgICApO1xuICAgIHRoaXMuX25vZGVNb2R1bGVzRGlyZWN0b3J5ID0gdGhpcy5maW5kTm9kZU1vZHVsZXNEaXJlY3RvcnkodGhpcy5iYXNlUGF0aCk7XG4gIH1cblxuICAvKiogUHJvY2VzcyB0aGUgZW50aXJlIG5vZGUgbW9kdWxlcyB0cmVlLiAqL1xuICBwcm9jZXNzKCkge1xuICAgIC8vIFVuZGVyIEJhemVsIHdoZW4gcnVubmluZyBpbiBzYW5kYm94IG1vZGUgcGFydHMgb2YgdGhlIGZpbGVzeXN0ZW0gaXMgcmVhZC1vbmx5LCBvciB3aGVuIHVzaW5nXG4gICAgLy8gWWFybiBQblAgdGhlcmUgbWF5IG5vdCBiZSBhIG5vZGVfbW9kdWxlcyBkaXJlY3RvcnkuIG5nY2MgY2FuJ3QgcnVuIGluIHRob3NlIGNhc2VzLCBzbyB0aGVcbiAgICAvLyBwcm9jZXNzaW5nIGlzIHNraXBwZWQuXG4gICAgaWYgKHByb2Nlc3MuZW52LkJBWkVMX1RBUkdFVCB8fCAhdGhpcy5fbm9kZU1vZHVsZXNEaXJlY3RvcnkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTa2lwIGlmIG5vZGVfbW9kdWxlcyBhcmUgcmVhZC1vbmx5XG4gICAgY29uc3QgY29yZVBhY2thZ2UgPSB0aGlzLnRyeVJlc29sdmVQYWNrYWdlKCdAYW5ndWxhci9jb3JlJywgdGhpcy5fbm9kZU1vZHVsZXNEaXJlY3RvcnkpO1xuICAgIGlmIChjb3JlUGFja2FnZSAmJiBpc1JlYWRPbmx5RmlsZShjb3JlUGFja2FnZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIGEgbmdjYyBydW4gY2hlY2sgdG8gZGV0ZXJtaW5lIGlmIGFuIGluaXRpYWwgZXhlY3V0aW9uIGlzIHJlcXVpcmVkLlxuICAgIC8vIElmIGEgcnVuIGhhc2ggZmlsZSBleGlzdHMgdGhhdCBtYXRjaGVzIHRoZSBjdXJyZW50IHBhY2thZ2UgbWFuYWdlciBsb2NrIGZpbGUgYW5kIHRoZVxuICAgIC8vIHByb2plY3QncyB0c2NvbmZpZywgdGhlbiBhbiBpbml0aWFsIG5nY2MgcnVuIGhhcyBhbHJlYWR5IGJlZW4gcGVyZm9ybWVkLlxuICAgIGxldCBza2lwUHJvY2Vzc2luZyA9IGZhbHNlO1xuICAgIGxldCBydW5IYXNoRmlsZVBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBydW5IYXNoQmFzZVBhdGggPSBwYXRoLmpvaW4odGhpcy5fbm9kZU1vZHVsZXNEaXJlY3RvcnksICcuY2xpLW5nY2MnKTtcbiAgICBjb25zdCBwcm9qZWN0QmFzZVBhdGggPSBwYXRoLmpvaW4odGhpcy5fbm9kZU1vZHVsZXNEaXJlY3RvcnksICcuLicpO1xuICAgIHRyeSB7XG4gICAgICBsZXQgbmdjY0NvbmZpZ0RhdGE7XG4gICAgICB0cnkge1xuICAgICAgICBuZ2NjQ29uZmlnRGF0YSA9IHJlYWRGaWxlU3luYyhwYXRoLmpvaW4ocHJvamVjdEJhc2VQYXRoLCAnbmdjYy5jb25maWcuanMnKSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgbmdjY0NvbmZpZ0RhdGEgPSAnJztcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVsYXRpdmVUc2NvbmZpZ1BhdGggPSBwYXRoLnJlbGF0aXZlKHByb2plY3RCYXNlUGF0aCwgdGhpcy50c0NvbmZpZ1BhdGgpO1xuICAgICAgY29uc3QgdHNjb25maWdEYXRhID0gcmVhZEZpbGVTeW5jKHRoaXMudHNDb25maWdQYXRoKTtcbiAgICAgIGNvbnN0IHsgbG9ja0ZpbGVEYXRhLCBsb2NrRmlsZVBhdGggfSA9IHRoaXMuZmluZFBhY2thZ2VNYW5hZ2VyTG9ja0ZpbGUocHJvamVjdEJhc2VQYXRoKTtcblxuICAgICAgLy8gR2VuZXJhdGUgYSBoYXNoIHRoYXQgcmVwcmVzZW50cyB0aGUgc3RhdGUgb2YgdGhlIHBhY2thZ2UgbG9jayBmaWxlIGFuZCB1c2VkIHRzY29uZmlnXG4gICAgICBjb25zdCBydW5IYXNoID0gY3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgICAgLnVwZGF0ZShsb2NrRmlsZURhdGEpXG4gICAgICAgIC51cGRhdGUobG9ja0ZpbGVQYXRoKVxuICAgICAgICAudXBkYXRlKG5nY2NDb25maWdEYXRhKVxuICAgICAgICAudXBkYXRlKHRzY29uZmlnRGF0YSlcbiAgICAgICAgLnVwZGF0ZShyZWxhdGl2ZVRzY29uZmlnUGF0aClcbiAgICAgICAgLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgICAgIC8vIFRoZSBoYXNoIGlzIHVzZWQgZGlyZWN0bHkgaW4gdGhlIGZpbGUgbmFtZSB0byBtaXRpZ2F0ZSBwb3RlbnRpYWwgcmVhZC93cml0ZSByYWNlXG4gICAgICAvLyBjb25kaXRpb25zIGFzIHdlbGwgYXMgdG8gb25seSByZXF1aXJlIGEgZmlsZSBleGlzdGVuY2UgY2hlY2tcbiAgICAgIHJ1bkhhc2hGaWxlUGF0aCA9IHBhdGguam9pbihydW5IYXNoQmFzZVBhdGgsIHJ1bkhhc2ggKyAnLmxvY2snKTtcblxuICAgICAgLy8gSWYgdGhlIHJ1biBoYXNoIGxvY2sgZmlsZSBleGlzdHMsIHRoZW4gbmdjYyB3YXMgYWxyZWFkeSBydW4gYWdhaW5zdCB0aGlzIHByb2plY3Qgc3RhdGVcbiAgICAgIGlmIChleGlzdHNTeW5jKHJ1bkhhc2hGaWxlUGF0aCkpIHtcbiAgICAgICAgc2tpcFByb2Nlc3NpbmcgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gQW55IGVycm9yIG1lYW5zIGFuIG5nY2MgZXhlY3V0aW9uIGlzIG5lZWRlZFxuICAgIH1cblxuICAgIGlmIChza2lwUHJvY2Vzc2luZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRpbWVMYWJlbCA9ICdOZ2NjUHJvY2Vzc29yLnByb2Nlc3MnO1xuICAgIHRpbWUodGltZUxhYmVsKTtcblxuICAgIC8vIFdlIHNwYXduIGluc3RlYWQgb2YgdXNpbmcgdGhlIEFQSSBiZWNhdXNlOlxuICAgIC8vIC0gTkdDQyBBc3luYyB1c2VzIGNsdXN0ZXJpbmcgd2hpY2ggaXMgcHJvYmxlbWF0aWMgd2hlbiB1c2VkIHZpYSB0aGUgQVBJIHdoaWNoIG1lYW5zXG4gICAgLy8gdGhhdCB3ZSBjYW5ub3Qgc2V0dXAgbXVsdGlwbGUgY2x1c3RlciBtYXN0ZXJzIHdpdGggZGlmZmVyZW50IG9wdGlvbnMuXG4gICAgLy8gLSBXZSB3aWxsIG5vdCBiZSBhYmxlIHRvIGhhdmUgY29uY3VycmVudCBidWlsZHMgb3RoZXJ3aXNlIEV4OiBBcHAtU2hlbGwsXG4gICAgLy8gYXMgTkdDQyB3aWxsIGNyZWF0ZSBhIGxvY2sgZmlsZSBmb3IgYm90aCBidWlsZHMgYW5kIGl0IHdpbGwgY2F1c2UgYnVpbGRzIHRvIGZhaWxzLlxuICAgIGNvbnN0IG9yaWdpbmFsUHJvY2Vzc1RpdGxlID0gcHJvY2Vzcy50aXRsZTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBzdGF0dXMsIGVycm9yIH0gPSBzcGF3blN5bmMoXG4gICAgICAgIHByb2Nlc3MuZXhlY1BhdGgsXG4gICAgICAgIFtcbiAgICAgICAgICB0aGlzLmNvbXBpbGVyTmdjYy5uZ2NjTWFpbkZpbGVQYXRoLFxuICAgICAgICAgICctLXNvdXJjZScgLyoqIGJhc2VQYXRoICovLFxuICAgICAgICAgIHRoaXMuX25vZGVNb2R1bGVzRGlyZWN0b3J5LFxuICAgICAgICAgICctLXByb3BlcnRpZXMnIC8qKiBwcm9wZXJ0aWVzVG9Db25zaWRlciAqLyxcbiAgICAgICAgICAuLi50aGlzLnByb3BlcnRpZXNUb0NvbnNpZGVyLFxuICAgICAgICAgICctLWZpcnN0LW9ubHknIC8qKiBjb21waWxlQWxsRm9ybWF0cyAqLyxcbiAgICAgICAgICAnLS1jcmVhdGUtaXZ5LWVudHJ5LXBvaW50cycgLyoqIGNyZWF0ZU5ld0VudHJ5UG9pbnRGb3JtYXRzICovLFxuICAgICAgICAgICctLWFzeW5jJyxcbiAgICAgICAgICAnLS10c2NvbmZpZycgLyoqIHRzQ29uZmlnUGF0aCAqLyxcbiAgICAgICAgICB0aGlzLnRzQ29uZmlnUGF0aCxcbiAgICAgICAgICAnLS11c2UtcHJvZ3JhbS1kZXBlbmRlbmNpZXMnLFxuICAgICAgICBdLFxuICAgICAgICB7XG4gICAgICAgICAgc3RkaW86IFsnaW5oZXJpdCcsIHByb2Nlc3Muc3RkZXJyLCBwcm9jZXNzLnN0ZGVycl0sXG4gICAgICAgIH0sXG4gICAgICApO1xuXG4gICAgICBpZiAoc3RhdHVzICE9PSAwKSB7XG4gICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yPy5tZXNzYWdlIHx8ICcnO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlICsgYE5HQ0MgZmFpbGVkJHtlcnJvck1lc3NhZ2UgPyAnLCBzZWUgYWJvdmUnIDogJyd9LmApO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBwcm9jZXNzLnRpdGxlID0gb3JpZ2luYWxQcm9jZXNzVGl0bGU7XG4gICAgfVxuXG4gICAgdGltZUVuZCh0aW1lTGFiZWwpO1xuXG4gICAgLy8gbmdjYyB3YXMgc3VjY2Vzc2Z1bCBzbyBpZiBhIHJ1biBoYXNoIHdhcyBnZW5lcmF0ZWQsIHdyaXRlIGl0IGZvciBuZXh0IHRpbWVcbiAgICBpZiAocnVuSGFzaEZpbGVQYXRoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIWV4aXN0c1N5bmMocnVuSGFzaEJhc2VQYXRoKSkge1xuICAgICAgICAgIG1rZGlyU3luYyhydW5IYXNoQmFzZVBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgICB9XG4gICAgICAgIHdyaXRlRmlsZVN5bmMocnVuSGFzaEZpbGVQYXRoLCAnJyk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gRXJyb3JzIGFyZSBub24tZmF0YWxcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiogUHJvY2VzcyBhIG1vZHVsZSBhbmQgaXRzIGRlcGVuZGVuY2llcy4gKi9cbiAgcHJvY2Vzc01vZHVsZShcbiAgICBtb2R1bGVOYW1lOiBzdHJpbmcsXG4gICAgcmVzb2x2ZWRNb2R1bGU6IHRzLlJlc29sdmVkTW9kdWxlIHwgdHMuUmVzb2x2ZWRUeXBlUmVmZXJlbmNlRGlyZWN0aXZlLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCByZXNvbHZlZEZpbGVOYW1lID0gcmVzb2x2ZWRNb2R1bGUucmVzb2x2ZWRGaWxlTmFtZTtcbiAgICBpZiAoXG4gICAgICAhdGhpcy5fbm9kZU1vZHVsZXNEaXJlY3RvcnkgfHxcbiAgICAgICFyZXNvbHZlZEZpbGVOYW1lIHx8XG4gICAgICBtb2R1bGVOYW1lLnN0YXJ0c1dpdGgoJy4nKSB8fFxuICAgICAgdGhpcy5fcHJvY2Vzc2VkTW9kdWxlcy5oYXMocmVzb2x2ZWRGaWxlTmFtZSlcbiAgICApIHtcbiAgICAgIC8vIFNraXAgd2hlbiBtb2R1bGVfbW9kdWxlcyBkaXJlY3RvcnkgaXMgbm90IHByZXNlbnQsIG1vZHVsZSBpcyB1bmtub3duLCByZWxhdGl2ZSBvciB0aGVcbiAgICAgIC8vIE5HQ0MgY29tcGlsZXIgaXMgbm90IGZvdW5kIG9yIGFscmVhZHkgcHJvY2Vzc2VkLlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHRoaXMudHJ5UmVzb2x2ZVBhY2thZ2UobW9kdWxlTmFtZSwgcmVzb2x2ZWRGaWxlTmFtZSk7XG4gICAgLy8gSWYgdGhlIHBhY2thZ2UuanNvbiBpcyByZWFkIG9ubHkgd2Ugc2hvdWxkIHNraXAgY2FsbGluZyBOR0NDLlxuICAgIC8vIFdpdGggQmF6ZWwgd2hlbiBydW5uaW5nIHVuZGVyIHNhbmRib3ggdGhlIGZpbGVzeXN0ZW0gaXMgcmVhZC1vbmx5LlxuICAgIGlmICghcGFja2FnZUpzb25QYXRoIHx8IGlzUmVhZE9ubHlGaWxlKHBhY2thZ2VKc29uUGF0aCkpIHtcbiAgICAgIC8vIGFkZCBpdCB0byBwcm9jZXNzZWQgc28gdGhlIHNlY29uZCB0aW1lIHJvdW5kIHdlIHNraXAgdGhpcy5cbiAgICAgIHRoaXMuX3Byb2Nlc3NlZE1vZHVsZXMuYWRkKHJlc29sdmVkRmlsZU5hbWUpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdGltZUxhYmVsID0gYE5nY2NQcm9jZXNzb3IucHJvY2Vzc01vZHVsZS5uZ2NjLnByb2Nlc3MrJHttb2R1bGVOYW1lfWA7XG4gICAgdGltZSh0aW1lTGFiZWwpO1xuICAgIHRoaXMuY29tcGlsZXJOZ2NjLnByb2Nlc3Moe1xuICAgICAgYmFzZVBhdGg6IHRoaXMuX25vZGVNb2R1bGVzRGlyZWN0b3J5LFxuICAgICAgdGFyZ2V0RW50cnlQb2ludFBhdGg6IHBhdGguZGlybmFtZShwYWNrYWdlSnNvblBhdGgpLFxuICAgICAgcHJvcGVydGllc1RvQ29uc2lkZXI6IHRoaXMucHJvcGVydGllc1RvQ29uc2lkZXIsXG4gICAgICBjb21waWxlQWxsRm9ybWF0czogZmFsc2UsXG4gICAgICBjcmVhdGVOZXdFbnRyeVBvaW50Rm9ybWF0czogdHJ1ZSxcbiAgICAgIGxvZ2dlcjogdGhpcy5fbG9nZ2VyLFxuICAgICAgdHNDb25maWdQYXRoOiB0aGlzLnRzQ29uZmlnUGF0aCxcbiAgICB9KTtcbiAgICB0aW1lRW5kKHRpbWVMYWJlbCk7XG5cbiAgICAvLyBQdXJnZSB0aGlzIGZpbGUgZnJvbSBjYWNoZSwgc2luY2UgTkdDQyBhZGQgbmV3IG1haW5GaWVsZHMuIEV4OiBtb2R1bGVfaXZ5X25nY2NcbiAgICAvLyB3aGljaCBhcmUgdW5rbm93biBpbiB0aGUgY2FjaGVkIGZpbGUuXG4gICAgdGhpcy5pbnB1dEZpbGVTeXN0ZW0ucHVyZ2U/LihwYWNrYWdlSnNvblBhdGgpO1xuXG4gICAgdGhpcy5fcHJvY2Vzc2VkTW9kdWxlcy5hZGQocmVzb2x2ZWRGaWxlTmFtZSk7XG4gIH1cblxuICBpbnZhbGlkYXRlKGZpbGVOYW1lOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9wcm9jZXNzZWRNb2R1bGVzLmRlbGV0ZShmaWxlTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogVHJ5IHJlc29sdmUgYSBwYWNrYWdlLmpzb24gZmlsZSBmcm9tIHRoZSByZXNvbHZlZCAuZC50cyBmaWxlLlxuICAgKi9cbiAgcHJpdmF0ZSB0cnlSZXNvbHZlUGFja2FnZShtb2R1bGVOYW1lOiBzdHJpbmcsIHJlc29sdmVkRmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHRoaXMucmVzb2x2ZXIucmVzb2x2ZVN5bmMoXG4gICAgICAgIHt9LFxuICAgICAgICByZXNvbHZlZEZpbGVOYW1lLFxuICAgICAgICBgJHttb2R1bGVOYW1lfS9wYWNrYWdlLmpzb25gLFxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIHJlc29sdmVkUGF0aCB8fCB1bmRlZmluZWQ7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBFeDogQGFuZ3VsYXIvY29tcGlsZXIvc3JjL2kxOG4vaTE4bl9hc3QvcGFja2FnZS5qc29uXG4gICAgICAvLyBvciBsb2NhbCBsaWJyYXJpZXMgd2hpY2ggZG9uJ3QgcmVzaWRlIGluIG5vZGVfbW9kdWxlc1xuICAgICAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gcGF0aC5yZXNvbHZlKHJlc29sdmVkRmlsZU5hbWUsICcuLi9wYWNrYWdlLmpzb24nKTtcblxuICAgICAgcmV0dXJuIGV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSA/IHBhY2thZ2VKc29uUGF0aCA6IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmROb2RlTW9kdWxlc0RpcmVjdG9yeShzdGFydFBvaW50OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBsZXQgY3VycmVudCA9IHN0YXJ0UG9pbnQ7XG4gICAgd2hpbGUgKHBhdGguZGlybmFtZShjdXJyZW50KSAhPT0gY3VycmVudCkge1xuICAgICAgY29uc3Qgbm9kZVBhdGggPSBwYXRoLmpvaW4oY3VycmVudCwgJ25vZGVfbW9kdWxlcycpO1xuICAgICAgaWYgKGV4aXN0c1N5bmMobm9kZVBhdGgpKSB7XG4gICAgICAgIHJldHVybiBub2RlUGF0aDtcbiAgICAgIH1cblxuICAgICAgY3VycmVudCA9IHBhdGguZGlybmFtZShjdXJyZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgZmluZFBhY2thZ2VNYW5hZ2VyTG9ja0ZpbGUocHJvamVjdEJhc2VQYXRoOiBzdHJpbmcpOiB7XG4gICAgbG9ja0ZpbGVQYXRoOiBzdHJpbmc7XG4gICAgbG9ja0ZpbGVEYXRhOiBCdWZmZXI7XG4gIH0ge1xuICAgIGZvciAoY29uc3QgbG9ja0ZpbGUgb2YgWyd5YXJuLmxvY2snLCAncG5wbS1sb2NrLnlhbWwnLCAncGFja2FnZS1sb2NrLmpzb24nXSkge1xuICAgICAgY29uc3QgbG9ja0ZpbGVQYXRoID0gcGF0aC5qb2luKHByb2plY3RCYXNlUGF0aCwgbG9ja0ZpbGUpO1xuXG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxvY2tGaWxlUGF0aCxcbiAgICAgICAgICBsb2NrRmlsZURhdGE6IHJlYWRGaWxlU3luYyhsb2NrRmlsZVBhdGgpLFxuICAgICAgICB9O1xuICAgICAgfSBjYXRjaCB7fVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGxvY2F0ZSBhIHBhY2thZ2UgbWFuYWdlciBsb2NrIGZpbGUuJyk7XG4gIH1cbn1cblxuY2xhc3MgTmdjY0xvZ2dlciBpbXBsZW1lbnRzIExvZ2dlciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29tcGlsYXRpb25XYXJuaW5nczogKEVycm9yIHwgc3RyaW5nKVtdLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29tcGlsYXRpb25FcnJvcnM6IChFcnJvciB8IHN0cmluZylbXSxcbiAgICBwdWJsaWMgbGV2ZWw6IExvZ0xldmVsLFxuICApIHt9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICBkZWJ1ZygpIHt9XG5cbiAgaW5mbyguLi5hcmdzOiBzdHJpbmdbXSkge1xuICAgIC8vIExvZyB0byBzdGRlcnIgYmVjYXVzZSBpdCdzIGEgcHJvZ3Jlc3MtbGlrZSBpbmZvIG1lc3NhZ2UuXG4gICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoYFxcbiR7YXJncy5qb2luKCcgJyl9XFxuYCk7XG4gIH1cblxuICB3YXJuKC4uLmFyZ3M6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5jb21waWxhdGlvbldhcm5pbmdzLnB1c2goYXJncy5qb2luKCcgJykpO1xuICB9XG5cbiAgZXJyb3IoLi4uYXJnczogc3RyaW5nW10pIHtcbiAgICB0aGlzLmNvbXBpbGF0aW9uRXJyb3JzLnB1c2gobmV3IEVycm9yKGFyZ3Muam9pbignICcpKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNSZWFkT25seUZpbGUoZmlsZU5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICB0cnkge1xuICAgIGFjY2Vzc1N5bmMoZmlsZU5hbWUsIGNvbnN0YW50cy5XX09LKTtcblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiJdfQ==