UNPKG

@angular/core

Version:

Angular - the core framework

163 lines 26.2 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 { resolveForwardRef } from '../../di'; import { RuntimeError } from '../../errors'; import { assertEqual } from '../../util/assert'; import { EMPTY_OBJ } from '../../util/empty'; import { getComponentDef, getDirectiveDef } from '../definition'; /** * This feature adds the host directives behavior to a directive definition by patching a * function onto it. The expectation is that the runtime will invoke the function during * directive matching. * * For example: * ```ts * class ComponentWithHostDirective { * static ɵcmp = defineComponent({ * type: ComponentWithHostDirective, * features: [ɵɵHostDirectivesFeature([ * SimpleHostDirective, * {directive: AdvancedHostDirective, inputs: ['foo: alias'], outputs: ['bar']}, * ])] * }); * } * ``` * * @codeGenApi */ export function ɵɵHostDirectivesFeature(rawHostDirectives) { const feature = (definition) => { const resolved = (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => { return typeof dir === 'function' ? { directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } : { directive: resolveForwardRef(dir.directive), inputs: bindingArrayToMap(dir.inputs), outputs: bindingArrayToMap(dir.outputs) }; }); if (definition.hostDirectives === null) { definition.findHostDirectiveDefs = findHostDirectiveDefs; definition.hostDirectives = resolved; } else { definition.hostDirectives.unshift(...resolved); } }; feature.ngInherit = true; return feature; } function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) { if (currentDef.hostDirectives !== null) { for (const hostDirectiveConfig of currentDef.hostDirectives) { const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive); if (typeof ngDevMode === 'undefined' || ngDevMode) { validateHostDirective(hostDirectiveConfig, hostDirectiveDef); } // We need to patch the `declaredInputs` so that // `ngOnChanges` can map the properties correctly. patchDeclaredInputs(hostDirectiveDef.declaredInputs, hostDirectiveConfig.inputs); // Host directives execute before the host so that its host bindings can be overwritten. findHostDirectiveDefs(hostDirectiveDef, matchedDefs, hostDirectiveDefs); hostDirectiveDefs.set(hostDirectiveDef, hostDirectiveConfig); matchedDefs.push(hostDirectiveDef); } } } /** * Converts an array in the form of `['publicName', 'alias', 'otherPublicName', 'otherAlias']` into * a map in the form of `{publicName: 'alias', otherPublicName: 'otherAlias'}`. */ function bindingArrayToMap(bindings) { if (bindings === undefined || bindings.length === 0) { return EMPTY_OBJ; } const result = {}; for (let i = 0; i < bindings.length; i += 2) { result[bindings[i]] = bindings[i + 1]; } return result; } /** * `ngOnChanges` has some leftover legacy ViewEngine behavior where the keys inside the * `SimpleChanges` event refer to the *declared* name of the input, not its public name or its * minified name. E.g. in `@Input('alias') foo: string`, the name in the `SimpleChanges` object * will always be `foo`, and not `alias` or the minified name of `foo` in apps using property * minification. * * This is achieved through the `DirectiveDef.declaredInputs` map that is constructed when the * definition is declared. When a property is written to the directive instance, the * `NgOnChangesFeature` will try to remap the property name being written to using the * `declaredInputs`. * * Since the host directive input remapping happens during directive matching, `declaredInputs` * won't contain the new alias that the input is available under. This function addresses the * issue by patching the host directive aliases to the `declaredInputs`. There is *not* a risk of * this patching accidentally introducing new inputs to the host directive, because `declaredInputs` * is used *only* by the `NgOnChangesFeature` when determining what name is used in the * `SimpleChanges` object which won't be reached if an input doesn't exist. */ function patchDeclaredInputs(declaredInputs, exposedInputs) { for (const publicName in exposedInputs) { if (exposedInputs.hasOwnProperty(publicName)) { const remappedPublicName = exposedInputs[publicName]; const privateName = declaredInputs[publicName]; // We *technically* shouldn't be able to hit this case because we can't have multiple // inputs on the same property and we have validations against conflicting aliases in // `validateMappings`. If we somehow did, it would lead to `ngOnChanges` being invoked // with the wrong name so we have a non-user-friendly assertion here just in case. if ((typeof ngDevMode === 'undefined' || ngDevMode) && declaredInputs.hasOwnProperty(remappedPublicName)) { assertEqual(declaredInputs[remappedPublicName], declaredInputs[publicName], `Conflicting host directive input alias ${publicName}.`); } declaredInputs[remappedPublicName] = privateName; } } } /** * Verifies that the host directive has been configured correctly. * @param hostDirectiveConfig Host directive configuration object. * @param directiveDef Directive definition of the host directive. */ function validateHostDirective(hostDirectiveConfig, directiveDef) { const type = hostDirectiveConfig.directive; if (directiveDef === null) { if (getComponentDef(type) !== null) { throw new RuntimeError(310 /* RuntimeErrorCode.HOST_DIRECTIVE_COMPONENT */, `Host directive ${type.name} cannot be a component.`); } throw new RuntimeError(307 /* RuntimeErrorCode.HOST_DIRECTIVE_UNRESOLVABLE */, `Could not resolve metadata for host directive ${type.name}. ` + `Make sure that the ${type.name} class is annotated with an @Directive decorator.`); } if (!directiveDef.standalone) { throw new RuntimeError(308 /* RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE */, `Host directive ${directiveDef.type.name} must be standalone.`); } validateMappings('input', directiveDef, hostDirectiveConfig.inputs); validateMappings('output', directiveDef, hostDirectiveConfig.outputs); } /** * Checks that the host directive inputs/outputs configuration is valid. * @param bindingType Kind of binding that is being validated. Used in the error message. * @param def Definition of the host directive that is being validated against. * @param hostDirectiveBindings Host directive mapping object that shold be validated. */ function validateMappings(bindingType, def, hostDirectiveBindings) { const className = def.type.name; const bindings = bindingType === 'input' ? def.inputs : def.outputs; for (const publicName in hostDirectiveBindings) { if (hostDirectiveBindings.hasOwnProperty(publicName)) { if (!bindings.hasOwnProperty(publicName)) { throw new RuntimeError(311 /* RuntimeErrorCode.HOST_DIRECTIVE_UNDEFINED_BINDING */, `Directive ${className} does not have an ${bindingType} with a public name of ${publicName}.`); } const remappedPublicName = hostDirectiveBindings[publicName]; if (bindings.hasOwnProperty(remappedPublicName) && remappedPublicName !== publicName) { throw new RuntimeError(312 /* RuntimeErrorCode.HOST_DIRECTIVE_CONFLICTING_ALIAS */, `Cannot alias ${bindingType} ${publicName} of host directive ${className} to ${remappedPublicName}, because it already has a different ${bindingType} with the same public name.`); } } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdF9kaXJlY3RpdmVzX2ZlYXR1cmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXIzL2ZlYXR1cmVzL2hvc3RfZGlyZWN0aXZlc19mZWF0dXJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUNILE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUMzQyxPQUFPLEVBQUMsWUFBWSxFQUFtQixNQUFNLGNBQWMsQ0FBQztBQUU1RCxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxlQUFlLEVBQUUsZUFBZSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBVS9EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLGlCQUM2QjtJQUNuRSxNQUFNLE9BQU8sR0FBd0IsQ0FBQyxVQUFpQyxFQUFFLEVBQUU7UUFDekUsTUFBTSxRQUFRLEdBQ1YsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3JGLE9BQU8sT0FBTyxHQUFHLEtBQUssVUFBVSxDQUFDLENBQUM7Z0JBQzlCLEVBQUMsU0FBUyxFQUFFLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBQyxDQUFDLENBQUM7Z0JBQzVFO29CQUNFLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDO29CQUMzQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsR0FB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RyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUNoQyxNQUFNLFFBQVEsR0FBRyxXQUFXLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDO0lBRXBFLEtBQUssTUFBTSxVQUFVLElBQUkscUJBQXFCLEVBQUUsQ0FBQztRQUMvQyxJQUFJLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sSUFBSSxZQUFZLDhEQUVsQixhQUFhLFNBQVMscUJBQXFCLFdBQVcsMEJBQ2xELFVBQVUsR0FBRyxDQUFDLENBQUM7WUFDekIsQ0FBQztZQUVELE1BQU0sa0JBQWtCLEdBQUcscUJBQXFCLENBQUMsVUFBVSxDQUFDLENBQUM7WUFFN0QsSUFBSSxRQUFRLENBQUMsY0FBYyxDQUFDLGtCQUFrQixDQUFDLElBQUksa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3JGLE1BQU0sSUFBSSxZQUFZLDhEQUVsQixnQkFBZ0IsV0FBVyxJQUFJLFVBQVUsc0JBQXNCLFNBQVMsT0FDcEUsa0JBQWtCLHdDQUNsQixXQUFXLDZCQUE2QixDQUFDLENBQUM7WUFDcEQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuaW1wb3J0IHtyZXNvbHZlRm9yd2FyZFJlZn0gZnJvbSAnLi4vLi4vZGknO1xuaW1wb3J0IHtSdW50aW1lRXJyb3IsIFJ1bnRpbWVFcnJvckNvZGV9IGZyb20gJy4uLy4uL2Vycm9ycyc7XG5pbXBvcnQge1R5cGV9IGZyb20gJy4uLy4uL2ludGVyZmFjZS90eXBlJztcbmltcG9ydCB7YXNzZXJ0RXF1YWx9IGZyb20gJy4uLy4uL3V0aWwvYXNzZXJ0JztcbmltcG9ydCB7RU1QVFlfT0JKfSBmcm9tICcuLi8uLi91dGlsL2VtcHR5JztcbmltcG9ydCB7Z2V0Q29tcG9uZW50RGVmLCBnZXREaXJlY3RpdmVEZWZ9IGZyb20gJy4uL2RlZmluaXRpb24nO1xuaW1wb3J0IHtEaXJlY3RpdmVEZWYsIERpcmVjdGl2ZURlZkZlYXR1cmUsIEhvc3REaXJlY3RpdmVCaW5kaW5nTWFwLCBIb3N0RGlyZWN0aXZlRGVmLCBIb3N0RGlyZWN0aXZlRGVmc30gZnJvbSAnLi4vaW50ZXJmYWNlcy9kZWZpbml0aW9uJztcblxuLyoqIFZhbHVlcyB0aGF0IGNhbiBiZSB1c2VkIHRvIGRlZmluZSBhIGhvc3QgZGlyZWN0aXZlIHRocm91Z2ggdGhlIGBIb3N0RGlyZWN0aXZlc0ZlYXR1cmVgLiAqL1xudHlwZSBIb3N0RGlyZWN0aXZlQ29uZmlnID0gVHlwZTx1bmtub3duPnx7XG4gIGRpcmVjdGl2ZTogVHlwZTx1bmtub3duPjtcbiAgaW5wdXRzPzogc3RyaW5nW107XG4gIG91dHB1dHM/OiBzdHJpbmdbXTtcbn07XG5cbi8qKlxuICogVGhpcyBmZWF0dXJlIGFkZHMgdGhlIGhvc3QgZGlyZWN0aXZlcyBiZWhhdmlvciB0byBhIGRpcmVjdGl2ZSBkZWZpbml0aW9uIGJ5IHBhdGNoaW5nIGFcbiAqIGZ1bmN0aW9uIG9udG8gaXQuIFRoZSBleHBlY3RhdGlvbiBpcyB0aGF0IHRoZSBydW50aW1lIHdpbGwgaW52b2tlIHRoZSBmdW5jdGlvbiBkdXJpbmdcbiAqIGRpcmVjdGl2ZSBtYXRjaGluZy5cbiAqXG4gKiBGb3IgZXhhbXBsZTpcbiAqIGBgYHRzXG4gKiBjbGFzcyBDb21wb25lbnRXaXRoSG9zdERpcmVjdGl2ZSB7XG4gKiAgIHN0YXRpYyDJtWNtcCA9IGRlZmluZUNvbXBvbmVudCh7XG4gKiAgICB0eXBlOiBDb21wb25lbnRXaXRoSG9zdERpcmVjdGl2ZSxcbiAqICAgIGZlYXR1cmVzOiBbybXJtUhvc3REaXJlY3RpdmVzRmVhdHVyZShbXG4gKiAgICAgIFNpbXBsZUhvc3REaXJlY3RpdmUsXG4gKiAgICAgIHtkaXJlY3RpdmU6IEFkdmFuY2VkSG9zdERpcmVjdGl2ZSwgaW5wdXRzOiBbJ2ZvbzogYWxpYXMnXSwgb3V0cHV0czogWydiYXInXX0sXG4gKiAgICBdKV1cbiAqICB9KTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBjb2RlR2VuQXBpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiDJtcm1SG9zdERpcmVjdGl2ZXNGZWF0dXJlKHJhd0hvc3REaXJlY3RpdmVzOiBIb3N0RGlyZWN0aXZlQ29uZmlnW118XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCgpID0+IEhvc3REaXJlY3RpdmVDb25maWdbXSkpIHtcbiAgY29uc3QgZmVhdHVyZTogRGlyZWN0aXZlRGVmRmVhdHVyZSA9IChkZWZpbml0aW9uOiBEaXJlY3RpdmVEZWY8dW5rbm93bj4pID0+IHtcbiAgICBjb25zdCByZXNvbHZlZCA9XG4gICAgICAgIChBcnJheS5pc0FycmF5KHJhd0hvc3REaXJlY3RpdmVzKSA/IHJhd0hvc3REaXJlY3RpdmVzIDogcmF3SG9zdERpcmVjdGl2ZXMoKSkubWFwKGRpciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHR5cGVvZiBkaXIgPT09ICdmdW5jdGlvbicgP1xuICAgICAgICAgICAgICB7ZGlyZWN0aXZlOiByZXNvbHZlRm9yd2FyZFJlZihkaXIpLCBpbnB1dHM6IEVNUFRZX09CSiwgb3V0cHV0czogRU1QVFlfT0JKfSA6XG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBkaXJlY3RpdmU6IHJlc29sdmVGb3J3YXJkUmVmKGRpci5kaXJlY3RpdmUpLFxuICAgICAgICAgICAgICAgIGlucHV0czogYmluZGluZ0FycmF5VG9NYXAoZGlyLmlucHV0cyksXG4gICAgICAgICAgICAgICAgb3V0cHV0czogYmluZGluZ0FycmF5VG9NYXAoZGlyLm91dHB1dHMpXG4gICAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIGlmIChkZWZpbml0aW9uLmhvc3REaXJlY3RpdmVzID09PSBudWxsKSB7XG4gICAgICBkZWZpbml0aW9uLmZpbmRIb3N0RGlyZWN0aXZlRGVmcyA9IGZpbmRIb3N0RGlyZWN0aXZlRGVmcztcbiAgICAgIGRlZmluaXRpb24uaG9zdERpcmVjdGl2ZXMgPSByZXNvbHZlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVmaW5pdGlvbi5ob3N0RGlyZWN0aXZlcy51bnNoaWZ0KC4uLnJlc29sdmVkKTtcbiAgICB9XG4gIH07XG4gIGZlYXR1cmUubmdJbmhlcml0ID0gdHJ1ZTtcbiAgcmV0dXJuIGZlYXR1cmU7XG59XG5cbmZ1bmN0aW9uIGZpbmRIb3N0RGlyZWN0aXZlRGVmcyhcbiAgICBjdXJyZW50RGVmOiBEaXJlY3RpdmVEZWY8dW5rbm93bj4sIG1hdGNoZWREZWZzOiBEaXJlY3RpdmVEZWY8dW5rbm93bj5bXSxcbiAgICBob3N0RGlyZWN0aXZlRGVmczogSG9zdERpcmVjdGl2ZURlZnMpOiB2b2lkIHtcbiAgaWYgKGN1cnJlbnREZWYuaG9zdERpcmVjdGl2ZXMgIT09IG51bGwpIHtcbiAgICBmb3IgKGNvbnN0IGhvc3REaXJlY3RpdmVDb25maWcgb2YgY3VycmVudERlZi5ob3N0RGlyZWN0aXZlcykge1xuICAgICAgY29uc3QgaG9zdERpcmVjdGl2ZURlZiA9IGdldERpcmVjdGl2ZURlZihob3N0RGlyZWN0aXZlQ29uZmlnLmRpcmVjdGl2ZSkhO1xuXG4gICAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSB7XG4gICAgICAgIHZhbGlkYXRlSG9zdERpcmVjdGl2ZShob3N0RGlyZWN0aXZlQ29uZmlnLCBob3N0RGlyZWN0aXZlRGVmKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2UgbmVlZCB0byBwYXRjaCB0aGUgYGRlY2xhcmVkSW5wdXRzYCBzbyB0aGF0XG4gICAgICAvLyBgbmdPbkNoYW5nZXNgIGNhbiBtYXAgdGhlIHByb3BlcnRpZXMgY29ycmVjdGx5LlxuICAgICAgcGF0Y2hEZWNsYXJlZElucHV0cyhob3N0RGlyZWN0aXZlRGVmLmRlY2xhcmVkSW5wdXRzLCBob3N0RGlyZWN0aXZlQ29uZmlnLmlucHV0cyk7XG5cbiAgICAgIC8vIEhvc3QgZGlyZWN0aXZlcyBleGVjdXRlIGJlZm9yZSB0aGUgaG9zdCBzbyB0aGF0IGl0cyBob3N0IGJpbmRpbmdzIGNhbiBiZSBvdmVyd3JpdHRlbi5cbiAgICAgIGZpbmRIb3N0RGlyZWN0aXZlRGVmcyhob3N0RGlyZWN0aXZlRGVmLCBtYXRjaGVkRGVmcywgaG9zdERpcmVjdGl2ZURlZnMpO1xuICAgICAgaG9zdERpcmVjdGl2ZURlZnMuc2V0KGhvc3REaXJlY3RpdmVEZWYsIGhvc3REaXJlY3RpdmVDb25maWcpO1xuICAgICAgbWF0Y2hlZERlZnMucHVzaChob3N0RGlyZWN0aXZlRGVmKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhbiBhcnJheSBpbiB0aGUgZm9ybSBvZiBgWydwdWJsaWNOYW1lJywgJ2FsaWFzJywgJ290aGVyUHVibGljTmFtZScsICdvdGhlckFsaWFzJ11gIGludG9cbiAqIGEgbWFwIGluIHRoZSBmb3JtIG9mIGB7cHVibGljTmFtZTogJ2FsaWFzJywgb3RoZXJQdWJsaWNOYW1lOiAnb3RoZXJBbGlhcyd9YC5cbiAqL1xuZnVuY3Rpb24gYmluZGluZ0FycmF5VG9NYXAoYmluZGluZ3M6IHN0cmluZ1tdfHVuZGVmaW5lZCk6IEhvc3REaXJlY3RpdmVCaW5kaW5nTWFwIHtcbiAgaWYgKGJpbmRpbmdzID09PSB1bmRlZmluZWQgfHwgYmluZGluZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEVNUFRZX09CSjtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogSG9zdERpcmVjdGl2ZUJpbmRpbmdNYXAgPSB7fTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGJpbmRpbmdzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgcmVzdWx0W2JpbmRpbmdzW2ldXSA9IGJpbmRpbmdzW2kgKyAxXTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogYG5nT25DaGFuZ2VzYCBoYXMgc29tZSBsZWZ0b3ZlciBsZWdhY3kgVmlld0VuZ2luZSBiZWhhdmlvciB3aGVyZSB0aGUga2V5cyBpbnNpZGUgdGhlXG4gKiBgU2ltcGxlQ2hhbmdlc2AgZXZlbnQgcmVmZXIgdG8gdGhlICpkZWNsYXJlZCogbmFtZSBvZiB0aGUgaW5wdXQsIG5vdCBpdHMgcHVibGljIG5hbWUgb3IgaXRzXG4gKiBtaW5pZmllZCBuYW1lLiBFLmcuIGluIGBASW5wdXQoJ2FsaWFzJykgZm9vOiBzdHJpbmdgLCB0aGUgbmFtZSBpbiB0aGUgYFNpbXBsZUNoYW5nZXNgIG9iamVjdFxuICogd2lsbCBhbHdheXMgYmUgYGZvb2AsIGFuZCBub3QgYGFsaWFzYCBvciB0aGUgbWluaWZpZWQgbmFtZSBvZiBgZm9vYCBpbiBhcHBzIHVzaW5nIHByb3BlcnR5XG4gKiBtaW5pZmljYXRpb24uXG4gKlxuICogVGhpcyBpcyBhY2hpZXZlZCB0aHJvdWdoIHRoZSBgRGlyZWN0aXZlRGVmLmRlY2xhcmVkSW5wdXRzYCBtYXAgdGhhdCBpcyBjb25zdHJ1Y3RlZCB3aGVuIHRoZVxuICogZGVmaW5pdGlvbiBpcyBkZWNsYXJlZC4gV2hlbiBhIHByb3BlcnR5IGlzIHdyaXR0ZW4gdG8gdGhlIGRpcmVjdGl2ZSBpbnN0YW5jZSwgdGhlXG4gKiBgTmdPbkNoYW5nZXNGZWF0dXJlYCB3aWxsIHRyeSB0byByZW1hcCB0aGUgcHJvcGVydHkgbmFtZSBiZWluZyB3cml0dGVuIHRvIHVzaW5nIHRoZVxuICogYGRlY2xhcmVkSW5wdXRzYC5cbiAqXG4gKiBTaW5jZSB0aGUgaG9zdCBkaXJlY3RpdmUgaW5wdXQgcmVtYXBwaW5nIGhhcHBlbnMgZHVyaW5nIGRpcmVjdGl2ZSBtYXRjaGluZywgYGRlY2xhcmVkSW5wdXRzYFxuICogd29uJ3QgY29udGFpbiB0aGUgbmV3IGFsaWFzIHRoYXQgdGhlIGlucHV0IGlzIGF2YWlsYWJsZSB1bmRlci4gVGhpcyBmdW5jdGlvbiBhZGRyZXNzZXMgdGhlXG4gKiBpc3N1ZSBieSBwYXRjaGluZyB0aGUgaG9zdCBkaXJlY3RpdmUgYWxpYXNlcyB0byB0aGUgYGRlY2xhcmVkSW5wdXRzYC4gVGhlcmUgaXMgKm5vdCogYSByaXNrIG9mXG4gKiB0aGlzIHBhdGNoaW5nIGFjY2lkZW50YWxseSBpbnRyb2R1Y2luZyBuZXcgaW5wdXRzIHRvIHRoZSBob3N0IGRpcmVjdGl2ZSwgYmVjYXVzZSBgZGVjbGFyZWRJbnB1dHNgXG4gKiBpcyB1c2VkICpvbmx5KiBieSB0aGUgYE5nT25DaGFuZ2VzRmVhdHVyZWAgd2hlbiBkZXRlcm1pbmluZyB3aGF0IG5hbWUgaXMgdXNlZCBpbiB0aGVcbiAqIGBTaW1wbGVDaGFuZ2VzYCBvYmplY3Qgd2hpY2ggd29uJ3QgYmUgcmVhY2hlZCBpZiBhbiBpbnB1dCBkb2Vzbid0IGV4aXN0LlxuICovXG5mdW5jdGlvbiBwYXRjaERlY2xhcmVkSW5wdXRzKFxuICAgIGRlY2xhcmVkSW5wdXRzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCBleHBvc2VkSW5wdXRzOiBIb3N0RGlyZWN0aXZlQmluZGluZ01hcCk6IHZvaWQge1xuICBmb3IgKGNvbnN0IHB1YmxpY05hbWUgaW4gZXhwb3NlZElucHV0cykge1xuICAgIGlmIChleHBvc2VkSW5wdXRzLmhhc093blByb3BlcnR5KHB1YmxpY05hbWUpKSB7XG4gICAgICBjb25zdCByZW1hcHBlZFB1YmxpY05hbWUgPSBleHBvc2VkSW5wdXRzW3B1YmxpY05hbWVdO1xuICAgICAgY29uc3QgcHJpdmF0ZU5hbWUgPSBkZWNsYXJlZElucHV0c1twdWJsaWNOYW1lXTtcblxuICAgICAgLy8gV2UgKnRlY2huaWNhbGx5KiBzaG91bGRuJ3QgYmUgYWJsZSB0byBoaXQgdGhpcyBjYXNlIGJlY2F1c2Ugd2UgY2FuJ3QgaGF2ZSBtdWx0aXBsZVxuICAgICAgLy8gaW5wdXRzIG9uIHRoZSBzYW1lIHByb3BlcnR5IGFuZCB3ZSBoYXZlIHZhbGlkYXRpb25zIGFnYWluc3QgY29uZmxpY3RpbmcgYWxpYXNlcyBpblxuICAgICAgLy8gYHZhbGlkYXRlTWFwcGluZ3NgLiBJZiB3ZSBzb21laG93IGRpZCwgaXQgd291bGQgbGVhZCB0byBgbmdPbkNoYW5nZXNgIGJlaW5nIGludm9rZWRcbiAgICAgIC8vIHdpdGggdGhlIHdyb25nIG5hbWUgc28gd2UgaGF2ZSBhIG5vbi11c2VyLWZyaWVuZGx5IGFzc2VydGlvbiBoZXJlIGp1c3QgaW4gY2FzZS5cbiAgICAgIGlmICgodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSAmJlxuICAgICAgICAgIGRlY2xhcmVkSW5wdXRzLmhhc093blByb3BlcnR5KHJlbWFwcGVkUHVibGljTmFtZSkpIHtcbiAgICAgICAgYXNzZXJ0RXF1YWwoXG4gICAgICAgICAgICBkZWNsYXJlZElucHV0c1tyZW1hcHBlZFB1YmxpY05hbWVdLCBkZWNsYXJlZElucHV0c1twdWJsaWNOYW1lXSxcbiAgICAgICAgICAgIGBDb25mbGljdGluZyBob3N0IGRpcmVjdGl2ZSBpbnB1dCBhbGlhcyAke3B1YmxpY05hbWV9LmApO1xuICAgICAgfVxuXG4gICAgICBkZWNsYXJlZElucHV0c1tyZW1hcHBlZFB1YmxpY05hbWVdID0gcHJpdmF0ZU5hbWU7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVmVyaWZpZXMgdGhhdCB0aGUgaG9zdCBkaXJlY3RpdmUgaGFzIGJlZW4gY29uZmlndXJlZCBjb3JyZWN0bHkuXG4gKiBAcGFyYW0gaG9zdERpcmVjdGl2ZUNvbmZpZyBIb3N0IGRpcmVjdGl2ZSBjb25maWd1cmF0aW9uIG9iamVjdC5cbiAqIEBwYXJhbSBkaXJlY3RpdmVEZWYgRGlyZWN0aXZlIGRlZmluaXRpb24gb2YgdGhlIGhvc3QgZGlyZWN0aXZlLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUhvc3REaXJlY3RpdmUoXG4gICAgaG9zdERpcmVjdGl2ZUNvbmZpZzogSG9zdERpcmVjdGl2ZURlZjx1bmtub3duPixcbiAgICBkaXJlY3RpdmVEZWY6IERpcmVjdGl2ZURlZjxhbnk+fG51bGwpOiBhc3NlcnRzIGRpcmVjdGl2ZURlZiBpcyBEaXJlY3RpdmVEZWY8dW5rbm93bj4ge1xuICBjb25zdCB0eXBlID0gaG9zdERpcmVjdGl2ZUNvbmZpZy5kaXJlY3RpdmU7XG5cbiAgaWYgKGRpcmVjdGl2ZURlZiA9PT0gbnVsbCkge1xuICAgIGlmIChnZXRDb21wb25lbnREZWYodHlwZSkgIT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICAgICAgUnVudGltZUVycm9yQ29kZS5IT1NUX0RJUkVDVElWRV9DT01QT05FTlQsXG4gICAgICAgICAgYEhvc3QgZGlyZWN0aXZlICR7dHlwZS5uYW1lfSBjYW5ub3QgYmUgYSBjb21wb25lbnQuYCk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICAgICAgUnVudGltZUVycm9yQ29kZS5IT1NUX0RJUkVDVElWRV9VTlJFU09MVkFCTEUsXG4gICAgICAgIGBDb3VsZCBub3QgcmVzb2x2ZSBtZXRhZGF0YSBmb3IgaG9zdCBkaXJlY3RpdmUgJHt0eXBlLm5hbWV9LiBgICtcbiAgICAgICAgICAgIGBNYWtlIHN1cmUgdGhhdCB0aGUgJHt0eXBlLm5hbWV9IGNsYXNzIGlzIGFubm90YXRlZCB3aXRoIGFuIEBEaXJlY3RpdmUgZGVjb3JhdG9yLmApO1xuICB9XG5cbiAgaWYgKCFkaXJlY3RpdmVEZWYuc3RhbmRhbG9uZSkge1xuICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICAgIFJ1bnRpbWVFcnJvckNvZGUuSE9TVF9ESVJFQ1RJVkVfTk9UX1NUQU5EQUxPTkUsXG4gICAgICAgIGBIb3N0IGRpcmVjdGl2ZSAke2RpcmVjdGl2ZURlZi50eXBlLm5hbWV9IG11c3QgYmUgc3RhbmRhbG9uZS5gKTtcbiAgfVxuXG4gIHZhbGlkYXRlTWFwcGluZ3MoJ2lucHV0JywgZGlyZWN0aXZlRGVmLCBob3N0RGlyZWN0aXZlQ29uZmlnLmlucHV0cyk7XG4gIHZhbGlkYXRlTWFwcGluZ3MoJ291dHB1dCcsIGRpcmVjdGl2ZURlZiwgaG9zdERpcmVjdGl2ZUNvbmZpZy5vdXRwdXRzKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgdGhhdCB0aGUgaG9zdCBkaXJlY3RpdmUgaW5wdXRzL291dHB1dHMgY29uZmlndXJhdGlvbiBpcyB2YWxpZC5cbiAqIEBwYXJhbSBiaW5kaW5nVHlwZSBLaW5kIG9mIGJpbmRpbmcgdGhhdCBpcyBiZWluZyB2YWxpZGF0ZWQuIFVzZWQgaW4gdGhlIGVycm9yIG1lc3NhZ2UuXG4gKiBAcGFyYW0gZGVmIERlZmluaXRpb24gb2YgdGhlIGhvc3QgZGlyZWN0aXZlIHRoYXQgaXMgYmVpbmcgdmFsaWRhdGVkIGFnYWluc3QuXG4gKiBAcGFyYW0gaG9zdERpcmVjdGl2ZUJpbmRpbmdzIEhvc3QgZGlyZWN0aXZlIG1hcHBpbmcgb2JqZWN0IHRoYXQgc2hvbGQgYmUgdmFsaWRhdGVkLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZU1hcHBpbmdzPFQ+KFxuICAgIGJpbmRpbmdUeXBlOiAnaW5wdXQnfCdvdXRwdXQnLCBkZWY6IERpcmVjdGl2ZURlZjxUPixcbiAgICBob3N0RGlyZWN0aXZlQmluZGluZ3M6IEhvc3REaXJlY3RpdmVCaW5kaW5nTWFwKSB7XG4gIGNvbnN0IGNsYXNzTmFtZSA9IGRlZi50eXBlLm5hbWU7XG4gIGNvbnN0IGJpbmRpbmdzID0gYmluZGluZ1R5cGUgPT09ICdpbnB1dCcgPyBkZWYuaW5wdXRzIDogZGVmLm91dHB1dHM7XG5cbiAgZm9yIChjb25zdCBwdWJsaWNOYW1lIGluIGhvc3REaXJlY3RpdmVCaW5kaW5ncykge1xuICAgIGlmIChob3N0RGlyZWN0aXZlQmluZGluZ3MuaGFzT3duUHJvcGVydHkocHVibGljTmFtZSkpIHtcbiAgICAgIGlmICghYmluZGluZ3MuaGFzT3duUHJvcGVydHkocHVibGljTmFtZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICAgICAgICAgIFJ1bnRpbWVFcnJvckNvZGUuSE9TVF9ESVJFQ1RJVkVfVU5ERUZJTkVEX0JJTkRJTkcsXG4gICAgICAgICAgICBgRGlyZWN0aXZlICR7Y2xhc3NOYW1lfSBkb2VzIG5vdCBoYXZlIGFuICR7YmluZGluZ1R5cGV9IHdpdGggYSBwdWJsaWMgbmFtZSBvZiAke1xuICAgICAgICAgICAgICAgIHB1YmxpY05hbWV9LmApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZW1hcHBlZFB1YmxpY05hbWUgPSBob3N0RGlyZWN0aXZlQmluZGluZ3NbcHVibGljTmFtZV07XG5cbiAgICAgIGlmIChiaW5kaW5ncy5oYXNPd25Qcm9wZXJ0eShyZW1hcHBlZFB1YmxpY05hbWUpICYmIHJlbWFwcGVkUHVibGljTmFtZSAhPT0gcHVibGljTmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgUnVudGltZUVycm9yKFxuICAgICAgICAgICAgUnVudGltZUVycm9yQ29kZS5IT1NUX0RJUkVDVElWRV9DT05GTElDVElOR19BTElBUyxcbiAgICAgICAgICAgIGBDYW5ub3QgYWxpYXMgJHtiaW5kaW5nVHlwZX0gJHtwdWJsaWNOYW1lfSBvZiBob3N0IGRpcmVjdGl2ZSAke2NsYXNzTmFtZX0gdG8gJHtcbiAgICAgICAgICAgICAgICByZW1hcHBlZFB1YmxpY05hbWV9LCBiZWNhdXNlIGl0IGFscmVhZHkgaGFzIGEgZGlmZmVyZW50ICR7XG4gICAgICAgICAgICAgICAgYmluZGluZ1R5cGV9IHdpdGggdGhlIHNhbWUgcHVibGljIG5hbWUuYCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=