semantifold 0.3.0 → 0.5.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 +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -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/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- 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 +160 -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 +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -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 +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -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 +2174 -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 +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -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 +177 -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 +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -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/android.md +79 -0
- package/docs/architecture.md +47 -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 +238 -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 +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -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/android.js +1370 -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 +166 -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 +144 -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 +1408 -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 +2314 -115
- 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 +545 -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 +182 -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 +810 -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,527 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @typedef {(code: string, detail: string, location: import("./types.js").SourceLocation) => never} LifetimeFail */
|
|
3
|
+
/** @typedef {{kind: "open", originId: string, origin: import("./types.js").SourceLocation} | {kind: "moved", originId: string, origin: import("./types.js").SourceLocation, destination: string} | {kind: "terminal", originId: string, origin: import("./types.js").SourceLocation, closeSiteId: string | import("./types.js").SourceLocation}} OwnerState */
|
|
4
|
+
/** @typedef {{kind: "normal" | "return" | "raise" | "break" | "continue", state: Map<string, OwnerState>, location?: import("./types.js").SourceLocation, errorId?: string}} LifetimeExit */
|
|
5
|
+
/**
|
|
6
|
+
* Performs path-sensitive structured lifetime validation for Task 034 owned values.
|
|
7
|
+
* @param {import("./types.js").SemanticModule} module - Fully type-resolved module.
|
|
8
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
9
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
10
|
+
* @returns {void}
|
|
11
|
+
*/
|
|
12
|
+
export function validateResourceLifetimes(module, errorEffects, fail) {
|
|
13
|
+
if (!(module.capabilities ?? []).some(({ resources }) => resources.length > 0) && !moduleContainsOwnedType(module))
|
|
14
|
+
return;
|
|
15
|
+
for (const declaration of module.classes ?? []) {
|
|
16
|
+
analyzeOwner(declaration.constructor.parameters, declaration.constructor.body, fail, undefined, errorEffects);
|
|
17
|
+
for (const method of declaration.methods)
|
|
18
|
+
analyzeOwner(method.parameters, method.body, fail, declaration.ownership?.kind == "ownedResource" ? declaration.ownership.fieldId : undefined, errorEffects);
|
|
19
|
+
}
|
|
20
|
+
for (const declaration of module.functions)
|
|
21
|
+
analyzeOwner(declaration.parameters, declaration.body, fail, undefined, errorEffects);
|
|
22
|
+
analyzeOwner([], module.entryPoint.body, fail, undefined, errorEffects);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Analyzes one function, constructor, method, or entry-point owner.
|
|
26
|
+
* @param {import("./types.js").Parameter[]} parameters - Owned parameters.
|
|
27
|
+
* @param {import("./types.js").Block} body - Structured body.
|
|
28
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
29
|
+
* @param {string | undefined} borrowedFieldId - Owned receiver field, when present.
|
|
30
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
31
|
+
* @returns {void}
|
|
32
|
+
*/
|
|
33
|
+
function analyzeOwner(parameters, body, fail, borrowedFieldId, errorEffects) {
|
|
34
|
+
/** @type {Map<string, OwnerState>} */
|
|
35
|
+
const initial = new Map();
|
|
36
|
+
const obligations = new Set(parameters.filter(({ type }) => isOwned(type)).map(({ name }) => name));
|
|
37
|
+
for (const parameter of parameters) {
|
|
38
|
+
if (isOwned(parameter.type))
|
|
39
|
+
initial.set(parameter.name, openState(`parameter:${parameter.name}`, parameter.location));
|
|
40
|
+
}
|
|
41
|
+
if (borrowedFieldId)
|
|
42
|
+
initial.set(`this.${borrowedFieldId}`, openState(`receiver:${borrowedFieldId}`, body.location));
|
|
43
|
+
const exits = analyzeBlock(body, [{ kind: "normal", state: initial }], fail, errorEffects);
|
|
44
|
+
for (const exit of exits)
|
|
45
|
+
checkLeaks(exit.state, obligations, exit.location ?? body.location, fail);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Evaluates one lexical block while retaining every abrupt exit separately.
|
|
49
|
+
* @param {import("./types.js").Block} block - Structured block.
|
|
50
|
+
* @param {LifetimeExit[]} incoming - Incoming control-flow states.
|
|
51
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
52
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
53
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
54
|
+
*/
|
|
55
|
+
function analyzeBlock(block, incoming, fail, errorEffects) {
|
|
56
|
+
let active = incoming.filter(({ kind }) => kind == "normal");
|
|
57
|
+
const departed = incoming.filter(({ kind }) => kind != "normal");
|
|
58
|
+
/** @type {Set<string>} */
|
|
59
|
+
const locals = new Set();
|
|
60
|
+
for (const statement of block.statements) {
|
|
61
|
+
if (active.length == 0)
|
|
62
|
+
break;
|
|
63
|
+
const next = [];
|
|
64
|
+
for (const flow of active)
|
|
65
|
+
next.push(...analyzeStatement(statement, flow.state, fail, locals, errorEffects));
|
|
66
|
+
departed.push(...next.filter(({ kind }) => kind != "normal"));
|
|
67
|
+
active = mergeEquivalentNormals(next.filter(({ kind }) => kind == "normal"), statement.location, fail);
|
|
68
|
+
}
|
|
69
|
+
const exits = [...departed, ...active.map((flow) => ({ ...flow, location: flow.location ?? block.location }))];
|
|
70
|
+
for (const exit of exits) {
|
|
71
|
+
checkLeaks(exit.state, locals, exit.location ?? block.location, fail);
|
|
72
|
+
for (const name of locals)
|
|
73
|
+
exit.state.delete(name);
|
|
74
|
+
}
|
|
75
|
+
return exits;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Evaluates one statement from one normal state.
|
|
79
|
+
* @param {import("./types.js").Statement} statement - Statement.
|
|
80
|
+
* @param {Map<string, OwnerState>} state - Incoming ownership state.
|
|
81
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
82
|
+
* @param {Set<string>} locals - Locals introduced in the current block.
|
|
83
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
84
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
85
|
+
*/
|
|
86
|
+
function analyzeStatement(statement, state, fail, locals, errorEffects) {
|
|
87
|
+
if (statement.kind == "LocalDeclaration") {
|
|
88
|
+
const flows = evaluateExpression(statement.initializer, cloneState(state), fail, errorEffects);
|
|
89
|
+
if (isOwned(statement.type)) {
|
|
90
|
+
locals.add(statement.name);
|
|
91
|
+
for (const flow of flows) {
|
|
92
|
+
if (flow.kind != "normal")
|
|
93
|
+
continue;
|
|
94
|
+
const origin = statement.initializer.kind == "OwnedMoveExpression"
|
|
95
|
+
? flow.state.get(statement.initializer.expression.name)?.origin ?? statement.initializer.location
|
|
96
|
+
: statement.initializer.location;
|
|
97
|
+
flow.state.set(statement.name, openState(`local:${statement.name}`, origin));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return flows.map((flow) => ({ ...flow, location: statement.location }));
|
|
101
|
+
}
|
|
102
|
+
if (statement.kind == "ExpressionStatement" || statement.kind == "PrintStatement") {
|
|
103
|
+
return evaluateExpression(statement.expression, cloneState(state), fail, errorEffects)
|
|
104
|
+
.map((flow) => ({ ...flow, location: statement.location }));
|
|
105
|
+
}
|
|
106
|
+
if (statement.kind == "AssignmentStatement" || statement.kind == "PrivateFieldWriteStatement") {
|
|
107
|
+
return evaluateExpression(statement.expression, cloneState(state), fail, errorEffects)
|
|
108
|
+
.map((flow) => ({ ...flow, location: statement.location }));
|
|
109
|
+
}
|
|
110
|
+
if (statement.kind == "ReturnStatement") {
|
|
111
|
+
const flows = statement.expression ? evaluateExpression(statement.expression, cloneState(state), fail, errorEffects) :
|
|
112
|
+
/** @type {LifetimeExit[]} */ ([{ kind: "normal", state: cloneState(state) }]);
|
|
113
|
+
return flows.map((flow) => flow.kind == "normal"
|
|
114
|
+
? { kind: "return", location: statement.location, state: flow.state }
|
|
115
|
+
: { ...flow, location: statement.location });
|
|
116
|
+
}
|
|
117
|
+
if (statement.kind == "RaiseStatement") {
|
|
118
|
+
const flows = evaluateExpression(statement.error.message, cloneState(state), fail, errorEffects);
|
|
119
|
+
return flows.map((flow) => flow.kind == "normal"
|
|
120
|
+
? { errorId: statement.error.error.declarationId, kind: "raise", location: statement.location, state: flow.state }
|
|
121
|
+
: { ...flow, location: statement.location });
|
|
122
|
+
}
|
|
123
|
+
if (statement.kind == "IfStatement") {
|
|
124
|
+
const conditions = evaluateExpression(statement.condition, cloneState(state), fail, errorEffects);
|
|
125
|
+
/** @type {LifetimeExit[]} */
|
|
126
|
+
const result = conditions.filter(({ kind }) => kind != "normal");
|
|
127
|
+
for (const condition of conditions.filter(({ kind }) => kind == "normal")) {
|
|
128
|
+
result.push(...analyzeBlock(statement.consequent, [{ kind: "normal", state: cloneState(condition.state) }], fail, errorEffects));
|
|
129
|
+
const alternate = statement.alternate
|
|
130
|
+
? analyzeBlock(statement.alternate, [{ kind: "normal", state: cloneState(condition.state) }], fail, errorEffects)
|
|
131
|
+
: /** @type {LifetimeExit[]} */ ([{ kind: "normal", location: statement.location, state: cloneState(condition.state) }]);
|
|
132
|
+
result.push(...alternate);
|
|
133
|
+
}
|
|
134
|
+
return mergeEquivalentNormals(result, statement.location, fail);
|
|
135
|
+
}
|
|
136
|
+
if (statement.kind == "TryStatement") {
|
|
137
|
+
const bodyExits = analyzeBlock(statement.body, [{ kind: "normal", state: cloneState(state) }], fail, errorEffects);
|
|
138
|
+
/** @type {LifetimeExit[]} */
|
|
139
|
+
const result = bodyExits.filter((flow) => flow.kind != "raise" || flow.errorId != statement.catchType.declarationId);
|
|
140
|
+
for (const caught of bodyExits.filter((flow) => flow.kind == "raise" && flow.errorId == statement.catchType.declarationId)) {
|
|
141
|
+
result.push(...analyzeBlock(statement.catchBody, [{ kind: "normal", state: cloneState(caught.state) }], fail, errorEffects));
|
|
142
|
+
}
|
|
143
|
+
return mergeEquivalentNormals(result, statement.location, fail);
|
|
144
|
+
}
|
|
145
|
+
if (statement.kind == "WhileStatement") {
|
|
146
|
+
const conditions = evaluateExpression(statement.condition, cloneState(state), fail, errorEffects);
|
|
147
|
+
/** @type {LifetimeExit[]} */
|
|
148
|
+
const result = conditions.filter(({ kind }) => kind != "normal");
|
|
149
|
+
for (const condition of conditions.filter(({ kind }) => kind == "normal")) {
|
|
150
|
+
const bodyExits = analyzeBlock(statement.body, [{ kind: "normal", state: cloneState(condition.state) }], fail, errorEffects);
|
|
151
|
+
for (const exit of bodyExits) {
|
|
152
|
+
if (exit.kind == "normal" || exit.kind == "continue")
|
|
153
|
+
requireSameState(condition.state, exit.state, statement.location, fail);
|
|
154
|
+
else if (exit.kind == "break") {
|
|
155
|
+
requireSameState(condition.state, exit.state, statement.location, fail);
|
|
156
|
+
result.push({ kind: "normal", location: statement.location, state: exit.state });
|
|
157
|
+
}
|
|
158
|
+
else
|
|
159
|
+
result.push(exit);
|
|
160
|
+
}
|
|
161
|
+
result.push({ kind: "normal", location: statement.location, state: condition.state });
|
|
162
|
+
}
|
|
163
|
+
return mergeEquivalentNormals(result, statement.location, fail);
|
|
164
|
+
}
|
|
165
|
+
if (statement.kind == "ForEachStatement" || statement.kind == "ForEachMapStatement") {
|
|
166
|
+
const operand = statement.kind == "ForEachStatement" ? statement.list : statement.map;
|
|
167
|
+
const operands = evaluateExpression(operand, cloneState(state), fail, errorEffects);
|
|
168
|
+
/** @type {LifetimeExit[]} */
|
|
169
|
+
const result = operands.filter(({ kind }) => kind != "normal");
|
|
170
|
+
for (const evaluated of operands.filter(({ kind }) => kind == "normal")) {
|
|
171
|
+
const bodyExits = analyzeBlock(statement.body, [{ kind: "normal", state: cloneState(evaluated.state) }], fail, errorEffects);
|
|
172
|
+
for (const exit of bodyExits) {
|
|
173
|
+
if (exit.kind == "normal" || exit.kind == "continue")
|
|
174
|
+
requireSameState(evaluated.state, exit.state, statement.location, fail);
|
|
175
|
+
else if (exit.kind == "break") {
|
|
176
|
+
requireSameState(evaluated.state, exit.state, statement.location, fail);
|
|
177
|
+
result.push({ kind: "normal", location: statement.location, state: exit.state });
|
|
178
|
+
}
|
|
179
|
+
else
|
|
180
|
+
result.push(exit);
|
|
181
|
+
}
|
|
182
|
+
result.push({ kind: "normal", location: statement.location, state: evaluated.state });
|
|
183
|
+
}
|
|
184
|
+
return mergeEquivalentNormals(result, statement.location, fail);
|
|
185
|
+
}
|
|
186
|
+
if (statement.kind == "BreakStatement")
|
|
187
|
+
return [{ kind: "break", location: statement.location, state: cloneState(state) }];
|
|
188
|
+
if (statement.kind == "ContinueStatement")
|
|
189
|
+
return [{ kind: "continue", location: statement.location, state: cloneState(state) }];
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Evaluates one expression with failure states at exact evaluation boundaries.
|
|
194
|
+
* @param {import("./types.js").Expression} expression - Expression.
|
|
195
|
+
* @param {Map<string, OwnerState>} state - Incoming ownership state.
|
|
196
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
197
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
198
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
199
|
+
*/
|
|
200
|
+
function evaluateExpression(expression, state, fail, errorEffects) {
|
|
201
|
+
if (expression.kind == "OwnedMoveExpression") {
|
|
202
|
+
const owner = requireOwner(expression.expression.name, state, expression.location, fail);
|
|
203
|
+
if (owner.kind == "moved")
|
|
204
|
+
fail("USE_AFTER_MOVE", `Resource '${expression.expression.name}' was already moved.`, expression.location);
|
|
205
|
+
if (owner.kind == "terminal")
|
|
206
|
+
fail("USE_AFTER_CLOSE", `Resource '${expression.expression.name}' is terminal after close.`, expression.location);
|
|
207
|
+
state.set(expression.expression.name, { ...owner, destination: "transfer", kind: "moved" });
|
|
208
|
+
return [{ kind: "normal", state }];
|
|
209
|
+
}
|
|
210
|
+
if (expression.kind == "OwnedBorrowExpression") {
|
|
211
|
+
const name = placeName(expression.expression);
|
|
212
|
+
const owner = requireOwner(name, state, expression.location, fail);
|
|
213
|
+
if (owner.kind == "moved")
|
|
214
|
+
fail("USE_AFTER_MOVE", `Resource '${name}' was moved before this borrow.`, expression.location);
|
|
215
|
+
return [{ kind: "normal", state }];
|
|
216
|
+
}
|
|
217
|
+
if (expression.kind == "EffectCallExpression")
|
|
218
|
+
return evaluateEffectCall(expression, state, fail, errorEffects);
|
|
219
|
+
if (expression.kind == "CallExpression" || expression.kind == "MethodCallExpression" || expression.kind == "ReferenceConstruction") {
|
|
220
|
+
return evaluateOrdinaryCall(expression, state, fail, errorEffects);
|
|
221
|
+
}
|
|
222
|
+
/** @type {LifetimeExit[]} */
|
|
223
|
+
let flows = [{ kind: "normal", state }];
|
|
224
|
+
for (const child of expressionChildren(expression))
|
|
225
|
+
flows = evaluateForFlows(child, flows, fail, errorEffects);
|
|
226
|
+
return flows;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Applies one capability operation's declared ownership and failure flow.
|
|
230
|
+
* @param {import("./types.js").EffectCallExpression} expression - Effect call.
|
|
231
|
+
* @param {Map<string, OwnerState>} state - Incoming ownership state.
|
|
232
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
233
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
234
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
235
|
+
*/
|
|
236
|
+
function evaluateEffectCall(expression, state, fail, errorEffects) {
|
|
237
|
+
/** @type {LifetimeExit[]} */
|
|
238
|
+
let flows = [{ kind: "normal", state }];
|
|
239
|
+
for (const argument of expression.arguments)
|
|
240
|
+
flows = evaluateForFlows(argument, flows, fail, errorEffects);
|
|
241
|
+
const result = flows.filter(({ kind }) => kind != "normal");
|
|
242
|
+
const resourceFlow = expression.resolution.resourceFlow;
|
|
243
|
+
for (const flow of flows.filter(({ kind }) => kind == "normal")) {
|
|
244
|
+
let operationState = cloneState(flow.state);
|
|
245
|
+
let terminalFailure;
|
|
246
|
+
if (resourceFlow.kind == "borrow" || resourceFlow.kind == "close") {
|
|
247
|
+
const argument = expression.arguments[resourceFlow.parameterIndex];
|
|
248
|
+
if (argument.kind != "OwnedBorrowExpression")
|
|
249
|
+
fail("INVALID_RESOURCE_BORROW", "Resource operation lacks an immediate borrow.", argument.location);
|
|
250
|
+
const name = placeName(argument.expression);
|
|
251
|
+
const owner = requireOwner(name, operationState, argument.location, fail);
|
|
252
|
+
if (owner.kind == "moved")
|
|
253
|
+
fail("USE_AFTER_MOVE", `Resource '${name}' was moved before this operation.`, argument.location);
|
|
254
|
+
if (owner.kind == "terminal")
|
|
255
|
+
terminalFailure = resourceFlow.terminalFailureId;
|
|
256
|
+
else if (resourceFlow.kind == "close")
|
|
257
|
+
operationState.set(name, { ...owner, closeSiteId: expression.effectSiteId, kind: "terminal" });
|
|
258
|
+
}
|
|
259
|
+
if (terminalFailure) {
|
|
260
|
+
result.push({ errorId: terminalFailure, kind: "raise", location: expression.location, state: operationState });
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const failureIds = expression.resolution.failureIds.filter((id) => resourceFlow.kind != "borrow" && resourceFlow.kind != "close" || id != resourceFlow.terminalFailureId);
|
|
264
|
+
result.push({ kind: "normal", state: cloneState(operationState) });
|
|
265
|
+
for (const errorId of failureIds) {
|
|
266
|
+
result.push({ errorId, kind: "raise", location: expression.location, state: cloneState(operationState) });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Applies call-entry ownership commit semantics after ordered argument evaluation.
|
|
273
|
+
* @param {import("./types.js").CallExpression | import("./types.js").MethodCallExpression | import("./types.js").ReferenceConstruction} expression - Call.
|
|
274
|
+
* @param {Map<string, OwnerState>} state - Incoming ownership state.
|
|
275
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
276
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
277
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
278
|
+
*/
|
|
279
|
+
function evaluateOrdinaryCall(expression, state, fail, errorEffects) {
|
|
280
|
+
const arguments_ = expression.kind == "MethodCallExpression" ? [expression.receiver, ...expression.arguments] : expression.arguments;
|
|
281
|
+
/** @type {LifetimeExit[]} */
|
|
282
|
+
let flows = [{ kind: "normal", state }];
|
|
283
|
+
/** @type {string[]} */
|
|
284
|
+
const reservedMoves = [];
|
|
285
|
+
for (const argument of arguments_) {
|
|
286
|
+
if (argument.kind == "OwnedMoveExpression") {
|
|
287
|
+
for (const flow of flows.filter(({ kind }) => kind == "normal")) {
|
|
288
|
+
const owner = requireOwner(argument.expression.name, flow.state, argument.location, fail);
|
|
289
|
+
if (owner.kind == "moved")
|
|
290
|
+
fail("USE_AFTER_MOVE", `Resource '${argument.expression.name}' was already moved.`, argument.location);
|
|
291
|
+
if (owner.kind == "terminal")
|
|
292
|
+
fail("USE_AFTER_CLOSE", `Resource '${argument.expression.name}' is terminal after close.`, argument.location);
|
|
293
|
+
}
|
|
294
|
+
if (reservedMoves.includes(argument.expression.name)) {
|
|
295
|
+
fail("RESOURCE_ALIAS", `Resource '${argument.expression.name}' cannot be transferred to two parameters.`, argument.location);
|
|
296
|
+
}
|
|
297
|
+
reservedMoves.push(argument.expression.name);
|
|
298
|
+
}
|
|
299
|
+
else
|
|
300
|
+
flows = evaluateForFlows(argument, flows, fail, errorEffects);
|
|
301
|
+
}
|
|
302
|
+
const result = flows.filter(({ kind }) => kind != "normal");
|
|
303
|
+
for (const flow of flows.filter(({ kind }) => kind == "normal")) {
|
|
304
|
+
const entered = cloneState(flow.state);
|
|
305
|
+
for (const name of reservedMoves) {
|
|
306
|
+
const owner = requireOwner(name, entered, expression.location, fail);
|
|
307
|
+
if (owner.kind == "moved")
|
|
308
|
+
fail("USE_AFTER_MOVE", `Resource '${name}' was already moved.`, expression.location);
|
|
309
|
+
if (owner.kind == "terminal")
|
|
310
|
+
fail("USE_AFTER_CLOSE", `Resource '${name}' is terminal after close.`, expression.location);
|
|
311
|
+
entered.set(name, { ...owner, destination: "callee", kind: "moved" });
|
|
312
|
+
}
|
|
313
|
+
if (expression.kind == "MethodCallExpression" && expression.resolution?.resourceFlow) {
|
|
314
|
+
const receiver = expression.receiver.kind == "OwnedBorrowExpression" ? expression.receiver.expression : expression.receiver;
|
|
315
|
+
if (receiver.kind != "IdentifierExpression" && receiver.kind != "ReceiverExpression" && receiver.kind != "PrivateFieldRead") {
|
|
316
|
+
fail("INVALID_RESOURCE_BORROW", "Owned method receiver must be an immediate borrowed place.", receiver.location);
|
|
317
|
+
}
|
|
318
|
+
const name = placeName(receiver);
|
|
319
|
+
const owner = requireOwner(name, entered, expression.location, fail);
|
|
320
|
+
if (owner.kind == "terminal") {
|
|
321
|
+
if (expression.resolution.resourceFlow.terminalFailureId) {
|
|
322
|
+
result.push({ errorId: expression.resolution.resourceFlow.terminalFailureId, kind: "raise",
|
|
323
|
+
location: expression.location, state: entered });
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
fail("USE_AFTER_CLOSE", `Resource '${name}' is terminal after close.`, expression.location);
|
|
327
|
+
}
|
|
328
|
+
if (expression.resolution.resourceFlow.kind == "terminal") {
|
|
329
|
+
entered.set(name, { ...owner, closeSiteId: expression.effectSiteId ?? expression.location, kind: "terminal" });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
result.push({ kind: "normal", state: cloneState(entered) });
|
|
333
|
+
const escaping = new Set(expression.failureIds ?? []);
|
|
334
|
+
if (expression.kind == "CallExpression") {
|
|
335
|
+
for (const errorId of errorEffects.functions.get(expression.callee) ?? [])
|
|
336
|
+
escaping.add(errorId);
|
|
337
|
+
}
|
|
338
|
+
else if (expression.kind == "MethodCallExpression") {
|
|
339
|
+
for (const errorId of errorEffects.methods.get(expression.method) ?? [])
|
|
340
|
+
escaping.add(errorId);
|
|
341
|
+
}
|
|
342
|
+
for (const errorId of escaping) {
|
|
343
|
+
result.push({ errorId, kind: "raise", location: expression.location, state: cloneState(entered) });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Evaluates a child expression only along normal incoming paths.
|
|
350
|
+
* @param {import("./types.js").Expression} expression - Child expression.
|
|
351
|
+
* @param {LifetimeExit[]} flows - Incoming paths.
|
|
352
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
353
|
+
* @param {{functions: Map<string, Set<string>>, methods: Map<string, Set<string>>}} errorEffects - Complete escaping error sets per function and method.
|
|
354
|
+
* @returns {LifetimeExit[]} Reachable exits.
|
|
355
|
+
*/
|
|
356
|
+
function evaluateForFlows(expression, flows, fail, errorEffects) {
|
|
357
|
+
const result = flows.filter(({ kind }) => kind != "normal");
|
|
358
|
+
for (const flow of flows.filter(({ kind }) => kind == "normal")) {
|
|
359
|
+
result.push(...evaluateExpression(expression, cloneState(flow.state), fail, errorEffects));
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Returns non-call expression children in evaluation order.
|
|
365
|
+
* @param {import("./types.js").Expression} expression - Parent expression.
|
|
366
|
+
* @returns {import("./types.js").Expression[]} Children.
|
|
367
|
+
*/
|
|
368
|
+
function expressionChildren(expression) {
|
|
369
|
+
if (expression.kind == "BinaryExpression")
|
|
370
|
+
return [expression.left, expression.right];
|
|
371
|
+
if (expression.kind == "UnaryExpression")
|
|
372
|
+
return [expression.operand];
|
|
373
|
+
if (expression.kind == "OptionalSome")
|
|
374
|
+
return [expression.value];
|
|
375
|
+
if (expression.kind == "OptionalIsPresent" || expression.kind == "OptionalUnwrap")
|
|
376
|
+
return [expression.operand];
|
|
377
|
+
if (expression.kind == "ListLiteral")
|
|
378
|
+
return expression.elements;
|
|
379
|
+
if (expression.kind == "MapLiteral" || expression.kind == "OrderedMapLiteral")
|
|
380
|
+
return expression.entries.map(({ value }) => value);
|
|
381
|
+
if (expression.kind == "ListIndexExpression")
|
|
382
|
+
return [expression.collection, expression.index];
|
|
383
|
+
if (expression.kind == "MapLookupExpression")
|
|
384
|
+
return [expression.collection, expression.key];
|
|
385
|
+
if (expression.kind == "CollectionSizeExpression")
|
|
386
|
+
return [expression.collection];
|
|
387
|
+
if (expression.kind == "RecordConstruction")
|
|
388
|
+
return expression.arguments;
|
|
389
|
+
if (expression.kind == "MemberRead")
|
|
390
|
+
return [expression.receiver];
|
|
391
|
+
if (expression.kind == "PrivateFieldRead")
|
|
392
|
+
return [expression.receiver];
|
|
393
|
+
if (expression.kind == "ErrorMessageRead")
|
|
394
|
+
return [expression.receiver];
|
|
395
|
+
return [];
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Merges normal paths only after proving identical ownership states.
|
|
399
|
+
* @param {LifetimeExit[]} flows - Candidate paths.
|
|
400
|
+
* @param {import("./types.js").SourceLocation} location - Join location.
|
|
401
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
402
|
+
* @returns {LifetimeExit[]} Merged paths.
|
|
403
|
+
*/
|
|
404
|
+
function mergeEquivalentNormals(flows, location, fail) {
|
|
405
|
+
const normal = flows.filter(({ kind }) => kind == "normal");
|
|
406
|
+
if (normal.length > 1) {
|
|
407
|
+
for (const candidate of normal.slice(1))
|
|
408
|
+
requireSameState(normal[0].state, candidate.state, location, fail);
|
|
409
|
+
}
|
|
410
|
+
return [...flows.filter(({ kind }) => kind != "normal"), ...(normal.length > 0 ? [normal[0]] : [])];
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Requires a finite ownership invariant at a branch or loop join.
|
|
414
|
+
* @param {Map<string, OwnerState>} left - First ownership state.
|
|
415
|
+
* @param {Map<string, OwnerState>} right - Second ownership state.
|
|
416
|
+
* @param {import("./types.js").SourceLocation} location - Join location.
|
|
417
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
418
|
+
* @returns {void}
|
|
419
|
+
*/
|
|
420
|
+
function requireSameState(left, right, location, fail) {
|
|
421
|
+
const names = new Set([...left.keys(), ...right.keys()]);
|
|
422
|
+
for (const name of names) {
|
|
423
|
+
const leftState = left.get(name);
|
|
424
|
+
const rightState = right.get(name);
|
|
425
|
+
if (leftState?.kind != rightState?.kind || leftState?.originId != rightState?.originId) {
|
|
426
|
+
fail("RESOURCE_STATE_MISMATCH", `Resource '${name}' has different ownership state across reachable paths.`, location);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Rejects every owned value that leaves its introducing scope open.
|
|
432
|
+
* @param {Map<string, OwnerState>} state - Ownership state.
|
|
433
|
+
* @param {Set<string>} names - Owners introduced in the scope.
|
|
434
|
+
* @param {import("./types.js").SourceLocation} location - Exit location.
|
|
435
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
436
|
+
* @returns {void}
|
|
437
|
+
*/
|
|
438
|
+
function checkLeaks(state, names, location, fail) {
|
|
439
|
+
for (const name of names) {
|
|
440
|
+
const owner = state.get(name);
|
|
441
|
+
if (owner?.kind == "open") {
|
|
442
|
+
const origin = owner.origin;
|
|
443
|
+
fail("LEAKED_RESOURCE", `Owned resource '${name}' remains open; acquired at ${origin.filename}:${origin.start.line}:${origin.start.column}.`, location);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Resolves an owned place in the current scope.
|
|
449
|
+
* @param {string} name - Stable place name.
|
|
450
|
+
* @param {Map<string, OwnerState>} state - Ownership state.
|
|
451
|
+
* @param {import("./types.js").SourceLocation} location - Use location.
|
|
452
|
+
* @param {LifetimeFail} fail - Located failure.
|
|
453
|
+
* @returns {OwnerState} Owner state.
|
|
454
|
+
*/
|
|
455
|
+
function requireOwner(name, state, location, fail) {
|
|
456
|
+
const owner = state.get(name);
|
|
457
|
+
if (!owner)
|
|
458
|
+
return fail("INVALID_RESOURCE_BORROW", `No owned resource place '${name}' is in scope.`, location);
|
|
459
|
+
return owner;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Converts an immediate owned expression to a stable place name.
|
|
463
|
+
* @param {import("./types.js").IdentifierExpression | import("./types.js").ReceiverExpression | import("./types.js").PrivateFieldRead} expression - Owned place.
|
|
464
|
+
* @returns {string} Place identity.
|
|
465
|
+
*/
|
|
466
|
+
function placeName(expression) {
|
|
467
|
+
if (expression.kind == "IdentifierExpression")
|
|
468
|
+
return expression.name;
|
|
469
|
+
if (expression.kind == "ReceiverExpression")
|
|
470
|
+
return "this";
|
|
471
|
+
if (expression.kind == "PrivateFieldRead")
|
|
472
|
+
return `this.${expression.field}`;
|
|
473
|
+
return "<invalid>";
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Creates one open ownership state.
|
|
477
|
+
* @param {string} originId - Deterministic origin identity.
|
|
478
|
+
* @param {import("./types.js").SourceLocation} origin - Acquisition location.
|
|
479
|
+
* @returns {OwnerState} Open state.
|
|
480
|
+
*/
|
|
481
|
+
function openState(originId, origin) {
|
|
482
|
+
return { kind: "open", origin, originId };
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Clones an ownership state for a control-flow fork.
|
|
486
|
+
* @param {Map<string, OwnerState>} state - State to clone.
|
|
487
|
+
* @returns {Map<string, OwnerState>} Detached state.
|
|
488
|
+
*/
|
|
489
|
+
function cloneState(state) {
|
|
490
|
+
return new Map([...state].map(([name, value]) => [name, { ...value }]));
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Checks whether a type carries linear ownership.
|
|
494
|
+
* @param {import("./types.js").SemanticFunctionReturnType} type - Semantic type.
|
|
495
|
+
* @returns {boolean} Whether the type is owned.
|
|
496
|
+
*/
|
|
497
|
+
function isOwned(type) {
|
|
498
|
+
return type.kind == "OwnedResourceType" || type.kind == "OwnedReferenceType";
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Checks whether the module contains any owned semantic type.
|
|
502
|
+
* @param {import("./types.js").SemanticModule} module - Semantic module.
|
|
503
|
+
* @returns {boolean} Whether lifetime analysis is required.
|
|
504
|
+
*/
|
|
505
|
+
function moduleContainsOwnedType(module) {
|
|
506
|
+
const pending = [/** @type {unknown} */ (module)];
|
|
507
|
+
const seen = new Set();
|
|
508
|
+
while (pending.length > 0) {
|
|
509
|
+
const value = pending.pop();
|
|
510
|
+
if (!value || typeof value != "object" || seen.has(value))
|
|
511
|
+
continue;
|
|
512
|
+
seen.add(value);
|
|
513
|
+
if (!Array.isArray(value) && (Reflect.get(value, "kind") == "OwnedResourceType" ||
|
|
514
|
+
Reflect.get(value, "kind") == "OwnedReferenceType"))
|
|
515
|
+
return true;
|
|
516
|
+
for (const [key, child] of Object.entries(value)) {
|
|
517
|
+
if (["location", "provenance", "sourceProvenance"].includes(key))
|
|
518
|
+
continue;
|
|
519
|
+
if (Array.isArray(child))
|
|
520
|
+
pending.push(...child);
|
|
521
|
+
else if (child && typeof child == "object")
|
|
522
|
+
pending.push(child);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlmZXRpbWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VtYW50aWMvbGlmZXRpbWUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLHFIQUFxSDtBQUNySCwrVkFBK1Y7QUFDL1YsNkxBQTZMO0FBRTdMOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSx5QkFBeUIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLElBQUk7SUFDbEUsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFDLFNBQVMsRUFBQyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTTtJQUV4SCxLQUFLLE1BQU0sV0FBVyxJQUFJLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxFQUFFLENBQUM7UUFDL0MsWUFBWSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUE7UUFDN0csS0FBSyxNQUFNLE1BQU0sSUFBSSxXQUFXLENBQUMsT0FBTztZQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUN6RixXQUFXLENBQUMsU0FBUyxFQUFFLElBQUksSUFBSSxlQUFlLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUE7SUFDN0csQ0FBQztJQUNELEtBQUssTUFBTSxXQUFXLElBQUksTUFBTSxDQUFDLFNBQVM7UUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMs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dHJpbmcsIGRldGFpbDogc3RyaW5nLCBsb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbikgPT4gbmV2ZXJ9IExpZmV0aW1lRmFpbCAqL1xuLyoqIEB0eXBlZGVmIHt7a2luZDogXCJvcGVuXCIsIG9yaWdpbklkOiBzdHJpbmcsIG9yaWdpbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gfCB7a2luZDogXCJtb3ZlZFwiLCBvcmlnaW5JZDogc3RyaW5nLCBvcmlnaW46IGltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIGRlc3RpbmF0aW9uOiBzdHJpbmd9IHwge2tpbmQ6IFwidGVybWluYWxcIiwgb3JpZ2luSWQ6IHN0cmluZywgb3JpZ2luOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBjbG9zZVNpdGVJZDogc3RyaW5nIHwgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn19IE93bmVyU3RhdGUgKi9cbi8qKiBAdHlwZWRlZiB7e2tpbmQ6IFwibm9ybWFsXCIgfCBcInJldHVyblwiIHwgXCJyYWlzZVwiIHwgXCJicmVha1wiIHwgXCJjb250aW51ZVwiLCBzdGF0ZTogTWFwPHN0cmluZywgT3duZXJTdGF0ZT4sIGxvY2F0aW9uPzogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgZXJyb3JJZD86IHN0cmluZ319IExpZmV0aW1lRXhpdCAqL1xuXG4vKipcbiAqIFBlcmZvcm1zIHBhdGgtc2Vuc2l0aXZlIHN0cnVjdHVyZWQgbGlmZXRpbWUgdmFsaWRhdGlvbiBmb3IgVGFzayAwMzQgb3duZWQgdmFsdWVzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBGdWxseSB0eXBlLXJlc29sdmVkIG1vZHVsZS5cbiAqIEBwYXJhbSB7e2Z1bmN0aW9uczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LCBtZXRob2RzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj59fSBlcnJvckVmZmVjdHMgLSBDb21wbGV0ZSBlc2NhcGluZyBlcnJvciBzZXRzIHBlciBmdW5jdGlvbiBhbmQgbWV0aG9kLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUmVzb3VyY2VMaWZldGltZXMobW9kdWxlLCBlcnJvckVmZmVjdHMsIGZhaWwpIHtcbiAgaWYgKCEobW9kdWxlLmNhcGFiaWxpdGllcyA/PyBbXSkuc29tZSgoe3Jlc291cmNlc30pID0+IHJlc291cmNlcy5sZW5ndGggPiAwKSAmJiAhbW9kdWxlQ29udGFpbnNPd25lZFR5cGUobW9kdWxlKSkgcmV0dXJuXG5cbiAgZm9yIChjb25zdCBkZWNsYXJhdGlvbiBvZiBtb2R1bGUuY2xhc3NlcyA/PyBbXSkge1xuICAgIGFuYWx5emVPd25lcihkZWNsYXJhdGlvbi5jb25zdHJ1Y3Rvci5wYXJhbWV0ZXJzLCBkZWNsYXJhdGlvbi5jb25zdHJ1Y3Rvci5ib2R5LCBmYWlsLCB1bmRlZmluZWQsIGVycm9yRWZmZWN0cylcbiAgICBmb3IgKGNvbnN0IG1ldGhvZCBvZiBkZWNsYXJhdGlvbi5tZXRob2RzKSBhbmFseXplT3duZXIobWV0aG9kLnBhcmFtZXRlcnMsIG1ldGhvZC5ib2R5LCBmYWlsLFxuICAgICAgZGVjbGFyYXRpb24ub3duZXJzaGlwPy5raW5kID09IFwib3duZWRSZXNvdXJjZVwiID8gZGVjbGFyYXRpb24ub3duZXJzaGlwLmZpZWxkSWQgOiB1bmRlZmluZWQsIGVycm9yRWZmZWN0cylcbiAgfVxuICBmb3IgKGNvbnN0IGRlY2xhcmF0aW9uIG9mIG1vZHVsZS5mdW5jdGlvbnMpIGFuYWx5emVPd25lcihkZWNsYXJhdGlvbi5wYXJhbWV0ZXJzLCBkZWNsYXJhdGlvbi5ib2R5LCBmYWlsLCB1bmRlZmluZWQsIGVycm9yRWZmZWN0cylcbiAgYW5hbHl6ZU93bmVyKFtdLCBtb2R1bGUuZW50cnlQb2ludC5ib2R5LCBmYWlsLCB1bmRlZmluZWQsIGVycm9yRWZmZWN0cylcbn1cblxuLyoqXG4gKiBBbmFseXplcyBvbmUgZnVuY3Rpb24sIGNvbnN0cnVjdG9yLCBtZXRob2QsIG9yIGVudHJ5LXBvaW50IG93bmVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlBhcmFtZXRlcltdfSBwYXJhbWV0ZXJzIC0gT3duZWQgcGFyYW1ldGVycy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CbG9ja30gYm9keSAtIFN0cnVjdHVyZWQgYm9keS5cbiAqIEBwYXJhbSB7TGlmZXRpbWVGYWlsfSBmYWlsIC0gTG9jYXRlZCBmYWlsdXJlLlxuICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IGJvcnJvd2VkRmllbGRJZCAtIE93bmVkIHJlY2VpdmVyIGZpZWxkLCB3aGVuIHByZXNlbnQuXG4gKiBAcGFyYW0ge3tmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PiwgbWV0aG9kczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+fX0gZXJyb3JFZmZlY3RzIC0gQ29tcGxldGUgZXNjYXBpbmcgZXJyb3Igc2V0cyBwZXIgZnVuY3Rpb24gYW5kIG1ldGhvZC5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhbmFseXplT3duZXIocGFyYW1ldGVycywgYm9keSwgZmFpbCwgYm9ycm93ZWRGaWVsZElkLCBlcnJvckVmZmVjdHMpIHtcbiAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBPd25lclN0YXRlPn0gKi9cbiAgY29uc3QgaW5pdGlhbCA9IG5ldyBNYXAoKVxuICBjb25zdCBvYmxpZ2F0aW9ucyA9IG5ldyBTZXQocGFyYW1ldGVycy5maWx0ZXIoKHt0eXBlfSkgPT4gaXNPd25lZCh0eXBlKSkubWFwKCh7bmFtZX0pID0+IG5hbWUpKVxuXG4gIGZvciAoY29uc3QgcGFyYW1ldGVyIG9mIHBhcmFtZXRlcnMpIHtcbiAgICBpZiAoaXNPd25lZChwYXJhbWV0ZXIudHlwZSkpIGluaXRpYWwuc2V0KHBhcmFtZXRlci5uYW1lLCBvcGVuU3RhdGUoYHBhcmFtZXRlcjoke3BhcmFtZXRlci5uYW1lfWAsIHBhcmFtZXRlci5sb2NhdGlvbikpXG4gIH1cbiAgaWYgKGJvcnJvd2VkRmllbGRJZCkgaW5pdGlhbC5zZXQoYHRoaXMuJHtib3Jyb3dlZEZpZWxkSWR9YCwgb3BlblN0YXRlKGByZWNlaXZlcjoke2JvcnJvd2VkRmllbGRJZH1gLCBib2R5LmxvY2F0aW9uKSlcbiAgY29uc3QgZXhpdHMgPSBhbmFseXplQmxvY2soYm9keSwgW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZTogaW5pdGlhbH1dLCBmYWlsLCBlcnJvckVmZmVjdHMpXG5cbiAgZm9yIChjb25zdCBleGl0IG9mIGV4aXRzKSBjaGVja0xlYWtzKGV4aXQuc3RhdGUsIG9ibGlnYXRpb25zLCBleGl0LmxvY2F0aW9uID8/IGJvZHkubG9jYXRpb24sIGZhaWwpXG59XG5cbi8qKlxuICogRXZhbHVhdGVzIG9uZSBsZXhpY2FsIGJsb2NrIHdoaWxlIHJldGFpbmluZyBldmVyeSBhYnJ1cHQgZXhpdCBzZXBhcmF0ZWx5LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJsb2NrfSBibG9jayAtIFN0cnVjdHVyZWQgYmxvY2suXG4gKiBAcGFyYW0ge0xpZmV0aW1lRXhpdFtdfSBpbmNvbWluZyAtIEluY29taW5nIGNvbnRyb2wtZmxvdyBzdGF0ZXMuXG4gKiBAcGFyYW0ge0xpZmV0aW1lRmFpbH0gZmFpbCAtIExvY2F0ZWQgZmFpbHVyZS5cbiAqIEBwYXJhbSB7e2Z1bmN0aW9uczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LCBtZXRob2RzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj59fSBlcnJvckVmZmVjdHMgLSBDb21wbGV0ZSBlc2NhcGluZyBlcnJvciBzZXRzIHBlciBmdW5jdGlvbiBhbmQgbWV0aG9kLlxuICogQHJldHVybnMge0xpZmV0aW1lRXhpdFtdfSBSZWFjaGFibGUgZXhpdHMuXG4gKi9cbmZ1bmN0aW9uIGFuYWx5emVCbG9jayhibG9jaywgaW5jb21pbmcsIGZhaWwsIGVycm9yRWZmZWN0cykge1xuICBsZXQgYWN0aXZlID0gaW5jb21pbmcuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIilcbiAgY29uc3QgZGVwYXJ0ZWQgPSBpbmNvbWluZy5maWx0ZXIoKHtraW5kfSkgPT4ga2luZCAhPSBcIm5vcm1hbFwiKVxuICAvKiogQHR5cGUge1NldDxzdHJpbmc+fSAqL1xuICBjb25zdCBsb2NhbHMgPSBuZXcgU2V0KClcblxuICBmb3IgKGNvbnN0IHN0YXRlbWVudCBvZiBibG9jay5zdGF0ZW1lbnRzKSB7XG4gICAgaWYgKGFjdGl2ZS5sZW5ndGggPT0gMCkgYnJlYWtcbiAgICBjb25zdCBuZXh0ID0gW11cblxuICAgIGZvciAoY29uc3QgZmxvdyBvZiBhY3RpdmUpIG5leHQucHVzaCguLi5hbmFseXplU3RhdGVtZW50KHN0YXRlbWVudCwgZmxvdy5zdGF0ZSwgZmFpbCwgbG9jYWxzLCBlcnJvckVmZmVjdHMpKVxuICAgIGRlcGFydGVkLnB1c2goLi4ubmV4dC5maWx0ZXIoKHtraW5kfSkgPT4ga2luZCAhPSBcIm5vcm1hbFwiKSlcbiAgICBhY3RpdmUgPSBtZXJnZUVxdWl2YWxlbnROb3JtYWxzKG5leHQuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIiksIHN0YXRlbWVudC5sb2NhdGlvbiwgZmFpbClcbiAgfVxuICBjb25zdCBleGl0cyA9IFsuLi5kZXBhcnRlZCwgLi4uYWN0aXZlLm1hcCgoZmxvdykgPT4gKHsuLi5mbG93LCBsb2NhdGlvbjogZmxvdy5sb2NhdGlvbiA/PyBibG9jay5sb2NhdGlvbn0pKV1cblxuICBmb3IgKGNvbnN0IGV4aXQgb2YgZXhpdHMpIHtcbiAgICBjaGVja0xlYWtzKGV4aXQuc3RhdGUsIGxvY2FscywgZXhpdC5sb2NhdGlvbiA/PyBibG9jay5sb2NhdGlvbiwgZmFpbClcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgbG9jYWxzKSBleGl0LnN0YXRlLmRlbGV0ZShuYW1lKVxuICB9XG4gIHJldHVybiBleGl0c1xufVxuXG4vKipcbiAqIEV2YWx1YXRlcyBvbmUgc3RhdGVtZW50IGZyb20gb25lIG5vcm1hbCBzdGF0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IHN0YXRlbWVudCAtIFN0YXRlbWVudC5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gSW5jb21pbmcgb3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSBsb2NhbHMgLSBMb2NhbHMgaW50cm9kdWNlZCBpbiB0aGUgY3VycmVudCBibG9jay5cbiAqIEBwYXJhbSB7e2Z1bmN0aW9uczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LCBtZXRob2RzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj59fSBlcnJvckVmZmVjdHMgLSBDb21wbGV0ZSBlc2NhcGluZyBlcnJvciBzZXRzIHBlciBmdW5jdGlvbiBhbmQgbWV0aG9kLlxuICogQHJldHVybnMge0xpZmV0aW1lRXhpdFtdfSBSZWFjaGFibGUgZXhpdHMuXG4gKi9cbmZ1bmN0aW9uIGFuYWx5emVTdGF0ZW1lbnQoc3RhdGVtZW50LCBzdGF0ZSwgZmFpbCwgbG9jYWxzLCBlcnJvckVmZmVjdHMpIHtcbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiTG9jYWxEZWNsYXJhdGlvblwiKSB7XG4gICAgY29uc3QgZmxvd3MgPSBldmFsdWF0ZUV4cHJlc3Npb24oc3RhdGVtZW50LmluaXRpYWxpemVyLCBjbG9uZVN0YXRlKHN0YXRlKSwgZmFpbCwgZXJyb3JFZmZlY3RzKVxuXG4gICAgaWYgKGlzT3duZWQoc3RhdGVtZW50LnR5cGUpKSB7XG4gICAgICBsb2NhbHMuYWRkKHN0YXRlbWVudC5uYW1lKVxuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzKSB7XG4gICAgICAgIGlmIChmbG93LmtpbmQgIT0gXCJub3JtYWxcIikgY29udGludWVcbiAgICAgICAgY29uc3Qgb3JpZ2luID0gc3RhdGVtZW50LmluaXRpYWxpemVyLmtpbmQgPT0gXCJPd25lZE1vdmVFeHByZXNzaW9uXCJcbiAgICAgICAgICA/IGZsb3cuc3RhdGUuZ2V0KHN0YXRlbWVudC5pbml0aWFsaXplci5leHByZXNzaW9uLm5hbWUpPy5vcmlnaW4gPz8gc3RhdGVtZW50LmluaXRpYWxpemVyLmxvY2F0aW9uXG4gICAgICAgICAgOiBzdGF0ZW1lbnQuaW5pdGlhbGl6ZXIubG9jYXRpb25cbiAgICAgICAgZmxvdy5zdGF0ZS5zZXQoc3RhdGVtZW50Lm5hbWUsIG9wZW5TdGF0ZShgbG9jYWw6JHtzdGF0ZW1lbnQubmFtZX1gLCBvcmlnaW4pKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmxvd3MubWFwKChmbG93KSA9PiAoey4uLmZsb3csIGxvY2F0aW9uOiBzdGF0ZW1lbnQubG9jYXRpb259KSlcbiAgfVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJFeHByZXNzaW9uU3RhdGVtZW50XCIgfHwgc3RhdGVtZW50LmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSB7XG4gICAgcmV0dXJuIGV2YWx1YXRlRXhwcmVzc2lvbihzdGF0ZW1lbnQuZXhwcmVzc2lvbiwgY2xvbmVTdGF0ZShzdGF0ZSksIGZhaWwsIGVycm9yRWZmZWN0cylcbiAgICAgIC5tYXAoKGZsb3cpID0+ICh7Li4uZmxvdywgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbn0pKVxuICB9XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIiB8fCBzdGF0ZW1lbnQua2luZCA9PSBcIlByaXZhdGVGaWVsZFdyaXRlU3RhdGVtZW50XCIpIHtcbiAgICByZXR1cm4gZXZhbHVhdGVFeHByZXNzaW9uKHN0YXRlbWVudC5leHByZXNzaW9uLCBjbG9uZVN0YXRlKHN0YXRlKSwgZmFpbCwgZXJyb3JFZmZlY3RzKVxuICAgICAgLm1hcCgoZmxvdykgPT4gKHsuLi5mbG93LCBsb2NhdGlvbjogc3RhdGVtZW50LmxvY2F0aW9ufSkpXG4gIH1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiUmV0dXJuU3RhdGVtZW50XCIpIHtcbiAgICBjb25zdCBmbG93cyA9IHN0YXRlbWVudC5leHByZXNzaW9uID8gZXZhbHVhdGVFeHByZXNzaW9uKHN0YXRlbWVudC5leHByZXNzaW9uLCBjbG9uZVN0YXRlKHN0YXRlKSwgZmFpbCwgZXJyb3JFZmZlY3RzKSA6XG4gICAgICAvKiogQHR5cGUge0xpZmV0aW1lRXhpdFtdfSAqLyAoW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZTogY2xvbmVTdGF0ZShzdGF0ZSl9XSlcbiAgICByZXR1cm4gZmxvd3MubWFwKChmbG93KSA9PiBmbG93LmtpbmQgPT0gXCJub3JtYWxcIlxuICAgICAgPyB7a2luZDogXCJyZXR1cm5cIiwgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbiwgc3RhdGU6IGZsb3cuc3RhdGV9XG4gICAgICA6IHsuLi5mbG93LCBsb2NhdGlvbjogc3RhdGVtZW50LmxvY2F0aW9ufSlcbiAgfVxuICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJSYWlzZVN0YXRlbWVudFwiKSB7XG4gICAgY29uc3QgZmxvd3MgPSBldmFsdWF0ZUV4cHJlc3Npb24oc3RhdGVtZW50LmVycm9yLm1lc3NhZ2UsIGNsb25lU3RhdGUoc3RhdGUpLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gICAgcmV0dXJuIGZsb3dzLm1hcCgoZmxvdykgPT4gZmxvdy5raW5kID09IFwibm9ybWFsXCJcbiAgICAgID8ge2Vycm9ySWQ6IHN0YXRlbWVudC5lcnJvci5lcnJvci5kZWNsYXJhdGlvbklkLCBraW5kOiBcInJhaXNlXCIsIGxvY2F0aW9uOiBzdGF0ZW1lbnQubG9jYXRpb24sIHN0YXRlOiBmbG93LnN0YXRlfVxuICAgICAgOiB7Li4uZmxvdywgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbn0pXG4gIH1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiSWZTdGF0ZW1lbnRcIikge1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBldmFsdWF0ZUV4cHJlc3Npb24oc3RhdGVtZW50LmNvbmRpdGlvbiwgY2xvbmVTdGF0ZShzdGF0ZSksIGZhaWwsIGVycm9yRWZmZWN0cylcbiAgICAvKiogQHR5cGUge0xpZmV0aW1lRXhpdFtdfSAqL1xuICAgIGNvbnN0IHJlc3VsdCA9IGNvbmRpdGlvbnMuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgIT0gXCJub3JtYWxcIilcblxuICAgIGZvciAoY29uc3QgY29uZGl0aW9uIG9mIGNvbmRpdGlvbnMuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIikpIHtcbiAgICAgIHJlc3VsdC5wdXNoKC4uLmFuYWx5emVCbG9jayhzdGF0ZW1lbnQuY29uc2VxdWVudCwgW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZTogY2xvbmVTdGF0ZShjb25kaXRpb24uc3RhdGUpfV0sIGZhaWwsXG4gICAgICAgIGVycm9yRWZmZWN0cykpXG4gICAgICBjb25zdCBhbHRlcm5hdGUgPSBzdGF0ZW1lbnQuYWx0ZXJuYXRlXG4gICAgICAgID8gYW5hbHl6ZUJsb2NrKHN0YXRlbWVudC5hbHRlcm5hdGUsIFt7a2luZDogXCJub3JtYWxcIiwgc3RhdGU6IGNsb25lU3RhdGUoY29uZGl0aW9uLnN0YXRlKX1dLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gICAgICAgIDogLyoqIEB0eXBlIHtMaWZldGltZUV4aXRbXX0gKi8gKFt7a2luZDogXCJub3JtYWxcIiwgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbiwgc3RhdGU6IGNsb25lU3RhdGUoY29uZGl0aW9uLnN0YXRlKX1dKVxuXG4gICAgICByZXN1bHQucHVzaCguLi5hbHRlcm5hdGUpXG4gICAgfVxuICAgIHJldHVybiBtZXJnZUVxdWl2YWxlbnROb3JtYWxzKHJlc3VsdCwgc3RhdGVtZW50LmxvY2F0aW9uLCBmYWlsKVxuICB9XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIlRyeVN0YXRlbWVudFwiKSB7XG4gICAgY29uc3QgYm9keUV4aXRzID0gYW5hbHl6ZUJsb2NrKHN0YXRlbWVudC5ib2R5LCBbe2tpbmQ6IFwibm9ybWFsXCIsIHN0YXRlOiBjbG9uZVN0YXRlKHN0YXRlKX1dLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gICAgLyoqIEB0eXBlIHtMaWZldGltZUV4aXRbXX0gKi9cbiAgICBjb25zdCByZXN1bHQgPSBib2R5RXhpdHMuZmlsdGVyKChmbG93KSA9PiBmbG93LmtpbmQgIT0gXCJyYWlzZVwiIHx8IGZsb3cuZXJyb3JJZCAhPSBzdGF0ZW1lbnQuY2F0Y2hUeXBlLmRlY2xhcmF0aW9uSWQpXG5cbiAgICBmb3IgKGNvbnN0IGNhdWdodCBvZiBib2R5RXhpdHMuZmlsdGVyKChmbG93KSA9PiBmbG93LmtpbmQgPT0gXCJyYWlzZVwiICYmIGZsb3cuZXJyb3JJZCA9PSBzdGF0ZW1lbnQuY2F0Y2hUeXBlLmRlY2xhcmF0aW9uSWQpKSB7XG4gICAgICByZXN1bHQucHVzaCguLi5hbmFseXplQmxvY2soc3RhdGVtZW50LmNhdGNoQm9keSwgW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZTogY2xvbmVTdGF0ZShjYXVnaHQuc3RhdGUpfV0sIGZhaWwsIGVycm9yRWZmZWN0cykpXG4gICAgfVxuICAgIHJldHVybiBtZXJnZUVxdWl2YWxlbnROb3JtYWxzKHJlc3VsdCwgc3RhdGVtZW50LmxvY2F0aW9uLCBmYWlsKVxuICB9XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIldoaWxlU3RhdGVtZW50XCIpIHtcbiAgICBjb25zdCBjb25kaXRpb25zID0gZXZhbHVhdGVFeHByZXNzaW9uKHN0YXRlbWVudC5jb25kaXRpb24sIGNsb25lU3RhdGUoc3RhdGUpLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gICAgLyoqIEB0eXBlIHtMaWZldGltZUV4aXRbXX0gKi9cbiAgICBjb25zdCByZXN1bHQgPSBjb25kaXRpb25zLmZpbHRlcigoe2tpbmR9KSA9PiBraW5kICE9IFwibm9ybWFsXCIpXG5cbiAgICBmb3IgKGNvbnN0IGNvbmRpdGlvbiBvZiBjb25kaXRpb25zLmZpbHRlcigoe2tpbmR9KSA9PiBraW5kID09IFwibm9ybWFsXCIpKSB7XG4gICAgICBjb25zdCBib2R5RXhpdHMgPSBhbmFseXplQmxvY2soc3RhdGVtZW50LmJvZHksIFt7a2luZDogXCJub3JtYWxcIiwgc3RhdGU6IGNsb25lU3RhdGUoY29uZGl0aW9uLnN0YXRlKX1dLCBmYWlsLFxuICAgICAgICBlcnJvckVmZmVjdHMpXG4gICAgICBmb3IgKGNvbnN0IGV4aXQgb2YgYm9keUV4aXRzKSB7XG4gICAgICAgIGlmIChleGl0LmtpbmQgPT0gXCJub3JtYWxcIiB8fCBleGl0LmtpbmQgPT0gXCJjb250aW51ZVwiKSByZXF1aXJlU2FtZVN0YXRlKGNvbmRpdGlvbi5zdGF0ZSwgZXhpdC5zdGF0ZSwgc3RhdGVtZW50LmxvY2F0aW9uLCBmYWlsKVxuICAgICAgICBlbHNlIGlmIChleGl0LmtpbmQgPT0gXCJicmVha1wiKSB7XG4gICAgICAgICAgcmVxdWlyZVNhbWVTdGF0ZShjb25kaXRpb24uc3RhdGUsIGV4aXQuc3RhdGUsIHN0YXRlbWVudC5sb2NhdGlvbiwgZmFpbClcbiAgICAgICAgICByZXN1bHQucHVzaCh7a2luZDogXCJub3JtYWxcIiwgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbiwgc3RhdGU6IGV4aXQuc3RhdGV9KVxuICAgICAgICB9IGVsc2UgcmVzdWx0LnB1c2goZXhpdClcbiAgICAgIH1cbiAgICAgIHJlc3VsdC5wdXNoKHtraW5kOiBcIm5vcm1hbFwiLCBsb2NhdGlvbjogc3RhdGVtZW50LmxvY2F0aW9uLCBzdGF0ZTogY29uZGl0aW9uLnN0YXRlfSlcbiAgICB9XG4gICAgcmV0dXJuIG1lcmdlRXF1aXZhbGVudE5vcm1hbHMocmVzdWx0LCBzdGF0ZW1lbnQubG9jYXRpb24sIGZhaWwpXG4gIH1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaFN0YXRlbWVudFwiIHx8IHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaE1hcFN0YXRlbWVudFwiKSB7XG4gICAgY29uc3Qgb3BlcmFuZCA9IHN0YXRlbWVudC5raW5kID09IFwiRm9yRWFjaFN0YXRlbWVudFwiID8gc3RhdGVtZW50Lmxpc3QgOiBzdGF0ZW1lbnQubWFwXG4gICAgY29uc3Qgb3BlcmFuZHMgPSBldmFsdWF0ZUV4cHJlc3Npb24ob3BlcmFuZCwgY2xvbmVTdGF0ZShzdGF0ZSksIGZhaWwsIGVycm9yRWZmZWN0cylcbiAgICAvKiogQHR5cGUge0xpZmV0aW1lRXhpdFtdfSAqL1xuICAgIGNvbnN0IHJlc3VsdCA9IG9wZXJhbmRzLmZpbHRlcigoe2tpbmR9KSA9PiBraW5kICE9IFwibm9ybWFsXCIpXG5cbiAgICBmb3IgKGNvbnN0IGV2YWx1YXRlZCBvZiBvcGVyYW5kcy5maWx0ZXIoKHtraW5kfSkgPT4ga2luZCA9PSBcIm5vcm1hbFwiKSkge1xuICAgICAgY29uc3QgYm9keUV4aXRzID0gYW5hbHl6ZUJsb2NrKHN0YXRlbWVudC5ib2R5LCBbe2tpbmQ6IFwibm9ybWFsXCIsIHN0YXRlOiBjbG9uZVN0YXRlKGV2YWx1YXRlZC5zdGF0ZSl9XSwgZmFpbCxcbiAgICAgICAgZXJyb3JFZmZlY3RzKVxuICAgICAgZm9yIChjb25zdCBleGl0IG9mIGJvZHlFeGl0cykge1xuICAgICAgICBpZiAoZXhpdC5raW5kID09IFwibm9ybWFsXCIgfHwgZXhpdC5raW5kID09IFwiY29udGludWVcIikgcmVxdWlyZVNhbWVTdGF0ZShldmFsdWF0ZWQuc3RhdGUsIGV4aXQuc3RhdGUsIHN0YXRlbWVudC5sb2NhdGlvbiwgZmFpbClcbiAgICAgICAgZWxzZSBpZiAoZXhpdC5raW5kID09IFwiYnJlYWtcIikge1xuICAgICAgICAgIHJlcXVpcmVTYW1lU3RhdGUoZXZhbHVhdGVkLnN0YXRlLCBleGl0LnN0YXRlLCBzdGF0ZW1lbnQubG9jYXRpb24sIGZhaWwpXG4gICAgICAgICAgcmVzdWx0LnB1c2goe2tpbmQ6IFwibm9ybWFsXCIsIGxvY2F0aW9uOiBzdGF0ZW1lbnQubG9jYXRpb24sIHN0YXRlOiBleGl0LnN0YXRlfSlcbiAgICAgICAgfSBlbHNlIHJlc3VsdC5wdXNoKGV4aXQpXG4gICAgICB9XG4gICAgICByZXN1bHQucHVzaCh7a2luZDogXCJub3JtYWxcIiwgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbiwgc3RhdGU6IGV2YWx1YXRlZC5zdGF0ZX0pXG4gICAgfVxuICAgIHJldHVybiBtZXJnZUVxdWl2YWxlbnROb3JtYWxzKHJlc3VsdCwgc3RhdGVtZW50LmxvY2F0aW9uLCBmYWlsKVxuICB9XG4gIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkJyZWFrU3RhdGVtZW50XCIpIHJldHVybiBbe2tpbmQ6IFwiYnJlYWtcIiwgbG9jYXRpb246IHN0YXRlbWVudC5sb2NhdGlvbiwgc3RhdGU6IGNsb25lU3RhdGUoc3RhdGUpfV1cbiAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiQ29udGludWVTdGF0ZW1lbnRcIikgcmV0dXJuIFt7a2luZDogXCJjb250aW51ZVwiLCBsb2NhdGlvbjogc3RhdGVtZW50LmxvY2F0aW9uLCBzdGF0ZTogY2xvbmVTdGF0ZShzdGF0ZSl9XVxuXG4gIHJldHVybiBbXVxufVxuXG4vKipcbiAqIEV2YWx1YXRlcyBvbmUgZXhwcmVzc2lvbiB3aXRoIGZhaWx1cmUgc3RhdGVzIGF0IGV4YWN0IGV2YWx1YXRpb24gYm91bmRhcmllcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBleHByZXNzaW9uIC0gRXhwcmVzc2lvbi5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gSW5jb21pbmcgb3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcGFyYW0ge3tmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PiwgbWV0aG9kczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+fX0gZXJyb3JFZmZlY3RzIC0gQ29tcGxldGUgZXNjYXBpbmcgZXJyb3Igc2V0cyBwZXIgZnVuY3Rpb24gYW5kIG1ldGhvZC5cbiAqIEByZXR1cm5zIHtMaWZldGltZUV4aXRbXX0gUmVhY2hhYmxlIGV4aXRzLlxuICovXG5mdW5jdGlvbiBldmFsdWF0ZUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgc3RhdGUsIGZhaWwsIGVycm9yRWZmZWN0cykge1xuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiT3duZWRNb3ZlRXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3Qgb3duZXIgPSByZXF1aXJlT3duZXIoZXhwcmVzc2lvbi5leHByZXNzaW9uLm5hbWUsIHN0YXRlLCBleHByZXNzaW9uLmxvY2F0aW9uLCBmYWlsKVxuXG4gICAgaWYgKG93bmVyLmtpbmQgPT0gXCJtb3ZlZFwiKSBmYWlsKFwiVVNFX0FGVEVSX01PVkVcIiwgYFJlc291cmNlICcke2V4cHJlc3Npb24uZXhwcmVzc2lvbi5uYW1lfScgd2FzIGFscmVhZHkgbW92ZWQuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICBpZiAob3duZXIua2luZCA9PSBcInRlcm1pbmFsXCIpIGZhaWwoXCJVU0VfQUZURVJfQ0xPU0VcIiwgYFJlc291cmNlICcke2V4cHJlc3Npb24uZXhwcmVzc2lvbi5uYW1lfScgaXMgdGVybWluYWwgYWZ0ZXIgY2xvc2UuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICBzdGF0ZS5zZXQoZXhwcmVzc2lvbi5leHByZXNzaW9uLm5hbWUsIHsuLi5vd25lciwgZGVzdGluYXRpb246IFwidHJhbnNmZXJcIiwga2luZDogXCJtb3ZlZFwifSlcbiAgICByZXR1cm4gW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZX1dXG4gIH1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIk93bmVkQm9ycm93RXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgbmFtZSA9IHBsYWNlTmFtZShleHByZXNzaW9uLmV4cHJlc3Npb24pXG4gICAgY29uc3Qgb3duZXIgPSByZXF1aXJlT3duZXIobmFtZSwgc3RhdGUsIGV4cHJlc3Npb24ubG9jYXRpb24sIGZhaWwpXG5cbiAgICBpZiAob3duZXIua2luZCA9PSBcIm1vdmVkXCIpIGZhaWwoXCJVU0VfQUZURVJfTU9WRVwiLCBgUmVzb3VyY2UgJyR7bmFtZX0nIHdhcyBtb3ZlZCBiZWZvcmUgdGhpcyBib3Jyb3cuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICByZXR1cm4gW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZX1dXG4gIH1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkVmZmVjdENhbGxFeHByZXNzaW9uXCIpIHJldHVybiBldmFsdWF0ZUVmZmVjdENhbGwoZXhwcmVzc2lvbiwgc3RhdGUsIGZhaWwsIGVycm9yRWZmZWN0cylcbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkNhbGxFeHByZXNzaW9uXCIgfHwgZXhwcmVzc2lvbi5raW5kID09IFwiTWV0aG9kQ2FsbEV4cHJlc3Npb25cIiB8fCBleHByZXNzaW9uLmtpbmQgPT0gXCJSZWZlcmVuY2VDb25zdHJ1Y3Rpb25cIikge1xuICAgIHJldHVybiBldmFsdWF0ZU9yZGluYXJ5Q2FsbChleHByZXNzaW9uLCBzdGF0ZSwgZmFpbCwgZXJyb3JFZmZlY3RzKVxuICB9XG5cbiAgLyoqIEB0eXBlIHtMaWZldGltZUV4aXRbXX0gKi9cbiAgbGV0IGZsb3dzID0gW3traW5kOiBcIm5vcm1hbFwiLCBzdGF0ZX1dXG4gIGZvciAoY29uc3QgY2hpbGQgb2YgZXhwcmVzc2lvbkNoaWxkcmVuKGV4cHJlc3Npb24pKSBmbG93cyA9IGV2YWx1YXRlRm9yRmxvd3MoY2hpbGQsIGZsb3dzLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gIHJldHVybiBmbG93c1xufVxuXG4vKipcbiAqIEFwcGxpZXMgb25lIGNhcGFiaWxpdHkgb3BlcmF0aW9uJ3MgZGVjbGFyZWQgb3duZXJzaGlwIGFuZCBmYWlsdXJlIGZsb3cuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRWZmZWN0Q2FsbEV4cHJlc3Npb259IGV4cHJlc3Npb24gLSBFZmZlY3QgY2FsbC5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gSW5jb21pbmcgb3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcGFyYW0ge3tmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PiwgbWV0aG9kczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+fX0gZXJyb3JFZmZlY3RzIC0gQ29tcGxldGUgZXNjYXBpbmcgZXJyb3Igc2V0cyBwZXIgZnVuY3Rpb24gYW5kIG1ldGhvZC5cbiAqIEByZXR1cm5zIHtMaWZldGltZUV4aXRbXX0gUmVhY2hhYmxlIGV4aXRzLlxuICovXG5mdW5jdGlvbiBldmFsdWF0ZUVmZmVjdENhbGwoZXhwcmVzc2lvbiwgc3RhdGUsIGZhaWwsIGVycm9yRWZmZWN0cykge1xuICAvKiogQHR5cGUge0xpZmV0aW1lRXhpdFtdfSAqL1xuICBsZXQgZmxvd3MgPSBbe2tpbmQ6IFwibm9ybWFsXCIsIHN0YXRlfV1cblxuICBmb3IgKGNvbnN0IGFyZ3VtZW50IG9mIGV4cHJlc3Npb24uYXJndW1lbnRzKSBmbG93cyA9IGV2YWx1YXRlRm9yRmxvd3MoYXJndW1lbnQsIGZsb3dzLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gIGNvbnN0IHJlc3VsdCA9IGZsb3dzLmZpbHRlcigoe2tpbmR9KSA9PiBraW5kICE9IFwibm9ybWFsXCIpXG4gIGNvbnN0IHJlc291cmNlRmxvdyA9IGV4cHJlc3Npb24ucmVzb2x1dGlvbi5yZXNvdXJjZUZsb3dcblxuICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIikpIHtcbiAgICBsZXQgb3BlcmF0aW9uU3RhdGUgPSBjbG9uZVN0YXRlKGZsb3cuc3RhdGUpXG4gICAgbGV0IHRlcm1pbmFsRmFpbHVyZVxuXG4gICAgaWYgKHJlc291cmNlRmxvdy5raW5kID09IFwiYm9ycm93XCIgfHwgcmVzb3VyY2VGbG93LmtpbmQgPT0gXCJjbG9zZVwiKSB7XG4gICAgICBjb25zdCBhcmd1bWVudCA9IGV4cHJlc3Npb24uYXJndW1lbnRzW3Jlc291cmNlRmxvdy5wYXJhbWV0ZXJJbmRleF1cbiAgICAgIGlmIChhcmd1bWVudC5raW5kICE9IFwiT3duZWRCb3Jyb3dFeHByZXNzaW9uXCIpIGZhaWwoXCJJTlZBTElEX1JFU09VUkNFX0JPUlJPV1wiLCBcIlJlc291cmNlIG9wZXJhdGlvbiBsYWNrcyBhbiBpbW1lZGlhdGUgYm9ycm93LlwiLCBhcmd1bWVudC5sb2NhdGlvbilcbiAgICAgIGNvbnN0IG5hbWUgPSBwbGFjZU5hbWUoYXJndW1lbnQuZXhwcmVzc2lvbilcbiAgICAgIGNvbnN0IG93bmVyID0gcmVxdWlyZU93bmVyKG5hbWUsIG9wZXJhdGlvblN0YXRlLCBhcmd1bWVudC5sb2NhdGlvbiwgZmFpbClcblxuICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJtb3ZlZFwiKSBmYWlsKFwiVVNFX0FGVEVSX01PVkVcIiwgYFJlc291cmNlICcke25hbWV9JyB3YXMgbW92ZWQgYmVmb3JlIHRoaXMgb3BlcmF0aW9uLmAsIGFyZ3VtZW50LmxvY2F0aW9uKVxuICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJ0ZXJtaW5hbFwiKSB0ZXJtaW5hbEZhaWx1cmUgPSByZXNvdXJjZUZsb3cudGVybWluYWxGYWlsdXJlSWRcbiAgICAgIGVsc2UgaWYgKHJlc291cmNlRmxvdy5raW5kID09IFwiY2xvc2VcIikgb3BlcmF0aW9uU3RhdGUuc2V0KG5hbWUsIHsuLi5vd25lciwgY2xvc2VTaXRlSWQ6IGV4cHJlc3Npb24uZWZmZWN0U2l0ZUlkLCBraW5kOiBcInRlcm1pbmFsXCJ9KVxuICAgIH1cbiAgICBpZiAodGVybWluYWxGYWlsdXJlKSB7XG4gICAgICByZXN1bHQucHVzaCh7ZXJyb3JJZDogdGVybWluYWxGYWlsdXJlLCBraW5kOiBcInJhaXNlXCIsIGxvY2F0aW9uOiBleHByZXNzaW9uLmxvY2F0aW9uLCBzdGF0ZTogb3BlcmF0aW9uU3RhdGV9KVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgY29uc3QgZmFpbHVyZUlkcyA9IGV4cHJlc3Npb24ucmVzb2x1dGlvbi5mYWlsdXJlSWRzLmZpbHRlcigoaWQpID0+XG4gICAgICByZXNvdXJjZUZsb3cua2luZCAhPSBcImJvcnJvd1wiICYmIHJlc291cmNlRmxvdy5raW5kICE9IFwiY2xvc2VcIiB8fCBpZCAhPSByZXNvdXJjZUZsb3cudGVybWluYWxGYWlsdXJlSWQpXG5cbiAgICByZXN1bHQucHVzaCh7a2luZDogXCJub3JtYWxcIiwgc3RhdGU6IGNsb25lU3RhdGUob3BlcmF0aW9uU3RhdGUpfSlcbiAgICBmb3IgKGNvbnN0IGVycm9ySWQgb2YgZmFpbHVyZUlkcykge1xuICAgICAgcmVzdWx0LnB1c2goe2Vycm9ySWQsIGtpbmQ6IFwicmFpc2VcIiwgbG9jYXRpb246IGV4cHJlc3Npb24ubG9jYXRpb24sIHN0YXRlOiBjbG9uZVN0YXRlKG9wZXJhdGlvblN0YXRlKX0pXG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRcbn1cblxuLyoqXG4gKiBBcHBsaWVzIGNhbGwtZW50cnkgb3duZXJzaGlwIGNvbW1pdCBzZW1hbnRpY3MgYWZ0ZXIgb3JkZXJlZCBhcmd1bWVudCBldmFsdWF0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkNhbGxFeHByZXNzaW9uIHwgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5NZXRob2RDYWxsRXhwcmVzc2lvbiB8IGltcG9ydChcIi4vdHlwZXMuanNcIikuUmVmZXJlbmNlQ29uc3RydWN0aW9ufSBleHByZXNzaW9uIC0gQ2FsbC5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gSW5jb21pbmcgb3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcGFyYW0ge3tmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PiwgbWV0aG9kczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+fX0gZXJyb3JFZmZlY3RzIC0gQ29tcGxldGUgZXNjYXBpbmcgZXJyb3Igc2V0cyBwZXIgZnVuY3Rpb24gYW5kIG1ldGhvZC5cbiAqIEByZXR1cm5zIHtMaWZldGltZUV4aXRbXX0gUmVhY2hhYmxlIGV4aXRzLlxuICovXG5mdW5jdGlvbiBldmFsdWF0ZU9yZGluYXJ5Q2FsbChleHByZXNzaW9uLCBzdGF0ZSwgZmFpbCwgZXJyb3JFZmZlY3RzKSB7XG4gIGNvbnN0IGFyZ3VtZW50c18gPSBleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiID8gW2V4cHJlc3Npb24ucmVjZWl2ZXIsIC4uLmV4cHJlc3Npb24uYXJndW1lbnRzXSA6IGV4cHJlc3Npb24uYXJndW1lbnRzXG4gIC8qKiBAdHlwZSB7TGlmZXRpbWVFeGl0W119ICovXG4gIGxldCBmbG93cyA9IFt7a2luZDogXCJub3JtYWxcIiwgc3RhdGV9XVxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBjb25zdCByZXNlcnZlZE1vdmVzID0gW11cblxuICBmb3IgKGNvbnN0IGFyZ3VtZW50IG9mIGFyZ3VtZW50c18pIHtcbiAgICBpZiAoYXJndW1lbnQua2luZCA9PSBcIk93bmVkTW92ZUV4cHJlc3Npb25cIikge1xuICAgICAgZm9yIChjb25zdCBmbG93IG9mIGZsb3dzLmZpbHRlcigoe2tpbmR9KSA9PiBraW5kID09IFwibm9ybWFsXCIpKSB7XG4gICAgICAgIGNvbnN0IG93bmVyID0gcmVxdWlyZU93bmVyKGFyZ3VtZW50LmV4cHJlc3Npb24ubmFtZSwgZmxvdy5zdGF0ZSwgYXJndW1lbnQubG9jYXRpb24sIGZhaWwpXG4gICAgICAgIGlmIChvd25lci5raW5kID09IFwibW92ZWRcIikgZmFpbChcIlVTRV9BRlRFUl9NT1ZFXCIsIGBSZXNvdXJjZSAnJHthcmd1bWVudC5leHByZXNzaW9uLm5hbWV9JyB3YXMgYWxyZWFkeSBtb3ZlZC5gLCBhcmd1bWVudC5sb2NhdGlvbilcbiAgICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJ0ZXJtaW5hbFwiKSBmYWlsKFwiVVNFX0FGVEVSX0NMT1NFXCIsIGBSZXNvdXJjZSAnJHthcmd1bWVudC5leHByZXNzaW9uLm5hbWV9JyBpcyB0ZXJtaW5hbCBhZnRlciBjbG9zZS5gLCBhcmd1bWVudC5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIGlmIChyZXNlcnZlZE1vdmVzLmluY2x1ZGVzKGFyZ3VtZW50LmV4cHJlc3Npb24ubmFtZSkpIHtcbiAgICAgICAgZmFpbChcIlJFU09VUkNFX0FMSUFTXCIsIGBSZXNvdXJjZSAnJHthcmd1bWVudC5leHByZXNzaW9uLm5hbWV9JyBjYW5ub3QgYmUgdHJhbnNmZXJyZWQgdG8gdHdvIHBhcmFtZXRlcnMuYCwgYXJndW1lbnQubG9jYXRpb24pXG4gICAgICB9XG4gICAgICByZXNlcnZlZE1vdmVzLnB1c2goYXJndW1lbnQuZXhwcmVzc2lvbi5uYW1lKVxuICAgIH0gZWxzZSBmbG93cyA9IGV2YWx1YXRlRm9yRmxvd3MoYXJndW1lbnQsIGZsb3dzLCBmYWlsLCBlcnJvckVmZmVjdHMpXG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gZmxvd3MuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgIT0gXCJub3JtYWxcIilcblxuICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIikpIHtcbiAgICBjb25zdCBlbnRlcmVkID0gY2xvbmVTdGF0ZShmbG93LnN0YXRlKVxuICAgIGZvciAoY29uc3QgbmFtZSBvZiByZXNlcnZlZE1vdmVzKSB7XG4gICAgICBjb25zdCBvd25lciA9IHJlcXVpcmVPd25lcihuYW1lLCBlbnRlcmVkLCBleHByZXNzaW9uLmxvY2F0aW9uLCBmYWlsKVxuICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJtb3ZlZFwiKSBmYWlsKFwiVVNFX0FGVEVSX01PVkVcIiwgYFJlc291cmNlICcke25hbWV9JyB3YXMgYWxyZWFkeSBtb3ZlZC5gLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJ0ZXJtaW5hbFwiKSBmYWlsKFwiVVNFX0FGVEVSX0NMT1NFXCIsIGBSZXNvdXJjZSAnJHtuYW1lfScgaXMgdGVybWluYWwgYWZ0ZXIgY2xvc2UuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgIGVudGVyZWQuc2V0KG5hbWUsIHsuLi5vd25lciwgZGVzdGluYXRpb246IFwiY2FsbGVlXCIsIGtpbmQ6IFwibW92ZWRcIn0pXG4gICAgfVxuICAgIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiICYmIGV4cHJlc3Npb24ucmVzb2x1dGlvbj8ucmVzb3VyY2VGbG93KSB7XG4gICAgICBjb25zdCByZWNlaXZlciA9IGV4cHJlc3Npb24ucmVjZWl2ZXIua2luZCA9PSBcIk93bmVkQm9ycm93RXhwcmVzc2lvblwiID8gZXhwcmVzc2lvbi5yZWNlaXZlci5leHByZXNzaW9uIDogZXhwcmVzc2lvbi5yZWNlaXZlclxuICAgICAgaWYgKHJlY2VpdmVyLmtpbmQgIT0gXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiICYmIHJlY2VpdmVyLmtpbmQgIT0gXCJSZWNlaXZlckV4cHJlc3Npb25cIiAmJiByZWNlaXZlci5raW5kICE9IFwiUHJpdmF0ZUZpZWxkUmVhZFwiKSB7XG4gICAgICAgIGZhaWwoXCJJTlZBTElEX1JFU09VUkNFX0JPUlJPV1wiLCBcIk93bmVkIG1ldGhvZCByZWNlaXZlciBtdXN0IGJlIGFuIGltbWVkaWF0ZSBib3Jyb3dlZCBwbGFjZS5cIiwgcmVjZWl2ZXIubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBjb25zdCBuYW1lID0gcGxhY2VOYW1lKHJlY2VpdmVyKVxuICAgICAgY29uc3Qgb3duZXIgPSByZXF1aXJlT3duZXIobmFtZSwgZW50ZXJlZCwgZXhwcmVzc2lvbi5sb2NhdGlvbiwgZmFpbClcblxuICAgICAgaWYgKG93bmVyLmtpbmQgPT0gXCJ0ZXJtaW5hbFwiKSB7XG4gICAgICAgIGlmIChleHByZXNzaW9uLnJlc29sdXRpb24ucmVzb3VyY2VGbG93LnRlcm1pbmFsRmFpbHVyZUlkKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goe2Vycm9ySWQ6IGV4cHJlc3Npb24ucmVzb2x1dGlvbi5yZXNvdXJjZUZsb3cudGVybWluYWxGYWlsdXJlSWQsIGtpbmQ6IFwicmFpc2VcIixcbiAgICAgICAgICAgIGxvY2F0aW9uOiBleHByZXNzaW9uLmxvY2F0aW9uLCBzdGF0ZTogZW50ZXJlZH0pXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuICAgICAgICBmYWlsKFwiVVNFX0FGVEVSX0NMT1NFXCIsIGBSZXNvdXJjZSAnJHtuYW1lfScgaXMgdGVybWluYWwgYWZ0ZXIgY2xvc2UuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICAgIH1cbiAgICAgIGlmIChleHByZXNzaW9uLnJlc29sdXRpb24ucmVzb3VyY2VGbG93LmtpbmQgPT0gXCJ0ZXJtaW5hbFwiKSB7XG4gICAgICAgIGVudGVyZWQuc2V0KG5hbWUsIHsuLi5vd25lciwgY2xvc2VTaXRlSWQ6IGV4cHJlc3Npb24uZWZmZWN0U2l0ZUlkID8/IGV4cHJlc3Npb24ubG9jYXRpb24sIGtpbmQ6IFwidGVybWluYWxcIn0pXG4gICAgICB9XG4gICAgfVxuICAgIHJlc3VsdC5wdXNoKHtraW5kOiBcIm5vcm1hbFwiLCBzdGF0ZTogY2xvbmVTdGF0ZShlbnRlcmVkKX0pXG4gICAgY29uc3QgZXNjYXBpbmcgPSBuZXcgU2V0KGV4cHJlc3Npb24uZmFpbHVyZUlkcyA/PyBbXSlcblxuICAgIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiKSB7XG4gICAgICBmb3IgKGNvbnN0IGVycm9ySWQgb2YgZXJyb3JFZmZlY3RzLmZ1bmN0aW9ucy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpID8/IFtdKSBlc2NhcGluZy5hZGQoZXJyb3JJZClcbiAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIk1ldGhvZENhbGxFeHByZXNzaW9uXCIpIHtcbiAgICAgIGZvciAoY29uc3QgZXJyb3JJZCBvZiBlcnJvckVmZmVjdHMubWV0aG9kcy5nZXQoZXhwcmVzc2lvbi5tZXRob2QpID8/IFtdKSBlc2NhcGluZy5hZGQoZXJyb3JJZClcbiAgICB9XG4gICAgZm9yIChjb25zdCBlcnJvcklkIG9mIGVzY2FwaW5nKSB7XG4gICAgICByZXN1bHQucHVzaCh7ZXJyb3JJZCwga2luZDogXCJyYWlzZVwiLCBsb2NhdGlvbjogZXhwcmVzc2lvbi5sb2NhdGlvbiwgc3RhdGU6IGNsb25lU3RhdGUoZW50ZXJlZCl9KVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8qKlxuICogRXZhbHVhdGVzIGEgY2hpbGQgZXhwcmVzc2lvbiBvbmx5IGFsb25nIG5vcm1hbCBpbmNvbWluZyBwYXRocy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBleHByZXNzaW9uIC0gQ2hpbGQgZXhwcmVzc2lvbi5cbiAqIEBwYXJhbSB7TGlmZXRpbWVFeGl0W119IGZsb3dzIC0gSW5jb21pbmcgcGF0aHMuXG4gKiBAcGFyYW0ge0xpZmV0aW1lRmFpbH0gZmFpbCAtIExvY2F0ZWQgZmFpbHVyZS5cbiAqIEBwYXJhbSB7e2Z1bmN0aW9uczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LCBtZXRob2RzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj59fSBlcnJvckVmZmVjdHMgLSBDb21wbGV0ZSBlc2NhcGluZyBlcnJvciBzZXRzIHBlciBmdW5jdGlvbiBhbmQgbWV0aG9kLlxuICogQHJldHVybnMge0xpZmV0aW1lRXhpdFtdfSBSZWFjaGFibGUgZXhpdHMuXG4gKi9cbmZ1bmN0aW9uIGV2YWx1YXRlRm9yRmxvd3MoZXhwcmVzc2lvbiwgZmxvd3MsIGZhaWwsIGVycm9yRWZmZWN0cykge1xuICBjb25zdCByZXN1bHQgPSBmbG93cy5maWx0ZXIoKHtraW5kfSkgPT4ga2luZCAhPSBcIm5vcm1hbFwiKVxuICBmb3IgKGNvbnN0IGZsb3cgb2YgZmxvd3MuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgPT0gXCJub3JtYWxcIikpIHtcbiAgICByZXN1bHQucHVzaCguLi5ldmFsdWF0ZUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgY2xvbmVTdGF0ZShmbG93LnN0YXRlKSwgZmFpbCwgZXJyb3JFZmZlY3RzKSlcbiAgfVxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8qKlxuICogUmV0dXJucyBub24tY2FsbCBleHByZXNzaW9uIGNoaWxkcmVuIGluIGV2YWx1YXRpb24gb3JkZXIuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gZXhwcmVzc2lvbiAtIFBhcmVudCBleHByZXNzaW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRXhwcmVzc2lvbltdfSBDaGlsZHJlbi5cbiAqL1xuZnVuY3Rpb24gZXhwcmVzc2lvbkNoaWxkcmVuKGV4cHJlc3Npb24pIHtcbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLmxlZnQsIGV4cHJlc3Npb24ucmlnaHRdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJVbmFyeUV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLm9wZXJhbmRdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJPcHRpb25hbFNvbWVcIikgcmV0dXJuIFtleHByZXNzaW9uLnZhbHVlXVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiT3B0aW9uYWxJc1ByZXNlbnRcIiB8fCBleHByZXNzaW9uLmtpbmQgPT0gXCJPcHRpb25hbFVud3JhcFwiKSByZXR1cm4gW2V4cHJlc3Npb24ub3BlcmFuZF1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkxpc3RMaXRlcmFsXCIpIHJldHVybiBleHByZXNzaW9uLmVsZW1lbnRzXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJNYXBMaXRlcmFsXCIgfHwgZXhwcmVzc2lvbi5raW5kID09IFwiT3JkZXJlZE1hcExpdGVyYWxcIikgcmV0dXJuIGV4cHJlc3Npb24uZW50cmllcy5tYXAoKHt2YWx1ZX0pID0+IHZhbHVlKVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTGlzdEluZGV4RXhwcmVzc2lvblwiKSByZXR1cm4gW2V4cHJlc3Npb24uY29sbGVjdGlvbiwgZXhwcmVzc2lvbi5pbmRleF1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIk1hcExvb2t1cEV4cHJlc3Npb25cIikgcmV0dXJuIFtleHByZXNzaW9uLmNvbGxlY3Rpb24sIGV4cHJlc3Npb24ua2V5XVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ29sbGVjdGlvblNpemVFeHByZXNzaW9uXCIpIHJldHVybiBbZXhwcmVzc2lvbi5jb2xsZWN0aW9uXVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiUmVjb3JkQ29uc3RydWN0aW9uXCIpIHJldHVybiBleHByZXNzaW9uLmFyZ3VtZW50c1xuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiTWVtYmVyUmVhZFwiKSByZXR1cm4gW2V4cHJlc3Npb24ucmVjZWl2ZXJdXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJQcml2YXRlRmllbGRSZWFkXCIpIHJldHVybiBbZXhwcmVzc2lvbi5yZWNlaXZlcl1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkVycm9yTWVzc2FnZVJlYWRcIikgcmV0dXJuIFtleHByZXNzaW9uLnJlY2VpdmVyXVxuICByZXR1cm4gW11cbn1cblxuLyoqXG4gKiBNZXJnZXMgbm9ybWFsIHBhdGhzIG9ubHkgYWZ0ZXIgcHJvdmluZyBpZGVudGljYWwgb3duZXJzaGlwIHN0YXRlcy5cbiAqIEBwYXJhbSB7TGlmZXRpbWVFeGl0W119IGZsb3dzIC0gQ2FuZGlkYXRlIHBhdGhzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBsb2NhdGlvbiAtIEpvaW4gbG9jYXRpb24uXG4gKiBAcGFyYW0ge0xpZmV0aW1lRmFpbH0gZmFpbCAtIExvY2F0ZWQgZmFpbHVyZS5cbiAqIEByZXR1cm5zIHtMaWZldGltZUV4aXRbXX0gTWVyZ2VkIHBhdGhzLlxuICovXG5mdW5jdGlvbiBtZXJnZUVxdWl2YWxlbnROb3JtYWxzKGZsb3dzLCBsb2NhdGlvbiwgZmFpbCkge1xuICBjb25zdCBub3JtYWwgPSBmbG93cy5maWx0ZXIoKHtraW5kfSkgPT4ga2luZCA9PSBcIm5vcm1hbFwiKVxuICBpZiAobm9ybWFsLmxlbmd0aCA+IDEpIHtcbiAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBub3JtYWwuc2xpY2UoMSkpIHJlcXVpcmVTYW1lU3RhdGUobm9ybWFsWzBdLnN0YXRlLCBjYW5kaWRhdGUuc3RhdGUsIGxvY2F0aW9uLCBmYWlsKVxuICB9XG4gIHJldHVybiBbLi4uZmxvd3MuZmlsdGVyKCh7a2luZH0pID0+IGtpbmQgIT0gXCJub3JtYWxcIiksIC4uLihub3JtYWwubGVuZ3RoID4gMCA/IFtub3JtYWxbMF1dIDogW10pXVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIGEgZmluaXRlIG93bmVyc2hpcCBpbnZhcmlhbnQgYXQgYSBicmFuY2ggb3IgbG9vcCBqb2luLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBPd25lclN0YXRlPn0gbGVmdCAtIEZpcnN0IG93bmVyc2hpcCBzdGF0ZS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHJpZ2h0IC0gU2Vjb25kIG93bmVyc2hpcCBzdGF0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBKb2luIGxvY2F0aW9uLlxuICogQHBhcmFtIHtMaWZldGltZUZhaWx9IGZhaWwgLSBMb2NhdGVkIGZhaWx1cmUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZVNhbWVTdGF0ZShsZWZ0LCByaWdodCwgbG9jYXRpb24sIGZhaWwpIHtcbiAgY29uc3QgbmFtZXMgPSBuZXcgU2V0KFsuLi5sZWZ0LmtleXMoKSwgLi4ucmlnaHQua2V5cygpXSlcbiAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgY29uc3QgbGVmdFN0YXRlID0gbGVmdC5nZXQobmFtZSlcbiAgICBjb25zdCByaWdodFN0YXRlID0gcmlnaHQuZ2V0KG5hbWUpXG4gICAgaWYgKGxlZnRTdGF0ZT8ua2luZCAhPSByaWdodFN0YXRlPy5raW5kIHx8IGxlZnRTdGF0ZT8ub3JpZ2luSWQgIT0gcmlnaHRTdGF0ZT8ub3JpZ2luSWQpIHtcbiAgICAgIGZhaWwoXCJSRVNPVVJDRV9TVEFURV9NSVNNQVRDSFwiLCBgUmVzb3VyY2UgJyR7bmFtZX0nIGhhcyBkaWZmZXJlbnQgb3duZXJzaGlwIHN0YXRlIGFjcm9zcyByZWFjaGFibGUgcGF0aHMuYCwgbG9jYXRpb24pXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUmVqZWN0cyBldmVyeSBvd25lZCB2YWx1ZSB0aGF0IGxlYXZlcyBpdHMgaW50cm9kdWNpbmcgc2NvcGUgb3Blbi5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gT3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gbmFtZXMgLSBPd25lcnMgaW50cm9kdWNlZCBpbiB0aGUgc2NvcGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gRXhpdCBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7TGlmZXRpbWVGYWlsfSBmYWlsIC0gTG9jYXRlZCBmYWlsdXJlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGNoZWNrTGVha3Moc3RhdGUsIG5hbWVzLCBsb2NhdGlvbiwgZmFpbCkge1xuICBmb3IgKGNvbnN0IG5hbWUgb2YgbmFtZXMpIHtcbiAgICBjb25zdCBvd25lciA9IHN0YXRlLmdldChuYW1lKVxuICAgIGlmIChvd25lcj8ua2luZCA9PSBcIm9wZW5cIikge1xuICAgICAgY29uc3Qgb3JpZ2luID0gb3duZXIub3JpZ2luXG4gICAgICBmYWlsKFwiTEVBS0VEX1JFU09VUkNFXCIsIGBPd25lZCByZXNvdXJjZSAnJHtuYW1lfScgcmVtYWlucyBvcGVuOyBhY3F1aXJlZCBhdCAke29yaWdpbi5maWxlbmFtZX06JHtvcmlnaW4uc3RhcnQubGluZX06JHtvcmlnaW4uc3RhcnQuY29sdW1ufS5gLCBsb2NhdGlvbilcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhbiBvd25lZCBwbGFjZSBpbiB0aGUgY3VycmVudCBzY29wZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gU3RhYmxlIHBsYWNlIG5hbWUuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIE93bmVyU3RhdGU+fSBzdGF0ZSAtIE93bmVyc2hpcCBzdGF0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBVc2UgbG9jYXRpb24uXG4gKiBAcGFyYW0ge0xpZmV0aW1lRmFpbH0gZmFpbCAtIExvY2F0ZWQgZmFpbHVyZS5cbiAqIEByZXR1cm5zIHtPd25lclN0YXRlfSBPd25lciBzdGF0ZS5cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZU93bmVyKG5hbWUsIHN0YXRlLCBsb2NhdGlvbiwgZmFpbCkge1xuICBjb25zdCBvd25lciA9IHN0YXRlLmdldChuYW1lKVxuICBpZiAoIW93bmVyKSByZXR1cm4gZmFpbChcIklOVkFMSURfUkVTT1VSQ0VfQk9SUk9XXCIsIGBObyBvd25lZCByZXNvdXJjZSBwbGFjZSAnJHtuYW1lfScgaXMgaW4gc2NvcGUuYCwgbG9jYXRpb24pXG4gIHJldHVybiBvd25lclxufVxuXG4vKipcbiAqIENvbnZlcnRzIGFuIGltbWVkaWF0ZSBvd25lZCBleHByZXNzaW9uIHRvIGEgc3RhYmxlIHBsYWNlIG5hbWUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuSWRlbnRpZmllckV4cHJlc3Npb24gfCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlY2VpdmVyRXhwcmVzc2lvbiB8IGltcG9ydChcIi4vdHlwZXMuanNcIikuUHJpdmF0ZUZpZWxkUmVhZH0gZXhwcmVzc2lvbiAtIE93bmVkIHBsYWNlLlxuICogQHJldHVybnMge3N0cmluZ30gUGxhY2UgaWRlbnRpdHkuXG4gKi9cbmZ1bmN0aW9uIHBsYWNlTmFtZShleHByZXNzaW9uKSB7XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiKSByZXR1cm4gZXhwcmVzc2lvbi5uYW1lXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJSZWNlaXZlckV4cHJlc3Npb25cIikgcmV0dXJuIFwidGhpc1wiXG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJQcml2YXRlRmllbGRSZWFkXCIpIHJldHVybiBgdGhpcy4ke2V4cHJlc3Npb24uZmllbGR9YFxuICByZXR1cm4gXCI8aW52YWxpZD5cIlxufVxuXG4vKipcbiAqIENyZWF0ZXMgb25lIG9wZW4gb3duZXJzaGlwIHN0YXRlLlxuICogQHBhcmFtIHtzdHJpbmd9IG9yaWdpbklkIC0gRGV0ZXJtaW5pc3RpYyBvcmlnaW4gaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IG9yaWdpbiAtIEFjcXVpc2l0aW9uIGxvY2F0aW9uLlxuICogQHJldHVybnMge093bmVyU3RhdGV9IE9wZW4gc3RhdGUuXG4gKi9cbmZ1bmN0aW9uIG9wZW5TdGF0ZShvcmlnaW5JZCwgb3JpZ2luKSB7XG4gIHJldHVybiB7a2luZDogXCJvcGVuXCIsIG9yaWdpbiwgb3JpZ2luSWR9XG59XG5cbi8qKlxuICogQ2xvbmVzIGFuIG93bmVyc2hpcCBzdGF0ZSBmb3IgYSBjb250cm9sLWZsb3cgZm9yay5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IHN0YXRlIC0gU3RhdGUgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7TWFwPHN0cmluZywgT3duZXJTdGF0ZT59IERldGFjaGVkIHN0YXRlLlxuICovXG5mdW5jdGlvbiBjbG9uZVN0YXRlKHN0YXRlKSB7XG4gIHJldHVybiBuZXcgTWFwKFsuLi5zdGF0ZV0ubWFwKChbbmFtZSwgdmFsdWVdKSA9PiBbbmFtZSwgey4uLnZhbHVlfV0pKVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgdHlwZSBjYXJyaWVzIGxpbmVhciBvd25lcnNoaXAuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNGdW5jdGlvblJldHVyblR5cGV9IHR5cGUgLSBTZW1hbnRpYyB0eXBlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHR5cGUgaXMgb3duZWQuXG4gKi9cbmZ1bmN0aW9uIGlzT3duZWQodHlwZSkge1xuICByZXR1cm4gdHlwZS5raW5kID09IFwiT3duZWRSZXNvdXJjZVR5cGVcIiB8fCB0eXBlLmtpbmQgPT0gXCJPd25lZFJlZmVyZW5jZVR5cGVcIlxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBtb2R1bGUgY29udGFpbnMgYW55IG93bmVkIHNlbWFudGljIHR5cGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFNlbWFudGljIG1vZHVsZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGxpZmV0aW1lIGFuYWx5c2lzIGlzIHJlcXVpcmVkLlxuICovXG5mdW5jdGlvbiBtb2R1bGVDb250YWluc093bmVkVHlwZShtb2R1bGUpIHtcbiAgY29uc3QgcGVuZGluZyA9IFsvKiogQHR5cGUge3Vua25vd259ICovIChtb2R1bGUpXVxuICBjb25zdCBzZWVuID0gbmV3IFNldCgpXG5cbiAgd2hpbGUgKHBlbmRpbmcubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IHZhbHVlID0gcGVuZGluZy5wb3AoKVxuXG4gICAgaWYgKCF2YWx1ZSB8fCB0eXBlb2YgdmFsdWUgIT0gXCJvYmplY3RcIiB8fCBzZWVuLmhhcyh2YWx1ZSkpIGNvbnRpbnVlXG4gICAgc2Vlbi5hZGQodmFsdWUpXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiAoUmVmbGVjdC5nZXQodmFsdWUsIFwia2luZFwiKSA9PSBcIk93bmVkUmVzb3VyY2VUeXBlXCIgfHxcbiAgICAgIFJlZmxlY3QuZ2V0KHZhbHVlLCBcImtpbmRcIikgPT0gXCJPd25lZFJlZmVyZW5jZVR5cGVcIikpIHJldHVybiB0cnVlXG4gICAgZm9yIChjb25zdCBba2V5LCBjaGlsZF0gb2YgT2JqZWN0LmVudHJpZXModmFsdWUpKSB7XG4gICAgICBpZiAoW1wibG9jYXRpb25cIiwgXCJwcm92ZW5hbmNlXCIsIFwic291cmNlUHJvdmVuYW5jZVwiXS5pbmNsdWRlcyhrZXkpKSBjb250aW51ZVxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY2hpbGQpKSBwZW5kaW5nLnB1c2goLi4uY2hpbGQpXG4gICAgICBlbHNlIGlmIChjaGlsZCAmJiB0eXBlb2YgY2hpbGQgPT0gXCJvYmplY3RcIikgcGVuZGluZy5wdXNoKGNoaWxkKVxuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2Vcbn1cbiJdfQ==
|