jderobot-ide-interface 0.3.17 → 0.3.19
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/dist/a5a14e7d119e89dea736.wasm +0 -0
- package/dist/components/Button/Button.styles.d.ts +3 -1
- package/dist/components/ButtonsContainer/ButtonsContainer.styles.d.ts +6 -2
- package/dist/components/Dropdown/Dropdown.styles.d.ts +3 -1
- package/dist/components/Explorer/Explorer.styles.d.ts +9 -3
- package/dist/components/Explorer/file_explorer/FileExplorer.styles.d.ts +3 -1
- package/dist/components/Explorer/file_explorer/MoreActionsMenu.styles.d.ts +12 -4
- package/dist/components/Explorer/file_explorer/TreeNode.styles.d.ts +18 -6
- package/dist/components/FileEditor/FileEditor.d.ts +2 -1
- package/dist/components/FileEditor/FileEditor.styles.d.ts +9 -3
- package/dist/components/FileEditor/IdeInterface.stories.d.ts +5 -0
- package/dist/components/FileEditor/TextEditor.d.ts +2 -1
- package/dist/components/FileEditor/lsp-client.d.ts +1 -0
- package/dist/components/IdeInterface/IdeInterface.d.ts +2 -1
- package/dist/components/IdeInterface/IdeInterface.stories.d.ts +1 -1
- package/dist/components/IdeInterface/IdeInterface.styles.d.ts +67 -1228
- package/dist/components/IdeInterface/TheoryInterface.styles.d.ts +21 -7
- package/dist/components/Modals/EditorKeybindModal.styles.d.ts +3 -1
- package/dist/components/Modals/ErrorModal.styles.d.ts +9 -3
- package/dist/components/Modals/Modal.styles.d.ts +68 -25
- package/dist/components/ProgressBar/ProgressBar.style.d.ts +3 -1
- package/dist/components/StatusBar/StatusBar.style.d.ts +9 -3
- package/dist/components/Theory/Canvas.styles.d.ts +3 -1
- package/dist/components/Theory/CarouselDisplay.styles.d.ts +39 -13
- package/dist/components/Theory/Code.styles.d.ts +3 -1
- package/dist/components/Theory/FormulaSection.styles.d.ts +3 -1
- package/dist/components/Theory/HighlightedSection.styles.d.ts +3 -1
- package/dist/components/Theory/Image.styles.d.ts +3 -1
- package/dist/components/Theory/ImageRow.styles.d.ts +3 -1
- package/dist/components/Theory/Link.styles.d.ts +3 -1
- package/dist/components/Theory/List.styles.d.ts +3 -1
- package/dist/components/Theory/LocalVideo.styles.d.ts +3 -1
- package/dist/components/Theory/NumberedList.styles.d.ts +3 -1
- package/dist/components/Theory/Section.styles.d.ts +6 -2
- package/dist/components/Theory/Subsection.styles.d.ts +6 -2
- package/dist/components/Theory/Subsubsection.styles.d.ts +6 -2
- package/dist/components/Theory/Timeline.styles.d.ts +24 -8
- package/dist/components/Theory/TimelineComparison.styles.d.ts +15 -5
- package/dist/components/Theory/YoutubeVideo.styles.d.ts +1 -1
- package/dist/components/VncViewer/VncViewer.styles.d.ts +12 -4
- package/dist/d94e0a7c7ed2cbcaeba4.html +123 -0
- package/dist/main.js +4071 -1890
- package/dist/node_fs_promises.main.js +13 -0
- package/dist/node_modules_vscode_diff_dist_worker_js_esm.main.js +397 -0
- package/dist/package.json +1 -1
- package/dist/vendors-node_modules_jschardet_index_js.main.js +8224 -0
- package/dist/vendors-node_modules_vscode_diff_dist_index_js.main.js +626 -0
- package/dist/vendors-node_modules_vscode_diff_dist_wire_js.main.js +2233 -0
- package/dist/vendors-node_modules_vscode_iconv-lite-umd_lib_iconv-lite-umd_js.main.js +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(this["webpackChunkjderobot_ide_interface"] = this["webpackChunkjderobot_ide_interface"] || []).push([["vendors-node_modules_vscode_diff_dist_index_js"],{
|
|
3
|
+
|
|
4
|
+
/***/ "./node_modules/@vscode/diff/dist/index.js"
|
|
5
|
+
/*!*************************************************!*\
|
|
6
|
+
!*** ./node_modules/@vscode/diff/dist/index.js ***!
|
|
7
|
+
\*************************************************/
|
|
8
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
9
|
+
|
|
10
|
+
__webpack_require__.r(__webpack_exports__);
|
|
11
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
12
|
+
/* harmony export */ AnnotatedStringEdit: () => (/* binding */ AnnotatedStringEdit),
|
|
13
|
+
/* harmony export */ AnnotatedStringReplacement: () => (/* binding */ AnnotatedStringReplacement),
|
|
14
|
+
/* harmony export */ DiffAnnotation: () => (/* binding */ DiffAnnotation),
|
|
15
|
+
/* harmony export */ DiffResult: () => (/* binding */ DiffResult),
|
|
16
|
+
/* harmony export */ Move: () => (/* binding */ Move),
|
|
17
|
+
/* harmony export */ OffsetRange: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.O),
|
|
18
|
+
/* harmony export */ OffsetRangeMapping: () => (/* binding */ OffsetRangeMapping),
|
|
19
|
+
/* harmony export */ StringEdit: () => (/* binding */ StringEdit),
|
|
20
|
+
/* harmony export */ StringReplacement: () => (/* binding */ StringReplacement),
|
|
21
|
+
/* harmony export */ _DefaultLinesDiffComputer: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.D),
|
|
22
|
+
/* harmony export */ _DetailedLineRangeMapping: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.b),
|
|
23
|
+
/* harmony export */ _LineRange: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.L),
|
|
24
|
+
/* harmony export */ _LineRangeMapping: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.d),
|
|
25
|
+
/* harmony export */ _LinesDiff: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.c),
|
|
26
|
+
/* harmony export */ _RangeMapping: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.R),
|
|
27
|
+
/* harmony export */ _getWasm: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.g),
|
|
28
|
+
/* harmony export */ _initWasm: () => (/* reexport safe */ _wire_js__WEBPACK_IMPORTED_MODULE_0__.i),
|
|
29
|
+
/* harmony export */ createDiffComputer: () => (/* binding */ createDiffComputer),
|
|
30
|
+
/* harmony export */ createWorkerDiffComputer: () => (/* binding */ createWorkerDiffComputer)
|
|
31
|
+
/* harmony export */ });
|
|
32
|
+
/* harmony import */ var _wire_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./wire.js */ "./node_modules/@vscode/diff/dist/wire.js");
|
|
33
|
+
/*---------------------------------------------------------------------------------------------
|
|
34
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
35
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
36
|
+
*--------------------------------------------------------------------------------------------*/
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A pair of ranges, one in `original`, one in `modified`.
|
|
42
|
+
*/
|
|
43
|
+
class OffsetRangeMapping {
|
|
44
|
+
original;
|
|
45
|
+
modified;
|
|
46
|
+
constructor(original, modified) {
|
|
47
|
+
this.original = original;
|
|
48
|
+
this.modified = modified;
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return `${this.original} <-> ${this.modified}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A single atomic replacement: replace `range` in the input with `newText`.
|
|
57
|
+
*/
|
|
58
|
+
class StringReplacement {
|
|
59
|
+
range;
|
|
60
|
+
newText;
|
|
61
|
+
constructor(range, newText) {
|
|
62
|
+
this.range = range;
|
|
63
|
+
this.newText = newText;
|
|
64
|
+
}
|
|
65
|
+
get isEmpty() {
|
|
66
|
+
return this.range.isEmpty && this.newText.length === 0;
|
|
67
|
+
}
|
|
68
|
+
toString() {
|
|
69
|
+
return `${this.range}->${JSON.stringify(this.newText)}`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A set of replacements applied in parallel to one input string.
|
|
74
|
+
*
|
|
75
|
+
* Invariants:
|
|
76
|
+
* - replacements are sorted by `range.start`
|
|
77
|
+
* - replacements do not overlap (touching is allowed)
|
|
78
|
+
* - all ranges live in the same coordinate space (the input passed to `apply`)
|
|
79
|
+
*/
|
|
80
|
+
class StringEdit {
|
|
81
|
+
replacements;
|
|
82
|
+
static empty = new StringEdit([]);
|
|
83
|
+
static single(replacement) {
|
|
84
|
+
return new StringEdit([replacement]);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validates that replacements are sorted and non-overlapping.
|
|
88
|
+
*/
|
|
89
|
+
static of(replacements) {
|
|
90
|
+
for (let i = 1; i < replacements.length; i++) {
|
|
91
|
+
const prev = replacements[i - 1];
|
|
92
|
+
const cur = replacements[i];
|
|
93
|
+
if (prev.range.endExclusive > cur.range.start) {
|
|
94
|
+
throw new Error(`StringEdit.of: replacements must be sorted and non-overlapping (` +
|
|
95
|
+
`${prev.range} vs ${cur.range})`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return new StringEdit(replacements);
|
|
99
|
+
}
|
|
100
|
+
constructor(replacements) {
|
|
101
|
+
this.replacements = replacements;
|
|
102
|
+
}
|
|
103
|
+
get isEmpty() {
|
|
104
|
+
return this.replacements.length === 0;
|
|
105
|
+
}
|
|
106
|
+
apply(text) {
|
|
107
|
+
if (this.replacements.length === 0) {
|
|
108
|
+
return text;
|
|
109
|
+
}
|
|
110
|
+
const parts = [];
|
|
111
|
+
let cursor = 0;
|
|
112
|
+
for (const r of this.replacements) {
|
|
113
|
+
parts.push(text.substring(cursor, r.range.start));
|
|
114
|
+
parts.push(r.newText);
|
|
115
|
+
cursor = r.range.endExclusive;
|
|
116
|
+
}
|
|
117
|
+
parts.push(text.substring(cursor));
|
|
118
|
+
return parts.join('');
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Returns an edit `E` such that `E.apply(this.apply(input)) === input`.
|
|
122
|
+
*/
|
|
123
|
+
inverse(input) {
|
|
124
|
+
const out = [];
|
|
125
|
+
let delta = 0;
|
|
126
|
+
for (const r of this.replacements) {
|
|
127
|
+
const newStart = r.range.start + delta;
|
|
128
|
+
const newEnd = newStart + r.newText.length;
|
|
129
|
+
const oldText = input.substring(r.range.start, r.range.endExclusive);
|
|
130
|
+
out.push(new StringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(newStart, newEnd), oldText));
|
|
131
|
+
delta += r.newText.length - r.range.length;
|
|
132
|
+
}
|
|
133
|
+
return new StringEdit(out);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Joins touching replacements and drops no-ops.
|
|
137
|
+
*/
|
|
138
|
+
normalize() {
|
|
139
|
+
const out = [];
|
|
140
|
+
for (const r of this.replacements) {
|
|
141
|
+
if (r.isEmpty) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const prev = out[out.length - 1];
|
|
145
|
+
if (prev && prev.range.endExclusive === r.range.start) {
|
|
146
|
+
out[out.length - 1] = new StringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(prev.range.start, r.range.endExclusive), prev.newText + r.newText);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
out.push(r);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return new StringEdit(out);
|
|
153
|
+
}
|
|
154
|
+
toString() {
|
|
155
|
+
return `StringEdit[${this.replacements.map(r => r.toString()).join(', ')}]`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* An atomic replacement carrying user-defined metadata.
|
|
161
|
+
*/
|
|
162
|
+
class AnnotatedStringReplacement {
|
|
163
|
+
range;
|
|
164
|
+
newText;
|
|
165
|
+
data;
|
|
166
|
+
constructor(range, newText, data) {
|
|
167
|
+
this.range = range;
|
|
168
|
+
this.newText = newText;
|
|
169
|
+
this.data = data;
|
|
170
|
+
}
|
|
171
|
+
get isEmpty() {
|
|
172
|
+
return this.range.isEmpty && this.newText.length === 0;
|
|
173
|
+
}
|
|
174
|
+
toString() {
|
|
175
|
+
return `${this.range}->${JSON.stringify(this.newText)}#${this.data}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* A set of annotated replacements applied in parallel.
|
|
180
|
+
*
|
|
181
|
+
* Invariants: same as `StringEdit` (sorted by `range.start`, non-overlapping,
|
|
182
|
+
* shared coordinate space).
|
|
183
|
+
*/
|
|
184
|
+
class AnnotatedStringEdit {
|
|
185
|
+
replacements;
|
|
186
|
+
static empty() {
|
|
187
|
+
return new AnnotatedStringEdit([]);
|
|
188
|
+
}
|
|
189
|
+
static single(replacement) {
|
|
190
|
+
return new AnnotatedStringEdit([replacement]);
|
|
191
|
+
}
|
|
192
|
+
static of(replacements) {
|
|
193
|
+
for (let i = 1; i < replacements.length; i++) {
|
|
194
|
+
const prev = replacements[i - 1];
|
|
195
|
+
const cur = replacements[i];
|
|
196
|
+
if (prev.range.endExclusive > cur.range.start) {
|
|
197
|
+
throw new Error(`AnnotatedStringEdit.of: replacements must be sorted and non-overlapping (` +
|
|
198
|
+
`${prev.range} vs ${cur.range})`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return new AnnotatedStringEdit(replacements);
|
|
202
|
+
}
|
|
203
|
+
constructor(replacements) {
|
|
204
|
+
this.replacements = replacements;
|
|
205
|
+
}
|
|
206
|
+
get isEmpty() {
|
|
207
|
+
return this.replacements.length === 0;
|
|
208
|
+
}
|
|
209
|
+
apply(text) {
|
|
210
|
+
if (this.replacements.length === 0) {
|
|
211
|
+
return text;
|
|
212
|
+
}
|
|
213
|
+
const parts = [];
|
|
214
|
+
let cursor = 0;
|
|
215
|
+
for (const r of this.replacements) {
|
|
216
|
+
parts.push(text.substring(cursor, r.range.start));
|
|
217
|
+
parts.push(r.newText);
|
|
218
|
+
cursor = r.range.endExclusive;
|
|
219
|
+
}
|
|
220
|
+
parts.push(text.substring(cursor));
|
|
221
|
+
return parts.join('');
|
|
222
|
+
}
|
|
223
|
+
inverse(input, invertData) {
|
|
224
|
+
const out = [];
|
|
225
|
+
let delta = 0;
|
|
226
|
+
for (const r of this.replacements) {
|
|
227
|
+
const newStart = r.range.start + delta;
|
|
228
|
+
const newEnd = newStart + r.newText.length;
|
|
229
|
+
const oldText = input.substring(r.range.start, r.range.endExclusive);
|
|
230
|
+
out.push(new AnnotatedStringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(newStart, newEnd), oldText, invertData(r.data)));
|
|
231
|
+
delta += r.newText.length - r.range.length;
|
|
232
|
+
}
|
|
233
|
+
return new AnnotatedStringEdit(out);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Joins touching replacements when their annotations join. Drops no-ops.
|
|
237
|
+
*/
|
|
238
|
+
normalize() {
|
|
239
|
+
const out = [];
|
|
240
|
+
for (const r of this.replacements) {
|
|
241
|
+
if (r.isEmpty) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const prev = out[out.length - 1];
|
|
245
|
+
if (prev && prev.range.endExclusive === r.range.start) {
|
|
246
|
+
const joined = prev.data.join(r.data);
|
|
247
|
+
if (joined !== undefined) {
|
|
248
|
+
out[out.length - 1] = new AnnotatedStringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(prev.range.start, r.range.endExclusive), prev.newText + r.newText, joined);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
out.push(r);
|
|
253
|
+
}
|
|
254
|
+
return new AnnotatedStringEdit(out);
|
|
255
|
+
}
|
|
256
|
+
mapData(f) {
|
|
257
|
+
return new AnnotatedStringEdit(this.replacements.map(r => new AnnotatedStringReplacement(r.range, r.newText, f(r.data))));
|
|
258
|
+
}
|
|
259
|
+
stripData() {
|
|
260
|
+
return StringEdit.of(this.replacements.map(r => new StringReplacement(r.range, r.newText)));
|
|
261
|
+
}
|
|
262
|
+
toString() {
|
|
263
|
+
return `AnnotatedStringEdit[${this.replacements.map(r => r.toString()).join(', ')}]`;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Diff result annotation.
|
|
268
|
+
*
|
|
269
|
+
* Carries flags describing the nature of the replacement. For now only
|
|
270
|
+
* `isFormattingChange` is exposed; more flags (e.g. move source/target,
|
|
271
|
+
* semantic category) can be added later.
|
|
272
|
+
*/
|
|
273
|
+
class DiffAnnotation {
|
|
274
|
+
isFormattingChange;
|
|
275
|
+
static change = new DiffAnnotation(false);
|
|
276
|
+
static formatting = new DiffAnnotation(true);
|
|
277
|
+
constructor(
|
|
278
|
+
/** Whether the replacement is purely a formatting change (whitespace, indentation, etc.). */
|
|
279
|
+
isFormattingChange) {
|
|
280
|
+
this.isFormattingChange = isFormattingChange;
|
|
281
|
+
}
|
|
282
|
+
join(other) {
|
|
283
|
+
if (this.isFormattingChange !== other.isFormattingChange) {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
toString() {
|
|
289
|
+
return this.isFormattingChange ? 'formatting' : 'change';
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* A block of text that was moved between two locations.
|
|
295
|
+
*
|
|
296
|
+
* `range` locates the block in `original` and in `modified` (offsets in the
|
|
297
|
+
* respective full texts). `innerEdit` describes the changes inside the moved
|
|
298
|
+
* block, with offsets local to the slice (i.e. `0` is the start of the slice).
|
|
299
|
+
*/
|
|
300
|
+
class Move {
|
|
301
|
+
range;
|
|
302
|
+
innerEdit;
|
|
303
|
+
constructor(range, innerEdit) {
|
|
304
|
+
this.range = range;
|
|
305
|
+
this.innerEdit = innerEdit;
|
|
306
|
+
}
|
|
307
|
+
toString() {
|
|
308
|
+
return `Move ${this.range}` + (this.innerEdit.isEmpty ? '' : ` (${this.innerEdit})`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Output of a diff computation.
|
|
314
|
+
*/
|
|
315
|
+
class DiffResult {
|
|
316
|
+
edits;
|
|
317
|
+
moves;
|
|
318
|
+
hitTimeout;
|
|
319
|
+
constructor(
|
|
320
|
+
/**
|
|
321
|
+
* Parallel set of replacements transforming `original` into `modified`,
|
|
322
|
+
* excluding any replacements that are part of a `Move`.
|
|
323
|
+
*
|
|
324
|
+
* When no moves are computed: `edits.apply(original) === modified`.
|
|
325
|
+
*/
|
|
326
|
+
edits,
|
|
327
|
+
/**
|
|
328
|
+
* Detected text moves. Empty unless `DiffOptions.computeMoves` is set.
|
|
329
|
+
*/
|
|
330
|
+
moves,
|
|
331
|
+
/**
|
|
332
|
+
* `true` if the algorithm aborted because of `maxComputationTimeMs`.
|
|
333
|
+
* The result is still valid but may be coarser than ideal.
|
|
334
|
+
*/
|
|
335
|
+
hitTimeout) {
|
|
336
|
+
this.edits = edits;
|
|
337
|
+
this.moves = moves;
|
|
338
|
+
this.hitTimeout = hitTimeout;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async function createDiffComputer(options = {}) {
|
|
343
|
+
if (options.useWasm) {
|
|
344
|
+
await (0,_wire_js__WEBPACK_IMPORTED_MODULE_0__.i)();
|
|
345
|
+
return new _WasmDiffComputer(options.algorithm);
|
|
346
|
+
}
|
|
347
|
+
return new _TsDiffComputer(options.algorithm);
|
|
348
|
+
}
|
|
349
|
+
// ============================================================================
|
|
350
|
+
// TS-backed computer
|
|
351
|
+
// ============================================================================
|
|
352
|
+
class _TsDiffComputer {
|
|
353
|
+
_algorithm;
|
|
354
|
+
_impl = new _wire_js__WEBPACK_IMPORTED_MODULE_0__.D();
|
|
355
|
+
constructor(_algorithm) {
|
|
356
|
+
this._algorithm = _algorithm;
|
|
357
|
+
}
|
|
358
|
+
computeDiff(original, modified, options) {
|
|
359
|
+
const originalLines = original.split('\n');
|
|
360
|
+
const modifiedLines = modified.split('\n');
|
|
361
|
+
const internal = {
|
|
362
|
+
maxComputationTimeMs: options?.maxComputationTimeMs ?? 0,
|
|
363
|
+
ignoreTrimWhitespace: options?.ignoreTrimWhitespace ?? false,
|
|
364
|
+
computeMoves: options?.computeMoves ?? false,
|
|
365
|
+
extendToSubwords: options?.extendToSubwords ?? false,
|
|
366
|
+
};
|
|
367
|
+
const linesDiff = this._impl.computeDiff(originalLines, modifiedLines, internal);
|
|
368
|
+
void this._algorithm; // currently a hint; auto-selection lives inside DefaultLinesDiffComputer
|
|
369
|
+
return _adaptLinesDiff(linesDiff, original, modified, originalLines, modifiedLines);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// ============================================================================
|
|
373
|
+
// WASM-backed computer
|
|
374
|
+
// ============================================================================
|
|
375
|
+
class _WasmDiffComputer {
|
|
376
|
+
_algorithm;
|
|
377
|
+
constructor(_algorithm) {
|
|
378
|
+
this._algorithm = _algorithm;
|
|
379
|
+
}
|
|
380
|
+
computeDiff(original, modified, options) {
|
|
381
|
+
const originalLines = original.split('\n');
|
|
382
|
+
const modifiedLines = modified.split('\n');
|
|
383
|
+
const wasmOptions = {};
|
|
384
|
+
if (options?.maxComputationTimeMs !== undefined)
|
|
385
|
+
wasmOptions.maxComputationTimeMs = options.maxComputationTimeMs;
|
|
386
|
+
if (options?.ignoreTrimWhitespace !== undefined)
|
|
387
|
+
wasmOptions.ignoreTrimWhitespace = options.ignoreTrimWhitespace;
|
|
388
|
+
if (options?.computeMoves !== undefined)
|
|
389
|
+
wasmOptions.computeMoves = options.computeMoves;
|
|
390
|
+
if (options?.extendToSubwords !== undefined)
|
|
391
|
+
wasmOptions.extendToSubwords = options.extendToSubwords;
|
|
392
|
+
const wasm = (0,_wire_js__WEBPACK_IMPORTED_MODULE_0__.g)();
|
|
393
|
+
const wasmResult = wasm.computeDiffLines(originalLines, modifiedLines, wasmOptions);
|
|
394
|
+
void this._algorithm;
|
|
395
|
+
const linesDiff = _wasmToLinesDiff(wasmResult);
|
|
396
|
+
return _adaptLinesDiff(linesDiff, original, modified, originalLines, modifiedLines);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function _wasmToLinesDiff(wasmResult) {
|
|
400
|
+
const changes = wasmResult.changes.map((c) => {
|
|
401
|
+
const inner = c.innerChanges?.map((ic) => new _wire_js__WEBPACK_IMPORTED_MODULE_0__.R(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.a(ic.originalStartLine, ic.originalStartColumn, ic.originalEndLine, ic.originalEndColumn), new _wire_js__WEBPACK_IMPORTED_MODULE_0__.a(ic.modifiedStartLine, ic.modifiedStartColumn, ic.modifiedEndLine, ic.modifiedEndColumn)));
|
|
402
|
+
return new _wire_js__WEBPACK_IMPORTED_MODULE_0__.b(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.L(c.original.startLineNumber, c.original.endLineNumberExclusive), new _wire_js__WEBPACK_IMPORTED_MODULE_0__.L(c.modified.startLineNumber, c.modified.endLineNumberExclusive), inner);
|
|
403
|
+
});
|
|
404
|
+
return new _wire_js__WEBPACK_IMPORTED_MODULE_0__.c(changes, [], wasmResult.hitTimeout);
|
|
405
|
+
}
|
|
406
|
+
// ============================================================================
|
|
407
|
+
// LinesDiff -> DiffResult adapter
|
|
408
|
+
// ============================================================================
|
|
409
|
+
/** @internal — exported for the worker-side client. */
|
|
410
|
+
function _adaptLinesDiff(linesDiff, original, modified, originalLines, modifiedLines) {
|
|
411
|
+
const originalLineStarts = _computeLineStarts(originalLines);
|
|
412
|
+
const modifiedLineStarts = _computeLineStarts(modifiedLines);
|
|
413
|
+
const replacements = [];
|
|
414
|
+
for (const change of linesDiff.changes) {
|
|
415
|
+
_appendChangeReplacements(change, original, modified, originalLines, modifiedLines, originalLineStarts, modifiedLineStarts, replacements);
|
|
416
|
+
}
|
|
417
|
+
const edits = AnnotatedStringEdit.of(replacements);
|
|
418
|
+
const moves = linesDiff.moves.map(m => _adaptMove(m, original, modified, originalLines, modifiedLines, originalLineStarts, modifiedLineStarts));
|
|
419
|
+
return new DiffResult(edits, moves, linesDiff.hitTimeout);
|
|
420
|
+
}
|
|
421
|
+
function _appendChangeReplacements(change, original, modified, originalLines, modifiedLines, originalLineStarts, modifiedLineStarts, out) {
|
|
422
|
+
if (change.innerChanges && change.innerChanges.length > 0) {
|
|
423
|
+
for (const ic of change.innerChanges) {
|
|
424
|
+
const origRange = _rangeToOffsetRange(ic.originalRange, original, originalLines, originalLineStarts);
|
|
425
|
+
const modRange = _rangeToOffsetRange(ic.modifiedRange, modified, modifiedLines, modifiedLineStarts);
|
|
426
|
+
const newText = modified.substring(modRange.start, modRange.endExclusive);
|
|
427
|
+
out.push(new AnnotatedStringReplacement(origRange, newText, DiffAnnotation.change));
|
|
428
|
+
}
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
// Fallback: no inner detail — replace the whole line range.
|
|
432
|
+
const origRange = _lineRangeToOffsetRange(change.original.startLineNumber, change.original.endLineNumberExclusive, original, originalLineStarts);
|
|
433
|
+
const modRange = _lineRangeToOffsetRange(change.modified.startLineNumber, change.modified.endLineNumberExclusive, modified, modifiedLineStarts);
|
|
434
|
+
const newText = modified.substring(modRange.start, modRange.endExclusive);
|
|
435
|
+
out.push(new AnnotatedStringReplacement(origRange, newText, DiffAnnotation.change));
|
|
436
|
+
}
|
|
437
|
+
function _adaptMove(move, original, modified, originalLines, modifiedLines, originalLineStarts, modifiedLineStarts) {
|
|
438
|
+
const origRange = _lineRangeToOffsetRange(move.lineRangeMapping.original.startLineNumber, move.lineRangeMapping.original.endLineNumberExclusive, original, originalLineStarts);
|
|
439
|
+
const modRange = _lineRangeToOffsetRange(move.lineRangeMapping.modified.startLineNumber, move.lineRangeMapping.modified.endLineNumberExclusive, modified, modifiedLineStarts);
|
|
440
|
+
// Build inner edit with offsets local to the moved slices.
|
|
441
|
+
const inner = [];
|
|
442
|
+
for (const change of move.changes) {
|
|
443
|
+
if (change.innerChanges && change.innerChanges.length > 0) {
|
|
444
|
+
for (const ic of change.innerChanges) {
|
|
445
|
+
const globalOrig = _rangeToOffsetRange(ic.originalRange, original, originalLines, originalLineStarts);
|
|
446
|
+
const globalMod = _rangeToOffsetRange(ic.modifiedRange, modified, modifiedLines, modifiedLineStarts);
|
|
447
|
+
inner.push(new StringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(globalOrig.start - origRange.start, globalOrig.endExclusive - origRange.start), modified.substring(globalMod.start, globalMod.endExclusive)));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
const globalOrig = _lineRangeToOffsetRange(change.original.startLineNumber, change.original.endLineNumberExclusive, original, originalLineStarts);
|
|
452
|
+
const globalMod = _lineRangeToOffsetRange(change.modified.startLineNumber, change.modified.endLineNumberExclusive, modified, modifiedLineStarts);
|
|
453
|
+
inner.push(new StringReplacement(new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(globalOrig.start - origRange.start, globalOrig.endExclusive - origRange.start), modified.substring(globalMod.start, globalMod.endExclusive)));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return new Move(new OffsetRangeMapping(origRange, modRange), StringEdit.of(inner));
|
|
457
|
+
}
|
|
458
|
+
// ----- offset/line helpers -----
|
|
459
|
+
function _computeLineStarts(lines) {
|
|
460
|
+
// Offsets correspond to `lines.join('\n')`, which equals the input string
|
|
461
|
+
// when the input was split by `\n`.
|
|
462
|
+
const starts = new Array(lines.length + 1);
|
|
463
|
+
starts[0] = 0;
|
|
464
|
+
for (let i = 0; i < lines.length; i++) {
|
|
465
|
+
starts[i + 1] = starts[i] + lines[i].length + 1; // +1 for the '\n'
|
|
466
|
+
}
|
|
467
|
+
// `starts[lines.length]` is one past the synthetic trailing newline; the
|
|
468
|
+
// real text ends one earlier when there is no trailing newline (which is
|
|
469
|
+
// what `split('\n')` produces for non-newline-terminated input).
|
|
470
|
+
return starts;
|
|
471
|
+
}
|
|
472
|
+
function _lineRangeToOffsetRange(startLineNumber, endLineNumberExclusive, text, lineStarts) {
|
|
473
|
+
const start = _lineColToOffset(startLineNumber, 1, text, lineStarts);
|
|
474
|
+
const end = _lineColToOffset(endLineNumberExclusive, 1, text, lineStarts);
|
|
475
|
+
return new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(start, end);
|
|
476
|
+
}
|
|
477
|
+
function _rangeToOffsetRange(range, text, lines, lineStarts) {
|
|
478
|
+
const start = _lineColToOffset(range.startLineNumber, range.startColumn, text, lineStarts);
|
|
479
|
+
const end = _lineColToOffset(range.endLineNumber, range.endColumn, text, lineStarts);
|
|
480
|
+
return new _wire_js__WEBPACK_IMPORTED_MODULE_0__.O(start, end);
|
|
481
|
+
}
|
|
482
|
+
function _lineColToOffset(lineNumber, column, text, lineStarts) {
|
|
483
|
+
// `lineNumber` and `column` are 1-based; `endLineNumberExclusive` can be
|
|
484
|
+
// `lines.length + 1` (one past the last line).
|
|
485
|
+
if (lineNumber <= 0) {
|
|
486
|
+
return 0;
|
|
487
|
+
}
|
|
488
|
+
if (lineNumber > lineStarts.length) {
|
|
489
|
+
return text.length;
|
|
490
|
+
}
|
|
491
|
+
const base = lineStarts[lineNumber - 1];
|
|
492
|
+
const offset = base + (column - 1);
|
|
493
|
+
return Math.min(Math.max(offset, 0), text.length);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Main-thread client for the diff worker. Exposes an async `IAsyncDiffComputer`.
|
|
498
|
+
*
|
|
499
|
+
* Inputs travel as `string[]` via structured-clone postMessage. The response
|
|
500
|
+
* is a small JSON-friendly `WireLinesDiff`; the main thread reconstructs the
|
|
501
|
+
* full `LinesDiff` and runs `_adaptLinesDiff` locally (it already has the
|
|
502
|
+
* input strings).
|
|
503
|
+
*/
|
|
504
|
+
async function createWorkerDiffComputer(opts = {}) {
|
|
505
|
+
const worker = opts.workerFactory ? opts.workerFactory() : defaultWorkerFactory();
|
|
506
|
+
const backend = opts.useWasm ? 'wasm' : 'ts';
|
|
507
|
+
const computer = new _WorkerDiffComputer(worker, backend);
|
|
508
|
+
await computer.init();
|
|
509
|
+
return computer;
|
|
510
|
+
}
|
|
511
|
+
function defaultWorkerFactory() {
|
|
512
|
+
// The `?esm` marker is auto-discovered by `@vscode/*-plugin-esm-url`
|
|
513
|
+
// bundler plugins; they emit `worker.ts` as a sibling `worker.js` bundle
|
|
514
|
+
// and rewrite this URL accordingly.
|
|
515
|
+
return new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u("node_modules_vscode_diff_dist_worker_js_esm"), __webpack_require__.b), { type: undefined });
|
|
516
|
+
}
|
|
517
|
+
class _WorkerDiffComputer {
|
|
518
|
+
_worker;
|
|
519
|
+
_backend;
|
|
520
|
+
_nextId = 1;
|
|
521
|
+
_pending = new Map();
|
|
522
|
+
_pendingInit = null;
|
|
523
|
+
_disposed = false;
|
|
524
|
+
constructor(_worker, _backend) {
|
|
525
|
+
this._worker = _worker;
|
|
526
|
+
this._backend = _backend;
|
|
527
|
+
this._worker.addEventListener('message', (ev) => {
|
|
528
|
+
this._onMessage(ev.data);
|
|
529
|
+
});
|
|
530
|
+
this._worker.addEventListener('error', (ev) => {
|
|
531
|
+
this._failAll(new Error(`Worker error: ${ev.message ?? 'unknown'}`));
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
init() {
|
|
535
|
+
const id = this._nextId++;
|
|
536
|
+
const req = { kind: 'init', id, backend: this._backend };
|
|
537
|
+
return new Promise((resolve, reject) => {
|
|
538
|
+
this._pendingInit = { resolve, reject };
|
|
539
|
+
this._worker.postMessage(req);
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
computeDiff(original, modified, options = {}) {
|
|
543
|
+
if (this._disposed) {
|
|
544
|
+
return Promise.reject(new Error('Worker computer disposed'));
|
|
545
|
+
}
|
|
546
|
+
const id = this._nextId++;
|
|
547
|
+
const originalLines = original.split('\n');
|
|
548
|
+
const modifiedLines = modified.split('\n');
|
|
549
|
+
const msg = {
|
|
550
|
+
kind: 'computeDiff',
|
|
551
|
+
id,
|
|
552
|
+
backend: this._backend,
|
|
553
|
+
originalLines,
|
|
554
|
+
modifiedLines,
|
|
555
|
+
options,
|
|
556
|
+
};
|
|
557
|
+
return new Promise((resolve, reject) => {
|
|
558
|
+
this._pending.set(id, {
|
|
559
|
+
resolve,
|
|
560
|
+
reject,
|
|
561
|
+
original,
|
|
562
|
+
modified,
|
|
563
|
+
originalLines,
|
|
564
|
+
modifiedLines,
|
|
565
|
+
});
|
|
566
|
+
this._worker.postMessage(msg);
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
dispose() {
|
|
570
|
+
if (this._disposed)
|
|
571
|
+
return;
|
|
572
|
+
this._disposed = true;
|
|
573
|
+
this._failAll(new Error('Worker computer disposed'));
|
|
574
|
+
this._worker.terminate();
|
|
575
|
+
}
|
|
576
|
+
_onMessage(msg) {
|
|
577
|
+
if (msg.kind === 'init') {
|
|
578
|
+
const pending = this._pendingInit;
|
|
579
|
+
this._pendingInit = null;
|
|
580
|
+
pending?.resolve();
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
const entry = this._pending.get(msg.id);
|
|
584
|
+
if (!entry) {
|
|
585
|
+
// Init failure is reported on the init id with `kind === 'computeDiff'`
|
|
586
|
+
// and `ok === false`; route to the init promise if it's still pending.
|
|
587
|
+
if (!msg.ok && this._pendingInit) {
|
|
588
|
+
const p = this._pendingInit;
|
|
589
|
+
this._pendingInit = null;
|
|
590
|
+
p.reject(new Error(msg.error));
|
|
591
|
+
}
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
this._pending.delete(msg.id);
|
|
595
|
+
if (!msg.ok) {
|
|
596
|
+
entry.reject(new Error(msg.error));
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
try {
|
|
600
|
+
const linesDiff = (0,_wire_js__WEBPACK_IMPORTED_MODULE_0__.w)(msg.result);
|
|
601
|
+
const result = _adaptLinesDiff(linesDiff, entry.original, entry.modified, entry.originalLines, entry.modifiedLines);
|
|
602
|
+
entry.resolve(result);
|
|
603
|
+
}
|
|
604
|
+
catch (err) {
|
|
605
|
+
entry.reject(err instanceof Error ? err : new Error(String(err)));
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
_failAll(err) {
|
|
609
|
+
for (const p of this._pending.values())
|
|
610
|
+
p.reject(err);
|
|
611
|
+
this._pending.clear();
|
|
612
|
+
if (this._pendingInit) {
|
|
613
|
+
this._pendingInit.reject(err);
|
|
614
|
+
this._pendingInit = null;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
//# sourceMappingURL=index.js.map
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
/***/ }
|
|
624
|
+
|
|
625
|
+
}]);
|
|
626
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVuZG9ycy1ub2RlX21vZHVsZXNfdnNjb2RlX2RpZmZfZGlzdF9pbmRleF9qcy5tYWluLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDNk47QUFDMUs7O0FBRW5EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsZUFBZSxNQUFNLGNBQWM7QUFDckQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFdBQVcsSUFBSSw2QkFBNkI7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5QkFBeUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsWUFBWSxLQUFLLFVBQVU7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsdUNBQVc7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFLHVDQUFXO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIsb0RBQW9EO0FBQ2pGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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LDJDQUFlO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRXNiO0FBQ3RiIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vamRlcm9ib3QtaWRlLWludGVyZmFjZS8uL25vZGVfbW9kdWxlcy9AdnNjb2RlL2RpZmYvZGlzdC9pbmRleC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXG4gKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbmltcG9ydCB7IE8gYXMgT2Zmc2V0UmFuZ2UsIGkgYXMgaW5pdFdhc20sIGcgYXMgZ2V0V2FzbSwgRCBhcyBEZWZhdWx0TGluZXNEaWZmQ29tcHV0ZXIsIFIgYXMgUmFuZ2VNYXBwaW5nLCBhIGFzIFJhbmdlLCBiIGFzIERldGFpbGVkTGluZVJhbmdlTWFwcGluZywgTCBhcyBMaW5lUmFuZ2UsIGMgYXMgTGluZXNEaWZmLCB3IGFzIHdpcmVUb0xpbmVzRGlmZiB9IGZyb20gJy4vd2lyZS5qcyc7XG5leHBvcnQgeyBkIGFzIF9MaW5lUmFuZ2VNYXBwaW5nIH0gZnJvbSAnLi93aXJlLmpzJztcblxuLyoqXG4gKiBBIHBhaXIgb2YgcmFuZ2VzLCBvbmUgaW4gYG9yaWdpbmFsYCwgb25lIGluIGBtb2RpZmllZGAuXG4gKi9cbmNsYXNzIE9mZnNldFJhbmdlTWFwcGluZyB7XG4gICAgb3JpZ2luYWw7XG4gICAgbW9kaWZpZWQ7XG4gICAgY29uc3RydWN0b3Iob3JpZ2luYWwsIG1vZGlmaWVkKSB7XG4gICAgICAgIHRoaXMub3JpZ2luYWwgPSBvcmlnaW5hbDtcbiAgICAgICAgdGhpcy5tb2RpZmllZCA9IG1vZGlmaWVkO1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGAke3RoaXMub3JpZ2luYWx9IDwtPiAke3RoaXMubW9kaWZpZWR9YDtcbiAgICB9XG59XG5cbi8qKlxuICogQSBzaW5nbGUgYXRvbWljIHJlcGxhY2VtZW50OiByZXBsYWNlIGByYW5nZWAgaW4gdGhlIGlucHV0IHdpdGggYG5ld1RleHRgLlxuICovXG5jbGFzcyBTdHJpbmdSZXBsYWNlbWVudCB7XG4gICAgcmFuZ2U7XG4gICAgbmV3VGV4dDtcbiAgICBjb25zdHJ1Y3RvcihyYW5nZSwgbmV3VGV4dCkge1xuICAgICAgICB0aGlzLnJhbmdlID0gcmFuZ2U7XG4gICAgICAgIHRoaXMubmV3VGV4dCA9IG5ld1RleHQ7XG4gICAgfVxuICAgIGdldCBpc0VtcHR5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yYW5nZS5pc0VtcHR5ICYmIHRoaXMubmV3VGV4dC5sZW5ndGggPT09IDA7XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5yYW5nZX0tPiR7SlNPTi5zdHJpbmdpZnkodGhpcy5uZXdUZXh0KX1gO1xuICAgIH1cbn1cbi8qKlxuICogQSBzZXQgb2YgcmVwbGFjZW1lbnRzIGFwcGxpZWQgaW4gcGFyYWxsZWwgdG8gb25lIGlucHV0IHN0cmluZy5cbiAqXG4gKiBJbnZhcmlhbnRzOlxuICogIC0gcmVwbGFjZW1lbnRzIGFyZSBzb3J0ZWQgYnkgYHJhbmdlLnN0YXJ0YFxuICogIC0gcmVwbGFjZW1lbnRzIGRvIG5vdCBvdmVybGFwICh0b3VjaGluZyBpcyBhbGxvd2VkKVxuICogIC0gYWxsIHJhbmdlcyBsaXZlIGluIHRoZSBzYW1lIGNvb3JkaW5hdGUgc3BhY2UgKHRoZSBpbnB1dCBwYXNzZWQgdG8gYGFwcGx5YClcbiAqL1xuY2xhc3MgU3RyaW5nRWRpdCB7XG4gICAgcmVwbGFjZW1lbnRzO1xuICAgIHN0YXRpYyBlbXB0eSA9IG5ldyBTdHJpbmdFZGl0KFtdKTtcbiAgICBzdGF0aWMgc2luZ2xlKHJlcGxhY2VtZW50KSB7XG4gICAgICAgIHJldHVybiBuZXcgU3RyaW5nRWRpdChbcmVwbGFjZW1lbnRdKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVmFsaWRhdGVzIHRoYXQgcmVwbGFjZW1lbnRzIGFyZSBzb3J0ZWQgYW5kIG5vbi1vdmVybGFwcGluZy5cbiAgICAgKi9cbiAgICBzdGF0aWMgb2YocmVwbGFjZW1lbnRzKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgcmVwbGFjZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBwcmV2ID0gcmVwbGFjZW1lbnRzW2kgLSAxXTtcbiAgICAgICAgICAgIGNvbnN0IGN1ciA9IHJlcGxhY2VtZW50c1tpXTtcbiAgICAgICAgICAgIGlmIChwcmV2LnJhbmdlLmVuZEV4Y2x1c2l2ZSA+IGN1ci5yYW5nZS5zdGFydCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU3RyaW5nRWRpdC5vZjogcmVwbGFjZW1lbnRzIG11c3QgYmUgc29ydGVkIGFuZCBub24tb3ZlcmxhcHBpbmcgKGAgK1xuICAgICAgICAgICAgICAgICAgICBgJHtwcmV2LnJhbmdlfSB2cyAke2N1ci5yYW5nZX0pYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBTdHJpbmdFZGl0KHJlcGxhY2VtZW50cyk7XG4gICAgfVxuICAgIGNvbnN0cnVjdG9yKHJlcGxhY2VtZW50cykge1xuICAgICAgICB0aGlzLnJlcGxhY2VtZW50cyA9IHJlcGxhY2VtZW50cztcbiAgICB9XG4gICAgZ2V0IGlzRW1wdHkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlcGxhY2VtZW50cy5sZW5ndGggPT09IDA7XG4gICAgfVxuICAgIGFwcGx5KHRleHQpIHtcbiAgICAgICAgaWYgKHRoaXMucmVwbGFjZW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFydHMgPSBbXTtcbiAgICAgICAgbGV0IGN1cnNvciA9IDA7XG4gICAgICAgIGZvciAoY29uc3QgciBvZiB0aGlzLnJlcGxhY2VtZW50cykge1xuICAgICAgICAgICAgcGFydHMucHVzaCh0ZXh0LnN1YnN0cmluZyhjdXJzb3IsIHIucmFuZ2Uuc3RhcnQpKTtcbiAgICAgICAgICAgIHBhcnRzLnB1c2goci5uZXdUZXh0KTtcbiAgICAgICAgICAgIGN1cnNvciA9IHIucmFuZ2UuZW5kRXhjbHVzaXZlO1xuICAgICAgICB9XG4gICAgICAgIHBhcnRzLnB1c2godGV4dC5zdWJzdHJpbmcoY3Vyc29yKSk7XG4gICAgICAgIHJldHVybiBwYXJ0cy5qb2luKCcnKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBlZGl0IGBFYCBzdWNoIHRoYXQgYEUuYXBwbHkodGhpcy5hcHBseShpbnB1dCkpID09PSBpbnB1dGAuXG4gICAgICovXG4gICAgaW52ZXJzZShpbnB1dCkge1xuICAgICAgICBjb25zdCBvdXQgPSBbXTtcbiAgICAgICAgbGV0IGRlbHRhID0gMDtcbiAgICAgICAgZm9yIChjb25zdCByIG9mIHRoaXMucmVwbGFjZW1lbnRzKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdTdGFydCA9IHIucmFuZ2Uuc3RhcnQgKyBkZWx0YTtcbiAgICAgICAgICAgIGNvbnN0IG5ld0VuZCA9IG5ld1N0YXJ0ICsgci5uZXdUZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IG9sZFRleHQgPSBpbnB1dC5zdWJzdHJpbmcoci5yYW5nZS5zdGFydCwgci5yYW5nZS5lbmRFeGNsdXNpdmUpO1xuICAgICAgICAgICAgb3V0LnB1c2gobmV3IFN0cmluZ1JlcGxhY2VtZW50KG5ldyBPZmZzZXRSYW5nZShuZXdTdGFydCwgbmV3RW5kKSwgb2xkVGV4dCkpO1xuICAgICAgICAgICAgZGVsdGEgKz0gci5uZXdUZXh0Lmxlbmd0aCAtIHIucmFuZ2UubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU3RyaW5nRWRpdChvdXQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBKb2lucyB0b3VjaGluZyByZXBsYWNlbWVudHMgYW5kIGRyb3BzIG5vLW9wcy5cbiAgICAgKi9cbiAgICBub3JtYWxpemUoKSB7XG4gICAgICAgIGNvbnN0IG91dCA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHIgb2YgdGhpcy5yZXBsYWNlbWVudHMpIHtcbiAgICAgICAgICAgIGlmIChyLmlzRW1wdHkpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHByZXYgPSBvdXRbb3V0Lmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgaWYgKHByZXYgJiYgcHJldi5yYW5nZS5lbmRFeGNsdXNpdmUgPT09IHIucmFuZ2Uuc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBvdXRbb3V0Lmxlbmd0aCAtIDFdID0gbmV3IFN0cmluZ1JlcGxhY2VtZW50KG5ldyBPZmZzZXRSYW5nZShwcmV2LnJhbmdlLnN0YXJ0LCByLnJhbmdlLmVuZEV4Y2x1c2l2ZSksIHByZXYubmV3VGV4dCArIHIubmV3VGV4dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBvdXQucHVzaChyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFN0cmluZ0VkaXQob3V0KTtcbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgU3RyaW5nRWRpdFske3RoaXMucmVwbGFjZW1lbnRzLm1hcChyID0+IHIudG9TdHJpbmcoKSkuam9pbignLCAnKX1dYDtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gYXRvbWljIHJlcGxhY2VtZW50IGNhcnJ5aW5nIHVzZXItZGVmaW5lZCBtZXRhZGF0YS5cbiAqL1xuY2xhc3MgQW5ub3RhdGVkU3RyaW5nUmVwbGFjZW1lbnQge1xuICAgIHJhbmdlO1xuICAgIG5ld1RleHQ7XG4gICAgZGF0YTtcbiAgICBjb25zdHJ1Y3RvcihyYW5nZSwgbmV3VGV4dCwgZGF0YSkge1xuICAgICAgICB0aGlzLnJhbmdlID0gcmFuZ2U7XG4gICAgICAgIHRoaXMubmV3VGV4dCA9IG5ld1RleHQ7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxuICAgIGdldCBpc0VtcHR5KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yYW5nZS5pc0VtcHR5ICYmIHRoaXMubmV3VGV4dC5sZW5ndGggPT09IDA7XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5yYW5nZX0tPiR7SlNPTi5zdHJpbmdpZnkodGhpcy5uZXdUZXh0KX0jJHt0aGlzLmRhdGF9YDtcbiAgICB9XG59XG4vKipcbiAqIEEgc2V0IG9mIGFubm90YXRlZCByZXBsYWNlbWVudHMgYXBwbGllZCBpbiBwYXJhbGxlbC5cbiAqXG4gKiBJbnZhcmlhbnRzOiBzYW1lIGFzIGBTdHJpbmdFZGl0YCAoc29ydGVkIGJ5IGByYW5nZS5zdGFydGAsIG5vbi1vdmVybGFwcGluZyxcbiAqIHNoYXJlZCBjb29yZGluYXRlIHNwYWNlKS5cbiAqL1xuY2xhc3MgQW5ub3RhdGVkU3RyaW5nRWRpdCB7XG4gICAgcmVwbGFjZW1lbnRzO1xuICAgIHN0YXRpYyBlbXB0eSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBBbm5vdGF0ZWRTdHJpbmdFZGl0KFtdKTtcbiAgICB9XG4gICAgc3RhdGljIHNpbmdsZShyZXBsYWNlbWVudCkge1xuICAgICAgICByZXR1cm4gbmV3IEFubm90YXRlZFN0cmluZ0VkaXQoW3JlcGxhY2VtZW50XSk7XG4gICAgfVxuICAgIHN0YXRpYyBvZihyZXBsYWNlbWVudHMpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCByZXBsYWNlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXYgPSByZXBsYWNlbWVudHNbaSAtIDFdO1xuICAgICAgICAgICAgY29uc3QgY3VyID0gcmVwbGFjZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKHByZXYucmFuZ2UuZW5kRXhjbHVzaXZlID4gY3VyLnJhbmdlLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBbm5vdGF0ZWRTdHJpbmdFZGl0Lm9mOiByZXBsYWNlbWVudHMgbXVzdCBiZSBzb3J0ZWQgYW5kIG5vbi1vdmVybGFwcGluZyAoYCArXG4gICAgICAgICAgICAgICAgICAgIGAke3ByZXYucmFuZ2V9IHZzICR7Y3VyLnJhbmdlfSlgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IEFubm90YXRlZFN0cmluZ0VkaXQocmVwbGFjZW1lbnRzKTtcbiAgICB9XG4gICAgY29uc3RydWN0b3IocmVwbGFjZW1lbnRzKSB7XG4gICAgICAgIHRoaXMucmVwbGFjZW1lbnRzID0gcmVwbGFjZW1lbnRzO1xuICAgIH1cbiAgICBnZXQgaXNFbXB0eSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVwbGFjZW1lbnRzLmxlbmd0aCA9PT0gMDtcbiAgICB9XG4gICAgYXBwbHkodGV4dCkge1xuICAgICAgICBpZiAodGhpcy5yZXBsYWNlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwYXJ0cyA9IFtdO1xuICAgICAgICBsZXQgY3Vyc29yID0gMDtcbiAgICAgICAgZm9yIChjb25zdCByIG9mIHRoaXMucmVwbGFjZW1lbnRzKSB7XG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHRleHQuc3Vic3RyaW5nKGN1cnNvciwgci5yYW5nZS5zdGFydCkpO1xuICAgICAgICAgICAgcGFydHMucHVzaChyLm5ld1RleHQpO1xuICAgICAgICAgICAgY3Vyc29yID0gci5yYW5nZS5lbmRFeGNsdXNpdmU7XG4gICAgICAgIH1cbiAgICAgICAgcGFydHMucHVzaCh0ZXh0LnN1YnN0cmluZyhjdXJzb3IpKTtcbiAgICAgICAgcmV0dXJuIHBhcnRzLmpvaW4oJycpO1xuICAgIH1cbiAgICBpbnZlcnNlKGlucHV0LCBpbnZlcnREYXRhKSB7XG4gICAgICAgIGNvbnN0IG91dCA9IFtdO1xuICAgICAgICBsZXQgZGVsdGEgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IHIgb2YgdGhpcy5yZXBsYWNlbWVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1N0YXJ0ID0gci5yYW5nZS5zdGFydCArIGRlbHRhO1xuICAgICAgICAgICAgY29uc3QgbmV3RW5kID0gbmV3U3RhcnQgKyByLm5ld1RleHQubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3Qgb2xkVGV4dCA9IGlucHV0LnN1YnN0cmluZyhyLnJhbmdlLnN0YXJ0LCByLnJhbmdlLmVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgICAgICBvdXQucHVzaChuZXcgQW5ub3RhdGVkU3RyaW5nUmVwbGFjZW1lbnQobmV3IE9mZnNldFJhbmdlKG5ld1N0YXJ0LCBuZXdFbmQpLCBvbGRUZXh0LCBpbnZlcnREYXRhKHIuZGF0YSkpKTtcbiAgICAgICAgICAgIGRlbHRhICs9IHIubmV3VGV4dC5sZW5ndGggLSByLnJhbmdlLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IEFubm90YXRlZFN0cmluZ0VkaXQob3V0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSm9pbnMgdG91Y2hpbmcgcmVwbGFjZW1lbnRzIHdoZW4gdGhlaXIgYW5ub3RhdGlvbnMgam9pbi4gRHJvcHMgbm8tb3BzLlxuICAgICAqL1xuICAgIG5vcm1hbGl6ZSgpIHtcbiAgICAgICAgY29uc3Qgb3V0ID0gW107XG4gICAgICAgIGZvciAoY29uc3QgciBvZiB0aGlzLnJlcGxhY2VtZW50cykge1xuICAgICAgICAgICAgaWYgKHIuaXNFbXB0eSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcHJldiA9IG91dFtvdXQubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICBpZiAocHJldiAmJiBwcmV2LnJhbmdlLmVuZEV4Y2x1c2l2ZSA9PT0gci5yYW5nZS5zdGFydCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGpvaW5lZCA9IHByZXYuZGF0YS5qb2luKHIuZGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKGpvaW5lZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIG91dFtvdXQubGVuZ3RoIC0gMV0gPSBuZXcgQW5ub3RhdGVkU3RyaW5nUmVwbGFjZW1lbnQobmV3IE9mZnNldFJhbmdlKHByZXYucmFuZ2Uuc3RhcnQsIHIucmFuZ2UuZW5kRXhjbHVzaXZlKSwgcHJldi5uZXdUZXh0ICsgci5uZXdUZXh0LCBqb2luZWQpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvdXQucHVzaChyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IEFubm90YXRlZFN0cmluZ0VkaXQob3V0KTtcbiAgICB9XG4gICAgbWFwRGF0YShmKSB7XG4gICAgICAgIHJldHVybiBuZXcgQW5ub3RhdGVkU3RyaW5nRWRpdCh0aGlzLnJlcGxhY2VtZW50cy5tYXAociA9PiBuZXcgQW5ub3RhdGVkU3RyaW5nUmVwbGFjZW1lbnQoci5yYW5nZSwgci5uZXdUZXh0LCBmKHIuZGF0YSkpKSk7XG4gICAgfVxuICAgIHN0cmlwRGF0YSgpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZ0VkaXQub2YodGhpcy5yZXBsYWNlbWVudHMubWFwKHIgPT4gbmV3IFN0cmluZ1JlcGxhY2VtZW50KHIucmFuZ2UsIHIubmV3VGV4dCkpKTtcbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgQW5ub3RhdGVkU3RyaW5nRWRpdFske3RoaXMucmVwbGFjZW1lbnRzLm1hcChyID0+IHIudG9TdHJpbmcoKSkuam9pbignLCAnKX1dYDtcbiAgICB9XG59XG4vKipcbiAqIERpZmYgcmVzdWx0IGFubm90YXRpb24uXG4gKlxuICogQ2FycmllcyBmbGFncyBkZXNjcmliaW5nIHRoZSBuYXR1cmUgb2YgdGhlIHJlcGxhY2VtZW50LiBGb3Igbm93IG9ubHlcbiAqIGBpc0Zvcm1hdHRpbmdDaGFuZ2VgIGlzIGV4cG9zZWQ7IG1vcmUgZmxhZ3MgKGUuZy4gbW92ZSBzb3VyY2UvdGFyZ2V0LFxuICogc2VtYW50aWMgY2F0ZWdvcnkpIGNhbiBiZSBhZGRlZCBsYXRlci5cbiAqL1xuY2xhc3MgRGlmZkFubm90YXRpb24ge1xuICAgIGlzRm9ybWF0dGluZ0NoYW5nZTtcbiAgICBzdGF0aWMgY2hhbmdlID0gbmV3IERpZmZBbm5vdGF0aW9uKGZhbHNlKTtcbiAgICBzdGF0aWMgZm9ybWF0dGluZyA9IG5ldyBEaWZmQW5ub3RhdGlvbih0cnVlKTtcbiAgICBjb25zdHJ1Y3RvcihcbiAgICAvKiogV2hldGhlciB0aGUgcmVwbGFjZW1lbnQgaXMgcHVyZWx5IGEgZm9ybWF0dGluZyBjaGFuZ2UgKHdoaXRlc3BhY2UsIGluZGVudGF0aW9uLCBldGMuKS4gKi9cbiAgICBpc0Zvcm1hdHRpbmdDaGFuZ2UpIHtcbiAgICAgICAgdGhpcy5pc0Zvcm1hdHRpbmdDaGFuZ2UgPSBpc0Zvcm1hdHRpbmdDaGFuZ2U7XG4gICAgfVxuICAgIGpvaW4ob3RoZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNGb3JtYXR0aW5nQ2hhbmdlICE9PSBvdGhlci5pc0Zvcm1hdHRpbmdDaGFuZ2UpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc0Zvcm1hdHRpbmdDaGFuZ2UgPyAnZm9ybWF0dGluZycgOiAnY2hhbmdlJztcbiAgICB9XG59XG5cbi8qKlxuICogQSBibG9jayBvZiB0ZXh0IHRoYXQgd2FzIG1vdmVkIGJldHdlZW4gdHdvIGxvY2F0aW9ucy5cbiAqXG4gKiBgcmFuZ2VgIGxvY2F0ZXMgdGhlIGJsb2NrIGluIGBvcmlnaW5hbGAgYW5kIGluIGBtb2RpZmllZGAgKG9mZnNldHMgaW4gdGhlXG4gKiByZXNwZWN0aXZlIGZ1bGwgdGV4dHMpLiBgaW5uZXJFZGl0YCBkZXNjcmliZXMgdGhlIGNoYW5nZXMgaW5zaWRlIHRoZSBtb3ZlZFxuICogYmxvY2ssIHdpdGggb2Zmc2V0cyBsb2NhbCB0byB0aGUgc2xpY2UgKGkuZS4gYDBgIGlzIHRoZSBzdGFydCBvZiB0aGUgc2xpY2UpLlxuICovXG5jbGFzcyBNb3ZlIHtcbiAgICByYW5nZTtcbiAgICBpbm5lckVkaXQ7XG4gICAgY29uc3RydWN0b3IocmFuZ2UsIGlubmVyRWRpdCkge1xuICAgICAgICB0aGlzLnJhbmdlID0gcmFuZ2U7XG4gICAgICAgIHRoaXMuaW5uZXJFZGl0ID0gaW5uZXJFZGl0O1xuICAgIH1cbiAgICB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIGBNb3ZlICR7dGhpcy5yYW5nZX1gICsgKHRoaXMuaW5uZXJFZGl0LmlzRW1wdHkgPyAnJyA6IGAgKCR7dGhpcy5pbm5lckVkaXR9KWApO1xuICAgIH1cbn1cblxuLyoqXG4gKiBPdXRwdXQgb2YgYSBkaWZmIGNvbXB1dGF0aW9uLlxuICovXG5jbGFzcyBEaWZmUmVzdWx0IHtcbiAgICBlZGl0cztcbiAgICBtb3ZlcztcbiAgICBoaXRUaW1lb3V0O1xuICAgIGNvbnN0cnVjdG9yKFxuICAgIC8qKlxuICAgICAqIFBhcmFsbGVsIHNldCBvZiByZXBsYWNlbWVudHMgdHJhbnNmb3JtaW5nIGBvcmlnaW5hbGAgaW50byBgbW9kaWZpZWRgLFxuICAgICAqIGV4Y2x1ZGluZyBhbnkgcmVwbGFjZW1lbnRzIHRoYXQgYXJlIHBhcnQgb2YgYSBgTW92ZWAuXG4gICAgICpcbiAgICAgKiBXaGVuIG5vIG1vdmVzIGFyZSBjb21wdXRlZDogYGVkaXRzLmFwcGx5KG9yaWdpbmFsKSA9PT0gbW9kaWZpZWRgLlxuICAgICAqL1xuICAgIGVkaXRzLCBcbiAgICAvKipcbiAgICAgKiBEZXRlY3RlZCB0ZXh0IG1vdmVzLiBFbXB0eSB1bmxlc3MgYERpZmZPcHRpb25zLmNvbXB1dGVNb3Zlc2AgaXMgc2V0LlxuICAgICAqL1xuICAgIG1vdmVzLCBcbiAgICAvKipcbiAgICAgKiBgdHJ1ZWAgaWYgdGhlIGFsZ29yaXRobSBhYm9ydGVkIGJlY2F1c2Ugb2YgYG1heENvbXB1dGF0aW9uVGltZU1zYC5cbiAgICAgKiBUaGUgcmVzdWx0IGlzIHN0aWxsIHZhbGlkIGJ1dCBtYXkgYmUgY29hcnNlciB0aGFuIGlkZWFsLlxuICAgICAqL1xuICAgIGhpdFRpbWVvdXQpIHtcbiAgICAgICAgdGhpcy5lZGl0cyA9IGVkaXRzO1xuICAgICAgICB0aGlzLm1vdmVzID0gbW92ZXM7XG4gICAgICAgIHRoaXMuaGl0VGltZW91dCA9IGhpdFRpbWVvdXQ7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVEaWZmQ29tcHV0ZXIob3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKG9wdGlvbnMudXNlV2FzbSkge1xuICAgICAgICBhd2FpdCBpbml0V2FzbSgpO1xuICAgICAgICByZXR1cm4gbmV3IF9XYXNtRGlmZkNvbXB1dGVyKG9wdGlvbnMuYWxnb3JpdGhtKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBfVHNEaWZmQ29tcHV0ZXIob3B0aW9ucy5hbGdvcml0aG0pO1xufVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFMtYmFja2VkIGNvbXB1dGVyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5jbGFzcyBfVHNEaWZmQ29tcHV0ZXIge1xuICAgIF9hbGdvcml0aG07XG4gICAgX2ltcGwgPSBuZXcgRGVmYXVsdExpbmVzRGlmZkNvbXB1dGVyKCk7XG4gICAgY29uc3RydWN0b3IoX2FsZ29yaXRobSkge1xuICAgICAgICB0aGlzLl9hbGdvcml0aG0gPSBfYWxnb3JpdGhtO1xuICAgIH1cbiAgICBjb21wdXRlRGlmZihvcmlnaW5hbCwgbW9kaWZpZWQsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxMaW5lcyA9IG9yaWdpbmFsLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgY29uc3QgbW9kaWZpZWRMaW5lcyA9IG1vZGlmaWVkLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgY29uc3QgaW50ZXJuYWwgPSB7XG4gICAgICAgICAgICBtYXhDb21wdXRhdGlvblRpbWVNczogb3B0aW9ucz8ubWF4Q29tcHV0YXRpb25UaW1lTXMgPz8gMCxcbiAgICAgICAgICAgIGlnbm9yZVRyaW1XaGl0ZXNwYWNlOiBvcHRpb25zPy5pZ25vcmVUcmltV2hpdGVzcGFjZSA/PyBmYWxzZSxcbiAgICAgICAgICAgIGNvbXB1dGVNb3Zlczogb3B0aW9ucz8uY29tcHV0ZU1vdmVzID8/IGZhbHNlLFxuICAgICAgICAgICAgZXh0ZW5kVG9TdWJ3b3Jkczogb3B0aW9ucz8uZXh0ZW5kVG9TdWJ3b3JkcyA/PyBmYWxzZSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgbGluZXNEaWZmID0gdGhpcy5faW1wbC5jb21wdXRlRGlmZihvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzLCBpbnRlcm5hbCk7XG4gICAgICAgIHZvaWQgdGhpcy5fYWxnb3JpdGhtOyAvLyBjdXJyZW50bHkgYSBoaW50OyBhdXRvLXNlbGVjdGlvbiBsaXZlcyBpbnNpZGUgRGVmYXVsdExpbmVzRGlmZkNvbXB1dGVyXG4gICAgICAgIHJldHVybiBfYWRhcHRMaW5lc0RpZmYobGluZXNEaWZmLCBvcmlnaW5hbCwgbW9kaWZpZWQsIG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMpO1xuICAgIH1cbn1cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFdBU00tYmFja2VkIGNvbXB1dGVyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5jbGFzcyBfV2FzbURpZmZDb21wdXRlciB7XG4gICAgX2FsZ29yaXRobTtcbiAgICBjb25zdHJ1Y3RvcihfYWxnb3JpdGhtKSB7XG4gICAgICAgIHRoaXMuX2FsZ29yaXRobSA9IF9hbGdvcml0aG07XG4gICAgfVxuICAgIGNvbXB1dGVEaWZmKG9yaWdpbmFsLCBtb2RpZmllZCwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBvcmlnaW5hbExpbmVzID0gb3JpZ2luYWwuc3BsaXQoJ1xcbicpO1xuICAgICAgICBjb25zdCBtb2RpZmllZExpbmVzID0gbW9kaWZpZWQuc3BsaXQoJ1xcbicpO1xuICAgICAgICBjb25zdCB3YXNtT3B0aW9ucyA9IHt9O1xuICAgICAgICBpZiAob3B0aW9ucz8ubWF4Q29tcHV0YXRpb25UaW1lTXMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHdhc21PcHRpb25zLm1heENvbXB1dGF0aW9uVGltZU1zID0gb3B0aW9ucy5tYXhDb21wdXRhdGlvblRpbWVNcztcbiAgICAgICAgaWYgKG9wdGlvbnM/Lmlnbm9yZVRyaW1XaGl0ZXNwYWNlICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB3YXNtT3B0aW9ucy5pZ25vcmVUcmltV2hpdGVzcGFjZSA9IG9wdGlvbnMuaWdub3JlVHJpbVdoaXRlc3BhY2U7XG4gICAgICAgIGlmIChvcHRpb25zPy5jb21wdXRlTW92ZXMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgIHdhc21PcHRpb25zLmNvbXB1dGVNb3ZlcyA9IG9wdGlvbnMuY29tcHV0ZU1vdmVzO1xuICAgICAgICBpZiAob3B0aW9ucz8uZXh0ZW5kVG9TdWJ3b3JkcyAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgd2FzbU9wdGlvbnMuZXh0ZW5kVG9TdWJ3b3JkcyA9IG9wdGlvbnMuZXh0ZW5kVG9TdWJ3b3JkcztcbiAgICAgICAgY29uc3Qgd2FzbSA9IGdldFdhc20oKTtcbiAgICAgICAgY29uc3Qgd2FzbVJlc3VsdCA9IHdhc20uY29tcHV0ZURpZmZMaW5lcyhvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzLCB3YXNtT3B0aW9ucyk7XG4gICAgICAgIHZvaWQgdGhpcy5fYWxnb3JpdGhtO1xuICAgICAgICBjb25zdCBsaW5lc0RpZmYgPSBfd2FzbVRvTGluZXNEaWZmKHdhc21SZXN1bHQpO1xuICAgICAgICByZXR1cm4gX2FkYXB0TGluZXNEaWZmKGxpbmVzRGlmZiwgb3JpZ2luYWwsIG1vZGlmaWVkLCBvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzKTtcbiAgICB9XG59XG5mdW5jdGlvbiBfd2FzbVRvTGluZXNEaWZmKHdhc21SZXN1bHQpIHtcbiAgICBjb25zdCBjaGFuZ2VzID0gd2FzbVJlc3VsdC5jaGFuZ2VzLm1hcCgoYykgPT4ge1xuICAgICAgICBjb25zdCBpbm5lciA9IGMuaW5uZXJDaGFuZ2VzPy5tYXAoKGljKSA9PiBuZXcgUmFuZ2VNYXBwaW5nKG5ldyBSYW5nZShpYy5vcmlnaW5hbFN0YXJ0TGluZSwgaWMub3JpZ2luYWxTdGFydENvbHVtbiwgaWMub3JpZ2luYWxFbmRMaW5lLCBpYy5vcmlnaW5hbEVuZENvbHVtbiksIG5ldyBSYW5nZShpYy5tb2RpZmllZFN0YXJ0TGluZSwgaWMubW9kaWZpZWRTdGFydENvbHVtbiwgaWMubW9kaWZpZWRFbmRMaW5lLCBpYy5tb2RpZmllZEVuZENvbHVtbikpKTtcbiAgICAgICAgcmV0dXJuIG5ldyBEZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcobmV3IExpbmVSYW5nZShjLm9yaWdpbmFsLnN0YXJ0TGluZU51bWJlciwgYy5vcmlnaW5hbC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlKSwgbmV3IExpbmVSYW5nZShjLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlciwgYy5tb2RpZmllZC5lbmRMaW5lTnVtYmVyRXhjbHVzaXZlKSwgaW5uZXIpO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgTGluZXNEaWZmKGNoYW5nZXMsIFtdLCB3YXNtUmVzdWx0LmhpdFRpbWVvdXQpO1xufVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gTGluZXNEaWZmIC0+IERpZmZSZXN1bHQgYWRhcHRlclxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLyoqIEBpbnRlcm5hbCDigJQgZXhwb3J0ZWQgZm9yIHRoZSB3b3JrZXItc2lkZSBjbGllbnQuICovXG5mdW5jdGlvbiBfYWRhcHRMaW5lc0RpZmYobGluZXNEaWZmLCBvcmlnaW5hbCwgbW9kaWZpZWQsIG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMpIHtcbiAgICBjb25zdCBvcmlnaW5hbExpbmVTdGFydHMgPSBfY29tcHV0ZUxpbmVTdGFydHMob3JpZ2luYWxMaW5lcyk7XG4gICAgY29uc3QgbW9kaWZpZWRMaW5lU3RhcnRzID0gX2NvbXB1dGVMaW5lU3RhcnRzKG1vZGlmaWVkTGluZXMpO1xuICAgIGNvbnN0IHJlcGxhY2VtZW50cyA9IFtdO1xuICAgIGZvciAoY29uc3QgY2hhbmdlIG9mIGxpbmVzRGlmZi5jaGFuZ2VzKSB7XG4gICAgICAgIF9hcHBlbmRDaGFuZ2VSZXBsYWNlbWVudHMoY2hhbmdlLCBvcmlnaW5hbCwgbW9kaWZpZWQsIG9yaWdpbmFsTGluZXMsIG1vZGlmaWVkTGluZXMsIG9yaWdpbmFsTGluZVN0YXJ0cywgbW9kaWZpZWRMaW5lU3RhcnRzLCByZXBsYWNlbWVudHMpO1xuICAgIH1cbiAgICBjb25zdCBlZGl0cyA9IEFubm90YXRlZFN0cmluZ0VkaXQub2YocmVwbGFjZW1lbnRzKTtcbiAgICBjb25zdCBtb3ZlcyA9IGxpbmVzRGlmZi5tb3Zlcy5tYXAobSA9PiBfYWRhcHRNb3ZlKG0sIG9yaWdpbmFsLCBtb2RpZmllZCwgb3JpZ2luYWxMaW5lcywgbW9kaWZpZWRMaW5lcywgb3JpZ2luYWxMaW5lU3RhcnRzLCBtb2RpZmllZExpbmVTdGFydHMpKTtcbiAgICByZXR1cm4gbmV3IERpZmZSZXN1bHQoZWRpdHMsIG1vdmVzLCBsaW5lc0RpZmYuaGl0VGltZW91dCk7XG59XG5mdW5jdGlvbiBfYXBwZW5kQ2hhbmdlUmVwbGFjZW1lbnRzKGNoYW5nZSwgb3JpZ2luYWwsIG1vZGlmaWVkLCBvcmlnaW5hbExpbmVzLCBtb2RpZmllZExpbmVzLCBvcmlnaW5hbExpbmVTdGFydHMsIG1vZGlmaWVkTGluZVN0YXJ0cywgb3V0KSB7XG4gICAgaWYgKGNoYW5nZS5pbm5lckNoYW5nZXMgJiYgY2hhbmdlLmlubmVyQ2hhbmdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvciAoY29uc3QgaWMgb2YgY2hhbmdlLmlubmVyQ2hhbmdlcykge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ1JhbmdlID0gX3JhbmdlVG9PZmZzZXRSYW5nZShpYy5vcmlnaW5hbFJhbmdlLCBvcmlnaW5hbCwgb3JpZ2luYWxMaW5lcywgb3JpZ2luYWxMaW5lU3RhcnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG1vZFJhbmdlID0gX3JhbmdlVG9PZmZzZXRSYW5nZShpYy5tb2RpZmllZFJhbmdlLCBtb2RpZmllZCwgbW9kaWZpZWRMaW5lcywgbW9kaWZpZWRMaW5lU3RhcnRzKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1RleHQgPSBtb2RpZmllZC5zdWJzdHJpbmcobW9kUmFuZ2Uuc3RhcnQsIG1vZFJhbmdlLmVuZEV4Y2x1c2l2ZSk7XG4gICAgICAgICAgICBvdXQucHVzaChuZXcgQW5ub3RhdGVkU3RyaW5nUmVwbGFjZW1lbnQob3JpZ1JhbmdlLCBuZXdUZXh0LCBEaWZmQW5ub3RhdGlvbi5jaGFuZ2UpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIEZhbGxiYWNrOiBubyBpbm5lciBkZXRhaWwg4oCUIHJlcGxhY2UgdGhlIHdob2xlIGxpbmUgcmFuZ2UuXG4gICAgY29uc3Qgb3JpZ1JhbmdlID0gX2xpbmVSYW5nZVRvT2Zmc2V0UmFuZ2UoY2hhbmdlLm9yaWdpbmFsLnN0YXJ0TGluZU51bWJlciwgY2hhbmdlLm9yaWdpbmFsLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIG9yaWdpbmFsLCBvcmlnaW5hbExpbmVTdGFydHMpO1xuICAgIGNvbnN0IG1vZFJhbmdlID0gX2xpbmVSYW5nZVRvT2Zmc2V0UmFuZ2UoY2hhbmdlLm1vZGlmaWVkLnN0YXJ0TGluZU51bWJlciwgY2hhbmdlLm1vZGlmaWVkLmVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIG1vZGlmaWVkLCBtb2RpZmllZExpbmVTdGFydHMpO1xuICAgIGNvbnN0IG5ld1RleHQgPSBtb2RpZmllZC5zdWJzdHJpbmcobW9kUmFuZ2Uuc3RhcnQsIG1vZFJhbmdlLmVuZEV4Y2x1c2l2ZSk7XG4gICAgb3V0LnB1c2gobmV3IEFubm90YXRlZFN0cmluZ1JlcGxhY2VtZW50KG9yaWdSYW5nZSwgbmV3VGV4dCwgRGlmZkFubm90YXRpb24uY2hhbmdlKSk7XG59XG5mdW5jdGlvbiBfYWRhcHRNb3ZlKG1vdmUsIG9yaWdpbmFsLCBtb2RpZmllZCwgb3JpZ2luYWxMaW5lcywgbW9kaWZpZWRMaW5lcywgb3JpZ2luYWxMaW5lU3RhcnRzLCBtb2RpZmllZExpbmVTdGFydHMpIHtcbiAgICBjb25zdCBvcmlnUmFuZ2UgPSBfbGluZVJhbmdlVG9PZmZzZXRSYW5nZShtb3ZlLmxpbmVSYW5nZU1hcHBpbmcub3JpZ2luYWwuc3RhcnRMaW5lTnVtYmVyLCBtb3ZlLmxpbmVSYW5nZU1hcHBpbmcub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgb3JpZ2luYWwsIG9yaWdpbmFsTGluZVN0YXJ0cyk7XG4gICAgY29uc3QgbW9kUmFuZ2UgPSBfbGluZVJhbmdlVG9PZmZzZXRSYW5nZShtb3ZlLmxpbmVSYW5nZU1hcHBpbmcubW9kaWZpZWQuc3RhcnRMaW5lTnVtYmVyLCBtb3ZlLmxpbmVSYW5nZU1hcHBpbmcubW9kaWZpZWQuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgbW9kaWZpZWQsIG1vZGlmaWVkTGluZVN0YXJ0cyk7XG4gICAgLy8gQnVpbGQgaW5uZXIgZWRpdCB3aXRoIG9mZnNldHMgbG9jYWwgdG8gdGhlIG1vdmVkIHNsaWNlcy5cbiAgICBjb25zdCBpbm5lciA9IFtdO1xuICAgIGZvciAoY29uc3QgY2hhbmdlIG9mIG1vdmUuY2hhbmdlcykge1xuICAgICAgICBpZiAoY2hhbmdlLmlubmVyQ2hhbmdlcyAmJiBjaGFuZ2UuaW5uZXJDaGFuZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaWMgb2YgY2hhbmdlLmlubmVyQ2hhbmdlcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbE9yaWcgPSBfcmFuZ2VUb09mZnNldFJhbmdlKGljLm9yaWdpbmFsUmFuZ2UsIG9yaWdpbmFsLCBvcmlnaW5hbExpbmVzLCBvcmlnaW5hbExpbmVTdGFydHMpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbE1vZCA9IF9yYW5nZVRvT2Zmc2V0UmFuZ2UoaWMubW9kaWZpZWRSYW5nZSwgbW9kaWZpZWQsIG1vZGlmaWVkTGluZXMsIG1vZGlmaWVkTGluZVN0YXJ0cyk7XG4gICAgICAgICAgICAgICAgaW5uZXIucHVzaChuZXcgU3RyaW5nUmVwbGFjZW1lbnQobmV3IE9mZnNldFJhbmdlKGdsb2JhbE9yaWcuc3RhcnQgLSBvcmlnUmFuZ2Uuc3RhcnQsIGdsb2JhbE9yaWcuZW5kRXhjbHVzaXZlIC0gb3JpZ1JhbmdlLnN0YXJ0KSwgbW9kaWZpZWQuc3Vic3RyaW5nKGdsb2JhbE1vZC5zdGFydCwgZ2xvYmFsTW9kLmVuZEV4Y2x1c2l2ZSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGdsb2JhbE9yaWcgPSBfbGluZVJhbmdlVG9PZmZzZXRSYW5nZShjaGFuZ2Uub3JpZ2luYWwuc3RhcnRMaW5lTnVtYmVyLCBjaGFuZ2Uub3JpZ2luYWwuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgb3JpZ2luYWwsIG9yaWdpbmFsTGluZVN0YXJ0cyk7XG4gICAgICAgICAgICBjb25zdCBnbG9iYWxNb2QgPSBfbGluZVJhbmdlVG9PZmZzZXRSYW5nZShjaGFuZ2UubW9kaWZpZWQuc3RhcnRMaW5lTnVtYmVyLCBjaGFuZ2UubW9kaWZpZWQuZW5kTGluZU51bWJlckV4Y2x1c2l2ZSwgbW9kaWZpZWQsIG1vZGlmaWVkTGluZVN0YXJ0cyk7XG4gICAgICAgICAgICBpbm5lci5wdXNoKG5ldyBTdHJpbmdSZXBsYWNlbWVudChuZXcgT2Zmc2V0UmFuZ2UoZ2xvYmFsT3JpZy5zdGFydCAtIG9yaWdSYW5nZS5zdGFydCwgZ2xvYmFsT3JpZy5lbmRFeGNsdXNpdmUgLSBvcmlnUmFuZ2Uuc3RhcnQpLCBtb2RpZmllZC5zdWJzdHJpbmcoZ2xvYmFsTW9kLnN0YXJ0LCBnbG9iYWxNb2QuZW5kRXhjbHVzaXZlKSkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgTW92ZShuZXcgT2Zmc2V0UmFuZ2VNYXBwaW5nKG9yaWdSYW5nZSwgbW9kUmFuZ2UpLCBTdHJpbmdFZGl0Lm9mKGlubmVyKSk7XG59XG4vLyAtLS0tLSBvZmZzZXQvbGluZSBoZWxwZXJzIC0tLS0tXG5mdW5jdGlvbiBfY29tcHV0ZUxpbmVTdGFydHMobGluZXMpIHtcbiAgICAvLyBPZmZzZXRzIGNvcnJlc3BvbmQgdG8gYGxpbmVzLmpvaW4oJ1xcbicpYCwgd2hpY2ggZXF1YWxzIHRoZSBpbnB1dCBzdHJpbmdcbiAgICAvLyB3aGVuIHRoZSBpbnB1dCB3YXMgc3BsaXQgYnkgYFxcbmAuXG4gICAgY29uc3Qgc3RhcnRzID0gbmV3IEFycmF5KGxpbmVzLmxlbmd0aCArIDEpO1xuICAgIHN0YXJ0c1swXSA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBzdGFydHNbaSArIDFdID0gc3RhcnRzW2ldICsgbGluZXNbaV0ubGVuZ3RoICsgMTsgLy8gKzEgZm9yIHRoZSAnXFxuJ1xuICAgIH1cbiAgICAvLyBgc3RhcnRzW2xpbmVzLmxlbmd0aF1gIGlzIG9uZSBwYXN0IHRoZSBzeW50aGV0aWMgdHJhaWxpbmcgbmV3bGluZTsgdGhlXG4gICAgLy8gcmVhbCB0ZXh0IGVuZHMgb25lIGVhcmxpZXIgd2hlbiB0aGVyZSBpcyBubyB0cmFpbGluZyBuZXdsaW5lICh3aGljaCBpc1xuICAgIC8vIHdoYXQgYHNwbGl0KCdcXG4nKWAgcHJvZHVjZXMgZm9yIG5vbi1uZXdsaW5lLXRlcm1pbmF0ZWQgaW5wdXQpLlxuICAgIHJldHVybiBzdGFydHM7XG59XG5mdW5jdGlvbiBfbGluZVJhbmdlVG9PZmZzZXRSYW5nZShzdGFydExpbmVOdW1iZXIsIGVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIHRleHQsIGxpbmVTdGFydHMpIHtcbiAgICBjb25zdCBzdGFydCA9IF9saW5lQ29sVG9PZmZzZXQoc3RhcnRMaW5lTnVtYmVyLCAxLCB0ZXh0LCBsaW5lU3RhcnRzKTtcbiAgICBjb25zdCBlbmQgPSBfbGluZUNvbFRvT2Zmc2V0KGVuZExpbmVOdW1iZXJFeGNsdXNpdmUsIDEsIHRleHQsIGxpbmVTdGFydHMpO1xuICAgIHJldHVybiBuZXcgT2Zmc2V0UmFuZ2Uoc3RhcnQsIGVuZCk7XG59XG5mdW5jdGlvbiBfcmFuZ2VUb09mZnNldFJhbmdlKHJhbmdlLCB0ZXh0LCBsaW5lcywgbGluZVN0YXJ0cykge1xuICAgIGNvbnN0IHN0YXJ0ID0gX2xpbmVDb2xUb09mZnNldChyYW5nZS5zdGFydExpbmVOdW1iZXIsIHJhbmdlLnN0YXJ0Q29sdW1uLCB0ZXh0LCBsaW5lU3RhcnRzKTtcbiAgICBjb25zdCBlbmQgPSBfbGluZUNvbFRvT2Zmc2V0KHJhbmdlLmVuZExpbmVOdW1iZXIsIHJhbmdlLmVuZENvbHVtbiwgdGV4dCwgbGluZVN0YXJ0cyk7XG4gICAgcmV0dXJuIG5ldyBPZmZzZXRSYW5nZShzdGFydCwgZW5kKTtcbn1cbmZ1bmN0aW9uIF9saW5lQ29sVG9PZmZzZXQobGluZU51bWJlciwgY29sdW1uLCB0ZXh0LCBsaW5lU3RhcnRzKSB7XG4gICAgLy8gYGxpbmVOdW1iZXJgIGFuZCBgY29sdW1uYCBhcmUgMS1iYXNlZDsgYGVuZExpbmVOdW1iZXJFeGNsdXNpdmVgIGNhbiBiZVxuICAgIC8vIGBsaW5lcy5sZW5ndGggKyAxYCAob25lIHBhc3QgdGhlIGxhc3QgbGluZSkuXG4gICAgaWYgKGxpbmVOdW1iZXIgPD0gMCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKGxpbmVOdW1iZXIgPiBsaW5lU3RhcnRzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gdGV4dC5sZW5ndGg7XG4gICAgfVxuICAgIGNvbnN0IGJhc2UgPSBsaW5lU3RhcnRzW2xpbmVOdW1iZXIgLSAxXTtcbiAgICBjb25zdCBvZmZzZXQgPSBiYXNlICsgKGNvbHVtbiAtIDEpO1xuICAgIHJldHVybiBNYXRoLm1pbihNYXRoLm1heChvZmZzZXQsIDApLCB0ZXh0Lmxlbmd0aCk7XG59XG5cbi8qKlxuICogTWFpbi10aHJlYWQgY2xpZW50IGZvciB0aGUgZGlmZiB3b3JrZXIuIEV4cG9zZXMgYW4gYXN5bmMgYElBc3luY0RpZmZDb21wdXRlcmAuXG4gKlxuICogSW5wdXRzIHRyYXZlbCBhcyBgc3RyaW5nW11gIHZpYSBzdHJ1Y3R1cmVkLWNsb25lIHBvc3RNZXNzYWdlLiBUaGUgcmVzcG9uc2VcbiAqIGlzIGEgc21hbGwgSlNPTi1mcmllbmRseSBgV2lyZUxpbmVzRGlmZmA7IHRoZSBtYWluIHRocmVhZCByZWNvbnN0cnVjdHMgdGhlXG4gKiBmdWxsIGBMaW5lc0RpZmZgIGFuZCBydW5zIGBfYWRhcHRMaW5lc0RpZmZgIGxvY2FsbHkgKGl0IGFscmVhZHkgaGFzIHRoZVxuICogaW5wdXQgc3RyaW5ncykuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdvcmtlckRpZmZDb21wdXRlcihvcHRzID0ge30pIHtcbiAgICBjb25zdCB3b3JrZXIgPSBvcHRzLndvcmtlckZhY3RvcnkgPyBvcHRzLndvcmtlckZhY3RvcnkoKSA6IGRlZmF1bHRXb3JrZXJGYWN0b3J5KCk7XG4gICAgY29uc3QgYmFja2VuZCA9IG9wdHMudXNlV2FzbSA/ICd3YXNtJyA6ICd0cyc7XG4gICAgY29uc3QgY29tcHV0ZXIgPSBuZXcgX1dvcmtlckRpZmZDb21wdXRlcih3b3JrZXIsIGJhY2tlbmQpO1xuICAgIGF3YWl0IGNvbXB1dGVyLmluaXQoKTtcbiAgICByZXR1cm4gY29tcHV0ZXI7XG59XG5mdW5jdGlvbiBkZWZhdWx0V29ya2VyRmFjdG9yeSgpIHtcbiAgICAvLyBUaGUgYD9lc21gIG1hcmtlciBpcyBhdXRvLWRpc2NvdmVyZWQgYnkgYEB2c2NvZGUvKi1wbHVnaW4tZXNtLXVybGBcbiAgICAvLyBidW5kbGVyIHBsdWdpbnM7IHRoZXkgZW1pdCBgd29ya2VyLnRzYCBhcyBhIHNpYmxpbmcgYHdvcmtlci5qc2AgYnVuZGxlXG4gICAgLy8gYW5kIHJld3JpdGUgdGhpcyBVUkwgYWNjb3JkaW5nbHkuXG4gICAgcmV0dXJuIG5ldyBXb3JrZXIobmV3IFVSTCgnd29ya2VyLmpzP2VzbScsIGltcG9ydC5tZXRhLnVybCksIHsgdHlwZTogJ21vZHVsZScgfSk7XG59XG5jbGFzcyBfV29ya2VyRGlmZkNvbXB1dGVyIHtcbiAgICBfd29ya2VyO1xuICAgIF9iYWNrZW5kO1xuICAgIF9uZXh0SWQgPSAxO1xuICAgIF9wZW5kaW5nID0gbmV3IE1hcCgpO1xuICAgIF9wZW5kaW5nSW5pdCA9IG51bGw7XG4gICAgX2Rpc3Bvc2VkID0gZmFsc2U7XG4gICAgY29uc3RydWN0b3IoX3dvcmtlciwgX2JhY2tlbmQpIHtcbiAgICAgICAgdGhpcy5fd29ya2VyID0gX3dvcmtlcjtcbiAgICAgICAgdGhpcy5fYmFja2VuZCA9IF9iYWNrZW5kO1xuICAgICAgICB0aGlzLl93b3JrZXIuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIChldikgPT4ge1xuICAgICAgICAgICAgdGhpcy5fb25NZXNzYWdlKGV2LmRhdGEpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fd29ya2VyLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgKGV2KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9mYWlsQWxsKG5ldyBFcnJvcihgV29ya2VyIGVycm9yOiAke2V2Lm1lc3NhZ2UgPz8gJ3Vua25vd24nfWApKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGluaXQoKSB7XG4gICAgICAgIGNvbnN0IGlkID0gdGhpcy5fbmV4dElkKys7XG4gICAgICAgIGNvbnN0IHJlcSA9IHsga2luZDogJ2luaXQnLCBpZCwgYmFja2VuZDogdGhpcy5fYmFja2VuZCB9O1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcGVuZGluZ0luaXQgPSB7IHJlc29sdmUsIHJlamVjdCB9O1xuICAgICAgICAgICAgdGhpcy5fd29ya2VyLnBvc3RNZXNzYWdlKHJlcSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjb21wdXRlRGlmZihvcmlnaW5hbCwgbW9kaWZpZWQsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBpZiAodGhpcy5fZGlzcG9zZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ1dvcmtlciBjb21wdXRlciBkaXNwb3NlZCcpKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpZCA9IHRoaXMuX25leHRJZCsrO1xuICAgICAgICBjb25zdCBvcmlnaW5hbExpbmVzID0gb3JpZ2luYWwuc3BsaXQoJ1xcbicpO1xuICAgICAgICBjb25zdCBtb2RpZmllZExpbmVzID0gbW9kaWZpZWQuc3BsaXQoJ1xcbicpO1xuICAgICAgICBjb25zdCBtc2cgPSB7XG4gICAgICAgICAgICBraW5kOiAnY29tcHV0ZURpZmYnLFxuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBiYWNrZW5kOiB0aGlzLl9iYWNrZW5kLFxuICAgICAgICAgICAgb3JpZ2luYWxMaW5lcyxcbiAgICAgICAgICAgIG1vZGlmaWVkTGluZXMsXG4gICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcGVuZGluZy5zZXQoaWQsIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlLFxuICAgICAgICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgICAgICAgICBvcmlnaW5hbCxcbiAgICAgICAgICAgICAgICBtb2RpZmllZCxcbiAgICAgICAgICAgICAgICBvcmlnaW5hbExpbmVzLFxuICAgICAgICAgICAgICAgIG1vZGlmaWVkTGluZXMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuX3dvcmtlci5wb3N0TWVzc2FnZShtc2cpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZGlzcG9zZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2Rpc3Bvc2VkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLl9kaXNwb3NlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX2ZhaWxBbGwobmV3IEVycm9yKCdXb3JrZXIgY29tcHV0ZXIgZGlzcG9zZWQnKSk7XG4gICAgICAgIHRoaXMuX3dvcmtlci50ZXJtaW5hdGUoKTtcbiAgICB9XG4gICAgX29uTWVzc2FnZShtc2cpIHtcbiAgICAgICAgaWYgKG1zZy5raW5kID09PSAnaW5pdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHBlbmRpbmcgPSB0aGlzLl9wZW5kaW5nSW5pdDtcbiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdJbml0ID0gbnVsbDtcbiAgICAgICAgICAgIHBlbmRpbmc/LnJlc29sdmUoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBlbnRyeSA9IHRoaXMuX3BlbmRpbmcuZ2V0KG1zZy5pZCk7XG4gICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICAgIC8vIEluaXQgZmFpbHVyZSBpcyByZXBvcnRlZCBvbiB0aGUgaW5pdCBpZCB3aXRoIGBraW5kID09PSAnY29tcHV0ZURpZmYnYFxuICAgICAgICAgICAgLy8gYW5kIGBvayA9PT0gZmFsc2VgOyByb3V0ZSB0byB0aGUgaW5pdCBwcm9taXNlIGlmIGl0J3Mgc3RpbGwgcGVuZGluZy5cbiAgICAgICAgICAgIGlmICghbXNnLm9rICYmIHRoaXMuX3BlbmRpbmdJbml0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcCA9IHRoaXMuX3BlbmRpbmdJbml0O1xuICAgICAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdJbml0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICBwLnJlamVjdChuZXcgRXJyb3IobXNnLmVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcGVuZGluZy5kZWxldGUobXNnLmlkKTtcbiAgICAgICAgaWYgKCFtc2cub2spIHtcbiAgICAgICAgICAgIGVudHJ5LnJlamVjdChuZXcgRXJyb3IobXNnLmVycm9yKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGxpbmVzRGlmZiA9IHdpcmVUb0xpbmVzRGlmZihtc2cucmVzdWx0KTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IF9hZGFwdExpbmVzRGlmZihsaW5lc0RpZmYsIGVudHJ5Lm9yaWdpbmFsLCBlbnRyeS5tb2RpZmllZCwgZW50cnkub3JpZ2luYWxMaW5lcywgZW50cnkubW9kaWZpZWRMaW5lcyk7XG4gICAgICAgICAgICBlbnRyeS5yZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZW50cnkucmVqZWN0KGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKFN0cmluZyhlcnIpKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgX2ZhaWxBbGwoZXJyKSB7XG4gICAgICAgIGZvciAoY29uc3QgcCBvZiB0aGlzLl9wZW5kaW5nLnZhbHVlcygpKVxuICAgICAgICAgICAgcC5yZWplY3QoZXJyKTtcbiAgICAgICAgdGhpcy5fcGVuZGluZy5jbGVhcigpO1xuICAgICAgICBpZiAodGhpcy5fcGVuZGluZ0luaXQpIHtcbiAgICAgICAgICAgIHRoaXMuX3BlbmRpbmdJbml0LnJlamVjdChlcnIpO1xuICAgICAgICAgICAgdGhpcy5fcGVuZGluZ0luaXQgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgeyBBbm5vdGF0ZWRTdHJpbmdFZGl0LCBBbm5vdGF0ZWRTdHJpbmdSZXBsYWNlbWVudCwgRGlmZkFubm90YXRpb24sIERpZmZSZXN1bHQsIE1vdmUsIE9mZnNldFJhbmdlLCBPZmZzZXRSYW5nZU1hcHBpbmcsIFN0cmluZ0VkaXQsIFN0cmluZ1JlcGxhY2VtZW50LCBEZWZhdWx0TGluZXNEaWZmQ29tcHV0ZXIgYXMgX0RlZmF1bHRMaW5lc0RpZmZDb21wdXRlciwgRGV0YWlsZWRMaW5lUmFuZ2VNYXBwaW5nIGFzIF9EZXRhaWxlZExpbmVSYW5nZU1hcHBpbmcsIExpbmVSYW5nZSBhcyBfTGluZVJhbmdlLCBMaW5lc0RpZmYgYXMgX0xpbmVzRGlmZiwgUmFuZ2VNYXBwaW5nIGFzIF9SYW5nZU1hcHBpbmcsIGdldFdhc20gYXMgX2dldFdhc20sIGluaXRXYXNtIGFzIF9pbml0V2FzbSwgY3JlYXRlRGlmZkNvbXB1dGVyLCBjcmVhdGVXb3JrZXJEaWZmQ29tcHV0ZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZGV4LmpzLm1hcFxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9
|