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,630 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { parser } from "@lezer/java";
|
|
3
|
+
import { SemantifoldDiagnostic, missingType, unsupportedSyntax } from "../diagnostic.js";
|
|
4
|
+
import { locationFromOffsets, moduleLocation } from "../semantic/location.js";
|
|
5
|
+
import { withAdaptedOperation } from "../semantic/operators.js";
|
|
6
|
+
import { withParserRanges } from "../semantic/provenance.js";
|
|
7
|
+
import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
|
|
8
|
+
import { sourceScalarType } from "./scalars.js";
|
|
9
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
10
|
+
const simpleStringEscapes = Object.freeze({
|
|
11
|
+
"\"": "\"",
|
|
12
|
+
"'": "'",
|
|
13
|
+
"\\": "\\",
|
|
14
|
+
b: "\b",
|
|
15
|
+
f: "\f",
|
|
16
|
+
n: "\n",
|
|
17
|
+
r: "\r",
|
|
18
|
+
s: " ",
|
|
19
|
+
t: "\t"
|
|
20
|
+
});
|
|
21
|
+
const javaBinaryOperations = new Map([
|
|
22
|
+
["+", "Add"],
|
|
23
|
+
["-", "Subtract"],
|
|
24
|
+
["*", "Multiply"],
|
|
25
|
+
["&&", "And"],
|
|
26
|
+
["||", "Or"],
|
|
27
|
+
["==", "JavaEqual"],
|
|
28
|
+
["!=", "JavaNotEqual"],
|
|
29
|
+
["<", "LessThan"],
|
|
30
|
+
["<=", "LessThanOrEqual"],
|
|
31
|
+
[">", "GreaterThan"],
|
|
32
|
+
[">=", "GreaterThanOrEqual"]
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* Returns all direct child syntax nodes.
|
|
36
|
+
* @param {import("@lezer/common").SyntaxNode} node - Parent syntax node.
|
|
37
|
+
* @returns {import("@lezer/common").SyntaxNode[]} Child syntax nodes.
|
|
38
|
+
*/
|
|
39
|
+
function directChildren(node) {
|
|
40
|
+
const children = [];
|
|
41
|
+
for (let child = node.firstChild; child; child = child.nextSibling)
|
|
42
|
+
children.push(child);
|
|
43
|
+
return children;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns structural direct children, excluding known grammar delimiters.
|
|
47
|
+
* @param {import("@lezer/common").SyntaxNode} node - Parent syntax node.
|
|
48
|
+
* @returns {import("@lezer/common").SyntaxNode[]} Named children.
|
|
49
|
+
*/
|
|
50
|
+
function structuralChildren(node) {
|
|
51
|
+
return directChildren(node).filter((child) => !["{", "}", "(", ")", ",", ";", "."].includes(child.name));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Finds all descendant syntax nodes with a given name.
|
|
55
|
+
* @param {import("@lezer/common").SyntaxNode} node - Root syntax node.
|
|
56
|
+
* @param {string} name - Node name.
|
|
57
|
+
* @returns {import("@lezer/common").SyntaxNode[]} Matching descendants.
|
|
58
|
+
*/
|
|
59
|
+
function descendants(node, name) {
|
|
60
|
+
const matches = [];
|
|
61
|
+
for (const child of directChildren(node)) {
|
|
62
|
+
if (child.name == name)
|
|
63
|
+
matches.push(child);
|
|
64
|
+
matches.push(...descendants(child, name));
|
|
65
|
+
}
|
|
66
|
+
return matches;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Requires one direct child node.
|
|
70
|
+
* @param {import("@lezer/common").SyntaxNode} node - Parent node.
|
|
71
|
+
* @param {string} name - Child name.
|
|
72
|
+
* @param {string} filename - Source filename.
|
|
73
|
+
* @param {string} source - Complete source.
|
|
74
|
+
* @returns {import("@lezer/common").SyntaxNode} Child node.
|
|
75
|
+
*/
|
|
76
|
+
function requiredChild(node, name, filename, source) {
|
|
77
|
+
const child = node.getChild(name);
|
|
78
|
+
if (!child)
|
|
79
|
+
return unsupportedSyntax("java", `${node.name} without ${name}`, nodeLocation(node, filename, source));
|
|
80
|
+
return child;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Returns a normalized Lezer node location.
|
|
84
|
+
* @param {import("@lezer/common").SyntaxNode} node - Lezer node.
|
|
85
|
+
* @param {string} filename - Source filename.
|
|
86
|
+
* @param {string} source - Complete source.
|
|
87
|
+
* @returns {import("../semantic/types.js").SourceLocation} Source location.
|
|
88
|
+
*/
|
|
89
|
+
function nodeLocation(node, filename, source) {
|
|
90
|
+
return locationFromOffsets(filename, source, node.from, node.to);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns source text belonging to a syntax node.
|
|
94
|
+
* @param {import("@lezer/common").SyntaxNode} node - Lezer node.
|
|
95
|
+
* @param {string} source - Complete source.
|
|
96
|
+
* @returns {string} Node text.
|
|
97
|
+
*/
|
|
98
|
+
function nodeText(node, source) {
|
|
99
|
+
return source.slice(node.from, node.to);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Converts a supported Java expression node.
|
|
103
|
+
* @param {import("@lezer/common").SyntaxNode} node - Lezer expression.
|
|
104
|
+
* @param {string} filename - Source filename.
|
|
105
|
+
* @param {string} source - Complete source.
|
|
106
|
+
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
107
|
+
*/
|
|
108
|
+
function convertExpression(node, filename, source) {
|
|
109
|
+
const location = nodeLocation(node, filename, source);
|
|
110
|
+
if (node.name == "ParenthesizedExpression") {
|
|
111
|
+
const children = structuralChildren(node);
|
|
112
|
+
if (children.length != 1) {
|
|
113
|
+
return unsupportedSyntax("java", "unsupported parenthesized expression", location);
|
|
114
|
+
}
|
|
115
|
+
return convertExpression(children[0], filename, source);
|
|
116
|
+
}
|
|
117
|
+
if (node.name == "Identifier") {
|
|
118
|
+
return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name: nodeText(node, source) }, { name: location });
|
|
119
|
+
}
|
|
120
|
+
if (node.name == "IntegerLiteral") {
|
|
121
|
+
const value = Number(nodeText(node, source));
|
|
122
|
+
if (!Number.isSafeInteger(value))
|
|
123
|
+
return unsupportedSyntax("java", "non-safe integer literal", location);
|
|
124
|
+
return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value }, { literal: location });
|
|
125
|
+
}
|
|
126
|
+
if (node.name == "BooleanLiteral") {
|
|
127
|
+
return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: nodeText(node, source) == "true" }, { literal: location });
|
|
128
|
+
}
|
|
129
|
+
if (node.name == "StringLiteral") {
|
|
130
|
+
return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: decodeStringLiteral(node, filename, source) }, { literal: location });
|
|
131
|
+
}
|
|
132
|
+
if (node.name == "UnaryExpression") {
|
|
133
|
+
const children = structuralChildren(node);
|
|
134
|
+
const operatorNode = node.getChild("LogicOp") ?? node.getChild("ArithOp");
|
|
135
|
+
const operand = children.find((child) => child.name != "LogicOp" && child.name != "ArithOp");
|
|
136
|
+
const operator = operatorNode ? nodeText(operatorNode, source) : undefined;
|
|
137
|
+
if (!operatorNode || !operand || children.length != 2 || (operator != "!" && operator != "-")) {
|
|
138
|
+
return unsupportedSyntax("java", "unary expression", location);
|
|
139
|
+
}
|
|
140
|
+
if (operator == "!" && operand.name == "MethodInvocation" && isEqualsInvocation(operand, source)) {
|
|
141
|
+
return convertStringEquality(operand, true, location, nodeLocation(operatorNode, filename, source), filename, source);
|
|
142
|
+
}
|
|
143
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
144
|
+
kind: "UnaryExpression",
|
|
145
|
+
location,
|
|
146
|
+
operand: convertExpression(operand, filename, source)
|
|
147
|
+
}, { operator: nodeLocation(operatorNode, filename, source) }), operator == "!" ? "Not" : "Negate");
|
|
148
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
149
|
+
}
|
|
150
|
+
if (node.name == "BinaryExpression") {
|
|
151
|
+
const named = structuralChildren(node);
|
|
152
|
+
const operatorNode = node.getChild("CompareOp") ?? node.getChild("ArithOp") ?? node.getChild("LogicOp") ?? node.getChild("BitOp");
|
|
153
|
+
if (!operatorNode || named.length != 3)
|
|
154
|
+
return unsupportedSyntax("java", "binary expression", location);
|
|
155
|
+
const operands = [named[0], named[2]];
|
|
156
|
+
const unsupportedOperand = operands.find((operand) => !isSupportedExpressionNode(operand));
|
|
157
|
+
if (unsupportedOperand)
|
|
158
|
+
return unsupportedSyntax("java", unsupportedOperand.name, nodeLocation(unsupportedOperand, filename, source));
|
|
159
|
+
const operator = nodeText(operatorNode, source);
|
|
160
|
+
if (!javaBinaryOperations.has(operator))
|
|
161
|
+
return unsupportedSyntax("java", `binary ${operator}`, location);
|
|
162
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
163
|
+
kind: "BinaryExpression",
|
|
164
|
+
left: convertExpression(operands[0], filename, source),
|
|
165
|
+
location,
|
|
166
|
+
right: convertExpression(operands[1], filename, source)
|
|
167
|
+
}, { operator: nodeLocation(operatorNode, filename, source) }), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (javaBinaryOperations.get(operator)));
|
|
168
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
169
|
+
}
|
|
170
|
+
if (node.name == "MethodInvocation") {
|
|
171
|
+
if (isEqualsInvocation(node, source)) {
|
|
172
|
+
const methodName = requiredChild(node, "MethodName", filename, source);
|
|
173
|
+
return convertStringEquality(node, false, location, nodeLocation(methodName, filename, source), filename, source);
|
|
174
|
+
}
|
|
175
|
+
const unsupportedReceiver = structuralChildren(node).find((child) => child.name != "MethodName" && child.name != "ArgumentList");
|
|
176
|
+
if (unsupportedReceiver)
|
|
177
|
+
return unsupportedSyntax("java", "method invocation receiver", nodeLocation(unsupportedReceiver, filename, source));
|
|
178
|
+
const methodName = requiredChild(node, "MethodName", filename, source);
|
|
179
|
+
const argumentList = requiredChild(node, "ArgumentList", filename, source);
|
|
180
|
+
const argumentNodes = structuralChildren(argumentList);
|
|
181
|
+
const unsupportedArgument = argumentNodes.find((child) => !isSupportedExpressionNode(child));
|
|
182
|
+
if (unsupportedArgument)
|
|
183
|
+
return unsupportedSyntax("java", `method argument ${unsupportedArgument.name}`, nodeLocation(unsupportedArgument, filename, source));
|
|
184
|
+
const arguments_ = argumentNodes.map((child) => convertExpression(child, filename, source));
|
|
185
|
+
return withParserRanges({ arguments: arguments_, callee: nodeText(methodName, source), kind: /** @type {const} */ ("CallExpression"), location }, {
|
|
186
|
+
callee: nodeLocation(methodName, filename, source)
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return unsupportedSyntax("java", node.name, location);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Checks the one parser-native Java string equality invocation form.
|
|
193
|
+
* @param {import("@lezer/common").SyntaxNode} node - Method invocation node.
|
|
194
|
+
* @param {string} source - Complete source.
|
|
195
|
+
* @returns {boolean} Whether the invocation spells `.equals` with a receiver.
|
|
196
|
+
*/
|
|
197
|
+
function isEqualsInvocation(node, source) {
|
|
198
|
+
const methodName = node.getChild("MethodName");
|
|
199
|
+
const receivers = structuralChildren(node).filter((child) => child.name != "MethodName" && child.name != "ArgumentList");
|
|
200
|
+
return methodName != null && nodeText(methodName, source) == "equals" && receivers.length == 1;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Converts Java `.equals` or its directly negated form without source-text inference.
|
|
204
|
+
* @param {import("@lezer/common").SyntaxNode} node - Parser method invocation.
|
|
205
|
+
* @param {boolean} negated - Whether a parser-owned unary not wraps the invocation.
|
|
206
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Whole equality expression location.
|
|
207
|
+
* @param {import("../semantic/types.js").SourceLocation} operatorLocation - Parser-owned operator/method location.
|
|
208
|
+
* @param {string} filename - Source filename.
|
|
209
|
+
* @param {string} source - Complete source.
|
|
210
|
+
* @returns {import("../semantic/types.js").Expression} Adapted equality expression.
|
|
211
|
+
*/
|
|
212
|
+
function convertStringEquality(node, negated, location, operatorLocation, filename, source) {
|
|
213
|
+
const argumentList = requiredChild(node, "ArgumentList", filename, source);
|
|
214
|
+
const arguments_ = structuralChildren(argumentList);
|
|
215
|
+
const receivers = structuralChildren(node).filter((child) => child.name != "MethodName" && child.name != "ArgumentList");
|
|
216
|
+
const unsupportedArgument = arguments_.find((child) => !isSupportedExpressionNode(child));
|
|
217
|
+
if (receivers.length != 1 || arguments_.length != 1 || unsupportedArgument) {
|
|
218
|
+
return unsupportedSyntax("java", "string equals invocation", nodeLocation(node, filename, source));
|
|
219
|
+
}
|
|
220
|
+
/** @type {Record<string, import("../semantic/types.js").SourceLocation>} */
|
|
221
|
+
const ranges = { operator: operatorLocation };
|
|
222
|
+
if (negated) {
|
|
223
|
+
ranges.equalityOperator = nodeLocation(requiredChild(node, "MethodName", filename, source), filename, source);
|
|
224
|
+
}
|
|
225
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
226
|
+
kind: "BinaryExpression",
|
|
227
|
+
left: convertExpression(receivers[0], filename, source),
|
|
228
|
+
location,
|
|
229
|
+
right: convertExpression(arguments_[0], filename, source)
|
|
230
|
+
}, ranges), negated ? "StringNotEqual" : "StringEqual");
|
|
231
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Checks whether a Lezer node is in the expression subset.
|
|
235
|
+
* @param {import("@lezer/common").SyntaxNode} node - Java syntax node.
|
|
236
|
+
* @returns {boolean} Whether the node is supported.
|
|
237
|
+
*/
|
|
238
|
+
function isSupportedExpressionNode(node) {
|
|
239
|
+
return [
|
|
240
|
+
"Identifier",
|
|
241
|
+
"IntegerLiteral",
|
|
242
|
+
"BooleanLiteral",
|
|
243
|
+
"StringLiteral",
|
|
244
|
+
"UnaryExpression",
|
|
245
|
+
"BinaryExpression",
|
|
246
|
+
"MethodInvocation",
|
|
247
|
+
"ParenthesizedExpression"
|
|
248
|
+
].includes(node.name);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Applies Java Unicode translation before token-level string escape decoding.
|
|
252
|
+
* @param {string} literal - Parser-confirmed Java string literal.
|
|
253
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Literal source location.
|
|
254
|
+
* @returns {string} Unicode-translated literal.
|
|
255
|
+
*/
|
|
256
|
+
function translateUnicodeEscapes(literal, location) {
|
|
257
|
+
let translated = "";
|
|
258
|
+
let consecutiveBackslashes = 0;
|
|
259
|
+
let previousWasUnicodeEscape = false;
|
|
260
|
+
for (let index = 0; index < literal.length; index++) {
|
|
261
|
+
const character = literal[index];
|
|
262
|
+
const eligible = character == "\\" && (previousWasUnicodeEscape || consecutiveBackslashes % 2 == 0);
|
|
263
|
+
if (eligible && literal[index + 1] == "u") {
|
|
264
|
+
let digitsStart = index + 2;
|
|
265
|
+
while (literal[digitsStart] == "u")
|
|
266
|
+
digitsStart++;
|
|
267
|
+
const hexadecimal = literal.slice(digitsStart, digitsStart + 4);
|
|
268
|
+
const isHexadecimal = hexadecimal.length == 4 && [...hexadecimal].every((digit) => (digit >= "0" && digit <= "9") || (digit >= "A" && digit <= "F") || (digit >= "a" && digit <= "f"));
|
|
269
|
+
if (!isHexadecimal)
|
|
270
|
+
return unsupportedSyntax("java", "unsupported string escape", location);
|
|
271
|
+
const translatedCharacter = String.fromCharCode(Number.parseInt(hexadecimal, 16));
|
|
272
|
+
translated += translatedCharacter;
|
|
273
|
+
consecutiveBackslashes = translatedCharacter == "\\" ? consecutiveBackslashes + 1 : 0;
|
|
274
|
+
previousWasUnicodeEscape = true;
|
|
275
|
+
index = digitsStart + 3;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
translated += character;
|
|
279
|
+
consecutiveBackslashes = character == "\\" ? consecutiveBackslashes + 1 : 0;
|
|
280
|
+
previousWasUnicodeEscape = false;
|
|
281
|
+
}
|
|
282
|
+
return translated;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Decodes the accepted escapes from one parser-confirmed Java string literal.
|
|
286
|
+
* @param {import("@lezer/common").SyntaxNode} node - Java StringLiteral node.
|
|
287
|
+
* @param {string} filename - Source filename.
|
|
288
|
+
* @param {string} source - Complete source.
|
|
289
|
+
* @returns {string} Decoded Unicode string.
|
|
290
|
+
*/
|
|
291
|
+
function decodeStringLiteral(node, filename, source) {
|
|
292
|
+
const location = nodeLocation(node, filename, source);
|
|
293
|
+
const literal = translateUnicodeEscapes(nodeText(node, source), location);
|
|
294
|
+
let value = "";
|
|
295
|
+
for (let index = 1; index < literal.length - 1; index++) {
|
|
296
|
+
const character = literal[index];
|
|
297
|
+
if (character == "\"" || character == "\n" || character == "\r") {
|
|
298
|
+
return unsupportedSyntax("java", "invalid string literal", location);
|
|
299
|
+
}
|
|
300
|
+
if (character != "\\") {
|
|
301
|
+
value += character;
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (index + 1 >= literal.length - 1)
|
|
305
|
+
return unsupportedSyntax("java", "invalid string literal", location);
|
|
306
|
+
const escaped = literal[++index];
|
|
307
|
+
const simple = simpleStringEscapes[escaped];
|
|
308
|
+
if (simple !== undefined) {
|
|
309
|
+
value += simple;
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (escaped >= "0" && escaped <= "7") {
|
|
313
|
+
let octal = escaped;
|
|
314
|
+
const maximumLength = escaped <= "3" ? 3 : 2;
|
|
315
|
+
while (octal.length < maximumLength && literal[index + 1] >= "0" && literal[index + 1] <= "7") {
|
|
316
|
+
octal += literal[++index];
|
|
317
|
+
}
|
|
318
|
+
value += String.fromCharCode(Number.parseInt(octal, 8));
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
return unsupportedSyntax("java", "unsupported string escape", location);
|
|
322
|
+
}
|
|
323
|
+
if (!hasOnlyUnicodeScalars(value))
|
|
324
|
+
return unsupportedSyntax("java", "invalid Unicode string literal", location);
|
|
325
|
+
return value;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Converts one explicit Java return statement.
|
|
329
|
+
* @param {import("@lezer/common").SyntaxNode} statement - Java statement.
|
|
330
|
+
* @param {string} filename - Source filename.
|
|
331
|
+
* @param {string} source - Complete source.
|
|
332
|
+
* @returns {import("../semantic/types.js").ReturnStatement} Semantic return.
|
|
333
|
+
*/
|
|
334
|
+
function convertReturn(statement, filename, source) {
|
|
335
|
+
const location = nodeLocation(statement, filename, source);
|
|
336
|
+
if (statement.name != "ReturnStatement")
|
|
337
|
+
return unsupportedSyntax("java", statement.name, location);
|
|
338
|
+
const expressionNodes = directChildren(statement).filter((child) => child.name != "return" && child.name != ";");
|
|
339
|
+
const expression = expressionNodes.length == 1 ? expressionNodes[0] : undefined;
|
|
340
|
+
if (!expression) {
|
|
341
|
+
const unsupported = expressionNodes[0];
|
|
342
|
+
return unsupportedSyntax("java", unsupported?.name ?? "empty return", unsupported ? nodeLocation(unsupported, filename, source) : location);
|
|
343
|
+
}
|
|
344
|
+
return { expression: convertExpression(expression, filename, source), kind: "ReturnStatement", location };
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Converts one Java local declaration or assignment.
|
|
348
|
+
* @param {import("@lezer/common").SyntaxNode} statement - Java statement.
|
|
349
|
+
* @param {string} filename - Source filename.
|
|
350
|
+
* @param {string} source - Complete source.
|
|
351
|
+
* @returns {import("../semantic/types.js").LocalStatement} Semantic local statement.
|
|
352
|
+
*/
|
|
353
|
+
function convertLocalStatement(statement, filename, source) {
|
|
354
|
+
const location = nodeLocation(statement, filename, source);
|
|
355
|
+
if (statement.name == "LocalVariableDeclaration") {
|
|
356
|
+
const declarators = statement.getChildren("VariableDeclarator");
|
|
357
|
+
const typeNode = declarationType(statement);
|
|
358
|
+
const varNode = statement.getChild("var");
|
|
359
|
+
const modifiers = statement.getChild("Modifiers");
|
|
360
|
+
const modifierChildren = modifiers ? structuralChildren(modifiers) : [];
|
|
361
|
+
if (varNode)
|
|
362
|
+
return unsupportedSyntax("java", "var local declaration", nodeLocation(varNode, filename, source));
|
|
363
|
+
if (declarators.length != 1)
|
|
364
|
+
return unsupportedSyntax("java", "multiple local declarators", location);
|
|
365
|
+
if (!typeNode || typeNode.name == "ArrayType")
|
|
366
|
+
return unsupportedSyntax("java", "unsupported local type", location);
|
|
367
|
+
if (modifierChildren.some((child) => child.name != "final") || modifierChildren.length > 1) {
|
|
368
|
+
return unsupportedSyntax("java", "unsupported local modifiers", modifiers ? nodeLocation(modifiers, filename, source) : location);
|
|
369
|
+
}
|
|
370
|
+
const declarator = declarators[0];
|
|
371
|
+
const definition = requiredChild(declarator, "Definition", filename, source);
|
|
372
|
+
const assignment = declarator.getChild("AssignOp");
|
|
373
|
+
const dimensions = declarator.getChildren("Dimension");
|
|
374
|
+
const initializerNodes = directChildren(declarator).filter((child) => child.name != "Definition" && child.name != "AssignOp");
|
|
375
|
+
if (dimensions.length > 0)
|
|
376
|
+
return unsupportedSyntax("java", "array local declaration", nodeLocation(declarator, filename, source));
|
|
377
|
+
if (!assignment || nodeText(assignment, source) != "=" || initializerNodes.length != 1) {
|
|
378
|
+
return unsupportedSyntax("java", "uninitialized local declaration", nodeLocation(declarator, filename, source));
|
|
379
|
+
}
|
|
380
|
+
const name = nodeText(definition, source);
|
|
381
|
+
return withParserRanges({
|
|
382
|
+
initializer: convertExpression(initializerNodes[0], filename, source),
|
|
383
|
+
kind: "LocalDeclaration",
|
|
384
|
+
location,
|
|
385
|
+
mutable: modifierChildren.length == 0,
|
|
386
|
+
name,
|
|
387
|
+
type: convertType(typeNode, `Local '${name}'`, location, filename, source)
|
|
388
|
+
}, { name: nodeLocation(definition, filename, source), operator: nodeLocation(assignment, filename, source) });
|
|
389
|
+
}
|
|
390
|
+
if (statement.name == "ExpressionStatement") {
|
|
391
|
+
const assignment = statement.getChild("AssignmentExpression");
|
|
392
|
+
if (!assignment)
|
|
393
|
+
return unsupportedSyntax("java", statement.name, location);
|
|
394
|
+
const children = structuralChildren(assignment);
|
|
395
|
+
const operator = assignment.getChild("AssignOp");
|
|
396
|
+
const target = children[0];
|
|
397
|
+
const expression = children.at(-1);
|
|
398
|
+
if (!operator || nodeText(operator, source) != "=")
|
|
399
|
+
return unsupportedSyntax("java", "compound assignment", nodeLocation(assignment, filename, source));
|
|
400
|
+
if (!target || target.name != "Identifier")
|
|
401
|
+
return unsupportedSyntax("java", target?.name ?? "assignment target", target ? nodeLocation(target, filename, source) : location);
|
|
402
|
+
if (!expression || expression == target || expression == operator)
|
|
403
|
+
return unsupportedSyntax("java", "assignment expression", nodeLocation(assignment, filename, source));
|
|
404
|
+
const targetExpression = withParserRanges({
|
|
405
|
+
kind: /** @type {const} */ ("IdentifierExpression"),
|
|
406
|
+
location: nodeLocation(target, filename, source),
|
|
407
|
+
name: nodeText(target, source)
|
|
408
|
+
}, { name: nodeLocation(target, filename, source) });
|
|
409
|
+
return withParserRanges({
|
|
410
|
+
expression: convertExpression(expression, filename, source),
|
|
411
|
+
kind: "AssignmentStatement",
|
|
412
|
+
location,
|
|
413
|
+
target: targetExpression
|
|
414
|
+
}, { operator: nodeLocation(operator, filename, source) });
|
|
415
|
+
}
|
|
416
|
+
return unsupportedSyntax("java", statement.name, location);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Converts one exhaustive direct Java block child.
|
|
420
|
+
* @param {import("@lezer/common").SyntaxNode} statement - Java statement.
|
|
421
|
+
* @param {string} filename - Source filename.
|
|
422
|
+
* @param {string} source - Complete source.
|
|
423
|
+
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
424
|
+
*/
|
|
425
|
+
function convertStatement(statement, filename, source) {
|
|
426
|
+
if (statement.name == "ReturnStatement")
|
|
427
|
+
return convertReturn(statement, filename, source);
|
|
428
|
+
if (statement.name == "IfStatement")
|
|
429
|
+
return convertIf(statement, filename, source);
|
|
430
|
+
if (statement.name == "LocalVariableDeclaration")
|
|
431
|
+
return convertLocalStatement(statement, filename, source);
|
|
432
|
+
if (statement.name == "ExpressionStatement") {
|
|
433
|
+
if (statement.getChild("AssignmentExpression"))
|
|
434
|
+
return convertLocalStatement(statement, filename, source);
|
|
435
|
+
if (!statement.getChild("MethodInvocation")) {
|
|
436
|
+
return unsupportedSyntax("java", statement.name, nodeLocation(statement, filename, source));
|
|
437
|
+
}
|
|
438
|
+
return convertPrint(statement, filename, source);
|
|
439
|
+
}
|
|
440
|
+
return unsupportedSyntax("java", statement.name, nodeLocation(statement, filename, source));
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Converts direct structural children of one Java block in source order.
|
|
444
|
+
* @param {import("@lezer/common").SyntaxNode} node - Java Block node.
|
|
445
|
+
* @param {string} filename - Source filename.
|
|
446
|
+
* @param {string} source - Complete source.
|
|
447
|
+
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
448
|
+
*/
|
|
449
|
+
function convertBlock(node, filename, source) {
|
|
450
|
+
if (node.name != "Block")
|
|
451
|
+
return unsupportedSyntax("java", `expected block, received ${node.name}`, nodeLocation(node, filename, source));
|
|
452
|
+
return {
|
|
453
|
+
kind: "Block",
|
|
454
|
+
location: nodeLocation(node, filename, source),
|
|
455
|
+
statements: structuralChildren(node).map((statement) => convertStatement(statement, filename, source))
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Requires an exact Java scalar type node.
|
|
460
|
+
* @param {import("@lezer/common").SyntaxNode | null} sourceType - Java type node.
|
|
461
|
+
* @param {string} subject - Typed subject.
|
|
462
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Source location.
|
|
463
|
+
* @param {string} filename - Source filename.
|
|
464
|
+
* @param {string} source - Complete source.
|
|
465
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic type.
|
|
466
|
+
*/
|
|
467
|
+
function convertType(sourceType, subject, location, filename, source) {
|
|
468
|
+
if (!sourceType)
|
|
469
|
+
return missingType("java", subject, location);
|
|
470
|
+
if (!["PrimitiveType", "TypeName", "ScopedTypeName"].includes(sourceType.name)) {
|
|
471
|
+
return unsupportedSyntax("java", "unsupported scalar type", location);
|
|
472
|
+
}
|
|
473
|
+
const type = sourceScalarType("java", nodeText(sourceType, source), nodeLocation(sourceType, filename, source));
|
|
474
|
+
if (!type)
|
|
475
|
+
return unsupportedSyntax("java", "unsupported scalar type", nodeLocation(sourceType, location.filename, source));
|
|
476
|
+
return type;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Returns the direct Java declaration type node supported by scalar conversion.
|
|
480
|
+
* @param {import("@lezer/common").SyntaxNode} node - Declaration node.
|
|
481
|
+
* @returns {import("@lezer/common").SyntaxNode | null} Type syntax node.
|
|
482
|
+
*/
|
|
483
|
+
function declarationType(node) {
|
|
484
|
+
return node.getChild("PrimitiveType") ?? node.getChild("TypeName") ?? node.getChild("ScopedTypeName");
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Converts the supported Java function method.
|
|
488
|
+
* @param {import("@lezer/common").SyntaxNode} node - Method declaration.
|
|
489
|
+
* @param {string} filename - Source filename.
|
|
490
|
+
* @param {string} source - Complete source.
|
|
491
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
492
|
+
*/
|
|
493
|
+
function convertFunction(node, filename, source) {
|
|
494
|
+
const location = nodeLocation(node, filename, source);
|
|
495
|
+
const definition = requiredChild(node, "Definition", filename, source);
|
|
496
|
+
const name = nodeText(definition, source);
|
|
497
|
+
const parametersNode = requiredChild(node, "FormalParameters", filename, source);
|
|
498
|
+
const parameters = parametersNode.getChildren("FormalParameter").map((parameter) => {
|
|
499
|
+
const parameterLocation = nodeLocation(parameter, filename, source);
|
|
500
|
+
const parameterNameNode = requiredChild(parameter, "Definition", filename, source);
|
|
501
|
+
const parameterName = nodeText(parameterNameNode, source);
|
|
502
|
+
const semanticParameter = {
|
|
503
|
+
kind: /** @type {const} */ ("Parameter"),
|
|
504
|
+
location: parameterLocation,
|
|
505
|
+
name: parameterName,
|
|
506
|
+
type: convertType(declarationType(parameter), `Parameter '${parameterName}'`, parameterLocation, filename, source)
|
|
507
|
+
};
|
|
508
|
+
return withParserRanges(semanticParameter, { name: nodeLocation(parameterNameNode, filename, source) });
|
|
509
|
+
});
|
|
510
|
+
const block = requiredChild(node, "Block", filename, source);
|
|
511
|
+
const body = convertBlock(block, filename, source);
|
|
512
|
+
return withParserRanges({
|
|
513
|
+
body,
|
|
514
|
+
kind: "FunctionDeclaration",
|
|
515
|
+
location,
|
|
516
|
+
name,
|
|
517
|
+
parameters,
|
|
518
|
+
returnType: convertType(declarationType(node), `Function '${name}' return`, location, filename, source)
|
|
519
|
+
}, { name: nodeLocation(definition, filename, source) });
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Converts the existing exact Java if/else terminal with restricted branch prefixes.
|
|
523
|
+
* @param {import("@lezer/common").SyntaxNode} node - Java if statement.
|
|
524
|
+
* @param {string} filename - Source filename.
|
|
525
|
+
* @param {string} source - Complete source.
|
|
526
|
+
* @returns {import("../semantic/types.js").IfStatement} Semantic branch.
|
|
527
|
+
*/
|
|
528
|
+
function convertIf(node, filename, source) {
|
|
529
|
+
const location = nodeLocation(node, filename, source);
|
|
530
|
+
const conditionContainer = requiredChild(node, "ParenthesizedExpression", filename, source);
|
|
531
|
+
const conditionNodes = structuralChildren(conditionContainer);
|
|
532
|
+
const condition = conditionNodes.length == 1 ? conditionNodes[0] : undefined;
|
|
533
|
+
const direct = directChildren(node);
|
|
534
|
+
const conditionIndex = direct.findIndex((child) => child.name == conditionContainer.name &&
|
|
535
|
+
child.from == conditionContainer.from && child.to == conditionContainer.to);
|
|
536
|
+
const consequentNode = direct[conditionIndex + 1];
|
|
537
|
+
const alternateNode = direct.at(-1) == consequentNode ? undefined : direct.at(-1);
|
|
538
|
+
if (!condition || !consequentNode || consequentNode.name != "Block") {
|
|
539
|
+
return unsupportedSyntax("java", "if without block consequent", location);
|
|
540
|
+
}
|
|
541
|
+
let alternate;
|
|
542
|
+
if (alternateNode?.name == "Block")
|
|
543
|
+
alternate = convertBlock(alternateNode, filename, source);
|
|
544
|
+
else if (alternateNode?.name == "IfStatement") {
|
|
545
|
+
alternate = {
|
|
546
|
+
kind: /** @type {const} */ ("Block"),
|
|
547
|
+
location: nodeLocation(alternateNode, filename, source),
|
|
548
|
+
statements: [convertIf(alternateNode, filename, source)]
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
else if (alternateNode && alternateNode.name != "else") {
|
|
552
|
+
return unsupportedSyntax("java", `if alternate ${alternateNode.name}`, nodeLocation(alternateNode, filename, source));
|
|
553
|
+
}
|
|
554
|
+
return {
|
|
555
|
+
...(alternate ? { alternate } : {}),
|
|
556
|
+
condition: convertExpression(condition, filename, source),
|
|
557
|
+
consequent: convertBlock(consequentNode, filename, source),
|
|
558
|
+
kind: "IfStatement",
|
|
559
|
+
location
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Converts Java's supported main method.
|
|
564
|
+
* @param {import("@lezer/common").SyntaxNode} node - Main method.
|
|
565
|
+
* @param {string} filename - Source filename.
|
|
566
|
+
* @param {string} source - Complete source.
|
|
567
|
+
* @returns {import("../semantic/types.js").EntryPoint} Semantic entry point.
|
|
568
|
+
*/
|
|
569
|
+
function convertEntryPoint(node, filename, source) {
|
|
570
|
+
const location = nodeLocation(node, filename, source);
|
|
571
|
+
const block = requiredChild(node, "Block", filename, source);
|
|
572
|
+
const body = convertBlock(block, filename, source);
|
|
573
|
+
return { body, kind: "EntryPoint", location };
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Converts one supported Java print statement.
|
|
577
|
+
* @param {import("@lezer/common").SyntaxNode} statement - Expression statement.
|
|
578
|
+
* @param {string} filename - Source filename.
|
|
579
|
+
* @param {string} source - Complete source.
|
|
580
|
+
* @returns {import("../semantic/types.js").PrintStatement} Semantic print.
|
|
581
|
+
*/
|
|
582
|
+
function convertPrint(statement, filename, source) {
|
|
583
|
+
const location = nodeLocation(statement, filename, source);
|
|
584
|
+
const printInvocation = statement.getChild("MethodInvocation");
|
|
585
|
+
if (!printInvocation)
|
|
586
|
+
return unsupportedSyntax("java", "main without System.out.println", location);
|
|
587
|
+
const fieldAccess = printInvocation.getChild("FieldAccess");
|
|
588
|
+
const methodName = printInvocation.getChild("MethodName");
|
|
589
|
+
if (!fieldAccess || !methodName || nodeText(fieldAccess, source) != "System.out" || nodeText(methodName, source) != "println") {
|
|
590
|
+
return unsupportedSyntax("java", "main without System.out.println", nodeLocation(printInvocation, filename, source));
|
|
591
|
+
}
|
|
592
|
+
const argumentList = requiredChild(printInvocation, "ArgumentList", filename, source);
|
|
593
|
+
const arguments_ = structuralChildren(argumentList);
|
|
594
|
+
if (arguments_.length != 1) {
|
|
595
|
+
return unsupportedSyntax("java", "println without one supported argument", nodeLocation(argumentList, filename, source));
|
|
596
|
+
}
|
|
597
|
+
const printLocation = nodeLocation(printInvocation, filename, source);
|
|
598
|
+
return { expression: convertExpression(arguments_[0], filename, source), kind: "PrintStatement", location: printLocation };
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Parses Java into the shared semantic module.
|
|
602
|
+
* @param {object} input - Parser input.
|
|
603
|
+
* @param {string} input.filename - Source filename.
|
|
604
|
+
* @param {string} input.source - Source text.
|
|
605
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
606
|
+
*/
|
|
607
|
+
export function parseJava({ filename, source }) {
|
|
608
|
+
const tree = parser.parse(source);
|
|
609
|
+
const error = descendants(tree.topNode, "⚠")[0];
|
|
610
|
+
if (error) {
|
|
611
|
+
throw new SemantifoldDiagnostic({
|
|
612
|
+
code: "PARSE_ERROR",
|
|
613
|
+
language: "java",
|
|
614
|
+
location: nodeLocation(error, filename, source),
|
|
615
|
+
message: "Java parser reported invalid syntax."
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
const methods = descendants(tree.topNode, "MethodDeclaration");
|
|
619
|
+
const mainMethod = methods.find((method) => nodeText(requiredChild(method, "Definition", filename, source), source) == "main");
|
|
620
|
+
const functionMethods = methods.filter((method) => method != mainMethod);
|
|
621
|
+
const location = moduleLocation(filename, source);
|
|
622
|
+
if (functionMethods.length == 0)
|
|
623
|
+
return unsupportedSyntax("java", "class without a semantic function", location);
|
|
624
|
+
if (!mainMethod)
|
|
625
|
+
return unsupportedSyntax("java", "class without main", location);
|
|
626
|
+
const functions = functionMethods.map((method) => convertFunction(method, filename, source));
|
|
627
|
+
const entryPoint = convertEntryPoint(mainMethod, filename, source);
|
|
628
|
+
return { entryPoint, functions, kind: "Module", location };
|
|
629
|
+
}
|
|
630
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamF2YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mcm9udGVuZHMvamF2YS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLGFBQWEsQ0FBQTtBQUNsQyxPQUFPLEVBQUMscUJBQXFCLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDdEYsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGNBQWMsRUFBQyxNQUFNLHlCQUF5QixDQUFBO0FBQzNFLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDBCQUEwQixDQUFBO0FBQzdELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLDJCQUEyQixDQUFBO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHdCQUF3QixDQUFBO0FBQzVELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGNBQWMsQ0FBQTtBQUU3QywrQ0FBK0M7QUFDL0MsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQ3hDLElBQUksRUFBRSxJQUFJO0lBQ1YsR0FBRyxFQUFFLEdBQUc7SUFDUixJQUFJLEVBQUUsSUFBSTtJQUNWLENBQUMsRUFBRSxJQUFJO0lBQ1AsQ0FBQyxFQUFFLElBQUk7SUFDUCxDQUFDLEVBQUUsSUFBSTtJQUNQLENBQUMsRUFBRSxJQUFJO0lBQ1AsQ0FBQyxFQUFFLEdBQUc7SUFDTixDQUFDLEVBQUUsSUFBSTtDQUNSLENBQUMsQ0FBQTtBQUNGLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDbkMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDO0lBQ1osQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQztJQUNqQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUM7SUFDYixDQUFDLElBQUksRUFBRSxJQUFJ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LFNBQVMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFBO0FBQzFELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtwYXJzZXJ9IGZyb20gXCJAbGV6ZXIvamF2YVwiXG5pbXBvcnQge1NlbWFudGlmb2xkRGlhZ25vc3RpYywgbWlzc2luZ1R5cGUsIHVuc3VwcG9ydGVkU3ludGF4fSBmcm9tIFwiLi4vZGlhZ25vc3RpYy5qc1wiXG5pbXBvcnQge2xvY2F0aW9uRnJvbU9mZnNldHMsIG1vZHVsZUxvY2F0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvbG9jYXRpb24uanNcIlxuaW1wb3J0IHt3aXRoQWRhcHRlZE9wZXJhdGlvbn0gZnJvbSBcIi4uL3NlbWFudGljL29wZXJhdG9ycy5qc1wiXG5pbXBvcnQge3dpdGhQYXJzZXJSYW5nZXN9IGZyb20gXCIuLi9zZW1hbnRpYy9wcm92ZW5hbmNlLmpzXCJcbmltcG9ydCB7aGFzT25seVVuaWNvZGVTY2FsYXJzfSBmcm9tIFwiLi4vc2VtYW50aWMvc2NhbGFycy5qc1wiXG5pbXBvcnQge3NvdXJjZVNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuXG4vKiogQHR5cGUge1JlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHN0cmluZz4+fSAqL1xuY29uc3Qgc2ltcGxlU3RyaW5nRXNjYXBlcyA9IE9iamVjdC5mcmVlemUoe1xuICBcIlxcXCJcIjogXCJcXFwiXCIsXG4gIFwiJ1wiOiBcIidcIixcbiAgXCJcXFxcXCI6IFwiXFxcXFwiLFxuICBiOiBcIlxcYlwiLFxuICBmOiBcIlxcZlwiLFxuICBuOiBcIlxcblwiLFxuICByOiBcIlxcclwiLFxuICBzOiBcIiBcIixcbiAgdDogXCJcXHRcIlxufSlcbmNvbnN0IGphdmFCaW5hcnlPcGVyYXRpb25zID0gbmV3IE1hcChbXG4gIFtcIitcIiwgXCJBZGRcIl0sXG4gIFtcIi1cIiwgXCJTdWJ0cmFjdFwiXSxcbiAgW1wiKlwiLCBcIk11bHRpcGx5XCJdLFxuICBbXCImJlwiLCBcIkFuZFwiXSxcbiAgW1wifHxcIiwgXCJPclwiXSxcbiAgW1wiPT1cIiwgXCJKYXZhRXF1YWxcIl0sXG4gIFtcIiE9XCIsIFwiSmF2YU5vdEVxdWFsXCJdLFxuICBbXCI8XCIsIFwiTGVzc1RoYW5cIl0sXG4gIFtcIjw9XCIsIFwiTGVzc1RoYW5PckVxdWFsXCJdLFxuICBbXCI+XCIsIFwiR3JlYXRlclRoYW5cIl0sXG4gIFtcIj49XCIsIFwiR3JlYXRlclRoYW5PckVxdWFsXCJdXG5dKVxuXG4vKipcbiAqIFJldHVybnMgYWxsIGRpcmVjdCBjaGlsZCBzeW50YXggbm9kZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIFBhcmVudCBzeW50YXggbm9kZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGVbXX0gQ2hpbGQgc3ludGF4IG5vZGVzLlxuICovXG5mdW5jdGlvbiBkaXJlY3RDaGlsZHJlbihub2RlKSB7XG4gIGNvbnN0IGNoaWxkcmVuID0gW11cblxuICBmb3IgKGxldCBjaGlsZCA9IG5vZGUuZmlyc3RDaGlsZDsgY2hpbGQ7IGNoaWxkID0gY2hpbGQubmV4dFNpYmxpbmcpIGNoaWxkcmVuLnB1c2goY2hpbGQpXG5cbiAgcmV0dXJuIGNoaWxkcmVuXG59XG5cbi8qKlxuICogUmV0dXJucyBzdHJ1Y3R1cmFsIGRpcmVjdCBjaGlsZHJlbiwgZXhjbHVkaW5nIGtub3duIGdyYW1tYXIgZGVsaW1pdGVycy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUGFyZW50IHN5bnRheCBub2RlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZVtdfSBOYW1lZCBjaGlsZHJlbi5cbiAqL1xuZnVuY3Rpb24gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpIHtcbiAgcmV0dXJuIGRpcmVjdENoaWxkcmVuKG5vZGUpLmZpbHRlcigoY2hpbGQpID0+ICFbXCJ7XCIsIFwifVwiLCBcIihcIiwgXCIpXCIsIFwiLFwiLCBcIjtcIiwgXCIuXCJdLmluY2x1ZGVzKGNoaWxkLm5hbWUpKVxufVxuXG4vKipcbiAqIEZpbmRzIGFsbCBkZXNjZW5kYW50IHN5bnRheCBub2RlcyB3aXRoIGEgZ2l2ZW4gbmFtZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUm9vdCBzeW50YXggbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTm9kZSBuYW1lLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZVtdfSBNYXRjaGluZyBkZXNjZW5kYW50cy5cbiAqL1xuZnVuY3Rpb24gZGVzY2VuZGFudHMobm9kZSwgbmFtZSkge1xuICBjb25zdCBtYXRjaGVzID0gW11cblxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIGRpcmVjdENoaWxkcmVuKG5vZGUpKSB7XG4gICAgaWYgKGNoaWxkLm5hbWUgPT0gbmFtZSkgbWF0Y2hlcy5wdXNoKGNoaWxkKVxuICAgIG1hdGNoZXMucHVzaCguLi5kZXNjZW5kYW50cyhjaGlsZCwgbmFtZSkpXG4gIH1cblxuICByZXR1cm4gbWF0Y2hlc1xufVxuXG4vKipcbiAqIFJlcXVpcmVzIG9uZSBkaXJlY3QgY2hpbGQgbm9kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gUGFyZW50IG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIENoaWxkIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gQ2hpbGQgbm9kZS5cbiAqL1xuZnVuY3Rpb24gcmVxdWlyZWRDaGlsZChub2RlLCBuYW1lLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGNoaWxkID0gbm9kZS5nZXRDaGlsZChuYW1lKVxuXG4gIGlmICghY2hpbGQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgYCR7bm9kZS5uYW1lfSB3aXRob3V0ICR7bmFtZX1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIGNoaWxkXG59XG5cbi8qKlxuICogUmV0dXJucyBhIG5vcm1hbGl6ZWQgTGV6ZXIgbm9kZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gTGV6ZXIgbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IFNvdXJjZSBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgbm9kZS5mcm9tLCBub2RlLnRvKVxufVxuXG4vKipcbiAqIFJldHVybnMgc291cmNlIHRleHQgYmVsb25naW5nIHRvIGEgc3ludGF4IG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIExlemVyIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3N0cmluZ30gTm9kZSB0ZXh0LlxuICovXG5mdW5jdGlvbiBub2RlVGV4dChub2RlLCBzb3VyY2UpIHtcbiAgcmV0dXJuIHNvdXJjZS5zbGljZShub2RlLmZyb20sIG5vZGUudG8pXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdXBwb3J0ZWQgSmF2YSBleHByZXNzaW9uIG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIExlemVyIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkV4cHJlc3Npb259IFNlbWFudGljIGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFeHByZXNzaW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZS5uYW1lID09IFwiUGFyZW50aGVzaXplZEV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpXG5cbiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoICE9IDEpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBwYXJlbnRoZXNpemVkIGV4cHJlc3Npb25cIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnZlcnRFeHByZXNzaW9uKGNoaWxkcmVuWzBdLCBmaWxlbmFtZSwgc291cmNlKVxuICB9XG5cbiAgaWYgKG5vZGUubmFtZSA9PSBcIklkZW50aWZpZXJcIikge1xuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJJZGVudGlmaWVyRXhwcmVzc2lvblwiKSwgbG9jYXRpb24sIG5hbWU6IG5vZGVUZXh0KG5vZGUsIHNvdXJjZSl9LCB7bmFtZTogbG9jYXRpb259KVxuICB9XG5cbiAgaWYgKG5vZGUubmFtZSA9PSBcIkludGVnZXJMaXRlcmFsXCIpIHtcbiAgICBjb25zdCB2YWx1ZSA9IE51bWJlcihub2RlVGV4dChub2RlLCBzb3VyY2UpKVxuXG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWx1ZSkpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJub24tc2FmZSBpbnRlZ2VyIGxpdGVyYWxcIiwgbG9jYXRpb24pXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSW50ZWdlckxpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZS5uYW1lID09IFwiQm9vbGVhbkxpdGVyYWxcIikge1xuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJCb29sZWFuTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBub2RlVGV4dChub2RlLCBzb3VyY2UpID09IFwidHJ1ZVwifSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJTdHJpbmdMaXRlcmFsXCIpIHtcbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiU3RyaW5nTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBkZWNvZGVTdHJpbmdMaXRlcmFsKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJVbmFyeUV4cHJlc3Npb25cIikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gc3RydWN0dXJhbENoaWxkcmVuKG5vZGUpXG4gICAgY29uc3Qgb3BlcmF0b3JOb2RlID0gbm9kZS5nZXRDaGlsZChcIkxvZ2ljT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkFyaXRoT3BcIilcbiAgICBjb25zdCBvcGVyYW5kID0gY2hpbGRyZW4uZmluZCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJMb2dpY09wXCIgJiYgY2hpbGQubmFtZSAhPSBcIkFyaXRoT3BcIilcbiAgICBjb25zdCBvcGVyYXRvciA9IG9wZXJhdG9yTm9kZSA/IG5vZGVUZXh0KG9wZXJhdG9yTm9kZSwgc291cmNlKSA6IHVuZGVmaW5lZFxuXG4gICAgaWYgKCFvcGVyYXRvck5vZGUgfHwgIW9wZXJhbmQgfHwgY2hpbGRyZW4ubGVuZ3RoICE9IDIgfHwgKG9wZXJhdG9yICE9IFwiIVwiICYmIG9wZXJhdG9yICE9IFwiLVwiKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuYXJ5IGV4cHJlc3Npb25cIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdG9yID09IFwiIVwiICYmIG9wZXJhbmQubmFtZSA9PSBcIk1ldGhvZEludm9jYXRpb25cIiAmJiBpc0VxdWFsc0ludm9jYXRpb24ob3BlcmFuZCwgc291cmNlKSkge1xuICAgICAgcmV0dXJuIGNvbnZlcnRTdHJpbmdFcXVhbGl0eShvcGVyYW5kLCB0cnVlLCBsb2NhdGlvbiwgbm9kZUxvY2F0aW9uKG9wZXJhdG9yTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiVW5hcnlFeHByZXNzaW9uXCIsXG4gICAgICBsb2NhdGlvbixcbiAgICAgIG9wZXJhbmQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3JOb2RlLCBmaWxlbmFtZSwgc291cmNlKX0pLCBvcGVyYXRvciA9PSBcIiFcIiA/IFwiTm90XCIgOiBcIk5lZ2F0ZVwiKVxuXG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHNlbWFudGljKSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJCaW5hcnlFeHByZXNzaW9uXCIpIHtcbiAgICBjb25zdCBuYW1lZCA9IHN0cnVjdHVyYWxDaGlsZHJlbihub2RlKVxuICAgIGNvbnN0IG9wZXJhdG9yTm9kZSA9IG5vZGUuZ2V0Q2hpbGQoXCJDb21wYXJlT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkFyaXRoT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkxvZ2ljT3BcIikgPz8gbm9kZS5nZXRDaGlsZChcIkJpdE9wXCIpXG5cbiAgICBpZiAoIW9wZXJhdG9yTm9kZSB8fCBuYW1lZC5sZW5ndGggIT0gMykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImJpbmFyeSBleHByZXNzaW9uXCIsIGxvY2F0aW9uKVxuXG4gICAgY29uc3Qgb3BlcmFuZHMgPSBbbmFtZWRbMF0sIG5hbWVkWzJdXVxuICAgIGNvbnN0IHVuc3VwcG9ydGVkT3BlcmFuZCA9IG9wZXJhbmRzLmZpbmQoKG9wZXJhbmQpID0+ICFpc1N1cHBvcnRlZEV4cHJlc3Npb25Ob2RlKG9wZXJhbmQpKVxuXG4gICAgaWYgKHVuc3VwcG9ydGVkT3BlcmFuZCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCB1bnN1cHBvcnRlZE9wZXJhbmQubmFtZSwgbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkT3BlcmFuZCwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgICBjb25zdCBvcGVyYXRvciA9IG5vZGVUZXh0KG9wZXJhdG9yTm9kZSwgc291cmNlKVxuXG4gICAgaWYgKCFqYXZhQmluYXJ5T3BlcmF0aW9ucy5oYXMob3BlcmF0b3IpKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBiaW5hcnkgJHtvcGVyYXRvcn1gLCBsb2NhdGlvbilcblxuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxlZnQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmRzWzBdLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHQ6IGNvbnZlcnRFeHByZXNzaW9uKG9wZXJhbmRzWzFdLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtvcGVyYXRvcjogbm9kZUxvY2F0aW9uKG9wZXJhdG9yTm9kZSwgZmlsZW5hbWUsIHNvdXJjZSl9KSwgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy9vcGVyYXRvcnMuanNcIikuQWRhcHRlZE9wZXJhdGlvbn0gKi8gKGphdmFCaW5hcnlPcGVyYXRpb25zLmdldChvcGVyYXRvcikpKVxuXG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHNlbWFudGljKSlcbiAgfVxuXG4gIGlmIChub2RlLm5hbWUgPT0gXCJNZXRob2RJbnZvY2F0aW9uXCIpIHtcbiAgICBpZiAoaXNFcXVhbHNJbnZvY2F0aW9uKG5vZGUsIHNvdXJjZSkpIHtcbiAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiTWV0aG9kTmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgICByZXR1cm4gY29udmVydFN0cmluZ0VxdWFsaXR5KG5vZGUsIGZhbHNlLCBsb2NhdGlvbiwgbm9kZUxvY2F0aW9uKG1ldGhvZE5hbWUsIGZpbGVuYW1lLCBzb3VyY2UpLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH1cblxuICAgIGNvbnN0IHVuc3VwcG9ydGVkUmVjZWl2ZXIgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkuZmluZCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJNZXRob2ROYW1lXCIgJiYgY2hpbGQubmFtZSAhPSBcIkFyZ3VtZW50TGlzdFwiKVxuXG4gICAgaWYgKHVuc3VwcG9ydGVkUmVjZWl2ZXIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtZXRob2QgaW52b2NhdGlvbiByZWNlaXZlclwiLCBub2RlTG9jYXRpb24odW5zdXBwb3J0ZWRSZWNlaXZlciwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgICBjb25zdCBtZXRob2ROYW1lID0gcmVxdWlyZWRDaGlsZChub2RlLCBcIk1ldGhvZE5hbWVcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhcmd1bWVudExpc3QgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgY29uc3QgYXJndW1lbnROb2RlcyA9IHN0cnVjdHVyYWxDaGlsZHJlbihhcmd1bWVudExpc3QpXG4gICAgY29uc3QgdW5zdXBwb3J0ZWRBcmd1bWVudCA9IGFyZ3VtZW50Tm9kZXMuZmluZCgoY2hpbGQpID0+ICFpc1N1cHBvcnRlZEV4cHJlc3Npb25Ob2RlKGNoaWxkKSlcblxuICAgIGlmICh1bnN1cHBvcnRlZEFyZ3VtZW50KSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBtZXRob2QgYXJndW1lbnQgJHt1bnN1cHBvcnRlZEFyZ3VtZW50Lm5hbWV9YCwgbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkQXJndW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgY29uc3QgYXJndW1lbnRzXyA9IGFyZ3VtZW50Tm9kZXMubWFwKChjaGlsZCkgPT4gY29udmVydEV4cHJlc3Npb24oY2hpbGQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2FyZ3VtZW50czogYXJndW1lbnRzXywgY2FsbGVlOiBub2RlVGV4dChtZXRob2ROYW1lLCBzb3VyY2UpLCBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJDYWxsRXhwcmVzc2lvblwiKSwgbG9jYXRpb259LCB7XG4gICAgICBjYWxsZWU6IG5vZGVMb2NhdGlvbihtZXRob2ROYW1lLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIG5vZGUubmFtZSwgbG9jYXRpb24pXG59XG5cbi8qKlxuICogQ2hlY2tzIHRoZSBvbmUgcGFyc2VyLW5hdGl2ZSBKYXZhIHN0cmluZyBlcXVhbGl0eSBpbnZvY2F0aW9uIGZvcm0uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIE1ldGhvZCBpbnZvY2F0aW9uIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGludm9jYXRpb24gc3BlbGxzIGAuZXF1YWxzYCB3aXRoIGEgcmVjZWl2ZXIuXG4gKi9cbmZ1bmN0aW9uIGlzRXF1YWxzSW52b2NhdGlvbihub2RlLCBzb3VyY2UpIHtcbiAgY29uc3QgbWV0aG9kTmFtZSA9IG5vZGUuZ2V0Q2hpbGQoXCJNZXRob2ROYW1lXCIpXG4gIGNvbnN0IHJlY2VpdmVycyA9IHN0cnVjdHVyYWxDaGlsZHJlbihub2RlKS5maWx0ZXIoKGNoaWxkKSA9PiBjaGlsZC5uYW1lICE9IFwiTWV0aG9kTmFtZVwiICYmIGNoaWxkLm5hbWUgIT0gXCJBcmd1bWVudExpc3RcIilcblxuICByZXR1cm4gbWV0aG9kTmFtZSAhPSBudWxsICYmIG5vZGVUZXh0KG1ldGhvZE5hbWUsIHNvdXJjZSkgPT0gXCJlcXVhbHNcIiAmJiByZWNlaXZlcnMubGVuZ3RoID09IDFcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBKYXZhIGAuZXF1YWxzYCBvciBpdHMgZGlyZWN0bHkgbmVnYXRlZCBmb3JtIHdpdGhvdXQgc291cmNlLXRleHQgaW5mZXJlbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBQYXJzZXIgbWV0aG9kIGludm9jYXRpb24uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG5lZ2F0ZWQgLSBXaGV0aGVyIGEgcGFyc2VyLW93bmVkIHVuYXJ5IG5vdCB3cmFwcyB0aGUgaW52b2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gV2hvbGUgZXF1YWxpdHkgZXhwcmVzc2lvbiBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IG9wZXJhdG9yTG9jYXRpb24gLSBQYXJzZXItb3duZWQgb3BlcmF0b3IvbWV0aG9kIGxvY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBBZGFwdGVkIGVxdWFsaXR5IGV4cHJlc3Npb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRTdHJpbmdFcXVhbGl0eShub2RlLCBuZWdhdGVkLCBsb2NhdGlvbiwgb3BlcmF0b3JMb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBhcmd1bWVudExpc3QgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFyZ3VtZW50c18gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXJndW1lbnRMaXN0KVxuICBjb25zdCByZWNlaXZlcnMgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQubmFtZSAhPSBcIk1ldGhvZE5hbWVcIiAmJiBjaGlsZC5uYW1lICE9IFwiQXJndW1lbnRMaXN0XCIpXG4gIGNvbnN0IHVuc3VwcG9ydGVkQXJndW1lbnQgPSBhcmd1bWVudHNfLmZpbmQoKGNoaWxkKSA9PiAhaXNTdXBwb3J0ZWRFeHByZXNzaW9uTm9kZShjaGlsZCkpXG5cbiAgaWYgKHJlY2VpdmVycy5sZW5ndGggIT0gMSB8fCBhcmd1bWVudHNfLmxlbmd0aCAhPSAxIHx8IHVuc3VwcG9ydGVkQXJndW1lbnQpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwic3RyaW5nIGVxdWFscyBpbnZvY2F0aW9uXCIsIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24+fSAqL1xuICBjb25zdCByYW5nZXMgPSB7b3BlcmF0b3I6IG9wZXJhdG9yTG9jYXRpb259XG5cbiAgaWYgKG5lZ2F0ZWQpIHtcbiAgICByYW5nZXMuZXF1YWxpdHlPcGVyYXRvciA9IG5vZGVMb2NhdGlvbihyZXF1aXJlZENoaWxkKG5vZGUsIFwiTWV0aG9kTmFtZVwiLCBmaWxlbmFtZSwgc291cmNlKSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfVxuXG4gIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAga2luZDogXCJCaW5hcnlFeHByZXNzaW9uXCIsXG4gICAgbGVmdDogY29udmVydEV4cHJlc3Npb24ocmVjZWl2ZXJzWzBdLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBsb2NhdGlvbixcbiAgICByaWdodDogY29udmVydEV4cHJlc3Npb24oYXJndW1lbnRzX1swXSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgfSwgcmFuZ2VzKSwgbmVnYXRlZCA/IFwiU3RyaW5nTm90RXF1YWxcIiA6IFwiU3RyaW5nRXF1YWxcIilcblxuICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgTGV6ZXIgbm9kZSBpcyBpbiB0aGUgZXhwcmVzc2lvbiBzdWJzZXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIEphdmEgc3ludGF4IG5vZGUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbm9kZSBpcyBzdXBwb3J0ZWQuXG4gKi9cbmZ1bmN0aW9uIGlzU3VwcG9ydGVkRXhwcmVzc2lvbk5vZGUobm9kZSkge1xuICByZXR1cm4gW1xuICAgIFwiSWRlbnRpZmllclwiLFxuICAgIFwiSW50ZWdlckxpdGVyYWxcIixcbiAgICBcIkJvb2xlYW5MaXRlcmFsXCIsXG4gICAgXCJTdHJpbmdMaXRlcmFsXCIsXG4gICAgXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICBcIk1ldGhvZEludm9jYXRpb25cIixcbiAgICBcIlBhcmVudGhlc2l6ZWRFeHByZXNzaW9uXCJcbiAgXS5pbmNsdWRlcyhub2RlLm5hbWUpXG59XG5cbi8qKlxuICogQXBwbGllcyBKYXZhIFVuaWNvZGUgdHJhbnNsYXRpb24gYmVmb3JlIHRva2VuLWxldmVsIHN0cmluZyBlc2NhcGUgZGVjb2RpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gbGl0ZXJhbCAtIFBhcnNlci1jb25maXJtZWQgSmF2YSBzdHJpbmcgbGl0ZXJhbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gTGl0ZXJhbCBzb3VyY2UgbG9jYXRpb24uXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBVbmljb2RlLXRyYW5zbGF0ZWQgbGl0ZXJhbC5cbiAqL1xuZnVuY3Rpb24gdHJhbnNsYXRlVW5pY29kZUVzY2FwZXMobGl0ZXJhbCwgbG9jYXRpb24pIHtcbiAgbGV0IHRyYW5zbGF0ZWQgPSBcIlwiXG4gIGxldCBjb25zZWN1dGl2ZUJhY2tzbGFzaGVzID0gMFxuICBsZXQgcHJldmlvdXNXYXNVbmljb2RlRXNjYXBlID0gZmFsc2VcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbGl0ZXJhbC5sZW5ndGg7IGluZGV4KyspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSBsaXRlcmFsW2luZGV4XVxuICAgIGNvbnN0IGVsaWdpYmxlID0gY2hhcmFjdGVyID09IFwiXFxcXFwiICYmIChwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgfHwgY29uc2VjdXRpdmVCYWNrc2xhc2hlcyAlIDIgPT0gMClcblxuICAgIGlmIChlbGlnaWJsZSAmJiBsaXRlcmFsW2luZGV4ICsgMV0gPT0gXCJ1XCIpIHtcbiAgICAgIGxldCBkaWdpdHNTdGFydCA9IGluZGV4ICsgMlxuXG4gICAgICB3aGlsZSAobGl0ZXJhbFtkaWdpdHNTdGFydF0gPT0gXCJ1XCIpIGRpZ2l0c1N0YXJ0KytcblxuICAgICAgY29uc3QgaGV4YWRlY2ltYWwgPSBsaXRlcmFsLnNsaWNlKGRpZ2l0c1N0YXJ0LCBkaWdpdHNTdGFydCArIDQpXG4gICAgICBjb25zdCBpc0hleGFkZWNpbWFsID0gaGV4YWRlY2ltYWwubGVuZ3RoID09IDQgJiYgWy4uLmhleGFkZWNpbWFsXS5ldmVyeSgoZGlnaXQpID0+XG4gICAgICAgIChkaWdpdCA+PSBcIjBcIiAmJiBkaWdpdCA8PSBcIjlcIikgfHwgKGRpZ2l0ID49IFwiQVwiICYmIGRpZ2l0IDw9IFwiRlwiKSB8fCAoZGlnaXQgPj0gXCJhXCIgJiYgZGlnaXQgPD0gXCJmXCIpXG4gICAgICApXG5cbiAgICAgIGlmICghaXNIZXhhZGVjaW1hbCkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIHN0cmluZyBlc2NhcGVcIiwgbG9jYXRpb24pXG5cbiAgICAgIGNvbnN0IHRyYW5zbGF0ZWRDaGFyYWN0ZXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKE51bWJlci5wYXJzZUludChoZXhhZGVjaW1hbCwgMTYpKVxuXG4gICAgICB0cmFuc2xhdGVkICs9IHRyYW5zbGF0ZWRDaGFyYWN0ZXJcbiAgICAgIGNvbnNlY3V0aXZlQmFja3NsYXNoZXMgPSB0cmFuc2xhdGVkQ2hhcmFjdGVyID09IFwiXFxcXFwiID8gY29uc2VjdXRpdmVCYWNrc2xhc2hlcyArIDEgOiAwXG4gICAgICBwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgPSB0cnVlXG4gICAgICBpbmRleCA9IGRpZ2l0c1N0YXJ0ICsgM1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICB0cmFuc2xhdGVkICs9IGNoYXJhY3RlclxuICAgIGNvbnNlY3V0aXZlQmFja3NsYXNoZXMgPSBjaGFyYWN0ZXIgPT0gXCJcXFxcXCIgPyBjb25zZWN1dGl2ZUJhY2tzbGFzaGVzICsgMSA6IDBcbiAgICBwcmV2aW91c1dhc1VuaWNvZGVFc2NhcGUgPSBmYWxzZVxuICB9XG5cbiAgcmV0dXJuIHRyYW5zbGF0ZWRcbn1cblxuLyoqXG4gKiBEZWNvZGVzIHRoZSBhY2NlcHRlZCBlc2NhcGVzIGZyb20gb25lIHBhcnNlci1jb25maXJtZWQgSmF2YSBzdHJpbmcgbGl0ZXJhbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gSmF2YSBTdHJpbmdMaXRlcmFsIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3N0cmluZ30gRGVjb2RlZCBVbmljb2RlIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZGVjb2RlU3RyaW5nTGl0ZXJhbChub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGxpdGVyYWwgPSB0cmFuc2xhdGVVbmljb2RlRXNjYXBlcyhub2RlVGV4dChub2RlLCBzb3VyY2UpLCBsb2NhdGlvbilcbiAgbGV0IHZhbHVlID0gXCJcIlxuXG4gIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPCBsaXRlcmFsLmxlbmd0aCAtIDE7IGluZGV4KyspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSBsaXRlcmFsW2luZGV4XVxuXG4gICAgaWYgKGNoYXJhY3RlciA9PSBcIlxcXCJcIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXG5cIiB8fCBjaGFyYWN0ZXIgPT0gXCJcXHJcIikge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImludmFsaWQgc3RyaW5nIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgaWYgKGNoYXJhY3RlciAhPSBcIlxcXFxcIikge1xuICAgICAgdmFsdWUgKz0gY2hhcmFjdGVyXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGlmIChpbmRleCArIDEgPj0gbGl0ZXJhbC5sZW5ndGggLSAxKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiaW52YWxpZCBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcblxuICAgIGNvbnN0IGVzY2FwZWQgPSBsaXRlcmFsWysraW5kZXhdXG4gICAgY29uc3Qgc2ltcGxlID0gc2ltcGxlU3RyaW5nRXNjYXBlc1tlc2NhcGVkXVxuXG4gICAgaWYgKHNpbXBsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YWx1ZSArPSBzaW1wbGVcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgaWYgKGVzY2FwZWQgPj0gXCIwXCIgJiYgZXNjYXBlZCA8PSBcIjdcIikge1xuICAgICAgbGV0IG9jdGFsID0gZXNjYXBlZFxuICAgICAgY29uc3QgbWF4aW11bUxlbmd0aCA9IGVzY2FwZWQgPD0gXCIzXCIgPyAzIDogMlxuXG4gICAgICB3aGlsZSAob2N0YWwubGVuZ3RoIDwgbWF4aW11bUxlbmd0aCAmJiBsaXRlcmFsW2luZGV4ICsgMV0gPj0gXCIwXCIgJiYgbGl0ZXJhbFtpbmRleCArIDFdIDw9IFwiN1wiKSB7XG4gICAgICAgIG9jdGFsICs9IGxpdGVyYWxbKytpbmRleF1cbiAgICAgIH1cblxuICAgICAgdmFsdWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShOdW1iZXIucGFyc2VJbnQob2N0YWwsIDgpKVxuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwidW5zdXBwb3J0ZWQgc3RyaW5nIGVzY2FwZVwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGlmICghaGFzT25seVVuaWNvZGVTY2FsYXJzKHZhbHVlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImludmFsaWQgVW5pY29kZSBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcblxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgZXhwbGljaXQgSmF2YSByZXR1cm4gc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEphdmEgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5SZXR1cm5TdGF0ZW1lbnR9IFNlbWFudGljIHJldHVybi5cbiAqL1xuZnVuY3Rpb24gY29udmVydFJldHVybihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24oc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChzdGF0ZW1lbnQubmFtZSAhPSBcIlJldHVyblN0YXRlbWVudFwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIHN0YXRlbWVudC5uYW1lLCBsb2NhdGlvbilcblxuICBjb25zdCBleHByZXNzaW9uTm9kZXMgPSBkaXJlY3RDaGlsZHJlbihzdGF0ZW1lbnQpLmZpbHRlcigoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJyZXR1cm5cIiAmJiBjaGlsZC5uYW1lICE9IFwiO1wiKVxuICBjb25zdCBleHByZXNzaW9uID0gZXhwcmVzc2lvbk5vZGVzLmxlbmd0aCA9PSAxID8gZXhwcmVzc2lvbk5vZGVzWzBdIDogdW5kZWZpbmVkXG5cbiAgaWYgKCFleHByZXNzaW9uKSB7XG4gICAgY29uc3QgdW5zdXBwb3J0ZWQgPSBleHByZXNzaW9uTm9kZXNbMF1cblxuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcbiAgICAgIFwiamF2YVwiLFxuICAgICAgdW5zdXBwb3J0ZWQ/Lm5hbWUgPz8gXCJlbXB0eSByZXR1cm5cIixcbiAgICAgIHVuc3VwcG9ydGVkID8gbm9kZUxvY2F0aW9uKHVuc3VwcG9ydGVkLCBmaWxlbmFtZSwgc291cmNlKSA6IGxvY2F0aW9uXG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihleHByZXNzaW9uLCBmaWxlbmFtZSwgc291cmNlKSwga2luZDogXCJSZXR1cm5TdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIEphdmEgbG9jYWwgZGVjbGFyYXRpb24gb3IgYXNzaWdubWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBzdGF0ZW1lbnQgLSBKYXZhIHN0YXRlbWVudC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuTG9jYWxTdGF0ZW1lbnR9IFNlbWFudGljIGxvY2FsIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiTG9jYWxWYXJpYWJsZURlY2xhcmF0aW9uXCIpIHtcbiAgICBjb25zdCBkZWNsYXJhdG9ycyA9IHN0YXRlbWVudC5nZXRDaGlsZHJlbihcIlZhcmlhYmxlRGVjbGFyYXRvclwiKVxuICAgIGNvbnN0IHR5cGVOb2RlID0gZGVjbGFyYXRpb25UeXBlKHN0YXRlbWVudClcbiAgICBjb25zdCB2YXJOb2RlID0gc3RhdGVtZW50LmdldENoaWxkKFwidmFyXCIpXG4gICAgY29uc3QgbW9kaWZpZXJzID0gc3RhdGVtZW50LmdldENoaWxkKFwiTW9kaWZpZXJzXCIpXG4gICAgY29uc3QgbW9kaWZpZXJDaGlsZHJlbiA9IG1vZGlmaWVycyA/IHN0cnVjdHVyYWxDaGlsZHJlbihtb2RpZmllcnMpIDogW11cblxuICAgIGlmICh2YXJOb2RlKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwidmFyIGxvY2FsIGRlY2xhcmF0aW9uXCIsIG5vZGVMb2NhdGlvbih2YXJOb2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICBpZiAoZGVjbGFyYXRvcnMubGVuZ3RoICE9IDEpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtdWx0aXBsZSBsb2NhbCBkZWNsYXJhdG9yc1wiLCBsb2NhdGlvbilcbiAgICBpZiAoIXR5cGVOb2RlIHx8IHR5cGVOb2RlLm5hbWUgPT0gXCJBcnJheVR5cGVcIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIGxvY2FsIHR5cGVcIiwgbG9jYXRpb24pXG4gICAgaWYgKG1vZGlmaWVyQ2hpbGRyZW4uc29tZSgoY2hpbGQpID0+IGNoaWxkLm5hbWUgIT0gXCJmaW5hbFwiKSB8fCBtb2RpZmllckNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBsb2NhbCBtb2RpZmllcnNcIiwgbW9kaWZpZXJzID8gbm9kZUxvY2F0aW9uKG1vZGlmaWVycywgZmlsZW5hbWUsIHNvdXJjZSkgOiBsb2NhdGlvbilcbiAgICB9XG5cbiAgICBjb25zdCBkZWNsYXJhdG9yID0gZGVjbGFyYXRvcnNbMF1cbiAgICBjb25zdCBkZWZpbml0aW9uID0gcmVxdWlyZWRDaGlsZChkZWNsYXJhdG9yLCBcIkRlZmluaXRpb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBhc3NpZ25tZW50ID0gZGVjbGFyYXRvci5nZXRDaGlsZChcIkFzc2lnbk9wXCIpXG4gICAgY29uc3QgZGltZW5zaW9ucyA9IGRlY2xhcmF0b3IuZ2V0Q2hpbGRyZW4oXCJEaW1lbnNpb25cIilcbiAgICBjb25zdCBpbml0aWFsaXplck5vZGVzID0gZGlyZWN0Q2hpbGRyZW4oZGVjbGFyYXRvcikuZmlsdGVyKChjaGlsZCkgPT4gY2hpbGQubmFtZSAhPSBcIkRlZmluaXRpb25cIiAmJiBjaGlsZC5uYW1lICE9IFwiQXNzaWduT3BcIilcblxuICAgIGlmIChkaW1lbnNpb25zLmxlbmd0aCA+IDApIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJhcnJheSBsb2NhbCBkZWNsYXJhdGlvblwiLCBub2RlTG9jYXRpb24oZGVjbGFyYXRvciwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgaWYgKCFhc3NpZ25tZW50IHx8IG5vZGVUZXh0KGFzc2lnbm1lbnQsIHNvdXJjZSkgIT0gXCI9XCIgfHwgaW5pdGlhbGl6ZXJOb2Rlcy5sZW5ndGggIT0gMSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuaW5pdGlhbGl6ZWQgbG9jYWwgZGVjbGFyYXRpb25cIiwgbm9kZUxvY2F0aW9uKGRlY2xhcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPSBub2RlVGV4dChkZWZpbml0aW9uLCBzb3VyY2UpXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBpbml0aWFsaXplcjogY29udmVydEV4cHJlc3Npb24oaW5pdGlhbGl6ZXJOb2Rlc1swXSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkxvY2FsRGVjbGFyYXRpb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgbXV0YWJsZTogbW9kaWZpZXJDaGlsZHJlbi5sZW5ndGggPT0gMCxcbiAgICAgIG5hbWUsXG4gICAgICB0eXBlOiBjb252ZXJ0VHlwZSh0eXBlTm9kZSwgYExvY2FsICcke25hbWV9J2AsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0sIHtuYW1lOiBub2RlTG9jYXRpb24oZGVmaW5pdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSksIG9wZXJhdG9yOiBub2RlTG9jYXRpb24oYXNzaWdubWVudCwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9XG5cbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiKSB7XG4gICAgY29uc3QgYXNzaWdubWVudCA9IHN0YXRlbWVudC5nZXRDaGlsZChcIkFzc2lnbm1lbnRFeHByZXNzaW9uXCIpXG5cbiAgICBpZiAoIWFzc2lnbm1lbnQpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIGxvY2F0aW9uKVxuXG4gICAgY29uc3QgY2hpbGRyZW4gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXNzaWdubWVudClcbiAgICBjb25zdCBvcGVyYXRvciA9IGFzc2lnbm1lbnQuZ2V0Q2hpbGQoXCJBc3NpZ25PcFwiKVxuICAgIGNvbnN0IHRhcmdldCA9IGNoaWxkcmVuWzBdXG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGNoaWxkcmVuLmF0KC0xKVxuXG4gICAgaWYgKCFvcGVyYXRvciB8fCBub2RlVGV4dChvcGVyYXRvciwgc291cmNlKSAhPSBcIj1cIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcImNvbXBvdW5kIGFzc2lnbm1lbnRcIiwgbm9kZUxvY2F0aW9uKGFzc2lnbm1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIGlmICghdGFyZ2V0IHx8IHRhcmdldC5uYW1lICE9IFwiSWRlbnRpZmllclwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIHRhcmdldD8ubmFtZSA/PyBcImFzc2lnbm1lbnQgdGFyZ2V0XCIsIHRhcmdldCA/IG5vZGVMb2NhdGlvbih0YXJnZXQsIGZpbGVuYW1lLCBzb3VyY2UpIDogbG9jYXRpb24pXG4gICAgaWYgKCFleHByZXNzaW9uIHx8IGV4cHJlc3Npb24gPT0gdGFyZ2V0IHx8IGV4cHJlc3Npb24gPT0gb3BlcmF0b3IpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJhc3NpZ25tZW50IGV4cHJlc3Npb25cIiwgbm9kZUxvY2F0aW9uKGFzc2lnbm1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuXG4gICAgY29uc3QgdGFyZ2V0RXhwcmVzc2lvbiA9IHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksXG4gICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKHRhcmdldCwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBuYW1lOiBub2RlVGV4dCh0YXJnZXQsIHNvdXJjZSlcbiAgICB9LCB7bmFtZTogbm9kZUxvY2F0aW9uKHRhcmdldCwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAgZXhwcmVzc2lvbjogY29udmVydEV4cHJlc3Npb24oZXhwcmVzc2lvbiwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgdGFyZ2V0OiB0YXJnZXRFeHByZXNzaW9uXG4gICAgfSwge29wZXJhdG9yOiBub2RlTG9jYXRpb24ob3BlcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleGhhdXN0aXZlIGRpcmVjdCBKYXZhIGJsb2NrIGNoaWxkLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEphdmEgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IFNlbWFudGljIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFN0YXRlbWVudChzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiUmV0dXJuU3RhdGVtZW50XCIpIHJldHVybiBjb252ZXJ0UmV0dXJuKHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiSWZTdGF0ZW1lbnRcIikgcmV0dXJuIGNvbnZlcnRJZihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChzdGF0ZW1lbnQubmFtZSA9PSBcIkxvY2FsVmFyaWFibGVEZWNsYXJhdGlvblwiKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgaWYgKHN0YXRlbWVudC5uYW1lID09IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiKSB7XG4gICAgaWYgKHN0YXRlbWVudC5nZXRDaGlsZChcIkFzc2lnbm1lbnRFeHByZXNzaW9uXCIpKSByZXR1cm4gY29udmVydExvY2FsU3RhdGVtZW50KHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBpZiAoIXN0YXRlbWVudC5nZXRDaGlsZChcIk1ldGhvZEludm9jYXRpb25cIikpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgc3RhdGVtZW50Lm5hbWUsIG5vZGVMb2NhdGlvbihzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICAgIH1cblxuICAgIHJldHVybiBjb252ZXJ0UHJpbnQoc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuICB9XG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBzdGF0ZW1lbnQubmFtZSwgbm9kZUxvY2F0aW9uKHN0YXRlbWVudCwgZmlsZW5hbWUsIHNvdXJjZSkpXG59XG5cbi8qKlxuICogQ29udmVydHMgZGlyZWN0IHN0cnVjdHVyYWwgY2hpbGRyZW4gb2Ygb25lIEphdmEgYmxvY2sgaW4gc291cmNlIG9yZGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBKYXZhIEJsb2NrIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLkJsb2NrfSBTZW1hbnRpYyBibG9jay5cbiAqL1xuZnVuY3Rpb24gY29udmVydEJsb2NrKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgaWYgKG5vZGUubmFtZSAhPSBcIkJsb2NrXCIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgYGV4cGVjdGVkIGJsb2NrLCByZWNlaXZlZCAke25vZGUubmFtZX1gLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIHtcbiAgICBraW5kOiBcIkJsb2NrXCIsXG4gICAgbG9jYXRpb246IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBzdGF0ZW1lbnRzOiBzdHJ1Y3R1cmFsQ2hpbGRyZW4obm9kZSkubWFwKChzdGF0ZW1lbnQpID0+IGNvbnZlcnRTdGF0ZW1lbnQoc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIGFuIGV4YWN0IEphdmEgc2NhbGFyIHR5cGUgbm9kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlIHwgbnVsbH0gc291cmNlVHlwZSAtIEphdmEgdHlwZSBub2RlLlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBUeXBlZCBzdWJqZWN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBTb3VyY2UgbG9jYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IFNlbWFudGljIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUeXBlKHNvdXJjZVR5cGUsIHN1YmplY3QsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGlmICghc291cmNlVHlwZSkgcmV0dXJuIG1pc3NpbmdUeXBlKFwiamF2YVwiLCBzdWJqZWN0LCBsb2NhdGlvbilcbiAgaWYgKCFbXCJQcmltaXRpdmVUeXBlXCIsIFwiVHlwZU5hbWVcIiwgXCJTY29wZWRUeXBlTmFtZVwiXS5pbmNsdWRlcyhzb3VyY2VUeXBlLm5hbWUpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInVuc3VwcG9ydGVkIHNjYWxhciB0eXBlXCIsIGxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgdHlwZSA9IHNvdXJjZVNjYWxhclR5cGUoXCJqYXZhXCIsIG5vZGVUZXh0KHNvdXJjZVR5cGUsIHNvdXJjZSksIG5vZGVMb2NhdGlvbihzb3VyY2VUeXBlLCBmaWxlbmFtZSwgc291cmNlKSlcblxuICBpZiAoIXR5cGUpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJ1bnN1cHBvcnRlZCBzY2FsYXIgdHlwZVwiLCBub2RlTG9jYXRpb24oc291cmNlVHlwZSwgbG9jYXRpb24uZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgcmV0dXJuIHR5cGVcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkaXJlY3QgSmF2YSBkZWNsYXJhdGlvbiB0eXBlIG5vZGUgc3VwcG9ydGVkIGJ5IHNjYWxhciBjb252ZXJzaW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBEZWNsYXJhdGlvbiBub2RlLlxuICogQHJldHVybnMge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZSB8IG51bGx9IFR5cGUgc3ludGF4IG5vZGUuXG4gKi9cbmZ1bmN0aW9uIGRlY2xhcmF0aW9uVHlwZShub2RlKSB7XG4gIHJldHVybiBub2RlLmdldENoaWxkKFwiUHJpbWl0aXZlVHlwZVwiKSA/PyBub2RlLmdldENoaWxkKFwiVHlwZU5hbWVcIikgPz8gbm9kZS5nZXRDaGlsZChcIlNjb3BlZFR5cGVOYW1lXCIpXG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIHN1cHBvcnRlZCBKYXZhIGZ1bmN0aW9uIG1ldGhvZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGxlemVyL2NvbW1vblwiKS5TeW50YXhOb2RlfSBub2RlIC0gTWV0aG9kIGRlY2xhcmF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5GdW5jdGlvbkRlY2xhcmF0aW9ufSBTZW1hbnRpYyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEZ1bmN0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgZGVmaW5pdGlvbiA9IHJlcXVpcmVkQ2hpbGQobm9kZSwgXCJEZWZpbml0aW9uXCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IG5hbWUgPSBub2RlVGV4dChkZWZpbml0aW9uLCBzb3VyY2UpXG4gIGNvbnN0IHBhcmFtZXRlcnNOb2RlID0gcmVxdWlyZWRDaGlsZChub2RlLCBcIkZvcm1hbFBhcmFtZXRlcnNcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgcGFyYW1ldGVycyA9IHBhcmFtZXRlcnNOb2RlLmdldENoaWxkcmVuKFwiRm9ybWFsUGFyYW1ldGVyXCIpLm1hcCgocGFyYW1ldGVyKSA9PiB7XG4gICAgY29uc3QgcGFyYW1ldGVyTG9jYXRpb24gPSBub2RlTG9jYXRpb24ocGFyYW1ldGVyLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHBhcmFtZXRlck5hbWVOb2RlID0gcmVxdWlyZWRDaGlsZChwYXJhbWV0ZXIsIFwiRGVmaW5pdGlvblwiLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIGNvbnN0IHBhcmFtZXRlck5hbWUgPSBub2RlVGV4dChwYXJhbWV0ZXJOYW1lTm9kZSwgc291cmNlKVxuXG4gICAgY29uc3Qgc2VtYW50aWNQYXJhbWV0ZXIgPSB7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJQYXJhbWV0ZXJcIiksXG4gICAgICBsb2NhdGlvbjogcGFyYW1ldGVyTG9jYXRpb24sXG4gICAgICBuYW1lOiBwYXJhbWV0ZXJOYW1lLFxuICAgICAgdHlwZTogY29udmVydFR5cGUoZGVjbGFyYXRpb25UeXBlKHBhcmFtZXRlciksIGBQYXJhbWV0ZXIgJyR7cGFyYW1ldGVyTmFtZX0nYCwgcGFyYW1ldGVyTG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoc2VtYW50aWNQYXJhbWV0ZXIsIHtuYW1lOiBub2RlTG9jYXRpb24ocGFyYW1ldGVyTmFtZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbiAgfSlcbiAgY29uc3QgYmxvY2sgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQmxvY2tcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhibG9jaywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgYm9keSxcbiAgICBraW5kOiBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIixcbiAgICBsb2NhdGlvbixcbiAgICBuYW1lLFxuICAgIHBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogY29udmVydFR5cGUoZGVjbGFyYXRpb25UeXBlKG5vZGUpLCBgRnVuY3Rpb24gJyR7bmFtZX0nIHJldHVybmAsIGxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKVxuICB9LCB7bmFtZTogbm9kZUxvY2F0aW9uKGRlZmluaXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZXhpc3RpbmcgZXhhY3QgSmF2YSBpZi9lbHNlIHRlcm1pbmFsIHdpdGggcmVzdHJpY3RlZCBicmFuY2ggcHJlZml4ZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBsZXplci9jb21tb25cIikuU3ludGF4Tm9kZX0gbm9kZSAtIEphdmEgaWYgc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjb25kaXRpb25Db250YWluZXIgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiUGFyZW50aGVzaXplZEV4cHJlc3Npb25cIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgY29uZGl0aW9uTm9kZXMgPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oY29uZGl0aW9uQ29udGFpbmVyKVxuICBjb25zdCBjb25kaXRpb24gPSBjb25kaXRpb25Ob2Rlcy5sZW5ndGggPT0gMSA/IGNvbmRpdGlvbk5vZGVzWzBdIDogdW5kZWZpbmVkXG4gIGNvbnN0IGRpcmVjdCA9IGRpcmVjdENoaWxkcmVuKG5vZGUpXG4gIGNvbnN0IGNvbmRpdGlvbkluZGV4ID0gZGlyZWN0LmZpbmRJbmRleCgoY2hpbGQpID0+IGNoaWxkLm5hbWUgPT0gY29uZGl0aW9uQ29udGFpbmVyLm5hbWUgJiZcbiAgICBjaGlsZC5mcm9tID09IGNvbmRpdGlvbkNvbnRhaW5lci5mcm9tICYmIGNoaWxkLnRvID09IGNvbmRpdGlvbkNvbnRhaW5lci50bylcbiAgY29uc3QgY29uc2VxdWVudE5vZGUgPSBkaXJlY3RbY29uZGl0aW9uSW5kZXggKyAxXVxuICBjb25zdCBhbHRlcm5hdGVOb2RlID0gZGlyZWN0LmF0KC0xKSA9PSBjb25zZXF1ZW50Tm9kZSA/IHVuZGVmaW5lZCA6IGRpcmVjdC5hdCgtMSlcblxuICBpZiAoIWNvbmRpdGlvbiB8fCAhY29uc2VxdWVudE5vZGUgfHwgY29uc2VxdWVudE5vZGUubmFtZSAhPSBcIkJsb2NrXCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiaWYgd2l0aG91dCBibG9jayBjb25zZXF1ZW50XCIsIGxvY2F0aW9uKVxuICB9XG5cbiAgbGV0IGFsdGVybmF0ZVxuXG4gIGlmIChhbHRlcm5hdGVOb2RlPy5uYW1lID09IFwiQmxvY2tcIikgYWx0ZXJuYXRlID0gY29udmVydEJsb2NrKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGVsc2UgaWYgKGFsdGVybmF0ZU5vZGU/Lm5hbWUgPT0gXCJJZlN0YXRlbWVudFwiKSB7XG4gICAgYWx0ZXJuYXRlID0ge1xuICAgICAga2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQmxvY2tcIiksXG4gICAgICBsb2NhdGlvbjogbm9kZUxvY2F0aW9uKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgc3RhdGVtZW50czogW2NvbnZlcnRJZihhbHRlcm5hdGVOb2RlLCBmaWxlbmFtZSwgc291cmNlKV1cbiAgICB9XG4gIH0gZWxzZSBpZiAoYWx0ZXJuYXRlTm9kZSAmJiBhbHRlcm5hdGVOb2RlLm5hbWUgIT0gXCJlbHNlXCIpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIGBpZiBhbHRlcm5hdGUgJHthbHRlcm5hdGVOb2RlLm5hbWV9YCwgbm9kZUxvY2F0aW9uKGFsdGVybmF0ZU5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi4oYWx0ZXJuYXRlID8ge2FsdGVybmF0ZX0gOiB7fSksXG4gICAgY29uZGl0aW9uOiBjb252ZXJ0RXhwcmVzc2lvbihjb25kaXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGNvbnNlcXVlbnQ6IGNvbnZlcnRCbG9jayhjb25zZXF1ZW50Tm9kZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAga2luZDogXCJJZlN0YXRlbWVudFwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBKYXZhJ3Mgc3VwcG9ydGVkIG1haW4gbWV0aG9kLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IG5vZGUgLSBNYWluIG1ldGhvZC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRW50cnlQb2ludH0gU2VtYW50aWMgZW50cnkgcG9pbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRFbnRyeVBvaW50KG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYmxvY2sgPSByZXF1aXJlZENoaWxkKG5vZGUsIFwiQmxvY2tcIiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhibG9jaywgZmlsZW5hbWUsIHNvdXJjZSlcblxuICByZXR1cm4ge2JvZHksIGtpbmQ6IFwiRW50cnlQb2ludFwiLCBsb2NhdGlvbn1cbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBvbmUgc3VwcG9ydGVkIEphdmEgcHJpbnQgc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAbGV6ZXIvY29tbW9uXCIpLlN5bnRheE5vZGV9IHN0YXRlbWVudCAtIEV4cHJlc3Npb24gc3RhdGVtZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5QcmludFN0YXRlbWVudH0gU2VtYW50aWMgcHJpbnQuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRQcmludChzdGF0ZW1lbnQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24oc3RhdGVtZW50LCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGNvbnN0IHByaW50SW52b2NhdGlvbiA9IHN0YXRlbWVudC5nZXRDaGlsZChcIk1ldGhvZEludm9jYXRpb25cIilcblxuICBpZiAoIXByaW50SW52b2NhdGlvbikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcIm1haW4gd2l0aG91dCBTeXN0ZW0ub3V0LnByaW50bG5cIiwgbG9jYXRpb24pXG5cbiAgY29uc3QgZmllbGRBY2Nlc3MgPSBwcmludEludm9jYXRpb24uZ2V0Q2hpbGQoXCJGaWVsZEFjY2Vzc1wiKVxuICBjb25zdCBtZXRob2ROYW1lID0gcHJpbnRJbnZvY2F0aW9uLmdldENoaWxkKFwiTWV0aG9kTmFtZVwiKVxuXG4gIGlmICghZmllbGRBY2Nlc3MgfHwgIW1ldGhvZE5hbWUgfHwgbm9kZVRleHQoZmllbGRBY2Nlc3MsIHNvdXJjZSkgIT0gXCJTeXN0ZW0ub3V0XCIgfHwgbm9kZVRleHQobWV0aG9kTmFtZSwgc291cmNlKSAhPSBcInByaW50bG5cIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJtYWluIHdpdGhvdXQgU3lzdGVtLm91dC5wcmludGxuXCIsIG5vZGVMb2NhdGlvbihwcmludEludm9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgY29uc3QgYXJndW1lbnRMaXN0ID0gcmVxdWlyZWRDaGlsZChwcmludEludm9jYXRpb24sIFwiQXJndW1lbnRMaXN0XCIsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGNvbnN0IGFyZ3VtZW50c18gPSBzdHJ1Y3R1cmFsQ2hpbGRyZW4oYXJndW1lbnRMaXN0KVxuXG4gIGlmIChhcmd1bWVudHNfLmxlbmd0aCAhPSAxKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwiamF2YVwiLCBcInByaW50bG4gd2l0aG91dCBvbmUgc3VwcG9ydGVkIGFyZ3VtZW50XCIsIG5vZGVMb2NhdGlvbihhcmd1bWVudExpc3QsIGZpbGVuYW1lLCBzb3VyY2UpKVxuICB9XG5cbiAgY29uc3QgcHJpbnRMb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihwcmludEludm9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihhcmd1bWVudHNfWzBdLCBmaWxlbmFtZSwgc291cmNlKSwga2luZDogXCJQcmludFN0YXRlbWVudFwiLCBsb2NhdGlvbjogcHJpbnRMb2NhdGlvbn1cbn1cblxuLyoqXG4gKiBQYXJzZXMgSmF2YSBpbnRvIHRoZSBzaGFyZWQgc2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtvYmplY3R9IGlucHV0IC0gUGFyc2VyIGlucHV0LlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LmZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LnNvdXJjZSAtIFNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBTZW1hbnRpYyBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUphdmEoe2ZpbGVuYW1lLCBzb3VyY2V9KSB7XG4gIGNvbnN0IHRyZWUgPSBwYXJzZXIucGFyc2Uoc291cmNlKVxuICBjb25zdCBlcnJvciA9IGRlc2NlbmRhbnRzKHRyZWUudG9wTm9kZSwgXCLimqBcIilbMF1cblxuICBpZiAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgU2VtYW50aWZvbGREaWFnbm9zdGljKHtcbiAgICAgIGNvZGU6IFwiUEFSU0VfRVJST1JcIixcbiAgICAgIGxhbmd1YWdlOiBcImphdmFcIixcbiAgICAgIGxvY2F0aW9uOiBub2RlTG9jYXRpb24oZXJyb3IsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgbWVzc2FnZTogXCJKYXZhIHBhcnNlciByZXBvcnRlZCBpbnZhbGlkIHN5bnRheC5cIlxuICAgIH0pXG4gIH1cblxuICBjb25zdCBtZXRob2RzID0gZGVzY2VuZGFudHModHJlZS50b3BOb2RlLCBcIk1ldGhvZERlY2xhcmF0aW9uXCIpXG4gIGNvbnN0IG1haW5NZXRob2QgPSBtZXRob2RzLmZpbmQoKG1ldGhvZCkgPT4gbm9kZVRleHQocmVxdWlyZWRDaGlsZChtZXRob2QsIFwiRGVmaW5pdGlvblwiLCBmaWxlbmFtZSwgc291cmNlKSwgc291cmNlKSA9PSBcIm1haW5cIilcbiAgY29uc3QgZnVuY3Rpb25NZXRob2RzID0gbWV0aG9kcy5maWx0ZXIoKG1ldGhvZCkgPT4gbWV0aG9kICE9IG1haW5NZXRob2QpXG4gIGNvbnN0IGxvY2F0aW9uID0gbW9kdWxlTG9jYXRpb24oZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAoZnVuY3Rpb25NZXRob2RzLmxlbmd0aCA9PSAwKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJqYXZhXCIsIFwiY2xhc3Mgd2l0aG91dCBhIHNlbWFudGljIGZ1bmN0aW9uXCIsIGxvY2F0aW9uKVxuICBpZiAoIW1haW5NZXRob2QpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChcImphdmFcIiwgXCJjbGFzcyB3aXRob3V0IG1haW5cIiwgbG9jYXRpb24pXG5cbiAgY29uc3QgZnVuY3Rpb25zID0gZnVuY3Rpb25NZXRob2RzLm1hcCgobWV0aG9kKSA9PiBjb252ZXJ0RnVuY3Rpb24obWV0aG9kLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgZW50cnlQb2ludCA9IGNvbnZlcnRFbnRyeVBvaW50KG1haW5NZXRob2QsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgcmV0dXJuIHtlbnRyeVBvaW50LCBmdW5jdGlvbnMsIGtpbmQ6IFwiTW9kdWxlXCIsIGxvY2F0aW9ufVxufVxuIl19
|