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 { ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan } from '../parse_util';
|
---|
10 | import { NAMED_ENTITIES } from './entities';
|
---|
11 | import { DEFAULT_INTERPOLATION_CONFIG } from './interpolation_config';
|
---|
12 | import { TagContentType } from './tags';
|
---|
13 | export class TokenError extends ParseError {
|
---|
14 | constructor(errorMsg, tokenType, span) {
|
---|
15 | super(span, errorMsg);
|
---|
16 | this.tokenType = tokenType;
|
---|
17 | }
|
---|
18 | }
|
---|
19 | export class TokenizeResult {
|
---|
20 | constructor(tokens, errors, nonNormalizedIcuExpressions) {
|
---|
21 | this.tokens = tokens;
|
---|
22 | this.errors = errors;
|
---|
23 | this.nonNormalizedIcuExpressions = nonNormalizedIcuExpressions;
|
---|
24 | }
|
---|
25 | }
|
---|
26 | export function tokenize(source, url, getTagDefinition, options = {}) {
|
---|
27 | const tokenizer = new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options);
|
---|
28 | tokenizer.tokenize();
|
---|
29 | return new TokenizeResult(mergeTextTokens(tokenizer.tokens), tokenizer.errors, tokenizer.nonNormalizedIcuExpressions);
|
---|
30 | }
|
---|
31 | const _CR_OR_CRLF_REGEXP = /\r\n?/g;
|
---|
32 | function _unexpectedCharacterErrorMsg(charCode) {
|
---|
33 | const char = charCode === chars.$EOF ? 'EOF' : String.fromCharCode(charCode);
|
---|
34 | return `Unexpected character "${char}"`;
|
---|
35 | }
|
---|
36 | function _unknownEntityErrorMsg(entitySrc) {
|
---|
37 | return `Unknown entity "${entitySrc}" - use the "&#<decimal>;" or "&#x<hex>;" syntax`;
|
---|
38 | }
|
---|
39 | function _unparsableEntityErrorMsg(type, entityStr) {
|
---|
40 | return `Unable to parse entity "${entityStr}" - ${type} character reference entities must end with ";"`;
|
---|
41 | }
|
---|
42 | var CharacterReferenceType;
|
---|
43 | (function (CharacterReferenceType) {
|
---|
44 | CharacterReferenceType["HEX"] = "hexadecimal";
|
---|
45 | CharacterReferenceType["DEC"] = "decimal";
|
---|
46 | })(CharacterReferenceType || (CharacterReferenceType = {}));
|
---|
47 | class _ControlFlowError {
|
---|
48 | constructor(error) {
|
---|
49 | this.error = error;
|
---|
50 | }
|
---|
51 | }
|
---|
52 | // See https://www.w3.org/TR/html51/syntax.html#writing-html-documents
|
---|
53 | class _Tokenizer {
|
---|
54 | /**
|
---|
55 | * @param _file The html source file being tokenized.
|
---|
56 | * @param _getTagDefinition A function that will retrieve a tag definition for a given tag name.
|
---|
57 | * @param options Configuration of the tokenization.
|
---|
58 | */
|
---|
59 | constructor(_file, _getTagDefinition, options) {
|
---|
60 | this._getTagDefinition = _getTagDefinition;
|
---|
61 | this._currentTokenStart = null;
|
---|
62 | this._currentTokenType = null;
|
---|
63 | this._expansionCaseStack = [];
|
---|
64 | this._inInterpolation = false;
|
---|
65 | this.tokens = [];
|
---|
66 | this.errors = [];
|
---|
67 | this.nonNormalizedIcuExpressions = [];
|
---|
68 | this._tokenizeIcu = options.tokenizeExpansionForms || false;
|
---|
69 | this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
|
---|
70 | this._leadingTriviaCodePoints =
|
---|
71 | options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0);
|
---|
72 | const range = options.range || { endPos: _file.content.length, startPos: 0, startLine: 0, startCol: 0 };
|
---|
73 | this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) :
|
---|
74 | new PlainCharacterCursor(_file, range);
|
---|
75 | this._preserveLineEndings = options.preserveLineEndings || false;
|
---|
76 | this._escapedString = options.escapedString || false;
|
---|
77 | this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
|
---|
78 | try {
|
---|
79 | this._cursor.init();
|
---|
80 | }
|
---|
81 | catch (e) {
|
---|
82 | this.handleError(e);
|
---|
83 | }
|
---|
84 | }
|
---|
85 | _processCarriageReturns(content) {
|
---|
86 | if (this._preserveLineEndings) {
|
---|
87 | return content;
|
---|
88 | }
|
---|
89 | // https://www.w3.org/TR/html51/syntax.html#preprocessing-the-input-stream
|
---|
90 | // In order to keep the original position in the source, we can not
|
---|
91 | // pre-process it.
|
---|
92 | // Instead CRs are processed right before instantiating the tokens.
|
---|
93 | return content.replace(_CR_OR_CRLF_REGEXP, '\n');
|
---|
94 | }
|
---|
95 | tokenize() {
|
---|
96 | while (this._cursor.peek() !== chars.$EOF) {
|
---|
97 | const start = this._cursor.clone();
|
---|
98 | try {
|
---|
99 | if (this._attemptCharCode(chars.$LT)) {
|
---|
100 | if (this._attemptCharCode(chars.$BANG)) {
|
---|
101 | if (this._attemptCharCode(chars.$LBRACKET)) {
|
---|
102 | this._consumeCdata(start);
|
---|
103 | }
|
---|
104 | else if (this._attemptCharCode(chars.$MINUS)) {
|
---|
105 | this._consumeComment(start);
|
---|
106 | }
|
---|
107 | else {
|
---|
108 | this._consumeDocType(start);
|
---|
109 | }
|
---|
110 | }
|
---|
111 | else if (this._attemptCharCode(chars.$SLASH)) {
|
---|
112 | this._consumeTagClose(start);
|
---|
113 | }
|
---|
114 | else {
|
---|
115 | this._consumeTagOpen(start);
|
---|
116 | }
|
---|
117 | }
|
---|
118 | else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
|
---|
119 | // In (possibly interpolated) text the end of the text is given by `isTextEnd()`, while
|
---|
120 | // the premature end of an interpolation is given by the start of a new HTML element.
|
---|
121 | this._consumeWithInterpolation(5 /* TEXT */, 8 /* INTERPOLATION */, () => this._isTextEnd(), () => this._isTagStart());
|
---|
122 | }
|
---|
123 | }
|
---|
124 | catch (e) {
|
---|
125 | this.handleError(e);
|
---|
126 | }
|
---|
127 | }
|
---|
128 | this._beginToken(24 /* EOF */);
|
---|
129 | this._endToken([]);
|
---|
130 | }
|
---|
131 | /**
|
---|
132 | * @returns whether an ICU token has been created
|
---|
133 | * @internal
|
---|
134 | */
|
---|
135 | _tokenizeExpansionForm() {
|
---|
136 | if (this.isExpansionFormStart()) {
|
---|
137 | this._consumeExpansionFormStart();
|
---|
138 | return true;
|
---|
139 | }
|
---|
140 | if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) {
|
---|
141 | this._consumeExpansionCaseStart();
|
---|
142 | return true;
|
---|
143 | }
|
---|
144 | if (this._cursor.peek() === chars.$RBRACE) {
|
---|
145 | if (this._isInExpansionCase()) {
|
---|
146 | this._consumeExpansionCaseEnd();
|
---|
147 | return true;
|
---|
148 | }
|
---|
149 | if (this._isInExpansionForm()) {
|
---|
150 | this._consumeExpansionFormEnd();
|
---|
151 | return true;
|
---|
152 | }
|
---|
153 | }
|
---|
154 | return false;
|
---|
155 | }
|
---|
156 | _beginToken(type, start = this._cursor.clone()) {
|
---|
157 | this._currentTokenStart = start;
|
---|
158 | this._currentTokenType = type;
|
---|
159 | }
|
---|
160 | _endToken(parts, end) {
|
---|
161 | if (this._currentTokenStart === null) {
|
---|
162 | throw new TokenError('Programming error - attempted to end a token when there was no start to the token', this._currentTokenType, this._cursor.getSpan(end));
|
---|
163 | }
|
---|
164 | if (this._currentTokenType === null) {
|
---|
165 | throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart));
|
---|
166 | }
|
---|
167 | const token = {
|
---|
168 | type: this._currentTokenType,
|
---|
169 | parts,
|
---|
170 | sourceSpan: (end !== null && end !== void 0 ? end : this._cursor).getSpan(this._currentTokenStart, this._leadingTriviaCodePoints),
|
---|
171 | };
|
---|
172 | this.tokens.push(token);
|
---|
173 | this._currentTokenStart = null;
|
---|
174 | this._currentTokenType = null;
|
---|
175 | return token;
|
---|
176 | }
|
---|
177 | _createError(msg, span) {
|
---|
178 | if (this._isInExpansionForm()) {
|
---|
179 | msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
|
---|
180 | }
|
---|
181 | const error = new TokenError(msg, this._currentTokenType, span);
|
---|
182 | this._currentTokenStart = null;
|
---|
183 | this._currentTokenType = null;
|
---|
184 | return new _ControlFlowError(error);
|
---|
185 | }
|
---|
186 | handleError(e) {
|
---|
187 | if (e instanceof CursorError) {
|
---|
188 | e = this._createError(e.msg, this._cursor.getSpan(e.cursor));
|
---|
189 | }
|
---|
190 | if (e instanceof _ControlFlowError) {
|
---|
191 | this.errors.push(e.error);
|
---|
192 | }
|
---|
193 | else {
|
---|
194 | throw e;
|
---|
195 | }
|
---|
196 | }
|
---|
197 | _attemptCharCode(charCode) {
|
---|
198 | if (this._cursor.peek() === charCode) {
|
---|
199 | this._cursor.advance();
|
---|
200 | return true;
|
---|
201 | }
|
---|
202 | return false;
|
---|
203 | }
|
---|
204 | _attemptCharCodeCaseInsensitive(charCode) {
|
---|
205 | if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) {
|
---|
206 | this._cursor.advance();
|
---|
207 | return true;
|
---|
208 | }
|
---|
209 | return false;
|
---|
210 | }
|
---|
211 | _requireCharCode(charCode) {
|
---|
212 | const location = this._cursor.clone();
|
---|
213 | if (!this._attemptCharCode(charCode)) {
|
---|
214 | throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
|
---|
215 | }
|
---|
216 | }
|
---|
217 | _attemptStr(chars) {
|
---|
218 | const len = chars.length;
|
---|
219 | if (this._cursor.charsLeft() < len) {
|
---|
220 | return false;
|
---|
221 | }
|
---|
222 | const initialPosition = this._cursor.clone();
|
---|
223 | for (let i = 0; i < len; i++) {
|
---|
224 | if (!this._attemptCharCode(chars.charCodeAt(i))) {
|
---|
225 | // If attempting to parse the string fails, we want to reset the parser
|
---|
226 | // to where it was before the attempt
|
---|
227 | this._cursor = initialPosition;
|
---|
228 | return false;
|
---|
229 | }
|
---|
230 | }
|
---|
231 | return true;
|
---|
232 | }
|
---|
233 | _attemptStrCaseInsensitive(chars) {
|
---|
234 | for (let i = 0; i < chars.length; i++) {
|
---|
235 | if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) {
|
---|
236 | return false;
|
---|
237 | }
|
---|
238 | }
|
---|
239 | return true;
|
---|
240 | }
|
---|
241 | _requireStr(chars) {
|
---|
242 | const location = this._cursor.clone();
|
---|
243 | if (!this._attemptStr(chars)) {
|
---|
244 | throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
|
---|
245 | }
|
---|
246 | }
|
---|
247 | _attemptCharCodeUntilFn(predicate) {
|
---|
248 | while (!predicate(this._cursor.peek())) {
|
---|
249 | this._cursor.advance();
|
---|
250 | }
|
---|
251 | }
|
---|
252 | _requireCharCodeUntilFn(predicate, len) {
|
---|
253 | const start = this._cursor.clone();
|
---|
254 | this._attemptCharCodeUntilFn(predicate);
|
---|
255 | if (this._cursor.diff(start) < len) {
|
---|
256 | throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
|
---|
257 | }
|
---|
258 | }
|
---|
259 | _attemptUntilChar(char) {
|
---|
260 | while (this._cursor.peek() !== char) {
|
---|
261 | this._cursor.advance();
|
---|
262 | }
|
---|
263 | }
|
---|
264 | _readChar() {
|
---|
265 | // Don't rely upon reading directly from `_input` as the actual char value
|
---|
266 | // may have been generated from an escape sequence.
|
---|
267 | const char = String.fromCodePoint(this._cursor.peek());
|
---|
268 | this._cursor.advance();
|
---|
269 | return char;
|
---|
270 | }
|
---|
271 | _consumeEntity(textTokenType) {
|
---|
272 | this._beginToken(9 /* ENCODED_ENTITY */);
|
---|
273 | const start = this._cursor.clone();
|
---|
274 | this._cursor.advance();
|
---|
275 | if (this._attemptCharCode(chars.$HASH)) {
|
---|
276 | const isHex = this._attemptCharCode(chars.$x) || this._attemptCharCode(chars.$X);
|
---|
277 | const codeStart = this._cursor.clone();
|
---|
278 | this._attemptCharCodeUntilFn(isDigitEntityEnd);
|
---|
279 | if (this._cursor.peek() != chars.$SEMICOLON) {
|
---|
280 | // Advance cursor to include the peeked character in the string provided to the error
|
---|
281 | // message.
|
---|
282 | this._cursor.advance();
|
---|
283 | const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC;
|
---|
284 | throw this._createError(_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), this._cursor.getSpan());
|
---|
285 | }
|
---|
286 | const strNum = this._cursor.getChars(codeStart);
|
---|
287 | this._cursor.advance();
|
---|
288 | try {
|
---|
289 | const charCode = parseInt(strNum, isHex ? 16 : 10);
|
---|
290 | this._endToken([String.fromCharCode(charCode), this._cursor.getChars(start)]);
|
---|
291 | }
|
---|
292 | catch (_a) {
|
---|
293 | throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
|
---|
294 | }
|
---|
295 | }
|
---|
296 | else {
|
---|
297 | const nameStart = this._cursor.clone();
|
---|
298 | this._attemptCharCodeUntilFn(isNamedEntityEnd);
|
---|
299 | if (this._cursor.peek() != chars.$SEMICOLON) {
|
---|
300 | // No semicolon was found so abort the encoded entity token that was in progress, and treat
|
---|
301 | // this as a text token
|
---|
302 | this._beginToken(textTokenType, start);
|
---|
303 | this._cursor = nameStart;
|
---|
304 | this._endToken(['&']);
|
---|
305 | }
|
---|
306 | else {
|
---|
307 | const name = this._cursor.getChars(nameStart);
|
---|
308 | this._cursor.advance();
|
---|
309 | const char = NAMED_ENTITIES[name];
|
---|
310 | if (!char) {
|
---|
311 | throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
|
---|
312 | }
|
---|
313 | this._endToken([char, `&${name};`]);
|
---|
314 | }
|
---|
315 | }
|
---|
316 | }
|
---|
317 | _consumeRawText(consumeEntities, endMarkerPredicate) {
|
---|
318 | this._beginToken(consumeEntities ? 6 /* ESCAPABLE_RAW_TEXT */ : 7 /* RAW_TEXT */);
|
---|
319 | const parts = [];
|
---|
320 | while (true) {
|
---|
321 | const tagCloseStart = this._cursor.clone();
|
---|
322 | const foundEndMarker = endMarkerPredicate();
|
---|
323 | this._cursor = tagCloseStart;
|
---|
324 | if (foundEndMarker) {
|
---|
325 | break;
|
---|
326 | }
|
---|
327 | if (consumeEntities && this._cursor.peek() === chars.$AMPERSAND) {
|
---|
328 | this._endToken([this._processCarriageReturns(parts.join(''))]);
|
---|
329 | parts.length = 0;
|
---|
330 | this._consumeEntity(6 /* ESCAPABLE_RAW_TEXT */);
|
---|
331 | this._beginToken(6 /* ESCAPABLE_RAW_TEXT */);
|
---|
332 | }
|
---|
333 | else {
|
---|
334 | parts.push(this._readChar());
|
---|
335 | }
|
---|
336 | }
|
---|
337 | this._endToken([this._processCarriageReturns(parts.join(''))]);
|
---|
338 | }
|
---|
339 | _consumeComment(start) {
|
---|
340 | this._beginToken(10 /* COMMENT_START */, start);
|
---|
341 | this._requireCharCode(chars.$MINUS);
|
---|
342 | this._endToken([]);
|
---|
343 | this._consumeRawText(false, () => this._attemptStr('-->'));
|
---|
344 | this._beginToken(11 /* COMMENT_END */);
|
---|
345 | this._requireStr('-->');
|
---|
346 | this._endToken([]);
|
---|
347 | }
|
---|
348 | _consumeCdata(start) {
|
---|
349 | this._beginToken(12 /* CDATA_START */, start);
|
---|
350 | this._requireStr('CDATA[');
|
---|
351 | this._endToken([]);
|
---|
352 | this._consumeRawText(false, () => this._attemptStr(']]>'));
|
---|
353 | this._beginToken(13 /* CDATA_END */);
|
---|
354 | this._requireStr(']]>');
|
---|
355 | this._endToken([]);
|
---|
356 | }
|
---|
357 | _consumeDocType(start) {
|
---|
358 | this._beginToken(18 /* DOC_TYPE */, start);
|
---|
359 | const contentStart = this._cursor.clone();
|
---|
360 | this._attemptUntilChar(chars.$GT);
|
---|
361 | const content = this._cursor.getChars(contentStart);
|
---|
362 | this._cursor.advance();
|
---|
363 | this._endToken([content]);
|
---|
364 | }
|
---|
365 | _consumePrefixAndName() {
|
---|
366 | const nameOrPrefixStart = this._cursor.clone();
|
---|
367 | let prefix = '';
|
---|
368 | while (this._cursor.peek() !== chars.$COLON && !isPrefixEnd(this._cursor.peek())) {
|
---|
369 | this._cursor.advance();
|
---|
370 | }
|
---|
371 | let nameStart;
|
---|
372 | if (this._cursor.peek() === chars.$COLON) {
|
---|
373 | prefix = this._cursor.getChars(nameOrPrefixStart);
|
---|
374 | this._cursor.advance();
|
---|
375 | nameStart = this._cursor.clone();
|
---|
376 | }
|
---|
377 | else {
|
---|
378 | nameStart = nameOrPrefixStart;
|
---|
379 | }
|
---|
380 | this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
|
---|
381 | const name = this._cursor.getChars(nameStart);
|
---|
382 | return [prefix, name];
|
---|
383 | }
|
---|
384 | _consumeTagOpen(start) {
|
---|
385 | let tagName;
|
---|
386 | let prefix;
|
---|
387 | let openTagToken;
|
---|
388 | try {
|
---|
389 | if (!chars.isAsciiLetter(this._cursor.peek())) {
|
---|
390 | throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
|
---|
391 | }
|
---|
392 | openTagToken = this._consumeTagOpenStart(start);
|
---|
393 | prefix = openTagToken.parts[0];
|
---|
394 | tagName = openTagToken.parts[1];
|
---|
395 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
396 | while (this._cursor.peek() !== chars.$SLASH && this._cursor.peek() !== chars.$GT &&
|
---|
397 | this._cursor.peek() !== chars.$LT && this._cursor.peek() !== chars.$EOF) {
|
---|
398 | this._consumeAttributeName();
|
---|
399 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
400 | if (this._attemptCharCode(chars.$EQ)) {
|
---|
401 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
402 | this._consumeAttributeValue();
|
---|
403 | }
|
---|
404 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
405 | }
|
---|
406 | this._consumeTagOpenEnd();
|
---|
407 | }
|
---|
408 | catch (e) {
|
---|
409 | if (e instanceof _ControlFlowError) {
|
---|
410 | if (openTagToken) {
|
---|
411 | // We errored before we could close the opening tag, so it is incomplete.
|
---|
412 | openTagToken.type = 4 /* INCOMPLETE_TAG_OPEN */;
|
---|
413 | }
|
---|
414 | else {
|
---|
415 | // When the start tag is invalid, assume we want a "<" as text.
|
---|
416 | // Back to back text tokens are merged at the end.
|
---|
417 | this._beginToken(5 /* TEXT */, start);
|
---|
418 | this._endToken(['<']);
|
---|
419 | }
|
---|
420 | return;
|
---|
421 | }
|
---|
422 | throw e;
|
---|
423 | }
|
---|
424 | const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
|
---|
425 | if (contentTokenType === TagContentType.RAW_TEXT) {
|
---|
426 | this._consumeRawTextWithTagClose(prefix, tagName, false);
|
---|
427 | }
|
---|
428 | else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
|
---|
429 | this._consumeRawTextWithTagClose(prefix, tagName, true);
|
---|
430 | }
|
---|
431 | }
|
---|
432 | _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) {
|
---|
433 | this._consumeRawText(consumeEntities, () => {
|
---|
434 | if (!this._attemptCharCode(chars.$LT))
|
---|
435 | return false;
|
---|
436 | if (!this._attemptCharCode(chars.$SLASH))
|
---|
437 | return false;
|
---|
438 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
439 | if (!this._attemptStrCaseInsensitive(tagName))
|
---|
440 | return false;
|
---|
441 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
442 | return this._attemptCharCode(chars.$GT);
|
---|
443 | });
|
---|
444 | this._beginToken(3 /* TAG_CLOSE */);
|
---|
445 | this._requireCharCodeUntilFn(code => code === chars.$GT, 3);
|
---|
446 | this._cursor.advance(); // Consume the `>`
|
---|
447 | this._endToken([prefix, tagName]);
|
---|
448 | }
|
---|
449 | _consumeTagOpenStart(start) {
|
---|
450 | this._beginToken(0 /* TAG_OPEN_START */, start);
|
---|
451 | const parts = this._consumePrefixAndName();
|
---|
452 | return this._endToken(parts);
|
---|
453 | }
|
---|
454 | _consumeAttributeName() {
|
---|
455 | const attrNameStart = this._cursor.peek();
|
---|
456 | if (attrNameStart === chars.$SQ || attrNameStart === chars.$DQ) {
|
---|
457 | throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
|
---|
458 | }
|
---|
459 | this._beginToken(14 /* ATTR_NAME */);
|
---|
460 | const prefixAndName = this._consumePrefixAndName();
|
---|
461 | this._endToken(prefixAndName);
|
---|
462 | }
|
---|
463 | _consumeAttributeValue() {
|
---|
464 | let value;
|
---|
465 | if (this._cursor.peek() === chars.$SQ || this._cursor.peek() === chars.$DQ) {
|
---|
466 | const quoteChar = this._cursor.peek();
|
---|
467 | this._consumeQuote(quoteChar);
|
---|
468 | // In an attribute then end of the attribute value and the premature end to an interpolation
|
---|
469 | // are both triggered by the `quoteChar`.
|
---|
470 | const endPredicate = () => this._cursor.peek() === quoteChar;
|
---|
471 | this._consumeWithInterpolation(16 /* ATTR_VALUE_TEXT */, 17 /* ATTR_VALUE_INTERPOLATION */, endPredicate, endPredicate);
|
---|
472 | this._consumeQuote(quoteChar);
|
---|
473 | }
|
---|
474 | else {
|
---|
475 | const endPredicate = () => isNameEnd(this._cursor.peek());
|
---|
476 | this._consumeWithInterpolation(16 /* ATTR_VALUE_TEXT */, 17 /* ATTR_VALUE_INTERPOLATION */, endPredicate, endPredicate);
|
---|
477 | }
|
---|
478 | }
|
---|
479 | _consumeQuote(quoteChar) {
|
---|
480 | this._beginToken(15 /* ATTR_QUOTE */);
|
---|
481 | this._requireCharCode(quoteChar);
|
---|
482 | this._endToken([String.fromCodePoint(quoteChar)]);
|
---|
483 | }
|
---|
484 | _consumeTagOpenEnd() {
|
---|
485 | const tokenType = this._attemptCharCode(chars.$SLASH) ? 2 /* TAG_OPEN_END_VOID */ : 1 /* TAG_OPEN_END */;
|
---|
486 | this._beginToken(tokenType);
|
---|
487 | this._requireCharCode(chars.$GT);
|
---|
488 | this._endToken([]);
|
---|
489 | }
|
---|
490 | _consumeTagClose(start) {
|
---|
491 | this._beginToken(3 /* TAG_CLOSE */, start);
|
---|
492 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
493 | const prefixAndName = this._consumePrefixAndName();
|
---|
494 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
495 | this._requireCharCode(chars.$GT);
|
---|
496 | this._endToken(prefixAndName);
|
---|
497 | }
|
---|
498 | _consumeExpansionFormStart() {
|
---|
499 | this._beginToken(19 /* EXPANSION_FORM_START */);
|
---|
500 | this._requireCharCode(chars.$LBRACE);
|
---|
501 | this._endToken([]);
|
---|
502 | this._expansionCaseStack.push(19 /* EXPANSION_FORM_START */);
|
---|
503 | this._beginToken(7 /* RAW_TEXT */);
|
---|
504 | const condition = this._readUntil(chars.$COMMA);
|
---|
505 | const normalizedCondition = this._processCarriageReturns(condition);
|
---|
506 | if (this._i18nNormalizeLineEndingsInICUs) {
|
---|
507 | // We explicitly want to normalize line endings for this text.
|
---|
508 | this._endToken([normalizedCondition]);
|
---|
509 | }
|
---|
510 | else {
|
---|
511 | // We are not normalizing line endings.
|
---|
512 | const conditionToken = this._endToken([condition]);
|
---|
513 | if (normalizedCondition !== condition) {
|
---|
514 | this.nonNormalizedIcuExpressions.push(conditionToken);
|
---|
515 | }
|
---|
516 | }
|
---|
517 | this._requireCharCode(chars.$COMMA);
|
---|
518 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
519 | this._beginToken(7 /* RAW_TEXT */);
|
---|
520 | const type = this._readUntil(chars.$COMMA);
|
---|
521 | this._endToken([type]);
|
---|
522 | this._requireCharCode(chars.$COMMA);
|
---|
523 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
524 | }
|
---|
525 | _consumeExpansionCaseStart() {
|
---|
526 | this._beginToken(20 /* EXPANSION_CASE_VALUE */);
|
---|
527 | const value = this._readUntil(chars.$LBRACE).trim();
|
---|
528 | this._endToken([value]);
|
---|
529 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
530 | this._beginToken(21 /* EXPANSION_CASE_EXP_START */);
|
---|
531 | this._requireCharCode(chars.$LBRACE);
|
---|
532 | this._endToken([]);
|
---|
533 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
534 | this._expansionCaseStack.push(21 /* EXPANSION_CASE_EXP_START */);
|
---|
535 | }
|
---|
536 | _consumeExpansionCaseEnd() {
|
---|
537 | this._beginToken(22 /* EXPANSION_CASE_EXP_END */);
|
---|
538 | this._requireCharCode(chars.$RBRACE);
|
---|
539 | this._endToken([]);
|
---|
540 | this._attemptCharCodeUntilFn(isNotWhitespace);
|
---|
541 | this._expansionCaseStack.pop();
|
---|
542 | }
|
---|
543 | _consumeExpansionFormEnd() {
|
---|
544 | this._beginToken(23 /* EXPANSION_FORM_END */);
|
---|
545 | this._requireCharCode(chars.$RBRACE);
|
---|
546 | this._endToken([]);
|
---|
547 | this._expansionCaseStack.pop();
|
---|
548 | }
|
---|
549 | /**
|
---|
550 | * Consume a string that may contain interpolation expressions.
|
---|
551 | *
|
---|
552 | * The first token consumed will be of `tokenType` and then there will be alternating
|
---|
553 | * `interpolationTokenType` and `tokenType` tokens until the `endPredicate()` returns true.
|
---|
554 | *
|
---|
555 | * If an interpolation token ends prematurely it will have no end marker in its `parts` array.
|
---|
556 | *
|
---|
557 | * @param textTokenType the kind of tokens to interleave around interpolation tokens.
|
---|
558 | * @param interpolationTokenType the kind of tokens that contain interpolation.
|
---|
559 | * @param endPredicate a function that should return true when we should stop consuming.
|
---|
560 | * @param endInterpolation a function that should return true if there is a premature end to an
|
---|
561 | * interpolation expression - i.e. before we get to the normal interpolation closing marker.
|
---|
562 | */
|
---|
563 | _consumeWithInterpolation(textTokenType, interpolationTokenType, endPredicate, endInterpolation) {
|
---|
564 | this._beginToken(textTokenType);
|
---|
565 | const parts = [];
|
---|
566 | while (!endPredicate()) {
|
---|
567 | const current = this._cursor.clone();
|
---|
568 | if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
|
---|
569 | this._endToken([this._processCarriageReturns(parts.join(''))], current);
|
---|
570 | parts.length = 0;
|
---|
571 | this._consumeInterpolation(interpolationTokenType, current, endInterpolation);
|
---|
572 | this._beginToken(textTokenType);
|
---|
573 | }
|
---|
574 | else if (this._cursor.peek() === chars.$AMPERSAND) {
|
---|
575 | this._endToken([this._processCarriageReturns(parts.join(''))]);
|
---|
576 | parts.length = 0;
|
---|
577 | this._consumeEntity(textTokenType);
|
---|
578 | this._beginToken(textTokenType);
|
---|
579 | }
|
---|
580 | else {
|
---|
581 | parts.push(this._readChar());
|
---|
582 | }
|
---|
583 | }
|
---|
584 | // It is possible that an interpolation was started but not ended inside this text token.
|
---|
585 | // Make sure that we reset the state of the lexer correctly.
|
---|
586 | this._inInterpolation = false;
|
---|
587 | this._endToken([this._processCarriageReturns(parts.join(''))]);
|
---|
588 | }
|
---|
589 | /**
|
---|
590 | * Consume a block of text that has been interpreted as an Angular interpolation.
|
---|
591 | *
|
---|
592 | * @param interpolationTokenType the type of the interpolation token to generate.
|
---|
593 | * @param interpolationStart a cursor that points to the start of this interpolation.
|
---|
594 | * @param prematureEndPredicate a function that should return true if the next characters indicate
|
---|
595 | * an end to the interpolation before its normal closing marker.
|
---|
596 | */
|
---|
597 | _consumeInterpolation(interpolationTokenType, interpolationStart, prematureEndPredicate) {
|
---|
598 | const parts = [];
|
---|
599 | this._beginToken(interpolationTokenType, interpolationStart);
|
---|
600 | parts.push(this._interpolationConfig.start);
|
---|
601 | // Find the end of the interpolation, ignoring content inside quotes.
|
---|
602 | const expressionStart = this._cursor.clone();
|
---|
603 | let inQuote = null;
|
---|
604 | let inComment = false;
|
---|
605 | while (this._cursor.peek() !== chars.$EOF &&
|
---|
606 | (prematureEndPredicate === null || !prematureEndPredicate())) {
|
---|
607 | const current = this._cursor.clone();
|
---|
608 | if (this._isTagStart()) {
|
---|
609 | // We are starting what looks like an HTML element in the middle of this interpolation.
|
---|
610 | // Reset the cursor to before the `<` character and end the interpolation token.
|
---|
611 | // (This is actually wrong but here for backward compatibility).
|
---|
612 | this._cursor = current;
|
---|
613 | parts.push(this._getProcessedChars(expressionStart, current));
|
---|
614 | this._endToken(parts);
|
---|
615 | return;
|
---|
616 | }
|
---|
617 | if (inQuote === null) {
|
---|
618 | if (this._attemptStr(this._interpolationConfig.end)) {
|
---|
619 | // We are not in a string, and we hit the end interpolation marker
|
---|
620 | parts.push(this._getProcessedChars(expressionStart, current));
|
---|
621 | parts.push(this._interpolationConfig.end);
|
---|
622 | this._endToken(parts);
|
---|
623 | return;
|
---|
624 | }
|
---|
625 | else if (this._attemptStr('//')) {
|
---|
626 | // Once we are in a comment we ignore any quotes
|
---|
627 | inComment = true;
|
---|
628 | }
|
---|
629 | }
|
---|
630 | const char = this._cursor.peek();
|
---|
631 | this._cursor.advance();
|
---|
632 | if (char === chars.$BACKSLASH) {
|
---|
633 | // Skip the next character because it was escaped.
|
---|
634 | this._cursor.advance();
|
---|
635 | }
|
---|
636 | else if (char === inQuote) {
|
---|
637 | // Exiting the current quoted string
|
---|
638 | inQuote = null;
|
---|
639 | }
|
---|
640 | else if (!inComment && inQuote === null && chars.isQuote(char)) {
|
---|
641 | // Entering a new quoted string
|
---|
642 | inQuote = char;
|
---|
643 | }
|
---|
644 | }
|
---|
645 | // We hit EOF without finding a closing interpolation marker
|
---|
646 | parts.push(this._getProcessedChars(expressionStart, this._cursor));
|
---|
647 | this._endToken(parts);
|
---|
648 | }
|
---|
649 | _getProcessedChars(start, end) {
|
---|
650 | return this._processCarriageReturns(end.getChars(start));
|
---|
651 | }
|
---|
652 | _isTextEnd() {
|
---|
653 | if (this._isTagStart() || this._cursor.peek() === chars.$EOF) {
|
---|
654 | return true;
|
---|
655 | }
|
---|
656 | if (this._tokenizeIcu && !this._inInterpolation) {
|
---|
657 | if (this.isExpansionFormStart()) {
|
---|
658 | // start of an expansion form
|
---|
659 | return true;
|
---|
660 | }
|
---|
661 | if (this._cursor.peek() === chars.$RBRACE && this._isInExpansionCase()) {
|
---|
662 | // end of and expansion case
|
---|
663 | return true;
|
---|
664 | }
|
---|
665 | }
|
---|
666 | return false;
|
---|
667 | }
|
---|
668 | /**
|
---|
669 | * Returns true if the current cursor is pointing to the start of a tag
|
---|
670 | * (opening/closing/comments/cdata/etc).
|
---|
671 | */
|
---|
672 | _isTagStart() {
|
---|
673 | if (this._cursor.peek() === chars.$LT) {
|
---|
674 | // We assume that `<` followed by whitespace is not the start of an HTML element.
|
---|
675 | const tmp = this._cursor.clone();
|
---|
676 | tmp.advance();
|
---|
677 | // If the next character is alphabetic, ! nor / then it is a tag start
|
---|
678 | const code = tmp.peek();
|
---|
679 | if ((chars.$a <= code && code <= chars.$z) || (chars.$A <= code && code <= chars.$Z) ||
|
---|
680 | code === chars.$SLASH || code === chars.$BANG) {
|
---|
681 | return true;
|
---|
682 | }
|
---|
683 | }
|
---|
684 | return false;
|
---|
685 | }
|
---|
686 | _readUntil(char) {
|
---|
687 | const start = this._cursor.clone();
|
---|
688 | this._attemptUntilChar(char);
|
---|
689 | return this._cursor.getChars(start);
|
---|
690 | }
|
---|
691 | _isInExpansionCase() {
|
---|
692 | return this._expansionCaseStack.length > 0 &&
|
---|
693 | this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
|
---|
694 | 21 /* EXPANSION_CASE_EXP_START */;
|
---|
695 | }
|
---|
696 | _isInExpansionForm() {
|
---|
697 | return this._expansionCaseStack.length > 0 &&
|
---|
698 | this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
|
---|
699 | 19 /* EXPANSION_FORM_START */;
|
---|
700 | }
|
---|
701 | isExpansionFormStart() {
|
---|
702 | if (this._cursor.peek() !== chars.$LBRACE) {
|
---|
703 | return false;
|
---|
704 | }
|
---|
705 | if (this._interpolationConfig) {
|
---|
706 | const start = this._cursor.clone();
|
---|
707 | const isInterpolation = this._attemptStr(this._interpolationConfig.start);
|
---|
708 | this._cursor = start;
|
---|
709 | return !isInterpolation;
|
---|
710 | }
|
---|
711 | return true;
|
---|
712 | }
|
---|
713 | }
|
---|
714 | function isNotWhitespace(code) {
|
---|
715 | return !chars.isWhitespace(code) || code === chars.$EOF;
|
---|
716 | }
|
---|
717 | function isNameEnd(code) {
|
---|
718 | return chars.isWhitespace(code) || code === chars.$GT || code === chars.$LT ||
|
---|
719 | code === chars.$SLASH || code === chars.$SQ || code === chars.$DQ || code === chars.$EQ ||
|
---|
720 | code === chars.$EOF;
|
---|
721 | }
|
---|
722 | function isPrefixEnd(code) {
|
---|
723 | return (code < chars.$a || chars.$z < code) && (code < chars.$A || chars.$Z < code) &&
|
---|
724 | (code < chars.$0 || code > chars.$9);
|
---|
725 | }
|
---|
726 | function isDigitEntityEnd(code) {
|
---|
727 | return code === chars.$SEMICOLON || code === chars.$EOF || !chars.isAsciiHexDigit(code);
|
---|
728 | }
|
---|
729 | function isNamedEntityEnd(code) {
|
---|
730 | return code === chars.$SEMICOLON || code === chars.$EOF || !chars.isAsciiLetter(code);
|
---|
731 | }
|
---|
732 | function isExpansionCaseStart(peek) {
|
---|
733 | return peek !== chars.$RBRACE;
|
---|
734 | }
|
---|
735 | function compareCharCodeCaseInsensitive(code1, code2) {
|
---|
736 | return toUpperCaseCharCode(code1) === toUpperCaseCharCode(code2);
|
---|
737 | }
|
---|
738 | function toUpperCaseCharCode(code) {
|
---|
739 | return code >= chars.$a && code <= chars.$z ? code - chars.$a + chars.$A : code;
|
---|
740 | }
|
---|
741 | function mergeTextTokens(srcTokens) {
|
---|
742 | const dstTokens = [];
|
---|
743 | let lastDstToken = undefined;
|
---|
744 | for (let i = 0; i < srcTokens.length; i++) {
|
---|
745 | const token = srcTokens[i];
|
---|
746 | if ((lastDstToken && lastDstToken.type === 5 /* TEXT */ && token.type === 5 /* TEXT */) ||
|
---|
747 | (lastDstToken && lastDstToken.type === 16 /* ATTR_VALUE_TEXT */ &&
|
---|
748 | token.type === 16 /* ATTR_VALUE_TEXT */)) {
|
---|
749 | lastDstToken.parts[0] += token.parts[0];
|
---|
750 | lastDstToken.sourceSpan.end = token.sourceSpan.end;
|
---|
751 | }
|
---|
752 | else {
|
---|
753 | lastDstToken = token;
|
---|
754 | dstTokens.push(lastDstToken);
|
---|
755 | }
|
---|
756 | }
|
---|
757 | return dstTokens;
|
---|
758 | }
|
---|
759 | class PlainCharacterCursor {
|
---|
760 | constructor(fileOrCursor, range) {
|
---|
761 | if (fileOrCursor instanceof PlainCharacterCursor) {
|
---|
762 | this.file = fileOrCursor.file;
|
---|
763 | this.input = fileOrCursor.input;
|
---|
764 | this.end = fileOrCursor.end;
|
---|
765 | const state = fileOrCursor.state;
|
---|
766 | // Note: avoid using `{...fileOrCursor.state}` here as that has a severe performance penalty.
|
---|
767 | // In ES5 bundles the object spread operator is translated into the `__assign` helper, which
|
---|
768 | // is not optimized by VMs as efficiently as a raw object literal. Since this constructor is
|
---|
769 | // called in tight loops, this difference matters.
|
---|
770 | this.state = {
|
---|
771 | peek: state.peek,
|
---|
772 | offset: state.offset,
|
---|
773 | line: state.line,
|
---|
774 | column: state.column,
|
---|
775 | };
|
---|
776 | }
|
---|
777 | else {
|
---|
778 | if (!range) {
|
---|
779 | throw new Error('Programming error: the range argument must be provided with a file argument.');
|
---|
780 | }
|
---|
781 | this.file = fileOrCursor;
|
---|
782 | this.input = fileOrCursor.content;
|
---|
783 | this.end = range.endPos;
|
---|
784 | this.state = {
|
---|
785 | peek: -1,
|
---|
786 | offset: range.startPos,
|
---|
787 | line: range.startLine,
|
---|
788 | column: range.startCol,
|
---|
789 | };
|
---|
790 | }
|
---|
791 | }
|
---|
792 | clone() {
|
---|
793 | return new PlainCharacterCursor(this);
|
---|
794 | }
|
---|
795 | peek() {
|
---|
796 | return this.state.peek;
|
---|
797 | }
|
---|
798 | charsLeft() {
|
---|
799 | return this.end - this.state.offset;
|
---|
800 | }
|
---|
801 | diff(other) {
|
---|
802 | return this.state.offset - other.state.offset;
|
---|
803 | }
|
---|
804 | advance() {
|
---|
805 | this.advanceState(this.state);
|
---|
806 | }
|
---|
807 | init() {
|
---|
808 | this.updatePeek(this.state);
|
---|
809 | }
|
---|
810 | getSpan(start, leadingTriviaCodePoints) {
|
---|
811 | start = start || this;
|
---|
812 | let fullStart = start;
|
---|
813 | if (leadingTriviaCodePoints) {
|
---|
814 | while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) {
|
---|
815 | if (fullStart === start) {
|
---|
816 | start = start.clone();
|
---|
817 | }
|
---|
818 | start.advance();
|
---|
819 | }
|
---|
820 | }
|
---|
821 | const startLocation = this.locationFromCursor(start);
|
---|
822 | const endLocation = this.locationFromCursor(this);
|
---|
823 | const fullStartLocation = fullStart !== start ? this.locationFromCursor(fullStart) : startLocation;
|
---|
824 | return new ParseSourceSpan(startLocation, endLocation, fullStartLocation);
|
---|
825 | }
|
---|
826 | getChars(start) {
|
---|
827 | return this.input.substring(start.state.offset, this.state.offset);
|
---|
828 | }
|
---|
829 | charAt(pos) {
|
---|
830 | return this.input.charCodeAt(pos);
|
---|
831 | }
|
---|
832 | advanceState(state) {
|
---|
833 | if (state.offset >= this.end) {
|
---|
834 | this.state = state;
|
---|
835 | throw new CursorError('Unexpected character "EOF"', this);
|
---|
836 | }
|
---|
837 | const currentChar = this.charAt(state.offset);
|
---|
838 | if (currentChar === chars.$LF) {
|
---|
839 | state.line++;
|
---|
840 | state.column = 0;
|
---|
841 | }
|
---|
842 | else if (!chars.isNewLine(currentChar)) {
|
---|
843 | state.column++;
|
---|
844 | }
|
---|
845 | state.offset++;
|
---|
846 | this.updatePeek(state);
|
---|
847 | }
|
---|
848 | updatePeek(state) {
|
---|
849 | state.peek = state.offset >= this.end ? chars.$EOF : this.charAt(state.offset);
|
---|
850 | }
|
---|
851 | locationFromCursor(cursor) {
|
---|
852 | return new ParseLocation(cursor.file, cursor.state.offset, cursor.state.line, cursor.state.column);
|
---|
853 | }
|
---|
854 | }
|
---|
855 | class EscapedCharacterCursor extends PlainCharacterCursor {
|
---|
856 | constructor(fileOrCursor, range) {
|
---|
857 | if (fileOrCursor instanceof EscapedCharacterCursor) {
|
---|
858 | super(fileOrCursor);
|
---|
859 | this.internalState = Object.assign({}, fileOrCursor.internalState);
|
---|
860 | }
|
---|
861 | else {
|
---|
862 | super(fileOrCursor, range);
|
---|
863 | this.internalState = this.state;
|
---|
864 | }
|
---|
865 | }
|
---|
866 | advance() {
|
---|
867 | this.state = this.internalState;
|
---|
868 | super.advance();
|
---|
869 | this.processEscapeSequence();
|
---|
870 | }
|
---|
871 | init() {
|
---|
872 | super.init();
|
---|
873 | this.processEscapeSequence();
|
---|
874 | }
|
---|
875 | clone() {
|
---|
876 | return new EscapedCharacterCursor(this);
|
---|
877 | }
|
---|
878 | getChars(start) {
|
---|
879 | const cursor = start.clone();
|
---|
880 | let chars = '';
|
---|
881 | while (cursor.internalState.offset < this.internalState.offset) {
|
---|
882 | chars += String.fromCodePoint(cursor.peek());
|
---|
883 | cursor.advance();
|
---|
884 | }
|
---|
885 | return chars;
|
---|
886 | }
|
---|
887 | /**
|
---|
888 | * Process the escape sequence that starts at the current position in the text.
|
---|
889 | *
|
---|
890 | * This method is called to ensure that `peek` has the unescaped value of escape sequences.
|
---|
891 | */
|
---|
892 | processEscapeSequence() {
|
---|
893 | const peek = () => this.internalState.peek;
|
---|
894 | if (peek() === chars.$BACKSLASH) {
|
---|
895 | // We have hit an escape sequence so we need the internal state to become independent
|
---|
896 | // of the external state.
|
---|
897 | this.internalState = Object.assign({}, this.state);
|
---|
898 | // Move past the backslash
|
---|
899 | this.advanceState(this.internalState);
|
---|
900 | // First check for standard control char sequences
|
---|
901 | if (peek() === chars.$n) {
|
---|
902 | this.state.peek = chars.$LF;
|
---|
903 | }
|
---|
904 | else if (peek() === chars.$r) {
|
---|
905 | this.state.peek = chars.$CR;
|
---|
906 | }
|
---|
907 | else if (peek() === chars.$v) {
|
---|
908 | this.state.peek = chars.$VTAB;
|
---|
909 | }
|
---|
910 | else if (peek() === chars.$t) {
|
---|
911 | this.state.peek = chars.$TAB;
|
---|
912 | }
|
---|
913 | else if (peek() === chars.$b) {
|
---|
914 | this.state.peek = chars.$BSPACE;
|
---|
915 | }
|
---|
916 | else if (peek() === chars.$f) {
|
---|
917 | this.state.peek = chars.$FF;
|
---|
918 | }
|
---|
919 | // Now consider more complex sequences
|
---|
920 | else if (peek() === chars.$u) {
|
---|
921 | // Unicode code-point sequence
|
---|
922 | this.advanceState(this.internalState); // advance past the `u` char
|
---|
923 | if (peek() === chars.$LBRACE) {
|
---|
924 | // Variable length Unicode, e.g. `\x{123}`
|
---|
925 | this.advanceState(this.internalState); // advance past the `{` char
|
---|
926 | // Advance past the variable number of hex digits until we hit a `}` char
|
---|
927 | const digitStart = this.clone();
|
---|
928 | let length = 0;
|
---|
929 | while (peek() !== chars.$RBRACE) {
|
---|
930 | this.advanceState(this.internalState);
|
---|
931 | length++;
|
---|
932 | }
|
---|
933 | this.state.peek = this.decodeHexDigits(digitStart, length);
|
---|
934 | }
|
---|
935 | else {
|
---|
936 | // Fixed length Unicode, e.g. `\u1234`
|
---|
937 | const digitStart = this.clone();
|
---|
938 | this.advanceState(this.internalState);
|
---|
939 | this.advanceState(this.internalState);
|
---|
940 | this.advanceState(this.internalState);
|
---|
941 | this.state.peek = this.decodeHexDigits(digitStart, 4);
|
---|
942 | }
|
---|
943 | }
|
---|
944 | else if (peek() === chars.$x) {
|
---|
945 | // Hex char code, e.g. `\x2F`
|
---|
946 | this.advanceState(this.internalState); // advance past the `x` char
|
---|
947 | const digitStart = this.clone();
|
---|
948 | this.advanceState(this.internalState);
|
---|
949 | this.state.peek = this.decodeHexDigits(digitStart, 2);
|
---|
950 | }
|
---|
951 | else if (chars.isOctalDigit(peek())) {
|
---|
952 | // Octal char code, e.g. `\012`,
|
---|
953 | let octal = '';
|
---|
954 | let length = 0;
|
---|
955 | let previous = this.clone();
|
---|
956 | while (chars.isOctalDigit(peek()) && length < 3) {
|
---|
957 | previous = this.clone();
|
---|
958 | octal += String.fromCodePoint(peek());
|
---|
959 | this.advanceState(this.internalState);
|
---|
960 | length++;
|
---|
961 | }
|
---|
962 | this.state.peek = parseInt(octal, 8);
|
---|
963 | // Backup one char
|
---|
964 | this.internalState = previous.internalState;
|
---|
965 | }
|
---|
966 | else if (chars.isNewLine(this.internalState.peek)) {
|
---|
967 | // Line continuation `\` followed by a new line
|
---|
968 | this.advanceState(this.internalState); // advance over the newline
|
---|
969 | this.state = this.internalState;
|
---|
970 | }
|
---|
971 | else {
|
---|
972 | // If none of the `if` blocks were executed then we just have an escaped normal character.
|
---|
973 | // In that case we just, effectively, skip the backslash from the character.
|
---|
974 | this.state.peek = this.internalState.peek;
|
---|
975 | }
|
---|
976 | }
|
---|
977 | }
|
---|
978 | decodeHexDigits(start, length) {
|
---|
979 | const hex = this.input.substr(start.internalState.offset, length);
|
---|
980 | const charCode = parseInt(hex, 16);
|
---|
981 | if (!isNaN(charCode)) {
|
---|
982 | return charCode;
|
---|
983 | }
|
---|
984 | else {
|
---|
985 | start.state = start.internalState;
|
---|
986 | throw new CursorError('Invalid hexadecimal escape sequence', start);
|
---|
987 | }
|
---|
988 | }
|
---|
989 | }
|
---|
990 | export class CursorError {
|
---|
991 | constructor(msg, cursor) {
|
---|
992 | this.msg = msg;
|
---|
993 | this.cursor = cursor;
|
---|
994 | }
|
---|
995 | }
|
---|
996 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGV4ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvbWxfcGFyc2VyL2xleGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sS0FBSyxLQUFLLE1BQU0sVUFBVSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxVQUFVLEVBQUUsYUFBYSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLFlBQVksQ0FBQztBQUUxQyxPQUFPLEVBQUMsNEJBQTRCLEVBQXNCLE1BQU0sd0JBQXdCLENBQUM7QUFDekYsT0FBTyxFQUFDLGNBQWMsRUFBZ0IsTUFBTSxRQUFRLENBQUM7QUFHckQsTUFBTSxPQUFPLFVBQVcsU0FBUSxVQUFVO0lBQ3hDLFlBQVksUUFBZ0IsRUFBUyxTQUF5QixFQUFFLElBQXFCO1FBQ25GLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFEYSxjQUFTLEdBQVQsU0FBUyxDQUFnQjtJQUU5RCxDQUFDO0NBQ0Y7QUFFRCxNQUFNLE9BQU8sY0FBYztJQUN6QixZQUNXLE1BQWUsRUFBUyxNQUFvQixFQUM1QywyQkFBb0M7UUFEcEMsV0FBTSxHQUFOLE1BQU0sQ0FBUztRQUFTLFdBQU0sR0FBTixNQUFNLENBQWM7UUFDNUMsZ0NBQTJCLEdBQTNCLDJCQUEyQixDQUFTO0lBQUcsQ0FBQztDQUNwRDtBQW1FRCxNQUFNLFVBQVUsUUFBUSxDQUNwQixNQUFjLEVBQUUsR0FBVyxFQUFFLGdCQUFvRCxFQUNqRixVQUEyQixFQUFFO0lBQy9CLE1BQU0sU0FBUyxHQUFHLElBQUksVUFBVSxDQUFDLElBQUksZUFBZSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5RixTQUFTLENBQUMsUUFB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TUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDbEUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ3BCLE9BQU8sUUFBUSxDQUFDO1NBQ2pCO2FBQU07WUFDTCxLQUFLLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7WUFDbEMsTUFBTSxJQUFJLFdBQVcsQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNyRTtJQUNILENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyxXQUFXO0lBQ3RCLFlBQW1CLEdBQVcsRUFBUyxNQUF1QjtRQUEzQyxRQUFHLEdBQUgsR0FBRyxDQUFRO1FBQVMsV0FBTSxHQUFOLE1BQU0sQ0FBaUI7SUFBRyxDQUFDO0NBQ25FIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCAqIGFzIGNoYXJzIGZyb20gJy4uL2NoYXJzJztcbmltcG9ydCB7UGFyc2VFcnJvciwgUGFyc2VMb2NhdGlvbiwgUGFyc2VTb3VyY2VGaWxlLCBQYXJzZVNvdXJjZVNwYW59IGZyb20gJy4uL3BhcnNlX3V0aWwnO1xuaW1wb3J0IHtOQU1FRF9FTlRJVElFU30gZnJvbSAnLi9lbnRpdGllcyc7XG5cbmltcG9ydCB7REVGQVVMVF9JTlRFUlBPTEFUSU9OX0NPTkZJRywgSW50ZXJwb2xhdGlvbkNvbmZpZ30gZnJvbSAnLi9pbnRlcnBvbGF0aW9uX2NvbmZpZyc7XG5pbXBvcnQge1RhZ0NvbnRlbnRUeXBlLCBUYWdEZWZpbml0aW9ufSBmcm9tICcuL3RhZ3MnO1xuaW1wb3J0IHtJbmNvbXBsZXRlVGFnT3BlblRva2VuLCBUYWdPcGVuU3RhcnRUb2tlbiwgVG9rZW4sIFRva2VuVHlwZX0gZnJvbSAnLi90b2tlbnMnO1xuXG5leHBvcnQgY2xhc3MgVG9rZW5FcnJvciBleHRlbmRzIFBhcnNlRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihlcnJvck1zZzogc3RyaW5nLCBwdWJsaWMgdG9rZW5UeXBlOiBUb2tlblR5cGV8bnVsbCwgc3BhbjogUGFyc2VTb3VyY2VTcGFuKSB7XG4gICAgc3VwZXIoc3BhbiwgZXJyb3JNc2cpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUb2tlbml6ZVJlc3VsdCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIHRva2VuczogVG9rZW5bXSwgcHVibGljIGVycm9yczogVG9rZW5FcnJvcltdLFxuICAgICAgcHVibGljIG5vbk5vcm1hbGl6ZWRJY3VFeHByZXNzaW9uczogVG9rZW5bXSkge31cbn1cblxuZXhwb3J0IGludGVyZmFjZSBMZXhlclJhbmdlIHtcbiAgc3RhcnRQb3M6IG51bWJlcjtcbiAgc3RhcnRMaW5lOiBudW1iZXI7XG4gIHN0YXJ0Q29sOiBudW1iZXI7XG4gIGVuZFBvczogbnVtYmVyO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgdGhhdCBtb2RpZnkgaG93IHRoZSB0ZXh0IGlzIHRva2VuaXplZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUb2tlbml6ZU9wdGlvbnMge1xuICAvKiogV2hldGhlciB0byB0b2tlbml6ZSBJQ1UgbWVzc2FnZXMgKGNvbnNpZGVyZWQgYXMgdGV4dCBub2RlcyB3aGVuIGZhbHNlKS4gKi9cbiAgdG9rZW5pemVFeHBhbnNpb25Gb3Jtcz86IGJvb2xlYW47XG4gIC8qKiBIb3cgdG8gdG9rZW5pemUgaW50ZXJwb2xhdGlvbiBtYXJrZXJzLiAqL1xuICBpbnRlcnBvbGF0aW9uQ29uZmlnPzogSW50ZXJwb2xhdGlvbkNvbmZpZztcbiAgLyoqXG4gICAqIFRoZSBzdGFydCBhbmQgZW5kIHBvaW50IG9mIHRoZSB0ZXh0IHRvIHBhcnNlIHdpdGhpbiB0aGUgYHNvdXJjZWAgc3RyaW5nLlxuICAgKiBUaGUgZW50aXJlIGBzb3VyY2VgIHN0cmluZyBpcyBwYXJzZWQgaWYgdGhpcyBpcyBub3QgcHJvdmlkZWQuXG4gICAqICovXG4gIHJhbmdlPzogTGV4ZXJSYW5nZTtcbiAgLyoqXG4gICAqIElmIHRoaXMgdGV4dCBpcyBzdG9yZWQgaW4gYSBKYXZhU2NyaXB0IHN0cmluZywgdGhlbiB3ZSBoYXZlIHRvIGRlYWwgd2l0aCBlc2NhcGUgc2VxdWVuY2VzLlxuICAgKlxuICAgKiAqKkV4YW1wbGUgMToqKlxuICAgKlxuICAgKiBgYGBcbiAgICogXCJhYmNcXFwiZGVmXFxuZ2hpXCJcbiAgICogYGBgXG4gICAqXG4gICAqIC0gVGhlIGBcXFwiYCBtdXN0IGJlIGNvbnZlcnRlZCB0byBgXCJgLlxuICAgKiAtIFRoZSBgXFxuYCBtdXN0IGJlIGNvbnZlcnRlZCB0byBhIG5ldyBsaW5lIGNoYXJhY3RlciBpbiBhIHRva2VuLFxuICAgKiAgIGJ1dCBpdCBzaG91bGQgbm90IGluY3JlbWVudCB0aGUgY3VycmVudCBsaW5lIGZvciBzb3VyY2UgbWFwcGluZy5cbiAgICpcbiAgICogKipFeGFtcGxlIDI6KipcbiAgICpcbiAgICogYGBgXG4gICAqIFwiYWJjXFxcbiAgICogIGRlZlwiXG4gICAqIGBgYFxuICAgKlxuICAgKiBUaGUgbGluZSBjb250aW51YXRpb24gKGBcXGAgZm9sbG93ZWQgYnkgYSBuZXdsaW5lKSBzaG91bGQgYmUgcmVtb3ZlZCBmcm9tIGEgdG9rZW5cbiAgICogYnV0IHRoZSBuZXcgbGluZSBzaG91bGQgaW5jcmVtZW50IHRoZSBjdXJyZW50IGxpbmUgZm9yIHNvdXJjZSBtYXBwaW5nLlxuICAgKi9cbiAgZXNjYXBlZFN0cmluZz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZiB0aGlzIHRleHQgaXMgc3RvcmVkIGluIGFuIGV4dGVybmFsIHRlbXBsYXRlIChlLmcuIHZpYSBgdGVtcGxhdGVVcmxgKSB0aGVuIHdlIG5lZWQgdG8gZGVjaWRlXG4gICAqIHdoZXRoZXIgb3Igbm90IHRvIG5vcm1hbGl6ZSB0aGUgbGluZS1lbmRpbmdzIChmcm9tIGBcXHJcXG5gIHRvIGBcXG5gKSB3aGVuIHByb2Nlc3NpbmcgSUNVXG4gICAqIGV4cHJlc3Npb25zLlxuICAgKlxuICAgKiBJZiBgdHJ1ZWAgdGhlbiB3ZSB3aWxsIG5vcm1hbGl6ZSBJQ1UgZXhwcmVzc2lvbiBsaW5lIGVuZGluZ3MuXG4gICAqIFRoZSBkZWZhdWx0IGlzIGBmYWxzZWAsIGJ1dCB0aGlzIHdpbGwgYmUgc3dpdGNoZWQgaW4gYSBmdXR1cmUgbWFqb3IgcmVsZWFzZS5cbiAgICovXG4gIGkxOG5Ob3JtYWxpemVMaW5lRW5kaW5nc0luSUNVcz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiBjaGFyYWN0ZXJzIHRoYXQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYXMgbGVhZGluZyB0cml2aWEuXG4gICAqIExlYWRpbmcgdHJpdmlhIGFyZSBjaGFyYWN0ZXJzIHRoYXQgYXJlIG5vdCBpbXBvcnRhbnQgdG8gdGhlIGRldmVsb3BlciwgYW5kIHNvIHNob3VsZCBub3QgYmVcbiAgICogaW5jbHVkZWQgaW4gc291cmNlLW1hcCBzZWdtZW50cy4gIEEgY29tbW9uIGV4YW1wbGUgaXMgd2hpdGVzcGFjZS5cbiAgICovXG4gIGxlYWRpbmdUcml2aWFDaGFycz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogSWYgdHJ1ZSwgZG8gbm90IGNvbnZlcnQgQ1JMRiB0byBMRi5cbiAgICovXG4gIHByZXNlcnZlTGluZUVuZGluZ3M/OiBib29sZWFuO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9rZW5pemUoXG4gICAgc291cmNlOiBzdHJpbmcsIHVybDogc3RyaW5nLCBnZXRUYWdEZWZpbml0aW9uOiAodGFnTmFtZTogc3RyaW5nKSA9PiBUYWdEZWZpbml0aW9uLFxuICAgIG9wdGlvbnM6IFRva2VuaXplT3B0aW9ucyA9IHt9KTogVG9rZW5pemVSZXN1bHQge1xuICBjb25zdCB0b2tlbml6ZXIgPSBuZXcgX1Rva2VuaXplcihuZXcgUGFyc2VTb3VyY2VGaWxlKHNvdXJjZSwgdXJsKSwgZ2V0VGFnRGVmaW5pdGlvbiwgb3B0aW9ucyk7XG4gIHRva2VuaXplci50b2tlbml6ZSgpO1xuICByZXR1cm4gbmV3IFRva2VuaXplUmVzdWx0KFxuICAgICAgbWVyZ2VUZXh0VG9rZW5zKHRva2VuaXplci50b2tlbnMpLCB0b2tlbml6ZXIuZXJyb3JzLCB0b2tlbml6ZXIubm9uTm9ybWFsaXplZEljdUV4cHJlc3Npb25zKTtcbn1cblxuY29uc3QgX0NSX09SX0NSTEZfUkVHRVhQID0gL1xcclxcbj8vZztcblxuZnVuY3Rpb24gX3VuZXhwZWN0ZWRDaGFyYWN0ZXJFcnJvck1zZyhjaGFyQ29kZTogbnVtYmVyKTogc3RyaW5nIHtcbiAgY29uc3QgY2hhciA9IGNoYXJDb2RlID09PSBjaGFycy4kRU9GID8gJ0VPRicgOiBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXJDb2RlKTtcbiAgcmV0dXJuIGBVbmV4cGVjdGVkIGNoYXJhY3RlciBcIiR7Y2hhcn1cImA7XG59XG5cbmZ1bmN0aW9uIF91bmtub3duRW50aXR5RXJyb3JNc2coZW50aXR5U3JjOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYFVua25vd24gZW50aXR5IFwiJHtlbnRpdHlTcmN9XCIgLSB1c2UgdGhlIFwiJiM8ZGVjaW1hbD47XCIgb3IgIFwiJiN4PGhleD47XCIgc3ludGF4YDtcbn1cblxuZnVuY3Rpb24gX3VucGFyc2FibGVFbnRpdHlFcnJvck1zZyh0eXBlOiBDaGFyYWN0ZXJSZWZlcmVuY2VUeXBlLCBlbnRpdHlTdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgVW5hYmxlIHRvIHBhcnNlIGVudGl0eSBcIiR7ZW50aXR5U3RyfVwiIC0gJHtcbiAgICAgIHR5cGV9IGNoYXJhY3RlciByZWZlcmVuY2UgZW50aXRpZXMgbXVzdCBlbmQgd2l0aCBcIjtcImA7XG59XG5cbmVudW0gQ2hhcmFjdGVyUmVmZXJlbmNlVHlwZSB7XG4gIEhFWCA9ICdoZXhhZGVjaW1hbCcsXG4gIERFQyA9ICdkZWNpbWFsJyxcbn1cblxuY2xhc3MgX0NvbnRyb2xGbG93RXJyb3Ige1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgZXJyb3I6IFRva2VuRXJyb3IpIHt9XG59XG5cbi8vIFNlZSBodHRwczovL3d3dy53My5vcmcvVFIvaHRtbDUxL3N5bnRheC5odG1sI3dyaXRpbmctaHRtbC1kb2N1bWVudHNcbmNsYXNzIF9Ub2tlbml6ZXIge1xuICBwcml2YXRlIF9jdXJzb3I6IENoYXJhY3RlckN1cnNvcjtcbiAgcHJpdmF0ZSBfdG9rZW5pemVJY3U6IGJvb2xlYW47XG4gIHByaXZhdGUgX2ludGVycG9sYXRpb25Db25maWc6IEludGVycG9sYXRpb25Db25maWc7XG4gIHByaXZhdGUgX2xlYWRpbmdUcml2aWFDb2RlUG9pbnRzOiBudW1iZXJbXXx1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2N1cnJlbnRUb2tlblN0YXJ0OiBDaGFyYWN0ZXJDdXJzb3J8bnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX2N1cnJlbnRUb2tlblR5cGU6IFRva2VuVHlwZXxudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfZXhwYW5zaW9uQ2FzZVN0YWNrOiBUb2tlblR5cGVbXSA9IFtdO1xuICBwcml2YXRlIF9pbkludGVycG9sYXRpb246IGJvb2xlYW4gPSBmYWxzZTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcHJlc2VydmVMaW5lRW5kaW5nczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBfZXNjYXBlZFN0cmluZzogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBfaTE4bk5vcm1hbGl6ZUxpbmVFbmRpbmdzSW5JQ1VzOiBib29sZWFuO1xuICB0b2tlbnM6IFRva2VuW10gPSBbXTtcbiAgZXJyb3JzOiBUb2tlbkVycm9yW10gPSBbXTtcbiAgbm9uTm9ybWFsaXplZEljdUV4cHJlc3Npb25zOiBUb2tlbltdID0gW107XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBfZmlsZSBUaGUgaHRtbCBzb3VyY2UgZmlsZSBiZWluZyB0b2tlbml6ZWQuXG4gICAqIEBwYXJhbSBfZ2V0VGFnRGVmaW5pdGlvbiBBIGZ1bmN0aW9uIHRoYXQgd2lsbCByZXRyaWV2ZSBhIHRhZyBkZWZpbml0aW9uIGZvciBhIGdpdmVuIHRhZyBuYW1lLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBDb25maWd1cmF0aW9uIG9mIHRoZSB0b2tlbml6YXRpb24uXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIF9maWxlOiBQYXJzZVNvdXJjZUZpbGUsIHByaXZhdGUgX2dldFRhZ0RlZmluaXRpb246ICh0YWdOYW1lOiBzdHJpbmcpID0+IFRhZ0RlZmluaXRpb24sXG4gICAgICBvcHRpb25zOiBUb2tlbml6ZU9wdGlvbnMpIHtcbiAgICB0aGlzLl90b2tlbml6ZUljdSA9IG9wdGlvbnMudG9rZW5pemVFeHBhbnNpb25Gb3JtcyB8fCBmYWxzZTtcbiAgICB0aGlzLl9pbnRlcnBvbGF0aW9uQ29uZmlnID0gb3B0aW9ucy5pbnRlcnBvbGF0aW9uQ29uZmlnIHx8IERFRkFVTFRfSU5URVJQT0xBVElPTl9DT05GSUc7XG4gICAgdGhpcy5fbGVhZGluZ1RyaXZpYUNvZGVQb2ludHMgPVxuICAgICAgICBvcHRpb25zLmxlYWRpbmdUcml2aWFDaGFycyAmJiBvcHRpb25zLmxlYWRpbmdUcml2aWFDaGFycy5tYXAoYyA9PiBjLmNvZGVQb2ludEF0KDApIHx8IDApO1xuICAgIGNvbnN0IHJhbmdlID1cbiAgICAgICAgb3B0aW9ucy5yYW5nZSB8fCB7ZW5kUG9zOiBfZmlsZS5jb250ZW50Lmxlbmd0aCwgc3RhcnRQb3M6IDAsIHN0YXJ0TGluZTogMCwgc3RhcnRDb2w6IDB9O1xuICAgIHRoaXMuX2N1cnNvciA9IG9wdGlvbnMuZXNjYXBlZFN0cmluZyA/IG5ldyBFc2NhcGVkQ2hhcmFjdGVyQ3Vyc29yKF9maWxlLCByYW5nZSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQbGFpbkNoYXJhY3RlckN1cnNvcihfZmlsZSwgcmFuZ2UpO1xuICAgIHRoaXMuX3ByZXNlcnZlTGluZUVuZGluZ3MgPSBvcHRpb25zLnByZXNlcnZlTGluZUVuZGluZ3MgfHwgZmFsc2U7XG4gICAgdGhpcy5fZXNjYXBlZFN0cmluZyA9IG9wdGlvbnMuZXNjYXBlZFN0cmluZyB8fCBmYWxzZTtcbiAgICB0aGlzLl9pMThuTm9ybWFsaXplTGluZUVuZGluZ3NJbklDVXMgPSBvcHRpb25zLmkxOG5Ob3JtYWxpemVMaW5lRW5kaW5nc0luSUNVcyB8fCBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5fY3Vyc29yLmluaXQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmhhbmRsZUVycm9yKGUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3Byb2Nlc3NDYXJyaWFnZVJldHVybnMoY29udGVudDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5fcHJlc2VydmVMaW5lRW5kaW5ncykge1xuICAgICAgcmV0dXJuIGNvbnRlbnQ7XG4gICAgfVxuICAgIC8vIGh0dHBzOi8vd3d3LnczLm9yZy9UUi9odG1sNTEvc3ludGF4Lmh0bWwjcHJlcHJvY2Vzc2luZy10aGUtaW5wdXQtc3RyZWFtXG4gICAgLy8gSW4gb3JkZXIgdG8ga2VlcCB0aGUgb3JpZ2luYWwgcG9zaXRpb24gaW4gdGhlIHNvdXJjZSwgd2UgY2FuIG5vdFxuICAgIC8vIHByZS1wcm9jZXNzIGl0LlxuICAgIC8vIEluc3RlYWQgQ1JzIGFyZSBwcm9jZXNzZWQgcmlnaHQgYmVmb3JlIGluc3RhbnRpYXRpbmcgdGhlIHRva2Vucy5cbiAgICByZXR1cm4gY29udGVudC5yZXBsYWNlKF9DUl9PUl9DUkxGX1JFR0VYUCwgJ1xcbicpO1xuICB9XG5cbiAgdG9rZW5pemUoKTogdm9pZCB7XG4gICAgd2hpbGUgKHRoaXMuX2N1cnNvci5wZWVrKCkgIT09IGNoYXJzLiRFT0YpIHtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAodGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJzLiRMVCkpIHtcbiAgICAgICAgICBpZiAodGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJzLiRCQU5HKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy4kTEJSQUNLRVQpKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2NvbnN1bWVDZGF0YShzdGFydCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy4kTUlOVVMpKSB7XG4gICAgICAgICAgICAgIHRoaXMuX2NvbnN1bWVDb21tZW50KHN0YXJ0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuX2NvbnN1bWVEb2NUeXBlKHN0YXJ0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy4kU0xBU0gpKSB7XG4gICAgICAgICAgICB0aGlzLl9jb25zdW1lVGFnQ2xvc2Uoc3RhcnQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9jb25zdW1lVGFnT3BlbihzdGFydCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEodGhpcy5fdG9rZW5pemVJY3UgJiYgdGhpcy5fdG9rZW5pemVFeHBhbnNpb25Gb3JtKCkpKSB7XG4gICAgICAgICAgLy8gSW4gKHBvc3NpYmx5IGludGVycG9sYXRlZCkgdGV4dCB0aGUgZW5kIG9mIHRoZSB0ZXh0IGlzIGdpdmVuIGJ5IGBpc1RleHRFbmQoKWAsIHdoaWxlXG4gICAgICAgICAgLy8gdGhlIHByZW1hdHVyZSBlbmQgb2YgYW4gaW50ZXJwb2xhdGlvbiBpcyBnaXZlbiBieSB0aGUgc3RhcnQgb2YgYSBuZXcgSFRNTCBlbGVtZW50LlxuICAgICAgICAgIHRoaXMuX2NvbnN1bWVXaXRoSW50ZXJwb2xhdGlvbihcbiAgICAgICAgICAgICAgVG9rZW5UeXBlLlRFWFQsIFRva2VuVHlwZS5JTlRFUlBPTEFUSU9OLCAoKSA9PiB0aGlzLl9pc1RleHRFbmQoKSxcbiAgICAgICAgICAgICAgKCkgPT4gdGhpcy5faXNUYWdTdGFydCgpKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLmhhbmRsZUVycm9yKGUpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5FT0YpO1xuICAgIHRoaXMuX2VuZFRva2VuKFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB3aGV0aGVyIGFuIElDVSB0b2tlbiBoYXMgYmVlbiBjcmVhdGVkXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBfdG9rZW5pemVFeHBhbnNpb25Gb3JtKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlzRXhwYW5zaW9uRm9ybVN0YXJ0KCkpIHtcbiAgICAgIHRoaXMuX2NvbnN1bWVFeHBhbnNpb25Gb3JtU3RhcnQoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChpc0V4cGFuc2lvbkNhc2VTdGFydCh0aGlzLl9jdXJzb3IucGVlaygpKSAmJiB0aGlzLl9pc0luRXhwYW5zaW9uRm9ybSgpKSB7XG4gICAgICB0aGlzLl9jb25zdW1lRXhwYW5zaW9uQ2FzZVN0YXJ0KCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gY2hhcnMuJFJCUkFDRSkge1xuICAgICAgaWYgKHRoaXMuX2lzSW5FeHBhbnNpb25DYXNlKCkpIHtcbiAgICAgICAgdGhpcy5fY29uc3VtZUV4cGFuc2lvbkNhc2VFbmQoKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9pc0luRXhwYW5zaW9uRm9ybSgpKSB7XG4gICAgICAgIHRoaXMuX2NvbnN1bWVFeHBhbnNpb25Gb3JtRW5kKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgX2JlZ2luVG9rZW4odHlwZTogVG9rZW5UeXBlLCBzdGFydCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpKSB7XG4gICAgdGhpcy5fY3VycmVudFRva2VuU3RhcnQgPSBzdGFydDtcbiAgICB0aGlzLl9jdXJyZW50VG9rZW5UeXBlID0gdHlwZTtcbiAgfVxuXG4gIHByaXZhdGUgX2VuZFRva2VuKHBhcnRzOiBzdHJpbmdbXSwgZW5kPzogQ2hhcmFjdGVyQ3Vyc29yKTogVG9rZW4ge1xuICAgIGlmICh0aGlzLl9jdXJyZW50VG9rZW5TdGFydCA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IFRva2VuRXJyb3IoXG4gICAgICAgICAgJ1Byb2dyYW1taW5nIGVycm9yIC0gYXR0ZW1wdGVkIHRvIGVuZCBhIHRva2VuIHdoZW4gdGhlcmUgd2FzIG5vIHN0YXJ0IHRvIHRoZSB0b2tlbicsXG4gICAgICAgICAgdGhpcy5fY3VycmVudFRva2VuVHlwZSwgdGhpcy5fY3Vyc29yLmdldFNwYW4oZW5kKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jdXJyZW50VG9rZW5UeXBlID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgVG9rZW5FcnJvcihcbiAgICAgICAgICAnUHJvZ3JhbW1pbmcgZXJyb3IgLSBhdHRlbXB0ZWQgdG8gZW5kIGEgdG9rZW4gd2hpY2ggaGFzIG5vIHRva2VuIHR5cGUnLCBudWxsLFxuICAgICAgICAgIHRoaXMuX2N1cnNvci5nZXRTcGFuKHRoaXMuX2N1cnJlbnRUb2tlblN0YXJ0KSk7XG4gICAgfVxuICAgIGNvbnN0IHRva2VuID0ge1xuICAgICAgdHlwZTogdGhpcy5fY3VycmVudFRva2VuVHlwZSxcbiAgICAgIHBhcnRzLFxuICAgICAgc291cmNlU3BhbjpcbiAgICAgICAgICAoZW5kID8/IHRoaXMuX2N1cnNvcikuZ2V0U3Bhbih0aGlzLl9jdXJyZW50VG9rZW5TdGFydCwgdGhpcy5fbGVhZGluZ1RyaXZpYUNvZGVQb2ludHMpLFxuICAgIH0gYXMgVG9rZW47XG4gICAgdGhpcy50b2tlbnMucHVzaCh0b2tlbik7XG4gICAgdGhpcy5fY3VycmVudFRva2VuU3RhcnQgPSBudWxsO1xuICAgIHRoaXMuX2N1cnJlbnRUb2tlblR5cGUgPSBudWxsO1xuICAgIHJldHVybiB0b2tlbjtcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZUVycm9yKG1zZzogc3RyaW5nLCBzcGFuOiBQYXJzZVNvdXJjZVNwYW4pOiBfQ29udHJvbEZsb3dFcnJvciB7XG4gICAgaWYgKHRoaXMuX2lzSW5FeHBhbnNpb25Gb3JtKCkpIHtcbiAgICAgIG1zZyArPSBgIChEbyB5b3UgaGF2ZSBhbiB1bmVzY2FwZWQgXCJ7XCIgaW4geW91ciB0ZW1wbGF0ZT8gVXNlIFwie3sgJ3snIH19XCIpIHRvIGVzY2FwZSBpdC4pYDtcbiAgICB9XG4gICAgY29uc3QgZXJyb3IgPSBuZXcgVG9rZW5FcnJvcihtc2csIHRoaXMuX2N1cnJlbnRUb2tlblR5cGUsIHNwYW4pO1xuICAgIHRoaXMuX2N1cnJlbnRUb2tlblN0YXJ0ID0gbnVsbDtcbiAgICB0aGlzLl9jdXJyZW50VG9rZW5UeXBlID0gbnVsbDtcbiAgICByZXR1cm4gbmV3IF9Db250cm9sRmxvd0Vycm9yKGVycm9yKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlRXJyb3IoZTogYW55KSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBDdXJzb3JFcnJvcikge1xuICAgICAgZSA9IHRoaXMuX2NyZWF0ZUVycm9yKGUubXNnLCB0aGlzLl9jdXJzb3IuZ2V0U3BhbihlLmN1cnNvcikpO1xuICAgIH1cbiAgICBpZiAoZSBpbnN0YW5jZW9mIF9Db250cm9sRmxvd0Vycm9yKSB7XG4gICAgICB0aGlzLmVycm9ycy5wdXNoKGUuZXJyb3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2F0dGVtcHRDaGFyQ29kZShjaGFyQ29kZTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuX2N1cnNvci5wZWVrKCkgPT09IGNoYXJDb2RlKSB7XG4gICAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgX2F0dGVtcHRDaGFyQ29kZUNhc2VJbnNlbnNpdGl2ZShjaGFyQ29kZTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKGNvbXBhcmVDaGFyQ29kZUNhc2VJbnNlbnNpdGl2ZSh0aGlzLl9jdXJzb3IucGVlaygpLCBjaGFyQ29kZSkpIHtcbiAgICAgIHRoaXMuX2N1cnNvci5hZHZhbmNlKCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVxdWlyZUNoYXJDb2RlKGNoYXJDb2RlOiBudW1iZXIpIHtcbiAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgIGlmICghdGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJDb2RlKSkge1xuICAgICAgdGhyb3cgdGhpcy5fY3JlYXRlRXJyb3IoXG4gICAgICAgICAgX3VuZXhwZWN0ZWRDaGFyYWN0ZXJFcnJvck1zZyh0aGlzLl9jdXJzb3IucGVlaygpKSwgdGhpcy5fY3Vyc29yLmdldFNwYW4obG9jYXRpb24pKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9hdHRlbXB0U3RyKGNoYXJzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBsZW4gPSBjaGFycy5sZW5ndGg7XG4gICAgaWYgKHRoaXMuX2N1cnNvci5jaGFyc0xlZnQoKSA8IGxlbikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBpbml0aWFsUG9zaXRpb24gPSB0aGlzLl9jdXJzb3IuY2xvbmUoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpZiAoIXRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy5jaGFyQ29kZUF0KGkpKSkge1xuICAgICAgICAvLyBJZiBhdHRlbXB0aW5nIHRvIHBhcnNlIHRoZSBzdHJpbmcgZmFpbHMsIHdlIHdhbnQgdG8gcmVzZXQgdGhlIHBhcnNlclxuICAgICAgICAvLyB0byB3aGVyZSBpdCB3YXMgYmVmb3JlIHRoZSBhdHRlbXB0XG4gICAgICAgIHRoaXMuX2N1cnNvciA9IGluaXRpYWxQb3NpdGlvbjtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2F0dGVtcHRTdHJDYXNlSW5zZW5zaXRpdmUoY2hhcnM6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghdGhpcy5fYXR0ZW1wdENoYXJDb2RlQ2FzZUluc2Vuc2l0aXZlKGNoYXJzLmNoYXJDb2RlQXQoaSkpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIF9yZXF1aXJlU3RyKGNoYXJzOiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgIGlmICghdGhpcy5fYXR0ZW1wdFN0cihjaGFycykpIHtcbiAgICAgIHRocm93IHRoaXMuX2NyZWF0ZUVycm9yKFxuICAgICAgICAgIF91bmV4cGVjdGVkQ2hhcmFjdGVyRXJyb3JNc2codGhpcy5fY3Vyc29yLnBlZWsoKSksIHRoaXMuX2N1cnNvci5nZXRTcGFuKGxvY2F0aW9uKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYXR0ZW1wdENoYXJDb2RlVW50aWxGbihwcmVkaWNhdGU6IChjb2RlOiBudW1iZXIpID0+IGJvb2xlYW4pIHtcbiAgICB3aGlsZSAoIXByZWRpY2F0ZSh0aGlzLl9jdXJzb3IucGVlaygpKSkge1xuICAgICAgdGhpcy5fY3Vyc29yLmFkdmFuY2UoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9yZXF1aXJlQ2hhckNvZGVVbnRpbEZuKHByZWRpY2F0ZTogKGNvZGU6IG51bWJlcikgPT4gYm9vbGVhbiwgbGVuOiBudW1iZXIpIHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4ocHJlZGljYXRlKTtcbiAgICBpZiAodGhpcy5fY3Vyc29yLmRpZmYoc3RhcnQpIDwgbGVuKSB7XG4gICAgICB0aHJvdyB0aGlzLl9jcmVhdGVFcnJvcihcbiAgICAgICAgICBfdW5leHBlY3RlZENoYXJhY3RlckVycm9yTXNnKHRoaXMuX2N1cnNvci5wZWVrKCkpLCB0aGlzLl9jdXJzb3IuZ2V0U3BhbihzdGFydCkpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2F0dGVtcHRVbnRpbENoYXIoY2hhcjogbnVtYmVyKSB7XG4gICAgd2hpbGUgKHRoaXMuX2N1cnNvci5wZWVrKCkgIT09IGNoYXIpIHtcbiAgICAgIHRoaXMuX2N1cnNvci5hZHZhbmNlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfcmVhZENoYXIoKTogc3RyaW5nIHtcbiAgICAvLyBEb24ndCByZWx5IHVwb24gcmVhZGluZyBkaXJlY3RseSBmcm9tIGBfaW5wdXRgIGFzIHRoZSBhY3R1YWwgY2hhciB2YWx1ZVxuICAgIC8vIG1heSBoYXZlIGJlZW4gZ2VuZXJhdGVkIGZyb20gYW4gZXNjYXBlIHNlcXVlbmNlLlxuICAgIGNvbnN0IGNoYXIgPSBTdHJpbmcuZnJvbUNvZGVQb2ludCh0aGlzLl9jdXJzb3IucGVlaygpKTtcbiAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgIHJldHVybiBjaGFyO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZUVudGl0eSh0ZXh0VG9rZW5UeXBlOiBUb2tlblR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5FTkNPREVEX0VOVElUWSk7XG4gICAgY29uc3Qgc3RhcnQgPSB0aGlzLl9jdXJzb3IuY2xvbmUoKTtcbiAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgIGlmICh0aGlzLl9hdHRlbXB0Q2hhckNvZGUoY2hhcnMuJEhBU0gpKSB7XG4gICAgICBjb25zdCBpc0hleCA9IHRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy4keCkgfHwgdGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJzLiRYKTtcbiAgICAgIGNvbnN0IGNvZGVTdGFydCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlVW50aWxGbihpc0RpZ2l0RW50aXR5RW5kKTtcbiAgICAgIGlmICh0aGlzLl9jdXJzb3IucGVlaygpICE9IGNoYXJzLiRTRU1JQ09MT04pIHtcbiAgICAgICAgLy8gQWR2YW5jZSBjdXJzb3IgdG8gaW5jbHVkZSB0aGUgcGVla2VkIGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nIHByb3ZpZGVkIHRvIHRoZSBlcnJvclxuICAgICAgICAvLyBtZXNzYWdlLlxuICAgICAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgICAgICBjb25zdCBlbnRpdHlUeXBlID0gaXNIZXggPyBDaGFyYWN0ZXJSZWZlcmVuY2VUeXBlLkhFWCA6IENoYXJhY3RlclJlZmVyZW5jZVR5cGUuREVDO1xuICAgICAgICB0aHJvdyB0aGlzLl9jcmVhdGVFcnJvcihcbiAgICAgICAgICAgIF91bnBhcnNhYmxlRW50aXR5RXJyb3JNc2coZW50aXR5VHlwZSwgdGhpcy5fY3Vyc29yLmdldENoYXJzKHN0YXJ0KSksXG4gICAgICAgICAgICB0aGlzLl9jdXJzb3IuZ2V0U3BhbigpKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN0ck51bSA9IHRoaXMuX2N1cnNvci5nZXRDaGFycyhjb2RlU3RhcnQpO1xuICAgICAgdGhpcy5fY3Vyc29yLmFkdmFuY2UoKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGNoYXJDb2RlID0gcGFyc2VJbnQoc3RyTnVtLCBpc0hleCA/IDE2IDogMTApO1xuICAgICAgICB0aGlzLl9lbmRUb2tlbihbU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSksIHRoaXMuX2N1cnNvci5nZXRDaGFycyhzdGFydCldKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICB0aHJvdyB0aGlzLl9jcmVhdGVFcnJvcihcbiAgICAgICAgICAgIF91bmtub3duRW50aXR5RXJyb3JNc2codGhpcy5fY3Vyc29yLmdldENoYXJzKHN0YXJ0KSksIHRoaXMuX2N1cnNvci5nZXRTcGFuKCkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBuYW1lU3RhcnQgPSB0aGlzLl9jdXJzb3IuY2xvbmUoKTtcbiAgICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOYW1lZEVudGl0eUVuZCk7XG4gICAgICBpZiAodGhpcy5fY3Vyc29yLnBlZWsoKSAhPSBjaGFycy4kU0VNSUNPTE9OKSB7XG4gICAgICAgIC8vIE5vIHNlbWljb2xvbiB3YXMgZm91bmQgc28gYWJvcnQgdGhlIGVuY29kZWQgZW50aXR5IHRva2VuIHRoYXQgd2FzIGluIHByb2dyZXNzLCBhbmQgdHJlYXRcbiAgICAgICAgLy8gdGhpcyBhcyBhIHRleHQgdG9rZW5cbiAgICAgICAgdGhpcy5fYmVnaW5Ub2tlbih0ZXh0VG9rZW5UeXBlLCBzdGFydCk7XG4gICAgICAgIHRoaXMuX2N1cnNvciA9IG5hbWVTdGFydDtcbiAgICAgICAgdGhpcy5fZW5kVG9rZW4oWycmJ10pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHRoaXMuX2N1cnNvci5nZXRDaGFycyhuYW1lU3RhcnQpO1xuICAgICAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgICAgICBjb25zdCBjaGFyID0gTkFNRURfRU5USVRJRVNbbmFtZV07XG4gICAgICAgIGlmICghY2hhcikge1xuICAgICAgICAgIHRocm93IHRoaXMuX2NyZWF0ZUVycm9yKF91bmtub3duRW50aXR5RXJyb3JNc2cobmFtZSksIHRoaXMuX2N1cnNvci5nZXRTcGFuKHN0YXJ0KSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fZW5kVG9rZW4oW2NoYXIsIGAmJHtuYW1lfTtgXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZVJhd1RleHQoY29uc3VtZUVudGl0aWVzOiBib29sZWFuLCBlbmRNYXJrZXJQcmVkaWNhdGU6ICgpID0+IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9iZWdpblRva2VuKGNvbnN1bWVFbnRpdGllcyA/IFRva2VuVHlwZS5FU0NBUEFCTEVfUkFXX1RFWFQgOiBUb2tlblR5cGUuUkFXX1RFWFQpO1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICBjb25zdCB0YWdDbG9zZVN0YXJ0ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgICBjb25zdCBmb3VuZEVuZE1hcmtlciA9IGVuZE1hcmtlclByZWRpY2F0ZSgpO1xuICAgICAgdGhpcy5fY3Vyc29yID0gdGFnQ2xvc2VTdGFydDtcbiAgICAgIGlmIChmb3VuZEVuZE1hcmtlcikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChjb25zdW1lRW50aXRpZXMgJiYgdGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gY2hhcnMuJEFNUEVSU0FORCkge1xuICAgICAgICB0aGlzLl9lbmRUb2tlbihbdGhpcy5fcHJvY2Vzc0NhcnJpYWdlUmV0dXJucyhwYXJ0cy5qb2luKCcnKSldKTtcbiAgICAgICAgcGFydHMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5fY29uc3VtZUVudGl0eShUb2tlblR5cGUuRVNDQVBBQkxFX1JBV19URVhUKTtcbiAgICAgICAgdGhpcy5fYmVnaW5Ub2tlbihUb2tlblR5cGUuRVNDQVBBQkxFX1JBV19URVhUKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcnRzLnB1c2godGhpcy5fcmVhZENoYXIoKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuX2VuZFRva2VuKFt0aGlzLl9wcm9jZXNzQ2FycmlhZ2VSZXR1cm5zKHBhcnRzLmpvaW4oJycpKV0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZUNvbW1lbnQoc3RhcnQ6IENoYXJhY3RlckN1cnNvcikge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkNPTU1FTlRfU1RBUlQsIHN0YXJ0KTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGUoY2hhcnMuJE1JTlVTKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbXSk7XG4gICAgdGhpcy5fY29uc3VtZVJhd1RleHQoZmFsc2UsICgpID0+IHRoaXMuX2F0dGVtcHRTdHIoJy0tPicpKTtcbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5DT01NRU5UX0VORCk7XG4gICAgdGhpcy5fcmVxdWlyZVN0cignLS0+Jyk7XG4gICAgdGhpcy5fZW5kVG9rZW4oW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZUNkYXRhKHN0YXJ0OiBDaGFyYWN0ZXJDdXJzb3IpIHtcbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5DREFUQV9TVEFSVCwgc3RhcnQpO1xuICAgIHRoaXMuX3JlcXVpcmVTdHIoJ0NEQVRBWycpO1xuICAgIHRoaXMuX2VuZFRva2VuKFtdKTtcbiAgICB0aGlzLl9jb25zdW1lUmF3VGV4dChmYWxzZSwgKCkgPT4gdGhpcy5fYXR0ZW1wdFN0cignXV0+JykpO1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkNEQVRBX0VORCk7XG4gICAgdGhpcy5fcmVxdWlyZVN0cignXV0+Jyk7XG4gICAgdGhpcy5fZW5kVG9rZW4oW10pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZURvY1R5cGUoc3RhcnQ6IENoYXJhY3RlckN1cnNvcikge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkRPQ19UWVBFLCBzdGFydCk7XG4gICAgY29uc3QgY29udGVudFN0YXJ0ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgdGhpcy5fYXR0ZW1wdFVudGlsQ2hhcihjaGFycy4kR1QpO1xuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jdXJzb3IuZ2V0Q2hhcnMoY29udGVudFN0YXJ0KTtcbiAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgIHRoaXMuX2VuZFRva2VuKFtjb250ZW50XSk7XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lUHJlZml4QW5kTmFtZSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgbmFtZU9yUHJlZml4U3RhcnQgPSB0aGlzLl9jdXJzb3IuY2xvbmUoKTtcbiAgICBsZXQgcHJlZml4OiBzdHJpbmcgPSAnJztcbiAgICB3aGlsZSAodGhpcy5fY3Vyc29yLnBlZWsoKSAhPT0gY2hhcnMuJENPTE9OICYmICFpc1ByZWZpeEVuZCh0aGlzLl9jdXJzb3IucGVlaygpKSkge1xuICAgICAgdGhpcy5fY3Vyc29yLmFkdmFuY2UoKTtcbiAgICB9XG4gICAgbGV0IG5hbWVTdGFydDogQ2hhcmFjdGVyQ3Vyc29yO1xuICAgIGlmICh0aGlzLl9jdXJzb3IucGVlaygpID09PSBjaGFycy4kQ09MT04pIHtcbiAgICAgIHByZWZpeCA9IHRoaXMuX2N1cnNvci5nZXRDaGFycyhuYW1lT3JQcmVmaXhTdGFydCk7XG4gICAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgICAgbmFtZVN0YXJ0ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5hbWVTdGFydCA9IG5hbWVPclByZWZpeFN0YXJ0O1xuICAgIH1cbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGVVbnRpbEZuKGlzTmFtZUVuZCwgcHJlZml4ID09PSAnJyA/IDAgOiAxKTtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5fY3Vyc29yLmdldENoYXJzKG5hbWVTdGFydCk7XG4gICAgcmV0dXJuIFtwcmVmaXgsIG5hbWVdO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZVRhZ09wZW4oc3RhcnQ6IENoYXJhY3RlckN1cnNvcikge1xuICAgIGxldCB0YWdOYW1lOiBzdHJpbmc7XG4gICAgbGV0IHByZWZpeDogc3RyaW5nO1xuICAgIGxldCBvcGVuVGFnVG9rZW46IFRhZ09wZW5TdGFydFRva2VufEluY29tcGxldGVUYWdPcGVuVG9rZW58dW5kZWZpbmVkO1xuICAgIHRyeSB7XG4gICAgICBpZiAoIWNoYXJzLmlzQXNjaWlMZXR0ZXIodGhpcy5fY3Vyc29yLnBlZWsoKSkpIHtcbiAgICAgICAgdGhyb3cgdGhpcy5fY3JlYXRlRXJyb3IoXG4gICAgICAgICAgICBfdW5leHBlY3RlZENoYXJhY3RlckVycm9yTXNnKHRoaXMuX2N1cnNvci5wZWVrKCkpLCB0aGlzLl9jdXJzb3IuZ2V0U3BhbihzdGFydCkpO1xuICAgICAgfVxuXG4gICAgICBvcGVuVGFnVG9rZW4gPSB0aGlzLl9jb25zdW1lVGFnT3BlblN0YXJ0KHN0YXJ0KTtcbiAgICAgIHByZWZpeCA9IG9wZW5UYWdUb2tlbi5wYXJ0c1swXTtcbiAgICAgIHRhZ05hbWUgPSBvcGVuVGFnVG9rZW4ucGFydHNbMV07XG4gICAgICB0aGlzLl9hdHRlbXB0Q2hhckNvZGVVbnRpbEZuKGlzTm90V2hpdGVzcGFjZSk7XG4gICAgICB3aGlsZSAodGhpcy5fY3Vyc29yLnBlZWsoKSAhPT0gY2hhcnMuJFNMQVNIICYmIHRoaXMuX2N1cnNvci5wZWVrKCkgIT09IGNoYXJzLiRHVCAmJlxuICAgICAgICAgICAgIHRoaXMuX2N1cnNvci5wZWVrKCkgIT09IGNoYXJzLiRMVCAmJiB0aGlzLl9jdXJzb3IucGVlaygpICE9PSBjaGFycy4kRU9GKSB7XG4gICAgICAgIHRoaXMuX2NvbnN1bWVBdHRyaWJ1dGVOYW1lKCk7XG4gICAgICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOb3RXaGl0ZXNwYWNlKTtcbiAgICAgICAgaWYgKHRoaXMuX2F0dGVtcHRDaGFyQ29kZShjaGFycy4kRVEpKSB7XG4gICAgICAgICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlVW50aWxGbihpc05vdFdoaXRlc3BhY2UpO1xuICAgICAgICAgIHRoaXMuX2NvbnN1bWVBdHRyaWJ1dGVWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOb3RXaGl0ZXNwYWNlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2NvbnN1bWVUYWdPcGVuRW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiBfQ29udHJvbEZsb3dFcnJvcikge1xuICAgICAgICBpZiAob3BlblRhZ1Rva2VuKSB7XG4gICAgICAgICAgLy8gV2UgZXJyb3JlZCBiZWZvcmUgd2UgY291bGQgY2xvc2UgdGhlIG9wZW5pbmcgdGFnLCBzbyBpdCBpcyBpbmNvbXBsZXRlLlxuICAgICAgICAgIG9wZW5UYWdUb2tlbi50eXBlID0gVG9rZW5UeXBlLklOQ09NUExFVEVfVEFHX09QRU47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gV2hlbiB0aGUgc3RhcnQgdGFnIGlzIGludmFsaWQsIGFzc3VtZSB3ZSB3YW50IGEgXCI8XCIgYXMgdGV4dC5cbiAgICAgICAgICAvLyBCYWNrIHRvIGJhY2sgdGV4dCB0b2tlbnMgYXJlIG1lcmdlZCBhdCB0aGUgZW5kLlxuICAgICAgICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLlRFWFQsIHN0YXJ0KTtcbiAgICAgICAgICB0aGlzLl9lbmRUb2tlbihbJzwnXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbnRlbnRUb2tlblR5cGUgPSB0aGlzLl9nZXRUYWdEZWZpbml0aW9uKHRhZ05hbWUpLmdldENvbnRlbnRUeXBlKHByZWZpeCk7XG5cbiAgICBpZiAoY29udGVudFRva2VuVHlwZSA9PT0gVGFnQ29udGVudFR5cGUuUkFXX1RFWFQpIHtcbiAgICAgIHRoaXMuX2NvbnN1bWVSYXdUZXh0V2l0aFRhZ0Nsb3NlKHByZWZpeCwgdGFnTmFtZSwgZmFsc2UpO1xuICAgIH0gZWxzZSBpZiAoY29udGVudFRva2VuVHlwZSA9PT0gVGFnQ29udGVudFR5cGUuRVNDQVBBQkxFX1JBV19URVhUKSB7XG4gICAgICB0aGlzLl9jb25zdW1lUmF3VGV4dFdpdGhUYWdDbG9zZShwcmVmaXgsIHRhZ05hbWUsIHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2NvbnN1bWVSYXdUZXh0V2l0aFRhZ0Nsb3NlKHByZWZpeDogc3RyaW5nLCB0YWdOYW1lOiBzdHJpbmcsIGNvbnN1bWVFbnRpdGllczogYm9vbGVhbikge1xuICAgIHRoaXMuX2NvbnN1bWVSYXdUZXh0KGNvbnN1bWVFbnRpdGllcywgKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLl9hdHRlbXB0Q2hhckNvZGUoY2hhcnMuJExUKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgaWYgKCF0aGlzLl9hdHRlbXB0Q2hhckNvZGUoY2hhcnMuJFNMQVNIKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlVW50aWxGbihpc05vdFdoaXRlc3BhY2UpO1xuICAgICAgaWYgKCF0aGlzLl9hdHRlbXB0U3RyQ2FzZUluc2Vuc2l0aXZlKHRhZ05hbWUpKSByZXR1cm4gZmFsc2U7XG4gICAgICB0aGlzLl9hdHRlbXB0Q2hhckNvZGVVbnRpbEZuKGlzTm90V2hpdGVzcGFjZSk7XG4gICAgICByZXR1cm4gdGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJzLiRHVCk7XG4gICAgfSk7XG4gICAgdGhpcy5fYmVnaW5Ub2tlbihUb2tlblR5cGUuVEFHX0NMT1NFKTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGVVbnRpbEZuKGNvZGUgPT4gY29kZSA9PT0gY2hhcnMuJEdULCAzKTtcbiAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpOyAgLy8gQ29uc3VtZSB0aGUgYD5gXG4gICAgdGhpcy5fZW5kVG9rZW4oW3ByZWZpeCwgdGFnTmFtZV0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZVRhZ09wZW5TdGFydChzdGFydDogQ2hhcmFjdGVyQ3Vyc29yKTogVGFnT3BlblN0YXJ0VG9rZW4ge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLlRBR19PUEVOX1NUQVJULCBzdGFydCk7XG4gICAgY29uc3QgcGFydHMgPSB0aGlzLl9jb25zdW1lUHJlZml4QW5kTmFtZSgpO1xuICAgIHJldHVybiB0aGlzLl9lbmRUb2tlbihwYXJ0cykgYXMgVGFnT3BlblN0YXJ0VG9rZW47XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lQXR0cmlidXRlTmFtZSgpIHtcbiAgICBjb25zdCBhdHRyTmFtZVN0YXJ0ID0gdGhpcy5fY3Vyc29yLnBlZWsoKTtcbiAgICBpZiAoYXR0ck5hbWVTdGFydCA9PT0gY2hhcnMuJFNRIHx8IGF0dHJOYW1lU3RhcnQgPT09IGNoYXJzLiREUSkge1xuICAgICAgdGhyb3cgdGhpcy5fY3JlYXRlRXJyb3IoX3VuZXhwZWN0ZWRDaGFyYWN0ZXJFcnJvck1zZyhhdHRyTmFtZVN0YXJ0KSwgdGhpcy5fY3Vyc29yLmdldFNwYW4oKSk7XG4gICAgfVxuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkFUVFJfTkFNRSk7XG4gICAgY29uc3QgcHJlZml4QW5kTmFtZSA9IHRoaXMuX2NvbnN1bWVQcmVmaXhBbmROYW1lKCk7XG4gICAgdGhpcy5fZW5kVG9rZW4ocHJlZml4QW5kTmFtZSk7XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lQXR0cmlidXRlVmFsdWUoKSB7XG4gICAgbGV0IHZhbHVlOiBzdHJpbmc7XG4gICAgaWYgKHRoaXMuX2N1cnNvci5wZWVrKCkgPT09IGNoYXJzLiRTUSB8fCB0aGlzLl9jdXJzb3IucGVlaygpID09PSBjaGFycy4kRFEpIHtcbiAgICAgIGNvbnN0IHF1b3RlQ2hhciA9IHRoaXMuX2N1cnNvci5wZWVrKCk7XG4gICAgICB0aGlzLl9jb25zdW1lUXVvdGUocXVvdGVDaGFyKTtcbiAgICAgIC8vIEluIGFuIGF0dHJpYnV0ZSB0aGVuIGVuZCBvZiB0aGUgYXR0cmlidXRlIHZhbHVlIGFuZCB0aGUgcHJlbWF0dXJlIGVuZCB0byBhbiBpbnRlcnBvbGF0aW9uXG4gICAgICAvLyBhcmUgYm90aCB0cmlnZ2VyZWQgYnkgdGhlIGBxdW90ZUNoYXJgLlxuICAgICAgY29uc3QgZW5kUHJlZGljYXRlID0gKCkgPT4gdGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gcXVvdGVDaGFyO1xuICAgICAgdGhpcy5fY29uc3VtZVdpdGhJbnRlcnBvbGF0aW9uKFxuICAgICAgICAgIFRva2VuVHlwZS5BVFRSX1ZBTFVFX1RFWFQsIFRva2VuVHlwZS5BVFRSX1ZBTFVFX0lOVEVSUE9MQVRJT04sIGVuZFByZWRpY2F0ZSxcbiAgICAgICAgICBlbmRQcmVkaWNhdGUpO1xuICAgICAgdGhpcy5fY29uc3VtZVF1b3RlKHF1b3RlQ2hhcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGVuZFByZWRpY2F0ZSA9ICgpID0+IGlzTmFtZUVuZCh0aGlzLl9jdXJzb3IucGVlaygpKTtcbiAgICAgIHRoaXMuX2NvbnN1bWVXaXRoSW50ZXJwb2xhdGlvbihcbiAgICAgICAgICBUb2tlblR5cGUuQVRUUl9WQUxVRV9URVhULCBUb2tlblR5cGUuQVRUUl9WQUxVRV9JTlRFUlBPTEFUSU9OLCBlbmRQcmVkaWNhdGUsXG4gICAgICAgICAgZW5kUHJlZGljYXRlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lUXVvdGUocXVvdGVDaGFyOiBudW1iZXIpIHtcbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5BVFRSX1FVT1RFKTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGUocXVvdGVDaGFyKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbU3RyaW5nLmZyb21Db2RlUG9pbnQocXVvdGVDaGFyKV0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfY29uc3VtZVRhZ09wZW5FbmQoKSB7XG4gICAgY29uc3QgdG9rZW5UeXBlID1cbiAgICAgICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlKGNoYXJzLiRTTEFTSCkgPyBUb2tlblR5cGUuVEFHX09QRU5fRU5EX1ZPSUQgOiBUb2tlblR5cGUuVEFHX09QRU5fRU5EO1xuICAgIHRoaXMuX2JlZ2luVG9rZW4odG9rZW5UeXBlKTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGUoY2hhcnMuJEdUKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbXSk7XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lVGFnQ2xvc2Uoc3RhcnQ6IENoYXJhY3RlckN1cnNvcikge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLlRBR19DTE9TRSwgc3RhcnQpO1xuICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOb3RXaGl0ZXNwYWNlKTtcbiAgICBjb25zdCBwcmVmaXhBbmROYW1lID0gdGhpcy5fY29uc3VtZVByZWZpeEFuZE5hbWUoKTtcbiAgICB0aGlzLl9hdHRlbXB0Q2hhckNvZGVVbnRpbEZuKGlzTm90V2hpdGVzcGFjZSk7XG4gICAgdGhpcy5fcmVxdWlyZUNoYXJDb2RlKGNoYXJzLiRHVCk7XG4gICAgdGhpcy5fZW5kVG9rZW4ocHJlZml4QW5kTmFtZSk7XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lRXhwYW5zaW9uRm9ybVN0YXJ0KCkge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkVYUEFOU0lPTl9GT1JNX1NUQVJUKTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGUoY2hhcnMuJExCUkFDRSk7XG4gICAgdGhpcy5fZW5kVG9rZW4oW10pO1xuXG4gICAgdGhpcy5fZXhwYW5zaW9uQ2FzZVN0YWNrLnB1c2goVG9rZW5UeXBlLkVYUEFOU0lPTl9GT1JNX1NUQVJUKTtcblxuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLlJBV19URVhUKTtcbiAgICBjb25zdCBjb25kaXRpb24gPSB0aGlzLl9yZWFkVW50aWwoY2hhcnMuJENPTU1BKTtcbiAgICBjb25zdCBub3JtYWxpemVkQ29uZGl0aW9uID0gdGhpcy5fcHJvY2Vzc0NhcnJpYWdlUmV0dXJucyhjb25kaXRpb24pO1xuICAgIGlmICh0aGlzLl9pMThuTm9ybWFsaXplTGluZUVuZGluZ3NJbklDVXMpIHtcbiAgICAgIC8vIFdlIGV4cGxpY2l0bHkgd2FudCB0byBub3JtYWxpemUgbGluZSBlbmRpbmdzIGZvciB0aGlzIHRleHQuXG4gICAgICB0aGlzLl9lbmRUb2tlbihbbm9ybWFsaXplZENvbmRpdGlvbl0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBXZSBhcmUgbm90IG5vcm1hbGl6aW5nIGxpbmUgZW5kaW5ncy5cbiAgICAgIGNvbnN0IGNvbmRpdGlvblRva2VuID0gdGhpcy5fZW5kVG9rZW4oW2NvbmRpdGlvbl0pO1xuICAgICAgaWYgKG5vcm1hbGl6ZWRDb25kaXRpb24gIT09IGNvbmRpdGlvbikge1xuICAgICAgICB0aGlzLm5vbk5vcm1hbGl6ZWRJY3VFeHByZXNzaW9ucy5wdXNoKGNvbmRpdGlvblRva2VuKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fcmVxdWlyZUNoYXJDb2RlKGNoYXJzLiRDT01NQSk7XG4gICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlVW50aWxGbihpc05vdFdoaXRlc3BhY2UpO1xuXG4gICAgdGhpcy5fYmVnaW5Ub2tlbihUb2tlblR5cGUuUkFXX1RFWFQpO1xuICAgIGNvbnN0IHR5cGUgPSB0aGlzLl9yZWFkVW50aWwoY2hhcnMuJENPTU1BKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbdHlwZV0pO1xuICAgIHRoaXMuX3JlcXVpcmVDaGFyQ29kZShjaGFycy4kQ09NTUEpO1xuICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOb3RXaGl0ZXNwYWNlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbnN1bWVFeHBhbnNpb25DYXNlU3RhcnQoKSB7XG4gICAgdGhpcy5fYmVnaW5Ub2tlbihUb2tlblR5cGUuRVhQQU5TSU9OX0NBU0VfVkFMVUUpO1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5fcmVhZFVudGlsKGNoYXJzLiRMQlJBQ0UpLnRyaW0oKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbdmFsdWVdKTtcbiAgICB0aGlzLl9hdHRlbXB0Q2hhckNvZGVVbnRpbEZuKGlzTm90V2hpdGVzcGFjZSk7XG5cbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5FWFBBTlNJT05fQ0FTRV9FWFBfU1RBUlQpO1xuICAgIHRoaXMuX3JlcXVpcmVDaGFyQ29kZShjaGFycy4kTEJSQUNFKTtcbiAgICB0aGlzLl9lbmRUb2tlbihbXSk7XG4gICAgdGhpcy5fYXR0ZW1wdENoYXJDb2RlVW50aWxGbihpc05vdFdoaXRlc3BhY2UpO1xuXG4gICAgdGhpcy5fZXhwYW5zaW9uQ2FzZVN0YWNrLnB1c2goVG9rZW5UeXBlLkVYUEFOU0lPTl9DQVNFX0VYUF9TVEFSVCk7XG4gIH1cblxuICBwcml2YXRlIF9jb25zdW1lRXhwYW5zaW9uQ2FzZUVuZCgpIHtcbiAgICB0aGlzLl9iZWdpblRva2VuKFRva2VuVHlwZS5FWFBBTlNJT05fQ0FTRV9FWFBfRU5EKTtcbiAgICB0aGlzLl9yZXF1aXJlQ2hhckNvZGUoY2hhcnMuJFJCUkFDRSk7XG4gICAgdGhpcy5fZW5kVG9rZW4oW10pO1xuICAgIHRoaXMuX2F0dGVtcHRDaGFyQ29kZVVudGlsRm4oaXNOb3RXaGl0ZXNwYWNlKTtcblxuICAgIHRoaXMuX2V4cGFuc2lvbkNhc2VTdGFjay5wb3AoKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbnN1bWVFeHBhbnNpb25Gb3JtRW5kKCkge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oVG9rZW5UeXBlLkVYUEFOU0lPTl9GT1JNX0VORCk7XG4gICAgdGhpcy5fcmVxdWlyZUNoYXJDb2RlKGNoYXJzLiRSQlJBQ0UpO1xuICAgIHRoaXMuX2VuZFRva2VuKFtdKTtcblxuICAgIHRoaXMuX2V4cGFuc2lvbkNhc2VTdGFjay5wb3AoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdW1lIGEgc3RyaW5nIHRoYXQgbWF5IGNvbnRhaW4gaW50ZXJwb2xhdGlvbiBleHByZXNzaW9ucy5cbiAgICpcbiAgICogVGhlIGZpcnN0IHRva2VuIGNvbnN1bWVkIHdpbGwgYmUgb2YgYHRva2VuVHlwZWAgYW5kIHRoZW4gdGhlcmUgd2lsbCBiZSBhbHRlcm5hdGluZ1xuICAgKiBgaW50ZXJwb2xhdGlvblRva2VuVHlwZWAgYW5kIGB0b2tlblR5cGVgIHRva2VucyB1bnRpbCB0aGUgYGVuZFByZWRpY2F0ZSgpYCByZXR1cm5zIHRydWUuXG4gICAqXG4gICAqIElmIGFuIGludGVycG9sYXRpb24gdG9rZW4gZW5kcyBwcmVtYXR1cmVseSBpdCB3aWxsIGhhdmUgbm8gZW5kIG1hcmtlciBpbiBpdHMgYHBhcnRzYCBhcnJheS5cbiAgICpcbiAgICogQHBhcmFtIHRleHRUb2tlblR5cGUgdGhlIGtpbmQgb2YgdG9rZW5zIHRvIGludGVybGVhdmUgYXJvdW5kIGludGVycG9sYXRpb24gdG9rZW5zLlxuICAgKiBAcGFyYW0gaW50ZXJwb2xhdGlvblRva2VuVHlwZSB0aGUga2luZCBvZiB0b2tlbnMgdGhhdCBjb250YWluIGludGVycG9sYXRpb24uXG4gICAqIEBwYXJhbSBlbmRQcmVkaWNhdGUgYSBmdW5jdGlvbiB0aGF0IHNob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIHdlIHNob3VsZCBzdG9wIGNvbnN1bWluZy5cbiAgICogQHBhcmFtIGVuZEludGVycG9sYXRpb24gYSBmdW5jdGlvbiB0aGF0IHNob3VsZCByZXR1cm4gdHJ1ZSBpZiB0aGVyZSBpcyBhIHByZW1hdHVyZSBlbmQgdG8gYW5cbiAgICogICAgIGludGVycG9sYXRpb24gZXhwcmVzc2lvbiAtIGkuZS4gYmVmb3JlIHdlIGdldCB0byB0aGUgbm9ybWFsIGludGVycG9sYXRpb24gY2xvc2luZyBtYXJrZXIuXG4gICAqL1xuICBwcml2YXRlIF9jb25zdW1lV2l0aEludGVycG9sYXRpb24oXG4gICAgICB0ZXh0VG9rZW5UeXBlOiBUb2tlblR5cGUsIGludGVycG9sYXRpb25Ub2tlblR5cGU6IFRva2VuVHlwZSwgZW5kUHJlZGljYXRlOiAoKSA9PiBib29sZWFuLFxuICAgICAgZW5kSW50ZXJwb2xhdGlvbjogKCkgPT4gYm9vbGVhbikge1xuICAgIHRoaXMuX2JlZ2luVG9rZW4odGV4dFRva2VuVHlwZSk7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG5cbiAgICB3aGlsZSAoIWVuZFByZWRpY2F0ZSgpKSB7XG4gICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgICBpZiAodGhpcy5faW50ZXJwb2xhdGlvbkNvbmZpZyAmJiB0aGlzLl9hdHRlbXB0U3RyKHRoaXMuX2ludGVycG9sYXRpb25Db25maWcuc3RhcnQpKSB7XG4gICAgICAgIHRoaXMuX2VuZFRva2VuKFt0aGlzLl9wcm9jZXNzQ2FycmlhZ2VSZXR1cm5zKHBhcnRzLmpvaW4oJycpKV0sIGN1cnJlbnQpO1xuICAgICAgICBwYXJ0cy5sZW5ndGggPSAwO1xuICAgICAgICB0aGlzLl9jb25zdW1lSW50ZXJwb2xhdGlvbihpbnRlcnBvbGF0aW9uVG9rZW5UeXBlLCBjdXJyZW50LCBlbmRJbnRlcnBvbGF0aW9uKTtcbiAgICAgICAgdGhpcy5fYmVnaW5Ub2tlbih0ZXh0VG9rZW5UeXBlKTtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gY2hhcnMuJEFNUEVSU0FORCkge1xuICAgICAgICB0aGlzLl9lbmRUb2tlbihbdGhpcy5fcHJvY2Vzc0NhcnJpYWdlUmV0dXJucyhwYXJ0cy5qb2luKCcnKSldKTtcbiAgICAgICAgcGFydHMubGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5fY29uc3VtZUVudGl0eSh0ZXh0VG9rZW5UeXBlKTtcbiAgICAgICAgdGhpcy5fYmVnaW5Ub2tlbih0ZXh0VG9rZW5UeXBlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcnRzLnB1c2godGhpcy5fcmVhZENoYXIoKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSXQgaXMgcG9zc2libGUgdGhhdCBhbiBpbnRlcnBvbGF0aW9uIHdhcyBzdGFydGVkIGJ1dCBub3QgZW5kZWQgaW5zaWRlIHRoaXMgdGV4dCB0b2tlbi5cbiAgICAvLyBNYWtlIHN1cmUgdGhhdCB3ZSByZXNldCB0aGUgc3RhdGUgb2YgdGhlIGxleGVyIGNvcnJlY3RseS5cbiAgICB0aGlzLl9pbkludGVycG9sYXRpb24gPSBmYWxzZTtcblxuICAgIHRoaXMuX2VuZFRva2VuKFt0aGlzLl9wcm9jZXNzQ2FycmlhZ2VSZXR1cm5zKHBhcnRzLmpvaW4oJycpKV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN1bWUgYSBibG9jayBvZiB0ZXh0IHRoYXQgaGFzIGJlZW4gaW50ZXJwcmV0ZWQgYXMgYW4gQW5ndWxhciBpbnRlcnBvbGF0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gaW50ZXJwb2xhdGlvblRva2VuVHlwZSB0aGUgdHlwZSBvZiB0aGUgaW50ZXJwb2xhdGlvbiB0b2tlbiB0byBnZW5lcmF0ZS5cbiAgICogQHBhcmFtIGludGVycG9sYXRpb25TdGFydCBhIGN1cnNvciB0aGF0IHBvaW50cyB0byB0aGUgc3RhcnQgb2YgdGhpcyBpbnRlcnBvbGF0aW9uLlxuICAgKiBAcGFyYW0gcHJlbWF0dXJlRW5kUHJlZGljYXRlIGEgZnVuY3Rpb24gdGhhdCBzaG91bGQgcmV0dXJuIHRydWUgaWYgdGhlIG5leHQgY2hhcmFjdGVycyBpbmRpY2F0ZVxuICAgKiAgICAgYW4gZW5kIHRvIHRoZSBpbnRlcnBvbGF0aW9uIGJlZm9yZSBpdHMgbm9ybWFsIGNsb3NpbmcgbWFya2VyLlxuICAgKi9cbiAgcHJpdmF0ZSBfY29uc3VtZUludGVycG9sYXRpb24oXG4gICAgICBpbnRlcnBvbGF0aW9uVG9rZW5UeXBlOiBUb2tlblR5cGUsIGludGVycG9sYXRpb25TdGFydDogQ2hhcmFjdGVyQ3Vyc29yLFxuICAgICAgcHJlbWF0dXJlRW5kUHJlZGljYXRlOiAoKCkgPT4gYm9vbGVhbil8bnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHRoaXMuX2JlZ2luVG9rZW4oaW50ZXJwb2xhdGlvblRva2VuVHlwZSwgaW50ZXJwb2xhdGlvblN0YXJ0KTtcbiAgICBwYXJ0cy5wdXNoKHRoaXMuX2ludGVycG9sYXRpb25Db25maWcuc3RhcnQpO1xuXG4gICAgLy8gRmluZCB0aGUgZW5kIG9mIHRoZSBpbnRlcnBvbGF0aW9uLCBpZ25vcmluZyBjb250ZW50IGluc2lkZSBxdW90ZXMuXG4gICAgY29uc3QgZXhwcmVzc2lvblN0YXJ0ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG4gICAgbGV0IGluUXVvdGU6IG51bWJlcnxudWxsID0gbnVsbDtcbiAgICBsZXQgaW5Db21tZW50ID0gZmFsc2U7XG4gICAgd2hpbGUgKHRoaXMuX2N1cnNvci5wZWVrKCkgIT09IGNoYXJzLiRFT0YgJiZcbiAgICAgICAgICAgKHByZW1hdHVyZUVuZFByZWRpY2F0ZSA9PT0gbnVsbCB8fCAhcHJlbWF0dXJlRW5kUHJlZGljYXRlKCkpKSB7XG4gICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5fY3Vyc29yLmNsb25lKCk7XG5cbiAgICAgIGlmICh0aGlzLl9pc1RhZ1N0YXJ0KCkpIHtcbiAgICAgICAgLy8gV2UgYXJlIHN0YXJ0aW5nIHdoYXQgbG9va3MgbGlrZSBhbiBIVE1MIGVsZW1lbnQgaW4gdGhlIG1pZGRsZSBvZiB0aGlzIGludGVycG9sYXRpb24uXG4gICAgICAgIC8vIFJlc2V0IHRoZSBjdXJzb3IgdG8gYmVmb3JlIHRoZSBgPGAgY2hhcmFjdGVyIGFuZCBlbmQgdGhlIGludGVycG9sYXRpb24gdG9rZW4uXG4gICAgICAgIC8vIChUaGlzIGlzIGFjdHVhbGx5IHdyb25nIGJ1dCBoZXJlIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5KS5cbiAgICAgICAgdGhpcy5fY3Vyc29yID0gY3VycmVudDtcbiAgICAgICAgcGFydHMucHVzaCh0aGlzLl9nZXRQcm9jZXNzZWRDaGFycyhleHByZXNzaW9uU3RhcnQsIGN1cnJlbnQpKTtcbiAgICAgICAgdGhpcy5fZW5kVG9rZW4ocGFydHMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmIChpblF1b3RlID09PSBudWxsKSB7XG4gICAgICAgIGlmICh0aGlzLl9hdHRlbXB0U3RyKHRoaXMuX2ludGVycG9sYXRpb25Db25maWcuZW5kKSkge1xuICAgICAgICAgIC8vIFdlIGFyZSBub3QgaW4gYSBzdHJpbmcsIGFuZCB3ZSBoaXQgdGhlIGVuZCBpbnRlcnBvbGF0aW9uIG1hcmtlclxuICAgICAgICAgIHBhcnRzLnB1c2godGhpcy5fZ2V0UHJvY2Vzc2VkQ2hhcnMoZXhwcmVzc2lvblN0YXJ0LCBjdXJyZW50KSk7XG4gICAgICAgICAgcGFydHMucHVzaCh0aGlzLl9pbnRlcnBvbGF0aW9uQ29uZmlnLmVuZCk7XG4gICAgICAgICAgdGhpcy5fZW5kVG9rZW4ocGFydHMpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9hdHRlbXB0U3RyKCcvLycpKSB7XG4gICAgICAgICAgLy8gT25jZSB3ZSBhcmUgaW4gYSBjb21tZW50IHdlIGlnbm9yZSBhbnkgcXVvdGVzXG4gICAgICAgICAgaW5Db21tZW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBjaGFyID0gdGhpcy5fY3Vyc29yLnBlZWsoKTtcbiAgICAgIHRoaXMuX2N1cnNvci5hZHZhbmNlKCk7XG4gICAgICBpZiAoY2hhciA9PT0gY2hhcnMuJEJBQ0tTTEFTSCkge1xuICAgICAgICAvLyBTa2lwIHRoZSBuZXh0IGNoYXJhY3RlciBiZWNhdXNlIGl0IHdhcyBlc2NhcGVkLlxuICAgICAgICB0aGlzLl9jdXJzb3IuYWR2YW5jZSgpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyID09PSBpblF1b3RlKSB7XG4gICAgICAgIC8vIEV4aXRpbmcgdGhlIGN1cnJlbnQgcXVvdGVkIHN0cmluZ1xuICAgICAgICBpblF1b3RlID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoIWluQ29tbWVudCAmJiBpblF1b3RlID09PSBudWxsICYmIGNoYXJzLmlzUXVvdGUoY2hhcikpIHtcbiAgICAgICAgLy8gRW50ZXJpbmcgYSBuZXcgcXVvdGVkIHN0cmluZ1xuICAgICAgICBpblF1b3RlID0gY2hhcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBXZSBoaXQgRU9GIHdpdGhvdXQgZmluZGluZyBhIGNsb3NpbmcgaW50ZXJwb2xhdGlvbiBtYXJrZXJcbiAgICBwYXJ0cy5wdXNoKHRoaXMuX2dldFByb2Nlc3NlZENoYXJzKGV4cHJlc3Npb25TdGFydCwgdGhpcy5fY3Vyc29yKSk7XG4gICAgdGhpcy5fZW5kVG9rZW4ocGFydHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0UHJvY2Vzc2VkQ2hhcnMoc3RhcnQ6IENoYXJhY3RlckN1cnNvciwgZW5kOiBDaGFyYWN0ZXJDdXJzb3IpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9wcm9jZXNzQ2FycmlhZ2VSZXR1cm5zKGVuZC5nZXRDaGFycyhzdGFydCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNUZXh0RW5kKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLl9pc1RhZ1N0YXJ0KCkgfHwgdGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gY2hhcnMuJEVPRikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3Rva2VuaXplSWN1ICYmICF0aGlzLl9pbkludGVycG9sYXRpb24pIHtcbiAgICAgIGlmICh0aGlzLmlzRXhwYW5zaW9uRm9ybVN0YXJ0KCkpIHtcbiAgICAgICAgLy8gc3RhcnQgb2YgYW4gZXhwYW5zaW9uIGZvcm1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9jdXJzb3IucGVlaygpID09PSBjaGFycy4kUkJSQUNFICYmIHRoaXMuX2lzSW5FeHBhbnNpb25DYXNlKCkpIHtcbiAgICAgICAgLy8gZW5kIG9mIGFuZCBleHBhbnNpb24gY2FzZVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBjdXJyZW50IGN1cnNvciBpcyBwb2ludGluZyB0byB0aGUgc3RhcnQgb2YgYSB0YWdcbiAgICogKG9wZW5pbmcvY2xvc2luZy9jb21tZW50cy9jZGF0YS9ldGMpLlxuICAgKi9cbiAgcHJpdmF0ZSBfaXNUYWdTdGFydCgpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5fY3Vyc29yLnBlZWsoKSA9PT0gY2hhcnMuJExUKSB7XG4gICAgICAvLyBXZSBhc3N1bWUgdGhhdCBgPGAgZm9sbG93ZWQgYnkgd2hpdGVzcGFjZSBpcyBub3QgdGhlIHN0YXJ0IG9mIGFuIEhUTUwgZWxlbWVudC5cbiAgICAgIGNvbnN0IHRtcCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgICAgdG1wLmFkdmFuY2UoKTtcbiAgICAgIC8vIElmIHRoZSBuZXh0IGNoYXJhY3RlciBpcyBhbHBoYWJldGljLCAhIG5vciAvIHRoZW4gaXQgaXMgYSB0YWcgc3RhcnRcbiAgICAgIGNvbnN0IGNvZGUgPSB0bXAucGVlaygpO1xuICAgICAgaWYgKChjaGFycy4kYSA8PSBjb2RlICYmIGNvZGUgPD0gY2hhcnMuJHopIHx8IChjaGFycy4kQSA8PSBjb2RlICYmIGNvZGUgPD0gY2hhcnMuJFopIHx8XG4gICAgICAgICAgY29kZSA9PT0gY2hhcnMuJFNMQVNIIHx8IGNvZGUgPT09IGNoYXJzLiRCQU5HKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIF9yZWFkVW50aWwoY2hhcjogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgIHRoaXMuX2F0dGVtcHRVbnRpbENoYXIoY2hhcik7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnNvci5nZXRDaGFycyhzdGFydCk7XG4gIH1cblxuICBwcml2YXRlIF9pc0luRXhwYW5zaW9uQ2FzZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZXhwYW5zaW9uQ2FzZVN0YWNrLmxlbmd0aCA+IDAgJiZcbiAgICAgICAgdGhpcy5fZXhwYW5zaW9uQ2FzZVN0YWNrW3RoaXMuX2V4cGFuc2lvbkNhc2VTdGFjay5sZW5ndGggLSAxXSA9PT1cbiAgICAgICAgVG9rZW5UeXBlLkVYUEFOU0lPTl9DQVNFX0VYUF9TVEFSVDtcbiAgfVxuXG4gIHByaXZhdGUgX2lzSW5FeHBhbnNpb25Gb3JtKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9leHBhbnNpb25DYXNlU3RhY2subGVuZ3RoID4gMCAmJlxuICAgICAgICB0aGlzLl9leHBhbnNpb25DYXNlU3RhY2tbdGhpcy5fZXhwYW5zaW9uQ2FzZVN0YWNrLmxlbmd0aCAtIDFdID09PVxuICAgICAgICBUb2tlblR5cGUuRVhQQU5TSU9OX0ZPUk1fU1RBUlQ7XG4gIH1cblxuICBwcml2YXRlIGlzRXhwYW5zaW9uRm9ybVN0YXJ0KCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLl9jdXJzb3IucGVlaygpICE9PSBjaGFycy4kTEJSQUNFKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICh0aGlzLl9pbnRlcnBvbGF0aW9uQ29uZmlnKSB7XG4gICAgICBjb25zdCBzdGFydCA9IHRoaXMuX2N1cnNvci5jbG9uZSgpO1xuICAgICAgY29uc3QgaXNJbnRlcnBvbGF0aW9uID0gdGhpcy5fYXR0ZW1wdFN0cih0aGlzLl9pbnRlcnBvbGF0aW9uQ29uZmlnLnN0YXJ0KTtcbiAgICAgIHRoaXMuX2N1cnNvciA9IHN0YXJ0O1xuICAgICAgcmV0dXJuICFpc0ludGVycG9sYXRpb247XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzTm90V2hpdGVzcGFjZShjb2RlOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuICFjaGFycy5pc1doaXRlc3BhY2UoY29kZSkgfHwgY29kZSA9PT0gY2hhcnMuJEVPRjtcbn1cblxuZnVuY3Rpb24gaXNOYW1lRW5kKGNvZGU6IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4gY2hhcnMuaXNXaGl0ZXNwYWNlKGNvZGUpIHx8IGNvZGUgPT09IGNoYXJzLiRHVCB8fCBjb2RlID09PSBjaGFycy4kTFQgfHxcbiAgICAgIGNvZGUgPT09IGNoYXJzLiRTTEFTSCB8fCBjb2RlID09PSBjaGFycy4kU1EgfHwgY29kZSA9PT0gY2hhcnMuJERRIHx8IGNvZGUgPT09IGNoYXJzLiRFUSB8fFxuICAgICAgY29kZSA9PT0gY2hhcnMuJEVPRjtcbn1cblxuZnVuY3Rpb24gaXNQcmVmaXhFbmQoY29kZTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiAoY29kZSA8IGNoYXJzLiRhIHx8IGNoYXJzLiR6IDwgY29kZSkgJiYgKGNvZGUgPCBjaGFycy4kQSB8fCBjaGFycy4kWiA8IGNvZGUpICYmXG4gICAgICAoY29kZSA8IGNoYXJzLiQwIHx8IGNvZGUgPiBjaGFycy4kOSk7XG59XG5cbmZ1bmN0aW9uIGlzRGlnaXRFbnRpdHlFbmQoY29kZTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiBjb2RlID09PSBjaGFycy4kU0VNSUNPTE9OIHx8IGNvZGUgPT09IGNoYXJzLiRFT0YgfHwgIWNoYXJzLmlzQXNjaWlIZXhEaWdpdChjb2RlKTtcbn1cblxuZnVuY3Rpb24gaXNOYW1lZEVudGl0eUVuZChjb2RlOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIGNvZGUgPT09IGNoYXJzLiRTRU1JQ09MT04gfHwgY29kZSA9PT0gY2hhcnMuJEVPRiB8fCAhY2hhcnMuaXNBc2NpaUxldHRlcihjb2RlKTtcbn1cblxuZnVuY3Rpb24gaXNFeHBhbnNpb25DYXNlU3RhcnQocGVlazogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiBwZWVrICE9PSBjaGFycy4kUkJSQUNFO1xufVxuXG5mdW5jdGlvbiBjb21wYXJlQ2hhckNvZGVDYXNlSW5zZW5zaXRpdmUoY29kZTE6IG51bWJlciwgY29kZTI6IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4gdG9VcHBlckNhc2VDaGFyQ29kZShjb2RlMSkgPT09IHRvVXBwZXJDYXNlQ2hhckNvZGUoY29kZTIpO1xufVxuXG5mdW5jdGlvbiB0b1VwcGVyQ2FzZUNoYXJDb2RlKGNvZGU6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBjb2RlID49IGNoYXJzLiRhICYmIGNvZGUgPD0gY2hhcnMuJHogPyBjb2RlIC0gY2hhcnMuJGEgKyBjaGFycy4kQSA6IGNvZGU7XG59XG5cbmZ1bmN0aW9uIG1lcmdlVGV4dFRva2VucyhzcmNUb2tlbnM6IFRva2VuW10pOiBUb2tlbltdIHtcbiAgY29uc3QgZHN0VG9rZW5zOiBUb2tlbltdID0gW107XG4gIGxldCBsYXN0RHN0VG9rZW46IFRva2VufHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzcmNUb2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCB0b2tlbiA9IHNyY1Rva2Vuc1tpXTtcbiAgICBpZiAoKGxhc3REc3RUb2tlbiAmJiBsYXN0RHN0VG9rZW4udHlwZSA9PT0gVG9rZW5UeXBlLlRFWFQgJiYgdG9rZW4udHlwZSA9PT0gVG9rZW5UeXBlLlRFWFQpIHx8XG4gICAgICAgIChsYXN0RHN0VG9rZW4gJiYgbGFzdERzdFRva2VuLnR5cGUgPT09IFRva2VuVHlwZS5BVFRSX1ZBTFVFX1RFWFQgJiZcbiAgICAgICAgIHRva2VuLnR5cGUgPT09IFRva2VuVHlwZS5BVFRSX1ZBTFVFX1RFWFQpKSB7XG4gICAgICBsYXN0RHN0VG9rZW4ucGFydHNbMF0hICs9IHRva2VuLnBhcnRzWzBdO1xuICAgICAgbGFzdERzdFRva2VuLnNvdXJjZVNwYW4uZW5kID0gdG9rZW4uc291cmNlU3Bhbi5lbmQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxhc3REc3RUb2tlbiA9IHRva2VuO1xuICAgICAgZHN0VG9rZW5zLnB1c2gobGFzdERzdFRva2VuKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZHN0VG9rZW5zO1xufVxuXG5cbi8qKlxuICogVGhlIF9Ub2tlbml6ZXIgdXNlcyBvYmplY3RzIG9mIHRoaXMgdHlwZSB0byBtb3ZlIHRocm91Z2ggdGhlIGlucHV0IHRleHQsXG4gKiBleHRyYWN0aW5nIFwicGFyc2VkIGNoYXJhY3RlcnNcIi4gVGhlc2UgY291bGQgYmUgbW9yZSB0aGFuIG9uZSBhY3R1YWwgY2hhcmFjdGVyXG4gKiBpZiB0aGUgdGV4dCBjb250YWlucyBlc2NhcGUgc2VxdWVuY2VzLlxuICovXG5pbnRlcmZhY2UgQ2hhcmFjdGVyQ3Vyc29yIHtcbiAgLyoqIEluaXRpYWxpemUgdGhlIGN1cnNvci4gKi9cbiAgaW5pdCgpOiB2b2lkO1xuICAvKiogVGhlIHBhcnNlZCBjaGFyYWN0ZXIgYXQgdGhlIGN1cnJlbnQgY3Vyc29yIHBvc2l0aW9uLiAqL1xuICBwZWVrKCk6IG51bWJlcjtcbiAgLyoqIEFkdmFuY2UgdGhlIGN1cnNvciBieSBvbmUgcGFyc2VkIGNoYXJhY3Rlci4gKi9cbiAgYWR2YW5jZSgpOiB2b2lkO1xuICAvKiogR2V0IGEgc3BhbiBmcm9tIHRoZSBtYXJrZWQgc3RhcnQgcG9pbnQgdG8gdGhlIGN1cnJlbnQgcG9pbnQuICovXG4gIGdldFNwYW4oc3RhcnQ/OiB0aGlzLCBsZWFkaW5nVHJpdmlhQ29kZVBvaW50cz86IG51bWJlcltdKTogUGFyc2VTb3VyY2VTcGFuO1xuICAvKiogR2V0IHRoZSBwYXJzZWQgY2hhcmFjdGVycyBmcm9tIHRoZSBtYXJrZWQgc3RhcnQgcG9pbnQgdG8gdGhlIGN1cnJlbnQgcG9pbnQuICovXG4gIGdldENoYXJzKHN0YXJ0OiB0aGlzKTogc3RyaW5nO1xuICAvKiogVGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGxlZnQgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGN1cnNvci4gKi9cbiAgY2hhcnNMZWZ0KCk6IG51bWJlcjtcbiAgLyoqIFRoZSBudW1iZXIgb2YgY2hhcmFjdGVycyBiZXR3ZWVuIGB0aGlzYCBjdXJzb3IgYW5kIGBvdGhlcmAgY3Vyc29yLiAqL1xuICBkaWZmKG90aGVyOiB0aGlzKTogbnVtYmVyO1xuICAvKiogTWFrZSBhIGNvcHkgb2YgdGhpcyBjdXJzb3IgKi9cbiAgY2xvbmUoKTogQ2hhcmFjdGVyQ3Vyc29yO1xufVxuXG5pbnRlcmZhY2UgQ3Vyc29yU3RhdGUge1xuICBwZWVrOiBudW1iZXI7XG4gIG9mZnNldDogbnVtYmVyO1xuICBsaW5lOiBudW1iZXI7XG4gIGNvbHVtbjogbnVtYmVyO1xufVxuXG5jbGFzcyBQbGFpbkNoYXJhY3RlckN1cnNvciBpbXBsZW1lbnRzIENoYXJhY3RlckN1cnNvciB7XG4gIHByb3RlY3RlZCBzdGF0ZTogQ3Vyc29yU3RhdGU7XG4gIHByb3RlY3RlZCBmaWxlOiBQYXJzZVNvdXJjZUZpbGU7XG4gIHByb3RlY3RlZCBpbnB1dDogc3RyaW5nO1xuICBwcm90ZWN0ZWQgZW5kOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IoZmlsZU9yQ3Vyc29yOiBQbGFpbkNoYXJhY3RlckN1cnNvcik7XG4gIGNvbnN0cnVjdG9yKGZpbGVPckN1cnNvcjogUGFyc2VTb3VyY2VGaWxlLCByYW5nZTogTGV4ZXJSYW5nZSk7XG4gIGNvbnN0cnVjdG9yKGZpbGVPckN1cnNvcjogUGFyc2VTb3VyY2VGaWxlfFBsYWluQ2hhcmFjdGVyQ3Vyc29yLCByYW5nZT86IExleGVyUmFuZ2UpIHtcbiAgICBpZiAoZmlsZU9yQ3Vyc29yIGluc3RhbmNlb2YgUGxhaW5DaGFyYWN0ZXJDdXJzb3IpIHtcbiAgICAgIHRoaXMuZmlsZSA9IGZpbGVPckN1cnNvci5maWxlO1xuICAgICAgdGhpcy5pbnB1dCA9IGZpbGVPckN1cnNvci5pbnB1dDtcbiAgICAgIHRoaXMuZW5kID0gZmlsZU9yQ3Vyc29yLmVuZDtcblxuICAgICAgY29uc3Qgc3RhdGUgPSBmaWxlT3JDdXJzb3Iuc3RhdGU7XG4gICAgICAvLyBOb3RlOiBhdm9pZCB1c2luZyBgey4uLmZpbGVPckN1cnNvci5zdGF0ZX1gIGhlcmUgYXMgdGhhdCBoYXMgYSBzZXZlcmUgcGVyZm9ybWFuY2UgcGVuYWx0eS5cbiAgICAgIC8vIEluIEVTNSBidW5kbGVzIHRoZSBvYmplY3Qgc3ByZWFkIG9wZXJhdG9yIGlzIHRyYW5zbGF0ZWQgaW50byB0aGUgYF9fYXNzaWduYCBoZWxwZXIsIHdoaWNoXG4gICAgICAvLyBpcyBub3Qgb3B0aW1pemVkIGJ5IFZNcyBhcyBlZmZpY2llbnRseSBhcyBhIHJhdyBvYmplY3QgbGl0ZXJhbC4gU2luY2UgdGhpcyBjb25zdHJ1Y3RvciBpc1xuICAgICAgLy8gY2FsbGVkIGluIHRpZ2h0IGxvb3BzLCB0aGlzIGRpZmZlcmVuY2UgbWF0dGVycy5cbiAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgIHBlZWs6IHN0YXRlLnBlZWssXG4gICAgICAgIG9mZnNldDogc3RhdGUub2Zmc2V0LFxuICAgICAgICBsaW5lOiBzdGF0ZS5saW5lLFxuICAgICAgICBjb2x1bW46IHN0YXRlLmNvbHVtbixcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghcmFuZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ1Byb2dyYW1taW5nIGVycm9yOiB0aGUgcmFuZ2UgYXJndW1lbnQgbXVzdCBiZSBwcm92aWRlZCB3aXRoIGEgZmlsZSBhcmd1bWVudC4nKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZmlsZSA9IGZpbGVPckN1cnNvcjtcbiAgICAgIHRoaXMuaW5wdXQgPSBmaWxlT3JDdXJzb3IuY29udGVudDtcbiAgICAgIHRoaXMuZW5kID0gcmFuZ2UuZW5kUG9zO1xuICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgcGVlazogLTEsXG4gICAgICAgIG9mZnNldDogcmFuZ2Uuc3RhcnRQb3MsXG4gICAgICAgIGxpbmU6IHJhbmdlLnN0YXJ0TGluZSxcbiAgICAgICAgY29sdW1uOiByYW5nZS5zdGFydENvbCxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgY2xvbmUoKTogUGxhaW5DaGFyYWN0ZXJDdXJzb3Ige1xuICAgIHJldHVybiBuZXcgUGxhaW5DaGFyYWN0ZXJDdXJzb3IodGhpcyk7XG4gIH1cblxuICBwZWVrKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlLnBlZWs7XG4gIH1cbiAgY2hhcnNMZWZ0KCkge1xuICAgIHJldHVybiB0aGlzLmVuZCAtIHRoaXMuc3RhdGUub2Zmc2V0O1xuICB9XG4gIGRpZmYob3RoZXI6IHRoaXMpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5vZmZzZXQgLSBvdGhlci5zdGF0ZS5vZmZzZXQ7XG4gIH1cblxuICBhZHZhbmNlKCk6IHZvaWQge1xuICAgIHRoaXMuYWR2YW5jZVN0YXRlKHRoaXMuc3RhdGUpO1xuICB9XG5cbiAgaW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZVBlZWsodGhpcy5zdGF0ZSk7XG4gIH1cblxuICBnZXRTcGFuKHN0YXJ0PzogdGhpcywgbGVhZGluZ1RyaXZpYUNvZGVQb2ludHM/OiBudW1iZXJbXSk6IFBhcnNlU291cmNlU3BhbiB7XG4gICAgc3RhcnQgPSBzdGFydCB8fCB0aGlzO1xuICAgIGxldCBmdWxsU3RhcnQgPSBzdGFydDtcbiAgICBpZiAobGVhZGluZ1RyaXZpYUNvZGVQb2ludHMpIHtcbiAgICAgIHdoaWxlICh0aGlzLmRpZmYoc3RhcnQpID4gMCAmJiBsZWFkaW5nVHJpdmlhQ29kZVBvaW50cy5pbmRleE9mKHN0YXJ0LnBlZWsoKSkgIT09IC0xKSB7XG4gICAgICAgIGlmIChmdWxsU3RhcnQgPT09IHN0YXJ0KSB7XG4gICAgICAgICAgc3RhcnQgPSBzdGFydC5jbG9uZSgpIGFzIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgc3RhcnQuYWR2YW5jZSgpO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBzdGFydExvY2F0aW9uID0gdGhpcy5sb2NhdGlvbkZyb21DdXJzb3Ioc3RhcnQpO1xuICAgIGNvbnN0IGVuZExvY2F0aW9uID0gdGhpcy5sb2NhdGlvbkZyb21DdXJzb3IodGhpcyk7XG4gICAgY29uc3QgZnVsbFN0YXJ0TG9jYXRpb24gPVxuICAgICAgICBmdWxsU3RhcnQgIT09IHN0YXJ0ID8gdGhpcy5sb2NhdGlvbkZyb21DdXJzb3IoZnVsbFN0YXJ0KSA6IHN0YXJ0TG9jYXRpb247XG4gICAgcmV0dXJuIG5ldyBQYXJzZVNvdXJjZVNwYW4oc3RhcnRMb2NhdGlvbiwgZW5kTG9jYXRpb24sIGZ1bGxTdGFydExvY2F0aW9uKTtcbiAgfVxuXG4gIGdldENoYXJzKHN0YXJ0OiB0aGlzKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5pbnB1dC5zdWJzdHJpbmcoc3RhcnQuc3RhdGUub2Zmc2V0LCB0aGlzLnN0YXRlLm9mZnNldCk7XG4gIH1cblxuICBjaGFyQXQocG9zOiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmlucHV0LmNoYXJDb2RlQXQocG9zKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhZHZhbmNlU3RhdGUoc3RhdGU6IEN1cnNvclN0YXRlKSB7XG4gICAgaWYgKHN0YXRlLm9mZnNldCA+PSB0aGlzLmVuZCkge1xuICAgICAgdGhpcy5zdGF0ZSA9IHN0YXRlO1xuICAgICAgdGhyb3cgbmV3IEN1cnNvckVycm9yKCdVbmV4cGVjdGVkIGNoYXJhY3RlciBcIkVPRlwiJywgdGhpcyk7XG4gICAgfVxuICAgIGNvbnN0IGN1cnJlbnRDaGFyID0gdGhpcy5jaGFyQXQoc3RhdGUub2Zmc2V0KTtcbiAgICBpZiAoY3VycmVudENoYXIgPT09IGNoYXJzLiRMRikge1xuICAgICAgc3RhdGUubGluZSsrO1xuICAgICAgc3RhdGUuY29sdW1uID0gMDtcbiAgICB9IGVsc2UgaWYgKCFjaGFycy5pc05ld0xpbmUoY3VycmVudENoYXIpKSB7XG4gICAgICBzdGF0ZS5jb2x1bW4rKztcbiAgICB9XG4gICAgc3RhdGUub2Zmc2V0Kys7XG4gICAgdGhpcy51cGRhdGVQZWVrKHN0YXRlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCB1cGRhdGVQZWVrKHN0YXRlOiBDdXJzb3JTdGF0ZSk6IHZvaWQge1xuICAgIHN0YXRlLnBlZWsgPSBzdGF0ZS5vZmZzZXQgPj0gdGhpcy5lbmQgPyBjaGFycy4kRU9GIDogdGhpcy5jaGFyQXQoc3RhdGUub2Zmc2V0KTtcbiAgfVxuXG4gIHByaXZhdGUgbG9jYXRpb25Gcm9tQ3Vyc29yKGN1cnNvcjogdGhpcyk6IFBhcnNlTG9jYXRpb24ge1xuICAgIHJldHVybiBuZXcgUGFyc2VMb2NhdGlvbihcbiAgICAgICAgY3Vyc29yLmZpbGUsIGN1cnNvci5zdGF0ZS5vZmZzZXQsIGN1cnNvci5zdGF0ZS5saW5lLCBjdXJzb3Iuc3RhdGUuY29sdW1uKTtcbiAgfVxufVxuXG5jbGFzcyBFc2NhcGVkQ2hhcmFjdGVyQ3Vyc29yIGV4dGVuZHMgUGxhaW5DaGFyYWN0ZXJDdXJzb3Ige1xuICBwcm90ZWN0ZWQgaW50ZXJuYWxTdGF0ZTogQ3Vyc29yU3RhdGU7XG5cbiAgY29uc3RydWN0b3IoZmlsZU9yQ3Vyc29yOiBFc2NhcGVkQ2hhcmFjdGVyQ3Vyc29yKTtcbiAgY29uc3RydWN0b3IoZmlsZU9yQ3Vyc29yOiBQYXJzZVNvdXJjZUZpbGUsIHJhbmdlOiBMZXhlclJhbmdlKTtcbiAgY29uc3RydWN0b3IoZmlsZU9yQ3Vyc29yOiBQYXJzZVNvdXJjZUZpbGV8RXNjYXBlZENoYXJhY3RlckN1cnNvciwgcmFuZ2U/OiBMZXhlclJhbmdlKSB7XG4gICAgaWYgKGZpbGVPckN1cnNvciBpbnN0YW5jZW9mIEVzY2FwZWRDaGFyYWN0ZXJDdXJzb3IpIHtcbiAgICAgIHN1cGVyKGZpbGVPckN1cnNvcik7XG4gICAgICB0aGlzLmludGVybmFsU3RhdGUgPSB7Li4uZmlsZU9yQ3Vyc29yLmludGVybmFsU3RhdGV9O1xuICAgIH0gZWxzZSB7XG4gICAgICBzdXBlcihmaWxlT3JDdXJzb3IsIHJhbmdlISk7XG4gICAgICB0aGlzLmludGVybmFsU3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFkdmFuY2UoKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0ZSA9IHRoaXMuaW50ZXJuYWxTdGF0ZTtcbiAgICBzdXBlci5hZHZhbmNlKCk7XG4gICAgdGhpcy5wcm9jZXNzRXNjYXBlU2VxdWVuY2UoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGluaXQoKTogdm9pZCB7XG4gICAgc3VwZXIuaW5pdCgpO1xuICAgIHRoaXMucHJvY2Vzc0VzY2FwZVNlcXVlbmNlKCk7XG4gIH1cblxuICBvdmVycmlkZSBjbG9uZSgpOiBFc2NhcGVkQ2hhcmFjdGVyQ3Vyc29yIHtcbiAgICByZXR1cm4gbmV3IEVzY2FwZWRDaGFyYWN0ZXJDdXJzb3IodGhpcyk7XG4gIH1cblxuICBvdmVycmlkZSBnZXRDaGFycyhzdGFydDogdGhpcyk6IHN0cmluZyB7XG4gICAgY29uc3QgY3Vyc29yID0gc3RhcnQuY2xvbmUoKTtcbiAgICBsZXQgY2hhcnMgPSAnJztcbiAgICB3aGlsZSAoY3Vyc29yLmludGVybmFsU3RhdGUub2Zmc2V0IDwgdGhpcy5pbnRlcm5hbFN0YXRlLm9mZnNldCkge1xuICAgICAgY2hhcnMgKz0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY3Vyc29yLnBlZWsoKSk7XG4gICAgICBjdXJzb3IuYWR2YW5jZSgpO1xuICAgIH1cbiAgICByZXR1cm4gY2hhcnM7XG4gIH1cblxuICAvKipcbiAgICogUHJvY2VzcyB0aGUgZXNjYXBlIHNlcXVlbmNlIHRoYXQgc3RhcnRzIGF0IHRoZSBjdXJyZW50IHBvc2l0aW9uIGluIHRoZSB0ZXh0LlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gZW5zdXJlIHRoYXQgYHBlZWtgIGhhcyB0aGUgdW5lc2NhcGVkIHZhbHVlIG9mIGVzY2FwZSBzZXF1ZW5jZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJvY2Vzc0VzY2FwZVNlcXVlbmNlKCk6IHZvaWQge1xuICAgIGNvbnN0IHBlZWsgPSAoKSA9PiB0aGlzLmludGVybmFsU3RhdGUucGVlaztcblxuICAgIGlmIChwZWVrKCkgPT09IGNoYXJzLiRCQUNLU0xBU0gpIHtcbiAgICAgIC8vIFdlIGhhdmUgaGl0IGFuIGVzY2FwZSBzZXF1ZW5jZSBzbyB3ZSBuZWVkIHRoZSBpbnRlcm5hbCBzdGF0ZSB0byBiZWNvbWUgaW5kZXBlbmRlbnRcbiAgICAgIC8vIG9mIHRoZSBleHRlcm5hbCBzdGF0ZS5cbiAgICAgIHRoaXMuaW50ZXJuYWxTdGF0ZSA9IHsuLi50aGlzLnN0YXRlfTtcblxuICAgICAgLy8gTW92ZSBwYXN0IHRoZSBiYWNrc2xhc2hcbiAgICAgIHRoaXMuYWR2YW5jZVN0YXRlKHRoaXMuaW50ZXJuYWxTdGF0ZSk7XG5cbiAgICAgIC8vIEZpcnN0IGNoZWNrIGZvciBzdGFuZGFyZCBjb250cm9sIGNoYXIgc2VxdWVuY2VzXG4gICAgICBpZiAocGVlaygpID09PSBjaGFycy4kbikge1xuICAgICAgICB0aGlzLnN0YXRlLnBlZWsgPSBjaGFycy4kTEY7XG4gICAgICB9IGVsc2UgaWYgKHBlZWsoKSA9PT0gY2hhcnMuJHIpIHtcbiAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gY2hhcnMuJENSO1xuICAgICAgfSBlbHNlIGlmIChwZWVrKCkgPT09IGNoYXJzLiR2KSB7XG4gICAgICAgIHRoaXMuc3RhdGUucGVlayA9IGNoYXJzLiRWVEFCO1xuICAgICAgfSBlbHNlIGlmIChwZWVrKCkgPT09IGNoYXJzLiR0KSB7XG4gICAgICAgIHRoaXMuc3RhdGUucGVlayA9IGNoYXJzLiRUQUI7XG4gICAgICB9IGVsc2UgaWYgKHBlZWsoKSA9PT0gY2hhcnMuJGIpIHtcbiAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gY2hhcnMuJEJTUEFDRTtcbiAgICAgIH0gZWxzZSBpZiAocGVlaygpID09PSBjaGFycy4kZikge1xuICAgICAgICB0aGlzLnN0YXRlLnBlZWsgPSBjaGFycy4kRkY7XG4gICAgICB9XG5cbiAgICAgIC8vIE5vdyBjb25zaWRlciBtb3JlIGNvbXBsZXggc2VxdWVuY2VzXG4gICAgICBlbHNlIGlmIChwZWVrKCkgPT09IGNoYXJzLiR1KSB7XG4gICAgICAgIC8vIFVuaWNvZGUgY29kZS1wb2ludCBzZXF1ZW5jZVxuICAgICAgICB0aGlzLmFkdmFuY2VTdGF0ZSh0aGlzLmludGVybmFsU3RhdGUpOyAgLy8gYWR2YW5jZSBwYXN0IHRoZSBgdWAgY2hhclxuICAgICAgICBpZiAocGVlaygpID09PSBjaGFycy4kTEJSQUNFKSB7XG4gICAgICAgICAgLy8gVmFyaWFibGUgbGVuZ3RoIFVuaWNvZGUsIGUuZy4gYFxceHsxMjN9YFxuICAgICAgICAgIHRoaXMuYWR2YW5jZVN0YXRlKHRoaXMuaW50ZXJuYWxTdGF0ZSk7ICAvLyBhZHZhbmNlIHBhc3QgdGhlIGB7YCBjaGFyXG4gICAgICAgICAgLy8gQWR2YW5jZSBwYXN0IHRoZSB2YXJpYWJsZSBudW1iZXIgb2YgaGV4IGRpZ2l0cyB1bnRpbCB3ZSBoaXQgYSBgfWAgY2hhclxuICAgICAgICAgIGNvbnN0IGRpZ2l0U3RhcnQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgICAgICAgd2hpbGUgKHBlZWsoKSAhPT0gY2hhcnMuJFJCUkFDRSkge1xuICAgICAgICAgICAgdGhpcy5hZHZhbmNlU3RhdGUodGhpcy5pbnRlcm5hbFN0YXRlKTtcbiAgICAgICAgICAgIGxlbmd0aCsrO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLnN0YXRlLnBlZWsgPSB0aGlzLmRlY29kZUhleERpZ2l0cyhkaWdpdFN0YXJ0LCBsZW5ndGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEZpeGVkIGxlbmd0aCBVbmljb2RlLCBlLmcuIGBcXHUxMjM0YFxuICAgICAgICAgIGNvbnN0IGRpZ2l0U3RhcnQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgICAgdGhpcy5hZHZhbmNlU3RhdGUodGhpcy5pbnRlcm5hbFN0YXRlKTtcbiAgICAgICAgICB0aGlzLmFkdmFuY2VTdGF0ZSh0aGlzLmludGVybmFsU3RhdGUpO1xuICAgICAgICAgIHRoaXMuYWR2YW5jZVN0YXRlKHRoaXMuaW50ZXJuYWxTdGF0ZSk7XG4gICAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gdGhpcy5kZWNvZGVIZXhEaWdpdHMoZGlnaXRTdGFydCwgNCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZWxzZSBpZiAocGVlaygpID09PSBjaGFycy4keCkge1xuICAgICAgICAvLyBIZXggY2hhciBjb2RlLCBlLmcuIGBcXHgyRmBcbiAgICAgICAgdGhpcy5hZHZhbmNlU3RhdGUodGhpcy5pbnRlcm5hbFN0YXRlKTsgIC8vIGFkdmFuY2UgcGFzdCB0aGUgYHhgIGNoYXJcbiAgICAgICAgY29uc3QgZGlnaXRTdGFydCA9IHRoaXMuY2xvbmUoKTtcbiAgICAgICAgdGhpcy5hZHZhbmNlU3RhdGUodGhpcy5pbnRlcm5hbFN0YXRlKTtcbiAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gdGhpcy5kZWNvZGVIZXhEaWdpdHMoZGlnaXRTdGFydCwgMik7XG4gICAgICB9XG5cbiAgICAgIGVsc2UgaWYgKGNoYXJzLmlzT2N0YWxEaWdpdChwZWVrKCkpKSB7XG4gICAgICAgIC8vIE9jdGFsIGNoYXIgY29kZSwgZS5nLiBgXFwwMTJgLFxuICAgICAgICBsZXQgb2N0YWwgPSAnJztcbiAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG4gICAgICAgIGxldCBwcmV2aW91cyA9IHRoaXMuY2xvbmUoKTtcbiAgICAgICAgd2hpbGUgKGNoYXJzLmlzT2N0YWxEaWdpdChwZWVrKCkpICYmIGxlbmd0aCA8IDMpIHtcbiAgICAgICAgICBwcmV2aW91cyA9IHRoaXMuY2xvbmUoKTtcbiAgICAgICAgICBvY3RhbCArPSBTdHJpbmcuZnJvbUNvZGVQb2ludChwZWVrKCkpO1xuICAgICAgICAgIHRoaXMuYWR2YW5jZVN0YXRlKHRoaXMuaW50ZXJuYWxTdGF0ZSk7XG4gICAgICAgICAgbGVuZ3RoKys7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gcGFyc2VJbnQob2N0YWwsIDgpO1xuICAgICAgICAvLyBCYWNrdXAgb25lIGNoYXJcbiAgICAgICAgdGhpcy5pbnRlcm5hbFN0YXRlID0gcHJldmlvdXMuaW50ZXJuYWxTdGF0ZTtcbiAgICAgIH1cblxuICAgICAgZWxzZSBpZiAoY2hhcnMuaXNOZXdMaW5lKHRoaXMuaW50ZXJuYWxTdGF0ZS5wZWVrKSkge1xuICAgICAgICAvLyBMaW5lIGNvbnRpbnVhdGlvbiBgXFxgIGZvbGxvd2VkIGJ5IGEgbmV3IGxpbmVcbiAgICAgICAgdGhpcy5hZHZhbmNlU3RhdGUodGhpcy5pbnRlcm5hbFN0YXRlKTsgIC8vIGFkdmFuY2Ugb3ZlciB0aGUgbmV3bGluZVxuICAgICAgICB0aGlzLnN0YXRlID0gdGhpcy5pbnRlcm5hbFN0YXRlO1xuICAgICAgfVxuXG4gICAgICBlbHNlIHtcbiAgICAgICAgLy8gSWYgbm9uZSBvZiB0aGUgYGlmYCBibG9ja3Mgd2VyZSBleGVjdXRlZCB0aGVuIHdlIGp1c3QgaGF2ZSBhbiBlc2NhcGVkIG5vcm1hbCBjaGFyYWN0ZXIuXG4gICAgICAgIC8vIEluIHRoYXQgY2FzZSB3ZSBqdXN0LCBlZmZlY3RpdmVseSwgc2tpcCB0aGUgYmFja3NsYXNoIGZyb20gdGhlIGNoYXJhY3Rlci5cbiAgICAgICAgdGhpcy5zdGF0ZS5wZWVrID0gdGhpcy5pbnRlcm5hbFN0YXRlLnBlZWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGRlY29kZUhleERpZ2l0cyhzdGFydDogRXNjYXBlZENoYXJhY3RlckN1cnNvciwgbGVuZ3RoOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IGhleCA9IHRoaXMuaW5wdXQuc3Vic3RyKHN0YXJ0LmludGVybmFsU3RhdGUub2Zmc2V0LCBsZW5ndGgpO1xuICAgIGNvbnN0IGNoYXJDb2RlID0gcGFyc2VJbnQoaGV4LCAxNik7XG4gICAgaWYgKCFpc05hTihjaGFyQ29kZSkpIHtcbiAgICAgIHJldHVybiBjaGFyQ29kZTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhcnQuc3RhdGUgPSBzdGFydC5pbnRlcm5hbFN0YXRlO1xuICAgICAgdGhyb3cgbmV3IEN1cnNvckVycm9yKCdJbnZhbGlkIGhleGFkZWNpbWFsIGVzY2FwZSBzZXF1ZW5jZScsIHN0YXJ0KTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEN1cnNvckVycm9yIHtcbiAgY29uc3RydWN0b3IocHVibGljIG1zZzogc3RyaW5nLCBwdWJsaWMgY3Vyc29yOiBDaGFyYWN0ZXJDdXJzb3IpIHt9XG59XG4iXX0= |
---|