1 | /**
|
---|
2 | * @license
|
---|
3 | * Copyright Google LLC All Rights Reserved.
|
---|
4 | *
|
---|
5 | * Use of this source code is governed by an MIT-style license that can be
|
---|
6 | * found in the LICENSE file at https://angular.io/license
|
---|
7 | */
|
---|
8 | import * as chars from '../chars';
|
---|
9 | import { DEFAULT_INTERPOLATION_CONFIG } from '../ml_parser/interpolation_config';
|
---|
10 | import { AbsoluteSourceSpan, ASTWithSource, Binary, BindingPipe, Chain, Conditional, EmptyExpr, ExpressionBinding, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParserError, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, RecursiveAstVisitor, SafeKeyedRead, SafeMethodCall, SafePropertyRead, ThisReceiver, Unary, VariableBinding } from './ast';
|
---|
11 | import { EOF, isIdentifier, TokenType } from './lexer';
|
---|
12 | export class SplitInterpolation {
|
---|
13 | constructor(strings, expressions, offsets) {
|
---|
14 | this.strings = strings;
|
---|
15 | this.expressions = expressions;
|
---|
16 | this.offsets = offsets;
|
---|
17 | }
|
---|
18 | }
|
---|
19 | export class TemplateBindingParseResult {
|
---|
20 | constructor(templateBindings, warnings, errors) {
|
---|
21 | this.templateBindings = templateBindings;
|
---|
22 | this.warnings = warnings;
|
---|
23 | this.errors = errors;
|
---|
24 | }
|
---|
25 | }
|
---|
26 | export class Parser {
|
---|
27 | constructor(_lexer) {
|
---|
28 | this._lexer = _lexer;
|
---|
29 | this.errors = [];
|
---|
30 | this.simpleExpressionChecker = SimpleExpressionChecker;
|
---|
31 | }
|
---|
32 | parseAction(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
---|
33 | this._checkNoInterpolation(input, location, interpolationConfig);
|
---|
34 | const sourceToLex = this._stripComments(input);
|
---|
35 | const tokens = this._lexer.tokenize(this._stripComments(input));
|
---|
36 | const ast = new _ParseAST(input, location, absoluteOffset, tokens, sourceToLex.length, true, this.errors, input.length - sourceToLex.length)
|
---|
37 | .parseChain();
|
---|
38 | return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
|
---|
39 | }
|
---|
40 | parseBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
---|
41 | const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
|
---|
42 | return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
|
---|
43 | }
|
---|
44 | checkSimpleExpression(ast) {
|
---|
45 | const checker = new this.simpleExpressionChecker();
|
---|
46 | ast.visit(checker);
|
---|
47 | return checker.errors;
|
---|
48 | }
|
---|
49 | parseSimpleBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
---|
50 | const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
|
---|
51 | const errors = this.checkSimpleExpression(ast);
|
---|
52 | if (errors.length > 0) {
|
---|
53 | this._reportError(`Host binding expression cannot contain ${errors.join(' ')}`, input, location);
|
---|
54 | }
|
---|
55 | return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
|
---|
56 | }
|
---|
57 | _reportError(message, input, errLocation, ctxLocation) {
|
---|
58 | this.errors.push(new ParserError(message, input, errLocation, ctxLocation));
|
---|
59 | }
|
---|
60 | _parseBindingAst(input, location, absoluteOffset, interpolationConfig) {
|
---|
61 | // Quotes expressions use 3rd-party expression language. We don't want to use
|
---|
62 | // our lexer or parser for that, so we check for that ahead of time.
|
---|
63 | const quote = this._parseQuote(input, location, absoluteOffset);
|
---|
64 | if (quote != null) {
|
---|
65 | return quote;
|
---|
66 | }
|
---|
67 | this._checkNoInterpolation(input, location, interpolationConfig);
|
---|
68 | const sourceToLex = this._stripComments(input);
|
---|
69 | const tokens = this._lexer.tokenize(sourceToLex);
|
---|
70 | return new _ParseAST(input, location, absoluteOffset, tokens, sourceToLex.length, false, this.errors, input.length - sourceToLex.length)
|
---|
71 | .parseChain();
|
---|
72 | }
|
---|
73 | _parseQuote(input, location, absoluteOffset) {
|
---|
74 | if (input == null)
|
---|
75 | return null;
|
---|
76 | const prefixSeparatorIndex = input.indexOf(':');
|
---|
77 | if (prefixSeparatorIndex == -1)
|
---|
78 | return null;
|
---|
79 | const prefix = input.substring(0, prefixSeparatorIndex).trim();
|
---|
80 | if (!isIdentifier(prefix))
|
---|
81 | return null;
|
---|
82 | const uninterpretedExpression = input.substring(prefixSeparatorIndex + 1);
|
---|
83 | const span = new ParseSpan(0, input.length);
|
---|
84 | return new Quote(span, span.toAbsolute(absoluteOffset), prefix, uninterpretedExpression, location);
|
---|
85 | }
|
---|
86 | /**
|
---|
87 | * Parse microsyntax template expression and return a list of bindings or
|
---|
88 | * parsing errors in case the given expression is invalid.
|
---|
89 | *
|
---|
90 | * For example,
|
---|
91 | * ```
|
---|
92 | * <div *ngFor="let item of items">
|
---|
93 | * ^ ^ absoluteValueOffset for `templateValue`
|
---|
94 | * absoluteKeyOffset for `templateKey`
|
---|
95 | * ```
|
---|
96 | * contains three bindings:
|
---|
97 | * 1. ngFor -> null
|
---|
98 | * 2. item -> NgForOfContext.$implicit
|
---|
99 | * 3. ngForOf -> items
|
---|
100 | *
|
---|
101 | * This is apparent from the de-sugared template:
|
---|
102 | * ```
|
---|
103 | * <ng-template ngFor let-item [ngForOf]="items">
|
---|
104 | * ```
|
---|
105 | *
|
---|
106 | * @param templateKey name of directive, without the * prefix. For example: ngIf, ngFor
|
---|
107 | * @param templateValue RHS of the microsyntax attribute
|
---|
108 | * @param templateUrl template filename if it's external, component filename if it's inline
|
---|
109 | * @param absoluteKeyOffset start of the `templateKey`
|
---|
110 | * @param absoluteValueOffset start of the `templateValue`
|
---|
111 | */
|
---|
112 | parseTemplateBindings(templateKey, templateValue, templateUrl, absoluteKeyOffset, absoluteValueOffset) {
|
---|
113 | const tokens = this._lexer.tokenize(templateValue);
|
---|
114 | const parser = new _ParseAST(templateValue, templateUrl, absoluteValueOffset, tokens, templateValue.length, false /* parseAction */, this.errors, 0 /* relative offset */);
|
---|
115 | return parser.parseTemplateBindings({
|
---|
116 | source: templateKey,
|
---|
117 | span: new AbsoluteSourceSpan(absoluteKeyOffset, absoluteKeyOffset + templateKey.length),
|
---|
118 | });
|
---|
119 | }
|
---|
120 | parseInterpolation(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
---|
121 | const { strings, expressions, offsets } = this.splitInterpolation(input, location, interpolationConfig);
|
---|
122 | if (expressions.length === 0)
|
---|
123 | return null;
|
---|
124 | const expressionNodes = [];
|
---|
125 | for (let i = 0; i < expressions.length; ++i) {
|
---|
126 | const expressionText = expressions[i].text;
|
---|
127 | const sourceToLex = this._stripComments(expressionText);
|
---|
128 | const tokens = this._lexer.tokenize(sourceToLex);
|
---|
129 | const ast = new _ParseAST(input, location, absoluteOffset, tokens, sourceToLex.length, false, this.errors, offsets[i] + (expressionText.length - sourceToLex.length))
|
---|
130 | .parseChain();
|
---|
131 | expressionNodes.push(ast);
|
---|
132 | }
|
---|
133 | return this.createInterpolationAst(strings.map(s => s.text), expressionNodes, input, location, absoluteOffset);
|
---|
134 | }
|
---|
135 | /**
|
---|
136 | * Similar to `parseInterpolation`, but treats the provided string as a single expression
|
---|
137 | * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`).
|
---|
138 | * This is used for parsing the switch expression in ICUs.
|
---|
139 | */
|
---|
140 | parseInterpolationExpression(expression, location, absoluteOffset) {
|
---|
141 | const sourceToLex = this._stripComments(expression);
|
---|
142 | const tokens = this._lexer.tokenize(sourceToLex);
|
---|
143 | const ast = new _ParseAST(expression, location, absoluteOffset, tokens, sourceToLex.length,
|
---|
144 | /* parseAction */ false, this.errors, 0)
|
---|
145 | .parseChain();
|
---|
146 | const strings = ['', '']; // The prefix and suffix strings are both empty
|
---|
147 | return this.createInterpolationAst(strings, [ast], expression, location, absoluteOffset);
|
---|
148 | }
|
---|
149 | createInterpolationAst(strings, expressions, input, location, absoluteOffset) {
|
---|
150 | const span = new ParseSpan(0, input.length);
|
---|
151 | const interpolation = new Interpolation(span, span.toAbsolute(absoluteOffset), strings, expressions);
|
---|
152 | return new ASTWithSource(interpolation, input, location, absoluteOffset, this.errors);
|
---|
153 | }
|
---|
154 | /**
|
---|
155 | * Splits a string of text into "raw" text segments and expressions present in interpolations in
|
---|
156 | * the string.
|
---|
157 | * Returns `null` if there are no interpolations, otherwise a
|
---|
158 | * `SplitInterpolation` with splits that look like
|
---|
159 | * <raw text> <expression> <raw text> ... <raw text> <expression> <raw text>
|
---|
160 | */
|
---|
161 | splitInterpolation(input, location, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
|
---|
162 | const strings = [];
|
---|
163 | const expressions = [];
|
---|
164 | const offsets = [];
|
---|
165 | let i = 0;
|
---|
166 | let atInterpolation = false;
|
---|
167 | let extendLastString = false;
|
---|
168 | let { start: interpStart, end: interpEnd } = interpolationConfig;
|
---|
169 | while (i < input.length) {
|
---|
170 | if (!atInterpolation) {
|
---|
171 | // parse until starting {{
|
---|
172 | const start = i;
|
---|
173 | i = input.indexOf(interpStart, i);
|
---|
174 | if (i === -1) {
|
---|
175 | i = input.length;
|
---|
176 | }
|
---|
177 | const text = input.substring(start, i);
|
---|
178 | strings.push({ text, start, end: i });
|
---|
179 | atInterpolation = true;
|
---|
180 | }
|
---|
181 | else {
|
---|
182 | // parse from starting {{ to ending }} while ignoring content inside quotes.
|
---|
183 | const fullStart = i;
|
---|
184 | const exprStart = fullStart + interpStart.length;
|
---|
185 | const exprEnd = this._getInterpolationEndIndex(input, interpEnd, exprStart);
|
---|
186 | if (exprEnd === -1) {
|
---|
187 | // Could not find the end of the interpolation; do not parse an expression.
|
---|
188 | // Instead we should extend the content on the last raw string.
|
---|
189 | atInterpolation = false;
|
---|
190 | extendLastString = true;
|
---|
191 | break;
|
---|
192 | }
|
---|
193 | const fullEnd = exprEnd + interpEnd.length;
|
---|
194 | const text = input.substring(exprStart, exprEnd);
|
---|
195 | if (text.trim().length === 0) {
|
---|
196 | this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, location);
|
---|
197 | }
|
---|
198 | expressions.push({ text, start: fullStart, end: fullEnd });
|
---|
199 | offsets.push(exprStart);
|
---|
200 | i = fullEnd;
|
---|
201 | atInterpolation = false;
|
---|
202 | }
|
---|
203 | }
|
---|
204 | if (!atInterpolation) {
|
---|
205 | // If we are now at a text section, add the remaining content as a raw string.
|
---|
206 | if (extendLastString) {
|
---|
207 | const piece = strings[strings.length - 1];
|
---|
208 | piece.text += input.substring(i);
|
---|
209 | piece.end = input.length;
|
---|
210 | }
|
---|
211 | else {
|
---|
212 | strings.push({ text: input.substring(i), start: i, end: input.length });
|
---|
213 | }
|
---|
214 | }
|
---|
215 | return new SplitInterpolation(strings, expressions, offsets);
|
---|
216 | }
|
---|
217 | wrapLiteralPrimitive(input, location, absoluteOffset) {
|
---|
218 | const span = new ParseSpan(0, input == null ? 0 : input.length);
|
---|
219 | return new ASTWithSource(new LiteralPrimitive(span, span.toAbsolute(absoluteOffset), input), input, location, absoluteOffset, this.errors);
|
---|
220 | }
|
---|
221 | _stripComments(input) {
|
---|
222 | const i = this._commentStart(input);
|
---|
223 | return i != null ? input.substring(0, i).trim() : input;
|
---|
224 | }
|
---|
225 | _commentStart(input) {
|
---|
226 | let outerQuote = null;
|
---|
227 | for (let i = 0; i < input.length - 1; i++) {
|
---|
228 | const char = input.charCodeAt(i);
|
---|
229 | const nextChar = input.charCodeAt(i + 1);
|
---|
230 | if (char === chars.$SLASH && nextChar == chars.$SLASH && outerQuote == null)
|
---|
231 | return i;
|
---|
232 | if (outerQuote === char) {
|
---|
233 | outerQuote = null;
|
---|
234 | }
|
---|
235 | else if (outerQuote == null && chars.isQuote(char)) {
|
---|
236 | outerQuote = char;
|
---|
237 | }
|
---|
238 | }
|
---|
239 | return null;
|
---|
240 | }
|
---|
241 | _checkNoInterpolation(input, location, { start, end }) {
|
---|
242 | let startIndex = -1;
|
---|
243 | let endIndex = -1;
|
---|
244 | for (const charIndex of this._forEachUnquotedChar(input, 0)) {
|
---|
245 | if (startIndex === -1) {
|
---|
246 | if (input.startsWith(start)) {
|
---|
247 | startIndex = charIndex;
|
---|
248 | }
|
---|
249 | }
|
---|
250 | else {
|
---|
251 | endIndex = this._getInterpolationEndIndex(input, end, charIndex);
|
---|
252 | if (endIndex > -1) {
|
---|
253 | break;
|
---|
254 | }
|
---|
255 | }
|
---|
256 | }
|
---|
257 | if (startIndex > -1 && endIndex > -1) {
|
---|
258 | this._reportError(`Got interpolation (${start}${end}) where expression was expected`, input, `at column ${startIndex} in`, location);
|
---|
259 | }
|
---|
260 | }
|
---|
261 | /**
|
---|
262 | * Finds the index of the end of an interpolation expression
|
---|
263 | * while ignoring comments and quoted content.
|
---|
264 | */
|
---|
265 | _getInterpolationEndIndex(input, expressionEnd, start) {
|
---|
266 | for (const charIndex of this._forEachUnquotedChar(input, start)) {
|
---|
267 | if (input.startsWith(expressionEnd, charIndex)) {
|
---|
268 | return charIndex;
|
---|
269 | }
|
---|
270 | // Nothing else in the expression matters after we've
|
---|
271 | // hit a comment so look directly for the end token.
|
---|
272 | if (input.startsWith('//', charIndex)) {
|
---|
273 | return input.indexOf(expressionEnd, charIndex);
|
---|
274 | }
|
---|
275 | }
|
---|
276 | return -1;
|
---|
277 | }
|
---|
278 | /**
|
---|
279 | * Generator used to iterate over the character indexes of a string that are outside of quotes.
|
---|
280 | * @param input String to loop through.
|
---|
281 | * @param start Index within the string at which to start.
|
---|
282 | */
|
---|
283 | *_forEachUnquotedChar(input, start) {
|
---|
284 | let currentQuote = null;
|
---|
285 | let escapeCount = 0;
|
---|
286 | for (let i = start; i < input.length; i++) {
|
---|
287 | const char = input[i];
|
---|
288 | // Skip the characters inside quotes. Note that we only care about the outer-most
|
---|
289 | // quotes matching up and we need to account for escape characters.
|
---|
290 | if (chars.isQuote(input.charCodeAt(i)) && (currentQuote === null || currentQuote === char) &&
|
---|
291 | escapeCount % 2 === 0) {
|
---|
292 | currentQuote = currentQuote === null ? char : null;
|
---|
293 | }
|
---|
294 | else if (currentQuote === null) {
|
---|
295 | yield i;
|
---|
296 | }
|
---|
297 | escapeCount = char === '\\' ? escapeCount + 1 : 0;
|
---|
298 | }
|
---|
299 | }
|
---|
300 | }
|
---|
301 | export class IvyParser extends Parser {
|
---|
302 | constructor() {
|
---|
303 | super(...arguments);
|
---|
304 | this.simpleExpressionChecker = IvySimpleExpressionChecker;
|
---|
305 | }
|
---|
306 | }
|
---|
307 | /** Describes a stateful context an expression parser is in. */
|
---|
308 | var ParseContextFlags;
|
---|
309 | (function (ParseContextFlags) {
|
---|
310 | ParseContextFlags[ParseContextFlags["None"] = 0] = "None";
|
---|
311 | /**
|
---|
312 | * A Writable context is one in which a value may be written to an lvalue.
|
---|
313 | * For example, after we see a property access, we may expect a write to the
|
---|
314 | * property via the "=" operator.
|
---|
315 | * prop
|
---|
316 | * ^ possible "=" after
|
---|
317 | */
|
---|
318 | ParseContextFlags[ParseContextFlags["Writable"] = 1] = "Writable";
|
---|
319 | })(ParseContextFlags || (ParseContextFlags = {}));
|
---|
320 | export class _ParseAST {
|
---|
321 | constructor(input, location, absoluteOffset, tokens, inputLength, parseAction, errors, offset) {
|
---|
322 | this.input = input;
|
---|
323 | this.location = location;
|
---|
324 | this.absoluteOffset = absoluteOffset;
|
---|
325 | this.tokens = tokens;
|
---|
326 | this.inputLength = inputLength;
|
---|
327 | this.parseAction = parseAction;
|
---|
328 | this.errors = errors;
|
---|
329 | this.offset = offset;
|
---|
330 | this.rparensExpected = 0;
|
---|
331 | this.rbracketsExpected = 0;
|
---|
332 | this.rbracesExpected = 0;
|
---|
333 | this.context = ParseContextFlags.None;
|
---|
334 | // Cache of expression start and input indeces to the absolute source span they map to, used to
|
---|
335 | // prevent creating superfluous source spans in `sourceSpan`.
|
---|
336 | // A serial of the expression start and input index is used for mapping because both are stateful
|
---|
337 | // and may change for subsequent expressions visited by the parser.
|
---|
338 | this.sourceSpanCache = new Map();
|
---|
339 | this.index = 0;
|
---|
340 | }
|
---|
341 | peek(offset) {
|
---|
342 | const i = this.index + offset;
|
---|
343 | return i < this.tokens.length ? this.tokens[i] : EOF;
|
---|
344 | }
|
---|
345 | get next() {
|
---|
346 | return this.peek(0);
|
---|
347 | }
|
---|
348 | /** Whether all the parser input has been processed. */
|
---|
349 | get atEOF() {
|
---|
350 | return this.index >= this.tokens.length;
|
---|
351 | }
|
---|
352 | /**
|
---|
353 | * Index of the next token to be processed, or the end of the last token if all have been
|
---|
354 | * processed.
|
---|
355 | */
|
---|
356 | get inputIndex() {
|
---|
357 | return this.atEOF ? this.currentEndIndex : this.next.index + this.offset;
|
---|
358 | }
|
---|
359 | /**
|
---|
360 | * End index of the last processed token, or the start of the first token if none have been
|
---|
361 | * processed.
|
---|
362 | */
|
---|
363 | get currentEndIndex() {
|
---|
364 | if (this.index > 0) {
|
---|
365 | const curToken = this.peek(-1);
|
---|
366 | return curToken.end + this.offset;
|
---|
367 | }
|
---|
368 | // No tokens have been processed yet; return the next token's start or the length of the input
|
---|
369 | // if there is no token.
|
---|
370 | if (this.tokens.length === 0) {
|
---|
371 | return this.inputLength + this.offset;
|
---|
372 | }
|
---|
373 | return this.next.index + this.offset;
|
---|
374 | }
|
---|
375 | /**
|
---|
376 | * Returns the absolute offset of the start of the current token.
|
---|
377 | */
|
---|
378 | get currentAbsoluteOffset() {
|
---|
379 | return this.absoluteOffset + this.inputIndex;
|
---|
380 | }
|
---|
381 | /**
|
---|
382 | * Retrieve a `ParseSpan` from `start` to the current position (or to `artificialEndIndex` if
|
---|
383 | * provided).
|
---|
384 | *
|
---|
385 | * @param start Position from which the `ParseSpan` will start.
|
---|
386 | * @param artificialEndIndex Optional ending index to be used if provided (and if greater than the
|
---|
387 | * natural ending index)
|
---|
388 | */
|
---|
389 | span(start, artificialEndIndex) {
|
---|
390 | let endIndex = this.currentEndIndex;
|
---|
391 | if (artificialEndIndex !== undefined && artificialEndIndex > this.currentEndIndex) {
|
---|
392 | endIndex = artificialEndIndex;
|
---|
393 | }
|
---|
394 | // In some unusual parsing scenarios (like when certain tokens are missing and an `EmptyExpr` is
|
---|
395 | // being created), the current token may already be advanced beyond the `currentEndIndex`. This
|
---|
396 | // appears to be a deep-seated parser bug.
|
---|
397 | //
|
---|
398 | // As a workaround for now, swap the start and end indices to ensure a valid `ParseSpan`.
|
---|
399 | // TODO(alxhub): fix the bug upstream in the parser state, and remove this workaround.
|
---|
400 | if (start > endIndex) {
|
---|
401 | const tmp = endIndex;
|
---|
402 | endIndex = start;
|
---|
403 | start = tmp;
|
---|
404 | }
|
---|
405 | return new ParseSpan(start, endIndex);
|
---|
406 | }
|
---|
407 | sourceSpan(start, artificialEndIndex) {
|
---|
408 | const serial = `${start}@${this.inputIndex}:${artificialEndIndex}`;
|
---|
409 | if (!this.sourceSpanCache.has(serial)) {
|
---|
410 | this.sourceSpanCache.set(serial, this.span(start, artificialEndIndex).toAbsolute(this.absoluteOffset));
|
---|
411 | }
|
---|
412 | return this.sourceSpanCache.get(serial);
|
---|
413 | }
|
---|
414 | advance() {
|
---|
415 | this.index++;
|
---|
416 | }
|
---|
417 | /**
|
---|
418 | * Executes a callback in the provided context.
|
---|
419 | */
|
---|
420 | withContext(context, cb) {
|
---|
421 | this.context |= context;
|
---|
422 | const ret = cb();
|
---|
423 | this.context ^= context;
|
---|
424 | return ret;
|
---|
425 | }
|
---|
426 | consumeOptionalCharacter(code) {
|
---|
427 | if (this.next.isCharacter(code)) {
|
---|
428 | this.advance();
|
---|
429 | return true;
|
---|
430 | }
|
---|
431 | else {
|
---|
432 | return false;
|
---|
433 | }
|
---|
434 | }
|
---|
435 | peekKeywordLet() {
|
---|
436 | return this.next.isKeywordLet();
|
---|
437 | }
|
---|
438 | peekKeywordAs() {
|
---|
439 | return this.next.isKeywordAs();
|
---|
440 | }
|
---|
441 | /**
|
---|
442 | * Consumes an expected character, otherwise emits an error about the missing expected character
|
---|
443 | * and skips over the token stream until reaching a recoverable point.
|
---|
444 | *
|
---|
445 | * See `this.error` and `this.skip` for more details.
|
---|
446 | */
|
---|
447 | expectCharacter(code) {
|
---|
448 | if (this.consumeOptionalCharacter(code))
|
---|
449 | return;
|
---|
450 | this.error(`Missing expected ${String.fromCharCode(code)}`);
|
---|
451 | }
|
---|
452 | consumeOptionalOperator(op) {
|
---|
453 | if (this.next.isOperator(op)) {
|
---|
454 | this.advance();
|
---|
455 | return true;
|
---|
456 | }
|
---|
457 | else {
|
---|
458 | return false;
|
---|
459 | }
|
---|
460 | }
|
---|
461 | expectOperator(operator) {
|
---|
462 | if (this.consumeOptionalOperator(operator))
|
---|
463 | return;
|
---|
464 | this.error(`Missing expected operator ${operator}`);
|
---|
465 | }
|
---|
466 | prettyPrintToken(tok) {
|
---|
467 | return tok === EOF ? 'end of input' : `token ${tok}`;
|
---|
468 | }
|
---|
469 | expectIdentifierOrKeyword() {
|
---|
470 | const n = this.next;
|
---|
471 | if (!n.isIdentifier() && !n.isKeyword()) {
|
---|
472 | if (n.isPrivateIdentifier()) {
|
---|
473 | this._reportErrorForPrivateIdentifier(n, 'expected identifier or keyword');
|
---|
474 | }
|
---|
475 | else {
|
---|
476 | this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier or keyword`);
|
---|
477 | }
|
---|
478 | return null;
|
---|
479 | }
|
---|
480 | this.advance();
|
---|
481 | return n.toString();
|
---|
482 | }
|
---|
483 | expectIdentifierOrKeywordOrString() {
|
---|
484 | const n = this.next;
|
---|
485 | if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) {
|
---|
486 | if (n.isPrivateIdentifier()) {
|
---|
487 | this._reportErrorForPrivateIdentifier(n, 'expected identifier, keyword or string');
|
---|
488 | }
|
---|
489 | else {
|
---|
490 | this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier, keyword, or string`);
|
---|
491 | }
|
---|
492 | return '';
|
---|
493 | }
|
---|
494 | this.advance();
|
---|
495 | return n.toString();
|
---|
496 | }
|
---|
497 | parseChain() {
|
---|
498 | const exprs = [];
|
---|
499 | const start = this.inputIndex;
|
---|
500 | while (this.index < this.tokens.length) {
|
---|
501 | const expr = this.parsePipe();
|
---|
502 | exprs.push(expr);
|
---|
503 | if (this.consumeOptionalCharacter(chars.$SEMICOLON)) {
|
---|
504 | if (!this.parseAction) {
|
---|
505 | this.error('Binding expression cannot contain chained expression');
|
---|
506 | }
|
---|
507 | while (this.consumeOptionalCharacter(chars.$SEMICOLON)) {
|
---|
508 | } // read all semicolons
|
---|
509 | }
|
---|
510 | else if (this.index < this.tokens.length) {
|
---|
511 | this.error(`Unexpected token '${this.next}'`);
|
---|
512 | }
|
---|
513 | }
|
---|
514 | if (exprs.length == 0) {
|
---|
515 | // We have no expressions so create an empty expression that spans the entire input length
|
---|
516 | const artificialStart = this.offset;
|
---|
517 | const artificialEnd = this.offset + this.inputLength;
|
---|
518 | return new EmptyExpr(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
|
---|
519 | }
|
---|
520 | if (exprs.length == 1)
|
---|
521 | return exprs[0];
|
---|
522 | return new Chain(this.span(start), this.sourceSpan(start), exprs);
|
---|
523 | }
|
---|
524 | parsePipe() {
|
---|
525 | const start = this.inputIndex;
|
---|
526 | let result = this.parseExpression();
|
---|
527 | if (this.consumeOptionalOperator('|')) {
|
---|
528 | if (this.parseAction) {
|
---|
529 | this.error('Cannot have a pipe in an action expression');
|
---|
530 | }
|
---|
531 | do {
|
---|
532 | const nameStart = this.inputIndex;
|
---|
533 | let nameId = this.expectIdentifierOrKeyword();
|
---|
534 | let nameSpan;
|
---|
535 | let fullSpanEnd = undefined;
|
---|
536 | if (nameId !== null) {
|
---|
537 | nameSpan = this.sourceSpan(nameStart);
|
---|
538 | }
|
---|
539 | else {
|
---|
540 | // No valid identifier was found, so we'll assume an empty pipe name ('').
|
---|
541 | nameId = '';
|
---|
542 | // However, there may have been whitespace present between the pipe character and the next
|
---|
543 | // token in the sequence (or the end of input). We want to track this whitespace so that
|
---|
544 | // the `BindingPipe` we produce covers not just the pipe character, but any trailing
|
---|
545 | // whitespace beyond it. Another way of thinking about this is that the zero-length name
|
---|
546 | // is assumed to be at the end of any whitespace beyond the pipe character.
|
---|
547 | //
|
---|
548 | // Therefore, we push the end of the `ParseSpan` for this pipe all the way up to the
|
---|
549 | // beginning of the next token, or until the end of input if the next token is EOF.
|
---|
550 | fullSpanEnd = this.next.index !== -1 ? this.next.index : this.inputLength + this.offset;
|
---|
551 | // The `nameSpan` for an empty pipe name is zero-length at the end of any whitespace
|
---|
552 | // beyond the pipe character.
|
---|
553 | nameSpan = new ParseSpan(fullSpanEnd, fullSpanEnd).toAbsolute(this.absoluteOffset);
|
---|
554 | }
|
---|
555 | const args = [];
|
---|
556 | while (this.consumeOptionalCharacter(chars.$COLON)) {
|
---|
557 | args.push(this.parseExpression());
|
---|
558 | // If there are additional expressions beyond the name, then the artificial end for the
|
---|
559 | // name is no longer relevant.
|
---|
560 | }
|
---|
561 | result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, nameSpan);
|
---|
562 | } while (this.consumeOptionalOperator('|'));
|
---|
563 | }
|
---|
564 | return result;
|
---|
565 | }
|
---|
566 | parseExpression() {
|
---|
567 | return this.parseConditional();
|
---|
568 | }
|
---|
569 | parseConditional() {
|
---|
570 | const start = this.inputIndex;
|
---|
571 | const result = this.parseLogicalOr();
|
---|
572 | if (this.consumeOptionalOperator('?')) {
|
---|
573 | const yes = this.parsePipe();
|
---|
574 | let no;
|
---|
575 | if (!this.consumeOptionalCharacter(chars.$COLON)) {
|
---|
576 | const end = this.inputIndex;
|
---|
577 | const expression = this.input.substring(start, end);
|
---|
578 | this.error(`Conditional expression ${expression} requires all 3 expressions`);
|
---|
579 | no = new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
580 | }
|
---|
581 | else {
|
---|
582 | no = this.parsePipe();
|
---|
583 | }
|
---|
584 | return new Conditional(this.span(start), this.sourceSpan(start), result, yes, no);
|
---|
585 | }
|
---|
586 | else {
|
---|
587 | return result;
|
---|
588 | }
|
---|
589 | }
|
---|
590 | parseLogicalOr() {
|
---|
591 | // '||'
|
---|
592 | const start = this.inputIndex;
|
---|
593 | let result = this.parseLogicalAnd();
|
---|
594 | while (this.consumeOptionalOperator('||')) {
|
---|
595 | const right = this.parseLogicalAnd();
|
---|
596 | result = new Binary(this.span(start), this.sourceSpan(start), '||', result, right);
|
---|
597 | }
|
---|
598 | return result;
|
---|
599 | }
|
---|
600 | parseLogicalAnd() {
|
---|
601 | // '&&'
|
---|
602 | const start = this.inputIndex;
|
---|
603 | let result = this.parseNullishCoalescing();
|
---|
604 | while (this.consumeOptionalOperator('&&')) {
|
---|
605 | const right = this.parseNullishCoalescing();
|
---|
606 | result = new Binary(this.span(start), this.sourceSpan(start), '&&', result, right);
|
---|
607 | }
|
---|
608 | return result;
|
---|
609 | }
|
---|
610 | parseNullishCoalescing() {
|
---|
611 | // '??'
|
---|
612 | const start = this.inputIndex;
|
---|
613 | let result = this.parseEquality();
|
---|
614 | while (this.consumeOptionalOperator('??')) {
|
---|
615 | const right = this.parseEquality();
|
---|
616 | result = new Binary(this.span(start), this.sourceSpan(start), '??', result, right);
|
---|
617 | }
|
---|
618 | return result;
|
---|
619 | }
|
---|
620 | parseEquality() {
|
---|
621 | // '==','!=','===','!=='
|
---|
622 | const start = this.inputIndex;
|
---|
623 | let result = this.parseRelational();
|
---|
624 | while (this.next.type == TokenType.Operator) {
|
---|
625 | const operator = this.next.strValue;
|
---|
626 | switch (operator) {
|
---|
627 | case '==':
|
---|
628 | case '===':
|
---|
629 | case '!=':
|
---|
630 | case '!==':
|
---|
631 | this.advance();
|
---|
632 | const right = this.parseRelational();
|
---|
633 | result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
---|
634 | continue;
|
---|
635 | }
|
---|
636 | break;
|
---|
637 | }
|
---|
638 | return result;
|
---|
639 | }
|
---|
640 | parseRelational() {
|
---|
641 | // '<', '>', '<=', '>='
|
---|
642 | const start = this.inputIndex;
|
---|
643 | let result = this.parseAdditive();
|
---|
644 | while (this.next.type == TokenType.Operator) {
|
---|
645 | const operator = this.next.strValue;
|
---|
646 | switch (operator) {
|
---|
647 | case '<':
|
---|
648 | case '>':
|
---|
649 | case '<=':
|
---|
650 | case '>=':
|
---|
651 | this.advance();
|
---|
652 | const right = this.parseAdditive();
|
---|
653 | result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
---|
654 | continue;
|
---|
655 | }
|
---|
656 | break;
|
---|
657 | }
|
---|
658 | return result;
|
---|
659 | }
|
---|
660 | parseAdditive() {
|
---|
661 | // '+', '-'
|
---|
662 | const start = this.inputIndex;
|
---|
663 | let result = this.parseMultiplicative();
|
---|
664 | while (this.next.type == TokenType.Operator) {
|
---|
665 | const operator = this.next.strValue;
|
---|
666 | switch (operator) {
|
---|
667 | case '+':
|
---|
668 | case '-':
|
---|
669 | this.advance();
|
---|
670 | let right = this.parseMultiplicative();
|
---|
671 | result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
---|
672 | continue;
|
---|
673 | }
|
---|
674 | break;
|
---|
675 | }
|
---|
676 | return result;
|
---|
677 | }
|
---|
678 | parseMultiplicative() {
|
---|
679 | // '*', '%', '/'
|
---|
680 | const start = this.inputIndex;
|
---|
681 | let result = this.parsePrefix();
|
---|
682 | while (this.next.type == TokenType.Operator) {
|
---|
683 | const operator = this.next.strValue;
|
---|
684 | switch (operator) {
|
---|
685 | case '*':
|
---|
686 | case '%':
|
---|
687 | case '/':
|
---|
688 | this.advance();
|
---|
689 | let right = this.parsePrefix();
|
---|
690 | result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
|
---|
691 | continue;
|
---|
692 | }
|
---|
693 | break;
|
---|
694 | }
|
---|
695 | return result;
|
---|
696 | }
|
---|
697 | parsePrefix() {
|
---|
698 | if (this.next.type == TokenType.Operator) {
|
---|
699 | const start = this.inputIndex;
|
---|
700 | const operator = this.next.strValue;
|
---|
701 | let result;
|
---|
702 | switch (operator) {
|
---|
703 | case '+':
|
---|
704 | this.advance();
|
---|
705 | result = this.parsePrefix();
|
---|
706 | return Unary.createPlus(this.span(start), this.sourceSpan(start), result);
|
---|
707 | case '-':
|
---|
708 | this.advance();
|
---|
709 | result = this.parsePrefix();
|
---|
710 | return Unary.createMinus(this.span(start), this.sourceSpan(start), result);
|
---|
711 | case '!':
|
---|
712 | this.advance();
|
---|
713 | result = this.parsePrefix();
|
---|
714 | return new PrefixNot(this.span(start), this.sourceSpan(start), result);
|
---|
715 | }
|
---|
716 | }
|
---|
717 | return this.parseCallChain();
|
---|
718 | }
|
---|
719 | parseCallChain() {
|
---|
720 | const start = this.inputIndex;
|
---|
721 | let result = this.parsePrimary();
|
---|
722 | while (true) {
|
---|
723 | if (this.consumeOptionalCharacter(chars.$PERIOD)) {
|
---|
724 | result = this.parseAccessMemberOrMethodCall(result, start, false);
|
---|
725 | }
|
---|
726 | else if (this.consumeOptionalOperator('?.')) {
|
---|
727 | result = this.consumeOptionalCharacter(chars.$LBRACKET) ?
|
---|
728 | this.parseKeyedReadOrWrite(result, start, true) :
|
---|
729 | this.parseAccessMemberOrMethodCall(result, start, true);
|
---|
730 | }
|
---|
731 | else if (this.consumeOptionalCharacter(chars.$LBRACKET)) {
|
---|
732 | result = this.parseKeyedReadOrWrite(result, start, false);
|
---|
733 | }
|
---|
734 | else if (this.consumeOptionalCharacter(chars.$LPAREN)) {
|
---|
735 | this.rparensExpected++;
|
---|
736 | const args = this.parseCallArguments();
|
---|
737 | this.rparensExpected--;
|
---|
738 | this.expectCharacter(chars.$RPAREN);
|
---|
739 | result = new FunctionCall(this.span(start), this.sourceSpan(start), result, args);
|
---|
740 | }
|
---|
741 | else if (this.consumeOptionalOperator('!')) {
|
---|
742 | result = new NonNullAssert(this.span(start), this.sourceSpan(start), result);
|
---|
743 | }
|
---|
744 | else {
|
---|
745 | return result;
|
---|
746 | }
|
---|
747 | }
|
---|
748 | }
|
---|
749 | parsePrimary() {
|
---|
750 | const start = this.inputIndex;
|
---|
751 | if (this.consumeOptionalCharacter(chars.$LPAREN)) {
|
---|
752 | this.rparensExpected++;
|
---|
753 | const result = this.parsePipe();
|
---|
754 | this.rparensExpected--;
|
---|
755 | this.expectCharacter(chars.$RPAREN);
|
---|
756 | return result;
|
---|
757 | }
|
---|
758 | else if (this.next.isKeywordNull()) {
|
---|
759 | this.advance();
|
---|
760 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), null);
|
---|
761 | }
|
---|
762 | else if (this.next.isKeywordUndefined()) {
|
---|
763 | this.advance();
|
---|
764 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), void 0);
|
---|
765 | }
|
---|
766 | else if (this.next.isKeywordTrue()) {
|
---|
767 | this.advance();
|
---|
768 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), true);
|
---|
769 | }
|
---|
770 | else if (this.next.isKeywordFalse()) {
|
---|
771 | this.advance();
|
---|
772 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), false);
|
---|
773 | }
|
---|
774 | else if (this.next.isKeywordThis()) {
|
---|
775 | this.advance();
|
---|
776 | return new ThisReceiver(this.span(start), this.sourceSpan(start));
|
---|
777 | }
|
---|
778 | else if (this.consumeOptionalCharacter(chars.$LBRACKET)) {
|
---|
779 | this.rbracketsExpected++;
|
---|
780 | const elements = this.parseExpressionList(chars.$RBRACKET);
|
---|
781 | this.rbracketsExpected--;
|
---|
782 | this.expectCharacter(chars.$RBRACKET);
|
---|
783 | return new LiteralArray(this.span(start), this.sourceSpan(start), elements);
|
---|
784 | }
|
---|
785 | else if (this.next.isCharacter(chars.$LBRACE)) {
|
---|
786 | return this.parseLiteralMap();
|
---|
787 | }
|
---|
788 | else if (this.next.isIdentifier()) {
|
---|
789 | return this.parseAccessMemberOrMethodCall(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), start, false);
|
---|
790 | }
|
---|
791 | else if (this.next.isNumber()) {
|
---|
792 | const value = this.next.toNumber();
|
---|
793 | this.advance();
|
---|
794 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), value);
|
---|
795 | }
|
---|
796 | else if (this.next.isString()) {
|
---|
797 | const literalValue = this.next.toString();
|
---|
798 | this.advance();
|
---|
799 | return new LiteralPrimitive(this.span(start), this.sourceSpan(start), literalValue);
|
---|
800 | }
|
---|
801 | else if (this.next.isPrivateIdentifier()) {
|
---|
802 | this._reportErrorForPrivateIdentifier(this.next, null);
|
---|
803 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
804 | }
|
---|
805 | else if (this.index >= this.tokens.length) {
|
---|
806 | this.error(`Unexpected end of expression: ${this.input}`);
|
---|
807 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
808 | }
|
---|
809 | else {
|
---|
810 | this.error(`Unexpected token ${this.next}`);
|
---|
811 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
812 | }
|
---|
813 | }
|
---|
814 | parseExpressionList(terminator) {
|
---|
815 | const result = [];
|
---|
816 | do {
|
---|
817 | if (!this.next.isCharacter(terminator)) {
|
---|
818 | result.push(this.parsePipe());
|
---|
819 | }
|
---|
820 | else {
|
---|
821 | break;
|
---|
822 | }
|
---|
823 | } while (this.consumeOptionalCharacter(chars.$COMMA));
|
---|
824 | return result;
|
---|
825 | }
|
---|
826 | parseLiteralMap() {
|
---|
827 | const keys = [];
|
---|
828 | const values = [];
|
---|
829 | const start = this.inputIndex;
|
---|
830 | this.expectCharacter(chars.$LBRACE);
|
---|
831 | if (!this.consumeOptionalCharacter(chars.$RBRACE)) {
|
---|
832 | this.rbracesExpected++;
|
---|
833 | do {
|
---|
834 | const keyStart = this.inputIndex;
|
---|
835 | const quoted = this.next.isString();
|
---|
836 | const key = this.expectIdentifierOrKeywordOrString();
|
---|
837 | keys.push({ key, quoted });
|
---|
838 | // Properties with quoted keys can't use the shorthand syntax.
|
---|
839 | if (quoted) {
|
---|
840 | this.expectCharacter(chars.$COLON);
|
---|
841 | values.push(this.parsePipe());
|
---|
842 | }
|
---|
843 | else if (this.consumeOptionalCharacter(chars.$COLON)) {
|
---|
844 | values.push(this.parsePipe());
|
---|
845 | }
|
---|
846 | else {
|
---|
847 | const span = this.span(keyStart);
|
---|
848 | const sourceSpan = this.sourceSpan(keyStart);
|
---|
849 | values.push(new PropertyRead(span, sourceSpan, sourceSpan, new ImplicitReceiver(span, sourceSpan), key));
|
---|
850 | }
|
---|
851 | } while (this.consumeOptionalCharacter(chars.$COMMA));
|
---|
852 | this.rbracesExpected--;
|
---|
853 | this.expectCharacter(chars.$RBRACE);
|
---|
854 | }
|
---|
855 | return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values);
|
---|
856 | }
|
---|
857 | parseAccessMemberOrMethodCall(receiver, start, isSafe) {
|
---|
858 | const nameStart = this.inputIndex;
|
---|
859 | const id = this.withContext(ParseContextFlags.Writable, () => {
|
---|
860 | var _a;
|
---|
861 | const id = (_a = this.expectIdentifierOrKeyword()) !== null && _a !== void 0 ? _a : '';
|
---|
862 | if (id.length === 0) {
|
---|
863 | this.error(`Expected identifier for property access`, receiver.span.end);
|
---|
864 | }
|
---|
865 | return id;
|
---|
866 | });
|
---|
867 | const nameSpan = this.sourceSpan(nameStart);
|
---|
868 | if (this.consumeOptionalCharacter(chars.$LPAREN)) {
|
---|
869 | const argumentStart = this.inputIndex;
|
---|
870 | this.rparensExpected++;
|
---|
871 | const args = this.parseCallArguments();
|
---|
872 | const argumentSpan = this.span(argumentStart, this.inputIndex).toAbsolute(this.absoluteOffset);
|
---|
873 | this.expectCharacter(chars.$RPAREN);
|
---|
874 | this.rparensExpected--;
|
---|
875 | const span = this.span(start);
|
---|
876 | const sourceSpan = this.sourceSpan(start);
|
---|
877 | return isSafe ?
|
---|
878 | new SafeMethodCall(span, sourceSpan, nameSpan, receiver, id, args, argumentSpan) :
|
---|
879 | new MethodCall(span, sourceSpan, nameSpan, receiver, id, args, argumentSpan);
|
---|
880 | }
|
---|
881 | else {
|
---|
882 | if (isSafe) {
|
---|
883 | if (this.consumeOptionalOperator('=')) {
|
---|
884 | this.error('The \'?.\' operator cannot be used in the assignment');
|
---|
885 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
886 | }
|
---|
887 | else {
|
---|
888 | return new SafePropertyRead(this.span(start), this.sourceSpan(start), nameSpan, receiver, id);
|
---|
889 | }
|
---|
890 | }
|
---|
891 | else {
|
---|
892 | if (this.consumeOptionalOperator('=')) {
|
---|
893 | if (!this.parseAction) {
|
---|
894 | this.error('Bindings cannot contain assignments');
|
---|
895 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
896 | }
|
---|
897 | const value = this.parseConditional();
|
---|
898 | return new PropertyWrite(this.span(start), this.sourceSpan(start), nameSpan, receiver, id, value);
|
---|
899 | }
|
---|
900 | else {
|
---|
901 | return new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, receiver, id);
|
---|
902 | }
|
---|
903 | }
|
---|
904 | }
|
---|
905 | }
|
---|
906 | parseCallArguments() {
|
---|
907 | if (this.next.isCharacter(chars.$RPAREN))
|
---|
908 | return [];
|
---|
909 | const positionals = [];
|
---|
910 | do {
|
---|
911 | positionals.push(this.parsePipe());
|
---|
912 | } while (this.consumeOptionalCharacter(chars.$COMMA));
|
---|
913 | return positionals;
|
---|
914 | }
|
---|
915 | /**
|
---|
916 | * Parses an identifier, a keyword, a string with an optional `-` in between,
|
---|
917 | * and returns the string along with its absolute source span.
|
---|
918 | */
|
---|
919 | expectTemplateBindingKey() {
|
---|
920 | let result = '';
|
---|
921 | let operatorFound = false;
|
---|
922 | const start = this.currentAbsoluteOffset;
|
---|
923 | do {
|
---|
924 | result += this.expectIdentifierOrKeywordOrString();
|
---|
925 | operatorFound = this.consumeOptionalOperator('-');
|
---|
926 | if (operatorFound) {
|
---|
927 | result += '-';
|
---|
928 | }
|
---|
929 | } while (operatorFound);
|
---|
930 | return {
|
---|
931 | source: result,
|
---|
932 | span: new AbsoluteSourceSpan(start, start + result.length),
|
---|
933 | };
|
---|
934 | }
|
---|
935 | /**
|
---|
936 | * Parse microsyntax template expression and return a list of bindings or
|
---|
937 | * parsing errors in case the given expression is invalid.
|
---|
938 | *
|
---|
939 | * For example,
|
---|
940 | * ```
|
---|
941 | * <div *ngFor="let item of items; index as i; trackBy: func">
|
---|
942 | * ```
|
---|
943 | * contains five bindings:
|
---|
944 | * 1. ngFor -> null
|
---|
945 | * 2. item -> NgForOfContext.$implicit
|
---|
946 | * 3. ngForOf -> items
|
---|
947 | * 4. i -> NgForOfContext.index
|
---|
948 | * 5. ngForTrackBy -> func
|
---|
949 | *
|
---|
950 | * For a full description of the microsyntax grammar, see
|
---|
951 | * https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855
|
---|
952 | *
|
---|
953 | * @param templateKey name of the microsyntax directive, like ngIf, ngFor,
|
---|
954 | * without the *, along with its absolute span.
|
---|
955 | */
|
---|
956 | parseTemplateBindings(templateKey) {
|
---|
957 | const bindings = [];
|
---|
958 | // The first binding is for the template key itself
|
---|
959 | // In *ngFor="let item of items", key = "ngFor", value = null
|
---|
960 | // In *ngIf="cond | pipe", key = "ngIf", value = "cond | pipe"
|
---|
961 | bindings.push(...this.parseDirectiveKeywordBindings(templateKey));
|
---|
962 | while (this.index < this.tokens.length) {
|
---|
963 | // If it starts with 'let', then this must be variable declaration
|
---|
964 | const letBinding = this.parseLetBinding();
|
---|
965 | if (letBinding) {
|
---|
966 | bindings.push(letBinding);
|
---|
967 | }
|
---|
968 | else {
|
---|
969 | // Two possible cases here, either `value "as" key` or
|
---|
970 | // "directive-keyword expression". We don't know which case, but both
|
---|
971 | // "value" and "directive-keyword" are template binding key, so consume
|
---|
972 | // the key first.
|
---|
973 | const key = this.expectTemplateBindingKey();
|
---|
974 | // Peek at the next token, if it is "as" then this must be variable
|
---|
975 | // declaration.
|
---|
976 | const binding = this.parseAsBinding(key);
|
---|
977 | if (binding) {
|
---|
978 | bindings.push(binding);
|
---|
979 | }
|
---|
980 | else {
|
---|
981 | // Otherwise the key must be a directive keyword, like "of". Transform
|
---|
982 | // the key to actual key. Eg. of -> ngForOf, trackBy -> ngForTrackBy
|
---|
983 | key.source =
|
---|
984 | templateKey.source + key.source.charAt(0).toUpperCase() + key.source.substring(1);
|
---|
985 | bindings.push(...this.parseDirectiveKeywordBindings(key));
|
---|
986 | }
|
---|
987 | }
|
---|
988 | this.consumeStatementTerminator();
|
---|
989 | }
|
---|
990 | return new TemplateBindingParseResult(bindings, [] /* warnings */, this.errors);
|
---|
991 | }
|
---|
992 | parseKeyedReadOrWrite(receiver, start, isSafe) {
|
---|
993 | return this.withContext(ParseContextFlags.Writable, () => {
|
---|
994 | this.rbracketsExpected++;
|
---|
995 | const key = this.parsePipe();
|
---|
996 | if (key instanceof EmptyExpr) {
|
---|
997 | this.error(`Key access cannot be empty`);
|
---|
998 | }
|
---|
999 | this.rbracketsExpected--;
|
---|
1000 | this.expectCharacter(chars.$RBRACKET);
|
---|
1001 | if (this.consumeOptionalOperator('=')) {
|
---|
1002 | if (isSafe) {
|
---|
1003 | this.error('The \'?.\' operator cannot be used in the assignment');
|
---|
1004 | }
|
---|
1005 | else {
|
---|
1006 | const value = this.parseConditional();
|
---|
1007 | return new KeyedWrite(this.span(start), this.sourceSpan(start), receiver, key, value);
|
---|
1008 | }
|
---|
1009 | }
|
---|
1010 | else {
|
---|
1011 | return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) :
|
---|
1012 | new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
|
---|
1013 | }
|
---|
1014 | return new EmptyExpr(this.span(start), this.sourceSpan(start));
|
---|
1015 | });
|
---|
1016 | }
|
---|
1017 | /**
|
---|
1018 | * Parse a directive keyword, followed by a mandatory expression.
|
---|
1019 | * For example, "of items", "trackBy: func".
|
---|
1020 | * The bindings are: ngForOf -> items, ngForTrackBy -> func
|
---|
1021 | * There could be an optional "as" binding that follows the expression.
|
---|
1022 | * For example,
|
---|
1023 | * ```
|
---|
1024 | * *ngFor="let item of items | slice:0:1 as collection".
|
---|
1025 | * ^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
|
---|
1026 | * keyword bound target optional 'as' binding
|
---|
1027 | * ```
|
---|
1028 | *
|
---|
1029 | * @param key binding key, for example, ngFor, ngIf, ngForOf, along with its
|
---|
1030 | * absolute span.
|
---|
1031 | */
|
---|
1032 | parseDirectiveKeywordBindings(key) {
|
---|
1033 | const bindings = [];
|
---|
1034 | this.consumeOptionalCharacter(chars.$COLON); // trackBy: trackByFunction
|
---|
1035 | const value = this.getDirectiveBoundTarget();
|
---|
1036 | let spanEnd = this.currentAbsoluteOffset;
|
---|
1037 | // The binding could optionally be followed by "as". For example,
|
---|
1038 | // *ngIf="cond | pipe as x". In this case, the key in the "as" binding
|
---|
1039 | // is "x" and the value is the template key itself ("ngIf"). Note that the
|
---|
1040 | // 'key' in the current context now becomes the "value" in the next binding.
|
---|
1041 | const asBinding = this.parseAsBinding(key);
|
---|
1042 | if (!asBinding) {
|
---|
1043 | this.consumeStatementTerminator();
|
---|
1044 | spanEnd = this.currentAbsoluteOffset;
|
---|
1045 | }
|
---|
1046 | const sourceSpan = new AbsoluteSourceSpan(key.span.start, spanEnd);
|
---|
1047 | bindings.push(new ExpressionBinding(sourceSpan, key, value));
|
---|
1048 | if (asBinding) {
|
---|
1049 | bindings.push(asBinding);
|
---|
1050 | }
|
---|
1051 | return bindings;
|
---|
1052 | }
|
---|
1053 | /**
|
---|
1054 | * Return the expression AST for the bound target of a directive keyword
|
---|
1055 | * binding. For example,
|
---|
1056 | * ```
|
---|
1057 | * *ngIf="condition | pipe"
|
---|
1058 | * ^^^^^^^^^^^^^^^^ bound target for "ngIf"
|
---|
1059 | * *ngFor="let item of items"
|
---|
1060 | * ^^^^^ bound target for "ngForOf"
|
---|
1061 | * ```
|
---|
1062 | */
|
---|
1063 | getDirectiveBoundTarget() {
|
---|
1064 | if (this.next === EOF || this.peekKeywordAs() || this.peekKeywordLet()) {
|
---|
1065 | return null;
|
---|
1066 | }
|
---|
1067 | const ast = this.parsePipe(); // example: "condition | async"
|
---|
1068 | const { start, end } = ast.span;
|
---|
1069 | const value = this.input.substring(start, end);
|
---|
1070 | return new ASTWithSource(ast, value, this.location, this.absoluteOffset + start, this.errors);
|
---|
1071 | }
|
---|
1072 | /**
|
---|
1073 | * Return the binding for a variable declared using `as`. Note that the order
|
---|
1074 | * of the key-value pair in this declaration is reversed. For example,
|
---|
1075 | * ```
|
---|
1076 | * *ngFor="let item of items; index as i"
|
---|
1077 | * ^^^^^ ^
|
---|
1078 | * value key
|
---|
1079 | * ```
|
---|
1080 | *
|
---|
1081 | * @param value name of the value in the declaration, "ngIf" in the example
|
---|
1082 | * above, along with its absolute span.
|
---|
1083 | */
|
---|
1084 | parseAsBinding(value) {
|
---|
1085 | if (!this.peekKeywordAs()) {
|
---|
1086 | return null;
|
---|
1087 | }
|
---|
1088 | this.advance(); // consume the 'as' keyword
|
---|
1089 | const key = this.expectTemplateBindingKey();
|
---|
1090 | this.consumeStatementTerminator();
|
---|
1091 | const sourceSpan = new AbsoluteSourceSpan(value.span.start, this.currentAbsoluteOffset);
|
---|
1092 | return new VariableBinding(sourceSpan, key, value);
|
---|
1093 | }
|
---|
1094 | /**
|
---|
1095 | * Return the binding for a variable declared using `let`. For example,
|
---|
1096 | * ```
|
---|
1097 | * *ngFor="let item of items; let i=index;"
|
---|
1098 | * ^^^^^^^^ ^^^^^^^^^^^
|
---|
1099 | * ```
|
---|
1100 | * In the first binding, `item` is bound to `NgForOfContext.$implicit`.
|
---|
1101 | * In the second binding, `i` is bound to `NgForOfContext.index`.
|
---|
1102 | */
|
---|
1103 | parseLetBinding() {
|
---|
1104 | if (!this.peekKeywordLet()) {
|
---|
1105 | return null;
|
---|
1106 | }
|
---|
1107 | const spanStart = this.currentAbsoluteOffset;
|
---|
1108 | this.advance(); // consume the 'let' keyword
|
---|
1109 | const key = this.expectTemplateBindingKey();
|
---|
1110 | let value = null;
|
---|
1111 | if (this.consumeOptionalOperator('=')) {
|
---|
1112 | value = this.expectTemplateBindingKey();
|
---|
1113 | }
|
---|
1114 | this.consumeStatementTerminator();
|
---|
1115 | const sourceSpan = new AbsoluteSourceSpan(spanStart, this.currentAbsoluteOffset);
|
---|
1116 | return new VariableBinding(sourceSpan, key, value);
|
---|
1117 | }
|
---|
1118 | /**
|
---|
1119 | * Consume the optional statement terminator: semicolon or comma.
|
---|
1120 | */
|
---|
1121 | consumeStatementTerminator() {
|
---|
1122 | this.consumeOptionalCharacter(chars.$SEMICOLON) || this.consumeOptionalCharacter(chars.$COMMA);
|
---|
1123 | }
|
---|
1124 | /**
|
---|
1125 | * Records an error and skips over the token stream until reaching a recoverable point. See
|
---|
1126 | * `this.skip` for more details on token skipping.
|
---|
1127 | */
|
---|
1128 | error(message, index = null) {
|
---|
1129 | this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location));
|
---|
1130 | this.skip();
|
---|
1131 | }
|
---|
1132 | locationText(index = null) {
|
---|
1133 | if (index == null)
|
---|
1134 | index = this.index;
|
---|
1135 | return (index < this.tokens.length) ? `at column ${this.tokens[index].index + 1} in` :
|
---|
1136 | `at the end of the expression`;
|
---|
1137 | }
|
---|
1138 | /**
|
---|
1139 | * Records an error for an unexpected private identifier being discovered.
|
---|
1140 | * @param token Token representing a private identifier.
|
---|
1141 | * @param extraMessage Optional additional message being appended to the error.
|
---|
1142 | */
|
---|
1143 | _reportErrorForPrivateIdentifier(token, extraMessage) {
|
---|
1144 | let errorMessage = `Private identifiers are not supported. Unexpected private identifier: ${token}`;
|
---|
1145 | if (extraMessage !== null) {
|
---|
1146 | errorMessage += `, ${extraMessage}`;
|
---|
1147 | }
|
---|
1148 | this.error(errorMessage);
|
---|
1149 | }
|
---|
1150 | /**
|
---|
1151 | * Error recovery should skip tokens until it encounters a recovery point.
|
---|
1152 | *
|
---|
1153 | * The following are treated as unconditional recovery points:
|
---|
1154 | * - end of input
|
---|
1155 | * - ';' (parseChain() is always the root production, and it expects a ';')
|
---|
1156 | * - '|' (since pipes may be chained and each pipe expression may be treated independently)
|
---|
1157 | *
|
---|
1158 | * The following are conditional recovery points:
|
---|
1159 | * - ')', '}', ']' if one of calling productions is expecting one of these symbols
|
---|
1160 | * - This allows skip() to recover from errors such as '(a.) + 1' allowing more of the AST to
|
---|
1161 | * be retained (it doesn't skip any tokens as the ')' is retained because of the '(' begins
|
---|
1162 | * an '(' <expr> ')' production).
|
---|
1163 | * The recovery points of grouping symbols must be conditional as they must be skipped if
|
---|
1164 | * none of the calling productions are not expecting the closing token else we will never
|
---|
1165 | * make progress in the case of an extraneous group closing symbol (such as a stray ')').
|
---|
1166 | * That is, we skip a closing symbol if we are not in a grouping production.
|
---|
1167 | * - '=' in a `Writable` context
|
---|
1168 | * - In this context, we are able to recover after seeing the `=` operator, which
|
---|
1169 | * signals the presence of an independent rvalue expression following the `=` operator.
|
---|
1170 | *
|
---|
1171 | * If a production expects one of these token it increments the corresponding nesting count,
|
---|
1172 | * and then decrements it just prior to checking if the token is in the input.
|
---|
1173 | */
|
---|
1174 | skip() {
|
---|
1175 | let n = this.next;
|
---|
1176 | while (this.index < this.tokens.length && !n.isCharacter(chars.$SEMICOLON) &&
|
---|
1177 | !n.isOperator('|') && (this.rparensExpected <= 0 || !n.isCharacter(chars.$RPAREN)) &&
|
---|
1178 | (this.rbracesExpected <= 0 || !n.isCharacter(chars.$RBRACE)) &&
|
---|
1179 | (this.rbracketsExpected <= 0 || !n.isCharacter(chars.$RBRACKET)) &&
|
---|
1180 | (!(this.context & ParseContextFlags.Writable) || !n.isOperator('='))) {
|
---|
1181 | if (this.next.isError()) {
|
---|
1182 | this.errors.push(new ParserError(this.next.toString(), this.input, this.locationText(), this.location));
|
---|
1183 | }
|
---|
1184 | this.advance();
|
---|
1185 | n = this.next;
|
---|
1186 | }
|
---|
1187 | }
|
---|
1188 | }
|
---|
1189 | class SimpleExpressionChecker {
|
---|
1190 | constructor() {
|
---|
1191 | this.errors = [];
|
---|
1192 | }
|
---|
1193 | visitImplicitReceiver(ast, context) { }
|
---|
1194 | visitThisReceiver(ast, context) { }
|
---|
1195 | visitInterpolation(ast, context) { }
|
---|
1196 | visitLiteralPrimitive(ast, context) { }
|
---|
1197 | visitPropertyRead(ast, context) { }
|
---|
1198 | visitPropertyWrite(ast, context) { }
|
---|
1199 | visitSafePropertyRead(ast, context) { }
|
---|
1200 | visitMethodCall(ast, context) { }
|
---|
1201 | visitSafeMethodCall(ast, context) { }
|
---|
1202 | visitFunctionCall(ast, context) { }
|
---|
1203 | visitLiteralArray(ast, context) {
|
---|
1204 | this.visitAll(ast.expressions, context);
|
---|
1205 | }
|
---|
1206 | visitLiteralMap(ast, context) {
|
---|
1207 | this.visitAll(ast.values, context);
|
---|
1208 | }
|
---|
1209 | visitUnary(ast, context) { }
|
---|
1210 | visitBinary(ast, context) { }
|
---|
1211 | visitPrefixNot(ast, context) { }
|
---|
1212 | visitNonNullAssert(ast, context) { }
|
---|
1213 | visitConditional(ast, context) { }
|
---|
1214 | visitPipe(ast, context) {
|
---|
1215 | this.errors.push('pipes');
|
---|
1216 | }
|
---|
1217 | visitKeyedRead(ast, context) { }
|
---|
1218 | visitKeyedWrite(ast, context) { }
|
---|
1219 | visitAll(asts, context) {
|
---|
1220 | return asts.map(node => node.visit(this, context));
|
---|
1221 | }
|
---|
1222 | visitChain(ast, context) { }
|
---|
1223 | visitQuote(ast, context) { }
|
---|
1224 | visitSafeKeyedRead(ast, context) { }
|
---|
1225 | }
|
---|
1226 | /**
|
---|
1227 | * This class implements SimpleExpressionChecker used in View Engine and performs more strict checks
|
---|
1228 | * to make sure host bindings do not contain pipes. In View Engine, having pipes in host bindings is
|
---|
1229 | * not supported as well, but in some cases (like `!(value | async)`) the error is not triggered at
|
---|
1230 | * compile time. In order to preserve View Engine behavior, more strict checks are introduced for
|
---|
1231 | * Ivy mode only.
|
---|
1232 | */
|
---|
1233 | class IvySimpleExpressionChecker extends RecursiveAstVisitor {
|
---|
1234 | constructor() {
|
---|
1235 | super(...arguments);
|
---|
1236 | this.errors = [];
|
---|
1237 | }
|
---|
1238 | visitPipe() {
|
---|
1239 | this.errors.push('pipes');
|
---|
1240 | }
|
---|
1241 | }
|
---|
1242 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tcGlsZXIvc3JjL2V4cHJlc3Npb25fcGFyc2VyL3BhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssS0FBSyxNQUFNLFVBQVUsQ0FBQztBQUNsQyxPQUFPLEVBQUMsNEJBQTRCLEVBQXNCLE1BQU0sbUNBQW1DLENBQUM7QUFFcEcsT0FBTyxFQUFDLGtCQUFrQixFQUFtQixhQUFhLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBaUIsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUE4QyxZQUFZLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUMzZ0IsT0FBTyxFQUFDLEdBQUcsRUFBRSxZQUFZLEVBQWdCLFNBQVMsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQU9uRSxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCLFlBQ1csT0FBNkIsRUFBUyxXQUFpQyxFQUN2RSxPQUFpQjtRQURqQixZQUFPLEdBQVAsT0FBTyxDQUFzQjtRQUFTLGdCQUFXLEdBQVgsV0FBVyxDQUFzQjtRQUN2RSxZQUFPLEdBQVAsT0FBTyxDQUFVO0lBQUcsQ0FBQztDQUNqQztBQUVELE1BQU0sT0FBTywwQkFBMEI7SUFDckMsWUFDVyxnQkFBbUMsRUFBUyxRQUFrQixFQUM5RCxNQUFxQjtRQURyQixx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RUFBRSxPQUFZLElBQUcsQ0FBQztJQUV2QyxXQUFXLENBQUMsR0FBVyxFQUFFLE9BQVksSUFBRyxDQUFDO0lBRXpDLGNBQWMsQ0FBQyxHQUFjLEVBQUUsT0FBWSxJQUFHLENBQUM7SUFFL0Msa0JBQWtCLENBQUMsR0FBa0IsRUFBRSxPQUFZLElBQUcsQ0FBQztJQUV2RCxnQkFBZ0IsQ0FBQyxHQUFnQixFQUFFLE9BQVksSUFBRyxDQUFDO0lBRW5ELFNBQVMsQ0FBQyxHQUFnQixFQUFFLE9BQVk7UUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELGNBQWMsQ0FBQyxHQUFjLEVBQUUsT0FBWSxJQUFHLENBQUM7SUFFL0MsZUFBZSxDQUFDLEdBQWUsRUFBRSxPQUFZLElBQUcsQ0FBQztJQUVqRCxRQUFRLENBQUMsSUFBVyxFQUFFLE9BQVk7UUFDaEMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsVUFBVSxDQUFDLEdBQVUsRUFBRSxPQUFZLElBQUcsQ0FBQztJQUV2QyxVQUFVLENBQUMsR0FBVSxFQUFFLE9BQVksSUFBRyxDQUFDO0lBRXZDLGtCQUFrQixDQUFDLEdBQWtCLEVBQUUsT0FBWSxJQUFHLENBQUM7Q0FDeEQ7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLDBCQUEyQixTQUFRLG1CQUFtQjtJQUE1RDs7UUFDRSxXQUFNLEdBQWEsRUFBRSxDQUFDO0lBS3hCLENBQUM7SUFIVSxTQUFTO1FBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgKiBhcyBjaGFycyBmcm9tICcuLi9jaGFycyc7XG5pbXBvcnQge0RFRkFVTFRfSU5URVJQT0xBVElPTl9DT05GSUcsIEludGVycG9sYXRpb25Db25maWd9IGZyb20gJy4uL21sX3BhcnNlci9pbnRlcnBvbGF0aW9uX2NvbmZpZyc7XG5cbmltcG9ydCB7QWJzb2x1dGVTb3VyY2VTcGFuLCBBU1QsIEFzdFZpc2l0b3IsIEFTVFdpdGhTb3VyY2UsIEJpbmFyeSwgQmluZGluZ1BpcGUsIENoYWluLCBDb25kaXRpb25hbCwgRW1wdHlFeHByLCBFeHByZXNzaW9uQmluZGluZywgRnVuY3Rpb25DYWxsLCBJbXBsaWNpdFJlY2VpdmVyLCBJbnRlcnBvbGF0aW9uLCBLZXllZFJlYWQsIEtleWVkV3JpdGUsIExpdGVyYWxBcnJheSwgTGl0ZXJhbE1hcCwgTGl0ZXJhbE1hcEtleSwgTGl0ZXJhbFByaW1pdGl2ZSwgTWV0aG9kQ2FsbCwgTm9uTnVsbEFzc2VydCwgUGFyc2VyRXJyb3IsIFBhcnNlU3BhbiwgUHJlZml4Tm90LCBQcm9wZXJ0eVJlYWQsIFByb3BlcnR5V3JpdGUsIFF1b3RlLCBSZWN1cnNpdmVBc3RWaXNpdG9yLCBTYWZlS2V5ZWRSZWFkLCBTYWZlTWV0aG9kQ2FsbCwgU2FmZVByb3BlcnR5UmVhZCwgVGVtcGxhdGVCaW5kaW5nLCBUZW1wbGF0ZUJpbmRpbmdJZGVudGlmaWVyLCBUaGlzUmVjZWl2ZXIsIFVuYXJ5LCBWYXJpYWJsZUJpbmRpbmd9IGZyb20gJy4vYXN0JztcbmltcG9ydCB7RU9GLCBpc0lkZW50aWZpZXIsIExleGVyLCBUb2tlbiwgVG9rZW5UeXBlfSBmcm9tICcuL2xleGVyJztcblxuZXhwb3J0IGludGVyZmFjZSBJbnRlcnBvbGF0aW9uUGllY2Uge1xuICB0ZXh0OiBzdHJpbmc7XG4gIHN0YXJ0OiBudW1iZXI7XG4gIGVuZDogbnVtYmVyO1xufVxuZXhwb3J0IGNsYXNzIFNwbGl0SW50ZXJwb2xhdGlvbiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIHN0cmluZ3M6IEludGVycG9sYXRpb25QaWVjZVtdLCBwdWJsaWMgZXhwcmVzc2lvbnM6IEludGVycG9sYXRpb25QaWVjZVtdLFxuICAgICAgcHVibGljIG9mZnNldHM6IG51bWJlcltdKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgVGVtcGxhdGVCaW5kaW5nUGFyc2VSZXN1bHQge1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHB1YmxpYyB0ZW1wbGF0ZUJpbmRpbmdzOiBUZW1wbGF0ZUJpbmRpbmdbXSwgcHVibGljIHdhcm5pbmdzOiBzdHJpbmdbXSxcbiAgICAgIHB1YmxpYyBlcnJvcnM6IFBhcnNlckVycm9yW10pIHt9XG59XG5cbmV4cG9ydCBjbGFzcyBQYXJzZXIge1xuICBwcml2YXRlIGVycm9yczogUGFyc2VyRXJyb3JbXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2xleGVyOiBMZXhlcikge31cblxuICBzaW1wbGVFeHByZXNzaW9uQ2hlY2tlciA9IFNpbXBsZUV4cHJlc3Npb25DaGVja2VyO1xuXG4gIHBhcnNlQWN0aW9uKFxuICAgICAgaW5wdXQ6IHN0cmluZywgbG9jYXRpb246IHN0cmluZywgYWJzb2x1dGVPZmZzZXQ6IG51bWJlcixcbiAgICAgIGludGVycG9sYXRpb25Db25maWc6IEludGVycG9sYXRpb25Db25maWcgPSBERUZBVUxUX0lOVEVSUE9MQVRJT05fQ09ORklHKTogQVNUV2l0aFNvdXJjZSB7XG4gICAgdGhpcy5fY2hlY2tOb0ludGVycG9sYXRpb24oaW5wdXQsIGxvY2F0aW9uLCBpbnRlcnBvbGF0aW9uQ29uZmlnKTtcbiAgICBjb25zdCBzb3VyY2VUb0xleCA9IHRoaXMuX3N0cmlwQ29tbWVudHMoaW5wdXQpO1xuICAgIGNvbnN0IHRva2VucyA9IHRoaXMuX2xleGVyLnRva2VuaXplKHRoaXMuX3N0cmlwQ29tbWVudHMoaW5wdXQpKTtcbiAgICBjb25zdCBhc3QgPSBuZXcgX1BhcnNlQVNUKFxuICAgICAgICAgICAgICAgICAgICBpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCB0b2tlbnMsIHNvdXJjZVRvTGV4Lmxlbmd0aCwgdHJ1ZSwgdGhpcy5lcnJvcnMsXG4gICAgICAgICAgICAgICAgICAgIGlucHV0Lmxlbmd0aCAtIHNvdXJjZVRvTGV4Lmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgLnBhcnNlQ2hhaW4oKTtcbiAgICByZXR1cm4gbmV3IEFTVFdpdGhTb3VyY2UoYXN0LCBpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCB0aGlzLmVycm9ycyk7XG4gIH1cblxuICBwYXJzZUJpbmRpbmcoXG4gICAgICBpbnB1dDogc3RyaW5nLCBsb2NhdGlvbjogc3RyaW5nLCBhYnNvbHV0ZU9mZnNldDogbnVtYmVyLFxuICAgICAgaW50ZXJwb2xhdGlvbkNvbmZpZzogSW50ZXJwb2xhdGlvbkNvbmZpZyA9IERFRkFVTFRfSU5URVJQT0xBVElPTl9DT05GSUcpOiBBU1RXaXRoU291cmNlIHtcbiAgICBjb25zdCBhc3QgPSB0aGlzLl9wYXJzZUJpbmRpbmdBc3QoaW5wdXQsIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCwgaW50ZXJwb2xhdGlvbkNvbmZpZyk7XG4gICAgcmV0dXJuIG5ldyBBU1RXaXRoU291cmNlKGFzdCwgaW5wdXQsIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCwgdGhpcy5lcnJvcnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja1NpbXBsZUV4cHJlc3Npb24oYXN0OiBBU1QpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgY2hlY2tlciA9IG5ldyB0aGlzLnNpbXBsZUV4cHJlc3Npb25DaGVja2VyKCk7XG4gICAgYXN0LnZpc2l0KGNoZWNrZXIpO1xuICAgIHJldHVybiBjaGVja2VyLmVycm9ycztcbiAgfVxuXG4gIHBhcnNlU2ltcGxlQmluZGluZyhcbiAgICAgIGlucHV0OiBzdHJpbmcsIGxvY2F0aW9uOiBzdHJpbmcsIGFic29sdXRlT2Zmc2V0OiBudW1iZXIsXG4gICAgICBpbnRlcnBvbGF0aW9uQ29uZmlnOiBJbnRlcnBvbGF0aW9uQ29uZmlnID0gREVGQVVMVF9JTlRFUlBPTEFUSU9OX0NPTkZJRyk6IEFTVFdpdGhTb3VyY2Uge1xuICAgIGNvbnN0IGFzdCA9IHRoaXMuX3BhcnNlQmluZGluZ0FzdChpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCBpbnRlcnBvbGF0aW9uQ29uZmlnKTtcbiAgICBjb25zdCBlcnJvcnMgPSB0aGlzLmNoZWNrU2ltcGxlRXhwcmVzc2lvbihhc3QpO1xuICAgIGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5fcmVwb3J0RXJyb3IoXG4gICAgICAgICAgYEhvc3QgYmluZGluZyBleHByZXNzaW9uIGNhbm5vdCBjb250YWluICR7ZXJyb3JzLmpvaW4oJyAnKX1gLCBpbnB1dCwgbG9jYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEFTVFdpdGhTb3VyY2UoYXN0LCBpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCB0aGlzLmVycm9ycyk7XG4gIH1cblxuICBwcml2YXRlIF9yZXBvcnRFcnJvcihtZXNzYWdlOiBzdHJpbmcsIGlucHV0OiBzdHJpbmcsIGVyckxvY2F0aW9uOiBzdHJpbmcsIGN0eExvY2F0aW9uPzogc3RyaW5nKSB7XG4gICAgdGhpcy5lcnJvcnMucHVzaChuZXcgUGFyc2VyRXJyb3IobWVzc2FnZSwgaW5wdXQsIGVyckxvY2F0aW9uLCBjdHhMb2NhdGlvbikpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcGFyc2VCaW5kaW5nQXN0KFxuICAgICAgaW5wdXQ6IHN0cmluZywgbG9jYXRpb246IHN0cmluZywgYWJzb2x1dGVPZmZzZXQ6IG51bWJlcixcbiAgICAgIGludGVycG9sYXRpb25Db25maWc6IEludGVycG9sYXRpb25Db25maWcpOiBBU1Qge1xuICAgIC8vIFF1b3RlcyBleHByZXNzaW9ucyB1c2UgM3JkLXBhcnR5IGV4cHJlc3Npb24gbGFuZ3VhZ2UuIFdlIGRvbid0IHdhbnQgdG8gdXNlXG4gICAgLy8gb3VyIGxleGVyIG9yIHBhcnNlciBmb3IgdGhhdCwgc28gd2UgY2hlY2sgZm9yIHRoYXQgYWhlYWQgb2YgdGltZS5cbiAgICBjb25zdCBxdW90ZSA9IHRoaXMuX3BhcnNlUXVvdGUoaW5wdXQsIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCk7XG5cbiAgICBpZiAocXVvdGUgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHF1b3RlO1xuICAgIH1cblxuICAgIHRoaXMuX2NoZWNrTm9JbnRlcnBvbGF0aW9uKGlucHV0LCBsb2NhdGlvbiwgaW50ZXJwb2xhdGlvbkNvbmZpZyk7XG4gICAgY29uc3Qgc291cmNlVG9MZXggPSB0aGlzLl9zdHJpcENvbW1lbnRzKGlucHV0KTtcbiAgICBjb25zdCB0b2tlbnMgPSB0aGlzLl9sZXhlci50b2tlbml6ZShzb3VyY2VUb0xleCk7XG4gICAgcmV0dXJuIG5ldyBfUGFyc2VBU1QoXG4gICAgICAgICAgICAgICBpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCB0b2tlbnMsIHNvdXJjZVRvTGV4Lmxlbmd0aCwgZmFsc2UsIHRoaXMuZXJyb3JzLFxuICAgICAgICAgICAgICAgaW5wdXQubGVuZ3RoIC0gc291cmNlVG9MZXgubGVuZ3RoKVxuICAgICAgICAucGFyc2VDaGFpbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcGFyc2VRdW90ZShpbnB1dDogc3RyaW5nfG51bGwsIGxvY2F0aW9uOiBzdHJpbmcsIGFic29sdXRlT2Zmc2V0OiBudW1iZXIpOiBBU1R8bnVsbCB7XG4gICAgaWYgKGlucHV0ID09IG51bGwpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHByZWZpeFNlcGFyYXRvckluZGV4ID0gaW5wdXQuaW5kZXhPZignOicpO1xuICAgIGlmIChwcmVmaXhTZXBhcmF0b3JJbmRleCA9PSAtMSkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgcHJlZml4ID0gaW5wdXQuc3Vic3RyaW5nKDAsIHByZWZpeFNlcGFyYXRvckluZGV4KS50cmltKCk7XG4gICAgaWYgKCFpc0lkZW50aWZpZXIocHJlZml4KSkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgdW5pbnRlcnByZXRlZEV4cHJlc3Npb24gPSBpbnB1dC5zdWJzdHJpbmcocHJlZml4U2VwYXJhdG9ySW5kZXggKyAxKTtcbiAgICBjb25zdCBzcGFuID0gbmV3IFBhcnNlU3BhbigwLCBpbnB1dC5sZW5ndGgpO1xuICAgIHJldHVybiBuZXcgUXVvdGUoXG4gICAgICAgIHNwYW4sIHNwYW4udG9BYnNvbHV0ZShhYnNvbHV0ZU9mZnNldCksIHByZWZpeCwgdW5pbnRlcnByZXRlZEV4cHJlc3Npb24sIGxvY2F0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBtaWNyb3N5bnRheCB0ZW1wbGF0ZSBleHByZXNzaW9uIGFuZCByZXR1cm4gYSBsaXN0IG9mIGJpbmRpbmdzIG9yXG4gICAqIHBhcnNpbmcgZXJyb3JzIGluIGNhc2UgdGhlIGdpdmVuIGV4cHJlc3Npb24gaXMgaW52YWxpZC5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsXG4gICAqIGBgYFxuICAgKiAgIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaXRlbXNcIj5cbiAgICogICAgICAgICBeICAgICAgXiBhYnNvbHV0ZVZhbHVlT2Zmc2V0IGZvciBgdGVtcGxhdGVWYWx1ZWBcbiAgICogICAgICAgICBhYnNvbHV0ZUtleU9mZnNldCBmb3IgYHRlbXBsYXRlS2V5YFxuICAgKiBgYGBcbiAgICogY29udGFpbnMgdGhyZWUgYmluZGluZ3M6XG4gICAqIDEuIG5nRm9yIC0+IG51bGxcbiAgICogMi4gaXRlbSAtPiBOZ0Zvck9mQ29udGV4dC4kaW1wbGljaXRcbiAgICogMy4gbmdGb3JPZiAtPiBpdGVtc1xuICAgKlxuICAgKiBUaGlzIGlzIGFwcGFyZW50IGZyb20gdGhlIGRlLXN1Z2FyZWQgdGVtcGxhdGU6XG4gICAqIGBgYFxuICAgKiAgIDxuZy10ZW1wbGF0ZSBuZ0ZvciBsZXQtaXRlbSBbbmdGb3JPZl09XCJpdGVtc1wiPlxuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIHRlbXBsYXRlS2V5IG5hbWUgb2YgZGlyZWN0aXZlLCB3aXRob3V0IHRoZSAqIHByZWZpeC4gRm9yIGV4YW1wbGU6IG5nSWYsIG5nRm9yXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZVZhbHVlIFJIUyBvZiB0aGUgbWljcm9zeW50YXggYXR0cmlidXRlXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZVVybCB0ZW1wbGF0ZSBmaWxlbmFtZSBpZiBpdCdzIGV4dGVybmFsLCBjb21wb25lbnQgZmlsZW5hbWUgaWYgaXQncyBpbmxpbmVcbiAgICogQHBhcmFtIGFic29sdXRlS2V5T2Zmc2V0IHN0YXJ0IG9mIHRoZSBgdGVtcGxhdGVLZXlgXG4gICAqIEBwYXJhbSBhYnNvbHV0ZVZhbHVlT2Zmc2V0IHN0YXJ0IG9mIHRoZSBgdGVtcGxhdGVWYWx1ZWBcbiAgICovXG4gIHBhcnNlVGVtcGxhdGVCaW5kaW5ncyhcbiAgICAgIHRlbXBsYXRlS2V5OiBzdHJpbmcsIHRlbXBsYXRlVmFsdWU6IHN0cmluZywgdGVtcGxhdGVVcmw6IHN0cmluZywgYWJzb2x1dGVLZXlPZmZzZXQ6IG51bWJlcixcbiAgICAgIGFic29sdXRlVmFsdWVPZmZzZXQ6IG51bWJlcik6IFRlbXBsYXRlQmluZGluZ1BhcnNlUmVzdWx0IHtcbiAgICBjb25zdCB0b2tlbnMgPSB0aGlzLl9sZXhlci50b2tlbml6ZSh0ZW1wbGF0ZVZhbHVlKTtcbiAgICBjb25zdCBwYXJzZXIgPSBuZXcgX1BhcnNlQVNUKFxuICAgICAgICB0ZW1wbGF0ZVZhbHVlLCB0ZW1wbGF0ZVVybCwgYWJzb2x1dGVWYWx1ZU9mZnNldCwgdG9rZW5zLCB0ZW1wbGF0ZVZhbHVlLmxlbmd0aCxcbiAgICAgICAgZmFsc2UgLyogcGFyc2VBY3Rpb24gKi8sIHRoaXMuZXJyb3JzLCAwIC8qIHJlbGF0aXZlIG9mZnNldCAqLyk7XG4gICAgcmV0dXJuIHBhcnNlci5wYXJzZVRlbXBsYXRlQmluZGluZ3Moe1xuICAgICAgc291cmNlOiB0ZW1wbGF0ZUtleSxcbiAgICAgIHNwYW46IG5ldyBBYnNvbHV0ZVNvdXJjZVNwYW4oYWJzb2x1dGVLZXlPZmZzZXQsIGFic29sdXRlS2V5T2Zmc2V0ICsgdGVtcGxhdGVLZXkubGVuZ3RoKSxcbiAgICB9KTtcbiAgfVxuXG4gIHBhcnNlSW50ZXJwb2xhdGlvbihcbiAgICAgIGlucHV0OiBzdHJpbmcsIGxvY2F0aW9uOiBzdHJpbmcsIGFic29sdXRlT2Zmc2V0OiBudW1iZXIsXG4gICAgICBpbnRlcnBvbGF0aW9uQ29uZmlnOiBJbnRlcnBvbGF0aW9uQ29uZmlnID0gREVGQVVMVF9JTlRFUlBPTEFUSU9OX0NPTkZJRyk6IEFTVFdpdGhTb3VyY2V8bnVsbCB7XG4gICAgY29uc3Qge3N0cmluZ3MsIGV4cHJlc3Npb25zLCBvZmZzZXRzfSA9XG4gICAgICAgIHRoaXMuc3BsaXRJbnRlcnBvbGF0aW9uKGlucHV0LCBsb2NhdGlvbiwgaW50ZXJwb2xhdGlvbkNvbmZpZyk7XG4gICAgaWYgKGV4cHJlc3Npb25zLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBleHByZXNzaW9uTm9kZXM6IEFTVFtdID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cHJlc3Npb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICBjb25zdCBleHByZXNzaW9uVGV4dCA9IGV4cHJlc3Npb25zW2ldLnRleHQ7XG4gICAgICBjb25zdCBzb3VyY2VUb0xleCA9IHRoaXMuX3N0cmlwQ29tbWVudHMoZXhwcmVzc2lvblRleHQpO1xuICAgICAgY29uc3QgdG9rZW5zID0gdGhpcy5fbGV4ZXIudG9rZW5pemUoc291cmNlVG9MZXgpO1xuICAgICAgY29uc3QgYXN0ID0gbmV3IF9QYXJzZUFTVChcbiAgICAgICAgICAgICAgICAgICAgICBpbnB1dCwgbG9jYXRpb24sIGFic29sdXRlT2Zmc2V0LCB0b2tlbnMsIHNvdXJjZVRvTGV4Lmxlbmd0aCwgZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5lcnJvcnMsIG9mZnNldHNbaV0gKyAoZXhwcmVzc2lvblRleHQubGVuZ3RoIC0gc291cmNlVG9MZXgubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAucGFyc2VDaGFpbigpO1xuICAgICAgZXhwcmVzc2lvbk5vZGVzLnB1c2goYXN0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jcmVhdGVJbnRlcnBvbGF0aW9uQXN0KFxuICAgICAgICBzdHJpbmdzLm1hcChzID0+IHMudGV4dCksIGV4cHJlc3Npb25Ob2RlcywgaW5wdXQsIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCk7XG4gIH1cblxuICAvKipcbiAgICogU2ltaWxhciB0byBgcGFyc2VJbnRlcnBvbGF0aW9uYCwgYnV0IHRyZWF0cyB0aGUgcHJvdmlkZWQgc3RyaW5nIGFzIGEgc2luZ2xlIGV4cHJlc3Npb25cbiAgICogZWxlbWVudCB0aGF0IHdvdWxkIG5vcm1hbGx5IGFwcGVhciB3aXRoaW4gdGhlIGludGVycG9sYXRpb24gcHJlZml4IGFuZCBzdWZmaXggKGB7e2AgYW5kIGB9fWApLlxuICAgKiBUaGlzIGlzIHVzZWQgZm9yIHBhcnNpbmcgdGhlIHN3aXRjaCBleHByZXNzaW9uIGluIElDVXMuXG4gICAqL1xuICBwYXJzZUludGVycG9sYXRpb25FeHByZXNzaW9uKGV4cHJlc3Npb246IHN0cmluZywgbG9jYXRpb246IHN0cmluZywgYWJzb2x1dGVPZmZzZXQ6IG51bWJlcik6XG4gICAgICBBU1RXaXRoU291cmNlIHtcbiAgICBjb25zdCBzb3VyY2VUb0xleCA9IHRoaXMuX3N0cmlwQ29tbWVudHMoZXhwcmVzc2lvbik7XG4gICAgY29uc3QgdG9rZW5zID0gdGhpcy5fbGV4ZXIudG9rZW5pemUoc291cmNlVG9MZXgpO1xuICAgIGNvbnN0IGFzdCA9IG5ldyBfUGFyc2VBU1QoXG4gICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb24sIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCwgdG9rZW5zLCBzb3VyY2VUb0xleC5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIC8qIHBhcnNlQWN0aW9uICovIGZhbHNlLCB0aGlzLmVycm9ycywgMClcbiAgICAgICAgICAgICAgICAgICAgLnBhcnNlQ2hhaW4oKTtcbiAgICBjb25zdCBzdHJpbmdzID0gWycnLCAnJ107ICAvLyBUaGUgcHJlZml4IGFuZCBzdWZmaXggc3RyaW5ncyBhcmUgYm90aCBlbXB0eVxuICAgIHJldHVybiB0aGlzLmNyZWF0ZUludGVycG9sYXRpb25Bc3Qoc3RyaW5ncywgW2FzdF0sIGV4cHJlc3Npb24sIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUludGVycG9sYXRpb25Bc3QoXG4gICAgICBzdHJpbmdzOiBzdHJpbmdbXSwgZXhwcmVzc2lvbnM6IEFTVFtdLCBpbnB1dDogc3RyaW5nLCBsb2NhdGlvbjogc3RyaW5nLFxuICAgICAgYWJzb2x1dGVPZmZzZXQ6IG51bWJlcik6IEFTVFdpdGhTb3VyY2Uge1xuICAgIGNvbnN0IHNwYW4gPSBuZXcgUGFyc2VTcGFuKDAsIGlucHV0Lmxlbmd0aCk7XG4gICAgY29uc3QgaW50ZXJwb2xhdGlvbiA9XG4gICAgICAgIG5ldyBJbnRlcnBvbGF0aW9uKHNwYW4sIHNwYW4udG9BYnNvbHV0ZShhYnNvbHV0ZU9mZnNldCksIHN0cmluZ3MsIGV4cHJlc3Npb25zKTtcbiAgICByZXR1cm4gbmV3IEFTVFdpdGhTb3VyY2UoaW50ZXJwb2xhdGlvbiwgaW5wdXQsIGxvY2F0aW9uLCBhYnNvbHV0ZU9mZnNldCwgdGhpcy5lcnJvcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0cyBhIHN0cmluZyBvZiB0ZXh0IGludG8gXCJyYXdcIiB0ZXh0IHNlZ21lbnRzIGFuZCBleHByZXNzaW9ucyBwcmVzZW50IGluIGludGVycG9sYXRpb25zIGluXG4gICAqIHRoZSBzdHJpbmcuXG4gICAqIFJldHVybnMgYG51bGxgIGlmIHRoZXJlIGFyZSBubyBpbnRlcnBvbGF0aW9ucywgb3RoZXJ3aXNlIGFcbiAgICogYFNwbGl0SW50ZXJwb2xhdGlvbmAgd2l0aCBzcGxpdHMgdGhhdCBsb29rIGxpa2VcbiAgICogICA8cmF3IHRleHQ+IDxleHByZXNzaW9uPiA8cmF3IHRleHQ+IC4uLiA8cmF3IHRleHQ+IDxleHByZXNzaW9uPiA8cmF3IHRleHQ+XG4gICAqL1xuICBzcGxpdEludGVycG9sYXRpb24oXG4gICAgICBpbnB1dDogc3RyaW5nLCBsb2NhdGlvbjogc3RyaW5nLFxuICAgICAgaW50ZXJwb2xhdGlvbkNvbmZpZzogSW50ZXJwb2xhdGlvbkNvbmZpZyA9IERFRkFVTFRfSU5URVJQT0xBVElPTl9DT05GSUcpOiBTcGxpdEludGVycG9sYXRpb24ge1xuICAgIGNvbnN0IHN0cmluZ3M6IEludGVycG9sYXRpb25QaWVjZVtdID0gW107XG4gICAgY29uc3QgZXhwcmVzc2lvbnM6IEludGVycG9sYXRpb25QaWVjZVtdID0gW107XG4gICAgY29uc3Qgb2Zmc2V0czogbnVtYmVyW10gPSBbXTtcbiAgICBsZXQgaSA9IDA7XG4gICAgbGV0IGF0SW50ZXJwb2xhdGlvbiA9IGZhbHNlO1xuICAgIGxldCBleHRlbmRMYXN0U3RyaW5nID0gZmFsc2U7XG4gICAgbGV0IHtzdGFydDogaW50ZXJwU3RhcnQsIGVuZDogaW50ZXJwRW5kfSA9IGludGVycG9sYXRpb25Db25maWc7XG4gICAgd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpIHtcbiAgICAgIGlmICghYXRJbnRlcnBvbGF0aW9uKSB7XG4gICAgICAgIC8vIHBhcnNlIHVudGlsIHN0YXJ0aW5nIHt7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gaTtcbiAgICAgICAgaSA9IGlucHV0LmluZGV4T2YoaW50ZXJwU3RhcnQsIGkpO1xuICAgICAgICBpZiAoaSA9PT0gLTEpIHtcbiAgICAgICAgICBpID0gaW5wdXQubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRleHQgPSBpbnB1dC5zdWJzdHJpbmcoc3RhcnQsIGkpO1xuICAgICAgICBzdHJpbmdzLnB1c2goe3RleHQsIHN0YXJ0LCBlbmQ6IGl9KTtcblxuICAgICAgICBhdEludGVycG9sYXRpb24gPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcGFyc2UgZnJvbSBzdGFydGluZyB7eyB0byBlbmRpbmcgfX0gd2hpbGUgaWdub3JpbmcgY29udGVudCBpbnNpZGUgcXVvdGVzLlxuICAgICAgICBjb25zdCBmdWxsU3RhcnQgPSBpO1xuICAgICAgICBjb25zdCBleHByU3RhcnQgPSBmdWxsU3RhcnQgKyBpbnRlcnBTdGFydC5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGV4cHJFbmQgPSB0aGlzLl9nZXRJbnRlcnBvbGF0aW9uRW5kSW5kZXgoaW5wdXQsIGludGVycEVuZCwgZXhwclN0YXJ0KTtcbiAgICAgICAgaWYgKGV4cHJFbmQgPT09IC0xKSB7XG4gICAgICAgICAgLy8gQ291bGQgbm90IGZpbmQgdGhlIGVuZCBvZiB0aGUgaW50ZXJwb2xhdGlvbjsgZG8gbm90IHBhcnNlIGFuIGV4cHJlc3Npb24uXG4gICAgICAgICAgLy8gSW5zdGVhZCB3ZSBzaG91bGQgZXh0ZW5kIHRoZSBjb250ZW50IG9uIHRoZSBsYXN0IHJhdyBzdHJpbmcuXG4gICAgICAgICAgYXRJbnRlcnBvbGF0aW9uID0gZmFsc2U7XG4gICAgICAgICAgZXh0ZW5kTGFzdFN0cmluZyA9IHRydWU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZnVsbEVuZCA9IGV4cHJFbmQgKyBpbnRlcnBFbmQubGVuZ3RoO1xuXG4gICAgICAgIGNvbnN0IHRleHQgPSBpbnB1dC5zdWJzdHJpbmcoZXhwclN0YXJ0LCBleHByRW5kKTtcbiAgICAgICAgaWYgKHRleHQudHJpbSgpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuX3JlcG9ydEVycm9yKFxuICAgICAgICAgICAgICAnQmxhbmsgZXhwcmVzc2lvbnMgYXJlIG5vdCBhbGxvd2VkIGluIGludGVycG9sYXRlZCBzdHJpbmdzJywgaW5wdXQsXG4gICAgICAgICAgICAgIGBhdCBjb2x1bW4gJHtpfSBpbmAsIGxvY2F0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBleHByZXNzaW9ucy5wdXNoKHt0ZXh0LCBzdGFydDogZnVsbFN0YXJ0LCBlbmQ6IGZ1bGxFbmR9KTtcbiAgICAgICAgb2Zmc2V0cy5wdXNoKGV4cHJTdGFydCk7XG5cbiAgICAgICAgaSA9IGZ1bGxFbmQ7XG4gICAgICAgIGF0SW50ZXJwb2xhdGlvbiA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWF0SW50ZXJwb2xhdGlvbikge1xuICAgICAgLy8gSWYgd2UgYXJlIG5vdyBhdCBhIHRleHQgc2VjdGlvbiwgYWRkIHRoZSByZW1haW5pbmcgY29udGVudCBhcyBhIHJhdyBzdHJpbmcuXG4gICAgICBpZiAoZXh0ZW5kTGFzdFN0cmluZykge1xuICAgICAgICBjb25zdCBwaWVjZSA9IHN0cmluZ3Nbc3RyaW5ncy5sZW5ndGggLSAxXTtcbiAgICAgICAgcGllY2UudGV4dCArPSBpbnB1dC5zdWJzdHJpbmcoaSk7XG4gICAgICAgIHBpZWNlLmVuZCA9IGlucHV0Lmxlbmd0aDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmluZ3MucHVzaCh7dGV4dDogaW5wdXQuc3Vic3RyaW5nKGkpLCBzdGFydDogaSwgZW5kOiBpbnB1dC5sZW5ndGh9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBTcGxpdEludGVycG9sYXRpb24oc3RyaW5ncywgZXhwcmVzc2lvbnMsIG9mZnNldHMpO1xuICB9XG5cbiAgd3JhcExpdGVyYWxQcmltaXRpdmUoaW5wdXQ6IHN0cmluZ3xudWxsLCBsb2NhdGlvbjogc3RyaW5nLCBhYnNvbHV0ZU9mZnNldDogbnVtYmVyKTpcbiAgICAgIEFTVFdpdGhTb3VyY2Uge1xuICAgIGNvbnN0IHNwYW4gPSBuZXcgUGFyc2VTcGFuKDAsIGlucHV0ID09IG51bGwgPyAwIDogaW5wdXQubGVuZ3RoKTtcbiAgICByZXR1cm4gbmV3IEFTVFdpdGhTb3VyY2UoXG4gICAgICAgIG5ldyBMaXRlcmFsUHJpbWl0aXZlKHNwYW4sIHNwYW4udG9BYnNvbHV0ZShhYnNvbHV0ZU9mZnNldCksIGlucHV0KSwgaW5wdXQsIGxvY2F0aW9uLFxuICAgICAgICBhYnNvbHV0ZU9mZnNldCwgdGhpcy5lcnJvcnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3RyaXBDb21tZW50cyhpbnB1dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBpID0gdGhpcy5fY29tbWVudFN0YXJ0KGlucHV0KTtcbiAgICByZXR1cm4gaSAhPSBudWxsID8gaW5wdXQuc3Vic3RyaW5nKDAsIGkpLnRyaW0oKSA6IGlucHV0O1xuICB9XG5cbiAgcHJpdmF0ZSBfY29tbWVudFN0YXJ0KGlucHV0OiBzdHJpbmcpOiBudW1iZXJ8bnVsbCB7XG4gICAgbGV0IG91dGVyUXVvdGU6IG51bWJlcnxudWxsID0gbnVsbDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Lmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgY29uc3QgY2hhciA9IGlucHV0LmNoYXJDb2RlQXQoaSk7XG4gICAgICBjb25zdCBuZXh0Q2hhciA9IGlucHV0LmNoYXJDb2RlQXQoaSArIDEpO1xuXG4gICAgICBpZiAoY2hhciA9PT0gY2hhcnMuJFNMQVNIICYmIG5leHRDaGFyID09IGNoYXJzLiRTTEFTSCAmJiBvdXRlclF1b3RlID09IG51bGwpIHJldHVybiBpO1xuXG4gICAgICBpZiAob3V0ZXJRdW90ZSA9PT0gY2hhcikge1xuICAgICAgICBvdXRlclF1b3RlID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAob3V0ZXJRdW90ZSA9PSBudWxsICYmIGNoYXJzLmlzUXVvdGUoY2hhcikpIHtcbiAgICAgICAgb3V0ZXJRdW90ZSA9IGNoYXI7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tOb0ludGVycG9sYXRpb24oaW5wdXQ6IHN0cmluZywgbG9jYXRpb246IHN0cmluZywge3N0YXJ0LCBlbmR9OiBJbnRlcnBvbGF0aW9uQ29uZmlnKTpcbiAgICAgIHZvaWQge1xuICAgIGxldCBzdGFydEluZGV4ID0gLTE7XG4gICAgbGV0IGVuZEluZGV4ID0gLTE7XG5cbiAgICBmb3IgKGNvbnN0IGNoYXJJbmRleCBvZiB0aGlzLl9mb3JFYWNoVW5xdW90ZWRDaGFyKGlucHV0LCAwKSkge1xuICAgICAgaWYgKHN0YXJ0SW5kZXggPT09IC0xKSB7XG4gICAgICAgIGlmIChpbnB1dC5zdGFydHNXaXRoKHN0YXJ0KSkge1xuICAgICAgICAgIHN0YXJ0SW5kZXggPSBjaGFySW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVuZEluZGV4ID0gdGhpcy5fZ2V0SW50ZXJwb2xhdGlvbkVuZEluZGV4KGlucHV0LCBlbmQsIGNoYXJJbmRleCk7XG4gICAgICAgIGlmIChlbmRJbmRleCA+IC0xKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3RhcnRJbmRleCA+IC0xICYmIGVuZEluZGV4ID4gLTEpIHtcbiAgICAgIHRoaXMuX3JlcG9ydEVycm9yKFxuICAgICAgICAgIGBHb3QgaW50ZXJwb2xhdGlvbiAoJHtzdGFydH0ke2VuZH0pIHdoZXJlIGV4cHJlc3Npb24gd2FzIGV4cGVjdGVkYCwgaW5wdXQsXG4gICAgICAgICAgYGF0IGNvbHVtbiAke3N0YXJ0SW5kZXh9IGluYCwgbG9jYXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyB0aGUgaW5kZXggb2YgdGhlIGVuZCBvZiBhbiBpbnRlcnBvbGF0aW9uIGV4cHJlc3Npb25cbiAgICogd2hpbGUgaWdub3JpbmcgY29tbWVudHMgYW5kIHF1b3RlZCBjb250ZW50LlxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0SW50ZXJwb2xhdGlvbkVuZEluZGV4KGlucHV0OiBzdHJpbmcsIGV4cHJlc3Npb25FbmQ6IHN0cmluZywgc3RhcnQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgZm9yIChjb25zdCBjaGFySW5kZXggb2YgdGhpcy5fZm9yRWFjaFVucXVvdGVkQ2hhcihpbnB1dCwgc3RhcnQpKSB7XG4gICAgICBpZiAoaW5wdXQuc3RhcnRzV2l0aChleHByZXNzaW9uRW5kLCBjaGFySW5kZXgpKSB7XG4gICAgICAgIHJldHVybiBjaGFySW5kZXg7XG4gICAgICB9XG5cbiAgICAgIC8vIE5vdGhpbmcgZWxzZSBpbiB0aGUgZXhwcmVzc2lvbiBtYXR0ZXJzIGFmdGVyIHdlJ3ZlXG4gICAgICAvLyBoaXQgYSBjb21tZW50IHNvIGxvb2sgZGlyZWN0bHkgZm9yIHRoZSBlbmQgdG9rZW4uXG4gICAgICBpZiAoaW5wdXQuc3RhcnRzV2l0aCgnLy8nLCBjaGFySW5kZXgpKSB7XG4gICAgICAgIHJldHVybiBpbnB1dC5pbmRleE9mKGV4cHJlc3Npb25FbmQsIGNoYXJJbmRleCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRvciB1c2VkIHRvIGl0ZXJhdGUgb3ZlciB0aGUgY2hhcmFjdGVyIGluZGV4ZXMgb2YgYSBzdHJpbmcgdGhhdCBhcmUgb3V0c2lkZSBvZiBxdW90ZXMuXG4gICAqIEBwYXJhbSBpbnB1dCBTdHJpbmcgdG8gbG9vcCB0aHJvdWdoLlxuICAgKiBAcGFyYW0gc3RhcnQgSW5kZXggd2l0aGluIHRoZSBzdHJpbmcgYXQgd2hpY2ggdG8gc3RhcnQuXG4gICAqL1xuICBwcml2YXRlICogX2ZvckVhY2hVbnF1b3RlZENoYXIoaW5wdXQ6IHN0cmluZywgc3RhcnQ6IG51bWJlcikge1xuICAgIGxldCBjdXJyZW50UXVvdGU6IHN0cmluZ3xudWxsID0gbnVsbDtcbiAgICBsZXQgZXNjYXBlQ291bnQgPSAwO1xuICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGlucHV0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBjaGFyID0gaW5wdXRbaV07XG4gICAgICAvLyBTa2lwIHRoZSBjaGFyYWN0ZXJzIGluc2lkZSBxdW90ZXMuIE5vdGUgdGhhdCB3ZSBvbmx5IGNhcmUgYWJvdXQgdGhlIG91dGVyLW1vc3RcbiAgICAgIC8vIHF1b3RlcyBtYXRjaGluZyB1cCBhbmQgd2UgbmVlZCB0byBhY2NvdW50IGZvciBlc2NhcGUgY2hhcmFjdGVycy5cbiAgICAgIGlmIChjaGFycy5pc1F1b3RlKGlucHV0LmNoYXJDb2RlQXQoaSkpICYmIChjdXJyZW50UXVvdGUgPT09IG51bGwgfHwgY3VycmVudFF1b3RlID09PSBjaGFyKSAmJlxuICAgICAgICAgIGVzY2FwZUNvdW50ICUgMiA9PT0gMCkge1xuICAgICAgICBjdXJyZW50UXVvdGUgPSBjdXJyZW50UXVvdGUgPT09IG51bGwgPyBjaGFyIDogbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFF1b3RlID09PSBudWxsKSB7XG4gICAgICAgIHlpZWxkIGk7XG4gICAgICB9XG4gICAgICBlc2NhcGVDb3VudCA9IGNoYXIgPT09ICdcXFxcJyA/IGVzY2FwZUNvdW50ICsgMSA6IDA7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBJdnlQYXJzZXIgZXh0ZW5kcyBQYXJzZXIge1xuICBvdmVycmlkZSBzaW1wbGVFeHByZXNzaW9uQ2hlY2tlciA9IEl2eVNpbXBsZUV4cHJlc3Npb25DaGVja2VyO1xufVxuXG4vKiogRGVzY3JpYmVzIGEgc3RhdGVmdWwgY29udGV4dCBhbiBleHByZXNzaW9uIHBhcnNlciBpcyBpbi4gKi9cbmVudW0gUGFyc2VDb250ZXh0RmxhZ3Mge1xuICBOb25lID0gMCxcbiAgLyoqXG4gICAqIEEgV3JpdGFibGUgY29udGV4dCBpcyBvbmUgaW4gd2hpY2ggYSB2YWx1ZSBtYXkgYmUgd3JpdHRlbiB0byBhbiBsdmFsdWUuXG4gICAqIEZvciBleGFtcGxlLCBhZnRlciB3ZSBzZWUgYSBwcm9wZXJ0eSBhY2Nlc3MsIHdlIG1heSBleHBlY3QgYSB3cml0ZSB0byB0aGVcbiAgICogcHJvcGVydHkgdmlhIHRoZSBcIj1cIiBvcGVyYXRvci5cbiAgICogICBwcm9wXG4gICAqICAgICAgICBeIHBvc3NpYmxlIFwiPVwiIGFmdGVyXG4gICAqL1xuICBXcml0YWJsZSA9IDEsXG59XG5cbmV4cG9ydCBjbGFzcyBfUGFyc2VBU1Qge1xuICBwcml2YXRlIHJwYXJlbnNFeHBlY3RlZCA9IDA7XG4gIHByaXZhdGUgcmJyYWNrZXRzRXhwZWN0ZWQgPSAwO1xuICBwcml2YXRlIHJicmFjZXNFeHBlY3RlZCA9IDA7XG4gIHByaXZhdGUgY29udGV4dCA9IFBhcnNlQ29udGV4dEZsYWdzLk5vbmU7XG5cbiAgLy8gQ2FjaGUgb2YgZXhwcmVzc2lvbiBzdGFydCBhbmQgaW5wdXQgaW5kZWNlcyB0byB0aGUgYWJzb2x1dGUgc291cmNlIHNwYW4gdGhleSBtYXAgdG8sIHVzZWQgdG9cbiAgLy8gcHJldmVudCBjcmVhdGluZyBzdXBlcmZsdW91cyBzb3VyY2Ugc3BhbnMgaW4gYHNvdXJjZVNwYW5gLlxuICAvLyBBIHNlcmlhbCBvZiB0aGUgZXhwcmVzc2lvbiBzdGFydCBhbmQgaW5wdXQgaW5kZXggaXMgdXNlZCBmb3IgbWFwcGluZyBiZWNhdXNlIGJvdGggYXJlIHN0YXRlZnVsXG4gIC8vIGFuZCBtYXkgY2hhbmdlIGZvciBzdWJzZXF1ZW50IGV4cHJlc3Npb25zIHZpc2l0ZWQgYnkgdGhlIHBhcnNlci5cbiAgcHJpdmF0ZSBzb3VyY2VTcGFuQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgQWJzb2x1dGVTb3VyY2VTcGFuPigpO1xuXG4gIGluZGV4OiBudW1iZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIGlucHV0OiBzdHJpbmcsIHB1YmxpYyBsb2NhdGlvbjogc3RyaW5nLCBwdWJsaWMgYWJzb2x1dGVPZmZzZXQ6IG51bWJlcixcbiAgICAgIHB1YmxpYyB0b2tlbnM6IFRva2VuW10sIHB1YmxpYyBpbnB1dExlbmd0aDogbnVtYmVyLCBwdWJsaWMgcGFyc2VBY3Rpb246IGJvb2xlYW4sXG4gICAgICBwcml2YXRlIGVycm9yczogUGFyc2VyRXJyb3JbXSwgcHJpdmF0ZSBvZmZzZXQ6IG51bWJlcikge31cblxuICBwZWVrKG9mZnNldDogbnVtYmVyKTogVG9rZW4ge1xuICAgIGNvbnN0IGkgPSB0aGlzLmluZGV4ICsgb2Zmc2V0O1xuICAgIHJldHVybiBpIDwgdGhpcy50b2tlbnMubGVuZ3RoID8gdGhpcy50b2tlbnNbaV0gOiBFT0Y7XG4gIH1cblxuICBnZXQgbmV4dCgpOiBUb2tlbiB7XG4gICAgcmV0dXJuIHRoaXMucGVlaygwKTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIGFsbCB0aGUgcGFyc2VyIGlucHV0IGhhcyBiZWVuIHByb2Nlc3NlZC4gKi9cbiAgZ2V0IGF0RU9GKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmluZGV4ID49IHRoaXMudG9rZW5zLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRleCBvZiB0aGUgbmV4dCB0b2tlbiB0byBiZSBwcm9jZXNzZWQsIG9yIHRoZSBlbmQgb2YgdGhlIGxhc3QgdG9rZW4gaWYgYWxsIGhhdmUgYmVlblxuICAgKiBwcm9jZXNzZWQuXG4gICAqL1xuICBnZXQgaW5wdXRJbmRleCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmF0RU9GID8gdGhpcy5jdXJyZW50RW5kSW5kZXggOiB0aGlzLm5leHQuaW5kZXggKyB0aGlzLm9mZnNldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmQgaW5kZXggb2YgdGhlIGxhc3QgcHJvY2Vzc2VkIHRva2VuLCBvciB0aGUgc3RhcnQgb2YgdGhlIGZpcnN0IHRva2VuIGlmIG5vbmUgaGF2ZSBiZWVuXG4gICAqIHByb2Nlc3NlZC5cbiAgICovXG4gIGdldCBjdXJyZW50RW5kSW5kZXgoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5pbmRleCA+IDApIHtcbiAgICAgIGNvbnN0IGN1clRva2VuID0gdGhpcy5wZWVrKC0xKTtcbiAgICAgIHJldHVybiBjdXJUb2tlbi5lbmQgKyB0aGlzLm9mZnNldDtcbiAgICB9XG4gICAgLy8gTm8gdG9rZW5zIGhhdmUgYmVlbiBwcm9jZXNzZWQgeWV0OyByZXR1cm4gdGhlIG5leHQgdG9rZW4ncyBzdGFydCBvciB0aGUgbGVuZ3RoIG9mIHRoZSBpbnB1dFxuICAgIC8vIGlmIHRoZXJlIGlzIG5vIHRva2VuLlxuICAgIGlmICh0aGlzLnRva2Vucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB0aGlzLmlucHV0TGVuZ3RoICsgdGhpcy5vZmZzZXQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm5leHQuaW5kZXggKyB0aGlzLm9mZnNldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhYnNvbHV0ZSBvZmZzZXQgb2YgdGhlIHN0YXJ0IG9mIHRoZSBjdXJyZW50IHRva2VuLlxuICAgKi9cbiAgZ2V0IGN1cnJlbnRBYnNvbHV0ZU9mZnNldCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmFic29sdXRlT2Zmc2V0ICsgdGhpcy5pbnB1dEluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGEgYFBhcnNlU3BhbmAgZnJvbSBgc3RhcnRgIHRvIHRoZSBjdXJyZW50IHBvc2l0aW9uIChvciB0byBgYXJ0aWZpY2lhbEVuZEluZGV4YCBpZlxuICAgKiBwcm92aWRlZCkuXG4gICAqXG4gICAqIEBwYXJhbSBzdGFydCBQb3NpdGlvbiBmcm9tIHdoaWNoIHRoZSBgUGFyc2VTcGFuYCB3aWxsIHN0YXJ0LlxuICAgKiBAcGFyYW0gYXJ0aWZpY2lhbEVuZEluZGV4IE9wdGlvbmFsIGVuZGluZyBpbmRleCB0byBiZSB1c2VkIGlmIHByb3ZpZGVkIChhbmQgaWYgZ3JlYXRlciB0aGFuIHRoZVxuICAgKiAgICAgbmF0dXJhbCBlbmRpbmcgaW5kZXgpXG4gICAqL1xuICBzcGFuKHN0YXJ0OiBudW1iZXIsIGFydGlmaWNpYWxFbmRJbmRleD86IG51bWJlcik6IFBhcnNlU3BhbiB7XG4gICAgbGV0IGVuZEluZGV4ID0gdGhpcy5jdXJyZW50RW5kSW5kZXg7XG4gICAgaWYgKGFydGlmaWNpYWxFbmRJbmRleCAhPT0gdW5kZWZpbmVkICYmIGFydGlmaWNpYWxFbmRJbmRleCA+IHRoaXMuY3VycmVudEVuZEluZGV4KSB7XG4gICAgICBlbmRJbmRleCA9IGFydGlmaWNpYWxFbmRJbmRleDtcbiAgICB9XG5cbiAgICAvLyBJbiBzb21lIHVudXN1YWwgcGFyc2luZyBzY2VuYXJpb3MgKGxpa2Ugd2hlbiBjZXJ0YWluIHRva2VucyBhcmUgbWlzc2luZyBhbmQgYW4gYEVtcHR5RXhwcmAgaXNcbiAgICAvLyBiZWluZyBjcmVhdGVkKSwgdGhlIGN1cnJlbnQgdG9rZW4gbWF5IGFscmVhZHkgYmUgYWR2YW5jZWQgYmV5b25kIHRoZSBgY3VycmVudEVuZEluZGV4YC4gVGhpc1xuICAgIC8vIGFwcGVhcnMgdG8gYmUgYSBkZWVwLXNlYXRlZCBwYXJzZXIgYnVnLlxuICAgIC8vXG4gICAgLy8gQXMgYSB3b3JrYXJvdW5kIGZvciBub3csIHN3YXAgdGhlIHN0YXJ0IGFuZCBlbmQgaW5kaWNlcyB0byBlbnN1cmUgYSB2YWxpZCBgUGFyc2VTcGFuYC5cbiAgICAvLyBUT0RPKGFseGh1Yik6IGZpeCB0aGUgYnVnIHVwc3RyZWFtIGluIHRoZSBwYXJzZXIgc3RhdGUsIGFuZCByZW1vdmUgdGhpcyB3b3JrYXJvdW5kLlxuICAgIGlmIChzdGFydCA+IGVuZEluZGV4KSB7XG4gICAgICBjb25zdCB0bXAgPSBlbmRJbmRleDtcbiAgICAgIGVuZEluZGV4ID0gc3RhcnQ7XG4gICAgICBzdGFydCA9IHRtcDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFBhcnNlU3BhbihzdGFydCwgZW5kSW5kZXgpO1xuICB9XG5cbiAgc291cmNlU3BhbihzdGFydDogbnVtYmVyLCBhcnRpZmljaWFsRW5kSW5kZXg/OiBudW1iZXIpOiBBYnNvbHV0ZVNvdXJjZVNwYW4ge1xuICAgIGNvbnN0IHNlcmlhbCA9IGAke3N0YXJ0fUAke3RoaXMuaW5wdXRJbmRleH06JHthcnRpZmljaWFsRW5kSW5kZXh9YDtcbiAgICBpZiAoIXRoaXMuc291cmNlU3BhbkNhY2hlLmhhcyhzZXJpYWwpKSB7XG4gICAgICB0aGlzLnNvdXJjZVNwYW5DYWNoZS5zZXQoXG4gICAgICAgICAgc2VyaWFsLCB0aGlzLnNwYW4oc3RhcnQsIGFydGlmaWNpYWxFbmRJbmRleCkudG9BYnNvbHV0ZSh0aGlzLmFic29sdXRlT2Zmc2V0KSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNvdXJjZVNwYW5DYWNoZS5nZXQoc2VyaWFsKSE7XG4gIH1cblxuICBhZHZhbmNlKCkge1xuICAgIHRoaXMuaW5kZXgrKztcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBhIGNhbGxiYWNrIGluIHRoZSBwcm92aWRlZCBjb250ZXh0LlxuICAgKi9cbiAgcHJpdmF0ZSB3aXRoQ29udGV4dDxUPihjb250ZXh0OiBQYXJzZUNvbnRleHRGbGFncywgY2I6ICgpID0+IFQpOiBUIHtcbiAgICB0aGlzLmNvbnRleHQgfD0gY29udGV4dDtcbiAgICBjb25zdCByZXQgPSBjYigpO1xuICAgIHRoaXMuY29udGV4dCBePSBjb250ZXh0O1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBjb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY29kZTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMubmV4dC5pc0NoYXJhY3Rlcihjb2RlKSkge1xuICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHBlZWtLZXl3b3JkTGV0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm5leHQuaXNLZXl3b3JkTGV0KCk7XG4gIH1cbiAgcGVla0tleXdvcmRBcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5uZXh0LmlzS2V5d29yZEFzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3VtZXMgYW4gZXhwZWN0ZWQgY2hhcmFjdGVyLCBvdGhlcndpc2UgZW1pdHMgYW4gZXJyb3IgYWJvdXQgdGhlIG1pc3NpbmcgZXhwZWN0ZWQgY2hhcmFjdGVyXG4gICAqIGFuZCBza2lwcyBvdmVyIHRoZSB0b2tlbiBzdHJlYW0gdW50aWwgcmVhY2hpbmcgYSByZWNvdmVyYWJsZSBwb2ludC5cbiAgICpcbiAgICogU2VlIGB0aGlzLmVycm9yYCBhbmQgYHRoaXMuc2tpcGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICovXG4gIGV4cGVjdENoYXJhY3Rlcihjb2RlOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY29kZSkpIHJldHVybjtcbiAgICB0aGlzLmVycm9yKGBNaXNzaW5nIGV4cGVjdGVkICR7U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlKX1gKTtcbiAgfVxuXG4gIGNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKG9wOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5uZXh0LmlzT3BlcmF0b3Iob3ApKSB7XG4gICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgZXhwZWN0T3BlcmF0b3Iob3BlcmF0b3I6IHN0cmluZykge1xuICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKG9wZXJhdG9yKSkgcmV0dXJuO1xuICAgIHRoaXMuZXJyb3IoYE1pc3NpbmcgZXhwZWN0ZWQgb3BlcmF0b3IgJHtvcGVyYXRvcn1gKTtcbiAgfVxuXG4gIHByZXR0eVByaW50VG9rZW4odG9rOiBUb2tlbik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRvayA9PT0gRU9GID8gJ2VuZCBvZiBpbnB1dCcgOiBgdG9rZW4gJHt0b2t9YDtcbiAgfVxuXG4gIGV4cGVjdElkZW50aWZpZXJPcktleXdvcmQoKTogc3RyaW5nfG51bGwge1xuICAgIGNvbnN0IG4gPSB0aGlzLm5leHQ7XG4gICAgaWYgKCFuLmlzSWRlbnRpZmllcigpICYmICFuLmlzS2V5d29yZCgpKSB7XG4gICAgICBpZiAobi5pc1ByaXZhdGVJZGVudGlmaWVyKCkpIHtcbiAgICAgICAgdGhpcy5fcmVwb3J0RXJyb3JGb3JQcml2YXRlSWRlbnRpZmllcihuLCAnZXhwZWN0ZWQgaWRlbnRpZmllciBvciBrZXl3b3JkJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmVycm9yKGBVbmV4cGVjdGVkICR7dGhpcy5wcmV0dHlQcmludFRva2VuKG4pfSwgZXhwZWN0ZWQgaWRlbnRpZmllciBvciBrZXl3b3JkYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgcmV0dXJuIG4udG9TdHJpbmcoKSBhcyBzdHJpbmc7XG4gIH1cblxuICBleHBlY3RJZGVudGlmaWVyT3JLZXl3b3JkT3JTdHJpbmcoKTogc3RyaW5nIHtcbiAgICBjb25zdCBuID0gdGhpcy5uZXh0O1xuICAgIGlmICghbi5pc0lkZW50aWZpZXIoKSAmJiAhbi5pc0tleXdvcmQoKSAmJiAhbi5pc1N0cmluZygpKSB7XG4gICAgICBpZiAobi5pc1ByaXZhdGVJZGVudGlmaWVyKCkpIHtcbiAgICAgICAgdGhpcy5fcmVwb3J0RXJyb3JGb3JQcml2YXRlSWRlbnRpZmllcihuLCAnZXhwZWN0ZWQgaWRlbnRpZmllciwga2V5d29yZCBvciBzdHJpbmcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZXJyb3IoXG4gICAgICAgICAgICBgVW5leHBlY3RlZCAke3RoaXMucHJldHR5UHJpbnRUb2tlbihuKX0sIGV4cGVjdGVkIGlkZW50aWZpZXIsIGtleXdvcmQsIG9yIHN0cmluZ2ApO1xuICAgICAgfVxuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICByZXR1cm4gbi50b1N0cmluZygpIGFzIHN0cmluZztcbiAgfVxuXG4gIHBhcnNlQ2hhaW4oKTogQVNUIHtcbiAgICBjb25zdCBleHByczogQVNUW10gPSBbXTtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICB3aGlsZSAodGhpcy5pbmRleCA8IHRoaXMudG9rZW5zLmxlbmd0aCkge1xuICAgICAgY29uc3QgZXhwciA9IHRoaXMucGFyc2VQaXBlKCk7XG4gICAgICBleHBycy5wdXNoKGV4cHIpO1xuXG4gICAgICBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJFNFTUlDT0xPTikpIHtcbiAgICAgICAgaWYgKCF0aGlzLnBhcnNlQWN0aW9uKSB7XG4gICAgICAgICAgdGhpcy5lcnJvcignQmluZGluZyBleHByZXNzaW9uIGNhbm5vdCBjb250YWluIGNoYWluZWQgZXhwcmVzc2lvbicpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlICh0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kU0VNSUNPTE9OKSkge1xuICAgICAgICB9ICAvLyByZWFkIGFsbCBzZW1pY29sb25zXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuaW5kZXggPCB0aGlzLnRva2Vucy5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5lcnJvcihgVW5leHBlY3RlZCB0b2tlbiAnJHt0aGlzLm5leHR9J2ApO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZXhwcnMubGVuZ3RoID09IDApIHtcbiAgICAgIC8vIFdlIGhhdmUgbm8gZXhwcmVzc2lvbnMgc28gY3JlYXRlIGFuIGVtcHR5IGV4cHJlc3Npb24gdGhhdCBzcGFucyB0aGUgZW50aXJlIGlucHV0IGxlbmd0aFxuICAgICAgY29uc3QgYXJ0aWZpY2lhbFN0YXJ0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICBjb25zdCBhcnRpZmljaWFsRW5kID0gdGhpcy5vZmZzZXQgKyB0aGlzLmlucHV0TGVuZ3RoO1xuICAgICAgcmV0dXJuIG5ldyBFbXB0eUV4cHIoXG4gICAgICAgICAgdGhpcy5zcGFuKGFydGlmaWNpYWxTdGFydCwgYXJ0aWZpY2lhbEVuZCksXG4gICAgICAgICAgdGhpcy5zb3VyY2VTcGFuKGFydGlmaWNpYWxTdGFydCwgYXJ0aWZpY2lhbEVuZCkpO1xuICAgIH1cbiAgICBpZiAoZXhwcnMubGVuZ3RoID09IDEpIHJldHVybiBleHByc1swXTtcbiAgICByZXR1cm4gbmV3IENoYWluKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIGV4cHJzKTtcbiAgfVxuXG4gIHBhcnNlUGlwZSgpOiBBU1Qge1xuICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5pbnB1dEluZGV4O1xuICAgIGxldCByZXN1bHQgPSB0aGlzLnBhcnNlRXhwcmVzc2lvbigpO1xuICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCd8JykpIHtcbiAgICAgIGlmICh0aGlzLnBhcnNlQWN0aW9uKSB7XG4gICAgICAgIHRoaXMuZXJyb3IoJ0Nhbm5vdCBoYXZlIGEgcGlwZSBpbiBhbiBhY3Rpb24gZXhwcmVzc2lvbicpO1xuICAgICAgfVxuXG4gICAgICBkbyB7XG4gICAgICAgIGNvbnN0IG5hbWVTdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICAgICAgbGV0IG5hbWVJZCA9IHRoaXMuZXhwZWN0SWRlbnRpZmllck9yS2V5d29yZCgpO1xuICAgICAgICBsZXQgbmFtZVNwYW46IEFic29sdXRlU291cmNlU3BhbjtcbiAgICAgICAgbGV0IGZ1bGxTcGFuRW5kOiBudW1iZXJ8dW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAobmFtZUlkICE9PSBudWxsKSB7XG4gICAgICAgICAgbmFtZVNwYW4gPSB0aGlzLnNvdXJjZVNwYW4obmFtZVN0YXJ0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBObyB2YWxpZCBpZGVudGlmaWVyIHdhcyBmb3VuZCwgc28gd2UnbGwgYXNzdW1lIGFuIGVtcHR5IHBpcGUgbmFtZSAoJycpLlxuICAgICAgICAgIG5hbWVJZCA9ICcnO1xuXG4gICAgICAgICAgLy8gSG93ZXZlciwgdGhlcmUgbWF5IGhhdmUgYmVlbiB3aGl0ZXNwYWNlIHByZXNlbnQgYmV0d2VlbiB0aGUgcGlwZSBjaGFyYWN0ZXIgYW5kIHRoZSBuZXh0XG4gICAgICAgICAgLy8gdG9rZW4gaW4gdGhlIHNlcXVlbmNlIChvciB0aGUgZW5kIG9mIGlucHV0KS4gV2Ugd2FudCB0byB0cmFjayB0aGlzIHdoaXRlc3BhY2Ugc28gdGhhdFxuICAgICAgICAgIC8vIHRoZSBgQmluZGluZ1BpcGVgIHdlIHByb2R1Y2UgY292ZXJzIG5vdCBqdXN0IHRoZSBwaXBlIGNoYXJhY3RlciwgYnV0IGFueSB0cmFpbGluZ1xuICAgICAgICAgIC8vIHdoaXRlc3BhY2UgYmV5b25kIGl0LiBBbm90aGVyIHdheSBvZiB0aGlua2luZyBhYm91dCB0aGlzIGlzIHRoYXQgdGhlIHplcm8tbGVuZ3RoIG5hbWVcbiAgICAgICAgICAvLyBpcyBhc3N1bWVkIHRvIGJlIGF0IHRoZSBlbmQgb2YgYW55IHdoaXRlc3BhY2UgYmV5b25kIHRoZSBwaXBlIGNoYXJhY3Rlci5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIFRoZXJlZm9yZSwgd2UgcHVzaCB0aGUgZW5kIG9mIHRoZSBgUGFyc2VTcGFuYCBmb3IgdGhpcyBwaXBlIGFsbCB0aGUgd2F5IHVwIHRvIHRoZVxuICAgICAgICAgIC8vIGJlZ2lubmluZyBvZiB0aGUgbmV4dCB0b2tlbiwgb3IgdW50aWwgdGhlIGVuZCBvZiBpbnB1dCBpZiB0aGUgbmV4dCB0b2tlbiBpcyBFT0YuXG4gICAgICAgICAgZnVsbFNwYW5FbmQgPSB0aGlzLm5leHQuaW5kZXggIT09IC0xID8gdGhpcy5uZXh0LmluZGV4IDogdGhpcy5pbnB1dExlbmd0aCArIHRoaXMub2Zmc2V0O1xuXG4gICAgICAgICAgLy8gVGhlIGBuYW1lU3BhbmAgZm9yIGFuIGVtcHR5IHBpcGUgbmFtZSBpcyB6ZXJvLWxlbmd0aCBhdCB0aGUgZW5kIG9mIGFueSB3aGl0ZXNwYWNlXG4gICAgICAgICAgLy8gYmV5b25kIHRoZSBwaXBlIGNoYXJhY3Rlci5cbiAgICAgICAgICBuYW1lU3BhbiA9IG5ldyBQYXJzZVNwYW4oZnVsbFNwYW5FbmQsIGZ1bGxTcGFuRW5kKS50b0Fic29sdXRlKHRoaXMuYWJzb2x1dGVPZmZzZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXJnczogQVNUW10gPSBbXTtcbiAgICAgICAgd2hpbGUgKHRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRDT0xPTikpIHtcbiAgICAgICAgICBhcmdzLnB1c2godGhpcy5wYXJzZUV4cHJlc3Npb24oKSk7XG5cbiAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgYWRkaXRpb25hbCBleHByZXNzaW9ucyBiZXlvbmQgdGhlIG5hbWUsIHRoZW4gdGhlIGFydGlmaWNpYWwgZW5kIGZvciB0aGVcbiAgICAgICAgICAvLyBuYW1lIGlzIG5vIGxvbmdlciByZWxldmFudC5cbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSBuZXcgQmluZGluZ1BpcGUoXG4gICAgICAgICAgICB0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQsIGZ1bGxTcGFuRW5kKSwgcmVzdWx0LCBuYW1lSWQsIGFyZ3MsIG5hbWVTcGFuKTtcbiAgICAgIH0gd2hpbGUgKHRoaXMuY29uc3VtZU9wdGlvbmFsT3BlcmF0b3IoJ3wnKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHBhcnNlRXhwcmVzc2lvbigpOiBBU1Qge1xuICAgIHJldHVybiB0aGlzLnBhcnNlQ29uZGl0aW9uYWwoKTtcbiAgfVxuXG4gIHBhcnNlQ29uZGl0aW9uYWwoKTogQVNUIHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLnBhcnNlTG9naWNhbE9yKCk7XG5cbiAgICBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxPcGVyYXRvcignPycpKSB7XG4gICAgICBjb25zdCB5ZXMgPSB0aGlzLnBhcnNlUGlwZSgpO1xuICAgICAgbGV0IG5vOiBBU1Q7XG4gICAgICBpZiAoIXRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRDT0xPTikpIHtcbiAgICAgICAgY29uc3QgZW5kID0gdGhpcy5pbnB1dEluZGV4O1xuICAgICAgICBjb25zdCBleHByZXNzaW9uID0gdGhpcy5pbnB1dC5zdWJzdHJpbmcoc3RhcnQsIGVuZCk7XG4gICAgICAgIHRoaXMuZXJyb3IoYENvbmRpdGlvbmFsIGV4cHJlc3Npb24gJHtleHByZXNzaW9ufSByZXF1aXJlcyBhbGwgMyBleHByZXNzaW9uc2ApO1xuICAgICAgICBubyA9IG5ldyBFbXB0eUV4cHIodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBubyA9IHRoaXMucGFyc2VQaXBlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IENvbmRpdGlvbmFsKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIHJlc3VsdCwgeWVzLCBubyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgcGFyc2VMb2dpY2FsT3IoKTogQVNUIHtcbiAgICAvLyAnfHwnXG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMucGFyc2VMb2dpY2FsQW5kKCk7XG4gICAgd2hpbGUgKHRoaXMuY29uc3VtZU9wdGlvbmFsT3BlcmF0b3IoJ3x8JykpIHtcbiAgICAgIGNvbnN0IHJpZ2h0ID0gdGhpcy5wYXJzZUxvZ2ljYWxBbmQoKTtcbiAgICAgIHJlc3VsdCA9IG5ldyBCaW5hcnkodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgJ3x8JywgcmVzdWx0LCByaWdodCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwYXJzZUxvZ2ljYWxBbmQoKTogQVNUIHtcbiAgICAvLyAnJiYnXG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMucGFyc2VOdWxsaXNoQ29hbGVzY2luZygpO1xuICAgIHdoaWxlICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCcmJicpKSB7XG4gICAgICBjb25zdCByaWdodCA9IHRoaXMucGFyc2VOdWxsaXNoQ29hbGVzY2luZygpO1xuICAgICAgcmVzdWx0ID0gbmV3IEJpbmFyeSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCAnJiYnLCByZXN1bHQsIHJpZ2h0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHBhcnNlTnVsbGlzaENvYWxlc2NpbmcoKTogQVNUIHtcbiAgICAvLyAnPz8nXG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMucGFyc2VFcXVhbGl0eSgpO1xuICAgIHdoaWxlICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCc/PycpKSB7XG4gICAgICBjb25zdCByaWdodCA9IHRoaXMucGFyc2VFcXVhbGl0eSgpO1xuICAgICAgcmVzdWx0ID0gbmV3IEJpbmFyeSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCAnPz8nLCByZXN1bHQsIHJpZ2h0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHBhcnNlRXF1YWxpdHkoKTogQVNUIHtcbiAgICAvLyAnPT0nLCchPScsJz09PScsJyE9PSdcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5wYXJzZVJlbGF0aW9uYWwoKTtcbiAgICB3aGlsZSAodGhpcy5uZXh0LnR5cGUgPT0gVG9rZW5UeXBlLk9wZXJhdG9yKSB7XG4gICAgICBjb25zdCBvcGVyYXRvciA9IHRoaXMubmV4dC5zdHJWYWx1ZTtcbiAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICAgICAgY2FzZSAnPT0nOlxuICAgICAgICBjYXNlICc9PT0nOlxuICAgICAgICBjYXNlICchPSc6XG4gICAgICAgIGNhc2UgJyE9PSc6XG4gICAgICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICAgICAgY29uc3QgcmlnaHQgPSB0aGlzLnBhcnNlUmVsYXRpb25hbCgpO1xuICAgICAgICAgIHJlc3VsdCA9IG5ldyBCaW5hcnkodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgb3BlcmF0b3IsIHJlc3VsdCwgcmlnaHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwYXJzZVJlbGF0aW9uYWwoKTogQVNUIHtcbiAgICAvLyAnPCcsICc+JywgJzw9JywgJz49J1xuICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5pbnB1dEluZGV4O1xuICAgIGxldCByZXN1bHQgPSB0aGlzLnBhcnNlQWRkaXRpdmUoKTtcbiAgICB3aGlsZSAodGhpcy5uZXh0LnR5cGUgPT0gVG9rZW5UeXBlLk9wZXJhdG9yKSB7XG4gICAgICBjb25zdCBvcGVyYXRvciA9IHRoaXMubmV4dC5zdHJWYWx1ZTtcbiAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICAgICAgY2FzZSAnPCc6XG4gICAgICAgIGNhc2UgJz4nOlxuICAgICAgICBjYXNlICc8PSc6XG4gICAgICAgIGNhc2UgJz49JzpcbiAgICAgICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgICAgICBjb25zdCByaWdodCA9IHRoaXMucGFyc2VBZGRpdGl2ZSgpO1xuICAgICAgICAgIHJlc3VsdCA9IG5ldyBCaW5hcnkodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgb3BlcmF0b3IsIHJlc3VsdCwgcmlnaHQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwYXJzZUFkZGl0aXZlKCk6IEFTVCB7XG4gICAgLy8gJysnLCAnLSdcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5wYXJzZU11bHRpcGxpY2F0aXZlKCk7XG4gICAgd2hpbGUgKHRoaXMubmV4dC50eXBlID09IFRva2VuVHlwZS5PcGVyYXRvcikge1xuICAgICAgY29uc3Qgb3BlcmF0b3IgPSB0aGlzLm5leHQuc3RyVmFsdWU7XG4gICAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7XG4gICAgICAgIGNhc2UgJysnOlxuICAgICAgICBjYXNlICctJzpcbiAgICAgICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgICAgICBsZXQgcmlnaHQgPSB0aGlzLnBhcnNlTXVsdGlwbGljYXRpdmUoKTtcbiAgICAgICAgICByZXN1bHQgPSBuZXcgQmluYXJ5KHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIG9wZXJhdG9yLCByZXN1bHQsIHJpZ2h0KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcGFyc2VNdWx0aXBsaWNhdGl2ZSgpOiBBU1Qge1xuICAgIC8vICcqJywgJyUnLCAnLydcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5wYXJzZVByZWZpeCgpO1xuICAgIHdoaWxlICh0aGlzLm5leHQudHlwZSA9PSBUb2tlblR5cGUuT3BlcmF0b3IpIHtcbiAgICAgIGNvbnN0IG9wZXJhdG9yID0gdGhpcy5uZXh0LnN0clZhbHVlO1xuICAgICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgICBjYXNlICcqJzpcbiAgICAgICAgY2FzZSAnJSc6XG4gICAgICAgIGNhc2UgJy8nOlxuICAgICAgICAgIHRoaXMuYWR2YW5jZSgpO1xuICAgICAgICAgIGxldCByaWdodCA9IHRoaXMucGFyc2VQcmVmaXgoKTtcbiAgICAgICAgICByZXN1bHQgPSBuZXcgQmluYXJ5KHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIG9wZXJhdG9yLCByZXN1bHQsIHJpZ2h0KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcGFyc2VQcmVmaXgoKTogQVNUIHtcbiAgICBpZiAodGhpcy5uZXh0LnR5cGUgPT0gVG9rZW5UeXBlLk9wZXJhdG9yKSB7XG4gICAgICBjb25zdCBzdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICAgIGNvbnN0IG9wZXJhdG9yID0gdGhpcy5uZXh0LnN0clZhbHVlO1xuICAgICAgbGV0IHJlc3VsdDogQVNUO1xuICAgICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgICBjYXNlICcrJzpcbiAgICAgICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlUHJlZml4KCk7XG4gICAgICAgICAgcmV0dXJuIFVuYXJ5LmNyZWF0ZVBsdXModGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgcmVzdWx0KTtcbiAgICAgICAgY2FzZSAnLSc6XG4gICAgICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICAgICAgcmVzdWx0ID0gdGhpcy5wYXJzZVByZWZpeCgpO1xuICAgICAgICAgIHJldHVybiBVbmFyeS5jcmVhdGVNaW51cyh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCByZXN1bHQpO1xuICAgICAgICBjYXNlICchJzpcbiAgICAgICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlUHJlZml4KCk7XG4gICAgICAgICAgcmV0dXJuIG5ldyBQcmVmaXhOb3QodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucGFyc2VDYWxsQ2hhaW4oKTtcbiAgfVxuXG4gIHBhcnNlQ2FsbENoYWluKCk6IEFTVCB7XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMucGFyc2VQcmltYXJ5KCk7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kUEVSSU9EKSkge1xuICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlQWNjZXNzTWVtYmVyT3JNZXRob2RDYWxsKHJlc3VsdCwgc3RhcnQsIGZhbHNlKTtcblxuICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCc/LicpKSB7XG4gICAgICAgIHJlc3VsdCA9IHRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRMQlJBQ0tFVCkgP1xuICAgICAgICAgICAgdGhpcy5wYXJzZUtleWVkUmVhZE9yV3JpdGUocmVzdWx0LCBzdGFydCwgdHJ1ZSkgOlxuICAgICAgICAgICAgdGhpcy5wYXJzZUFjY2Vzc01lbWJlck9yTWV0aG9kQ2FsbChyZXN1bHQsIHN0YXJ0LCB0cnVlKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJExCUkFDS0VUKSkge1xuICAgICAgICByZXN1bHQgPSB0aGlzLnBhcnNlS2V5ZWRSZWFkT3JXcml0ZShyZXN1bHQsIHN0YXJ0LCBmYWxzZSk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRMUEFSRU4pKSB7XG4gICAgICAgIHRoaXMucnBhcmVuc0V4cGVjdGVkKys7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSB0aGlzLnBhcnNlQ2FsbEFyZ3VtZW50cygpO1xuICAgICAgICB0aGlzLnJwYXJlbnNFeHBlY3RlZC0tO1xuICAgICAgICB0aGlzLmV4cGVjdENoYXJhY3RlcihjaGFycy4kUlBBUkVOKTtcbiAgICAgICAgcmVzdWx0ID0gbmV3IEZ1bmN0aW9uQ2FsbCh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCByZXN1bHQsIGFyZ3MpO1xuXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuY29uc3VtZU9wdGlvbmFsT3BlcmF0b3IoJyEnKSkge1xuICAgICAgICByZXN1bHQgPSBuZXcgTm9uTnVsbEFzc2VydCh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCByZXN1bHQpO1xuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBhcnNlUHJpbWFyeSgpOiBBU1Qge1xuICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5pbnB1dEluZGV4O1xuICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kTFBBUkVOKSkge1xuICAgICAgdGhpcy5ycGFyZW5zRXhwZWN0ZWQrKztcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucGFyc2VQaXBlKCk7XG4gICAgICB0aGlzLnJwYXJlbnNFeHBlY3RlZC0tO1xuICAgICAgdGhpcy5leHBlY3RDaGFyYWN0ZXIoY2hhcnMuJFJQQVJFTik7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuXG4gICAgfSBlbHNlIGlmICh0aGlzLm5leHQuaXNLZXl3b3JkTnVsbCgpKSB7XG4gICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgIHJldHVybiBuZXcgTGl0ZXJhbFByaW1pdGl2ZSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCBudWxsKTtcblxuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0LmlzS2V5d29yZFVuZGVmaW5lZCgpKSB7XG4gICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgIHJldHVybiBuZXcgTGl0ZXJhbFByaW1pdGl2ZSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCB2b2lkIDApO1xuXG4gICAgfSBlbHNlIGlmICh0aGlzLm5leHQuaXNLZXl3b3JkVHJ1ZSgpKSB7XG4gICAgICB0aGlzLmFkdmFuY2UoKTtcbiAgICAgIHJldHVybiBuZXcgTGl0ZXJhbFByaW1pdGl2ZSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCB0cnVlKTtcblxuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0LmlzS2V5d29yZEZhbHNlKCkpIHtcbiAgICAgIHRoaXMuYWR2YW5jZSgpO1xuICAgICAgcmV0dXJuIG5ldyBMaXRlcmFsUHJpbWl0aXZlKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIGZhbHNlKTtcblxuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0LmlzS2V5d29yZFRoaXMoKSkge1xuICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICByZXR1cm4gbmV3IFRoaXNSZWNlaXZlcih0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRMQlJBQ0tFVCkpIHtcbiAgICAgIHRoaXMucmJyYWNrZXRzRXhwZWN0ZWQrKztcbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gdGhpcy5wYXJzZUV4cHJlc3Npb25MaXN0KGNoYXJzLiRSQlJBQ0tFVCk7XG4gICAgICB0aGlzLnJicmFja2V0c0V4cGVjdGVkLS07XG4gICAgICB0aGlzLmV4cGVjdENoYXJhY3RlcihjaGFycy4kUkJSQUNLRVQpO1xuICAgICAgcmV0dXJuIG5ldyBMaXRlcmFsQXJyYXkodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgZWxlbWVudHMpO1xuXG4gICAgfSBlbHNlIGlmICh0aGlzLm5leHQuaXNDaGFyYWN0ZXIoY2hhcnMuJExCUkFDRSkpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlTGl0ZXJhbE1hcCgpO1xuXG4gICAgfSBlbHNlIGlmICh0aGlzLm5leHQuaXNJZGVudGlmaWVyKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlQWNjZXNzTWVtYmVyT3JNZXRob2RDYWxsKFxuICAgICAgICAgIG5ldyBJbXBsaWNpdFJlY2VpdmVyKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCkpLCBzdGFydCwgZmFsc2UpO1xuXG4gICAgfSBlbHNlIGlmICh0aGlzLm5leHQuaXNOdW1iZXIoKSkge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLm5leHQudG9OdW1iZXIoKTtcbiAgICAgIHRoaXMuYWR2YW5jZSgpO1xuICAgICAgcmV0dXJuIG5ldyBMaXRlcmFsUHJpbWl0aXZlKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIHZhbHVlKTtcblxuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0LmlzU3RyaW5nKCkpIHtcbiAgICAgIGNvbnN0IGxpdGVyYWxWYWx1ZSA9IHRoaXMubmV4dC50b1N0cmluZygpO1xuICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICByZXR1cm4gbmV3IExpdGVyYWxQcmltaXRpdmUodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgbGl0ZXJhbFZhbHVlKTtcblxuICAgIH0gZWxzZSBpZiAodGhpcy5uZXh0LmlzUHJpdmF0ZUlkZW50aWZpZXIoKSkge1xuICAgICAgdGhpcy5fcmVwb3J0RXJyb3JGb3JQcml2YXRlSWRlbnRpZmllcih0aGlzLm5leHQsIG51bGwpO1xuICAgICAgcmV0dXJuIG5ldyBFbXB0eUV4cHIodGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSk7XG5cbiAgICB9IGVsc2UgaWYgKHRoaXMuaW5kZXggPj0gdGhpcy50b2tlbnMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmVycm9yKGBVbmV4cGVjdGVkIGVuZCBvZiBleHByZXNzaW9uOiAke3RoaXMuaW5wdXR9YCk7XG4gICAgICByZXR1cm4gbmV3IEVtcHR5RXhwcih0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lcnJvcihgVW5leHBlY3RlZCB0b2tlbiAke3RoaXMubmV4dH1gKTtcbiAgICAgIHJldHVybiBuZXcgRW1wdHlFeHByKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCkpO1xuICAgIH1cbiAgfVxuXG4gIHBhcnNlRXhwcmVzc2lvbkxpc3QodGVybWluYXRvcjogbnVtYmVyKTogQVNUW10ge1xuICAgIGNvbnN0IHJlc3VsdDogQVNUW10gPSBbXTtcblxuICAgIGRvIHtcbiAgICAgIGlmICghdGhpcy5uZXh0LmlzQ2hhcmFjdGVyKHRlcm1pbmF0b3IpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRoaXMucGFyc2VQaXBlKCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSB3aGlsZSAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJENPTU1BKSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHBhcnNlTGl0ZXJhbE1hcCgpOiBMaXRlcmFsTWFwIHtcbiAgICBjb25zdCBrZXlzOiBMaXRlcmFsTWFwS2V5W10gPSBbXTtcbiAgICBjb25zdCB2YWx1ZXM6IEFTVFtdID0gW107XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgdGhpcy5leHBlY3RDaGFyYWN0ZXIoY2hhcnMuJExCUkFDRSk7XG4gICAgaWYgKCF0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kUkJSQUNFKSkge1xuICAgICAgdGhpcy5yYnJhY2VzRXhwZWN0ZWQrKztcbiAgICAgIGRvIHtcbiAgICAgICAgY29uc3Qga2V5U3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgICAgIGNvbnN0IHF1b3RlZCA9IHRoaXMubmV4dC5pc1N0cmluZygpO1xuICAgICAgICBjb25zdCBrZXkgPSB0aGlzLmV4cGVjdElkZW50aWZpZXJPcktleXdvcmRPclN0cmluZygpO1xuICAgICAgICBrZXlzLnB1c2goe2tleSwgcXVvdGVkfSk7XG5cbiAgICAgICAgLy8gUHJvcGVydGllcyB3aXRoIHF1b3RlZCBrZXlzIGNhbid0IHVzZSB0aGUgc2hvcnRoYW5kIHN5bnRheC5cbiAgICAgICAgaWYgKHF1b3RlZCkge1xuICAgICAgICAgIHRoaXMuZXhwZWN0Q2hhcmFjdGVyKGNoYXJzLiRDT0xPTik7XG4gICAgICAgICAgdmFsdWVzLnB1c2godGhpcy5wYXJzZVBpcGUoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJENPTE9OKSkge1xuICAgICAgICAgIHZhbHVlcy5wdXNoKHRoaXMucGFyc2VQaXBlKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHNwYW4gPSB0aGlzLnNwYW4oa2V5U3RhcnQpO1xuICAgICAgICAgIGNvbnN0IHNvdXJjZVNwYW4gPSB0aGlzLnNvdXJjZVNwYW4oa2V5U3RhcnQpO1xuICAgICAgICAgIHZhbHVlcy5wdXNoKG5ldyBQcm9wZXJ0eVJlYWQoXG4gICAgICAgICAgICAgIHNwYW4sIHNvdXJjZVNwYW4sIHNvdXJjZVNwYW4sIG5ldyBJbXBsaWNpdFJlY2VpdmVyKHNwYW4sIHNvdXJjZVNwYW4pLCBrZXkpKTtcbiAgICAgICAgfVxuICAgICAgfSB3aGlsZSAodGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJENPTU1BKSk7XG4gICAgICB0aGlzLnJicmFjZXNFeHBlY3RlZC0tO1xuICAgICAgdGhpcy5leHBlY3RDaGFyYWN0ZXIoY2hhcnMuJFJCUkFDRSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgTGl0ZXJhbE1hcCh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCBrZXlzLCB2YWx1ZXMpO1xuICB9XG5cbiAgcGFyc2VBY2Nlc3NNZW1iZXJPck1ldGhvZENhbGwocmVjZWl2ZXI6IEFTVCwgc3RhcnQ6IG51bWJlciwgaXNTYWZlOiBib29sZWFuKTogQVNUIHtcbiAgICBjb25zdCBuYW1lU3RhcnQgPSB0aGlzLmlucHV0SW5kZXg7XG4gICAgY29uc3QgaWQgPSB0aGlzLndpdGhDb250ZXh0KFBhcnNlQ29udGV4dEZsYWdzLldyaXRhYmxlLCAoKSA9PiB7XG4gICAgICBjb25zdCBpZCA9IHRoaXMuZXhwZWN0SWRlbnRpZmllck9yS2V5d29yZCgpID8/ICcnO1xuICAgICAgaWYgKGlkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLmVycm9yKGBFeHBlY3RlZCBpZGVudGlmaWVyIGZvciBwcm9wZXJ0eSBhY2Nlc3NgLCByZWNlaXZlci5zcGFuLmVuZCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaWQ7XG4gICAgfSk7XG4gICAgY29uc3QgbmFtZVNwYW4gPSB0aGlzLnNvdXJjZVNwYW4obmFtZVN0YXJ0KTtcblxuICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kTFBBUkVOKSkge1xuICAgICAgY29uc3QgYXJndW1lbnRTdGFydCA9IHRoaXMuaW5wdXRJbmRleDtcbiAgICAgIHRoaXMucnBhcmVuc0V4cGVjdGVkKys7XG4gICAgICBjb25zdCBhcmdzID0gdGhpcy5wYXJzZUNhbGxBcmd1bWVudHMoKTtcbiAgICAgIGNvbnN0IGFyZ3VtZW50U3BhbiA9XG4gICAgICAgICAgdGhpcy5zcGFuKGFyZ3VtZW50U3RhcnQsIHRoaXMuaW5wdXRJbmRleCkudG9BYnNvbHV0ZSh0aGlzLmFic29sdXRlT2Zmc2V0KTtcblxuICAgICAgdGhpcy5leHBlY3RDaGFyYWN0ZXIoY2hhcnMuJFJQQVJFTik7XG4gICAgICB0aGlzLnJwYXJlbnNFeHBlY3RlZC0tO1xuICAgICAgY29uc3Qgc3BhbiA9IHRoaXMuc3BhbihzdGFydCk7XG4gICAgICBjb25zdCBzb3VyY2VTcGFuID0gdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KTtcbiAgICAgIHJldHVybiBpc1NhZmUgP1xuICAgICAgICAgIG5ldyBTYWZlTWV0aG9kQ2FsbChzcGFuLCBzb3VyY2VTcGFuLCBuYW1lU3BhbiwgcmVjZWl2ZXIsIGlkLCBhcmdzLCBhcmd1bWVudFNwYW4pIDpcbiAgICAgICAgICBuZXcgTWV0aG9kQ2FsbChzcGFuLCBzb3VyY2VTcGFuLCBuYW1lU3BhbiwgcmVjZWl2ZXIsIGlkLCBhcmdzLCBhcmd1bWVudFNwYW4pO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChpc1NhZmUpIHtcbiAgICAgICAgaWYgKHRoaXMuY29uc3VtZU9wdGlvbmFsT3BlcmF0b3IoJz0nKSkge1xuICAgICAgICAgIHRoaXMuZXJyb3IoJ1RoZSBcXCc/LlxcJyBvcGVyYXRvciBjYW5ub3QgYmUgdXNlZCBpbiB0aGUgYXNzaWdubWVudCcpO1xuICAgICAgICAgIHJldHVybiBuZXcgRW1wdHlFeHByKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBuZXcgU2FmZVByb3BlcnR5UmVhZChcbiAgICAgICAgICAgICAgdGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgbmFtZVNwYW4sIHJlY2VpdmVyLCBpZCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCc9JykpIHtcbiAgICAgICAgICBpZiAoIXRoaXMucGFyc2VBY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3IoJ0JpbmRpbmdzIGNhbm5vdCBjb250YWluIGFzc2lnbm1lbnRzJyk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVtcHR5RXhwcih0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucGFyc2VDb25kaXRpb25hbCgpO1xuICAgICAgICAgIHJldHVybiBuZXcgUHJvcGVydHlXcml0ZShcbiAgICAgICAgICAgICAgdGhpcy5zcGFuKHN0YXJ0KSwgdGhpcy5zb3VyY2VTcGFuKHN0YXJ0KSwgbmFtZVNwYW4sIHJlY2VpdmVyLCBpZCwgdmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBuZXcgUHJvcGVydHlSZWFkKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIG5hbWVTcGFuLCByZWNlaXZlciwgaWQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGFyc2VDYWxsQXJndW1lbnRzKCk6IEJpbmRpbmdQaXBlW10ge1xuICAgIGlmICh0aGlzLm5leHQuaXNDaGFyYWN0ZXIoY2hhcnMuJFJQQVJFTikpIHJldHVybiBbXTtcbiAgICBjb25zdCBwb3NpdGlvbmFsczogQVNUW10gPSBbXTtcbiAgICBkbyB7XG4gICAgICBwb3NpdGlvbmFscy5wdXNoKHRoaXMucGFyc2VQaXBlKCkpO1xuICAgIH0gd2hpbGUgKHRoaXMuY29uc3VtZU9wdGlvbmFsQ2hhcmFjdGVyKGNoYXJzLiRDT01NQSkpO1xuICAgIHJldHVybiBwb3NpdGlvbmFscyBhcyBCaW5kaW5nUGlwZVtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyBhbiBpZGVudGlmaWVyLCBhIGtleXdvcmQsIGEgc3RyaW5nIHdpdGggYW4gb3B0aW9uYWwgYC1gIGluIGJldHdlZW4sXG4gICAqIGFuZCByZXR1cm5zIHRoZSBzdHJpbmcgYWxvbmcgd2l0aCBpdHMgYWJzb2x1dGUgc291cmNlIHNwYW4uXG4gICAqL1xuICBleHBlY3RUZW1wbGF0ZUJpbmRpbmdLZXkoKTogVGVtcGxhdGVCaW5kaW5nSWRlbnRpZmllciB7XG4gICAgbGV0IHJlc3VsdCA9ICcnO1xuICAgIGxldCBvcGVyYXRvckZvdW5kID0gZmFsc2U7XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLmN1cnJlbnRBYnNvbHV0ZU9mZnNldDtcbiAgICBkbyB7XG4gICAgICByZXN1bHQgKz0gdGhpcy5leHBlY3RJZGVudGlmaWVyT3JLZXl3b3JkT3JTdHJpbmcoKTtcbiAgICAgIG9wZXJhdG9yRm91bmQgPSB0aGlzLmNvbnN1bWVPcHRpb25hbE9wZXJhdG9yKCctJyk7XG4gICAgICBpZiAob3BlcmF0b3JGb3VuZCkge1xuICAgICAgICByZXN1bHQgKz0gJy0nO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKG9wZXJhdG9yRm91bmQpO1xuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2U6IHJlc3VsdCxcbiAgICAgIHNwYW46IG5ldyBBYnNvbHV0ZVNvdXJjZVNwYW4oc3RhcnQsIHN0YXJ0ICsgcmVzdWx0Lmxlbmd0aCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBtaWNyb3N5bnRheCB0ZW1wbGF0ZSBleHByZXNzaW9uIGFuZCByZXR1cm4gYSBsaXN0IG9mIGJpbmRpbmdzIG9yXG4gICAqIHBhcnNpbmcgZXJyb3JzIGluIGNhc2UgdGhlIGdpdmVuIGV4cHJlc3Npb24gaXMgaW52YWxpZC5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsXG4gICAqIGBgYFxuICAgKiAgIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaXRlbXM7IGluZGV4IGFzIGk7IHRyYWNrQnk6IGZ1bmNcIj5cbiAgICogYGBgXG4gICAqIGNvbnRhaW5zIGZpdmUgYmluZGluZ3M6XG4gICAqIDEuIG5nRm9yIC0+IG51bGxcbiAgICogMi4gaXRlbSAtPiBOZ0Zvck9mQ29udGV4dC4kaW1wbGljaXRcbiAgICogMy4gbmdGb3JPZiAtPiBpdGVtc1xuICAgKiA0LiBpIC0+IE5nRm9yT2ZDb250ZXh0LmluZGV4XG4gICAqIDUuIG5nRm9yVHJhY2tCeSAtPiBmdW5jXG4gICAqXG4gICAqIEZvciBhIGZ1bGwgZGVzY3JpcHRpb24gb2YgdGhlIG1pY3Jvc3ludGF4IGdyYW1tYXIsIHNlZVxuICAgKiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9taGV2ZXJ5L2QzNTMwMjk0Y2ZmMmU0YTFiM2ZlMTVmZjc1ZDA4ODU1XG4gICAqXG4gICAqIEBwYXJhbSB0ZW1wbGF0ZUtleSBuYW1lIG9mIHRoZSBtaWNyb3N5bnRheCBkaXJlY3RpdmUsIGxpa2UgbmdJZiwgbmdGb3IsXG4gICAqIHdpdGhvdXQgdGhlICosIGFsb25nIHdpdGggaXRzIGFic29sdXRlIHNwYW4uXG4gICAqL1xuICBwYXJzZVRlbXBsYXRlQmluZGluZ3ModGVtcGxhdGVLZXk6IFRlbXBsYXRlQmluZGluZ0lkZW50aWZpZXIpOiBUZW1wbGF0ZUJpbmRpbmdQYXJzZVJlc3VsdCB7XG4gICAgY29uc3QgYmluZGluZ3M6IFRlbXBsYXRlQmluZGluZ1tdID0gW107XG5cbiAgICAvLyBUaGUgZmlyc3QgYmluZGluZyBpcyBmb3IgdGhlIHRlbXBsYXRlIGtleSBpdHNlbGZcbiAgICAvLyBJbiAqbmdGb3I9XCJsZXQgaXRlbSBvZiBpdGVtc1wiLCBrZXkgPSBcIm5nRm9yXCIsIHZhbHVlID0gbnVsbFxuICAgIC8vIEluICpuZ0lmPVwiY29uZCB8IHBpcGVcIiwga2V5ID0gXCJuZ0lmXCIsIHZhbHVlID0gXCJjb25kIHwgcGlwZVwiXG4gICAgYmluZGluZ3MucHVzaCguLi50aGlzLnBhcnNlRGlyZWN0aXZlS2V5d29yZEJpbmRpbmdzKHRlbXBsYXRlS2V5KSk7XG5cbiAgICB3aGlsZSAodGhpcy5pbmRleCA8IHRoaXMudG9rZW5zLmxlbmd0aCkge1xuICAgICAgLy8gSWYgaXQgc3RhcnRzIHdpdGggJ2xldCcsIHRoZW4gdGhpcyBtdXN0IGJlIHZhcmlhYmxlIGRlY2xhcmF0aW9uXG4gICAgICBjb25zdCBsZXRCaW5kaW5nID0gdGhpcy5wYXJzZUxldEJpbmRpbmcoKTtcbiAgICAgIGlmIChsZXRCaW5kaW5nKSB7XG4gICAgICAgIGJpbmRpbmdzLnB1c2gobGV0QmluZGluZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBUd28gcG9zc2libGUgY2FzZXMgaGVyZSwgZWl0aGVyIGB2YWx1ZSBcImFzXCIga2V5YCBvclxuICAgICAgICAvLyBcImRpcmVjdGl2ZS1rZXl3b3JkIGV4cHJlc3Npb25cIi4gV2UgZG9uJ3Qga25vdyB3aGljaCBjYXNlLCBidXQgYm90aFxuICAgICAgICAvLyBcInZhbHVlXCIgYW5kIFwiZGlyZWN0aXZlLWtleXdvcmRcIiBhcmUgdGVtcGxhdGUgYmluZGluZyBrZXksIHNvIGNvbnN1bWVcbiAgICAgICAgLy8gdGhlIGtleSBmaXJzdC5cbiAgICAgICAgY29uc3Qga2V5ID0gdGhpcy5leHBlY3RUZW1wbGF0ZUJpbmRpbmdLZXkoKTtcbiAgICAgICAgLy8gUGVlayBhdCB0aGUgbmV4dCB0b2tlbiwgaWYgaXQgaXMgXCJhc1wiIHRoZW4gdGhpcyBtdXN0IGJlIHZhcmlhYmxlXG4gICAgICAgIC8vIGRlY2xhcmF0aW9uLlxuICAgICAgICBjb25zdCBiaW5kaW5nID0gdGhpcy5wYXJzZUFzQmluZGluZyhrZXkpO1xuICAgICAgICBpZiAoYmluZGluZykge1xuICAgICAgICAgIGJpbmRpbmdzLnB1c2goYmluZGluZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gT3RoZXJ3aXNlIHRoZSBrZXkgbXVzdCBiZSBhIGRpcmVjdGl2ZSBrZXl3b3JkLCBsaWtlIFwib2ZcIi4gVHJhbnNmb3JtXG4gICAgICAgICAgLy8gdGhlIGtleSB0byBhY3R1YWwga2V5LiBFZy4gb2YgLT4gbmdGb3JPZiwgdHJhY2tCeSAtPiBuZ0ZvclRyYWNrQnlcbiAgICAgICAgICBrZXkuc291cmNlID1cbiAgICAgICAgICAgICAgdGVtcGxhdGVLZXkuc291cmNlICsga2V5LnNvdXJjZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGtleS5zb3VyY2Uuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGJpbmRpbmdzLnB1c2goLi4udGhpcy5wYXJzZURpcmVjdGl2ZUtleXdvcmRCaW5kaW5ncyhrZXkpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5jb25zdW1lU3RhdGVtZW50VGVybWluYXRvcigpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVGVtcGxhdGVCaW5kaW5nUGFyc2VSZXN1bHQoYmluZGluZ3MsIFtdIC8qIHdhcm5pbmdzICovLCB0aGlzLmVycm9ycyk7XG4gIH1cblxuICBwYXJzZUtleWVkUmVhZE9yV3JpdGUocmVjZWl2ZXI6IEFTVCwgc3RhcnQ6IG51bWJlciwgaXNTYWZlOiBib29sZWFuKTogQVNUIHtcbiAgICByZXR1cm4gdGhpcy53aXRoQ29udGV4dChQYXJzZUNvbnRleHRGbGFncy5Xcml0YWJsZSwgKCkgPT4ge1xuICAgICAgdGhpcy5yYnJhY2tldHNFeHBlY3RlZCsrO1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5wYXJzZVBpcGUoKTtcbiAgICAgIGlmIChrZXkgaW5zdGFuY2VvZiBFbXB0eUV4cHIpIHtcbiAgICAgICAgdGhpcy5lcnJvcihgS2V5IGFjY2VzcyBjYW5ub3QgYmUgZW1wdHlgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucmJyYWNrZXRzRXhwZWN0ZWQtLTtcbiAgICAgIHRoaXMuZXhwZWN0Q2hhcmFjdGVyKGNoYXJzLiRSQlJBQ0tFVCk7XG4gICAgICBpZiAodGhpcy5jb25zdW1lT3B0aW9uYWxPcGVyYXRvcignPScpKSB7XG4gICAgICAgIGlmIChpc1NhZmUpIHtcbiAgICAgICAgICB0aGlzLmVycm9yKCdUaGUgXFwnPy5cXCcgb3BlcmF0b3IgY2Fubm90IGJlIHVzZWQgaW4gdGhlIGFzc2lnbm1lbnQnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMucGFyc2VDb25kaXRpb25hbCgpO1xuICAgICAgICAgIHJldHVybiBuZXcgS2V5ZWRXcml0ZSh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCByZWNlaXZlciwga2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpc1NhZmUgPyBuZXcgU2FmZUtleWVkUmVhZCh0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpLCByZWNlaXZlciwga2V5KSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgS2V5ZWRSZWFkKHRoaXMuc3BhbihzdGFydCksIHRoaXMuc291cmNlU3BhbihzdGFydCksIHJlY2VpdmVyLCBrZXkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmV3IEVtcHR5RXhwcih0aGlzLnNwYW4oc3RhcnQpLCB0aGlzLnNvdXJjZVNwYW4oc3RhcnQpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBhIGRpcmVjdGl2ZSBrZXl3b3JkLCBmb2xsb3dlZCBieSBhIG1hbmRhdG9yeSBleHByZXNzaW9uLlxuICAgKiBGb3IgZXhhbXBsZSwgXCJvZiBpdGVtc1wiLCBcInRyYWNrQnk6IGZ1bmNcIi5cbiAgICogVGhlIGJpbmRpbmdzIGFyZTogbmdGb3JPZiAtPiBpdGVtcywgbmdGb3JUcmFja0J5IC0+IGZ1bmNcbiAgICogVGhlcmUgY291bGQgYmUgYW4gb3B0aW9uYWwgXCJhc1wiIGJpbmRpbmcgdGhhdCBmb2xsb3dzIHRoZSBleHByZXNzaW9uLlxuICAgKiBGb3IgZXhhbXBsZSxcbiAgICogYGBgXG4gICAqICAgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaXRlbXMgfCBzbGljZTowOjEgYXMgY29sbGVjdGlvblwiLlxuICAgKiAgICAgICAgICAgICAgICAgICAgXl4gXl5eXl5eXl5eXl5eXl5eXl4gXl5eXl5eXl5eXl5eXlxuICAgKiAgICAgICAgICAgICAgIGtleXdvcmQgICAgYm91bmQgdGFyZ2V0ICAgb3B0aW9uYWwgJ2FzJyBiaW5kaW5nXG4gICAqIGBgYFxuICAgKlxuICAgKiBAcGFyYW0ga2V5IGJpbmRpbmcga2V5LCBmb3IgZXhhbXBsZSwgbmdGb3IsIG5nSWYsIG5nRm9yT2YsIGFsb25nIHdpdGggaXRzXG4gICAqIGFic29sdXRlIHNwYW4uXG4gICAqL1xuICBwcml2YXRlIHBhcnNlRGlyZWN0aXZlS2V5d29yZEJpbmRpbmdzKGtleTogVGVtcGxhdGVCaW5kaW5nSWRlbnRpZmllcik6IFRlbXBsYXRlQmluZGluZ1tdIHtcbiAgICBjb25zdCBiaW5kaW5nczogVGVtcGxhdGVCaW5kaW5nW10gPSBbXTtcbiAgICB0aGlzLmNvbnN1bWVPcHRpb25hbENoYXJhY3RlcihjaGFycy4kQ09MT04pOyAgLy8gdHJhY2tCeTogdHJhY2tCeUZ1bmN0aW9uXG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmdldERpcmVjdGl2ZUJvdW5kVGFyZ2V0KCk7XG4gICAgbGV0IHNwYW5FbmQgPSB0aGlzLmN1cnJlbnRBYnNvbHV0ZU9mZnNldDtcbiAgICAvLyBUaGUgYmluZGluZyBjb3VsZCBvcHRpb25hbGx5IGJlIGZvbGxvd2VkIGJ5IFwiYXNcIi4gRm9yIGV4YW1wbGUsXG4gICAgLy8gKm5nSWY9XCJjb25kIHwgcGlwZSBhcyB4XCIuIEluIHRoaXMgY2FzZSwgdGhlIGtleSBpbiB0aGUgXCJhc1wiIGJpbmRpbmdcbiAgICAvLyBpcyBcInhcIiBhbmQgdGhlIHZhbHVlIGlzIHRoZSB0ZW1wbGF0ZSBrZXkgaXRzZWxmIChcIm5nSWZcIikuIE5vdGUgdGhhdCB0aGVcbiAgICAvLyAna2V5JyBpbiB0aGUgY3VycmVudCBjb250ZXh0IG5vdyBiZWNvbWVzIHRoZSBcInZhbHVlXCIgaW4gdGhlIG5leHQgYmluZGluZy5cbiAgICBjb25zdCBhc0JpbmRpbmcgPSB0aGlzLnBhcnNlQXNCaW5kaW5nKGtleSk7XG4gICAgaWYgKCFhc0JpbmRpbmcpIHtcbiAgICAgIHRoaXMuY29uc3VtZVN0YXRlbWVudFRlcm1pbmF0b3IoKTtcbiAgICAgIHNwYW5FbmQgPSB0aGlzLmN1cnJlbnRBYnNvbHV0ZU9mZnNldDtcbiAgICB9XG4gICAgY29uc3Qgc291cmNlU3BhbiA9IG5ldyBBYnNvbHV0ZVNvdXJjZVNwYW4oa2V5LnNwYW4uc3RhcnQsIHNwYW5FbmQpO1xuICAgIGJpbmRpbmdzLnB1c2gobmV3IEV4cHJlc3Npb25CaW5kaW5nKHNvdXJjZVNwYW4sIGtleSwgdmFsdWUpKTtcbiAgICBpZiAoYXNCaW5kaW5nKSB7XG4gICAgICBiaW5kaW5ncy5wdXNoKGFzQmluZGluZyk7XG4gICAgfVxuICAgIHJldHVybiBiaW5kaW5ncztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGV4cHJlc3Npb24gQVNUIGZvciB0aGUgYm91bmQgdGFyZ2V0IG9mIGEgZGlyZWN0aXZlIGtleXdvcmRcbiAgICogYmluZGluZy4gRm9yIGV4YW1wbGUsXG4gICAqIGBgYFxuICAgKiAgICpuZ0lmPVwiY29uZGl0aW9uIHwgcGlwZVwiXG4gICAqICAgICAgICAgIF5eXl5eXl5eXl5eXl5eXl4gYm91bmQgdGFyZ2V0IGZvciBcIm5nSWZcIlxuICAgKiAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zXCJcbiAgICogICAgICAgICAgICAgICAgICAgICAgIF5eXl5eIGJvdW5kIHRhcmdldCBmb3IgXCJuZ0Zvck9mXCJcbiAgICogYGBgXG4gICAqL1xuICBwcml2YXRlIGdldERpcmVjdGl2ZUJvdW5kVGFyZ2V0KCk6IEFTVFdpdGhTb3VyY2V8bnVsbCB7XG4gICAgaWYgKHRoaXMubmV4dCA9PT0gRU9GIHx8IHRoaXMucGVla0tleXdvcmRBcygpIHx8IHRoaXMucGVla0tleXdvcmRMZXQoKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGFzdCA9IHRoaXMucGFyc2VQaXBlKCk7ICAvLyBleGFtcGxlOiBcImNvbmRpdGlvbiB8IGFzeW5jXCJcbiAgICBjb25zdCB7c3RhcnQsIGVuZH0gPSBhc3Quc3BhbjtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuaW5wdXQuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpO1xuICAgIHJldHVybiBuZXcgQVNUV2l0aFNvdXJjZShhc3QsIHZhbHVlLCB0aGlzLmxvY2F0aW9uLCB0aGlzLmFic29sdXRlT2Zmc2V0ICsgc3RhcnQsIHRoaXMuZXJyb3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGJpbmRpbmcgZm9yIGEgdmFyaWFibGUgZGVjbGFyZWQgdXNpbmcgYGFzYC4gTm90ZSB0aGF0IHRoZSBvcmRlclxuICAgKiBvZiB0aGUga2V5LXZhbHVlIHBhaXIgaW4gdGhpcyBkZWNsYXJhdGlvbiBpcyByZXZlcnNlZC4gRm9yIGV4YW1wbGUsXG4gICAqIGBgYFxuICAgKiAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zOyBpbmRleCBhcyBpXCJcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBeXl5eXiAgICBeXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgICAga2V5XG4gICAqIGBgYFxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgbmFtZSBvZiB0aGUgdmFsdWUgaW4gdGhlIGRlY2xhcmF0aW9uLCBcIm5nSWZcIiBpbiB0aGUgZXhhbXBsZVxuICAgKiBhYm92ZSwgYWxvbmcgd2l0aCBpdHMgYWJzb2x1dGUgc3Bhbi5cbiAgICovXG4gIHByaXZhdGUgcGFyc2VBc0JpbmRpbmcodmFsdWU6IFRlbXBsYXRlQmluZGluZ0lkZW50aWZpZXIpOiBUZW1wbGF0ZUJpbmRpbmd8bnVsbCB7XG4gICAgaWYgKCF0aGlzLnBlZWtLZXl3b3JkQXMoKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHRoaXMuYWR2YW5jZSgpOyAgLy8gY29uc3VtZSB0aGUgJ2FzJyBrZXl3b3JkXG4gICAgY29uc3Qga2V5ID0gdGhpcy5leHBlY3RUZW1wbGF0ZUJpbmRpbmdLZXkoKTtcbiAgICB0aGlzLmNvbnN1bWVTdGF0ZW1lbnRUZXJtaW5hdG9yKCk7XG4gICAgY29uc3Qgc291cmNlU3BhbiA9IG5ldyBBYnNvbHV0ZVNvdXJjZVNwYW4odmFsdWUuc3Bhbi5zdGFydCwgdGhpcy5jdXJyZW50QWJzb2x1dGVPZmZzZXQpO1xuICAgIHJldHVybiBuZXcgVmFyaWFibGVCaW5kaW5nKHNvdXJjZVNwYW4sIGtleSwgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgYmluZGluZyBmb3IgYSB2YXJpYWJsZSBkZWNsYXJlZCB1c2luZyBgbGV0YC4gRm9yIGV4YW1wbGUsXG4gICAqIGBgYFxuICAgKiAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zOyBsZXQgaT1pbmRleDtcIlxuICAgKiAgICAgICAgICAgXl5eXl5eXl4gICAgICAgICAgIF5eXl5eXl5eXl5eXG4gICAqIGBgYFxuICAgKiBJbiB0aGUgZmlyc3QgYmluZGluZywgYGl0ZW1gIGlzIGJvdW5kIHRvIGBOZ0Zvck9mQ29udGV4dC4kaW1wbGljaXRgLlxuICAgKiBJbiB0aGUgc2Vjb25kIGJpbmRpbmcsIGBpYCBpcyBib3VuZCB0byBgTmdGb3JPZkNvbnRleHQuaW5kZXhgLlxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZUxldEJpbmRpbmcoKTogVGVtcGxhdGVCaW5kaW5nfG51bGwge1xuICAgIGlmICghdGhpcy5wZWVrS2V5d29yZExldCgpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qgc3BhblN0YXJ0ID0gdGhpcy5jdXJyZW50QWJzb2x1dGVPZmZzZXQ7XG4gICAgdGhpcy5hZHZhbmNlKCk7ICAvLyBjb25zdW1lIHRoZSAnbGV0JyBrZXl3b3JkXG4gICAgY29uc3Qga2V5ID0gdGhpcy5leHBlY3RUZW1wbGF0ZUJpbmRpbmdLZXkoKTtcbiAgICBsZXQgdmFsdWU6IFRlbXBsYXRlQmluZGluZ0lkZW50aWZpZXJ8bnVsbCA9IG51bGw7XG4gICAgaWYgKHRoaXMuY29uc3VtZU9wdGlvbmFsT3BlcmF0b3IoJz0nKSkge1xuICAgICAgdmFsdWUgPSB0aGlzLmV4cGVjdFRlbXBsYXRlQmluZGluZ0tleSgpO1xuICAgIH1cbiAgICB0aGlzLmNvbnN1bWVTdGF0ZW1lbnRUZXJtaW5hdG9yKCk7XG4gICAgY29uc3Qgc291cmNlU3BhbiA9IG5ldyBBYnNvbHV0ZVNvdXJjZVNwYW4oc3BhblN0YXJ0LCB0aGlzLmN1cnJlbnRBYnNvbHV0ZU9mZnNldCk7XG4gICAgcmV0dXJuIG5ldyBWYXJpYWJsZUJpbmRpbmcoc291cmNlU3Bhbiwga2V5LCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3VtZSB0aGUgb3B0aW9uYWwgc3RhdGVtZW50IHRlcm1pbmF0b3I6IHNlbWljb2xvbiBvciBjb21tYS5cbiAgICovXG4gIHByaXZhdGUgY29uc3VtZVN0YXRlbWVudFRlcm1pbmF0b3IoKSB7XG4gICAgdGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJFNFTUlDT0xPTikgfHwgdGhpcy5jb25zdW1lT3B0aW9uYWxDaGFyYWN0ZXIoY2hhcnMuJENPTU1BKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNvcmRzIGFuIGVycm9yIGFuZCBza2lwcyBvdmVyIHRoZSB0b2tlbiBzdHJlYW0gdW50aWwgcmVhY2hpbmcgYSByZWNvdmVyYWJsZSBwb2ludC4gU2VlXG4gICAqIGB0aGlzLnNraXBgIGZvciBtb3JlIGRldGFpbHMgb24gdG9rZW4gc2tpcHBpbmcuXG4gICAqL1xuICBlcnJvcihtZXNzYWdlOiBzdHJpbmcsIGluZGV4OiBudW1iZXJ8bnVsbCA9IG51bGwpIHtcbiAgICB0aGlzLmVycm9ycy5wdXNoKG5ldyBQYXJzZXJFcnJvcihtZXNzYWdlLCB0aGlzLmlucHV0LCB0aGlzLmxvY2F0aW9uVGV4dChpbmRleCksIHRoaXMubG9jYXRpb24pKTtcbiAgICB0aGlzLnNraXAoKTtcbiAgfVxuXG4gIHByaXZhdGUgbG9jYXRpb25UZXh0KGluZGV4OiBudW1iZXJ8bnVsbCA9IG51bGwpIHtcbiAgICBpZiAoaW5kZXggPT0gbnVsbCkgaW5kZXggPSB0aGlzLmluZGV4O1xuICAgIHJldHVybiAoaW5kZXggPCB0aGlzLnRva2Vucy5sZW5ndGgpID8gYGF0IGNvbHVtbiAke3RoaXMudG9rZW5zW2luZGV4XS5pbmRleCArIDF9IGluYCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgYXQgdGhlIGVuZCBvZiB0aGUgZXhwcmVzc2lvbmA7XG4gIH1cblxuICAvKipcbiAgICogUmVjb3JkcyBhbiBlcnJvciBmb3IgYW4gdW5leHBlY3RlZCBwcml2YXRlIGlkZW50aWZpZXIgYmVpbmcgZGlzY292ZXJlZC5cbiAgICogQHBhcmFtIHRva2VuIFRva2VuIHJlcHJlc2VudGluZyBhIHByaXZhdGUgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIGV4dHJhTWVzc2FnZSBPcHRpb25hbCBhZGRpdGlvbmFsIG1lc3NhZ2UgYmVpbmcgYXBwZW5kZWQgdG8gdGhlIGVycm9yLlxuICAgKi9cbiAgcHJpdmF0ZSBfcmVwb3J0RXJyb3JGb3JQcml2YXRlSWRlbnRpZmllcih0b2tlbjogVG9rZW4sIGV4dHJhTWVzc2FnZTogc3RyaW5nfG51bGwpIHtcbiAgICBsZXQgZXJyb3JNZXNzYWdlID1cbiAgICAgICAgYFByaXZhdGUgaWRlbnRpZmllcnMgYXJlIG5vdCBzdXBwb3J0ZWQuIFVuZXhwZWN0ZWQgcHJpdmF0ZSBpZGVudGlmaWVyOiAke3Rva2VufWA7XG4gICAgaWYgKGV4dHJhTWVzc2FnZSAhPT0gbnVsbCkge1xuICAgICAgZXJyb3JNZXNzYWdlICs9IGAsICR7ZXh0cmFNZXNzYWdlfWA7XG4gICAgfVxuICAgIHRoaXMuZXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFcnJvciByZWNvdmVyeSBzaG91bGQgc2tpcCB0b2tlbnMgdW50aWwgaXQgZW5jb3VudGVycyBhIHJlY292ZXJ5IHBvaW50LlxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGFyZSB0cmVhdGVkIGFzIHVuY29uZGl0aW9uYWwgcmVjb3ZlcnkgcG9pbnRzOlxuICAgKiAgIC0gZW5kIG9mIGlucHV0XG4gICAqICAgLSAnOycgKHBhcnNlQ2hhaW4oKSBpcyBhbHdheXMgdGhlIHJvb3QgcHJvZHVjdGlvbiwgYW5kIGl0IGV4cGVjdHMgYSAnOycpXG4gICAqICAgLSAnfCcgKHNpbmNlIHBpcGVzIG1heSBiZSBjaGFpbmVkIGFuZCBlYWNoIHBpcGUgZXhwcmVzc2lvbiBtYXkgYmUgdHJlYXRlZCBpbmRlcGVuZGVudGx5KVxuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGFyZSBjb25kaXRpb25hbCByZWNvdmVyeSBwb2ludHM6XG4gICAqICAgLSAnKScsICd9JywgJ10nIGlmIG9uZSBvZiBjYWxsaW5nIHByb2R1Y3Rpb25zIGlzIGV4cGVjdGluZyBvbmUgb2YgdGhlc2Ugc3ltYm9sc1xuICAgKiAgICAgLSBUaGlzIGFsbG93cyBza2lwKCkgdG8gcmVjb3ZlciBmcm9tIGVycm9ycyBzdWNoIGFzICcoYS4pICsgMScgYWxsb3dpbmcgbW9yZSBvZiB0aGUgQVNUIHRvXG4gICAqICAgICAgIGJlIHJldGFpbmVkIChpdCBkb2Vzbid0IHNraXAgYW55IHRva2VucyBhcyB0aGUgJyknIGlzIHJldGFpbmVkIGJlY2F1c2Ugb2YgdGhlICcoJyBiZWdpbnNcbiAgICogICAgICAgYW4gJygnIDxleHByPiAnKScgcHJvZHVjdGlvbikuXG4gICAqICAgICAgIFRoZSByZWNvdmVyeSBwb2ludHMgb2YgZ3JvdXBpbmcgc3ltYm9scyBtdXN0IGJlIGNvbmRpdGlvbmFsIGFzIHRoZXkgbXVzdCBiZSBza2lwcGVkIGlmXG4gICAqICAgICAgIG5vbmUgb2YgdGhlIGNhbGxpbmcgcHJvZHVjdGlvbnMgYXJlIG5vdCBleHBlY3RpbmcgdGhlIGNsb3NpbmcgdG9rZW4gZWxzZSB3ZSB3aWxsIG5ldmVyXG4gICAqICAgICAgIG1ha2UgcHJvZ3Jlc3MgaW4gdGhlIGNhc2Ugb2YgYW4gZXh0cmFuZW91cyBncm91cCBjbG9zaW5nIHN5bWJvbCAoc3VjaCBhcyBhIHN0cmF5ICcpJykuXG4gICAqICAgICAgIFRoYXQgaXMsIHdlIHNraXAgYSBjbG9zaW5nIHN5bWJvbCBpZiB3ZSBhcmUgbm90IGluIGEgZ3JvdXBpbmcgcHJvZHVjdGlvbi5cbiAgICogICAtICc9JyBpbiBhIGBXcml0YWJsZWAgY29udGV4dFxuICAgKiAgICAgLSBJbiB0aGlzIGNvbnRleHQsIHdlIGFyZSBhYmxlIHRvIHJlY292ZXIgYWZ0ZXIgc2VlaW5nIHRoZSBgPWAgb3BlcmF0b3IsIHdoaWNoXG4gICAqICAgICAgIHNpZ25hbHMgdGhlIHByZXNlbmNlIG9mIGFuIGluZGVwZW5kZW50IHJ2YWx1ZSBleHByZXNzaW9uIGZvbGxvd2luZyB0aGUgYD1gIG9wZXJhdG9yLlxuICAgKlxuICAgKiBJZiBhIHByb2R1Y3Rpb24gZXhwZWN0cyBvbmUgb2YgdGhlc2UgdG9rZW4gaXQgaW5jcmVtZW50cyB0aGUgY29ycmVzcG9uZGluZyBuZXN0aW5nIGNvdW50LFxuICAgKiBhbmQgdGhlbiBkZWNyZW1lbnRzIGl0IGp1c3QgcHJpb3IgdG8gY2hlY2tpbmcgaWYgdGhlIHRva2VuIGlzIGluIHRoZSBpbnB1dC5cbiAgICovXG4gIHByaXZhdGUgc2tpcCgpIHtcbiAgICBsZXQgbiA9IHRoaXMubmV4dDtcbiAgICB3aGlsZSAodGhpcy5pbmRleCA8IHRoaXMudG9rZW5zLmxlbmd0aCAmJiAhbi5pc0NoYXJhY3RlcihjaGFycy4kU0VNSUNPTE9OKSAmJlxuICAgICAgICAgICAhbi5pc09wZXJhdG9yKCd8JykgJiYgKHRoaXMucnBhcmVuc0V4cGVjdGVkIDw9IDAgfHwgIW4uaXNDaGFyYWN0ZXIoY2hhcnMuJFJQQVJFTikpICYmXG4gICAgICAgICAgICh0aGlzLnJicmFjZXNFeHBlY3RlZCA8PSAwIHx8ICFuLmlzQ2hhcmFjdGVyKGNoYXJzLiRSQlJBQ0UpKSAmJlxuICAgICAgICAgICAodGhpcy5yYnJhY2tldHNFeHBlY3RlZCA8PSAwIHx8ICFuLmlzQ2hhcmFjdGVyKGNoYXJzLiRSQlJBQ0tFVCkpICYmXG4gICAgICAgICAgICghKHRoaXMuY29udGV4dCAmIFBhcnNlQ29udGV4dEZsYWdzLldyaXRhYmxlKSB8fCAhbi5pc09wZXJhdG9yKCc9JykpKSB7XG4gICAgICBpZiAodGhpcy5uZXh0LmlzRXJyb3IoKSkge1xuICAgICAgICB0aGlzLmVycm9ycy5wdXNoKFxuICAgICAgICAgICAgbmV3IFBhcnNlckVycm9yKHRoaXMubmV4dC50b1N0cmluZygpISwgdGhpcy5pbnB1dCwgdGhpcy5sb2NhdGlvblRleHQoKSwgdGhpcy5sb2NhdGlvbikpO1xuICAgICAgfVxuICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICBuID0gdGhpcy5uZXh0O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBTaW1wbGVFeHByZXNzaW9uQ2hlY2tlciBpbXBsZW1lbnRzIEFzdFZpc2l0b3Ige1xuICBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgdmlzaXRJbXBsaWNpdFJlY2VpdmVyKGFzdDogSW1wbGljaXRSZWNlaXZlciwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0VGhpc1JlY2VpdmVyKGFzdDogVGhpc1JlY2VpdmVyLCBjb250ZXh0OiBhbnkpIHt9XG5cbiAgdmlzaXRJbnRlcnBvbGF0aW9uKGFzdDogSW50ZXJwb2xhdGlvbiwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0TGl0ZXJhbFByaW1pdGl2ZShhc3Q6IExpdGVyYWxQcmltaXRpdmUsIGNvbnRleHQ6IGFueSkge31cblxuICB2aXNpdFByb3BlcnR5UmVhZChhc3Q6IFByb3BlcnR5UmVhZCwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0UHJvcGVydHlXcml0ZShhc3Q6IFByb3BlcnR5V3JpdGUsIGNvbnRleHQ6IGFueSkge31cblxuICB2aXNpdFNhZmVQcm9wZXJ0eVJlYWQoYXN0OiBTYWZlUHJvcGVydHlSZWFkLCBjb250ZXh0OiBhbnkpIHt9XG5cbiAgdmlzaXRNZXRob2RDYWxsKGFzdDogTWV0aG9kQ2FsbCwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0U2FmZU1ldGhvZENhbGwoYXN0OiBTYWZlTWV0aG9kQ2FsbCwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0RnVuY3Rpb25DYWxsKGFzdDogRnVuY3Rpb25DYWxsLCBjb250ZXh0OiBhbnkpIHt9XG5cbiAgdmlzaXRMaXRlcmFsQXJyYXkoYXN0OiBMaXRlcmFsQXJyYXksIGNvbnRleHQ6IGFueSkge1xuICAgIHRoaXMudmlzaXRBbGwoYXN0LmV4cHJlc3Npb25zLCBjb250ZXh0KTtcbiAgfVxuXG4gIHZpc2l0TGl0ZXJhbE1hcChhc3Q6IExpdGVyYWxNYXAsIGNvbnRleHQ6IGFueSkge1xuICAgIHRoaXMudmlzaXRBbGwoYXN0LnZhbHVlcywgY29udGV4dCk7XG4gIH1cblxuICB2aXNpdFVuYXJ5KGFzdDogVW5hcnksIGNvbnRleHQ6IGFueSkge31cblxuICB2aXNpdEJpbmFyeShhc3Q6IEJpbmFyeSwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0UHJlZml4Tm90KGFzdDogUHJlZml4Tm90LCBjb250ZXh0OiBhbnkpIHt9XG5cbiAgdmlzaXROb25OdWxsQXNzZXJ0KGFzdDogTm9uTnVsbEFzc2VydCwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0Q29uZGl0aW9uYWwoYXN0OiBDb25kaXRpb25hbCwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0UGlwZShhc3Q6IEJpbmRpbmdQaXBlLCBjb250ZXh0OiBhbnkpIHtcbiAgICB0aGlzLmVycm9ycy5wdXNoKCdwaXBlcycpO1xuICB9XG5cbiAgdmlzaXRLZXllZFJlYWQoYXN0OiBLZXllZFJlYWQsIGNvbnRleHQ6IGFueSkge31cblxuICB2aXNpdEtleWVkV3JpdGUoYXN0OiBLZXllZFdyaXRlLCBjb250ZXh0OiBhbnkpIHt9XG5cbiAgdmlzaXRBbGwoYXN0czogYW55W10sIGNvbnRleHQ6IGFueSk6IGFueVtdIHtcbiAgICByZXR1cm4gYXN0cy5tYXAobm9kZSA9PiBub2RlLnZpc2l0KHRoaXMsIGNvbnRleHQpKTtcbiAgfVxuXG4gIHZpc2l0Q2hhaW4oYXN0OiBDaGFpbiwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0UXVvdGUoYXN0OiBRdW90ZSwgY29udGV4dDogYW55KSB7fVxuXG4gIHZpc2l0U2FmZUtleWVkUmVhZChhc3Q6IFNhZmVLZXllZFJlYWQsIGNvbnRleHQ6IGFueSkge31cbn1cblxuLyoqXG4gKiBUaGlzIGNsYXNzIGltcGxlbWVudHMgU2ltcGxlRXhwcmVzc2lvbkNoZWNrZXIgdXNlZCBpbiBWaWV3IEVuZ2luZSBhbmQgcGVyZm9ybXMgbW9yZSBzdHJpY3QgY2hlY2tzXG4gKiB0byBtYWtlIHN1cmUgaG9zdCBiaW5kaW5ncyBkbyBub3QgY29udGFpbiBwaXBlcy4gSW4gVmlldyBFbmdpbmUsIGhhdmluZyBwaXBlcyBpbiBob3N0IGJpbmRpbmdzIGlzXG4gKiBub3Qgc3VwcG9ydGVkIGFzIHdlbGwsIGJ1dCBpbiBzb21lIGNhc2VzIChsaWtlIGAhKHZhbHVlIHwgYXN5bmMpYCkgdGhlIGVycm9yIGlzIG5vdCB0cmlnZ2VyZWQgYXRcbiAqIGNvbXBpbGUgdGltZS4gSW4gb3JkZXIgdG8gcHJlc2VydmUgVmlldyBFbmdpbmUgYmVoYXZpb3IsIG1vcmUgc3RyaWN0IGNoZWNrcyBhcmUgaW50cm9kdWNlZCBmb3JcbiAqIEl2eSBtb2RlIG9ubHkuXG4gKi9cbmNsYXNzIEl2eVNpbXBsZUV4cHJlc3Npb25DaGVja2VyIGV4dGVuZHMgUmVjdXJzaXZlQXN0VmlzaXRvciBpbXBsZW1lbnRzIFNpbXBsZUV4cHJlc3Npb25DaGVja2VyIHtcbiAgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIG92ZXJyaWRlIHZpc2l0UGlwZSgpIHtcbiAgICB0aGlzLmVycm9ycy5wdXNoKCdwaXBlcycpO1xuICB9XG59XG4iXX0= |
---|