UNPKG

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