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 | (function (factory) {
|
---|
9 | if (typeof module === "object" && typeof module.exports === "object") {
|
---|
10 | var v = factory(require, exports);
|
---|
11 | if (v !== undefined) module.exports = v;
|
---|
12 | }
|
---|
13 | else if (typeof define === "function" && define.amd) {
|
---|
14 | define("@angular/compiler/src/selector", ["require", "exports", "@angular/compiler/src/ml_parser/html_tags"], factory);
|
---|
15 | }
|
---|
16 | })(function (require, exports) {
|
---|
17 | "use strict";
|
---|
18 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
19 | exports.SelectorContext = exports.SelectorListContext = exports.SelectorMatcher = exports.CssSelector = void 0;
|
---|
20 | var html_tags_1 = require("@angular/compiler/src/ml_parser/html_tags");
|
---|
21 | var _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not("
|
---|
22 | '(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#";
|
---|
23 | // "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range
|
---|
24 | // 4: attribute; 5: attribute_string; 6: attribute_value
|
---|
25 | '(?:\\[([-.\\w*\\\\$]+)(?:=([\"\']?)([^\\]\"\']*)\\5)?\\])|' + // "[name]", "[name=value]",
|
---|
26 | // "[name="value"]",
|
---|
27 | // "[name='value']"
|
---|
28 | '(\\))|' + // 7: ")"
|
---|
29 | '(\\s*,\\s*)', // 8: ","
|
---|
30 | 'g');
|
---|
31 | /**
|
---|
32 | * A css selector contains an element name,
|
---|
33 | * css classes and attribute/value pairs with the purpose
|
---|
34 | * of selecting subsets out of them.
|
---|
35 | */
|
---|
36 | var CssSelector = /** @class */ (function () {
|
---|
37 | function CssSelector() {
|
---|
38 | this.element = null;
|
---|
39 | this.classNames = [];
|
---|
40 | /**
|
---|
41 | * The selectors are encoded in pairs where:
|
---|
42 | * - even locations are attribute names
|
---|
43 | * - odd locations are attribute values.
|
---|
44 | *
|
---|
45 | * Example:
|
---|
46 | * Selector: `[key1=value1][key2]` would parse to:
|
---|
47 | * ```
|
---|
48 | * ['key1', 'value1', 'key2', '']
|
---|
49 | * ```
|
---|
50 | */
|
---|
51 | this.attrs = [];
|
---|
52 | this.notSelectors = [];
|
---|
53 | }
|
---|
54 | CssSelector.parse = function (selector) {
|
---|
55 | var results = [];
|
---|
56 | var _addResult = function (res, cssSel) {
|
---|
57 | if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 &&
|
---|
58 | cssSel.attrs.length == 0) {
|
---|
59 | cssSel.element = '*';
|
---|
60 | }
|
---|
61 | res.push(cssSel);
|
---|
62 | };
|
---|
63 | var cssSelector = new CssSelector();
|
---|
64 | var match;
|
---|
65 | var current = cssSelector;
|
---|
66 | var inNot = false;
|
---|
67 | _SELECTOR_REGEXP.lastIndex = 0;
|
---|
68 | while (match = _SELECTOR_REGEXP.exec(selector)) {
|
---|
69 | if (match[1 /* NOT */]) {
|
---|
70 | if (inNot) {
|
---|
71 | throw new Error('Nesting :not in a selector is not allowed');
|
---|
72 | }
|
---|
73 | inNot = true;
|
---|
74 | current = new CssSelector();
|
---|
75 | cssSelector.notSelectors.push(current);
|
---|
76 | }
|
---|
77 | var tag = match[2 /* TAG */];
|
---|
78 | if (tag) {
|
---|
79 | var prefix = match[3 /* PREFIX */];
|
---|
80 | if (prefix === '#') {
|
---|
81 | // #hash
|
---|
82 | current.addAttribute('id', tag.substr(1));
|
---|
83 | }
|
---|
84 | else if (prefix === '.') {
|
---|
85 | // Class
|
---|
86 | current.addClassName(tag.substr(1));
|
---|
87 | }
|
---|
88 | else {
|
---|
89 | // Element
|
---|
90 | current.setElement(tag);
|
---|
91 | }
|
---|
92 | }
|
---|
93 | var attribute = match[4 /* ATTRIBUTE */];
|
---|
94 | if (attribute) {
|
---|
95 | current.addAttribute(current.unescapeAttribute(attribute), match[6 /* ATTRIBUTE_VALUE */]);
|
---|
96 | }
|
---|
97 | if (match[7 /* NOT_END */]) {
|
---|
98 | inNot = false;
|
---|
99 | current = cssSelector;
|
---|
100 | }
|
---|
101 | if (match[8 /* SEPARATOR */]) {
|
---|
102 | if (inNot) {
|
---|
103 | throw new Error('Multiple selectors in :not are not supported');
|
---|
104 | }
|
---|
105 | _addResult(results, cssSelector);
|
---|
106 | cssSelector = current = new CssSelector();
|
---|
107 | }
|
---|
108 | }
|
---|
109 | _addResult(results, cssSelector);
|
---|
110 | return results;
|
---|
111 | };
|
---|
112 | /**
|
---|
113 | * Unescape `\$` sequences from the CSS attribute selector.
|
---|
114 | *
|
---|
115 | * This is needed because `$` can have a special meaning in CSS selectors,
|
---|
116 | * but we might want to match an attribute that contains `$`.
|
---|
117 | * [MDN web link for more
|
---|
118 | * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
|
---|
119 | * @param attr the attribute to unescape.
|
---|
120 | * @returns the unescaped string.
|
---|
121 | */
|
---|
122 | CssSelector.prototype.unescapeAttribute = function (attr) {
|
---|
123 | var result = '';
|
---|
124 | var escaping = false;
|
---|
125 | for (var i = 0; i < attr.length; i++) {
|
---|
126 | var char = attr.charAt(i);
|
---|
127 | if (char === '\\') {
|
---|
128 | escaping = true;
|
---|
129 | continue;
|
---|
130 | }
|
---|
131 | if (char === '$' && !escaping) {
|
---|
132 | throw new Error("Error in attribute selector \"" + attr + "\". " +
|
---|
133 | "Unescaped \"$\" is not supported. Please escape with \"\\$\".");
|
---|
134 | }
|
---|
135 | escaping = false;
|
---|
136 | result += char;
|
---|
137 | }
|
---|
138 | return result;
|
---|
139 | };
|
---|
140 | /**
|
---|
141 | * Escape `$` sequences from the CSS attribute selector.
|
---|
142 | *
|
---|
143 | * This is needed because `$` can have a special meaning in CSS selectors,
|
---|
144 | * with this method we are escaping `$` with `\$'.
|
---|
145 | * [MDN web link for more
|
---|
146 | * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
|
---|
147 | * @param attr the attribute to escape.
|
---|
148 | * @returns the escaped string.
|
---|
149 | */
|
---|
150 | CssSelector.prototype.escapeAttribute = function (attr) {
|
---|
151 | return attr.replace(/\\/g, '\\\\').replace(/\$/g, '\\$');
|
---|
152 | };
|
---|
153 | CssSelector.prototype.isElementSelector = function () {
|
---|
154 | return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 &&
|
---|
155 | this.notSelectors.length === 0;
|
---|
156 | };
|
---|
157 | CssSelector.prototype.hasElementSelector = function () {
|
---|
158 | return !!this.element;
|
---|
159 | };
|
---|
160 | CssSelector.prototype.setElement = function (element) {
|
---|
161 | if (element === void 0) { element = null; }
|
---|
162 | this.element = element;
|
---|
163 | };
|
---|
164 | /** Gets a template string for an element that matches the selector. */
|
---|
165 | CssSelector.prototype.getMatchingElementTemplate = function () {
|
---|
166 | var tagName = this.element || 'div';
|
---|
167 | var classAttr = this.classNames.length > 0 ? " class=\"" + this.classNames.join(' ') + "\"" : '';
|
---|
168 | var attrs = '';
|
---|
169 | for (var i = 0; i < this.attrs.length; i += 2) {
|
---|
170 | var attrName = this.attrs[i];
|
---|
171 | var attrValue = this.attrs[i + 1] !== '' ? "=\"" + this.attrs[i + 1] + "\"" : '';
|
---|
172 | attrs += " " + attrName + attrValue;
|
---|
173 | }
|
---|
174 | return html_tags_1.getHtmlTagDefinition(tagName).isVoid ? "<" + tagName + classAttr + attrs + "/>" :
|
---|
175 | "<" + tagName + classAttr + attrs + "></" + tagName + ">";
|
---|
176 | };
|
---|
177 | CssSelector.prototype.getAttrs = function () {
|
---|
178 | var result = [];
|
---|
179 | if (this.classNames.length > 0) {
|
---|
180 | result.push('class', this.classNames.join(' '));
|
---|
181 | }
|
---|
182 | return result.concat(this.attrs);
|
---|
183 | };
|
---|
184 | CssSelector.prototype.addAttribute = function (name, value) {
|
---|
185 | if (value === void 0) { value = ''; }
|
---|
186 | this.attrs.push(name, value && value.toLowerCase() || '');
|
---|
187 | };
|
---|
188 | CssSelector.prototype.addClassName = function (name) {
|
---|
189 | this.classNames.push(name.toLowerCase());
|
---|
190 | };
|
---|
191 | CssSelector.prototype.toString = function () {
|
---|
192 | var res = this.element || '';
|
---|
193 | if (this.classNames) {
|
---|
194 | this.classNames.forEach(function (klass) { return res += "." + klass; });
|
---|
195 | }
|
---|
196 | if (this.attrs) {
|
---|
197 | for (var i = 0; i < this.attrs.length; i += 2) {
|
---|
198 | var name_1 = this.escapeAttribute(this.attrs[i]);
|
---|
199 | var value = this.attrs[i + 1];
|
---|
200 | res += "[" + name_1 + (value ? '=' + value : '') + "]";
|
---|
201 | }
|
---|
202 | }
|
---|
203 | this.notSelectors.forEach(function (notSelector) { return res += ":not(" + notSelector + ")"; });
|
---|
204 | return res;
|
---|
205 | };
|
---|
206 | return CssSelector;
|
---|
207 | }());
|
---|
208 | exports.CssSelector = CssSelector;
|
---|
209 | /**
|
---|
210 | * Reads a list of CssSelectors and allows to calculate which ones
|
---|
211 | * are contained in a given CssSelector.
|
---|
212 | */
|
---|
213 | var SelectorMatcher = /** @class */ (function () {
|
---|
214 | function SelectorMatcher() {
|
---|
215 | this._elementMap = new Map();
|
---|
216 | this._elementPartialMap = new Map();
|
---|
217 | this._classMap = new Map();
|
---|
218 | this._classPartialMap = new Map();
|
---|
219 | this._attrValueMap = new Map();
|
---|
220 | this._attrValuePartialMap = new Map();
|
---|
221 | this._listContexts = [];
|
---|
222 | }
|
---|
223 | SelectorMatcher.createNotMatcher = function (notSelectors) {
|
---|
224 | var notMatcher = new SelectorMatcher();
|
---|
225 | notMatcher.addSelectables(notSelectors, null);
|
---|
226 | return notMatcher;
|
---|
227 | };
|
---|
228 | SelectorMatcher.prototype.addSelectables = function (cssSelectors, callbackCtxt) {
|
---|
229 | var listContext = null;
|
---|
230 | if (cssSelectors.length > 1) {
|
---|
231 | listContext = new SelectorListContext(cssSelectors);
|
---|
232 | this._listContexts.push(listContext);
|
---|
233 | }
|
---|
234 | for (var i = 0; i < cssSelectors.length; i++) {
|
---|
235 | this._addSelectable(cssSelectors[i], callbackCtxt, listContext);
|
---|
236 | }
|
---|
237 | };
|
---|
238 | /**
|
---|
239 | * Add an object that can be found later on by calling `match`.
|
---|
240 | * @param cssSelector A css selector
|
---|
241 | * @param callbackCtxt An opaque object that will be given to the callback of the `match` function
|
---|
242 | */
|
---|
243 | SelectorMatcher.prototype._addSelectable = function (cssSelector, callbackCtxt, listContext) {
|
---|
244 | var matcher = this;
|
---|
245 | var element = cssSelector.element;
|
---|
246 | var classNames = cssSelector.classNames;
|
---|
247 | var attrs = cssSelector.attrs;
|
---|
248 | var selectable = new SelectorContext(cssSelector, callbackCtxt, listContext);
|
---|
249 | if (element) {
|
---|
250 | var isTerminal = attrs.length === 0 && classNames.length === 0;
|
---|
251 | if (isTerminal) {
|
---|
252 | this._addTerminal(matcher._elementMap, element, selectable);
|
---|
253 | }
|
---|
254 | else {
|
---|
255 | matcher = this._addPartial(matcher._elementPartialMap, element);
|
---|
256 | }
|
---|
257 | }
|
---|
258 | if (classNames) {
|
---|
259 | for (var i = 0; i < classNames.length; i++) {
|
---|
260 | var isTerminal = attrs.length === 0 && i === classNames.length - 1;
|
---|
261 | var className = classNames[i];
|
---|
262 | if (isTerminal) {
|
---|
263 | this._addTerminal(matcher._classMap, className, selectable);
|
---|
264 | }
|
---|
265 | else {
|
---|
266 | matcher = this._addPartial(matcher._classPartialMap, className);
|
---|
267 | }
|
---|
268 | }
|
---|
269 | }
|
---|
270 | if (attrs) {
|
---|
271 | for (var i = 0; i < attrs.length; i += 2) {
|
---|
272 | var isTerminal = i === attrs.length - 2;
|
---|
273 | var name_2 = attrs[i];
|
---|
274 | var value = attrs[i + 1];
|
---|
275 | if (isTerminal) {
|
---|
276 | var terminalMap = matcher._attrValueMap;
|
---|
277 | var terminalValuesMap = terminalMap.get(name_2);
|
---|
278 | if (!terminalValuesMap) {
|
---|
279 | terminalValuesMap = new Map();
|
---|
280 | terminalMap.set(name_2, terminalValuesMap);
|
---|
281 | }
|
---|
282 | this._addTerminal(terminalValuesMap, value, selectable);
|
---|
283 | }
|
---|
284 | else {
|
---|
285 | var partialMap = matcher._attrValuePartialMap;
|
---|
286 | var partialValuesMap = partialMap.get(name_2);
|
---|
287 | if (!partialValuesMap) {
|
---|
288 | partialValuesMap = new Map();
|
---|
289 | partialMap.set(name_2, partialValuesMap);
|
---|
290 | }
|
---|
291 | matcher = this._addPartial(partialValuesMap, value);
|
---|
292 | }
|
---|
293 | }
|
---|
294 | }
|
---|
295 | };
|
---|
296 | SelectorMatcher.prototype._addTerminal = function (map, name, selectable) {
|
---|
297 | var terminalList = map.get(name);
|
---|
298 | if (!terminalList) {
|
---|
299 | terminalList = [];
|
---|
300 | map.set(name, terminalList);
|
---|
301 | }
|
---|
302 | terminalList.push(selectable);
|
---|
303 | };
|
---|
304 | SelectorMatcher.prototype._addPartial = function (map, name) {
|
---|
305 | var matcher = map.get(name);
|
---|
306 | if (!matcher) {
|
---|
307 | matcher = new SelectorMatcher();
|
---|
308 | map.set(name, matcher);
|
---|
309 | }
|
---|
310 | return matcher;
|
---|
311 | };
|
---|
312 | /**
|
---|
313 | * Find the objects that have been added via `addSelectable`
|
---|
314 | * whose css selector is contained in the given css selector.
|
---|
315 | * @param cssSelector A css selector
|
---|
316 | * @param matchedCallback This callback will be called with the object handed into `addSelectable`
|
---|
317 | * @return boolean true if a match was found
|
---|
318 | */
|
---|
319 | SelectorMatcher.prototype.match = function (cssSelector, matchedCallback) {
|
---|
320 | var result = false;
|
---|
321 | var element = cssSelector.element;
|
---|
322 | var classNames = cssSelector.classNames;
|
---|
323 | var attrs = cssSelector.attrs;
|
---|
324 | for (var i = 0; i < this._listContexts.length; i++) {
|
---|
325 | this._listContexts[i].alreadyMatched = false;
|
---|
326 | }
|
---|
327 | result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
|
---|
328 | result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) ||
|
---|
329 | result;
|
---|
330 | if (classNames) {
|
---|
331 | for (var i = 0; i < classNames.length; i++) {
|
---|
332 | var className = classNames[i];
|
---|
333 | result =
|
---|
334 | this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
|
---|
335 | result =
|
---|
336 | this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) ||
|
---|
337 | result;
|
---|
338 | }
|
---|
339 | }
|
---|
340 | if (attrs) {
|
---|
341 | for (var i = 0; i < attrs.length; i += 2) {
|
---|
342 | var name_3 = attrs[i];
|
---|
343 | var value = attrs[i + 1];
|
---|
344 | var terminalValuesMap = this._attrValueMap.get(name_3);
|
---|
345 | if (value) {
|
---|
346 | result =
|
---|
347 | this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;
|
---|
348 | }
|
---|
349 | result =
|
---|
350 | this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;
|
---|
351 | var partialValuesMap = this._attrValuePartialMap.get(name_3);
|
---|
352 | if (value) {
|
---|
353 | result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;
|
---|
354 | }
|
---|
355 | result =
|
---|
356 | this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result;
|
---|
357 | }
|
---|
358 | }
|
---|
359 | return result;
|
---|
360 | };
|
---|
361 | /** @internal */
|
---|
362 | SelectorMatcher.prototype._matchTerminal = function (map, name, cssSelector, matchedCallback) {
|
---|
363 | if (!map || typeof name !== 'string') {
|
---|
364 | return false;
|
---|
365 | }
|
---|
366 | var selectables = map.get(name) || [];
|
---|
367 | var starSelectables = map.get('*');
|
---|
368 | if (starSelectables) {
|
---|
369 | selectables = selectables.concat(starSelectables);
|
---|
370 | }
|
---|
371 | if (selectables.length === 0) {
|
---|
372 | return false;
|
---|
373 | }
|
---|
374 | var selectable;
|
---|
375 | var result = false;
|
---|
376 | for (var i = 0; i < selectables.length; i++) {
|
---|
377 | selectable = selectables[i];
|
---|
378 | result = selectable.finalize(cssSelector, matchedCallback) || result;
|
---|
379 | }
|
---|
380 | return result;
|
---|
381 | };
|
---|
382 | /** @internal */
|
---|
383 | SelectorMatcher.prototype._matchPartial = function (map, name, cssSelector, matchedCallback) {
|
---|
384 | if (!map || typeof name !== 'string') {
|
---|
385 | return false;
|
---|
386 | }
|
---|
387 | var nestedSelector = map.get(name);
|
---|
388 | if (!nestedSelector) {
|
---|
389 | return false;
|
---|
390 | }
|
---|
391 | // TODO(perf): get rid of recursion and measure again
|
---|
392 | // TODO(perf): don't pass the whole selector into the recursion,
|
---|
393 | // but only the not processed parts
|
---|
394 | return nestedSelector.match(cssSelector, matchedCallback);
|
---|
395 | };
|
---|
396 | return SelectorMatcher;
|
---|
397 | }());
|
---|
398 | exports.SelectorMatcher = SelectorMatcher;
|
---|
399 | var SelectorListContext = /** @class */ (function () {
|
---|
400 | function SelectorListContext(selectors) {
|
---|
401 | this.selectors = selectors;
|
---|
402 | this.alreadyMatched = false;
|
---|
403 | }
|
---|
404 | return SelectorListContext;
|
---|
405 | }());
|
---|
406 | exports.SelectorListContext = SelectorListContext;
|
---|
407 | // Store context to pass back selector and context when a selector is matched
|
---|
408 | var SelectorContext = /** @class */ (function () {
|
---|
409 | function SelectorContext(selector, cbContext, listContext) {
|
---|
410 | this.selector = selector;
|
---|
411 | this.cbContext = cbContext;
|
---|
412 | this.listContext = listContext;
|
---|
413 | this.notSelectors = selector.notSelectors;
|
---|
414 | }
|
---|
415 | SelectorContext.prototype.finalize = function (cssSelector, callback) {
|
---|
416 | var result = true;
|
---|
417 | if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {
|
---|
418 | var notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);
|
---|
419 | result = !notMatcher.match(cssSelector, null);
|
---|
420 | }
|
---|
421 | if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) {
|
---|
422 | if (this.listContext) {
|
---|
423 | this.listContext.alreadyMatched = true;
|
---|
424 | }
|
---|
425 | callback(this.selector, this.cbContext);
|
---|
426 | }
|
---|
427 | return result;
|
---|
428 | };
|
---|
429 | return SelectorContext;
|
---|
430 | }());
|
---|
431 | exports.SelectorContext = SelectorContext;
|
---|
432 | });
|
---|
433 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21waWxlci9zcmMvc2VsZWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7O0lBRUgsdUVBQTJEO0lBRTNELElBQU0sZ0JBQWdCLEdBQUcsSUFBSSxNQUFNLENBQy9CLGNBQWMsR0FBaUIsYUFBYTtRQUN4Qyx1QkFBdUIsR0FBSSx3QkFBd0I7UUFDbkQsaUZBQWlGO1FBQ2pGLHdEQUF3RDtRQUN4RCw0REFBNEQsR0FBSSw0QkFBNEI7UUFDNUIsb0JBQW9CO1FBQ3BCLG1CQUFtQjtRQUNuRixRQUFRLEdBQXdELFNBQVM7UUFDekUsYUFBYSxFQUFtRCxTQUFTO0lBQzdFLEdBQUcsQ0FBQyxDQUFDO0lBZ0JUOzs7O09BSUc7SUFDSDtRQUFBO1lBQ0UsWUFBTyxHQUFnQixJQUFJLENBQUM7WUFDNUIsZUFBVSxHQUFhLEVBQUUsQ0FBQztZQUMxQjs7Ozs7Ozs7OztlQVVHO1lBQ0gsVUFBSyxHQUFhLEVBQUUsQ0FBQztZQUNyQixpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFxS25DLENBQUM7UUFuS1EsaUJBQUssR0FBWixVQUFhLFFBQWdCO1lBQzNCLElBQU0sT0FBTyxHQUFrQixFQUFFLENBQUM7WUFDbEMsSUFBTSxVQUFVLEdBQUcsVUFBQyxHQUFrQixFQUFFLE1BQW1CO2dCQUN6RCxJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLElBQUksQ0FBQztvQkFDbEYsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLElBQUksQ0FBQyxFQUFFO29CQUM1QixNQUFNLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQztpQkFDdEI7Z0JBQ0QsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENB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biAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge2dldEh0bWxUYWdEZWZpbml0aW9ufSBmcm9tICcuL21sX3BhcnNlci9odG1sX3RhZ3MnO1xuXG5jb25zdCBfU0VMRUNUT1JfUkVHRVhQID0gbmV3IFJlZ0V4cChcbiAgICAnKFxcXFw6bm90XFxcXCgpfCcgKyAgICAgICAgICAgICAgIC8vIDE6IFwiOm5vdChcIlxuICAgICAgICAnKChbXFxcXC5cXFxcI10/KVstXFxcXHddKyl8JyArICAvLyAyOiBcInRhZ1wiOyAzOiBcIi5cIi9cIiNcIjtcbiAgICAgICAgLy8gXCItXCIgc2hvdWxkIGFwcGVhciBmaXJzdCBpbiB0aGUgcmVnZXhwIGJlbG93IGFzIEZGMzEgcGFyc2VzIFwiWy4tXFx3XVwiIGFzIGEgcmFuZ2VcbiAgICAgICAgLy8gNDogYXR0cmlidXRlOyA1OiBhdHRyaWJ1dGVfc3RyaW5nOyA2OiBhdHRyaWJ1dGVfdmFsdWVcbiAgICAgICAgJyg/OlxcXFxbKFstLlxcXFx3KlxcXFxcXFxcJF0rKSg/Oj0oW1xcXCJcXCddPykoW15cXFxcXVxcXCJcXCddKilcXFxcNSk/XFxcXF0pfCcgKyAgLy8gXCJbbmFtZV1cIiwgXCJbbmFtZT12YWx1ZV1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFwiW25hbWU9XCJ2YWx1ZVwiXVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gXCJbbmFtZT0ndmFsdWUnXVwiXG4gICAgICAgICcoXFxcXCkpfCcgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDc6IFwiKVwiXG4gICAgICAgICcoXFxcXHMqLFxcXFxzKiknLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gODogXCIsXCJcbiAgICAnZycpO1xuXG4vKipcbiAqIFRoZXNlIG9mZnNldHMgc2hvdWxkIG1hdGNoIHRoZSBtYXRjaC1ncm91cHMgaW4gYF9TRUxFQ1RPUl9SRUdFWFBgIG9mZnNldHMuXG4gKi9cbmNvbnN0IGVudW0gU2VsZWN0b3JSZWdleHAge1xuICBBTEwgPSAwLCAgLy8gVGhlIHdob2xlIG1hdGNoXG4gIE5PVCA9IDEsXG4gIFRBRyA9IDIsXG4gIFBSRUZJWCA9IDMsXG4gIEFUVFJJQlVURSA9IDQsXG4gIEFUVFJJQlVURV9TVFJJTkcgPSA1LFxuICBBVFRSSUJVVEVfVkFMVUUgPSA2LFxuICBOT1RfRU5EID0gNyxcbiAgU0VQQVJBVE9SID0gOCxcbn1cbi8qKlxuICogQSBjc3Mgc2VsZWN0b3IgY29udGFpbnMgYW4gZWxlbWVudCBuYW1lLFxuICogY3NzIGNsYXNzZXMgYW5kIGF0dHJpYnV0ZS92YWx1ZSBwYWlycyB3aXRoIHRoZSBwdXJwb3NlXG4gKiBvZiBzZWxlY3Rpbmcgc3Vic2V0cyBvdXQgb2YgdGhlbS5cbiAqL1xuZXhwb3J0IGNsYXNzIENzc1NlbGVjdG9yIHtcbiAgZWxlbWVudDogc3RyaW5nfG51bGwgPSBudWxsO1xuICBjbGFzc05hbWVzOiBzdHJpbmdbXSA9IFtdO1xuICAvKipcbiAgICogVGhlIHNlbGVjdG9ycyBhcmUgZW5jb2RlZCBpbiBwYWlycyB3aGVyZTpcbiAgICogLSBldmVuIGxvY2F0aW9ucyBhcmUgYXR0cmlidXRlIG5hbWVzXG4gICAqIC0gb2RkIGxvY2F0aW9ucyBhcmUgYXR0cmlidXRlIHZhbHVlcy5cbiAgICpcbiAgICogRXhhbXBsZTpcbiAgICogU2VsZWN0b3I6IGBba2V5MT12YWx1ZTFdW2tleTJdYCB3b3VsZCBwYXJzZSB0bzpcbiAgICogYGBgXG4gICAqIFsna2V5MScsICd2YWx1ZTEnLCAna2V5MicsICcnXVxuICAgKiBgYGBcbiAgICovXG4gIGF0dHJzOiBzdHJpbmdbXSA9IFtdO1xuICBub3RTZWxlY3RvcnM6IENzc1NlbGVjdG9yW10gPSBbXTtcblxuICBzdGF0aWMgcGFyc2Uoc2VsZWN0b3I6IHN0cmluZyk6IENzc1NlbGVjdG9yW10ge1xuICAgIGNvbnN0IHJlc3VsdHM6IENzc1NlbGVjdG9yW10gPSBbXTtcbiAgICBjb25zdCBfYWRkUmVzdWx0ID0gKHJlczogQ3NzU2VsZWN0b3JbXSwgY3NzU2VsOiBDc3NTZWxlY3RvcikgPT4ge1xuICAgICAgaWYgKGNzc1NlbC5ub3RTZWxlY3RvcnMubGVuZ3RoID4gMCAmJiAhY3NzU2VsLmVsZW1lbnQgJiYgY3NzU2VsLmNsYXNzTmFtZXMubGVuZ3RoID09IDAgJiZcbiAgICAgICAgICBjc3NTZWwuYXR0cnMubGVuZ3RoID09IDApIHtcbiAgICAgICAgY3NzU2VsLmVsZW1lbnQgPSAnKic7XG4gICAgICB9XG4gICAgICByZXMucHVzaChjc3NTZWwpO1xuICAgIH07XG4gICAgbGV0IGNzc1NlbGVjdG9yID0gbmV3IENzc1NlbGVjdG9yKCk7XG4gICAgbGV0IG1hdGNoOiBzdHJpbmdbXXxudWxsO1xuICAgIGxldCBjdXJyZW50ID0gY3NzU2VsZWN0b3I7XG4gICAgbGV0IGluTm90ID0gZmFsc2U7XG4gICAgX1NFTEVDVE9SX1JFR0VYUC5sYXN0SW5kZXggPSAwO1xuICAgIHdoaWxlIChtYXRjaCA9IF9TRUxFQ1RPUl9SRUdFWFAuZXhlYyhzZWxlY3RvcikpIHtcbiAgICAgIGlmIChtYXRjaFtTZWxlY3RvclJlZ2V4cC5OT1RdKSB7XG4gICAgICAgIGlmIChpbk5vdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTmVzdGluZyA6bm90IGluIGEgc2VsZWN0b3IgaXMgbm90IGFsbG93ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpbk5vdCA9IHRydWU7XG4gICAgICAgIGN1cnJlbnQgPSBuZXcgQ3NzU2VsZWN0b3IoKTtcbiAgICAgICAgY3NzU2VsZWN0b3Iubm90U2VsZWN0b3JzLnB1c2goY3VycmVudCk7XG4gICAgICB9XG4gICAgICBjb25zdCB0YWcgPSBtYXRjaFtTZWxlY3RvclJlZ2V4cC5UQUddO1xuICAgICAgaWYgKHRhZykge1xuICAgICAgICBjb25zdCBwcmVmaXggPSBtYXRjaFtTZWxlY3RvclJlZ2V4cC5QUkVGSVhdO1xuICAgICAgICBpZiAocHJlZml4ID09PSAnIycpIHtcbiAgICAgICAgICAvLyAjaGFzaFxuICAgICAgICAgIGN1cnJlbnQuYWRkQXR0cmlidXRlKCdpZCcsIHRhZy5zdWJzdHIoMSkpO1xuICAgICAgICB9IGVsc2UgaWYgKHByZWZpeCA9PT0gJy4nKSB7XG4gICAgICAgICAgLy8gQ2xhc3NcbiAgICAgICAgICBjdXJyZW50LmFkZENsYXNzTmFtZSh0YWcuc3Vic3RyKDEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBFbGVtZW50XG4gICAgICAgICAgY3VycmVudC5zZXRFbGVtZW50KHRhZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IG1hdGNoW1NlbGVjdG9yUmVnZXhwLkFUVFJJQlVURV07XG5cbiAgICAgIGlmIChhdHRyaWJ1dGUpIHtcbiAgICAgICAgY3VycmVudC5hZGRBdHRyaWJ1dGUoXG4gICAgICAgICAgICBjdXJyZW50LnVuZXNjYXBlQXR0cmlidXRlKGF0dHJpYnV0ZSksIG1hdGNoW1NlbGVjdG9yUmVnZXhwLkFUVFJJQlVURV9WQUxVRV0pO1xuICAgICAgfVxuICAgICAgaWYgKG1hdGNoW1NlbGVjdG9yUmVnZXhwLk5PVF9FTkRdKSB7XG4gICAgICAgIGluTm90ID0gZmFsc2U7XG4gICAgICAgIGN1cnJlbnQgPSBjc3NTZWxlY3RvcjtcbiAgICAgIH1cbiAgICAgIGlmIChtYXRjaFtTZWxlY3RvclJlZ2V4cC5TRVBBUkFUT1JdKSB7XG4gICAgICAgIGlmIChpbk5vdCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTXVsdGlwbGUgc2VsZWN0b3JzIGluIDpub3QgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBfYWRkUmVzdWx0KHJlc3VsdHMsIGNzc1NlbGVjdG9yKTtcbiAgICAgICAgY3NzU2VsZWN0b3IgPSBjdXJyZW50ID0gbmV3IENzc1NlbGVjdG9yKCk7XG4gICAgICB9XG4gICAgfVxuICAgIF9hZGRSZXN1bHQocmVzdWx0cywgY3NzU2VsZWN0b3IpO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFVuZXNjYXBlIGBcXCRgIHNlcXVlbmNlcyBmcm9tIHRoZSBDU1MgYXR0cmlidXRlIHNlbGVjdG9yLlxuICAgKlxuICAgKiBUaGlzIGlzIG5lZWRlZCBiZWNhdXNlIGAkYCBjYW4gaGF2ZSBhIHNwZWNpYWwgbWVhbmluZyBpbiBDU1Mgc2VsZWN0b3JzLFxuICAgKiBidXQgd2UgbWlnaHQgd2FudCB0byBtYXRjaCBhbiBhdHRyaWJ1dGUgdGhhdCBjb250YWlucyBgJGAuXG4gICAqIFtNRE4gd2ViIGxpbmsgZm9yIG1vcmVcbiAgICogaW5mb10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0F0dHJpYnV0ZV9zZWxlY3RvcnMpLlxuICAgKiBAcGFyYW0gYXR0ciB0aGUgYXR0cmlidXRlIHRvIHVuZXNjYXBlLlxuICAgKiBAcmV0dXJucyB0aGUgdW5lc2NhcGVkIHN0cmluZy5cbiAgICovXG4gIHVuZXNjYXBlQXR0cmlidXRlKGF0dHI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IHJlc3VsdCA9ICcnO1xuICAgIGxldCBlc2NhcGluZyA9IGZhbHNlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ci5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgY2hhciA9IGF0dHIuY2hhckF0KGkpO1xuICAgICAgaWYgKGNoYXIgPT09ICdcXFxcJykge1xuICAgICAgICBlc2NhcGluZyA9IHRydWU7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKGNoYXIgPT09ICckJyAmJiAhZXNjYXBpbmcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYEVycm9yIGluIGF0dHJpYnV0ZSBzZWxlY3RvciBcIiR7YXR0cn1cIi4gYCArXG4gICAgICAgICAgICBgVW5lc2NhcGVkIFwiJFwiIGlzIG5vdCBzdXBwb3J0ZWQuIFBsZWFzZSBlc2NhcGUgd2l0aCBcIlxcXFwkXCIuYCk7XG4gICAgICB9XG4gICAgICBlc2NhcGluZyA9IGZhbHNlO1xuICAgICAgcmVzdWx0ICs9IGNoYXI7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRXNjYXBlIGAkYCBzZXF1ZW5jZXMgZnJvbSB0aGUgQ1NTIGF0dHJpYnV0ZSBzZWxlY3Rvci5cbiAgICpcbiAgICogVGhpcyBpcyBuZWVkZWQgYmVjYXVzZSBgJGAgY2FuIGhhdmUgYSBzcGVjaWFsIG1lYW5pbmcgaW4gQ1NTIHNlbGVjdG9ycyxcbiAgICogd2l0aCB0aGlzIG1ldGhvZCB3ZSBhcmUgZXNjYXBpbmcgYCRgIHdpdGggYFxcJCcuXG4gICAqIFtNRE4gd2ViIGxpbmsgZm9yIG1vcmVcbiAgICogaW5mb10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0F0dHJpYnV0ZV9zZWxlY3RvcnMpLlxuICAgKiBAcGFyYW0gYXR0ciB0aGUgYXR0cmlidXRlIHRvIGVzY2FwZS5cbiAgICogQHJldHVybnMgdGhlIGVzY2FwZWQgc3RyaW5nLsKgXG4gICAqL1xuICBlc2NhcGVBdHRyaWJ1dGUoYXR0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYXR0ci5yZXBsYWNlKC9cXFxcL2csICdcXFxcXFxcXCcpLnJlcGxhY2UoL1xcJC9nLCAnXFxcXCQnKTtcbiAgfVxuXG4gIGlzRWxlbWVudFNlbGVjdG9yKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmhhc0VsZW1lbnRTZWxlY3RvcigpICYmIHRoaXMuY2xhc3NOYW1lcy5sZW5ndGggPT0gMCAmJiB0aGlzLmF0dHJzLmxlbmd0aCA9PSAwICYmXG4gICAgICAgIHRoaXMubm90U2VsZWN0b3JzLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIGhhc0VsZW1lbnRTZWxlY3RvcigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmVsZW1lbnQ7XG4gIH1cblxuICBzZXRFbGVtZW50KGVsZW1lbnQ6IHN0cmluZ3xudWxsID0gbnVsbCkge1xuICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gIH1cblxuICAvKiogR2V0cyBhIHRlbXBsYXRlIHN0cmluZyBmb3IgYW4gZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNlbGVjdG9yLiAqL1xuICBnZXRNYXRjaGluZ0VsZW1lbnRUZW1wbGF0ZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHRhZ05hbWUgPSB0aGlzLmVsZW1lbnQgfHwgJ2Rpdic7XG4gICAgY29uc3QgY2xhc3NBdHRyID0gdGhpcy5jbGFzc05hbWVzLmxlbmd0aCA+IDAgPyBgIGNsYXNzPVwiJHt0aGlzLmNsYXNzTmFtZXMuam9pbignICcpfVwiYCA6ICcnO1xuXG4gICAgbGV0IGF0dHJzID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmF0dHJzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICBjb25zdCBhdHRyTmFtZSA9IHRoaXMuYXR0cnNbaV07XG4gICAgICBjb25zdCBhdHRyVmFsdWUgPSB0aGlzLmF0dHJzW2kgKyAxXSAhPT0gJycgPyBgPVwiJHt0aGlzLmF0dHJzW2kgKyAxXX1cImAgOiAnJztcbiAgICAgIGF0dHJzICs9IGAgJHthdHRyTmFtZX0ke2F0dHJWYWx1ZX1gO1xuICAgIH1cblxuICAgIHJldHVybiBnZXRIdG1sVGFnRGVmaW5pdGlvbih0YWdOYW1lKS5pc1ZvaWQgPyBgPCR7dGFnTmFtZX0ke2NsYXNzQXR0cn0ke2F0dHJzfS8+YCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA8JHt0YWdOYW1lfSR7Y2xhc3NBdHRyfSR7YXR0cnN9PjwvJHt0YWdOYW1lfT5gO1xuICB9XG5cbiAgZ2V0QXR0cnMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHJlc3VsdDogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAodGhpcy5jbGFzc05hbWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJlc3VsdC5wdXNoKCdjbGFzcycsIHRoaXMuY2xhc3NOYW1lcy5qb2luKCcgJykpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0LmNvbmNhdCh0aGlzLmF0dHJzKTtcbiAgfVxuXG4gIGFkZEF0dHJpYnV0ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgPSAnJykge1xuICAgIHRoaXMuYXR0cnMucHVzaChuYW1lLCB2YWx1ZSAmJiB2YWx1ZS50b0xvd2VyQ2FzZSgpIHx8ICcnKTtcbiAgfVxuXG4gIGFkZENsYXNzTmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICB0aGlzLmNsYXNzTmFtZXMucHVzaChuYW1lLnRvTG93ZXJDYXNlKCkpO1xuICB9XG5cbiAgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICBsZXQgcmVzOiBzdHJpbmcgPSB0aGlzLmVsZW1lbnQgfHwgJyc7XG4gICAgaWYgKHRoaXMuY2xhc3NOYW1lcykge1xuICAgICAgdGhpcy5jbGFzc05hbWVzLmZvckVhY2goa2xhc3MgPT4gcmVzICs9IGAuJHtrbGFzc31gKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYXR0cnMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5hdHRycy5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgICBjb25zdCBuYW1lID0gdGhpcy5lc2NhcGVBdHRyaWJ1dGUodGhpcy5hdHRyc1tpXSk7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5hdHRyc1tpICsgMV07XG4gICAgICAgIHJlcyArPSBgWyR7bmFtZX0ke3ZhbHVlID8gJz0nICsgdmFsdWUgOiAnJ31dYDtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5ub3RTZWxlY3RvcnMuZm9yRWFjaChub3RTZWxlY3RvciA9PiByZXMgKz0gYDpub3QoJHtub3RTZWxlY3Rvcn0pYCk7XG4gICAgcmV0dXJuIHJlcztcbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIGEgbGlzdCBvZiBDc3NTZWxlY3RvcnMgYW5kIGFsbG93cyB0byBjYWxjdWxhdGUgd2hpY2ggb25lc1xuICogYXJlIGNvbnRhaW5lZCBpbiBhIGdpdmVuIENzc1NlbGVjdG9yLlxuICovXG5leHBvcnQgY2xhc3MgU2VsZWN0b3JNYXRjaGVyPFQgPSBhbnk+IHtcbiAgc3RhdGljIGNyZWF0ZU5vdE1hdGNoZXIobm90U2VsZWN0b3JzOiBDc3NTZWxlY3RvcltdKTogU2VsZWN0b3JNYXRjaGVyPG51bGw+IHtcbiAgICBjb25zdCBub3RNYXRjaGVyID0gbmV3IFNlbGVjdG9yTWF0Y2hlcjxudWxsPigpO1xuICAgIG5vdE1hdGNoZXIuYWRkU2VsZWN0YWJsZXMobm90U2VsZWN0b3JzLCBudWxsKTtcbiAgICByZXR1cm4gbm90TWF0Y2hlcjtcbiAgfVxuXG4gIHByaXZhdGUgX2VsZW1lbnRNYXAgPSBuZXcgTWFwPHN0cmluZywgU2VsZWN0b3JDb250ZXh0PFQ+W10+KCk7XG4gIHByaXZhdGUgX2VsZW1lbnRQYXJ0aWFsTWFwID0gbmV3IE1hcDxzdHJpbmcsIFNlbGVjdG9yTWF0Y2hlcjxUPj4oKTtcbiAgcHJpdmF0ZSBfY2xhc3NNYXAgPSBuZXcgTWFwPHN0cmluZywgU2VsZWN0b3JDb250ZXh0PFQ+W10+KCk7XG4gIHByaXZhdGUgX2NsYXNzUGFydGlhbE1hcCA9IG5ldyBNYXA8c3RyaW5nLCBTZWxlY3Rvck1hdGNoZXI8VD4+KCk7XG4gIHByaXZhdGUgX2F0dHJWYWx1ZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBTZWxlY3RvckNvbnRleHQ8VD5bXT4+KCk7XG4gIHByaXZhdGUgX2F0dHJWYWx1ZVBhcnRpYWxNYXAgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgU2VsZWN0b3JNYXRjaGVyPFQ+Pj4oKTtcbiAgcHJpdmF0ZSBfbGlzdENvbnRleHRzOiBTZWxlY3Rvckxpc3RDb250ZXh0W10gPSBbXTtcblxuICBhZGRTZWxlY3RhYmxlcyhjc3NTZWxlY3RvcnM6IENzc1NlbGVjdG9yW10sIGNhbGxiYWNrQ3R4dD86IFQpIHtcbiAgICBsZXQgbGlzdENvbnRleHQ6IFNlbGVjdG9yTGlzdENvbnRleHQgPSBudWxsITtcbiAgICBpZiAoY3NzU2VsZWN0b3JzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGxpc3RDb250ZXh0ID0gbmV3IFNlbGVjdG9yTGlzdENvbnRleHQoY3NzU2VsZWN0b3JzKTtcbiAgICAgIHRoaXMuX2xpc3RDb250ZXh0cy5wdXNoKGxpc3RDb250ZXh0KTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjc3NTZWxlY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuX2FkZFNlbGVjdGFibGUoY3NzU2VsZWN0b3JzW2ldLCBjYWxsYmFja0N0eHQgYXMgVCwgbGlzdENvbnRleHQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIGZvdW5kIGxhdGVyIG9uIGJ5IGNhbGxpbmcgYG1hdGNoYC5cbiAgICogQHBhcmFtIGNzc1NlbGVjdG9yIEEgY3NzIHNlbGVjdG9yXG4gICAqIEBwYXJhbSBjYWxsYmFja0N0eHQgQW4gb3BhcXVlIG9iamVjdCB0aGF0IHdpbGwgYmUgZ2l2ZW4gdG8gdGhlIGNhbGxiYWNrIG9mIHRoZSBgbWF0Y2hgIGZ1bmN0aW9uXG4gICAqL1xuICBwcml2YXRlIF9hZGRTZWxlY3RhYmxlKFxuICAgICAgY3NzU2VsZWN0b3I6IENzc1NlbGVjdG9yLCBjYWxsYmFja0N0eHQ6IFQsIGxpc3RDb250ZXh0OiBTZWxlY3Rvckxpc3RDb250ZXh0KSB7XG4gICAgbGV0IG1hdGNoZXI6IFNlbGVjdG9yTWF0Y2hlcjxUPiA9IHRoaXM7XG4gICAgY29uc3QgZWxlbWVudCA9IGNzc1NlbGVjdG9yLmVsZW1lbnQ7XG4gICAgY29uc3QgY2xhc3NOYW1lcyA9IGNzc1NlbGVjdG9yLmNsYXNzTmFtZXM7XG4gICAgY29uc3QgYXR0cnMgPSBjc3NTZWxlY3Rvci5hdHRycztcbiAgICBjb25zdCBzZWxlY3RhYmxlID0gbmV3IFNlbGVjdG9yQ29udGV4dChjc3NTZWxlY3RvciwgY2FsbGJhY2tDdHh0LCBsaXN0Q29udGV4dCk7XG5cbiAgICBpZiAoZWxlbWVudCkge1xuICAgICAgY29uc3QgaXNUZXJtaW5hbCA9IGF0dHJzLmxlbmd0aCA9PT0gMCAmJiBjbGFzc05hbWVzLmxlbmd0aCA9PT0gMDtcbiAgICAgIGlmIChpc1Rlcm1pbmFsKSB7XG4gICAgICAgIHRoaXMuX2FkZFRlcm1pbmFsKG1hdGNoZXIuX2VsZW1lbnRNYXAsIGVsZW1lbnQsIHNlbGVjdGFibGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF0Y2hlciA9IHRoaXMuX2FkZFBhcnRpYWwobWF0Y2hlci5fZWxlbWVudFBhcnRpYWxNYXAsIGVsZW1lbnQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjbGFzc05hbWVzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNsYXNzTmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaXNUZXJtaW5hbCA9IGF0dHJzLmxlbmd0aCA9PT0gMCAmJiBpID09PSBjbGFzc05hbWVzLmxlbmd0aCAtIDE7XG4gICAgICAgIGNvbnN0IGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbaV07XG4gICAgICAgIGlmIChpc1Rlcm1pbmFsKSB7XG4gICAgICAgICAgdGhpcy5fYWRkVGVybWluYWwobWF0Y2hlci5fY2xhc3NNYXAsIGNsYXNzTmFtZSwgc2VsZWN0YWJsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbWF0Y2hlciA9IHRoaXMuX2FkZFBhcnRpYWwobWF0Y2hlci5fY2xhc3NQYXJ0aWFsTWFwLCBjbGFzc05hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGF0dHJzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgIGNvbnN0IGlzVGVybWluYWwgPSBpID09PSBhdHRycy5sZW5ndGggLSAyO1xuICAgICAgICBjb25zdCBuYW1lID0gYXR0cnNbaV07XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXR0cnNbaSArIDFdO1xuICAgICAgICBpZiAoaXNUZXJtaW5hbCkge1xuICAgICAgICAgIGNvbnN0IHRlcm1pbmFsTWFwID0gbWF0Y2hlci5fYXR0clZhbHVlTWFwO1xuICAgICAgICAgIGxldCB0ZXJtaW5hbFZhbHVlc01hcCA9IHRlcm1pbmFsTWFwLmdldChuYW1lKTtcbiAgICAgICAgICBpZiAoIXRlcm1pbmFsVmFsdWVzTWFwKSB7XG4gICAgICAgICAgICB0ZXJtaW5hbFZhbHVlc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBTZWxlY3RvckNvbnRleHQ8VD5bXT4oKTtcbiAgICAgICAgICAgIHRlcm1pbmFsTWFwLnNldChuYW1lLCB0ZXJtaW5hbFZhbHVlc01hcCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuX2FkZFRlcm1pbmFsKHRlcm1pbmFsVmFsdWVzTWFwLCB2YWx1ZSwgc2VsZWN0YWJsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgcGFydGlhbE1hcCA9IG1hdGNoZXIuX2F0dHJWYWx1ZVBhcnRpYWxNYXA7XG4gICAgICAgICAgbGV0IHBhcnRpYWxWYWx1ZXNNYXAgPSBwYXJ0aWFsTWFwLmdldChuYW1lKTtcbiAgICAgICAgICBpZiAoIXBhcnRpYWxWYWx1ZXNNYXApIHtcbiAgICAgICAgICAgIHBhcnRpYWxWYWx1ZXNNYXAgPSBuZXcgTWFwPHN0cmluZywgU2VsZWN0b3JNYXRjaGVyPFQ+PigpO1xuICAgICAgICAgICAgcGFydGlhbE1hcC5zZXQobmFtZSwgcGFydGlhbFZhbHVlc01hcCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG1hdGNoZXIgPSB0aGlzLl9hZGRQYXJ0aWFsKHBhcnRpYWxWYWx1ZXNNYXAsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2FkZFRlcm1pbmFsKFxuICAgICAgbWFwOiBNYXA8c3RyaW5nLCBTZWxlY3RvckNvbnRleHQ8VD5bXT4sIG5hbWU6IHN0cmluZywgc2VsZWN0YWJsZTogU2VsZWN0b3JDb250ZXh0PFQ+KSB7XG4gICAgbGV0IHRlcm1pbmFsTGlzdCA9IG1hcC5nZXQobmFtZSk7XG4gICAgaWYgKCF0ZXJtaW5hbExpc3QpIHtcbiAgICAgIHRlcm1pbmFsTGlzdCA9IFtdO1xuICAgICAgbWFwLnNldChuYW1lLCB0ZXJtaW5hbExpc3QpO1xuICAgIH1cbiAgICB0ZXJtaW5hbExpc3QucHVzaChzZWxlY3RhYmxlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2FkZFBhcnRpYWwobWFwOiBNYXA8c3RyaW5nLCBTZWxlY3Rvck1hdGNoZXI8VD4+LCBuYW1lOiBzdHJpbmcpOiBTZWxlY3Rvck1hdGNoZXI8VD4ge1xuICAgIGxldCBtYXRjaGVyID0gbWFwLmdldChuYW1lKTtcbiAgICBpZiAoIW1hdGNoZXIpIHtcbiAgICAgIG1hdGNoZXIgPSBuZXcgU2VsZWN0b3JNYXRjaGVyPFQ+KCk7XG4gICAgICBtYXAuc2V0KG5hbWUsIG1hdGNoZXIpO1xuICAgIH1cbiAgICByZXR1cm4gbWF0Y2hlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kIHRoZSBvYmplY3RzIHRoYXQgaGF2ZSBiZWVuIGFkZGVkIHZpYSBgYWRkU2VsZWN0YWJsZWBcbiAgICogd2hvc2UgY3NzIHNlbGVjdG9yIGlzIGNvbnRhaW5lZCBpbiB0aGUgZ2l2ZW4gY3NzIHNlbGVjdG9yLlxuICAgKiBAcGFyYW0gY3NzU2VsZWN0b3IgQSBjc3Mgc2VsZWN0b3JcbiAgICogQHBhcmFtIG1hdGNoZWRDYWxsYmFjayBUaGlzIGNhbGxiYWNrIHdpbGwgYmUgY2FsbGVkIHdpdGggdGhlIG9iamVjdCBoYW5kZWQgaW50byBgYWRkU2VsZWN0YWJsZWBcbiAgICogQHJldHVybiBib29sZWFuIHRydWUgaWYgYSBtYXRjaCB3YXMgZm91bmRcbiAgICovXG4gIG1hdGNoKGNzc1NlbGVjdG9yOiBDc3NTZWxlY3RvciwgbWF0Y2hlZENhbGxiYWNrOiAoKGM6IENzc1NlbGVjdG9yLCBhOiBUKSA9PiB2b2lkKXxudWxsKTogYm9vbGVhbiB7XG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlO1xuICAgIGNvbnN0IGVsZW1lbnQgPSBjc3NTZWxlY3Rvci5lbGVtZW50ITtcbiAgICBjb25zdCBjbGFzc05hbWVzID0gY3NzU2VsZWN0b3IuY2xhc3NOYW1lcztcbiAgICBjb25zdCBhdHRycyA9IGNzc1NlbGVjdG9yLmF0dHJzO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9saXN0Q29udGV4dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuX2xpc3RDb250ZXh0c1tpXS5hbHJlYWR5TWF0Y2hlZCA9IGZhbHNlO1xuICAgIH1cblxuICAgIHJlc3VsdCA9IHRoaXMuX21hdGNoVGVybWluYWwodGhpcy5fZWxlbWVudE1hcCwgZWxlbWVudCwgY3NzU2VsZWN0b3IsIG1hdGNoZWRDYWxsYmFjaykgfHwgcmVzdWx0O1xuICAgIHJlc3VsdCA9IHRoaXMuX21hdGNoUGFydGlhbCh0aGlzLl9lbGVtZW50UGFydGlhbE1hcCwgZWxlbWVudCwgY3NzU2VsZWN0b3IsIG1hdGNoZWRDYWxsYmFjaykgfHxcbiAgICAgICAgcmVzdWx0O1xuXG4gICAgaWYgKGNsYXNzTmFtZXMpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2xhc3NOYW1lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjbGFzc05hbWUgPSBjbGFzc05hbWVzW2ldO1xuICAgICAgICByZXN1bHQgPVxuICAgICAgICAgICAgdGhpcy5fbWF0Y2hUZXJtaW5hbCh0aGlzLl9jbGFzc01hcCwgY2xhc3NOYW1lLCBjc3NTZWxlY3RvciwgbWF0Y2hlZENhbGxiYWNrKSB8fCByZXN1bHQ7XG4gICAgICAgIHJlc3VsdCA9XG4gICAgICAgICAgICB0aGlzLl9tYXRjaFBhcnRpYWwodGhpcy5fY2xhc3NQYXJ0aWFsTWFwLCBjbGFzc05hbWUsIGNzc1NlbGVjdG9yLCBtYXRjaGVkQ2FsbGJhY2spIHx8XG4gICAgICAgICAgICByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGF0dHJzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHJzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBhdHRyc1tpXTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBhdHRyc1tpICsgMV07XG5cbiAgICAgICAgY29uc3QgdGVybWluYWxWYWx1ZXNNYXAgPSB0aGlzLl9hdHRyVmFsdWVNYXAuZ2V0KG5hbWUpITtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgcmVzdWx0ID1cbiAgICAgICAgICAgICAgdGhpcy5fbWF0Y2hUZXJtaW5hbCh0ZXJtaW5hbFZhbHVlc01hcCwgJycsIGNzc1NlbGVjdG9yLCBtYXRjaGVkQ2FsbGJhY2spIHx8IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPVxuICAgICAgICAgICAgdGhpcy5fbWF0Y2hUZXJtaW5hbCh0ZXJtaW5hbFZhbHVlc01hcCwgdmFsdWUsIGNzc1NlbGVjdG9yLCBtYXRjaGVkQ2FsbGJhY2spIHx8IHJlc3VsdDtcblxuICAgICAgICBjb25zdCBwYXJ0aWFsVmFsdWVzTWFwID0gdGhpcy5fYXR0clZhbHVlUGFydGlhbE1hcC5nZXQobmFtZSkhO1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICByZXN1bHQgPSB0aGlzLl9tYXRjaFBhcnRpYWwocGFydGlhbFZhbHVlc01hcCwgJycsIGNzc1NlbGVjdG9yLCBtYXRjaGVkQ2FsbGJhY2spIHx8IHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPVxuICAgICAgICAgICAgdGhpcy5fbWF0Y2hQYXJ0aWFsKHBhcnRpYWxWYWx1ZXNNYXAsIHZhbHVlLCBjc3NTZWxlY3RvciwgbWF0Y2hlZENhbGxiYWNrKSB8fCByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIF9tYXRjaFRlcm1pbmFsKFxuICAgICAgbWFwOiBNYXA8c3RyaW5nLCBTZWxlY3RvckNvbnRleHQ8VD5bXT4sIG5hbWU6IHN0cmluZywgY3NzU2VsZWN0b3I6IENzc1NlbGVjdG9yLFxuICAgICAgbWF0Y2hlZENhbGxiYWNrOiAoKGM6IENzc1NlbGVjdG9yLCBhOiBhbnkpID0+IHZvaWQpfG51bGwpOiBib29sZWFuIHtcbiAgICBpZiAoIW1hcCB8fCB0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBsZXQgc2VsZWN0YWJsZXM6IFNlbGVjdG9yQ29udGV4dDxUPltdID0gbWFwLmdldChuYW1lKSB8fCBbXTtcbiAgICBjb25zdCBzdGFyU2VsZWN0YWJsZXM6IFNlbGVjdG9yQ29udGV4dDxUPltdID0gbWFwLmdldCgnKicpITtcbiAgICBpZiAoc3RhclNlbGVjdGFibGVzKSB7XG4gICAgICBzZWxlY3RhYmxlcyA9IHNlbGVjdGFibGVzLmNvbmNhdChzdGFyU2VsZWN0YWJsZXMpO1xuICAgIH1cbiAgICBpZiAoc2VsZWN0YWJsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGxldCBzZWxlY3RhYmxlOiBTZWxlY3RvckNvbnRleHQ8VD47XG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0YWJsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHNlbGVjdGFibGUgPSBzZWxlY3RhYmxlc1tpXTtcbiAgICAgIHJlc3VsdCA9IHNlbGVjdGFibGUuZmluYWxpemUoY3NzU2VsZWN0b3IsIG1hdGNoZWRDYWxsYmFjaykgfHwgcmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBfbWF0Y2hQYXJ0aWFsKFxuICAgICAgbWFwOiBNYXA8c3RyaW5nLCBTZWxlY3Rvck1hdGNoZXI8VD4+LCBuYW1lOiBzdHJpbmcsIGNzc1NlbGVjdG9yOiBDc3NTZWxlY3RvcixcbiAgICAgIG1hdGNoZWRDYWxsYmFjazogKChjOiBDc3NTZWxlY3RvciwgYTogYW55KSA9PiB2b2lkKXxudWxsKTogYm9vbGVhbiB7XG4gICAgaWYgKCFtYXAgfHwgdHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgbmVzdGVkU2VsZWN0b3IgPSBtYXAuZ2V0KG5hbWUpO1xuICAgIGlmICghbmVzdGVkU2VsZWN0b3IpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgLy8gVE9ETyhwZXJmKTogZ2V0IHJpZCBvZiByZWN1cnNpb24gYW5kIG1lYXN1cmUgYWdhaW5cbiAgICAvLyBUT0RPKHBlcmYpOiBkb24ndCBwYXNzIHRoZSB3aG9sZSBzZWxlY3RvciBpbnRvIHRoZSByZWN1cnNpb24sXG4gICAgLy8gYnV0IG9ubHkgdGhlIG5vdCBwcm9jZXNzZWQgcGFydHNcbiAgICByZXR1cm4gbmVzdGVkU2VsZWN0b3IubWF0Y2goY3NzU2VsZWN0b3IsIG1hdGNoZWRDYWxsYmFjayk7XG4gIH1cbn1cblxuXG5leHBvcnQgY2xhc3MgU2VsZWN0b3JMaXN0Q29udGV4dCB7XG4gIGFscmVhZHlNYXRjaGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHNlbGVjdG9yczogQ3NzU2VsZWN0b3JbXSkge31cbn1cblxuLy8gU3RvcmUgY29udGV4dCB0byBwYXNzIGJhY2sgc2VsZWN0b3IgYW5kIGNvbnRleHQgd2hlbiBhIHNlbGVjdG9yIGlzIG1hdGNoZWRcbmV4cG9ydCBjbGFzcyBTZWxlY3RvckNvbnRleHQ8VCA9IGFueT4ge1xuICBub3RTZWxlY3RvcnM6IENzc1NlbGVjdG9yW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBwdWJsaWMgc2VsZWN0b3I6IENzc1NlbGVjdG9yLCBwdWJsaWMgY2JDb250ZXh0OiBULCBwdWJsaWMgbGlzdENvbnRleHQ6IFNlbGVjdG9yTGlzdENvbnRleHQpIHtcbiAgICB0aGlzLm5vdFNlbGVjdG9ycyA9IHNlbGVjdG9yLm5vdFNlbGVjdG9ycztcbiAgfVxuXG4gIGZpbmFsaXplKGNzc1NlbGVjdG9yOiBDc3NTZWxlY3RvciwgY2FsbGJhY2s6ICgoYzogQ3NzU2VsZWN0b3IsIGE6IFQpID0+IHZvaWQpfG51bGwpOiBib29sZWFuIHtcbiAgICBsZXQgcmVzdWx0ID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5ub3RTZWxlY3RvcnMubGVuZ3RoID4gMCAmJiAoIXRoaXMubGlzdENvbnRleHQgfHwgIXRoaXMubGlzdENvbnRleHQuYWxyZWFkeU1hdGNoZWQpKSB7XG4gICAgICBjb25zdCBub3RNYXRjaGVyID0gU2VsZWN0b3JNYXRjaGVyLmNyZWF0ZU5vdE1hdGNoZXIodGhpcy5ub3RTZWxlY3RvcnMpO1xuICAgICAgcmVzdWx0ID0gIW5vdE1hdGNoZXIubWF0Y2goY3NzU2VsZWN0b3IsIG51bGwpO1xuICAgIH1cbiAgICBpZiAocmVzdWx0ICYmIGNhbGxiYWNrICYmICghdGhpcy5saXN0Q29udGV4dCB8fCAhdGhpcy5saXN0Q29udGV4dC5hbHJlYWR5TWF0Y2hlZCkpIHtcbiAgICAgIGlmICh0aGlzLmxpc3RDb250ZXh0KSB7XG4gICAgICAgIHRoaXMubGlzdENvbnRleHQuYWxyZWFkeU1hdGNoZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgY2FsbGJhY2sodGhpcy5zZWxlY3RvciwgdGhpcy5jYkNvbnRleHQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iXX0= |
---|