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,633 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { parse as parseBabel } from "@babel/parser";
|
|
3
|
+
import { parse as parseComment } from "comment-parser";
|
|
4
|
+
import { missingType, parseFailure, unsupportedSyntax } from "../diagnostic.js";
|
|
5
|
+
import { locationFromOffsets, moduleLocation } from "../semantic/location.js";
|
|
6
|
+
import { withAdaptedOperation } from "../semantic/operators.js";
|
|
7
|
+
import { withParserRanges } from "../semantic/provenance.js";
|
|
8
|
+
import { hasOnlyUnicodeScalars } from "../semantic/scalars.js";
|
|
9
|
+
import { requireSourceScalarType } from "./scalars.js";
|
|
10
|
+
/** @typedef {NonNullable<import("@babel/parser").ParseResult<import("@babel/types").File>["tokens"]>[number]} BabelToken */
|
|
11
|
+
/** @typedef {{byStart: Map<number, BabelToken>, tokens: BabelToken[]}} BabelTokenIndex */
|
|
12
|
+
/** @type {WeakMap<object, BabelTokenIndex>} */
|
|
13
|
+
const nodeTokens = new WeakMap();
|
|
14
|
+
const babelBinaryOperations = new Map([
|
|
15
|
+
["+", "Add"],
|
|
16
|
+
["-", "Subtract"],
|
|
17
|
+
["*", "Multiply"],
|
|
18
|
+
["===", "Equal"],
|
|
19
|
+
["!==", "NotEqual"],
|
|
20
|
+
["<", "LessThan"],
|
|
21
|
+
["<=", "LessThanOrEqual"],
|
|
22
|
+
[">", "GreaterThan"],
|
|
23
|
+
[">=", "GreaterThanOrEqual"]
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* Returns a source location for a Babel node.
|
|
27
|
+
* @param {import("@babel/types").Node} node - Babel node.
|
|
28
|
+
* @param {string} filename - Source filename.
|
|
29
|
+
* @param {string} source - Complete source.
|
|
30
|
+
* @returns {import("../semantic/types.js").SourceLocation} Normalized location.
|
|
31
|
+
*/
|
|
32
|
+
function nodeLocation(node, filename, source) {
|
|
33
|
+
if (typeof node.start != "number" || typeof node.end != "number") {
|
|
34
|
+
throw new Error(`Babel omitted source offsets for ${node.type}.`);
|
|
35
|
+
}
|
|
36
|
+
return locationFromOffsets(filename, source, node.start, node.end);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns the identifier spelling rather than a trailing TypeScript annotation.
|
|
40
|
+
* @param {import("@babel/types").Identifier} node - Parser identifier.
|
|
41
|
+
* @param {string} filename - Source filename.
|
|
42
|
+
* @param {string} source - Complete source.
|
|
43
|
+
* @returns {import("../semantic/types.js").SourceLocation} Identifier location.
|
|
44
|
+
*/
|
|
45
|
+
function identifierLocation(node, filename, source) {
|
|
46
|
+
if (typeof node.start != "number")
|
|
47
|
+
throw new Error("Babel omitted an identifier start offset.");
|
|
48
|
+
const token = nodeTokens.get(node)?.byStart.get(node.start);
|
|
49
|
+
if (!token || token.type.label != "name")
|
|
50
|
+
throw new Error(`Babel omitted the identifier token for '${node.name}'.`);
|
|
51
|
+
return locationFromOffsets(filename, source, token.start, token.end);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Locates one Babel token within parser-node boundaries.
|
|
55
|
+
* @param {import("@babel/types").Node} owner - Token-owning parser node.
|
|
56
|
+
* @param {string} value - Exact token spelling.
|
|
57
|
+
* @param {number} startOffset - Inclusive boundary.
|
|
58
|
+
* @param {number} endOffset - Exclusive boundary.
|
|
59
|
+
* @param {string} filename - Source filename.
|
|
60
|
+
* @param {string} source - Complete source.
|
|
61
|
+
* @returns {import("../semantic/types.js").SourceLocation} Exact token location.
|
|
62
|
+
*/
|
|
63
|
+
function tokenLocation(owner, value, startOffset, endOffset, filename, source) {
|
|
64
|
+
const tokens = nodeTokens.get(owner)?.tokens ?? [];
|
|
65
|
+
let low = 0;
|
|
66
|
+
let high = tokens.length;
|
|
67
|
+
while (low < high) {
|
|
68
|
+
const middle = Math.floor((low + high) / 2);
|
|
69
|
+
if (tokens[middle].start < startOffset)
|
|
70
|
+
low = middle + 1;
|
|
71
|
+
else
|
|
72
|
+
high = middle;
|
|
73
|
+
}
|
|
74
|
+
let token;
|
|
75
|
+
for (let index = low; index < tokens.length && tokens[index].start < endOffset; index++) {
|
|
76
|
+
const candidate = tokens[index];
|
|
77
|
+
if (candidate.end <= endOffset && (candidate.value == value || candidate.type.label == value)) {
|
|
78
|
+
token = candidate;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (!token)
|
|
83
|
+
throw new Error(`Babel omitted token '${value}' between ${startOffset} and ${endOffset}.`);
|
|
84
|
+
return locationFromOffsets(filename, source, token.start, token.end);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Locates a comment-parser token inside a Babel-owned doc comment.
|
|
88
|
+
* @param {import("@babel/types").CommentBlock} comment - Babel doc comment.
|
|
89
|
+
* @param {import("comment-parser").Spec} tag - Parsed doc tag.
|
|
90
|
+
* @param {"name" | "type"} field - Token field.
|
|
91
|
+
* @param {string} filename - Source filename.
|
|
92
|
+
* @param {string} source - Complete source.
|
|
93
|
+
* @returns {import("../semantic/types.js").SourceLocation} Exact token location.
|
|
94
|
+
*/
|
|
95
|
+
function commentTagLocation(comment, tag, field, filename, source) {
|
|
96
|
+
const line = tag.source[0];
|
|
97
|
+
if (typeof comment.start != "number" || !line)
|
|
98
|
+
throw new Error(`Comment parser omitted the @${tag.tag} source token.`);
|
|
99
|
+
let lineStart = comment.start;
|
|
100
|
+
for (let lineNumber = 0; lineNumber < line.number; lineNumber++) {
|
|
101
|
+
while (lineStart < source.length && source[lineStart] != "\r" && source[lineStart] != "\n")
|
|
102
|
+
lineStart++;
|
|
103
|
+
if (source[lineStart] == "\r" && source[lineStart + 1] == "\n")
|
|
104
|
+
lineStart += 2;
|
|
105
|
+
else
|
|
106
|
+
lineStart++;
|
|
107
|
+
}
|
|
108
|
+
const orderedFields = ["start", "delimiter", "postDelimiter", "tag", "postTag", "type", "postType", "name"];
|
|
109
|
+
const fieldIndex = orderedFields.indexOf(field);
|
|
110
|
+
const start = lineStart + orderedFields.slice(0, fieldIndex).reduce((length, key) => length + line.tokens[ /** @type {keyof typeof line.tokens} */(key)].length, 0);
|
|
111
|
+
const token = line.tokens[field];
|
|
112
|
+
return locationFromOffsets(filename, source, start, start + token.length);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Converts a supported Babel expression.
|
|
116
|
+
* @param {import("@babel/types").Expression} node - Babel expression.
|
|
117
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
118
|
+
* @param {string} filename - Source filename.
|
|
119
|
+
* @param {string} source - Complete source.
|
|
120
|
+
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
121
|
+
*/
|
|
122
|
+
function convertExpression(node, language, filename, source) {
|
|
123
|
+
const location = nodeLocation(node, filename, source);
|
|
124
|
+
if (node.type == "Identifier") {
|
|
125
|
+
return withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location, name: node.name }, {
|
|
126
|
+
name: identifierLocation(node, filename, source)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (node.type == "NumericLiteral") {
|
|
130
|
+
if (!Number.isSafeInteger(node.value))
|
|
131
|
+
return unsupportedSyntax(language, "non-safe integer literal", location);
|
|
132
|
+
return withParserRanges({ kind: /** @type {const} */ ("IntegerLiteral"), location, value: node.value }, { literal: location });
|
|
133
|
+
}
|
|
134
|
+
if (node.type == "BooleanLiteral") {
|
|
135
|
+
if (typeof node.value != "boolean")
|
|
136
|
+
return unsupportedSyntax(language, "invalid boolean literal value", location);
|
|
137
|
+
return withParserRanges({ kind: /** @type {const} */ ("BooleanLiteral"), location, value: node.value }, { literal: location });
|
|
138
|
+
}
|
|
139
|
+
if (node.type == "StringLiteral") {
|
|
140
|
+
if (typeof node.value != "string" || !hasOnlyUnicodeScalars(node.value)) {
|
|
141
|
+
return unsupportedSyntax(language, "invalid Unicode string literal", location);
|
|
142
|
+
}
|
|
143
|
+
return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: node.value }, { literal: location });
|
|
144
|
+
}
|
|
145
|
+
if (node.type == "TemplateLiteral") {
|
|
146
|
+
if (node.expressions.length > 0)
|
|
147
|
+
return unsupportedSyntax(language, "interpolated string", location);
|
|
148
|
+
const quasi = node.quasis[0];
|
|
149
|
+
if (typeof quasi.value.cooked != "string" || !hasOnlyUnicodeScalars(quasi.value.cooked)) {
|
|
150
|
+
return unsupportedSyntax(language, "invalid Unicode string literal", location);
|
|
151
|
+
}
|
|
152
|
+
return withParserRanges({ kind: /** @type {const} */ ("StringLiteral"), location, value: quasi.value.cooked }, { literal: location });
|
|
153
|
+
}
|
|
154
|
+
if (node.type == "UnaryExpression" && ["!", "-"].includes(node.operator)) {
|
|
155
|
+
const operand = convertExpression(node.argument, language, filename, source);
|
|
156
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
157
|
+
kind: "UnaryExpression",
|
|
158
|
+
location,
|
|
159
|
+
operand
|
|
160
|
+
}, {
|
|
161
|
+
operator: tokenLocation(node, node.operator, node.start ?? 0, node.argument.start ?? node.end ?? source.length, filename, source)
|
|
162
|
+
}), node.operator == "!" ? "Not" : "Negate");
|
|
163
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
164
|
+
}
|
|
165
|
+
if (node.type == "LogicalExpression" && ["&&", "||"].includes(node.operator)) {
|
|
166
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
167
|
+
kind: "BinaryExpression",
|
|
168
|
+
left: convertExpression(node.left, language, filename, source),
|
|
169
|
+
location,
|
|
170
|
+
right: convertExpression(node.right, language, filename, source)
|
|
171
|
+
}, {
|
|
172
|
+
operator: tokenLocation(node, node.operator, node.left.end ?? node.start ?? 0, node.right.start ?? node.end ?? source.length, filename, source)
|
|
173
|
+
}), node.operator == "&&" ? "And" : "Or");
|
|
174
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
175
|
+
}
|
|
176
|
+
if (node.type == "BinaryExpression" && babelBinaryOperations.has(node.operator)) {
|
|
177
|
+
if (node.left.type == "PrivateName")
|
|
178
|
+
unsupportedSyntax(language, node.left.type, location);
|
|
179
|
+
const left = convertExpression(node.left, language, filename, source);
|
|
180
|
+
const right = convertExpression(node.right, language, filename, source);
|
|
181
|
+
const semantic = withAdaptedOperation(withParserRanges({
|
|
182
|
+
kind: "BinaryExpression",
|
|
183
|
+
left,
|
|
184
|
+
location,
|
|
185
|
+
right
|
|
186
|
+
}, {
|
|
187
|
+
operator: tokenLocation(node, node.operator, node.left.end ?? node.start ?? 0, node.right.start ?? node.end ?? source.length, filename, source)
|
|
188
|
+
}), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (babelBinaryOperations.get(node.operator)));
|
|
189
|
+
return /** @type {import("../semantic/types.js").Expression} */ ( /** @type {unknown} */(semantic));
|
|
190
|
+
}
|
|
191
|
+
if (node.type == "BinaryExpression" && ["==", "!="].includes(node.operator)) {
|
|
192
|
+
return unsupportedSyntax(language, `coercive equality ${node.operator}`, location);
|
|
193
|
+
}
|
|
194
|
+
if (node.type == "CallExpression" && node.callee.type == "Identifier") {
|
|
195
|
+
const arguments_ = node.arguments.map((argument) => {
|
|
196
|
+
if (argument.type == "SpreadElement" || argument.type == "ArgumentPlaceholder") {
|
|
197
|
+
return unsupportedSyntax(language, argument.type, nodeLocation(argument, filename, source));
|
|
198
|
+
}
|
|
199
|
+
return convertExpression(argument, language, filename, source);
|
|
200
|
+
});
|
|
201
|
+
return withParserRanges({ arguments: arguments_, callee: node.callee.name, kind: /** @type {const} */ ("CallExpression"), location }, {
|
|
202
|
+
callee: identifierLocation(node.callee, filename, source)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return unsupportedSyntax(language, node.type, location);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Converts a supported return statement.
|
|
209
|
+
* @param {import("@babel/types").Statement} node - Babel statement.
|
|
210
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
211
|
+
* @param {string} filename - Source filename.
|
|
212
|
+
* @param {string} source - Complete source.
|
|
213
|
+
* @returns {import("../semantic/types.js").ReturnStatement} Semantic return.
|
|
214
|
+
*/
|
|
215
|
+
function convertReturn(node, language, filename, source) {
|
|
216
|
+
const location = nodeLocation(node, filename, source);
|
|
217
|
+
if (node.type != "ReturnStatement" || !node.argument)
|
|
218
|
+
return unsupportedSyntax(language, node.type, location);
|
|
219
|
+
return { expression: convertExpression(node.argument, language, filename, source), kind: "ReturnStatement", location };
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Converts one supported local declaration or assignment.
|
|
223
|
+
* @param {import("@babel/types").Statement} node - Babel statement.
|
|
224
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
225
|
+
* @param {string} filename - Source filename.
|
|
226
|
+
* @param {string} source - Complete source.
|
|
227
|
+
* @returns {import("../semantic/types.js").LocalStatement} Semantic local statement.
|
|
228
|
+
*/
|
|
229
|
+
function convertLocalStatement(node, language, filename, source) {
|
|
230
|
+
const location = nodeLocation(node, filename, source);
|
|
231
|
+
if (node.type == "VariableDeclaration") {
|
|
232
|
+
if (!["let", "const"].includes(node.kind) || node.declarations.length != 1) {
|
|
233
|
+
return unsupportedSyntax(language, `${node.kind} declaration`, location);
|
|
234
|
+
}
|
|
235
|
+
const declarator = node.declarations[0];
|
|
236
|
+
const declaratorLocation = nodeLocation(declarator, filename, source);
|
|
237
|
+
if (declarator.id.type != "Identifier")
|
|
238
|
+
return unsupportedSyntax(language, declarator.id.type, declaratorLocation);
|
|
239
|
+
if (!declarator.init)
|
|
240
|
+
return unsupportedSyntax(language, "uninitialized declaration", declaratorLocation);
|
|
241
|
+
const type = language == "typescript"
|
|
242
|
+
? convertTypeScriptType(declarator.id.typeAnnotation, `Local '${declarator.id.name}'`, declaratorLocation, filename, source)
|
|
243
|
+
: localJavaScriptType(node, declarator.id.name, filename, source);
|
|
244
|
+
return withParserRanges({
|
|
245
|
+
initializer: convertExpression(declarator.init, language, filename, source),
|
|
246
|
+
kind: "LocalDeclaration",
|
|
247
|
+
location,
|
|
248
|
+
mutable: node.kind == "let",
|
|
249
|
+
name: declarator.id.name,
|
|
250
|
+
type
|
|
251
|
+
}, {
|
|
252
|
+
name: identifierLocation(declarator.id, filename, source),
|
|
253
|
+
operator: tokenLocation(declarator, "=", declarator.id.end ?? declarator.start ?? 0, declarator.init.start ?? declarator.end ?? source.length, filename, source)
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
if (node.type == "ExpressionStatement" && node.expression.type == "AssignmentExpression") {
|
|
257
|
+
const assignment = node.expression;
|
|
258
|
+
const targetLocation = nodeLocation(assignment.left, filename, source);
|
|
259
|
+
if (assignment.operator != "=")
|
|
260
|
+
return unsupportedSyntax(language, `assignment ${assignment.operator}`, location);
|
|
261
|
+
if (assignment.left.type != "Identifier")
|
|
262
|
+
return unsupportedSyntax(language, assignment.left.type, targetLocation);
|
|
263
|
+
const target = withParserRanges({ kind: /** @type {const} */ ("IdentifierExpression"), location: targetLocation, name: assignment.left.name }, {
|
|
264
|
+
name: identifierLocation(assignment.left, filename, source)
|
|
265
|
+
});
|
|
266
|
+
return withParserRanges({
|
|
267
|
+
expression: convertExpression(assignment.right, language, filename, source),
|
|
268
|
+
kind: "AssignmentStatement",
|
|
269
|
+
location,
|
|
270
|
+
target
|
|
271
|
+
}, {
|
|
272
|
+
operator: tokenLocation(assignment, "=", assignment.left.end ?? assignment.start ?? 0, assignment.right.start ?? assignment.end ?? source.length, filename, source)
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return unsupportedSyntax(language, node.type, location);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Reads an immediately associated JavaScript local `@type` tag.
|
|
279
|
+
* @param {import("@babel/types").VariableDeclaration} node - Local declaration.
|
|
280
|
+
* @param {string} name - Local name.
|
|
281
|
+
* @param {string} filename - Source filename.
|
|
282
|
+
* @param {string} source - Complete source.
|
|
283
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic type.
|
|
284
|
+
*/
|
|
285
|
+
function localJavaScriptType(node, name, filename, source) {
|
|
286
|
+
const comment = node.leadingComments?.at(-1);
|
|
287
|
+
const location = nodeLocation(node, filename, source);
|
|
288
|
+
if (!comment || comment.type != "CommentBlock" || !comment.value.startsWith("*")) {
|
|
289
|
+
return missingType("javascript", `Local '${name}'`, location);
|
|
290
|
+
}
|
|
291
|
+
const gap = source.slice(comment.end ?? 0, node.start ?? 0);
|
|
292
|
+
if (!/^\s*$/u.test(gap) || (gap.match(/\n/gu)?.length ?? 0) > 1) {
|
|
293
|
+
return missingType("javascript", `Local '${name}'`, location);
|
|
294
|
+
}
|
|
295
|
+
const block = parseComment(`/*${comment.value}*/`)[0];
|
|
296
|
+
const tags = block?.tags.filter((tag) => tag.tag == "type") ?? [];
|
|
297
|
+
const tag = tags.length == 1 ? tags[0] : undefined;
|
|
298
|
+
return convertType(tag?.type, "javascript", `Local '${name}'`, location, tag ? commentTagLocation(comment, tag, "type", filename, source) : location);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Converts one exhaustive Babel statement.
|
|
302
|
+
* @param {import("@babel/types").Statement} node - Babel statement.
|
|
303
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
304
|
+
* @param {string} filename - Source filename.
|
|
305
|
+
* @param {string} source - Complete source.
|
|
306
|
+
* @param {boolean} canonicalZeroRequired - Whether generated scalar output may contain signed zero.
|
|
307
|
+
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
308
|
+
*/
|
|
309
|
+
function convertStatement(node, language, filename, source, canonicalZeroRequired) {
|
|
310
|
+
if (node.type == "ReturnStatement")
|
|
311
|
+
return convertReturn(node, language, filename, source);
|
|
312
|
+
if (node.type == "IfStatement")
|
|
313
|
+
return convertIf(node, language, filename, source, canonicalZeroRequired);
|
|
314
|
+
if (node.type == "VariableDeclaration" || node.type == "ExpressionStatement" && node.expression.type == "AssignmentExpression") {
|
|
315
|
+
return convertLocalStatement(node, language, filename, source);
|
|
316
|
+
}
|
|
317
|
+
if (node.type == "ExpressionStatement")
|
|
318
|
+
return convertPrint(node, language, filename, source, canonicalZeroRequired);
|
|
319
|
+
return unsupportedSyntax(language, node.type, nodeLocation(node, filename, source));
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Converts one Babel block or normalized single-statement body.
|
|
323
|
+
* @param {import("@babel/types").BlockStatement | import("@babel/types").Statement[]} input - Parser block or statements.
|
|
324
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
325
|
+
* @param {string} filename - Source filename.
|
|
326
|
+
* @param {string} source - Complete source.
|
|
327
|
+
* @param {boolean} canonicalZeroRequired - Whether generated scalar output may contain signed zero.
|
|
328
|
+
* @param {import("../semantic/types.js").SourceLocation} [location] - Location for a statement-array block.
|
|
329
|
+
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
330
|
+
*/
|
|
331
|
+
function convertBlock(input, language, filename, source, canonicalZeroRequired, location) {
|
|
332
|
+
const statements = Array.isArray(input) ? input : input.body;
|
|
333
|
+
const directives = Array.isArray(input) ? [] : input.directives;
|
|
334
|
+
const blockLocation = location ?? nodeLocation(/** @type {import("@babel/types").BlockStatement} */ (input), filename, source);
|
|
335
|
+
if (directives.length > 0) {
|
|
336
|
+
return unsupportedSyntax(language, "directive", nodeLocation(directives[0], filename, source));
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
kind: "Block",
|
|
340
|
+
location: blockLocation,
|
|
341
|
+
statements: statements.map((statement) => convertStatement(statement, language, filename, source, canonicalZeroRequired))
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Reads JavaScript JSDoc types from a function.
|
|
346
|
+
* @param {import("@babel/types").FunctionDeclaration} node - Babel function node.
|
|
347
|
+
* @param {string} filename - Source filename.
|
|
348
|
+
* @param {string} source - Complete source.
|
|
349
|
+
* @returns {{parameters: Map<string, {location: import("../semantic/types.js").SourceLocation, sourceType: string}>, returnType: {location: import("../semantic/types.js").SourceLocation, sourceType: string} | undefined}} Parsed types.
|
|
350
|
+
*/
|
|
351
|
+
function jsdocTypes(node, filename, source) {
|
|
352
|
+
const comment = node.leadingComments?.find((candidate) => candidate.type == "CommentBlock" && candidate.value.startsWith("*"));
|
|
353
|
+
if (!comment)
|
|
354
|
+
missingType("javascript", `Function '${node.id?.name ?? "anonymous"}'`, nodeLocation(node, filename, source));
|
|
355
|
+
const commentBlock = /** @type {import("@babel/types").CommentBlock} */ (comment);
|
|
356
|
+
const block = parseComment(`/*${commentBlock.value}*/`)[0];
|
|
357
|
+
const parameters = new Map(block.tags.filter((tag) => tag.tag == "param").map((tag) => [tag.name, {
|
|
358
|
+
location: commentTagLocation(commentBlock, tag, "type", filename, source),
|
|
359
|
+
sourceType: tag.type
|
|
360
|
+
}]));
|
|
361
|
+
const returnTag = block.tags.find((tag) => tag.tag == "returns" || tag.tag == "return");
|
|
362
|
+
return {
|
|
363
|
+
parameters,
|
|
364
|
+
returnType: returnTag ? { location: commentTagLocation(commentBlock, returnTag, "type", filename, source), sourceType: returnTag.type } : undefined
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Requires a supported JavaScript JSDoc scalar type spelling.
|
|
369
|
+
* @param {string | undefined} sourceType - Source-language type.
|
|
370
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
371
|
+
* @param {string} subject - Typed subject.
|
|
372
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Source location.
|
|
373
|
+
* @param {import("../semantic/types.js").SourceLocation} [typeLocation] - Exact type token location.
|
|
374
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic type.
|
|
375
|
+
*/
|
|
376
|
+
function convertType(sourceType, language, subject, location, typeLocation = location) {
|
|
377
|
+
return requireSourceScalarType(language, sourceType, subject, location, typeLocation);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Converts one exact TypeScript scalar keyword annotation.
|
|
381
|
+
* @param {import("@babel/types").TypeAnnotation | import("@babel/types").TSTypeAnnotation | import("@babel/types").Noop | null | undefined} annotation - Type annotation.
|
|
382
|
+
* @param {string} subject - Typed subject.
|
|
383
|
+
* @param {import("../semantic/types.js").SourceLocation} ownerLocation - Owning declaration location.
|
|
384
|
+
* @param {string} filename - Source filename.
|
|
385
|
+
* @param {string} source - Complete source.
|
|
386
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic scalar type.
|
|
387
|
+
*/
|
|
388
|
+
function convertTypeScriptType(annotation, subject, ownerLocation, filename, source) {
|
|
389
|
+
if (!annotation)
|
|
390
|
+
return missingType("typescript", subject, ownerLocation);
|
|
391
|
+
if (annotation.type != "TSTypeAnnotation") {
|
|
392
|
+
return unsupportedSyntax("typescript", "unsupported scalar type", nodeLocation(annotation, filename, source));
|
|
393
|
+
}
|
|
394
|
+
const typeNode = annotation.typeAnnotation;
|
|
395
|
+
const sourceType = typeNode.type == "TSNumberKeyword"
|
|
396
|
+
? "number"
|
|
397
|
+
: typeNode.type == "TSBooleanKeyword"
|
|
398
|
+
? "boolean"
|
|
399
|
+
: typeNode.type == "TSStringKeyword" ? "string" : undefined;
|
|
400
|
+
if (!sourceType) {
|
|
401
|
+
return unsupportedSyntax("typescript", "unsupported scalar type", nodeLocation(typeNode, filename, source));
|
|
402
|
+
}
|
|
403
|
+
return requireSourceScalarType("typescript", sourceType, subject, ownerLocation, nodeLocation(typeNode, filename, source));
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Converts a supported function declaration.
|
|
407
|
+
* @param {import("@babel/types").FunctionDeclaration} node - Babel function.
|
|
408
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
409
|
+
* @param {string} filename - Source filename.
|
|
410
|
+
* @param {string} source - Complete source.
|
|
411
|
+
* @param {boolean} canonicalZeroRequired - Whether generated scalar output may contain signed zero.
|
|
412
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
413
|
+
*/
|
|
414
|
+
function convertFunction(node, language, filename, source, canonicalZeroRequired) {
|
|
415
|
+
const location = nodeLocation(node, filename, source);
|
|
416
|
+
if (!node.id)
|
|
417
|
+
return unsupportedSyntax(language, "anonymous function", location);
|
|
418
|
+
if (node.async)
|
|
419
|
+
return unsupportedSyntax(language, "async function", location);
|
|
420
|
+
if (node.generator)
|
|
421
|
+
return unsupportedSyntax(language, "generator function", location);
|
|
422
|
+
const documentedTypes = language == "javascript" ? jsdocTypes(node, filename, source) : undefined;
|
|
423
|
+
const parameters = node.params.map((parameter) => {
|
|
424
|
+
const parameterLocation = nodeLocation(parameter, filename, source);
|
|
425
|
+
if (parameter.type != "Identifier")
|
|
426
|
+
return unsupportedSyntax(language, parameter.type, parameterLocation);
|
|
427
|
+
const documentedType = documentedTypes?.parameters.get(parameter.name);
|
|
428
|
+
const type = language == "javascript"
|
|
429
|
+
? convertType(documentedType?.sourceType, language, `Parameter '${parameter.name}'`, parameterLocation, documentedType?.location)
|
|
430
|
+
: convertTypeScriptType(parameter.typeAnnotation, `Parameter '${parameter.name}'`, parameterLocation, filename, source);
|
|
431
|
+
return withParserRanges({
|
|
432
|
+
kind: /** @type {const} */ ("Parameter"),
|
|
433
|
+
location: parameterLocation,
|
|
434
|
+
name: parameter.name,
|
|
435
|
+
type
|
|
436
|
+
}, { name: identifierLocation(parameter, filename, source) });
|
|
437
|
+
});
|
|
438
|
+
const returnAnnotation = node.returnType;
|
|
439
|
+
const returnType = language == "javascript"
|
|
440
|
+
? convertType(documentedTypes?.returnType?.sourceType, language, `Function '${node.id.name}' return`, location, documentedTypes?.returnType?.location)
|
|
441
|
+
: convertTypeScriptType(returnAnnotation, `Function '${node.id.name}' return`, location, filename, source);
|
|
442
|
+
const body = convertBlock(node.body, language, filename, source, canonicalZeroRequired);
|
|
443
|
+
return withParserRanges({
|
|
444
|
+
body,
|
|
445
|
+
kind: "FunctionDeclaration",
|
|
446
|
+
location,
|
|
447
|
+
name: node.id.name,
|
|
448
|
+
parameters,
|
|
449
|
+
returnType
|
|
450
|
+
}, { name: identifierLocation(node.id, filename, source) });
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Converts the existing exact if/else terminal shape.
|
|
454
|
+
* @param {import("@babel/types").IfStatement} node - Babel if statement.
|
|
455
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
456
|
+
* @param {string} filename - Source filename.
|
|
457
|
+
* @param {string} source - Complete source.
|
|
458
|
+
* @param {boolean} canonicalZeroRequired - Whether generated scalar output may contain signed zero.
|
|
459
|
+
* @returns {import("../semantic/types.js").IfStatement} Semantic branch.
|
|
460
|
+
*/
|
|
461
|
+
function convertIf(node, language, filename, source, canonicalZeroRequired) {
|
|
462
|
+
const location = nodeLocation(node, filename, source);
|
|
463
|
+
const consequent = node.consequent.type == "BlockStatement"
|
|
464
|
+
? convertBlock(node.consequent, language, filename, source, canonicalZeroRequired)
|
|
465
|
+
: convertBlock([node.consequent], language, filename, source, canonicalZeroRequired, nodeLocation(node.consequent, filename, source));
|
|
466
|
+
const alternate = node.alternate
|
|
467
|
+
? node.alternate.type == "BlockStatement"
|
|
468
|
+
? convertBlock(node.alternate, language, filename, source, canonicalZeroRequired)
|
|
469
|
+
: convertBlock([node.alternate], language, filename, source, canonicalZeroRequired, nodeLocation(node.alternate, filename, source))
|
|
470
|
+
: undefined;
|
|
471
|
+
return {
|
|
472
|
+
...(alternate ? { alternate } : {}),
|
|
473
|
+
condition: convertExpression(node.test, language, filename, source),
|
|
474
|
+
consequent,
|
|
475
|
+
kind: "IfStatement",
|
|
476
|
+
location
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Reports whether Babel parsed an operation that makes generated JavaScript-family scalar output require zero canonicalization.
|
|
481
|
+
* @param {unknown} value - Babel parser subtree.
|
|
482
|
+
* @param {WeakSet<object>} [visited] - Cycle protection.
|
|
483
|
+
* @returns {boolean} Whether the subtree contains integer negation or multiplication syntax.
|
|
484
|
+
*/
|
|
485
|
+
function parserTreeRequiresCanonicalZero(value, visited = new WeakSet()) {
|
|
486
|
+
if (!value || typeof value != "object")
|
|
487
|
+
return false;
|
|
488
|
+
if (visited.has(value))
|
|
489
|
+
return false;
|
|
490
|
+
visited.add(value);
|
|
491
|
+
if (Reflect.get(value, "type") == "UnaryExpression" && Reflect.get(value, "operator") == "-")
|
|
492
|
+
return true;
|
|
493
|
+
if (Reflect.get(value, "type") == "BinaryExpression" && Reflect.get(value, "operator") == "*")
|
|
494
|
+
return true;
|
|
495
|
+
return Object.entries(value).some(([key, child]) => !["extra", "innerComments", "leadingComments", "loc", "trailingComments"].includes(key) &&
|
|
496
|
+
(Array.isArray(child)
|
|
497
|
+
? child.some((item) => parserTreeRequiresCanonicalZero(item, visited))
|
|
498
|
+
: parserTreeRequiresCanonicalZero(child, visited)));
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Recognizes the parser-owned receiver parentheses emitted only for canonical integer output.
|
|
502
|
+
* @param {import("@babel/types").Expression | import("@babel/types").Super} receiver - Qualified-call receiver.
|
|
503
|
+
* @param {import("@babel/types").CallExpression} call - Outer `toString` call.
|
|
504
|
+
* @returns {boolean} Whether the receiver has the generated wrapper shape.
|
|
505
|
+
*/
|
|
506
|
+
function hasCanonicalZeroReceiverWrapper(receiver, call) {
|
|
507
|
+
const extra = Reflect.get(receiver, "extra");
|
|
508
|
+
const expressionParentheses = ["BinaryExpression", "LogicalExpression", "UnaryExpression"].includes(receiver.type) ? 1 : 0;
|
|
509
|
+
const wrapperParentheses = expressionParentheses + 1;
|
|
510
|
+
const property = call.callee.type == "MemberExpression" ? call.callee.property : undefined;
|
|
511
|
+
return Boolean(extra) && typeof extra == "object" && Reflect.get(extra, "parenthesized") === true &&
|
|
512
|
+
Reflect.get(extra, "parenStart") === call.start && typeof call.start == "number" && typeof call.end == "number" &&
|
|
513
|
+
typeof receiver.start == "number" && typeof receiver.end == "number" && property?.type == "Identifier" &&
|
|
514
|
+
typeof property.start == "number" && typeof property.end == "number" && call.callee.start === call.start &&
|
|
515
|
+
receiver.start == call.start + wrapperParentheses && property.start == receiver.end + wrapperParentheses + 1 &&
|
|
516
|
+
property.end == property.start + "toString".length && call.end == property.end + 2;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Converts a console.log entry-point call.
|
|
520
|
+
* @param {import("@babel/types").Statement} node - Babel statement.
|
|
521
|
+
* @param {"javascript" | "typescript"} language - Frontend language.
|
|
522
|
+
* @param {string} filename - Source filename.
|
|
523
|
+
* @param {string} source - Complete source.
|
|
524
|
+
* @param {boolean} canonicalZeroRequired - Whether this parsed module contains a sign-producing integer operation.
|
|
525
|
+
* @returns {import("../semantic/types.js").PrintStatement} Print statement.
|
|
526
|
+
*/
|
|
527
|
+
function convertPrint(node, language, filename, source, canonicalZeroRequired) {
|
|
528
|
+
const location = nodeLocation(node, filename, source);
|
|
529
|
+
if (node.type != "ExpressionStatement" || node.expression.type != "CallExpression") {
|
|
530
|
+
return unsupportedSyntax(language, node.type, location);
|
|
531
|
+
}
|
|
532
|
+
const call = node.expression;
|
|
533
|
+
const callee = call.callee;
|
|
534
|
+
if (callee.type != "MemberExpression" || callee.computed || callee.object.type != "Identifier" ||
|
|
535
|
+
callee.object.name != "console" || callee.property.type != "Identifier" || callee.property.name != "log" ||
|
|
536
|
+
call.arguments.length != 1) {
|
|
537
|
+
return unsupportedSyntax(language, "entry-point expression", location);
|
|
538
|
+
}
|
|
539
|
+
let argument = call.arguments[0];
|
|
540
|
+
if (argument.type == "SpreadElement" || argument.type == "ArgumentPlaceholder") {
|
|
541
|
+
return unsupportedSyntax(language, argument.type, nodeLocation(argument, filename, source));
|
|
542
|
+
}
|
|
543
|
+
if (argument.type == "CallExpression" && argument.callee.type == "MemberExpression" && !argument.callee.computed &&
|
|
544
|
+
!argument.callee.optional && argument.callee.object.type != "Super" && argument.callee.property.type == "Identifier" &&
|
|
545
|
+
argument.callee.property.name == "toString" && !argument.optional && !argument.typeArguments &&
|
|
546
|
+
!argument.typeParameters && argument.arguments.length == 0) {
|
|
547
|
+
if (!canonicalZeroRequired || !hasCanonicalZeroReceiverWrapper(argument.callee.object, argument)) {
|
|
548
|
+
return unsupportedSyntax(language, "entry-point qualified call", nodeLocation(argument.callee.property, filename, source));
|
|
549
|
+
}
|
|
550
|
+
argument = argument.callee.object;
|
|
551
|
+
}
|
|
552
|
+
return { expression: convertExpression(argument, language, filename, source), kind: "PrintStatement", location };
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Parses JavaScript or TypeScript into the shared semantic module.
|
|
556
|
+
* @param {object} input - Parser input.
|
|
557
|
+
* @param {string} input.filename - Source filename.
|
|
558
|
+
* @param {"javascript" | "typescript"} input.language - Frontend language.
|
|
559
|
+
* @param {string} input.source - Source text.
|
|
560
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
561
|
+
*/
|
|
562
|
+
export function parseJavaScriptTypeScript({ filename, language, source }) {
|
|
563
|
+
const file = parseBabelSource({ filename, language, source });
|
|
564
|
+
const tokens = file.tokens ?? [];
|
|
565
|
+
const tokenIndex = { byStart: new Map(tokens.map((token) => [token.start, token])), tokens };
|
|
566
|
+
const canonicalZeroRequired = parserTreeRequiresCanonicalZero(file.program);
|
|
567
|
+
rememberTokens(file, tokenIndex);
|
|
568
|
+
if (file.program.directives.length > 0) {
|
|
569
|
+
return unsupportedSyntax(language, "top-level directive", nodeLocation(file.program.directives[0], filename, source));
|
|
570
|
+
}
|
|
571
|
+
const functions = file.program.body.filter((node) => node.type == "FunctionDeclaration")
|
|
572
|
+
.map((node) => convertFunction(node, language, filename, source, canonicalZeroRequired));
|
|
573
|
+
const entryNodes = file.program.body.filter((node) => node.type != "FunctionDeclaration");
|
|
574
|
+
const location = moduleLocation(filename, source);
|
|
575
|
+
if (functions.length == 0)
|
|
576
|
+
return unsupportedSyntax(language, "module without a function", location);
|
|
577
|
+
const entryLocation = entryNodes.length == 0 ? location : locationFromOffsets(filename, source, entryNodes[0].start ?? 0, entryNodes.at(-1)?.end ?? source.length);
|
|
578
|
+
const entryBlock = convertBlock(entryNodes, language, filename, source, canonicalZeroRequired, entryLocation);
|
|
579
|
+
return {
|
|
580
|
+
entryPoint: {
|
|
581
|
+
body: entryBlock,
|
|
582
|
+
kind: "EntryPoint",
|
|
583
|
+
location: entryLocation
|
|
584
|
+
},
|
|
585
|
+
functions,
|
|
586
|
+
kind: "Module",
|
|
587
|
+
location
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Invokes Babel and normalizes syntax failures.
|
|
592
|
+
* @param {object} input - Parser input.
|
|
593
|
+
* @param {string} input.filename - Source filename.
|
|
594
|
+
* @param {"javascript" | "typescript"} input.language - Frontend language.
|
|
595
|
+
* @param {string} input.source - Source text.
|
|
596
|
+
* @returns {import("@babel/parser").ParseResult<import("@babel/types").File>} Babel file.
|
|
597
|
+
*/
|
|
598
|
+
function parseBabelSource({ filename, language, source }) {
|
|
599
|
+
try {
|
|
600
|
+
return parseBabel(source, {
|
|
601
|
+
plugins: language == "typescript" ? ["typescript"] : [],
|
|
602
|
+
sourceFilename: filename,
|
|
603
|
+
sourceType: "script",
|
|
604
|
+
tokens: true
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
return parseFailure(language, error);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Associates Babel nodes with their parser token stream without leaking it into semantic values.
|
|
613
|
+
* @param {object} value - Current parser value.
|
|
614
|
+
* @param {BabelTokenIndex} tokens - Indexed parser tokens.
|
|
615
|
+
* @param {WeakSet<object>} [visited] - Cycle protection.
|
|
616
|
+
* @returns {void}
|
|
617
|
+
*/
|
|
618
|
+
function rememberTokens(value, tokens, visited = new WeakSet()) {
|
|
619
|
+
if (visited.has(value))
|
|
620
|
+
return;
|
|
621
|
+
visited.add(value);
|
|
622
|
+
nodeTokens.set(value, tokens);
|
|
623
|
+
for (const child of Object.values(value)) {
|
|
624
|
+
if (Array.isArray(child)) {
|
|
625
|
+
for (const item of child)
|
|
626
|
+
if (item && typeof item == "object")
|
|
627
|
+
rememberTokens(item, tokens, visited);
|
|
628
|
+
}
|
|
629
|
+
else if (child && typeof child == "object")
|
|
630
|
+
rememberTokens(child, tokens, visited);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamF2YXNjcmlwdC10eXBlc2NyaXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2Zyb250ZW5kcy9qYXZhc2NyaXB0LXR5cGVzY3JpcHQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxLQUFLLElBQUksVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFBO0FBQ2pELE9BQU8sRUFBQyxLQUFLLElBQUksWUFBWSxFQUFDLE1BQU0sZ0JBQWdCLENBQUE7QUFDcEQsT0FBTyxFQUFDLFdBQVcsRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQTtBQUM3RSxPQUFPLEVBQUMsbUJBQW1CLEVBQUUsY0FBYyxFQUFDLE1BQU0seUJBQXlCLENBQUE7QUFDM0UsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sMEJBQTBCLENBQUE7QUFDN0QsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sMkJBQTJCLENBQUE7QUFDMUQsT0FBTyxFQUFDLHFCQUFxQixFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFDNUQsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0sY0FBYyxDQUFBO0FBRXBELDRIQUE0SDtBQUM1SCwwRkFBMEY7QUFFMUYsK0NBQStDO0FBQy9DLE1BQU0sVUFBVSxHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFDaEMsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLEdBQUcsQ0FBQztJQUNwQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUM7SUFDWixDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUM7SUFDakIsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQztJQUNoQixDQUFDLEtBQUssRUFBRSxVQUFVLENBQUM7SUFDbkIsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDO0lBQ2pCLENBQUMsSUFBSSxFQUFFLGlCQUFpQixDQUFDO0lBQ3pC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QUFDSCxTQUFTLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRTtJQUM1RCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDO1FBQUUsT0FBTTtJQUU5QixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ2xCLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBRTdCLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3pCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSztnQkFBRSxJQUFJLElBQUksSUFBSSxPQUFPLElBQUksSUFBSSxRQUFRO29CQUFFLGNBQWMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQ3RHLENBQUM7YUFBTSxJQUFJLEtBQUssSUFBSSxPQUFPLEtBQUssSUFBSSxRQUFRO1lBQUUsY0FBYyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDdEYsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtwYXJzZSBhcyBwYXJzZUJhYmVsfSBmcm9tIFwiQGJhYmVsL3BhcnNlclwiXG5pbXBvcnQge3BhcnNlIGFzIHBhcnNlQ29tbWVudH0gZnJvbSBcImNvbW1lbnQtcGFyc2VyXCJcbmltcG9ydCB7bWlzc2luZ1R5cGUsIHBhcnNlRmFpbHVyZSwgdW5zdXBwb3J0ZWRTeW50YXh9IGZyb20gXCIuLi9kaWFnbm9zdGljLmpzXCJcbmltcG9ydCB7bG9jYXRpb25Gcm9tT2Zmc2V0cywgbW9kdWxlTG9jYXRpb259IGZyb20gXCIuLi9zZW1hbnRpYy9sb2NhdGlvbi5qc1wiXG5pbXBvcnQge3dpdGhBZGFwdGVkT3BlcmF0aW9ufSBmcm9tIFwiLi4vc2VtYW50aWMvb3BlcmF0b3JzLmpzXCJcbmltcG9ydCB7d2l0aFBhcnNlclJhbmdlc30gZnJvbSBcIi4uL3NlbWFudGljL3Byb3ZlbmFuY2UuanNcIlxuaW1wb3J0IHtoYXNPbmx5VW5pY29kZVNjYWxhcnN9IGZyb20gXCIuLi9zZW1hbnRpYy9zY2FsYXJzLmpzXCJcbmltcG9ydCB7cmVxdWlyZVNvdXJjZVNjYWxhclR5cGV9IGZyb20gXCIuL3NjYWxhcnMuanNcIlxuXG4vKiogQHR5cGVkZWYge05vbk51bGxhYmxlPGltcG9ydChcIkBiYWJlbC9wYXJzZXJcIikuUGFyc2VSZXN1bHQ8aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLkZpbGU+W1widG9rZW5zXCJdPltudW1iZXJdfSBCYWJlbFRva2VuICovXG4vKiogQHR5cGVkZWYge3tieVN0YXJ0OiBNYXA8bnVtYmVyLCBCYWJlbFRva2VuPiwgdG9rZW5zOiBCYWJlbFRva2VuW119fSBCYWJlbFRva2VuSW5kZXggKi9cblxuLyoqIEB0eXBlIHtXZWFrTWFwPG9iamVjdCwgQmFiZWxUb2tlbkluZGV4Pn0gKi9cbmNvbnN0IG5vZGVUb2tlbnMgPSBuZXcgV2Vha01hcCgpXG5jb25zdCBiYWJlbEJpbmFyeU9wZXJhdGlvbnMgPSBuZXcgTWFwKFtcbiAgW1wiK1wiLCBcIkFkZFwiXSxcbiAgW1wiLVwiLCBcIlN1YnRyYWN0XCJdLFxuICBbXCIqXCIsIFwiTXVsdGlwbHlcIl0sXG4gIFtcIj09PVwiLCBcIkVxdWFsXCJdLFxuICBbXCIhPT1cIiwgXCJOb3RFcXVhbFwiXSxcbiAgW1wiPFwiLCBcIkxlc3NUaGFuXCJdLFxuICBbXCI8PVwiLCBcIkxlc3NUaGFuT3JFcXVhbFwiXSxcbiAgW1wiPlwiLCBcIkdyZWF0ZXJUaGFuXCJdLFxuICBbXCI+PVwiLCBcIkdyZWF0ZXJUaGFuT3JFcXVhbFwiXVxuXSlcblxuLyoqXG4gKiBSZXR1cm5zIGEgc291cmNlIGxvY2F0aW9uIGZvciBhIEJhYmVsIG5vZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5Ob2RlfSBub2RlIC0gQmFiZWwgbm9kZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IE5vcm1hbGl6ZWQgbG9jYXRpb24uXG4gKi9cbmZ1bmN0aW9uIG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGlmICh0eXBlb2Ygbm9kZS5zdGFydCAhPSBcIm51bWJlclwiIHx8IHR5cGVvZiBub2RlLmVuZCAhPSBcIm51bWJlclwiKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBCYWJlbCBvbWl0dGVkIHNvdXJjZSBvZmZzZXRzIGZvciAke25vZGUudHlwZX0uYClcbiAgfVxuXG4gIHJldHVybiBsb2NhdGlvbkZyb21PZmZzZXRzKGZpbGVuYW1lLCBzb3VyY2UsIG5vZGUuc3RhcnQsIG5vZGUuZW5kKVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGlkZW50aWZpZXIgc3BlbGxpbmcgcmF0aGVyIHRoYW4gYSB0cmFpbGluZyBUeXBlU2NyaXB0IGFubm90YXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5JZGVudGlmaWVyfSBub2RlIC0gUGFyc2VyIGlkZW50aWZpZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBJZGVudGlmaWVyIGxvY2F0aW9uLlxuICovXG5mdW5jdGlvbiBpZGVudGlmaWVyTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBpZiAodHlwZW9mIG5vZGUuc3RhcnQgIT0gXCJudW1iZXJcIikgdGhyb3cgbmV3IEVycm9yKFwiQmFiZWwgb21pdHRlZCBhbiBpZGVudGlmaWVyIHN0YXJ0IG9mZnNldC5cIilcbiAgY29uc3QgdG9rZW4gPSBub2RlVG9rZW5zLmdldChub2RlKT8uYnlTdGFydC5nZXQobm9kZS5zdGFydClcblxuICBpZiAoIXRva2VuIHx8IHRva2VuLnR5cGUubGFiZWwgIT0gXCJuYW1lXCIpIHRocm93IG5ldyBFcnJvcihgQmFiZWwgb21pdHRlZCB0aGUgaWRlbnRpZmllciB0b2tlbiBmb3IgJyR7bm9kZS5uYW1lfScuYClcblxuICByZXR1cm4gbG9jYXRpb25Gcm9tT2Zmc2V0cyhmaWxlbmFtZSwgc291cmNlLCB0b2tlbi5zdGFydCwgdG9rZW4uZW5kKVxufVxuXG4vKipcbiAqIExvY2F0ZXMgb25lIEJhYmVsIHRva2VuIHdpdGhpbiBwYXJzZXItbm9kZSBib3VuZGFyaWVzLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuTm9kZX0gb3duZXIgLSBUb2tlbi1vd25pbmcgcGFyc2VyIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBFeGFjdCB0b2tlbiBzcGVsbGluZy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydE9mZnNldCAtIEluY2x1c2l2ZSBib3VuZGFyeS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmRPZmZzZXQgLSBFeGNsdXNpdmUgYm91bmRhcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBFeGFjdCB0b2tlbiBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gdG9rZW5Mb2NhdGlvbihvd25lciwgdmFsdWUsIHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgdG9rZW5zID0gbm9kZVRva2Vucy5nZXQob3duZXIpPy50b2tlbnMgPz8gW11cbiAgbGV0IGxvdyA9IDBcbiAgbGV0IGhpZ2ggPSB0b2tlbnMubGVuZ3RoXG5cbiAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICBjb25zdCBtaWRkbGUgPSBNYXRoLmZsb29yKChsb3cgKyBoaWdoKSAvIDIpXG5cbiAgICBpZiAodG9rZW5zW21pZGRsZV0uc3RhcnQgPCBzdGFydE9mZnNldCkgbG93ID0gbWlkZGxlICsgMVxuICAgIGVsc2UgaGlnaCA9IG1pZGRsZVxuICB9XG4gIGxldCB0b2tlblxuXG4gIGZvciAobGV0IGluZGV4ID0gbG93OyBpbmRleCA8IHRva2Vucy5sZW5ndGggJiYgdG9rZW5zW2luZGV4XS5zdGFydCA8IGVuZE9mZnNldDsgaW5kZXgrKykge1xuICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHRva2Vuc1tpbmRleF1cblxuICAgIGlmIChjYW5kaWRhdGUuZW5kIDw9IGVuZE9mZnNldCAmJiAoY2FuZGlkYXRlLnZhbHVlID09IHZhbHVlIHx8IGNhbmRpZGF0ZS50eXBlLmxhYmVsID09IHZhbHVlKSkge1xuICAgICAgdG9rZW4gPSBjYW5kaWRhdGVcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKCF0b2tlbikgdGhyb3cgbmV3IEVycm9yKGBCYWJlbCBvbWl0dGVkIHRva2VuICcke3ZhbHVlfScgYmV0d2VlbiAke3N0YXJ0T2Zmc2V0fSBhbmQgJHtlbmRPZmZzZXR9LmApXG5cbiAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgdG9rZW4uc3RhcnQsIHRva2VuLmVuZClcbn1cblxuLyoqXG4gKiBMb2NhdGVzIGEgY29tbWVudC1wYXJzZXIgdG9rZW4gaW5zaWRlIGEgQmFiZWwtb3duZWQgZG9jIGNvbW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5Db21tZW50QmxvY2t9IGNvbW1lbnQgLSBCYWJlbCBkb2MgY29tbWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiY29tbWVudC1wYXJzZXJcIikuU3BlY30gdGFnIC0gUGFyc2VkIGRvYyB0YWcuXG4gKiBAcGFyYW0ge1wibmFtZVwiIHwgXCJ0eXBlXCJ9IGZpZWxkIC0gVG9rZW4gZmllbGQuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBFeGFjdCB0b2tlbiBsb2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gY29tbWVudFRhZ0xvY2F0aW9uKGNvbW1lbnQsIHRhZywgZmllbGQsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbGluZSA9IHRhZy5zb3VyY2VbMF1cblxuICBpZiAodHlwZW9mIGNvbW1lbnQuc3RhcnQgIT0gXCJudW1iZXJcIiB8fCAhbGluZSkgdGhyb3cgbmV3IEVycm9yKGBDb21tZW50IHBhcnNlciBvbWl0dGVkIHRoZSBAJHt0YWcudGFnfSBzb3VyY2UgdG9rZW4uYClcblxuICBsZXQgbGluZVN0YXJ0ID0gY29tbWVudC5zdGFydFxuXG4gIGZvciAobGV0IGxpbmVOdW1iZXIgPSAwOyBsaW5lTnVtYmVyIDwgbGluZS5udW1iZXI7IGxpbmVOdW1iZXIrKykge1xuICAgIHdoaWxlIChsaW5lU3RhcnQgPCBzb3VyY2UubGVuZ3RoICYmIHNvdXJjZVtsaW5lU3RhcnRdICE9IFwiXFxyXCIgJiYgc291cmNlW2xpbmVTdGFydF0gIT0gXCJcXG5cIikgbGluZVN0YXJ0KytcbiAgICBpZiAoc291cmNlW2xpbmVTdGFydF0gPT0gXCJcXHJcIiAmJiBzb3VyY2VbbGluZVN0YXJ0ICsgMV0gPT0gXCJcXG5cIikgbGluZVN0YXJ0ICs9IDJcbiAgICBlbHNlIGxpbmVTdGFydCsrXG4gIH1cblxuICBjb25zdCBvcmRlcmVkRmllbGRzID0gW1wic3RhcnRcIiwgXCJkZWxpbWl0ZXJcIiwgXCJwb3N0RGVsaW1pdGVyXCIsIFwidGFnXCIsIFwicG9zdFRhZ1wiLCBcInR5cGVcIiwgXCJwb3N0VHlwZVwiLCBcIm5hbWVcIl1cbiAgY29uc3QgZmllbGRJbmRleCA9IG9yZGVyZWRGaWVsZHMuaW5kZXhPZihmaWVsZClcbiAgY29uc3Qgc3RhcnQgPSBsaW5lU3RhcnQgKyBvcmRlcmVkRmllbGRzLnNsaWNlKDAsIGZpZWxkSW5kZXgpLnJlZHVjZSgobGVuZ3RoLCBrZXkpID0+XG4gICAgbGVuZ3RoICsgbGluZS50b2tlbnNbLyoqIEB0eXBlIHtrZXlvZiB0eXBlb2YgbGluZS50b2tlbnN9ICovIChrZXkpXS5sZW5ndGgsIDApXG4gIGNvbnN0IHRva2VuID0gbGluZS50b2tlbnNbZmllbGRdXG5cbiAgcmV0dXJuIGxvY2F0aW9uRnJvbU9mZnNldHMoZmlsZW5hbWUsIHNvdXJjZSwgc3RhcnQsIHN0YXJ0ICsgdG9rZW4ubGVuZ3RoKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgc3VwcG9ydGVkIEJhYmVsIGV4cHJlc3Npb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5FeHByZXNzaW9ufSBub2RlIC0gQmFiZWwgZXhwcmVzc2lvbi5cbiAqIEBwYXJhbSB7XCJqYXZhc2NyaXB0XCIgfCBcInR5cGVzY3JpcHRcIn0gbGFuZ3VhZ2UgLSBGcm9udGVuZCBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gU2VtYW50aWMgZXhwcmVzc2lvbi5cbiAqL1xuZnVuY3Rpb24gY29udmVydEV4cHJlc3Npb24obm9kZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZS50eXBlID09IFwiSWRlbnRpZmllclwiKSB7XG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpLCBsb2NhdGlvbiwgbmFtZTogbm9kZS5uYW1lfSwge1xuICAgICAgbmFtZTogaWRlbnRpZmllckxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJOdW1lcmljTGl0ZXJhbFwiKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihub2RlLnZhbHVlKSkgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBcIm5vbi1zYWZlIGludGVnZXIgbGl0ZXJhbFwiLCBsb2NhdGlvbilcblxuICAgIHJldHVybiB3aXRoUGFyc2VyUmFuZ2VzKHtraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJJbnRlZ2VyTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBub2RlLnZhbHVlfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJCb29sZWFuTGl0ZXJhbFwiKSB7XG4gICAgaWYgKHR5cGVvZiBub2RlLnZhbHVlICE9IFwiYm9vbGVhblwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIFwiaW52YWxpZCBib29sZWFuIGxpdGVyYWwgdmFsdWVcIiwgbG9jYXRpb24pXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiQm9vbGVhbkxpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZTogbm9kZS52YWx1ZX0sIHtsaXRlcmFsOiBsb2NhdGlvbn0pXG4gIH1cblxuICBpZiAobm9kZS50eXBlID09IFwiU3RyaW5nTGl0ZXJhbFwiKSB7XG4gICAgaWYgKHR5cGVvZiBub2RlLnZhbHVlICE9IFwic3RyaW5nXCIgfHwgIWhhc09ubHlVbmljb2RlU2NhbGFycyhub2RlLnZhbHVlKSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBcImludmFsaWQgVW5pY29kZSBzdHJpbmcgbGl0ZXJhbFwiLCBsb2NhdGlvbilcbiAgICB9XG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiU3RyaW5nTGl0ZXJhbFwiKSwgbG9jYXRpb24sIHZhbHVlOiBub2RlLnZhbHVlfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJUZW1wbGF0ZUxpdGVyYWxcIikge1xuICAgIGlmIChub2RlLmV4cHJlc3Npb25zLmxlbmd0aCA+IDApIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgXCJpbnRlcnBvbGF0ZWQgc3RyaW5nXCIsIGxvY2F0aW9uKVxuXG4gICAgY29uc3QgcXVhc2kgPSBub2RlLnF1YXNpc1swXVxuXG4gICAgaWYgKHR5cGVvZiBxdWFzaS52YWx1ZS5jb29rZWQgIT0gXCJzdHJpbmdcIiB8fCAhaGFzT25seVVuaWNvZGVTY2FsYXJzKHF1YXNpLnZhbHVlLmNvb2tlZCkpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgXCJpbnZhbGlkIFVuaWNvZGUgc3RyaW5nIGxpdGVyYWxcIiwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2tpbmQ6IC8qKiBAdHlwZSB7Y29uc3R9ICovIChcIlN0cmluZ0xpdGVyYWxcIiksIGxvY2F0aW9uLCB2YWx1ZTogcXVhc2kudmFsdWUuY29va2VkfSwge2xpdGVyYWw6IGxvY2F0aW9ufSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJVbmFyeUV4cHJlc3Npb25cIiAmJiBbXCIhXCIsIFwiLVwiXS5pbmNsdWRlcyhub2RlLm9wZXJhdG9yKSkge1xuICAgIGNvbnN0IG9wZXJhbmQgPSBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCBzZW1hbnRpYyA9IHdpdGhBZGFwdGVkT3BlcmF0aW9uKHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgICAga2luZDogXCJVbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgb3BlcmFuZFxuICAgIH0sIHtcbiAgICAgIG9wZXJhdG9yOiB0b2tlbkxvY2F0aW9uKG5vZGUsIG5vZGUub3BlcmF0b3IsIG5vZGUuc3RhcnQgPz8gMCwgbm9kZS5hcmd1bWVudC5zdGFydCA/PyBub2RlLmVuZCA/PyBzb3VyY2UubGVuZ3RoLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pLCBub2RlLm9wZXJhdG9yID09IFwiIVwiID8gXCJOb3RcIiA6IFwiTmVnYXRlXCIpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUudHlwZSA9PSBcIkxvZ2ljYWxFeHByZXNzaW9uXCIgJiYgW1wiJiZcIiwgXCJ8fFwiXS5pbmNsdWRlcyhub2RlLm9wZXJhdG9yKSkge1xuICAgIGNvbnN0IHNlbWFudGljID0gd2l0aEFkYXB0ZWRPcGVyYXRpb24od2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiBcIkJpbmFyeUV4cHJlc3Npb25cIixcbiAgICAgIGxlZnQ6IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUubGVmdCwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgbG9jYXRpb24sXG4gICAgICByaWdodDogY29udmVydEV4cHJlc3Npb24obm9kZS5yaWdodCwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSwge1xuICAgICAgb3BlcmF0b3I6IHRva2VuTG9jYXRpb24obm9kZSwgbm9kZS5vcGVyYXRvciwgbm9kZS5sZWZ0LmVuZCA/PyBub2RlLnN0YXJ0ID8/IDAsIG5vZGUucmlnaHQuc3RhcnQgPz8gbm9kZS5lbmQgPz8gc291cmNlLmxlbmd0aCwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9KSwgbm9kZS5vcGVyYXRvciA9PSBcIiYmXCIgPyBcIkFuZFwiIDogXCJPclwiKVxuXG4gICAgcmV0dXJuIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRXhwcmVzc2lvbn0gKi8gKC8qKiBAdHlwZSB7dW5rbm93bn0gKi8gKHNlbWFudGljKSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJCaW5hcnlFeHByZXNzaW9uXCIgJiYgYmFiZWxCaW5hcnlPcGVyYXRpb25zLmhhcyhub2RlLm9wZXJhdG9yKSkge1xuICAgIGlmIChub2RlLmxlZnQudHlwZSA9PSBcIlByaXZhdGVOYW1lXCIpIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBub2RlLmxlZnQudHlwZSwgbG9jYXRpb24pXG5cbiAgICBjb25zdCBsZWZ0ID0gY29udmVydEV4cHJlc3Npb24obm9kZS5sZWZ0LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICBjb25zdCByaWdodCA9IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUucmlnaHQsIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gICAgY29uc3Qgc2VtYW50aWMgPSB3aXRoQWRhcHRlZE9wZXJhdGlvbih3aXRoUGFyc2VyUmFuZ2VzKHtcbiAgICAgIGtpbmQ6IFwiQmluYXJ5RXhwcmVzc2lvblwiLFxuICAgICAgbGVmdCxcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgcmlnaHRcbiAgICB9LCB7XG4gICAgICBvcGVyYXRvcjogdG9rZW5Mb2NhdGlvbihub2RlLCBub2RlLm9wZXJhdG9yLCBub2RlLmxlZnQuZW5kID8/IG5vZGUuc3RhcnQgPz8gMCwgbm9kZS5yaWdodC5zdGFydCA/PyBub2RlLmVuZCA/PyBzb3VyY2UubGVuZ3RoLCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pLCAvKiogQHR5cGUge2ltcG9ydChcIi4uL3NlbWFudGljL29wZXJhdG9ycy5qc1wiKS5BZGFwdGVkT3BlcmF0aW9ufSAqLyAoYmFiZWxCaW5hcnlPcGVyYXRpb25zLmdldChub2RlLm9wZXJhdG9yKSkpXG5cbiAgICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoc2VtYW50aWMpKVxuICB9XG5cbiAgaWYgKG5vZGUudHlwZSA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIiAmJiBbXCI9PVwiLCBcIiE9XCJdLmluY2x1ZGVzKG5vZGUub3BlcmF0b3IpKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBgY29lcmNpdmUgZXF1YWxpdHkgJHtub2RlLm9wZXJhdG9yfWAsIGxvY2F0aW9uKVxuICB9XG5cbiAgaWYgKG5vZGUudHlwZSA9PSBcIkNhbGxFeHByZXNzaW9uXCIgJiYgbm9kZS5jYWxsZWUudHlwZSA9PSBcIklkZW50aWZpZXJcIikge1xuICAgIGNvbnN0IGFyZ3VtZW50c18gPSBub2RlLmFyZ3VtZW50cy5tYXAoKGFyZ3VtZW50KSA9PiB7XG4gICAgICBpZiAoYXJndW1lbnQudHlwZSA9PSBcIlNwcmVhZEVsZW1lbnRcIiB8fCBhcmd1bWVudC50eXBlID09IFwiQXJndW1lbnRQbGFjZWhvbGRlclwiKSB7XG4gICAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgYXJndW1lbnQudHlwZSwgbm9kZUxvY2F0aW9uKGFyZ3VtZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbnZlcnRFeHByZXNzaW9uKGFyZ3VtZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9KVxuXG4gICAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe2FyZ3VtZW50czogYXJndW1lbnRzXywgY2FsbGVlOiBub2RlLmNhbGxlZS5uYW1lLCBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJDYWxsRXhwcmVzc2lvblwiKSwgbG9jYXRpb259LCB7XG4gICAgICBjYWxsZWU6IGlkZW50aWZpZXJMb2NhdGlvbihub2RlLmNhbGxlZSwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBub2RlLnR5cGUsIGxvY2F0aW9uKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgc3VwcG9ydGVkIHJldHVybiBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5TdGF0ZW1lbnR9IG5vZGUgLSBCYWJlbCBzdGF0ZW1lbnQuXG4gKiBAcGFyYW0ge1wiamF2YXNjcmlwdFwiIHwgXCJ0eXBlc2NyaXB0XCJ9IGxhbmd1YWdlIC0gRnJvbnRlbmQgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlJldHVyblN0YXRlbWVudH0gU2VtYW50aWMgcmV0dXJuLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0UmV0dXJuKG5vZGUsIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5vZGUudHlwZSAhPSBcIlJldHVyblN0YXRlbWVudFwiIHx8ICFub2RlLmFyZ3VtZW50KSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIG5vZGUudHlwZSwgbG9jYXRpb24pXG5cbiAgcmV0dXJuIHtleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihub2RlLmFyZ3VtZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IFwiUmV0dXJuU3RhdGVtZW50XCIsIGxvY2F0aW9ufVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBzdXBwb3J0ZWQgbG9jYWwgZGVjbGFyYXRpb24gb3IgYXNzaWdubWVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLlN0YXRlbWVudH0gbm9kZSAtIEJhYmVsIHN0YXRlbWVudC5cbiAqIEBwYXJhbSB7XCJqYXZhc2NyaXB0XCIgfCBcInR5cGVzY3JpcHRcIn0gbGFuZ3VhZ2UgLSBGcm9udGVuZCBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuTG9jYWxTdGF0ZW1lbnR9IFNlbWFudGljIGxvY2FsIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydExvY2FsU3RhdGVtZW50KG5vZGUsIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKG5vZGUudHlwZSA9PSBcIlZhcmlhYmxlRGVjbGFyYXRpb25cIikge1xuICAgIGlmICghW1wibGV0XCIsIFwiY29uc3RcIl0uaW5jbHVkZXMobm9kZS5raW5kKSB8fCBub2RlLmRlY2xhcmF0aW9ucy5sZW5ndGggIT0gMSkge1xuICAgICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBgJHtub2RlLmtpbmR9IGRlY2xhcmF0aW9uYCwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgY29uc3QgZGVjbGFyYXRvciA9IG5vZGUuZGVjbGFyYXRpb25zWzBdXG4gICAgY29uc3QgZGVjbGFyYXRvckxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKGRlY2xhcmF0b3IsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICBpZiAoZGVjbGFyYXRvci5pZC50eXBlICE9IFwiSWRlbnRpZmllclwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIGRlY2xhcmF0b3IuaWQudHlwZSwgZGVjbGFyYXRvckxvY2F0aW9uKVxuICAgIGlmICghZGVjbGFyYXRvci5pbml0KSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIFwidW5pbml0aWFsaXplZCBkZWNsYXJhdGlvblwiLCBkZWNsYXJhdG9yTG9jYXRpb24pXG5cbiAgICBjb25zdCB0eXBlID0gbGFuZ3VhZ2UgPT0gXCJ0eXBlc2NyaXB0XCJcbiAgICAgID8gY29udmVydFR5cGVTY3JpcHRUeXBlKGRlY2xhcmF0b3IuaWQudHlwZUFubm90YXRpb24sIGBMb2NhbCAnJHtkZWNsYXJhdG9yLmlkLm5hbWV9J2AsIGRlY2xhcmF0b3JMb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgICAgIDogbG9jYWxKYXZhU2NyaXB0VHlwZShub2RlLCBkZWNsYXJhdG9yLmlkLm5hbWUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBpbml0aWFsaXplcjogY29udmVydEV4cHJlc3Npb24oZGVjbGFyYXRvci5pbml0LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkxvY2FsRGVjbGFyYXRpb25cIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgbXV0YWJsZTogbm9kZS5raW5kID09IFwibGV0XCIsXG4gICAgICBuYW1lOiBkZWNsYXJhdG9yLmlkLm5hbWUsXG4gICAgICB0eXBlXG4gICAgfSwge1xuICAgICAgbmFtZTogaWRlbnRpZmllckxvY2F0aW9uKGRlY2xhcmF0b3IuaWQsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgICAgb3BlcmF0b3I6IHRva2VuTG9jYXRpb24oZGVjbGFyYXRvciwgXCI9XCIsIGRlY2xhcmF0b3IuaWQuZW5kID8/IGRlY2xhcmF0b3Iuc3RhcnQgPz8gMCwgZGVjbGFyYXRvci5pbml0LnN0YXJ0ID8/IGRlY2xhcmF0b3IuZW5kID8/IHNvdXJjZS5sZW5ndGgsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSlcbiAgfVxuXG4gIGlmIChub2RlLnR5cGUgPT0gXCJFeHByZXNzaW9uU3RhdGVtZW50XCIgJiYgbm9kZS5leHByZXNzaW9uLnR5cGUgPT0gXCJBc3NpZ25tZW50RXhwcmVzc2lvblwiKSB7XG4gICAgY29uc3QgYXNzaWdubWVudCA9IG5vZGUuZXhwcmVzc2lvblxuICAgIGNvbnN0IHRhcmdldExvY2F0aW9uID0gbm9kZUxvY2F0aW9uKGFzc2lnbm1lbnQubGVmdCwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmIChhc3NpZ25tZW50Lm9wZXJhdG9yICE9IFwiPVwiKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIGBhc3NpZ25tZW50ICR7YXNzaWdubWVudC5vcGVyYXRvcn1gLCBsb2NhdGlvbilcbiAgICBpZiAoYXNzaWdubWVudC5sZWZ0LnR5cGUgIT0gXCJJZGVudGlmaWVyXCIpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgYXNzaWdubWVudC5sZWZ0LnR5cGUsIHRhcmdldExvY2F0aW9uKVxuXG4gICAgY29uc3QgdGFyZ2V0ID0gd2l0aFBhcnNlclJhbmdlcyh7a2luZDogLyoqIEB0eXBlIHtjb25zdH0gKi8gKFwiSWRlbnRpZmllckV4cHJlc3Npb25cIiksIGxvY2F0aW9uOiB0YXJnZXRMb2NhdGlvbiwgbmFtZTogYXNzaWdubWVudC5sZWZ0Lm5hbWV9LCB7XG4gICAgICBuYW1lOiBpZGVudGlmaWVyTG9jYXRpb24oYXNzaWdubWVudC5sZWZ0LCBmaWxlbmFtZSwgc291cmNlKVxuICAgIH0pXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBleHByZXNzaW9uOiBjb252ZXJ0RXhwcmVzc2lvbihhc3NpZ25tZW50LnJpZ2h0LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSksXG4gICAgICBraW5kOiBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIixcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgdGFyZ2V0XG4gICAgfSwge1xuICAgICAgb3BlcmF0b3I6IHRva2VuTG9jYXRpb24oYXNzaWdubWVudCwgXCI9XCIsIGFzc2lnbm1lbnQubGVmdC5lbmQgPz8gYXNzaWdubWVudC5zdGFydCA/PyAwLCBhc3NpZ25tZW50LnJpZ2h0LnN0YXJ0ID8/IGFzc2lnbm1lbnQuZW5kID8/IHNvdXJjZS5sZW5ndGgsIGZpbGVuYW1lLCBzb3VyY2UpXG4gICAgfSlcbiAgfVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgbm9kZS50eXBlLCBsb2NhdGlvbilcbn1cblxuLyoqXG4gKiBSZWFkcyBhbiBpbW1lZGlhdGVseSBhc3NvY2lhdGVkIEphdmFTY3JpcHQgbG9jYWwgYEB0eXBlYCB0YWcuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5WYXJpYWJsZURlY2xhcmF0aW9ufSBub2RlIC0gTG9jYWwgZGVjbGFyYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIExvY2FsIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IFNlbWFudGljIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGxvY2FsSmF2YVNjcmlwdFR5cGUobm9kZSwgbmFtZSwgZmlsZW5hbWUsIHNvdXJjZSkge1xuICBjb25zdCBjb21tZW50ID0gbm9kZS5sZWFkaW5nQ29tbWVudHM/LmF0KC0xKVxuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmICghY29tbWVudCB8fCBjb21tZW50LnR5cGUgIT0gXCJDb21tZW50QmxvY2tcIiB8fCAhY29tbWVudC52YWx1ZS5zdGFydHNXaXRoKFwiKlwiKSkge1xuICAgIHJldHVybiBtaXNzaW5nVHlwZShcImphdmFzY3JpcHRcIiwgYExvY2FsICcke25hbWV9J2AsIGxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgZ2FwID0gc291cmNlLnNsaWNlKGNvbW1lbnQuZW5kID8/IDAsIG5vZGUuc3RhcnQgPz8gMClcblxuICBpZiAoIS9eXFxzKiQvdS50ZXN0KGdhcCkgfHwgKGdhcC5tYXRjaCgvXFxuL2d1KT8ubGVuZ3RoID8/IDApID4gMSkge1xuICAgIHJldHVybiBtaXNzaW5nVHlwZShcImphdmFzY3JpcHRcIiwgYExvY2FsICcke25hbWV9J2AsIGxvY2F0aW9uKVxuICB9XG5cbiAgY29uc3QgYmxvY2sgPSBwYXJzZUNvbW1lbnQoYC8qJHtjb21tZW50LnZhbHVlfSovYClbMF1cbiAgY29uc3QgdGFncyA9IGJsb2NrPy50YWdzLmZpbHRlcigodGFnKSA9PiB0YWcudGFnID09IFwidHlwZVwiKSA/PyBbXVxuXG4gIGNvbnN0IHRhZyA9IHRhZ3MubGVuZ3RoID09IDEgPyB0YWdzWzBdIDogdW5kZWZpbmVkXG5cbiAgcmV0dXJuIGNvbnZlcnRUeXBlKFxuICAgIHRhZz8udHlwZSxcbiAgICBcImphdmFzY3JpcHRcIixcbiAgICBgTG9jYWwgJyR7bmFtZX0nYCxcbiAgICBsb2NhdGlvbixcbiAgICB0YWcgPyBjb21tZW50VGFnTG9jYXRpb24oY29tbWVudCwgdGFnLCBcInR5cGVcIiwgZmlsZW5hbWUsIHNvdXJjZSkgOiBsb2NhdGlvblxuICApXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIGV4aGF1c3RpdmUgQmFiZWwgc3RhdGVtZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuU3RhdGVtZW50fSBub2RlIC0gQmFiZWwgc3RhdGVtZW50LlxuICogQHBhcmFtIHtcImphdmFzY3JpcHRcIiB8IFwidHlwZXNjcmlwdFwifSBsYW5ndWFnZSAtIEZyb250ZW5kIGxhbmd1YWdlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2Fub25pY2FsWmVyb1JlcXVpcmVkIC0gV2hldGhlciBnZW5lcmF0ZWQgc2NhbGFyIG91dHB1dCBtYXkgY29udGFpbiBzaWduZWQgemVyby5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5TdGF0ZW1lbnR9IFNlbWFudGljIHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFN0YXRlbWVudChub2RlLCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkKSB7XG4gIGlmIChub2RlLnR5cGUgPT0gXCJSZXR1cm5TdGF0ZW1lbnRcIikgcmV0dXJuIGNvbnZlcnRSZXR1cm4obm9kZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIGlmIChub2RlLnR5cGUgPT0gXCJJZlN0YXRlbWVudFwiKSByZXR1cm4gY29udmVydElmKG5vZGUsIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlLCBjYW5vbmljYWxaZXJvUmVxdWlyZWQpXG4gIGlmIChub2RlLnR5cGUgPT0gXCJWYXJpYWJsZURlY2xhcmF0aW9uXCIgfHwgbm9kZS50eXBlID09IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiICYmIG5vZGUuZXhwcmVzc2lvbi50eXBlID09IFwiQXNzaWdubWVudEV4cHJlc3Npb25cIikge1xuICAgIHJldHVybiBjb252ZXJ0TG9jYWxTdGF0ZW1lbnQobm9kZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpXG4gIH1cbiAgaWYgKG5vZGUudHlwZSA9PSBcIkV4cHJlc3Npb25TdGF0ZW1lbnRcIikgcmV0dXJuIGNvbnZlcnRQcmludChub2RlLCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkKVxuXG4gIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgbm9kZS50eXBlLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG59XG5cbi8qKlxuICogQ29udmVydHMgb25lIEJhYmVsIGJsb2NrIG9yIG5vcm1hbGl6ZWQgc2luZ2xlLXN0YXRlbWVudCBib2R5LlxuICogQHBhcmFtIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuQmxvY2tTdGF0ZW1lbnQgfCBpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuU3RhdGVtZW50W119IGlucHV0IC0gUGFyc2VyIGJsb2NrIG9yIHN0YXRlbWVudHMuXG4gKiBAcGFyYW0ge1wiamF2YXNjcmlwdFwiIHwgXCJ0eXBlc2NyaXB0XCJ9IGxhbmd1YWdlIC0gRnJvbnRlbmQgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHBhcmFtIHtib29sZWFufSBjYW5vbmljYWxaZXJvUmVxdWlyZWQgLSBXaGV0aGVyIGdlbmVyYXRlZCBzY2FsYXIgb3V0cHV0IG1heSBjb250YWluIHNpZ25lZCB6ZXJvLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gW2xvY2F0aW9uXSAtIExvY2F0aW9uIGZvciBhIHN0YXRlbWVudC1hcnJheSBibG9jay5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5CbG9ja30gU2VtYW50aWMgYmxvY2suXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRCbG9jayhpbnB1dCwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UsIGNhbm9uaWNhbFplcm9SZXF1aXJlZCwgbG9jYXRpb24pIHtcbiAgY29uc3Qgc3RhdGVtZW50cyA9IEFycmF5LmlzQXJyYXkoaW5wdXQpID8gaW5wdXQgOiBpbnB1dC5ib2R5XG4gIGNvbnN0IGRpcmVjdGl2ZXMgPSBBcnJheS5pc0FycmF5KGlucHV0KSA/IFtdIDogaW5wdXQuZGlyZWN0aXZlc1xuICBjb25zdCBibG9ja0xvY2F0aW9uID0gbG9jYXRpb24gPz8gbm9kZUxvY2F0aW9uKC8qKiBAdHlwZSB7aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLkJsb2NrU3RhdGVtZW50fSAqLyAoaW5wdXQpLCBmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChkaXJlY3RpdmVzLmxlbmd0aCA+IDApIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIFwiZGlyZWN0aXZlXCIsIG5vZGVMb2NhdGlvbihkaXJlY3RpdmVzWzBdLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiB7XG4gICAga2luZDogXCJCbG9ja1wiLFxuICAgIGxvY2F0aW9uOiBibG9ja0xvY2F0aW9uLFxuICAgIHN0YXRlbWVudHM6IHN0YXRlbWVudHMubWFwKChzdGF0ZW1lbnQpID0+IGNvbnZlcnRTdGF0ZW1lbnQoc3RhdGVtZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkKSlcbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIEphdmFTY3JpcHQgSlNEb2MgdHlwZXMgZnJvbSBhIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbn0gbm9kZSAtIEJhYmVsIGZ1bmN0aW9uIG5vZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlIC0gQ29tcGxldGUgc291cmNlLlxuICogQHJldHVybnMge3twYXJhbWV0ZXJzOiBNYXA8c3RyaW5nLCB7bG9jYXRpb246IGltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uLCBzb3VyY2VUeXBlOiBzdHJpbmd9PiwgcmV0dXJuVHlwZToge2xvY2F0aW9uOiBpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgc291cmNlVHlwZTogc3RyaW5nfSB8IHVuZGVmaW5lZH19IFBhcnNlZCB0eXBlcy5cbiAqL1xuZnVuY3Rpb24ganNkb2NUeXBlcyhub2RlLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGNvbnN0IGNvbW1lbnQgPSBub2RlLmxlYWRpbmdDb21tZW50cz8uZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUudHlwZSA9PSBcIkNvbW1lbnRCbG9ja1wiICYmIGNhbmRpZGF0ZS52YWx1ZS5zdGFydHNXaXRoKFwiKlwiKSlcblxuICBpZiAoIWNvbW1lbnQpIG1pc3NpbmdUeXBlKFwiamF2YXNjcmlwdFwiLCBgRnVuY3Rpb24gJyR7bm9kZS5pZD8ubmFtZSA/PyBcImFub255bW91c1wifSdgLCBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG5cbiAgY29uc3QgY29tbWVudEJsb2NrID0gLyoqIEB0eXBlIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuQ29tbWVudEJsb2NrfSAqLyAoY29tbWVudClcbiAgY29uc3QgYmxvY2sgPSBwYXJzZUNvbW1lbnQoYC8qJHtjb21tZW50QmxvY2sudmFsdWV9Ki9gKVswXVxuICBjb25zdCBwYXJhbWV0ZXJzID0gbmV3IE1hcChibG9jay50YWdzLmZpbHRlcigodGFnKSA9PiB0YWcudGFnID09IFwicGFyYW1cIikubWFwKCh0YWcpID0+IFt0YWcubmFtZSwge1xuICAgIGxvY2F0aW9uOiBjb21tZW50VGFnTG9jYXRpb24oY29tbWVudEJsb2NrLCB0YWcsIFwidHlwZVwiLCBmaWxlbmFtZSwgc291cmNlKSxcbiAgICBzb3VyY2VUeXBlOiB0YWcudHlwZVxuICB9XSkpXG4gIGNvbnN0IHJldHVyblRhZyA9IGJsb2NrLnRhZ3MuZmluZCgodGFnKSA9PiB0YWcudGFnID09IFwicmV0dXJuc1wiIHx8IHRhZy50YWcgPT0gXCJyZXR1cm5cIilcblxuICByZXR1cm4ge1xuICAgIHBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZTogcmV0dXJuVGFnID8ge2xvY2F0aW9uOiBjb21tZW50VGFnTG9jYXRpb24oY29tbWVudEJsb2NrLCByZXR1cm5UYWcsIFwidHlwZVwiLCBmaWxlbmFtZSwgc291cmNlKSwgc291cmNlVHlwZTogcmV0dXJuVGFnLnR5cGV9IDogdW5kZWZpbmVkXG4gIH1cbn1cblxuLyoqXG4gKiBSZXF1aXJlcyBhIHN1cHBvcnRlZCBKYXZhU2NyaXB0IEpTRG9jIHNjYWxhciB0eXBlIHNwZWxsaW5nLlxuICogQHBhcmFtIHtzdHJpbmcgfCB1bmRlZmluZWR9IHNvdXJjZVR5cGUgLSBTb3VyY2UtbGFuZ3VhZ2UgdHlwZS5cbiAqIEBwYXJhbSB7XCJqYXZhc2NyaXB0XCIgfCBcInR5cGVzY3JpcHRcIn0gbGFuZ3VhZ2UgLSBGcm9udGVuZCBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzdWJqZWN0IC0gVHlwZWQgc3ViamVjdC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gU291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gW3R5cGVMb2NhdGlvbl0gLSBFeGFjdCB0eXBlIHRva2VuIGxvY2F0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlR5cGVSZWZlcmVuY2V9IFNlbWFudGljIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUeXBlKHNvdXJjZVR5cGUsIGxhbmd1YWdlLCBzdWJqZWN0LCBsb2NhdGlvbiwgdHlwZUxvY2F0aW9uID0gbG9jYXRpb24pIHtcbiAgcmV0dXJuIHJlcXVpcmVTb3VyY2VTY2FsYXJUeXBlKGxhbmd1YWdlLCBzb3VyY2VUeXBlLCBzdWJqZWN0LCBsb2NhdGlvbiwgdHlwZUxvY2F0aW9uKVxufVxuXG4vKipcbiAqIENvbnZlcnRzIG9uZSBleGFjdCBUeXBlU2NyaXB0IHNjYWxhciBrZXl3b3JkIGFubm90YXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5UeXBlQW5ub3RhdGlvbiB8IGltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5UU1R5cGVBbm5vdGF0aW9uIHwgaW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLk5vb3AgfCBudWxsIHwgdW5kZWZpbmVkfSBhbm5vdGF0aW9uIC0gVHlwZSBhbm5vdGF0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IHN1YmplY3QgLSBUeXBlZCBzdWJqZWN0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gb3duZXJMb2NhdGlvbiAtIE93bmluZyBkZWNsYXJhdGlvbiBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuVHlwZVJlZmVyZW5jZX0gU2VtYW50aWMgc2NhbGFyIHR5cGUuXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRUeXBlU2NyaXB0VHlwZShhbm5vdGF0aW9uLCBzdWJqZWN0LCBvd25lckxvY2F0aW9uLCBmaWxlbmFtZSwgc291cmNlKSB7XG4gIGlmICghYW5ub3RhdGlvbikgcmV0dXJuIG1pc3NpbmdUeXBlKFwidHlwZXNjcmlwdFwiLCBzdWJqZWN0LCBvd25lckxvY2F0aW9uKVxuICBpZiAoYW5ub3RhdGlvbi50eXBlICE9IFwiVFNUeXBlQW5ub3RhdGlvblwiKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KFwidHlwZXNjcmlwdFwiLCBcInVuc3VwcG9ydGVkIHNjYWxhciB0eXBlXCIsIG5vZGVMb2NhdGlvbihhbm5vdGF0aW9uLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIGNvbnN0IHR5cGVOb2RlID0gYW5ub3RhdGlvbi50eXBlQW5ub3RhdGlvblxuICBjb25zdCBzb3VyY2VUeXBlID0gdHlwZU5vZGUudHlwZSA9PSBcIlRTTnVtYmVyS2V5d29yZFwiXG4gICAgPyBcIm51bWJlclwiXG4gICAgOiB0eXBlTm9kZS50eXBlID09IFwiVFNCb29sZWFuS2V5d29yZFwiXG4gICAgICA/IFwiYm9vbGVhblwiXG4gICAgICA6IHR5cGVOb2RlLnR5cGUgPT0gXCJUU1N0cmluZ0tleXdvcmRcIiA/IFwic3RyaW5nXCIgOiB1bmRlZmluZWRcblxuICBpZiAoIXNvdXJjZVR5cGUpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgoXCJ0eXBlc2NyaXB0XCIsIFwidW5zdXBwb3J0ZWQgc2NhbGFyIHR5cGVcIiwgbm9kZUxvY2F0aW9uKHR5cGVOb2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIHJldHVybiByZXF1aXJlU291cmNlU2NhbGFyVHlwZShcInR5cGVzY3JpcHRcIiwgc291cmNlVHlwZSwgc3ViamVjdCwgb3duZXJMb2NhdGlvbiwgbm9kZUxvY2F0aW9uKHR5cGVOb2RlLCBmaWxlbmFtZSwgc291cmNlKSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHN1cHBvcnRlZCBmdW5jdGlvbiBkZWNsYXJhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb259IG5vZGUgLSBCYWJlbCBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7XCJqYXZhc2NyaXB0XCIgfCBcInR5cGVzY3JpcHRcIn0gbGFuZ3VhZ2UgLSBGcm9udGVuZCBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGNhbm9uaWNhbFplcm9SZXF1aXJlZCAtIFdoZXRoZXIgZ2VuZXJhdGVkIHNjYWxhciBvdXRwdXQgbWF5IGNvbnRhaW4gc2lnbmVkIHplcm8uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuRnVuY3Rpb25EZWNsYXJhdGlvbn0gU2VtYW50aWMgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNvbnZlcnRGdW5jdGlvbihub2RlLCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkKSB7XG4gIGNvbnN0IGxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgaWYgKCFub2RlLmlkKSByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIFwiYW5vbnltb3VzIGZ1bmN0aW9uXCIsIGxvY2F0aW9uKVxuICBpZiAobm9kZS5hc3luYykgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBcImFzeW5jIGZ1bmN0aW9uXCIsIGxvY2F0aW9uKVxuICBpZiAobm9kZS5nZW5lcmF0b3IpIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgXCJnZW5lcmF0b3IgZnVuY3Rpb25cIiwgbG9jYXRpb24pXG5cbiAgY29uc3QgZG9jdW1lbnRlZFR5cGVzID0gbGFuZ3VhZ2UgPT0gXCJqYXZhc2NyaXB0XCIgPyBqc2RvY1R5cGVzKG5vZGUsIGZpbGVuYW1lLCBzb3VyY2UpIDogdW5kZWZpbmVkXG4gIGNvbnN0IHBhcmFtZXRlcnMgPSBub2RlLnBhcmFtcy5tYXAoKHBhcmFtZXRlcikgPT4ge1xuICAgIGNvbnN0IHBhcmFtZXRlckxvY2F0aW9uID0gbm9kZUxvY2F0aW9uKHBhcmFtZXRlciwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICAgIGlmIChwYXJhbWV0ZXIudHlwZSAhPSBcIklkZW50aWZpZXJcIikgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBwYXJhbWV0ZXIudHlwZSwgcGFyYW1ldGVyTG9jYXRpb24pXG5cbiAgICBjb25zdCBkb2N1bWVudGVkVHlwZSA9IGRvY3VtZW50ZWRUeXBlcz8ucGFyYW1ldGVycy5nZXQocGFyYW1ldGVyLm5hbWUpXG4gICAgY29uc3QgdHlwZSA9IGxhbmd1YWdlID09IFwiamF2YXNjcmlwdFwiXG4gICAgICA/IGNvbnZlcnRUeXBlKGRvY3VtZW50ZWRUeXBlPy5zb3VyY2VUeXBlLCBsYW5ndWFnZSwgYFBhcmFtZXRlciAnJHtwYXJhbWV0ZXIubmFtZX0nYCwgcGFyYW1ldGVyTG9jYXRpb24sIGRvY3VtZW50ZWRUeXBlPy5sb2NhdGlvbilcbiAgICAgIDogY29udmVydFR5cGVTY3JpcHRUeXBlKHBhcmFtZXRlci50eXBlQW5ub3RhdGlvbiwgYFBhcmFtZXRlciAnJHtwYXJhbWV0ZXIubmFtZX0nYCwgcGFyYW1ldGVyTG9jYXRpb24sIGZpbGVuYW1lLCBzb3VyY2UpXG5cbiAgICByZXR1cm4gd2l0aFBhcnNlclJhbmdlcyh7XG4gICAgICBraW5kOiAvKiogQHR5cGUge2NvbnN0fSAqLyAoXCJQYXJhbWV0ZXJcIiksXG4gICAgICBsb2NhdGlvbjogcGFyYW1ldGVyTG9jYXRpb24sXG4gICAgICBuYW1lOiBwYXJhbWV0ZXIubmFtZSxcbiAgICAgIHR5cGVcbiAgICB9LCB7bmFtZTogaWRlbnRpZmllckxvY2F0aW9uKHBhcmFtZXRlciwgZmlsZW5hbWUsIHNvdXJjZSl9KVxuICB9KVxuICBjb25zdCByZXR1cm5Bbm5vdGF0aW9uID0gbm9kZS5yZXR1cm5UeXBlXG4gIGNvbnN0IHJldHVyblR5cGUgPSBsYW5ndWFnZSA9PSBcImphdmFzY3JpcHRcIlxuICAgID8gY29udmVydFR5cGUoZG9jdW1lbnRlZFR5cGVzPy5yZXR1cm5UeXBlPy5zb3VyY2VUeXBlLCBsYW5ndWFnZSwgYEZ1bmN0aW9uICcke25vZGUuaWQubmFtZX0nIHJldHVybmAsIGxvY2F0aW9uLCBkb2N1bWVudGVkVHlwZXM/LnJldHVyblR5cGU/LmxvY2F0aW9uKVxuICAgIDogY29udmVydFR5cGVTY3JpcHRUeXBlKHJldHVybkFubm90YXRpb24sIGBGdW5jdGlvbiAnJHtub2RlLmlkLm5hbWV9JyByZXR1cm5gLCBsb2NhdGlvbiwgZmlsZW5hbWUsIHNvdXJjZSlcbiAgY29uc3QgYm9keSA9IGNvbnZlcnRCbG9jayhub2RlLmJvZHksIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlLCBjYW5vbmljYWxaZXJvUmVxdWlyZWQpXG5cbiAgcmV0dXJuIHdpdGhQYXJzZXJSYW5nZXMoe1xuICAgIGJvZHksXG4gICAga2luZDogXCJGdW5jdGlvbkRlY2xhcmF0aW9uXCIsXG4gICAgbG9jYXRpb24sXG4gICAgbmFtZTogbm9kZS5pZC5uYW1lLFxuICAgIHBhcmFtZXRlcnMsXG4gICAgcmV0dXJuVHlwZVxuICB9LCB7bmFtZTogaWRlbnRpZmllckxvY2F0aW9uKG5vZGUuaWQsIGZpbGVuYW1lLCBzb3VyY2UpfSlcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZXhpc3RpbmcgZXhhY3QgaWYvZWxzZSB0ZXJtaW5hbCBzaGFwZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLklmU3RhdGVtZW50fSBub2RlIC0gQmFiZWwgaWYgc3RhdGVtZW50LlxuICogQHBhcmFtIHtcImphdmFzY3JpcHRcIiB8IFwidHlwZXNjcmlwdFwifSBsYW5ndWFnZSAtIEZyb250ZW5kIGxhbmd1YWdlLlxuICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIENvbXBsZXRlIHNvdXJjZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gY2Fub25pY2FsWmVyb1JlcXVpcmVkIC0gV2hldGhlciBnZW5lcmF0ZWQgc2NhbGFyIG91dHB1dCBtYXkgY29udGFpbiBzaWduZWQgemVyby5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9zZW1hbnRpYy90eXBlcy5qc1wiKS5JZlN0YXRlbWVudH0gU2VtYW50aWMgYnJhbmNoLlxuICovXG5mdW5jdGlvbiBjb252ZXJ0SWYobm9kZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UsIGNhbm9uaWNhbFplcm9SZXF1aXJlZCkge1xuICBjb25zdCBsb2NhdGlvbiA9IG5vZGVMb2NhdGlvbihub2RlLCBmaWxlbmFtZSwgc291cmNlKVxuICBjb25zdCBjb25zZXF1ZW50ID0gbm9kZS5jb25zZXF1ZW50LnR5cGUgPT0gXCJCbG9ja1N0YXRlbWVudFwiXG4gICAgPyBjb252ZXJ0QmxvY2sobm9kZS5jb25zZXF1ZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkKVxuICAgIDogY29udmVydEJsb2NrKFtub2RlLmNvbnNlcXVlbnRdLCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSwgY2Fub25pY2FsWmVyb1JlcXVpcmVkLCBub2RlTG9jYXRpb24obm9kZS5jb25zZXF1ZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgY29uc3QgYWx0ZXJuYXRlID0gbm9kZS5hbHRlcm5hdGVcbiAgICA/IG5vZGUuYWx0ZXJuYXRlLnR5cGUgPT0gXCJCbG9ja1N0YXRlbWVudFwiXG4gICAgICA/IGNvbnZlcnRCbG9jayhub2RlLmFsdGVybmF0ZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UsIGNhbm9uaWNhbFplcm9SZXF1aXJlZClcbiAgICAgIDogY29udmVydEJsb2NrKFtub2RlLmFsdGVybmF0ZV0sIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlLCBjYW5vbmljYWxaZXJvUmVxdWlyZWQsIG5vZGVMb2NhdGlvbihub2RlLmFsdGVybmF0ZSwgZmlsZW5hbWUsIHNvdXJjZSkpXG4gICAgOiB1bmRlZmluZWRcblxuICByZXR1cm4ge1xuICAgIC4uLihhbHRlcm5hdGUgPyB7YWx0ZXJuYXRlfSA6IHt9KSxcbiAgICBjb25kaXRpb246IGNvbnZlcnRFeHByZXNzaW9uKG5vZGUudGVzdCwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UpLFxuICAgIGNvbnNlcXVlbnQsXG4gICAga2luZDogXCJJZlN0YXRlbWVudFwiLFxuICAgIGxvY2F0aW9uXG4gIH1cbn1cblxuLyoqXG4gKiBSZXBvcnRzIHdoZXRoZXIgQmFiZWwgcGFyc2VkIGFuIG9wZXJhdGlvbiB0aGF0IG1ha2VzIGdlbmVyYXRlZCBKYXZhU2NyaXB0LWZhbWlseSBzY2FsYXIgb3V0cHV0IHJlcXVpcmUgemVybyBjYW5vbmljYWxpemF0aW9uLlxuICogQHBhcmFtIHt1bmtub3dufSB2YWx1ZSAtIEJhYmVsIHBhcnNlciBzdWJ0cmVlLlxuICogQHBhcmFtIHtXZWFrU2V0PG9iamVjdD59IFt2aXNpdGVkXSAtIEN5Y2xlIHByb3RlY3Rpb24uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgc3VidHJlZSBjb250YWlucyBpbnRlZ2VyIG5lZ2F0aW9uIG9yIG11bHRpcGxpY2F0aW9uIHN5bnRheC5cbiAqL1xuZnVuY3Rpb24gcGFyc2VyVHJlZVJlcXVpcmVzQ2Fub25pY2FsWmVybyh2YWx1ZSwgdmlzaXRlZCA9IG5ldyBXZWFrU2V0KCkpIHtcbiAgaWYgKCF2YWx1ZSB8fCB0eXBlb2YgdmFsdWUgIT0gXCJvYmplY3RcIikgcmV0dXJuIGZhbHNlXG4gIGlmICh2aXNpdGVkLmhhcyh2YWx1ZSkpIHJldHVybiBmYWxzZVxuXG4gIHZpc2l0ZWQuYWRkKHZhbHVlKVxuICBpZiAoUmVmbGVjdC5nZXQodmFsdWUsIFwidHlwZVwiKSA9PSBcIlVuYXJ5RXhwcmVzc2lvblwiICYmIFJlZmxlY3QuZ2V0KHZhbHVlLCBcIm9wZXJhdG9yXCIpID09IFwiLVwiKSByZXR1cm4gdHJ1ZVxuICBpZiAoUmVmbGVjdC5nZXQodmFsdWUsIFwidHlwZVwiKSA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIiAmJiBSZWZsZWN0LmdldCh2YWx1ZSwgXCJvcGVyYXRvclwiKSA9PSBcIipcIikgcmV0dXJuIHRydWVcblxuICByZXR1cm4gT2JqZWN0LmVudHJpZXModmFsdWUpLnNvbWUoKFtrZXksIGNoaWxkXSkgPT5cbiAgICAhW1wiZXh0cmFcIiwgXCJpbm5lckNvbW1lbnRzXCIsIFwibGVhZGluZ0NvbW1lbnRzXCIsIFwibG9jXCIsIFwidHJhaWxpbmdDb21tZW50c1wiXS5pbmNsdWRlcyhrZXkpICYmXG4gICAgKEFycmF5LmlzQXJyYXkoY2hpbGQpXG4gICAgICA/IGNoaWxkLnNvbWUoKGl0ZW0pID0+IHBhcnNlclRyZWVSZXF1aXJlc0Nhbm9uaWNhbFplcm8oaXRlbSwgdmlzaXRlZCkpXG4gICAgICA6IHBhcnNlclRyZWVSZXF1aXJlc0Nhbm9uaWNhbFplcm8oY2hpbGQsIHZpc2l0ZWQpKSlcbn1cblxuLyoqXG4gKiBSZWNvZ25pemVzIHRoZSBwYXJzZXItb3duZWQgcmVjZWl2ZXIgcGFyZW50aGVzZXMgZW1pdHRlZCBvbmx5IGZvciBjYW5vbmljYWwgaW50ZWdlciBvdXRwdXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIkBiYWJlbC90eXBlc1wiKS5FeHByZXNzaW9uIHwgaW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLlN1cGVyfSByZWNlaXZlciAtIFF1YWxpZmllZC1jYWxsIHJlY2VpdmVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuQ2FsbEV4cHJlc3Npb259IGNhbGwgLSBPdXRlciBgdG9TdHJpbmdgIGNhbGwuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgcmVjZWl2ZXIgaGFzIHRoZSBnZW5lcmF0ZWQgd3JhcHBlciBzaGFwZS5cbiAqL1xuZnVuY3Rpb24gaGFzQ2Fub25pY2FsWmVyb1JlY2VpdmVyV3JhcHBlcihyZWNlaXZlciwgY2FsbCkge1xuICBjb25zdCBleHRyYSA9IFJlZmxlY3QuZ2V0KHJlY2VpdmVyLCBcImV4dHJhXCIpXG4gIGNvbnN0IGV4cHJlc3Npb25QYXJlbnRoZXNlcyA9IFtcIkJpbmFyeUV4cHJlc3Npb25cIiwgXCJMb2dpY2FsRXhwcmVzc2lvblwiLCBcIlVuYXJ5RXhwcmVzc2lvblwiXS5pbmNsdWRlcyhyZWNlaXZlci50eXBlKSA/IDEgOiAwXG4gIGNvbnN0IHdyYXBwZXJQYXJlbnRoZXNlcyA9IGV4cHJlc3Npb25QYXJlbnRoZXNlcyArIDFcbiAgY29uc3QgcHJvcGVydHkgPSBjYWxsLmNhbGxlZS50eXBlID09IFwiTWVtYmVyRXhwcmVzc2lvblwiID8gY2FsbC5jYWxsZWUucHJvcGVydHkgOiB1bmRlZmluZWRcblxuICByZXR1cm4gQm9vbGVhbihleHRyYSkgJiYgdHlwZW9mIGV4dHJhID09IFwib2JqZWN0XCIgJiYgUmVmbGVjdC5nZXQoZXh0cmEsIFwicGFyZW50aGVzaXplZFwiKSA9PT0gdHJ1ZSAmJlxuICAgIFJlZmxlY3QuZ2V0KGV4dHJhLCBcInBhcmVuU3RhcnRcIikgPT09IGNhbGwuc3RhcnQgJiYgdHlwZW9mIGNhbGwuc3RhcnQgPT0gXCJudW1iZXJcIiAmJiB0eXBlb2YgY2FsbC5lbmQgPT0gXCJudW1iZXJcIiAmJlxuICAgIHR5cGVvZiByZWNlaXZlci5zdGFydCA9PSBcIm51bWJlclwiICYmIHR5cGVvZiByZWNlaXZlci5lbmQgPT0gXCJudW1iZXJcIiAmJiBwcm9wZXJ0eT8udHlwZSA9PSBcIklkZW50aWZpZXJcIiAmJlxuICAgIHR5cGVvZiBwcm9wZXJ0eS5zdGFydCA9PSBcIm51bWJlclwiICYmIHR5cGVvZiBwcm9wZXJ0eS5lbmQgPT0gXCJudW1iZXJcIiAmJiBjYWxsLmNhbGxlZS5zdGFydCA9PT0gY2FsbC5zdGFydCAmJlxuICAgIHJlY2VpdmVyLnN0YXJ0ID09IGNhbGwuc3RhcnQgKyB3cmFwcGVyUGFyZW50aGVzZXMgJiYgcHJvcGVydHkuc3RhcnQgPT0gcmVjZWl2ZXIuZW5kICsgd3JhcHBlclBhcmVudGhlc2VzICsgMSAmJlxuICAgIHByb3BlcnR5LmVuZCA9PSBwcm9wZXJ0eS5zdGFydCArIFwidG9TdHJpbmdcIi5sZW5ndGggJiYgY2FsbC5lbmQgPT0gcHJvcGVydHkuZW5kICsgMlxufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgY29uc29sZS5sb2cgZW50cnktcG9pbnQgY2FsbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiQGJhYmVsL3R5cGVzXCIpLlN0YXRlbWVudH0gbm9kZSAtIEJhYmVsIHN0YXRlbWVudC5cbiAqIEBwYXJhbSB7XCJqYXZhc2NyaXB0XCIgfCBcInR5cGVzY3JpcHRcIn0gbGFuZ3VhZ2UgLSBGcm9udGVuZCBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFNvdXJjZSBmaWxlbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgLSBDb21wbGV0ZSBzb3VyY2UuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGNhbm9uaWNhbFplcm9SZXF1aXJlZCAtIFdoZXRoZXIgdGhpcyBwYXJzZWQgbW9kdWxlIGNvbnRhaW5zIGEgc2lnbi1wcm9kdWNpbmcgaW50ZWdlciBvcGVyYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vc2VtYW50aWMvdHlwZXMuanNcIikuUHJpbnRTdGF0ZW1lbnR9IFByaW50IHN0YXRlbWVudC5cbiAqL1xuZnVuY3Rpb24gY29udmVydFByaW50KG5vZGUsIGxhbmd1YWdlLCBmaWxlbmFtZSwgc291cmNlLCBjYW5vbmljYWxaZXJvUmVxdWlyZWQpIHtcbiAgY29uc3QgbG9jYXRpb24gPSBub2RlTG9jYXRpb24obm9kZSwgZmlsZW5hbWUsIHNvdXJjZSlcblxuICBpZiAobm9kZS50eXBlICE9IFwiRXhwcmVzc2lvblN0YXRlbWVudFwiIHx8IG5vZGUuZXhwcmVzc2lvbi50eXBlICE9IFwiQ2FsbEV4cHJlc3Npb25cIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgbm9kZS50eXBlLCBsb2NhdGlvbilcbiAgfVxuXG4gIGNvbnN0IGNhbGwgPSBub2RlLmV4cHJlc3Npb25cbiAgY29uc3QgY2FsbGVlID0gY2FsbC5jYWxsZWVcblxuICBpZiAoY2FsbGVlLnR5cGUgIT0gXCJNZW1iZXJFeHByZXNzaW9uXCIgfHwgY2FsbGVlLmNvbXB1dGVkIHx8IGNhbGxlZS5vYmplY3QudHlwZSAhPSBcIklkZW50aWZpZXJcIiB8fFxuICAgIGNhbGxlZS5vYmplY3QubmFtZSAhPSBcImNvbnNvbGVcIiB8fCBjYWxsZWUucHJvcGVydHkudHlwZSAhPSBcIklkZW50aWZpZXJcIiB8fCBjYWxsZWUucHJvcGVydHkubmFtZSAhPSBcImxvZ1wiIHx8XG4gICAgY2FsbC5hcmd1bWVudHMubGVuZ3RoICE9IDEpIHtcbiAgICByZXR1cm4gdW5zdXBwb3J0ZWRTeW50YXgobGFuZ3VhZ2UsIFwiZW50cnktcG9pbnQgZXhwcmVzc2lvblwiLCBsb2NhdGlvbilcbiAgfVxuXG4gIGxldCBhcmd1bWVudCA9IGNhbGwuYXJndW1lbnRzWzBdXG5cbiAgaWYgKGFyZ3VtZW50LnR5cGUgPT0gXCJTcHJlYWRFbGVtZW50XCIgfHwgYXJndW1lbnQudHlwZSA9PSBcIkFyZ3VtZW50UGxhY2Vob2xkZXJcIikge1xuICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgYXJndW1lbnQudHlwZSwgbm9kZUxvY2F0aW9uKGFyZ3VtZW50LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuXG4gIGlmIChhcmd1bWVudC50eXBlID09IFwiQ2FsbEV4cHJlc3Npb25cIiAmJiBhcmd1bWVudC5jYWxsZWUudHlwZSA9PSBcIk1lbWJlckV4cHJlc3Npb25cIiAmJiAhYXJndW1lbnQuY2FsbGVlLmNvbXB1dGVkICYmXG4gICAgIWFyZ3VtZW50LmNhbGxlZS5vcHRpb25hbCAmJiBhcmd1bWVudC5jYWxsZWUub2JqZWN0LnR5cGUgIT0gXCJTdXBlclwiICYmIGFyZ3VtZW50LmNhbGxlZS5wcm9wZXJ0eS50eXBlID09IFwiSWRlbnRpZmllclwiICYmXG4gICAgYXJndW1lbnQuY2FsbGVlLnByb3BlcnR5Lm5hbWUgPT0gXCJ0b1N0cmluZ1wiICYmICFhcmd1bWVudC5vcHRpb25hbCAmJiAhYXJndW1lbnQudHlwZUFyZ3VtZW50cyAmJlxuICAgICFhcmd1bWVudC50eXBlUGFyYW1ldGVycyAmJiBhcmd1bWVudC5hcmd1bWVudHMubGVuZ3RoID09IDApIHtcbiAgICBpZiAoIWNhbm9uaWNhbFplcm9SZXF1aXJlZCB8fCAhaGFzQ2Fub25pY2FsWmVyb1JlY2VpdmVyV3JhcHBlcihhcmd1bWVudC5jYWxsZWUub2JqZWN0LCBhcmd1bWVudCkpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgXCJlbnRyeS1wb2ludCBxdWFsaWZpZWQgY2FsbFwiLCBub2RlTG9jYXRpb24oYXJndW1lbnQuY2FsbGVlLnByb3BlcnR5LCBmaWxlbmFtZSwgc291cmNlKSlcbiAgICB9XG4gICAgYXJndW1lbnQgPSBhcmd1bWVudC5jYWxsZWUub2JqZWN0XG4gIH1cblxuICByZXR1cm4ge2V4cHJlc3Npb246IGNvbnZlcnRFeHByZXNzaW9uKGFyZ3VtZW50LCBsYW5ndWFnZSwgZmlsZW5hbWUsIHNvdXJjZSksIGtpbmQ6IFwiUHJpbnRTdGF0ZW1lbnRcIiwgbG9jYXRpb259XG59XG5cbi8qKlxuICogUGFyc2VzIEphdmFTY3JpcHQgb3IgVHlwZVNjcmlwdCBpbnRvIHRoZSBzaGFyZWQgc2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtvYmplY3R9IGlucHV0IC0gUGFyc2VyIGlucHV0LlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LmZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtcImphdmFzY3JpcHRcIiB8IFwidHlwZXNjcmlwdFwifSBpbnB1dC5sYW5ndWFnZSAtIEZyb250ZW5kIGxhbmd1YWdlLlxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0LnNvdXJjZSAtIFNvdXJjZSB0ZXh0LlxuICogQHJldHVybnMge2ltcG9ydChcIi4uL3NlbWFudGljL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBTZW1hbnRpYyBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUphdmFTY3JpcHRUeXBlU2NyaXB0KHtmaWxlbmFtZSwgbGFuZ3VhZ2UsIHNvdXJjZX0pIHtcbiAgY29uc3QgZmlsZSA9IHBhcnNlQmFiZWxTb3VyY2Uoe2ZpbGVuYW1lLCBsYW5ndWFnZSwgc291cmNlfSlcbiAgY29uc3QgdG9rZW5zID0gZmlsZS50b2tlbnMgPz8gW11cbiAgY29uc3QgdG9rZW5JbmRleCA9IHtieVN0YXJ0OiBuZXcgTWFwKHRva2Vucy5tYXAoKHRva2VuKSA9PiBbdG9rZW4uc3RhcnQsIHRva2VuXSkpLCB0b2tlbnN9XG4gIGNvbnN0IGNhbm9uaWNhbFplcm9SZXF1aXJlZCA9IHBhcnNlclRyZWVSZXF1aXJlc0Nhbm9uaWNhbFplcm8oZmlsZS5wcm9ncmFtKVxuXG4gIHJlbWVtYmVyVG9rZW5zKGZpbGUsIHRva2VuSW5kZXgpXG4gIGlmIChmaWxlLnByb2dyYW0uZGlyZWN0aXZlcy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIHVuc3VwcG9ydGVkU3ludGF4KGxhbmd1YWdlLCBcInRvcC1sZXZlbCBkaXJlY3RpdmVcIiwgbm9kZUxvY2F0aW9uKGZpbGUucHJvZ3JhbS5kaXJlY3RpdmVzWzBdLCBmaWxlbmFtZSwgc291cmNlKSlcbiAgfVxuICBjb25zdCBmdW5jdGlvbnMgPSBmaWxlLnByb2dyYW0uYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUudHlwZSA9PSBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIilcbiAgICAubWFwKChub2RlKSA9PiBjb252ZXJ0RnVuY3Rpb24obm9kZSwgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UsIGNhbm9uaWNhbFplcm9SZXF1aXJlZCkpXG4gIGNvbnN0IGVudHJ5Tm9kZXMgPSBmaWxlLnByb2dyYW0uYm9keS5maWx0ZXIoKG5vZGUpID0+IG5vZGUudHlwZSAhPSBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIilcbiAgY29uc3QgbG9jYXRpb24gPSBtb2R1bGVMb2NhdGlvbihmaWxlbmFtZSwgc291cmNlKVxuXG4gIGlmIChmdW5jdGlvbnMubGVuZ3RoID09IDApIHJldHVybiB1bnN1cHBvcnRlZFN5bnRheChsYW5ndWFnZSwgXCJtb2R1bGUgd2l0aG91dCBhIGZ1bmN0aW9uXCIsIGxvY2F0aW9uKVxuICBjb25zdCBlbnRyeUxvY2F0aW9uID0gZW50cnlOb2Rlcy5sZW5ndGggPT0gMCA/IGxvY2F0aW9uIDogbG9jYXRpb25Gcm9tT2Zmc2V0cyhcbiAgICBmaWxlbmFtZSxcbiAgICBzb3VyY2UsXG4gICAgZW50cnlOb2Rlc1swXS5zdGFydCA/PyAwLFxuICAgIGVudHJ5Tm9kZXMuYXQoLTEpPy5lbmQgPz8gc291cmNlLmxlbmd0aFxuICApXG4gIGNvbnN0IGVudHJ5QmxvY2sgPSBjb252ZXJ0QmxvY2soZW50cnlOb2RlcywgbGFuZ3VhZ2UsIGZpbGVuYW1lLCBzb3VyY2UsIGNhbm9uaWNhbFplcm9SZXF1aXJlZCwgZW50cnlMb2NhdGlvbilcblxuICByZXR1cm4ge1xuICAgIGVudHJ5UG9pbnQ6IHtcbiAgICAgIGJvZHk6IGVudHJ5QmxvY2ssXG4gICAgICBraW5kOiBcIkVudHJ5UG9pbnRcIixcbiAgICAgIGxvY2F0aW9uOiBlbnRyeUxvY2F0aW9uXG4gICAgfSxcbiAgICBmdW5jdGlvbnMsXG4gICAga2luZDogXCJNb2R1bGVcIixcbiAgICBsb2NhdGlvblxuICB9XG59XG5cbi8qKlxuICogSW52b2tlcyBCYWJlbCBhbmQgbm9ybWFsaXplcyBzeW50YXggZmFpbHVyZXMuXG4gKiBAcGFyYW0ge29iamVjdH0gaW5wdXQgLSBQYXJzZXIgaW5wdXQuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQuZmlsZW5hbWUgLSBTb3VyY2UgZmlsZW5hbWUuXG4gKiBAcGFyYW0ge1wiamF2YXNjcmlwdFwiIHwgXCJ0eXBlc2NyaXB0XCJ9IGlucHV0Lmxhbmd1YWdlIC0gRnJvbnRlbmQgbGFuZ3VhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQuc291cmNlIC0gU291cmNlIHRleHQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiQGJhYmVsL3BhcnNlclwiKS5QYXJzZVJlc3VsdDxpbXBvcnQoXCJAYmFiZWwvdHlwZXNcIikuRmlsZT59IEJhYmVsIGZpbGUuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlQmFiZWxTb3VyY2Uoe2ZpbGVuYW1lLCBsYW5ndWFnZSwgc291cmNlfSkge1xuICB0cnkge1xuICAgIHJldHVybiBwYXJzZUJhYmVsKHNvdXJjZSwge1xuICAgICAgcGx1Z2luczogbGFuZ3VhZ2UgPT0gXCJ0eXBlc2NyaXB0XCIgPyBbXCJ0eXBlc2NyaXB0XCJdIDogW10sXG4gICAgICBzb3VyY2VGaWxlbmFtZTogZmlsZW5hbWUsXG4gICAgICBzb3VyY2VUeXBlOiBcInNjcmlwdFwiLFxuICAgICAgdG9rZW5zOiB0cnVlXG4gICAgfSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gcGFyc2VGYWlsdXJlKGxhbmd1YWdlLCBlcnJvcilcbiAgfVxufVxuXG4vKipcbiAqIEFzc29jaWF0ZXMgQmFiZWwgbm9kZXMgd2l0aCB0aGVpciBwYXJzZXIgdG9rZW4gc3RyZWFtIHdpdGhvdXQgbGVha2luZyBpdCBpbnRvIHNlbWFudGljIHZhbHVlcy5cbiAqIEBwYXJhbSB7b2JqZWN0fSB2YWx1ZSAtIEN1cnJlbnQgcGFyc2VyIHZhbHVlLlxuICogQHBhcmFtIHtCYWJlbFRva2VuSW5kZXh9IHRva2VucyAtIEluZGV4ZWQgcGFyc2VyIHRva2Vucy5cbiAqIEBwYXJhbSB7V2Vha1NldDxvYmplY3Q+fSBbdmlzaXRlZF0gLSBDeWNsZSBwcm90ZWN0aW9uLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHJlbWVtYmVyVG9rZW5zKHZhbHVlLCB0b2tlbnMsIHZpc2l0ZWQgPSBuZXcgV2Vha1NldCgpKSB7XG4gIGlmICh2aXNpdGVkLmhhcyh2YWx1ZSkpIHJldHVyblxuXG4gIHZpc2l0ZWQuYWRkKHZhbHVlKVxuICBub2RlVG9rZW5zLnNldCh2YWx1ZSwgdG9rZW5zKVxuXG4gIGZvciAoY29uc3QgY2hpbGQgb2YgT2JqZWN0LnZhbHVlcyh2YWx1ZSkpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjaGlsZCkpIHtcbiAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBjaGlsZCkgaWYgKGl0ZW0gJiYgdHlwZW9mIGl0ZW0gPT0gXCJvYmplY3RcIikgcmVtZW1iZXJUb2tlbnMoaXRlbSwgdG9rZW5zLCB2aXNpdGVkKVxuICAgIH0gZWxzZSBpZiAoY2hpbGQgJiYgdHlwZW9mIGNoaWxkID09IFwib2JqZWN0XCIpIHJlbWVtYmVyVG9rZW5zKGNoaWxkLCB0b2tlbnMsIHZpc2l0ZWQpXG4gIH1cbn1cbiJdfQ==
|