@angular/core
Version:
Angular - the core framework
369 lines • 65.1 kB
JavaScript
/**
* @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
*/
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
(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-di/transform", ["require", "exports", "@angular/core", "typescript", "@angular/core/schematics/utils/import_manager", "@angular/core/schematics/utils/ng_decorators", "@angular/core/schematics/utils/typescript/class_declaration", "@angular/core/schematics/utils/typescript/find_base_classes", "@angular/core/schematics/utils/typescript/imports", "@angular/core/schematics/migrations/undecorated-classes-with-di/decorator_rewrite/convert_directive_metadata", "@angular/core/schematics/migrations/undecorated-classes-with-di/decorator_rewrite/decorator_rewriter", "@angular/core/schematics/migrations/undecorated-classes-with-di/ng_declaration_collector"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@angular/core");
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 class_declaration_1 = require("@angular/core/schematics/utils/typescript/class_declaration");
const find_base_classes_1 = require("@angular/core/schematics/utils/typescript/find_base_classes");
const imports_1 = require("@angular/core/schematics/utils/typescript/imports");
const convert_directive_metadata_1 = require("@angular/core/schematics/migrations/undecorated-classes-with-di/decorator_rewrite/convert_directive_metadata");
const decorator_rewriter_1 = require("@angular/core/schematics/migrations/undecorated-classes-with-di/decorator_rewrite/decorator_rewriter");
const ng_declaration_collector_1 = require("@angular/core/schematics/migrations/undecorated-classes-with-di/ng_declaration_collector");
class UndecoratedClassesTransform {
constructor(typeChecker, compiler, evaluator, getUpdateRecorder) {
this.typeChecker = typeChecker;
this.compiler = compiler;
this.evaluator = evaluator;
this.getUpdateRecorder = getUpdateRecorder;
this.printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
this.importManager = new import_manager_1.ImportManager(this.getUpdateRecorder, this.printer);
this.decoratorRewriter = new decorator_rewriter_1.DecoratorRewriter(this.importManager, this.typeChecker, this.evaluator, this.compiler);
/** Set of class declarations which have been decorated with "@Directive". */
this.decoratedDirectives = new Set();
/** Set of class declarations which have been decorated with "@Injectable" */
this.decoratedProviders = new Set();
/**
* Set of class declarations which have been analyzed and need to specify
* an explicit constructor.
*/
this.missingExplicitConstructorClasses = new Set();
this.symbolResolver = compiler['_symbolResolver'];
this.compilerHost = compiler['_host'];
this.metadataResolver = compiler['_metadataResolver'];
// Unset the default error recorder so that the reflector will throw an exception
// if metadata cannot be resolved.
this.compiler.reflector['errorRecorder'] = undefined;
// Disables that static symbols are resolved through summaries from within the static
// reflector. Summaries cannot be used for decorator serialization as decorators are
// omitted in summaries and the decorator can't be reconstructed from the directive summary.
this._disableSummaryResolution();
}
/**
* Migrates decorated directives which can potentially inherit a constructor
* from an undecorated base class. All base classes until the first one
* with an explicit constructor will be decorated with the abstract "@Directive()"
* decorator. See case 1 in the migration plan: https://hackmd.io/@alx/S1XKqMZeS
*/
migrateDecoratedDirectives(directives) {
return directives.reduce((failures, node) => failures.concat(this._migrateDirectiveBaseClass(node)), []);
}
/**
* Migrates decorated providers which can potentially inherit a constructor
* from an undecorated base class. All base classes until the first one
* with an explicit constructor will be decorated with the "@Injectable()".
*/
migrateDecoratedProviders(providers) {
return providers.reduce((failures, node) => failures.concat(this._migrateProviderBaseClass(node)), []);
}
_migrateProviderBaseClass(node) {
return this._migrateDecoratedClassWithInheritedCtor(node, symbol => this.metadataResolver.isInjectable(symbol), node => this._addInjectableDecorator(node));
}
_migrateDirectiveBaseClass(node) {
return this._migrateDecoratedClassWithInheritedCtor(node, symbol => this.metadataResolver.isDirective(symbol), node => this._addAbstractDirectiveDecorator(node));
}
_migrateDecoratedClassWithInheritedCtor(node, isClassDecorated, addClassDecorator) {
// In case the provider has an explicit constructor, we don't need to do anything
// because the class is already decorated and does not inherit a constructor.
if (class_declaration_1.hasExplicitConstructor(node)) {
return [];
}
const orderedBaseClasses = find_base_classes_1.findBaseClassDeclarations(node, this.typeChecker);
const undecoratedBaseClasses = [];
for (let { node: baseClass, identifier } of orderedBaseClasses) {
const baseClassFile = baseClass.getSourceFile();
if (class_declaration_1.hasExplicitConstructor(baseClass)) {
// All classes in between the decorated class and the undecorated class
// that defines the constructor need to be decorated as well.
undecoratedBaseClasses.forEach(b => addClassDecorator(b));
if (baseClassFile.isDeclarationFile) {
const staticSymbol = this._getStaticSymbolOfIdentifier(identifier);
// If the base class is decorated through metadata files, we don't
// need to add a comment to the derived class for the external base class.
if (staticSymbol && isClassDecorated(staticSymbol)) {
break;
}
// Find the last class in the inheritance chain that is decorated and will be
// used as anchor for a comment explaining that the class that defines the
// constructor cannot be decorated automatically.
const lastDecoratedClass = undecoratedBaseClasses[undecoratedBaseClasses.length - 1] || node;
return this._addMissingExplicitConstructorTodo(lastDecoratedClass);
}
// Decorate the class that defines the constructor that is inherited.
addClassDecorator(baseClass);
break;
}
// Add the class decorator for all base classes in the inheritance chain until
// the base class with the explicit constructor. The decorator will be only
// added for base classes which can be modified.
if (!baseClassFile.isDeclarationFile) {
undecoratedBaseClasses.push(baseClass);
}
}
return [];
}
/**
* Adds the abstract "@Directive()" decorator to the given class in case there
* is no existing directive decorator.
*/
_addAbstractDirectiveDecorator(baseClass) {
if (ng_declaration_collector_1.hasDirectiveDecorator(baseClass, this.typeChecker) ||
this.decoratedDirectives.has(baseClass)) {
return;
}
const baseClassFile = baseClass.getSourceFile();
const recorder = this.getUpdateRecorder(baseClassFile);
const directiveExpr = this.importManager.addImportToSourceFile(baseClassFile, 'Directive', '@angular/core');
const newDecorator = ts.createDecorator(ts.createCall(directiveExpr, undefined, []));
const newDecoratorText = this.printer.printNode(ts.EmitHint.Unspecified, newDecorator, baseClassFile);
recorder.addClassDecorator(baseClass, newDecoratorText);
this.decoratedDirectives.add(baseClass);
}
/**
* Adds the abstract "@Injectable()" decorator to the given class in case there
* is no existing directive decorator.
*/
_addInjectableDecorator(baseClass) {
if (ng_declaration_collector_1.hasInjectableDecorator(baseClass, this.typeChecker) ||
this.decoratedProviders.has(baseClass)) {
return;
}
const baseClassFile = baseClass.getSourceFile();
const recorder = this.getUpdateRecorder(baseClassFile);
const injectableExpr = this.importManager.addImportToSourceFile(baseClassFile, 'Injectable', '@angular/core');
const newDecorator = ts.createDecorator(ts.createCall(injectableExpr, undefined, []));
const newDecoratorText = this.printer.printNode(ts.EmitHint.Unspecified, newDecorator, baseClassFile);
recorder.addClassDecorator(baseClass, newDecoratorText);
this.decoratedProviders.add(baseClass);
}
/** Adds a comment for adding an explicit constructor to the given class declaration. */
_addMissingExplicitConstructorTodo(node) {
// In case a todo comment has been already inserted to the given class, we don't
// want to add a comment or transform failure multiple times.
if (this.missingExplicitConstructorClasses.has(node)) {
return [];
}
this.missingExplicitConstructorClasses.add(node);
const recorder = this.getUpdateRecorder(node.getSourceFile());
recorder.addClassComment(node, 'TODO: add explicit constructor');
return [{ node: node, message: 'Class needs to declare an explicit constructor.' }];
}
/**
* Migrates undecorated directives which were referenced in NgModule declarations.
* These directives inherit the metadata from a parent base class, but with Ivy
* these classes need to explicitly have a decorator for locality. The migration
* determines the inherited decorator and copies it to the undecorated declaration.
*
* Note that the migration serializes the metadata for external declarations
* where the decorator is not part of the source file AST.
*
* See case 2 in the migration plan: https://hackmd.io/@alx/S1XKqMZeS
*/
migrateUndecoratedDeclarations(directives) {
return directives.reduce((failures, node) => failures.concat(this._migrateDerivedDeclaration(node)), []);
}
_migrateDerivedDeclaration(node) {
const targetSourceFile = node.getSourceFile();
const orderedBaseClasses = find_base_classes_1.findBaseClassDeclarations(node, this.typeChecker);
let newDecoratorText = null;
for (let { node: baseClass, identifier } of orderedBaseClasses) {
// Before looking for decorators within the metadata or summary files, we
// try to determine the directive decorator through the source file AST.
if (baseClass.decorators) {
const ngDecorator = ng_decorators_1.getAngularDecorators(this.typeChecker, baseClass.decorators)
.find(({ name }) => name === 'Component' || name === 'Directive' || name === 'Pipe');
if (ngDecorator) {
const newDecorator = this.decoratorRewriter.rewrite(ngDecorator, node.getSourceFile());
newDecoratorText = this.printer.printNode(ts.EmitHint.Unspecified, newDecorator, ngDecorator.node.getSourceFile());
break;
}
}
// If no metadata could be found within the source-file AST, try to find
// decorator data through Angular metadata and summary files.
const staticSymbol = this._getStaticSymbolOfIdentifier(identifier);
// Check if the static symbol resolves to a class declaration with
// pipe or directive metadata.
if (!staticSymbol ||
!(this.metadataResolver.isPipe(staticSymbol) ||
this.metadataResolver.isDirective(staticSymbol))) {
continue;
}
const metadata = this._resolveDeclarationMetadata(staticSymbol);
// If no metadata could be resolved for the static symbol, print a failure message
// and ask the developer to manually migrate the class. This case is rare because
// usually decorator metadata is always present but just can't be read if a program
// only has access to summaries (this is a special case in google3).
if (!metadata) {
return [{
node,
message: `Class cannot be migrated as the inherited metadata from ` +
`${identifier.getText()} cannot be converted into a decorator. Please manually
decorate the class.`,
}];
}
const newDecorator = this._constructDecoratorFromMetadata(metadata, targetSourceFile);
if (!newDecorator) {
const annotationType = metadata.type;
return [{
node,
message: `Class cannot be migrated as the inherited @${annotationType} decorator ` +
`cannot be copied. Please manually add a @${annotationType} decorator.`,
}];
}
// In case the decorator could be constructed from the resolved metadata, use
// that decorator for the derived undecorated classes.
newDecoratorText =
this.printer.printNode(ts.EmitHint.Unspecified, newDecorator, targetSourceFile);
break;
}
if (!newDecoratorText) {
return [{
node,
message: 'Class cannot be migrated as no directive/component/pipe metadata could be found. ' +
'Please manually add a @Directive, @Component or @Pipe decorator.'
}];
}
this.getUpdateRecorder(targetSourceFile).addClassDecorator(node, newDecoratorText);
return [];
}
/** Records all changes that were made in the import manager. */
recordChanges() {
this.importManager.recordChanges();
}
/**
* Constructs a TypeScript decorator node from the specified declaration metadata. Returns
* null if the metadata could not be simplified/resolved.
*/
_constructDecoratorFromMetadata(directiveMetadata, targetSourceFile) {
try {
const decoratorExpr = convert_directive_metadata_1.convertDirectiveMetadataToExpression(directiveMetadata.metadata, staticSymbol => this.compilerHost
.fileNameToModuleName(staticSymbol.filePath, targetSourceFile.fileName)
.replace(/\/index$/, ''), (moduleName, name) => this.importManager.addImportToSourceFile(targetSourceFile, name, moduleName), (propertyName, value) => {
// Only normalize properties called "changeDetection" and "encapsulation"
// for "@Directive" and "@Component" annotations.
if (directiveMetadata.type === 'Pipe') {
return null;
}
// Instead of using the number as value for the "changeDetection" and
// "encapsulation" properties, we want to use the actual enum symbols.
if (propertyName === 'changeDetection' && typeof value === 'number') {
return ts.createPropertyAccess(this.importManager.addImportToSourceFile(targetSourceFile, 'ChangeDetectionStrategy', '@angular/core'), core_1.ChangeDetectionStrategy[value]);
}
else if (propertyName === 'encapsulation' && typeof value === 'number') {
return ts.createPropertyAccess(this.importManager.addImportToSourceFile(targetSourceFile, 'ViewEncapsulation', '@angular/core'), core_1.ViewEncapsulation[value]);
}
return null;
});
return ts.createDecorator(ts.createCall(this.importManager.addImportToSourceFile(targetSourceFile, directiveMetadata.type, '@angular/core'), undefined, [decoratorExpr]));
}
catch (e) {
if (e instanceof convert_directive_metadata_1.UnexpectedMetadataValueError) {
return null;
}
throw e;
}
}
/**
* Resolves the declaration metadata of a given static symbol. The metadata
* is determined by resolving metadata for the static symbol.
*/
_resolveDeclarationMetadata(symbol) {
try {
// Note that this call can throw if the metadata is not computable. In that
// case we are not able to serialize the metadata into a decorator and we return
// null.
const annotations = this.compiler.reflector.annotations(symbol).find(s => s.ngMetadataName === 'Component' || s.ngMetadataName === 'Directive' ||
s.ngMetadataName === 'Pipe');
if (!annotations) {
return null;
}
const { ngMetadataName } = annotations, metadata = __rest(annotations, ["ngMetadataName"]);
// Delete the "ngMetadataName" property as we don't want to generate
// a property assignment in the new decorator for that internal property.
delete metadata['ngMetadataName'];
return { type: ngMetadataName, metadata };
}
catch (e) {
return null;
}
}
_getStaticSymbolOfIdentifier(node) {
const sourceFile = node.getSourceFile();
const resolvedImport = imports_1.getImportOfIdentifier(this.typeChecker, node);
if (!resolvedImport) {
return null;
}
const moduleName = this.compilerHost.moduleNameToFileName(resolvedImport.importModule, sourceFile.fileName);
if (!moduleName) {
return null;
}
// Find the declaration symbol as symbols could be aliased due to
// metadata re-exports.
return this.compiler.reflector.findSymbolDeclaration(this.symbolResolver.getStaticSymbol(moduleName, resolvedImport.name));
}
/**
* Disables that static symbols are resolved through summaries. Summaries
* cannot be used for decorator analysis as decorators are omitted in summaries.
*/
_disableSummaryResolution() {
// We never want to resolve symbols through summaries. Summaries never contain
// decorators for class symbols and therefore summaries will cause every class
// to be considered as undecorated. See reason for this in: "ToJsonSerializer".
// In order to ensure that metadata is not retrieved through summaries, we
// need to disable summary resolution, clear previous symbol caches. This way
// future calls to "StaticReflector#annotations" are based on metadata files.
this.symbolResolver['_resolveSymbolFromSummary'] = () => null;
this.symbolResolver['resolvedSymbols'].clear();
this.symbolResolver['symbolFromFile'].clear();
this.compiler.reflector['annotationCache'].clear();
// Original summary resolver used by the AOT compiler.
const summaryResolver = this.symbolResolver['summaryResolver'];
// Additionally we need to ensure that no files are treated as "library" files when
// resolving metadata. This is necessary because by default the symbol resolver discards
// class metadata for library files. See "StaticSymbolResolver#createResolvedSymbol".
// Patching this function **only** for the static symbol resolver ensures that metadata
// is not incorrectly omitted. Note that we only want to do this for the symbol resolver
// because otherwise we could break the summary loading logic which is used to detect
// if a static symbol is either a directive, component or pipe (see MetadataResolver).
this.symbolResolver['summaryResolver'] = {
fromSummaryFileName: summaryResolver.fromSummaryFileName.bind(summaryResolver),
addSummary: summaryResolver.addSummary.bind(summaryResolver),
getImportAs: summaryResolver.getImportAs.bind(summaryResolver),
getKnownModuleName: summaryResolver.getKnownModuleName.bind(summaryResolver),
resolveSummary: summaryResolver.resolveSummary.bind(summaryResolver),
toSummaryFileName: summaryResolver.toSummaryFileName.bind(summaryResolver),
getSymbolsOf: summaryResolver.getSymbolsOf.bind(summaryResolver),
isLibraryFile: () => false,
};
}
}
exports.UndecoratedClassesTransform = UndecoratedClassesTransform;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmb3JtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zY2hlbWF0aWNzL21pZ3JhdGlvbnMvdW5kZWNvcmF0ZWQtY2xhc3Nlcy13aXRoLWRpL3RyYW5zZm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBSUgsd0NBQXlFO0lBQ3pFLGlDQUFpQztJQUVqQyxrRkFBeUQ7SUFDekQsZ0ZBQStEO0lBQy9ELG1HQUFnRjtJQUNoRixtR0FBbUY7SUFDbkYsK0VBQXFFO0lBRXJFLDZKQUFrSTtJQUNsSSw2SUFBeUU7SUFDekUsdUlBQXlGO0lBZ0J6RixNQUFhLDJCQUEyQjtRQW9CdEMsWUFDWSxXQUEyQixFQUFVLFFBQXFCLEVBQzFELFNBQTJCLEVBQzNCLGlCQUF3RDtZQUZ4RCxnQkFBVyxHQUFYLFdBQVcsQ0FBZ0I7WUFBVSxhQUFRLEdBQVIsUUFBUSxDQUFhO1lBQzFELGNBQVMsR0FBVCxTQUFTLENBQWtCO1lBQzNCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBdUM7WUF0QjVELFlBQU8sR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFDLENBQUMsQ0FBQztZQUMvRCxrQkFBYSxHQUFHLElBQUksOEJBQWEsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3hFLHNCQUFpQixHQUNyQixJQUFJLHNDQUFpQixDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQU0vRiw2RUFBNkU7WUFDckUsd0JBQW1CLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7WUFDN0QsNkVBQTZFO1lB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LGVBQWUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFFL0QsbUZBQW1GO1lBQ25GLHdGQUF3RjtZQUN4RixxRkFBcUY7WUFDckYsdUZBQXVGO1lBQ3ZGLHdGQUF3RjtZQUN4RixxRkFBcUY7WUFDckYsc0ZBQXNGO1lBQ3RGLElBQUksQ0FBQyxjQUFjLENBQUMsaUJBQWlCLENBQUMsR0FBa0M7Z0JBQ3RFLG1CQUFtQixFQUFFLGVBQWUsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO2dCQUM5RSxVQUFVLEVBQUUsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO2dCQUM1RCxXQUFXLEVBQUUsZUFBZSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO2dCQUM5RCxrQkFBa0IsRUFBRSxlQUFlLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztnQkFDNUUsY0FBYyxFQUFFLGVBQWUsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztnQkFDcEUsaUJBQWlCLEVBQUUsZUFBZSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7Z0JBQzFFLFlBQVksRUFBRSxlQUFlLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7Z0JBQ2hFLGFBQWEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLO2FBQzNCLENBQUM7UUFDSixDQUFDO0tBQ0Y7SUF0YUQsa0VBc2FDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0FvdENvbXBpbGVyLCBBb3RDb21waWxlckhvc3QsIENvbXBpbGVNZXRhZGF0YVJlc29sdmVyLCBTdGF0aWNTeW1ib2wsIFN0YXRpY1N5bWJvbFJlc29sdmVyLCBTdW1tYXJ5UmVzb2x2ZXJ9IGZyb20gJ0Bhbmd1bGFyL2NvbXBpbGVyJztcbmltcG9ydCB7UGFydGlhbEV2YWx1YXRvcn0gZnJvbSAnQGFuZ3VsYXIvY29tcGlsZXItY2xpL3NyYy9uZ3RzYy9wYXJ0aWFsX2V2YWx1YXRvcic7XG5pbXBvcnQge0NoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBWaWV3RW5jYXBzdWxhdGlvbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyB0cyBmcm9tICd0eXBlc2NyaXB0JztcblxuaW1wb3J0IHtJbXBvcnRNYW5hZ2VyfSBmcm9tICcuLi8uLi91dGlscy9pbXBvcnRfbWFuYWdlcic7XG5pbXBvcnQge2dldEFuZ3VsYXJEZWNvcmF0b3JzfSBmcm9tICcuLi8uLi91dGlscy9uZ19kZWNvcmF0b3JzJztcbmltcG9ydCB7aGFzRXhwbGljaXRDb25zdHJ1Y3Rvcn0gZnJvbSAnLi4vLi4vdXRpbHMvdHlwZXNjcmlwdC9jbGFzc19kZWNsYXJhdGlvbic7XG5pbXBvcnQge2ZpbmRCYXNlQ2xhc3NEZWNsYXJhdGlvbnN9IGZyb20gJy4uLy4uL3V0aWxzL3R5cGVzY3JpcHQvZmluZF9iYXNlX2NsYXNzZXMnO1xuaW1wb3J0IHtnZXRJbXBvcnRPZklkZW50aWZpZXJ9IGZyb20gJy4uLy4uL3V0aWxzL3R5cGVzY3JpcHQvaW1wb3J0cyc7XG5cbmltcG9ydCB7Y29udmVydERpcmVjdGl2ZU1ldGFkYXRhVG9FeHByZXNzaW9uLCBVbmV4cGVjdGVkTWV0YWRhdGFWYWx1ZUVycm9yfSBmcm9tICcuL2RlY29yYXRvcl9yZXdyaXRlL2NvbnZlcnRfZGlyZWN0aXZlX21ldGFkYXRhJztcbmltcG9ydCB7RGVjb3JhdG9yUmV3cml0ZXJ9IGZyb20gJy4vZGVjb3JhdG9yX3Jld3JpdGUvZGVjb3JhdG9yX3Jld3JpdGVyJztcbmltcG9ydCB7aGFzRGlyZWN0aXZlRGVjb3JhdG9yLCBoYXNJbmplY3RhYmxlRGVjb3JhdG9yfSBmcm9tICcuL25nX2RlY2xhcmF0aW9uX2NvbGxlY3Rvcic7XG5pbXBvcnQge1VwZGF0ZVJlY29yZGVyfSBmcm9tICcuL3VwZGF0ZV9yZWNvcmRlcic7XG5cblxuXG4vKiogUmVzb2x2ZWQgbWV0YWRhdGEgb2YgYSBkZWNsYXJhdGlvbi4gKi9cbmludGVyZmFjZSBEZWNsYXJhdGlvbk1ldGFkYXRhIHtcbiAgbWV0YWRhdGE6IGFueTtcbiAgdHlwZTogJ0NvbXBvbmVudCd8J0RpcmVjdGl2ZSd8J1BpcGUnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zZm9ybUZhaWx1cmUge1xuICBub2RlOiB0cy5Ob2RlO1xuICBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBVbmRlY29yYXRlZENsYXNzZXNUcmFuc2Zvcm0ge1xuICBwcml2YXRlIHByaW50ZXIgPSB0cy5jcmVhdGVQcmludGVyKHtuZXdMaW5lOiB0cy5OZXdMaW5lS2luZC5MaW5lRmVlZH0pO1xuICBwcml2YXRlIGltcG9ydE1hbmFnZXIgPSBuZXcgSW1wb3J0TWFuYWdlcih0aGlzLmdldFVwZGF0ZVJlY29yZGVyLCB0aGlzLnByaW50ZXIpO1xuICBwcml2YXRlIGRlY29yYXRvclJld3JpdGVyID1cbiAgICAgIG5ldyBEZWNvcmF0b3JSZXdyaXRlcih0aGlzLmltcG9ydE1hbmFnZXIsIHRoaXMudHlwZUNoZWNrZXIsIHRoaXMuZXZhbHVhdG9yLCB0aGlzLmNvbXBpbGVyKTtcblxuICBwcml2YXRlIGNvbXBpbGVySG9zdDogQW90Q29tcGlsZXJIb3N0O1xuICBwcml2YXRlIHN5bWJvbFJlc29sdmVyOiBTdGF0aWNTeW1ib2xSZXNvbHZlcjtcbiAgcHJpdmF0ZSBtZXRhZGF0YVJlc29sdmVyOiBDb21waWxlTWV0YWRhdGFSZXNvbHZlcjtcblxuICAvKiogU2V0IG9mIGNsYXNzIGRlY2xhcmF0aW9ucyB3aGljaCBoYXZlIGJlZW4gZGVjb3JhdGVkIHdpdGggXCJARGlyZWN0aXZlXCIuICovXG4gIHByaXZhdGUgZGVjb3JhdGVkRGlyZWN0aXZlcyA9IG5ldyBTZXQ8dHMuQ2xhc3NEZWNsYXJhdGlvbj4oKTtcbiAgLyoqIFNldCBvZiBjbGFzcyBkZWNsYXJhdGlvbnMgd2hpY2ggaGF2ZSBiZWVuIGRlY29yYXRlZCB3aXRoIFwiQEluamVjdGFibGVcIiAqL1xuICBwcml2YXRlIGRlY29yYXRlZFByb3ZpZGVycyA9IG5ldyBTZXQ8dHMuQ2xhc3NEZWNsYXJhdGlvbj4oKTtcbiAgLyoqXG4gICAqIFNldCBvZiBjbGFzcyBkZWNsYXJhdGlvbnMgd2hpY2ggaGF2ZSBiZWVuIGFuYWx5emVkIGFuZCBuZWVkIHRvIHNwZWNpZnlcbiAgICogYW4gZXhwbGljaXQgY29uc3RydWN0b3IuXG4gICAqL1xuICBwcml2YXRlIG1pc3NpbmdFeHBsaWNpdENvbnN0cnVjdG9yQ2xhc3NlcyA9IG5ldyBTZXQ8dHMuQ2xhc3NEZWNsYXJhdGlvbj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgdHlwZUNoZWNrZXI6IHRzLlR5cGVDaGVja2VyLCBwcml2YXRlIGNvbXBpbGVyOiBBb3RDb21waWxlcixcbiAgICAgIHByaXZhdGUgZXZhbHVhdG9yOiBQYXJ0aWFsRXZhbHVhdG9yLFxuICAgICAgcHJpdmF0ZSBnZXRVcGRhdGVSZWNvcmRlcjogKHNmOiB0cy5Tb3VyY2VGaWxlKSA9PiBVcGRhdGVSZWNvcmRlcikge1xuICAgIHRoaXMuc3ltYm9sUmVzb2x2ZXIgPSBjb21waWxlclsnX3N5bWJvbFJlc29sdmVyJ107XG4gICAgdGhpcy5jb21waWxlckhvc3QgPSBjb21waWxlclsnX2hvc3QnXTtcbiAgICB0aGlzLm1ldGFkYXRhUmVzb2x2ZXIgPSBjb21waWxlclsnX21ldGFkYXRhUmVzb2x2ZXInXTtcblxuICAgIC8vIFVuc2V0IHRoZSBkZWZhdWx0IGVycm9yIHJlY29yZGVyIHNvIHRoYXQgdGhlIHJlZmxlY3RvciB3aWxsIHRocm93IGFuIGV4Y2VwdGlvblxuICAgIC8vIGlmIG1ldGFkYXRhIGNhbm5vdCBiZSByZXNvbHZlZC5cbiAgICB0aGlzLmNvbXBpbGVyLnJlZmxlY3RvclsnZXJyb3JSZWNvcmRlciddID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gRGlzYWJsZXMgdGhhdCBzdGF0aWMgc3ltYm9scyBhcmUgcmVzb2x2ZWQgdGhyb3VnaCBzdW1tYXJpZXMgZnJvbSB3aXRoaW4gdGhlIHN0YXRpY1xuICAgIC8vIHJlZmxlY3Rvci4gU3VtbWFyaWVzIGNhbm5vdCBiZSB1c2VkIGZvciBkZWNvcmF0b3Igc2VyaWFsaXphdGlvbiBhcyBkZWNvcmF0b3JzIGFyZVxuICAgIC8vIG9taXR0ZWQgaW4gc3VtbWFyaWVzIGFuZCB0aGUgZGVjb3JhdG9yIGNhbid0IGJlIHJlY29uc3RydWN0ZWQgZnJvbSB0aGUgZGlyZWN0aXZlIHN1bW1hcnkuXG4gICAgdGhpcy5fZGlzYWJsZVN1bW1hcnlSZXNvbHV0aW9uKCk7XG4gIH1cblxuICAvKipcbiAgICogTWlncmF0ZXMgZGVjb3JhdGVkIGRpcmVjdGl2ZXMgd2hpY2ggY2FuIHBvdGVudGlhbGx5IGluaGVyaXQgYSBjb25zdHJ1Y3RvclxuICAgKiBmcm9tIGFuIHVuZGVjb3JhdGVkIGJhc2UgY2xhc3MuIEFsbCBiYXNlIGNsYXNzZXMgdW50aWwgdGhlIGZpcnN0IG9uZVxuICAgKiB3aXRoIGFuIGV4cGxpY2l0IGNvbnN0cnVjdG9yIHdpbGwgYmUgZGVjb3JhdGVkIHdpdGggdGhlIGFic3RyYWN0IFwiQERpcmVjdGl2ZSgpXCJcbiAgICogZGVjb3JhdG9yLiBTZWUgY2FzZSAxIGluIHRoZSBtaWdyYXRpb24gcGxhbjogaHR0cHM6Ly9oYWNrbWQuaW8vQGFseC9TMVhLcU1aZVNcbiAgICovXG4gIG1pZ3JhdGVEZWNvcmF0ZWREaXJlY3RpdmVzKGRpcmVjdGl2ZXM6IHRzLkNsYXNzRGVjbGFyYXRpb25bXSk6IFRyYW5zZm9ybUZhaWx1cmVbXSB7XG4gICAgcmV0dXJuIGRpcmVjdGl2ZXMucmVkdWNlKFxuICAgICAgICAoZmFpbHVyZXMsIG5vZGUpID0+IGZhaWx1cmVzLmNvbmNhdCh0aGlzLl9taWdyYXRlRGlyZWN0aXZlQmFzZUNsYXNzKG5vZGUpKSxcbiAgICAgICAgW10gYXMgVHJhbnNmb3JtRmFpbHVyZVtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNaWdyYXRlcyBkZWNvcmF0ZWQgcHJvdmlkZXJzIHdoaWNoIGNhbiBwb3RlbnRpYWxseSBpbmhlcml0IGEgY29uc3RydWN0b3JcbiAgICogZnJvbSBhbiB1bmRlY29yYXRlZCBiYXNlIGNsYXNzLiBBbGwgYmFzZSBjbGFzc2VzIHVudGlsIHRoZSBmaXJzdCBvbmVcbiAgICogd2l0aCBhbiBleHBsaWNpdCBjb25zdHJ1Y3RvciB3aWxsIGJlIGRlY29yYXRlZCB3aXRoIHRoZSBcIkBJbmplY3RhYmxlKClcIi5cbiAgICovXG4gIG1pZ3JhdGVEZWNvcmF0ZWRQcm92aWRlcnMocHJvdmlkZXJzOiB0cy5DbGFzc0RlY2xhcmF0aW9uW10pOiBUcmFuc2Zvcm1GYWlsdXJlW10ge1xuICAgIHJldHVybiBwcm92aWRlcnMucmVkdWNlKFxuICAgICAgICAoZmFpbHVyZXMsIG5vZGUpID0+IGZhaWx1cmVzLmNvbmNhdCh0aGlzLl9taWdyYXRlUHJvdmlkZXJCYXNlQ2xhc3Mobm9kZSkpLFxuICAgICAgICBbXSBhcyBUcmFuc2Zvcm1GYWlsdXJlW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBfbWlncmF0ZVByb3ZpZGVyQmFzZUNsYXNzKG5vZGU6IHRzLkNsYXNzRGVjbGFyYXRpb24pOiBUcmFuc2Zvcm1GYWlsdXJlW10ge1xuICAgIHJldHVybiB0aGlzLl9taWdyYXRlRGVjb3JhdGVkQ2xhc3NXaXRoSW5oZXJpdGVkQ3RvcihcbiAgICAgICAgbm9kZSwgc3ltYm9sID0+IHRoaXMubWV0YWRhdGFSZXNvbHZlci5pc0luamVjdGFibGUoc3ltYm9sKSxcbiAgICAgICAgbm9kZSA9PiB0aGlzLl9hZGRJbmplY3RhYmxlRGVjb3JhdG9yKG5vZGUpKTtcbiAgfVxuXG4gIHByaXZhdGUgX21pZ3JhdGVEaXJlY3RpdmVCYXNlQ2xhc3Mobm9kZTogdHMuQ2xhc3NEZWNsYXJhdGlvbik6IFRyYW5zZm9ybUZhaWx1cmVbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21pZ3JhdGVEZWNvcmF0ZWRDbGFzc1dpdGhJbmhlcml0ZWRDdG9yKFxuICAgICAgICBub2RlLCBzeW1ib2wgPT4gdGhpcy5tZXRhZGF0YVJlc29sdmVyLmlzRGlyZWN0aXZlKHN5bWJvbCksXG4gICAgICAgIG5vZGUgPT4gdGhpcy5fYWRkQWJzdHJhY3REaXJlY3RpdmVEZWNvcmF0b3Iobm9kZSkpO1xuICB9XG5cblxuICBwcml2YXRlIF9taWdyYXRlRGVjb3JhdGVkQ2xhc3NXaXRoSW5oZXJpdGVkQ3RvcihcbiAgICAgIG5vZGU6IHRzLkNsYXNzRGVjbGFyYXRpb24sIGlzQ2xhc3NEZWNvcmF0ZWQ6IChzeW1ib2w6IFN0YXRpY1N5bWJvbCkgPT4gYm9vbGVhbixcbiAgICAgIGFkZENsYXNzRGVjb3JhdG9yOiAobm9kZTogdHMuQ2xhc3NEZWNsYXJhdGlvbikgPT4gdm9pZCk6IFRyYW5zZm9ybUZhaWx1cmVbXSB7XG4gICAgLy8gSW4gY2FzZSB0aGUgcHJvdmlkZXIgaGFzIGFuIGV4cGxpY2l0IGNvbnN0cnVjdG9yLCB3ZSBkb24ndCBuZWVkIHRvIGRvIGFueXRoaW5nXG4gICAgLy8gYmVjYXVzZSB0aGUgY2xhc3MgaXMgYWxyZWFkeSBkZWNvcmF0ZWQgYW5kIGRvZXMgbm90IGluaGVyaXQgYSBjb25zdHJ1Y3Rvci5cbiAgICBpZiAoaGFzRXhwbGljaXRDb25zdHJ1Y3Rvcihub2RlKSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IG9yZGVyZWRCYXNlQ2xhc3NlcyA9IGZpbmRCYXNlQ2xhc3NEZWNsYXJhdGlvbnMobm9kZSwgdGhpcy50eXBlQ2hlY2tlcik7XG4gICAgY29uc3QgdW5kZWNvcmF0ZWRCYXNlQ2xhc3NlczogdHMuQ2xhc3NEZWNsYXJhdGlvbltdID0gW107XG5cbiAgICBmb3IgKGxldCB7bm9kZTogYmFzZUNsYXNzLCBpZGVudGlmaWVyfSBvZiBvcmRlcmVkQmFzZUNsYXNzZXMpIHtcbiAgICAgIGNvbnN0IGJhc2VDbGFzc0ZpbGUgPSBiYXNlQ2xhc3MuZ2V0U291cmNlRmlsZSgpO1xuXG4gICAgICBpZiAoaGFzRXhwbGljaXRDb25zdHJ1Y3RvcihiYXNlQ2xhc3MpKSB7XG4gICAgICAgIC8vIEFsbCBjbGFzc2VzIGluIGJldHdlZW4gdGhlIGRlY29yYXRlZCBjbGFzcyBhbmQgdGhlIHVuZGVjb3JhdGVkIGNsYXNzXG4gICAgICAgIC8vIHRoYXQgZGVmaW5lcyB0aGUgY29uc3RydWN0b3IgbmVlZCB0byBiZSBkZWNvcmF0ZWQgYXMgd2VsbC5cbiAgICAgICAgdW5kZWNvcmF0ZWRCYXNlQ2xhc3Nlcy5mb3JFYWNoKGIgPT4gYWRkQ2xhc3NEZWNvcmF0b3IoYikpO1xuXG4gICAgICAgIGlmIChiYXNlQ2xhc3NGaWxlLmlzRGVjbGFyYXRpb25GaWxlKSB7XG4gICAgICAgICAgY29uc3Qgc3RhdGljU3ltYm9sID0gdGhpcy5fZ2V0U3RhdGljU3ltYm9sT2ZJZGVudGlmaWVyKGlkZW50aWZpZXIpO1xuXG4gICAgICAgICAgLy8gSWYgdGhlIGJhc2UgY2xhc3MgaXMgZGVjb3JhdGVkIHRocm91Z2ggbWV0YWRhdGEgZmlsZXMsIHdlIGRvbid0XG4gICAgICAgICAgLy8gbmVlZCB0byBhZGQgYSBjb21tZW50IHRvIHRoZSBkZXJpdmVkIGNsYXNzIGZvciB0aGUgZXh0ZXJuYWwgYmFzZSBjbGFzcy5cbiAgICAgICAgICBpZiAoc3RhdGljU3ltYm9sICYmIGlzQ2xhc3NEZWNvcmF0ZWQoc3RhdGljU3ltYm9sKSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRmluZCB0aGUgbGFzdCBjbGFzcyBpbiB0aGUgaW5oZXJpdGFuY2UgY2hhaW4gdGhhdCBpcyBkZWNvcmF0ZWQgYW5kIHdpbGwgYmVcbiAgICAgICAgICAvLyB1c2VkIGFzIGFuY2hvciBmb3IgYSBjb21tZW50IGV4cGxhaW5pbmcgdGhhdCB0aGUgY2xhc3MgdGhhdCBkZWZpbmVzIHRoZVxuICAgICAgICAgIC8vIGNvbnN0cnVjdG9yIGNhbm5vdCBiZSBkZWNvcmF0ZWQgYXV0b21hdGljYWxseS5cbiAgICAgICAgICBjb25zdCBsYXN0RGVjb3JhdGVkQ2xhc3MgPVxuICAgICAgICAgICAgICB1bmRlY29yYXRlZEJhc2VDbGFzc2VzW3VuZGVjb3JhdGVkQmFzZUNsYXNzZXMubGVuZ3RoIC0gMV0gfHwgbm9kZTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5fYWRkTWlzc2luZ0V4cGxpY2l0Q29uc3RydWN0b3JUb2RvKGxhc3REZWNvcmF0ZWRDbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWNvcmF0ZSB0aGUgY2xhc3MgdGhhdCBkZWZpbmVzIHRoZSBjb25zdHJ1Y3RvciB0aGF0IGlzIGluaGVyaXRlZC5cbiAgICAgICAgYWRkQ2xhc3NEZWNvcmF0b3IoYmFzZUNsYXNzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8vIEFkZCB0aGUgY2xhc3MgZGVjb3JhdG9yIGZvciBhbGwgYmFzZSBjbGFzc2VzIGluIHRoZSBpbmhlcml0YW5jZSBjaGFpbiB1bnRpbFxuICAgICAgLy8gdGhlIGJhc2UgY2xhc3Mgd2l0aCB0aGUgZXhwbGljaXQgY29uc3RydWN0b3IuIFRoZSBkZWNvcmF0b3Igd2lsbCBiZSBvbmx5XG4gICAgICAvLyBhZGRlZCBmb3IgYmFzZSBjbGFzc2VzIHdoaWNoIGNhbiBiZSBtb2RpZmllZC5cbiAgICAgIGlmICghYmFzZUNsYXNzRmlsZS5pc0RlY2xhcmF0aW9uRmlsZSkge1xuICAgICAgICB1bmRlY29yYXRlZEJhc2VDbGFzc2VzLnB1c2goYmFzZUNsYXNzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgdGhlIGFic3RyYWN0IFwiQERpcmVjdGl2ZSgpXCIgZGVjb3JhdG9yIHRvIHRoZSBnaXZlbiBjbGFzcyBpbiBjYXNlIHRoZXJlXG4gICAqIGlzIG5vIGV4aXN0aW5nIGRpcmVjdGl2ZSBkZWNvcmF0b3IuXG4gICAqL1xuICBwcml2YXRlIF9hZGRBYnN0cmFjdERpcmVjdGl2ZURlY29yYXRvcihiYXNlQ2xhc3M6IHRzLkNsYXNzRGVjbGFyYXRpb24pIHtcbiAgICBpZiAoaGFzRGlyZWN0aXZlRGVjb3JhdG9yKGJhc2VDbGFzcywgdGhpcy50eXBlQ2hlY2tlcikgfHxcbiAgICAgICAgdGhpcy5kZWNvcmF0ZWREaXJlY3RpdmVzLmhhcyhiYXNlQ2xhc3MpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYmFzZUNsYXNzRmlsZSA9IGJhc2VDbGFzcy5nZXRTb3VyY2VGaWxlKCk7XG4gICAgY29uc3QgcmVjb3JkZXIgPSB0aGlzLmdldFVwZGF0ZVJlY29yZGVyKGJhc2VDbGFzc0ZpbGUpO1xuICAgIGNvbnN0IGRpcmVjdGl2ZUV4cHIgPVxuICAgICAgICB0aGlzLmltcG9ydE1hbmFnZXIuYWRkSW1wb3J0VG9Tb3VyY2VGaWxlKGJhc2VDbGFzc0ZpbGUsICdEaXJlY3RpdmUnLCAnQGFuZ3VsYXIvY29yZScpO1xuXG4gICAgY29uc3QgbmV3RGVjb3JhdG9yID0gdHMuY3JlYXRlRGVjb3JhdG9yKHRzLmNyZWF0ZUNhbGwoZGlyZWN0aXZlRXhwciwgdW5kZWZpbmVkLCBbXSkpO1xuICAgIGNvbnN0IG5ld0RlY29yYXRvclRleHQgPVxuICAgICAgICB0aGlzLnByaW50ZXIucHJpbnROb2RlKHRzLkVtaXRIaW50LlVuc3BlY2lmaWVkLCBuZXdEZWNvcmF0b3IsIGJhc2VDbGFzc0ZpbGUpO1xuXG4gICAgcmVjb3JkZXIuYWRkQ2xhc3NEZWNvcmF0b3IoYmFzZUNsYXNzLCBuZXdEZWNvcmF0b3JUZXh0KTtcbiAgICB0aGlzLmRlY29yYXRlZERpcmVjdGl2ZXMuYWRkKGJhc2VDbGFzcyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyB0aGUgYWJzdHJhY3QgXCJASW5qZWN0YWJsZSgpXCIgZGVjb3JhdG9yIHRvIHRoZSBnaXZlbiBjbGFzcyBpbiBjYXNlIHRoZXJlXG4gICAqIGlzIG5vIGV4aXN0aW5nIGRpcmVjdGl2ZSBkZWNvcmF0b3IuXG4gICAqL1xuICBwcml2YXRlIF9hZGRJbmplY3RhYmxlRGVjb3JhdG9yKGJhc2VDbGFzczogdHMuQ2xhc3NEZWNsYXJhdGlvbikge1xuICAgIGlmIChoYXNJbmplY3RhYmxlRGVjb3JhdG9yKGJhc2VDbGFzcywgdGhpcy50eXBlQ2hlY2tlcikgfHxcbiAgICAgICAgdGhpcy5kZWNvcmF0ZWRQcm92aWRlcnMuaGFzKGJhc2VDbGFzcykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBiYXNlQ2xhc3NGaWxlID0gYmFzZUNsYXNzLmdldFNvdXJjZUZpbGUoKTtcbiAgICBjb25zdCByZWNvcmRlciA9IHRoaXMuZ2V0VXBkYXRlUmVjb3JkZXIoYmFzZUNsYXNzRmlsZSk7XG4gICAgY29uc3QgaW5qZWN0YWJsZUV4cHIgPVxuICAgICAgICB0aGlzLmltcG9ydE1hbmFnZXIuYWRkSW1wb3J0VG9Tb3VyY2VGaWxlKGJhc2VDbGFzc0ZpbGUsICdJbmplY3RhYmxlJywgJ0Bhbmd1bGFyL2NvcmUnKTtcblxuICAgIGNvbnN0IG5ld0RlY29yYXRvciA9IHRzLmNyZWF0ZURlY29yYXRvcih0cy5jcmVhdGVDYWxsKGluamVjdGFibGVFeHByLCB1bmRlZmluZWQsIFtdKSk7XG4gICAgY29uc3QgbmV3RGVjb3JhdG9yVGV4dCA9XG4gICAgICAgIHRoaXMucHJpbnRlci5wcmludE5vZGUodHMuRW1pdEhpbnQuVW5zcGVjaWZpZWQsIG5ld0RlY29yYXRvciwgYmFzZUNsYXNzRmlsZSk7XG5cbiAgICByZWNvcmRlci5hZGRDbGFzc0RlY29yYXRvcihiYXNlQ2xhc3MsIG5ld0RlY29yYXRvclRleHQpO1xuICAgIHRoaXMuZGVjb3JhdGVkUHJvdmlkZXJzLmFkZChiYXNlQ2xhc3MpO1xuICB9XG5cbiAgLyoqIEFkZHMgYSBjb21tZW50IGZvciBhZGRpbmcgYW4gZXhwbGljaXQgY29uc3RydWN0b3IgdG8gdGhlIGdpdmVuIGNsYXNzIGRlY2xhcmF0aW9uLiAqL1xuICBwcml2YXRlIF9hZGRNaXNzaW5nRXhwbGljaXRDb25zdHJ1Y3RvclRvZG8obm9kZTogdHMuQ2xhc3NEZWNsYXJhdGlvbik6IFRyYW5zZm9ybUZhaWx1cmVbXSB7XG4gICAgLy8gSW4gY2FzZSBhIHRv