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,1167 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { isDenseArray } from "./array.js";
|
|
3
|
+
import { isSafeArtifactPath } from "./artifact-path.js";
|
|
4
|
+
import { SemantifoldDiagnostic } from "./diagnostic.js";
|
|
5
|
+
import { compareStdlibVersions, parseStdlibVersion, parseStdlibVersionRange, resolveStdlibModule, stdlibVersionSatisfies } from "./semantic/stdlib.js";
|
|
6
|
+
const facadeIdentityPattern = /^[a-z][a-z0-9.-]*$/u;
|
|
7
|
+
const moduleIdPattern = /^[a-z][a-z0-9_]*(?:[.-][a-z][a-z0-9_]*)*$/u;
|
|
8
|
+
const declarationNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
9
|
+
const supportedLanguages = new Set(["php", "ruby", "javascript", "typescript", "java"]);
|
|
10
|
+
const canonicalTypes = new Set(["boolean", "integer", "string", "void"]);
|
|
11
|
+
/**
|
|
12
|
+
* @typedef StdlibFacadeFunctionDeclaration
|
|
13
|
+
* @property {"function"} kind - Closed public declaration kind.
|
|
14
|
+
* @property {string} name - Exact source-visible symbol.
|
|
15
|
+
* @property {{name: string, type: string}[]} parameters - Ordered source signature.
|
|
16
|
+
* @property {string} returnType - Canonical result type.
|
|
17
|
+
* @property {string[]} effects - Closed public effects.
|
|
18
|
+
* @property {string[]} failures - Escaping canonical failure names.
|
|
19
|
+
* @property {("direct-call" | "unqualified-call" | "receiver-call")[]} forms - Accepted source call forms.
|
|
20
|
+
* @property {"not-applicable"} ownership - Initial scalar qualification ownership.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* @typedef StdlibFacadeClassDeclaration
|
|
24
|
+
* @property {"class"} kind - Closed public declaration kind.
|
|
25
|
+
* @property {string} name - Exact source-visible class symbol.
|
|
26
|
+
* @property {["constructor-call"]} forms - Accepted construction form.
|
|
27
|
+
* @property {"owned-reference"} ownership - Class instance ownership.
|
|
28
|
+
* @property {{effects: string[], failures: string[], ownership: "acquired", parameters: {name: string, type: string}[]}} constructor - Constructor contract.
|
|
29
|
+
* @property {{effects: string[], failures: string[], forms: ["receiver-call"], name: string, ownership: "borrowed" | "consumed", parameters: {name: string, type: string}[], returnType: string}[]} methods - Public instance methods.
|
|
30
|
+
*/
|
|
31
|
+
/** @typedef {StdlibFacadeFunctionDeclaration | StdlibFacadeClassDeclaration} StdlibFacadePublicDeclaration */
|
|
32
|
+
/**
|
|
33
|
+
* @typedef StdlibFacadeRecord
|
|
34
|
+
* @property {{identity: string, range: string}[]} dependencies - Facade-module dependencies.
|
|
35
|
+
* @property {string} identity - Versioned facade identity.
|
|
36
|
+
* @property {import("./semantic/types.js").SemanticLanguage} language - Source language.
|
|
37
|
+
* @property {({identity: string, kind: "module", symbols: string[]} | {forms: ("unqualified-call" | "receiver-call")[], identity: string, kind: "builtin", symbols: string[]})[]} nativeModules - Exact source native identities.
|
|
38
|
+
* @property {StdlibFacadePublicDeclaration[]} publicDeclarations - Public source surface.
|
|
39
|
+
* @property {{module: string, operations: string[], range: string}[]} requirements - Canonical-only requirements.
|
|
40
|
+
* @property {string} runtimeProfile - Exact compatible source/runtime profile.
|
|
41
|
+
* @property {{content: string, filename: string, id: string}} source - Executable compiler-owned source module.
|
|
42
|
+
* @property {string} version - Exact facade version.
|
|
43
|
+
* @property {"internal" | "public"} visibility - Native-selectable visibility.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* @typedef FacadeSourceNames
|
|
47
|
+
* @property {string} extension - Source filename extension.
|
|
48
|
+
* @property {string} nativeModule - Public native stdlib module identity.
|
|
49
|
+
* @property {string} publicName - Public native symbol.
|
|
50
|
+
* @property {string} unusedName - Unused-elimination fixture symbol.
|
|
51
|
+
* @property {string} unusedNativeModule - Unused-elimination fixture module.
|
|
52
|
+
* @property {string} probeSource - Public executable facade source.
|
|
53
|
+
* @property {string} runnerSource - Internal canonical runner source.
|
|
54
|
+
* @property {string} unusedSource - Unused executable facade source.
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* @typedef StdlibFacadeRegistry
|
|
58
|
+
* @property {readonly StdlibFacadeRecord[]} facades - Stable immutable facade records.
|
|
59
|
+
* @property {(language: string, nativeModule: string, symbol: string, range?: string) => StdlibFacadeRecord} resolveFacade - Exact native identity resolver.
|
|
60
|
+
* @property {(identity: string, language: string, range?: string) => StdlibFacadeRecord} resolveIdentity - Facade dependency resolver.
|
|
61
|
+
* @property {(language: string, nativeModule: string, range?: string) => StdlibFacadeRecord} resolveModule - Exact native module resolver.
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* Creates a detached immutable source-language facade registry.
|
|
65
|
+
* @param {unknown} records - Optional facade definitions; built-in qualification definitions by default.
|
|
66
|
+
* @returns {Readonly<StdlibFacadeRegistry>} Validated facade registry.
|
|
67
|
+
*/
|
|
68
|
+
export function createStdlibFacadeRegistry(records = builtinFacadeRecords()) {
|
|
69
|
+
if (!isDenseArray(records))
|
|
70
|
+
invalidFacade("Facade records must be an ordered dense array.");
|
|
71
|
+
/** @type {StdlibFacadeRecord[]} */
|
|
72
|
+
const facades = [];
|
|
73
|
+
/** @type {Map<string, Map<string, StdlibFacadeRecord>>} */
|
|
74
|
+
const byIdentity = new Map();
|
|
75
|
+
/** @type {Map<string, StdlibFacadeRecord[]>} */
|
|
76
|
+
const byNativeModule = new Map();
|
|
77
|
+
const sourceIds = new Map();
|
|
78
|
+
const sourceFilenames = new Map();
|
|
79
|
+
for (let index = 0; index < records.length; index += 1) {
|
|
80
|
+
const record = validateFacadeRecord(records[index]);
|
|
81
|
+
const identityKey = `${record.language}\0${record.identity}`;
|
|
82
|
+
const versions = byIdentity.get(identityKey) ?? new Map();
|
|
83
|
+
if (versions.has(record.version))
|
|
84
|
+
invalidFacade(`Duplicate facade '${record.identity}' version '${record.version}' for '${record.language}'.`);
|
|
85
|
+
if (sourceIds.has(record.source.id) && sourceIds.get(record.source.id) != identityKey) {
|
|
86
|
+
invalidFacade(`Duplicate facade source module identity '${record.source.id}'.`);
|
|
87
|
+
}
|
|
88
|
+
if (sourceFilenames.has(record.source.filename) && sourceFilenames.get(record.source.filename) != identityKey) {
|
|
89
|
+
invalidFacade(`Duplicate facade source filename '${record.source.filename}'.`);
|
|
90
|
+
}
|
|
91
|
+
versions.set(record.version, record);
|
|
92
|
+
byIdentity.set(identityKey, versions);
|
|
93
|
+
sourceIds.set(record.source.id, identityKey);
|
|
94
|
+
sourceFilenames.set(record.source.filename, identityKey);
|
|
95
|
+
facades.push(record);
|
|
96
|
+
for (const nativeModule of record.nativeModules) {
|
|
97
|
+
const nativeKey = `${record.language}\0${nativeModule.identity}`;
|
|
98
|
+
const nativeRecords = byNativeModule.get(nativeKey) ?? [];
|
|
99
|
+
nativeRecords.push(record);
|
|
100
|
+
byNativeModule.set(nativeKey, nativeRecords);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const record of facades) {
|
|
104
|
+
for (const dependency of record.dependencies) {
|
|
105
|
+
resolveIdentityFromStore(byIdentity, dependency.identity, record.language, dependency.range, record.identity);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
validateFacadeDependencyCycles(facades, byIdentity);
|
|
109
|
+
return Object.freeze(/** @type {StdlibFacadeRegistry} */ ({
|
|
110
|
+
facades: Object.freeze(facades),
|
|
111
|
+
resolveFacade(language, nativeModule, symbol, range) {
|
|
112
|
+
return resolveNativeFacadeFromStore(byNativeModule, language, nativeModule, symbol, range);
|
|
113
|
+
},
|
|
114
|
+
resolveIdentity(identity, language, range) {
|
|
115
|
+
return resolveIdentityFromStore(byIdentity, identity, language, range);
|
|
116
|
+
},
|
|
117
|
+
resolveModule(language, nativeModule, range) {
|
|
118
|
+
const records = byNativeModule.get(`${language}\0${nativeModule}`);
|
|
119
|
+
if (!records)
|
|
120
|
+
unprovedIdentity(language, nativeModule);
|
|
121
|
+
const identities = new Set(/** @type {StdlibFacadeRecord[]} */ (records).map(({ identity }) => identity));
|
|
122
|
+
if (identities.size != 1)
|
|
123
|
+
invalidFacade(`Native facade module '${nativeModule}' is ambiguous for '${language}'.`);
|
|
124
|
+
return selectFacadeVersion(new Map(/** @type {StdlibFacadeRecord[]} */ (records).map((record) => [record.version, record])),
|
|
125
|
+
/** @type {StdlibFacadeRecord} */ (records[0]).identity, language, range);
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Rejects cycles after every versioned dependency has resolved successfully.
|
|
131
|
+
* @param {StdlibFacadeRecord[]} facades - Validated facade records.
|
|
132
|
+
* @param {Map<string, Map<string, StdlibFacadeRecord>>} store - Records by language and identity.
|
|
133
|
+
* @returns {void}
|
|
134
|
+
*/
|
|
135
|
+
function validateFacadeDependencyCycles(facades, store) {
|
|
136
|
+
const active = new Set();
|
|
137
|
+
const complete = new Set();
|
|
138
|
+
/**
|
|
139
|
+
* Visits one exact selected facade version.
|
|
140
|
+
* @param {StdlibFacadeRecord} record - Facade record.
|
|
141
|
+
* @returns {void}
|
|
142
|
+
*/
|
|
143
|
+
function visit(record) {
|
|
144
|
+
const key = `${record.language}\0${record.identity}\0${record.version}`;
|
|
145
|
+
if (complete.has(key))
|
|
146
|
+
return;
|
|
147
|
+
if (active.has(key))
|
|
148
|
+
invalidFacade(`Facade dependency cycle includes '${record.identity}'.`);
|
|
149
|
+
active.add(key);
|
|
150
|
+
for (const dependency of record.dependencies) {
|
|
151
|
+
visit(resolveIdentityFromStore(store, dependency.identity, record.language, dependency.range, record.identity));
|
|
152
|
+
}
|
|
153
|
+
active.delete(key);
|
|
154
|
+
complete.add(key);
|
|
155
|
+
}
|
|
156
|
+
for (const record of facades)
|
|
157
|
+
visit(record);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Lists all built-in public and internal facade modules in stable order.
|
|
161
|
+
* @returns {readonly StdlibFacadeRecord[]} Immutable facade definitions.
|
|
162
|
+
*/
|
|
163
|
+
export function listStdlibFacades() {
|
|
164
|
+
return stdlibFacadeRegistry.facades;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolves one built-in facade from parser-proved native module and symbol identities.
|
|
168
|
+
* @param {string} language - Source language.
|
|
169
|
+
* @param {string} nativeModule - Exact native module identity.
|
|
170
|
+
* @param {string} symbol - Exact imported or qualified symbol.
|
|
171
|
+
* @param {string} [range] - Compatible facade version range.
|
|
172
|
+
* @returns {StdlibFacadeRecord} Immutable facade definition.
|
|
173
|
+
*/
|
|
174
|
+
export function resolveStdlibFacade(language, nativeModule, symbol, range) {
|
|
175
|
+
return stdlibFacadeRegistry.resolveFacade(language, nativeModule, symbol, range);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Resolves a dependency-first, cycle-free facade module closure.
|
|
179
|
+
* @param {StdlibFacadeRecord[]} roots - Parser-selected facade roots.
|
|
180
|
+
* @param {Readonly<StdlibFacadeRegistry>} [registry] - Facade registry.
|
|
181
|
+
* @returns {StdlibFacadeRecord[]} Stable dependency-first closure.
|
|
182
|
+
*/
|
|
183
|
+
export function resolveStdlibFacadeClosure(roots, registry = stdlibFacadeRegistry) {
|
|
184
|
+
const active = new Set();
|
|
185
|
+
const complete = new Set();
|
|
186
|
+
/** @type {StdlibFacadeRecord[]} */
|
|
187
|
+
const result = [];
|
|
188
|
+
/**
|
|
189
|
+
* Visits one selected facade and its declared dependencies.
|
|
190
|
+
* @param {StdlibFacadeRecord} record - Facade to visit.
|
|
191
|
+
* @returns {void}
|
|
192
|
+
*/
|
|
193
|
+
function visit(record) {
|
|
194
|
+
const key = `${record.language}\0${record.identity}\0${record.version}`;
|
|
195
|
+
if (complete.has(key))
|
|
196
|
+
return;
|
|
197
|
+
if (active.has(key))
|
|
198
|
+
invalidFacade(`Facade dependency cycle includes '${record.identity}'.`);
|
|
199
|
+
active.add(key);
|
|
200
|
+
for (const dependency of record.dependencies) {
|
|
201
|
+
visit(registry.resolveIdentity(dependency.identity, record.language, dependency.range));
|
|
202
|
+
}
|
|
203
|
+
active.delete(key);
|
|
204
|
+
complete.add(key);
|
|
205
|
+
result.push(record);
|
|
206
|
+
}
|
|
207
|
+
for (const root of roots)
|
|
208
|
+
visit(root);
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates the detached, deterministic program descriptor for one selected facade closure.
|
|
213
|
+
* @param {import("./semantic/types.js").SemanticLanguage} language - Source language profile.
|
|
214
|
+
* @param {StdlibFacadeRecord[]} facades - Dependency-first selected facade records.
|
|
215
|
+
* @returns {import("./semantic/types.js").StdlibFacadeProgramDescriptor} Plain program descriptor.
|
|
216
|
+
*/
|
|
217
|
+
export function stdlibFacadeProgramDescriptor(language, facades) {
|
|
218
|
+
return {
|
|
219
|
+
language,
|
|
220
|
+
modules: facades.map((facade) => ({
|
|
221
|
+
dependencies: facade.dependencies.map((dependency) => ({ ...dependency })),
|
|
222
|
+
identity: facade.identity,
|
|
223
|
+
nativeModules: facade.nativeModules.map((module) => ({ ...module,
|
|
224
|
+
...(module.kind == "builtin" ? { forms: [...module.forms] } : {}), symbols: [...module.symbols] })),
|
|
225
|
+
publicDeclarations: facade.publicDeclarations.map(detachPublicDeclaration),
|
|
226
|
+
requirements: facade.requirements.map((requirement) => ({ ...requirement, operations: [...requirement.operations] })),
|
|
227
|
+
runtimeProfile: facade.runtimeProfile,
|
|
228
|
+
sourceModule: facade.source.id,
|
|
229
|
+
version: facade.version,
|
|
230
|
+
visibility: facade.visibility
|
|
231
|
+
})),
|
|
232
|
+
schema: "SemantifoldStdlibFacades",
|
|
233
|
+
version: 1
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Derives compiler-owned semantic capability authority from selected facade requirements.
|
|
238
|
+
* The initial executable qualification corpus intentionally targets one canonical module.
|
|
239
|
+
* @param {StdlibFacadeRecord[]} records - Selected facade closure.
|
|
240
|
+
* @returns {{contract: {contractVersion: string, identity: string}, input: import("./semantic/types.js").CapabilityAuthorityInput} | {contracts: {contractVersion: string, identity: string}[], input: import("./semantic/types.js").CapabilityAuthorityInput} | null} Authority input.
|
|
241
|
+
*/
|
|
242
|
+
export function facadeCapabilityAuthority(records) {
|
|
243
|
+
const requirements = records.flatMap((record) => record.requirements);
|
|
244
|
+
if (requirements.length == 0)
|
|
245
|
+
return null;
|
|
246
|
+
const identities = new Set(requirements.map(({ module }) => module));
|
|
247
|
+
const ranges = new Set(requirements.map(({ range }) => range));
|
|
248
|
+
const task037 = records.some(({ identity }) => identity.startsWith("semantifold.task037."));
|
|
249
|
+
if (task037) {
|
|
250
|
+
const requirementByModule = new Map();
|
|
251
|
+
for (const requirement of requirements) {
|
|
252
|
+
const current = requirementByModule.get(requirement.module);
|
|
253
|
+
if (current && current.range != requirement.range)
|
|
254
|
+
invalidFacade("Task 037 facade requirements disagree on a canonical range.");
|
|
255
|
+
const operations = new Set(current?.operations ?? []);
|
|
256
|
+
for (const operation of requirement.operations)
|
|
257
|
+
operations.add(operation);
|
|
258
|
+
requirementByModule.set(requirement.module, { operations, range: requirement.range });
|
|
259
|
+
}
|
|
260
|
+
const modules = [...requirementByModule.entries()].map(([identity, requirement]) => {
|
|
261
|
+
const contract = resolveStdlibModule(identity, requirement.range);
|
|
262
|
+
return {
|
|
263
|
+
capabilities: [{
|
|
264
|
+
failures: contract.failures.map(({ name }) => ({ name })),
|
|
265
|
+
name: canonicalCapabilityName(identity),
|
|
266
|
+
operations: contract.operations.filter(({ name }) => requirement.operations.has(name)).map((operation) => ({
|
|
267
|
+
effects: /** @type {["host"]} */ ([...operation.effects]),
|
|
268
|
+
failures: operation.failures.map(detachCanonicalReference),
|
|
269
|
+
name: operation.name,
|
|
270
|
+
parameters: operation.parameters.map((parameter) => ({
|
|
271
|
+
name: parameter.name,
|
|
272
|
+
type: canonicalCapabilityParameterType(parameter.type)
|
|
273
|
+
})),
|
|
274
|
+
resourceFlow: detachResourceFlow(operation.resourceFlow),
|
|
275
|
+
returnType: canonicalCapabilityType(operation.returnType)
|
|
276
|
+
})),
|
|
277
|
+
resources: contract.resources.map(({ name }) => ({ name }))
|
|
278
|
+
}],
|
|
279
|
+
contractVersion: requirement.range,
|
|
280
|
+
identity
|
|
281
|
+
};
|
|
282
|
+
});
|
|
283
|
+
return {
|
|
284
|
+
contracts: modules.map(({ contractVersion, identity }) => ({ contractVersion, identity })),
|
|
285
|
+
input: { id: "semantifold.task037.blocking-tcp", modules, schema: "SemantifoldCapabilityAuthority", schemaVersion: 2 }
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
if (identities.size != 1 || ranges.size != 1) {
|
|
289
|
+
invalidFacade("The Task 036 qualification facade closure must resolve one canonical module and version range.");
|
|
290
|
+
}
|
|
291
|
+
const identity = requirements[0].module;
|
|
292
|
+
const contractVersion = requirements[0].range;
|
|
293
|
+
const contract = resolveStdlibModule(identity, contractVersion);
|
|
294
|
+
return {
|
|
295
|
+
contract: { contractVersion, identity },
|
|
296
|
+
input: {
|
|
297
|
+
capabilities: [{
|
|
298
|
+
failures: contract.failures.map(({ name }) => ({ name })),
|
|
299
|
+
name: "ResourceProbe",
|
|
300
|
+
operations: contract.operations.map((operation) => ({
|
|
301
|
+
effects: [...operation.effects],
|
|
302
|
+
failures: [...operation.failures],
|
|
303
|
+
name: operation.name,
|
|
304
|
+
parameters: operation.parameters.map((parameter) => ({
|
|
305
|
+
name: parameter.name,
|
|
306
|
+
type: canonicalCapabilityParameterType(parameter.type)
|
|
307
|
+
})),
|
|
308
|
+
resourceFlow: /** @type {import("./semantic/types.js").CapabilityResourceFlowInput} */ ({ ...operation.resourceFlow }),
|
|
309
|
+
returnType: canonicalCapabilityType(operation.returnType)
|
|
310
|
+
})),
|
|
311
|
+
resources: contract.resources.map(({ name }) => ({ name }))
|
|
312
|
+
}],
|
|
313
|
+
contractVersion,
|
|
314
|
+
id: identity,
|
|
315
|
+
schema: "SemantifoldCapabilityAuthority",
|
|
316
|
+
schemaVersion: 1
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Converts one registry contract type to a capability-authority input type.
|
|
322
|
+
* @param {string | import("./semantic/stdlib.js").CanonicalDeclarationReference} type - Canonical contract type.
|
|
323
|
+
* @returns {import("./semantic/types.js").FunctionReturnTypeName | {kind: "OwnedResourceType", resource: string | import("./semantic/types.js").CapabilityDeclarationReferenceInput} | {kind: "OptionalType", valueType: import("./semantic/types.js").SemanticTypeName}} Semantic authority type.
|
|
324
|
+
*/
|
|
325
|
+
function canonicalCapabilityType(type) {
|
|
326
|
+
if (typeof type != "string")
|
|
327
|
+
return { kind: "OwnedResourceType", resource: detachCanonicalReference(type) };
|
|
328
|
+
if (type == "void" || type == "boolean" || type == "integer" || type == "string")
|
|
329
|
+
return type;
|
|
330
|
+
if (type.startsWith("optional:"))
|
|
331
|
+
return { kind: "OptionalType",
|
|
332
|
+
valueType: /** @type {import("./semantic/types.js").SemanticTypeName} */ (type.slice("optional:".length)) };
|
|
333
|
+
return { kind: "OwnedResourceType", resource: type };
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Converts a non-void registry parameter type to capability-authority input.
|
|
337
|
+
* @param {string | import("./semantic/stdlib.js").CanonicalDeclarationReference} type - Canonical parameter type.
|
|
338
|
+
* @returns {import("./semantic/types.js").SemanticTypeName | {kind: "OwnedResourceType", resource: string} | {kind: "OptionalType", valueType: import("./semantic/types.js").SemanticTypeName}} Semantic parameter type.
|
|
339
|
+
*/
|
|
340
|
+
function canonicalCapabilityParameterType(type) {
|
|
341
|
+
const converted = canonicalCapabilityType(type);
|
|
342
|
+
if (converted == "void")
|
|
343
|
+
invalidFacade("Canonical facade requirement parameters cannot have void type.");
|
|
344
|
+
return /** @type {import("./semantic/types.js").SemanticTypeName | {kind: "OwnedResourceType", resource: string} | {kind: "OptionalType", valueType: import("./semantic/types.js").SemanticTypeName}} */ (converted);
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Resolves one dependency identity from a validated registry store.
|
|
348
|
+
* @param {Map<string, Map<string, StdlibFacadeRecord>>} store - Records by language and identity.
|
|
349
|
+
* @param {string} identity - Facade identity.
|
|
350
|
+
* @param {string} language - Source language.
|
|
351
|
+
* @param {string | undefined} range - Compatible range.
|
|
352
|
+
* @param {string} [owner] - Depending facade for diagnostics.
|
|
353
|
+
* @returns {StdlibFacadeRecord} Highest compatible record.
|
|
354
|
+
*/
|
|
355
|
+
function resolveIdentityFromStore(store, identity, language, range, owner) {
|
|
356
|
+
const versions = store.get(`${language}\0${identity}`);
|
|
357
|
+
if (!versions) {
|
|
358
|
+
invalidFacade(owner ? `Facade '${owner}' depends on unknown facade '${identity}' for '${language}'.` :
|
|
359
|
+
`Unknown facade identity '${identity}' for '${language}'.`);
|
|
360
|
+
}
|
|
361
|
+
return selectFacadeVersion(/** @type {Map<string, StdlibFacadeRecord>} */ (versions), identity, language, range);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Resolves one exact native identity from a validated registry store.
|
|
365
|
+
* @param {Map<string, StdlibFacadeRecord[]>} store - Records by language and native module.
|
|
366
|
+
* @param {string} language - Source language.
|
|
367
|
+
* @param {string} nativeModule - Exact parser-owned native module identity.
|
|
368
|
+
* @param {string} symbol - Exact source-visible symbol.
|
|
369
|
+
* @param {string | undefined} range - Compatible range.
|
|
370
|
+
* @returns {StdlibFacadeRecord} Highest compatible record.
|
|
371
|
+
*/
|
|
372
|
+
function resolveNativeFacadeFromStore(store, language, nativeModule, symbol, range) {
|
|
373
|
+
if (!supportedLanguages.has(language) || typeof nativeModule != "string" || nativeModule.length == 0) {
|
|
374
|
+
unprovedIdentity(language, nativeModule);
|
|
375
|
+
}
|
|
376
|
+
const moduleRecords = store.get(`${language}\0${nativeModule}`);
|
|
377
|
+
if (!moduleRecords)
|
|
378
|
+
unprovedIdentity(language, nativeModule);
|
|
379
|
+
const symbolRecords = /** @type {StdlibFacadeRecord[]} */ (moduleRecords).filter((record) => record.nativeModules.some((module) => module.identity == nativeModule && module.symbols.includes(symbol)));
|
|
380
|
+
if (symbolRecords.length == 0)
|
|
381
|
+
unsupportedMember(language, nativeModule, symbol);
|
|
382
|
+
const identities = new Set(symbolRecords.map(({ identity }) => identity));
|
|
383
|
+
if (identities.size != 1)
|
|
384
|
+
invalidFacade(`Native facade identity '${nativeModule}#${symbol}' is ambiguous for '${language}'.`);
|
|
385
|
+
const versions = new Map(symbolRecords.map((record) => [record.version, record]));
|
|
386
|
+
return selectFacadeVersion(versions, symbolRecords[0].identity, language, range);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Selects the highest facade version satisfying a canonical range.
|
|
390
|
+
* @param {Map<string, StdlibFacadeRecord>} versions - Records by exact version.
|
|
391
|
+
* @param {string} identity - Facade identity.
|
|
392
|
+
* @param {string} language - Source language.
|
|
393
|
+
* @param {string | undefined} range - Compatible range.
|
|
394
|
+
* @returns {StdlibFacadeRecord} Selected record.
|
|
395
|
+
*/
|
|
396
|
+
function selectFacadeVersion(versions, identity, language, range) {
|
|
397
|
+
const parsedRange = range === undefined ? { lower: /** @type {[number, number, number]} */ ([0, 0, 0]), upper: null } :
|
|
398
|
+
parseStdlibVersionRange(range);
|
|
399
|
+
if (!parsedRange)
|
|
400
|
+
facadeVersionMalformed(language, String(range));
|
|
401
|
+
/** @type {[number, number, number] | undefined} */
|
|
402
|
+
let selected;
|
|
403
|
+
for (const version of versions.keys()) {
|
|
404
|
+
const parsed = /** @type {[number, number, number]} */ (parseStdlibVersion(version));
|
|
405
|
+
if (stdlibVersionSatisfies(parsed, parsedRange) && (!selected || compareStdlibVersions(parsed, selected) > 0))
|
|
406
|
+
selected = parsed;
|
|
407
|
+
}
|
|
408
|
+
if (!selected)
|
|
409
|
+
facadeVersionIncompatible(language, identity);
|
|
410
|
+
return /** @type {StdlibFacadeRecord} */ (versions.get(selected.join(".")));
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Validates and detaches one executable facade record.
|
|
414
|
+
* @param {unknown} candidate - Candidate record.
|
|
415
|
+
* @returns {StdlibFacadeRecord} Detached frozen record.
|
|
416
|
+
*/
|
|
417
|
+
function validateFacadeRecord(candidate) {
|
|
418
|
+
if (!isPlainObject(candidate))
|
|
419
|
+
invalidFacade("Every facade record must be a plain object.");
|
|
420
|
+
requireKeys(candidate, ["dependencies", "identity", "language", "nativeModules", "publicDeclarations", "requirements",
|
|
421
|
+
"runtimeProfile", "source", "version", "visibility"], "facade record");
|
|
422
|
+
const identity = requireString(candidate.identity, "Facade identity");
|
|
423
|
+
const language = requireString(candidate.language, "Facade language");
|
|
424
|
+
const version = requireString(candidate.version, "Facade version");
|
|
425
|
+
const runtimeProfile = requireString(candidate.runtimeProfile, "Facade runtime profile");
|
|
426
|
+
const visibility = candidate.visibility;
|
|
427
|
+
if (!facadeIdentityPattern.test(identity))
|
|
428
|
+
invalidFacade(`Facade identity '${identity}' is invalid.`);
|
|
429
|
+
if (!supportedLanguages.has(language))
|
|
430
|
+
invalidFacade(`Facade language '${language}' is outside the adopted cohort.`);
|
|
431
|
+
if (!parseStdlibVersion(version))
|
|
432
|
+
invalidFacade(`Facade version '${version}' is invalid.`);
|
|
433
|
+
if (!/^[a-z][a-z0-9.-]*$/u.test(runtimeProfile))
|
|
434
|
+
invalidFacade(`Facade runtime profile '${runtimeProfile}' is invalid.`);
|
|
435
|
+
if (visibility != "public" && visibility != "internal")
|
|
436
|
+
invalidFacade(`Facade '${identity}' has invalid visibility.`);
|
|
437
|
+
const source = validateSource(candidate.source, identity, language);
|
|
438
|
+
const publicDeclarations = validatePublicDeclarations(candidate.publicDeclarations, identity);
|
|
439
|
+
const nativeModules = validateNativeModules(candidate.nativeModules, identity, publicDeclarations);
|
|
440
|
+
const requirements = validateRequirements(candidate.requirements, identity);
|
|
441
|
+
const dependencies = validateDependencies(candidate.dependencies, identity);
|
|
442
|
+
if (visibility == "public" && (publicDeclarations.length == 0 || nativeModules.length == 0)) {
|
|
443
|
+
invalidFacade(`Public facade '${identity}' requires declarations and native identities.`);
|
|
444
|
+
}
|
|
445
|
+
if (visibility == "internal" && nativeModules.length > 0)
|
|
446
|
+
invalidFacade(`Internal facade '${identity}' cannot expose native identities.`);
|
|
447
|
+
return deepFreeze({
|
|
448
|
+
dependencies,
|
|
449
|
+
identity,
|
|
450
|
+
language: /** @type {import("./semantic/types.js").SemanticLanguage} */ (language),
|
|
451
|
+
nativeModules,
|
|
452
|
+
publicDeclarations,
|
|
453
|
+
requirements,
|
|
454
|
+
runtimeProfile,
|
|
455
|
+
source,
|
|
456
|
+
version,
|
|
457
|
+
visibility: /** @type {"internal" | "public"} */ (visibility)
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Validates one compiler-owned executable facade source.
|
|
462
|
+
* @param {unknown} candidate - Candidate source descriptor.
|
|
463
|
+
* @param {string} identity - Owning facade identity.
|
|
464
|
+
* @param {string} language - Facade source language.
|
|
465
|
+
* @returns {{content: string, filename: string, id: string}} Validated source descriptor.
|
|
466
|
+
*/
|
|
467
|
+
function validateSource(candidate, identity, language) {
|
|
468
|
+
if (!isPlainObject(candidate))
|
|
469
|
+
invalidFacade(`Facade '${identity}' requires an executable source descriptor.`);
|
|
470
|
+
requireKeys(candidate, ["content", "filename", "id"], `facade '${identity}' source`);
|
|
471
|
+
const content = requireString(candidate.content, `Facade '${identity}' source content`);
|
|
472
|
+
const filename = requireString(candidate.filename, `Facade '${identity}' source filename`);
|
|
473
|
+
const id = requireString(candidate.id, `Facade '${identity}' source module identity`);
|
|
474
|
+
if (content.length == 0 || !isSafeArtifactPath(filename) || !filename.startsWith(`__semantifold_facades__/${language}/`) ||
|
|
475
|
+
!moduleIdPattern.test(id) || !id.startsWith(`semantifold.facade.${language}.`)) {
|
|
476
|
+
invalidFacade(`Facade '${identity}' has an invalid compiler-owned source descriptor.`);
|
|
477
|
+
}
|
|
478
|
+
return { content, filename, id };
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Validates one facade's closed public declaration surface.
|
|
482
|
+
* @param {unknown} candidate - Candidate declarations.
|
|
483
|
+
* @param {string} identity - Owning facade identity.
|
|
484
|
+
* @returns {StdlibFacadePublicDeclaration[]} Validated declarations.
|
|
485
|
+
*/
|
|
486
|
+
function validatePublicDeclarations(candidate, identity) {
|
|
487
|
+
if (!isDenseArray(candidate))
|
|
488
|
+
invalidFacade(`Facade '${identity}' public declarations must be a dense array.`);
|
|
489
|
+
const names = new Set();
|
|
490
|
+
return candidate.map((value) => {
|
|
491
|
+
if (!isPlainObject(value))
|
|
492
|
+
invalidFacade(`Facade '${identity}' public declarations must be plain objects.`);
|
|
493
|
+
const name = requireString(value.name, `Facade '${identity}' declaration name`);
|
|
494
|
+
if (!declarationNamePattern.test(name) || names.has(name)) {
|
|
495
|
+
invalidFacade(`Facade '${identity}' has an invalid or duplicate public declaration.`);
|
|
496
|
+
}
|
|
497
|
+
names.add(name);
|
|
498
|
+
if (value.kind == "class")
|
|
499
|
+
return validatePublicClass(value, identity, name);
|
|
500
|
+
requireKeys(value, ["effects", "failures", "forms", "kind", "name", "ownership", "parameters", "returnType"], `facade '${identity}' public declaration`);
|
|
501
|
+
if (value.kind != "function")
|
|
502
|
+
invalidFacade(`Facade '${identity}' has an invalid public declaration kind.`);
|
|
503
|
+
if (!isDenseArray(value.effects) || !value.effects.every((effect) => effect == "host") || new Set(value.effects).size != value.effects.length ||
|
|
504
|
+
!isDenseArray(value.failures) || !value.failures.every((failure) => typeof failure == "string" && declarationNamePattern.test(failure)) ||
|
|
505
|
+
!isDenseArray(value.forms) || value.forms.length == 0 || !value.forms.every((form) => typeof form == "string" && ["direct-call", "unqualified-call", "receiver-call"].includes(form)) ||
|
|
506
|
+
new Set(value.forms).size != value.forms.length ||
|
|
507
|
+
value.ownership != "not-applicable" ||
|
|
508
|
+
!isDenseArray(value.parameters))
|
|
509
|
+
invalidFacade(`Facade '${identity}' declaration '${name}' has an invalid public contract.`);
|
|
510
|
+
const parameters = validateFacadeParameters(value.parameters, identity, name);
|
|
511
|
+
const returnType = requireString(value.returnType, `Facade '${identity}' return type`);
|
|
512
|
+
if (!isFacadeType(returnType, true))
|
|
513
|
+
invalidFacade(`Facade '${identity}' declaration '${name}' has an invalid return type.`);
|
|
514
|
+
return {
|
|
515
|
+
effects: /** @type {string[]} */ ([...value.effects]),
|
|
516
|
+
failures: /** @type {string[]} */ ([...value.failures]),
|
|
517
|
+
forms: /** @type {("direct-call" | "unqualified-call" | "receiver-call")[]} */ ([...value.forms]),
|
|
518
|
+
kind: /** @type {const} */ ("function"),
|
|
519
|
+
name,
|
|
520
|
+
ownership: /** @type {const} */ ("not-applicable"),
|
|
521
|
+
parameters,
|
|
522
|
+
returnType
|
|
523
|
+
};
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Validates the exact native module and symbol identities selecting a facade.
|
|
528
|
+
* @param {unknown} candidate - Candidate native modules.
|
|
529
|
+
* @param {string} identity - Owning facade identity.
|
|
530
|
+
* @param {StdlibFacadePublicDeclaration[]} declarations - Validated public surface.
|
|
531
|
+
* @returns {({identity: string, kind: "module", symbols: string[]} | {forms: ("unqualified-call" | "receiver-call")[], identity: string, kind: "builtin", symbols: string[]})[]} Validated native identities.
|
|
532
|
+
*/
|
|
533
|
+
function validateNativeModules(candidate, identity, declarations) {
|
|
534
|
+
if (!isDenseArray(candidate))
|
|
535
|
+
invalidFacade(`Facade '${identity}' native modules must be a dense array.`);
|
|
536
|
+
const modules = new Set();
|
|
537
|
+
const publicNames = new Set(declarations.map(({ name }) => name));
|
|
538
|
+
return candidate.map((value) => {
|
|
539
|
+
if (!isPlainObject(value))
|
|
540
|
+
invalidFacade(`Facade '${identity}' native modules must be plain objects.`);
|
|
541
|
+
const builtin = value.kind == "builtin";
|
|
542
|
+
requireKeys(value, builtin ? ["forms", "identity", "kind", "symbols"] : ["identity", "kind", "symbols"], `facade '${identity}' native module`);
|
|
543
|
+
const moduleIdentity = requireString(value.identity, `Facade '${identity}' native module identity`);
|
|
544
|
+
if (value.kind != "module" && value.kind != "builtin" || modules.has(moduleIdentity) ||
|
|
545
|
+
!isDenseArray(value.symbols) || value.symbols.length == 0 ||
|
|
546
|
+
!value.symbols.every((symbol) => typeof symbol == "string" && publicNames.has(symbol)) ||
|
|
547
|
+
new Set(value.symbols).size != value.symbols.length) {
|
|
548
|
+
invalidFacade(`Facade '${identity}' has an invalid native module declaration.`);
|
|
549
|
+
}
|
|
550
|
+
if (builtin && (!isDenseArray(value.forms) || value.forms.length == 0 ||
|
|
551
|
+
!value.forms.every((form) => form == "unqualified-call" || form == "receiver-call") ||
|
|
552
|
+
new Set(value.forms).size != value.forms.length))
|
|
553
|
+
invalidFacade(`Facade '${identity}' has invalid builtin forms.`);
|
|
554
|
+
modules.add(moduleIdentity);
|
|
555
|
+
return builtin
|
|
556
|
+
? { forms: /** @type {("unqualified-call" | "receiver-call")[]} */ ([... /** @type {unknown[]} */(value.forms)]), identity: moduleIdentity,
|
|
557
|
+
kind: /** @type {const} */ ("builtin"), symbols: /** @type {string[]} */ ([...value.symbols]) }
|
|
558
|
+
: { identity: moduleIdentity, kind: /** @type {const} */ ("module"), symbols: /** @type {string[]} */ ([...value.symbols]) };
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Validates canonical-only facade capability requirements.
|
|
563
|
+
* @param {unknown} candidate - Candidate requirements.
|
|
564
|
+
* @param {string} identity - Owning facade identity.
|
|
565
|
+
* @returns {{module: string, operations: string[], range: string}[]} Validated requirements.
|
|
566
|
+
*/
|
|
567
|
+
function validateRequirements(candidate, identity) {
|
|
568
|
+
if (!isDenseArray(candidate))
|
|
569
|
+
invalidFacade(`Facade '${identity}' requirements must be a dense array.`);
|
|
570
|
+
const modules = new Set();
|
|
571
|
+
return candidate.map((value) => {
|
|
572
|
+
if (!isPlainObject(value))
|
|
573
|
+
invalidFacade(`Facade '${identity}' requirements must be plain objects.`);
|
|
574
|
+
requireKeys(value, ["module", "operations", "range"], `facade '${identity}' requirement`);
|
|
575
|
+
const module = requireString(value.module, `Facade '${identity}' canonical module`);
|
|
576
|
+
const range = requireString(value.range, `Facade '${identity}' canonical range`);
|
|
577
|
+
if (modules.has(module) || !parseStdlibVersionRange(range) || !isDenseArray(value.operations) || value.operations.length == 0 ||
|
|
578
|
+
!value.operations.every((operation) => typeof operation == "string" && declarationNamePattern.test(operation)) ||
|
|
579
|
+
new Set(value.operations).size != value.operations.length)
|
|
580
|
+
invalidFacade(`Facade '${identity}' has an invalid canonical requirement.`);
|
|
581
|
+
const contract = resolveStdlibModule(module, range);
|
|
582
|
+
const declared = new Set(contract.operations.map(({ name }) => name));
|
|
583
|
+
if (! /** @type {string[]} */(value.operations).every((operation) => declared.has(operation))) {
|
|
584
|
+
invalidFacade(`Facade '${identity}' requires an undeclared canonical operation.`);
|
|
585
|
+
}
|
|
586
|
+
modules.add(module);
|
|
587
|
+
return { module, operations: /** @type {string[]} */ ([...value.operations]), range };
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Validates versioned same-language facade dependencies.
|
|
592
|
+
* @param {unknown} candidate - Candidate dependencies.
|
|
593
|
+
* @param {string} identity - Owning facade identity.
|
|
594
|
+
* @returns {{identity: string, range: string}[]} Validated dependencies.
|
|
595
|
+
*/
|
|
596
|
+
function validateDependencies(candidate, identity) {
|
|
597
|
+
if (!isDenseArray(candidate))
|
|
598
|
+
invalidFacade(`Facade '${identity}' dependencies must be a dense array.`);
|
|
599
|
+
const identities = new Set();
|
|
600
|
+
return candidate.map((value) => {
|
|
601
|
+
if (!isPlainObject(value))
|
|
602
|
+
invalidFacade(`Facade '${identity}' dependencies must be plain objects.`);
|
|
603
|
+
requireKeys(value, ["identity", "range"], `facade '${identity}' dependency`);
|
|
604
|
+
const dependencyIdentity = requireString(value.identity, `Facade '${identity}' dependency identity`);
|
|
605
|
+
const range = requireString(value.range, `Facade '${identity}' dependency range`);
|
|
606
|
+
if (!facadeIdentityPattern.test(dependencyIdentity) || dependencyIdentity == identity || identities.has(dependencyIdentity) ||
|
|
607
|
+
!parseStdlibVersionRange(range))
|
|
608
|
+
invalidFacade(`Facade '${identity}' has an invalid dependency.`);
|
|
609
|
+
identities.add(dependencyIdentity);
|
|
610
|
+
return { identity: dependencyIdentity, range };
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Builds the bounded original-five qualification facade definitions.
|
|
615
|
+
* @returns {unknown[]} Unvalidated built-in qualification facade definitions.
|
|
616
|
+
*/
|
|
617
|
+
function builtinFacadeRecords() {
|
|
618
|
+
return ["php", "ruby", "javascript", "typescript", "java"].flatMap((language) => builtinLanguageFacades(language))
|
|
619
|
+
.concat(builtinTask037RubyFacades());
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Builds one source language's public, internal, and unreachable qualification facades.
|
|
623
|
+
* @param {string} language - Source language.
|
|
624
|
+
* @returns {unknown[]} Language facade definitions.
|
|
625
|
+
*/
|
|
626
|
+
function builtinLanguageFacades(language) {
|
|
627
|
+
const names = facadeNames(language);
|
|
628
|
+
const base = `semantifold.task036.${language}`;
|
|
629
|
+
const sourceBase = `semantifold.facade.${language}`;
|
|
630
|
+
const sourceDirectory = `__semantifold_facades__/${language}`;
|
|
631
|
+
const probeFilename = language == "java" ? `${sourceDirectory}/semantifold/facade/java/probe/Probe.java` :
|
|
632
|
+
`${sourceDirectory}/probe.${names.extension}`;
|
|
633
|
+
const runnerFilename = language == "java" ? `${sourceDirectory}/semantifold/facade/java/proberunner/ProbeRunner.java` :
|
|
634
|
+
`${sourceDirectory}/probe-runner.${names.extension}`;
|
|
635
|
+
const unusedFilename = language == "java" ? `${sourceDirectory}/semantifold/facade/java/unused/Unused.java` :
|
|
636
|
+
`${sourceDirectory}/unused.${names.extension}`;
|
|
637
|
+
return [{
|
|
638
|
+
dependencies: [{ identity: `${base}.probe-runner`, range: "1" }],
|
|
639
|
+
identity: `${base}.probe`,
|
|
640
|
+
language,
|
|
641
|
+
nativeModules: [{ identity: names.nativeModule, kind: "module", symbols: [names.publicName] }],
|
|
642
|
+
publicDeclarations: [publicDeclaration(names.publicName)],
|
|
643
|
+
requirements: [],
|
|
644
|
+
runtimeProfile: `${language}-task036-v1`,
|
|
645
|
+
source: { content: names.probeSource, filename: probeFilename, id: `${sourceBase}.probe` },
|
|
646
|
+
version: "1.0.0",
|
|
647
|
+
visibility: "public"
|
|
648
|
+
}, {
|
|
649
|
+
dependencies: [],
|
|
650
|
+
identity: `${base}.probe-runner`,
|
|
651
|
+
language,
|
|
652
|
+
nativeModules: [],
|
|
653
|
+
publicDeclarations: [],
|
|
654
|
+
requirements: [{ module: "semantifold.task034.resource-probe", operations: ["probeEffect", "probeTrace"], range: "1" }],
|
|
655
|
+
runtimeProfile: `${language}-task036-v1`,
|
|
656
|
+
source: { content: names.runnerSource, filename: runnerFilename, id: `${sourceBase}.probe_runner` },
|
|
657
|
+
version: "1.0.0",
|
|
658
|
+
visibility: "internal"
|
|
659
|
+
}, {
|
|
660
|
+
dependencies: [],
|
|
661
|
+
identity: `${base}.unused`,
|
|
662
|
+
language,
|
|
663
|
+
nativeModules: [{ identity: names.unusedNativeModule, kind: "module", symbols: [names.unusedName] }],
|
|
664
|
+
publicDeclarations: [publicDeclaration(names.unusedName)],
|
|
665
|
+
requirements: [{ module: "semantifold.task034.resource-probe", operations: ["probeTrace"], range: "1" }],
|
|
666
|
+
runtimeProfile: `${language}-task036-v1`,
|
|
667
|
+
source: { content: names.unusedSource, filename: unusedFilename, id: `${sourceBase}.unused` },
|
|
668
|
+
version: "1.0.0",
|
|
669
|
+
visibility: "public"
|
|
670
|
+
}];
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Builds the common bounded qualification function declaration.
|
|
674
|
+
* @param {string} name - Source-visible function name.
|
|
675
|
+
* @returns {StdlibFacadePublicDeclaration} Public facade declaration.
|
|
676
|
+
*/
|
|
677
|
+
function publicDeclaration(name) {
|
|
678
|
+
return {
|
|
679
|
+
effects: ["host"], failures: [], forms: ["direct-call"], kind: "function", name,
|
|
680
|
+
ownership: "not-applicable", parameters: [{ name: "label", type: "string" }], returnType: "string"
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Builds the exact Ruby Task 037 socket and output compatibility facades.
|
|
685
|
+
* @returns {unknown[]} Unvalidated facade records.
|
|
686
|
+
*/
|
|
687
|
+
function builtinTask037RubyFacades() {
|
|
688
|
+
return [{
|
|
689
|
+
dependencies: [],
|
|
690
|
+
identity: "semantifold.task037.ruby.socket",
|
|
691
|
+
language: "ruby",
|
|
692
|
+
nativeModules: [{ identity: "socket", kind: "module", symbols: ["TCPSocket"] }],
|
|
693
|
+
publicDeclarations: [{
|
|
694
|
+
constructor: {
|
|
695
|
+
effects: ["host"], failures: ["InvalidHost", "InvalidPort", "ConnectionFailure"], ownership: "acquired",
|
|
696
|
+
parameters: [{ name: "host", type: "string" }, { name: "port", type: "integer" }]
|
|
697
|
+
},
|
|
698
|
+
forms: ["constructor-call"],
|
|
699
|
+
kind: "class",
|
|
700
|
+
methods: [{
|
|
701
|
+
effects: ["host"], failures: ["ReadFailure", "DecodeFailure", "ResourceClosed"], forms: ["receiver-call"],
|
|
702
|
+
name: "gets", ownership: "borrowed", parameters: [], returnType: "optional:string"
|
|
703
|
+
}, {
|
|
704
|
+
effects: ["host"], failures: ["CloseFailure", "ResourceClosed"], forms: ["receiver-call"],
|
|
705
|
+
name: "close", ownership: "consumed", parameters: [], returnType: "void"
|
|
706
|
+
}],
|
|
707
|
+
name: "TCPSocket",
|
|
708
|
+
ownership: "owned-reference"
|
|
709
|
+
}],
|
|
710
|
+
requirements: [
|
|
711
|
+
{ module: "semantifold.socket-client", operations: ["v1_connect"], range: "1" },
|
|
712
|
+
{ module: "semantifold.text-stream", operations: ["v1_read_line"], range: "1" },
|
|
713
|
+
{ module: "semantifold.resource", operations: ["v1_close"], range: "1" }
|
|
714
|
+
],
|
|
715
|
+
runtimeProfile: "ruby-task037-socket-v1",
|
|
716
|
+
source: {
|
|
717
|
+
content: `module SemantifoldTask037Socket
|
|
718
|
+
class TCPSocket
|
|
719
|
+
# @param host [String]
|
|
720
|
+
# @param port [Integer]
|
|
721
|
+
def initialize(host, port)
|
|
722
|
+
@resource = v1_connect(host, port)
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
# @return [String?]
|
|
726
|
+
def gets
|
|
727
|
+
return v1_read_line(@resource)
|
|
728
|
+
end
|
|
729
|
+
|
|
730
|
+
# @return [void]
|
|
731
|
+
def close
|
|
732
|
+
v1_close(@resource)
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
end
|
|
736
|
+
`,
|
|
737
|
+
filename: "__semantifold_facades__/ruby/socket.rb",
|
|
738
|
+
id: "semantifold.facade.ruby.socket"
|
|
739
|
+
},
|
|
740
|
+
version: "1.0.0",
|
|
741
|
+
visibility: "public"
|
|
742
|
+
}, {
|
|
743
|
+
dependencies: [],
|
|
744
|
+
identity: "semantifold.task037.ruby.output",
|
|
745
|
+
language: "ruby",
|
|
746
|
+
nativeModules: [{ forms: ["unqualified-call", "receiver-call"], identity: "ruby:Kernel", kind: "builtin", symbols: ["puts"] }],
|
|
747
|
+
publicDeclarations: [{
|
|
748
|
+
effects: ["host"], failures: ["WriteFailure"], forms: ["unqualified-call", "receiver-call"], kind: "function",
|
|
749
|
+
name: "puts", ownership: "not-applicable", parameters: [{ name: "text", type: "string" }], returnType: "void"
|
|
750
|
+
}],
|
|
751
|
+
requirements: [{ module: "semantifold.output", operations: ["v1_write_line"], range: "1" }],
|
|
752
|
+
runtimeProfile: "ruby-task037-output-v1",
|
|
753
|
+
source: {
|
|
754
|
+
content: `module SemantifoldTask037Output
|
|
755
|
+
module_function
|
|
756
|
+
# @param text [String]
|
|
757
|
+
# @return [void]
|
|
758
|
+
def puts(text)
|
|
759
|
+
v1_write_line(text)
|
|
760
|
+
return
|
|
761
|
+
end
|
|
762
|
+
end
|
|
763
|
+
`,
|
|
764
|
+
filename: "__semantifold_facades__/ruby/output.rb",
|
|
765
|
+
id: "semantifold.facade.ruby.output"
|
|
766
|
+
},
|
|
767
|
+
version: "1.0.0",
|
|
768
|
+
visibility: "public"
|
|
769
|
+
}];
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Validates one public facade class descriptor.
|
|
773
|
+
* @param {Record<string, unknown>} value - Candidate class.
|
|
774
|
+
* @param {string} identity - Owning facade.
|
|
775
|
+
* @param {string} name - Validated class name.
|
|
776
|
+
* @returns {StdlibFacadeClassDeclaration} Detached class descriptor.
|
|
777
|
+
*/
|
|
778
|
+
function validatePublicClass(value, identity, name) {
|
|
779
|
+
requireKeys(value, ["constructor", "forms", "kind", "methods", "name", "ownership"], `facade '${identity}' public class`);
|
|
780
|
+
if (!isDenseArray(value.forms) || value.forms.length != 1 || value.forms[0] != "constructor-call" ||
|
|
781
|
+
value.ownership != "owned-reference" || !isPlainObject(value.constructor) || !isDenseArray(value.methods)) {
|
|
782
|
+
invalidFacade(`Facade '${identity}' class '${name}' has an invalid public contract.`);
|
|
783
|
+
}
|
|
784
|
+
const constructor = /** @type {Record<string, unknown>} */ (value.constructor);
|
|
785
|
+
requireKeys(constructor, ["effects", "failures", "ownership", "parameters"], `facade '${identity}' constructor`);
|
|
786
|
+
if (constructor.ownership != "acquired" || !validFacadeEffects(constructor.effects) ||
|
|
787
|
+
!validFacadeFailures(constructor.failures))
|
|
788
|
+
invalidFacade(`Facade '${identity}' class '${name}' has an invalid constructor.`);
|
|
789
|
+
const parameters = validateFacadeParameters(constructor.parameters, identity, `${name}.new`);
|
|
790
|
+
const methodNames = new Set();
|
|
791
|
+
const methods = value.methods.map((method) => {
|
|
792
|
+
if (!isPlainObject(method))
|
|
793
|
+
invalidFacade(`Facade '${identity}' class '${name}' has an invalid method.`);
|
|
794
|
+
requireKeys(method, ["effects", "failures", "forms", "name", "ownership", "parameters", "returnType"], `facade '${identity}' class method`);
|
|
795
|
+
const methodName = requireString(method.name, `Facade '${identity}' method name`);
|
|
796
|
+
const returnType = requireString(method.returnType, `Facade '${identity}' method return type`);
|
|
797
|
+
if (!declarationNamePattern.test(methodName) || methodNames.has(methodName) || !validFacadeEffects(method.effects) ||
|
|
798
|
+
!validFacadeFailures(method.failures) || !isDenseArray(method.forms) || method.forms.length != 1 ||
|
|
799
|
+
method.forms[0] != "receiver-call" || method.ownership != "borrowed" && method.ownership != "consumed" ||
|
|
800
|
+
!isFacadeType(returnType, true))
|
|
801
|
+
invalidFacade(`Facade '${identity}' class '${name}' has an invalid method.`);
|
|
802
|
+
methodNames.add(methodName);
|
|
803
|
+
return {
|
|
804
|
+
effects: /** @type {string[]} */ ([... /** @type {unknown[]} */(method.effects)]),
|
|
805
|
+
failures: /** @type {string[]} */ ([... /** @type {unknown[]} */(method.failures)]),
|
|
806
|
+
forms: /** @type {["receiver-call"]} */ (["receiver-call"]),
|
|
807
|
+
name: methodName,
|
|
808
|
+
ownership: /** @type {"borrowed" | "consumed"} */ (method.ownership),
|
|
809
|
+
parameters: validateFacadeParameters(method.parameters, identity, `${name}.${methodName}`),
|
|
810
|
+
returnType
|
|
811
|
+
};
|
|
812
|
+
});
|
|
813
|
+
return {
|
|
814
|
+
constructor: {
|
|
815
|
+
effects: /** @type {string[]} */ ([... /** @type {unknown[]} */(constructor.effects)]),
|
|
816
|
+
failures: /** @type {string[]} */ ([... /** @type {unknown[]} */(constructor.failures)]),
|
|
817
|
+
ownership: "acquired",
|
|
818
|
+
parameters
|
|
819
|
+
},
|
|
820
|
+
forms: ["constructor-call"],
|
|
821
|
+
kind: "class",
|
|
822
|
+
methods,
|
|
823
|
+
name,
|
|
824
|
+
ownership: "owned-reference"
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Validates facade parameters shared by functions, constructors, and methods.
|
|
829
|
+
* @param {unknown} candidate - Candidate parameters.
|
|
830
|
+
* @param {string} identity - Owning facade.
|
|
831
|
+
* @param {string} callable - Callable name.
|
|
832
|
+
* @returns {{name: string, type: string}[]} Detached parameters.
|
|
833
|
+
*/
|
|
834
|
+
function validateFacadeParameters(candidate, identity, callable) {
|
|
835
|
+
if (!isDenseArray(candidate))
|
|
836
|
+
invalidFacade(`Facade '${identity}' declaration '${callable}' has invalid parameters.`);
|
|
837
|
+
const names = new Set();
|
|
838
|
+
return candidate.map((parameter) => {
|
|
839
|
+
if (!isPlainObject(parameter))
|
|
840
|
+
invalidFacade(`Facade '${identity}' declaration '${callable}' has an invalid parameter.`);
|
|
841
|
+
requireKeys(parameter, ["name", "type"], `facade '${identity}' declaration parameter`);
|
|
842
|
+
const name = requireString(parameter.name, `Facade '${identity}' parameter name`);
|
|
843
|
+
const type = requireString(parameter.type, `Facade '${identity}' parameter type`);
|
|
844
|
+
if (!declarationNamePattern.test(name) || names.has(name) || !isFacadeType(type, false)) {
|
|
845
|
+
invalidFacade(`Facade '${identity}' declaration '${callable}' has an invalid parameter.`);
|
|
846
|
+
}
|
|
847
|
+
names.add(name);
|
|
848
|
+
return { name, type };
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Checks one facade effect list.
|
|
853
|
+
* @param {unknown} candidate - Candidate effects.
|
|
854
|
+
* @returns {boolean} Whether effects are exact.
|
|
855
|
+
*/
|
|
856
|
+
function validFacadeEffects(candidate) {
|
|
857
|
+
return isDenseArray(candidate) && candidate.every((effect) => effect == "host") && new Set(candidate).size == candidate.length;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Checks one facade failure list.
|
|
861
|
+
* @param {unknown} candidate - Candidate failures.
|
|
862
|
+
* @returns {candidate is string[]} Whether failures are exact.
|
|
863
|
+
*/
|
|
864
|
+
function validFacadeFailures(candidate) {
|
|
865
|
+
return isDenseArray(candidate) && candidate.every((failure) => typeof failure == "string" && declarationNamePattern.test(failure)) &&
|
|
866
|
+
new Set(candidate).size == candidate.length;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Checks one facade type spelling.
|
|
870
|
+
* @param {string} type - Candidate type.
|
|
871
|
+
* @param {boolean} allowVoid - Whether void is valid in this position.
|
|
872
|
+
* @returns {boolean} Whether the type is canonical.
|
|
873
|
+
*/
|
|
874
|
+
function isFacadeType(type, allowVoid) {
|
|
875
|
+
if (canonicalTypes.has(type))
|
|
876
|
+
return allowVoid || type != "void";
|
|
877
|
+
const optional = /^optional:(boolean|integer|string)$/u.exec(type);
|
|
878
|
+
return optional !== null;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Detaches one descriptor for the public program record.
|
|
882
|
+
* @param {StdlibFacadePublicDeclaration} declaration - Registry declaration.
|
|
883
|
+
* @returns {StdlibFacadePublicDeclaration} Detached declaration.
|
|
884
|
+
*/
|
|
885
|
+
function detachPublicDeclaration(declaration) {
|
|
886
|
+
if (declaration.kind == "function")
|
|
887
|
+
return { ...declaration, effects: [...declaration.effects], failures: [...declaration.failures],
|
|
888
|
+
forms: [...declaration.forms], parameters: declaration.parameters.map((parameter) => ({ ...parameter })) };
|
|
889
|
+
return { ...declaration,
|
|
890
|
+
constructor: { ...declaration.constructor, effects: [...declaration.constructor.effects], failures: [...declaration.constructor.failures],
|
|
891
|
+
parameters: declaration.constructor.parameters.map((parameter) => ({ ...parameter })) },
|
|
892
|
+
forms: [...declaration.forms],
|
|
893
|
+
methods: declaration.methods.map((method) => ({ ...method, effects: [...method.effects], failures: [...method.failures],
|
|
894
|
+
forms: [...method.forms], parameters: method.parameters.map((parameter) => ({ ...parameter })) })) };
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Detaches a local or dependency-qualified contract reference.
|
|
898
|
+
* @param {string | import("./semantic/stdlib.js").CanonicalDeclarationReference} reference - Contract reference.
|
|
899
|
+
* @returns {string | import("./semantic/types.js").CapabilityDeclarationReferenceInput} Detached reference.
|
|
900
|
+
*/
|
|
901
|
+
function detachCanonicalReference(reference) {
|
|
902
|
+
return typeof reference == "string" ? reference : { module: reference.module, name: reference.name };
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Detaches a canonical resource flow for authority construction.
|
|
906
|
+
* @param {object} flow - Canonical resource flow.
|
|
907
|
+
* @returns {import("./semantic/types.js").CapabilityResourceFlowInput} Detached flow.
|
|
908
|
+
*/
|
|
909
|
+
function detachResourceFlow(flow) {
|
|
910
|
+
const candidate = /** @type {Record<string, unknown>} */ (flow);
|
|
911
|
+
if (candidate.kind == "none")
|
|
912
|
+
return { kind: "none" };
|
|
913
|
+
if (candidate.kind == "acquire")
|
|
914
|
+
return { kind: "acquire", resource: detachCanonicalReference(
|
|
915
|
+
/** @type {string | import("./semantic/stdlib.js").CanonicalDeclarationReference} */ (candidate.resource)) };
|
|
916
|
+
return {
|
|
917
|
+
kind: /** @type {"borrow" | "close"} */ (candidate.kind),
|
|
918
|
+
parameterIndex: /** @type {number} */ (candidate.parameterIndex),
|
|
919
|
+
terminalFailure: detachCanonicalReference(
|
|
920
|
+
/** @type {string | import("./semantic/stdlib.js").CanonicalDeclarationReference} */ (candidate.terminalFailure))
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Maps one canonical module identity to its closed capability name.
|
|
925
|
+
* @param {string} identity - Canonical identity.
|
|
926
|
+
* @returns {string} Capability name.
|
|
927
|
+
*/
|
|
928
|
+
function canonicalCapabilityName(identity) {
|
|
929
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
930
|
+
const names = {
|
|
931
|
+
"semantifold.output": "Output",
|
|
932
|
+
"semantifold.resource": "Resource",
|
|
933
|
+
"semantifold.socket-client": "SocketClient",
|
|
934
|
+
"semantifold.task034.resource-probe": "ResourceProbe",
|
|
935
|
+
"semantifold.text-stream": "TextStream"
|
|
936
|
+
};
|
|
937
|
+
return names[identity] ?? invalidFacade(`Facade requirements name unknown canonical module '${identity}'.`);
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Builds executable source and native identity spellings for one original-five language.
|
|
941
|
+
* @param {string} language - Source language.
|
|
942
|
+
* @returns {FacadeSourceNames} Facade source definitions.
|
|
943
|
+
*/
|
|
944
|
+
function facadeNames(language) {
|
|
945
|
+
if (language == "php")
|
|
946
|
+
return {
|
|
947
|
+
extension: "php", nativeModule: "Semantifold\\Task036\\Probe", publicName: "compatibility_probe",
|
|
948
|
+
unusedName: "unused_probe", unusedNativeModule: "Semantifold\\Task036\\Unused",
|
|
949
|
+
probeSource: `<?php
|
|
950
|
+
declare(strict_types=1);
|
|
951
|
+
namespace Semantifold\\Facade\\Php\\Probe;
|
|
952
|
+
use function Semantifold\\Facade\\Php\\ProbeRunner\\run_compatibility_probe;
|
|
953
|
+
require_once __DIR__ . "/probe-runner.php";
|
|
954
|
+
function compatibility_probe(string $label): string { return run_compatibility_probe($label); }
|
|
955
|
+
`,
|
|
956
|
+
runnerSource: `<?php
|
|
957
|
+
declare(strict_types=1);
|
|
958
|
+
namespace Semantifold\\Facade\\Php\\ProbeRunner;
|
|
959
|
+
function run_compatibility_probe(string $label): string {
|
|
960
|
+
try {
|
|
961
|
+
/**
|
|
962
|
+
* @var int $effect
|
|
963
|
+
* @semantifold-immutable
|
|
964
|
+
*/
|
|
965
|
+
$effect = probeEffect($label, 1, false);
|
|
966
|
+
return probeTrace();
|
|
967
|
+
}
|
|
968
|
+
catch (ProbeOperationFailure $error) { return $error->getMessage(); }
|
|
969
|
+
}
|
|
970
|
+
`,
|
|
971
|
+
unusedSource: `<?php
|
|
972
|
+
declare(strict_types=1);
|
|
973
|
+
namespace Semantifold\\Facade\\Php\\Unused;
|
|
974
|
+
function unused_probe(string $label): string { return probeTrace(); }
|
|
975
|
+
`
|
|
976
|
+
};
|
|
977
|
+
if (language == "ruby")
|
|
978
|
+
return {
|
|
979
|
+
extension: "rb", nativeModule: "semantifold/task036/probe", publicName: "compatibility_probe",
|
|
980
|
+
unusedName: "unused_probe", unusedNativeModule: "semantifold/task036/unused",
|
|
981
|
+
probeSource: `require_relative "probe-runner"
|
|
982
|
+
module SemantifoldTask036Probe
|
|
983
|
+
module_function
|
|
984
|
+
# @param label [String]
|
|
985
|
+
# @return [String]
|
|
986
|
+
def compatibility_probe(label)
|
|
987
|
+
return SemantifoldTask036ProbeRunner.run_compatibility_probe(label)
|
|
988
|
+
end
|
|
989
|
+
end
|
|
990
|
+
`,
|
|
991
|
+
runnerSource: `module SemantifoldTask036ProbeRunner
|
|
992
|
+
module_function
|
|
993
|
+
# @param label [String]
|
|
994
|
+
# @return [String]
|
|
995
|
+
def run_compatibility_probe(label)
|
|
996
|
+
begin
|
|
997
|
+
# @type [Integer]
|
|
998
|
+
# @semantifold-immutable
|
|
999
|
+
effect = probeEffect(label, 1, false)
|
|
1000
|
+
return probeTrace
|
|
1001
|
+
rescue ProbeOperationFailure => error
|
|
1002
|
+
return error.message
|
|
1003
|
+
end
|
|
1004
|
+
end
|
|
1005
|
+
end
|
|
1006
|
+
`,
|
|
1007
|
+
unusedSource: `module SemantifoldTask036Unused
|
|
1008
|
+
module_function
|
|
1009
|
+
# @param label [String]
|
|
1010
|
+
# @return [String]
|
|
1011
|
+
def unused_probe(label)
|
|
1012
|
+
return probeTrace
|
|
1013
|
+
end
|
|
1014
|
+
end
|
|
1015
|
+
`
|
|
1016
|
+
};
|
|
1017
|
+
if (language == "java")
|
|
1018
|
+
return {
|
|
1019
|
+
extension: "java", nativeModule: "semantifold.task036.Probe", publicName: "compatibilityProbe",
|
|
1020
|
+
unusedName: "unusedProbe", unusedNativeModule: "semantifold.task036.Unused",
|
|
1021
|
+
probeSource: `package semantifold.facade.java.probe;
|
|
1022
|
+
import semantifold.facade.java.proberunner.ProbeRunner;
|
|
1023
|
+
public final class Probe {
|
|
1024
|
+
public static String compatibilityProbe(String label) { return ProbeRunner.runCompatibilityProbe(label); }
|
|
1025
|
+
}
|
|
1026
|
+
`,
|
|
1027
|
+
runnerSource: `package semantifold.facade.java.proberunner;
|
|
1028
|
+
public final class ProbeRunner {
|
|
1029
|
+
public static String runCompatibilityProbe(String label) {
|
|
1030
|
+
try { final int effect = probeEffect(label, 1, false); return probeTrace(); }
|
|
1031
|
+
catch (ProbeOperationFailure error) { return error.getMessage(); }
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
`,
|
|
1035
|
+
unusedSource: `package semantifold.facade.java.unused;
|
|
1036
|
+
public final class Unused {
|
|
1037
|
+
public static String unusedProbe(String label) { return probeTrace(); }
|
|
1038
|
+
}
|
|
1039
|
+
`
|
|
1040
|
+
};
|
|
1041
|
+
const typed = language == "typescript";
|
|
1042
|
+
const extension = typed ? "ts" : "js";
|
|
1043
|
+
const parameter = typed ? "label: string" : "label";
|
|
1044
|
+
const result = typed ? ": string" : "";
|
|
1045
|
+
const documentation = typed ? "" : `/**
|
|
1046
|
+
* @param {string} label
|
|
1047
|
+
* @returns {string}
|
|
1048
|
+
*/
|
|
1049
|
+
`;
|
|
1050
|
+
return {
|
|
1051
|
+
extension, nativeModule: "semantifold:task036/probe", publicName: "compatibilityProbe",
|
|
1052
|
+
unusedName: "unusedProbe", unusedNativeModule: "semantifold:task036/unused",
|
|
1053
|
+
probeSource: `import {runCompatibilityProbe} from "./probe-runner.js"
|
|
1054
|
+
${documentation}export function compatibilityProbe(${parameter})${result} { return runCompatibilityProbe(label) }
|
|
1055
|
+
`,
|
|
1056
|
+
runnerSource: `${documentation}export function runCompatibilityProbe(${parameter})${result} {
|
|
1057
|
+
try { ${typed ? "const effect: number" : "/** @type {number} */ const effect"} = probeEffect(label, 1, false); return probeTrace() }
|
|
1058
|
+
catch (error) { if (!(error instanceof ProbeOperationFailure)) { throw error } return error.message }
|
|
1059
|
+
}
|
|
1060
|
+
`,
|
|
1061
|
+
unusedSource: `${documentation}export function unusedProbe(${parameter})${result} { return probeTrace() }
|
|
1062
|
+
`
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* Requires a closed exact key set.
|
|
1067
|
+
* @param {Record<string, unknown>} value - Plain candidate object.
|
|
1068
|
+
* @param {string[]} keys - Expected keys.
|
|
1069
|
+
* @param {string} subject - Diagnostic subject.
|
|
1070
|
+
* @returns {void}
|
|
1071
|
+
*/
|
|
1072
|
+
function requireKeys(value, keys, subject) {
|
|
1073
|
+
if (Object.keys(value).sort().join(",") != [...keys].sort().join(","))
|
|
1074
|
+
invalidFacade(`Invalid ${subject} fields.`);
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Requires one non-empty string.
|
|
1078
|
+
* @param {unknown} value - Candidate value.
|
|
1079
|
+
* @param {string} subject - Diagnostic subject.
|
|
1080
|
+
* @returns {string} Validated string.
|
|
1081
|
+
*/
|
|
1082
|
+
function requireString(value, subject) {
|
|
1083
|
+
if (typeof value != "string" || value.length == 0)
|
|
1084
|
+
invalidFacade(`${subject} must be a non-empty string.`);
|
|
1085
|
+
return /** @type {string} */ (value);
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Checks for an ordinary object with no custom prototype.
|
|
1089
|
+
* @param {unknown} value - Candidate value.
|
|
1090
|
+
* @returns {value is Record<string, unknown>} Whether the candidate is plain.
|
|
1091
|
+
*/
|
|
1092
|
+
function isPlainObject(value) {
|
|
1093
|
+
return value !== null && typeof value == "object" && !Array.isArray(value) && Object.getPrototypeOf(value) == Object.prototype;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Recursively freezes one detached facade registry value.
|
|
1097
|
+
* @template {object} T
|
|
1098
|
+
* @param {T} value - Detached object.
|
|
1099
|
+
* @returns {Readonly<T>} Frozen value.
|
|
1100
|
+
*/
|
|
1101
|
+
function deepFreeze(value) {
|
|
1102
|
+
for (const child of Object.values(value))
|
|
1103
|
+
if (child && typeof child == "object" && !Object.isFrozen(child))
|
|
1104
|
+
deepFreeze(child);
|
|
1105
|
+
return Object.freeze(value);
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Throws a stable invalid-registry diagnostic.
|
|
1109
|
+
* @param {string} message - Failure detail.
|
|
1110
|
+
* @returns {never} Always throws.
|
|
1111
|
+
*/
|
|
1112
|
+
function invalidFacade(message) {
|
|
1113
|
+
throw new SemantifoldDiagnostic({ code: "STDLIB_FACADE_INVALID", language: "stdlib", message });
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Throws when parser evidence does not name a registered native module.
|
|
1117
|
+
* @param {string} language - Source language.
|
|
1118
|
+
* @param {unknown} nativeModule - Unproved module identity.
|
|
1119
|
+
* @returns {never} Always throws.
|
|
1120
|
+
*/
|
|
1121
|
+
function unprovedIdentity(language, nativeModule) {
|
|
1122
|
+
throw new SemantifoldDiagnostic({
|
|
1123
|
+
code: "STDLIB_FACADE_IDENTITY_UNPROVED",
|
|
1124
|
+
language: supportedLanguages.has(language) ? language : "stdlib",
|
|
1125
|
+
message: `Native standard-library module '${String(nativeModule)}' is not a registered '${language}' facade identity.`
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Throws when a native module member is outside its public facade surface.
|
|
1130
|
+
* @param {string} language - Source language.
|
|
1131
|
+
* @param {string} nativeModule - Exact native module.
|
|
1132
|
+
* @param {string} symbol - Unsupported member.
|
|
1133
|
+
* @returns {never} Always throws.
|
|
1134
|
+
*/
|
|
1135
|
+
function unsupportedMember(language, nativeModule, symbol) {
|
|
1136
|
+
throw new SemantifoldDiagnostic({
|
|
1137
|
+
code: "STDLIB_FACADE_MEMBER_UNSUPPORTED",
|
|
1138
|
+
language,
|
|
1139
|
+
message: `Native standard-library symbol '${nativeModule}#${symbol}' is outside the registered facade surface.`
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* Throws for a malformed facade version range.
|
|
1144
|
+
* @param {string} language - Source language.
|
|
1145
|
+
* @param {string} range - Malformed range.
|
|
1146
|
+
* @returns {never} Always throws.
|
|
1147
|
+
*/
|
|
1148
|
+
function facadeVersionMalformed(language, range) {
|
|
1149
|
+
throw new SemantifoldDiagnostic({
|
|
1150
|
+
code: "STDLIB_FACADE_VERSION_MALFORMED", language,
|
|
1151
|
+
message: `Facade version range '${range}' is not canonical.`
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
/**
|
|
1155
|
+
* Throws when no registered facade version satisfies a range.
|
|
1156
|
+
* @param {string} language - Source language.
|
|
1157
|
+
* @param {string} identity - Facade identity.
|
|
1158
|
+
* @returns {never} Always throws.
|
|
1159
|
+
*/
|
|
1160
|
+
function facadeVersionIncompatible(language, identity) {
|
|
1161
|
+
throw new SemantifoldDiagnostic({
|
|
1162
|
+
code: "STDLIB_FACADE_VERSION_INCOMPATIBLE", language,
|
|
1163
|
+
message: `No registered version of facade '${identity}' satisfies the required compatibility range.`
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
export const stdlibFacadeRegistry = createStdlibFacadeRegistry();
|
|
1167
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RkbGliLWZhY2FkZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RkbGliLWZhY2FkZXMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxZQUFZLENBQUE7QUFDdkMsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sb0JBQW9CLENBQUE7QUFDckQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0saUJBQWlCLENBQUE7QUFDckQsT0FBTyxFQUNMLHFCQUFxQixFQUFFLGtCQUFrQixFQUFFLHVCQUF1QixFQUFFLG1CQUFtQixFQUFFLHNCQUFzQixFQUNoSCxNQUFNLHNCQUFzQixDQUFBO0FBRTdCLE1BQU0scUJBQXFCLEdBQUcscUJBQXFCLENBQUE7QUFDbkQsTUFBTSxlQUFlLEdBQUcsNENBQTRDLENBQUE7QUFDcEUsTUFBTSxzQkFBc0IsR0FBRywyQkFBMkIsQ0FBQTtBQUMxRCxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7QUFDdkYsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFBO0FBRXhFOzs7Ozs7Ozs7O0dBVUc7QUFDSDs7Ozs7Ozs7R0FRRztBQUNILDhHQUE4RztBQUM5Rzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSDs7Ozs7Ozs7OztHQVVHO0FBQ0g7Ozs7OztHQU1HO0FBRUg7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxPQUFPLEdBQUcsb0JBQW9CLEVBQUU7SUFDekUsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7UUFBRSxhQUFhLENBQUMsZ0RBQWdELENBQUMsQ0FBQTtJQUMzRixtQ0FBbUM7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QVMsRUFBQyxDQUFDLENBQUMsRUFBQyxDQUFBO0lBQ3pHLE9BQU8sRUFBQyxHQUFHLFdBQVc7UUFDcEIsV0FBVyxFQUFFLEVBQUMsR0FBRyxXQUFXLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDO1lBQ3RJLFVBQVUsRUFBRSxXQUFXLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBQyxHQUFHLFNBQVMsRUFBQyxDQUFDLENBQUMsRUFBQztRQUN0RixLQUFLLEVBQUUsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7UUFDN0IsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUMsR0FBRyxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDO1lBQ3BILEtBQUssRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFDLEdBQUcsU0FBUyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxFQUFDLENBQUE7QUFDdEcsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLHdCQUF3QixDQUFDLFNBQVM7SUFDekMsT0FBTyxPQUFPLFNBQVMsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFD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QTtBQUNKLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxZQUFZLEVBQUUsTUFBTTtJQUN2RCxNQUFNLElBQUkscUJBQXFCLENBQUM7UUFDOUIsSUFBSSxFQUFFLGtDQUFrQztRQUN4QyxRQUFRO1FBQ1IsT0FBTyxFQUFFLG1DQUFtQyxZQUFZLElBQUksTUFBTSw2Q0FBNkM7S0FDaEgsQ0FBQyxDQUFBO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBQyxRQUFRLEVBQUUsS0FBSztJQUM3QyxNQUFNLElBQUkscUJBQXFCLENBQUM7UUFDOUIsSUFBSSxFQUFFLGlDQUFpQyxFQUFFLFFBQVE7UUFDakQsT0FBTyxFQUFFLHlCQUF5QixLQUFLLHFCQUFxQjtLQUM3RCxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLHlCQUF5QixDQUFDLFFBQVEsRUFBRSxRQUFRO0lBQ25ELE1BQU0sSUFBSSxxQkFBcUIsQ0FBQztRQUM5QixJQUFJLEVBQUUsb0NBQW9DLEVBQUUsUUFBUTtRQUNwRCxPQUFPLEVBQUUsb0NBQW9DLFFBQVEsK0NBQStDO0tBQ3JHLENBQUMsQ0FBQTtBQUNKLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRywwQkFBMEIsRUFBRSxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7aXNEZW5zZUFycmF5fSBmcm9tIFwiLi9hcnJheS5qc1wiXG5pbXBvcnQge2lzU2FmZUFydGlmYWN0UGF0aH0gZnJvbSBcIi4vYXJ0aWZhY3QtcGF0aC5qc1wiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpY30gZnJvbSBcIi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge1xuICBjb21wYXJlU3RkbGliVmVyc2lvbnMsIHBhcnNlU3RkbGliVmVyc2lvbiwgcGFyc2VTdGRsaWJWZXJzaW9uUmFuZ2UsIHJlc29sdmVTdGRsaWJNb2R1bGUsIHN0ZGxpYlZlcnNpb25TYXRpc2ZpZXNcbn0gZnJvbSBcIi4vc2VtYW50aWMvc3RkbGliLmpzXCJcblxuY29uc3QgZmFjYWRlSWRlbnRpdHlQYXR0ZXJuID0gL15bYS16XVthLXowLTkuLV0qJC91XG5jb25zdCBtb2R1bGVJZFBhdHRlcm4gPSAvXlthLXpdW2EtejAtOV9dKig/OlsuLV1bYS16XVthLXowLTlfXSopKiQvdVxuY29uc3QgZGVjbGFyYXRpb25OYW1lUGF0dGVybiA9IC9eW0EtWmEtel9dW0EtWmEtejAtOV9dKiQvdVxuY29uc3Qgc3VwcG9ydGVkTGFuZ3VhZ2VzID0gbmV3IFNldChbXCJwaHBcIiwgXCJydWJ5XCIsIFwiamF2YXNjcmlwdFwiLCBcInR5cGVzY3JpcHRcIiwgXCJqYXZhXCJdKVxuY29uc3QgY2Fub25pY2FsVHlwZXMgPSBuZXcgU2V0KFtcImJvb2xlYW5cIiwgXCJpbnRlZ2VyXCIsIFwic3RyaW5nXCIsIFwidm9pZFwiXSlcblxuLyoqXG4gKiBAdHlwZWRlZiBTdGRsaWJGYWNhZGVGdW5jdGlvbkRlY2xhcmF0aW9uXG4gKiBAcHJvcGVydHkge1wiZnVuY3Rpb25cIn0ga2luZCAtIENsb3NlZCBwdWJsaWMgZGVjbGFyYXRpb24ga2luZC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBuYW1lIC0gRXhhY3Qgc291cmNlLXZpc2libGUgc3ltYm9sLlxuICogQHByb3BlcnR5IHt7bmFtZTogc3RyaW5nLCB0eXBlOiBzdHJpbmd9W119IHBhcmFtZXRlcnMgLSBPcmRlcmVkIHNvdXJjZSBzaWduYXR1cmUuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcmV0dXJuVHlwZSAtIENhbm9uaWNhbCByZXN1bHQgdHlwZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nW119IGVmZmVjdHMgLSBDbG9zZWQgcHVibGljIGVmZmVjdHMuXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBmYWlsdXJlcyAtIEVzY2FwaW5nIGNhbm9uaWNhbCBmYWlsdXJlIG5hbWVzLlxuICogQHByb3BlcnR5IHsoXCJkaXJlY3QtY2FsbFwiIHwgXCJ1bnF1YWxpZmllZC1jYWxsXCIgfCBcInJlY2VpdmVyLWNhbGxcIilbXX0gZm9ybXMgLSBBY2NlcHRlZCBzb3VyY2UgY2FsbCBmb3Jtcy5cbiAqIEBwcm9wZXJ0eSB7XCJub3QtYXBwbGljYWJsZVwifSBvd25lcnNoaXAgLSBJbml0aWFsIHNjYWxhciBxdWFsaWZpY2F0aW9uIG93bmVyc2hpcC5cbiAqL1xuLyoqXG4gKiBAdHlwZWRlZiBTdGRsaWJGYWNhZGVDbGFzc0RlY2xhcmF0aW9uXG4gKiBAcHJvcGVydHkge1wiY2xhc3NcIn0ga2luZCAtIENsb3NlZCBwdWJsaWMgZGVjbGFyYXRpb24ga2luZC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBuYW1lIC0gRXhhY3Qgc291cmNlLXZpc2libGUgY2xhc3Mgc3ltYm9sLlxuICogQHByb3BlcnR5IHtbXCJjb25zdHJ1Y3Rvci1jYWxsXCJdfSBmb3JtcyAtIEFjY2VwdGVkIGNvbnN0cnVjdGlvbiBmb3JtLlxuICogQHByb3BlcnR5IHtcIm93bmVkLXJlZmVyZW5jZVwifSBvd25lcnNoaXAgLSBDbGFzcyBpbnN0YW5jZSBvd25lcnNoaXAuXG4gKiBAcHJvcGVydHkge3tlZmZlY3RzOiBzdHJpbmdbXSwgZmFpbHVyZXM6IHN0cmluZ1tdLCBvd25lcnNoaXA6IFwiYWNxdWlyZWRcIiwgcGFyYW1ldGVyczoge25hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nfVtdfX0gY29uc3RydWN0b3IgLSBDb25zdHJ1Y3RvciBjb250cmFjdC5cbiAqIEBwcm9wZXJ0eSB7e2VmZmVjdHM6IHN0cmluZ1tdLCBmYWlsdXJlczogc3RyaW5nW10sIGZvcm1zOiBbXCJyZWNlaXZlci1jYWxsXCJdLCBuYW1lOiBzdHJpbmcsIG93bmVyc2hpcDogXCJib3Jyb3dlZFwiIHwgXCJjb25zdW1lZFwiLCBwYXJhbWV0ZXJzOiB7bmFtZTogc3RyaW5nLCB0eXBlOiBzdHJpbmd9W10sIHJldHVyblR5cGU6IHN0cmluZ31bXX0gbWV0aG9kcyAtIFB1YmxpYyBpbnN0YW5jZSBtZXRob2RzLlxuICovXG4vKiogQHR5cGVkZWYge1N0ZGxpYkZhY2FkZUZ1bmN0aW9uRGVjbGFyYXRpb24gfCBTdGRsaWJGYWNhZGVDbGFzc0RlY2xhcmF0aW9ufSBTdGRsaWJGYWNhZGVQdWJsaWNEZWNsYXJhdGlvbiAqL1xuLyoqXG4gKiBAdHlwZWRlZiBTdGRsaWJGYWNhZGVSZWNvcmRcbiAqIEBwcm9wZXJ0eSB7e2lkZW50aXR5OiBzdHJpbmcsIHJhbmdlOiBzdHJpbmd9W119IGRlcGVuZGVuY2llcyAtIEZhY2FkZS1tb2R1bGUgZGVwZW5kZW5jaWVzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IGlkZW50aXR5IC0gVmVyc2lvbmVkIGZhY2FkZSBpZGVudGl0eS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0xhbmd1YWdlfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwcm9wZXJ0eSB7KHtpZGVudGl0eTogc3RyaW5nLCBraW5kOiBcIm1vZHVsZVwiLCBzeW1ib2xzOiBzdHJpbmdbXX0gfCB7Zm9ybXM6IChcInVucXVhbGlmaWVkLWNhbGxcIiB8IFwicmVjZWl2ZXItY2FsbFwiKVtdLCBpZGVudGl0eTogc3RyaW5nLCBraW5kOiBcImJ1aWx0aW5cIiwgc3ltYm9sczogc3RyaW5nW119KVtdfSBuYXRpdmVNb2R1bGVzIC0gRXhhY3Qgc291cmNlIG5hdGl2ZSBpZGVudGl0aWVzLlxuICogQHByb3BlcnR5IHtTdGRsaWJGYWNhZGVQdWJsaWNEZWNsYXJhdGlvbltdfSBwdWJsaWNEZWNsYXJhdGlvbnMgLSBQdWJsaWMgc291cmNlIHN1cmZhY2UuXG4gKiBAcHJvcGVydHkge3ttb2R1bGU6IHN0cmluZywgb3BlcmF0aW9uczogc3RyaW5nW10sIHJhbmdlOiBzdHJpbmd9W119IHJlcXVpcmVtZW50cyAtIENhbm9uaWNhbC1vbmx5IHJlcXVpcmVtZW50cy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBydW50aW1lUHJvZmlsZSAtIEV4YWN0IGNvbXBhdGlibGUgc291cmNlL3J1bnRpbWUgcHJvZmlsZS5cbiAqIEBwcm9wZXJ0eSB7e2NvbnRlbnQ6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZywgaWQ6IHN0cmluZ319IHNvdXJjZSAtIEV4ZWN1dGFibGUgY29tcGlsZXItb3duZWQgc291cmNlIG1vZHVsZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJzaW9uIC0gRXhhY3QgZmFjYWRlIHZlcnNpb24uXG4gKiBAcHJvcGVydHkge1wiaW50ZXJuYWxcIiB8IFwicHVibGljXCJ9IHZpc2liaWxpdHkgLSBOYXRpdmUtc2VsZWN0YWJsZSB2aXNpYmlsaXR5LlxuICovXG4vKipcbiAqIEB0eXBlZGVmIEZhY2FkZVNvdXJjZU5hbWVzXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZXh0ZW5zaW9uIC0gU291cmNlIGZpbGVuYW1lIGV4dGVuc2lvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBuYXRpdmVNb2R1bGUgLSBQdWJsaWMgbmF0aXZlIHN0ZGxpYiBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gcHVibGljTmFtZSAtIFB1YmxpYyBuYXRpdmUgc3ltYm9sLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHVudXNlZE5hbWUgLSBVbnVzZWQtZWxpbWluYXRpb24gZml4dHVyZSBzeW1ib2wuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdW51c2VkTmF0aXZlTW9kdWxlIC0gVW51c2VkLWVsaW1pbmF0aW9uIGZpeHR1cmUgbW9kdWxlLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHByb2JlU291cmNlIC0gUHVibGljIGV4ZWN1dGFibGUgZmFjYWRlIHNvdXJjZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBydW5uZXJTb3VyY2UgLSBJbnRlcm5hbCBjYW5vbmljYWwgcnVubmVyIHNvdXJjZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB1bnVzZWRTb3VyY2UgLSBVbnVzZWQgZXhlY3V0YWJsZSBmYWNhZGUgc291cmNlLlxuICovXG4vKipcbiAqIEB0eXBlZGVmIFN0ZGxpYkZhY2FkZVJlZ2lzdHJ5XG4gKiBAcHJvcGVydHkge3JlYWRvbmx5IFN0ZGxpYkZhY2FkZVJlY29yZFtdfSBmYWNhZGVzIC0gU3RhYmxlIGltbXV0YWJsZSBmYWNhZGUgcmVjb3Jkcy5cbiAqIEBwcm9wZXJ0eSB7KGxhbmd1YWdlOiBzdHJpbmcsIG5hdGl2ZU1vZHVsZTogc3RyaW5nLCBzeW1ib2w6IHN0cmluZywgcmFuZ2U/OiBzdHJpbmcpID0+IFN0ZGxpYkZhY2FkZVJlY29yZH0gcmVzb2x2ZUZhY2FkZSAtIEV4YWN0IG5hdGl2ZSBpZGVudGl0eSByZXNvbHZlci5cbiAqIEBwcm9wZXJ0eSB7KGlkZW50aXR5OiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHJhbmdlPzogc3RyaW5nKSA9PiBTdGRsaWJGYWNhZGVSZWNvcmR9IHJlc29sdmVJZGVudGl0eSAtIEZhY2FkZSBkZXBlbmRlbmN5IHJlc29sdmVyLlxuICogQHByb3BlcnR5IHsobGFuZ3VhZ2U6IHN0cmluZywgbmF0aXZlTW9kdWxlOiBzdHJpbmcsIHJhbmdlPzogc3RyaW5nKSA9PiBTdGRsaWJGYWNhZGVSZWNvcmR9IHJlc29sdmVNb2R1bGUgLSBFeGFjdCBuYXRpdmUgbW9kdWxlIHJlc29sdmVyLlxuICovXG5cbi8qKlxuICogQ3JlYXRlcyBhIGRldGFjaGVkIGltbXV0YWJsZSBzb3VyY2UtbGFuZ3VhZ2UgZmFjYWRlIHJlZ2lzdHJ5LlxuICogQHBhcmFtIHt1bmtub3dufSByZWNvcmRzIC0gT3B0aW9uYWwgZmFjYWRlIGRlZmluaXRpb25zOyBidWlsdC1pbiBxdWFsaWZpY2F0aW9uIGRlZmluaXRpb25zIGJ5IGRlZmF1bHQuXG4gKiBAcmV0dXJucyB7UmVhZG9ubHk8U3RkbGliRmFjYWRlUmVnaXN0cnk+fSBWYWxpZGF0ZWQgZmFjYWRlIHJlZ2lzdHJ5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3RkbGliRmFjYWRlUmVnaXN0cnkocmVjb3JkcyA9IGJ1aWx0aW5GYWNhZGVSZWNvcmRzKCkpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkocmVjb3JkcykpIGludmFsaWRGYWNhZGUoXCJGYWNhZGUgcmVjb3JkcyBtdXN0IGJlIGFuIG9yZGVyZWQgZGVuc2UgYXJyYXkuXCIpXG4gIC8qKiBAdHlwZSB7U3RkbGliRmFjYWRlUmVjb3JkW119ICovXG4gIGNvbnN0IGZhY2FkZXMgPSBbXVxuICAvKiogQHR5cGUge01hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIFN0ZGxpYkZhY2FkZVJlY29yZD4+fSAqL1xuICBjb25zdCBieUlkZW50aXR5ID0gbmV3IE1hcCgpXG4gIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgU3RkbGliRmFjYWRlUmVjb3JkW10+fSAqL1xuICBjb25zdCBieU5hdGl2ZU1vZHVsZSA9IG5ldyBNYXAoKVxuICBjb25zdCBzb3VyY2VJZHMgPSBuZXcgTWFwKClcbiAgY29uc3Qgc291cmNlRmlsZW5hbWVzID0gbmV3IE1hcCgpXG5cbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHJlY29yZHMubGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgY29uc3QgcmVjb3JkID0gdmFsaWRhdGVGYWNhZGVSZWNvcmQocmVjb3Jkc1tpbmRleF0pXG4gICAgY29uc3QgaWRlbnRpdHlLZXkgPSBgJHtyZWNvcmQubGFuZ3VhZ2V9XFwwJHtyZWNvcmQuaWRlbnRpdHl9YFxuICAgIGNvbnN0IHZlcnNpb25zID0gYnlJZGVudGl0eS5nZXQoaWRlbnRpdHlLZXkpID8/IG5ldyBNYXAoKVxuXG4gICAgaWYgKHZlcnNpb25zLmhhcyhyZWNvcmQudmVyc2lvbikpIGludmFsaWRGYWNhZGUoYER1cGxpY2F0ZSBmYWNhZGUgJyR7cmVjb3JkLmlkZW50aXR5fScgdmVyc2lvbiAnJHtyZWNvcmQudmVyc2lvbn0nIGZvciAnJHtyZWNvcmQubGFuZ3VhZ2V9Jy5gKVxuICAgIGlmIChzb3VyY2VJZHMuaGFzKHJlY29yZC5zb3VyY2UuaWQpICYmIHNvdXJjZUlkcy5nZXQocmVjb3JkLnNvdXJjZS5pZCkgIT0gaWRlbnRpdHlLZXkpIHtcbiAgICAgIGludmFsaWRGYWNhZGUoYER1cGxpY2F0ZSBmYWNhZGUgc291cmNlIG1vZHVsZSBpZGVudGl0eSAnJHtyZWNvcmQuc291cmNlLmlkfScuYClcbiAgICB9XG4gICAgaWYgKHNvdXJjZUZpbGVuYW1lcy5oYXMocmVjb3JkLnNvdXJjZS5maWxlbmFtZSkgJiYgc291cmNlRmlsZW5hbWVzLmdldChyZWNvcmQuc291cmNlLmZpbGVuYW1lKSAhPSBpZGVudGl0eUtleSkge1xuICAgICAgaW52YWxpZEZhY2FkZShgRHVwbGljYXRlIGZhY2FkZSBzb3VyY2UgZmlsZW5hbWUgJyR7cmVjb3JkLnNvdXJjZS5maWxlbmFtZX0nLmApXG4gICAgfVxuICAgIHZlcnNpb25zLnNldChyZWNvcmQudmVyc2lvbiwgcmVjb3JkKVxuICAgIGJ5SWRlbnRpdHkuc2V0KGlkZW50aXR5S2V5LCB2ZXJzaW9ucylcbiAgICBzb3VyY2VJZHMuc2V0KHJlY29yZC5zb3VyY2UuaWQsIGlkZW50aXR5S2V5KVxuICAgIHNvdXJjZUZpbGVuYW1lcy5zZXQocmVjb3JkLnNvdXJjZS5maWxlbmFtZSwgaWRlbnRpdHlLZXkpXG4gICAgZmFjYWRlcy5wdXNoKHJlY29yZClcblxuICAgIGZvciAoY29uc3QgbmF0aXZlTW9kdWxlIG9mIHJlY29yZC5uYXRpdmVNb2R1bGVzKSB7XG4gICAgICBjb25zdCBuYXRpdmVLZXkgPSBgJHtyZWNvcmQubGFuZ3VhZ2V9XFwwJHtuYXRpdmVNb2R1bGUuaWRlbnRpdHl9YFxuICAgICAgY29uc3QgbmF0aXZlUmVjb3JkcyA9IGJ5TmF0aXZlTW9kdWxlLmdldChuYXRpdmVLZXkpID8/IFtdXG5cbiAgICAgIG5hdGl2ZVJlY29yZHMucHVzaChyZWNvcmQpXG4gICAgICBieU5hdGl2ZU1vZHVsZS5zZXQobmF0aXZlS2V5LCBuYXRpdmVSZWNvcmRzKVxuICAgIH1cbiAgfVxuXG4gIGZvciAoY29uc3QgcmVjb3JkIG9mIGZhY2FkZXMpIHtcbiAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3kgb2YgcmVjb3JkLmRlcGVuZGVuY2llcykge1xuICAgICAgcmVzb2x2ZUlkZW50aXR5RnJvbVN0b3JlKGJ5SWRlbnRpdHksIGRlcGVuZGVuY3kuaWRlbnRpdHksIHJlY29yZC5sYW5ndWFnZSwgZGVwZW5kZW5jeS5yYW5nZSwgcmVjb3JkLmlkZW50aXR5KVxuICAgIH1cbiAgfVxuICB2YWxpZGF0ZUZhY2FkZURlcGVuZGVuY3lDeWNsZXMoZmFjYWRlcywgYnlJZGVudGl0eSlcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZSgvKiogQHR5cGUge1N0ZGxpYkZhY2FkZVJlZ2lzdHJ5fSAqLyAoe1xuICAgIGZhY2FkZXM6IE9iamVjdC5mcmVlemUoZmFjYWRlcyksXG4gICAgcmVzb2x2ZUZhY2FkZShsYW5ndWFnZSwgbmF0aXZlTW9kdWxlLCBzeW1ib2wsIHJhbmdlKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZU5hdGl2ZUZhY2FkZUZyb21TdG9yZShieU5hdGl2ZU1vZHVsZSwgbGFuZ3VhZ2UsIG5hdGl2ZU1vZHVsZSwgc3ltYm9sLCByYW5nZSlcbiAgICB9LFxuICAgIHJlc29sdmVJZGVudGl0eShpZGVudGl0eSwgbGFuZ3VhZ2UsIHJhbmdlKSB7XG4gICAgICByZXR1cm4gcmVzb2x2ZUlkZW50aXR5RnJvbVN0b3JlKGJ5SWRlbnRpdHksIGlkZW50aXR5LCBsYW5ndWFnZSwgcmFuZ2UpXG4gICAgfSxcbiAgICByZXNvbHZlTW9kdWxlKGxhbmd1YWdlLCBuYXRpdmVNb2R1bGUsIHJhbmdlKSB7XG4gICAgICBjb25zdCByZWNvcmRzID0gYnlOYXRpdmVNb2R1bGUuZ2V0KGAke2xhbmd1YWdlfVxcMCR7bmF0aXZlTW9kdWxlfWApXG5cbiAgICAgIGlmICghcmVjb3JkcykgdW5wcm92ZWRJZGVudGl0eShsYW5ndWFnZSwgbmF0aXZlTW9kdWxlKVxuICAgICAgY29uc3QgaWRlbnRpdGllcyA9IG5ldyBTZXQoLyoqIEB0eXBlIHtTdGRsaWJGYWNhZGVSZWNvcmRbXX0gKi8gKHJlY29yZHMpLm1hcCgoe2lkZW50aXR5fSkgPT4gaWRlbnRpdHkpKVxuXG4gICAgICBpZiAoaWRlbnRpdGllcy5zaXplICE9IDEpIGludmFsaWRGYWNhZGUoYE5hdGl2ZSBmYWNhZGUgbW9kdWxlICcke25hdGl2ZU1vZHVsZX0nIGlzIGFtYmlndW91cyBmb3IgJyR7bGFuZ3VhZ2V9Jy5gKVxuICAgICAgcmV0dXJuIHNlbGVjdEZhY2FkZVZlcnNpb24obmV3IE1hcCgvKiogQHR5cGUge1N0ZGxpYkZhY2FkZVJlY29yZFtdfSAqLyAocmVjb3JkcykubWFwKChyZWNvcmQpID0+IFtyZWNvcmQudmVyc2lvbiwgcmVjb3JkXSkpLFxuICAgICAgICAvKiogQHR5cGUge1N0ZGxpYkZhY2FkZVJlY29yZH0gKi8gKHJlY29yZHNbMF0pLmlkZW50aXR5LCBsYW5ndWFnZSwgcmFuZ2UpXG4gICAgfVxuICB9KSlcbn1cblxuLyoqXG4gKiBSZWplY3RzIGN5Y2xlcyBhZnRlciBldmVyeSB2ZXJzaW9uZWQgZGVwZW5kZW5jeSBoYXMgcmVzb2x2ZWQgc3VjY2Vzc2Z1bGx5LlxuICogQHBhcmFtIHtTdGRsaWJGYWNhZGVSZWNvcmRbXX0gZmFjYWRlcyAtIFZhbGlkYXRlZCBmYWNhZGUgcmVjb3Jkcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgTWFwPHN0cmluZywgU3RkbGliRmFjYWRlUmVjb3JkPj59IHN0b3JlIC0gUmVjb3JkcyBieSBsYW5ndWFnZSBhbmQgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVGYWNhZGVEZXBlbmRlbmN5Q3ljbGVzKGZhY2FkZXMsIHN0b3JlKSB7XG4gIGNvbnN0IGFjdGl2ZSA9IG5ldyBTZXQoKVxuICBjb25zdCBjb21wbGV0ZSA9IG5ldyBTZXQoKVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgb25lIGV4YWN0IHNlbGVjdGVkIGZhY2FkZSB2ZXJzaW9uLlxuICAgKiBAcGFyYW0ge1N0ZGxpYkZhY2FkZVJlY29yZH0gcmVjb3JkIC0gRmFjYWRlIHJlY29yZC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiB2aXNpdChyZWNvcmQpIHtcbiAgICBjb25zdCBrZXkgPSBgJHtyZWNvcmQubGFuZ3VhZ2V9XFwwJHtyZWNvcmQuaWRlbnRpdHl9XFwwJHtyZWNvcmQudmVyc2lvbn1gXG5cbiAgICBpZiAoY29tcGxldGUuaGFzKGtleSkpIHJldHVyblxuICAgIGlmIChhY3RpdmUuaGFzKGtleSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSBkZXBlbmRlbmN5IGN5Y2xlIGluY2x1ZGVzICcke3JlY29yZC5pZGVudGl0eX0nLmApXG4gICAgYWN0aXZlLmFkZChrZXkpXG4gICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIHJlY29yZC5kZXBlbmRlbmNpZXMpIHtcbiAgICAgIHZpc2l0KHJlc29sdmVJZGVudGl0eUZyb21TdG9yZShzdG9yZSwgZGVwZW5kZW5jeS5pZGVudGl0eSwgcmVjb3JkLmxhbmd1YWdlLCBkZXBlbmRlbmN5LnJhbmdlLCByZWNvcmQuaWRlbnRpdHkpKVxuICAgIH1cbiAgICBhY3RpdmUuZGVsZXRlKGtleSlcbiAgICBjb21wbGV0ZS5hZGQoa2V5KVxuICB9XG5cbiAgZm9yIChjb25zdCByZWNvcmQgb2YgZmFjYWRlcykgdmlzaXQocmVjb3JkKVxufVxuXG4vKipcbiAqIExpc3RzIGFsbCBidWlsdC1pbiBwdWJsaWMgYW5kIGludGVybmFsIGZhY2FkZSBtb2R1bGVzIGluIHN0YWJsZSBvcmRlci5cbiAqIEByZXR1cm5zIHtyZWFkb25seSBTdGRsaWJGYWNhZGVSZWNvcmRbXX0gSW1tdXRhYmxlIGZhY2FkZSBkZWZpbml0aW9ucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RTdGRsaWJGYWNhZGVzKCkge1xuICByZXR1cm4gc3RkbGliRmFjYWRlUmVnaXN0cnkuZmFjYWRlc1xufVxuXG4vKipcbiAqIFJlc29sdmVzIG9uZSBidWlsdC1pbiBmYWNhZGUgZnJvbSBwYXJzZXItcHJvdmVkIG5hdGl2ZSBtb2R1bGUgYW5kIHN5bWJvbCBpZGVudGl0aWVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGxhbmd1YWdlIC0gU291cmNlIGxhbmd1YWdlLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hdGl2ZU1vZHVsZSAtIEV4YWN0IG5hdGl2ZSBtb2R1bGUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge3N0cmluZ30gc3ltYm9sIC0gRXhhY3QgaW1wb3J0ZWQgb3IgcXVhbGlmaWVkIHN5bWJvbC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbcmFuZ2VdIC0gQ29tcGF0aWJsZSBmYWNhZGUgdmVyc2lvbiByYW5nZS5cbiAqIEByZXR1cm5zIHtTdGRsaWJGYWNhZGVSZWNvcmR9IEltbXV0YWJsZSBmYWNhZGUgZGVmaW5pdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTdGRsaWJGYWNhZGUobGFuZ3VhZ2UsIG5hdGl2ZU1vZHVsZSwgc3ltYm9sLCByYW5nZSkge1xuICByZXR1cm4gc3RkbGliRmFjYWRlUmVnaXN0cnkucmVzb2x2ZUZhY2FkZShsYW5ndWFnZSwgbmF0aXZlTW9kdWxlLCBzeW1ib2wsIHJhbmdlKVxufVxuXG4vKipcbiAqIFJlc29sdmVzIGEgZGVwZW5kZW5jeS1maXJzdCwgY3ljbGUtZnJlZSBmYWNhZGUgbW9kdWxlIGNsb3N1cmUuXG4gKiBAcGFyYW0ge1N0ZGxpYkZhY2FkZVJlY29yZFtdfSByb290cyAtIFBhcnNlci1zZWxlY3RlZCBmYWNhZGUgcm9vdHMuXG4gKiBAcGFyYW0ge1JlYWRvbmx5PFN0ZGxpYkZhY2FkZVJlZ2lzdHJ5Pn0gW3JlZ2lzdHJ5XSAtIEZhY2FkZSByZWdpc3RyeS5cbiAqIEByZXR1cm5zIHtTdGRsaWJGYWNhZGVSZWNvcmRbXX0gU3RhYmxlIGRlcGVuZGVuY3ktZmlyc3QgY2xvc3VyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTdGRsaWJGYWNhZGVDbG9zdXJlKHJvb3RzLCByZWdpc3RyeSA9IHN0ZGxpYkZhY2FkZVJlZ2lzdHJ5KSB7XG4gIGNvbnN0IGFjdGl2ZSA9IG5ldyBTZXQoKVxuICBjb25zdCBjb21wbGV0ZSA9IG5ldyBTZXQoKVxuICAvKiogQHR5cGUge1N0ZGxpYkZhY2FkZVJlY29yZFtdfSAqL1xuICBjb25zdCByZXN1bHQgPSBbXVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgb25lIHNlbGVjdGVkIGZhY2FkZSBhbmQgaXRzIGRlY2xhcmVkIGRlcGVuZGVuY2llcy5cbiAgICogQHBhcmFtIHtTdGRsaWJGYWNhZGVSZWNvcmR9IHJlY29yZCAtIEZhY2FkZSB0byB2aXNpdC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiB2aXNpdChyZWNvcmQpIHtcbiAgICBjb25zdCBrZXkgPSBgJHtyZWNvcmQubGFuZ3VhZ2V9XFwwJHtyZWNvcmQuaWRlbnRpdHl9XFwwJHtyZWNvcmQudmVyc2lvbn1gXG5cbiAgICBpZiAoY29tcGxldGUuaGFzKGtleSkpIHJldHVyblxuICAgIGlmIChhY3RpdmUuaGFzKGtleSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSBkZXBlbmRlbmN5IGN5Y2xlIGluY2x1ZGVzICcke3JlY29yZC5pZGVudGl0eX0nLmApXG4gICAgYWN0aXZlLmFkZChrZXkpXG4gICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIHJlY29yZC5kZXBlbmRlbmNpZXMpIHtcbiAgICAgIHZpc2l0KHJlZ2lzdHJ5LnJlc29sdmVJZGVudGl0eShkZXBlbmRlbmN5LmlkZW50aXR5LCByZWNvcmQubGFuZ3VhZ2UsIGRlcGVuZGVuY3kucmFuZ2UpKVxuICAgIH1cbiAgICBhY3RpdmUuZGVsZXRlKGtleSlcbiAgICBjb21wbGV0ZS5hZGQoa2V5KVxuICAgIHJlc3VsdC5wdXNoKHJlY29yZClcbiAgfVxuXG4gIGZvciAoY29uc3Qgcm9vdCBvZiByb290cykgdmlzaXQocm9vdClcbiAgcmV0dXJuIHJlc3VsdFxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGRldGFjaGVkLCBkZXRlcm1pbmlzdGljIHByb2dyYW0gZGVzY3JpcHRvciBmb3Igb25lIHNlbGVjdGVkIGZhY2FkZSBjbG9zdXJlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTGFuZ3VhZ2V9IGxhbmd1YWdlIC0gU291cmNlIGxhbmd1YWdlIHByb2ZpbGUuXG4gKiBAcGFyYW0ge1N0ZGxpYkZhY2FkZVJlY29yZFtdfSBmYWNhZGVzIC0gRGVwZW5kZW5jeS1maXJzdCBzZWxlY3RlZCBmYWNhZGUgcmVjb3Jkcy5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlN0ZGxpYkZhY2FkZVByb2dyYW1EZXNjcmlwdG9yfSBQbGFpbiBwcm9ncmFtIGRlc2NyaXB0b3IuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGRsaWJGYWNhZGVQcm9ncmFtRGVzY3JpcHRvcihsYW5ndWFnZSwgZmFjYWRlcykge1xuICByZXR1cm4ge1xuICAgIGxhbmd1YWdlLFxuICAgIG1vZHVsZXM6IGZhY2FkZXMubWFwKChmYWNhZGUpID0+ICh7XG4gICAgICBkZXBlbmRlbmNpZXM6IGZhY2FkZS5kZXBlbmRlbmNpZXMubWFwKChkZXBlbmRlbmN5KSA9PiAoey4uLmRlcGVuZGVuY3l9KSksXG4gICAgICBpZGVudGl0eTogZmFjYWRlLmlkZW50aXR5LFxuICAgICAgbmF0aXZlTW9kdWxlczogZmFjYWRlLm5hdGl2ZU1vZHVsZXMubWFwKChtb2R1bGUpID0+ICh7Li4ubW9kdWxlLFxuICAgICAgICAuLi4obW9kdWxlLmtpbmQgPT0gXCJidWlsdGluXCIgPyB7Zm9ybXM6IFsuLi5tb2R1bGUuZm9ybXNdfSA6IHt9KSwgc3ltYm9sczogWy4uLm1vZHVsZS5zeW1ib2xzXX0pKSxcbiAgICAgIHB1YmxpY0RlY2xhcmF0aW9uczogZmFjYWRlLnB1YmxpY0RlY2xhcmF0aW9ucy5tYXAoZGV0YWNoUHVibGljRGVjbGFyYXRpb24pLFxuICAgICAgcmVxdWlyZW1lbnRzOiBmYWNhZGUucmVxdWlyZW1lbnRzLm1hcCgocmVxdWlyZW1lbnQpID0+ICh7Li4ucmVxdWlyZW1lbnQsIG9wZXJhdGlvbnM6IFsuLi5yZXF1aXJlbWVudC5vcGVyYXRpb25zXX0pKSxcbiAgICAgIHJ1bnRpbWVQcm9maWxlOiBmYWNhZGUucnVudGltZVByb2ZpbGUsXG4gICAgICBzb3VyY2VNb2R1bGU6IGZhY2FkZS5zb3VyY2UuaWQsXG4gICAgICB2ZXJzaW9uOiBmYWNhZGUudmVyc2lvbixcbiAgICAgIHZpc2liaWxpdHk6IGZhY2FkZS52aXNpYmlsaXR5XG4gICAgfSkpLFxuICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZFN0ZGxpYkZhY2FkZXNcIixcbiAgICB2ZXJzaW9uOiAxXG4gIH1cbn1cblxuLyoqXG4gKiBEZXJpdmVzIGNvbXBpbGVyLW93bmVkIHNlbWFudGljIGNhcGFiaWxpdHkgYXV0aG9yaXR5IGZyb20gc2VsZWN0ZWQgZmFjYWRlIHJlcXVpcmVtZW50cy5cbiAqIFRoZSBpbml0aWFsIGV4ZWN1dGFibGUgcXVhbGlmaWNhdGlvbiBjb3JwdXMgaW50ZW50aW9uYWxseSB0YXJnZXRzIG9uZSBjYW5vbmljYWwgbW9kdWxlLlxuICogQHBhcmFtIHtTdGRsaWJGYWNhZGVSZWNvcmRbXX0gcmVjb3JkcyAtIFNlbGVjdGVkIGZhY2FkZSBjbG9zdXJlLlxuICogQHJldHVybnMge3tjb250cmFjdDoge2NvbnRyYWN0VmVyc2lvbjogc3RyaW5nLCBpZGVudGl0eTogc3RyaW5nfSwgaW5wdXQ6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2FwYWJpbGl0eUF1dGhvcml0eUlucHV0fSB8IHtjb250cmFjdHM6IHtjb250cmFjdFZlcnNpb246IHN0cmluZywgaWRlbnRpdHk6IHN0cmluZ31bXSwgaW5wdXQ6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2FwYWJpbGl0eUF1dGhvcml0eUlucHV0fSB8IG51bGx9IEF1dGhvcml0eSBpbnB1dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhY2FkZUNhcGFiaWxpdHlBdXRob3JpdHkocmVjb3Jkcykge1xuICBjb25zdCByZXF1aXJlbWVudHMgPSByZWNvcmRzLmZsYXRNYXAoKHJlY29yZCkgPT4gcmVjb3JkLnJlcXVpcmVtZW50cylcblxuICBpZiAocmVxdWlyZW1lbnRzLmxlbmd0aCA9PSAwKSByZXR1cm4gbnVsbFxuICBjb25zdCBpZGVudGl0aWVzID0gbmV3IFNldChyZXF1aXJlbWVudHMubWFwKCh7bW9kdWxlfSkgPT4gbW9kdWxlKSlcbiAgY29uc3QgcmFuZ2VzID0gbmV3IFNldChyZXF1aXJlbWVudHMubWFwKCh7cmFuZ2V9KSA9PiByYW5nZSkpXG5cbiAgY29uc3QgdGFzazAzNyA9IHJlY29yZHMuc29tZSgoe2lkZW50aXR5fSkgPT4gaWRlbnRpdHkuc3RhcnRzV2l0aChcInNlbWFudGlmb2xkLnRhc2swMzcuXCIpKVxuXG4gIGlmICh0YXNrMDM3KSB7XG4gICAgY29uc3QgcmVxdWlyZW1lbnRCeU1vZHVsZSA9IG5ldyBNYXAoKVxuXG4gICAgZm9yIChjb25zdCByZXF1aXJlbWVudCBvZiByZXF1aXJlbWVudHMpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnQgPSByZXF1aXJlbWVudEJ5TW9kdWxlLmdldChyZXF1aXJlbWVudC5tb2R1bGUpXG5cbiAgICAgIGlmIChjdXJyZW50ICYmIGN1cnJlbnQucmFuZ2UgIT0gcmVxdWlyZW1lbnQucmFuZ2UpIGludmFsaWRGYWNhZGUoXCJUYXNrIDAzNyBmYWNhZGUgcmVxdWlyZW1lbnRzIGRpc2FncmVlIG9uIGEgY2Fub25pY2FsIHJhbmdlLlwiKVxuICAgICAgY29uc3Qgb3BlcmF0aW9ucyA9IG5ldyBTZXQoY3VycmVudD8ub3BlcmF0aW9ucyA/PyBbXSlcblxuICAgICAgZm9yIChjb25zdCBvcGVyYXRpb24gb2YgcmVxdWlyZW1lbnQub3BlcmF0aW9ucykgb3BlcmF0aW9ucy5hZGQob3BlcmF0aW9uKVxuICAgICAgcmVxdWlyZW1lbnRCeU1vZHVsZS5zZXQocmVxdWlyZW1lbnQubW9kdWxlLCB7b3BlcmF0aW9ucywgcmFuZ2U6IHJlcXVpcmVtZW50LnJhbmdlfSlcbiAgICB9XG4gICAgY29uc3QgbW9kdWxlcyA9IFsuLi5yZXF1aXJlbWVudEJ5TW9kdWxlLmVudHJpZXMoKV0ubWFwKChbaWRlbnRpdHksIHJlcXVpcmVtZW50XSkgPT4ge1xuICAgICAgY29uc3QgY29udHJhY3QgPSByZXNvbHZlU3RkbGliTW9kdWxlKGlkZW50aXR5LCByZXF1aXJlbWVudC5yYW5nZSlcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2FwYWJpbGl0aWVzOiBbe1xuICAgICAgICAgIGZhaWx1cmVzOiBjb250cmFjdC5mYWlsdXJlcy5tYXAoKHtuYW1lfSkgPT4gKHtuYW1lfSkpLFxuICAgICAgICAgIG5hbWU6IGNhbm9uaWNhbENhcGFiaWxpdHlOYW1lKGlkZW50aXR5KSxcbiAgICAgICAgICBvcGVyYXRpb25zOiBjb250cmFjdC5vcGVyYXRpb25zLmZpbHRlcigoe25hbWV9KSA9PiByZXF1aXJlbWVudC5vcGVyYXRpb25zLmhhcyhuYW1lKSkubWFwKChvcGVyYXRpb24pID0+ICh7XG4gICAgICAgICAgICBlZmZlY3RzOiAvKiogQHR5cGUge1tcImhvc3RcIl19ICovIChbLi4ub3BlcmF0aW9uLmVmZmVjdHNdKSxcbiAgICAgICAgICAgIGZhaWx1cmVzOiBvcGVyYXRpb24uZmFpbHVyZXMubWFwKGRldGFjaENhbm9uaWNhbFJlZmVyZW5jZSksXG4gICAgICAgICAgICBuYW1lOiBvcGVyYXRpb24ubmFtZSxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IG9wZXJhdGlvbi5wYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyKSA9PiAoe1xuICAgICAgICAgICAgICBuYW1lOiBwYXJhbWV0ZXIubmFtZSxcbiAgICAgICAgICAgICAgdHlwZTogY2Fub25pY2FsQ2FwYWJpbGl0eVBhcmFtZXRlclR5cGUocGFyYW1ldGVyLnR5cGUpXG4gICAgICAgICAgICB9KSksXG4gICAgICAgICAgICByZXNvdXJjZUZsb3c6IGRldGFjaFJlc291cmNlRmxvdyhvcGVyYXRpb24ucmVzb3VyY2VGbG93KSxcbiAgICAgICAgICAgIHJldHVyblR5cGU6IGNhbm9uaWNhbENhcGFiaWxpdHlUeXBlKG9wZXJhdGlvbi5yZXR1cm5UeXBlKVxuICAgICAgICAgIH0pKSxcbiAgICAgICAgICByZXNvdXJjZXM6IGNvbnRyYWN0LnJlc291cmNlcy5tYXAoKHtuYW1lfSkgPT4gKHtuYW1lfSkpXG4gICAgICAgIH1dLFxuICAgICAgICBjb250cmFjdFZlcnNpb246IHJlcXVpcmVtZW50LnJhbmdlLFxuICAgICAgICBpZGVudGl0eVxuICAgICAgfVxuICAgIH0pXG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udHJhY3RzOiBtb2R1bGVzLm1hcCgoe2NvbnRyYWN0VmVyc2lvbiwgaWRlbnRpdHl9KSA9PiAoe2NvbnRyYWN0VmVyc2lvbiwgaWRlbnRpdHl9KSksXG4gICAgICBpbnB1dDoge2lkOiBcInNlbWFudGlmb2xkLnRhc2swMzcuYmxvY2tpbmctdGNwXCIsIG1vZHVsZXMsIHNjaGVtYTogXCJTZW1hbnRpZm9sZENhcGFiaWxpdHlBdXRob3JpdHlcIiwgc2NoZW1hVmVyc2lvbjogMn1cbiAgICB9XG4gIH1cbiAgaWYgKGlkZW50aXRpZXMuc2l6ZSAhPSAxIHx8IHJhbmdlcy5zaXplICE9IDEpIHtcbiAgICBpbnZhbGlkRmFjYWRlKFwiVGhlIFRhc2sgMDM2IHF1YWxpZmljYXRpb24gZmFjYWRlIGNsb3N1cmUgbXVzdCByZXNvbHZlIG9uZSBjYW5vbmljYWwgbW9kdWxlIGFuZCB2ZXJzaW9uIHJhbmdlLlwiKVxuICB9XG4gIGNvbnN0IGlkZW50aXR5ID0gcmVxdWlyZW1lbnRzWzBdLm1vZHVsZVxuICBjb25zdCBjb250cmFjdFZlcnNpb24gPSByZXF1aXJlbWVudHNbMF0ucmFuZ2VcbiAgY29uc3QgY29udHJhY3QgPSByZXNvbHZlU3RkbGliTW9kdWxlKGlkZW50aXR5LCBjb250cmFjdFZlcnNpb24pXG5cbiAgcmV0dXJuIHtcbiAgICBjb250cmFjdDoge2NvbnRyYWN0VmVyc2lvbiwgaWRlbnRpdHl9LFxuICAgIGlucHV0OiB7XG4gICAgICBjYXBhYmlsaXRpZXM6IFt7XG4gICAgICAgIGZhaWx1cmVzOiBjb250cmFjdC5mYWlsdXJlcy5tYXAoKHtuYW1lfSkgPT4gKHtuYW1lfSkpLFxuICAgICAgICBuYW1lOiBcIlJlc291cmNlUHJvYmVcIixcbiAgICAgICAgb3BlcmF0aW9uczogY29udHJhY3Qub3BlcmF0aW9ucy5tYXAoKG9wZXJhdGlvbikgPT4gKHtcbiAgICAgICAgICBlZmZlY3RzOiBbLi4ub3BlcmF0aW9uLmVmZmVjdHNdLFxuICAgICAgICAgIGZhaWx1cmVzOiBbLi4ub3BlcmF0aW9uLmZhaWx1cmVzXSxcbiAgICAgICAgICBuYW1lOiBvcGVyYXRpb24ubmFtZSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiBvcGVyYXRpb24ucGFyYW1ldGVycy5tYXAoKHBhcmFtZXRlcikgPT4gKHtcbiAgICAgICAgICAgIG5hbWU6IHBhcmFtZXRlci5uYW1lLFxuICAgICAgICAgICAgdHlwZTogY2Fub25pY2FsQ2FwYWJpbGl0eVBhcmFtZXRlclR5cGUocGFyYW1ldGVyLnR5cGUpXG4gICAgICAgICAgfSkpLFxuICAgICAgICAgIHJlc291cmNlRmxvdzogLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkNhcGFiaWxpdHlSZXNvdXJjZUZsb3dJbnB1dH0gKi8gKHsuLi5vcGVyYXRpb24ucmVzb3VyY2VGbG93fSksXG4gICAgICAgICAgcmV0dXJuVHlwZTogY2Fub25pY2FsQ2FwYWJpbGl0eVR5cGUob3BlcmF0aW9uLnJldHVyblR5cGUpXG4gICAgICAgIH0pKSxcbiAgICAgICAgcmVzb3VyY2VzOiBjb250cmFjdC5yZXNvdXJjZXMubWFwKCh7bmFtZX0pID0+ICh7bmFtZX0pKVxuICAgICAgfV0sXG4gICAgICBjb250cmFjdFZlcnNpb24sXG4gICAgICBpZDogaWRlbnRpdHksXG4gICAgICBzY2hlbWE6IFwiU2VtYW50aWZvbGRDYXBhYmlsaXR5QXV0aG9yaXR5XCIsXG4gICAgICBzY2hlbWFWZXJzaW9uOiAxXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIHJlZ2lzdHJ5IGNvbnRyYWN0IHR5cGUgdG8gYSBjYXBhYmlsaXR5LWF1dGhvcml0eSBpbnB1dCB0eXBlLlxuICogQHBhcmFtIHtzdHJpbmcgfCBpbXBvcnQoXCIuL3NlbWFudGljL3N0ZGxpYi5qc1wiKS5DYW5vbmljYWxEZWNsYXJhdGlvblJlZmVyZW5jZX0gdHlwZSAtIENhbm9uaWNhbCBjb250cmFjdCB0eXBlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuRnVuY3Rpb25SZXR1cm5UeXBlTmFtZSB8IHtraW5kOiBcIk93bmVkUmVzb3VyY2VUeXBlXCIsIHJlc291cmNlOiBzdHJpbmcgfCBpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLkNhcGFiaWxpdHlEZWNsYXJhdGlvblJlZmVyZW5jZUlucHV0fSB8IHtraW5kOiBcIk9wdGlvbmFsVHlwZVwiLCB2YWx1ZVR5cGU6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZX19IFNlbWFudGljIGF1dGhvcml0eSB0eXBlLlxuICovXG5mdW5jdGlvbiBjYW5vbmljYWxDYXBhYmlsaXR5VHlwZSh0eXBlKSB7XG4gIGlmICh0eXBlb2YgdHlwZSAhPSBcInN0cmluZ1wiKSByZXR1cm4ge2tpbmQ6IFwiT3duZWRSZXNvdXJjZVR5cGVcIiwgcmVzb3VyY2U6IGRldGFjaENhbm9uaWNhbFJlZmVyZW5jZSh0eXBlKX1cbiAgaWYgKHR5cGUgPT0gXCJ2b2lkXCIgfHwgdHlwZSA9PSBcImJvb2xlYW5cIiB8fCB0eXBlID09IFwiaW50ZWdlclwiIHx8IHR5cGUgPT0gXCJzdHJpbmdcIikgcmV0dXJuIHR5cGVcbiAgaWYgKHR5cGUuc3RhcnRzV2l0aChcIm9wdGlvbmFsOlwiKSkgcmV0dXJuIHtraW5kOiBcIk9wdGlvbmFsVHlwZVwiLFxuICAgIHZhbHVlVHlwZTogLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZU5hbWV9ICovICh0eXBlLnNsaWNlKFwib3B0aW9uYWw6XCIubGVuZ3RoKSl9XG4gIHJldHVybiB7a2luZDogXCJPd25lZFJlc291cmNlVHlwZVwiLCByZXNvdXJjZTogdHlwZX1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIG5vbi12b2lkIHJlZ2lzdHJ5IHBhcmFtZXRlciB0eXBlIHRvIGNhcGFiaWxpdHktYXV0aG9yaXR5IGlucHV0LlxuICogQHBhcmFtIHtzdHJpbmcgfCBpbXBvcnQoXCIuL3NlbWFudGljL3N0ZGxpYi5qc1wiKS5DYW5vbmljYWxEZWNsYXJhdGlvblJlZmVyZW5jZX0gdHlwZSAtIENhbm9uaWNhbCBwYXJhbWV0ZXIgdHlwZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZU5hbWUgfCB7a2luZDogXCJPd25lZFJlc291cmNlVHlwZVwiLCByZXNvdXJjZTogc3RyaW5nfSB8IHtraW5kOiBcIk9wdGlvbmFsVHlwZVwiLCB2YWx1ZVR5cGU6IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZX19IFNlbWFudGljIHBhcmFtZXRlciB0eXBlLlxuICovXG5mdW5jdGlvbiBjYW5vbmljYWxDYXBhYmlsaXR5UGFyYW1ldGVyVHlwZSh0eXBlKSB7XG4gIGNvbnN0IGNvbnZlcnRlZCA9IGNhbm9uaWNhbENhcGFiaWxpdHlUeXBlKHR5cGUpXG5cbiAgaWYgKGNvbnZlcnRlZCA9PSBcInZvaWRcIikgaW52YWxpZEZhY2FkZShcIkNhbm9uaWNhbCBmYWNhZGUgcmVxdWlyZW1lbnQgcGFyYW1ldGVycyBjYW5ub3QgaGF2ZSB2b2lkIHR5cGUuXCIpXG4gIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZSB8IHtraW5kOiBcIk93bmVkUmVzb3VyY2VUeXBlXCIsIHJlc291cmNlOiBzdHJpbmd9IHwge2tpbmQ6IFwiT3B0aW9uYWxUeXBlXCIsIHZhbHVlVHlwZTogaW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVOYW1lfX0gKi8gKGNvbnZlcnRlZClcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBvbmUgZGVwZW5kZW5jeSBpZGVudGl0eSBmcm9tIGEgdmFsaWRhdGVkIHJlZ2lzdHJ5IHN0b3JlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBTdGRsaWJGYWNhZGVSZWNvcmQ+Pn0gc3RvcmUgLSBSZWNvcmRzIGJ5IGxhbmd1YWdlIGFuZCBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIEZhY2FkZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkfSByYW5nZSAtIENvbXBhdGlibGUgcmFuZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gW293bmVyXSAtIERlcGVuZGluZyBmYWNhZGUgZm9yIGRpYWdub3N0aWNzLlxuICogQHJldHVybnMge1N0ZGxpYkZhY2FkZVJlY29yZH0gSGlnaGVzdCBjb21wYXRpYmxlIHJlY29yZC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUlkZW50aXR5RnJvbVN0b3JlKHN0b3JlLCBpZGVudGl0eSwgbGFuZ3VhZ2UsIHJhbmdlLCBvd25lcikge1xuICBjb25zdCB2ZXJzaW9ucyA9IHN0b3JlLmdldChgJHtsYW5ndWFnZX1cXDAke2lkZW50aXR5fWApXG5cbiAgaWYgKCF2ZXJzaW9ucykge1xuICAgIGludmFsaWRGYWNhZGUob3duZXIgPyBgRmFjYWRlICcke293bmVyfScgZGVwZW5kcyBvbiB1bmtub3duIGZhY2FkZSAnJHtpZGVudGl0eX0nIGZvciAnJHtsYW5ndWFnZX0nLmAgOlxuICAgICAgYFVua25vd24gZmFjYWRlIGlkZW50aXR5ICcke2lkZW50aXR5fScgZm9yICcke2xhbmd1YWdlfScuYClcbiAgfVxuICByZXR1cm4gc2VsZWN0RmFjYWRlVmVyc2lvbigvKiogQHR5cGUge01hcDxzdHJpbmcsIFN0ZGxpYkZhY2FkZVJlY29yZD59ICovICh2ZXJzaW9ucyksIGlkZW50aXR5LCBsYW5ndWFnZSwgcmFuZ2UpXG59XG5cbi8qKlxuICogUmVzb2x2ZXMgb25lIGV4YWN0IG5hdGl2ZSBpZGVudGl0eSBmcm9tIGEgdmFsaWRhdGVkIHJlZ2lzdHJ5IHN0b3JlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBTdGRsaWJGYWNhZGVSZWNvcmRbXT59IHN0b3JlIC0gUmVjb3JkcyBieSBsYW5ndWFnZSBhbmQgbmF0aXZlIG1vZHVsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYXRpdmVNb2R1bGUgLSBFeGFjdCBwYXJzZXItb3duZWQgbmF0aXZlIG1vZHVsZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgLSBFeGFjdCBzb3VyY2UtdmlzaWJsZSBzeW1ib2wuXG4gKiBAcGFyYW0ge3N0cmluZyB8IHVuZGVmaW5lZH0gcmFuZ2UgLSBDb21wYXRpYmxlIHJhbmdlLlxuICogQHJldHVybnMge1N0ZGxpYkZhY2FkZVJlY29yZH0gSGlnaGVzdCBjb21wYXRpYmxlIHJlY29yZC5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZU5hdGl2ZUZhY2FkZUZyb21TdG9yZShzdG9yZSwgbGFuZ3VhZ2UsIG5hdGl2ZU1vZHVsZSwgc3ltYm9sLCByYW5nZSkge1xuICBpZiAoIXN1cHBvcnRlZExhbmd1YWdlcy5oYXMobGFuZ3VhZ2UpIHx8IHR5cGVvZiBuYXRpdmVNb2R1bGUgIT0gXCJzdHJpbmdcIiB8fCBuYXRpdmVNb2R1bGUubGVuZ3RoID09IDApIHtcbiAgICB1bnByb3ZlZElkZW50aXR5KGxhbmd1YWdlLCBuYXRpdmVNb2R1bGUpXG4gIH1cbiAgY29uc3QgbW9kdWxlUmVjb3JkcyA9IHN0b3JlLmdldChgJHtsYW5ndWFnZX1cXDAke25hdGl2ZU1vZHVsZX1gKVxuXG4gIGlmICghbW9kdWxlUmVjb3JkcykgdW5wcm92ZWRJZGVudGl0eShsYW5ndWFnZSwgbmF0aXZlTW9kdWxlKVxuICBjb25zdCBzeW1ib2xSZWNvcmRzID0gLyoqIEB0eXBlIHtTdGRsaWJGYWNhZGVSZWNvcmRbXX0gKi8gKG1vZHVsZVJlY29yZHMpLmZpbHRlcigocmVjb3JkKSA9PiByZWNvcmQubmF0aXZlTW9kdWxlcy5zb21lKChtb2R1bGUpID0+XG4gICAgbW9kdWxlLmlkZW50aXR5ID09IG5hdGl2ZU1vZHVsZSAmJiBtb2R1bGUuc3ltYm9scy5pbmNsdWRlcyhzeW1ib2wpKSlcblxuICBpZiAoc3ltYm9sUmVjb3Jkcy5sZW5ndGggPT0gMCkgdW5zdXBwb3J0ZWRNZW1iZXIobGFuZ3VhZ2UsIG5hdGl2ZU1vZHVsZSwgc3ltYm9sKVxuICBjb25zdCBpZGVudGl0aWVzID0gbmV3IFNldChzeW1ib2xSZWNvcmRzLm1hcCgoe2lkZW50aXR5fSkgPT4gaWRlbnRpdHkpKVxuXG4gIGlmIChpZGVudGl0aWVzLnNpemUgIT0gMSkgaW52YWxpZEZhY2FkZShgTmF0aXZlIGZhY2FkZSBpZGVudGl0eSAnJHtuYXRpdmVNb2R1bGV9IyR7c3ltYm9sfScgaXMgYW1iaWd1b3VzIGZvciAnJHtsYW5ndWFnZX0nLmApXG4gIGNvbnN0IHZlcnNpb25zID0gbmV3IE1hcChzeW1ib2xSZWNvcmRzLm1hcCgocmVjb3JkKSA9PiBbcmVjb3JkLnZlcnNpb24sIHJlY29yZF0pKVxuXG4gIHJldHVybiBzZWxlY3RGYWNhZGVWZXJzaW9uKHZlcnNpb25zLCBzeW1ib2xSZWNvcmRzWzBdLmlkZW50aXR5LCBsYW5ndWFnZSwgcmFuZ2UpXG59XG5cbi8qKlxuICogU2VsZWN0cyB0aGUgaGlnaGVzdCBmYWNhZGUgdmVyc2lvbiBzYXRpc2Z5aW5nIGEgY2Fub25pY2FsIHJhbmdlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBTdGRsaWJGYWNhZGVSZWNvcmQ+fSB2ZXJzaW9ucyAtIFJlY29yZHMgYnkgZXhhY3QgdmVyc2lvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIEZhY2FkZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkfSByYW5nZSAtIENvbXBhdGlibGUgcmFuZ2UuXG4gKiBAcmV0dXJucyB7U3RkbGliRmFjYWRlUmVjb3JkfSBTZWxlY3RlZCByZWNvcmQuXG4gKi9cbmZ1bmN0aW9uIHNlbGVjdEZhY2FkZVZlcnNpb24odmVyc2lvbnMsIGlkZW50aXR5LCBsYW5ndWFnZSwgcmFuZ2UpIHtcbiAgY29uc3QgcGFyc2VkUmFuZ2UgPSByYW5nZSA9PT0gdW5kZWZpbmVkID8ge2xvd2VyOiAvKiogQHR5cGUge1tudW1iZXIsIG51bWJlciwgbnVtYmVyXX0gKi8gKFswLCAwLCAwXSksIHVwcGVyOiBudWxsfSA6XG4gICAgcGFyc2VTdGRsaWJWZXJzaW9uUmFuZ2UocmFuZ2UpXG5cbiAgaWYgKCFwYXJzZWRSYW5nZSkgZmFjYWRlVmVyc2lvbk1hbGZvcm1lZChsYW5ndWFnZSwgU3RyaW5nKHJhbmdlKSlcbiAgLyoqIEB0eXBlIHtbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWR9ICovXG4gIGxldCBzZWxlY3RlZFxuXG4gIGZvciAoY29uc3QgdmVyc2lvbiBvZiB2ZXJzaW9ucy5rZXlzKCkpIHtcbiAgICBjb25zdCBwYXJzZWQgPSAvKiogQHR5cGUge1tudW1iZXIsIG51bWJlciwgbnVtYmVyXX0gKi8gKHBhcnNlU3RkbGliVmVyc2lvbih2ZXJzaW9uKSlcblxuICAgIGlmIChzdGRsaWJWZXJzaW9uU2F0aXNmaWVzKHBhcnNlZCwgcGFyc2VkUmFuZ2UpICYmICghc2VsZWN0ZWQgfHwgY29tcGFyZVN0ZGxpYlZlcnNpb25zKHBhcnNlZCwgc2VsZWN0ZWQpID4gMCkpIHNlbGVjdGVkID0gcGFyc2VkXG4gIH1cbiAgaWYgKCFzZWxlY3RlZCkgZmFjYWRlVmVyc2lvbkluY29tcGF0aWJsZShsYW5ndWFnZSwgaWRlbnRpdHkpXG5cbiAgcmV0dXJuIC8qKiBAdHlwZSB7U3RkbGliRmFjYWRlUmVjb3JkfSAqLyAodmVyc2lvbnMuZ2V0KHNlbGVjdGVkLmpvaW4oXCIuXCIpKSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYW5kIGRldGFjaGVzIG9uZSBleGVjdXRhYmxlIGZhY2FkZSByZWNvcmQuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSByZWNvcmQuXG4gKiBAcmV0dXJucyB7U3RkbGliRmFjYWRlUmVjb3JkfSBEZXRhY2hlZCBmcm96ZW4gcmVjb3JkLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUZhY2FkZVJlY29yZChjYW5kaWRhdGUpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGNhbmRpZGF0ZSkpIGludmFsaWRGYWNhZGUoXCJFdmVyeSBmYWNhZGUgcmVjb3JkIG11c3QgYmUgYSBwbGFpbiBvYmplY3QuXCIpXG4gIHJlcXVpcmVLZXlzKGNhbmRpZGF0ZSwgW1wiZGVwZW5kZW5jaWVzXCIsIFwiaWRlbnRpdHlcIiwgXCJsYW5ndWFnZVwiLCBcIm5hdGl2ZU1vZHVsZXNcIiwgXCJwdWJsaWNEZWNsYXJhdGlvbnNcIiwgXCJyZXF1aXJlbWVudHNcIixcbiAgICBcInJ1bnRpbWVQcm9maWxlXCIsIFwic291cmNlXCIsIFwidmVyc2lvblwiLCBcInZpc2liaWxpdHlcIl0sIFwiZmFjYWRlIHJlY29yZFwiKVxuICBjb25zdCBpZGVudGl0eSA9IHJlcXVpcmVTdHJpbmcoY2FuZGlkYXRlLmlkZW50aXR5LCBcIkZhY2FkZSBpZGVudGl0eVwiKVxuICBjb25zdCBsYW5ndWFnZSA9IHJlcXVpcmVTdHJpbmcoY2FuZGlkYXRlLmxhbmd1YWdlLCBcIkZhY2FkZSBsYW5ndWFnZVwiKVxuICBjb25zdCB2ZXJzaW9uID0gcmVxdWlyZVN0cmluZyhjYW5kaWRhdGUudmVyc2lvbiwgXCJGYWNhZGUgdmVyc2lvblwiKVxuICBjb25zdCBydW50aW1lUHJvZmlsZSA9IHJlcXVpcmVTdHJpbmcoY2FuZGlkYXRlLnJ1bnRpbWVQcm9maWxlLCBcIkZhY2FkZSBydW50aW1lIHByb2ZpbGVcIilcbiAgY29uc3QgdmlzaWJpbGl0eSA9IGNhbmRpZGF0ZS52aXNpYmlsaXR5XG5cbiAgaWYgKCFmYWNhZGVJZGVudGl0eVBhdHRlcm4udGVzdChpZGVudGl0eSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSBpZGVudGl0eSAnJHtpZGVudGl0eX0nIGlzIGludmFsaWQuYClcbiAgaWYgKCFzdXBwb3J0ZWRMYW5ndWFnZXMuaGFzKGxhbmd1YWdlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlIGxhbmd1YWdlICcke2xhbmd1YWdlfScgaXMgb3V0c2lkZSB0aGUgYWRvcHRlZCBjb2hvcnQuYClcbiAgaWYgKCFwYXJzZVN0ZGxpYlZlcnNpb24odmVyc2lvbikpIGludmFsaWRGYWNhZGUoYEZhY2FkZSB2ZXJzaW9uICcke3ZlcnNpb259JyBpcyBpbnZhbGlkLmApXG4gIGlmICghL15bYS16XVthLXowLTkuLV0qJC91LnRlc3QocnVudGltZVByb2ZpbGUpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgcnVudGltZSBwcm9maWxlICcke3J1bnRpbWVQcm9maWxlfScgaXMgaW52YWxpZC5gKVxuICBpZiAodmlzaWJpbGl0eSAhPSBcInB1YmxpY1wiICYmIHZpc2liaWxpdHkgIT0gXCJpbnRlcm5hbFwiKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBoYXMgaW52YWxpZCB2aXNpYmlsaXR5LmApXG4gIGNvbnN0IHNvdXJjZSA9IHZhbGlkYXRlU291cmNlKGNhbmRpZGF0ZS5zb3VyY2UsIGlkZW50aXR5LCBsYW5ndWFnZSlcbiAgY29uc3QgcHVibGljRGVjbGFyYXRpb25zID0gdmFsaWRhdGVQdWJsaWNEZWNsYXJhdGlvbnMoY2FuZGlkYXRlLnB1YmxpY0RlY2xhcmF0aW9ucywgaWRlbnRpdHkpXG4gIGNvbnN0IG5hdGl2ZU1vZHVsZXMgPSB2YWxpZGF0ZU5hdGl2ZU1vZHVsZXMoY2FuZGlkYXRlLm5hdGl2ZU1vZHVsZXMsIGlkZW50aXR5LCBwdWJsaWNEZWNsYXJhdGlvbnMpXG4gIGNvbnN0IHJlcXVpcmVtZW50cyA9IHZhbGlkYXRlUmVxdWlyZW1lbnRzKGNhbmRpZGF0ZS5yZXF1aXJlbWVudHMsIGlkZW50aXR5KVxuICBjb25zdCBkZXBlbmRlbmNpZXMgPSB2YWxpZGF0ZURlcGVuZGVuY2llcyhjYW5kaWRhdGUuZGVwZW5kZW5jaWVzLCBpZGVudGl0eSlcblxuICBpZiAodmlzaWJpbGl0eSA9PSBcInB1YmxpY1wiICYmIChwdWJsaWNEZWNsYXJhdGlvbnMubGVuZ3RoID09IDAgfHwgbmF0aXZlTW9kdWxlcy5sZW5ndGggPT0gMCkpIHtcbiAgICBpbnZhbGlkRmFjYWRlKGBQdWJsaWMgZmFjYWRlICcke2lkZW50aXR5fScgcmVxdWlyZXMgZGVjbGFyYXRpb25zIGFuZCBuYXRpdmUgaWRlbnRpdGllcy5gKVxuICB9XG4gIGlmICh2aXNpYmlsaXR5ID09IFwiaW50ZXJuYWxcIiAmJiBuYXRpdmVNb2R1bGVzLmxlbmd0aCA+IDApIGludmFsaWRGYWNhZGUoYEludGVybmFsIGZhY2FkZSAnJHtpZGVudGl0eX0nIGNhbm5vdCBleHBvc2UgbmF0aXZlIGlkZW50aXRpZXMuYClcblxuICByZXR1cm4gZGVlcEZyZWV6ZSh7XG4gICAgZGVwZW5kZW5jaWVzLFxuICAgIGlkZW50aXR5LFxuICAgIGxhbmd1YWdlOiAvKiogQHR5cGUge2ltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNMYW5ndWFnZX0gKi8gKGxhbmd1YWdlKSxcbiAgICBuYXRpdmVNb2R1bGVzLFxuICAgIHB1YmxpY0RlY2xhcmF0aW9ucyxcbiAgICByZXF1aXJlbWVudHMsXG4gICAgcnVudGltZVByb2ZpbGUsXG4gICAgc291cmNlLFxuICAgIHZlcnNpb24sXG4gICAgdmlzaWJpbGl0eTogLyoqIEB0eXBlIHtcImludGVybmFsXCIgfCBcInB1YmxpY1wifSAqLyAodmlzaWJpbGl0eSlcbiAgfSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgb25lIGNvbXBpbGVyLW93bmVkIGV4ZWN1dGFibGUgZmFjYWRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7dW5rbm93bn0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIHNvdXJjZSBkZXNjcmlwdG9yLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gT3duaW5nIGZhY2FkZSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIEZhY2FkZSBzb3VyY2UgbGFuZ3VhZ2UuXG4gKiBAcmV0dXJucyB7e2NvbnRlbnQ6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZywgaWQ6IHN0cmluZ319IFZhbGlkYXRlZCBzb3VyY2UgZGVzY3JpcHRvci5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVTb3VyY2UoY2FuZGlkYXRlLCBpZGVudGl0eSwgbGFuZ3VhZ2UpIHtcbiAgaWYgKCFpc1BsYWluT2JqZWN0KGNhbmRpZGF0ZSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIHJlcXVpcmVzIGFuIGV4ZWN1dGFibGUgc291cmNlIGRlc2NyaXB0b3IuYClcbiAgcmVxdWlyZUtleXMoY2FuZGlkYXRlLCBbXCJjb250ZW50XCIsIFwiZmlsZW5hbWVcIiwgXCJpZFwiXSwgYGZhY2FkZSAnJHtpZGVudGl0eX0nIHNvdXJjZWApXG4gIGNvbnN0IGNvbnRlbnQgPSByZXF1aXJlU3RyaW5nKGNhbmRpZGF0ZS5jb250ZW50LCBgRmFjYWRlICcke2lkZW50aXR5fScgc291cmNlIGNvbnRlbnRgKVxuICBjb25zdCBmaWxlbmFtZSA9IHJlcXVpcmVTdHJpbmcoY2FuZGlkYXRlLmZpbGVuYW1lLCBgRmFjYWRlICcke2lkZW50aXR5fScgc291cmNlIGZpbGVuYW1lYClcbiAgY29uc3QgaWQgPSByZXF1aXJlU3RyaW5nKGNhbmRpZGF0ZS5pZCwgYEZhY2FkZSAnJHtpZGVudGl0eX0nIHNvdXJjZSBtb2R1bGUgaWRlbnRpdHlgKVxuXG4gIGlmIChjb250ZW50Lmxlbmd0aCA9PSAwIHx8ICFpc1NhZmVBcnRpZmFjdFBhdGgoZmlsZW5hbWUpIHx8ICFmaWxlbmFtZS5zdGFydHNXaXRoKGBfX3NlbWFudGlmb2xkX2ZhY2FkZXNfXy8ke2xhbmd1YWdlfS9gKSB8fFxuICAgICFtb2R1bGVJZFBhdHRlcm4udGVzdChpZCkgfHwgIWlkLnN0YXJ0c1dpdGgoYHNlbWFudGlmb2xkLmZhY2FkZS4ke2xhbmd1YWdlfS5gKSkge1xuICAgIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIGhhcyBhbiBpbnZhbGlkIGNvbXBpbGVyLW93bmVkIHNvdXJjZSBkZXNjcmlwdG9yLmApXG4gIH1cbiAgcmV0dXJuIHtjb250ZW50LCBmaWxlbmFtZSwgaWR9XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIG9uZSBmYWNhZGUncyBjbG9zZWQgcHVibGljIGRlY2xhcmF0aW9uIHN1cmZhY2UuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBkZWNsYXJhdGlvbnMuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRlbnRpdHkgLSBPd25pbmcgZmFjYWRlIGlkZW50aXR5LlxuICogQHJldHVybnMge1N0ZGxpYkZhY2FkZVB1YmxpY0RlY2xhcmF0aW9uW119IFZhbGlkYXRlZCBkZWNsYXJhdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlUHVibGljRGVjbGFyYXRpb25zKGNhbmRpZGF0ZSwgaWRlbnRpdHkpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkoY2FuZGlkYXRlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgcHVibGljIGRlY2xhcmF0aW9ucyBtdXN0IGJlIGEgZGVuc2UgYXJyYXkuYClcbiAgY29uc3QgbmFtZXMgPSBuZXcgU2V0KClcbiAgcmV0dXJuIGNhbmRpZGF0ZS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgcHVibGljIGRlY2xhcmF0aW9ucyBtdXN0IGJlIHBsYWluIG9iamVjdHMuYClcbiAgICBjb25zdCBuYW1lID0gcmVxdWlyZVN0cmluZyh2YWx1ZS5uYW1lLCBgRmFjYWRlICcke2lkZW50aXR5fScgZGVjbGFyYXRpb24gbmFtZWApXG5cbiAgICBpZiAoIWRlY2xhcmF0aW9uTmFtZVBhdHRlcm4udGVzdChuYW1lKSB8fCBuYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIGhhcyBhbiBpbnZhbGlkIG9yIGR1cGxpY2F0ZSBwdWJsaWMgZGVjbGFyYXRpb24uYClcbiAgICB9XG4gICAgbmFtZXMuYWRkKG5hbWUpXG4gICAgaWYgKHZhbHVlLmtpbmQgPT0gXCJjbGFzc1wiKSByZXR1cm4gdmFsaWRhdGVQdWJsaWNDbGFzcyh2YWx1ZSwgaWRlbnRpdHksIG5hbWUpXG4gICAgcmVxdWlyZUtleXModmFsdWUsIFtcImVmZmVjdHNcIiwgXCJmYWlsdXJlc1wiLCBcImZvcm1zXCIsIFwia2luZFwiLCBcIm5hbWVcIiwgXCJvd25lcnNoaXBcIiwgXCJwYXJhbWV0ZXJzXCIsIFwicmV0dXJuVHlwZVwiXSxcbiAgICAgIGBmYWNhZGUgJyR7aWRlbnRpdHl9JyBwdWJsaWMgZGVjbGFyYXRpb25gKVxuICAgIGlmICh2YWx1ZS5raW5kICE9IFwiZnVuY3Rpb25cIikgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgaGFzIGFuIGludmFsaWQgcHVibGljIGRlY2xhcmF0aW9uIGtpbmQuYClcbiAgICBpZiAoIWlzRGVuc2VBcnJheSh2YWx1ZS5lZmZlY3RzKSB8fCAhdmFsdWUuZWZmZWN0cy5ldmVyeSgoZWZmZWN0KSA9PiBlZmZlY3QgPT0gXCJob3N0XCIpIHx8IG5ldyBTZXQodmFsdWUuZWZmZWN0cykuc2l6ZSAhPSB2YWx1ZS5lZmZlY3RzLmxlbmd0aCB8fFxuICAgICAgIWlzRGVuc2VBcnJheSh2YWx1ZS5mYWlsdXJlcykgfHwgIXZhbHVlLmZhaWx1cmVzLmV2ZXJ5KChmYWlsdXJlKSA9PiB0eXBlb2YgZmFpbHVyZSA9PSBcInN0cmluZ1wiICYmIGRlY2xhcmF0aW9uTmFtZVBhdHRlcm4udGVzdChmYWlsdXJlKSkgfHxcbiAgICAgICFpc0RlbnNlQXJyYXkodmFsdWUuZm9ybXMpIHx8IHZhbHVlLmZvcm1zLmxlbmd0aCA9PSAwIHx8ICF2YWx1ZS5mb3Jtcy5ldmVyeSgoZm9ybSkgPT5cbiAgICAgICAgdHlwZW9mIGZvcm0gPT0gXCJzdHJpbmdcIiAmJiBbXCJkaXJlY3QtY2FsbFwiLCBcInVucXVhbGlmaWVkLWNhbGxcIiwgXCJyZWNlaXZlci1jYWxsXCJdLmluY2x1ZGVzKGZvcm0pKSB8fFxuICAgICAgbmV3IFNldCh2YWx1ZS5mb3Jtcykuc2l6ZSAhPSB2YWx1ZS5mb3Jtcy5sZW5ndGggfHxcbiAgICAgIHZhbHVlLm93bmVyc2hpcCAhPSBcIm5vdC1hcHBsaWNhYmxlXCIgfHxcbiAgICAgICFpc0RlbnNlQXJyYXkodmFsdWUucGFyYW1ldGVycykpIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIGRlY2xhcmF0aW9uICcke25hbWV9JyBoYXMgYW4gaW52YWxpZCBwdWJsaWMgY29udHJhY3QuYClcbiAgICBjb25zdCBwYXJhbWV0ZXJzID0gdmFsaWRhdGVGYWNhZGVQYXJhbWV0ZXJzKHZhbHVlLnBhcmFtZXRlcnMsIGlkZW50aXR5LCBuYW1lKVxuICAgIGNvbnN0IHJldHVyblR5cGUgPSByZXF1aXJlU3RyaW5nKHZhbHVlLnJldHVyblR5cGUsIGBGYWNhZGUgJyR7aWRlbnRpdHl9JyByZXR1cm4gdHlwZWApXG5cbiAgICBpZiAoIWlzRmFjYWRlVHlwZShyZXR1cm5UeXBlLCB0cnVlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgZGVjbGFyYXRpb24gJyR7bmFtZX0nIGhhcyBhbiBpbnZhbGlkIHJldHVybiB0eXBlLmApXG4gICAgcmV0dXJuIHtcbiAgICAgIGVmZmVjdHM6IC8qKiBAdHlwZSB7c3RyaW5nW119ICovIChbLi4udmFsdWUuZWZmZWN0c10pLFxuICAgICAgZmFpbHVyZXM6IC8qKiBAdHlwZSB7c3RyaW5nW119ICovIChbLi4udmFsdWUuZmFpbHVyZXNdKSxcbiAgICAgIGZvcm1zOiAvKiogQHR5cGUgeyhcImRpcmVjdC1jYWxsXCIgfCBcInVucXVhbGlmaWVkLWNhbGxcIiB8IFwicmVjZWl2ZXItY2FsbFwiKVtdfSAqLyAoWy4uLnZhbHVlLmZvcm1zXSksXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJmdW5jdGlvblwiKSxcbiAgICAgIG5hbWUsXG4gICAgICBvd25lcnNoaXA6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIm5vdC1hcHBsaWNhYmxlXCIpLFxuICAgICAgcGFyYW1ldGVycyxcbiAgICAgIHJldHVyblR5cGVcbiAgICB9XG4gIH0pXG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHRoZSBleGFjdCBuYXRpdmUgbW9kdWxlIGFuZCBzeW1ib2wgaWRlbnRpdGllcyBzZWxlY3RpbmcgYSBmYWNhZGUuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBuYXRpdmUgbW9kdWxlcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIE93bmluZyBmYWNhZGUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge1N0ZGxpYkZhY2FkZVB1YmxpY0RlY2xhcmF0aW9uW119IGRlY2xhcmF0aW9ucyAtIFZhbGlkYXRlZCBwdWJsaWMgc3VyZmFjZS5cbiAqIEByZXR1cm5zIHsoe2lkZW50aXR5OiBzdHJpbmcsIGtpbmQ6IFwibW9kdWxlXCIsIHN5bWJvbHM6IHN0cmluZ1tdfSB8IHtmb3JtczogKFwidW5xdWFsaWZpZWQtY2FsbFwiIHwgXCJyZWNlaXZlci1jYWxsXCIpW10sIGlkZW50aXR5OiBzdHJpbmcsIGtpbmQ6IFwiYnVpbHRpblwiLCBzeW1ib2xzOiBzdHJpbmdbXX0pW119IFZhbGlkYXRlZCBuYXRpdmUgaWRlbnRpdGllcy5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVOYXRpdmVNb2R1bGVzKGNhbmRpZGF0ZSwgaWRlbnRpdHksIGRlY2xhcmF0aW9ucykge1xuICBpZiAoIWlzRGVuc2VBcnJheShjYW5kaWRhdGUpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBuYXRpdmUgbW9kdWxlcyBtdXN0IGJlIGEgZGVuc2UgYXJyYXkuYClcbiAgY29uc3QgbW9kdWxlcyA9IG5ldyBTZXQoKVxuICBjb25zdCBwdWJsaWNOYW1lcyA9IG5ldyBTZXQoZGVjbGFyYXRpb25zLm1hcCgoe25hbWV9KSA9PiBuYW1lKSlcbiAgcmV0dXJuIGNhbmRpZGF0ZS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KHZhbHVlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgbmF0aXZlIG1vZHVsZXMgbXVzdCBiZSBwbGFpbiBvYmplY3RzLmApXG4gICAgY29uc3QgYnVpbHRpbiA9IHZhbHVlLmtpbmQgPT0gXCJidWlsdGluXCJcblxuICAgIHJlcXVpcmVLZXlzKHZhbHVlLCBidWlsdGluID8gW1wiZm9ybXNcIiwgXCJpZGVudGl0eVwiLCBcImtpbmRcIiwgXCJzeW1ib2xzXCJdIDogW1wiaWRlbnRpdHlcIiwgXCJraW5kXCIsIFwic3ltYm9sc1wiXSxcbiAgICAgIGBmYWNhZGUgJyR7aWRlbnRpdHl9JyBuYXRpdmUgbW9kdWxlYClcbiAgICBjb25zdCBtb2R1bGVJZGVudGl0eSA9IHJlcXVpcmVTdHJpbmcodmFsdWUuaWRlbnRpdHksIGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBuYXRpdmUgbW9kdWxlIGlkZW50aXR5YClcblxuICAgIGlmICh2YWx1ZS5raW5kICE9IFwibW9kdWxlXCIgJiYgdmFsdWUua2luZCAhPSBcImJ1aWx0aW5cIiB8fCBtb2R1bGVzLmhhcyhtb2R1bGVJZGVudGl0eSkgfHxcbiAgICAgICFpc0RlbnNlQXJyYXkodmFsdWUuc3ltYm9scykgfHwgdmFsdWUuc3ltYm9scy5sZW5ndGggPT0gMCB8fFxuICAgICAgIXZhbHVlLnN5bWJvbHMuZXZlcnkoKHN5bWJvbCkgPT4gdHlwZW9mIHN5bWJvbCA9PSBcInN0cmluZ1wiICYmIHB1YmxpY05hbWVzLmhhcyhzeW1ib2wpKSB8fFxuICAgICAgbmV3IFNldCh2YWx1ZS5zeW1ib2xzKS5zaXplICE9IHZhbHVlLnN5bWJvbHMubGVuZ3RoKSB7XG4gICAgICBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBoYXMgYW4gaW52YWxpZCBuYXRpdmUgbW9kdWxlIGRlY2xhcmF0aW9uLmApXG4gICAgfVxuICAgIGlmIChidWlsdGluICYmICghaXNEZW5zZUFycmF5KHZhbHVlLmZvcm1zKSB8fCB2YWx1ZS5mb3Jtcy5sZW5ndGggPT0gMCB8fFxuICAgICAgIXZhbHVlLmZvcm1zLmV2ZXJ5KChmb3JtKSA9PiBmb3JtID09IFwidW5xdWFsaWZpZWQtY2FsbFwiIHx8IGZvcm0gPT0gXCJyZWNlaXZlci1jYWxsXCIpIHx8XG4gICAgICBuZXcgU2V0KHZhbHVlLmZvcm1zKS5zaXplICE9IHZhbHVlLmZvcm1zLmxlbmd0aCkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIGhhcyBpbnZhbGlkIGJ1aWx0aW4gZm9ybXMuYClcbiAgICBtb2R1bGVzLmFkZChtb2R1bGVJZGVudGl0eSlcbiAgICByZXR1cm4gYnVpbHRpblxuICAgICAgPyB7Zm9ybXM6IC8qKiBAdHlwZSB7KFwidW5xdWFsaWZpZWQtY2FsbFwiIHwgXCJyZWNlaXZlci1jYWxsXCIpW119ICovIChbLi4uLyoqIEB0eXBlIHt1bmtub3duW119ICovICh2YWx1ZS5mb3JtcyldKSwgaWRlbnRpdHk6IG1vZHVsZUlkZW50aXR5LFxuICAgICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJidWlsdGluXCIpLCBzeW1ib2xzOiAvKiogQHR5cGUge3N0cmluZ1tdfSAqLyAoWy4uLnZhbHVlLnN5bWJvbHNdKX1cbiAgICAgIDoge2lkZW50aXR5OiBtb2R1bGVJZGVudGl0eSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwibW9kdWxlXCIpLCBzeW1ib2xzOiAvKiogQHR5cGUge3N0cmluZ1tdfSAqLyAoWy4uLnZhbHVlLnN5bWJvbHNdKX1cbiAgfSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgY2Fub25pY2FsLW9ubHkgZmFjYWRlIGNhcGFiaWxpdHkgcmVxdWlyZW1lbnRzLlxuICogQHBhcmFtIHt1bmtub3dufSBjYW5kaWRhdGUgLSBDYW5kaWRhdGUgcmVxdWlyZW1lbnRzLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gT3duaW5nIGZhY2FkZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHt7bW9kdWxlOiBzdHJpbmcsIG9wZXJhdGlvbnM6IHN0cmluZ1tdLCByYW5nZTogc3RyaW5nfVtdfSBWYWxpZGF0ZWQgcmVxdWlyZW1lbnRzLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVJlcXVpcmVtZW50cyhjYW5kaWRhdGUsIGlkZW50aXR5KSB7XG4gIGlmICghaXNEZW5zZUFycmF5KGNhbmRpZGF0ZSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIHJlcXVpcmVtZW50cyBtdXN0IGJlIGEgZGVuc2UgYXJyYXkuYClcbiAgY29uc3QgbW9kdWxlcyA9IG5ldyBTZXQoKVxuICByZXR1cm4gY2FuZGlkYXRlLm1hcCgodmFsdWUpID0+IHtcbiAgICBpZiAoIWlzUGxhaW5PYmplY3QodmFsdWUpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyByZXF1aXJlbWVudHMgbXVzdCBiZSBwbGFpbiBvYmplY3RzLmApXG4gICAgcmVxdWlyZUtleXModmFsdWUsIFtcIm1vZHVsZVwiLCBcIm9wZXJhdGlvbnNcIiwgXCJyYW5nZVwiXSwgYGZhY2FkZSAnJHtpZGVudGl0eX0nIHJlcXVpcmVtZW50YClcbiAgICBjb25zdCBtb2R1bGUgPSByZXF1aXJlU3RyaW5nKHZhbHVlLm1vZHVsZSwgYEZhY2FkZSAnJHtpZGVudGl0eX0nIGNhbm9uaWNhbCBtb2R1bGVgKVxuICAgIGNvbnN0IHJhbmdlID0gcmVxdWlyZVN0cmluZyh2YWx1ZS5yYW5nZSwgYEZhY2FkZSAnJHtpZGVudGl0eX0nIGNhbm9uaWNhbCByYW5nZWApXG5cbiAgICBpZiAobW9kdWxlcy5oYXMobW9kdWxlKSB8fCAhcGFyc2VTdGRsaWJWZXJzaW9uUmFuZ2UocmFuZ2UpIHx8ICFpc0RlbnNlQXJyYXkodmFsdWUub3BlcmF0aW9ucykgfHwgdmFsdWUub3BlcmF0aW9ucy5sZW5ndGggPT0gMCB8fFxuICAgICAgIXZhbHVlLm9wZXJhdGlvbnMuZXZlcnkoKG9wZXJhdGlvbikgPT4gdHlwZW9mIG9wZXJhdGlvbiA9PSBcInN0cmluZ1wiICYmIGRlY2xhcmF0aW9uTmFtZVBhdHRlcm4udGVzdChvcGVyYXRpb24pKSB8fFxuICAgICAgbmV3IFNldCh2YWx1ZS5vcGVyYXRpb25zKS5zaXplICE9IHZhbHVlLm9wZXJhdGlvbnMubGVuZ3RoKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBoYXMgYW4gaW52YWxpZCBjYW5vbmljYWwgcmVxdWlyZW1lbnQuYClcbiAgICBjb25zdCBjb250cmFjdCA9IHJlc29sdmVTdGRsaWJNb2R1bGUobW9kdWxlLCByYW5nZSlcbiAgICBjb25zdCBkZWNsYXJlZCA9IG5ldyBTZXQoY29udHJhY3Qub3BlcmF0aW9ucy5tYXAoKHtuYW1lfSkgPT4gbmFtZSkpXG5cbiAgICBpZiAoIS8qKiBAdHlwZSB7c3RyaW5nW119ICovICh2YWx1ZS5vcGVyYXRpb25zKS5ldmVyeSgob3BlcmF0aW9uKSA9PiBkZWNsYXJlZC5oYXMob3BlcmF0aW9uKSkpIHtcbiAgICAgIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIHJlcXVpcmVzIGFuIHVuZGVjbGFyZWQgY2Fub25pY2FsIG9wZXJhdGlvbi5gKVxuICAgIH1cbiAgICBtb2R1bGVzLmFkZChtb2R1bGUpXG4gICAgcmV0dXJuIHttb2R1bGUsIG9wZXJhdGlvbnM6IC8qKiBAdHlwZSB7c3RyaW5nW119ICovIChbLi4udmFsdWUub3BlcmF0aW9uc10pLCByYW5nZX1cbiAgfSlcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdmVyc2lvbmVkIHNhbWUtbGFuZ3VhZ2UgZmFjYWRlIGRlcGVuZGVuY2llcy5cbiAqIEBwYXJhbSB7dW5rbm93bn0gY2FuZGlkYXRlIC0gQ2FuZGlkYXRlIGRlcGVuZGVuY2llcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIE93bmluZyBmYWNhZGUgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7e2lkZW50aXR5OiBzdHJpbmcsIHJhbmdlOiBzdHJpbmd9W119IFZhbGlkYXRlZCBkZXBlbmRlbmNpZXMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlRGVwZW5kZW5jaWVzKGNhbmRpZGF0ZSwgaWRlbnRpdHkpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkoY2FuZGlkYXRlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgZGVwZW5kZW5jaWVzIG11c3QgYmUgYSBkZW5zZSBhcnJheS5gKVxuICBjb25zdCBpZGVudGl0aWVzID0gbmV3IFNldCgpXG4gIHJldHVybiBjYW5kaWRhdGUubWFwKCh2YWx1ZSkgPT4ge1xuICAgIGlmICghaXNQbGFpbk9iamVjdCh2YWx1ZSkpIGludmFsaWRGYWNhZGUoYEZhY2FkZSAnJHtpZGVudGl0eX0nIGRlcGVuZGVuY2llcyBtdXN0IGJlIHBsYWluIG9iamVjdHMuYClcbiAgICByZXF1aXJlS2V5cyh2YWx1ZSwgW1wiaWRlbnRpdHlcIiwgXCJyYW5nZVwiXSwgYGZhY2FkZSAnJHtpZGVudGl0eX0nIGRlcGVuZGVuY3lgKVxuICAgIGNvbnN0IGRlcGVuZGVuY3lJZGVudGl0eSA9IHJlcXVpcmVTdHJpbmcodmFsdWUuaWRlbnRpdHksIGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBkZXBlbmRlbmN5IGlkZW50aXR5YClcbiAgICBjb25zdCByYW5nZSA9IHJlcXVpcmVTdHJpbmcodmFsdWUucmFuZ2UsIGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBkZXBlbmRlbmN5IHJhbmdlYClcblxuICAgIGlmICghZmFjYWRlSWRlbnRpdHlQYXR0ZXJuLnRlc3QoZGVwZW5kZW5jeUlkZW50aXR5KSB8fCBkZXBlbmRlbmN5SWRlbnRpdHkgPT0gaWRlbnRpdHkgfHwgaWRlbnRpdGllcy5oYXMoZGVwZW5kZW5jeUlkZW50aXR5KSB8fFxuICAgICAgIXBhcnNlU3RkbGliVmVyc2lvblJhbmdlKHJhbmdlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgaGFzIGFuIGludmFsaWQgZGVwZW5kZW5jeS5gKVxuICAgIGlkZW50aXRpZXMuYWRkKGRlcGVuZGVuY3lJZGVudGl0eSlcbiAgICByZXR1cm4ge2lkZW50aXR5OiBkZXBlbmRlbmN5SWRlbnRpdHksIHJhbmdlfVxuICB9KVxufVxuXG4vKipcbiAqIEJ1aWxkcyB0aGUgYm91bmRlZCBvcmlnaW5hbC1maXZlIHF1YWxpZmljYXRpb24gZmFjYWRlIGRlZmluaXRpb25zLlxuICogQHJldHVybnMge3Vua25vd25bXX0gVW52YWxpZGF0ZWQgYnVpbHQtaW4gcXVhbGlmaWNhdGlvbiBmYWNhZGUgZGVmaW5pdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIGJ1aWx0aW5GYWNhZGVSZWNvcmRzKCkge1xuICByZXR1cm4gW1wicGhwXCIsIFwicnVieVwiLCBcImphdmFzY3JpcHRcIiwgXCJ0eXBlc2NyaXB0XCIsIFwiamF2YVwiXS5mbGF0TWFwKChsYW5ndWFnZSkgPT4gYnVpbHRpbkxhbmd1YWdlRmFjYWRlcyhsYW5ndWFnZSkpXG4gICAgLmNvbmNhdChidWlsdGluVGFzazAzN1J1YnlGYWNhZGVzKCkpXG59XG5cbi8qKlxuICogQnVpbGRzIG9uZSBzb3VyY2UgbGFuZ3VhZ2UncyBwdWJsaWMsIGludGVybmFsLCBhbmQgdW5yZWFjaGFibGUgcXVhbGlmaWNhdGlvbiBmYWNhZGVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGxhbmd1YWdlIC0gU291cmNlIGxhbmd1YWdlLlxuICogQHJldHVybnMge3Vua25vd25bXX0gTGFuZ3VhZ2UgZmFjYWRlIGRlZmluaXRpb25zLlxuICovXG5mdW5jdGlvbiBidWlsdGluTGFuZ3VhZ2VGYWNhZGVzKGxhbmd1YWdlKSB7XG4gIGNvbnN0IG5hbWVzID0gZmFjYWRlTmFtZXMobGFuZ3VhZ2UpXG4gIGNvbnN0IGJhc2UgPSBgc2VtYW50aWZvbGQudGFzazAzNi4ke2xhbmd1YWdlfWBcbiAgY29uc3Qgc291cmNlQmFzZSA9IGBzZW1hbnRpZm9sZC5mYWNhZGUuJHtsYW5ndWFnZX1gXG4gIGNvbnN0IHNvdXJjZURpcmVjdG9yeSA9IGBfX3NlbWFudGlmb2xkX2ZhY2FkZXNfXy8ke2xhbmd1YWdlfWBcbiAgY29uc3QgcHJvYmVGaWxlbmFtZSA9IGxhbmd1YWdlID09IFwiamF2YVwiID8gYCR7c291cmNlRGlyZWN0b3J5fS9zZW1hbnRpZm9sZC9mYWNhZGUvamF2YS9wcm9iZS9Qcm9iZS5qYXZhYCA6XG4gICAgYCR7c291cmNlRGlyZWN0b3J5fS9wcm9iZS4ke25hbWVzLmV4dGVuc2lvbn1gXG4gIGNvbnN0IHJ1bm5lckZpbGVuYW1lID0gbGFuZ3VhZ2UgPT0gXCJqYXZhXCIgPyBgJHtzb3VyY2VEaXJlY3Rvcnl9L3NlbWFudGlmb2xkL2ZhY2FkZS9qYXZhL3Byb2JlcnVubmVyL1Byb2JlUnVubmVyLmphdmFgIDpcbiAgICBgJHtzb3VyY2VEaXJlY3Rvcnl9L3Byb2JlLXJ1bm5lci4ke25hbWVzLmV4dGVuc2lvbn1gXG4gIGNvbnN0IHVudXNlZEZpbGVuYW1lID0gbGFuZ3VhZ2UgPT0gXCJqYXZhXCIgPyBgJHtzb3VyY2VEaXJlY3Rvcnl9L3NlbWFudGlmb2xkL2ZhY2FkZS9qYXZhL3VudXNlZC9VbnVzZWQuamF2YWAgOlxuICAgIGAke3NvdXJjZURpcmVjdG9yeX0vdW51c2VkLiR7bmFtZXMuZXh0ZW5zaW9ufWBcblxuICByZXR1cm4gW3tcbiAgICBkZXBlbmRlbmNpZXM6IFt7aWRlbnRpdHk6IGAke2Jhc2V9LnByb2JlLXJ1bm5lcmAsIHJhbmdlOiBcIjFcIn1dLFxuICAgIGlkZW50aXR5OiBgJHtiYXNlfS5wcm9iZWAsXG4gICAgbGFuZ3VhZ2UsXG4gICAgbmF0aXZlTW9kdWxlczogW3tpZGVudGl0eTogbmFtZXMubmF0aXZlTW9kdWxlLCBraW5kOiBcIm1vZHVsZVwiLCBzeW1ib2xzOiBbbmFtZXMucHVibGljTmFtZV19XSxcbiAgICBwdWJsaWNEZWNsYXJhdGlvbnM6IFtwdWJsaWNEZWNsYXJhdGlvbihuYW1lcy5wdWJsaWNOYW1lKV0sXG4gICAgcmVxdWlyZW1lbnRzOiBbXSxcbiAgICBydW50aW1lUHJvZmlsZTogYCR7bGFuZ3VhZ2V9LXRhc2swMzYtdjFgLFxuICAgIHNvdXJjZToge2NvbnRlbnQ6IG5hbWVzLnByb2JlU291cmNlLCBmaWxlbmFtZTogcHJvYmVGaWxlbmFtZSwgaWQ6IGAke3NvdXJjZUJhc2V9LnByb2JlYH0sXG4gICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgIHZpc2liaWxpdHk6IFwicHVibGljXCJcbiAgfSwge1xuICAgIGRlcGVuZGVuY2llczogW10sXG4gICAgaWRlbnRpdHk6IGAke2Jhc2V9LnByb2JlLXJ1bm5lcmAsXG4gICAgbGFuZ3VhZ2UsXG4gICAgbmF0aXZlTW9kdWxlczogW10sXG4gICAgcHVibGljRGVjbGFyYXRpb25zOiBbXSxcbiAgICByZXF1aXJlbWVudHM6IFt7bW9kdWxlOiBcInNlbWFudGlmb2xkLnRhc2swMzQucmVzb3VyY2UtcHJvYmVcIiwgb3BlcmF0aW9uczogW1wicHJvYmVFZmZlY3RcIiwgXCJwcm9iZVRyYWNlXCJdLCByYW5nZTogXCIxXCJ9XSxcbiAgICBydW50aW1lUHJvZmlsZTogYCR7bGFuZ3VhZ2V9LXRhc2swMzYtdjFgLFxuICAgIHNvdXJjZToge2NvbnRlbnQ6IG5hbWVzLnJ1bm5lclNvdXJjZSwgZmlsZW5hbWU6IHJ1bm5lckZpbGVuYW1lLCBpZDogYCR7c291cmNlQmFzZX0ucHJvYmVfcnVubmVyYH0sXG4gICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgIHZpc2liaWxpdHk6IFwiaW50ZXJuYWxcIlxuICB9LCB7XG4gICAgZGVwZW5kZW5jaWVzOiBbXSxcbiAgICBpZGVudGl0eTogYCR7YmFzZX0udW51c2VkYCxcbiAgICBsYW5ndWFnZSxcbiAgICBuYXRpdmVNb2R1bGVzOiBbe2lkZW50aXR5OiBuYW1lcy51bnVzZWROYXRpdmVNb2R1bGUsIGtpbmQ6IFwibW9kdWxlXCIsIHN5bWJvbHM6IFtuYW1lcy51bnVzZWROYW1lXX1dLFxuICAgIHB1YmxpY0RlY2xhcmF0aW9uczogW3B1YmxpY0RlY2xhcmF0aW9uKG5hbWVzLnVudXNlZE5hbWUpXSxcbiAgICByZXF1aXJlbWVudHM6IFt7bW9kdWxlOiBcInNlbWFudGlmb2xkLnRhc2swMzQucmVzb3VyY2UtcHJvYmVcIiwgb3BlcmF0aW9uczogW1wicHJvYmVUcmFjZVwiXSwgcmFuZ2U6IFwiMVwifV0sXG4gICAgcnVudGltZVByb2ZpbGU6IGAke2xhbmd1YWdlfS10YXNrMDM2LXYxYCxcbiAgICBzb3VyY2U6IHtjb250ZW50OiBuYW1lcy51bnVzZWRTb3VyY2UsIGZpbGVuYW1lOiB1bnVzZWRGaWxlbmFtZSwgaWQ6IGAke3NvdXJjZUJhc2V9LnVudXNlZGB9LFxuICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAgICB2aXNpYmlsaXR5OiBcInB1YmxpY1wiXG4gIH1dXG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBjb21tb24gYm91bmRlZCBxdWFsaWZpY2F0aW9uIGZ1bmN0aW9uIGRlY2xhcmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBTb3VyY2UtdmlzaWJsZSBmdW5jdGlvbiBuYW1lLlxuICogQHJldHVybnMge1N0ZGxpYkZhY2FkZVB1YmxpY0RlY2xhcmF0aW9ufSBQdWJsaWMgZmFjYWRlIGRlY2xhcmF0aW9uLlxuICovXG5mdW5jdGlvbiBwdWJsaWNEZWNsYXJhdGlvbihuYW1lKSB7XG4gIHJldHVybiB7XG4gICAgZWZmZWN0czogW1wiaG9zdFwiXSwgZmFpbHVyZXM6IFtdLCBmb3JtczogW1wiZGlyZWN0LWNhbGxcIl0sIGtpbmQ6IFwiZnVuY3Rpb25cIiwgbmFtZSxcbiAgICBvd25lcnNoaXA6IFwibm90LWFwcGxpY2FibGVcIiwgcGFyYW1ldGVyczogW3tuYW1lOiBcImxhYmVsXCIsIHR5cGU6IFwic3RyaW5nXCJ9XSwgcmV0dXJuVHlwZTogXCJzdHJpbmdcIlxuICB9XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBleGFjdCBSdWJ5IFRhc2sgMDM3IHNvY2tldCBhbmQgb3V0cHV0IGNvbXBhdGliaWxpdHkgZmFjYWRlcy5cbiAqIEByZXR1cm5zIHt1bmtub3duW119IFVudmFsaWRhdGVkIGZhY2FkZSByZWNvcmRzLlxuICovXG5mdW5jdGlvbiBidWlsdGluVGFzazAzN1J1YnlGYWNhZGVzKCkge1xuICByZXR1cm4gW3tcbiAgICBkZXBlbmRlbmNpZXM6IFtdLFxuICAgIGlkZW50aXR5OiBcInNlbWFudGlmb2xkLnRhc2swMzcucnVieS5zb2NrZXRcIixcbiAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgbmF0aXZlTW9kdWxlczogW3tpZGVudGl0eTogXCJzb2NrZXRcIiwga2luZDogXCJtb2R1bGVcIiwgc3ltYm9sczogW1wiVENQU29ja2V0XCJdfV0sXG4gICAgcHVibGljRGVjbGFyYXRpb25zOiBbe1xuICAgICAgY29uc3RydWN0b3I6IHtcbiAgICAgICAgZWZmZWN0czogW1wiaG9zdFwiXSwgZmFpbHVyZXM6IFtcIkludmFsaWRIb3N0XCIsIFwiSW52YWxpZFBvcnRcIiwgXCJDb25uZWN0aW9uRmFpbHVyZVwiXSwgb3duZXJzaGlwOiBcImFjcXVpcmVkXCIsXG4gICAgICAgIHBhcmFtZXRlcnM6IFt7bmFtZTogXCJob3N0XCIsIHR5cGU6IFwic3RyaW5nXCJ9LCB7bmFtZTogXCJwb3J0XCIsIHR5cGU6IFwiaW50ZWdlclwifV1cbiAgICAgIH0sXG4gICAgICBmb3JtczogW1wiY29uc3RydWN0b3ItY2FsbFwiXSxcbiAgICAgIGtpbmQ6IFwiY2xhc3NcIixcbiAgICAgIG1ldGhvZHM6IFt7XG4gICAgICAgIGVmZmVjdHM6IFtcImhvc3RcIl0sIGZhaWx1cmVzOiBbXCJSZWFkRmFpbHVyZVwiLCBcIkRlY29kZUZhaWx1cmVcIiwgXCJSZXNvdXJjZUNsb3NlZFwiXSwgZm9ybXM6IFtcInJlY2VpdmVyLWNhbGxcIl0sXG4gICAgICAgIG5hbWU6IFwiZ2V0c1wiLCBvd25lcnNoaXA6IFwiYm9ycm93ZWRcIiwgcGFyYW1ldGVyczogW10sIHJldHVyblR5cGU6IFwib3B0aW9uYWw6c3RyaW5nXCJcbiAgICAgIH0sIHtcbiAgICAgICAgZWZmZWN0czogW1wiaG9zdFwiXSwgZmFpbHVyZXM6IFtcIkNsb3NlRmFpbHVyZVwiLCBcIlJlc291cmNlQ2xvc2VkXCJdLCBmb3JtczogW1wicmVjZWl2ZXItY2FsbFwiXSxcbiAgICAgICAgbmFtZTogXCJjbG9zZVwiLCBvd25lcnNoaXA6IFwiY29uc3VtZWRcIiwgcGFyYW1ldGVyczogW10sIHJldHVyblR5cGU6IFwidm9pZFwiXG4gICAgICB9XSxcbiAgICAgIG5hbWU6IFwiVENQU29ja2V0XCIsXG4gICAgICBvd25lcnNoaXA6IFwib3duZWQtcmVmZXJlbmNlXCJcbiAgICB9XSxcbiAgICByZXF1aXJlbWVudHM6IFtcbiAgICAgIHttb2R1bGU6IFwic2VtYW50aWZvbGQuc29ja2V0LWNsaWVudFwiLCBvcGVyYXRpb25zOiBbXCJ2MV9jb25uZWN0XCJdLCByYW5nZTogXCIxXCJ9LFxuICAgICAge21vZHVsZTogXCJzZW1hbnRpZm9sZC50ZXh0LXN0cmVhbVwiLCBvcGVyYXRpb25zOiBbXCJ2MV9yZWFkX2xpbmVcIl0sIHJhbmdlOiBcIjFcIn0sXG4gICAgICB7bW9kdWxlOiBcInNlbWFudGlmb2xkLnJlc291cmNlXCIsIG9wZXJhdGlvbnM6IFtcInYxX2Nsb3NlXCJdLCByYW5nZTogXCIxXCJ9XG4gICAgXSxcbiAgICBydW50aW1lUHJvZmlsZTogXCJydWJ5LXRhc2swMzctc29ja2V0LXYxXCIsXG4gICAgc291cmNlOiB7XG4gICAgICBjb250ZW50OiBgbW9kdWxlIFNlbWFudGlmb2xkVGFzazAzN1NvY2tldFxuICBjbGFzcyBUQ1BTb2NrZXRcbiAgICAjIEBwYXJhbSBob3N0IFtTdHJpbmddXG4gICAgIyBAcGFyYW0gcG9ydCBbSW50ZWdlcl1cbiAgICBkZWYgaW5pdGlhbGl6ZShob3N0LCBwb3J0KVxuICAgICAgQHJlc291cmNlID0gdjFfY29ubmVjdChob3N0LCBwb3J0KVxuICAgIGVuZFxuXG4gICAgIyBAcmV0dXJuIFtTdHJpbmc/XVxuICAgIGRlZiBnZXRzXG4gICAgICByZXR1cm4gdjFfcmVhZF9saW5lKEByZXNvdXJjZSlcbiAgICBlbmRcblxuICAgICMgQHJldHVybiBbdm9pZF1cbiAgICBkZWYgY2xvc2VcbiAgICAgIHYxX2Nsb3NlKEByZXNvdXJjZSlcbiAgICBlbmRcbiAgZW5kXG5lbmRcbmAsXG4gICAgICBmaWxlbmFtZTogXCJfX3NlbWFudGlmb2xkX2ZhY2FkZXNfXy9ydWJ5L3NvY2tldC5yYlwiLFxuICAgICAgaWQ6IFwic2VtYW50aWZvbGQuZmFjYWRlLnJ1Ynkuc29ja2V0XCJcbiAgICB9LFxuICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAgICB2aXNpYmlsaXR5OiBcInB1YmxpY1wiXG4gIH0sIHtcbiAgICBkZXBlbmRlbmNpZXM6IFtdLFxuICAgIGlkZW50aXR5OiBcInNlbWFudGlmb2xkLnRhc2swMzcucnVieS5vdXRwdXRcIixcbiAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgbmF0aXZlTW9kdWxlczogW3tmb3JtczogW1widW5xdWFsaWZpZWQtY2FsbFwiLCBcInJlY2VpdmVyLWNhbGxcIl0sIGlkZW50aXR5OiBcInJ1Ynk6S2VybmVsXCIsIGtpbmQ6IFwiYnVpbHRpblwiLCBzeW1ib2xzOiBbXCJwdXRzXCJdfV0sXG4gICAgcHVibGljRGVjbGFyYXRpb25zOiBbe1xuICAgICAgZWZmZWN0czogW1wiaG9zdFwiXSwgZmFpbHVyZXM6IFtcIldyaXRlRmFpbHVyZVwiXSwgZm9ybXM6IFtcInVucXVhbGlmaWVkLWNhbGxcIiwgXCJyZWNlaXZlci1jYWxsXCJdLCBraW5kOiBcImZ1bmN0aW9uXCIsXG4gICAgICBuYW1lOiBcInB1dHNcIiwgb3duZXJzaGlwOiBcIm5vdC1hcHBsaWNhYmxlXCIsIHBhcmFtZXRlcnM6IFt7bmFtZTogXCJ0ZXh0XCIsIHR5cGU6IFwic3RyaW5nXCJ9XSwgcmV0dXJuVHlwZTogXCJ2b2lkXCJcbiAgICB9XSxcbiAgICByZXF1aXJlbWVudHM6IFt7bW9kdWxlOiBcInNlbWFudGlmb2xkLm91dHB1dFwiLCBvcGVyYXRpb25zOiBbXCJ2MV93cml0ZV9saW5lXCJdLCByYW5nZTogXCIxXCJ9XSxcbiAgICBydW50aW1lUHJvZmlsZTogXCJydWJ5LXRhc2swMzctb3V0cHV0LXYxXCIsXG4gICAgc291cmNlOiB7XG4gICAgICBjb250ZW50OiBgbW9kdWxlIFNlbWFudGlmb2xkVGFzazAzN091dHB1dFxuICBtb2R1bGVfZnVuY3Rpb25cbiAgIyBAcGFyYW0gdGV4dCBbU3RyaW5nXVxuICAjIEByZXR1cm4gW3ZvaWRdXG4gIGRlZiBwdXRzKHRleHQpXG4gICAgdjFfd3JpdGVfbGluZSh0ZXh0KVxuICAgIHJldHVyblxuICBlbmRcbmVuZFxuYCxcbiAgICAgIGZpbGVuYW1lOiBcIl9fc2VtYW50aWZvbGRfZmFjYWRlc19fL3J1Ynkvb3V0cHV0LnJiXCIsXG4gICAgICBpZDogXCJzZW1hbnRpZm9sZC5mYWNhZGUucnVieS5vdXRwdXRcIlxuICAgIH0sXG4gICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgIHZpc2liaWxpdHk6IFwicHVibGljXCJcbiAgfV1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgb25lIHB1YmxpYyBmYWNhZGUgY2xhc3MgZGVzY3JpcHRvci5cbiAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IHZhbHVlIC0gQ2FuZGlkYXRlIGNsYXNzLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gT3duaW5nIGZhY2FkZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVmFsaWRhdGVkIGNsYXNzIG5hbWUuXG4gKiBAcmV0dXJucyB7U3RkbGliRmFjYWRlQ2xhc3NEZWNsYXJhdGlvbn0gRGV0YWNoZWQgY2xhc3MgZGVzY3JpcHRvci5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVQdWJsaWNDbGFzcyh2YWx1ZSwgaWRlbnRpdHksIG5hbWUpIHtcbiAgcmVxdWlyZUtleXModmFsdWUsIFtcImNvbnN0cnVjdG9yXCIsIFwiZm9ybXNcIiwgXCJraW5kXCIsIFwibWV0aG9kc1wiLCBcIm5hbWVcIiwgXCJvd25lcnNoaXBcIl0sXG4gICAgYGZhY2FkZSAnJHtpZGVudGl0eX0nIHB1YmxpYyBjbGFzc2ApXG4gIGlmICghaXNEZW5zZUFycmF5KHZhbHVlLmZvcm1zKSB8fCB2YWx1ZS5mb3Jtcy5sZW5ndGggIT0gMSB8fCB2YWx1ZS5mb3Jtc1swXSAhPSBcImNvbnN0cnVjdG9yLWNhbGxcIiB8fFxuICAgIHZhbHVlLm93bmVyc2hpcCAhPSBcIm93bmVkLXJlZmVyZW5jZVwiIHx8ICFpc1BsYWluT2JqZWN0KHZhbHVlLmNvbnN0cnVjdG9yKSB8fCAhaXNEZW5zZUFycmF5KHZhbHVlLm1ldGhvZHMpKSB7XG4gICAgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgY2xhc3MgJyR7bmFtZX0nIGhhcyBhbiBpbnZhbGlkIHB1YmxpYyBjb250cmFjdC5gKVxuICB9XG4gIGNvbnN0IGNvbnN0cnVjdG9yID0gLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gKi8gKHZhbHVlLmNvbnN0cnVjdG9yKVxuXG4gIHJlcXVpcmVLZXlzKGNvbnN0cnVjdG9yLCBbXCJlZmZlY3RzXCIsIFwiZmFpbHVyZXNcIiwgXCJvd25lcnNoaXBcIiwgXCJwYXJhbWV0ZXJzXCJdLCBgZmFjYWRlICcke2lkZW50aXR5fScgY29uc3RydWN0b3JgKVxuICBpZiAoY29uc3RydWN0b3Iub3duZXJzaGlwICE9IFwiYWNxdWlyZWRcIiB8fCAhdmFsaWRGYWNhZGVFZmZlY3RzKGNvbnN0cnVjdG9yLmVmZmVjdHMpIHx8XG4gICAgIXZhbGlkRmFjYWRlRmFpbHVyZXMoY29uc3RydWN0b3IuZmFpbHVyZXMpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBjbGFzcyAnJHtuYW1lfScgaGFzIGFuIGludmFsaWQgY29uc3RydWN0b3IuYClcbiAgY29uc3QgcGFyYW1ldGVycyA9IHZhbGlkYXRlRmFjYWRlUGFyYW1ldGVycyhjb25zdHJ1Y3Rvci5wYXJhbWV0ZXJzLCBpZGVudGl0eSwgYCR7bmFtZX0ubmV3YClcbiAgY29uc3QgbWV0aG9kTmFtZXMgPSBuZXcgU2V0KClcbiAgY29uc3QgbWV0aG9kcyA9IHZhbHVlLm1ldGhvZHMubWFwKChtZXRob2QpID0+IHtcbiAgICBpZiAoIWlzUGxhaW5PYmplY3QobWV0aG9kKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgY2xhc3MgJyR7bmFtZX0nIGhhcyBhbiBpbnZhbGlkIG1ldGhvZC5gKVxuICAgIHJlcXVpcmVLZXlzKG1ldGhvZCwgW1wiZWZmZWN0c1wiLCBcImZhaWx1cmVzXCIsIFwiZm9ybXNcIiwgXCJuYW1lXCIsIFwib3duZXJzaGlwXCIsIFwicGFyYW1ldGVyc1wiLCBcInJldHVyblR5cGVcIl0sXG4gICAgICBgZmFjYWRlICcke2lkZW50aXR5fScgY2xhc3MgbWV0aG9kYClcbiAgICBjb25zdCBtZXRob2ROYW1lID0gcmVxdWlyZVN0cmluZyhtZXRob2QubmFtZSwgYEZhY2FkZSAnJHtpZGVudGl0eX0nIG1ldGhvZCBuYW1lYClcbiAgICBjb25zdCByZXR1cm5UeXBlID0gcmVxdWlyZVN0cmluZyhtZXRob2QucmV0dXJuVHlwZSwgYEZhY2FkZSAnJHtpZGVudGl0eX0nIG1ldGhvZCByZXR1cm4gdHlwZWApXG5cbiAgICBpZiAoIWRlY2xhcmF0aW9uTmFtZVBhdHRlcm4udGVzdChtZXRob2ROYW1lKSB8fCBtZXRob2ROYW1lcy5oYXMobWV0aG9kTmFtZSkgfHwgIXZhbGlkRmFjYWRlRWZmZWN0cyhtZXRob2QuZWZmZWN0cykgfHxcbiAgICAgICF2YWxpZEZhY2FkZUZhaWx1cmVzKG1ldGhvZC5mYWlsdXJlcykgfHwgIWlzRGVuc2VBcnJheShtZXRob2QuZm9ybXMpIHx8IG1ldGhvZC5mb3Jtcy5sZW5ndGggIT0gMSB8fFxuICAgICAgbWV0aG9kLmZvcm1zWzBdICE9IFwicmVjZWl2ZXItY2FsbFwiIHx8IG1ldGhvZC5vd25lcnNoaXAgIT0gXCJib3Jyb3dlZFwiICYmIG1ldGhvZC5vd25lcnNoaXAgIT0gXCJjb25zdW1lZFwiIHx8XG4gICAgICAhaXNGYWNhZGVUeXBlKHJldHVyblR5cGUsIHRydWUpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBjbGFzcyAnJHtuYW1lfScgaGFzIGFuIGludmFsaWQgbWV0aG9kLmApXG4gICAgbWV0aG9kTmFtZXMuYWRkKG1ldGhvZE5hbWUpXG4gICAgcmV0dXJuIHtcbiAgICAgIGVmZmVjdHM6IC8qKiBAdHlwZSB7c3RyaW5nW119ICovIChbLi4uLyoqIEB0eXBlIHt1bmtub3duW119ICovIChtZXRob2QuZWZmZWN0cyldKSxcbiAgICAgIGZhaWx1cmVzOiAvKiogQHR5cGUge3N0cmluZ1tdfSAqLyAoWy4uLi8qKiBAdHlwZSB7dW5rbm93bltdfSAqLyAobWV0aG9kLmZhaWx1cmVzKV0pLFxuICAgICAgZm9ybXM6IC8qKiBAdHlwZSB7W1wicmVjZWl2ZXItY2FsbFwiXX0gKi8gKFtcInJlY2VpdmVyLWNhbGxcIl0pLFxuICAgICAgbmFtZTogbWV0aG9kTmFtZSxcbiAgICAgIG93bmVyc2hpcDogLyoqIEB0eXBlIHtcImJvcnJvd2VkXCIgfCBcImNvbnN1bWVkXCJ9ICovIChtZXRob2Qub3duZXJzaGlwKSxcbiAgICAgIHBhcmFtZXRlcnM6IHZhbGlkYXRlRmFjYWRlUGFyYW1ldGVycyhtZXRob2QucGFyYW1ldGVycywgaWRlbnRpdHksIGAke25hbWV9LiR7bWV0aG9kTmFtZX1gKSxcbiAgICAgIHJldHVyblR5cGVcbiAgICB9XG4gIH0pXG5cbiAgcmV0dXJuIHtcbiAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgZWZmZWN0czogLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi8gKFsuLi4vKiogQHR5cGUge3Vua25vd25bXX0gKi8gKGNvbnN0cnVjdG9yLmVmZmVjdHMpXSksXG4gICAgICBmYWlsdXJlczogLyoqIEB0eXBlIHtzdHJpbmdbXX0gKi8gKFsuLi4vKiogQHR5cGUge3Vua25vd25bXX0gKi8gKGNvbnN0cnVjdG9yLmZhaWx1cmVzKV0pLFxuICAgICAgb3duZXJzaGlwOiBcImFjcXVpcmVkXCIsXG4gICAgICBwYXJhbWV0ZXJzXG4gICAgfSxcbiAgICBmb3JtczogW1wiY29uc3RydWN0b3ItY2FsbFwiXSxcbiAgICBraW5kOiBcImNsYXNzXCIsXG4gICAgbWV0aG9kcyxcbiAgICBuYW1lLFxuICAgIG93bmVyc2hpcDogXCJvd25lZC1yZWZlcmVuY2VcIlxuICB9XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGZhY2FkZSBwYXJhbWV0ZXJzIHNoYXJlZCBieSBmdW5jdGlvbnMsIGNvbnN0cnVjdG9ycywgYW5kIG1ldGhvZHMuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBwYXJhbWV0ZXJzLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkZW50aXR5IC0gT3duaW5nIGZhY2FkZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBjYWxsYWJsZSAtIENhbGxhYmxlIG5hbWUuXG4gKiBAcmV0dXJucyB7e25hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nfVtdfSBEZXRhY2hlZCBwYXJhbWV0ZXJzLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUZhY2FkZVBhcmFtZXRlcnMoY2FuZGlkYXRlLCBpZGVudGl0eSwgY2FsbGFibGUpIHtcbiAgaWYgKCFpc0RlbnNlQXJyYXkoY2FuZGlkYXRlKSkgaW52YWxpZEZhY2FkZShgRmFjYWRlICcke2lkZW50aXR5fScgZGVjbGFyYXRpb24gJyR7Y2FsbGFibGV9JyBoYXMgaW52YWxpZCBwYXJhbWV0ZXJzLmApXG4gIGNvbnN0IG5hbWVzID0gbmV3IFNldCgpXG5cbiAgcmV0dXJuIGNhbmRpZGF0ZS5tYXAoKHBhcmFtZXRlcikgPT4ge1xuICAgIGlmICghaXNQbGFpbk9iamVjdChwYXJhbWV0ZXIpKSBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBkZWNsYXJhdGlvbiAnJHtjYWxsYWJsZX0nIGhhcyBhbiBpbnZhbGlkIHBhcmFtZXRlci5gKVxuICAgIHJlcXVpcmVLZXlzKHBhcmFtZXRlciwgW1wibmFtZVwiLCBcInR5cGVcIl0sIGBmYWNhZGUgJyR7aWRlbnRpdHl9JyBkZWNsYXJhdGlvbiBwYXJhbWV0ZXJgKVxuICAgIGNvbnN0IG5hbWUgPSByZXF1aXJlU3RyaW5nKHBhcmFtZXRlci5uYW1lLCBgRmFjYWRlICcke2lkZW50aXR5fScgcGFyYW1ldGVyIG5hbWVgKVxuICAgIGNvbnN0IHR5cGUgPSByZXF1aXJlU3RyaW5nKHBhcmFtZXRlci50eXBlLCBgRmFjYWRlICcke2lkZW50aXR5fScgcGFyYW1ldGVyIHR5cGVgKVxuXG4gICAgaWYgKCFkZWNsYXJhdGlvbk5hbWVQYXR0ZXJuLnRlc3QobmFtZSkgfHwgbmFtZXMuaGFzKG5hbWUpIHx8ICFpc0ZhY2FkZVR5cGUodHlwZSwgZmFsc2UpKSB7XG4gICAgICBpbnZhbGlkRmFjYWRlKGBGYWNhZGUgJyR7aWRlbnRpdHl9JyBkZWNsYXJhdGlvbiAnJHtjYWxsYWJsZX0nIGhhcyBhbiBpbnZhbGlkIHBhcmFtZXRlci5gKVxuICAgIH1cbiAgICBuYW1lcy5hZGQobmFtZSlcbiAgICByZXR1cm4ge25hbWUsIHR5cGV9XG4gIH0pXG59XG5cbi8qKlxuICogQ2hlY2tzIG9uZSBmYWNhZGUgZWZmZWN0IGxpc3QuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBlZmZlY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgZWZmZWN0cyBhcmUgZXhhY3QuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkRmFjYWRlRWZmZWN0cyhjYW5kaWRhdGUpIHtcbiAgcmV0dXJuIGlzRGVuc2VBcnJheShjYW5kaWRhdGUpICYmIGNhbmRpZGF0ZS5ldmVyeSgoZWZmZWN0KSA9PiBlZmZlY3QgPT0gXCJob3N0XCIpICYmIG5ldyBTZXQoY2FuZGlkYXRlKS5zaXplID09IGNhbmRpZGF0ZS5sZW5ndGhcbn1cblxuLyoqXG4gKiBDaGVja3Mgb25lIGZhY2FkZSBmYWlsdXJlIGxpc3QuXG4gKiBAcGFyYW0ge3Vua25vd259IGNhbmRpZGF0ZSAtIENhbmRpZGF0ZSBmYWlsdXJlcy5cbiAqIEByZXR1cm5zIHtjYW5kaWRhdGUgaXMgc3RyaW5nW119IFdoZXRoZXIgZmFpbHVyZXMgYXJlIGV4YWN0LlxuICovXG5mdW5jdGlvbiB2YWxpZEZhY2FkZUZhaWx1cmVzKGNhbmRpZGF0ZSkge1xuICByZXR1cm4gaXNEZW5zZUFycmF5KGNhbmRpZGF0ZSkgJiYgY2FuZGlkYXRlLmV2ZXJ5KChmYWlsdXJlKSA9PiB0eXBlb2YgZmFpbHVyZSA9PSBcInN0cmluZ1wiICYmIGRlY2xhcmF0aW9uTmFtZVBhdHRlcm4udGVzdChmYWlsdXJlKSkgJiZcbiAgICBuZXcgU2V0KGNhbmRpZGF0ZSkuc2l6ZSA9PSBjYW5kaWRhdGUubGVuZ3RoXG59XG5cbi8qKlxuICogQ2hlY2tzIG9uZSBmYWNhZGUgdHlwZSBzcGVsbGluZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIC0gQ2FuZGlkYXRlIHR5cGUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFsbG93Vm9pZCAtIFdoZXRoZXIgdm9pZCBpcyB2YWxpZCBpbiB0aGlzIHBvc2l0aW9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHR5cGUgaXMgY2Fub25pY2FsLlxuICovXG5mdW5jdGlvbiBpc0ZhY2FkZVR5cGUodHlwZSwgYWxsb3dWb2lkKSB7XG4gIGlmIChjYW5vbmljYWxUeXBlcy5oYXModHlwZSkpIHJldHVybiBhbGxvd1ZvaWQgfHwgdHlwZSAhPSBcInZvaWRcIlxuICBjb25zdCBvcHRpb25hbCA9IC9eb3B0aW9uYWw6KGJvb2xlYW58aW50ZWdlcnxzdHJpbmcpJC91LmV4ZWModHlwZSlcblxuICByZXR1cm4gb3B0aW9uYWwgIT09IG51bGxcbn1cblxuLyoqXG4gKiBEZXRhY2hlcyBvbmUgZGVzY3JpcHRvciBmb3IgdGhlIHB1YmxpYyBwcm9ncmFtIHJlY29yZC5cbiAqIEBwYXJhbSB7U3RkbGliRmFjYWRlUHVibGljRGVjbGFyYXRpb259IGRlY2xhcmF0aW9uIC0gUmVnaXN0cnkgZGVjbGFyYXRpb24uXG4gKiBAcmV0dXJucyB7U3RkbGliRmFjYWRlUHVibGljRGVjbGFyYXRpb259IERldGFjaGVkIGRlY2xhcmF0aW9uLlxuICovXG5mdW5jdGlvbiBkZXRhY2hQdWJsaWNEZWNsYXJhdGlvbihkZWNsYXJhdGlvbikge1xuICBpZiAoZGVjbGFyYXRpb24ua2luZCA9PSBcImZ1bmN0aW9uXCIpIHJldHVybiB7Li4uZGVjbGFyYXRpb24sIGVmZmVjdHM6IFsuLi5kZWNsYXJhdGlvbi5lZmZlY3RzXSwgZmFpbHVyZXM6IFsuLi5kZWNsYXJhdGlvbi5mYWlsdXJlc10sXG4gICAgZm9ybXM6IFsuLi5kZWNsYXJhdGlvbi5mb3Jtc10sIHBhcmFtZXRlcnM6IGRlY2xhcmF0aW9uLnBhcmFtZXRlcnMubWFwKChwYXJhbWV0ZXIpID0+ICh7Li4ucGFyYW1ldGVyfSkpfVxuICByZXR1cm4gey4uLmRlY2xhcmF0aW9uLFxuICAgIGNvbnN0cnVjdG9yOiB7Li4uZGVjbGFyYXRpb24uY29uc3RydWN0b3IsIGVmZmVjdHM6IFsuLi5kZWNsYXJhdGlvbi5jb25zdHJ1Y3Rvci5lZmZlY3RzXSwgZmFpbHVyZXM6IFsuLi5kZWNsYXJhdGlvbi5jb25zdHJ1Y3Rvci5mYWlsdXJlc10sXG4gICAgICBwYXJhbWV0ZXJzOiBkZWNsYXJhdGlvbi5jb25zdHJ1Y3Rvci5wYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyKSA9PiAoey4uLnBhcmFtZXRlcn0pKX0sXG4gICAgZm9ybXM6IFsuLi5kZWNsYXJhdGlvbi5mb3Jtc10sXG4gICAgbWV0aG9kczogZGVjbGFyYXRpb24ubWV0aG9kcy5tYXAoKG1ldGhvZCkgPT4gKHsuLi5tZXRob2QsIGVmZmVjdHM6IFsuLi5tZXRob2QuZWZmZWN0c10sIGZhaWx1cmVzOiBbLi4ubWV0aG9kLmZhaWx1cmVzXSxcbiAgICAgIGZvcm1zOiBbLi4ubWV0aG9kLmZvcm1zXSwgcGFyYW1ldGVyczogbWV0aG9kLnBhcmFtZXRlcnMubWFwKChwYXJhbWV0ZXIpID0+ICh7Li4ucGFyYW1ldGVyfSkpfSkpfVxufVxuXG4vKipcbiAqIERldGFjaGVzIGEgbG9jYWwgb3IgZGVwZW5kZW5jeS1xdWFsaWZpZWQgY29udHJhY3QgcmVmZXJlbmNlLlxuICogQHBhcmFtIHtzdHJpbmcgfCBpbXBvcnQoXCIuL3NlbWFudGljL3N0ZGxpYi5qc1wiKS5DYW5vbmljYWxEZWNsYXJhdGlvblJlZmVyZW5jZX0gcmVmZXJlbmNlIC0gQ29udHJhY3QgcmVmZXJlbmNlLlxuICogQHJldHVybnMge3N0cmluZyB8IGltcG9ydChcIi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2FwYWJpbGl0eURlY2xhcmF0aW9uUmVmZXJlbmNlSW5wdXR9IERldGFjaGVkIHJlZmVyZW5jZS5cbiAqL1xuZnVuY3Rpb24gZGV0YWNoQ2Fub25pY2FsUmVmZXJlbmNlKHJlZmVyZW5jZSkge1xuICByZXR1cm4gdHlwZW9mIHJlZmVyZW5jZSA9PSBcInN0cmluZ1wiID8gcmVmZXJlbmNlIDoge21vZHVsZTogcmVmZXJlbmNlLm1vZHVsZSwgbmFtZTogcmVmZXJlbmNlLm5hbWV9XG59XG5cbi8qKlxuICogRGV0YWNoZXMgYSBjYW5vbmljYWwgcmVzb3VyY2UgZmxvdyBmb3IgYXV0aG9yaXR5IGNvbnN0cnVjdGlvbi5cbiAqIEBwYXJhbSB7b2JqZWN0fSBmbG93IC0gQ2Fub25pY2FsIHJlc291cmNlIGZsb3cuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5DYXBhYmlsaXR5UmVzb3VyY2VGbG93SW5wdXR9IERldGFjaGVkIGZsb3cuXG4gKi9cbmZ1bmN0aW9uIGRldGFjaFJlc291cmNlRmxvdyhmbG93KSB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59ICovIChmbG93KVxuXG4gIGlmIChjYW5kaWRhdGUua2luZCA9PSBcIm5vbmVcIikgcmV0dXJuIHtraW5kOiBcIm5vbmVcIn1cbiAgaWYgKGNhbmRpZGF0ZS5raW5kID09IFwiYWNxdWlyZVwiKSByZXR1cm4ge2tpbmQ6IFwiYWNxdWlyZVwiLCByZXNvdXJjZTogZGV0YWNoQ2Fub25pY2FsUmVmZXJlbmNlKFxuICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgaW1wb3J0KFwiLi9zZW1hbnRpYy9zdGRsaWIuanNcIikuQ2Fub25pY2FsRGVjbGFyYXRpb25SZWZlcmVuY2V9ICovIChjYW5kaWRhdGUucmVzb3VyY2UpKX1cbiAgcmV0dXJuIHtcbiAgICBraW5kOiAvKiogQHR5cGUge1wiYm9ycm93XCIgfCBcImNsb3NlXCJ9ICovIChjYW5kaWRhdGUua2luZCksXG4gICAgcGFyYW1ldGVySW5kZXg6IC8qKiBAdHlwZSB7bnVtYmVyfSAqLyAoY2FuZGlkYXRlLnBhcmFtZXRlckluZGV4KSxcbiAgICB0ZXJtaW5hbEZhaWx1cmU6IGRldGFjaENhbm9uaWNhbFJlZmVyZW5jZShcbiAgICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgaW1wb3J0KFwiLi9zZW1hbnRpYy9zdGRsaWIuanNcIikuQ2Fub25pY2FsRGVjbGFyYXRpb25SZWZlcmVuY2V9ICovIChjYW5kaWRhdGUudGVybWluYWxGYWlsdXJlKSlcbiAgfVxufVxuXG4vKipcbiAqIE1hcHMgb25lIGNhbm9uaWNhbCBtb2R1bGUgaWRlbnRpdHkgdG8gaXRzIGNsb3NlZCBjYXBhYmlsaXR5IG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRlbnRpdHkgLSBDYW5vbmljYWwgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDYXBhYmlsaXR5IG5hbWUuXG4gKi9cbmZ1bmN0aW9uIGNhbm9uaWNhbENhcGFiaWxpdHlOYW1lKGlkZW50aXR5KSB7XG4gIC8qKiBAdHlwZSB7UmVhZG9ubHk8UmVjb3JkPHN0cmluZywgc3RyaW5nPj59ICovXG4gIGNvbnN0IG5hbWVzID0ge1xuICAgIFwic2VtYW50aWZvbGQub3V0cHV0XCI6IFwiT3V0cHV0XCIsXG4gICAgXCJzZW1hbnRpZm9sZC5yZXNvdXJjZVwiOiBcIlJlc291cmNlXCIsXG4gICAgXCJzZW1hbnRpZm9sZC5zb2NrZXQtY2xpZW50XCI6IFwiU29ja2V0Q2xpZW50XCIsXG4gICAgXCJzZW1hbnRpZm9sZC50YXNrMDM0LnJlc291cmNlLXByb2JlXCI6IFwiUmVzb3VyY2VQcm9iZVwiLFxuICAgIFwic2VtYW50aWZvbGQudGV4dC1zdHJlYW1cIjogXCJUZXh0U3RyZWFtXCJcbiAgfVxuXG4gIHJldHVybiBuYW1lc1tpZGVudGl0eV0gPz8gaW52YWxpZEZhY2FkZShgRmFjYWRlIHJlcXVpcmVtZW50cyBuYW1lIHVua25vd24gY2Fub25pY2FsIG1vZHVsZSAnJHtpZGVudGl0eX0nLmApXG59XG5cbi8qKlxuICogQnVpbGRzIGV4ZWN1dGFibGUgc291cmNlIGFuZCBuYXRpdmUgaWRlbnRpdHkgc3BlbGxpbmdzIGZvciBvbmUgb3JpZ2luYWwtZml2ZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEByZXR1cm5zIHtGYWNhZGVTb3VyY2VOYW1lc30gRmFjYWRlIHNvdXJjZSBkZWZpbml0aW9ucy5cbiAqL1xuZnVuY3Rpb24gZmFjYWRlTmFtZXMobGFuZ3VhZ2UpIHtcbiAgaWYgKGxhbmd1YWdlID09IFwicGhwXCIpIHJldHVybiB7XG4gICAgZXh0ZW5zaW9uOiBcInBocFwiLCBuYXRpdmVNb2R1bGU6IFwiU2VtYW50aWZvbGRcXFxcVGFzazAzNlxcXFxQcm9iZVwiLCBwdWJsaWNOYW1lOiBcImNvbXBhdGliaWxpdHlfcHJvYmVcIixcbiAgICB1bnVzZWROYW1lOiBcInVudXNlZF9wcm9iZVwiLCB1bnVzZWROYXRpdmVNb2R1bGU6IFwiU2VtYW50aWZvbGRcXFxcVGFzazAzNlxcXFxVbnVzZWRcIixcbiAgICBwcm9iZVNvdXJjZTogYDw/cGhwXG5kZWNsYXJlKHN0cmljdF90eXBlcz0xKTtcbm5hbWVzcGFjZSBTZW1hbnRpZm9sZFxcXFxGYWNhZGVcXFxcUGhwXFxcXFByb2JlO1xudXNlIGZ1bmN0aW9uIFNlbWFudGlmb2xkXFxcXEZhY2FkZVxcXFxQaHBcXFxcUHJvYmVSdW5uZXJcXFxccnVuX2NvbXBhdGliaWxpdHlfcHJvYmU7XG5yZXF1aXJlX29uY2UgX19ESVJfXyAuIFwiL3Byb2JlLXJ1bm5lci5waHBcIjtcbmZ1bmN0aW9uIGNvbXBhdGliaWxpdHlfcHJvYmUoc3RyaW5nICRsYWJlbCk6IHN0cmluZyB7IHJldHVybiBydW5fY29tcGF0aWJpbGl0eV9wcm9iZSgkbGFiZWwpOyB9XG5gLFxuICAgIHJ1bm5lclNvdXJjZTogYDw/cGhwXG5kZWNsYXJlKHN0cmljdF90eXBlcz0xKTtcbm5hbWVzcGFjZSBTZW1hbnRpZm9sZFxcXFxGYWNhZGVcXFxcUGhwXFxcXFByb2JlUnVubmVyO1xuZnVuY3Rpb24gcnVuX2NvbXBhdGliaWxpdHlfcHJvYmUoc3RyaW5nICRsYWJlbCk6IHN0cmluZyB7XG4gICAgdHJ5IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEB2YXIgaW50ICRlZmZlY3RcbiAgICAgICAgICogQHNlbWFudGlmb2xkLWltbXV0YWJsZVxuICAgICAgICAgKi9cbiAgICAgICAgJGVmZmVjdCA9IHByb2JlRWZmZWN0KCRsYWJlbCwgMSwgZmFsc2UpO1xuICAgICAgICByZXR1cm4gcHJvYmVUcmFjZSgpO1xuICAgIH1cbiAgICBjYXRjaCAoUHJvYmVPcGVyYXRpb25GYWlsdXJlICRlcnJvcikgeyByZXR1cm4gJGVycm9yLT5nZXRNZXNzYWdlKCk7IH1cbn1cbmAsXG4gICAgdW51c2VkU291cmNlOiBgPD9waHBcbmRlY2xhcmUoc3RyaWN0X3R5cGVzPTEpO1xubmFtZXNwYWNlIFNlbWFudGlmb2xkXFxcXEZhY2FkZVxcXFxQaHBcXFxcVW51c2VkO1xuZnVuY3Rpb24gdW51c2VkX3Byb2JlKHN0cmluZyAkbGFiZWwpOiBzdHJpbmcgeyByZXR1cm4gcHJvYmVUcmFjZSgpOyB9XG5gXG4gIH1cbiAgaWYgKGxhbmd1YWdlID09IFwicnVieVwiKSByZXR1cm4ge1xuICAgIGV4dGVuc2lvbjogXCJyYlwiLCBuYXRpdmVNb2R1bGU6IFwic2VtYW50aWZvbGQvdGFzazAzNi9wcm9iZVwiLCBwdWJsaWNOYW1lOiBcImNvbXBhdGliaWxpdHlfcHJvYmVcIixcbiAgICB1bnVzZWROYW1lOiBcInVudXNlZF9wcm9iZVwiLCB1bnVzZWROYXRpdmVNb2R1bGU6IFwic2VtYW50aWZvbGQvdGFzazAzNi91bnVzZWRcIixcbiAgICBwcm9iZVNvdXJjZTogYHJlcXVpcmVfcmVsYXRpdmUgXCJwcm9iZS1ydW5uZXJcIlxubW9kdWxlIFNlbWFudGlmb2xkVGFzazAzNlByb2JlXG4gIG1vZHVsZV9mdW5jdGlvblxuICAjIEBwYXJhbSBsYWJlbCBbU3RyaW5nXVxuICAjIEByZXR1cm4gW1N0cmluZ11cbiAgZGVmIGNvbXBhdGliaWxpdHlfcHJvYmUobGFiZWwpXG4gICAgcmV0dXJuIFNlbWFudGlmb2xkVGFzazAzNlByb2JlUnVubmVyLnJ1bl9jb21wYXRpYmlsaXR5X3Byb2JlKGxhYmVsKVxuICBlbmRcbmVuZFxuYCxcbiAgICBydW5uZXJTb3VyY2U6IGBtb2R1bGUgU2VtYW50aWZvbGRUYXNrMDM2UHJvYmVSdW5uZXJcbiAgbW9kdWxlX2Z1bmN0aW9uXG4gICMgQHBhcmFtIGxhYmVsIFtTdHJpbmddXG4gICMgQHJldHVybiBbU3RyaW5nXVxuICBkZWYgcnVuX2NvbXBhdGliaWxpdHlfcHJvYmUobGFiZWwpXG4gICAgYmVnaW5cbiAgICAgICMgQHR5cGUgW0ludGVnZXJdXG4gICAgICAjIEBzZW1hbnRpZm9sZC1pbW11dGFibGVcbiAgICAgIGVmZmVjdCA9IHByb2JlRWZmZWN0KGxhYmVsLCAxLCBmYWxzZSlcbiAgICAgIHJldHVybiBwcm9iZVRyYWNlXG4gICAgcmVzY3VlIFByb2JlT3BlcmF0aW9uRmFpbHVyZSA9PiBlcnJvclxuICAgICAgcmV0dXJuIGVycm9yLm1lc3NhZ2VcbiAgICBlbmRcbiAgZW5kXG5lbmRcbmAsXG4gICAgdW51c2VkU291cmNlOiBgbW9kdWxlIFNlbWFudGlmb2xkVGFzazAzNlVudXNlZFxuICBtb2R1bGVfZnVuY3Rpb25cbiAgIyBAcGFyYW0gbGFiZWwgW1N0cmluZ11cbiAgIyBAcmV0dXJuIFtTdHJpbmddXG4gIGRlZiB1bnVzZWRfcHJvYmUobGFiZWwpXG4gICAgcmV0dXJuIHByb2JlVHJhY2VcbiAgZW5kXG5lbmRcbmBcbiAgfVxuICBpZiAobGFuZ3VhZ2UgPT0gXCJqYXZhXCIpIHJldHVybiB7XG4gICAgZXh0ZW5zaW9uOiBcImphdmFcIiwgbmF0aXZlTW9kdWxlOiBcInNlbWFudGlmb2xkLnRhc2swMzYuUHJvYmVcIiwgcHVibGljTmFtZTogXCJjb21wYXRpYmlsaXR5UHJvYmVcIixcbiAgICB1bnVzZWROYW1lOiBcInVudXNlZFByb2JlXCIsIHVudXNlZE5hdGl2ZU1vZHVsZTogXCJzZW1hbnRpZm9sZC50YXNrMDM2LlVudXNlZFwiLFxuICAgIHByb2JlU291cmNlOiBgcGFja2FnZSBzZW1hbnRpZm9sZC5mYWNhZGUuamF2YS5wcm9iZTtcbmltcG9ydCBzZW1hbnRpZm9sZC5mYWNhZGUuamF2YS5wcm9iZXJ1bm5lci5Qcm9iZVJ1bm5lcjtcbnB1YmxpYyBmaW5hbCBjbGFzcyBQcm9iZSB7XG4gIHB1YmxpYyBzdGF0aWMgU3RyaW5nIGNvbXBhdGliaWxpdHlQcm9iZShTdHJpbmcgbGFiZWwpIHsgcmV0dXJuIFByb2JlUnVubmVyLnJ1bkNvbXBhdGliaWxpdHlQcm9iZShsYWJlbCk7IH1cbn1cbmAsXG4gICAgcnVubmVyU291cmNlOiBgcGFja2FnZSBzZW1hbnRpZm9sZC5mYWNhZGUuamF2YS5wcm9iZXJ1bm5lcjtcbnB1YmxpYyBmaW5hbCBjbGFzcyBQcm9iZVJ1bm5lciB7XG4gIHB1YmxpYyBzdGF0aWMgU3RyaW5nIHJ1bkNvbXBhdGliaWxpdHlQcm9iZShTdHJpbmcgbGFiZWwpIHtcbiAgICB0cnkgeyBmaW5hbCBpbnQgZWZmZWN0ID0gcHJvYmVFZmZlY3QobGFiZWwsIDEsIGZhbHNlKTsgcmV0dXJuIHByb2JlVHJhY2UoKTsgfVxuICAgIGNhdGNoIChQcm9iZU9wZXJhdGlvbkZhaWx1cmUgZXJyb3IpIHsgcmV0dXJuIGVycm9yLmdldE1lc3NhZ2UoKTsgfVxuICB9XG59XG5gLFxuICAgIHVudXNlZFNvdXJjZTogYHBhY2thZ2Ugc2VtYW50aWZvbGQuZmFjYWRlLmphdmEudW51c2VkO1xucHVibGljIGZpbmFsIGNsYXNzIFVudXNlZCB7XG4gIHB1YmxpYyBzdGF0aWMgU3RyaW5nIHVudXNlZFByb2JlKFN0cmluZyBsYWJlbCkgeyByZXR1cm4gcHJvYmVUcmFjZSgpOyB9XG59XG5gXG4gIH1cbiAgY29uc3QgdHlwZWQgPSBsYW5ndWFnZSA9PSBcInR5cGVzY3JpcHRcIlxuICBjb25zdCBleHRlbnNpb24gPSB0eXBlZCA/IFwidHNcIiA6IFwianNcIlxuICBjb25zdCBwYXJhbWV0ZXIgPSB0eXBlZCA/IFwibGFiZWw6IHN0cmluZ1wiIDogXCJsYWJlbFwiXG4gIGNvbnN0IHJlc3VsdCA9IHR5cGVkID8gXCI6IHN0cmluZ1wiIDogXCJcIlxuICBjb25zdCBkb2N1bWVudGF0aW9uID0gdHlwZWQgPyBcIlwiIDogYC8qKlxuICogQHBhcmFtIHtzdHJpbmd9IGxhYmVsXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5gXG5cbiAgcmV0dXJuIHtcbiAgICBleHRlbnNpb24sIG5hdGl2ZU1vZHVsZTogXCJzZW1hbnRpZm9sZDp0YXNrMDM2L3Byb2JlXCIsIHB1YmxpY05hbWU6IFwiY29tcGF0aWJpbGl0eVByb2JlXCIsXG4gICAgdW51c2VkTmFtZTogXCJ1bnVzZWRQcm9iZVwiLCB1bnVzZWROYXRpdmVNb2R1bGU6IFwic2VtYW50aWZvbGQ6dGFzazAzNi91bnVzZWRcIixcbiAgICBwcm9iZVNvdXJjZTogYGltcG9ydCB7cnVuQ29tcGF0aWJpbGl0eVByb2JlfSBmcm9tIFwiLi9wcm9iZS1ydW5uZXIuanNcIlxuJHtkb2N1bWVudGF0aW9ufWV4cG9ydCBmdW5jdGlvbiBjb21wYXRpYmlsaXR5UHJvYmUoJHtwYXJhbWV0ZXJ9KSR7cmVzdWx0fSB7IHJldHVybiBydW5Db21wYXRpYmlsaXR5UHJvYmUobGFiZWwpIH1cbmAsXG4gICAgcnVubmVyU291cmNlOiBgJHtkb2N1bWVudGF0aW9ufWV4cG9ydCBmdW5jdGlvbiBydW5Db21wYXRpYmlsaXR5UHJvYmUoJHtwYXJhbWV0ZXJ9KSR7cmVzdWx0fSB7XG4gIHRyeSB7ICR7dHlwZWQgPyBcImNvbnN0IGVmZmVjdDogbnVtYmVyXCIgOiBcIi8qKiBAdHlwZSB7bnVtYmVyfSAqLyBjb25zdCBlZmZlY3RcIn0gPSBwcm9iZUVmZmVjdChsYWJlbCwgMSwgZmFsc2UpOyByZXR1cm4gcHJvYmVUcmFjZSgpIH1cbiAgY2F0Y2ggKGVycm9yKSB7IGlmICghKGVycm9yIGluc3RhbmNlb2YgUHJvYmVPcGVyYXRpb25GYWlsdXJlKSkgeyB0aHJvdyBlcnJvciB9IHJldHVybiBlcnJvci5tZXNzYWdlIH1cbn1cbmAsXG4gICAgdW51c2VkU291cmNlOiBgJHtkb2N1bWVudGF0aW9ufWV4cG9ydCBmdW5jdGlvbiB1bnVzZWRQcm9iZSgke3BhcmFtZXRlcn0pJHtyZXN1bHR9IHsgcmV0dXJuIHByb2JlVHJhY2UoKSB9XG5gXG4gIH1cbn1cblxuLyoqXG4gKiBSZXF1aXJlcyBhIGNsb3NlZCBleGFjdCBrZXkgc2V0LlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gdmFsdWUgLSBQbGFpbiBjYW5kaWRhdGUgb2JqZWN0LlxuICogQHBhcmFtIHtzdHJpbmdbXX0ga2V5cyAtIEV4cGVjdGVkIGtleXMuXG4gKiBAcGFyYW0ge3N0cmluZ30gc3ViamVjdCAtIERpYWdub3N0aWMgc3ViamVjdC5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiByZXF1aXJlS2V5cyh2YWx1ZSwga2V5cywgc3ViamVjdCkge1xuICBpZiAoT2JqZWN0LmtleXModmFsdWUpLnNvcnQoKS5qb2luKFwiLFwiKSAhPSBbLi4ua2V5c10uc29ydCgpLmpvaW4oXCIsXCIpKSBpbnZhbGlkRmFjYWRlKGBJbnZhbGlkICR7c3ViamVjdH0gZmllbGRzLmApXG59XG5cbi8qKlxuICogUmVxdWlyZXMgb25lIG5vbi1lbXB0eSBzdHJpbmcuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHZhbHVlLlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBEaWFnbm9zdGljIHN1YmplY3QuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBWYWxpZGF0ZWQgc3RyaW5nLlxuICovXG5mdW5jdGlvbiByZXF1aXJlU3RyaW5nKHZhbHVlLCBzdWJqZWN0KSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT0gXCJzdHJpbmdcIiB8fCB2YWx1ZS5sZW5ndGggPT0gMCkgaW52YWxpZEZhY2FkZShgJHtzdWJqZWN0fSBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZy5gKVxuICByZXR1cm4gLyoqIEB0eXBlIHtzdHJpbmd9ICovICh2YWx1ZSlcbn1cblxuLyoqXG4gKiBDaGVja3MgZm9yIGFuIG9yZGluYXJ5IG9iamVjdCB3aXRoIG5vIGN1c3RvbSBwcm90b3R5cGUuXG4gKiBAcGFyYW0ge3Vua25vd259IHZhbHVlIC0gQ2FuZGlkYXRlIHZhbHVlLlxuICogQHJldHVybnMge3ZhbHVlIGlzIFJlY29yZDxzdHJpbmcsIHVua25vd24+fSBXaGV0aGVyIHRoZSBjYW5kaWRhdGUgaXMgcGxhaW4uXG4gKi9cbmZ1bmN0aW9uIGlzUGxhaW5PYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpID09IE9iamVjdC5wcm90b3R5cGVcbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBmcmVlemVzIG9uZSBkZXRhY2hlZCBmYWNhZGUgcmVnaXN0cnkgdmFsdWUuXG4gKiBAdGVtcGxhdGUge29iamVjdH0gVFxuICogQHBhcmFtIHtUfSB2YWx1ZSAtIERldGFjaGVkIG9iamVjdC5cbiAqIEByZXR1cm5zIHtSZWFkb25seTxUPn0gRnJvemVuIHZhbHVlLlxuICovXG5mdW5jdGlvbiBkZWVwRnJlZXplKHZhbHVlKSB7XG4gIGZvciAoY29uc3QgY2hpbGQgb2YgT2JqZWN0LnZhbHVlcyh2YWx1ZSkpIGlmIChjaGlsZCAmJiB0eXBlb2YgY2hpbGQgPT0gXCJvYmplY3RcIiAmJiAhT2JqZWN0LmlzRnJvemVuKGNoaWxkKSkgZGVlcEZyZWV6ZShjaGlsZClcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUodmFsdWUpXG59XG5cbi8qKlxuICogVGhyb3dzIGEgc3RhYmxlIGludmFsaWQtcmVnaXN0cnkgZGlhZ25vc3RpYy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRmFpbHVyZSBkZXRhaWwuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IEFsd2F5cyB0aHJvd3MuXG4gKi9cbmZ1bmN0aW9uIGludmFsaWRGYWNhZGUobWVzc2FnZSkge1xuICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlNURExJQl9GQUNBREVfSU5WQUxJRFwiLCBsYW5ndWFnZTogXCJzdGRsaWJcIiwgbWVzc2FnZX0pXG59XG5cbi8qKlxuICogVGhyb3dzIHdoZW4gcGFyc2VyIGV2aWRlbmNlIGRvZXMgbm90IG5hbWUgYSByZWdpc3RlcmVkIG5hdGl2ZSBtb2R1bGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFuZ3VhZ2UgLSBTb3VyY2UgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3Vua25vd259IG5hdGl2ZU1vZHVsZSAtIFVucHJvdmVkIG1vZHVsZSBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAqL1xuZnVuY3Rpb24gdW5wcm92ZWRJZGVudGl0eShsYW5ndWFnZSwgbmF0aXZlTW9kdWxlKSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNvZGU6IFwiU1RETElCX0ZBQ0FERV9JREVOVElUWV9VTlBST1ZFRFwiLFxuICAgIGxhbmd1YWdlOiBzdXBwb3J0ZWRMYW5ndWFnZXMuaGFzKGxhbmd1YWdlKSA/IGxhbmd1YWdlIDogXCJzdGRsaWJcIixcbiAgICBtZXNzYWdlOiBgTmF0aXZlIHN0YW5kYXJkLWxpYnJhcnkgbW9kdWxlICcke1N0cmluZyhuYXRpdmVNb2R1bGUpfScgaXMgbm90IGEgcmVnaXN0ZXJlZCAnJHtsYW5ndWFnZX0nIGZhY2FkZSBpZGVudGl0eS5gXG4gIH0pXG59XG5cbi8qKlxuICogVGhyb3dzIHdoZW4gYSBuYXRpdmUgbW9kdWxlIG1lbWJlciBpcyBvdXRzaWRlIGl0cyBwdWJsaWMgZmFjYWRlIHN1cmZhY2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFuZ3VhZ2UgLSBTb3VyY2UgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmF0aXZlTW9kdWxlIC0gRXhhY3QgbmF0aXZlIG1vZHVsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgLSBVbnN1cHBvcnRlZCBtZW1iZXIuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IEFsd2F5cyB0aHJvd3MuXG4gKi9cbmZ1bmN0aW9uIHVuc3VwcG9ydGVkTWVtYmVyKGxhbmd1YWdlLCBuYXRpdmVNb2R1bGUsIHN5bWJvbCkge1xuICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICBjb2RlOiBcIlNURExJQl9GQUNBREVfTUVNQkVSX1VOU1VQUE9SVEVEXCIsXG4gICAgbGFuZ3VhZ2UsXG4gICAgbWVzc2FnZTogYE5hdGl2ZSBzdGFuZGFyZC1saWJyYXJ5IHN5bWJvbCAnJHtuYXRpdmVNb2R1bGV9IyR7c3ltYm9sfScgaXMgb3V0c2lkZSB0aGUgcmVnaXN0ZXJlZCBmYWNhZGUgc3VyZmFjZS5gXG4gIH0pXG59XG5cbi8qKlxuICogVGhyb3dzIGZvciBhIG1hbGZvcm1lZCBmYWNhZGUgdmVyc2lvbiByYW5nZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSByYW5nZSAtIE1hbGZvcm1lZCByYW5nZS5cbiAqIEByZXR1cm5zIHtuZXZlcn0gQWx3YXlzIHRocm93cy5cbiAqL1xuZnVuY3Rpb24gZmFjYWRlVmVyc2lvbk1hbGZvcm1lZChsYW5ndWFnZSwgcmFuZ2UpIHtcbiAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgY29kZTogXCJTVERMSUJfRkFDQURFX1ZFUlNJT05fTUFMRk9STUVEXCIsIGxhbmd1YWdlLFxuICAgIG1lc3NhZ2U6IGBGYWNhZGUgdmVyc2lvbiByYW5nZSAnJHtyYW5nZX0nIGlzIG5vdCBjYW5vbmljYWwuYFxuICB9KVxufVxuXG4vKipcbiAqIFRocm93cyB3aGVuIG5vIHJlZ2lzdGVyZWQgZmFjYWRlIHZlcnNpb24gc2F0aXNmaWVzIGEgcmFuZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGFuZ3VhZ2UgLSBTb3VyY2UgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRlbnRpdHkgLSBGYWNhZGUgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7bmV2ZXJ9IEFsd2F5cyB0aHJvd3MuXG4gKi9cbmZ1bmN0aW9uIGZhY2FkZVZlcnNpb25JbmNvbXBhdGlibGUobGFuZ3VhZ2UsIGlkZW50aXR5KSB7XG4gIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNvZGU6IFwiU1RETElCX0ZBQ0FERV9WRVJTSU9OX0lOQ09NUEFUSUJMRVwiLCBsYW5ndWFnZSxcbiAgICBtZXNzYWdlOiBgTm8gcmVnaXN0ZXJlZCB2ZXJzaW9uIG9mIGZhY2FkZSAnJHtpZGVudGl0eX0nIHNhdGlzZmllcyB0aGUgcmVxdWlyZWQgY29tcGF0aWJpbGl0eSByYW5nZS5gXG4gIH0pXG59XG5cbmV4cG9ydCBjb25zdCBzdGRsaWJGYWNhZGVSZWdpc3RyeSA9IGNyZWF0ZVN0ZGxpYkZhY2FkZVJlZ2lzdHJ5KClcbiJdfQ==
|