semantifold 0.1.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/LICENSE +15 -0
- package/README.md +71 -0
- package/build/index.d.ts +54 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +45 -0
- package/build/src/backends/identifiers.d.ts +19 -0
- package/build/src/backends/identifiers.d.ts.map +1 -0
- package/build/src/backends/identifiers.js +93 -0
- package/build/src/backends/index.d.ts +35 -0
- package/build/src/backends/index.d.ts.map +1 -0
- package/build/src/backends/index.js +149 -0
- package/build/src/backends/java.d.ts +8 -0
- package/build/src/backends/java.d.ts.map +1 -0
- package/build/src/backends/java.js +172 -0
- package/build/src/backends/javascript.d.ts +8 -0
- package/build/src/backends/javascript.d.ts.map +1 -0
- package/build/src/backends/javascript.js +173 -0
- package/build/src/backends/php.d.ts +8 -0
- package/build/src/backends/php.d.ts.map +1 -0
- package/build/src/backends/php.js +175 -0
- package/build/src/backends/ruby.d.ts +8 -0
- package/build/src/backends/ruby.d.ts.map +1 -0
- package/build/src/backends/ruby.js +155 -0
- package/build/src/backends/scalars.d.ts +15 -0
- package/build/src/backends/scalars.d.ts.map +1 -0
- package/build/src/backends/scalars.js +138 -0
- package/build/src/backends/shared.d.ts +26 -0
- package/build/src/backends/shared.d.ts.map +1 -0
- package/build/src/backends/shared.js +424 -0
- package/build/src/backends/typescript.d.ts +8 -0
- package/build/src/backends/typescript.d.ts.map +1 -0
- package/build/src/backends/typescript.js +160 -0
- package/build/src/backends/writer.d.ts +87 -0
- package/build/src/backends/writer.d.ts.map +1 -0
- package/build/src/backends/writer.js +207 -0
- package/build/src/diagnostic.d.ts +67 -0
- package/build/src/diagnostic.d.ts.map +1 -0
- package/build/src/diagnostic.js +96 -0
- package/build/src/frontends/index.d.ts +14 -0
- package/build/src/frontends/index.d.ts.map +1 -0
- package/build/src/frontends/index.js +36 -0
- package/build/src/frontends/java.d.ts +12 -0
- package/build/src/frontends/java.d.ts.map +1 -0
- package/build/src/frontends/java.js +630 -0
- package/build/src/frontends/javascript-typescript.d.ts +19 -0
- package/build/src/frontends/javascript-typescript.d.ts.map +1 -0
- package/build/src/frontends/javascript-typescript.js +633 -0
- package/build/src/frontends/php.d.ts +12 -0
- package/build/src/frontends/php.d.ts.map +1 -0
- package/build/src/frontends/php.js +523 -0
- package/build/src/frontends/ruby.d.ts +12 -0
- package/build/src/frontends/ruby.d.ts.map +1 -0
- package/build/src/frontends/ruby.js +515 -0
- package/build/src/frontends/scalars.d.ts +19 -0
- package/build/src/frontends/scalars.d.ts.map +1 -0
- package/build/src/frontends/scalars.js +71 -0
- package/build/src/mapping.d.ts +160 -0
- package/build/src/mapping.d.ts.map +1 -0
- package/build/src/mapping.js +1120 -0
- package/build/src/semantic/location.d.ts +61 -0
- package/build/src/semantic/location.d.ts.map +1 -0
- package/build/src/semantic/location.js +142 -0
- package/build/src/semantic/operators.d.ts +16 -0
- package/build/src/semantic/operators.d.ts.map +1 -0
- package/build/src/semantic/operators.js +24 -0
- package/build/src/semantic/provenance.d.ts +74 -0
- package/build/src/semantic/provenance.d.ts.map +1 -0
- package/build/src/semantic/provenance.js +577 -0
- package/build/src/semantic/scalars.d.ts +19 -0
- package/build/src/semantic/scalars.d.ts.map +1 -0
- package/build/src/semantic/scalars.js +40 -0
- package/build/src/semantic/types.d.ts +1003 -0
- package/build/src/semantic/types.d.ts.map +1 -0
- package/build/src/semantic/types.js +279 -0
- package/build/src/semantic/validate.d.ts +60 -0
- package/build/src/semantic/validate.d.ts.map +1 -0
- package/build/src/semantic/validate.js +472 -0
- package/docs/architecture.md +39 -0
- package/docs/coding-standards.md +7 -0
- package/docs/goals.md +7 -0
- package/docs/language-support.md +69 -0
- package/docs/plans/2026-09-02-initial-toolchain.md +54 -0
- package/docs/source-maps.md +134 -0
- package/docs/testing.md +25 -0
- package/index.js +63 -0
- package/package.json +69 -0
- package/src/backends/identifiers.js +101 -0
- package/src/backends/index.js +159 -0
- package/src/backends/java.js +182 -0
- package/src/backends/javascript.js +184 -0
- package/src/backends/php.js +184 -0
- package/src/backends/ruby.js +163 -0
- package/src/backends/scalars.js +120 -0
- package/src/backends/shared.js +456 -0
- package/src/backends/typescript.js +168 -0
- package/src/backends/writer.js +224 -0
- package/src/diagnostic.js +103 -0
- package/src/frontends/index.js +36 -0
- package/src/frontends/java.js +735 -0
- package/src/frontends/javascript-typescript.js +718 -0
- package/src/frontends/php.js +593 -0
- package/src/frontends/ruby.js +622 -0
- package/src/frontends/scalars.js +77 -0
- package/src/mapping.js +1260 -0
- package/src/semantic/location.js +154 -0
- package/src/semantic/operators.js +28 -0
- package/src/semantic/provenance.js +629 -0
- package/src/semantic/scalars.js +44 -0
- package/src/semantic/types.js +319 -0
- package/src/semantic/validate.js +529 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { semanticFailure, unsupportedCapability, unsupportedSyntax } from "../diagnostic.js";
|
|
3
|
+
import { hasOnlyUnicodeScalars, isScalarTypeName } from "./scalars.js";
|
|
4
|
+
import { adaptedOperationFor } from "./operators.js";
|
|
5
|
+
/**
|
|
6
|
+
* @typedef Binding
|
|
7
|
+
* @property {boolean} mutable - Whether assignment is allowed.
|
|
8
|
+
* @property {import("./types.js").SemanticTypeName} type - Binding type.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @typedef Scope
|
|
12
|
+
* @property {Map<string, Binding>} bindings - Bindings declared directly in this scope.
|
|
13
|
+
* @property {Set<string>} pending - Names declared later in this scope.
|
|
14
|
+
* @property {Scope | undefined} parent - Enclosing lexical scope.
|
|
15
|
+
* @property {Set<string>} usedNames - All names used by the enclosing function or entry point.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @typedef SemanticFail
|
|
19
|
+
* @type {(code: string, detail: string, location: import("./types.js").SourceLocation) => never}
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Enforces the coherent release-candidate semantic subset after adaptation.
|
|
23
|
+
* @param {import("./types.js").SemanticModule} module - Adapted semantic module.
|
|
24
|
+
* @param {import("./types.js").SemanticLanguage} language - Source language.
|
|
25
|
+
* @returns {import("./types.js").SemanticModule} Validated module.
|
|
26
|
+
*/
|
|
27
|
+
export function validateParsedModule(module, language) {
|
|
28
|
+
validateModuleShape(module, (detail, location) => unsupportedSyntax(language, detail, location));
|
|
29
|
+
validateModuleTypes(module, (code, detail, location) => semanticFailure(language, code, detail, location), true);
|
|
30
|
+
return module;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validates scalar types and bindings for a caller-supplied semantic module before emission.
|
|
34
|
+
* @param {import("./types.js").SemanticModule} module - Semantic module.
|
|
35
|
+
* @param {import("./types.js").SemanticLanguage} language - Backend language.
|
|
36
|
+
* @returns {void}
|
|
37
|
+
*/
|
|
38
|
+
export function validateBackendTypes(module, language) {
|
|
39
|
+
validateModuleTypes(module, (_code, detail, location) => unsupportedCapability(language, detail, location), false);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks parser-authored block and statement layouts before semantic validation.
|
|
43
|
+
* @param {import("./types.js").SemanticModule} module - Semantic module.
|
|
44
|
+
* @param {(detail: string, location: import("./types.js").SourceLocation) => never} fail - Shape failure.
|
|
45
|
+
* @returns {void}
|
|
46
|
+
*/
|
|
47
|
+
function validateModuleShape(module, fail) {
|
|
48
|
+
for (const functionDeclaration of module.functions) {
|
|
49
|
+
if (functionDeclaration.parameters.length != 2) {
|
|
50
|
+
fail("function parameter count other than two", functionDeclaration.location);
|
|
51
|
+
}
|
|
52
|
+
validateBlockShape(functionDeclaration.body, "function body", fail);
|
|
53
|
+
}
|
|
54
|
+
validateBlockShape(module.entryPoint.body, "entry point", fail);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Checks one recursively nested semantic block produced by a frontend.
|
|
58
|
+
* @param {import("./types.js").Block} block - Semantic block.
|
|
59
|
+
* @param {string} detail - Diagnostic detail.
|
|
60
|
+
* @param {(detail: string, location: import("./types.js").SourceLocation) => never} fail - Shape failure.
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
function validateBlockShape(block, detail, fail) {
|
|
64
|
+
if (!block || block.kind != "Block" || !Array.isArray(block.statements)) {
|
|
65
|
+
fail(`${detail} without Block`, block?.location ?? /** @type {never} */ (undefined));
|
|
66
|
+
}
|
|
67
|
+
for (const statement of block.statements) {
|
|
68
|
+
if (!["AssignmentStatement", "IfStatement", "LocalDeclaration", "PrintStatement", "ReturnStatement"].includes(statement.kind)) {
|
|
69
|
+
fail(`${detail} statement ${statement.kind}`, statement.location);
|
|
70
|
+
}
|
|
71
|
+
if (statement.kind == "IfStatement") {
|
|
72
|
+
validateBlockShape(statement.consequent, "if consequent", fail);
|
|
73
|
+
if (statement.alternate)
|
|
74
|
+
validateBlockShape(statement.alternate, "if alternate", fail);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Validates declarations and expression types within lexical scopes.
|
|
80
|
+
* @param {import("./types.js").SemanticModule} module - Semantic module.
|
|
81
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
82
|
+
* @param {boolean} normalizeOperations - Whether to replace transient frontend operation intent.
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
85
|
+
function validateModuleTypes(module, fail, normalizeOperations) {
|
|
86
|
+
/** @type {Map<string, import("./types.js").FunctionDeclaration>} */
|
|
87
|
+
const functions = new Map();
|
|
88
|
+
for (const functionDeclaration of module.functions) {
|
|
89
|
+
if (functions.has(functionDeclaration.name)) {
|
|
90
|
+
fail("DUPLICATE_BINDING", `duplicate function '${functionDeclaration.name}'.`, functionDeclaration.location);
|
|
91
|
+
}
|
|
92
|
+
functions.set(functionDeclaration.name, functionDeclaration);
|
|
93
|
+
}
|
|
94
|
+
for (const functionDeclaration of module.functions)
|
|
95
|
+
validateFunction(functionDeclaration, functions, fail, normalizeOperations);
|
|
96
|
+
const callableNames = new Set(functions.keys());
|
|
97
|
+
const entryScope = createScope(undefined, module.entryPoint.body.statements, callableNames);
|
|
98
|
+
validateBlock(module.entryPoint.body, entryScope, undefined, functions, fail, normalizeOperations);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validates one non-void function and its complete control flow.
|
|
102
|
+
* @param {import("./types.js").FunctionDeclaration} declaration - Function declaration.
|
|
103
|
+
* @param {Map<string, import("./types.js").FunctionDeclaration>} functions - Function signatures.
|
|
104
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
105
|
+
* @param {boolean} normalizeOperations - Whether to replace transient frontend operation intent.
|
|
106
|
+
* @returns {void}
|
|
107
|
+
*/
|
|
108
|
+
function validateFunction(declaration, functions, fail, normalizeOperations) {
|
|
109
|
+
const scope = createScope(undefined, declaration.body.statements, new Set(functions.keys()));
|
|
110
|
+
for (const parameter of declaration.parameters) {
|
|
111
|
+
const type = validateTypeReference(parameter.type, parameter.location, fail);
|
|
112
|
+
declareBinding(parameter.name, { mutable: false, type }, parameter.location, scope, fail);
|
|
113
|
+
}
|
|
114
|
+
const returnType = validateTypeReference(declaration.returnType, declaration.location, fail);
|
|
115
|
+
const returns = validateBlock(declaration.body, scope, returnType, functions, fail, normalizeOperations);
|
|
116
|
+
if (!returns)
|
|
117
|
+
fail("MISSING_RETURN", `Function '${declaration.name}' does not return on every reachable path.`, declaration.location);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validates one ordered block and reports whether every path returns.
|
|
121
|
+
* @param {import("./types.js").Block} block - Semantic block.
|
|
122
|
+
* @param {Scope} scope - Scope belonging to this block.
|
|
123
|
+
* @param {import("./types.js").SemanticTypeName | undefined} returnType - Function return type, absent for entry points.
|
|
124
|
+
* @param {Map<string, import("./types.js").FunctionDeclaration>} functions - Function signatures.
|
|
125
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
126
|
+
* @param {boolean} normalizeOperations - Whether to replace transient frontend operation intent.
|
|
127
|
+
* @returns {boolean} Whether every path through the block returns.
|
|
128
|
+
*/
|
|
129
|
+
function validateBlock(block, scope, returnType, functions, fail, normalizeOperations) {
|
|
130
|
+
let alwaysReturns = false;
|
|
131
|
+
for (const statement of block.statements) {
|
|
132
|
+
if (alwaysReturns)
|
|
133
|
+
fail("UNREACHABLE_STATEMENT", "Statement is unreachable.", statement.location);
|
|
134
|
+
if (statement.kind == "LocalDeclaration") {
|
|
135
|
+
const declaredType = validateTypeReference(statement.type, statement.location, fail);
|
|
136
|
+
const initializerType = inferExpressionType(statement.initializer, scope, functions, fail, normalizeOperations);
|
|
137
|
+
scope.pending.delete(statement.name);
|
|
138
|
+
if (initializerType != declaredType) {
|
|
139
|
+
fail("TYPE_MISMATCH", `Initializer type ${initializerType}; expected ${declaredType}.`, statement.initializer.location);
|
|
140
|
+
}
|
|
141
|
+
declareBinding(statement.name, { mutable: statement.mutable, type: declaredType }, statement.location, scope, fail);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (statement.kind == "AssignmentStatement") {
|
|
145
|
+
const expressionType = inferExpressionType(statement.expression, scope, functions, fail, normalizeOperations);
|
|
146
|
+
const binding = resolveBinding(statement.target.name, statement.target.location, scope, fail);
|
|
147
|
+
if (!binding.mutable) {
|
|
148
|
+
fail("IMMUTABLE_ASSIGNMENT", `Cannot assign to immutable binding '${statement.target.name}'.`, statement.target.location);
|
|
149
|
+
}
|
|
150
|
+
if (expressionType != binding.type) {
|
|
151
|
+
fail("TYPE_MISMATCH", `Assignment type ${expressionType}; expected ${binding.type}.`, statement.expression.location);
|
|
152
|
+
}
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (statement.kind == "PrintStatement") {
|
|
156
|
+
inferExpressionType(statement.expression, scope, functions, fail, normalizeOperations);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (statement.kind == "ReturnStatement") {
|
|
160
|
+
if (!returnType)
|
|
161
|
+
fail("ILLEGAL_RETURN_CONTEXT", "Return statement outside a function.", statement.location);
|
|
162
|
+
const actualType = inferExpressionType(statement.expression, scope, functions, fail, normalizeOperations);
|
|
163
|
+
if (actualType != returnType) {
|
|
164
|
+
fail("TYPE_MISMATCH", `Return type ${actualType}; expected ${returnType}.`, statement.expression.location);
|
|
165
|
+
}
|
|
166
|
+
alwaysReturns = true;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (statement.kind == "IfStatement") {
|
|
170
|
+
const conditionType = inferExpressionType(statement.condition, scope, functions, fail, normalizeOperations);
|
|
171
|
+
if (conditionType != "boolean") {
|
|
172
|
+
fail("NON_BOOLEAN_CONDITION", `If condition type ${conditionType}; expected boolean.`, statement.condition.location);
|
|
173
|
+
}
|
|
174
|
+
const consequentScope = createScope(scope, statement.consequent.statements);
|
|
175
|
+
const consequentReturns = validateBlock(statement.consequent, consequentScope, returnType, functions, fail, normalizeOperations);
|
|
176
|
+
let alternateReturns = false;
|
|
177
|
+
if (statement.alternate) {
|
|
178
|
+
const alternateScope = createScope(scope, statement.alternate.statements);
|
|
179
|
+
alternateReturns = validateBlock(statement.alternate, alternateScope, returnType, functions, fail, normalizeOperations);
|
|
180
|
+
}
|
|
181
|
+
alwaysReturns = consequentReturns && alternateReturns;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const unexpected = /** @type {{kind: string, location: import("./types.js").SourceLocation}} */ (statement);
|
|
185
|
+
fail("UNSUPPORTED_STATEMENT", unexpected.kind, unexpected.location);
|
|
186
|
+
}
|
|
187
|
+
return alwaysReturns;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Creates a lexical scope with declarations marked pending until visited.
|
|
191
|
+
* @param {Scope | undefined} parent - Enclosing scope.
|
|
192
|
+
* @param {{kind: string, name?: string}[]} statements - Scope statements.
|
|
193
|
+
* @param {Set<string>} [reservedNames] - Names unavailable to root bindings.
|
|
194
|
+
* @returns {Scope} Scope.
|
|
195
|
+
*/
|
|
196
|
+
function createScope(parent, statements, reservedNames = new Set()) {
|
|
197
|
+
const pending = new Set(statements.filter((statement) => statement.kind == "LocalDeclaration")
|
|
198
|
+
.map((statement) => /** @type {{name: string}} */ (statement).name));
|
|
199
|
+
return { bindings: new Map(), parent, pending, usedNames: parent?.usedNames ?? new Set(reservedNames) };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Adds one binding while rejecting duplicates and shadowing.
|
|
203
|
+
* @param {string} name - Binding name.
|
|
204
|
+
* @param {Binding} binding - Binding metadata.
|
|
205
|
+
* @param {import("./types.js").SourceLocation} location - Declaration location.
|
|
206
|
+
* @param {Scope} scope - Current scope.
|
|
207
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
208
|
+
* @returns {void}
|
|
209
|
+
*/
|
|
210
|
+
function declareBinding(name, binding, location, scope, fail) {
|
|
211
|
+
if (scope.usedNames.has(name))
|
|
212
|
+
fail("DUPLICATE_BINDING", `Duplicate or shadowed binding '${name}'.`, location);
|
|
213
|
+
scope.bindings.set(name, binding);
|
|
214
|
+
scope.usedNames.add(name);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Resolves one identifier and distinguishes use-before-declaration.
|
|
218
|
+
* @param {string} name - Binding name.
|
|
219
|
+
* @param {import("./types.js").SourceLocation} location - Reference location.
|
|
220
|
+
* @param {Scope} scope - Current scope.
|
|
221
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
222
|
+
* @returns {Binding} Binding.
|
|
223
|
+
*/
|
|
224
|
+
function resolveBinding(name, location, scope, fail) {
|
|
225
|
+
for (let current = /** @type {Scope | undefined} */ (scope); current; current = current.parent) {
|
|
226
|
+
const binding = current.bindings.get(name);
|
|
227
|
+
if (binding)
|
|
228
|
+
return binding;
|
|
229
|
+
if (current.pending.has(name)) {
|
|
230
|
+
return fail("USE_BEFORE_DECLARATION", `Binding '${name}' is used before its declaration.`, location);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return fail("UNRESOLVED_BINDING", `Unknown binding '${name}'.`, location);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Validates one semantic type reference.
|
|
237
|
+
* @param {unknown} type - Candidate semantic type reference.
|
|
238
|
+
* @param {import("./types.js").SourceLocation} location - Owning source location.
|
|
239
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
240
|
+
* @returns {import("./types.js").SemanticTypeName} Validated scalar name.
|
|
241
|
+
*/
|
|
242
|
+
function validateTypeReference(type, location, fail) {
|
|
243
|
+
if (!type || typeof type != "object" || Array.isArray(type)) {
|
|
244
|
+
return fail("TYPE_MISMATCH", "Unsupported scalar type.", location);
|
|
245
|
+
}
|
|
246
|
+
const candidate = /** @type {import("./types.js").TypeReference} */ (type);
|
|
247
|
+
if (candidate.kind != "TypeReference" || !isScalarTypeName(candidate.name)) {
|
|
248
|
+
fail("TYPE_MISMATCH", "Unsupported scalar type.", location);
|
|
249
|
+
}
|
|
250
|
+
return candidate.name;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Infers and validates one expression.
|
|
254
|
+
* @param {import("./types.js").Expression} expression - Semantic expression.
|
|
255
|
+
* @param {Scope} scope - Visible lexical scope.
|
|
256
|
+
* @param {Map<string, import("./types.js").FunctionDeclaration>} functions - Module function signatures.
|
|
257
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
258
|
+
* @param {boolean} normalizeOperations - Whether to replace transient frontend operation intent.
|
|
259
|
+
* @returns {import("./types.js").SemanticTypeName} Expression type.
|
|
260
|
+
*/
|
|
261
|
+
function inferExpressionType(expression, scope, functions, fail, normalizeOperations) {
|
|
262
|
+
if (expression.kind == "IdentifierExpression")
|
|
263
|
+
return resolveBinding(expression.name, expression.location, scope, fail).type;
|
|
264
|
+
if (expression.kind == "IntegerLiteral") {
|
|
265
|
+
if (!Number.isSafeInteger(expression.value))
|
|
266
|
+
fail("TYPE_MISMATCH", "Non-safe integer literal.", expression.location);
|
|
267
|
+
return "integer";
|
|
268
|
+
}
|
|
269
|
+
if (expression.kind == "BooleanLiteral") {
|
|
270
|
+
if (typeof Reflect.get(expression, "value") != "boolean") {
|
|
271
|
+
fail("TYPE_MISMATCH", "Invalid boolean literal value.", expression.location);
|
|
272
|
+
}
|
|
273
|
+
return "boolean";
|
|
274
|
+
}
|
|
275
|
+
if (expression.kind == "StringLiteral") {
|
|
276
|
+
const value = Reflect.get(expression, "value");
|
|
277
|
+
if (typeof value != "string" || !hasOnlyUnicodeScalars(value)) {
|
|
278
|
+
fail("TYPE_MISMATCH", "Invalid Unicode string literal.", expression.location);
|
|
279
|
+
}
|
|
280
|
+
return "string";
|
|
281
|
+
}
|
|
282
|
+
if (expression.kind == "CallExpression") {
|
|
283
|
+
const functionDeclaration = functions.get(expression.callee);
|
|
284
|
+
if (!functionDeclaration)
|
|
285
|
+
return fail("UNRESOLVED_BINDING", `Unknown function '${expression.callee}'.`, expression.location);
|
|
286
|
+
if (expression.arguments.length != functionDeclaration.parameters.length) {
|
|
287
|
+
return fail("TYPE_MISMATCH", `Call argument count for '${expression.callee}'.`, expression.location);
|
|
288
|
+
}
|
|
289
|
+
for (let index = 0; index < expression.arguments.length; index++) {
|
|
290
|
+
const argument = expression.arguments[index];
|
|
291
|
+
const actualType = inferExpressionType(argument, scope, functions, fail, normalizeOperations);
|
|
292
|
+
const expectedType = validateTypeReference(functionDeclaration.parameters[index].type, functionDeclaration.parameters[index].location, fail);
|
|
293
|
+
if (actualType != expectedType) {
|
|
294
|
+
fail("TYPE_MISMATCH", `Call argument type ${actualType}; expected ${expectedType}.`, argument.location);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return validateTypeReference(functionDeclaration.returnType, functionDeclaration.location, fail);
|
|
298
|
+
}
|
|
299
|
+
if (expression.kind == "UnaryExpression") {
|
|
300
|
+
const operandType = inferExpressionType(expression.operand, scope, functions, fail, normalizeOperations);
|
|
301
|
+
const operation = normalizeOperations
|
|
302
|
+
? normalizeUnaryOperation(adaptedOperationFor(expression), operandType, expression.operand.location, fail)
|
|
303
|
+
: expression.operation;
|
|
304
|
+
if (normalizeOperations)
|
|
305
|
+
setNormalizedOperation(expression, operation, unaryOperationSignatures[operation].result);
|
|
306
|
+
const signature = unaryOperationSignatures[operation];
|
|
307
|
+
if (!signature)
|
|
308
|
+
return fail("TYPE_MISMATCH", `Unknown unary operation ${String(operation)}.`, expression.location);
|
|
309
|
+
if (operandType != signature.operand) {
|
|
310
|
+
return fail("INVALID_OPERAND_TYPE", `${operation} requires ${signature.operand}; received ${operandType}.`, expression.operand.location);
|
|
311
|
+
}
|
|
312
|
+
if (expression.type != signature.result) {
|
|
313
|
+
return fail("TYPE_MISMATCH", `${operation} result type ${String(expression.type)}; expected ${signature.result}.`, expression.location);
|
|
314
|
+
}
|
|
315
|
+
return signature.result;
|
|
316
|
+
}
|
|
317
|
+
if (expression.kind == "BinaryExpression") {
|
|
318
|
+
const leftType = inferExpressionType(expression.left, scope, functions, fail, normalizeOperations);
|
|
319
|
+
const rightType = inferExpressionType(expression.right, scope, functions, fail, normalizeOperations);
|
|
320
|
+
const operation = normalizeOperations
|
|
321
|
+
? normalizeBinaryOperation(adaptedOperationFor(expression), leftType, rightType, expression.left.location, expression.right.location, expression.location, fail)
|
|
322
|
+
: expression.operation;
|
|
323
|
+
if (normalizeOperations)
|
|
324
|
+
setNormalizedOperation(expression, operation, binaryOperationSignatures[operation].result);
|
|
325
|
+
const signature = binaryOperationSignatures[operation];
|
|
326
|
+
if (!signature)
|
|
327
|
+
return fail("TYPE_MISMATCH", `Unknown binary operation ${String(operation)}.`, expression.location);
|
|
328
|
+
if (leftType != signature.left) {
|
|
329
|
+
return fail("INVALID_OPERAND_TYPE", `${operation} requires ${signature.left} left operand; received ${leftType}.`, expression.left.location);
|
|
330
|
+
}
|
|
331
|
+
if (rightType != signature.right) {
|
|
332
|
+
return fail("INVALID_OPERAND_TYPE", `${operation} requires ${signature.right} right operand; received ${rightType}.`, expression.right.location);
|
|
333
|
+
}
|
|
334
|
+
if (expression.type != signature.result) {
|
|
335
|
+
return fail("TYPE_MISMATCH", `${operation} result type ${String(expression.type)}; expected ${signature.result}.`, expression.location);
|
|
336
|
+
}
|
|
337
|
+
return signature.result;
|
|
338
|
+
}
|
|
339
|
+
const unexpected = /** @type {{kind: string, location: import("./types.js").SourceLocation}} */ (expression);
|
|
340
|
+
return fail("TYPE_MISMATCH", unexpected.kind, unexpected.location);
|
|
341
|
+
}
|
|
342
|
+
/** @type {Readonly<Record<import("./types.js").SemanticUnaryOperation, {operand: import("./types.js").SemanticTypeName, result: import("./types.js").SemanticTypeName}>>} */
|
|
343
|
+
const unaryOperationSignatures = Object.freeze({
|
|
344
|
+
BooleanNot: Object.freeze({ operand: "boolean", result: "boolean" }),
|
|
345
|
+
IntegerNegate: Object.freeze({ operand: "integer", result: "integer" })
|
|
346
|
+
});
|
|
347
|
+
/** @type {Readonly<Record<import("./types.js").SemanticBinaryOperation, {left: import("./types.js").SemanticTypeName, right: import("./types.js").SemanticTypeName, result: import("./types.js").SemanticTypeName}>>} */
|
|
348
|
+
const binaryOperationSignatures = Object.freeze({
|
|
349
|
+
BooleanAnd: Object.freeze({ left: "boolean", result: "boolean", right: "boolean" }),
|
|
350
|
+
BooleanEqual: Object.freeze({ left: "boolean", result: "boolean", right: "boolean" }),
|
|
351
|
+
BooleanNotEqual: Object.freeze({ left: "boolean", result: "boolean", right: "boolean" }),
|
|
352
|
+
BooleanOr: Object.freeze({ left: "boolean", result: "boolean", right: "boolean" }),
|
|
353
|
+
IntegerAdd: Object.freeze({ left: "integer", result: "integer", right: "integer" }),
|
|
354
|
+
IntegerEqual: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
355
|
+
IntegerGreaterThan: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
356
|
+
IntegerGreaterThanOrEqual: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
357
|
+
IntegerLessThan: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
358
|
+
IntegerLessThanOrEqual: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
359
|
+
IntegerMultiply: Object.freeze({ left: "integer", result: "integer", right: "integer" }),
|
|
360
|
+
IntegerNotEqual: Object.freeze({ left: "integer", result: "boolean", right: "integer" }),
|
|
361
|
+
IntegerSubtract: Object.freeze({ left: "integer", result: "integer", right: "integer" }),
|
|
362
|
+
StringConcat: Object.freeze({ left: "string", result: "string", right: "string" }),
|
|
363
|
+
StringEqual: Object.freeze({ left: "string", result: "boolean", right: "string" }),
|
|
364
|
+
StringNotEqual: Object.freeze({ left: "string", result: "boolean", right: "string" })
|
|
365
|
+
});
|
|
366
|
+
/**
|
|
367
|
+
* Selects one typed unary meaning from parser-normalized source intent.
|
|
368
|
+
* @param {unknown} sourceOperation - Transient frontend operation.
|
|
369
|
+
* @param {import("./types.js").SemanticTypeName} operandType - Resolved operand type.
|
|
370
|
+
* @param {import("./types.js").SourceLocation} location - Operand location.
|
|
371
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
372
|
+
* @returns {import("./types.js").SemanticUnaryOperation} Semantic operation.
|
|
373
|
+
*/
|
|
374
|
+
function normalizeUnaryOperation(sourceOperation, operandType, location, fail) {
|
|
375
|
+
if (sourceOperation == "Negate") {
|
|
376
|
+
if (operandType != "integer")
|
|
377
|
+
fail("INVALID_OPERAND_TYPE", `Integer negation requires integer; received ${operandType}.`, location);
|
|
378
|
+
return "IntegerNegate";
|
|
379
|
+
}
|
|
380
|
+
if (sourceOperation == "Not") {
|
|
381
|
+
if (operandType != "boolean")
|
|
382
|
+
fail("INVALID_OPERAND_TYPE", `Boolean not requires boolean; received ${operandType}.`, location);
|
|
383
|
+
return "BooleanNot";
|
|
384
|
+
}
|
|
385
|
+
return fail("TYPE_MISMATCH", `Unknown unary source operation ${String(sourceOperation)}.`, location);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Selects one typed binary meaning from parser-normalized source intent.
|
|
389
|
+
* @param {unknown} sourceOperation - Transient frontend operation.
|
|
390
|
+
* @param {import("./types.js").SemanticTypeName} leftType - Resolved left type.
|
|
391
|
+
* @param {import("./types.js").SemanticTypeName} rightType - Resolved right type.
|
|
392
|
+
* @param {import("./types.js").SourceLocation} leftLocation - Left operand location.
|
|
393
|
+
* @param {import("./types.js").SourceLocation} rightLocation - Right operand location.
|
|
394
|
+
* @param {import("./types.js").SourceLocation} expressionLocation - Whole operation location.
|
|
395
|
+
* @param {SemanticFail} fail - Diagnostic callback.
|
|
396
|
+
* @returns {import("./types.js").SemanticBinaryOperation} Semantic operation.
|
|
397
|
+
*/
|
|
398
|
+
function normalizeBinaryOperation(sourceOperation, leftType, rightType, leftLocation, rightLocation, expressionLocation, fail) {
|
|
399
|
+
if (sourceOperation == "PhpAdd") {
|
|
400
|
+
if (leftType == "string" && rightType == "string") {
|
|
401
|
+
return fail("UNSUPPORTED_SYNTAX", "PHP binary + does not concatenate strings; use . instead.", expressionLocation);
|
|
402
|
+
}
|
|
403
|
+
sourceOperation = "Add";
|
|
404
|
+
}
|
|
405
|
+
if (sourceOperation == "StringConcat") {
|
|
406
|
+
if (leftType != "string")
|
|
407
|
+
fail("INVALID_OPERAND_TYPE", `String concatenation requires string; received ${leftType}.`, leftLocation);
|
|
408
|
+
if (rightType != "string")
|
|
409
|
+
fail("INVALID_OPERAND_TYPE", `String concatenation requires string; received ${rightType}.`, rightLocation);
|
|
410
|
+
return "StringConcat";
|
|
411
|
+
}
|
|
412
|
+
if (sourceOperation == "Add") {
|
|
413
|
+
if (leftType == "integer" && rightType == "integer")
|
|
414
|
+
return "IntegerAdd";
|
|
415
|
+
if (leftType == "string" && rightType == "string")
|
|
416
|
+
return "StringConcat";
|
|
417
|
+
const location = leftType == "integer" || leftType == "string" ? rightLocation : leftLocation;
|
|
418
|
+
return fail("INVALID_OPERAND_TYPE", `Addition requires two integers or two strings; received ${leftType} and ${rightType}.`, location);
|
|
419
|
+
}
|
|
420
|
+
const fixedOperations = /** @type {const} */ ({
|
|
421
|
+
And: ["boolean", "BooleanAnd"],
|
|
422
|
+
GreaterThan: ["integer", "IntegerGreaterThan"],
|
|
423
|
+
GreaterThanOrEqual: ["integer", "IntegerGreaterThanOrEqual"],
|
|
424
|
+
LessThan: ["integer", "IntegerLessThan"],
|
|
425
|
+
LessThanOrEqual: ["integer", "IntegerLessThanOrEqual"],
|
|
426
|
+
Multiply: ["integer", "IntegerMultiply"],
|
|
427
|
+
Or: ["boolean", "BooleanOr"],
|
|
428
|
+
Subtract: ["integer", "IntegerSubtract"]
|
|
429
|
+
});
|
|
430
|
+
const fixed = Reflect.get(fixedOperations, String(sourceOperation));
|
|
431
|
+
if (fixed) {
|
|
432
|
+
const [requiredType, operation] = fixed;
|
|
433
|
+
if (leftType != requiredType)
|
|
434
|
+
fail("INVALID_OPERAND_TYPE", `${String(sourceOperation)} requires ${requiredType}; received ${leftType}.`, leftLocation);
|
|
435
|
+
if (rightType != requiredType)
|
|
436
|
+
fail("INVALID_OPERAND_TYPE", `${String(sourceOperation)} requires ${requiredType}; received ${rightType}.`, rightLocation);
|
|
437
|
+
return /** @type {import("./types.js").SemanticBinaryOperation} */ (operation);
|
|
438
|
+
}
|
|
439
|
+
if (sourceOperation == "JavaEqual" || sourceOperation == "JavaNotEqual") {
|
|
440
|
+
if (leftType == "string" || rightType == "string") {
|
|
441
|
+
return fail("UNSUPPORTED_SYNTAX", "Java reference equality is outside the implemented semantic subset.", expressionLocation);
|
|
442
|
+
}
|
|
443
|
+
sourceOperation = sourceOperation == "JavaEqual" ? "Equal" : "NotEqual";
|
|
444
|
+
}
|
|
445
|
+
if (sourceOperation == "StringEqual" || sourceOperation == "StringNotEqual") {
|
|
446
|
+
if (leftType != "string")
|
|
447
|
+
fail("INVALID_OPERAND_TYPE", `String equality requires string; received ${leftType}.`, leftLocation);
|
|
448
|
+
if (rightType != "string")
|
|
449
|
+
fail("INVALID_OPERAND_TYPE", `String equality requires string; received ${rightType}.`, rightLocation);
|
|
450
|
+
return /** @type {"StringEqual" | "StringNotEqual"} */ (sourceOperation);
|
|
451
|
+
}
|
|
452
|
+
if (sourceOperation == "Equal" || sourceOperation == "NotEqual") {
|
|
453
|
+
if (leftType != rightType) {
|
|
454
|
+
return fail("MISMATCHED_EQUALITY_TYPES", `Equality requires matching scalar types; received ${leftType} and ${rightType}.`, rightLocation);
|
|
455
|
+
}
|
|
456
|
+
const prefix = leftType == "integer" ? "Integer" : leftType == "boolean" ? "Boolean" : "String";
|
|
457
|
+
return /** @type {import("./types.js").SemanticBinaryOperation} */ (`${prefix}${sourceOperation}`);
|
|
458
|
+
}
|
|
459
|
+
return fail("TYPE_MISMATCH", `Unknown binary source operation ${String(sourceOperation)}.`, leftLocation);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Replaces transient frontend intent with the public typed operation fields.
|
|
463
|
+
* @param {object} expression - Mutable adapted expression.
|
|
464
|
+
* @param {import("./types.js").SemanticUnaryOperation | import("./types.js").SemanticBinaryOperation} operation - Typed operation.
|
|
465
|
+
* @param {import("./types.js").SemanticTypeName} type - Explicit result type.
|
|
466
|
+
* @returns {void}
|
|
467
|
+
*/
|
|
468
|
+
function setNormalizedOperation(expression, operation, type) {
|
|
469
|
+
Reflect.set(expression, "operation", operation);
|
|
470
|
+
Reflect.set(expression, "type", type);
|
|
471
|
+
}
|
|
472
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VtYW50aWMvdmFsaWRhdGUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxlQUFlLEVBQUUscUJBQXFCLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQTtBQUMxRixPQUFPLEVBQUMscUJBQXFCLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDcEUsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sZ0JBQWdCLENBQUE7QUFFbEQ7Ozs7R0FJRztBQUVIOzs7Ozs7R0FNRztBQUVIOzs7R0FHRztBQUVIOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxRQUFRO0lBQ25ELG1CQUFtQixDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQTtJQUNoRyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFBO0lBRWhILE9BQU8sTUFBTSxDQUFBO0FBQ2YsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxRQUFRO0lBQ25ELG1CQUFtQixDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQ3BILENBQUM7QUFFRDs7Ozs7R0FLRztB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RyxFQUFFLFlBQVksQ0FBQyxDQUFBO0FBQzNHLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLHNCQUFzQixDQUFDLFVBQVUsRUFBRSxTQUFTLEVBQUUsSUFBSTtJQUN6RCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUE7SUFDL0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQ3ZDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtzZW1hbnRpY0ZhaWx1cmUsIHVuc3VwcG9ydGVkQ2FwYWJpbGl0eSwgdW5zdXBwb3J0ZWRTeW50YXh9IGZyb20gXCIuLi9kaWFnbm9zdGljLmpzXCJcbmltcG9ydCB7aGFzT25seVVuaWNvZGVTY2FsYXJzLCBpc1NjYWxhclR5cGVOYW1lfSBmcm9tIFwiLi9zY2FsYXJzLmpzXCJcbmltcG9ydCB7YWRhcHRlZE9wZXJhdGlvbkZvcn0gZnJvbSBcIi4vb3BlcmF0b3JzLmpzXCJcblxuLyoqXG4gKiBAdHlwZWRlZiBCaW5kaW5nXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IG11dGFibGUgLSBXaGV0aGVyIGFzc2lnbm1lbnQgaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVOYW1lfSB0eXBlIC0gQmluZGluZyB0eXBlLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYgU2NvcGVcbiAqIEBwcm9wZXJ0eSB7TWFwPHN0cmluZywgQmluZGluZz59IGJpbmRpbmdzIC0gQmluZGluZ3MgZGVjbGFyZWQgZGlyZWN0bHkgaW4gdGhpcyBzY29wZS5cbiAqIEBwcm9wZXJ0eSB7U2V0PHN0cmluZz59IHBlbmRpbmcgLSBOYW1lcyBkZWNsYXJlZCBsYXRlciBpbiB0aGlzIHNjb3BlLlxuICogQHByb3BlcnR5IHtTY29wZSB8IHVuZGVmaW5lZH0gcGFyZW50IC0gRW5jbG9zaW5nIGxleGljYWwgc2NvcGUuXG4gKiBAcHJvcGVydHkge1NldDxzdHJpbmc+fSB1c2VkTmFtZXMgLSBBbGwgbmFtZXMgdXNlZCBieSB0aGUgZW5jbG9zaW5nIGZ1bmN0aW9uIG9yIGVudHJ5IHBvaW50LlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYgU2VtYW50aWNGYWlsXG4gKiBAdHlwZSB7KGNvZGU6IHN0cmluZywgZGV0YWlsOiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uKSA9PiBuZXZlcn1cbiAqL1xuXG4vKipcbiAqIEVuZm9yY2VzIHRoZSBjb2hlcmVudCByZWxlYXNlLWNhbmRpZGF0ZSBzZW1hbnRpYyBzdWJzZXQgYWZ0ZXIgYWRhcHRhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gQWRhcHRlZCBzZW1hbnRpYyBtb2R1bGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNMYW5ndWFnZX0gbGFuZ3VhZ2UgLSBTb3VyY2UgbGFuZ3VhZ2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gVmFsaWRhdGVkIG1vZHVsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUGFyc2VkTW9kdWxlKG1vZHVsZSwgbGFuZ3VhZ2UpIHtcbiAgdmFsaWRhdGVNb2R1bGVTaGFwZShtb2R1bGUsIChkZXRhaWwsIGxvY2F0aW9uKSA9PiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgZGV0YWlsLCBsb2NhdGlvbikpXG4gIHZhbGlkYXRlTW9kdWxlVHlwZXMobW9kdWxlLCAoY29kZSwgZGV0YWlsLCBsb2NhdGlvbikgPT4gc2VtYW50aWNGYWlsdXJlKGxhbmd1YWdlLCBjb2RlLCBkZXRhaWwsIGxvY2F0aW9uKSwgdHJ1ZSlcblxuICByZXR1cm4gbW9kdWxlXG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHNjYWxhciB0eXBlcyBhbmQgYmluZGluZ3MgZm9yIGEgY2FsbGVyLXN1cHBsaWVkIHNlbWFudGljIG1vZHVsZSBiZWZvcmUgZW1pc3Npb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY0xhbmd1YWdlfSBsYW5ndWFnZSAtIEJhY2tlbmQgbGFuZ3VhZ2UuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQmFja2VuZFR5cGVzKG1vZHVsZSwgbGFuZ3VhZ2UpIHtcbiAgdmFsaWRhdGVNb2R1bGVUeXBlcyhtb2R1bGUsIChfY29kZSwgZGV0YWlsLCBsb2NhdGlvbikgPT4gdW5zdXBwb3J0ZWRDYXBhYmlsaXR5KGxhbmd1YWdlLCBkZXRhaWwsIGxvY2F0aW9uKSwgZmFsc2UpXG59XG5cbi8qKlxuICogQ2hlY2tzIHBhcnNlci1hdXRob3JlZCBibG9jayBhbmQgc3RhdGVtZW50IGxheW91dHMgYmVmb3JlIHNlbWFudGljIHZhbGlkYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFNlbWFudGljIG1vZHVsZS5cbiAqIEBwYXJhbSB7KGRldGFpbDogc3RyaW5nLCBsb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbikgPT4gbmV2ZXJ9IGZhaWwgLSBTaGFwZSBmYWlsdXJlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlTW9kdWxlU2hhcGUobW9kdWxlLCBmYWlsKSB7XG4gIGZvciAoY29uc3QgZnVuY3Rpb25EZWNsYXJhdGlvbiBvZiBtb2R1bGUuZnVuY3Rpb25zKSB7XG4gICAgaWYgKGZ1bmN0aW9uRGVjbGFyYXRpb24ucGFyYW1ldGVycy5sZW5ndGggIT0gMikge1xuICAgICAgZmFpbChcImZ1bmN0aW9uIHBhcmFtZXRlciBjb3VudCBvdGhlciB0aGFuIHR3b1wiLCBmdW5jdGlvbkRlY2xhcmF0aW9uLmxvY2F0aW9uKVxuICAgIH1cblxuICAgIHZhbGlkYXRlQmxvY2tTaGFwZShmdW5jdGlvbkRlY2xhcmF0aW9uLmJvZHksIFwiZnVuY3Rpb24gYm9keVwiLCBmYWlsKVxuICB9XG5cbiAgdmFsaWRhdGVCbG9ja1NoYXBlKG1vZHVsZS5lbnRyeVBvaW50LmJvZHksIFwiZW50cnkgcG9pbnRcIiwgZmFpbClcbn1cblxuLyoqXG4gKiBDaGVja3Mgb25lIHJlY3Vyc2l2ZWx5IG5lc3RlZCBzZW1hbnRpYyBibG9jayBwcm9kdWNlZCBieSBhIGZyb250ZW5kLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJsb2NrfSBibG9jayAtIFNlbWFudGljIGJsb2NrLlxuICogQHBhcmFtIHtzdHJpbmd9IGRldGFpbCAtIERpYWdub3N0aWMgZGV0YWlsLlxuICogQHBhcmFtIHsoZGV0YWlsOiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uKSA9PiBuZXZlcn0gZmFpbCAtIFNoYXBlIGZhaWx1cmUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVCbG9ja1NoYXBlKGJsb2NrLCBkZXRhaWwsIGZhaWwpIHtcbiAgaWYgKCFibG9jayB8fCBibG9jay5raW5kICE9IFwiQmxvY2tcIiB8fCAhQXJyYXkuaXNBcnJheShibG9jay5zdGF0ZW1lbnRzKSkge1xuICAgIGZhaWwoYCR7ZGV0YWlsfSB3aXRob3V0IEJsb2NrYCwgYmxvY2s/LmxvY2F0aW9uID8/IC8qKiBAdHlwZSB7bmV2ZXJ9ICovICh1bmRlZmluZWQpKVxuICB9XG5cbiAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgYmxvY2suc3RhdGVtZW50cykge1xuICAgIGlmICghW1wiQXNzaWdubWVudFN0YXRlbWVudFwiLCBcIklmU3RhdGVtZW50XCIsIFwiTG9jYWxEZWNsYXJhdGlvblwiLCBcIlByaW50U3RhdGVtZW50XCIsIFwiUmV0dXJuU3RhdGVtZW50XCJdLmluY2x1ZGVzKHN0YXRlbWVudC5raW5kKSkge1xuICAgICAgZmFpbChgJHtkZXRhaWx9IHN0YXRlbWVudCAke3N0YXRlbWVudC5raW5kfWAsIHN0YXRlbWVudC5sb2NhdGlvbilcbiAgICB9XG4gICAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiSWZTdGF0ZW1lbnRcIikge1xuICAgICAgdmFsaWRhdGVCbG9ja1NoYXBlKHN0YXRlbWVudC5jb25zZXF1ZW50LCBcImlmIGNvbnNlcXVlbnRcIiwgZmFpbClcbiAgICAgIGlmIChzdGF0ZW1lbnQuYWx0ZXJuYXRlKSB2YWxpZGF0ZUJsb2NrU2hhcGUoc3RhdGVtZW50LmFsdGVybmF0ZSwgXCJpZiBhbHRlcm5hdGVcIiwgZmFpbClcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgZGVjbGFyYXRpb25zIGFuZCBleHByZXNzaW9uIHR5cGVzIHdpdGhpbiBsZXhpY2FsIHNjb3Blcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gU2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtTZW1hbnRpY0ZhaWx9IGZhaWwgLSBEaWFnbm9zdGljIGNhbGxiYWNrLlxuICogQHBhcmFtIHtib29sZWFufSBub3JtYWxpemVPcGVyYXRpb25zIC0gV2hldGhlciB0byByZXBsYWNlIHRyYW5zaWVudCBmcm9udGVuZCBvcGVyYXRpb24gaW50ZW50LlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlTW9kdWxlVHlwZXMobW9kdWxlLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKSB7XG4gIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uPn0gKi9cbiAgY29uc3QgZnVuY3Rpb25zID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBmdW5jdGlvbkRlY2xhcmF0aW9uIG9mIG1vZHVsZS5mdW5jdGlvbnMpIHtcbiAgICBpZiAoZnVuY3Rpb25zLmhhcyhmdW5jdGlvbkRlY2xhcmF0aW9uLm5hbWUpKSB7XG4gICAgICBmYWlsKFwiRFVQTElDQVRFX0JJTkRJTkdcIiwgYGR1cGxpY2F0ZSBmdW5jdGlvbiAnJHtmdW5jdGlvbkRlY2xhcmF0aW9uLm5hbWV9Jy5gLCBmdW5jdGlvbkRlY2xhcmF0aW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICBmdW5jdGlvbnMuc2V0KGZ1bmN0aW9uRGVjbGFyYXRpb24ubmFtZSwgZnVuY3Rpb25EZWNsYXJhdGlvbilcbiAgfVxuXG4gIGZvciAoY29uc3QgZnVuY3Rpb25EZWNsYXJhdGlvbiBvZiBtb2R1bGUuZnVuY3Rpb25zKSB2YWxpZGF0ZUZ1bmN0aW9uKGZ1bmN0aW9uRGVjbGFyYXRpb24sIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplT3BlcmF0aW9ucylcblxuICBjb25zdCBjYWxsYWJsZU5hbWVzID0gbmV3IFNldChmdW5jdGlvbnMua2V5cygpKVxuXG4gIGNvbnN0IGVudHJ5U2NvcGUgPSBjcmVhdGVTY29wZSh1bmRlZmluZWQsIG1vZHVsZS5lbnRyeVBvaW50LmJvZHkuc3RhdGVtZW50cywgY2FsbGFibGVOYW1lcylcblxuICB2YWxpZGF0ZUJsb2NrKG1vZHVsZS5lbnRyeVBvaW50LmJvZHksIGVudHJ5U2NvcGUsIHVuZGVmaW5lZCwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBvbmUgbm9uLXZvaWQgZnVuY3Rpb24gYW5kIGl0cyBjb21wbGV0ZSBjb250cm9sIGZsb3cuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbn0gZGVjbGFyYXRpb24gLSBGdW5jdGlvbiBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uPn0gZnVuY3Rpb25zIC0gRnVuY3Rpb24gc2lnbmF0dXJlcy5cbiAqIEBwYXJhbSB7U2VtYW50aWNGYWlsfSBmYWlsIC0gRGlhZ25vc3RpYyBjYWxsYmFjay5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gbm9ybWFsaXplT3BlcmF0aW9ucyAtIFdoZXRoZXIgdG8gcmVwbGFjZSB0cmFuc2llbnQgZnJvbnRlbmQgb3BlcmF0aW9uIGludGVudC5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUZ1bmN0aW9uKGRlY2xhcmF0aW9uLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpIHtcbiAgY29uc3Qgc2NvcGUgPSBjcmVhdGVTY29wZSh1bmRlZmluZWQsIGRlY2xhcmF0aW9uLmJvZHkuc3RhdGVtZW50cywgbmV3IFNldChmdW5jdGlvbnMua2V5cygpKSlcblxuICBmb3IgKGNvbnN0IHBhcmFtZXRlciBvZiBkZWNsYXJhdGlvbi5wYXJhbWV0ZXJzKSB7XG4gICAgY29uc3QgdHlwZSA9IHZhbGlkYXRlVHlwZVJlZmVyZW5jZShwYXJhbWV0ZXIudHlwZSwgcGFyYW1ldGVyLmxvY2F0aW9uLCBmYWlsKVxuXG4gICAgZGVjbGFyZUJpbmRpbmcocGFyYW1ldGVyLm5hbWUsIHttdXRhYmxlOiBmYWxzZSwgdHlwZX0sIHBhcmFtZXRlci5sb2NhdGlvbiwgc2NvcGUsIGZhaWwpXG4gIH1cblxuICBjb25zdCByZXR1cm5UeXBlID0gdmFsaWRhdGVUeXBlUmVmZXJlbmNlKGRlY2xhcmF0aW9uLnJldHVyblR5cGUsIGRlY2xhcmF0aW9uLmxvY2F0aW9uLCBmYWlsKVxuICBjb25zdCByZXR1cm5zID0gdmFsaWRhdGVCbG9jayhkZWNsYXJhdGlvbi5ib2R5LCBzY29wZSwgcmV0dXJuVHlwZSwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxuXG4gIGlmICghcmV0dXJucykgZmFpbChcIk1JU1NJTkdfUkVUVVJOXCIsIGBGdW5jdGlvbiAnJHtkZWNsYXJhdGlvbi5uYW1lfScgZG9lcyBub3QgcmV0dXJuIG9uIGV2ZXJ5IHJlYWNoYWJsZSBwYXRoLmAsIGRlY2xhcmF0aW9uLmxvY2F0aW9uKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBvbmUgb3JkZXJlZCBibG9jayBhbmQgcmVwb3J0cyB3aGV0aGVyIGV2ZXJ5IHBhdGggcmV0dXJucy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CbG9ja30gYmxvY2sgLSBTZW1hbnRpYyBibG9jay5cbiAqIEBwYXJhbSB7U2NvcGV9IHNjb3BlIC0gU2NvcGUgYmVsb25naW5nIHRvIHRoaXMgYmxvY2suXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZSB8IHVuZGVmaW5lZH0gcmV0dXJuVHlwZSAtIEZ1bmN0aW9uIHJldHVybiB0eXBlLCBhYnNlbnQgZm9yIGVudHJ5IHBvaW50cy5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uPn0gZnVuY3Rpb25zIC0gRnVuY3Rpb24gc2lnbmF0dXJlcy5cbiAqIEBwYXJhbSB7U2VtYW50aWNGYWlsfSBmYWlsIC0gRGlhZ25vc3RpYyBjYWxsYmFjay5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gbm9ybWFsaXplT3BlcmF0aW9ucyAtIFdoZXRoZXIgdG8gcmVwbGFjZSB0cmFuc2llbnQgZnJvbnRlbmQgb3BlcmF0aW9uIGludGVudC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIGV2ZXJ5IHBhdGggdGhyb3VnaCB0aGUgYmxvY2sgcmV0dXJucy5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVCbG9jayhibG9jaywgc2NvcGUsIHJldHVyblR5cGUsIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplT3BlcmF0aW9ucykge1xuICBsZXQgYWx3YXlzUmV0dXJucyA9IGZhbHNlXG5cbiAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgYmxvY2suc3RhdGVtZW50cykge1xuICAgIGlmIChhbHdheXNSZXR1cm5zKSBmYWlsKFwiVU5SRUFDSEFCTEVfU1RBVEVNRU5UXCIsIFwiU3RhdGVtZW50IGlzIHVucmVhY2hhYmxlLlwiLCBzdGF0ZW1lbnQubG9jYXRpb24pXG5cbiAgICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpIHtcbiAgICAgIGNvbnN0IGRlY2xhcmVkVHlwZSA9IHZhbGlkYXRlVHlwZVJlZmVyZW5jZShzdGF0ZW1lbnQudHlwZSwgc3RhdGVtZW50LmxvY2F0aW9uLCBmYWlsKVxuICAgICAgY29uc3QgaW5pdGlhbGl6ZXJUeXBlID0gaW5mZXJFeHByZXNzaW9uVHlwZShzdGF0ZW1lbnQuaW5pdGlhbGl6ZXIsIHNjb3BlLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpXG5cbiAgICAgIHNjb3BlLnBlbmRpbmcuZGVsZXRlKHN0YXRlbWVudC5uYW1lKVxuICAgICAgaWYgKGluaXRpYWxpemVyVHlwZSAhPSBkZWNsYXJlZFR5cGUpIHtcbiAgICAgICAgZmFpbChcIlRZUEVfTUlTTUFUQ0hcIiwgYEluaXRpYWxpemVyIHR5cGUgJHtpbml0aWFsaXplclR5cGV9OyBleHBlY3RlZCAke2RlY2xhcmVkVHlwZX0uYCwgc3RhdGVtZW50LmluaXRpYWxpemVyLmxvY2F0aW9uKVxuICAgICAgfVxuICAgICAgZGVjbGFyZUJpbmRpbmcoc3RhdGVtZW50Lm5hbWUsIHttdXRhYmxlOiBzdGF0ZW1lbnQubXV0YWJsZSwgdHlwZTogZGVjbGFyZWRUeXBlfSwgc3RhdGVtZW50LmxvY2F0aW9uLCBzY29wZSwgZmFpbClcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGlmIChzdGF0ZW1lbnQua2luZCA9PSBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIikge1xuICAgICAgY29uc3QgZXhwcmVzc2lvblR5cGUgPSBpbmZlckV4cHJlc3Npb25UeXBlKHN0YXRlbWVudC5leHByZXNzaW9uLCBzY29wZSwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxuICAgICAgY29uc3QgYmluZGluZyA9IHJlc29sdmVCaW5kaW5nKHN0YXRlbWVudC50YXJnZXQubmFtZSwgc3RhdGVtZW50LnRhcmdldC5sb2NhdGlvbiwgc2NvcGUsIGZhaWwpXG5cbiAgICAgIGlmICghYmluZGluZy5tdXRhYmxlKSB7XG4gICAgICAgIGZhaWwoXCJJTU1VVEFCTEVfQVNTSUdOTUVOVFwiLCBgQ2Fubm90IGFzc2lnbiB0byBpbW11dGFibGUgYmluZGluZyAnJHtzdGF0ZW1lbnQudGFyZ2V0Lm5hbWV9Jy5gLCBzdGF0ZW1lbnQudGFyZ2V0LmxvY2F0aW9uKVxuICAgICAgfVxuICAgICAgaWYgKGV4cHJlc3Npb25UeXBlICE9IGJpbmRpbmcudHlwZSkge1xuICAgICAgICBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgQXNzaWdubWVudCB0eXBlICR7ZXhwcmVzc2lvblR5cGV9OyBleHBlY3RlZCAke2JpbmRpbmcudHlwZX0uYCwgc3RhdGVtZW50LmV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSB7XG4gICAgICBpbmZlckV4cHJlc3Npb25UeXBlKHN0YXRlbWVudC5leHByZXNzaW9uLCBzY29wZSwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiUmV0dXJuU3RhdGVtZW50XCIpIHtcbiAgICAgIGlmICghcmV0dXJuVHlwZSkgZmFpbChcIklMTEVHQUxfUkVUVVJOX0NPTlRFWFRcIiwgXCJSZXR1cm4gc3RhdGVtZW50IG91dHNpZGUgYSBmdW5jdGlvbi5cIiwgc3RhdGVtZW50LmxvY2F0aW9uKVxuICAgICAgY29uc3QgYWN0dWFsVHlwZSA9IGluZmVyRXhwcmVzc2lvblR5cGUoc3RhdGVtZW50LmV4cHJlc3Npb24sIHNjb3BlLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpXG5cbiAgICAgIGlmIChhY3R1YWxUeXBlICE9IHJldHVyblR5cGUpIHtcbiAgICAgICAgZmFpbChcIlRZUEVfTUlTTUFUQ0hcIiwgYFJldHVybiB0eXBlICR7YWN0dWFsVHlwZX07IGV4cGVjdGVkICR7cmV0dXJuVHlwZX0uYCwgc3RhdGVtZW50LmV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgICB9XG4gICAgICBhbHdheXNSZXR1cm5zID0gdHJ1ZVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgaWYgKHN0YXRlbWVudC5raW5kID09IFwiSWZTdGF0ZW1lbnRcIikge1xuICAgICAgY29uc3QgY29uZGl0aW9uVHlwZSA9IGluZmVyRXhwcmVzc2lvblR5cGUoc3RhdGVtZW50LmNvbmRpdGlvbiwgc2NvcGUsIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplT3BlcmF0aW9ucylcblxuICAgICAgaWYgKGNvbmRpdGlvblR5cGUgIT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgZmFpbChcIk5PTl9CT09MRUFOX0NPTkRJVElPTlwiLCBgSWYgY29uZGl0aW9uIHR5cGUgJHtjb25kaXRpb25UeXBlfTsgZXhwZWN0ZWQgYm9vbGVhbi5gLCBzdGF0ZW1lbnQuY29uZGl0aW9uLmxvY2F0aW9uKVxuICAgICAgfVxuICAgICAgY29uc3QgY29uc2VxdWVudFNjb3BlID0gY3JlYXRlU2NvcGUoc2NvcGUsIHN0YXRlbWVudC5jb25zZXF1ZW50LnN0YXRlbWVudHMpXG4gICAgICBjb25zdCBjb25zZXF1ZW50UmV0dXJucyA9IHZhbGlkYXRlQmxvY2soc3RhdGVtZW50LmNvbnNlcXVlbnQsIGNvbnNlcXVlbnRTY29wZSwgcmV0dXJuVHlwZSwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxuICAgICAgbGV0IGFsdGVybmF0ZVJldHVybnMgPSBmYWxzZVxuXG4gICAgICBpZiAoc3RhdGVtZW50LmFsdGVybmF0ZSkge1xuICAgICAgICBjb25zdCBhbHRlcm5hdGVTY29wZSA9IGNyZWF0ZVNjb3BlKHNjb3BlLCBzdGF0ZW1lbnQuYWx0ZXJuYXRlLnN0YXRlbWVudHMpXG5cbiAgICAgICAgYWx0ZXJuYXRlUmV0dXJucyA9IHZhbGlkYXRlQmxvY2soc3RhdGVtZW50LmFsdGVybmF0ZSwgYWx0ZXJuYXRlU2NvcGUsIHJldHVyblR5cGUsIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplT3BlcmF0aW9ucylcbiAgICAgIH1cbiAgICAgIGFsd2F5c1JldHVybnMgPSBjb25zZXF1ZW50UmV0dXJucyAmJiBhbHRlcm5hdGVSZXR1cm5zXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGNvbnN0IHVuZXhwZWN0ZWQgPSAvKiogQHR5cGUge3traW5kOiBzdHJpbmcsIGxvY2F0aW9uOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufX0gKi8gKHN0YXRlbWVudClcblxuICAgIGZhaWwoXCJVTlNVUFBPUlRFRF9TVEFURU1FTlRcIiwgdW5leHBlY3RlZC5raW5kLCB1bmV4cGVjdGVkLmxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIGFsd2F5c1JldHVybnNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbGV4aWNhbCBzY29wZSB3aXRoIGRlY2xhcmF0aW9ucyBtYXJrZWQgcGVuZGluZyB1bnRpbCB2aXNpdGVkLlxuICogQHBhcmFtIHtTY29wZSB8IHVuZGVmaW5lZH0gcGFyZW50IC0gRW5jbG9zaW5nIHNjb3BlLlxuICogQHBhcmFtIHt7a2luZDogc3RyaW5nLCBuYW1lPzogc3RyaW5nfVtdfSBzdGF0ZW1lbnRzIC0gU2NvcGUgc3RhdGVtZW50cy5cbiAqIEBwYXJhbSB7U2V0PHN0cmluZz59IFtyZXNlcnZlZE5hbWVzXSAtIE5hbWVzIHVuYXZhaWxhYmxlIHRvIHJvb3QgYmluZGluZ3MuXG4gKiBAcmV0dXJucyB7U2NvcGV9IFNjb3BlLlxuICovXG5mdW5jdGlvbiBjcmVhdGVTY29wZShwYXJlbnQsIHN0YXRlbWVudHMsIHJlc2VydmVkTmFtZXMgPSBuZXcgU2V0KCkpIHtcbiAgY29uc3QgcGVuZGluZyA9IG5ldyBTZXQoc3RhdGVtZW50cy5maWx0ZXIoKHN0YXRlbWVudCkgPT4gc3RhdGVtZW50LmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpXG4gICAgLm1hcCgoc3RhdGVtZW50KSA9PiAvKiogQHR5cGUge3tuYW1lOiBzdHJpbmd9fSAqLyAoc3RhdGVtZW50KS5uYW1lKSlcblxuICByZXR1cm4ge2JpbmRpbmdzOiBuZXcgTWFwKCksIHBhcmVudCwgcGVuZGluZywgdXNlZE5hbWVzOiBwYXJlbnQ/LnVzZWROYW1lcyA/PyBuZXcgU2V0KHJlc2VydmVkTmFtZXMpfVxufVxuXG4vKipcbiAqIEFkZHMgb25lIGJpbmRpbmcgd2hpbGUgcmVqZWN0aW5nIGR1cGxpY2F0ZXMgYW5kIHNoYWRvd2luZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gQmluZGluZyBuYW1lLlxuICogQHBhcmFtIHtCaW5kaW5nfSBiaW5kaW5nIC0gQmluZGluZyBtZXRhZGF0YS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBEZWNsYXJhdGlvbiBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7U2NvcGV9IHNjb3BlIC0gQ3VycmVudCBzY29wZS5cbiAqIEBwYXJhbSB7U2VtYW50aWNGYWlsfSBmYWlsIC0gRGlhZ25vc3RpYyBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBkZWNsYXJlQmluZGluZyhuYW1lLCBiaW5kaW5nLCBsb2NhdGlvbiwgc2NvcGUsIGZhaWwpIHtcbiAgaWYgKHNjb3BlLnVzZWROYW1lcy5oYXMobmFtZSkpIGZhaWwoXCJEVVBMSUNBVEVfQklORElOR1wiLCBgRHVwbGljYXRlIG9yIHNoYWRvd2VkIGJpbmRpbmcgJyR7bmFtZX0nLmAsIGxvY2F0aW9uKVxuXG4gIHNjb3BlLmJpbmRpbmdzLnNldChuYW1lLCBiaW5kaW5nKVxuICBzY29wZS51c2VkTmFtZXMuYWRkKG5hbWUpXG59XG5cbi8qKlxuICogUmVzb2x2ZXMgb25lIGlkZW50aWZpZXIgYW5kIGRpc3Rpbmd1aXNoZXMgdXNlLWJlZm9yZS1kZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gQmluZGluZyBuYW1lLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBsb2NhdGlvbiAtIFJlZmVyZW5jZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7U2NvcGV9IHNjb3BlIC0gQ3VycmVudCBzY29wZS5cbiAqIEBwYXJhbSB7U2VtYW50aWNGYWlsfSBmYWlsIC0gRGlhZ25vc3RpYyBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHtCaW5kaW5nfSBCaW5kaW5nLlxuICovXG5mdW5jdGlvbiByZXNvbHZlQmluZGluZyhuYW1lLCBsb2NhdGlvbiwgc2NvcGUsIGZhaWwpIHtcbiAgZm9yIChsZXQgY3VycmVudCA9IC8qKiBAdHlwZSB7U2NvcGUgfCB1bmRlZmluZWR9ICovIChzY29wZSk7IGN1cnJlbnQ7IGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudCkge1xuICAgIGNvbnN0IGJpbmRpbmcgPSBjdXJyZW50LmJpbmRpbmdzLmdldChuYW1lKVxuXG4gICAgaWYgKGJpbmRpbmcpIHJldHVybiBiaW5kaW5nXG4gICAgaWYgKGN1cnJlbnQucGVuZGluZy5oYXMobmFtZSkpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiVVNFX0JFRk9SRV9ERUNMQVJBVElPTlwiLCBgQmluZGluZyAnJHtuYW1lfScgaXMgdXNlZCBiZWZvcmUgaXRzIGRlY2xhcmF0aW9uLmAsIGxvY2F0aW9uKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWlsKFwiVU5SRVNPTFZFRF9CSU5ESU5HXCIsIGBVbmtub3duIGJpbmRpbmcgJyR7bmFtZX0nLmAsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBvbmUgc2VtYW50aWMgdHlwZSByZWZlcmVuY2UuXG4gKiBAcGFyYW0ge3Vua25vd259IHR5cGUgLSBDYW5kaWRhdGUgc2VtYW50aWMgdHlwZSByZWZlcmVuY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gT3duaW5nIHNvdXJjZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7U2VtYW50aWNGYWlsfSBmYWlsIC0gRGlhZ25vc3RpYyBjYWxsYmFjay5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZU5hbWV9IFZhbGlkYXRlZCBzY2FsYXIgbmFtZS5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVUeXBlUmVmZXJlbmNlKHR5cGUsIGxvY2F0aW9uLCBmYWlsKSB7XG4gIGlmICghdHlwZSB8fCB0eXBlb2YgdHlwZSAhPSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkodHlwZSkpIHtcbiAgICByZXR1cm4gZmFpbChcIlRZUEVfTUlTTUFUQ0hcIiwgXCJVbnN1cHBvcnRlZCBzY2FsYXIgdHlwZS5cIiwgbG9jYXRpb24pXG4gIH1cblxuICBjb25zdCBjYW5kaWRhdGUgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuVHlwZVJlZmVyZW5jZX0gKi8gKHR5cGUpXG5cbiAgaWYgKGNhbmRpZGF0ZS5raW5kICE9IFwiVHlwZVJlZmVyZW5jZVwiIHx8ICFpc1NjYWxhclR5cGVOYW1lKGNhbmRpZGF0ZS5uYW1lKSkge1xuICAgIGZhaWwoXCJUWVBFX01JU01BVENIXCIsIFwiVW5zdXBwb3J0ZWQgc2NhbGFyIHR5cGUuXCIsIGxvY2F0aW9uKVxuICB9XG5cbiAgcmV0dXJuIGNhbmRpZGF0ZS5uYW1lXG59XG5cbi8qKlxuICogSW5mZXJzIGFuZCB2YWxpZGF0ZXMgb25lIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gZXhwcmVzc2lvbiAtIFNlbWFudGljIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge1Njb3BlfSBzY29wZSAtIFZpc2libGUgbGV4aWNhbCBzY29wZS5cbiAqIEBwYXJhbSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9uPn0gZnVuY3Rpb25zIC0gTW9kdWxlIGZ1bmN0aW9uIHNpZ25hdHVyZXMuXG4gKiBAcGFyYW0ge1NlbWFudGljRmFpbH0gZmFpbCAtIERpYWdub3N0aWMgY2FsbGJhY2suXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG5vcm1hbGl6ZU9wZXJhdGlvbnMgLSBXaGV0aGVyIHRvIHJlcGxhY2UgdHJhbnNpZW50IGZyb250ZW5kIG9wZXJhdGlvbiBpbnRlbnQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVOYW1lfSBFeHByZXNzaW9uIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGluZmVyRXhwcmVzc2lvblR5cGUoZXhwcmVzc2lvbiwgc2NvcGUsIGZ1bmN0aW9ucywgZmFpbCwgbm9ybWFsaXplT3BlcmF0aW9ucykge1xuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiSWRlbnRpZmllckV4cHJlc3Npb25cIikgcmV0dXJuIHJlc29sdmVCaW5kaW5nKGV4cHJlc3Npb24ubmFtZSwgZXhwcmVzc2lvbi5sb2NhdGlvbiwgc2NvcGUsIGZhaWwpLnR5cGVcblxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiSW50ZWdlckxpdGVyYWxcIikge1xuICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIoZXhwcmVzc2lvbi52YWx1ZSkpIGZhaWwoXCJUWVBFX01JU01BVENIXCIsIFwiTm9uLXNhZmUgaW50ZWdlciBsaXRlcmFsLlwiLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgIHJldHVybiBcImludGVnZXJcIlxuICB9XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJCb29sZWFuTGl0ZXJhbFwiKSB7XG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0LmdldChleHByZXNzaW9uLCBcInZhbHVlXCIpICE9IFwiYm9vbGVhblwiKSB7XG4gICAgICBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBcIkludmFsaWQgYm9vbGVhbiBsaXRlcmFsIHZhbHVlLlwiLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICByZXR1cm4gXCJib29sZWFuXCJcbiAgfVxuICBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiU3RyaW5nTGl0ZXJhbFwiKSB7XG4gICAgY29uc3QgdmFsdWUgPSBSZWZsZWN0LmdldChleHByZXNzaW9uLCBcInZhbHVlXCIpXG5cbiAgICBpZiAodHlwZW9mIHZhbHVlICE9IFwic3RyaW5nXCIgfHwgIWhhc09ubHlVbmljb2RlU2NhbGFycyh2YWx1ZSkpIHtcbiAgICAgIGZhaWwoXCJUWVBFX01JU01BVENIXCIsIFwiSW52YWxpZCBVbmljb2RlIHN0cmluZyBsaXRlcmFsLlwiLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICByZXR1cm4gXCJzdHJpbmdcIlxuICB9XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgZnVuY3Rpb25EZWNsYXJhdGlvbiA9IGZ1bmN0aW9ucy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpXG5cbiAgICBpZiAoIWZ1bmN0aW9uRGVjbGFyYXRpb24pIHJldHVybiBmYWlsKFwiVU5SRVNPTFZFRF9CSU5ESU5HXCIsIGBVbmtub3duIGZ1bmN0aW9uICcke2V4cHJlc3Npb24uY2FsbGVlfScuYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICBpZiAoZXhwcmVzc2lvbi5hcmd1bWVudHMubGVuZ3RoICE9IGZ1bmN0aW9uRGVjbGFyYXRpb24ucGFyYW1ldGVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgQ2FsbCBhcmd1bWVudCBjb3VudCBmb3IgJyR7ZXhwcmVzc2lvbi5jYWxsZWV9Jy5gLCBleHByZXNzaW9uLmxvY2F0aW9uKVxuICAgIH1cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZXhwcmVzc2lvbi5hcmd1bWVudHMubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICBjb25zdCBhcmd1bWVudCA9IGV4cHJlc3Npb24uYXJndW1lbnRzW2luZGV4XVxuICAgICAgY29uc3QgYWN0dWFsVHlwZSA9IGluZmVyRXhwcmVzc2lvblR5cGUoYXJndW1lbnQsIHNjb3BlLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpXG4gICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSB2YWxpZGF0ZVR5cGVSZWZlcmVuY2UoZnVuY3Rpb25EZWNsYXJhdGlvbi5wYXJhbWV0ZXJzW2luZGV4XS50eXBlLCBmdW5jdGlvbkRlY2xhcmF0aW9uLnBhcmFtZXRlcnNbaW5kZXhdLmxvY2F0aW9uLCBmYWlsKVxuXG4gICAgICBpZiAoYWN0dWFsVHlwZSAhPSBleHBlY3RlZFR5cGUpIHtcbiAgICAgICAgZmFpbChcIlRZUEVfTUlTTUFUQ0hcIiwgYENhbGwgYXJndW1lbnQgdHlwZSAke2FjdHVhbFR5cGV9OyBleHBlY3RlZCAke2V4cGVjdGVkVHlwZX0uYCwgYXJndW1lbnQubG9jYXRpb24pXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2YWxpZGF0ZVR5cGVSZWZlcmVuY2UoZnVuY3Rpb25EZWNsYXJhdGlvbi5yZXR1cm5UeXBlLCBmdW5jdGlvbkRlY2xhcmF0aW9uLmxvY2F0aW9uLCBmYWlsKVxuICB9XG4gIGlmIChleHByZXNzaW9uLmtpbmQgPT0gXCJVbmFyeUV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IG9wZXJhbmRUeXBlID0gaW5mZXJFeHByZXNzaW9uVHlwZShleHByZXNzaW9uLm9wZXJhbmQsIHNjb3BlLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpXG4gICAgY29uc3Qgb3BlcmF0aW9uID0gbm9ybWFsaXplT3BlcmF0aW9uc1xuICAgICAgPyBub3JtYWxpemVVbmFyeU9wZXJhdGlvbihhZGFwdGVkT3BlcmF0aW9uRm9yKGV4cHJlc3Npb24pLCBvcGVyYW5kVHlwZSwgZXhwcmVzc2lvbi5vcGVyYW5kLmxvY2F0aW9uLCBmYWlsKVxuICAgICAgOiBleHByZXNzaW9uLm9wZXJhdGlvblxuXG4gICAgaWYgKG5vcm1hbGl6ZU9wZXJhdGlvbnMpIHNldE5vcm1hbGl6ZWRPcGVyYXRpb24oZXhwcmVzc2lvbiwgb3BlcmF0aW9uLCB1bmFyeU9wZXJhdGlvblNpZ25hdHVyZXNbb3BlcmF0aW9uXS5yZXN1bHQpXG5cbiAgICBjb25zdCBzaWduYXR1cmUgPSB1bmFyeU9wZXJhdGlvblNpZ25hdHVyZXNbb3BlcmF0aW9uXVxuXG4gICAgaWYgKCFzaWduYXR1cmUpIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgVW5rbm93biB1bmFyeSBvcGVyYXRpb24gJHtTdHJpbmcob3BlcmF0aW9uKX0uYCwgZXhwcmVzc2lvbi5sb2NhdGlvbilcbiAgICBpZiAob3BlcmFuZFR5cGUgIT0gc2lnbmF0dXJlLm9wZXJhbmQpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiSU5WQUxJRF9PUEVSQU5EX1RZUEVcIiwgYCR7b3BlcmF0aW9ufSByZXF1aXJlcyAke3NpZ25hdHVyZS5vcGVyYW5kfTsgcmVjZWl2ZWQgJHtvcGVyYW5kVHlwZX0uYCwgZXhwcmVzc2lvbi5vcGVyYW5kLmxvY2F0aW9uKVxuICAgIH1cbiAgICBpZiAoZXhwcmVzc2lvbi50eXBlICE9IHNpZ25hdHVyZS5yZXN1bHQpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgJHtvcGVyYXRpb259IHJlc3VsdCB0eXBlICR7U3RyaW5nKGV4cHJlc3Npb24udHlwZSl9OyBleHBlY3RlZCAke3NpZ25hdHVyZS5yZXN1bHR9LmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgfVxuICAgIHJldHVybiBzaWduYXR1cmUucmVzdWx0XG4gIH1cbiAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGxlZnRUeXBlID0gaW5mZXJFeHByZXNzaW9uVHlwZShleHByZXNzaW9uLmxlZnQsIHNjb3BlLCBmdW5jdGlvbnMsIGZhaWwsIG5vcm1hbGl6ZU9wZXJhdGlvbnMpXG4gICAgY29uc3QgcmlnaHRUeXBlID0gaW5mZXJFeHByZXNzaW9uVHlwZShleHByZXNzaW9uLnJpZ2h0LCBzY29wZSwgZnVuY3Rpb25zLCBmYWlsLCBub3JtYWxpemVPcGVyYXRpb25zKVxuICAgIGNvbnN0IG9wZXJhdGlvbiA9IG5vcm1hbGl6ZU9wZXJhdGlvbnNcbiAgICAgID8gbm9ybWFsaXplQmluYXJ5T3BlcmF0aW9uKGFkYXB0ZWRPcGVyYXRpb25Gb3IoZXhwcmVzc2lvbiksIGxlZnRUeXBlLCByaWdodFR5cGUsIGV4cHJlc3Npb24ubGVmdC5sb2NhdGlvbiwgZXhwcmVzc2lvbi5yaWdodC5sb2NhdGlvbiwgZXhwcmVzc2lvbi5sb2NhdGlvbiwgZmFpbClcbiAgICAgIDogZXhwcmVzc2lvbi5vcGVyYXRpb25cblxuICAgIGlmIChub3JtYWxpemVPcGVyYXRpb25zKSBzZXROb3JtYWxpemVkT3BlcmF0aW9uKGV4cHJlc3Npb24sIG9wZXJhdGlvbiwgYmluYXJ5T3BlcmF0aW9uU2lnbmF0dXJlc1tvcGVyYXRpb25dLnJlc3VsdClcblxuICAgIGNvbnN0IHNpZ25hdHVyZSA9IGJpbmFyeU9wZXJhdGlvblNpZ25hdHVyZXNbb3BlcmF0aW9uXVxuXG4gICAgaWYgKCFzaWduYXR1cmUpIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgVW5rbm93biBiaW5hcnkgb3BlcmF0aW9uICR7U3RyaW5nKG9wZXJhdGlvbil9LmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgaWYgKGxlZnRUeXBlICE9IHNpZ25hdHVyZS5sZWZ0KSB7XG4gICAgICByZXR1cm4gZmFpbChcIklOVkFMSURfT1BFUkFORF9UWVBFXCIsIGAke29wZXJhdGlvbn0gcmVxdWlyZXMgJHtzaWduYXR1cmUubGVmdH0gbGVmdCBvcGVyYW5kOyByZWNlaXZlZCAke2xlZnRUeXBlfS5gLCBleHByZXNzaW9uLmxlZnQubG9jYXRpb24pXG4gICAgfVxuICAgIGlmIChyaWdodFR5cGUgIT0gc2lnbmF0dXJlLnJpZ2h0KSB7XG4gICAgICByZXR1cm4gZmFpbChcIklOVkFMSURfT1BFUkFORF9UWVBFXCIsIGAke29wZXJhdGlvbn0gcmVxdWlyZXMgJHtzaWduYXR1cmUucmlnaHR9IHJpZ2h0IG9wZXJhbmQ7IHJlY2VpdmVkICR7cmlnaHRUeXBlfS5gLCBleHByZXNzaW9uLnJpZ2h0LmxvY2F0aW9uKVxuICAgIH1cbiAgICBpZiAoZXhwcmVzc2lvbi50eXBlICE9IHNpZ25hdHVyZS5yZXN1bHQpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgJHtvcGVyYXRpb259IHJlc3VsdCB0eXBlICR7U3RyaW5nKGV4cHJlc3Npb24udHlwZSl9OyBleHBlY3RlZCAke3NpZ25hdHVyZS5yZXN1bHR9LmAsIGV4cHJlc3Npb24ubG9jYXRpb24pXG4gICAgfVxuICAgIHJldHVybiBzaWduYXR1cmUucmVzdWx0XG4gIH1cblxuICBjb25zdCB1bmV4cGVjdGVkID0gLyoqIEB0eXBlIHt7a2luZDogc3RyaW5nLCBsb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn19ICovIChleHByZXNzaW9uKVxuXG4gIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCB1bmV4cGVjdGVkLmtpbmQsIHVuZXhwZWN0ZWQubG9jYXRpb24pXG59XG5cbi8qKiBAdHlwZSB7UmVhZG9ubHk8UmVjb3JkPGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNVbmFyeU9wZXJhdGlvbiwge29wZXJhbmQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZSwgcmVzdWx0OiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZU5hbWV9Pj59ICovXG5jb25zdCB1bmFyeU9wZXJhdGlvblNpZ25hdHVyZXMgPSBPYmplY3QuZnJlZXplKHtcbiAgQm9vbGVhbk5vdDogT2JqZWN0LmZyZWV6ZSh7b3BlcmFuZDogXCJib29sZWFuXCIsIHJlc3VsdDogXCJib29sZWFuXCJ9KSxcbiAgSW50ZWdlck5lZ2F0ZTogT2JqZWN0LmZyZWV6ZSh7b3BlcmFuZDogXCJpbnRlZ2VyXCIsIHJlc3VsdDogXCJpbnRlZ2VyXCJ9KVxufSlcblxuLyoqIEB0eXBlIHtSZWFkb25seTxSZWNvcmQ8aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY0JpbmFyeU9wZXJhdGlvbiwge2xlZnQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZSwgcmlnaHQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZSwgcmVzdWx0OiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljVHlwZU5hbWV9Pj59ICovXG5jb25zdCBiaW5hcnlPcGVyYXRpb25TaWduYXR1cmVzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIEJvb2xlYW5BbmQ6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiYm9vbGVhblwiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJib29sZWFuXCJ9KSxcbiAgQm9vbGVhbkVxdWFsOiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcImJvb2xlYW5cIiwgcmVzdWx0OiBcImJvb2xlYW5cIiwgcmlnaHQ6IFwiYm9vbGVhblwifSksXG4gIEJvb2xlYW5Ob3RFcXVhbDogT2JqZWN0LmZyZWV6ZSh7bGVmdDogXCJib29sZWFuXCIsIHJlc3VsdDogXCJib29sZWFuXCIsIHJpZ2h0OiBcImJvb2xlYW5cIn0pLFxuICBCb29sZWFuT3I6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiYm9vbGVhblwiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJib29sZWFuXCJ9KSxcbiAgSW50ZWdlckFkZDogT2JqZWN0LmZyZWV6ZSh7bGVmdDogXCJpbnRlZ2VyXCIsIHJlc3VsdDogXCJpbnRlZ2VyXCIsIHJpZ2h0OiBcImludGVnZXJcIn0pLFxuICBJbnRlZ2VyRXF1YWw6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiaW50ZWdlclwiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJpbnRlZ2VyXCJ9KSxcbiAgSW50ZWdlckdyZWF0ZXJUaGFuOiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcImludGVnZXJcIiwgcmVzdWx0OiBcImJvb2xlYW5cIiwgcmlnaHQ6IFwiaW50ZWdlclwifSksXG4gIEludGVnZXJHcmVhdGVyVGhhbk9yRXF1YWw6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiaW50ZWdlclwiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJpbnRlZ2VyXCJ9KSxcbiAgSW50ZWdlckxlc3NUaGFuOiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcImludGVnZXJcIiwgcmVzdWx0OiBcImJvb2xlYW5cIiwgcmlnaHQ6IFwiaW50ZWdlclwifSksXG4gIEludGVnZXJMZXNzVGhhbk9yRXF1YWw6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiaW50ZWdlclwiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJpbnRlZ2VyXCJ9KSxcbiAgSW50ZWdlck11bHRpcGx5OiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcImludGVnZXJcIiwgcmVzdWx0OiBcImludGVnZXJcIiwgcmlnaHQ6IFwiaW50ZWdlclwifSksXG4gIEludGVnZXJOb3RFcXVhbDogT2JqZWN0LmZyZWV6ZSh7bGVmdDogXCJpbnRlZ2VyXCIsIHJlc3VsdDogXCJib29sZWFuXCIsIHJpZ2h0OiBcImludGVnZXJcIn0pLFxuICBJbnRlZ2VyU3VidHJhY3Q6IE9iamVjdC5mcmVlemUoe2xlZnQ6IFwiaW50ZWdlclwiLCByZXN1bHQ6IFwiaW50ZWdlclwiLCByaWdodDogXCJpbnRlZ2VyXCJ9KSxcbiAgU3RyaW5nQ29uY2F0OiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcInN0cmluZ1wiLCByZXN1bHQ6IFwic3RyaW5nXCIsIHJpZ2h0OiBcInN0cmluZ1wifSksXG4gIFN0cmluZ0VxdWFsOiBPYmplY3QuZnJlZXplKHtsZWZ0OiBcInN0cmluZ1wiLCByZXN1bHQ6IFwiYm9vbGVhblwiLCByaWdodDogXCJzdHJpbmdcIn0pLFxuICBTdHJpbmdOb3RFcXVhbDogT2JqZWN0LmZyZWV6ZSh7bGVmdDogXCJzdHJpbmdcIiwgcmVzdWx0OiBcImJvb2xlYW5cIiwgcmlnaHQ6IFwic3RyaW5nXCJ9KVxufSlcblxuLyoqXG4gKiBTZWxlY3RzIG9uZSB0eXBlZCB1bmFyeSBtZWFuaW5nIGZyb20gcGFyc2VyLW5vcm1hbGl6ZWQgc291cmNlIGludGVudC5cbiAqIEBwYXJhbSB7dW5rbm93bn0gc291cmNlT3BlcmF0aW9uIC0gVHJhbnNpZW50IGZyb250ZW5kIG9wZXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVOYW1lfSBvcGVyYW5kVHlwZSAtIFJlc29sdmVkIG9wZXJhbmQgdHlwZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBPcGVyYW5kIGxvY2F0aW9uLlxuICogQHBhcmFtIHtTZW1hbnRpY0ZhaWx9IGZhaWwgLSBEaWFnbm9zdGljIGNhbGxiYWNrLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNVbmFyeU9wZXJhdGlvbn0gU2VtYW50aWMgb3BlcmF0aW9uLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVVbmFyeU9wZXJhdGlvbihzb3VyY2VPcGVyYXRpb24sIG9wZXJhbmRUeXBlLCBsb2NhdGlvbiwgZmFpbCkge1xuICBpZiAoc291cmNlT3BlcmF0aW9uID09IFwiTmVnYXRlXCIpIHtcbiAgICBpZiAob3BlcmFuZFR5cGUgIT0gXCJpbnRlZ2VyXCIpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgSW50ZWdlciBuZWdhdGlvbiByZXF1aXJlcyBpbnRlZ2VyOyByZWNlaXZlZCAke29wZXJhbmRUeXBlfS5gLCBsb2NhdGlvbilcbiAgICByZXR1cm4gXCJJbnRlZ2VyTmVnYXRlXCJcbiAgfVxuICBpZiAoc291cmNlT3BlcmF0aW9uID09IFwiTm90XCIpIHtcbiAgICBpZiAob3BlcmFuZFR5cGUgIT0gXCJib29sZWFuXCIpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgQm9vbGVhbiBub3QgcmVxdWlyZXMgYm9vbGVhbjsgcmVjZWl2ZWQgJHtvcGVyYW5kVHlwZX0uYCwgbG9jYXRpb24pXG4gICAgcmV0dXJuIFwiQm9vbGVhbk5vdFwiXG4gIH1cblxuICByZXR1cm4gZmFpbChcIlRZUEVfTUlTTUFUQ0hcIiwgYFVua25vd24gdW5hcnkgc291cmNlIG9wZXJhdGlvbiAke1N0cmluZyhzb3VyY2VPcGVyYXRpb24pfS5gLCBsb2NhdGlvbilcbn1cblxuLyoqXG4gKiBTZWxlY3RzIG9uZSB0eXBlZCBiaW5hcnkgbWVhbmluZyBmcm9tIHBhcnNlci1ub3JtYWxpemVkIHNvdXJjZSBpbnRlbnQuXG4gKiBAcGFyYW0ge3Vua25vd259IHNvdXJjZU9wZXJhdGlvbiAtIFRyYW5zaWVudCBmcm9udGVuZCBvcGVyYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZX0gbGVmdFR5cGUgLSBSZXNvbHZlZCBsZWZ0IHR5cGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNUeXBlTmFtZX0gcmlnaHRUeXBlIC0gUmVzb2x2ZWQgcmlnaHQgdHlwZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbGVmdExvY2F0aW9uIC0gTGVmdCBvcGVyYW5kIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSByaWdodExvY2F0aW9uIC0gUmlnaHQgb3BlcmFuZCBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gZXhwcmVzc2lvbkxvY2F0aW9uIC0gV2hvbGUgb3BlcmF0aW9uIGxvY2F0aW9uLlxuICogQHBhcmFtIHtTZW1hbnRpY0ZhaWx9IGZhaWwgLSBEaWFnbm9zdGljIGNhbGxiYWNrLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNCaW5hcnlPcGVyYXRpb259IFNlbWFudGljIG9wZXJhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQmluYXJ5T3BlcmF0aW9uKHNvdXJjZU9wZXJhdGlvbiwgbGVmdFR5cGUsIHJpZ2h0VHlwZSwgbGVmdExvY2F0aW9uLCByaWdodExvY2F0aW9uLCBleHByZXNzaW9uTG9jYXRpb24sIGZhaWwpIHtcbiAgaWYgKHNvdXJjZU9wZXJhdGlvbiA9PSBcIlBocEFkZFwiKSB7XG4gICAgaWYgKGxlZnRUeXBlID09IFwic3RyaW5nXCIgJiYgcmlnaHRUeXBlID09IFwic3RyaW5nXCIpIHtcbiAgICAgIHJldHVybiBmYWlsKFwiVU5TVVBQT1JURURfU1lOVEFYXCIsIFwiUEhQIGJpbmFyeSArIGRvZXMgbm90IGNvbmNhdGVuYXRlIHN0cmluZ3M7IHVzZSAuIGluc3RlYWQuXCIsIGV4cHJlc3Npb25Mb2NhdGlvbilcbiAgICB9XG5cbiAgICBzb3VyY2VPcGVyYXRpb24gPSBcIkFkZFwiXG4gIH1cblxuICBpZiAoc291cmNlT3BlcmF0aW9uID09IFwiU3RyaW5nQ29uY2F0XCIpIHtcbiAgICBpZiAobGVmdFR5cGUgIT0gXCJzdHJpbmdcIikgZmFpbChcIklOVkFMSURfT1BFUkFORF9UWVBFXCIsIGBTdHJpbmcgY29uY2F0ZW5hdGlvbiByZXF1aXJlcyBzdHJpbmc7IHJlY2VpdmVkICR7bGVmdFR5cGV9LmAsIGxlZnRMb2NhdGlvbilcbiAgICBpZiAocmlnaHRUeXBlICE9IFwic3RyaW5nXCIpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgU3RyaW5nIGNvbmNhdGVuYXRpb24gcmVxdWlyZXMgc3RyaW5nOyByZWNlaXZlZCAke3JpZ2h0VHlwZX0uYCwgcmlnaHRMb2NhdGlvbilcbiAgICByZXR1cm4gXCJTdHJpbmdDb25jYXRcIlxuICB9XG5cbiAgaWYgKHNvdXJjZU9wZXJhdGlvbiA9PSBcIkFkZFwiKSB7XG4gICAgaWYgKGxlZnRUeXBlID09IFwiaW50ZWdlclwiICYmIHJpZ2h0VHlwZSA9PSBcImludGVnZXJcIikgcmV0dXJuIFwiSW50ZWdlckFkZFwiXG4gICAgaWYgKGxlZnRUeXBlID09IFwic3RyaW5nXCIgJiYgcmlnaHRUeXBlID09IFwic3RyaW5nXCIpIHJldHVybiBcIlN0cmluZ0NvbmNhdFwiXG5cbiAgICBjb25zdCBsb2NhdGlvbiA9IGxlZnRUeXBlID09IFwiaW50ZWdlclwiIHx8IGxlZnRUeXBlID09IFwic3RyaW5nXCIgPyByaWdodExvY2F0aW9uIDogbGVmdExvY2F0aW9uXG5cbiAgICByZXR1cm4gZmFpbChcIklOVkFMSURfT1BFUkFORF9UWVBFXCIsIGBBZGRpdGlvbiByZXF1aXJlcyB0d28gaW50ZWdlcnMgb3IgdHdvIHN0cmluZ3M7IHJlY2VpdmVkICR7bGVmdFR5cGV9IGFuZCAke3JpZ2h0VHlwZX0uYCwgbG9jYXRpb24pXG4gIH1cblxuICBjb25zdCBmaXhlZE9wZXJhdGlvbnMgPSAvKiogQHR5cGUge2NvbnN0fSAqLyAoe1xuICAgIEFuZDogW1wiYm9vbGVhblwiLCBcIkJvb2xlYW5BbmRcIl0sXG4gICAgR3JlYXRlclRoYW46IFtcImludGVnZXJcIiwgXCJJbnRlZ2VyR3JlYXRlclRoYW5cIl0sXG4gICAgR3JlYXRlclRoYW5PckVxdWFsOiBbXCJpbnRlZ2VyXCIsIFwiSW50ZWdlckdyZWF0ZXJUaGFuT3JFcXVhbFwiXSxcbiAgICBMZXNzVGhhbjogW1wiaW50ZWdlclwiLCBcIkludGVnZXJMZXNzVGhhblwiXSxcbiAgICBMZXNzVGhhbk9yRXF1YWw6IFtcImludGVnZXJcIiwgXCJJbnRlZ2VyTGVzc1RoYW5PckVxdWFsXCJdLFxuICAgIE11bHRpcGx5OiBbXCJpbnRlZ2VyXCIsIFwiSW50ZWdlck11bHRpcGx5XCJdLFxuICAgIE9yOiBbXCJib29sZWFuXCIsIFwiQm9vbGVhbk9yXCJdLFxuICAgIFN1YnRyYWN0OiBbXCJpbnRlZ2VyXCIsIFwiSW50ZWdlclN1YnRyYWN0XCJdXG4gIH0pXG4gIGNvbnN0IGZpeGVkID0gUmVmbGVjdC5nZXQoZml4ZWRPcGVyYXRpb25zLCBTdHJpbmcoc291cmNlT3BlcmF0aW9uKSlcblxuICBpZiAoZml4ZWQpIHtcbiAgICBjb25zdCBbcmVxdWlyZWRUeXBlLCBvcGVyYXRpb25dID0gZml4ZWRcblxuICAgIGlmIChsZWZ0VHlwZSAhPSByZXF1aXJlZFR5cGUpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgJHtTdHJpbmcoc291cmNlT3BlcmF0aW9uKX0gcmVxdWlyZXMgJHtyZXF1aXJlZFR5cGV9OyByZWNlaXZlZCAke2xlZnRUeXBlfS5gLCBsZWZ0TG9jYXRpb24pXG4gICAgaWYgKHJpZ2h0VHlwZSAhPSByZXF1aXJlZFR5cGUpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgJHtTdHJpbmcoc291cmNlT3BlcmF0aW9uKX0gcmVxdWlyZXMgJHtyZXF1aXJlZFR5cGV9OyByZWNlaXZlZCAke3JpZ2h0VHlwZX0uYCwgcmlnaHRMb2NhdGlvbilcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNCaW5hcnlPcGVyYXRpb259ICovIChvcGVyYXRpb24pXG4gIH1cblxuICBpZiAoc291cmNlT3BlcmF0aW9uID09IFwiSmF2YUVxdWFsXCIgfHwgc291cmNlT3BlcmF0aW9uID09IFwiSmF2YU5vdEVxdWFsXCIpIHtcbiAgICBpZiAobGVmdFR5cGUgPT0gXCJzdHJpbmdcIiB8fCByaWdodFR5cGUgPT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIGZhaWwoXCJVTlNVUFBPUlRFRF9TWU5UQVhcIiwgXCJKYXZhIHJlZmVyZW5jZSBlcXVhbGl0eSBpcyBvdXRzaWRlIHRoZSBpbXBsZW1lbnRlZCBzZW1hbnRpYyBzdWJzZXQuXCIsIGV4cHJlc3Npb25Mb2NhdGlvbilcbiAgICB9XG5cbiAgICBzb3VyY2VPcGVyYXRpb24gPSBzb3VyY2VPcGVyYXRpb24gPT0gXCJKYXZhRXF1YWxcIiA/IFwiRXF1YWxcIiA6IFwiTm90RXF1YWxcIlxuICB9XG5cbiAgaWYgKHNvdXJjZU9wZXJhdGlvbiA9PSBcIlN0cmluZ0VxdWFsXCIgfHwgc291cmNlT3BlcmF0aW9uID09IFwiU3RyaW5nTm90RXF1YWxcIikge1xuICAgIGlmIChsZWZ0VHlwZSAhPSBcInN0cmluZ1wiKSBmYWlsKFwiSU5WQUxJRF9PUEVSQU5EX1RZUEVcIiwgYFN0cmluZyBlcXVhbGl0eSByZXF1aXJlcyBzdHJpbmc7IHJlY2VpdmVkICR7bGVmdFR5cGV9LmAsIGxlZnRMb2NhdGlvbilcbiAgICBpZiAocmlnaHRUeXBlICE9IFwic3RyaW5nXCIpIGZhaWwoXCJJTlZBTElEX09QRVJBTkRfVFlQRVwiLCBgU3RyaW5nIGVxdWFsaXR5IHJlcXVpcmVzIHN0cmluZzsgcmVjZWl2ZWQgJHtyaWdodFR5cGV9LmAsIHJpZ2h0TG9jYXRpb24pXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtcIlN0cmluZ0VxdWFsXCIgfCBcIlN0cmluZ05vdEVxdWFsXCJ9ICovIChzb3VyY2VPcGVyYXRpb24pXG4gIH1cblxuICBpZiAoc291cmNlT3BlcmF0aW9uID09IFwiRXF1YWxcIiB8fCBzb3VyY2VPcGVyYXRpb24gPT0gXCJOb3RFcXVhbFwiKSB7XG4gICAgaWYgKGxlZnRUeXBlICE9IHJpZ2h0VHlwZSkge1xuICAgICAgcmV0dXJuIGZhaWwoXCJNSVNNQVRDSEVEX0VRVUFMSVRZX1RZUEVTXCIsIGBFcXVhbGl0eSByZXF1aXJlcyBtYXRjaGluZyBzY2FsYXIgdHlwZXM7IHJlY2VpdmVkICR7bGVmdFR5cGV9IGFuZCAke3JpZ2h0VHlwZX0uYCwgcmlnaHRMb2NhdGlvbilcbiAgICB9XG5cbiAgICBjb25zdCBwcmVmaXggPSBsZWZ0VHlwZSA9PSBcImludGVnZXJcIiA/IFwiSW50ZWdlclwiIDogbGVmdFR5cGUgPT0gXCJib29sZWFuXCIgPyBcIkJvb2xlYW5cIiA6IFwiU3RyaW5nXCJcblxuICAgIHJldHVybiAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNCaW5hcnlPcGVyYXRpb259ICovIChgJHtwcmVmaXh9JHtzb3VyY2VPcGVyYXRpb259YClcbiAgfVxuXG4gIHJldHVybiBmYWlsKFwiVFlQRV9NSVNNQVRDSFwiLCBgVW5rbm93biBiaW5hcnkgc291cmNlIG9wZXJhdGlvbiAke1N0cmluZyhzb3VyY2VPcGVyYXRpb24pfS5gLCBsZWZ0TG9jYXRpb24pXG59XG5cbi8qKlxuICogUmVwbGFjZXMgdHJhbnNpZW50IGZyb250ZW5kIGludGVudCB3aXRoIHRoZSBwdWJsaWMgdHlwZWQgb3BlcmF0aW9uIGZpZWxkcy5cbiAqIEBwYXJhbSB7b2JqZWN0fSBleHByZXNzaW9uIC0gTXV0YWJsZSBhZGFwdGVkIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNVbmFyeU9wZXJhdGlvbiB8IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNCaW5hcnlPcGVyYXRpb259IG9wZXJhdGlvbiAtIFR5cGVkIG9wZXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1R5cGVOYW1lfSB0eXBlIC0gRXhwbGljaXQgcmVzdWx0IHR5cGUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gc2V0Tm9ybWFsaXplZE9wZXJhdGlvbihleHByZXNzaW9uLCBvcGVyYXRpb24sIHR5cGUpIHtcbiAgUmVmbGVjdC5zZXQoZXhwcmVzc2lvbiwgXCJvcGVyYXRpb25cIiwgb3BlcmF0aW9uKVxuICBSZWZsZWN0LnNldChleHByZXNzaW9uLCBcInR5cGVcIiwgdHlwZSlcbn1cbiJdfQ==
|