@angular/core
Version:
Angular - the core framework
632 lines • 67 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @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
*/
import { getCompilerFacade } from '../../compiler/compiler_facade';
import { resolveForwardRef } from '../../di/forward_ref';
import { NG_INJECTOR_DEF } from '../../di/interface/defs';
import { reflectDependencies } from '../../di/jit/util';
import { flatten } from '../../util/array_utils';
import { assertDefined } from '../../util/assert';
import { getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef } from '../definition';
import { NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_MODULE_DEF, NG_PIPE_DEF } from '../fields';
import { maybeUnwrapFn, stringifyForError } from '../util/misc_utils';
import { angularCoreEnv } from './environment';
/** @type {?} */
const EMPTY_ARRAY = [];
/**
* @record
*/
function ModuleQueueItem() { }
if (false) {
/** @type {?} */
ModuleQueueItem.prototype.moduleType;
/** @type {?} */
ModuleQueueItem.prototype.ngModule;
}
/** @type {?} */
const moduleQueue = [];
/**
* Enqueues moduleDef to be checked later to see if scope can be set on its
* component declarations.
* @param {?} moduleType
* @param {?} ngModule
* @return {?}
*/
function enqueueModuleForDelayedScoping(moduleType, ngModule) {
moduleQueue.push({ moduleType, ngModule });
}
/** @type {?} */
let flushingModuleQueue = false;
/**
* Loops over queued module definitions, if a given module definition has all of its
* declarations resolved, it dequeues that module definition and sets the scope on
* its declarations.
* @return {?}
*/
export function flushModuleScopingQueueAsMuchAsPossible() {
if (!flushingModuleQueue) {
flushingModuleQueue = true;
try {
for (let i = moduleQueue.length - 1; i >= 0; i--) {
const { moduleType, ngModule } = moduleQueue[i];
if (ngModule.declarations && ngModule.declarations.every(isResolvedDeclaration)) {
// dequeue
moduleQueue.splice(i, 1);
setScopeOnDeclaredComponents(moduleType, ngModule);
}
}
}
finally {
flushingModuleQueue = false;
}
}
}
/**
* Returns truthy if a declaration has resolved. If the declaration happens to be
* an array of declarations, it will recurse to check each declaration in that array
* (which may also be arrays).
* @param {?} declaration
* @return {?}
*/
function isResolvedDeclaration(declaration) {
if (Array.isArray(declaration)) {
return declaration.every(isResolvedDeclaration);
}
return !!resolveForwardRef(declaration);
}
/**
* Compiles a module in JIT mode.
*
* This function automatically gets called when a class has a `\@NgModule` decorator.
* @param {?} moduleType
* @param {?=} ngModule
* @return {?}
*/
export function compileNgModule(moduleType, ngModule = {}) {
compileNgModuleDefs((/** @type {?} */ (moduleType)), ngModule);
// Because we don't know if all declarations have resolved yet at the moment the
// NgModule decorator is executing, we're enqueueing the setting of module scope
// on its declarations to be run at a later time when all declarations for the module,
// including forward refs, have resolved.
enqueueModuleForDelayedScoping(moduleType, ngModule);
}
/**
* Compiles and adds the `ngModuleDef` and `ngInjectorDef` properties to the module class.
*
* It's possible to compile a module via this API which will allow duplicate declarations in its
* root.
* @param {?} moduleType
* @param {?} ngModule
* @param {?=} allowDuplicateDeclarationsInRoot
* @return {?}
*/
export function compileNgModuleDefs(moduleType, ngModule, allowDuplicateDeclarationsInRoot = false) {
ngDevMode && assertDefined(moduleType, 'Required value moduleType');
ngDevMode && assertDefined(ngModule, 'Required value ngModule');
/** @type {?} */
const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
/** @type {?} */
/** @nocollapse */ let ngModuleDef = null;
Object.defineProperty(moduleType, NG_MODULE_DEF, {
configurable: true,
get: (/**
* @return {?}
*/
() => {
if (ngModuleDef === null) {
ngModuleDef = getCompilerFacade().compileNgModule(angularCoreEnv, `ng:///${moduleType.name}/ngModuleDef.js`, {
type: moduleType,
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef),
declarations: declarations.map(resolveForwardRef),
imports: flatten(ngModule.imports || EMPTY_ARRAY)
.map(resolveForwardRef)
.map(expandModuleWithProviders),
exports: flatten(ngModule.exports || EMPTY_ARRAY)
.map(resolveForwardRef)
.map(expandModuleWithProviders),
emitInline: true,
schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
id: ngModule.id || null,
});
}
return ngModuleDef;
})
});
/** @type {?} */
/** @nocollapse */ let ngInjectorDef = null;
Object.defineProperty(moduleType, NG_INJECTOR_DEF, {
get: (/**
* @return {?}
*/
() => {
if (ngInjectorDef === null) {
ngDevMode && verifySemanticsOfNgModuleDef((/** @type {?} */ ((/** @type {?} */ (moduleType)))), allowDuplicateDeclarationsInRoot);
/** @type {?} */
const meta = {
name: moduleType.name,
type: moduleType,
deps: reflectDependencies(moduleType),
providers: ngModule.providers || EMPTY_ARRAY,
imports: [
(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef),
(ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef),
],
};
ngInjectorDef = getCompilerFacade().compileInjector(angularCoreEnv, `ng:///${moduleType.name}/ngInjectorDef.js`, meta);
}
return ngInjectorDef;
}),
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
});
}
/**
* @param {?} moduleType
* @param {?} allowDuplicateDeclarationsInRoot
* @return {?}
*/
function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot) {
if (verifiedNgModule.get(moduleType))
return;
verifiedNgModule.set(moduleType, true);
moduleType = resolveForwardRef(moduleType);
/** @type {?} */
/** @nocollapse */ const ngModuleDef = getNgModuleDef(moduleType, true);
/** @type {?} */
const errors = [];
/** @type {?} */
const declarations = maybeUnwrapFn(ngModuleDef.declarations);
/** @type {?} */
const imports = maybeUnwrapFn(ngModuleDef.imports);
flatten(imports)
.map(unwrapModuleWithProvidersImports)
.forEach((/**
* @param {?} mod
* @return {?}
*/
mod => verifySemanticsOfNgModuleDef(mod, false)));
/** @type {?} */
const exports = maybeUnwrapFn(ngModuleDef.exports);
declarations.forEach(verifyDeclarationsHaveDefinitions);
/** @type {?} */
const combinedDeclarations = [
...declarations.map(resolveForwardRef),
...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef),
];
exports.forEach(verifyExportsAreDeclaredOrReExported);
declarations.forEach((/**
* @param {?} decl
* @return {?}
*/
decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot)));
declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
/** @type {?} */
const ngModule = getAnnotation(moduleType, 'NgModule');
if (ngModule) {
ngModule.imports &&
flatten(ngModule.imports)
.map(unwrapModuleWithProvidersImports)
.forEach((/**
* @param {?} mod
* @return {?}
*/
mod => verifySemanticsOfNgModuleDef(mod, false)));
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyCorrectBootstrapType);
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
ngModule.entryComponents && ngModule.entryComponents.forEach(verifyComponentIsPartOfNgModule);
}
// Throw Error if any errors were detected.
if (errors.length) {
throw new Error(errors.join('\n'));
}
////////////////////////////////////////////////////////////////////////////////////////////////
/**
* @param {?} type
* @return {?}
*/
function verifyDeclarationsHaveDefinitions(type) {
type = resolveForwardRef(type);
/** @type {?} */
const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef(type);
if (!def) {
errors.push(`Unexpected value '${stringifyForError(type)}' declared by the module '${stringifyForError(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`);
}
}
/**
* @param {?} type
* @return {?}
*/
function verifyExportsAreDeclaredOrReExported(type) {
type = resolveForwardRef(type);
/** @type {?} */
const kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' ||
getPipeDef(type) && 'pipe';
if (kind) {
// only checked if we are declared as Component, Directive, or Pipe
// Modules don't need to be declared or imported.
if (combinedDeclarations.lastIndexOf(type) === -1) {
// We are exporting something which we don't explicitly declare or import.
errors.push(`Can't export ${kind} ${stringifyForError(type)} from ${stringifyForError(moduleType)} as it was neither declared nor imported!`);
}
}
}
/**
* @param {?} type
* @param {?} suppressErrors
* @return {?}
*/
function verifyDeclarationIsUnique(type, suppressErrors) {
type = resolveForwardRef(type);
/** @type {?} */
const existingModule = ownerNgModule.get(type);
if (existingModule && existingModule !== moduleType) {
if (!suppressErrors) {
/** @type {?} */
const modules = [existingModule, moduleType].map(stringifyForError).sort();
errors.push(`Type ${stringifyForError(type)} is part of the declarations of 2 modules: ${modules[0]} and ${modules[1]}! ` +
`Please consider moving ${stringifyForError(type)} to a higher module that imports ${modules[0]} and ${modules[1]}. ` +
`You can also create a new NgModule that exports and includes ${stringifyForError(type)} then import that NgModule in ${modules[0]} and ${modules[1]}.`);
}
}
else {
// Mark type as having owner.
ownerNgModule.set(type, moduleType);
}
}
/**
* @param {?} type
* @return {?}
*/
function verifyComponentIsPartOfNgModule(type) {
type = resolveForwardRef(type);
/** @type {?} */
const existingModule = ownerNgModule.get(type);
if (!existingModule) {
errors.push(`Component ${stringifyForError(type)} is not part of any NgModule or the module has not been imported into your module.`);
}
}
/**
* @param {?} type
* @return {?}
*/
function verifyCorrectBootstrapType(type) {
type = resolveForwardRef(type);
if (!getComponentDef(type)) {
errors.push(`${stringifyForError(type)} cannot be used as an entry component.`);
}
}
/**
* @param {?} type
* @return {?}
*/
function verifyComponentEntryComponentsIsPartOfNgModule(type) {
type = resolveForwardRef(type);
if (getComponentDef(type)) {
// We know we are component
/** @type {?} */
const component = getAnnotation(type, 'Component');
if (component && component.entryComponents) {
component.entryComponents.forEach(verifyComponentIsPartOfNgModule);
}
}
}
}
/**
* @param {?} typeOrWithProviders
* @return {?}
*/
function unwrapModuleWithProvidersImports(typeOrWithProviders) {
typeOrWithProviders = resolveForwardRef(typeOrWithProviders);
return ((/** @type {?} */ (typeOrWithProviders))).ngModule || typeOrWithProviders;
}
/**
* @template T
* @param {?} type
* @param {?} name
* @return {?}
*/
function getAnnotation(type, name) {
/** @type {?} */
let annotation = null;
collect(type.__annotations__);
collect(type.decorators);
return annotation;
/**
* @param {?} annotations
* @return {?}
*/
function collect(annotations) {
if (annotations) {
annotations.forEach(readAnnotation);
}
}
/**
* @param {?} decorator
* @return {?}
*/
function readAnnotation(decorator) {
if (!annotation) {
/** @type {?} */
const proto = Object.getPrototypeOf(decorator);
if (proto.ngMetadataName == name) {
annotation = (/** @type {?} */ (decorator));
}
else if (decorator.type) {
/** @type {?} */
const proto = Object.getPrototypeOf(decorator.type);
if (proto.ngMetadataName == name) {
annotation = decorator.args[0];
}
}
}
}
}
/**
* Keep track of compiled components. This is needed because in tests we often want to compile the
* same component with more than one NgModule. This would cause an error unless we reset which
* NgModule the component belongs to. We keep the list of compiled components here so that the
* TestBed can reset it later.
* @type {?}
*/
let ownerNgModule = new Map();
/** @type {?} */
let verifiedNgModule = new Map();
/**
* @return {?}
*/
export function resetCompiledComponents() {
ownerNgModule = new Map();
verifiedNgModule = new Map();
moduleQueue.length = 0;
}
/**
* Computes the combined declarations of explicit declarations, as well as declarations inherited by
* traversing the exports of imported modules.
* @param {?} type
* @return {?}
*/
function computeCombinedExports(type) {
type = resolveForwardRef(type);
/** @type {?} */
/** @nocollapse */ const ngModuleDef = getNgModuleDef(type, true);
return [...flatten(maybeUnwrapFn(ngModuleDef.exports).map((/**
* @param {?} type
* @return {?}
*/
(type) => {
/** @type {?} */
/** @nocollapse */ const ngModuleDef = getNgModuleDef(type);
if (ngModuleDef) {
verifySemanticsOfNgModuleDef((/** @type {?} */ ((/** @type {?} */ (type)))), false);
return computeCombinedExports(type);
}
else {
return type;
}
})))];
}
/**
* Some declared components may be compiled asynchronously, and thus may not have their
* ngComponentDef set yet. If this is the case, then a reference to the module is written into
* the `ngSelectorScope` property of the declared type.
* @param {?} moduleType
* @param {?} ngModule
* @return {?}
*/
function setScopeOnDeclaredComponents(moduleType, ngModule) {
/** @type {?} */
const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
/** @type {?} */
const transitiveScopes = transitiveScopesFor(moduleType);
declarations.forEach((/**
* @param {?} declaration
* @return {?}
*/
declaration => {
if (declaration.hasOwnProperty(NG_COMPONENT_DEF)) {
// An `ngComponentDef` field exists - go ahead and patch the component directly.
/** @type {?} */
const component = (/** @type {?} */ (declaration));
/** @type {?} */
const componentDef = (/** @type {?} */ (getComponentDef(component)));
patchComponentDefWithScope(componentDef, transitiveScopes);
}
else if (!declaration.hasOwnProperty(NG_DIRECTIVE_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) {
// Set `ngSelectorScope` for future reference when the component compilation finishes.
((/** @type {?} */ (declaration))).ngSelectorScope = moduleType;
}
}));
}
/**
* Patch the definition of a component with directives and pipes from the compilation scope of
* a given module.
* @template C
* @param {?} componentDef
* @param {?} transitiveScopes
* @return {?}
*/
export function patchComponentDefWithScope(componentDef, transitiveScopes) {
componentDef.directiveDefs = (/**
* @return {?}
*/
() => Array.from(transitiveScopes.compilation.directives)
.map((/**
* @param {?} dir
* @return {?}
*/
dir => dir.hasOwnProperty(NG_COMPONENT_DEF) ? (/** @type {?} */ (getComponentDef(dir))) :
(/** @type {?} */ (getDirectiveDef(dir)))))
.filter((/**
* @param {?} def
* @return {?}
*/
def => !!def)));
componentDef.pipeDefs = (/**
* @return {?}
*/
() => Array.from(transitiveScopes.compilation.pipes).map((/**
* @param {?} pipe
* @return {?}
*/
pipe => (/** @type {?} */ (getPipeDef(pipe))))));
componentDef.schemas = transitiveScopes.schemas;
// Since we avoid Components/Directives/Pipes recompiling in case there are no overrides, we
// may face a problem where previously compiled defs available to a given Component/Directive
// are cached in TView and may become stale (in case any of these defs gets recompiled). In
// order to avoid this problem, we force fresh TView to be created.
componentDef.tView = null;
}
/**
* Compute the pair of transitive scopes (compilation scope and exported scope) for a given module.
*
* This operation is memoized and the result is cached on the module's definition. It can be called
* on modules with components that have not fully compiled yet, but the result should not be used
* until they have.
* @template T
* @param {?} moduleType
* @param {?=} processNgModuleFn
* @return {?}
*/
export function transitiveScopesFor(moduleType, processNgModuleFn) {
if (!isNgModule(moduleType)) {
throw new Error(`${moduleType.name} does not have an ngModuleDef`);
}
/** @type {?} */
const def = (/** @type {?} */ (getNgModuleDef(moduleType)));
if (def.transitiveCompileScopes !== null) {
return def.transitiveCompileScopes;
}
/** @type {?} */
const scopes = {
schemas: def.schemas || null,
compilation: {
directives: new Set(),
pipes: new Set(),
},
exported: {
directives: new Set(),
pipes: new Set(),
},
};
maybeUnwrapFn(def.declarations).forEach((/**
* @param {?} declared
* @return {?}
*/
declared => {
/** @type {?} */
const declaredWithDefs = (/** @type {?} */ (declared));
if (getPipeDef(declaredWithDefs)) {
scopes.compilation.pipes.add(declared);
}
else {
// Either declared has an ngComponentDef or ngDirectiveDef, or it's a component which hasn't
// had its template compiled yet. In either case, it gets added to the compilation's
// directives.
scopes.compilation.directives.add(declared);
}
}));
maybeUnwrapFn(def.imports).forEach((/**
* @template I
* @param {?} imported
* @return {?}
*/
(imported) => {
/** @type {?} */
const importedType = (/** @type {?} */ (imported));
if (!isNgModule(importedType)) {
throw new Error(`Importing ${importedType.name} which does not have an ngModuleDef`);
}
if (processNgModuleFn) {
processNgModuleFn((/** @type {?} */ (importedType)));
}
// When this module imports another, the imported module's exported directives and pipes are
// added to the compilation scope of this module.
/** @type {?} */
const importedScope = transitiveScopesFor(importedType, processNgModuleFn);
importedScope.exported.directives.forEach((/**
* @param {?} entry
* @return {?}
*/
entry => scopes.compilation.directives.add(entry)));
importedScope.exported.pipes.forEach((/**
* @param {?} entry
* @return {?}
*/
entry => scopes.compilation.pipes.add(entry)));
}));
maybeUnwrapFn(def.exports).forEach((/**
* @template E
* @param {?} exported
* @return {?}
*/
(exported) => {
/** @type {?} */
const exportedType = (/** @type {?} */ (exported));
// Either the type is a module, a pipe, or a component/directive (which may not have an
// ngComponentDef as it might be compiled asynchronously).
if (isNgModule(exportedType)) {
// When this module exports another, the exported module's exported directives and pipes are
// added to both the compilation and exported scopes of this module.
/** @type {?} */
const exportedScope = transitiveScopesFor(exportedType, processNgModuleFn);
exportedScope.exported.directives.forEach((/**
* @param {?} entry
* @return {?}
*/
entry => {
scopes.compilation.directives.add(entry);
scopes.exported.directives.add(entry);
}));
exportedScope.exported.pipes.forEach((/**
* @param {?} entry
* @return {?}
*/
entry => {
scopes.compilation.pipes.add(entry);
scopes.exported.pipes.add(entry);
}));
}
else if (getPipeDef(exportedType)) {
scopes.exported.pipes.add(exportedType);
}
else {
scopes.exported.directives.add(exportedType);
}
}));
def.transitiveCompileScopes = scopes;
return scopes;
}
/**
* @param {?} value
* @return {?}
*/
function expandModuleWithProviders(value) {
if (isModuleWithProviders(value)) {
return value.ngModule;
}
return value;
}
/**
* @param {?} value
* @return {?}
*/
function isModuleWithProviders(value) {
return ((/** @type {?} */ (value))).ngModule !== undefined;
}
/**
* @template T
* @param {?} value
* @return {?}
*/
function isNgModule(value) {
return !!getNgModuleDef(value);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kdWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29yZS9zcmMvcmVuZGVyMy9qaXQvbW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBUUEsT0FBTyxFQUEyQixpQkFBaUIsRUFBQyxNQUFNLGdDQUFnQyxDQUFDO0FBQzNGLE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ3ZELE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsbUJBQW1CLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQztBQUl0RCxPQUFPLEVBQUMsT0FBTyxFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDL0MsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ2hELE9BQU8sRUFBQyxlQUFlLEVBQUUsZUFBZSxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDM0YsT0FBTyxFQUFDLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFHekYsT0FBTyxFQUFDLGFBQWEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBRXBFLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSxlQUFlLENBQUM7O01BRXZDLFdBQVcsR0FBZ0IsRUFBRTs7OztBQUVuQyw4QkFHQzs7O0lBRkMscUNBQXNCOztJQUN0QixtQ0FBbUI7OztNQUdmLFdBQVcsR0FBc0IsRUFBRTs7Ozs7Ozs7QUFNekMsU0FBUyw4QkFBOEIsQ0FBQyxVQUFxQixFQUFFLFFBQWtCO0lBQy9FLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBQyxVQUFVLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQztBQUMzQyxDQUFDOztJQUVHLG1CQUFtQixHQUFHLEtBQUs7Ozs7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Q2YsQ0FBQzs7Ozs7QUFFRCxTQUFTLHFCQUFxQixDQUFDLEtBQVU7SUFDdkMsT0FBTyxDQUFDLG1CQUFBLEtBQUssRUFBbUIsQ0FBQyxDQUFDLFFBQVEsS0FBSyxTQUFTLENBQUM7QUFDM0QsQ0FBQzs7Ozs7O0FBRUQsU0FBUyxVQUFVLENBQUksS0FBYztJQUNuQyxPQUFPLENBQUMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDakMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtSM0luamVjdG9yTWV0YWRhdGFGYWNhZGUsIGdldENvbXBpbGVyRmFjYWRlfSBmcm9tICcuLi8uLi9jb21waWxlci9jb21waWxlcl9mYWNhZGUnO1xuaW1wb3J0IHtyZXNvbHZlRm9yd2FyZFJlZn0gZnJvbSAnLi4vLi4vZGkvZm9yd2FyZF9yZWYnO1xuaW1wb3J0IHtOR19JTkpFQ1RPUl9ERUZ9IGZyb20gJy4uLy4uL2RpL2ludGVyZmFjZS9kZWZzJztcbmltcG9ydCB7cmVmbGVjdERlcGVuZGVuY2llc30gZnJvbSAnLi4vLi4vZGkvaml0L3V0aWwnO1xuaW1wb3J0IHtUeXBlfSBmcm9tICcuLi8uLi9pbnRlcmZhY2UvdHlwZSc7XG5pbXBvcnQge0NvbXBvbmVudH0gZnJvbSAnLi4vLi4vbWV0YWRhdGEnO1xuaW1wb3J0IHtNb2R1bGVXaXRoUHJvdmlkZXJzLCBOZ01vZHVsZSwgTmdNb2R1bGVEZWYsIE5nTW9kdWxlVHJhbnNpdGl2ZVNjb3Blc30gZnJvbSAnLi4vLi4vbWV0YWRhdGEvbmdfbW9kdWxlJztcbmltcG9ydCB7ZmxhdHRlbn0gZnJvbSAnLi4vLi4vdXRpbC9hcnJheV91dGlscyc7XG5pbXBvcnQge2Fzc2VydERlZmluZWR9IGZyb20gJy4uLy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7Z2V0Q29tcG9uZW50RGVmLCBnZXREaXJlY3RpdmVEZWYsIGdldE5nTW9kdWxlRGVmLCBnZXRQaXBlRGVmfSBmcm9tICcuLi9kZWZpbml0aW9uJztcbmltcG9ydCB7TkdfQ09NUE9ORU5UX0RFRiwgTkdfRElSRUNUSVZFX0RFRiwgTkdfTU9EVUxFX0RFRiwgTkdfUElQRV9ERUZ9IGZyb20gJy4uL2ZpZWxkcyc7XG5pbXBvcnQge0NvbXBvbmVudERlZn0gZnJvbSAnLi4vaW50ZXJmYWNlcy9kZWZpbml0aW9uJztcbmltcG9ydCB7TmdNb2R1bGVUeXBlfSBmcm9tICcuLi9uZ19tb2R1bGVfcmVmJztcbmltcG9ydCB7bWF5YmVVbndyYXBGbiwgc3RyaW5naWZ5Rm9yRXJyb3J9IGZyb20gJy4uL3V0aWwvbWlzY191dGlscyc7XG5cbmltcG9ydCB7YW5ndWxhckNvcmVFbnZ9IGZyb20gJy4vZW52aXJvbm1lbnQnO1xuXG5jb25zdCBFTVBUWV9BUlJBWTogVHlwZTxhbnk+W10gPSBbXTtcblxuaW50ZXJmYWNlIE1vZHVsZVF1ZXVlSXRlbSB7XG4gIG1vZHVsZVR5cGU6IFR5cGU8YW55PjtcbiAgbmdNb2R1bGU6IE5nTW9kdWxlO1xufVxuXG5jb25zdCBtb2R1bGVRdWV1ZTogTW9kdWxlUXVldWVJdGVtW10gPSBbXTtcblxuLyoqXG4gKiBFbnF1ZXVlcyBtb2R1bGVEZWYgdG8gYmUgY2hlY2tlZCBsYXRlciB0byBzZWUgaWYgc2NvcGUgY2FuIGJlIHNldCBvbiBpdHNcbiAqIGNvbXBvbmVudCBkZWNsYXJhdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIGVucXVldWVNb2R1bGVGb3JEZWxheWVkU2NvcGluZyhtb2R1bGVUeXBlOiBUeXBlPGFueT4sIG5nTW9kdWxlOiBOZ01vZHVsZSkge1xuICBtb2R1bGVRdWV1ZS5wdXNoKHttb2R1bGVUeXBlLCBuZ01vZHVsZX0pO1xufVxuXG5sZXQgZmx1c2hpbmdNb2R1bGVRdWV1ZSA9IGZhbHNlO1xuLyoqXG4gKiBMb29wcyBvdmVyIHF1ZXVlZCBtb2R1bGUgZGVmaW5pdGlvbnMsIGlmIGEgZ2l2ZW4gbW9kdWxlIGRlZmluaXRpb24gaGFzIGFsbCBvZiBpdHNcbiAqIGRlY2xhcmF0aW9ucyByZXNvbHZlZCwgaXQgZGVxdWV1ZXMgdGhhdCBtb2R1bGUgZGVmaW5pdGlvbiBhbmQgc2V0cyB0aGUgc2NvcGUgb25cbiAqIGl0cyBkZWNsYXJhdGlvbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaE1vZHVsZVNjb3BpbmdRdWV1ZUFzTXVjaEFzUG9zc2libGUoKSB7XG4gIGlmICghZmx1c2hpbmdNb2R1bGVRdWV1ZSkge1xuICAgIGZsdXNoaW5nTW9kdWxlUXVldWUgPSB0cnVlO1xuICAgIHRyeSB7XG4gICAgICBmb3IgKGxldCBpID0gbW9kdWxlUXVldWUubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgY29uc3Qge21vZHVsZVR5cGUsIG5nTW9kdWxlfSA9IG1vZHVsZVF1ZXVlW2ldO1xuXG4gICAgICAgIGlmIChuZ01vZHVsZS5kZWNsYXJhdGlvbnMgJiYgbmdNb2R1bGUuZGVjbGFyYXRpb25zLmV2ZXJ5KGlzUmVzb2x2ZWREZWNsYXJhdGlvbikpIHtcbiAgICAgICAgICAvLyBkZXF1ZXVlXG4gICAgICAgICAgbW9kdWxlUXVldWUuc3BsaWNlKGksIDEpO1xuICAgICAgICAgIHNldFNjb3BlT25EZWNsYXJlZENvbXBvbmVudHMobW9kdWxlVHlwZSwgbmdNb2R1bGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGZsdXNoaW5nTW9kdWxlUXVldWUgPSBmYWxzZTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydXRoeSBpZiBhIGRlY2xhcmF0aW9uIGhhcyByZXNvbHZlZC4gSWYgdGhlIGRlY2xhcmF0aW9uIGhhcHBlbnMgdG8gYmVcbiAqIGFuIGFycmF5IG9mIGRlY2xhcmF0aW9ucywgaXQgd2lsbCByZWN1cnNlIHRvIGNoZWNrIGVhY2ggZGVjbGFyYXRpb24gaW4gdGhhdCBhcnJheVxuICogKHdoaWNoIG1heSBhbHNvIGJlIGFycmF5cykuXG4gKi9cbmZ1bmN0aW9uIGlzUmVzb2x2ZWREZWNsYXJhdGlvbihkZWNsYXJhdGlvbjogYW55W10gfCBUeXBlPGFueT4pOiBib29sZWFuIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoZGVjbGFyYXRpb24pKSB7XG4gICAgcmV0dXJuIGRlY2xhcmF0aW9uLmV2ZXJ5KGlzUmVzb2x2ZWREZWNsYXJhdGlvbik7XG4gIH1cbiAgcmV0dXJuICEhcmVzb2x2ZUZvcndhcmRSZWYoZGVjbGFyYXRpb24pO1xufVxuXG4vKipcbiAqIENvbXBpbGVzIGEgbW9kdWxlIGluIEpJVCBtb2RlLlxuICpcbiAqIFRoaXMgZnVuY3Rpb24gYXV0b21hdGljYWxseSBnZXRzIGNhbGxlZCB3aGVuIGEgY2xhc3MgaGFzIGEgYEBOZ01vZHVsZWAgZGVjb3JhdG9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZU5nTW9kdWxlKG1vZHVsZVR5cGU6IFR5cGU8YW55PiwgbmdNb2R1bGU6IE5nTW9kdWxlID0ge30pOiB2b2lkIHtcbiAgY29tcGlsZU5nTW9kdWxlRGVmcyhtb2R1bGVUeXBlIGFzIE5nTW9kdWxlVHlwZSwgbmdNb2R1bGUpO1xuXG4gIC8vIEJlY2F1c2Ugd2UgZG9uJ3Qga25vdyBpZiBhbGwgZGVjbGFyYXRpb25zIGhhdmUgcmVzb2x2ZWQgeWV0IGF0IHRoZSBtb21lbnQgdGhlXG4gIC8vIE5nTW9kdWxlIGRlY29yYXRvciBpcyBleGVjdXRpbmcsIHdlJ3JlIGVucXVldWVpbmcgdGhlIHNldHRpbmcgb2YgbW9kdWxlIHNjb3BlXG4gIC8vIG9uIGl0cyBkZWNsYXJhdGlvbnMgdG8gYmUgcnVuIGF0IGEgbGF0ZXIgdGltZSB3aGVuIGFsbCBkZWNsYXJhdGlvbnMgZm9yIHRoZSBtb2R1bGUsXG4gIC8vIGluY2x1ZGluZyBmb3J3YXJkIHJlZnMsIGhhdmUgcmVzb2x2ZWQuXG4gIGVucXVldWVNb2R1bGVGb3JEZWxheWVkU2NvcGluZyhtb2R1bGVUeXBlLCBuZ01vZHVsZSk7XG59XG5cbi8qKlxuICogQ29tcGlsZXMgYW5kIGFkZHMgdGhlIGBuZ01vZHVsZURlZmAgYW5kIGBuZ0luamVjdG9yRGVmYCBwcm9wZXJ0aWVzIHRvIHRoZSBtb2R1bGUgY2xhc3MuXG4gKlxuICogSXQncyBwb3NzaWJsZSB0byBjb21waWxlIGEgbW9kdWxlIHZpYSB0aGlzIEFQSSB3aGljaCB3aWxsIGFsbG93IGR1cGxpY2F0ZSBkZWNsYXJhdGlvbnMgaW4gaXRzXG4gKiByb290LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZU5nTW9kdWxlRGVmcyhcbiAgICBtb2R1bGVUeXBlOiBOZ01vZHVsZVR5cGUsIG5nTW9kdWxlOiBOZ01vZHVsZSxcbiAgICBhbGxvd0R1cGxpY2F0ZURlY2xhcmF0aW9uc0luUm9vdDogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gIG5nRGV2TW9kZSAmJiBhc3NlcnREZWZpbmVkKG1vZHVsZVR5cGUsICdSZXF1aXJlZCB2YWx1ZSBtb2R1bGVUeXBlJyk7XG4gIG5nRGV2TW9kZSAmJiBhc3NlcnREZWZpbmVkKG5nTW9kdWxlLCAnUmVxdWlyZWQgdmFsdWUgbmdNb2R1bGUnKTtcbiAgY29uc3QgZGVjbGFyYXRpb25zOiBUeXBlPGFueT5bXSA9IGZsYXR0ZW4obmdNb2R1bGUuZGVjbGFyYXRpb25zIHx8IEVNUFRZX0FSUkFZKTtcbiAgbGV0IG5nTW9kdWxlRGVmOiBhbnkgPSBudWxsO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kdWxlVHlwZSwgTkdfTU9EVUxFX0RFRiwge1xuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICBnZXQ6ICgpID0+IHtcbiAgICAgIGlmIChuZ01vZHVsZURlZiA9PT0gbnVsbCkge1xuICAgICAgICBuZ01vZHVsZURlZiA9IGdldENvbXBpbGVyRmFjYWRlKCkuY29tcGlsZU5nTW9kdWxlKFxuICAgICAgICAgICAgYW5ndWxhckNvcmVFbnYsIGBuZzovLy8ke21vZHVsZVR5cGUubmFtZX0vbmdNb2R1bGVEZWYuanNgLCB7XG4gICAgICAgICAgICAgIHR5cGU6IG1vZHVsZVR5cGUsXG4gICAgICAgICAgICAgIGJvb3RzdHJhcDogZmxhdHRlbihuZ01vZHVsZS5ib290c3RyYXAgfHwgRU1QVFlfQVJSQVkpLm1hcChyZXNvbHZlRm9yd2FyZFJlZiksXG4gICAgICAgICAgICAgIGRlY2xhcmF0aW9uczogZGVjbGFyYXRpb25zLm1hcChyZXNvbHZlRm9yd2FyZFJlZiksXG4gICAgICAgICAgICAgIGltcG9ydHM6IGZsYXR0ZW4obmdNb2R1bGUuaW1wb3J0cyB8fCBFTVBUWV9BUlJBWSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAocmVzb2x2ZUZvcndhcmRSZWYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKGV4cGFuZE1vZHVsZVdpdGhQcm92aWRlcnMpLFxuICAgICAgICAgICAgICBleHBvcnRzOiBmbGF0dGVuKG5nTW9kdWxlLmV4cG9ydHMgfHwgRU1QVFlfQVJSQVkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKHJlc29sdmVGb3J3YXJkUmVmKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLm1hcChleHBhbmRNb2R1bGVXaXRoUHJvdmlkZXJzKSxcbiAgICAgICAgICAgICAgZW1pdElubGluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgc2NoZW1hczogbmdNb2R1bGUuc2NoZW1hcyA/IGZsYXR0ZW4obmdNb2R1bGUuc2NoZW1hcykgOiBudWxsLFxuICAgICAgICAgICAgICBpZDogbmdNb2R1bGUuaWQgfHwgbnVsbCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5nTW9kdWxlRGVmO1xuICAgIH1cbiAgfSk7XG5cbiAgbGV0IG5nSW5qZWN0b3JEZWY6IGFueSA9IG51bGw7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGVUeXBlLCBOR19JTkpFQ1RPUl9ERUYsIHtcbiAgICBnZXQ6ICgpID0+IHtcbiAgICAgIGlmIChuZ0luamVjdG9yRGVmID09PSBudWxsKSB7XG4gICAgICAgIG5nRGV2TW9kZSAmJiB2ZXJpZnlTZW1hbnRpY3NPZk5nTW9kdWxlRGVmKFxuICAgICAgICAgICAgICAgICAgICAgICAgIG1vZHVsZVR5cGUgYXMgYW55IGFzIE5nTW9kdWxlVHlwZSwgYWxsb3dEdXBsaWNhdGVEZWNsYXJhdGlvbnNJblJvb3QpO1xuICAgICAgICBjb25zdCBtZXRhOiBSM0luamVjdG9yTWV0YWRhdGFGYWNhZGUgPSB7XG4gICAgICAgICAgbmFtZTogbW9kdWxlVHlwZS5uYW1lLFxuICAgICAgICAgIHR5cGU6IG1vZHVsZVR5cGUsXG4gICAgICAgICAgZGVwczogcmVmbGVjdERlcGVuZGVuY2llcyhtb2R1bGVUeXBlKSxcbiAgICAgICAgICBwcm92aWRlcnM6IG5nTW9kdWxlLnByb3ZpZGVycyB8fCBFTVBUWV9BUlJBWSxcbiAgICAgICAgICBpbXBvcnRzOiBbXG4gICAgICAgICAgICAobmdNb2R1bGUuaW1wb3J0cyB8fCBFTVBUWV9BUlJBWSkubWFwKHJlc29sdmVGb3J3YXJkUmVmKSxcbiAgICAgICAgICAgIChuZ01vZHVsZS5leHBvcnRzIHx8IEVNUFRZX0FSUkFZKS5tYXAocmVzb2x2ZUZvcndhcmRSZWYpLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICAgIG5nSW5qZWN0b3JEZWYgPSBnZXRDb21waWxlckZhY2FkZSgpLmNvbXBpbGVJbmplY3RvcihcbiAgICAgICAgICAgIGFuZ3VsYXJDb3JlRW52LCBgbmc6Ly8vJHttb2R1bGVUeXBlLm5hbWV9L25nSW5qZWN0b3JEZWYuanNgLCBtZXRhKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZ0luamVjdG9yRGVmO1xuICAgIH0sXG4gICAgLy8gTWFrZSB0aGUgcHJvcGVydHkgY29uZmlndXJhYmxlIGluIGRldiBtb2RlIHRvIGFsbG93IG92ZXJyaWRpbmcgaW4gdGVzdHNcbiAgICBjb25maWd1cmFibGU6ICEhbmdEZXZNb2RlLFxuICB9KTtcbn1cblxuZnVuY3Rpb24gdmVyaWZ5U2VtYW50aWNzT2ZOZ01vZHVsZURlZihcbiAgICBtb2R1bGVUeXBlOiBOZ01vZHVsZVR5cGUsIGFsbG93RHVwbGljYXRlRGVjbGFyYXRpb25zSW5Sb290OiBib29sZWFuKTogdm9pZCB7XG4gIGlmICh2ZXJpZmllZE5nTW9kdWxlLmdldChtb2R1bGVUeXBlKSkgcmV0dXJuO1xuICB2ZXJpZmllZE5nTW9kdWxlLnNldChtb2R1bGVUeXBlLCB0cnVlKTtcbiAgbW9kdWxlVHlwZSA9IHJlc29sdmVGb3J3YXJkUmVmKG1vZHVsZVR5cGUpO1xuICBjb25zdCBuZ01vZHVsZURlZiA9IGdldE5nTW9kdWxlRGVmKG1vZHVsZVR5cGUsIHRydWUpO1xuICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IGRlY2xhcmF0aW9ucyA9IG1heWJlVW53cmFwRm4obmdNb2R1bGVEZWYuZGVjbGFyYXRpb25zKTtcbiAgY29uc3QgaW1wb3J0cyA9IG1heWJlVW53cmFwRm4obmdNb2R1bGVEZWYuaW1wb3J0cyk7XG4gIGZsYXR0ZW4oaW1wb3J0cylcbiAgICAgIC5tYXAodW53cmFwTW9kdWxlV2l0aFByb3ZpZGVyc0ltcG9ydHMpXG4gICAgICAuZm9yRWFjaChtb2QgPT4gdmVyaWZ5U2VtYW50aWNzT2ZOZ01vZHVsZURlZihtb2QsIGZhbHNlKSk7XG4gIGNvbnN0IGV4cG9ydHMgPSBtYXliZVVud3JhcEZuKG5nTW9kdWxlRGVmLmV4cG9ydHMpO1xuICBkZWNsYXJhdGlvbnMuZm9yRWFjaCh2ZXJpZnlEZWNsYXJhdGlvbnNIYXZlRGVmaW5pdGlvbnMpO1xuICBjb25zdCBjb21iaW5lZERlY2xhcmF0aW9uczogVHlwZTxhbnk+W10gPSBbXG4gICAgLi4uZGVjbGFyYXRpb25zLm1hcChyZXNvbHZlRm9yd2FyZFJlZiksICAvL1xuICAgIC4uLmZsYXR0ZW4oaW1wb3J0cy5tYXAoY29tcHV0ZUNvbWJpbmVkRXhwb3J0cykpLm1hcChyZXNvbHZlRm9yd2FyZFJlZiksXG4gIF07XG4gIGV4cG9ydHMuZm9yRWFjaCh2ZXJpZnlFeHBvcnRzQXJlRGVjbGFyZWRPclJlRXhwb3J0ZWQpO1xuICBkZWNsYXJhdGlvbnMuZm9yRWFjaChkZWNsID0+IHZlcmlmeURlY2xhcmF0aW9uSXNVbmlxdWUoZGVjbCwgYWxsb3dEdXBsaWNhdGVEZWNsYXJhdGlvbnNJblJvb3QpKTtcbiAgZGVjbGFyYXRpb25zLmZvckVhY2godmVyaWZ5Q29tcG9uZW50RW50cnlDb21wb25lbnRzSXNQYXJ0T2ZOZ01vZHVsZSk7XG5cbiAgY29uc3QgbmdNb2R1bGUgPSBnZXR