@xaendar/compiler 0.4.5 → 0.4.6

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.
@@ -1,1063 +1,2439 @@
1
- import { Stack as e, indent as t } from "@xaendar/common";
2
- import n from "typescript";
1
+ import { Stack, indent } from "@xaendar/common";
2
+ import ts from "typescript";
3
3
  //#region ../packages/compiler/src/lexer/types/lexer-state.enum.ts
4
- var r = /* @__PURE__ */ function(e) {
5
- return e.START = "start", e.TEXT = "text", e.TAG_OPEN_NAME = "tag-open-name", e.TAG_BODY = "tag-body", e.TAG_OPEN_END = "tag-open-end", e.TAG_CLOSE = "tag-close", e.ATTRIBUTE = "attribute", e.EVENT = "event", e.FLOW_CONTROL = "flow-control", e.FLOW_CONTROL_CONDITION = "flow-control-condition", e.CASE_FLOW_CONTROL_CONDITION = "case-flow-control-condition", e.FLOW_CONTROL_BLOCK = "flow-control-block", e.INTERPOLATION = "interpolation", e.INTERPOLATION_EXPRESSION = "interpolation-expression", e.INTERPOLATION_LITERAL = "interpolation-literal", e.CONST_DECLARATION = "const-declaration", e;
6
- }({}), i = /* @__PURE__ */ function(e) {
7
- return e[e.TEXT = 0] = "TEXT", e[e.TAG_OPEN_NAME = 1] = "TAG_OPEN_NAME", e[e.TAG_SELF_CLOSE = 2] = "TAG_SELF_CLOSE", e[e.TAG_OPEN_END = 3] = "TAG_OPEN_END", e[e.TAG_CLOSE_NAME = 4] = "TAG_CLOSE_NAME", e[e.ATTRIBUTE = 5] = "ATTRIBUTE", e[e.EVENT = 6] = "EVENT", e[e.INTERPOLATION_LITERAL = 7] = "INTERPOLATION_LITERAL", e[e.INTERPOLATION_EXPRESSION = 8] = "INTERPOLATION_EXPRESSION", e[e.CONST_DECLARATION = 9] = "CONST_DECLARATION", e[e.IF = 10] = "IF", e[e.FOR = 11] = "FOR", e[e.ELSE = 12] = "ELSE", e[e.ELSE_IF = 13] = "ELSE_IF", e[e.SWITCH = 14] = "SWITCH", e[e.CASE = 15] = "CASE", e[e.DEFAULT = 16] = "DEFAULT", e[e.CONDITION = 17] = "CONDITION", e[e.BLOCK_OPEN = 18] = "BLOCK_OPEN", e[e.BLOCK_CLOSE = 19] = "BLOCK_CLOSE", e[e.EOF = 20] = "EOF", e;
4
+ /**
5
+ * Represents the set of states the lexer can be in while processing template input.
6
+ */
7
+ var LexerState = /* @__PURE__ */ function(LexerState) {
8
+ /**
9
+ * Initial state before any input has been processed.
10
+ */
11
+ LexerState["START"] = "start";
12
+ /**
13
+ * Consuming plain text content between tags or at the top level.
14
+ */
15
+ LexerState["TEXT"] = "text";
16
+ /**
17
+ * Consuming the opening tag name after `<`.
18
+ */
19
+ LexerState["TAG_OPEN_NAME"] = "tag-open-name";
20
+ /**
21
+ * Inside an open tag body, scanning for attributes, events, or the closing `>`.
22
+ */
23
+ LexerState["TAG_BODY"] = "tag-body";
24
+ /**
25
+ * Processing the end of an open tag: `>` or `/>`.
26
+ */
27
+ LexerState["TAG_OPEN_END"] = "tag-open-end";
28
+ /**
29
+ * Consuming a closing tag `</tagName>`.
30
+ */
31
+ LexerState["TAG_CLOSE"] = "tag-close";
32
+ /**
33
+ * Consuming an HTML attribute name and its optional value.
34
+ */
35
+ LexerState["ATTRIBUTE"] = "attribute";
36
+ /**
37
+ * Consuming a DOM event binding starting with `@`.
38
+ */
39
+ LexerState["EVENT"] = "event";
40
+ /**
41
+ * Dispatching a flow-control keyword (@if, @for, @switch, etc.).
42
+ */
43
+ LexerState["FLOW_CONTROL"] = "flow-control";
44
+ /**
45
+ * Consuming the condition expression `(...)` of a flow-control directive.
46
+ */
47
+ LexerState["FLOW_CONTROL_CONDITION"] = "flow-control-condition";
48
+ /**
49
+ * Consuming the condition expression `(...)` of a @case directive.
50
+ * This is needed to correctly handle special consecutives @case
51
+ */
52
+ LexerState["CASE_FLOW_CONTROL_CONDITION"] = "case-flow-control-condition";
53
+ /**
54
+ * Consuming the opening `{` of a flow-control block body.
55
+ */
56
+ LexerState["FLOW_CONTROL_BLOCK"] = "flow-control-block";
57
+ /**
58
+ * Dispatching between an expression or literal interpolation after `{`.
59
+ */
60
+ LexerState["INTERPOLATION"] = "interpolation";
61
+ /**
62
+ * Consuming a JavaScript expression inside `{ }`.
63
+ */
64
+ LexerState["INTERPOLATION_EXPRESSION"] = "interpolation-expression";
65
+ /**
66
+ * Consuming a template-literal string inside `` {`...`} ``.
67
+ */
68
+ LexerState["INTERPOLATION_LITERAL"] = "interpolation-literal";
69
+ /**
70
+ * Consuming a `@const name = expression;` declaration.
71
+ */
72
+ LexerState["CONST_DECLARATION"] = "const-declaration";
73
+ return LexerState;
74
+ }({});
75
+ //#endregion
76
+ //#region ../packages/compiler/src/lexer/types/token-type.enum.ts
77
+ /**
78
+ * Discriminant values that identify the type of each token emitted by the lexer.
79
+ */
80
+ var TokenType = /* @__PURE__ */ function(TokenType) {
81
+ /**
82
+ * A plain text node between tags or at the top level.
83
+ */
84
+ TokenType[TokenType["TEXT"] = 0] = "TEXT";
85
+ /**
86
+ * The name portion of an opening tag, e.g. `div` in `<div`.
87
+ */
88
+ TokenType[TokenType["TAG_OPEN_NAME"] = 1] = "TAG_OPEN_NAME";
89
+ /**
90
+ * A self-closing tag marker `/>`.
91
+ */
92
+ TokenType[TokenType["TAG_SELF_CLOSE"] = 2] = "TAG_SELF_CLOSE";
93
+ /**
94
+ * The closing `>` of an opening tag.
95
+ */
96
+ TokenType[TokenType["TAG_OPEN_END"] = 3] = "TAG_OPEN_END";
97
+ /**
98
+ * The name portion of a closing tag, e.g. `div` in `</div>`.
99
+ */
100
+ TokenType[TokenType["TAG_CLOSE_NAME"] = 4] = "TAG_CLOSE_NAME";
101
+ /**
102
+ * An HTML attribute and its optional value.
103
+ */
104
+ TokenType[TokenType["ATTRIBUTE"] = 5] = "ATTRIBUTE";
105
+ /**
106
+ * A DOM event binding declared with `@eventName=handler`.
107
+ */
108
+ TokenType[TokenType["EVENT"] = 6] = "EVENT";
109
+ /**
110
+ * A template-literal interpolation string enclosed in `` {`...`} ``.
111
+ */
112
+ TokenType[TokenType["INTERPOLATION_LITERAL"] = 7] = "INTERPOLATION_LITERAL";
113
+ /**
114
+ * A JavaScript expression interpolation enclosed in `{ }`.
115
+ */
116
+ TokenType[TokenType["INTERPOLATION_EXPRESSION"] = 8] = "INTERPOLATION_EXPRESSION";
117
+ /**
118
+ * A `@const name = expression;` template-level constant declaration.
119
+ */
120
+ TokenType[TokenType["CONST_DECLARATION"] = 9] = "CONST_DECLARATION";
121
+ /**
122
+ * Opening keyword of an `@if` directive.
123
+ */
124
+ TokenType[TokenType["IF"] = 10] = "IF";
125
+ /**
126
+ * Opening keyword of a `@for` directive.
127
+ */
128
+ TokenType[TokenType["FOR"] = 11] = "FOR";
129
+ /**
130
+ * Opening keyword of an `@else` branch.
131
+ */
132
+ TokenType[TokenType["ELSE"] = 12] = "ELSE";
133
+ /**
134
+ * Opening keyword of an `@else if` branch.
135
+ */
136
+ TokenType[TokenType["ELSE_IF"] = 13] = "ELSE_IF";
137
+ /**
138
+ * Opening keyword of a `@switch` directive.
139
+ */
140
+ TokenType[TokenType["SWITCH"] = 14] = "SWITCH";
141
+ /**
142
+ * Opening keyword of a `@case` branch.
143
+ */
144
+ TokenType[TokenType["CASE"] = 15] = "CASE";
145
+ /**
146
+ * Opening keyword of a `@default` branch.
147
+ */
148
+ TokenType[TokenType["DEFAULT"] = 16] = "DEFAULT";
149
+ /**
150
+ * The condition expression `(...)` associated with a flow-control directive.
151
+ */
152
+ TokenType[TokenType["CONDITION"] = 17] = "CONDITION";
153
+ /**
154
+ * The opening `{` of a flow-control block body.
155
+ */
156
+ TokenType[TokenType["BLOCK_OPEN"] = 18] = "BLOCK_OPEN";
157
+ /**
158
+ * The closing `}` of a flow-control block body.
159
+ */
160
+ TokenType[TokenType["BLOCK_CLOSE"] = 19] = "BLOCK_CLOSE";
161
+ /**
162
+ * Sentinel token emitted when the end of the input is reached.
163
+ */
164
+ TokenType[TokenType["EOF"] = 20] = "EOF";
165
+ return TokenType;
8
166
  }({});
9
167
  //#endregion
10
168
  //#region ../packages/compiler/src/lexer/states/attribute.state.ts
11
- function a(e, t) {
12
- let n = !0, a = "", o;
13
- for (; n;) switch (e.peek()) {
169
+ /**
170
+ * Consumes an attribute name and optional value from the current position,
171
+ * transitioning back to TAG_BODY when a space, `/`, or `>` is encountered.
172
+ * If the attribute value is an interpolation, pushes the INTERPOLATION state.
173
+ *
174
+ * @param cursor The lexer cursor positioned at the start of the attribute.
175
+ * @param _context Unused lexer context.
176
+ * @returns Transition result with the ATTRIBUTE token and next state.
177
+ */
178
+ function consumeAttribute(cursor, _context) {
179
+ let read = true;
180
+ let attribute = "";
181
+ let retVal;
182
+ while (read) switch (cursor.peek()) {
14
183
  case 32:
15
184
  case 47:
16
185
  case 62:
17
- o = {
18
- state: r.TAG_BODY,
186
+ retVal = {
187
+ state: LexerState.TAG_BODY,
19
188
  tokens: [{
20
- type: i.ATTRIBUTE,
21
- parts: [a]
189
+ type: TokenType.ATTRIBUTE,
190
+ parts: [attribute]
22
191
  }]
23
- }, n = !1;
192
+ };
193
+ read = false;
24
194
  break;
25
195
  case 123:
26
- o = {
27
- state: r.INTERPOLATION,
196
+ retVal = {
197
+ state: LexerState.INTERPOLATION,
28
198
  tokens: [{
29
- type: i.ATTRIBUTE,
30
- parts: [a]
199
+ type: TokenType.ATTRIBUTE,
200
+ parts: [attribute]
31
201
  }],
32
- pushState: !0
33
- }, n = !1;
202
+ pushState: true
203
+ };
204
+ read = false;
34
205
  break;
35
- default: e.advance(), a = `${a}${e.currentChar.value}`;
206
+ default:
207
+ cursor.advance();
208
+ attribute = `${attribute}${cursor.currentChar.value}`;
36
209
  }
37
- return o;
210
+ return retVal;
38
211
  }
39
212
  //#endregion
40
213
  //#region ../packages/compiler/src/lexer/utils/consume-flow-control-condition.utils.ts
41
- function o(e, t) {
42
- if (e.skipSpaces(), e.peek() !== 40) throw Error(`Expected '(' but got '${String.fromCharCode(e.peek())}' at row ${e.position.row}, col ${e.position.column}`);
43
- e.advance();
44
- let n = "", r = 1;
45
- for (; r > 0;) switch (e.peek()) {
214
+ function consumeFlowControlCondition(cursor, _context) {
215
+ cursor.skipSpaces();
216
+ if (cursor.peek() !== 40) throw new Error(`Expected '(' but got '${String.fromCharCode(cursor.peek())}' at row ${cursor.position.row}, col ${cursor.position.column}`);
217
+ cursor.advance();
218
+ let expression = "";
219
+ let depth = 1;
220
+ while (depth > 0) switch (cursor.peek()) {
46
221
  case 40:
47
- r++, n = s(e, n);
222
+ depth++;
223
+ expression = addCharacter$2(cursor, expression);
48
224
  break;
49
225
  case 41:
50
- if (r--, !r) {
51
- e.advance();
226
+ depth--;
227
+ if (!depth) {
228
+ cursor.advance();
52
229
  break;
53
230
  }
54
- n = s(e, n);
231
+ expression = addCharacter$2(cursor, expression);
55
232
  break;
56
- default: n = s(e, n);
233
+ default: expression = addCharacter$2(cursor, expression);
57
234
  }
58
- return n;
235
+ return expression;
59
236
  }
60
- function s(e, t) {
61
- return e.advance(), `${t}${e.currentChar.value}`;
237
+ /**
238
+ * Advances the cursor by one character and appends it to the accumulator string.
239
+ *
240
+ * @param cursor The lexer cursor to advance.
241
+ * @param expression The current accumulated string.
242
+ * @returns The updated string with the new character appended.
243
+ */
244
+ function addCharacter$2(cursor, expression) {
245
+ cursor.advance();
246
+ return `${expression}${cursor.currentChar.value}`;
62
247
  }
63
248
  //#endregion
64
249
  //#region ../packages/compiler/src/lexer/states/case-flow-control-condition.state.ts
65
- function c(e, t) {
66
- let n = o(e, t);
67
- return e.skipSpaces(), {
68
- state: e.peekMatch("@case") ? r.FLOW_CONTROL : r.FLOW_CONTROL_BLOCK,
250
+ /**
251
+ * Consumes the condition expression `(...)` of a flow-control directive,
252
+ * handling nested parentheses correctly. Emits a CONDITION token with the
253
+ * raw expression string and transitions to FLOW_CONTROL_BLOCK.
254
+ *
255
+ * @param cursor The lexer cursor positioned at the opening `(`.
256
+ * @param _context Unused lexer context.
257
+ * @returns Transition result with the CONDITION token and the FLOW_CONTROL_BLOCK state.
258
+ */
259
+ function consumeCaseFlowControlCondition(cursor, _context) {
260
+ const condition = consumeFlowControlCondition(cursor, _context);
261
+ cursor.skipSpaces();
262
+ return {
263
+ state: cursor.peekMatch("@case") ? LexerState.FLOW_CONTROL : LexerState.FLOW_CONTROL_BLOCK,
69
264
  tokens: [{
70
- type: i.CONDITION,
71
- parts: [n]
265
+ type: TokenType.CONDITION,
266
+ parts: [condition]
72
267
  }],
73
- popState: !0
268
+ popState: true
74
269
  };
75
270
  }
76
271
  //#endregion
77
272
  //#region ../packages/compiler/src/lexer/states/const-declaration.ts
78
- function l(e, t) {
79
- let n = !0, a = "", o = "", s;
80
- for (e.skipSpaces(); n;) switch (e.peek()) {
273
+ /**
274
+ * Consumes a `@const name = expression;` declaration from the current position.
275
+ * Expects the cursor to be positioned after the `@const ` keyword.
276
+ * Emits a CONST_DECLARATION token containing the variable name and initializer expression.
277
+ *
278
+ * @param cursor The lexer cursor positioned at the start of the variable name.
279
+ * @param _context Unused lexer context.
280
+ * @returns Transition result with the CONST_DECLARATION token and the TEXT state.
281
+ */
282
+ function consumeConstDeclaration(cursor, _context) {
283
+ let read = true;
284
+ let varName = "";
285
+ let expression = "";
286
+ let retVal;
287
+ cursor.skipSpaces();
288
+ while (read) switch (cursor.peek()) {
81
289
  case 32:
82
- n = !1;
290
+ read = false;
83
291
  break;
84
- default: e.advance(), a = `${a}${e.currentChar.value}`;
292
+ default:
293
+ cursor.advance();
294
+ varName = `${varName}${cursor.currentChar.value}`;
85
295
  }
86
- e.skipSpaces();
87
- let c = e.peek();
88
- if (c !== 61) throw Error(`Unexpected character ${String.fromCharCode(c)}.\nExpected '=' `);
89
- for (e.advance(), e.skipSpaces(), n = !0; n;) switch (e.peek()) {
296
+ cursor.skipSpaces();
297
+ const nextChar = cursor.peek();
298
+ if (nextChar !== 61) throw new Error(`Unexpected character ${String.fromCharCode(nextChar)}.\nExpected '=' `);
299
+ cursor.advance();
300
+ cursor.skipSpaces();
301
+ read = true;
302
+ while (read) switch (cursor.peek()) {
90
303
  case 59:
91
- s = {
92
- state: r.TEXT,
304
+ retVal = {
305
+ state: LexerState.TEXT,
93
306
  tokens: [{
94
- type: i.CONST_DECLARATION,
95
- parts: [a, o]
307
+ type: TokenType.CONST_DECLARATION,
308
+ parts: [varName, expression]
96
309
  }]
97
- }, n = !1;
310
+ };
311
+ read = false;
98
312
  break;
99
- default: e.advance(), o = `${o}${e.currentChar.value}`;
313
+ default:
314
+ cursor.advance();
315
+ expression = `${expression}${cursor.currentChar.value}`;
100
316
  }
101
- return e.advance(), o = `${o};`, s;
317
+ cursor.advance();
318
+ expression = `${expression};`;
319
+ return retVal;
102
320
  }
103
321
  //#endregion
104
322
  //#region ../packages/compiler/src/lexer/states/event.state.ts
105
- function u(e, t) {
106
- let n = !0, a = "", o;
107
- for (e.advance(); n;) switch (e.peek()) {
323
+ /**
324
+ * Consumes a DOM event binding starting with `@` and reads until a delimiter
325
+ * (space, `/`, or `>`) is found. Emits an EVENT token containing the raw binding string.
326
+ *
327
+ * @param cursor The lexer cursor positioned on the `@` character.
328
+ * @param _context Unused lexer context.
329
+ * @returns Transition result with the EVENT token and the TAG_BODY state.
330
+ */
331
+ function consumeEvent(cursor, _context) {
332
+ let read = true;
333
+ let event = "";
334
+ let retVal;
335
+ cursor.advance();
336
+ while (read) switch (cursor.peek()) {
108
337
  case 32:
109
338
  case 47:
110
339
  case 62:
111
- a.includes("=") || (a = `${a}=on${a[0].toUpperCase()}${a.slice(1)}($event)`), o = {
112
- state: r.TAG_BODY,
340
+ if (!event.includes("=")) event = `${event}=on${event[0].toUpperCase()}${event.slice(1)}($event)`;
341
+ retVal = {
342
+ state: LexerState.TAG_BODY,
113
343
  tokens: [{
114
- type: i.EVENT,
115
- parts: [a]
344
+ type: TokenType.EVENT,
345
+ parts: [event]
116
346
  }]
117
- }, n = !1;
347
+ };
348
+ read = false;
118
349
  break;
119
- default: e.advance(), a = `${a}${e.currentChar.value}`;
350
+ default:
351
+ cursor.advance();
352
+ event = `${event}${cursor.currentChar.value}`;
120
353
  }
121
- return o;
354
+ return retVal;
122
355
  }
123
356
  //#endregion
124
357
  //#region ../packages/compiler/src/lexer/states/flow-control-block.state.ts
125
- function d(e, t) {
126
- if (e.skipSpaces(), e.peek() !== 123) throw Error(`Expected '{' but got '${String.fromCharCode(e.peek())}' at row ${e.position.row}, col ${e.position.column}`);
127
- return e.advance(), {
128
- state: r.TEXT,
129
- tokens: [{ type: i.BLOCK_OPEN }],
130
- pushState: !0
358
+ /**
359
+ * Consumes the opening `{` of a flow control block body,
360
+ * skipping any leading whitespace before it.
361
+ *
362
+ * Emits a BLOCK_OPEN token and transitions to TEXT,
363
+ * pushing FLOW_CONTROL_BLOCK onto the state stack.
364
+ * This allows consumeText to later recognise the matching `}` as a BLOCK_CLOSE
365
+ * rather than as an interpolation boundary.
366
+ *
367
+ * Used by: @if, @for, @switch, @case, @else, @default
368
+ */
369
+ function consumeFlowControlBlock(cursor, _context) {
370
+ cursor.skipSpaces();
371
+ if (cursor.peek() !== 123) throw new Error(`Expected '{' but got '${String.fromCharCode(cursor.peek())}' at row ${cursor.position.row}, col ${cursor.position.column}`);
372
+ cursor.advance();
373
+ return {
374
+ state: LexerState.TEXT,
375
+ tokens: [{ type: TokenType.BLOCK_OPEN }],
376
+ pushState: true
131
377
  };
132
378
  }
133
379
  //#endregion
134
380
  //#region ../packages/compiler/src/lexer/states/default-flow-control-condition.state.ts
135
- function f(e, t) {
381
+ /**
382
+ * Consumes the condition expression `(...)` of a flow-control directive,
383
+ * handling nested parentheses correctly. Emits a CONDITION token with the
384
+ * raw expression string and transitions to FLOW_CONTROL_BLOCK.
385
+ *
386
+ * @param cursor The lexer cursor positioned at the opening `(`.
387
+ * @param _context Unused lexer context.
388
+ * @returns Transition result with the CONDITION token and the FLOW_CONTROL_BLOCK state.
389
+ */
390
+ function consumeDefaultFlowControlCondition(cursor, _context) {
136
391
  return {
137
- state: r.FLOW_CONTROL_BLOCK,
392
+ state: LexerState.FLOW_CONTROL_BLOCK,
138
393
  tokens: [{
139
- type: i.CONDITION,
140
- parts: [o(e, t)]
394
+ type: TokenType.CONDITION,
395
+ parts: [consumeFlowControlCondition(cursor, _context)]
141
396
  }],
142
- popState: !0
397
+ popState: true
143
398
  };
144
399
  }
145
400
  //#endregion
146
401
  //#region ../packages/compiler/src/lexer/states/flow-control.ts
147
- function p(e, t) {
148
- let n;
149
- return e.advance(), e.peekMatch("for ") ? (e.advance(4), n = {
150
- state: r.FLOW_CONTROL_CONDITION,
151
- tokens: [{ type: i.FOR }],
152
- pushState: !0
153
- }) : e.peekMatch("if ") ? (e.advance(2), n = {
154
- state: r.FLOW_CONTROL_CONDITION,
155
- tokens: [{ type: i.IF }],
156
- pushState: !0
157
- }) : e.peekMatch("else if ") ? (e.advance(8), n = {
158
- state: r.FLOW_CONTROL_CONDITION,
159
- tokens: [{ type: i.ELSE_IF }],
160
- pushState: !0
161
- }) : e.peekMatch("else ") ? (e.advance(5), n = {
162
- state: r.FLOW_CONTROL_BLOCK,
163
- tokens: [{ type: i.ELSE }]
164
- }) : e.peekMatch("switch ") ? (e.advance(7), n = {
165
- state: r.FLOW_CONTROL_CONDITION,
166
- tokens: [{ type: i.SWITCH }],
167
- pushState: !0
168
- }) : e.peekMatch("case ") ? (e.advance(5), n = {
169
- state: r.CASE_FLOW_CONTROL_CONDITION,
170
- tokens: [{ type: i.CASE }],
171
- pushState: !0
172
- }) : e.peekMatch("default ") ? (e.advance(8), n = {
173
- state: r.FLOW_CONTROL_BLOCK,
174
- tokens: [{ type: i.DEFAULT }]
175
- }) : e.peekMatch("const ") && (e.advance(6), n = { state: r.CONST_DECLARATION }), n;
402
+ /**
403
+ * Dispatches on a `@keyword` to determine which flow-control directive begins here.
404
+ * Recognises `@if`, `@for`, `@else`, `@switch`, `@case`, `@default`, and `@const`.
405
+ * Advances the cursor past the keyword and transitions to the appropriate next state.
406
+ *
407
+ * @param cursor The lexer cursor positioned on the `@` character.
408
+ * @param _context Unused lexer context.
409
+ * @returns Transition result with the matching flow-control token and next state.
410
+ */
411
+ function consumeFlowControl(cursor, _context) {
412
+ let retVal;
413
+ cursor.advance();
414
+ if (cursor.peekMatch("for ")) {
415
+ cursor.advance(4);
416
+ retVal = {
417
+ state: LexerState.FLOW_CONTROL_CONDITION,
418
+ tokens: [{ type: TokenType.FOR }],
419
+ pushState: true
420
+ };
421
+ } else if (cursor.peekMatch("if ")) {
422
+ cursor.advance(2);
423
+ retVal = {
424
+ state: LexerState.FLOW_CONTROL_CONDITION,
425
+ tokens: [{ type: TokenType.IF }],
426
+ pushState: true
427
+ };
428
+ } else if (cursor.peekMatch("else if ")) {
429
+ cursor.advance(8);
430
+ retVal = {
431
+ state: LexerState.FLOW_CONTROL_CONDITION,
432
+ tokens: [{ type: TokenType.ELSE_IF }],
433
+ pushState: true
434
+ };
435
+ } else if (cursor.peekMatch("else ")) {
436
+ cursor.advance(5);
437
+ retVal = {
438
+ state: LexerState.FLOW_CONTROL_BLOCK,
439
+ tokens: [{ type: TokenType.ELSE }]
440
+ };
441
+ } else if (cursor.peekMatch("switch ")) {
442
+ cursor.advance(7);
443
+ retVal = {
444
+ state: LexerState.FLOW_CONTROL_CONDITION,
445
+ tokens: [{ type: TokenType.SWITCH }],
446
+ pushState: true
447
+ };
448
+ } else if (cursor.peekMatch("case ")) {
449
+ cursor.advance(5);
450
+ retVal = {
451
+ state: LexerState.CASE_FLOW_CONTROL_CONDITION,
452
+ tokens: [{ type: TokenType.CASE }],
453
+ pushState: true
454
+ };
455
+ } else if (cursor.peekMatch("default ")) {
456
+ cursor.advance(8);
457
+ retVal = {
458
+ state: LexerState.FLOW_CONTROL_BLOCK,
459
+ tokens: [{ type: TokenType.DEFAULT }]
460
+ };
461
+ } else if (cursor.peekMatch("const ")) {
462
+ cursor.advance(6);
463
+ retVal = { state: LexerState.CONST_DECLARATION };
464
+ }
465
+ return retVal;
176
466
  }
177
467
  //#endregion
178
468
  //#region ../packages/compiler/src/lexer/states/interpolation-expression.state.ts
179
- function m(e, t) {
180
- let n = !0, a = "", o = 1, s;
181
- for (; n;) switch (e.peek()) {
469
+ /**
470
+ * Consumes a JavaScript expression interpolation `{ expression }`, tracking nested
471
+ * brace depth. Emits an INTERPOLATION_EXPRESSION token and pops the state stack to
472
+ * return to the previous state (ATTRIBUTE or TEXT).
473
+ *
474
+ * @param cursor The lexer cursor positioned at the first character of the expression.
475
+ * @param context Lexer context used to retrieve the previous state for restoration.
476
+ * @returns Transition result with the INTERPOLATION_EXPRESSION token and restored state.
477
+ */
478
+ function consumeInterpolationExpression(cursor, context) {
479
+ let read = true;
480
+ let interpolation = "";
481
+ let deep = 1;
482
+ let retVal;
483
+ while (read) switch (cursor.peek()) {
182
484
  case 123:
183
- o++, a = h(e, a);
485
+ deep++;
486
+ interpolation = addCharacter$1(cursor, interpolation);
184
487
  break;
185
488
  case 125:
186
- if (o--, o === 0) {
187
- e.advance();
188
- let o = t.history.pop(), c;
189
- switch (o) {
190
- case r.ATTRIBUTE:
191
- let e = t.tokens[t.tokens.length - 1];
192
- e?.type === i.ATTRIBUTE && !e.parts[0] && (e.parts[0] = `${a}=`), c = r.TAG_BODY;
489
+ deep--;
490
+ if (deep === 0) {
491
+ cursor.advance();
492
+ const previousState = context.history.pop();
493
+ let state;
494
+ switch (previousState) {
495
+ case LexerState.ATTRIBUTE:
496
+ const lastToken = context.tokens[context.tokens.length - 1];
497
+ if (lastToken?.type === TokenType.ATTRIBUTE && !lastToken.parts[0]) lastToken.parts[0] = `${interpolation}=`;
498
+ state = LexerState.TAG_BODY;
193
499
  break;
194
- case r.TEXT: c = r.TEXT;
500
+ case LexerState.TEXT: state = LexerState.TEXT;
195
501
  }
196
- s = {
197
- state: c,
502
+ retVal = {
503
+ state,
198
504
  tokens: [{
199
- type: i.INTERPOLATION_EXPRESSION,
200
- parts: [a]
505
+ type: TokenType.INTERPOLATION_EXPRESSION,
506
+ parts: [interpolation]
201
507
  }],
202
- popState: !0
203
- }, n = !1;
204
- } else a = h(e, a);
508
+ popState: true
509
+ };
510
+ read = false;
511
+ } else interpolation = addCharacter$1(cursor, interpolation);
205
512
  break;
206
- default: a = h(e, a);
513
+ default: interpolation = addCharacter$1(cursor, interpolation);
207
514
  }
208
- return s;
515
+ return retVal;
209
516
  }
210
- function h(e, t) {
211
- return e.advance(1), `${t}${e.currentChar.value}`;
517
+ /**
518
+ * Advances the cursor by one character and appends it to the accumulator string.
519
+ *
520
+ * @param cursor The lexer cursor to advance.
521
+ * @param interpolation The current accumulated string.
522
+ * @returns The updated string with the new character appended.
523
+ */
524
+ function addCharacter$1(cursor, interpolation) {
525
+ cursor.advance(1);
526
+ return `${interpolation}${cursor.currentChar.value}`;
212
527
  }
213
528
  //#endregion
214
529
  //#region ../packages/compiler/src/lexer/states/interpolation-literal.state.ts
215
- function ee(e, t) {
216
- let n = !0, a = "`", o;
217
- for (e.advance(); n;) switch (e.peek()) {
530
+ /**
531
+ * Consumes a template-literal interpolation `` {`...`} ``, collecting characters
532
+ * until the closing backtick followed by `}`. Emits an INTERPOLATION_LITERAL token
533
+ * and pops the state stack to return to the previous state.
534
+ *
535
+ * @param cursor The lexer cursor positioned at the opening backtick.
536
+ * @param context Lexer context used to retrieve the previous state for restoration.
537
+ * @returns Transition result with the INTERPOLATION_LITERAL token and restored state.
538
+ */
539
+ function consumeInterpolationliteral(cursor, context) {
540
+ let read = true;
541
+ let interpolation = "`";
542
+ let retVal;
543
+ cursor.advance();
544
+ while (read) switch (cursor.peek()) {
218
545
  case 96:
219
- if (a = g(e, a), e.peek() === 125) {
220
- e.advance();
221
- let s = t.history.pop(), c;
222
- switch (s) {
223
- case r.ATTRIBUTE:
224
- c = r.TAG_BODY;
546
+ interpolation = addCharacter(cursor, interpolation);
547
+ if (cursor.peek() === 125) {
548
+ cursor.advance();
549
+ const previousState = context.history.pop();
550
+ let state;
551
+ switch (previousState) {
552
+ case LexerState.ATTRIBUTE:
553
+ state = LexerState.TAG_BODY;
225
554
  break;
226
- case r.TEXT: c = r.TEXT;
555
+ case LexerState.TEXT: state = LexerState.TEXT;
227
556
  }
228
- o = {
229
- state: c,
557
+ retVal = {
558
+ state,
230
559
  tokens: [{
231
- type: i.INTERPOLATION_LITERAL,
232
- parts: [a]
560
+ type: TokenType.INTERPOLATION_LITERAL,
561
+ parts: [interpolation]
233
562
  }],
234
- popState: !0
235
- }, n = !1;
236
- } else a = `${a}${e.currentChar.value}`;
563
+ popState: true
564
+ };
565
+ read = false;
566
+ } else interpolation = `${interpolation}${cursor.currentChar.value}`;
237
567
  break;
238
- default: a = g(e, a);
568
+ default: interpolation = addCharacter(cursor, interpolation);
239
569
  }
240
- return o;
570
+ return retVal;
241
571
  }
242
- function g(e, t) {
243
- return e.advance(), `${t}${e.currentChar.value}`;
572
+ /**
573
+ * Advances the cursor by one character and appends it to the accumulator string.
574
+ *
575
+ * @param cursor The lexer cursor to advance.
576
+ * @param interpolation The current accumulated string.
577
+ * @returns The updated string with the new character appended.
578
+ */
579
+ function addCharacter(cursor, interpolation) {
580
+ cursor.advance();
581
+ return `${interpolation}${cursor.currentChar.value}`;
244
582
  }
245
583
  //#endregion
246
584
  //#region ../packages/compiler/src/utils/chars.utils.ts
247
- function te(e) {
248
- return /\S/.test(e);
585
+ /**
586
+ * Check if the string contains at least one character different from
587
+ * ' '
588
+ * \n
589
+ * \r
590
+ * \t
591
+ * \f
592
+ * \v
593
+ * @param str String to check
594
+ * @returns True if string is not blank, false otherwise
595
+ */
596
+ function isNotBlank(str) {
597
+ return /\S/.test(str);
249
598
  }
250
- function ne(e) {
251
- return e >= 65 && e <= 90 || e >= 97 && e <= 122 || e === 36 || e === 95;
599
+ /**
600
+ * Check if given ascii code is a valid First Character
601
+ * for Javasript Identifiers
602
+ * @param code The ascii code to valuate
603
+ * @returns True if is valid, false otherwise
604
+ */
605
+ function isJSIdentifierStart(code) {
606
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 36 || code === 95;
252
607
  }
253
608
  //#endregion
254
609
  //#region ../packages/compiler/src/lexer/states/interpolation.state.ts
255
- function _(e, t) {
256
- let n;
257
- e.advance(), e.skipSpaces();
258
- let i = e.peek();
259
- if (i === 96) n = { state: r.INTERPOLATION_LITERAL };
260
- else if (ne(i)) n = { state: r.INTERPOLATION_EXPRESSION };
261
- else throw Error(`Unrecognized First Character ${String.fromCharCode(i)} in interpolation`);
262
- return n;
610
+ /**
611
+ * Dispatches between an expression and a literal interpolation after the opening `{`.
612
+ * Advances past `{` and any leading spaces, then inspects the next character:
613
+ * a backtick routes to INTERPOLATION_LITERAL, a JS identifier start routes to INTERPOLATION_EXPRESSION.
614
+ *
615
+ * @param cursor The lexer cursor positioned on the `{` character.
616
+ * @param _context Unused lexer context.
617
+ * @returns Transition result with the appropriate interpolation sub-state.
618
+ */
619
+ function consumeInterpolation(cursor, _context) {
620
+ let retVal;
621
+ cursor.advance();
622
+ cursor.skipSpaces();
623
+ const nextChar = cursor.peek();
624
+ if (nextChar === 96) retVal = { state: LexerState.INTERPOLATION_LITERAL };
625
+ else if (isJSIdentifierStart(nextChar)) retVal = { state: LexerState.INTERPOLATION_EXPRESSION };
626
+ else throw new Error(`Unrecognized First Character ${String.fromCharCode(nextChar)} in interpolation`);
627
+ return retVal;
263
628
  }
264
629
  //#endregion
265
630
  //#region ../packages/compiler/src/lexer/states/tag-body.state.ts
266
- function v(e, t) {
267
- let n = !0, i;
268
- for (; n;) switch (e.peek()) {
631
+ /**
632
+ * Scans the body of an open tag to determine what comes next:
633
+ * an event binding (`@`), an attribute, the end of the tag (`>` or `/`), or whitespace.
634
+ * Transitions to the appropriate state without emitting any tokens.
635
+ *
636
+ * @param cursor The lexer cursor positioned inside a tag body.
637
+ * @param _context Unused lexer context.
638
+ * @returns Transition result with the next state and no tokens.
639
+ */
640
+ function consumeTagBody(cursor, _context) {
641
+ let read = true;
642
+ let retVal;
643
+ while (read) switch (cursor.peek()) {
269
644
  case 64:
270
- i = { state: r.EVENT }, n = !1;
645
+ retVal = { state: LexerState.EVENT };
646
+ read = false;
271
647
  break;
272
648
  case 32:
273
- e.skipSpaces();
649
+ cursor.skipSpaces();
274
650
  break;
275
651
  case 62:
276
652
  case 47:
277
- i = { state: r.TAG_OPEN_END }, n = !1;
653
+ retVal = { state: LexerState.TAG_OPEN_END };
654
+ read = false;
278
655
  break;
279
- default: i = { state: r.ATTRIBUTE }, n = !1;
656
+ default:
657
+ retVal = { state: LexerState.ATTRIBUTE };
658
+ read = false;
280
659
  }
281
- return i;
660
+ return retVal;
282
661
  }
283
662
  //#endregion
284
663
  //#region ../packages/compiler/src/lexer/states/tag-close.state.ts
285
- function y(e, t) {
286
- let n = !0, a = "", o;
287
- for (e.advance(2), e.skipSpaces(); n;) switch (e.peek()) {
664
+ /**
665
+ * Consumes a closing tag `</tagName>`, skipping the `</` prefix and any surrounding
666
+ * whitespace. Emits a TAG_CLOSE_NAME token with the tag name and transitions to TEXT.
667
+ *
668
+ * @param cursor The lexer cursor positioned at the `<` of a closing tag.
669
+ * @param _context Unused lexer context.
670
+ * @returns Transition result with the TAG_CLOSE_NAME token and the TEXT state.
671
+ */
672
+ function consumeTagClose(cursor, _context) {
673
+ let read = true;
674
+ let tagName = "";
675
+ let retVal;
676
+ cursor.advance(2);
677
+ cursor.skipSpaces();
678
+ while (read) switch (cursor.peek()) {
288
679
  case 62:
289
- e.advance(), o = {
290
- state: r.TEXT,
680
+ cursor.advance();
681
+ retVal = {
682
+ state: LexerState.TEXT,
291
683
  tokens: [{
292
- type: i.TAG_CLOSE_NAME,
293
- parts: [a]
684
+ type: TokenType.TAG_CLOSE_NAME,
685
+ parts: [tagName]
294
686
  }]
295
- }, n = !1;
687
+ };
688
+ read = false;
296
689
  break;
297
- case 32: throw Error("Tag Close Name cannot contains spaces");
298
- default: e.advance(), a = `${a}${e.currentChar.value}`;
690
+ case 32: throw new Error("Tag Close Name cannot contains spaces");
691
+ default:
692
+ cursor.advance();
693
+ tagName = `${tagName}${cursor.currentChar.value}`;
299
694
  }
300
- return o;
695
+ return retVal;
301
696
  }
302
697
  //#endregion
303
698
  //#region ../packages/compiler/src/lexer/states/tag-open-end.state.ts
304
- function b(e, t) {
305
- let n;
306
- if (e.peek() === 62) e.advance(), n = {
307
- state: r.TEXT,
308
- tokens: [{
309
- type: i.TAG_OPEN_END,
310
- parts: []
311
- }]
312
- };
313
- else {
314
- e.advance();
315
- let t = e.peek();
316
- if (t === 62) e.advance(), n = {
317
- state: r.TEXT,
699
+ /**
700
+ * Consumes the closing characters of an open tag: `>` emits TAG_OPEN_END and
701
+ * transitions to TEXT, while `/>` emits TAG_SELF_CLOSE and also transitions to TEXT.
702
+ *
703
+ * @param cursor The lexer cursor positioned at `>` or `/`.
704
+ * @param _context Unused lexer context.
705
+ * @returns Transition result with TAG_OPEN_END or TAG_SELF_CLOSE and the TEXT state.
706
+ */
707
+ function consumeTagOpenEnd(cursor, _context) {
708
+ let retVal;
709
+ if (cursor.peek() === 62) {
710
+ cursor.advance();
711
+ retVal = {
712
+ state: LexerState.TEXT,
318
713
  tokens: [{
319
- type: i.TAG_SELF_CLOSE,
714
+ type: TokenType.TAG_OPEN_END,
320
715
  parts: []
321
716
  }]
322
717
  };
323
- else throw Error(`Unexpected character ${t} for closing tag.\nExpected />\nRead of /${String.fromCharCode(t)}\nAt line ${e.position.row + 1} col ${e.position.column + 1}`);
718
+ } else {
719
+ cursor.advance();
720
+ const nextChar = cursor.peek();
721
+ if (nextChar === 62) {
722
+ cursor.advance();
723
+ retVal = {
724
+ state: LexerState.TEXT,
725
+ tokens: [{
726
+ type: TokenType.TAG_SELF_CLOSE,
727
+ parts: []
728
+ }]
729
+ };
730
+ } else throw new Error(`Unexpected character ${nextChar} for closing tag.\nExpected />\nRead of /${String.fromCharCode(nextChar)}\nAt line ${cursor.position.row + 1} col ${cursor.position.column + 1}`);
324
731
  }
325
- return n;
732
+ return retVal;
326
733
  }
327
734
  //#endregion
328
735
  //#region ../packages/compiler/src/lexer/states/tag-open-name.state.ts
329
- function x(e, t) {
330
- let n = !0, a = "", o;
331
- for (e.advance(), e.skipSpaces(); n;) switch (e.peek()) {
736
+ /**
737
+ * Consumes an opening tag name after `<`, reading until a space, `/`, or `>` is found.
738
+ * Emits a TAG_OPEN_NAME token with the tag name and transitions to TAG_BODY.
739
+ *
740
+ * @param cursor The lexer cursor positioned at the `<` character.
741
+ * @param _context Unused lexer context.
742
+ * @returns Transition result with the TAG_OPEN_NAME token and the TAG_BODY state.
743
+ */
744
+ function consumeTagOpenName(cursor, _context) {
745
+ let read = true;
746
+ let tagName = "";
747
+ let retVal;
748
+ cursor.advance();
749
+ cursor.skipSpaces();
750
+ while (read) switch (cursor.peek()) {
332
751
  case 32:
333
752
  case 47:
334
753
  case 62:
335
- o = {
336
- state: r.TAG_BODY,
754
+ retVal = {
755
+ state: LexerState.TAG_BODY,
337
756
  tokens: [{
338
- type: i.TAG_OPEN_NAME,
339
- parts: [a]
757
+ type: TokenType.TAG_OPEN_NAME,
758
+ parts: [tagName]
340
759
  }]
341
- }, n = !1;
760
+ };
761
+ read = false;
342
762
  break;
343
- default: e.advance(), a = `${a}${e.currentChar.value}`;
763
+ default:
764
+ cursor.advance();
765
+ tagName = `${tagName}${cursor.currentChar.value}`;
344
766
  }
345
- return o;
767
+ return retVal;
346
768
  }
347
769
  //#endregion
348
770
  //#region ../packages/compiler/src/lexer/states/text.state.ts
349
- function S(e, t) {
350
- let n = !0, a = "", o;
351
- for (; n;) switch (e.peek()) {
771
+ /**
772
+ * Consumes plain text content, accumulating characters until a structural boundary
773
+ * is reached: `<` (tag open/close), `{` (interpolation), `@` (flow-control or event),
774
+ * or `}` (block close). Emits a TEXT token if non-blank text was accumulated.
775
+ *
776
+ * @param cursor The lexer cursor positioned at the start of text content.
777
+ * @param context Lexer context used to detect flow-control block boundaries.
778
+ * @returns Transition result with an optional TEXT token and the next state.
779
+ */
780
+ function consumeText(cursor, context) {
781
+ let read = true;
782
+ let text = "";
783
+ let retVal;
784
+ while (read) switch (cursor.peek()) {
352
785
  case 60:
353
- o = { state: e.peek(1, { offset: 1 }) === 47 ? r.TAG_CLOSE : r.TAG_OPEN_NAME }, n = !1;
786
+ retVal = { state: cursor.peek(1, { offset: 1 }) === 47 ? LexerState.TAG_CLOSE : LexerState.TAG_OPEN_NAME };
787
+ read = false;
354
788
  break;
355
789
  case 123:
356
- o = {
357
- state: r.INTERPOLATION,
358
- pushState: !0
359
- }, n = !1;
790
+ retVal = {
791
+ state: LexerState.INTERPOLATION,
792
+ pushState: true
793
+ };
794
+ read = false;
360
795
  break;
361
796
  case 64:
362
- o = { state: r.FLOW_CONTROL }, n = !1;
797
+ retVal = { state: LexerState.FLOW_CONTROL };
798
+ read = false;
363
799
  break;
364
800
  case 125:
365
- t.history[t.history.length - 1] === r.FLOW_CONTROL_BLOCK ? (e.advance(), o = {
366
- state: r.TEXT,
367
- tokens: [{ type: i.BLOCK_CLOSE }],
368
- popState: !0
369
- }, n = !1) : (e.advance(), a = `${a}${e.currentChar.value}`);
801
+ if (context.history[context.history.length - 1] === LexerState.FLOW_CONTROL_BLOCK) {
802
+ cursor.advance();
803
+ retVal = {
804
+ state: LexerState.TEXT,
805
+ tokens: [{ type: TokenType.BLOCK_CLOSE }],
806
+ popState: true
807
+ };
808
+ read = false;
809
+ } else {
810
+ cursor.advance();
811
+ text = `${text}${cursor.currentChar.value}`;
812
+ }
370
813
  break;
371
814
  case 10:
372
815
  case 13:
373
- e.advance();
816
+ cursor.advance();
374
817
  break;
375
- default: e.advance(), a = `${a}${e.currentChar.value}`;
818
+ default:
819
+ cursor.advance();
820
+ text = `${text}${cursor.currentChar.value}`;
376
821
  }
377
- return o.tokens ??= te(a) ? [{
378
- type: i.TEXT,
379
- parts: [a]
380
- }] : void 0, o;
822
+ retVal.tokens ??= isNotBlank(text) ? [{
823
+ type: TokenType.TEXT,
824
+ parts: [text]
825
+ }] : void 0;
826
+ return retVal;
381
827
  }
382
828
  //#endregion
383
829
  //#region ../packages/compiler/src/lexer/types/lexer-cursor.model.ts
384
- var re = class {
830
+ /**
831
+ * Cursor abstraction used by the Lexer to navigate the input source.
832
+ *
833
+ * The LexerCursor is responsible for:
834
+ * - Sequential character consumption
835
+ * - Lookahead (peek) operations without state mutation
836
+ * - Tracking logical position (row, column)
837
+ * - Handling end-of-file conditions
838
+ *
839
+ * This class deliberately contains **no lexer logic**:
840
+ * it does not know about tokens, states, or grammar rules.
841
+ * Its sole responsibility is controlled navigation of the input stream.
842
+ */
843
+ var LexerCursor = class {
385
844
  input;
845
+ /**
846
+ * Representation of the current character.
847
+ *
848
+ * - `index`: absolute index within the input string
849
+ * - `code`: Unicode code point of the character
850
+ * - `value`: actual character value
851
+ *
852
+ * An index of `-1` indicates that the cursor has not yet consumed
853
+ * any character or has reached EOF.
854
+ */
386
855
  _currentChar = {
387
856
  code: 0,
388
857
  index: -1,
389
858
  value: ""
390
859
  };
860
+ /**
861
+ * Returns a read-only snapshot of the current character.
862
+ */
391
863
  get currentChar() {
392
864
  return this._currentChar;
393
865
  }
866
+ /**
867
+ * Cache used by peek operations to avoid re-reading
868
+ * the same character positions multiple times.
869
+ *
870
+ * Key: absolute character index
871
+ * Value: Unicode code point
872
+ */
394
873
  _peekCache = /* @__PURE__ */ new Map();
874
+ /**
875
+ * Logical position of the cursor in the input.
876
+ *
877
+ * - `row`: zero-based line number
878
+ * - `column`: zero-based column number
879
+ */
395
880
  _position = {
396
881
  row: 0,
397
882
  column: 0
398
883
  };
884
+ /**
885
+ * Returns a read-only snapshot of the current cursor position.
886
+ */
399
887
  get position() {
400
888
  return this._position;
401
889
  }
402
- constructor(e) {
403
- this.input = e;
890
+ /**
891
+ * Creates a new cursor for the given input source.
892
+ *
893
+ * @param input Full source string to be tokenized.
894
+ */
895
+ constructor(input) {
896
+ this.input = input;
404
897
  }
405
- advance(e = 1) {
406
- if (e < 1) throw Error(`${e} is not a valid value. Please enter a number equal or greater than 1`);
407
- let t = this._currentChar.index + e;
408
- t >= this.input.length ? (this._currentChar.code = 0, this._currentChar.index = -1, this._currentChar.value = "", this.throwEOFError()) : ([10, 13].includes(this._currentChar.code) ? (this._position.row++, this._position.column = 0) : this._position.column++, this._currentChar.index = t, this._currentChar.value = this.input[t], this._currentChar.code = this.input.charCodeAt(t));
898
+ /**
899
+ * Advances the cursor by the specified number of characters.
900
+ *
901
+ * This method:
902
+ * - Updates the current character
903
+ * - Updates row/column position
904
+ * - Detects line breaks (LF / CR)
905
+ * - Throws an EOF error when the end of the input is reached
906
+ *
907
+ * @param chars Number of characters to consume (must be >= 1)
908
+ *
909
+ * @throws Error with cause `EOF` when advancing past input length
910
+ */
911
+ advance(chars = 1) {
912
+ if (chars < 1) throw new Error(`${chars} is not a valid value. Please enter a number equal or greater than 1`);
913
+ const newIndex = this._currentChar.index + chars;
914
+ if (newIndex >= this.input.length) {
915
+ this._currentChar.code = 0;
916
+ this._currentChar.index = -1;
917
+ this._currentChar.value = "";
918
+ this.throwEOFError();
919
+ } else {
920
+ if ([10, 13].includes(this._currentChar.code)) {
921
+ this._position.row++;
922
+ this._position.column = 0;
923
+ } else this._position.column++;
924
+ this._currentChar.index = newIndex;
925
+ this._currentChar.value = this.input[newIndex];
926
+ this._currentChar.code = this.input.charCodeAt(newIndex);
927
+ }
409
928
  }
410
- peekMatch(e, t) {
411
- if (typeof e == "string") {
412
- let t = this.peek(e.length);
413
- for (let n = 0; n < e.length; n++) if (t[n] !== e.charCodeAt(n)) return !1;
414
- return !0;
929
+ peekMatch(pattern, length) {
930
+ if (typeof pattern === "string") {
931
+ const peekedChars = this.peek(pattern.length);
932
+ for (let i = 0; i < pattern.length; i++) if (peekedChars[i] !== pattern.charCodeAt(i)) return false;
933
+ return true;
415
934
  }
416
- let n = this._currentChar.index + 1, r = this.input.slice(n, n + t);
417
- return e.test(r);
935
+ const start = this._currentChar.index + 1;
936
+ const slice = this.input.slice(start, start + length);
937
+ return pattern.test(slice);
418
938
  }
419
- peek(e, t) {
420
- let n = this._peekCache, r = typeof e == "number" ? e : 1, i = (typeof e == "object" ? e : t)?.offset ?? 0;
421
- return r === 1 ? this.peekOneChar(this._currentChar.index + i + 1, n) : this.peekMany(r + i, n);
939
+ peek(charsOrOptions, options) {
940
+ const cache = this._peekCache;
941
+ const chars = typeof charsOrOptions === "number" ? charsOrOptions : 1;
942
+ const offset = (typeof charsOrOptions === "object" ? charsOrOptions : options)?.offset ?? 0;
943
+ return chars === 1 ? this.peekOneChar(this._currentChar.index + offset + 1, cache) : this.peekMany(chars + offset, cache);
422
944
  }
945
+ /**
946
+ * Skips all consecutive space characters from the current position.
947
+ */
423
948
  skipSpaces() {
424
- for (; this.peek() === 32 || this.peek() === 10 || this.peek() === 13;) this.advance();
949
+ while (this.peek() === 32 || this.peek() === 10 || this.peek() === 13) this.advance();
425
950
  }
426
- peekMany(e, t) {
427
- let n = [], r = this._currentChar.index + 1;
428
- for (let i = r; i < r + e; i++) n.push(this.peekOneChar(i, t));
429
- return n;
951
+ /**
952
+ * Peeks multiple characters ahead.
953
+ */
954
+ peekMany(chars, cache) {
955
+ const peekedChars = new Array();
956
+ const nextCharIndex = this._currentChar.index + 1;
957
+ for (let i = nextCharIndex; i < nextCharIndex + chars; i++) peekedChars.push(this.peekOneChar(i, cache));
958
+ return peekedChars;
430
959
  }
431
- peekOneChar(e, t) {
432
- if (t.has(e)) return t.get(e);
433
- e >= this.input.length && this.throwEOFError();
434
- let n = this.input.charCodeAt(e);
435
- return t.set(e, n), n;
960
+ /**
961
+ * Peeks a single character at the given absolute index.
962
+ */
963
+ peekOneChar(index, cache) {
964
+ if (cache.has(index)) return cache.get(index);
965
+ if (index >= this.input.length) this.throwEOFError();
966
+ const charCode = this.input.charCodeAt(index);
967
+ cache.set(index, charCode);
968
+ return charCode;
436
969
  }
970
+ /**
971
+ * Throws a standardized EOF error used by the lexer engine
972
+ * to terminate tokenization.
973
+ */
437
974
  throwEOFError() {
438
- throw Error("", { cause: 0 });
975
+ throw new Error("", { cause: 0 });
439
976
  }
440
- }, ie = class {
977
+ };
978
+ //#endregion
979
+ //#region ../packages/compiler/src/lexer/lexer.ts
980
+ /**
981
+ * Utility class that emulates a cursor navigating through a template string.
982
+ *
983
+ * The cursor keeps track of the current character, its absolute position
984
+ * within the text, and its logical position expressed as row and column.
985
+ * This is useful when parsing or analyzing template content character by character.
986
+ */
987
+ var Lexer = class {
441
988
  input;
989
+ /**
990
+ * Cursor for navigating the input character stream.
991
+ */
442
992
  _cursor;
443
- _state = r.START;
444
- _stack = new e();
445
- _tokens = [];
993
+ /**
994
+ * Current lexer state.
995
+ */
996
+ _state = LexerState.START;
997
+ /**
998
+ * State stack used to support nested states (e.g. interpolations).
999
+ */
1000
+ _stack = new Stack();
1001
+ /**
1002
+ * Accumulated list of tokens emitted during tokenization.
1003
+ */
1004
+ _tokens = new Array();
1005
+ /**
1006
+ * Maps each lexer state to its corresponding transition function.
1007
+ */
446
1008
  _states = {
447
- [r.START]: S,
448
- [r.TEXT]: S,
449
- [r.TAG_OPEN_NAME]: x,
450
- [r.TAG_BODY]: v,
451
- [r.TAG_OPEN_END]: b,
452
- [r.TAG_CLOSE]: y,
453
- [r.ATTRIBUTE]: a,
454
- [r.FLOW_CONTROL]: p,
455
- [r.FLOW_CONTROL_CONDITION]: f,
456
- [r.CASE_FLOW_CONTROL_CONDITION]: c,
457
- [r.FLOW_CONTROL_BLOCK]: d,
458
- [r.EVENT]: u,
459
- [r.INTERPOLATION]: _,
460
- [r.INTERPOLATION_EXPRESSION]: m,
461
- [r.INTERPOLATION_LITERAL]: ee,
462
- [r.CONST_DECLARATION]: l
1009
+ [LexerState.START]: consumeText,
1010
+ [LexerState.TEXT]: consumeText,
1011
+ [LexerState.TAG_OPEN_NAME]: consumeTagOpenName,
1012
+ [LexerState.TAG_BODY]: consumeTagBody,
1013
+ [LexerState.TAG_OPEN_END]: consumeTagOpenEnd,
1014
+ [LexerState.TAG_CLOSE]: consumeTagClose,
1015
+ [LexerState.ATTRIBUTE]: consumeAttribute,
1016
+ [LexerState.FLOW_CONTROL]: consumeFlowControl,
1017
+ [LexerState.FLOW_CONTROL_CONDITION]: consumeDefaultFlowControlCondition,
1018
+ [LexerState.CASE_FLOW_CONTROL_CONDITION]: consumeCaseFlowControlCondition,
1019
+ [LexerState.FLOW_CONTROL_BLOCK]: consumeFlowControlBlock,
1020
+ [LexerState.EVENT]: consumeEvent,
1021
+ [LexerState.INTERPOLATION]: consumeInterpolation,
1022
+ [LexerState.INTERPOLATION_EXPRESSION]: consumeInterpolationExpression,
1023
+ [LexerState.INTERPOLATION_LITERAL]: consumeInterpolationliteral,
1024
+ [LexerState.CONST_DECLARATION]: consumeConstDeclaration
463
1025
  };
464
- constructor(e) {
465
- this.input = e, this._cursor = new re(this.input);
1026
+ /**
1027
+ * Creates a new Cursor instance for the given template content.
1028
+ *
1029
+ * @param input The full template text that the cursor will navigate.
1030
+ */
1031
+ constructor(input) {
1032
+ this.input = input;
1033
+ this._cursor = new LexerCursor(this.input);
466
1034
  }
1035
+ /**
1036
+ * Runs the lexer over the input string and returns the full token array.
1037
+ * Drives the state machine until EOF is reached.
1038
+ *
1039
+ * @returns Array of all tokens produced from the input.
1040
+ */
467
1041
  tokenize() {
468
- let e = !1;
469
- for (; !e;) try {
470
- let e = this._states[this._state], { state: t, tokens: n, popState: r, pushState: i } = e(this._cursor, {
1042
+ let eof = false;
1043
+ while (!eof) try {
1044
+ const transitionFunction = this._states[this._state];
1045
+ const { state, tokens, popState, pushState } = transitionFunction(this._cursor, {
471
1046
  history: this._stack.values,
472
1047
  tokens: [...this._tokens]
473
1048
  });
474
- n?.length && this._tokens.push(...n), i && this._stack.push(this._state), r && this._stack.pop(), this._state = t;
475
- } catch (t) {
476
- if (t.cause === 0) e = !0;
477
- else throw t;
1049
+ if (tokens?.length) this._tokens.push(...tokens);
1050
+ if (pushState) this._stack.push(this._state);
1051
+ if (popState) this._stack.pop();
1052
+ this._state = state;
1053
+ } catch (err) {
1054
+ if (err.cause === 0) eof = true;
1055
+ else throw err;
478
1056
  }
479
1057
  return this._tokens;
480
1058
  }
481
- }, ae = class {
1059
+ };
1060
+ //#endregion
1061
+ //#region ../packages/compiler/src/parser/models/parser-cursor.model.ts
1062
+ /**
1063
+ * Cursor abstraction used by the Parser to navigate
1064
+ * through a sequence of tokens produced by the Lexer.
1065
+ *
1066
+ * Responsibilities:
1067
+ * - Sequential token consumption
1068
+ * - Lookahead (peek) operations without mutating state
1069
+ * - Handling end-of-file conditions
1070
+ *
1071
+ * This class does not perform parsing itself: it only
1072
+ * manages position and access to the token stream.
1073
+ */
1074
+ var ParserCursor = class {
482
1075
  _tokens;
1076
+ /**
1077
+ * Representation of the current token.
1078
+ *
1079
+ * - `index`: absolute index within the token array
1080
+ * - `value`: current token object (or EOF token)
1081
+ *
1082
+ * An index of `-1` indicates that the cursor has not
1083
+ * yet consumed any token or has reached EOF.
1084
+ */
483
1085
  _currentToken = {
484
- value: { type: i.EOF },
1086
+ value: { type: TokenType.EOF },
485
1087
  index: -1
486
1088
  };
1089
+ /**
1090
+ * Returns a read-only snapshot of the current token.
1091
+ */
487
1092
  get currentToken() {
488
1093
  return this._currentToken;
489
1094
  }
490
- constructor(e) {
491
- this._tokens = e;
1095
+ /**
1096
+ * Creates a new ParserCursor for the given token array.
1097
+ *
1098
+ * @param _tokens Array of tokens to navigate.
1099
+ */
1100
+ constructor(_tokens) {
1101
+ this._tokens = _tokens;
492
1102
  }
493
- advance(e = 1) {
494
- if (e < 1) throw Error(`${e} is not a valid value. Please enter a number equal or greater than 1`);
495
- let t = this._currentToken.index + e;
496
- t >= this._tokens.length ? (this._currentToken.value = { type: i.EOF }, this._currentToken.index = -1) : (this._currentToken.index = t, this._currentToken.value = this._tokens[t]);
1103
+ /**
1104
+ * Advances the cursor by the specified number of tokens.
1105
+ *
1106
+ * Updates the current token and index.
1107
+ *
1108
+ * @param chars Number of tokens to advance (must be >= 1)
1109
+ *
1110
+ * @throws Error with cause `EOF` when advancing past the end
1111
+ */
1112
+ advance(chars = 1) {
1113
+ if (chars < 1) throw new Error(`${chars} is not a valid value. Please enter a number equal or greater than 1`);
1114
+ const newIndex = this._currentToken.index + chars;
1115
+ if (newIndex >= this._tokens.length) {
1116
+ this._currentToken.value = { type: TokenType.EOF };
1117
+ this._currentToken.index = -1;
1118
+ } else {
1119
+ this._currentToken.index = newIndex;
1120
+ this._currentToken.value = this._tokens[newIndex];
1121
+ }
497
1122
  }
498
- peek(e, t) {
499
- let n = typeof e == "number" ? e : 1, r = (typeof e == "object" ? e : t)?.offset ?? 0;
500
- return n === 1 ? this.peekOneToken(this._currentToken.index + r + 1) : this.peekMany(n + r);
1123
+ peek(charsOrOptions, options) {
1124
+ const tokens = typeof charsOrOptions === "number" ? charsOrOptions : 1;
1125
+ const offset = (typeof charsOrOptions === "object" ? charsOrOptions : options)?.offset ?? 0;
1126
+ return tokens === 1 ? this.peekOneToken(this._currentToken.index + offset + 1) : this.peekMany(tokens + offset);
501
1127
  }
502
- peekMany(e) {
503
- let t = [], n = this._currentToken.index + 1;
504
- for (let r = n; r < n + e; r++) t.push(this.peekOneToken(r));
505
- return t;
1128
+ /**
1129
+ * Peeks multiple tokens ahead.
1130
+ */
1131
+ peekMany(chars) {
1132
+ const peekedTokens = new Array();
1133
+ const nextTokenIndex = this._currentToken.index + 1;
1134
+ for (let i = nextTokenIndex; i < nextTokenIndex + chars; i++) peekedTokens.push(this.peekOneToken(i));
1135
+ return peekedTokens;
506
1136
  }
507
- peekOneToken(e) {
508
- return e < this._tokens.length ? this._tokens[e] : { type: i.EOF };
1137
+ /**
1138
+ * Peeks a single token at the given absolute index.
1139
+ */
1140
+ peekOneToken(index) {
1141
+ return index < this._tokens.length ? this._tokens[index] : { type: TokenType.EOF };
509
1142
  }
510
- }, C = /* @__PURE__ */ function(e) {
511
- return e[e.Element = 0] = "Element", e[e.Text = 1] = "Text", e[e.Interpolation = 2] = "Interpolation", e[e.If = 3] = "If", e[e.Else = 4] = "Else", e[e.ElseIf = 5] = "ElseIf", e[e.For = 6] = "For", e[e.Switch = 7] = "Switch", e[e.Case = 8] = "Case", e[e.ConstDeclaration = 9] = "ConstDeclaration", e;
1143
+ };
1144
+ //#endregion
1145
+ //#region ../packages/compiler/src/parser/types/node.enum.ts
1146
+ /**
1147
+ * Discriminant values that identify the type of each AST node produced by the parser.
1148
+ */
1149
+ var ASTNodeType = /* @__PURE__ */ function(ASTNodeType) {
1150
+ /**
1151
+ * An HTML element node with a tag name, attributes, events, and children.
1152
+ */
1153
+ ASTNodeType[ASTNodeType["Element"] = 0] = "Element";
1154
+ /**
1155
+ * A plain text node.
1156
+ */
1157
+ ASTNodeType[ASTNodeType["Text"] = 1] = "Text";
1158
+ /**
1159
+ * An inline interpolation expression or literal.
1160
+ */
1161
+ ASTNodeType[ASTNodeType["Interpolation"] = 2] = "Interpolation";
1162
+ /**
1163
+ * An `@if` conditional node.
1164
+ */
1165
+ ASTNodeType[ASTNodeType["If"] = 3] = "If";
1166
+ /**
1167
+ * An `@else` branch node attached to an `@if`.
1168
+ */
1169
+ ASTNodeType[ASTNodeType["Else"] = 4] = "Else";
1170
+ /**
1171
+ * An `@else if` branch node attached to an `@if`.
1172
+ */
1173
+ ASTNodeType[ASTNodeType["ElseIf"] = 5] = "ElseIf";
1174
+ /**
1175
+ * An `@for` iteration node.
1176
+ */
1177
+ ASTNodeType[ASTNodeType["For"] = 6] = "For";
1178
+ /**
1179
+ * An `@switch` node containing one or more case nodes.
1180
+ */
1181
+ ASTNodeType[ASTNodeType["Switch"] = 7] = "Switch";
1182
+ /**
1183
+ * A `@case` or `@default` branch inside a `@switch`.
1184
+ */
1185
+ ASTNodeType[ASTNodeType["Case"] = 8] = "Case";
1186
+ /**
1187
+ * A `@const` declaration node.
1188
+ */
1189
+ ASTNodeType[ASTNodeType["ConstDeclaration"] = 9] = "ConstDeclaration";
1190
+ return ASTNodeType;
512
1191
  }({});
513
1192
  //#endregion
514
1193
  //#region ../packages/compiler/src/parser/states/parse-const-declaration.state.ts
515
- function oe(e, t, n) {
516
- return e.advance(), {
517
- type: C.ConstDeclaration,
518
- varName: n.parts[0],
519
- expression: n.parts[1]
1194
+ /**
1195
+ * Parses a CONST_DECLARATION token into a `ConstDeclarationNode`.
1196
+ *
1197
+ * @param cursor Parser cursor; advanced past the CONST_DECLARATION token.
1198
+ * @param _parseNode Unused parser function.
1199
+ * @param token The CONST_DECLARATION token containing variable name and expression.
1200
+ * @returns The parsed `ConstDeclarationNode`.
1201
+ */
1202
+ function parseConstDeclaration(cursor, _parseNode, token) {
1203
+ cursor.advance();
1204
+ return {
1205
+ type: ASTNodeType.ConstDeclaration,
1206
+ varName: token.parts[0],
1207
+ expression: token.parts[1]
520
1208
  };
521
1209
  }
522
1210
  //#endregion
523
1211
  //#region ../packages/compiler/src/parser/states/parse-interpolation.state.ts
524
- function w(e, t, n) {
525
- return e.advance(), {
526
- type: C.Interpolation,
527
- expression: n.parts[0]
1212
+ /**
1213
+ * Parses an interpolation expression or literal token into an `InterpolationNode`.
1214
+ *
1215
+ * @param cursor Parser cursor; advanced past the interpolation token.
1216
+ * @param _parseNode Unused parser function.
1217
+ * @param token The INTERPOLATION_EXPRESSION or INTERPOLATION_LITERAL token.
1218
+ * @returns The parsed `InterpolationNode`.
1219
+ */
1220
+ function parseInterpolation(cursor, _parseNode, token) {
1221
+ cursor.advance();
1222
+ return {
1223
+ type: ASTNodeType.Interpolation,
1224
+ expression: token.parts[0]
528
1225
  };
529
1226
  }
530
1227
  //#endregion
531
1228
  //#region ../packages/compiler/src/parser/states/parse-attribute.state.ts
532
- function se(e, t, n) {
533
- e.advance();
534
- let r = n.parts[0];
535
- if (!r.includes("=")) return {
536
- name: r,
1229
+ /**
1230
+ * Parses an ATTRIBUTE token into an `AttributeNode`.
1231
+ * Handles boolean attributes (no `=`), string values, and interpolation values.
1232
+ *
1233
+ * @param cursor Parser cursor; advanced past the ATTRIBUTE token.
1234
+ * @param parseNode Parser node function for recursive parsing.
1235
+ * @param token The ATTRIBUTE token to parse.
1236
+ * @returns The parsed `AttributeNode`.
1237
+ */
1238
+ function parseAttribute(cursor, parseNode, token) {
1239
+ cursor.advance();
1240
+ const raw = token.parts[0];
1241
+ if (!raw.includes("=")) return {
1242
+ name: raw,
537
1243
  value: "true"
538
1244
  };
539
- let [a, o] = r.split("=");
540
- if (!a) throw Error(`[Parser] Attribute name missing in: ${r}`);
541
- let s = e.peek();
542
- if (s.type === i.INTERPOLATION_EXPRESSION || s.type === i.INTERPOLATION_LITERAL) return {
543
- name: a,
544
- value: w(e, t, s)
1245
+ const [name, value] = raw.split("=");
1246
+ if (!name) throw new Error(`[Parser] Attribute name missing in: ${raw}`);
1247
+ const nextToken = cursor.peek();
1248
+ if (nextToken.type === TokenType.INTERPOLATION_EXPRESSION || nextToken.type === TokenType.INTERPOLATION_LITERAL) return {
1249
+ name,
1250
+ value: parseInterpolation(cursor, parseNode, nextToken)
545
1251
  };
546
- if (!o) throw Error(`[Parser] Attribute value missing for ${a} in: ${r}`);
1252
+ if (!value) throw new Error(`[Parser] Attribute value missing for ${name} in: ${raw}`);
547
1253
  return {
548
- name: a,
549
- value: o.replace(/^['']|['']$/g, "")
1254
+ name,
1255
+ value: value.replace(/^['']|['']$/g, "")
550
1256
  };
551
1257
  }
552
1258
  //#endregion
553
1259
  //#region ../packages/compiler/src/parser/states/parse-event.state.ts
554
- function ce(e, t, n) {
555
- e.advance();
556
- let r = n.parts[0], [i, a] = r.split("=");
557
- if (!i || !a) throw Error(`[Parser] Invalid event format: ${r}`);
1260
+ /**
1261
+ * Parses an EVENT token into an `EventNode` by splitting the raw
1262
+ * `eventName=handler` string.
1263
+ *
1264
+ * @param cursor Parser cursor; advanced past the EVENT token.
1265
+ * @param _parseNode Unused parser function.
1266
+ * @param token The EVENT token to parse.
1267
+ * @returns The parsed `EventNode`.
1268
+ */
1269
+ function parseEvent(cursor, _parseNode, token) {
1270
+ cursor.advance();
1271
+ const raw = token.parts[0];
1272
+ const [name, value] = raw.split("=");
1273
+ if (!name || !value) throw new Error(`[Parser] Invalid event format: ${raw}`);
558
1274
  return {
559
- name: i,
560
- handler: a.replace(/^[""]|[""]$/g, "")
1275
+ name,
1276
+ handler: value.replace(/^[""]|[""]$/g, "")
561
1277
  };
562
1278
  }
563
1279
  //#endregion
564
1280
  //#region ../packages/compiler/src/parser/states/parse-element.state.ts
565
- function le(e, t, n) {
566
- e.advance();
567
- let r = n.parts[0], a = [], o = [], s = !0;
568
- for (; s;) {
569
- let n = e.peek();
570
- switch (n.type) {
571
- case i.ATTRIBUTE:
572
- a.push(se(e, t, n));
1281
+ /**
1282
+ * Parses a TAG_OPEN_NAME token and the subsequent attributes, events, and children
1283
+ * into an `ElementNode`. Handles both regular and self-closing tags.
1284
+ *
1285
+ * @param cursor Parser cursor positioned at the TAG_OPEN_NAME token.
1286
+ * @param context Parser context for recursive child parsing.
1287
+ * @param token The TAG_OPEN_NAME token containing the tag name.
1288
+ * @returns The parsed `ElementNode`.
1289
+ */
1290
+ function parseElement(cursor, parseNode, token) {
1291
+ cursor.advance();
1292
+ const tagName = token.parts[0];
1293
+ const attributes = new Array();
1294
+ const events = new Array();
1295
+ let read = true;
1296
+ while (read) {
1297
+ const token = cursor.peek();
1298
+ switch (token.type) {
1299
+ case TokenType.ATTRIBUTE:
1300
+ attributes.push(parseAttribute(cursor, parseNode, token));
573
1301
  break;
574
- case i.EVENT:
575
- o.push(ce(e, t, n));
1302
+ case TokenType.EVENT:
1303
+ events.push(parseEvent(cursor, parseNode, token));
576
1304
  break;
577
- default: s = !1;
1305
+ default: read = false;
578
1306
  }
579
1307
  }
580
- if (e.peek().type === i.TAG_OPEN_END && e.advance(), e.peek().type === i.TAG_SELF_CLOSE) return e.advance(), {
581
- type: C.Element,
582
- tagName: r,
583
- attributes: a,
584
- events: o,
585
- children: []
586
- };
587
- let c = [];
588
- for (; !ue(e, r);) {
589
- let e = t();
590
- e && c.push(e);
1308
+ if (cursor.peek().type === TokenType.TAG_OPEN_END) cursor.advance();
1309
+ if (cursor.peek().type === TokenType.TAG_SELF_CLOSE) {
1310
+ cursor.advance();
1311
+ return {
1312
+ type: ASTNodeType.Element,
1313
+ tagName,
1314
+ attributes,
1315
+ events,
1316
+ children: []
1317
+ };
1318
+ }
1319
+ const children = new Array();
1320
+ while (!isTagClose(cursor, tagName)) {
1321
+ const child = parseNode();
1322
+ if (child) children.push(child);
591
1323
  }
592
- return e.advance(), {
593
- type: C.Element,
594
- tagName: r,
595
- attributes: a,
596
- events: o,
597
- children: c
1324
+ cursor.advance();
1325
+ return {
1326
+ type: ASTNodeType.Element,
1327
+ tagName,
1328
+ attributes,
1329
+ events,
1330
+ children
598
1331
  };
599
1332
  }
600
- function ue(e, t) {
601
- let n = e.peek();
602
- return n.type === i.TAG_CLOSE_NAME && n.parts[0] === t;
1333
+ /**
1334
+ * Returns `true` if the next token in the stream is a closing tag for the given tag name.
1335
+ *
1336
+ * @param cursor Parser cursor to peek from.
1337
+ * @param tagName The expected tag name to match.
1338
+ * @returns `true` if the next token is TAG_CLOSE_NAME matching `tagName`.
1339
+ */
1340
+ function isTagClose(cursor, tagName) {
1341
+ const nextToken = cursor.peek();
1342
+ return nextToken.type === TokenType.TAG_CLOSE_NAME && nextToken.parts[0] === tagName;
603
1343
  }
604
1344
  //#endregion
605
1345
  //#region ../packages/compiler/src/parser/utils/expression-validator.ts
606
- function T(e) {
607
- let t = n.createSourceFile("expression.ts", `const x = ${e}`, n.ScriptTarget.ESNext, !0).statements[0].declarationList.declarations[0].initializer, r = [];
608
- if (E(t, 10, r), r.length) throw Error(r.reduce((e, t) => `${e}${t.message}\n`, ""));
609
- return { node: t };
1346
+ /**
1347
+ * Validates that a string contains a single expression belonging to the
1348
+ * permitted subset of JavaScript supported inside Xaendar template expressions.
1349
+ *
1350
+ * ## Permitted constructs
1351
+ *
1352
+ * - **Literals** — strings, numbers, bigints, booleans, `null`, `undefined`
1353
+ * - **Identifiers** — resolved at runtime against the active scope chain
1354
+ * - **Member access** — `user.name`, `user.address.city`, `items[0]`
1355
+ * - **Call expressions** — `user.getFullName()`, `user.hasRole('admin')`
1356
+ * - **Binary expressions** — arithmetic (`+`, `-`, `*`, `/`, `%`, `**`),
1357
+ * comparison (`===`, `!==`, `<`, `>`, `<=`, `>=`),
1358
+ * logical (`&&`, `||`, `??`),
1359
+ * bitwise (`&`, `|`, `^`, `<<`, `>>`, `>>>`)
1360
+ * - **Unary expressions** — `!`, `~`, `+`, `-`, `typeof`, `void`
1361
+ * - **Conditional (ternary)** — `isAdmin ? 'yes' : 'no'`
1362
+ * - **Parenthesised expressions** — `(user.age > 18)`
1363
+ * - **Template literals** — `` `Hello ${user.name}` ``
1364
+ * - **Array literals** — `[1, 2, 3]`, `[...items]`
1365
+ * - **Object literals** — `{ key: value }`, `{ ...defaults, name }`
1366
+ * - **Spread** — `foo(...args)`, `[...items]`, `{ ...obj }`
1367
+ * - **`typeof` / `instanceof`** — `typeof user.role`, `user instanceof AdminUser`
1368
+ *
1369
+ * ## Prohibited constructs
1370
+ *
1371
+ * - Assignments (`=`, `+=`, `&&=`, etc.) — use `@const` for local bindings
1372
+ * - `await` and `yield`
1373
+ * - `new` expressions
1374
+ * - Function and arrow function expressions
1375
+ * - Tagged template expressions
1376
+ *
1377
+ * ## Scope resolution
1378
+ *
1379
+ * This function performs **syntactic** validation only. Identifier resolution
1380
+ * (scope chain walk → `ctx.` prefix injection) is the responsibility of the
1381
+ * caller and must be performed on the returned `node` after this function
1382
+ * reports no diagnostics.
1383
+ *
1384
+ * @param source - The raw expression string extracted from the template.
1385
+ * @returns A {@link ExpressionValidationResult} containing the parsed AST node
1386
+ * (when valid) and any diagnostics produced during validation.
1387
+ *
1388
+ * @example
1389
+ * const result = validateExpression('user.hasRole("admin") && isVerified');
1390
+ * if (result.diagnostics.length === 0) {
1391
+ * // result.node is safe to use
1392
+ * }
1393
+ *
1394
+ * @example
1395
+ * const result = validateExpression('await user.load()');
1396
+ * // result.diagnostics[0].message →
1397
+ * // "'await' is not allowed inside template expressions."
1398
+ */
1399
+ function validateExpression(source) {
1400
+ const expression = ts.createSourceFile("expression.ts", `const x = ${source}`, ts.ScriptTarget.ESNext, true).statements[0].declarationList.declarations[0].initializer;
1401
+ const diagnostics = new Array();
1402
+ visitNode(expression, 10, diagnostics);
1403
+ if (diagnostics.length) throw new Error(diagnostics.reduce((acc, d) => `${acc}${d.message}\n`, ""));
1404
+ return { node: expression };
610
1405
  }
611
- function E(e, t, r) {
612
- if (!D(e)) throw Error(O(e));
613
- if (n.forEachChild(e, (e) => E(e, t, r)), r.length) throw Error(r[0].message);
1406
+ /**
1407
+ * Recursively visits an AST node and appends a diagnostic for every node
1408
+ * kind that is not part of the permitted expression subset.
1409
+ *
1410
+ * Recursion stops at the first disallowed node to avoid producing a cascade
1411
+ * of redundant diagnostics for its children.
1412
+ *
1413
+ * @param node - The AST node to inspect.
1414
+ * @param offset - Number of characters to subtract from raw node positions
1415
+ * to obtain offsets relative to the original expression string.
1416
+ * @param diagnostics - Accumulator for diagnostics found during the walk.
1417
+ */
1418
+ function visitNode(node, offset, diagnostics) {
1419
+ if (!isAllowedNode(node)) throw new Error(buildDisallowedMessage(node));
1420
+ ts.forEachChild(node, (child) => visitNode(child, offset, diagnostics));
1421
+ if (diagnostics.length) throw new Error(diagnostics[0].message);
614
1422
  }
615
- function D(e) {
616
- switch (e.kind) {
617
- case n.SyntaxKind.StringLiteral:
618
- case n.SyntaxKind.NumericLiteral:
619
- case n.SyntaxKind.BigIntLiteral:
620
- case n.SyntaxKind.TrueKeyword:
621
- case n.SyntaxKind.FalseKeyword:
622
- case n.SyntaxKind.NullKeyword:
623
- case n.SyntaxKind.UndefinedKeyword:
624
- case n.SyntaxKind.Identifier:
625
- case n.SyntaxKind.PropertyAccessExpression:
626
- case n.SyntaxKind.ElementAccessExpression:
627
- case n.SyntaxKind.CallExpression:
628
- case n.SyntaxKind.BinaryExpression:
629
- case n.SyntaxKind.EqualsEqualsToken:
630
- case n.SyntaxKind.EqualsEqualsEqualsToken:
631
- case n.SyntaxKind.ExclamationEqualsToken:
632
- case n.SyntaxKind.ExclamationEqualsEqualsToken:
633
- case n.SyntaxKind.LessThanToken:
634
- case n.SyntaxKind.LessThanEqualsToken:
635
- case n.SyntaxKind.GreaterThanToken:
636
- case n.SyntaxKind.GreaterThanEqualsToken:
637
- case n.SyntaxKind.PlusToken:
638
- case n.SyntaxKind.MinusToken:
639
- case n.SyntaxKind.AsteriskToken:
640
- case n.SyntaxKind.SlashToken:
641
- case n.SyntaxKind.PercentToken:
642
- case n.SyntaxKind.AsteriskAsteriskToken:
643
- case n.SyntaxKind.AmpersandAmpersandToken:
644
- case n.SyntaxKind.BarBarToken:
645
- case n.SyntaxKind.QuestionQuestionToken:
646
- case n.SyntaxKind.AmpersandToken:
647
- case n.SyntaxKind.BarToken:
648
- case n.SyntaxKind.CaretToken:
649
- case n.SyntaxKind.LessThanLessThanToken:
650
- case n.SyntaxKind.GreaterThanGreaterThanToken:
651
- case n.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
652
- case n.SyntaxKind.InstanceOfKeyword:
653
- case n.SyntaxKind.InKeyword:
654
- case n.SyntaxKind.PrefixUnaryExpression:
655
- case n.SyntaxKind.PostfixUnaryExpression:
656
- case n.SyntaxKind.TypeOfExpression:
657
- case n.SyntaxKind.VoidExpression:
658
- case n.SyntaxKind.ConditionalExpression:
659
- case n.SyntaxKind.ParenthesizedExpression:
660
- case n.SyntaxKind.TemplateExpression:
661
- case n.SyntaxKind.NoSubstitutionTemplateLiteral:
662
- case n.SyntaxKind.TemplateHead:
663
- case n.SyntaxKind.TemplateMiddle:
664
- case n.SyntaxKind.TemplateTail:
665
- case n.SyntaxKind.TemplateSpan:
666
- case n.SyntaxKind.ArrayLiteralExpression:
667
- case n.SyntaxKind.ObjectLiteralExpression:
668
- case n.SyntaxKind.PropertyAssignment:
669
- case n.SyntaxKind.ShorthandPropertyAssignment:
670
- case n.SyntaxKind.SpreadAssignment:
671
- case n.SyntaxKind.SpreadElement:
672
- case n.SyntaxKind.SyntaxList: return !0;
673
- default: return !1;
1423
+ /**
1424
+ * Returns `true` if the given AST node kind is permitted inside a
1425
+ * Xaendar template expression.
1426
+ *
1427
+ * Assignment operators nested inside a `BinaryExpression` are handled
1428
+ * separately in {@link buildDisallowedMessage} since TypeScript does not
1429
+ * distinguish them at the node-kind level.
1430
+ */
1431
+ function isAllowedNode(node) {
1432
+ switch (node.kind) {
1433
+ case ts.SyntaxKind.StringLiteral:
1434
+ case ts.SyntaxKind.NumericLiteral:
1435
+ case ts.SyntaxKind.BigIntLiteral:
1436
+ case ts.SyntaxKind.TrueKeyword:
1437
+ case ts.SyntaxKind.FalseKeyword:
1438
+ case ts.SyntaxKind.NullKeyword:
1439
+ case ts.SyntaxKind.UndefinedKeyword:
1440
+ case ts.SyntaxKind.Identifier:
1441
+ case ts.SyntaxKind.PropertyAccessExpression:
1442
+ case ts.SyntaxKind.ElementAccessExpression:
1443
+ case ts.SyntaxKind.CallExpression:
1444
+ case ts.SyntaxKind.BinaryExpression:
1445
+ case ts.SyntaxKind.EqualsEqualsToken:
1446
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
1447
+ case ts.SyntaxKind.ExclamationEqualsToken:
1448
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
1449
+ case ts.SyntaxKind.LessThanToken:
1450
+ case ts.SyntaxKind.LessThanEqualsToken:
1451
+ case ts.SyntaxKind.GreaterThanToken:
1452
+ case ts.SyntaxKind.GreaterThanEqualsToken:
1453
+ case ts.SyntaxKind.PlusToken:
1454
+ case ts.SyntaxKind.MinusToken:
1455
+ case ts.SyntaxKind.AsteriskToken:
1456
+ case ts.SyntaxKind.SlashToken:
1457
+ case ts.SyntaxKind.PercentToken:
1458
+ case ts.SyntaxKind.AsteriskAsteriskToken:
1459
+ case ts.SyntaxKind.AmpersandAmpersandToken:
1460
+ case ts.SyntaxKind.BarBarToken:
1461
+ case ts.SyntaxKind.QuestionQuestionToken:
1462
+ case ts.SyntaxKind.AmpersandToken:
1463
+ case ts.SyntaxKind.BarToken:
1464
+ case ts.SyntaxKind.CaretToken:
1465
+ case ts.SyntaxKind.LessThanLessThanToken:
1466
+ case ts.SyntaxKind.GreaterThanGreaterThanToken:
1467
+ case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
1468
+ case ts.SyntaxKind.InstanceOfKeyword:
1469
+ case ts.SyntaxKind.InKeyword:
1470
+ case ts.SyntaxKind.PrefixUnaryExpression:
1471
+ case ts.SyntaxKind.PostfixUnaryExpression:
1472
+ case ts.SyntaxKind.TypeOfExpression:
1473
+ case ts.SyntaxKind.VoidExpression:
1474
+ case ts.SyntaxKind.ConditionalExpression:
1475
+ case ts.SyntaxKind.ParenthesizedExpression:
1476
+ case ts.SyntaxKind.TemplateExpression:
1477
+ case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
1478
+ case ts.SyntaxKind.TemplateHead:
1479
+ case ts.SyntaxKind.TemplateMiddle:
1480
+ case ts.SyntaxKind.TemplateTail:
1481
+ case ts.SyntaxKind.TemplateSpan:
1482
+ case ts.SyntaxKind.ArrayLiteralExpression:
1483
+ case ts.SyntaxKind.ObjectLiteralExpression:
1484
+ case ts.SyntaxKind.PropertyAssignment:
1485
+ case ts.SyntaxKind.ShorthandPropertyAssignment:
1486
+ case ts.SyntaxKind.SpreadAssignment:
1487
+ case ts.SyntaxKind.SpreadElement:
1488
+ case ts.SyntaxKind.SyntaxList: return true;
1489
+ default: return false;
674
1490
  }
675
1491
  }
676
- function O(e) {
677
- switch (e.kind) {
678
- case n.SyntaxKind.AwaitExpression: return "'await' is not allowed inside template expressions.";
679
- case n.SyntaxKind.YieldExpression: return "'yield' is not allowed inside template expressions.";
680
- case n.SyntaxKind.NewExpression: return "'new' is not allowed inside template expressions.";
681
- case n.SyntaxKind.ArrowFunction:
682
- case n.SyntaxKind.FunctionExpression: return "Function expressions are not allowed inside template expressions.";
683
- case n.SyntaxKind.TaggedTemplateExpression: return "Tagged template expressions are not allowed inside template expressions.";
684
- case n.SyntaxKind.BinaryExpression: return k(e.operatorToken.kind) ? "Assignments are not allowed inside template expressions. Use @const to declare local template variables instead." : `'${n.SyntaxKind[e.kind]}' is not allowed inside template expressions.`;
685
- default: return `'${n.SyntaxKind[e.kind]}' is not allowed inside template expressions.`;
1492
+ /**
1493
+ * Builds a human-readable diagnostic message for a node that is not permitted
1494
+ * inside a Xaendar template expression.
1495
+ *
1496
+ * Provides specific messages for the most common mistakes (assignments, `await`,
1497
+ * `new`, functions) and falls back to a generic message for anything else.
1498
+ */
1499
+ function buildDisallowedMessage(node) {
1500
+ switch (node.kind) {
1501
+ case ts.SyntaxKind.AwaitExpression: return "'await' is not allowed inside template expressions.";
1502
+ case ts.SyntaxKind.YieldExpression: return "'yield' is not allowed inside template expressions.";
1503
+ case ts.SyntaxKind.NewExpression: return "'new' is not allowed inside template expressions.";
1504
+ case ts.SyntaxKind.ArrowFunction:
1505
+ case ts.SyntaxKind.FunctionExpression: return "Function expressions are not allowed inside template expressions.";
1506
+ case ts.SyntaxKind.TaggedTemplateExpression: return "Tagged template expressions are not allowed inside template expressions.";
1507
+ case ts.SyntaxKind.BinaryExpression: return isAssignmentOperator(node.operatorToken.kind) ? "Assignments are not allowed inside template expressions. Use @const to declare local template variables instead." : `'${ts.SyntaxKind[node.kind]}' is not allowed inside template expressions.`;
1508
+ default: return `'${ts.SyntaxKind[node.kind]}' is not allowed inside template expressions.`;
686
1509
  }
687
1510
  }
688
- function k(e) {
689
- return e >= n.SyntaxKind.FirstAssignment && e <= n.SyntaxKind.LastAssignment;
1511
+ /**
1512
+ * Returns `true` if the given {@link ts.SyntaxKind} is an assignment operator.
1513
+ *
1514
+ * Covers simple assignment (`=`) as well as all compound assignment operators
1515
+ * (`+=`, `-=`, `&&=`, `||=`, `??=`, etc.) as defined by the TypeScript
1516
+ * `FirstAssignment`–`LastAssignment` range.
1517
+ */
1518
+ function isAssignmentOperator(kind) {
1519
+ return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
690
1520
  }
691
1521
  //#endregion
692
1522
  //#region ../packages/compiler/src/parser/states/parse-block-children.state.ts
693
- function A(e, t) {
694
- let n = [];
695
- for (; e.peek().type !== i.BLOCK_CLOSE;) {
696
- let e = t();
697
- e && n.push(e);
1523
+ /**
1524
+ * Parses child AST nodes inside a flow-control block until a BLOCK_CLOSE token is reached.
1525
+ * Consumes the BLOCK_CLOSE token before returning.
1526
+ *
1527
+ * @param cursor Parser cursor positioned at the first token inside the block.
1528
+ * @param parseNode Parser function for recursive child parsing.
1529
+ * @returns Array of parsed child `ASTNode`s.
1530
+ */
1531
+ function parseBlockChildren(cursor, parseNode) {
1532
+ const children = new Array();
1533
+ while (cursor.peek().type !== TokenType.BLOCK_CLOSE) {
1534
+ const child = parseNode();
1535
+ if (child) children.push(child);
698
1536
  }
699
- return e.advance(), n;
1537
+ cursor.advance();
1538
+ return children;
700
1539
  }
701
1540
  //#endregion
702
1541
  //#region ../packages/compiler/src/parser/states/parse-for.state.ts
703
- function j(e, t, n) {
704
- e.advance();
705
- let r = e.peek();
706
- if (r.type !== i.CONDITION) throw Error(`[Parser] Expected CONDITION after FOR, got ${i[r.type]}`);
707
- let a = M(r.parts[0], 0);
708
- e.advance(2);
709
- let o = A(e, t);
1542
+ /**
1543
+ * Parses a `@for` directive, consuming the FOR token, the CONDITION token,
1544
+ * the BLOCK_OPEN token, and all child nodes until BLOCK_CLOSE.
1545
+ *
1546
+ * @param cursor Parser cursor positioned at the FOR token.
1547
+ * @param context Parser context for recursive child parsing.
1548
+ * @param _token The FOR token (unused; consumed for position advancement).
1549
+ * @returns The parsed `ForNode`.
1550
+ */
1551
+ function parseForControlFlow(cursor, parseNode, _token) {
1552
+ cursor.advance();
1553
+ const conditionToken = cursor.peek();
1554
+ if (conditionToken.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after FOR, got ${TokenType[conditionToken.type]}`);
1555
+ const expression = parseForExpression(conditionToken.parts[0], 0);
1556
+ cursor.advance(2);
1557
+ const children = parseBlockChildren(cursor, parseNode);
710
1558
  return {
711
- type: C.For,
712
- ...a,
713
- children: o
1559
+ type: ASTNodeType.For,
1560
+ ...expression,
1561
+ children
714
1562
  };
715
1563
  }
716
- function M(e, t) {
717
- let n = P(e);
718
- if (n.length < 2) throw Error("[Parser] @for requires at least \"item of iterable; track expr\".");
719
- let r = n[0].trim(), i = r.indexOf(" of ");
720
- if (i === -1) throw Error("[Parser] @for expression must be in the form \"item of iterable\".");
721
- let a = r.slice(0, i).trim(), o = r.slice(i + 4).trim();
722
- if (!F(a)) throw Error(`[Parser] '${a}' is not a valid item alias.`);
723
- let s = T(o), c = n[1].trim();
724
- if (!c.startsWith("track ")) throw Error("[Parser] Second section of @for must start with \"track\".");
725
- let l = c.slice(6).trim(), u = T(l), d = /* @__PURE__ */ new Map();
726
- return n.length >= 3 && n[2] !== void 0 && N(n[2].trim(), t + e.indexOf(n[2]), d), {
727
- itemAlias: a,
728
- iterableExpression: s.node,
729
- iterableSource: o,
730
- trackExpression: u.node,
731
- trackSource: l,
732
- implicitAliases: d
1564
+ /**
1565
+ * Parses the body of an `@for` block into a structured {@link ForExpression}.
1566
+ *
1567
+ * The expected format is:
1568
+ * ```
1569
+ * item of iterable; track expr[; $implicit = alias, ...]
1570
+ * ```
1571
+ *
1572
+ * @param source - The raw string content of the `@for(...)` expression.
1573
+ * @param baseOffset - Character offset of `source` within the original template,
1574
+ * used to produce accurate diagnostic positions.
1575
+ * @returns A {@link ForExpression} object. When unrecoverable syntax errors are
1576
+ * found the returned object contains only `diagnostics`.
1577
+ */
1578
+ function parseForExpression(source, baseOffset) {
1579
+ const sections = splitForSections(source);
1580
+ if (sections.length < 2) throw new Error(`[Parser] @for requires at least "item of iterable; track expr".`);
1581
+ const iterSection = sections[0].trim();
1582
+ const ofIndex = iterSection.indexOf(" of ");
1583
+ if (ofIndex === -1) throw new Error(`[Parser] @for expression must be in the form "item of iterable".`);
1584
+ const itemAlias = iterSection.slice(0, ofIndex).trim();
1585
+ const iterableSource = iterSection.slice(ofIndex + 4).trim();
1586
+ if (!isValidIdentifier(itemAlias)) throw new Error(`[Parser] '${itemAlias}' is not a valid item alias.`);
1587
+ const iterValidation = validateExpression(iterableSource);
1588
+ const trackSection = sections[1].trim();
1589
+ if (!trackSection.startsWith("track ")) throw new Error(`[Parser] Second section of @for must start with "track".`);
1590
+ const trackSource = trackSection.slice(6).trim();
1591
+ const trackValidation = validateExpression(trackSource);
1592
+ const implicitAliases = /* @__PURE__ */ new Map();
1593
+ if (sections.length >= 3 && sections[2] !== void 0) parseImplicitAliases(sections[2].trim(), baseOffset + source.indexOf(sections[2]), implicitAliases);
1594
+ return {
1595
+ itemAlias,
1596
+ iterableExpression: iterValidation.node,
1597
+ iterableSource,
1598
+ trackExpression: trackValidation.node,
1599
+ trackSource,
1600
+ implicitAliases
733
1601
  };
734
1602
  }
735
- function N(e, t, n) {
736
- let r = e.split(","), i = 0, a = new Set([
1603
+ /**
1604
+ * Parses the optional third section of an `@for` expression, which declares
1605
+ * aliases for implicit loop variables (e.g. `$index = i, $last = l, $even = isEven`).
1606
+ *
1607
+ * Valid entries are comma-separated pairs in the form `$implicit = alias`.
1608
+ * Diagnostics are pushed to `diagnostics` for any malformed or duplicate entry.
1609
+ *
1610
+ * @param source - The raw alias-declarations string (everything after the second `;`).
1611
+ * @param baseOffset - Character offset of `source` within the original template.
1612
+ * @param out - Map to populate with `alias → implicit-variable` entries.
1613
+ * @param diagnostics - Array to collect any parse errors.
1614
+ */
1615
+ function parseImplicitAliases(source, baseOffset, out) {
1616
+ const entries = source.split(",");
1617
+ let cursor = 0;
1618
+ const IMPLICIT_VARIABLES = new Set([
737
1619
  "$index",
738
1620
  "$last",
739
1621
  "$first",
740
1622
  "$even",
741
1623
  "$odd"
742
1624
  ]);
743
- for (let e of r) {
744
- let t = e.trim(), r = t.indexOf("=");
745
- if (r === -1) throw Error(`[Parser] Invalid alias declaration '${t}'. Expected '$implicit = alias'.`);
746
- i += e.length + 1;
747
- let o = t.slice(0, r).trim(), s = t.slice(r + 1).trim();
748
- if (!((e) => a.has(e))(o)) throw Error(`[Parser] '${o}' is not a known implicit variable. Known variables: ${[...a].join(", ")}.`);
749
- if (i += e.length + 1, !F(s)) throw Error(`[Parser] '${s}' is not a valid alias identifier.`);
750
- if (i += e.length + 1, n.has(o)) throw Error(`[Parser] '${o}' is already aliased in this @for expression.`);
751
- n.set(o, s), i += e.length + 1;
1625
+ for (const entry of entries) {
1626
+ const trimmed = entry.trim();
1627
+ const eqIndex = trimmed.indexOf("=");
1628
+ if (eqIndex === -1) throw new Error(`[Parser] Invalid alias declaration '${trimmed}'. Expected '$implicit = alias'.`);
1629
+ cursor += entry.length + 1;
1630
+ const implicit = trimmed.slice(0, eqIndex).trim();
1631
+ const alias = trimmed.slice(eqIndex + 1).trim();
1632
+ const isImplicitVariable = (value) => IMPLICIT_VARIABLES.has(value);
1633
+ if (!isImplicitVariable(implicit)) throw new Error(`[Parser] '${implicit}' is not a known implicit variable. Known variables: ${[...IMPLICIT_VARIABLES].join(", ")}.`);
1634
+ cursor += entry.length + 1;
1635
+ if (!isValidIdentifier(alias)) throw new Error(`[Parser] '${alias}' is not a valid alias identifier.`);
1636
+ cursor += entry.length + 1;
1637
+ if (out.has(implicit)) throw new Error(`[Parser] '${implicit}' is already aliased in this @for expression.`);
1638
+ else out.set(implicit, alias);
1639
+ cursor += entry.length + 1;
752
1640
  }
753
1641
  }
754
- function P(e) {
755
- let t = [], n = "", r = 0, i;
756
- for (let a = 0; a < e.length; a++) {
757
- let o = e[a];
758
- if (!(!n && o === " ")) {
759
- if (i) {
760
- n += o, o === i && e[a - 1] !== "\\" && (i = null);
761
- continue;
762
- }
763
- if (o === "\"" || o === "'" || o === "`") {
764
- i = o, n += o;
765
- continue;
766
- }
767
- if (o === "(" || o === "[" || o === "{") {
768
- r++, n += o;
769
- continue;
770
- }
771
- if (o === ")" || o === "]" || o === "}") {
772
- r--, n += o;
773
- continue;
774
- }
775
- if (o === ";" && r === 0) {
776
- t.push(n), n = "";
777
- continue;
778
- }
779
- n += o;
1642
+ /**
1643
+ * Splits the raw `@for(...)` body into its semicolon-delimited sections,
1644
+ * respecting nested brackets and string literals so that semicolons inside
1645
+ * them are never treated as section separators.
1646
+ *
1647
+ * Example input: `"item of items; track item.id; $index = i"`
1648
+ * Example output: `["item of items", " track item.id", " $index = i"]`
1649
+ *
1650
+ * @param source - The raw content of the `@for(...)` expression.
1651
+ * @returns An array of section strings (without the `;` separators).
1652
+ */
1653
+ function splitForSections(source) {
1654
+ const sections = new Array();
1655
+ let current = "";
1656
+ let depth = 0;
1657
+ let inString;
1658
+ for (let i = 0; i < source.length; i++) {
1659
+ const char = source[i];
1660
+ if (!current && char === " ") continue;
1661
+ if (inString) {
1662
+ current += char;
1663
+ if (char === inString && source[i - 1] !== "\\") inString = null;
1664
+ continue;
1665
+ }
1666
+ if (char === "\"" || char === "'" || char === "`") {
1667
+ inString = char;
1668
+ current += char;
1669
+ continue;
1670
+ }
1671
+ if (char === "(" || char === "[" || char === "{") {
1672
+ depth++;
1673
+ current += char;
1674
+ continue;
1675
+ }
1676
+ if (char === ")" || char === "]" || char === "}") {
1677
+ depth--;
1678
+ current += char;
1679
+ continue;
780
1680
  }
1681
+ if (char === ";" && depth === 0) {
1682
+ sections.push(current);
1683
+ current = "";
1684
+ continue;
1685
+ }
1686
+ current += char;
781
1687
  }
782
- return n.trim().length > 0 && t.push(n), t;
1688
+ if (current.trim().length > 0) sections.push(current);
1689
+ return sections;
783
1690
  }
784
- function F(e) {
785
- if (!e.length) return !1;
786
- let t = n.createSourceFile("__id.ts", e, n.ScriptTarget.ESNext, !1).statements[0];
787
- return !!t && n.isExpressionStatement(t) && n.isIdentifier(t.expression) && t.expression.text === e;
1691
+ /**
1692
+ * Checks whether `name` is a valid JavaScript identifier by delegating to
1693
+ * the TypeScript parser.
1694
+ *
1695
+ * A string is considered valid when the TS parser produces a single
1696
+ * `ExpressionStatement` whose expression is an `Identifier` with the
1697
+ * same text.
1698
+ *
1699
+ * @param name - The string to validate.
1700
+ * @returns `true` if `name` is a valid JS identifier, `false` otherwise.
1701
+ */
1702
+ function isValidIdentifier(name) {
1703
+ if (!name.length) return false;
1704
+ const statement = ts.createSourceFile("__id.ts", name, ts.ScriptTarget.ESNext, false).statements[0];
1705
+ return !!statement && ts.isExpressionStatement(statement) && ts.isIdentifier(statement.expression) && statement.expression.text === name;
788
1706
  }
789
1707
  //#endregion
790
1708
  //#region ../packages/compiler/src/parser/states/parse-if.state.ts
791
- function I(e, t, n) {
792
- return L(e, t, n);
1709
+ /**
1710
+ * Parses an `@if` directive, consuming the IF token, the CONDITION token,
1711
+ * the BLOCK_OPEN token, all consequent children, and an optional `@else` branch.
1712
+ *
1713
+ * @param cursor Parser cursor positioned at the IF token.
1714
+ * @param context Parser context for recursive child parsing.
1715
+ * @param token The IF token (unused; consumed for position advancement).
1716
+ * @returns The parsed `IfNode`.
1717
+ */
1718
+ function parseIfControlFlow(cursor, parseNode, token) {
1719
+ return parseIfRecursively(cursor, parseNode, token);
793
1720
  }
794
- function L(e, t, n) {
795
- switch (n.type) {
796
- case i.IF:
797
- case i.ELSE_IF:
798
- e.advance();
799
- let r = e.peek();
800
- if (r.type !== i.CONDITION) throw Error(`[Parser] Expected CONDITION after ${i[n.type]}, got ${i[r.type]}`);
801
- e.advance(2);
802
- let a = r.parts[0], o = T(a), s = A(e, t);
1721
+ function parseIfRecursively(cursor, parseNode, token) {
1722
+ switch (token.type) {
1723
+ case TokenType.IF:
1724
+ case TokenType.ELSE_IF:
1725
+ cursor.advance();
1726
+ const conditionToken = cursor.peek();
1727
+ if (conditionToken.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after ${TokenType[token.type]}, got ${TokenType[conditionToken.type]}`);
1728
+ cursor.advance(2);
1729
+ const condition = conditionToken.parts[0];
1730
+ const validationResult = validateExpression(condition);
1731
+ const consequent = parseBlockChildren(cursor, parseNode);
803
1732
  return {
804
- type: n.type === i.IF ? C.If : C.ElseIf,
805
- condition: a,
806
- conditionNode: o.node,
807
- consequent: s,
808
- alternate: L(e, t, e.peek())
1733
+ type: token.type === TokenType.IF ? ASTNodeType.If : ASTNodeType.ElseIf,
1734
+ condition,
1735
+ conditionNode: validationResult.node,
1736
+ consequent,
1737
+ alternate: parseIfRecursively(cursor, parseNode, cursor.peek())
809
1738
  };
810
- case i.ELSE:
811
- e.advance(2);
812
- let c = A(e, t);
1739
+ case TokenType.ELSE:
1740
+ cursor.advance(2);
1741
+ const elseChildren = parseBlockChildren(cursor, parseNode);
813
1742
  return {
814
- type: C.Else,
815
- consequent: c
1743
+ type: ASTNodeType.Else,
1744
+ consequent: elseChildren
816
1745
  };
817
1746
  }
818
1747
  }
819
1748
  //#endregion
820
1749
  //#region ../packages/compiler/src/parser/states/parse-switch.state.ts
821
- function R(e, t, n) {
822
- e.advance();
823
- let r = e.peek();
824
- if (r.type !== i.CONDITION) throw Error(`[Parser] Expected CONDITION after SWITCH, got ${i[r.type]}`);
825
- let a = r.parts[0];
826
- e.advance(2);
827
- let o = [];
828
- for (; e.peek().type !== i.BLOCK_CLOSE;) switch (e.peek().type) {
829
- case i.CASE:
830
- let n = [];
1750
+ /**
1751
+ * Parses a `@switch` directive, consuming the SWITCH token, the CONDITION token,
1752
+ * the outer BLOCK_OPEN, all `@case` and `@default` branches, and the outer BLOCK_CLOSE.
1753
+ *
1754
+ * @param cursor Parser cursor positioned at the SWITCH token.
1755
+ * @param parseNode Parser function for recursive child parsing.
1756
+ * @param _token The SWITCH token (unused; consumed for position advancement).
1757
+ * @returns The parsed `SwitchNode`.
1758
+ */
1759
+ function parseSwitchControlFlow(cursor, parseNode, _token) {
1760
+ cursor.advance();
1761
+ const conditionToken = cursor.peek();
1762
+ if (conditionToken.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after SWITCH, got ${TokenType[conditionToken.type]}`);
1763
+ const expression = conditionToken.parts[0];
1764
+ cursor.advance(2);
1765
+ const cases = new Array();
1766
+ while (cursor.peek().type !== TokenType.BLOCK_CLOSE) switch (cursor.peek().type) {
1767
+ case TokenType.CASE:
1768
+ const condition = new Array();
831
1769
  do {
832
- e.advance();
833
- let t = e.peek();
834
- if (t.type !== i.CONDITION) throw Error("[Parser] Expected CONDITION after CASE");
835
- n.push(t.parts[0]), e.advance();
836
- } while (e.peek().type !== i.BLOCK_OPEN);
837
- e.advance(), o.push({
838
- type: C.Case,
839
- condition: n,
840
- children: A(e, t)
1770
+ cursor.advance();
1771
+ const caseCondition = cursor.peek();
1772
+ if (caseCondition.type !== TokenType.CONDITION) throw new Error(`[Parser] Expected CONDITION after CASE`);
1773
+ condition.push(caseCondition.parts[0]);
1774
+ cursor.advance();
1775
+ } while (cursor.peek().type !== TokenType.BLOCK_OPEN);
1776
+ cursor.advance();
1777
+ cases.push({
1778
+ type: ASTNodeType.Case,
1779
+ condition,
1780
+ children: parseBlockChildren(cursor, parseNode)
841
1781
  });
842
1782
  break;
843
- case i.DEFAULT:
844
- e.advance(2), o.push({
845
- type: C.Case,
1783
+ case TokenType.DEFAULT:
1784
+ cursor.advance(2);
1785
+ cases.push({
1786
+ type: ASTNodeType.Case,
846
1787
  condition: null,
847
- children: A(e, t)
1788
+ children: parseBlockChildren(cursor, parseNode)
848
1789
  });
849
1790
  break;
850
1791
  }
851
- return e.advance(), {
852
- type: C.Switch,
853
- expression: a,
854
- cases: o
1792
+ cursor.advance();
1793
+ return {
1794
+ type: ASTNodeType.Switch,
1795
+ expression,
1796
+ cases
855
1797
  };
856
1798
  }
857
1799
  //#endregion
858
1800
  //#region ../packages/compiler/src/parser/states/parse-text.state.ts
859
- function z(e, t, n) {
860
- return e.advance(), {
861
- type: C.Text,
862
- value: n.parts[0]
1801
+ /**
1802
+ * Parses a TEXT token into a `TextNode`.
1803
+ *
1804
+ * @param cursor Parser cursor; advanced past the TEXT token.
1805
+ * @param _parseNode Function to parse the next AST node.
1806
+ * @param token The TEXT token containing the raw text content.
1807
+ * @returns The parsed `TextNode`.
1808
+ */
1809
+ function parseText(cursor, _parseNode, token) {
1810
+ cursor.advance();
1811
+ return {
1812
+ type: ASTNodeType.Text,
1813
+ value: token.parts[0]
863
1814
  };
864
1815
  }
865
1816
  //#endregion
866
1817
  //#region ../packages/compiler/src/parser/parser.ts
867
- var B = class {
1818
+ /**
1819
+ * Parser class that transforms a stream of tokens (from the Lexer)
1820
+ * into an Abstract Syntax Tree (AST) representing the template structure.
1821
+ *
1822
+ * Responsibilities:
1823
+ * - Parse text nodes, elements, attributes, events, and interpolations
1824
+ * - Maintain cursor state for sequential token consumption
1825
+ * - Detect tag boundaries and nested structures
1826
+ *
1827
+ * The parser assumes that the token stream is syntactically valid according
1828
+ * to the Lexer rules. Parsing errors are thrown as exceptions.
1829
+ */
1830
+ var Parser = class {
868
1831
  tokens;
1832
+ /**
1833
+ * Internal cursor for navigating tokens
1834
+ */
869
1835
  _cursor;
1836
+ /**
1837
+ * Mapping of token types to their corresponding parser transition functions,
1838
+ * which handle the logic for parsing each token type into AST nodes.
1839
+ */
870
1840
  _states = {
871
- [i.TEXT]: z,
872
- [i.INTERPOLATION_EXPRESSION]: w,
873
- [i.INTERPOLATION_LITERAL]: w,
874
- [i.TAG_OPEN_NAME]: le,
875
- [i.IF]: I,
876
- [i.FOR]: j,
877
- [i.SWITCH]: R,
878
- [i.CONST_DECLARATION]: oe
1841
+ [TokenType.TEXT]: parseText,
1842
+ [TokenType.INTERPOLATION_EXPRESSION]: parseInterpolation,
1843
+ [TokenType.INTERPOLATION_LITERAL]: parseInterpolation,
1844
+ [TokenType.TAG_OPEN_NAME]: parseElement,
1845
+ [TokenType.IF]: parseIfControlFlow,
1846
+ [TokenType.FOR]: parseForControlFlow,
1847
+ [TokenType.SWITCH]: parseSwitchControlFlow,
1848
+ [TokenType.CONST_DECLARATION]: parseConstDeclaration
879
1849
  };
880
- constructor(e) {
881
- this.tokens = e, this._cursor = new ae(this.tokens);
1850
+ /**
1851
+ * Creates a new Parser instance.
1852
+ *
1853
+ * @param tokens Array of tokens produced by the Lexer
1854
+ */
1855
+ constructor(tokens) {
1856
+ this.tokens = tokens;
1857
+ this._cursor = new ParserCursor(this.tokens);
882
1858
  }
1859
+ /**
1860
+ * Entry point for parsing the token stream into AST nodes.
1861
+ *
1862
+ * @returns Array of top-level AST nodes
1863
+ */
883
1864
  parse() {
884
- let e = [];
885
- for (; this._cursor.peek().type !== i.EOF;) {
886
- let t = this.parseNode();
887
- t && e.push(t);
1865
+ const nodes = new Array();
1866
+ while (this._cursor.peek().type !== TokenType.EOF) {
1867
+ const parseNode = this.parseNode();
1868
+ if (parseNode) nodes.push(parseNode);
888
1869
  }
889
- return e;
1870
+ return nodes;
890
1871
  }
1872
+ /**
1873
+ * Parses the next AST node based on the current token.
1874
+ *
1875
+ * @returns Parsed AST node
1876
+ * @throws Error if an unexpected token is encountered
1877
+ */
891
1878
  parseNode() {
892
- let e = this._cursor.peek();
893
- if (e.type === i.EOF) return;
894
- let t = this._states[e.type];
895
- if (!t) throw Error(`[Parser] No transition function for token type ${i[e.type]}`);
896
- return t(this._cursor, this.parseNode.bind(this), e);
1879
+ const token = this._cursor.peek();
1880
+ if (token.type === TokenType.EOF) return;
1881
+ const state = this._states[token.type];
1882
+ if (!state) throw new Error(`[Parser] No transition function for token type ${TokenType[token.type]}`);
1883
+ return state(this._cursor, this.parseNode.bind(this), token);
897
1884
  }
898
- }, V = class {
1885
+ };
1886
+ //#endregion
1887
+ //#region ../packages/compiler/src/render-generator/models/render-context.model.ts
1888
+ /**
1889
+ * Tracks identifier scope during render code generation.
1890
+ * Each `Context` instance represents one lexical scope (e.g. a `@for` loop body)
1891
+ * and can be chained to a parent context for outer-scope resolution.
1892
+ */
1893
+ var Context = class {
899
1894
  _identifiers;
900
1895
  _parent;
901
- constructor(e = [], t) {
902
- this._identifiers = e, this._parent = t;
1896
+ /**
1897
+ * Creates a new scope context.
1898
+ *
1899
+ * @param _identifiers List of loop variable names declared in this scope.
1900
+ * @param _parent Optional parent context representing the enclosing scope.
1901
+ */
1902
+ constructor(_identifiers = new Array(), _parent) {
1903
+ this._identifiers = _identifiers;
1904
+ this._parent = _parent;
903
1905
  }
904
- addIdentifier(e) {
905
- if (this.getIdentifier(e)) throw Error(`Identifier "${e}" is already declared in this scope.`);
906
- this._identifiers.push(e);
1906
+ addIdentifier(name) {
1907
+ if (this.getIdentifier(name)) throw new Error(`Identifier "${name}" is already declared in this scope.`);
1908
+ this._identifiers.push(name);
907
1909
  }
908
- getIdentifier(e) {
909
- return this._identifiers.includes(e) ? e : this._parent?.getIdentifier(e);
1910
+ /**
1911
+ * Returns the innermost identifier in the current scope chain, or
1912
+ * delegates to the parent context if none is found in this scope.
1913
+ *
1914
+ * @returns The most recently declared identifier name, or `undefined` if none exists.
1915
+ */
1916
+ getIdentifier(name) {
1917
+ return this._identifiers.includes(name) ? name : this._parent?.getIdentifier(name);
910
1918
  }
911
- }, H = new Set(/* @__PURE__ */ "undefined.NaN.Infinity.globalThis.eval.isFinite.isNaN.parseFloat.parseInt.decodeURI.decodeURIComponent.encodeURI.encodeURIComponent.escape.unescape.Object.Function.Boolean.Symbol.Error.AggregateError.EvalError.RangeError.ReferenceError.SyntaxError.TypeError.URIError.SuppressedError.InternalError.Number.BigInt.Math.Date.Temporal.String.RegExp.Array.TypedArray.Int8Array.Uint8Array.Uint8ClampedArray.Int16Array.Uint16Array.Int32Array.Uint32Array.BigInt64Array.BigUint64Array.Float16Array.Float32Array.Float64Array.Map.Set.WeakMap.WeakSet.ArrayBuffer.SharedArrayBuffer.DataView.Atomics.JSON.WeakRef.FinalizationRegistry.Iterator.AsyncIterator.Promise.GeneratorFunction.AsyncGeneratorFunction.Generator.AsyncGenerator.AsyncFunction.DisposableStack.AsyncDisposableStack.Reflect.Proxy.Intl.WebAssembly.window.document.navigator.location.history.screen.console.performance.crypto.fetch.alert.confirm.prompt.setTimeout.setInterval.clearTimeout.clearInterval.requestAnimationFrame.cancelAnimationFrame.queueMicrotask.structuredClone.URL.URLSearchParams.FormData.Headers.Request.Response.AbortController.AbortSignal.CustomEvent.Event.EventTarget.MutationObserver.IntersectionObserver.ResizeObserver.PerformanceObserver.Worker.SharedWorker.ServiceWorker.Blob.File.FileReader.ReadableStream.WritableStream.TransformStream.TextEncoder.TextDecoder.ImageData.Canvas.Storage.localStorage.sessionStorage.indexedDB.WebSocket.XMLHttpRequest.HTMLElement.HTMLInputElement.HTMLButtonElement.HTMLFormElement.HTMLAnchorElement.HTMLImageElement.HTMLVideoElement.HTMLAudioElement.HTMLCanvasElement.HTMLSelectElement.HTMLTextAreaElement.HTMLDivElement.HTMLSpanElement.HTMLParagraphElement.HTMLHeadingElement.HTMLTableElement.HTMLTableRowElement.HTMLTableCellElement.HTMLUListElement.HTMLOListElement.HTMLLIElement.HTMLLabelElement.HTMLDialogElement.HTMLDetailsElement.HTMLSlotElement.HTMLTemplateElement.SVGElement.SVGSVGElement.Element.Node.NodeList.DocumentFragment.ShadowRoot.Document.Window".split(".")), U = "this._root";
912
- function W(e, t) {
913
- return typeof e == "string" ? t.getIdentifier(e) ?? `this.${e}` : G(e, e, t);
1919
+ };
1920
+ //#endregion
1921
+ //#region ../packages/compiler/src/render-generator/utils/render-generator.utils.ts
1922
+ /**
1923
+ * Complete set of JavaScript global identifiers up to ES2026.
1924
+ *
1925
+ * These are identifiers that TypeScript's parser classifies as
1926
+ * `SyntaxKind.Identifier` (unlike true keywords such as `typeof`,
1927
+ * `instanceof`, `true`, `false`, `null` which have their own SyntaxKind)
1928
+ * but that must never be prefixed with `this.` inside a template expression
1929
+ * because they refer to well-known globals, not to component properties.
1930
+ *
1931
+ * Organised by ECMAScript category, mirroring the MDN "Standard built-in
1932
+ * objects" reference, plus the ES2026 additions (Temporal, DisposableStack,
1933
+ * AsyncDisposableStack, SuppressedError, Math.sumPrecise surface).
1934
+ *
1935
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
1936
+ */
1937
+ var GLOBAL_IDENTIFIERS = new Set([
1938
+ "undefined",
1939
+ "NaN",
1940
+ "Infinity",
1941
+ "globalThis",
1942
+ "eval",
1943
+ "isFinite",
1944
+ "isNaN",
1945
+ "parseFloat",
1946
+ "parseInt",
1947
+ "decodeURI",
1948
+ "decodeURIComponent",
1949
+ "encodeURI",
1950
+ "encodeURIComponent",
1951
+ "escape",
1952
+ "unescape",
1953
+ "Object",
1954
+ "Function",
1955
+ "Boolean",
1956
+ "Symbol",
1957
+ "Error",
1958
+ "AggregateError",
1959
+ "EvalError",
1960
+ "RangeError",
1961
+ "ReferenceError",
1962
+ "SyntaxError",
1963
+ "TypeError",
1964
+ "URIError",
1965
+ "SuppressedError",
1966
+ "InternalError",
1967
+ "Number",
1968
+ "BigInt",
1969
+ "Math",
1970
+ "Date",
1971
+ "Temporal",
1972
+ "String",
1973
+ "RegExp",
1974
+ "Array",
1975
+ "TypedArray",
1976
+ "Int8Array",
1977
+ "Uint8Array",
1978
+ "Uint8ClampedArray",
1979
+ "Int16Array",
1980
+ "Uint16Array",
1981
+ "Int32Array",
1982
+ "Uint32Array",
1983
+ "BigInt64Array",
1984
+ "BigUint64Array",
1985
+ "Float16Array",
1986
+ "Float32Array",
1987
+ "Float64Array",
1988
+ "Map",
1989
+ "Set",
1990
+ "WeakMap",
1991
+ "WeakSet",
1992
+ "ArrayBuffer",
1993
+ "SharedArrayBuffer",
1994
+ "DataView",
1995
+ "Atomics",
1996
+ "JSON",
1997
+ "WeakRef",
1998
+ "FinalizationRegistry",
1999
+ "Iterator",
2000
+ "AsyncIterator",
2001
+ "Promise",
2002
+ "GeneratorFunction",
2003
+ "AsyncGeneratorFunction",
2004
+ "Generator",
2005
+ "AsyncGenerator",
2006
+ "AsyncFunction",
2007
+ "DisposableStack",
2008
+ "AsyncDisposableStack",
2009
+ "Reflect",
2010
+ "Proxy",
2011
+ "Intl",
2012
+ "WebAssembly",
2013
+ "window",
2014
+ "document",
2015
+ "navigator",
2016
+ "location",
2017
+ "history",
2018
+ "screen",
2019
+ "console",
2020
+ "performance",
2021
+ "crypto",
2022
+ "fetch",
2023
+ "alert",
2024
+ "confirm",
2025
+ "prompt",
2026
+ "setTimeout",
2027
+ "setInterval",
2028
+ "clearTimeout",
2029
+ "clearInterval",
2030
+ "requestAnimationFrame",
2031
+ "cancelAnimationFrame",
2032
+ "queueMicrotask",
2033
+ "structuredClone",
2034
+ "URL",
2035
+ "URLSearchParams",
2036
+ "FormData",
2037
+ "Headers",
2038
+ "Request",
2039
+ "Response",
2040
+ "AbortController",
2041
+ "AbortSignal",
2042
+ "CustomEvent",
2043
+ "Event",
2044
+ "EventTarget",
2045
+ "MutationObserver",
2046
+ "IntersectionObserver",
2047
+ "ResizeObserver",
2048
+ "PerformanceObserver",
2049
+ "Worker",
2050
+ "SharedWorker",
2051
+ "ServiceWorker",
2052
+ "Blob",
2053
+ "File",
2054
+ "FileReader",
2055
+ "ReadableStream",
2056
+ "WritableStream",
2057
+ "TransformStream",
2058
+ "TextEncoder",
2059
+ "TextDecoder",
2060
+ "ImageData",
2061
+ "Canvas",
2062
+ "Storage",
2063
+ "localStorage",
2064
+ "sessionStorage",
2065
+ "indexedDB",
2066
+ "WebSocket",
2067
+ "XMLHttpRequest",
2068
+ "HTMLElement",
2069
+ "HTMLInputElement",
2070
+ "HTMLButtonElement",
2071
+ "HTMLFormElement",
2072
+ "HTMLAnchorElement",
2073
+ "HTMLImageElement",
2074
+ "HTMLVideoElement",
2075
+ "HTMLAudioElement",
2076
+ "HTMLCanvasElement",
2077
+ "HTMLSelectElement",
2078
+ "HTMLTextAreaElement",
2079
+ "HTMLDivElement",
2080
+ "HTMLSpanElement",
2081
+ "HTMLParagraphElement",
2082
+ "HTMLHeadingElement",
2083
+ "HTMLTableElement",
2084
+ "HTMLTableRowElement",
2085
+ "HTMLTableCellElement",
2086
+ "HTMLUListElement",
2087
+ "HTMLOListElement",
2088
+ "HTMLLIElement",
2089
+ "HTMLLabelElement",
2090
+ "HTMLDialogElement",
2091
+ "HTMLDetailsElement",
2092
+ "HTMLSlotElement",
2093
+ "HTMLTemplateElement",
2094
+ "SVGElement",
2095
+ "SVGSVGElement",
2096
+ "Element",
2097
+ "Node",
2098
+ "NodeList",
2099
+ "DocumentFragment",
2100
+ "ShadowRoot",
2101
+ "Document",
2102
+ "Window"
2103
+ ]);
2104
+ var ROOT_NODE = "this._root";
2105
+ /**
2106
+ * Resolves references to component properties inside a template expression.
2107
+ *
2108
+ * Identifiers that are not found in the active scope chain and are not
2109
+ * well-known globals are prefixed with `this.` so they resolve against
2110
+ * the component instance at runtime.
2111
+ *
2112
+ * The original formatting of the expression — parentheses, spacing,
2113
+ * operator tokens, member access dots — is preserved verbatim by delegating
2114
+ * to `node.getText()` for any subtree that contains no resolvable identifiers.
2115
+ *
2116
+ * @param expression - Either a raw identifier string or a validated
2117
+ * `ts.Expression` node produced by `validateExpression`.
2118
+ * @param context - The active template scope context.
2119
+ * @returns The resolved expression as a JavaScript string ready for codegen.
2120
+ *
2121
+ * @example
2122
+ * // Simple identifier
2123
+ * resolveExpression('items', context) // → 'this.items'
2124
+ *
2125
+ * @example
2126
+ * // Complex expression — formatting preserved
2127
+ * resolveExpression(node, context)
2128
+ * // typeof id !== 'boolean' || pippo instanceof HTMLElement
2129
+ * // → typeof this.id !== 'boolean' || this.pippo instanceof HTMLElement
2130
+ */
2131
+ function resolveExpression(expression, context) {
2132
+ return typeof expression === "string" ? context.getIdentifier(expression) ?? `this.${expression}` : emitNode(expression, expression, context);
914
2133
  }
915
- function G(e, t, r) {
916
- if (n.isIdentifier(e) && q(e, t)) return r.getIdentifier(e.text) ?? `this.${e.text}`;
917
- if (!K(e, t)) return e.getText();
918
- let i = e.getSourceFile().text, a = "", o = e.getStart();
919
- return n.forEachChild(e, (t) => {
920
- a = `${a}${i.slice(o, t.getStart())}${G(t, e, r)}`, o = t.getEnd();
921
- }), `${a}${i.slice(o, e.getEnd())}`;
2134
+ /**
2135
+ * Emits the resolved text for a node.
2136
+ *
2137
+ * - If the node has no resolvable identifiers in its subtree, emits
2138
+ * `node.getText()` verbatim — preserving all original spacing,
2139
+ * parentheses, dots, and punctuation.
2140
+ * - If the node is a resolvable Identifier, emits the resolved name.
2141
+ * - Otherwise recurses into children and concatenates their output.
2142
+ */
2143
+ function emitNode(node, parent, context) {
2144
+ if (ts.isIdentifier(node) && needsResolution(node, parent)) return context.getIdentifier(node.text) ?? `this.${node.text}`;
2145
+ if (!containsResolvableIdentifier(node, parent)) return node.getText();
2146
+ const sourceText = node.getSourceFile().text;
2147
+ let result = "";
2148
+ let lastEnd = node.getStart();
2149
+ ts.forEachChild(node, (child) => {
2150
+ result = `${result}${sourceText.slice(lastEnd, child.getStart())}${emitNode(child, node, context)}`;
2151
+ lastEnd = child.getEnd();
2152
+ });
2153
+ return `${result}${sourceText.slice(lastEnd, node.getEnd())}`;
922
2154
  }
923
- function K(e, t) {
924
- if (n.isIdentifier(e) && q(e, t)) return !0;
925
- let r = !1;
926
- return n.forEachChild(e, (t) => {
927
- r ||= K(t, e);
928
- }), r;
2155
+ /**
2156
+ * Returns true if the subtree rooted at `node` contains at least one
2157
+ * Identifier that needs context resolution.
2158
+ *
2159
+ * Short-circuits as soon as one is found to avoid visiting the whole tree.
2160
+ */
2161
+ function containsResolvableIdentifier(node, parent) {
2162
+ if (ts.isIdentifier(node) && needsResolution(node, parent)) return true;
2163
+ let found = false;
2164
+ ts.forEachChild(node, (child) => {
2165
+ if (!found) found = containsResolvableIdentifier(child, node);
2166
+ });
2167
+ return found;
929
2168
  }
930
- function q(e, t) {
931
- return !(n.isPropertyAccessExpression(t) && t.name === e || H.has(e.text));
2169
+ /**
2170
+ * Returns true if the identifier needs to be resolved against the context
2171
+ * or prefixed with `this.` — i.e. it is not a global/builtin identifier
2172
+ * and not the property-name side of a member access expression.
2173
+ */
2174
+ function needsResolution(node, parent) {
2175
+ return !(ts.isPropertyAccessExpression(parent) && parent.name === node || GLOBAL_IDENTIFIERS.has(node.text));
932
2176
  }
933
- function de(e, t, n) {
934
- return (t === "this._root" ? `${e.tagName}${n}` : `${t}_${e.tagName}${n}`).replace(/-/g, "_");
2177
+ /**
2178
+ * Generates a unique variable name for an element based on its tag name and parent node.
2179
+ * If the parent node is 'this._root', the identifier will be based solely on the element's type.
2180
+ * Otherwise, it will be prefixed with the parent node's name to ensure uniqueness.
2181
+ * @param node The ElementNode for which to generate the identifier.
2182
+ * @param parentNode The name of the parent node to ensure uniqueness in the context of nested elements.
2183
+ * @returns A string representing the unique variable name for the element.
2184
+ */
2185
+ function getElementIdentifier(node, parentNode, index) {
2186
+ return (parentNode !== "this._root" ? `${parentNode}_${node.tagName}${index}` : `${node.tagName}${index}`).replace(/-/g, "_");
935
2187
  }
936
- function J(e, t, n = "text") {
937
- return (e === "this._root" ? `${n}${t}` : `${e}_${n}${t}`).replace(/-/g, "_");
2188
+ function getTextIdentifier(parentNode, index, prefix = "text") {
2189
+ return (parentNode !== "this._root" ? `${parentNode}_${prefix}${index}` : `${prefix}${index}`).replace(/-/g, "_");
938
2190
  }
939
2191
  //#endregion
940
2192
  //#region ../packages/compiler/src/render-generator/states/process-const-declaration.state.ts
941
- function fe(e, t, n, r) {
942
- return r.addIdentifier(e.varName), [`const ${e.varName} = ${W(e.expression, r)};`];
2193
+ /**
2194
+ * Generates code for a `@const` declaration node.
2195
+ * Emits a `const name = expression;` JavaScript statement.
2196
+ *
2197
+ * @param node The `ConstDeclarationNode` to process.
2198
+ * @param _nodeName Unused node name.
2199
+ * @param _parentNode Unused parent node name.
2200
+ * @param _context Unused render context.
2201
+ * @returns Array containing the generated const statement string.
2202
+ */
2203
+ function processConstDeclaration(node, _nodeName, _parentNode, context) {
2204
+ context.addIdentifier(node.varName);
2205
+ return [`const ${node.varName} = ${resolveExpression(node.expression, context)};`];
943
2206
  }
944
2207
  //#endregion
945
2208
  //#region ../packages/compiler/src/render-generator/states/process-element.state.ts
946
- function pe(e, t, n, r) {
947
- let i = new V([], r);
2209
+ /**
2210
+ * Generates code for an HTML element node: creates the DOM element, sets attributes,
2211
+ * attaches event listeners, appends it to the parent, and recursively processes children.
2212
+ *
2213
+ * @param node The `ElementNode` to process.
2214
+ * @param nodeName Variable name to use for the created DOM element.
2215
+ * @param parentNode Variable name of the parent DOM node to append to.
2216
+ * @param context Current render scope context.
2217
+ * @returns Array of generated code lines.
2218
+ */
2219
+ function processElement(node, nodeName, parentNode, context) {
2220
+ const childrenContext = new Context([], context);
948
2221
  return [
949
- `const ${t} = document.createElement("${e.tagName}");`,
950
- ...e.attributes?.map((e) => {
951
- let n = e.value;
952
- return typeof n == "string" ? `${t}.setAttribute('${e.name}', ${n});` : `effect(() => ${t}.setAttribute('${e.name}', ${W(n.expression, r)}));`;
2222
+ `const ${nodeName} = document.createElement("${node.tagName}");`,
2223
+ ...node.attributes?.map((attr) => {
2224
+ const value = attr.value;
2225
+ return typeof value === "string" ? `${nodeName}.setAttribute('${attr.name}', ${value});` : `effect(() => ${nodeName}.setAttribute('${attr.name}', ${resolveExpression(value.expression, context)}));`;
953
2226
  }) || [],
954
- ...e.events?.map((e) => `${t}.addEventListener("${e.name}", ($event) => this.${e.handler});`) || [],
955
- `${n}.appendChild(${t});`,
956
- ...e.children.map((e, n) => $(e, n.toString(), t, i)).flat()
2227
+ ...node.events?.map((event) => `${nodeName}.addEventListener("${event.name}", ($event) => this.${event.handler});`) || [],
2228
+ `${parentNode}.appendChild(${nodeName});`,
2229
+ ...node.children.map((child, i) => processNode(child, i.toString(), nodeName, childrenContext)).flat()
957
2230
  ];
958
2231
  }
959
2232
  //#endregion
960
2233
  //#region ../packages/compiler/src/render-generator/states/process-for.state.ts
961
- function me(e, n, r, i) {
962
- let a = e.iterableSource, o = i.getIdentifier(a) ?? `this.${a}`, s = J(r, n, "items"), c = J(r, n, "i"), l = Y(e, "$index"), u = Y(e, "$first"), d = Y(e, "$last"), f = Y(e, "$even"), p = Y(e, "$odd"), m = new V([
963
- e.itemAlias,
964
- l,
965
- u,
966
- d,
967
- f,
968
- p
969
- ], i);
2234
+ /**
2235
+ * Generates code for a `@for` iteration node.
2236
+ *
2237
+ * Emits a classic index-based `for` loop with all implicit variables
2238
+ * declared at the top of the loop body:
2239
+ *
2240
+ * ```javascript
2241
+ * for (let $i = 0; $i < ctx_items.length; $i++) {
2242
+ * const item = items[$i];
2243
+ * const $index = $i;
2244
+ * const $first = $i === 0;
2245
+ * const $last = $i === items.length - 1;
2246
+ * const $even = $i % 2 === 0;
2247
+ * const $odd = $i % 2 !== 0;
2248
+ * // ... child nodes
2249
+ * }
2250
+ * ```
2251
+ *
2252
+ * The iterable identifier is resolved through the active {@link Context}:
2253
+ * if found in scope it is used as-is, otherwise `this.` is prepended.
2254
+ *
2255
+ * The internal loop counter is always named `$i_<nodeName>` to avoid
2256
+ * collisions when `@for` blocks are nested.
2257
+ *
2258
+ * @param node - The `ForNode` to process.
2259
+ * @param nodeName - Base variable name prefix used for child nodes and
2260
+ * to produce a unique loop counter identifier.
2261
+ * @param parentNode - Variable name of the parent DOM node.
2262
+ * @param parentContext - The enclosing scope context.
2263
+ * @returns Array of generated code lines.
2264
+ */
2265
+ function processFor(node, nodeName, parentNode, parentContext) {
2266
+ const iterableSource = node.iterableSource;
2267
+ const iterableExpr = parentContext.getIdentifier(iterableSource) ?? `this.${iterableSource}`;
2268
+ const itemsName = getTextIdentifier(parentNode, nodeName, "items");
2269
+ const counterName = getTextIdentifier(parentNode, nodeName, "i");
2270
+ const indexName = resolveImplicit(node, "$index");
2271
+ const firstName = resolveImplicit(node, "$first");
2272
+ const lastName = resolveImplicit(node, "$last");
2273
+ const evenName = resolveImplicit(node, "$even");
2274
+ const oddName = resolveImplicit(node, "$odd");
2275
+ const forContext = new Context([
2276
+ node.itemAlias,
2277
+ indexName,
2278
+ firstName,
2279
+ lastName,
2280
+ evenName,
2281
+ oddName
2282
+ ], parentContext);
970
2283
  return [
971
- `const ${s} = ${o};`,
972
- `for (let ${c} = 0; ${c} < ${s}.length; ${c}++) {`,
973
- ...t(`const ${e.itemAlias} = ${s}[${c}];`, `const ${l} = ${c};`, `const ${u} = ${c} === 0;`, `const ${d} = ${c} === ${s}.length - 1;`, `const ${f} = ${c} % 2 === 0;`, `const ${p} = ${c} % 2 !== 0;`),
974
- ...e.children.flatMap((e, i) => t(...$(e, `${n}_${i}`, r, m))),
2284
+ `const ${itemsName} = ${iterableExpr};`,
2285
+ `for (let ${counterName} = 0; ${counterName} < ${itemsName}.length; ${counterName}++) {`,
2286
+ ...indent(`const ${node.itemAlias} = ${itemsName}[${counterName}];`, `const ${indexName} = ${counterName};`, `const ${firstName} = ${counterName} === 0;`, `const ${lastName} = ${counterName} === ${itemsName}.length - 1;`, `const ${evenName} = ${counterName} % 2 === 0;`, `const ${oddName} = ${counterName} % 2 !== 0;`),
2287
+ ...node.children.flatMap((child, i) => indent(...processNode(child, `${nodeName}_${i}`, parentNode, forContext))),
975
2288
  "}"
976
2289
  ];
977
2290
  }
978
- function Y(e, t) {
979
- return e.implicitAliases.get(t) ?? t;
2291
+ /**
2292
+ * Resolves the name that should be used in generated code for a given
2293
+ * implicit variable.
2294
+ *
2295
+ * If the template declared an explicit alias for the variable
2296
+ * (e.g. `; $index = i`) that alias is returned. Otherwise the default
2297
+ * implicit variable name (e.g. `$index`) is used.
2298
+ *
2299
+ * @param node - The `ForNode` whose implicit alias map is consulted.
2300
+ * @param implicit - The implicit variable to look up (e.g. `'$index'`).
2301
+ * @returns The alias string if one was declared, otherwise `implicit` itself.
2302
+ */
2303
+ function resolveImplicit(node, implicit) {
2304
+ return node.implicitAliases.get(implicit) ?? implicit;
980
2305
  }
981
2306
  //#endregion
982
2307
  //#region ../packages/compiler/src/render-generator/states/process-if.state.ts
983
- function he(e, t, n, r) {
984
- let i = new V([], r), a = [
985
- `if (${W(e.conditionNode, r)}) {`,
986
- ...X(e, t, n, i),
2308
+ /**
2309
+ * Generates code for an `@if` conditional node.
2310
+ * Emits an `if (...) { ... }` block, appending an `else { ... }` block if an alternate exists.
2311
+ *
2312
+ * @param node The `IfNode` to process.
2313
+ * @param nodeName Base variable name prefix for child nodes.
2314
+ * @param parentNode Variable name of the parent DOM node.
2315
+ * @param context Current render scope context.
2316
+ * @returns Array of generated code lines.
2317
+ */
2318
+ function processIf(node, nodeName, parentNode, context) {
2319
+ const ifContext = new Context([], context);
2320
+ const code = [
2321
+ `if (${resolveExpression(node.conditionNode, context)}) {`,
2322
+ ...processConsequent(node, nodeName, parentNode, ifContext),
987
2323
  "}"
988
- ], o = e.alternate;
989
- for (; o?.type === C.ElseIf;) {
990
- let e = new V([], r);
991
- a[a.length - 1] += ` else if (${W(o.conditionNode, r)}) {`, a.push(...X(o, t, n, e), "}"), o = o.alternate;
2324
+ ];
2325
+ let alt = node.alternate;
2326
+ while (alt?.type === ASTNodeType.ElseIf) {
2327
+ const elseIfContext = new Context([], context);
2328
+ code[code.length - 1] += ` else if (${resolveExpression(alt.conditionNode, context)}) {`;
2329
+ code.push(...processConsequent(alt, nodeName, parentNode, elseIfContext), "}");
2330
+ alt = alt.alternate;
992
2331
  }
993
- if (o) {
994
- let e = new V([], r);
995
- a[a.length - 1] += " else {", a.push(...X(o, t, n, e), "}");
2332
+ if (alt) {
2333
+ const elseContext = new Context([], context);
2334
+ code[code.length - 1] += " else {";
2335
+ code.push(...processConsequent(alt, nodeName, parentNode, elseContext), "}");
996
2336
  }
997
- return a;
2337
+ return code;
998
2338
  }
999
- function X(e, n, r, i) {
1000
- return e.consequent.map((e, a) => t(...$(e, `${n}_${a}`, r, i))).flat();
2339
+ function processConsequent(node, nodeName, parentNode, context) {
2340
+ return node.consequent.map((child, i) => indent(...processNode(child, `${nodeName}_${i}`, parentNode, context))).flat();
1001
2341
  }
1002
2342
  //#endregion
1003
2343
  //#region ../packages/compiler/src/render-generator/states/process-switch.state.ts
1004
- function Z(e, n, r, i) {
2344
+ /**
2345
+ * Generates code for a `@switch` node.
2346
+ * Emits a `switch (expression) { case ...: { ... break; } ... }` block.
2347
+ *
2348
+ * @param node The `SwitchNode` to process.
2349
+ * @param nodeName Base variable name prefix for child nodes.
2350
+ * @param parentNode Variable name of the parent DOM node.
2351
+ * @param context Current render scope context.
2352
+ * @param processNode Recursive node processor function.
2353
+ * @returns Array of generated code lines.
2354
+ */
2355
+ function processSwitch(node, nodeName, parentNode, context) {
1005
2356
  return [
1006
- `switch (${W(e.expression, i)}) {`,
1007
- ...e.cases.map((e) => [...t(...e.condition ? e.condition.map((e, t, n) => `case ${e}:${t === n.length - 1 ? " {" : ""}`) : ["default: {"], ...e.children.map((e, a) => t(...$(e, `${n}_${a}_${a}`, r, new V([], i)))).flat(), `${t("break;")}`, "}")]).flat(),
2357
+ `switch (${resolveExpression(node.expression, context)}) {`,
2358
+ ...node.cases.map((caseNode) => [...indent(...!caseNode.condition ? ["default: {"] : caseNode.condition.map((cond, i, arr) => `case ${cond}:${i === arr.length - 1 ? " {" : ""}`), ...caseNode.children.map((child, i) => indent(...processNode(child, `${nodeName}_${i}_${i}`, parentNode, new Context([], context)))).flat(), `${indent("break;")}`, `}`)]).flat(),
1008
2359
  "}"
1009
2360
  ];
1010
2361
  }
1011
2362
  //#endregion
1012
2363
  //#region ../packages/compiler/src/render-generator/states/process-text-and-interpolation.state.ts
1013
- function ge(e, t, n, r) {
1014
- let i = e.type === C.Text ? JSON.stringify(e.value) : W(e.expression, r);
2364
+ /**
2365
+ * Generates code for a text or interpolation node.
2366
+ * Creates a DOM text node with either a JSON-stringified literal or a resolved expression,
2367
+ * then appends it to the parent DOM node.
2368
+ *
2369
+ * @param node A `TextNode` or `InterpolationNode` to process.
2370
+ * @param nodeName Variable name for the created text node.
2371
+ * @param parentNode Variable name of the parent DOM node.
2372
+ * @param _context Unused render context.
2373
+ * @returns Array of two generated code lines: the text node creation and the appendChild call.
2374
+ */
2375
+ function processTextAndInterpolation(node, nodeName, parentNode, context) {
2376
+ const textValue = node.type === ASTNodeType.Text ? JSON.stringify(node.value) : resolveExpression(node.expression, context);
1015
2377
  return [
1016
- `const ${t} = document.createTextNode(${i});`,
1017
- `${n}.appendChild(${t});`,
1018
- `effect(() => ${t}.textContent = ${i});`
2378
+ `const ${nodeName} = document.createTextNode(${textValue});`,
2379
+ `${parentNode}.appendChild(${nodeName});`,
2380
+ `effect(() => ${nodeName}.textContent = ${textValue});`
1019
2381
  ];
1020
2382
  }
1021
2383
  //#endregion
1022
2384
  //#region ../packages/compiler/src/render-generator/render-generator.ts
1023
- var Q = /* @__PURE__ */ new Map();
1024
- function _e(e, n) {
1025
- Q.clear();
1026
- let r = new V(), i = [
2385
+ var nodeToProcess = /* @__PURE__ */ new Map();
2386
+ /**
2387
+ * Generates the TypeScript body of a render function from an AST.
2388
+ *
2389
+ * @param ast Top-level AST nodes produced by the Parser
2390
+ * @returns String containing the render function body
2391
+ */
2392
+ function generateRenderFunction(ast, cssVariableName) {
2393
+ nodeToProcess.clear();
2394
+ const context = new Context();
2395
+ const renderFunctions = [
1027
2396
  "_render() {",
1028
- ...t(...[n ? `this._root.adoptedStyleSheets = [${n}];` : void 0].filter((e) => !!e), ...e.map((e, t) => [...$(e, t.toString(), U, r)]).flat()),
2397
+ ...indent(...[cssVariableName ? `this._root.adoptedStyleSheets = [${cssVariableName}];` : void 0].filter((line) => !!line), ...ast.map((node, i) => [...processNode(node, i.toString(), ROOT_NODE, context)]).flat()),
1029
2398
  "}"
1030
2399
  ];
1031
- for (; Q.size > 0;) {
1032
- let [e, n] = Q.entries().next().value;
1033
- i.push(`${e} {`, ...t(...n()), "}"), Q.delete(e);
2400
+ while (nodeToProcess.size > 0) {
2401
+ const [key, fn] = nodeToProcess.entries().next().value;
2402
+ renderFunctions.push(`${key} {`, ...indent(...fn()), "}");
2403
+ nodeToProcess.delete(key);
1034
2404
  }
1035
- return i.join("\n");
2405
+ return renderFunctions.join("\n");
1036
2406
  }
1037
- function $(e, t, n, r) {
1038
- switch (e.type) {
1039
- case C.Text:
1040
- case C.Interpolation: return ge(e, J(n, t), n, r);
1041
- case C.Element: return pe(e, de(e, n, t), n, r);
1042
- case C.If:
1043
- let i = `if_${t}()`;
1044
- return Q.set(i, () => he(e, t, n, r)), [`this.${i};`];
1045
- case C.For:
1046
- let a = `for_${t}()`;
1047
- return Q.set(a, () => me(e, t, n, r)), [`this.${a};`];
1048
- case C.Switch:
1049
- let o = `switch_${t}()`;
1050
- return Q.set(o, () => Z(e, t, n, r)), [`this.${o};`];
1051
- case C.ConstDeclaration: return fe(e, t, n, r);
2407
+ /**
2408
+ * Generates code that appends `nodeName` to `parentNode`.
2409
+ * For flow control nodes no single var is produced; instead multiple children
2410
+ * are appended directly inside the control flow block.
2411
+ */
2412
+ function processNode(node, nodeName, parentNode, context) {
2413
+ switch (node.type) {
2414
+ case ASTNodeType.Text:
2415
+ case ASTNodeType.Interpolation: return processTextAndInterpolation(node, getTextIdentifier(parentNode, nodeName), parentNode, context);
2416
+ case ASTNodeType.Element: return processElement(node, getElementIdentifier(node, parentNode, nodeName), parentNode, context);
2417
+ case ASTNodeType.If:
2418
+ const keyIf = `if_${nodeName}()`;
2419
+ nodeToProcess.set(keyIf, () => processIf(node, nodeName, parentNode, context));
2420
+ return [`this.${keyIf};`];
2421
+ case ASTNodeType.For:
2422
+ const keyFor = `for_${nodeName}()`;
2423
+ nodeToProcess.set(keyFor, () => processFor(node, nodeName, parentNode, context));
2424
+ return [`this.${keyFor};`];
2425
+ case ASTNodeType.Switch:
2426
+ const keySwitch = `switch_${nodeName}()`;
2427
+ nodeToProcess.set(keySwitch, () => processSwitch(node, nodeName, parentNode, context));
2428
+ return [`this.${keySwitch};`];
2429
+ case ASTNodeType.ConstDeclaration: return processConstDeclaration(node, nodeName, parentNode, context);
1052
2430
  default: return [];
1053
2431
  }
1054
2432
  }
1055
2433
  //#endregion
1056
2434
  //#region ../packages/compiler/src/compile.ts
1057
- function ve(e, t) {
1058
- return _e(new B(new ie(e).tokenize()).parse(), t);
2435
+ function compile(input, cssVariableName) {
2436
+ return generateRenderFunction(new Parser(new Lexer(input).tokenize()).parse(), cssVariableName);
1059
2437
  }
1060
2438
  //#endregion
1061
- export { ve as compile };
1062
-
1063
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieGFlbmRhci1jb21waWxlci5lcy5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvdHlwZXMvbGV4ZXItc3RhdGUuZW51bS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci90eXBlcy90b2tlbi10eXBlLmVudW0udHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL2F0dHJpYnV0ZS5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci91dGlscy9jb25zdW1lLWZsb3ctY29udHJvbC1jb25kaXRpb24udXRpbHMudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL2Nhc2UtZmxvdy1jb250cm9sLWNvbmRpdGlvbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9zdGF0ZXMvY29uc3QtZGVjbGFyYXRpb24udHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL2V2ZW50LnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2xleGVyL3N0YXRlcy9mbG93LWNvbnRyb2wtYmxvY2suc3RhdGUudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL2RlZmF1bHQtZmxvdy1jb250cm9sLWNvbmRpdGlvbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9zdGF0ZXMvZmxvdy1jb250cm9sLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2xleGVyL3N0YXRlcy9pbnRlcnBvbGF0aW9uLWV4cHJlc3Npb24uc3RhdGUudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL2ludGVycG9sYXRpb24tbGl0ZXJhbC5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy91dGlscy9jaGFycy51dGlscy50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9zdGF0ZXMvaW50ZXJwb2xhdGlvbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9zdGF0ZXMvdGFnLWJvZHkuc3RhdGUudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbGV4ZXIvc3RhdGVzL3RhZy1jbG9zZS5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9zdGF0ZXMvdGFnLW9wZW4tZW5kLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2xleGVyL3N0YXRlcy90YWctb3Blbi1uYW1lLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2xleGVyL3N0YXRlcy90ZXh0LnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2xleGVyL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9sZXhlci9sZXhlci50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvbW9kZWxzL3BhcnNlci1jdXJzb3IubW9kZWwudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvcGFyc2VyL3R5cGVzL25vZGUuZW51bS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvc3RhdGVzL3BhcnNlLWNvbnN0LWRlY2xhcmF0aW9uLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3BhcnNlci9zdGF0ZXMvcGFyc2UtaW50ZXJwb2xhdGlvbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvc3RhdGVzL3BhcnNlLWF0dHJpYnV0ZS5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvc3RhdGVzL3BhcnNlLWV2ZW50LnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3BhcnNlci9zdGF0ZXMvcGFyc2UtZWxlbWVudC5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvdXRpbHMvZXhwcmVzc2lvbi12YWxpZGF0b3IudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvcGFyc2VyL3N0YXRlcy9wYXJzZS1ibG9jay1jaGlsZHJlbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvc3RhdGVzL3BhcnNlLWZvci5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvc3RhdGVzL3BhcnNlLWlmLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3BhcnNlci9zdGF0ZXMvcGFyc2Utc3dpdGNoLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3BhcnNlci9zdGF0ZXMvcGFyc2UtdGV4dC5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9wYXJzZXIvcGFyc2VyLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlci1nZW5lcmF0b3IvbW9kZWxzL3JlbmRlci1jb250ZXh0Lm1vZGVsLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlci1nZW5lcmF0b3IvdXRpbHMvcmVuZGVyLWdlbmVyYXRvci51dGlscy50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9yZW5kZXItZ2VuZXJhdG9yL3N0YXRlcy9wcm9jZXNzLWNvbnN0LWRlY2xhcmF0aW9uLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlci1nZW5lcmF0b3Ivc3RhdGVzL3Byb2Nlc3MtZWxlbWVudC5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9yZW5kZXItZ2VuZXJhdG9yL3N0YXRlcy9wcm9jZXNzLWZvci5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9yZW5kZXItZ2VuZXJhdG9yL3N0YXRlcy9wcm9jZXNzLWlmLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlci1nZW5lcmF0b3Ivc3RhdGVzL3Byb2Nlc3Mtc3dpdGNoLnN0YXRlLnRzIiwiLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlci1nZW5lcmF0b3Ivc3RhdGVzL3Byb2Nlc3MtdGV4dC1hbmQtaW50ZXJwb2xhdGlvbi5zdGF0ZS50cyIsIi4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9yZW5kZXItZ2VuZXJhdG9yL3JlbmRlci1nZW5lcmF0b3IudHMiLCIuLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvY29tcGlsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogUmVwcmVzZW50cyB0aGUgc2V0IG9mIHN0YXRlcyB0aGUgbGV4ZXIgY2FuIGJlIGluIHdoaWxlIHByb2Nlc3NpbmcgdGVtcGxhdGUgaW5wdXQuXHJcbiAqL1xyXG5leHBvcnQgZW51bSBMZXhlclN0YXRlIHtcclxuICAvKipcclxuICAgKiBJbml0aWFsIHN0YXRlIGJlZm9yZSBhbnkgaW5wdXQgaGFzIGJlZW4gcHJvY2Vzc2VkLlxyXG4gICAqL1xyXG4gIFNUQVJUID0gJ3N0YXJ0JyxcclxuICAvKipcclxuICAgKiBDb25zdW1pbmcgcGxhaW4gdGV4dCBjb250ZW50IGJldHdlZW4gdGFncyBvciBhdCB0aGUgdG9wIGxldmVsLlxyXG4gICAqL1xyXG4gIFRFWFQgPSAndGV4dCcsXHJcbiAgLyoqXHJcbiAgICogQ29uc3VtaW5nIHRoZSBvcGVuaW5nIHRhZyBuYW1lIGFmdGVyIGA8YC5cclxuICAgKi9cclxuICBUQUdfT1BFTl9OQU1FID0gJ3RhZy1vcGVuLW5hbWUnLFxyXG4gIC8qKlxyXG4gICAqIEluc2lkZSBhbiBvcGVuIHRhZyBib2R5LCBzY2FubmluZyBmb3IgYXR0cmlidXRlcywgZXZlbnRzLCBvciB0aGUgY2xvc2luZyBgPmAuXHJcbiAgICovXHJcbiAgVEFHX0JPRFkgID0gJ3RhZy1ib2R5JyxcclxuICAvKipcclxuICAgKiBQcm9jZXNzaW5nIHRoZSBlbmQgb2YgYW4gb3BlbiB0YWc6IGA+YCBvciBgLz5gLlxyXG4gICAqL1xyXG4gIFRBR19PUEVOX0VORCA9ICd0YWctb3Blbi1lbmQnLFxyXG4gIC8qKlxyXG4gICAqIENvbnN1bWluZyBhIGNsb3NpbmcgdGFnIGA8L3RhZ05hbWU+YC5cclxuICAgKi9cclxuICBUQUdfQ0xPU0UgPSAndGFnLWNsb3NlJyxcclxuICAvKipcclxuICAgKiBDb25zdW1pbmcgYW4gSFRNTCBhdHRyaWJ1dGUgbmFtZSBhbmQgaXRzIG9wdGlvbmFsIHZhbHVlLlxyXG4gICAqL1xyXG4gIEFUVFJJQlVURSA9ICdhdHRyaWJ1dGUnLFxyXG4gIC8qKlxyXG4gICAqIENvbnN1bWluZyBhIERPTSBldmVudCBiaW5kaW5nIHN0YXJ0aW5nIHdpdGggYEBgLlxyXG4gICAqL1xyXG4gIEVWRU5UID0gJ2V2ZW50JyxcclxuICAvKipcclxuICAgKiBEaXNwYXRjaGluZyBhIGZsb3ctY29udHJvbCBrZXl3b3JkIChAaWYsIEBmb3IsIEBzd2l0Y2gsIGV0Yy4pLlxyXG4gICAqL1xyXG4gIEZMT1dfQ09OVFJPTCA9ICdmbG93LWNvbnRyb2wnLFxyXG4gIC8qKlxyXG4gICAqIENvbnN1bWluZyB0aGUgY29uZGl0aW9uIGV4cHJlc3Npb24gYCguLi4pYCBvZiBhIGZsb3ctY29udHJvbCBkaXJlY3RpdmUuXHJcbiAgICovXHJcbiAgRkxPV19DT05UUk9MX0NPTkRJVElPTiA9ICdmbG93LWNvbnRyb2wtY29uZGl0aW9uJyxcclxuICAvKipcclxuICAgKiBDb25zdW1pbmcgdGhlIGNvbmRpdGlvbiBleHByZXNzaW9uIGAoLi4uKWAgb2YgYSBAY2FzZSBkaXJlY3RpdmUuXHJcbiAgICogVGhpcyBpcyBuZWVkZWQgdG8gY29ycmVjdGx5IGhhbmRsZSBzcGVjaWFsIGNvbnNlY3V0aXZlcyBAY2FzZSBcclxuICAgKi9cclxuICBDQVNFX0ZMT1dfQ09OVFJPTF9DT05ESVRJT04gPSAnY2FzZS1mbG93LWNvbnRyb2wtY29uZGl0aW9uJyxcclxuICAvKipcclxuICAgKiBDb25zdW1pbmcgdGhlIG9wZW5pbmcgYHtgIG9mIGEgZmxvdy1jb250cm9sIGJsb2NrIGJvZHkuXHJcbiAgICovXHJcbiAgRkxPV19DT05UUk9MX0JMT0NLID0gJ2Zsb3ctY29udHJvbC1ibG9jaycsXHJcbiAgLyoqXHJcbiAgICogRGlzcGF0Y2hpbmcgYmV0d2VlbiBhbiBleHByZXNzaW9uIG9yIGxpdGVyYWwgaW50ZXJwb2xhdGlvbiBhZnRlciBge2AuXHJcbiAgICovXHJcbiAgSU5URVJQT0xBVElPTiA9ICdpbnRlcnBvbGF0aW9uJyxcclxuICAvKipcclxuICAgKiBDb25zdW1pbmcgYSBKYXZhU2NyaXB0IGV4cHJlc3Npb24gaW5zaWRlIGB7IH1gLlxyXG4gICAqL1xyXG4gIElOVEVSUE9MQVRJT05fRVhQUkVTU0lPTiA9ICdpbnRlcnBvbGF0aW9uLWV4cHJlc3Npb24nLFxyXG4gIC8qKlxyXG4gICAqIENvbnN1bWluZyBhIHRlbXBsYXRlLWxpdGVyYWwgc3RyaW5nIGluc2lkZSBgYCB7YC4uLmB9IGBgLlxyXG4gICAqL1xyXG4gIElOVEVSUE9MQVRJT05fTElURVJBTCA9ICdpbnRlcnBvbGF0aW9uLWxpdGVyYWwnLFxyXG4gIC8qKlxyXG4gICAqIENvbnN1bWluZyBhIGBAY29uc3QgbmFtZSA9IGV4cHJlc3Npb247YCBkZWNsYXJhdGlvbi5cclxuICAgKi9cclxuICBDT05TVF9ERUNMQVJBVElPTiA9ICdjb25zdC1kZWNsYXJhdGlvbidcclxufVxyXG4iLCIvKipcclxuICogRGlzY3JpbWluYW50IHZhbHVlcyB0aGF0IGlkZW50aWZ5IHRoZSB0eXBlIG9mIGVhY2ggdG9rZW4gZW1pdHRlZCBieSB0aGUgbGV4ZXIuXHJcbiAqL1xyXG5leHBvcnQgZW51bSBUb2tlblR5cGUge1xyXG4gIC8qKlxyXG4gICAqIEEgcGxhaW4gdGV4dCBub2RlIGJldHdlZW4gdGFncyBvciBhdCB0aGUgdG9wIGxldmVsLlxyXG4gICAqL1xyXG4gIFRFWFQsXHJcbiAgLyoqXHJcbiAgICogVGhlIG5hbWUgcG9ydGlvbiBvZiBhbiBvcGVuaW5nIHRhZywgZS5nLiBgZGl2YCBpbiBgPGRpdmAuXHJcbiAgICovXHJcbiAgVEFHX09QRU5fTkFNRSxcclxuICAvKipcclxuICAgKiBBIHNlbGYtY2xvc2luZyB0YWcgbWFya2VyIGAvPmAuXHJcbiAgICovXHJcbiAgVEFHX1NFTEZfQ0xPU0UsXHJcbiAgLyoqXHJcbiAgICogVGhlIGNsb3NpbmcgYD5gIG9mIGFuIG9wZW5pbmcgdGFnLlxyXG4gICAqL1xyXG4gIFRBR19PUEVOX0VORCxcclxuICAvKipcclxuICAgKiBUaGUgbmFtZSBwb3J0aW9uIG9mIGEgY2xvc2luZyB0YWcsIGUuZy4gYGRpdmAgaW4gYDwvZGl2PmAuXHJcbiAgICovXHJcbiAgVEFHX0NMT1NFX05BTUUsXHJcbiAgLyoqXHJcbiAgICogQW4gSFRNTCBhdHRyaWJ1dGUgYW5kIGl0cyBvcHRpb25hbCB2YWx1ZS5cclxuICAgKi9cclxuICBBVFRSSUJVVEUsXHJcbiAgLyoqXHJcbiAgICogQSBET00gZXZlbnQgYmluZGluZyBkZWNsYXJlZCB3aXRoIGBAZXZlbnROYW1lPWhhbmRsZXJgLlxyXG4gICAqL1xyXG4gIEVWRU5ULFxyXG4gIC8qKlxyXG4gICAqIEEgdGVtcGxhdGUtbGl0ZXJhbCBpbnRlcnBvbGF0aW9uIHN0cmluZyBlbmNsb3NlZCBpbiBgYCB7YC4uLmB9IGBgLlxyXG4gICAqL1xyXG4gIElOVEVSUE9MQVRJT05fTElURVJBTCxcclxuICAvKipcclxuICAgKiBBIEphdmFTY3JpcHQgZXhwcmVzc2lvbiBpbnRlcnBvbGF0aW9uIGVuY2xvc2VkIGluIGB7IH1gLlxyXG4gICAqL1xyXG4gIElOVEVSUE9MQVRJT05fRVhQUkVTU0lPTixcclxuICAvKipcclxuICAgKiBBIGBAY29uc3QgbmFtZSA9IGV4cHJlc3Npb247YCB0ZW1wbGF0ZS1sZXZlbCBjb25zdGFudCBkZWNsYXJhdGlvbi5cclxuICAgKi9cclxuICBDT05TVF9ERUNMQVJBVElPTixcclxuICAvKipcclxuICAgKiBPcGVuaW5nIGtleXdvcmQgb2YgYW4gYEBpZmAgZGlyZWN0aXZlLlxyXG4gICAqL1xyXG4gIElGLFxyXG4gIC8qKlxyXG4gICAqIE9wZW5pbmcga2V5d29yZCBvZiBhIGBAZm9yYCBkaXJlY3RpdmUuXHJcbiAgICovXHJcbiAgRk9SLFxyXG4gIC8qKlxyXG4gICAqIE9wZW5pbmcga2V5d29yZCBvZiBhbiBgQGVsc2VgIGJyYW5jaC5cclxuICAgKi9cclxuICBFTFNFLFxyXG4gIC8qKlxyXG4gICAqIE9wZW5pbmcga2V5d29yZCBvZiBhbiBgQGVsc2UgaWZgIGJyYW5jaC5cclxuICAgKi9cclxuICBFTFNFX0lGLFxyXG4gIC8qKlxyXG4gICAqIE9wZW5pbmcga2V5d29yZCBvZiBhIGBAc3dpdGNoYCBkaXJlY3RpdmUuXHJcbiAgICovXHJcbiAgU1dJVENILFxyXG4gIC8qKlxyXG4gICAqIE9wZW5pbmcga2V5d29yZCBvZiBhIGBAY2FzZWAgYnJhbmNoLlxyXG4gICAqL1xyXG4gIENBU0UsXHJcbiAgLyoqXHJcbiAgICogT3BlbmluZyBrZXl3b3JkIG9mIGEgYEBkZWZhdWx0YCBicmFuY2guXHJcbiAgICovXHJcbiAgREVGQVVMVCxcclxuICAvKipcclxuICAgKiBUaGUgY29uZGl0aW9uIGV4cHJlc3Npb24gYCguLi4pYCBhc3NvY2lhdGVkIHdpdGggYSBmbG93LWNvbnRyb2wgZGlyZWN0aXZlLlxyXG4gICAqL1xyXG4gIENPTkRJVElPTixcclxuICAvKipcclxuICAgKiBUaGUgb3BlbmluZyBge2Agb2YgYSBmbG93LWNvbnRyb2wgYmxvY2sgYm9keS5cclxuICAgKi9cclxuICBCTE9DS19PUEVOLFxyXG4gIC8qKlxyXG4gICAqIFRoZSBjbG9zaW5nIGB9YCBvZiBhIGZsb3ctY29udHJvbCBibG9jayBib2R5LlxyXG4gICAqL1xyXG4gIEJMT0NLX0NMT1NFLFxyXG4gIC8qKlxyXG4gICAqIFNlbnRpbmVsIHRva2VuIGVtaXR0ZWQgd2hlbiB0aGUgZW5kIG9mIHRoZSBpbnB1dCBpcyByZWFjaGVkLlxyXG4gICAqL1xyXG4gIEVPRlxyXG59XHJcbiIsImltcG9ydCB7IEdSRUFURVJfVEhFTiwgTEVGVF9CUkFDRSwgU0xBU0gsIFNQQUNFIH0gZnJvbSAnLi4vLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tICcuLi90eXBlcy9sZXhlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBMZXhlclN0YXRlIH0gZnJvbSAnLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1jb250ZXh0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUgfSBmcm9tICcuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXMgYW4gYXR0cmlidXRlIG5hbWUgYW5kIG9wdGlvbmFsIHZhbHVlIGZyb20gdGhlIGN1cnJlbnQgcG9zaXRpb24sXHJcbiAqIHRyYW5zaXRpb25pbmcgYmFjayB0byBUQUdfQk9EWSB3aGVuIGEgc3BhY2UsIGAvYCwgb3IgYD5gIGlzIGVuY291bnRlcmVkLlxyXG4gKiBJZiB0aGUgYXR0cmlidXRlIHZhbHVlIGlzIGFuIGludGVycG9sYXRpb24sIHB1c2hlcyB0aGUgSU5URVJQT0xBVElPTiBzdGF0ZS5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIHN0YXJ0IG9mIHRoZSBhdHRyaWJ1dGUuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgQVRUUklCVVRFIHRva2VuIGFuZCBuZXh0IHN0YXRlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVBdHRyaWJ1dGUoY3Vyc29yOiBMZXhlckN1cnNvciwgX2NvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgbGV0IHJlYWQgPSB0cnVlO1xyXG4gIGxldCBhdHRyaWJ1dGUgPSAnJztcclxuICBsZXQgcmV0VmFsITogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlO1xyXG5cclxuICB3aGlsZSAocmVhZCkge1xyXG4gICAgc3dpdGNoIChjdXJzb3IucGVlaygpKSB7XHJcbiAgICAgIGNhc2UgU1BBQ0U6XHJcbiAgICAgIGNhc2UgU0xBU0g6XHJcbiAgICAgIGNhc2UgR1JFQVRFUl9USEVOOlxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLlRBR19CT0RZLFxyXG4gICAgICAgICAgdG9rZW5zOiBbe1xyXG4gICAgICAgICAgICB0eXBlOiBUb2tlblR5cGUuQVRUUklCVVRFLFxyXG4gICAgICAgICAgICBwYXJ0czogW2F0dHJpYnV0ZV1cclxuICAgICAgICAgIH1dIFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmVhZCA9IGZhbHNlO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBMRUZUX0JSQUNFOlxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLklOVEVSUE9MQVRJT04sXHJcbiAgICAgICAgICB0b2tlbnM6IFt7XHJcbiAgICAgICAgICAgIHR5cGU6IFRva2VuVHlwZS5BVFRSSUJVVEUsXHJcbiAgICAgICAgICAgIHBhcnRzOiBbYXR0cmlidXRlXVxyXG4gICAgICAgICAgfV0sXHJcbiAgICAgICAgICBwdXNoU3RhdGU6IHRydWUgXHJcbiAgICAgICAgfTtcclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICAgICAgYXR0cmlidXRlID0gYCR7YXR0cmlidXRlfSR7Y3Vyc29yLmN1cnJlbnRDaGFyLnZhbHVlfWBcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiByZXRWYWw7XHJcbn0iLCJpbXBvcnQgeyBMUEFSRU4sIFJQQVJFTiB9IGZyb20gXCIuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHNcIjtcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZVwiO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVGbG93Q29udHJvbENvbmRpdGlvbihjdXJzb3I6IExleGVyQ3Vyc29yLCBfY29udGV4dDogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0KTogc3RyaW5nIHtcclxuICBjdXJzb3Iuc2tpcFNwYWNlcygpO1xyXG5cclxuICBpZiAoY3Vyc29yLnBlZWsoKSAhPT0gTFBBUkVOKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkICcoJyBidXQgZ290ICcke1N0cmluZy5mcm9tQ2hhckNvZGUoY3Vyc29yLnBlZWsoKSl9JyBhdCByb3cgJHtjdXJzb3IucG9zaXRpb24ucm93fSwgY29sICR7Y3Vyc29yLnBvc2l0aW9uLmNvbHVtbn1gKVxyXG4gIH1cclxuXHJcbiAgLy8gY29uc3VtZSAnKCdcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG5cclxuICBsZXQgZXhwcmVzc2lvbiA9ICcnO1xyXG4gIGxldCBkZXB0aCA9IDE7XHJcblxyXG4gIHdoaWxlIChkZXB0aCA+IDApIHtcclxuICAgIGNvbnN0IGNvZGUgPSBjdXJzb3IucGVlaygpO1xyXG5cclxuICAgIHN3aXRjaCAoY29kZSkge1xyXG4gICAgICBjYXNlIExQQVJFTjpcclxuICAgICAgICBkZXB0aCsrO1xyXG4gICAgICAgIGV4cHJlc3Npb24gPSBhZGRDaGFyYWN0ZXIoY3Vyc29yLCBleHByZXNzaW9uKTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgUlBBUkVOOlxyXG4gICAgICAgIGRlcHRoLS07XHJcbiAgICAgICAgaWYgKCFkZXB0aCkge1xyXG4gICAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZXhwcmVzc2lvbiA9IGFkZENoYXJhY3RlcihjdXJzb3IsIGV4cHJlc3Npb24pO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBleHByZXNzaW9uID0gYWRkQ2hhcmFjdGVyKGN1cnNvciwgZXhwcmVzc2lvbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gZXhwcmVzc2lvbjtcclxufVxyXG5cclxuLyoqXHJcbiAqIEFkdmFuY2VzIHRoZSBjdXJzb3IgYnkgb25lIGNoYXJhY3RlciBhbmQgYXBwZW5kcyBpdCB0byB0aGUgYWNjdW11bGF0b3Igc3RyaW5nLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFRoZSBsZXhlciBjdXJzb3IgdG8gYWR2YW5jZS5cclxuICogQHBhcmFtIGV4cHJlc3Npb24gVGhlIGN1cnJlbnQgYWNjdW11bGF0ZWQgc3RyaW5nLlxyXG4gKiBAcmV0dXJucyBUaGUgdXBkYXRlZCBzdHJpbmcgd2l0aCB0aGUgbmV3IGNoYXJhY3RlciBhcHBlbmRlZC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBhZGRDaGFyYWN0ZXIoY3Vyc29yOiBMZXhlckN1cnNvciwgZXhwcmVzc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gIHJldHVybiBgJHtleHByZXNzaW9ufSR7Y3Vyc29yLmN1cnJlbnRDaGFyLnZhbHVlfWA7XHJcbn0iLCJpbXBvcnQgeyBMZXhlckN1cnNvciB9IGZyb20gXCIuLi90eXBlcy9sZXhlci1jdXJzb3IubW9kZWwuanNcIjtcclxuaW1wb3J0IHsgTGV4ZXJTdGF0ZSB9IGZyb20gXCIuLi90eXBlcy9sZXhlci1zdGF0ZS5lbnVtLmpzXCI7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gXCIuLi90eXBlcy90b2tlbi10eXBlLmVudW0uanNcIjtcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0IH0gZnJvbSBcIi4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1jb250ZXh0LnR5cGUuanNcIjtcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlIH0gZnJvbSBcIi4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1yZXR1cm4tdHlwZS50eXBlLmpzXCI7XHJcbmltcG9ydCB7IGNvbnN1bWVGbG93Q29udHJvbENvbmRpdGlvbiB9IGZyb20gXCIuLi91dGlscy9jb25zdW1lLWZsb3ctY29udHJvbC1jb25kaXRpb24udXRpbHMuanNcIjtcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyB0aGUgY29uZGl0aW9uIGV4cHJlc3Npb24gYCguLi4pYCBvZiBhIGZsb3ctY29udHJvbCBkaXJlY3RpdmUsXHJcbiAqIGhhbmRsaW5nIG5lc3RlZCBwYXJlbnRoZXNlcyBjb3JyZWN0bHkuIEVtaXRzIGEgQ09ORElUSU9OIHRva2VuIHdpdGggdGhlXHJcbiAqIHJhdyBleHByZXNzaW9uIHN0cmluZyBhbmQgdHJhbnNpdGlvbnMgdG8gRkxPV19DT05UUk9MX0JMT0NLLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFRoZSBsZXhlciBjdXJzb3IgcG9zaXRpb25lZCBhdCB0aGUgb3BlbmluZyBgKGAuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgQ09ORElUSU9OIHRva2VuIGFuZCB0aGUgRkxPV19DT05UUk9MX0JMT0NLIHN0YXRlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVDYXNlRmxvd0NvbnRyb2xDb25kaXRpb24oY3Vyc29yOiBMZXhlckN1cnNvciwgX2NvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgY29uc3QgY29uZGl0aW9uID0gY29uc3VtZUZsb3dDb250cm9sQ29uZGl0aW9uKGN1cnNvciwgX2NvbnRleHQpO1xyXG4gIGN1cnNvci5za2lwU3BhY2VzKCk7XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBzdGF0ZTogY3Vyc29yLnBlZWtNYXRjaCgnQGNhc2UnKSA/IExleGVyU3RhdGUuRkxPV19DT05UUk9MIDogTGV4ZXJTdGF0ZS5GTE9XX0NPTlRST0xfQkxPQ0ssXHJcbiAgICB0b2tlbnM6IFt7XHJcbiAgICAgIHR5cGU6IFRva2VuVHlwZS5DT05ESVRJT04sXHJcbiAgICAgIHBhcnRzOiBbY29uZGl0aW9uXVxyXG4gICAgfV0sXHJcbiAgICBwb3BTdGF0ZTogdHJ1ZVxyXG4gIH07XHJcbn1cclxuIiwiaW1wb3J0IHsgRVFVQUxfVEhFTiwgU0VNSUNPTE9OLCBTUEFDRSB9IGZyb20gXCIuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHNcIjtcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsXCI7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bVwiO1xyXG5pbXBvcnQgeyBUb2tlblR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZVwiO1xyXG5cclxuLyoqXHJcbiAqIENvbnN1bWVzIGEgYEBjb25zdCBuYW1lID0gZXhwcmVzc2lvbjtgIGRlY2xhcmF0aW9uIGZyb20gdGhlIGN1cnJlbnQgcG9zaXRpb24uXHJcbiAqIEV4cGVjdHMgdGhlIGN1cnNvciB0byBiZSBwb3NpdGlvbmVkIGFmdGVyIHRoZSBgQGNvbnN0IGAga2V5d29yZC5cclxuICogRW1pdHMgYSBDT05TVF9ERUNMQVJBVElPTiB0b2tlbiBjb250YWluaW5nIHRoZSB2YXJpYWJsZSBuYW1lIGFuZCBpbml0aWFsaXplciBleHByZXNzaW9uLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFRoZSBsZXhlciBjdXJzb3IgcG9zaXRpb25lZCBhdCB0aGUgc3RhcnQgb2YgdGhlIHZhcmlhYmxlIG5hbWUuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgQ09OU1RfREVDTEFSQVRJT04gdG9rZW4gYW5kIHRoZSBURVhUIHN0YXRlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVDb25zdERlY2xhcmF0aW9uKGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZWFkID0gdHJ1ZTtcclxuICBsZXQgdmFyTmFtZSA9ICcnO1xyXG4gIGxldCBleHByZXNzaW9uID0gJyc7XHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZTtcclxuXHJcbiAgLypcclxuICAgIFNraXAgYWxsIHBvc3NpYmxlIHNwYWNlcyBiZXR3ZWVuIHRoZSAnY29uc3QnIGlkZW50aWZpZXIgYW5kIHRoZSAnPSdcclxuICAgIEBjb25zdCB2YXJOYW1lXHJcbiAgICBvclxyXG4gICAgQGNvbnN0ICAgICAgICAgIHZhck5hbWVcclxuICAqL1xyXG4gIGN1cnNvci5za2lwU3BhY2VzKCk7XHJcblxyXG4gIHdoaWxlKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIFNQQUNFOlxyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGRlZmF1bHQ6IFxyXG4gICAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICAgICAgdmFyTmFtZSA9IGAke3Zhck5hbWV9JHtjdXJzb3IuY3VycmVudENoYXIudmFsdWV9YFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLypcclxuICAgIFNraXAgYWxsIHBvc3NpYmxlIHNwYWNlcyBiZXR3ZWVuIHRoZSB2YXJOYW1lIGFuZCB0aGUgJz0nXHJcbiAgICB2YXJOYW1lID1cclxuICAgIG9yXHJcbiAgICB2YXJOYW1lICAgICAgICAgID1cclxuICAqL1xyXG4gIGN1cnNvci5za2lwU3BhY2VzKCk7XHJcblxyXG4gIGNvbnN0IG5leHRDaGFyID0gY3Vyc29yLnBlZWsoKTtcclxuICBpZiAobmV4dENoYXIgIT09IEVRVUFMX1RIRU4pIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBjaGFyYWN0ZXIgJHtTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHRDaGFyKX0uXFxuRXhwZWN0ZWQgJz0nIGApO1xyXG4gIH1cclxuICBcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gIC8qXHJcbiAgICBTa2lwIGFsbCBwb3NzaWJsZSBzcGFjZXMgYmV0d2VlbiB0aGUgJz0nIGFuZCB0aGUgZXhwcmVzc2lvblxyXG4gICAgPSB1c2VyLm5hbWVcclxuICAgIG9yXHJcbiAgICA9ICAgICAgICAgIHVzZXIubmFtZVxyXG4gICovXHJcbiAgY3Vyc29yLnNraXBTcGFjZXMoKTtcclxuICByZWFkID0gdHJ1ZVxyXG5cclxuICB3aGlsZShyZWFkKSB7XHJcbiAgICBzd2l0Y2ggKGN1cnNvci5wZWVrKCkpIHtcclxuICAgICAgY2FzZSBTRU1JQ09MT046XHJcbiAgICAgICAgcmV0VmFsID0ge1xyXG4gICAgICAgICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgICAgICAgIHRva2VuczogW3tcclxuICAgICAgICAgICAgdHlwZTogVG9rZW5UeXBlLkNPTlNUX0RFQ0xBUkFUSU9OLFxyXG4gICAgICAgICAgICBwYXJ0czogW3Zhck5hbWUsIGV4cHJlc3Npb25dXHJcbiAgICAgICAgICB9XVxyXG4gICAgICAgIH1cclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBkZWZhdWx0OiBcclxuICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgIGV4cHJlc3Npb24gPSBgJHtleHByZXNzaW9ufSR7Y3Vyc29yLmN1cnJlbnRDaGFyLnZhbHVlfWBcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIENvbnN1bWUgJzsnXHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICBleHByZXNzaW9uID0gYCR7ZXhwcmVzc2lvbn07YFxyXG5cclxuICByZXR1cm4gcmV0VmFsO1xyXG59IiwiaW1wb3J0IHsgR1JFQVRFUl9USEVOLCBTTEFTSCwgU1BBQ0UgfSBmcm9tICcuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHMuanMnO1xyXG5pbXBvcnQgeyBMZXhlckN1cnNvciB9IGZyb20gJy4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tICcuLi90eXBlcy9sZXhlci1zdGF0ZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0IH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1yZXR1cm4tdHlwZS50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyBhIERPTSBldmVudCBiaW5kaW5nIHN0YXJ0aW5nIHdpdGggYEBgIGFuZCByZWFkcyB1bnRpbCBhIGRlbGltaXRlclxyXG4gKiAoc3BhY2UsIGAvYCwgb3IgYD5gKSBpcyBmb3VuZC4gRW1pdHMgYW4gRVZFTlQgdG9rZW4gY29udGFpbmluZyB0aGUgcmF3IGJpbmRpbmcgc3RyaW5nLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFRoZSBsZXhlciBjdXJzb3IgcG9zaXRpb25lZCBvbiB0aGUgYEBgIGNoYXJhY3Rlci5cclxuICogQHBhcmFtIF9jb250ZXh0IFVudXNlZCBsZXhlciBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBUcmFuc2l0aW9uIHJlc3VsdCB3aXRoIHRoZSBFVkVOVCB0b2tlbiBhbmQgdGhlIFRBR19CT0RZIHN0YXRlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVFdmVudChjdXJzb3I6IExleGVyQ3Vyc29yLCBfY29udGV4dDogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0KTogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlIHtcclxuICBsZXQgcmVhZCA9IHRydWU7XHJcbiAgbGV0IGV2ZW50ID0gJyc7XHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZTtcclxuXHJcbiAgLy8gQ29uc3VtZSAnQCcgY2hhcmFjdGVyXHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgd2hpbGUgKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIFNQQUNFOlxyXG4gICAgICBjYXNlIFNMQVNIOlxyXG4gICAgICBjYXNlIEdSRUFURVJfVEhFTjpcclxuICAgICAgICAvKlxyXG4gICAgICAgICAgU3BlY2lhbCBjYXNlIHRvIGhhbmRsZSBzeW50YXggc3VnYXIgZm9yIGV2ZW50IGJpbmRpbmdzOlxyXG4gICAgICAgICAgSWYgdGhlIGRlc2lyZWQgZnVuY3Rpb24gdG8gYmUgYmluZGVkIGlzIHRoZSBlcXVhbCB0byB0aGUgZXZlbnQgbmFtZVxyXG4gICAgICAgICAgd2l0aCB0aGUgXCJvblwiIHByZWZpeCwgYXV0b21hdGljYWxseSBnZW5lcmF0ZSB0aGUgYmluZGluZyBzdHJpbmcuXHJcbiAgICAgICAgICBFeDogQGNsaWNrPVwib25DbGlja1wiIGNhbiBiZSB3cml0dGVuIGFzIEBjbGljaywgYW5kIHRoZSBlbWl0dGVkIHRva2VuIHdpbGwgaGF2ZSBcIm9uQ2xpY2tcIiBhcyBwYXJ0XHJcbiAgICAgICAgKi9cclxuICAgICAgICBpZiAoIWV2ZW50LmluY2x1ZGVzKCc9JykpIHtcclxuICAgICAgICAgIGV2ZW50ID0gYCR7ZXZlbnR9PW9uJHtldmVudFswXSEudG9VcHBlckNhc2UoKX0ke2V2ZW50LnNsaWNlKDEpfSgkZXZlbnQpYDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLlRBR19CT0RZLFxyXG4gICAgICAgICAgdG9rZW5zOiBbeyBcclxuICAgICAgICAgICAgdHlwZTogVG9rZW5UeXBlLkVWRU5ULCBcclxuICAgICAgICAgICAgcGFydHM6IFtldmVudF0gXHJcbiAgICAgICAgICB9XVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgcmVhZCA9IGZhbHNlO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgIGV2ZW50ID0gYCR7ZXZlbnR9JHtjdXJzb3IuY3VycmVudENoYXIudmFsdWV9YFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHJldFZhbDtcclxufSIsImltcG9ydCB7IExFRlRfQlJBQ0UgfSBmcm9tIFwiLi4vLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzXCI7XHJcbmltcG9ydCB7IExleGVyQ3Vyc29yIH0gZnJvbSBcIi4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclN0YXRlIH0gZnJvbSBcIi4uL3R5cGVzL2xleGVyLXN0YXRlLmVudW0uanNcIjtcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSBcIi4uL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQgfSBmcm9tIFwiLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLXJldHVybi10eXBlLnR5cGUuanNcIjtcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyB0aGUgb3BlbmluZyBge2Agb2YgYSBmbG93IGNvbnRyb2wgYmxvY2sgYm9keSxcclxuICogc2tpcHBpbmcgYW55IGxlYWRpbmcgd2hpdGVzcGFjZSBiZWZvcmUgaXQuXHJcbiAqXHJcbiAqIEVtaXRzIGEgQkxPQ0tfT1BFTiB0b2tlbiBhbmQgdHJhbnNpdGlvbnMgdG8gVEVYVCxcclxuICogcHVzaGluZyBGTE9XX0NPTlRST0xfQkxPQ0sgb250byB0aGUgc3RhdGUgc3RhY2suXHJcbiAqIFRoaXMgYWxsb3dzIGNvbnN1bWVUZXh0IHRvIGxhdGVyIHJlY29nbmlzZSB0aGUgbWF0Y2hpbmcgYH1gIGFzIGEgQkxPQ0tfQ0xPU0VcclxuICogcmF0aGVyIHRoYW4gYXMgYW4gaW50ZXJwb2xhdGlvbiBib3VuZGFyeS5cclxuICpcclxuICogVXNlZCBieTogQGlmLCBAZm9yLCBAc3dpdGNoLCBAY2FzZSwgQGVsc2UsIEBkZWZhdWx0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29uc3VtZUZsb3dDb250cm9sQmxvY2soY3Vyc29yOiBMZXhlckN1cnNvciwgX2NvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgY3Vyc29yLnNraXBTcGFjZXMoKTtcclxuXHJcbiAgaWYgKGN1cnNvci5wZWVrKCkgIT09IExFRlRfQlJBQ0UpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJ3snIGJ1dCBnb3QgJyR7U3RyaW5nLmZyb21DaGFyQ29kZShjdXJzb3IucGVlaygpKX0nIGF0IHJvdyAke2N1cnNvci5wb3NpdGlvbi5yb3d9LCBjb2wgJHtjdXJzb3IucG9zaXRpb24uY29sdW1ufWApO1xyXG4gIH1cclxuXHJcbiAgLy8gY29uc3VtZSAneydcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgIHRva2VuczogW3sgdHlwZTogVG9rZW5UeXBlLkJMT0NLX09QRU4gfV0sXHJcbiAgICBwdXNoU3RhdGU6IHRydWVcclxuICB9O1xyXG59XHJcbiIsImltcG9ydCB7IENSLCBMRiB9IGZyb20gXCIuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHMuanNcIjtcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsLmpzXCI7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bS5qc1wiO1xyXG5pbXBvcnQgeyBUb2tlblR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlLmpzXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZS5qc1wiO1xyXG5pbXBvcnQgeyBjb25zdW1lRmxvd0NvbnRyb2xDb25kaXRpb24gfSBmcm9tIFwiLi4vdXRpbHMvY29uc3VtZS1mbG93LWNvbnRyb2wtY29uZGl0aW9uLnV0aWxzLmpzXCI7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXMgdGhlIGNvbmRpdGlvbiBleHByZXNzaW9uIGAoLi4uKWAgb2YgYSBmbG93LWNvbnRyb2wgZGlyZWN0aXZlLFxyXG4gKiBoYW5kbGluZyBuZXN0ZWQgcGFyZW50aGVzZXMgY29ycmVjdGx5LiBFbWl0cyBhIENPTkRJVElPTiB0b2tlbiB3aXRoIHRoZVxyXG4gKiByYXcgZXhwcmVzc2lvbiBzdHJpbmcgYW5kIHRyYW5zaXRpb25zIHRvIEZMT1dfQ09OVFJPTF9CTE9DSy5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIG9wZW5pbmcgYChgLlxyXG4gKiBAcGFyYW0gX2NvbnRleHQgVW51c2VkIGxleGVyIGNvbnRleHQuXHJcbiAqIEByZXR1cm5zIFRyYW5zaXRpb24gcmVzdWx0IHdpdGggdGhlIENPTkRJVElPTiB0b2tlbiBhbmQgdGhlIEZMT1dfQ09OVFJPTF9CTE9DSyBzdGF0ZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjb25zdW1lRGVmYXVsdEZsb3dDb250cm9sQ29uZGl0aW9uKGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIHJldHVybiB7XHJcbiAgICBzdGF0ZTogTGV4ZXJTdGF0ZS5GTE9XX0NPTlRST0xfQkxPQ0ssXHJcbiAgICB0b2tlbnM6IFt7XHJcbiAgICAgIHR5cGU6IFRva2VuVHlwZS5DT05ESVRJT04sXHJcbiAgICAgIHBhcnRzOiBbY29uc3VtZUZsb3dDb250cm9sQ29uZGl0aW9uKGN1cnNvciwgX2NvbnRleHQpXVxyXG4gICAgfV0sXHJcbiAgICBwb3BTdGF0ZTogdHJ1ZVxyXG4gIH07XHJcbn1cclxuIiwiaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsLmpzXCI7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tIFwiLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bS5qc1wiO1xyXG5pbXBvcnQgeyBUb2tlblR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlLmpzXCI7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gXCIuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZS5qc1wiO1xyXG5cclxuLyoqXHJcbiAqIERpc3BhdGNoZXMgb24gYSBgQGtleXdvcmRgIHRvIGRldGVybWluZSB3aGljaCBmbG93LWNvbnRyb2wgZGlyZWN0aXZlIGJlZ2lucyBoZXJlLlxyXG4gKiBSZWNvZ25pc2VzIGBAaWZgLCBgQGZvcmAsIGBAZWxzZWAsIGBAc3dpdGNoYCwgYEBjYXNlYCwgYEBkZWZhdWx0YCwgYW5kIGBAY29uc3RgLlxyXG4gKiBBZHZhbmNlcyB0aGUgY3Vyc29yIHBhc3QgdGhlIGtleXdvcmQgYW5kIHRyYW5zaXRpb25zIHRvIHRoZSBhcHByb3ByaWF0ZSBuZXh0IHN0YXRlLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFRoZSBsZXhlciBjdXJzb3IgcG9zaXRpb25lZCBvbiB0aGUgYEBgIGNoYXJhY3Rlci5cclxuICogQHBhcmFtIF9jb250ZXh0IFVudXNlZCBsZXhlciBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBUcmFuc2l0aW9uIHJlc3VsdCB3aXRoIHRoZSBtYXRjaGluZyBmbG93LWNvbnRyb2wgdG9rZW4gYW5kIG5leHQgc3RhdGUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29uc3VtZUZsb3dDb250cm9sKGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZXRWYWwhOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGU7XHJcblxyXG4gIC8vIENvbnN1bWUgJ0AnIGNoYXJhY3RlclxyXG4gIGN1cnNvci5hZHZhbmNlKCk7XHJcblxyXG4gIGlmIChjdXJzb3IucGVla01hdGNoKCdmb3IgJykpIHtcclxuICAgIGN1cnNvci5hZHZhbmNlKDQpO1xyXG4gICAgcmV0VmFsID0ge1xyXG4gICAgICBzdGF0ZTogTGV4ZXJTdGF0ZS5GTE9XX0NPTlRST0xfQ09ORElUSU9OLFxyXG4gICAgICB0b2tlbnM6IFt7XHJcbiAgICAgICAgdHlwZTogVG9rZW5UeXBlLkZPUlxyXG4gICAgICB9XSxcclxuICAgICAgcHVzaFN0YXRlOiB0cnVlXHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChjdXJzb3IucGVla01hdGNoKCdpZiAnKSkge1xyXG4gICAgY3Vyc29yLmFkdmFuY2UoMik7XHJcbiAgICByZXRWYWwgPSB7XHJcbiAgICAgIHN0YXRlOiBMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF9DT05ESVRJT04sXHJcbiAgICAgIHRva2VuczogW3tcclxuICAgICAgICB0eXBlOiBUb2tlblR5cGUuSUZcclxuICAgICAgfV0sXHJcbiAgICAgIHB1c2hTdGF0ZTogdHJ1ZVxyXG4gICAgfVxyXG4gIH0gZWxzZSBpZiAoY3Vyc29yLnBlZWtNYXRjaCgnZWxzZSBpZiAnKSkge1xyXG4gICAgY3Vyc29yLmFkdmFuY2UoOCk7XHJcbiAgICByZXRWYWwgPSB7XHJcbiAgICAgIHN0YXRlOiBMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF9DT05ESVRJT04sXHJcbiAgICAgIHRva2VuczogW3tcclxuICAgICAgICB0eXBlOiBUb2tlblR5cGUuRUxTRV9JRlxyXG4gICAgICB9XSxcclxuICAgICAgcHVzaFN0YXRlOiB0cnVlXHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChjdXJzb3IucGVla01hdGNoKCdlbHNlICcpKSB7XHJcbiAgICBjdXJzb3IuYWR2YW5jZSg1KTtcclxuICAgIHJldFZhbCA9IHtcclxuICAgICAgc3RhdGU6IExleGVyU3RhdGUuRkxPV19DT05UUk9MX0JMT0NLLFxyXG4gICAgICB0b2tlbnM6IFt7XHJcbiAgICAgICAgdHlwZTogVG9rZW5UeXBlLkVMU0VcclxuICAgICAgfV1cclxuICAgIH1cclxuICB9IGVsc2UgaWYgKGN1cnNvci5wZWVrTWF0Y2goJ3N3aXRjaCAnKSkge1xyXG4gICAgY3Vyc29yLmFkdmFuY2UoNyk7XHJcbiAgICByZXRWYWwgPSB7XHJcbiAgICAgIHN0YXRlOiBMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF9DT05ESVRJT04sXHJcbiAgICAgIHRva2VuczogW3tcclxuICAgICAgICB0eXBlOiBUb2tlblR5cGUuU1dJVENIXHJcbiAgICAgIH1dLFxyXG4gICAgICBwdXNoU3RhdGU6IHRydWVcclxuICAgIH1cclxuICB9IGVsc2UgaWYgKGN1cnNvci5wZWVrTWF0Y2goJ2Nhc2UgJykpIHtcclxuICAgIGN1cnNvci5hZHZhbmNlKDUpO1xyXG4gICAgcmV0VmFsID0ge1xyXG4gICAgICBzdGF0ZTogTGV4ZXJTdGF0ZS5DQVNFX0ZMT1dfQ09OVFJPTF9DT05ESVRJT04sXHJcbiAgICAgIHRva2VuczogW3tcclxuICAgICAgICB0eXBlOiBUb2tlblR5cGUuQ0FTRVxyXG4gICAgICB9XSxcclxuICAgICAgcHVzaFN0YXRlOiB0cnVlXHJcbiAgICB9XHJcbiAgfSBlbHNlIGlmIChjdXJzb3IucGVla01hdGNoKCdkZWZhdWx0ICcpKSB7XHJcbiAgICBjdXJzb3IuYWR2YW5jZSg4KTtcclxuICAgIHJldFZhbCA9IHtcclxuICAgICAgc3RhdGU6IExleGVyU3RhdGUuRkxPV19DT05UUk9MX0JMT0NLLFxyXG4gICAgICB0b2tlbnM6IFt7XHJcbiAgICAgICAgdHlwZTogVG9rZW5UeXBlLkRFRkFVTFRcclxuICAgICAgfV1cclxuICAgIH1cclxuICB9IGVsc2UgaWYgKGN1cnNvci5wZWVrTWF0Y2goJ2NvbnN0ICcpKSB7XHJcbiAgICBjdXJzb3IuYWR2YW5jZSg2KTtcclxuICAgIHJldFZhbCA9IHtcclxuICAgICAgc3RhdGU6IExleGVyU3RhdGUuQ09OU1RfREVDTEFSQVRJT05cclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiByZXRWYWxcclxufSIsImltcG9ydCB7IExFRlRfQlJBQ0UsIFJJR0hUX0JSQUNFLCBTUEFDRSB9IGZyb20gJy4uLy4uL2Nvc3RhbnRzL2NoYXJzLmNvbnN0YW50cy5qcyc7XHJcbmltcG9ydCB7IExleGVyQ3Vyc29yIH0gZnJvbSAnLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJTdGF0ZSB9IGZyb20gJy4uL3R5cGVzL2xleGVyLXN0YXRlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBUb2tlblR5cGUgfSBmcm9tICcuLi90eXBlcy90b2tlbi10eXBlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQgfSBmcm9tICcuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlIH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLXJldHVybi10eXBlLnR5cGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIENvbnN1bWVzIGEgSmF2YVNjcmlwdCBleHByZXNzaW9uIGludGVycG9sYXRpb24gYHsgZXhwcmVzc2lvbiB9YCwgdHJhY2tpbmcgbmVzdGVkXHJcbiAqIGJyYWNlIGRlcHRoLiBFbWl0cyBhbiBJTlRFUlBPTEFUSU9OX0VYUFJFU1NJT04gdG9rZW4gYW5kIHBvcHMgdGhlIHN0YXRlIHN0YWNrIHRvXHJcbiAqIHJldHVybiB0byB0aGUgcHJldmlvdXMgc3RhdGUgKEFUVFJJQlVURSBvciBURVhUKS5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiB0aGUgZXhwcmVzc2lvbi5cclxuICogQHBhcmFtIGNvbnRleHQgTGV4ZXIgY29udGV4dCB1c2VkIHRvIHJldHJpZXZlIHRoZSBwcmV2aW91cyBzdGF0ZSBmb3IgcmVzdG9yYXRpb24uXHJcbiAqIEByZXR1cm5zIFRyYW5zaXRpb24gcmVzdWx0IHdpdGggdGhlIElOVEVSUE9MQVRJT05fRVhQUkVTU0lPTiB0b2tlbiBhbmQgcmVzdG9yZWQgc3RhdGUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29uc3VtZUludGVycG9sYXRpb25FeHByZXNzaW9uKGN1cnNvcjogTGV4ZXJDdXJzb3IsIGNvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgbGV0IHJlYWQgPSB0cnVlO1xyXG4gIGxldCBpbnRlcnBvbGF0aW9uID0gJyc7XHJcbiAgbGV0IGRlZXAgPSAxXHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZTtcclxuXHJcbiAgd2hpbGUgKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIExFRlRfQlJBQ0U6XHJcbiAgICAgICAgZGVlcCsrO1xyXG4gICAgICAgIGludGVycG9sYXRpb24gPSBhZGRDaGFyYWN0ZXIoY3Vyc29yLCBpbnRlcnBvbGF0aW9uKTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgUklHSFRfQlJBQ0U6XHJcbiAgICAgICAgZGVlcC0tO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGlmIChkZWVwID09PSAwKSB7XHJcbiAgICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgICAgLypcclxuICAgICAgICAgICAgQWZ0ZXIgYW4gaW50ZXJwb2xhdGlvbiB3ZSBoYXZlIHRvIHVuZGVyc3RhbmFkIHdoZXJlIHRvIHRyYW5zaXRlXHJcbiAgICAgICAgICAgIFRoZSBuZXh0IHN0YXRlIGRlcGVuZHMgZnJvbSB0aGUgcHJldmlvdXMgc3RhdGVcclxuICAgICAgICAgICovXHJcbiAgICAgICAgICBjb25zdCBwcmV2aW91c1N0YXRlID0gY29udGV4dC5oaXN0b3J5LnBvcCgpO1xyXG4gICAgICAgICAgbGV0IHN0YXRlITogTGV4ZXJTdGF0ZTtcclxuXHJcbiAgICAgICAgICBzd2l0Y2ggKHByZXZpb3VzU3RhdGUpIHtcclxuICAgICAgICAgICAgY2FzZSBMZXhlclN0YXRlLkFUVFJJQlVURTpcclxuICAgICAgICAgICAgICAvKlxyXG4gICAgICAgICAgICAgICAgVGhpcyBpcyBhIHNwZWNpYWwgY2FzZSB0byBoYW5kbGUgc3ludGF4IHN1Z2FyIGZvciBhdHRyaWJ1dGUgaW50ZXJwb2xhdGlvbnM6XHJcbiAgICAgICAgICAgICAgICBJZiB0aGUgYXR0cmlidXRlIG5hbWUgYW5kIHRoZSB2YXJpYWJsZSBiaW5kZWQgaGF2ZSB0aGUgc2FtZSBpbmRlbnRpZmllciBpdCBjYW4gYmUgd3JpdHRlblxyXG4gICAgICAgICAgICAgICAgZnJvbSBhdHRyaWJ1dGU9e2F0dHJpYnV0ZX0gdG8ge2F0dHJpYnV0ZX1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgSW4gdGhpcyBjYXNlIHRoZSBhdHRyaWJ1dGUgdG9rZW4gZW1pdHRlZCBieSB0aGUgcHJldmlvc3Ugc3RhdGUgd2lsbCBoYXZlIGFuIGVtcHR5IHN0cmluZ1xyXG4gICAgICAgICAgICAgICAgYXMgcGFydCBhbmQgd2UgbmVlZCB0byBmaWxsIGl0IHdpdGggdGhlIGFjdHVhbCBpbnRlcnBvbGF0aW9uIGNvbnRlbnRcclxuXHJcbiAgICAgICAgICAgICAgICBUaGlzIGlzIHRyaWNreSBidXQgaXQgYWxsb3dzIHRvIGF2b2lkIHVubmVjZXNzYXJ5IGNvbXBsaWNhdGlvbiBpbiB0aGUgcGFyc2VyIGFuZFxyXG4gICAgICAgICAgICAgICAgcmVuZGVyIGdlbmVyYXRvciwgYnkga2VlcGluZyB0aGlzIHN5bnRheCBzdWdhciBhcyBhIHB1cmVseSBsZXhpY2FsIGZlYXR1cmUgYW5kXHJcbiAgICAgICAgICAgICAgICBieSByZWRpcmVjdGluZyB0byB0aGUgc3RhbmRhcmQgZmxvdyBmb3IgYXR0cmlidXRlIGludGVycG9sYXRpb25zIGFmdGVyIHRoZSBsZXhlclxyXG4gICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgY29uc3QgbGFzdFRva2VuID0gY29udGV4dC50b2tlbnNbY29udGV4dC50b2tlbnMubGVuZ3RoIC0gMV07XHJcbiAgICAgICAgICAgICAgaWYgKGxhc3RUb2tlbj8udHlwZSA9PT0gVG9rZW5UeXBlLkFUVFJJQlVURSAmJiAhbGFzdFRva2VuLnBhcnRzWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBsYXN0VG9rZW4ucGFydHNbMF0gPSBgJHtpbnRlcnBvbGF0aW9ufT1gO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBzdGF0ZSA9IExleGVyU3RhdGUuVEFHX0JPRFlcclxuICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UgTGV4ZXJTdGF0ZS5URVhUOlxyXG4gICAgICAgICAgICAgIHN0YXRlID0gTGV4ZXJTdGF0ZS5URVhUXHJcbiAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgICAgc3RhdGUsXHJcbiAgICAgICAgICAgIHRva2VuczogW3sgXHJcbiAgICAgICAgICAgICAgdHlwZTogVG9rZW5UeXBlLklOVEVSUE9MQVRJT05fRVhQUkVTU0lPTiwgXHJcbiAgICAgICAgICAgICAgcGFydHM6IFtpbnRlcnBvbGF0aW9uXSBcclxuICAgICAgICAgICAgfV0sXHJcbiAgICAgICAgICAgIHBvcFN0YXRlOiB0cnVlXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGludGVycG9sYXRpb24gPSBhZGRDaGFyYWN0ZXIoY3Vyc29yLCBpbnRlcnBvbGF0aW9uKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBpbnRlcnBvbGF0aW9uID0gYWRkQ2hhcmFjdGVyKGN1cnNvciwgaW50ZXJwb2xhdGlvbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmV0VmFsO1xyXG59XHJcblxyXG4vKipcclxuICogQWR2YW5jZXMgdGhlIGN1cnNvciBieSBvbmUgY2hhcmFjdGVyIGFuZCBhcHBlbmRzIGl0IHRvIHRoZSBhY2N1bXVsYXRvciBzdHJpbmcuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciB0byBhZHZhbmNlLlxyXG4gKiBAcGFyYW0gaW50ZXJwb2xhdGlvbiBUaGUgY3VycmVudCBhY2N1bXVsYXRlZCBzdHJpbmcuXHJcbiAqIEByZXR1cm5zIFRoZSB1cGRhdGVkIHN0cmluZyB3aXRoIHRoZSBuZXcgY2hhcmFjdGVyIGFwcGVuZGVkLlxyXG4gKi9cclxuZnVuY3Rpb24gYWRkQ2hhcmFjdGVyKGN1cnNvcjogTGV4ZXJDdXJzb3IsIGludGVycG9sYXRpb246IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoMSk7XHJcbiAgcmV0dXJuIGAke2ludGVycG9sYXRpb259JHtjdXJzb3IuY3VycmVudENoYXIudmFsdWV9YDtcclxufSIsImltcG9ydCB7IEdSQVZFX0FDQ0VOVCwgUklHSFRfQlJBQ0UgfSBmcm9tICcuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHMuanMnO1xyXG5pbXBvcnQgeyBMZXhlckN1cnNvciB9IGZyb20gJy4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tICcuLi90eXBlcy9sZXhlci1zdGF0ZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0IH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1yZXR1cm4tdHlwZS50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyBhIHRlbXBsYXRlLWxpdGVyYWwgaW50ZXJwb2xhdGlvbiBgYCB7YC4uLmB9IGBgLCBjb2xsZWN0aW5nIGNoYXJhY3RlcnNcclxuICogdW50aWwgdGhlIGNsb3NpbmcgYmFja3RpY2sgZm9sbG93ZWQgYnkgYH1gLiBFbWl0cyBhbiBJTlRFUlBPTEFUSU9OX0xJVEVSQUwgdG9rZW5cclxuICogYW5kIHBvcHMgdGhlIHN0YXRlIHN0YWNrIHRvIHJldHVybiB0byB0aGUgcHJldmlvdXMgc3RhdGUuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciBwb3NpdGlvbmVkIGF0IHRoZSBvcGVuaW5nIGJhY2t0aWNrLlxyXG4gKiBAcGFyYW0gY29udGV4dCBMZXhlciBjb250ZXh0IHVzZWQgdG8gcmV0cmlldmUgdGhlIHByZXZpb3VzIHN0YXRlIGZvciByZXN0b3JhdGlvbi5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgSU5URVJQT0xBVElPTl9MSVRFUkFMIHRva2VuIGFuZCByZXN0b3JlZCBzdGF0ZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjb25zdW1lSW50ZXJwb2xhdGlvbmxpdGVyYWwoY3Vyc29yOiBMZXhlckN1cnNvciwgY29udGV4dDogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0KTogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlIHtcclxuICBsZXQgcmVhZCA9IHRydWU7XHJcbiAgbGV0IGludGVycG9sYXRpb24gPSAnYCc7XHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZTtcclxuXHJcbiAgLy8gQ29uc3VtZSAnYCcgY2hhcmFjdGVyXHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgd2hpbGUgKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIEdSQVZFX0FDQ0VOVDpcclxuICAgICAgICBpbnRlcnBvbGF0aW9uID0gYWRkQ2hhcmFjdGVyKGN1cnNvciwgaW50ZXJwb2xhdGlvbik7XHJcblxyXG4gICAgICAgIGlmIChjdXJzb3IucGVlaygpID09PSBSSUdIVF9CUkFDRSkge1xyXG4gICAgICAgICAgLy8gQ29uc3VtZSAnfSdcclxuICAgICAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICAgICAgICAvKlxyXG4gICAgICAgICAgICBBZnRlciBhbiBpbnRlcnBvbGF0aW9uIHdlIGhhdmUgdG8gdW5kZXJzdGFuYWQgd2hlcmUgdG8gdHJhbnNpdGVcclxuICAgICAgICAgICAgVGhlIG5leHQgc3RhdGUgZGVwZW5kcyBmcm9tIHRoZSBwcmV2aW91cyBzdGF0ZVxyXG4gICAgICAgICAgKi9cclxuICAgICAgICAgIGNvbnN0IHByZXZpb3VzU3RhdGUgPSBjb250ZXh0Lmhpc3RvcnkucG9wKCk7XHJcbiAgICAgICAgICBsZXQgc3RhdGUhOiBMZXhlclN0YXRlO1xyXG5cclxuICAgICAgICAgIHN3aXRjaCAocHJldmlvdXNTdGF0ZSkge1xyXG4gICAgICAgICAgICBjYXNlIExleGVyU3RhdGUuQVRUUklCVVRFOlxyXG4gICAgICAgICAgICAgIHN0YXRlID0gTGV4ZXJTdGF0ZS5UQUdfQk9EWVxyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZSBMZXhlclN0YXRlLlRFWFQ6XHJcbiAgICAgICAgICAgICAgc3RhdGUgPSBMZXhlclN0YXRlLlRFWFRcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgcmV0VmFsID0ge1xyXG4gICAgICAgICAgICBzdGF0ZSxcclxuICAgICAgICAgICAgdG9rZW5zOiBbe1xyXG4gICAgICAgICAgICAgIHR5cGU6IFRva2VuVHlwZS5JTlRFUlBPTEFUSU9OX0xJVEVSQUwsXHJcbiAgICAgICAgICAgICAgcGFydHM6IFtpbnRlcnBvbGF0aW9uXVxyXG4gICAgICAgICAgICB9XSxcclxuICAgICAgICAgICAgcG9wU3RhdGU6IHRydWVcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgLypcclxuICAgICAgICAgICAgSWYgYCBpcyBub3QgZm9sbG93ZWQgYnkgfSwgaXQgbWVhbnMgdGhlIGludGVycG9sYXRpb24gaXMgbm90IGNsb3NlZFxyXG4gICAgICAgICAgICBhbmQgYCBpcyBwYXJ0IG9mIHRoZSBpbnRlcnBvbGF0ZWQgc3RyaW5nXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIMuFXHJcbiAgICAgICAgICAgIEV4YW1wbGU6IHtgdGV4dCAke3Zhcn0gYCB0ZXh0YH1cclxuICAgICAgICAgICovXHJcbiAgICAgICAgICBpbnRlcnBvbGF0aW9uID0gYCR7aW50ZXJwb2xhdGlvbn0ke2N1cnNvci5jdXJyZW50Q2hhci52YWx1ZX1gXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBpbnRlcnBvbGF0aW9uID0gYWRkQ2hhcmFjdGVyKGN1cnNvciwgaW50ZXJwb2xhdGlvbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmV0VmFsO1xyXG59XHJcblxyXG4vKipcclxuICogQWR2YW5jZXMgdGhlIGN1cnNvciBieSBvbmUgY2hhcmFjdGVyIGFuZCBhcHBlbmRzIGl0IHRvIHRoZSBhY2N1bXVsYXRvciBzdHJpbmcuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciB0byBhZHZhbmNlLlxyXG4gKiBAcGFyYW0gaW50ZXJwb2xhdGlvbiBUaGUgY3VycmVudCBhY2N1bXVsYXRlZCBzdHJpbmcuXHJcbiAqIEByZXR1cm5zIFRoZSB1cGRhdGVkIHN0cmluZyB3aXRoIHRoZSBuZXcgY2hhcmFjdGVyIGFwcGVuZGVkLlxyXG4gKi9cclxuZnVuY3Rpb24gYWRkQ2hhcmFjdGVyKGN1cnNvcjogTGV4ZXJDdXJzb3IsIGludGVycG9sYXRpb246IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICByZXR1cm4gYCR7aW50ZXJwb2xhdGlvbn0ke2N1cnNvci5jdXJyZW50Q2hhci52YWx1ZX1gO1xyXG59IiwiaW1wb3J0IHsgQSwgYSwgQ1IsIExGLCBaLCB6IH0gZnJvbSAnLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiBjaGFyIGNvZGUgaXMgYSBMaW5lIEZlZWQgKFxcbikgb3IgQ2FycmlhZ2UgUmV0dXJuIChcXHIpXHJcbiAqIEBwYXJhbSBjaGFyIENoYXJhY3RlciB0byBjb250cm9sXHJcbiAqIEByZXR1cm5zIFRydWUgaWYgY2hhcmFjdGVyIGlzIExGIG9yIENSLCBmYWxzZSBvdGhlcndpc2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc05ld0xpbmUoY2hhcjogbnVtYmVyKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIGNoYXIgPT09IExGIHx8IGNoYXIgPT09IENSO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2sgaWYgY2hhciBjb2RlIGlzIGlzIGEgbG93ZXIgY2FzZSBsZXR0ZXJcclxuICogQHBhcmFtIGNoYXIgQ2hhcmFjdGVyIHRvIGNvbnRyb2xcclxuICogQHJldHVybnMgVHJ1ZSBpZiBjaGFyYWN0ZXIgaXMgYSBsb3dlcmNhc2UgbGV0dGVyLCBmYWxzZSBvdGhlcndpc2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0xvd2VyQ2FzZShjaGFyOiBudW1iZXIpOiBib29sZWFuIHtcclxuICByZXR1cm4gY2hhciA+PSBhICYmIGNoYXIgPD0gejtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrIGlmIGNoYXIgY29kZSBpcyBpcyBhIHVwcGVyICBjYXNlIGxldHRlclxyXG4gKiBAcGFyYW0gY2hhciBDaGFyYWN0ZXIgdG8gY29udHJvbFxyXG4gKiBAcmV0dXJucyBUcnVlIGlmIGNoYXJhY3RlciBpcyBhIHVwcGVyIGNhc2UgbGV0dGVyLCBmYWxzZSBvdGhlcndpc2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1VwcGVyQ2FzZShjaGFyOiBudW1iZXIpOiBib29sZWFuIHtcclxuICByZXR1cm4gY2hhciA+PSBBICYmIGNoYXIgPD0gWjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrIGlmIHRoZSBzdHJpbmcgY29udGFpbnMgYXQgbGVhc3Qgb25lIGNoYXJhY3RlciBkaWZmZXJlbnQgZnJvbVxyXG4gKiAnICdcclxuICogXFxuXHJcbiAqIFxcclxyXG4gKiBcXHRcclxuICogXFxmXHJcbiAqIFxcdlxyXG4gKiBAcGFyYW0gc3RyIFN0cmluZyB0byBjaGVja1xyXG4gKiBAcmV0dXJucyBUcnVlIGlmIHN0cmluZyBpcyBub3QgYmxhbmssIGZhbHNlIG90aGVyd2lzZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzTm90Qmxhbmsoc3RyOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAvKiBcclxuICAgIERpZmZlcmVudGx5IGZyb20gdGhlIGFwcHJvYWNoIG9mIHRoZSBvdGhlciBmdW5jdGlvbnNcclxuICAgIGhlcmUgd2UgYXJlIHdvcmtpbmcgd2l0aCBzdHJpbmcgYW5kIG5vdCBudW1iZXJzLlxyXG5cclxuICAgIE51bWJlciBjaGVja3MgYXJlIHVzdWFsbHkgZmFzdGVyIHdoZW4gY2hlY2tpbmcgYSBjaGFyYWN0ZXIgaXNcclxuICAgIGluY2x1ZGVkIGluIGEgc3BlY2lmaWMgcmFuZ2UuXHJcbiAgICBGb3IgdGhpcyBjYXNlIHdlIGFyZSBjaGVja2luZyBpZiB0aGUgc3RyaW5nIGNvbnRhaW5zIGF0IGxlYXN0IG9uZSBjaGFyXHJcbiAgICBkaWZmZXJlbnQgZnJvbSBhIGxpc3Qgb2Ygbm9uIGFkaWFjZW50IGNoYXJhY3RlcnMgaW4gdGhlIEFTQ0lJIGNvZGUsIHJlc3VsdGluZ1xyXG4gICAgaW4gYSB2ZXJ5IGxvbmcgY29uZGl0aW9uIHdpdGggbXVsdGlwbGUgT1JcclxuXHJcbiAgICBUaGlzIGhhcyBiZWVuIHByb3ZlbiBzbG93ZXIgdGhhbiB1c2luZyBhIHJlZ2V4XHJcbiAgKi9cclxuICByZXR1cm4gL1xcUy8udGVzdChzdHIpXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiBnaXZlbiBhc2NpaSBjb2RlIGlzIGEgdmFsaWQgRmlyc3QgQ2hhcmFjdGVyXHJcbiAqIGZvciBKYXZhc3JpcHQgSWRlbnRpZmllcnNcclxuICogQHBhcmFtIGNvZGUgVGhlIGFzY2lpIGNvZGUgdG8gdmFsdWF0ZVxyXG4gKiBAcmV0dXJucyBUcnVlIGlmIGlzIHZhbGlkLCBmYWxzZSBvdGhlcndpc2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0pTSWRlbnRpZmllclN0YXJ0KGNvZGU6IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gIHJldHVybiAoXHJcbiAgICAoY29kZSA+PSA2NSAmJiBjb2RlIDw9IDkwKSB8fCAgICAvLyBBLVpcclxuICAgIChjb2RlID49IDk3ICYmIGNvZGUgPD0gMTIyKSB8fCAgIC8vIGEtelxyXG4gICAgY29kZSA9PT0gMzYgfHwgICAgICAgICAgICAgICAgICAgLy8gJFxyXG4gICAgY29kZSA9PT0gOTUgICAgICAgICAgICAgICAgICAgICAgLy8gX1xyXG4gICk7XHJcbn0iLCJpbXBvcnQgeyBHUkFWRV9BQ0NFTlQgfSBmcm9tICcuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHMuanMnO1xyXG5pbXBvcnQgeyBpc0pTSWRlbnRpZmllclN0YXJ0IH0gZnJvbSAnLi4vLi4vdXRpbHMvY2hhcnMudXRpbHMuanMnO1xyXG5pbXBvcnQgeyBMZXhlckN1cnNvciB9IGZyb20gJy4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tICcuLi90eXBlcy9sZXhlci1zdGF0ZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0IH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1yZXR1cm4tdHlwZS50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBEaXNwYXRjaGVzIGJldHdlZW4gYW4gZXhwcmVzc2lvbiBhbmQgYSBsaXRlcmFsIGludGVycG9sYXRpb24gYWZ0ZXIgdGhlIG9wZW5pbmcgYHtgLlxyXG4gKiBBZHZhbmNlcyBwYXN0IGB7YCBhbmQgYW55IGxlYWRpbmcgc3BhY2VzLCB0aGVuIGluc3BlY3RzIHRoZSBuZXh0IGNoYXJhY3RlcjpcclxuICogYSBiYWNrdGljayByb3V0ZXMgdG8gSU5URVJQT0xBVElPTl9MSVRFUkFMLCBhIEpTIGlkZW50aWZpZXIgc3RhcnQgcm91dGVzIHRvIElOVEVSUE9MQVRJT05fRVhQUkVTU0lPTi5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgb24gdGhlIGB7YCBjaGFyYWN0ZXIuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgaW50ZXJwb2xhdGlvbiBzdWItc3RhdGUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29uc3VtZUludGVycG9sYXRpb24oY3Vyc29yOiBMZXhlckN1cnNvciwgX2NvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZTtcclxuXHJcbiAgLy8gQ29uc3VtZSAneycgY2hhcmFjdGVyc1xyXG4gIGN1cnNvci5hZHZhbmNlKCk7XHJcblxyXG4gIC8qXHJcbiAgICBTa2lwIGFsbCB0aGUgc3BhY2VzIGJldHdlZW4gJ3snIGFuZCB0aGUgYWN0dWFsIGludGVycG9sYXRpb24gY29udGVudFxyXG4gICAgRXg6ICd7ICAgICAgICAgbGFiZWx9XHJcbiAgKi9cclxuICBjdXJzb3Iuc2tpcFNwYWNlcygpO1xyXG4gIFxyXG4gIGNvbnN0IG5leHRDaGFyID0gY3Vyc29yLnBlZWsoKTtcclxuXHJcbiAgaWYgKG5leHRDaGFyID09PSBHUkFWRV9BQ0NFTlQpIHtcclxuICAgIHJldFZhbCA9IHsgc3RhdGU6IExleGVyU3RhdGUuSU5URVJQT0xBVElPTl9MSVRFUkFMIH07XHJcbiAgfSBlbHNlIGlmIChpc0pTSWRlbnRpZmllclN0YXJ0KG5leHRDaGFyKSkge1xyXG4gICAgcmV0VmFsID0geyBzdGF0ZTogTGV4ZXJTdGF0ZS5JTlRFUlBPTEFUSU9OX0VYUFJFU1NJT04gfTtcclxuICB9IGVsc2Uge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbnJlY29nbml6ZWQgRmlyc3QgQ2hhcmFjdGVyICR7U3RyaW5nLmZyb21DaGFyQ29kZShuZXh0Q2hhcil9IGluIGludGVycG9sYXRpb25gKTtcclxuICB9XHJcblxyXG4gIHJldHVybiByZXRWYWw7XHJcbn0iLCJpbXBvcnQgeyBBVF9TSUdOLCBHUkVBVEVSX1RIRU4sIFNMQVNILCBTUEFDRSB9IGZyb20gJy4uLy4uL2Nvc3RhbnRzL2NoYXJzLmNvbnN0YW50cy5qcyc7XHJcbmltcG9ydCB7IExleGVyQ3Vyc29yIH0gZnJvbSAnLi4vdHlwZXMvbGV4ZXItY3Vyc29yLm1vZGVsLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJTdGF0ZSB9IGZyb20gJy4uL3R5cGVzL2xleGVyLXN0YXRlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQgfSBmcm9tICcuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tY29udGV4dC50eXBlLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlIH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLXJldHVybi10eXBlLnR5cGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIFNjYW5zIHRoZSBib2R5IG9mIGFuIG9wZW4gdGFnIHRvIGRldGVybWluZSB3aGF0IGNvbWVzIG5leHQ6XHJcbiAqIGFuIGV2ZW50IGJpbmRpbmcgKGBAYCksIGFuIGF0dHJpYnV0ZSwgdGhlIGVuZCBvZiB0aGUgdGFnIChgPmAgb3IgYC9gKSwgb3Igd2hpdGVzcGFjZS5cclxuICogVHJhbnNpdGlvbnMgdG8gdGhlIGFwcHJvcHJpYXRlIHN0YXRlIHdpdGhvdXQgZW1pdHRpbmcgYW55IHRva2Vucy5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgaW5zaWRlIGEgdGFnIGJvZHkuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCB0aGUgbmV4dCBzdGF0ZSBhbmQgbm8gdG9rZW5zLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVUYWdCb2R5KGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZWFkID0gdHJ1ZTtcclxuICBsZXQgcmV0VmFsITogTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25SZXR1cm5UeXBlO1xyXG5cclxuICB3aGlsZSAocmVhZCkge1xyXG4gICAgY29uc3QgbmV4dENoYXIgPSBjdXJzb3IucGVlaygpO1xyXG5cclxuICAgIHN3aXRjaCAobmV4dENoYXIpIHtcclxuICAgICAgY2FzZSBBVF9TSUdOOlxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLkVWRU5UXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgU1BBQ0U6XHJcbiAgICAgICAgY3Vyc29yLnNraXBTcGFjZXMoKTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgR1JFQVRFUl9USEVOOlxyXG4gICAgICBjYXNlIFNMQVNIOlxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLlRBR19PUEVOX0VORFxyXG4gICAgICAgIH1cclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHJldFZhbCA9IHtcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLkFUVFJJQlVURVxyXG4gICAgICAgIH1cclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmV0VmFsXHJcbn0iLCJpbXBvcnQgeyBHUkVBVEVSX1RIRU4sIFNQQUNFIH0gZnJvbSAnLi4vLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tICcuLi90eXBlcy9sZXhlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBMZXhlclN0YXRlIH0gZnJvbSAnLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1jb250ZXh0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUgfSBmcm9tICcuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXMgYSBjbG9zaW5nIHRhZyBgPC90YWdOYW1lPmAsIHNraXBwaW5nIHRoZSBgPC9gIHByZWZpeCBhbmQgYW55IHN1cnJvdW5kaW5nXHJcbiAqIHdoaXRlc3BhY2UuIEVtaXRzIGEgVEFHX0NMT1NFX05BTUUgdG9rZW4gd2l0aCB0aGUgdGFnIG5hbWUgYW5kIHRyYW5zaXRpb25zIHRvIFRFWFQuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciBwb3NpdGlvbmVkIGF0IHRoZSBgPGAgb2YgYSBjbG9zaW5nIHRhZy5cclxuICogQHBhcmFtIF9jb250ZXh0IFVudXNlZCBsZXhlciBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBUcmFuc2l0aW9uIHJlc3VsdCB3aXRoIHRoZSBUQUdfQ0xPU0VfTkFNRSB0b2tlbiBhbmQgdGhlIFRFWFQgc3RhdGUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY29uc3VtZVRhZ0Nsb3NlKGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZWFkID0gdHJ1ZTtcclxuICBsZXQgdGFnTmFtZSA9ICcnO1xyXG4gIGxldCByZXRWYWwhOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGU7XHJcblxyXG4gIC8vIFNraXAgJzwvJ1xyXG4gIGN1cnNvci5hZHZhbmNlKDIpO1xyXG5cclxuICAvKlxyXG4gICAgU2tpcCBhbGwgdGhlIHNwYWNlcyBiZXR3ZWVuICc8LycgYW5kIHRoZSBhY3R1YWwgdGFnIG5hbWVcclxuICAgIEV4OiAnPC8gICAgICAgICBkaXY+XHJcbiAgKi9cclxuICBjdXJzb3Iuc2tpcFNwYWNlcygpO1xyXG5cclxuICB3aGlsZSAocmVhZCkge1xyXG4gICAgc3dpdGNoIChjdXJzb3IucGVlaygpKSB7XHJcbiAgICAgIGNhc2UgR1JFQVRFUl9USEVOOlxyXG4gICAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICAgICAgcmV0VmFsID0ge1xyXG4gICAgICAgICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgICAgICAgIHRva2VuczogW3tcclxuICAgICAgICAgICAgdHlwZTogVG9rZW5UeXBlLlRBR19DTE9TRV9OQU1FLCBcclxuICAgICAgICAgICAgcGFydHM6IFt0YWdOYW1lXVxyXG4gICAgICAgICAgfV1cclxuICAgICAgICB9O1xyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgU1BBQ0U6XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUYWcgQ2xvc2UgTmFtZSBjYW5ub3QgY29udGFpbnMgc3BhY2VzJyk7XHJcblxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICAgICAgdGFnTmFtZSA9IGAke3RhZ05hbWV9JHtjdXJzb3IuY3VycmVudENoYXIudmFsdWV9YDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiByZXRWYWw7XHJcbn0iLCJpbXBvcnQgeyBHUkVBVEVSX1RIRU4gfSBmcm9tICcuLi8uLi9jb3N0YW50cy9jaGFycy5jb25zdGFudHMuanMnO1xyXG5pbXBvcnQgeyBMZXhlckN1cnNvciB9IGZyb20gJy4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tICcuLi90eXBlcy9sZXhlci1zdGF0ZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJUcmFuc2l0aW9uRnVuY3Rpb25Db250ZXh0IH0gZnJvbSAnLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1yZXR1cm4tdHlwZS50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyB0aGUgY2xvc2luZyBjaGFyYWN0ZXJzIG9mIGFuIG9wZW4gdGFnOiBgPmAgZW1pdHMgVEFHX09QRU5fRU5EIGFuZFxyXG4gKiB0cmFuc2l0aW9ucyB0byBURVhULCB3aGlsZSBgLz5gIGVtaXRzIFRBR19TRUxGX0NMT1NFIGFuZCBhbHNvIHRyYW5zaXRpb25zIHRvIFRFWFQuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciBwb3NpdGlvbmVkIGF0IGA+YCBvciBgL2AuXHJcbiAqIEBwYXJhbSBfY29udGV4dCBVbnVzZWQgbGV4ZXIgY29udGV4dC5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCBUQUdfT1BFTl9FTkQgb3IgVEFHX1NFTEZfQ0xPU0UgYW5kIHRoZSBURVhUIHN0YXRlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVUYWdPcGVuRW5kKGN1cnNvcjogTGV4ZXJDdXJzb3IsIF9jb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZXRWYWwhOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGVcclxuXHJcbiAgLy8gV2UgYXJyaXZlIGluIHRoaXMgcG9pbnQgYnkgcmVhZGluZyAnPicgb3IgJy8nIGF0IHRoZSBlbmQgb2YgYSBPcGVuIFRhZyBcclxuICBpZiAoY3Vyc29yLnBlZWsoKSA9PT0gR1JFQVRFUl9USEVOKSB7XHJcbiAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgcmV0VmFsID0geyBcclxuICAgICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgICAgdG9rZW5zOiBbe1xyXG4gICAgICAgIHR5cGU6IFRva2VuVHlwZS5UQUdfT1BFTl9FTkQsXHJcbiAgICAgICAgcGFydHM6IFtdXHJcbiAgICAgIH1dIFxyXG4gICAgfTtcclxuICB9IGVsc2Uge1xyXG4gICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgIGNvbnN0IG5leHRDaGFyID0gY3Vyc29yLnBlZWsoKTtcclxuXHJcbiAgICBpZiAobmV4dENoYXIgPT09IEdSRUFURVJfVEhFTikge1xyXG4gICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICByZXRWYWwgPSB7XHJcbiAgICAgICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgICAgICB0b2tlbnM6IFt7XHJcbiAgICAgICAgICB0eXBlOiBUb2tlblR5cGUuVEFHX1NFTEZfQ0xPU0UsXHJcbiAgICAgICAgICBwYXJ0czogW11cclxuICAgICAgICB9XVxyXG4gICAgICB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGNoYXJhY3RlciAke25leHRDaGFyfSBmb3IgY2xvc2luZyB0YWcuXFxuRXhwZWN0ZWQgLz5cXG5SZWFkIG9mIC8ke1N0cmluZy5mcm9tQ2hhckNvZGUobmV4dENoYXIpfVxcbkF0IGxpbmUgJHtjdXJzb3IucG9zaXRpb24ucm93ICsgMX0gY29sICR7Y3Vyc29yLnBvc2l0aW9uLmNvbHVtbiArIDF9YClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiByZXRWYWxcclxufSIsImltcG9ydCB7IEdSRUFURVJfVEhFTiwgU0xBU0gsIFNQQUNFIH0gZnJvbSAnLi4vLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tICcuLi90eXBlcy9sZXhlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBMZXhlclN0YXRlIH0gZnJvbSAnLi4vdHlwZXMvbGV4ZXItc3RhdGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzL3RyYW5zaXRpb24tZnVuY3Rpb24vdHJhbnNpdGlvbi1mdW5jdGlvbi1jb250ZXh0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUgfSBmcm9tICcuLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24tcmV0dXJuLXR5cGUudHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogQ29uc3VtZXMgYW4gb3BlbmluZyB0YWcgbmFtZSBhZnRlciBgPGAsIHJlYWRpbmcgdW50aWwgYSBzcGFjZSwgYC9gLCBvciBgPmAgaXMgZm91bmQuXHJcbiAqIEVtaXRzIGEgVEFHX09QRU5fTkFNRSB0b2tlbiB3aXRoIHRoZSB0YWcgbmFtZSBhbmQgdHJhbnNpdGlvbnMgdG8gVEFHX0JPRFkuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgVGhlIGxleGVyIGN1cnNvciBwb3NpdGlvbmVkIGF0IHRoZSBgPGAgY2hhcmFjdGVyLlxyXG4gKiBAcGFyYW0gX2NvbnRleHQgVW51c2VkIGxleGVyIGNvbnRleHQuXHJcbiAqIEByZXR1cm5zIFRyYW5zaXRpb24gcmVzdWx0IHdpdGggdGhlIFRBR19PUEVOX05BTUUgdG9rZW4gYW5kIHRoZSBUQUdfQk9EWSBzdGF0ZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjb25zdW1lVGFnT3Blbk5hbWUoY3Vyc29yOiBMZXhlckN1cnNvciwgX2NvbnRleHQ6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uQ29udGV4dCk6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZSB7XHJcbiAgbGV0IHJlYWQgPSB0cnVlO1xyXG4gIGxldCB0YWdOYW1lID0gJyc7XHJcbiAgbGV0IHJldFZhbCE6IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uUmV0dXJuVHlwZVxyXG5cclxuICAvLyBDb25zdW1lICc8JyBjaGFyYWN0ZXJcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG5cclxuICAvKlxyXG4gICAgU2tpcCBhbGwgdGhlIHNwYWNlcyBiZXR3ZWVuICc8JyBhbmQgdGhlIGFjdHVhbCB0YWcgbmFtZVxyXG4gICAgRXg6ICc8ICAgICAgICAgZGl2PlxyXG4gICovXHJcbiAgY3Vyc29yLnNraXBTcGFjZXMoKTtcclxuXHJcbiAgLypcclxuICAgIEtlZXAgcmVhZCBpbnB1dCB1bnRpbDpcclxuICAgIC0gU3BhY2U6IDxzcGFuIFxyXG4gICAgLSBHVDogPHNwYW4+XHJcbiAgICAtIFNsYXNoIChTZWxmIENsb3NpbmcgdGFnKSA8c3BhbiAvIG9yIDxzcGFuL1xyXG4gICovXHJcbiAgd2hpbGUgKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIFNQQUNFOlxyXG4gICAgICBjYXNlIFNMQVNIOlxyXG4gICAgICBjYXNlIEdSRUFURVJfVEhFTjpcclxuICAgICAgICByZXRWYWwgPSB7XHJcbiAgICAgICAgICBzdGF0ZTogTGV4ZXJTdGF0ZS5UQUdfQk9EWSxcclxuICAgICAgICAgIHRva2VuczogW3sgXHJcbiAgICAgICAgICAgIHR5cGU6IFRva2VuVHlwZS5UQUdfT1BFTl9OQU1FLCBcclxuICAgICAgICAgICAgcGFydHM6IFt0YWdOYW1lXSBcclxuICAgICAgICAgIH1dXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgICAgICB0YWdOYW1lID0gYCR7dGFnTmFtZX0ke2N1cnNvci5jdXJyZW50Q2hhci52YWx1ZX1gXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmV0VmFsXHJcbn0iLCJpbXBvcnQgeyBBVF9TSUdOLCBDUiwgTEVGVF9CUkFDRSwgTEVTU19USEFOLCBMRiwgUklHSFRfQlJBQ0UsIFNMQVNIIH0gZnJvbSBcIi4uLy4uL2Nvc3RhbnRzL2NoYXJzLmNvbnN0YW50cy5qc1wiO1xyXG5pbXBvcnQgeyBpc05vdEJsYW5rIH0gZnJvbSBcIi4uLy4uL3V0aWxzL2NoYXJzLnV0aWxzLmpzXCI7XHJcbmltcG9ydCB7IExleGVyQ3Vyc29yIH0gZnJvbSBcIi4uL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclN0YXRlIH0gZnJvbSBcIi4uL3R5cGVzL2xleGVyLXN0YXRlLmVudW0uanNcIjtcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSBcIi4uL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQgfSBmcm9tIFwiLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLWNvbnRleHQudHlwZS5qc1wiO1xyXG5pbXBvcnQgeyBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUgfSBmcm9tIFwiLi4vdHlwZXMvdHJhbnNpdGlvbi1mdW5jdGlvbi90cmFuc2l0aW9uLWZ1bmN0aW9uLXJldHVybi10eXBlLnR5cGUuanNcIjtcclxuXHJcbi8qKlxyXG4gKiBDb25zdW1lcyBwbGFpbiB0ZXh0IGNvbnRlbnQsIGFjY3VtdWxhdGluZyBjaGFyYWN0ZXJzIHVudGlsIGEgc3RydWN0dXJhbCBib3VuZGFyeVxyXG4gKiBpcyByZWFjaGVkOiBgPGAgKHRhZyBvcGVuL2Nsb3NlKSwgYHtgIChpbnRlcnBvbGF0aW9uKSwgYEBgIChmbG93LWNvbnRyb2wgb3IgZXZlbnQpLFxyXG4gKiBvciBgfWAgKGJsb2NrIGNsb3NlKS4gRW1pdHMgYSBURVhUIHRva2VuIGlmIG5vbi1ibGFuayB0ZXh0IHdhcyBhY2N1bXVsYXRlZC5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBUaGUgbGV4ZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIHN0YXJ0IG9mIHRleHQgY29udGVudC5cclxuICogQHBhcmFtIGNvbnRleHQgTGV4ZXIgY29udGV4dCB1c2VkIHRvIGRldGVjdCBmbG93LWNvbnRyb2wgYmxvY2sgYm91bmRhcmllcy5cclxuICogQHJldHVybnMgVHJhbnNpdGlvbiByZXN1bHQgd2l0aCBhbiBvcHRpb25hbCBURVhUIHRva2VuIGFuZCB0aGUgbmV4dCBzdGF0ZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBjb25zdW1lVGV4dChjdXJzb3I6IExleGVyQ3Vyc29yLCBjb250ZXh0OiBMZXhlclRyYW5zaXRpb25GdW5jdGlvbkNvbnRleHQpOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGUge1xyXG4gIGxldCByZWFkID0gdHJ1ZTtcclxuICBsZXQgdGV4dCA9ICcnO1xyXG4gIGxldCByZXRWYWwhOiBMZXhlclRyYW5zaXRpb25GdW5jdGlvblJldHVyblR5cGVcclxuXHJcbiAgd2hpbGUgKHJlYWQpIHtcclxuICAgIHN3aXRjaCAoY3Vyc29yLnBlZWsoKSkge1xyXG4gICAgICBjYXNlIExFU1NfVEhBTjpcclxuICAgICAgICAvLyBJZiBhZnRlciAnPCcgd2UgcmVhZCBhICcvJywgd2Ugc3VwcG9zZSB3ZSdyZSBhcHByb2FjaGluZyBhIENsb3N1cmVUYWcsIG90aGVyd2lzZSBhbiBPcGVuVGFnXHJcbiAgICAgICAgY29uc3QgbmV4dFN0YXRlID0gY3Vyc29yLnBlZWsoMSwgeyBvZmZzZXQ6IDEgfSkgPT09IFNMQVNIID8gTGV4ZXJTdGF0ZS5UQUdfQ0xPU0UgOiBMZXhlclN0YXRlLlRBR19PUEVOX05BTUU7XHJcbiAgICAgICAgcmV0VmFsID0geyBzdGF0ZTogbmV4dFN0YXRlIH1cclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIExFRlRfQlJBQ0U6XHJcbiAgICAgICAgcmV0VmFsID0geyBcclxuICAgICAgICAgIHN0YXRlOiBMZXhlclN0YXRlLklOVEVSUE9MQVRJT04sXHJcbiAgICAgICAgICBwdXNoU3RhdGU6IHRydWVcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgXHJcbiAgICAgIGNhc2UgQVRfU0lHTjpcclxuICAgICAgICByZXRWYWwgPSB7XHJcbiAgICAgICAgICBzdGF0ZTogTGV4ZXJTdGF0ZS5GTE9XX0NPTlRST0wsXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuXHJcbiAgICAgIGNhc2UgUklHSFRfQlJBQ0U6XHJcbiAgICAgICAgaWYgKGNvbnRleHQuaGlzdG9yeVtjb250ZXh0Lmhpc3RvcnkubGVuZ3RoIC0gMV0gPT09IExleGVyU3RhdGUuRkxPV19DT05UUk9MX0JMT0NLKSB7XHJcbiAgICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgICAgcmV0VmFsID0geyBcclxuICAgICAgICAgICAgc3RhdGU6IExleGVyU3RhdGUuVEVYVCxcclxuICAgICAgICAgICAgdG9rZW5zOiBbeyB0eXBlOiBUb2tlblR5cGUuQkxPQ0tfQ0xPU0UgfV0sXHJcbiAgICAgICAgICAgIHBvcFN0YXRlOiB0cnVlIFxyXG4gICAgICAgICAgfTtcclxuICAgICAgICAgIHJlYWQgPSBmYWxzZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgICAgICAgIHRleHQgPSBgJHt0ZXh0fSR7Y3Vyc29yLmN1cnJlbnRDaGFyLnZhbHVlfWA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBMRjpcclxuICAgICAgY2FzZSBDUjpcclxuICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gICAgICAgIHRleHQgPSBgJHt0ZXh0fSR7Y3Vyc29yLmN1cnJlbnRDaGFyLnZhbHVlfWA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuXHJcbiAgLypcclxuICAgIElmIHRoZSBmaXJzdCByZWFkIGNoYXJhY3RlciB0cmlnZ2VyIGEgU3RhdGVDaGFuZ2VcclxuICAgIFRoZSBjdW11bGF0aXZlIGB0ZXh0YCB2YXJpYWJsZSB3aWxsIGJlIGVtcHR5XHJcblxyXG4gICAgSW4gdGhpcyBjYXNlIHdlIG11c3QgTk9UIGFkZCBhbnkgdG9rZW5cclxuXHJcbiAgICBFeDpcclxuICAgIFRlbXBsYXRlIHN0YXJ0cyB3aXRoIGEgdGFnOlxyXG4gICAgICBgPGRpdiAuLi5gXHJcbiAgICBPciBhbiBpbnRlcnBvbGF0aW9uOlxyXG4gICAgICBgeyBteVZhcmlhYmxlIH1gXHJcbiAgKi9cclxuICByZXRWYWwudG9rZW5zID8/PSAoaXNOb3RCbGFuayh0ZXh0KVxyXG4gICAgPyBbeyB0eXBlOiBUb2tlblR5cGUuVEVYVCwgcGFydHM6IFt0ZXh0XSB9XVxyXG4gICAgOiB1bmRlZmluZWQpO1xyXG5cclxuICByZXR1cm4gcmV0VmFsXHJcbn0iLCJpbXBvcnQgeyBQb3NpdGl2ZUludGVnZXIsIFR1cGxlT2ZMZW5ndGggfSBmcm9tICdAeGFlbmRhci90eXBlcyc7XHJcbmltcG9ydCB7IENSLCBFT0YsIExGLCBTUEFDRSB9IGZyb20gJy4uLy4uL2Nvc3RhbnRzL2NoYXJzLmNvbnN0YW50cy5qcyc7XHJcbmltcG9ydCB7IEN1cnJlbnRDaGFyIH0gZnJvbSAnLi9jdXJyZW50LWNoYXIudHlwZS5qcyc7XHJcbmltcG9ydCB7IEN1cnNvclBvc2l0aW9uIH0gZnJvbSAnLi9jdXJyZW50LXBvc2l0aW9uLnR5cGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIEN1cnNvciBhYnN0cmFjdGlvbiB1c2VkIGJ5IHRoZSBMZXhlciB0byBuYXZpZ2F0ZSB0aGUgaW5wdXQgc291cmNlLlxyXG4gKlxyXG4gKiBUaGUgTGV4ZXJDdXJzb3IgaXMgcmVzcG9uc2libGUgZm9yOlxyXG4gKiAtIFNlcXVlbnRpYWwgY2hhcmFjdGVyIGNvbnN1bXB0aW9uXHJcbiAqIC0gTG9va2FoZWFkIChwZWVrKSBvcGVyYXRpb25zIHdpdGhvdXQgc3RhdGUgbXV0YXRpb25cclxuICogLSBUcmFja2luZyBsb2dpY2FsIHBvc2l0aW9uIChyb3csIGNvbHVtbilcclxuICogLSBIYW5kbGluZyBlbmQtb2YtZmlsZSBjb25kaXRpb25zXHJcbiAqXHJcbiAqIFRoaXMgY2xhc3MgZGVsaWJlcmF0ZWx5IGNvbnRhaW5zICoqbm8gbGV4ZXIgbG9naWMqKjpcclxuICogaXQgZG9lcyBub3Qga25vdyBhYm91dCB0b2tlbnMsIHN0YXRlcywgb3IgZ3JhbW1hciBydWxlcy5cclxuICogSXRzIHNvbGUgcmVzcG9uc2liaWxpdHkgaXMgY29udHJvbGxlZCBuYXZpZ2F0aW9uIG9mIHRoZSBpbnB1dCBzdHJlYW0uXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgTGV4ZXJDdXJzb3Ige1xyXG4gIC8qKlxyXG4gICAqIFJlcHJlc2VudGF0aW9uIG9mIHRoZSBjdXJyZW50IGNoYXJhY3Rlci5cclxuICAgKlxyXG4gICAqIC0gYGluZGV4YDogYWJzb2x1dGUgaW5kZXggd2l0aGluIHRoZSBpbnB1dCBzdHJpbmdcclxuICAgKiAtIGBjb2RlYDogVW5pY29kZSBjb2RlIHBvaW50IG9mIHRoZSBjaGFyYWN0ZXJcclxuICAgKiAtIGB2YWx1ZWA6IGFjdHVhbCBjaGFyYWN0ZXIgdmFsdWVcclxuICAgKlxyXG4gICAqIEFuIGluZGV4IG9mIGAtMWAgaW5kaWNhdGVzIHRoYXQgdGhlIGN1cnNvciBoYXMgbm90IHlldCBjb25zdW1lZFxyXG4gICAqIGFueSBjaGFyYWN0ZXIgb3IgaGFzIHJlYWNoZWQgRU9GLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2N1cnJlbnRDaGFyOiBDdXJyZW50Q2hhciA9IHtcclxuICAgIGNvZGU6IDAsXHJcbiAgICBpbmRleDogLTEsXHJcbiAgICB2YWx1ZTogJydcclxuICB9O1xyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSByZWFkLW9ubHkgc25hcHNob3Qgb2YgdGhlIGN1cnJlbnQgY2hhcmFjdGVyLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBnZXQgY3VycmVudENoYXIoKTogUmVhZG9ubHk8Q3VycmVudENoYXI+IHtcclxuICAgIHJldHVybiB0aGlzLl9jdXJyZW50Q2hhcjtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ2FjaGUgdXNlZCBieSBwZWVrIG9wZXJhdGlvbnMgdG8gYXZvaWQgcmUtcmVhZGluZ1xyXG4gICAqIHRoZSBzYW1lIGNoYXJhY3RlciBwb3NpdGlvbnMgbXVsdGlwbGUgdGltZXMuXHJcbiAgICpcclxuICAgKiBLZXk6IGFic29sdXRlIGNoYXJhY3RlciBpbmRleFxyXG4gICAqIFZhbHVlOiBVbmljb2RlIGNvZGUgcG9pbnRcclxuICAgKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IF9wZWVrQ2FjaGUgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xyXG4gIC8qKlxyXG4gICAqIExvZ2ljYWwgcG9zaXRpb24gb2YgdGhlIGN1cnNvciBpbiB0aGUgaW5wdXQuXHJcbiAgICpcclxuICAgKiAtIGByb3dgOiB6ZXJvLWJhc2VkIGxpbmUgbnVtYmVyXHJcbiAgICogLSBgY29sdW1uYDogemVyby1iYXNlZCBjb2x1bW4gbnVtYmVyXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSBfcG9zaXRpb246IEN1cnNvclBvc2l0aW9uID0ge1xyXG4gICAgcm93OiAwLFxyXG4gICAgY29sdW1uOiAwXHJcbiAgfTtcclxuICAvKipcclxuICAgKiBSZXR1cm5zIGEgcmVhZC1vbmx5IHNuYXBzaG90IG9mIHRoZSBjdXJyZW50IGN1cnNvciBwb3NpdGlvbi5cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IHBvc2l0aW9uKCk6IFJlYWRvbmx5PEN1cnNvclBvc2l0aW9uPiB7XHJcbiAgICByZXR1cm4gdGhpcy5fcG9zaXRpb247XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGEgbmV3IGN1cnNvciBmb3IgdGhlIGdpdmVuIGlucHV0IHNvdXJjZS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBpbnB1dCBGdWxsIHNvdXJjZSBzdHJpbmcgdG8gYmUgdG9rZW5pemVkLlxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBpbnB1dDogc3RyaW5nKSB7IH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWR2YW5jZXMgdGhlIGN1cnNvciBieSB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBjaGFyYWN0ZXJzLlxyXG4gICAqXHJcbiAgICogVGhpcyBtZXRob2Q6XHJcbiAgICogLSBVcGRhdGVzIHRoZSBjdXJyZW50IGNoYXJhY3RlclxyXG4gICAqIC0gVXBkYXRlcyByb3cvY29sdW1uIHBvc2l0aW9uXHJcbiAgICogLSBEZXRlY3RzIGxpbmUgYnJlYWtzIChMRiAvIENSKVxyXG4gICAqIC0gVGhyb3dzIGFuIEVPRiBlcnJvciB3aGVuIHRoZSBlbmQgb2YgdGhlIGlucHV0IGlzIHJlYWNoZWRcclxuICAgKlxyXG4gICAqIEBwYXJhbSBjaGFycyBOdW1iZXIgb2YgY2hhcmFjdGVycyB0byBjb25zdW1lIChtdXN0IGJlID49IDEpXHJcbiAgICpcclxuICAgKiBAdGhyb3dzIEVycm9yIHdpdGggY2F1c2UgYEVPRmAgd2hlbiBhZHZhbmNpbmcgcGFzdCBpbnB1dCBsZW5ndGhcclxuICAgKi9cclxuICBwdWJsaWMgYWR2YW5jZShjaGFycyA9IDEpOiB2b2lkIHtcclxuICAgIGlmIChjaGFycyA8IDEpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NoYXJzfSBpcyBub3QgYSB2YWxpZCB2YWx1ZS4gUGxlYXNlIGVudGVyIGEgbnVtYmVyIGVxdWFsIG9yIGdyZWF0ZXIgdGhhbiAxYCk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbmV3SW5kZXggPSB0aGlzLl9jdXJyZW50Q2hhci5pbmRleCArIGNoYXJzO1xyXG5cclxuICAgIGlmIChuZXdJbmRleCA+PSB0aGlzLmlucHV0Lmxlbmd0aCkge1xyXG4gICAgICB0aGlzLl9jdXJyZW50Q2hhci5jb2RlID0gRU9GO1xyXG4gICAgICB0aGlzLl9jdXJyZW50Q2hhci5pbmRleCA9IC0xO1xyXG4gICAgICB0aGlzLl9jdXJyZW50Q2hhci52YWx1ZSA9ICcnO1xyXG4gICAgICB0aGlzLnRocm93RU9GRXJyb3IoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8qXHJcbiAgICAgICAgQmVmb3JlIHVwZGF0aW5nIHRoZSBjaGFyYWN0ZXIsIGFkanVzdCBsb2dpY2FsIHBvc2l0aW9uLlxyXG4gICAgICAgIExpbmUgYnJlYWtzIHJlc2V0IGNvbHVtbiBhbmQgaW5jcmVtZW50IHJvdy5cclxuICAgICAgKi9cclxuICAgICAgaWYgKFtMRiwgQ1JdLmluY2x1ZGVzKHRoaXMuX2N1cnJlbnRDaGFyLmNvZGUpKSB7XHJcbiAgICAgICAgdGhpcy5fcG9zaXRpb24ucm93Kys7XHJcbiAgICAgICAgdGhpcy5fcG9zaXRpb24uY29sdW1uID0gMDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLl9wb3NpdGlvbi5jb2x1bW4rKztcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5fY3VycmVudENoYXIuaW5kZXggPSBuZXdJbmRleDtcclxuICAgICAgdGhpcy5fY3VycmVudENoYXIudmFsdWUgPSB0aGlzLmlucHV0W25ld0luZGV4XSE7XHJcbiAgICAgIHRoaXMuX2N1cnJlbnRDaGFyLmNvZGUgPSB0aGlzLmlucHV0LmNoYXJDb2RlQXQobmV3SW5kZXgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIHVwY29taW5nIGNoYXJhY3RlcnMgaW4gdGhlIGlucHV0IG1hdGNoIHRoZSBnaXZlbiBwYXR0ZXJuLFxyXG4gICAqIHdpdGhvdXQgYWR2YW5jaW5nIHRoZSBjdXJzb3IuXHJcbiAgICpcclxuICAgKiAtIGBzdHJpbmdgOiBmYXN0IHBhdGggdXNpbmcgY2hhciBjb2RlIGNvbXBhcmlzb24gKG5vIGFsbG9jYXRpb24pXHJcbiAgICogLSBgUmVnRXhwYDogc2xpY2VzIHRoZSBpbnB1dCBhbmQgdGVzdHMgdGhlIHBhdHRlcm4gYWdhaW5zdCBpdC5cclxuICAgKiAgIFJlcXVpcmVzIGBsZW5ndGhgIHRvIGtub3cgaG93IG1hbnkgY2hhcmFjdGVycyB0byBwZWVrLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHBhdHRlcm4gU3RyaW5nIG9yIFJlZ0V4cCB0byBtYXRjaCBhZ2FpbnN0XHJcbiAgICogQHBhcmFtIGxlbmd0aCAgTnVtYmVyIG9mIGNoYXJhY3RlcnMgdG8gcGVlayDigJQgcmVxdWlyZWQgd2hlbiBgcGF0dGVybmAgaXMgYSBSZWdFeHBcclxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHVwY29taW5nIGNoYXJhY3RlcnMgbWF0Y2gsIGBmYWxzZWAgb3RoZXJ3aXNlXHJcbiAgICovXHJcbiAgcHVibGljIHBlZWtNYXRjaChwYXR0ZXJuOiBzdHJpbmcpOiBib29sZWFuO1xyXG4gIHB1YmxpYyBwZWVrTWF0Y2gocGF0dGVybjogUmVnRXhwLCBsZW5ndGg6IG51bWJlcik6IGJvb2xlYW47XHJcbiAgcHVibGljIHBlZWtNYXRjaChwYXR0ZXJuOiBzdHJpbmcgfCBSZWdFeHAsIGxlbmd0aD86IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykge1xyXG4gICAgICBjb25zdCBwZWVrZWRDaGFycyA9IHRoaXMucGVlayhwYXR0ZXJuLmxlbmd0aCk7XHJcblxyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBpZiAocGVla2VkQ2hhcnNbaV0gIT09IHBhdHRlcm4uY2hhckNvZGVBdChpKSkge1xyXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmVnRXhwIHBhdGgg4oCUIHNsaWNlIGlucHV0IGFuZCB0ZXN0XHJcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX2N1cnJlbnRDaGFyLmluZGV4ICsgMTtcclxuICAgIGNvbnN0IHNsaWNlID0gdGhpcy5pbnB1dC5zbGljZShzdGFydCwgc3RhcnQgKyBsZW5ndGghKTtcclxuICAgIHJldHVybiBwYXR0ZXJuLnRlc3Qoc2xpY2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVla3MgYWhlYWQgaW4gdGhlIGlucHV0IHN0cmVhbSB3aXRob3V0IGFkdmFuY2luZyB0aGUgY3Vyc29yLlxyXG4gICAqXHJcbiAgICogVGhpcyBtZXRob2Qgc3VwcG9ydHM6XHJcbiAgICogLSBTaW5nbGUtY2hhcmFjdGVyIGxvb2thaGVhZFxyXG4gICAqIC0gTXVsdGktY2hhcmFjdGVyIGxvb2thaGVhZFxyXG4gICAqIC0gT3B0aW9uYWwgb2Zmc2V0IGZyb20gdGhlIGN1cnJlbnQgcG9zaXRpb25cclxuICAgKlxyXG4gICAqIFBlZWsgb3BlcmF0aW9ucyBhcmUgY2FjaGVkIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIGFuZCBkbyBub3RcclxuICAgKiBtb2RpZnkgdGhlIGN1cnNvciBzdGF0ZS5cclxuICAgKlxyXG4gICAqIEByZXR1cm5zXHJcbiAgICogLSBBIHNpbmdsZSBVbmljb2RlIGNvZGUgcG9pbnQgd2hlbiBwZWVraW5nIG9uZSBjaGFyYWN0ZXJcclxuICAgKiAtIEFuIGFycmF5IG9mIFVuaWNvZGUgY29kZSBwb2ludHMgd2hlbiBwZWVraW5nIG11bHRpcGxlIGNoYXJhY3RlcnNcclxuICAgKlxyXG4gICAqIEB0aHJvd3MgRXJyb3Igd2l0aCBjYXVzZSBgRU9GYCBpZiB0aGUgcGVlayBleGNlZWRzIGlucHV0IGxlbmd0aFxyXG4gICAqL1xyXG4gIHB1YmxpYyBwZWVrKCk6IG51bWJlcjtcclxuICBwdWJsaWMgcGVlazxPZmZTZXQgZXh0ZW5kcyBudW1iZXI+KG9wdGlvbnM/OiB7IG9mZnNldD86IFBvc2l0aXZlSW50ZWdlcjxPZmZTZXQ+IH0pOiBudW1iZXI7XHJcbiAgcHVibGljIHBlZWsoY2hhcnM6IDEpOiBudW1iZXI7XHJcbiAgcHVibGljIHBlZWs8T2ZmU2V0IGV4dGVuZHMgbnVtYmVyPihjaGFyczogMSwgb3B0aW9ucz86IHsgb2Zmc2V0PzogUG9zaXRpdmVJbnRlZ2VyPE9mZlNldD4gfSk6IG51bWJlcjsgXHJcbiAgcHVibGljIHBlZWs8UmVhZENoYXJzIGV4dGVuZHMgbnVtYmVyPihjaGFyczogUG9zaXRpdmVJbnRlZ2VyPFJlYWRDaGFycz4pOiBUdXBsZU9mTGVuZ3RoPFJlYWRDaGFycz47IFxyXG4gIHB1YmxpYyBwZWVrPFJlYWRDaGFycyBleHRlbmRzIG51bWJlciwgT2ZmU2V0IGV4dGVuZHMgbnVtYmVyPihjaGFyczogUG9zaXRpdmVJbnRlZ2VyPFJlYWRDaGFycz4sIG9wdGlvbnM/OiB7IG9mZnNldD86IFBvc2l0aXZlSW50ZWdlcjxPZmZTZXQ+IH0pOiBUdXBsZU9mTGVuZ3RoPFJlYWRDaGFycz47XHJcbiAgcHVibGljIHBlZWsoY2hhcnNPck9wdGlvbnM/OiBudW1iZXIgfCB7IG9mZnNldD86IG51bWJlciB9LCBvcHRpb25zPzogeyBvZmZzZXQ/OiBudW1iZXIgfSk6IG51bWJlciB8IG51bWJlcltdIHtcclxuICAgIGNvbnN0IGNhY2hlID0gdGhpcy5fcGVla0NhY2hlO1xyXG4gICAgY29uc3QgY2hhcnMgPSB0eXBlb2YgY2hhcnNPck9wdGlvbnMgPT09ICdudW1iZXInID8gY2hhcnNPck9wdGlvbnMgOiAxO1xyXG4gICAgY29uc3Qgb2Zmc2V0ID0gKHR5cGVvZiBjaGFyc09yT3B0aW9ucyA9PT0gJ29iamVjdCcgPyBjaGFyc09yT3B0aW9ucyA6IG9wdGlvbnMpPy5vZmZzZXQgPz8gMDtcclxuICAgIHJldHVybiBjaGFycyA9PT0gMSA/IHRoaXMucGVla09uZUNoYXIodGhpcy5fY3VycmVudENoYXIuaW5kZXggKyBvZmZzZXQgKyAxLCBjYWNoZSkgOiB0aGlzLnBlZWtNYW55KGNoYXJzICsgb2Zmc2V0LCBjYWNoZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTa2lwcyBhbGwgY29uc2VjdXRpdmUgc3BhY2UgY2hhcmFjdGVycyBmcm9tIHRoZSBjdXJyZW50IHBvc2l0aW9uLlxyXG4gICAqL1xyXG4gIHB1YmxpYyBza2lwU3BhY2VzKCk6IHZvaWQge1xyXG4gICAgd2hpbGUgKHRoaXMucGVlaygpID09PSBTUEFDRSB8fCB0aGlzLnBlZWsoKSA9PT0gTEYgfHwgdGhpcy5wZWVrKCkgPT09IENSKSB7XHJcbiAgICAgIHRoaXMuYWR2YW5jZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVla3MgbXVsdGlwbGUgY2hhcmFjdGVycyBhaGVhZC5cclxuICAgKi9cclxuICBwcml2YXRlIHBlZWtNYW55KGNoYXJzOiBudW1iZXIsIGNhY2hlOiBNYXA8bnVtYmVyLCBudW1iZXI+KTogbnVtYmVyW10ge1xyXG4gICAgY29uc3QgcGVla2VkQ2hhcnMgPSBuZXcgQXJyYXk8bnVtYmVyPjtcclxuICAgIGNvbnN0IG5leHRDaGFySW5kZXggPSB0aGlzLl9jdXJyZW50Q2hhci5pbmRleCArIDE7XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IG5leHRDaGFySW5kZXg7IGkgPCBuZXh0Q2hhckluZGV4ICsgY2hhcnM7IGkrKykge1xyXG4gICAgICBwZWVrZWRDaGFycy5wdXNoKHRoaXMucGVla09uZUNoYXIoaSwgY2FjaGUpKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gcGVla2VkQ2hhcnM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZWVrcyBhIHNpbmdsZSBjaGFyYWN0ZXIgYXQgdGhlIGdpdmVuIGFic29sdXRlIGluZGV4LlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcGVla09uZUNoYXIoaW5kZXg6IG51bWJlciwgY2FjaGU6IE1hcDxudW1iZXIsIG51bWJlcj4pOiBudW1iZXIge1xyXG4gICAgaWYgKGNhY2hlLmhhcyhpbmRleCkpIHtcclxuICAgICAgcmV0dXJuIGNhY2hlLmdldChpbmRleCkhO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChpbmRleCA+PSB0aGlzLmlucHV0Lmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnRocm93RU9GRXJyb3IoKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjaGFyQ29kZSA9IHRoaXMuaW5wdXQuY2hhckNvZGVBdChpbmRleCk7XHJcbiAgICBjYWNoZS5zZXQoaW5kZXgsIGNoYXJDb2RlKTtcclxuICAgIHJldHVybiBjaGFyQ29kZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRocm93cyBhIHN0YW5kYXJkaXplZCBFT0YgZXJyb3IgdXNlZCBieSB0aGUgbGV4ZXIgZW5naW5lXHJcbiAgICogdG8gdGVybWluYXRlIHRva2VuaXphdGlvbi5cclxuICAgKi9cclxuICBwcml2YXRlIHRocm93RU9GRXJyb3IoKTogbmV2ZXIge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKCcnLCB7IGNhdXNlOiBFT0YgfSk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IFN0YWNrIH0gZnJvbSAnQHhhZW5kYXIvY29tbW9uJztcclxuaW1wb3J0IHsgRGljdGlvbmFyeSB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgRU9GIH0gZnJvbSAnLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuaW1wb3J0IHsgY29uc3VtZUF0dHJpYnV0ZSB9IGZyb20gJy4vc3RhdGVzL2F0dHJpYnV0ZS5zdGF0ZS5qcyc7XHJcbmltcG9ydCB7IGNvbnN1bWVDYXNlRmxvd0NvbnRyb2xDb25kaXRpb24gfSBmcm9tICcuL3N0YXRlcy9jYXNlLWZsb3ctY29udHJvbC1jb25kaXRpb24uc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lQ29uc3REZWNsYXJhdGlvbiB9IGZyb20gJy4vc3RhdGVzL2NvbnN0LWRlY2xhcmF0aW9uLmpzJztcclxuaW1wb3J0IHsgY29uc3VtZUV2ZW50IH0gZnJvbSAnLi9zdGF0ZXMvZXZlbnQuc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lRmxvd0NvbnRyb2xCbG9jayB9IGZyb20gJy4vc3RhdGVzL2Zsb3ctY29udHJvbC1ibG9jay5zdGF0ZS5qcyc7XHJcbmltcG9ydCB7IGNvbnN1bWVEZWZhdWx0Rmxvd0NvbnRyb2xDb25kaXRpb24gfSBmcm9tICcuL3N0YXRlcy9kZWZhdWx0LWZsb3ctY29udHJvbC1jb25kaXRpb24uc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lRmxvd0NvbnRyb2wgfSBmcm9tICcuL3N0YXRlcy9mbG93LWNvbnRyb2wuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lSW50ZXJwb2xhdGlvbkV4cHJlc3Npb24gfSBmcm9tICcuL3N0YXRlcy9pbnRlcnBvbGF0aW9uLWV4cHJlc3Npb24uc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lSW50ZXJwb2xhdGlvbmxpdGVyYWwgfSBmcm9tICcuL3N0YXRlcy9pbnRlcnBvbGF0aW9uLWxpdGVyYWwuc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lSW50ZXJwb2xhdGlvbiB9IGZyb20gJy4vc3RhdGVzL2ludGVycG9sYXRpb24uc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lVGFnQm9keSB9IGZyb20gJy4vc3RhdGVzL3RhZy1ib2R5LnN0YXRlLmpzJztcclxuaW1wb3J0IHsgY29uc3VtZVRhZ0Nsb3NlIH0gZnJvbSAnLi9zdGF0ZXMvdGFnLWNsb3NlLnN0YXRlLmpzJztcclxuaW1wb3J0IHsgY29uc3VtZVRhZ09wZW5FbmQgfSBmcm9tICcuL3N0YXRlcy90YWctb3Blbi1lbmQuc3RhdGUuanMnO1xyXG5pbXBvcnQgeyBjb25zdW1lVGFnT3Blbk5hbWUgfSBmcm9tICcuL3N0YXRlcy90YWctb3Blbi1uYW1lLnN0YXRlLmpzJztcclxuaW1wb3J0IHsgY29uc3VtZVRleHQgfSBmcm9tICcuL3N0YXRlcy90ZXh0LnN0YXRlLmpzJztcclxuaW1wb3J0IHsgTGV4ZXJDdXJzb3IgfSBmcm9tICcuL3R5cGVzL2xleGVyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IExleGVyU3RhdGUgfSBmcm9tICcuL3R5cGVzL2xleGVyLXN0YXRlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBUb2tlbiB9IGZyb20gJy4vdHlwZXMvdG9rZW4udHlwZS5qcyc7XHJcbmltcG9ydCB7IExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uIH0gZnJvbSAnLi90eXBlcy90cmFuc2l0aW9uLWZ1bmN0aW9uL3RyYW5zaXRpb24tZnVuY3Rpb24udHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogVXRpbGl0eSBjbGFzcyB0aGF0IGVtdWxhdGVzIGEgY3Vyc29yIG5hdmlnYXRpbmcgdGhyb3VnaCBhIHRlbXBsYXRlIHN0cmluZy5cclxuICpcclxuICogVGhlIGN1cnNvciBrZWVwcyB0cmFjayBvZiB0aGUgY3VycmVudCBjaGFyYWN0ZXIsIGl0cyBhYnNvbHV0ZSBwb3NpdGlvblxyXG4gKiB3aXRoaW4gdGhlIHRleHQsIGFuZCBpdHMgbG9naWNhbCBwb3NpdGlvbiBleHByZXNzZWQgYXMgcm93IGFuZCBjb2x1bW4uXHJcbiAqIFRoaXMgaXMgdXNlZnVsIHdoZW4gcGFyc2luZyBvciBhbmFseXppbmcgdGVtcGxhdGUgY29udGVudCBjaGFyYWN0ZXIgYnkgY2hhcmFjdGVyLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIExleGVyIHtcclxuICAvKipcclxuICAgKiBDdXJzb3IgZm9yIG5hdmlnYXRpbmcgdGhlIGlucHV0IGNoYXJhY3RlciBzdHJlYW0uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSBfY3Vyc29yOiBMZXhlckN1cnNvcjtcclxuICAvKipcclxuICAgKiBDdXJyZW50IGxleGVyIHN0YXRlLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgX3N0YXRlID0gTGV4ZXJTdGF0ZS5TVEFSVDtcclxuICAvKipcclxuICAgKiBTdGF0ZSBzdGFjayB1c2VkIHRvIHN1cHBvcnQgbmVzdGVkIHN0YXRlcyAoZS5nLiBpbnRlcnBvbGF0aW9ucykuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBfc3RhY2sgPSBuZXcgU3RhY2s8TGV4ZXJTdGF0ZT47XHJcbiAgLyoqXHJcbiAgICogQWNjdW11bGF0ZWQgbGlzdCBvZiB0b2tlbnMgZW1pdHRlZCBkdXJpbmcgdG9rZW5pemF0aW9uLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX3Rva2VucyA9IG5ldyBBcnJheTxUb2tlbj47XHJcbiAgLyoqXHJcbiAgICogTWFwcyBlYWNoIGxleGVyIHN0YXRlIHRvIGl0cyBjb3JyZXNwb25kaW5nIHRyYW5zaXRpb24gZnVuY3Rpb24uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSBfc3RhdGVzOiBEaWN0aW9uYXJ5PExleGVyU3RhdGUsIExleGVyVHJhbnNpdGlvbkZ1bmN0aW9uPiA9IHtcclxuICAgIFtMZXhlclN0YXRlLlNUQVJUXTogY29uc3VtZVRleHQsXHJcbiAgICBbTGV4ZXJTdGF0ZS5URVhUXTogY29uc3VtZVRleHQsXHJcbiAgICBbTGV4ZXJTdGF0ZS5UQUdfT1BFTl9OQU1FXTogY29uc3VtZVRhZ09wZW5OYW1lLFxyXG4gICAgW0xleGVyU3RhdGUuVEFHX0JPRFldOiBjb25zdW1lVGFnQm9keSxcclxuICAgIFtMZXhlclN0YXRlLlRBR19PUEVOX0VORF06IGNvbnN1bWVUYWdPcGVuRW5kLFxyXG4gICAgW0xleGVyU3RhdGUuVEFHX0NMT1NFXTogY29uc3VtZVRhZ0Nsb3NlLFxyXG4gICAgW0xleGVyU3RhdGUuQVRUUklCVVRFXTogY29uc3VtZUF0dHJpYnV0ZSxcclxuICAgIFtMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF06IGNvbnN1bWVGbG93Q29udHJvbCxcclxuICAgIFtMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF9DT05ESVRJT05dOiBjb25zdW1lRGVmYXVsdEZsb3dDb250cm9sQ29uZGl0aW9uLFxyXG4gICAgW0xleGVyU3RhdGUuQ0FTRV9GTE9XX0NPTlRST0xfQ09ORElUSU9OXTogY29uc3VtZUNhc2VGbG93Q29udHJvbENvbmRpdGlvbixcclxuICAgIFtMZXhlclN0YXRlLkZMT1dfQ09OVFJPTF9CTE9DS106IGNvbnN1bWVGbG93Q29udHJvbEJsb2NrLFxyXG4gICAgW0xleGVyU3RhdGUuRVZFTlRdOiBjb25zdW1lRXZlbnQsXHJcbiAgICBbTGV4ZXJTdGF0ZS5JTlRFUlBPTEFUSU9OXTogY29uc3VtZUludGVycG9sYXRpb24sXHJcbiAgICBbTGV4ZXJTdGF0ZS5JTlRFUlBPTEFUSU9OX0VYUFJFU1NJT05dOiBjb25zdW1lSW50ZXJwb2xhdGlvbkV4cHJlc3Npb24sXHJcbiAgICBbTGV4ZXJTdGF0ZS5JTlRFUlBPTEFUSU9OX0xJVEVSQUxdOiBjb25zdW1lSW50ZXJwb2xhdGlvbmxpdGVyYWwsXHJcbiAgICBbTGV4ZXJTdGF0ZS5DT05TVF9ERUNMQVJBVElPTl06IGNvbnN1bWVDb25zdERlY2xhcmF0aW9uXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGEgbmV3IEN1cnNvciBpbnN0YW5jZSBmb3IgdGhlIGdpdmVuIHRlbXBsYXRlIGNvbnRlbnQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0gaW5wdXQgVGhlIGZ1bGwgdGVtcGxhdGUgdGV4dCB0aGF0IHRoZSBjdXJzb3Igd2lsbCBuYXZpZ2F0ZS5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihwdWJsaWMgaW5wdXQ6IHN0cmluZykge1xyXG4gICAgdGhpcy5fY3Vyc29yID0gbmV3IExleGVyQ3Vyc29yKHRoaXMuaW5wdXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUnVucyB0aGUgbGV4ZXIgb3ZlciB0aGUgaW5wdXQgc3RyaW5nIGFuZCByZXR1cm5zIHRoZSBmdWxsIHRva2VuIGFycmF5LlxyXG4gICAqIERyaXZlcyB0aGUgc3RhdGUgbWFjaGluZSB1bnRpbCBFT0YgaXMgcmVhY2hlZC5cclxuICAgKlxyXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIGFsbCB0b2tlbnMgcHJvZHVjZWQgZnJvbSB0aGUgaW5wdXQuXHJcbiAgICovXHJcbiAgcHVibGljIHRva2VuaXplKCk6IFRva2VuW10ge1xyXG4gICAgbGV0IGVvZiA9IGZhbHNlO1xyXG5cclxuICAgIHdoaWxlICghZW9mKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3QgdHJhbnNpdGlvbkZ1bmN0aW9uID0gdGhpcy5fc3RhdGVzW3RoaXMuX3N0YXRlXTtcclxuICAgICAgICBjb25zdCB7IHN0YXRlLCB0b2tlbnMsIHBvcFN0YXRlLCBwdXNoU3RhdGUgfSA9IHRyYW5zaXRpb25GdW5jdGlvbiEodGhpcy5fY3Vyc29yLCB7IFxyXG4gICAgICAgICAgaGlzdG9yeTogdGhpcy5fc3RhY2sudmFsdWVzLFxyXG4gICAgICAgICAgdG9rZW5zOiBbLi4udGhpcy5fdG9rZW5zXSBcclxuICAgICAgICB9KTtcclxuICAgICAgICBcclxuICAgICAgICBpZiAodG9rZW5zPy5sZW5ndGgpIHtcclxuICAgICAgICAgIHRoaXMuX3Rva2Vucy5wdXNoKC4uLnRva2Vucyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIGlmIChwdXNoU3RhdGUpIHtcclxuICAgICAgICAgIHRoaXMuX3N0YWNrLnB1c2godGhpcy5fc3RhdGUpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICBpZiAocG9wU3RhdGUpIHtcclxuICAgICAgICAgIHRoaXMuX3N0YWNrLnBvcCgpO1xyXG4gICAgICAgIH0gXHJcbiAgICAgICAgXHJcbiAgICAgICAgdGhpcy5fc3RhdGUgPSBzdGF0ZTtcclxuICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3IgPSBlcnIgYXMgRXJyb3I7XHJcbiAgICAgICAgaWYgKGVycm9yLmNhdXNlID09PSBFT0YpIHtcclxuICAgICAgICAgIGVvZiA9IHRydWU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRocm93IGVycjtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5fdG9rZW5zO1xyXG4gIH1cclxufSIsImltcG9ydCB7IFBvc2l0aXZlSW50ZWdlciwgVHVwbGVPZkxlbmd0aCB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgRU9GIH0gZnJvbSAnLi4vLi4vY29zdGFudHMvY2hhcnMuY29uc3RhbnRzLmpzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICcuLi8uLi9sZXhlci90eXBlcy90b2tlbi50eXBlLmpzJztcclxuaW1wb3J0IHsgQ3VycmVudFRva2VuIH0gZnJvbSAnLi4vdHlwZXMvY3VycmVudC10b2tlbi50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBDdXJzb3IgYWJzdHJhY3Rpb24gdXNlZCBieSB0aGUgUGFyc2VyIHRvIG5hdmlnYXRlXHJcbiAqIHRocm91Z2ggYSBzZXF1ZW5jZSBvZiB0b2tlbnMgcHJvZHVjZWQgYnkgdGhlIExleGVyLlxyXG4gKlxyXG4gKiBSZXNwb25zaWJpbGl0aWVzOlxyXG4gKiAtIFNlcXVlbnRpYWwgdG9rZW4gY29uc3VtcHRpb25cclxuICogLSBMb29rYWhlYWQgKHBlZWspIG9wZXJhdGlvbnMgd2l0aG91dCBtdXRhdGluZyBzdGF0ZVxyXG4gKiAtIEhhbmRsaW5nIGVuZC1vZi1maWxlIGNvbmRpdGlvbnNcclxuICpcclxuICogVGhpcyBjbGFzcyBkb2VzIG5vdCBwZXJmb3JtIHBhcnNpbmcgaXRzZWxmOiBpdCBvbmx5XHJcbiAqIG1hbmFnZXMgcG9zaXRpb24gYW5kIGFjY2VzcyB0byB0aGUgdG9rZW4gc3RyZWFtLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFBhcnNlckN1cnNvciB7XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlcHJlc2VudGF0aW9uIG9mIHRoZSBjdXJyZW50IHRva2VuLlxyXG4gICAqXHJcbiAgICogLSBgaW5kZXhgOiBhYnNvbHV0ZSBpbmRleCB3aXRoaW4gdGhlIHRva2VuIGFycmF5XHJcbiAgICogLSBgdmFsdWVgOiBjdXJyZW50IHRva2VuIG9iamVjdCAob3IgRU9GIHRva2VuKVxyXG4gICAqXHJcbiAgICogQW4gaW5kZXggb2YgYC0xYCBpbmRpY2F0ZXMgdGhhdCB0aGUgY3Vyc29yIGhhcyBub3RcclxuICAgKiB5ZXQgY29uc3VtZWQgYW55IHRva2VuIG9yIGhhcyByZWFjaGVkIEVPRi5cclxuICAgKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IF9jdXJyZW50VG9rZW46IEN1cnJlbnRUb2tlbiA9IHtcclxuICAgIHZhbHVlOiB7IHR5cGU6IFRva2VuVHlwZS5FT0YgfSxcclxuICAgIGluZGV4OiAtMVxyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgYSByZWFkLW9ubHkgc25hcHNob3Qgb2YgdGhlIGN1cnJlbnQgdG9rZW4uXHJcbiAgICovXHJcbiAgcHVibGljIGdldCBjdXJyZW50VG9rZW4oKTogUmVhZG9ubHk8Q3VycmVudFRva2VuPiB7XHJcbiAgICByZXR1cm4gdGhpcy5fY3VycmVudFRva2VuO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIG5ldyBQYXJzZXJDdXJzb3IgZm9yIHRoZSBnaXZlbiB0b2tlbiBhcnJheS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSBfdG9rZW5zIEFycmF5IG9mIHRva2VucyB0byBuYXZpZ2F0ZS5cclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IF90b2tlbnM6IFRva2VuW10pIHsgfVxyXG5cclxuICAvKipcclxuICAgKiBBZHZhbmNlcyB0aGUgY3Vyc29yIGJ5IHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIHRva2Vucy5cclxuICAgKlxyXG4gICAqIFVwZGF0ZXMgdGhlIGN1cnJlbnQgdG9rZW4gYW5kIGluZGV4LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGNoYXJzIE51bWJlciBvZiB0b2tlbnMgdG8gYWR2YW5jZSAobXVzdCBiZSA+PSAxKVxyXG4gICAqXHJcbiAgICogQHRocm93cyBFcnJvciB3aXRoIGNhdXNlIGBFT0ZgIHdoZW4gYWR2YW5jaW5nIHBhc3QgdGhlIGVuZFxyXG4gICAqL1xyXG4gIHB1YmxpYyBhZHZhbmNlKGNoYXJzID0gMSk6IHZvaWQge1xyXG4gICAgaWYgKGNoYXJzIDwgMSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y2hhcnN9IGlzIG5vdCBhIHZhbGlkIHZhbHVlLiBQbGVhc2UgZW50ZXIgYSBudW1iZXIgZXF1YWwgb3IgZ3JlYXRlciB0aGFuIDFgKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBuZXdJbmRleCA9IHRoaXMuX2N1cnJlbnRUb2tlbi5pbmRleCArIGNoYXJzO1xyXG5cclxuICAgIGlmIChuZXdJbmRleCA+PSB0aGlzLl90b2tlbnMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMuX2N1cnJlbnRUb2tlbi52YWx1ZSA9IHsgdHlwZTogVG9rZW5UeXBlLkVPRiB9O1xyXG4gICAgICB0aGlzLl9jdXJyZW50VG9rZW4uaW5kZXggPSAtMTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuX2N1cnJlbnRUb2tlbi5pbmRleCA9IG5ld0luZGV4O1xyXG4gICAgICB0aGlzLl9jdXJyZW50VG9rZW4udmFsdWUgPSB0aGlzLl90b2tlbnNbbmV3SW5kZXhdITtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlZWtzIGFoZWFkIGluIHRoZSB0b2tlbiBzdHJlYW0gd2l0aG91dCBhZHZhbmNpbmcgdGhlIGN1cnNvci5cclxuICAgKlxyXG4gICAqIFN1cHBvcnRzOlxyXG4gICAqIC0gU2luZ2xlLXRva2VuIGxvb2thaGVhZFxyXG4gICAqIC0gTXVsdGktdG9rZW4gbG9va2FoZWFkXHJcbiAgICogLSBPcHRpb25hbCBvZmZzZXQgZnJvbSB0aGUgY3VycmVudCB0b2tlblxyXG4gICAqXHJcbiAgICogQHJldHVybnNcclxuICAgKiAtIEEgc2luZ2xlIFRva2VuIHdoZW4gcGVla2luZyBvbmUgdG9rZW5cclxuICAgKiAtIEFuIGFycmF5IG9mIFRva2VucyB3aGVuIHBlZWtpbmcgbXVsdGlwbGUgdG9rZW5zXHJcbiAgICpcclxuICAgKiBAdGhyb3dzIEVycm9yIHdpdGggY2F1c2UgYEVPRmAgaWYgdGhlIHBlZWsgZXhjZWVkcyB0aGUgdG9rZW4gYXJyYXlcclxuICAgKi9cclxuICBwdWJsaWMgcGVlazxUIGV4dGVuZHMgVG9rZW4gPSBUb2tlbj4oKTogVDtcclxuICBwdWJsaWMgcGVlazxPZmZTZXQgZXh0ZW5kcyBudW1iZXIsIFQgZXh0ZW5kcyBUb2tlbiA9IFRva2VuPihvcHRpb25zPzogeyBvZmZzZXQ/OiBQb3NpdGl2ZUludGVnZXI8T2ZmU2V0PiB9KTogVDtcclxuICBwdWJsaWMgcGVlazxUIGV4dGVuZHMgVG9rZW4gPSBUb2tlbj4oY2hhcnM6IDEpOiBUO1xyXG4gIHB1YmxpYyBwZWVrPE9mZlNldCBleHRlbmRzIG51bWJlciwgVCBleHRlbmRzIFRva2VuID0gVG9rZW4+KGNoYXJzOiAxLCBvcHRpb25zPzogeyBvZmZzZXQ/OiBQb3NpdGl2ZUludGVnZXI8T2ZmU2V0PiB9KTogVDsgXHJcbiAgcHVibGljIHBlZWs8UmVhZENoYXJzIGV4dGVuZHMgbnVtYmVyLCBUIGV4dGVuZHMgVG9rZW4gPSBUb2tlbj4oY2hhcnM6IFBvc2l0aXZlSW50ZWdlcjxSZWFkQ2hhcnM+KTogVHVwbGVPZkxlbmd0aDxSZWFkQ2hhcnMsIFQ+OyBcclxuICBwdWJsaWMgcGVlazxSZWFkQ2hhcnMgZXh0ZW5kcyBudW1iZXIsIE9mZlNldCBleHRlbmRzIG51bWJlciwgVCBleHRlbmRzIFRva2VuID0gVG9rZW4+KGNoYXJzOiBQb3NpdGl2ZUludGVnZXI8UmVhZENoYXJzPiwgb3B0aW9ucz86IHsgb2Zmc2V0PzogUG9zaXRpdmVJbnRlZ2VyPE9mZlNldD4gfSk6IFR1cGxlT2ZMZW5ndGg8UmVhZENoYXJzLCBUPjtcclxuICBwdWJsaWMgcGVlayhjaGFyc09yT3B0aW9ucz86IG51bWJlciB8IHsgb2Zmc2V0PzogbnVtYmVyIH0sIG9wdGlvbnM/OiB7IG9mZnNldD86IG51bWJlciB9KTogVG9rZW4gfCBUb2tlbltdIHtcclxuICAgIGNvbnN0IHRva2VucyA9IHR5cGVvZiBjaGFyc09yT3B0aW9ucyA9PT0gJ251bWJlcicgPyBjaGFyc09yT3B0aW9ucyA6IDE7XHJcbiAgICBjb25zdCBvZmZzZXQgPSAodHlwZW9mIGNoYXJzT3JPcHRpb25zID09PSAnb2JqZWN0JyA/IGNoYXJzT3JPcHRpb25zIDogb3B0aW9ucyk/Lm9mZnNldCA/PyAwO1xyXG4gICAgcmV0dXJuIHRva2VucyA9PT0gMSA/IHRoaXMucGVla09uZVRva2VuKHRoaXMuX2N1cnJlbnRUb2tlbi5pbmRleCArIG9mZnNldCArIDEpIDogdGhpcy5wZWVrTWFueSh0b2tlbnMgKyBvZmZzZXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVla3MgbXVsdGlwbGUgdG9rZW5zIGFoZWFkLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcGVla01hbnkoY2hhcnM6IG51bWJlcik6IFRva2VuW10ge1xyXG4gICAgY29uc3QgcGVla2VkVG9rZW5zID0gbmV3IEFycmF5PFRva2VuPjtcclxuICAgIGNvbnN0IG5leHRUb2tlbkluZGV4ID0gdGhpcy5fY3VycmVudFRva2VuLmluZGV4ICsgMTtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gbmV4dFRva2VuSW5kZXg7IGkgPCBuZXh0VG9rZW5JbmRleCArIGNoYXJzOyBpKyspIHtcclxuICAgICAgcGVla2VkVG9rZW5zLnB1c2godGhpcy5wZWVrT25lVG9rZW4oaSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBwZWVrZWRUb2tlbnM7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZWVrcyBhIHNpbmdsZSB0b2tlbiBhdCB0aGUgZ2l2ZW4gYWJzb2x1dGUgaW5kZXguXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwZWVrT25lVG9rZW4oaW5kZXg6IG51bWJlcik6IFRva2VuIHtcclxuICAgIHJldHVybiBpbmRleCA8IHRoaXMuX3Rva2Vucy5sZW5ndGggPyB0aGlzLl90b2tlbnNbaW5kZXhdISA6IHsgdHlwZTogVG9rZW5UeXBlLkVPRiB9O1xyXG4gIH1cclxufVxyXG4iLCIvKipcclxuICogRGlzY3JpbWluYW50IHZhbHVlcyB0aGF0IGlkZW50aWZ5IHRoZSB0eXBlIG9mIGVhY2ggQVNUIG5vZGUgcHJvZHVjZWQgYnkgdGhlIHBhcnNlci5cclxuICovXHJcbmV4cG9ydCBlbnVtIEFTVE5vZGVUeXBlIHtcclxuICAvKipcclxuICAgKiBBbiBIVE1MIGVsZW1lbnQgbm9kZSB3aXRoIGEgdGFnIG5hbWUsIGF0dHJpYnV0ZXMsIGV2ZW50cywgYW5kIGNoaWxkcmVuLlxyXG4gICAqL1xyXG4gIEVsZW1lbnQsXHJcbiAgLyoqXHJcbiAgICogQSBwbGFpbiB0ZXh0IG5vZGUuXHJcbiAgICovXHJcbiAgVGV4dCxcclxuICAvKipcclxuICAgKiBBbiBpbmxpbmUgaW50ZXJwb2xhdGlvbiBleHByZXNzaW9uIG9yIGxpdGVyYWwuXHJcbiAgICovXHJcbiAgSW50ZXJwb2xhdGlvbixcclxuICAvKipcclxuICAgKiBBbiBgQGlmYCBjb25kaXRpb25hbCBub2RlLlxyXG4gICAqL1xyXG4gIElmLFxyXG4gIC8qKlxyXG4gICAqIEFuIGBAZWxzZWAgYnJhbmNoIG5vZGUgYXR0YWNoZWQgdG8gYW4gYEBpZmAuXHJcbiAgICovXHJcbiAgRWxzZSxcclxuICAvKipcclxuICAgKiBBbiBgQGVsc2UgaWZgIGJyYW5jaCBub2RlIGF0dGFjaGVkIHRvIGFuIGBAaWZgLlxyXG4gICAqL1xyXG4gIEVsc2VJZixcclxuICAvKipcclxuICAgKiBBbiBgQGZvcmAgaXRlcmF0aW9uIG5vZGUuXHJcbiAgICovXHJcbiAgRm9yLFxyXG4gIC8qKlxyXG4gICAqIEFuIGBAc3dpdGNoYCBub2RlIGNvbnRhaW5pbmcgb25lIG9yIG1vcmUgY2FzZSBub2Rlcy5cclxuICAgKi9cclxuICBTd2l0Y2gsXHJcbiAgLyoqXHJcbiAgICogQSBgQGNhc2VgIG9yIGBAZGVmYXVsdGAgYnJhbmNoIGluc2lkZSBhIGBAc3dpdGNoYC5cclxuICAgKi9cclxuICBDYXNlLFxyXG4gIC8qKlxyXG4gICAqIEEgYEBjb25zdGAgZGVjbGFyYXRpb24gbm9kZS5cclxuICAgKi9cclxuICBDb25zdERlY2xhcmF0aW9uXHJcbn0iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgQ29uc3REZWNsYXJhdGlvblRva2VuIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW5zL2NvbnN0LWRlY2xhcmF0aW9uLXRva2VuLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBQYXJzZXJDdXJzb3IgfSBmcm9tICcuLi9tb2RlbHMvcGFyc2VyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tICcuLi90eXBlcy9hc3QudHlwZS5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgQ29uc3REZWNsYXJhdGlvbk5vZGUgfSBmcm9tICcuLi90eXBlcy9ub2Rlcy9jb25zdC1kZWNsYXJhdGlvbi1ub2RlLnR5cGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIFBhcnNlcyBhIENPTlNUX0RFQ0xBUkFUSU9OIHRva2VuIGludG8gYSBgQ29uc3REZWNsYXJhdGlvbk5vZGVgLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFBhcnNlciBjdXJzb3I7IGFkdmFuY2VkIHBhc3QgdGhlIENPTlNUX0RFQ0xBUkFUSU9OIHRva2VuLlxyXG4gKiBAcGFyYW0gX3BhcnNlTm9kZSBVbnVzZWQgcGFyc2VyIGZ1bmN0aW9uLlxyXG4gKiBAcGFyYW0gdG9rZW4gVGhlIENPTlNUX0RFQ0xBUkFUSU9OIHRva2VuIGNvbnRhaW5pbmcgdmFyaWFibGUgbmFtZSBhbmQgZXhwcmVzc2lvbi5cclxuICogQHJldHVybnMgVGhlIHBhcnNlZCBgQ29uc3REZWNsYXJhdGlvbk5vZGVgLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ29uc3REZWNsYXJhdGlvbihjdXJzb3I6IFBhcnNlckN1cnNvciwgX3BhcnNlTm9kZTogTm9BcmdzRnVuY3Rpb248QVNUTm9kZSB8IHVuZGVmaW5lZD4sIHRva2VuOiBDb25zdERlY2xhcmF0aW9uVG9rZW4pOiBDb25zdERlY2xhcmF0aW9uTm9kZSB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHR5cGU6IEFTVE5vZGVUeXBlLkNvbnN0RGVjbGFyYXRpb24sXHJcbiAgICB2YXJOYW1lOiB0b2tlbi5wYXJ0c1swXSxcclxuICAgIGV4cHJlc3Npb246IHRva2VuLnBhcnRzWzFdXHJcbiAgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgSW50ZXJwb2xhdGlvbkV4cHJlc3Npb25Ub2tlbiB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2Vucy9pbnRlcnBvbGF0aW9uLWV4cHJlc3Npb24tdG9rZW4udHlwZS5qcyc7XHJcbmltcG9ydCB7IEludGVycG9sYXRpb25MaXRlcmFsVG9rZW4gfSBmcm9tICcuLi8uLi9sZXhlci90eXBlcy90b2tlbnMvaW50ZXJwb2xhdGlvbi1saXRlcmFsLXRva2VuLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBQYXJzZXJDdXJzb3IgfSBmcm9tICcuLi9tb2RlbHMvcGFyc2VyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tICcuLi90eXBlcy9hc3QudHlwZS5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgSW50ZXJwb2xhdGlvbk5vZGUgfSBmcm9tICcuLi90eXBlcy9ub2Rlcy9pbnRlcnBvbGF0aW9uLW5vZGUudHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogUGFyc2VzIGFuIGludGVycG9sYXRpb24gZXhwcmVzc2lvbiBvciBsaXRlcmFsIHRva2VuIGludG8gYW4gYEludGVycG9sYXRpb25Ob2RlYC5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBQYXJzZXIgY3Vyc29yOyBhZHZhbmNlZCBwYXN0IHRoZSBpbnRlcnBvbGF0aW9uIHRva2VuLlxyXG4gKiBAcGFyYW0gX3BhcnNlTm9kZSBVbnVzZWQgcGFyc2VyIGZ1bmN0aW9uLlxyXG4gKiBAcGFyYW0gdG9rZW4gVGhlIElOVEVSUE9MQVRJT05fRVhQUkVTU0lPTiBvciBJTlRFUlBPTEFUSU9OX0xJVEVSQUwgdG9rZW4uXHJcbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgYEludGVycG9sYXRpb25Ob2RlYC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUludGVycG9sYXRpb24oY3Vyc29yOiBQYXJzZXJDdXJzb3IsIF9wYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+LCB0b2tlbjogSW50ZXJwb2xhdGlvbkV4cHJlc3Npb25Ub2tlbiB8IEludGVycG9sYXRpb25MaXRlcmFsVG9rZW4pOiBJbnRlcnBvbGF0aW9uTm9kZSB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICBcclxuICByZXR1cm4ge1xyXG4gICAgdHlwZTogQVNUTm9kZVR5cGUuSW50ZXJwb2xhdGlvbixcclxuICAgIGV4cHJlc3Npb246IHRva2VuLnBhcnRzWzBdXHJcbiAgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgQXR0cmlidXRlVG9rZW4gfSBmcm9tICcuLi8uLi9sZXhlci90eXBlcy90b2tlbnMvYXR0cmlidXRlLXRva2VuLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBQYXJzZXJDdXJzb3IgfSBmcm9tICcuLi9tb2RlbHMvcGFyc2VyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tICcuLi90eXBlcy9hc3QudHlwZS5qcyc7XHJcbmltcG9ydCB7IEF0dHJpYnV0ZU5vZGUgfSBmcm9tICcuLi90eXBlcy9ub2Rlcy9hdHRyaWJ1dGUtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgcGFyc2VJbnRlcnBvbGF0aW9uIH0gZnJvbSAnLi9wYXJzZS1pbnRlcnBvbGF0aW9uLnN0YXRlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBQYXJzZXMgYW4gQVRUUklCVVRFIHRva2VuIGludG8gYW4gYEF0dHJpYnV0ZU5vZGVgLlxyXG4gKiBIYW5kbGVzIGJvb2xlYW4gYXR0cmlidXRlcyAobm8gYD1gKSwgc3RyaW5nIHZhbHVlcywgYW5kIGludGVycG9sYXRpb24gdmFsdWVzLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFBhcnNlciBjdXJzb3I7IGFkdmFuY2VkIHBhc3QgdGhlIEFUVFJJQlVURSB0b2tlbi5cclxuICogQHBhcmFtIHBhcnNlTm9kZSBQYXJzZXIgbm9kZSBmdW5jdGlvbiBmb3IgcmVjdXJzaXZlIHBhcnNpbmcuXHJcbiAqIEBwYXJhbSB0b2tlbiBUaGUgQVRUUklCVVRFIHRva2VuIHRvIHBhcnNlLlxyXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIGBBdHRyaWJ1dGVOb2RlYC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUF0dHJpYnV0ZShjdXJzb3I6IFBhcnNlckN1cnNvciwgcGFyc2VOb2RlOiBOb0FyZ3NGdW5jdGlvbjxBU1ROb2RlIHwgdW5kZWZpbmVkPiwgdG9rZW46IEF0dHJpYnV0ZVRva2VuKTogQXR0cmlidXRlTm9kZSB7XHJcbiAgLy8gY29uc3VtZSBBVFRSSUJVVEUgdG9rZW5cclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gIGNvbnN0IHJhdyA9IHRva2VuLnBhcnRzWzBdO1xyXG5cclxuICBpZiAoIXJhdy5pbmNsdWRlcygnPScpKSB7XHJcbiAgICByZXR1cm4geyBuYW1lOiByYXcsIHZhbHVlOiAndHJ1ZScgfTtcclxuICB9XHJcblxyXG4gIGNvbnN0IFtuYW1lLCB2YWx1ZV0gPSByYXcuc3BsaXQoJz0nKTtcclxuICBpZiAoIW5hbWUpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgW1BhcnNlcl0gQXR0cmlidXRlIG5hbWUgbWlzc2luZyBpbjogJHtyYXd9YCk7XHJcbiAgfVxyXG5cclxuICBjb25zdCBuZXh0VG9rZW4gPSBjdXJzb3IucGVlaygpO1xyXG4gIGlmIChuZXh0VG9rZW4udHlwZSA9PT0gVG9rZW5UeXBlLklOVEVSUE9MQVRJT05fRVhQUkVTU0lPTiB8fCBuZXh0VG9rZW4udHlwZSA9PT0gVG9rZW5UeXBlLklOVEVSUE9MQVRJT05fTElURVJBTCkge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgbmFtZSxcclxuICAgICAgdmFsdWU6IHBhcnNlSW50ZXJwb2xhdGlvbihjdXJzb3IsIHBhcnNlTm9kZSwgbmV4dFRva2VuKVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGlmICghdmFsdWUpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgW1BhcnNlcl0gQXR0cmlidXRlIHZhbHVlIG1pc3NpbmcgZm9yICR7bmFtZX0gaW46ICR7cmF3fWApO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIG5hbWUsXHJcbiAgICB2YWx1ZTogdmFsdWUucmVwbGFjZSgvXlsnJ118WycnXSQvZywgJycpXHJcbiAgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgRXZlbnRUb2tlbiB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2Vucy9ldmVudC10b2tlbi50eXBlLmpzJztcclxuaW1wb3J0IHsgUGFyc2VyQ3Vyc29yIH0gZnJvbSAnLi4vbW9kZWxzL3BhcnNlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBBU1ROb2RlIH0gZnJvbSAnLi4vdHlwZXMvYXN0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBFdmVudE5vZGUgfSBmcm9tICcuLi90eXBlcy9ub2Rlcy9ldmVudC1ub2RlLnR5cGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIFBhcnNlcyBhbiBFVkVOVCB0b2tlbiBpbnRvIGFuIGBFdmVudE5vZGVgIGJ5IHNwbGl0dGluZyB0aGUgcmF3XHJcbiAqIGBldmVudE5hbWU9aGFuZGxlcmAgc3RyaW5nLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFBhcnNlciBjdXJzb3I7IGFkdmFuY2VkIHBhc3QgdGhlIEVWRU5UIHRva2VuLlxyXG4gKiBAcGFyYW0gX3BhcnNlTm9kZSBVbnVzZWQgcGFyc2VyIGZ1bmN0aW9uLlxyXG4gKiBAcGFyYW0gdG9rZW4gVGhlIEVWRU5UIHRva2VuIHRvIHBhcnNlLlxyXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIGBFdmVudE5vZGVgLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRXZlbnQoY3Vyc29yOiBQYXJzZXJDdXJzb3IsIF9wYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+LCB0b2tlbjogRXZlbnRUb2tlbik6IEV2ZW50Tm9kZSB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICBjb25zdCByYXcgPSB0b2tlbi5wYXJ0c1swXTtcclxuICBjb25zdCBbbmFtZSwgdmFsdWVdID0gcmF3LnNwbGl0KCc9Jyk7XHJcblxyXG4gIGlmICghbmFtZSB8fCAhdmFsdWUpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihgW1BhcnNlcl0gSW52YWxpZCBldmVudCBmb3JtYXQ6ICR7cmF3fWApO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIG5hbWUsXHJcbiAgICBoYW5kbGVyOiB2YWx1ZS5yZXBsYWNlKC9eW1wiXCJdfFtcIlwiXSQvZywgJycpXHJcbiAgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgVGFnT3Blbk5hbWVUb2tlbiB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2Vucy90YWctb3Blbi1uYW1lLXRva2VuLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBQYXJzZXJDdXJzb3IgfSBmcm9tICcuLi9tb2RlbHMvcGFyc2VyLWN1cnNvci5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tICcuLi90eXBlcy9hc3QudHlwZS5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgQXR0cmlidXRlTm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2F0dHJpYnV0ZS1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBFbGVtZW50Tm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2VsZW1lbnQtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgRXZlbnROb2RlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZXMvZXZlbnQtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgcGFyc2VBdHRyaWJ1dGUgfSBmcm9tICcuL3BhcnNlLWF0dHJpYnV0ZS5zdGF0ZS5qcyc7XHJcbmltcG9ydCB7IHBhcnNlRXZlbnQgfSBmcm9tICcuL3BhcnNlLWV2ZW50LnN0YXRlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBQYXJzZXMgYSBUQUdfT1BFTl9OQU1FIHRva2VuIGFuZCB0aGUgc3Vic2VxdWVudCBhdHRyaWJ1dGVzLCBldmVudHMsIGFuZCBjaGlsZHJlblxyXG4gKiBpbnRvIGFuIGBFbGVtZW50Tm9kZWAuIEhhbmRsZXMgYm90aCByZWd1bGFyIGFuZCBzZWxmLWNsb3NpbmcgdGFncy5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBQYXJzZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIFRBR19PUEVOX05BTUUgdG9rZW4uXHJcbiAqIEBwYXJhbSBjb250ZXh0IFBhcnNlciBjb250ZXh0IGZvciByZWN1cnNpdmUgY2hpbGQgcGFyc2luZy5cclxuICogQHBhcmFtIHRva2VuIFRoZSBUQUdfT1BFTl9OQU1FIHRva2VuIGNvbnRhaW5pbmcgdGhlIHRhZyBuYW1lLlxyXG4gKiBAcmV0dXJucyBUaGUgcGFyc2VkIGBFbGVtZW50Tm9kZWAuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VFbGVtZW50KGN1cnNvcjogUGFyc2VyQ3Vyc29yLCBwYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+LCB0b2tlbjogVGFnT3Blbk5hbWVUb2tlbik6IEVsZW1lbnROb2RlIHtcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG4gIGNvbnN0IHRhZ05hbWUgPSB0b2tlbi5wYXJ0c1swXTtcclxuXHJcbiAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBBcnJheTxBdHRyaWJ1dGVOb2RlPigpO1xyXG4gIGNvbnN0IGV2ZW50cyA9IG5ldyBBcnJheTxFdmVudE5vZGU+KCk7XHJcblxyXG4gIGxldCByZWFkID0gdHJ1ZTtcclxuICB3aGlsZSAocmVhZCkge1xyXG4gICAgY29uc3QgdG9rZW4gPSBjdXJzb3IucGVlaygpO1xyXG4gICAgc3dpdGNoICh0b2tlbi50eXBlKSB7XHJcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkFUVFJJQlVURTpcclxuICAgICAgICBhdHRyaWJ1dGVzLnB1c2gocGFyc2VBdHRyaWJ1dGUoY3Vyc29yLCBwYXJzZU5vZGUsIHRva2VuKSk7XHJcbiAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICBjYXNlIFRva2VuVHlwZS5FVkVOVDpcclxuICAgICAgICBldmVudHMucHVzaChwYXJzZUV2ZW50KGN1cnNvciwgcGFyc2VOb2RlLCB0b2tlbikpO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICByZWFkID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBDb25zdW1lIFRBR19PUEVOX0VORCBpZiBwcmVzZW50OiA8ZGl2PlxyXG4gIGlmIChjdXJzb3IucGVlaygpLnR5cGUgPT09IFRva2VuVHlwZS5UQUdfT1BFTl9FTkQpIHtcclxuICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgfVxyXG5cclxuICAvLyBIYW5kbGUgc2VsZi1jbG9zaW5nIHRhZ3M6IDxkaXYgLz5cclxuICBpZiAoY3Vyc29yLnBlZWsoKS50eXBlID09PSBUb2tlblR5cGUuVEFHX1NFTEZfQ0xPU0UpIHtcclxuICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICB0eXBlOiBBU1ROb2RlVHlwZS5FbGVtZW50LFxyXG4gICAgICB0YWdOYW1lLFxyXG4gICAgICBhdHRyaWJ1dGVzLFxyXG4gICAgICBldmVudHMsXHJcbiAgICAgIGNoaWxkcmVuOiBbXVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vIFBhcnNlIGNoaWxkcmVuIHJlY3Vyc2l2ZWx5IHVudGlsIGNsb3NpbmcgdGFnXHJcbiAgY29uc3QgY2hpbGRyZW4gPSBuZXcgQXJyYXk8QVNUTm9kZT47XHJcbiAgd2hpbGUgKCFpc1RhZ0Nsb3NlKGN1cnNvciwgdGFnTmFtZSkpIHtcclxuICAgIGNvbnN0IGNoaWxkID0gcGFyc2VOb2RlKCk7XHJcbiAgICBpZiAoY2hpbGQpIHtcclxuICAgICAgY2hpbGRyZW4ucHVzaChjaGlsZCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBDb25zdW1lIGNsb3NpbmcgdGFnIDwvZGl2PlxyXG4gIGN1cnNvci5hZHZhbmNlKCk7XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICB0eXBlOiBBU1ROb2RlVHlwZS5FbGVtZW50LFxyXG4gICAgdGFnTmFtZSxcclxuICAgIGF0dHJpYnV0ZXMsXHJcbiAgICBldmVudHMsXHJcbiAgICBjaGlsZHJlblxyXG4gIH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgbmV4dCB0b2tlbiBpbiB0aGUgc3RyZWFtIGlzIGEgY2xvc2luZyB0YWcgZm9yIHRoZSBnaXZlbiB0YWcgbmFtZS5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBQYXJzZXIgY3Vyc29yIHRvIHBlZWsgZnJvbS5cclxuICogQHBhcmFtIHRhZ05hbWUgVGhlIGV4cGVjdGVkIHRhZyBuYW1lIHRvIG1hdGNoLlxyXG4gKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG5leHQgdG9rZW4gaXMgVEFHX0NMT1NFX05BTUUgbWF0Y2hpbmcgYHRhZ05hbWVgLlxyXG4gKi9cclxuZnVuY3Rpb24gaXNUYWdDbG9zZShjdXJzb3I6IFBhcnNlckN1cnNvciwgdGFnTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgY29uc3QgbmV4dFRva2VuID0gY3Vyc29yLnBlZWsoKTtcclxuICByZXR1cm4gbmV4dFRva2VuLnR5cGUgPT09IFRva2VuVHlwZS5UQUdfQ0xPU0VfTkFNRSAmJiBuZXh0VG9rZW4ucGFydHNbMF0gPT09IHRhZ05hbWU7XHJcbn1cclxuIiwiaW1wb3J0IHRzLCB7IERpYWdub3N0aWMgfSBmcm9tICd0eXBlc2NyaXB0JztcclxuaW1wb3J0IHsgRXhwcmVzc2lvblZhbGlkYXRpb25SZXN1bHQgfSBmcm9tICcuLi90eXBlcy9leHByZXNzaW9uLXZhbGlkYXRpb24tcmVzdWx0LnR5cGUnO1xyXG5pbXBvcnQgeyBFeHByZXNzaW9uRGlhZ25vc3RpYyB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2V4cHJlc3Npb24tZGlhbmdub3N0aWMudHlwZSc7XHJcblxyXG4vKipcclxuICogVmFsaWRhdGVzIHRoYXQgYSBzdHJpbmcgY29udGFpbnMgYSBzaW5nbGUgZXhwcmVzc2lvbiBiZWxvbmdpbmcgdG8gdGhlXHJcbiAqIHBlcm1pdHRlZCBzdWJzZXQgb2YgSmF2YVNjcmlwdCBzdXBwb3J0ZWQgaW5zaWRlIFhhZW5kYXIgdGVtcGxhdGUgZXhwcmVzc2lvbnMuXHJcbiAqXHJcbiAqICMjIFBlcm1pdHRlZCBjb25zdHJ1Y3RzXHJcbiAqXHJcbiAqIC0gKipMaXRlcmFscyoqIOKAlCBzdHJpbmdzLCBudW1iZXJzLCBiaWdpbnRzLCBib29sZWFucywgYG51bGxgLCBgdW5kZWZpbmVkYFxyXG4gKiAtICoqSWRlbnRpZmllcnMqKiDigJQgcmVzb2x2ZWQgYXQgcnVudGltZSBhZ2FpbnN0IHRoZSBhY3RpdmUgc2NvcGUgY2hhaW5cclxuICogLSAqKk1lbWJlciBhY2Nlc3MqKiDigJQgYHVzZXIubmFtZWAsIGB1c2VyLmFkZHJlc3MuY2l0eWAsIGBpdGVtc1swXWBcclxuICogLSAqKkNhbGwgZXhwcmVzc2lvbnMqKiDigJQgYHVzZXIuZ2V0RnVsbE5hbWUoKWAsIGB1c2VyLmhhc1JvbGUoJ2FkbWluJylgXHJcbiAqIC0gKipCaW5hcnkgZXhwcmVzc2lvbnMqKiDigJQgYXJpdGhtZXRpYyAoYCtgLCBgLWAsIGAqYCwgYC9gLCBgJWAsIGAqKmApLFxyXG4gKiAgIGNvbXBhcmlzb24gKGA9PT1gLCBgIT09YCwgYDxgLCBgPmAsIGA8PWAsIGA+PWApLFxyXG4gKiAgIGxvZ2ljYWwgKGAmJmAsIGB8fGAsIGA/P2ApLFxyXG4gKiAgIGJpdHdpc2UgKGAmYCwgYHxgLCBgXmAsIGA8PGAsIGA+PmAsIGA+Pj5gKVxyXG4gKiAtICoqVW5hcnkgZXhwcmVzc2lvbnMqKiDigJQgYCFgLCBgfmAsIGArYCwgYC1gLCBgdHlwZW9mYCwgYHZvaWRgXHJcbiAqIC0gKipDb25kaXRpb25hbCAodGVybmFyeSkqKiDigJQgYGlzQWRtaW4gPyAneWVzJyA6ICdubydgXHJcbiAqIC0gKipQYXJlbnRoZXNpc2VkIGV4cHJlc3Npb25zKiog4oCUIGAodXNlci5hZ2UgPiAxOClgXHJcbiAqIC0gKipUZW1wbGF0ZSBsaXRlcmFscyoqIOKAlCBgYCBgSGVsbG8gJHt1c2VyLm5hbWV9YCBgYFxyXG4gKiAtICoqQXJyYXkgbGl0ZXJhbHMqKiDigJQgYFsxLCAyLCAzXWAsIGBbLi4uaXRlbXNdYFxyXG4gKiAtICoqT2JqZWN0IGxpdGVyYWxzKiog4oCUIGB7IGtleTogdmFsdWUgfWAsIGB7IC4uLmRlZmF1bHRzLCBuYW1lIH1gXHJcbiAqIC0gKipTcHJlYWQqKiDigJQgYGZvbyguLi5hcmdzKWAsIGBbLi4uaXRlbXNdYCwgYHsgLi4ub2JqIH1gXHJcbiAqIC0gKipgdHlwZW9mYCAvIGBpbnN0YW5jZW9mYCoqIOKAlCBgdHlwZW9mIHVzZXIucm9sZWAsIGB1c2VyIGluc3RhbmNlb2YgQWRtaW5Vc2VyYFxyXG4gKlxyXG4gKiAjIyBQcm9oaWJpdGVkIGNvbnN0cnVjdHNcclxuICpcclxuICogLSBBc3NpZ25tZW50cyAoYD1gLCBgKz1gLCBgJiY9YCwgZXRjLikg4oCUIHVzZSBgQGNvbnN0YCBmb3IgbG9jYWwgYmluZGluZ3NcclxuICogLSBgYXdhaXRgIGFuZCBgeWllbGRgXHJcbiAqIC0gYG5ld2AgZXhwcmVzc2lvbnNcclxuICogLSBGdW5jdGlvbiBhbmQgYXJyb3cgZnVuY3Rpb24gZXhwcmVzc2lvbnNcclxuICogLSBUYWdnZWQgdGVtcGxhdGUgZXhwcmVzc2lvbnNcclxuICpcclxuICogIyMgU2NvcGUgcmVzb2x1dGlvblxyXG4gKlxyXG4gKiBUaGlzIGZ1bmN0aW9uIHBlcmZvcm1zICoqc3ludGFjdGljKiogdmFsaWRhdGlvbiBvbmx5LiBJZGVudGlmaWVyIHJlc29sdXRpb25cclxuICogKHNjb3BlIGNoYWluIHdhbGsg4oaSIGBjdHguYCBwcmVmaXggaW5qZWN0aW9uKSBpcyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgdGhlXHJcbiAqIGNhbGxlciBhbmQgbXVzdCBiZSBwZXJmb3JtZWQgb24gdGhlIHJldHVybmVkIGBub2RlYCBhZnRlciB0aGlzIGZ1bmN0aW9uXHJcbiAqIHJlcG9ydHMgbm8gZGlhZ25vc3RpY3MuXHJcbiAqXHJcbiAqIEBwYXJhbSBzb3VyY2UgLSBUaGUgcmF3IGV4cHJlc3Npb24gc3RyaW5nIGV4dHJhY3RlZCBmcm9tIHRoZSB0ZW1wbGF0ZS5cclxuICogQHJldHVybnMgQSB7QGxpbmsgRXhwcmVzc2lvblZhbGlkYXRpb25SZXN1bHR9IGNvbnRhaW5pbmcgdGhlIHBhcnNlZCBBU1Qgbm9kZVxyXG4gKiAgICh3aGVuIHZhbGlkKSBhbmQgYW55IGRpYWdub3N0aWNzIHByb2R1Y2VkIGR1cmluZyB2YWxpZGF0aW9uLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiBjb25zdCByZXN1bHQgPSB2YWxpZGF0ZUV4cHJlc3Npb24oJ3VzZXIuaGFzUm9sZShcImFkbWluXCIpICYmIGlzVmVyaWZpZWQnKTtcclxuICogaWYgKHJlc3VsdC5kaWFnbm9zdGljcy5sZW5ndGggPT09IDApIHtcclxuICogICAvLyByZXN1bHQubm9kZSBpcyBzYWZlIHRvIHVzZVxyXG4gKiB9XHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGNvbnN0IHJlc3VsdCA9IHZhbGlkYXRlRXhwcmVzc2lvbignYXdhaXQgdXNlci5sb2FkKCknKTtcclxuICogLy8gcmVzdWx0LmRpYWdub3N0aWNzWzBdLm1lc3NhZ2Ug4oaSXHJcbiAqIC8vICAgXCInYXdhaXQnIGlzIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy5cIlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRXhwcmVzc2lvbihzb3VyY2U6IHN0cmluZyk6IEV4cHJlc3Npb25WYWxpZGF0aW9uUmVzdWx0IHtcclxuICBjb25zdCBwcmVmaXggPSAnY29uc3QgeCA9ICc7XHJcbiAgY29uc3Qgc291cmNlRmlsZSA9IHRzLmNyZWF0ZVNvdXJjZUZpbGUoJ2V4cHJlc3Npb24udHMnLCBgJHtwcmVmaXh9JHtzb3VyY2V9YCwgdHMuU2NyaXB0VGFyZ2V0LkVTTmV4dCwgdHJ1ZSk7XHJcblxyXG4gIGNvbnN0IHN0YXRlbWVudCA9IHNvdXJjZUZpbGUuc3RhdGVtZW50c1swXSBhcyB0cy5WYXJpYWJsZVN0YXRlbWVudDtcclxuICBjb25zdCBleHByZXNzaW9uID0gc3RhdGVtZW50LmRlY2xhcmF0aW9uTGlzdC5kZWNsYXJhdGlvbnNbMF0hLmluaXRpYWxpemVyITtcclxuXHJcbiAgY29uc3QgZGlhZ25vc3RpY3MgPSBuZXcgQXJyYXk8RXhwcmVzc2lvbkRpYWdub3N0aWM+O1xyXG4gIHZpc2l0Tm9kZShleHByZXNzaW9uLCBwcmVmaXgubGVuZ3RoLCBkaWFnbm9zdGljcyk7XHJcblxyXG4gIGlmIChkaWFnbm9zdGljcy5sZW5ndGgpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihkaWFnbm9zdGljcy5yZWR1Y2UoKGFjYywgZCkgPT4gYCR7YWNjfSR7ZC5tZXNzYWdlfVxcbmAsICcnKSk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgbm9kZTogZXhwcmVzc2lvbixcclxuICB9O1xyXG59XHJcblxyXG4vKipcclxuICogUmVjdXJzaXZlbHkgdmlzaXRzIGFuIEFTVCBub2RlIGFuZCBhcHBlbmRzIGEgZGlhZ25vc3RpYyBmb3IgZXZlcnkgbm9kZVxyXG4gKiBraW5kIHRoYXQgaXMgbm90IHBhcnQgb2YgdGhlIHBlcm1pdHRlZCBleHByZXNzaW9uIHN1YnNldC5cclxuICpcclxuICogUmVjdXJzaW9uIHN0b3BzIGF0IHRoZSBmaXJzdCBkaXNhbGxvd2VkIG5vZGUgdG8gYXZvaWQgcHJvZHVjaW5nIGEgY2FzY2FkZVxyXG4gKiBvZiByZWR1bmRhbnQgZGlhZ25vc3RpY3MgZm9yIGl0cyBjaGlsZHJlbi5cclxuICpcclxuICogQHBhcmFtIG5vZGUgLSBUaGUgQVNUIG5vZGUgdG8gaW5zcGVjdC5cclxuICogQHBhcmFtIG9mZnNldCAtIE51bWJlciBvZiBjaGFyYWN0ZXJzIHRvIHN1YnRyYWN0IGZyb20gcmF3IG5vZGUgcG9zaXRpb25zXHJcbiAqICAgdG8gb2J0YWluIG9mZnNldHMgcmVsYXRpdmUgdG8gdGhlIG9yaWdpbmFsIGV4cHJlc3Npb24gc3RyaW5nLlxyXG4gKiBAcGFyYW0gZGlhZ25vc3RpY3MgLSBBY2N1bXVsYXRvciBmb3IgZGlhZ25vc3RpY3MgZm91bmQgZHVyaW5nIHRoZSB3YWxrLlxyXG4gKi9cclxuZnVuY3Rpb24gdmlzaXROb2RlKG5vZGU6IHRzLk5vZGUsIG9mZnNldDogbnVtYmVyLCBkaWFnbm9zdGljczogRXhwcmVzc2lvbkRpYWdub3N0aWNbXSk6IHZvaWQge1xyXG4gIGlmICghaXNBbGxvd2VkTm9kZShub2RlKSkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGJ1aWxkRGlzYWxsb3dlZE1lc3NhZ2Uobm9kZSkpO1xyXG4gIH1cclxuXHJcbiAgdHMuZm9yRWFjaENoaWxkKG5vZGUsIGNoaWxkID0+IHZpc2l0Tm9kZShjaGlsZCwgb2Zmc2V0LCBkaWFnbm9zdGljcykpO1xyXG5cclxuICBpZiAoZGlhZ25vc3RpY3MubGVuZ3RoKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoZGlhZ25vc3RpY3NbMF0hLm1lc3NhZ2UpO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBBU1Qgbm9kZSBraW5kIGlzIHBlcm1pdHRlZCBpbnNpZGUgYVxyXG4gKiBYYWVuZGFyIHRlbXBsYXRlIGV4cHJlc3Npb24uXHJcbiAqXHJcbiAqIEFzc2lnbm1lbnQgb3BlcmF0b3JzIG5lc3RlZCBpbnNpZGUgYSBgQmluYXJ5RXhwcmVzc2lvbmAgYXJlIGhhbmRsZWRcclxuICogc2VwYXJhdGVseSBpbiB7QGxpbmsgYnVpbGREaXNhbGxvd2VkTWVzc2FnZX0gc2luY2UgVHlwZVNjcmlwdCBkb2VzIG5vdFxyXG4gKiBkaXN0aW5ndWlzaCB0aGVtIGF0IHRoZSBub2RlLWtpbmQgbGV2ZWwuXHJcbiAqL1xyXG5mdW5jdGlvbiBpc0FsbG93ZWROb2RlKG5vZGU6IHRzLk5vZGUpOiBib29sZWFuIHtcclxuICBzd2l0Y2ggKG5vZGUua2luZCkge1xyXG4gICAgLy8gLS0tLSBMaXRlcmFscyAtLS0tXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuU3RyaW5nTGl0ZXJhbDpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5OdW1lcmljTGl0ZXJhbDpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5CaWdJbnRMaXRlcmFsOlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlRydWVLZXl3b3JkOlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkZhbHNlS2V5d29yZDpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5OdWxsS2V5d29yZDpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5VbmRlZmluZWRLZXl3b3JkOlxyXG5cclxuICAgIC8vIC0tLS0gSWRlbnRpZmllcnMgLS0tLVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLklkZW50aWZpZXI6XHJcblxyXG4gICAgLy8gLS0tLSBNZW1iZXIgYWNjZXNzIC0tLS1cclxuICAgIC8vIHVzZXIubmFtZVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbjpcclxuICAgIC8vIHVzZXJbJ25hbWUnXSwgaXRlbXNbMF1cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5FbGVtZW50QWNjZXNzRXhwcmVzc2lvbjpcclxuXHJcbiAgICAvLyAtLS0tIENhbGwgZXhwcmVzc2lvbnMgLS0tLVxyXG4gICAgLy8gdXNlci5nZXRGdWxsTmFtZSgpLCB1c2VyLmhhc1JvbGUoJ2FkbWluJylcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5DYWxsRXhwcmVzc2lvbjpcclxuXHJcbiAgICAvLyAtLS0tIEJpbmFyeSBleHByZXNzaW9ucyAtLS0tXHJcbiAgICAvLyBDb3ZlcnMgYXJpdGhtZXRpYywgY29tcGFyaXNvbiwgbG9naWNhbCwgYml0d2lzZSwgbnVsbGlzaCBjb2FsZXNjaW5nLFxyXG4gICAgLy8gYW5kIGluc3RhbmNlb2YuIEFzc2lnbm1lbnQgb3BlcmF0b3JzIGFyZSByZWplY3RlZCBpbiB2aXNpdE5vZGUgdmlhXHJcbiAgICAvLyBidWlsZERpc2FsbG93ZWRNZXNzYWdlIGJlZm9yZSByZWN1cnNpbmcgaW50byBjaGlsZHJlbi5cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5CaW5hcnlFeHByZXNzaW9uOlxyXG5cclxuICAgIC8vIC0tLS0gT3BlcmF0b3IgdG9rZW5zIOKAlCB2aXNpdGVkIGFzIGNoaWxkcmVuIG9mIEJpbmFyeUV4cHJlc3Npb24gLS0tLVxyXG4gICAgLy8gQ29tcGFyaXNvblxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkVxdWFsc0VxdWFsc1Rva2VuOiAgICAgICAgICAgIC8vID09XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuRXF1YWxzRXF1YWxzRXF1YWxzVG9rZW46ICAgICAgIC8vID09PVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkV4Y2xhbWF0aW9uRXF1YWxzVG9rZW46ICAgICAgICAvLyAhPVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkV4Y2xhbWF0aW9uRXF1YWxzRXF1YWxzVG9rZW46ICAvLyAhPT1cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5MZXNzVGhhblRva2VuOiAgICAgICAgICAgICAgICAgLy8gXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuTGVzc1RoYW5FcXVhbHNUb2tlbjogICAgICAgICAgIC8vIDw9XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuR3JlYXRlclRoYW5Ub2tlbjogICAgICAgICAgICAgIC8vID5cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5HcmVhdGVyVGhhbkVxdWFsc1Rva2VuOiAgICAgICAgLy8gPj1cclxuXHJcbiAgICAvLyBBcml0aG1ldGljXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuUGx1c1Rva2VuOiAgICAgICAgICAgICAgICAgICAgIC8vICtcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5NaW51c1Rva2VuOiAgICAgICAgICAgICAgICAgICAgLy8gLVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkFzdGVyaXNrVG9rZW46ICAgICAgICAgICAgICAgICAvLyAqXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuU2xhc2hUb2tlbjogICAgICAgICAgICAgICAgICAgIC8vIC9cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5QZXJjZW50VG9rZW46ICAgICAgICAgICAgICAgICAgLy8gJVxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkFzdGVyaXNrQXN0ZXJpc2tUb2tlbjogICAgICAgICAvLyAqKlxyXG5cclxuICAgIC8vIExvZ2ljYWxcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5BbXBlcnNhbmRBbXBlcnNhbmRUb2tlbjogICAgICAgLy8gJiZcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5CYXJCYXJUb2tlbjogICAgICAgICAgICAgICAgICAgLy8gfHxcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5RdWVzdGlvblF1ZXN0aW9uVG9rZW46ICAgICAgICAgLy8gPz9cclxuXHJcbiAgICAvLyBCaXR3aXNlXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuQW1wZXJzYW5kVG9rZW46ICAgICAgICAgICAgICAgIC8vICZcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5CYXJUb2tlbjogICAgICAgICAgICAgICAgICAgICAgLy8gfFxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkNhcmV0VG9rZW46ICAgICAgICAgICAgICAgICAgICAvLyBeXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuTGVzc1RoYW5MZXNzVGhhblRva2VuOiAgICAgICAgIC8vIFxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkdyZWF0ZXJUaGFuR3JlYXRlclRoYW5Ub2tlbjogICAvLyA+PlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkdyZWF0ZXJUaGFuR3JlYXRlclRoYW5HcmVhdGVyVGhhblRva2VuOiAvLyA+Pj5cclxuICAgIFxyXG4gICAgLy8gaW5zdGFuY2VvZiAvIGluXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuSW5zdGFuY2VPZktleXdvcmQ6ICAgICAgICAgICAgIC8vIGluc3RhbmNlb2ZcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5JbktleXdvcmQ6ICAgICAgICAgICAgICAgICAgICAgLy8gaW5cclxuXHJcbiAgICAvLyAtLS0tIFVuYXJ5IGV4cHJlc3Npb25zIC0tLS1cclxuICAgIC8vICFpc0FkbWluLCB+ZmxhZ3MsICtuLCAtbiwgdHlwZW9mIHgsIHZvaWQgMFxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlByZWZpeFVuYXJ5RXhwcmVzc2lvbjpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5Qb3N0Zml4VW5hcnlFeHByZXNzaW9uOlxyXG4gICAgLy8gdHlwZW9mIGlzIHJlcHJlc2VudGVkIGFzIGEgZGVkaWNhdGVkIG5vZGUga2luZCBpbiBzb21lIFRTIHZlcnNpb25zXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuVHlwZU9mRXhwcmVzc2lvbjpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5Wb2lkRXhwcmVzc2lvbjpcclxuXHJcbiAgICAvLyAtLS0tIENvbmRpdGlvbmFsICh0ZXJuYXJ5KSAtLS0tXHJcbiAgICAvLyBpc0FkbWluID8gJ3llcycgOiAnbm8nXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuQ29uZGl0aW9uYWxFeHByZXNzaW9uOlxyXG5cclxuICAgIC8vIC0tLS0gUGFyZW50aGVzaXNlZCBleHByZXNzaW9ucyAtLS0tXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuUGFyZW50aGVzaXplZEV4cHJlc3Npb246XHJcblxyXG4gICAgLy8gLS0tLSBUZW1wbGF0ZSBsaXRlcmFscyAtLS0tXHJcbiAgICAvLyBgSGVsbG8gJHt1c2VyLm5hbWV9YFxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlRlbXBsYXRlRXhwcmVzc2lvbjpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5Ob1N1YnN0aXR1dGlvblRlbXBsYXRlTGl0ZXJhbDpcclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5UZW1wbGF0ZUhlYWQ6XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuVGVtcGxhdGVNaWRkbGU6XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuVGVtcGxhdGVUYWlsOlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlRlbXBsYXRlU3BhbjpcclxuXHJcbiAgICAvLyAtLS0tIEFycmF5cyAtLS0tXHJcbiAgICAvLyBbMSwgMiwgM10sIFsuLi5pdGVtc11cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5BcnJheUxpdGVyYWxFeHByZXNzaW9uOlxyXG5cclxuICAgIC8vIC0tLS0gT2JqZWN0cyAtLS0tXHJcbiAgICAvLyB7IGtleTogdmFsdWUgfSwgeyAuLi5kZWZhdWx0cywgbmFtZSB9XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb246XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuUHJvcGVydHlBc3NpZ25tZW50OlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlNob3J0aGFuZFByb3BlcnR5QXNzaWdubWVudDpcclxuICAgIC8vIHsgLi4ub2JqIH0gaW5zaWRlIGFuIG9iamVjdCBsaXRlcmFsXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuU3ByZWFkQXNzaWdubWVudDpcclxuXHJcbiAgICAvLyAtLS0tIFNwcmVhZCAtLS0tXHJcbiAgICAvLyBmb28oLi4uYXJncyksIFsuLi5pdGVtc11cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5TcHJlYWRFbGVtZW50OlxyXG5cclxuICAgIC8vIC0tLS0gSW50ZXJuYWwgc3RydWN0dXJhbCBub2RlcyAtLS0tXHJcbiAgICAvLyBWaXNpdGVkIGR1cmluZyByZWN1cnNpb24gYnV0IGNhcnJ5IG5vIHNlbWFudGljIG1lYW5pbmcgb2YgdGhlaXIgb3duLlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlN5bnRheExpc3Q6XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG5cclxuICAgIC8vIC0tLS0gRGlzYWxsb3dlZCBieSBkZWZhdWx0IC0tLS1cclxuICAgIGRlZmF1bHQ6XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBCdWlsZHMgYSBodW1hbi1yZWFkYWJsZSBkaWFnbm9zdGljIG1lc3NhZ2UgZm9yIGEgbm9kZSB0aGF0IGlzIG5vdCBwZXJtaXR0ZWRcclxuICogaW5zaWRlIGEgWGFlbmRhciB0ZW1wbGF0ZSBleHByZXNzaW9uLlxyXG4gKlxyXG4gKiBQcm92aWRlcyBzcGVjaWZpYyBtZXNzYWdlcyBmb3IgdGhlIG1vc3QgY29tbW9uIG1pc3Rha2VzIChhc3NpZ25tZW50cywgYGF3YWl0YCxcclxuICogYG5ld2AsIGZ1bmN0aW9ucykgYW5kIGZhbGxzIGJhY2sgdG8gYSBnZW5lcmljIG1lc3NhZ2UgZm9yIGFueXRoaW5nIGVsc2UuXHJcbiAqL1xyXG5mdW5jdGlvbiBidWlsZERpc2FsbG93ZWRNZXNzYWdlKG5vZGU6IHRzLk5vZGUpOiBzdHJpbmcge1xyXG4gIHN3aXRjaCAobm9kZS5raW5kKSB7XHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuQXdhaXRFeHByZXNzaW9uOlxyXG4gICAgICByZXR1cm4gXCInYXdhaXQnIGlzIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy5cIjtcclxuXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuWWllbGRFeHByZXNzaW9uOlxyXG4gICAgICByZXR1cm4gXCIneWllbGQnIGlzIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy5cIjtcclxuXHJcbiAgICBjYXNlIHRzLlN5bnRheEtpbmQuTmV3RXhwcmVzc2lvbjpcclxuICAgICAgcmV0dXJuIFwiJ25ldycgaXMgbm90IGFsbG93ZWQgaW5zaWRlIHRlbXBsYXRlIGV4cHJlc3Npb25zLlwiO1xyXG5cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5BcnJvd0Z1bmN0aW9uOlxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLkZ1bmN0aW9uRXhwcmVzc2lvbjpcclxuICAgICAgcmV0dXJuICdGdW5jdGlvbiBleHByZXNzaW9ucyBhcmUgbm90IGFsbG93ZWQgaW5zaWRlIHRlbXBsYXRlIGV4cHJlc3Npb25zLic7XHJcblxyXG4gICAgY2FzZSB0cy5TeW50YXhLaW5kLlRhZ2dlZFRlbXBsYXRlRXhwcmVzc2lvbjpcclxuICAgICAgcmV0dXJuICdUYWdnZWQgdGVtcGxhdGUgZXhwcmVzc2lvbnMgYXJlIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy4nO1xyXG5cclxuICAgIGNhc2UgdHMuU3ludGF4S2luZC5CaW5hcnlFeHByZXNzaW9uOiB7XHJcbiAgICAgIGNvbnN0IGJpbiA9IG5vZGUgYXMgdHMuQmluYXJ5RXhwcmVzc2lvbjtcclxuICAgICAgcmV0dXJuIGlzQXNzaWdubWVudE9wZXJhdG9yKGJpbi5vcGVyYXRvclRva2VuLmtpbmQpXHJcbiAgICAgICAgPyAnQXNzaWdubWVudHMgYXJlIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy4gVXNlIEBjb25zdCB0byBkZWNsYXJlIGxvY2FsIHRlbXBsYXRlIHZhcmlhYmxlcyBpbnN0ZWFkLidcclxuICAgICAgICA6IGAnJHt0cy5TeW50YXhLaW5kW25vZGUua2luZF19JyBpcyBub3QgYWxsb3dlZCBpbnNpZGUgdGVtcGxhdGUgZXhwcmVzc2lvbnMuYDtcclxuICAgIH1cclxuXHJcbiAgICBkZWZhdWx0OlxyXG4gICAgICByZXR1cm4gYCcke3RzLlN5bnRheEtpbmRbbm9kZS5raW5kXX0nIGlzIG5vdCBhbGxvd2VkIGluc2lkZSB0ZW1wbGF0ZSBleHByZXNzaW9ucy5gO1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiB7QGxpbmsgdHMuU3ludGF4S2luZH0gaXMgYW4gYXNzaWdubWVudCBvcGVyYXRvci5cclxuICpcclxuICogQ292ZXJzIHNpbXBsZSBhc3NpZ25tZW50IChgPWApIGFzIHdlbGwgYXMgYWxsIGNvbXBvdW5kIGFzc2lnbm1lbnQgb3BlcmF0b3JzXHJcbiAqIChgKz1gLCBgLT1gLCBgJiY9YCwgYHx8PWAsIGA/Pz1gLCBldGMuKSBhcyBkZWZpbmVkIGJ5IHRoZSBUeXBlU2NyaXB0XHJcbiAqIGBGaXJzdEFzc2lnbm1lbnRg4oCTYExhc3RBc3NpZ25tZW50YCByYW5nZS5cclxuICovXHJcbmZ1bmN0aW9uIGlzQXNzaWdubWVudE9wZXJhdG9yKGtpbmQ6IHRzLlN5bnRheEtpbmQpOiBib29sZWFuIHtcclxuICByZXR1cm4ga2luZCA+PSB0cy5TeW50YXhLaW5kLkZpcnN0QXNzaWdubWVudCAmJiBraW5kIDw9IHRzLlN5bnRheEtpbmQuTGFzdEFzc2lnbm1lbnQ7XHJcbn0iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgVG9rZW5UeXBlIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW4tdHlwZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgUGFyc2VyQ3Vyc29yIH0gZnJvbSAnLi4vbW9kZWxzL3BhcnNlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBBU1ROb2RlIH0gZnJvbSAnLi4vdHlwZXMvYXN0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBwYXJzZSB9IGZyb20gJ25vZGU6cGF0aCc7XHJcblxyXG4vKipcclxuICogUGFyc2VzIGNoaWxkIEFTVCBub2RlcyBpbnNpZGUgYSBmbG93LWNvbnRyb2wgYmxvY2sgdW50aWwgYSBCTE9DS19DTE9TRSB0b2tlbiBpcyByZWFjaGVkLlxyXG4gKiBDb25zdW1lcyB0aGUgQkxPQ0tfQ0xPU0UgdG9rZW4gYmVmb3JlIHJldHVybmluZy5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBQYXJzZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIGZpcnN0IHRva2VuIGluc2lkZSB0aGUgYmxvY2suXHJcbiAqIEBwYXJhbSBwYXJzZU5vZGUgUGFyc2VyIGZ1bmN0aW9uIGZvciByZWN1cnNpdmUgY2hpbGQgcGFyc2luZy5cclxuICogQHJldHVybnMgQXJyYXkgb2YgcGFyc2VkIGNoaWxkIGBBU1ROb2RlYHMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VCbG9ja0NoaWxkcmVuKGN1cnNvcjogUGFyc2VyQ3Vyc29yLCBwYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+KTogQVNUTm9kZVtdIHtcclxuICBjb25zdCBjaGlsZHJlbiA9IG5ldyBBcnJheTxBU1ROb2RlPjtcclxuXHJcbiAgd2hpbGUgKGN1cnNvci5wZWVrKCkudHlwZSAhPT0gVG9rZW5UeXBlLkJMT0NLX0NMT1NFKSB7XHJcbiAgICBjb25zdCBjaGlsZCA9IHBhcnNlTm9kZSgpO1xyXG4gICAgaWYgKGNoaWxkKSB7XHJcbiAgICAgIGNoaWxkcmVuLnB1c2goY2hpbGQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gY29uc3VtZSBCTE9DS19DTE9TRVxyXG4gIGN1cnNvci5hZHZhbmNlKCk7XHJcbiAgcmV0dXJuIGNoaWxkcmVuO1xyXG59XHJcbiIsImltcG9ydCB7IE5vQXJnc0Z1bmN0aW9uIH0gZnJvbSAnQHhhZW5kYXIvdHlwZXMnO1xyXG5pbXBvcnQgdHMgZnJvbSAndHlwZXNjcmlwdCc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IEZvclRva2VuIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW5zL2Zvci10b2tlbi50eXBlLmpzJztcclxuaW1wb3J0IHsgUGFyc2VyQ3Vyc29yIH0gZnJvbSAnLi4vbW9kZWxzL3BhcnNlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBBU1ROb2RlIH0gZnJvbSAnLi4vdHlwZXMvYXN0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBGb3JFeHByZXNzaW9uIH0gZnJvbSAnLi4vdHlwZXMvZm9yLWV4cHJlc3Npb24udHlwZS5qcyc7XHJcbmltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZS5lbnVtLmpzJztcclxuaW1wb3J0IHsgRm9ySW1wbGljaXRWYXJpYWJsZXMgfSBmcm9tICcuLi90eXBlcy9ub2Rlcy9mb3ItaW1wbGljaXQtdmFyaWFibGVzLmpzJztcclxuaW1wb3J0IHsgRm9yTm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2Zvci1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyB2YWxpZGF0ZUV4cHJlc3Npb24gfSBmcm9tICcuLi91dGlscy9leHByZXNzaW9uLXZhbGlkYXRvci5qcyc7XHJcbmltcG9ydCB7IHBhcnNlQmxvY2tDaGlsZHJlbiB9IGZyb20gJy4vcGFyc2UtYmxvY2stY2hpbGRyZW4uc3RhdGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIFBhcnNlcyBhIGBAZm9yYCBkaXJlY3RpdmUsIGNvbnN1bWluZyB0aGUgRk9SIHRva2VuLCB0aGUgQ09ORElUSU9OIHRva2VuLFxyXG4gKiB0aGUgQkxPQ0tfT1BFTiB0b2tlbiwgYW5kIGFsbCBjaGlsZCBub2RlcyB1bnRpbCBCTE9DS19DTE9TRS5cclxuICpcclxuICogQHBhcmFtIGN1cnNvciBQYXJzZXIgY3Vyc29yIHBvc2l0aW9uZWQgYXQgdGhlIEZPUiB0b2tlbi5cclxuICogQHBhcmFtIGNvbnRleHQgUGFyc2VyIGNvbnRleHQgZm9yIHJlY3Vyc2l2ZSBjaGlsZCBwYXJzaW5nLlxyXG4gKiBAcGFyYW0gX3Rva2VuIFRoZSBGT1IgdG9rZW4gKHVudXNlZDsgY29uc3VtZWQgZm9yIHBvc2l0aW9uIGFkdmFuY2VtZW50KS5cclxuICogQHJldHVybnMgVGhlIHBhcnNlZCBgRm9yTm9kZWAuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VGb3JDb250cm9sRmxvdyhjdXJzb3I6IFBhcnNlckN1cnNvciwgcGFyc2VOb2RlOiBOb0FyZ3NGdW5jdGlvbjxBU1ROb2RlIHwgdW5kZWZpbmVkPiwgX3Rva2VuOiBGb3JUb2tlbik6IEZvck5vZGUge1xyXG4gIC8vIGNvbnN1bWUgRk9SXHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgY29uc3QgY29uZGl0aW9uVG9rZW4gPSBjdXJzb3IucGVlaygpO1xyXG4gIGlmIChjb25kaXRpb25Ub2tlbi50eXBlICE9PSBUb2tlblR5cGUuQ09ORElUSU9OKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFtQYXJzZXJdIEV4cGVjdGVkIENPTkRJVElPTiBhZnRlciBGT1IsIGdvdCAke1Rva2VuVHlwZVtjb25kaXRpb25Ub2tlbi50eXBlXX1gKTtcclxuICB9XHJcbiAgY29uc3QgZXhwcmVzc2lvbiA9IHBhcnNlRm9yRXhwcmVzc2lvbihjb25kaXRpb25Ub2tlbi5wYXJ0c1swXSwgMCk7XHJcblxyXG4gIC8vIGNvbnN1bWUgQ09ORElUSU9OIGFuZCBCTE9DS19PUEVOXHJcbiAgY3Vyc29yLmFkdmFuY2UoMik7XHJcblxyXG4gIGNvbnN0IGNoaWxkcmVuID0gcGFyc2VCbG9ja0NoaWxkcmVuKGN1cnNvciwgcGFyc2VOb2RlKTtcclxuXHJcbiAgcmV0dXJuIHsgdHlwZTogQVNUTm9kZVR5cGUuRm9yLCAuLi5leHByZXNzaW9uLCBjaGlsZHJlbiB9O1xyXG59XHJcblxyXG4vKipcclxuICogUGFyc2VzIHRoZSBib2R5IG9mIGFuIGBAZm9yYCBibG9jayBpbnRvIGEgc3RydWN0dXJlZCB7QGxpbmsgRm9yRXhwcmVzc2lvbn0uXHJcbiAqXHJcbiAqIFRoZSBleHBlY3RlZCBmb3JtYXQgaXM6XHJcbiAqIGBgYFxyXG4gKiBpdGVtIG9mIGl0ZXJhYmxlOyB0cmFjayBleHByWzsgJGltcGxpY2l0ID0gYWxpYXMsIC4uLl1cclxuICogYGBgXHJcbiAqXHJcbiAqIEBwYXJhbSBzb3VyY2UgICAgIC0gVGhlIHJhdyBzdHJpbmcgY29udGVudCBvZiB0aGUgYEBmb3IoLi4uKWAgZXhwcmVzc2lvbi5cclxuICogQHBhcmFtIGJhc2VPZmZzZXQgLSBDaGFyYWN0ZXIgb2Zmc2V0IG9mIGBzb3VyY2VgIHdpdGhpbiB0aGUgb3JpZ2luYWwgdGVtcGxhdGUsXHJcbiAqICAgICAgICAgICAgICAgICAgICAgdXNlZCB0byBwcm9kdWNlIGFjY3VyYXRlIGRpYWdub3N0aWMgcG9zaXRpb25zLlxyXG4gKiBAcmV0dXJucyBBIHtAbGluayBGb3JFeHByZXNzaW9ufSBvYmplY3QuIFdoZW4gdW5yZWNvdmVyYWJsZSBzeW50YXggZXJyb3JzIGFyZVxyXG4gKiAgICAgICAgICBmb3VuZCB0aGUgcmV0dXJuZWQgb2JqZWN0IGNvbnRhaW5zIG9ubHkgYGRpYWdub3N0aWNzYC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUZvckV4cHJlc3Npb24oc291cmNlOiBzdHJpbmcsIGJhc2VPZmZzZXQ6IG51bWJlcik6IEZvckV4cHJlc3Npb24ge1xyXG4gIGNvbnN0IHNlY3Rpb25zID0gc3BsaXRGb3JTZWN0aW9ucyhzb3VyY2UpO1xyXG5cclxuICBpZiAoc2VjdGlvbnMubGVuZ3RoIDwgMikge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBAZm9yIHJlcXVpcmVzIGF0IGxlYXN0IFwiaXRlbSBvZiBpdGVyYWJsZTsgdHJhY2sgZXhwclwiLmApO1xyXG4gIH1cclxuXHJcbiAgLy8gLS0tLSBTZWN0aW9uIDE6IFwiaXRlbSBvZiBpdGVtc1wiIC0tLS1cclxuICBjb25zdCBpdGVyU2VjdGlvbiA9IHNlY3Rpb25zWzBdIS50cmltKCk7XHJcbiAgY29uc3Qgb2ZJbmRleCA9IGl0ZXJTZWN0aW9uLmluZGV4T2YoJyBvZiAnKTtcclxuXHJcbiAgaWYgKG9mSW5kZXggPT09IC0xKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFtQYXJzZXJdIEBmb3IgZXhwcmVzc2lvbiBtdXN0IGJlIGluIHRoZSBmb3JtIFwiaXRlbSBvZiBpdGVyYWJsZVwiLmApO1xyXG4gIH1cclxuXHJcbiAgY29uc3QgaXRlbUFsaWFzID0gaXRlclNlY3Rpb24uc2xpY2UoMCwgb2ZJbmRleCkudHJpbSgpO1xyXG4gIGNvbnN0IGl0ZXJhYmxlU291cmNlID0gaXRlclNlY3Rpb24uc2xpY2Uob2ZJbmRleCArIDQpLnRyaW0oKTtcclxuXHJcbiAgaWYgKCFpc1ZhbGlkSWRlbnRpZmllcihpdGVtQWxpYXMpKSB7XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFtQYXJzZXJdICcke2l0ZW1BbGlhc30nIGlzIG5vdCBhIHZhbGlkIGl0ZW0gYWxpYXMuYCk7XHJcbiAgfVxyXG5cclxuICAvLyBWYWxpZGF0ZSB0aGUgaXRlcmFibGUgYXMgYSBKUyBleHByZXNzaW9uLlxyXG4gIGNvbnN0IGl0ZXJWYWxpZGF0aW9uID0gdmFsaWRhdGVFeHByZXNzaW9uKGl0ZXJhYmxlU291cmNlKTtcclxuXHJcbiAgLy8gLS0tLSBTZWN0aW9uIDI6IFwidHJhY2sgaXRlbS5pZFwiIC0tLS1cclxuICBjb25zdCB0cmFja1NlY3Rpb24gPSBzZWN0aW9uc1sxXSEudHJpbSgpO1xyXG5cclxuICBpZiAoIXRyYWNrU2VjdGlvbi5zdGFydHNXaXRoKCd0cmFjayAnKSkge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBTZWNvbmQgc2VjdGlvbiBvZiBAZm9yIG11c3Qgc3RhcnQgd2l0aCBcInRyYWNrXCIuYCk7XHJcbiAgfVxyXG5cclxuICBjb25zdCB0cmFja1NvdXJjZSA9IHRyYWNrU2VjdGlvbi5zbGljZSg2KS50cmltKCk7XHJcbiAgY29uc3QgdHJhY2tWYWxpZGF0aW9uID0gdmFsaWRhdGVFeHByZXNzaW9uKHRyYWNrU291cmNlKTtcclxuXHJcbiAgLy8gLS0tLSBTZWN0aW9uIDMgKG9wdGlvbmFsKTogXCIkaW5kZXggPSBpLCAkbGFzdCA9IGxcIiAtLS0tXHJcbiAgY29uc3QgaW1wbGljaXRBbGlhc2VzID0gbmV3IE1hcDxGb3JJbXBsaWNpdFZhcmlhYmxlcywgc3RyaW5nPjtcclxuXHJcbiAgaWYgKHNlY3Rpb25zLmxlbmd0aCA+PSAzICYmIHNlY3Rpb25zWzJdICE9PSB1bmRlZmluZWQpIHtcclxuICAgIGNvbnN0IGFsaWFzU2VjdGlvbiA9IHNlY3Rpb25zWzJdLnRyaW0oKTtcclxuICAgIGNvbnN0IGFsaWFzT2Zmc2V0ID0gYmFzZU9mZnNldCArIHNvdXJjZS5pbmRleE9mKHNlY3Rpb25zWzJdKTtcclxuICAgIHBhcnNlSW1wbGljaXRBbGlhc2VzKGFsaWFzU2VjdGlvbiwgYWxpYXNPZmZzZXQsIGltcGxpY2l0QWxpYXNlcyk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgaXRlbUFsaWFzLFxyXG4gICAgaXRlcmFibGVFeHByZXNzaW9uOiBpdGVyVmFsaWRhdGlvbi5ub2RlLFxyXG4gICAgaXRlcmFibGVTb3VyY2UsXHJcbiAgICB0cmFja0V4cHJlc3Npb246IHRyYWNrVmFsaWRhdGlvbi5ub2RlLFxyXG4gICAgdHJhY2tTb3VyY2UsXHJcbiAgICBpbXBsaWNpdEFsaWFzZXNcclxuICB9O1xyXG59XHJcblxyXG4vKipcclxuICogUGFyc2VzIHRoZSBvcHRpb25hbCB0aGlyZCBzZWN0aW9uIG9mIGFuIGBAZm9yYCBleHByZXNzaW9uLCB3aGljaCBkZWNsYXJlc1xyXG4gKiBhbGlhc2VzIGZvciBpbXBsaWNpdCBsb29wIHZhcmlhYmxlcyAoZS5nLiBgJGluZGV4ID0gaSwgJGxhc3QgPSBsLCAkZXZlbiA9IGlzRXZlbmApLlxyXG4gKlxyXG4gKiBWYWxpZCBlbnRyaWVzIGFyZSBjb21tYS1zZXBhcmF0ZWQgcGFpcnMgaW4gdGhlIGZvcm0gYCRpbXBsaWNpdCA9IGFsaWFzYC5cclxuICogRGlhZ25vc3RpY3MgYXJlIHB1c2hlZCB0byBgZGlhZ25vc3RpY3NgIGZvciBhbnkgbWFsZm9ybWVkIG9yIGR1cGxpY2F0ZSBlbnRyeS5cclxuICpcclxuICogQHBhcmFtIHNvdXJjZSAgICAgIC0gVGhlIHJhdyBhbGlhcy1kZWNsYXJhdGlvbnMgc3RyaW5nIChldmVyeXRoaW5nIGFmdGVyIHRoZSBzZWNvbmQgYDtgKS5cclxuICogQHBhcmFtIGJhc2VPZmZzZXQgIC0gQ2hhcmFjdGVyIG9mZnNldCBvZiBgc291cmNlYCB3aXRoaW4gdGhlIG9yaWdpbmFsIHRlbXBsYXRlLlxyXG4gKiBAcGFyYW0gb3V0ICAgICAgICAgLSBNYXAgdG8gcG9wdWxhdGUgd2l0aCBgYWxpYXMg4oaSIGltcGxpY2l0LXZhcmlhYmxlYCBlbnRyaWVzLlxyXG4gKiBAcGFyYW0gZGlhZ25vc3RpY3MgLSBBcnJheSB0byBjb2xsZWN0IGFueSBwYXJzZSBlcnJvcnMuXHJcbiAqL1xyXG5mdW5jdGlvbiBwYXJzZUltcGxpY2l0QWxpYXNlcyhzb3VyY2U6IHN0cmluZywgYmFzZU9mZnNldDogbnVtYmVyLCBvdXQ6IE1hcDxGb3JJbXBsaWNpdFZhcmlhYmxlcywgc3RyaW5nPik6IHZvaWQge1xyXG4gIGNvbnN0IGVudHJpZXMgPSBzb3VyY2Uuc3BsaXQoJywnKTtcclxuICBsZXQgY3Vyc29yID0gMDtcclxuICBcclxuICBjb25zdCBJTVBMSUNJVF9WQVJJQUJMRVMgPSBuZXcgU2V0KFsnJGluZGV4JywgJyRsYXN0JywgJyRmaXJzdCcsICckZXZlbicsICckb2RkJ10pO1xyXG5cclxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcclxuICAgIGNvbnN0IHRyaW1tZWQgPSBlbnRyeS50cmltKCk7XHJcbiAgICBjb25zdCBlcUluZGV4ID0gdHJpbW1lZC5pbmRleE9mKCc9Jyk7XHJcblxyXG4gICAgaWYgKGVxSW5kZXggPT09IC0xKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgW1BhcnNlcl0gSW52YWxpZCBhbGlhcyBkZWNsYXJhdGlvbiAnJHt0cmltbWVkfScuIEV4cGVjdGVkICckaW1wbGljaXQgPSBhbGlhcycuYCk7XHJcbiAgICB9XHJcblxyXG4gICAgY3Vyc29yICs9IGVudHJ5Lmxlbmd0aCArIDE7XHJcbiAgICBjb25zdCBpbXBsaWNpdCA9IHRyaW1tZWQuc2xpY2UoMCwgZXFJbmRleCkudHJpbSgpO1xyXG4gICAgY29uc3QgYWxpYXMgPSB0cmltbWVkLnNsaWNlKGVxSW5kZXggKyAxKS50cmltKCk7XHJcblxyXG4gICAgY29uc3QgaXNJbXBsaWNpdFZhcmlhYmxlID0gKHZhbHVlOiBzdHJpbmcpOiB2YWx1ZSBpcyBGb3JJbXBsaWNpdFZhcmlhYmxlcyA9PiBJTVBMSUNJVF9WQVJJQUJMRVMuaGFzKHZhbHVlIGFzIEZvckltcGxpY2l0VmFyaWFibGVzKTtcclxuICAgIFxyXG4gICAgaWYgKCFpc0ltcGxpY2l0VmFyaWFibGUoaW1wbGljaXQpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgW1BhcnNlcl0gJyR7aW1wbGljaXR9JyBpcyBub3QgYSBrbm93biBpbXBsaWNpdCB2YXJpYWJsZS4gS25vd24gdmFyaWFibGVzOiAke1suLi5JTVBMSUNJVF9WQVJJQUJMRVNdLmpvaW4oJywgJyl9LmApO1xyXG4gICAgfVxyXG5cclxuICAgIGN1cnNvciArPSBlbnRyeS5sZW5ndGggKyAxO1xyXG4gICAgaWYgKCFpc1ZhbGlkSWRlbnRpZmllcihhbGlhcykpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSAnJHthbGlhc30nIGlzIG5vdCBhIHZhbGlkIGFsaWFzIGlkZW50aWZpZXIuYCk7XHJcbiAgICB9XHJcblxyXG4gICAgY3Vyc29yICs9IGVudHJ5Lmxlbmd0aCArIDE7XHJcbiAgICBpZiAob3V0LmhhcyhpbXBsaWNpdCkpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSAnJHtpbXBsaWNpdH0nIGlzIGFscmVhZHkgYWxpYXNlZCBpbiB0aGlzIEBmb3IgZXhwcmVzc2lvbi5gKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIG91dC5zZXQoaW1wbGljaXQsIGFsaWFzKTtcclxuICAgIH1cclxuXHJcbiAgICBjdXJzb3IgKz0gZW50cnkubGVuZ3RoICsgMTtcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTcGxpdHMgdGhlIHJhdyBgQGZvciguLi4pYCBib2R5IGludG8gaXRzIHNlbWljb2xvbi1kZWxpbWl0ZWQgc2VjdGlvbnMsXHJcbiAqIHJlc3BlY3RpbmcgbmVzdGVkIGJyYWNrZXRzIGFuZCBzdHJpbmcgbGl0ZXJhbHMgc28gdGhhdCBzZW1pY29sb25zIGluc2lkZVxyXG4gKiB0aGVtIGFyZSBuZXZlciB0cmVhdGVkIGFzIHNlY3Rpb24gc2VwYXJhdG9ycy5cclxuICpcclxuICogRXhhbXBsZSBpbnB1dDogIGBcIml0ZW0gb2YgaXRlbXM7IHRyYWNrIGl0ZW0uaWQ7ICRpbmRleCA9IGlcImBcclxuICogRXhhbXBsZSBvdXRwdXQ6IGBbXCJpdGVtIG9mIGl0ZW1zXCIsIFwiIHRyYWNrIGl0ZW0uaWRcIiwgXCIgJGluZGV4ID0gaVwiXWBcclxuICpcclxuICogQHBhcmFtIHNvdXJjZSAtIFRoZSByYXcgY29udGVudCBvZiB0aGUgYEBmb3IoLi4uKWAgZXhwcmVzc2lvbi5cclxuICogQHJldHVybnMgQW4gYXJyYXkgb2Ygc2VjdGlvbiBzdHJpbmdzICh3aXRob3V0IHRoZSBgO2Agc2VwYXJhdG9ycykuXHJcbiAqL1xyXG5mdW5jdGlvbiBzcGxpdEZvclNlY3Rpb25zKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nW10ge1xyXG4gIGNvbnN0IHNlY3Rpb25zID0gbmV3IEFycmF5PHN0cmluZz47XHJcbiAgbGV0IGN1cnJlbnQgPSAnJztcclxuICBsZXQgZGVwdGggPSAwO1xyXG4gIGxldCBpblN0cmluZzogJ1wiJyB8IFwiJ1wiIHwgJ2AnIHwgbnVsbCB8IHVuZGVmaW5lZDtcclxuXHJcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2UubGVuZ3RoOyBpKyspIHtcclxuICAgIGNvbnN0IGNoYXIgPSBzb3VyY2VbaV0hO1xyXG5cclxuICAgIGlmICghY3VycmVudCAmJiBjaGFyID09PSAnICcpIHtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGluU3RyaW5nKSB7XHJcbiAgICAgIGN1cnJlbnQgKz0gY2hhcjtcclxuICAgICAgaWYgKGNoYXIgPT09IGluU3RyaW5nICYmIHNvdXJjZVtpIC0gMV0gIT09ICdcXFxcJykge1xyXG4gICAgICAgIGluU3RyaW5nID0gbnVsbDtcclxuICAgICAgfVxyXG4gICAgICBjb250aW51ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoY2hhciA9PT0gJ1wiJyB8fCBjaGFyID09PSBcIidcIiB8fCBjaGFyID09PSAnYCcpIHtcclxuICAgICAgaW5TdHJpbmcgPSBjaGFyO1xyXG4gICAgICBjdXJyZW50ICs9IGNoYXI7XHJcbiAgICAgIGNvbnRpbnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEJyYWNrZXRzIOKAlCBkbyBub3Qgc3BsaXQgaW5zaWRlIG5lc3RlZCBicmFja2V0IHBhaXJzLlxyXG4gICAgaWYgKGNoYXIgPT09ICcoJyB8fCBjaGFyID09PSAnWycgfHwgY2hhciA9PT0gJ3snKSB7XHJcbiAgICAgIGRlcHRoKys7XHJcbiAgICAgIGN1cnJlbnQgKz0gY2hhcjtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGNoYXIgPT09ICcpJyB8fCBjaGFyID09PSAnXScgfHwgY2hhciA9PT0gJ30nKSB7XHJcbiAgICAgIGRlcHRoLS07XHJcbiAgICAgIGN1cnJlbnQgKz0gY2hhcjtcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gU2VjdGlvbiBzZXBhcmF0b3Ig4oCUIG9ubHkgc3BsaXQgd2hlbiBub3QgaW5zaWRlIGJyYWNrZXRzIG9yIHN0cmluZ3MuXHJcbiAgICBpZiAoY2hhciA9PT0gJzsnICYmIGRlcHRoID09PSAwKSB7XHJcbiAgICAgIHNlY3Rpb25zLnB1c2goY3VycmVudCk7XHJcbiAgICAgIGN1cnJlbnQgPSAnJztcclxuICAgICAgY29udGludWU7XHJcbiAgICB9XHJcblxyXG4gICAgY3VycmVudCArPSBjaGFyO1xyXG4gIH1cclxuXHJcbiAgLy8gUHVzaCB0aGUgbGFzdCBzZWN0aW9uIGV2ZW4gd2hlbiBpdCBoYXMgbm8gdHJhaWxpbmcgYDtgLlxyXG4gIGlmIChjdXJyZW50LnRyaW0oKS5sZW5ndGggPiAwKSB7XHJcbiAgICBzZWN0aW9ucy5wdXNoKGN1cnJlbnQpO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHNlY3Rpb25zO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIHdoZXRoZXIgYG5hbWVgIGlzIGEgdmFsaWQgSmF2YVNjcmlwdCBpZGVudGlmaWVyIGJ5IGRlbGVnYXRpbmcgdG9cclxuICogdGhlIFR5cGVTY3JpcHQgcGFyc2VyLlxyXG4gKlxyXG4gKiBBIHN0cmluZyBpcyBjb25zaWRlcmVkIHZhbGlkIHdoZW4gdGhlIFRTIHBhcnNlciBwcm9kdWNlcyBhIHNpbmdsZVxyXG4gKiBgRXhwcmVzc2lvblN0YXRlbWVudGAgd2hvc2UgZXhwcmVzc2lvbiBpcyBhbiBgSWRlbnRpZmllcmAgd2l0aCB0aGVcclxuICogc2FtZSB0ZXh0LlxyXG4gKlxyXG4gKiBAcGFyYW0gbmFtZSAtIFRoZSBzdHJpbmcgdG8gdmFsaWRhdGUuXHJcbiAqIEByZXR1cm5zIGB0cnVlYCBpZiBgbmFtZWAgaXMgYSB2YWxpZCBKUyBpZGVudGlmaWVyLCBgZmFsc2VgIG90aGVyd2lzZS5cclxuICovXHJcbmZ1bmN0aW9uIGlzVmFsaWRJZGVudGlmaWVyKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gIGlmICghbmFtZS5sZW5ndGgpIHtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIGNvbnN0IHNvdXJjZUZpbGUgPSB0cy5jcmVhdGVTb3VyY2VGaWxlKCdfX2lkLnRzJywgbmFtZSwgdHMuU2NyaXB0VGFyZ2V0LkVTTmV4dCwgZmFsc2UpO1xyXG4gIGNvbnN0IHN0YXRlbWVudCA9IHNvdXJjZUZpbGUuc3RhdGVtZW50c1swXTtcclxuICByZXR1cm4gISFzdGF0ZW1lbnQgJiYgdHMuaXNFeHByZXNzaW9uU3RhdGVtZW50KHN0YXRlbWVudCkgJiYgdHMuaXNJZGVudGlmaWVyKHN0YXRlbWVudC5leHByZXNzaW9uKSAmJiBzdGF0ZW1lbnQuZXhwcmVzc2lvbi50ZXh0ID09PSBuYW1lO1xyXG59IiwiaW1wb3J0IHsgTm9BcmdzRnVuY3Rpb24gfSBmcm9tICdAeGFlbmRhci90eXBlcyc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IElmVG9rZW4gfSBmcm9tICcuLi8uLi9sZXhlci90eXBlcy90b2tlbnMvaWYtdG9rZW4udHlwZS5qcyc7XHJcbmltcG9ydCB7IFBhcnNlckN1cnNvciB9IGZyb20gJy4uL21vZGVscy9wYXJzZXItY3Vyc29yLm1vZGVsLmpzJztcclxuaW1wb3J0IHsgQVNUTm9kZSB9IGZyb20gJy4uL3R5cGVzL2FzdC50eXBlLmpzJztcclxuaW1wb3J0IHsgQVNUTm9kZVR5cGUgfSBmcm9tICcuLi90eXBlcy9ub2RlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBFbHNlTm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2Vsc2Utbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgSWZOb2RlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZXMvaWYtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgdmFsaWRhdGVFeHByZXNzaW9uIH0gZnJvbSAnLi4vdXRpbHMvZXhwcmVzc2lvbi12YWxpZGF0b3IuanMnO1xyXG5pbXBvcnQgeyBwYXJzZUJsb2NrQ2hpbGRyZW4gfSBmcm9tICcuL3BhcnNlLWJsb2NrLWNoaWxkcmVuLnN0YXRlLmpzJztcclxuaW1wb3J0IHsgRWxzZUlmVG9rZW4gfSBmcm9tICcuLi8uLi9sZXhlci90eXBlcy90b2tlbnMvZWxzZS1pZi10b2tlbi50eXBlLmpzJztcclxuaW1wb3J0IHsgRWxzZUlmTm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL2Vsc2UtaWYtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgRWxzZVRva2VuIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW5zL2Vsc2UtdG9rZW4udHlwZS5qcyc7XHJcblxyXG4vKipcclxuICogUGFyc2VzIGFuIGBAaWZgIGRpcmVjdGl2ZSwgY29uc3VtaW5nIHRoZSBJRiB0b2tlbiwgdGhlIENPTkRJVElPTiB0b2tlbixcclxuICogdGhlIEJMT0NLX09QRU4gdG9rZW4sIGFsbCBjb25zZXF1ZW50IGNoaWxkcmVuLCBhbmQgYW4gb3B0aW9uYWwgYEBlbHNlYCBicmFuY2guXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgUGFyc2VyIGN1cnNvciBwb3NpdGlvbmVkIGF0IHRoZSBJRiB0b2tlbi5cclxuICogQHBhcmFtIGNvbnRleHQgUGFyc2VyIGNvbnRleHQgZm9yIHJlY3Vyc2l2ZSBjaGlsZCBwYXJzaW5nLlxyXG4gKiBAcGFyYW0gdG9rZW4gVGhlIElGIHRva2VuICh1bnVzZWQ7IGNvbnN1bWVkIGZvciBwb3NpdGlvbiBhZHZhbmNlbWVudCkuXHJcbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgYElmTm9kZWAuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VJZkNvbnRyb2xGbG93KGN1cnNvcjogUGFyc2VyQ3Vyc29yLCBwYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+LCB0b2tlbjogSWZUb2tlbik6IElmTm9kZSB7XHJcbiAgcmV0dXJuIHBhcnNlSWZSZWN1cnNpdmVseShjdXJzb3IsIHBhcnNlTm9kZSwgdG9rZW4pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwYXJzZUlmUmVjdXJzaXZlbHkoY3Vyc29yOiBQYXJzZXJDdXJzb3IsIHBhcnNlTm9kZTogTm9BcmdzRnVuY3Rpb248QVNUTm9kZSB8IHVuZGVmaW5lZD4sIHRva2VuOiBJZlRva2VuKTogSWZOb2RlO1xyXG5mdW5jdGlvbiBwYXJzZUlmUmVjdXJzaXZlbHkoY3Vyc29yOiBQYXJzZXJDdXJzb3IsIHBhcnNlTm9kZTogTm9BcmdzRnVuY3Rpb248QVNUTm9kZSB8IHVuZGVmaW5lZD4sIHRva2VuOiBFbHNlSWZUb2tlbiB8IEVsc2VUb2tlbik6IEVsc2VJZk5vZGUgfCBFbHNlTm9kZTtcclxuZnVuY3Rpb24gcGFyc2VJZlJlY3Vyc2l2ZWx5KGN1cnNvcjogUGFyc2VyQ3Vyc29yLCBwYXJzZU5vZGU6IE5vQXJnc0Z1bmN0aW9uPEFTVE5vZGUgfCB1bmRlZmluZWQ+LCB0b2tlbjogRWxzZVRva2VuKTogRWxzZU5vZGU7XHJcbmZ1bmN0aW9uIHBhcnNlSWZSZWN1cnNpdmVseShjdXJzb3I6IFBhcnNlckN1cnNvciwgcGFyc2VOb2RlOiBOb0FyZ3NGdW5jdGlvbjxBU1ROb2RlIHwgdW5kZWZpbmVkPiwgdG9rZW46IElmVG9rZW4gfCBFbHNlSWZUb2tlbiB8IEVsc2VUb2tlbik6IElmTm9kZSB8IEVsc2VJZk5vZGUgfCBFbHNlTm9kZSB7XHJcbiAgc3dpdGNoICh0b2tlbi50eXBlKSB7XHJcbiAgICBjYXNlIFRva2VuVHlwZS5JRjpcclxuICAgIGNhc2UgVG9rZW5UeXBlLkVMU0VfSUY6XHJcbiAgICAgIGN1cnNvci5hZHZhbmNlKCk7XHJcblxyXG4gICAgICBjb25zdCBjb25kaXRpb25Ub2tlbiA9IGN1cnNvci5wZWVrKCk7XHJcbiAgICAgIGlmIChjb25kaXRpb25Ub2tlbi50eXBlICE9PSBUb2tlblR5cGUuQ09ORElUSU9OKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBFeHBlY3RlZCBDT05ESVRJT04gYWZ0ZXIgJHtUb2tlblR5cGVbdG9rZW4udHlwZV19LCBnb3QgJHtUb2tlblR5cGVbY29uZGl0aW9uVG9rZW4udHlwZV19YCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGNvbnN1bWUgQ09ORElUSU9OIGFuZCBCTE9DS19PUEVOXHJcbiAgICAgIGN1cnNvci5hZHZhbmNlKDIpO1xyXG5cclxuICAgICAgY29uc3QgY29uZGl0aW9uID0gY29uZGl0aW9uVG9rZW4ucGFydHNbMF07XHJcbiAgICAgIGNvbnN0IHZhbGlkYXRpb25SZXN1bHQgPSB2YWxpZGF0ZUV4cHJlc3Npb24oY29uZGl0aW9uKTtcclxuXHJcbiAgICAgIGNvbnN0IGNvbnNlcXVlbnQgPSBwYXJzZUJsb2NrQ2hpbGRyZW4oY3Vyc29yLCBwYXJzZU5vZGUpO1xyXG5cclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICB0eXBlOiB0b2tlbi50eXBlID09PSBUb2tlblR5cGUuSUYgPyBBU1ROb2RlVHlwZS5JZiA6IEFTVE5vZGVUeXBlLkVsc2VJZixcclxuICAgICAgICBjb25kaXRpb24sXHJcbiAgICAgICAgY29uZGl0aW9uTm9kZTogdmFsaWRhdGlvblJlc3VsdC5ub2RlLFxyXG4gICAgICAgIGNvbnNlcXVlbnQsXHJcbiAgICAgICAgYWx0ZXJuYXRlOiBwYXJzZUlmUmVjdXJzaXZlbHkoY3Vyc29yLCBwYXJzZU5vZGUsIGN1cnNvci5wZWVrPEVsc2VJZlRva2VuIHwgRWxzZVRva2VuPigpKVxyXG4gICAgICB9O1xyXG5cclxuICAgIGNhc2UgVG9rZW5UeXBlLkVMU0U6XHJcbiAgICAgIC8vIGNvbnN1bWUgRUxTRSBhbmQgQkxPQ0tfT1BFTlxyXG4gICAgICBjdXJzb3IuYWR2YW5jZSgyKTtcclxuXHJcbiAgICAgIGNvbnN0IGVsc2VDaGlsZHJlbiA9IHBhcnNlQmxvY2tDaGlsZHJlbihjdXJzb3IsIHBhcnNlTm9kZSk7XHJcbiAgICAgIFxyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIHR5cGU6IEFTVE5vZGVUeXBlLkVsc2UsXHJcbiAgICAgICAgY29uc2VxdWVudDogZWxzZUNoaWxkcmVuXHJcbiAgICAgIH07XHJcbiAgfVxyXG59IiwiaW1wb3J0IHsgTm9BcmdzRnVuY3Rpb24gfSBmcm9tICdAeGFlbmRhci90eXBlcyc7XHJcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4uLy4uL2xleGVyL3R5cGVzL3Rva2VuLXR5cGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IFN3aXRjaFRva2VuIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW5zL3N3aXRjaC10b2tlbi50eXBlLmpzJztcclxuaW1wb3J0IHsgUGFyc2VyQ3Vyc29yIH0gZnJvbSAnLi4vbW9kZWxzL3BhcnNlci1jdXJzb3IubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBBU1ROb2RlIH0gZnJvbSAnLi4vdHlwZXMvYXN0LnR5cGUuanMnO1xyXG5pbXBvcnQgeyBBU1ROb2RlVHlwZSB9IGZyb20gJy4uL3R5cGVzL25vZGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IENhc2VOb2RlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZXMvY2FzZS1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBTd2l0Y2hOb2RlIH0gZnJvbSAnLi4vdHlwZXMvbm9kZXMvc3dpdGNoLW5vZGUudHlwZS5qcyc7XHJcbmltcG9ydCB7IHBhcnNlQmxvY2tDaGlsZHJlbiB9IGZyb20gJy4vcGFyc2UtYmxvY2stY2hpbGRyZW4uc3RhdGUuanMnO1xyXG5cclxuLyoqXHJcbiAqIFBhcnNlcyBhIGBAc3dpdGNoYCBkaXJlY3RpdmUsIGNvbnN1bWluZyB0aGUgU1dJVENIIHRva2VuLCB0aGUgQ09ORElUSU9OIHRva2VuLFxyXG4gKiB0aGUgb3V0ZXIgQkxPQ0tfT1BFTiwgYWxsIGBAY2FzZWAgYW5kIGBAZGVmYXVsdGAgYnJhbmNoZXMsIGFuZCB0aGUgb3V0ZXIgQkxPQ0tfQ0xPU0UuXHJcbiAqXHJcbiAqIEBwYXJhbSBjdXJzb3IgUGFyc2VyIGN1cnNvciBwb3NpdGlvbmVkIGF0IHRoZSBTV0lUQ0ggdG9rZW4uXHJcbiAqIEBwYXJhbSBwYXJzZU5vZGUgUGFyc2VyIGZ1bmN0aW9uIGZvciByZWN1cnNpdmUgY2hpbGQgcGFyc2luZy5cclxuICogQHBhcmFtIF90b2tlbiBUaGUgU1dJVENIIHRva2VuICh1bnVzZWQ7IGNvbnN1bWVkIGZvciBwb3NpdGlvbiBhZHZhbmNlbWVudCkuXHJcbiAqIEByZXR1cm5zIFRoZSBwYXJzZWQgYFN3aXRjaE5vZGVgLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlU3dpdGNoQ29udHJvbEZsb3coY3Vyc29yOiBQYXJzZXJDdXJzb3IsIHBhcnNlTm9kZTogTm9BcmdzRnVuY3Rpb248QVNUTm9kZSB8IHVuZGVmaW5lZD4sIF90b2tlbjogU3dpdGNoVG9rZW4pOiBTd2l0Y2hOb2RlIHtcclxuICAvLyBjb25zdW1lIFNXSVRDSFxyXG4gIGN1cnNvci5hZHZhbmNlKCk7XHJcblxyXG4gIGNvbnN0IGNvbmRpdGlvblRva2VuID0gY3Vyc29yLnBlZWsoKTtcclxuICBpZiAoY29uZGl0aW9uVG9rZW4udHlwZSAhPT0gVG9rZW5UeXBlLkNPTkRJVElPTikge1xyXG4gICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBFeHBlY3RlZCBDT05ESVRJT04gYWZ0ZXIgU1dJVENILCBnb3QgJHtUb2tlblR5cGVbY29uZGl0aW9uVG9rZW4udHlwZV19YCk7XHJcbiAgfVxyXG5cclxuICBjb25zdCBleHByZXNzaW9uID0gY29uZGl0aW9uVG9rZW4ucGFydHNbMF07XHJcbiAgLy8gY29uc3VtZSBDT05ESVRJT04gYW5kIEJMT0NLX09QRU5cclxuICBjdXJzb3IuYWR2YW5jZSgyKTtcclxuXHJcbiAgY29uc3QgY2FzZXMgPSBuZXcgQXJyYXk8Q2FzZU5vZGU+O1xyXG5cclxuICB3aGlsZSAoY3Vyc29yLnBlZWsoKS50eXBlICE9PSBUb2tlblR5cGUuQkxPQ0tfQ0xPU0UpIHtcclxuICAgIGNvbnN0IHRva2VuID0gY3Vyc29yLnBlZWsoKTtcclxuXHJcbiAgICBzd2l0Y2ggKHRva2VuLnR5cGUpIHtcclxuICAgICAgY2FzZSBUb2tlblR5cGUuQ0FTRTpcclxuICAgICAgICBjb25zdCBjb25kaXRpb24gPSBuZXcgQXJyYXk8c3RyaW5nPjtcclxuICAgICAgICBcclxuICAgICAgICAvKlxyXG4gICAgICAgICAgV2UgbG9vcCB0byBzdXBwb3J0IGJsb2NrIGNhc2Ugd2l0aCBtdWx0aXBsZSBjb25kaXRpb25zLCBlLmcuOlxyXG4gICAgICAgICAgQHN3aXRjaCAoeCkge1xyXG4gICAgICAgICAgICBAY2FzZSAoMSkgXHJcbiAgICAgICAgICAgIEBjYXNlICgyKSB7XHJcbiAgICAgICAgICAgICAgLy8gLi4uXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAqL1xyXG4gICAgICAgIGRvIHtcclxuICAgICAgICAgIC8vIGNvbnN1bWUgQ0FTRVxyXG4gICAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgICAgICAgICBjb25zdCBjYXNlQ29uZGl0aW9uID0gY3Vyc29yLnBlZWsoKTtcclxuICAgICAgICAgIGlmIChjYXNlQ29uZGl0aW9uLnR5cGUgIT09IFRva2VuVHlwZS5DT05ESVRJT04pIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBFeHBlY3RlZCBDT05ESVRJT04gYWZ0ZXIgQ0FTRWApO1xyXG4gICAgICAgICAgfVxyXG4gIFxyXG4gICAgICAgICAgY29uZGl0aW9uLnB1c2goY2FzZUNvbmRpdGlvbi5wYXJ0c1swXSk7XHJcbiAgICAgICAgICAvLyBjb25zdW1lIENPTkRJVElPTlxyXG4gICAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgICAgICB9IHdoaWxlIChjdXJzb3IucGVlaygpLnR5cGUgIT09IFRva2VuVHlwZS5CTE9DS19PUEVOKTtcclxuXHJcbiAgICAgICAgLy8gY29uc3VtZSBCTE9DS19PUEVOXHJcbiAgICAgICAgY3Vyc29yLmFkdmFuY2UoKTtcclxuICAgICAgICBcclxuICAgICAgICBjYXNlcy5wdXNoKHtcclxuICAgICAgICAgIHR5cGU6IEFTVE5vZGVUeXBlLkNhc2UsIFxyXG4gICAgICAgICAgY29uZGl0aW9uLCBcclxuICAgICAgICAgIGNoaWxkcmVuOiBwYXJzZUJsb2NrQ2hpbGRyZW4oY3Vyc29yLCBwYXJzZU5vZGUpIFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgY2FzZSBUb2tlblR5cGUuREVGQVVMVDpcclxuICAgICAgICAvLyBjb25zdW1lIERFRkFVTFQgYW5kIEJMT0NLX09QRU5cclxuICAgICAgICBjdXJzb3IuYWR2YW5jZSgyKTtcclxuICAgICAgICBjYXNlcy5wdXNoKHtcclxuICAgICAgICAgIHR5cGU6IEFTVE5vZGVUeXBlLkNhc2UsIFxyXG4gICAgICAgICAgY29uZGl0aW9uOiBudWxsLCBcclxuICAgICAgICAgIGNoaWxkcmVuOiBwYXJzZUJsb2NrQ2hpbGRyZW4oY3Vyc29yLCBwYXJzZU5vZGUpIFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG5cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIGNvbnN1bWUgb3V0ZXIgQkxPQ0tfQ0xPU0VcclxuICBjdXJzb3IuYWR2YW5jZSgpO1xyXG5cclxuICByZXR1cm4ge1xyXG4gICAgdHlwZTogQVNUTm9kZVR5cGUuU3dpdGNoLFxyXG4gICAgZXhwcmVzc2lvbixcclxuICAgIGNhc2VzXHJcbiAgfTtcclxufVxyXG4iLCJpbXBvcnQgeyBOb0FyZ3NGdW5jdGlvbiB9IGZyb20gJ0B4YWVuZGFyL3R5cGVzJztcclxuaW1wb3J0IHsgVGV4dFRva2VuIH0gZnJvbSAnLi4vLi4vbGV4ZXIvdHlwZXMvdG9rZW5zL3RleHQtdG9rZW4udHlwZS5qcyc7XHJcbmltcG9ydCB7IFBhcnNlckN1cnNvciB9IGZyb20gJy4uL21vZGVscy9wYXJzZXItY3Vyc29yLm1vZGVsLmpzJztcclxuaW1wb3J0IHsgQVNUTm9kZSB9IGZyb20gJy4uL3R5cGVzL2FzdC50eXBlLmpzJztcclxuaW1wb3J0IHsgQVNUTm9kZVR5cGUgfSBmcm9tICcuLi90eXBlcy9ub2RlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBUZXh0Tm9kZSB9IGZyb20gJy4uL3R5cGVzL25vZGVzL3RleHQtbm9kZS50eXBlLmpzJztcclxuXHJcbi8qKlxyXG4gKiBQYXJzZXMgYSBURVhUIHRva2VuIGludG8gYSBgVGV4dE5vZGVgLlxyXG4gKlxyXG4gKiBAcGFyYW0gY3Vyc29yIFBhcnNlciBjdXJzb3I7IGFkdmFuY2VkIHBhc3QgdGhlIFRFWFQgdG9rZW4uXHJcbiAqIEBwYXJhbSBfcGFyc2VOb2RlIEZ1bmN0aW9uIHRvIHBhcnNlIHRoZSBuZXh0IEFTVCBub2RlLlxyXG4gKiBAcGFyYW0gdG9rZW4gVGhlIFRFWFQgdG9rZW4gY29udGFpbmluZyB0aGUgcmF3IHRleHQgY29udGVudC5cclxuICogQHJldHVybnMgVGhlIHBhcnNlZCBgVGV4dE5vZGVgLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlVGV4dChjdXJzb3I6IFBhcnNlckN1cnNvciwgX3BhcnNlTm9kZTogTm9BcmdzRnVuY3Rpb248QVNUTm9kZSB8IHVuZGVmaW5lZD4sIHRva2VuOiBUZXh0VG9rZW4pOiBUZXh0Tm9kZSB7XHJcbiAgY3Vyc29yLmFkdmFuY2UoKTtcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHR5cGU6IEFTVE5vZGVUeXBlLlRleHQsXHJcbiAgICB2YWx1ZTogdG9rZW4ucGFydHNbMF1cclxuICB9O1xyXG59XHJcbiIsImltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gXCIuLi9sZXhlci90eXBlcy90b2tlbi10eXBlLmVudW0uanNcIjtcclxuaW1wb3J0IHsgVG9rZW4gfSBmcm9tIFwiLi4vbGV4ZXIvdHlwZXMvdG9rZW4udHlwZS5qc1wiO1xyXG5pbXBvcnQgeyBQYXJzZXJDdXJzb3IgfSBmcm9tIFwiLi9tb2RlbHMvcGFyc2VyLWN1cnNvci5tb2RlbC5qc1wiO1xyXG5pbXBvcnQgeyBwYXJzZUNvbnN0RGVjbGFyYXRpb24gfSBmcm9tIFwiLi9zdGF0ZXMvcGFyc2UtY29uc3QtZGVjbGFyYXRpb24uc3RhdGUuanNcIjtcclxuaW1wb3J0IHsgcGFyc2VFbGVtZW50IH0gZnJvbSBcIi4vc3RhdGVzL3BhcnNlLWVsZW1lbnQuc3RhdGUuanNcIjtcclxuaW1wb3J0IHsgcGFyc2VGb3JDb250cm9sRmxvdyB9IGZyb20gXCIuL3N0YXRlcy9wYXJzZS1mb3Iuc3RhdGUuanNcIjtcclxuaW1wb3J0IHsgcGFyc2VJZkNvbnRyb2xGbG93IH0gZnJvbSBcIi4vc3RhdGVzL3BhcnNlLWlmLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHBhcnNlSW50ZXJwb2xhdGlvbiB9IGZyb20gXCIuL3N0YXRlcy9wYXJzZS1pbnRlcnBvbGF0aW9uLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHBhcnNlU3dpdGNoQ29udHJvbEZsb3cgfSBmcm9tIFwiLi9zdGF0ZXMvcGFyc2Utc3dpdGNoLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHBhcnNlVGV4dCB9IGZyb20gXCIuL3N0YXRlcy9wYXJzZS10ZXh0LnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tIFwiLi90eXBlcy9hc3QudHlwZS5qc1wiO1xyXG5pbXBvcnQgeyBQYXJzZXJTdGF0ZXMgfSBmcm9tIFwiLi90eXBlcy9wYXJzZXItc3RhdGVzLnR5cGUuanNcIjtcclxuXHJcbi8qKlxyXG4gKiBQYXJzZXIgY2xhc3MgdGhhdCB0cmFuc2Zvcm1zIGEgc3RyZWFtIG9mIHRva2VucyAoZnJvbSB0aGUgTGV4ZXIpXHJcbiAqIGludG8gYW4gQWJzdHJhY3QgU3ludGF4IFRyZWUgKEFTVCkgcmVwcmVzZW50aW5nIHRoZSB0ZW1wbGF0ZSBzdHJ1Y3R1cmUuXHJcbiAqXHJcbiAqIFJlc3BvbnNpYmlsaXRpZXM6XHJcbiAqIC0gUGFyc2UgdGV4dCBub2RlcywgZWxlbWVudHMsIGF0dHJpYnV0ZXMsIGV2ZW50cywgYW5kIGludGVycG9sYXRpb25zXHJcbiAqIC0gTWFpbnRhaW4gY3Vyc29yIHN0YXRlIGZvciBzZXF1ZW50aWFsIHRva2VuIGNvbnN1bXB0aW9uXHJcbiAqIC0gRGV0ZWN0IHRhZyBib3VuZGFyaWVzIGFuZCBuZXN0ZWQgc3RydWN0dXJlc1xyXG4gKlxyXG4gKiBUaGUgcGFyc2VyIGFzc3VtZXMgdGhhdCB0aGUgdG9rZW4gc3RyZWFtIGlzIHN5bnRhY3RpY2FsbHkgdmFsaWQgYWNjb3JkaW5nXHJcbiAqIHRvIHRoZSBMZXhlciBydWxlcy4gUGFyc2luZyBlcnJvcnMgYXJlIHRocm93biBhcyBleGNlcHRpb25zLlxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFBhcnNlciB7XHJcbiAgLyoqXHJcbiAgICogSW50ZXJuYWwgY3Vyc29yIGZvciBuYXZpZ2F0aW5nIHRva2Vuc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2N1cnNvcjogUGFyc2VyQ3Vyc29yO1xyXG4gIC8qKlxyXG4gICAqIE1hcHBpbmcgb2YgdG9rZW4gdHlwZXMgdG8gdGhlaXIgY29ycmVzcG9uZGluZyBwYXJzZXIgdHJhbnNpdGlvbiBmdW5jdGlvbnMsIFxyXG4gICAqIHdoaWNoIGhhbmRsZSB0aGUgbG9naWMgZm9yIHBhcnNpbmcgZWFjaCB0b2tlbiB0eXBlIGludG8gQVNUIG5vZGVzLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N0YXRlczogUGFyc2VyU3RhdGVzID0ge1xyXG4gICAgW1Rva2VuVHlwZS5URVhUXTogcGFyc2VUZXh0LFxyXG4gICAgW1Rva2VuVHlwZS5JTlRFUlBPTEFUSU9OX0VYUFJFU1NJT05dOiBwYXJzZUludGVycG9sYXRpb24sXHJcbiAgICBbVG9rZW5UeXBlLklOVEVSUE9MQVRJT05fTElURVJBTF06IHBhcnNlSW50ZXJwb2xhdGlvbixcclxuICAgIFtUb2tlblR5cGUuVEFHX09QRU5fTkFNRV06IHBhcnNlRWxlbWVudCxcclxuICAgIFtUb2tlblR5cGUuSUZdOiBwYXJzZUlmQ29udHJvbEZsb3csXHJcbiAgICBbVG9rZW5UeXBlLkZPUl06IHBhcnNlRm9yQ29udHJvbEZsb3csXHJcbiAgICBbVG9rZW5UeXBlLlNXSVRDSF06IHBhcnNlU3dpdGNoQ29udHJvbEZsb3csXHJcbiAgICBbVG9rZW5UeXBlLkNPTlNUX0RFQ0xBUkFUSU9OXTogcGFyc2VDb25zdERlY2xhcmF0aW9uXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIGEgbmV3IFBhcnNlciBpbnN0YW5jZS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB0b2tlbnMgQXJyYXkgb2YgdG9rZW5zIHByb2R1Y2VkIGJ5IHRoZSBMZXhlclxyXG4gICAqL1xyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgdG9rZW5zOiBUb2tlbltdKSB7XHJcbiAgICB0aGlzLl9jdXJzb3IgPSBuZXcgUGFyc2VyQ3Vyc29yKHRoaXMudG9rZW5zKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEVudHJ5IHBvaW50IGZvciBwYXJzaW5nIHRoZSB0b2tlbiBzdHJlYW0gaW50byBBU1Qgbm9kZXMuXHJcbiAgICpcclxuICAgKiBAcmV0dXJucyBBcnJheSBvZiB0b3AtbGV2ZWwgQVNUIG5vZGVzXHJcbiAgICovXHJcbiAgcHVibGljIHBhcnNlKCk6IEFTVE5vZGVbXSB7XHJcbiAgICBjb25zdCBub2RlcyA9IG5ldyBBcnJheTxBU1ROb2RlPjtcclxuICAgIFxyXG4gICAgd2hpbGUgKHRoaXMuX2N1cnNvci5wZWVrKCkudHlwZSAhPT0gVG9rZW5UeXBlLkVPRikge1xyXG4gICAgICBjb25zdCBwYXJzZU5vZGUgPSB0aGlzLnBhcnNlTm9kZSgpO1xyXG4gICAgICBpZiAocGFyc2VOb2RlKSB7XHJcbiAgICAgICAgbm9kZXMucHVzaChwYXJzZU5vZGUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5vZGVzO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGFyc2VzIHRoZSBuZXh0IEFTVCBub2RlIGJhc2VkIG9uIHRoZSBjdXJyZW50IHRva2VuLlxyXG4gICAqXHJcbiAgICogQHJldHVybnMgUGFyc2VkIEFTVCBub2RlXHJcbiAgICogQHRocm93cyBFcnJvciBpZiBhbiB1bmV4cGVjdGVkIHRva2VuIGlzIGVuY291bnRlcmVkXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwYXJzZU5vZGUoKTogQVNUTm9kZSB8IHVuZGVmaW5lZCB7XHJcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuX2N1cnNvci5wZWVrKCk7XHJcbiAgICBpZiAodG9rZW4udHlwZSA9PT0gVG9rZW5UeXBlLkVPRikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBcclxuICAgIGNvbnN0IHN0YXRlID0gdGhpcy5fc3RhdGVzW3Rva2VuLnR5cGVdO1xyXG5cclxuICAgIGlmICghc3RhdGUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBbUGFyc2VyXSBObyB0cmFuc2l0aW9uIGZ1bmN0aW9uIGZvciB0b2tlbiB0eXBlICR7VG9rZW5UeXBlW3Rva2VuLnR5cGVdfWApO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBzdGF0ZSh0aGlzLl9jdXJzb3IsIHRoaXMucGFyc2VOb2RlLmJpbmQodGhpcyksIHRva2VuIGFzIG5ldmVyKTtcclxuICB9XHJcbn1cclxuIiwiLyoqXHJcbiAqIFRyYWNrcyBpZGVudGlmaWVyIHNjb3BlIGR1cmluZyByZW5kZXIgY29kZSBnZW5lcmF0aW9uLlxyXG4gKiBFYWNoIGBDb250ZXh0YCBpbnN0YW5jZSByZXByZXNlbnRzIG9uZSBsZXhpY2FsIHNjb3BlIChlLmcuIGEgYEBmb3JgIGxvb3AgYm9keSlcclxuICogYW5kIGNhbiBiZSBjaGFpbmVkIHRvIGEgcGFyZW50IGNvbnRleHQgZm9yIG91dGVyLXNjb3BlIHJlc29sdXRpb24uXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgQ29udGV4dCB7XHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhIG5ldyBzY29wZSBjb250ZXh0LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIF9pZGVudGlmaWVycyBMaXN0IG9mIGxvb3AgdmFyaWFibGUgbmFtZXMgZGVjbGFyZWQgaW4gdGhpcyBzY29wZS5cclxuICAgKiBAcGFyYW0gX3BhcmVudCBPcHRpb25hbCBwYXJlbnQgY29udGV4dCByZXByZXNlbnRpbmcgdGhlIGVuY2xvc2luZyBzY29wZS5cclxuICAgKi9cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgX2lkZW50aWZpZXJzID0gbmV3IEFycmF5PHN0cmluZz4sXHJcbiAgICBwcml2YXRlIF9wYXJlbnQ/OiBDb250ZXh0XHJcbiAgKSB7IH1cclxuXHJcbiAgcHVibGljIGFkZElkZW50aWZpZXIobmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5nZXRJZGVudGlmaWVyKG5hbWUpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSWRlbnRpZmllciBcIiR7bmFtZX1cIiBpcyBhbHJlYWR5IGRlY2xhcmVkIGluIHRoaXMgc2NvcGUuYCk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuX2lkZW50aWZpZXJzLnB1c2gobmFtZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSBpbm5lcm1vc3QgaWRlbnRpZmllciBpbiB0aGUgY3VycmVudCBzY29wZSBjaGFpbiwgb3JcclxuICAgKiBkZWxlZ2F0ZXMgdG8gdGhlIHBhcmVudCBjb250ZXh0IGlmIG5vbmUgaXMgZm91bmQgaW4gdGhpcyBzY29wZS5cclxuICAgKlxyXG4gICAqIEByZXR1cm5zIFRoZSBtb3N0IHJlY2VudGx5IGRlY2xhcmVkIGlkZW50aWZpZXIgbmFtZSwgb3IgYHVuZGVmaW5lZGAgaWYgbm9uZSBleGlzdHMuXHJcbiAgICovXHJcbiAgcHVibGljIGdldElkZW50aWZpZXIobmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIHJldHVybiB0aGlzLl9pZGVudGlmaWVycy5pbmNsdWRlcyhuYW1lKSA/IG5hbWUgOiB0aGlzLl9wYXJlbnQ/LmdldElkZW50aWZpZXIobmFtZSk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB0cywgeyBFeHByZXNzaW9uIH0gZnJvbSAndHlwZXNjcmlwdCc7XHJcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuLi9tb2RlbHMvcmVuZGVyLWNvbnRleHQubW9kZWwnO1xyXG5pbXBvcnQgeyBFbGVtZW50Tm9kZSB9IGZyb20gJy4uLy4uL3BhcnNlci90eXBlcy9ub2Rlcy9lbGVtZW50LW5vZGUudHlwZSc7XHJcblxyXG4vKipcclxuICogQ29tcGxldGUgc2V0IG9mIEphdmFTY3JpcHQgZ2xvYmFsIGlkZW50aWZpZXJzIHVwIHRvIEVTMjAyNi5cclxuICpcclxuICogVGhlc2UgYXJlIGlkZW50aWZpZXJzIHRoYXQgVHlwZVNjcmlwdCdzIHBhcnNlciBjbGFzc2lmaWVzIGFzXHJcbiAqIGBTeW50YXhLaW5kLklkZW50aWZpZXJgICh1bmxpa2UgdHJ1ZSBrZXl3b3JkcyBzdWNoIGFzIGB0eXBlb2ZgLFxyXG4gKiBgaW5zdGFuY2VvZmAsIGB0cnVlYCwgYGZhbHNlYCwgYG51bGxgIHdoaWNoIGhhdmUgdGhlaXIgb3duIFN5bnRheEtpbmQpXHJcbiAqIGJ1dCB0aGF0IG11c3QgbmV2ZXIgYmUgcHJlZml4ZWQgd2l0aCBgdGhpcy5gIGluc2lkZSBhIHRlbXBsYXRlIGV4cHJlc3Npb25cclxuICogYmVjYXVzZSB0aGV5IHJlZmVyIHRvIHdlbGwta25vd24gZ2xvYmFscywgbm90IHRvIGNvbXBvbmVudCBwcm9wZXJ0aWVzLlxyXG4gKlxyXG4gKiBPcmdhbmlzZWQgYnkgRUNNQVNjcmlwdCBjYXRlZ29yeSwgbWlycm9yaW5nIHRoZSBNRE4gXCJTdGFuZGFyZCBidWlsdC1pblxyXG4gKiBvYmplY3RzXCIgcmVmZXJlbmNlLCBwbHVzIHRoZSBFUzIwMjYgYWRkaXRpb25zIChUZW1wb3JhbCwgRGlzcG9zYWJsZVN0YWNrLFxyXG4gKiBBc3luY0Rpc3Bvc2FibGVTdGFjaywgU3VwcHJlc3NlZEVycm9yLCBNYXRoLnN1bVByZWNpc2Ugc3VyZmFjZSkuXHJcbiAqXHJcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHNcclxuICovXHJcbmV4cG9ydCBjb25zdCBHTE9CQUxfSURFTlRJRklFUlM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcclxuICAvLyAtLS0tIFZhbHVlIHByb3BlcnRpZXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgLy8gdHJ1ZSwgZmFsc2UsIG51bGwgYXJlIFN5bnRheEtpbmQga2V5d29yZHMg4oCUIG5vdCBuZWVkZWQgaGVyZS5cclxuICAndW5kZWZpbmVkJyxcclxuICAnTmFOJyxcclxuICAnSW5maW5pdHknLFxyXG4gICdnbG9iYWxUaGlzJyxcclxuIFxyXG4gIC8vIC0tLS0gR2xvYmFsIGZ1bmN0aW9ucyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnZXZhbCcsXHJcbiAgJ2lzRmluaXRlJyxcclxuICAnaXNOYU4nLFxyXG4gICdwYXJzZUZsb2F0JyxcclxuICAncGFyc2VJbnQnLFxyXG4gICdkZWNvZGVVUkknLFxyXG4gICdkZWNvZGVVUklDb21wb25lbnQnLFxyXG4gICdlbmNvZGVVUkknLFxyXG4gICdlbmNvZGVVUklDb21wb25lbnQnLFxyXG4gIC8vIERlcHJlY2F0ZWQgYnV0IHN0aWxsIElkZW50aWZpZXJzIGluIFRTXHJcbiAgJ2VzY2FwZScsXHJcbiAgJ3VuZXNjYXBlJyxcclxuIFxyXG4gIC8vIC0tLS0gRnVuZGFtZW50YWwgb2JqZWN0cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnT2JqZWN0JyxcclxuICAnRnVuY3Rpb24nLFxyXG4gICdCb29sZWFuJyxcclxuICAnU3ltYm9sJyxcclxuIFxyXG4gIC8vIC0tLS0gRXJyb3Igb2JqZWN0cyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnRXJyb3InLFxyXG4gICdBZ2dyZWdhdGVFcnJvcicsXHJcbiAgJ0V2YWxFcnJvcicsXHJcbiAgJ1JhbmdlRXJyb3InLFxyXG4gICdSZWZlcmVuY2VFcnJvcicsXHJcbiAgJ1N5bnRheEVycm9yJyxcclxuICAnVHlwZUVycm9yJyxcclxuICAnVVJJRXJyb3InLFxyXG4gICdTdXBwcmVzc2VkRXJyb3InLCAgICAgICAvLyBFUzIwMjYg4oCUIGV4cGxpY2l0IHJlc291cmNlIG1hbmFnZW1lbnRcclxuICAnSW50ZXJuYWxFcnJvcicsICAgICAgICAgLy8gTm9uLXN0YW5kYXJkIChGaXJlZm94KSBidXQgY29tbW9uXHJcbiBcclxuICAvLyAtLS0tIE51bWJlcnMgYW5kIGRhdGVzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgJ051bWJlcicsXHJcbiAgJ0JpZ0ludCcsXHJcbiAgJ01hdGgnLFxyXG4gICdEYXRlJyxcclxuICAnVGVtcG9yYWwnLCAgICAgICAgICAgICAgLy8gRVMyMDI2IOKAlCByZXBsYWNlcyBEYXRlXHJcbiBcclxuICAvLyAtLS0tIFRleHQgcHJvY2Vzc2luZyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgJ1N0cmluZycsXHJcbiAgJ1JlZ0V4cCcsXHJcbiBcclxuICAvLyAtLS0tIEluZGV4ZWQgY29sbGVjdGlvbnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgJ0FycmF5JyxcclxuICAnVHlwZWRBcnJheScsXHJcbiAgJ0ludDhBcnJheScsXHJcbiAgJ1VpbnQ4QXJyYXknLFxyXG4gICdVaW50OENsYW1wZWRBcnJheScsXHJcbiAgJ0ludDE2QXJyYXknLFxyXG4gICdVaW50MTZBcnJheScsXHJcbiAgJ0ludDMyQXJyYXknLFxyXG4gICdVaW50MzJBcnJheScsXHJcbiAgJ0JpZ0ludDY0QXJyYXknLFxyXG4gICdCaWdVaW50NjRBcnJheScsXHJcbiAgJ0Zsb2F0MTZBcnJheScsICAgICAgICAgIC8vIEVTMjAyNVxyXG4gICdGbG9hdDMyQXJyYXknLFxyXG4gICdGbG9hdDY0QXJyYXknLFxyXG4gXHJcbiAgLy8gLS0tLSBLZXllZCBjb2xsZWN0aW9ucyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICdNYXAnLFxyXG4gICdTZXQnLFxyXG4gICdXZWFrTWFwJyxcclxuICAnV2Vha1NldCcsXHJcbiBcclxuICAvLyAtLS0tIFN0cnVjdHVyZWQgZGF0YSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgJ0FycmF5QnVmZmVyJyxcclxuICAnU2hhcmVkQXJyYXlCdWZmZXInLFxyXG4gICdEYXRhVmlldycsXHJcbiAgJ0F0b21pY3MnLFxyXG4gICdKU09OJyxcclxuIFxyXG4gIC8vIC0tLS0gTWVtb3J5IG1hbmFnZW1lbnQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnV2Vha1JlZicsXHJcbiAgJ0ZpbmFsaXphdGlvblJlZ2lzdHJ5JyxcclxuIFxyXG4gIC8vIC0tLS0gQ29udHJvbCBhYnN0cmFjdGlvbnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnSXRlcmF0b3InLCAgICAgICAgICAgICAgLy8gRVMyMDI1XHJcbiAgJ0FzeW5jSXRlcmF0b3InLCAgICAgICAgIC8vIEVTMjAyNVxyXG4gICdQcm9taXNlJyxcclxuICAnR2VuZXJhdG9yRnVuY3Rpb24nLFxyXG4gICdBc3luY0dlbmVyYXRvckZ1bmN0aW9uJyxcclxuICAnR2VuZXJhdG9yJyxcclxuICAnQXN5bmNHZW5lcmF0b3InLFxyXG4gICdBc3luY0Z1bmN0aW9uJyxcclxuICAnRGlzcG9zYWJsZVN0YWNrJywgICAgICAgLy8gRVMyMDI2IOKAlCBleHBsaWNpdCByZXNvdXJjZSBtYW5hZ2VtZW50XHJcbiAgJ0FzeW5jRGlzcG9zYWJsZVN0YWNrJywgIC8vIEVTMjAyNiDigJQgZXhwbGljaXQgcmVzb3VyY2UgbWFuYWdlbWVudFxyXG4gXHJcbiAgLy8gLS0tLSBSZWZsZWN0aW9uIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICdSZWZsZWN0JyxcclxuICAnUHJveHknLFxyXG4gXHJcbiAgLy8gLS0tLSBJbnRlcm5hdGlvbmFsaXphdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICdJbnRsJyxcclxuIFxyXG4gIC8vIC0tLS0gV2ViQXNzZW1ibHkgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAnV2ViQXNzZW1ibHknLFxyXG4gXHJcbiAgLy8gLS0tLSBCcm93c2VyIC8gRE9NIGdsb2JhbHMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gIC8vIFRoZXNlIGFyZSBub3QgcGFydCBvZiB0aGUgRUNNQVNjcmlwdCBzcGVjIGJ1dCBhcmUgdW5pdmVyc2FsbHkgYXZhaWxhYmxlXHJcbiAgLy8gaW4gYnJvd3NlciBlbnZpcm9ubWVudHMgYW5kIG11c3Qgbm90IGJlIHRyZWF0ZWQgYXMgY29tcG9uZW50IHByb3BlcnRpZXMuXHJcbiAgJ3dpbmRvdycsXHJcbiAgJ2RvY3VtZW50JyxcclxuICAnbmF2aWdhdG9yJyxcclxuICAnbG9jYXRpb24nLFxyXG4gICdoaXN0b3J5JyxcclxuICAnc2NyZWVuJyxcclxuICAnY29uc29sZScsXHJcbiAgJ3BlcmZvcm1hbmNlJyxcclxuICAnY3J5cHRvJyxcclxuICAnZmV0Y2gnLFxyXG4gICdhbGVydCcsXHJcbiAgJ2NvbmZpcm0nLFxyXG4gICdwcm9tcHQnLFxyXG4gICdzZXRUaW1lb3V0JyxcclxuICAnc2V0SW50ZXJ2YWwnLFxyXG4gICdjbGVhclRpbWVvdXQnLFxyXG4gICdjbGVhckludGVydmFsJyxcclxuICAncmVxdWVzdEFuaW1hdGlvbkZyYW1lJyxcclxuICAnY2FuY2VsQW5pbWF0aW9uRnJhbWUnLFxyXG4gICdxdWV1ZU1pY3JvdGFzaycsXHJcbiAgJ3N0cnVjdHVyZWRDbG9uZScsXHJcbiAgJ1VSTCcsXHJcbiAgJ1VSTFNlYXJjaFBhcmFtcycsXHJcbiAgJ0Zvcm1EYXRhJyxcclxuICAnSGVhZGVycycsXHJcbiAgJ1JlcXVlc3QnLFxyXG4gICdSZXNwb25zZScsXHJcbiAgJ0Fib3J0Q29udHJvbGxlcicsXHJcbiAgJ0Fib3J0U2lnbmFsJyxcclxuICAnQ3VzdG9tRXZlbnQnLFxyXG4gICdFdmVudCcsXHJcbiAgJ0V2ZW50VGFyZ2V0JyxcclxuICAnTXV0YXRpb25PYnNlcnZlcicsXHJcbiAgJ0ludGVyc2VjdGlvbk9ic2VydmVyJyxcclxuICAnUmVzaXplT2JzZXJ2ZXInLFxyXG4gICdQZXJmb3JtYW5jZU9ic2VydmVyJyxcclxuICAnV29ya2VyJyxcclxuICAnU2hhcmVkV29ya2VyJyxcclxuICAnU2VydmljZVdvcmtlcicsXHJcbiAgJ0Jsb2InLFxyXG4gICdGaWxlJyxcclxuICAnRmlsZVJlYWRlcicsXHJcbiAgJ1JlYWRhYmxlU3RyZWFtJyxcclxuICAnV3JpdGFibGVTdHJlYW0nLFxyXG4gICdUcmFuc2Zvcm1TdHJlYW0nLFxyXG4gICdUZXh0RW5jb2RlcicsXHJcbiAgJ1RleHREZWNvZGVyJyxcclxuICAnSW1hZ2VEYXRhJyxcclxuICAnQ2FudmFzJyxcclxuICAnU3RvcmFnZScsXHJcbiAgJ2xvY2FsU3RvcmFnZScsXHJcbiAgJ3Nlc3Npb25TdG9yYWdlJyxcclxuICAnaW5kZXhlZERCJyxcclxuICAnV2ViU29ja2V0JyxcclxuICAnWE1MSHR0cFJlcXVlc3QnLFxyXG4gXHJcbiAgLy8gLS0tLSBET00gZWxlbWVudCBjb25zdHJ1Y3RvcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gIC8vIENvbW1vbmx5IHVzZWQgd2l0aCBpbnN0YW5jZW9mIGluIHRlbXBsYXRlIGV4cHJlc3Npb25zLlxyXG4gICdIVE1MRWxlbWVudCcsXHJcbiAgJ0hUTUxJbnB1dEVsZW1lbnQnLFxyXG4gICdIVE1MQnV0dG9uRWxlbWVudCcsXHJcbiAgJ0hUTUxGb3JtRWxlbWVudCcsXHJcbiAgJ0hUTUxBbmNob3JFbGVtZW50JyxcclxuICAnSFRNTEltYWdlRWxlbWVudCcsXHJcbiAgJ0hUTUxWaWRlb0VsZW1lbnQnLFxyXG4gICdIVE1MQXVkaW9FbGVtZW50JyxcclxuICAnSFRNTENhbnZhc0VsZW1lbnQnLFxyXG4gICdIVE1MU2VsZWN0RWxlbWVudCcsXHJcbiAgJ0hUTUxUZXh0QXJlYUVsZW1lbnQnLFxyXG4gICdIVE1MRGl2RWxlbWVudCcsXHJcbiAgJ0hUTUxTcGFuRWxlbWVudCcsXHJcbiAgJ0hUTUxQYXJhZ3JhcGhFbGVtZW50JyxcclxuICAnSFRNTEhlYWRpbmdFbGVtZW50JyxcclxuICAnSFRNTFRhYmxlRWxlbWVudCcsXHJcbiAgJ0hUTUxUYWJsZVJvd0VsZW1lbnQnLFxyXG4gICdIVE1MVGFibGVDZWxsRWxlbWVudCcsXHJcbiAgJ0hUTUxVTGlzdEVsZW1lbnQnLFxyXG4gICdIVE1MT0xpc3RFbGVtZW50JyxcclxuICAnSFRNTExJRWxlbWVudCcsXHJcbiAgJ0hUTUxMYWJlbEVsZW1lbnQnLFxyXG4gICdIVE1MRGlhbG9nRWxlbWVudCcsXHJcbiAgJ0hUTUxEZXRhaWxzRWxlbWVudCcsXHJcbiAgJ0hUTUxTbG90RWxlbWVudCcsXHJcbiAgJ0hUTUxUZW1wbGF0ZUVsZW1lbnQnLFxyXG4gICdTVkdFbGVtZW50JyxcclxuICAnU1ZHU1ZHRWxlbWVudCcsXHJcbiAgJ0VsZW1lbnQnLFxyXG4gICdOb2RlJyxcclxuICAnTm9kZUxpc3QnLFxyXG4gICdEb2N1bWVudEZyYWdtZW50JyxcclxuICAnU2hhZG93Um9vdCcsXHJcbiAgJ0RvY3VtZW50JyxcclxuICAnV2luZG93JyxcclxuXSk7XHJcblxyXG5leHBvcnQgY29uc3QgUk9PVF9OT0RFID0gJ3RoaXMuX3Jvb3QnO1xyXG5cclxuLyoqXHJcbiAqIFJlc29sdmVzIHJlZmVyZW5jZXMgdG8gY29tcG9uZW50IHByb3BlcnRpZXMgaW5zaWRlIGEgdGVtcGxhdGUgZXhwcmVzc2lvbi5cclxuICpcclxuICogSWRlbnRpZmllcnMgdGhhdCBhcmUgbm90IGZvdW5kIGluIHRoZSBhY3RpdmUgc2NvcGUgY2hhaW4gYW5kIGFyZSBub3RcclxuICogd2VsbC1rbm93biBnbG9iYWxzIGFyZSBwcmVmaXhlZCB3aXRoIGB0aGlzLmAgc28gdGhleSByZXNvbHZlIGFnYWluc3RcclxuICogdGhlIGNvbXBvbmVudCBpbnN0YW5jZSBhdCBydW50aW1lLlxyXG4gKlxyXG4gKiBUaGUgb3JpZ2luYWwgZm9ybWF0dGluZyBvZiB0aGUgZXhwcmVzc2lvbiDigJQgcGFyZW50aGVzZXMsIHNwYWNpbmcsXHJcbiAqIG9wZXJhdG9yIHRva2VucywgbWVtYmVyIGFjY2VzcyBkb3RzIOKAlCBpcyBwcmVzZXJ2ZWQgdmVyYmF0aW0gYnkgZGVsZWdhdGluZ1xyXG4gKiB0byBgbm9kZS5nZXRUZXh0KClgIGZvciBhbnkgc3VidHJlZSB0aGF0IGNvbnRhaW5zIG5vIHJlc29sdmFibGUgaWRlbnRpZmllcnMuXHJcbiAqXHJcbiAqIEBwYXJhbSBleHByZXNzaW9uIC0gRWl0aGVyIGEgcmF3IGlkZW50aWZpZXIgc3RyaW5nIG9yIGEgdmFsaWRhdGVkXHJcbiAqICAgYHRzLkV4cHJlc3Npb25gIG5vZGUgcHJvZHVjZWQgYnkgYHZhbGlkYXRlRXhwcmVzc2lvbmAuXHJcbiAqIEBwYXJhbSBjb250ZXh0IC0gVGhlIGFjdGl2ZSB0ZW1wbGF0ZSBzY29wZSBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBUaGUgcmVzb2x2ZWQgZXhwcmVzc2lvbiBhcyBhIEphdmFTY3JpcHQgc3RyaW5nIHJlYWR5IGZvciBjb2RlZ2VuLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKiAvLyBTaW1wbGUgaWRlbnRpZmllclxyXG4gKiByZXNvbHZlRXhwcmVzc2lvbignaXRlbXMnLCBjb250ZXh0KSAvLyDihpIgJ3RoaXMuaXRlbXMnXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIC8vIENvbXBsZXggZXhwcmVzc2lvbiDigJQgZm9ybWF0dGluZyBwcmVzZXJ2ZWRcclxuICogcmVzb2x2ZUV4cHJlc3Npb24obm9kZSwgY29udGV4dClcclxuICogLy8gdHlwZW9mIGlkICE9PSAnYm9vbGVhbicgfHwgcGlwcG8gaW5zdGFuY2VvZiBIVE1MRWxlbWVudFxyXG4gKiAvLyDihpIgdHlwZW9mIHRoaXMuaWQgIT09ICdib29sZWFuJyB8fCB0aGlzLnBpcHBvIGluc3RhbmNlb2YgSFRNTEVsZW1lbnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlRXhwcmVzc2lvbihleHByZXNzaW9uOiBzdHJpbmcgfCBFeHByZXNzaW9uLCBjb250ZXh0OiBDb250ZXh0KTogc3RyaW5nIHtcclxuICByZXR1cm4gdHlwZW9mIGV4cHJlc3Npb24gPT09ICdzdHJpbmcnXHJcbiAgICA/IGNvbnRleHQuZ2V0SWRlbnRpZmllcihleHByZXNzaW9uKSA/PyBgdGhpcy4ke2V4cHJlc3Npb259YFxyXG4gICAgOiBlbWl0Tm9kZShleHByZXNzaW9uLCBleHByZXNzaW9uLCBjb250ZXh0KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEVtaXRzIHRoZSByZXNvbHZlZCB0ZXh0IGZvciBhIG5vZGUuXHJcbiAqXHJcbiAqIC0gSWYgdGhlIG5vZGUgaGFzIG5vIHJlc29sdmFibGUgaWRlbnRpZmllcnMgaW4gaXRzIHN1YnRyZWUsIGVtaXRzXHJcbiAqICAgYG5vZGUuZ2V0VGV4dCgpYCB2ZXJiYXRpbSDigJQgcHJlc2VydmluZyBhbGwgb3JpZ2luYWwgc3BhY2luZyxcclxuICogICBwYXJlbnRoZXNlcywgZG90cywgYW5kIHB1bmN0dWF0aW9uLlxyXG4gKiAtIElmIHRoZSBub2RlIGlzIGEgcmVzb2x2YWJsZSBJZGVudGlmaWVyLCBlbWl0cyB0aGUgcmVzb2x2ZWQgbmFtZS5cclxuICogLSBPdGhlcndpc2UgcmVjdXJzZXMgaW50byBjaGlsZHJlbiBhbmQgY29uY2F0ZW5hdGVzIHRoZWlyIG91dHB1dC5cclxuICovXHJcbmZ1bmN0aW9uIGVtaXROb2RlKG5vZGU6IHRzLk5vZGUsIHBhcmVudDogdHMuTm9kZSwgY29udGV4dDogQ29udGV4dCk6IHN0cmluZyB7XHJcbiAgLy8gTGVhZiBJZGVudGlmaWVyIHRoYXQgbmVlZHMgcmVzb2x1dGlvblxyXG4gIGlmICh0cy5pc0lkZW50aWZpZXIobm9kZSkgJiYgbmVlZHNSZXNvbHV0aW9uKG5vZGUsIHBhcmVudCkpIHtcclxuICAgIHJldHVybiBjb250ZXh0LmdldElkZW50aWZpZXIobm9kZS50ZXh0KSA/PyBgdGhpcy4ke25vZGUudGV4dH1gO1xyXG4gIH1cclxuXHJcbiAgLy8gTm8gcmVzb2x2YWJsZSBpZGVudGlmaWVycyBpbiB0aGlzIHN1YnRyZWUg4oCUIGVtaXQgdmVyYmF0aW1cclxuICBpZiAoIWNvbnRhaW5zUmVzb2x2YWJsZUlkZW50aWZpZXIobm9kZSwgcGFyZW50KSkge1xyXG4gICAgcmV0dXJuIG5vZGUuZ2V0VGV4dCgpO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgIEhhcyByZXNvbHZhYmxlIGlkZW50aWZpZXJzIOKAlCByZWN1cnNlIGludG8gY2hpbGRyZW4gYW5kIGNvbmNhdGVuYXRlLlxyXG4gICAgV2UgdXNlIHRoZSBvcmlnaW5hbCBzb3VyY2UgcG9zaXRpb25zIHRvIHJlY29uc3RydWN0IHNwYWNpbmcgYmV0d2VlblxyXG4gICAgY2hpbGRyZW4gZmFpdGhmdWxseSBpbnN0ZWFkIG9mIGpvaW5pbmcgd2l0aCBhIGZpeGVkIHNlcGFyYXRvci5cclxuICAqL1xyXG4gIGNvbnN0IHNvdXJjZVRleHQgPSBub2RlLmdldFNvdXJjZUZpbGUoKS50ZXh0O1xyXG4gIGxldCByZXN1bHQgPSAnJztcclxuICBsZXQgbGFzdEVuZCA9IG5vZGUuZ2V0U3RhcnQoKTtcclxuXHJcbiAgdHMuZm9yRWFjaENoaWxkKG5vZGUsIGNoaWxkID0+IHtcclxuICAgIHJlc3VsdCA9IGAke3Jlc3VsdH0ke3NvdXJjZVRleHQuc2xpY2UobGFzdEVuZCwgY2hpbGQuZ2V0U3RhcnQoKSl9JHtlbWl0Tm9kZShjaGlsZCwgbm9kZSwgY29udGV4dCl9YDtcclxuICAgIGxhc3RFbmQgPSBjaGlsZC5nZXRFbmQoKTtcclxuICB9KTtcclxuXHJcbiAgLy8gQXBwZW5kIGFueSB0cmFpbGluZyB0ZXh0IGFmdGVyIHRoZSBsYXN0IGNoaWxkIChlLmcuIGNsb3NpbmcgcGFyZW4pXHJcbiAgcmV0dXJuIGAke3Jlc3VsdH0ke3NvdXJjZVRleHQuc2xpY2UobGFzdEVuZCwgbm9kZS5nZXRFbmQoKSl9YDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3VidHJlZSByb290ZWQgYXQgYG5vZGVgIGNvbnRhaW5zIGF0IGxlYXN0IG9uZVxyXG4gKiBJZGVudGlmaWVyIHRoYXQgbmVlZHMgY29udGV4dCByZXNvbHV0aW9uLlxyXG4gKlxyXG4gKiBTaG9ydC1jaXJjdWl0cyBhcyBzb29uIGFzIG9uZSBpcyBmb3VuZCB0byBhdm9pZCB2aXNpdGluZyB0aGUgd2hvbGUgdHJlZS5cclxuICovXHJcbmZ1bmN0aW9uIGNvbnRhaW5zUmVzb2x2YWJsZUlkZW50aWZpZXIobm9kZTogdHMuTm9kZSwgcGFyZW50OiB0cy5Ob2RlKTogYm9vbGVhbiB7XHJcbiBpZiAodHMuaXNJZGVudGlmaWVyKG5vZGUpICYmIG5lZWRzUmVzb2x1dGlvbihub2RlLCBwYXJlbnQpKSB7XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIGxldCBmb3VuZCA9IGZhbHNlO1xyXG5cclxuICB0cy5mb3JFYWNoQ2hpbGQobm9kZSwgY2hpbGQgPT4ge1xyXG4gICAgaWYgKCFmb3VuZCkge1xyXG4gICAgICBmb3VuZCA9IGNvbnRhaW5zUmVzb2x2YWJsZUlkZW50aWZpZXIoY2hpbGQsIG5vZGUpO1xyXG4gICAgfVxyXG4gIH0pO1xyXG5cclxuICByZXR1cm4gZm91bmQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGlkZW50aWZpZXIgbmVlZHMgdG8gYmUgcmVzb2x2ZWQgYWdhaW5zdCB0aGUgY29udGV4dFxyXG4gKiBvciBwcmVmaXhlZCB3aXRoIGB0aGlzLmAg4oCUIGkuZS4gaXQgaXMgbm90IGEgZ2xvYmFsL2J1aWx0aW4gaWRlbnRpZmllclxyXG4gKiBhbmQgbm90IHRoZSBwcm9wZXJ0eS1uYW1lIHNpZGUgb2YgYSBtZW1iZXIgYWNjZXNzIGV4cHJlc3Npb24uXHJcbiAqL1xyXG5mdW5jdGlvbiBuZWVkc1Jlc29sdXRpb24obm9kZTogdHMuSWRlbnRpZmllciwgcGFyZW50OiB0cy5Ob2RlKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuICEoKHRzLmlzUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKHBhcmVudCkgJiYgcGFyZW50Lm5hbWUgPT09IG5vZGUpIHx8IEdMT0JBTF9JREVOVElGSUVSUy5oYXMobm9kZS50ZXh0KSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgdmFyaWFibGUgbmFtZSBmb3IgYW4gZWxlbWVudCBiYXNlZCBvbiBpdHMgdGFnIG5hbWUgYW5kIHBhcmVudCBub2RlLlxyXG4gKiBJZiB0aGUgcGFyZW50IG5vZGUgaXMgJ3RoaXMuX3Jvb3QnLCB0aGUgaWRlbnRpZmllciB3aWxsIGJlIGJhc2VkIHNvbGVseSBvbiB0aGUgZWxlbWVudCdzIHR5cGUuXHJcbiAqIE90aGVyd2lzZSwgaXQgd2lsbCBiZSBwcmVmaXhlZCB3aXRoIHRoZSBwYXJlbnQgbm9kZSdzIG5hbWUgdG8gZW5zdXJlIHVuaXF1ZW5lc3MuXHJcbiAqIEBwYXJhbSBub2RlIFRoZSBFbGVtZW50Tm9kZSBmb3Igd2hpY2ggdG8gZ2VuZXJhdGUgdGhlIGlkZW50aWZpZXIuXHJcbiAqIEBwYXJhbSBwYXJlbnROb2RlICBUaGUgbmFtZSBvZiB0aGUgcGFyZW50IG5vZGUgdG8gZW5zdXJlIHVuaXF1ZW5lc3MgaW4gdGhlIGNvbnRleHQgb2YgbmVzdGVkIGVsZW1lbnRzLlxyXG4gKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHVuaXF1ZSB2YXJpYWJsZSBuYW1lIGZvciB0aGUgZWxlbWVudC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRFbGVtZW50SWRlbnRpZmllcihub2RlOiBFbGVtZW50Tm9kZSwgcGFyZW50Tm9kZTogc3RyaW5nLCBpbmRleDogc3RyaW5nKTogc3RyaW5nIHtcclxuICBjb25zdCBpZGVudGlmaWVyID0gcGFyZW50Tm9kZSAhPT0gUk9PVF9OT0RFID8gYCR7cGFyZW50Tm9kZX1fJHtub2RlLnRhZ05hbWV9JHtpbmRleH1gIDogYCR7bm9kZS50YWdOYW1lfSR7aW5kZXh9YDtcclxuICByZXR1cm4gaWRlbnRpZmllci5yZXBsYWNlKC8tL2csICdfJyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRUZXh0SWRlbnRpZmllcihwYXJlbnROb2RlOiBzdHJpbmcsIGluZGV4OiBzdHJpbmcsIHByZWZpeCA9ICd0ZXh0Jyk6IHN0cmluZyB7XHJcbiAgY29uc3QgaWRlbnRpZmllciA9IHBhcmVudE5vZGUgIT09IFJPT1RfTk9ERSA/IGAke3BhcmVudE5vZGV9XyR7cHJlZml4fSR7aW5kZXh9YCA6IGAke3ByZWZpeH0ke2luZGV4fWA7XHJcbiAgcmV0dXJuIGlkZW50aWZpZXIucmVwbGFjZSgvLS9nLCAnXycpO1xyXG59XHJcblxyXG4iLCJpbXBvcnQgeyBDb25zdERlY2xhcmF0aW9uTm9kZSB9IGZyb20gJy4uLy4uL3BhcnNlci90eXBlcy9ub2Rlcy9jb25zdC1kZWNsYXJhdGlvbi1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSAnLi4vbW9kZWxzL3JlbmRlci1jb250ZXh0Lm1vZGVsLmpzJztcclxuaW1wb3J0IHsgcmVzb2x2ZUV4cHJlc3Npb24gfSBmcm9tICcuLi91dGlscy9yZW5kZXItZ2VuZXJhdG9yLnV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgY29kZSBmb3IgYSBgQGNvbnN0YCBkZWNsYXJhdGlvbiBub2RlLlxyXG4gKiBFbWl0cyBhIGBjb25zdCBuYW1lID0gZXhwcmVzc2lvbjtgIEphdmFTY3JpcHQgc3RhdGVtZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBUaGUgYENvbnN0RGVjbGFyYXRpb25Ob2RlYCB0byBwcm9jZXNzLlxyXG4gKiBAcGFyYW0gX25vZGVOYW1lIFVudXNlZCBub2RlIG5hbWUuXHJcbiAqIEBwYXJhbSBfcGFyZW50Tm9kZSBVbnVzZWQgcGFyZW50IG5vZGUgbmFtZS5cclxuICogQHBhcmFtIF9jb250ZXh0IFVudXNlZCByZW5kZXIgY29udGV4dC5cclxuICogQHJldHVybnMgQXJyYXkgY29udGFpbmluZyB0aGUgZ2VuZXJhdGVkIGNvbnN0IHN0YXRlbWVudCBzdHJpbmcuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0NvbnN0RGVjbGFyYXRpb24obm9kZTogQ29uc3REZWNsYXJhdGlvbk5vZGUsIF9ub2RlTmFtZTogc3RyaW5nLCBfcGFyZW50Tm9kZTogc3RyaW5nLCBjb250ZXh0OiBDb250ZXh0KTogc3RyaW5nW10ge1xyXG4gIGNvbnRleHQuYWRkSWRlbnRpZmllcihub2RlLnZhck5hbWUpO1xyXG4gIFxyXG4gIHJldHVybiBbXHJcbiAgICBgY29uc3QgJHtub2RlLnZhck5hbWV9ID0gJHtyZXNvbHZlRXhwcmVzc2lvbihub2RlLmV4cHJlc3Npb24sIGNvbnRleHQpfTtgXHJcbiAgXTtcclxufVxyXG4iLCJpbXBvcnQgeyBFbGVtZW50Tm9kZSB9IGZyb20gJy4uLy4uL3BhcnNlci90eXBlcy9ub2Rlcy9lbGVtZW50LW5vZGUudHlwZS5qcyc7XHJcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuLi9tb2RlbHMvcmVuZGVyLWNvbnRleHQubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBwcm9jZXNzTm9kZSB9IGZyb20gJy4uL3JlbmRlci1nZW5lcmF0b3IuanMnO1xyXG5pbXBvcnQgeyBnZXRFbGVtZW50SWRlbnRpZmllciwgcmVzb2x2ZUV4cHJlc3Npb24gfSBmcm9tICcuLi91dGlscy9yZW5kZXItZ2VuZXJhdG9yLnV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgY29kZSBmb3IgYW4gSFRNTCBlbGVtZW50IG5vZGU6IGNyZWF0ZXMgdGhlIERPTSBlbGVtZW50LCBzZXRzIGF0dHJpYnV0ZXMsXHJcbiAqIGF0dGFjaGVzIGV2ZW50IGxpc3RlbmVycywgYXBwZW5kcyBpdCB0byB0aGUgcGFyZW50LCBhbmQgcmVjdXJzaXZlbHkgcHJvY2Vzc2VzIGNoaWxkcmVuLlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSBUaGUgYEVsZW1lbnROb2RlYCB0byBwcm9jZXNzLlxyXG4gKiBAcGFyYW0gbm9kZU5hbWUgVmFyaWFibGUgbmFtZSB0byB1c2UgZm9yIHRoZSBjcmVhdGVkIERPTSBlbGVtZW50LlxyXG4gKiBAcGFyYW0gcGFyZW50Tm9kZSBWYXJpYWJsZSBuYW1lIG9mIHRoZSBwYXJlbnQgRE9NIG5vZGUgdG8gYXBwZW5kIHRvLlxyXG4gKiBAcGFyYW0gY29udGV4dCBDdXJyZW50IHJlbmRlciBzY29wZSBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBBcnJheSBvZiBnZW5lcmF0ZWQgY29kZSBsaW5lcy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBwcm9jZXNzRWxlbWVudChub2RlOiBFbGVtZW50Tm9kZSwgbm9kZU5hbWU6IHN0cmluZywgcGFyZW50Tm9kZTogc3RyaW5nLCBjb250ZXh0OiBDb250ZXh0KTogc3RyaW5nW10ge1xyXG4gIGNvbnN0IGNoaWxkcmVuQ29udGV4dCA9IG5ldyBDb250ZXh0KFtdLCBjb250ZXh0KTtcclxuICBjb25zdCB0YWdOYW1lID0gbm9kZS50YWdOYW1lO1xyXG5cclxuICByZXR1cm4gW1xyXG4gICAgYGNvbnN0ICR7bm9kZU5hbWV9ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIiR7dGFnTmFtZX1cIik7YCxcclxuICAgIC4uLihub2RlLmF0dHJpYnV0ZXM/Lm1hcChhdHRyID0+IHtcclxuICAgICAgY29uc3QgdmFsdWUgPSBhdHRyLnZhbHVlO1xyXG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIFxyXG4gICAgICAgID8gYCR7bm9kZU5hbWV9LnNldEF0dHJpYnV0ZSgnJHthdHRyLm5hbWV9JywgJHt2YWx1ZX0pO2BcclxuICAgICAgICA6IGBlZmZlY3QoKCkgPT4gJHtub2RlTmFtZX0uc2V0QXR0cmlidXRlKCcke2F0dHIubmFtZX0nLCAke3Jlc29sdmVFeHByZXNzaW9uKHZhbHVlLmV4cHJlc3Npb24sIGNvbnRleHQpfSkpO2BcclxuICAgIH0pIHx8IFtdKSxcclxuICAgIC4uLihub2RlLmV2ZW50cz8ubWFwKGV2ZW50ID0+IGAke25vZGVOYW1lfS5hZGRFdmVudExpc3RlbmVyKFwiJHtldmVudC5uYW1lfVwiLCAoJGV2ZW50KSA9PiB0aGlzLiR7ZXZlbnQuaGFuZGxlcn0pO2ApIHx8IFtdKSxcclxuICAgIGAke3BhcmVudE5vZGV9LmFwcGVuZENoaWxkKCR7bm9kZU5hbWV9KTtgLFxyXG4gICAgLi4uKG5vZGUuY2hpbGRyZW4ubWFwKChjaGlsZCwgaSkgPT4gcHJvY2Vzc05vZGUoY2hpbGQsIGkudG9TdHJpbmcoKSwgbm9kZU5hbWUsIGNoaWxkcmVuQ29udGV4dCkpLmZsYXQoKSlcclxuICBdO1xyXG59XHJcbiIsImltcG9ydCB7IGluZGVudCB9IGZyb20gJ0B4YWVuZGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEZvckltcGxpY2l0VmFyaWFibGVzIH0gZnJvbSAnLi4vLi4vcGFyc2VyL3R5cGVzL25vZGVzL2Zvci1pbXBsaWNpdC12YXJpYWJsZXMuanMnO1xyXG5pbXBvcnQgeyBGb3JOb2RlIH0gZnJvbSAnLi4vLi4vcGFyc2VyL3R5cGVzL25vZGVzL2Zvci1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSAnLi4vbW9kZWxzL3JlbmRlci1jb250ZXh0Lm1vZGVsLmpzJztcclxuaW1wb3J0IHsgcHJvY2Vzc05vZGUgfSBmcm9tICcuLi9yZW5kZXItZ2VuZXJhdG9yLmpzJztcclxuaW1wb3J0IHsgZ2V0VGV4dElkZW50aWZpZXIgfSBmcm9tICcuLi91dGlscy9yZW5kZXItZ2VuZXJhdG9yLnV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgY29kZSBmb3IgYSBgQGZvcmAgaXRlcmF0aW9uIG5vZGUuXHJcbiAqXHJcbiAqIEVtaXRzIGEgY2xhc3NpYyBpbmRleC1iYXNlZCBgZm9yYCBsb29wIHdpdGggYWxsIGltcGxpY2l0IHZhcmlhYmxlc1xyXG4gKiBkZWNsYXJlZCBhdCB0aGUgdG9wIG9mIHRoZSBsb29wIGJvZHk6XHJcbiAqXHJcbiAqIGBgYGphdmFzY3JpcHRcclxuICogZm9yIChsZXQgJGkgPSAwOyAkaSA8IGN0eF9pdGVtcy5sZW5ndGg7ICRpKyspIHtcclxuICogICBjb25zdCBpdGVtID0gaXRlbXNbJGldO1xyXG4gKiAgIGNvbnN0ICRpbmRleCA9ICRpO1xyXG4gKiAgIGNvbnN0ICRmaXJzdCA9ICRpID09PSAwO1xyXG4gKiAgIGNvbnN0ICRsYXN0ICA9ICRpID09PSBpdGVtcy5sZW5ndGggLSAxO1xyXG4gKiAgIGNvbnN0ICRldmVuICA9ICRpICUgMiA9PT0gMDtcclxuICogICBjb25zdCAkb2RkICAgPSAkaSAlIDIgIT09IDA7XHJcbiAqICAgLy8gLi4uIGNoaWxkIG5vZGVzXHJcbiAqIH1cclxuICogYGBgXHJcbiAqXHJcbiAqIFRoZSBpdGVyYWJsZSBpZGVudGlmaWVyIGlzIHJlc29sdmVkIHRocm91Z2ggdGhlIGFjdGl2ZSB7QGxpbmsgQ29udGV4dH06XHJcbiAqIGlmIGZvdW5kIGluIHNjb3BlIGl0IGlzIHVzZWQgYXMtaXMsIG90aGVyd2lzZSBgdGhpcy5gIGlzIHByZXBlbmRlZC5cclxuICpcclxuICogVGhlIGludGVybmFsIGxvb3AgY291bnRlciBpcyBhbHdheXMgbmFtZWQgYCRpXzxub2RlTmFtZT5gIHRvIGF2b2lkXHJcbiAqIGNvbGxpc2lvbnMgd2hlbiBgQGZvcmAgYmxvY2tzIGFyZSBuZXN0ZWQuXHJcbiAqXHJcbiAqIEBwYXJhbSBub2RlIC0gVGhlIGBGb3JOb2RlYCB0byBwcm9jZXNzLlxyXG4gKiBAcGFyYW0gbm9kZU5hbWUgLSBCYXNlIHZhcmlhYmxlIG5hbWUgcHJlZml4IHVzZWQgZm9yIGNoaWxkIG5vZGVzIGFuZFxyXG4gKiAgIHRvIHByb2R1Y2UgYSB1bmlxdWUgbG9vcCBjb3VudGVyIGlkZW50aWZpZXIuXHJcbiAqIEBwYXJhbSBwYXJlbnROb2RlIC0gVmFyaWFibGUgbmFtZSBvZiB0aGUgcGFyZW50IERPTSBub2RlLlxyXG4gKiBAcGFyYW0gcGFyZW50Q29udGV4dCAtIFRoZSBlbmNsb3Npbmcgc2NvcGUgY29udGV4dC5cclxuICogQHJldHVybnMgQXJyYXkgb2YgZ2VuZXJhdGVkIGNvZGUgbGluZXMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0Zvcihub2RlOiBGb3JOb2RlLCBub2RlTmFtZTogc3RyaW5nLCBwYXJlbnROb2RlOiBzdHJpbmcsIHBhcmVudENvbnRleHQ6IENvbnRleHQpOiBzdHJpbmdbXSB7XHJcbiAgY29uc3QgaXRlcmFibGVTb3VyY2UgPSBub2RlLml0ZXJhYmxlU291cmNlO1xyXG4gIGNvbnN0IGl0ZXJhYmxlRXhwciA9IHBhcmVudENvbnRleHQuZ2V0SWRlbnRpZmllcihpdGVyYWJsZVNvdXJjZSkgPz8gYHRoaXMuJHtpdGVyYWJsZVNvdXJjZX1gO1xyXG5cclxuICBjb25zdCBpdGVtc05hbWUgPSBnZXRUZXh0SWRlbnRpZmllcihwYXJlbnROb2RlLCBub2RlTmFtZSwgJ2l0ZW1zJyk7XHJcbiAgY29uc3QgY291bnRlck5hbWUgPSBnZXRUZXh0SWRlbnRpZmllcihwYXJlbnROb2RlLCBub2RlTmFtZSwgJ2knKTtcclxuXHJcbiAgY29uc3QgaW5kZXhOYW1lID0gcmVzb2x2ZUltcGxpY2l0KG5vZGUsICckaW5kZXgnKTtcclxuICBjb25zdCBmaXJzdE5hbWUgPSByZXNvbHZlSW1wbGljaXQobm9kZSwgJyRmaXJzdCcpO1xyXG4gIGNvbnN0IGxhc3ROYW1lID0gcmVzb2x2ZUltcGxpY2l0KG5vZGUsICckbGFzdCcpO1xyXG4gIGNvbnN0IGV2ZW5OYW1lID0gcmVzb2x2ZUltcGxpY2l0KG5vZGUsICckZXZlbicpO1xyXG4gIGNvbnN0IG9kZE5hbWUgPSByZXNvbHZlSW1wbGljaXQobm9kZSwgJyRvZGQnKTtcclxuICBjb25zdCBmb3JDb250ZXh0ID0gbmV3IENvbnRleHQoW25vZGUuaXRlbUFsaWFzLCBpbmRleE5hbWUsIGZpcnN0TmFtZSwgbGFzdE5hbWUsIGV2ZW5OYW1lLCBvZGROYW1lXSwgcGFyZW50Q29udGV4dCk7XHJcblxyXG4gIHJldHVybiBbXHJcbiAgICBgY29uc3QgJHtpdGVtc05hbWV9ID0gJHtpdGVyYWJsZUV4cHJ9O2AsXHJcbiAgICBgZm9yIChsZXQgJHtjb3VudGVyTmFtZX0gPSAwOyAke2NvdW50ZXJOYW1lfSA8ICR7aXRlbXNOYW1lfS5sZW5ndGg7ICR7Y291bnRlck5hbWV9KyspIHtgLFxyXG4gICAgLi4uaW5kZW50KGBjb25zdCAke25vZGUuaXRlbUFsaWFzfSA9ICR7aXRlbXNOYW1lfVske2NvdW50ZXJOYW1lfV07YCxcclxuICAgICAgYGNvbnN0ICR7aW5kZXhOYW1lfSA9ICR7Y291bnRlck5hbWV9O2AsXHJcbiAgICAgIGBjb25zdCAke2ZpcnN0TmFtZX0gPSAke2NvdW50ZXJOYW1lfSA9PT0gMDtgLFxyXG4gICAgICBgY29uc3QgJHtsYXN0TmFtZX0gPSAke2NvdW50ZXJOYW1lfSA9PT0gJHtpdGVtc05hbWV9Lmxlbmd0aCAtIDE7YCxcclxuICAgICAgYGNvbnN0ICR7ZXZlbk5hbWV9ID0gJHtjb3VudGVyTmFtZX0gJSAyID09PSAwO2AsXHJcbiAgICAgIGBjb25zdCAke29kZE5hbWV9ID0gJHtjb3VudGVyTmFtZX0gJSAyICE9PSAwO2BcclxuICAgICksXHJcbiAgICAuLi5ub2RlLmNoaWxkcmVuLmZsYXRNYXAoKGNoaWxkLCBpKSA9PiBpbmRlbnQoLi4ucHJvY2Vzc05vZGUoY2hpbGQsIGAke25vZGVOYW1lfV8ke2l9YCwgcGFyZW50Tm9kZSwgZm9yQ29udGV4dCkpKSxcclxuICAgICd9JyxcclxuICBdO1xyXG59XHJcblxyXG4vKipcclxuICogUmVzb2x2ZXMgdGhlIG5hbWUgdGhhdCBzaG91bGQgYmUgdXNlZCBpbiBnZW5lcmF0ZWQgY29kZSBmb3IgYSBnaXZlblxyXG4gKiBpbXBsaWNpdCB2YXJpYWJsZS5cclxuICpcclxuICogSWYgdGhlIHRlbXBsYXRlIGRlY2xhcmVkIGFuIGV4cGxpY2l0IGFsaWFzIGZvciB0aGUgdmFyaWFibGVcclxuICogKGUuZy4gYDsgJGluZGV4ID0gaWApIHRoYXQgYWxpYXMgaXMgcmV0dXJuZWQuIE90aGVyd2lzZSB0aGUgZGVmYXVsdFxyXG4gKiBpbXBsaWNpdCB2YXJpYWJsZSBuYW1lIChlLmcuIGAkaW5kZXhgKSBpcyB1c2VkLlxyXG4gKlxyXG4gKiBAcGFyYW0gbm9kZSAtIFRoZSBgRm9yTm9kZWAgd2hvc2UgaW1wbGljaXQgYWxpYXMgbWFwIGlzIGNvbnN1bHRlZC5cclxuICogQHBhcmFtIGltcGxpY2l0IC0gVGhlIGltcGxpY2l0IHZhcmlhYmxlIHRvIGxvb2sgdXAgKGUuZy4gYCckaW5kZXgnYCkuXHJcbiAqIEByZXR1cm5zIFRoZSBhbGlhcyBzdHJpbmcgaWYgb25lIHdhcyBkZWNsYXJlZCwgb3RoZXJ3aXNlIGBpbXBsaWNpdGAgaXRzZWxmLlxyXG4gKi9cclxuZnVuY3Rpb24gcmVzb2x2ZUltcGxpY2l0KG5vZGU6IEZvck5vZGUsIGltcGxpY2l0OiBGb3JJbXBsaWNpdFZhcmlhYmxlcyk6IHN0cmluZyB7XHJcbiAgcmV0dXJuIG5vZGUuaW1wbGljaXRBbGlhc2VzLmdldChpbXBsaWNpdCkgPz8gaW1wbGljaXQ7XHJcbn0iLCJpbXBvcnQgeyBpbmRlbnQgfSBmcm9tICdAeGFlbmRhci9jb21tb24nO1xyXG5pbXBvcnQgeyBBU1ROb2RlVHlwZSB9IGZyb20gJy4uLy4uL3BhcnNlci90eXBlcy9ub2RlLmVudW0uanMnO1xyXG5pbXBvcnQgeyBFbHNlSWZOb2RlIH0gZnJvbSAnLi4vLi4vcGFyc2VyL3R5cGVzL25vZGVzL2Vsc2UtaWYtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgRWxzZU5vZGUgfSBmcm9tICcuLi8uLi9wYXJzZXIvdHlwZXMvbm9kZXMvZWxzZS1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBJZk5vZGUgfSBmcm9tICcuLi8uLi9wYXJzZXIvdHlwZXMvbm9kZXMvaWYtbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gJy4uL21vZGVscy9yZW5kZXItY29udGV4dC5tb2RlbC5qcyc7XHJcbmltcG9ydCB7IHByb2Nlc3NOb2RlIH0gZnJvbSAnLi4vcmVuZGVyLWdlbmVyYXRvci5qcyc7XHJcbmltcG9ydCB7IHJlc29sdmVFeHByZXNzaW9uIH0gZnJvbSAnLi4vdXRpbHMvcmVuZGVyLWdlbmVyYXRvci51dGlscy5qcyc7XHJcblxyXG4vKipcclxuICogR2VuZXJhdGVzIGNvZGUgZm9yIGFuIGBAaWZgIGNvbmRpdGlvbmFsIG5vZGUuXHJcbiAqIEVtaXRzIGFuIGBpZiAoLi4uKSB7IC4uLiB9YCBibG9jaywgYXBwZW5kaW5nIGFuIGBlbHNlIHsgLi4uIH1gIGJsb2NrIGlmIGFuIGFsdGVybmF0ZSBleGlzdHMuXHJcbiAqXHJcbiAqIEBwYXJhbSBub2RlIFRoZSBgSWZOb2RlYCB0byBwcm9jZXNzLlxyXG4gKiBAcGFyYW0gbm9kZU5hbWUgQmFzZSB2YXJpYWJsZSBuYW1lIHByZWZpeCBmb3IgY2hpbGQgbm9kZXMuXHJcbiAqIEBwYXJhbSBwYXJlbnROb2RlIFZhcmlhYmxlIG5hbWUgb2YgdGhlIHBhcmVudCBET00gbm9kZS5cclxuICogQHBhcmFtIGNvbnRleHQgQ3VycmVudCByZW5kZXIgc2NvcGUgY29udGV4dC5cclxuICogQHJldHVybnMgQXJyYXkgb2YgZ2VuZXJhdGVkIGNvZGUgbGluZXMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc0lmKG5vZGU6IElmTm9kZSwgbm9kZU5hbWU6IHN0cmluZywgcGFyZW50Tm9kZTogc3RyaW5nLCBjb250ZXh0OiBDb250ZXh0KTogc3RyaW5nW10ge1xyXG4gIGNvbnN0IGlmQ29udGV4dCA9IG5ldyBDb250ZXh0KFtdLCBjb250ZXh0KTtcclxuXHJcbiAgY29uc3QgY29kZSA9IFtcclxuICAgIGBpZiAoJHtyZXNvbHZlRXhwcmVzc2lvbihub2RlLmNvbmRpdGlvbk5vZGUsIGNvbnRleHQpfSkge2AsXHJcbiAgICAuLi5wcm9jZXNzQ29uc2VxdWVudChub2RlLCBub2RlTmFtZSwgcGFyZW50Tm9kZSwgaWZDb250ZXh0KSxcclxuICAgICd9J1xyXG4gIF07XHJcblxyXG4gIGxldCBhbHQgPSBub2RlLmFsdGVybmF0ZTtcclxuICB3aGlsZSAoYWx0Py50eXBlID09PSBBU1ROb2RlVHlwZS5FbHNlSWYpIHtcclxuICAgIGNvbnN0IGVsc2VJZkNvbnRleHQgPSBuZXcgQ29udGV4dChbXSwgY29udGV4dCk7XHJcblxyXG4gICAgY29kZVtjb2RlLmxlbmd0aCAtIDFdICs9IGAgZWxzZSBpZiAoJHtyZXNvbHZlRXhwcmVzc2lvbihhbHQuY29uZGl0aW9uTm9kZSwgY29udGV4dCl9KSB7YFxyXG4gICAgY29kZS5wdXNoKFxyXG4gICAgICAuLi5wcm9jZXNzQ29uc2VxdWVudChhbHQsIG5vZGVOYW1lLCBwYXJlbnROb2RlLCBlbHNlSWZDb250ZXh0KSxcclxuICAgICAgJ30nXHJcbiAgICApO1xyXG4gICAgYWx0ID0gYWx0LmFsdGVybmF0ZTtcclxuICB9XHJcbiAgXHJcbiAgaWYgKGFsdCkge1xyXG4gICAgY29uc3QgZWxzZUNvbnRleHQgPSBuZXcgQ29udGV4dChbXSwgY29udGV4dCk7XHJcbiAgICBjb2RlW2NvZGUubGVuZ3RoIC0gMV0gKz0gJyBlbHNlIHsnO1xyXG4gICAgY29kZS5wdXNoKFxyXG4gICAgICAuLi5wcm9jZXNzQ29uc2VxdWVudChhbHQsIG5vZGVOYW1lLCBwYXJlbnROb2RlLCBlbHNlQ29udGV4dCksXHJcbiAgICAgICd9J1xyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHJldHVybiBjb2RlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBwcm9jZXNzQ29uc2VxdWVudChub2RlOiBJZk5vZGUgfCBFbHNlSWZOb2RlIHwgRWxzZU5vZGUsIG5vZGVOYW1lOiBzdHJpbmcsIHBhcmVudE5vZGU6IHN0cmluZywgY29udGV4dDogQ29udGV4dCk6IHN0cmluZ1tdIHtcclxuICByZXR1cm4gbm9kZS5jb25zZXF1ZW50Lm1hcCgoY2hpbGQsIGkpID0+IGluZGVudCguLi5wcm9jZXNzTm9kZShjaGlsZCwgYCR7bm9kZU5hbWV9XyR7aX1gLCBwYXJlbnROb2RlLCBjb250ZXh0KSkpLmZsYXQoKTtcclxufSIsImltcG9ydCB7IGluZGVudCB9IGZyb20gJ0B4YWVuZGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IFN3aXRjaE5vZGUgfSBmcm9tICcuLi8uLi9wYXJzZXIvdHlwZXMvbm9kZXMvc3dpdGNoLW5vZGUudHlwZS5qcyc7XHJcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuLi9tb2RlbHMvcmVuZGVyLWNvbnRleHQubW9kZWwuanMnO1xyXG5pbXBvcnQgeyBwcm9jZXNzTm9kZSB9IGZyb20gJy4uL3JlbmRlci1nZW5lcmF0b3IuanMnO1xyXG5pbXBvcnQgeyByZXNvbHZlRXhwcmVzc2lvbiB9IGZyb20gJy4uL3V0aWxzL3JlbmRlci1nZW5lcmF0b3IudXRpbHMuanMnO1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBjb2RlIGZvciBhIGBAc3dpdGNoYCBub2RlLlxyXG4gKiBFbWl0cyBhIGBzd2l0Y2ggKGV4cHJlc3Npb24pIHsgY2FzZSAuLi46IHsgLi4uIGJyZWFrOyB9IC4uLiB9YCBibG9jay5cclxuICpcclxuICogQHBhcmFtIG5vZGUgVGhlIGBTd2l0Y2hOb2RlYCB0byBwcm9jZXNzLlxyXG4gKiBAcGFyYW0gbm9kZU5hbWUgQmFzZSB2YXJpYWJsZSBuYW1lIHByZWZpeCBmb3IgY2hpbGQgbm9kZXMuXHJcbiAqIEBwYXJhbSBwYXJlbnROb2RlIFZhcmlhYmxlIG5hbWUgb2YgdGhlIHBhcmVudCBET00gbm9kZS5cclxuICogQHBhcmFtIGNvbnRleHQgQ3VycmVudCByZW5kZXIgc2NvcGUgY29udGV4dC5cclxuICogQHBhcmFtIHByb2Nlc3NOb2RlIFJlY3Vyc2l2ZSBub2RlIHByb2Nlc3NvciBmdW5jdGlvbi5cclxuICogQHJldHVybnMgQXJyYXkgb2YgZ2VuZXJhdGVkIGNvZGUgbGluZXMuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc1N3aXRjaChub2RlOiBTd2l0Y2hOb2RlLCBub2RlTmFtZTogc3RyaW5nLCBwYXJlbnROb2RlOiBzdHJpbmcsIGNvbnRleHQ6IENvbnRleHQpOiBzdHJpbmdbXSB7XHJcbiAgcmV0dXJuIFtcclxuICAgIGBzd2l0Y2ggKCR7cmVzb2x2ZUV4cHJlc3Npb24obm9kZS5leHByZXNzaW9uLCBjb250ZXh0KX0pIHtgLFxyXG4gICAgLi4ubm9kZS5jYXNlcy5tYXAoY2FzZU5vZGUgPT4gKFtcclxuICAgICAgLi4uaW5kZW50KFxyXG4gICAgICAgIC4uLighY2FzZU5vZGUuY29uZGl0aW9uID8gWydkZWZhdWx0OiB7J10gOiBjYXNlTm9kZS5jb25kaXRpb24ubWFwKChjb25kLCBpLCBhcnIpID0+IGBjYXNlICR7Y29uZH06JHtpID09PSBhcnIubGVuZ3RoIC0gMSA/ICcgeycgOiAnJ31gKSksXHJcbiAgICAgICAgLi4uY2FzZU5vZGUuY2hpbGRyZW4ubWFwKChjaGlsZCwgaSkgPT4gaW5kZW50KC4uLnByb2Nlc3NOb2RlKGNoaWxkLCBgJHtub2RlTmFtZX1fJHtpfV8ke2l9YCwgcGFyZW50Tm9kZSwgbmV3IENvbnRleHQoW10sIGNvbnRleHQpKSkpLmZsYXQoKSxcclxuICAgICAgICBgJHtpbmRlbnQoJ2JyZWFrOycpfWAsXHJcbiAgICAgICAgYH1gXHJcbiAgICAgIClcclxuICAgIF0pKS5mbGF0KCksXHJcbiAgICAnfSdcclxuICBdO1xyXG59XHJcbiIsImltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSAnLi4vLi4vcGFyc2VyL3R5cGVzL25vZGUuZW51bS5qcyc7XHJcbmltcG9ydCB7IEludGVycG9sYXRpb25Ob2RlIH0gZnJvbSAnLi4vLi4vcGFyc2VyL3R5cGVzL25vZGVzL2ludGVycG9sYXRpb24tbm9kZS50eXBlLmpzJztcclxuaW1wb3J0IHsgVGV4dE5vZGUgfSBmcm9tICcuLi8uLi9wYXJzZXIvdHlwZXMvbm9kZXMvdGV4dC1ub2RlLnR5cGUuanMnO1xyXG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSAnLi4vbW9kZWxzL3JlbmRlci1jb250ZXh0Lm1vZGVsLmpzJztcclxuaW1wb3J0IHsgcmVzb2x2ZUV4cHJlc3Npb24gfSBmcm9tICcuLi91dGlscy9yZW5kZXItZ2VuZXJhdG9yLnV0aWxzLmpzJztcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgY29kZSBmb3IgYSB0ZXh0IG9yIGludGVycG9sYXRpb24gbm9kZS5cclxuICogQ3JlYXRlcyBhIERPTSB0ZXh0IG5vZGUgd2l0aCBlaXRoZXIgYSBKU09OLXN0cmluZ2lmaWVkIGxpdGVyYWwgb3IgYSByZXNvbHZlZCBleHByZXNzaW9uLFxyXG4gKiB0aGVuIGFwcGVuZHMgaXQgdG8gdGhlIHBhcmVudCBET00gbm9kZS5cclxuICpcclxuICogQHBhcmFtIG5vZGUgQSBgVGV4dE5vZGVgIG9yIGBJbnRlcnBvbGF0aW9uTm9kZWAgdG8gcHJvY2Vzcy5cclxuICogQHBhcmFtIG5vZGVOYW1lIFZhcmlhYmxlIG5hbWUgZm9yIHRoZSBjcmVhdGVkIHRleHQgbm9kZS5cclxuICogQHBhcmFtIHBhcmVudE5vZGUgVmFyaWFibGUgbmFtZSBvZiB0aGUgcGFyZW50IERPTSBub2RlLlxyXG4gKiBAcGFyYW0gX2NvbnRleHQgVW51c2VkIHJlbmRlciBjb250ZXh0LlxyXG4gKiBAcmV0dXJucyBBcnJheSBvZiB0d28gZ2VuZXJhdGVkIGNvZGUgbGluZXM6IHRoZSB0ZXh0IG5vZGUgY3JlYXRpb24gYW5kIHRoZSBhcHBlbmRDaGlsZCBjYWxsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NUZXh0QW5kSW50ZXJwb2xhdGlvbihub2RlOiBUZXh0Tm9kZSB8IEludGVycG9sYXRpb25Ob2RlLCBub2RlTmFtZTogc3RyaW5nLCBwYXJlbnROb2RlOiBzdHJpbmcsIGNvbnRleHQ6IENvbnRleHQpOiBzdHJpbmdbXSB7XHJcbiAgY29uc3QgdGV4dFZhbHVlID0gbm9kZS50eXBlID09PSBBU1ROb2RlVHlwZS5UZXh0ID8gSlNPTi5zdHJpbmdpZnkobm9kZS52YWx1ZSkgOiByZXNvbHZlRXhwcmVzc2lvbihub2RlLmV4cHJlc3Npb24sIGNvbnRleHQpO1xyXG5cclxuICByZXR1cm4gW1xyXG4gICAgYGNvbnN0ICR7bm9kZU5hbWV9ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJHt0ZXh0VmFsdWV9KTtgLFxyXG4gICAgYCR7cGFyZW50Tm9kZX0uYXBwZW5kQ2hpbGQoJHtub2RlTmFtZX0pO2AsXHJcbiAgICBgZWZmZWN0KCgpID0+ICR7bm9kZU5hbWV9LnRleHRDb250ZW50ID0gJHt0ZXh0VmFsdWV9KTtgXHJcbiAgXTtcclxufVxyXG4iLCJpbXBvcnQgeyBpbmRlbnQgfSBmcm9tIFwiQHhhZW5kYXIvY29tbW9uXCI7XHJcbmltcG9ydCB7IE5vQXJnc0Z1bmN0aW9uIH0gZnJvbSBcIkB4YWVuZGFyL3R5cGVzXCI7XHJcbmltcG9ydCB7IEFTVE5vZGUgfSBmcm9tIFwiLi4vcGFyc2VyL3R5cGVzL2FzdC50eXBlLmpzXCI7XHJcbmltcG9ydCB7IEFTVE5vZGVUeXBlIH0gZnJvbSBcIi4uL3BhcnNlci90eXBlcy9ub2RlLmVudW0uanNcIjtcclxuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuL21vZGVscy9yZW5kZXItY29udGV4dC5tb2RlbC5qc1wiO1xyXG5pbXBvcnQgeyBwcm9jZXNzQ29uc3REZWNsYXJhdGlvbiB9IGZyb20gXCIuL3N0YXRlcy9wcm9jZXNzLWNvbnN0LWRlY2xhcmF0aW9uLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHByb2Nlc3NFbGVtZW50IH0gZnJvbSBcIi4vc3RhdGVzL3Byb2Nlc3MtZWxlbWVudC5zdGF0ZS5qc1wiO1xyXG5pbXBvcnQgeyBwcm9jZXNzRm9yIH0gZnJvbSBcIi4vc3RhdGVzL3Byb2Nlc3MtZm9yLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHByb2Nlc3NJZiB9IGZyb20gXCIuL3N0YXRlcy9wcm9jZXNzLWlmLnN0YXRlLmpzXCI7XHJcbmltcG9ydCB7IHByb2Nlc3NTd2l0Y2ggfSBmcm9tIFwiLi9zdGF0ZXMvcHJvY2Vzcy1zd2l0Y2guc3RhdGUuanNcIjtcclxuaW1wb3J0IHsgcHJvY2Vzc1RleHRBbmRJbnRlcnBvbGF0aW9uIH0gZnJvbSBcIi4vc3RhdGVzL3Byb2Nlc3MtdGV4dC1hbmQtaW50ZXJwb2xhdGlvbi5zdGF0ZS5qc1wiO1xyXG5pbXBvcnQgeyBnZXRFbGVtZW50SWRlbnRpZmllciwgZ2V0VGV4dElkZW50aWZpZXIsIFJPT1RfTk9ERSB9IGZyb20gXCIuL3V0aWxzL3JlbmRlci1nZW5lcmF0b3IudXRpbHMuanNcIjtcclxuXHJcbmNvbnN0IG5vZGVUb1Byb2Nlc3MgPSBuZXcgTWFwPHN0cmluZywgTm9BcmdzRnVuY3Rpb248c3RyaW5nW10+PjtcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgdGhlIFR5cGVTY3JpcHQgYm9keSBvZiBhIHJlbmRlciBmdW5jdGlvbiBmcm9tIGFuIEFTVC5cclxuICpcclxuICogQHBhcmFtIGFzdCBUb3AtbGV2ZWwgQVNUIG5vZGVzIHByb2R1Y2VkIGJ5IHRoZSBQYXJzZXJcclxuICogQHJldHVybnMgU3RyaW5nIGNvbnRhaW5pbmcgdGhlIHJlbmRlciBmdW5jdGlvbiBib2R5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVSZW5kZXJGdW5jdGlvbihhc3Q6IEFTVE5vZGVbXSwgY3NzVmFyaWFibGVOYW1lPzogc3RyaW5nKTogc3RyaW5nIHtcclxuICBub2RlVG9Qcm9jZXNzLmNsZWFyKCk7XHJcbiAgY29uc3QgY29udGV4dCA9IG5ldyBDb250ZXh0O1xyXG5cclxuICBjb25zdCByZW5kZXJGdW5jdGlvbnMgPSBbXHJcbiAgICAnX3JlbmRlcigpIHsnLFxyXG4gICAgLi4uaW5kZW50KFxyXG4gICAgICAuLi5bY3NzVmFyaWFibGVOYW1lID8gYHRoaXMuX3Jvb3QuYWRvcHRlZFN0eWxlU2hlZXRzID0gWyR7Y3NzVmFyaWFibGVOYW1lfV07YCA6IHVuZGVmaW5lZF0uZmlsdGVyKChsaW5lKTogbGluZSBpcyBzdHJpbmcgPT4gISFsaW5lKSxcclxuICAgICAgLi4uYXN0Lm1hcCgobm9kZSwgaSkgPT4gWy4uLnByb2Nlc3NOb2RlKG5vZGUsIGkudG9TdHJpbmcoKSwgUk9PVF9OT0RFLCBjb250ZXh0KV0pLmZsYXQoKVxyXG4gICAgKSxcclxuICAgICd9JyxcclxuICBdXHJcblxyXG4gIHdoaWxlIChub2RlVG9Qcm9jZXNzLnNpemUgPiAwKSB7XHJcbiAgICBjb25zdCBba2V5LCBmbl0gPSBub2RlVG9Qcm9jZXNzLmVudHJpZXMoKS5uZXh0KCkudmFsdWUhO1xyXG4gICAgcmVuZGVyRnVuY3Rpb25zLnB1c2goXHJcbiAgICAgIGAke2tleX0ge2AsXHJcbiAgICAgIC4uLmluZGVudCguLi5mbigpKSxcclxuICAgICAgJ30nLFxyXG4gICAgKTtcclxuICAgIG5vZGVUb1Byb2Nlc3MuZGVsZXRlKGtleSk7XHJcbiAgfVxyXG5cclxuICByZXR1cm4gcmVuZGVyRnVuY3Rpb25zLmpvaW4oXCJcXG5cIik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgY29kZSB0aGF0IGFwcGVuZHMgYG5vZGVOYW1lYCB0byBgcGFyZW50Tm9kZWAuXHJcbiAqIEZvciBmbG93IGNvbnRyb2wgbm9kZXMgbm8gc2luZ2xlIHZhciBpcyBwcm9kdWNlZDsgaW5zdGVhZCBtdWx0aXBsZSBjaGlsZHJlblxyXG4gKiBhcmUgYXBwZW5kZWQgZGlyZWN0bHkgaW5zaWRlIHRoZSBjb250cm9sIGZsb3cgYmxvY2suXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcHJvY2Vzc05vZGUobm9kZTogQVNUTm9kZSwgbm9kZU5hbWU6IHN0cmluZywgcGFyZW50Tm9kZTogc3RyaW5nLCBjb250ZXh0OiBDb250ZXh0KTogc3RyaW5nW10ge1xyXG4gIHN3aXRjaCAobm9kZS50eXBlKSB7XHJcbiAgICBjYXNlIEFTVE5vZGVUeXBlLlRleHQ6XHJcbiAgICBjYXNlIEFTVE5vZGVUeXBlLkludGVycG9sYXRpb246XHJcbiAgICAgIHJldHVybiBwcm9jZXNzVGV4dEFuZEludGVycG9sYXRpb24obm9kZSwgZ2V0VGV4dElkZW50aWZpZXIocGFyZW50Tm9kZSwgbm9kZU5hbWUpLCBwYXJlbnROb2RlLCBjb250ZXh0KTtcclxuXHJcbiAgICBjYXNlIEFTVE5vZGVUeXBlLkVsZW1lbnQ6XHJcbiAgICAgIHJldHVybiBwcm9jZXNzRWxlbWVudChub2RlLCBnZXRFbGVtZW50SWRlbnRpZmllcihub2RlLCBwYXJlbnROb2RlLCBub2RlTmFtZSksIHBhcmVudE5vZGUsIGNvbnRleHQpO1xyXG5cclxuICAgIGNhc2UgQVNUTm9kZVR5cGUuSWY6XHJcbiAgICAgIGNvbnN0IGtleUlmID0gYGlmXyR7bm9kZU5hbWV9KClgXHJcbiAgICAgIG5vZGVUb1Byb2Nlc3Muc2V0KGtleUlmLCAoKSA9PiBwcm9jZXNzSWYobm9kZSwgbm9kZU5hbWUsIHBhcmVudE5vZGUsIGNvbnRleHQpKTtcclxuICAgICAgcmV0dXJuIFtgdGhpcy4ke2tleUlmfTtgXTtcclxuXHJcbiAgICBjYXNlIEFTVE5vZGVUeXBlLkZvcjpcclxuICAgICAgY29uc3Qga2V5Rm9yID0gYGZvcl8ke25vZGVOYW1lfSgpYFxyXG4gICAgICBub2RlVG9Qcm9jZXNzLnNldChrZXlGb3IsICgpID0+IHByb2Nlc3NGb3Iobm9kZSwgbm9kZU5hbWUsIHBhcmVudE5vZGUsIGNvbnRleHQpKTtcclxuICAgICAgcmV0dXJuIFtgdGhpcy4ke2tleUZvcn07YF07XHJcblxyXG4gICAgY2FzZSBBU1ROb2RlVHlwZS5Td2l0Y2g6XHJcbiAgICAgIGNvbnN0IGtleVN3aXRjaCA9IGBzd2l0Y2hfJHtub2RlTmFtZX0oKWBcclxuICAgICAgbm9kZVRvUHJvY2Vzcy5zZXQoa2V5U3dpdGNoLCAoKSA9PiBwcm9jZXNzU3dpdGNoKG5vZGUsIG5vZGVOYW1lLCBwYXJlbnROb2RlLCBjb250ZXh0KSk7XHJcbiAgICAgIHJldHVybiBbYHRoaXMuJHtrZXlTd2l0Y2h9O2BdO1xyXG5cclxuICAgIGNhc2UgQVNUTm9kZVR5cGUuQ29uc3REZWNsYXJhdGlvbjpcclxuICAgICAgcmV0dXJuIHByb2Nlc3NDb25zdERlY2xhcmF0aW9uKG5vZGUsIG5vZGVOYW1lLCBwYXJlbnROb2RlLCBjb250ZXh0KTtcclxuXHJcbiAgICBkZWZhdWx0OlxyXG4gICAgICByZXR1cm4gW107XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IExleGVyIH0gZnJvbSBcIi4vbGV4ZXIvbGV4ZXJcIjtcclxuaW1wb3J0IHsgUGFyc2VyIH0gZnJvbSBcIi4vcGFyc2VyL3BhcnNlclwiO1xyXG5pbXBvcnQgeyBnZW5lcmF0ZVJlbmRlckZ1bmN0aW9uIH0gZnJvbSBcIi4vcmVuZGVyLWdlbmVyYXRvci9yZW5kZXItZ2VuZXJhdG9yXCI7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZShpbnB1dDogc3RyaW5nLCBjc3NWYXJpYWJsZU5hbWU/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gIGNvbnN0IHRva2VucyA9IG5ldyBMZXhlcihpbnB1dCkudG9rZW5pemUoKTtcclxuICBjb25zdCBhc3QgPSBuZXcgUGFyc2VyKHRva2VucykucGFyc2UoKTtcclxuICByZXR1cm4gZ2VuZXJhdGVSZW5kZXJGdW5jdGlvbihhc3QsIGNzc1ZhcmlhYmxlTmFtZSk7XHJcbn0iXSwibWFwcGluZ3MiOiI7OztBQUdBLElBQVksSUFBTCx5QkFBQSxHQUFBO1FBSUwsRUFBQSxRQUFBLFNBSUEsRUFBQSxPQUFBLFFBSUEsRUFBQSxnQkFBQSxpQkFJQSxFQUFBLFdBQUEsWUFJQSxFQUFBLGVBQUEsZ0JBSUEsRUFBQSxZQUFBLGFBSUEsRUFBQSxZQUFBLGFBSUEsRUFBQSxRQUFBLFNBSUEsRUFBQSxlQUFBLGdCQUlBLEVBQUEseUJBQUEsMEJBS0EsRUFBQSw4QkFBQSwrQkFJQSxFQUFBLHFCQUFBLHNCQUlBLEVBQUEsZ0JBQUEsaUJBSUEsRUFBQSwyQkFBQSw0QkFJQSxFQUFBLHdCQUFBLHlCQUlBLEVBQUEsb0JBQUE7QUFDRixFQUFBLENBQUEsQ0FBQSxHQ2xFWSxJQUFMLHlCQUFBLEdBQUE7UUFJTCxFQUFBLEVBQUEsT0FBQSxLQUFBLFFBSUEsRUFBQSxFQUFBLGdCQUFBLEtBQUEsaUJBSUEsRUFBQSxFQUFBLGlCQUFBLEtBQUEsa0JBSUEsRUFBQSxFQUFBLGVBQUEsS0FBQSxnQkFJQSxFQUFBLEVBQUEsaUJBQUEsS0FBQSxrQkFJQSxFQUFBLEVBQUEsWUFBQSxLQUFBLGFBSUEsRUFBQSxFQUFBLFFBQUEsS0FBQSxTQUlBLEVBQUEsRUFBQSx3QkFBQSxLQUFBLHlCQUlBLEVBQUEsRUFBQSwyQkFBQSxLQUFBLDRCQUlBLEVBQUEsRUFBQSxvQkFBQSxLQUFBLHFCQUlBLEVBQUEsRUFBQSxLQUFBLE1BQUEsTUFJQSxFQUFBLEVBQUEsTUFBQSxNQUFBLE9B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
2439
+ export { compile };