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.
Files changed (111) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +71 -0
  3. package/build/index.d.ts +54 -0
  4. package/build/index.d.ts.map +1 -0
  5. package/build/index.js +45 -0
  6. package/build/src/backends/identifiers.d.ts +19 -0
  7. package/build/src/backends/identifiers.d.ts.map +1 -0
  8. package/build/src/backends/identifiers.js +93 -0
  9. package/build/src/backends/index.d.ts +35 -0
  10. package/build/src/backends/index.d.ts.map +1 -0
  11. package/build/src/backends/index.js +149 -0
  12. package/build/src/backends/java.d.ts +8 -0
  13. package/build/src/backends/java.d.ts.map +1 -0
  14. package/build/src/backends/java.js +172 -0
  15. package/build/src/backends/javascript.d.ts +8 -0
  16. package/build/src/backends/javascript.d.ts.map +1 -0
  17. package/build/src/backends/javascript.js +173 -0
  18. package/build/src/backends/php.d.ts +8 -0
  19. package/build/src/backends/php.d.ts.map +1 -0
  20. package/build/src/backends/php.js +175 -0
  21. package/build/src/backends/ruby.d.ts +8 -0
  22. package/build/src/backends/ruby.d.ts.map +1 -0
  23. package/build/src/backends/ruby.js +155 -0
  24. package/build/src/backends/scalars.d.ts +15 -0
  25. package/build/src/backends/scalars.d.ts.map +1 -0
  26. package/build/src/backends/scalars.js +138 -0
  27. package/build/src/backends/shared.d.ts +26 -0
  28. package/build/src/backends/shared.d.ts.map +1 -0
  29. package/build/src/backends/shared.js +424 -0
  30. package/build/src/backends/typescript.d.ts +8 -0
  31. package/build/src/backends/typescript.d.ts.map +1 -0
  32. package/build/src/backends/typescript.js +160 -0
  33. package/build/src/backends/writer.d.ts +87 -0
  34. package/build/src/backends/writer.d.ts.map +1 -0
  35. package/build/src/backends/writer.js +207 -0
  36. package/build/src/diagnostic.d.ts +67 -0
  37. package/build/src/diagnostic.d.ts.map +1 -0
  38. package/build/src/diagnostic.js +96 -0
  39. package/build/src/frontends/index.d.ts +14 -0
  40. package/build/src/frontends/index.d.ts.map +1 -0
  41. package/build/src/frontends/index.js +36 -0
  42. package/build/src/frontends/java.d.ts +12 -0
  43. package/build/src/frontends/java.d.ts.map +1 -0
  44. package/build/src/frontends/java.js +630 -0
  45. package/build/src/frontends/javascript-typescript.d.ts +19 -0
  46. package/build/src/frontends/javascript-typescript.d.ts.map +1 -0
  47. package/build/src/frontends/javascript-typescript.js +633 -0
  48. package/build/src/frontends/php.d.ts +12 -0
  49. package/build/src/frontends/php.d.ts.map +1 -0
  50. package/build/src/frontends/php.js +523 -0
  51. package/build/src/frontends/ruby.d.ts +12 -0
  52. package/build/src/frontends/ruby.d.ts.map +1 -0
  53. package/build/src/frontends/ruby.js +515 -0
  54. package/build/src/frontends/scalars.d.ts +19 -0
  55. package/build/src/frontends/scalars.d.ts.map +1 -0
  56. package/build/src/frontends/scalars.js +71 -0
  57. package/build/src/mapping.d.ts +160 -0
  58. package/build/src/mapping.d.ts.map +1 -0
  59. package/build/src/mapping.js +1120 -0
  60. package/build/src/semantic/location.d.ts +61 -0
  61. package/build/src/semantic/location.d.ts.map +1 -0
  62. package/build/src/semantic/location.js +142 -0
  63. package/build/src/semantic/operators.d.ts +16 -0
  64. package/build/src/semantic/operators.d.ts.map +1 -0
  65. package/build/src/semantic/operators.js +24 -0
  66. package/build/src/semantic/provenance.d.ts +74 -0
  67. package/build/src/semantic/provenance.d.ts.map +1 -0
  68. package/build/src/semantic/provenance.js +577 -0
  69. package/build/src/semantic/scalars.d.ts +19 -0
  70. package/build/src/semantic/scalars.d.ts.map +1 -0
  71. package/build/src/semantic/scalars.js +40 -0
  72. package/build/src/semantic/types.d.ts +1003 -0
  73. package/build/src/semantic/types.d.ts.map +1 -0
  74. package/build/src/semantic/types.js +279 -0
  75. package/build/src/semantic/validate.d.ts +60 -0
  76. package/build/src/semantic/validate.d.ts.map +1 -0
  77. package/build/src/semantic/validate.js +472 -0
  78. package/docs/architecture.md +39 -0
  79. package/docs/coding-standards.md +7 -0
  80. package/docs/goals.md +7 -0
  81. package/docs/language-support.md +69 -0
  82. package/docs/plans/2026-09-02-initial-toolchain.md +54 -0
  83. package/docs/source-maps.md +134 -0
  84. package/docs/testing.md +25 -0
  85. package/index.js +63 -0
  86. package/package.json +69 -0
  87. package/src/backends/identifiers.js +101 -0
  88. package/src/backends/index.js +159 -0
  89. package/src/backends/java.js +182 -0
  90. package/src/backends/javascript.js +184 -0
  91. package/src/backends/php.js +184 -0
  92. package/src/backends/ruby.js +163 -0
  93. package/src/backends/scalars.js +120 -0
  94. package/src/backends/shared.js +456 -0
  95. package/src/backends/typescript.js +168 -0
  96. package/src/backends/writer.js +224 -0
  97. package/src/diagnostic.js +103 -0
  98. package/src/frontends/index.js +36 -0
  99. package/src/frontends/java.js +735 -0
  100. package/src/frontends/javascript-typescript.js +718 -0
  101. package/src/frontends/php.js +593 -0
  102. package/src/frontends/ruby.js +622 -0
  103. package/src/frontends/scalars.js +77 -0
  104. package/src/mapping.js +1260 -0
  105. package/src/semantic/location.js +154 -0
  106. package/src/semantic/operators.js +28 -0
  107. package/src/semantic/provenance.js +629 -0
  108. package/src/semantic/scalars.js +44 -0
  109. package/src/semantic/types.js +319 -0
  110. package/src/semantic/validate.js +529 -0
  111. package/tsconfig.json +16 -0
@@ -0,0 +1,577 @@
1
+ // @ts-check
2
+ import { createCoordinateIndex, indexedPointAt } from "./location.js";
3
+ /** @type {WeakMap<object, Readonly<Record<string, import("./types.js").SourceLocation>>>} */
4
+ const parserRanges = new WeakMap();
5
+ /** @type {WeakMap<import("./types.js").RegisteredSource, ReturnType<typeof createCoordinateIndex>>} */
6
+ const sourceCoordinateIndexes = new WeakMap();
7
+ /**
8
+ * Records parser-provided semantic-token ranges without exposing parser trees.
9
+ * @param {object} node - Semantic node.
10
+ * @param {Readonly<Record<string, import("./types.js").SourceLocation>>} ranges - Exact role ranges.
11
+ * @returns {void}
12
+ */
13
+ export function setParserRanges(node, ranges) {
14
+ parserRanges.set(node, ranges);
15
+ }
16
+ /**
17
+ * Records parser ranges and returns the same semantic node.
18
+ * @template {object} Node
19
+ * @param {Node} node - Semantic node.
20
+ * @param {Readonly<Record<string, import("./types.js").SourceLocation>>} ranges - Exact role ranges.
21
+ * @returns {Node} The same node.
22
+ */
23
+ export function withParserRanges(node, ranges) {
24
+ setParserRanges(node, ranges);
25
+ return node;
26
+ }
27
+ /**
28
+ * Adds deterministic provenance to a validated frontend module.
29
+ * @param {import("./types.js").SemanticModule} module - Validated semantic module.
30
+ * @param {object} source - Parsed source.
31
+ * @param {string} source.filename - Source filename.
32
+ * @param {import("./types.js").SemanticLanguage} source.language - Source language.
33
+ * @param {string} source.source - Exact source content.
34
+ * @returns {import("./types.js").SemanticModule} The same semantic module.
35
+ */
36
+ export function annotateParsedModule(module, { filename, language, source }) {
37
+ const sources = [{ content: source, filename, id: "source:0", language }];
38
+ const entries = semanticEntries(module);
39
+ /** @type {Map<string, import("./types.js").SemanticNodeProvenance>} */
40
+ const recordsByPath = new Map();
41
+ /** @type {import("./types.js").SemanticNodeProvenance[]} */
42
+ const records = [];
43
+ for (const [index, entry] of entries.entries()) {
44
+ const ranges = parserRanges.get(entry.node) ?? {};
45
+ const location = "location" in entry.node ? entry.node.location : ranges.type ?? entry.ownerLocation;
46
+ const sourceProvenance = /** @type {import("./types.js").SemanticNodeSourceProvenance} */ ({
47
+ origin: { kind: "source", location, sourceId: "source:0" },
48
+ ranges,
49
+ schema: "SemantifoldNodeProvenance",
50
+ version: 1
51
+ });
52
+ const record = {
53
+ id: `node:${index}`,
54
+ kind: entry.node.kind,
55
+ origin: sourceProvenance.origin,
56
+ path: entry.path,
57
+ ranges: sourceProvenance.ranges
58
+ };
59
+ records.push(record);
60
+ recordsByPath.set(entry.path, record);
61
+ entry.node.sourceProvenance = sourceProvenance;
62
+ }
63
+ const symbols = resolveSymbols(module, recordsByPath);
64
+ module.provenance = {
65
+ coordinateSystem: "utf16",
66
+ nodes: records,
67
+ schema: "SemantifoldProvenance",
68
+ sources,
69
+ symbols,
70
+ version: 1
71
+ };
72
+ return module;
73
+ }
74
+ /**
75
+ * Rebuilds canonical generation metadata without trusting caller-provided identities.
76
+ * @param {import("./types.js").SemanticModule} module - Semantic module.
77
+ * @param {{filename: string, content: string, language?: import("./types.js").SemanticLanguage}[]} [providedSources] - Additional source content.
78
+ * @returns {{provenance: import("./types.js").SemanticProvenance, recordFor: (node: import("./types.js").SemanticNode, path?: string) => import("./types.js").SemanticNodeProvenance}} Canonical index.
79
+ */
80
+ export function createGenerationIndex(module, providedSources = []) {
81
+ const entries = semanticEntries(module);
82
+ const priorSources = usableSourceProvenance(module.provenance);
83
+ /** @type {import("./types.js").RegisteredSource[]} */
84
+ const sources = [];
85
+ /** @type {Map<string, import("./types.js").RegisteredSource>} */
86
+ const priorSourcesById = new Map();
87
+ for (const source of providedSources)
88
+ addSource(source.filename, source.content, source.language ?? null);
89
+ if (priorSources) {
90
+ for (const source of priorSources.sources) {
91
+ const canonical = addSource(source.filename, source.content, source.language);
92
+ priorSourcesById.set(source.id, canonical);
93
+ }
94
+ }
95
+ for (const entry of entries) {
96
+ const location = "location" in entry.node ? entry.node.location : entry.ownerLocation;
97
+ if (!sources.some((source) => source.filename == location.filename))
98
+ addSource(location.filename, null, null);
99
+ }
100
+ const verifiableSources = sources.filter((source) => source.content != null);
101
+ /** @type {Map<object, import("./types.js").SemanticNodeProvenance[]>} */
102
+ const recordsByNode = new Map();
103
+ /** @type {Map<string, import("./types.js").SemanticNodeProvenance>} */
104
+ const recordsByPath = new Map();
105
+ /** @type {import("./types.js").SemanticNodeProvenance[]} */
106
+ const records = [];
107
+ for (const [index, entry] of entries.entries()) {
108
+ const located = "location" in entry.node ? entry.node.location : entry.ownerLocation;
109
+ const associated = usableNodeProvenance(entry.node.sourceProvenance);
110
+ const ranges = associated ? validRanges(associated.ranges, verifiableSources) : {};
111
+ const normalizedOrigin = associated
112
+ ? normalizeOrigin(associated.origin, priorSourcesById, verifiableSources)
113
+ : undefined;
114
+ const fallbackSource = sourceForLocation(located, sources);
115
+ const origin = normalizedOrigin ?? sourceOrigin(fallbackSource, located);
116
+ const record = {
117
+ id: `node:${index}`,
118
+ kind: entry.node.kind,
119
+ origin,
120
+ path: entry.path,
121
+ ranges
122
+ };
123
+ records.push(record);
124
+ recordsByPath.set(entry.path, record);
125
+ const occurrences = recordsByNode.get(entry.node) ?? [];
126
+ occurrences.push(record);
127
+ recordsByNode.set(entry.node, occurrences);
128
+ }
129
+ const symbols = resolveSymbols(module, recordsByPath);
130
+ const provenance = /** @type {import("./types.js").SemanticProvenance} */ ({
131
+ coordinateSystem: "utf16",
132
+ nodes: records,
133
+ schema: "SemantifoldProvenance",
134
+ sources,
135
+ symbols,
136
+ version: 1
137
+ });
138
+ return {
139
+ provenance,
140
+ recordFor(node, path) {
141
+ const occurrences = recordsByNode.get(node);
142
+ if (!occurrences)
143
+ throw new RangeError("Semantic node is not part of this module.");
144
+ if (path !== undefined) {
145
+ const record = occurrences.find((candidate) => candidate.path == path);
146
+ if (!record)
147
+ throw new RangeError(`Semantic node does not occur at '${path}'.`);
148
+ return record;
149
+ }
150
+ if (occurrences.length != 1) {
151
+ throw new RangeError("Shared semantic node requires an occurrence path.");
152
+ }
153
+ return occurrences[0];
154
+ }
155
+ };
156
+ /**
157
+ * Registers one canonical source.
158
+ * @param {string} filename - Source filename.
159
+ * @param {string | null} content - Source content.
160
+ * @param {import("./types.js").SemanticLanguage | null} language - Source language.
161
+ * @returns {import("./types.js").RegisteredSource} Canonical source.
162
+ */
163
+ function addSource(filename, content, language) {
164
+ if (typeof filename != "string" || content !== null && typeof content != "string" ||
165
+ language !== null && !["php", "ruby", "javascript", "typescript", "java"].includes(language)) {
166
+ throw new TypeError("Malformed semantic source registry entry.");
167
+ }
168
+ const existing = sources.find((source) => source.filename == filename && source.content == content);
169
+ if (existing)
170
+ return existing;
171
+ const registered = { content, filename, id: `source:${sources.length}`, language };
172
+ sources.push(registered);
173
+ return registered;
174
+ }
175
+ }
176
+ /**
177
+ * Selects the safe primary original location for closed provenance.
178
+ * @param {import("./types.js").SemanticOrigin} origin - Closed provenance.
179
+ * @returns {import("./types.js").SourceLocation | undefined} Primary location.
180
+ */
181
+ export function primaryLocation(origin) {
182
+ if (origin.kind == "source")
183
+ return origin.location;
184
+ if (origin.kind == "derived")
185
+ return origin.origins[0]?.location;
186
+ return origin.relatedOrigins[0]?.location;
187
+ }
188
+ /**
189
+ * Accepts source metadata only when it is attached to the semantic node it describes.
190
+ * Registry-local IDs and paths are intentionally ignored and rebuilt.
191
+ * @param {import("./types.js").SemanticNodeSourceProvenance | undefined} record - Candidate node association.
192
+ * @returns {import("./types.js").SemanticNodeSourceProvenance | undefined} Usable association.
193
+ */
194
+ function usableNodeProvenance(record) {
195
+ if (!record || record.schema != "SemantifoldNodeProvenance" || record.version != 1 ||
196
+ !record.origin || typeof record.origin != "object" ||
197
+ !record.ranges || typeof record.ranges != "object" || Array.isArray(record.ranges))
198
+ return undefined;
199
+ return record;
200
+ }
201
+ /**
202
+ * Retains a valid source registry independently from potentially stale node metadata.
203
+ * @param {import("./types.js").SemanticProvenance | undefined} provenance - Candidate provenance.
204
+ * @returns {import("./types.js").SemanticProvenance | undefined} Provenance with a usable source registry.
205
+ */
206
+ function usableSourceProvenance(provenance) {
207
+ if (!provenance || provenance.schema != "SemantifoldProvenance" || provenance.version != 1 ||
208
+ provenance.coordinateSystem != "utf16" || !Array.isArray(provenance.sources))
209
+ return undefined;
210
+ const sourceIds = new Set();
211
+ for (const source of provenance.sources) {
212
+ if (!source || typeof source.id != "string" || sourceIds.has(source.id) || typeof source.filename != "string" ||
213
+ source.filename.length == 0 ||
214
+ source.content !== null && typeof source.content != "string" || source.language !== null &&
215
+ !["php", "ruby", "javascript", "typescript", "java"].includes(source.language))
216
+ return undefined;
217
+ sourceIds.add(source.id);
218
+ }
219
+ return provenance;
220
+ }
221
+ /**
222
+ * Retains only self-consistent source ranges.
223
+ * @param {Readonly<Record<string, import("./types.js").SourceLocation>>} ranges - Candidate ranges.
224
+ * @param {import("./types.js").RegisteredSource[]} sources - Canonical sources.
225
+ * @returns {Readonly<Record<string, import("./types.js").SourceLocation>>} Safe ranges.
226
+ */
227
+ function validRanges(ranges, sources) {
228
+ if (!ranges || typeof ranges != "object" || Array.isArray(ranges))
229
+ return {};
230
+ /** @type {Record<string, import("./types.js").SourceLocation>} */
231
+ const valid = {};
232
+ for (const [role, location] of Object.entries(ranges)) {
233
+ if (validLocation(location, sources))
234
+ valid[role] = location;
235
+ }
236
+ return valid;
237
+ }
238
+ /**
239
+ * Normalizes a closed origin while remapping untrusted source identities.
240
+ * @param {import("./types.js").SemanticOrigin} origin - Candidate origin.
241
+ * @param {Map<string, import("./types.js").RegisteredSource>} priorSources - Prior-to-canonical source mapping.
242
+ * @param {import("./types.js").RegisteredSource[]} sources - Canonical sources.
243
+ * @returns {import("./types.js").SemanticOrigin | undefined} Safe origin.
244
+ */
245
+ function normalizeOrigin(origin, priorSources, sources) {
246
+ if (!origin || typeof origin != "object")
247
+ return undefined;
248
+ if (origin.kind == "source" && validLocation(origin.location, sources)) {
249
+ const claimed = priorSources.get(origin.sourceId);
250
+ const source = claimed && sourceOwnsLocation(claimed, origin.location) ? claimed : sourceForLocation(origin.location, sources);
251
+ return sourceOrigin(source, origin.location);
252
+ }
253
+ if (origin.kind == "derived" && Array.isArray(origin.origins) && origin.origins.length > 0) {
254
+ const origins = origin.origins.map((related) => normalizeRelatedOrigin(related, priorSources, sources));
255
+ if (origins.every(Boolean))
256
+ return { kind: "derived", origins: /** @type {import("./types.js").RelatedOrigin[]} */ (origins) };
257
+ }
258
+ if (origin.kind == "synthetic" && typeof origin.reason == "string" && Array.isArray(origin.relatedOrigins)) {
259
+ const relatedOrigins = origin.relatedOrigins.map((related) => normalizeRelatedOrigin(related, priorSources, sources));
260
+ if (relatedOrigins.every(Boolean)) {
261
+ return { kind: "synthetic", reason: origin.reason, relatedOrigins: /** @type {import("./types.js").RelatedOrigin[]} */ (relatedOrigins) };
262
+ }
263
+ }
264
+ return undefined;
265
+ }
266
+ /**
267
+ * Normalizes one related origin.
268
+ * @param {import("./types.js").RelatedOrigin} related - Candidate related origin.
269
+ * @param {Map<string, import("./types.js").RegisteredSource>} priorSources - Prior sources.
270
+ * @param {import("./types.js").RegisteredSource[]} sources - Canonical sources.
271
+ * @returns {import("./types.js").RelatedOrigin | undefined} Safe related origin.
272
+ */
273
+ function normalizeRelatedOrigin(related, priorSources, sources) {
274
+ if (!related || !validLocation(related.location, sources))
275
+ return undefined;
276
+ const claimed = priorSources.get(related.sourceId);
277
+ const source = claimed && sourceOwnsLocation(claimed, related.location) ? claimed : sourceForLocation(related.location, sources);
278
+ const normalized = { location: related.location, sourceId: source.id };
279
+ if (typeof related.role == "string")
280
+ Object.assign(normalized, { role: related.role });
281
+ return normalized;
282
+ }
283
+ /**
284
+ * Checks normalized coordinates against exact source content when available.
285
+ * @param {import("./types.js").SourceLocation} location - Candidate location.
286
+ * @param {import("./types.js").RegisteredSource[]} sources - Registered sources.
287
+ * @returns {boolean} Whether the location is safe.
288
+ */
289
+ function validLocation(location, sources) {
290
+ if (!location || typeof location.filename != "string" || !location.start || !location.end ||
291
+ !Number.isInteger(location.start.offset) || !Number.isInteger(location.end.offset) || location.start.offset < 0 ||
292
+ location.end.offset < location.start.offset || !validPointShape(location.start) || !validPointShape(location.end))
293
+ return false;
294
+ const candidates = sources.filter((source) => source.filename == location.filename);
295
+ return candidates.some((source) => sourceOwnsLocation(source, location));
296
+ }
297
+ /**
298
+ * Checks that one identified registry source owns a normalized location.
299
+ * @param {import("./types.js").RegisteredSource} source - Identified source.
300
+ * @param {import("./types.js").SourceLocation} location - Candidate location.
301
+ * @returns {boolean} Whether the source owns the location.
302
+ */
303
+ function sourceOwnsLocation(source, location) {
304
+ if (source.filename != location.filename)
305
+ return false;
306
+ if (source.content == null)
307
+ return true;
308
+ if (location.end.offset > source.content.length)
309
+ return false;
310
+ let coordinates = sourceCoordinateIndexes.get(source);
311
+ if (!coordinates) {
312
+ coordinates = createCoordinateIndex(source.content);
313
+ sourceCoordinateIndexes.set(source, coordinates);
314
+ }
315
+ return samePoint(indexedPointAt(coordinates, location.start.offset), location.start) &&
316
+ samePoint(indexedPointAt(coordinates, location.end.offset), location.end);
317
+ }
318
+ /**
319
+ * Checks the integer shape of one source point.
320
+ * @param {import("./types.js").SourcePoint} point - Source point.
321
+ * @returns {boolean} Whether it is structurally valid.
322
+ */
323
+ function validPointShape(point) {
324
+ return Number.isInteger(point.line) && point.line >= 1 && Number.isInteger(point.column) && point.column >= 1;
325
+ }
326
+ /**
327
+ * Compares normalized source coordinates.
328
+ * @param {import("./types.js").SourcePoint} left - Left point.
329
+ * @param {import("./types.js").SourcePoint} right - Right point.
330
+ * @returns {boolean} Whether all coordinates match.
331
+ */
332
+ function samePoint(left, right) {
333
+ return left.offset == right.offset && left.line == right.line && left.column == right.column;
334
+ }
335
+ /**
336
+ * Finds the deterministic source owning a location.
337
+ * @param {import("./types.js").SourceLocation} location - Source location.
338
+ * @param {import("./types.js").RegisteredSource[]} sources - Canonical sources.
339
+ * @returns {import("./types.js").RegisteredSource} Owning source.
340
+ */
341
+ function sourceForLocation(location, sources) {
342
+ const source = sources.find((candidate) => sourceOwnsLocation(candidate, location));
343
+ if (!source)
344
+ throw new RangeError(`No registered source owns ${location.filename}:${location.start.offset}.`);
345
+ return source;
346
+ }
347
+ /**
348
+ * Creates direct source provenance.
349
+ * @param {import("./types.js").RegisteredSource} source - Source.
350
+ * @param {import("./types.js").SourceLocation} location - Location.
351
+ * @returns {import("./types.js").SourceOrigin} Origin.
352
+ */
353
+ function sourceOrigin(source, location) {
354
+ return { kind: "source", location, sourceId: source.id };
355
+ }
356
+ /**
357
+ * Finds one node provenance record by semantic object or node identity.
358
+ * @param {import("./types.js").SemanticModule} module - Semantic module.
359
+ * @param {import("./types.js").SemanticNode | string} node - Semantic object or node identity.
360
+ * @returns {import("./types.js").SemanticNodeProvenance} Provenance record.
361
+ */
362
+ export function getNodeProvenance(module, node) {
363
+ requireProvenance(module);
364
+ const index = createGenerationIndex(module);
365
+ const record = typeof node == "string"
366
+ ? index.provenance.nodes.find((candidate) => candidate.id == node)
367
+ : index.recordFor(node);
368
+ if (!record)
369
+ throw new RangeError(`Unknown semantic node: ${node}`);
370
+ return record;
371
+ }
372
+ /**
373
+ * Finds one semantic symbol record.
374
+ * @param {import("./types.js").SemanticModule} module - Semantic module.
375
+ * @param {string} symbolId - Symbol identity.
376
+ * @returns {import("./types.js").SemanticSymbolProvenance} Symbol record.
377
+ */
378
+ export function getSymbolProvenance(module, symbolId) {
379
+ requireProvenance(module);
380
+ const symbol = createGenerationIndex(module).provenance.symbols.find((candidate) => candidate.id == symbolId);
381
+ if (!symbol)
382
+ throw new RangeError(`Unknown semantic symbol: ${symbolId}`);
383
+ return symbol;
384
+ }
385
+ /**
386
+ * Requires frontend provenance.
387
+ * @param {import("./types.js").SemanticModule} module - Semantic module.
388
+ * @returns {import("./types.js").SemanticProvenance} Provenance.
389
+ */
390
+ function requireProvenance(module) {
391
+ if (!module.provenance)
392
+ throw new TypeError("Semantic module does not contain source provenance.");
393
+ return module.provenance;
394
+ }
395
+ /**
396
+ * Traverses public semantic nodes in one stable order.
397
+ * @param {import("./types.js").SemanticModule} module - Semantic module.
398
+ * @returns {{node: import("./types.js").SemanticNode, ownerLocation: import("./types.js").SourceLocation, path: string}[]} Entries.
399
+ */
400
+ export function semanticEntries(module) {
401
+ /** @type {{node: import("./types.js").SemanticNode, ownerLocation: import("./types.js").SourceLocation, path: string}[]} */
402
+ const entries = [];
403
+ visit(module, "", module.location);
404
+ return entries;
405
+ /**
406
+ * Visits one semantic node and its children.
407
+ * @param {import("./types.js").SemanticNode} node - Current node.
408
+ * @param {string} path - Current JSON Pointer.
409
+ * @param {import("./types.js").SourceLocation} ownerLocation - Nearest located owner.
410
+ * @returns {void}
411
+ */
412
+ function visit(node, path, ownerLocation) {
413
+ const location = "location" in node ? node.location : ownerLocation;
414
+ entries.push({ node, ownerLocation: location, path });
415
+ if (node.kind == "Module") {
416
+ node.functions.forEach((child, index) => visit(child, `/functions/${index}`, location));
417
+ visit(node.entryPoint, "/entryPoint", location);
418
+ }
419
+ else if (node.kind == "FunctionDeclaration") {
420
+ node.parameters.forEach((child, index) => visit(child, `${path}/parameters/${index}`, location));
421
+ visit(node.returnType, `${path}/returnType`, location);
422
+ visit(node.body, `${path}/body`, location);
423
+ }
424
+ else if (node.kind == "Block") {
425
+ node.statements.forEach((child, index) => visit(child, `${path}/statements/${index}`, location));
426
+ }
427
+ else if (node.kind == "Parameter") {
428
+ visit(node.type, `${path}/type`, location);
429
+ }
430
+ else if (node.kind == "LocalDeclaration") {
431
+ visit(node.type, `${path}/type`, location);
432
+ visit(node.initializer, `${path}/initializer`, location);
433
+ }
434
+ else if (node.kind == "AssignmentStatement") {
435
+ visit(node.target, `${path}/target`, location);
436
+ visit(node.expression, `${path}/expression`, location);
437
+ }
438
+ else if (node.kind == "ReturnStatement" || node.kind == "PrintStatement") {
439
+ visit(node.expression, `${path}/expression`, location);
440
+ }
441
+ else if (node.kind == "IfStatement") {
442
+ visit(node.condition, `${path}/condition`, location);
443
+ visit(node.consequent, `${path}/consequent`, location);
444
+ if (node.alternate)
445
+ visit(node.alternate, `${path}/alternate`, location);
446
+ }
447
+ else if (node.kind == "EntryPoint") {
448
+ visit(node.body, `${path}/body`, location);
449
+ }
450
+ else if (node.kind == "UnaryExpression") {
451
+ visit(node.operand, `${path}/operand`, location);
452
+ }
453
+ else if (node.kind == "BinaryExpression") {
454
+ visit(node.left, `${path}/left`, location);
455
+ visit(node.right, `${path}/right`, location);
456
+ }
457
+ else if (node.kind == "CallExpression") {
458
+ node.arguments.forEach((child, index) => visit(child, `${path}/arguments/${index}`, location));
459
+ }
460
+ }
461
+ }
462
+ /**
463
+ * Resolves declarations and references after semantic validation.
464
+ * @param {import("./types.js").SemanticModule} module - Validated module.
465
+ * @param {Map<string, import("./types.js").SemanticNodeProvenance>} records - Node records by occurrence path.
466
+ * @returns {import("./types.js").SemanticSymbolProvenance[]} Symbols.
467
+ */
468
+ function resolveSymbols(module, records) {
469
+ /** @type {import("./types.js").SemanticSymbolProvenance[]} */
470
+ const symbols = [];
471
+ /** @type {Map<string, string>} */
472
+ const functions = new Map();
473
+ for (const [index, declaration] of module.functions.entries()) {
474
+ functions.set(declaration.name, declare(declaration, declaration.name, "function", `/functions/${index}`));
475
+ }
476
+ for (const [index, declaration] of module.functions.entries()) {
477
+ const declarationPath = `/functions/${index}`;
478
+ const scope = new Map();
479
+ for (const [parameterIndex, parameter] of declaration.parameters.entries()) {
480
+ scope.set(parameter.name, declare(parameter, parameter.name, "parameter", `${declarationPath}/parameters/${parameterIndex}`));
481
+ }
482
+ visitBlock(declaration.body, scope, `${declarationPath}/body`);
483
+ }
484
+ visitBlock(module.entryPoint.body, new Map(), "/entryPoint/body");
485
+ return symbols;
486
+ /**
487
+ * Declares one canonical symbol.
488
+ * @param {import("./types.js").FunctionDeclaration | import("./types.js").Parameter | import("./types.js").LocalDeclaration} node - Declaration.
489
+ * @param {string} name - Symbol name.
490
+ * @param {import("./types.js").SemanticSymbolKind} kind - Symbol kind.
491
+ * @param {string} path - Declaration occurrence path.
492
+ * @returns {string} Symbol identity.
493
+ */
494
+ function declare(node, name, kind, path) {
495
+ const record = records.get(path);
496
+ if (!record)
497
+ throw new Error(`Missing provenance for ${node.kind}.`);
498
+ const location = record.ranges.name ?? node.location;
499
+ const id = `symbol:${symbols.length}`;
500
+ record.symbolId = id;
501
+ symbols.push({ declarationNodeId: record.id, id, kind, location, name, references: [] });
502
+ return id;
503
+ }
504
+ /**
505
+ * Resolves references in one lexical block.
506
+ * @param {import("./types.js").Block} block - Semantic block.
507
+ * @param {Map<string, string>} parent - Visible bindings.
508
+ * @param {string} path - Statement sequence path.
509
+ * @returns {void}
510
+ */
511
+ function visitBlock(block, parent, path) {
512
+ const scope = new Map(parent);
513
+ for (const [index, statement] of block.statements.entries()) {
514
+ const statementPath = `${path}/statements/${index}`;
515
+ if (statement.kind == "LocalDeclaration") {
516
+ visitExpression(statement.initializer, scope, `${statementPath}/initializer`);
517
+ scope.set(statement.name, declare(statement, statement.name, "local", statementPath));
518
+ }
519
+ else if (statement.kind == "AssignmentStatement") {
520
+ reference(statement.target, scope.get(statement.target.name), "write", `${statementPath}/target`);
521
+ visitExpression(statement.expression, scope, `${statementPath}/expression`);
522
+ }
523
+ else if (statement.kind == "ReturnStatement" || statement.kind == "PrintStatement") {
524
+ visitExpression(statement.expression, scope, `${statementPath}/expression`);
525
+ }
526
+ else if (statement.kind == "IfStatement") {
527
+ visitExpression(statement.condition, scope, `${statementPath}/condition`);
528
+ visitBlock(statement.consequent, scope, `${statementPath}/consequent`);
529
+ if (statement.alternate)
530
+ visitBlock(statement.alternate, scope, `${statementPath}/alternate`);
531
+ }
532
+ }
533
+ }
534
+ /**
535
+ * Resolves references in one expression.
536
+ * @param {import("./types.js").Expression} expression - Expression.
537
+ * @param {Map<string, string>} scope - Visible bindings.
538
+ * @param {string} path - Expression occurrence path.
539
+ * @returns {void}
540
+ */
541
+ function visitExpression(expression, scope, path) {
542
+ if (expression.kind == "IdentifierExpression")
543
+ reference(expression, scope.get(expression.name), "read", path);
544
+ else if (expression.kind == "CallExpression") {
545
+ reference(expression, functions.get(expression.callee), "call", path);
546
+ for (const [index, argument] of expression.arguments.entries())
547
+ visitExpression(argument, scope, `${path}/arguments/${index}`);
548
+ }
549
+ else if (expression.kind == "UnaryExpression") {
550
+ visitExpression(expression.operand, scope, `${path}/operand`);
551
+ }
552
+ else if (expression.kind == "BinaryExpression") {
553
+ visitExpression(expression.left, scope, `${path}/left`);
554
+ visitExpression(expression.right, scope, `${path}/right`);
555
+ }
556
+ }
557
+ /**
558
+ * Attaches one resolved symbol reference.
559
+ * @param {import("./types.js").IdentifierExpression | import("./types.js").CallExpression} node - Reference node.
560
+ * @param {string | undefined} symbolId - Resolved symbol.
561
+ * @param {"read" | "write" | "call"} role - Reference role.
562
+ * @param {string} path - Reference occurrence path.
563
+ * @returns {void}
564
+ */
565
+ function reference(node, symbolId, role, path) {
566
+ if (!symbolId)
567
+ return;
568
+ const record = records.get(path);
569
+ const symbol = symbols.find((candidate) => candidate.id == symbolId);
570
+ if (!record || !symbol)
571
+ throw new Error(`Missing provenance while resolving ${node.kind}.`);
572
+ const location = record.ranges[role == "call" ? "callee" : "name"] ?? node.location;
573
+ record.symbolId = symbolId;
574
+ symbol.references.push({ location, nodeId: record.id, role });
575
+ }
576
+ }
577
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVuYW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZW1hbnRpYy9wcm92ZW5hbmNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMscUJBQXFCLEVBQUUsY0FBYyxFQUFDLE1BQU0sZUFBZSxDQUFBO0FBRW5FLDZGQUE2RjtBQUM3RixNQUFNLFlBQVksR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO0FBQ2xDLHVHQUF1RztBQUN2RyxNQUFNLHVCQUF1QixHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFFN0M7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLElBQUksRUFBRSxNQUFNO0lBQzFDLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQ2hDLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLE1BQU07SUFDM0MsZUFBZSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUU3QixPQUFPLElBQUksQ0FBQTtBQUNiLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxNQUFNLEVBQUUsRUFBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBQztJQUN2RSxNQUFNLE9BQU8sR0FBRyxDQUFDLEVBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUMsQ0FBQyxDQUFBO0lBQ3ZFLE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUN2Qyx1RUFBdUU7SUFDdkUsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUMvQiw0REFBNEQ7SUFDNUQsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFBO0lBRWxCLEtBQUssTUFBTSxDQUFDLEtB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QUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxPQUFPLENBQUMsQ0FBQTtZQUN2RCxlQUFlLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLFFBQVEsQ0FBQyxDQUFBO1FBQzNELENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFNBQVMsU0FBUyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLElBQUk7UUFDM0MsSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFNO1FBRXJCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDaEMsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxRQUFRLENBQUMsQ0FBQTtRQUVwRSxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTTtZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsc0NBQXNDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFBO1FBRTNGLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFBO1FBRW5GLE1BQU0sQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQzFCLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUE7SUFDN0QsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtjcmVhdGVDb29yZGluYXRlSW5kZXgsIGluZGV4ZWRQb2ludEF0fSBmcm9tIFwiLi9sb2NhdGlvbi5qc1wiXG5cbi8qKiBAdHlwZSB7V2Vha01hcDxvYmplY3QsIFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIGltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24+Pj59ICovXG5jb25zdCBwYXJzZXJSYW5nZXMgPSBuZXcgV2Vha01hcCgpXG4vKiogQHR5cGUge1dlYWtNYXA8aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWdpc3RlcmVkU291cmNlLCBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVDb29yZGluYXRlSW5kZXg+Pn0gKi9cbmNvbnN0IHNvdXJjZUNvb3JkaW5hdGVJbmRleGVzID0gbmV3IFdlYWtNYXAoKVxuXG4vKipcbiAqIFJlY29yZHMgcGFyc2VyLXByb3ZpZGVkIHNlbWFudGljLXRva2VuIHJhbmdlcyB3aXRob3V0IGV4cG9zaW5nIHBhcnNlciB0cmVlcy5cbiAqIEBwYXJhbSB7b2JqZWN0fSBub2RlIC0gU2VtYW50aWMgbm9kZS5cbiAqIEBwYXJhbSB7UmVhZG9ubHk8UmVjb3JkPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbj4+fSByYW5nZXMgLSBFeGFjdCByb2xlIHJhbmdlcy5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0UGFyc2VyUmFuZ2VzKG5vZGUsIHJhbmdlcykge1xuICBwYXJzZXJSYW5nZXMuc2V0KG5vZGUsIHJhbmdlcylcbn1cblxuLyoqXG4gKiBSZWNvcmRzIHBhcnNlciByYW5nZXMgYW5kIHJldHVybnMgdGhlIHNhbWUgc2VtYW50aWMgbm9kZS5cbiAqIEB0ZW1wbGF0ZSB7b2JqZWN0fSBOb2RlXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgLSBTZW1hbnRpYyBub2RlLlxuICogQHBhcmFtIHtSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uPj59IHJhbmdlcyAtIEV4YWN0IHJvbGUgcmFuZ2VzLlxuICogQHJldHVybnMge05vZGV9IFRoZSBzYW1lIG5vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3aXRoUGFyc2VyUmFuZ2VzKG5vZGUsIHJhbmdlcykge1xuICBzZXRQYXJzZXJSYW5nZXMobm9kZSwgcmFuZ2VzKVxuXG4gIHJldHVybiBub2RlXG59XG5cbi8qKlxuICogQWRkcyBkZXRlcm1pbmlzdGljIHByb3ZlbmFuY2UgdG8gYSB2YWxpZGF0ZWQgZnJvbnRlbmQgbW9kdWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBWYWxpZGF0ZWQgc2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtvYmplY3R9IHNvdXJjZSAtIFBhcnNlZCBzb3VyY2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlLmZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTGFuZ3VhZ2V9IHNvdXJjZS5sYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2Uuc291cmNlIC0gRXhhY3Qgc291cmNlIGNvbnRlbnQuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gVGhlIHNhbWUgc2VtYW50aWMgbW9kdWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYW5ub3RhdGVQYXJzZWRNb2R1bGUobW9kdWxlLCB7ZmlsZW5hbWUsIGxhbmd1YWdlLCBzb3VyY2V9KSB7XG4gIGNvbnN0IHNvdXJjZXMgPSBbe2NvbnRlbnQ6IHNvdXJjZSwgZmlsZW5hbWUsIGlkOiBcInNvdXJjZTowXCIsIGxhbmd1YWdlfV1cbiAgY29uc3QgZW50cmllcyA9IHNlbWFudGljRW50cmllcyhtb2R1bGUpXG4gIC8qKiBAdHlwZSB7TWFwPHN0cmluZywgaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY05vZGVQcm92ZW5hbmNlPn0gKi9cbiAgY29uc3QgcmVjb3Jkc0J5UGF0aCA9IG5ldyBNYXAoKVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlUHJvdmVuYW5jZVtdfSAqL1xuICBjb25zdCByZWNvcmRzID0gW11cblxuICBmb3IgKGNvbnN0IFtpbmRleCwgZW50cnldIG9mIGVudHJpZXMuZW50cmllcygpKSB7XG4gICAgY29uc3QgcmFuZ2VzID0gcGFyc2VyUmFuZ2VzLmdldChlbnRyeS5ub2RlKSA/PyB7fVxuICAgIGNvbnN0IGxvY2F0aW9uID0gXCJsb2NhdGlvblwiIGluIGVudHJ5Lm5vZGUgPyBlbnRyeS5ub2RlLmxvY2F0aW9uIDogcmFuZ2VzLnR5cGUgPz8gZW50cnkub3duZXJMb2NhdGlvblxuICAgIGNvbnN0IHNvdXJjZVByb3ZlbmFuY2UgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlU291cmNlUHJvdmVuYW5jZX0gKi8gKHtcbiAgICAgIG9yaWdpbjoge2tpbmQ6IFwic291cmNlXCIsIGxvY2F0aW9uLCBzb3VyY2VJZDogXCJzb3VyY2U6MFwifSxcbiAgICAgIHJhbmdlcyxcbiAgICAgIHNjaGVtYTogXCJTZW1hbnRpZm9sZE5vZGVQcm92ZW5hbmNlXCIsXG4gICAgICB2ZXJzaW9uOiAxXG4gICAgfSlcbiAgICBjb25zdCByZWNvcmQgPSB7XG4gICAgICBpZDogYG5vZGU6JHtpbmRleH1gLFxuICAgICAga2luZDogZW50cnkubm9kZS5raW5kLFxuICAgICAgb3JpZ2luOiBzb3VyY2VQcm92ZW5hbmNlLm9yaWdpbixcbiAgICAgIHBhdGg6IGVudHJ5LnBhdGgsXG4gICAgICByYW5nZXM6IHNvdXJjZVByb3ZlbmFuY2UucmFuZ2VzXG4gICAgfVxuXG4gICAgcmVjb3Jkcy5wdXNoKHJlY29yZClcbiAgICByZWNvcmRzQnlQYXRoLnNldChlbnRyeS5wYXRoLCByZWNvcmQpXG4gICAgZW50cnkubm9kZS5zb3VyY2VQcm92ZW5hbmNlID0gc291cmNlUHJvdmVuYW5jZVxuICB9XG5cbiAgY29uc3Qgc3ltYm9scyA9IHJlc29sdmVTeW1ib2xzKG1vZHVsZSwgcmVjb3Jkc0J5UGF0aClcblxuICBtb2R1bGUucHJvdmVuYW5jZSA9IHtcbiAgICBjb29yZGluYXRlU3lzdGVtOiBcInV0ZjE2XCIsXG4gICAgbm9kZXM6IHJlY29yZHMsXG4gICAgc2NoZW1hOiBcIlNlbWFudGlmb2xkUHJvdmVuYW5jZVwiLFxuICAgIHNvdXJjZXMsXG4gICAgc3ltYm9scyxcbiAgICB2ZXJzaW9uOiAxXG4gIH1cblxuICByZXR1cm4gbW9kdWxlXG59XG5cbi8qKlxuICogUmVidWlsZHMgY2Fub25pY2FsIGdlbmVyYXRpb24gbWV0YWRhdGEgd2l0aG91dCB0cnVzdGluZyBjYWxsZXItcHJvdmlkZWQgaWRlbnRpdGllcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gU2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHt7ZmlsZW5hbWU6IHN0cmluZywgY29udGVudDogc3RyaW5nLCBsYW5ndWFnZT86IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNMYW5ndWFnZX1bXX0gW3Byb3ZpZGVkU291cmNlc10gLSBBZGRpdGlvbmFsIHNvdXJjZSBjb250ZW50LlxuICogQHJldHVybnMge3twcm92ZW5hbmNlOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljUHJvdmVuYW5jZSwgcmVjb3JkRm9yOiAobm9kZTogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY05vZGUsIHBhdGg/OiBzdHJpbmcpID0+IGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlUHJvdmVuYW5jZX19IENhbm9uaWNhbCBpbmRleC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUdlbmVyYXRpb25JbmRleChtb2R1bGUsIHByb3ZpZGVkU291cmNlcyA9IFtdKSB7XG4gIGNvbnN0IGVudHJpZXMgPSBzZW1hbnRpY0VudHJpZXMobW9kdWxlKVxuICBjb25zdCBwcmlvclNvdXJjZXMgPSB1c2FibGVTb3VyY2VQcm92ZW5hbmNlKG1vZHVsZS5wcm92ZW5hbmNlKVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZVtdfSAqL1xuICBjb25zdCBzb3VyY2VzID0gW11cbiAgLyoqIEB0eXBlIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZ2lzdGVyZWRTb3VyY2U+fSAqL1xuICBjb25zdCBwcmlvclNvdXJjZXNCeUlkID0gbmV3IE1hcCgpXG5cbiAgZm9yIChjb25zdCBzb3VyY2Ugb2YgcHJvdmlkZWRTb3VyY2VzKSBhZGRTb3VyY2Uoc291cmNlLmZpbGVuYW1lLCBzb3VyY2UuY29udGVudCwgc291cmNlLmxhbmd1YWdlID8/IG51bGwpXG4gIGlmIChwcmlvclNvdXJjZXMpIHtcbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBwcmlvclNvdXJjZXMuc291cmNlcykge1xuICAgICAgY29uc3QgY2Fub25pY2FsID0gYWRkU291cmNlKHNvdXJjZS5maWxlbmFtZSwgc291cmNlLmNvbnRlbnQsIHNvdXJjZS5sYW5ndWFnZSlcblxuICAgICAgcHJpb3JTb3VyY2VzQnlJZC5zZXQoc291cmNlLmlkLCBjYW5vbmljYWwpXG4gICAgfVxuICB9XG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGNvbnN0IGxvY2F0aW9uID0gXCJsb2NhdGlvblwiIGluIGVudHJ5Lm5vZGUgPyBlbnRyeS5ub2RlLmxvY2F0aW9uIDogZW50cnkub3duZXJMb2NhdGlvblxuXG4gICAgaWYgKCFzb3VyY2VzLnNvbWUoKHNvdXJjZSkgPT4gc291cmNlLmZpbGVuYW1lID09IGxvY2F0aW9uLmZpbGVuYW1lKSkgYWRkU291cmNlKGxvY2F0aW9uLmZpbGVuYW1lLCBudWxsLCBudWxsKVxuICB9XG4gIGNvbnN0IHZlcmlmaWFibGVTb3VyY2VzID0gc291cmNlcy5maWx0ZXIoKHNvdXJjZSkgPT4gc291cmNlLmNvbnRlbnQgIT0gbnVsbClcblxuICAvKiogQHR5cGUge01hcDxvYmplY3QsIGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlUHJvdmVuYW5jZVtdPn0gKi9cbiAgY29uc3QgcmVjb3Jkc0J5Tm9kZSA9IG5ldyBNYXAoKVxuICAvKiogQHR5cGUge01hcDxzdHJpbmcsIGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlUHJvdmVuYW5jZT59ICovXG4gIGNvbnN0IHJlY29yZHNCeVBhdGggPSBuZXcgTWFwKClcbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTm9kZVByb3ZlbmFuY2VbXX0gKi9cbiAgY29uc3QgcmVjb3JkcyA9IFtdXG5cbiAgZm9yIChjb25zdCBbaW5kZXgsIGVudHJ5XSBvZiBlbnRyaWVzLmVudHJpZXMoKSkge1xuICAgIGNvbnN0IGxvY2F0ZWQgPSBcImxvY2F0aW9uXCIgaW4gZW50cnkubm9kZSA/IGVudHJ5Lm5vZGUubG9jYXRpb24gOiBlbnRyeS5vd25lckxvY2F0aW9uXG4gICAgY29uc3QgYXNzb2NpYXRlZCA9IHVzYWJsZU5vZGVQcm92ZW5hbmNlKGVudHJ5Lm5vZGUuc291cmNlUHJvdmVuYW5jZSlcbiAgICBjb25zdCByYW5nZXMgPSBhc3NvY2lhdGVkID8gdmFsaWRSYW5nZXMoYXNzb2NpYXRlZC5yYW5nZXMsIHZlcmlmaWFibGVTb3VyY2VzKSA6IHt9XG4gICAgY29uc3Qgbm9ybWFsaXplZE9yaWdpbiA9IGFzc29jaWF0ZWRcbiAgICAgID8gbm9ybWFsaXplT3JpZ2luKGFzc29jaWF0ZWQub3JpZ2luLCBwcmlvclNvdXJjZXNCeUlkLCB2ZXJpZmlhYmxlU291cmNlcylcbiAgICAgIDogdW5kZWZpbmVkXG4gICAgY29uc3QgZmFsbGJhY2tTb3VyY2UgPSBzb3VyY2VGb3JMb2NhdGlvbihsb2NhdGVkLCBzb3VyY2VzKVxuICAgIGNvbnN0IG9yaWdpbiA9IG5vcm1hbGl6ZWRPcmlnaW4gPz8gc291cmNlT3JpZ2luKGZhbGxiYWNrU291cmNlLCBsb2NhdGVkKVxuXG4gICAgY29uc3QgcmVjb3JkID0ge1xuICAgICAgaWQ6IGBub2RlOiR7aW5kZXh9YCxcbiAgICAgIGtpbmQ6IGVudHJ5Lm5vZGUua2luZCxcbiAgICAgIG9yaWdpbixcbiAgICAgIHBhdGg6IGVudHJ5LnBhdGgsXG4gICAgICByYW5nZXNcbiAgICB9XG5cbiAgICByZWNvcmRzLnB1c2gocmVjb3JkKVxuICAgIHJlY29yZHNCeVBhdGguc2V0KGVudHJ5LnBhdGgsIHJlY29yZClcbiAgICBjb25zdCBvY2N1cnJlbmNlcyA9IHJlY29yZHNCeU5vZGUuZ2V0KGVudHJ5Lm5vZGUpID8/IFtdXG5cbiAgICBvY2N1cnJlbmNlcy5wdXNoKHJlY29yZClcbiAgICByZWNvcmRzQnlOb2RlLnNldChlbnRyeS5ub2RlLCBvY2N1cnJlbmNlcylcbiAgfVxuXG4gIGNvbnN0IHN5bWJvbHMgPSByZXNvbHZlU3ltYm9scyhtb2R1bGUsIHJlY29yZHNCeVBhdGgpXG4gIGNvbnN0IHByb3ZlbmFuY2UgPSAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNQcm92ZW5hbmNlfSAqLyAoe1xuICAgIGNvb3JkaW5hdGVTeXN0ZW06IFwidXRmMTZcIixcbiAgICBub2RlczogcmVjb3JkcyxcbiAgICBzY2hlbWE6IFwiU2VtYW50aWZvbGRQcm92ZW5hbmNlXCIsXG4gICAgc291cmNlcyxcbiAgICBzeW1ib2xzLFxuICAgIHZlcnNpb246IDFcbiAgfSlcblxuICByZXR1cm4ge1xuICAgIHByb3ZlbmFuY2UsXG4gICAgcmVjb3JkRm9yKG5vZGUsIHBhdGgpIHtcbiAgICAgIGNvbnN0IG9jY3VycmVuY2VzID0gcmVjb3Jkc0J5Tm9kZS5nZXQobm9kZSlcblxuICAgICAgaWYgKCFvY2N1cnJlbmNlcykgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJTZW1hbnRpYyBub2RlIGlzIG5vdCBwYXJ0IG9mIHRoaXMgbW9kdWxlLlwiKVxuICAgICAgaWYgKHBhdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCByZWNvcmQgPSBvY2N1cnJlbmNlcy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5wYXRoID09IHBhdGgpXG5cbiAgICAgICAgaWYgKCFyZWNvcmQpIHRocm93IG5ldyBSYW5nZUVycm9yKGBTZW1hbnRpYyBub2RlIGRvZXMgbm90IG9jY3VyIGF0ICcke3BhdGh9Jy5gKVxuXG4gICAgICAgIHJldHVybiByZWNvcmRcbiAgICAgIH1cbiAgICAgIGlmIChvY2N1cnJlbmNlcy5sZW5ndGggIT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIlNoYXJlZCBzZW1hbnRpYyBub2RlIHJlcXVpcmVzIGFuIG9jY3VycmVuY2UgcGF0aC5cIilcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9jY3VycmVuY2VzWzBdXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBvbmUgY2Fub25pY2FsIHNvdXJjZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVuYW1lIC0gU291cmNlIGZpbGVuYW1lLlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IG51bGx9IGNvbnRlbnQgLSBTb3VyY2UgY29udGVudC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTGFuZ3VhZ2UgfCBudWxsfSBsYW5ndWFnZSAtIFNvdXJjZSBsYW5ndWFnZS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZX0gQ2Fub25pY2FsIHNvdXJjZS5cbiAgICovXG4gIGZ1bmN0aW9uIGFkZFNvdXJjZShmaWxlbmFtZSwgY29udGVudCwgbGFuZ3VhZ2UpIHtcbiAgICBpZiAodHlwZW9mIGZpbGVuYW1lICE9IFwic3RyaW5nXCIgfHwgY29udGVudCAhPT0gbnVsbCAmJiB0eXBlb2YgY29udGVudCAhPSBcInN0cmluZ1wiIHx8XG4gICAgICBsYW5ndWFnZSAhPT0gbnVsbCAmJiAhW1wicGhwXCIsIFwicnVieVwiLCBcImphdmFzY3JpcHRcIiwgXCJ0eXBlc2NyaXB0XCIsIFwiamF2YVwiXS5pbmNsdWRlcyhsYW5ndWFnZSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNYWxmb3JtZWQgc2VtYW50aWMgc291cmNlIHJlZ2lzdHJ5IGVudHJ5LlwiKVxuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nID0gc291cmNlcy5maW5kKChzb3VyY2UpID0+IHNvdXJjZS5maWxlbmFtZSA9PSBmaWxlbmFtZSAmJiBzb3VyY2UuY29udGVudCA9PSBjb250ZW50KVxuXG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3RpbmdcblxuICAgIGNvbnN0IHJlZ2lzdGVyZWQgPSB7Y29udGVudCwgZmlsZW5hbWUsIGlkOiBgc291cmNlOiR7c291cmNlcy5sZW5ndGh9YCwgbGFuZ3VhZ2V9XG5cbiAgICBzb3VyY2VzLnB1c2gocmVnaXN0ZXJlZClcblxuICAgIHJldHVybiByZWdpc3RlcmVkXG4gIH1cbn1cblxuLyoqXG4gKiBTZWxlY3RzIHRoZSBzYWZlIHByaW1hcnkgb3JpZ2luYWwgbG9jYXRpb24gZm9yIGNsb3NlZCBwcm92ZW5hbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljT3JpZ2lufSBvcmlnaW4gLSBDbG9zZWQgcHJvdmVuYW5jZS5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uIHwgdW5kZWZpbmVkfSBQcmltYXJ5IGxvY2F0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJpbWFyeUxvY2F0aW9uKG9yaWdpbikge1xuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJzb3VyY2VcIikgcmV0dXJuIG9yaWdpbi5sb2NhdGlvblxuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJkZXJpdmVkXCIpIHJldHVybiBvcmlnaW4ub3JpZ2luc1swXT8ubG9jYXRpb25cblxuICByZXR1cm4gb3JpZ2luLnJlbGF0ZWRPcmlnaW5zWzBdPy5sb2NhdGlvblxufVxuXG4vKipcbiAqIEFjY2VwdHMgc291cmNlIG1ldGFkYXRhIG9ubHkgd2hlbiBpdCBpcyBhdHRhY2hlZCB0byB0aGUgc2VtYW50aWMgbm9kZSBpdCBkZXNjcmliZXMuXG4gKiBSZWdpc3RyeS1sb2NhbCBJRHMgYW5kIHBhdGhzIGFyZSBpbnRlbnRpb25hbGx5IGlnbm9yZWQgYW5kIHJlYnVpbHQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlU291cmNlUHJvdmVuYW5jZSB8IHVuZGVmaW5lZH0gcmVjb3JkIC0gQ2FuZGlkYXRlIG5vZGUgYXNzb2NpYXRpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY05vZGVTb3VyY2VQcm92ZW5hbmNlIHwgdW5kZWZpbmVkfSBVc2FibGUgYXNzb2NpYXRpb24uXG4gKi9cbmZ1bmN0aW9uIHVzYWJsZU5vZGVQcm92ZW5hbmNlKHJlY29yZCkge1xuICBpZiAoIXJlY29yZCB8fCByZWNvcmQuc2NoZW1hICE9IFwiU2VtYW50aWZvbGROb2RlUHJvdmVuYW5jZVwiIHx8IHJlY29yZC52ZXJzaW9uICE9IDEgfHxcbiAgICAhcmVjb3JkLm9yaWdpbiB8fCB0eXBlb2YgcmVjb3JkLm9yaWdpbiAhPSBcIm9iamVjdFwiIHx8XG4gICAgIXJlY29yZC5yYW5nZXMgfHwgdHlwZW9mIHJlY29yZC5yYW5nZXMgIT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHJlY29yZC5yYW5nZXMpKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgcmV0dXJuIHJlY29yZFxufVxuXG4vKipcbiAqIFJldGFpbnMgYSB2YWxpZCBzb3VyY2UgcmVnaXN0cnkgaW5kZXBlbmRlbnRseSBmcm9tIHBvdGVudGlhbGx5IHN0YWxlIG5vZGUgbWV0YWRhdGEuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNQcm92ZW5hbmNlIHwgdW5kZWZpbmVkfSBwcm92ZW5hbmNlIC0gQ2FuZGlkYXRlIHByb3ZlbmFuY2UuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY1Byb3ZlbmFuY2UgfCB1bmRlZmluZWR9IFByb3ZlbmFuY2Ugd2l0aCBhIHVzYWJsZSBzb3VyY2UgcmVnaXN0cnkuXG4gKi9cbmZ1bmN0aW9uIHVzYWJsZVNvdXJjZVByb3ZlbmFuY2UocHJvdmVuYW5jZSkge1xuICBpZiAoIXByb3ZlbmFuY2UgfHwgcHJvdmVuYW5jZS5zY2hlbWEgIT0gXCJTZW1hbnRpZm9sZFByb3ZlbmFuY2VcIiB8fCBwcm92ZW5hbmNlLnZlcnNpb24gIT0gMSB8fFxuICAgIHByb3ZlbmFuY2UuY29vcmRpbmF0ZVN5c3RlbSAhPSBcInV0ZjE2XCIgfHwgIUFycmF5LmlzQXJyYXkocHJvdmVuYW5jZS5zb3VyY2VzKSkgcmV0dXJuIHVuZGVmaW5lZFxuXG4gIGNvbnN0IHNvdXJjZUlkcyA9IG5ldyBTZXQoKVxuXG4gIGZvciAoY29uc3Qgc291cmNlIG9mIHByb3ZlbmFuY2Uuc291cmNlcykge1xuICAgIGlmICghc291cmNlIHx8IHR5cGVvZiBzb3VyY2UuaWQgIT0gXCJzdHJpbmdcIiB8fCBzb3VyY2VJZHMuaGFzKHNvdXJjZS5pZCkgfHwgdHlwZW9mIHNvdXJjZS5maWxlbmFtZSAhPSBcInN0cmluZ1wiIHx8XG4gICAgICBzb3VyY2UuZmlsZW5hbWUubGVuZ3RoID09IDAgfHxcbiAgICAgIHNvdXJjZS5jb250ZW50ICE9PSBudWxsICYmIHR5cGVvZiBzb3VyY2UuY29udGVudCAhPSBcInN0cmluZ1wiIHx8IHNvdXJjZS5sYW5ndWFnZSAhPT0gbnVsbCAmJlxuICAgICAgIVtcInBocFwiLCBcInJ1YnlcIiwgXCJqYXZhc2NyaXB0XCIsIFwidHlwZXNjcmlwdFwiLCBcImphdmFcIl0uaW5jbHVkZXMoc291cmNlLmxhbmd1YWdlKSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHNvdXJjZUlkcy5hZGQoc291cmNlLmlkKVxuICB9XG5cbiAgcmV0dXJuIHByb3ZlbmFuY2Vcbn1cblxuLyoqXG4gKiBSZXRhaW5zIG9ubHkgc2VsZi1jb25zaXN0ZW50IHNvdXJjZSByYW5nZXMuXG4gKiBAcGFyYW0ge1JlYWRvbmx5PFJlY29yZDxzdHJpbmcsIGltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb24+Pn0gcmFuZ2VzIC0gQ2FuZGlkYXRlIHJhbmdlcy5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWdpc3RlcmVkU291cmNlW119IHNvdXJjZXMgLSBDYW5vbmljYWwgc291cmNlcy5cbiAqIEByZXR1cm5zIHtSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uPj59IFNhZmUgcmFuZ2VzLlxuICovXG5mdW5jdGlvbiB2YWxpZFJhbmdlcyhyYW5nZXMsIHNvdXJjZXMpIHtcbiAgaWYgKCFyYW5nZXMgfHwgdHlwZW9mIHJhbmdlcyAhPSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkocmFuZ2VzKSkgcmV0dXJuIHt9XG5cbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9uPn0gKi9cbiAgY29uc3QgdmFsaWQgPSB7fVxuXG4gIGZvciAoY29uc3QgW3JvbGUsIGxvY2F0aW9uXSBvZiBPYmplY3QuZW50cmllcyhyYW5nZXMpKSB7XG4gICAgaWYgKHZhbGlkTG9jYXRpb24obG9jYXRpb24sIHNvdXJjZXMpKSB2YWxpZFtyb2xlXSA9IGxvY2F0aW9uXG4gIH1cblxuICByZXR1cm4gdmFsaWRcbn1cblxuLyoqXG4gKiBOb3JtYWxpemVzIGEgY2xvc2VkIG9yaWdpbiB3aGlsZSByZW1hcHBpbmcgdW50cnVzdGVkIHNvdXJjZSBpZGVudGl0aWVzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljT3JpZ2lufSBvcmlnaW4gLSBDYW5kaWRhdGUgb3JpZ2luLlxuICogQHBhcmFtIHtNYXA8c3RyaW5nLCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZ2lzdGVyZWRTb3VyY2U+fSBwcmlvclNvdXJjZXMgLSBQcmlvci10by1jYW5vbmljYWwgc291cmNlIG1hcHBpbmcuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZVtdfSBzb3VyY2VzIC0gQ2Fub25pY2FsIHNvdXJjZXMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY09yaWdpbiB8IHVuZGVmaW5lZH0gU2FmZSBvcmlnaW4uXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZU9yaWdpbihvcmlnaW4sIHByaW9yU291cmNlcywgc291cmNlcykge1xuICBpZiAoIW9yaWdpbiB8fCB0eXBlb2Ygb3JpZ2luICE9IFwib2JqZWN0XCIpIHJldHVybiB1bmRlZmluZWRcblxuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJzb3VyY2VcIiAmJiB2YWxpZExvY2F0aW9uKG9yaWdpbi5sb2NhdGlvbiwgc291cmNlcykpIHtcbiAgICBjb25zdCBjbGFpbWVkID0gcHJpb3JTb3VyY2VzLmdldChvcmlnaW4uc291cmNlSWQpXG4gICAgY29uc3Qgc291cmNlID0gY2xhaW1lZCAmJiBzb3VyY2VPd25zTG9jYXRpb24oY2xhaW1lZCwgb3JpZ2luLmxvY2F0aW9uKSA/IGNsYWltZWQgOiBzb3VyY2VGb3JMb2NhdGlvbihvcmlnaW4ubG9jYXRpb24sIHNvdXJjZXMpXG5cbiAgICByZXR1cm4gc291cmNlT3JpZ2luKHNvdXJjZSwgb3JpZ2luLmxvY2F0aW9uKVxuICB9XG4gIGlmIChvcmlnaW4ua2luZCA9PSBcImRlcml2ZWRcIiAmJiBBcnJheS5pc0FycmF5KG9yaWdpbi5vcmlnaW5zKSAmJiBvcmlnaW4ub3JpZ2lucy5sZW5ndGggPiAwKSB7XG4gICAgY29uc3Qgb3JpZ2lucyA9IG9yaWdpbi5vcmlnaW5zLm1hcCgocmVsYXRlZCkgPT4gbm9ybWFsaXplUmVsYXRlZE9yaWdpbihyZWxhdGVkLCBwcmlvclNvdXJjZXMsIHNvdXJjZXMpKVxuXG4gICAgaWYgKG9yaWdpbnMuZXZlcnkoQm9vbGVhbikpIHJldHVybiB7a2luZDogXCJkZXJpdmVkXCIsIG9yaWdpbnM6IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWxhdGVkT3JpZ2luW119ICovIChvcmlnaW5zKX1cbiAgfVxuICBpZiAob3JpZ2luLmtpbmQgPT0gXCJzeW50aGV0aWNcIiAmJiB0eXBlb2Ygb3JpZ2luLnJlYXNvbiA9PSBcInN0cmluZ1wiICYmIEFycmF5LmlzQXJyYXkob3JpZ2luLnJlbGF0ZWRPcmlnaW5zKSkge1xuICAgIGNvbnN0IHJlbGF0ZWRPcmlnaW5zID0gb3JpZ2luLnJlbGF0ZWRPcmlnaW5zLm1hcCgocmVsYXRlZCkgPT4gbm9ybWFsaXplUmVsYXRlZE9yaWdpbihyZWxhdGVkLCBwcmlvclNvdXJjZXMsIHNvdXJjZXMpKVxuXG4gICAgaWYgKHJlbGF0ZWRPcmlnaW5zLmV2ZXJ5KEJvb2xlYW4pKSB7XG4gICAgICByZXR1cm4ge2tpbmQ6IFwic3ludGhldGljXCIsIHJlYXNvbjogb3JpZ2luLnJlYXNvbiwgcmVsYXRlZE9yaWdpbnM6IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWxhdGVkT3JpZ2luW119ICovIChyZWxhdGVkT3JpZ2lucyl9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZXMgb25lIHJlbGF0ZWQgb3JpZ2luLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlbGF0ZWRPcmlnaW59IHJlbGF0ZWQgLSBDYW5kaWRhdGUgcmVsYXRlZCBvcmlnaW4uXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZT59IHByaW9yU291cmNlcyAtIFByaW9yIHNvdXJjZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZVtdfSBzb3VyY2VzIC0gQ2Fub25pY2FsIHNvdXJjZXMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWxhdGVkT3JpZ2luIHwgdW5kZWZpbmVkfSBTYWZlIHJlbGF0ZWQgb3JpZ2luLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSZWxhdGVkT3JpZ2luKHJlbGF0ZWQsIHByaW9yU291cmNlcywgc291cmNlcykge1xuICBpZiAoIXJlbGF0ZWQgfHwgIXZhbGlkTG9jYXRpb24ocmVsYXRlZC5sb2NhdGlvbiwgc291cmNlcykpIHJldHVybiB1bmRlZmluZWRcblxuICBjb25zdCBjbGFpbWVkID0gcHJpb3JTb3VyY2VzLmdldChyZWxhdGVkLnNvdXJjZUlkKVxuICBjb25zdCBzb3VyY2UgPSBjbGFpbWVkICYmIHNvdXJjZU93bnNMb2NhdGlvbihjbGFpbWVkLCByZWxhdGVkLmxvY2F0aW9uKSA/IGNsYWltZWQgOiBzb3VyY2VGb3JMb2NhdGlvbihyZWxhdGVkLmxvY2F0aW9uLCBzb3VyY2VzKVxuICBjb25zdCBub3JtYWxpemVkID0ge2xvY2F0aW9uOiByZWxhdGVkLmxvY2F0aW9uLCBzb3VyY2VJZDogc291cmNlLmlkfVxuXG4gIGlmICh0eXBlb2YgcmVsYXRlZC5yb2xlID09IFwic3RyaW5nXCIpIE9iamVjdC5hc3NpZ24obm9ybWFsaXplZCwge3JvbGU6IHJlbGF0ZWQucm9sZX0pXG5cbiAgcmV0dXJuIG5vcm1hbGl6ZWRcbn1cblxuLyoqXG4gKiBDaGVja3Mgbm9ybWFsaXplZCBjb29yZGluYXRlcyBhZ2FpbnN0IGV4YWN0IHNvdXJjZSBjb250ZW50IHdoZW4gYXZhaWxhYmxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBsb2NhdGlvbiAtIENhbmRpZGF0ZSBsb2NhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5SZWdpc3RlcmVkU291cmNlW119IHNvdXJjZXMgLSBSZWdpc3RlcmVkIHNvdXJjZXMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgbG9jYXRpb24gaXMgc2FmZS5cbiAqL1xuZnVuY3Rpb24gdmFsaWRMb2NhdGlvbihsb2NhdGlvbiwgc291cmNlcykge1xuICBpZiAoIWxvY2F0aW9uIHx8IHR5cGVvZiBsb2NhdGlvbi5maWxlbmFtZSAhPSBcInN0cmluZ1wiIHx8ICFsb2NhdGlvbi5zdGFydCB8fCAhbG9jYXRpb24uZW5kIHx8XG4gICAgIU51bWJlci5pc0ludGVnZXIobG9jYXRpb24uc3RhcnQub2Zmc2V0KSB8fCAhTnVtYmVyLmlzSW50ZWdlcihsb2NhdGlvbi5lbmQub2Zmc2V0KSB8fCBsb2NhdGlvbi5zdGFydC5vZmZzZXQgPCAwIHx8XG4gICAgbG9jYXRpb24uZW5kLm9mZnNldCA8IGxvY2F0aW9uLnN0YXJ0Lm9mZnNldCB8fCAhdmFsaWRQb2ludFNoYXBlKGxvY2F0aW9uLnN0YXJ0KSB8fCAhdmFsaWRQb2ludFNoYXBlKGxvY2F0aW9uLmVuZCkpIHJldHVybiBmYWxzZVxuXG4gIGNvbnN0IGNhbmRpZGF0ZXMgPSBzb3VyY2VzLmZpbHRlcigoc291cmNlKSA9PiBzb3VyY2UuZmlsZW5hbWUgPT0gbG9jYXRpb24uZmlsZW5hbWUpXG5cbiAgcmV0dXJuIGNhbmRpZGF0ZXMuc29tZSgoc291cmNlKSA9PiBzb3VyY2VPd25zTG9jYXRpb24oc291cmNlLCBsb2NhdGlvbikpXG59XG5cbi8qKlxuICogQ2hlY2tzIHRoYXQgb25lIGlkZW50aWZpZWQgcmVnaXN0cnkgc291cmNlIG93bnMgYSBub3JtYWxpemVkIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZ2lzdGVyZWRTb3VyY2V9IHNvdXJjZSAtIElkZW50aWZpZWQgc291cmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBsb2NhdGlvbiAtIENhbmRpZGF0ZSBsb2NhdGlvbi5cbiAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIHRoZSBzb3VyY2Ugb3ducyB0aGUgbG9jYXRpb24uXG4gKi9cbmZ1bmN0aW9uIHNvdXJjZU93bnNMb2NhdGlvbihzb3VyY2UsIGxvY2F0aW9uKSB7XG4gIGlmIChzb3VyY2UuZmlsZW5hbWUgIT0gbG9jYXRpb24uZmlsZW5hbWUpIHJldHVybiBmYWxzZVxuICBpZiAoc291cmNlLmNvbnRlbnQgPT0gbnVsbCkgcmV0dXJuIHRydWVcbiAgaWYgKGxvY2F0aW9uLmVuZC5vZmZzZXQgPiBzb3VyY2UuY29udGVudC5sZW5ndGgpIHJldHVybiBmYWxzZVxuICBsZXQgY29vcmRpbmF0ZXMgPSBzb3VyY2VDb29yZGluYXRlSW5kZXhlcy5nZXQoc291cmNlKVxuXG4gIGlmICghY29vcmRpbmF0ZXMpIHtcbiAgICBjb29yZGluYXRlcyA9IGNyZWF0ZUNvb3JkaW5hdGVJbmRleChzb3VyY2UuY29udGVudClcbiAgICBzb3VyY2VDb29yZGluYXRlSW5kZXhlcy5zZXQoc291cmNlLCBjb29yZGluYXRlcylcbiAgfVxuXG4gIHJldHVybiBzYW1lUG9pbnQoaW5kZXhlZFBvaW50QXQoY29vcmRpbmF0ZXMsIGxvY2F0aW9uLnN0YXJ0Lm9mZnNldCksIGxvY2F0aW9uLnN0YXJ0KSAmJlxuICAgIHNhbWVQb2ludChpbmRleGVkUG9pbnRBdChjb29yZGluYXRlcywgbG9jYXRpb24uZW5kLm9mZnNldCksIGxvY2F0aW9uLmVuZClcbn1cblxuLyoqXG4gKiBDaGVja3MgdGhlIGludGVnZXIgc2hhcGUgb2Ygb25lIHNvdXJjZSBwb2ludC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VQb2ludH0gcG9pbnQgLSBTb3VyY2UgcG9pbnQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciBpdCBpcyBzdHJ1Y3R1cmFsbHkgdmFsaWQuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkUG9pbnRTaGFwZShwb2ludCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihwb2ludC5saW5lKSAmJiBwb2ludC5saW5lID49IDEgJiYgTnVtYmVyLmlzSW50ZWdlcihwb2ludC5jb2x1bW4pICYmIHBvaW50LmNvbHVtbiA+PSAxXG59XG5cbi8qKlxuICogQ29tcGFyZXMgbm9ybWFsaXplZCBzb3VyY2UgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlUG9pbnR9IGxlZnQgLSBMZWZ0IHBvaW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZVBvaW50fSByaWdodCAtIFJpZ2h0IHBvaW50LlxuICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgYWxsIGNvb3JkaW5hdGVzIG1hdGNoLlxuICovXG5mdW5jdGlvbiBzYW1lUG9pbnQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQub2Zmc2V0ID09IHJpZ2h0Lm9mZnNldCAmJiBsZWZ0LmxpbmUgPT0gcmlnaHQubGluZSAmJiBsZWZ0LmNvbHVtbiA9PSByaWdodC5jb2x1bW5cbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgZGV0ZXJtaW5pc3RpYyBzb3VyY2Ugb3duaW5nIGEgbG9jYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU291cmNlTG9jYXRpb259IGxvY2F0aW9uIC0gU291cmNlIGxvY2F0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZ2lzdGVyZWRTb3VyY2VbXX0gc291cmNlcyAtIENhbm9uaWNhbCBzb3VyY2VzLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuUmVnaXN0ZXJlZFNvdXJjZX0gT3duaW5nIHNvdXJjZS5cbiAqL1xuZnVuY3Rpb24gc291cmNlRm9yTG9jYXRpb24obG9jYXRpb24sIHNvdXJjZXMpIHtcbiAgY29uc3Qgc291cmNlID0gc291cmNlcy5maW5kKChjYW5kaWRhdGUpID0+IHNvdXJjZU93bnNMb2NhdGlvbihjYW5kaWRhdGUsIGxvY2F0aW9uKSlcblxuICBpZiAoIXNvdXJjZSkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoYE5vIHJlZ2lzdGVyZWQgc291cmNlIG93bnMgJHtsb2NhdGlvbi5maWxlbmFtZX06JHtsb2NhdGlvbi5zdGFydC5vZmZzZXR9LmApXG5cbiAgcmV0dXJuIHNvdXJjZVxufVxuXG4vKipcbiAqIENyZWF0ZXMgZGlyZWN0IHNvdXJjZSBwcm92ZW5hbmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlJlZ2lzdGVyZWRTb3VyY2V9IHNvdXJjZSAtIFNvdXJjZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbn0gbG9jYXRpb24gLSBMb2NhdGlvbi5cbiAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZU9yaWdpbn0gT3JpZ2luLlxuICovXG5mdW5jdGlvbiBzb3VyY2VPcmlnaW4oc291cmNlLCBsb2NhdGlvbikge1xuICByZXR1cm4ge2tpbmQ6IFwic291cmNlXCIsIGxvY2F0aW9uLCBzb3VyY2VJZDogc291cmNlLmlkfVxufVxuXG4vKipcbiAqIEZpbmRzIG9uZSBub2RlIHByb3ZlbmFuY2UgcmVjb3JkIGJ5IHNlbWFudGljIG9iamVjdCBvciBub2RlIGlkZW50aXR5LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTW9kdWxlfSBtb2R1bGUgLSBTZW1hbnRpYyBtb2R1bGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlIHwgc3RyaW5nfSBub2RlIC0gU2VtYW50aWMgb2JqZWN0IG9yIG5vZGUgaWRlbnRpdHkuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY05vZGVQcm92ZW5hbmNlfSBQcm92ZW5hbmNlIHJlY29yZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE5vZGVQcm92ZW5hbmNlKG1vZHVsZSwgbm9kZSkge1xuICByZXF1aXJlUHJvdmVuYW5jZShtb2R1bGUpXG4gIGNvbnN0IGluZGV4ID0gY3JlYXRlR2VuZXJhdGlvbkluZGV4KG1vZHVsZSlcbiAgY29uc3QgcmVjb3JkID0gdHlwZW9mIG5vZGUgPT0gXCJzdHJpbmdcIlxuICAgID8gaW5kZXgucHJvdmVuYW5jZS5ub2Rlcy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PSBub2RlKVxuICAgIDogaW5kZXgucmVjb3JkRm9yKG5vZGUpXG5cbiAgaWYgKCFyZWNvcmQpIHRocm93IG5ldyBSYW5nZUVycm9yKGBVbmtub3duIHNlbWFudGljIG5vZGU6ICR7bm9kZX1gKVxuXG4gIHJldHVybiByZWNvcmRcbn1cblxuLyoqXG4gKiBGaW5kcyBvbmUgc2VtYW50aWMgc3ltYm9sIHJlY29yZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gU2VtYW50aWMgbW9kdWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IHN5bWJvbElkIC0gU3ltYm9sIGlkZW50aXR5LlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNTeW1ib2xQcm92ZW5hbmNlfSBTeW1ib2wgcmVjb3JkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3ltYm9sUHJvdmVuYW5jZShtb2R1bGUsIHN5bWJvbElkKSB7XG4gIHJlcXVpcmVQcm92ZW5hbmNlKG1vZHVsZSlcbiAgY29uc3Qgc3ltYm9sID0gY3JlYXRlR2VuZXJhdGlvbkluZGV4KG1vZHVsZSkucHJvdmVuYW5jZS5zeW1ib2xzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmlkID09IHN5bWJvbElkKVxuXG4gIGlmICghc3ltYm9sKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgVW5rbm93biBzZW1hbnRpYyBzeW1ib2w6ICR7c3ltYm9sSWR9YClcblxuICByZXR1cm4gc3ltYm9sXG59XG5cbi8qKlxuICogUmVxdWlyZXMgZnJvbnRlbmQgcHJvdmVuYW5jZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gU2VtYW50aWMgbW9kdWxlLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNQcm92ZW5hbmNlfSBQcm92ZW5hbmNlLlxuICovXG5mdW5jdGlvbiByZXF1aXJlUHJvdmVuYW5jZShtb2R1bGUpIHtcbiAgaWYgKCFtb2R1bGUucHJvdmVuYW5jZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlNlbWFudGljIG1vZHVsZSBkb2VzIG5vdCBjb250YWluIHNvdXJjZSBwcm92ZW5hbmNlLlwiKVxuXG4gIHJldHVybiBtb2R1bGUucHJvdmVuYW5jZVxufVxuXG4vKipcbiAqIFRyYXZlcnNlcyBwdWJsaWMgc2VtYW50aWMgbm9kZXMgaW4gb25lIHN0YWJsZSBvcmRlci5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5TZW1hbnRpY01vZHVsZX0gbW9kdWxlIC0gU2VtYW50aWMgbW9kdWxlLlxuICogQHJldHVybnMge3tub2RlOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTm9kZSwgb3duZXJMb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgcGF0aDogc3RyaW5nfVtdfSBFbnRyaWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VtYW50aWNFbnRyaWVzKG1vZHVsZSkge1xuICAvKiogQHR5cGUge3tub2RlOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTm9kZSwgb3duZXJMb2NhdGlvbjogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5Tb3VyY2VMb2NhdGlvbiwgcGF0aDogc3RyaW5nfVtdfSAqL1xuICBjb25zdCBlbnRyaWVzID0gW11cblxuICB2aXNpdChtb2R1bGUsIFwiXCIsIG1vZHVsZS5sb2NhdGlvbilcblxuICByZXR1cm4gZW50cmllc1xuXG4gIC8qKlxuICAgKiBWaXNpdHMgb25lIHNlbWFudGljIG5vZGUgYW5kIGl0cyBjaGlsZHJlbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNlbWFudGljTm9kZX0gbm9kZSAtIEN1cnJlbnQgbm9kZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBDdXJyZW50IEpTT04gUG9pbnRlci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlNvdXJjZUxvY2F0aW9ufSBvd25lckxvY2F0aW9uIC0gTmVhcmVzdCBsb2NhdGVkIG93bmVyLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGZ1bmN0aW9uIHZpc2l0KG5vZGUsIHBhdGgsIG93bmVyTG9jYXRpb24pIHtcbiAgICBjb25zdCBsb2NhdGlvbiA9IFwibG9jYXRpb25cIiBpbiBub2RlID8gbm9kZS5sb2NhdGlvbiA6IG93bmVyTG9jYXRpb25cblxuICAgIGVudHJpZXMucHVzaCh7bm9kZSwgb3duZXJMb2NhdGlvbjogbG9jYXRpb24sIHBhdGh9KVxuXG4gICAgaWYgKG5vZGUua2luZCA9PSBcIk1vZHVsZVwiKSB7XG4gICAgICBub2RlLmZ1bmN0aW9ucy5mb3JFYWNoKChjaGlsZCwgaW5kZXgpID0+IHZpc2l0KGNoaWxkLCBgL2Z1bmN0aW9ucy8ke2luZGV4fWAsIGxvY2F0aW9uKSlcbiAgICAgIHZpc2l0KG5vZGUuZW50cnlQb2ludCwgXCIvZW50cnlQb2ludFwiLCBsb2NhdGlvbilcbiAgICB9IGVsc2UgaWYgKG5vZGUua2luZCA9PSBcIkZ1bmN0aW9uRGVjbGFyYXRpb25cIikge1xuICAgICAgbm9kZS5wYXJhbWV0ZXJzLmZvckVhY2goKGNoaWxkLCBpbmRleCkgPT4gdmlzaXQoY2hpbGQsIGAke3BhdGh9L3BhcmFtZXRlcnMvJHtpbmRleH1gLCBsb2NhdGlvbikpXG4gICAgICB2aXNpdChub2RlLnJldHVyblR5cGUsIGAke3BhdGh9L3JldHVyblR5cGVgLCBsb2NhdGlvbilcbiAgICAgIHZpc2l0KG5vZGUuYm9keSwgYCR7cGF0aH0vYm9keWAsIGxvY2F0aW9uKVxuICAgIH0gZWxzZSBpZiAobm9kZS5raW5kID09IFwiQmxvY2tcIikge1xuICAgICAgbm9kZS5zdGF0ZW1lbnRzLmZvckVhY2goKGNoaWxkLCBpbmRleCkgPT4gdmlzaXQoY2hpbGQsIGAke3BhdGh9L3N0YXRlbWVudHMvJHtpbmRleH1gLCBsb2NhdGlvbikpXG4gICAgfSBlbHNlIGlmIChub2RlLmtpbmQgPT0gXCJQYXJhbWV0ZXJcIikge1xuICAgICAgdmlzaXQobm9kZS50eXBlLCBgJHtwYXRofS90eXBlYCwgbG9jYXRpb24pXG4gICAgfSBlbHNlIGlmIChub2RlLmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpIHtcbiAgICAgIHZpc2l0KG5vZGUudHlwZSwgYCR7cGF0aH0vdHlwZWAsIGxvY2F0aW9uKVxuICAgICAgdmlzaXQobm9kZS5pbml0aWFsaXplciwgYCR7cGF0aH0vaW5pdGlhbGl6ZXJgLCBsb2NhdGlvbilcbiAgICB9IGVsc2UgaWYgKG5vZGUua2luZCA9PSBcIkFzc2lnbm1lbnRTdGF0ZW1lbnRcIikge1xuICAgICAgdmlzaXQobm9kZS50YXJnZXQsIGAke3BhdGh9L3RhcmdldGAsIGxvY2F0aW9uKVxuICAgICAgdmlzaXQobm9kZS5leHByZXNzaW9uLCBgJHtwYXRofS9leHByZXNzaW9uYCwgbG9jYXRpb24pXG4gICAgfSBlbHNlIGlmIChub2RlLmtpbmQgPT0gXCJSZXR1cm5TdGF0ZW1lbnRcIiB8fCBub2RlLmtpbmQgPT0gXCJQcmludFN0YXRlbWVudFwiKSB7XG4gICAgICB2aXNpdChub2RlLmV4cHJlc3Npb24sIGAke3BhdGh9L2V4cHJlc3Npb25gLCBsb2NhdGlvbilcbiAgICB9IGVsc2UgaWYgKG5vZGUua2luZCA9PSBcIklmU3RhdGVtZW50XCIpIHtcbiAgICAgIHZpc2l0KG5vZGUuY29uZGl0aW9uLCBgJHtwYXRofS9jb25kaXRpb25gLCBsb2NhdGlvbilcbiAgICAgIHZpc2l0KG5vZGUuY29uc2VxdWVudCwgYCR7cGF0aH0vY29uc2VxdWVudGAsIGxvY2F0aW9uKVxuICAgICAgaWYgKG5vZGUuYWx0ZXJuYXRlKSB2aXNpdChub2RlLmFsdGVybmF0ZSwgYCR7cGF0aH0vYWx0ZXJuYXRlYCwgbG9jYXRpb24pXG4gICAgfSBlbHNlIGlmIChub2RlLmtpbmQgPT0gXCJFbnRyeVBvaW50XCIpIHtcbiAgICAgIHZpc2l0KG5vZGUuYm9keSwgYCR7cGF0aH0vYm9keWAsIGxvY2F0aW9uKVxuICAgIH0gZWxzZSBpZiAobm9kZS5raW5kID09IFwiVW5hcnlFeHByZXNzaW9uXCIpIHtcbiAgICAgIHZpc2l0KG5vZGUub3BlcmFuZCwgYCR7cGF0aH0vb3BlcmFuZGAsIGxvY2F0aW9uKVxuICAgIH0gZWxzZSBpZiAobm9kZS5raW5kID09IFwiQmluYXJ5RXhwcmVzc2lvblwiKSB7XG4gICAgICB2aXNpdChub2RlLmxlZnQsIGAke3BhdGh9L2xlZnRgLCBsb2NhdGlvbilcbiAgICAgIHZpc2l0KG5vZGUucmlnaHQsIGAke3BhdGh9L3JpZ2h0YCwgbG9jYXRpb24pXG4gICAgfSBlbHNlIGlmIChub2RlLmtpbmQgPT0gXCJDYWxsRXhwcmVzc2lvblwiKSB7XG4gICAgICBub2RlLmFyZ3VtZW50cy5mb3JFYWNoKChjaGlsZCwgaW5kZXgpID0+IHZpc2l0KGNoaWxkLCBgJHtwYXRofS9hcmd1bWVudHMvJHtpbmRleH1gLCBsb2NhdGlvbikpXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUmVzb2x2ZXMgZGVjbGFyYXRpb25zIGFuZCByZWZlcmVuY2VzIGFmdGVyIHNlbWFudGljIHZhbGlkYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNNb2R1bGV9IG1vZHVsZSAtIFZhbGlkYXRlZCBtb2R1bGUuXG4gKiBAcGFyYW0ge01hcDxzdHJpbmcsIGltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNOb2RlUHJvdmVuYW5jZT59IHJlY29yZHMgLSBOb2RlIHJlY29yZHMgYnkgb2NjdXJyZW5jZSBwYXRoLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNTeW1ib2xQcm92ZW5hbmNlW119IFN5bWJvbHMuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2xzKG1vZHVsZSwgcmVjb3Jkcykge1xuICAvKiogQHR5cGUge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNTeW1ib2xQcm92ZW5hbmNlW119ICovXG4gIGNvbnN0IHN5bWJvbHMgPSBbXVxuICAvKiogQHR5cGUge01hcDxzdHJpbmcsIHN0cmluZz59ICovXG4gIGNvbnN0IGZ1bmN0aW9ucyA9IG5ldyBNYXAoKVxuXG4gIGZvciAoY29uc3QgW2luZGV4LCBkZWNsYXJhdGlvbl0gb2YgbW9kdWxlLmZ1bmN0aW9ucy5lbnRyaWVzKCkpIHtcbiAgICBmdW5jdGlvbnMuc2V0KGRlY2xhcmF0aW9uLm5hbWUsIGRlY2xhcmUoZGVjbGFyYXRpb24sIGRlY2xhcmF0aW9uLm5hbWUsIFwiZnVuY3Rpb25cIiwgYC9mdW5jdGlvbnMvJHtpbmRleH1gKSlcbiAgfVxuXG4gIGZvciAoY29uc3QgW2luZGV4LCBkZWNsYXJhdGlvbl0gb2YgbW9kdWxlLmZ1bmN0aW9ucy5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCBkZWNsYXJhdGlvblBhdGggPSBgL2Z1bmN0aW9ucy8ke2luZGV4fWBcbiAgICBjb25zdCBzY29wZSA9IG5ldyBNYXAoKVxuXG4gICAgZm9yIChjb25zdCBbcGFyYW1ldGVySW5kZXgsIHBhcmFtZXRlcl0gb2YgZGVjbGFyYXRpb24ucGFyYW1ldGVycy5lbnRyaWVzKCkpIHtcbiAgICAgIHNjb3BlLnNldChwYXJhbWV0ZXIubmFtZSwgZGVjbGFyZShwYXJhbWV0ZXIsIHBhcmFtZXRlci5uYW1lLCBcInBhcmFtZXRlclwiLCBgJHtkZWNsYXJhdGlvblBhdGh9L3BhcmFtZXRlcnMvJHtwYXJhbWV0ZXJJbmRleH1gKSlcbiAgICB9XG4gICAgdmlzaXRCbG9jayhkZWNsYXJhdGlvbi5ib2R5LCBzY29wZSwgYCR7ZGVjbGFyYXRpb25QYXRofS9ib2R5YClcbiAgfVxuXG4gIHZpc2l0QmxvY2sobW9kdWxlLmVudHJ5UG9pbnQuYm9keSwgbmV3IE1hcCgpLCBcIi9lbnRyeVBvaW50L2JvZHlcIilcblxuICByZXR1cm4gc3ltYm9sc1xuXG4gIC8qKlxuICAgKiBEZWNsYXJlcyBvbmUgY2Fub25pY2FsIHN5bWJvbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkZ1bmN0aW9uRGVjbGFyYXRpb24gfCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLlBhcmFtZXRlciB8IGltcG9ydChcIi4vdHlwZXMuanNcIikuTG9jYWxEZWNsYXJhdGlvbn0gbm9kZSAtIERlY2xhcmF0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFN5bWJvbCBuYW1lLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuU2VtYW50aWNTeW1ib2xLaW5kfSBraW5kIC0gU3ltYm9sIGtpbmQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gRGVjbGFyYXRpb24gb2NjdXJyZW5jZSBwYXRoLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBTeW1ib2wgaWRlbnRpdHkuXG4gICAqL1xuICBmdW5jdGlvbiBkZWNsYXJlKG5vZGUsIG5hbWUsIGtpbmQsIHBhdGgpIHtcbiAgICBjb25zdCByZWNvcmQgPSByZWNvcmRzLmdldChwYXRoKVxuXG4gICAgaWYgKCFyZWNvcmQpIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyBwcm92ZW5hbmNlIGZvciAke25vZGUua2luZH0uYClcblxuICAgIGNvbnN0IGxvY2F0aW9uID0gcmVjb3JkLnJhbmdlcy5uYW1lID8/IG5vZGUubG9jYXRpb25cbiAgICBjb25zdCBpZCA9IGBzeW1ib2w6JHtzeW1ib2xzLmxlbmd0aH1gXG5cbiAgICByZWNvcmQuc3ltYm9sSWQgPSBpZFxuICAgIHN5bWJvbHMucHVzaCh7ZGVjbGFyYXRpb25Ob2RlSWQ6IHJlY29yZC5pZCwgaWQsIGtpbmQsIGxvY2F0aW9uLCBuYW1lLCByZWZlcmVuY2VzOiBbXX0pXG5cbiAgICByZXR1cm4gaWRcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyByZWZlcmVuY2VzIGluIG9uZSBsZXhpY2FsIGJsb2NrLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuQmxvY2t9IGJsb2NrIC0gU2VtYW50aWMgYmxvY2suXG4gICAqIEBwYXJhbSB7TWFwPHN0cmluZywgc3RyaW5nPn0gcGFyZW50IC0gVmlzaWJsZSBiaW5kaW5ncy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBTdGF0ZW1lbnQgc2VxdWVuY2UgcGF0aC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiB2aXNpdEJsb2NrKGJsb2NrLCBwYXJlbnQsIHBhdGgpIHtcbiAgICBjb25zdCBzY29wZSA9IG5ldyBNYXAocGFyZW50KVxuXG4gICAgZm9yIChjb25zdCBbaW5kZXgsIHN0YXRlbWVudF0gb2YgYmxvY2suc3RhdGVtZW50cy5lbnRyaWVzKCkpIHtcbiAgICAgIGNvbnN0IHN0YXRlbWVudFBhdGggPSBgJHtwYXRofS9zdGF0ZW1lbnRzLyR7aW5kZXh9YFxuXG4gICAgICBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJMb2NhbERlY2xhcmF0aW9uXCIpIHtcbiAgICAgICAgdmlzaXRFeHByZXNzaW9uKHN0YXRlbWVudC5pbml0aWFsaXplciwgc2NvcGUsIGAke3N0YXRlbWVudFBhdGh9L2luaXRpYWxpemVyYClcbiAgICAgICAgc2NvcGUuc2V0KHN0YXRlbWVudC5uYW1lLCBkZWNsYXJlKHN0YXRlbWVudCwgc3RhdGVtZW50Lm5hbWUsIFwibG9jYWxcIiwgc3RhdGVtZW50UGF0aCkpXG4gICAgICB9IGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiQXNzaWdubWVudFN0YXRlbWVudFwiKSB7XG4gICAgICAgIHJlZmVyZW5jZShzdGF0ZW1lbnQudGFyZ2V0LCBzY29wZS5nZXQoc3RhdGVtZW50LnRhcmdldC5uYW1lKSwgXCJ3cml0ZVwiLCBgJHtzdGF0ZW1lbnRQYXRofS90YXJnZXRgKVxuICAgICAgICB2aXNpdEV4cHJlc3Npb24oc3RhdGVtZW50LmV4cHJlc3Npb24sIHNjb3BlLCBgJHtzdGF0ZW1lbnRQYXRofS9leHByZXNzaW9uYClcbiAgICAgIH0gZWxzZSBpZiAoc3RhdGVtZW50LmtpbmQgPT0gXCJSZXR1cm5TdGF0ZW1lbnRcIiB8fCBzdGF0ZW1lbnQua2luZCA9PSBcIlByaW50U3RhdGVtZW50XCIpIHtcbiAgICAgICAgdmlzaXRFeHByZXNzaW9uKHN0YXRlbWVudC5leHByZXNzaW9uLCBzY29wZSwgYCR7c3RhdGVtZW50UGF0aH0vZXhwcmVzc2lvbmApXG4gICAgICB9IGVsc2UgaWYgKHN0YXRlbWVudC5raW5kID09IFwiSWZTdGF0ZW1lbnRcIikge1xuICAgICAgICB2aXNpdEV4cHJlc3Npb24oc3RhdGVtZW50LmNvbmRpdGlvbiwgc2NvcGUsIGAke3N0YXRlbWVudFBhdGh9L2NvbmRpdGlvbmApXG4gICAgICAgIHZpc2l0QmxvY2soc3RhdGVtZW50LmNvbnNlcXVlbnQsIHNjb3BlLCBgJHtzdGF0ZW1lbnRQYXRofS9jb25zZXF1ZW50YClcbiAgICAgICAgaWYgKHN0YXRlbWVudC5hbHRlcm5hdGUpIHZpc2l0QmxvY2soc3RhdGVtZW50LmFsdGVybmF0ZSwgc2NvcGUsIGAke3N0YXRlbWVudFBhdGh9L2FsdGVybmF0ZWApXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHJlZmVyZW5jZXMgaW4gb25lIGV4cHJlc3Npb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5FeHByZXNzaW9ufSBleHByZXNzaW9uIC0gRXhwcmVzc2lvbi5cbiAgICogQHBhcmFtIHtNYXA8c3RyaW5nLCBzdHJpbmc+fSBzY29wZSAtIFZpc2libGUgYmluZGluZ3MuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gRXhwcmVzc2lvbiBvY2N1cnJlbmNlIHBhdGguXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZnVuY3Rpb24gdmlzaXRFeHByZXNzaW9uKGV4cHJlc3Npb24sIHNjb3BlLCBwYXRoKSB7XG4gICAgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIklkZW50aWZpZXJFeHByZXNzaW9uXCIpIHJlZmVyZW5jZShleHByZXNzaW9uLCBzY29wZS5nZXQoZXhwcmVzc2lvbi5uYW1lKSwgXCJyZWFkXCIsIHBhdGgpXG4gICAgZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiQ2FsbEV4cHJlc3Npb25cIikge1xuICAgICAgcmVmZXJlbmNlKGV4cHJlc3Npb24sIGZ1bmN0aW9ucy5nZXQoZXhwcmVzc2lvbi5jYWxsZWUpLCBcImNhbGxcIiwgcGF0aClcbiAgICAgIGZvciAoY29uc3QgW2luZGV4LCBhcmd1bWVudF0gb2YgZXhwcmVzc2lvbi5hcmd1bWVudHMuZW50cmllcygpKSB2aXNpdEV4cHJlc3Npb24oYXJndW1lbnQsIHNjb3BlLCBgJHtwYXRofS9hcmd1bWVudHMvJHtpbmRleH1gKVxuICAgIH0gZWxzZSBpZiAoZXhwcmVzc2lvbi5raW5kID09IFwiVW5hcnlFeHByZXNzaW9uXCIpIHtcbiAgICAgIHZpc2l0RXhwcmVzc2lvbihleHByZXNzaW9uLm9wZXJhbmQsIHNjb3BlLCBgJHtwYXRofS9vcGVyYW5kYClcbiAgICB9IGVsc2UgaWYgKGV4cHJlc3Npb24ua2luZCA9PSBcIkJpbmFyeUV4cHJlc3Npb25cIikge1xuICAgICAgdmlzaXRFeHByZXNzaW9uKGV4cHJlc3Npb24ubGVmdCwgc2NvcGUsIGAke3BhdGh9L2xlZnRgKVxuICAgICAgdmlzaXRFeHByZXNzaW9uKGV4cHJlc3Npb24ucmlnaHQsIHNjb3BlLCBgJHtwYXRofS9yaWdodGApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF0dGFjaGVzIG9uZSByZXNvbHZlZCBzeW1ib2wgcmVmZXJlbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuSWRlbnRpZmllckV4cHJlc3Npb24gfCBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkNhbGxFeHByZXNzaW9ufSBub2RlIC0gUmVmZXJlbmNlIG5vZGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgdW5kZWZpbmVkfSBzeW1ib2xJZCAtIFJlc29sdmVkIHN5bWJvbC5cbiAgICogQHBhcmFtIHtcInJlYWRcIiB8IFwid3JpdGVcIiB8IFwiY2FsbFwifSByb2xlIC0gUmVmZXJlbmNlIHJvbGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIC0gUmVmZXJlbmNlIG9jY3VycmVuY2UgcGF0aC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmdW5jdGlvbiByZWZlcmVuY2Uobm9kZSwgc3ltYm9sSWQsIHJvbGUsIHBhdGgpIHtcbiAgICBpZiAoIXN5bWJvbElkKSByZXR1cm5cblxuICAgIGNvbnN0IHJlY29yZCA9IHJlY29yZHMuZ2V0KHBhdGgpXG4gICAgY29uc3Qgc3ltYm9sID0gc3ltYm9scy5maW5kKChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PSBzeW1ib2xJZClcblxuICAgIGlmICghcmVjb3JkIHx8ICFzeW1ib2wpIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyBwcm92ZW5hbmNlIHdoaWxlIHJlc29sdmluZyAke25vZGUua2luZH0uYClcblxuICAgIGNvbnN0IGxvY2F0aW9uID0gcmVjb3JkLnJhbmdlc1tyb2xlID09IFwiY2FsbFwiID8gXCJjYWxsZWVcIiA6IFwibmFtZVwiXSA/PyBub2RlLmxvY2F0aW9uXG5cbiAgICByZWNvcmQuc3ltYm9sSWQgPSBzeW1ib2xJZFxuICAgIHN5bWJvbC5yZWZlcmVuY2VzLnB1c2goe2xvY2F0aW9uLCBub2RlSWQ6IHJlY29yZC5pZCwgcm9sZX0pXG4gIH1cbn1cbiJdfQ==