UNPKG

29.5 kBJavaScriptView Raw
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/language-service/src/utils", ["require", "exports", "tslib", "@angular/compiler", "path"], factory);
15 }
16})(function (require, exports) {
17 "use strict";
18 Object.defineProperty(exports, "__esModule", { value: true });
19 exports.extractAbsoluteFilePath = exports.findOutputBinding = exports.invertMap = exports.getPathToNodeAtPosition = exports.findTemplateAstAt = exports.diagnosticInfoFromTemplateInfo = exports.getSelectors = exports.isStructuralDirective = exports.isNarrower = exports.offsetSpan = exports.inSpan = exports.spanOf = void 0;
20 var tslib_1 = require("tslib");
21 var compiler_1 = require("@angular/compiler");
22 var path = require("path");
23 function isParseSourceSpan(value) {
24 return value && !!value.start;
25 }
26 function spanOf(span) {
27 if (!span)
28 return undefined;
29 if (isParseSourceSpan(span)) {
30 return { start: span.start.offset, end: span.end.offset };
31 }
32 else {
33 if (span.endSourceSpan) {
34 return { start: span.sourceSpan.start.offset, end: span.endSourceSpan.end.offset };
35 }
36 else if (span.children && span.children.length) {
37 return {
38 start: span.sourceSpan.start.offset,
39 end: spanOf(span.children[span.children.length - 1]).end
40 };
41 }
42 return { start: span.sourceSpan.start.offset, end: span.sourceSpan.end.offset };
43 }
44 }
45 exports.spanOf = spanOf;
46 function inSpan(position, span, exclusive) {
47 return span != null &&
48 (exclusive ? position >= span.start && position < span.end :
49 position >= span.start && position <= span.end);
50 }
51 exports.inSpan = inSpan;
52 function offsetSpan(span, amount) {
53 return { start: span.start + amount, end: span.end + amount };
54 }
55 exports.offsetSpan = offsetSpan;
56 function isNarrower(spanA, spanB) {
57 return spanA.start >= spanB.start && spanA.end <= spanB.end;
58 }
59 exports.isNarrower = isNarrower;
60 function isStructuralDirective(type) {
61 var e_1, _a;
62 var _b;
63 try {
64 for (var _c = tslib_1.__values(type.diDeps), _d = _c.next(); !_d.done; _d = _c.next()) {
65 var diDep = _d.value;
66 var diDepName = compiler_1.identifierName((_b = diDep.token) === null || _b === void 0 ? void 0 : _b.identifier);
67 if (diDepName === compiler_1.Identifiers.TemplateRef.name ||
68 diDepName === compiler_1.Identifiers.ViewContainerRef.name) {
69 return true;
70 }
71 }
72 }
73 catch (e_1_1) { e_1 = { error: e_1_1 }; }
74 finally {
75 try {
76 if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
77 }
78 finally { if (e_1) throw e_1.error; }
79 }
80 return false;
81 }
82 exports.isStructuralDirective = isStructuralDirective;
83 function getSelectors(info) {
84 var e_2, _a, e_3, _b;
85 var map = new Map();
86 var results = [];
87 try {
88 for (var _c = tslib_1.__values(info.directives), _d = _c.next(); !_d.done; _d = _c.next()) {
89 var directive = _d.value;
90 var selectors = compiler_1.CssSelector.parse(directive.selector);
91 try {
92 for (var selectors_1 = (e_3 = void 0, tslib_1.__values(selectors)), selectors_1_1 = selectors_1.next(); !selectors_1_1.done; selectors_1_1 = selectors_1.next()) {
93 var selector = selectors_1_1.value;
94 results.push(selector);
95 map.set(selector, directive);
96 }
97 }
98 catch (e_3_1) { e_3 = { error: e_3_1 }; }
99 finally {
100 try {
101 if (selectors_1_1 && !selectors_1_1.done && (_b = selectors_1.return)) _b.call(selectors_1);
102 }
103 finally { if (e_3) throw e_3.error; }
104 }
105 }
106 }
107 catch (e_2_1) { e_2 = { error: e_2_1 }; }
108 finally {
109 try {
110 if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
111 }
112 finally { if (e_2) throw e_2.error; }
113 }
114 return { selectors: results, map: map };
115 }
116 exports.getSelectors = getSelectors;
117 function diagnosticInfoFromTemplateInfo(info) {
118 return {
119 fileName: info.template.fileName,
120 offset: info.template.span.start,
121 query: info.template.query,
122 members: info.template.members,
123 htmlAst: info.htmlAst,
124 templateAst: info.templateAst,
125 source: info.template.source,
126 };
127 }
128 exports.diagnosticInfoFromTemplateInfo = diagnosticInfoFromTemplateInfo;
129 function findTemplateAstAt(ast, position) {
130 var path = [];
131 var visitor = new /** @class */ (function (_super) {
132 tslib_1.__extends(class_1, _super);
133 function class_1() {
134 return _super !== null && _super.apply(this, arguments) || this;
135 }
136 class_1.prototype.visit = function (ast) {
137 var span = spanOf(ast);
138 if (inSpan(position, span)) {
139 var len = path.length;
140 if (!len || isNarrower(span, spanOf(path[len - 1]))) {
141 path.push(ast);
142 }
143 }
144 else {
145 // Returning a value here will result in the children being skipped.
146 return true;
147 }
148 };
149 class_1.prototype.visitEmbeddedTemplate = function (ast, context) {
150 return this.visitChildren(context, function (visit) {
151 // Ignore reference, variable and providers
152 visit(ast.attrs);
153 visit(ast.directives);
154 visit(ast.children);
155 });
156 };
157 class_1.prototype.visitElement = function (ast, context) {
158 return this.visitChildren(context, function (visit) {
159 // Ingnore providers
160 visit(ast.attrs);
161 visit(ast.inputs);
162 visit(ast.outputs);
163 visit(ast.references);
164 visit(ast.directives);
165 visit(ast.children);
166 });
167 };
168 class_1.prototype.visitDirective = function (ast, context) {
169 // Ignore the host properties of a directive
170 var result = this.visitChildren(context, function (visit) {
171 visit(ast.inputs);
172 });
173 // We never care about the diretive itself, just its inputs.
174 if (path[path.length - 1] === ast) {
175 path.pop();
176 }
177 return result;
178 };
179 return class_1;
180 }(compiler_1.RecursiveTemplateAstVisitor));
181 compiler_1.templateVisitAll(visitor, ast);
182 return new compiler_1.AstPath(path, position);
183 }
184 exports.findTemplateAstAt = findTemplateAstAt;
185 /**
186 * Find the tightest node at the specified `position` from the AST `nodes`, and
187 * return the path to the node.
188 * @param nodes HTML AST nodes
189 * @param position
190 */
191 function getPathToNodeAtPosition(nodes, position) {
192 var path = [];
193 var visitor = new /** @class */ (function (_super) {
194 tslib_1.__extends(class_2, _super);
195 function class_2() {
196 return _super !== null && _super.apply(this, arguments) || this;
197 }
198 class_2.prototype.visit = function (ast) {
199 var span = spanOf(ast);
200 if (inSpan(position, span)) {
201 path.push(ast);
202 }
203 else {
204 // Returning a truthy value here will skip all children and terminate
205 // the visit.
206 return true;
207 }
208 };
209 return class_2;
210 }(compiler_1.RecursiveVisitor));
211 compiler_1.visitAll(visitor, nodes);
212 return new compiler_1.AstPath(path, position);
213 }
214 exports.getPathToNodeAtPosition = getPathToNodeAtPosition;
215 /**
216 * Inverts an object's key-value pairs.
217 */
218 function invertMap(obj) {
219 var e_4, _a;
220 var result = {};
221 try {
222 for (var _b = tslib_1.__values(Object.keys(obj)), _c = _b.next(); !_c.done; _c = _b.next()) {
223 var name_1 = _c.value;
224 var v = obj[name_1];
225 result[v] = name_1;
226 }
227 }
228 catch (e_4_1) { e_4 = { error: e_4_1 }; }
229 finally {
230 try {
231 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
232 }
233 finally { if (e_4) throw e_4.error; }
234 }
235 return result;
236 }
237 exports.invertMap = invertMap;
238 /**
239 * Finds the directive member providing a template output binding, if one exists.
240 * @param info aggregate template AST information
241 * @param path narrowing
242 */
243 function findOutputBinding(binding, path, query) {
244 var e_5, _a;
245 var element = path.first(compiler_1.ElementAst);
246 if (element) {
247 try {
248 for (var _b = tslib_1.__values(element.directives), _c = _b.next(); !_c.done; _c = _b.next()) {
249 var directive = _c.value;
250 var invertedOutputs = invertMap(directive.directive.outputs);
251 var fieldName = invertedOutputs[binding.name];
252 if (fieldName) {
253 var classSymbol = query.getTypeSymbol(directive.directive.type.reference);
254 if (classSymbol) {
255 return classSymbol.members().get(fieldName);
256 }
257 }
258 }
259 }
260 catch (e_5_1) { e_5 = { error: e_5_1 }; }
261 finally {
262 try {
263 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
264 }
265 finally { if (e_5) throw e_5.error; }
266 }
267 }
268 }
269 exports.findOutputBinding = findOutputBinding;
270 /**
271 * Returns an absolute path from the text in `node`. If the text is already
272 * an absolute path, return it as is, otherwise join the path with the filename
273 * of the source file.
274 */
275 function extractAbsoluteFilePath(node) {
276 var url = node.text;
277 return path.isAbsolute(url) ? url : path.join(path.dirname(node.getSourceFile().fileName), url);
278 }
279 exports.extractAbsoluteFilePath = extractAbsoluteFilePath;
280});
281//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9sYW5ndWFnZS1zZXJ2aWNlL3NyYy91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7Ozs7O0lBRUgsOENBQTZVO0lBQzdVLDJCQUE2QjtJQVU3QixTQUFTLGlCQUFpQixDQUFDLEtBQVU7UUFDbkMsT0FBTyxLQUFLLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDaEMsQ0FBQztJQUtELFNBQWdCLE1BQU0sQ0FBQyxJQUFpQztRQUN0RCxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQzVCLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDM0IsT0FBTyxFQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUMsQ0FBQztTQUN6RDthQUFNO1lBQ0wsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUN0QixPQUFPLEVBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFDLENBQUM7YUFDbEY7aUJBQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFO2dCQUNoRCxPQUFPO29CQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNO29CQUNuQyxHQUFHLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUUsQ0FBQyxHQUFHO2lCQUMxRCxDQUFDO2FB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UmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtBc3RQYXRoLCBCb3VuZEV2ZW50QXN0LCBDb21waWxlRGlyZWN0aXZlU3VtbWFyeSwgQ29tcGlsZVR5cGVNZXRhZGF0YSwgQ3NzU2VsZWN0b3IsIERpcmVjdGl2ZUFzdCwgRWxlbWVudEFzdCwgRW1iZWRkZWRUZW1wbGF0ZUFzdCwgSHRtbEFzdFBhdGgsIGlkZW50aWZpZXJOYW1lLCBJZGVudGlmaWVycywgTm9kZSwgUGFyc2VTb3VyY2VTcGFuLCBSZWN1cnNpdmVUZW1wbGF0ZUFzdFZpc2l0b3IsIFJlY3Vyc2l2ZVZpc2l0b3IsIFRlbXBsYXRlQXN0LCBUZW1wbGF0ZUFzdFBhdGgsIHRlbXBsYXRlVmlzaXRBbGwsIHZpc2l0QWxsfSBmcm9tICdAYW5ndWxhci9jb21waWxlcic7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0FzdFJlc3VsdCwgRGlhZ25vc3RpY1RlbXBsYXRlSW5mbywgU2VsZWN0b3JJbmZvLCBTcGFuLCBTeW1ib2wsIFN5bWJvbFF1ZXJ5fSBmcm9tICcuL3R5cGVzJztcblxuaW50ZXJmYWNlIFNwYW5Ib2xkZXIge1xuICBzb3VyY2VTcGFuOiBQYXJzZVNvdXJjZVNwYW47XG4gIGVuZFNvdXJjZVNwYW4/OiBQYXJzZVNvdXJjZVNwYW58bnVsbDtcbiAgY2hpbGRyZW4/OiBTcGFuSG9sZGVyW107XG59XG5cbmZ1bmN0aW9uIGlzUGFyc2VTb3VyY2VTcGFuKHZhbHVlOiBhbnkpOiB2YWx1ZSBpcyBQYXJzZVNvdXJjZVNwYW4ge1xuICByZXR1cm4gdmFsdWUgJiYgISF2YWx1ZS5zdGFydDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNwYW5PZihzcGFuOiBTcGFuSG9sZGVyKTogU3BhbjtcbmV4cG9ydCBmdW5jdGlvbiBzcGFuT2Yoc3BhbjogUGFyc2VTb3VyY2VTcGFuKTogU3BhbjtcbmV4cG9ydCBmdW5jdGlvbiBzcGFuT2Yoc3BhbjogU3BhbkhvbGRlcnxQYXJzZVNvdXJjZVNwYW58dW5kZWZpbmVkKTogU3Bhbnx1bmRlZmluZWQ7XG5leHBvcnQgZnVuY3Rpb24gc3Bhbk9mKHNwYW4/OiBTcGFuSG9sZGVyfFBhcnNlU291cmNlU3Bhbik6IFNwYW58dW5kZWZpbmVkIHtcbiAgaWYgKCFzcGFuKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoaXNQYXJzZVNvdXJjZVNwYW4oc3BhbikpIHtcbiAgICByZXR1cm4ge3N0YXJ0OiBzcGFuLnN0YXJ0Lm9mZnNldCwgZW5kOiBzcGFuLmVuZC5vZmZzZXR9O1xuICB9IGVsc2Uge1xuICAgIGlmIChzcGFuLmVuZFNvdXJjZVNwYW4pIHtcbiAgICAgIHJldHVybiB7c3RhcnQ6IHNwYW4uc291cmNlU3Bhbi5zdGFydC5vZmZzZXQsIGVuZDogc3Bhbi5lbmRTb3VyY2VTcGFuLmVuZC5vZmZzZXR9O1xuICAgIH0gZWxzZSBpZiAoc3Bhbi5jaGlsZHJlbiAmJiBzcGFuLmNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhcnQ6IHNwYW4uc291cmNlU3Bhbi5zdGFydC5vZmZzZXQsXG4gICAgICAgIGVuZDogc3Bhbk9mKHNwYW4uY2hpbGRyZW5bc3Bhbi5jaGlsZHJlbi5sZW5ndGggLSAxXSkhLmVuZFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtzdGFydDogc3Bhbi5zb3VyY2VTcGFuLnN0YXJ0Lm9mZnNldCwgZW5kOiBzcGFuLnNvdXJjZVNwYW4uZW5kLm9mZnNldH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluU3Bhbihwb3NpdGlvbjogbnVtYmVyLCBzcGFuPzogU3BhbiwgZXhjbHVzaXZlPzogYm9vbGVhbik6IGJvb2xlYW4ge1xuICByZXR1cm4gc3BhbiAhPSBudWxsICYmXG4gICAgICAoZXhjbHVzaXZlID8gcG9zaXRpb24gPj0gc3Bhbi5zdGFydCAmJiBwb3NpdGlvbiA8IHNwYW4uZW5kIDpcbiAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA+PSBzcGFuLnN0YXJ0ICYmIHBvc2l0aW9uIDw9IHNwYW4uZW5kKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9mZnNldFNwYW4oc3BhbjogU3BhbiwgYW1vdW50OiBudW1iZXIpOiBTcGFuIHtcbiAgcmV0dXJuIHtzdGFydDogc3Bhbi5zdGFydCArIGFtb3VudCwgZW5kOiBzcGFuLmVuZCArIGFtb3VudH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc05hcnJvd2VyKHNwYW5BOiBTcGFuLCBzcGFuQjogU3Bhbik6IGJvb2xlYW4ge1xuICByZXR1cm4gc3BhbkEuc3RhcnQgPj0gc3BhbkIuc3RhcnQgJiYgc3BhbkEuZW5kIDw9IHNwYW5CLmVuZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU3RydWN0dXJhbERpcmVjdGl2ZSh0eXBlOiBDb21waWxlVHlwZU1ldGFkYXRhKTogYm9vbGVhbiB7XG4gIGZvciAoY29uc3QgZGlEZXAgb2YgdHlwZS5kaURlcHMpIHtcbiAgICBjb25zdCBkaURlcE5hbWUgPSBpZGVudGlmaWVyTmFtZShkaURlcC50b2tlbj8uaWRlbnRpZmllcik7XG4gICAgaWYgKGRpRGVwTmFtZSA9PT0gSWRlbnRpZmllcnMuVGVtcGxhdGVSZWYubmFtZSB8fFxuICAgICAgICBkaURlcE5hbWUgPT09IElkZW50aWZpZXJzLlZpZXdDb250YWluZXJSZWYubmFtZSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNlbGVjdG9ycyhpbmZvOiBBc3RSZXN1bHQpOiBTZWxlY3RvckluZm8ge1xuICBjb25zdCBtYXAgPSBuZXcgTWFwPENzc1NlbGVjdG9yLCBDb21waWxlRGlyZWN0aXZlU3VtbWFyeT4oKTtcbiAgY29uc3QgcmVzdWx0czogQ3NzU2VsZWN0b3JbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGRpcmVjdGl2ZSBvZiBpbmZvLmRpcmVjdGl2ZXMpIHtcbiAgICBjb25zdCBzZWxlY3RvcnM6IENzc1NlbGVjdG9yW10gPSBDc3NTZWxlY3Rvci5wYXJzZShkaXJlY3RpdmUuc2VsZWN0b3IhKTtcbiAgICBmb3IgKGNvbnN0IHNlbGVjdG9yIG9mIHNlbGVjdG9ycykge1xuICAgICAgcmVzdWx0cy5wdXNoKHNlbGVjdG9yKTtcbiAgICAgIG1hcC5zZXQoc2VsZWN0b3IsIGRpcmVjdGl2ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB7c2VsZWN0b3JzOiByZXN1bHRzLCBtYXB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGlhZ25vc3RpY0luZm9Gcm9tVGVtcGxhdGVJbmZvKGluZm86IEFzdFJlc3VsdCk6IERpYWdub3N0aWNUZW1wbGF0ZUluZm8ge1xuICByZXR1cm4ge1xuICAgIGZpbGVOYW1lOiBpbmZvLnRlbXBsYXRlLmZpbGVOYW1lLFxuICAgIG9mZnNldDogaW5mby50ZW1wbGF0ZS5zcGFuLnN0YXJ0LFxuICAgIHF1ZXJ5OiBpbmZvLnRlbXBsYXRlLnF1ZXJ5LFxuICAgIG1lbWJlcnM6IGluZm8udGVtcGxhdGUubWVtYmVycyxcbiAgICBodG1sQXN0OiBpbmZvLmh0bWxBc3QsXG4gICAgdGVtcGxhdGVBc3Q6IGluZm8udGVtcGxhdGVBc3QsXG4gICAgc291cmNlOiBpbmZvLnRlbXBsYXRlLnNvdXJjZSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRUZW1wbGF0ZUFzdEF0KGFzdDogVGVtcGxhdGVBc3RbXSwgcG9zaXRpb246IG51bWJlcik6IFRlbXBsYXRlQXN0UGF0aCB7XG4gIGNvbnN0IHBhdGg6IFRlbXBsYXRlQXN0W10gPSBbXTtcbiAgY29uc3QgdmlzaXRvciA9IG5ldyBjbGFzcyBleHRlbmRzIFJlY3Vyc2l2ZVRlbXBsYXRlQXN0VmlzaXRvciB7XG4gICAgdmlzaXQoYXN0OiBUZW1wbGF0ZUFzdCk6IGFueSB7XG4gICAgICBsZXQgc3BhbiA9IHNwYW5PZihhc3QpO1xuICAgICAgaWYgKGluU3Bhbihwb3NpdGlvbiwgc3BhbikpIHtcbiAgICAgICAgY29uc3QgbGVuID0gcGF0aC5sZW5ndGg7XG4gICAgICAgIGlmICghbGVuIHx8IGlzTmFycm93ZXIoc3Bhbiwgc3Bhbk9mKHBhdGhbbGVuIC0gMV0pKSkge1xuICAgICAgICAgIHBhdGgucHVzaChhc3QpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBSZXR1cm5pbmcgYSB2YWx1ZSBoZXJlIHdpbGwgcmVzdWx0IGluIHRoZSBjaGlsZHJlbiBiZWluZyBza2lwcGVkLlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2aXNpdEVtYmVkZGVkVGVtcGxhdGUoYXN0OiBFbWJlZGRlZFRlbXBsYXRlQXN0LCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMudmlzaXRDaGlsZHJlbihjb250ZXh0LCB2aXNpdCA9PiB7XG4gICAgICAgIC8vIElnbm9yZSByZWZlcmVuY2UsIHZhcmlhYmxlIGFuZCBwcm92aWRlcnNcbiAgICAgICAgdmlzaXQoYXN0LmF0dHJzKTtcbiAgICAgICAgdmlzaXQoYXN0LmRpcmVjdGl2ZXMpO1xuICAgICAgICB2aXNpdChhc3QuY2hpbGRyZW4pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmlzaXRFbGVtZW50KGFzdDogRWxlbWVudEFzdCwgY29udGV4dDogYW55KTogYW55IHtcbiAgICAgIHJldHVybiB0aGlzLnZpc2l0Q2hpbGRyZW4oY29udGV4dCwgdmlzaXQgPT4ge1xuICAgICAgICAvLyBJbmdub3JlIHByb3ZpZGVyc1xuICAgICAgICB2aXNpdChhc3QuYXR0cnMpO1xuICAgICAgICB2aXNpdChhc3QuaW5wdXRzKTtcbiAgICAgICAgdmlzaXQoYXN0Lm91dHB1dHMpO1xuICAgICAgICB2aXNpdChhc3QucmVmZXJlbmNlcyk7XG4gICAgICAgIHZpc2l0KGFzdC5kaXJlY3RpdmVzKTtcbiAgICAgICAgdmlzaXQoYXN0LmNoaWxkcmVuKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZpc2l0RGlyZWN0aXZlKGFzdDogRGlyZWN0aXZlQXN0LCBjb250ZXh0OiBhbnkpOiBhbnkge1xuICAgICAgLy8gSWdub3JlIHRoZSBob3N0IHByb3BlcnRpZXMgb2YgYSBkaXJlY3RpdmVcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMudmlzaXRDaGlsZHJlbihjb250ZXh0LCB2aXNpdCA9PiB7XG4gICAgICAgIHZpc2l0KGFzdC5pbnB1dHMpO1xuICAgICAgfSk7XG4gICAgICAvLyBXZSBuZXZlciBjYXJlIGFib3V0IHRoZSBkaXJldGl2ZSBpdHNlbGYsIGp1c3QgaXRzIGlucHV0cy5cbiAgICAgIGlmIChwYXRoW3BhdGgubGVuZ3RoIC0gMV0gPT09IGFzdCkge1xuICAgICAgICBwYXRoLnBvcCgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH07XG5cbiAgdGVtcGxhdGVWaXNpdEFsbCh2aXNpdG9yLCBhc3QpO1xuXG4gIHJldHVybiBuZXcgQXN0UGF0aDxUZW1wbGF0ZUFzdD4ocGF0aCwgcG9zaXRpb24pO1xufVxuXG4vKipcbiAqIEZpbmQgdGhlIHRpZ2h0ZXN0IG5vZGUgYXQgdGhlIHNwZWNpZmllZCBgcG9zaXRpb25gIGZyb20gdGhlIEFTVCBgbm9kZXNgLCBhbmRcbiAqIHJldHVybiB0aGUgcGF0aCB0byB0aGUgbm9kZS5cbiAqIEBwYXJhbSBub2RlcyBIVE1MIEFTVCBub2Rlc1xuICogQHBhcmFtIHBvc2l0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXRoVG9Ob2RlQXRQb3NpdGlvbihub2RlczogTm9kZVtdLCBwb3NpdGlvbjogbnVtYmVyKTogSHRtbEFzdFBhdGgge1xuICBjb25zdCBwYXRoOiBOb2RlW10gPSBbXTtcbiAgY29uc3QgdmlzaXRvciA9IG5ldyBjbGFzcyBleHRlbmRzIFJlY3Vyc2l2ZVZpc2l0b3Ige1xuICAgIHZpc2l0KGFzdDogTm9kZSkge1xuICAgICAgY29uc3Qgc3BhbiA9IHNwYW5PZihhc3QpO1xuICAgICAgaWYgKGluU3Bhbihwb3NpdGlvbiwgc3BhbikpIHtcbiAgICAgICAgcGF0aC5wdXNoKGFzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBSZXR1cm5pbmcgYSB0cnV0aHkgdmFsdWUgaGVyZSB3aWxsIHNraXAgYWxsIGNoaWxkcmVuIGFuZCB0ZXJtaW5hdGVcbiAgICAgICAgLy8gdGhlIHZpc2l0LlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHZpc2l0QWxsKHZpc2l0b3IsIG5vZGVzKTtcbiAgcmV0dXJuIG5ldyBBc3RQYXRoPE5vZGU+KHBhdGgsIHBvc2l0aW9uKTtcbn1cblxuXG4vKipcbiAqIEludmVydHMgYW4gb2JqZWN0J3Mga2V5LXZhbHVlIHBhaXJzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW52ZXJ0TWFwKG9iajoge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9KToge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9IHtcbiAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30gPSB7fTtcbiAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5rZXlzKG9iaikpIHtcbiAgICBjb25zdCB2ID0gb2JqW25hbWVdO1xuICAgIHJlc3VsdFt2XSA9IG5hbWU7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuXG4vKipcbiAqIEZpbmRzIHRoZSBkaXJlY3RpdmUgbWVtYmVyIHByb3ZpZGluZyBhIHRlbXBsYXRlIG91dHB1dCBiaW5kaW5nLCBpZiBvbmUgZXhpc3RzLlxuICogQHBhcmFtIGluZm8gYWdncmVnYXRlIHRlbXBsYXRlIEFTVCBpbmZvcm1hdGlvblxuICogQHBhcmFtIHBhdGggbmFycm93aW5nXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kT3V0cHV0QmluZGluZyhcbiAgICBiaW5kaW5nOiBCb3VuZEV2ZW50QXN0LCBwYXRoOiBUZW1wbGF0ZUFzdFBhdGgsIHF1ZXJ5OiBTeW1ib2xRdWVyeSk6IFN5bWJvbHx1bmRlZmluZWQge1xuICBjb25zdCBlbGVtZW50ID0gcGF0aC5maXJzdChFbGVtZW50QXN0KTtcbiAgaWYgKGVsZW1lbnQpIHtcbiAgICBmb3IgKGNvbnN0IGRpcmVjdGl2ZSBvZiBlbGVtZW50LmRpcmVjdGl2ZXMpIHtcbiAgICAgIGNvbnN0IGludmVydGVkT3V0cHV0cyA9IGludmVydE1hcChkaXJlY3RpdmUuZGlyZWN0aXZlLm91dHB1dHMpO1xuICAgICAgY29uc3QgZmllbGROYW1lID0gaW52ZXJ0ZWRPdXRwdXRzW2JpbmRpbmcubmFtZV07XG4gICAgICBpZiAoZmllbGROYW1lKSB7XG4gICAgICAgIGNvbnN0IGNsYXNzU3ltYm9sID0gcXVlcnkuZ2V0VHlwZVN5bWJvbChkaXJlY3RpdmUuZGlyZWN0aXZlLnR5cGUucmVmZXJlbmNlKTtcbiAgICAgICAgaWYgKGNsYXNzU3ltYm9sKSB7XG4gICAgICAgICAgcmV0dXJuIGNsYXNzU3ltYm9sLm1lbWJlcnMoKS5nZXQoZmllbGROYW1lKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgYW4gYWJzb2x1dGUgcGF0aCBmcm9tIHRoZSB0ZXh0IGluIGBub2RlYC4gSWYgdGhlIHRleHQgaXMgYWxyZWFkeVxuICogYW4gYWJzb2x1dGUgcGF0aCwgcmV0dXJuIGl0IGFzIGlzLCBvdGhlcndpc2Ugam9pbiB0aGUgcGF0aCB3aXRoIHRoZSBmaWxlbmFtZVxuICogb2YgdGhlIHNvdXJjZSBmaWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdEFic29sdXRlRmlsZVBhdGgobm9kZTogdHMuU3RyaW5nTGl0ZXJhbExpa2UpIHtcbiAgY29uc3QgdXJsID0gbm9kZS50ZXh0O1xuICByZXR1cm4gcGF0aC5pc0Fic29sdXRlKHVybCkgPyB1cmwgOiBwYXRoLmpvaW4ocGF0aC5kaXJuYW1lKG5vZGUuZ2V0U291cmNlRmlsZSgpLmZpbGVOYW1lKSwgdXJsKTtcbn1cbiJdfQ==
\No newline at end of file