@angular/core 13.3.0 → 14.0.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core.d.ts +116 -42
- package/esm2020/src/application_tokens.mjs +10 -1
- package/esm2020/src/change_detection/change_detection.mjs +2 -3
- package/esm2020/src/compiler/compiler_facade_interface.mjs +1 -1
- package/esm2020/src/core.mjs +2 -2
- package/esm2020/src/core_private_export.mjs +2 -1
- package/esm2020/src/core_render3_private_export.mjs +4 -3
- package/esm2020/src/debug/debug_node.mjs +11 -10
- package/esm2020/src/di/injector_compatibility.mjs +2 -2
- package/esm2020/src/di/reflective_provider.mjs +4 -4
- package/esm2020/src/linker/ng_module_factory_loader.mjs +2 -2
- package/esm2020/src/linker/ng_module_registration.mjs +55 -0
- package/esm2020/src/linker/template_ref.mjs +3 -3
- package/esm2020/src/linker/view_container_ref.mjs +12 -3
- package/esm2020/src/reflection/platform_reflection_capabilities.mjs +1 -1
- package/esm2020/src/reflection/reflection_capabilities.mjs +1 -37
- package/esm2020/src/render3/component.mjs +3 -3
- package/esm2020/src/render3/component_ref.mjs +24 -18
- package/esm2020/src/render3/context_discovery.mjs +34 -30
- package/esm2020/src/render3/definition.mjs +3 -1
- package/esm2020/src/render3/di.mjs +177 -97
- package/esm2020/src/render3/hooks.mjs +3 -3
- package/esm2020/src/render3/i18n/i18n_parse.mjs +3 -3
- package/esm2020/src/render3/index.mjs +2 -2
- package/esm2020/src/render3/instructions/lview_debug.mjs +7 -4
- package/esm2020/src/render3/instructions/shared.mjs +16 -7
- package/esm2020/src/render3/interfaces/context.mjs +35 -2
- package/esm2020/src/render3/interfaces/definition.mjs +1 -1
- package/esm2020/src/render3/interfaces/injector.mjs +1 -1
- package/esm2020/src/render3/interfaces/lview_tracking.mjs +33 -0
- package/esm2020/src/render3/interfaces/renderer_dom.mjs +1 -1
- package/esm2020/src/render3/interfaces/view.mjs +4 -2
- package/esm2020/src/render3/jit/directive.mjs +5 -2
- package/esm2020/src/render3/jit/environment.mjs +4 -1
- package/esm2020/src/render3/jit/module.mjs +7 -1
- package/esm2020/src/render3/jit/module_patch.mjs +11 -0
- package/esm2020/src/render3/jit/pipe.mjs +5 -2
- package/esm2020/src/render3/ng_module_ref.mjs +1 -29
- package/esm2020/src/render3/node_manipulation.mjs +12 -3
- package/esm2020/src/render3/state.mjs +16 -2
- package/esm2020/src/render3/styling/styling_parser.mjs +2 -2
- package/esm2020/src/render3/util/discovery_utils.mjs +33 -22
- package/esm2020/src/util/coercion.mjs +12 -0
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/logger.mjs +3 -3
- package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
- package/esm2020/testing/src/r3_test_bed.mjs +8 -2
- package/fesm2015/core.mjs +516 -389
- package/fesm2015/core.mjs.map +1 -1
- package/fesm2015/testing.mjs +8 -2
- package/fesm2015/testing.mjs.map +1 -1
- package/fesm2020/core.mjs +516 -389
- package/fesm2020/core.mjs.map +1 -1
- package/fesm2020/testing.mjs +8 -2
- package/fesm2020/testing.mjs.map +1 -1
- package/package.json +2 -2
- package/schematics/migrations/entry-components/util.js +2 -2
- package/schematics/migrations/typed-forms/index.d.ts +1 -5
- package/schematics/migrations/typed-forms/index.js +12 -34
- package/schematics/migrations/typed-forms/util.d.ts +8 -10
- package/schematics/migrations/typed-forms/util.js +99 -52
- package/schematics/migrations.json +6 -16
- package/schematics/utils/import_manager.js +11 -22
- package/schematics/utils/typescript/imports.js +5 -9
- package/testing/testing.d.ts +1 -1
- package/esm2020/src/di/util.mjs +0 -51
- package/esm2020/src/linker/ng_module_factory_registration.mjs +0 -59
- package/esm2020/src/reflection/reflection.mjs +0 -16
- package/esm2020/src/reflection/reflector.mjs +0 -56
- package/esm2020/src/reflection/types.mjs +0 -9
- package/schematics/migrations/router-link-empty-expression/analyze_template.d.ts +0 -11
- package/schematics/migrations/router-link-empty-expression/analyze_template.js +0 -34
- package/schematics/migrations/router-link-empty-expression/angular/html_routerlink_empty_expr_visitor.d.ts +0 -20
- package/schematics/migrations/router-link-empty-expression/angular/html_routerlink_empty_expr_visitor.js +0 -47
- package/schematics/migrations/router-link-empty-expression/index.d.ts +0 -11
- package/schematics/migrations/router-link-empty-expression/index.js +0 -170
- package/schematics/migrations/testbed-teardown/index.d.ts +0 -11
- package/schematics/migrations/testbed-teardown/index.js +0 -92
- package/schematics/migrations/testbed-teardown/util.d.ts +0 -35
- package/schematics/migrations/testbed-teardown/util.js +0 -188
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
(function (factory) {
|
|
12
|
-
if (typeof module === "object" && typeof module.exports === "object") {
|
|
13
|
-
var v = factory(require, exports);
|
|
14
|
-
if (v !== undefined) module.exports = v;
|
|
15
|
-
}
|
|
16
|
-
else if (typeof define === "function" && define.amd) {
|
|
17
|
-
define("@angular/core/schematics/migrations/testbed-teardown/util", ["require", "exports", "typescript", "@angular/core/schematics/utils/typescript/imports", "@angular/core/schematics/utils/typescript/symbol"], factory);
|
|
18
|
-
}
|
|
19
|
-
})(function (require, exports) {
|
|
20
|
-
"use strict";
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.migrateTestModuleMetadataLiteral = exports.getInitTestEnvironmentLiteralReplacement = exports.findTestModuleMetadataNodes = exports.findInitTestEnvironmentCalls = void 0;
|
|
23
|
-
const typescript_1 = __importDefault(require("typescript"));
|
|
24
|
-
const imports_1 = require("@angular/core/schematics/utils/typescript/imports");
|
|
25
|
-
const symbol_1 = require("@angular/core/schematics/utils/typescript/symbol");
|
|
26
|
-
/** Finds the `initTestEnvironment` calls that need to be migrated. */
|
|
27
|
-
function findInitTestEnvironmentCalls(typeChecker, allSourceFiles) {
|
|
28
|
-
const callsToMigrate = new Set();
|
|
29
|
-
let totalCalls = 0;
|
|
30
|
-
allSourceFiles.forEach(sourceFile => {
|
|
31
|
-
sourceFile.forEachChild(function walk(node) {
|
|
32
|
-
if (typescript_1.default.isCallExpression(node) && typescript_1.default.isPropertyAccessExpression(node.expression) &&
|
|
33
|
-
typescript_1.default.isIdentifier(node.expression.name) &&
|
|
34
|
-
node.expression.name.text === 'initTestEnvironment' &&
|
|
35
|
-
isTestBedAccess(typeChecker, node.expression)) {
|
|
36
|
-
totalCalls++;
|
|
37
|
-
if (shouldMigrateInitTestEnvironment(node)) {
|
|
38
|
-
callsToMigrate.add(node);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
node.forEachChild(walk);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
return {
|
|
45
|
-
// Sort the nodes so that they will be migrated in reverse source order (nodes at the end of
|
|
46
|
-
// the file are migrated first). This avoids issues where a migrated node will offset the
|
|
47
|
-
// bounds of all nodes that come after it. Note that the nodes here are from all of the
|
|
48
|
-
// passed in source files, but that doesn't matter since the later nodes will still appear
|
|
49
|
-
// after the earlier ones.
|
|
50
|
-
callsToMigrate: sortInReverseSourceOrder(Array.from(callsToMigrate)),
|
|
51
|
-
totalCalls
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
exports.findInitTestEnvironmentCalls = findInitTestEnvironmentCalls;
|
|
55
|
-
/** Finds the `configureTestingModule` and `withModule` calls that need to be migrated. */
|
|
56
|
-
function findTestModuleMetadataNodes(typeChecker, sourceFile) {
|
|
57
|
-
const testModuleMetadataLiterals = new Set();
|
|
58
|
-
const withModuleImport = (0, imports_1.getImportSpecifier)(sourceFile, '@angular/core/testing', 'withModule');
|
|
59
|
-
sourceFile.forEachChild(function walk(node) {
|
|
60
|
-
if (typescript_1.default.isCallExpression(node)) {
|
|
61
|
-
const isConfigureTestingModuleCall = typescript_1.default.isPropertyAccessExpression(node.expression) &&
|
|
62
|
-
typescript_1.default.isIdentifier(node.expression.name) &&
|
|
63
|
-
node.expression.name.text === 'configureTestingModule' &&
|
|
64
|
-
isTestBedAccess(typeChecker, node.expression) && shouldMigrateModuleConfigCall(node);
|
|
65
|
-
const isWithModuleCall = withModuleImport && typescript_1.default.isIdentifier(node.expression) &&
|
|
66
|
-
(0, symbol_1.isReferenceToImport)(typeChecker, node.expression, withModuleImport) &&
|
|
67
|
-
shouldMigrateModuleConfigCall(node);
|
|
68
|
-
if (isConfigureTestingModuleCall || isWithModuleCall) {
|
|
69
|
-
testModuleMetadataLiterals.add(node.arguments[0]);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
node.forEachChild(walk);
|
|
73
|
-
});
|
|
74
|
-
// Sort the nodes so that they will be migrated in reverse source order (nodes at the end of
|
|
75
|
-
// the file are migrated first). This avoids issues where a migrated node will offset the
|
|
76
|
-
// bounds of all nodes that come after it.
|
|
77
|
-
return sortInReverseSourceOrder(Array.from(testModuleMetadataLiterals));
|
|
78
|
-
}
|
|
79
|
-
exports.findTestModuleMetadataNodes = findTestModuleMetadataNodes;
|
|
80
|
-
/**
|
|
81
|
-
* Gets data that can be used to migrate a call to `TestBed.initTestEnvironment`.
|
|
82
|
-
* The returned `span` is used to mark the text that should be replaced while the `text`
|
|
83
|
-
* is the code that should be inserted instead.
|
|
84
|
-
*/
|
|
85
|
-
function getInitTestEnvironmentLiteralReplacement(node, printer) {
|
|
86
|
-
const literalProperties = [];
|
|
87
|
-
const lastArg = node.arguments[node.arguments.length - 1];
|
|
88
|
-
let span;
|
|
89
|
-
let prefix;
|
|
90
|
-
if (node.arguments.length > 2) {
|
|
91
|
-
if (isFunction(lastArg)) {
|
|
92
|
-
// If the last argument is a function, add the function as the `aotSummaries` property.
|
|
93
|
-
literalProperties.push(typescript_1.default.createPropertyAssignment('aotSummaries', lastArg));
|
|
94
|
-
}
|
|
95
|
-
else if (typescript_1.default.isObjectLiteralExpression(lastArg)) {
|
|
96
|
-
// If the property is an object literal, copy over all the properties.
|
|
97
|
-
literalProperties.push(...lastArg.properties);
|
|
98
|
-
}
|
|
99
|
-
prefix = '';
|
|
100
|
-
span = { start: lastArg.getStart(), end: lastArg.getEnd(), length: lastArg.getWidth() };
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
const start = lastArg.getEnd();
|
|
104
|
-
prefix = ', ';
|
|
105
|
-
span = { start, end: start, length: 0 };
|
|
106
|
-
}
|
|
107
|
-
// Finally push the teardown object so that it appears last.
|
|
108
|
-
literalProperties.push(createTeardownAssignment());
|
|
109
|
-
return {
|
|
110
|
-
span,
|
|
111
|
-
text: prefix +
|
|
112
|
-
printer.printNode(typescript_1.default.EmitHint.Unspecified, typescript_1.default.createObjectLiteral(literalProperties, true), node.getSourceFile())
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
exports.getInitTestEnvironmentLiteralReplacement = getInitTestEnvironmentLiteralReplacement;
|
|
116
|
-
/** Migrates an object literal that is passed into `configureTestingModule` or `withModule`. */
|
|
117
|
-
function migrateTestModuleMetadataLiteral(node) {
|
|
118
|
-
return typescript_1.default.createObjectLiteral([...node.properties, createTeardownAssignment()], node.properties.length > 0);
|
|
119
|
-
}
|
|
120
|
-
exports.migrateTestModuleMetadataLiteral = migrateTestModuleMetadataLiteral;
|
|
121
|
-
/** Returns whether a property access points to `TestBed`. */
|
|
122
|
-
function isTestBedAccess(typeChecker, node) {
|
|
123
|
-
var _a, _b;
|
|
124
|
-
const symbolName = (_b = (_a = typeChecker.getTypeAtLocation(node.expression)) === null || _a === void 0 ? void 0 : _a.getSymbol()) === null || _b === void 0 ? void 0 : _b.getName();
|
|
125
|
-
return symbolName === 'TestBed' || symbolName === 'TestBedStatic';
|
|
126
|
-
}
|
|
127
|
-
/** Whether a call to `initTestEnvironment` should be migrated. */
|
|
128
|
-
function shouldMigrateInitTestEnvironment(node) {
|
|
129
|
-
// If there is no third argument, we definitely have to migrate it.
|
|
130
|
-
if (node.arguments.length === 2) {
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
// This is technically a type error so we shouldn't mess with it.
|
|
134
|
-
if (node.arguments.length < 2) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
// Otherwise we need to figure out if the `teardown` flag is set on the last argument.
|
|
138
|
-
const lastArg = node.arguments[2];
|
|
139
|
-
// Note: the checks below will identify something like `initTestEnvironment(..., ..., {})`,
|
|
140
|
-
// but they'll ignore a variable being passed in as the last argument like `const config = {};
|
|
141
|
-
// initTestEnvironment(..., ..., config)`. While we can resolve the variable to its declaration
|
|
142
|
-
// using `typeChecker.getTypeAtLocation(lastArg).getSymbol()?.valueDeclaration`, we deliberately
|
|
143
|
-
// don't, because it introduces some complexity and we may end up breaking user code. E.g.
|
|
144
|
-
// the `config` from the example above may be passed in to other functions or the `teardown`
|
|
145
|
-
// flag could be added later on by a function call.
|
|
146
|
-
// If the argument is an object literal and there are no
|
|
147
|
-
// properties called `teardown`, we have to migrate it.
|
|
148
|
-
if (isObjectLiteralWithoutTeardown(lastArg)) {
|
|
149
|
-
return true;
|
|
150
|
-
}
|
|
151
|
-
// If the last argument is an `aotSummaries` function, we also have to migrate.
|
|
152
|
-
if (isFunction(lastArg)) {
|
|
153
|
-
return true;
|
|
154
|
-
}
|
|
155
|
-
// Otherwise don't migrate if we couldn't identify the last argument.
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Whether a call to a module configuration function should be migrated. This covers
|
|
160
|
-
* `TestBed.configureTestingModule` and `withModule` since they both accept `TestModuleMetadata`
|
|
161
|
-
* as their first argument.
|
|
162
|
-
*/
|
|
163
|
-
function shouldMigrateModuleConfigCall(node) {
|
|
164
|
-
return node.arguments.length > 0 && isObjectLiteralWithoutTeardown(node.arguments[0]);
|
|
165
|
-
}
|
|
166
|
-
/** Returns whether a node is a function literal. */
|
|
167
|
-
function isFunction(node) {
|
|
168
|
-
return typescript_1.default.isArrowFunction(node) || typescript_1.default.isFunctionExpression(node) ||
|
|
169
|
-
typescript_1.default.isFunctionDeclaration(node);
|
|
170
|
-
}
|
|
171
|
-
/** Checks whether a node is an object literal that doesn't contain a property called `teardown`. */
|
|
172
|
-
function isObjectLiteralWithoutTeardown(node) {
|
|
173
|
-
return typescript_1.default.isObjectLiteralExpression(node) && !node.properties.find(prop => {
|
|
174
|
-
var _a;
|
|
175
|
-
return ((_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText()) === 'teardown';
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
/** Creates a teardown configuration property assignment. */
|
|
179
|
-
function createTeardownAssignment() {
|
|
180
|
-
// `teardown: {destroyAfterEach: false}`
|
|
181
|
-
return typescript_1.default.createPropertyAssignment('teardown', typescript_1.default.createObjectLiteral([typescript_1.default.createPropertyAssignment('destroyAfterEach', typescript_1.default.createFalse())]));
|
|
182
|
-
}
|
|
183
|
-
/** Sorts an array of AST nodes in reverse source order. */
|
|
184
|
-
function sortInReverseSourceOrder(nodes) {
|
|
185
|
-
return nodes.sort((a, b) => b.getEnd() - a.getEnd());
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvcmUvc2NoZW1hdGljcy9taWdyYXRpb25zL3Rlc3RiZWQtdGVhcmRvd24vdXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7Ozs7SUFFSCw0REFBNEI7SUFFNUIsK0VBQWtFO0lBQ2xFLDZFQUFrRTtJQVVsRSxzRUFBc0U7SUFDdEUsU0FBZ0IsNEJBQTRCLENBQ3hDLFdBQTJCLEVBQUUsY0FBK0I7UUFDOUQsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUM7UUFDcEQsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBRW5CLGNBQWMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDbEMsVUFBVSxDQUFDLFlBQVksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFhO2dCQUNqRCxJQUFJLG9CQUFFLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksb0JBQUUsQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO29CQUMzRSxvQkFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQztvQkFDckMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLHFCQUFxQjtvQkFDbkQsZUFBZSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7b0JBQ2pELFVBQVUsRUFBRSxDQUFDO29CQUNiLElBQUksZ0NBQWdDLENBQUMsSUFBSSxDQUFDLEVBQUU7d0JBQzFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7cUJBQzFCO2lCQUNGO2dCQUVELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDMUIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMs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NUQsb0JBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsb0dBQW9HO0lBQ3BHLFNBQVMsOEJBQThCLENBQUMsSUFBYTtRQUNuRCxPQUFPLG9CQUFFLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTs7WUFDeEUsT0FBTyxDQUFBLE1BQUEsSUFBSSxDQUFDLElBQUksMENBQUUsT0FBTyxFQUFFLE1BQUssVUFBVSxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDREQUE0RDtJQUM1RCxTQUFTLHdCQUF3QjtRQUMvQix3Q0FBd0M7UUFDeEMsT0FBTyxvQkFBRSxDQUFDLHdCQUF3QixDQUM5QixVQUFVLEVBQ1Ysb0JBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLG9CQUFFLENBQUMsd0JBQXdCLENBQUMsa0JBQWtCLEVBQUUsb0JBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25HLENBQUM7SUFFRCwyREFBMkQ7SUFDM0QsU0FBUyx3QkFBd0IsQ0FBb0IsS0FBVTtRQUM3RCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7SUFDdkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgdHMgZnJvbSAndHlwZXNjcmlwdCc7XG5cbmltcG9ydCB7Z2V0SW1wb3J0U3BlY2lmaWVyfSBmcm9tICcuLi8uLi91dGlscy90eXBlc2NyaXB0L2ltcG9ydHMnO1xuaW1wb3J0IHtpc1JlZmVyZW5jZVRvSW1wb3J0fSBmcm9tICcuLi8uLi91dGlscy90eXBlc2NyaXB0L3N5bWJvbCc7XG5cbi8qKiBSZXN1bHQgb2YgYSBmdWxsLXByb2dyYW0gYW5hbHlzaXMgbG9va2luZyBmb3IgYGluaXRUZXN0RW52aXJvbm1lbnRgIGNhbGxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbml0VGVzdEVudmlyb25tZW50QW5hbHlzaXMge1xuICAvKiogVG90YWwgbnVtYmVyIG9mIGNhbGxzIHRoYXQgd2VyZSBmb3VuZC4gKi9cbiAgdG90YWxDYWxsczogbnVtYmVyO1xuICAvKiogQ2FsbHMgdGhhdCBuZWVkIHRvIGJlIG1pZ3JhdGVkLiAqL1xuICBjYWxsc1RvTWlncmF0ZTogdHMuQ2FsbEV4cHJlc3Npb25bXTtcbn1cblxuLyoqIEZpbmRzIHRoZSBgaW5pdFRlc3RFbnZpcm9ubWVudGAgY2FsbHMgdGhhdCBuZWVkIHRvIGJlIG1pZ3JhdGVkLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRJbml0VGVzdEVudmlyb25tZW50Q2FsbHMoXG4gICAgdHlwZUNoZWNrZXI6IHRzLlR5cGVDaGVja2VyLCBhbGxTb3VyY2VGaWxlczogdHMuU291cmNlRmlsZVtdKTogSW5pdFRlc3RFbnZpcm9ubWVudEFuYWx5c2lzIHtcbiAgY29uc3QgY2FsbHNUb01pZ3JhdGUgPSBuZXcgU2V0PHRzLkNhbGxFeHByZXNzaW9uPigpO1xuICBsZXQgdG90YWxDYWxscyA9IDA7XG5cbiAgYWxsU291cmNlRmlsZXMuZm9yRWFjaChzb3VyY2VGaWxlID0+IHtcbiAgICBzb3VyY2VGaWxlLmZvckVhY2hDaGlsZChmdW5jdGlvbiB3YWxrKG5vZGU6IHRzLk5vZGUpIHtcbiAgICAgIGlmICh0cy5pc0NhbGxFeHByZXNzaW9uKG5vZGUpICYmIHRzLmlzUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKG5vZGUuZXhwcmVzc2lvbikgJiZcbiAgICAgICAgICB0cy5pc0lkZW50aWZpZXIobm9kZS5leHByZXNzaW9uLm5hbWUpICYmXG4gICAgICAgICAgbm9kZS5leHByZXNzaW9uLm5hbWUudGV4dCA9PT0gJ2luaXRUZXN0RW52aXJvbm1lbnQnICYmXG4gICAgICAgICAgaXNUZXN0QmVkQWNjZXNzKHR5cGVDaGVja2VyLCBub2RlLmV4cHJlc3Npb24pKSB7XG4gICAgICAgIHRvdGFsQ2FsbHMrKztcbiAgICAgICAgaWYgKHNob3VsZE1pZ3JhdGVJbml0VGVzdEVudmlyb25tZW50KG5vZGUpKSB7XG4gICAgICAgICAgY2FsbHNUb01pZ3JhdGUuYWRkKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG5vZGUuZm9yRWFjaENoaWxkKHdhbGspO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIC8vIFNvcnQgdGhlIG5vZGVzIHNvIHRoYXQgdGhleSB3aWxsIGJlIG1pZ3JhdGVkIGluIHJldmVyc2Ugc291cmNlIG9yZGVyIChub2RlcyBhdCB0aGUgZW5kIG9mXG4gICAgLy8gdGhlIGZpbGUgYXJlIG1pZ3JhdGVkIGZpcnN0KS4gVGhpcyBhdm9pZHMgaXNzdWVzIHdoZXJlIGEgbWlncmF0ZWQgbm9kZSB3aWxsIG9mZnNldCB0aGVcbiAgICAvLyBib3VuZHMgb2YgYWxsIG5vZGVzIHRoYXQgY29tZSBhZnRlciBpdC4gTm90ZSB0aGF0IHRoZSBub2RlcyBoZXJlIGFyZSBmcm9tIGFsbCBvZiB0aGVcbiAgICAvLyBwYXNzZWQgaW4gc291cmNlIGZpbGVzLCBidXQgdGhhdCBkb2Vzbid0IG1hdHRlciBzaW5jZSB0aGUgbGF0ZXIgbm9kZXMgd2lsbCBzdGlsbCBhcHBlYXJcbiAgICAvLyBhZnRlciB0aGUgZWFybGllciBvbmVzLlxuICAgIGNhbGxzVG9NaWdyYXRlOiBzb3J0SW5SZXZlcnNlU291cmNlT3JkZXIoQXJyYXkuZnJvbShjYWxsc1RvTWlncmF0ZSkpLFxuICAgIHRvdGFsQ2FsbHNcbiAgfTtcbn1cblxuLyoqIEZpbmRzIHRoZSBgY29uZmlndXJlVGVzdGluZ01vZHVsZWAgYW5kIGB3aXRoTW9kdWxlYCBjYWxscyB0aGF0IG5lZWQgdG8gYmUgbWlncmF0ZWQuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZFRlc3RNb2R1bGVNZXRhZGF0YU5vZGVzKFxuICAgIHR5cGVDaGVja2VyOiB0cy5UeXBlQ2hlY2tlciwgc291cmNlRmlsZTogdHMuU291cmNlRmlsZSkge1xuICBjb25zdCB0ZXN0TW9kdWxlTWV0YWRhdGFMaXRlcmFscyA9IG5ldyBTZXQ8dHMuT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24+KCk7XG4gIGNvbnN0IHdpdGhNb2R1bGVJbXBvcnQgPSBnZXRJbXBvcnRTcGVjaWZpZXIoc291cmNlRmlsZSwgJ0Bhbmd1bGFyL2NvcmUvdGVzdGluZycsICd3aXRoTW9kdWxlJyk7XG5cbiAgc291cmNlRmlsZS5mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gd2Fsayhub2RlOiB0cy5Ob2RlKSB7XG4gICAgaWYgKHRzLmlzQ2FsbEV4cHJlc3Npb24obm9kZSkpIHtcbiAgICAgIGNvbnN0IGlzQ29uZmlndXJlVGVzdGluZ01vZHVsZUNhbGwgPSB0cy5pc1Byb3BlcnR5QWNjZXNzRXhwcmVzc2lvbihub2RlLmV4cHJlc3Npb24pICYmXG4gICAgICAgICAgdHMuaXNJZGVudGlmaWVyKG5vZGUuZXhwcmVzc2lvbi5uYW1lKSAmJlxuICAgICAgICAgIG5vZGUuZXhwcmVzc2lvbi5uYW1lLnRleHQgPT09ICdjb25maWd1cmVUZXN0aW5nTW9kdWxlJyAmJlxuICAgICAgICAgIGlzVGVzdEJlZEFjY2Vzcyh0eXBlQ2hlY2tlciwgbm9kZS5leHByZXNzaW9uKSAmJiBzaG91bGRNaWdyYXRlTW9kdWxlQ29uZmlnQ2FsbChub2RlKTtcbiAgICAgIGNvbnN0IGlzV2l0aE1vZHVsZUNhbGwgPSB3aXRoTW9kdWxlSW1wb3J0ICYmIHRzLmlzSWRlbnRpZmllcihub2RlLmV4cHJlc3Npb24pICYmXG4gICAgICAgICAgaXNSZWZlcmVuY2VUb0ltcG9ydCh0eXBlQ2hlY2tlciwgbm9kZS5leHByZXNzaW9uLCB3aXRoTW9kdWxlSW1wb3J0KSAmJlxuICAgICAgICAgIHNob3VsZE1pZ3JhdGVNb2R1bGVDb25maWdDYWxsKG5vZGUpO1xuXG4gICAgICBpZiAoaXNDb25maWd1cmVUZXN0aW5nTW9kdWxlQ2FsbCB8fCBpc1dpdGhNb2R1bGVDYWxsKSB7XG4gICAgICAgIHRlc3RNb2R1bGVNZXRhZGF0YUxpdGVyYWxzLmFkZChub2RlLmFyZ3VtZW50c1swXSBhcyB0cy5PYmplY3RMaXRlcmFsRXhwcmVzc2lvbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbm9kZS5mb3JFYWNoQ2hpbGQod2Fsayk7XG4gIH0pO1xuXG4gIC8vIFNvcnQgdGhlIG5vZGVzIHNvIHRoYXQgdGhleSB3aWxsIGJlIG1pZ3JhdGVkIGluIHJldmVyc2Ugc291cmNlIG9yZGVyIChub2RlcyBhdCB0aGUgZW5kIG9mXG4gIC8vIHRoZSBmaWxlIGFyZSBtaWdyYXRlZCBmaXJzdCkuIFRoaXMgYXZvaWRzIGlzc3VlcyB3aGVyZSBhIG1pZ3JhdGVkIG5vZGUgd2lsbCBvZmZzZXQgdGhlXG4gIC8vIGJvdW5kcyBvZiBhbGwgbm9kZXMgdGhhdCBjb21lIGFmdGVyIGl0LlxuICByZXR1cm4gc29ydEluUmV2ZXJzZVNvdXJjZU9yZGVyKEFycmF5LmZyb20odGVzdE1vZHVsZU1ldGFkYXRhTGl0ZXJhbHMpKTtcbn1cblxuLyoqXG4gKiBHZXRzIGRhdGEgdGhhdCBjYW4gYmUgdXNlZCB0byBtaWdyYXRlIGEgY2FsbCB0byBgVGVzdEJlZC5pbml0VGVzdEVudmlyb25tZW50YC5cbiAqIFRoZSByZXR1cm5lZCBgc3BhbmAgaXMgdXNlZCB0byBtYXJrIHRoZSB0ZXh0IHRoYXQgc2hvdWxkIGJlIHJlcGxhY2VkIHdoaWxlIHRoZSBgdGV4dGBcbiAqIGlzIHRoZSBjb2RlIHRoYXQgc2hvdWxkIGJlIGluc2VydGVkIGluc3RlYWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJbml0VGVzdEVudmlyb25tZW50TGl0ZXJhbFJlcGxhY2VtZW50KFxuICAgIG5vZGU6IHRzLkNhbGxFeHByZXNzaW9uLCBwcmludGVyOiB0cy5QcmludGVyKSB7XG4gIGNvbnN0IGxpdGVyYWxQcm9wZXJ0aWVzOiB0cy5PYmplY3RMaXRlcmFsRWxlbWVudExpa2VbXSA9IFtdO1xuICBjb25zdCBsYXN0QXJnID0gbm9kZS5hcmd1bWVudHNbbm9kZS5hcmd1bWVudHMubGVuZ3RoIC0gMV07XG4gIGxldCBzcGFuOiB7c3RhcnQ6IG51bWJlciwgZW5kOiBudW1iZXIsIGxlbmd0aDogbnVtYmVyfTtcbiAgbGV0IHByZWZpeDogc3RyaW5nO1xuXG4gIGlmIChub2RlLmFyZ3VtZW50cy5sZW5ndGggPiAyKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24obGFzdEFyZykpIHtcbiAgICAgIC8vIElmIHRoZSBsYXN0IGFyZ3VtZW50IGlzIGEgZnVuY3Rpb24sIGFkZCB0aGUgZnVuY3Rpb24gYXMgdGhlIGBhb3RTdW1tYXJpZXNgIHByb3BlcnR5LlxuICAgICAgbGl0ZXJhbFByb3BlcnRpZXMucHVzaCh0cy5jcmVhdGVQcm9wZXJ0eUFzc2lnbm1lbnQoJ2FvdFN1bW1hcmllcycsIGxhc3RBcmcpKTtcbiAgICB9IGVsc2UgaWYgKHRzLmlzT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24obGFzdEFyZykpIHtcbiAgICAgIC8vIElmIHRoZSBwcm9wZXJ0eSBpcyBhbiBvYmplY3QgbGl0ZXJhbCwgY29weSBvdmVyIGFsbCB0aGUgcHJvcGVydGllcy5cbiAgICAgIGxpdGVyYWxQcm9wZXJ0aWVzLnB1c2goLi4ubGFzdEFyZy5wcm9wZXJ0aWVzKTtcbiAgICB9XG5cbiAgICBwcmVmaXggPSAnJztcbiAgICBzcGFuID0ge3N0YXJ0OiBsYXN0QXJnLmdldFN0YXJ0KCksIGVuZDogbGFzdEFyZy5nZXRFbmQoKSwgbGVuZ3RoOiBsYXN0QXJnLmdldFdpZHRoKCl9O1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHN0YXJ0ID0gbGFzdEFyZy5nZXRFbmQoKTtcbiAgICBwcmVmaXggPSAnLCAnO1xuICAgIHNwYW4gPSB7c3RhcnQsIGVuZDogc3RhcnQsIGxlbmd0aDogMH07XG4gIH1cblxuICAvLyBGaW5hbGx5IHB1c2ggdGhlIHRlYXJkb3duIG9iamVjdCBzbyB0aGF0IGl0IGFwcGVhcnMgbGFzdC5cbiAgbGl0ZXJhbFByb3BlcnRpZXMucHVzaChjcmVhdGVUZWFyZG93bkFzc2lnbm1lbnQoKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBzcGFuLFxuICAgIHRleHQ6IHByZWZpeCArXG4gICAgICAgIHByaW50ZXIucHJpbnROb2RlKFxuICAgICAgICAgICAgdHMuRW1pdEhpbnQuVW5zcGVjaWZpZWQsIHRzLmNyZWF0ZU9iamVjdExpdGVyYWwobGl0ZXJhbFByb3BlcnRpZXMsIHRydWUpLFxuICAgICAgICAgICAgbm9kZS5nZXRTb3VyY2VGaWxlKCkpXG4gIH07XG59XG5cbi8qKiBNaWdyYXRlcyBhbiBvYmplY3QgbGl0ZXJhbCB0aGF0IGlzIHBhc3NlZCBpbnRvIGBjb25maWd1cmVUZXN0aW5nTW9kdWxlYCBvciBgd2l0aE1vZHVsZWAuICovXG5leHBvcnQgZnVuY3Rpb24gbWlncmF0ZVRlc3RNb2R1bGVNZXRhZGF0YUxpdGVyYWwobm9kZTogdHMuT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24pOlxuICAgIHRzLk9iamVjdExpdGVyYWxFeHByZXNzaW9uIHtcbiAgcmV0dXJuIHRzLmNyZWF0ZU9iamVjdExpdGVyYWwoXG4gICAgICBbLi4ubm9kZS5wcm9wZXJ0aWVzLCBjcmVhdGVUZWFyZG93bkFzc2lnbm1lbnQoKV0sIG5vZGUucHJvcGVydGllcy5sZW5ndGggPiAwKTtcbn1cblxuLyoqIFJldHVybnMgd2hldGhlciBhIHByb3BlcnR5IGFjY2VzcyBwb2ludHMgdG8gYFRlc3RCZWRgLiAqL1xuZnVuY3Rpb24gaXNUZXN0QmVkQWNjZXNzKHR5cGVDaGVja2VyOiB0cy5UeXBlQ2hlY2tlciwgbm9kZTogdHMuUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKTogYm9vbGVhbiB7XG4gIGNvbnN0IHN5bWJvbE5hbWUgPSB0eXBlQ2hlY2tlci5nZXRUeXBlQXRMb2NhdGlvbihub2RlLmV4cHJlc3Npb24pPy5nZXRTeW1ib2woKT8uZ2V0TmFtZSgpO1xuICByZXR1cm4gc3ltYm9sTmFtZSA9PT0gJ1Rlc3RCZWQnIHx8IHN5bWJvbE5hbWUgPT09ICdUZXN0QmVkU3RhdGljJztcbn1cblxuLyoqIFdoZXRoZXIgYSBjYWxsIHRvIGBpbml0VGVzdEVudmlyb25tZW50YCBzaG91bGQgYmUgbWlncmF0ZWQuICovXG5mdW5jdGlvbiBzaG91bGRNaWdyYXRlSW5pdFRlc3RFbnZpcm9ubWVudChub2RlOiB0cy5DYWxsRXhwcmVzc2lvbik6IGJvb2xlYW4ge1xuICAvLyBJZiB0aGVyZSBpcyBubyB0aGlyZCBhcmd1bWVudCwgd2UgZGVmaW5pdGVseSBoYXZlIHRvIG1pZ3JhdGUgaXQuXG4gIGlmIChub2RlLmFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIFRoaXMgaXMgdGVjaG5pY2FsbHkgYSB0eXBlIGVycm9yIHNvIHdlIHNob3VsZG4ndCBtZXNzIHdpdGggaXQuXG4gIGlmIChub2RlLmFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlIHdlIG5lZWQgdG8gZmlndXJlIG91dCBpZiB0aGUgYHRlYXJkb3duYCBmbGFnIGlzIHNldCBvbiB0aGUgbGFzdCBhcmd1bWVudC5cbiAgY29uc3QgbGFzdEFyZyA9IG5vZGUuYXJndW1lbnRzWzJdO1xuXG4gIC8vIE5vdGU6IHRoZSBjaGVja3MgYmVsb3cgd2lsbCBpZGVudGlmeSBzb21ldGhpbmcgbGlrZSBgaW5pdFRlc3RFbnZpcm9ubWVudCguLi4sIC4uLiwge30pYCxcbiAgLy8gYnV0IHRoZXknbGwgaWdub3JlIGEgdmFyaWFibGUgYmVpbmcgcGFzc2VkIGluIGFzIHRoZSBsYXN0IGFyZ3VtZW50IGxpa2UgYGNvbnN0IGNvbmZpZyA9IHt9O1xuICAvLyBpbml0VGVzdEVudmlyb25tZW50KC4uLiwgLi4uLCBjb25maWcpYC4gV2hpbGUgd2UgY2FuIHJlc29sdmUgdGhlIHZhcmlhYmxlIHRvIGl0cyBkZWNsYXJhdGlvblxuICAvLyB1c2luZyBgdHlwZUNoZWNrZXIuZ2V0VHlwZUF0TG9jYXRpb24obGFzdEFyZykuZ2V0U3ltYm9sKCk/LnZhbHVlRGVjbGFyYXRpb25gLCB3ZSBkZWxpYmVyYXRlbHlcbiAgLy8gZG9uJ3QsIGJlY2F1c2UgaXQgaW50cm9kdWNlcyBzb21lIGNvbXBsZXhpdHkgYW5kIHdlIG1heSBlbmQgdXAgYnJlYWtpbmcgdXNlciBjb2RlLiBFLmcuXG4gIC8vIHRoZSBgY29uZmlnYCBmcm9tIHRoZSBleGFtcGxlIGFib3ZlIG1heSBiZSBwYXNzZWQgaW4gdG8gb3RoZXIgZnVuY3Rpb25zIG9yIHRoZSBgdGVhcmRvd25gXG4gIC8vIGZsYWcgY291bGQgYmUgYWRkZWQgbGF0ZXIgb24gYnkgYSBmdW5jdGlvbiBjYWxsLlxuXG4gIC8vIElmIHRoZSBhcmd1bWVudCBpcyBhbiBvYmplY3QgbGl0ZXJhbCBhbmQgdGhlcmUgYXJlIG5vXG4gIC8vIHByb3BlcnRpZXMgY2FsbGVkIGB0ZWFyZG93bmAsIHdlIGhhdmUgdG8gbWlncmF0ZSBpdC5cbiAgaWYgKGlzT2JqZWN0TGl0ZXJhbFdpdGhvdXRUZWFyZG93bihsYXN0QXJnKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gSWYgdGhlIGxhc3QgYXJndW1lbnQgaXMgYW4gYGFvdFN1bW1hcmllc2AgZnVuY3Rpb24sIHdlIGFsc28gaGF2ZSB0byBtaWdyYXRlLlxuICBpZiAoaXNGdW5jdGlvbihsYXN0QXJnKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlIGRvbid0IG1pZ3JhdGUgaWYgd2UgY291bGRuJ3QgaWRlbnRpZnkgdGhlIGxhc3QgYXJndW1lbnQuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGEgY2FsbCB0byBhIG1vZHVsZSBjb25maWd1cmF0aW9uIGZ1bmN0aW9uIHNob3VsZCBiZSBtaWdyYXRlZC4gVGhpcyBjb3ZlcnNcbiAqIGBUZXN0QmVkLmNvbmZpZ3VyZVRlc3RpbmdNb2R1bGVgIGFuZCBgd2l0aE1vZHVsZWAgc2luY2UgdGhleSBib3RoIGFjY2VwdCBgVGVzdE1vZHVsZU1ldGFkYXRhYFxuICogYXMgdGhlaXIgZmlyc3QgYXJndW1lbnQuXG4gKi9cbmZ1bmN0aW9uIHNob3VsZE1pZ3JhdGVNb2R1bGVDb25maWdDYWxsKG5vZGU6IHRzLkNhbGxFeHByZXNzaW9uKTogbm9kZSBpcyB0cy5DYWxsRXhwcmVzc2lvbiZcbiAgICB7YXJndW1lbnRzOiBbdHMuT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24sIC4uLnRzLkV4cHJlc3Npb25bXV19IHtcbiAgcmV0dXJuIG5vZGUuYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgaXNPYmplY3RMaXRlcmFsV2l0aG91dFRlYXJkb3duKG5vZGUuYXJndW1lbnRzWzBdKTtcbn1cblxuLyoqIFJldHVybnMgd2hldGhlciBhIG5vZGUgaXMgYSBmdW5jdGlvbiBsaXRlcmFsLiAqL1xuZnVuY3Rpb24gaXNGdW5jdGlvbihub2RlOiB0cy5Ob2RlKTogbm9kZSBpcyB0cy5BcnJvd0Z1bmN0aW9ufHRzLkZ1bmN0aW9uRXhwcmVzc2lvbnxcbiAgICB0cy5GdW5jdGlvbkRlY2xhcmF0aW9uIHtcbiAgcmV0dXJuIHRzLmlzQXJyb3dGdW5jdGlvbihub2RlKSB8fCB0cy5pc0Z1bmN0aW9uRXhwcmVzc2lvbihub2RlKSB8fFxuICAgICAgdHMuaXNGdW5jdGlvbkRlY2xhcmF0aW9uKG5vZGUpO1xufVxuXG4vKiogQ2hlY2tzIHdoZXRoZXIgYSBub2RlIGlzIGFuIG9iamVjdCBsaXRlcmFsIHRoYXQgZG9lc24ndCBjb250YWluIGEgcHJvcGVydHkgY2FsbGVkIGB0ZWFyZG93bmAuICovXG5mdW5jdGlvbiBpc09iamVjdExpdGVyYWxXaXRob3V0VGVhcmRvd24obm9kZTogdHMuTm9kZSk6IG5vZGUgaXMgdHMuT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24ge1xuICByZXR1cm4gdHMuaXNPYmplY3RMaXRlcmFsRXhwcmVzc2lvbihub2RlKSAmJiAhbm9kZS5wcm9wZXJ0aWVzLmZpbmQocHJvcCA9PiB7XG4gICAgcmV0dXJuIHByb3AubmFtZT8uZ2V0VGV4dCgpID09PSAndGVhcmRvd24nO1xuICB9KTtcbn1cblxuLyoqIENyZWF0ZXMgYSB0ZWFyZG93biBjb25maWd1cmF0aW9uIHByb3BlcnR5IGFzc2lnbm1lbnQuICovXG5mdW5jdGlvbiBjcmVhdGVUZWFyZG93bkFzc2lnbm1lbnQoKTogdHMuUHJvcGVydHlBc3NpZ25tZW50IHtcbiAgLy8gYHRlYXJkb3duOiB7ZGVzdHJveUFmdGVyRWFjaDogZmFsc2V9YFxuICByZXR1cm4gdHMuY3JlYXRlUHJvcGVydHlBc3NpZ25tZW50KFxuICAgICAgJ3RlYXJkb3duJyxcbiAgICAgIHRzLmNyZWF0ZU9iamVjdExpdGVyYWwoW3RzLmNyZWF0ZVByb3BlcnR5QXNzaWdubWVudCgnZGVzdHJveUFmdGVyRWFjaCcsIHRzLmNyZWF0ZUZhbHNlKCkpXSkpO1xufVxuXG4vKiogU29ydHMgYW4gYXJyYXkgb2YgQVNUIG5vZGVzIGluIHJldmVyc2Ugc291cmNlIG9yZGVyLiAqL1xuZnVuY3Rpb24gc29ydEluUmV2ZXJzZVNvdXJjZU9yZGVyPFQgZXh0ZW5kcyB0cy5Ob2RlPihub2RlczogVFtdKTogVFtdIHtcbiAgcmV0dXJuIG5vZGVzLnNvcnQoKGEsIGIpID0+IGIuZ2V0RW5kKCkgLSBhLmdldEVuZCgpKTtcbn1cbiJdfQ==
|