UNPKG

@angular/compiler

Version:

Angular - the compiler library

482 lines • 73.6 kB
/** * @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 */ import { ValueTransformer, visitValue } from '../util'; import { StaticSymbol } from './static_symbol'; import { isGeneratedFile, stripSummaryForJitFileSuffix, stripSummaryForJitNameSuffix, summaryForJitFileName, summaryForJitName } from './util'; const TS = /^(?!.*\.d\.ts$).*\.ts$/; export class ResolvedStaticSymbol { constructor(symbol, metadata) { this.symbol = symbol; this.metadata = metadata; } } const SUPPORTED_SCHEMA_VERSION = 4; /** * This class is responsible for loading metadata per symbol, * and normalizing references between symbols. * * Internally, it only uses symbols without members, * and deduces the values for symbols with members based * on these symbols. */ export class StaticSymbolResolver { constructor(host, staticSymbolCache, summaryResolver, errorRecorder) { this.host = host; this.staticSymbolCache = staticSymbolCache; this.summaryResolver = summaryResolver; this.errorRecorder = errorRecorder; this.metadataCache = new Map(); // Note: this will only contain StaticSymbols without members! this.resolvedSymbols = new Map(); // Note: this will only contain StaticSymbols without members! this.importAs = new Map(); this.symbolResourcePaths = new Map(); this.symbolFromFile = new Map(); this.knownFileNameToModuleNames = new Map(); } resolveSymbol(staticSymbol) { if (staticSymbol.members.length > 0) { return this._resolveSymbolMembers(staticSymbol); } // Note: always ask for a summary first, // as we might have read shallow metadata via a .d.ts file // for the symbol. const resultFromSummary = this._resolveSymbolFromSummary(staticSymbol); if (resultFromSummary) { return resultFromSummary; } const resultFromCache = this.resolvedSymbols.get(staticSymbol); if (resultFromCache) { return resultFromCache; } // Note: Some users use libraries that were not compiled with ngc, i.e. they don't // have summaries, only .d.ts files. So we always need to check both, the summary // and metadata. this._createSymbolsOf(staticSymbol.filePath); return this.resolvedSymbols.get(staticSymbol); } /** * getImportAs produces a symbol that can be used to import the given symbol. * The import might be different than the symbol if the symbol is exported from * a library with a summary; in which case we want to import the symbol from the * ngfactory re-export instead of directly to avoid introducing a direct dependency * on an otherwise indirect dependency. * * @param staticSymbol the symbol for which to generate a import symbol */ getImportAs(staticSymbol, useSummaries = true) { if (staticSymbol.members.length) { const baseSymbol = this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name); const baseImportAs = this.getImportAs(baseSymbol, useSummaries); return baseImportAs ? this.getStaticSymbol(baseImportAs.filePath, baseImportAs.name, staticSymbol.members) : null; } const summarizedFileName = stripSummaryForJitFileSuffix(staticSymbol.filePath); if (summarizedFileName !== staticSymbol.filePath) { const summarizedName = stripSummaryForJitNameSuffix(staticSymbol.name); const baseSymbol = this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members); const baseImportAs = this.getImportAs(baseSymbol, useSummaries); return baseImportAs ? this.getStaticSymbol(summaryForJitFileName(baseImportAs.filePath), summaryForJitName(baseImportAs.name), baseSymbol.members) : null; } let result = (useSummaries && this.summaryResolver.getImportAs(staticSymbol)) || null; if (!result) { result = this.importAs.get(staticSymbol); } return result; } /** * getResourcePath produces the path to the original location of the symbol and should * be used to determine the relative location of resource references recorded in * symbol metadata. */ getResourcePath(staticSymbol) { return this.symbolResourcePaths.get(staticSymbol) || staticSymbol.filePath; } /** * getTypeArity returns the number of generic type parameters the given symbol * has. If the symbol is not a type the result is null. */ getTypeArity(staticSymbol) { // If the file is a factory/ngsummary file, don't resolve the symbol as doing so would // cause the metadata for an factory/ngsummary file to be loaded which doesn't exist. // All references to generated classes must include the correct arity whenever // generating code. if (isGeneratedFile(staticSymbol.filePath)) { return null; } let resolvedSymbol = unwrapResolvedMetadata(this.resolveSymbol(staticSymbol)); while (resolvedSymbol && resolvedSymbol.metadata instanceof StaticSymbol) { resolvedSymbol = unwrapResolvedMetadata(this.resolveSymbol(resolvedSymbol.metadata)); } return (resolvedSymbol && resolvedSymbol.metadata && resolvedSymbol.metadata.arity) || null; } getKnownModuleName(filePath) { return this.knownFileNameToModuleNames.get(filePath) || null; } recordImportAs(sourceSymbol, targetSymbol) { sourceSymbol.assertNoMembers(); targetSymbol.assertNoMembers(); this.importAs.set(sourceSymbol, targetSymbol); } recordModuleNameForFileName(fileName, moduleName) { this.knownFileNameToModuleNames.set(fileName, moduleName); } /** * Invalidate all information derived from the given file and return the * static symbols contained in the file. * * @param fileName the file to invalidate */ invalidateFile(fileName) { this.metadataCache.delete(fileName); const symbols = this.symbolFromFile.get(fileName); if (!symbols) { return []; } this.symbolFromFile.delete(fileName); for (const symbol of symbols) { this.resolvedSymbols.delete(symbol); this.importAs.delete(symbol); this.symbolResourcePaths.delete(symbol); } return symbols; } /** @internal */ ignoreErrorsFor(cb) { const recorder = this.errorRecorder; this.errorRecorder = () => { }; try { return cb(); } finally { this.errorRecorder = recorder; } } _resolveSymbolMembers(staticSymbol) { const members = staticSymbol.members; const baseResolvedSymbol = this.resolveSymbol(this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name)); if (!baseResolvedSymbol) { return null; } let baseMetadata = unwrapResolvedMetadata(baseResolvedSymbol.metadata); if (baseMetadata instanceof StaticSymbol) { return new ResolvedStaticSymbol(staticSymbol, this.getStaticSymbol(baseMetadata.filePath, baseMetadata.name, members)); } else if (baseMetadata && baseMetadata.__symbolic === 'class') { if (baseMetadata.statics && members.length === 1) { return new ResolvedStaticSymbol(staticSymbol, baseMetadata.statics[members[0]]); } } else { let value = baseMetadata; for (let i = 0; i < members.length && value; i++) { value = value[members[i]]; } return new ResolvedStaticSymbol(staticSymbol, value); } return null; } _resolveSymbolFromSummary(staticSymbol) { const summary = this.summaryResolver.resolveSummary(staticSymbol); return summary ? new ResolvedStaticSymbol(staticSymbol, summary.metadata) : null; } /** * getStaticSymbol produces a Type whose metadata is known but whose implementation is not loaded. * All types passed to the StaticResolver should be pseudo-types returned by this method. * * @param declarationFile the absolute path of the file where the symbol is declared * @param name the name of the type. * @param members a symbol for a static member of the named type */ getStaticSymbol(declarationFile, name, members) { return this.staticSymbolCache.get(declarationFile, name, members); } /** * hasDecorators checks a file's metadata for the presence of decorators without evaluating the * metadata. * * @param filePath the absolute path to examine for decorators. * @returns true if any class in the file has a decorator. */ hasDecorators(filePath) { const metadata = this.getModuleMetadata(filePath); if (metadata['metadata']) { return Object.keys(metadata['metadata']).some((metadataKey) => { const entry = metadata['metadata'][metadataKey]; return entry && entry.__symbolic === 'class' && entry.decorators; }); } return false; } getSymbolsOf(filePath) { const summarySymbols = this.summaryResolver.getSymbolsOf(filePath); if (summarySymbols) { return summarySymbols; } // Note: Some users use libraries that were not compiled with ngc, i.e. they don't // have summaries, only .d.ts files, but `summaryResolver.isLibraryFile` returns true. this._createSymbolsOf(filePath); return this.symbolFromFile.get(filePath) || []; } _createSymbolsOf(filePath) { if (this.symbolFromFile.has(filePath)) { return; } const resolvedSymbols = []; const metadata = this.getModuleMetadata(filePath); if (metadata['importAs']) { // Index bundle indices should use the importAs module name defined // in the bundle. this.knownFileNameToModuleNames.set(filePath, metadata['importAs']); } // handle the symbols in one of the re-export location if (metadata['exports']) { for (const moduleExport of metadata['exports']) { // handle the symbols in the list of explicitly re-exported symbols. if (moduleExport.export) { moduleExport.export.forEach((exportSymbol) => { let symbolName; if (typeof exportSymbol === 'string') { symbolName = exportSymbol; } else { symbolName = exportSymbol.as; } symbolName = unescapeIdentifier(symbolName); let symName = symbolName; if (typeof exportSymbol !== 'string') { symName = unescapeIdentifier(exportSymbol.name); } const resolvedModule = this.resolveModule(moduleExport.from, filePath); if (resolvedModule) { const targetSymbol = this.getStaticSymbol(resolvedModule, symName); const sourceSymbol = this.getStaticSymbol(filePath, symbolName); resolvedSymbols.push(this.createExport(sourceSymbol, targetSymbol)); } }); } else { // Handle the symbols loaded by 'export *' directives. const resolvedModule = this.resolveModule(moduleExport.from, filePath); if (resolvedModule && resolvedModule !== filePath) { const nestedExports = this.getSymbolsOf(resolvedModule); nestedExports.forEach((targetSymbol) => { const sourceSymbol = this.getStaticSymbol(filePath, targetSymbol.name); resolvedSymbols.push(this.createExport(sourceSymbol, targetSymbol)); }); } } } } // handle the actual metadata. Has to be after the exports // as there might be collisions in the names, and we want the symbols // of the current module to win ofter reexports. if (metadata['metadata']) { // handle direct declarations of the symbol const topLevelSymbolNames = new Set(Object.keys(metadata['metadata']).map(unescapeIdentifier)); const origins = metadata['origins'] || {}; Object.keys(metadata['metadata']).forEach((metadataKey) => { const symbolMeta = metadata['metadata'][metadataKey]; const name = unescapeIdentifier(metadataKey); const symbol = this.getStaticSymbol(filePath, name); const origin = origins.hasOwnProperty(metadataKey) && origins[metadataKey]; if (origin) { // If the symbol is from a bundled index, use the declaration location of the // symbol so relative references (such as './my.html') will be calculated // correctly. const originFilePath = this.resolveModule(origin, filePath); if (!originFilePath) { this.reportError(new Error(`Couldn't resolve original symbol for ${origin} from ${this.host.getOutputName(filePath)}`)); } else { this.symbolResourcePaths.set(symbol, originFilePath); } } resolvedSymbols.push(this.createResolvedSymbol(symbol, filePath, topLevelSymbolNames, symbolMeta)); }); } const uniqueSymbols = new Set(); for (const resolvedSymbol of resolvedSymbols) { this.resolvedSymbols.set(resolvedSymbol.symbol, resolvedSymbol); uniqueSymbols.add(resolvedSymbol.symbol); } this.symbolFromFile.set(filePath, Array.from(uniqueSymbols)); } createResolvedSymbol(sourceSymbol, topLevelPath, topLevelSymbolNames, metadata) { // For classes that don't have Angular summaries / metadata, // we only keep their arity, but nothing else // (e.g. their constructor parameters). // We do this to prevent introducing deep imports // as we didn't generate .ngfactory.ts files with proper reexports. const isTsFile = TS.test(sourceSymbol.filePath); if (this.summaryResolver.isLibraryFile(sourceSymbol.filePath) && !isTsFile && metadata && metadata['__symbolic'] === 'class') { const transformedMeta = { __symbolic: 'class', arity: metadata.arity }; return new ResolvedStaticSymbol(sourceSymbol, transformedMeta); } let _originalFileMemo; const getOriginalName = () => { if (!_originalFileMemo) { // Guess what the original file name is from the reference. If it has a `.d.ts` extension // replace it with `.ts`. If it already has `.ts` just leave it in place. If it doesn't have // .ts or .d.ts, append `.ts'. Also, if it is in `node_modules`, trim the `node_module` // location as it is not important to finding the file. _originalFileMemo = this.host.getOutputName(topLevelPath.replace(/((\.ts)|(\.d\.ts)|)$/, '.ts') .replace(/^.*node_modules[/\\]/, '')); } return _originalFileMemo; }; const self = this; class ReferenceTransformer extends ValueTransformer { visitStringMap(map, functionParams) { const symbolic = map['__symbolic']; if (symbolic === 'function') { const oldLen = functionParams.length; functionParams.push(...(map['parameters'] || [])); const result = super.visitStringMap(map, functionParams); functionParams.length = oldLen; return result; } else if (symbolic === 'reference') { const module = map['module']; const name = map['name'] ? unescapeIdentifier(map['name']) : map['name']; if (!name) { return null; } let filePath; if (module) { filePath = self.resolveModule(module, sourceSymbol.filePath); if (!filePath) { return { __symbolic: 'error', message: `Could not resolve ${module} relative to ${self.host.getMetadataFor(sourceSymbol.filePath)}.`, line: map['line'], character: map['character'], fileName: getOriginalName() }; } return { __symbolic: 'resolved', symbol: self.getStaticSymbol(filePath, name), line: map['line'], character: map['character'], fileName: getOriginalName() }; } else if (functionParams.indexOf(name) >= 0) { // reference to a function parameter return { __symbolic: 'reference', name: name }; } else { if (topLevelSymbolNames.has(name)) { return self.getStaticSymbol(topLevelPath, name); } // ambient value null; } } else if (symbolic === 'error') { return { ...map, fileName: getOriginalName() }; } else { return super.visitStringMap(map, functionParams); } } } const transformedMeta = visitValue(metadata, new ReferenceTransformer(), []); let unwrappedTransformedMeta = unwrapResolvedMetadata(transformedMeta); if (unwrappedTransformedMeta instanceof StaticSymbol) { return this.createExport(sourceSymbol, unwrappedTransformedMeta); } return new ResolvedStaticSymbol(sourceSymbol, transformedMeta); } createExport(sourceSymbol, targetSymbol) { sourceSymbol.assertNoMembers(); targetSymbol.assertNoMembers(); if (this.summaryResolver.isLibraryFile(sourceSymbol.filePath) && this.summaryResolver.isLibraryFile(targetSymbol.filePath)) { // This case is for an ng library importing symbols from a plain ts library // transitively. // Note: We rely on the fact that we discover symbols in the direction // from source files to library files this.importAs.set(targetSymbol, this.getImportAs(sourceSymbol) || sourceSymbol); } return new ResolvedStaticSymbol(sourceSymbol, targetSymbol); } reportError(error, context, path) { if (this.errorRecorder) { this.errorRecorder(error, (context && context.filePath) || path); } else { throw error; } } /** * @param module an absolute path to a module file. */ getModuleMetadata(module) { let moduleMetadata = this.metadataCache.get(module); if (!moduleMetadata) { const moduleMetadatas = this.host.getMetadataFor(module); if (moduleMetadatas) { let maxVersion = -1; moduleMetadatas.forEach((md) => { if (md && md['version'] > maxVersion) { maxVersion = md['version']; moduleMetadata = md; } }); } if (!moduleMetadata) { moduleMetadata = { __symbolic: 'module', version: SUPPORTED_SCHEMA_VERSION, module: module, metadata: {} }; } if (moduleMetadata['version'] != SUPPORTED_SCHEMA_VERSION) { const errorMessage = moduleMetadata['version'] == 2 ? `Unsupported metadata version ${moduleMetadata['version']} for module ${module}. This module should be compiled with a newer version of ngc` : `Metadata version mismatch for module ${this.host.getOutputName(module)}, found version ${moduleMetadata['version']}, expected ${SUPPORTED_SCHEMA_VERSION}`; this.reportError(new Error(errorMessage)); } this.metadataCache.set(module, moduleMetadata); } return moduleMetadata; } getSymbolByModule(module, symbolName, containingFile) { const filePath = this.resolveModule(module, containingFile); if (!filePath) { this.reportError(new Error(`Could not resolve module ${module}${containingFile ? ' relative to ' + this.host.getOutputName(containingFile) : ''}`)); return this.getStaticSymbol(`ERROR:${module}`, symbolName); } return this.getStaticSymbol(filePath, symbolName); } resolveModule(module, containingFile) { try { return this.host.moduleNameToFileName(module, containingFile); } catch (e) { console.error(`Could not resolve module '${module}' relative to file ${containingFile}`); this.reportError(e, undefined, containingFile); } return null; } } // Remove extra underscore from escaped identifier. // See https://github.com/Microsoft/TypeScript/blob/master/src/compiler/utilities.ts export function unescapeIdentifier(identifier) { return identifier.startsWith('___') ? identifier.substr(1) : identifier; } export function unwrapResolvedMetadata(metadata) { if (metadata && metadata.__symbolic === 'resolved') { return metadata.symbol; } return metadata; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljX3N5bWJvbF9yZXNvbHZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9hb3Qvc3RhdGljX3N5bWJvbF9yZXNvbHZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFHSCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUUsVUFBVSxFQUFDLE1BQU0sU0FBUyxDQUFDO0FBRXJELE9BQU8sRUFBQyxZQUFZLEVBQW9CLE1BQU0saUJBQWlCLENBQUM7QUFDaEUsT0FBTyxFQUFDLGVBQWUsRUFBRSw0QkFBNEIsRUFBRSw0QkFBNEIsRUFBRSxxQkFBcUIsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLFFBQVEsQ0FBQztBQUU3SSxNQUFNLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQztBQUVwQyxNQUFNLE9BQU8sb0JBQW9CO0lBQy9CLFlBQW1CLE1BQW9CLEVBQVMsUUFBYTtRQUExQyxXQUFNLEdBQU4sTUFBTSxDQUFjO1FBQVMsYUFBUSxHQUFSLFFBQVEsQ0FBSztJQUFHLENBQUM7Q0FDbEU7QUFpQ0QsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLENBQUM7QUFFbkM7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFVL0IsWUFDWSxJQUE4QixFQUFVLGlCQUFvQyxFQUM1RSxlQUE4QyxFQUM5QyxhQUF1RDtRQUZ2RCxTQUFJLEdBQUosSUFBSSxDQUEwQjtRQUFVLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDNUUsb0JBQWUsR0FBZixlQUFlLENBQStCO1FBQzlDLGtCQUFhLEdBQWIsYUFBYSxDQUEwQztRQVozRCxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUFnQyxDQUFDO1FBQ2hFLDhEQUE4RDtRQUN0RCxvQkFBZSxHQUFHLElBQUksR0FBRyxFQUFzQyxDQUFDO1FBQ3hFLDhEQUE4RDtRQUN0RCxhQUFRLEdBQUcsSUFBSSxHQUFHLEVBQThCLENB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TUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1NBQy9EO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLENBQUMsS0FBSyxDQUFDLDZCQUE2QixNQUFNLHNCQUFzQixjQUFjLEVBQUUsQ0FBQyxDQUFDO1lBQ3pGLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxjQUFjLENBQUMsQ0FBQztTQUNoRDtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztDQUNGO0FBRUQsbURBQW1EO0FBQ25ELG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsa0JBQWtCLENBQUMsVUFBa0I7SUFDbkQsT0FBTyxVQUFVLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7QUFDMUUsQ0FBQztBQUVELE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxRQUFhO0lBQ2xELElBQUksUUFBUSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFO1FBQ2xELE9BQU8sUUFBUSxDQUFDLE1BQU0sQ0FBQztLQUN4QjtJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtTdW1tYXJ5UmVzb2x2ZXJ9IGZyb20gJy4uL3N1bW1hcnlfcmVzb2x2ZXInO1xuaW1wb3J0IHtWYWx1ZVRyYW5zZm9ybWVyLCB2aXNpdFZhbHVlfSBmcm9tICcuLi91dGlsJztcblxuaW1wb3J0IHtTdGF0aWNTeW1ib2wsIFN0YXRpY1N5bWJvbENhY2hlfSBmcm9tICcuL3N0YXRpY19zeW1ib2wnO1xuaW1wb3J0IHtpc0dlbmVyYXRlZEZpbGUsIHN0cmlwU3VtbWFyeUZvckppdEZpbGVTdWZmaXgsIHN0cmlwU3VtbWFyeUZvckppdE5hbWVTdWZmaXgsIHN1bW1hcnlGb3JKaXRGaWxlTmFtZSwgc3VtbWFyeUZvckppdE5hbWV9IGZyb20gJy4vdXRpbCc7XG5cbmNvbnN0IFRTID0gL14oPyEuKlxcLmRcXC50cyQpLipcXC50cyQvO1xuXG5leHBvcnQgY2xhc3MgUmVzb2x2ZWRTdGF0aWNTeW1ib2wge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgc3ltYm9sOiBTdGF0aWNTeW1ib2wsIHB1YmxpYyBtZXRhZGF0YTogYW55KSB7fVxufVxuXG4vKipcbiAqIFRoZSBob3N0IG9mIHRoZSBTeW1ib2xSZXNvbHZlckhvc3QgZGlzY29ubmVjdHMgdGhlIGltcGxlbWVudGF0aW9uIGZyb20gVHlwZVNjcmlwdCAvIG90aGVyXG4gKiBsYW5ndWFnZVxuICogc2VydmljZXMgYW5kIGZyb20gdW5kZXJseWluZyBmaWxlIHN5c3RlbXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGljU3ltYm9sUmVzb2x2ZXJIb3N0IHtcbiAgLyoqXG4gICAqIFJldHVybiBhIE1vZHVsZU1ldGFkYXRhIGZvciB0aGUgZ2l2ZW4gbW9kdWxlLlxuICAgKiBBbmd1bGFyIENMSSB3aWxsIHByb2R1Y2UgdGhpcyBtZXRhZGF0YSBmb3IgYSBtb2R1bGUgd2hlbmV2ZXIgYSAuZC50cyBmaWxlcyBpc1xuICAgKiBwcm9kdWNlZCBhbmQgdGhlIG1vZHVsZSBoYXMgZXhwb3J0ZWQgdmFyaWFibGVzIG9yIGNsYXNzZXMgd2l0aCBkZWNvcmF0b3JzLiBNb2R1bGUgbWV0YWRhdGEgY2FuXG4gICAqIGFsc28gYmUgcHJvZHVjZWQgZGlyZWN0bHkgZnJvbSBUeXBlU2NyaXB0IHNvdXJjZXMgYnkgdXNpbmcgTWV0YWRhdGFDb2xsZWN0b3IgaW4gdG9vbHMvbWV0YWRhdGEuXG4gICAqXG4gICAqIEBwYXJhbSBtb2R1bGVQYXRoIGlzIGEgc3RyaW5nIGlkZW50aWZpZXIgZm9yIGEgbW9kdWxlIGFzIGFuIGFic29sdXRlIHBhdGguXG4gICAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBmb3IgdGhlIGdpdmVuIG1vZHVsZS5cbiAgICovXG4gIGdldE1ldGFkYXRhRm9yKG1vZHVsZVBhdGg6IHN0cmluZyk6IHtba2V5OiBzdHJpbmddOiBhbnl9W118dW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIG1vZHVsZSBuYW1lIHRoYXQgaXMgdXNlZCBpbiBhbiBgaW1wb3J0YCB0byBhIGZpbGUgcGF0aC5cbiAgICogSS5lLlxuICAgKiBgcGF0aC90by9jb250YWluaW5nRmlsZS50c2AgY29udGFpbmluZyBgaW1wb3J0IHsuLi59IGZyb20gJ21vZHVsZS1uYW1lJ2AuXG4gICAqL1xuICBtb2R1bGVOYW1lVG9GaWxlTmFtZShtb2R1bGVOYW1lOiBzdHJpbmcsIGNvbnRhaW5pbmdGaWxlPzogc3RyaW5nKTogc3RyaW5nfG51bGw7XG5cbiAgLyoqXG4gICAqIEdldCBhIGZpbGUgc3VpdGFibGUgZm9yIGRpc3BsYXkgdG8gdGhlIHVzZXIgdGhhdCBzaG91bGQgYmUgcmVsYXRpdmUgdG8gdGhlIHByb2plY3QgZGlyZWN0b3J5XG4gICAqIG9yIHRoZSBjdXJyZW50IGRpcmVjdG9yeS5cbiAgICovXG4gIGdldE91dHB1dE5hbWUoZmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZztcbn1cblxuY29uc3QgU1VQUE9SVEVEX1NDSEVNQV9WRVJTSU9OID0gNDtcblxuLyoqXG4gKiBUaGlzIGNsYXNzIGlzIHJlc3BvbnNpYmxlIGZvciBsb2FkaW5nIG1ldGFkYXRhIHBlciBzeW1ib2wsXG4gKiBhbmQgbm9ybWFsaXppbmcgcmVmZXJlbmNlcyBiZXR3ZWVuIHN5bWJvbHMuXG4gKlxuICogSW50ZXJuYWxseSwgaXQgb25seSB1c2VzIHN5bWJvbHMgd2l0aG91dCBtZW1iZXJzLFxuICogYW5kIGRlZHVjZXMgdGhlIHZhbHVlcyBmb3Igc3ltYm9scyB3aXRoIG1lbWJlcnMgYmFzZWRcbiAqIG9uIHRoZXNlIHN5bWJvbHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGF0aWNTeW1ib2xSZXNvbHZlciB7XG4gIHByaXZhdGUgbWV0YWRhdGFDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCB7W2tleTogc3RyaW5nXTogYW55fT4oKTtcbiAgLy8gTm90ZTogdGhpcyB3aWxsIG9ubHkgY29udGFpbiBTdGF0aWNTeW1ib2xzIHdpdGhvdXQgbWVtYmVycyFcbiAgcHJpdmF0ZSByZXNvbHZlZFN5bWJvbHMgPSBuZXcgTWFwPFN0YXRpY1N5bWJvbCwgUmVzb2x2ZWRTdGF0aWNTeW1ib2w+KCk7XG4gIC8vIE5vdGU6IHRoaXMgd2lsbCBvbmx5IGNvbnRhaW4gU3RhdGljU3ltYm9scyB3aXRob3V0IG1lbWJlcnMhXG4gIHByaXZhdGUgaW1wb3J0QXMgPSBuZXcgTWFwPFN0YXRpY1N5bWJvbCwgU3RhdGljU3ltYm9sPigpO1xuICBwcml2YXRlIHN5bWJvbFJlc291cmNlUGF0aHMgPSBuZXcgTWFwPFN0YXRpY1N5bWJvbCwgc3RyaW5nPigpO1xuICBwcml2YXRlIHN5bWJvbEZyb21GaWxlID0gbmV3IE1hcDxzdHJpbmcsIFN0YXRpY1N5bWJvbFtdPigpO1xuICBwcml2YXRlIGtub3duRmlsZU5hbWVUb01vZHVsZU5hbWVzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgaG9zdDogU3RhdGljU3ltYm9sUmVzb2x2ZXJIb3N0LCBwcml2YXRlIHN0YXRpY1N5bWJvbENhY2hlOiBTdGF0aWNTeW1ib2xDYWNoZSxcbiAgICAgIHByaXZhdGUgc3VtbWFyeVJlc29sdmVyOiBTdW1tYXJ5UmVzb2x2ZXI8U3RhdGljU3ltYm9sPixcbiAgICAgIHByaXZhdGUgZXJyb3JSZWNvcmRlcj86IChlcnJvcjogYW55LCBmaWxlTmFtZT86IHN0cmluZykgPT4gdm9pZCkge31cblxuICByZXNvbHZlU3ltYm9sKHN0YXRpY1N5bWJvbDogU3RhdGljU3ltYm9sKTogUmVzb2x2ZWRTdGF0aWNTeW1ib2wge1xuICAgIGlmIChzdGF0aWNTeW1ib2wubWVtYmVycy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVzb2x2ZVN5bWJvbE1lbWJlcnMoc3RhdGljU3ltYm9sKSE7XG4gICAgfVxuICAgIC8vIE5vdGU6IGFsd2F5cyBhc2sgZm9yIGEgc3VtbWFyeSBmaXJzdCxcbiAgICAvLyBhcyB3ZSBtaWdodCBoYXZlIHJlYWQgc2hhbGxvdyBtZXRhZGF0YSB2aWEgYSAuZC50cyBmaWxlXG4gICAgLy8gZm9yIHRoZSBzeW1ib2wuXG4gICAgY29uc3QgcmVzdWx0RnJvbVN1bW1hcnkgPSB0aGlzLl9yZXNvbHZlU3ltYm9sRnJvbVN1bW1hcnkoc3RhdGljU3ltYm9sKSE7XG4gICAgaWYgKHJlc3VsdEZyb21TdW1tYXJ5KSB7XG4gICAgICByZXR1cm4gcmVzdWx0RnJvbVN1bW1hcnk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdEZyb21DYWNoZSA9IHRoaXMucmVzb2x2ZWRTeW1ib2xzLmdldChzdGF0aWNTeW1ib2wpO1xuICAgIGlmIChyZXN1bHRGcm9tQ2FjaGUpIHtcbiAgICAgIHJldHVybiByZXN1bHRGcm9tQ2FjaGU7XG4gICAgfVxuICAgIC8vIE5vdGU6IFNvbWUgdXNlcnMgdXNlIGxpYnJhcmllcyB0aGF0IHdlcmUgbm90IGNvbXBpbGVkIHdpdGggbmdjLCBpLmUuIHRoZXkgZG9uJ3RcbiAgICAvLyBoYXZlIHN1bW1hcmllcywgb25seSAuZC50cyBmaWxlcy4gU28gd2UgYWx3YXlzIG5lZWQgdG8gY2hlY2sgYm90aCwgdGhlIHN1bW1hcnlcbiAgICAvLyBhbmQgbWV0YWRhdGEuXG4gICAgdGhpcy5fY3JlYXRlU3ltYm9sc09mKHN0YXRpY1N5bWJvbC5maWxlUGF0aCk7XG4gICAgcmV0dXJuIHRoaXMucmVzb2x2ZWRTeW1ib2xzLmdldChzdGF0aWNTeW1ib2wpITtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXRJbXBvcnRBcyBwcm9kdWNlcyBhIHN5bWJvbCB0aGF0IGNhbiBiZSB1c2VkIHRvIGltcG9ydCB0aGUgZ2l2ZW4gc3ltYm9sLlxuICAgKiBUaGUgaW1wb3J0IG1pZ2h0IGJlIGRpZmZlcmVudCB0aGFuIHRoZSBzeW1ib2wgaWYgdGhlIHN5bWJvbCBpcyBleHBvcnRlZCBmcm9tXG4gICAqIGEgbGlicmFyeSB3aXRoIGEgc3VtbWFyeTsgaW4gd2hpY2ggY2FzZSB3ZSB3YW50IHRvIGltcG9ydCB0aGUgc3ltYm9sIGZyb20gdGhlXG4gICAqIG5nZmFjdG9yeSByZS1leHBvcnQgaW5zdGVhZCBvZiBkaXJlY3RseSB0byBhdm9pZCBpbnRyb2R1Y2luZyBhIGRpcmVjdCBkZXBlbmRlbmN5XG4gICAqIG9uIGFuIG90aGVyd2lzZSBpbmRpcmVjdCBkZXBlbmRlbmN5LlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGljU3ltYm9sIHRoZSBzeW1ib2wgZm9yIHdoaWNoIHRvIGdlbmVyYXRlIGEgaW1wb3J0IHN5bWJvbFxuICAgKi9cbiAgZ2V0SW1wb3J0QXMoc3RhdGljU3ltYm9sOiBTdGF0aWNTeW1ib2wsIHVzZVN1bW1hcmllczogYm9vbGVhbiA9IHRydWUpOiBTdGF0aWNTeW1ib2x8bnVsbCB7XG4gICAgaWYgKHN0YXRpY1N5bWJvbC5tZW1iZXJzLmxlbmd0aCkge1xuICAgICAgY29uc3QgYmFzZVN5bWJvbCA9IHRoaXMuZ2V0U3RhdGljU3ltYm9sKHN0YXRpY1N5bWJvbC5maWxlUGF0aCwgc3RhdGljU3ltYm9sLm5hbWUpO1xuICAgICAgY29uc3QgYmFzZUltcG9ydEFzID0gdGhpcy5nZXRJbXBvcnRBcyhiYXNlU3ltYm9sLCB1c2VTdW1tYXJpZXMpO1xuICAgICAgcmV0dXJuIGJhc2VJbXBvcnRBcyA/XG4gICAgICAgICAgdGhpcy5nZXRTdGF0aWNTeW1ib2woYmFzZUltcG9ydEFzLmZpbGVQYXRoLCBiYXNlSW1wb3J0QXMubmFtZSwgc3RhdGljU3ltYm9sLm1lbWJlcnMpIDpcbiAgICAgICAgICBudWxsO1xuICAgIH1cbiAgICBjb25zdCBzdW1tYXJpemVkRmlsZU5hbWUgPSBzdHJpcFN1bW1hcnlGb3JKaXRGaWxlU3VmZml4KHN0YXRpY1N5bWJvbC5maWxlUGF0aCk7XG4gICAgaWYgKHN1bW1hcml6ZWRGaWxlTmFtZSAhPT0gc3RhdGljU3ltYm9sLmZpbGVQYXRoKSB7XG4gICAgICBjb25zdCBzdW1tYXJpemVkTmFtZSA9IHN0cmlwU3VtbWFyeUZvckppdE5hbWVTdWZmaXgoc3RhdGljU3ltYm9sLm5hbWUpO1xuICAgICAgY29uc3QgYmFzZVN5bWJvbCA9XG4gICAgICAgICAgdGhpcy5nZXRTdGF0aWNTeW1ib2woc3VtbWFyaXplZEZpbGVOYW1lLCBzdW1tYXJpemVkTmFtZSwgc3RhdGljU3ltYm9sLm1lbWJlcnMpO1xuICAgICAgY29uc3QgYmFzZUltcG9ydEFzID0gdGhpcy5nZXRJbXBvcnRBcyhiYXNlU3ltYm9sLCB1c2VTdW1tYXJpZXMpO1xuICAgICAgcmV0dXJuIGJhc2VJbXBvcnRBcyA/IHRoaXMuZ2V0U3RhdGljU3ltYm9sKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5Rm9ySml0RmlsZU5hbWUoYmFzZUltcG9ydEFzLmZpbGVQYXRoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VtbWFyeUZvckppdE5hbWUoYmFzZUltcG9ydEFzLm5hbWUpLCBiYXNlU3ltYm9sL