semantifold 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -15
- package/build/index.d.ts +52 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +60 -8
- package/build/src/artifact-path.d.ts +23 -1
- package/build/src/artifact-path.d.ts.map +1 -1
- package/build/src/artifact-path.js +45 -3
- package/build/src/artifacts.d.ts.map +1 -1
- package/build/src/artifacts.js +66 -1
- package/build/src/backends/android.d.ts +49 -0
- package/build/src/backends/android.d.ts.map +1 -0
- package/build/src/backends/android.js +1274 -0
- package/build/src/backends/c-validation.d.ts.map +1 -1
- package/build/src/backends/c-validation.js +7 -3
- package/build/src/backends/cpp-validation.d.ts.map +1 -1
- package/build/src/backends/cpp-validation.js +7 -3
- package/build/src/backends/csharp.js +7 -1
- package/build/src/backends/dart-runtime.d.ts +2 -0
- package/build/src/backends/dart-runtime.d.ts.map +1 -0
- package/build/src/backends/dart-runtime.js +41 -0
- package/build/src/backends/dart.d.ts +20 -0
- package/build/src/backends/dart.d.ts.map +1 -0
- package/build/src/backends/dart.js +321 -0
- package/build/src/backends/effects.d.ts +60 -0
- package/build/src/backends/effects.d.ts.map +1 -0
- package/build/src/backends/effects.js +746 -0
- package/build/src/backends/go.js +18 -4
- package/build/src/backends/identifiers.d.ts +36 -4
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +160 -10
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +27 -4
- package/build/src/backends/ios.d.ts +68 -0
- package/build/src/backends/ios.d.ts.map +1 -0
- package/build/src/backends/ios.js +1503 -0
- package/build/src/backends/java.d.ts.map +1 -1
- package/build/src/backends/java.js +429 -36
- package/build/src/backends/javascript.d.ts +6 -0
- package/build/src/backends/javascript.d.ts.map +1 -1
- package/build/src/backends/javascript.js +380 -24
- package/build/src/backends/kotlin-runtime.d.ts +3 -0
- package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
- package/build/src/backends/kotlin-runtime.js +29 -0
- package/build/src/backends/kotlin.d.ts +33 -0
- package/build/src/backends/kotlin.d.ts.map +1 -0
- package/build/src/backends/kotlin.js +138 -0
- package/build/src/backends/native-validation.d.ts +2 -2
- package/build/src/backends/native-validation.d.ts.map +1 -1
- package/build/src/backends/native-validation.js +2 -2
- package/build/src/backends/ordered-expressions.d.ts.map +1 -1
- package/build/src/backends/ordered-expressions.js +39 -7
- package/build/src/backends/php-stdlib-support.d.ts +19 -0
- package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
- package/build/src/backends/php-stdlib-support.js +227 -0
- package/build/src/backends/php.d.ts.map +1 -1
- package/build/src/backends/php.js +448 -33
- package/build/src/backends/program.d.ts +83 -0
- package/build/src/backends/program.d.ts.map +1 -0
- package/build/src/backends/program.js +1309 -0
- package/build/src/backends/python.js +7 -1
- package/build/src/backends/ruby.d.ts.map +1 -1
- package/build/src/backends/ruby.js +310 -24
- package/build/src/backends/rust-runtime.d.ts +7 -0
- package/build/src/backends/rust-runtime.d.ts.map +1 -0
- package/build/src/backends/rust-runtime.js +32 -0
- package/build/src/backends/rust-validation.d.ts +9 -0
- package/build/src/backends/rust-validation.d.ts.map +1 -0
- package/build/src/backends/rust-validation.js +78 -0
- package/build/src/backends/rust.d.ts +24 -0
- package/build/src/backends/rust.d.ts.map +1 -0
- package/build/src/backends/rust.js +344 -0
- package/build/src/backends/scalars.d.ts +14 -6
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +167 -17
- package/build/src/backends/shared.d.ts +23 -4
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +2174 -62
- package/build/src/backends/stdlib-support.d.ts +14 -0
- package/build/src/backends/stdlib-support.d.ts.map +1 -0
- package/build/src/backends/stdlib-support.js +237 -0
- package/build/src/backends/swift-runtime.d.ts +3 -0
- package/build/src/backends/swift-runtime.d.ts.map +1 -0
- package/build/src/backends/swift-runtime.js +14 -0
- package/build/src/backends/swift.d.ts +8 -0
- package/build/src/backends/swift.d.ts.map +1 -0
- package/build/src/backends/swift.js +127 -0
- package/build/src/backends/typescript.d.ts.map +1 -1
- package/build/src/backends/typescript.js +344 -24
- package/build/src/backends/wasm.d.ts +43 -0
- package/build/src/backends/wasm.d.ts.map +1 -0
- package/build/src/backends/wasm.js +2164 -0
- package/build/src/backends/writer.d.ts +255 -4
- package/build/src/backends/writer.d.ts.map +1 -1
- package/build/src/backends/writer.js +491 -3
- package/build/src/diagnostic.d.ts +4 -3
- package/build/src/diagnostic.d.ts.map +1 -1
- package/build/src/diagnostic.js +5 -3
- package/build/src/frontends/c.d.ts.map +1 -1
- package/build/src/frontends/c.js +5 -3
- package/build/src/frontends/cpp.d.ts.map +1 -1
- package/build/src/frontends/cpp.js +5 -3
- package/build/src/frontends/csharp.d.ts.map +1 -1
- package/build/src/frontends/csharp.js +7 -3
- package/build/src/frontends/dart.d.ts +10 -0
- package/build/src/frontends/dart.d.ts.map +1 -0
- package/build/src/frontends/dart.js +913 -0
- package/build/src/frontends/index.d.ts +3 -1
- package/build/src/frontends/index.d.ts.map +1 -1
- package/build/src/frontends/index.js +15 -5
- package/build/src/frontends/java.d.ts +110 -1
- package/build/src/frontends/java.d.ts.map +1 -1
- package/build/src/frontends/java.js +1725 -70
- package/build/src/frontends/javascript-typescript.d.ts +69 -1
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
- package/build/src/frontends/javascript-typescript.js +1825 -93
- package/build/src/frontends/kotlin.d.ts +10 -0
- package/build/src/frontends/kotlin.d.ts.map +1 -0
- package/build/src/frontends/kotlin.js +685 -0
- package/build/src/frontends/php.d.ts +118 -1
- package/build/src/frontends/php.d.ts.map +1 -1
- package/build/src/frontends/php.js +1583 -76
- package/build/src/frontends/program.d.ts +74 -0
- package/build/src/frontends/program.d.ts.map +1 -0
- package/build/src/frontends/program.js +989 -0
- package/build/src/frontends/ruby.d.ts +68 -1
- package/build/src/frontends/ruby.d.ts.map +1 -1
- package/build/src/frontends/ruby.js +1446 -101
- package/build/src/frontends/rust-parser.d.ts +11 -0
- package/build/src/frontends/rust-parser.d.ts.map +1 -0
- package/build/src/frontends/rust-parser.js +15 -0
- package/build/src/frontends/rust.d.ts +14 -0
- package/build/src/frontends/rust.d.ts.map +1 -0
- package/build/src/frontends/rust.js +715 -0
- package/build/src/frontends/scalars.d.ts +10 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +28 -2
- package/build/src/frontends/swift.d.ts +10 -0
- package/build/src/frontends/swift.d.ts.map +1 -0
- package/build/src/frontends/swift.js +860 -0
- package/build/src/frontends/types.d.ts +186 -0
- package/build/src/frontends/types.d.ts.map +1 -0
- package/build/src/frontends/types.js +634 -0
- package/build/src/language-registry.d.ts +46 -4
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +177 -13
- package/build/src/mapping.d.ts +2 -2
- package/build/src/mapping.d.ts.map +1 -1
- package/build/src/mapping.js +31 -10
- package/build/src/semantic/capabilities.d.ts +66 -0
- package/build/src/semantic/capabilities.d.ts.map +1 -0
- package/build/src/semantic/capabilities.js +649 -0
- package/build/src/semantic/effects.d.ts +26 -0
- package/build/src/semantic/effects.d.ts.map +1 -0
- package/build/src/semantic/effects.js +764 -0
- package/build/src/semantic/generics.d.ts +23 -0
- package/build/src/semantic/generics.d.ts.map +1 -0
- package/build/src/semantic/generics.js +61 -0
- package/build/src/semantic/lifetime.d.ts +37 -0
- package/build/src/semantic/lifetime.d.ts.map +1 -0
- package/build/src/semantic/lifetime.js +527 -0
- package/build/src/semantic/provenance.d.ts +9 -2
- package/build/src/semantic/provenance.d.ts.map +1 -1
- package/build/src/semantic/provenance.js +462 -20
- package/build/src/semantic/scalars.d.ts +11 -0
- package/build/src/semantic/scalars.d.ts.map +1 -1
- package/build/src/semantic/scalars.js +16 -1
- package/build/src/semantic/stdlib.d.ts +254 -0
- package/build/src/semantic/stdlib.d.ts.map +1 -0
- package/build/src/semantic/stdlib.js +880 -0
- package/build/src/semantic/types.d.ts +3108 -178
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +730 -15
- package/build/src/semantic/validate.d.ts +85 -5
- package/build/src/semantic/validate.d.ts.map +1 -1
- package/build/src/semantic/validate.js +2576 -98
- package/build/src/stdlib-facades.d.ts +304 -0
- package/build/src/stdlib-facades.d.ts.map +1 -0
- package/build/src/stdlib-facades.js +1167 -0
- package/build/src/stdlib-negotiation.d.ts +69 -0
- package/build/src/stdlib-negotiation.d.ts.map +1 -0
- package/build/src/stdlib-negotiation.js +403 -0
- package/build/src/stdlib-providers.d.ts +72 -0
- package/build/src/stdlib-providers.d.ts.map +1 -0
- package/build/src/stdlib-providers.js +339 -0
- package/build/src/toolchains.d.ts +55 -1
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +15 -4
- package/docs/android.md +79 -0
- package/docs/architecture.md +47 -13
- package/docs/dart.md +60 -0
- package/docs/goals.md +3 -3
- package/docs/ios.md +121 -0
- package/docs/kotlin.md +42 -0
- package/docs/language-support.md +238 -26
- package/docs/multi-file-modules.md +52 -0
- package/docs/parser-qualification.md +121 -8
- package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
- package/docs/rust.md +88 -0
- package/docs/source-maps.md +17 -7
- package/docs/specification.md +5 -0
- package/docs/standard-library-portability.md +39 -8
- package/docs/swift.md +44 -0
- package/docs/testing.md +381 -4
- package/docs/webassembly.md +52 -0
- package/index.js +66 -8
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
- package/package.json +5 -2
- package/src/artifact-path.js +47 -2
- package/src/artifacts.js +67 -0
- package/src/backends/android.js +1370 -0
- package/src/backends/c-validation.js +6 -1
- package/src/backends/cpp-validation.js +6 -1
- package/src/backends/csharp.js +3 -0
- package/src/backends/dart-runtime.js +41 -0
- package/src/backends/dart.js +326 -0
- package/src/backends/effects.js +705 -0
- package/src/backends/go.js +14 -2
- package/src/backends/identifiers.js +166 -9
- package/src/backends/index.js +27 -2
- package/src/backends/ios.js +1612 -0
- package/src/backends/java.js +454 -36
- package/src/backends/javascript.js +389 -23
- package/src/backends/kotlin-runtime.js +29 -0
- package/src/backends/kotlin.js +144 -0
- package/src/backends/native-validation.js +1 -1
- package/src/backends/ordered-expressions.js +40 -6
- package/src/backends/php-stdlib-support.js +239 -0
- package/src/backends/php.js +469 -32
- package/src/backends/program.js +1408 -0
- package/src/backends/python.js +3 -0
- package/src/backends/ruby.js +326 -23
- package/src/backends/rust-runtime.js +34 -0
- package/src/backends/rust-validation.js +75 -0
- package/src/backends/rust.js +335 -0
- package/src/backends/scalars.js +141 -16
- package/src/backends/shared.js +2314 -115
- package/src/backends/stdlib-support.js +234 -0
- package/src/backends/swift-runtime.js +14 -0
- package/src/backends/swift.js +132 -0
- package/src/backends/typescript.js +349 -23
- package/src/backends/wasm.js +2208 -0
- package/src/backends/writer.js +545 -2
- package/src/diagnostic.js +4 -2
- package/src/frontends/c.js +4 -2
- package/src/frontends/cpp.js +4 -2
- package/src/frontends/csharp.js +4 -2
- package/src/frontends/dart.js +963 -0
- package/src/frontends/index.js +14 -4
- package/src/frontends/java.js +1977 -69
- package/src/frontends/javascript-typescript.js +2046 -102
- package/src/frontends/kotlin.js +713 -0
- package/src/frontends/php.js +1725 -79
- package/src/frontends/program.js +1062 -0
- package/src/frontends/ruby.js +1624 -98
- package/src/frontends/rust-parser.js +18 -0
- package/src/frontends/rust.js +714 -0
- package/src/frontends/scalars.js +31 -1
- package/src/frontends/swift.js +893 -0
- package/src/frontends/types.js +750 -0
- package/src/language-registry.js +182 -12
- package/src/mapping.js +33 -9
- package/src/semantic/capabilities.js +671 -0
- package/src/semantic/effects.js +737 -0
- package/src/semantic/generics.js +58 -0
- package/src/semantic/lifetime.js +517 -0
- package/src/semantic/provenance.js +412 -19
- package/src/semantic/scalars.js +17 -0
- package/src/semantic/stdlib.js +921 -0
- package/src/semantic/types.js +810 -14
- package/src/semantic/validate.js +2934 -209
- package/src/stdlib-facades.js +1211 -0
- package/src/stdlib-negotiation.js +446 -0
- package/src/stdlib-providers.js +377 -0
- package/src/toolchains.js +16 -3
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
import { AndNode, CallNode, DefNode, ElseNode, FalseNode, IfNode, IntegerNode, InterpolatedStringNode, LocalVariableReadNode, LocalVariableWriteNode, OrNode, ParenthesesNode, ProgramNode, RequiredParameterNode, ReturnNode, StatementsNode, StringNode, TrueNode, loadPrism } from "@ruby/prism";
|
|
2
|
+
import { AndNode, ArrayNode, AssocNode, BlockNode, BlockParametersNode, BeginNode, BreakNode, CallNode, ClassNode, ConstantPathNode, ConstantReadNode, DefNode, ElseNode, FalseNode, HashNode, IfNode, IntegerNode, InstanceVariableWriteNode, InstanceVariableReadNode, InterpolatedStringNode, LocalVariableReadNode, LocalVariableTargetNode, LocalVariableWriteNode, ModuleNode, NextNode, NilNode, OrNode, ParenthesesNode, ProgramNode, RequiredParameterNode, RedoNode, RescueNode, ReturnNode, RetryNode, SelfNode, StatementsNode, StringNode, SymbolNode, TrueNode, UnlessNode, WhileNode, loadPrism } from "@ruby/prism";
|
|
3
3
|
import { missingType, SemantifoldDiagnostic, unsupportedSyntax } from "../diagnostic.js";
|
|
4
|
+
import { blockReferencesProtectedEntry } from "../semantic/effects.js";
|
|
4
5
|
import { locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset } from "../semantic/location.js";
|
|
5
6
|
import { withAdaptedOperation } from "../semantic/operators.js";
|
|
6
7
|
import { withParserRanges } from "../semantic/provenance.js";
|
|
7
8
|
import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
|
|
8
|
-
import {
|
|
9
|
+
import { isTask034ResourceProbe } from "../semantic/capabilities.js";
|
|
10
|
+
import { hasExactEffectSupport } from "../backends/effects.js";
|
|
11
|
+
import { requireSourceReturnType } from "./scalars.js";
|
|
12
|
+
import { capabilityFunctionSignatures, documentedValueType, instantiatedRecordFieldType, iterationBindingType, iterationOperandType, knownCallReturnType, orderedMapTypeFromMap, preservesGenericOptionalEvidence, recordType, referenceType, sameValueType } from "./types.js";
|
|
9
13
|
const parsePrism = await loadPrism();
|
|
14
|
+
const referenceMethodHooks = new Set([
|
|
15
|
+
"__send__", "extend", "fetch", "instance_eval", "instance_exec", "method", "method_missing", "public_send",
|
|
16
|
+
"respond_to_missing?", "send", "singleton_class", "size"
|
|
17
|
+
]);
|
|
18
|
+
/** @typedef {{name: string, nameLocation: import("../semantic/types.js").SourceLocation, parameters: import("../semantic/types.js").Parameter[], returnType: import("../semantic/types.js").SemanticFunctionReturnType, typeParameters?: import("../semantic/types.js").TypeParameter[], location: import("../semantic/types.js").SourceLocation}} RubyFunctionSignature */
|
|
19
|
+
/** @typedef {{bindings: Map<string, import("../semantic/types.js").SemanticBindingType>, classes: Map<string, import("../semantic/types.js").ClassDeclaration>, currentClass?: import("../semantic/types.js").ClassDeclaration, errorNames: Map<string, import("../semantic/types.js").ErrorDeclaration>, errors: Map<string, import("../semantic/types.js").ErrorDeclaration>, functions: Map<string, RubyFunctionSignature>, orderedMapDeclarations?: Set<object>, records: Map<string, import("../semantic/types.js").RecordDeclaration>, recordNames: Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>, loopDepth?: number, returnType?: import("../semantic/types.js").SemanticFunctionReturnType, typeParameters?: Map<string, import("../semantic/types.js").TypeParameter>}} RubyConversionContext */
|
|
10
20
|
const rubyBinaryOperations = new Map([
|
|
11
21
|
["+", "Add"],
|
|
12
22
|
["-", "Subtract"],
|
|
@@ -53,15 +63,58 @@ function slicePrismSource(source, startOffset, endOffset) {
|
|
|
53
63
|
* @param {import("@ruby/prism").Node} node - Prism node.
|
|
54
64
|
* @param {string} filename - Source filename.
|
|
55
65
|
* @param {string} source - Complete source.
|
|
66
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
67
|
+
* @param {import("../semantic/types.js").SemanticValueType} [expectedType] - Explicit contextual value type.
|
|
68
|
+
* @param {boolean} [preserveOptional] - Whether an optional identifier remains wrapped.
|
|
56
69
|
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
57
70
|
*/
|
|
58
|
-
function convertExpression(node, filename, source) {
|
|
71
|
+
function convertExpression(node, filename, source, context, expectedType, preserveOptional = false) {
|
|
59
72
|
const location = nodeLocation(node, filename, source);
|
|
73
|
+
if (expectedType?.kind == "OptionalType") {
|
|
74
|
+
if (node instanceof NilNode) {
|
|
75
|
+
return withParserRanges({ kind: /** @type {const} */ ("OptionalNone"), location }, { absence: location });
|
|
76
|
+
}
|
|
77
|
+
if (knownExpressionType(node, context)?.kind == "OptionalType") {
|
|
78
|
+
return convertExpression(node, filename, source, context, undefined, true);
|
|
79
|
+
}
|
|
80
|
+
return withParserRanges({
|
|
81
|
+
kind: /** @type {const} */ ("OptionalSome"),
|
|
82
|
+
location,
|
|
83
|
+
value: convertExpression(node, filename, source, context, expectedType.valueType)
|
|
84
|
+
}, { some: location });
|
|
85
|
+
}
|
|
86
|
+
if (node instanceof NilNode)
|
|
87
|
+
return unsupportedSyntax("ruby", "nil outside an explicit optional context", location);
|
|
88
|
+
if (node instanceof CallNode && node.block) {
|
|
89
|
+
return unsupportedSyntax("ruby", "call block", nodeLocation(node.block, filename, source));
|
|
90
|
+
}
|
|
91
|
+
if (node instanceof CallNode && node.callOperatorLoc && slicePrismSource(source, node.callOperatorLoc.startOffset, node.callOperatorLoc.startOffset + node.callOperatorLoc.length) == "&.") {
|
|
92
|
+
return unsupportedSyntax("ruby", node.constructor.name, location);
|
|
93
|
+
}
|
|
60
94
|
if (node instanceof ParenthesesNode && node.body instanceof StatementsNode && node.body.body.length == 1) {
|
|
61
|
-
return convertExpression(node.body.body[0], filename, source);
|
|
95
|
+
return convertExpression(node.body.body[0], filename, source, context, expectedType, preserveOptional);
|
|
62
96
|
}
|
|
63
97
|
if (node instanceof LocalVariableReadNode) {
|
|
64
|
-
|
|
98
|
+
const identifier = withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name: node.name }, { name: location });
|
|
99
|
+
if (!preserveOptional && context.bindings.get(node.name)?.kind == "OptionalType") {
|
|
100
|
+
return withParserRanges({ kind: /** @type {const} */ ("OptionalUnwrap"), location, operand: identifier }, { unwrap: location });
|
|
101
|
+
}
|
|
102
|
+
return identifier;
|
|
103
|
+
}
|
|
104
|
+
if (node instanceof SelfNode) {
|
|
105
|
+
if (!context.currentClass)
|
|
106
|
+
return unsupportedSyntax("ruby", "self outside a reference class", location);
|
|
107
|
+
return withParserRanges({ classId: /** @type {string} */ (context.currentClass.id), kind: /** @type {const} */ ("ReceiverExpression"),
|
|
108
|
+
location }, { receiver: location });
|
|
109
|
+
}
|
|
110
|
+
if (node instanceof InstanceVariableReadNode) {
|
|
111
|
+
const field = context.currentClass?.fields.find((candidate) => `@${candidate.name}` == node.name);
|
|
112
|
+
if (!field || !context.currentClass)
|
|
113
|
+
return unsupportedSyntax("ruby", "private instance field outside its declaring class", location);
|
|
114
|
+
const receiver = withParserRanges({ classId: /** @type {string} */ (context.currentClass.id),
|
|
115
|
+
kind: /** @type {const} */ ("ReceiverExpression"), location }, { receiver: location });
|
|
116
|
+
return withParserRanges({ field: /** @type {string} */ (field.id), kind: /** @type {const} */ ("PrivateFieldRead"),
|
|
117
|
+
location, receiver }, { member: location });
|
|
65
118
|
}
|
|
66
119
|
if (node instanceof IntegerNode) {
|
|
67
120
|
if (!Number.isSafeInteger(node.value))
|
|
@@ -81,6 +134,95 @@ function convertExpression(node, filename, source) {
|
|
|
81
134
|
}
|
|
82
135
|
if (node instanceof InterpolatedStringNode)
|
|
83
136
|
return unsupportedSyntax("ruby", "interpolated string", location);
|
|
137
|
+
if (node instanceof OrNode && node.left instanceof LocalVariableReadNode &&
|
|
138
|
+
context.bindings.get(node.left.name)?.kind == "OptionalType") {
|
|
139
|
+
return unsupportedSyntax("ruby", "optional default with ||", prismLocation(node.operatorLoc, filename, source));
|
|
140
|
+
}
|
|
141
|
+
if (exactNilTest(node, source)) {
|
|
142
|
+
const call = /** @type {CallNode} */ (node);
|
|
143
|
+
const receiver = /** @type {LocalVariableReadNode} */ (call.receiver);
|
|
144
|
+
const operand = /** @type {import("../semantic/types.js").IdentifierExpression} */ (convertExpression(receiver, filename, source, context, undefined, true));
|
|
145
|
+
const present = withParserRanges({ kind: /** @type {const} */ ("OptionalIsPresent"), location, operand }, {
|
|
146
|
+
operator: prismLocation(call.messageLoc ?? call.location, filename, source)
|
|
147
|
+
});
|
|
148
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
149
|
+
kind: "UnaryExpression",
|
|
150
|
+
location,
|
|
151
|
+
operand: present
|
|
152
|
+
}, { operator: prismLocation(call.messageLoc ?? call.location, filename, source) }), "Not");
|
|
153
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
154
|
+
}
|
|
155
|
+
if (node instanceof ArrayNode) {
|
|
156
|
+
if (!node.openingLoc || !node.closingLoc)
|
|
157
|
+
return unsupportedSyntax("ruby", "special array literal", location);
|
|
158
|
+
if (node.isContainsSplat()) {
|
|
159
|
+
const splat = node.elements.find((element) => element.constructor.name == "SplatNode");
|
|
160
|
+
return unsupportedSyntax("ruby", "array splat", splat ? nodeLocation(splat, filename, source) : location);
|
|
161
|
+
}
|
|
162
|
+
const elementType = expectedType?.kind == "ListType" ? expectedType.elementType : undefined;
|
|
163
|
+
return withParserRanges({
|
|
164
|
+
elements: node.elements.map((element) => convertExpression(element, filename, source, context, elementType)),
|
|
165
|
+
kind: /** @type {const} */ ("ListLiteral"),
|
|
166
|
+
location
|
|
167
|
+
}, {
|
|
168
|
+
close: prismLocation(node.closingLoc, filename, source),
|
|
169
|
+
open: prismLocation(node.openingLoc, filename, source)
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (node instanceof HashNode) {
|
|
173
|
+
const valueType = expectedType?.kind == "MapType" || expectedType?.kind == "OrderedMapType"
|
|
174
|
+
? expectedType.valueType : undefined;
|
|
175
|
+
const entries = node.elements.map((element) => {
|
|
176
|
+
if (!(element instanceof AssocNode) || !element.operatorLoc ||
|
|
177
|
+
slicePrismSource(source, element.operatorLoc.startOffset, element.operatorLoc.startOffset + element.operatorLoc.length) != "=>") {
|
|
178
|
+
return unsupportedSyntax("ruby", "hash entry", nodeLocation(element, filename, source));
|
|
179
|
+
}
|
|
180
|
+
if (!(element.key instanceof StringNode)) {
|
|
181
|
+
return unsupportedSyntax("ruby", "map key other than a string literal", nodeLocation(element.key, filename, source));
|
|
182
|
+
}
|
|
183
|
+
const key = convertExpression(element.key, filename, source, context);
|
|
184
|
+
return withParserRanges({
|
|
185
|
+
key: /** @type {import("../semantic/types.js").StringLiteral} */ (key),
|
|
186
|
+
kind: /** @type {const} */ ("MapEntry"),
|
|
187
|
+
location: nodeLocation(element, filename, source),
|
|
188
|
+
value: convertExpression(element.value, filename, source, context, valueType)
|
|
189
|
+
}, { operator: prismLocation(element.operatorLoc, filename, source) });
|
|
190
|
+
});
|
|
191
|
+
return withParserRanges({
|
|
192
|
+
entries,
|
|
193
|
+
kind: expectedType?.kind == "OrderedMapType"
|
|
194
|
+
? /** @type {const} */ ("OrderedMapLiteral")
|
|
195
|
+
: /** @type {const} */ ("MapLiteral"),
|
|
196
|
+
location
|
|
197
|
+
}, {
|
|
198
|
+
close: prismLocation(node.closingLoc, filename, source),
|
|
199
|
+
open: prismLocation(node.openingLoc, filename, source)
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (node instanceof CallNode && (node.receiver instanceof ConstantReadNode || node.receiver instanceof ConstantPathNode) && node.name == "new" &&
|
|
203
|
+
node.callOperatorLoc && !node.block) {
|
|
204
|
+
const recordName = constantPathName(node.receiver);
|
|
205
|
+
const declaration = context.recordNames.get(recordName);
|
|
206
|
+
if (!declaration)
|
|
207
|
+
return unsupportedSyntax("ruby", "construction of a non-record class", nodeLocation(node.receiver, filename, source));
|
|
208
|
+
if (declaration.kind == "ClassDeclaration") {
|
|
209
|
+
return withParserRanges({ arguments: (node.arguments_?.arguments_ ?? []).map((argument, index) => convertExpression(argument, filename, source, context, declaration.constructor.parameters[index]?.type)),
|
|
210
|
+
kind: /** @type {const} */ ("ReferenceConstruction"), location,
|
|
211
|
+
reference: referenceType(/** @type {string} */ (declaration.id), nodeLocation(node.receiver, filename, source)) }, { class: nodeLocation(node.receiver, filename, source) });
|
|
212
|
+
}
|
|
213
|
+
if (declaration.kind == "EffectResourceDeclaration") {
|
|
214
|
+
return unsupportedSyntax("ruby", "owned resource construction", nodeLocation(node.receiver, filename, source));
|
|
215
|
+
}
|
|
216
|
+
const typeArguments = expectedType?.kind == "RecordType" && expectedType.declarationId == declaration.id
|
|
217
|
+
? expectedType.arguments
|
|
218
|
+
: undefined;
|
|
219
|
+
return withParserRanges({
|
|
220
|
+
arguments: (node.arguments_?.arguments_ ?? []).map((argument, index) => convertExpression(argument, filename, source, context, instantiatedRecordFieldType(declaration, typeArguments, index))),
|
|
221
|
+
kind: /** @type {const} */ ("RecordConstruction"),
|
|
222
|
+
location,
|
|
223
|
+
record: recordType(/** @type {string} */ (declaration.id), nodeLocation(node.receiver, filename, source), typeArguments)
|
|
224
|
+
}, { record: nodeLocation(node.receiver, filename, source) });
|
|
225
|
+
}
|
|
84
226
|
if (node instanceof CallNode && node.receiver && node.name == "!") {
|
|
85
227
|
const operatorLocation = prismLocation(node.messageLoc ?? node.location, filename, source);
|
|
86
228
|
if (node.callOperatorLoc)
|
|
@@ -90,10 +232,14 @@ function convertExpression(node, filename, source) {
|
|
|
90
232
|
}
|
|
91
233
|
if (node.arguments_)
|
|
92
234
|
return unsupportedSyntax("ruby", "boolean not argument list", operatorLocation);
|
|
235
|
+
const operand = convertExpression(node.receiver, filename, source, context);
|
|
236
|
+
if (operand.kind == "UnaryExpression" && operand.operand.kind == "OptionalIsPresent") {
|
|
237
|
+
return operand.operand;
|
|
238
|
+
}
|
|
93
239
|
const semantic = withAdaptedOperation(withParserRanges({
|
|
94
240
|
kind: "UnaryExpression",
|
|
95
241
|
location,
|
|
96
|
-
operand
|
|
242
|
+
operand
|
|
97
243
|
}, { operator: operatorLocation }), "Not");
|
|
98
244
|
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
99
245
|
}
|
|
@@ -106,7 +252,7 @@ function convertExpression(node, filename, source) {
|
|
|
106
252
|
const semantic = withAdaptedOperation(withParserRanges({
|
|
107
253
|
kind: "UnaryExpression",
|
|
108
254
|
location,
|
|
109
|
-
operand: convertExpression(node.receiver, filename, source)
|
|
255
|
+
operand: convertExpression(node.receiver, filename, source, context)
|
|
110
256
|
}, { operator: operatorLocation }), "Negate");
|
|
111
257
|
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
112
258
|
}
|
|
@@ -118,9 +264,9 @@ function convertExpression(node, filename, source) {
|
|
|
118
264
|
}
|
|
119
265
|
const semantic = withAdaptedOperation(withParserRanges({
|
|
120
266
|
kind: "BinaryExpression",
|
|
121
|
-
left: convertExpression(node.left, filename, source),
|
|
267
|
+
left: convertExpression(node.left, filename, source, context),
|
|
122
268
|
location,
|
|
123
|
-
right: convertExpression(node.right, filename, source)
|
|
269
|
+
right: convertExpression(node.right, filename, source, context)
|
|
124
270
|
}, { operator: operatorLocation }), node instanceof AndNode ? "And" : "Or");
|
|
125
271
|
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
126
272
|
}
|
|
@@ -131,36 +277,210 @@ function convertExpression(node, filename, source) {
|
|
|
131
277
|
if (node instanceof CallNode && node.receiver && rubyBinaryOperations.has(node.name) && node.arguments_?.arguments_.length == 1) {
|
|
132
278
|
const semantic = withAdaptedOperation(withParserRanges({
|
|
133
279
|
kind: "BinaryExpression",
|
|
134
|
-
left: convertExpression(node.receiver, filename, source),
|
|
280
|
+
left: convertExpression(node.receiver, filename, source, context),
|
|
135
281
|
location,
|
|
136
|
-
right: convertExpression(node.arguments_.arguments_[0], filename, source)
|
|
282
|
+
right: convertExpression(node.arguments_.arguments_[0], filename, source, context)
|
|
137
283
|
}, { operator: prismLocation(node.messageLoc ?? node.location, filename, source) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (rubyBinaryOperations.get(node.name)));
|
|
138
284
|
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
139
285
|
}
|
|
286
|
+
if (node instanceof CallNode && node.receiver && node.name == "[]" && node.arguments_?.arguments_.length == 1 &&
|
|
287
|
+
!node.callOperatorLoc && !node.block) {
|
|
288
|
+
return withParserRanges({
|
|
289
|
+
collection: convertExpression(node.receiver, filename, source, context),
|
|
290
|
+
index: convertExpression(node.arguments_.arguments_[0], filename, source, context),
|
|
291
|
+
kind: /** @type {const} */ ("ListIndexExpression"),
|
|
292
|
+
location,
|
|
293
|
+
totality: /** @type {const} */ ("proven")
|
|
294
|
+
}, { operator: prismLocation(node.openingLoc ?? node.messageLoc ?? node.location, filename, source) });
|
|
295
|
+
}
|
|
296
|
+
if (node instanceof CallNode && node.receiver && node.name == "fetch" && node.arguments_?.arguments_.length == 1 &&
|
|
297
|
+
node.callOperatorLoc && !node.block) {
|
|
298
|
+
return withParserRanges({
|
|
299
|
+
collection: convertExpression(node.receiver, filename, source, context),
|
|
300
|
+
key: convertExpression(node.arguments_.arguments_[0], filename, source, context),
|
|
301
|
+
kind: /** @type {const} */ ("MapLookupExpression"),
|
|
302
|
+
location,
|
|
303
|
+
totality: /** @type {const} */ ("fail-on-absence")
|
|
304
|
+
}, { operator: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
305
|
+
}
|
|
306
|
+
if (node instanceof CallNode && node.receiver instanceof ConstantReadNode && node.callOperatorLoc && !node.block) {
|
|
307
|
+
const callee = `${node.receiver.name}.${node.name}`;
|
|
308
|
+
const signature = context.functions.get(callee);
|
|
309
|
+
if (signature) {
|
|
310
|
+
return withParserRanges({
|
|
311
|
+
arguments: (node.arguments_?.arguments_ ?? []).map((argument, index) => convertExpression(argument, filename, source, context, signature.parameters[index]?.type, preservesGenericOptionalEvidence(signature, index))),
|
|
312
|
+
callee,
|
|
313
|
+
kind: /** @type {const} */ ("CallExpression"),
|
|
314
|
+
location
|
|
315
|
+
}, { callee: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (node instanceof CallNode && node.receiver && node.name == "size" && !node.arguments_ && node.callOperatorLoc && !node.block) {
|
|
319
|
+
const receiverType = knownValueExpressionType(node.receiver, context);
|
|
320
|
+
if (receiverType?.kind == "RecordType") {
|
|
321
|
+
return withParserRanges({
|
|
322
|
+
field: node.name,
|
|
323
|
+
kind: /** @type {const} */ ("MemberRead"),
|
|
324
|
+
location,
|
|
325
|
+
receiver: convertExpression(node.receiver, filename, source, context)
|
|
326
|
+
}, { member: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
327
|
+
}
|
|
328
|
+
return withParserRanges({
|
|
329
|
+
collection: convertExpression(node.receiver, filename, source, context),
|
|
330
|
+
kind: /** @type {const} */ ("CollectionSizeExpression"),
|
|
331
|
+
location
|
|
332
|
+
}, { operator: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
333
|
+
}
|
|
334
|
+
if (node instanceof CallNode && node.receiver instanceof LocalVariableReadNode && node.name == "message" &&
|
|
335
|
+
!node.arguments_ && node.callOperatorLoc && !node.block && context.bindings.get(node.receiver.name)?.kind == "ErrorType") {
|
|
336
|
+
const receiverLocation = nodeLocation(node.receiver, filename, source);
|
|
337
|
+
return withParserRanges({
|
|
338
|
+
kind: /** @type {const} */ ("ErrorMessageRead"),
|
|
339
|
+
location,
|
|
340
|
+
receiver: withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: receiverLocation, name: node.receiver.name }, {
|
|
341
|
+
name: receiverLocation
|
|
342
|
+
})
|
|
343
|
+
}, { member: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
344
|
+
}
|
|
345
|
+
if (node instanceof CallNode && node.receiver && node.callOperatorLoc && !node.block &&
|
|
346
|
+
knownValueExpressionType(node.receiver, context)?.kind == "ReferenceType") {
|
|
347
|
+
const receiverType = /** @type {import("../semantic/types.js").ReferenceType} */ (knownValueExpressionType(node.receiver, context));
|
|
348
|
+
const method = context.classes.get(receiverType.declarationId)?.methods.find((candidate) => candidate.name == node.name);
|
|
349
|
+
return withParserRanges({ arguments: (node.arguments_?.arguments_ ?? []).map((argument, index) => convertExpression(argument, filename, source, context, method?.parameters[index]?.type)),
|
|
350
|
+
kind: /** @type {const} */ ("MethodCallExpression"), location, method: method?.id ?? node.name,
|
|
351
|
+
receiver: convertExpression(node.receiver, filename, source, context) }, { member: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
352
|
+
}
|
|
353
|
+
if (node instanceof CallNode && node.receiver && node.callOperatorLoc && !node.arguments_ && !node.block) {
|
|
354
|
+
if (["send", "public_send", "__send__", "instance_variable_get", "method"].includes(node.name)) {
|
|
355
|
+
return unsupportedSyntax("ruby", "dynamic or reflective member access", prismLocation(node.messageLoc ?? node.location, filename, source));
|
|
356
|
+
}
|
|
357
|
+
return withParserRanges({
|
|
358
|
+
field: node.name,
|
|
359
|
+
kind: /** @type {const} */ ("MemberRead"),
|
|
360
|
+
location,
|
|
361
|
+
receiver: convertExpression(node.receiver, filename, source, context)
|
|
362
|
+
}, { member: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
363
|
+
}
|
|
140
364
|
if (node instanceof CallNode && !node.receiver) {
|
|
365
|
+
if (["send", "public_send", "__send__"].includes(node.name)) {
|
|
366
|
+
return unsupportedSyntax("ruby", "dynamic call", prismLocation(node.messageLoc ?? node.location, filename, source));
|
|
367
|
+
}
|
|
368
|
+
const signature = context.functions.get(node.name);
|
|
141
369
|
return withParserRanges({
|
|
142
|
-
arguments: (node.arguments_?.arguments_ ?? []).map((argument) => convertExpression(argument, filename, source)),
|
|
370
|
+
arguments: (node.arguments_?.arguments_ ?? []).map((argument, index) => convertExpression(argument, filename, source, context, signature?.parameters[index]?.type, preservesGenericOptionalEvidence(signature, index))),
|
|
143
371
|
callee: node.name,
|
|
144
372
|
kind: "CallExpression",
|
|
145
373
|
location
|
|
146
374
|
}, { callee: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
147
375
|
}
|
|
376
|
+
if (node instanceof CallNode && node.receiver) {
|
|
377
|
+
const unsupportedLocation = !node.callOperatorLoc && node.messageLoc && node.arguments_?.arguments_.length == 1
|
|
378
|
+
? prismLocation(node.messageLoc, filename, source)
|
|
379
|
+
: nodeLocation(node.receiver, filename, source);
|
|
380
|
+
return unsupportedSyntax("ruby", node.constructor.name, unsupportedLocation);
|
|
381
|
+
}
|
|
148
382
|
return unsupportedSyntax("ruby", node.constructor.name, location);
|
|
149
383
|
}
|
|
384
|
+
/**
|
|
385
|
+
* Resolves only result types established by explicit signatures and bindings.
|
|
386
|
+
* @param {import("@ruby/prism").Node} node - Parser-owned expression.
|
|
387
|
+
* @param {RubyConversionContext} context - Typed lexical context.
|
|
388
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType | import("../semantic/types.js").ErrorType | undefined} Known result type.
|
|
389
|
+
*/
|
|
390
|
+
function knownExpressionType(node, context) {
|
|
391
|
+
if (node instanceof ParenthesesNode && node.body instanceof StatementsNode && node.body.body.length == 1) {
|
|
392
|
+
return knownExpressionType(node.body.body[0], context);
|
|
393
|
+
}
|
|
394
|
+
if (node instanceof LocalVariableReadNode)
|
|
395
|
+
return context.bindings.get(node.name);
|
|
396
|
+
if (node instanceof CallNode && !node.receiver) {
|
|
397
|
+
const signature = context.functions.get(node.name);
|
|
398
|
+
if (signature)
|
|
399
|
+
return knownCallReturnType(signature, (node.arguments_?.arguments_ ?? []).map((argument) => knownExpressionType(argument, context)));
|
|
400
|
+
}
|
|
401
|
+
if (node instanceof CallNode && node.receiver instanceof ConstantReadNode) {
|
|
402
|
+
const signature = context.functions.get(`${node.receiver.name}.${node.name}`);
|
|
403
|
+
if (signature)
|
|
404
|
+
return knownCallReturnType(signature, (node.arguments_?.arguments_ ?? []).map((argument) => knownExpressionType(argument, context)));
|
|
405
|
+
}
|
|
406
|
+
if (node instanceof CallNode && node.receiver && node.name == "[]") {
|
|
407
|
+
const collectionType = knownValueExpressionType(node.receiver, context);
|
|
408
|
+
if (collectionType?.kind == "ListType")
|
|
409
|
+
return collectionType.elementType;
|
|
410
|
+
}
|
|
411
|
+
if (node instanceof CallNode && node.receiver && node.name == "fetch") {
|
|
412
|
+
const collectionType = knownValueExpressionType(node.receiver, context);
|
|
413
|
+
if (collectionType?.kind == "MapType" || collectionType?.kind == "OrderedMapType")
|
|
414
|
+
return collectionType.valueType;
|
|
415
|
+
}
|
|
416
|
+
if (node instanceof CallNode && (node.receiver instanceof ConstantReadNode || node.receiver instanceof ConstantPathNode) && node.name == "new") {
|
|
417
|
+
const declaration = context.recordNames.get(constantPathName(node.receiver));
|
|
418
|
+
if (declaration?.id)
|
|
419
|
+
return declaration.kind == "ClassDeclaration"
|
|
420
|
+
? { declarationId: declaration.id, kind: "ReferenceType" }
|
|
421
|
+
: { declarationId: declaration.id, kind: "RecordType" };
|
|
422
|
+
}
|
|
423
|
+
if (node instanceof SelfNode && context.currentClass?.id)
|
|
424
|
+
return { declarationId: context.currentClass.id, kind: "ReferenceType" };
|
|
425
|
+
if (node instanceof InstanceVariableReadNode && context.currentClass) {
|
|
426
|
+
return context.currentClass.fields.find((field) => `@${field.name}` == node.name)?.type;
|
|
427
|
+
}
|
|
428
|
+
if (node instanceof CallNode && node.receiver && node.callOperatorLoc) {
|
|
429
|
+
const receiver = knownValueExpressionType(node.receiver, context);
|
|
430
|
+
if (receiver?.kind == "ReferenceType") {
|
|
431
|
+
return context.classes.get(receiver.declarationId)?.methods.find((method) => method.name == node.name)?.returnType;
|
|
432
|
+
}
|
|
433
|
+
if (node.arguments_)
|
|
434
|
+
return undefined;
|
|
435
|
+
if (receiver?.kind != "RecordType")
|
|
436
|
+
return undefined;
|
|
437
|
+
const declaration = context.records.get(receiver.declarationId);
|
|
438
|
+
const index = declaration?.fields.findIndex((field) => field.name == node.name) ?? -1;
|
|
439
|
+
return declaration ? instantiatedRecordFieldType(declaration, receiver.arguments, index) : undefined;
|
|
440
|
+
}
|
|
441
|
+
return undefined;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Resolves the value type produced by the frontend's implicit optional-binding unwrap.
|
|
445
|
+
* Semantic validation separately proves that the unwrap occurs only on a present path.
|
|
446
|
+
* @param {import("@ruby/prism").Node} node - Parser-owned expression.
|
|
447
|
+
* @param {RubyConversionContext} context - Typed lexical context.
|
|
448
|
+
* @returns {import("../semantic/types.js").SemanticFunctionReturnType | import("../semantic/types.js").ErrorType | undefined} Converted value type.
|
|
449
|
+
*/
|
|
450
|
+
function knownValueExpressionType(node, context) {
|
|
451
|
+
if (node instanceof ParenthesesNode && node.body instanceof StatementsNode && node.body.body.length == 1) {
|
|
452
|
+
return knownValueExpressionType(node.body.body[0], context);
|
|
453
|
+
}
|
|
454
|
+
const type = knownExpressionType(node, context);
|
|
455
|
+
return node instanceof LocalVariableReadNode && type?.kind == "OptionalType" ? type.valueType : type;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Recognizes only the parser-backed `identifier.nil?` spelling used by Task 007.
|
|
459
|
+
* @param {import("@ruby/prism").Node} node - Candidate Prism expression.
|
|
460
|
+
* @param {string} source - Complete source.
|
|
461
|
+
* @returns {boolean} Whether this is one exact nil test.
|
|
462
|
+
*/
|
|
463
|
+
function exactNilTest(node, source) {
|
|
464
|
+
if (!(node instanceof CallNode) || !(node.receiver instanceof LocalVariableReadNode) ||
|
|
465
|
+
node.name != "nil?" || !node.callOperatorLoc || node.arguments_ || node.block)
|
|
466
|
+
return false;
|
|
467
|
+
return slicePrismSource(source, node.callOperatorLoc.startOffset, node.callOperatorLoc.startOffset + node.callOperatorLoc.length) == ".";
|
|
468
|
+
}
|
|
150
469
|
/**
|
|
151
470
|
* Converts one explicit Ruby return.
|
|
152
471
|
* @param {import("@ruby/prism").Node} node - Prism node.
|
|
153
472
|
* @param {string} filename - Source filename.
|
|
154
473
|
* @param {string} source - Complete source.
|
|
474
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
155
475
|
* @returns {import("../semantic/types.js").ReturnStatement} Semantic return.
|
|
156
476
|
*/
|
|
157
|
-
function convertReturn(node, filename, source) {
|
|
477
|
+
function convertReturn(node, filename, source, context) {
|
|
158
478
|
const location = nodeLocation(node, filename, source);
|
|
159
|
-
if (!(node instanceof ReturnNode) || node.arguments_?.arguments_.length
|
|
479
|
+
if (!(node instanceof ReturnNode) || (node.arguments_?.arguments_.length ?? 0) > 1) {
|
|
160
480
|
return unsupportedSyntax("ruby", node.constructor.name, location);
|
|
161
481
|
}
|
|
162
482
|
return {
|
|
163
|
-
expression: convertExpression(node.arguments_.arguments_[0], filename, source),
|
|
483
|
+
...(node.arguments_?.arguments_[0] ? { expression: convertExpression(node.arguments_.arguments_[0], filename, source, context, context.returnType?.kind == "TypeReference" && context.returnType.name == "void" ? undefined : context.returnType) } : {}),
|
|
164
484
|
kind: "ReturnStatement",
|
|
165
485
|
location
|
|
166
486
|
};
|
|
@@ -171,23 +491,61 @@ function convertReturn(node, filename, source) {
|
|
|
171
491
|
* @param {{location: import("@ruby/prism").Location}} node - Comment owner.
|
|
172
492
|
* @param {string} filename - Source filename.
|
|
173
493
|
* @param {string} source - Complete source.
|
|
174
|
-
* @
|
|
494
|
+
* @param {string} [ownerId] - Stable declaration identity.
|
|
495
|
+
* @returns {{parameters: Map<string, {location: import("../semantic/types.js").SourceLocation, sourceType: string}>, returnType: {location: import("../semantic/types.js").SourceLocation, sourceType: string} | undefined, typeParameters?: import("../semantic/types.js").TypeParameter[]}} Declared types.
|
|
175
496
|
*/
|
|
176
|
-
function typeComments(comments, node, filename, source) {
|
|
497
|
+
function typeComments(comments, node, filename, source, ownerId) {
|
|
177
498
|
const preceding = associatedComments(comments, node, source);
|
|
178
499
|
const parameterTypes = new Map();
|
|
179
500
|
/** @type {{location: import("../semantic/types.js").SourceLocation, sourceType: string} | undefined} */
|
|
180
501
|
let returnType;
|
|
502
|
+
/** @type {import("../semantic/types.js").TypeParameter[]} */
|
|
503
|
+
const typeParameters = [];
|
|
181
504
|
for (const comment of preceding) {
|
|
182
505
|
const words = commentTokens(comment, filename, source);
|
|
183
|
-
if (words[0]?.text == "@param" && words.length
|
|
184
|
-
parameterTypes.
|
|
506
|
+
if (words[0]?.text == "@param" && words.length >= 3) {
|
|
507
|
+
if (parameterTypes.has(words[1].text)) {
|
|
508
|
+
return unsupportedSyntax("ruby", "duplicate parameter annotation", words[1].location);
|
|
509
|
+
}
|
|
510
|
+
parameterTypes.set(words[1].text, joinedCommentToken(words, 2, source));
|
|
511
|
+
}
|
|
512
|
+
else if (words[0]?.text == "@return" && words.length >= 2) {
|
|
513
|
+
if (returnType)
|
|
514
|
+
return unsupportedSyntax("ruby", "duplicate return annotation", words[1].location);
|
|
515
|
+
returnType = joinedCommentToken(words, 1, source);
|
|
516
|
+
}
|
|
517
|
+
else if (words[0]?.text == "@template" && words.length == 2 && ownerId &&
|
|
518
|
+
/^[A-Za-z_][A-Za-z0-9_]*$/u.test(words[1].text)) {
|
|
519
|
+
typeParameters.push(withParserRanges({
|
|
520
|
+
id: `${ownerId}:type:${typeParameters.length}`,
|
|
521
|
+
kind: /** @type {const} */ ("TypeParameter"),
|
|
522
|
+
location: words[1].location,
|
|
523
|
+
name: words[1].text
|
|
524
|
+
}, { name: words[1].location }));
|
|
185
525
|
}
|
|
186
|
-
if (words[0]?.text
|
|
187
|
-
|
|
526
|
+
else if (words[0]?.text?.startsWith("@template")) {
|
|
527
|
+
return unsupportedSyntax("ruby", "bounded, defaulted, variant, or malformed type parameter", words[1]?.location ?? nodeLocation(node, filename, source));
|
|
528
|
+
}
|
|
529
|
+
else if (words[0]?.text?.startsWith("@param") || words[0]?.text?.startsWith("@return")) {
|
|
530
|
+
return unsupportedSyntax("ruby", "malformed function type annotation", nodeLocation(node, filename, source));
|
|
188
531
|
}
|
|
189
532
|
}
|
|
190
|
-
return { parameters: parameterTypes, returnType };
|
|
533
|
+
return { parameters: parameterTypes, returnType, ...(typeParameters.length > 0 ? { typeParameters } : {}) };
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Rejoins a bounded metadata suffix while retaining its parser-owned range.
|
|
537
|
+
* @param {{location: import("../semantic/types.js").SourceLocation, text: string}[]} tokens - Comment tokens.
|
|
538
|
+
* @param {number} start - First suffix token.
|
|
539
|
+
* @param {string} source - Complete source.
|
|
540
|
+
* @returns {{location: import("../semantic/types.js").SourceLocation, sourceType: string}} Joined token.
|
|
541
|
+
*/
|
|
542
|
+
function joinedCommentToken(tokens, start, source) {
|
|
543
|
+
const first = tokens[start];
|
|
544
|
+
const last = tokens.at(-1);
|
|
545
|
+
if (!first || !last)
|
|
546
|
+
throw new Error("Ruby metadata suffix unexpectedly disappeared.");
|
|
547
|
+
const location = locationFromOffsets(first.location.filename, source, first.location.start.offset, last.location.end.offset);
|
|
548
|
+
return { location, sourceType: source.slice(location.start.offset, location.end.offset) };
|
|
191
549
|
}
|
|
192
550
|
/**
|
|
193
551
|
* Lexes whitespace-separated metadata tokens inside a Prism-owned Ruby comment.
|
|
@@ -250,9 +608,11 @@ function associatedComments(comments, node, source) {
|
|
|
250
608
|
* @param {LocalVariableWriteNode} node - Local write.
|
|
251
609
|
* @param {string} filename - Source filename.
|
|
252
610
|
* @param {string} source - Complete source.
|
|
253
|
-
* @
|
|
611
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
612
|
+
* @param {Map<string, import("../semantic/types.js").TypeParameter>} [typeParameters] - Declaration-scoped parameters.
|
|
613
|
+
* @returns {{immutable: boolean, type: import("../semantic/types.js").SemanticValueType} | undefined} Metadata when present.
|
|
254
614
|
*/
|
|
255
|
-
function localMetadata(comments, node, filename, source) {
|
|
615
|
+
function localMetadata(comments, node, filename, source, recordNames, typeParameters = new Map()) {
|
|
256
616
|
const associated = associatedComments(comments, node, source);
|
|
257
617
|
const metadata = associated.map((comment) => commentTokens(comment, filename, source));
|
|
258
618
|
const typeMetadata = metadata.filter(([token]) => token?.text == "@type");
|
|
@@ -263,89 +623,333 @@ function localMetadata(comments, node, filename, source) {
|
|
|
263
623
|
if (profileMetadata.length == 0)
|
|
264
624
|
return undefined;
|
|
265
625
|
const location = nodeLocation(node, filename, source);
|
|
266
|
-
if (typeMetadata.length != 1 || typeMetadata[0].length
|
|
626
|
+
if (typeMetadata.length != 1 || typeMetadata[0].length < 2 ||
|
|
267
627
|
immutableMetadata.length > 1 || immutableMetadata.some((tokens) => tokens.length != 1) ||
|
|
268
628
|
profileMetadata.length != typeMetadata.length + immutableMetadata.length) {
|
|
269
629
|
return unsupportedSyntax("ruby", "malformed local type metadata", location);
|
|
270
630
|
}
|
|
631
|
+
const declaredType = joinedCommentToken(typeMetadata[0], 1, source);
|
|
271
632
|
return {
|
|
272
633
|
immutable: immutableMetadata.length == 1,
|
|
273
|
-
type: convertType(
|
|
634
|
+
type: convertType(declaredType.sourceType, `Local '${node.name}'`, location, source, declaredType.location, recordNames, typeParameters)
|
|
274
635
|
};
|
|
275
636
|
}
|
|
276
637
|
/**
|
|
277
638
|
* Converts one Ruby local declaration or assignment.
|
|
278
639
|
* @param {import("@ruby/prism").Node} node - Prism node.
|
|
279
640
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
280
|
-
* @param {
|
|
641
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
281
642
|
* @param {string} filename - Source filename.
|
|
282
643
|
* @param {string} source - Complete source.
|
|
283
644
|
* @returns {import("../semantic/types.js").LocalStatement} Semantic local statement.
|
|
284
645
|
*/
|
|
285
|
-
function convertLocalStatement(node, comments,
|
|
646
|
+
function convertLocalStatement(node, comments, context, filename, source) {
|
|
286
647
|
const location = nodeLocation(node, filename, source);
|
|
287
648
|
if (!(node instanceof LocalVariableWriteNode))
|
|
288
649
|
return unsupportedSyntax("ruby", node.constructor.name, location);
|
|
289
|
-
const metadata = localMetadata(comments, node, filename, source);
|
|
650
|
+
const metadata = localMetadata(comments, node, filename, source, context.recordNames, context.typeParameters);
|
|
290
651
|
if (metadata) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
652
|
+
let declaredType = metadata.type;
|
|
653
|
+
if (metadata.immutable && declaredType.kind == "MapType" && context.orderedMapDeclarations?.has(node) &&
|
|
654
|
+
node.value instanceof HashNode) {
|
|
655
|
+
declaredType = orderedMapTypeFromMap(declaredType, location);
|
|
656
|
+
}
|
|
657
|
+
const semantic = withParserRanges({
|
|
658
|
+
initializer: convertExpression(node.value, filename, source, context, declaredType),
|
|
659
|
+
kind: /** @type {const} */ ("LocalDeclaration"),
|
|
295
660
|
location,
|
|
296
661
|
mutable: !metadata.immutable,
|
|
297
662
|
name: node.name,
|
|
298
|
-
type:
|
|
663
|
+
type: declaredType
|
|
299
664
|
}, { name: prismLocation(node.nameLoc, filename, source), operator: prismLocation(node.operatorLoc, filename, source) });
|
|
665
|
+
context.bindings.set(node.name, declaredType);
|
|
666
|
+
return semantic;
|
|
300
667
|
}
|
|
301
|
-
if (!
|
|
668
|
+
if (!context.bindings.has(node.name)) {
|
|
669
|
+
if (node.value instanceof LocalVariableReadNode && context.bindings.get(node.value.name)?.kind == "OrderedMapType") {
|
|
670
|
+
return unsupportedSyntax("ruby", "ordered map alias escape", location);
|
|
671
|
+
}
|
|
302
672
|
return missingType("ruby", `Local '${node.name}'`, location);
|
|
673
|
+
}
|
|
303
674
|
const targetLocation = prismLocation(node.nameLoc, filename, source);
|
|
304
675
|
const target = withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: targetLocation, name: node.name }, {
|
|
305
676
|
name: targetLocation
|
|
306
677
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
678
|
+
const bindingType = context.bindings.get(node.name);
|
|
679
|
+
const semantic = withParserRanges({
|
|
680
|
+
expression: convertExpression(node.value, filename, source, context, bindingType?.kind == "ErrorType" ? undefined : bindingType),
|
|
681
|
+
kind: /** @type {const} */ ("AssignmentStatement"),
|
|
310
682
|
location,
|
|
311
683
|
target
|
|
312
684
|
}, { operator: prismLocation(node.operatorLoc, filename, source) });
|
|
685
|
+
return semantic;
|
|
313
686
|
}
|
|
314
687
|
/**
|
|
315
688
|
* Converts one exhaustive Prism statement.
|
|
316
689
|
* @param {import("@ruby/prism").Node} node - Prism statement.
|
|
317
690
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
318
|
-
* @param {
|
|
691
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
319
692
|
* @param {string} filename - Source filename.
|
|
320
693
|
* @param {string} source - Complete source.
|
|
321
694
|
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
322
695
|
*/
|
|
323
|
-
function convertStatement(node, comments,
|
|
324
|
-
if (node instanceof ReturnNode)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return
|
|
696
|
+
function convertStatement(node, comments, context, filename, source) {
|
|
697
|
+
if (node instanceof ReturnNode) {
|
|
698
|
+
if ((context.loopDepth ?? 0) > 0)
|
|
699
|
+
return unsupportedSyntax("ruby", "nonlocal return from each block", nodeLocation(node, filename, source));
|
|
700
|
+
return convertReturn(node, filename, source, context);
|
|
701
|
+
}
|
|
702
|
+
if (node instanceof IfNode || node instanceof UnlessNode)
|
|
703
|
+
return convertIf(node, comments, context, filename, source);
|
|
704
|
+
if (node instanceof WhileNode)
|
|
705
|
+
return convertWhile(node, comments, context, filename, source);
|
|
706
|
+
if (node instanceof BeginNode)
|
|
707
|
+
return convertRubyTry(node, comments, context, filename, source);
|
|
328
708
|
if (node instanceof LocalVariableWriteNode)
|
|
329
|
-
return convertLocalStatement(node, comments,
|
|
330
|
-
if (node instanceof
|
|
331
|
-
|
|
709
|
+
return convertLocalStatement(node, comments, context, filename, source);
|
|
710
|
+
if (node instanceof InstanceVariableWriteNode) {
|
|
711
|
+
const location = nodeLocation(node, filename, source);
|
|
712
|
+
const field = context.currentClass?.fields.find((candidate) => `@${candidate.name}` == node.name);
|
|
713
|
+
if (!field || !context.currentClass)
|
|
714
|
+
return unsupportedSyntax("ruby", "private instance field outside its declaring class", location);
|
|
715
|
+
const receiver = withParserRanges({ classId: /** @type {string} */ (context.currentClass.id),
|
|
716
|
+
kind: /** @type {const} */ ("ReceiverExpression"), location }, { receiver: location });
|
|
717
|
+
return withParserRanges({ expression: convertExpression(node.value, filename, source, context, field.type),
|
|
718
|
+
field: /** @type {string} */ (field.id), kind: /** @type {const} */ ("PrivateFieldWriteStatement"), location, receiver }, { member: location });
|
|
719
|
+
}
|
|
720
|
+
if (node instanceof BreakNode || node instanceof NextNode) {
|
|
721
|
+
if (node.arguments_)
|
|
722
|
+
return unsupportedSyntax("ruby", `${node instanceof BreakNode ? "break" : "next"} value`, nodeLocation(node.arguments_, filename, source));
|
|
723
|
+
const location = prismLocation(node.keywordLoc, filename, source);
|
|
724
|
+
return withParserRanges({
|
|
725
|
+
kind: /** @type {"BreakStatement" | "ContinueStatement"} */ (node instanceof BreakNode ? "BreakStatement" : "ContinueStatement"),
|
|
726
|
+
location
|
|
727
|
+
}, { keyword: location });
|
|
728
|
+
}
|
|
729
|
+
if (node instanceof CallNode) {
|
|
730
|
+
if (!node.receiver && node.name == "raise")
|
|
731
|
+
return convertRubyRaise(node, context, filename, source);
|
|
732
|
+
if (node.block)
|
|
733
|
+
return convertForEach(node, comments, context, filename, source);
|
|
734
|
+
if (!node.receiver && node.name == "puts" && !context.functions.has("puts"))
|
|
735
|
+
return convertPrint(node, filename, source, context);
|
|
736
|
+
return {
|
|
737
|
+
expression: /** @type {import("../semantic/types.js").CallExpression} */ (convertExpression(node, filename, source, context)),
|
|
738
|
+
kind: "ExpressionStatement",
|
|
739
|
+
location: nodeLocation(node, filename, source)
|
|
740
|
+
};
|
|
741
|
+
}
|
|
332
742
|
return unsupportedSyntax("ruby", node.constructor.name, nodeLocation(node, filename, source));
|
|
333
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Converts exact `raise DeclaredError, message`.
|
|
746
|
+
* @param {CallNode} node - Prism raise call.
|
|
747
|
+
* @param {RubyConversionContext} context - Typed lexical context.
|
|
748
|
+
* @param {string} filename - Source filename.
|
|
749
|
+
* @param {string} source - Complete source.
|
|
750
|
+
* @returns {import("../semantic/types.js").RaiseStatement} Semantic raise.
|
|
751
|
+
*/
|
|
752
|
+
function convertRubyRaise(node, context, filename, source) {
|
|
753
|
+
const location = nodeLocation(node, filename, source);
|
|
754
|
+
const arguments_ = node.arguments_?.arguments_ ?? [];
|
|
755
|
+
const errorNode = arguments_[0];
|
|
756
|
+
if (node.block || node.callOperatorLoc || arguments_.length != 2 ||
|
|
757
|
+
!(errorNode instanceof ConstantReadNode) && !(errorNode instanceof ConstantPathNode) ||
|
|
758
|
+
!context.errorNames.has(constantPathName(errorNode))) {
|
|
759
|
+
return unsupportedSyntax("ruby", "raise other than exact declared error and message", location);
|
|
760
|
+
}
|
|
761
|
+
const declaration = /** @type {import("../semantic/types.js").ErrorDeclaration} */ (context.errorNames.get(constantPathName(errorNode)));
|
|
762
|
+
const typeLocation = nodeLocation(errorNode, filename, source);
|
|
763
|
+
return withParserRanges({
|
|
764
|
+
error: withParserRanges({
|
|
765
|
+
error: withParserRanges({ declarationId: /** @type {string} */ (declaration.id), kind: /** @type {const} */ ("ErrorType") }, { type: typeLocation }),
|
|
766
|
+
kind: /** @type {const} */ ("ErrorConstruction"),
|
|
767
|
+
location,
|
|
768
|
+
message: convertExpression(arguments_[1], filename, source, context)
|
|
769
|
+
}, { type: typeLocation }),
|
|
770
|
+
kind: /** @type {const} */ ("RaiseStatement"),
|
|
771
|
+
location
|
|
772
|
+
}, { keyword: prismLocation(node.messageLoc ?? node.location, filename, source) });
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Converts one exact typed rescue with no else/ensure.
|
|
776
|
+
* @param {BeginNode} node - Prism begin node.
|
|
777
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Parser-owned comments.
|
|
778
|
+
* @param {RubyConversionContext} context - Typed lexical context.
|
|
779
|
+
* @param {string} filename - Source filename.
|
|
780
|
+
* @param {string} source - Complete source.
|
|
781
|
+
* @returns {import("../semantic/types.js").TryStatement} Semantic exact handler.
|
|
782
|
+
*/
|
|
783
|
+
function convertRubyTry(node, comments, context, filename, source) {
|
|
784
|
+
const location = nodeLocation(node, filename, source);
|
|
785
|
+
const handler = node.rescueClause;
|
|
786
|
+
if (!(handler instanceof RescueNode) || handler.subsequent || node.elseClause || node.ensureClause ||
|
|
787
|
+
handler.exceptions.length != 1 ||
|
|
788
|
+
!(handler.exceptions[0] instanceof ConstantReadNode) && !(handler.exceptions[0] instanceof ConstantPathNode) ||
|
|
789
|
+
!context.errorNames.has(constantPathName(handler.exceptions[0])) || !(handler.reference instanceof LocalVariableTargetNode)) {
|
|
790
|
+
return unsupportedSyntax("ruby", "begin without one exact typed rescue and binding", location);
|
|
791
|
+
}
|
|
792
|
+
const errorNode = handler.exceptions[0];
|
|
793
|
+
const declaration = /** @type {import("../semantic/types.js").ErrorDeclaration} */ (context.errorNames.get(constantPathName(errorNode)));
|
|
794
|
+
const caughtLocation = nodeLocation(errorNode, filename, source);
|
|
795
|
+
const catchType = withParserRanges({ declarationId: /** @type {string} */ (declaration.id), kind: /** @type {const} */ ("ErrorType") }, {
|
|
796
|
+
type: caughtLocation
|
|
797
|
+
});
|
|
798
|
+
const bodyContext = { ...context, bindings: new Map(context.bindings) };
|
|
799
|
+
const catchContext = { ...context, bindings: new Map(context.bindings) };
|
|
800
|
+
catchContext.bindings.set(handler.reference.name, catchType);
|
|
801
|
+
return withParserRanges({
|
|
802
|
+
body: convertBlock(node.statements, comments, bodyContext, filename, source, location),
|
|
803
|
+
catchBinding: withParserRanges({
|
|
804
|
+
kind: /** @type {const} */ ("CatchBinding"),
|
|
805
|
+
location: nodeLocation(handler.reference, filename, source),
|
|
806
|
+
mutable: /** @type {const} */ (false),
|
|
807
|
+
name: handler.reference.name,
|
|
808
|
+
type: catchType
|
|
809
|
+
}, { name: nodeLocation(handler.reference, filename, source) }),
|
|
810
|
+
catchBody: convertBlock(handler.statements, comments, catchContext, filename, source, nodeLocation(handler, filename, source)),
|
|
811
|
+
catchType,
|
|
812
|
+
kind: /** @type {const} */ ("TryStatement"),
|
|
813
|
+
location
|
|
814
|
+
}, { catch: nodeLocation(handler, filename, source), try: location });
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Converts exact resolved-list `.each do |value| ... end` syntax.
|
|
818
|
+
* @param {CallNode} node - Prism call with a block.
|
|
819
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
820
|
+
* @param {RubyConversionContext} context - Typed lexical context.
|
|
821
|
+
* @param {string} filename - Source filename.
|
|
822
|
+
* @param {string} source - Complete source.
|
|
823
|
+
* @returns {import("../semantic/types.js").ForEachStatement | import("../semantic/types.js").ForEachMapStatement} Semantic loop.
|
|
824
|
+
*/
|
|
825
|
+
function convertForEach(node, comments, context, filename, source) {
|
|
826
|
+
const location = nodeLocation(node, filename, source);
|
|
827
|
+
const block = node.block;
|
|
828
|
+
if (!(block instanceof BlockNode))
|
|
829
|
+
return unsupportedSyntax("ruby", "call block", block ? nodeLocation(block, filename, source) : location);
|
|
830
|
+
if (!node.receiver || node.name != "each" || node.arguments_ || !node.callOperatorLoc || !node.messageLoc) {
|
|
831
|
+
return unsupportedSyntax("ruby", "arbitrary call block", nodeLocation(block, filename, source));
|
|
832
|
+
}
|
|
833
|
+
if (slicePrismSource(source, block.openingLoc.startOffset, block.openingLoc.startOffset + block.openingLoc.length) != "do") {
|
|
834
|
+
return unsupportedSyntax("ruby", "non-do each block", prismLocation(block.openingLoc, filename, source));
|
|
835
|
+
}
|
|
836
|
+
const excluded = findRubyDescendant(block.body, (candidate) => candidate instanceof RedoNode || candidate instanceof RetryNode || candidate instanceof ReturnNode);
|
|
837
|
+
if (excluded) {
|
|
838
|
+
const detail = excluded instanceof ReturnNode ? "nonlocal return from each block" :
|
|
839
|
+
excluded instanceof RedoNode ? "redo in each block" : "retry in each block";
|
|
840
|
+
return unsupportedSyntax("ruby", detail, nodeLocation(excluded, filename, source));
|
|
841
|
+
}
|
|
842
|
+
if (!(block.parameters instanceof BlockParametersNode) || block.parameters.locals.length > 0 ||
|
|
843
|
+
!block.parameters.parameters) {
|
|
844
|
+
return unsupportedSyntax("ruby", "each block parameters", block.parameters
|
|
845
|
+
? nodeLocation(block.parameters, filename, source)
|
|
846
|
+
: nodeLocation(block, filename, source));
|
|
847
|
+
}
|
|
848
|
+
const parameters = block.parameters.parameters;
|
|
849
|
+
const supportedRequireds = parameters.requireds.length == 1 || parameters.requireds.length == 2;
|
|
850
|
+
const unsupportedParameter = !supportedRequireds
|
|
851
|
+
? parameters.requireds[2] ?? parameters.requireds[1] ?? parameters.requireds[0] ?? block.parameters
|
|
852
|
+
: parameters.requireds.every((parameter) => parameter instanceof RequiredParameterNode) &&
|
|
853
|
+
parameters.optionals.length == 0 && !parameters.rest &&
|
|
854
|
+
parameters.posts.length == 0 && parameters.keywords.length == 0 && !parameters.keywordRest && !parameters.block
|
|
855
|
+
? undefined
|
|
856
|
+
: parameters.optionals[0] ?? parameters.rest ?? parameters.posts[0] ?? parameters.keywords[0] ??
|
|
857
|
+
parameters.keywordRest ?? parameters.block ?? parameters.requireds[0];
|
|
858
|
+
if (unsupportedParameter)
|
|
859
|
+
return unsupportedSyntax("ruby", "each block parameter arity or shape", nodeLocation(unsupportedParameter, filename, source));
|
|
860
|
+
const collectionType = iterationOperandType(knownExpressionType(node.receiver, context));
|
|
861
|
+
if (parameters.requireds.length == 2) {
|
|
862
|
+
if (collectionType?.kind == "MapType") {
|
|
863
|
+
return unsupportedSyntax("ruby", "unordered map iteration", nodeLocation(node.receiver, filename, source));
|
|
864
|
+
}
|
|
865
|
+
if (!collectionType || collectionType.kind != "OrderedMapType") {
|
|
866
|
+
return missingType("ruby", "Ordered map iteration collection", nodeLocation(node.receiver, filename, source));
|
|
867
|
+
}
|
|
868
|
+
const [keyParameter, valueParameter] = /** @type {[RequiredParameterNode, RequiredParameterNode]} */ (parameters.requireds);
|
|
869
|
+
const keyLocation = nodeLocation(keyParameter, filename, source);
|
|
870
|
+
const valueLocation = nodeLocation(valueParameter, filename, source);
|
|
871
|
+
const keyType = iterationBindingType(collectionType.keyType, keyLocation);
|
|
872
|
+
const valueType = iterationBindingType(collectionType.valueType, valueLocation);
|
|
873
|
+
const keyBinding = withParserRanges({
|
|
874
|
+
kind: /** @type {const} */ ("ValueBinding"), location: keyLocation, mutable: /** @type {const} */ (false),
|
|
875
|
+
name: keyParameter.name, type: keyType
|
|
876
|
+
}, { name: keyLocation });
|
|
877
|
+
const valueBinding = withParserRanges({
|
|
878
|
+
kind: /** @type {const} */ ("ValueBinding"), location: valueLocation, mutable: /** @type {const} */ (false),
|
|
879
|
+
name: valueParameter.name, type: valueType
|
|
880
|
+
}, { name: valueLocation });
|
|
881
|
+
const bodyContext = { ...context, bindings: new Map(context.bindings), loopDepth: (context.loopDepth ?? 0) + 1 };
|
|
882
|
+
bodyContext.bindings.set(keyParameter.name, keyType);
|
|
883
|
+
bodyContext.bindings.set(valueParameter.name, valueType);
|
|
884
|
+
return withParserRanges({
|
|
885
|
+
body: convertBlock(block.body instanceof StatementsNode ? block.body : null, comments, bodyContext, filename, source, nodeLocation(block, filename, source)),
|
|
886
|
+
keyBinding,
|
|
887
|
+
kind: /** @type {const} */ ("ForEachMapStatement"),
|
|
888
|
+
location,
|
|
889
|
+
map: convertExpression(node.receiver, filename, source, context),
|
|
890
|
+
valueBinding
|
|
891
|
+
}, { operator: prismLocation(node.messageLoc, filename, source) });
|
|
892
|
+
}
|
|
893
|
+
const parameter = /** @type {RequiredParameterNode} */ (parameters.requireds[0]);
|
|
894
|
+
if (collectionType?.kind == "MapType" || collectionType?.kind == "OrderedMapType") {
|
|
895
|
+
return unsupportedSyntax("ruby", "map iteration without key/value pair binding", nodeLocation(node.receiver, filename, source));
|
|
896
|
+
}
|
|
897
|
+
if (!collectionType || collectionType.kind != "ListType") {
|
|
898
|
+
return missingType("ruby", "Iteration collection", nodeLocation(node.receiver, filename, source));
|
|
899
|
+
}
|
|
900
|
+
const bindingLocation = nodeLocation(parameter, filename, source);
|
|
901
|
+
const inferredType = collectionType.elementType;
|
|
902
|
+
const bindingType = iterationBindingType(inferredType, bindingLocation);
|
|
903
|
+
const valueBinding = withParserRanges({
|
|
904
|
+
kind: /** @type {const} */ ("ValueBinding"),
|
|
905
|
+
location: bindingLocation,
|
|
906
|
+
mutable: /** @type {const} */ (false),
|
|
907
|
+
name: parameter.name,
|
|
908
|
+
type: bindingType
|
|
909
|
+
}, { name: bindingLocation });
|
|
910
|
+
const bodyContext = { ...context, bindings: new Map(context.bindings), loopDepth: (context.loopDepth ?? 0) + 1 };
|
|
911
|
+
bodyContext.bindings.set(parameter.name, bindingType);
|
|
912
|
+
return withParserRanges({
|
|
913
|
+
body: convertBlock(block.body instanceof StatementsNode ? block.body : null, comments, bodyContext, filename, source, nodeLocation(block, filename, source)),
|
|
914
|
+
kind: /** @type {const} */ ("ForEachStatement"),
|
|
915
|
+
list: convertExpression(node.receiver, filename, source, context),
|
|
916
|
+
location,
|
|
917
|
+
valueBinding
|
|
918
|
+
}, { operator: prismLocation(node.messageLoc, filename, source) });
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Finds the first parser descendant matching one excluded block construct.
|
|
922
|
+
* @param {import("@ruby/prism").Node | null} node - Parser subtree.
|
|
923
|
+
* @param {(node: import("@ruby/prism").Node) => boolean} predicate - Exclusion predicate.
|
|
924
|
+
* @returns {import("@ruby/prism").Node | undefined} First source-ordered match.
|
|
925
|
+
*/
|
|
926
|
+
function findRubyDescendant(node, predicate) {
|
|
927
|
+
if (!node)
|
|
928
|
+
return undefined;
|
|
929
|
+
if (predicate(node))
|
|
930
|
+
return node;
|
|
931
|
+
for (const child of node.compactChildNodes()) {
|
|
932
|
+
const match = findRubyDescendant(child, predicate);
|
|
933
|
+
if (match)
|
|
934
|
+
return match;
|
|
935
|
+
}
|
|
936
|
+
return undefined;
|
|
937
|
+
}
|
|
334
938
|
/**
|
|
335
939
|
* Converts one ordered Prism statement list.
|
|
336
940
|
* @param {StatementsNode | null} node - Prism statements, or an empty source block.
|
|
337
941
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
338
|
-
* @param {
|
|
942
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
339
943
|
* @param {string} filename - Source filename.
|
|
340
944
|
* @param {string} source - Complete source.
|
|
341
945
|
* @param {import("../semantic/types.js").SourceLocation} fallbackLocation - Empty block location.
|
|
342
946
|
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
343
947
|
*/
|
|
344
|
-
function convertBlock(node, comments,
|
|
948
|
+
function convertBlock(node, comments, context, filename, source, fallbackLocation) {
|
|
345
949
|
return {
|
|
346
950
|
kind: "Block",
|
|
347
951
|
location: node ? nodeLocation(node, filename, source) : fallbackLocation,
|
|
348
|
-
statements: node ? node.body.map((statement) => convertStatement(statement, comments,
|
|
952
|
+
statements: node ? node.body.map((statement) => convertStatement(statement, comments, context, filename, source)) : []
|
|
349
953
|
};
|
|
350
954
|
}
|
|
351
955
|
/**
|
|
@@ -366,33 +970,54 @@ function isImmediateCommentGap(gap) {
|
|
|
366
970
|
return newlines <= 1;
|
|
367
971
|
}
|
|
368
972
|
/**
|
|
369
|
-
* Requires an exact supported Ruby
|
|
973
|
+
* Requires an exact supported Ruby value-type spelling.
|
|
370
974
|
* @param {string | undefined} sourceType - Ruby type comment value.
|
|
371
975
|
* @param {string} subject - Typed subject.
|
|
372
976
|
* @param {import("../semantic/types.js").SourceLocation} location - Source location.
|
|
977
|
+
* @param {string} source - Complete parser input.
|
|
373
978
|
* @param {import("../semantic/types.js").SourceLocation} [typeLocation] - Exact type comment token location.
|
|
374
|
-
* @
|
|
979
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} [recordNames] - Nominal declarations by source name.
|
|
980
|
+
* @param {Map<string, import("../semantic/types.js").TypeParameter>} [typeParameters] - Declaration-scoped parameters.
|
|
981
|
+
* @returns {import("../semantic/types.js").SemanticValueType} Semantic type.
|
|
375
982
|
*/
|
|
376
|
-
function convertType(sourceType, subject, location, typeLocation = location) {
|
|
377
|
-
return
|
|
983
|
+
function convertType(sourceType, subject, location, source, typeLocation = location, recordNames = new Map(), typeParameters = new Map()) {
|
|
984
|
+
return documentedValueType({ language: "ruby", location: typeLocation, ownerLocation: location, records: recordNames, source, sourceType, subject, typeParameters });
|
|
378
985
|
}
|
|
379
986
|
/**
|
|
380
|
-
* Converts a Ruby definition.
|
|
987
|
+
* Converts a Ruby definition signature before body expressions.
|
|
381
988
|
* @param {DefNode} node - Prism definition.
|
|
382
989
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
383
990
|
* @param {string} filename - Source filename.
|
|
384
991
|
* @param {string} source - Complete source.
|
|
385
|
-
* @
|
|
992
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
993
|
+
* @param {string} ownerId - Stable function identity.
|
|
994
|
+
* @param {boolean} [allowBuiltinOutput] - Whether compiler authority admits the exact output facade function.
|
|
995
|
+
* @returns {RubyFunctionSignature} Semantic signature.
|
|
386
996
|
*/
|
|
387
|
-
function
|
|
997
|
+
function convertFunctionSignature(node, comments, filename, source, recordNames, ownerId, allowBuiltinOutput = false) {
|
|
388
998
|
const location = nodeLocation(node, filename, source);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
999
|
+
const parameterList = node.parameters;
|
|
1000
|
+
if (node.receiver)
|
|
1001
|
+
return unsupportedSyntax("ruby", "singleton method", nodeLocation(node.receiver, filename, source));
|
|
1002
|
+
const nameLocation = prismLocation(node.nameLoc, filename, source);
|
|
1003
|
+
if (node.name == "puts" && !allowBuiltinOutput) {
|
|
1004
|
+
return unsupportedSyntax("ruby", "function 'puts' captures built-in printing", nameLocation);
|
|
393
1005
|
}
|
|
394
|
-
const
|
|
395
|
-
|
|
1006
|
+
const unsupportedParameter = parameterList && [
|
|
1007
|
+
parameterList.optionals[0], parameterList.rest, parameterList.posts[0], parameterList.keywords[0],
|
|
1008
|
+
parameterList.keywordRest, parameterList.block,
|
|
1009
|
+
parameterList.requireds.find((parameter) => !(parameter instanceof RequiredParameterNode))
|
|
1010
|
+
].find(Boolean);
|
|
1011
|
+
if (unsupportedParameter) {
|
|
1012
|
+
return unsupportedSyntax("ruby", "parameters", nodeLocation(unsupportedParameter, filename, source));
|
|
1013
|
+
}
|
|
1014
|
+
const declaredTypes = typeComments(comments, node, filename, source, ownerId);
|
|
1015
|
+
const typeParameterNames = new Map((declaredTypes.typeParameters ?? []).map((parameter) => [parameter.name, parameter]));
|
|
1016
|
+
const requiredParameters = parameterList?.requireds ?? [];
|
|
1017
|
+
const extraAnnotation = [...declaredTypes.parameters.keys()].find((name) => !requiredParameters.some((parameter) => parameter instanceof RequiredParameterNode && parameter.name == name));
|
|
1018
|
+
if (extraAnnotation)
|
|
1019
|
+
return unsupportedSyntax("ruby", `annotation for unknown parameter '${extraAnnotation}'`, location);
|
|
1020
|
+
const parameters = requiredParameters.map((parameter) => {
|
|
396
1021
|
if (!(parameter instanceof RequiredParameterNode))
|
|
397
1022
|
return unsupportedSyntax("ruby", parameter.constructor.name, location);
|
|
398
1023
|
const parameterLocation = nodeLocation(parameter, filename, source);
|
|
@@ -401,83 +1026,423 @@ function convertFunction(node, comments, filename, source) {
|
|
|
401
1026
|
kind: /** @type {const} */ ("Parameter"),
|
|
402
1027
|
location: parameterLocation,
|
|
403
1028
|
name: parameter.name,
|
|
404
|
-
type: convertType(declaredType?.sourceType, `Parameter '${parameter.name}'`, parameterLocation, declaredType?.location)
|
|
1029
|
+
type: convertType(declaredType?.sourceType, `Parameter '${parameter.name}'`, parameterLocation, source, declaredType?.location, recordNames, typeParameterNames)
|
|
405
1030
|
}, { name: parameterLocation });
|
|
406
1031
|
});
|
|
407
|
-
|
|
408
|
-
const body = convertBlock(node.body instanceof StatementsNode ? node.body : null, comments, visible, filename, source, location);
|
|
409
|
-
return withParserRanges({
|
|
410
|
-
body,
|
|
411
|
-
kind: "FunctionDeclaration",
|
|
1032
|
+
return {
|
|
412
1033
|
location,
|
|
413
1034
|
name: node.name,
|
|
1035
|
+
nameLocation,
|
|
414
1036
|
parameters,
|
|
415
|
-
returnType:
|
|
416
|
-
|
|
1037
|
+
returnType: declaredTypes.returnType?.sourceType == "[void]"
|
|
1038
|
+
? requireSourceReturnType("ruby", "[void]", `Function '${node.name}' return`, location, declaredTypes.returnType.location)
|
|
1039
|
+
: convertType(declaredTypes.returnType?.sourceType, `Function '${node.name}' return`, location, source, declaredTypes.returnType?.location, recordNames, typeParameterNames),
|
|
1040
|
+
...(declaredTypes.typeParameters ? { typeParameters: declaredTypes.typeParameters } : {})
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Converts a Ruby definition body using all already-proved signatures.
|
|
1045
|
+
* @param {DefNode} node - Prism definition.
|
|
1046
|
+
* @param {RubyFunctionSignature} signature - Converted signature.
|
|
1047
|
+
* @param {Map<string, RubyFunctionSignature>} functions - Module signatures.
|
|
1048
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by source name.
|
|
1049
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration>} records - Record declarations by identity.
|
|
1050
|
+
* @param {Map<string, import("../semantic/types.js").ClassDeclaration>} classes - Reference classes by identity.
|
|
1051
|
+
* @param {Map<string, import("../semantic/types.js").ErrorDeclaration>} errorNames - Error declarations by source name.
|
|
1052
|
+
* @param {Map<string, import("../semantic/types.js").ErrorDeclaration>} errors - Error declarations by identity.
|
|
1053
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
1054
|
+
* @param {string} filename - Source filename.
|
|
1055
|
+
* @param {string} source - Complete source.
|
|
1056
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
1057
|
+
*/
|
|
1058
|
+
function convertFunction(node, signature, functions, recordNames, records, classes, errorNames, errors, comments, filename, source) {
|
|
1059
|
+
const context = {
|
|
1060
|
+
bindings: new Map(signature.parameters.map((parameter) => [parameter.name, parameter.type])),
|
|
1061
|
+
classes,
|
|
1062
|
+
errorNames,
|
|
1063
|
+
errors,
|
|
1064
|
+
functions,
|
|
1065
|
+
orderedMapDeclarations: orderedMapDeclarationsForRuby(node.body instanceof StatementsNode ? node.body.body : []),
|
|
1066
|
+
recordNames,
|
|
1067
|
+
records,
|
|
1068
|
+
returnType: signature.returnType,
|
|
1069
|
+
typeParameters: new Map((signature.typeParameters ?? []).map((parameter) => [parameter.name, parameter]))
|
|
1070
|
+
};
|
|
1071
|
+
const body = convertBlock(node.body instanceof StatementsNode ? node.body : null, comments, context, filename, source, signature.location);
|
|
1072
|
+
return withParserRanges({
|
|
1073
|
+
body,
|
|
1074
|
+
kind: "FunctionDeclaration",
|
|
1075
|
+
location: signature.location,
|
|
1076
|
+
name: signature.name,
|
|
1077
|
+
parameters: signature.parameters,
|
|
1078
|
+
returnType: signature.returnType,
|
|
1079
|
+
...(signature.typeParameters ? { typeParameters: signature.typeParameters } : {})
|
|
1080
|
+
}, { name: signature.nameLocation });
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Resolves parser-owned pair blocks to exact declarations inside one lexical owner.
|
|
1084
|
+
* Ambiguous same-name declarations produce no evidence and fail during loop conversion.
|
|
1085
|
+
* @param {import("@ruby/prism").Node[]} nodes - Function body or entry-point roots.
|
|
1086
|
+
* @returns {Set<object>} Exact pair-iterated parser declarations.
|
|
1087
|
+
*/
|
|
1088
|
+
function orderedMapDeclarationsForRuby(nodes) {
|
|
1089
|
+
/** @type {{declaration: LocalVariableWriteNode, name: string, offset: number}[]} */
|
|
1090
|
+
const declarations = [];
|
|
1091
|
+
/** @type {{name: string, offset: number}[]} */
|
|
1092
|
+
const receivers = [];
|
|
1093
|
+
/**
|
|
1094
|
+
* Visits one parser candidate.
|
|
1095
|
+
* @param {import("@ruby/prism").Node} node - Parser candidate.
|
|
1096
|
+
*/
|
|
1097
|
+
const visit = (node) => {
|
|
1098
|
+
if (node instanceof DefNode || node instanceof ClassNode)
|
|
1099
|
+
return;
|
|
1100
|
+
if (node instanceof LocalVariableWriteNode)
|
|
1101
|
+
declarations.push({
|
|
1102
|
+
declaration: node,
|
|
1103
|
+
name: node.name,
|
|
1104
|
+
offset: node.location.startOffset
|
|
1105
|
+
});
|
|
1106
|
+
if (node instanceof CallNode && node.receiver instanceof LocalVariableReadNode && node.name == "each" &&
|
|
1107
|
+
node.block instanceof BlockNode && node.block.parameters instanceof BlockParametersNode &&
|
|
1108
|
+
node.block.parameters.parameters?.requireds.length == 2)
|
|
1109
|
+
receivers.push({
|
|
1110
|
+
name: node.receiver.name,
|
|
1111
|
+
offset: node.location.startOffset
|
|
1112
|
+
});
|
|
1113
|
+
for (const child of node.compactChildNodes())
|
|
1114
|
+
visit(child);
|
|
1115
|
+
};
|
|
1116
|
+
for (const node of nodes)
|
|
1117
|
+
visit(node);
|
|
1118
|
+
const selected = new Set();
|
|
1119
|
+
for (const receiver of receivers) {
|
|
1120
|
+
const matches = declarations.filter(({ name, offset }) => name == receiver.name && offset < receiver.offset);
|
|
1121
|
+
if (matches.length == 1)
|
|
1122
|
+
selected.add(matches[0].declaration);
|
|
1123
|
+
}
|
|
1124
|
+
return selected;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Converts one exact empty StandardError subclass.
|
|
1128
|
+
* @param {ClassNode} node - Prism class declaration.
|
|
1129
|
+
* @param {import("../semantic/types.js").ErrorDeclaration} declaration - Predeclared semantic error.
|
|
1130
|
+
* @param {string} filename - Source filename.
|
|
1131
|
+
* @param {string} source - Complete source.
|
|
1132
|
+
* @returns {import("../semantic/types.js").ErrorDeclaration} Semantic error declaration.
|
|
1133
|
+
*/
|
|
1134
|
+
function convertRubyError(node, declaration, filename, source) {
|
|
1135
|
+
const location = nodeLocation(node, filename, source);
|
|
1136
|
+
if (!(node.constantPath instanceof ConstantReadNode) || !(node.superclass instanceof ConstantReadNode) ||
|
|
1137
|
+
node.superclass.name != "StandardError" || !node.inheritanceOperatorLoc || node.body) {
|
|
1138
|
+
return unsupportedSyntax("ruby", "noncanonical typed error declaration", location);
|
|
1139
|
+
}
|
|
1140
|
+
return withParserRanges(declaration, {
|
|
1141
|
+
name: nodeLocation(node.constantPath, filename, source),
|
|
1142
|
+
type: nodeLocation(node.superclass, filename, source)
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Converts the bounded Ruby reference-class profile.
|
|
1147
|
+
* @param {ClassNode} node - Prism class declaration.
|
|
1148
|
+
* @param {import("../semantic/types.js").ClassDeclaration} declaration - Predeclared class identity.
|
|
1149
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} nominalNames - Visible nominal declarations.
|
|
1150
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration>} records - Records by identity.
|
|
1151
|
+
* @param {Map<string, import("../semantic/types.js").ClassDeclaration>} classes - Classes by identity.
|
|
1152
|
+
* @param {Map<string, RubyFunctionSignature>} functions - Top-level signatures.
|
|
1153
|
+
* @param {Map<string, import("../semantic/types.js").ErrorDeclaration>} errorNames - Errors by name.
|
|
1154
|
+
* @param {Map<string, import("../semantic/types.js").ErrorDeclaration>} errors - Errors by identity.
|
|
1155
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
1156
|
+
* @param {string} filename - Source filename.
|
|
1157
|
+
* @param {string} source - Complete source.
|
|
1158
|
+
* @returns {import("../semantic/types.js").ClassDeclaration} Semantic class.
|
|
1159
|
+
*/
|
|
1160
|
+
function convertRubyReferenceClass(node, declaration, nominalNames, records, classes, functions, errorNames, errors, comments, filename, source) {
|
|
1161
|
+
const location = nodeLocation(node, filename, source);
|
|
1162
|
+
if (!(node.constantPath instanceof ConstantReadNode) || node.superclass || node.inheritanceOperatorLoc ||
|
|
1163
|
+
!(node.body instanceof StatementsNode)) {
|
|
1164
|
+
return unsupportedSyntax("ruby", "reference class inheritance, qualified name, or empty body", location);
|
|
1165
|
+
}
|
|
1166
|
+
const members = node.body.body;
|
|
1167
|
+
const initializers = members.filter((member) => member instanceof DefNode && member.name == "initialize");
|
|
1168
|
+
const methodNodes = /** @type {DefNode[]} */ (members.filter((member) => member instanceof DefNode && member.name != "initialize"));
|
|
1169
|
+
const reservedMethod = methodNodes.find((method) => referenceMethodHooks.has(method.name));
|
|
1170
|
+
if (initializers.length != 1 || members.some((member) => !(member instanceof DefNode)) || reservedMethod) {
|
|
1171
|
+
return unsupportedSyntax("ruby", "reference class requires one initializer and ordinary methods", location);
|
|
1172
|
+
}
|
|
1173
|
+
const initializer = /** @type {DefNode} */ (initializers[0]);
|
|
1174
|
+
const parameters = initializer.parameters?.requireds ?? [];
|
|
1175
|
+
const invalidParameter = initializer.parameters && [initializer.parameters.optionals[0], initializer.parameters.rest,
|
|
1176
|
+
initializer.parameters.posts[0], initializer.parameters.keywords[0], initializer.parameters.keywordRest,
|
|
1177
|
+
initializer.parameters.block].find(Boolean);
|
|
1178
|
+
const statements = initializer.body instanceof StatementsNode ? initializer.body.body : [];
|
|
1179
|
+
const annotations = typeComments(comments, initializer, filename, source);
|
|
1180
|
+
const acquisition = statements.length == 1 && statements[0] instanceof InstanceVariableWriteNode &&
|
|
1181
|
+
statements[0].name == "@resource" && statements[0].value instanceof CallNode && !statements[0].value.receiver &&
|
|
1182
|
+
!statements[0].value.block && statements[0].value.name == "v1_connect" &&
|
|
1183
|
+
statements[0].value.arguments_?.arguments_.length == 2 && parameters.length == 2 &&
|
|
1184
|
+
parameters[0] instanceof RequiredParameterNode && parameters[0].name == "host" &&
|
|
1185
|
+
parameters[1] instanceof RequiredParameterNode && parameters[1].name == "port" &&
|
|
1186
|
+
statements[0].value.arguments_.arguments_[0] instanceof LocalVariableReadNode &&
|
|
1187
|
+
statements[0].value.arguments_.arguments_[0].name == "host" &&
|
|
1188
|
+
statements[0].value.arguments_.arguments_[1] instanceof LocalVariableReadNode &&
|
|
1189
|
+
statements[0].value.arguments_.arguments_[1].name == "port" && declaration.name == "TCPSocket" &&
|
|
1190
|
+
functions.get("v1_connect")?.returnType.kind == "OwnedResourceType";
|
|
1191
|
+
if (initializer.receiver || invalidParameter || annotations.returnType || annotations.parameters.size != parameters.length ||
|
|
1192
|
+
!acquisition && statements.length != parameters.length) {
|
|
1193
|
+
return unsupportedSyntax("ruby", "noncanonical reference class initializer", nodeLocation(initializer, filename, source));
|
|
1194
|
+
}
|
|
1195
|
+
declaration.fields = acquisition ? [withParserRanges({
|
|
1196
|
+
id: `${declaration.id}:field:0`,
|
|
1197
|
+
kind: /** @type {const} */ ("PrivateField"),
|
|
1198
|
+
location: nodeLocation(/** @type {InstanceVariableWriteNode} */ (statements[0]), filename, source),
|
|
1199
|
+
name: "resource",
|
|
1200
|
+
type: /** @type {import("../semantic/types.js").OwnedResourceType} */ (structuredClone(functions.get("v1_connect")?.returnType))
|
|
1201
|
+
}, { name: nodeLocation(/** @type {InstanceVariableWriteNode} */ (statements[0]), filename, source) })] : parameters.map((candidate, index) => {
|
|
1202
|
+
const parameter = /** @type {RequiredParameterNode} */ (candidate);
|
|
1203
|
+
const assignment = statements[index];
|
|
1204
|
+
const annotated = annotations.parameters.get(parameter.name);
|
|
1205
|
+
if (!(parameter instanceof RequiredParameterNode) || !(assignment instanceof InstanceVariableWriteNode) ||
|
|
1206
|
+
assignment.name != `@${parameter.name}` || !(assignment.value instanceof LocalVariableReadNode) ||
|
|
1207
|
+
assignment.value.name != parameter.name || !annotated) {
|
|
1208
|
+
return unsupportedSyntax("ruby", "private field not initialized exactly once in parameter order", nodeLocation(assignment ?? initializer, filename, source));
|
|
1209
|
+
}
|
|
1210
|
+
return withParserRanges({ id: `${declaration.id}:field:${index}`, kind: /** @type {const} */ ("PrivateField"),
|
|
1211
|
+
location: nodeLocation(assignment, filename, source), name: parameter.name,
|
|
1212
|
+
type: convertType(annotated.sourceType, `Private field '${parameter.name}'`, nodeLocation(parameter, filename, source), source, annotated.location, nominalNames) }, { name: nodeLocation(assignment, filename, source) });
|
|
1213
|
+
});
|
|
1214
|
+
const constructorParameters = parameters.map((candidate, index) => {
|
|
1215
|
+
const parameter = /** @type {RequiredParameterNode} */ (candidate);
|
|
1216
|
+
const parameterLocation = nodeLocation(parameter, filename, source);
|
|
1217
|
+
const annotated = annotations.parameters.get(parameter.name);
|
|
1218
|
+
return withParserRanges({ kind: /** @type {const} */ ("Parameter"), location: parameterLocation, name: parameter.name,
|
|
1219
|
+
type: acquisition
|
|
1220
|
+
? convertType(annotated?.sourceType, `Constructor parameter '${parameter.name}'`, parameterLocation, source, annotated?.location, nominalNames)
|
|
1221
|
+
: declaration.fields[index].type }, { name: parameterLocation });
|
|
1222
|
+
});
|
|
1223
|
+
declaration.constructor = withParserRanges({ body: /** @type {import("../semantic/types.js").Block} */ ({}),
|
|
1224
|
+
id: `${declaration.id}:constructor`, kind: /** @type {const} */ ("ConstructorDeclaration"), location: nodeLocation(initializer, filename, source),
|
|
1225
|
+
parameters: constructorParameters }, { constructor: prismLocation(initializer.nameLoc, filename, source) });
|
|
1226
|
+
const methodSignatures = methodNodes.map((method, index) => convertFunctionSignature(method, comments, filename, source, nominalNames, `${declaration.id}:method:${index}`));
|
|
1227
|
+
declaration.methods = methodSignatures.map((signature, index) => withParserRanges({
|
|
1228
|
+
body: /** @type {import("../semantic/types.js").Block} */ ({}), id: `${declaration.id}:method:${index}`,
|
|
1229
|
+
kind: /** @type {const} */ ("MethodDeclaration"), location: signature.location, name: signature.name,
|
|
1230
|
+
parameters: signature.parameters, returnType: signature.returnType
|
|
1231
|
+
}, { name: signature.nameLocation }));
|
|
1232
|
+
const base = { bindings: new Map(), classes, currentClass: declaration, errorNames, errors, functions,
|
|
1233
|
+
recordNames: nominalNames, records };
|
|
1234
|
+
declaration.constructor.body = convertBlock(initializer.body instanceof StatementsNode ? initializer.body : null, comments, { ...base, bindings: new Map(constructorParameters.map((parameter) => [parameter.name, parameter.type])),
|
|
1235
|
+
returnType: { kind: /** @type {const} */ ("TypeReference"), name: /** @type {const} */ ("void") } }, filename, source, declaration.constructor.location);
|
|
1236
|
+
for (let index = 0; index < methodNodes.length; index += 1) {
|
|
1237
|
+
const method = declaration.methods[index];
|
|
1238
|
+
const methodBody = methodNodes[index].body;
|
|
1239
|
+
method.body = convertBlock(methodBody instanceof StatementsNode ? methodBody : null, comments, { ...base, bindings: new Map(method.parameters.map((parameter) => [parameter.name, parameter.type])),
|
|
1240
|
+
returnType: method.returnType }, filename, source, method.location);
|
|
1241
|
+
}
|
|
1242
|
+
return withParserRanges(declaration, { name: nodeLocation(node.constantPath, filename, source) });
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* Converts one exact typed-reader/initializer/freeze Ruby record profile.
|
|
1246
|
+
* @param {ClassNode} node - Prism class declaration.
|
|
1247
|
+
* @param {import("../semantic/types.js").RecordDeclaration} declaration - Predeclared nominal identity.
|
|
1248
|
+
* @param {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} recordNames - Nominal declarations by name.
|
|
1249
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Parser-owned comments.
|
|
1250
|
+
* @param {string} filename - Source filename.
|
|
1251
|
+
* @param {string} source - Complete source.
|
|
1252
|
+
* @returns {import("../semantic/types.js").RecordDeclaration} Semantic record.
|
|
1253
|
+
*/
|
|
1254
|
+
function convertRubyRecord(node, declaration, recordNames, comments, filename, source) {
|
|
1255
|
+
const location = nodeLocation(node, filename, source);
|
|
1256
|
+
const typeParameterNames = new Map((declaration.typeParameters ?? []).map((parameter) => [parameter.name, parameter]));
|
|
1257
|
+
if (!(node.constantPath instanceof ConstantReadNode) || node.superclass || node.inheritanceOperatorLoc) {
|
|
1258
|
+
return unsupportedSyntax("ruby", "record inheritance or qualified name", location);
|
|
1259
|
+
}
|
|
1260
|
+
const members = node.body instanceof StatementsNode ? node.body.body : [];
|
|
1261
|
+
const initializerIndex = members.findIndex((member) => member instanceof DefNode && member.name == "initialize");
|
|
1262
|
+
if (initializerIndex < 0 || initializerIndex != members.length - 1 || members.slice(0, initializerIndex).some((member) => !(member instanceof CallNode) || member.receiver || member.name != "attr_reader" || member.block ||
|
|
1263
|
+
member.arguments_?.arguments_.length != 1 || !(member.arguments_.arguments_[0] instanceof SymbolNode))) {
|
|
1264
|
+
return unsupportedSyntax("ruby", "record class body outside typed readers and one initializer", nodeLocation(members.find((member, index) => index >= initializerIndex + 1 || !(member instanceof CallNode) || member.name != "attr_reader") ?? node, filename, source));
|
|
1265
|
+
}
|
|
1266
|
+
const readerNodes = /** @type {CallNode[]} */ (members.slice(0, initializerIndex));
|
|
1267
|
+
declaration.fields = readerNodes.map((reader) => {
|
|
1268
|
+
const symbol = /** @type {SymbolNode} */ (reader.arguments_?.arguments_[0]);
|
|
1269
|
+
const metadata = associatedComments(comments, reader, source).map((comment) => commentTokens(comment, filename, source));
|
|
1270
|
+
const typeMetadata = metadata.filter(([token]) => token?.text == "@type");
|
|
1271
|
+
const fieldLocation = nodeLocation(reader, filename, source);
|
|
1272
|
+
if (typeMetadata.length != 1 || typeMetadata[0].length < 2 || metadata.some(([token]) => token?.text?.startsWith("@type") && token.text != "@type")) {
|
|
1273
|
+
return unsupportedSyntax("ruby", "missing or malformed record reader type", fieldLocation);
|
|
1274
|
+
}
|
|
1275
|
+
const declaredType = joinedCommentToken(typeMetadata[0], 1, source);
|
|
1276
|
+
const field = {
|
|
1277
|
+
kind: /** @type {const} */ ("RecordField"),
|
|
1278
|
+
location: fieldLocation,
|
|
1279
|
+
name: symbol.unescaped.value,
|
|
1280
|
+
type: convertType(declaredType.sourceType, `Record field '${symbol.unescaped.value}'`, fieldLocation, source, declaredType.location, recordNames, typeParameterNames)
|
|
1281
|
+
};
|
|
1282
|
+
return withParserRanges(field, { name: symbol.valueLoc ? prismLocation(symbol.valueLoc, filename, source) : fieldLocation });
|
|
1283
|
+
});
|
|
1284
|
+
const initializer = /** @type {DefNode} */ (members[initializerIndex]);
|
|
1285
|
+
const parameterList = initializer.parameters;
|
|
1286
|
+
const parameters = parameterList?.requireds ?? [];
|
|
1287
|
+
const invalidParameter = parameterList && [parameterList.optionals[0], parameterList.rest, parameterList.posts[0],
|
|
1288
|
+
parameterList.keywords[0], parameterList.keywordRest, parameterList.block].find(Boolean);
|
|
1289
|
+
const initializerStatements = initializer.body instanceof StatementsNode ? initializer.body.body : [];
|
|
1290
|
+
if (initializer.receiver || invalidParameter || parameters.length != declaration.fields.length ||
|
|
1291
|
+
parameters.some((parameter, index) => !(parameter instanceof RequiredParameterNode) || parameter.name != declaration.fields[index].name) ||
|
|
1292
|
+
initializerStatements.length != declaration.fields.length + 1) {
|
|
1293
|
+
return unsupportedSyntax("ruby", "noncanonical record initializer", nodeLocation(initializer, filename, source));
|
|
1294
|
+
}
|
|
1295
|
+
const annotations = typeComments(comments, initializer, filename, source);
|
|
1296
|
+
if (annotations.returnType || annotations.parameters.size != declaration.fields.length) {
|
|
1297
|
+
return unsupportedSyntax("ruby", "incomplete record initializer annotations", nodeLocation(initializer, filename, source));
|
|
1298
|
+
}
|
|
1299
|
+
for (let index = 0; index < declaration.fields.length; index += 1) {
|
|
1300
|
+
const field = declaration.fields[index];
|
|
1301
|
+
const parameter = /** @type {RequiredParameterNode} */ (parameters[index]);
|
|
1302
|
+
const assignment = initializerStatements[index];
|
|
1303
|
+
const annotated = annotations.parameters.get(parameter.name);
|
|
1304
|
+
if (!(assignment instanceof InstanceVariableWriteNode) || assignment.name != `@${field.name}` ||
|
|
1305
|
+
!(assignment.value instanceof LocalVariableReadNode) || assignment.value.name != field.name || !annotated) {
|
|
1306
|
+
return unsupportedSyntax("ruby", "record field not initialized exactly once", nodeLocation(assignment ?? initializer, filename, source));
|
|
1307
|
+
}
|
|
1308
|
+
const parameterType = convertType(annotated.sourceType, `Record initializer parameter '${parameter.name}'`, nodeLocation(parameter, filename, source), source, annotated.location, recordNames, typeParameterNames);
|
|
1309
|
+
if (!sameValueType(parameterType, field.type)) {
|
|
1310
|
+
return unsupportedSyntax("ruby", "record reader/initializer type mismatch", annotated.location);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
const freeze = initializerStatements.at(-1);
|
|
1314
|
+
if (!isRubyRecordFreeze(freeze)) {
|
|
1315
|
+
return unsupportedSyntax("ruby", "record initializer without final freeze", nodeLocation(freeze ?? initializer, filename, source));
|
|
1316
|
+
}
|
|
1317
|
+
return withParserRanges(declaration, { name: nodeLocation(node.constantPath, filename, source) });
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* Recognizes canonical source freezing or the generated root-owned Kernel implementation binding.
|
|
1321
|
+
* @param {import("@ruby/prism").Node | undefined} node - Final initializer statement.
|
|
1322
|
+
* @returns {boolean} Whether the statement owns the native record-freeze operation.
|
|
1323
|
+
*/
|
|
1324
|
+
function isRubyRecordFreeze(node) {
|
|
1325
|
+
if (!(node instanceof CallNode) || node.block)
|
|
1326
|
+
return false;
|
|
1327
|
+
if (!node.receiver)
|
|
1328
|
+
return node.name == "freeze" && !node.arguments_;
|
|
1329
|
+
if (node.name != "bind_call" || !node.callOperatorLoc || node.arguments_?.arguments_.length != 1 ||
|
|
1330
|
+
!(node.arguments_.arguments_[0] instanceof SelfNode) || !(node.receiver instanceof CallNode))
|
|
1331
|
+
return false;
|
|
1332
|
+
const method = node.receiver;
|
|
1333
|
+
if (method.name != "instance_method" || !method.callOperatorLoc || method.block ||
|
|
1334
|
+
method.arguments_?.arguments_.length != 1 || !(method.arguments_.arguments_[0] instanceof SymbolNode) ||
|
|
1335
|
+
!(method.receiver instanceof ConstantPathNode))
|
|
1336
|
+
return false;
|
|
1337
|
+
return method.receiver.parent == null && method.receiver.delimiterLoc != null && method.receiver.name == "Kernel" &&
|
|
1338
|
+
method.arguments_.arguments_[0].unescaped.value == "freeze";
|
|
417
1339
|
}
|
|
418
1340
|
/**
|
|
419
1341
|
* Converts the existing Ruby if/else terminal with restricted branch prefixes.
|
|
420
|
-
* @param {IfNode} node - Prism
|
|
1342
|
+
* @param {IfNode | UnlessNode} node - Prism conditional node.
|
|
421
1343
|
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
422
|
-
* @param {
|
|
1344
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
423
1345
|
* @param {string} filename - Source filename.
|
|
424
1346
|
* @param {string} source - Complete source.
|
|
425
1347
|
* @returns {import("../semantic/types.js").IfStatement} Semantic branch.
|
|
426
1348
|
*/
|
|
427
|
-
function convertIf(node, comments,
|
|
1349
|
+
function convertIf(node, comments, context, filename, source) {
|
|
428
1350
|
const location = nodeLocation(node, filename, source);
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
1351
|
+
const keywordLocation = node instanceof UnlessNode ? node.keywordLoc : node.ifKeywordLoc;
|
|
1352
|
+
if (!keywordLocation || keywordLocation.startOffset != node.location.startOffset) {
|
|
1353
|
+
return unsupportedSyntax("ruby", "modifier conditional", keywordLocation
|
|
1354
|
+
? prismLocation(keywordLocation, filename, source)
|
|
432
1355
|
: location);
|
|
433
1356
|
}
|
|
434
|
-
|
|
1357
|
+
if (node.predicate instanceof LocalVariableReadNode &&
|
|
1358
|
+
context.bindings.get(node.predicate.name)?.kind == "OptionalType") {
|
|
1359
|
+
return unsupportedSyntax("ruby", "optional truthiness condition", nodeLocation(node.predicate, filename, source));
|
|
1360
|
+
}
|
|
1361
|
+
if (node instanceof UnlessNode && !exactNilTest(node.predicate, source)) {
|
|
1362
|
+
return unsupportedSyntax("ruby", "unless condition other than an exact nil? presence guard", nodeLocation(node.predicate, filename, source));
|
|
1363
|
+
}
|
|
1364
|
+
const predicate = convertExpression(node.predicate, filename, source, context);
|
|
1365
|
+
const condition = node instanceof UnlessNode && predicate.kind == "UnaryExpression" &&
|
|
1366
|
+
predicate.operand.kind == "OptionalIsPresent"
|
|
1367
|
+
? predicate.operand
|
|
1368
|
+
: predicate;
|
|
1369
|
+
if (node instanceof UnlessNode && condition.kind != "OptionalIsPresent") {
|
|
1370
|
+
return unsupportedSyntax("ruby", "unless condition other than an exact nil? presence guard", nodeLocation(node.predicate, filename, source));
|
|
1371
|
+
}
|
|
1372
|
+
const consequentContext = { ...context, bindings: new Map(context.bindings) };
|
|
1373
|
+
const alternateContext = { ...context, bindings: new Map(context.bindings) };
|
|
435
1374
|
let alternate;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (
|
|
439
|
-
alternate = convertBlock(
|
|
1375
|
+
const subsequent = node instanceof UnlessNode ? node.elseClause : node.subsequent;
|
|
1376
|
+
if (subsequent) {
|
|
1377
|
+
if (subsequent instanceof ElseNode) {
|
|
1378
|
+
alternate = convertBlock(subsequent.statements, comments, alternateContext, filename, source, nodeLocation(subsequent, filename, source));
|
|
440
1379
|
}
|
|
441
|
-
else if (
|
|
1380
|
+
else if (subsequent instanceof IfNode) {
|
|
442
1381
|
alternate = {
|
|
443
1382
|
kind: /** @type {const} */ ("Block"),
|
|
444
|
-
location: nodeLocation(
|
|
445
|
-
statements: [convertIf(
|
|
1383
|
+
location: nodeLocation(subsequent, filename, source),
|
|
1384
|
+
statements: [convertIf(subsequent, comments, alternateContext, filename, source)]
|
|
446
1385
|
};
|
|
447
1386
|
}
|
|
448
1387
|
else
|
|
449
|
-
return unsupportedSyntax("ruby",
|
|
1388
|
+
return unsupportedSyntax("ruby", subsequent.constructor.name, nodeLocation(subsequent, filename, source));
|
|
450
1389
|
}
|
|
451
1390
|
return {
|
|
452
1391
|
...(alternate ? { alternate } : {}),
|
|
453
|
-
condition
|
|
454
|
-
consequent: convertBlock(node.statements, comments,
|
|
1392
|
+
condition,
|
|
1393
|
+
consequent: convertBlock(node.statements, comments, consequentContext, filename, source, location),
|
|
455
1394
|
kind: "IfStatement",
|
|
456
1395
|
location
|
|
457
1396
|
};
|
|
458
1397
|
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Converts one ordinary block-form Ruby pre-condition loop.
|
|
1400
|
+
* @param {WhileNode} node - Prism while node.
|
|
1401
|
+
* @param {import("@ruby/prism/src/deserialize.js").Comment[]} comments - Prism comments.
|
|
1402
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
1403
|
+
* @param {string} filename - Source filename.
|
|
1404
|
+
* @param {string} source - Complete source.
|
|
1405
|
+
* @returns {import("../semantic/types.js").WhileStatement} Semantic loop.
|
|
1406
|
+
*/
|
|
1407
|
+
function convertWhile(node, comments, context, filename, source) {
|
|
1408
|
+
const location = nodeLocation(node, filename, source);
|
|
1409
|
+
const keywordLocation = prismLocation(node.keywordLoc, filename, source);
|
|
1410
|
+
if (node.isBeginModifier() || !node.closingLoc || node.keywordLoc.startOffset != node.location.startOffset) {
|
|
1411
|
+
return unsupportedSyntax("ruby", "modifier while", keywordLocation);
|
|
1412
|
+
}
|
|
1413
|
+
const bodyContext = { ...context, bindings: new Map(context.bindings) };
|
|
1414
|
+
return withParserRanges({
|
|
1415
|
+
body: convertBlock(node.statements, comments, bodyContext, filename, source, location),
|
|
1416
|
+
condition: convertExpression(node.predicate, filename, source, context, undefined, true),
|
|
1417
|
+
kind: /** @type {const} */ ("WhileStatement"),
|
|
1418
|
+
location
|
|
1419
|
+
}, { keyword: keywordLocation });
|
|
1420
|
+
}
|
|
459
1421
|
/**
|
|
460
1422
|
* Converts the supported Ruby puts entry point.
|
|
461
1423
|
* @param {import("@ruby/prism").Node} node - Prism node.
|
|
462
1424
|
* @param {string} filename - Source filename.
|
|
463
1425
|
* @param {string} source - Complete source.
|
|
1426
|
+
* @param {RubyConversionContext} context - Typed lexical conversion context.
|
|
464
1427
|
* @returns {import("../semantic/types.js").PrintStatement} Print statement.
|
|
465
1428
|
*/
|
|
466
|
-
function convertPrint(node, filename, source) {
|
|
1429
|
+
function convertPrint(node, filename, source, context) {
|
|
467
1430
|
const location = nodeLocation(node, filename, source);
|
|
468
1431
|
if (!(node instanceof CallNode) || node.receiver || node.name != "puts" || node.arguments_?.arguments_.length != 1) {
|
|
469
1432
|
return unsupportedSyntax("ruby", node.constructor.name, location);
|
|
470
1433
|
}
|
|
471
|
-
return { expression: convertExpression(node.arguments_.arguments_[0], filename, source), kind: "PrintStatement", location };
|
|
1434
|
+
return { expression: convertExpression(node.arguments_.arguments_[0], filename, source, context), kind: "PrintStatement", location };
|
|
472
1435
|
}
|
|
473
1436
|
/**
|
|
474
1437
|
* Parses Ruby into the shared semantic module.
|
|
475
1438
|
* @param {object} input - Parser input.
|
|
476
1439
|
* @param {string} input.filename - Source filename.
|
|
477
1440
|
* @param {string} input.source - Source text.
|
|
1441
|
+
* @param {readonly import("../semantic/types.js").EffectCapabilityDeclaration[]} [input.capabilities] - Compiler-authorized declarations.
|
|
1442
|
+
* @param {{isEntry: boolean, classes?: Map<string, import("../semantic/types.js").ClassDeclaration>, functions: Map<string, import("../semantic/types.js").FunctionDeclaration>, records: Map<string, import("../semantic/types.js").RecordDeclaration>, errors?: Map<string, import("../semantic/types.js").ErrorDeclaration>}} [input.program] - Resolved program imports and entry role.
|
|
478
1443
|
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
479
1444
|
*/
|
|
480
|
-
export function parseRuby({ filename, source }) {
|
|
1445
|
+
export function parseRuby({ capabilities = [], filename, source, program }) {
|
|
481
1446
|
const result = parsePrism(source, { filepath: filename });
|
|
482
1447
|
if (result.errors.length > 0) {
|
|
483
1448
|
const error = result.errors[0];
|
|
@@ -486,21 +1451,107 @@ export function parseRuby({ filename, source }) {
|
|
|
486
1451
|
}
|
|
487
1452
|
if (!(result.value instanceof ProgramNode))
|
|
488
1453
|
throw new Error("Prism returned a non-program root.");
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
1454
|
+
let body = task034RubyBody(result.value.statements.body, result.comments, capabilities, filename, source);
|
|
1455
|
+
if (program) {
|
|
1456
|
+
inspectRubyModule({ filename, source });
|
|
1457
|
+
const moduleNode = /** @type {ModuleNode} */ (body.find((node) => node instanceof ModuleNode));
|
|
1458
|
+
body = moduleNode.body instanceof StatementsNode ? moduleNode.body.body : [];
|
|
1459
|
+
const moduleFunctionNodes = body.filter(isModuleFunctionMarker);
|
|
1460
|
+
const definitions = body.filter((node) => node instanceof DefNode);
|
|
1461
|
+
if (definitions.length > 0 && (moduleFunctionNodes.length != 1 || body.indexOf(moduleFunctionNodes[0]) > body.indexOf(definitions[0]))) {
|
|
1462
|
+
return unsupportedSyntax("ruby", "module functions outside one leading module_function profile", nodeLocation(moduleFunctionNodes[1] ?? definitions[0], filename, source));
|
|
1463
|
+
}
|
|
1464
|
+
body = body.filter((node) => !isModuleFunctionMarker(node) && !rubyVisibilityMarker(node));
|
|
1465
|
+
}
|
|
1466
|
+
const classNodes = body.filter((node) => node instanceof ClassNode);
|
|
1467
|
+
const errorNodes = classNodes.filter((node) => node.superclass instanceof ConstantReadNode && node.superclass.name == "StandardError");
|
|
1468
|
+
const referenceClassNodes = classNodes.filter((node) => !errorNodes.includes(node) && node.body instanceof StatementsNode &&
|
|
1469
|
+
node.body.body.length > 0 && node.body.body.every((member) => member instanceof DefNode));
|
|
1470
|
+
const recordNodes = classNodes.filter((node) => !errorNodes.includes(node) && !referenceClassNodes.includes(node));
|
|
1471
|
+
const errorDeclarations = errorNodes.map((node, index) => ({
|
|
1472
|
+
id: `error:${index}`,
|
|
1473
|
+
kind: /** @type {const} */ ("ErrorDeclaration"),
|
|
1474
|
+
location: nodeLocation(node, filename, source),
|
|
1475
|
+
name: node.name
|
|
1476
|
+
}));
|
|
1477
|
+
const recordDeclarations = recordNodes.map((node, index) => {
|
|
1478
|
+
const id = `record:${index}`;
|
|
1479
|
+
const documented = typeComments(result.comments, node, filename, source, id);
|
|
1480
|
+
if (documented.parameters.size || documented.returnType) {
|
|
1481
|
+
return unsupportedSyntax("ruby", "function type annotation on record declaration", nodeLocation(node, filename, source));
|
|
1482
|
+
}
|
|
1483
|
+
return {
|
|
1484
|
+
fields: [],
|
|
1485
|
+
id,
|
|
1486
|
+
kind: /** @type {const} */ ("RecordDeclaration"),
|
|
1487
|
+
location: nodeLocation(node, filename, source),
|
|
1488
|
+
name: node.name,
|
|
1489
|
+
...(documented.typeParameters ? { typeParameters: documented.typeParameters } : {})
|
|
1490
|
+
};
|
|
1491
|
+
});
|
|
1492
|
+
const classDeclarations = referenceClassNodes.map((node, index) => ({
|
|
1493
|
+
constructor: /** @type {import("../semantic/types.js").ConstructorDeclaration} */ ({}), fields: [], id: `class:${index}`,
|
|
1494
|
+
kind: /** @type {const} */ ("ClassDeclaration"), location: nodeLocation(node, filename, source), methods: [], name: node.name
|
|
1495
|
+
}));
|
|
1496
|
+
const reopened = classDeclarations.find((declaration, index) => classDeclarations.findIndex((candidate) => candidate.name == declaration.name) != index);
|
|
1497
|
+
if (reopened)
|
|
1498
|
+
return unsupportedSyntax("ruby", `reference class reopening '${reopened.name}'`, reopened.location);
|
|
1499
|
+
const recordNames = /** @type {Map<string, import("../semantic/types.js").RecordDeclaration | import("../semantic/types.js").ClassDeclaration | import("../semantic/types.js").EffectResourceDeclaration>} */ (new Map(program?.records ?? []));
|
|
1500
|
+
for (const [name, declaration] of program?.classes ?? [])
|
|
1501
|
+
recordNames.set(name, declaration);
|
|
1502
|
+
for (const resource of capabilities.flatMap(({ resources }) => resources))
|
|
1503
|
+
recordNames.set(resource.name, resource);
|
|
1504
|
+
const errorNames = new Map(program?.errors ?? []);
|
|
1505
|
+
for (const failure of capabilities.flatMap(({ failures }) => failures)) {
|
|
1506
|
+
errorNames.set(failure.name, /** @type {import("../semantic/types.js").ErrorDeclaration} */ ( /** @type {unknown} */(failure)));
|
|
1507
|
+
}
|
|
1508
|
+
for (const declaration of errorDeclarations)
|
|
1509
|
+
errorNames.set(declaration.name, declaration);
|
|
1510
|
+
const errorsById = new Map([...errorNames.values()].map((declaration) => [/** @type {string} */ (declaration.id), declaration]));
|
|
1511
|
+
const errors = errorNodes.map((node, index) => convertRubyError(node, errorDeclarations[index], filename, source));
|
|
1512
|
+
for (const declaration of recordDeclarations)
|
|
1513
|
+
recordNames.set(declaration.name, declaration);
|
|
1514
|
+
for (const declaration of classDeclarations)
|
|
1515
|
+
recordNames.set(declaration.name, declaration);
|
|
1516
|
+
const recordsById = new Map(recordDeclarations.map((declaration) => [/** @type {string} */ (declaration.id), declaration]));
|
|
1517
|
+
const classesById = new Map([
|
|
1518
|
+
...[...program?.classes?.values() ?? []].map((declaration) => /** @type {[string, import("../semantic/types.js").ClassDeclaration]} */ ([/** @type {string} */ (declaration.id), declaration])),
|
|
1519
|
+
...classDeclarations.map((declaration) => /** @type {[string, import("../semantic/types.js").ClassDeclaration]} */ ([/** @type {string} */ (declaration.id), declaration]))
|
|
1520
|
+
]);
|
|
1521
|
+
const functionNodes = body.filter((node) => node instanceof DefNode);
|
|
1522
|
+
const allowsBuiltinOutput = capabilities.some(({ operations }) => operations.some(({ name }) => name == "v1_write_line"));
|
|
1523
|
+
const signatures = functionNodes.map((node, index) => convertFunctionSignature(node, result.comments, filename, source, recordNames, `function:${index}`, allowsBuiltinOutput));
|
|
1524
|
+
const functionSignatures = new Map([...capabilityFunctionSignatures(capabilities, moduleLocation(filename, source)),
|
|
1525
|
+
...(program?.functions ?? [])].map(([localName, declaration]) => [localName, {
|
|
1526
|
+
location: declaration.location,
|
|
1527
|
+
name: localName,
|
|
1528
|
+
nameLocation: declaration.location,
|
|
1529
|
+
parameters: declaration.parameters,
|
|
1530
|
+
returnType: declaration.returnType,
|
|
1531
|
+
...(declaration.typeParameters ? { typeParameters: declaration.typeParameters } : {})
|
|
1532
|
+
}]));
|
|
1533
|
+
for (const signature of signatures)
|
|
1534
|
+
functionSignatures.set(signature.name, signature);
|
|
1535
|
+
const records = recordNodes.map((node, index) => convertRubyRecord(node, recordDeclarations[index], recordNames, result.comments, filename, source));
|
|
1536
|
+
const classes = referenceClassNodes.map((node, index) => convertRubyReferenceClass(node, classDeclarations[index], recordNames, recordsById, classesById, functionSignatures, errorNames, errorsById, result.comments, filename, source));
|
|
1537
|
+
const functions = functionNodes.map((node, index) => convertFunction(node, signatures[index], functionSignatures, recordNames, recordsById, classesById, errorNames, errorsById, result.comments, filename, source));
|
|
1538
|
+
const entryNodes = body.filter((node) => !(node instanceof DefNode) && !(node instanceof ClassNode));
|
|
493
1539
|
const location = moduleLocation(filename, source);
|
|
494
|
-
if (
|
|
495
|
-
return unsupportedSyntax("ruby", "
|
|
1540
|
+
if (program && !program.isEntry && entryNodes.length > 0) {
|
|
1541
|
+
return unsupportedSyntax("ruby", "top-level side effect outside the selected entry module", nodeLocation(entryNodes[0], filename, source));
|
|
1542
|
+
}
|
|
496
1543
|
const firstEntry = entryNodes[0];
|
|
497
1544
|
const entryLocation = firstEntry ? locationFromOffsets(filename, source, utf8ByteOffsetToUtf16Offset(source, firstEntry.location.startOffset), utf8ByteOffsetToUtf16Offset(source, (entryNodes.at(-1)?.location.startOffset ?? 0) + (entryNodes.at(-1)?.location.length ?? 0))) : location;
|
|
498
|
-
const
|
|
1545
|
+
const entryContext = { bindings: new Map(), classes: classesById, errorNames, errors: errorsById, functions: functionSignatures,
|
|
1546
|
+
orderedMapDeclarations: orderedMapDeclarationsForRuby(entryNodes), recordNames, records: recordsById };
|
|
499
1547
|
const entryBlock = {
|
|
500
1548
|
kind: /** @type {const} */ ("Block"),
|
|
501
1549
|
location: entryLocation,
|
|
502
|
-
statements: entryNodes.map((statement) => convertStatement(statement, result.comments,
|
|
1550
|
+
statements: entryNodes.map((statement) => convertStatement(statement, result.comments, entryContext, filename, source))
|
|
503
1551
|
};
|
|
1552
|
+
if (!program && functions.length == 0 && capabilities.length == 0 && !blockReferencesProtectedEntry(entryBlock)) {
|
|
1553
|
+
return unsupportedSyntax("ruby", "module without a function", location);
|
|
1554
|
+
}
|
|
504
1555
|
return {
|
|
505
1556
|
entryPoint: {
|
|
506
1557
|
body: entryBlock,
|
|
@@ -509,7 +1560,301 @@ export function parseRuby({ filename, source }) {
|
|
|
509
1560
|
},
|
|
510
1561
|
functions,
|
|
511
1562
|
kind: "Module",
|
|
512
|
-
location
|
|
1563
|
+
location,
|
|
1564
|
+
...(classes.length > 0 ? { classes } : {}),
|
|
1565
|
+
...(errors.length > 0 ? { errors } : {}),
|
|
1566
|
+
...(records.length > 0 ? { records } : {})
|
|
513
1567
|
};
|
|
514
1568
|
}
|
|
515
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVieS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvcnVieS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUNMLE9BQU8sRUFDUCxRQUFRLEVBQ1IsT0FBTyxFQUNQLFFBQVEsRUFDUixTQUFTLEVBQ1QsTUFBTSxFQUNOLFdBQVcsRUFDWCxzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixNQUFNLEVBQ04sZUFBZSxFQUNmLFdBQVcsRUFDWCxxQkFBcUIsRUFDckIsVUFBVSxFQUNWLGNBQWMsRUFDZCxVQUFVLEVBQ1YsUUFBUSxFQUNSLFNBQVMsRUFDVixNQUFNLGFBQWEsQ0FBQTtBQUNwQixPQUFPLEVBQUMsV0FBVyxFQUFFLHFCQUFxQixFQUFFLGlCQUFpQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEYsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGNBQWMsRUFBRSwyQkFBMkIsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQ3hHLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDBCQUEwQixDQUFBO0FBQzdELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDJCQUEyQixDQUFBO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyx1QkFBdUIsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUNwRCxNQUFNLFVBQVUsR0FBRyxNQUFNLFNBQVMsRUFBRSxDQUFBO0FBQ3BDLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDbkMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO0lBQ1osQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQztJQUNqQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUM7SUFDZixDQUFDLElBQUksRUFBRSxVQUFVLENBQUM7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SUFBSSxDQUFDLENBQUMsQ0FDM0YsQ0FDRixDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUE7SUFDWixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO0lBQzlCLE1BQU0sVUFBVSxHQUFHO1FBQ2pCLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNwQyxRQUFRLEVBQUUsYUFBYTtRQUN2QixVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUN4SCxDQUFBO0lBRUQsT0FBTztRQUNMLFVBQVUsRUFBRTtZQUNWLElBQUksRUFBRSxVQUFVO1lBQ2hCLElBQUksRUFBRSxZQUFZO1lBQ2xCLFFBQVEsRUFBRSxhQUFhO1NBQ3hCO1FBQ0QsU0FBUztRQUNULElBQUksRUFBRSxRQUFRO1FBQ2QsUUFBUTtLQUNULENBQUE7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7XG4gIEFuZE5vZGUsXG4gIENhbGxOb2RlLFxuICBEZWZOb2RlLFxuICBFbHNlTm9kZSxcbiAgRmFsc2VOb2RlLFxuICBJZk5vZGUsXG4gIEludGVnZXJOb2RlLFxuICBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlLFxuICBMb2NhbFZhcmlhYmxlUmVhZE5vZGUsXG4gIExvY2FsVmFyaWFibGVXcml0ZU5vZGUsXG4gIE9yTm9kZSxcbiAgUGFyZW50aGVzZXNOb2RlLFxuICBQcm9ncmFtTm9kZSxcbiAgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlLFxuICBSZXR1cm5Ob2RlLFxuICBTdGF0ZW1lbnRzTm9kZSxcbiAgU3RyaW5nTm9kZSxcbiAgVHJ1ZU5vZGUsXG4gIGxvYWRQcmlzbVxufSBmcm9tIFwiQHJ1YnkvcHJpc21cIlxuaW1wb3J0IHttaXNzaW5nVHlwZSwgU2VtYW50aWZvbGREaWFnbm9zdGljLCB1bnN1cHBvcnRlZFN5bnRheH0gZnJvbSBcIi4uL2RpYWdub3N0aWMuanNcIlxuaW1wb3J0IHtsb2NhdGlvbkZyb21PZmZzZXRzLCBtb2R1bGVMb2NhdGlvbiwgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0fSBmcm9tIFwiLi4vc2VtYW50aWMvbG9jYXRpb24uanNcIlxuaW1wb3J0IHt3aXRoQWRhcHRlZE9wZXJhdGlvbn0gZnJvbSBcIi4uL3NlbWFudGljL29wZXJhdG9ycy5qc1wiXG5pbXBvcnQge3dpdGhQYXJzZXJSYW5nZXN9IGZyb20gXCIuLi9zZW1hbnRpYy9wcm92ZW5hbmNlLmpzXCJcbmltcG9ydCB7aGFzT25seVVuaWNvZGVTY2FsYXJzfSBmcm9tIFwiLi4vc2VtYW50aWMvc2NhbGFycy5qc1wiXG5pbXBvcnQge3JlcXVpcmVTb3VyY2VTY2FsYXJUeXBlfSBmcm9tIFwiLi9zY2FsYXJzLmpzXCJcbmNvbnN0IHBhcnNlUHJpc20gPSBhd2FpdCBsb2FkUHJpc20oKVxuY29uc3QgcnVieUJpbmFyeU9wZXJhdGlvbnMgPSBuZXcgTWFwKFtcbiAgW1wiK1wiLCBcIkFkZFwiXSxcbiAgW1wiLVwiLCBcIlN1YnRyYWN0XCJdLFxuICBbXCIqXCIsIFwiTXVsdGlwbHlcIl0sXG4gIFtcIj09XCIsIFwiRXF1YWxcIl0sXG4gIFtcIiE9XCIsIFwiTm90RXF1YWxcIl0sXG4gIFtcIjxcIiwgXCJMZXNzVGhhblwiXSxcbiAgW1wiPD1cIiwgXCJMZXNzVGhhbk9yRXF1YWxcIl0sXG4gIFtcIj5cIiwgXCJHcmVhdGVyVGhhblwiXSxcbiAgW1wiPj1cIiwgXCJHcmVhdGVyVGhhbk9yRXF1YWxcIl1cbl0pXG5cbi8qKlxuICogUmV0dXJucyBhIG5vcm1hbGl6ZWQgUHJpc20gbm9kZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7e2xvY2F0aW9uOiBpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Mb2NhdGlvbn19IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gU291cmNlIGxvY2F0aW9uLlxuICovXG5mdW5jdGlvbiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICByZXR1cm4gcHJpc21Mb2NhdGlvbihub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgUHJpc20gbG9jYXRpb24gaW50byBhIG5vcm1hbGl6ZWQgc291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Mb2NhdGlvbn0gbG9jYXRpb24gLSBQcmlzbSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IFNvdXJjZSBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gcHJpc21Mb2NhdGlvbihsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICByZXR1cm4gbG9jYXRpb25Gcm9tT2Zmc2V0cyhcbiAgICBmaWxlbmFtZSxcbiAgICBzb3VyY2UsXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgbG9jYXRpb24uc3RhcnRPZmZzZXQpLFxuICAgIHV0ZjhCeXRlT2Zmc2V0VG9VdGYxNk9mZnNldChzb3VyY2UsIGxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgbG9jYXRpb24ubGVuZ3RoKVxuICApXG59XG5cbi8qKlxuICogU2xpY2VzIEphdmFTY3JpcHQgc291cmNlIHVzaW5nIFByaXNtJ3MgVVRGLTggYnl0ZSBvZmZzZXRzLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydE9mZnNldCAtIEluY2x1c2l2ZSBQcmlzbSBieXRlIG9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmRPZmZzZXQgLSBFeGNsdXNpdmUgUHJpc20gYnl0ZSBvZmZzZXQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTb3VyY2UgdGV4dCBpbiB0aGUgYnl0ZSByYW5nZS5cbiAqL1xuZnVuY3Rpb24gc2xpY2VQcmlzbVNvdXJjZShzb3VyY2UsIHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQpIHtcbiAgcmV0dXJuIHNvdXJjZS5zbGljZShcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBzdGFydE9mZnNldCksXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgZW5kT2Zmc2V0KVxuICApXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdXBwb3J0ZWQgUHJpc20gZXhwcmVzc2lvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIFByaXNtIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IFNlbWFudGljIGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFeHByZXNzaW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFBhcmVudGhlc2VzTm9kZSAmJiBub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSAmJiBub2RlLmJvZHkuYm9keS5sZW5ndGggPT0gMSkge1xuICAgIHJldHVybiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmJvZHkuYm9keVswXSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbiwgbmFtZTogbm9kZS5uYW1lfSwge25hbWU6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW50ZWdlck5vZGUpIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKG5vZGUudmFsdWUpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibm9uLXNhZmUgaW50ZWdlciBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkludGVnZXJMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZSB8fCBub2RlIGluc3RhbmNlb2YgRmFsc2VOb2RlKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJvb2xlYW5MaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFN0cmluZ05vZGUpIHtcbiAgICBjb25zdCBkZWNvZGVkID0gbm9kZS51bmVzY2FwZWRcblxuICAgIGlmICghZGVjb2RlZC52YWxpZEVuY29kaW5nIHx8IGRlY29kZWQuZW5jb2RpbmcgIT0gXCJ1dGYtOFwiIHx8IG5vZGUuaXNGb3JjZWRCaW5hcnlFbmNvZGluZygpIHx8XG4gICAgICAhaGFzT25seVVuaWNvZGVTY2FsYXJzKGRlY29kZWQudmFsdWUpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW52YWxpZCBVbmljb2RlIHN0cmluZyBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuICAgIH1cblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTdHJpbmdMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IGRlY29kZWQudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW50ZXJwb2xhdGVkIHN0cmluZ1wiLCBsb2NhdGlvbilcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiIVwiKSB7XG4gICAgY29uc3Qgb3BlcmF0b3JMb2NhdGlvbiA9IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBpZiAobm9kZS5jYWxsT3BlcmF0b3JMb2MpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJxdWFsaWZpZWQgYm9vbGVhbiBub3RcIiwgb3BlcmF0b3JMb2NhdGlvbilcbiAgICBpZiAobm9kZS5tZXNzYWdlTG9jPy5sZW5ndGggIT0gMSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInByZWNlZGVuY2Utc2Vuc2l0aXZlIGJvb2xlYW4gbm90XCIsIG9wZXJhdG9yTG9jYXRpb24pXG4gICAgfVxuICAgIGlmIChub2RlLmFyZ3VtZW50c18pIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJib29sZWFuIG5vdCBhcmd1bWVudCBsaXN0XCIsIG9wZXJhdG9yTG9jYXRpb24pXG5cbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZDogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9LCB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259KSwgXCJOb3RcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiLUBcIikge1xuICAgIGNvbnN0IG9wZXJhdG9yTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgaWYgKG5vZGUuY2FsbE9wZXJhdG9yTG9jKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicXVhbGlmaWVkIGludGVnZXIgbmVnYXRpb25cIiwgb3BlcmF0b3JMb2NhdGlvbilcbiAgICBpZiAobm9kZS5hcmd1bWVudHNfKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW50ZWdlciBuZWdhdGlvbiBhcmd1bWVudCBsaXN0XCIsIG9wZXJhdG9yTG9jYXRpb24pXG5cbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZDogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9LCB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259KSwgXCJOZWdhdGVcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIEFuZE5vZGUgfHwgbm9kZSBpbnN0YW5jZW9mIE9yTm9kZSkge1xuICAgIGNvbnN0IG9wZXJhdG9yTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUub3BlcmF0b3JMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3Qgc291cmNlT3BlcmF0b3IgPSBzb3VyY2Uuc2xpY2Uob3BlcmF0b3JMb2NhdGlvbi5zdGFydC5vZmZzZXQsIG9wZXJhdG9yTG9jYXRpb24uZW5kLm9mZnNldClcblxuICAgIGlmIChzb3VyY2VPcGVyYXRvciAhPSBcIiYmXCIgJiYgc291cmNlT3BlcmF0b3IgIT0gXCJ8fFwiKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIGBwcmVjZWRlbmNlLXNlbnNpdGl2ZSBib29sZWFuICR7c291cmNlT3BlcmF0b3J9YCwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiQmluYXJ5RXhwcmVzc2lvblwiLFxuICAgICAgbGVmdDogY29udmVydEV4cHJlc3Npb24obm9kZS5sZWZ0LCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmlnaHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge29wZXJhdG9yOiBvcGVyYXRvckxvY2F0aW9ufSksIG5vZGUgaW5zdGFuY2VvZiBBbmROb2RlID8gXCJBbmRcIiA6IFwiT3JcIilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgcnVieUJpbmFyeU9wZXJhdGlvbnMuaGFzKG5vZGUubmFtZSkgJiYgbm9kZS5jYWxsT3BlcmF0b3JMb2MgJiZcbiAgICBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXG4gICAgICBcInJ1YnlcIixcbiAgICAgIGBxdWFsaWZpZWQgYmluYXJ5IG9wZXJhdG9yICR7bm9kZS5uYW1lfWAsXG4gICAgICBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIClcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgbm9kZS5yZWNlaXZlciAmJiBydWJ5QmluYXJ5T3BlcmF0aW9ucy5oYXMobm9kZS5uYW1lKSAmJiBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEpIHtcbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJCaW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsZWZ0OiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtvcGVyYXRvcjogcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSl9KSwgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbn0gKi8gKHJ1YnlCaW5hcnlPcGVyYXRpb25zLmdldChub2RlLm5hbWUpKSlcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259ICovICgvKiogQHR5cGUge3Vua25vd259ICovIChzZW1hbnRpYykpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFub2RlLnJlY2VpdmVyKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgYXJndW1lbnRzOiAobm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfID8/IFtdKS5tYXAoKGFyZ3VtZW50KSA9PiBjb252ZXJ0RXhwcmVzc2lvbihhcmd1bWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpLFxuICAgICAgY2FsbGVlOiBub2RlLm5hbWUsXG4gICAgICBraW5kOiBcIkNhbGxFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvblxuICAgIH0sIHtjYWxsZWU6IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCBsb2NhdGlvbilcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhwbGljaXQgUnVieSByZXR1cm4uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZXR1cm5TdGF0ZW1lbnR9IFNlbWFudGljIHJldHVybi5cbiAqL1xuZnVuY3Rpb24gY29udmVydFJldHVybihub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKCEobm9kZSBpbnN0YW5jZW9mIFJldHVybk5vZGUpIHx8IG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggIT0gMSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCBsb2NhdGlvbilcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZXhwcmVzc2lvbjogY29udmVydEV4cHJlc3Npb24obm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0sIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGtpbmQ6IFwiUmV0dXJuU3RhdGVtZW50XCIsXG4gICAgbG9jYXRpb25cbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIFByaXNtLW93bmVkIFJCUy1zdHlsZSB0eXBlIGNvbW1lbnRzIGRpcmVjdGx5IHByZWNlZGluZyBhIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTG9jYXRpb259fSBub2RlIC0gQ29tbWVudCBvd25lci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7e3BhcmFtZXRlcnM6IE1hcDxzdHJpbmcsIHtsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHNvdXJjZVR5cGU6IHN0cmluZ30+LCByZXR1cm5UeXBlOiB7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9IHwgdW5kZWZpbmVkfX0gRGVjbGFyZWQgdHlwZXMuXG4gKi9cbmZ1bmN0aW9uIHR5cGVDb21tZW50cyhjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBwcmVjZWRpbmcgPSBhc3NvY2lhdGVkQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVyVHlwZXMgPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHt7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9IHwgdW5kZWZpbmVkfSAqL1xuICBsZXQgcmV0dXJuVHlwZVxuXG4gIGZvciAoY29uc3QgY29tbWVudCBvZiBwcmVjZWRpbmcpIHtcbiAgICBjb25zdCB3b3JkcyA9IGNvbW1lbnRUb2tlbnMoY29tbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmICh3b3Jkc1swXT8udGV4dCA9PSBcIkBwYXJhbVwiICYmIHdvcmRzLmxlbmd0aCA9PSAzKSB7XG4gICAgICBwYXJhbWV0ZXJUeXBlcy5zZXQod29yZHNbMV0udGV4dCwge2xvY2F0aW9uOiB3b3Jkc1syXS5sb2NhdGlvbiwgc291cmNlVHlwZTogd29yZHNbMl0udGV4dH0pXG4gICAgfVxuICAgIGlmICh3b3Jkc1swXT8udGV4dCA9PSBcIkByZXR1cm5cIiAmJiB3b3Jkcy5sZW5ndGggPT0gMikge1xuICAgICAgcmV0dXJuVHlwZSA9IHtsb2NhdGlvbjogd29yZHNbMV0ubG9jYXRpb24sIHNvdXJjZVR5cGU6IHdvcmRzWzFdLnRleHR9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtwYXJhbWV0ZXJzOiBwYXJhbWV0ZXJUeXBlcywgcmV0dXJuVHlwZX1cbn1cblxuLyoqXG4gKiBMZXhlcyB3aGl0ZXNwYWNlLXNlcGFyYXRlZCBtZXRhZGF0YSB0b2tlbnMgaW5zaWRlIGEgUHJpc20tb3duZWQgUnVieSBjb21tZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudH0gY29tbWVudCAtIFByaXNtIGNvbW1lbnQgdG9rZW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHRleHQ6IHN0cmluZ31bXX0gTWV0YWRhdGEgdG9rZW5zLlxuICovXG5mdW5jdGlvbiBjb21tZW50VG9rZW5zKGNvbW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3Qgc3RhcnQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0KVxuICBjb25zdCBlbmQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGgpXG4gIGNvbnN0IHRva2VucyA9IFtdXG4gIGxldCBvZmZzZXQgPSBzdGFydCArIDFcblxuICB3aGlsZSAob2Zmc2V0IDwgZW5kKSB7XG4gICAgd2hpbGUgKG9mZnNldCA8IGVuZCAmJiBpc1J1YnlNZXRhZGF0YVdoaXRlc3BhY2Uoc291cmNlW29mZnNldF0pKSBvZmZzZXQrK1xuICAgIGNvbnN0IHRva2VuU3RhcnQgPSBvZmZzZXRcblxuICAgIHdoaWxlIChvZmZzZXQgPCBlbmQgJiYgIWlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShzb3VyY2Vbb2Zmc2V0XSkpIG9mZnNldCsrXG4gICAgaWYgKHRva2VuU3RhcnQgPCBvZmZzZXQpIHtcbiAgICAgIHRva2Vucy5wdXNoKHtsb2NhdGlvbjogbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCB0b2tlblN0YXJ0LCBvZmZzZXQpLCB0ZXh0OiBzb3VyY2Uuc2xpY2UodG9rZW5TdGFydCwgb2Zmc2V0KX0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRva2Vuc1xufVxuXG4vKipcbiAqIENoZWNrcyBvbmUgUnVieSBtZXRhZGF0YSBzZXBhcmF0b3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhcmFjdGVyIC0gU291cmNlIGNoYXJhY3Rlci5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGl0IHNlcGFyYXRlcyBtZXRhZGF0YSB0b2tlbnMuXG4gKi9cbmZ1bmN0aW9uIGlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShjaGFyYWN0ZXIpIHtcbiAgcmV0dXJuIGNoYXJhY3RlciA9PSBcIiBcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHRcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXG5cIlxufVxuXG4vKipcbiAqIFNlbGVjdHMgb25seSB0aGUgY29udGlndW91cyBjb21tZW50IGJsb2NrIGltbWVkaWF0ZWx5IGJlZm9yZSBhIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTG9jYXRpb259fSBub2RlIC0gQ29tbWVudCBvd25lci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiQHJ1YnkvcHJpc20vc3JjL2Rlc2VyaWFsaXplLmpzXCIpLkNvbW1lbnRbXX0gQXNzb2NpYXRlZCBjb21tZW50cy5cbiAqL1xuZnVuY3Rpb24gYXNzb2NpYXRlZENvbW1lbnRzKGNvbW1lbnRzLCBub2RlLCBzb3VyY2UpIHtcbiAgY29uc3QgcHJlY2VkaW5nID0gY29tbWVudHMuZmlsdGVyKChjb21tZW50KSA9PiBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0IDwgbm9kZS5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgICAuc29ydCgobGVmdCwgcmlnaHQpID0+IGxlZnQubG9jYXRpb24uc3RhcnRPZmZzZXQgLSByaWdodC5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgY29uc3QgYXNzb2NpYXRlZCA9IFtdXG4gIGxldCBib3VuZGFyeSA9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXRcblxuICBmb3IgKGxldCBpbmRleCA9IHByZWNlZGluZy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgY29uc3QgY29tbWVudCA9IHByZWNlZGluZ1tpbmRleF1cbiAgICBjb25zdCBlbmRPZmZzZXQgPSBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGhcbiAgICBjb25zdCBnYXAgPSBzbGljZVByaXNtU291cmNlKHNvdXJjZSwgZW5kT2Zmc2V0LCBib3VuZGFyeSlcblxuICAgIGlmICghaXNJbW1lZGlhdGVDb21tZW50R2FwKGdhcCkpIGJyZWFrXG5cbiAgICBhc3NvY2lhdGVkLnVuc2hpZnQoY29tbWVudClcbiAgICBib3VuZGFyeSA9IGNvbW1lbnQubG9jYXRpb24uc3RhcnRPZmZzZXRcbiAgfVxuXG4gIHJldHVybiBhc3NvY2lhdGVkXG59XG5cbi8qKlxuICogUmVhZHMgb25lIGV4YWN0IFJ1YnkgbG9jYWwgdHlwZSBjYXJyaWVyIGFuZCBpbW11dGFiaWxpdHkgbWFya2VyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtMb2NhbFZhcmlhYmxlV3JpdGVOb2RlfSBub2RlIC0gTG9jYWwgd3JpdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tpbW11dGFibGU6IGJvb2xlYW4sIHR5cGU6IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IHwgdW5kZWZpbmVkfSBNZXRhZGF0YSB3aGVuIHByZXNlbnQuXG4gKi9cbmZ1bmN0aW9uIGxvY2FsTWV0YWRhdGEoY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgYXNzb2NpYXRlZCA9IGFzc29jaWF0ZWRDb21tZW50cyhjb21tZW50cywgbm9kZSwgc291cmNlKVxuICBjb25zdCBtZXRhZGF0YSA9IGFzc29jaWF0ZWQubWFwKChjb21tZW50KSA9PiBjb21tZW50VG9rZW5zKGNvbW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICBjb25zdCB0eXBlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHRva2VuPy50ZXh0ID09IFwiQHR5cGVcIilcbiAgY29uc3QgaW1tdXRhYmxlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHRva2VuPy50ZXh0ID09IFwiQHNlbWFudGlmb2xkLWltbXV0YWJsZVwiKVxuICBjb25zdCBwcm9maWxlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHtcbiAgICByZXR1cm4gdG9rZW4/LnRleHQuc3RhcnRzV2l0aChcIkB0eXBlXCIpIHx8IHRva2VuPy50ZXh0LnN0YXJ0c1dpdGgoXCJAc2VtYW50aWZvbGQtaW1tdXRhYmxlXCIpXG4gIH0pXG5cbiAgaWYgKHByb2ZpbGVNZXRhZGF0YS5sZW5ndGggPT0gMCkgcmV0dXJuIHVuZGVmaW5lZFxuXG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKHR5cGVNZXRhZGF0YS5sZW5ndGggIT0gMSB8fCB0eXBlTWV0YWRhdGFbMF0ubGVuZ3RoICE9IDIgfHxcbiAgICBpbW11dGFibGVNZXRhZGF0YS5sZW5ndGggPiAxIHx8IGltbXV0YWJsZU1ldGFkYXRhLnNvbWUoKHRva2VucykgPT4gdG9rZW5zLmxlbmd0aCAhPSAxKSB8fFxuICAgIHByb2ZpbGVNZXRhZGF0YS5sZW5ndGggIT0gdHlwZU1ldGFkYXRhLmxlbmd0aCArIGltbXV0YWJsZU1ldGFkYXRhLmxlbmd0aCkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJtYWxmb3JtZWQgbG9jYWwgdHlwZSBtZXRhZGF0YVwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaW1tdXRhYmxlOiBpbW11dGFibGVNZXRhZGF0YS5sZW5ndGggPT0gMSxcbiAgICB0eXBlOiBjb252ZXJ0VHlwZSh0eXBlTWV0YWRhdGFbMF1bMV0udGV4dCwgYExvY2FsICcke25vZGUubmFtZX0nYCwgbG9jYXRpb24sIHR5cGVNZXRhZGF0YVswXVsxXS5sb2NhdGlvbilcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBSdWJ5IGxvY2FsIGRlY2xhcmF0aW9uIG9yIGFzc2lnbm1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIE5hbWVzIHZpc2libGUgZHVyaW5nIGFkYXB0YXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkxvY2FsU3RhdGVtZW50fSBTZW1hbnRpYyBsb2NhbCBzdGF0ZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRMb2NhbFN0YXRlbWVudChub2RlLCBjb21tZW50cywgdmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuXG4gIGNvbnN0IG1ldGFkYXRhID0gbG9jYWxNZXRhZGF0YShjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobWV0YWRhdGEpIHtcbiAgICB2aXNpYmxlLmFkZChub2RlLm5hbWUpXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgaW5pdGlhbGl6ZXI6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUudmFsdWUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAga2luZDogXCJMb2NhbERlY2xhcmF0aW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG11dGFibGU6ICFtZXRhZGF0YS5pbW11dGFibGUsXG4gICAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgICB0eXBlOiBtZXRhZGF0YS50eXBlXG4gICAgfSwge25hbWU6IHByaXNtTG9jYXRpb24obm9kZS5uYW1lTG9jLCBmaWxlbmFtZSwgc291cmNlKSwgb3BlcmF0b3I6IHByaXNtTG9jYXRpb24obm9kZS5vcGVyYXRvckxvYywgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKCF2aXNpYmxlLmhhcyhub2RlLm5hbWUpKSByZXR1cm4gbWlzc2luZ1R5cGUoXCJydWJ5XCIsIGBMb2NhbCAnJHtub2RlLm5hbWV9J2AsIGxvY2F0aW9uKVxuXG4gIGNvbnN0IHRhcmdldExvY2F0aW9uID0gcHJpc21Mb2NhdGlvbihub2RlLm5hbWVMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHRhcmdldCA9IHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbjogdGFyZ2V0TG9jYXRpb24sIG5hbWU6IG5vZGUubmFtZX0sIHtcbiAgICBuYW1lOiB0YXJnZXRMb2NhdGlvblxuICB9KVxuXG4gIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICBleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnZhbHVlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBraW5kOiBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIixcbiAgICBsb2NhdGlvbixcbiAgICB0YXJnZXRcbiAgfSwge29wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKG5vZGUub3BlcmF0b3JMb2MsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhoYXVzdGl2ZSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge1NldDxzdHJpbmc+fSB2aXNpYmxlIC0gTmFtZXMgdmlzaWJsZSBkdXJpbmcgYWRhcHRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU3RhdGVtZW50fSBTZW1hbnRpYyBzdGF0ZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRTdGF0ZW1lbnQobm9kZSwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBSZXR1cm5Ob2RlKSByZXR1cm4gY29udmVydFJldHVybihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIElmTm9kZSkgcmV0dXJuIGNvbnZlcnRJZihub2RlLCBjb21tZW50cywgdmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KG5vZGUsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlKSByZXR1cm4gY29udmVydFByaW50KG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgb3JkZXJlZCBQcmlzbSBzdGF0ZW1lbnQgbGlzdC5cbiAqIEBwYXJhbSB7U3RhdGVtZW50c05vZGUgfCBudWxsfSBub2RlIC0gUHJpc20gc3RhdGVtZW50cywgb3IgYW4gZW1wdHkgc291cmNlIGJsb2NrLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIE5hbWVzIHZpc2libGUgb24gYmxvY2sgZW50cnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gZmFsbGJhY2tMb2NhdGlvbiAtIEVtcHR5IGJsb2NrIGxvY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSBTZW1hbnRpYyBibG9jay5cbiAqL1xuZnVuY3Rpb24gY29udmVydEJsb2NrKG5vZGUsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLCBmYWxsYmFja0xvY2F0aW9uKSB7XG4gIHJldHVybiB7XG4gICAga2luZDogXCJCbG9ja1wiLFxuICAgIGxvY2F0aW9uOiBub2RlID8gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIDogZmFsbGJhY2tMb2NhdGlvbixcbiAgICBzdGF0ZW1lbnRzOiBub2RlID8gbm9kZS5ib2R5Lm1hcCgoc3RhdGVtZW50KSA9PiBjb252ZXJ0U3RhdGVtZW50KHN0YXRlbWVudCwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpKSA6IFtdXG4gIH1cbn1cblxuLyoqXG4gKiBDaGVja3MgdGhhdCBhIGNvbW1lbnQgYW5kIGl0cyBvd25lciBhcmUgc2VwYXJhdGVkIGJ5IGF0IG1vc3Qgb25lIG5ld2xpbmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZ2FwIC0gU291cmNlIGJldHdlZW4gdGhlIGNvbW1lbnQgYW5kIGZvbGxvd2luZyBpdGVtLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGdhcCBpcyBpbW1lZGlhdGUgd2hpdGVzcGFjZS5cbiAqL1xuZnVuY3Rpb24gaXNJbW1lZGlhdGVDb21tZW50R2FwKGdhcCkge1xuICBsZXQgbmV3bGluZXMgPSAwXG5cbiAgZm9yIChjb25zdCBjaGFyYWN0ZXIgb2YgZ2FwKSB7XG4gICAgaWYgKGNoYXJhY3RlciA9PSBcIlxcblwiKSB7XG4gICAgICBuZXdsaW5lcysrXG4gICAgfSBlbHNlIGlmIChjaGFyYWN0ZXIgIT0gXCIgXCIgJiYgY2hhcmFjdGVyICE9IFwiXFx0XCIgJiYgY2hhcmFjdGVyICE9IFwiXFxyXCIpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdsaW5lcyA8PSAxXG59XG5cbi8qKlxuICogUmVxdWlyZXMgYW4gZXhhY3Qgc3VwcG9ydGVkIFJ1Ynkgc2NhbGFyIHNwZWxsaW5nLlxuICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IHNvdXJjZVR5cGUgLSBSdWJ5IHR5cGUgY29tbWVudCB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJqZWN0IC0gVHlwZWQgc3ViamVjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gU291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gW3R5cGVMb2NhdGlvbl0gLSBFeGFjdCB0eXBlIGNvbW1lbnQgdG9rZW4gbG9jYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVJlZmVyZW5jZX0gU2VtYW50aWMgdHlwZS5cbiAqL1xuZnVuY3Rpb24gY29udmVydFR5cGUoc291cmNlVHlwZSwgc3ViamVjdCwgbG9jYXRpb24sIHR5cGVMb2NhdGlvbiA9IGxvY2F0aW9uKSB7XG4gIHJldHVybiByZXF1aXJlU291cmNlU2NhbGFyVHlwZShcInJ1YnlcIiwgc291cmNlVHlwZSwgc3ViamVjdCwgbG9jYXRpb24sIHR5cGVMb2NhdGlvbilcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIFJ1YnkgZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7RGVmTm9kZX0gbm9kZSAtIFByaXNtIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb259IFNlbWFudGljIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0RnVuY3Rpb24obm9kZSwgY29tbWVudHMsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIW5vZGUucGFyYW1ldGVycyB8fCBub2RlLnBhcmFtZXRlcnMub3B0aW9uYWxzLmxlbmd0aCA+IDAgfHwgbm9kZS5wYXJhbWV0ZXJzLnJlc3QgfHwgbm9kZS5wYXJhbWV0ZXJzLnBvc3RzLmxlbmd0aCA+IDAgfHxcbiAgICBub2RlLnBhcmFtZXRlcnMua2V5d29yZHMubGVuZ3RoID4gMCB8fCBub2RlLnBhcmFtZXRlcnMua2V5d29yZFJlc3QgfHwgbm9kZS5wYXJhbWV0ZXJzLmJsb2NrIHx8XG4gICAgbm9kZS5wYXJhbWV0ZXJzLnJlcXVpcmVkcy5zb21lKChwYXJhbWV0ZXIpID0+ICEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSkpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicGFyYW1ldGVyc1wiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGNvbnN0IGRlY2xhcmVkVHlwZXMgPSB0eXBlQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBub2RlLnBhcmFtZXRlcnMucmVxdWlyZWRzLm1hcCgocGFyYW1ldGVyKSA9PiB7XG4gICAgaWYgKCEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBwYXJhbWV0ZXIuY29uc3RydWN0b3IubmFtZSwgbG9jYXRpb24pXG5cbiAgICBjb25zdCBwYXJhbWV0ZXJMb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihwYXJhbWV0ZXIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBjb25zdCBkZWNsYXJlZFR5cGUgPSBkZWNsYXJlZFR5cGVzLnBhcmFtZXRlcnMuZ2V0KHBhcmFtZXRlci5uYW1lKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUGFyYW1ldGVyXCIpLFxuICAgICAgbG9jYXRpb246IHBhcmFtZXRlckxvY2F0aW9uLFxuICAgICAgbmFtZTogcGFyYW1ldGVyLm5hbWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZShkZWNsYXJlZFR5cGU/LnNvdXJjZVR5cGUsIGBQYXJhbWV0ZXIgJyR7cGFyYW1ldGVyLm5hbWV9J2AsIHBhcmFtZXRlckxvY2F0aW9uLCBkZWNsYXJlZFR5cGU/LmxvY2F0aW9uKVxuICAgIH0sIHtuYW1lOiBwYXJhbWV0ZXJMb2NhdGlvbn0pXG4gIH0pXG4gIGNvbnN0IHZpc2libGUgPSBuZXcgU2V0KHBhcmFtZXRlcnMubWFwKChwYXJhbWV0ZXIpID0+IHBhcmFtZXRlci5uYW1lKSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSA/IG5vZGUuYm9keSA6IG51bGwsIGNvbW1lbnRzLCB2aXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLCBsb2NhdGlvbilcblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keSxcbiAgICBraW5kOiBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIixcbiAgICBsb2NhdGlvbixcbiAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgcGFyYW1ldGVycyxcbiAgICByZXR1cm5UeXBlOiBjb252ZXJ0VHlwZShkZWNsYXJlZFR5cGVzLnJldHVyblR5cGU/LnNvdXJjZVR5cGUsIGBGdW5jdGlvbiAnJHtub2RlLm5hbWV9JyByZXR1cm5gLCBsb2NhdGlvbiwgZGVjbGFyZWRUeXBlcy5yZXR1cm5UeXBlPy5sb2NhdGlvbilcbiAgfSwge25hbWU6IHByaXNtTG9jYXRpb24obm9kZS5uYW1lTG9jLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGV4aXN0aW5nIFJ1YnkgaWYvZWxzZSB0ZXJtaW5hbCB3aXRoIHJlc3RyaWN0ZWQgYnJhbmNoIHByZWZpeGVzLlxuICogQHBhcmFtIHtJZk5vZGV9IG5vZGUgLSBQcmlzbSBpZiBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtTZXQ8c3RyaW5nPn0gdmlzaWJsZSAtIEVuY2xvc2luZyB2aXNpYmxlIG5hbWVzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgY29tbWVudHMsIHZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIW5vZGUuaWZLZXl3b3JkTG9jIHx8IG5vZGUuaWZLZXl3b3JkTG9jLnN0YXJ0T2Zmc2V0ICE9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibW9kaWZpZXIgY29uZGl0aW9uYWxcIiwgbm9kZS5pZktleXdvcmRMb2NcbiAgICAgID8gcHJpc21Mb2NhdGlvbihub2RlLmlmS2V5d29yZExvYywgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICAgIDogbG9jYXRpb24pXG4gIH1cblxuICBjb25zdCBjb25zZXF1ZW50VmlzaWJsZSA9IG5ldyBTZXQodmlzaWJsZSlcbiAgbGV0IGFsdGVybmF0ZVxuXG4gIGlmIChub2RlLnN1YnNlcXVlbnQpIHtcbiAgICBjb25zdCBhbHRlcm5hdGVWaXNpYmxlID0gbmV3IFNldCh2aXNpYmxlKVxuXG4gICAgaWYgKG5vZGUuc3Vic2VxdWVudCBpbnN0YW5jZW9mIEVsc2VOb2RlKSB7XG4gICAgICBhbHRlcm5hdGUgPSBjb252ZXJ0QmxvY2sobm9kZS5zdWJzZXF1ZW50LnN0YXRlbWVudHMsIGNvbW1lbnRzLCBhbHRlcm5hdGVWaXNpYmxlLCBmaWxlbmFtZSwgc291cmNlLFxuICAgICAgICBub2RlTG9jYXRpb24obm9kZS5zdWJzZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9IGVsc2UgaWYgKG5vZGUuc3Vic2VxdWVudCBpbnN0YW5jZW9mIElmTm9kZSkge1xuICAgICAgYWx0ZXJuYXRlID0ge1xuICAgICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCbG9ja1wiKSxcbiAgICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLnN1YnNlcXVlbnQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICBzdGF0ZW1lbnRzOiBbY29udmVydElmKG5vZGUuc3Vic2VxdWVudCwgY29tbWVudHMsIGFsdGVybmF0ZVZpc2libGUsIGZpbGVuYW1lLCBzb3VyY2UpXVxuICAgICAgfVxuICAgIH0gZWxzZSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIG5vZGUuc3Vic2VxdWVudC5jb25zdHJ1Y3Rvci5uYW1lLCBub2RlTG9jYXRpb24obm9kZS5zdWJzZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKGFsdGVybmF0ZSA/IHthbHRlcm5hdGV9IDoge30pLFxuICAgIGNvbmRpdGlvbjogY29udmVydEV4cHJlc3Npb24obm9kZS5wcmVkaWNhdGUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGNvbnNlcXVlbnQ6IGNvbnZlcnRCbG9jayhub2RlLnN0YXRlbWVudHMsIGNvbW1lbnRzLCBjb25zZXF1ZW50VmlzaWJsZSwgZmlsZW5hbWUsIHNvdXJjZSwgbG9jYXRpb24pLFxuICAgIGtpbmQ6IFwiSWZTdGF0ZW1lbnRcIixcbiAgICBsb2NhdGlvblxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIHN1cHBvcnRlZCBSdWJ5IHB1dHMgZW50cnkgcG9pbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QcmludFN0YXRlbWVudH0gUHJpbnQgc3RhdGVtZW50LlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UHJpbnQobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgbm9kZS5yZWNlaXZlciB8fCBub2RlLm5hbWUgIT0gXCJwdXRzXCIgfHwgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IFwiUHJpbnRTdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogUGFyc2VzIFJ1YnkgaW50byB0aGUgc2hhcmVkIHNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBpbnB1dCAtIFBhcnNlciBpbnB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5maWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5zb3VyY2UgLSBTb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gU2VtYW50aWMgbW9kdWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VSdWJ5KHtmaWxlbmFtZSwgc291cmNlfSkge1xuICBjb25zdCByZXN1bHQgPSBwYXJzZVByaXNtKHNvdXJjZSwge2ZpbGVwYXRoOiBmaWxlbmFtZX0pXG5cbiAgaWYgKHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGVycm9yID0gcmVzdWx0LmVycm9yc1swXVxuICAgIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCBlcnJvci5sb2NhdGlvbi5zdGFydE9mZnNldCwgZXJyb3IubG9jYXRpb24uc3RhcnRPZmZzZXQgKyBlcnJvci5sb2NhdGlvbi5sZW5ndGgpXG5cbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlBBUlNFX0VSUk9SXCIsIGxhbmd1YWdlOiBcInJ1YnlcIiwgbG9jYXRpb24sIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KVxuICB9XG5cbiAgaWYgKCEocmVzdWx0LnZhbHVlIGluc3RhbmNlb2YgUHJvZ3JhbU5vZGUpKSB0aHJvdyBuZXcgRXJyb3IoXCJQcmlzbSByZXR1cm5lZCBhIG5vbi1wcm9ncmFtIHJvb3QuXCIpXG5cbiAgY29uc3QgYm9keSA9IHJlc3VsdC52YWx1ZS5zdGF0ZW1lbnRzLmJvZHlcbiAgY29uc3QgZnVuY3Rpb25zID0gYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUgaW5zdGFuY2VvZiBEZWZOb2RlKVxuICAgIC5tYXAoKG5vZGUpID0+IGNvbnZlcnRGdW5jdGlvbihub2RlLCByZXN1bHQuY29tbWVudHMsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICBjb25zdCBlbnRyeU5vZGVzID0gYm9keS5maWx0ZXIoKG5vZGUpID0+ICEobm9kZSBpbnN0YW5jZW9mIERlZk5vZGUpKVxuICBjb25zdCBsb2NhdGlvbiA9IG1vZHVsZUxvY2F0aW9uKGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKGZ1bmN0aW9ucy5sZW5ndGggPT0gMCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1vZHVsZSB3aXRob3V0IGEgZnVuY3Rpb25cIiwgbG9jYXRpb24pXG4gIGNvbnN0IGZpcnN0RW50cnkgPSBlbnRyeU5vZGVzWzBdXG4gIGNvbnN0IGVudHJ5TG9jYXRpb24gPSBmaXJzdEVudHJ5ID8gbG9jYXRpb25Gcm9tT2Zmc2V0cyhcbiAgICBmaWxlbmFtZSxcbiAgICBzb3VyY2UsXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgZmlyc3RFbnRyeS5sb2NhdGlvbi5zdGFydE9mZnNldCksXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KFxuICAgICAgc291cmNlLFxuICAgICAgKGVudHJ5Tm9kZXMuYXQoLTEpPy5sb2NhdGlvbi5zdGFydE9mZnNldCA/PyAwKSArIChlbnRyeU5vZGVzLmF0KC0xKT8ubG9jYXRpb24ubGVuZ3RoID8/IDApXG4gICAgKVxuICApIDogbG9jYXRpb25cbiAgY29uc3QgZW50cnlWaXNpYmxlID0gbmV3IFNldCgpXG4gIGNvbnN0IGVudHJ5QmxvY2sgPSB7XG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmxvY2tcIiksXG4gICAgbG9jYXRpb246IGVudHJ5TG9jYXRpb24sXG4gICAgc3RhdGVtZW50czogZW50cnlOb2Rlcy5tYXAoKHN0YXRlbWVudCkgPT4gY29udmVydFN0YXRlbWVudChzdGF0ZW1lbnQsIHJlc3VsdC5jb21tZW50cywgZW50cnlWaXNpYmxlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZW50cnlQb2ludDoge1xuICAgICAgYm9keTogZW50cnlCbG9jayxcbiAgICAgIGtpbmQ6IFwiRW50cnlQb2ludFwiLFxuICAgICAgbG9jYXRpb246IGVudHJ5TG9jYXRpb25cbiAgICB9LFxuICAgIGZ1bmN0aW9ucyxcbiAgICBraW5kOiBcIk1vZHVsZVwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cbiJdfQ==
|
|
1569
|
+
/**
|
|
1570
|
+
* Removes exact protected Ruby probe support before portable conversion.
|
|
1571
|
+
* @param {import("@ruby/prism").Node[]} body - Parsed top-level nodes.
|
|
1572
|
+
* @param {{location: {startOffset: number, length: number}}[]} comments - Parser comments.
|
|
1573
|
+
* @param {readonly import("../semantic/types.js").EffectCapabilityDeclaration[]} capabilities - Authorized declarations.
|
|
1574
|
+
* @param {string} filename - Source filename.
|
|
1575
|
+
* @param {string} source - Complete source.
|
|
1576
|
+
* @returns {import("@ruby/prism").Node[]} Portable nodes.
|
|
1577
|
+
*/
|
|
1578
|
+
function task034RubyBody(body, comments, capabilities, filename, source) {
|
|
1579
|
+
if (!isTask034ResourceProbe(capabilities))
|
|
1580
|
+
return body;
|
|
1581
|
+
const marker = comments.find((comment) => source.slice(comment.location.startOffset, comment.location.startOffset + comment.location.length) ==
|
|
1582
|
+
"# semantifold-task034-support");
|
|
1583
|
+
if (!marker)
|
|
1584
|
+
return body;
|
|
1585
|
+
if (!hasExactEffectSupport(source, "ruby")) {
|
|
1586
|
+
return unsupportedSyntax("ruby", "malformed protected Task 034 support", nodeLocation(body[0], filename, source));
|
|
1587
|
+
}
|
|
1588
|
+
const expected = [
|
|
1589
|
+
["ClassNode", "ProbeOperationFailure"], ["ClassNode", "ProbeAcquireFailure"], ["ClassNode", "ProbeReadFailure"],
|
|
1590
|
+
["ClassNode", "ProbeCloseFailure"], ["ClassNode", "ProbeResourceClosed"], ["ClassNode", "ProbeResource"],
|
|
1591
|
+
["GlobalVariableWriteNode", "$__semantifold_task034_trace"], ["DefNode", "probeEffect"], ["DefNode", "probeAcquire"],
|
|
1592
|
+
["DefNode", "probeRead"], ["DefNode", "probeClose"], ["DefNode", "probeTrace"]
|
|
1593
|
+
];
|
|
1594
|
+
const matches = expected.every(([kind, name], index) => body[index]?.constructor.name == kind && Reflect.get(body[index], "name") == name);
|
|
1595
|
+
const end = comments.find((comment) => source.slice(comment.location.startOffset, comment.location.startOffset + comment.location.length) ==
|
|
1596
|
+
"# semantifold-task034-support-end");
|
|
1597
|
+
if (!matches || !end || end.location.startOffset < body[expected.length - 1].location.startOffset + body[expected.length - 1].location.length) {
|
|
1598
|
+
return unsupportedSyntax("ruby", "malformed protected Task 034 support", nodeLocation(body[0], filename, source));
|
|
1599
|
+
}
|
|
1600
|
+
return body.slice(expected.length);
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* Reads the canonical parser-owned Ruby module and literal require-relative edges.
|
|
1604
|
+
* @param {object} input - Parser input.
|
|
1605
|
+
* @param {string} input.filename - Source filename.
|
|
1606
|
+
* @param {string} input.source - Source text.
|
|
1607
|
+
* @returns {{imports: {importedName: string, localName: string, location: import("../semantic/types.js").SourceLocation, namespace: true, pathLocation: import("../semantic/types.js").SourceLocation, specifier: string, stdlibCandidate?: true, typeOnly: false}[], exports: {exportedName: string, localName: string, location: import("../semantic/types.js").SourceLocation, typeOnly: false}[], nativeName: string, nativeReferences: {form: "constructor-call" | "receiver-call" | "unqualified-call", location: import("../semantic/types.js").SourceLocation, nativeModule: string, symbol: string}[]}} Parser-owned Ruby module header.
|
|
1608
|
+
*/
|
|
1609
|
+
export function inspectRubyModule({ filename, source }) {
|
|
1610
|
+
const result = parsePrism(source, { filepath: filename });
|
|
1611
|
+
if (result.errors.length > 0) {
|
|
1612
|
+
const error = result.errors[0];
|
|
1613
|
+
const location = locationFromOffsets(filename, source, error.location.startOffset, error.location.startOffset + error.location.length);
|
|
1614
|
+
throw new SemantifoldDiagnostic({ code: "PARSE_ERROR", language: "ruby", location, message: error.message });
|
|
1615
|
+
}
|
|
1616
|
+
if (!(result.value instanceof ProgramNode))
|
|
1617
|
+
throw new Error("Prism returned a non-program root.");
|
|
1618
|
+
const body = result.value.statements.body;
|
|
1619
|
+
const modules = body.filter((node) => node instanceof ModuleNode);
|
|
1620
|
+
const dynamicRequire = body.find(isDynamicStdlibRequire);
|
|
1621
|
+
if (dynamicRequire) {
|
|
1622
|
+
throw new SemantifoldDiagnostic({
|
|
1623
|
+
code: "STDLIB_FACADE_DYNAMIC_REFERENCE",
|
|
1624
|
+
language: "ruby",
|
|
1625
|
+
location: nodeLocation(dynamicRequire, filename, source),
|
|
1626
|
+
message: "Dynamic require cannot prove a standard-library facade identity."
|
|
1627
|
+
});
|
|
1628
|
+
}
|
|
1629
|
+
validateTask037NativeAttempts(body, filename, source);
|
|
1630
|
+
const invalid = body.find((node) => !(node instanceof ModuleNode) && !isRequireRelative(node) && !isStdlibRequire(node));
|
|
1631
|
+
if (modules.length != 1 || !(modules[0].constantPath instanceof ConstantReadNode) || invalid) {
|
|
1632
|
+
return unsupportedSyntax("ruby", "one simple module with literal require_relative declarations", nodeLocation(invalid ?? modules[1] ?? modules[0] ?? result.value, filename, source));
|
|
1633
|
+
}
|
|
1634
|
+
const imports = body.filter((node) => isRequireRelative(node) || isStdlibRequire(node)).map((node) => {
|
|
1635
|
+
const call = /** @type {CallNode} */ (node);
|
|
1636
|
+
const argument = /** @type {StringNode} */ (call.arguments_?.arguments_[0]);
|
|
1637
|
+
const stdlibCandidate = isStdlibRequire(call);
|
|
1638
|
+
if (!argument.unescaped.validEncoding || argument.unescaped.encoding != "utf-8" || argument.isForcedBinaryEncoding()) {
|
|
1639
|
+
return unsupportedSyntax("ruby", "non-UTF-8 require_relative path", nodeLocation(argument, filename, source));
|
|
1640
|
+
}
|
|
1641
|
+
return {
|
|
1642
|
+
importedName: "*",
|
|
1643
|
+
kind: /** @type {const} */ ("Import"),
|
|
1644
|
+
localName: "",
|
|
1645
|
+
location: nodeLocation(call, filename, source),
|
|
1646
|
+
namespace: /** @type {const} */ (true),
|
|
1647
|
+
pathLocation: nodeLocation(argument, filename, source),
|
|
1648
|
+
specifier: argument.unescaped.value,
|
|
1649
|
+
...(stdlibCandidate ? { stdlibCandidate: /** @type {const} */ (true) } : {}),
|
|
1650
|
+
typeOnly: /** @type {const} */ (false)
|
|
1651
|
+
};
|
|
1652
|
+
});
|
|
1653
|
+
const moduleBody = modules[0].body instanceof StatementsNode ? modules[0].body.body : [];
|
|
1654
|
+
const visibility = new Map();
|
|
1655
|
+
for (const node of moduleBody) {
|
|
1656
|
+
if (!(node instanceof CallNode) || !["private_class_method", "private_constant"].includes(node.name))
|
|
1657
|
+
continue;
|
|
1658
|
+
const marker = rubyVisibilityMarker(node);
|
|
1659
|
+
if (!marker)
|
|
1660
|
+
return unsupportedSyntax("ruby", `malformed ${node.name}`, nodeLocation(node, filename, source));
|
|
1661
|
+
if (visibility.has(marker.name))
|
|
1662
|
+
return unsupportedSyntax("ruby", `duplicate visibility marker for '${marker.name}'`, nodeLocation(node, filename, source));
|
|
1663
|
+
const declaration = moduleBody.find((candidate) => marker.kind == "function"
|
|
1664
|
+
? candidate instanceof DefNode && candidate.name == marker.name
|
|
1665
|
+
: candidate instanceof ClassNode && candidate.name == marker.name);
|
|
1666
|
+
if (!declaration || moduleBody.indexOf(declaration) > moduleBody.indexOf(node)) {
|
|
1667
|
+
return unsupportedSyntax("ruby", `visibility marker without an earlier ${marker.kind}`, nodeLocation(node, filename, source));
|
|
1668
|
+
}
|
|
1669
|
+
visibility.set(marker.name, marker.kind);
|
|
1670
|
+
}
|
|
1671
|
+
const exports = moduleBody.flatMap((node) => {
|
|
1672
|
+
if (node instanceof DefNode || node instanceof ClassNode) {
|
|
1673
|
+
const kind = node instanceof DefNode ? "function" : node.body instanceof StatementsNode && node.body.body.length > 0 &&
|
|
1674
|
+
node.body.body.every((member) => member instanceof DefNode) ? "class" : "record";
|
|
1675
|
+
if (visibility.get(node.name) == kind)
|
|
1676
|
+
return [];
|
|
1677
|
+
return [{
|
|
1678
|
+
exportedName: node.name,
|
|
1679
|
+
localName: node.name,
|
|
1680
|
+
location: nodeLocation(node instanceof ClassNode ? node.constantPath : node, filename, source),
|
|
1681
|
+
symbolKind: /** @type {import("../semantic/types.js").SemanticDeclarationKind} */ (kind),
|
|
1682
|
+
typeOnly: /** @type {const} */ (false)
|
|
1683
|
+
}];
|
|
1684
|
+
}
|
|
1685
|
+
return [];
|
|
1686
|
+
});
|
|
1687
|
+
const nativeReferences = rubyNativeReferences(modules[0], filename, source);
|
|
1688
|
+
return { exports, imports, nativeName: modules[0].name, nativeReferences };
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Rejects parser-proved attempts to use or mutate the bounded socket facade outside its exact surface.
|
|
1692
|
+
* @param {import("@ruby/prism").Node[]} body - Prism program body.
|
|
1693
|
+
* @param {string} filename - Source filename.
|
|
1694
|
+
* @param {string} source - Complete source.
|
|
1695
|
+
* @returns {void}
|
|
1696
|
+
*/
|
|
1697
|
+
function validateTask037NativeAttempts(body, filename, source) {
|
|
1698
|
+
const active = body.some((node) => isStdlibRequire(node) && node instanceof CallNode &&
|
|
1699
|
+
node.arguments_?.arguments_[0] instanceof StringNode && node.arguments_.arguments_[0].unescaped.value == "socket");
|
|
1700
|
+
const reopened = body.find((node) => node instanceof ClassNode && node.name == "TCPSocket");
|
|
1701
|
+
if (active && reopened)
|
|
1702
|
+
throw new SemantifoldDiagnostic({
|
|
1703
|
+
code: "STDLIB_FACADE_REOPENED",
|
|
1704
|
+
language: "ruby",
|
|
1705
|
+
location: nodeLocation(reopened, filename, source),
|
|
1706
|
+
message: "Caller source reopens the compiler-owned TCPSocket facade identity."
|
|
1707
|
+
});
|
|
1708
|
+
const modules = body.filter((node) => node instanceof ModuleNode);
|
|
1709
|
+
/**
|
|
1710
|
+
* Visits one parser node for bounded native attempts.
|
|
1711
|
+
* @param {import("@ruby/prism").Node} node - Candidate Prism node.
|
|
1712
|
+
*/
|
|
1713
|
+
function visit(node) {
|
|
1714
|
+
if (node instanceof CallNode) {
|
|
1715
|
+
const receiver = node.receiver;
|
|
1716
|
+
const tcpReceiver = receiver instanceof ConstantReadNode && receiver.name == "TCPSocket";
|
|
1717
|
+
if (tcpReceiver) {
|
|
1718
|
+
if (!active)
|
|
1719
|
+
throw new SemantifoldDiagnostic({
|
|
1720
|
+
code: "STDLIB_FACADE_IDENTITY_UNPROVED",
|
|
1721
|
+
language: "ruby",
|
|
1722
|
+
location: nodeLocation(/** @type {ConstantReadNode} */ (receiver), filename, source),
|
|
1723
|
+
message: "TCPSocket requires the exact parser-proved require \"socket\" identity."
|
|
1724
|
+
});
|
|
1725
|
+
if (node.name != "new" || node.block || node.arguments_?.arguments_.length != 2) {
|
|
1726
|
+
throw new SemantifoldDiagnostic({
|
|
1727
|
+
code: "STDLIB_FACADE_MEMBER_UNSUPPORTED",
|
|
1728
|
+
language: "ruby",
|
|
1729
|
+
location: nodeLocation(node, filename, source),
|
|
1730
|
+
message: "TCPSocket supports only exact two-argument new without a block."
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
const kernelPuts = !node.receiver && node.name == "puts" ||
|
|
1735
|
+
node.receiver instanceof ConstantReadNode && node.receiver.name == "Kernel" && node.name == "puts";
|
|
1736
|
+
if (active && kernelPuts && (node.block || node.arguments_?.arguments_.length != 1)) {
|
|
1737
|
+
throw new SemantifoldDiagnostic({
|
|
1738
|
+
code: "STDLIB_FACADE_MEMBER_UNSUPPORTED",
|
|
1739
|
+
language: "ruby",
|
|
1740
|
+
location: nodeLocation(node, filename, source),
|
|
1741
|
+
message: "The Task 037 Output facade supports exactly one string argument without a block."
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
for (const child of node.compactChildNodes())
|
|
1746
|
+
visit(child);
|
|
1747
|
+
}
|
|
1748
|
+
for (const module of modules)
|
|
1749
|
+
visit(module);
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Collects exact Task 037 native identities from Prism nodes in source order.
|
|
1753
|
+
* @param {ModuleNode} module - Parsed application module.
|
|
1754
|
+
* @param {string} filename - Source filename.
|
|
1755
|
+
* @param {string} source - Complete source.
|
|
1756
|
+
* @returns {{form: "constructor-call" | "receiver-call" | "unqualified-call", location: import("../semantic/types.js").SourceLocation, nativeModule: string, symbol: string}[]} Parser-proved native references.
|
|
1757
|
+
*/
|
|
1758
|
+
function rubyNativeReferences(module, filename, source) {
|
|
1759
|
+
/** @type {{form: "constructor-call" | "receiver-call" | "unqualified-call", location: import("../semantic/types.js").SourceLocation, nativeModule: string, offset: number, symbol: string}[]} */
|
|
1760
|
+
const references = [];
|
|
1761
|
+
/**
|
|
1762
|
+
* Visits one parser node without interpreting source text.
|
|
1763
|
+
* @param {import("@ruby/prism").Node} node - Parser node.
|
|
1764
|
+
* @returns {void}
|
|
1765
|
+
*/
|
|
1766
|
+
function visit(node) {
|
|
1767
|
+
if (node instanceof CallNode && !node.block && node.arguments_?.arguments_.length == 1 &&
|
|
1768
|
+
!node.receiver && node.name == "puts") {
|
|
1769
|
+
references.push({ form: "unqualified-call", location: nodeLocation(node, filename, source), nativeModule: "ruby:Kernel",
|
|
1770
|
+
offset: node.location.startOffset, symbol: "puts" });
|
|
1771
|
+
}
|
|
1772
|
+
if (node instanceof CallNode && !node.block && node.arguments_?.arguments_.length == 1 && node.name == "puts" &&
|
|
1773
|
+
node.callOperatorLoc && node.receiver instanceof ConstantReadNode && node.receiver.name == "Kernel") {
|
|
1774
|
+
references.push({ form: "receiver-call", location: nodeLocation(node, filename, source), nativeModule: "ruby:Kernel",
|
|
1775
|
+
offset: node.location.startOffset, symbol: "puts" });
|
|
1776
|
+
}
|
|
1777
|
+
if (node instanceof CallNode && !node.block && node.arguments_?.arguments_.length == 2 && node.name == "new" &&
|
|
1778
|
+
node.callOperatorLoc && node.receiver instanceof ConstantReadNode && node.receiver.name == "TCPSocket") {
|
|
1779
|
+
references.push({ form: "constructor-call", location: nodeLocation(node, filename, source), nativeModule: "socket",
|
|
1780
|
+
offset: node.location.startOffset, symbol: "TCPSocket" });
|
|
1781
|
+
}
|
|
1782
|
+
for (const child of node.compactChildNodes())
|
|
1783
|
+
visit(child);
|
|
1784
|
+
}
|
|
1785
|
+
visit(module);
|
|
1786
|
+
return references.sort((left, right) => left.offset - right.offset).map(({ offset: _offset, ...reference }) => reference);
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Reports whether a Ruby node is one canonical literal relative load edge.
|
|
1790
|
+
* @param {import("@ruby/prism").Node} node - Candidate call.
|
|
1791
|
+
* @returns {boolean} Whether the node is a supported require-relative call.
|
|
1792
|
+
*/
|
|
1793
|
+
function isRequireRelative(node) {
|
|
1794
|
+
return node instanceof CallNode && !node.receiver && !node.block && node.name == "require_relative" &&
|
|
1795
|
+
node.arguments_?.arguments_.length == 1 && node.arguments_.arguments_[0] instanceof StringNode;
|
|
1796
|
+
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Reports whether a Ruby node is one parser-proved literal facade require candidate.
|
|
1799
|
+
* Other load-path requires retain the Task 010 unsupported profile.
|
|
1800
|
+
* @param {import("@ruby/prism").Node} node - Candidate call.
|
|
1801
|
+
* @returns {boolean} Whether the node is a literal Semantifold facade require.
|
|
1802
|
+
*/
|
|
1803
|
+
function isStdlibRequire(node) {
|
|
1804
|
+
return node instanceof CallNode && !node.receiver && !node.block && node.name == "require" &&
|
|
1805
|
+
node.arguments_?.arguments_.length == 1 && node.arguments_.arguments_[0] instanceof StringNode &&
|
|
1806
|
+
(node.arguments_.arguments_[0].unescaped.value == "socket" ||
|
|
1807
|
+
node.arguments_.arguments_[0].unescaped.value.startsWith("semantifold/"));
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Reports whether a Ruby node dynamically constructs a facade require identity.
|
|
1811
|
+
* @param {import("@ruby/prism").Node} node - Candidate call.
|
|
1812
|
+
* @returns {boolean} Whether the parser exposes a nonliteral require.
|
|
1813
|
+
*/
|
|
1814
|
+
function isDynamicStdlibRequire(node) {
|
|
1815
|
+
if (!(node instanceof CallNode) || node.receiver || node.block || node.name != "require" ||
|
|
1816
|
+
node.arguments_?.arguments_.length != 1)
|
|
1817
|
+
return false;
|
|
1818
|
+
return !(node.arguments_.arguments_[0] instanceof StringNode);
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* Reports whether a Ruby node is the canonical module-function marker.
|
|
1822
|
+
* @param {import("@ruby/prism").Node} node - Candidate marker.
|
|
1823
|
+
* @returns {boolean} Whether the node is a bare module-function call.
|
|
1824
|
+
*/
|
|
1825
|
+
function isModuleFunctionMarker(node) {
|
|
1826
|
+
return node instanceof CallNode && !node.receiver && !node.block && node.name == "module_function" && !node.arguments_;
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Reads one exact generated Ruby visibility marker.
|
|
1830
|
+
* @param {import("@ruby/prism").Node} node - Candidate module-body node.
|
|
1831
|
+
* @returns {{kind: import("../semantic/types.js").SemanticDeclarationKind, name: string} | undefined} Marker meaning.
|
|
1832
|
+
*/
|
|
1833
|
+
function rubyVisibilityMarker(node) {
|
|
1834
|
+
if (!(node instanceof CallNode) || node.receiver || node.block ||
|
|
1835
|
+
!["private_class_method", "private_constant"].includes(node.name) ||
|
|
1836
|
+
node.arguments_?.arguments_.length != 1 || !(node.arguments_.arguments_[0] instanceof SymbolNode))
|
|
1837
|
+
return undefined;
|
|
1838
|
+
return {
|
|
1839
|
+
kind: node.name == "private_class_method" ? "function" : "record",
|
|
1840
|
+
name: node.arguments_.arguments_[0].unescaped.value
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* Builds a parser-owned simple Ruby constant path without inspecting source text.
|
|
1845
|
+
* @param {ConstantReadNode | ConstantPathNode} node - Constant path.
|
|
1846
|
+
* @returns {string} Qualified constant name.
|
|
1847
|
+
*/
|
|
1848
|
+
function constantPathName(node) {
|
|
1849
|
+
if (node instanceof ConstantReadNode)
|
|
1850
|
+
return node.name;
|
|
1851
|
+
if (typeof node.name != "string")
|
|
1852
|
+
throw new Error("Prism returned a constant path without a name.");
|
|
1853
|
+
if (!node.parent)
|
|
1854
|
+
return node.name;
|
|
1855
|
+
if (!(node.parent instanceof ConstantReadNode) && !(node.parent instanceof ConstantPathNode)) {
|
|
1856
|
+
throw new Error("Prism returned an unsupported constant-path parent.");
|
|
1857
|
+
}
|
|
1858
|
+
return `${constantPathName(node.parent)}::${node.name}`;
|
|
1859
|
+
}
|
|
1860
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVieS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvcnVieS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUNMLE9BQU8sRUFDUCxTQUFTLEVBQ1QsU0FBUyxFQUNULFNBQVMsRUFDVCxtQkFBbUIsRUFDbkIsU0FBUyxFQUNULFNBQVMsRUFDVCxRQUFRLEVBQ1IsU0FBUyxFQUNULGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsT0FBTyxFQUNQLFFBQVEsRUFDUixTQUFTLEVBQ1QsUUFBUSxFQUNSLE1BQU0sRUFDTixXQUFXLEVBQ1gseUJBQXlCLEVBQ3pCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdEIscUJBQXFCLEVBQ3JCLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsVUFBVSxFQUNWLFFBQVEsRUFDUixPQUFPLEVBQ1AsTUFBTSxFQUNOLGVBQWUsRUFDZixXQUFXLEVBQ1gscUJBQXFCLEVBQ3JCLFFBQVEsRUFDUixVQUFVLEVBQ1YsVUFBVSxFQUNWLFNBQVMsRUFDVCxRQUFRLEVBQ1IsY0FBYyxFQUNkLFVBQVUsRUFDVixVQUFVLEVBQ1YsUUFBUSxFQUNSLFVBQVUsRUFDVixTQUFTLEVBQ1QsU0FBUyxFQUNWLE1BQU0sYUFBYSxDQUFBO0FBQ3BCLE9BQU8sRUFBQyxXQUFXLEVBQUUscUJBQXFCLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQTtBQUN0RixPQUFPLEVBQUMsNkJBQTZCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQTtBQUNwRSxPQUFPLEVBQUMsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLDJCQUEyQixFQUFDLE1BQU0seUJBQXlCLENBQUE7QUFDeEcsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sMEJBQTBCLENBQUE7QUFDN0QsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sMkJBQTJCLENBQUE7QUFDMUQsT0FBTyxFQUFDLHFCQUFxQixFQUFD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QVUsQ0FBQztRQUFFLE9BQU8sU0FBUyxDQUFBO0lBRXJILE9BQU87UUFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxRQUFRO1FBQ2pFLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSztLQUNwRCxDQUFBO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLElBQUk7SUFDNUIsSUFBSSxJQUFJLFlBQVksZ0JBQWdCO1FBQUUsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFBO0lBQ3RELElBQUksT0FBTyxJQUFJLENBQUMsSUFBSSxJQUFJLFFBQVE7UUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUE7SUFDbkcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFBO0lBQ2xDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLFlBQVksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sWUFBWSxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7UUFDN0YsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFBO0lBQ3hFLENBQUM7SUFFRCxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtBQUN6RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7XG4gIEFuZE5vZGUsXG4gIEFycmF5Tm9kZSxcbiAgQXNzb2NOb2RlLFxuICBCbG9ja05vZGUsXG4gIEJsb2NrUGFyYW1ldGVyc05vZGUsXG4gIEJlZ2luTm9kZSxcbiAgQnJlYWtOb2RlLFxuICBDYWxsTm9kZSxcbiAgQ2xhc3NOb2RlLFxuICBDb25zdGFudFBhdGhOb2RlLFxuICBDb25zdGFudFJlYWROb2RlLFxuICBEZWZOb2RlLFxuICBFbHNlTm9kZSxcbiAgRmFsc2VOb2RlLFxuICBIYXNoTm9kZSxcbiAgSWZOb2RlLFxuICBJbnRlZ2VyTm9kZSxcbiAgSW5zdGFuY2VWYXJpYWJsZVdyaXRlTm9kZSxcbiAgSW5zdGFuY2VWYXJpYWJsZVJlYWROb2RlLFxuICBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlLFxuICBMb2NhbFZhcmlhYmxlUmVhZE5vZGUsXG4gIExvY2FsVmFyaWFibGVUYXJnZXROb2RlLFxuICBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlLFxuICBNb2R1bGVOb2RlLFxuICBOZXh0Tm9kZSxcbiAgTmlsTm9kZSxcbiAgT3JOb2RlLFxuICBQYXJlbnRoZXNlc05vZGUsXG4gIFByb2dyYW1Ob2RlLFxuICBSZXF1aXJlZFBhcmFtZXRlck5vZGUsXG4gIFJlZG9Ob2RlLFxuICBSZXNjdWVOb2RlLFxuICBSZXR1cm5Ob2RlLFxuICBSZXRyeU5vZGUsXG4gIFNlbGZOb2RlLFxuICBTdGF0ZW1lbnRzTm9kZSxcbiAgU3RyaW5nTm9kZSxcbiAgU3ltYm9sTm9kZSxcbiAgVHJ1ZU5vZGUsXG4gIFVubGVzc05vZGUsXG4gIFdoaWxlTm9kZSxcbiAgbG9hZFByaXNtXG59IGZyb20gXCJAcnVieS9wcmlzbVwiXG5pbXBvcnQge21pc3NpbmdUeXBlLCBTZW1hbnRpZm9sZERpYWdub3N0aWMsIHVuc3VwcG9ydGVkU3ludGF4fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2Jsb2NrUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5fSBmcm9tIFwiLi4vc2VtYW50aWMvZWZmZWN0cy5qc1wiXG5pbXBvcnQge2xvY2F0aW9uRnJvbU9mZnNldHMsIG1vZHVsZUxvY2F0aW9uLCB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXR9IGZyb20gXCIuLi9zZW1hbnRpYy9sb2NhdGlvbi5qc1wiXG5pbXBvcnQge3dpdGhBZGFwdGVkT3BlcmF0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCJcbmltcG9ydCB7d2l0aFBhcnNlclJhbmdlc30gZnJvbSBcIi4uL3NlbWFudGljL3Byb3ZlbmFuY2UuanNcIlxuaW1wb3J0IHtoYXNPbmx5VW5pY29kZVNjYWxhcnN9IGZyb20gXCIuLi9zZW1hbnRpYy9zY2FsYXJzLmpzXCJcbmltcG9ydCB7aXNUYXNrMDM0UmVzb3VyY2VQcm9iZX0gZnJvbSBcIi4uL3NlbWFudGljL2NhcGFiaWxpdGllcy5qc1wiXG5pbXBvcnQge2hhc0V4YWN0RWZmZWN0U3VwcG9ydH0gZnJvbSBcIi4uL2JhY2tlbmRzL2VmZmVjdHMuanNcIlxuaW1wb3J0IHtyZXF1aXJlU291cmNlUmV0dXJuVHlwZX0gZnJvbSBcIi4vc2NhbGFycy5qc1wiXG5pbXBvcnQge2NhcGFiaWxpdHlGdW5jdGlvblNpZ25hdHVyZXMsIGRvY3VtZW50ZWRWYWx1ZVR5cGUsIGluc3RhbnRpYXRlZFJlY29yZEZpZWxkVHlwZSwgaXRlcmF0aW9uQmluZGluZ1R5cGUsIGl0ZXJhdGlvbk9wZXJhbmRUeXBlLCBrbm93bkNhbGxSZXR1cm5UeXBlLCBvcmRlcmVkTWFwVHlwZUZyb21NYXAsIHByZXNlcnZlc0dlbmVyaWNPcHRpb25hbEV2aWRlbmNlLCByZWNvcmRUeXBlLCByZWZlcmVuY2VUeXBlLCBzYW1lVmFsdWVUeXBlfSBmcm9tIFwiLi90eXBlcy5qc1wiXG5jb25zdCBwYXJzZVByaXNtID0gYXdhaXQgbG9hZFByaXNtKClcbmNvbnN0IHJlZmVyZW5jZU1ldGhvZEhvb2tzID0gbmV3IFNldChbXG4gIFwiX19zZW5kX19cIiwgXCJleHRlbmRcIiwgXCJmZXRjaFwiLCBcImluc3RhbmNlX2V2YWxcIiwgXCJpbnN0YW5jZV9leGVjXCIsIFwibWV0aG9kXCIsIFwibWV0aG9kX21pc3NpbmdcIiwgXCJwdWJsaWNfc2VuZFwiLFxuICBcInJlc3BvbmRfdG9fbWlzc2luZz9cIiwgXCJzZW5kXCIsIFwic2luZ2xldG9uX2NsYXNzXCIsIFwic2l6ZVwiXG5dKVxuLyoqIEB0eXBlZGVmIHt7bmFtZTogc3RyaW5nLCBuYW1lTG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBwYXJhbWV0ZXJzOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QYXJhbWV0ZXJbXSwgcmV0dXJuVHlwZTogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNGdW5jdGlvblJldHVyblR5cGUsIHR5cGVQYXJhbWV0ZXJzPzogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVBhcmFtZXRlcltdLCBsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259fSBSdWJ5RnVuY3Rpb25TaWduYXR1cmUgKi9cbi8qKiBAdHlwZWRlZiB7e2JpbmRpbmdzOiBNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0JpbmRpbmdUeXBlPiwgY2xhc3NlczogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbj4sIGN1cnJlbnRDbGFzcz86IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24sIGVycm9yTmFtZXM6IE1hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb24+LCBlcnJvcnM6IE1hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb24+LCBmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIFJ1YnlGdW5jdGlvblNpZ25hdHVyZT4sIG9yZGVyZWRNYXBEZWNsYXJhdGlvbnM/OiBTZXQ8b2JqZWN0PiwgcmVjb3JkczogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUmVjb3JkRGVjbGFyYXRpb24+LCByZWNvcmROYW1lczogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUmVjb3JkRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5DbGFzc0RlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRWZmZWN0UmVzb3VyY2VEZWNsYXJhdGlvbj4sIGxvb3BEZXB0aD86IG51bWJlciwgcmV0dXJuVHlwZT86IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljRnVuY3Rpb25SZXR1cm5UeXBlLCB0eXBlUGFyYW1ldGVycz86IE1hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVQYXJhbWV0ZXI+fX0gUnVieUNvbnZlcnNpb25Db250ZXh0ICovXG5jb25zdCBydWJ5QmluYXJ5T3BlcmF0aW9ucyA9IG5ldyBNYXAoW1xuICBbXCIrXCIsIFwiQWRkXCJdLFxuICBbXCItXCIsIFwiU3VidHJhY3RcIl0sXG4gIFtcIipcIiwgXCJNdWx0aXBseVwiXSxcbiAgW1wiPT1cIiwgXCJFcXVhbFwiXSxcbiAgW1wiIT1cIiwgXCJOb3RFcXVhbFwiXSxcbiAgW1wiPFwiLCBcIkxlc3NUaGFuXCJdLFxuICBbXCI8PVwiLCBcIkxlc3NUaGFuT3JFcXVhbFwiXSxcbiAgW1wiPlwiLCBcIkdyZWF0ZXJUaGFuXCJdLFxuICBbXCI+PVwiLCBcIkdyZWF0ZXJUaGFuT3JFcXVhbFwiXVxuXSlcblxuLyoqXG4gKiBSZXR1cm5zIGEgbm9ybWFsaXplZCBQcmlzbSBub2RlIGxvY2F0aW9uLlxuICogQHBhcmFtIHt7bG9jYXRpb246IGltcG9ydChcIkBydWJ5L3ByaXNtXCIpLkxvY2F0aW9ufX0gbm9kZSAtIFByaXNtIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBTb3VyY2UgbG9jYXRpb24uXG4gKi9cbmZ1bmN0aW9uIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIHJldHVybiBwcmlzbUxvY2F0aW9uKG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBQcmlzbSBsb2NhdGlvbiBpbnRvIGEgbm9ybWFsaXplZCBzb3VyY2UgbG9jYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLkxvY2F0aW9ufSBsb2NhdGlvbiAtIFByaXNtIGxvY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gU291cmNlIGxvY2F0aW9uLlxuICovXG5mdW5jdGlvbiBwcmlzbUxvY2F0aW9uKGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIHJldHVybiBsb2NhdGlvbkZyb21PZmZzZXRzKFxuICAgIGZpbGVuYW1lLFxuICAgIHNvdXJjZSxcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBsb2NhdGlvbi5zdGFydE9mZnNldCksXG4gICAgdXRmOEJ5dGVPZmZzZXRUb1V0ZjE2T2Zmc2V0KHNvdXJjZSwgbG9jYXRpb24uc3RhcnRPZmZzZXQgKyBsb2NhdGlvbi5sZW5ndGgpXG4gIClcbn1cblxuLyoqXG4gKiBTbGljZXMgSmF2YVNjcmlwdCBzb3VyY2UgdXNpbmcgUHJpc20ncyBVVEYtOCBieXRlIG9mZnNldHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0T2Zmc2V0IC0gSW5jbHVzaXZlIFByaXNtIGJ5dGUgb2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZE9mZnNldCAtIEV4Y2x1c2l2ZSBQcmlzbSBieXRlIG9mZnNldC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFNvdXJjZSB0ZXh0IGluIHRoZSBieXRlIHJhbmdlLlxuICovXG5mdW5jdGlvbiBzbGljZVByaXNtU291cmNlKHNvdXJjZSwgc3RhcnRPZmZzZXQsIGVuZE9mZnNldCkge1xuICByZXR1cm4gc291cmNlLnNsaWNlKFxuICAgIHV0ZjhCeXRlT2Zmc2V0VG9VdGYxNk9mZnNldChzb3VyY2UsIHN0YXJ0T2Zmc2V0KSxcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBlbmRPZmZzZXQpXG4gIClcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHN1cHBvcnRlZCBQcmlzbSBleHByZXNzaW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gUHJpc20gbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udmVyc2lvbiBjb250ZXh0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1ZhbHVlVHlwZX0gW2V4cGVjdGVkVHlwZV0gLSBFeHBsaWNpdCBjb250ZXh0dWFsIHZhbHVlIHR5cGUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtwcmVzZXJ2ZU9wdGlvbmFsXSAtIFdoZXRoZXIgYW4gb3B0aW9uYWwgaWRlbnRpZmllciByZW1haW5zIHdyYXBwZWQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gU2VtYW50aWMgZXhwcmVzc2lvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEV4cHJlc3Npb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCwgZXhwZWN0ZWRUeXBlLCBwcmVzZXJ2ZU9wdGlvbmFsID0gZmFsc2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoZXhwZWN0ZWRUeXBlPy5raW5kID09IFwiT3B0aW9uYWxUeXBlXCIpIHtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIE5pbE5vZGUpIHtcbiAgICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJPcHRpb25hbE5vbmVcIiksIGxvY2F0aW9ufSwge2Fic2VuY2U6IGxvY2F0aW9ufSlcbiAgICB9XG4gICAgaWYgKGtub3duRXhwcmVzc2lvblR5cGUobm9kZSwgY29udGV4dCk/LmtpbmQgPT0gXCJPcHRpb25hbFR5cGVcIikge1xuICAgICAgcmV0dXJuIGNvbnZlcnRFeHByZXNzaW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIHVuZGVmaW5lZCwgdHJ1ZSlcbiAgICB9XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiT3B0aW9uYWxTb21lXCIpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICB2YWx1ZTogY29udmVydEV4cHJlc3Npb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCwgZXhwZWN0ZWRUeXBlLnZhbHVlVHlwZSlcbiAgICB9LCB7c29tZTogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBOaWxOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibmlsIG91dHNpZGUgYW4gZXhwbGljaXQgb3B0aW9uYWwgY29udGV4dFwiLCBsb2NhdGlvbilcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUuYmxvY2spIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiY2FsbCBibG9ja1wiLCBub2RlTG9jYXRpb24obm9kZS5ibG9jaywgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUuY2FsbE9wZXJhdG9yTG9jICYmIHNsaWNlUHJpc21Tb3VyY2UoXG4gICAgc291cmNlLFxuICAgIG5vZGUuY2FsbE9wZXJhdG9yTG9jLnN0YXJ0T2Zmc2V0LFxuICAgIG5vZGUuY2FsbE9wZXJhdG9yTG9jLnN0YXJ0T2Zmc2V0ICsgbm9kZS5jYWxsT3BlcmF0b3JMb2MubGVuZ3RoXG4gICkgPT0gXCImLlwiKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBQYXJlbnRoZXNlc05vZGUgJiYgbm9kZS5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgJiYgbm9kZS5ib2R5LmJvZHkubGVuZ3RoID09IDEpIHtcbiAgICByZXR1cm4gY29udmVydEV4cHJlc3Npb24obm9kZS5ib2R5LmJvZHlbMF0sIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIGV4cGVjdGVkVHlwZSwgcHJlc2VydmVPcHRpb25hbClcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlKSB7XG4gICAgY29uc3QgaWRlbnRpZmllciA9IHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbiwgbmFtZTogbm9kZS5uYW1lfSwge25hbWU6IGxvY2F0aW9ufSlcblxuICAgIGlmICghcHJlc2VydmVPcHRpb25hbCAmJiBjb250ZXh0LmJpbmRpbmdzLmdldChub2RlLm5hbWUpPy5raW5kID09IFwiT3B0aW9uYWxUeXBlXCIpIHtcbiAgICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJPcHRpb25hbFVud3JhcFwiKSwgbG9jYXRpb24sIG9wZXJhbmQ6IGlkZW50aWZpZXJ9LCB7dW53cmFwOiBsb2NhdGlvbn0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGlkZW50aWZpZXJcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgU2VsZk5vZGUpIHtcbiAgICBpZiAoIWNvbnRleHQuY3VycmVudENsYXNzKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwic2VsZiBvdXRzaWRlIGEgcmVmZXJlbmNlIGNsYXNzXCIsIGxvY2F0aW9uKVxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtjbGFzc0lkOiAvKiogQHR5cGUge3N0cmluZ30gKi8gKGNvbnRleHQuY3VycmVudENsYXNzLmlkKSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVjZWl2ZXJFeHByZXNzaW9uXCIpLFxuICAgICAgbG9jYXRpb259LCB7cmVjZWl2ZXI6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW5zdGFuY2VWYXJpYWJsZVJlYWROb2RlKSB7XG4gICAgY29uc3QgZmllbGQgPSBjb250ZXh0LmN1cnJlbnRDbGFzcz8uZmllbGRzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gYEAke2NhbmRpZGF0ZS5uYW1lfWAgPT0gbm9kZS5uYW1lKVxuXG4gICAgaWYgKCFmaWVsZCB8fCAhY29udGV4dC5jdXJyZW50Q2xhc3MpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJwcml2YXRlIGluc3RhbmNlIGZpZWxkIG91dHNpZGUgaXRzIGRlY2xhcmluZyBjbGFzc1wiLCBsb2NhdGlvbilcbiAgICBjb25zdCByZWNlaXZlciA9IHdpdGhQYXJzZXJSYW5nZXMoe2NsYXNzSWQ6IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoY29udGV4dC5jdXJyZW50Q2xhc3MuaWQpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVjZWl2ZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbn0sIHtyZWNlaXZlcjogbG9jYXRpb259KVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2ZpZWxkOiAvKiogQHR5cGUge3N0cmluZ30gKi8gKGZpZWxkLmlkKSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUHJpdmF0ZUZpZWxkUmVhZFwiKSxcbiAgICAgIGxvY2F0aW9uLCByZWNlaXZlcn0sIHttZW1iZXI6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW50ZWdlck5vZGUpIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKG5vZGUudmFsdWUpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibm9uLXNhZmUgaW50ZWdlciBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkludGVnZXJMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZSB8fCBub2RlIGluc3RhbmNlb2YgRmFsc2VOb2RlKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJvb2xlYW5MaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IG5vZGUgaW5zdGFuY2VvZiBUcnVlTm9kZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFN0cmluZ05vZGUpIHtcbiAgICBjb25zdCBkZWNvZGVkID0gbm9kZS51bmVzY2FwZWRcblxuICAgIGlmICghZGVjb2RlZC52YWxpZEVuY29kaW5nIHx8IGRlY29kZWQuZW5jb2RpbmcgIT0gXCJ1dGYtOFwiIHx8IG5vZGUuaXNGb3JjZWRCaW5hcnlFbmNvZGluZygpIHx8XG4gICAgICAhaGFzT25seVVuaWNvZGVTY2FsYXJzKGRlY29kZWQudmFsdWUpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW52YWxpZCBVbmljb2RlIHN0cmluZyBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuICAgIH1cblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJTdHJpbmdMaXRlcmFsXCIpLCBsb2NhdGlvbiwgdmFsdWU6IGRlY29kZWQudmFsdWV9LCB7bGl0ZXJhbDogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBJbnRlcnBvbGF0ZWRTdHJpbmdOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiaW50ZXJwb2xhdGVkIHN0cmluZ1wiLCBsb2NhdGlvbilcblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIE9yTm9kZSAmJiBub2RlLmxlZnQgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlUmVhZE5vZGUgJiZcbiAgICBjb250ZXh0LmJpbmRpbmdzLmdldChub2RlLmxlZnQubmFtZSk/LmtpbmQgPT0gXCJPcHRpb25hbFR5cGVcIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJvcHRpb25hbCBkZWZhdWx0IHdpdGggfHxcIiwgcHJpc21Mb2NhdGlvbihub2RlLm9wZXJhdG9yTG9jLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIGlmIChleGFjdE5pbFRlc3Qobm9kZSwgc291cmNlKSkge1xuICAgIGNvbnN0IGNhbGwgPSAvKiogQHR5cGUge0NhbGxOb2RlfSAqLyAobm9kZSlcbiAgICBjb25zdCByZWNlaXZlciA9IC8qKiBAdHlwZSB7TG9jYWxWYXJpYWJsZVJlYWROb2RlfSAqLyAoY2FsbC5yZWNlaXZlcilcbiAgICBjb25zdCBvcGVyYW5kID0gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZGVudGlmaWVyRXhwcmVzc2lvbn0gKi8gKFxuICAgICAgY29udmVydEV4cHJlc3Npb24ocmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIHVuZGVmaW5lZCwgdHJ1ZSlcbiAgICApXG4gICAgY29uc3QgcHJlc2VudCA9IHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIk9wdGlvbmFsSXNQcmVzZW50XCIpLCBsb2NhdGlvbiwgb3BlcmFuZH0sIHtcbiAgICAgIG9wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKGNhbGwubWVzc2FnZUxvYyA/PyBjYWxsLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiVW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG9wZXJhbmQ6IHByZXNlbnRcbiAgICB9LCB7b3BlcmF0b3I6IHByaXNtTG9jYXRpb24oY2FsbC5tZXNzYWdlTG9jID8/IGNhbGwubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSksIFwiTm90XCIpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBBcnJheU5vZGUpIHtcbiAgICBpZiAoIW5vZGUub3BlbmluZ0xvYyB8fCAhbm9kZS5jbG9zaW5nTG9jKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwic3BlY2lhbCBhcnJheSBsaXRlcmFsXCIsIGxvY2F0aW9uKVxuICAgIGlmIChub2RlLmlzQ29udGFpbnNTcGxhdCgpKSB7XG4gICAgICBjb25zdCBzcGxhdCA9IG5vZGUuZWxlbWVudHMuZmluZCgoZWxlbWVudCkgPT4gZWxlbWVudC5jb25zdHJ1Y3Rvci5uYW1lID09IFwiU3BsYXROb2RlXCIpXG5cbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJhcnJheSBzcGxhdFwiLCBzcGxhdCA/IG5vZGVMb2NhdGlvbihzcGxhdCwgZmlsZW5hbWUsIHNvdXJjZSkgOiBsb2NhdGlvbilcbiAgICB9XG5cbiAgICBjb25zdCBlbGVtZW50VHlwZSA9IGV4cGVjdGVkVHlwZT8ua2luZCA9PSBcIkxpc3RUeXBlXCIgPyBleHBlY3RlZFR5cGUuZWxlbWVudFR5cGUgOiB1bmRlZmluZWRcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGVsZW1lbnRzOiBub2RlLmVsZW1lbnRzLm1hcCgoZWxlbWVudCkgPT4gY29udmVydEV4cHJlc3Npb24oZWxlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCwgZWxlbWVudFR5cGUpKSxcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkxpc3RMaXRlcmFsXCIpLFxuICAgICAgbG9jYXRpb25cbiAgICB9LCB7XG4gICAgICBjbG9zZTogcHJpc21Mb2NhdGlvbihub2RlLmNsb3NpbmdMb2MsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgb3BlbjogcHJpc21Mb2NhdGlvbihub2RlLm9wZW5pbmdMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSGFzaE5vZGUpIHtcbiAgICBjb25zdCB2YWx1ZVR5cGUgPSBleHBlY3RlZFR5cGU/LmtpbmQgPT0gXCJNYXBUeXBlXCIgfHwgZXhwZWN0ZWRUeXBlPy5raW5kID09IFwiT3JkZXJlZE1hcFR5cGVcIlxuICAgICAgPyBleHBlY3RlZFR5cGUudmFsdWVUeXBlIDogdW5kZWZpbmVkXG4gICAgY29uc3QgZW50cmllcyA9IG5vZGUuZWxlbWVudHMubWFwKChlbGVtZW50KSA9PiB7XG4gICAgICBpZiAoIShlbGVtZW50IGluc3RhbmNlb2YgQXNzb2NOb2RlKSB8fCAhZWxlbWVudC5vcGVyYXRvckxvYyB8fFxuICAgICAgICBzbGljZVByaXNtU291cmNlKHNvdXJjZSwgZWxlbWVudC5vcGVyYXRvckxvYy5zdGFydE9mZnNldCwgZWxlbWVudC5vcGVyYXRvckxvYy5zdGFydE9mZnNldCArIGVsZW1lbnQub3BlcmF0b3JMb2MubGVuZ3RoKSAhPSBcIj0+XCIpIHtcbiAgICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImhhc2ggZW50cnlcIiwgbm9kZUxvY2F0aW9uKGVsZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgICAgfVxuICAgICAgaWYgKCEoZWxlbWVudC5rZXkgaW5zdGFuY2VvZiBTdHJpbmdOb2RlKSkge1xuICAgICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibWFwIGtleSBvdGhlciB0aGFuIGEgc3RyaW5nIGxpdGVyYWxcIiwgbm9kZUxvY2F0aW9uKGVsZW1lbnQua2V5LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICAgIH1cbiAgICAgIGNvbnN0IGtleSA9IGNvbnZlcnRFeHByZXNzaW9uKGVsZW1lbnQua2V5LCBmaWxlbmFtZSwgc291cmNlLCBjb250ZXh0KVxuXG4gICAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICAgIGtleTogLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdHJpbmdMaXRlcmFsfSAqLyAoa2V5KSxcbiAgICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTWFwRW50cnlcIiksXG4gICAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24oZWxlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICAgIHZhbHVlOiBjb252ZXJ0RXhwcmVzc2lvbihlbGVtZW50LnZhbHVlLCBmaWxlbmFtZSwgc291cmNlLCBjb250ZXh0LCB2YWx1ZVR5cGUpXG4gICAgICB9LCB7b3BlcmF0b3I6IHByaXNtTG9jYXRpb24oZWxlbWVudC5vcGVyYXRvckxvYywgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICAgIH0pXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBlbnRyaWVzLFxuICAgICAga2luZDogZXhwZWN0ZWRUeXBlPy5raW5kID09IFwiT3JkZXJlZE1hcFR5cGVcIlxuICAgICAgICA/IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIk9yZGVyZWRNYXBMaXRlcmFsXCIpXG4gICAgICAgIDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTWFwTGl0ZXJhbFwiKSxcbiAgICAgIGxvY2F0aW9uXG4gICAgfSwge1xuICAgICAgY2xvc2U6IHByaXNtTG9jYXRpb24obm9kZS5jbG9zaW5nTG9jLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIG9wZW46IHByaXNtTG9jYXRpb24obm9kZS5vcGVuaW5nTG9jLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIChub2RlLnJlY2VpdmVyIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSB8fCBub2RlLnJlY2VpdmVyIGluc3RhbmNlb2YgQ29uc3RhbnRQYXRoTm9kZSkgJiYgbm9kZS5uYW1lID09IFwibmV3XCIgJiZcbiAgICBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jaykge1xuICAgIGNvbnN0IHJlY29yZE5hbWUgPSBjb25zdGFudFBhdGhOYW1lKG5vZGUucmVjZWl2ZXIpXG4gICAgY29uc3QgZGVjbGFyYXRpb24gPSBjb250ZXh0LnJlY29yZE5hbWVzLmdldChyZWNvcmROYW1lKVxuXG4gICAgaWYgKCFkZWNsYXJhdGlvbikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImNvbnN0cnVjdGlvbiBvZiBhIG5vbi1yZWNvcmQgY2xhc3NcIiwgbm9kZUxvY2F0aW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIGlmIChkZWNsYXJhdGlvbi5raW5kID09IFwiQ2xhc3NEZWNsYXJhdGlvblwiKSB7XG4gICAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7YXJndW1lbnRzOiAobm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfID8/IFtdKS5tYXAoKGFyZ3VtZW50LCBpbmRleCkgPT5cbiAgICAgICAgY29udmVydEV4cHJlc3Npb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIGRlY2xhcmF0aW9uLmNvbnN0cnVjdG9yLnBhcmFtZXRlcnNbaW5kZXhdPy50eXBlKSksXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJSZWZlcmVuY2VDb25zdHJ1Y3Rpb25cIiksIGxvY2F0aW9uLFxuICAgICAgcmVmZXJlbmNlOiByZWZlcmVuY2VUeXBlKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZGVjbGFyYXRpb24uaWQpLCBub2RlTG9jYXRpb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSkpfSxcbiAgICAgIHtjbGFzczogbm9kZUxvY2F0aW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgICB9XG4gICAgaWYgKGRlY2xhcmF0aW9uLmtpbmQgPT0gXCJFZmZlY3RSZXNvdXJjZURlY2xhcmF0aW9uXCIpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJvd25lZCByZXNvdXJjZSBjb25zdHJ1Y3Rpb25cIiwgbm9kZUxvY2F0aW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cbiAgICBjb25zdCB0eXBlQXJndW1lbnRzID0gZXhwZWN0ZWRUeXBlPy5raW5kID09IFwiUmVjb3JkVHlwZVwiICYmIGV4cGVjdGVkVHlwZS5kZWNsYXJhdGlvbklkID09IGRlY2xhcmF0aW9uLmlkXG4gICAgICA/IGV4cGVjdGVkVHlwZS5hcmd1bWVudHNcbiAgICAgIDogdW5kZWZpbmVkXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBhcmd1bWVudHM6IChub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18gPz8gW10pLm1hcCgoYXJndW1lbnQsIGluZGV4KSA9PlxuICAgICAgICBjb252ZXJ0RXhwcmVzc2lvbihhcmd1bWVudCwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCxcbiAgICAgICAgICBpbnN0YW50aWF0ZWRSZWNvcmRGaWVsZFR5cGUoZGVjbGFyYXRpb24sIHR5cGVBcmd1bWVudHMsIGluZGV4KSkpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVjb3JkQ29uc3RydWN0aW9uXCIpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICByZWNvcmQ6IHJlY29yZFR5cGUoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkZWNsYXJhdGlvbi5pZCksIG5vZGVMb2NhdGlvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgICAgdHlwZUFyZ3VtZW50cylcbiAgICB9LCB7cmVjb3JkOiBub2RlTG9jYXRpb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIG5vZGUubmFtZSA9PSBcIiFcIikge1xuICAgIGNvbnN0IG9wZXJhdG9yTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgaWYgKG5vZGUuY2FsbE9wZXJhdG9yTG9jKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicXVhbGlmaWVkIGJvb2xlYW4gbm90XCIsIG9wZXJhdG9yTG9jYXRpb24pXG4gICAgaWYgKG5vZGUubWVzc2FnZUxvYz8ubGVuZ3RoICE9IDEpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJwcmVjZWRlbmNlLXNlbnNpdGl2ZSBib29sZWFuIG5vdFwiLCBvcGVyYXRvckxvY2F0aW9uKVxuICAgIH1cbiAgICBpZiAobm9kZS5hcmd1bWVudHNfKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiYm9vbGVhbiBub3QgYXJndW1lbnQgbGlzdFwiLCBvcGVyYXRvckxvY2F0aW9uKVxuXG4gICAgY29uc3Qgb3BlcmFuZCA9IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG5cbiAgICBpZiAob3BlcmFuZC5raW5kID09IFwiVW5hcnlFeHByZXNzaW9uXCIgJiYgb3BlcmFuZC5vcGVyYW5kLmtpbmQgPT0gXCJPcHRpb25hbElzUHJlc2VudFwiKSB7XG4gICAgICByZXR1cm4gb3BlcmFuZC5vcGVyYW5kXG4gICAgfVxuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIlVuYXJ5RXhwcmVzc2lvblwiLFxuICAgICAgbG9jYXRpb24sXG4gICAgICBvcGVyYW5kXG4gICAgfSwge29wZXJhdG9yOiBvcGVyYXRvckxvY2F0aW9ufSksIFwiTm90XCIpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIG5vZGUubmFtZSA9PSBcIi1AXCIpIHtcbiAgICBjb25zdCBvcGVyYXRvckxvY2F0aW9uID0gcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmIChub2RlLmNhbGxPcGVyYXRvckxvYykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInF1YWxpZmllZCBpbnRlZ2VyIG5lZ2F0aW9uXCIsIG9wZXJhdG9yTG9jYXRpb24pXG4gICAgaWYgKG5vZGUuYXJndW1lbnRzXykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImludGVnZXIgbmVnYXRpb24gYXJndW1lbnQgbGlzdFwiLCBvcGVyYXRvckxvY2F0aW9uKVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiVW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG9wZXJhbmQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG4gICAgfSwge29wZXJhdG9yOiBvcGVyYXRvckxvY2F0aW9ufSksIFwiTmVnYXRlXCIpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBBbmROb2RlIHx8IG5vZGUgaW5zdGFuY2VvZiBPck5vZGUpIHtcbiAgICBjb25zdCBvcGVyYXRvckxvY2F0aW9uID0gcHJpc21Mb2NhdGlvbihub2RlLm9wZXJhdG9yTG9jLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHNvdXJjZU9wZXJhdG9yID0gc291cmNlLnNsaWNlKG9wZXJhdG9yTG9jYXRpb24uc3RhcnQub2Zmc2V0LCBvcGVyYXRvckxvY2F0aW9uLmVuZC5vZmZzZXQpXG5cbiAgICBpZiAoc291cmNlT3BlcmF0b3IgIT0gXCImJlwiICYmIHNvdXJjZU9wZXJhdG9yICE9IFwifHxcIikge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBgcHJlY2VkZW5jZS1zZW5zaXRpdmUgYm9vbGVhbiAke3NvdXJjZU9wZXJhdG9yfWAsIGxvY2F0aW9uKVxuICAgIH1cblxuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxlZnQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUubGVmdCwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCksXG4gICAgICBsb2NhdGlvbixcbiAgICAgIHJpZ2h0OiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnJpZ2h0LCBmaWxlbmFtZSwgc291cmNlLCBjb250ZXh0KVxuICAgIH0sIHtvcGVyYXRvcjogb3BlcmF0b3JMb2NhdGlvbn0pLCBub2RlIGluc3RhbmNlb2YgQW5kTm9kZSA/IFwiQW5kXCIgOiBcIk9yXCIpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIHJ1YnlCaW5hcnlPcGVyYXRpb25zLmhhcyhub2RlLm5hbWUpICYmIG5vZGUuY2FsbE9wZXJhdG9yTG9jICYmXG4gICAgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFxuICAgICAgXCJydWJ5XCIsXG4gICAgICBgcXVhbGlmaWVkIGJpbmFyeSBvcGVyYXRvciAke25vZGUubmFtZX1gLFxuICAgICAgcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICApXG4gIH1cblxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgcnVieUJpbmFyeU9wZXJhdGlvbnMuaGFzKG5vZGUubmFtZSkgJiYgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAxKSB7XG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiQmluYXJ5RXhwcmVzc2lvblwiLFxuICAgICAgbGVmdDogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCksXG4gICAgICBsb2NhdGlvbixcbiAgICAgIHJpZ2h0OiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dClcbiAgICB9LCB7b3BlcmF0b3I6IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSksIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCIpLkFkYXB0ZWRPcGVyYXRpb259ICovIChydWJ5QmluYXJ5T3BlcmF0aW9ucy5nZXQobm9kZS5uYW1lKSkpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIG5vZGUubmFtZSA9PSBcIltdXCIgJiYgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAxICYmXG4gICAgIW5vZGUuY2FsbE9wZXJhdG9yTG9jICYmICFub2RlLmJsb2NrKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgY29sbGVjdGlvbjogY29udmVydEV4cHJlc3Npb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCksXG4gICAgICBpbmRleDogY29udmVydEV4cHJlc3Npb24obm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0sIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTGlzdEluZGV4RXhwcmVzc2lvblwiKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgdG90YWxpdHk6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcInByb3ZlblwiKVxuICAgIH0sIHtvcGVyYXRvcjogcHJpc21Mb2NhdGlvbihub2RlLm9wZW5pbmdMb2MgPz8gbm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiZmV0Y2hcIiAmJiBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEgJiZcbiAgICBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jaykge1xuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGNvbGxlY3Rpb246IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpLFxuICAgICAga2V5OiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCksXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJNYXBMb29rdXBFeHByZXNzaW9uXCIpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICB0b3RhbGl0eTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiZmFpbC1vbi1hYnNlbmNlXCIpXG4gICAgfSwge29wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSAmJiBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jaykge1xuICAgIGNvbnN0IGNhbGxlZSA9IGAke25vZGUucmVjZWl2ZXIubmFtZX0uJHtub2RlLm5hbWV9YFxuICAgIGNvbnN0IHNpZ25hdHVyZSA9IGNvbnRleHQuZnVuY3Rpb25zLmdldChjYWxsZWUpXG5cbiAgICBpZiAoc2lnbmF0dXJlKSB7XG4gICAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICAgIGFyZ3VtZW50czogKG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXyA/PyBbXSkubWFwKChhcmd1bWVudCwgaW5kZXgpID0+XG4gICAgICAgICAgY29udmVydEV4cHJlc3Npb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIHNpZ25hdHVyZS5wYXJhbWV0ZXJzW2luZGV4XT8udHlwZSxcbiAgICAgICAgICAgIHByZXNlcnZlc0dlbmVyaWNPcHRpb25hbEV2aWRlbmNlKHNpZ25hdHVyZSwgaW5kZXgpKSksXG4gICAgICAgIGNhbGxlZSxcbiAgICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQ2FsbEV4cHJlc3Npb25cIiksXG4gICAgICAgIGxvY2F0aW9uXG4gICAgICB9LCB7Y2FsbGVlOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG4gICAgfVxuICB9XG4gIGlmIChub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgbm9kZS5yZWNlaXZlciAmJiBub2RlLm5hbWUgPT0gXCJzaXplXCIgJiYgIW5vZGUuYXJndW1lbnRzXyAmJiBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jaykge1xuICAgIGNvbnN0IHJlY2VpdmVyVHlwZSA9IGtub3duVmFsdWVFeHByZXNzaW9uVHlwZShub2RlLnJlY2VpdmVyLCBjb250ZXh0KVxuXG4gICAgaWYgKHJlY2VpdmVyVHlwZT8ua2luZCA9PSBcIlJlY29yZFR5cGVcIikge1xuICAgICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgICBmaWVsZDogbm9kZS5uYW1lLFxuICAgICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJNZW1iZXJSZWFkXCIpLFxuICAgICAgICBsb2NhdGlvbixcbiAgICAgICAgcmVjZWl2ZXI6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG4gICAgICB9LCB7bWVtYmVyOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG4gICAgfVxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGNvbGxlY3Rpb246IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQ29sbGVjdGlvblNpemVFeHByZXNzaW9uXCIpLFxuICAgICAgbG9jYXRpb25cbiAgICB9LCB7b3BlcmF0b3I6IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlUmVhZE5vZGUgJiYgbm9kZS5uYW1lID09IFwibWVzc2FnZVwiICYmXG4gICAgIW5vZGUuYXJndW1lbnRzXyAmJiBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jayAmJiBjb250ZXh0LmJpbmRpbmdzLmdldChub2RlLnJlY2VpdmVyLm5hbWUpPy5raW5kID09IFwiRXJyb3JUeXBlXCIpIHtcbiAgICBjb25zdCByZWNlaXZlckxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJFcnJvck1lc3NhZ2VSZWFkXCIpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICByZWNlaXZlcjogd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksIGxvY2F0aW9uOiByZWNlaXZlckxvY2F0aW9uLCBuYW1lOiBub2RlLnJlY2VpdmVyLm5hbWV9LCB7XG4gICAgICAgIG5hbWU6IHJlY2VpdmVyTG9jYXRpb25cbiAgICAgIH0pXG4gICAgfSwge21lbWJlcjogcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG4gIGlmIChub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgbm9kZS5yZWNlaXZlciAmJiBub2RlLmNhbGxPcGVyYXRvckxvYyAmJiAhbm9kZS5ibG9jayAmJlxuICAgIGtub3duVmFsdWVFeHByZXNzaW9uVHlwZShub2RlLnJlY2VpdmVyLCBjb250ZXh0KT8ua2luZCA9PSBcIlJlZmVyZW5jZVR5cGVcIikge1xuICAgIGNvbnN0IHJlY2VpdmVyVHlwZSA9IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUmVmZXJlbmNlVHlwZX0gKi8gKGtub3duVmFsdWVFeHByZXNzaW9uVHlwZShub2RlLnJlY2VpdmVyLCBjb250ZXh0KSlcbiAgICBjb25zdCBtZXRob2QgPSBjb250ZXh0LmNsYXNzZXMuZ2V0KHJlY2VpdmVyVHlwZS5kZWNsYXJhdGlvbklkKT8ubWV0aG9kcy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5uYW1lID09IG5vZGUubmFtZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHthcmd1bWVudHM6IChub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18gPz8gW10pLm1hcCgoYXJndW1lbnQsIGluZGV4KSA9PlxuICAgICAgY29udmVydEV4cHJlc3Npb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIG1ldGhvZD8ucGFyYW1ldGVyc1tpbmRleF0/LnR5cGUpKSxcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJNZXRob2RDYWxsRXhwcmVzc2lvblwiKSwgbG9jYXRpb24sIG1ldGhvZDogbWV0aG9kPy5pZCA/PyBub2RlLm5hbWUsXG4gICAgcmVjZWl2ZXI6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpfSxcbiAgICB7bWVtYmVyOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIG5vZGUuY2FsbE9wZXJhdG9yTG9jICYmICFub2RlLmFyZ3VtZW50c18gJiYgIW5vZGUuYmxvY2spIHtcbiAgICBpZiAoW1wic2VuZFwiLCBcInB1YmxpY19zZW5kXCIsIFwiX19zZW5kX19cIiwgXCJpbnN0YW5jZV92YXJpYWJsZV9nZXRcIiwgXCJtZXRob2RcIl0uaW5jbHVkZXMobm9kZS5uYW1lKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImR5bmFtaWMgb3IgcmVmbGVjdGl2ZSBtZW1iZXIgYWNjZXNzXCIsIHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBmaWVsZDogbm9kZS5uYW1lLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTWVtYmVyUmVhZFwiKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmVjZWl2ZXI6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG4gICAgfSwge21lbWJlcjogcHJpc21Mb2NhdGlvbihub2RlLm1lc3NhZ2VMb2MgPz8gbm9kZS5sb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiAhbm9kZS5yZWNlaXZlcikge1xuICAgIGlmIChbXCJzZW5kXCIsIFwicHVibGljX3NlbmRcIiwgXCJfX3NlbmRfX1wiXS5pbmNsdWRlcyhub2RlLm5hbWUpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiZHluYW1pYyBjYWxsXCIsIHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jID8/IG5vZGUubG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cbiAgICBjb25zdCBzaWduYXR1cmUgPSBjb250ZXh0LmZ1bmN0aW9ucy5nZXQobm9kZS5uYW1lKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgYXJndW1lbnRzOiAobm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfID8/IFtdKS5tYXAoKGFyZ3VtZW50LCBpbmRleCkgPT5cbiAgICAgICAgY29udmVydEV4cHJlc3Npb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIHNpZ25hdHVyZT8ucGFyYW1ldGVyc1tpbmRleF0/LnR5cGUsXG4gICAgICAgICAgcHJlc2VydmVzR2VuZXJpY09wdGlvbmFsRXZpZGVuY2Uoc2lnbmF0dXJlLCBpbmRleCkpKSxcbiAgICAgIGNhbGxlZTogbm9kZS5uYW1lLFxuICAgICAga2luZDogXCJDYWxsRXhwcmVzc2lvblwiLFxuICAgICAgbG9jYXRpb25cbiAgICB9LCB7Y2FsbGVlOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyKSB7XG4gICAgY29uc3QgdW5zdXBwb3J0ZWRMb2NhdGlvbiA9ICFub2RlLmNhbGxPcGVyYXRvckxvYyAmJiBub2RlLm1lc3NhZ2VMb2MgJiYgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAxXG4gICAgICA/IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jLCBmaWxlbmFtZSwgc291cmNlKVxuICAgICAgOiBub2RlTG9jYXRpb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCB1bnN1cHBvcnRlZExvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIFJlc29sdmVzIG9ubHkgcmVzdWx0IHR5cGVzIGVzdGFibGlzaGVkIGJ5IGV4cGxpY2l0IHNpZ25hdHVyZXMgYW5kIGJpbmRpbmdzLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gUGFyc2VyLW93bmVkIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0Z1bmN0aW9uUmV0dXJuVHlwZSB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yVHlwZSB8IHVuZGVmaW5lZH0gS25vd24gcmVzdWx0IHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGtub3duRXhwcmVzc2lvblR5cGUobm9kZSwgY29udGV4dCkge1xuICBpZiAobm9kZSBpbnN0YW5jZW9mIFBhcmVudGhlc2VzTm9kZSAmJiBub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSAmJiBub2RlLmJvZHkuYm9keS5sZW5ndGggPT0gMSkge1xuICAgIHJldHVybiBrbm93bkV4cHJlc3Npb25UeXBlKG5vZGUuYm9keS5ib2R5WzBdLCBjb250ZXh0KVxuICB9XG4gIGlmIChub2RlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlKSByZXR1cm4gY29udGV4dC5iaW5kaW5ncy5nZXQobm9kZS5uYW1lKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFub2RlLnJlY2VpdmVyKSB7XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gY29udGV4dC5mdW5jdGlvbnMuZ2V0KG5vZGUubmFtZSlcblxuICAgIGlmIChzaWduYXR1cmUpIHJldHVybiBrbm93bkNhbGxSZXR1cm5UeXBlKHNpZ25hdHVyZSwgKG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXyA/PyBbXSkubWFwKChhcmd1bWVudCkgPT5cbiAgICAgIGtub3duRXhwcmVzc2lvblR5cGUoYXJndW1lbnQsIGNvbnRleHQpKSlcbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBDb25zdGFudFJlYWROb2RlKSB7XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gY29udGV4dC5mdW5jdGlvbnMuZ2V0KGAke25vZGUucmVjZWl2ZXIubmFtZX0uJHtub2RlLm5hbWV9YClcblxuICAgIGlmIChzaWduYXR1cmUpIHJldHVybiBrbm93bkNhbGxSZXR1cm5UeXBlKHNpZ25hdHVyZSwgKG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXyA/PyBbXSkubWFwKChhcmd1bWVudCkgPT5cbiAgICAgIGtub3duRXhwcmVzc2lvblR5cGUoYXJndW1lbnQsIGNvbnRleHQpKSlcbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiW11cIikge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25UeXBlID0ga25vd25WYWx1ZUV4cHJlc3Npb25UeXBlKG5vZGUucmVjZWl2ZXIsIGNvbnRleHQpXG5cbiAgICBpZiAoY29sbGVjdGlvblR5cGU/LmtpbmQgPT0gXCJMaXN0VHlwZVwiKSByZXR1cm4gY29sbGVjdGlvblR5cGUuZWxlbWVudFR5cGVcbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgJiYgbm9kZS5uYW1lID09IFwiZmV0Y2hcIikge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25UeXBlID0ga25vd25WYWx1ZUV4cHJlc3Npb25UeXBlKG5vZGUucmVjZWl2ZXIsIGNvbnRleHQpXG5cbiAgICBpZiAoY29sbGVjdGlvblR5cGU/LmtpbmQgPT0gXCJNYXBUeXBlXCIgfHwgY29sbGVjdGlvblR5cGU/LmtpbmQgPT0gXCJPcmRlcmVkTWFwVHlwZVwiKSByZXR1cm4gY29sbGVjdGlvblR5cGUudmFsdWVUeXBlXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiAobm9kZS5yZWNlaXZlciBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUgfHwgbm9kZS5yZWNlaXZlciBpbnN0YW5jZW9mIENvbnN0YW50UGF0aE5vZGUpICYmIG5vZGUubmFtZSA9PSBcIm5ld1wiKSB7XG4gICAgY29uc3QgZGVjbGFyYXRpb24gPSBjb250ZXh0LnJlY29yZE5hbWVzLmdldChjb25zdGFudFBhdGhOYW1lKG5vZGUucmVjZWl2ZXIpKVxuXG4gICAgaWYgKGRlY2xhcmF0aW9uPy5pZCkgcmV0dXJuIGRlY2xhcmF0aW9uLmtpbmQgPT0gXCJDbGFzc0RlY2xhcmF0aW9uXCJcbiAgICAgID8ge2RlY2xhcmF0aW9uSWQ6IGRlY2xhcmF0aW9uLmlkLCBraW5kOiBcIlJlZmVyZW5jZVR5cGVcIn1cbiAgICAgIDoge2RlY2xhcmF0aW9uSWQ6IGRlY2xhcmF0aW9uLmlkLCBraW5kOiBcIlJlY29yZFR5cGVcIn1cbiAgfVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIFNlbGZOb2RlICYmIGNvbnRleHQuY3VycmVudENsYXNzPy5pZCkgcmV0dXJuIHtkZWNsYXJhdGlvbklkOiBjb250ZXh0LmN1cnJlbnRDbGFzcy5pZCwga2luZDogXCJSZWZlcmVuY2VUeXBlXCJ9XG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW5zdGFuY2VWYXJpYWJsZVJlYWROb2RlICYmIGNvbnRleHQuY3VycmVudENsYXNzKSB7XG4gICAgcmV0dXJuIGNvbnRleHQuY3VycmVudENsYXNzLmZpZWxkcy5maW5kKChmaWVsZCkgPT4gYEAke2ZpZWxkLm5hbWV9YCA9PSBub2RlLm5hbWUpPy50eXBlXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiBub2RlLnJlY2VpdmVyICYmIG5vZGUuY2FsbE9wZXJhdG9yTG9jKSB7XG4gICAgY29uc3QgcmVjZWl2ZXIgPSBrbm93blZhbHVlRXhwcmVzc2lvblR5cGUobm9kZS5yZWNlaXZlciwgY29udGV4dClcblxuICAgIGlmIChyZWNlaXZlcj8ua2luZCA9PSBcIlJlZmVyZW5jZVR5cGVcIikge1xuICAgICAgcmV0dXJuIGNvbnRleHQuY2xhc3Nlcy5nZXQocmVjZWl2ZXIuZGVjbGFyYXRpb25JZCk/Lm1ldGhvZHMuZmluZCgobWV0aG9kKSA9PiBtZXRob2QubmFtZSA9PSBub2RlLm5hbWUpPy5yZXR1cm5UeXBlXG4gICAgfVxuICAgIGlmIChub2RlLmFyZ3VtZW50c18pIHJldHVybiB1bmRlZmluZWRcbiAgICBpZiAocmVjZWl2ZXI/LmtpbmQgIT0gXCJSZWNvcmRUeXBlXCIpIHJldHVybiB1bmRlZmluZWRcbiAgICBjb25zdCBkZWNsYXJhdGlvbiA9IGNvbnRleHQucmVjb3Jkcy5nZXQocmVjZWl2ZXIuZGVjbGFyYXRpb25JZClcbiAgICBjb25zdCBpbmRleCA9IGRlY2xhcmF0aW9uPy5maWVsZHMuZmluZEluZGV4KChmaWVsZCkgPT4gZmllbGQubmFtZSA9PSBub2RlLm5hbWUpID8/IC0xXG5cbiAgICByZXR1cm4gZGVjbGFyYXRpb24gPyBpbnN0YW50aWF0ZWRSZWNvcmRGaWVsZFR5cGUoZGVjbGFyYXRpb24sIHJlY2VpdmVyLmFyZ3VtZW50cywgaW5kZXgpIDogdW5kZWZpbmVkXG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkXG59XG5cbi8qKlxuICogUmVzb2x2ZXMgdGhlIHZhbHVlIHR5cGUgcHJvZHVjZWQgYnkgdGhlIGZyb250ZW5kJ3MgaW1wbGljaXQgb3B0aW9uYWwtYmluZGluZyB1bndyYXAuXG4gKiBTZW1hbnRpYyB2YWxpZGF0aW9uIHNlcGFyYXRlbHkgcHJvdmVzIHRoYXQgdGhlIHVud3JhcCBvY2N1cnMgb25seSBvbiBhIHByZXNlbnQgcGF0aC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIFBhcnNlci1vd25lZCBleHByZXNzaW9uLlxuICogQHBhcmFtIHtSdWJ5Q29udmVyc2lvbkNvbnRleHR9IGNvbnRleHQgLSBUeXBlZCBsZXhpY2FsIGNvbnRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNGdW5jdGlvblJldHVyblR5cGUgfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FcnJvclR5cGUgfCB1bmRlZmluZWR9IENvbnZlcnRlZCB2YWx1ZSB0eXBlLlxuICovXG5mdW5jdGlvbiBrbm93blZhbHVlRXhwcmVzc2lvblR5cGUobm9kZSwgY29udGV4dCkge1xuICBpZiAobm9kZSBpbnN0YW5jZW9mIFBhcmVudGhlc2VzTm9kZSAmJiBub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSAmJiBub2RlLmJvZHkuYm9keS5sZW5ndGggPT0gMSkge1xuICAgIHJldHVybiBrbm93blZhbHVlRXhwcmVzc2lvblR5cGUobm9kZS5ib2R5LmJvZHlbMF0sIGNvbnRleHQpXG4gIH1cbiAgY29uc3QgdHlwZSA9IGtub3duRXhwcmVzc2lvblR5cGUobm9kZSwgY29udGV4dClcblxuICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVSZWFkTm9kZSAmJiB0eXBlPy5raW5kID09IFwiT3B0aW9uYWxUeXBlXCIgPyB0eXBlLnZhbHVlVHlwZSA6IHR5cGVcbn1cblxuLyoqXG4gKiBSZWNvZ25pemVzIG9ubHkgdGhlIHBhcnNlci1iYWNrZWQgYGlkZW50aWZpZXIubmlsP2Agc3BlbGxpbmcgdXNlZCBieSBUYXNrIDAwNy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIENhbmRpZGF0ZSBQcmlzbSBleHByZXNzaW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoaXMgaXMgb25lIGV4YWN0IG5pbCB0ZXN0LlxuICovXG5mdW5jdGlvbiBleGFjdE5pbFRlc3Qobm9kZSwgc291cmNlKSB7XG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgIShub2RlLnJlY2VpdmVyIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlKSB8fFxuICAgIG5vZGUubmFtZSAhPSBcIm5pbD9cIiB8fCAhbm9kZS5jYWxsT3BlcmF0b3JMb2MgfHwgbm9kZS5hcmd1bWVudHNfIHx8IG5vZGUuYmxvY2spIHJldHVybiBmYWxzZVxuXG4gIHJldHVybiBzbGljZVByaXNtU291cmNlKFxuICAgIHNvdXJjZSxcbiAgICBub2RlLmNhbGxPcGVyYXRvckxvYy5zdGFydE9mZnNldCxcbiAgICBub2RlLmNhbGxPcGVyYXRvckxvYy5zdGFydE9mZnNldCArIG5vZGUuY2FsbE9wZXJhdG9yTG9jLmxlbmd0aFxuICApID09IFwiLlwiXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIGV4cGxpY2l0IFJ1YnkgcmV0dXJuLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gUHJpc20gbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udmVyc2lvbiBjb250ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJldHVyblN0YXRlbWVudH0gU2VtYW50aWMgcmV0dXJuLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UmV0dXJuKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIShub2RlIGluc3RhbmNlb2YgUmV0dXJuTm9kZSkgfHwgKG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggPz8gMCkgPiAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi4obm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfWzBdID8ge2V4cHJlc3Npb246IGNvbnZlcnRFeHByZXNzaW9uKFxuICAgICAgbm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0sXG4gICAgICBmaWxlbmFtZSxcbiAgICAgIHNvdXJjZSxcbiAgICAgIGNvbnRleHQsXG4gICAgICBjb250ZXh0LnJldHVyblR5cGU/LmtpbmQgPT0gXCJUeXBlUmVmZXJlbmNlXCIgJiYgY29udGV4dC5yZXR1cm5UeXBlLm5hbWUgPT0gXCJ2b2lkXCIgPyB1bmRlZmluZWQgOiBjb250ZXh0LnJldHVyblR5cGVcbiAgICApfSA6IHt9KSxcbiAgICBraW5kOiBcIlJldHVyblN0YXRlbWVudFwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cblxuLyoqXG4gKiBSZWFkcyBQcmlzbS1vd25lZCBSQlMtc3R5bGUgdHlwZSBjb21tZW50cyBkaXJlY3RseSBwcmVjZWRpbmcgYSBkZWZpbml0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHt7bG9jYXRpb246IGltcG9ydChcIkBydWJ5L3ByaXNtXCIpLkxvY2F0aW9ufX0gbm9kZSAtIENvbW1lbnQgb3duZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtzdHJpbmd9IFtvd25lcklkXSAtIFN0YWJsZSBkZWNsYXJhdGlvbiBpZGVudGl0eS5cbiAqIEByZXR1cm5zIHt7cGFyYW1ldGVyczogTWFwPHN0cmluZywge2xvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgc291cmNlVHlwZTogc3RyaW5nfT4sIHJldHVyblR5cGU6IHtsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHNvdXJjZVR5cGU6IHN0cmluZ30gfCB1bmRlZmluZWQsIHR5cGVQYXJhbWV0ZXJzPzogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVBhcmFtZXRlcltdfX0gRGVjbGFyZWQgdHlwZXMuXG4gKi9cbmZ1bmN0aW9uIHR5cGVDb21tZW50cyhjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgb3duZXJJZCkge1xuICBjb25zdCBwcmVjZWRpbmcgPSBhc3NvY2lhdGVkQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVyVHlwZXMgPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHt7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9IHwgdW5kZWZpbmVkfSAqL1xuICBsZXQgcmV0dXJuVHlwZVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVQYXJhbWV0ZXJbXX0gKi9cbiAgY29uc3QgdHlwZVBhcmFtZXRlcnMgPSBbXVxuXG4gIGZvciAoY29uc3QgY29tbWVudCBvZiBwcmVjZWRpbmcpIHtcbiAgICBjb25zdCB3b3JkcyA9IGNvbW1lbnRUb2tlbnMoY29tbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmICh3b3Jkc1swXT8udGV4dCA9PSBcIkBwYXJhbVwiICYmIHdvcmRzLmxlbmd0aCA+PSAzKSB7XG4gICAgICBpZiAocGFyYW1ldGVyVHlwZXMuaGFzKHdvcmRzWzFdLnRleHQpKSB7XG4gICAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJkdXBsaWNhdGUgcGFyYW1ldGVyIGFubm90YXRpb25cIiwgd29yZHNbMV0ubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBwYXJhbWV0ZXJUeXBlcy5zZXQod29yZHNbMV0udGV4dCwgam9pbmVkQ29tbWVudFRva2VuKHdvcmRzLCAyLCBzb3VyY2UpKVxuICAgIH0gZWxzZSBpZiAod29yZHNbMF0/LnRleHQgPT0gXCJAcmV0dXJuXCIgJiYgd29yZHMubGVuZ3RoID49IDIpIHtcbiAgICAgIGlmIChyZXR1cm5UeXBlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiZHVwbGljYXRlIHJldHVybiBhbm5vdGF0aW9uXCIsIHdvcmRzWzFdLmxvY2F0aW9uKVxuICAgICAgcmV0dXJuVHlwZSA9IGpvaW5lZENvbW1lbnRUb2tlbih3b3JkcywgMSwgc291cmNlKVxuICAgIH0gZWxzZSBpZiAod29yZHNbMF0/LnRleHQgPT0gXCJAdGVtcGxhdGVcIiAmJiB3b3Jkcy5sZW5ndGggPT0gMiAmJiBvd25lcklkICYmXG4gICAgICAvXltBLVphLXpfXVtBLVphLXowLTlfXSokL3UudGVzdCh3b3Jkc1sxXS50ZXh0KSkge1xuICAgICAgdHlwZVBhcmFtZXRlcnMucHVzaCh3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgICAgaWQ6IGAke293bmVySWR9OnR5cGU6JHt0eXBlUGFyYW1ldGVycy5sZW5ndGh9YCxcbiAgICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiVHlwZVBhcmFtZXRlclwiKSxcbiAgICAgICAgbG9jYXRpb246IHdvcmRzWzFdLmxvY2F0aW9uLFxuICAgICAgICBuYW1lOiB3b3Jkc1sxXS50ZXh0XG4gICAgICB9LCB7bmFtZTogd29yZHNbMV0ubG9jYXRpb259KSlcbiAgICB9IGVsc2UgaWYgKHdvcmRzWzBdPy50ZXh0Py5zdGFydHNXaXRoKFwiQHRlbXBsYXRlXCIpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiYm91bmRlZCwgZGVmYXVsdGVkLCB2YXJpYW50LCBvciBtYWxmb3JtZWQgdHlwZSBwYXJhbWV0ZXJcIiwgd29yZHNbMV0/LmxvY2F0aW9uID8/IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9IGVsc2UgaWYgKHdvcmRzWzBdPy50ZXh0Py5zdGFydHNXaXRoKFwiQHBhcmFtXCIpIHx8IHdvcmRzWzBdPy50ZXh0Py5zdGFydHNXaXRoKFwiQHJldHVyblwiKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1hbGZvcm1lZCBmdW5jdGlvbiB0eXBlIGFubm90YXRpb25cIiwgbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7cGFyYW1ldGVyczogcGFyYW1ldGVyVHlwZXMsIHJldHVyblR5cGUsIC4uLih0eXBlUGFyYW1ldGVycy5sZW5ndGggPiAwID8ge3R5cGVQYXJhbWV0ZXJzfSA6IHt9KX1cbn1cblxuLyoqXG4gKiBSZWpvaW5zIGEgYm91bmRlZCBtZXRhZGF0YSBzdWZmaXggd2hpbGUgcmV0YWluaW5nIGl0cyBwYXJzZXItb3duZWQgcmFuZ2UuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHRleHQ6IHN0cmluZ31bXX0gdG9rZW5zIC0gQ29tbWVudCB0b2tlbnMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgLSBGaXJzdCBzdWZmaXggdG9rZW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHNvdXJjZVR5cGU6IHN0cmluZ319IEpvaW5lZCB0b2tlbi5cbiAqL1xuZnVuY3Rpb24gam9pbmVkQ29tbWVudFRva2VuKHRva2Vucywgc3RhcnQsIHNvdXJjZSkge1xuICBjb25zdCBmaXJzdCA9IHRva2Vuc1tzdGFydF1cbiAgY29uc3QgbGFzdCA9IHRva2Vucy5hdCgtMSlcblxuICBpZiAoIWZpcnN0IHx8ICFsYXN0KSB0aHJvdyBuZXcgRXJyb3IoXCJSdWJ5IG1ldGFkYXRhIHN1ZmZpeCB1bmV4cGVjdGVkbHkgZGlzYXBwZWFyZWQuXCIpXG4gIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaXJzdC5sb2NhdGlvbi5maWxlbmFtZSwgc291cmNlLCBmaXJzdC5sb2NhdGlvbi5zdGFydC5vZmZzZXQsIGxhc3QubG9jYXRpb24uZW5kLm9mZnNldClcblxuICByZXR1cm4ge2xvY2F0aW9uLCBzb3VyY2VUeXBlOiBzb3VyY2Uuc2xpY2UobG9jYXRpb24uc3RhcnQub2Zmc2V0LCBsb2NhdGlvbi5lbmQub2Zmc2V0KX1cbn1cblxuLyoqXG4gKiBMZXhlcyB3aGl0ZXNwYWNlLXNlcGFyYXRlZCBtZXRhZGF0YSB0b2tlbnMgaW5zaWRlIGEgUHJpc20tb3duZWQgUnVieSBjb21tZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudH0gY29tbWVudCAtIFByaXNtIGNvbW1lbnQgdG9rZW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3tsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHRleHQ6IHN0cmluZ31bXX0gTWV0YWRhdGEgdG9rZW5zLlxuICovXG5mdW5jdGlvbiBjb21tZW50VG9rZW5zKGNvbW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3Qgc3RhcnQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0KVxuICBjb25zdCBlbmQgPSB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGgpXG4gIGNvbnN0IHRva2VucyA9IFtdXG4gIGxldCBvZmZzZXQgPSBzdGFydCArIDFcblxuICB3aGlsZSAob2Zmc2V0IDwgZW5kKSB7XG4gICAgd2hpbGUgKG9mZnNldCA8IGVuZCAmJiBpc1J1YnlNZXRhZGF0YVdoaXRlc3BhY2Uoc291cmNlW29mZnNldF0pKSBvZmZzZXQrK1xuICAgIGNvbnN0IHRva2VuU3RhcnQgPSBvZmZzZXRcblxuICAgIHdoaWxlIChvZmZzZXQgPCBlbmQgJiYgIWlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShzb3VyY2Vbb2Zmc2V0XSkpIG9mZnNldCsrXG4gICAgaWYgKHRva2VuU3RhcnQgPCBvZmZzZXQpIHtcbiAgICAgIHRva2Vucy5wdXNoKHtsb2NhdGlvbjogbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCB0b2tlblN0YXJ0LCBvZmZzZXQpLCB0ZXh0OiBzb3VyY2Uuc2xpY2UodG9rZW5TdGFydCwgb2Zmc2V0KX0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRva2Vuc1xufVxuXG4vKipcbiAqIENoZWNrcyBvbmUgUnVieSBtZXRhZGF0YSBzZXBhcmF0b3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhcmFjdGVyIC0gU291cmNlIGNoYXJhY3Rlci5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGl0IHNlcGFyYXRlcyBtZXRhZGF0YSB0b2tlbnMuXG4gKi9cbmZ1bmN0aW9uIGlzUnVieU1ldGFkYXRhV2hpdGVzcGFjZShjaGFyYWN0ZXIpIHtcbiAgcmV0dXJuIGNoYXJhY3RlciA9PSBcIiBcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHRcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXG5cIlxufVxuXG4vKipcbiAqIFNlbGVjdHMgb25seSB0aGUgY29udGlndW91cyBjb21tZW50IGJsb2NrIGltbWVkaWF0ZWx5IGJlZm9yZSBhIGRlZmluaXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjogaW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTG9jYXRpb259fSBub2RlIC0gQ29tbWVudCBvd25lci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiQHJ1YnkvcHJpc20vc3JjL2Rlc2VyaWFsaXplLmpzXCIpLkNvbW1lbnRbXX0gQXNzb2NpYXRlZCBjb21tZW50cy5cbiAqL1xuZnVuY3Rpb24gYXNzb2NpYXRlZENvbW1lbnRzKGNvbW1lbnRzLCBub2RlLCBzb3VyY2UpIHtcbiAgY29uc3QgcHJlY2VkaW5nID0gY29tbWVudHMuZmlsdGVyKChjb21tZW50KSA9PiBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0IDwgbm9kZS5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgICAuc29ydCgobGVmdCwgcmlnaHQpID0+IGxlZnQubG9jYXRpb24uc3RhcnRPZmZzZXQgLSByaWdodC5sb2NhdGlvbi5zdGFydE9mZnNldClcbiAgY29uc3QgYXNzb2NpYXRlZCA9IFtdXG4gIGxldCBib3VuZGFyeSA9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXRcblxuICBmb3IgKGxldCBpbmRleCA9IHByZWNlZGluZy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgY29uc3QgY29tbWVudCA9IHByZWNlZGluZ1tpbmRleF1cbiAgICBjb25zdCBlbmRPZmZzZXQgPSBjb21tZW50LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgY29tbWVudC5sb2NhdGlvbi5sZW5ndGhcbiAgICBjb25zdCBnYXAgPSBzbGljZVByaXNtU291cmNlKHNvdXJjZSwgZW5kT2Zmc2V0LCBib3VuZGFyeSlcblxuICAgIGlmICghaXNJbW1lZGlhdGVDb21tZW50R2FwKGdhcCkpIGJyZWFrXG5cbiAgICBhc3NvY2lhdGVkLnVuc2hpZnQoY29tbWVudClcbiAgICBib3VuZGFyeSA9IGNvbW1lbnQubG9jYXRpb24uc3RhcnRPZmZzZXRcbiAgfVxuXG4gIHJldHVybiBhc3NvY2lhdGVkXG59XG5cbi8qKlxuICogUmVhZHMgb25lIGV4YWN0IFJ1YnkgbG9jYWwgdHlwZSBjYXJyaWVyIGFuZCBpbW11dGFiaWxpdHkgbWFya2VyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtMb2NhbFZhcmlhYmxlV3JpdGVOb2RlfSBub2RlIC0gTG9jYWwgd3JpdGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZWNvcmREZWNsYXJhdGlvbiB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FZmZlY3RSZXNvdXJjZURlY2xhcmF0aW9uPn0gcmVjb3JkTmFtZXMgLSBOb21pbmFsIGRlY2xhcmF0aW9ucyBieSBzb3VyY2UgbmFtZS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVBhcmFtZXRlcj59IFt0eXBlUGFyYW1ldGVyc10gLSBEZWNsYXJhdGlvbi1zY29wZWQgcGFyYW1ldGVycy5cbiAqIEByZXR1cm5zIHt7aW1tdXRhYmxlOiBib29sZWFuLCB0eXBlOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY1ZhbHVlVHlwZX0gfCB1bmRlZmluZWR9IE1ldGFkYXRhIHdoZW4gcHJlc2VudC5cbiAqL1xuZnVuY3Rpb24gbG9jYWxNZXRhZGF0YShjb21tZW50cywgbm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgcmVjb3JkTmFtZXMsIHR5cGVQYXJhbWV0ZXJzID0gbmV3IE1hcCgpKSB7XG4gIGNvbnN0IGFzc29jaWF0ZWQgPSBhc3NvY2lhdGVkQ29tbWVudHMoY29tbWVudHMsIG5vZGUsIHNvdXJjZSlcbiAgY29uc3QgbWV0YWRhdGEgPSBhc3NvY2lhdGVkLm1hcCgoY29tbWVudCkgPT4gY29tbWVudFRva2Vucyhjb21tZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgdHlwZU1ldGFkYXRhID0gbWV0YWRhdGEuZmlsdGVyKChbdG9rZW5dKSA9PiB0b2tlbj8udGV4dCA9PSBcIkB0eXBlXCIpXG4gIGNvbnN0IGltbXV0YWJsZU1ldGFkYXRhID0gbWV0YWRhdGEuZmlsdGVyKChbdG9rZW5dKSA9PiB0b2tlbj8udGV4dCA9PSBcIkBzZW1hbnRpZm9sZC1pbW11dGFibGVcIilcbiAgY29uc3QgcHJvZmlsZU1ldGFkYXRhID0gbWV0YWRhdGEuZmlsdGVyKChbdG9rZW5dKSA9PiB7XG4gICAgcmV0dXJuIHRva2VuPy50ZXh0LnN0YXJ0c1dpdGgoXCJAdHlwZVwiKSB8fCB0b2tlbj8udGV4dC5zdGFydHNXaXRoKFwiQHNlbWFudGlmb2xkLWltbXV0YWJsZVwiKVxuICB9KVxuXG4gIGlmIChwcm9maWxlTWV0YWRhdGEubGVuZ3RoID09IDApIHJldHVybiB1bmRlZmluZWRcblxuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICh0eXBlTWV0YWRhdGEubGVuZ3RoICE9IDEgfHwgdHlwZU1ldGFkYXRhWzBdLmxlbmd0aCA8IDIgfHxcbiAgICBpbW11dGFibGVNZXRhZGF0YS5sZW5ndGggPiAxIHx8IGltbXV0YWJsZU1ldGFkYXRhLnNvbWUoKHRva2VucykgPT4gdG9rZW5zLmxlbmd0aCAhPSAxKSB8fFxuICAgIHByb2ZpbGVNZXRhZGF0YS5sZW5ndGggIT0gdHlwZU1ldGFkYXRhLmxlbmd0aCArIGltbXV0YWJsZU1ldGFkYXRhLmxlbmd0aCkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJtYWxmb3JtZWQgbG9jYWwgdHlwZSBtZXRhZGF0YVwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGNvbnN0IGRlY2xhcmVkVHlwZSA9IGpvaW5lZENvbW1lbnRUb2tlbih0eXBlTWV0YWRhdGFbMF0sIDEsIHNvdXJjZSlcblxuICByZXR1cm4ge1xuICAgIGltbXV0YWJsZTogaW1tdXRhYmxlTWV0YWRhdGEubGVuZ3RoID09IDEsXG4gICAgdHlwZTogY29udmVydFR5cGUoZGVjbGFyZWRUeXBlLnNvdXJjZVR5cGUsIGBMb2NhbCAnJHtub2RlLm5hbWV9J2AsIGxvY2F0aW9uLCBzb3VyY2UsIGRlY2xhcmVkVHlwZS5sb2NhdGlvbiwgcmVjb3JkTmFtZXMsIHR5cGVQYXJhbWV0ZXJzKVxuICB9XG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIFJ1YnkgbG9jYWwgZGVjbGFyYXRpb24gb3IgYXNzaWdubWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIFByaXNtIG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udmVyc2lvbiBjb250ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Mb2NhbFN0YXRlbWVudH0gU2VtYW50aWMgbG9jYWwgc3RhdGVtZW50LlxuICovXG5mdW5jdGlvbiBjb252ZXJ0TG9jYWxTdGF0ZW1lbnQobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIShub2RlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVdyaXRlTm9kZSkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lLCBsb2NhdGlvbilcblxuICBjb25zdCBtZXRhZGF0YSA9IGxvY2FsTWV0YWRhdGEoY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQucmVjb3JkTmFtZXMsIGNvbnRleHQudHlwZVBhcmFtZXRlcnMpXG5cbiAgaWYgKG1ldGFkYXRhKSB7XG4gICAgbGV0IGRlY2xhcmVkVHlwZSA9IG1ldGFkYXRhLnR5cGVcblxuICAgIGlmIChtZXRhZGF0YS5pbW11dGFibGUgJiYgZGVjbGFyZWRUeXBlLmtpbmQgPT0gXCJNYXBUeXBlXCIgJiYgY29udGV4dC5vcmRlcmVkTWFwRGVjbGFyYXRpb25zPy5oYXMobm9kZSkgJiZcbiAgICAgIG5vZGUudmFsdWUgaW5zdGFuY2VvZiBIYXNoTm9kZSkge1xuICAgICAgZGVjbGFyZWRUeXBlID0gb3JkZXJlZE1hcFR5cGVGcm9tTWFwKGRlY2xhcmVkVHlwZSwgbG9jYXRpb24pXG4gICAgfVxuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBpbml0aWFsaXplcjogY29udmVydEV4cHJlc3Npb24obm9kZS52YWx1ZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCwgZGVjbGFyZWRUeXBlKSxcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkxvY2FsRGVjbGFyYXRpb25cIiksXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG11dGFibGU6ICFtZXRhZGF0YS5pbW11dGFibGUsXG4gICAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgICB0eXBlOiBkZWNsYXJlZFR5cGVcbiAgICB9LCB7bmFtZTogcHJpc21Mb2NhdGlvbihub2RlLm5hbWVMb2MsIGZpbGVuYW1lLCBzb3VyY2UpLCBvcGVyYXRvcjogcHJpc21Mb2NhdGlvbihub2RlLm9wZXJhdG9yTG9jLCBmaWxlbmFtZSwgc291cmNlKX0pXG5cbiAgICBjb250ZXh0LmJpbmRpbmdzLnNldChub2RlLm5hbWUsIGRlY2xhcmVkVHlwZSlcbiAgICByZXR1cm4gc2VtYW50aWNcbiAgfVxuXG4gIGlmICghY29udGV4dC5iaW5kaW5ncy5oYXMobm9kZS5uYW1lKSkge1xuICAgIGlmIChub2RlLnZhbHVlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVJlYWROb2RlICYmIGNvbnRleHQuYmluZGluZ3MuZ2V0KG5vZGUudmFsdWUubmFtZSk/LmtpbmQgPT0gXCJPcmRlcmVkTWFwVHlwZVwiKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwib3JkZXJlZCBtYXAgYWxpYXMgZXNjYXBlXCIsIGxvY2F0aW9uKVxuICAgIH1cbiAgICByZXR1cm4gbWlzc2luZ1R5cGUoXCJydWJ5XCIsIGBMb2NhbCAnJHtub2RlLm5hbWV9J2AsIGxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgdGFyZ2V0TG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUubmFtZUxvYywgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgdGFyZ2V0ID0gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksIGxvY2F0aW9uOiB0YXJnZXRMb2NhdGlvbiwgbmFtZTogbm9kZS5uYW1lfSwge1xuICAgIG5hbWU6IHRhcmdldExvY2F0aW9uXG4gIH0pXG5cbiAgY29uc3QgYmluZGluZ1R5cGUgPSBjb250ZXh0LmJpbmRpbmdzLmdldChub2RlLm5hbWUpXG4gIGNvbnN0IHNlbWFudGljID0gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgZXhwcmVzc2lvbjogY29udmVydEV4cHJlc3Npb24obm9kZS52YWx1ZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCxcbiAgICAgIGJpbmRpbmdUeXBlPy5raW5kID09IFwiRXJyb3JUeXBlXCIgPyB1bmRlZmluZWQgOiBiaW5kaW5nVHlwZSksXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQXNzaWdubWVudFN0YXRlbWVudFwiKSxcbiAgICBsb2NhdGlvbixcbiAgICB0YXJnZXRcbiAgfSwge29wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKG5vZGUub3BlcmF0b3JMb2MsIGZpbGVuYW1lLCBzb3VyY2UpfSlcblxuICByZXR1cm4gc2VtYW50aWNcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhoYXVzdGl2ZSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQcmlzbSBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udmVyc2lvbiBjb250ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IFNlbWFudGljIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFN0YXRlbWVudChub2RlLCBjb21tZW50cywgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBpZiAobm9kZSBpbnN0YW5jZW9mIFJldHVybk5vZGUpIHtcbiAgICBpZiAoKGNvbnRleHQubG9vcERlcHRoID8/IDApID4gMCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm5vbmxvY2FsIHJldHVybiBmcm9tIGVhY2ggYmxvY2tcIiwgbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIHJldHVybiBjb252ZXJ0UmV0dXJuKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBJZk5vZGUgfHwgbm9kZSBpbnN0YW5jZW9mIFVubGVzc05vZGUpIHJldHVybiBjb252ZXJ0SWYobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChub2RlIGluc3RhbmNlb2YgV2hpbGVOb2RlKSByZXR1cm4gY29udmVydFdoaWxlKG5vZGUsIGNvbW1lbnRzLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIEJlZ2luTm9kZSkgcmV0dXJuIGNvbnZlcnRSdWJ5VHJ5KG5vZGUsIGNvbW1lbnRzLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKVxuICBpZiAobm9kZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVXcml0ZU5vZGUpIHJldHVybiBjb252ZXJ0TG9jYWxTdGF0ZW1lbnQobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChub2RlIGluc3RhbmNlb2YgSW5zdGFuY2VWYXJpYWJsZVdyaXRlTm9kZSkge1xuICAgIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3QgZmllbGQgPSBjb250ZXh0LmN1cnJlbnRDbGFzcz8uZmllbGRzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gYEAke2NhbmRpZGF0ZS5uYW1lfWAgPT0gbm9kZS5uYW1lKVxuXG4gICAgaWYgKCFmaWVsZCB8fCAhY29udGV4dC5jdXJyZW50Q2xhc3MpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJwcml2YXRlIGluc3RhbmNlIGZpZWxkIG91dHNpZGUgaXRzIGRlY2xhcmluZyBjbGFzc1wiLCBsb2NhdGlvbilcbiAgICBjb25zdCByZWNlaXZlciA9IHdpdGhQYXJzZXJSYW5nZXMoe2NsYXNzSWQ6IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoY29udGV4dC5jdXJyZW50Q2xhc3MuaWQpLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVjZWl2ZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbn0sIHtyZWNlaXZlcjogbG9jYXRpb259KVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2V4cHJlc3Npb246IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUudmFsdWUsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQsIGZpZWxkLnR5cGUpLFxuICAgICAgZmllbGQ6IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZmllbGQuaWQpLCBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJQcml2YXRlRmllbGRXcml0ZVN0YXRlbWVudFwiKSwgbG9jYXRpb24sIHJlY2VpdmVyfSxcbiAgICB7bWVtYmVyOiBsb2NhdGlvbn0pXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBCcmVha05vZGUgfHwgbm9kZSBpbnN0YW5jZW9mIE5leHROb2RlKSB7XG4gICAgaWYgKG5vZGUuYXJndW1lbnRzXykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBgJHtub2RlIGluc3RhbmNlb2YgQnJlYWtOb2RlID8gXCJicmVha1wiIDogXCJuZXh0XCJ9IHZhbHVlYCwgbm9kZUxvY2F0aW9uKG5vZGUuYXJndW1lbnRzXywgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgY29uc3QgbG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUua2V5d29yZExvYywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7XCJCcmVha1N0YXRlbWVudFwiIHwgXCJDb250aW51ZVN0YXRlbWVudFwifSAqLyAobm9kZSBpbnN0YW5jZW9mIEJyZWFrTm9kZSA/IFwiQnJlYWtTdGF0ZW1lbnRcIiA6IFwiQ29udGludWVTdGF0ZW1lbnRcIiksXG4gICAgICBsb2NhdGlvblxuICAgIH0sIHtrZXl3b3JkOiBsb2NhdGlvbn0pXG4gIH1cbiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkge1xuICAgIGlmICghbm9kZS5yZWNlaXZlciAmJiBub2RlLm5hbWUgPT0gXCJyYWlzZVwiKSByZXR1cm4gY29udmVydFJ1YnlSYWlzZShub2RlLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGlmIChub2RlLmJsb2NrKSByZXR1cm4gY29udmVydEZvckVhY2gobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgaWYgKCFub2RlLnJlY2VpdmVyICYmIG5vZGUubmFtZSA9PSBcInB1dHNcIiAmJiAhY29udGV4dC5mdW5jdGlvbnMuaGFzKFwicHV0c1wiKSkgcmV0dXJuIGNvbnZlcnRQcmludChub2RlLCBmaWxlbmFtZSwgc291cmNlLCBjb250ZXh0KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGV4cHJlc3Npb246IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2FsbEV4cHJlc3Npb259ICovIChjb252ZXJ0RXhwcmVzc2lvbihub2RlLCBmaWxlbmFtZSwgc291cmNlLCBjb250ZXh0KSksXG4gICAgICBraW5kOiBcIkV4cHJlc3Npb25TdGF0ZW1lbnRcIixcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIG5vZGUuY29uc3RydWN0b3IubmFtZSwgbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGV4YWN0IGByYWlzZSBEZWNsYXJlZEVycm9yLCBtZXNzYWdlYC5cbiAqIEBwYXJhbSB7Q2FsbE5vZGV9IG5vZGUgLSBQcmlzbSByYWlzZSBjYWxsLlxuICogQHBhcmFtIHtSdWJ5Q29udmVyc2lvbkNvbnRleHR9IGNvbnRleHQgLSBUeXBlZCBsZXhpY2FsIGNvbnRleHQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJhaXNlU3RhdGVtZW50fSBTZW1hbnRpYyByYWlzZS5cbiAqL1xuZnVuY3Rpb24gY29udmVydFJ1YnlSYWlzZShub2RlLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFyZ3VtZW50c18gPSBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18gPz8gW11cbiAgY29uc3QgZXJyb3JOb2RlID0gYXJndW1lbnRzX1swXVxuXG4gIGlmIChub2RlLmJsb2NrIHx8IG5vZGUuY2FsbE9wZXJhdG9yTG9jIHx8IGFyZ3VtZW50c18ubGVuZ3RoICE9IDIgfHxcbiAgICAhKGVycm9yTm9kZSBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUpICYmICEoZXJyb3JOb2RlIGluc3RhbmNlb2YgQ29uc3RhbnRQYXRoTm9kZSkgfHxcbiAgICAhY29udGV4dC5lcnJvck5hbWVzLmhhcyhjb25zdGFudFBhdGhOYW1lKGVycm9yTm9kZSkpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJhaXNlIG90aGVyIHRoYW4gZXhhY3QgZGVjbGFyZWQgZXJyb3IgYW5kIG1lc3NhZ2VcIiwgbG9jYXRpb24pXG4gIH1cbiAgY29uc3QgZGVjbGFyYXRpb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb259ICovIChjb250ZXh0LmVycm9yTmFtZXMuZ2V0KGNvbnN0YW50UGF0aE5hbWUoZXJyb3JOb2RlKSkpXG4gIGNvbnN0IHR5cGVMb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihlcnJvck5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgIGVycm9yOiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGVycm9yOiB3aXRoUGFyc2VyUmFuZ2VzKHtkZWNsYXJhdGlvbklkOiAvKiogQHR5cGUge3N0cmluZ30gKi8gKGRlY2xhcmF0aW9uLmlkKSwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRXJyb3JUeXBlXCIpfSwge3R5cGU6IHR5cGVMb2NhdGlvbn0pLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiRXJyb3JDb25zdHJ1Y3Rpb25cIiksXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG1lc3NhZ2U6IGNvbnZlcnRFeHByZXNzaW9uKGFyZ3VtZW50c19bMV0sIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpXG4gICAgfSwge3R5cGU6IHR5cGVMb2NhdGlvbn0pLFxuICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlJhaXNlU3RhdGVtZW50XCIpLFxuICAgIGxvY2F0aW9uXG4gIH0sIHtrZXl3b3JkOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYyA/PyBub2RlLmxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIGV4YWN0IHR5cGVkIHJlc2N1ZSB3aXRoIG5vIGVsc2UvZW5zdXJlLlxuICogQHBhcmFtIHtCZWdpbk5vZGV9IG5vZGUgLSBQcmlzbSBiZWdpbiBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFBhcnNlci1vd25lZCBjb21tZW50cy5cbiAqIEBwYXJhbSB7UnVieUNvbnZlcnNpb25Db250ZXh0fSBjb250ZXh0IC0gVHlwZWQgbGV4aWNhbCBjb250ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UcnlTdGF0ZW1lbnR9IFNlbWFudGljIGV4YWN0IGhhbmRsZXIuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRSdWJ5VHJ5KG5vZGUsIGNvbW1lbnRzLCBjb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGhhbmRsZXIgPSBub2RlLnJlc2N1ZUNsYXVzZVxuXG4gIGlmICghKGhhbmRsZXIgaW5zdGFuY2VvZiBSZXNjdWVOb2RlKSB8fCBoYW5kbGVyLnN1YnNlcXVlbnQgfHwgbm9kZS5lbHNlQ2xhdXNlIHx8IG5vZGUuZW5zdXJlQ2xhdXNlIHx8XG4gICAgaGFuZGxlci5leGNlcHRpb25zLmxlbmd0aCAhPSAxIHx8XG4gICAgIShoYW5kbGVyLmV4Y2VwdGlvbnNbMF0gaW5zdGFuY2VvZiBDb25zdGFudFJlYWROb2RlKSAmJiAhKGhhbmRsZXIuZXhjZXB0aW9uc1swXSBpbnN0YW5jZW9mIENvbnN0YW50UGF0aE5vZGUpIHx8XG4gICAgIWNvbnRleHQuZXJyb3JOYW1lcy5oYXMoY29uc3RhbnRQYXRoTmFtZShoYW5kbGVyLmV4Y2VwdGlvbnNbMF0pKSB8fCAhKGhhbmRsZXIucmVmZXJlbmNlIGluc3RhbmNlb2YgTG9jYWxWYXJpYWJsZVRhcmdldE5vZGUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImJlZ2luIHdpdGhvdXQgb25lIGV4YWN0IHR5cGVkIHJlc2N1ZSBhbmQgYmluZGluZ1wiLCBsb2NhdGlvbilcbiAgfVxuICBjb25zdCBlcnJvck5vZGUgPSBoYW5kbGVyLmV4Y2VwdGlvbnNbMF1cbiAgY29uc3QgZGVjbGFyYXRpb24gPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb259ICovIChjb250ZXh0LmVycm9yTmFtZXMuZ2V0KGNvbnN0YW50UGF0aE5hbWUoZXJyb3JOb2RlKSkpXG4gIGNvbnN0IGNhdWdodExvY2F0aW9uID0gbm9kZUxvY2F0aW9uKGVycm9yTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgY2F0Y2hUeXBlID0gd2l0aFBhcnNlclJhbmdlcyh7ZGVjbGFyYXRpb25JZDogLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkZWNsYXJhdGlvbi5pZCksIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkVycm9yVHlwZVwiKX0sIHtcbiAgICB0eXBlOiBjYXVnaHRMb2NhdGlvblxuICB9KVxuICBjb25zdCBib2R5Q29udGV4dCA9IHsuLi5jb250ZXh0LCBiaW5kaW5nczogbmV3IE1hcChjb250ZXh0LmJpbmRpbmdzKX1cbiAgY29uc3QgY2F0Y2hDb250ZXh0ID0gey4uLmNvbnRleHQsIGJpbmRpbmdzOiBuZXcgTWFwKGNvbnRleHQuYmluZGluZ3MpfVxuXG4gIGNhdGNoQ29udGV4dC5iaW5kaW5ncy5zZXQoaGFuZGxlci5yZWZlcmVuY2UubmFtZSwgY2F0Y2hUeXBlKVxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keTogY29udmVydEJsb2NrKG5vZGUuc3RhdGVtZW50cywgY29tbWVudHMsIGJvZHlDb250ZXh0LCBmaWxlbmFtZSwgc291cmNlLCBsb2NhdGlvbiksXG4gICAgY2F0Y2hCaW5kaW5nOiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkNhdGNoQmluZGluZ1wiKSxcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24oaGFuZGxlci5yZWZlcmVuY2UsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgbXV0YWJsZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKGZhbHNlKSxcbiAgICAgIG5hbWU6IGhhbmRsZXIucmVmZXJlbmNlLm5hbWUsXG4gICAgICB0eXBlOiBjYXRjaFR5cGVcbiAgICB9LCB7bmFtZTogbm9kZUxvY2F0aW9uKGhhbmRsZXIucmVmZXJlbmNlLCBmaWxlbmFtZSwgc291cmNlKX0pLFxuICAgIGNhdGNoQm9keTogY29udmVydEJsb2NrKGhhbmRsZXIuc3RhdGVtZW50cywgY29tbWVudHMsIGNhdGNoQ29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSwgbm9kZUxvY2F0aW9uKGhhbmRsZXIsIGZpbGVuYW1lLCBzb3VyY2UpKSxcbiAgICBjYXRjaFR5cGUsXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiVHJ5U3RhdGVtZW50XCIpLFxuICAgIGxvY2F0aW9uXG4gIH0sIHtjYXRjaDogbm9kZUxvY2F0aW9uKGhhbmRsZXIsIGZpbGVuYW1lLCBzb3VyY2UpLCB0cnk6IGxvY2F0aW9ufSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBleGFjdCByZXNvbHZlZC1saXN0IGAuZWFjaCBkbyB8dmFsdWV8IC4uLiBlbmRgIHN5bnRheC5cbiAqIEBwYXJhbSB7Q2FsbE5vZGV9IG5vZGUgLSBQcmlzbSBjYWxsIHdpdGggYSBibG9jay5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc20vc3JjL2Rlc2VyaWFsaXplLmpzXCIpLkNvbW1lbnRbXX0gY29tbWVudHMgLSBQcmlzbSBjb21tZW50cy5cbiAqIEBwYXJhbSB7UnVieUNvbnZlcnNpb25Db250ZXh0fSBjb250ZXh0IC0gVHlwZWQgbGV4aWNhbCBjb250ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Gb3JFYWNoU3RhdGVtZW50IHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRm9yRWFjaE1hcFN0YXRlbWVudH0gU2VtYW50aWMgbG9vcC5cbiAqL1xuZnVuY3Rpb24gY29udmVydEZvckVhY2gobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYmxvY2sgPSBub2RlLmJsb2NrXG5cbiAgaWYgKCEoYmxvY2sgaW5zdGFuY2VvZiBCbG9ja05vZGUpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiY2FsbCBibG9ja1wiLCBibG9jayA/IG5vZGVMb2NhdGlvbihibG9jaywgZmlsZW5hbWUsIHNvdXJjZSkgOiBsb2NhdGlvbilcbiAgaWYgKCFub2RlLnJlY2VpdmVyIHx8IG5vZGUubmFtZSAhPSBcImVhY2hcIiB8fCBub2RlLmFyZ3VtZW50c18gfHwgIW5vZGUuY2FsbE9wZXJhdG9yTG9jIHx8ICFub2RlLm1lc3NhZ2VMb2MpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiYXJiaXRyYXJ5IGNhbGwgYmxvY2tcIiwgbm9kZUxvY2F0aW9uKGJsb2NrLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBpZiAoc2xpY2VQcmlzbVNvdXJjZShzb3VyY2UsIGJsb2NrLm9wZW5pbmdMb2Muc3RhcnRPZmZzZXQsIGJsb2NrLm9wZW5pbmdMb2Muc3RhcnRPZmZzZXQgKyBibG9jay5vcGVuaW5nTG9jLmxlbmd0aCkgIT0gXCJkb1wiKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm5vbi1kbyBlYWNoIGJsb2NrXCIsIHByaXNtTG9jYXRpb24oYmxvY2sub3BlbmluZ0xvYywgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgZXhjbHVkZWQgPSBmaW5kUnVieURlc2NlbmRhbnQoYmxvY2suYm9keSwgKGNhbmRpZGF0ZSkgPT5cbiAgICBjYW5kaWRhdGUgaW5zdGFuY2VvZiBSZWRvTm9kZSB8fCBjYW5kaWRhdGUgaW5zdGFuY2VvZiBSZXRyeU5vZGUgfHwgY2FuZGlkYXRlIGluc3RhbmNlb2YgUmV0dXJuTm9kZSlcblxuICBpZiAoZXhjbHVkZWQpIHtcbiAgICBjb25zdCBkZXRhaWwgPSBleGNsdWRlZCBpbnN0YW5jZW9mIFJldHVybk5vZGUgPyBcIm5vbmxvY2FsIHJldHVybiBmcm9tIGVhY2ggYmxvY2tcIiA6XG4gICAgICBleGNsdWRlZCBpbnN0YW5jZW9mIFJlZG9Ob2RlID8gXCJyZWRvIGluIGVhY2ggYmxvY2tcIiA6IFwicmV0cnkgaW4gZWFjaCBibG9ja1wiXG5cbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIGRldGFpbCwgbm9kZUxvY2F0aW9uKGV4Y2x1ZGVkLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBpZiAoIShibG9jay5wYXJhbWV0ZXJzIGluc3RhbmNlb2YgQmxvY2tQYXJhbWV0ZXJzTm9kZSkgfHwgYmxvY2sucGFyYW1ldGVycy5sb2NhbHMubGVuZ3RoID4gMCB8fFxuICAgICFibG9jay5wYXJhbWV0ZXJzLnBhcmFtZXRlcnMpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiZWFjaCBibG9jayBwYXJhbWV0ZXJzXCIsIGJsb2NrLnBhcmFtZXRlcnNcbiAgICAgID8gbm9kZUxvY2F0aW9uKGJsb2NrLnBhcmFtZXRlcnMsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgICA6IG5vZGVMb2NhdGlvbihibG9jaywgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgcGFyYW1ldGVycyA9IGJsb2NrLnBhcmFtZXRlcnMucGFyYW1ldGVyc1xuICBjb25zdCBzdXBwb3J0ZWRSZXF1aXJlZHMgPSBwYXJhbWV0ZXJzLnJlcXVpcmVkcy5sZW5ndGggPT0gMSB8fCBwYXJhbWV0ZXJzLnJlcXVpcmVkcy5sZW5ndGggPT0gMlxuICBjb25zdCB1bnN1cHBvcnRlZFBhcmFtZXRlciA9ICFzdXBwb3J0ZWRSZXF1aXJlZHNcbiAgICA/IHBhcmFtZXRlcnMucmVxdWlyZWRzWzJdID8/IHBhcmFtZXRlcnMucmVxdWlyZWRzWzFdID8/IHBhcmFtZXRlcnMucmVxdWlyZWRzWzBdID8/IGJsb2NrLnBhcmFtZXRlcnNcbiAgICA6IHBhcmFtZXRlcnMucmVxdWlyZWRzLmV2ZXJ5KChwYXJhbWV0ZXIpID0+IHBhcmFtZXRlciBpbnN0YW5jZW9mIFJlcXVpcmVkUGFyYW1ldGVyTm9kZSkgJiZcbiAgICAgICAgcGFyYW1ldGVycy5vcHRpb25hbHMubGVuZ3RoID09IDAgJiYgIXBhcmFtZXRlcnMucmVzdCAmJlxuICAgICAgICBwYXJhbWV0ZXJzLnBvc3RzLmxlbmd0aCA9PSAwICYmIHBhcmFtZXRlcnMua2V5d29yZHMubGVuZ3RoID09IDAgJiYgIXBhcmFtZXRlcnMua2V5d29yZFJlc3QgJiYgIXBhcmFtZXRlcnMuYmxvY2tcbiAgICAgID8gdW5kZWZpbmVkXG4gICAgICA6IHBhcmFtZXRlcnMub3B0aW9uYWxzWzBdID8/IHBhcmFtZXRlcnMucmVzdCA/PyBwYXJhbWV0ZXJzLnBvc3RzWzBdID8/IHBhcmFtZXRlcnMua2V5d29yZHNbMF0gPz9cbiAgICAgICAgcGFyYW1ldGVycy5rZXl3b3JkUmVzdCA/PyBwYXJhbWV0ZXJzLmJsb2NrID8/IHBhcmFtZXRlcnMucmVxdWlyZWRzWzBdXG5cbiAgaWYgKHVuc3VwcG9ydGVkUGFyYW1ldGVyKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwiZWFjaCBibG9jayBwYXJhbWV0ZXIgYXJpdHkgb3Igc2hhcGVcIiwgbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkUGFyYW1ldGVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgY29sbGVjdGlvblR5cGUgPSBpdGVyYXRpb25PcGVyYW5kVHlwZShrbm93bkV4cHJlc3Npb25UeXBlKG5vZGUucmVjZWl2ZXIsIGNvbnRleHQpKVxuXG4gIGlmIChwYXJhbWV0ZXJzLnJlcXVpcmVkcy5sZW5ndGggPT0gMikge1xuICAgIGlmIChjb2xsZWN0aW9uVHlwZT8ua2luZCA9PSBcIk1hcFR5cGVcIikge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInVub3JkZXJlZCBtYXAgaXRlcmF0aW9uXCIsIG5vZGVMb2NhdGlvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9XG4gICAgaWYgKCFjb2xsZWN0aW9uVHlwZSB8fCBjb2xsZWN0aW9uVHlwZS5raW5kICE9IFwiT3JkZXJlZE1hcFR5cGVcIikge1xuICAgICAgcmV0dXJuIG1pc3NpbmdUeXBlKFwicnVieVwiLCBcIk9yZGVyZWQgbWFwIGl0ZXJhdGlvbiBjb2xsZWN0aW9uXCIsIG5vZGVMb2NhdGlvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9XG4gICAgY29uc3QgW2tleVBhcmFtZXRlciwgdmFsdWVQYXJhbWV0ZXJdID0gLyoqIEB0eXBlIHtbUmVxdWlyZWRQYXJhbWV0ZXJOb2RlLCBSZXF1aXJlZFBhcmFtZXRlck5vZGVdfSAqLyAocGFyYW1ldGVycy5yZXF1aXJlZHMpXG4gICAgY29uc3Qga2V5TG9jYXRpb24gPSBub2RlTG9jYXRpb24oa2V5UGFyYW1ldGVyLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHZhbHVlTG9jYXRpb24gPSBub2RlTG9jYXRpb24odmFsdWVQYXJhbWV0ZXIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3Qga2V5VHlwZSA9IGl0ZXJhdGlvbkJpbmRpbmdUeXBlKGNvbGxlY3Rpb25UeXBlLmtleVR5cGUsIGtleUxvY2F0aW9uKVxuICAgIGNvbnN0IHZhbHVlVHlwZSA9IGl0ZXJhdGlvbkJpbmRpbmdUeXBlKGNvbGxlY3Rpb25UeXBlLnZhbHVlVHlwZSwgdmFsdWVMb2NhdGlvbilcbiAgICBjb25zdCBrZXlCaW5kaW5nID0gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJWYWx1ZUJpbmRpbmdcIiksIGxvY2F0aW9uOiBrZXlMb2NhdGlvbiwgbXV0YWJsZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKGZhbHNlKSxcbiAgICAgIG5hbWU6IGtleVBhcmFtZXRlci5uYW1lLCB0eXBlOiBrZXlUeXBlXG4gICAgfSwge25hbWU6IGtleUxvY2F0aW9ufSlcbiAgICBjb25zdCB2YWx1ZUJpbmRpbmcgPSB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlZhbHVlQmluZGluZ1wiKSwgbG9jYXRpb246IHZhbHVlTG9jYXRpb24sIG11dGFibGU6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChmYWxzZSksXG4gICAgICBuYW1lOiB2YWx1ZVBhcmFtZXRlci5uYW1lLCB0eXBlOiB2YWx1ZVR5cGVcbiAgICB9LCB7bmFtZTogdmFsdWVMb2NhdGlvbn0pXG4gICAgY29uc3QgYm9keUNvbnRleHQgPSB7Li4uY29udGV4dCwgYmluZGluZ3M6IG5ldyBNYXAoY29udGV4dC5iaW5kaW5ncyksIGxvb3BEZXB0aDogKGNvbnRleHQubG9vcERlcHRoID8/IDApICsgMX1cblxuICAgIGJvZHlDb250ZXh0LmJpbmRpbmdzLnNldChrZXlQYXJhbWV0ZXIubmFtZSwga2V5VHlwZSlcbiAgICBib2R5Q29udGV4dC5iaW5kaW5ncy5zZXQodmFsdWVQYXJhbWV0ZXIubmFtZSwgdmFsdWVUeXBlKVxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGJvZHk6IGNvbnZlcnRCbG9jayhibG9jay5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgPyBibG9jay5ib2R5IDogbnVsbCwgY29tbWVudHMsIGJvZHlDb250ZXh0LCBmaWxlbmFtZSxcbiAgICAgICAgc291cmNlLCBub2RlTG9jYXRpb24oYmxvY2ssIGZpbGVuYW1lLCBzb3VyY2UpKSxcbiAgICAgIGtleUJpbmRpbmcsXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJGb3JFYWNoTWFwU3RhdGVtZW50XCIpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICBtYXA6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpLFxuICAgICAgdmFsdWVCaW5kaW5nXG4gICAgfSwge29wZXJhdG9yOiBwcmlzbUxvY2F0aW9uKG5vZGUubWVzc2FnZUxvYywgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG4gIGNvbnN0IHBhcmFtZXRlciA9IC8qKiBAdHlwZSB7UmVxdWlyZWRQYXJhbWV0ZXJOb2RlfSAqLyAocGFyYW1ldGVycy5yZXF1aXJlZHNbMF0pXG5cbiAgaWYgKGNvbGxlY3Rpb25UeXBlPy5raW5kID09IFwiTWFwVHlwZVwiIHx8IGNvbGxlY3Rpb25UeXBlPy5raW5kID09IFwiT3JkZXJlZE1hcFR5cGVcIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJtYXAgaXRlcmF0aW9uIHdpdGhvdXQga2V5L3ZhbHVlIHBhaXIgYmluZGluZ1wiLCBub2RlTG9jYXRpb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgaWYgKCFjb2xsZWN0aW9uVHlwZSB8fCBjb2xsZWN0aW9uVHlwZS5raW5kICE9IFwiTGlzdFR5cGVcIikge1xuICAgIHJldHVybiBtaXNzaW5nVHlwZShcInJ1YnlcIiwgXCJJdGVyYXRpb24gY29sbGVjdGlvblwiLCBub2RlTG9jYXRpb24obm9kZS5yZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgYmluZGluZ0xvY2F0aW9uID0gbm9kZUxvY2F0aW9uKHBhcmFtZXRlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgaW5mZXJyZWRUeXBlID0gY29sbGVjdGlvblR5cGUuZWxlbWVudFR5cGVcbiAgY29uc3QgYmluZGluZ1R5cGUgPSBpdGVyYXRpb25CaW5kaW5nVHlwZShpbmZlcnJlZFR5cGUsIGJpbmRpbmdMb2NhdGlvbilcbiAgY29uc3QgdmFsdWVCaW5kaW5nID0gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiVmFsdWVCaW5kaW5nXCIpLFxuICAgIGxvY2F0aW9uOiBiaW5kaW5nTG9jYXRpb24sXG4gICAgbXV0YWJsZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKGZhbHNlKSxcbiAgICBuYW1lOiBwYXJhbWV0ZXIubmFtZSxcbiAgICB0eXBlOiBiaW5kaW5nVHlwZVxuICB9LCB7bmFtZTogYmluZGluZ0xvY2F0aW9ufSlcbiAgY29uc3QgYm9keUNvbnRleHQgPSB7Li4uY29udGV4dCwgYmluZGluZ3M6IG5ldyBNYXAoY29udGV4dC5iaW5kaW5ncyksIGxvb3BEZXB0aDogKGNvbnRleHQubG9vcERlcHRoID8/IDApICsgMX1cblxuICBib2R5Q29udGV4dC5iaW5kaW5ncy5zZXQocGFyYW1ldGVyLm5hbWUsIGJpbmRpbmdUeXBlKVxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keTogY29udmVydEJsb2NrKFxuICAgICAgYmxvY2suYm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlID8gYmxvY2suYm9keSA6IG51bGwsXG4gICAgICBjb21tZW50cyxcbiAgICAgIGJvZHlDb250ZXh0LFxuICAgICAgZmlsZW5hbWUsXG4gICAgICBzb3VyY2UsXG4gICAgICBub2RlTG9jYXRpb24oYmxvY2ssIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgKSxcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJGb3JFYWNoU3RhdGVtZW50XCIpLFxuICAgIGxpc3Q6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmVjZWl2ZXIsIGZpbGVuYW1lLCBzb3VyY2UsIGNvbnRleHQpLFxuICAgIGxvY2F0aW9uLFxuICAgIHZhbHVlQmluZGluZ1xuICB9LCB7b3BlcmF0b3I6IHByaXNtTG9jYXRpb24obm9kZS5tZXNzYWdlTG9jLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogRmluZHMgdGhlIGZpcnN0IHBhcnNlciBkZXNjZW5kYW50IG1hdGNoaW5nIG9uZSBleGNsdWRlZCBibG9jayBjb25zdHJ1Y3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGUgfCBudWxsfSBub2RlIC0gUGFyc2VyIHN1YnRyZWUuXG4gKiBAcGFyYW0geyhub2RlOiBpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlKSA9PiBib29sZWFufSBwcmVkaWNhdGUgLSBFeGNsdXNpb24gcHJlZGljYXRlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGUgfCB1bmRlZmluZWR9IEZpcnN0IHNvdXJjZS1vcmRlcmVkIG1hdGNoLlxuICovXG5mdW5jdGlvbiBmaW5kUnVieURlc2NlbmRhbnQobm9kZSwgcHJlZGljYXRlKSB7XG4gIGlmICghbm9kZSkgcmV0dXJuIHVuZGVmaW5lZFxuICBpZiAocHJlZGljYXRlKG5vZGUpKSByZXR1cm4gbm9kZVxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUuY29tcGFjdENoaWxkTm9kZXMoKSkge1xuICAgIGNvbnN0IG1hdGNoID0gZmluZFJ1YnlEZXNjZW5kYW50KGNoaWxkLCBwcmVkaWNhdGUpXG5cbiAgICBpZiAobWF0Y2gpIHJldHVybiBtYXRjaFxuICB9XG4gIHJldHVybiB1bmRlZmluZWRcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgb3JkZXJlZCBQcmlzbSBzdGF0ZW1lbnQgbGlzdC5cbiAqIEBwYXJhbSB7U3RhdGVtZW50c05vZGUgfCBudWxsfSBub2RlIC0gUHJpc20gc3RhdGVtZW50cywgb3IgYW4gZW1wdHkgc291cmNlIGJsb2NrLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtSdWJ5Q29udmVyc2lvbkNvbnRleHR9IGNvbnRleHQgLSBUeXBlZCBsZXhpY2FsIGNvbnZlcnNpb24gY29udGV4dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBmYWxsYmFja0xvY2F0aW9uIC0gRW1wdHkgYmxvY2sgbG9jYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQmxvY2t9IFNlbWFudGljIGJsb2NrLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0QmxvY2sobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UsIGZhbGxiYWNrTG9jYXRpb24pIHtcbiAgcmV0dXJuIHtcbiAgICBraW5kOiBcIkJsb2NrXCIsXG4gICAgbG9jYXRpb246IG5vZGUgPyBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkgOiBmYWxsYmFja0xvY2F0aW9uLFxuICAgIHN0YXRlbWVudHM6IG5vZGUgPyBub2RlLmJvZHkubWFwKChzdGF0ZW1lbnQpID0+IGNvbnZlcnRTdGF0ZW1lbnQoc3RhdGVtZW50LCBjb21tZW50cywgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkpIDogW11cbiAgfVxufVxuXG4vKipcbiAqIENoZWNrcyB0aGF0IGEgY29tbWVudCBhbmQgaXRzIG93bmVyIGFyZSBzZXBhcmF0ZWQgYnkgYXQgbW9zdCBvbmUgbmV3bGluZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBnYXAgLSBTb3VyY2UgYmV0d2VlbiB0aGUgY29tbWVudCBhbmQgZm9sbG93aW5nIGl0ZW0uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgZ2FwIGlzIGltbWVkaWF0ZSB3aGl0ZXNwYWNlLlxuICovXG5mdW5jdGlvbiBpc0ltbWVkaWF0ZUNvbW1lbnRHYXAoZ2FwKSB7XG4gIGxldCBuZXdsaW5lcyA9IDBcblxuICBmb3IgKGNvbnN0IGNoYXJhY3RlciBvZiBnYXApIHtcbiAgICBpZiAoY2hhcmFjdGVyID09IFwiXFxuXCIpIHtcbiAgICAgIG5ld2xpbmVzKytcbiAgICB9IGVsc2UgaWYgKGNoYXJhY3RlciAhPSBcIiBcIiAmJiBjaGFyYWN0ZXIgIT0gXCJcXHRcIiAmJiBjaGFyYWN0ZXIgIT0gXCJcXHJcIikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld2xpbmVzIDw9IDFcbn1cblxuLyoqXG4gKiBSZXF1aXJlcyBhbiBleGFjdCBzdXBwb3J0ZWQgUnVieSB2YWx1ZS10eXBlIHNwZWxsaW5nLlxuICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IHNvdXJjZVR5cGUgLSBSdWJ5IHR5cGUgY29tbWVudCB2YWx1ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJqZWN0IC0gVHlwZWQgc3ViamVjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gU291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHBhcnNlciBpbnB1dC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IFt0eXBlTG9jYXRpb25dIC0gRXhhY3QgdHlwZSBjb21tZW50IHRva2VuIGxvY2F0aW9uLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZWNvcmREZWNsYXJhdGlvbiB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FZmZlY3RSZXNvdXJjZURlY2xhcmF0aW9uPn0gW3JlY29yZE5hbWVzXSAtIE5vbWluYWwgZGVjbGFyYXRpb25zIGJ5IHNvdXJjZSBuYW1lLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5UeXBlUGFyYW1ldGVyPn0gW3R5cGVQYXJhbWV0ZXJzXSAtIERlY2xhcmF0aW9uLXNjb3BlZCBwYXJhbWV0ZXJzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljVmFsdWVUeXBlfSBTZW1hbnRpYyB0eXBlLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0VHlwZShzb3VyY2VUeXBlLCBzdWJqZWN0LCBsb2NhdGlvbiwgc291cmNlLCB0eXBlTG9jYXRpb24gPSBsb2NhdGlvbiwgcmVjb3JkTmFtZXMgPSBuZXcgTWFwKCksIHR5cGVQYXJhbWV0ZXJzID0gbmV3IE1hcCgpKSB7XG4gIHJldHVybiBkb2N1bWVudGVkVmFsdWVUeXBlKHtsYW5ndWFnZTogXCJydWJ5XCIsIGxvY2F0aW9uOiB0eXBlTG9jYXRpb24sIG93bmVyTG9jYXRpb246IGxvY2F0aW9uLCByZWNvcmRzOiByZWNvcmROYW1lcywgc291cmNlLCBzb3VyY2VUeXBlLCBzdWJqZWN0LCB0eXBlUGFyYW1ldGVyc30pXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBSdWJ5IGRlZmluaXRpb24gc2lnbmF0dXJlIGJlZm9yZSBib2R5IGV4cHJlc3Npb25zLlxuICogQHBhcmFtIHtEZWZOb2RlfSBub2RlIC0gUHJpc20gZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc20vc3JjL2Rlc2VyaWFsaXplLmpzXCIpLkNvbW1lbnRbXX0gY29tbWVudHMgLSBQcmlzbSBjb21tZW50cy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbiB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVmZmVjdFJlc291cmNlRGVjbGFyYXRpb24+fSByZWNvcmROYW1lcyAtIE5vbWluYWwgZGVjbGFyYXRpb25zIGJ5IHNvdXJjZSBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IG93bmVySWQgLSBTdGFibGUgZnVuY3Rpb24gaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFthbGxvd0J1aWx0aW5PdXRwdXRdIC0gV2hldGhlciBjb21waWxlciBhdXRob3JpdHkgYWRtaXRzIHRoZSBleGFjdCBvdXRwdXQgZmFjYWRlIGZ1bmN0aW9uLlxuICogQHJldHVybnMge1J1YnlGdW5jdGlvblNpZ25hdHVyZX0gU2VtYW50aWMgc2lnbmF0dXJlLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0RnVuY3Rpb25TaWduYXR1cmUobm9kZSwgY29tbWVudHMsIGZpbGVuYW1lLCBzb3VyY2UsIHJlY29yZE5hbWVzLCBvd25lcklkLCBhbGxvd0J1aWx0aW5PdXRwdXQgPSBmYWxzZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBwYXJhbWV0ZXJMaXN0ID0gbm9kZS5wYXJhbWV0ZXJzXG5cbiAgaWYgKG5vZGUucmVjZWl2ZXIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJzaW5nbGV0b24gbWV0aG9kXCIsIG5vZGVMb2NhdGlvbihub2RlLnJlY2VpdmVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgbmFtZUxvY2F0aW9uID0gcHJpc21Mb2NhdGlvbihub2RlLm5hbWVMb2MsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5vZGUubmFtZSA9PSBcInB1dHNcIiAmJiAhYWxsb3dCdWlsdGluT3V0cHV0KSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImZ1bmN0aW9uICdwdXRzJyBjYXB0dXJlcyBidWlsdC1pbiBwcmludGluZ1wiLCBuYW1lTG9jYXRpb24pXG4gIH1cbiAgY29uc3QgdW5zdXBwb3J0ZWRQYXJhbWV0ZXIgPSBwYXJhbWV0ZXJMaXN0ICYmIFtcbiAgICBwYXJhbWV0ZXJMaXN0Lm9wdGlvbmFsc1swXSwgcGFyYW1ldGVyTGlzdC5yZXN0LCBwYXJhbWV0ZXJMaXN0LnBvc3RzWzBdLCBwYXJhbWV0ZXJMaXN0LmtleXdvcmRzWzBdLFxuICAgIHBhcmFtZXRlckxpc3Qua2V5d29yZFJlc3QsIHBhcmFtZXRlckxpc3QuYmxvY2ssXG4gICAgcGFyYW1ldGVyTGlzdC5yZXF1aXJlZHMuZmluZCgocGFyYW1ldGVyKSA9PiAhKHBhcmFtZXRlciBpbnN0YW5jZW9mIFJlcXVpcmVkUGFyYW1ldGVyTm9kZSkpXG4gIF0uZmluZChCb29sZWFuKVxuXG4gIGlmICh1bnN1cHBvcnRlZFBhcmFtZXRlcikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJwYXJhbWV0ZXJzXCIsIG5vZGVMb2NhdGlvbih1bnN1cHBvcnRlZFBhcmFtZXRlciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cblxuICBjb25zdCBkZWNsYXJlZFR5cGVzID0gdHlwZUNvbW1lbnRzKGNvbW1lbnRzLCBub2RlLCBmaWxlbmFtZSwgc291cmNlLCBvd25lcklkKVxuICBjb25zdCB0eXBlUGFyYW1ldGVyTmFtZXMgPSBuZXcgTWFwKChkZWNsYXJlZFR5cGVzLnR5cGVQYXJhbWV0ZXJzID8/IFtdKS5tYXAoKHBhcmFtZXRlcikgPT4gW3BhcmFtZXRlci5uYW1lLCBwYXJhbWV0ZXJdKSlcbiAgY29uc3QgcmVxdWlyZWRQYXJhbWV0ZXJzID0gcGFyYW1ldGVyTGlzdD8ucmVxdWlyZWRzID8/IFtdXG4gIGNvbnN0IGV4dHJhQW5ub3RhdGlvbiA9IFsuLi5kZWNsYXJlZFR5cGVzLnBhcmFtZXRlcnMua2V5cygpXS5maW5kKChuYW1lKSA9PlxuICAgICFyZXF1aXJlZFBhcmFtZXRlcnMuc29tZSgocGFyYW1ldGVyKSA9PiBwYXJhbWV0ZXIgaW5zdGFuY2VvZiBSZXF1aXJlZFBhcmFtZXRlck5vZGUgJiYgcGFyYW1ldGVyLm5hbWUgPT0gbmFtZSkpXG5cbiAgaWYgKGV4dHJhQW5ub3RhdGlvbikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBgYW5ub3RhdGlvbiBmb3IgdW5rbm93biBwYXJhbWV0ZXIgJyR7ZXh0cmFBbm5vdGF0aW9ufSdgLCBsb2NhdGlvbilcbiAgY29uc3QgcGFyYW1ldGVycyA9IHJlcXVpcmVkUGFyYW1ldGVycy5tYXAoKHBhcmFtZXRlcikgPT4ge1xuICAgIGlmICghKHBhcmFtZXRlciBpbnN0YW5jZW9mIFJlcXVpcmVkUGFyYW1ldGVyTm9kZSkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgcGFyYW1ldGVyLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuXG4gICAgY29uc3QgcGFyYW1ldGVyTG9jYXRpb24gPSBub2RlTG9jYXRpb24ocGFyYW1ldGVyLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgY29uc3QgZGVjbGFyZWRUeXBlID0gZGVjbGFyZWRUeXBlcy5wYXJhbWV0ZXJzLmdldChwYXJhbWV0ZXIubmFtZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlBhcmFtZXRlclwiKSxcbiAgICAgIGxvY2F0aW9uOiBwYXJhbWV0ZXJMb2NhdGlvbixcbiAgICAgIG5hbWU6IHBhcmFtZXRlci5uYW1lLFxuICAgICAgdHlwZTogY29udmVydFR5cGUoZGVjbGFyZWRUeXBlPy5zb3VyY2VUeXBlLCBgUGFyYW1ldGVyICcke3BhcmFtZXRlci5uYW1lfSdgLCBwYXJhbWV0ZXJMb2NhdGlvbiwgc291cmNlLFxuICAgICAgICBkZWNsYXJlZFR5cGU/LmxvY2F0aW9uLCByZWNvcmROYW1lcywgdHlwZVBhcmFtZXRlck5hbWVzKVxuICAgIH0sIHtuYW1lOiBwYXJhbWV0ZXJMb2NhdGlvbn0pXG4gIH0pXG4gIHJldHVybiB7XG4gICAgbG9jYXRpb24sXG4gICAgbmFtZTogbm9kZS5uYW1lLFxuICAgIG5hbWVMb2NhdGlvbixcbiAgICBwYXJhbWV0ZXJzLFxuICAgIHJldHVyblR5cGU6IGRlY2xhcmVkVHlwZXMucmV0dXJuVHlwZT8uc291cmNlVHlwZSA9PSBcIlt2b2lkXVwiXG4gICAgICA/IHJlcXVpcmVTb3VyY2VSZXR1cm5UeXBlKFwicnVieVwiLCBcIlt2b2lkXVwiLCBgRnVuY3Rpb24gJyR7bm9kZS5uYW1lfScgcmV0dXJuYCwgbG9jYXRpb24sIGRlY2xhcmVkVHlwZXMucmV0dXJuVHlwZS5sb2NhdGlvbilcbiAgICAgIDogY29udmVydFR5cGUoZGVjbGFyZWRUeXBlcy5yZXR1cm5UeXBlPy5zb3VyY2VUeXBlLCBgRnVuY3Rpb24gJyR7bm9kZS5uYW1lfScgcmV0dXJuYCwgbG9jYXRpb24sIHNvdXJjZSxcbiAgICAgICAgZGVjbGFyZWRUeXBlcy5yZXR1cm5UeXBlPy5sb2NhdGlvbiwgcmVjb3JkTmFtZXMsIHR5cGVQYXJhbWV0ZXJOYW1lcyksXG4gICAgLi4uKGRlY2xhcmVkVHlwZXMudHlwZVBhcmFtZXRlcnMgPyB7dHlwZVBhcmFtZXRlcnM6IGRlY2xhcmVkVHlwZXMudHlwZVBhcmFtZXRlcnN9IDoge30pXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIFJ1YnkgZGVmaW5pdGlvbiBib2R5IHVzaW5nIGFsbCBhbHJlYWR5LXByb3ZlZCBzaWduYXR1cmVzLlxuICogQHBhcmFtIHtEZWZOb2RlfSBub2RlIC0gUHJpc20gZGVmaW5pdGlvbi5cbiAqIEBwYXJhbSB7UnVieUZ1bmN0aW9uU2lnbmF0dXJlfSBzaWduYXR1cmUgLSBDb252ZXJ0ZWQgc2lnbmF0dXJlLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBSdWJ5RnVuY3Rpb25TaWduYXR1cmU+fSBmdW5jdGlvbnMgLSBNb2R1bGUgc2lnbmF0dXJlcy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUmVjb3JkRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5DbGFzc0RlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRWZmZWN0UmVzb3VyY2VEZWNsYXJhdGlvbj59IHJlY29yZE5hbWVzIC0gTm9taW5hbCBkZWNsYXJhdGlvbnMgYnkgc291cmNlIG5hbWUuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9uPn0gcmVjb3JkcyAtIFJlY29yZCBkZWNsYXJhdGlvbnMgYnkgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24+fSBjbGFzc2VzIC0gUmVmZXJlbmNlIGNsYXNzZXMgYnkgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb24+fSBlcnJvck5hbWVzIC0gRXJyb3IgZGVjbGFyYXRpb25zIGJ5IHNvdXJjZSBuYW1lLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FcnJvckRlY2xhcmF0aW9uPn0gZXJyb3JzIC0gRXJyb3IgZGVjbGFyYXRpb25zIGJ5IGlkZW50aXR5LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9ufSBTZW1hbnRpYyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEZ1bmN0aW9uKG5vZGUsIHNpZ25hdHVyZSwgZnVuY3Rpb25zLCByZWNvcmROYW1lcywgcmVjb3JkcywgY2xhc3NlcywgZXJyb3JOYW1lcywgZXJyb3JzLCBjb21tZW50cywgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBjb250ZXh0ID0ge1xuICAgIGJpbmRpbmdzOiBuZXcgTWFwKHNpZ25hdHVyZS5wYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyKSA9PiBbcGFyYW1ldGVyLm5hbWUsIHBhcmFtZXRlci50eXBlXSkpLFxuICAgIGNsYXNzZXMsXG4gICAgZXJyb3JOYW1lcyxcbiAgICBlcnJvcnMsXG4gICAgZnVuY3Rpb25zLFxuICAgIG9yZGVyZWRNYXBEZWNsYXJhdGlvbnM6IG9yZGVyZWRNYXBEZWNsYXJhdGlvbnNGb3JSdWJ5KG5vZGUuYm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlID8gbm9kZS5ib2R5LmJvZHkgOiBbXSksXG4gICAgcmVjb3JkTmFtZXMsXG4gICAgcmVjb3JkcyxcbiAgICByZXR1cm5UeXBlOiBzaWduYXR1cmUucmV0dXJuVHlwZSxcbiAgICB0eXBlUGFyYW1ldGVyczogbmV3IE1hcCgoc2lnbmF0dXJlLnR5cGVQYXJhbWV0ZXJzID8/IFtdKS5tYXAoKHBhcmFtZXRlcikgPT4gW3BhcmFtZXRlci5uYW1lLCBwYXJhbWV0ZXJdKSlcbiAgfVxuICBjb25zdCBib2R5ID0gY29udmVydEJsb2NrKFxuICAgIG5vZGUuYm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlID8gbm9kZS5ib2R5IDogbnVsbCxcbiAgICBjb21tZW50cyxcbiAgICBjb250ZXh0LFxuICAgIGZpbGVuYW1lLFxuICAgIHNvdXJjZSxcbiAgICBzaWduYXR1cmUubG9jYXRpb25cbiAgKVxuXG4gIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICBib2R5LFxuICAgIGtpbmQ6IFwiRnVuY3Rpb25EZWNsYXJhdGlvblwiLFxuICAgIGxvY2F0aW9uOiBzaWduYXR1cmUubG9jYXRpb24sXG4gICAgbmFtZTogc2lnbmF0dXJlLm5hbWUsXG4gICAgcGFyYW1ldGVyczogc2lnbmF0dXJlLnBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogc2lnbmF0dXJlLnJldHVyblR5cGUsXG4gICAgLi4uKHNpZ25hdHVyZS50eXBlUGFyYW1ldGVycyA/IHt0eXBlUGFyYW1ldGVyczogc2lnbmF0dXJlLnR5cGVQYXJhbWV0ZXJzfSA6IHt9KVxuICB9LCB7bmFtZTogc2lnbmF0dXJlLm5hbWVMb2NhdGlvbn0pXG59XG5cbi8qKlxuICogUmVzb2x2ZXMgcGFyc2VyLW93bmVkIHBhaXIgYmxvY2tzIHRvIGV4YWN0IGRlY2xhcmF0aW9ucyBpbnNpZGUgb25lIGxleGljYWwgb3duZXIuXG4gKiBBbWJpZ3VvdXMgc2FtZS1uYW1lIGRlY2xhcmF0aW9ucyBwcm9kdWNlIG5vIGV2aWRlbmNlIGFuZCBmYWlsIGR1cmluZyBsb29wIGNvbnZlcnNpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGVbXX0gbm9kZXMgLSBGdW5jdGlvbiBib2R5IG9yIGVudHJ5LXBvaW50IHJvb3RzLlxuICogQHJldHVybnMge1NldDxvYmplY3Q+fSBFeGFjdCBwYWlyLWl0ZXJhdGVkIHBhcnNlciBkZWNsYXJhdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIG9yZGVyZWRNYXBEZWNsYXJhdGlvbnNGb3JSdWJ5KG5vZGVzKSB7XG4gIC8qKiBAdHlwZSB7e2RlY2xhcmF0aW9uOiBMb2NhbFZhcmlhYmxlV3JpdGVOb2RlLCBuYW1lOiBzdHJpbmcsIG9mZnNldDogbnVtYmVyfVtdfSAqL1xuICBjb25zdCBkZWNsYXJhdGlvbnMgPSBbXVxuICAvKiogQHR5cGUge3tuYW1lOiBzdHJpbmcsIG9mZnNldDogbnVtYmVyfVtdfSAqL1xuICBjb25zdCByZWNlaXZlcnMgPSBbXVxuICAvKipcbiAgICogVmlzaXRzIG9uZSBwYXJzZXIgY2FuZGlkYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBQYXJzZXIgY2FuZGlkYXRlLlxuICAgKi9cbiAgY29uc3QgdmlzaXQgPSAobm9kZSkgPT4ge1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgRGVmTm9kZSB8fCBub2RlIGluc3RhbmNlb2YgQ2xhc3NOb2RlKSByZXR1cm5cbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVXcml0ZU5vZGUpIGRlY2xhcmF0aW9ucy5wdXNoKHtcbiAgICAgIGRlY2xhcmF0aW9uOiBub2RlLFxuICAgICAgbmFtZTogbm9kZS5uYW1lLFxuICAgICAgb2Zmc2V0OiBub2RlLmxvY2F0aW9uLnN0YXJ0T2Zmc2V0XG4gICAgfSlcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmIG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlUmVhZE5vZGUgJiYgbm9kZS5uYW1lID09IFwiZWFjaFwiICYmXG4gICAgICBub2RlLmJsb2NrIGluc3RhbmNlb2YgQmxvY2tOb2RlICYmIG5vZGUuYmxvY2sucGFyYW1ldGVycyBpbnN0YW5jZW9mIEJsb2NrUGFyYW1ldGVyc05vZGUgJiZcbiAgICAgIG5vZGUuYmxvY2sucGFyYW1ldGVycy5wYXJhbWV0ZXJzPy5yZXF1aXJlZHMubGVuZ3RoID09IDIpIHJlY2VpdmVycy5wdXNoKHtcbiAgICAgIG5hbWU6IG5vZGUucmVjZWl2ZXIubmFtZSxcbiAgICAgIG9mZnNldDogbm9kZS5sb2NhdGlvbi5zdGFydE9mZnNldFxuICAgIH0pXG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNvbXBhY3RDaGlsZE5vZGVzKCkpIHZpc2l0KGNoaWxkKVxuICB9XG5cbiAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB2aXNpdChub2RlKVxuICBjb25zdCBzZWxlY3RlZCA9IG5ldyBTZXQoKVxuICBmb3IgKGNvbnN0IHJlY2VpdmVyIG9mIHJlY2VpdmVycykge1xuICAgIGNvbnN0IG1hdGNoZXMgPSBkZWNsYXJhdGlvbnMuZmlsdGVyKCh7bmFtZSwgb2Zmc2V0fSkgPT4gbmFtZSA9PSByZWNlaXZlci5uYW1lICYmIG9mZnNldCA8IHJlY2VpdmVyLm9mZnNldClcblxuICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PSAxKSBzZWxlY3RlZC5hZGQobWF0Y2hlc1swXS5kZWNsYXJhdGlvbilcbiAgfVxuXG4gIHJldHVybiBzZWxlY3RlZFxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleGFjdCBlbXB0eSBTdGFuZGFyZEVycm9yIHN1YmNsYXNzLlxuICogQHBhcmFtIHtDbGFzc05vZGV9IG5vZGUgLSBQcmlzbSBjbGFzcyBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXJyb3JEZWNsYXJhdGlvbn0gZGVjbGFyYXRpb24gLSBQcmVkZWNsYXJlZCBzZW1hbnRpYyBlcnJvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXJyb3JEZWNsYXJhdGlvbn0gU2VtYW50aWMgZXJyb3IgZGVjbGFyYXRpb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRSdWJ5RXJyb3Iobm9kZSwgZGVjbGFyYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoIShub2RlLmNvbnN0YW50UGF0aCBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUpIHx8ICEobm9kZS5zdXBlcmNsYXNzIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSkgfHxcbiAgICBub2RlLnN1cGVyY2xhc3MubmFtZSAhPSBcIlN0YW5kYXJkRXJyb3JcIiB8fCAhbm9kZS5pbmhlcml0YW5jZU9wZXJhdG9yTG9jIHx8IG5vZGUuYm9keSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJub25jYW5vbmljYWwgdHlwZWQgZXJyb3IgZGVjbGFyYXRpb25cIiwgbG9jYXRpb24pXG4gIH1cblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyhkZWNsYXJhdGlvbiwge1xuICAgIG5hbWU6IG5vZGVMb2NhdGlvbihub2RlLmNvbnN0YW50UGF0aCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgdHlwZTogbm9kZUxvY2F0aW9uKG5vZGUuc3VwZXJjbGFzcywgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgYm91bmRlZCBSdWJ5IHJlZmVyZW5jZS1jbGFzcyBwcm9maWxlLlxuICogQHBhcmFtIHtDbGFzc05vZGV9IG5vZGUgLSBQcmlzbSBjbGFzcyBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbn0gZGVjbGFyYXRpb24gLSBQcmVkZWNsYXJlZCBjbGFzcyBpZGVudGl0eS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUmVjb3JkRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5DbGFzc0RlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRWZmZWN0UmVzb3VyY2VEZWNsYXJhdGlvbj59IG5vbWluYWxOYW1lcyAtIFZpc2libGUgbm9taW5hbCBkZWNsYXJhdGlvbnMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9uPn0gcmVjb3JkcyAtIFJlY29yZHMgYnkgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24+fSBjbGFzc2VzIC0gQ2xhc3NlcyBieSBpZGVudGl0eS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgUnVieUZ1bmN0aW9uU2lnbmF0dXJlPn0gZnVuY3Rpb25zIC0gVG9wLWxldmVsIHNpZ25hdHVyZXMuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb24+fSBlcnJvck5hbWVzIC0gRXJyb3JzIGJ5IG5hbWUuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVycm9yRGVjbGFyYXRpb24+fSBlcnJvcnMgLSBFcnJvcnMgYnkgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb259IFNlbWFudGljIGNsYXNzLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UnVieVJlZmVyZW5jZUNsYXNzKG5vZGUsIGRlY2xhcmF0aW9uLCBub21pbmFsTmFtZXMsIHJlY29yZHMsIGNsYXNzZXMsIGZ1bmN0aW9ucywgZXJyb3JOYW1lcywgZXJyb3JzLFxuICBjb21tZW50cywgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUuY29uc3RhbnRQYXRoIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSkgfHwgbm9kZS5zdXBlcmNsYXNzIHx8IG5vZGUuaW5oZXJpdGFuY2VPcGVyYXRvckxvYyB8fFxuICAgICEobm9kZS5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJlZmVyZW5jZSBjbGFzcyBpbmhlcml0YW5jZSwgcXVhbGlmaWVkIG5hbWUsIG9yIGVtcHR5IGJvZHlcIiwgbG9jYXRpb24pXG4gIH1cbiAgY29uc3QgbWVtYmVycyA9IG5vZGUuYm9keS5ib2R5XG4gIGNvbnN0IGluaXRpYWxpemVycyA9IG1lbWJlcnMuZmlsdGVyKChtZW1iZXIpID0+IG1lbWJlciBpbnN0YW5jZW9mIERlZk5vZGUgJiYgbWVtYmVyLm5hbWUgPT0gXCJpbml0aWFsaXplXCIpXG4gIGNvbnN0IG1ldGhvZE5vZGVzID0gLyoqIEB0eXBlIHtEZWZOb2RlW119ICovIChtZW1iZXJzLmZpbHRlcigobWVtYmVyKSA9PiBtZW1iZXIgaW5zdGFuY2VvZiBEZWZOb2RlICYmIG1lbWJlci5uYW1lICE9IFwiaW5pdGlhbGl6ZVwiKSlcbiAgY29uc3QgcmVzZXJ2ZWRNZXRob2QgPSBtZXRob2ROb2Rlcy5maW5kKChtZXRob2QpID0+IHJlZmVyZW5jZU1ldGhvZEhvb2tzLmhhcyhtZXRob2QubmFtZSkpXG5cbiAgaWYgKGluaXRpYWxpemVycy5sZW5ndGggIT0gMSB8fCBtZW1iZXJzLnNvbWUoKG1lbWJlcikgPT4gIShtZW1iZXIgaW5zdGFuY2VvZiBEZWZOb2RlKSkgfHwgcmVzZXJ2ZWRNZXRob2QpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicmVmZXJlbmNlIGNsYXNzIHJlcXVpcmVzIG9uZSBpbml0aWFsaXplciBhbmQgb3JkaW5hcnkgbWV0aG9kc1wiLCBsb2NhdGlvbilcbiAgfVxuICBjb25zdCBpbml0aWFsaXplciA9IC8qKiBAdHlwZSB7RGVmTm9kZX0gKi8gKGluaXRpYWxpemVyc1swXSlcbiAgY29uc3QgcGFyYW1ldGVycyA9IGluaXRpYWxpemVyLnBhcmFtZXRlcnM/LnJlcXVpcmVkcyA/PyBbXVxuICBjb25zdCBpbnZhbGlkUGFyYW1ldGVyID0gaW5pdGlhbGl6ZXIucGFyYW1ldGVycyAmJiBbaW5pdGlhbGl6ZXIucGFyYW1ldGVycy5vcHRpb25hbHNbMF0sIGluaXRpYWxpemVyLnBhcmFtZXRlcnMucmVzdCxcbiAgICBpbml0aWFsaXplci5wYXJhbWV0ZXJzLnBvc3RzWzBdLCBpbml0aWFsaXplci5wYXJhbWV0ZXJzLmtleXdvcmRzWzBdLCBpbml0aWFsaXplci5wYXJhbWV0ZXJzLmtleXdvcmRSZXN0LFxuICAgIGluaXRpYWxpemVyLnBhcmFtZXRlcnMuYmxvY2tdLmZpbmQoQm9vbGVhbilcbiAgY29uc3Qgc3RhdGVtZW50cyA9IGluaXRpYWxpemVyLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSA/IGluaXRpYWxpemVyLmJvZHkuYm9keSA6IFtdXG4gIGNvbnN0IGFubm90YXRpb25zID0gdHlwZUNvbW1lbnRzKGNvbW1lbnRzLCBpbml0aWFsaXplciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYWNxdWlzaXRpb24gPSBzdGF0ZW1lbnRzLmxlbmd0aCA9PSAxICYmIHN0YXRlbWVudHNbMF0gaW5zdGFuY2VvZiBJbnN0YW5jZVZhcmlhYmxlV3JpdGVOb2RlICYmXG4gICAgc3RhdGVtZW50c1swXS5uYW1lID09IFwiQHJlc291cmNlXCIgJiYgc3RhdGVtZW50c1swXS52YWx1ZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFzdGF0ZW1lbnRzWzBdLnZhbHVlLnJlY2VpdmVyICYmXG4gICAgIXN0YXRlbWVudHNbMF0udmFsdWUuYmxvY2sgJiYgc3RhdGVtZW50c1swXS52YWx1ZS5uYW1lID09IFwidjFfY29ubmVjdFwiICYmXG4gICAgc3RhdGVtZW50c1swXS52YWx1ZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAyICYmIHBhcmFtZXRlcnMubGVuZ3RoID09IDIgJiZcbiAgICBwYXJhbWV0ZXJzWzBdIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlICYmIHBhcmFtZXRlcnNbMF0ubmFtZSA9PSBcImhvc3RcIiAmJlxuICAgIHBhcmFtZXRlcnNbMV0gaW5zdGFuY2VvZiBSZXF1aXJlZFBhcmFtZXRlck5vZGUgJiYgcGFyYW1ldGVyc1sxXS5uYW1lID09IFwicG9ydFwiICYmXG4gICAgc3RhdGVtZW50c1swXS52YWx1ZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0gaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlUmVhZE5vZGUgJiZcbiAgICBzdGF0ZW1lbnRzWzBdLnZhbHVlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXS5uYW1lID09IFwiaG9zdFwiICYmXG4gICAgc3RhdGVtZW50c1swXS52YWx1ZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMV0gaW5zdGFuY2VvZiBMb2NhbFZhcmlhYmxlUmVhZE5vZGUgJiZcbiAgICBzdGF0ZW1lbnRzWzBdLnZhbHVlLmFyZ3VtZW50c18uYXJndW1lbnRzX1sxXS5uYW1lID09IFwicG9ydFwiICYmIGRlY2xhcmF0aW9uLm5hbWUgPT0gXCJUQ1BTb2NrZXRcIiAmJlxuICAgIGZ1bmN0aW9ucy5nZXQoXCJ2MV9jb25uZWN0XCIpPy5yZXR1cm5UeXBlLmtpbmQgPT0gXCJPd25lZFJlc291cmNlVHlwZVwiXG5cbiAgaWYgKGluaXRpYWxpemVyLnJlY2VpdmVyIHx8IGludmFsaWRQYXJhbWV0ZXIgfHwgYW5ub3RhdGlvbnMucmV0dXJuVHlwZSB8fCBhbm5vdGF0aW9ucy5wYXJhbWV0ZXJzLnNpemUgIT0gcGFyYW1ldGVycy5sZW5ndGggfHxcbiAgICAhYWNxdWlzaXRpb24gJiYgc3RhdGVtZW50cy5sZW5ndGggIT0gcGFyYW1ldGVycy5sZW5ndGgpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibm9uY2Fub25pY2FsIHJlZmVyZW5jZSBjbGFzcyBpbml0aWFsaXplclwiLCBub2RlTG9jYXRpb24oaW5pdGlhbGl6ZXIsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGRlY2xhcmF0aW9uLmZpZWxkcyA9IGFjcXVpc2l0aW9uID8gW3dpdGhQYXJzZXJSYW5nZXMoe1xuICAgIGlkOiBgJHtkZWNsYXJhdGlvbi5pZH06ZmllbGQ6MGAsXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUHJpdmF0ZUZpZWxkXCIpLFxuICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24oLyoqIEB0eXBlIHtJbnN0YW5jZVZhcmlhYmxlV3JpdGVOb2RlfSAqLyAoc3RhdGVtZW50c1swXSksIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIG5hbWU6IFwicmVzb3VyY2VcIixcbiAgICB0eXBlOiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLk93bmVkUmVzb3VyY2VUeXBlfSAqLyAoc3RydWN0dXJlZENsb25lKGZ1bmN0aW9ucy5nZXQoXCJ2MV9jb25uZWN0XCIpPy5yZXR1cm5UeXBlKSlcbiAgfSwge25hbWU6IG5vZGVMb2NhdGlvbigvKiogQHR5cGUge0luc3RhbmNlVmFyaWFibGVXcml0ZU5vZGV9ICovIChzdGF0ZW1lbnRzWzBdKSwgZmlsZW5hbWUsIHNvdXJjZSl9KV0gOiBwYXJhbWV0ZXJzLm1hcCgoY2FuZGlkYXRlLCBpbmRleCkgPT4ge1xuICAgIGNvbnN0IHBhcmFtZXRlciA9IC8qKiBAdHlwZSB7UmVxdWlyZWRQYXJhbWV0ZXJOb2RlfSAqLyAoY2FuZGlkYXRlKVxuICAgIGNvbnN0IGFzc2lnbm1lbnQgPSBzdGF0ZW1lbnRzW2luZGV4XVxuICAgIGNvbnN0IGFubm90YXRlZCA9IGFubm90YXRpb25zLnBhcmFtZXRlcnMuZ2V0KHBhcmFtZXRlci5uYW1lKVxuXG4gICAgaWYgKCEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSB8fCAhKGFzc2lnbm1lbnQgaW5zdGFuY2VvZiBJbnN0YW5jZVZhcmlhYmxlV3JpdGVOb2RlKSB8fFxuICAgICAgYXNzaWdubWVudC5uYW1lICE9IGBAJHtwYXJhbWV0ZXIubmFtZX1gIHx8ICEoYXNzaWdubWVudC52YWx1ZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVSZWFkTm9kZSkgfHxcbiAgICAgIGFzc2lnbm1lbnQudmFsdWUubmFtZSAhPSBwYXJhbWV0ZXIubmFtZSB8fCAhYW5ub3RhdGVkKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicHJpdmF0ZSBmaWVsZCBub3QgaW5pdGlhbGl6ZWQgZXhhY3RseSBvbmNlIGluIHBhcmFtZXRlciBvcmRlclwiLFxuICAgICAgICBub2RlTG9jYXRpb24oYXNzaWdubWVudCA/PyBpbml0aWFsaXplciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgfVxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtpZDogYCR7ZGVjbGFyYXRpb24uaWR9OmZpZWxkOiR7aW5kZXh9YCwga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUHJpdmF0ZUZpZWxkXCIpLFxuICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihhc3NpZ25tZW50LCBmaWxlbmFtZSwgc291cmNlKSwgbmFtZTogcGFyYW1ldGVyLm5hbWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZShhbm5vdGF0ZWQuc291cmNlVHlwZSwgYFByaXZhdGUgZmllbGQgJyR7cGFyYW1ldGVyLm5hbWV9J2AsIG5vZGVMb2NhdGlvbihwYXJhbWV0ZXIsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICBzb3VyY2UsIGFubm90YXRlZC5sb2NhdGlvbiwgbm9taW5hbE5hbWVzKX0sIHtuYW1lOiBub2RlTG9jYXRpb24oYXNzaWdubWVudCwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9KVxuICBjb25zdCBjb25zdHJ1Y3RvclBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJzLm1hcCgoY2FuZGlkYXRlLCBpbmRleCkgPT4ge1xuICAgIGNvbnN0IHBhcmFtZXRlciA9IC8qKiBAdHlwZSB7UmVxdWlyZWRQYXJhbWV0ZXJOb2RlfSAqLyAoY2FuZGlkYXRlKVxuICAgIGNvbnN0IHBhcmFtZXRlckxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKHBhcmFtZXRlciwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhbm5vdGF0ZWQgPSBhbm5vdGF0aW9ucy5wYXJhbWV0ZXJzLmdldChwYXJhbWV0ZXIubmFtZSlcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJQYXJhbWV0ZXJcIiksIGxvY2F0aW9uOiBwYXJhbWV0ZXJMb2NhdGlvbiwgbmFtZTogcGFyYW1ldGVyLm5hbWUsXG4gICAgICB0eXBlOiBhY3F1aXNpdGlvblxuICAgICAgICA/IGNvbnZlcnRUeXBlKGFubm90YXRlZD8uc291cmNlVHlwZSwgYENvbnN0cnVjdG9yIHBhcmFtZXRlciAnJHtwYXJhbWV0ZXIubmFtZX0nYCwgcGFyYW1ldGVyTG9jYXRpb24sIHNvdXJjZSxcbiAgICAgICAgICBhbm5vdGF0ZWQ/LmxvY2F0aW9uLCBub21pbmFsTmFtZXMpXG4gICAgICAgIDogZGVjbGFyYXRpb24uZmllbGRzW2luZGV4XS50eXBlfSwge25hbWU6IHBhcmFtZXRlckxvY2F0aW9ufSlcbiAgfSlcbiAgZGVjbGFyYXRpb24uY29uc3RydWN0b3IgPSB3aXRoUGFyc2VyUmFuZ2VzKHtib2R5OiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSAqLyAoe30pLFxuICAgIGlkOiBgJHtkZWNsYXJhdGlvbi5pZH06Y29uc3RydWN0b3JgLCBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJDb25zdHJ1Y3RvckRlY2xhcmF0aW9uXCIpLCBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKGluaXRpYWxpemVyLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBwYXJhbWV0ZXJzOiBjb25zdHJ1Y3RvclBhcmFtZXRlcnN9LCB7Y29uc3RydWN0b3I6IHByaXNtTG9jYXRpb24oaW5pdGlhbGl6ZXIubmFtZUxvYywgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICBjb25zdCBtZXRob2RTaWduYXR1cmVzID0gbWV0aG9kTm9kZXMubWFwKChtZXRob2QsIGluZGV4KSA9PlxuICAgIGNvbnZlcnRGdW5jdGlvblNpZ25hdHVyZShtZXRob2QsIGNvbW1lbnRzLCBmaWxlbmFtZSwgc291cmNlLCBub21pbmFsTmFtZXMsIGAke2RlY2xhcmF0aW9uLmlkfTptZXRob2Q6JHtpbmRleH1gKSlcbiAgZGVjbGFyYXRpb24ubWV0aG9kcyA9IG1ldGhvZFNpZ25hdHVyZXMubWFwKChzaWduYXR1cmUsIGluZGV4KSA9PiB3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICBib2R5OiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSAqLyAoe30pLCBpZDogYCR7ZGVjbGFyYXRpb24uaWR9Om1ldGhvZDoke2luZGV4fWAsXG4gICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiTWV0aG9kRGVjbGFyYXRpb25cIiksIGxvY2F0aW9uOiBzaWduYXR1cmUubG9jYXRpb24sIG5hbWU6IHNpZ25hdHVyZS5uYW1lLFxuICAgIHBhcmFtZXRlcnM6IHNpZ25hdHVyZS5wYXJhbWV0ZXJzLCByZXR1cm5UeXBlOiBzaWduYXR1cmUucmV0dXJuVHlwZVxuICB9LCB7bmFtZTogc2lnbmF0dXJlLm5hbWVMb2NhdGlvbn0pKVxuICBjb25zdCBiYXNlID0ge2JpbmRpbmdzOiBuZXcgTWFwKCksIGNsYXNzZXMsIGN1cnJlbnRDbGFzczogZGVjbGFyYXRpb24sIGVycm9yTmFtZXMsIGVycm9ycywgZnVuY3Rpb25zLFxuICAgIHJlY29yZE5hbWVzOiBub21pbmFsTmFtZXMsIHJlY29yZHN9XG5cbiAgZGVjbGFyYXRpb24uY29uc3RydWN0b3IuYm9keSA9IGNvbnZlcnRCbG9jayhpbml0aWFsaXplci5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgPyBpbml0aWFsaXplci5ib2R5IDogbnVsbCxcbiAgICBjb21tZW50cywgey4uLmJhc2UsIGJpbmRpbmdzOiBuZXcgTWFwKGNvbnN0cnVjdG9yUGFyYW1ldGVycy5tYXAoKHBhcmFtZXRlcikgPT4gW3BhcmFtZXRlci5uYW1lLCBwYXJhbWV0ZXIudHlwZV0pKSxcbiAgICAgIHJldHVyblR5cGU6IHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJUeXBlUmVmZXJlbmNlXCIpLCBuYW1lOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJ2b2lkXCIpfX0sXG4gICAgZmlsZW5hbWUsIHNvdXJjZSwgZGVjbGFyYXRpb24uY29uc3RydWN0b3IubG9jYXRpb24pXG4gIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBtZXRob2ROb2Rlcy5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCBtZXRob2QgPSBkZWNsYXJhdGlvbi5tZXRob2RzW2luZGV4XVxuICAgIGNvbnN0IG1ldGhvZEJvZHkgPSBtZXRob2ROb2Rlc1tpbmRleF0uYm9keVxuXG4gICAgbWV0aG9kLmJvZHkgPSBjb252ZXJ0QmxvY2sobWV0aG9kQm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlID8gbWV0aG9kQm9keSA6IG51bGwsXG4gICAgICBjb21tZW50cywgey4uLmJhc2UsIGJpbmRpbmdzOiBuZXcgTWFwKG1ldGhvZC5wYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyKSA9PiBbcGFyYW1ldGVyLm5hbWUsIHBhcmFtZXRlci50eXBlXSkpLFxuICAgICAgICByZXR1cm5UeXBlOiBtZXRob2QucmV0dXJuVHlwZX0sIGZpbGVuYW1lLCBzb3VyY2UsIG1ldGhvZC5sb2NhdGlvbilcbiAgfVxuXG4gIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKGRlY2xhcmF0aW9uLCB7bmFtZTogbm9kZUxvY2F0aW9uKG5vZGUuY29uc3RhbnRQYXRoLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIGV4YWN0IHR5cGVkLXJlYWRlci9pbml0aWFsaXplci9mcmVlemUgUnVieSByZWNvcmQgcHJvZmlsZS5cbiAqIEBwYXJhbSB7Q2xhc3NOb2RlfSBub2RlIC0gUHJpc20gY2xhc3MgZGVjbGFyYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9ufSBkZWNsYXJhdGlvbiAtIFByZWRlY2xhcmVkIG5vbWluYWwgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9uIHwgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbiB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVmZmVjdFJlc291cmNlRGVjbGFyYXRpb24+fSByZWNvcmROYW1lcyAtIE5vbWluYWwgZGVjbGFyYXRpb25zIGJ5IG5hbWUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUGFyc2VyLW93bmVkIGNvbW1lbnRzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZWNvcmREZWNsYXJhdGlvbn0gU2VtYW50aWMgcmVjb3JkLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UnVieVJlY29yZChub2RlLCBkZWNsYXJhdGlvbiwgcmVjb3JkTmFtZXMsIGNvbW1lbnRzLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IHR5cGVQYXJhbWV0ZXJOYW1lcyA9IG5ldyBNYXAoKGRlY2xhcmF0aW9uLnR5cGVQYXJhbWV0ZXJzID8/IFtdKS5tYXAoKHBhcmFtZXRlcikgPT4gW3BhcmFtZXRlci5uYW1lLCBwYXJhbWV0ZXJdKSlcblxuICBpZiAoIShub2RlLmNvbnN0YW50UGF0aCBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUpIHx8IG5vZGUuc3VwZXJjbGFzcyB8fCBub2RlLmluaGVyaXRhbmNlT3BlcmF0b3JMb2MpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwicmVjb3JkIGluaGVyaXRhbmNlIG9yIHF1YWxpZmllZCBuYW1lXCIsIGxvY2F0aW9uKVxuICB9XG4gIGNvbnN0IG1lbWJlcnMgPSBub2RlLmJvZHkgaW5zdGFuY2VvZiBTdGF0ZW1lbnRzTm9kZSA/IG5vZGUuYm9keS5ib2R5IDogW11cbiAgY29uc3QgaW5pdGlhbGl6ZXJJbmRleCA9IG1lbWJlcnMuZmluZEluZGV4KChtZW1iZXIpID0+IG1lbWJlciBpbnN0YW5jZW9mIERlZk5vZGUgJiYgbWVtYmVyLm5hbWUgPT0gXCJpbml0aWFsaXplXCIpXG5cbiAgaWYgKGluaXRpYWxpemVySW5kZXggPCAwIHx8IGluaXRpYWxpemVySW5kZXggIT0gbWVtYmVycy5sZW5ndGggLSAxIHx8IG1lbWJlcnMuc2xpY2UoMCwgaW5pdGlhbGl6ZXJJbmRleCkuc29tZSgobWVtYmVyKSA9PlxuICAgICEobWVtYmVyIGluc3RhbmNlb2YgQ2FsbE5vZGUpIHx8IG1lbWJlci5yZWNlaXZlciB8fCBtZW1iZXIubmFtZSAhPSBcImF0dHJfcmVhZGVyXCIgfHwgbWVtYmVyLmJsb2NrIHx8XG4gICAgbWVtYmVyLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoICE9IDEgfHwgIShtZW1iZXIuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdIGluc3RhbmNlb2YgU3ltYm9sTm9kZSkpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJlY29yZCBjbGFzcyBib2R5IG91dHNpZGUgdHlwZWQgcmVhZGVycyBhbmQgb25lIGluaXRpYWxpemVyXCIsIG5vZGVMb2NhdGlvbihtZW1iZXJzLmZpbmQoKG1lbWJlciwgaW5kZXgpID0+XG4gICAgICBpbmRleCA+PSBpbml0aWFsaXplckluZGV4ICsgMSB8fCAhKG1lbWJlciBpbnN0YW5jZW9mIENhbGxOb2RlKSB8fCBtZW1iZXIubmFtZSAhPSBcImF0dHJfcmVhZGVyXCIpID8/IG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IHJlYWRlck5vZGVzID0gLyoqIEB0eXBlIHtDYWxsTm9kZVtdfSAqLyAobWVtYmVycy5zbGljZSgwLCBpbml0aWFsaXplckluZGV4KSlcbiAgZGVjbGFyYXRpb24uZmllbGRzID0gcmVhZGVyTm9kZXMubWFwKChyZWFkZXIpID0+IHtcbiAgICBjb25zdCBzeW1ib2wgPSAvKiogQHR5cGUge1N5bWJvbE5vZGV9ICovIChyZWFkZXIuYXJndW1lbnRzXz8uYXJndW1lbnRzX1swXSlcbiAgICBjb25zdCBtZXRhZGF0YSA9IGFzc29jaWF0ZWRDb21tZW50cyhjb21tZW50cywgcmVhZGVyLCBzb3VyY2UpLm1hcCgoY29tbWVudCkgPT4gY29tbWVudFRva2Vucyhjb21tZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICBjb25zdCB0eXBlTWV0YWRhdGEgPSBtZXRhZGF0YS5maWx0ZXIoKFt0b2tlbl0pID0+IHRva2VuPy50ZXh0ID09IFwiQHR5cGVcIilcbiAgICBjb25zdCBmaWVsZExvY2F0aW9uID0gbm9kZUxvY2F0aW9uKHJlYWRlciwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmICh0eXBlTWV0YWRhdGEubGVuZ3RoICE9IDEgfHwgdHlwZU1ldGFkYXRhWzBdLmxlbmd0aCA8IDIgfHwgbWV0YWRhdGEuc29tZSgoW3Rva2VuXSkgPT4gdG9rZW4/LnRleHQ/LnN0YXJ0c1dpdGgoXCJAdHlwZVwiKSAmJiB0b2tlbi50ZXh0ICE9IFwiQHR5cGVcIikpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJtaXNzaW5nIG9yIG1hbGZvcm1lZCByZWNvcmQgcmVhZGVyIHR5cGVcIiwgZmllbGRMb2NhdGlvbilcbiAgICB9XG4gICAgY29uc3QgZGVjbGFyZWRUeXBlID0gam9pbmVkQ29tbWVudFRva2VuKHR5cGVNZXRhZGF0YVswXSwgMSwgc291cmNlKVxuICAgIGNvbnN0IGZpZWxkID0ge1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiUmVjb3JkRmllbGRcIiksXG4gICAgICBsb2NhdGlvbjogZmllbGRMb2NhdGlvbixcbiAgICAgIG5hbWU6IHN5bWJvbC51bmVzY2FwZWQudmFsdWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZShkZWNsYXJlZFR5cGUuc291cmNlVHlwZSwgYFJlY29yZCBmaWVsZCAnJHtzeW1ib2wudW5lc2NhcGVkLnZhbHVlfSdgLCBmaWVsZExvY2F0aW9uLCBzb3VyY2UsXG4gICAgICAgIGRlY2xhcmVkVHlwZS5sb2NhdGlvbiwgcmVjb3JkTmFtZXMsIHR5cGVQYXJhbWV0ZXJOYW1lcylcbiAgICB9XG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyhmaWVsZCwge25hbWU6IHN5bWJvbC52YWx1ZUxvYyA/IHByaXNtTG9jYXRpb24oc3ltYm9sLnZhbHVlTG9jLCBmaWxlbmFtZSwgc291cmNlKSA6IGZpZWxkTG9jYXRpb259KVxuICB9KVxuICBjb25zdCBpbml0aWFsaXplciA9IC8qKiBAdHlwZSB7RGVmTm9kZX0gKi8gKG1lbWJlcnNbaW5pdGlhbGl6ZXJJbmRleF0pXG4gIGNvbnN0IHBhcmFtZXRlckxpc3QgPSBpbml0aWFsaXplci5wYXJhbWV0ZXJzXG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBwYXJhbWV0ZXJMaXN0Py5yZXF1aXJlZHMgPz8gW11cbiAgY29uc3QgaW52YWxpZFBhcmFtZXRlciA9IHBhcmFtZXRlckxpc3QgJiYgW3BhcmFtZXRlckxpc3Qub3B0aW9uYWxzWzBdLCBwYXJhbWV0ZXJMaXN0LnJlc3QsIHBhcmFtZXRlckxpc3QucG9zdHNbMF0sXG4gICAgcGFyYW1ldGVyTGlzdC5rZXl3b3Jkc1swXSwgcGFyYW1ldGVyTGlzdC5rZXl3b3JkUmVzdCwgcGFyYW1ldGVyTGlzdC5ibG9ja10uZmluZChCb29sZWFuKVxuICBjb25zdCBpbml0aWFsaXplclN0YXRlbWVudHMgPSBpbml0aWFsaXplci5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgPyBpbml0aWFsaXplci5ib2R5LmJvZHkgOiBbXVxuXG4gIGlmIChpbml0aWFsaXplci5yZWNlaXZlciB8fCBpbnZhbGlkUGFyYW1ldGVyIHx8IHBhcmFtZXRlcnMubGVuZ3RoICE9IGRlY2xhcmF0aW9uLmZpZWxkcy5sZW5ndGggfHxcbiAgICBwYXJhbWV0ZXJzLnNvbWUoKHBhcmFtZXRlciwgaW5kZXgpID0+ICEocGFyYW1ldGVyIGluc3RhbmNlb2YgUmVxdWlyZWRQYXJhbWV0ZXJOb2RlKSB8fCBwYXJhbWV0ZXIubmFtZSAhPSBkZWNsYXJhdGlvbi5maWVsZHNbaW5kZXhdLm5hbWUpIHx8XG4gICAgaW5pdGlhbGl6ZXJTdGF0ZW1lbnRzLmxlbmd0aCAhPSBkZWNsYXJhdGlvbi5maWVsZHMubGVuZ3RoICsgMSkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJub25jYW5vbmljYWwgcmVjb3JkIGluaXRpYWxpemVyXCIsIG5vZGVMb2NhdGlvbihpbml0aWFsaXplciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgYW5ub3RhdGlvbnMgPSB0eXBlQ29tbWVudHMoY29tbWVudHMsIGluaXRpYWxpemVyLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChhbm5vdGF0aW9ucy5yZXR1cm5UeXBlIHx8IGFubm90YXRpb25zLnBhcmFtZXRlcnMuc2l6ZSAhPSBkZWNsYXJhdGlvbi5maWVsZHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImluY29tcGxldGUgcmVjb3JkIGluaXRpYWxpemVyIGFubm90YXRpb25zXCIsIG5vZGVMb2NhdGlvbihpbml0aWFsaXplciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGRlY2xhcmF0aW9uLmZpZWxkcy5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBjb25zdCBmaWVsZCA9IGRlY2xhcmF0aW9uLmZpZWxkc1tpbmRleF1cbiAgICBjb25zdCBwYXJhbWV0ZXIgPSAvKiogQHR5cGUge1JlcXVpcmVkUGFyYW1ldGVyTm9kZX0gKi8gKHBhcmFtZXRlcnNbaW5kZXhdKVxuICAgIGNvbnN0IGFzc2lnbm1lbnQgPSBpbml0aWFsaXplclN0YXRlbWVudHNbaW5kZXhdXG4gICAgY29uc3QgYW5ub3RhdGVkID0gYW5ub3RhdGlvbnMucGFyYW1ldGVycy5nZXQocGFyYW1ldGVyLm5hbWUpXG5cbiAgICBpZiAoIShhc3NpZ25tZW50IGluc3RhbmNlb2YgSW5zdGFuY2VWYXJpYWJsZVdyaXRlTm9kZSkgfHwgYXNzaWdubWVudC5uYW1lICE9IGBAJHtmaWVsZC5uYW1lfWAgfHxcbiAgICAgICEoYXNzaWdubWVudC52YWx1ZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVSZWFkTm9kZSkgfHwgYXNzaWdubWVudC52YWx1ZS5uYW1lICE9IGZpZWxkLm5hbWUgfHwgIWFubm90YXRlZCkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJlY29yZCBmaWVsZCBub3QgaW5pdGlhbGl6ZWQgZXhhY3RseSBvbmNlXCIsIG5vZGVMb2NhdGlvbihhc3NpZ25tZW50ID8/IGluaXRpYWxpemVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9XG4gICAgY29uc3QgcGFyYW1ldGVyVHlwZSA9IGNvbnZlcnRUeXBlKGFubm90YXRlZC5zb3VyY2VUeXBlLCBgUmVjb3JkIGluaXRpYWxpemVyIHBhcmFtZXRlciAnJHtwYXJhbWV0ZXIubmFtZX0nYCxcbiAgICAgIG5vZGVMb2NhdGlvbihwYXJhbWV0ZXIsIGZpbGVuYW1lLCBzb3VyY2UpLCBzb3VyY2UsIGFubm90YXRlZC5sb2NhdGlvbiwgcmVjb3JkTmFtZXMsIHR5cGVQYXJhbWV0ZXJOYW1lcylcblxuICAgIGlmICghc2FtZVZhbHVlVHlwZShwYXJhbWV0ZXJUeXBlLCBmaWVsZC50eXBlKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJlY29yZCByZWFkZXIvaW5pdGlhbGl6ZXIgdHlwZSBtaXNtYXRjaFwiLCBhbm5vdGF0ZWQubG9jYXRpb24pXG4gICAgfVxuICB9XG4gIGNvbnN0IGZyZWV6ZSA9IGluaXRpYWxpemVyU3RhdGVtZW50cy5hdCgtMSlcblxuICBpZiAoIWlzUnVieVJlY29yZEZyZWV6ZShmcmVlemUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInJlY29yZCBpbml0aWFsaXplciB3aXRob3V0IGZpbmFsIGZyZWV6ZVwiLCBub2RlTG9jYXRpb24oZnJlZXplID8/IGluaXRpYWxpemVyLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKGRlY2xhcmF0aW9uLCB7bmFtZTogbm9kZUxvY2F0aW9uKG5vZGUuY29uc3RhbnRQYXRoLCBmaWxlbmFtZSwgc291cmNlKX0pXG59XG5cbi8qKlxuICogUmVjb2duaXplcyBjYW5vbmljYWwgc291cmNlIGZyZWV6aW5nIG9yIHRoZSBnZW5lcmF0ZWQgcm9vdC1vd25lZCBLZXJuZWwgaW1wbGVtZW50YXRpb24gYmluZGluZy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZSB8IHVuZGVmaW5lZH0gbm9kZSAtIEZpbmFsIGluaXRpYWxpemVyIHN0YXRlbWVudC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBzdGF0ZW1lbnQgb3ducyB0aGUgbmF0aXZlIHJlY29yZC1mcmVlemUgb3BlcmF0aW9uLlxuICovXG5mdW5jdGlvbiBpc1J1YnlSZWNvcmRGcmVlemUobm9kZSkge1xuICBpZiAoIShub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUpIHx8IG5vZGUuYmxvY2spIHJldHVybiBmYWxzZVxuICBpZiAoIW5vZGUucmVjZWl2ZXIpIHJldHVybiBub2RlLm5hbWUgPT0gXCJmcmVlemVcIiAmJiAhbm9kZS5hcmd1bWVudHNfXG4gIGlmIChub2RlLm5hbWUgIT0gXCJiaW5kX2NhbGxcIiB8fCAhbm9kZS5jYWxsT3BlcmF0b3JMb2MgfHwgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCAhPSAxIHx8XG4gICAgIShub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSBpbnN0YW5jZW9mIFNlbGZOb2RlKSB8fCAhKG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBDYWxsTm9kZSkpIHJldHVybiBmYWxzZVxuICBjb25zdCBtZXRob2QgPSBub2RlLnJlY2VpdmVyXG5cbiAgaWYgKG1ldGhvZC5uYW1lICE9IFwiaW5zdGFuY2VfbWV0aG9kXCIgfHwgIW1ldGhvZC5jYWxsT3BlcmF0b3JMb2MgfHwgbWV0aG9kLmJsb2NrIHx8XG4gICAgbWV0aG9kLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoICE9IDEgfHwgIShtZXRob2QuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdIGluc3RhbmNlb2YgU3ltYm9sTm9kZSkgfHxcbiAgICAhKG1ldGhvZC5yZWNlaXZlciBpbnN0YW5jZW9mIENvbnN0YW50UGF0aE5vZGUpKSByZXR1cm4gZmFsc2VcblxuICByZXR1cm4gbWV0aG9kLnJlY2VpdmVyLnBhcmVudCA9PSBudWxsICYmIG1ldGhvZC5yZWNlaXZlci5kZWxpbWl0ZXJMb2MgIT0gbnVsbCAmJiBtZXRob2QucmVjZWl2ZXIubmFtZSA9PSBcIktlcm5lbFwiICYmXG4gICAgbWV0aG9kLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXS51bmVzY2FwZWQudmFsdWUgPT0gXCJmcmVlemVcIlxufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZSBleGlzdGluZyBSdWJ5IGlmL2Vsc2UgdGVybWluYWwgd2l0aCByZXN0cmljdGVkIGJyYW5jaCBwcmVmaXhlcy5cbiAqIEBwYXJhbSB7SWZOb2RlIHwgVW5sZXNzTm9kZX0gbm9kZSAtIFByaXNtIGNvbmRpdGlvbmFsIG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtL3NyYy9kZXNlcmlhbGl6ZS5qc1wiKS5Db21tZW50W119IGNvbW1lbnRzIC0gUHJpc20gY29tbWVudHMuXG4gKiBAcGFyYW0ge1J1YnlDb252ZXJzaW9uQ29udGV4dH0gY29udGV4dCAtIFR5cGVkIGxleGljYWwgY29udmVyc2lvbiBjb250ZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgY29tbWVudHMsIGNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBjb25zdCBrZXl3b3JkTG9jYXRpb24gPSBub2RlIGluc3RhbmNlb2YgVW5sZXNzTm9kZSA/IG5vZGUua2V5d29yZExvYyA6IG5vZGUuaWZLZXl3b3JkTG9jXG5cbiAgaWYgKCFrZXl3b3JkTG9jYXRpb24gfHwga2V5d29yZExvY2F0aW9uLnN0YXJ0T2Zmc2V0ICE9IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibW9kaWZpZXIgY29uZGl0aW9uYWxcIiwga2V5d29yZExvY2F0aW9uXG4gICAgICA/IHByaXNtTG9jYXRpb24oa2V5d29yZExvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgICAgOiBsb2NhdGlvbilcbiAgfVxuXG4gIGlmIChub2RlLnByZWRpY2F0ZSBpbnN0YW5jZW9mIExvY2FsVmFyaWFibGVSZWFkTm9kZSAmJlxuICAgIGNvbnRleHQuYmluZGluZ3MuZ2V0KG5vZGUucHJlZGljYXRlLm5hbWUpPy5raW5kID09IFwiT3B0aW9uYWxUeXBlXCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwib3B0aW9uYWwgdHJ1dGhpbmVzcyBjb25kaXRpb25cIiwgbm9kZUxvY2F0aW9uKG5vZGUucHJlZGljYXRlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIGlmIChub2RlIGluc3RhbmNlb2YgVW5sZXNzTm9kZSAmJiAhZXhhY3ROaWxUZXN0KG5vZGUucHJlZGljYXRlLCBzb3VyY2UpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcInVubGVzcyBjb25kaXRpb24gb3RoZXIgdGhhbiBhbiBleGFjdCBuaWw/IHByZXNlbmNlIGd1YXJkXCIsIG5vZGVMb2NhdGlvbihub2RlLnByZWRpY2F0ZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cblxuICBjb25zdCBwcmVkaWNhdGUgPSBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnByZWRpY2F0ZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dClcbiAgY29uc3QgY29uZGl0aW9uID0gbm9kZSBpbnN0YW5jZW9mIFVubGVzc05vZGUgJiYgcHJlZGljYXRlLmtpbmQgPT0gXCJVbmFyeUV4cHJlc3Npb25cIiAmJlxuICAgIHByZWRpY2F0ZS5vcGVyYW5kLmtpbmQgPT0gXCJPcHRpb25hbElzUHJlc2VudFwiXG4gICAgPyBwcmVkaWNhdGUub3BlcmFuZFxuICAgIDogcHJlZGljYXRlXG4gIGlmIChub2RlIGluc3RhbmNlb2YgVW5sZXNzTm9kZSAmJiBjb25kaXRpb24ua2luZCAhPSBcIk9wdGlvbmFsSXNQcmVzZW50XCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwidW5sZXNzIGNvbmRpdGlvbiBvdGhlciB0aGFuIGFuIGV4YWN0IG5pbD8gcHJlc2VuY2UgZ3VhcmRcIiwgbm9kZUxvY2F0aW9uKG5vZGUucHJlZGljYXRlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBjb25zdCBjb25zZXF1ZW50Q29udGV4dCA9IHsuLi5jb250ZXh0LCBiaW5kaW5nczogbmV3IE1hcChjb250ZXh0LmJpbmRpbmdzKX1cbiAgY29uc3QgYWx0ZXJuYXRlQ29udGV4dCA9IHsuLi5jb250ZXh0LCBiaW5kaW5nczogbmV3IE1hcChjb250ZXh0LmJpbmRpbmdzKX1cbiAgbGV0IGFsdGVybmF0ZVxuICBjb25zdCBzdWJzZXF1ZW50ID0gbm9kZSBpbnN0YW5jZW9mIFVubGVzc05vZGUgPyBub2RlLmVsc2VDbGF1c2UgOiBub2RlLnN1YnNlcXVlbnRcblxuICBpZiAoc3Vic2VxdWVudCkge1xuICAgIGlmIChzdWJzZXF1ZW50IGluc3RhbmNlb2YgRWxzZU5vZGUpIHtcbiAgICAgIGFsdGVybmF0ZSA9IGNvbnZlcnRCbG9jayhzdWJzZXF1ZW50LnN0YXRlbWVudHMsIGNvbW1lbnRzLCBhbHRlcm5hdGVDb250ZXh0LCBmaWxlbmFtZSwgc291cmNlLFxuICAgICAgICBub2RlTG9jYXRpb24oc3Vic2VxdWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgfSBlbHNlIGlmIChzdWJzZXF1ZW50IGluc3RhbmNlb2YgSWZOb2RlKSB7XG4gICAgICBhbHRlcm5hdGUgPSB7XG4gICAgICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkJsb2NrXCIpLFxuICAgICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKHN1YnNlcXVlbnQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICBzdGF0ZW1lbnRzOiBbY29udmVydElmKHN1YnNlcXVlbnQsIGNvbW1lbnRzLCBhbHRlcm5hdGVDb250ZXh0LCBmaWxlbmFtZSwgc291cmNlKV1cbiAgICAgIH1cbiAgICB9IGVsc2UgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBzdWJzZXF1ZW50LmNvbnN0cnVjdG9yLm5hbWUsIG5vZGVMb2NhdGlvbihzdWJzZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uKGFsdGVybmF0ZSA/IHthbHRlcm5hdGV9IDoge30pLFxuICAgIGNvbmRpdGlvbixcbiAgICBjb25zZXF1ZW50OiBjb252ZXJ0QmxvY2sobm9kZS5zdGF0ZW1lbnRzLCBjb21tZW50cywgY29uc2VxdWVudENvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UsIGxvY2F0aW9uKSxcbiAgICBraW5kOiBcIklmU3RhdGVtZW50XCIsXG4gICAgbG9jYXRpb25cbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBvcmRpbmFyeSBibG9jay1mb3JtIFJ1YnkgcHJlLWNvbmRpdGlvbiBsb29wLlxuICogQHBhcmFtIHtXaGlsZU5vZGV9IG5vZGUgLSBQcmlzbSB3aGlsZSBub2RlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbS9zcmMvZGVzZXJpYWxpemUuanNcIikuQ29tbWVudFtdfSBjb21tZW50cyAtIFByaXNtIGNvbW1lbnRzLlxuICogQHBhcmFtIHtSdWJ5Q29udmVyc2lvbkNvbnRleHR9IGNvbnRleHQgLSBUeXBlZCBsZXhpY2FsIGNvbnZlcnNpb24gY29udGV4dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuV2hpbGVTdGF0ZW1lbnR9IFNlbWFudGljIGxvb3AuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRXaGlsZShub2RlLCBjb21tZW50cywgY29udGV4dCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBrZXl3b3JkTG9jYXRpb24gPSBwcmlzbUxvY2F0aW9uKG5vZGUua2V5d29yZExvYywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZS5pc0JlZ2luTW9kaWZpZXIoKSB8fCAhbm9kZS5jbG9zaW5nTG9jIHx8IG5vZGUua2V5d29yZExvYy5zdGFydE9mZnNldCAhPSBub2RlLmxvY2F0aW9uLnN0YXJ0T2Zmc2V0KSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1vZGlmaWVyIHdoaWxlXCIsIGtleXdvcmRMb2NhdGlvbilcbiAgfVxuICBjb25zdCBib2R5Q29udGV4dCA9IHsuLi5jb250ZXh0LCBiaW5kaW5nczogbmV3IE1hcChjb250ZXh0LmJpbmRpbmdzKX1cblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keTogY29udmVydEJsb2NrKG5vZGUuc3RhdGVtZW50cywgY29tbWVudHMsIGJvZHlDb250ZXh0LCBmaWxlbmFtZSwgc291cmNlLCBsb2NhdGlvbiksXG4gICAgY29uZGl0aW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLnByZWRpY2F0ZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCwgdW5kZWZpbmVkLCB0cnVlKSxcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJXaGlsZVN0YXRlbWVudFwiKSxcbiAgICBsb2NhdGlvblxuICB9LCB7a2V5d29yZDoga2V5d29yZExvY2F0aW9ufSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgc3VwcG9ydGVkIFJ1YnkgcHV0cyBlbnRyeSBwb2ludC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIFByaXNtIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtSdWJ5Q29udmVyc2lvbkNvbnRleHR9IGNvbnRleHQgLSBUeXBlZCBsZXhpY2FsIGNvbnZlcnNpb24gY29udGV4dC5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QcmludFN0YXRlbWVudH0gUHJpbnQgc3RhdGVtZW50LlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UHJpbnQobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgbm9kZS5yZWNlaXZlciB8fCBub2RlLm5hbWUgIT0gXCJwdXRzXCIgfHwgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBub2RlLmNvbnN0cnVjdG9yLm5hbWUsIGxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSwgY29udGV4dCksIGtpbmQ6IFwiUHJpbnRTdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogUGFyc2VzIFJ1YnkgaW50byB0aGUgc2hhcmVkIHNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBpbnB1dCAtIFBhcnNlciBpbnB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5maWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5zb3VyY2UgLSBTb3VyY2UgdGV4dC5cbiAqIEBwYXJhbSB7cmVhZG9ubHkgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRWZmZWN0Q2FwYWJpbGl0eURlY2xhcmF0aW9uW119IFtpbnB1dC5jYXBhYmlsaXRpZXNdIC0gQ29tcGlsZXItYXV0aG9yaXplZCBkZWNsYXJhdGlvbnMuXG4gKiBAcGFyYW0ge3tpc0VudHJ5OiBib29sZWFuLCBjbGFzc2VzPzogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbj4sIGZ1bmN0aW9uczogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbj4sIHJlY29yZHM6IE1hcDxzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJlY29yZERlY2xhcmF0aW9uPiwgZXJyb3JzPzogTWFwPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXJyb3JEZWNsYXJhdGlvbj59fSBbaW5wdXQucHJvZ3JhbV0gLSBSZXNvbHZlZCBwcm9ncmFtIGltcG9ydHMgYW5kIGVudHJ5IHJvbGUuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IFNlbWFudGljIG1vZHVsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUnVieSh7Y2FwYWJpbGl0aWVzID0gW10sIGZpbGVuYW1lLCBzb3VyY2UsIHByb2dyYW19KSB7XG4gIGNvbnN0IHJlc3VsdCA9IHBhcnNlUHJpc20oc291cmNlLCB7ZmlsZXBhdGg6IGZpbGVuYW1lfSlcblxuICBpZiAocmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3QgZXJyb3IgPSByZXN1bHQuZXJyb3JzWzBdXG4gICAgY29uc3QgbG9jYXRpb24gPSBsb2NhdGlvbkZyb21PZmZzZXRzKGZpbGVuYW1lLCBzb3VyY2UsIGVycm9yLmxvY2F0aW9uLnN0YXJ0T2Zmc2V0LCBlcnJvci5sb2NhdGlvbi5zdGFydE9mZnNldCArIGVycm9yLmxvY2F0aW9uLmxlbmd0aClcblxuICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe2NvZGU6IFwiUEFSU0VfRVJST1JcIiwgbGFuZ3VhZ2U6IFwicnVieVwiLCBsb2NhdGlvbiwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pXG4gIH1cblxuICBpZiAoIShyZXN1bHQudmFsdWUgaW5zdGFuY2VvZiBQcm9ncmFtTm9kZSkpIHRocm93IG5ldyBFcnJvcihcIlByaXNtIHJldHVybmVkIGEgbm9uLXByb2dyYW0gcm9vdC5cIilcblxuICBsZXQgYm9keSA9IHRhc2swMzRSdWJ5Qm9keShyZXN1bHQudmFsdWUuc3RhdGVtZW50cy5ib2R5LCByZXN1bHQuY29tbWVudHMsIGNhcGFiaWxpdGllcywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAocHJvZ3JhbSkge1xuICAgIGluc3BlY3RSdWJ5TW9kdWxlKHtmaWxlbmFtZSwgc291cmNlfSlcbiAgICBjb25zdCBtb2R1bGVOb2RlID0gLyoqIEB0eXBlIHtNb2R1bGVOb2RlfSAqLyAoYm9keS5maW5kKChub2RlKSA9PiBub2RlIGluc3RhbmNlb2YgTW9kdWxlTm9kZSkpXG5cbiAgICBib2R5ID0gbW9kdWxlTm9kZS5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgPyBtb2R1bGVOb2RlLmJvZHkuYm9keSA6IFtdXG4gICAgY29uc3QgbW9kdWxlRnVuY3Rpb25Ob2RlcyA9IGJvZHkuZmlsdGVyKGlzTW9kdWxlRnVuY3Rpb25NYXJrZXIpXG4gICAgY29uc3QgZGVmaW5pdGlvbnMgPSBib2R5LmZpbHRlcigobm9kZSkgPT4gbm9kZSBpbnN0YW5jZW9mIERlZk5vZGUpXG5cbiAgICBpZiAoZGVmaW5pdGlvbnMubGVuZ3RoID4gMCAmJiAobW9kdWxlRnVuY3Rpb25Ob2Rlcy5sZW5ndGggIT0gMSB8fCBib2R5LmluZGV4T2YobW9kdWxlRnVuY3Rpb25Ob2Rlc1swXSkgPiBib2R5LmluZGV4T2YoZGVmaW5pdGlvbnNbMF0pKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1vZHVsZSBmdW5jdGlvbnMgb3V0c2lkZSBvbmUgbGVhZGluZyBtb2R1bGVfZnVuY3Rpb24gcHJvZmlsZVwiLFxuICAgICAgICBub2RlTG9jYXRpb24obW9kdWxlRnVuY3Rpb25Ob2Rlc1sxXSA/PyBkZWZpbml0aW9uc1swXSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgfVxuICAgIGJvZHkgPSBib2R5LmZpbHRlcigobm9kZSkgPT4gIWlzTW9kdWxlRnVuY3Rpb25NYXJrZXIobm9kZSkgJiYgIXJ1YnlWaXNpYmlsaXR5TWFya2VyKG5vZGUpKVxuICB9XG4gIGNvbnN0IGNsYXNzTm9kZXMgPSBib2R5LmZpbHRlcigobm9kZSkgPT4gbm9kZSBpbnN0YW5jZW9mIENsYXNzTm9kZSlcbiAgY29uc3QgZXJyb3JOb2RlcyA9IGNsYXNzTm9kZXMuZmlsdGVyKChub2RlKSA9PiBub2RlLnN1cGVyY2xhc3MgaW5zdGFuY2VvZiBDb25zdGFudFJlYWROb2RlICYmIG5vZGUuc3VwZXJjbGFzcy5uYW1lID09IFwiU3RhbmRhcmRFcnJvclwiKVxuICBjb25zdCByZWZlcmVuY2VDbGFzc05vZGVzID0gY2xhc3NOb2Rlcy5maWx0ZXIoKG5vZGUpID0+ICFlcnJvck5vZGVzLmluY2x1ZGVzKG5vZGUpICYmIG5vZGUuYm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlICYmXG4gICAgbm9kZS5ib2R5LmJvZHkubGVuZ3RoID4gMCAmJiBub2RlLmJvZHkuYm9keS5ldmVyeSgobWVtYmVyKSA9PiBtZW1iZXIgaW5zdGFuY2VvZiBEZWZOb2RlKSlcbiAgY29uc3QgcmVjb3JkTm9kZXMgPSBjbGFzc05vZGVzLmZpbHRlcigobm9kZSkgPT4gIWVycm9yTm9kZXMuaW5jbHVkZXMobm9kZSkgJiYgIXJlZmVyZW5jZUNsYXNzTm9kZXMuaW5jbHVkZXMobm9kZSkpXG4gIGNvbnN0IGVycm9yRGVjbGFyYXRpb25zID0gZXJyb3JOb2Rlcy5tYXAoKG5vZGUsIGluZGV4KSA9PiAoe1xuICAgIGlkOiBgZXJyb3I6JHtpbmRleH1gLFxuICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkVycm9yRGVjbGFyYXRpb25cIiksXG4gICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBuYW1lOiBub2RlLm5hbWVcbiAgfSkpXG4gIGNvbnN0IHJlY29yZERlY2xhcmF0aW9ucyA9IHJlY29yZE5vZGVzLm1hcCgobm9kZSwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBpZCA9IGByZWNvcmQ6JHtpbmRleH1gXG4gICAgY29uc3QgZG9jdW1lbnRlZCA9IHR5cGVDb21tZW50cyhyZXN1bHQuY29tbWVudHMsIG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UsIGlkKVxuXG4gICAgaWYgKGRvY3VtZW50ZWQucGFyYW1ldGVycy5zaXplIHx8IGRvY3VtZW50ZWQucmV0dXJuVHlwZSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcImZ1bmN0aW9uIHR5cGUgYW5ub3RhdGlvbiBvbiByZWNvcmQgZGVjbGFyYXRpb25cIiwgbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBmaWVsZHM6IFtdLFxuICAgICAgaWQsXG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJSZWNvcmREZWNsYXJhdGlvblwiKSxcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBuYW1lOiBub2RlLm5hbWUsXG4gICAgICAuLi4oZG9jdW1lbnRlZC50eXBlUGFyYW1ldGVycyA/IHt0eXBlUGFyYW1ldGVyczogZG9jdW1lbnRlZC50eXBlUGFyYW1ldGVyc30gOiB7fSlcbiAgICB9XG4gIH0pXG4gIGNvbnN0IGNsYXNzRGVjbGFyYXRpb25zID0gcmVmZXJlbmNlQ2xhc3NOb2Rlcy5tYXAoKG5vZGUsIGluZGV4KSA9PiAoe1xuICAgIGNvbnN0cnVjdG9yOiAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNvbnN0cnVjdG9yRGVjbGFyYXRpb259ICovICh7fSksIGZpZWxkczogW10sIGlkOiBgY2xhc3M6JHtpbmRleH1gLFxuICAgIGtpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIkNsYXNzRGVjbGFyYXRpb25cIiksIGxvY2F0aW9uOiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksIG1ldGhvZHM6IFtdLCBuYW1lOiBub2RlLm5hbWVcbiAgfSkpXG4gIGNvbnN0IHJlb3BlbmVkID0gY2xhc3NEZWNsYXJhdGlvbnMuZmluZCgoZGVjbGFyYXRpb24sIGluZGV4KSA9PlxuICAgIGNsYXNzRGVjbGFyYXRpb25zLmZpbmRJbmRleCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUubmFtZSA9PSBkZWNsYXJhdGlvbi5uYW1lKSAhPSBpbmRleClcblxuICBpZiAocmVvcGVuZWQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgYHJlZmVyZW5jZSBjbGFzcyByZW9wZW5pbmcgJyR7cmVvcGVuZWQubmFtZX0nYCwgcmVvcGVuZWQubG9jYXRpb24pXG4gIGNvbnN0IHJlY29yZE5hbWVzID0gLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZWNvcmREZWNsYXJhdGlvbiB8IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FZmZlY3RSZXNvdXJjZURlY2xhcmF0aW9uPn0gKi8gKFxuICAgIG5ldyBNYXAocHJvZ3JhbT8ucmVjb3JkcyA/PyBbXSkpXG4gIGZvciAoY29uc3QgW25hbWUsIGRlY2xhcmF0aW9uXSBvZiBwcm9ncmFtPy5jbGFzc2VzID8/IFtdKSByZWNvcmROYW1lcy5zZXQobmFtZSwgZGVjbGFyYXRpb24pXG4gIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgY2FwYWJpbGl0aWVzLmZsYXRNYXAoKHtyZXNvdXJjZXN9KSA9PiByZXNvdXJjZXMpKSByZWNvcmROYW1lcy5zZXQocmVzb3VyY2UubmFtZSwgcmVzb3VyY2UpXG4gIGNvbnN0IGVycm9yTmFtZXMgPSBuZXcgTWFwKHByb2dyYW0/LmVycm9ycyA/PyBbXSlcbiAgZm9yIChjb25zdCBmYWlsdXJlIG9mIGNhcGFiaWxpdGllcy5mbGF0TWFwKCh7ZmFpbHVyZXN9KSA9PiBmYWlsdXJlcykpIHtcbiAgICBlcnJvck5hbWVzLnNldChmYWlsdXJlLm5hbWUsIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXJyb3JEZWNsYXJhdGlvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKGZhaWx1cmUpKSlcbiAgfVxuICBmb3IgKGNvbnN0IGRlY2xhcmF0aW9uIG9mIGVycm9yRGVjbGFyYXRpb25zKSBlcnJvck5hbWVzLnNldChkZWNsYXJhdGlvbi5uYW1lLCBkZWNsYXJhdGlvbilcbiAgY29uc3QgZXJyb3JzQnlJZCA9IG5ldyBNYXAoWy4uLmVycm9yTmFtZXMudmFsdWVzKCldLm1hcCgoZGVjbGFyYXRpb24pID0+IFsvKiogQHR5cGUge3N0cmluZ30gKi8gKGRlY2xhcmF0aW9uLmlkKSwgZGVjbGFyYXRpb25dKSlcbiAgY29uc3QgZXJyb3JzID0gZXJyb3JOb2Rlcy5tYXAoKG5vZGUsIGluZGV4KSA9PiBjb252ZXJ0UnVieUVycm9yKG5vZGUsIGVycm9yRGVjbGFyYXRpb25zW2luZGV4XSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgcmVjb3JkRGVjbGFyYXRpb25zKSByZWNvcmROYW1lcy5zZXQoZGVjbGFyYXRpb24ubmFtZSwgZGVjbGFyYXRpb24pXG4gIGZvciAoY29uc3QgZGVjbGFyYXRpb24gb2YgY2xhc3NEZWNsYXJhdGlvbnMpIHJlY29yZE5hbWVzLnNldChkZWNsYXJhdGlvbi5uYW1lLCBkZWNsYXJhdGlvbilcbiAgY29uc3QgcmVjb3Jkc0J5SWQgPSBuZXcgTWFwKHJlY29yZERlY2xhcmF0aW9ucy5tYXAoKGRlY2xhcmF0aW9uKSA9PiBbLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkZWNsYXJhdGlvbi5pZCksIGRlY2xhcmF0aW9uXSkpXG4gIGNvbnN0IGNsYXNzZXNCeUlkID0gbmV3IE1hcChbXG4gICAgLi4uWy4uLnByb2dyYW0/LmNsYXNzZXM/LnZhbHVlcygpID8/IFtdXS5tYXAoKGRlY2xhcmF0aW9uKSA9PiAvKiogQHR5cGUge1tzdHJpbmcsIGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkNsYXNzRGVjbGFyYXRpb25dfSAqLyAoXG4gICAgICBbLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkZWNsYXJhdGlvbi5pZCksIGRlY2xhcmF0aW9uXSkpLFxuICAgIC4uLmNsYXNzRGVjbGFyYXRpb25zLm1hcCgoZGVjbGFyYXRpb24pID0+IC8qKiBAdHlwZSB7W3N0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuQ2xhc3NEZWNsYXJhdGlvbl19ICovIChcbiAgICAgIFsvKiogQHR5cGUge3N0cmluZ30gKi8gKGRlY2xhcmF0aW9uLmlkKSwgZGVjbGFyYXRpb25dKSlcbiAgXSlcbiAgY29uc3QgZnVuY3Rpb25Ob2RlcyA9IGJvZHkuZmlsdGVyKChub2RlKSA9PiBub2RlIGluc3RhbmNlb2YgRGVmTm9kZSlcbiAgY29uc3QgYWxsb3dzQnVpbHRpbk91dHB1dCA9IGNhcGFiaWxpdGllcy5zb21lKCh7b3BlcmF0aW9uc30pID0+IG9wZXJhdGlvbnMuc29tZSgoe25hbWV9KSA9PiBuYW1lID09IFwidjFfd3JpdGVfbGluZVwiKSlcbiAgY29uc3Qgc2lnbmF0dXJlcyA9IGZ1bmN0aW9uTm9kZXMubWFwKChub2RlLCBpbmRleCkgPT5cbiAgICBjb252ZXJ0RnVuY3Rpb25TaWduYXR1cmUobm9kZSwgcmVzdWx0LmNvbW1lbnRzLCBmaWxlbmFtZSwgc291cmNlLCByZWNvcmROYW1lcywgYGZ1bmN0aW9uOiR7aW5kZXh9YCwgYWxsb3dzQnVpbHRpbk91dHB1dCkpXG4gIGNvbnN0IGZ1bmN0aW9uU2lnbmF0dXJlcyA9IG5ldyBNYXAoWy4uLmNhcGFiaWxpdHlGdW5jdGlvblNpZ25hdHVyZXMoY2FwYWJpbGl0aWVzLCBtb2R1bGVMb2NhdGlvbihmaWxlbmFtZSwgc291cmNlKSksXG4gICAgLi4uKHByb2dyYW0/LmZ1bmN0aW9ucyA/PyBbXSldLm1hcCgoW2xvY2FsTmFtZSwgZGVjbGFyYXRpb25dKSA9PiBbbG9jYWxOYW1lLCB7XG4gICAgbG9jYXRpb246IGRlY2xhcmF0aW9uLmxvY2F0aW9uLFxuICAgIG5hbWU6IGxvY2FsTmFtZSxcbiAgICBuYW1lTG9jYXRpb246IGRlY2xhcmF0aW9uLmxvY2F0aW9uLFxuICAgIHBhcmFtZXRlcnM6IGRlY2xhcmF0aW9uLnBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogZGVjbGFyYXRpb24ucmV0dXJuVHlwZSxcbiAgICAuLi4oZGVjbGFyYXRpb24udHlwZVBhcmFtZXRlcnMgPyB7dHlwZVBhcmFtZXRlcnM6IGRlY2xhcmF0aW9uLnR5cGVQYXJhbWV0ZXJzfSA6IHt9KVxuICB9XSkpXG4gIGZvciAoY29uc3Qgc2lnbmF0dXJlIG9mIHNpZ25hdHVyZXMpIGZ1bmN0aW9uU2lnbmF0dXJlcy5zZXQoc2lnbmF0dXJlLm5hbWUsIHNpZ25hdHVyZSlcbiAgY29uc3QgcmVjb3JkcyA9IHJlY29yZE5vZGVzLm1hcCgobm9kZSwgaW5kZXgpID0+XG4gICAgY29udmVydFJ1YnlSZWNvcmQobm9kZSwgcmVjb3JkRGVjbGFyYXRpb25zW2luZGV4XSwgcmVjb3JkTmFtZXMsIHJlc3VsdC5jb21tZW50cywgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIGNvbnN0IGNsYXNzZXMgPSByZWZlcmVuY2VDbGFzc05vZGVzLm1hcCgobm9kZSwgaW5kZXgpID0+IGNvbnZlcnRSdWJ5UmVmZXJlbmNlQ2xhc3Mobm9kZSwgY2xhc3NEZWNsYXJhdGlvbnNbaW5kZXhdLFxuICAgIHJlY29yZE5hbWVzLCByZWNvcmRzQnlJZCwgY2xhc3Nlc0J5SWQsIGZ1bmN0aW9uU2lnbmF0dXJlcywgZXJyb3JOYW1lcywgZXJyb3JzQnlJZCwgcmVzdWx0LmNvbW1lbnRzLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgZnVuY3Rpb25zID0gZnVuY3Rpb25Ob2Rlcy5tYXAoKG5vZGUsIGluZGV4KSA9PlxuICAgIGNvbnZlcnRGdW5jdGlvbihub2RlLCBzaWduYXR1cmVzW2luZGV4XSwgZnVuY3Rpb25TaWduYXR1cmVzLCByZWNvcmROYW1lcywgcmVjb3Jkc0J5SWQsIGNsYXNzZXNCeUlkLCBlcnJvck5hbWVzLCBlcnJvcnNCeUlkLFxuICAgICAgcmVzdWx0LmNvbW1lbnRzLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgZW50cnlOb2RlcyA9IGJvZHkuZmlsdGVyKChub2RlKSA9PiAhKG5vZGUgaW5zdGFuY2VvZiBEZWZOb2RlKSAmJiAhKG5vZGUgaW5zdGFuY2VvZiBDbGFzc05vZGUpKVxuICBjb25zdCBsb2NhdGlvbiA9IG1vZHVsZUxvY2F0aW9uKGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKHByb2dyYW0gJiYgIXByb2dyYW0uaXNFbnRyeSAmJiBlbnRyeU5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwidG9wLWxldmVsIHNpZGUgZWZmZWN0IG91dHNpZGUgdGhlIHNlbGVjdGVkIGVudHJ5IG1vZHVsZVwiLCBub2RlTG9jYXRpb24oZW50cnlOb2Rlc1swXSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gIH1cbiAgY29uc3QgZmlyc3RFbnRyeSA9IGVudHJ5Tm9kZXNbMF1cbiAgY29uc3QgZW50cnlMb2NhdGlvbiA9IGZpcnN0RW50cnkgPyBsb2NhdGlvbkZyb21PZmZzZXRzKFxuICAgIGZpbGVuYW1lLFxuICAgIHNvdXJjZSxcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoc291cmNlLCBmaXJzdEVudHJ5LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0KSxcbiAgICB1dGY4Qnl0ZU9mZnNldFRvVXRmMTZPZmZzZXQoXG4gICAgICBzb3VyY2UsXG4gICAgICAoZW50cnlOb2Rlcy5hdCgtMSk/LmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ID8/IDApICsgKGVudHJ5Tm9kZXMuYXQoLTEpPy5sb2NhdGlvbi5sZW5ndGggPz8gMClcbiAgICApXG4gICkgOiBsb2NhdGlvblxuICBjb25zdCBlbnRyeUNvbnRleHQgPSB7YmluZGluZ3M6IG5ldyBNYXAoKSwgY2xhc3NlczogY2xhc3Nlc0J5SWQsIGVycm9yTmFtZXMsIGVycm9yczogZXJyb3JzQnlJZCwgZnVuY3Rpb25zOiBmdW5jdGlvblNpZ25hdHVyZXMsXG4gICAgb3JkZXJlZE1hcERlY2xhcmF0aW9uczogb3JkZXJlZE1hcERlY2xhcmF0aW9uc0ZvclJ1YnkoZW50cnlOb2RlcyksIHJlY29yZE5hbWVzLCByZWNvcmRzOiByZWNvcmRzQnlJZH1cbiAgY29uc3QgZW50cnlCbG9jayA9IHtcbiAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCbG9ja1wiKSxcbiAgICBsb2NhdGlvbjogZW50cnlMb2NhdGlvbixcbiAgICBzdGF0ZW1lbnRzOiBlbnRyeU5vZGVzLm1hcCgoc3RhdGVtZW50KSA9PiBjb252ZXJ0U3RhdGVtZW50KHN0YXRlbWVudCwgcmVzdWx0LmNvbW1lbnRzLCBlbnRyeUNvbnRleHQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgaWYgKCFwcm9ncmFtICYmIGZ1bmN0aW9ucy5sZW5ndGggPT0gMCAmJiBjYXBhYmlsaXRpZXMubGVuZ3RoID09IDAgJiYgIWJsb2NrUmVmZXJlbmNlc1Byb3RlY3RlZEVudHJ5KGVudHJ5QmxvY2spKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBcIm1vZHVsZSB3aXRob3V0IGEgZnVuY3Rpb25cIiwgbG9jYXRpb24pXG4gIH1cbiAgcmV0dXJuIHtcbiAgICBlbnRyeVBvaW50OiB7XG4gICAgICBib2R5OiBlbnRyeUJsb2NrLFxuICAgICAga2luZDogXCJFbnRyeVBvaW50XCIsXG4gICAgICBsb2NhdGlvbjogZW50cnlMb2NhdGlvblxuICAgIH0sXG4gICAgZnVuY3Rpb25zLFxuICAgIGtpbmQ6IFwiTW9kdWxlXCIsXG4gICAgbG9jYXRpb24sXG4gICAgLi4uKGNsYXNzZXMubGVuZ3RoID4gMCA/IHtjbGFzc2VzfSA6IHt9KSxcbiAgICAuLi4oZXJyb3JzLmxlbmd0aCA+IDAgPyB7ZXJyb3JzfSA6IHt9KSxcbiAgICAuLi4ocmVjb3Jkcy5sZW5ndGggPiAwID8ge3JlY29yZHN9IDoge30pXG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIGV4YWN0IHByb3RlY3RlZCBSdWJ5IHByb2JlIHN1cHBvcnQgYmVmb3JlIHBvcnRhYmxlIGNvbnZlcnNpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGVbXX0gYm9keSAtIFBhcnNlZCB0b3AtbGV2ZWwgbm9kZXMuXG4gKiBAcGFyYW0ge3tsb2NhdGlvbjoge3N0YXJ0T2Zmc2V0OiBudW1iZXIsIGxlbmd0aDogbnVtYmVyfX1bXX0gY29tbWVudHMgLSBQYXJzZXIgY29tbWVudHMuXG4gKiBAcGFyYW0ge3JlYWRvbmx5IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkVmZmVjdENhcGFiaWxpdHlEZWNsYXJhdGlvbltdfSBjYXBhYmlsaXRpZXMgLSBBdXRob3JpemVkIGRlY2xhcmF0aW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZVtdfSBQb3J0YWJsZSBub2Rlcy5cbiAqL1xuZnVuY3Rpb24gdGFzazAzNFJ1YnlCb2R5KGJvZHksIGNvbW1lbnRzLCBjYXBhYmlsaXRpZXMsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKCFpc1Rhc2swMzRSZXNvdXJjZVByb2JlKGNhcGFiaWxpdGllcykpIHJldHVybiBib2R5XG4gIGNvbnN0IG1hcmtlciA9IGNvbW1lbnRzLmZpbmQoKGNvbW1lbnQpID0+XG4gICAgc291cmNlLnNsaWNlKGNvbW1lbnQubG9jYXRpb24uc3RhcnRPZmZzZXQsIGNvbW1lbnQubG9jYXRpb24uc3RhcnRPZmZzZXQgKyBjb21tZW50LmxvY2F0aW9uLmxlbmd0aCkgPT1cbiAgICAgIFwiIyBzZW1hbnRpZm9sZC10YXNrMDM0LXN1cHBvcnRcIilcblxuICBpZiAoIW1hcmtlcikgcmV0dXJuIGJvZHlcbiAgaWYgKCFoYXNFeGFjdEVmZmVjdFN1cHBvcnQoc291cmNlLCBcInJ1YnlcIikpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibWFsZm9ybWVkIHByb3RlY3RlZCBUYXNrIDAzNCBzdXBwb3J0XCIsIG5vZGVMb2NhdGlvbihib2R5WzBdLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBjb25zdCBleHBlY3RlZCA9IFtcbiAgICBbXCJDbGFzc05vZGVcIiwgXCJQcm9iZU9wZXJhdGlvbkZhaWx1cmVcIl0sIFtcIkNsYXNzTm9kZVwiLCBcIlByb2JlQWNxdWlyZUZhaWx1cmVcIl0sIFtcIkNsYXNzTm9kZVwiLCBcIlByb2JlUmVhZEZhaWx1cmVcIl0sXG4gICAgW1wiQ2xhc3NOb2RlXCIsIFwiUHJvYmVDbG9zZUZhaWx1cmVcIl0sIFtcIkNsYXNzTm9kZVwiLCBcIlByb2JlUmVzb3VyY2VDbG9zZWRcIl0sIFtcIkNsYXNzTm9kZVwiLCBcIlByb2JlUmVzb3VyY2VcIl0sXG4gICAgW1wiR2xvYmFsVmFyaWFibGVXcml0ZU5vZGVcIiwgXCIkX19zZW1hbnRpZm9sZF90YXNrMDM0X3RyYWNlXCJdLCBbXCJEZWZOb2RlXCIsIFwicHJvYmVFZmZlY3RcIl0sIFtcIkRlZk5vZGVcIiwgXCJwcm9iZUFjcXVpcmVcIl0sXG4gICAgW1wiRGVmTm9kZVwiLCBcInByb2JlUmVhZFwiXSwgW1wiRGVmTm9kZVwiLCBcInByb2JlQ2xvc2VcIl0sIFtcIkRlZk5vZGVcIiwgXCJwcm9iZVRyYWNlXCJdXG4gIF1cbiAgY29uc3QgbWF0Y2hlcyA9IGV4cGVjdGVkLmV2ZXJ5KChba2luZCwgbmFtZV0sIGluZGV4KSA9PiBib2R5W2luZGV4XT8uY29uc3RydWN0b3IubmFtZSA9PSBraW5kICYmIFJlZmxlY3QuZ2V0KGJvZHlbaW5kZXhdLCBcIm5hbWVcIikgPT0gbmFtZSlcbiAgY29uc3QgZW5kID0gY29tbWVudHMuZmluZCgoY29tbWVudCkgPT5cbiAgICBzb3VyY2Uuc2xpY2UoY29tbWVudC5sb2NhdGlvbi5zdGFydE9mZnNldCwgY29tbWVudC5sb2NhdGlvbi5zdGFydE9mZnNldCArIGNvbW1lbnQubG9jYXRpb24ubGVuZ3RoKSA9PVxuICAgICAgXCIjIHNlbWFudGlmb2xkLXRhc2swMzQtc3VwcG9ydC1lbmRcIilcblxuICBpZiAoIW1hdGNoZXMgfHwgIWVuZCB8fCBlbmQubG9jYXRpb24uc3RhcnRPZmZzZXQgPCBib2R5W2V4cGVjdGVkLmxlbmd0aCAtIDFdLmxvY2F0aW9uLnN0YXJ0T2Zmc2V0ICsgYm9keVtleHBlY3RlZC5sZW5ndGggLSAxXS5sb2NhdGlvbi5sZW5ndGgpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibWFsZm9ybWVkIHByb3RlY3RlZCBUYXNrIDAzNCBzdXBwb3J0XCIsIG5vZGVMb2NhdGlvbihib2R5WzBdLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICByZXR1cm4gYm9keS5zbGljZShleHBlY3RlZC5sZW5ndGgpXG59XG5cbi8qKlxuICogUmVhZHMgdGhlIGNhbm9uaWNhbCBwYXJzZXItb3duZWQgUnVieSBtb2R1bGUgYW5kIGxpdGVyYWwgcmVxdWlyZS1yZWxhdGl2ZSBlZGdlcy5cbiAqIEBwYXJhbSB7b2JqZWN0fSBpbnB1dCAtIFBhcnNlciBpbnB1dC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5maWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dC5zb3VyY2UgLSBTb3VyY2UgdGV4dC5cbiAqIEByZXR1cm5zIHt7aW1wb3J0czoge2ltcG9ydGVkTmFtZTogc3RyaW5nLCBsb2NhbE5hbWU6IHN0cmluZywgbG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBuYW1lc3BhY2U6IHRydWUsIHBhdGhMb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIHNwZWNpZmllcjogc3RyaW5nLCBzdGRsaWJDYW5kaWRhdGU/OiB0cnVlLCB0eXBlT25seTogZmFsc2V9W10sIGV4cG9ydHM6IHtleHBvcnRlZE5hbWU6IHN0cmluZywgbG9jYWxOYW1lOiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgdHlwZU9ubHk6IGZhbHNlfVtdLCBuYXRpdmVOYW1lOiBzdHJpbmcsIG5hdGl2ZVJlZmVyZW5jZXM6IHtmb3JtOiBcImNvbnN0cnVjdG9yLWNhbGxcIiB8IFwicmVjZWl2ZXItY2FsbFwiIHwgXCJ1bnF1YWxpZmllZC1jYWxsXCIsIGxvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgbmF0aXZlTW9kdWxlOiBzdHJpbmcsIHN5bWJvbDogc3RyaW5nfVtdfX0gUGFyc2VyLW93bmVkIFJ1YnkgbW9kdWxlIGhlYWRlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc3BlY3RSdWJ5TW9kdWxlKHtmaWxlbmFtZSwgc291cmNlfSkge1xuICBjb25zdCByZXN1bHQgPSBwYXJzZVByaXNtKHNvdXJjZSwge2ZpbGVwYXRoOiBmaWxlbmFtZX0pXG5cbiAgaWYgKHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGVycm9yID0gcmVzdWx0LmVycm9yc1swXVxuICAgIGNvbnN0IGxvY2F0aW9uID0gbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCBlcnJvci5sb2NhdGlvbi5zdGFydE9mZnNldCwgZXJyb3IubG9jYXRpb24uc3RhcnRPZmZzZXQgKyBlcnJvci5sb2NhdGlvbi5sZW5ndGgpXG5cbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtjb2RlOiBcIlBBUlNFX0VSUk9SXCIsIGxhbmd1YWdlOiBcInJ1YnlcIiwgbG9jYXRpb24sIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KVxuICB9XG4gIGlmICghKHJlc3VsdC52YWx1ZSBpbnN0YW5jZW9mIFByb2dyYW1Ob2RlKSkgdGhyb3cgbmV3IEVycm9yKFwiUHJpc20gcmV0dXJuZWQgYSBub24tcHJvZ3JhbSByb290LlwiKVxuICBjb25zdCBib2R5ID0gcmVzdWx0LnZhbHVlLnN0YXRlbWVudHMuYm9keVxuICBjb25zdCBtb2R1bGVzID0gYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUgaW5zdGFuY2VvZiBNb2R1bGVOb2RlKVxuICBjb25zdCBkeW5hbWljUmVxdWlyZSA9IGJvZHkuZmluZChpc0R5bmFtaWNTdGRsaWJSZXF1aXJlKVxuXG4gIGlmIChkeW5hbWljUmVxdWlyZSkge1xuICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgICAgY29kZTogXCJTVERMSUJfRkFDQURFX0RZTkFNSUNfUkVGRVJFTkNFXCIsXG4gICAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKGR5bmFtaWNSZXF1aXJlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIG1lc3NhZ2U6IFwiRHluYW1pYyByZXF1aXJlIGNhbm5vdCBwcm92ZSBhIHN0YW5kYXJkLWxpYnJhcnkgZmFjYWRlIGlkZW50aXR5LlwiXG4gICAgfSlcbiAgfVxuICB2YWxpZGF0ZVRhc2swMzdOYXRpdmVBdHRlbXB0cyhib2R5LCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBpbnZhbGlkID0gYm9keS5maW5kKChub2RlKSA9PiAhKG5vZGUgaW5zdGFuY2VvZiBNb2R1bGVOb2RlKSAmJiAhaXNSZXF1aXJlUmVsYXRpdmUobm9kZSkgJiYgIWlzU3RkbGliUmVxdWlyZShub2RlKSlcblxuICBpZiAobW9kdWxlcy5sZW5ndGggIT0gMSB8fCAhKG1vZHVsZXNbMF0uY29uc3RhbnRQYXRoIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSkgfHwgaW52YWxpZCkge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcInJ1YnlcIiwgXCJvbmUgc2ltcGxlIG1vZHVsZSB3aXRoIGxpdGVyYWwgcmVxdWlyZV9yZWxhdGl2ZSBkZWNsYXJhdGlvbnNcIixcbiAgICAgIG5vZGVMb2NhdGlvbihpbnZhbGlkID8/IG1vZHVsZXNbMV0gPz8gbW9kdWxlc1swXSA/PyByZXN1bHQudmFsdWUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG4gIGNvbnN0IGltcG9ydHMgPSBib2R5LmZpbHRlcigobm9kZSkgPT4gaXNSZXF1aXJlUmVsYXRpdmUobm9kZSkgfHwgaXNTdGRsaWJSZXF1aXJlKG5vZGUpKS5tYXAoKG5vZGUpID0+IHtcbiAgICBjb25zdCBjYWxsID0gLyoqIEB0eXBlIHtDYWxsTm9kZX0gKi8gKG5vZGUpXG4gICAgY29uc3QgYXJndW1lbnQgPSAvKiogQHR5cGUge1N0cmluZ05vZGV9ICovIChjYWxsLmFyZ3VtZW50c18/LmFyZ3VtZW50c19bMF0pXG4gICAgY29uc3Qgc3RkbGliQ2FuZGlkYXRlID0gaXNTdGRsaWJSZXF1aXJlKGNhbGwpXG5cbiAgICBpZiAoIWFyZ3VtZW50LnVuZXNjYXBlZC52YWxpZEVuY29kaW5nIHx8IGFyZ3VtZW50LnVuZXNjYXBlZC5lbmNvZGluZyAhPSBcInV0Zi04XCIgfHwgYXJndW1lbnQuaXNGb3JjZWRCaW5hcnlFbmNvZGluZygpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIFwibm9uLVVURi04IHJlcXVpcmVfcmVsYXRpdmUgcGF0aFwiLCBub2RlTG9jYXRpb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpbXBvcnRlZE5hbWU6IFwiKlwiLFxuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSW1wb3J0XCIpLFxuICAgICAgbG9jYWxOYW1lOiBcIlwiLFxuICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihjYWxsLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIG5hbWVzcGFjZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKHRydWUpLFxuICAgICAgcGF0aExvY2F0aW9uOiBub2RlTG9jYXRpb24oYXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgc3BlY2lmaWVyOiBhcmd1bWVudC51bmVzY2FwZWQudmFsdWUsXG4gICAgICAuLi4oc3RkbGliQ2FuZGlkYXRlID8ge3N0ZGxpYkNhbmRpZGF0ZTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKHRydWUpfSA6IHt9KSxcbiAgICAgIHR5cGVPbmx5OiAvKiogQHR5cGUge2NvbnN0fSAqLyAoZmFsc2UpXG4gICAgfVxuICB9KVxuICBjb25zdCBtb2R1bGVCb2R5ID0gbW9kdWxlc1swXS5ib2R5IGluc3RhbmNlb2YgU3RhdGVtZW50c05vZGUgPyBtb2R1bGVzWzBdLmJvZHkuYm9keSA6IFtdXG4gIGNvbnN0IHZpc2liaWxpdHkgPSBuZXcgTWFwKClcblxuICBmb3IgKGNvbnN0IG5vZGUgb2YgbW9kdWxlQm9keSkge1xuICAgIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgIVtcInByaXZhdGVfY2xhc3NfbWV0aG9kXCIsIFwicHJpdmF0ZV9jb25zdGFudFwiXS5pbmNsdWRlcyhub2RlLm5hbWUpKSBjb250aW51ZVxuICAgIGNvbnN0IG1hcmtlciA9IHJ1YnlWaXNpYmlsaXR5TWFya2VyKG5vZGUpXG5cbiAgICBpZiAoIW1hcmtlcikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwicnVieVwiLCBgbWFsZm9ybWVkICR7bm9kZS5uYW1lfWAsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICBpZiAodmlzaWJpbGl0eS5oYXMobWFya2VyLm5hbWUpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIGBkdXBsaWNhdGUgdmlzaWJpbGl0eSBtYXJrZXIgZm9yICcke21hcmtlci5uYW1lfSdgLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgY29uc3QgZGVjbGFyYXRpb24gPSBtb2R1bGVCb2R5LmZpbmQoKGNhbmRpZGF0ZSkgPT4gbWFya2VyLmtpbmQgPT0gXCJmdW5jdGlvblwiXG4gICAgICA/IGNhbmRpZGF0ZSBpbnN0YW5jZW9mIERlZk5vZGUgJiYgY2FuZGlkYXRlLm5hbWUgPT0gbWFya2VyLm5hbWVcbiAgICAgIDogY2FuZGlkYXRlIGluc3RhbmNlb2YgQ2xhc3NOb2RlICYmIGNhbmRpZGF0ZS5uYW1lID09IG1hcmtlci5uYW1lKVxuXG4gICAgaWYgKCFkZWNsYXJhdGlvbiB8fCBtb2R1bGVCb2R5LmluZGV4T2YoZGVjbGFyYXRpb24pID4gbW9kdWxlQm9keS5pbmRleE9mKG5vZGUpKSB7XG4gICAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJydWJ5XCIsIGB2aXNpYmlsaXR5IG1hcmtlciB3aXRob3V0IGFuIGVhcmxpZXIgJHttYXJrZXIua2luZH1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgfVxuICAgIHZpc2liaWxpdHkuc2V0KG1hcmtlci5uYW1lLCBtYXJrZXIua2luZClcbiAgfVxuICBjb25zdCBleHBvcnRzID0gbW9kdWxlQm9keS5mbGF0TWFwKChub2RlKSA9PiB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBEZWZOb2RlIHx8IG5vZGUgaW5zdGFuY2VvZiBDbGFzc05vZGUpIHtcbiAgICAgIGNvbnN0IGtpbmQgPSBub2RlIGluc3RhbmNlb2YgRGVmTm9kZSA/IFwiZnVuY3Rpb25cIiA6IG5vZGUuYm9keSBpbnN0YW5jZW9mIFN0YXRlbWVudHNOb2RlICYmIG5vZGUuYm9keS5ib2R5Lmxlbmd0aCA+IDAgJiZcbiAgICAgICAgbm9kZS5ib2R5LmJvZHkuZXZlcnkoKG1lbWJlcikgPT4gbWVtYmVyIGluc3RhbmNlb2YgRGVmTm9kZSkgPyBcImNsYXNzXCIgOiBcInJlY29yZFwiXG5cbiAgICAgIGlmICh2aXNpYmlsaXR5LmdldChub2RlLm5hbWUpID09IGtpbmQpIHJldHVybiBbXVxuICAgICAgcmV0dXJuIFt7XG4gICAgICAgIGV4cG9ydGVkTmFtZTogbm9kZS5uYW1lLFxuICAgICAgICBsb2NhbE5hbWU6IG5vZGUubmFtZSxcbiAgICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlIGluc3RhbmNlb2YgQ2xhc3NOb2RlID8gbm9kZS5jb25zdGFudFBhdGggOiBub2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgICAgc3ltYm9sS2luZDogLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0RlY2xhcmF0aW9uS2luZH0gKi8gKGtpbmQpLFxuICAgICAgICB0eXBlT25seTogLyoqIEB0eXBlIHtjb25zdH0gKi8gKGZhbHNlKVxuICAgICAgfV1cbiAgICB9XG4gICAgcmV0dXJuIFtdXG4gIH0pXG4gIGNvbnN0IG5hdGl2ZVJlZmVyZW5jZXMgPSBydWJ5TmF0aXZlUmVmZXJlbmNlcyhtb2R1bGVzWzBdLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIHJldHVybiB7ZXhwb3J0cywgaW1wb3J0cywgbmF0aXZlTmFtZTogbW9kdWxlc1swXS5uYW1lLCBuYXRpdmVSZWZlcmVuY2VzfVxufVxuXG4vKipcbiAqIFJlamVjdHMgcGFyc2VyLXByb3ZlZCBhdHRlbXB0cyB0byB1c2Ugb3IgbXV0YXRlIHRoZSBib3VuZGVkIHNvY2tldCBmYWNhZGUgb3V0c2lkZSBpdHMgZXhhY3Qgc3VyZmFjZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZVtdfSBib2R5IC0gUHJpc20gcHJvZ3JhbSBib2R5LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVRhc2swMzdOYXRpdmVBdHRlbXB0cyhib2R5LCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGFjdGl2ZSA9IGJvZHkuc29tZSgobm9kZSkgPT4gaXNTdGRsaWJSZXF1aXJlKG5vZGUpICYmIG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJlxuICAgIG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzX1swXSBpbnN0YW5jZW9mIFN0cmluZ05vZGUgJiYgbm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0udW5lc2NhcGVkLnZhbHVlID09IFwic29ja2V0XCIpXG4gIGNvbnN0IHJlb3BlbmVkID0gYm9keS5maW5kKChub2RlKSA9PiBub2RlIGluc3RhbmNlb2YgQ2xhc3NOb2RlICYmIG5vZGUubmFtZSA9PSBcIlRDUFNvY2tldFwiKVxuXG4gIGlmIChhY3RpdmUgJiYgcmVvcGVuZWQpIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgIGNvZGU6IFwiU1RETElCX0ZBQ0FERV9SRU9QRU5FRFwiLFxuICAgIGxhbmd1YWdlOiBcInJ1YnlcIixcbiAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKHJlb3BlbmVkLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBtZXNzYWdlOiBcIkNhbGxlciBzb3VyY2UgcmVvcGVucyB0aGUgY29tcGlsZXItb3duZWQgVENQU29ja2V0IGZhY2FkZSBpZGVudGl0eS5cIlxuICB9KVxuICBjb25zdCBtb2R1bGVzID0gYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUgaW5zdGFuY2VvZiBNb2R1bGVOb2RlKVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgb25lIHBhcnNlciBub2RlIGZvciBib3VuZGVkIG5hdGl2ZSBhdHRlbXB0cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gQ2FuZGlkYXRlIFByaXNtIG5vZGUuXG4gICAqL1xuICBmdW5jdGlvbiB2aXNpdChub2RlKSB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkge1xuICAgICAgY29uc3QgcmVjZWl2ZXIgPSBub2RlLnJlY2VpdmVyXG4gICAgICBjb25zdCB0Y3BSZWNlaXZlciA9IHJlY2VpdmVyIGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSAmJiByZWNlaXZlci5uYW1lID09IFwiVENQU29ja2V0XCJcblxuICAgICAgaWYgKHRjcFJlY2VpdmVyKSB7XG4gICAgICAgIGlmICghYWN0aXZlKSB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgICAgICBjb2RlOiBcIlNURExJQl9GQUNBREVfSURFTlRJVFlfVU5QUk9WRURcIixcbiAgICAgICAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbigvKiogQHR5cGUge0NvbnN0YW50UmVhZE5vZGV9ICovIChyZWNlaXZlciksIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICAgIG1lc3NhZ2U6IFwiVENQU29ja2V0IHJlcXVpcmVzIHRoZSBleGFjdCBwYXJzZXItcHJvdmVkIHJlcXVpcmUgXFxcInNvY2tldFxcXCIgaWRlbnRpdHkuXCJcbiAgICAgICAgfSlcbiAgICAgICAgaWYgKG5vZGUubmFtZSAhPSBcIm5ld1wiIHx8IG5vZGUuYmxvY2sgfHwgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCAhPSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlbWFudGlmb2xkRGlhZ25vc3RpYyh7XG4gICAgICAgICAgICBjb2RlOiBcIlNURExJQl9GQUNBREVfTUVNQkVSX1VOU1VQUE9SVEVEXCIsXG4gICAgICAgICAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgICAgICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgICAgICAgbWVzc2FnZTogXCJUQ1BTb2NrZXQgc3VwcG9ydHMgb25seSBleGFjdCB0d28tYXJndW1lbnQgbmV3IHdpdGhvdXQgYSBibG9jay5cIlxuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGtlcm5lbFB1dHMgPSAhbm9kZS5yZWNlaXZlciAmJiBub2RlLm5hbWUgPT0gXCJwdXRzXCIgfHxcbiAgICAgICAgbm9kZS5yZWNlaXZlciBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUgJiYgbm9kZS5yZWNlaXZlci5uYW1lID09IFwiS2VybmVsXCIgJiYgbm9kZS5uYW1lID09IFwicHV0c1wiXG5cbiAgICAgIGlmIChhY3RpdmUgJiYga2VybmVsUHV0cyAmJiAobm9kZS5ibG9jayB8fCBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoICE9IDEpKSB7XG4gICAgICAgIHRocm93IG5ldyBTZW1hbnRpZm9sZERpYWdub3N0aWMoe1xuICAgICAgICAgIGNvZGU6IFwiU1RETElCX0ZBQ0FERV9NRU1CRVJfVU5TVVBQT1JURURcIixcbiAgICAgICAgICBsYW5ndWFnZTogXCJydWJ5XCIsXG4gICAgICAgICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgICAgICBtZXNzYWdlOiBcIlRoZSBUYXNrIDAzNyBPdXRwdXQgZmFjYWRlIHN1cHBvcnRzIGV4YWN0bHkgb25lIHN0cmluZyBhcmd1bWVudCB3aXRob3V0IGEgYmxvY2suXCJcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNvbXBhY3RDaGlsZE5vZGVzKCkpIHZpc2l0KGNoaWxkKVxuICB9XG5cbiAgZm9yIChjb25zdCBtb2R1bGUgb2YgbW9kdWxlcykgdmlzaXQobW9kdWxlKVxufVxuXG4vKipcbiAqIENvbGxlY3RzIGV4YWN0IFRhc2sgMDM3IG5hdGl2ZSBpZGVudGl0aWVzIGZyb20gUHJpc20gbm9kZXMgaW4gc291cmNlIG9yZGVyLlxuICogQHBhcmFtIHtNb2R1bGVOb2RlfSBtb2R1bGUgLSBQYXJzZWQgYXBwbGljYXRpb24gbW9kdWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHt7Zm9ybTogXCJjb25zdHJ1Y3Rvci1jYWxsXCIgfCBcInJlY2VpdmVyLWNhbGxcIiB8IFwidW5xdWFsaWZpZWQtY2FsbFwiLCBsb2NhdGlvbjogaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24sIG5hdGl2ZU1vZHVsZTogc3RyaW5nLCBzeW1ib2w6IHN0cmluZ31bXX0gUGFyc2VyLXByb3ZlZCBuYXRpdmUgcmVmZXJlbmNlcy5cbiAqL1xuZnVuY3Rpb24gcnVieU5hdGl2ZVJlZmVyZW5jZXMobW9kdWxlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIC8qKiBAdHlwZSB7e2Zvcm06IFwiY29uc3RydWN0b3ItY2FsbFwiIHwgXCJyZWNlaXZlci1jYWxsXCIgfCBcInVucXVhbGlmaWVkLWNhbGxcIiwgbG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBuYXRpdmVNb2R1bGU6IHN0cmluZywgb2Zmc2V0OiBudW1iZXIsIHN5bWJvbDogc3RyaW5nfVtdfSAqL1xuICBjb25zdCByZWZlcmVuY2VzID0gW11cblxuICAvKipcbiAgICogVmlzaXRzIG9uZSBwYXJzZXIgbm9kZSB3aXRob3V0IGludGVycHJldGluZyBzb3VyY2UgdGV4dC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gUGFyc2VyIG5vZGUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZnVuY3Rpb24gdmlzaXQobm9kZSkge1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgIW5vZGUuYmxvY2sgJiYgbm9kZS5hcmd1bWVudHNfPy5hcmd1bWVudHNfLmxlbmd0aCA9PSAxICYmXG4gICAgICAhbm9kZS5yZWNlaXZlciAmJiBub2RlLm5hbWUgPT0gXCJwdXRzXCIpIHtcbiAgICAgIHJlZmVyZW5jZXMucHVzaCh7Zm9ybTogXCJ1bnF1YWxpZmllZC1jYWxsXCIsIGxvY2F0aW9uOiBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksIG5hdGl2ZU1vZHVsZTogXCJydWJ5Oktlcm5lbFwiLFxuICAgICAgICBvZmZzZXQ6IG5vZGUubG9jYXRpb24uc3RhcnRPZmZzZXQsIHN5bWJvbDogXCJwdXRzXCJ9KVxuICAgIH1cbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFub2RlLmJsb2NrICYmIG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggPT0gMSAmJiBub2RlLm5hbWUgPT0gXCJwdXRzXCIgJiZcbiAgICAgIG5vZGUuY2FsbE9wZXJhdG9yTG9jICYmIG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBDb25zdGFudFJlYWROb2RlICYmIG5vZGUucmVjZWl2ZXIubmFtZSA9PSBcIktlcm5lbFwiKSB7XG4gICAgICByZWZlcmVuY2VzLnB1c2goe2Zvcm06IFwicmVjZWl2ZXItY2FsbFwiLCBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpLCBuYXRpdmVNb2R1bGU6IFwicnVieTpLZXJuZWxcIixcbiAgICAgICAgb2Zmc2V0OiBub2RlLmxvY2F0aW9uLnN0YXJ0T2Zmc2V0LCBzeW1ib2w6IFwicHV0c1wifSlcbiAgICB9XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiAhbm9kZS5ibG9jayAmJiBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDIgJiYgbm9kZS5uYW1lID09IFwibmV3XCIgJiZcbiAgICAgIG5vZGUuY2FsbE9wZXJhdG9yTG9jICYmIG5vZGUucmVjZWl2ZXIgaW5zdGFuY2VvZiBDb25zdGFudFJlYWROb2RlICYmIG5vZGUucmVjZWl2ZXIubmFtZSA9PSBcIlRDUFNvY2tldFwiKSB7XG4gICAgICByZWZlcmVuY2VzLnB1c2goe2Zvcm06IFwiY29uc3RydWN0b3ItY2FsbFwiLCBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpLCBuYXRpdmVNb2R1bGU6IFwic29ja2V0XCIsXG4gICAgICAgIG9mZnNldDogbm9kZS5sb2NhdGlvbi5zdGFydE9mZnNldCwgc3ltYm9sOiBcIlRDUFNvY2tldFwifSlcbiAgICB9XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLmNvbXBhY3RDaGlsZE5vZGVzKCkpIHZpc2l0KGNoaWxkKVxuICB9XG5cbiAgdmlzaXQobW9kdWxlKVxuICByZXR1cm4gcmVmZXJlbmNlcy5zb3J0KChsZWZ0LCByaWdodCkgPT4gbGVmdC5vZmZzZXQgLSByaWdodC5vZmZzZXQpLm1hcCgoe29mZnNldDogX29mZnNldCwgLi4ucmVmZXJlbmNlfSkgPT4gcmVmZXJlbmNlKVxufVxuXG4vKipcbiAqIFJlcG9ydHMgd2hldGhlciBhIFJ1Ynkgbm9kZSBpcyBvbmUgY2Fub25pY2FsIGxpdGVyYWwgcmVsYXRpdmUgbG9hZCBlZGdlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gQ2FuZGlkYXRlIGNhbGwuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBhIHN1cHBvcnRlZCByZXF1aXJlLXJlbGF0aXZlIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGlzUmVxdWlyZVJlbGF0aXZlKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSAmJiAhbm9kZS5yZWNlaXZlciAmJiAhbm9kZS5ibG9jayAmJiBub2RlLm5hbWUgPT0gXCJyZXF1aXJlX3JlbGF0aXZlXCIgJiZcbiAgICBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoID09IDEgJiYgbm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0gaW5zdGFuY2VvZiBTdHJpbmdOb2RlXG59XG5cbi8qKlxuICogUmVwb3J0cyB3aGV0aGVyIGEgUnVieSBub2RlIGlzIG9uZSBwYXJzZXItcHJvdmVkIGxpdGVyYWwgZmFjYWRlIHJlcXVpcmUgY2FuZGlkYXRlLlxuICogT3RoZXIgbG9hZC1wYXRoIHJlcXVpcmVzIHJldGFpbiB0aGUgVGFzayAwMTAgdW5zdXBwb3J0ZWQgcHJvZmlsZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIENhbmRpZGF0ZSBjYWxsLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIG5vZGUgaXMgYSBsaXRlcmFsIFNlbWFudGlmb2xkIGZhY2FkZSByZXF1aXJlLlxuICovXG5mdW5jdGlvbiBpc1N0ZGxpYlJlcXVpcmUobm9kZSkge1xuICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlICYmICFub2RlLnJlY2VpdmVyICYmICFub2RlLmJsb2NrICYmIG5vZGUubmFtZSA9PSBcInJlcXVpcmVcIiAmJlxuICAgIG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggPT0gMSAmJiBub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSBpbnN0YW5jZW9mIFN0cmluZ05vZGUgJiZcbiAgICAobm9kZS5hcmd1bWVudHNfLmFyZ3VtZW50c19bMF0udW5lc2NhcGVkLnZhbHVlID09IFwic29ja2V0XCIgfHxcbiAgICAgIG5vZGUuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdLnVuZXNjYXBlZC52YWx1ZS5zdGFydHNXaXRoKFwic2VtYW50aWZvbGQvXCIpKVxufVxuXG4vKipcbiAqIFJlcG9ydHMgd2hldGhlciBhIFJ1Ynkgbm9kZSBkeW5hbWljYWxseSBjb25zdHJ1Y3RzIGEgZmFjYWRlIHJlcXVpcmUgaWRlbnRpdHkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBydWJ5L3ByaXNtXCIpLk5vZGV9IG5vZGUgLSBDYW5kaWRhdGUgY2FsbC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBwYXJzZXIgZXhwb3NlcyBhIG5vbmxpdGVyYWwgcmVxdWlyZS5cbiAqL1xuZnVuY3Rpb24gaXNEeW5hbWljU3RkbGliUmVxdWlyZShub2RlKSB7XG4gIGlmICghKG5vZGUgaW5zdGFuY2VvZiBDYWxsTm9kZSkgfHwgbm9kZS5yZWNlaXZlciB8fCBub2RlLmJsb2NrIHx8IG5vZGUubmFtZSAhPSBcInJlcXVpcmVcIiB8fFxuICAgIG5vZGUuYXJndW1lbnRzXz8uYXJndW1lbnRzXy5sZW5ndGggIT0gMSkgcmV0dXJuIGZhbHNlXG4gIHJldHVybiAhKG5vZGUuYXJndW1lbnRzXy5hcmd1bWVudHNfWzBdIGluc3RhbmNlb2YgU3RyaW5nTm9kZSlcbn1cblxuLyoqXG4gKiBSZXBvcnRzIHdoZXRoZXIgYSBSdWJ5IG5vZGUgaXMgdGhlIGNhbm9uaWNhbCBtb2R1bGUtZnVuY3Rpb24gbWFya2VyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAcnVieS9wcmlzbVwiKS5Ob2RlfSBub2RlIC0gQ2FuZGlkYXRlIG1hcmtlci5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBub2RlIGlzIGEgYmFyZSBtb2R1bGUtZnVuY3Rpb24gY2FsbC5cbiAqL1xuZnVuY3Rpb24gaXNNb2R1bGVGdW5jdGlvbk1hcmtlcihub2RlKSB7XG4gIHJldHVybiBub2RlIGluc3RhbmNlb2YgQ2FsbE5vZGUgJiYgIW5vZGUucmVjZWl2ZXIgJiYgIW5vZGUuYmxvY2sgJiYgbm9kZS5uYW1lID09IFwibW9kdWxlX2Z1bmN0aW9uXCIgJiYgIW5vZGUuYXJndW1lbnRzX1xufVxuXG4vKipcbiAqIFJlYWRzIG9uZSBleGFjdCBnZW5lcmF0ZWQgUnVieSB2aXNpYmlsaXR5IG1hcmtlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQHJ1YnkvcHJpc21cIikuTm9kZX0gbm9kZSAtIENhbmRpZGF0ZSBtb2R1bGUtYm9keSBub2RlLlxuICogQHJldHVybnMge3traW5kOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TZW1hbnRpY0RlY2xhcmF0aW9uS2luZCwgbmFtZTogc3RyaW5nfSB8IHVuZGVmaW5lZH0gTWFya2VyIG1lYW5pbmcuXG4gKi9cbmZ1bmN0aW9uIHJ1YnlWaXNpYmlsaXR5TWFya2VyKG5vZGUpIHtcbiAgaWYgKCEobm9kZSBpbnN0YW5jZW9mIENhbGxOb2RlKSB8fCBub2RlLnJlY2VpdmVyIHx8IG5vZGUuYmxvY2sgfHxcbiAgICAhW1wicHJpdmF0ZV9jbGFzc19tZXRob2RcIiwgXCJwcml2YXRlX2NvbnN0YW50XCJdLmluY2x1ZGVzKG5vZGUubmFtZSkgfHxcbiAgICBub2RlLmFyZ3VtZW50c18/LmFyZ3VtZW50c18ubGVuZ3RoICE9IDEgfHwgIShub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXSBpbnN0YW5jZW9mIFN5bWJvbE5vZGUpKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgcmV0dXJuIHtcbiAgICBraW5kOiBub2RlLm5hbWUgPT0gXCJwcml2YXRlX2NsYXNzX21ldGhvZFwiID8gXCJmdW5jdGlvblwiIDogXCJyZWNvcmRcIixcbiAgICBuYW1lOiBub2RlLmFyZ3VtZW50c18uYXJndW1lbnRzX1swXS51bmVzY2FwZWQudmFsdWVcbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkcyBhIHBhcnNlci1vd25lZCBzaW1wbGUgUnVieSBjb25zdGFudCBwYXRoIHdpdGhvdXQgaW5zcGVjdGluZyBzb3VyY2UgdGV4dC5cbiAqIEBwYXJhbSB7Q29uc3RhbnRSZWFkTm9kZSB8IENvbnN0YW50UGF0aE5vZGV9IG5vZGUgLSBDb25zdGFudCBwYXRoLlxuICogQHJldHVybnMge3N0cmluZ30gUXVhbGlmaWVkIGNvbnN0YW50IG5hbWUuXG4gKi9cbmZ1bmN0aW9uIGNvbnN0YW50UGF0aE5hbWUobm9kZSkge1xuICBpZiAobm9kZSBpbnN0YW5jZW9mIENvbnN0YW50UmVhZE5vZGUpIHJldHVybiBub2RlLm5hbWVcbiAgaWYgKHR5cGVvZiBub2RlLm5hbWUgIT0gXCJzdHJpbmdcIikgdGhyb3cgbmV3IEVycm9yKFwiUHJpc20gcmV0dXJuZWQgYSBjb25zdGFudCBwYXRoIHdpdGhvdXQgYSBuYW1lLlwiKVxuICBpZiAoIW5vZGUucGFyZW50KSByZXR1cm4gbm9kZS5uYW1lXG4gIGlmICghKG5vZGUucGFyZW50IGluc3RhbmNlb2YgQ29uc3RhbnRSZWFkTm9kZSkgJiYgIShub2RlLnBhcmVudCBpbnN0YW5jZW9mIENvbnN0YW50UGF0aE5vZGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiUHJpc20gcmV0dXJuZWQgYW4gdW5zdXBwb3J0ZWQgY29uc3RhbnQtcGF0aCBwYXJlbnQuXCIpXG4gIH1cblxuICByZXR1cm4gYCR7Y29uc3RhbnRQYXRoTmFtZShub2RlLnBhcmVudCl9Ojoke25vZGUubmFtZX1gXG59XG4iXX0=
|