UNPKG

@angular/core

Version:

Angular - the core framework

146 lines • 22.6 kB
/** * @license * Copyright Google Inc. 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 */ (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define("@angular/core/schematics/migrations/undecorated-classes-with-decorated-fields/transform", ["require", "exports", "@angular/compiler-cli/src/ngtsc/partial_evaluator", "@angular/compiler-cli/src/ngtsc/reflection", "typescript", "@angular/core/schematics/utils/import_manager", "@angular/core/schematics/utils/ng_decorators", "@angular/core/schematics/utils/typescript/find_base_classes", "@angular/core/schematics/utils/typescript/functions"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const partial_evaluator_1 = require("@angular/compiler-cli/src/ngtsc/partial_evaluator"); const reflection_1 = require("@angular/compiler-cli/src/ngtsc/reflection"); const ts = require("typescript"); const import_manager_1 = require("@angular/core/schematics/utils/import_manager"); const ng_decorators_1 = require("@angular/core/schematics/utils/ng_decorators"); const find_base_classes_1 = require("@angular/core/schematics/utils/typescript/find_base_classes"); const functions_1 = require("@angular/core/schematics/utils/typescript/functions"); class UndecoratedClassesWithDecoratedFieldsTransform { constructor(typeChecker, getUpdateRecorder) { this.typeChecker = typeChecker; this.getUpdateRecorder = getUpdateRecorder; this.printer = ts.createPrinter(); this.importManager = new import_manager_1.ImportManager(this.getUpdateRecorder, this.printer); this.reflectionHost = new reflection_1.TypeScriptReflectionHost(this.typeChecker); this.partialEvaluator = new partial_evaluator_1.PartialEvaluator(this.reflectionHost, this.typeChecker, null); } /** * Migrates the specified source files. The transform adds the abstract `@Directive` * decorator to classes that have Angular field decorators but are not decorated. * https://hackmd.io/vuQfavzfRG6KUCtU7oK_EA */ migrate(sourceFiles) { this._findUndecoratedAbstractDirectives(sourceFiles).forEach(node => { const sourceFile = node.getSourceFile(); const recorder = this.getUpdateRecorder(sourceFile); const directiveExpr = this.importManager.addImportToSourceFile(sourceFile, 'Directive', '@angular/core'); const decoratorExpr = ts.createDecorator(ts.createCall(directiveExpr, undefined, undefined)); recorder.addClassDecorator(node, this.printer.printNode(ts.EmitHint.Unspecified, decoratorExpr, sourceFile)); }); } /** Records all changes that were made in the import manager. */ recordChanges() { this.importManager.recordChanges(); } /** Finds undecorated abstract directives in the specified source files. */ _findUndecoratedAbstractDirectives(sourceFiles) { const result = new Set(); const undecoratedClasses = new Set(); const nonAbstractDirectives = new WeakSet(); const abstractDirectives = new WeakSet(); const visitNode = (node) => { node.forEachChild(visitNode); if (!ts.isClassDeclaration(node)) { return; } const { isDirectiveOrComponent, isAbstractDirective, usesAngularFeatures } = this._analyzeClassDeclaration(node); if (isDirectiveOrComponent) { if (isAbstractDirective) { abstractDirectives.add(node); } else { nonAbstractDirectives.add(node); } } else if (usesAngularFeatures) { abstractDirectives.add(node); result.add(node); } else { undecoratedClasses.add(node); } }; sourceFiles.forEach(sourceFile => sourceFile.forEachChild(visitNode)); // We collected all undecorated class declarations which inherit from abstract directives. // For such abstract directives, the derived classes also need to be migrated. undecoratedClasses.forEach(node => { for (const { node: baseClass } of find_base_classes_1.findBaseClassDeclarations(node, this.typeChecker)) { // If the undecorated class inherits from a non-abstract directive, skip the current // class. We do this because undecorated classes which inherit metadata from non-abstract // directives are handle in the `undecorated-classes-with-di` migration that copies // inherited metadata into an explicit decorator. if (nonAbstractDirectives.has(baseClass)) { break; } else if (abstractDirectives.has(baseClass)) { result.add(node); break; } } }); return result; } /** * Analyzes the given class declaration by determining whether the class * is a directive, is an abstract directive, or uses Angular features. */ _analyzeClassDeclaration(node) { const ngDecorators = node.decorators && ng_decorators_1.getAngularDecorators(this.typeChecker, node.decorators); const usesAngularFeatures = this._hasAngularDecoratedClassMember(node); if (ngDecorators === undefined || ngDecorators.length === 0) { return { isDirectiveOrComponent: false, isAbstractDirective: false, usesAngularFeatures }; } const directiveDecorator = ngDecorators.find(({ name }) => name === 'Directive'); const componentDecorator = ngDecorators.find(({ name }) => name === 'Component'); const isAbstractDirective = directiveDecorator !== undefined && this._isAbstractDirective(directiveDecorator); return { isDirectiveOrComponent: !!directiveDecorator || !!componentDecorator, isAbstractDirective, usesAngularFeatures, }; } /** * Checks whether the given decorator resolves to an abstract directive. An directive is * considered "abstract" if there is no selector specified. */ _isAbstractDirective({ node }) { const metadataArgs = node.expression.arguments; if (metadataArgs.length === 0) { return true; } const metadataExpr = functions_1.unwrapExpression(metadataArgs[0]); if (!ts.isObjectLiteralExpression(metadataExpr)) { return false; } const metadata = reflection_1.reflectObjectLiteral(metadataExpr); if (!metadata.has('selector')) { return false; } const selector = this.partialEvaluator.evaluate(metadata.get('selector')); return selector == null; } _hasAngularDecoratedClassMember(node) { return node.members.some(m => m.decorators && ng_decorators_1.getAngularDecorators(this.typeChecker, m.decorators).length !== 0); } } exports.UndecoratedClassesWithDecoratedFieldsTransform = UndecoratedClassesWithDecoratedFieldsTransform; }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zY2hlbWF0aWNzL21pZ3JhdGlvbnMvdW5kZWNvcmF0ZWQtY2xhc3Nlcy13aXRoLWRlY29yYXRlZC1maWVsZHMvdHJhbnNmb3JtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7Ozs7O0lBRUgseUZBQW1GO0lBQ25GLDJFQUEwRztJQUMxRyxpQ0FBaUM7SUFFakMsa0ZBQXlEO0lBQ3pELGdGQUE0RTtJQUM1RSxtR0FBbUY7SUFDbkYsbUZBQWtFO0lBZWxFLE1BQWEsOENBQThDO1FBTXpELFlBQ1ksV0FBMkIsRUFDM0IsaUJBQXdEO1lBRHhELGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtZQUMzQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQXVDO1lBUDVELFlBQU8sR0FBRyxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDN0Isa0JBQWEsR0FBRyxJQUFJLDhCQUFhLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4RSxtQkFBYyxHQUFHLElBQUkscUNBQXdCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2hFLHFCQUFnQixHQUFHLElBQUksb0NBQWdCLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBSXRCLENBQUM7UUFFeEU7Ozs7V0FJRztRQUNILE9BQU8sQ0FBQyxXQUE0QjtZQUNsQyxJQUFJLENBQUMsa0NBQWtDLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUNsRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3hDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FB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TUFBTSxZQUFZLEdBQUcsNEJBQWdCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkQsSUFBSSxDQUFDLEVBQUUsQ0FBQyx5QkFBeUIsQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDL0MsT0FBTyxLQUFLLENBQUM7YUFDZDtZQUNELE1BQU0sUUFBUSxHQUFHLGlDQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFO2dCQUM3QixPQUFPLEtBQUssQ0FBQzthQUNkO1lBQ0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBRSxDQUFDLENBQUM7WUFDM0UsT0FBTyxRQUFRLElBQUksSUFBSSxDQUFDO1FBQzFCLENBQUM7UUFFTywrQkFBK0IsQ0FBQyxJQUF5QjtZQUMvRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUNwQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksb0NBQW9CLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzlGLENBQUM7S0FDRjtJQWhJRCx3R0FnSUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7UGFydGlhbEV2YWx1YXRvcn0gZnJvbSAnQGFuZ3VsYXIvY29tcGlsZXItY2xpL3NyYy9uZ3RzYy9wYXJ0aWFsX2V2YWx1YXRvcic7XG5pbXBvcnQge3JlZmxlY3RPYmplY3RMaXRlcmFsLCBUeXBlU2NyaXB0UmVmbGVjdGlvbkhvc3R9IGZyb20gJ0Bhbmd1bGFyL2NvbXBpbGVyLWNsaS9zcmMvbmd0c2MvcmVmbGVjdGlvbic7XG5pbXBvcnQgKiBhcyB0cyBmcm9tICd0eXBlc2NyaXB0JztcblxuaW1wb3J0IHtJbXBvcnRNYW5hZ2VyfSBmcm9tICcuLi8uLi91dGlscy9pbXBvcnRfbWFuYWdlcic7XG5pbXBvcnQge2dldEFuZ3VsYXJEZWNvcmF0b3JzLCBOZ0RlY29yYXRvcn0gZnJvbSAnLi4vLi4vdXRpbHMvbmdfZGVjb3JhdG9ycyc7XG5pbXBvcnQge2ZpbmRCYXNlQ2xhc3NEZWNsYXJhdGlvbnN9IGZyb20gJy4uLy4uL3V0aWxzL3R5cGVzY3JpcHQvZmluZF9iYXNlX2NsYXNzZXMnO1xuaW1wb3J0IHt1bndyYXBFeHByZXNzaW9ufSBmcm9tICcuLi8uLi91dGlscy90eXBlc2NyaXB0L2Z1bmN0aW9ucyc7XG5cbmltcG9ydCB7VXBkYXRlUmVjb3JkZXJ9IGZyb20gJy4vdXBkYXRlX3JlY29yZGVyJztcblxuXG4vKiogQW5hbHl6ZWQgY2xhc3MgZGVjbGFyYXRpb24uICovXG5pbnRlcmZhY2UgQW5hbHl6ZWRDbGFzcyB7XG4gIC8qKiBXaGV0aGVyIHRoZSBjbGFzcyBpcyBkZWNvcmF0ZWQgd2l0aCBARGlyZWN0aXZlIG9yIEBDb21wb25lbnQuICovXG4gIGlzRGlyZWN0aXZlT3JDb21wb25lbnQ6IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHRoZSBjbGFzcyBpcyBhbiBhYnN0cmFjdCBkaXJlY3RpdmUuICovXG4gIGlzQWJzdHJhY3REaXJlY3RpdmU6IGJvb2xlYW47XG4gIC8qKiBXaGV0aGVyIHRoZSBjbGFzcyB1c2VzIGFueSBBbmd1bGFyIGZlYXR1cmVzLiAqL1xuICB1c2VzQW5ndWxhckZlYXR1cmVzOiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgVW5kZWNvcmF0ZWRDbGFzc2VzV2l0aERlY29yYXRlZEZpZWxkc1RyYW5zZm9ybSB7XG4gIHByaXZhdGUgcHJpbnRlciA9IHRzLmNyZWF0ZVByaW50ZXIoKTtcbiAgcHJpdmF0ZSBpbXBvcnRNYW5hZ2VyID0gbmV3IEltcG9ydE1hbmFnZXIodGhpcy5nZXRVcGRhdGVSZWNvcmRlciwgdGhpcy5wcmludGVyKTtcbiAgcHJpdmF0ZSByZWZsZWN0aW9uSG9zdCA9IG5ldyBUeXBlU2NyaXB0UmVmbGVjdGlvbkhvc3QodGhpcy50eXBlQ2hlY2tlcik7XG4gIHByaXZhdGUgcGFydGlhbEV2YWx1YXRvciA9IG5ldyBQYXJ0aWFsRXZhbHVhdG9yKHRoaXMucmVmbGVjdGlvbkhvc3QsIHRoaXMudHlwZUNoZWNrZXIsIG51bGwpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHJpdmF0ZSB0eXBlQ2hlY2tlcjogdHMuVHlwZUNoZWNrZXIsXG4gICAgICBwcml2YXRlIGdldFVwZGF0ZVJlY29yZGVyOiAoc2Y6IHRzLlNvdXJjZUZpbGUpID0+IFVwZGF0ZVJlY29yZGVyKSB7fVxuXG4gIC8qKlxuICAgKiBNaWdyYXRlcyB0aGUgc3BlY2lmaWVkIHNvdXJjZSBmaWxlcy4gVGhlIHRyYW5zZm9ybSBhZGRzIHRoZSBhYnN0cmFjdCBgQERpcmVjdGl2ZWBcbiAgICogZGVjb3JhdG9yIHRvIGNsYXNzZXMgdGhhdCBoYXZlIEFuZ3VsYXIgZmllbGQgZGVjb3JhdG9ycyBidXQgYXJlIG5vdCBkZWNvcmF0ZWQuXG4gICAqIGh0dHBzOi8vaGFja21kLmlvL3Z1UWZhdnpmUkc2S1VDdFU3b0tfRUFcbiAgICovXG4gIG1pZ3JhdGUoc291cmNlRmlsZXM6IHRzLlNvdXJjZUZpbGVbXSkge1xuICAgIHRoaXMuX2ZpbmRVbmRlY29yYXRlZEFic3RyYWN0RGlyZWN0aXZlcyhzb3VyY2VGaWxlcykuZm9yRWFjaChub2RlID0+IHtcbiAgICAgIGNvbnN0IHNvdXJjZUZpbGUgPSBub2RlLmdldFNvdXJjZUZpbGUoKTtcbiAgICAgIGNvbnN0IHJlY29yZGVyID0gdGhpcy5nZXRVcGRhdGVSZWNvcmRlcihzb3VyY2VGaWxlKTtcbiAgICAgIGNvbnN0IGRpcmVjdGl2ZUV4cHIgPVxuICAgICAgICAgIHRoaXMuaW1wb3J0TWFuYWdlci5hZGRJbXBvcnRUb1NvdXJjZUZpbGUoc291cmNlRmlsZSwgJ0RpcmVjdGl2ZScsICdAYW5ndWxhci9jb3JlJyk7XG4gICAgICBjb25zdCBkZWNvcmF0b3JFeHByID0gdHMuY3JlYXRlRGVjb3JhdG9yKHRzLmNyZWF0ZUNhbGwoZGlyZWN0aXZlRXhwciwgdW5kZWZpbmVkLCB1bmRlZmluZWQpKTtcbiAgICAgIHJlY29yZGVyLmFkZENsYXNzRGVjb3JhdG9yKFxuICAgICAgICAgIG5vZGUsIHRoaXMucHJpbnRlci5wcmludE5vZGUodHMuRW1pdEhpbnQuVW5zcGVjaWZpZWQsIGRlY29yYXRvckV4cHIsIHNvdXJjZUZpbGUpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBSZWNvcmRzIGFsbCBjaGFuZ2VzIHRoYXQgd2VyZSBtYWRlIGluIHRoZSBpbXBvcnQgbWFuYWdlci4gKi9cbiAgcmVjb3JkQ2hhbmdlcygpIHtcbiAgICB0aGlzLmltcG9ydE1hbmFnZXIucmVjb3JkQ2hhbmdlcygpO1xuICB9XG5cbiAgLyoqIEZpbmRzIHVuZGVjb3JhdGVkIGFic3RyYWN0IGRpcmVjdGl2ZXMgaW4gdGhlIHNwZWNpZmllZCBzb3VyY2UgZmlsZXMuICovXG4gIHByaXZhdGUgX2ZpbmRVbmRlY29yYXRlZEFic3RyYWN0RGlyZWN0aXZlcyhzb3VyY2VGaWxlczogdHMuU291cmNlRmlsZVtdKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IFNldDx0cy5DbGFzc0RlY2xhcmF0aW9uPigpO1xuICAgIGNvbnN0IHVuZGVjb3JhdGVkQ2xhc3NlcyA9IG5ldyBTZXQ8dHMuQ2xhc3NEZWNsYXJhdGlvbj4oKTtcbiAgICBjb25zdCBub25BYnN0cmFjdERpcmVjdGl2ZXMgPSBuZXcgV2Vha1NldDx0cy5DbGFzc0RlY2xhcmF0aW9uPigpO1xuICAgIGNvbnN0IGFic3RyYWN0RGlyZWN0aXZlcyA9IG5ldyBXZWFrU2V0PHRzLkNsYXNzRGVjbGFyYXRpb24+KCk7XG5cbiAgICBjb25zdCB2aXNpdE5vZGUgPSAobm9kZTogdHMuTm9kZSkgPT4ge1xuICAgICAgbm9kZS5mb3JFYWNoQ2hpbGQodmlzaXROb2RlKTtcbiAgICAgIGlmICghdHMuaXNDbGFzc0RlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHtpc0RpcmVjdGl2ZU9yQ29tcG9uZW50LCBpc0Fic3RyYWN0RGlyZWN0aXZlLCB1c2VzQW5ndWxhckZlYXR1cmVzfSA9XG4gICAgICAgICAgdGhpcy5fYW5hbHl6ZUNsYXNzRGVjbGFyYXRpb24obm9kZSk7XG4gICAgICBpZiAoaXNEaXJlY3RpdmVPckNvbXBvbmVudCkge1xuICAgICAgICBpZiAoaXNBYnN0cmFjdERpcmVjdGl2ZSkge1xuICAgICAgICAgIGFic3RyYWN0RGlyZWN0aXZlcy5hZGQobm9kZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbm9uQWJzdHJhY3REaXJlY3RpdmVzLmFkZChub2RlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh1c2VzQW5ndWxhckZlYXR1cmVzKSB7XG4gICAgICAgIGFic3RyYWN0RGlyZWN0aXZlcy5hZGQobm9kZSk7XG4gICAgICAgIHJlc3VsdC5hZGQobm9kZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1bmRlY29yYXRlZENsYXNzZXMuYWRkKG5vZGUpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBzb3VyY2VGaWxlcy5mb3JFYWNoKHNvdXJjZUZpbGUgPT4gc291cmNlRmlsZS5mb3JFYWNoQ2hpbGQodmlzaXROb2RlKSk7XG5cbiAgICAvLyBXZSBjb2xsZWN0ZWQgYWxsIHVuZGVjb3JhdGVkIGNsYXNzIGRlY2xhcmF0aW9ucyB3aGljaCBpbmhlcml0IGZyb20gYWJzdHJhY3QgZGlyZWN0aXZlcy5cbiAgICAvLyBGb3Igc3VjaCBhYnN0cmFjdCBkaXJlY3RpdmVzLCB0aGUgZGVyaXZlZCBjbGFzc2VzIGFsc28gbmVlZCB0byBiZSBtaWdyYXRlZC5cbiAgICB1bmRlY29yYXRlZENsYXNzZXMuZm9yRWFjaChub2RlID0+IHtcbiAgICAgIGZvciAoY29uc3Qge25vZGU6IGJhc2VDbGFzc30gb2YgZmluZEJhc2VDbGFzc0RlY2xhcmF0aW9ucyhub2RlLCB0aGlzLnR5cGVDaGVja2VyKSkge1xuICAgICAgICAvLyBJZiB0aGUgdW5kZWNvcmF0ZWQgY2xhc3MgaW5oZXJpdHMgZnJvbSBhIG5vbi1hYnN0cmFjdCBkaXJlY3RpdmUsIHNraXAgdGhlIGN1cnJlbnRcbiAgICAgICAgLy8gY2xhc3MuIFdlIGRvIHRoaXMgYmVjYXVzZSB1bmRlY29yYXRlZCBjbGFzc2VzIHdoaWNoIGluaGVyaXQgbWV0YWRhdGEgZnJvbSBub24tYWJzdHJhY3RcbiAgICAgICAgLy8gZGlyZWN0aXZlcyBhcmUgaGFuZGxlIGluIHRoZSBgdW5kZWNvcmF0ZWQtY2xhc3Nlcy13aXRoLWRpYCBtaWdyYXRpb24gdGhhdCBjb3BpZXNcbiAgICAgICAgLy8gaW5oZXJpdGVkIG1ldGFkYXRhIGludG8gYW4gZXhwbGljaXQgZGVjb3JhdG9yLlxuICAgICAgICBpZiAobm9uQWJzdHJhY3REaXJlY3RpdmVzLmhhcyhiYXNlQ2xhc3MpKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gZWxzZSBpZiAoYWJzdHJhY3REaXJlY3RpdmVzLmhhcyhiYXNlQ2xhc3MpKSB7XG4gICAgICAgICAgcmVzdWx0LmFkZChub2RlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbmFseXplcyB0aGUgZ2l2ZW4gY2xhc3MgZGVjbGFyYXRpb24gYnkgZGV0ZXJtaW5pbmcgd2hldGhlciB0aGUgY2xhc3NcbiAgICogaXMgYSBkaXJlY3RpdmUsIGlzIGFuIGFic3RyYWN0IGRpcmVjdGl2ZSwgb3IgdXNlcyBBbmd1bGFyIGZlYXR1cmVzLlxuICAgKi9cbiAgcHJpdmF0ZSBfYW5hbHl6ZUNsYXNzRGVjbGFyYXRpb24obm9kZTogdHMuQ2xhc3NEZWNsYXJhdGlvbik6IEFuYWx5emVkQ2xhc3Mge1xuICAgIGNvbnN0IG5nRGVjb3JhdG9ycyA9IG5vZGUuZGVjb3JhdG9ycyAmJiBnZXRBbmd1bGFyRGVjb3JhdG9ycyh0aGlzLnR5cGVDaGVja2VyLCBub2RlLmRlY29yYXRvcnMpO1xuICAgIGNvbnN0IHVzZXNBbmd1bGFyRmVhdHVyZXMgPSB0aGlzLl9oYXNBbmd1bGFyRGVjb3JhdGVkQ2xhc3NNZW1iZXIobm9kZSk7XG4gICAgaWYgKG5nRGVjb3JhdG9ycyA9PT0gdW5kZWZpbmVkIHx8IG5nRGVjb3JhdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB7aXNEaXJlY3RpdmVPckNvbXBvbmVudDogZmFsc2UsIGlzQWJzdHJhY3REaXJlY3RpdmU6IGZhbHNlLCB1c2VzQW5ndWxhckZlYXR1cmVzfTtcbiAgICB9XG4gICAgY29uc3QgZGlyZWN0aXZlRGVjb3JhdG9yID0gbmdEZWNvcmF0b3JzLmZpbmQoKHtuYW1lfSkgPT4gbmFtZSA9PT0gJ0RpcmVjdGl2ZScpO1xuICAgIGNvbnN0IGNvbXBvbmVudERlY29yYXRvciA9IG5nRGVjb3JhdG9ycy5maW5kKCh7bmFtZX0pID0+IG5hbWUgPT09ICdDb21wb25lbnQnKTtcbiAgICBjb25zdCBpc0Fic3RyYWN0RGlyZWN0aXZlID1cbiAgICAgICAgZGlyZWN0aXZlRGVjb3JhdG9yICE9PSB1bmRlZmluZWQgJiYgdGhpcy5faXNBYnN0cmFjdERpcmVjdGl2ZShkaXJlY3RpdmVEZWNvcmF0b3IpO1xuICAgIHJldHVybiB7XG4gICAgICBpc0RpcmVjdGl2ZU9yQ29tcG9uZW50OiAhIWRpcmVjdGl2ZURlY29yYXRvciB8fCAhIWNvbXBvbmVudERlY29yYXRvcixcbiAgICAgIGlzQWJzdHJhY3REaXJlY3RpdmUsXG4gICAgICB1c2VzQW5ndWxhckZlYXR1cmVzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGdpdmVuIGRlY29yYXRvciByZXNvbHZlcyB0byBhbiBhYnN0cmFjdCBkaXJlY3RpdmUuIEFuIGRpcmVjdGl2ZSBpc1xuICAgKiBjb25zaWRlcmVkIFwiYWJzdHJhY3RcIiBpZiB0aGVyZSBpcyBubyBzZWxlY3RvciBzcGVjaWZpZWQuXG4gICAqL1xuICBwcml2YXRlIF9pc0Fic3RyYWN0RGlyZWN0aXZlKHtub2RlfTogTmdEZWNvcmF0b3IpOiBib29sZWFuIHtcbiAgICBjb25zdCBtZXRhZGF0YUFyZ3MgPSBub2RlLmV4cHJlc3Npb24uYXJndW1lbnRzO1xuICAgIGlmIChtZXRhZGF0YUFyZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgbWV0YWRhdGFFeHByID0gdW53cmFwRXhwcmVzc2lvbihtZXRhZGF0YUFyZ3NbMF0pO1xuICAgIGlmICghdHMuaXNPYmplY3RMaXRlcmFsRXhwcmVzc2lvbihtZXRhZGF0YUV4cHIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IG1ldGFkYXRhID0gcmVmbGVjdE9iamVjdExpdGVyYWwobWV0YWRhdGFFeHByKTtcbiAgICBpZiAoIW1ldGFkYXRhLmhhcygnc2VsZWN0b3InKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBzZWxlY3RvciA9IHRoaXMucGFydGlhbEV2YWx1YXRvci5ldmFsdWF0ZShtZXRhZGF0YS5nZXQoJ3NlbGVjdG9yJykhKTtcbiAgICByZXR1cm4gc2VsZWN0b3IgPT0gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2hhc0FuZ3VsYXJEZWNvcmF0ZWRDbGFzc01lbWJlcihub2RlOiB0cy5DbGFzc0RlY2xhcmF0aW9uKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIG5vZGUubWVtYmVycy5zb21lKFxuICAgICAgICBtID0+IG0uZGVjb3JhdG9ycyAmJiBnZXRBbmd1bGFyRGVjb3JhdG9ycyh0aGlzLnR5cGVDaGVja2VyLCBtLmRlY29yYXRvcnMpLmxlbmd0aCAhPT0gMCk7XG4gIH1cbn1cbiJdfQ==