@angular/core 10.0.6 → 10.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/core-testing.umd.js +1 -1
- package/bundles/core-testing.umd.min.js +1 -1
- package/bundles/core-testing.umd.min.js.map +1 -1
- package/bundles/core.umd.js +1678 -1387
- package/bundles/core.umd.js.map +1 -1
- package/bundles/core.umd.min.js +152 -124
- package/bundles/core.umd.min.js.map +1 -1
- package/core.d.ts +258 -58
- package/core.metadata.json +1 -1
- package/esm2015/core.js +3 -3
- package/esm2015/src/application_module.js +2 -2
- package/esm2015/src/application_ref.js +2 -2
- package/esm2015/src/core_render3_private_export.js +2 -1
- package/esm2015/src/metadata/di.js +1 -1
- package/esm2015/src/r3_symbols.js +2 -1
- package/esm2015/src/reflection/reflection_capabilities.js +38 -8
- package/esm2015/src/render3/bindings.js +3 -3
- package/esm2015/src/render3/component.js +3 -3
- package/esm2015/src/render3/di.js +1 -1
- package/esm2015/src/render3/i18n/i18n_apply.js +445 -0
- package/esm2015/src/render3/i18n/i18n_debug.js +170 -0
- package/esm2015/src/render3/i18n/i18n_locale_id.js +37 -0
- package/esm2015/src/render3/i18n/i18n_parse.js +635 -0
- package/esm2015/src/render3/i18n/i18n_postprocess.js +121 -0
- package/esm2015/src/render3/index.js +3 -2
- package/esm2015/src/render3/instructions/advance.js +3 -3
- package/esm2015/src/render3/instructions/element.js +3 -3
- package/esm2015/src/render3/instructions/element_container.js +3 -3
- package/esm2015/src/render3/instructions/i18n.js +164 -0
- package/esm2015/src/render3/instructions/listener.js +3 -3
- package/esm2015/src/render3/instructions/lview_debug.js +54 -213
- package/esm2015/src/render3/instructions/shared.js +54 -38
- package/esm2015/src/render3/instructions/text.js +3 -3
- package/esm2015/src/render3/interfaces/i18n.js +12 -3
- package/esm2015/src/render3/interfaces/node.js +13 -1
- package/esm2015/src/render3/interfaces/view.js +1 -1
- package/esm2015/src/render3/jit/directive.js +33 -10
- package/esm2015/src/render3/ng_module_ref.js +2 -2
- package/esm2015/src/render3/node_manipulation.js +1 -11
- package/esm2015/src/render3/pure_function.js +3 -3
- package/esm2015/src/render3/query.js +14 -12
- package/esm2015/src/render3/styling/style_binding_list.js +3 -3
- package/esm2015/src/render3/styling/styling_parser.js +3 -2
- package/esm2015/src/render3/util/debug_utils.js +31 -2
- package/esm2015/src/render3/util/discovery_utils.js +1 -1
- package/esm2015/src/render3/util/view_utils.js +5 -5
- package/esm2015/src/render3/view_engine_compatibility.js +13 -4
- package/esm2015/src/util/assert.js +2 -2
- package/esm2015/src/util/char_code.js +1 -1
- package/esm2015/src/version.js +1 -1
- package/fesm2015/core.js +1652 -1364
- package/fesm2015/core.js.map +1 -1
- package/fesm2015/testing.js +1 -1
- package/package.json +1 -1
- package/src/r3_symbols.d.ts +13 -1
- package/testing/testing.d.ts +1 -1
- package/testing.d.ts +1 -1
- package/esm2015/src/render3/i18n.js +0 -1225
|
@@ -1,1225 +0,0 @@
|
|
|
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 '../util/ng_i18n_closure_mode';
|
|
9
|
-
import { DEFAULT_LOCALE_ID, getPluralCase } from '../i18n/localization';
|
|
10
|
-
import { getTemplateContent, SRCSET_ATTRS, URI_ATTRS, VALID_ATTRS, VALID_ELEMENTS } from '../sanitization/html_sanitizer';
|
|
11
|
-
import { getInertBodyHelper } from '../sanitization/inert_body';
|
|
12
|
-
import { _sanitizeUrl, sanitizeSrcset } from '../sanitization/url_sanitizer';
|
|
13
|
-
import { addAllToArray } from '../util/array_utils';
|
|
14
|
-
import { assertDataInRange, assertDefined, assertEqual } from '../util/assert';
|
|
15
|
-
import { bindingUpdated } from './bindings';
|
|
16
|
-
import { attachPatchData } from './context_discovery';
|
|
17
|
-
import { setDelayProjection } from './instructions/all';
|
|
18
|
-
import { attachI18nOpCodesDebug } from './instructions/lview_debug';
|
|
19
|
-
import { allocExpando, elementAttributeInternal, elementPropertyInternal, getOrCreateTNode, setInputsForProperty, setNgReflectProperties, textBindingInternal } from './instructions/shared';
|
|
20
|
-
import { NATIVE } from './interfaces/container';
|
|
21
|
-
import { getDocument } from './interfaces/document';
|
|
22
|
-
import { COMMENT_MARKER, ELEMENT_MARKER } from './interfaces/i18n';
|
|
23
|
-
import { isLContainer } from './interfaces/type_checks';
|
|
24
|
-
import { HEADER_OFFSET, RENDERER, T_HOST } from './interfaces/view';
|
|
25
|
-
import { appendChild, applyProjection, createTextNode, nativeRemoveNode } from './node_manipulation';
|
|
26
|
-
import { getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, getTView, nextBindingIndex, setIsNotParent, setPreviousOrParentTNode } from './state';
|
|
27
|
-
import { renderStringify } from './util/misc_utils';
|
|
28
|
-
import { getNativeByIndex, getNativeByTNode, getTNode, load } from './util/view_utils';
|
|
29
|
-
const MARKER = `�`;
|
|
30
|
-
const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/;
|
|
31
|
-
const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
|
|
32
|
-
const PH_REGEXP = /�(\/?[#*!]\d+):?\d*�/gi;
|
|
33
|
-
const BINDING_REGEXP = /�(\d+):?\d*�/gi;
|
|
34
|
-
const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;
|
|
35
|
-
// i18nPostprocess consts
|
|
36
|
-
const ROOT_TEMPLATE_ID = 0;
|
|
37
|
-
const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/;
|
|
38
|
-
const PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g;
|
|
39
|
-
const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
|
|
40
|
-
const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
|
|
41
|
-
const PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g;
|
|
42
|
-
const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
|
|
43
|
-
const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
|
|
44
|
-
/**
|
|
45
|
-
* Breaks pattern into strings and top level {...} blocks.
|
|
46
|
-
* Can be used to break a message into text and ICU expressions, or to break an ICU expression into
|
|
47
|
-
* keys and cases.
|
|
48
|
-
* Original code from closure library, modified for Angular.
|
|
49
|
-
*
|
|
50
|
-
* @param pattern (sub)Pattern to be broken.
|
|
51
|
-
*
|
|
52
|
-
*/
|
|
53
|
-
function extractParts(pattern) {
|
|
54
|
-
if (!pattern) {
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
let prevPos = 0;
|
|
58
|
-
const braceStack = [];
|
|
59
|
-
const results = [];
|
|
60
|
-
const braces = /[{}]/g;
|
|
61
|
-
// lastIndex doesn't get set to 0 so we have to.
|
|
62
|
-
braces.lastIndex = 0;
|
|
63
|
-
let match;
|
|
64
|
-
while (match = braces.exec(pattern)) {
|
|
65
|
-
const pos = match.index;
|
|
66
|
-
if (match[0] == '}') {
|
|
67
|
-
braceStack.pop();
|
|
68
|
-
if (braceStack.length == 0) {
|
|
69
|
-
// End of the block.
|
|
70
|
-
const block = pattern.substring(prevPos, pos);
|
|
71
|
-
if (ICU_BLOCK_REGEXP.test(block)) {
|
|
72
|
-
results.push(parseICUBlock(block));
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
results.push(block);
|
|
76
|
-
}
|
|
77
|
-
prevPos = pos + 1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
if (braceStack.length == 0) {
|
|
82
|
-
const substring = pattern.substring(prevPos, pos);
|
|
83
|
-
results.push(substring);
|
|
84
|
-
prevPos = pos + 1;
|
|
85
|
-
}
|
|
86
|
-
braceStack.push('{');
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const substring = pattern.substring(prevPos);
|
|
90
|
-
results.push(substring);
|
|
91
|
-
return results;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Parses text containing an ICU expression and produces a JSON object for it.
|
|
95
|
-
* Original code from closure library, modified for Angular.
|
|
96
|
-
*
|
|
97
|
-
* @param pattern Text containing an ICU expression that needs to be parsed.
|
|
98
|
-
*
|
|
99
|
-
*/
|
|
100
|
-
function parseICUBlock(pattern) {
|
|
101
|
-
const cases = [];
|
|
102
|
-
const values = [];
|
|
103
|
-
let icuType = 1 /* plural */;
|
|
104
|
-
let mainBinding = 0;
|
|
105
|
-
pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) {
|
|
106
|
-
if (type === 'select') {
|
|
107
|
-
icuType = 0 /* select */;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
icuType = 1 /* plural */;
|
|
111
|
-
}
|
|
112
|
-
mainBinding = parseInt(binding.substr(1), 10);
|
|
113
|
-
return '';
|
|
114
|
-
});
|
|
115
|
-
const parts = extractParts(pattern);
|
|
116
|
-
// Looking for (key block)+ sequence. One of the keys has to be "other".
|
|
117
|
-
for (let pos = 0; pos < parts.length;) {
|
|
118
|
-
let key = parts[pos++].trim();
|
|
119
|
-
if (icuType === 1 /* plural */) {
|
|
120
|
-
// Key can be "=x", we just want "x"
|
|
121
|
-
key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1');
|
|
122
|
-
}
|
|
123
|
-
if (key.length) {
|
|
124
|
-
cases.push(key);
|
|
125
|
-
}
|
|
126
|
-
const blocks = extractParts(parts[pos++]);
|
|
127
|
-
if (cases.length > values.length) {
|
|
128
|
-
values.push(blocks);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
// TODO(ocombe): support ICU expressions in attributes, see #21615
|
|
132
|
-
return { type: icuType, mainBinding: mainBinding, cases, values };
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Removes everything inside the sub-templates of a message.
|
|
136
|
-
*/
|
|
137
|
-
function removeInnerTemplateTranslation(message) {
|
|
138
|
-
let match;
|
|
139
|
-
let res = '';
|
|
140
|
-
let index = 0;
|
|
141
|
-
let inTemplate = false;
|
|
142
|
-
let tagMatched;
|
|
143
|
-
while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) {
|
|
144
|
-
if (!inTemplate) {
|
|
145
|
-
res += message.substring(index, match.index + match[0].length);
|
|
146
|
-
tagMatched = match[1];
|
|
147
|
-
inTemplate = true;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) {
|
|
151
|
-
index = match.index;
|
|
152
|
-
inTemplate = false;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
ngDevMode &&
|
|
157
|
-
assertEqual(inTemplate, false, `Tag mismatch: unable to find the end of the sub-template in the translation "${message}"`);
|
|
158
|
-
res += message.substr(index);
|
|
159
|
-
return res;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Extracts a part of a message and removes the rest.
|
|
163
|
-
*
|
|
164
|
-
* This method is used for extracting a part of the message associated with a template. A translated
|
|
165
|
-
* message can span multiple templates.
|
|
166
|
-
*
|
|
167
|
-
* Example:
|
|
168
|
-
* ```
|
|
169
|
-
* <div i18n>Translate <span *ngIf>me</span>!</div>
|
|
170
|
-
* ```
|
|
171
|
-
*
|
|
172
|
-
* @param message The message to crop
|
|
173
|
-
* @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the
|
|
174
|
-
* external template and removes all sub-templates.
|
|
175
|
-
*/
|
|
176
|
-
export function getTranslationForTemplate(message, subTemplateIndex) {
|
|
177
|
-
if (isRootTemplateMessage(subTemplateIndex)) {
|
|
178
|
-
// We want the root template message, ignore all sub-templates
|
|
179
|
-
return removeInnerTemplateTranslation(message);
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
// We want a specific sub-template
|
|
183
|
-
const start = message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length;
|
|
184
|
-
const end = message.search(new RegExp(`${MARKER}\\/\\*\\d+:${subTemplateIndex}${MARKER}`));
|
|
185
|
-
return removeInnerTemplateTranslation(message.substring(start, end));
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Generate the OpCodes to update the bindings of a string.
|
|
190
|
-
*
|
|
191
|
-
* @param str The string containing the bindings.
|
|
192
|
-
* @param destinationNode Index of the destination node which will receive the binding.
|
|
193
|
-
* @param attrName Name of the attribute, if the string belongs to an attribute.
|
|
194
|
-
* @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary.
|
|
195
|
-
*/
|
|
196
|
-
function generateBindingUpdateOpCodes(str, destinationNode, attrName, sanitizeFn = null) {
|
|
197
|
-
const updateOpCodes = [null, null]; // Alloc space for mask and size
|
|
198
|
-
const textParts = str.split(BINDING_REGEXP);
|
|
199
|
-
let mask = 0;
|
|
200
|
-
for (let j = 0; j < textParts.length; j++) {
|
|
201
|
-
const textValue = textParts[j];
|
|
202
|
-
if (j & 1) {
|
|
203
|
-
// Odd indexes are bindings
|
|
204
|
-
const bindingIndex = parseInt(textValue, 10);
|
|
205
|
-
updateOpCodes.push(-1 - bindingIndex);
|
|
206
|
-
mask = mask | toMaskBit(bindingIndex);
|
|
207
|
-
}
|
|
208
|
-
else if (textValue !== '') {
|
|
209
|
-
// Even indexes are text
|
|
210
|
-
updateOpCodes.push(textValue);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
updateOpCodes.push(destinationNode << 2 /* SHIFT_REF */ |
|
|
214
|
-
(attrName ? 1 /* Attr */ : 0 /* Text */));
|
|
215
|
-
if (attrName) {
|
|
216
|
-
updateOpCodes.push(attrName, sanitizeFn);
|
|
217
|
-
}
|
|
218
|
-
updateOpCodes[0] = mask;
|
|
219
|
-
updateOpCodes[1] = updateOpCodes.length - 2;
|
|
220
|
-
return updateOpCodes;
|
|
221
|
-
}
|
|
222
|
-
function getBindingMask(icuExpression, mask = 0) {
|
|
223
|
-
mask = mask | toMaskBit(icuExpression.mainBinding);
|
|
224
|
-
let match;
|
|
225
|
-
for (let i = 0; i < icuExpression.values.length; i++) {
|
|
226
|
-
const valueArr = icuExpression.values[i];
|
|
227
|
-
for (let j = 0; j < valueArr.length; j++) {
|
|
228
|
-
const value = valueArr[j];
|
|
229
|
-
if (typeof value === 'string') {
|
|
230
|
-
while (match = BINDING_REGEXP.exec(value)) {
|
|
231
|
-
mask = mask | toMaskBit(parseInt(match[1], 10));
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
mask = getBindingMask(value, mask);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return mask;
|
|
240
|
-
}
|
|
241
|
-
const i18nIndexStack = [];
|
|
242
|
-
let i18nIndexStackPointer = -1;
|
|
243
|
-
/**
|
|
244
|
-
* Convert binding index to mask bit.
|
|
245
|
-
*
|
|
246
|
-
* Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make
|
|
247
|
-
* the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to have
|
|
248
|
-
* more than 32 bindings this will be hit very rarely. The downside of hitting this corner case is
|
|
249
|
-
* that we will execute binding code more often than necessary. (penalty of performance)
|
|
250
|
-
*/
|
|
251
|
-
function toMaskBit(bindingIndex) {
|
|
252
|
-
return 1 << Math.min(bindingIndex, 31);
|
|
253
|
-
}
|
|
254
|
-
const parentIndexStack = [];
|
|
255
|
-
/**
|
|
256
|
-
* Marks a block of text as translatable.
|
|
257
|
-
*
|
|
258
|
-
* The instructions `i18nStart` and `i18nEnd` mark the translation block in the template.
|
|
259
|
-
* The translation `message` is the value which is locale specific. The translation string may
|
|
260
|
-
* contain placeholders which associate inner elements and sub-templates within the translation.
|
|
261
|
-
*
|
|
262
|
-
* The translation `message` placeholders are:
|
|
263
|
-
* - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
|
|
264
|
-
* interpolated into. The placeholder `index` points to the expression binding index. An optional
|
|
265
|
-
* `block` that matches the sub-template in which it was declared.
|
|
266
|
-
* - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
|
|
267
|
-
* and end of DOM element that were embedded in the original translation block. The placeholder
|
|
268
|
-
* `index` points to the element index in the template instructions set. An optional `block` that
|
|
269
|
-
* matches the sub-template in which it was declared.
|
|
270
|
-
* - `�!{index}(:{block})�`/`�/!{index}(:{block})�`: *Projection Placeholder*: Marks the
|
|
271
|
-
* beginning and end of <ng-content> that was embedded in the original translation block.
|
|
272
|
-
* The placeholder `index` points to the element index in the template instructions set.
|
|
273
|
-
* An optional `block` that matches the sub-template in which it was declared.
|
|
274
|
-
* - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
|
|
275
|
-
* split up and translated separately in each angular template function. The `index` points to the
|
|
276
|
-
* `template` instruction index. A `block` that matches the sub-template in which it was declared.
|
|
277
|
-
*
|
|
278
|
-
* @param index A unique index of the translation in the static block.
|
|
279
|
-
* @param message The translation message.
|
|
280
|
-
* @param subTemplateIndex Optional sub-template index in the `message`.
|
|
281
|
-
*
|
|
282
|
-
* @codeGenApi
|
|
283
|
-
*/
|
|
284
|
-
export function ɵɵi18nStart(index, message, subTemplateIndex) {
|
|
285
|
-
const tView = getTView();
|
|
286
|
-
ngDevMode && assertDefined(tView, `tView should be defined`);
|
|
287
|
-
i18nIndexStack[++i18nIndexStackPointer] = index;
|
|
288
|
-
// We need to delay projections until `i18nEnd`
|
|
289
|
-
setDelayProjection(true);
|
|
290
|
-
if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
|
|
291
|
-
i18nStartFirstPass(getLView(), tView, index, message, subTemplateIndex);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
// Count for the number of vars that will be allocated for each i18n block.
|
|
295
|
-
// It is global because this is used in multiple functions that include loops and recursive calls.
|
|
296
|
-
// This is reset to 0 when `i18nStartFirstPass` is called.
|
|
297
|
-
let i18nVarsCount;
|
|
298
|
-
function allocNodeIndex(startIndex) {
|
|
299
|
-
return startIndex + i18nVarsCount++;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* See `i18nStart` above.
|
|
303
|
-
*/
|
|
304
|
-
function i18nStartFirstPass(lView, tView, index, message, subTemplateIndex) {
|
|
305
|
-
const startIndex = tView.blueprint.length - HEADER_OFFSET;
|
|
306
|
-
i18nVarsCount = 0;
|
|
307
|
-
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
308
|
-
const parentTNode = getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
|
|
309
|
-
let parentIndex = parentTNode && parentTNode !== lView[T_HOST] ? parentTNode.index - HEADER_OFFSET : index;
|
|
310
|
-
let parentIndexPointer = 0;
|
|
311
|
-
parentIndexStack[parentIndexPointer] = parentIndex;
|
|
312
|
-
const createOpCodes = [];
|
|
313
|
-
// If the previous node wasn't the direct parent then we have a translation without top level
|
|
314
|
-
// element and we need to keep a reference of the previous element if there is one. We should also
|
|
315
|
-
// keep track whether an element was a parent node or not, so that the logic that consumes
|
|
316
|
-
// the generated `I18nMutateOpCode`s can leverage this information to properly set TNode state
|
|
317
|
-
// (whether it's a parent or sibling).
|
|
318
|
-
if (index > 0 && previousOrParentTNode !== parentTNode) {
|
|
319
|
-
let previousTNodeIndex = previousOrParentTNode.index - HEADER_OFFSET;
|
|
320
|
-
// If current TNode is a sibling node, encode it using a negative index. This information is
|
|
321
|
-
// required when the `Select` action is processed (see the `readCreateOpCodes` function).
|
|
322
|
-
if (!getIsParent()) {
|
|
323
|
-
previousTNodeIndex = ~previousTNodeIndex;
|
|
324
|
-
}
|
|
325
|
-
// Create an OpCode to select the previous TNode
|
|
326
|
-
createOpCodes.push(previousTNodeIndex << 3 /* SHIFT_REF */ | 0 /* Select */);
|
|
327
|
-
}
|
|
328
|
-
const updateOpCodes = [];
|
|
329
|
-
const icuExpressions = [];
|
|
330
|
-
if (message === '' && isRootTemplateMessage(subTemplateIndex)) {
|
|
331
|
-
// If top level translation is an empty string, do not invoke additional processing
|
|
332
|
-
// and just create op codes for empty text node instead.
|
|
333
|
-
createOpCodes.push(message, allocNodeIndex(startIndex), parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
const templateTranslation = getTranslationForTemplate(message, subTemplateIndex);
|
|
337
|
-
const msgParts = replaceNgsp(templateTranslation).split(PH_REGEXP);
|
|
338
|
-
for (let i = 0; i < msgParts.length; i++) {
|
|
339
|
-
let value = msgParts[i];
|
|
340
|
-
if (i & 1) {
|
|
341
|
-
// Odd indexes are placeholders (elements and sub-templates)
|
|
342
|
-
if (value.charAt(0) === '/') {
|
|
343
|
-
// It is a closing tag
|
|
344
|
-
if (value.charAt(1) === "#" /* ELEMENT */) {
|
|
345
|
-
const phIndex = parseInt(value.substr(2), 10);
|
|
346
|
-
parentIndex = parentIndexStack[--parentIndexPointer];
|
|
347
|
-
createOpCodes.push(phIndex << 3 /* SHIFT_REF */ | 5 /* ElementEnd */);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
const phIndex = parseInt(value.substr(1), 10);
|
|
352
|
-
const isElement = value.charAt(0) === "#" /* ELEMENT */;
|
|
353
|
-
// The value represents a placeholder that we move to the designated index.
|
|
354
|
-
// Note: positive indicies indicate that a TNode with a given index should also be marked
|
|
355
|
-
// as parent while executing `Select` instruction.
|
|
356
|
-
createOpCodes.push((isElement ? phIndex : ~phIndex) << 3 /* SHIFT_REF */ |
|
|
357
|
-
0 /* Select */, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
358
|
-
if (isElement) {
|
|
359
|
-
parentIndexStack[++parentIndexPointer] = parentIndex = phIndex;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
// Even indexes are text (including bindings & ICU expressions)
|
|
365
|
-
const parts = extractParts(value);
|
|
366
|
-
for (let j = 0; j < parts.length; j++) {
|
|
367
|
-
if (j & 1) {
|
|
368
|
-
// Odd indexes are ICU expressions
|
|
369
|
-
const icuExpression = parts[j];
|
|
370
|
-
// Verify that ICU expression has the right shape. Translations might contain invalid
|
|
371
|
-
// constructions (while original messages were correct), so ICU parsing at runtime may
|
|
372
|
-
// not succeed (thus `icuExpression` remains a string).
|
|
373
|
-
if (typeof icuExpression !== 'object') {
|
|
374
|
-
throw new Error(`Unable to parse ICU expression in "${templateTranslation}" message.`);
|
|
375
|
-
}
|
|
376
|
-
// Create the comment node that will anchor the ICU expression
|
|
377
|
-
const icuNodeIndex = allocNodeIndex(startIndex);
|
|
378
|
-
createOpCodes.push(COMMENT_MARKER, ngDevMode ? `ICU ${icuNodeIndex}` : '', icuNodeIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
379
|
-
// Update codes for the ICU expression
|
|
380
|
-
const mask = getBindingMask(icuExpression);
|
|
381
|
-
icuStart(icuExpressions, icuExpression, icuNodeIndex, icuNodeIndex);
|
|
382
|
-
// Since this is recursive, the last TIcu that was pushed is the one we want
|
|
383
|
-
const tIcuIndex = icuExpressions.length - 1;
|
|
384
|
-
updateOpCodes.push(toMaskBit(icuExpression.mainBinding), // mask of the main binding
|
|
385
|
-
3, // skip 3 opCodes if not changed
|
|
386
|
-
-1 - icuExpression.mainBinding, icuNodeIndex << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */, tIcuIndex, mask, // mask of all the bindings of this ICU expression
|
|
387
|
-
2, // skip 2 opCodes if not changed
|
|
388
|
-
icuNodeIndex << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */, tIcuIndex);
|
|
389
|
-
}
|
|
390
|
-
else if (parts[j] !== '') {
|
|
391
|
-
const text = parts[j];
|
|
392
|
-
// Even indexes are text (including bindings)
|
|
393
|
-
const hasBinding = text.match(BINDING_REGEXP);
|
|
394
|
-
// Create text nodes
|
|
395
|
-
const textNodeIndex = allocNodeIndex(startIndex);
|
|
396
|
-
createOpCodes.push(
|
|
397
|
-
// If there is a binding, the value will be set during update
|
|
398
|
-
hasBinding ? '' : text, textNodeIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
399
|
-
if (hasBinding) {
|
|
400
|
-
addAllToArray(generateBindingUpdateOpCodes(text, textNodeIndex), updateOpCodes);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
if (i18nVarsCount > 0) {
|
|
408
|
-
allocExpando(tView, lView, i18nVarsCount);
|
|
409
|
-
}
|
|
410
|
-
ngDevMode &&
|
|
411
|
-
attachI18nOpCodesDebug(createOpCodes, updateOpCodes, icuExpressions.length ? icuExpressions : null, lView);
|
|
412
|
-
// NOTE: local var needed to properly assert the type of `TI18n`.
|
|
413
|
-
const tI18n = {
|
|
414
|
-
vars: i18nVarsCount,
|
|
415
|
-
create: createOpCodes,
|
|
416
|
-
update: updateOpCodes,
|
|
417
|
-
icus: icuExpressions.length ? icuExpressions : null,
|
|
418
|
-
};
|
|
419
|
-
tView.data[index + HEADER_OFFSET] = tI18n;
|
|
420
|
-
}
|
|
421
|
-
function appendI18nNode(tView, tNode, parentTNode, previousTNode, lView) {
|
|
422
|
-
ngDevMode && ngDevMode.rendererMoveNode++;
|
|
423
|
-
const nextNode = tNode.next;
|
|
424
|
-
if (!previousTNode) {
|
|
425
|
-
previousTNode = parentTNode;
|
|
426
|
-
}
|
|
427
|
-
// Re-organize node tree to put this node in the correct position.
|
|
428
|
-
if (previousTNode === parentTNode && tNode !== parentTNode.child) {
|
|
429
|
-
tNode.next = parentTNode.child;
|
|
430
|
-
parentTNode.child = tNode;
|
|
431
|
-
}
|
|
432
|
-
else if (previousTNode !== parentTNode && tNode !== previousTNode.next) {
|
|
433
|
-
tNode.next = previousTNode.next;
|
|
434
|
-
previousTNode.next = tNode;
|
|
435
|
-
}
|
|
436
|
-
else {
|
|
437
|
-
tNode.next = null;
|
|
438
|
-
}
|
|
439
|
-
if (parentTNode !== lView[T_HOST]) {
|
|
440
|
-
tNode.parent = parentTNode;
|
|
441
|
-
}
|
|
442
|
-
// If tNode was moved around, we might need to fix a broken link.
|
|
443
|
-
let cursor = tNode.next;
|
|
444
|
-
while (cursor) {
|
|
445
|
-
if (cursor.next === tNode) {
|
|
446
|
-
cursor.next = nextNode;
|
|
447
|
-
}
|
|
448
|
-
cursor = cursor.next;
|
|
449
|
-
}
|
|
450
|
-
// If the placeholder to append is a projection, we need to move the projected nodes instead
|
|
451
|
-
if (tNode.type === 1 /* Projection */) {
|
|
452
|
-
applyProjection(tView, lView, tNode);
|
|
453
|
-
return tNode;
|
|
454
|
-
}
|
|
455
|
-
appendChild(tView, lView, getNativeByTNode(tNode, lView), tNode);
|
|
456
|
-
const slotValue = lView[tNode.index];
|
|
457
|
-
if (tNode.type !== 0 /* Container */ && isLContainer(slotValue)) {
|
|
458
|
-
// Nodes that inject ViewContainerRef also have a comment node that should be moved
|
|
459
|
-
appendChild(tView, lView, slotValue[NATIVE], tNode);
|
|
460
|
-
}
|
|
461
|
-
return tNode;
|
|
462
|
-
}
|
|
463
|
-
function isRootTemplateMessage(subTemplateIndex) {
|
|
464
|
-
return subTemplateIndex === undefined;
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Handles message string post-processing for internationalization.
|
|
468
|
-
*
|
|
469
|
-
* Handles message string post-processing by transforming it from intermediate
|
|
470
|
-
* format (that might contain some markers that we need to replace) to the final
|
|
471
|
-
* form, consumable by i18nStart instruction. Post processing steps include:
|
|
472
|
-
*
|
|
473
|
-
* 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
|
|
474
|
-
* 2. Replace all ICU vars (like "VAR_PLURAL")
|
|
475
|
-
* 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
|
|
476
|
-
* 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
|
|
477
|
-
* in case multiple ICUs have the same placeholder name
|
|
478
|
-
*
|
|
479
|
-
* @param message Raw translation string for post processing
|
|
480
|
-
* @param replacements Set of replacements that should be applied
|
|
481
|
-
*
|
|
482
|
-
* @returns Transformed string that can be consumed by i18nStart instruction
|
|
483
|
-
*
|
|
484
|
-
* @codeGenApi
|
|
485
|
-
*/
|
|
486
|
-
export function ɵɵi18nPostprocess(message, replacements = {}) {
|
|
487
|
-
/**
|
|
488
|
-
* Step 1: resolve all multi-value placeholders like [�#5�|�*1:1��#2:1�|�#4:1�]
|
|
489
|
-
*
|
|
490
|
-
* Note: due to the way we process nested templates (BFS), multi-value placeholders are typically
|
|
491
|
-
* grouped by templates, for example: [�#5�|�#6�|�#1:1�|�#3:2�] where �#5� and �#6� belong to root
|
|
492
|
-
* template, �#1:1� belong to nested template with index 1 and �#1:2� - nested template with index
|
|
493
|
-
* 3. However in real templates the order might be different: i.e. �#1:1� and/or �#3:2� may go in
|
|
494
|
-
* front of �#6�. The post processing step restores the right order by keeping track of the
|
|
495
|
-
* template id stack and looks for placeholders that belong to the currently active template.
|
|
496
|
-
*/
|
|
497
|
-
let result = message;
|
|
498
|
-
if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) {
|
|
499
|
-
const matches = {};
|
|
500
|
-
const templateIdsStack = [ROOT_TEMPLATE_ID];
|
|
501
|
-
result = result.replace(PP_PLACEHOLDERS_REGEXP, (m, phs, tmpl) => {
|
|
502
|
-
const content = phs || tmpl;
|
|
503
|
-
const placeholders = matches[content] || [];
|
|
504
|
-
if (!placeholders.length) {
|
|
505
|
-
content.split('|').forEach((placeholder) => {
|
|
506
|
-
const match = placeholder.match(PP_TEMPLATE_ID_REGEXP);
|
|
507
|
-
const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID;
|
|
508
|
-
const isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder);
|
|
509
|
-
placeholders.push([templateId, isCloseTemplateTag, placeholder]);
|
|
510
|
-
});
|
|
511
|
-
matches[content] = placeholders;
|
|
512
|
-
}
|
|
513
|
-
if (!placeholders.length) {
|
|
514
|
-
throw new Error(`i18n postprocess: unmatched placeholder - ${content}`);
|
|
515
|
-
}
|
|
516
|
-
const currentTemplateId = templateIdsStack[templateIdsStack.length - 1];
|
|
517
|
-
let idx = 0;
|
|
518
|
-
// find placeholder index that matches current template id
|
|
519
|
-
for (let i = 0; i < placeholders.length; i++) {
|
|
520
|
-
if (placeholders[i][0] === currentTemplateId) {
|
|
521
|
-
idx = i;
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
// update template id stack based on the current tag extracted
|
|
526
|
-
const [templateId, isCloseTemplateTag, placeholder] = placeholders[idx];
|
|
527
|
-
if (isCloseTemplateTag) {
|
|
528
|
-
templateIdsStack.pop();
|
|
529
|
-
}
|
|
530
|
-
else if (currentTemplateId !== templateId) {
|
|
531
|
-
templateIdsStack.push(templateId);
|
|
532
|
-
}
|
|
533
|
-
// remove processed tag from the list
|
|
534
|
-
placeholders.splice(idx, 1);
|
|
535
|
-
return placeholder;
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
// return current result if no replacements specified
|
|
539
|
-
if (!Object.keys(replacements).length) {
|
|
540
|
-
return result;
|
|
541
|
-
}
|
|
542
|
-
/**
|
|
543
|
-
* Step 2: replace all ICU vars (like "VAR_PLURAL")
|
|
544
|
-
*/
|
|
545
|
-
result = result.replace(PP_ICU_VARS_REGEXP, (match, start, key, _type, _idx, end) => {
|
|
546
|
-
return replacements.hasOwnProperty(key) ? `${start}${replacements[key]}${end}` : match;
|
|
547
|
-
});
|
|
548
|
-
/**
|
|
549
|
-
* Step 3: replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
|
|
550
|
-
*/
|
|
551
|
-
result = result.replace(PP_ICU_PLACEHOLDERS_REGEXP, (match, key) => {
|
|
552
|
-
return replacements.hasOwnProperty(key) ? replacements[key] : match;
|
|
553
|
-
});
|
|
554
|
-
/**
|
|
555
|
-
* Step 4: replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) in case
|
|
556
|
-
* multiple ICUs have the same placeholder name
|
|
557
|
-
*/
|
|
558
|
-
result = result.replace(PP_ICUS_REGEXP, (match, key) => {
|
|
559
|
-
if (replacements.hasOwnProperty(key)) {
|
|
560
|
-
const list = replacements[key];
|
|
561
|
-
if (!list.length) {
|
|
562
|
-
throw new Error(`i18n postprocess: unmatched ICU - ${match} with key: ${key}`);
|
|
563
|
-
}
|
|
564
|
-
return list.shift();
|
|
565
|
-
}
|
|
566
|
-
return match;
|
|
567
|
-
});
|
|
568
|
-
return result;
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes
|
|
572
|
-
* into the render tree, moves the placeholder nodes and removes the deleted nodes.
|
|
573
|
-
*
|
|
574
|
-
* @codeGenApi
|
|
575
|
-
*/
|
|
576
|
-
export function ɵɵi18nEnd() {
|
|
577
|
-
const lView = getLView();
|
|
578
|
-
const tView = getTView();
|
|
579
|
-
ngDevMode && assertDefined(tView, `tView should be defined`);
|
|
580
|
-
i18nEndFirstPass(tView, lView);
|
|
581
|
-
// Stop delaying projections
|
|
582
|
-
setDelayProjection(false);
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* See `i18nEnd` above.
|
|
586
|
-
*/
|
|
587
|
-
function i18nEndFirstPass(tView, lView) {
|
|
588
|
-
ngDevMode &&
|
|
589
|
-
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'i18nEnd should be called before any binding');
|
|
590
|
-
const rootIndex = i18nIndexStack[i18nIndexStackPointer--];
|
|
591
|
-
const tI18n = tView.data[rootIndex + HEADER_OFFSET];
|
|
592
|
-
ngDevMode && assertDefined(tI18n, `You should call i18nStart before i18nEnd`);
|
|
593
|
-
// Find the last node that was added before `i18nEnd`
|
|
594
|
-
const lastCreatedNode = getPreviousOrParentTNode();
|
|
595
|
-
// Read the instructions to insert/move/remove DOM elements
|
|
596
|
-
const visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, tView, lView);
|
|
597
|
-
// Remove deleted nodes
|
|
598
|
-
let index = rootIndex + 1;
|
|
599
|
-
while (index <= lastCreatedNode.index - HEADER_OFFSET) {
|
|
600
|
-
if (visitedNodes.indexOf(index) === -1) {
|
|
601
|
-
removeNode(tView, lView, index, /* markAsDetached */ true);
|
|
602
|
-
}
|
|
603
|
-
// Check if an element has any local refs and skip them
|
|
604
|
-
const tNode = getTNode(tView, index);
|
|
605
|
-
if (tNode &&
|
|
606
|
-
(tNode.type === 0 /* Container */ || tNode.type === 3 /* Element */ ||
|
|
607
|
-
tNode.type === 4 /* ElementContainer */) &&
|
|
608
|
-
tNode.localNames !== null) {
|
|
609
|
-
// Divide by 2 to get the number of local refs,
|
|
610
|
-
// since they are stored as an array that also includes directive indexes,
|
|
611
|
-
// i.e. ["localRef", directiveIndex, ...]
|
|
612
|
-
index += tNode.localNames.length >> 1;
|
|
613
|
-
}
|
|
614
|
-
index++;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Creates and stores the dynamic TNode, and unhooks it from the tree for now.
|
|
619
|
-
*/
|
|
620
|
-
function createDynamicNodeAtIndex(tView, lView, index, type, native, name) {
|
|
621
|
-
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
622
|
-
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
|
|
623
|
-
lView[index + HEADER_OFFSET] = native;
|
|
624
|
-
const tNode = getOrCreateTNode(tView, lView[T_HOST], index, type, name, null);
|
|
625
|
-
// We are creating a dynamic node, the previous tNode might not be pointing at this node.
|
|
626
|
-
// We will link ourselves into the tree later with `appendI18nNode`.
|
|
627
|
-
if (previousOrParentTNode && previousOrParentTNode.next === tNode) {
|
|
628
|
-
previousOrParentTNode.next = null;
|
|
629
|
-
}
|
|
630
|
-
return tNode;
|
|
631
|
-
}
|
|
632
|
-
function readCreateOpCodes(index, createOpCodes, tView, lView) {
|
|
633
|
-
const renderer = lView[RENDERER];
|
|
634
|
-
let currentTNode = null;
|
|
635
|
-
let previousTNode = null;
|
|
636
|
-
const visitedNodes = [];
|
|
637
|
-
for (let i = 0; i < createOpCodes.length; i++) {
|
|
638
|
-
const opCode = createOpCodes[i];
|
|
639
|
-
if (typeof opCode == 'string') {
|
|
640
|
-
const textRNode = createTextNode(opCode, renderer);
|
|
641
|
-
const textNodeIndex = createOpCodes[++i];
|
|
642
|
-
ngDevMode && ngDevMode.rendererCreateTextNode++;
|
|
643
|
-
previousTNode = currentTNode;
|
|
644
|
-
currentTNode =
|
|
645
|
-
createDynamicNodeAtIndex(tView, lView, textNodeIndex, 3 /* Element */, textRNode, null);
|
|
646
|
-
visitedNodes.push(textNodeIndex);
|
|
647
|
-
setIsNotParent();
|
|
648
|
-
}
|
|
649
|
-
else if (typeof opCode == 'number') {
|
|
650
|
-
switch (opCode & 7 /* MASK_OPCODE */) {
|
|
651
|
-
case 1 /* AppendChild */:
|
|
652
|
-
const destinationNodeIndex = opCode >>> 17 /* SHIFT_PARENT */;
|
|
653
|
-
let destinationTNode;
|
|
654
|
-
if (destinationNodeIndex === index) {
|
|
655
|
-
// If the destination node is `i18nStart`, we don't have a
|
|
656
|
-
// top-level node and we should use the host node instead
|
|
657
|
-
destinationTNode = lView[T_HOST];
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
destinationTNode = getTNode(tView, destinationNodeIndex);
|
|
661
|
-
}
|
|
662
|
-
ngDevMode &&
|
|
663
|
-
assertDefined(currentTNode, `You need to create or select a node before you can insert it into the DOM`);
|
|
664
|
-
previousTNode =
|
|
665
|
-
appendI18nNode(tView, currentTNode, destinationTNode, previousTNode, lView);
|
|
666
|
-
break;
|
|
667
|
-
case 0 /* Select */:
|
|
668
|
-
// Negative indicies indicate that a given TNode is a sibling node, not a parent node
|
|
669
|
-
// (see `i18nStartFirstPass` for additional information).
|
|
670
|
-
const isParent = opCode >= 0;
|
|
671
|
-
const nodeIndex = (isParent ? opCode : ~opCode) >>> 3 /* SHIFT_REF */;
|
|
672
|
-
visitedNodes.push(nodeIndex);
|
|
673
|
-
previousTNode = currentTNode;
|
|
674
|
-
currentTNode = getTNode(tView, nodeIndex);
|
|
675
|
-
if (currentTNode) {
|
|
676
|
-
setPreviousOrParentTNode(currentTNode, isParent);
|
|
677
|
-
}
|
|
678
|
-
break;
|
|
679
|
-
case 5 /* ElementEnd */:
|
|
680
|
-
const elementIndex = opCode >>> 3 /* SHIFT_REF */;
|
|
681
|
-
previousTNode = currentTNode = getTNode(tView, elementIndex);
|
|
682
|
-
setPreviousOrParentTNode(currentTNode, false);
|
|
683
|
-
break;
|
|
684
|
-
case 4 /* Attr */:
|
|
685
|
-
const elementNodeIndex = opCode >>> 3 /* SHIFT_REF */;
|
|
686
|
-
const attrName = createOpCodes[++i];
|
|
687
|
-
const attrValue = createOpCodes[++i];
|
|
688
|
-
// This code is used for ICU expressions only, since we don't support
|
|
689
|
-
// directives/components in ICUs, we don't need to worry about inputs here
|
|
690
|
-
elementAttributeInternal(getTNode(tView, elementNodeIndex), lView, attrName, attrValue, null, null);
|
|
691
|
-
break;
|
|
692
|
-
default:
|
|
693
|
-
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
else {
|
|
697
|
-
switch (opCode) {
|
|
698
|
-
case COMMENT_MARKER:
|
|
699
|
-
const commentValue = createOpCodes[++i];
|
|
700
|
-
const commentNodeIndex = createOpCodes[++i];
|
|
701
|
-
ngDevMode &&
|
|
702
|
-
assertEqual(typeof commentValue, 'string', `Expected "${commentValue}" to be a comment node value`);
|
|
703
|
-
const commentRNode = renderer.createComment(commentValue);
|
|
704
|
-
ngDevMode && ngDevMode.rendererCreateComment++;
|
|
705
|
-
previousTNode = currentTNode;
|
|
706
|
-
currentTNode = createDynamicNodeAtIndex(tView, lView, commentNodeIndex, 5 /* IcuContainer */, commentRNode, null);
|
|
707
|
-
visitedNodes.push(commentNodeIndex);
|
|
708
|
-
attachPatchData(commentRNode, lView);
|
|
709
|
-
currentTNode.activeCaseIndex = null;
|
|
710
|
-
// We will add the case nodes later, during the update phase
|
|
711
|
-
setIsNotParent();
|
|
712
|
-
break;
|
|
713
|
-
case ELEMENT_MARKER:
|
|
714
|
-
const tagNameValue = createOpCodes[++i];
|
|
715
|
-
const elementNodeIndex = createOpCodes[++i];
|
|
716
|
-
ngDevMode &&
|
|
717
|
-
assertEqual(typeof tagNameValue, 'string', `Expected "${tagNameValue}" to be an element node tag name`);
|
|
718
|
-
const elementRNode = renderer.createElement(tagNameValue);
|
|
719
|
-
ngDevMode && ngDevMode.rendererCreateElement++;
|
|
720
|
-
previousTNode = currentTNode;
|
|
721
|
-
currentTNode = createDynamicNodeAtIndex(tView, lView, elementNodeIndex, 3 /* Element */, elementRNode, tagNameValue);
|
|
722
|
-
visitedNodes.push(elementNodeIndex);
|
|
723
|
-
break;
|
|
724
|
-
default:
|
|
725
|
-
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
setIsNotParent();
|
|
730
|
-
return visitedNodes;
|
|
731
|
-
}
|
|
732
|
-
function readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, tView, lView, bypassCheckBit = false) {
|
|
733
|
-
let caseCreated = false;
|
|
734
|
-
for (let i = 0; i < updateOpCodes.length; i++) {
|
|
735
|
-
// bit code to check if we should apply the next update
|
|
736
|
-
const checkBit = updateOpCodes[i];
|
|
737
|
-
// Number of opCodes to skip until next set of update codes
|
|
738
|
-
const skipCodes = updateOpCodes[++i];
|
|
739
|
-
if (bypassCheckBit || (checkBit & changeMask)) {
|
|
740
|
-
// The value has been updated since last checked
|
|
741
|
-
let value = '';
|
|
742
|
-
for (let j = i + 1; j <= (i + skipCodes); j++) {
|
|
743
|
-
const opCode = updateOpCodes[j];
|
|
744
|
-
if (typeof opCode == 'string') {
|
|
745
|
-
value += opCode;
|
|
746
|
-
}
|
|
747
|
-
else if (typeof opCode == 'number') {
|
|
748
|
-
if (opCode < 0) {
|
|
749
|
-
// It's a binding index whose value is negative
|
|
750
|
-
value += renderStringify(lView[bindingsStartIndex - opCode]);
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
const nodeIndex = opCode >>> 2 /* SHIFT_REF */;
|
|
754
|
-
let tIcuIndex;
|
|
755
|
-
let tIcu;
|
|
756
|
-
let icuTNode;
|
|
757
|
-
switch (opCode & 3 /* MASK_OPCODE */) {
|
|
758
|
-
case 1 /* Attr */:
|
|
759
|
-
const propName = updateOpCodes[++j];
|
|
760
|
-
const sanitizeFn = updateOpCodes[++j];
|
|
761
|
-
elementPropertyInternal(tView, getTNode(tView, nodeIndex), lView, propName, value, lView[RENDERER], sanitizeFn, false);
|
|
762
|
-
break;
|
|
763
|
-
case 0 /* Text */:
|
|
764
|
-
textBindingInternal(lView, nodeIndex, value);
|
|
765
|
-
break;
|
|
766
|
-
case 2 /* IcuSwitch */:
|
|
767
|
-
tIcuIndex = updateOpCodes[++j];
|
|
768
|
-
tIcu = icus[tIcuIndex];
|
|
769
|
-
icuTNode = getTNode(tView, nodeIndex);
|
|
770
|
-
// If there is an active case, delete the old nodes
|
|
771
|
-
if (icuTNode.activeCaseIndex !== null) {
|
|
772
|
-
const removeCodes = tIcu.remove[icuTNode.activeCaseIndex];
|
|
773
|
-
for (let k = 0; k < removeCodes.length; k++) {
|
|
774
|
-
const removeOpCode = removeCodes[k];
|
|
775
|
-
switch (removeOpCode & 7 /* MASK_OPCODE */) {
|
|
776
|
-
case 3 /* Remove */:
|
|
777
|
-
const nodeIndex = removeOpCode >>> 3 /* SHIFT_REF */;
|
|
778
|
-
// Remove DOM element, but do *not* mark TNode as detached, since we are
|
|
779
|
-
// just switching ICU cases (while keeping the same TNode), so a DOM element
|
|
780
|
-
// representing a new ICU case will be re-created.
|
|
781
|
-
removeNode(tView, lView, nodeIndex, /* markAsDetached */ false);
|
|
782
|
-
break;
|
|
783
|
-
case 6 /* RemoveNestedIcu */:
|
|
784
|
-
const nestedIcuNodeIndex = removeCodes[k + 1] >>> 3 /* SHIFT_REF */;
|
|
785
|
-
const nestedIcuTNode = getTNode(tView, nestedIcuNodeIndex);
|
|
786
|
-
const activeIndex = nestedIcuTNode.activeCaseIndex;
|
|
787
|
-
if (activeIndex !== null) {
|
|
788
|
-
const nestedIcuTIndex = removeOpCode >>> 3 /* SHIFT_REF */;
|
|
789
|
-
const nestedTIcu = icus[nestedIcuTIndex];
|
|
790
|
-
addAllToArray(nestedTIcu.remove[activeIndex], removeCodes);
|
|
791
|
-
}
|
|
792
|
-
break;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
// Update the active caseIndex
|
|
797
|
-
const caseIndex = getCaseIndex(tIcu, value);
|
|
798
|
-
icuTNode.activeCaseIndex = caseIndex !== -1 ? caseIndex : null;
|
|
799
|
-
if (caseIndex > -1) {
|
|
800
|
-
// Add the nodes for the new case
|
|
801
|
-
readCreateOpCodes(-1, tIcu.create[caseIndex], tView, lView);
|
|
802
|
-
caseCreated = true;
|
|
803
|
-
}
|
|
804
|
-
break;
|
|
805
|
-
case 3 /* IcuUpdate */:
|
|
806
|
-
tIcuIndex = updateOpCodes[++j];
|
|
807
|
-
tIcu = icus[tIcuIndex];
|
|
808
|
-
icuTNode = getTNode(tView, nodeIndex);
|
|
809
|
-
if (icuTNode.activeCaseIndex !== null) {
|
|
810
|
-
readUpdateOpCodes(tIcu.update[icuTNode.activeCaseIndex], icus, bindingsStartIndex, changeMask, tView, lView, caseCreated);
|
|
811
|
-
}
|
|
812
|
-
break;
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
i += skipCodes;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
function removeNode(tView, lView, index, markAsDetached) {
|
|
822
|
-
const removedPhTNode = getTNode(tView, index);
|
|
823
|
-
const removedPhRNode = getNativeByIndex(index, lView);
|
|
824
|
-
if (removedPhRNode) {
|
|
825
|
-
nativeRemoveNode(lView[RENDERER], removedPhRNode);
|
|
826
|
-
}
|
|
827
|
-
const slotValue = load(lView, index);
|
|
828
|
-
if (isLContainer(slotValue)) {
|
|
829
|
-
const lContainer = slotValue;
|
|
830
|
-
if (removedPhTNode.type !== 0 /* Container */) {
|
|
831
|
-
nativeRemoveNode(lView[RENDERER], lContainer[NATIVE]);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
if (markAsDetached) {
|
|
835
|
-
// Define this node as detached to avoid projecting it later
|
|
836
|
-
removedPhTNode.flags |= 64 /* isDetached */;
|
|
837
|
-
}
|
|
838
|
-
ngDevMode && ngDevMode.rendererRemoveNode++;
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
*
|
|
842
|
-
* Use this instruction to create a translation block that doesn't contain any placeholder.
|
|
843
|
-
* It calls both {@link i18nStart} and {@link i18nEnd} in one instruction.
|
|
844
|
-
*
|
|
845
|
-
* The translation `message` is the value which is locale specific. The translation string may
|
|
846
|
-
* contain placeholders which associate inner elements and sub-templates within the translation.
|
|
847
|
-
*
|
|
848
|
-
* The translation `message` placeholders are:
|
|
849
|
-
* - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
|
|
850
|
-
* interpolated into. The placeholder `index` points to the expression binding index. An optional
|
|
851
|
-
* `block` that matches the sub-template in which it was declared.
|
|
852
|
-
* - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
|
|
853
|
-
* and end of DOM element that were embedded in the original translation block. The placeholder
|
|
854
|
-
* `index` points to the element index in the template instructions set. An optional `block` that
|
|
855
|
-
* matches the sub-template in which it was declared.
|
|
856
|
-
* - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
|
|
857
|
-
* split up and translated separately in each angular template function. The `index` points to the
|
|
858
|
-
* `template` instruction index. A `block` that matches the sub-template in which it was declared.
|
|
859
|
-
*
|
|
860
|
-
* @param index A unique index of the translation in the static block.
|
|
861
|
-
* @param message The translation message.
|
|
862
|
-
* @param subTemplateIndex Optional sub-template index in the `message`.
|
|
863
|
-
*
|
|
864
|
-
* @codeGenApi
|
|
865
|
-
*/
|
|
866
|
-
export function ɵɵi18n(index, message, subTemplateIndex) {
|
|
867
|
-
ɵɵi18nStart(index, message, subTemplateIndex);
|
|
868
|
-
ɵɵi18nEnd();
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* Marks a list of attributes as translatable.
|
|
872
|
-
*
|
|
873
|
-
* @param index A unique index in the static block
|
|
874
|
-
* @param values
|
|
875
|
-
*
|
|
876
|
-
* @codeGenApi
|
|
877
|
-
*/
|
|
878
|
-
export function ɵɵi18nAttributes(index, values) {
|
|
879
|
-
const lView = getLView();
|
|
880
|
-
const tView = getTView();
|
|
881
|
-
ngDevMode && assertDefined(tView, `tView should be defined`);
|
|
882
|
-
i18nAttributesFirstPass(lView, tView, index, values);
|
|
883
|
-
}
|
|
884
|
-
/**
|
|
885
|
-
* See `i18nAttributes` above.
|
|
886
|
-
*/
|
|
887
|
-
function i18nAttributesFirstPass(lView, tView, index, values) {
|
|
888
|
-
const previousElement = getPreviousOrParentTNode();
|
|
889
|
-
const previousElementIndex = previousElement.index - HEADER_OFFSET;
|
|
890
|
-
const updateOpCodes = [];
|
|
891
|
-
for (let i = 0; i < values.length; i += 2) {
|
|
892
|
-
const attrName = values[i];
|
|
893
|
-
const message = values[i + 1];
|
|
894
|
-
const parts = message.split(ICU_REGEXP);
|
|
895
|
-
for (let j = 0; j < parts.length; j++) {
|
|
896
|
-
const value = parts[j];
|
|
897
|
-
if (j & 1) {
|
|
898
|
-
// Odd indexes are ICU expressions
|
|
899
|
-
// TODO(ocombe): support ICU expressions in attributes
|
|
900
|
-
throw new Error('ICU expressions are not yet supported in attributes');
|
|
901
|
-
}
|
|
902
|
-
else if (value !== '') {
|
|
903
|
-
// Even indexes are text (including bindings)
|
|
904
|
-
const hasBinding = !!value.match(BINDING_REGEXP);
|
|
905
|
-
if (hasBinding) {
|
|
906
|
-
if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
|
|
907
|
-
addAllToArray(generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes);
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
else {
|
|
911
|
-
const tNode = getTNode(tView, previousElementIndex);
|
|
912
|
-
// Set attributes for Elements only, for other types (like ElementContainer),
|
|
913
|
-
// only set inputs below
|
|
914
|
-
if (tNode.type === 3 /* Element */) {
|
|
915
|
-
elementAttributeInternal(tNode, lView, attrName, value, null, null);
|
|
916
|
-
}
|
|
917
|
-
// Check if that attribute is a directive input
|
|
918
|
-
const dataValue = tNode.inputs !== null && tNode.inputs[attrName];
|
|
919
|
-
if (dataValue) {
|
|
920
|
-
setInputsForProperty(tView, lView, dataValue, attrName, value);
|
|
921
|
-
if (ngDevMode) {
|
|
922
|
-
const element = getNativeByIndex(previousElementIndex, lView);
|
|
923
|
-
setNgReflectProperties(lView, element, tNode.type, dataValue, value);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
|
|
931
|
-
tView.data[index + HEADER_OFFSET] = updateOpCodes;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
let changeMask = 0b0;
|
|
935
|
-
let shiftsCounter = 0;
|
|
936
|
-
/**
|
|
937
|
-
* Stores the values of the bindings during each update cycle in order to determine if we need to
|
|
938
|
-
* update the translated nodes.
|
|
939
|
-
*
|
|
940
|
-
* @param value The binding's value
|
|
941
|
-
* @returns This function returns itself so that it may be chained
|
|
942
|
-
* (e.g. `i18nExp(ctx.name)(ctx.title)`)
|
|
943
|
-
*
|
|
944
|
-
* @codeGenApi
|
|
945
|
-
*/
|
|
946
|
-
export function ɵɵi18nExp(value) {
|
|
947
|
-
const lView = getLView();
|
|
948
|
-
if (bindingUpdated(lView, nextBindingIndex(), value)) {
|
|
949
|
-
changeMask = changeMask | (1 << shiftsCounter);
|
|
950
|
-
}
|
|
951
|
-
shiftsCounter++;
|
|
952
|
-
return ɵɵi18nExp;
|
|
953
|
-
}
|
|
954
|
-
/**
|
|
955
|
-
* Updates a translation block or an i18n attribute when the bindings have changed.
|
|
956
|
-
*
|
|
957
|
-
* @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes}
|
|
958
|
-
* (i18n attribute) on which it should update the content.
|
|
959
|
-
*
|
|
960
|
-
* @codeGenApi
|
|
961
|
-
*/
|
|
962
|
-
export function ɵɵi18nApply(index) {
|
|
963
|
-
if (shiftsCounter) {
|
|
964
|
-
const tView = getTView();
|
|
965
|
-
ngDevMode && assertDefined(tView, `tView should be defined`);
|
|
966
|
-
const tI18n = tView.data[index + HEADER_OFFSET];
|
|
967
|
-
let updateOpCodes;
|
|
968
|
-
let icus = null;
|
|
969
|
-
if (Array.isArray(tI18n)) {
|
|
970
|
-
updateOpCodes = tI18n;
|
|
971
|
-
}
|
|
972
|
-
else {
|
|
973
|
-
updateOpCodes = tI18n.update;
|
|
974
|
-
icus = tI18n.icus;
|
|
975
|
-
}
|
|
976
|
-
const bindingsStartIndex = getBindingIndex() - shiftsCounter - 1;
|
|
977
|
-
const lView = getLView();
|
|
978
|
-
readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, tView, lView);
|
|
979
|
-
// Reset changeMask & maskBit to default for the next update cycle
|
|
980
|
-
changeMask = 0b0;
|
|
981
|
-
shiftsCounter = 0;
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
/**
|
|
985
|
-
* Returns the index of the current case of an ICU expression depending on the main binding value
|
|
986
|
-
*
|
|
987
|
-
* @param icuExpression
|
|
988
|
-
* @param bindingValue The value of the main binding used by this ICU expression
|
|
989
|
-
*/
|
|
990
|
-
function getCaseIndex(icuExpression, bindingValue) {
|
|
991
|
-
let index = icuExpression.cases.indexOf(bindingValue);
|
|
992
|
-
if (index === -1) {
|
|
993
|
-
switch (icuExpression.type) {
|
|
994
|
-
case 1 /* plural */: {
|
|
995
|
-
const resolvedCase = getPluralCase(bindingValue, getLocaleId());
|
|
996
|
-
index = icuExpression.cases.indexOf(resolvedCase);
|
|
997
|
-
if (index === -1 && resolvedCase !== 'other') {
|
|
998
|
-
index = icuExpression.cases.indexOf('other');
|
|
999
|
-
}
|
|
1000
|
-
break;
|
|
1001
|
-
}
|
|
1002
|
-
case 0 /* select */: {
|
|
1003
|
-
index = icuExpression.cases.indexOf('other');
|
|
1004
|
-
break;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
return index;
|
|
1009
|
-
}
|
|
1010
|
-
/**
|
|
1011
|
-
* Generate the OpCodes for ICU expressions.
|
|
1012
|
-
*
|
|
1013
|
-
* @param tIcus
|
|
1014
|
-
* @param icuExpression
|
|
1015
|
-
* @param startIndex
|
|
1016
|
-
* @param expandoStartIndex
|
|
1017
|
-
*/
|
|
1018
|
-
function icuStart(tIcus, icuExpression, startIndex, expandoStartIndex) {
|
|
1019
|
-
const createCodes = [];
|
|
1020
|
-
const removeCodes = [];
|
|
1021
|
-
const updateCodes = [];
|
|
1022
|
-
const vars = [];
|
|
1023
|
-
const childIcus = [];
|
|
1024
|
-
for (let i = 0; i < icuExpression.values.length; i++) {
|
|
1025
|
-
// Each value is an array of strings & other ICU expressions
|
|
1026
|
-
const valueArr = icuExpression.values[i];
|
|
1027
|
-
const nestedIcus = [];
|
|
1028
|
-
for (let j = 0; j < valueArr.length; j++) {
|
|
1029
|
-
const value = valueArr[j];
|
|
1030
|
-
if (typeof value !== 'string') {
|
|
1031
|
-
// It is an nested ICU expression
|
|
1032
|
-
const icuIndex = nestedIcus.push(value) - 1;
|
|
1033
|
-
// Replace nested ICU expression by a comment node
|
|
1034
|
-
valueArr[j] = `<!--�${icuIndex}�-->`;
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
const icuCase = parseIcuCase(valueArr.join(''), startIndex, nestedIcus, tIcus, expandoStartIndex);
|
|
1038
|
-
createCodes.push(icuCase.create);
|
|
1039
|
-
removeCodes.push(icuCase.remove);
|
|
1040
|
-
updateCodes.push(icuCase.update);
|
|
1041
|
-
vars.push(icuCase.vars);
|
|
1042
|
-
childIcus.push(icuCase.childIcus);
|
|
1043
|
-
}
|
|
1044
|
-
const tIcu = {
|
|
1045
|
-
type: icuExpression.type,
|
|
1046
|
-
vars,
|
|
1047
|
-
childIcus,
|
|
1048
|
-
cases: icuExpression.cases,
|
|
1049
|
-
create: createCodes,
|
|
1050
|
-
remove: removeCodes,
|
|
1051
|
-
update: updateCodes
|
|
1052
|
-
};
|
|
1053
|
-
tIcus.push(tIcu);
|
|
1054
|
-
// Adding the maximum possible of vars needed (based on the cases with the most vars)
|
|
1055
|
-
i18nVarsCount += Math.max(...vars);
|
|
1056
|
-
}
|
|
1057
|
-
/**
|
|
1058
|
-
* Transforms a string template into an HTML template and a list of instructions used to update
|
|
1059
|
-
* attributes or nodes that contain bindings.
|
|
1060
|
-
*
|
|
1061
|
-
* @param unsafeHtml The string to parse
|
|
1062
|
-
* @param parentIndex
|
|
1063
|
-
* @param nestedIcus
|
|
1064
|
-
* @param tIcus
|
|
1065
|
-
* @param expandoStartIndex
|
|
1066
|
-
*/
|
|
1067
|
-
function parseIcuCase(unsafeHtml, parentIndex, nestedIcus, tIcus, expandoStartIndex) {
|
|
1068
|
-
const inertBodyHelper = getInertBodyHelper(getDocument());
|
|
1069
|
-
const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
|
|
1070
|
-
if (!inertBodyElement) {
|
|
1071
|
-
throw new Error('Unable to generate inert body element');
|
|
1072
|
-
}
|
|
1073
|
-
const wrapper = getTemplateContent(inertBodyElement) || inertBodyElement;
|
|
1074
|
-
const opCodes = { vars: 0, childIcus: [], create: [], remove: [], update: [] };
|
|
1075
|
-
parseNodes(wrapper.firstChild, opCodes, parentIndex, nestedIcus, tIcus, expandoStartIndex);
|
|
1076
|
-
return opCodes;
|
|
1077
|
-
}
|
|
1078
|
-
const NESTED_ICU = /�(\d+)�/;
|
|
1079
|
-
/**
|
|
1080
|
-
* Parses a node, its children and its siblings, and generates the mutate & update OpCodes.
|
|
1081
|
-
*
|
|
1082
|
-
* @param currentNode The first node to parse
|
|
1083
|
-
* @param icuCase The data for the ICU expression case that contains those nodes
|
|
1084
|
-
* @param parentIndex Index of the current node's parent
|
|
1085
|
-
* @param nestedIcus Data for the nested ICU expressions that this case contains
|
|
1086
|
-
* @param tIcus Data for all ICU expressions of the current message
|
|
1087
|
-
* @param expandoStartIndex Expando start index for the current ICU expression
|
|
1088
|
-
*/
|
|
1089
|
-
function parseNodes(currentNode, icuCase, parentIndex, nestedIcus, tIcus, expandoStartIndex) {
|
|
1090
|
-
if (currentNode) {
|
|
1091
|
-
const nestedIcusToCreate = [];
|
|
1092
|
-
while (currentNode) {
|
|
1093
|
-
const nextNode = currentNode.nextSibling;
|
|
1094
|
-
const newIndex = expandoStartIndex + ++icuCase.vars;
|
|
1095
|
-
switch (currentNode.nodeType) {
|
|
1096
|
-
case Node.ELEMENT_NODE:
|
|
1097
|
-
const element = currentNode;
|
|
1098
|
-
const tagName = element.tagName.toLowerCase();
|
|
1099
|
-
if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
|
|
1100
|
-
// This isn't a valid element, we won't create an element for it
|
|
1101
|
-
icuCase.vars--;
|
|
1102
|
-
}
|
|
1103
|
-
else {
|
|
1104
|
-
icuCase.create.push(ELEMENT_MARKER, tagName, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
1105
|
-
const elAttrs = element.attributes;
|
|
1106
|
-
for (let i = 0; i < elAttrs.length; i++) {
|
|
1107
|
-
const attr = elAttrs.item(i);
|
|
1108
|
-
const lowerAttrName = attr.name.toLowerCase();
|
|
1109
|
-
const hasBinding = !!attr.value.match(BINDING_REGEXP);
|
|
1110
|
-
// we assume the input string is safe, unless it's using a binding
|
|
1111
|
-
if (hasBinding) {
|
|
1112
|
-
if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
|
|
1113
|
-
if (URI_ATTRS[lowerAttrName]) {
|
|
1114
|
-
addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name, _sanitizeUrl), icuCase.update);
|
|
1115
|
-
}
|
|
1116
|
-
else if (SRCSET_ATTRS[lowerAttrName]) {
|
|
1117
|
-
addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name, sanitizeSrcset), icuCase.update);
|
|
1118
|
-
}
|
|
1119
|
-
else {
|
|
1120
|
-
addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name), icuCase.update);
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
else {
|
|
1124
|
-
ngDevMode &&
|
|
1125
|
-
console.warn(`WARNING: ignoring unsafe attribute value ${lowerAttrName} on element ${tagName} (see http://g.co/ng/security#xss)`);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
else {
|
|
1129
|
-
icuCase.create.push(newIndex << 3 /* SHIFT_REF */ | 4 /* Attr */, attr.name, attr.value);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
// Parse the children of this node (if any)
|
|
1133
|
-
parseNodes(currentNode.firstChild, icuCase, newIndex, nestedIcus, tIcus, expandoStartIndex);
|
|
1134
|
-
// Remove the parent node after the children
|
|
1135
|
-
icuCase.remove.push(newIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
|
|
1136
|
-
}
|
|
1137
|
-
break;
|
|
1138
|
-
case Node.TEXT_NODE:
|
|
1139
|
-
const value = currentNode.textContent || '';
|
|
1140
|
-
const hasBinding = value.match(BINDING_REGEXP);
|
|
1141
|
-
icuCase.create.push(hasBinding ? '' : value, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
1142
|
-
icuCase.remove.push(newIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
|
|
1143
|
-
if (hasBinding) {
|
|
1144
|
-
addAllToArray(generateBindingUpdateOpCodes(value, newIndex), icuCase.update);
|
|
1145
|
-
}
|
|
1146
|
-
break;
|
|
1147
|
-
case Node.COMMENT_NODE:
|
|
1148
|
-
// Check if the comment node is a placeholder for a nested ICU
|
|
1149
|
-
const match = NESTED_ICU.exec(currentNode.textContent || '');
|
|
1150
|
-
if (match) {
|
|
1151
|
-
const nestedIcuIndex = parseInt(match[1], 10);
|
|
1152
|
-
const newLocal = ngDevMode ? `nested ICU ${nestedIcuIndex}` : '';
|
|
1153
|
-
// Create the comment node that will anchor the ICU expression
|
|
1154
|
-
icuCase.create.push(COMMENT_MARKER, newLocal, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
|
|
1155
|
-
const nestedIcu = nestedIcus[nestedIcuIndex];
|
|
1156
|
-
nestedIcusToCreate.push([nestedIcu, newIndex]);
|
|
1157
|
-
}
|
|
1158
|
-
else {
|
|
1159
|
-
// We do not handle any other type of comment
|
|
1160
|
-
icuCase.vars--;
|
|
1161
|
-
}
|
|
1162
|
-
break;
|
|
1163
|
-
default:
|
|
1164
|
-
// We do not handle any other type of element
|
|
1165
|
-
icuCase.vars--;
|
|
1166
|
-
}
|
|
1167
|
-
currentNode = nextNode;
|
|
1168
|
-
}
|
|
1169
|
-
for (let i = 0; i < nestedIcusToCreate.length; i++) {
|
|
1170
|
-
const nestedIcu = nestedIcusToCreate[i][0];
|
|
1171
|
-
const nestedIcuNodeIndex = nestedIcusToCreate[i][1];
|
|
1172
|
-
icuStart(tIcus, nestedIcu, nestedIcuNodeIndex, expandoStartIndex + icuCase.vars);
|
|
1173
|
-
// Since this is recursive, the last TIcu that was pushed is the one we want
|
|
1174
|
-
const nestTIcuIndex = tIcus.length - 1;
|
|
1175
|
-
icuCase.vars += Math.max(...tIcus[nestTIcuIndex].vars);
|
|
1176
|
-
icuCase.childIcus.push(nestTIcuIndex);
|
|
1177
|
-
const mask = getBindingMask(nestedIcu);
|
|
1178
|
-
icuCase.update.push(toMaskBit(nestedIcu.mainBinding), // mask of the main binding
|
|
1179
|
-
3, // skip 3 opCodes if not changed
|
|
1180
|
-
-1 - nestedIcu.mainBinding, nestedIcuNodeIndex << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */, nestTIcuIndex, mask, // mask of all the bindings of this ICU expression
|
|
1181
|
-
2, // skip 2 opCodes if not changed
|
|
1182
|
-
nestedIcuNodeIndex << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */, nestTIcuIndex);
|
|
1183
|
-
icuCase.remove.push(nestTIcuIndex << 3 /* SHIFT_REF */ | 6 /* RemoveNestedIcu */, nestedIcuNodeIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
/**
|
|
1188
|
-
* Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
|
|
1189
|
-
* https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
|
|
1190
|
-
* In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
|
|
1191
|
-
* and later on replaced by a space. We are re-implementing the same idea here, since translations
|
|
1192
|
-
* might contain this special character.
|
|
1193
|
-
*/
|
|
1194
|
-
const NGSP_UNICODE_REGEXP = /\uE500/g;
|
|
1195
|
-
function replaceNgsp(value) {
|
|
1196
|
-
return value.replace(NGSP_UNICODE_REGEXP, ' ');
|
|
1197
|
-
}
|
|
1198
|
-
/**
|
|
1199
|
-
* The locale id that the application is currently using (for translations and ICU expressions).
|
|
1200
|
-
* This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
|
|
1201
|
-
* but is now defined as a global value.
|
|
1202
|
-
*/
|
|
1203
|
-
let LOCALE_ID = DEFAULT_LOCALE_ID;
|
|
1204
|
-
/**
|
|
1205
|
-
* Sets the locale id that will be used for translations and ICU expressions.
|
|
1206
|
-
* This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
|
|
1207
|
-
* but is now defined as a global value.
|
|
1208
|
-
*
|
|
1209
|
-
* @param localeId
|
|
1210
|
-
*/
|
|
1211
|
-
export function setLocaleId(localeId) {
|
|
1212
|
-
assertDefined(localeId, `Expected localeId to be defined`);
|
|
1213
|
-
if (typeof localeId === 'string') {
|
|
1214
|
-
LOCALE_ID = localeId.toLowerCase().replace(/_/g, '-');
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
/**
|
|
1218
|
-
* Gets the locale id that will be used for translations and ICU expressions.
|
|
1219
|
-
* This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
|
|
1220
|
-
* but is now defined as a global value.
|
|
1221
|
-
*/
|
|
1222
|
-
export function getLocaleId() {
|
|
1223
|
-
return LOCALE_ID;
|
|
1224
|
-
}
|
|
1225
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaTE4bi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvcmUvc3JjL3JlbmRlcjMvaTE4bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFDSCxPQUFPLDhCQUE4QixDQUFDO0FBRXRDLE9BQU8sRUFBQyxpQkFBaUIsRUFBRSxhQUFhLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RSxPQUFPLEVBQUMsa0JBQWtCLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFDLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEgsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDOUQsT0FBTyxFQUFDLFlBQVksRUFBRSxjQUFjLEVBQUMsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRSxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFDLGlCQUFpQixFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU3RSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQzFDLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RCxPQUFPLEVBQUMsc0JBQXNCLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUNsRSxPQUFPLEVBQUMsWUFBWSxFQUFFLHdCQUF3QixFQUFFLHVCQUF1QixFQUFFLGdCQUFnQixFQUFFLG9CQUFvQixFQUFFLHNCQUFzQixFQUFFLG1CQUFtQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDM0wsT0FBTyxFQUFhLE1BQU0sRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzFELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNs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QUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFdBQVc7SUFDekIsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuaW1wb3J0ICcuLi91dGlsL25nX2kxOG5fY2xvc3VyZV9tb2RlJztcblxuaW1wb3J0IHtERUZBVUxUX0xPQ0FMRV9JRCwgZ2V0UGx1cmFsQ2FzZX0gZnJvbSAnLi4vaTE4bi9sb2NhbGl6YXRpb24nO1xuaW1wb3J0IHtnZXRUZW1wbGF0ZUNvbnRlbnQsIFNSQ1NFVF9BVFRSUywgVVJJX0FUVFJTLCBWQUxJRF9BVFRSUywgVkFMSURfRUxFTUVOVFN9IGZyb20gJy4uL3Nhbml0aXphdGlvbi9odG1sX3Nhbml0aXplcic7XG5pbXBvcnQge2dldEluZXJ0Qm9keUhlbHBlcn0gZnJvbSAnLi4vc2FuaXRpemF0aW9uL2luZXJ0X2JvZHknO1xuaW1wb3J0IHtfc2FuaXRpemVVcmwsIHNhbml0aXplU3Jjc2V0fSBmcm9tICcuLi9zYW5pdGl6YXRpb24vdXJsX3Nhbml0aXplcic7XG5pbXBvcnQge2FkZEFsbFRvQXJyYXl9IGZyb20gJy4uL3V0aWwvYXJyYXlfdXRpbHMnO1xuaW1wb3J0IHthc3NlcnREYXRhSW5SYW5nZSwgYXNzZXJ0RGVmaW5lZCwgYXNzZXJ0RXF1YWx9IGZyb20gJy4uL3V0aWwvYXNzZXJ0JztcblxuaW1wb3J0IHtiaW5kaW5nVXBkYXRlZH0gZnJvbSAnLi9iaW5kaW5ncyc7XG5pbXBvcnQge2F0dGFjaFBhdGNoRGF0YX0gZnJvbSAnLi9jb250ZXh0X2Rpc2NvdmVyeSc7XG5pbXBvcnQge3NldERlbGF5UHJvamVjdGlvbn0gZnJvbSAnLi9pbnN0cnVjdGlvbnMvYWxsJztcbmltcG9ydCB7YXR0YWNoSTE4bk9wQ29kZXNEZWJ1Z30gZnJvbSAnLi9pbnN0cnVjdGlvbnMvbHZpZXdfZGVidWcnO1xuaW1wb3J0IHthbGxvY0V4cGFuZG8sIGVsZW1lbnRBdHRyaWJ1dGVJbnRlcm5hbCwgZWxlbWVudFByb3BlcnR5SW50ZXJuYWwsIGdldE9yQ3JlYXRlVE5vZGUsIHNldElucHV0c0ZvclByb3BlcnR5LCBzZXROZ1JlZmxlY3RQcm9wZXJ0aWVzLCB0ZXh0QmluZGluZ0ludGVybmFsfSBmcm9tICcuL2luc3RydWN0aW9ucy9zaGFyZWQnO1xuaW1wb3J0IHtMQ29udGFpbmVyLCBOQVRJVkV9IGZyb20gJy4vaW50ZXJmYWNlcy9jb250YWluZXInO1xuaW1wb3J0IHtnZXREb2N1bWVudH0gZnJvbSAnLi9pbnRlcmZhY2VzL2RvY3VtZW50JztcbmltcG9ydCB7Q09NTUVOVF9NQVJLRVIsIEVMRU1FTlRfTUFSS0VSLCBJMThuTXV0YXRlT3BDb2RlLCBJMThuTXV0YXRlT3BDb2RlcywgSTE4blVwZGF0ZU9wQ29kZSwgSTE4blVwZGF0ZU9wQ29kZXMsIEljdVR5cGUsIFRJMThuLCBUSWN1fSBmcm9tICcuL2ludGVyZmFjZXMvaTE4bic7XG5pbXBvcnQge1RFbGVtZW50Tm9kZSwgVEljdUNvbnRhaW5lck5vZGUsIFROb2RlLCBUTm9kZUZsYWdzLCBUTm9kZVR5cGUsIFRQcm9qZWN0aW9uTm9kZX0gZnJvbSAnLi9pbnRlcmZhY2VzL25vZGUnO1xuaW1wb3J0IHtSQ29tbWVudCwgUkVsZW1lbnQsIFJUZXh0fSBmcm9tICcuL2ludGVyZmFjZXMvcmVuZGVyZXInO1xuaW1wb3J0IHtTYW5pdGl6ZXJGbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3Nhbml0aXphdGlvbic7XG5pbXBvcnQge2lzTENvbnRhaW5lcn0gZnJvbSAnLi9pbnRlcmZhY2VzL3R5cGVfY2hlY2tzJztcbmltcG9ydCB7SEVBREVSX09GRlNFVCwgTFZpZXcsIFJFTkRFUkVSLCBUX0hPU1QsIFRWSUVXLCBUVmlld30gZnJvbSAnLi9pbnRlcmZhY2VzL3ZpZXcnO1xuaW1wb3J0IHthcHBlbmRDaGlsZCwgYXBwbHlQcm9qZWN0aW9uLCBjcmVhdGVUZXh0Tm9kZSwgbmF0aXZlUmVtb3ZlTm9kZX0gZnJvbSAnLi9ub2RlX21hbmlwdWxhdGlvbic7XG5pbXBvcnQge2dldEJpbmRpbmdJbmRleCwgZ2V0SXNQYXJlbnQsIGdldExWaWV3LCBnZXRQcmV2aW91c09yUGFyZW50VE5vZGUsIGdldFRWaWV3LCBuZXh0QmluZGluZ0luZGV4LCBzZXRJc05vdFBhcmVudCwgc2V0UHJldmlvdXNPclBhcmVudFROb2RlfSBmcm9tICcuL3N0YXRlJztcbmltcG9ydCB7cmVuZGVyU3RyaW5naWZ5fSBmcm9tICcuL3V0aWwvbWlzY191dGlscyc7XG5pbXBvcnQge2dldE5hdGl2ZUJ5SW5kZXgsIGdldE5hdGl2ZUJ5VE5vZGUsIGdldFROb2RlLCBsb2FkfSBmcm9tICcuL3V0aWwvdmlld191dGlscyc7XG5cblxuY29uc3QgTUFSS0VSID0gYO+/vWA7XG5jb25zdCBJQ1VfQkxPQ0tfUkVHRVhQID0gL15cXHMqKO+/vVxcZCs6P1xcZCrvv70pXFxzKixcXHMqKHNlbGVjdHxwbHVyYWwpXFxzKiwvO1xuY29uc3QgU1VCVEVNUExBVEVfUkVHRVhQID0gL++/vVxcLz9cXCooXFxkKzpcXGQrKe+/vS9naTtcbmNvbnN0IFBIX1JFR0VYUCA9IC/vv70oXFwvP1sjKiFdXFxkKyk6P1xcZCrvv70vZ2k7XG5jb25zdCBCSU5ESU5HX1JFR0VYUCA9IC/vv70oXFxkKyk6P1xcZCrvv70vZ2k7XG5jb25zdCBJQ1VfUkVHRVhQID0gLyh7XFxzKu+/vVxcZCs6P1xcZCrvv71cXHMqLFxccypcXFN7Nn1cXHMqLFtcXHNcXFNdKn0pL2dpO1xuY29uc3QgZW51bSBUYWdUeXBlIHtcbiAgRUxFTUVOVCA9ICcjJyxcbiAgVEVNUExBVEUgPSAnKicsXG4gIFBST0pFQ1RJT04gPSAnIScsXG59XG5cbi8vIGkxOG5Qb3N0cHJvY2VzcyBjb25zdHNcbmNvbnN0IFJPT1RfVEVNUExBVEVfSUQgPSAwO1xuY29uc3QgUFBfTVVMVElfVkFMVUVfUExBQ0VIT0xERVJTX1JFR0VYUCA9IC9cXFso77+9Lis/77+9PylcXF0vO1xuY29uc3QgUFBfUExBQ0VIT0xERVJTX1JFR0VYUCA9IC9cXFso77+9Lis/77+9PylcXF18KO+/vVxcLz9cXCpcXGQrOlxcZCvvv70pL2c7XG5jb25zdCBQUF9JQ1VfVkFSU19SRUdFWFAgPSAvKHtcXHMqKShWQVJfKFBMVVJBTHxTRUxFQ1QpKF9cXGQrKT8pKFxccyosKS9nO1xuY29uc3QgUFBfSUNVX1BMQUNFSE9MREVSU19SRUdFWFAgPSAveyhbQS1aMC05X10rKX0vZztcbmNvbnN0IFBQX0lDVVNfUkVHRVhQID0gL++/vUkxOE5fRVhQXyhJQ1UoX1xcZCspPynvv70vZztcbmNvbnN0IFBQX0NMT1NFX1RFTVBMQVRFX1JFR0VYUCA9IC9cXC9cXCovO1xuY29uc3QgUFBfVEVNUExBVEVfSURfUkVHRVhQID0gL1xcZCtcXDooXFxkKykvO1xuXG4vLyBQYXJzZWQgcGxhY2Vob2xkZXIgc3RydWN0dXJlIHVzZWQgaW4gcG9zdHByb2Nlc3NpbmcgKHdpdGhpbiBgaTE4blBvc3Rwcm9jZXNzYCBmdW5jdGlvbilcbi8vIENvbnRhaW5zIHRoZSBmb2xsb3dpbmcgZmllbGRzOiBbdGVtcGxhdGVJZCwgaXNDbG9zZVRlbXBsYXRlVGFnLCBwbGFjZWhvbGRlcl1cbnR5cGUgUG9zdHByb2Nlc3NQbGFjZWhvbGRlciA9IFtudW1iZXIsIGJvb2xlYW4sIHN0cmluZ107XG5cbmludGVyZmFjZSBJY3VFeHByZXNzaW9uIHtcbiAgdHlwZTogSWN1VHlwZTtcbiAgbWFpbkJpbmRpbmc6IG51bWJlcjtcbiAgY2FzZXM6IHN0cmluZ1tdO1xuICB2YWx1ZXM6IChzdHJpbmd8SWN1RXhwcmVzc2lvbilbXVtdO1xufVxuXG5pbnRlcmZhY2UgSWN1Q2FzZSB7XG4gIC8qKlxuICAgKiBOdW1iZXIgb2Ygc2xvdHMgdG8gYWxsb2NhdGUgaW4gZXhwYW5kbyBmb3IgdGhpcyBjYXNlLlxuICAgKlxuICAgKiBUaGlzIGlzIHRoZSBtYXggbnVtYmVyIG9mIERPTSBlbGVtZW50cyB3aGljaCB3aWxsIGJlIGNyZWF0ZWQgYnkgdGhpcyBpMThuICsgSUNVIGJsb2Nrcy4gV2hlblxuICAgKiB0aGUgRE9NIGVsZW1lbnRzIGFyZSBiZWluZyBjcmVhdGVkIHRoZXkgYXJlIHN0b3JlZCBpbiB0aGUgRVhQQU5ETywgc28gdGhhdCB1cGRhdGUgT3BDb2RlcyBjYW5cbiAgICogd3JpdGUgaW50byB0aGVtLlxuICAgKi9cbiAgdmFyczogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBBbiBvcHRpb25hbCBhcnJheSBvZiBjaGlsZC9zdWIgSUNVcy5cbiAgICovXG4gIGNoaWxkSWN1czogbnVtYmVyW107XG5cbiAgLyoqXG4gICAqIEEgc2V0IG9mIE9wQ29kZXMgdG8gYXBwbHkgaW4gb3JkZXIgdG8gYnVpbGQgdXAgdGhlIERPTSByZW5kZXIgdHJlZSBmb3IgdGhlIElDVVxuICAgKi9cbiAgY3JlYXRlOiBJMThuTXV0YXRlT3BDb2RlcztcblxuICAvKipcbiAgICogQSBzZXQgb2YgT3BDb2RlcyB0byBhcHBseSBpbiBvcmRlciB0byBkZXN0cm95IHRoZSBET00gcmVuZGVyIHRyZWUgZm9yIHRoZSBJQ1UuXG4gICAqL1xuICByZW1vdmU6IEkxOG5NdXRhdGVPcENvZGVzO1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBPcENvZGVzIHRvIGFwcGx5IGluIG9yZGVyIHRvIHVwZGF0ZSB0aGUgRE9NIHJlbmRlciB0cmVlIGZvciB0aGUgSUNVIGJpbmRpbmdzLlxuICAgKi9cbiAgdXBkYXRlOiBJMThuVXBkYXRlT3BDb2Rlcztcbn1cblxuLyoqXG4gKiBCcmVha3MgcGF0dGVybiBpbnRvIHN0cmluZ3MgYW5kIHRvcCBsZXZlbCB7Li4ufSBibG9ja3MuXG4gKiBDYW4gYmUgdXNlZCB0byBicmVhayBhIG1lc3NhZ2UgaW50byB0ZXh0IGFuZCBJQ1UgZXhwcmVzc2lvbnMsIG9yIHRvIGJyZWFrIGFuIElDVSBleHByZXNzaW9uIGludG9cbiAqIGtleXMgYW5kIGNhc2VzLlxuICogT3JpZ2luYWwgY29kZSBmcm9tIGNsb3N1cmUgbGlicmFyeSwgbW9kaWZpZWQgZm9yIEFuZ3VsYXIuXG4gKlxuICogQHBhcmFtIHBhdHRlcm4gKHN1YilQYXR0ZXJuIHRvIGJlIGJyb2tlbi5cbiAqXG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RQYXJ0cyhwYXR0ZXJuOiBzdHJpbmcpOiAoc3RyaW5nfEljdUV4cHJlc3Npb24pW10ge1xuICBpZiAoIXBhdHRlcm4pIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBsZXQgcHJldlBvcyA9IDA7XG4gIGNvbnN0IGJyYWNlU3RhY2sgPSBbXTtcbiAgY29uc3QgcmVzdWx0czogKHN0cmluZ3xJY3VFeHByZXNzaW9uKVtdID0gW107XG4gIGNvbnN0IGJyYWNlcyA9IC9be31dL2c7XG4gIC8vIGxhc3RJbmRleCBkb2Vzbid0IGdldCBzZXQgdG8gMCBzbyB3ZSBoYXZlIHRvLlxuICBicmFjZXMubGFzdEluZGV4ID0gMDtcblxuICBsZXQgbWF0Y2g7XG4gIHdoaWxlIChtYXRjaCA9IGJyYWNlcy5leGVjKHBhdHRlcm4pKSB7XG4gICAgY29uc3QgcG9zID0gbWF0Y2guaW5kZXg7XG4gICAgaWYgKG1hdGNoWzBdID09ICd9Jykge1xuICAgICAgYnJhY2VTdGFjay5wb3AoKTtcblxuICAgICAgaWYgKGJyYWNlU3RhY2subGVuZ3RoID09IDApIHtcbiAgICAgICAgLy8gRW5kIG9mIHRoZSBibG9jay5cbiAgICAgICAgY29uc3QgYmxvY2sgPSBwYXR0ZXJuLnN1YnN0cmluZyhwcmV2UG9zLCBwb3MpO1xuICAgICAgICBpZiAoSUNVX0JMT0NLX1JFR0VYUC50ZXN0KGJsb2NrKSkge1xuICAgICAgICAgIHJlc3VsdHMucHVzaChwYXJzZUlDVUJsb2NrKGJsb2NrKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0cy5wdXNoKGJsb2NrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByZXZQb3MgPSBwb3MgKyAxO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYnJhY2VTdGFjay5sZW5ndGggPT0gMCkge1xuICAgICAgICBjb25zdCBzdWJzdHJpbmcgPSBwYXR0ZXJuLnN1YnN0cmluZyhwcmV2UG9zLCBwb3MpO1xuICAgICAgICByZXN1bHRzLnB1c2goc3Vic3RyaW5nKTtcbiAgICAgICAgcHJldlBvcyA9IHBvcyArIDE7XG4gICAgICB9XG4gICAgICBicmFjZVN0YWNrLnB1c2goJ3snKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBzdWJzdHJpbmcgPSBwYXR0ZXJuLnN1YnN0cmluZyhwcmV2UG9zKTtcbiAgcmVzdWx0cy5wdXNoKHN1YnN0cmluZyk7XG4gIHJldHVybiByZXN1bHRzO1xufVxuXG4vKipcbiAqIFBhcnNlcyB0ZXh0IGNvbnRhaW5pbmcgYW4gSUNVIGV4cHJlc3Npb24gYW5kIHByb2R1Y2VzIGEgSlNPTiBvYmplY3QgZm9yIGl0LlxuICogT3JpZ2luYWwgY29kZSBmcm9tIGNsb3N1cmUgbGlicmFyeSwgbW9kaWZpZWQgZm9yIEFuZ3VsYXIuXG4gKlxuICogQHBhcmFtIHBhdHRlcm4gVGV4dCBjb250YWluaW5nIGFuIElDVSBleHByZXNzaW9uIHRoYXQgbmVlZHMgdG8gYmUgcGFyc2VkLlxuICpcbiAqL1xuZnVuY3Rpb24gcGFyc2VJQ1VCbG9jayhwYXR0ZXJuOiBzdHJpbmcpOiBJY3VFeHByZXNzaW9uIHtcbiAgY29uc3QgY2FzZXMgPSBbXTtcbiAgY29uc3QgdmFsdWVzOiAoc3RyaW5nfEljdUV4cHJlc3Npb24pW11bXSA9IFtdO1xuICBsZXQgaWN1VHlwZSA9IEljdVR5cGUucGx1cmFsO1xuICBsZXQgbWFpbkJpbmRpbmcgPSAwO1xuICBwYXR0ZXJuID0gcGF0dGVybi5yZXBsYWNlKElDVV9CTE9DS19SRUdFWFAsIGZ1bmN0aW9uKHN0cjogc3RyaW5nLCBiaW5kaW5nOiBzdHJpbmcsIHR5cGU6IHN0cmluZykge1xuICAgIGlmICh0eXBlID09PSAnc2VsZWN0Jykge1xuICAgICAgaWN1VHlwZSA9IEljdVR5cGUuc2VsZWN0O1xuICAgIH0gZWxzZSB7XG4gICAgICBpY3VUeXBlID0gSWN1VHlwZS5wbHVyYWw7XG4gICAgfVxuICAgIG1haW5CaW5kaW5nID0gcGFyc2VJbnQoYmluZGluZy5zdWJzdHIoMSksIDEwKTtcbiAgICByZXR1cm4gJyc7XG4gIH0pO1xuXG4gIGNvbnN0IHBhcnRzID0gZXh0cmFjdFBhcnRzKHBhdHRlcm4pIGFzIHN0cmluZ1tdO1xuICAvLyBMb29raW5nIGZvciAoa2V5IGJsb2NrKSsgc2VxdWVuY2UuIE9uZSBvZiB0aGUga2V5cyBoYXMgdG8gYmUgXCJvdGhlclwiLlxuICBmb3IgKGxldCBwb3MgPSAwOyBwb3MgPCBwYXJ0cy5sZW5ndGg7KSB7XG4gICAgbGV0IGtleSA9IHBhcnRzW3BvcysrXS50cmltKCk7XG4gICAgaWYgKGljdVR5cGUgPT09IEljdVR5cGUucGx1cmFsKSB7XG4gICAgICAvLyBLZXkgY2FuIGJlIFwiPXhcIiwgd2UganVzdCB3YW50IFwieFwiXG4gICAgICBrZXkgPSBrZXkucmVwbGFjZSgvXFxzKig/Oj0pPyhcXHcrKVxccyovLCAnJDEnKTtcbiAgICB9XG4gICAgaWYgKGtleS5sZW5ndGgpIHtcbiAgICAgIGNhc2VzLnB1c2goa2V5KTtcbiAgICB9XG5cbiAgICBjb25zdCBibG9ja3MgPSBleHRyYWN0UGFydHMocGFydHNbcG9zKytdKSBhcyBzdHJpbmdbXTtcbiAgICBpZiAoY2FzZXMubGVuZ3RoID4gdmFsdWVzLmxlbmd0aCkge1xuICAgICAgdmFsdWVzLnB1c2goYmxvY2tzKTtcbiAgICB9XG4gIH1cblxuICAvLyBUT0RPKG9jb21iZSk6IHN1cHBvcnQgSUNVIGV4cHJlc3Npb25zIGluIGF0dHJpYnV0ZXMsIHNlZSAjMjE2MTVcbiAgcmV0dXJuIHt0eXBlOiBpY3VUeXBlLCBtYWluQmluZGluZzogbWFpbkJpbmRpbmcsIGNhc2VzLCB2YWx1ZXN9O1xufVxuXG4vKipcbiAqIFJlbW92ZXMgZXZlcnl0aGluZyBpbnNpZGUgdGhlIHN1Yi10ZW1wbGF0ZXMgb2YgYSBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiByZW1vdmVJbm5lclRlbXBsYXRlVHJhbnNsYXRpb24obWVzc2FnZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IG1hdGNoO1xuICBsZXQgcmVzID0gJyc7XG4gIGxldCBpbmRleCA9IDA7XG4gIGxldCBpblRlbXBsYXRlID0gZmFsc2U7XG4gIGxldCB0YWdNYXRjaGVkO1xuXG4gIHdoaWxlICgobWF0Y2ggPSBTVUJURU1QTEFURV9SRUdFWFAuZXhlYyhtZXNzYWdlKSkgIT09IG51bGwpIHtcbiAgICBpZiAoIWluVGVtcGxhdGUpIHtcbiAgICAgIHJlcyArPSBtZXNzYWdlLnN1YnN0cmluZyhpbmRleCwgbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGgpO1xuICAgICAgdGFnTWF0Y2hlZCA9IG1hdGNoWzFdO1xuICAgICAgaW5UZW1wbGF0ZSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChtYXRjaFswXSA9PT0gYCR7TUFSS0VSfS8qJHt0YWdNYXRjaGVkfSR7TUFSS0VSfWApIHtcbiAgICAgICAgaW5kZXggPSBtYXRjaC5pbmRleDtcbiAgICAgICAgaW5UZW1wbGF0ZSA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nRGV2TW9kZSAmJlxuICAgICAgYXNzZXJ0RXF1YWwoXG4gICAgICAgICAgaW5UZW1wbGF0ZSwgZmFsc2UsXG4gICAgICAgICAgYFRhZyBtaXNtYXRjaDogdW5hYmxlIHRvIGZpbmQgdGhlIGVuZCBvZiB0aGUgc3ViLXRlbXBsYXRlIGluIHRoZSB0cmFuc2xhdGlvbiBcIiR7XG4gICAgICAgICAgICAgIG1lc3NhZ2V9XCJgKTtcblxuICByZXMgKz0gbWVzc2FnZS5zdWJzdHIoaW5kZXgpO1xuICByZXR1cm4gcmVzO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIGEgcGFydCBvZiBhIG1lc3NhZ2UgYW5kIHJlbW92ZXMgdGhlIHJlc3QuXG4gKlxuICogVGhpcyBtZXRob2QgaXMgdXNlZCBmb3IgZXh0cmFjdGluZyBhIHBhcnQgb2YgdGhlIG1lc3NhZ2UgYXNzb2NpYXRlZCB3aXRoIGEgdGVtcGxhdGUuIEEgdHJhbnNsYXRlZFxuICogbWVzc2FnZSBjYW4gc3BhbiBtdWx0aXBsZSB0ZW1wbGF0ZXMuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYFxuICogPGRpdiBpMThuPlRyYW5zbGF0ZSA8c3BhbiAqbmdJZj5tZTwvc3Bhbj4hPC9kaXY+XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBjcm9wXG4gKiBAcGFyYW0gc3ViVGVtcGxhdGVJbmRleCBJbmRleCBvZiB0aGUgc3ViLXRlbXBsYXRlIHRvIGV4dHJhY3QuIElmIHVuZGVmaW5lZCBpdCByZXR1cm5zIHRoZVxuICogZXh0ZXJuYWwgdGVtcGxhdGUgYW5kIHJlbW92ZXMgYWxsIHN1Yi10ZW1wbGF0ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmFuc2xhdGlvbkZvclRlbXBsYXRlKG1lc3NhZ2U6IHN0cmluZywgc3ViVGVtcGxhdGVJbmRleD86IG51bWJlcikge1xuICBpZiAoaXNSb290VGVtcGxhdGVNZXNzYWdlKHN1YlRlbXBsYXRlSW5kZXgpKSB7XG4gICAgLy8gV2Ugd2FudCB0aGUgcm9vdCB0ZW1wbGF0ZSBtZXNzYWdlLCBpZ25vcmUgYWxsIHN1Yi10ZW1wbGF0ZXNcbiAgICByZXR1cm4gcmVtb3ZlSW5uZXJUZW1wbGF0ZVRyYW5zbGF0aW9uKG1lc3NhZ2UpO1xuICB9IGVsc2Uge1xuICAgIC8vIFdlIHdhbnQgYSBzcGVjaWZpYyBzdWItdGVtcGxhdGVcbiAgICBjb25zdCBzdGFydCA9XG4gICAgICAgIG1lc3NhZ2UuaW5kZXhPZihgOiR7c3ViVGVtcGxhdGVJbmRleH0ke01BUktFUn1gKSArIDIgKyBzdWJUZW1wbGF0ZUluZGV4LnRvU3RyaW5nKCkubGVuZ3RoO1xuICAgIGNvbnN0IGVuZCA9IG1lc3NhZ2Uuc2VhcmNoKG5ldyBSZWdFeHAoYCR7TUFSS0VSfVxcXFwvXFxcXCpcXFxcZCs6JHtzdWJUZW1wbGF0ZUluZGV4fSR7TUFSS0VSfWApKTtcbiAgICByZXR1cm4gcmVtb3ZlSW5uZXJUZW1wbGF0ZVRyYW5zbGF0aW9uKG1lc3NhZ2Uuc3Vic3RyaW5nKHN0YXJ0LCBlbmQpKTtcbiAgfVxufVxuXG4vKipcbiAqIEdlbmVyYXRlIHRoZSBPcENvZGVzIHRvIHVwZGF0ZSB0aGUgYmluZGluZ3Mgb2YgYSBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHN0ciBUaGUgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGJpbmRpbmdzLlxuICogQHBhcmFtIGRlc3RpbmF0aW9uTm9kZSBJbmRleCBvZiB0aGUgZGVzdGluYXRpb24gbm9kZSB3aGljaCB3aWxsIHJlY2VpdmUgdGhlIGJpbmRpbmcuXG4gKiBAcGFyYW0gYXR0ck5hbWUgTmFtZSBvZiB0aGUgYXR0cmlidXRlLCBpZiB0aGUgc3RyaW5nIGJlbG9uZ3MgdG8gYW4gYXR0cmlidXRlLlxuICogQHBhcmFtIHNhbml0aXplRm4gU2FuaXRpemF0aW9uIGZ1bmN0aW9uIHVzZWQgdG8gc2FuaXRpemUgdGhlIHN0cmluZyBhZnRlciB1cGRhdGUsIGlmIG5lY2Vzc2FyeS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVCaW5kaW5nVXBkYXRlT3BDb2RlcyhcbiAgICBzdHI6IHN0cmluZywgZGVzdGluYXRpb25Ob2RlOiBudW1iZXIsIGF0dHJOYW1lPzogc3RyaW5nLFxuICAgIHNhbml0aXplRm46IFNhbml0aXplckZufG51bGwgPSBudWxsKTogSTE4blVwZGF0ZU9wQ29kZXMge1xuICBjb25zdCB1cGRhdGVPcENvZGVzOiBJMThuVXBkYXRlT3BDb2RlcyA9IFtudWxsLCBudWxsXTsgIC8vIEFsbG9jIHNwYWNlIGZvciBtYXNrIGFuZCBzaXplXG4gIGNvbnN0IHRleHRQYXJ0cyA9IHN0ci5zcGxpdChCSU5ESU5HX1JFR0VYUCk7XG4gIGxldCBtYXNrID0gMDtcblxuICBmb3IgKGxldCBqID0gMDsgaiA8IHRleHRQYXJ0cy5sZW5ndGg7IGorKykge1xuICAgIGNvbnN0IHRleHRWYWx1ZSA9IHRleHRQYXJ0c1tqXTtcblxuICAgIGlmIChqICYgMSkge1xuICAgICAgLy8gT2RkIGluZGV4ZXMgYXJlIGJpbmRpbmdzXG4gICAgICBjb25zdCBiaW5kaW5nSW5kZXggPSBwYXJzZUludCh0ZXh0VmFsdWUsIDEwKTtcbiAgICAgIHVwZGF0ZU9wQ29kZXMucHVzaCgtMSAtIGJpbmRpbmdJbmRleCk7XG4gICAgICBtYXNrID0gbWFzayB8IHRvTWFza0JpdChiaW5kaW5nSW5kZXgpO1xuICAgIH0gZWxzZSBpZiAodGV4dFZhbHVlICE9PSAnJykge1xuICAgICAgLy8gRXZlbiBpbmRleGVzIGFyZSB0ZXh0XG4gICAgICB1cGRhdGVPcENvZGVzLnB1c2godGV4dFZhbHVlKTtcbiAgICB9XG4gIH1cblxuICB1cGRhdGVPcENvZGVzLnB1c2goXG4gICAgICBkZXN0aW5hdGlvbk5vZGUgPDwgSTE4blVwZGF0ZU9wQ29kZS5TSElGVF9SRUYgfFxuICAgICAgKGF0dHJOYW1lID8gSTE4blVwZGF0ZU9wQ29kZS5BdHRyIDogSTE4blVwZGF0ZU9wQ29kZS5UZXh0KSk7XG4gIGlmIChhdHRyTmFtZSkge1xuICAgIHVwZGF0ZU9wQ29kZXMucHVzaChhdHRyTmFtZSwgc2FuaXRpemVGbik7XG4gIH1cbiAgdXBkYXRlT3BDb2Rlc1swXSA9IG1hc2s7XG4gIHVwZGF0ZU9wQ29kZXNbMV0gPSB1cGRhdGVPcENvZGVzLmxlbmd0aCAtIDI7XG4gIHJldHVybiB1cGRhdGVPcENvZGVzO1xufVxuXG5mdW5jdGlvbiBnZXRCaW5kaW5nTWFzayhpY3VFeHByZXNzaW9uOiBJY3VFeHByZXNzaW9uLCBtYXNrID0gMCk6IG51bWJlciB7XG4gIG1hc2sgPSBtYXNrIHwgdG9NYXNrQml0KGljdUV4cHJlc3Npb24ubWFpbkJpbmRpbmcpO1xuICBsZXQgbWF0Y2g7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaWN1RXhwcmVzc2lvbi52YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCB2YWx1ZUFyciA9IGljdUV4cHJlc3Npb24udmFsdWVzW2ldO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgdmFsdWVBcnIubGVuZ3RoOyBqKyspIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdmFsdWVBcnJbal07XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICB3aGlsZSAobWF0Y2ggPSBCSU5ESU5HX1JFR0VYUC5leGVjKHZhbHVlKSkge1xuICAgICAgICAgIG1hc2sgPSBtYXNrIHwgdG9NYXNrQml0KHBhcnNlSW50KG1hdGNoWzFdLCAxMCkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXNrID0gZ2V0QmluZGluZ01hc2sodmFsdWUgYXMgSWN1RXhwcmVzc2lvbiwgbWFzayk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBtYXNrO1xufVxuXG5jb25zdCBpMThuSW5kZXhTdGFjazogbnVtYmVyW10gPSBbXTtcbmxldCBpMThuSW5kZXhTdGFja1BvaW50ZXIgPSAtMTtcblxuLyoqXG4gKiBDb252ZXJ0IGJpbmRpbmcgaW5kZXggdG8gbWFzayBiaXQuXG4gKlxuICogRWFjaCBpbmRleCByZXByZXNlbnRzIGEgc2luZ2xlIGJpdCBvbiB0aGUgYml0LW1hc2suIEJlY2F1c2UgYml0LW1hc2sgb25seSBoYXMgMzIgYml0cywgd2UgbWFrZVxuICogdGhlIDMybmQgYml0IHNoYXJlIGFsbCBtYXNrcyBmb3IgYWxsIGJpbmRpbmdzIGhpZ2hlciB0aGFuIDMyLiBTaW5jZSBpdCBpcyBleHRyZW1lbHkgcmFyZSB0byBoYXZlXG4gKiBtb3JlIHRoYW4gMzIgYmluZGluZ3MgdGhpcyB3aWxsIGJlIGhpdCB2ZXJ5IHJhcmVseS4gVGhlIGRvd25zaWRlIG9mIGhpdHRpbmcgdGhpcyBjb3JuZXIgY2FzZSBpc1xuICogdGhhdCB3ZSB3aWxsIGV4ZWN1dGUgYmluZGluZyBjb2RlIG1vcmUgb2Z0ZW4gdGhhbiBuZWNlc3NhcnkuIChwZW5hbHR5IG9mIHBlcmZvcm1hbmNlKVxuICovXG5mdW5jdGlvbiB0b01hc2tCaXQoYmluZGluZ0luZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gMSA8PCBNYXRoLm1pbihiaW5kaW5nSW5kZXgsIDMxKTtcbn1cblxuY29uc3QgcGFyZW50SW5kZXhTdGFjazogbnVtYmVyW10gPSBbXTtcblxuLyoqXG4gKiBNYXJrcyBhIGJsb2NrIG9mIHRleHQgYXMgdHJhbnNsYXRhYmxlLlxuICpcbiAqIFRoZSBpbnN0cnVjdGlvbnMgYGkxOG5TdGFydGAgYW5kIGBpMThuRW5kYCBtYXJrIHRoZSB0cmFuc2xhdGlvbiBibG9jayBpbiB0aGUgdGVtcGxhdGUuXG4gKiBUaGUgdHJhbnNsYXRpb24gYG1lc3NhZ2VgIGlzIHRoZSB2YWx1ZSB3aGljaCBpcyBsb2NhbGUgc3BlY2lmaWMuIFRoZSB0cmFuc2xhdGlvbiBzdHJpbmcgbWF5XG4gKiBjb250YWluIHBsYWNlaG9sZGVycyB3aGljaCBhc3NvY2lhdGUgaW5uZXIgZWxlbWVudHMgYW5kIHN1Yi10ZW1wbGF0ZXMgd2l0aGluIHRoZSB0cmFuc2xhdGlvbi5cbiAqXG4gKiBUaGUgdHJhbnNsYXRpb24gYG1lc3NhZ2VgIHBsYWNlaG9sZGVycyBhcmU6XG4gKiAtIGDvv717aW5kZXh9KDp7YmxvY2t9Ke+/vWA6ICpCaW5kaW5nIFBsYWNlaG9sZGVyKjogTWFya3MgYSBsb2NhdGlvbiB3aGVyZSBhbiBleHByZXNzaW9uIHdpbGwgYmVcbiAqICAgaW50ZXJwb2xhdGVkIGludG8uIFRoZSBwbGFjZWhvbGRlciBgaW5kZXhgIHBvaW50cyB0byB0aGUgZXhwcmVzc2lvbiBiaW5kaW5nIGluZGV4LiBBbiBvcHRpb25hbFxuICogICBgYmxvY2tgIHRoYXQgbWF0Y2hlcyB0aGUgc3ViLXRlbXBsYXRlIGluIHdoaWNoIGl0IHdhcyBkZWNsYXJlZC5cbiAqIC0gYO+/vSN7aW5kZXh9KDp7YmxvY2t9Ke+/vWAvYO+/vS8je2luZGV4fSg6e2Jsb2NrfSnvv71gOiAqRWxlbWVudCBQbGFjZWhvbGRlcio6ICBNYXJrcyB0aGUgYmVnaW5uaW5nXG4gKiAgIGFuZCBlbmQgb2YgRE9NIGVsZW1lbnQgdGhhdCB3ZXJlIGVtYmVkZGVkIGluIHRoZSBvcmlnaW5hbCB0cmFuc2xhdGlvbiBibG9jay4gVGhlIHBsYWNlaG9sZGVyXG4gKiAgIGBpbmRleGAgcG9pbnRzIHRvIHRoZSBlbGVtZW50IGluZGV4IGluIHRoZSB0ZW1wbGF0ZSBpbnN0cnVjdGlvbnMgc2V0LiBBbiBvcHRpb25hbCBgYmxvY2tgIHRoYXRcbiAqICAgbWF0Y2hlcyB0aGUgc3ViLXRlbXBsYXRlIGluIHdoaWNoIGl0IHdhcyBkZWNsYXJlZC5cbiAqIC0gYO+/vSF7aW5kZXh9KDp7YmxvY2t9Ke+/vWAvYO+/vS8he2luZGV4fSg6e2Jsb2NrfSnvv71gOiAqUHJvamVjdGlvbiBQbGFjZWhvbGRlcio6ICBNYXJrcyB0aGVcbiAqICAgYmVnaW5uaW5nIGFuZCBlbmQgb2YgPG5nLWNvbnRlbnQ+IHRoYXQgd2FzIGVtYmVkZGVkIGluIHRoZSBvcmlnaW5hbCB0cmFuc2xhdGlvbiBibG9jay5cbiAqICAgVGhlIHBsYWNlaG9sZGVyIGBpbmRleGAgcG9pbnRzIHRvIHRoZSBlbGVtZW50IGluZGV4IGluIHRoZSB0ZW1wbGF0ZSBpbnN0cnVjdGlvbnMgc2V0LlxuICogICBBbiBvcHRpb25hbCBgYmxvY2tgIHRoYXQgbWF0Y2hlcyB0aGUgc3ViLXRlbXBsYXRlIGluIHdoaWNoIGl0IHdhcyBkZWNsYXJlZC5cbiAqIC0gYO+/vSp7aW5kZXh9OntibG9ja33vv71gL2Dvv70vKntpbmRleH06e2Jsb2Nrfe+/vWA6ICpTdWItdGVtcGxhdGUgUGxhY2Vob2xkZXIqOiBTdWItdGVtcGxhdGVzIG11c3QgYmVcbiAqICAgc3BsaXQgdXAgYW5kIHRyYW5zbGF0ZWQgc2VwYXJhdGVseSBpbiBlYWNoIGFuZ3VsYXIgdGVtcGxhdGUgZnVuY3Rpb24uIFRoZSBgaW5kZXhgIHBvaW50cyB0byB0aGVcbiAqICAgYHRlbXBsYXRlYCBpbnN0cnVjdGlvbiBpbmRleC4gQSBgYmxvY2tgIHRoYXQgbWF0Y2hlcyB0aGUgc3ViLXRlbXBsYXRlIGluIHdoaWNoIGl0IHdhcyBkZWNsYXJlZC5cbiAqXG4gKiBAcGFyYW0gaW5kZXggQSB1bmlxdWUgaW5kZXggb2YgdGhlIHRyYW5zbGF0aW9uIGluIHRoZSBzdGF0aWMgYmxvY2suXG4gKiBAcGFyYW0gbWVzc2FnZSBUaGUgdHJhbnNsYXRpb24gbWVzc2FnZS5cbiAqIEBwYXJhbSBzdWJUZW1wbGF0ZUluZGV4IE9wdGlvbmFsIHN1Yi10ZW1wbGF0ZSBpbmRleCBpbiB0aGUgYG1lc3NhZ2VgLlxuICpcbiAqIEBjb2RlR2VuQXBpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiDJtcm1aTE4blN0YXJ0KGluZGV4OiBudW1iZXIsIG1lc3NhZ2U6IHN0cmluZywgc3ViVGVtcGxhdGVJbmRleD86IG51bWJlcik6IHZvaWQge1xuICBjb25zdCB0VmlldyA9IGdldFRWaWV3KCk7XG4gIG5nRGV2TW9kZSAmJiBhc3NlcnREZWZpbmVkKHRWaWV3LCBgdFZpZXcgc2hvdWxkIGJlIGRlZmluZWRgKTtcbiAgaTE4bkluZGV4U3RhY2tbKytpMThuSW5kZXhTdGFja1BvaW50ZXJdID0gaW5kZXg7XG4gIC8vIFdlIG5lZWQgdG8gZGVsYXkgcHJvamVjdGlvbnMgdW50aWwgYGkxOG5FbmRgXG4gIHNldERlbGF5UHJvamVjdGlvbih0cnVlKTtcbiAgaWYgKHRWaWV3LmZpcnN0Q3JlYXRlUGFzcyAmJiB0Vmlldy5kYXRhW2luZGV4ICsgSEVBREVSX09GRlNFVF0gPT09IG51bGwpIHtcbiAgICBpMThuU3RhcnRGaXJzdFBhc3MoZ2V0TFZpZXcoKSwgdFZpZXcsIGluZGV4LCBtZXNzYWdlLCBzdWJUZW1wbGF0ZUluZGV4KTtcbiAgfVxufVxuXG4vLyBDb3VudCBmb3IgdGhlIG51bWJlciBvZiB2YXJzIHRoYXQgd2lsbCBiZSBhbGxvY2F0ZWQgZm9yIGVhY2ggaTE4biBibG9jay5cbi8vIEl0IGlzIGdsb2JhbCBiZWNhdXNlIHRoaXMgaXMgdXNlZCBpbiBtdWx0aXBsZSBmdW5jdGlvbnMgdGhhdCBpbmNsdWRlIGxvb3BzIGFuZCByZWN1cnNpdmUgY2FsbHMuXG4vLyBUaGlzIGlzIHJlc2V0IHRvIDAgd2hlbiBgaTE4blN0YXJ0Rmlyc3RQYXNzYCBpcyBjYWxsZWQuXG5sZXQgaTE4blZhcnNDb3VudDogbnVtYmVyO1xuXG5mdW5jdGlvbiBhbGxvY05vZGVJbmRleChzdGFydEluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gc3RhcnRJbmRleCArIGkxOG5WYXJzQ291bnQrKztcbn1cblxuLyoqXG4gKiBTZWUgYGkxOG5TdGFydGAgYWJvdmUuXG4gKi9cbmZ1bmN0aW9uIGkxOG5TdGFydEZpcnN0UGFzcyhcbiAgICBsVmlldzogTFZpZXcsIHRWaWV3OiBUVmlldywgaW5kZXg6IG51bWJlciwgbWVzc2FnZTogc3RyaW5nLCBzdWJUZW1wbGF0ZUluZGV4PzogbnVtYmVyKSB7XG4gIGNvbnN0IHN0YXJ0SW5kZXggPSB0Vmlldy5ibHVlcHJpbnQubGVuZ3RoIC0gSEVBREVSX09GRlNFVDtcbiAgaTE4blZhcnNDb3VudCA9IDA7XG4gIGNvbnN0IHByZXZpb3VzT3JQYXJlbnRUTm9kZSA9IGdldFByZXZpb3VzT3JQYXJlbnRUTm9kZSgpO1xuICBjb25zdCBwYXJlbnRUTm9kZSA9XG4gICAgICBnZXRJc1BhcmVudCgpID8gcHJldmlvdXNPclBhcmVudFROb2RlIDogcHJldmlvdXNPclBhcmVudFROb2RlICYmIHByZXZpb3VzT3JQYXJlbnRUTm9kZS5wYXJlbnQ7XG4gIGxldCBwYXJlbnRJbmRleCA9XG4gICAgICBwYXJlbnRUTm9kZSAmJiBwYXJlbnRUTm9kZSAhPT0gbFZpZXdbVF9IT1NUXSA/IHBhcmVudFROb2RlLmluZGV4IC0gSEVBREVSX09GRlNFVCA6IGluZGV4O1xuICBsZXQgcGFyZW50SW5kZXhQb2ludGVyID0gMDtcbiAgcGFyZW50SW5kZXhTdGFja1twYXJlbnRJbmRleFBvaW50ZXJdID0gcGFyZW50SW5kZXg7XG4gIGNvbnN0IGNyZWF0ZU9wQ29kZXM6IEkxOG5NdXRhdGVPcENvZGVzID0gW107XG4gIC8vIElmIHRoZSBwcmV2aW91cyBub2RlIHdhc24ndCB0aGUgZGlyZWN0IHBhcmVudCB0aGVuIHdlIGhhdmUgYSB0cmFuc2xhdGlvbiB3aXRob3V0IHRvcCBsZXZlbFxuICAvLyBlbGVtZW50IGFuZCB3ZSBuZWVkIHRvIGtlZXAgYSByZWZlcmVuY2Ugb2YgdGhlIHByZXZpb3VzIGVsZW1lbnQgaWYgdGhlcmUgaXMgb25lLiBXZSBzaG91bGQgYWxzb1xuICAvLyBrZWVwIHRyYWNrIHdoZXRoZXIgYW4gZWxlbWVudCB3YXMgYSBwYXJlbnQgbm9kZSBvciBub3QsIHNvIHRoYXQgdGhlIGxvZ2ljIHRoYXQgY29uc3VtZXNcbiAgLy8gdGhlIGdlbmVyYXRlZCBgSTE4bk11dGF0ZU9wQ29kZWBzIGNhbiBsZXZlcmFnZSB0aGlzIGluZm9ybWF0aW9uIHRvIHByb3Blcmx5IHNldCBUTm9kZSBzdGF0ZVxuICAvLyAod2hldGhlciBpdCdzIGEgcGFyZW50IG9yIHNpYmxpbmcpLlxuICBpZiAoaW5kZXggPiAwICYmIHByZXZpb3VzT3JQYXJlbnRUTm9kZSAhPT0gcGFyZW50VE5vZGUpIHtcbiAgICBsZXQgcHJldmlvdXNUTm9kZUluZGV4ID0gcHJldmlvdXNPclBhcmVudFROb2RlLmluZGV4IC0gSEVBREVSX09GRlNFVDtcbiAgICAvLyBJZiBjdXJyZW50IFROb2RlIGlzIGEgc2libGluZyBub2RlLCBlbmNvZGUgaXQgdXNpbmcgYSBuZWdhdGl2ZSBpbmRleC4gVGhpcyBpbmZvcm1hdGlvbiBpc1xuICAgIC8vIHJlcXVpcmVkIHdoZW4gdGhlIGBTZWxlY3RgIGFjdGlvbiBpcyBwcm9jZXNzZWQgKHNlZSB0aGUgYHJlYWRDcmVhdGVPcENvZGVzYCBmdW5jdGlvbikuXG4gICAgaWYgKCFnZXRJc1BhcmVudCgpKSB7XG4gICAgICBwcmV2aW91c1ROb2RlSW5kZXggPSB+cHJldmlvdXNUTm9kZUluZGV4O1xuICAgIH1cbiAgICAvLyBDcmVhdGUgYW4gT3BDb2RlIHRvIHNlbGVjdCB0aGUgcHJldmlvdXMgVE5vZGVcbiAgICBjcmVhdGVPcENvZGVzLnB1c2gocHJldmlvdXNUTm9kZUluZGV4IDw8IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUkVGIHwgSTE4bk11dGF0ZU9wQ29kZS5TZWxlY3QpO1xuICB9XG4gIGNvbnN0IHVwZGF0ZU9wQ29kZXM6IEkxOG5VcGRhdGVPcENvZGVzID0gW107XG4gIGNvbnN0IGljdUV4cHJlc3Npb25zOiBUSWN1W10gPSBbXTtcblxuICBpZiAobWVzc2FnZSA9PT0gJycgJiYgaXNSb290VGVtcGxhdGVNZXNzYWdlKHN1YlRlbXBsYXRlSW5kZXgpKSB7XG4gICAgLy8gSWYgdG9wIGxldmVsIHRyYW5zbGF0aW9uIGlzIGFuIGVtcHR5IHN0cmluZywgZG8gbm90IGludm9rZSBhZGRpdGlvbmFsIHByb2Nlc3NpbmdcbiAgICAvLyBhbmQganVzdCBjcmVhdGUgb3AgY29kZXMgZm9yIGVtcHR5IHRleHQgbm9kZSBpbnN0ZWFkLlxuICAgIGNyZWF0ZU9wQ29kZXMucHVzaChcbiAgICAgICAgbWVzc2FnZSwgYWxsb2NOb2RlSW5kZXgoc3RhcnRJbmRleCksXG4gICAgICAgIHBhcmVudEluZGV4IDw8IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUEFSRU5UIHwgSTE4bk11dGF0ZU9wQ29kZS5BcHBlbmRDaGlsZCk7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgdGVtcGxhdGVUcmFuc2xhdGlvbiA9IGdldFRyYW5zbGF0aW9uRm9yVGVtcGxhdGUobWVzc2FnZSwgc3ViVGVtcGxhdGVJbmRleCk7XG4gICAgY29uc3QgbXNnUGFydHMgPSByZXBsYWNlTmdzcCh0ZW1wbGF0ZVRyYW5zbGF0aW9uKS5zcGxpdChQSF9SRUdFWFApO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbXNnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCB2YWx1ZSA9IG1zZ1BhcnRzW2ldO1xuICAgICAgaWYgKGkgJiAxKSB7XG4gICAgICAgIC8vIE9kZCBpbmRleGVzIGFyZSBwbGFjZWhvbGRlcnMgKGVsZW1lbnRzIGFuZCBzdWItdGVtcGxhdGVzKVxuICAgICAgICBpZiAodmFsdWUuY2hhckF0KDApID09PSAnLycpIHtcbiAgICAgICAgICAvLyBJdCBpcyBhIGNsb3NpbmcgdGFnXG4gICAgICAgICAgaWYgKHZhbHVlLmNoYXJBdCgxKSA9PT0gVGFnVHlwZS5FTEVNRU5UKSB7XG4gICAgICAgICAgICBjb25zdCBwaEluZGV4ID0gcGFyc2VJbnQodmFsdWUuc3Vic3RyKDIpLCAxMCk7XG4gICAgICAgICAgICBwYXJlbnRJbmRleCA9IHBhcmVudEluZGV4U3RhY2tbLS1wYXJlbnRJbmRleFBvaW50ZXJdO1xuICAgICAgICAgICAgY3JlYXRlT3BDb2Rlcy5wdXNoKHBoSW5kZXggPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUYgfCBJMThuTXV0YXRlT3BDb2RlLkVsZW1lbnRFbmQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBwaEluZGV4ID0gcGFyc2VJbnQodmFsdWUuc3Vic3RyKDEpLCAxMCk7XG4gICAgICAgICAgY29uc3QgaXNFbGVtZW50ID0gdmFsdWUuY2hhckF0KDApID09PSBUYWdUeXBlLkVMRU1FTlQ7XG4gICAgICAgICAgLy8gVGhlIHZhbHVlIHJlcHJlc2VudHMgYSBwbGFjZWhvbGRlciB0aGF0IHdlIG1vdmUgdG8gdGhlIGRlc2lnbmF0ZWQgaW5kZXguXG4gICAgICAgICAgLy8gTm90ZTogcG9zaXRpdmUgaW5kaWNpZXMgaW5kaWNhdGUgdGhhdCBhIFROb2RlIHdpdGggYSBnaXZlbiBpbmRleCBzaG91bGQgYWxzbyBiZSBtYXJrZWRcbiAgICAgICAgICAvLyBhcyBwYXJlbnQgd2hpbGUgZXhlY3V0aW5nIGBTZWxlY3RgIGluc3RydWN0aW9uLlxuICAgICAgICAgIGNyZWF0ZU9wQ29kZXMucHVzaChcbiAgICAgICAgICAgICAgKGlzRWxlbWVudCA/IHBoSW5kZXggOiB+cGhJbmRleCkgPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUYgfFxuICAgICAgICAgICAgICAgICAgSTE4bk11dGF0ZU9wQ29kZS5TZWxlY3QsXG4gICAgICAgICAgICAgIHBhcmVudEluZGV4IDw8IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUEFSRU5UIHwgSTE4bk11dGF0ZU9wQ29kZS5BcHBlbmRDaGlsZCk7XG5cbiAgICAgICAgICBpZiAoaXNFbGVtZW50KSB7XG4gICAgICAgICAgICBwYXJlbnRJbmRleFN0YWNrWysrcGFyZW50SW5kZXhQb2ludGVyXSA9IHBhcmVudEluZGV4ID0gcGhJbmRleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEV2ZW4gaW5kZXhlcyBhcmUgdGV4dCAoaW5jbHVkaW5nIGJpbmRpbmdzICYgSUNVIGV4cHJlc3Npb25zKVxuICAgICAgICBjb25zdCBwYXJ0cyA9IGV4dHJhY3RQYXJ0cyh2YWx1ZSk7XG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcGFydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBpZiAoaiAmIDEpIHtcbiAgICAgICAgICAgIC8vIE9kZCBpbmRleGVzIGFyZSBJQ1UgZXhwcmVzc2lvbnNcbiAgICAgICAgICAgIGNvbnN0IGljdUV4cHJlc3Npb24gPSBwYXJ0c1tqXSBhcyBJY3VFeHByZXNzaW9uO1xuXG4gICAgICAgICAgICAvLyBWZXJpZnkgdGhhdCBJQ1UgZXhwcmVzc2lvbiBoYXMgdGhlIHJpZ2h0IHNoYXBlLiBUcmFuc2xhdGlvbnMgbWlnaHQgY29udGFpbiBpbnZhbGlkXG4gICAgICAgICAgICAvLyBjb25zdHJ1Y3Rpb25zICh3aGlsZSBvcmlnaW5hbCBtZXNzYWdlcyB3ZXJlIGNvcnJlY3QpLCBzbyBJQ1UgcGFyc2luZyBhdCBydW50aW1lIG1heVxuICAgICAgICAgICAgLy8gbm90IHN1Y2NlZWQgKHRodXMgYGljdUV4cHJlc3Npb25gIHJlbWFpbnMgYSBzdHJpbmcpLlxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpY3VFeHByZXNzaW9uICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICBgVW5hYmxlIHRvIHBhcnNlIElDVSBleHByZXNzaW9uIGluIFwiJHt0ZW1wbGF0ZVRyYW5zbGF0aW9ufVwiIG1lc3NhZ2UuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSB0aGUgY29tbWVudCBub2RlIHRoYXQgd2lsbCBhbmNob3IgdGhlIElDVSBleHByZXNzaW9uXG4gICAgICAgICAgICBjb25zdCBpY3VOb2RlSW5kZXggPSBhbGxvY05vZGVJbmRleChzdGFydEluZGV4KTtcbiAgICAgICAgICAgIGNyZWF0ZU9wQ29kZXMucHVzaChcbiAgICAgICAgICAgICAgICBDT01NRU5UX01BUktFUiwgbmdEZXZNb2RlID8gYElDVSAke2ljdU5vZGVJbmRleH1gIDogJycsIGljdU5vZGVJbmRleCxcbiAgICAgICAgICAgICAgICBwYXJlbnRJbmRleCA8PCBJMThuTXV0YXRlT3BDb2RlLlNISUZUX1BBUkVOVCB8IEkxOG5NdXRhdGVPcENvZGUuQXBwZW5kQ2hpbGQpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgY29kZXMgZm9yIHRoZSBJQ1UgZXhwcmVzc2lvblxuICAgICAgICAgICAgY29uc3QgbWFzayA9IGdldEJpbmRpbmdNYXNrKGljdUV4cHJlc3Npb24pO1xuICAgICAgICAgICAgaWN1U3RhcnQoaWN1RXhwcmVzc2lvbnMsIGljdUV4cHJlc3Npb24sIGljdU5vZGVJbmRleCwgaWN1Tm9kZUluZGV4KTtcbiAgICAgICAgICAgIC8vIFNpbmNlIHRoaXMgaXMgcmVjdXJzaXZlLCB0aGUgbGFzdCBUSWN1IHRoYXQgd2FzIHB1c2hlZCBpcyB0aGUgb25lIHdlIHdhbnRcbiAgICAgICAgICAgIGNvbnN0IHRJY3VJbmRleCA9IGljdUV4cHJlc3Npb25zLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB1cGRhdGVPcENvZGVzLnB1c2goXG4gICAgICAgICAgICAgICAgdG9NYXNrQml0KGljdUV4cHJlc3Npb24ubWFpbkJpbmRpbmcpLCAgLy8gbWFzayBvZiB0aGUgbWFpbiBiaW5kaW5nXG4gICAgICAgICAgICAgICAgMywgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCAzIG9wQ29kZXMgaWYgbm90IGNoYW5nZWRcbiAgICAgICAgICAgICAgICAtMSAtIGljdUV4cHJlc3Npb24ubWFpbkJpbmRpbmcsXG4gICAgICAgICAgICAgICAgaWN1Tm9kZUluZGV4IDw8IEkxOG5VcGRhdGVPcENvZGUuU0hJRlRfUkVGIHwgSTE4blVwZGF0ZU9wQ29kZS5JY3VTd2l0Y2gsIHRJY3VJbmRleCxcbiAgICAgICAgICAgICAgICBtYXNrLCAgLy8gbWFzayBvZiBhbGwgdGhlIGJpbmRpbmdzIG9mIHRoaXMgSUNVIGV4cHJlc3Npb25cbiAgICAgICAgICAgICAgICAyLCAgICAgLy8gc2tpcCAyIG9wQ29kZXMgaWYgbm90IGNoYW5nZWRcbiAgICAgICAgICAgICAgICBpY3VOb2RlSW5kZXggPDwgSTE4blVwZGF0ZU9wQ29kZS5TSElGVF9SRUYgfCBJMThuVXBkYXRlT3BDb2RlLkljdVVwZGF0ZSwgdEljdUluZGV4KTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHBhcnRzW2pdICE9PSAnJykge1xuICAgICAgICAgICAgY29uc3QgdGV4dCA9IHBhcnRzW2pdIGFzIHN0cmluZztcbiAgICAgICAgICAgIC8vIEV2ZW4gaW5kZXhlcyBhcmUgdGV4dCAoaW5jbHVkaW5nIGJpbmRpbmdzKVxuICAgICAgICAgICAgY29uc3QgaGFzQmluZGluZyA9IHRleHQubWF0Y2goQklORElOR19SRUdFWFApO1xuICAgICAgICAgICAgLy8gQ3JlYXRlIHRleHQgbm9kZXNcbiAgICAgICAgICAgIGNvbnN0IHRleHROb2RlSW5kZXggPSBhbGxvY05vZGVJbmRleChzdGFydEluZGV4KTtcbiAgICAgICAgICAgIGNyZWF0ZU9wQ29kZXMucHVzaChcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIGJpbmRpbmcsIHRoZSB2YWx1ZSB3aWxsIGJlIHNldCBkdXJpbmcgdXBkYXRlXG4gICAgICAgICAgICAgICAgaGFzQmluZGluZyA/ICcnIDogdGV4dCwgdGV4dE5vZGVJbmRleCxcbiAgICAgICAgICAgICAgICBwYXJlbnRJbmRleCA8PCBJMThuTXV0YXRlT3BDb2RlLlNISUZUX1BBUkVOVCB8IEkxOG5NdXRhdGVPcENvZGUuQXBwZW5kQ2hpbGQpO1xuXG4gICAgICAgICAgICBpZiAoaGFzQmluZGluZykge1xuICAgICAgICAgICAgICBhZGRBbGxUb0FycmF5KGdlbmVyYXRlQmluZGluZ1VwZGF0ZU9wQ29kZXModGV4dCwgdGV4dE5vZGVJbmRleCksIHVwZGF0ZU9wQ29kZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChpMThuVmFyc0NvdW50ID4gMCkge1xuICAgIGFsbG9jRXhwYW5kbyh0VmlldywgbFZpZXcsIGkxOG5WYXJzQ291bnQpO1xuICB9XG5cbiAgbmdEZXZNb2RlICYmXG4gICAgICBhdHRhY2hJMThuT3BDb2Rlc0RlYnVnKFxuICAgICAgICAgIGNyZWF0ZU9wQ29kZXMsIHVwZGF0ZU9wQ29kZXMsIGljdUV4cHJlc3Npb25zLmxlbmd0aCA/IGljdUV4cHJlc3Npb25zIDogbnVsbCwgbFZpZXcpO1xuXG4gIC8vIE5PVEU6IGxvY2FsIHZhciBuZWVkZWQgdG8gcHJvcGVybHkgYXNzZXJ0IHRoZSB0eXBlIG9mIGBUSTE4bmAuXG4gIGNvbnN0IHRJMThuOiBUSTE4biA9IHtcbiAgICB2YXJzOiBpMThuVmFyc0NvdW50LFxuICAgIGNyZWF0ZTogY3JlYXRlT3BDb2RlcyxcbiAgICB1cGRhdGU6IHVwZGF0ZU9wQ29kZXMsXG4gICAgaWN1czogaWN1RXhwcmVzc2lvbnMubGVuZ3RoID8gaWN1RXhwcmVzc2lvbnMgOiBudWxsLFxuICB9O1xuXG4gIHRWaWV3LmRhdGFbaW5kZXggKyBIRUFERVJfT0ZGU0VUXSA9IHRJMThuO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRJMThuTm9kZShcbiAgICB0VmlldzogVFZpZXcsIHROb2RlOiBUTm9kZSwgcGFyZW50VE5vZGU6IFROb2RlLCBwcmV2aW91c1ROb2RlOiBUTm9kZXxudWxsLFxuICAgIGxWaWV3OiBMVmlldyk6IFROb2RlIHtcbiAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5yZW5kZXJlck1vdmVOb2RlKys7XG4gIGNvbnN0IG5leHROb2RlID0gdE5vZGUubmV4dDtcbiAgaWYgKCFwcmV2aW91c1ROb2RlKSB7XG4gICAgcHJldmlvdXNUTm9kZSA9IHBhcmVudFROb2RlO1xuICB9XG5cbiAgLy8gUmUtb3JnYW5pemUgbm9kZSB0cmVlIHRvIHB1dCB0aGlzIG5vZGUgaW4gdGhlIGNvcnJlY3QgcG9zaXRpb24uXG4gIGlmIChwcmV2aW91c1ROb2RlID09PSBwYXJlbnRUTm9kZSAmJiB0Tm9kZSAhPT0gcGFyZW50VE5vZGUuY2hpbGQpIHtcbiAgICB0Tm9kZS5uZXh0ID0gcGFyZW50VE5vZGUuY2hpbGQ7XG4gICAgcGFyZW50VE5vZGUuY2hpbGQgPSB0Tm9kZTtcbiAgfSBlbHNlIGlmIChwcmV2aW91c1ROb2RlICE9PSBwYXJlbnRUTm9kZSAmJiB0Tm9kZSAhPT0gcHJldmlvdXNUTm9kZS5uZXh0KSB7XG4gICAgdE5vZGUubmV4dCA9IHByZXZpb3VzVE5vZGUubmV4dDtcbiAgICBwcmV2aW91c1ROb2RlLm5leHQgPSB0Tm9kZTtcbiAgfSBlbHNlIHtcbiAgICB0Tm9kZS5uZXh0ID0gbnVsbDtcbiAgfVxuXG4gIGlmIChwYXJlbnRUTm9kZSAhPT0gbFZpZXdbVF9IT1NUXSkge1xuICAgIHROb2RlLnBhcmVudCA9IHBhcmVudFROb2RlIGFzIFRFbGVtZW50Tm9kZTtcbiAgfVxuXG4gIC8vIElmIHROb2RlIHdhcyBtb3ZlZCBhcm91bmQsIHdlIG1pZ2h0IG5lZWQgdG8gZml4IGEgYnJva2VuIGxpbmsuXG4gIGxldCBjdXJzb3I6IFROb2RlfG51bGwgPSB0Tm9kZS5uZXh0O1xuICB3aGlsZSAoY3Vyc29yKSB7XG4gICAgaWYgKGN1cnNvci5uZXh0ID09PSB0Tm9kZSkge1xuICAgICAgY3Vyc29yLm5leHQgPSBuZXh0Tm9kZTtcbiAgICB9XG4gICAgY3Vyc29yID0gY3Vyc29yLm5leHQ7XG4gIH1cblxuICAvLyBJZiB0aGUgcGxhY2Vob2xkZXIgdG8gYXBwZW5kIGlzIGEgcHJvamVjdGlvbiwgd2UgbmVlZCB0byBtb3ZlIHRoZSBwcm9qZWN0ZWQgbm9kZXMgaW5zdGVhZFxuICBpZiAodE5vZGUudHlwZSA9PT0gVE5vZGVUeXBlLlByb2plY3Rpb24pIHtcbiAgICBhcHBseVByb2plY3Rpb24odFZpZXcsIGxWaWV3LCB0Tm9kZSBhcyBUUHJvamVjdGlvbk5vZGUpO1xuICAgIHJldHVybiB0Tm9kZTtcbiAgfVxuXG4gIGFwcGVuZENoaWxkKHRWaWV3LCBsVmlldywgZ2V0TmF0aXZlQnlUTm9kZSh0Tm9kZSwgbFZpZXcpLCB0Tm9kZSk7XG5cbiAgY29uc3Qgc2xvdFZhbHVlID0gbFZpZXdbdE5vZGUuaW5kZXhdO1xuICBpZiAodE5vZGUudHlwZSAhPT0gVE5vZGVUeXBlLkNvbnRhaW5lciAmJiBpc0xDb250YWluZXIoc2xvdFZhbHVlKSkge1xuICAgIC8vIE5vZGVzIHRoYXQgaW5qZWN0IFZpZXdDb250YWluZXJSZWYgYWxzbyBoYXZlIGEgY29tbWVudCBub2RlIHRoYXQgc2hvdWxkIGJlIG1vdmVkXG4gICAgYXBwZW5kQ2hpbGQodFZpZXcsIGxWaWV3LCBzbG90VmFsdWVbTkFUSVZFXSwgdE5vZGUpO1xuICB9XG4gIHJldHVybiB0Tm9kZTtcbn1cblxuZnVuY3Rpb24gaXNSb290VGVtcGxhdGVNZXNzYWdlKHN1YlRlbXBsYXRlSW5kZXg6IG51bWJlcnx1bmRlZmluZWQpOiBzdWJUZW1wbGF0ZUluZGV4IGlzIHVuZGVmaW5lZCB7XG4gIHJldHVybiBzdWJUZW1wbGF0ZUluZGV4ID09PSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogSGFuZGxlcyBtZXNzYWdlIHN0cmluZyBwb3N0LXByb2Nlc3NpbmcgZm9yIGludGVybmF0aW9uYWxpemF0aW9uLlxuICpcbiAqIEhhbmRsZXMgbWVzc2FnZSBzdHJpbmcgcG9zdC1wcm9jZXNzaW5nIGJ5IHRyYW5zZm9ybWluZyBpdCBmcm9tIGludGVybWVkaWF0ZVxuICogZm9ybWF0ICh0aGF0IG1pZ2h0IGNvbnRhaW4gc29tZSBtYXJrZXJzIHRoYXQgd2UgbmVlZCB0byByZXBsYWNlKSB0byB0aGUgZmluYWxcbiAqIGZvcm0sIGNvbnN1bWFibGUgYnkgaTE4blN0YXJ0IGluc3RydWN0aW9uLiBQb3N0IHByb2Nlc3Npbmcgc3RlcHMgaW5jbHVkZTpcbiAqXG4gKiAxLiBSZXNvbHZlIGFsbCBtdWx0aS12YWx1ZSBjYXNlcyAobGlrZSBb77+9KjE6Me+/ve+/vSMyOjHvv71877+9IzQ6Me+/vXzvv70177+9XSlcbiAqIDIuIFJlcGxhY2UgYWxsIElDVSB2YXJzIChsaWtlIFwiVkFSX1BMVVJBTFwiKVxuICogMy4gUmVwbGFjZSBhbGwgcGxhY2Vob2xkZXJzIHVzZWQgaW5zaWRlIElDVXMgaW4gYSBmb3JtIG9mIHtQTEFDRUhPTERFUn1cbiAqIDQuIFJlcGxhY2UgYWxsIElDVSByZWZlcmVuY2VzIHdpdGggY29ycmVzcG9uZGluZyB2YWx1ZXMgKGxpa2Ug77+9SUNVX0VYUF9JQ1VfMe+/vSlcbiAqICAgIGluIGNhc2UgbXVsdGlwbGUgSUNVcyBoYXZlIHRoZSBzYW1lIHBsYWNlaG9sZGVyIG5hbWVcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBSYXcgdHJhbnNsYXRpb24gc3RyaW5nIGZvciBwb3N0IHByb2Nlc3NpbmdcbiAqIEBwYXJhbSByZXBsYWNlbWVudHMgU2V0IG9mIHJlcGxhY2VtZW50cyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkXG4gKlxuICogQHJldHVybnMgVHJhbnNmb3JtZWQgc3RyaW5nIHRoYXQgY2FuIGJlIGNvbnN1bWVkIGJ5IGkxOG5TdGFydCBpbnN0cnVjdGlvblxuICpcbiAqIEBjb2RlR2VuQXBpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiDJtcm1aTE4blBvc3Rwcm9jZXNzKFxuICAgIG1lc3NhZ2U6IHN0cmluZywgcmVwbGFjZW1lbnRzOiB7W2tleTogc3RyaW5nXTogKHN0cmluZ3xzdHJpbmdbXSl9ID0ge30pOiBzdHJpbmcge1xuICAvKipcbiAgICogU3RlcCAxOiByZXNvbHZlIGFsbCBtdWx0aS12YWx1ZSBwbGFjZWhvbGRlcnMgbGlrZSBb77+9IzXvv71877+9KjE6Me+/ve+/vSMyOjHvv71877+9IzQ6Me+/vV1cbiAgICpcbiAgICogTm90ZTogZHVlIHRvIHRoZSB3YXkgd2UgcHJvY2VzcyBuZXN0ZWQgdGVtcGxhdGVzIChCRlMpLCBtdWx0aS12YWx1ZSBwbGFjZWhvbGRlcnMgYXJlIHR5cGljYWxseVxuICAgKiBncm91cGVkIGJ5IHRlbXBsYXRlcywgZm9yIGV4YW1wbGU6IFvvv70jNe+/vXzvv70jNu+/vXzvv70jMTox77+9fO+/vSMzOjLvv71dIHdoZXJlIO+/vSM177+9IGFuZCDvv70jNu+/vSBiZWxvbmcgdG8gcm9vdFxuICAgKiB0ZW1wbGF0ZSwg77+9IzE6Me+/vSBiZWxvbmcgdG8gbmVzdGVkIHRlbXBsYXRlIHdpdGggaW5kZXggMSBhbmQg77+9IzE6Mu+/vSAtIG5lc3RlZCB0ZW1wbGF0ZSB3aXRoIGluZGV4XG4gICAqIDMuIEhvd2V2ZXIgaW4gcmVhbCB0ZW1wbGF0ZXMgdGhlIG9yZGVyIG1pZ2h0IGJlIGRpZmZlcmVudDogaS5lLiDvv70jMTox77+9IGFuZC9vciDvv70jMzoy77+9IG1heSBnbyBpblxuICAgKiBmcm9udCBvZiDvv70jNu+/vS4gVGhlIHBvc3QgcHJvY2Vzc2luZyBzdGVwIHJlc3RvcmVzIHRoZSByaWdodCBvcmRlciBieSBrZWVwaW5nIHRyYWNrIG9mIHRoZVxuICAgKiB0ZW1wbGF0ZSBpZCBzdGFjayBhbmQgbG9va3MgZm9yIHBsYWNlaG9sZGVycyB0aGF0IGJlbG9uZyB0byB0aGUgY3VycmVudGx5IGFjdGl2ZSB0ZW1wbGF0ZS5cbiAgICovXG4gIGxldCByZXN1bHQ6IHN0cmluZyA9IG1lc3NhZ2U7XG4gIGlmIChQUF9NVUxUSV9WQUxVRV9QTEFDRUhPTERFUlNfUkVHRVhQLnRlc3QobWVzc2FnZSkpIHtcbiAgICBjb25zdCBtYXRjaGVzOiB7W2tleTogc3RyaW5nXTogUG9zdHByb2Nlc3NQbGFjZWhvbGRlcltdfSA9IHt9O1xuICAgIGNvbnN0IHRlbXBsYXRlSWRzU3RhY2s6IG51bWJlcltdID0gW1JPT1RfVEVNUExBVEVfSURdO1xuICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKFBQX1BMQUNFSE9MREVSU19SRUdFWFAsIChtOiBhbnksIHBoczogc3RyaW5nLCB0bXBsOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgY29udGVudCA9IHBocyB8fCB0bXBsO1xuICAgICAgY29uc3QgcGxhY2Vob2xkZXJzOiBQb3N0cHJvY2Vzc1BsYWNlaG9sZGVyW10gPSBtYXRjaGVzW2NvbnRlbnRdIHx8IFtdO1xuICAgICAgaWYgKCFwbGFjZWhvbGRlcnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnRlbnQuc3BsaXQoJ3wnKS5mb3JFYWNoKChwbGFjZWhvbGRlcjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgY29uc3QgbWF0Y2ggPSBwbGFjZWhvbGRlci5tYXRjaChQUF9URU1QTEFURV9JRF9SRUdFWFApO1xuICAgICAgICAgIGNvbnN0IHRlbXBsYXRlSWQgPSBtYXRjaCA/IHBhcnNlSW50KG1hdGNoWzFdLCAxMCkgOiBST09UX1RFTVBMQVRFX0lEO1xuICAgICAgICAgIGNvbnN0IGlzQ2xvc2VUZW1wbGF0ZVRhZyA9IFBQX0NMT1NFX1RFTVBMQVRFX1JFR0VYUC50ZXN0KHBsYWNlaG9sZGVyKTtcbiAgICAgICAgICBwbGFjZWhvbGRlcnMucHVzaChbdGVtcGxhdGVJZCwgaXNDbG9zZVRlbXBsYXRlVGFnLCBwbGFjZWhvbGRlcl0pO1xuICAgICAgICB9KTtcbiAgICAgICAgbWF0Y2hlc1tjb250ZW50XSA9IHBsYWNlaG9sZGVycztcbiAgICAgIH1cblxuICAgICAgaWYgKCFwbGFjZWhvbGRlcnMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaTE4biBwb3N0cHJvY2VzczogdW5tYXRjaGVkIHBsYWNlaG9sZGVyIC0gJHtjb250ZW50fWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjdXJyZW50VGVtcGxhdGVJZCA9IHRlbXBsYXRlSWRzU3RhY2tbdGVtcGxhdGVJZHNTdGFjay5sZW5ndGggLSAxXTtcbiAgICAgIGxldCBpZHggPSAwO1xuICAgICAgLy8gZmluZCBwbGFjZWhvbGRlciBpbmRleCB0aGF0IG1hdGNoZXMgY3VycmVudCB0ZW1wbGF0ZSBpZFxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwbGFjZWhvbGRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHBsYWNlaG9sZGVyc1tpXVswXSA9PT0gY3VycmVudFRlbXBsYXRlSWQpIHtcbiAgICAgICAgICBpZHggPSBpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyB1cGRhdGUgdGVtcGxhdGUgaWQgc3RhY2sgYmFzZWQgb24gdGhlIGN1cnJlbnQgdGFnIGV4dHJhY3RlZFxuICAgICAgY29uc3QgW3RlbXBsYXRlSWQsIGlzQ2xvc2VUZW1wbGF0ZVRhZywgcGxhY2Vob2xkZXJdID0gcGxhY2Vob2xkZXJzW2lkeF07XG4gICAgICBpZiAoaXNDbG9zZVRlbXBsYXRlVGFnKSB7XG4gICAgICAgIHRlbXBsYXRlSWRzU3RhY2sucG9wKCk7XG4gICAgICB9IGVsc2UgaWYgKGN1cnJlbnRUZW1wbGF0ZUlkICE9PSB0ZW1wbGF0ZUlkKSB7XG4gICAgICAgIHRlbXBsYXRlSWRzU3RhY2sucHVzaCh0ZW1wbGF0ZUlkKTtcbiAgICAgIH1cbiAgICAgIC8vIHJlbW92ZSBwcm9jZXNzZWQgdGFnIGZyb20gdGhlIGxpc3RcbiAgICAgIHBsYWNlaG9sZGVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgIHJldHVybiBwbGFjZWhvbGRlcjtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIHJldHVybiBjdXJyZW50IHJlc3VsdCBpZiBubyByZXBsYWNlbWVudHMgc3BlY2lmaWVkXG4gIGlmICghT2JqZWN0LmtleXMocmVwbGFjZW1lbnRzKS5sZW5ndGgpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFN0ZXAgMjogcmVwbGFjZSBhbGwgSUNVIHZhcnMgKGxpa2UgXCJWQVJfUExVUkFMXCIpXG4gICAqL1xuICByZXN1bHQgPSByZXN1bHQucmVwbGFjZShQUF9JQ1VfVkFSU19SRUdFWFAsIChtYXRjaCwgc3RhcnQsIGtleSwgX3R5cGUsIF9pZHgsIGVuZCk6IHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIHJlcGxhY2VtZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpID8gYCR7c3RhcnR9JHtyZXBsYWNlbWVudHNba2V5XX0ke2VuZH1gIDogbWF0Y2g7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBTdGVwIDM6IHJlcGxhY2UgYWxsIHBsYWNlaG9sZGVycyB1c2VkIGluc2lkZSBJQ1VzIGluIGEgZm9ybSBvZiB7UExBQ0VIT0xERVJ9XG4gICAqL1xuICByZXN1bHQgPSByZXN1bHQucmVwbGFjZShQUF9JQ1VfUExBQ0VIT0xERVJTX1JFR0VYUCwgKG1hdGNoLCBrZXkpOiBzdHJpbmcgPT4ge1xuICAgIHJldHVybiByZXBsYWNlbWVudHMuaGFzT3duUHJvcGVydHkoa2V5KSA/IHJlcGxhY2VtZW50c1trZXldIGFzIHN0cmluZyA6IG1hdGNoO1xuICB9KTtcblxuICAvKipcbiAgICogU3RlcCA0OiByZXBsYWNlIGFsbCBJQ1UgcmVmZXJlbmNlcyB3aXRoIGNvcnJlc3BvbmRpbmcgdmFsdWVzIChsaWtlIO+/vUlDVV9FWFBfSUNVXzHvv70pIGluIGNhc2VcbiAgICogbXVsdGlwbGUgSUNVcyBoYXZlIHRoZSBzYW1lIHBsYWNlaG9sZGVyIG5hbWVcbiAgICovXG4gIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKFBQX0lDVVNfUkVHRVhQLCAobWF0Y2gsIGtleSk6IHN0cmluZyA9PiB7XG4gICAgaWYgKHJlcGxhY2VtZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICBjb25zdCBsaXN0ID0gcmVwbGFjZW1lbnRzW2tleV0gYXMgc3RyaW5nW107XG4gICAgICBpZiAoIWxpc3QubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaTE4biBwb3N0cHJvY2VzczogdW5tYXRjaGVkIElDVSAtICR7bWF0Y2h9IHdpdGgga2V5OiAke2tleX1gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsaXN0LnNoaWZ0KCkhO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2g7XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogVHJhbnNsYXRlcyBhIHRyYW5zbGF0aW9uIGJsb2NrIG1hcmtlZCBieSBgaTE4blN0YXJ0YCBhbmQgYGkxOG5FbmRgLiBJdCBpbnNlcnRzIHRoZSB0ZXh0L0lDVSBub2Rlc1xuICogaW50byB0aGUgcmVuZGVyIHRyZWUsIG1vdmVzIHRoZSBwbGFjZWhvbGRlciBub2RlcyBhbmQgcmVtb3ZlcyB0aGUgZGVsZXRlZCBub2Rlcy5cbiAqXG4gKiBAY29kZUdlbkFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gybXJtWkxOG5FbmQoKTogdm9pZCB7XG4gIGNvbnN0IGxWaWV3ID0gZ2V0TFZpZXcoKTtcbiAgY29uc3QgdFZpZXcgPSBnZXRUVmlldygpO1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0RGVmaW5lZCh0VmlldywgYHRWaWV3IHNob3VsZCBiZSBkZWZpbmVkYCk7XG4gIGkxOG5FbmRGaXJzdFBhc3ModFZpZXcsIGxWaWV3KTtcbiAgLy8gU3RvcCBkZWxheWluZyBwcm9qZWN0aW9uc1xuICBzZXREZWxheVByb2plY3Rpb24oZmFsc2UpO1xufVxuXG4vKipcbiAqIFNlZSBgaTE4bkVuZGAgYWJvdmUuXG4gKi9cbmZ1bmN0aW9uIGkxOG5FbmRGaXJzdFBhc3ModFZpZXc6IFRWaWV3LCBsVmlldzogTFZpZXcpIHtcbiAgbmdEZXZNb2RlICYmXG4gICAgICBhc3NlcnRFcXVhbChcbiAgICAgICAgICBnZXRCaW5kaW5nSW5kZXgoKSwgdFZpZXcuYmluZGluZ1N0YXJ0SW5kZXgsXG4gICAgICAgICAgJ2kxOG5FbmQgc2hvdWxkIGJlIGNhbGxlZCBiZWZvcmUgYW55IGJpbmRpbmcnKTtcblxuICBjb25zdCByb290SW5kZXggPSBpMThuSW5kZXhTdGFja1tpMThuSW5kZXhTdGFja1BvaW50ZXItLV07XG4gIGNvbnN0IHRJMThuID0gdFZpZXcuZGF0YVtyb290SW5kZXggKyBIRUFERVJfT0ZGU0VUXSBhcyBUSTE4bjtcbiAgbmdEZXZNb2RlICYmIGFzc2VydERlZmluZWQodEkxOG4sIGBZb3Ugc2hvdWxkIGNhbGwgaTE4blN0YXJ0IGJlZm9yZSBpMThuRW5kYCk7XG5cbiAgLy8gRmluZCB0aGUgbGFzdCBub2RlIHRoYXQgd2FzIGFkZGVkIGJlZm9yZSBgaTE4bkVuZGBcbiAgY29uc3QgbGFzdENyZWF0ZWROb2RlID0gZ2V0UHJldmlvdXNPclBhcmVudFROb2RlKCk7XG5cbiAgLy8gUmVhZCB0aGUgaW5zdHJ1Y3Rpb25zIHRvIGluc2VydC9tb3ZlL3JlbW92ZSBET00gZWxlbWVudHNcbiAgY29uc3QgdmlzaXRlZE5vZGVzID0gcmVhZENyZWF0ZU9wQ29kZXMocm9vdEluZGV4LCB0STE4bi5jcmVhdGUsIHRWaWV3LCBsVmlldyk7XG5cbiAgLy8gUmVtb3ZlIGRlbGV0ZWQgbm9kZXNcbiAgbGV0IGluZGV4ID0gcm9vdEluZGV4ICsgMTtcbiAgd2hpbGUgKGluZGV4IDw9IGxhc3RDcmVhdGVkTm9kZS5pbmRleCAtIEhFQURFUl9PRkZTRVQpIHtcbiAgICBpZiAodmlzaXRlZE5vZGVzLmluZGV4T2YoaW5kZXgpID09PSAtMSkge1xuICAgICAgcmVtb3ZlTm9kZSh0VmlldywgbFZpZXcsIGluZGV4LCAvKiBtYXJrQXNEZXRhY2hlZCAqLyB0cnVlKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgaWYgYW4gZWxlbWVudCBoYXMgYW55IGxvY2FsIHJlZnMgYW5kIHNraXAgdGhlbVxuICAgIGNvbnN0IHROb2RlID0gZ2V0VE5vZGUodFZpZXcsIGluZGV4KTtcbiAgICBpZiAodE5vZGUgJiZcbiAgICAgICAgKHROb2RlLnR5cGUgPT09IFROb2RlVHlwZS5Db250YWluZXIgfHwgdE5vZGUudHlwZSA9PT0gVE5vZGVUeXBlLkVsZW1lbnQgfHxcbiAgICAgICAgIHROb2RlLnR5cGUgPT09IFROb2RlVHlwZS5FbGVtZW50Q29udGFpbmVyKSAmJlxuICAgICAgICB0Tm9kZS5sb2NhbE5hbWVzICE9PSBudWxsKSB7XG4gICAgICAvLyBEaXZpZGUgYnkgMiB0byBnZXQgdGhlIG51bWJlciBvZiBsb2NhbCByZWZzLFxuICAgICAgLy8gc2luY2UgdGhleSBhcmUgc3RvcmVkIGFzIGFuIGFycmF5IHRoYXQgYWxzbyBpbmNsdWRlcyBkaXJlY3RpdmUgaW5kZXhlcyxcbiAgICAgIC8vIGkuZS4gW1wibG9jYWxSZWZcIiwgZGlyZWN0aXZlSW5kZXgsIC4uLl1cbiAgICAgIGluZGV4ICs9IHROb2RlLmxvY2FsTmFtZXMubGVuZ3RoID4+IDE7XG4gICAgfVxuICAgIGluZGV4Kys7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuZCBzdG9yZXMgdGhlIGR5bmFtaWMgVE5vZGUsIGFuZCB1bmhvb2tzIGl0IGZyb20gdGhlIHRyZWUgZm9yIG5vdy5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlRHluYW1pY05vZGVBdEluZGV4KFxuICAgIHRWaWV3OiBUVmlldywgbFZpZXc6IExWaWV3LCBpbmRleDogbnVtYmVyLCB0eXBlOiBUTm9kZVR5cGUsIG5hdGl2ZTogUkVsZW1lbnR8UlRleHR8bnVsbCxcbiAgICBuYW1lOiBzdHJpbmd8bnVsbCk6IFRFbGVtZW50Tm9kZXxUSWN1Q29udGFpbmVyTm9kZSB7XG4gIGNvbnN0IHByZXZpb3VzT3JQYXJlbnRUTm9kZSA9IGdldFByZXZpb3VzT3JQYXJlbnRUTm9kZSgpO1xuICBuZ0Rldk1vZGUgJiYgYXNzZXJ0RGF0YUluUmFuZ2UobFZpZXcsIGluZGV4ICsgSEVBREVSX09GRlNFVCk7XG4gIGxWaWV3W2luZGV4ICsgSEVBREVSX09GRlNFVF0gPSBuYXRpdmU7XG4gIGNvbnN0IHROb2RlID0gZ2V0T3JDcmVhdGVUTm9kZSh0VmlldywgbFZpZXdbVF9IT1NUXSwgaW5kZXgsIHR5cGUgYXMgYW55LCBuYW1lLCBudWxsKTtcblxuICAvLyBXZSBhcmUgY3JlYXRpbmcgYSBkeW5hbWljIG5vZGUsIHRoZSBwcmV2aW91cyB0Tm9kZSBtaWdodCBub3QgYmUgcG9pbnRpbmcgYXQgdGhpcyBub2RlLlxuICAvLyBXZSB3aWxsIGxpbmsgb3Vyc2VsdmVzIGludG8gdGhlIHRyZWUgbGF0ZXIgd2l0aCBgYXBwZW5kSTE4bk5vZGVgLlxuICBpZiAocHJldmlvdXNPclBhcmVudFROb2RlICYmIHByZXZpb3VzT3JQYXJlbnRUTm9kZS5uZXh0ID09PSB0Tm9kZSkge1xuICAgIHByZXZpb3VzT3JQYXJlbnRUTm9kZS5uZXh0ID0gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB0Tm9kZTtcbn1cblxuZnVuY3Rpb24gcmVhZENyZWF0ZU9wQ29kZXMoXG4gICAgaW5kZXg6IG51bWJlciwgY3JlYXRlT3BDb2RlczogSTE4bk11dGF0ZU9wQ29kZXMsIHRWaWV3OiBUVmlldywgbFZpZXc6IExWaWV3KTogbnVtYmVyW10ge1xuICBjb25zdCByZW5kZXJlciA9IGxWaWV3W1JFTkRFUkVSXTtcbiAgbGV0IGN1cnJlbnRUTm9kZTogVE5vZGV8bnVsbCA9IG51bGw7XG4gIGxldCBwcmV2aW91c1ROb2RlOiBUTm9kZXxudWxsID0gbnVsbDtcbiAgY29uc3QgdmlzaXRlZE5vZGVzOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGNyZWF0ZU9wQ29kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBvcENvZGUgPSBjcmVhdGVPcENvZGVzW2ldO1xuICAgIGlmICh0eXBlb2Ygb3BDb2RlID09ICdzdHJpbmcnKSB7XG4gICAgICBjb25zdCB0ZXh0Uk5vZGUgPSBjcmVhdGVUZXh0Tm9kZShvcENvZGUsIHJlbmRlcmVyKTtcbiAgICAgIGNvbnN0IHRleHROb2RlSW5kZXggPSBjcmVhdGVPcENvZGVzWysraV0gYXMgbnVtYmVyO1xuICAgICAgbmdEZXZNb2RlICYmIG5nRGV2TW9kZS5yZW5kZXJlckNyZWF0ZVRleHROb2RlKys7XG4gICAgICBwcmV2aW91c1ROb2RlID0gY3VycmVudFROb2RlO1xuICAgICAgY3VycmVudFROb2RlID1cbiAgICAgICAgICBjcmVhdGVEeW5hbWljTm9kZUF0SW5kZXgodFZpZXcsIGxWaWV3LCB0ZXh0Tm9kZUluZGV4LCBUTm9kZVR5cGUuRWxlbWVudCwgdGV4dFJOb2RlLCBudWxsKTtcbiAgICAgIHZpc2l0ZWROb2Rlcy5wdXNoKHRleHROb2RlSW5kZXgpO1xuICAgICAgc2V0SXNOb3RQYXJlbnQoKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcENvZGUgPT0gJ251bWJlcicpIHtcbiAgICAgIHN3aXRjaCAob3BDb2RlICYgSTE4bk11dGF0ZU9wQ29kZS5NQVNLX09QQ09ERSkge1xuICAgICAgICBjYXNlIEkxOG5NdXRhdGVPcENvZGUuQXBwZW5kQ2hpbGQ6XG4gICAgICAgICAgY29uc3QgZGVzdGluYXRpb25Ob2RlSW5kZXggPSBvcENvZGUgPj4+IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUEFSRU5UO1xuICAgICAgICAgIGxldCBkZXN0aW5hdGlvblROb2RlOiBUTm9kZTtcbiAgICAgICAgICBpZiAoZGVzdGluYXRpb25Ob2RlSW5kZXggPT09IGluZGV4KSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgZGVzdGluYXRpb24gbm9kZSBpcyBgaTE4blN0YXJ0YCwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAvLyB0b3AtbGV2ZWwgbm9kZSBhbmQgd2Ugc2hvdWxkIHVzZSB0aGUgaG9zdCBub2RlIGluc3RlYWRcbiAgICAgICAgICAgIGRlc3RpbmF0aW9uVE5vZGUgPSBsVmlld1tUX0hPU1RdITtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVzdGluYXRpb25UTm9kZSA9IGdldFROb2RlKHRWaWV3LCBkZXN0aW5hdGlvbk5vZGVJbmRleCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG5nRGV2TW9kZSAmJlxuICAgICAgICAgICAgICBhc3NlcnREZWZpbmVkKFxuICAgICAgICAgICAgICAgICAgY3VycmVudFROb2RlISxcbiAgICAgICAgICAgICAgICAgIGBZb3UgbmVlZCB0byBjcmVhdGUgb3Igc2VsZWN0IGEgbm9kZSBiZWZvcmUgeW91IGNhbiBpbnNlcnQgaXQgaW50byB0aGUgRE9NYCk7XG4gICAgICAgICAgcHJldmlvdXNUTm9kZSA9XG4gICAgICAgICAgICAgIGFwcGVuZEkxOG5Ob2RlKHRWaWV3LCBjdXJyZW50VE5vZGUhLCBkZXN0aW5hdGlvblROb2RlLCBwcmV2aW91c1ROb2RlLCBsVmlldyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSTE4bk11dGF0ZU9wQ29kZS5TZWxlY3Q6XG4gICAgICAgICAgLy8gTmVnYXRpdmUgaW5kaWNpZXMgaW5kaWNhdGUgdGhhdCBhIGdpdmVuIFROb2RlIGlzIGEgc2libGluZyBub2RlLCBub3QgYSBwYXJlbnQgbm9kZVxuICAgICAgICAgIC8vIChzZWUgYGkxOG5TdGFydEZpcnN0UGFzc2AgZm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24pLlxuICAgICAgICAgIGNvbnN0IGlzUGFyZW50ID0gb3BDb2RlID49IDA7XG4gICAgICAgICAgY29uc3Qgbm9kZUluZGV4ID0gKGlzUGFyZW50ID8gb3BDb2RlIDogfm9wQ29kZSkgPj4+IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUkVGO1xuICAgICAgICAgIHZpc2l0ZWROb2Rlcy5wdXNoKG5vZGVJbmRleCk7XG4gICAgICAgICAgcHJldmlvdXNUTm9kZSA9IGN1cnJlbnRUTm9kZTtcbiAgICAgICAgICBjdXJyZW50VE5vZGUgPSBnZXRUTm9kZSh0Vmlldywgbm9kZUluZGV4KTtcbiAgICAgICAgICBpZiAoY3VycmVudFROb2RlKSB7XG4gICAgICAgICAgICBzZXRQcmV2aW91c09yUGFyZW50VE5vZGUoY3VycmVudFROb2RlLCBpc1BhcmVudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEkxOG5NdXRhdGVPcENvZGUuRWxlbWVudEVuZDpcbiAgICAgICAgICBjb25zdCBlbGVtZW50SW5kZXggPSBvcENvZGUgPj4+IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUkVGO1xuICAgICAgICAgIHByZXZpb3VzVE5vZGUgPSBjdXJyZW50VE5vZGUgPSBnZXRUTm9kZSh0VmlldywgZWxlbWVudEluZGV4KTtcbiAgICAgICAgICBzZXRQcmV2aW91c09yUGFyZW50VE5vZGUoY3VycmVudFROb2RlLCBmYWxzZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSTE4bk11dGF0ZU9wQ29kZS5BdHRyOlxuICAgICAgICAgIGNvbnN0IGVsZW1lbnROb2RlSW5kZXggPSBvcENvZGUgPj4+IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUkVGO1xuICAgICAgICAgIGNvbnN0IGF0dHJOYW1lID0gY3JlYXRlT3BDb2Rlc1srK2ldIGFzIHN0cmluZztcbiAgICAgICAgICBjb25zdCBhdHRyVmFsdWUgPSBjcmVhdGVPcENvZGVzWysraV0gYXMgc3RyaW5nO1xuICAgICAgICAgIC8vIFRoaXMgY29kZSBpcyB1c2VkIGZvciBJQ1UgZXhwcmVzc2lvbnMgb25seSwgc2luY2Ugd2UgZG9uJ3Qgc3VwcG9ydFxuICAgICAgICAgIC8vIGRpcmVjdGl2ZXMvY29tcG9uZW50cyBpbiBJQ1VzLCB3ZSBkb24ndCBuZWVkIHRvIHdvcnJ5IGFib3V0IGlucHV0cyBoZXJlXG4gICAgICAgICAgZWxlbWVudEF0dHJpYnV0ZUludGVybmFsKFxuICAgICAgICAgICAgICBnZXRUTm9kZSh0VmlldywgZWxlbWVudE5vZGVJbmRleCksIGxWaWV3LCBhdHRyTmFtZSwgYXR0clZhbHVlLCBudWxsLCBudWxsKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBkZXRlcm1pbmUgdGhlIHR5cGUgb2YgbXV0YXRlIG9wZXJhdGlvbiBmb3IgXCIke29wQ29kZX1cImApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzd2l0Y2ggKG9wQ29kZSkge1xuICAgICAgICBjYXNlIENPTU1FTlRfTUFSS0VSOlxuICAgICAgICAgIGNvbnN0IGNvbW1lbnRWYWx1ZSA9IGNyZWF0ZU9wQ29kZXNbKytpXSBhcyBzdHJpbmc7XG4gICAgICAgICAgY29uc3QgY29tbWVudE5vZGVJbmRleCA9IGNyZWF0ZU9wQ29kZXNbKytpXSBhcyBudW1iZXI7XG4gICAgICAgICAgbmdEZXZNb2RlICYmXG4gICAgICAgICAgICAgIGFzc2VydEVxdWFsKFxuICAgICAgICAgICAgICAgICAgdHlwZW9mIGNvbW1lbnRWYWx1ZSwgJ3N0cmluZycsXG4gICAgICAgICAgICAgICAgICBgRXhwZWN0ZWQgXCIke2NvbW1lbnRWYWx1ZX1cIiB0byBiZSBhIGNvbW1lbnQgbm9kZSB2YWx1ZWApO1xuICAgICAgICAgIGNvbnN0IGNvbW1lbnRSTm9kZSA9IHJlbmRlcmVyLmNyZWF0ZUNvbW1lbnQoY29tbWVudFZhbHVlKTtcbiAgICAgICAgICBuZ0Rldk1vZGUgJiYgbmdEZXZNb2RlLnJlbmRlcmVyQ3JlYXRlQ29tbWVudCsrO1xuICAgICAgICAgIHByZXZpb3VzVE5vZGUgPSBjdXJyZW50VE5vZGU7XG4gICAgICAgICAgY3VycmVudFROb2RlID0gY3JlYXRlRHluYW1pY05vZGVBdEluZGV4KFxuICAgICAgICAgICAgICB0VmlldywgbFZpZXcsIGNvbW1lbnROb2RlSW5kZXgsIFROb2RlVHlwZS5JY3VDb250YWluZXIsIGNvbW1lbnRSTm9kZSwgbnVsbCk7XG4gICAgICAgICAgdmlzaXRlZE5vZGVzLnB1c2goY29tbWVudE5vZGVJbmRleCk7XG4gICAgICAgICAgYXR0YWNoUGF0Y2hEYXRhKGNvbW1lbnRSTm9kZSwgbFZpZXcpO1xuICAgICAgICAgIChjdXJyZW50VE5vZGUgYXMgVEljdUNvbnRhaW5lck5vZGUpLmFjdGl2ZUNhc2VJbmRleCA9IG51bGw7XG4gICAgICAgICAgLy8gV2Ugd2lsbCBhZGQgdGhlIGNhc2Ugbm9kZXMgbGF0ZXIsIGR1cmluZyB0aGUgdXBkYXRlIHBoYXNlXG4gICAgICAgICAgc2V0SXNOb3RQYXJlbnQoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBFTEVNRU5UX01BUktFUjpcbiAgICAgICAgICBjb25zdCB0YWdOYW1lVmFsdWUgPSBjcmVhdGVPcENvZGVzWysraV0gYXMgc3RyaW5nO1xuICAgICAgICAgIGNvbnN0IGVsZW1lbnROb2RlSW5kZXggPSBjcmVhdGVPcENvZGVzWysraV0gYXMgbnVtYmVyO1xuICAgICAgICAgIG5nRGV2TW9kZSAmJlxuICAgICAgICAgICAgICBhc3NlcnRFcXVhbChcbiAgICAgICAgICAgICAgICAgIHR5cGVvZiB0YWdOYW1lVmFsdWUsICdzdHJpbmcnLFxuICAgICAgICAgICAgICAgICAgYEV4cGVjdGVkIFwiJHt0YWdOYW1lVmFsdWV9XCIgdG8gYmUgYW4gZWxlbWVudCBub2RlIHRhZyBuYW1lYCk7XG4gICAgICAgICAgY29uc3QgZWxlbWVudFJOb2RlID0gcmVuZGVyZXIuY3JlYXRlRWxlbWVudCh0YWdOYW1lVmFsdWUpO1xuICAgICAgICAgIG5nRGV2TW9kZSAmJiBuZ0Rldk1vZGUucmVuZGVyZXJDcmVhdGVFbGVtZW50Kys7XG4gICAgICAgICAgcHJldmlvdXNUTm9kZSA9IGN1cnJlbnRUTm9kZTtcbiAgICAgICAgICBjdXJyZW50VE5vZGUgPSBjcmVhdGVEeW5hbWljTm9kZUF0SW5kZXgoXG4gICAgICAgICAgICAgIHRWaWV3LCBsVmlldywgZWxlbWVudE5vZGVJbmRleCwgVE5vZGVUeXBlLkVsZW1lbnQsIGVsZW1lbnRSTm9kZSwgdGFnTmFtZVZhbHVlKTtcbiAgICAgICAgICB2aXNpdGVkTm9kZXMucHVzaChlbGVtZW50Tm9kZUluZGV4KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBkZXRlcm1pbmUgdGhlIHR5cGUgb2YgbXV0YXRlIG9wZXJhdGlvbiBmb3IgXCIke29wQ29kZX1cImApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNldElzTm90UGFyZW50KCk7XG5cbiAgcmV0dXJuIHZpc2l0ZWROb2Rlcztcbn1cblxuZnVuY3Rpb24gcmVhZFVwZGF0ZU9wQ29kZXMoXG4gICAgdXBkYXRlT3BDb2RlczogSTE4blVwZGF0ZU9wQ29kZXMsIGljdXM6IFRJY3VbXXxudWxsLCBiaW5kaW5nc1N0YXJ0SW5kZXg6IG51bWJlcixcbiAgICBjaGFuZ2VNYXNrOiBudW1iZXIsIHRWaWV3OiBUVmlldywgbFZpZXc6IExWaWV3LCBieXBhc3NDaGVja0JpdCA9IGZhbHNlKSB7XG4gIGxldCBjYXNlQ3JlYXRlZCA9IGZhbHNlO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHVwZGF0ZU9wQ29kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBiaXQgY29kZSB0byBjaGVjayBpZiB3ZSBzaG91bGQgYXBwbHkgdGhlIG5leHQgdXBkYXRlXG4gICAgY29uc3QgY2hlY2tCaXQgPSB1cGRhdGVPcENvZGVzW2ldIGFzIG51bWJlcjtcbiAgICAvLyBOdW1iZXIgb2Ygb3BDb2RlcyB0byBza2lwIHVudGlsIG5leHQgc2V0IG9mIHVwZGF0ZSBjb2Rlc1xuICAgIGNvbnN0IHNraXBDb2RlcyA9IHVwZGF0ZU9wQ29kZXNbKytpXSBhcyBudW1iZXI7XG4gICAgaWYgKGJ5cGFzc0NoZWNrQml0IHx8IChjaGVja0JpdCAmIGNoYW5nZU1hc2spKSB7XG4gICAgICAvLyBUaGUgdmFsdWUgaGFzIGJlZW4gdXBkYXRlZCBzaW5jZSBsYXN0IGNoZWNrZWRcbiAgICAgIGxldCB2YWx1ZSA9ICcnO1xuICAgICAgZm9yIChsZXQgaiA9IGkgKyAxOyBqIDw9IChpICsgc2tpcENvZGVzKTsgaisrKSB7XG4gICAgICAgIGNvbnN0IG9wQ29kZSA9IHVwZGF0ZU9wQ29kZXNbal07XG4gICAgICAgIGlmICh0eXBlb2Ygb3BDb2RlID09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdmFsdWUgKz0gb3BDb2RlO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcENvZGUgPT0gJ251bWJlcicpIHtcbiAgICAgICAgICBpZiAob3BDb2RlIDwgMCkge1xuICAgICAgICAgICAgLy8gSXQncyBhIGJpbmRpbmcgaW5kZXggd2hvc2UgdmFsdWUgaXMgbmVnYXRpdmVcbiAgICAgICAgICAgIHZhbHVlICs9IHJlbmRlclN0cmluZ2lmeShsVmlld1tiaW5kaW5nc1N0YXJ0SW5kZXggLSBvcENvZGVdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgbm9kZUluZGV4ID0gb3BDb2RlID4+PiBJMThuVXBkYXRlT3BDb2RlLlNISUZUX1JFRjtcbiAgICAgICAgICAgIGxldCB0SWN1SW5kZXg6IG51bWJlcjtcbiAgICAgICAgICAgIGxldCB0SWN1OiBUSWN1O1xuICAgICAgICAgICAgbGV0IGljdVROb2RlOiBUSWN1Q29udGFpbmVyTm9kZTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BDb2RlICYgSTE4blVwZGF0ZU9wQ29kZS5NQVNLX09QQ09ERSkge1xuICAgICAgICAgICAgICBjYXNlIEkxOG5VcGRhdGVPcENvZGUuQXR0cjpcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9wTmFtZSA9IHVwZGF0ZU9wQ29kZXNbKytqXSBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2FuaXRpemVGbiA9IHVwZGF0ZU9wQ29kZXNbKytqXSBhcyBTYW5pdGl6ZXJGbiB8IG51bGw7XG4gICAgICAgICAgICAgICAgZWxlbWVudFByb3BlcnR5SW50ZXJuYWwoXG4gICAgICAgICAgICAgICAgICAgIHRWaWV3LCBnZXRUTm9kZSh0Vmlldywgbm9kZUluZGV4KSwgbFZpZXcsIHByb3BOYW1lLCB2YWx1ZSwgbFZpZXdbUkVOREVSRVJdLFxuICAgICAgICAgICAgICAgICAgICBzYW5pdGl6ZUZuLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgSTE4blVwZGF0ZU9wQ29kZS5UZXh0OlxuICAgICAgICAgICAgICAgIHRleHRCaW5kaW5nSW50ZXJuYWwobFZpZXcsIG5vZGVJbmRleCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlIEkxOG5VcGRhdGVPcENvZGUuSWN1U3dpdGNoOlxuICAgICAgICAgICAgICAgIHRJY3VJbmRleCA9IHVwZGF0ZU9wQ29kZXNbKytqXSBhcyBudW1iZXI7XG4gICAgICAgICAgICAgICAgdEljdSA9IGljdXMhW3RJY3VJbmRleF07XG4gICAgICAgICAgICAgICAgaWN1VE5vZGUgPSBnZXRUTm9kZSh0Vmlldywgbm9kZUluZGV4KSBhcyBUSWN1Q29udGFpbmVyTm9kZTtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBhbiBhY3RpdmUgY2FzZSwgZGVsZXRlIHRoZSBvbGQgbm9kZXNcbiAgICAgICAgICAgICAgICBpZiAoaWN1VE5vZGUuYWN0aXZlQ2FzZUluZGV4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCByZW1vdmVDb2RlcyA9IHRJY3UucmVtb3ZlW2ljdVROb2RlLmFjdGl2ZUNhc2VJbmRleF07XG4gICAgICAgICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHJlbW92ZUNvZGVzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbW92ZU9wQ29kZSA9IHJlbW92ZUNvZGVzW2tdIGFzIG51bWJlcjtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyZW1vdmVPcENvZGUgJiBJMThuTXV0YXRlT3BDb2RlLk1BU0tfT1BDT0RFKSB7XG4gICAgICAgICAgICAgICAgICAgICAgY2FzZSBJMThuTXV0YXRlT3BDb2RlLlJlbW92ZTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vZGVJbmRleCA9IHJlbW92ZU9wQ29kZSA+Pj4gSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUY7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgRE9NIGVsZW1lbnQsIGJ1dCBkbyAqbm90KiBtYXJrIFROb2RlIGFzIGRldGFjaGVkLCBzaW5jZSB3ZSBhcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGp1c3Qgc3dpdGNoaW5nIElDVSBjYXNlcyAod2hpbGUga2VlcGluZyB0aGUgc2FtZSBUTm9kZSksIHNvIGEgRE9NIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlcHJlc2VudGluZyBhIG5ldyBJQ1UgY2FzZSB3aWxsIGJlIHJlLWNyZWF0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVOb2RlKHRWaWV3LCBsVmlldywgbm9kZUluZGV4LCAvKiBtYXJrQXNEZXRhY2hlZCAqLyBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICBjYXNlIEkxOG5NdXRhdGVPcENvZGUuUmVtb3ZlTmVzdGVkSWN1OlxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmVzdGVkSWN1Tm9kZUluZGV4ID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVDb2Rlc1trICsgMV0gYXMgbnVtYmVyID4+PiBJMThuTXV0YXRlT3BDb2RlLlNISUZUX1JFRjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5lc3RlZEljdVROb2RlID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRUTm9kZSh0VmlldywgbmVzdGVkSWN1Tm9kZUluZGV4KSBhcyBUSWN1Q29udGFpbmVyTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjdGl2ZUluZGV4ID0gbmVzdGVkSWN1VE5vZGUuYWN0aXZlQ2FzZUluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFjdGl2ZUluZGV4ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5lc3RlZEljdVRJbmRleCA9IHJlbW92ZU9wQ29kZSA+Pj4gSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5lc3RlZFRJY3UgPSBpY3VzIVtuZXN0ZWRJY3VUSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRBbGxUb0FycmF5KG5lc3RlZFRJY3UucmVtb3ZlW2FjdGl2ZUluZGV4XSwgcmVtb3ZlQ29kZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGFjdGl2ZSBjYXNlSW5kZXhcbiAgICAgICAgICAgICAgICBjb25zdCBjYXNlSW5kZXggPSBnZXRDYXNlSW5kZXgodEljdSwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIGljdVROb2RlLmFjdGl2ZUNhc2VJbmRleCA9IGNhc2VJbmRleCAhPT0gLTEgPyBjYXNlSW5kZXggOiBudWxsO1xuICAgICAgICAgICAgICAgIGlmIChjYXNlSW5kZXggPiAtMSkge1xuICAgICAgICAgICAgICAgICAgLy8gQWRkIHRoZSBub2RlcyBmb3IgdGhlIG5ldyBjYXNlXG4gICAgICAgICAgICAgICAgICByZWFkQ3JlYXRlT3BDb2RlcygtMSwgdEljdS5jcmVhdGVbY2FzZUluZGV4XSwgdFZpZXcsIGxWaWV3KTtcbiAgICAgICAgICAgICAgICAgIGNhc2VDcmVhdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgSTE4blVwZGF0ZU9wQ29kZS5JY3VVcGRhdGU6XG4gICAgICAgICAgICAgICAgdEljdUluZGV4ID0gdXBkYXRlT3BDb2Rlc1srK2pdIGFzIG51bWJlcjtcbiAgICAgICAgICAgICAgICB0SWN1ID0gaWN1cyFbdEljdUluZGV4XTtcbiAgICAgICAgICAgICAgICBpY3VUTm9kZSA9IGdldFROb2RlKHRWaWV3LCBub2RlSW5kZXgpIGFzIFRJY3VDb250YWluZXJOb2RlO1xuICAgICAgICAgICAgICAgIGlmIChpY3VUTm9kZS5hY3RpdmVDYXNlSW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgIHJlYWRVcGRhdGVPcENvZGVzKFxuICAgICAgICAgICAgICAgICAgICAgIHRJY3UudXBkYXRlW2ljdVROb2RlLmFjdGl2ZUNhc2VJbmRleF0sIGljdXMsIGJpbmRpbmdzU3RhcnRJbmRleCwgY2hhbmdlTWFzayxcbiAgICAgICAgICAgICAgICAgICAgICB0VmlldywgbFZpZXcsIGNhc2VDcmVhdGVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGkgKz0gc2tpcENvZGVzO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5vZGUodFZpZXc6IFRWaWV3LCBsVmlldzogTFZpZXcsIGluZGV4OiBudW1iZXIsIG1hcmtBc0RldGFjaGVkOiBib29sZWFuKSB7XG4gIGNvbnN0IHJlbW92ZWRQaFROb2RlID0gZ2V0VE5vZGUodFZpZXcsIGluZGV4KTtcbiAgY29uc3QgcmVtb3ZlZFBoUk5vZGUgPSBnZXROYXRpdmVCeUluZGV4KGluZGV4LCBsVmlldyk7XG4gIGlmIChyZW1vdmVkUGhSTm9kZSkge1xuICAgIG5hdGl2ZVJlbW92ZU5vZGUobFZpZXdbUkVOREVSRVJdLCByZW1vdmVkUGhSTm9kZSk7XG4gIH1cblxuICBjb25zdCBzbG90VmFsdWUgPSBsb2FkKGxWaWV3LCBpbmRleCkgYXMgUkVsZW1lbnQgfCBSQ29tbWVudCB8IExDb250YWluZXI7XG4gIGlmIChpc0xDb250YWluZXIoc2xvdFZhbHVlKSkge1xuICAgIGNvbnN0IGxDb250YWluZXIgPSBzbG90VmFsdWUgYXMgTENvbnRhaW5lcjtcbiAgICBpZiAocmVtb3ZlZFBoVE5vZGUudHlwZSAhPT0gVE5vZGVUeXBlLkNvbnRhaW5lcikge1xuICAgICAgbmF0aXZlUmVtb3ZlTm9kZShsVmlld1tSRU5ERVJFUl0sIGxDb250YWluZXJbTkFUSVZFXSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG1hcmtBc0RldGFjaGVkKSB7XG4gICAgLy8gRGVmaW5lIHRoaXMgbm9kZSBhcyBkZXRhY2hlZCB0byBhdm9pZCBwcm9qZWN0aW5nIGl0IGxhdGVyXG4gICAgcmVtb3ZlZFBoVE5vZGUuZmxhZ3MgfD0gVE5vZGVGbGFncy5pc0RldGFjaGVkO1xuICB9XG4gIG5nRGV2TW9kZSAmJiBuZ0Rldk1vZGUucmVuZGVyZXJSZW1vdmVOb2RlKys7XG59XG5cbi8qKlxuICpcbiAqIFVzZSB0aGlzIGluc3RydWN0aW9uIHRvIGNyZWF0ZSBhIHRyYW5zbGF0aW9uIGJsb2NrIHRoYXQgZG9lc24ndCBjb250YWluIGFueSBwbGFjZWhvbGRlci5cbiAqIEl0IGNhbGxzIGJvdGgge0BsaW5rIGkxOG5TdGFydH0gYW5kIHtAbGluayBpMThuRW5kfSBpbiBvbmUgaW5zdHJ1Y3Rpb24uXG4gKlxuICogVGhlIHRyYW5zbGF0aW9uIGBtZXNzYWdlYCBpcyB0aGUgdmFsdWUgd2hpY2ggaXMgbG9jYWxlIHNwZWNpZmljLiBUaGUgdHJhbnNsYXRpb24gc3RyaW5nIG1heVxuICogY29udGFpbiBwbGFjZWhvbGRlcnMgd2hpY2ggYXNzb2NpYXRlIGlubmVyIGVsZW1lbnRzIGFuZCBzdWItdGVtcGxhdGVzIHdpdGhpbiB0aGUgdHJhbnNsYXRpb24uXG4gKlxuICogVGhlIHRyYW5zbGF0aW9uIGBtZXNzYWdlYCBwbGFjZWhvbGRlcnMgYXJlOlxuICogLSBg77+9e2luZGV4fSg6e2Jsb2NrfSnvv71gOiAqQmluZGluZyBQbGFjZWhvbGRlcio6IE1hcmtzIGEgbG9jYXRpb24gd2hlcmUgYW4gZXhwcmVzc2lvbiB3aWxsIGJlXG4gKiAgIGludGVycG9sYXRlZCBpbnRvLiBUaGUgcGxhY2Vob2xkZXIgYGluZGV4YCBwb2ludHMgdG8gdGhlIGV4cHJlc3Npb24gYmluZGluZyBpbmRleC4gQW4gb3B0aW9uYWxcbiAqICAgYGJsb2NrYCB0aGF0IG1hdGNoZXMgdGhlIHN1Yi10ZW1wbGF0ZSBpbiB3aGljaCBpdCB3YXMgZGVjbGFyZWQuXG4gKiAtIGDvv70je2luZGV4fSg6e2Jsb2NrfSnvv71gL2Dvv70vI3tpbmRleH0oOntibG9ja30p77+9YDogKkVsZW1lbnQgUGxhY2Vob2xkZXIqOiAgTWFya3MgdGhlIGJlZ2lubmluZ1xuICogICBhbmQgZW5kIG9mIERPTSBlbGVtZW50IHRoYXQgd2VyZSBlbWJlZGRlZCBpbiB0aGUgb3JpZ2luYWwgdHJhbnNsYXRpb24gYmxvY2suIFRoZSBwbGFjZWhvbGRlclxuICogICBgaW5kZXhgIHBvaW50cyB0byB0aGUgZWxlbWVudCBpbmRleCBpbiB0aGUgdGVtcGxhdGUgaW5zdHJ1Y3Rpb25zIHNldC4gQW4gb3B0aW9uYWwgYGJsb2NrYCB0aGF0XG4gKiAgIG1hdGNoZXMgdGhlIHN1Yi10ZW1wbGF0ZSBpbiB3aGljaCBpdCB3YXMgZGVjbGFyZWQuXG4gKiAtIGDvv70qe2luZGV4fTp7YmxvY2t977+9YC9g77+9Lyp7aW5kZXh9OntibG9ja33vv71gOiAqU3ViLXRlbXBsYXRlIFBsYWNlaG9sZGVyKjogU3ViLXRlbXBsYXRlcyBtdXN0IGJlXG4gKiAgIHNwbGl0IHVwIGFuZCB0cmFuc2xhdGVkIHNlcGFyYXRlbHkgaW4gZWFjaCBhbmd1bGFyIHRlbXBsYXRlIGZ1bmN0aW9uLiBUaGUgYGluZGV4YCBwb2ludHMgdG8gdGhlXG4gKiAgIGB0ZW1wbGF0ZWAgaW5zdHJ1Y3Rpb24gaW5kZXguIEEgYGJsb2NrYCB0aGF0IG1hdGNoZXMgdGhlIHN1Yi10ZW1wbGF0ZSBpbiB3aGljaCBpdCB3YXMgZGVjbGFyZWQuXG4gKlxuICogQHBhcmFtIGluZGV4IEEgdW5pcXVlIGluZGV4IG9mIHRoZSB0cmFuc2xhdGlvbiBpbiB0aGUgc3RhdGljIGJsb2NrLlxuICogQHBhcmFtIG1lc3NhZ2UgVGhlIHRyYW5zbGF0aW9uIG1lc3NhZ2UuXG4gKiBAcGFyYW0gc3ViVGVtcGxhdGVJbmRleCBPcHRpb25hbCBzdWItdGVtcGxhdGUgaW5kZXggaW4gdGhlIGBtZXNzYWdlYC5cbiAqXG4gKiBAY29kZUdlbkFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gybXJtWkxOG4oaW5kZXg6IG51bWJlciwgbWVzc2FnZTogc3RyaW5nLCBzdWJUZW1wbGF0ZUluZGV4PzogbnVtYmVyKTogdm9pZCB7XG4gIMm1ybVpMThuU3RhcnQoaW5kZXgsIG1lc3NhZ2UsIHN1YlRlbXBsYXRlSW5kZXgpO1xuICDJtcm1aTE4bkVuZCgpO1xufVxuXG4vKipcbiAqIE1hcmtzIGEgbGlzdCBvZiBhdHRyaWJ1dGVzIGFzIHRyYW5zbGF0YWJsZS5cbiAqXG4gKiBAcGFyYW0gaW5kZXggQSB1bmlxdWUgaW5kZXggaW4gdGhlIHN0YXRpYyBibG9ja1xuICogQHBhcmFtIHZhbHVlc1xuICpcbiAqIEBjb2RlR2VuQXBpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiDJtcm1aTE4bkF0dHJpYnV0ZXMoaW5kZXg6IG51bWJlciwgdmFsdWVzOiBzdHJpbmdbXSk6IHZvaWQge1xuICBjb25zdCBsVmlldyA9IGdldExWaWV3KCk7XG4gIGNvbnN0IHRWaWV3ID0gZ2V0VFZpZXcoKTtcbiAgbmdEZXZNb2RlICYmIGFzc2VydERlZmluZWQodFZpZXcsIGB0VmlldyBzaG91bGQgYmUgZGVmaW5lZGApO1xuICBpMThuQXR0cmlidXRlc0ZpcnN0UGFzcyhsVmlldywgdFZpZXcsIGluZGV4LCB2YWx1ZXMpO1xufVxuXG4vKipcbiAqIFNlZSBgaTE4bkF0dHJpYnV0ZXNgIGFib3ZlLlxuICovXG5mdW5jdGlvbiBpMThuQXR0cmlidXRlc0ZpcnN0UGFzcyhsVmlldzogTFZpZXcsIHRWaWV3OiBUVmlldywgaW5kZXg6IG51bWJlciwgdmFsdWVzOiBzdHJpbmdbXSkge1xuICBjb25zdCBwcmV2aW91c0VsZW1lbnQgPSBnZXRQcmV2aW91c09yUGFyZW50VE5vZGUoKTtcbiAgY29uc3QgcHJldmlvdXNFbGVtZW50SW5kZXggPSBwcmV2aW91c0VsZW1lbnQuaW5kZXggLSBIRUFERVJfT0ZGU0VUO1xuICBjb25zdCB1cGRhdGVPcENvZGVzOiBJMThuVXBkYXRlT3BDb2RlcyA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIGNvbnN0IGF0dHJOYW1lID0gdmFsdWVzW2ldO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSB2YWx1ZXNbaSArIDFdO1xuICAgIGNvbnN0IHBhcnRzID0gbWVzc2FnZS5zcGxpdChJQ1VfUkVHRVhQKTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHBhcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHBhcnRzW2pdO1xuXG4gICAgICBpZiAoaiAmIDEpIHtcbiAgICAgICAgLy8gT2RkIGluZGV4ZXMgYXJlIElDVSBleHByZXNzaW9uc1xuICAgICAgICAvLyBUT0RPKG9jb21iZSk6IHN1cHBvcnQgSUNVIGV4cHJlc3Npb25zIGluIGF0dHJpYnV0ZXNcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJQ1UgZXhwcmVzc2lvbnMgYXJlIG5vdCB5ZXQgc3VwcG9ydGVkIGluIGF0dHJpYnV0ZXMnKTtcbiAgICAgIH0gZWxzZSBpZiAodmFsdWUgIT09ICcnKSB7XG4gICAgICAgIC8vIEV2ZW4gaW5kZXhlcyBhcmUgdGV4dCAoaW5jbHVkaW5nIGJpbmRpbmdzKVxuICAgICAgICBjb25zdCBoYXNCaW5kaW5nID0gISF2YWx1ZS5tYXRjaChCSU5ESU5HX1JFR0VYUCk7XG4gICAgICAgIGlmIChoYXNCaW5kaW5nKSB7XG4gICAgICAgICAgaWYgKHRWaWV3LmZpcnN0Q3JlYXRlUGFzcyAmJiB0Vmlldy5kYXRhW2luZGV4ICsgSEVBREVSX09GRlNFVF0gPT09IG51bGwpIHtcbiAgICAgICAgICAgIGFkZEFsbFRvQXJyYXkoXG4gICAgICAgICAgICAgICAgZ2VuZXJhdGVCaW5kaW5nVXBkYXRlT3BDb2Rlcyh2YWx1ZSwgcHJldmlvdXNFbGVtZW50SW5kZXgsIGF0dHJOYW1lKSwgdXBkYXRlT3BDb2Rlcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHROb2RlID0gZ2V0VE5vZGUodFZpZXcsIHByZXZpb3VzRWxlbWVudEluZGV4KTtcbiAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlcyBmb3IgRWxlbWVudHMgb25seSwgZm9yIG90aGVyIHR5cGVzIChsaWtlIEVsZW1lbnRDb250YWluZXIpLFxuICAgICAgICAgIC8vIG9ubHkgc2V0IGlucHV0cyBiZWxvd1xuICAgICAgICAgIGlmICh0Tm9kZS50eXBlID09PSBUTm9kZVR5cGUuRWxlbWVudCkge1xuICAgICAgICAgICAgZWxlbWVudEF0dHJpYnV0ZUludGVybmFsKHROb2RlLCBsVmlldywgYXR0ck5hbWUsIHZhbHVlLCBudWxsLCBudWxsKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgdGhhdCBhdHRyaWJ1dGUgaXMgYSBkaXJlY3RpdmUgaW5wdXRcbiAgICAgICAgICBjb25zdCBkYXRhVmFsdWUgPSB0Tm9kZS5pbnB1dHMgIT09IG51bGwgJiYgdE5vZGUuaW5wdXRzW2F0dHJOYW1lXTtcbiAgICAgICAgICBpZiAoZGF0YVZhbHVlKSB7XG4gICAgICAgICAgICBzZXRJbnB1dHNGb3JQcm9wZXJ0eSh0VmlldywgbFZpZXcsIGRhdGFWYWx1ZSwgYXR0ck5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgIGlmIChuZ0Rldk1vZGUpIHtcbiAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGdldE5hdGl2ZUJ5SW5kZXgocHJldmlvdXNFbGVtZW50SW5kZXgsIGxWaWV3KSBhcyBSRWxlbWVudCB8IFJDb21tZW50O1xuICAgICAgICAgICAgICBzZXROZ1JlZmxlY3RQcm9wZXJ0aWVzKGxWaWV3LCBlbGVtZW50LCB0Tm9kZS50eXBlLCBkYXRhVmFsdWUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAodFZpZXcuZmlyc3RDcmVhdGVQYXNzICYmIHRWaWV3LmRhdGFbaW5kZXggKyBIRUFERVJfT0ZGU0VUXSA9PT0gbnVsbCkge1xuICAgIHRWaWV3LmRhdGFbaW5kZXggKyBIRUFERVJfT0ZGU0VUXSA9IHVwZGF0ZU9wQ29kZXM7XG4gIH1cbn1cblxubGV0IGNoYW5nZU1hc2sgPSAwYjA7XG5sZXQgc2hpZnRzQ291bnRlciA9IDA7XG5cbi8qKlxuICogU3RvcmVzIHRoZSB2YWx1ZXMgb2YgdGhlIGJpbmRpbmdzIGR1cmluZyBlYWNoIHVwZGF0ZSBjeWNsZSBpbiBvcmRlciB0byBkZXRlcm1pbmUgaWYgd2UgbmVlZCB0b1xuICogdXBkYXRlIHRoZSB0cmFuc2xhdGVkIG5vZGVzLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSBUaGUgYmluZGluZydzIHZhbHVlXG4gKiBAcmV0dXJucyBUaGlzIGZ1bmN0aW9uIHJldHVybnMgaXRzZWxmIHNvIHRoYXQgaXQgbWF5IGJlIGNoYWluZWRcbiAqIChlLmcuIGBpMThuRXhwKGN0eC5uYW1lKShjdHgudGl0bGUpYClcbiAqXG4gKiBAY29kZUdlbkFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gybXJtWkxOG5FeHA8VD4odmFsdWU6IFQpOiB0eXBlb2YgybXJtWkxOG5FeHAge1xuICBjb25zdCBsVmlldyA9IGdldExWaWV3KCk7XG4gIGlmIChiaW5kaW5nVXBkYXRlZChsVmlldywgbmV4dEJpbmRpbmdJbmRleCgpLCB2YWx1ZSkpIHtcbiAgICBjaGFuZ2VNYXNrID0gY2hhbmdlTWFzayB8ICgxIDw8IHNoaWZ0c0NvdW50ZXIpO1xuICB9XG4gIHNoaWZ0c0NvdW50ZXIrKztcbiAgcmV0dXJuIMm1ybVpMThuRXhwO1xufVxuXG4vKipcbiAqIFVwZGF0ZXMgYSB0cmFuc2xhdGlvbiBibG9jayBvciBhbiBpMThuIGF0dHJpYnV0ZSB3aGVuIHRoZSBiaW5kaW5ncyBoYXZlIGNoYW5nZWQuXG4gKlxuICogQHBhcmFtIGluZGV4IEluZGV4IG9mIGVpdGhlciB7QGxpbmsgaTE4blN0YXJ0fSAodHJhbnNsYXRpb24gYmxvY2spIG9yIHtAbGluayBpMThuQXR0cmlidXRlc31cbiAqIChpMThuIGF0dHJpYnV0ZSkgb24gd2hpY2ggaXQgc2hvdWxkIHVwZGF0ZSB0aGUgY29udGVudC5cbiAqXG4gKiBAY29kZUdlbkFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gybXJtWkxOG5BcHBseShpbmRleDogbnVtYmVyKSB7XG4gIGlmIChzaGlmdHNDb3VudGVyKSB7XG4gICAgY29uc3QgdFZpZXcgPSBnZXRUVmlldygpO1xuICAgIG5nRGV2TW9kZSAmJiBhc3NlcnREZWZpbmVkKHRWaWV3LCBgdFZpZXcgc2hvdWxkIGJlIGRlZmluZWRgKTtcbiAgICBjb25zdCB0STE4biA9IHRWaWV3LmRhdGFbaW5kZXggKyBIRUFERVJfT0ZGU0VUXTtcbiAgICBsZXQgdXBkYXRlT3BDb2RlczogSTE4blVwZGF0ZU9wQ29kZXM7XG4gICAgbGV0IGljdXM6IFRJY3VbXXxudWxsID0gbnVsbDtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0STE4bikpIHtcbiAgICAgIHVwZGF0ZU9wQ29kZXMgPSB0STE4biBhcyBJMThuVXBkYXRlT3BDb2RlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdXBkYXRlT3BDb2RlcyA9ICh0STE4biBhcyBUSTE4bikudXBkYXRlO1xuICAgICAgaWN1cyA9ICh0STE4biBhcyBUSTE4bikuaWN1cztcbiAgICB9XG4gICAgY29uc3QgYmluZGluZ3NTdGFydEluZGV4ID0gZ2V0QmluZGluZ0luZGV4KCkgLSBzaGlmdHNDb3VudGVyIC0gMTtcbiAgICBjb25zdCBsVmlldyA9IGdldExWaWV3KCk7XG4gICAgcmVhZFVwZGF0ZU9wQ29kZXModXBkYXRlT3BDb2RlcywgaWN1cywgYmluZGluZ3NTdGFydEluZGV4LCBjaGFuZ2VNYXNrLCB0VmlldywgbFZpZXcpO1xuXG4gICAgLy8gUmVzZXQgY2hhbmdlTWFzayAmIG1hc2tCaXQgdG8gZGVmYXVsdCBmb3IgdGhlIG5leHQgdXBkYXRlIGN5Y2xlXG4gICAgY2hhbmdlTWFzayA9IDBiMDtcbiAgICBzaGlmdHNDb3VudGVyID0gMDtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IGNhc2Ugb2YgYW4gSUNVIGV4cHJlc3Npb24gZGVwZW5kaW5nIG9uIHRoZSBtYWluIGJpbmRpbmcgdmFsdWVcbiAqXG4gKiBAcGFyYW0gaWN1RXhwcmVzc2lvblxuICogQHBhcmFtIGJpbmRpbmdWYWx1ZSBUaGUgdmFsdWUgb2YgdGhlIG1haW4gYmluZGluZyB1c2VkIGJ5IHRoaXMgSUNVIGV4cHJlc3Npb25cbiAqL1xuZnVuY3Rpb24gZ2V0Q2FzZUluZGV4KGljdUV4cHJlc3Npb246IFRJY3UsIGJpbmRpbmdWYWx1ZTogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IGluZGV4ID0gaWN1RXhwcmVzc2lvbi5jYXNlcy5pbmRleE9mKGJpbmRpbmdWYWx1ZSk7XG4gIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICBzd2l0Y2ggKGljdUV4cHJlc3Npb24udHlwZSkge1xuICAgICAgY2FzZSBJY3VUeXBlLnBsdXJhbDoge1xuICAgICAgICBjb25zdCByZXNvbHZlZENhc2UgPSBnZXRQbHVyYWxDYXNlKGJpbmRpbmdWYWx1ZSwgZ2V0TG9jYWxlSWQoKSk7XG4gICAgICAgIGluZGV4ID0gaWN1RXhwcmVzc2lvbi5jYXNlcy5pbmRleE9mKHJlc29sdmVkQ2FzZSk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gLTEgJiYgcmVzb2x2ZWRDYXNlICE9PSAnb3RoZXInKSB7XG4gICAgICAgICAgaW5kZXggPSBpY3VFeHByZXNzaW9uLmNhc2VzLmluZGV4T2YoJ290aGVyJyk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIEljdVR5cGUuc2VsZWN0OiB7XG4gICAgICAgIGluZGV4ID0gaWN1RXhwcmVzc2lvbi5jYXNlcy5pbmRleE9mKCdvdGhlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGluZGV4O1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIHRoZSBPcENvZGVzIGZvciBJQ1UgZXhwcmVzc2lvbnMuXG4gKlxuICogQHBhcmFtIHRJY3VzXG4gKiBAcGFyYW0gaWN1RXhwcmVzc2lvblxuICogQHBhcmFtIHN0YXJ0SW5kZXhcbiAqIEBwYXJhbSBleHBhbmRvU3RhcnRJbmRleFxuICovXG5mdW5jdGlvbiBpY3VTdGFydChcbiAgICB0SWN1czogVEljdVtdLCBpY3VFeHByZXNzaW9uOiBJY3VFeHByZXNzaW9uLCBzdGFydEluZGV4OiBudW1iZXIsXG4gICAgZXhwYW5kb1N0YXJ0SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICBjb25zdCBjcmVhdGVDb2RlcyA9IFtdO1xuICBjb25zdCByZW1vdmVDb2RlcyA9IFtdO1xuICBjb25zdCB1cGRhdGVDb2RlcyA9IFtdO1xuICBjb25zdCB2YXJzID0gW107XG4gIGNvbnN0IGNoaWxkSWN1czogbnVtYmVyW11bXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGljdUV4cHJlc3Npb24udmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gRWFjaCB2YWx1ZSBpcyBhbiBhcnJheSBvZiBzdHJpbmdzICYgb3RoZXIgSUNVIGV4cHJlc3Npb25zXG4gICAgY29uc3QgdmFsdWVBcnIgPSBpY3VFeHByZXNzaW9uLnZhbHVlc1tpXTtcbiAgICBjb25zdCBuZXN0ZWRJY3VzOiBJY3VFeHByZXNzaW9uW10gPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHZhbHVlQXJyLmxlbmd0aDsgaisrKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHZhbHVlQXJyW2pdO1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gSXQgaXMgYW4gbmVzdGVkIElDVSBleHByZXNzaW9uXG4gICAgICAgIGNvbnN0IGljdUluZGV4ID0gbmVzdGVkSWN1cy5wdXNoKHZhbHVlIGFzIEljdUV4cHJlc3Npb24pIC0gMTtcbiAgICAgICAgLy8gUmVwbGFjZSBuZXN0ZWQgSUNVIGV4cHJlc3Npb24gYnkgYSBjb21tZW50IG5vZGVcbiAgICAgICAgdmFsdWVBcnJbal0gPSBgPCEtLe+/vSR7aWN1SW5kZXh977+9LS0+YDtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaWN1Q2FzZTogSWN1Q2FzZSA9XG4gICAgICAgIHBhcnNlSWN1Q2FzZSh2YWx1ZUFyci5qb2luKCcnKSwgc3RhcnRJbmRleCwgbmVzdGVkSWN1cywgdEljdXMsIGV4cGFuZG9TdGFydEluZGV4KTtcbiAgICBjcmVhdGVDb2Rlcy5wdXNoKGljdUNhc2UuY3JlYXRlKTtcbiAgICByZW1vdmVDb2Rlcy5wdXNoKGljdUNhc2UucmVtb3ZlKTtcbiAgICB1cGRhdGVDb2Rlcy5wdXNoKGljdUNhc2UudXBkYXRlKTtcbiAgICB2YXJzLnB1c2goaWN1Q2FzZS52YXJzKTtcbiAgICBjaGlsZEljdXMucHVzaChpY3VDYXNlLmNoaWxkSWN1cyk7XG4gIH1cbiAgY29uc3QgdEljdTogVEljdSA9IHtcbiAgICB0eXBlOiBpY3VFeHByZXNzaW9uLnR5cGUsXG4gICAgdmFycyxcbiAgICBjaGlsZEljdXMsXG4gICAgY2FzZXM6IGljdUV4cHJlc3Npb24uY2FzZXMsXG4gICAgY3JlYXRlOiBjcmVhdGVDb2RlcyxcbiAgICByZW1vdmU6IHJlbW92ZUNvZGVzLFxuICAgIHVwZGF0ZTogdXBkYXRlQ29kZXNcbiAgfTtcbiAgdEljdXMucHVzaCh0SWN1KTtcbiAgLy8gQWRkaW5nIHRoZSBtYXhpbXVtIHBvc3NpYmxlIG9mIHZhcnMgbmVlZGVkIChiYXNlZCBvbiB0aGUgY2FzZXMgd2l0aCB0aGUgbW9zdCB2YXJzKVxuICBpMThuVmFyc0NvdW50ICs9IE1hdGgubWF4KC4uLnZhcnMpO1xufVxuXG4vKipcbiAqIFRyYW5zZm9ybXMgYSBzdHJpbmcgdGVtcGxhdGUgaW50byBhbiBIVE1MIHRlbXBsYXRlIGFuZCBhIGxpc3Qgb2YgaW5zdHJ1Y3Rpb25zIHVzZWQgdG8gdXBkYXRlXG4gKiBhdHRyaWJ1dGVzIG9yIG5vZGVzIHRoYXQgY29udGFpbiBiaW5kaW5ncy5cbiAqXG4gKiBAcGFyYW0gdW5zYWZlSHRtbCBUaGUgc3RyaW5nIHRvIHBhcnNlXG4gKiBAcGFyYW0gcGFyZW50SW5kZXhcbiAqIEBwYXJhbSBuZXN0ZWRJY3VzXG4gKiBAcGFyYW0gdEljdXNcbiAqIEBwYXJhbSBleHBhbmRvU3RhcnRJbmRleFxuICovXG5mdW5jdGlvbiBwYXJzZUljdUNhc2UoXG4gICAgdW5zYWZlSHRtbDogc3RyaW5nLCBwYXJlbnRJbmRleDogbnVtYmVyLCBuZXN0ZWRJY3VzOiBJY3VFeHByZXNzaW9uW10sIHRJY3VzOiBUSWN1W10sXG4gICAgZXhwYW5kb1N0YXJ0SW5kZXg6IG51bWJlcik6IEljdUNhc2Uge1xuICBjb25zdCBpbmVydEJvZHlIZWxwZXIgPSBnZXRJbmVydEJvZHlIZWxwZXIoZ2V0RG9jdW1lbnQoKSk7XG4gIGNvbnN0IGluZXJ0Qm9keUVsZW1lbnQgPSBpbmVydEJvZHlIZWxwZXIuZ2V0SW5lcnRCb2R5RWxlbWVudCh1bnNhZmVIdG1sKTtcbiAgaWYgKCFpbmVydEJvZHlFbGVtZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZ2VuZXJhdGUgaW5lcnQgYm9keSBlbGVtZW50Jyk7XG4gIH1cbiAgY29uc3Qgd3JhcHBlciA9IGdldFRlbXBsYXRlQ29udGVudChpbmVydEJvZHlFbGVtZW50ISkgYXMgRWxlbWVudCB8fCBpbmVydEJvZHlFbGVtZW50O1xuICBjb25zdCBvcENvZGVzOiBJY3VDYXNlID0ge3ZhcnM6IDAsIGNoaWxkSWN1czogW10sIGNyZWF0ZTogW10sIHJlbW92ZTogW10sIHVwZGF0ZTogW119O1xuICBwYXJzZU5vZGVzKHdyYXBwZXIuZmlyc3RDaGlsZCwgb3BDb2RlcywgcGFyZW50SW5kZXgsIG5lc3RlZEljdXMsIHRJY3VzLCBleHBhbmRvU3RhcnRJbmRleCk7XG4gIHJldHVybiBvcENvZGVzO1xufVxuXG5jb25zdCBORVNURURfSUNVID0gL++/vShcXGQrKe+/vS87XG5cbi8qKlxuICogUGFyc2VzIGEgbm9kZSwgaXRzIGNoaWxkcmVuIGFuZCBpdHMgc2libGluZ3MsIGFuZCBnZW5lcmF0ZXMgdGhlIG11dGF0ZSAmIHVwZGF0ZSBPcENvZGVzLlxuICpcbiAqIEBwYXJhbSBjdXJyZW50Tm9kZSBUaGUgZmlyc3Qgbm9kZSB0byBwYXJzZVxuICogQHBhcmFtIGljdUNhc2UgVGhlIGRhdGEgZm9yIHRoZSBJQ1UgZXhwcmVzc2lvbiBjYXNlIHRoYXQgY29udGFpbnMgdGhvc2Ugbm9kZXNcbiAqIEBwYXJhbSBwYXJlbnRJbmRleCBJbmRleCBvZiB0aGUgY3VycmVudCBub2RlJ3MgcGFyZW50XG4gKiBAcGFyYW0gbmVzdGVkSWN1cyBEYXRhIGZvciB0aGUgbmVzdGVkIElDVSBleHByZXNzaW9ucyB0aGF0IHRoaXMgY2FzZSBjb250YWluc1xuICogQHBhcmFtIHRJY3VzIERhdGEgZm9yIGFsbCBJQ1UgZXhwcmVzc2lvbnMgb2YgdGhlIGN1cnJlbnQgbWVzc2FnZVxuICogQHBhcmFtIGV4cGFuZG9TdGFydEluZGV4IEV4cGFuZG8gc3RhcnQgaW5kZXggZm9yIHRoZSBjdXJyZW50IElDVSBleHByZXNzaW9uXG4gKi9cbmZ1bmN0aW9uIHBhcnNlTm9kZXMoXG4gICAgY3VycmVudE5vZGU6IE5vZGV8bnVsbCwgaWN1Q2FzZTogSWN1Q2FzZSwgcGFyZW50SW5kZXg6IG51bWJlciwgbmVzdGVkSWN1czogSWN1RXhwcmVzc2lvbltdLFxuICAgIHRJY3VzOiBUSWN1W10sIGV4cGFuZG9TdGFydEluZGV4OiBudW1iZXIpIHtcbiAgaWYgKGN1cnJlbnROb2RlKSB7XG4gICAgY29uc3QgbmVzdGVkSWN1c1RvQ3JlYXRlOiBbSWN1RXhwcmVzc2lvbiwgbnVtYmVyXVtdID0gW107XG4gICAgd2hpbGUgKGN1cnJlbnROb2RlKSB7XG4gICAgICBjb25zdCBuZXh0Tm9kZTogTm9kZXxudWxsID0gY3VycmVudE5vZGUubmV4dFNpYmxpbmc7XG4gICAgICBjb25zdCBuZXdJbmRleCA9IGV4cGFuZG9TdGFydEluZGV4ICsgKytpY3VDYXNlLnZhcnM7XG4gICAgICBzd2l0Y2ggKGN1cnJlbnROb2RlLm5vZGVUeXBlKSB7XG4gICAgICAgIGNhc2UgTm9kZS5FTEVNRU5UX05PREU6XG4gICAgICAgICAgY29uc3QgZWxlbWVudCA9IGN1cnJlbnROb2RlIGFzIEVsZW1lbnQ7XG4gICAgICAgICAgY29uc3QgdGFnTmFtZSA9IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgIGlmICghVkFMSURfRUxFTUVOVFMuaGFzT3duUHJvcGVydHkodGFnTmFtZSkpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXNuJ3QgYSB2YWxpZCBlbGVtZW50LCB3ZSB3b24ndCBjcmVhdGUgYW4gZWxlbWVudCBmb3IgaXRcbiAgICAgICAgICAgIGljdUNhc2UudmFycy0tO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpY3VDYXNlLmNyZWF0ZS5wdXNoKFxuICAgICAgICAgICAgICAgIEVMRU1FTlRfTUFSS0VSLCB0YWdOYW1lLCBuZXdJbmRleCxcbiAgICAgICAgICAgICAgICBwYXJlbnRJbmRleCA8PCBJMThuTXV0YXRlT3BDb2RlLlNISUZUX1BBUkVOVCB8IEkxOG5NdXRhdGVPcENvZGUuQXBwZW5kQ2hpbGQpO1xuICAgICAgICAgICAgY29uc3QgZWxBdHRycyA9IGVsZW1lbnQuYXR0cmlidXRlcztcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxBdHRycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICBjb25zdCBhdHRyID0gZWxBdHRycy5pdGVtKGkpITtcbiAgICAgICAgICAgICAgY29uc3QgbG93ZXJBdHRyTmFtZSA9IGF0dHIubmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICBjb25zdCBoYXNCaW5kaW5nID0gISFhdHRyLnZhbHVlLm1hdGNoKEJJTkRJTkdfUkVHRVhQKTtcbiAgICAgICAgICAgICAgLy8gd2UgYXNzdW1lIHRoZSBpbnB1dCBzdHJpbmcgaXMgc2FmZSwgdW5sZXNzIGl0J3MgdXNpbmcgYSBiaW5kaW5nXG4gICAgICAgICAgICAgIGlmIChoYXNCaW5kaW5nKSB7XG4gICAgICAgICAgICAgICAgaWYgKFZBTElEX0FUVFJTLmhhc093blByb3BlcnR5KGxvd2VyQXR0ck5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICBpZiAoVVJJX0FUVFJTW2xvd2VyQXR0ck5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZEFsbFRvQXJyYXkoXG4gICAgICAgICAgICAgICAgICAgICAgICBnZW5lcmF0ZUJpbmRpbmdVcGRhdGVPcENvZGVzKGF0dHIudmFsdWUsIG5ld0luZGV4LCBhdHRyLm5hbWUsIF9zYW5pdGl6ZVVybCksXG4gICAgICAgICAgICAgICAgICAgICAgICBpY3VDYXNlLnVwZGF0ZSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFNSQ1NFVF9BVFRSU1tsb3dlckF0dHJOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICBhZGRBbGxUb0FycmF5KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVCaW5kaW5nVXBkYXRlT3BDb2RlcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyLnZhbHVlLCBuZXdJbmRleCwgYXR0ci5uYW1lLCBzYW5pdGl6ZVNyY3NldCksXG4gICAgICAgICAgICAgICAgICAgICAgICBpY3VDYXNlLnVwZGF0ZSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhZGRBbGxUb0FycmF5KFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJhdGVCaW5kaW5nVXBkYXRlT3BDb2RlcyhhdHRyLnZhbHVlLCBuZXdJbmRleCwgYXR0ci5uYW1lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGljdUNhc2UudXBkYXRlKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgbmdEZXZNb2RlICYmXG4gICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBXQVJOSU5HOiBpZ25vcmluZyB1bnNhZmUgYXR0cmlidXRlIHZhbHVlICR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxvd2VyQXR0ck5hbWV9IG9uIGVsZW1lbnQgJHt0YWdOYW1lfSAoc2VlIGh0dHA6Ly9nLmNvL25nL3NlY3VyaXR5I3hzcylgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWN1Q2FzZS5jcmVhdGUucHVzaChcbiAgICAgICAgICAgICAgICAgICAgbmV3SW5kZXggPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUYgfCBJMThuTXV0YXRlT3BDb2RlLkF0dHIsIGF0dHIubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgYXR0ci52YWx1ZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFBhcnNlIHRoZSBjaGlsZHJlbiBvZiB0aGlzIG5vZGUgKGlmIGFueSlcbiAgICAgICAgICAgIHBhcnNlTm9kZXMoXG4gICAgICAgICAgICAgICAgY3VycmVudE5vZGUuZmlyc3RDaGlsZCwgaWN1Q2FzZSwgbmV3SW5kZXgsIG5lc3RlZEljdXMsIHRJY3VzLCBleHBhbmRvU3RhcnRJbmRleCk7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIHBhcmVudCBub2RlIGFmdGVyIHRoZSBjaGlsZHJlblxuICAgICAgICAgICAgaWN1Q2FzZS5yZW1vdmUucHVzaChuZXdJbmRleCA8PCBJMThuTXV0YXRlT3BDb2RlLlNISUZUX1JFRiB8IEkxOG5NdXRhdGVPcENvZGUuUmVtb3ZlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgTm9kZS5URVhUX05PREU6XG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBjdXJyZW50Tm9kZS50ZXh0Q29udGVudCB8fCAnJztcbiAgICAgICAgICBjb25zdCBoYXNCaW5kaW5nID0gdmFsdWUubWF0Y2goQklORElOR19SRUdFWFApO1xuICAgICAgICAgIGljdUNhc2UuY3JlYXRlLnB1c2goXG4gICAgICAgICAgICAgIGhhc0JpbmRpbmcgPyAnJyA6IHZhbHVlLCBuZXdJbmRleCxcbiAgICAgICAgICAgICAgcGFyZW50SW5kZXggPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9QQVJFTlQgfCBJMThuTXV0YXRlT3BDb2RlLkFwcGVuZENoaWxkKTtcbiAgICAgICAgICBpY3VDYXNlLnJlbW92ZS5wdXNoKG5ld0luZGV4IDw8IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUkVGIHwgSTE4bk11dGF0ZU9wQ29kZS5SZW1vdmUpO1xuICAgICAgICAgIGlmIChoYXNCaW5kaW5nKSB7XG4gICAgICAgICAgICBhZGRBbGxUb0FycmF5KGdlbmVyYXRlQmluZGluZ1VwZGF0ZU9wQ29kZXModmFsdWUsIG5ld0luZGV4KSwgaWN1Q2FzZS51cGRhdGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBOb2RlLkNPTU1FTlRfTk9ERTpcbiAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgY29tbWVudCBub2RlIGlzIGEgcGxhY2Vob2xkZXIgZm9yIGEgbmVzdGVkIElDVVxuICAgICAgICAgIGNvbnN0IG1hdGNoID0gTkVTVEVEX0lDVS5leGVjKGN1cnJlbnROb2RlLnRleHRDb250ZW50IHx8ICcnKTtcbiAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgIGNvbnN0IG5lc3RlZEljdUluZGV4ID0gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld0xvY2FsID0gbmdEZXZNb2RlID8gYG5lc3RlZCBJQ1UgJHtuZXN0ZWRJY3VJbmRleH1gIDogJyc7XG4gICAgICAgICAgICAvLyBDcmVhdGUgdGhlIGNvbW1lbnQgbm9kZSB0aGF0IHdpbGwgYW5jaG9yIHRoZSBJQ1UgZXhwcmVzc2lvblxuICAgICAgICAgICAgaWN1Q2FzZS5jcmVhdGUucHVzaChcbiAgICAgICAgICAgICAgICBDT01NRU5UX01BUktFUiwgbmV3TG9jYWwsIG5ld0luZGV4LFxuICAgICAgICAgICAgICAgIHBhcmVudEluZGV4IDw8IEkxOG5NdXRhdGVPcENvZGUuU0hJRlRfUEFSRU5UIHwgSTE4bk11dGF0ZU9wQ29kZS5BcHBlbmRDaGlsZCk7XG4gICAgICAgICAgICBjb25zdCBuZXN0ZWRJY3UgPSBuZXN0ZWRJY3VzW25lc3RlZEljdUluZGV4XTtcbiAgICAgICAgICAgIG5lc3RlZEljdXNUb0NyZWF0ZS5wdXNoKFtuZXN0ZWRJY3UsIG5ld0luZGV4XSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFdlIGRvIG5vdCBoYW5kbGUgYW55IG90aGVyIHR5cGUgb2YgY29tbWVudFxuICAgICAgICAgICAgaWN1Q2FzZS52YXJzLS07XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIC8vIFdlIGRvIG5vdCBoYW5kbGUgYW55IG90aGVyIHR5cGUgb2YgZWxlbWVudFxuICAgICAgICAgIGljdUNhc2UudmFycy0tO1xuICAgICAgfVxuICAgICAgY3VycmVudE5vZGUgPSBuZXh0Tm9kZSE7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXN0ZWRJY3VzVG9DcmVhdGUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5lc3RlZEljdSA9IG5lc3RlZEljdXNUb0NyZWF0ZVtpXVswXTtcbiAgICAgIGNvbnN0IG5lc3RlZEljdU5vZGVJbmRleCA9IG5lc3RlZEljdXNUb0NyZWF0ZVtpXVsxXTtcbiAgICAgIGljdVN0YXJ0KHRJY3VzLCBuZXN0ZWRJY3UsIG5lc3RlZEljdU5vZGVJbmRleCwgZXhwYW5kb1N0YXJ0SW5kZXggKyBpY3VDYXNlLnZhcnMpO1xuICAgICAgLy8gU2luY2UgdGhpcyBpcyByZWN1cnNpdmUsIHRoZSBsYXN0IFRJY3UgdGhhdCB3YXMgcHVzaGVkIGlzIHRoZSBvbmUgd2Ugd2FudFxuICAgICAgY29uc3QgbmVzdFRJY3VJbmRleCA9IHRJY3VzLmxlbmd0aCAtIDE7XG4gICAgICBpY3VDYXNlLnZhcnMgKz0gTWF0aC5tYXgoLi4udEljdXNbbmVzdFRJY3VJbmRleF0udmFycyk7XG4gICAgICBpY3VDYXNlLmNoaWxkSWN1cy5wdXNoKG5lc3RUSWN1SW5kZXgpO1xuICAgICAgY29uc3QgbWFzayA9IGdldEJpbmRpbmdNYXNrKG5lc3RlZEljdSk7XG4gICAgICBpY3VDYXNlLnVwZGF0ZS5wdXNoKFxuICAgICAgICAgIHRvTWFza0JpdChuZXN0ZWRJY3UubWFpbkJpbmRpbmcpLCAgLy8gbWFzayBvZiB0aGUgbWFpbiBiaW5kaW5nXG4gICAgICAgICAgMywgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIDMgb3BDb2RlcyBpZiBub3QgY2hhbmdlZFxuICAgICAgICAgIC0xIC0gbmVzdGVkSWN1Lm1haW5CaW5kaW5nLFxuICAgICAgICAgIG5lc3RlZEljdU5vZGVJbmRleCA8PCBJMThuVXBkYXRlT3BDb2RlLlNISUZUX1JFRiB8IEkxOG5VcGRhdGVPcENvZGUuSWN1U3dpdGNoLFxuICAgICAgICAgIG5lc3RUSWN1SW5kZXgsXG4gICAgICAgICAgbWFzaywgIC8vIG1hc2sgb2YgYWxsIHRoZSBiaW5kaW5ncyBvZiB0aGlzIElDVSBleHByZXNzaW9uXG4gICAgICAgICAgMiwgICAgIC8vIHNraXAgMiBvcENvZGVzIGlmIG5vdCBjaGFuZ2VkXG4gICAgICAgICAgbmVzdGVkSWN1Tm9kZUluZGV4IDw8IEkxOG5VcGRhdGVPcENvZGUuU0hJRlRfUkVGIHwgSTE4blVwZGF0ZU9wQ29kZS5JY3VVcGRhdGUsXG4gICAgICAgICAgbmVzdFRJY3VJbmRleCk7XG4gICAgICBpY3VDYXNlLnJlbW92ZS5wdXNoKFxuICAgICAgICAgIG5lc3RUSWN1SW5kZXggPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUYgfCBJMThuTXV0YXRlT3BDb2RlLlJlbW92ZU5lc3RlZEljdSxcbiAgICAgICAgICBuZXN0ZWRJY3VOb2RlSW5kZXggPDwgSTE4bk11dGF0ZU9wQ29kZS5TSElGVF9SRUYgfCBJMThuTXV0YXRlT3BDb2RlLlJlbW92ZSk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQW5ndWxhciBEYXJ0IGludHJvZHVjZWQgJm5nc3A7IGFzIGEgcGxhY2Vob2xkZXIgZm9yIG5vbi1yZW1vdmFibGUgc3BhY2UsIHNlZTpcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9kYXJ0LWxhbmcvYW5ndWxhci9ibG9iLzBiYjYxMTM4N2QyOWQ2NWI1YWY3ZjlkMjUxNWFiNTcxZmQzZmJlZTQvX3Rlc3RzL3Rlc3QvY29tcGlsZXIvcHJlc2VydmVfd2hpdGVzcGFjZV90ZXN0LmRhcnQjTDI1LUwzMlxuICogSW4gQW5ndWxhciBEYXJ0ICZuZ3NwOyBpcyBjb252ZXJ0ZWQgdG8gdGhlIDB4RTUwMCBQVUEgKFByaXZhdGUgVXNlIEFyZWFzKSB1bmljb2RlIGNoYXJhY3RlclxuICogYW5kIGxhdGVyIG9uIHJlcGxhY2VkIGJ5IGEgc3BhY2UuIFdlIGFyZSByZS1pbXBsZW1lbnRpbmcgdGhlIHNhbWUgaWRlYSBoZXJlLCBzaW5jZSB0cmFuc2xhdGlvbnNcbiAqIG1pZ2h0IGNvbnRhaW4gdGhpcyBzcGVjaWFsIGNoYXJhY3Rlci5cbiAqL1xuY29uc3QgTkdTUF9VTklDT0RFX1JFR0VYUCA9IC9cXHVFNTAwL2c7XG5mdW5jdGlvbiByZXBsYWNlTmdzcCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlLnJlcGxhY2UoTkdTUF9VTklDT0RFX1JFR0VYUCwgJyAnKTtcbn1cblxuLyoqXG4gKiBUaGUgbG9jYWxlIGlkIHRoYXQgdGhlIGFwcGxpY2F0aW9uIGlzIGN1cnJlbnRseSB1c2luZyAoZm9yIHRyYW5zbGF0aW9ucyBhbmQgSUNVIGV4cHJlc3Npb25zKS5cbiAqIFRoaXMgaXMgdGhlIGl2eSB2ZXJzaW9uIG9mIGBMT0NBTEVfSURgIHRoYXQgd2FzIGRlZmluZWQgYXMgYW4gaW5qZWN0aW9uIHRva2VuIGZvciB0aGUgdmlldyBlbmdpbmVcbiAqIGJ1dCBpcyBub3cgZGVmaW5lZCBhcyBhIGdsb2JhbCB2YWx1ZS5cbiAqL1xubGV0IExPQ0FMRV9JRCA9IERFRkFVTFRfTE9DQUxFX0lEO1xuXG4vKipcbiAqIFNldHMgdGhlIGxvY2FsZSBpZCB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgdHJhbnNsYXRpb25zIGFuZCBJQ1UgZXhwcmVzc2lvbnMuXG4gKiBUaGlzIGlzIHRoZSBpdnkgdmVyc2lvbiBvZiBgTE9DQUxFX0lEYCB0aGF0IHdhcyBkZWZpbmVkIGFzIGFuIGluamVjdGlvbiB0b2tlbiBmb3IgdGhlIHZpZXcgZW5naW5lXG4gKiBidXQgaXMgbm93IGRlZmluZWQgYXMgYSBnbG9iYWwgdmFsdWUuXG4gKlxuICogQHBhcmFtIGxvY2FsZUlkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRMb2NhbGVJZChsb2NhbGVJZDogc3RyaW5nKSB7XG4gIGFzc2VydERlZmluZWQobG9jYWxlSWQsIGBFeHBlY3RlZCBsb2NhbGVJZCB0byBiZSBkZWZpbmVkYCk7XG4gIGlmICh0eXBlb2YgbG9jYWxlSWQgPT09ICdzdHJpbmcnKSB7XG4gICAgTE9DQUxFX0lEID0gbG9jYWxlSWQudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9fL2csICctJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBsb2NhbGUgaWQgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHRyYW5zbGF0aW9ucyBhbmQgSUNVIGV4cHJlc3Npb25zLlxuICogVGhpcyBpcyB0aGUgaXZ5IHZlcnNpb24gb2YgYExPQ0FMRV9JRGAgdGhhdCB3YXMgZGVmaW5lZCBhcyBhbiBpbmplY3Rpb24gdG9rZW4gZm9yIHRoZSB2aWV3IGVuZ2luZVxuICogYnV0IGlzIG5vdyBkZWZpbmVkIGFzIGEgZ2xvYmFsIHZhbHVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9jYWxlSWQoKTogc3RyaW5nIHtcbiAgcmV0dXJuIExPQ0FMRV9JRDtcbn1cbiJdfQ==
|