semantifold 0.3.0 → 0.4.0
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/README.md +58 -15
- package/build/index.d.ts +48 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +57 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +154 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +23 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +136 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +81 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1308 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2158 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +235 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +468 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +167 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +2952 -202
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +688 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/architecture.md +45 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +231 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +15 -7
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +366 -4
- package/docs/webassembly.md +52 -0
- package/index.js +63 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +160 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +141 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1407 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2304 -124
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +520 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +172 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +765 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- package/src/toolchains.js +16 -3
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { authorizedOperation, isTask034OperationName } from "./capabilities.js";
|
|
3
|
+
import { parseProtectedEntryName } from "./stdlib.js";
|
|
4
|
+
/** @typedef {{failureIds: Set<string>, host: boolean}} EffectSummary */
|
|
5
|
+
/** @typedef {(expression: import("./types.js").Expression) => void} ExpressionVisitor */
|
|
6
|
+
/**
|
|
7
|
+
* Resolves compiler-authorized calls before ordinary semantic type validation.
|
|
8
|
+
* Source functions always win; authority is never inferred from spelling alone.
|
|
9
|
+
* @param {import("./types.js").SemanticModule} module - Parser-authored module.
|
|
10
|
+
* @param {string} language - Source language identity for protected entry targets.
|
|
11
|
+
* @param {Map<string, import("./types.js").FunctionDeclaration>} functions - Visible ordinary functions.
|
|
12
|
+
* @param {(code: string, detail: string, location: import("./types.js").SourceLocation) => never} fail - Located failure.
|
|
13
|
+
* @param {boolean} normalize - Whether parser-authored operation intent may be normalized.
|
|
14
|
+
* @param {Map<string, import("./types.js").ClassDeclaration>} [visibleClasses] - Resolved reference classes.
|
|
15
|
+
* @returns {void}
|
|
16
|
+
*/
|
|
17
|
+
export function validateEffectGraph(module, language, functions, fail, normalize, visibleClasses = new Map()) {
|
|
18
|
+
const capabilities = module.capabilities ?? [];
|
|
19
|
+
const capabilityIds = new Set();
|
|
20
|
+
const operationIds = new Set();
|
|
21
|
+
const resourceIds = new Set();
|
|
22
|
+
const failureIds = new Set();
|
|
23
|
+
const operationNames = new Set();
|
|
24
|
+
if (!Array.isArray(capabilities))
|
|
25
|
+
fail("INVALID_CAPABILITY_AUTHORITY", "Capabilities must be an ordered array.", module.location);
|
|
26
|
+
for (const [capabilityIndex, capability] of capabilities.entries()) {
|
|
27
|
+
const legacyId = `capability:${capabilityIndex}`;
|
|
28
|
+
if (!capability || capability.kind != "EffectCapabilityDeclaration" ||
|
|
29
|
+
capability.id != legacyId && !/^module:\d+\/capability:\d+$/u.test(capability.id) || capabilityIds.has(capability.id) ||
|
|
30
|
+
typeof capability.authorityId != "string" || typeof capability.name != "string" || !Array.isArray(capability.resources) ||
|
|
31
|
+
!Array.isArray(capability.failures) || !Array.isArray(capability.operations)) {
|
|
32
|
+
fail("INVALID_CAPABILITY_AUTHORITY", "Malformed capability declaration graph.", module.location);
|
|
33
|
+
}
|
|
34
|
+
capabilityIds.add(capability.id);
|
|
35
|
+
for (const [index, resource] of capability.resources.entries()) {
|
|
36
|
+
if (resource.kind != "EffectResourceDeclaration" || resource.id != `${capability.id}/resource:${index}` ||
|
|
37
|
+
resourceIds.has(resource.id))
|
|
38
|
+
fail("INVALID_CAPABILITY_AUTHORITY", "Malformed capability resource identity.", module.location);
|
|
39
|
+
resourceIds.add(resource.id);
|
|
40
|
+
}
|
|
41
|
+
for (const [index, failure] of capability.failures.entries()) {
|
|
42
|
+
if (failure.kind != "EffectFailureDeclaration" || failure.id != `${capability.id}/failure:${index}` ||
|
|
43
|
+
failureIds.has(failure.id))
|
|
44
|
+
fail("INVALID_CAPABILITY_AUTHORITY", "Malformed capability failure identity.", module.location);
|
|
45
|
+
failureIds.add(failure.id);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const capability of capabilities) {
|
|
49
|
+
for (const [index, operation] of capability.operations.entries()) {
|
|
50
|
+
if (operation.kind != "EffectOperationDeclaration" || operation.id != `${capability.id}/operation:${index}` ||
|
|
51
|
+
operationIds.has(operation.id) || operationNames.has(operation.name) || !Array.isArray(operation.parameters) ||
|
|
52
|
+
!Array.isArray(operation.failureIds) || operation.effects?.length != 1 || operation.effects[0] != "host" ||
|
|
53
|
+
operation.failureIds.some((id) => !failureIds.has(id))) {
|
|
54
|
+
fail("INVALID_CAPABILITY_AUTHORITY", "Malformed or ambiguous capability operation graph.", module.location);
|
|
55
|
+
}
|
|
56
|
+
operationIds.add(operation.id);
|
|
57
|
+
operationNames.add(operation.name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const declaration of [
|
|
61
|
+
...module.functions,
|
|
62
|
+
...(module.records ?? []),
|
|
63
|
+
...(module.classes ?? []),
|
|
64
|
+
...(module.errors ?? [])
|
|
65
|
+
]) {
|
|
66
|
+
if (parseProtectedEntryName(declaration.name) !== null) {
|
|
67
|
+
fail("STDLIB_PROTECTED_BINDING_ACCESS", `Source declaration '${declaration.name}' captures a reserved protected provider binding.`, declaration.location);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
forEachExpression(module, (expression) => {
|
|
71
|
+
if (expression.kind == "EffectCallExpression") {
|
|
72
|
+
const capability = capabilities.find(({ id }) => id == expression.resolution?.capabilityId);
|
|
73
|
+
const operation = capability?.operations.find(({ id }) => id == expression.operation);
|
|
74
|
+
if (operation && expression.resolution.operationId == operation.id &&
|
|
75
|
+
(!Array.isArray(expression.resolution.failureIds) ||
|
|
76
|
+
expression.resolution.failureIds.join(",") != operation.failureIds.join(","))) {
|
|
77
|
+
fail("UNDECLARED_FAILURE", "UNDECLARED_FAILURE: Effect call failure boundary does not match its compiler authority.", expression.location);
|
|
78
|
+
}
|
|
79
|
+
if (!operation || expression.resolution.operationId != operation.id ||
|
|
80
|
+
JSON.stringify(expression.resolution) != JSON.stringify(signature(/** @type {import("./types.js").EffectCapabilityDeclaration} */ (capability), operation))) {
|
|
81
|
+
fail("UNDECLARED_EFFECT", "Effect call resolution does not match its compiler authority.", expression.location);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (expression.kind == "IdentifierExpression" && parseProtectedEntryName(expression.name) !== null) {
|
|
86
|
+
fail("STDLIB_PROTECTED_BINDING_ACCESS", `Reference to protected provider entry '${expression.name}' is not portable code.`, expression.location);
|
|
87
|
+
}
|
|
88
|
+
if (expression.kind != "CallExpression")
|
|
89
|
+
return;
|
|
90
|
+
if (functions.has(expression.callee))
|
|
91
|
+
return;
|
|
92
|
+
let operationName = expression.callee;
|
|
93
|
+
const protectedEntry = parseProtectedEntryName(expression.callee);
|
|
94
|
+
if (protectedEntry !== null) {
|
|
95
|
+
if (capabilities.length == 0) {
|
|
96
|
+
fail("STDLIB_PROTECTED_BINDING_ACCESS", `Protected provider entry '${expression.callee}' requires an explicit capability authority.`, expression.location);
|
|
97
|
+
}
|
|
98
|
+
if (protectedEntry.target != language) {
|
|
99
|
+
fail("STDLIB_PROTECTED_BINDING_ACCESS", `Protected provider entry target '${protectedEntry.target}' does not match source language '${language}'.`, expression.location);
|
|
100
|
+
}
|
|
101
|
+
operationName = protectedEntry.operation;
|
|
102
|
+
}
|
|
103
|
+
const match = authorizedOperation(capabilities, operationName);
|
|
104
|
+
if (!match) {
|
|
105
|
+
if (protectedEntry !== null) {
|
|
106
|
+
fail("STDLIB_PROTECTED_BINDING_ACCESS", `Protected provider entry for undeclared operation '${operationName}' has no authorized capability operation.`, expression.location);
|
|
107
|
+
}
|
|
108
|
+
if (isTask034OperationName(operationName)) {
|
|
109
|
+
fail("MISSING_CAPABILITY_AUTHORITY", `Operation '${operationName}' requires explicit compiler authority.`, expression.location);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!normalize) {
|
|
114
|
+
fail("UNDECLARED_EFFECT", `Caller-authored ordinary call '${expression.callee}' cannot forge a capability operation.`, expression.location);
|
|
115
|
+
}
|
|
116
|
+
const { capability, operation } = match;
|
|
117
|
+
const flow = operation.resourceFlow;
|
|
118
|
+
if ((flow.kind == "borrow" || flow.kind == "close") && expression.arguments[flow.parameterIndex]) {
|
|
119
|
+
const argument = expression.arguments[flow.parameterIndex];
|
|
120
|
+
if (argument.kind != "IdentifierExpression" && argument.kind != "PrivateFieldRead" && argument.kind != "ReceiverExpression") {
|
|
121
|
+
fail("INVALID_RESOURCE_BORROW", "An owned borrow must name one immediate resource place.", argument.location);
|
|
122
|
+
}
|
|
123
|
+
expression.arguments[flow.parameterIndex] = {
|
|
124
|
+
expression: argument,
|
|
125
|
+
kind: "OwnedBorrowExpression",
|
|
126
|
+
location: argument.location,
|
|
127
|
+
mode: flow.kind == "close" ? "exclusive" : "shared",
|
|
128
|
+
sourceProvenance: argument.sourceProvenance,
|
|
129
|
+
type: /** @type {import("./types.js").OwnedResourceType | import("./types.js").OwnedReferenceType} */ (operation.parameters[flow.parameterIndex].type)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const replacement = /** @type {import("./types.js").EffectCallExpression} */ ( /** @type {unknown} */(expression));
|
|
133
|
+
delete /** @type {{callee?: string}} */ (replacement).callee;
|
|
134
|
+
replacement.kind = "EffectCallExpression";
|
|
135
|
+
replacement.operation = operation.id;
|
|
136
|
+
replacement.resolution = signature(capability, operation);
|
|
137
|
+
});
|
|
138
|
+
const complete = completeEffectSummaries(module, failureIds, visibleClasses);
|
|
139
|
+
const summaries = complete.functions;
|
|
140
|
+
const methodSummaries = complete.methods;
|
|
141
|
+
const constructorSummaries = complete.constructors;
|
|
142
|
+
for (const declaration of module.classes ?? []) {
|
|
143
|
+
applyDeclarationSummary(declaration.constructor, constructorSummaries.get(/** @type {string} */ (declaration.constructor.id)), normalize, fail);
|
|
144
|
+
for (const method of declaration.methods) {
|
|
145
|
+
applyDeclarationSummary(method, methodSummaries.get(/** @type {string} */ (method.id)), normalize, fail);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
let site = 0;
|
|
149
|
+
forEachExpression(module, (expression) => {
|
|
150
|
+
if (expression.kind == "EffectCallExpression") {
|
|
151
|
+
if (normalize)
|
|
152
|
+
expression.effectSiteId = `effect:${site}`;
|
|
153
|
+
else
|
|
154
|
+
validateSite(expression, site, fail);
|
|
155
|
+
site += 1;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (expression.kind == "CallExpression") {
|
|
159
|
+
const summary = summaries.get(expression.callee);
|
|
160
|
+
if (!summary?.host) {
|
|
161
|
+
if (normalize) {
|
|
162
|
+
delete expression.effectSiteId;
|
|
163
|
+
delete expression.effects;
|
|
164
|
+
delete expression.failureIds;
|
|
165
|
+
}
|
|
166
|
+
if (!normalize && Array.isArray(expression.failureIds) && expression.failureIds.length > 0) {
|
|
167
|
+
fail("UNDECLARED_FAILURE", "UNDECLARED_FAILURE: Pure call carries a forged typed failure boundary.", expression.location);
|
|
168
|
+
}
|
|
169
|
+
if (!normalize && (expression.effectSiteId !== undefined || expression.effects !== undefined || expression.failureIds !== undefined)) {
|
|
170
|
+
fail("UNDECLARED_EFFECT", "Pure call carries forged effect metadata.", expression.location);
|
|
171
|
+
}
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (normalize) {
|
|
175
|
+
expression.effectSiteId = `effect:${site}`;
|
|
176
|
+
expression.effects = ["host"];
|
|
177
|
+
expression.failureIds = [...summary.failureIds];
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
validateSite(expression, site, fail);
|
|
181
|
+
if (!Array.isArray(expression.failureIds) || expression.failureIds.join(",") != [...summary.failureIds].join(",")) {
|
|
182
|
+
fail("UNDECLARED_FAILURE", "UNDECLARED_FAILURE: Call failure boundary does not match its resolved function.", expression.location);
|
|
183
|
+
}
|
|
184
|
+
if (expression.effects?.length != 1 || expression.effects[0] != "host") {
|
|
185
|
+
fail("UNDECLARED_EFFECT", "Call effect summary does not match its resolved function.", expression.location);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
site += 1;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (expression.kind == "MethodCallExpression" || expression.kind == "ReferenceConstruction") {
|
|
192
|
+
const summary = expression.kind == "MethodCallExpression"
|
|
193
|
+
? methodSummaries.get(expression.method)
|
|
194
|
+
: constructorSummaries.get(expression.resolution?.declarationId ?? `${expression.reference.declarationId}:constructor`);
|
|
195
|
+
const label = expression.kind == "MethodCallExpression" ? "method call" : "construction";
|
|
196
|
+
if (!summary?.host) {
|
|
197
|
+
if (normalize) {
|
|
198
|
+
delete expression.effectSiteId;
|
|
199
|
+
delete expression.effects;
|
|
200
|
+
delete expression.failureIds;
|
|
201
|
+
}
|
|
202
|
+
if (!normalize && Array.isArray(expression.failureIds) && expression.failureIds.length > 0) {
|
|
203
|
+
fail("UNDECLARED_FAILURE", `UNDECLARED_FAILURE: Pure ${label} carries a forged typed failure boundary.`, expression.location);
|
|
204
|
+
}
|
|
205
|
+
if (!normalize && (expression.effectSiteId !== undefined || expression.effects !== undefined || expression.failureIds !== undefined)) {
|
|
206
|
+
fail("UNDECLARED_EFFECT", `Pure ${label} carries forged effect metadata.`, expression.location);
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (normalize) {
|
|
211
|
+
expression.effectSiteId = `effect:${site}`;
|
|
212
|
+
expression.effects = ["host"];
|
|
213
|
+
expression.failureIds = [...summary.failureIds];
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
validateSite(expression, site, fail);
|
|
217
|
+
if (!Array.isArray(expression.failureIds) || expression.failureIds.join(",") != [...summary.failureIds].join(",")) {
|
|
218
|
+
fail("UNDECLARED_FAILURE", `UNDECLARED_FAILURE: ${label} failure boundary does not match its resolved declaration.`, expression.location);
|
|
219
|
+
}
|
|
220
|
+
if (expression.effects?.length != 1 || expression.effects[0] != "host") {
|
|
221
|
+
fail("UNDECLARED_EFFECT", `${label} effect summary does not match its resolved declaration.`, expression.location);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
site += 1;
|
|
225
|
+
}
|
|
226
|
+
}, true);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Computes the joint finite fixed point across functions and resolved receiver methods.
|
|
230
|
+
* @param {import("./types.js").SemanticModule} module - Resolved module.
|
|
231
|
+
* @param {Set<string>} capabilityFailureIds - Declared capability failures.
|
|
232
|
+
* @param {Map<string, import("./types.js").ClassDeclaration>} visibleClasses - Resolved reference classes.
|
|
233
|
+
* @returns {{constructors: Map<string, EffectSummary>, functions: Map<string, EffectSummary>, methods: Map<string, EffectSummary>}} Complete summaries.
|
|
234
|
+
*/
|
|
235
|
+
function completeEffectSummaries(module, capabilityFailureIds, visibleClasses) {
|
|
236
|
+
const importedMethods = declaredClassSummaries(visibleClasses, "methods");
|
|
237
|
+
let functions = effectSummaries(module.functions, new Map(), capabilityFailureIds);
|
|
238
|
+
let methods = directMethodSummaries(module, functions, importedMethods, capabilityFailureIds, importedMethods);
|
|
239
|
+
while (true) {
|
|
240
|
+
const nextFunctions = effectSummaries(module.functions, methods, capabilityFailureIds);
|
|
241
|
+
const nextMethods = directMethodSummaries(module, nextFunctions, methods, capabilityFailureIds, importedMethods);
|
|
242
|
+
if (sameSummaries(functions, nextFunctions) && sameSummaries(methods, nextMethods)) {
|
|
243
|
+
return { constructors: directConstructorSummaries(module, nextFunctions, nextMethods, capabilityFailureIds, declaredClassSummaries(visibleClasses, "constructors")), functions: nextFunctions, methods: nextMethods };
|
|
244
|
+
}
|
|
245
|
+
functions = nextFunctions;
|
|
246
|
+
methods = nextMethods;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Compares stable host/failure summary maps.
|
|
251
|
+
* @param {Map<string, EffectSummary>} left - Previous summaries.
|
|
252
|
+
* @param {Map<string, EffectSummary>} right - Next summaries.
|
|
253
|
+
* @returns {boolean} Whether the summaries are identical.
|
|
254
|
+
*/
|
|
255
|
+
function sameSummaries(left, right) {
|
|
256
|
+
if (left.size != right.size)
|
|
257
|
+
return false;
|
|
258
|
+
for (const [name, summary] of left) {
|
|
259
|
+
const candidate = right.get(name);
|
|
260
|
+
if (!candidate || summary.host != candidate.host || summary.failureIds.size != candidate.failureIds.size ||
|
|
261
|
+
[...summary.failureIds].some((id) => !candidate.failureIds.has(id)))
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Builds the complete immutable resolution recorded at an effect call site.
|
|
268
|
+
* @param {import("./types.js").EffectCapabilityDeclaration} capability - Declaring capability.
|
|
269
|
+
* @param {import("./types.js").EffectOperationDeclaration} operation - Resolved operation.
|
|
270
|
+
* @returns {import("./types.js").ResolvedEffectOperationSignature} Complete resolution.
|
|
271
|
+
*/
|
|
272
|
+
function signature(capability, operation) {
|
|
273
|
+
return {
|
|
274
|
+
capabilityId: capability.id,
|
|
275
|
+
effects: /** @type {const} */ (["host"]),
|
|
276
|
+
failureIds: [...operation.failureIds],
|
|
277
|
+
kind: /** @type {const} */ ("ResolvedEffectOperationSignature"),
|
|
278
|
+
operationId: operation.id,
|
|
279
|
+
parameterTypes: operation.parameters.map(({ type }) => /** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(type))),
|
|
280
|
+
resourceFlow: structuredClone(operation.resourceFlow),
|
|
281
|
+
returnType: typeIdentity(operation.returnType)
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Removes locations and provenance from one resolved type.
|
|
286
|
+
* @param {import("./types.js").SemanticFunctionReturnType} type - Semantic type.
|
|
287
|
+
* @returns {import("./types.js").FunctionReturnTypeIdentity} Stable type identity.
|
|
288
|
+
*/
|
|
289
|
+
function typeIdentity(type) {
|
|
290
|
+
if (type.kind == "TypeReference")
|
|
291
|
+
return type.name;
|
|
292
|
+
if (type.kind == "OwnedResourceType")
|
|
293
|
+
return { kind: type.kind, resourceId: type.resourceId };
|
|
294
|
+
if (type.kind == "OwnedReferenceType")
|
|
295
|
+
return { declarationId: type.declarationId, kind: type.kind };
|
|
296
|
+
if (type.kind == "OptionalType")
|
|
297
|
+
return { kind: type.kind,
|
|
298
|
+
valueType: /** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(type.valueType)) };
|
|
299
|
+
if (type.kind == "ListType")
|
|
300
|
+
return {
|
|
301
|
+
elementType: /** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(type.elementType)), kind: type.kind
|
|
302
|
+
};
|
|
303
|
+
if (type.kind == "MapType" || type.kind == "OrderedMapType") {
|
|
304
|
+
const keyType = /** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(type.keyType));
|
|
305
|
+
const valueType = /** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(type.valueType));
|
|
306
|
+
return type.kind == "OrderedMapType" ? { keyType, kind: type.kind, order: "insertion", valueType } :
|
|
307
|
+
{ keyType, kind: type.kind, valueType };
|
|
308
|
+
}
|
|
309
|
+
if (type.kind == "RecordType")
|
|
310
|
+
return { arguments: type.arguments?.map((argument) =>
|
|
311
|
+
/** @type {import("./types.js").SemanticTypeIdentity} */ (typeIdentity(argument))), declarationId: type.declarationId, kind: type.kind };
|
|
312
|
+
if (type.kind == "ReferenceType")
|
|
313
|
+
return { declarationId: type.declarationId, kind: type.kind };
|
|
314
|
+
return { kind: type.kind, parameterId: type.parameterId };
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Computes the fixed-point host-effect summary for ordinary functions.
|
|
318
|
+
* @param {import("./types.js").FunctionDeclaration[]} functions - Module functions.
|
|
319
|
+
* @param {Map<string, EffectSummary>} [methodSummaries] - Receiver-call summaries from the current fixed-point round.
|
|
320
|
+
* @param {Set<string>} [capabilityFailureIds] - Capability failures eligible for call-site propagation.
|
|
321
|
+
* @returns {Map<string, EffectSummary>} Summaries by source function name.
|
|
322
|
+
*/
|
|
323
|
+
function effectSummaries(functions, methodSummaries = new Map(), capabilityFailureIds = new Set()) {
|
|
324
|
+
const summaries = new Map(functions.map(({ name }) => /** @type {[string, EffectSummary]} */ ([name, { failureIds: new Set(), host: false }])));
|
|
325
|
+
let changed = true;
|
|
326
|
+
while (changed) {
|
|
327
|
+
changed = false;
|
|
328
|
+
for (const declaration of functions) {
|
|
329
|
+
const summary = summaries.get(declaration.name);
|
|
330
|
+
if (!summary)
|
|
331
|
+
continue;
|
|
332
|
+
forEachBlockExpression(declaration.body, (expression) => {
|
|
333
|
+
if (expression.kind == "EffectCallExpression") {
|
|
334
|
+
if (!summary.host) {
|
|
335
|
+
summary.host = true;
|
|
336
|
+
changed = true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
else if (expression.kind == "CallExpression") {
|
|
340
|
+
const called = summaries.get(expression.callee);
|
|
341
|
+
if (called?.host && !summary.host) {
|
|
342
|
+
summary.host = true;
|
|
343
|
+
changed = true;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else if (expression.kind == "MethodCallExpression") {
|
|
347
|
+
const called = methodSummaries.get(expression.method);
|
|
348
|
+
if (called?.host && !summary.host) {
|
|
349
|
+
summary.host = true;
|
|
350
|
+
changed = true;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}, false);
|
|
354
|
+
const escaping = escapingBlockFailures(declaration.body, summaries, methodSummaries, capabilityFailureIds);
|
|
355
|
+
for (const id of escaping)
|
|
356
|
+
if (!summary.failureIds.has(id)) {
|
|
357
|
+
summary.failureIds.add(id);
|
|
358
|
+
changed = true;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return summaries;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Computes the capability failures escaping one structured block.
|
|
366
|
+
* @param {import("./types.js").Block} block - Function body.
|
|
367
|
+
* @param {Map<string, EffectSummary>} functionSummaries - Current function fixed point.
|
|
368
|
+
* @param {Map<string, EffectSummary>} methodSummaries - Resolved method summaries.
|
|
369
|
+
* @param {Set<string>} capabilityFailureIds - Declared capability failures.
|
|
370
|
+
* @returns {Set<string>} Escaping failure identities.
|
|
371
|
+
*/
|
|
372
|
+
function escapingBlockFailures(block, functionSummaries, methodSummaries, capabilityFailureIds) {
|
|
373
|
+
const result = new Set();
|
|
374
|
+
for (const statement of block.statements) {
|
|
375
|
+
if (statement.kind == "TryStatement") {
|
|
376
|
+
const body = escapingBlockFailures(statement.body, functionSummaries, methodSummaries, capabilityFailureIds);
|
|
377
|
+
if (body.delete(statement.catchType.declarationId)) {
|
|
378
|
+
addFailures(result, escapingBlockFailures(statement.catchBody, functionSummaries, methodSummaries, capabilityFailureIds));
|
|
379
|
+
}
|
|
380
|
+
addFailures(result, body);
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
for (const expression of statementExpressions(statement)) {
|
|
384
|
+
addExpressionFailures(result, expression, functionSummaries, methodSummaries);
|
|
385
|
+
}
|
|
386
|
+
if (statement.kind == "RaiseStatement" && capabilityFailureIds.has(statement.error.error.declarationId)) {
|
|
387
|
+
result.add(statement.error.error.declarationId);
|
|
388
|
+
}
|
|
389
|
+
for (const child of statementBlocks(statement)) {
|
|
390
|
+
addFailures(result, escapingBlockFailures(child, functionSummaries, methodSummaries, capabilityFailureIds));
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Adds failures evaluated by one expression subtree.
|
|
397
|
+
* @param {Set<string>} target - Destination identities.
|
|
398
|
+
* @param {import("./types.js").Expression} expression - Expression root.
|
|
399
|
+
* @param {Map<string, EffectSummary>} functionSummaries - Function summaries.
|
|
400
|
+
* @param {Map<string, EffectSummary>} methodSummaries - Method summaries.
|
|
401
|
+
* @returns {void}
|
|
402
|
+
*/
|
|
403
|
+
function addExpressionFailures(target, expression, functionSummaries, methodSummaries) {
|
|
404
|
+
if (expression.kind == "EffectCallExpression")
|
|
405
|
+
addFailures(target, expression.resolution.failureIds);
|
|
406
|
+
else if (expression.kind == "CallExpression")
|
|
407
|
+
addFailures(target, functionSummaries.get(expression.callee)?.failureIds ?? []);
|
|
408
|
+
else if (expression.kind == "MethodCallExpression")
|
|
409
|
+
addFailures(target, methodSummaries.get(expression.method)?.failureIds ?? []);
|
|
410
|
+
for (const child of expressionChildren(expression))
|
|
411
|
+
addExpressionFailures(target, child, functionSummaries, methodSummaries);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Returns directly evaluated expressions for one statement.
|
|
415
|
+
* @param {import("./types.js").Statement} statement - Statement.
|
|
416
|
+
* @returns {import("./types.js").Expression[]} Expression roots.
|
|
417
|
+
*/
|
|
418
|
+
function statementExpressions(statement) {
|
|
419
|
+
if (statement.kind == "LocalDeclaration")
|
|
420
|
+
return [statement.initializer];
|
|
421
|
+
if (statement.kind == "AssignmentStatement" || statement.kind == "PrivateFieldWriteStatement" ||
|
|
422
|
+
statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement")
|
|
423
|
+
return [statement.expression];
|
|
424
|
+
if (statement.kind == "ReturnStatement")
|
|
425
|
+
return statement.expression ? [statement.expression] : [];
|
|
426
|
+
if (statement.kind == "RaiseStatement")
|
|
427
|
+
return [statement.error.message];
|
|
428
|
+
if (statement.kind == "IfStatement" || statement.kind == "WhileStatement")
|
|
429
|
+
return [statement.condition];
|
|
430
|
+
if (statement.kind == "ForEachStatement")
|
|
431
|
+
return [statement.list];
|
|
432
|
+
if (statement.kind == "ForEachMapStatement")
|
|
433
|
+
return [statement.map];
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Returns nested blocks whose failures propagate through one statement.
|
|
438
|
+
* @param {import("./types.js").Statement} statement - Statement.
|
|
439
|
+
* @returns {import("./types.js").Block[]} Child blocks.
|
|
440
|
+
*/
|
|
441
|
+
function statementBlocks(statement) {
|
|
442
|
+
if (statement.kind == "IfStatement")
|
|
443
|
+
return [statement.consequent, ...(statement.alternate ? [statement.alternate] : [])];
|
|
444
|
+
if (statement.kind == "WhileStatement" || statement.kind == "ForEachStatement" || statement.kind == "ForEachMapStatement") {
|
|
445
|
+
return [statement.body];
|
|
446
|
+
}
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Adds an iterable of failure identities to a set.
|
|
451
|
+
* @param {Set<string>} target - Destination.
|
|
452
|
+
* @param {Iterable<string>} source - Source identities.
|
|
453
|
+
* @returns {void}
|
|
454
|
+
*/
|
|
455
|
+
function addFailures(target, source) {
|
|
456
|
+
for (const id of source)
|
|
457
|
+
target.add(id);
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Computes bounded direct summaries for class methods.
|
|
461
|
+
* @param {import("./types.js").SemanticModule} module - Resolved module.
|
|
462
|
+
* @param {Map<string, EffectSummary>} functionSummaries - Ordinary function summaries.
|
|
463
|
+
* @param {Map<string, EffectSummary>} priorMethodSummaries - Receiver summaries from the previous fixed-point round.
|
|
464
|
+
* @param {Set<string>} capabilityFailureIds - Declared capability failures.
|
|
465
|
+
* @param {Map<string, EffectSummary>} baseSummaries - Imported receiver summaries.
|
|
466
|
+
* @returns {Map<string, EffectSummary>} Summaries by resolved method identity.
|
|
467
|
+
*/
|
|
468
|
+
function directMethodSummaries(module, functionSummaries, priorMethodSummaries, capabilityFailureIds, baseSummaries = new Map()) {
|
|
469
|
+
/** @type {Map<string, EffectSummary>} */
|
|
470
|
+
const summaries = new Map(baseSummaries);
|
|
471
|
+
for (const declaration of module.classes ?? []) {
|
|
472
|
+
for (const method of declaration.methods) {
|
|
473
|
+
/** @type {EffectSummary} */
|
|
474
|
+
const summary = { failureIds: escapingBlockFailures(method.body, functionSummaries, priorMethodSummaries, capabilityFailureIds), host: false };
|
|
475
|
+
forEachBlockExpression(method.body, (expression) => {
|
|
476
|
+
if (expression.kind == "EffectCallExpression") {
|
|
477
|
+
summary.host = true;
|
|
478
|
+
const flow = expression.resolution.resourceFlow;
|
|
479
|
+
const argument = flow.kind == "borrow" || flow.kind == "close" ? expression.arguments[flow.parameterIndex] : undefined;
|
|
480
|
+
const borrowedParameterName = argument?.kind == "OwnedBorrowExpression" && argument.expression.kind == "IdentifierExpression"
|
|
481
|
+
? argument.expression.name : undefined;
|
|
482
|
+
const knownOpenBorrow = declaration.ownership?.kind == "ownedResource" && argument?.kind == "OwnedBorrowExpression" && (argument.expression.kind == "PrivateFieldRead" && argument.expression.field == declaration.ownership.fieldId ||
|
|
483
|
+
borrowedParameterName !== undefined && method.parameters.some((parameter) => parameter.name == borrowedParameterName &&
|
|
484
|
+
(parameter.type.kind == "OwnedResourceType" || parameter.type.kind == "OwnedReferenceType")));
|
|
485
|
+
const terminalFailureId = knownOpenBorrow
|
|
486
|
+
? flow.kind == "borrow" || flow.kind == "close" ? flow.terminalFailureId : undefined
|
|
487
|
+
: undefined;
|
|
488
|
+
if (terminalFailureId)
|
|
489
|
+
summary.failureIds.delete(terminalFailureId);
|
|
490
|
+
}
|
|
491
|
+
else if (expression.kind == "CallExpression") {
|
|
492
|
+
const called = functionSummaries.get(expression.callee);
|
|
493
|
+
if (called?.host)
|
|
494
|
+
summary.host = true;
|
|
495
|
+
}
|
|
496
|
+
else if (expression.kind == "MethodCallExpression") {
|
|
497
|
+
const called = priorMethodSummaries.get(expression.method);
|
|
498
|
+
if (called?.host)
|
|
499
|
+
summary.host = true;
|
|
500
|
+
}
|
|
501
|
+
}, false);
|
|
502
|
+
summaries.set(/** @type {string} */ (method.id), summary);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return summaries;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Reads checked summaries already proved on imported class declarations.
|
|
509
|
+
* @param {Map<string, import("./types.js").ClassDeclaration>} classes - Visible classes.
|
|
510
|
+
* @param {"constructors" | "methods"} kind - Declaration cohort.
|
|
511
|
+
* @returns {Map<string, EffectSummary>} Imported summaries by declaration identity.
|
|
512
|
+
*/
|
|
513
|
+
function declaredClassSummaries(classes, kind) {
|
|
514
|
+
/** @type {Map<string, EffectSummary>} */
|
|
515
|
+
const summaries = new Map();
|
|
516
|
+
for (const declaration of classes.values()) {
|
|
517
|
+
const members = kind == "constructors" ? [declaration.constructor] : declaration.methods;
|
|
518
|
+
for (const member of members) {
|
|
519
|
+
if (member.effects?.length == 1 && member.effects[0] == "host" && Array.isArray(member.failureIds)) {
|
|
520
|
+
summaries.set(/** @type {string} */ (member.id), { failureIds: new Set(member.failureIds), host: true });
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return summaries;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Computes direct constructor effects after function and method fixed points stabilize.
|
|
528
|
+
* @param {import("./types.js").SemanticModule} module - Resolved module.
|
|
529
|
+
* @param {Map<string, EffectSummary>} functionSummaries - Stable function summaries.
|
|
530
|
+
* @param {Map<string, EffectSummary>} methodSummaries - Stable method summaries.
|
|
531
|
+
* @param {Set<string>} capabilityFailureIds - Declared capability failures.
|
|
532
|
+
* @param {Map<string, EffectSummary>} baseSummaries - Imported constructor summaries.
|
|
533
|
+
* @returns {Map<string, EffectSummary>} Constructor summaries by identity.
|
|
534
|
+
*/
|
|
535
|
+
function directConstructorSummaries(module, functionSummaries, methodSummaries, capabilityFailureIds, baseSummaries) {
|
|
536
|
+
const summaries = new Map(baseSummaries);
|
|
537
|
+
for (const declaration of module.classes ?? []) {
|
|
538
|
+
const constructor = declaration.constructor;
|
|
539
|
+
/** @type {EffectSummary} */
|
|
540
|
+
const summary = {
|
|
541
|
+
failureIds: escapingBlockFailures(constructor.body, functionSummaries, methodSummaries, capabilityFailureIds),
|
|
542
|
+
host: false
|
|
543
|
+
};
|
|
544
|
+
forEachBlockExpression(constructor.body, (expression) => {
|
|
545
|
+
if (expression.kind == "EffectCallExpression")
|
|
546
|
+
summary.host = true;
|
|
547
|
+
else if (expression.kind == "CallExpression" && functionSummaries.get(expression.callee)?.host)
|
|
548
|
+
summary.host = true;
|
|
549
|
+
else if (expression.kind == "MethodCallExpression" && methodSummaries.get(expression.method)?.host)
|
|
550
|
+
summary.host = true;
|
|
551
|
+
}, false);
|
|
552
|
+
summaries.set(/** @type {string} */ (constructor.id), summary);
|
|
553
|
+
}
|
|
554
|
+
return summaries;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Records or verifies one checked class-member summary.
|
|
558
|
+
* @param {import("./types.js").ConstructorDeclaration | import("./types.js").MethodDeclaration} declaration - Class member.
|
|
559
|
+
* @param {EffectSummary | undefined} summary - Computed summary.
|
|
560
|
+
* @param {boolean} normalize - Whether metadata may be written.
|
|
561
|
+
* @param {(code: string, detail: string, location: import("./types.js").SourceLocation) => never} fail - Located failure.
|
|
562
|
+
* @returns {void}
|
|
563
|
+
*/
|
|
564
|
+
function applyDeclarationSummary(declaration, summary, normalize, fail) {
|
|
565
|
+
if (!summary?.host) {
|
|
566
|
+
if (normalize) {
|
|
567
|
+
delete declaration.effects;
|
|
568
|
+
delete declaration.failureIds;
|
|
569
|
+
}
|
|
570
|
+
else if (declaration.effects !== undefined || declaration.failureIds !== undefined) {
|
|
571
|
+
fail("UNDECLARED_EFFECT", "Pure class member carries forged effect metadata.", declaration.location);
|
|
572
|
+
}
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const failureIds = [...summary.failureIds];
|
|
576
|
+
if (normalize) {
|
|
577
|
+
declaration.effects = ["host"];
|
|
578
|
+
declaration.failureIds = failureIds;
|
|
579
|
+
}
|
|
580
|
+
else if (declaration.effects?.length != 1 || declaration.effects[0] != "host" ||
|
|
581
|
+
!Array.isArray(declaration.failureIds) || declaration.failureIds.join(",") != failureIds.join(",")) {
|
|
582
|
+
fail("UNDECLARED_EFFECT", "Class member effect summary does not match its body.", declaration.location);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Validates one deterministic effect-site identity.
|
|
587
|
+
* @param {import("./types.js").CallExpression | import("./types.js").EffectCallExpression | import("./types.js").MethodCallExpression | import("./types.js").ReferenceConstruction} expression - Effectful call.
|
|
588
|
+
* @param {number} site - Expected traversal index.
|
|
589
|
+
* @param {(code: string, detail: string, location: import("./types.js").SourceLocation) => never} fail - Located failure.
|
|
590
|
+
* @returns {void}
|
|
591
|
+
*/
|
|
592
|
+
function validateSite(expression, site, fail) {
|
|
593
|
+
if (expression.effectSiteId != `effect:${site}`) {
|
|
594
|
+
fail("INVALID_EFFECT_ORDER", `Effect site '${String(expression.effectSiteId)}' is not expected site 'effect:${site}'.`, expression.location);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Visits every expression in deterministic declaration and evaluation order.
|
|
599
|
+
* @param {import("./types.js").SemanticModule} module - Module to traverse.
|
|
600
|
+
* @param {ExpressionVisitor} visitor - Expression visitor.
|
|
601
|
+
* @param {boolean} [postorder] - Visit children before parents.
|
|
602
|
+
* @returns {void}
|
|
603
|
+
*/
|
|
604
|
+
function forEachExpression(module, visitor, postorder = false) {
|
|
605
|
+
for (const declaration of module.classes ?? []) {
|
|
606
|
+
forEachBlockExpression(declaration.constructor.body, visitor, postorder);
|
|
607
|
+
for (const method of declaration.methods)
|
|
608
|
+
forEachBlockExpression(method.body, visitor, postorder);
|
|
609
|
+
}
|
|
610
|
+
for (const declaration of module.functions)
|
|
611
|
+
forEachBlockExpression(declaration.body, visitor, postorder);
|
|
612
|
+
forEachBlockExpression(module.entryPoint.body, visitor, postorder);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Visits expressions in one structured block.
|
|
616
|
+
* @param {import("./types.js").Block} block - Block to traverse.
|
|
617
|
+
* @param {ExpressionVisitor} visitor - Expression visitor.
|
|
618
|
+
* @param {boolean} postorder - Visit children before parents.
|
|
619
|
+
* @returns {void}
|
|
620
|
+
*/
|
|
621
|
+
function forEachBlockExpression(block, visitor, postorder) {
|
|
622
|
+
for (const statement of block.statements) {
|
|
623
|
+
if (statement.kind == "LocalDeclaration")
|
|
624
|
+
visit(statement.initializer);
|
|
625
|
+
else if (statement.kind == "AssignmentStatement" || statement.kind == "PrivateFieldWriteStatement")
|
|
626
|
+
visit(statement.expression);
|
|
627
|
+
else if (statement.kind == "ReturnStatement" && statement.expression)
|
|
628
|
+
visit(statement.expression);
|
|
629
|
+
else if (statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement")
|
|
630
|
+
visit(statement.expression);
|
|
631
|
+
else if (statement.kind == "IfStatement") {
|
|
632
|
+
visit(statement.condition);
|
|
633
|
+
forEachBlockExpression(statement.consequent, visitor, postorder);
|
|
634
|
+
if (statement.alternate)
|
|
635
|
+
forEachBlockExpression(statement.alternate, visitor, postorder);
|
|
636
|
+
}
|
|
637
|
+
else if (statement.kind == "ForEachStatement") {
|
|
638
|
+
visit(statement.list);
|
|
639
|
+
forEachBlockExpression(statement.body, visitor, postorder);
|
|
640
|
+
}
|
|
641
|
+
else if (statement.kind == "ForEachMapStatement") {
|
|
642
|
+
visit(statement.map);
|
|
643
|
+
forEachBlockExpression(statement.body, visitor, postorder);
|
|
644
|
+
}
|
|
645
|
+
else if (statement.kind == "WhileStatement") {
|
|
646
|
+
visit(statement.condition);
|
|
647
|
+
forEachBlockExpression(statement.body, visitor, postorder);
|
|
648
|
+
}
|
|
649
|
+
else if (statement.kind == "RaiseStatement")
|
|
650
|
+
visit(statement.error.message);
|
|
651
|
+
else if (statement.kind == "TryStatement") {
|
|
652
|
+
forEachBlockExpression(statement.body, visitor, postorder);
|
|
653
|
+
forEachBlockExpression(statement.catchBody, visitor, postorder);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Visits one expression subtree.
|
|
658
|
+
* @param {import("./types.js").Expression} expression - Expression root.
|
|
659
|
+
* @returns {void}
|
|
660
|
+
*/
|
|
661
|
+
function visit(expression) {
|
|
662
|
+
if (!postorder)
|
|
663
|
+
visitor(expression);
|
|
664
|
+
for (const child of expressionChildren(expression))
|
|
665
|
+
visit(child);
|
|
666
|
+
if (postorder)
|
|
667
|
+
visitor(expression);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Reports whether one semantic block references a reserved protected provider entry.
|
|
672
|
+
* @param {import("./types.js").Block} block - Semantic block.
|
|
673
|
+
* @returns {boolean} Whether a protected entry name is referenced.
|
|
674
|
+
*/
|
|
675
|
+
export function blockReferencesProtectedEntry(block) {
|
|
676
|
+
return block.statements.some(statementReferencesProtectedEntry);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Reports whether one semantic statement references a reserved protected provider entry.
|
|
680
|
+
* @param {import("./types.js").Statement} statement - Semantic statement.
|
|
681
|
+
* @returns {boolean} Whether a protected entry name is referenced.
|
|
682
|
+
*/
|
|
683
|
+
function statementReferencesProtectedEntry(statement) {
|
|
684
|
+
switch (statement.kind) {
|
|
685
|
+
case "LocalDeclaration":
|
|
686
|
+
return expressionReferencesProtectedEntry(statement.initializer);
|
|
687
|
+
case "AssignmentStatement":
|
|
688
|
+
case "PrivateFieldWriteStatement":
|
|
689
|
+
return expressionReferencesProtectedEntry(statement.expression);
|
|
690
|
+
case "ReturnStatement":
|
|
691
|
+
return statement.expression ? expressionReferencesProtectedEntry(statement.expression) : false;
|
|
692
|
+
case "ExpressionStatement":
|
|
693
|
+
case "PrintStatement":
|
|
694
|
+
return expressionReferencesProtectedEntry(statement.expression);
|
|
695
|
+
case "IfStatement":
|
|
696
|
+
return expressionReferencesProtectedEntry(statement.condition) ||
|
|
697
|
+
blockReferencesProtectedEntry(statement.consequent) ||
|
|
698
|
+
(statement.alternate ? blockReferencesProtectedEntry(statement.alternate) : false);
|
|
699
|
+
case "ForEachStatement":
|
|
700
|
+
return expressionReferencesProtectedEntry(statement.list) || blockReferencesProtectedEntry(statement.body);
|
|
701
|
+
case "ForEachMapStatement":
|
|
702
|
+
return expressionReferencesProtectedEntry(statement.map) || blockReferencesProtectedEntry(statement.body);
|
|
703
|
+
case "WhileStatement":
|
|
704
|
+
return expressionReferencesProtectedEntry(statement.condition) || blockReferencesProtectedEntry(statement.body);
|
|
705
|
+
case "RaiseStatement":
|
|
706
|
+
return expressionReferencesProtectedEntry(statement.error.message);
|
|
707
|
+
case "TryStatement":
|
|
708
|
+
return blockReferencesProtectedEntry(statement.body) || blockReferencesProtectedEntry(statement.catchBody);
|
|
709
|
+
default:
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Reports whether one semantic expression references a reserved protected provider entry.
|
|
715
|
+
* @param {import("./types.js").Expression} expression - Semantic expression.
|
|
716
|
+
* @returns {boolean} Whether a protected entry name is referenced.
|
|
717
|
+
*/
|
|
718
|
+
function expressionReferencesProtectedEntry(expression) {
|
|
719
|
+
if (expression.kind == "IdentifierExpression" && parseProtectedEntryName(expression.name) !== null)
|
|
720
|
+
return true;
|
|
721
|
+
if (expression.kind == "CallExpression" && parseProtectedEntryName(expression.callee) !== null)
|
|
722
|
+
return true;
|
|
723
|
+
return expressionChildren(expression).some(expressionReferencesProtectedEntry);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Returns semantic child expressions in evaluation order.
|
|
727
|
+
* @param {import("./types.js").Expression} expression - Parent expression.
|
|
728
|
+
* @returns {import("./types.js").Expression[]} Children.
|
|
729
|
+
*/
|
|
730
|
+
function expressionChildren(expression) {
|
|
731
|
+
if (expression.kind == "CallExpression" || expression.kind == "EffectCallExpression" || expression.kind == "ReferenceConstruction" ||
|
|
732
|
+
expression.kind == "RecordConstruction")
|
|
733
|
+
return expression.arguments;
|
|
734
|
+
if (expression.kind == "MethodCallExpression")
|
|
735
|
+
return [expression.receiver, ...expression.arguments];
|
|
736
|
+
if (expression.kind == "OwnedBorrowExpression" || expression.kind == "OwnedMoveExpression")
|
|
737
|
+
return [expression.expression];
|
|
738
|
+
if (expression.kind == "BinaryExpression")
|
|
739
|
+
return [expression.left, expression.right];
|
|
740
|
+
if (expression.kind == "UnaryExpression")
|
|
741
|
+
return [expression.operand];
|
|
742
|
+
if (expression.kind == "OptionalSome")
|
|
743
|
+
return [expression.value];
|
|
744
|
+
if (expression.kind == "OptionalIsPresent" || expression.kind == "OptionalUnwrap")
|
|
745
|
+
return [expression.operand];
|
|
746
|
+
if (expression.kind == "ListLiteral")
|
|
747
|
+
return expression.elements;
|
|
748
|
+
if (expression.kind == "MapLiteral" || expression.kind == "OrderedMapLiteral")
|
|
749
|
+
return expression.entries.map(({ value }) => value);
|
|
750
|
+
if (expression.kind == "ListIndexExpression")
|
|
751
|
+
return [expression.collection, expression.index];
|
|
752
|
+
if (expression.kind == "MapLookupExpression")
|
|
753
|
+
return [expression.collection, expression.key];
|
|
754
|
+
if (expression.kind == "CollectionSizeExpression")
|
|
755
|
+
return [expression.collection];
|
|
756
|
+
if (expression.kind == "MemberRead")
|
|
757
|
+
return [expression.receiver];
|
|
758
|
+
if (expression.kind == "PrivateFieldRead")
|
|
759
|
+
return [expression.receiver];
|
|
760
|
+
if (expression.kind == "ErrorMessageRead")
|
|
761
|
+
return [expression.receiver];
|
|
762
|
+
return [];
|
|
763
|
+
}
|
|
764
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWZmZWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZW1hbnRpYy9lZmZlY3RzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsbUJBQW1CLEVBQUUsc0JBQXNCLEVBQUMsTUFBTSxtQkFBbUIsQ0FBQTtBQUM3RSxPQUFPLEVBQUMsdUJBQXVCLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFFbkQsd0VBQXdFO0FBQ3hFLHlGQUF5RjtBQUV6Rjs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsY0FBYyxHQUFHLElBQUksR0FBRyxFQUFFO0lBQzFHLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFBO0lBQzlDLE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7SUFDL0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUM5QixNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQzdCLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7SUFDNUIsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUVoQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7UUFBRSxJQUFJLENBQUMsOEJBQThCLEVBQUUsd0NBQXdDLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ2pJLEtBQUssTUFBTSxDQUFDLGVBQWUsRUFBRSxVQUFVLENBQUMsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUNuRSxNQUFNLFFBQVEsR0FBRyxjQUFjLGVBQWUsRUFBRSxDQUFBO1FBRWhELElBQUksQ0FBQyxVQUFVLElBQUksVUFBVSxDQUFDLElBQUks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Q0FBQyxHQUFHLENBQUMsQ0FBQTtJQUM1RixJQUFJLFVBQVUsQ0FBQyxJQUFJLElBQUksMEJBQTBCO1FBQUUsT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUNqRixJQUFJLFVBQVUsQ0FBQyxJQUFJLElBQUksWUFBWTtRQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDakUsSUFBSSxVQUFVLENBQUMsSUFBSSxJQUFJLGtCQUFrQjtRQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDdkUsSUFBSSxVQUFVLENBQUMsSUFBSSxJQUFJLGtCQUFrQjtRQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDdkUsT0FBTyxFQUFFLENBQUE7QUFDWCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7YXV0aG9yaXplZE9wZXJhdGlvbiwgaXNUYXNrMDM0T3BlcmF0aW9uTmFtZX0gZnJvbSBcIi4vY2FwYWJpbGl0aWVzLmpzXCJcbmltcG9ydCB7cGFyc2VQcm90ZWN0ZWRFbnRyeU5hbWV9IGZyb20gXCIuL3N0ZGxpYi5qc1wiXG5cbi8qKiBAdHlwZWRlZiB7e2ZhaWx1cmVJZHM6IFNldDxzdHJpbmc+LCBob3N0OiBib29sZWFufX0gRWZmZWN0U3VtbWFyeSAqL1xuLyoqIEB0eXBlZGVmIHsoZXhwcmVzc2lvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9uKSA9PiB2b2lkfSBFeHByZXNzaW9uVmlzaXRvciAqL1xuXG4vKipcbiAqIFJlc29sdmVzIGNvbXBpbGVyLWF1dGhvcml6ZWQgY2FsbHMgYmVmb3JlIG9yZGluYXJ5IHNlbWFudGljIHR5cGUgdmFsaWRhdGlvbi5cbiAqIFNvdXJjZSBmdW5jdGlvbnMgYWx3YXlzIHdpbjsgYXV0aG9yaXR5IGlzIG5ldmVyIGluZmVycmVkIGZyb20gc3BlbGxpbmcgYWxvbmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFBhcnNlci1hdXRob3JlZCBtb2R1bGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFuZ3VhZ2UgLSBTb3VyY2UgbGFuZ3VhZ2UgaWRlbnRpdHkgZm9yIHByb3RlY3RlZCBlbnRyeSB0YXJnZXRzLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb24+fSBmdW5jdGlvbnMgLSBWaXNpYmxlIG9yZGluYXJ5IGZ1bmN0aW9ucy5cbiAqIEBwYXJhbSB7KGNvZGU6IHN0cmluZywgZGV0YWlsOiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uKSA9PiBuZXZlcn0gZmFpbCAtIExvY2F0ZWQgZmFpbHVyZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gbm9ybWFsaXplIC0gV2hldGhlciBwYXJzZXItYXV0aG9yZWQgb3BlcmF0aW9uIGludGVudCBtYXkgYmUgbm9ybWFsaXplZC5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5DbGFzc0RlY2xhcmF0aW9uPn0gW3Zpc2libGVDbGFzc2VzXSAtIFJlc29sdmVkIHJlZmVyZW5jZSBjbGFzc2VzLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUVmZmVjdEdyYXBoKG1vZHVsZSwgbGFuZ3VhZ2UsIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplLCB2aXNpYmxlQ2xhc3NlcyA9IG5ldyBNYXAoKSkge1xuICBjb25zdCBjYXBhYmlsaXRpZXMgPSBtb2R1bGUuY2FwYWJpbGl0aWVzID8/IFtdXG4gIGNvbnN0IGNhcGFiaWxpdHlJZHMgPSBuZXcgU2V0KClcbiAgY29uc3Qgb3BlcmF0aW9uSWRzID0gbmV3IFNldCgpXG4gIGNvbnN0IHJlc291cmNlSWRzID0gbmV3IFNldCgpXG4gIGNvbnN0IGZhaWx1cmVJZHMgPSBuZXcgU2V0KClcbiAgY29uc3Qgb3BlcmF0aW9uTmFtZXMgPSBuZXcgU2V0KClcblxuICBpZiAoIUFycmF5LmlzQXJyYXkoY2FwYWJpbGl0aWVzKSkgZmFpbChcIklOVkFMSURfQ0FQQUJJTElUWV9BVVRIT1JJVFlcIiwgXCJDYXBhYmlsaXRpZXMgbXVzdCBiZSBhbiBvcmRlcmVkIGFycmF5LlwiLCBtb2R1bGUubG9jYXRpb24pXG4gIGZvciAoY29uc3QgW2NhcGFiaWxpdHlJbmRleCwgY2FwYWJpbGl0eV0gb2YgY2FwYWJpbGl0aWVzLmVudHJpZXMoKSkge1xuICAgIGNvbnN0IGxlZ2FjeUlkID0gYGNhcGFiaWxpdHk6JHtjYXBhYmlsaXR5SW5kZXh9YFxuXG4gICAgaWYgKCFjYXBhYmlsaXR5IHx8IGNhcGFiaWxpdHkua2luZCAhPSBcIkVmZmVjdENhcGFiaWxpdHlEZWNsYXJhdGlvblwiIHx8XG4gICAgICBjYXBhYmlsaXR5LmlkICE9IGxlZ2FjeUlkICYmICEvXm1vZHVsZTpcXGQrXFwvY2FwYWJpbGl0eTpcXGQrJC91LnRlc3QoY2FwYWJpbGl0eS5pZCkgfHwgY2FwYWJpbGl0eUlkcy5oYXMoY2FwYWJpbGl0eS5pZCkgfHxcbiAgICAgIHR5cGVvZiBjYXBhYmlsaXR5LmF1dGhvcml0eUlkICE9IFwic3RyaW5nXCIgfHwgdHlwZW9mIGNhcGFiaWxpdHkubmFtZSAhPSBcInN0cmluZ1wiIHx8ICFBcnJheS5pc0FycmF5KGNhcGFiaWxpdHkucmVzb3VyY2VzKSB8fFxuICAgICAgIUFycmF5LmlzQXJyYXkoY2FwYWJpbGl0eS5mYWlsdXJlcykgfHwgIUFycmF5LmlzQXJyYXkoY2FwYWJpbGl0eS5vcGVyYXRpb25zKSkge1xuICAgICAgZmFpbChcIklOVkFMSURfQ0FQQUJJTElUWV9BVVRIT1JJVFlcIiwgXCJNYWxmb3JtZWQgY2FwYWJpbGl0eSBkZWNsYXJhdGlvbiBncmFwaC5cIiwgbW9kdWxlLmxvY2F0aW9uKVxuICAgIH1cbiAgICBjYXBhYmlsaXR5SWRzLmFkZChjYXBhYmlsaXR5LmlkKVxuICAgIGZvciAoY29uc3QgW2luZGV4LCByZXNvdXJjZV0gb2YgY2FwYWJpbGl0eS5yZXNvdXJjZXMuZW50cmllcygpKSB7XG4gICAgICBpZiAocmVzb3VyY2Uua2luZCAhPSBcIkVmZmVjdFJlc291cmNlRGVjbGFyYXRpb25cIiB8fCByZXNvdXJjZS5pZCAhPSBgJHtjYXBhYmlsaXR5LmlkfS9yZXNvdXJjZToke2luZGV4fWAgfHxcbiAgICAgICAgcmVzb3VyY2VJZHMuaGFzKHJlc291cmNlLmlkKSkgZmFpbChcIklOVkFMSURfQ0FQQUJJTElUWV9BVVRIT1JJVFlcIiwgXCJNYWxmb3JtZWQgY2FwYWJpbGl0eSByZXNvdXJjZSBpZGVudGl0eS5cIiwgbW9kdWxlLmxvY2F0aW9uKVxuICAgICAgcmVzb3VyY2VJZHMuYWRkKHJlc291cmNlLmlkKVxuICAgIH1cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgZmFpbHVyZV0gb2YgY2FwYWJpbGl0eS5mYWlsdXJlcy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChmYWlsdXJlLmtpbmQgIT0gXCJFZmZlY3RGYWlsdXJlRGVjbGFyYXRpb25cIiB8fCBmYWlsdXJlLmlkICE9IGAke2NhcGFiaWxpdHkuaWR9L2ZhaWx1cmU6JHtpbmRleH1gIHx8XG4gICAgICAgIGZhaWx1cmVJZHMuaGFzKGZhaWx1cmUuaWQpKSBmYWlsKFwiSU5WQUxJRF9DQVBBQklMSVRZX0FVVEhPUklUWVwiLCBcIk1hbGZvcm1lZCBjYXBhYmlsaXR5IGZhaWx1cmUgaWRlbnRpdHkuXCIsIG1vZHVsZS5sb2NhdGlvbilcbiAgICAgIGZhaWx1cmVJZHMuYWRkKGZhaWx1cmUuaWQpXG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgY2FwYWJpbGl0eSBvZiBjYXBhYmlsaXRpZXMpIHtcbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgb3BlcmF0aW9uXSBvZiBjYXBhYmlsaXR5Lm9wZXJhdGlvbnMuZW50cmllcygpKSB7XG4gICAgICBpZiAob3BlcmF0aW9uLmtpbmQgIT0gXCJFZmZlY3RPcGVyYXRpb25EZWNsYXJhdGlvblwiIHx8IG9wZXJhdGlvbi5pZCAhPSBgJHtjYXBhYmlsaXR5LmlkfS9vcGVyYXRpb246JHtpbmRleH1gIHx8XG4gICAgICAgIG9wZXJhdGlvbklkcy5oYXMob3BlcmF0aW9uLmlkKSB8fCBvcGVyYXRpb25OYW1lcy5oYXMob3BlcmF0aW9uLm5hbWUpIHx8ICFBcnJheS5pc0FycmF5KG9wZXJhdGlvbi5wYXJhbWV0ZXJzKSB8fFxuICAgICAgICAhQXJyYXkuaXNBcnJheShvcGVyYXRpb24uZmFpbHVyZUlkcykgfHwgb3BlcmF0aW9uLmVmZmVjdHM/Lmxlbmd0aCAhPSAxIHx8IG9wZXJhdGlvbi5lZmZlY3RzWzBdICE9IFwiaG9zdFwiIHx8XG4gICAgICAgIG9wZXJhdGlvbi5mYWlsdXJlSWRzLnNvbWUoKGlkKSA9PiAhZmFpbHVyZUlkcy5oYXMoaWQpKSkge1xuICAgICAgICBmYWlsKFwiSU5WQUxJRF9DQVBBQklMSVRZX0FVVEhPUklUWVwiLCBcIk1hbGZvcm1lZCBvciBhbWJpZ3VvdXMgY2FwYWJpbGl0eSBvcGVyYXRpb24gZ3JhcGguXCIsIG1vZHVsZS5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIG9wZXJhdGlvbklkcy5hZGQob3BlcmF0aW9uLmlkKVxuICAgICAgb3BlcmF0aW9uTmFtZXMuYWRkKG9wZXJhdGlvbi5uYW1lKVxuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgW1xuICAgIC4uLm1vZHVsZS5mdW5jdGlvbnMsXG4gICAgLi4uKG1vZHVsZS5yZWNvcmRzID8/IFtdKSxcbiAgICAuLi4obW9kdWxlLmNsYXNzZXMgPz8gW10pLFxuICAgIC4uLihtb2R1bGUuZXJyb3JzID8/IFtdKVxuICBdKSB7XG4gICAgaWYgKHBhcnNlUHJvdGVjdGVkRW50cnlOYW1lKGRlY2xhcmF0aW9uLm5hbWUpICE9PSBudWxsKSB7XG4gICAgICBmYWlsKFwiU1RETElCX1BST1RFQ1RFRF9CSU5ESU5HX0FDQ0VTU1wiLFxuICAgICAgICBgU291cmNlIGRlY2xhcmF0aW9uICcke2RlY2xhcmF0aW9uLm5hbWV9JyBjYXB0dXJlcyBhIHJlc2VydmVkIHByb3RlY3RlZCBwcm92aWRlciBiaW5kaW5nLmAsIGRlY2xhcmF0aW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgfVxuXG4gIGZvckVhY2hFeHByZXNzaW9uKG1vZHVsZSwgKGV4cHJlc3Npb24pID0+IHtcbiAgICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiRWZmZWN0Q2FsbEV4cHJlc3Npb25cIikge1xuICAgICAgY29uc3QgY2FwYWJpbGl0eSA9IGNhcGFiaWxpdGllcy5maW5kKCh7aWR9KSA9PiBpZCA9PSBleHByZXNzaW9uLnJlc29sdXRpb24/LmNhcGFiaWxpdHlJZClcbiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IGNhcGFiaWxpdHk/Lm9wZXJhdGlvbnMuZmluZCgoe2lkfSkgPT4gaWQgPT0gZXhwcmVzc2lvbi5vcGVyYXRpb24pXG5cbiAgICAgIGlmIChvcGVyYXRpb24gJiYgZXhwcmVzc2lvbi5yZXNvbHV0aW9uLm9wZXJhdGlvbklkID09IG9wZXJhdGlvbi5pZCAmJlxuICAgICAgICAoIUFycmF5LmlzQXJyYXkoZXhwcmVzc2lvbi5yZXNvbHV0aW9uLmZhaWx1cmVJZHMpIHx8XG4gICAgICAgICAgZXhwcmVzc2lvbi5yZXNvbHV0aW9uLmZhaWx1cmVJZHMuam9pbihcIixcIikgIT0gb3BlcmF0aW9uLmZhaWx1cmVJZHMuam9pbihcIixcIikpKSB7XG4gICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0ZBSUxVUkVcIiwgXCJVTkRFQ0xBUkVEX0ZBSUxVUkU6IEVmZmVjdCBjYWxsIGZhaWx1cmUgYm91bmRhcnkgZG9lcyBub3QgbWF0Y2ggaXRzIGNvbXBpbGVyIGF1dGhvcml0eS5cIixcbiAgICAgICAgICBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgfVxuICAgICAgaWYgKCFvcGVyYXRpb24gfHwgZXhwcmVzc2lvbi5yZXNvbHV0aW9uLm9wZXJhdGlvbklkICE9IG9wZXJhdGlvbi5pZCB8fFxuICAgICAgICBKU09OLnN0cmluZ2lmeShleHByZXNzaW9uLnJlc29sdXRpb24pICE9IEpTT04uc3RyaW5naWZ5KHNpZ25hdHVyZSgvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRWZmZWN0Q2FwYWJpbGl0eURlY2xhcmF0aW9ufSAqLyAoY2FwYWJpbGl0eSksIG9wZXJhdGlvbikpKSB7XG4gICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0VGRkVDVFwiLCBcIkVmZmVjdCBjYWxsIHJlc29sdXRpb24gZG9lcyBub3QgbWF0Y2ggaXRzIGNvbXBpbGVyIGF1dGhvcml0eS5cIiwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiAmJiBwYXJzZVByb3RlY3RlZEVudHJ5TmFtZShleHByZXNzaW9uLm5hbWUpICE9PSBudWxsKSB7XG4gICAgICBmYWlsKFwiU1RETElCX1BST1RFQ1RFRF9CSU5ESU5HX0FDQ0VTU1wiLFxuICAgICAgICBgUmVmZXJlbmNlIHRvIHByb3RlY3RlZCBwcm92aWRlciBlbnRyeSAnJHtleHByZXNzaW9uLm5hbWV9JyBpcyBub3QgcG9ydGFibGUgY29kZS5gLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICBpZiAoZXhwcmVzc2lvbi5raW5kICE9IFwiQ2FsbEV4cHJlc3Npb25cIikgcmV0dXJuXG4gICAgaWYgKGZ1bmN0aW9ucy5oYXMoZXhwcmVzc2lvbi5jYWxsZWUpKSByZXR1cm5cbiAgICBsZXQgb3BlcmF0aW9uTmFtZSA9IGV4cHJlc3Npb24uY2FsbGVlXG4gICAgY29uc3QgcHJvdGVjdGVkRW50cnkgPSBwYXJzZVByb3RlY3RlZEVudHJ5TmFtZShleHByZXNzaW9uLmNhbGxlZSlcblxuICAgIGlmIChwcm90ZWN0ZWRFbnRyeSAhPT0gbnVsbCkge1xuICAgICAgaWYgKGNhcGFiaWxpdGllcy5sZW5ndGggPT0gMCkge1xuICAgICAgICBmYWlsKFwiU1RETElCX1BST1RFQ1RFRF9CSU5ESU5HX0FDQ0VTU1wiLFxuICAgICAgICAgIGBQcm90ZWN0ZWQgcHJvdmlkZXIgZW50cnkgJyR7ZXhwcmVzc2lvbi5jYWxsZWV9JyByZXF1aXJlcyBhbiBleHBsaWNpdCBjYXBhYmlsaXR5IGF1dGhvcml0eS5gLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgfVxuICAgICAgaWYgKHByb3RlY3RlZEVudHJ5LnRhcmdldCAhPSBsYW5ndWFnZSkge1xuICAgICAgICBmYWlsKFwiU1RETElCX1BST1RFQ1RFRF9CSU5ESU5HX0FDQ0VTU1wiLFxuICAgICAgICAgIGBQcm90ZWN0ZWQgcHJvdmlkZXIgZW50cnkgdGFyZ2V0ICcke3Byb3RlY3RlZEVudHJ5LnRhcmdldH0nIGRvZXMgbm90IG1hdGNoIHNvdXJjZSBsYW5ndWFnZSAnJHtsYW5ndWFnZX0nLmAsXG4gICAgICAgICAgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIG9wZXJhdGlvbk5hbWUgPSBwcm90ZWN0ZWRFbnRyeS5vcGVyYXRpb25cbiAgICB9XG4gICAgY29uc3QgbWF0Y2ggPSBhdXRob3JpemVkT3BlcmF0aW9uKGNhcGFiaWxpdGllcywgb3BlcmF0aW9uTmFtZSlcblxuICAgIGlmICghbWF0Y2gpIHtcbiAgICAgIGlmIChwcm90ZWN0ZWRFbnRyeSAhPT0gbnVsbCkge1xuICAgICAgICBmYWlsKFwiU1RETElCX1BST1RFQ1RFRF9CSU5ESU5HX0FDQ0VTU1wiLFxuICAgICAgICAgIGBQcm90ZWN0ZWQgcHJvdmlkZXIgZW50cnkgZm9yIHVuZGVjbGFyZWQgb3BlcmF0aW9uICcke29wZXJhdGlvbk5hbWV9JyBoYXMgbm8gYXV0aG9yaXplZCBjYXBhYmlsaXR5IG9wZXJhdGlvbi5gLFxuICAgICAgICAgIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBpZiAoaXNUYXNrMDM0T3BlcmF0aW9uTmFtZShvcGVyYXRpb25OYW1lKSkge1xuICAgICAgICBmYWlsKFwiTUlTU0lOR19DQVBBQklMSVRZX0FVVEhPUklUWVwiLCBgT3BlcmF0aW9uICcke29wZXJhdGlvbk5hbWV9JyByZXF1aXJlcyBleHBsaWNpdCBjb21waWxlciBhdXRob3JpdHkuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoIW5vcm1hbGl6ZSkge1xuICAgICAgZmFpbChcIlVOREVDTEFSRURfRUZGRUNUXCIsIGBDYWxsZXItYXV0aG9yZWQgb3JkaW5hcnkgY2FsbCAnJHtleHByZXNzaW9uLmNhbGxlZX0nIGNhbm5vdCBmb3JnZSBhIGNhcGFiaWxpdHkgb3BlcmF0aW9uLmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgfVxuICAgIGNvbnN0IHtjYXBhYmlsaXR5LCBvcGVyYXRpb259ID0gbWF0Y2hcbiAgICBjb25zdCBmbG93ID0gb3BlcmF0aW9uLnJlc291cmNlRmxvd1xuXG4gICAgaWYgKChmbG93LmtpbmQgPT0gXCJib3Jyb3dcIiB8fCBmbG93LmtpbmQgPT0gXCJjbG9zZVwiKSAmJiBleHByZXNzaW9uLmFyZ3VtZW50c1tmbG93LnBhcmFtZXRlckluZGV4XSkge1xuICAgICAgY29uc3QgYXJndW1lbnQgPSBleHByZXNzaW9uLmFyZ3VtZW50c1tmbG93LnBhcmFtZXRlckluZGV4XVxuICAgICAgaWYgKGFyZ3VtZW50LmtpbmQgIT0gXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiICYmIGFyZ3VtZW50LmtpbmQgIT0gXCJQcml2YXRlRmllbGRSZWFkXCIgJiYgYXJndW1lbnQua2luZCAhPSBcIlJlY2VpdmVyRXhwcmVzc2lvblwiKSB7XG4gICAgICAgIGZhaWwoXCJJTlZBTElEX1JFU09VUkNFX0JPUlJPV1wiLCBcIkFuIG93bmVkIGJvcnJvdyBtdXN0IG5hbWUgb25lIGltbWVkaWF0ZSByZXNvdXJjZSBwbGFjZS5cIiwgYXJndW1lbnQubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBleHByZXNzaW9uLmFyZ3VtZW50c1tmbG93LnBhcmFtZXRlckluZGV4XSA9IHtcbiAgICAgICAgZXhwcmVzc2lvbjogYXJndW1lbnQsXG4gICAgICAgIGtpbmQ6IFwiT3duZWRCb3Jyb3dFeHByZXNzaW9uXCIsXG4gICAgICAgIGxvY2F0aW9uOiBhcmd1bWVudC5sb2NhdGlvbixcbiAgICAgICAgbW9kZTogZmxvdy5raW5kID09IFwiY2xvc2VcIiA/IFwiZXhjbHVzaXZlXCIgOiBcInNoYXJlZFwiLFxuICAgICAgICBzb3VyY2VQcm92ZW5hbmNlOiBhcmd1bWVudC5zb3VyY2VQcm92ZW5hbmNlLFxuICAgICAgICB0eXBlOiAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuT3duZWRSZXNvdXJjZVR5cGUgfCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLk93bmVkUmVmZXJlbmNlVHlwZX0gKi8gKFxuICAgICAgICAgIG9wZXJhdGlvbi5wYXJhbWV0ZXJzW2Zsb3cucGFyYW1ldGVySW5kZXhdLnR5cGVcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCByZXBsYWNlbWVudCA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FZmZlY3RDYWxsRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKGV4cHJlc3Npb24pKVxuICAgIGRlbGV0ZSAvKiogQHR5cGUge3tjYWxsZWU/OiBzdHJpbmd9fSAqLyAocmVwbGFjZW1lbnQpLmNhbGxlZVxuICAgIHJlcGxhY2VtZW50LmtpbmQgPSBcIkVmZmVjdENhbGxFeHByZXNzaW9uXCJcbiAgICByZXBsYWNlbWVudC5vcGVyYXRpb24gPSBvcGVyYXRpb24uaWRcbiAgICByZXBsYWNlbWVudC5yZXNvbHV0aW9uID0gc2lnbmF0dXJlKGNhcGFiaWxpdHksIG9wZXJhdGlvbilcbiAgfSlcblxuICBjb25zdCBjb21wbGV0ZSA9IGNvbXBsZXRlRWZmZWN0U3VtbWFyaWVzKG1vZHVsZSwgZmFpbHVyZUlkcywgdmlzaWJsZUNsYXNzZXMpXG4gIGNvbnN0IHN1bW1hcmllcyA9IGNvbXBsZXRlLmZ1bmN0aW9uc1xuICBjb25zdCBtZXRob2RTdW1tYXJpZXMgPSBjb21wbGV0ZS5tZXRob2RzXG4gIGNvbnN0IGNvbnN0cnVjdG9yU3VtbWFyaWVzID0gY29tcGxldGUuY29uc3RydWN0b3JzXG5cbiAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBtb2R1bGUuY2xhc3NlcyA/PyBbXSkge1xuICAgIGFwcGx5RGVjbGFyYXRpb25TdW1tYXJ5KGRlY2xhcmF0aW9uLmNvbnN0cnVjdG9yLFxuICAgICAgY29uc3RydWN0b3JTdW1tYXJpZXMuZ2V0KC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZGVjbGFyYXRpb24uY29uc3RydWN0b3IuaWQpKSwgbm9ybWFsaXplLCBmYWlsKVxuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIGRlY2xhcmF0aW9uLm1ldGhvZHMpIHtcbiAgICAgIGFwcGx5RGVjbGFyYXRpb25TdW1tYXJ5KG1ldGhvZCwgbWV0aG9kU3VtbWFyaWVzLmdldCgvKiogQHR5cGUge3N0cmluZ30gKi8gKG1ldGhvZC5pZCkpLCBub3JtYWxpemUsIGZhaWwpXG4gICAgfVxuICB9XG4gIGxldCBzaXRlID0gMFxuXG4gIGZvckVhY2hFeHByZXNzaW9uKG1vZHVsZSwgKGV4cHJlc3Npb24pID0+IHtcbiAgICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiRWZmZWN0Q2FsbEV4cHJlc3Npb25cIikge1xuICAgICAgaWYgKG5vcm1hbGl6ZSkgZXhwcmVzc2lvbi5lZmZlY3RTaXRlSWQgPSBgZWZmZWN0OiR7c2l0ZX1gXG4gICAgICBlbHNlIHZhbGlkYXRlU2l0ZShleHByZXNzaW9uLCBzaXRlLCBmYWlsKVxuICAgICAgc2l0ZSArPSAxXG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkNhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgIGNvbnN0IHN1bW1hcnkgPSBzdW1tYXJpZXMuZ2V0KGV4cHJlc3Npb24uY2FsbGVlKVxuICAgICAgaWYgKCFzdW1tYXJ5Py5ob3N0KSB7XG4gICAgICAgIGlmIChub3JtYWxpemUpIHtcbiAgICAgICAgICBkZWxldGUgZXhwcmVzc2lvbi5lZmZlY3RTaXRlSWRcbiAgICAgICAgICBkZWxldGUgZXhwcmVzc2lvbi5lZmZlY3RzXG4gICAgICAgICAgZGVsZXRlIGV4cHJlc3Npb24uZmFpbHVyZUlkc1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9ybWFsaXplICYmIEFycmF5LmlzQXJyYXkoZXhwcmVzc2lvbi5mYWlsdXJlSWRzKSAmJiBleHByZXNzaW9uLmZhaWx1cmVJZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0ZBSUxVUkVcIiwgXCJVTkRFQ0xBUkVEX0ZBSUxVUkU6IFB1cmUgY2FsbCBjYXJyaWVzIGEgZm9yZ2VkIHR5cGVkIGZhaWx1cmUgYm91bmRhcnkuXCIsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFub3JtYWxpemUgJiYgKGV4cHJlc3Npb24uZWZmZWN0U2l0ZUlkICE9PSB1bmRlZmluZWQgfHwgZXhwcmVzc2lvbi5lZmZlY3RzICE9PSB1bmRlZmluZWQgfHwgZXhwcmVzc2lvbi5mYWlsdXJlSWRzICE9PSB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgZmFpbChcIlVOREVDTEFSRURfRUZGRUNUXCIsIFwiUHVyZSBjYWxsIGNhcnJpZXMgZm9yZ2VkIGVmZmVjdCBtZXRhZGF0YS5cIiwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgICAgfVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGlmIChub3JtYWxpemUpIHtcbiAgICAgICAgZXhwcmVzc2lvbi5lZmZlY3RTaXRlSWQgPSBgZWZmZWN0OiR7c2l0ZX1gXG4gICAgICAgIGV4cHJlc3Npb24uZWZmZWN0cyA9IFtcImhvc3RcIl1cbiAgICAgICAgZXhwcmVzc2lvbi5mYWlsdXJlSWRzID0gWy4uLnN1bW1hcnkuZmFpbHVyZUlkc11cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbGlkYXRlU2l0ZShleHByZXNzaW9uLCBzaXRlLCBmYWlsKVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZXhwcmVzc2lvbi5mYWlsdXJlSWRzKSB8fCBleHByZXNzaW9uLmZhaWx1cmVJZHMuam9pbihcIixcIikgIT0gWy4uLnN1bW1hcnkuZmFpbHVyZUlkc10uam9pbihcIixcIikpIHtcbiAgICAgICAgICBmYWlsKFwiVU5ERUNMQVJFRF9GQUlMVVJFXCIsIFwiVU5ERUNMQVJFRF9GQUlMVVJFOiBDYWxsIGZhaWx1cmUgYm91bmRhcnkgZG9lcyBub3QgbWF0Y2ggaXRzIHJlc29sdmVkIGZ1bmN0aW9uLlwiLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgICB9XG4gICAgICAgIGlmIChleHByZXNzaW9uLmVmZmVjdHM/Lmxlbmd0aCAhPSAxIHx8IGV4cHJlc3Npb24uZWZmZWN0c1swXSAhPSBcImhvc3RcIikge1xuICAgICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0VGRkVDVFwiLCBcIkNhbGwgZWZmZWN0IHN1bW1hcnkgZG9lcyBub3QgbWF0Y2ggaXRzIHJlc29sdmVkIGZ1bmN0aW9uLlwiLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzaXRlICs9IDFcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTWV0aG9kQ2FsbEV4cHJlc3Npb25cIiB8fCBleHByZXNzaW9uLmtpbmQgPT0gXCJSZWZlcmVuY2VDb25zdHJ1Y3Rpb25cIikge1xuICAgICAgY29uc3Qgc3VtbWFyeSA9IGV4cHJlc3Npb24ua2luZCA9PSBcIk1ldGhvZENhbGxFeHByZXNzaW9uXCJcbiAgICAgICAgPyBtZXRob2RTdW1tYXJpZXMuZ2V0KGV4cHJlc3Npb24ubWV0aG9kKVxuICAgICAgICA6IGNvbnN0cnVjdG9yU3VtbWFyaWVzLmdldChleHByZXNzaW9uLnJlc29sdXRpb24/LmRlY2xhcmF0aW9uSWQgPz8gYCR7ZXhwcmVzc2lvbi5yZWZlcmVuY2UuZGVjbGFyYXRpb25JZH06Y29uc3RydWN0b3JgKVxuICAgICAgY29uc3QgbGFiZWwgPSBleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiID8gXCJtZXRob2QgY2FsbFwiIDogXCJjb25zdHJ1Y3Rpb25cIlxuICAgICAgaWYgKCFzdW1tYXJ5Py5ob3N0KSB7XG4gICAgICAgIGlmIChub3JtYWxpemUpIHtcbiAgICAgICAgICBkZWxldGUgZXhwcmVzc2lvbi5lZmZlY3RTaXRlSWRcbiAgICAgICAgICBkZWxldGUgZXhwcmVzc2lvbi5lZmZlY3RzXG4gICAgICAgICAgZGVsZXRlIGV4cHJlc3Npb24uZmFpbHVyZUlkc1xuICAgICAgICB9XG4gICAgICAgIGlmICghbm9ybWFsaXplICYmIEFycmF5LmlzQXJyYXkoZXhwcmVzc2lvbi5mYWlsdXJlSWRzKSAmJiBleHByZXNzaW9uLmZhaWx1cmVJZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0ZBSUxVUkVcIiwgYFVOREVDTEFSRURfRkFJTFVSRTogUHVyZSAke2xhYmVsfSBjYXJyaWVzIGEgZm9yZ2VkIHR5cGVkIGZhaWx1cmUgYm91bmRhcnkuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgICAgfVxuICAgICAgICBpZiAoIW5vcm1hbGl6ZSAmJiAoZXhwcmVzc2lvbi5lZmZlY3RTaXRlSWQgIT09IHVuZGVmaW5lZCB8fCBleHByZXNzaW9uLmVmZmVjdHMgIT09IHVuZGVmaW5lZCB8fCBleHByZXNzaW9uLmZhaWx1cmVJZHMgIT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgICBmYWlsKFwiVU5ERUNMQVJFRF9FRkZFQ1RcIiwgYFB1cmUgJHtsYWJlbH0gY2FycmllcyBmb3JnZWQgZWZmZWN0IG1ldGFkYXRhLmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBpZiAobm9ybWFsaXplKSB7XG4gICAgICAgIGV4cHJlc3Npb24uZWZmZWN0U2l0ZUlkID0gYGVmZmVjdDoke3NpdGV9YFxuICAgICAgICBleHByZXNzaW9uLmVmZmVjdHMgPSBbXCJob3N0XCJdXG4gICAgICAgIGV4cHJlc3Npb24uZmFpbHVyZUlkcyA9IFsuLi5zdW1tYXJ5LmZhaWx1cmVJZHNdXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWxpZGF0ZVNpdGUoZXhwcmVzc2lvbiwgc2l0ZSwgZmFpbClcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGV4cHJlc3Npb24uZmFpbHVyZUlkcykgfHwgZXhwcmVzc2lvbi5mYWlsdXJlSWRzLmpvaW4oXCIsXCIpICE9IFsuLi5zdW1tYXJ5LmZhaWx1cmVJZHNdLmpvaW4oXCIsXCIpKSB7XG4gICAgICAgICAgZmFpbChcIlVOREVDTEFSRURfRkFJTFVSRVwiLCBgVU5ERUNMQVJFRF9GQUlMVVJFOiAke2xhYmVsfSBmYWlsdXJlIGJvdW5kYXJ5IGRvZXMgbm90IG1hdGNoIGl0cyByZXNvbHZlZCBkZWNsYXJhdGlvbi5gLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgICB9XG4gICAgICAgIGlmIChleHByZXNzaW9uLmVmZmVjdHM/Lmxlbmd0aCAhPSAxIHx8IGV4cHJlc3Npb24uZWZmZWN0c1swXSAhPSBcImhvc3RcIikge1xuICAgICAgICAgIGZhaWwoXCJVTkRFQ0xBUkVEX0VGRkVDVFwiLCBgJHtsYWJlbH0gZWZmZWN0IHN1bW1hcnkgZG9lcyBub3QgbWF0Y2ggaXRzIHJlc29sdmVkIGRlY2xhcmF0aW9uLmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNpdGUgKz0gMVxuICAgIH1cbiAgfSwgdHJ1ZSlcbn1cblxuLyoqXG4gKiBDb21wdXRlcyB0aGUgam9pbnQgZmluaXRlIGZpeGVkIHBvaW50IGFjcm9zcyBmdW5jdGlvbnMgYW5kIHJlc29sdmVkIHJlY2VpdmVyIG1ldGhvZHMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFJlc29sdmVkIG1vZHVsZS5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IGNhcGFiaWxpdHlGYWlsdXJlSWRzIC0gRGVjbGFyZWQgY2FwYWJpbGl0eSBmYWlsdXJlcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5DbGFzc0RlY2xhcmF0aW9uPn0gdmlzaWJsZUNsYXNzZXMgLSBSZXNvbHZlZCByZWZlcmVuY2UgY2xhc3Nlcy5cbiAqIEByZXR1cm5zIHt7Y29uc3RydWN0b3JzOiBNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5PiwgZnVuY3Rpb25zOiBNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5PiwgbWV0aG9kczogTWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59fSBDb21wbGV0ZSBzdW1tYXJpZXMuXG4gKi9cbmZ1bmN0aW9uIGNvbXBsZXRlRWZmZWN0U3VtbWFyaWVzKG1vZHVsZSwgY2FwYWJpbGl0eUZhaWx1cmVJZHMsIHZpc2libGVDbGFzc2VzKSB7XG4gIGNvbnN0IGltcG9ydGVkTWV0aG9kcyA9IGRlY2xhcmVkQ2xhc3NTdW1tYXJpZXModmlzaWJsZUNsYXNzZXMsIFwibWV0aG9kc1wiKVxuICBsZXQgZnVuY3Rpb25zID0gZWZmZWN0U3VtbWFyaWVzKG1vZHVsZS5mdW5jdGlvbnMsIG5ldyBNYXAoKSwgY2FwYWJpbGl0eUZhaWx1cmVJZHMpXG4gIGxldCBtZXRob2RzID0gZGlyZWN0TWV0aG9kU3VtbWFyaWVzKG1vZHVsZSwgZnVuY3Rpb25zLCBpbXBvcnRlZE1ldGhvZHMsIGNhcGFiaWxpdHlGYWlsdXJlSWRzLCBpbXBvcnRlZE1ldGhvZHMpXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBjb25zdCBuZXh0RnVuY3Rpb25zID0gZWZmZWN0U3VtbWFyaWVzKG1vZHVsZS5mdW5jdGlvbnMsIG1ldGhvZHMsIGNhcGFiaWxpdHlGYWlsdXJlSWRzKVxuICAgIGNvbnN0IG5leHRNZXRob2RzID0gZGlyZWN0TWV0aG9kU3VtbWFyaWVzKG1vZHVsZSwgbmV4dEZ1bmN0aW9ucywgbWV0aG9kcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMsIGltcG9ydGVkTWV0aG9kcylcblxuICAgIGlmIChzYW1lU3VtbWFyaWVzKGZ1bmN0aW9ucywgbmV4dEZ1bmN0aW9ucykgJiYgc2FtZVN1bW1hcmllcyhtZXRob2RzLCBuZXh0TWV0aG9kcykpIHtcbiAgICAgIHJldHVybiB7Y29uc3RydWN0b3JzOiBkaXJlY3RDb25zdHJ1Y3RvclN1bW1hcmllcyhtb2R1bGUsIG5leHRGdW5jdGlvbnMsIG5leHRNZXRob2RzLCBjYXBhYmlsaXR5RmFpbHVyZUlkcyxcbiAgICAgICAgZGVjbGFyZWRDbGFzc1N1bW1hcmllcyh2aXNpYmxlQ2xhc3NlcywgXCJjb25zdHJ1Y3RvcnNcIikpLCBmdW5jdGlvbnM6IG5leHRGdW5jdGlvbnMsIG1ldGhvZHM6IG5leHRNZXRob2RzfVxuICAgIH1cbiAgICBmdW5jdGlvbnMgPSBuZXh0RnVuY3Rpb25zXG4gICAgbWV0aG9kcyA9IG5leHRNZXRob2RzXG4gIH1cbn1cblxuLyoqXG4gKiBDb21wYXJlcyBzdGFibGUgaG9zdC9mYWlsdXJlIHN1bW1hcnkgbWFwcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59IGxlZnQgLSBQcmV2aW91cyBzdW1tYXJpZXMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSByaWdodCAtIE5leHQgc3VtbWFyaWVzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHN1bW1hcmllcyBhcmUgaWRlbnRpY2FsLlxuICovXG5mdW5jdGlvbiBzYW1lU3VtbWFyaWVzKGxlZnQsIHJpZ2h0KSB7XG4gIGlmIChsZWZ0LnNpemUgIT0gcmlnaHQuc2l6ZSkgcmV0dXJuIGZhbHNlXG4gIGZvciAoY29uc3QgW25hbWUsIHN1bW1hcnldIG9mIGxlZnQpIHtcbiAgICBjb25zdCBjYW5kaWRhdGUgPSByaWdodC5nZXQobmFtZSlcblxuICAgIGlmICghY2FuZGlkYXRlIHx8IHN1bW1hcnkuaG9zdCAhPSBjYW5kaWRhdGUuaG9zdCB8fCBzdW1tYXJ5LmZhaWx1cmVJZHMuc2l6ZSAhPSBjYW5kaWRhdGUuZmFpbHVyZUlkcy5zaXplIHx8XG4gICAgICBbLi4uc3VtbWFyeS5mYWlsdXJlSWRzXS5zb21lKChpZCkgPT4gIWNhbmRpZGF0ZS5mYWlsdXJlSWRzLmhhcyhpZCkpKSByZXR1cm4gZmFsc2VcbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG4vKipcbiAqIEJ1aWxkcyB0aGUgY29tcGxldGUgaW1tdXRhYmxlIHJlc29sdXRpb24gcmVjb3JkZWQgYXQgYW4gZWZmZWN0IGNhbGwgc2l0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FZmZlY3RDYXBhYmlsaXR5RGVjbGFyYXRpb259IGNhcGFiaWxpdHkgLSBEZWNsYXJpbmcgY2FwYWJpbGl0eS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FZmZlY3RPcGVyYXRpb25EZWNsYXJhdGlvbn0gb3BlcmF0aW9uIC0gUmVzb2x2ZWQgb3BlcmF0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVzb2x2ZWRFZmZlY3RPcGVyYXRpb25TaWduYXR1cmV9IENvbXBsZXRlIHJlc29sdXRpb24uXG4gKi9cbmZ1bmN0aW9uIHNpZ25hdHVyZShjYXBhYmlsaXR5LCBvcGVyYXRpb24pIHtcbiAgcmV0dXJuIHtcbiAgICBjYXBhYmlsaXR5SWQ6IGNhcGFiaWxpdHkuaWQsXG4gICAgZWZmZWN0czogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFtcImhvc3RcIl0pLFxuICAgIGZhaWx1cmVJZHM6IFsuLi5vcGVyYXRpb24uZmFpbHVyZUlkc10sXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVzb2x2ZWRFZmZlY3RPcGVyYXRpb25TaWduYXR1cmVcIiksXG4gICAgb3BlcmF0aW9uSWQ6IG9wZXJhdGlvbi5pZCxcbiAgICBwYXJhbWV0ZXJUeXBlczogb3BlcmF0aW9uLnBhcmFtZXRlcnMubWFwKCh7dHlwZX0pID0+IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVJZGVudGl0eX0gKi8gKHR5cGVJZGVudGl0eSh0eXBlKSkpLFxuICAgIHJlc291cmNlRmxvdzogc3RydWN0dXJlZENsb25lKG9wZXJhdGlvbi5yZXNvdXJjZUZsb3cpLFxuICAgIHJldHVyblR5cGU6IHR5cGVJZGVudGl0eShvcGVyYXRpb24ucmV0dXJuVHlwZSlcbiAgfVxufVxuXG4vKipcbiAqIFJlbW92ZXMgbG9jYXRpb25zIGFuZCBwcm92ZW5hbmNlIGZyb20gb25lIHJlc29sdmVkIHR5cGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNGdW5jdGlvblJldHVyblR5cGV9IHR5cGUgLSBTZW1hbnRpYyB0eXBlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRnVuY3Rpb25SZXR1cm5UeXBlSWRlbnRpdHl9IFN0YWJsZSB0eXBlIGlkZW50aXR5LlxuICovXG5mdW5jdGlvbiB0eXBlSWRlbnRpdHkodHlwZSkge1xuICBpZiAodHlwZS5raW5kID09IFwiVHlwZVJlZmVyZW5jZVwiKSByZXR1cm4gdHlwZS5uYW1lXG4gIGlmICh0eXBlLmtpbmQgPT0gXCJPd25lZFJlc291cmNlVHlwZVwiKSByZXR1cm4ge2tpbmQ6IHR5cGUua2luZCwgcmVzb3VyY2VJZDogdHlwZS5yZXNvdXJjZUlkfVxuICBpZiAodHlwZS5raW5kID09IFwiT3duZWRSZWZlcmVuY2VUeXBlXCIpIHJldHVybiB7ZGVjbGFyYXRpb25JZDogdHlwZS5kZWNsYXJhdGlvbklkLCBraW5kOiB0eXBlLmtpbmR9XG4gIGlmICh0eXBlLmtpbmQgPT0gXCJPcHRpb25hbFR5cGVcIikgcmV0dXJuIHtraW5kOiB0eXBlLmtpbmQsXG4gICAgdmFsdWVUeXBlOiAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlSWRlbnRpdHl9ICovICh0eXBlSWRlbnRpdHkodHlwZS52YWx1ZVR5cGUpKX1cbiAgaWYgKHR5cGUua2luZCA9PSBcIkxpc3RUeXBlXCIpIHJldHVybiB7XG4gICAgZWxlbWVudFR5cGU6IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVJZGVudGl0eX0gKi8gKHR5cGVJZGVudGl0eSh0eXBlLmVsZW1lbnRUeXBlKSksIGtpbmQ6IHR5cGUua2luZH1cbiAgaWYgKHR5cGUua2luZCA9PSBcIk1hcFR5cGVcIiB8fCB0eXBlLmtpbmQgPT0gXCJPcmRlcmVkTWFwVHlwZVwiKSB7XG4gICAgY29uc3Qga2V5VHlwZSA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVJZGVudGl0eX0gKi8gKHR5cGVJZGVudGl0eSh0eXBlLmtleVR5cGUpKVxuICAgIGNvbnN0IHZhbHVlVHlwZSA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVJZGVudGl0eX0gKi8gKHR5cGVJZGVudGl0eSh0eXBlLnZhbHVlVHlwZSkpXG5cbiAgICByZXR1cm4gdHlwZS5raW5kID09IFwiT3JkZXJlZE1hcFR5cGVcIiA/IHtrZXlUeXBlLCBraW5kOiB0eXBlLmtpbmQsIG9yZGVyOiBcImluc2VydGlvblwiLCB2YWx1ZVR5cGV9IDpcbiAgICAgIHtrZXlUeXBlLCBraW5kOiB0eXBlLmtpbmQsIHZhbHVlVHlwZX1cbiAgfVxuICBpZiAodHlwZS5raW5kID09IFwiUmVjb3JkVHlwZVwiKSByZXR1cm4ge2FyZ3VtZW50czogdHlwZS5hcmd1bWVudHM/Lm1hcCgoYXJndW1lbnQpID0+XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZUlkZW50aXR5fSAqLyAodHlwZUlkZW50aXR5KGFyZ3VtZW50KSkpLCBkZWNsYXJhdGlvbklkOiB0eXBlLmRlY2xhcmF0aW9uSWQsIGtpbmQ6IHR5cGUua2luZH1cbiAgaWYgKHR5cGUua2luZCA9PSBcIlJlZmVyZW5jZVR5cGVcIikgcmV0dXJuIHtkZWNsYXJhdGlvbklkOiB0eXBlLmRlY2xhcmF0aW9uSWQsIGtpbmQ6IHR5cGUua2luZH1cbiAgcmV0dXJuIHtraW5kOiB0eXBlLmtpbmQsIHBhcmFtZXRlcklkOiB0eXBlLnBhcmFtZXRlcklkfVxufVxuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBmaXhlZC1wb2ludCBob3N0LWVmZmVjdCBzdW1tYXJ5IGZvciBvcmRpbmFyeSBmdW5jdGlvbnMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbltdfSBmdW5jdGlvbnMgLSBNb2R1bGUgZnVuY3Rpb25zLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5Pn0gW21ldGhvZFN1bW1hcmllc10gLSBSZWNlaXZlci1jYWxsIHN1bW1hcmllcyBmcm9tIHRoZSBjdXJyZW50IGZpeGVkLXBvaW50IHJvdW5kLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gW2NhcGFiaWxpdHlGYWlsdXJlSWRzXSAtIENhcGFiaWxpdHkgZmFpbHVyZXMgZWxpZ2libGUgZm9yIGNhbGwtc2l0ZSBwcm9wYWdhdGlvbi5cbiAqIEByZXR1cm5zIHtNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5Pn0gU3VtbWFyaWVzIGJ5IHNvdXJjZSBmdW5jdGlvbiBuYW1lLlxuICovXG5mdW5jdGlvbiBlZmZlY3RTdW1tYXJpZXMoZnVuY3Rpb25zLCBtZXRob2RTdW1tYXJpZXMgPSBuZXcgTWFwKCksIGNhcGFiaWxpdHlGYWlsdXJlSWRzID0gbmV3IFNldCgpKSB7XG4gIGNvbnN0IHN1bW1hcmllcyA9IG5ldyBNYXAoZnVuY3Rpb25zLm1hcCgoe25hbWV9KSA9PiAvKiogQHR5cGUge1tzdHJpbmcsIEVmZmVjdFN1bW1hcnldfSAqLyAoXG4gICAgW25hbWUsIHtmYWlsdXJlSWRzOiBuZXcgU2V0KCksIGhvc3Q6IGZhbHNlfV1cbiAgKSkpXG4gIGxldCBjaGFuZ2VkID0gdHJ1ZVxuXG4gIHdoaWxlIChjaGFuZ2VkKSB7XG4gICAgY2hhbmdlZCA9IGZhbHNlXG4gICAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBmdW5jdGlvbnMpIHtcbiAgICAgIGNvbnN0IHN1bW1hcnkgPSBzdW1tYXJpZXMuZ2V0KGRlY2xhcmF0aW9uLm5hbWUpXG4gICAgICBpZiAoIXN1bW1hcnkpIGNvbnRpbnVlXG4gICAgICBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKGRlY2xhcmF0aW9uLmJvZHksIChleHByZXNzaW9uKSA9PiB7XG4gICAgICAgIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJFZmZlY3RDYWxsRXhwcmVzc2lvblwiKSB7XG4gICAgICAgICAgaWYgKCFzdW1tYXJ5Lmhvc3QpIHsgc3VtbWFyeS5ob3N0ID0gdHJ1ZTsgY2hhbmdlZCA9IHRydWUgfVxuICAgICAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkNhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgICAgICBjb25zdCBjYWxsZWQgPSBzdW1tYXJpZXMuZ2V0KGV4cHJlc3Npb24uY2FsbGVlKVxuICAgICAgICAgIGlmIChjYWxsZWQ/Lmhvc3QgJiYgIXN1bW1hcnkuaG9zdCkgeyBzdW1tYXJ5Lmhvc3QgPSB0cnVlOyBjaGFuZ2VkID0gdHJ1ZSB9XG4gICAgICAgIH0gZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTWV0aG9kQ2FsbEV4cHJlc3Npb25cIikge1xuICAgICAgICAgIGNvbnN0IGNhbGxlZCA9IG1ldGhvZFN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5tZXRob2QpXG4gICAgICAgICAgaWYgKGNhbGxlZD8uaG9zdCAmJiAhc3VtbWFyeS5ob3N0KSB7IHN1bW1hcnkuaG9zdCA9IHRydWU7IGNoYW5nZWQgPSB0cnVlIH1cbiAgICAgICAgfVxuICAgICAgfSwgZmFsc2UpXG4gICAgICBjb25zdCBlc2NhcGluZyA9IGVzY2FwaW5nQmxvY2tGYWlsdXJlcyhkZWNsYXJhdGlvbi5ib2R5LCBzdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMpXG5cbiAgICAgIGZvciAoY29uc3QgaWQgb2YgZXNjYXBpbmcpIGlmICghc3VtbWFyeS5mYWlsdXJlSWRzLmhhcyhpZCkpIHsgc3VtbWFyeS5mYWlsdXJlSWRzLmFkZChpZCk7IGNoYW5nZWQgPSB0cnVlIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN1bW1hcmllc1xufVxuXG4vKipcbiAqIENvbXB1dGVzIHRoZSBjYXBhYmlsaXR5IGZhaWx1cmVzIGVzY2FwaW5nIG9uZSBzdHJ1Y3R1cmVkIGJsb2NrLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJsb2NrfSBibG9jayAtIEZ1bmN0aW9uIGJvZHkuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBmdW5jdGlvblN1bW1hcmllcyAtIEN1cnJlbnQgZnVuY3Rpb24gZml4ZWQgcG9pbnQuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBtZXRob2RTdW1tYXJpZXMgLSBSZXNvbHZlZCBtZXRob2Qgc3VtbWFyaWVzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gY2FwYWJpbGl0eUZhaWx1cmVJZHMgLSBEZWNsYXJlZCBjYXBhYmlsaXR5IGZhaWx1cmVzLlxuICogQHJldHVybnMge1NldDxzdHJpbmc+fSBFc2NhcGluZyBmYWlsdXJlIGlkZW50aXRpZXMuXG4gKi9cbmZ1bmN0aW9uIGVzY2FwaW5nQmxvY2tGYWlsdXJlcyhibG9jaywgZnVuY3Rpb25TdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMpIHtcbiAgY29uc3QgcmVzdWx0ID0gbmV3IFNldCgpXG5cbiAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgYmxvY2suc3RhdGVtZW50cykge1xuICAgIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIlRyeVN0YXRlbWVudFwiKSB7XG4gICAgICBjb25zdCBib2R5ID0gZXNjYXBpbmdCbG9ja0ZhaWx1cmVzKHN0YXRlbWVudC5ib2R5LCBmdW5jdGlvblN1bW1hcmllcywgbWV0aG9kU3VtbWFyaWVzLCBjYXBhYmlsaXR5RmFpbHVyZUlkcylcblxuICAgICAgaWYgKGJvZHkuZGVsZXRlKHN0YXRlbWVudC5jYXRjaFR5cGUuZGVjbGFyYXRpb25JZCkpIHtcbiAgICAgICAgYWRkRmFpbHVyZXMocmVzdWx0LCBlc2NhcGluZ0Jsb2NrRmFpbHVyZXMoc3RhdGVtZW50LmNhdGNoQm9keSwgZnVuY3Rpb25TdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMpKVxuICAgICAgfVxuICAgICAgYWRkRmFpbHVyZXMocmVzdWx0LCBib2R5KVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgZm9yIChjb25zdCBleHByZXNzaW9uIG9mIHN0YXRlbWVudEV4cHJlc3Npb25zKHN0YXRlbWVudCkpIHtcbiAgICAgIGFkZEV4cHJlc3Npb25GYWlsdXJlcyhyZXN1bHQsIGV4cHJlc3Npb24sIGZ1bmN0aW9uU3VtbWFyaWVzLCBtZXRob2RTdW1tYXJpZXMpXG4gICAgfVxuICAgIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIlJhaXNlU3RhdGVtZW50XCIgJiYgY2FwYWJpbGl0eUZhaWx1cmVJZHMuaGFzKHN0YXRlbWVudC5lcnJvci5lcnJvci5kZWNsYXJhdGlvbklkKSkge1xuICAgICAgcmVzdWx0LmFkZChzdGF0ZW1lbnQuZXJyb3IuZXJyb3IuZGVjbGFyYXRpb25JZClcbiAgICB9XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBzdGF0ZW1lbnRCbG9ja3Moc3RhdGVtZW50KSkge1xuICAgICAgYWRkRmFpbHVyZXMocmVzdWx0LCBlc2NhcGluZ0Jsb2NrRmFpbHVyZXMoY2hpbGQsIGZ1bmN0aW9uU3VtbWFyaWVzLCBtZXRob2RTdW1tYXJpZXMsIGNhcGFiaWxpdHlGYWlsdXJlSWRzKSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vKipcbiAqIEFkZHMgZmFpbHVyZXMgZXZhbHVhdGVkIGJ5IG9uZSBleHByZXNzaW9uIHN1YnRyZWUuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSB0YXJnZXQgLSBEZXN0aW5hdGlvbiBpZGVudGl0aWVzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IGV4cHJlc3Npb24gLSBFeHByZXNzaW9uIHJvb3QuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBmdW5jdGlvblN1bW1hcmllcyAtIEZ1bmN0aW9uIHN1bW1hcmllcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59IG1ldGhvZFN1bW1hcmllcyAtIE1ldGhvZCBzdW1tYXJpZXMuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkRXhwcmVzc2lvbkZhaWx1cmVzKHRhcmdldCwgZXhwcmVzc2lvbiwgZnVuY3Rpb25TdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcykge1xuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiRWZmZWN0Q2FsbEV4cHJlc3Npb25cIikgYWRkRmFpbHVyZXModGFyZ2V0LCBleHByZXNzaW9uLnJlc29sdXRpb24uZmFpbHVyZUlkcylcbiAgZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ2FsbEV4cHJlc3Npb25cIikgYWRkRmFpbHVyZXModGFyZ2V0LCBmdW5jdGlvblN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpPy5mYWlsdXJlSWRzID8/IFtdKVxuICBlbHNlIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiKSBhZGRGYWlsdXJlcyh0YXJnZXQsIG1ldGhvZFN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5tZXRob2QpPy5mYWlsdXJlSWRzID8/IFtdKVxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGV4cHJlc3Npb25DaGlsZHJlbihleHByZXNzaW9uKSkgYWRkRXhwcmVzc2lvbkZhaWx1cmVzKHRhcmdldCwgY2hpbGQsIGZ1bmN0aW9uU3VtbWFyaWVzLCBtZXRob2RTdW1tYXJpZXMpXG59XG5cbi8qKlxuICogUmV0dXJucyBkaXJlY3RseSBldmFsdWF0ZWQgZXhwcmVzc2lvbnMgZm9yIG9uZSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU3RhdGVtZW50fSBzdGF0ZW1lbnQgLSBTdGF0ZW1lbnQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9uW119IEV4cHJlc3Npb24gcm9vdHMuXG4gKi9cbmZ1bmN0aW9uIHN0YXRlbWVudEV4cHJlc3Npb25zKHN0YXRlbWVudCkge1xuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpIHJldHVybiBbc3RhdGVtZW50LmluaXRpYWxpemVyXVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJBc3NpZ25tZW50U3RhdGVtZW50XCIgfHwgc3RhdGVtZW50LmtpbmQgPT0gXCJQcml2YXRlRmllbGRXcml0ZVN0YXRlbWVudFwiIHx8XG4gICAgc3RhdGVtZW50LmtpbmQgPT0gXCJFeHByZXNzaW9uU3RhdGVtZW50XCIgfHwgc3RhdGVtZW50LmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSByZXR1cm4gW3N0YXRlbWVudC5leHByZXNzaW9uXVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJSZXR1cm5TdGF0ZW1lbnRcIikgcmV0dXJuIHN0YXRlbWVudC5leHByZXNzaW9uID8gW3N0YXRlbWVudC5leHByZXNzaW9uXSA6IFtdXG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIlJhaXNlU3RhdGVtZW50XCIpIHJldHVybiBbc3RhdGVtZW50LmVycm9yLm1lc3NhZ2VdXG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIklmU3RhdGVtZW50XCIgfHwgc3RhdGVtZW50LmtpbmQgPT0gXCJXaGlsZVN0YXRlbWVudFwiKSByZXR1cm4gW3N0YXRlbWVudC5jb25kaXRpb25dXG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkZvckVhY2hTdGF0ZW1lbnRcIikgcmV0dXJuIFtzdGF0ZW1lbnQubGlzdF1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaE1hcFN0YXRlbWVudFwiKSByZXR1cm4gW3N0YXRlbWVudC5tYXBdXG4gIHJldHVybiBbXVxufVxuXG4vKipcbiAqIFJldHVybnMgbmVzdGVkIGJsb2NrcyB3aG9zZSBmYWlsdXJlcyBwcm9wYWdhdGUgdGhyb3VnaCBvbmUgc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlN0YXRlbWVudH0gc3RhdGVtZW50IC0gU3RhdGVtZW50LlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuQmxvY2tbXX0gQ2hpbGQgYmxvY2tzLlxuICovXG5mdW5jdGlvbiBzdGF0ZW1lbnRCbG9ja3Moc3RhdGVtZW50KSB7XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIklmU3RhdGVtZW50XCIpIHJldHVybiBbc3RhdGVtZW50LmNvbnNlcXVlbnQsIC4uLihzdGF0ZW1lbnQuYWx0ZXJuYXRlID8gW3N0YXRlbWVudC5hbHRlcm5hdGVdIDogW10pXVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJXaGlsZVN0YXRlbWVudFwiIHx8IHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaFN0YXRlbWVudFwiIHx8IHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaE1hcFN0YXRlbWVudFwiKSB7XG4gICAgcmV0dXJuIFtzdGF0ZW1lbnQuYm9keV1cbiAgfVxuICByZXR1cm4gW11cbn1cblxuLyoqXG4gKiBBZGRzIGFuIGl0ZXJhYmxlIG9mIGZhaWx1cmUgaWRlbnRpdGllcyB0byBhIHNldC5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IHRhcmdldCAtIERlc3RpbmF0aW9uLlxuICogQHBhcmFtIHtJdGVyYWJsZTxzdHJpbmc+fSBzb3VyY2UgLSBTb3VyY2UgaWRlbnRpdGllcy5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRGYWlsdXJlcyh0YXJnZXQsIHNvdXJjZSkge1xuICBmb3IgKGNvbnN0IGlkIG9mIHNvdXJjZSkgdGFyZ2V0LmFkZChpZClcbn1cblxuLyoqXG4gKiBDb21wdXRlcyBib3VuZGVkIGRpcmVjdCBzdW1tYXJpZXMgZm9yIGNsYXNzIG1ldGhvZHMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFJlc29sdmVkIG1vZHVsZS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59IGZ1bmN0aW9uU3VtbWFyaWVzIC0gT3JkaW5hcnkgZnVuY3Rpb24gc3VtbWFyaWVzLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5Pn0gcHJpb3JNZXRob2RTdW1tYXJpZXMgLSBSZWNlaXZlciBzdW1tYXJpZXMgZnJvbSB0aGUgcHJldmlvdXMgZml4ZWQtcG9pbnQgcm91bmQuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBjYXBhYmlsaXR5RmFpbHVyZUlkcyAtIERlY2xhcmVkIGNhcGFiaWxpdHkgZmFpbHVyZXMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBiYXNlU3VtbWFyaWVzIC0gSW1wb3J0ZWQgcmVjZWl2ZXIgc3VtbWFyaWVzLlxuICogQHJldHVybnMge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBTdW1tYXJpZXMgYnkgcmVzb2x2ZWQgbWV0aG9kIGlkZW50aXR5LlxuICovXG5mdW5jdGlvbiBkaXJlY3RNZXRob2RTdW1tYXJpZXMobW9kdWxlLCBmdW5jdGlvblN1bW1hcmllcywgcHJpb3JNZXRob2RTdW1tYXJpZXMsIGNhcGFiaWxpdHlGYWlsdXJlSWRzLCBiYXNlU3VtbWFyaWVzID0gbmV3IE1hcCgpKSB7XG4gIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59ICovXG4gIGNvbnN0IHN1bW1hcmllcyA9IG5ldyBNYXAoYmFzZVN1bW1hcmllcylcblxuICBmb3IgKGNvbnN0IGRlY2xhcmF0aW9uIG9mIG1vZHVsZS5jbGFzc2VzID8/IFtdKSB7XG4gICAgZm9yIChjb25zdCBtZXRob2Qgb2YgZGVjbGFyYXRpb24ubWV0aG9kcykge1xuICAgICAgLyoqIEB0eXBlIHtFZmZlY3RTdW1tYXJ5fSAqL1xuICAgICAgY29uc3Qgc3VtbWFyeSA9IHtmYWlsdXJlSWRzOiBlc2NhcGluZ0Jsb2NrRmFpbHVyZXMobWV0aG9kLmJvZHksIGZ1bmN0aW9uU3VtbWFyaWVzLCBwcmlvck1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMpLCBob3N0OiBmYWxzZX1cblxuICAgICAgZm9yRWFjaEJsb2NrRXhwcmVzc2lvbihtZXRob2QuYm9keSwgKGV4cHJlc3Npb24pID0+IHtcbiAgICAgICAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkVmZmVjdENhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgICAgICBzdW1tYXJ5Lmhvc3QgPSB0cnVlXG4gICAgICAgICAgY29uc3QgZmxvdyA9IGV4cHJlc3Npb24ucmVzb2x1dGlvbi5yZXNvdXJjZUZsb3dcbiAgICAgICAgICBjb25zdCBhcmd1bWVudCA9IGZsb3cua2luZCA9PSBcImJvcnJvd1wiIHx8IGZsb3cua2luZCA9PSBcImNsb3NlXCIgPyBleHByZXNzaW9uLmFyZ3VtZW50c1tmbG93LnBhcmFtZXRlckluZGV4XSA6IHVuZGVmaW5lZFxuICAgICAgICAgIGNvbnN0IGJvcnJvd2VkUGFyYW1ldGVyTmFtZSA9IGFyZ3VtZW50Py5raW5kID09IFwiT3duZWRCb3Jyb3dFeHByZXNzaW9uXCIgJiYgYXJndW1lbnQuZXhwcmVzc2lvbi5raW5kID09IFwiSWRlbnRpZmllckV4cHJlc3Npb25cIlxuICAgICAgICAgICAgPyBhcmd1bWVudC5leHByZXNzaW9uLm5hbWUgOiB1bmRlZmluZWRcbiAgICAgICAgICBjb25zdCBrbm93bk9wZW5Cb3Jyb3cgPSBkZWNsYXJhdGlvbi5vd25lcnNoaXA/LmtpbmQgPT0gXCJvd25lZFJlc291cmNlXCIgJiYgYXJndW1lbnQ/LmtpbmQgPT0gXCJPd25lZEJvcnJvd0V4cHJlc3Npb25cIiAmJiAoXG4gICAgICAgICAgICBhcmd1bWVudC5leHByZXNzaW9uLmtpbmQgPT0gXCJQcml2YXRlRmllbGRSZWFkXCIgJiYgYXJndW1lbnQuZXhwcmVzc2lvbi5maWVsZCA9PSBkZWNsYXJhdGlvbi5vd25lcnNoaXAuZmllbGRJZCB8fFxuICAgICAgICAgICAgYm9ycm93ZWRQYXJhbWV0ZXJOYW1lICE9PSB1bmRlZmluZWQgJiYgbWV0aG9kLnBhcmFtZXRlcnMuc29tZSgocGFyYW1ldGVyKSA9PlxuICAgICAgICAgICAgICBwYXJhbWV0ZXIubmFtZSA9PSBib3Jyb3dlZFBhcmFtZXRlck5hbWUgJiZcbiAgICAgICAgICAgICAgKHBhcmFtZXRlci50eXBlLmtpbmQgPT0gXCJPd25lZFJlc291cmNlVHlwZVwiIHx8IHBhcmFtZXRlci50eXBlLmtpbmQgPT0gXCJPd25lZFJlZmVyZW5jZVR5cGVcIikpXG4gICAgICAgICAgKVxuICAgICAgICAgIGNvbnN0IHRlcm1pbmFsRmFpbHVyZUlkID0ga25vd25PcGVuQm9ycm93XG4gICAgICAgICAgICA/IGZsb3cua2luZCA9PSBcImJvcnJvd1wiIHx8IGZsb3cua2luZCA9PSBcImNsb3NlXCIgPyBmbG93LnRlcm1pbmFsRmFpbHVyZUlkIDogdW5kZWZpbmVkXG4gICAgICAgICAgICA6IHVuZGVmaW5lZFxuXG4gICAgICAgICAgaWYgKHRlcm1pbmFsRmFpbHVyZUlkKSBzdW1tYXJ5LmZhaWx1cmVJZHMuZGVsZXRlKHRlcm1pbmFsRmFpbHVyZUlkKVxuICAgICAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkNhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgICAgICBjb25zdCBjYWxsZWQgPSBmdW5jdGlvblN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpXG4gICAgICAgICAgaWYgKGNhbGxlZD8uaG9zdCkgc3VtbWFyeS5ob3N0ID0gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIk1ldGhvZENhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgICAgICBjb25zdCBjYWxsZWQgPSBwcmlvck1ldGhvZFN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5tZXRob2QpXG4gICAgICAgICAgaWYgKGNhbGxlZD8uaG9zdCkgc3VtbWFyeS5ob3N0ID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9LCBmYWxzZSlcbiAgICAgIHN1bW1hcmllcy5zZXQoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChtZXRob2QuaWQpLCBzdW1tYXJ5KVxuICAgIH1cbiAgfVxuICByZXR1cm4gc3VtbWFyaWVzXG59XG5cbi8qKlxuICogUmVhZHMgY2hlY2tlZCBzdW1tYXJpZXMgYWxyZWFkeSBwcm92ZWQgb24gaW1wb3J0ZWQgY2xhc3MgZGVjbGFyYXRpb25zLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24+fSBjbGFzc2VzIC0gVmlzaWJsZSBjbGFzc2VzLlxuICogQHBhcmFtIHtcImNvbnN0cnVjdG9yc1wiIHwgXCJtZXRob2RzXCJ9IGtpbmQgLSBEZWNsYXJhdGlvbiBjb2hvcnQuXG4gKiBAcmV0dXJucyB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59IEltcG9ydGVkIHN1bW1hcmllcyBieSBkZWNsYXJhdGlvbiBpZGVudGl0eS5cbiAqL1xuZnVuY3Rpb24gZGVjbGFyZWRDbGFzc1N1bW1hcmllcyhjbGFzc2VzLCBraW5kKSB7XG4gIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgRWZmZWN0U3VtbWFyeT59ICovXG4gIGNvbnN0IHN1bW1hcmllcyA9IG5ldyBNYXAoKVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgY2xhc3Nlcy52YWx1ZXMoKSkge1xuICAgIGNvbnN0IG1lbWJlcnMgPSBraW5kID09IFwiY29uc3RydWN0b3JzXCIgPyBbZGVjbGFyYXRpb24uY29uc3RydWN0b3JdIDogZGVjbGFyYXRpb24ubWV0aG9kc1xuXG4gICAgZm9yIChjb25zdCBtZW1iZXIgb2YgbWVtYmVycykge1xuICAgICAgaWYgKG1lbWJlci5lZmZlY3RzPy5sZW5ndGggPT0gMSAmJiBtZW1iZXIuZWZmZWN0c1swXSA9PSBcImhvc3RcIiAmJiBBcnJheS5pc0FycmF5KG1lbWJlci5mYWlsdXJlSWRzKSkge1xuICAgICAgICBzdW1tYXJpZXMuc2V0KC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAobWVtYmVyLmlkKSwge2ZhaWx1cmVJZHM6IG5ldyBTZXQobWVtYmVyLmZhaWx1cmVJZHMpLCBob3N0OiB0cnVlfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN1bW1hcmllc1xufVxuXG4vKipcbiAqIENvbXB1dGVzIGRpcmVjdCBjb25zdHJ1Y3RvciBlZmZlY3RzIGFmdGVyIGZ1bmN0aW9uIGFuZCBtZXRob2QgZml4ZWQgcG9pbnRzIHN0YWJpbGl6ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gUmVzb2x2ZWQgbW9kdWxlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5Pn0gZnVuY3Rpb25TdW1tYXJpZXMgLSBTdGFibGUgZnVuY3Rpb24gc3VtbWFyaWVzLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBFZmZlY3RTdW1tYXJ5Pn0gbWV0aG9kU3VtbWFyaWVzIC0gU3RhYmxlIG1ldGhvZCBzdW1tYXJpZXMuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBjYXBhYmlsaXR5RmFpbHVyZUlkcyAtIERlY2xhcmVkIGNhcGFiaWxpdHkgZmFpbHVyZXMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBiYXNlU3VtbWFyaWVzIC0gSW1wb3J0ZWQgY29uc3RydWN0b3Igc3VtbWFyaWVzLlxuICogQHJldHVybnMge01hcDxzdHJpbmcsIEVmZmVjdFN1bW1hcnk+fSBDb25zdHJ1Y3RvciBzdW1tYXJpZXMgYnkgaWRlbnRpdHkuXG4gKi9cbmZ1bmN0aW9uIGRpcmVjdENvbnN0cnVjdG9yU3VtbWFyaWVzKG1vZHVsZSwgZnVuY3Rpb25TdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMsIGJhc2VTdW1tYXJpZXMpIHtcbiAgY29uc3Qgc3VtbWFyaWVzID0gbmV3IE1hcChiYXNlU3VtbWFyaWVzKVxuXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgbW9kdWxlLmNsYXNzZXMgPz8gW10pIHtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IGRlY2xhcmF0aW9uLmNvbnN0cnVjdG9yXG4gICAgLyoqIEB0eXBlIHtFZmZlY3RTdW1tYXJ5fSAqL1xuICAgIGNvbnN0IHN1bW1hcnkgPSB7XG4gICAgICBmYWlsdXJlSWRzOiBlc2NhcGluZ0Jsb2NrRmFpbHVyZXMoY29uc3RydWN0b3IuYm9keSwgZnVuY3Rpb25TdW1tYXJpZXMsIG1ldGhvZFN1bW1hcmllcywgY2FwYWJpbGl0eUZhaWx1cmVJZHMpLFxuICAgICAgaG9zdDogZmFsc2VcbiAgICB9XG5cbiAgICBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKGNvbnN0cnVjdG9yLmJvZHksIChleHByZXNzaW9uKSA9PiB7XG4gICAgICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiRWZmZWN0Q2FsbEV4cHJlc3Npb25cIikgc3VtbWFyeS5ob3N0ID0gdHJ1ZVxuICAgICAgZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ2FsbEV4cHJlc3Npb25cIiAmJiBmdW5jdGlvblN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpPy5ob3N0KSBzdW1tYXJ5Lmhvc3QgPSB0cnVlXG4gICAgICBlbHNlIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiICYmIG1ldGhvZFN1bW1hcmllcy5nZXQoZXhwcmVzc2lvbi5tZXRob2QpPy5ob3N0KSBzdW1tYXJ5Lmhvc3QgPSB0cnVlXG4gICAgfSwgZmFsc2UpXG4gICAgc3VtbWFyaWVzLnNldCgvKiogQHR5cGUge3N0cmluZ30gKi8gKGNvbnN0cnVjdG9yLmlkKSwgc3VtbWFyeSlcbiAgfVxuICByZXR1cm4gc3VtbWFyaWVzXG59XG5cbi8qKlxuICogUmVjb3JkcyBvciB2ZXJpZmllcyBvbmUgY2hlY2tlZCBjbGFzcy1tZW1iZXIgc3VtbWFyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Db25zdHJ1Y3RvckRlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5NZXRob2REZWNsYXJhdGlvbn0gZGVjbGFyYXRpb24gLSBDbGFzcyBtZW1iZXIuXG4gKiBAcGFyYW0ge0VmZmVjdFN1bW1hcnkgfCB1bmRlZmluZWR9IHN1bW1hcnkgLSBDb21wdXRlZCBzdW1tYXJ5LlxuICogQHBhcmFtIHtib29sZWFufSBub3JtYWxpemUgLSBXaGV0aGVyIG1ldGFkYXRhIG1heSBiZSB3cml0dGVuLlxuICogQHBhcmFtIHsoY29kZTogc3RyaW5nLCBkZXRhaWw6IHN0cmluZywgbG9jYXRpb246IGltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24pID0+IG5ldmVyfSBmYWlsIC0gTG9jYXRlZCBmYWlsdXJlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGFwcGx5RGVjbGFyYXRpb25TdW1tYXJ5KGRlY2xhcmF0aW9uLCBzdW1tYXJ5LCBub3JtYWxpemUsIGZhaWwpIHtcbiAgaWYgKCFzdW1tYXJ5Py5ob3N0KSB7XG4gICAgaWYgKG5vcm1hbGl6ZSkge1xuICAgICAgZGVsZXRlIGRlY2xhcmF0aW9uLmVmZmVjdHNcbiAgICAgIGRlbGV0ZSBkZWNsYXJhdGlvbi5mYWlsdXJlSWRzXG4gICAgfSBlbHNlIGlmIChkZWNsYXJhdGlvbi5lZmZlY3RzICE9PSB1bmRlZmluZWQgfHwgZGVjbGFyYXRpb24uZmFpbHVyZUlkcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBmYWlsKFwiVU5ERUNMQVJFRF9FRkZFQ1RcIiwgXCJQdXJlIGNsYXNzIG1lbWJlciBjYXJyaWVzIGZvcmdlZCBlZmZlY3QgbWV0YWRhdGEuXCIsIGRlY2xhcmF0aW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICByZXR1cm5cbiAgfVxuICBjb25zdCBmYWlsdXJlSWRzID0gWy4uLnN1bW1hcnkuZmFpbHVyZUlkc11cblxuICBpZiAobm9ybWFsaXplKSB7XG4gICAgZGVjbGFyYXRpb24uZWZmZWN0cyA9IFtcImhvc3RcIl1cbiAgICBkZWNsYXJhdGlvbi5mYWlsdXJlSWRzID0gZmFpbHVyZUlkc1xuICB9IGVsc2UgaWYgKGRlY2xhcmF0aW9uLmVmZmVjdHM/Lmxlbmd0aCAhPSAxIHx8IGRlY2xhcmF0aW9uLmVmZmVjdHNbMF0gIT0gXCJob3N0XCIgfHxcbiAgICAhQXJyYXkuaXNBcnJheShkZWNsYXJhdGlvbi5mYWlsdXJlSWRzKSB8fCBkZWNsYXJhdGlvbi5mYWlsdXJlSWRzLmpvaW4oXCIsXCIpICE9IGZhaWx1cmVJZHMuam9pbihcIixcIikpIHtcbiAgICBmYWlsKFwiVU5ERUNMQVJFRF9FRkZFQ1RcIiwgXCJDbGFzcyBtZW1iZXIgZWZmZWN0IHN1bW1hcnkgZG9lcyBub3QgbWF0Y2ggaXRzIGJvZHkuXCIsIGRlY2xhcmF0aW9uLmxvY2F0aW9uKVxuICB9XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIG9uZSBkZXRlcm1pbmlzdGljIGVmZmVjdC1zaXRlIGlkZW50aXR5LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkNhbGxFeHByZXNzaW9uIHwgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FZmZlY3RDYWxsRXhwcmVzc2lvbiB8IGltcG9ydChcIi4vdHlwZXMuanNcIikuTWV0aG9kQ2FsbEV4cHJlc3Npb24gfCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZmVyZW5jZUNvbnN0cnVjdGlvbn0gZXhwcmVzc2lvbiAtIEVmZmVjdGZ1bCBjYWxsLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpdGUgLSBFeHBlY3RlZCB0cmF2ZXJzYWwgaW5kZXguXG4gKiBAcGFyYW0geyhjb2RlOiBzdHJpbmcsIGRldGFpbDogc3RyaW5nLCBsb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbikgPT4gbmV2ZXJ9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVTaXRlKGV4cHJlc3Npb24sIHNpdGUsIGZhaWwpIHtcbiAgaWYgKGV4cHJlc3Npb24uZWZmZWN0U2l0ZUlkICE9IGBlZmZlY3Q6JHtzaXRlfWApIHtcbiAgICBmYWlsKFwiSU5WQUxJRF9FRkZFQ1RfT1JERVJcIiwgYEVmZmVjdCBzaXRlICcke1N0cmluZyhleHByZXNzaW9uLmVmZmVjdFNpdGVJZCl9JyBpcyBub3QgZXhwZWN0ZWQgc2l0ZSAnZWZmZWN0OiR7c2l0ZX0nLmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gIH1cbn1cblxuLyoqXG4gKiBWaXNpdHMgZXZlcnkgZXhwcmVzc2lvbiBpbiBkZXRlcm1pbmlzdGljIGRlY2xhcmF0aW9uIGFuZCBldmFsdWF0aW9uIG9yZGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBNb2R1bGUgdG8gdHJhdmVyc2UuXG4gKiBAcGFyYW0ge0V4cHJlc3Npb25WaXNpdG9yfSB2aXNpdG9yIC0gRXhwcmVzc2lvbiB2aXNpdG9yLlxuICogQHBhcmFtIHtib29sZWFufSBbcG9zdG9yZGVyXSAtIFZpc2l0IGNoaWxkcmVuIGJlZm9yZSBwYXJlbnRzLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGZvckVhY2hFeHByZXNzaW9uKG1vZHVsZSwgdmlzaXRvciwgcG9zdG9yZGVyID0gZmFsc2UpIHtcbiAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBtb2R1bGUuY2xhc3NlcyA/PyBbXSkge1xuICAgIGZvckVhY2hCbG9ja0V4cHJlc3Npb24oZGVjbGFyYXRpb24uY29uc3RydWN0b3IuYm9keSwgdmlzaXRvciwgcG9zdG9yZGVyKVxuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIGRlY2xhcmF0aW9uLm1ldGhvZHMpIGZvckVhY2hCbG9ja0V4cHJlc3Npb24obWV0aG9kLmJvZHksIHZpc2l0b3IsIHBvc3RvcmRlcilcbiAgfVxuICBmb3IgKGNvbnN0IGRlY2xhcmF0aW9uIG9mIG1vZHVsZS5mdW5jdGlvbnMpIGZvckVhY2hCbG9ja0V4cHJlc3Npb24oZGVjbGFyYXRpb24uYm9keSwgdmlzaXRvciwgcG9zdG9yZGVyKVxuICBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKG1vZHVsZS5lbnRyeVBvaW50LmJvZHksIHZpc2l0b3IsIHBvc3RvcmRlcilcbn1cblxuLyoqXG4gKiBWaXNpdHMgZXhwcmVzc2lvbnMgaW4gb25lIHN0cnVjdHVyZWQgYmxvY2suXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuQmxvY2t9IGJsb2NrIC0gQmxvY2sgdG8gdHJhdmVyc2UuXG4gKiBAcGFyYW0ge0V4cHJlc3Npb25WaXNpdG9yfSB2aXNpdG9yIC0gRXhwcmVzc2lvbiB2aXNpdG9yLlxuICogQHBhcmFtIHtib29sZWFufSBwb3N0b3JkZXIgLSBWaXNpdCBjaGlsZHJlbiBiZWZvcmUgcGFyZW50cy5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKGJsb2NrLCB2aXNpdG9yLCBwb3N0b3JkZXIpIHtcbiAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgYmxvY2suc3RhdGVtZW50cykge1xuICAgIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkxvY2FsRGVjbGFyYXRpb25cIikgdmlzaXQoc3RhdGVtZW50LmluaXRpYWxpemVyKVxuICAgIGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiQXNzaWdubWVudFN0YXRlbWVudFwiIHx8IHN0YXRlbWVudC5raW5kID09IFwiUHJpdmF0ZUZpZWxkV3JpdGVTdGF0ZW1lbnRcIikgdmlzaXQoc3RhdGVtZW50LmV4cHJlc3Npb24pXG4gICAgZWxzZSBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJSZXR1cm5TdGF0ZW1lbnRcIiAmJiBzdGF0ZW1lbnQuZXhwcmVzc2lvbikgdmlzaXQoc3RhdGVtZW50LmV4cHJlc3Npb24pXG4gICAgZWxzZSBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJFeHByZXNzaW9uU3RhdGVtZW50XCIgfHwgc3RhdGVtZW50LmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSB2aXNpdChzdGF0ZW1lbnQuZXhwcmVzc2lvbilcbiAgICBlbHNlIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIklmU3RhdGVtZW50XCIpIHtcbiAgICAgIHZpc2l0KHN0YXRlbWVudC5jb25kaXRpb24pOyBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKHN0YXRlbWVudC5jb25zZXF1ZW50LCB2aXNpdG9yLCBwb3N0b3JkZXIpXG4gICAgICBpZiAoc3RhdGVtZW50LmFsdGVybmF0ZSkgZm9yRWFjaEJsb2NrRXhwcmVzc2lvbihzdGF0ZW1lbnQuYWx0ZXJuYXRlLCB2aXNpdG9yLCBwb3N0b3JkZXIpXG4gICAgfSBlbHNlIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkZvckVhY2hTdGF0ZW1lbnRcIikge1xuICAgICAgdmlzaXQoc3RhdGVtZW50Lmxpc3QpOyBmb3JFYWNoQmxvY2tFeHByZXNzaW9uKHN0YXRlbWVudC5ib2R5LCB2aXNpdG9yLCBwb3N0b3JkZXIpXG4gICAgfSBlbHNlIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkZvckVhY2hNYXBTdGF0ZW1lbnRcIikge1xuICAgICAgdmlzaXQoc3RhdGVtZW50Lm1hcCk7IGZvckVhY2hCbG9ja0V4cHJlc3Npb24oc3RhdGVtZW50LmJvZHksIHZpc2l0b3IsIHBvc3RvcmRlcilcbiAgICB9IGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiV2hpbGVTdGF0ZW1lbnRcIikge1xuICAgICAgdmlzaXQoc3RhdGVtZW50LmNvbmRpdGlvbik7IGZvckVhY2hCbG9ja0V4cHJlc3Npb24oc3RhdGVtZW50LmJvZHksIHZpc2l0b3IsIHBvc3RvcmRlcilcbiAgICB9IGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiUmFpc2VTdGF0ZW1lbnRcIikgdmlzaXQoc3RhdGVtZW50LmVycm9yLm1lc3NhZ2UpXG4gICAgZWxzZSBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJUcnlTdGF0ZW1lbnRcIikge1xuICAgICAgZm9yRWFjaEJsb2NrRXhwcmVzc2lvbihzdGF0ZW1lbnQuYm9keSwgdmlzaXRvciwgcG9zdG9yZGVyKTsgZm9yRWFjaEJsb2NrRXhwcmVzc2lvbihzdGF0ZW1lbnQuY2F0Y2hCb2R5LCB2aXNpdG9yLCBwb3N0b3JkZXIpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZpc2l0cyBvbmUgZXhwcmVzc2lvbiBzdWJ0cmVlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gZXhwcmVzc2lvbiAtIEV4cHJlc3Npb24gcm9vdC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiB2aXNpdChleHByZXNzaW9uKSB7XG4gICAgaWYgKCFwb3N0b3JkZXIpIHZpc2l0b3IoZXhwcmVzc2lvbilcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGV4cHJlc3Npb25DaGlsZHJlbihleHByZXNzaW9uKSkgdmlzaXQoY2hpbGQpXG4gICAgaWYgKHBvc3RvcmRlcikgdmlzaXRvcihleHByZXNzaW9uKVxuICB9XG59XG5cbi8qKlxuICogUmVwb3J0cyB3aGV0aGVyIG9uZSBzZW1hbnRpYyBibG9jayByZWZlcmVuY2VzIGEgcmVzZXJ2ZWQgcHJvdGVjdGVkIHByb3ZpZGVyIGVudHJ5LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJsb2NrfSBibG9jayAtIFNlbWFudGljIGJsb2NrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgYSBwcm90ZWN0ZWQgZW50cnkgbmFtZSBpcyByZWZlcmVuY2VkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYmxvY2tSZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkoYmxvY2spIHtcbiAgcmV0dXJuIGJsb2NrLnN0YXRlbWVudHMuc29tZShzdGF0ZW1lbnRSZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkpXG59XG5cbi8qKlxuICogUmVwb3J0cyB3aGV0aGVyIG9uZSBzZW1hbnRpYyBzdGF0ZW1lbnQgcmVmZXJlbmNlcyBhIHJlc2VydmVkIHByb3RlY3RlZCBwcm92aWRlciBlbnRyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IHN0YXRlbWVudCAtIFNlbWFudGljIHN0YXRlbWVudC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGEgcHJvdGVjdGVkIGVudHJ5IG5hbWUgaXMgcmVmZXJlbmNlZC5cbiAqL1xuZnVuY3Rpb24gc3RhdGVtZW50UmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudCkge1xuICBzd2l0Y2ggKHN0YXRlbWVudC5raW5kKSB7XG4gICAgY2FzZSBcIkxvY2FsRGVjbGFyYXRpb25cIjpcbiAgICAgIHJldHVybiBleHByZXNzaW9uUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5pbml0aWFsaXplcilcbiAgICBjYXNlIFwiQXNzaWdubWVudFN0YXRlbWVudFwiOlxuICAgIGNhc2UgXCJQcml2YXRlRmllbGRXcml0ZVN0YXRlbWVudFwiOlxuICAgICAgcmV0dXJuIGV4cHJlc3Npb25SZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkoc3RhdGVtZW50LmV4cHJlc3Npb24pXG4gICAgY2FzZSBcIlJldHVyblN0YXRlbWVudFwiOlxuICAgICAgcmV0dXJuIHN0YXRlbWVudC5leHByZXNzaW9uID8gZXhwcmVzc2lvblJlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuZXhwcmVzc2lvbikgOiBmYWxzZVxuICAgIGNhc2UgXCJFeHByZXNzaW9uU3RhdGVtZW50XCI6XG4gICAgY2FzZSBcIlByaW50U3RhdGVtZW50XCI6XG4gICAgICByZXR1cm4gZXhwcmVzc2lvblJlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuZXhwcmVzc2lvbilcbiAgICBjYXNlIFwiSWZTdGF0ZW1lbnRcIjpcbiAgICAgIHJldHVybiBleHByZXNzaW9uUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5jb25kaXRpb24pIHx8XG4gICAgICAgIGJsb2NrUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5jb25zZXF1ZW50KSB8fFxuICAgICAgICAoc3RhdGVtZW50LmFsdGVybmF0ZSA/IGJsb2NrUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5hbHRlcm5hdGUpIDogZmFsc2UpXG4gICAgY2FzZSBcIkZvckVhY2hTdGF0ZW1lbnRcIjpcbiAgICAgIHJldHVybiBleHByZXNzaW9uUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5saXN0KSB8fCBibG9ja1JlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuYm9keSlcbiAgICBjYXNlIFwiRm9yRWFjaE1hcFN0YXRlbWVudFwiOlxuICAgICAgcmV0dXJuIGV4cHJlc3Npb25SZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkoc3RhdGVtZW50Lm1hcCkgfHwgYmxvY2tSZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkoc3RhdGVtZW50LmJvZHkpXG4gICAgY2FzZSBcIldoaWxlU3RhdGVtZW50XCI6XG4gICAgICByZXR1cm4gZXhwcmVzc2lvblJlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuY29uZGl0aW9uKSB8fCBibG9ja1JlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuYm9keSlcbiAgICBjYXNlIFwiUmFpc2VTdGF0ZW1lbnRcIjpcbiAgICAgIHJldHVybiBleHByZXNzaW9uUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KHN0YXRlbWVudC5lcnJvci5tZXNzYWdlKVxuICAgIGNhc2UgXCJUcnlTdGF0ZW1lbnRcIjpcbiAgICAgIHJldHVybiBibG9ja1JlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShzdGF0ZW1lbnQuYm9keSkgfHwgYmxvY2tSZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkoc3RhdGVtZW50LmNhdGNoQm9keSlcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuLyoqXG4gKiBSZXBvcnRzIHdoZXRoZXIgb25lIHNlbWFudGljIGV4cHJlc3Npb24gcmVmZXJlbmNlcyBhIHJlc2VydmVkIHByb3RlY3RlZCBwcm92aWRlciBlbnRyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBleHByZXNzaW9uIC0gU2VtYW50aWMgZXhwcmVzc2lvbi5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGEgcHJvdGVjdGVkIGVudHJ5IG5hbWUgaXMgcmVmZXJlbmNlZC5cbiAqL1xuZnVuY3Rpb24gZXhwcmVzc2lvblJlZmVyZW5jZXNQcm90ZWN0ZWRFbnRyeShleHByZXNzaW9uKSB7XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiICYmIHBhcnNlUHJvdGVjdGVkRW50cnlOYW1lKGV4cHJlc3Npb24ubmFtZSkgIT09IG51bGwpIHJldHVybiB0cnVlXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiICYmIHBhcnNlUHJvdGVjdGVkRW50cnlOYW1lKGV4cHJlc3Npb24uY2FsbGVlKSAhPT0gbnVsbCkgcmV0dXJuIHRydWVcbiAgcmV0dXJuIGV4cHJlc3Npb25DaGlsZHJlbihleHByZXNzaW9uKS5zb21lKGV4cHJlc3Npb25SZWZlcmVuY2VzUHJvdGVjdGVkRW50cnkpXG59XG5cbi8qKlxuICogUmV0dXJucyBzZW1hbnRpYyBjaGlsZCBleHByZXNzaW9ucyBpbiBldmFsdWF0aW9uIG9yZGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IGV4cHJlc3Npb24gLSBQYXJlbnQgZXhwcmVzc2lvbi5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkV4cHJlc3Npb25bXX0gQ2hpbGRyZW4uXG4gKi9cbmZ1bmN0aW9uIGV4cHJlc3Npb25DaGlsZHJlbihleHByZXNzaW9uKSB7XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiIHx8IGV4cHJlc3Npb24ua2luZCA9PSBcIkVmZmVjdENhbGxFeHByZXNzaW9uXCIgfHwgZXhwcmVzc2lvbi5raW5kID09IFwiUmVmZXJlbmNlQ29uc3RydWN0aW9uXCIgfHxcbiAgICBleHByZXNzaW9uLmtpbmQgPT0gXCJSZWNvcmRDb25zdHJ1Y3Rpb25cIikgcmV0dXJuIGV4cHJlc3Npb24uYXJndW1lbnRzXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiKSByZXR1cm4gW2V4cHJlc3Npb24ucmVjZWl2ZXIsIC4uLmV4cHJlc3Npb24uYXJndW1lbnRzXVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiT3duZWRCb3Jyb3dFeHByZXNzaW9uXCIgfHwgZXhwcmVzc2lvbi5raW5kID09IFwiT3duZWRNb3ZlRXhwcmVzc2lvblwiKSByZXR1cm4gW2V4cHJlc3Npb24uZXhwcmVzc2lvbl1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLmxlZnQsIGV4cHJlc3Npb24ucmlnaHRdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJVbmFyeUV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLm9wZXJhbmRdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJPcHRpb25hbFNvbWVcIikgcmV0dXJuIFtleHByZXNzaW9uLnZhbHVlXVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiT3B0aW9uYWxJc1ByZXNlbnRcIiB8fCBleHByZXNzaW9uLmtpbmQgPT0gXCJPcHRpb25hbFVud3JhcFwiKSByZXR1cm4gW2V4cHJlc3Npb24ub3BlcmFuZF1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkxpc3RMaXRlcmFsXCIpIHJldHVybiBleHByZXNzaW9uLmVsZW1lbnRzXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNYXBMaXRlcmFsXCIgfHwgZXhwcmVzc2lvbi5raW5kID09IFwiT3JkZXJlZE1hcExpdGVyYWxcIikgcmV0dXJuIGV4cHJlc3Npb24uZW50cmllcy5tYXAoKHt2YWx1ZX0pID0+IHZhbHVlKVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTGlzdEluZGV4RXhwcmVzc2lvblwiKSByZXR1cm4gW2V4cHJlc3Npb24uY29sbGVjdGlvbiwgZXhwcmVzc2lvbi5pbmRleF1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIk1hcExvb2t1cEV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLmNvbGxlY3Rpb24sIGV4cHJlc3Npb24ua2V5XVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ29sbGVjdGlvblNpemVFeHByZXNzaW9uXCIpIHJldHVybiBbZXhwcmVzc2lvbi5jb2xsZWN0aW9uXVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTWVtYmVyUmVhZFwiKSByZXR1cm4gW2V4cHJlc3Npb24ucmVjZWl2ZXJdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJQcml2YXRlRmllbGRSZWFkXCIpIHJldHVybiBbZXhwcmVzc2lvbi5yZWNlaXZlcl1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkVycm9yTWVzc2FnZVJlYWRcIikgcmV0dXJuIFtleHByZXNzaW9uLnJlY2VpdmVyXVxuICByZXR1cm4gW11cbn1cbiJdfQ==
|