UNPKG

4.93 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
5 * This code may only be used under the BSD style license found at
6 * http://polymer.github.io/LICENSE.txt
7 * The complete set of authors may be found at
8 * http://polymer.github.io/AUTHORS.txt
9 * The complete set of contributors may be found at
10 * http://polymer.github.io/CONTRIBUTORS.txt
11 * Code distributed by Google as part of the polymer project is also
12 * subject to an additional IP rights grant found at
13 * http://polymer.github.io/PATENTS.txt
14 */
15var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16 return new (P || (P = Promise))(function (resolve, reject) {
17 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
20 step((generator = generator.apply(thisArg, _arguments || [])).next());
21 });
22};
23Object.defineProperty(exports, "__esModule", { value: true });
24function scan(document, scanners) {
25 return __awaiter(this, void 0, void 0, function* () {
26 // Scanners register a visitor to run via the `visit` callback passed to
27 // `scan()`. We run these visitors in a batch, then pass control back
28 // to the `scan()` methods by resolving a single Promise return for
29 // all calls to visit() in a batch when the visitors have run.
30 // Then we repeat if any visitors have registered new visitors.
31 // Resolves Promises returned by visit() calls
32 let batchDone;
33 // Promise returned by visit()
34 let visitorsPromise;
35 // Current batch of visitors
36 let visitors;
37 // results
38 const nestedFeatures = [];
39 const warnings = [];
40 // A Promise that runs the next batch of visitors in a microtask
41 let runner = null;
42 let visitError;
43 let visitErrorFound = false;
44 // Initializes the current batch running state
45 function setup() {
46 visitorsPromise = new Promise((resolve, _) => {
47 batchDone = resolve;
48 });
49 visitors = [];
50 runner = null;
51 }
52 // Runs the current batch of visitors
53 function runVisitors() {
54 // Record the current state so that any new visitors are enqueued into
55 // a fresh batch.
56 const currentVisitors = visitors;
57 const currentDoneCallback = batchDone;
58 setup();
59 try {
60 document.visit(currentVisitors);
61 }
62 finally {
63 // Let `scan` continue after calls to visit().then()
64 currentDoneCallback();
65 }
66 }
67 // The callback passed to `scan()`
68 function visit(visitor) {
69 visitors.push(visitor);
70 if (!runner) {
71 runner = Promise.resolve().then(runVisitors).catch((error) => {
72 visitErrorFound = true;
73 visitError = visitError || error;
74 });
75 }
76 return visitorsPromise;
77 }
78 // Ok, go!
79 setup();
80 const scannerPromises = scanners.map((f) => f.scan(document, visit));
81 // This waits for all `scan()` calls to finish
82 const nestedResults = yield Promise.all(scannerPromises);
83 if (visitErrorFound || !nestedResults) {
84 throw visitError;
85 }
86 for (const { features, warnings: w } of nestedResults) {
87 nestedFeatures.push(features);
88 if (w !== undefined) {
89 warnings.push(...w);
90 }
91 }
92 return { features: sortFeatures(nestedFeatures), warnings };
93 });
94}
95exports.scan = scan;
96function compareFeaturesBySourceLocation(ent1, ent2) {
97 const range1 = ent1.sourceRange;
98 const range2 = ent2.sourceRange;
99 if (range1 === range2) {
100 // Should only be true in the `both null` case
101 return 0;
102 }
103 if (range2 == null) {
104 // ent1 comes first
105 return -1;
106 }
107 if (range1 == null) {
108 // ent1 comes second
109 return 1;
110 }
111 const position1 = range1.start;
112 const position2 = range2.start;
113 if (position1.line < position2.line) {
114 return -1;
115 }
116 if (position1.line > position2.line) {
117 return 1;
118 }
119 // Lines are equal, compare by column.
120 return position1.column - position2.column;
121}
122function sortFeatures(unorderedFeatures) {
123 const allFeatures = [];
124 for (const subArray of unorderedFeatures) {
125 allFeatures.push(...subArray);
126 }
127 return allFeatures.sort(compareFeaturesBySourceLocation);
128}
129//# sourceMappingURL=scan.js.map
\No newline at end of file