astronomical 2.0.1 → 3.0.0
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/lib/{cjs/types/index.d.ts → index.d.mts} +16 -15
- package/lib/{esm/types/index.d.ts → index.d.ts} +16 -15
- package/lib/index.js +1355 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +1325 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +11 -13
- package/lib/cjs/index.js +0 -738
- package/lib/cjs/nodeutils.js +0 -260
- package/lib/cjs/parseQuery.js +0 -296
- package/lib/cjs/types/index.d.ts.map +0 -1
- package/lib/cjs/types/nodeutils.d.ts +0 -21
- package/lib/cjs/types/nodeutils.d.ts.map +0 -1
- package/lib/cjs/types/parseQuery.d.ts +0 -42
- package/lib/cjs/types/parseQuery.d.ts.map +0 -1
- package/lib/cjs/types/utils.d.ts +0 -3
- package/lib/cjs/types/utils.d.ts.map +0 -1
- package/lib/cjs/utils.js +0 -10
- package/lib/esm/index.mjs +0 -738
- package/lib/esm/nodeutils.js +0 -260
- package/lib/esm/parseQuery.js +0 -296
- package/lib/esm/types/index.d.ts.map +0 -1
- package/lib/esm/types/nodeutils.d.ts +0 -21
- package/lib/esm/types/nodeutils.d.ts.map +0 -1
- package/lib/esm/types/parseQuery.d.ts +0 -42
- package/lib/esm/types/parseQuery.d.ts.map +0 -1
- package/lib/esm/types/utils.d.ts +0 -3
- package/lib/esm/types/utils.d.ts.map +0 -1
- package/lib/esm/utils.js +0 -10
package/lib/cjs/index.js
DELETED
|
@@ -1,738 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.functions = void 0;
|
|
4
|
-
exports.isAvailableFunction = isAvailableFunction;
|
|
5
|
-
exports.query = query;
|
|
6
|
-
exports.multiQuery = multiQuery;
|
|
7
|
-
exports.parseSource = parseSource;
|
|
8
|
-
exports.default = createTraverser;
|
|
9
|
-
const parseQuery_1 = require("./parseQuery");
|
|
10
|
-
const meriyah_1 = require("meriyah");
|
|
11
|
-
const nodeutils_1 = require("./nodeutils");
|
|
12
|
-
const utils_1 = require("./utils");
|
|
13
|
-
const debugLogEnabled = false;
|
|
14
|
-
const log = debugLogEnabled ? {
|
|
15
|
-
debug: (...args) => {
|
|
16
|
-
console.debug(...args);
|
|
17
|
-
}
|
|
18
|
-
} : undefined;
|
|
19
|
-
exports.functions = {
|
|
20
|
-
"join": {
|
|
21
|
-
fn: (result) => {
|
|
22
|
-
if (result.length != 2)
|
|
23
|
-
throw new Error("Invalid number of arugments for join");
|
|
24
|
-
const [values, separators] = result;
|
|
25
|
-
if (separators.length != 1)
|
|
26
|
-
throw new Error("Invalid number of separators for join");
|
|
27
|
-
const separator = separators[0];
|
|
28
|
-
if (typeof separator != "string")
|
|
29
|
-
throw new Error("Separator must be a string");
|
|
30
|
-
if (values.length == 0)
|
|
31
|
-
return [];
|
|
32
|
-
return [values.join(separator)];
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
"concat": {
|
|
36
|
-
fn: (result) => {
|
|
37
|
-
if (result.some(x => x.length == 0))
|
|
38
|
-
return [];
|
|
39
|
-
return [result.flat().join("")];
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
"first": {
|
|
43
|
-
fn: (result) => {
|
|
44
|
-
if (result.length != 1)
|
|
45
|
-
throw new Error("Invalid number of arugments for first");
|
|
46
|
-
if (result[0].length == 0)
|
|
47
|
-
return [];
|
|
48
|
-
return [result.map(r => r[0])[0]];
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
"nthchild": {
|
|
52
|
-
fn: (result) => {
|
|
53
|
-
if (result.length != 2)
|
|
54
|
-
throw new Error("Invalid number of arguments for nthchild");
|
|
55
|
-
if (result[1].length != 1)
|
|
56
|
-
throw new Error("Invalid number of arguments for nthchild");
|
|
57
|
-
const x = result[1][0];
|
|
58
|
-
const number = typeof x == "number" ? x : parseInt(x);
|
|
59
|
-
return [result[0][number]];
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const functionNames = new Set(Object.keys(exports.functions));
|
|
64
|
-
function isAvailableFunction(name) {
|
|
65
|
-
return functionNames.has(name);
|
|
66
|
-
}
|
|
67
|
-
function breadCrumb(path) {
|
|
68
|
-
if (!debugLogEnabled)
|
|
69
|
-
return "";
|
|
70
|
-
return {
|
|
71
|
-
valueOf() {
|
|
72
|
-
if (path.parentPath == undefined)
|
|
73
|
-
return "@" + path.node.type;
|
|
74
|
-
return breadCrumb(path.parentPath) + "." + (path.parentKey == path.key ? path.key : path.parentKey + "[" + path.key + "]") + "@" + path.node.type;
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function createQuerier() {
|
|
79
|
-
const traverser = createTraverser();
|
|
80
|
-
const { getChildren, getPrimitiveChildren, getPrimitiveChildrenOrNodePaths, getBinding, createNodePath, traverse } = traverser;
|
|
81
|
-
function createFilter(filter, filterResult) {
|
|
82
|
-
if (filter.type == "and" || filter.type == "or" || filter.type == "equals") {
|
|
83
|
-
return {
|
|
84
|
-
type: filter.type,
|
|
85
|
-
left: createFilter(filter.left, []),
|
|
86
|
-
right: createFilter(filter.right, [])
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
else if (filter.type == "literal") {
|
|
90
|
-
const r = [filter.value];
|
|
91
|
-
return {
|
|
92
|
-
node: filter,
|
|
93
|
-
result: r
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return createFNode(filter, filterResult);
|
|
97
|
-
}
|
|
98
|
-
function createFNode(token, result) {
|
|
99
|
-
return {
|
|
100
|
-
node: token,
|
|
101
|
-
result: result
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function addFilterChildrenToState(filter, state) {
|
|
105
|
-
if ("type" in filter && (filter.type == "and" || filter.type == "or" || filter.type == "equals")) {
|
|
106
|
-
addFilterChildrenToState(filter.left, state);
|
|
107
|
-
addFilterChildrenToState(filter.right, state);
|
|
108
|
-
}
|
|
109
|
-
else if ("node" in filter) {
|
|
110
|
-
if (filter.node.type == "child") {
|
|
111
|
-
log?.debug("ADDING FILTER CHILD", filter.node);
|
|
112
|
-
state.child[state.depth + 1].push(filter);
|
|
113
|
-
}
|
|
114
|
-
if (filter.node.type == "descendant") {
|
|
115
|
-
log?.debug("ADDING FILTER DESCENDANT", filter.node);
|
|
116
|
-
state.descendant[state.depth + 1].push(filter);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function createFNodeAndAddToState(token, result, state) {
|
|
121
|
-
log?.debug("ADDING FNODE", token);
|
|
122
|
-
const fnode = createFNode(token, result);
|
|
123
|
-
if (token.type == "child") {
|
|
124
|
-
state.child[state.depth + 1].push(fnode);
|
|
125
|
-
}
|
|
126
|
-
else if (token.type == "descendant") {
|
|
127
|
-
state.descendant[state.depth + 1].push(fnode);
|
|
128
|
-
}
|
|
129
|
-
return fnode;
|
|
130
|
-
}
|
|
131
|
-
function isMatch(fnode, path) {
|
|
132
|
-
if (fnode.node.attribute) {
|
|
133
|
-
const m = fnode.node.value == path.parentKey || fnode.node.value == path.key;
|
|
134
|
-
if (m)
|
|
135
|
-
log?.debug("ATTR MATCH", fnode.node.value, breadCrumb(path));
|
|
136
|
-
return m;
|
|
137
|
-
}
|
|
138
|
-
if (fnode.node.value == "*") {
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
const m = fnode.node.value == path.node.type;
|
|
142
|
-
if (m)
|
|
143
|
-
log?.debug("NODE MATCH", fnode.node.value, breadCrumb(path));
|
|
144
|
-
return m;
|
|
145
|
-
}
|
|
146
|
-
function addIfTokenMatch(fnode, path, state) {
|
|
147
|
-
if (!isMatch(fnode, path))
|
|
148
|
-
return;
|
|
149
|
-
state.matches[state.depth].push([fnode, path]);
|
|
150
|
-
if (fnode.node.filter) {
|
|
151
|
-
const filter = createFilter(fnode.node.filter, []);
|
|
152
|
-
const filteredResult = [];
|
|
153
|
-
const f = { filter: filter, qNode: fnode.node, node: path.node, result: filteredResult };
|
|
154
|
-
state.filters[state.depth].push(f);
|
|
155
|
-
let fmap = state.filtersMap[state.depth].get(fnode.node);
|
|
156
|
-
if (!fmap) {
|
|
157
|
-
fmap = [];
|
|
158
|
-
state.filtersMap[state.depth].set(fnode.node, fmap);
|
|
159
|
-
}
|
|
160
|
-
fmap.push(f);
|
|
161
|
-
addFilterChildrenToState(filter, state);
|
|
162
|
-
const child = fnode.node.child;
|
|
163
|
-
if (child) {
|
|
164
|
-
if (child.type == "function") {
|
|
165
|
-
const fr = addFunction(fnode, child, path, state);
|
|
166
|
-
state.functionCalls[state.depth].push(fr);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
createFNodeAndAddToState(child, filteredResult, state);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
const child = fnode.node.child;
|
|
175
|
-
if (child?.type == "function") {
|
|
176
|
-
const fr = addFunction(fnode, child, path, state);
|
|
177
|
-
state.functionCalls[state.depth].push(fr);
|
|
178
|
-
}
|
|
179
|
-
else if (child && !fnode.node.binding && !fnode.node.resolve) {
|
|
180
|
-
createFNodeAndAddToState(child, fnode.result, state);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function addFunction(rootNode, functionCall, path, state) {
|
|
185
|
-
const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
|
|
186
|
-
for (const param of functionCall.parameters) {
|
|
187
|
-
if (param.type == "literal") {
|
|
188
|
-
functionNode.parameters.push({ node: param, result: [param.value] });
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
if (param.type == "function") {
|
|
192
|
-
functionNode.parameters.push(addFunction(functionNode, param, path, state));
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
functionNode.parameters.push(createFNodeAndAddToState(param, [], state));
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
return functionNode;
|
|
200
|
-
}
|
|
201
|
-
function addPrimitiveAttributeIfMatch(fnode, path) {
|
|
202
|
-
if (!fnode.node.attribute || fnode.node.value == undefined)
|
|
203
|
-
return;
|
|
204
|
-
if (fnode.node.child || fnode.node.filter)
|
|
205
|
-
return;
|
|
206
|
-
if (!Object.hasOwn(path.node, fnode.node.value))
|
|
207
|
-
return;
|
|
208
|
-
const nodes = getPrimitiveChildren(fnode.node.value, path);
|
|
209
|
-
if (nodes.length == 0)
|
|
210
|
-
return;
|
|
211
|
-
log?.debug("PRIMITIVE", fnode.node.value, nodes);
|
|
212
|
-
fnode.result.push(...nodes);
|
|
213
|
-
}
|
|
214
|
-
function evaluateFilter(filter, path) {
|
|
215
|
-
log?.debug("EVALUATING FILTER", filter, breadCrumb(path));
|
|
216
|
-
if ("type" in filter) {
|
|
217
|
-
if (filter.type == "and") {
|
|
218
|
-
const left = evaluateFilter(filter.left, path);
|
|
219
|
-
if (left.length == 0) {
|
|
220
|
-
return [];
|
|
221
|
-
}
|
|
222
|
-
const r = evaluateFilter(filter.right, path);
|
|
223
|
-
return r;
|
|
224
|
-
}
|
|
225
|
-
if (filter.type == "or") {
|
|
226
|
-
const left = evaluateFilter(filter.left, path);
|
|
227
|
-
if (left.length > 0) {
|
|
228
|
-
return left;
|
|
229
|
-
}
|
|
230
|
-
const r = evaluateFilter(filter.right, path);
|
|
231
|
-
return r;
|
|
232
|
-
}
|
|
233
|
-
if (filter.type == "equals") {
|
|
234
|
-
const left = evaluateFilter(filter.left, path);
|
|
235
|
-
const right = evaluateFilter(filter.right, path);
|
|
236
|
-
const r = left.filter(x => right.includes(x));
|
|
237
|
-
return r;
|
|
238
|
-
}
|
|
239
|
-
throw new Error("Unknown filter type: " + filter.type);
|
|
240
|
-
}
|
|
241
|
-
if (filter.node.type == "parent") {
|
|
242
|
-
const r = resolveFilterWithParent(filter.node, path);
|
|
243
|
-
return r;
|
|
244
|
-
}
|
|
245
|
-
return filter.result;
|
|
246
|
-
}
|
|
247
|
-
function resolveBinding(path) {
|
|
248
|
-
if (!(0, nodeutils_1.isIdentifier)(path.node))
|
|
249
|
-
return undefined;
|
|
250
|
-
log?.debug("RESOLVING BINDING FOR ", path.node);
|
|
251
|
-
const name = path.node.name;
|
|
252
|
-
if (name == undefined || typeof name != "string")
|
|
253
|
-
return undefined;
|
|
254
|
-
//const binding = path.scope.getBinding(name);
|
|
255
|
-
const binding = getBinding(path.scopeId, name);
|
|
256
|
-
if (!binding)
|
|
257
|
-
return undefined;
|
|
258
|
-
log?.debug("THIS IS THE BINDING", binding);
|
|
259
|
-
return binding.path;
|
|
260
|
-
}
|
|
261
|
-
function resolveFilterWithParent(node, path) {
|
|
262
|
-
let startNode = node;
|
|
263
|
-
let startPath = path;
|
|
264
|
-
while (startNode.type == "parent") {
|
|
265
|
-
if (!startNode.child)
|
|
266
|
-
throw new Error("Parent filter must have child");
|
|
267
|
-
if (!startPath.parentPath)
|
|
268
|
-
return [];
|
|
269
|
-
log?.debug("STEP OUT", startNode, breadCrumb(startPath));
|
|
270
|
-
startNode = startNode.child;
|
|
271
|
-
startPath = startPath.parentPath;
|
|
272
|
-
}
|
|
273
|
-
return resolveDirectly(startNode, startPath);
|
|
274
|
-
}
|
|
275
|
-
function isDefined(value) {
|
|
276
|
-
return value != undefined && value != null;
|
|
277
|
-
}
|
|
278
|
-
let subQueryCounter = 0;
|
|
279
|
-
const memo = new Map();
|
|
280
|
-
function resolveDirectly(node, path) {
|
|
281
|
-
let startNode = node;
|
|
282
|
-
const startPath = path;
|
|
283
|
-
let paths = [startPath];
|
|
284
|
-
while (startNode.attribute && startNode.type == "child") {
|
|
285
|
-
const lookup = startNode.value;
|
|
286
|
-
if (!lookup)
|
|
287
|
-
throw new Error("Selector must have a value");
|
|
288
|
-
//log?.debug("STEP IN ", lookup, paths.map(p => breadCrumb(p)));
|
|
289
|
-
const nodes = paths.filter(nodeutils_1.isNodePath).map(n => getPrimitiveChildrenOrNodePaths(lookup, n)).flat();
|
|
290
|
-
//log?.debug("LOOKUP", lookup, path.node.type, nodes.map(n => n.node));
|
|
291
|
-
//console.log(nodes);
|
|
292
|
-
if (nodes.length == 0)
|
|
293
|
-
return [];
|
|
294
|
-
paths = nodes;
|
|
295
|
-
if (startNode.resolve) {
|
|
296
|
-
const resolved = paths.filter(nodeutils_1.isNodePath).map(p => resolveBinding(p)).filter(isDefined).map(p => getChildren("init", p)).flat();
|
|
297
|
-
if (resolved.length > 0)
|
|
298
|
-
paths = resolved;
|
|
299
|
-
}
|
|
300
|
-
else if (startNode.binding) {
|
|
301
|
-
paths = paths.filter(nodeutils_1.isNodePath).map(p => resolveBinding(p)).filter(isDefined);
|
|
302
|
-
}
|
|
303
|
-
const filter = startNode.filter;
|
|
304
|
-
if (filter) {
|
|
305
|
-
paths = paths.filter(nodeutils_1.isNodePath).filter(p => travHandle({ subquery: filter }, p).subquery.length > 0);
|
|
306
|
-
}
|
|
307
|
-
if (!startNode.child) {
|
|
308
|
-
return paths.map(p => (0, nodeutils_1.isPrimitive)(p) ? p : p.node);
|
|
309
|
-
}
|
|
310
|
-
startNode = startNode.child;
|
|
311
|
-
}
|
|
312
|
-
//log?.debug("DIRECT TRAV RESOLVE", startNode, paths.map(p => breadCrumb(p)));
|
|
313
|
-
const result = [];
|
|
314
|
-
//console.log(paths.length, subQueryCounter);
|
|
315
|
-
for (const path of paths) {
|
|
316
|
-
if ((0, nodeutils_1.isNodePath)(path)) {
|
|
317
|
-
if (memo.has(startNode) && memo.get(startNode).has(path)) {
|
|
318
|
-
result.push(...memo.get(startNode).get(path));
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
const subQueryKey = "subquery-" + subQueryCounter++;
|
|
322
|
-
const subQueryResult = travHandle({ [subQueryKey]: startNode }, path)[subQueryKey];
|
|
323
|
-
if (!memo.has(startNode))
|
|
324
|
-
memo.set(startNode, new Map());
|
|
325
|
-
memo.get(startNode)?.set(path, subQueryResult);
|
|
326
|
-
result.push(...subQueryResult);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
log?.debug("DIRECT TRAV RESOLVE RESULT", result);
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
333
|
-
function addResultIfTokenMatch(fnode, path, state) {
|
|
334
|
-
const matchingFilters = [];
|
|
335
|
-
//console.log("FILTERS", state.filters[state.depth].length, state.filtersMap[state.depth].get(fnode.node)?.length);
|
|
336
|
-
const filters = [];
|
|
337
|
-
const nodeFilters = state.filtersMap[state.depth].get(fnode.node);
|
|
338
|
-
if (nodeFilters) {
|
|
339
|
-
for (const f of nodeFilters) {
|
|
340
|
-
if (f.qNode !== fnode.node)
|
|
341
|
-
continue;
|
|
342
|
-
if (f.node !== path.node)
|
|
343
|
-
continue;
|
|
344
|
-
filters.push(f);
|
|
345
|
-
}
|
|
346
|
-
for (const f of filters) {
|
|
347
|
-
if (evaluateFilter(f.filter, path).length > 0) {
|
|
348
|
-
matchingFilters.push(f);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
if (filters.length > 0 && matchingFilters.length == 0)
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
if (fnode.node.resolve) {
|
|
355
|
-
const binding = resolveBinding(path);
|
|
356
|
-
const resolved = binding ? getChildren("init", binding)[0] : undefined;
|
|
357
|
-
if (fnode.node.child) {
|
|
358
|
-
const result = resolveDirectly(fnode.node.child, resolved ?? path);
|
|
359
|
-
fnode.result.push(...result);
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
fnode.result.push(path.node);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
else if (fnode.node.binding) {
|
|
366
|
-
const binding = resolveBinding(path);
|
|
367
|
-
if (binding) {
|
|
368
|
-
if (fnode.node.child) {
|
|
369
|
-
const result = resolveDirectly(fnode.node.child, binding);
|
|
370
|
-
fnode.result.push(...result);
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
fnode.result.push(binding.node);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
else if (!fnode.node.child) {
|
|
378
|
-
fnode.result.push(path.node);
|
|
379
|
-
}
|
|
380
|
-
else if (fnode.node.child.type == "function") {
|
|
381
|
-
const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
|
|
382
|
-
if (!functionCallResult)
|
|
383
|
-
throw new Error("Did not find expected function call for " + fnode.node.child.function);
|
|
384
|
-
resolveFunctionCalls(fnode, functionCallResult, path, state);
|
|
385
|
-
}
|
|
386
|
-
else if (matchingFilters.length > 0) {
|
|
387
|
-
log?.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
|
|
388
|
-
fnode.result.push(...matchingFilters.flatMap(f => f.result));
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
function resolveFunctionCalls(fnode, functionCallResult, path, state) {
|
|
392
|
-
const parameterResults = [];
|
|
393
|
-
for (const p of functionCallResult.parameters) {
|
|
394
|
-
if ("parameters" in p) {
|
|
395
|
-
resolveFunctionCalls(p, p, path, state);
|
|
396
|
-
parameterResults.push(p.result);
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
parameterResults.push(p.result);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
|
|
403
|
-
log?.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
|
|
404
|
-
fnode.result.push(...functionResult);
|
|
405
|
-
}
|
|
406
|
-
function travHandle(queries, root) {
|
|
407
|
-
const results = Object.fromEntries(Object.keys(queries).map(name => [name, []]));
|
|
408
|
-
const state = {
|
|
409
|
-
depth: 0,
|
|
410
|
-
child: [[], []],
|
|
411
|
-
descendant: [[], []],
|
|
412
|
-
filters: [[], []],
|
|
413
|
-
filtersMap: [new Map(), new Map()],
|
|
414
|
-
matches: [[]],
|
|
415
|
-
functionCalls: [[]]
|
|
416
|
-
};
|
|
417
|
-
for (const [name, node] of Object.entries(queries)) {
|
|
418
|
-
createFNodeAndAddToState(node, results[name], state);
|
|
419
|
-
}
|
|
420
|
-
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root));
|
|
421
|
-
state.descendant.slice(0, state.depth + 1).forEach(fnodes => fnodes.forEach(fnode => addPrimitiveAttributeIfMatch(fnode, root)));
|
|
422
|
-
traverse(root.node, {
|
|
423
|
-
enter(path, state) {
|
|
424
|
-
//log?.debug("ENTER", breadCrumb(path));
|
|
425
|
-
state.depth++;
|
|
426
|
-
state.child.push([]);
|
|
427
|
-
state.descendant.push([]);
|
|
428
|
-
state.filters.push([]);
|
|
429
|
-
state.filtersMap.push(new Map());
|
|
430
|
-
state.matches.push([]);
|
|
431
|
-
state.functionCalls.push([]);
|
|
432
|
-
for (const fnode of state.child[state.depth]) {
|
|
433
|
-
addIfTokenMatch(fnode, path, state);
|
|
434
|
-
}
|
|
435
|
-
for (const fnodes of state.descendant.slice(0, state.depth + 1)) {
|
|
436
|
-
for (const fnode of fnodes) {
|
|
437
|
-
addIfTokenMatch(fnode, path, state);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
},
|
|
441
|
-
exit(path, state) {
|
|
442
|
-
log?.debug("EXIT", breadCrumb(path));
|
|
443
|
-
// Check for attributes as not all attributes are visited
|
|
444
|
-
state.child[state.depth + 1].forEach(fnode => addPrimitiveAttributeIfMatch(fnode, path));
|
|
445
|
-
for (const fnodes of state.descendant) {
|
|
446
|
-
for (const fnode of fnodes) {
|
|
447
|
-
addPrimitiveAttributeIfMatch(fnode, path);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
for (const [fNode, path] of state.matches[state.depth]) {
|
|
451
|
-
addResultIfTokenMatch(fNode, path, state);
|
|
452
|
-
}
|
|
453
|
-
state.depth--;
|
|
454
|
-
state.child.pop();
|
|
455
|
-
state.descendant.pop();
|
|
456
|
-
state.filters.pop();
|
|
457
|
-
state.filtersMap.pop();
|
|
458
|
-
state.matches.pop();
|
|
459
|
-
state.functionCalls.pop();
|
|
460
|
-
}
|
|
461
|
-
}, root.scopeId, state, root);
|
|
462
|
-
return results;
|
|
463
|
-
}
|
|
464
|
-
function beginHandle(queries, path) {
|
|
465
|
-
const rootPath = createNodePath(path, undefined, undefined, undefined, undefined);
|
|
466
|
-
const r = travHandle(queries, rootPath);
|
|
467
|
-
memo.clear();
|
|
468
|
-
return r;
|
|
469
|
-
}
|
|
470
|
-
return {
|
|
471
|
-
beginHandle
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
const defaultKey = "__default__";
|
|
475
|
-
function query(code, query, returnAST) {
|
|
476
|
-
const result = multiQuery(code, { [defaultKey]: query }, returnAST);
|
|
477
|
-
if (returnAST) {
|
|
478
|
-
const r = result[defaultKey];
|
|
479
|
-
r.__AST = result.__AST;
|
|
480
|
-
return r;
|
|
481
|
-
}
|
|
482
|
-
return result[defaultKey];
|
|
483
|
-
}
|
|
484
|
-
function multiQuery(code, namedQueries, returnAST) {
|
|
485
|
-
const start = Date.now();
|
|
486
|
-
const ast = typeof code == "string" ? parseSource(code) : code;
|
|
487
|
-
if (ast == null)
|
|
488
|
-
throw new Error("Could not pase code");
|
|
489
|
-
const queries = Object.fromEntries(Object.entries(namedQueries).map(([name, query]) => [name, (0, parseQuery_1.parse)(query)]));
|
|
490
|
-
const querier = createQuerier();
|
|
491
|
-
const result = querier.beginHandle(queries, ast);
|
|
492
|
-
log?.debug("Query time: ", Date.now() - start);
|
|
493
|
-
if (returnAST) {
|
|
494
|
-
return { ...result, __AST: ast };
|
|
495
|
-
}
|
|
496
|
-
return result;
|
|
497
|
-
}
|
|
498
|
-
function parseSource(source, optimize = true) {
|
|
499
|
-
const parsingOptions = optimize ? { loc: false, ranges: false } : { loc: true, ranges: true };
|
|
500
|
-
try {
|
|
501
|
-
return (0, meriyah_1.parseScript)(source, { module: true, next: true, ...parsingOptions });
|
|
502
|
-
}
|
|
503
|
-
catch (e) {
|
|
504
|
-
return (0, meriyah_1.parseScript)(source, { module: false, next: true, ...parsingOptions, webcompat: true });
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
function createTraverser() {
|
|
508
|
-
let scopeIdCounter = 0;
|
|
509
|
-
const scopes = new Map();
|
|
510
|
-
let removedScopes = 0;
|
|
511
|
-
const nodePathsCreated = {};
|
|
512
|
-
function createScope(parentScopeId) {
|
|
513
|
-
const id = scopeIdCounter++;
|
|
514
|
-
if (parentScopeId != undefined) {
|
|
515
|
-
scopes.set(id, parentScopeId ?? -1);
|
|
516
|
-
}
|
|
517
|
-
return id;
|
|
518
|
-
}
|
|
519
|
-
function getBinding(scopeId, name) {
|
|
520
|
-
let currentScope = scopes.get(scopeId);
|
|
521
|
-
while (currentScope !== undefined) {
|
|
522
|
-
if (typeof currentScope !== "number") {
|
|
523
|
-
// Full scope: Check for binding
|
|
524
|
-
if (currentScope.bindings[name]) {
|
|
525
|
-
return currentScope.bindings[name];
|
|
526
|
-
}
|
|
527
|
-
// Move to parent scope
|
|
528
|
-
if (currentScope.parentScopeId === -1)
|
|
529
|
-
break; // No parent scope
|
|
530
|
-
currentScope = scopes.get(currentScope.parentScopeId);
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
// Lightweight scope: Retrieve parent scope
|
|
534
|
-
if (currentScope === -1 || currentScope == undefined)
|
|
535
|
-
break; // No parent scope
|
|
536
|
-
currentScope = scopes.get(currentScope);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
return undefined; // Binding not found
|
|
540
|
-
}
|
|
541
|
-
function setBinding(scopeId, name, binding) {
|
|
542
|
-
let scope = scopes.get(scopeId);
|
|
543
|
-
if (typeof scope === "number" || scope === undefined) {
|
|
544
|
-
// Upgrade the lightweight scope to a full scope
|
|
545
|
-
scope = { bindings: {}, id: scopeId, parentScopeId: scope };
|
|
546
|
-
scopes.set(scopeId, scope);
|
|
547
|
-
}
|
|
548
|
-
if (scope && typeof scope !== "number") {
|
|
549
|
-
scope.bindings[name] = binding;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
let pathsCreated = 0;
|
|
553
|
-
function getChildren(key, path) {
|
|
554
|
-
if (key in path.node) {
|
|
555
|
-
const r = path.node[key];
|
|
556
|
-
if (Array.isArray(r)) {
|
|
557
|
-
return r.map((n, i) => createNodePath(n, i, key, path.scopeId, path.functionScopeId, path));
|
|
558
|
-
}
|
|
559
|
-
else if (r != undefined) {
|
|
560
|
-
return [createNodePath(r, key, key, path.scopeId, path.functionScopeId, path)];
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return [];
|
|
564
|
-
}
|
|
565
|
-
function getPrimitiveChildren(key, path) {
|
|
566
|
-
if (key in path.node) {
|
|
567
|
-
const r = path.node[key];
|
|
568
|
-
return (0, utils_1.toArray)(r).filter(utils_1.isDefined).filter(nodeutils_1.isPrimitive);
|
|
569
|
-
}
|
|
570
|
-
return [];
|
|
571
|
-
}
|
|
572
|
-
function getPrimitiveChildrenOrNodePaths(key, path) {
|
|
573
|
-
if (key in path.node) {
|
|
574
|
-
const r = path.node[key];
|
|
575
|
-
if (Array.isArray(r)) {
|
|
576
|
-
return r.map((n, i) => (0, nodeutils_1.isPrimitive)(n) ? n :
|
|
577
|
-
// isLiteral(n) ? n.value as PrimitiveValue :
|
|
578
|
-
createNodePath(n, i, key, path.scopeId, path.functionScopeId, path));
|
|
579
|
-
}
|
|
580
|
-
else if (r != undefined) {
|
|
581
|
-
return [
|
|
582
|
-
(0, nodeutils_1.isPrimitive)(r) ? r :
|
|
583
|
-
// isLiteral(r) ? r.value as PrimitiveValue :
|
|
584
|
-
createNodePath(r, key, key, path.scopeId, path.functionScopeId, path)
|
|
585
|
-
];
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return [];
|
|
589
|
-
}
|
|
590
|
-
function createNodePath(node, key, parentKey, scopeId, functionScopeId, nodePath) {
|
|
591
|
-
if (node.extra?.nodePath) {
|
|
592
|
-
const path = node.extra.nodePath;
|
|
593
|
-
if (nodePath && (0, nodeutils_1.isExportSpecifier)(nodePath.node) && key == "exported" && path.key == "local") {
|
|
594
|
-
//Special handling for "export { someName }" as id is both local and exported
|
|
595
|
-
path.key = "exported";
|
|
596
|
-
path.parentPath = nodePath;
|
|
597
|
-
return path;
|
|
598
|
-
}
|
|
599
|
-
if (key != undefined)
|
|
600
|
-
path.key = typeof (key) == "number" ? key.toString() : key;
|
|
601
|
-
if (parentKey != undefined)
|
|
602
|
-
path.parentKey = parentKey;
|
|
603
|
-
if (nodePath != undefined)
|
|
604
|
-
path.parentPath = nodePath;
|
|
605
|
-
return path;
|
|
606
|
-
}
|
|
607
|
-
const finalScope = ((node.extra && node.extra.scopeId != undefined) ? node.extra.scopeId : scopeId) ?? createScope();
|
|
608
|
-
const finalFScope = ((node.extra && node.extra.functionScopeId != undefined) ? node.extra.functionScopeId : functionScopeId) ?? finalScope;
|
|
609
|
-
const path = {
|
|
610
|
-
node,
|
|
611
|
-
scopeId: finalScope,
|
|
612
|
-
functionScopeId: finalFScope,
|
|
613
|
-
parentPath: nodePath,
|
|
614
|
-
key: typeof (key) == "number" ? key.toString() : key,
|
|
615
|
-
parentKey
|
|
616
|
-
};
|
|
617
|
-
if ((0, nodeutils_1.isNode)(node)) {
|
|
618
|
-
node.extra = node.extra ?? {};
|
|
619
|
-
node.extra.nodePath = path;
|
|
620
|
-
Object.defineProperty(node.extra, "nodePath", { enumerable: false });
|
|
621
|
-
}
|
|
622
|
-
nodePathsCreated[node.type] = (nodePathsCreated[node.type] ?? 0) + 1;
|
|
623
|
-
pathsCreated++;
|
|
624
|
-
return path;
|
|
625
|
-
}
|
|
626
|
-
function registerBinding(stack, scopeId, functionScopeId, key, parentKey) {
|
|
627
|
-
//console.log("x registerBinding?", isIdentifier(node) ? node.name : node.type, parentNode.type, grandParentNode?.type, scopeId, isBinding(node, parentNode, grandParentNode));
|
|
628
|
-
const node = stack[stack.length - 1];
|
|
629
|
-
if (!(0, nodeutils_1.isIdentifier)(node))
|
|
630
|
-
return;
|
|
631
|
-
const parentNode = stack[stack.length - 2];
|
|
632
|
-
if ((0, nodeutils_1.isAssignmentExpression)(parentNode) || (0, nodeutils_1.isMemberExpression)(parentNode) || (0, nodeutils_1.isUpdateExpression)(parentNode) || (0, nodeutils_1.isExportSpecifier)(parentNode))
|
|
633
|
-
return;
|
|
634
|
-
const grandParentNode = stack[stack.length - 3];
|
|
635
|
-
if (!(0, nodeutils_1.isBinding)(node, parentNode, grandParentNode))
|
|
636
|
-
return;
|
|
637
|
-
if (key == "id" && !(0, nodeutils_1.isVariableDeclarator)(parentNode)) {
|
|
638
|
-
setBinding(functionScopeId, node.name, { path: createNodePath(node, undefined, undefined, scopeId, functionScopeId) });
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
if ((0, nodeutils_1.isVariableDeclarator)(parentNode) && (0, nodeutils_1.isVariableDeclaration)(grandParentNode)) {
|
|
642
|
-
if (grandParentNode.kind == "var") {
|
|
643
|
-
setBinding(functionScopeId, node.name, { path: createNodePath(parentNode, undefined, undefined, scopeId, functionScopeId) });
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
else {
|
|
647
|
-
setBinding(scopeId, node.name, { path: createNodePath(parentNode, undefined, undefined, scopeId, functionScopeId) });
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
if ((0, nodeutils_1.isScope)(node, parentNode)) {
|
|
652
|
-
setBinding(scopeId, node.name, { path: createNodePath(node, key, parentKey, scopeId, functionScopeId) });
|
|
653
|
-
} /*else {
|
|
654
|
-
console.log(node.type, parentNode.type, grandParentNode?.type);
|
|
655
|
-
}*/
|
|
656
|
-
}
|
|
657
|
-
let bindingNodesVisited = 0;
|
|
658
|
-
function registerBindings(stack, scopeId, functionScopeId) {
|
|
659
|
-
const node = stack[stack.length - 1];
|
|
660
|
-
if (!(0, nodeutils_1.isNode)(node))
|
|
661
|
-
return;
|
|
662
|
-
if (node.extra?.scopeId != undefined)
|
|
663
|
-
return;
|
|
664
|
-
node.extra = node.extra ?? {};
|
|
665
|
-
node.extra.scopeId = scopeId;
|
|
666
|
-
bindingNodesVisited++;
|
|
667
|
-
const keys = nodeutils_1.VISITOR_KEYS[node.type];
|
|
668
|
-
if (keys.length == 0)
|
|
669
|
-
return;
|
|
670
|
-
let childScopeId = scopeId;
|
|
671
|
-
if ((0, nodeutils_1.isScopable)(node)) {
|
|
672
|
-
childScopeId = createScope(scopeId);
|
|
673
|
-
}
|
|
674
|
-
for (const key of keys) {
|
|
675
|
-
const childNodes = node[key];
|
|
676
|
-
const children = (0, utils_1.toArray)(childNodes).filter(utils_1.isDefined);
|
|
677
|
-
for (const [i, child] of children.entries()) {
|
|
678
|
-
if (!(0, nodeutils_1.isNode)(child))
|
|
679
|
-
continue;
|
|
680
|
-
const f = key === "body" && ((0, nodeutils_1.isFunctionDeclaration)(node) || (0, nodeutils_1.isFunctionExpression)(node)) ? childScopeId : functionScopeId;
|
|
681
|
-
stack.push(child);
|
|
682
|
-
if ((0, nodeutils_1.isIdentifier)(child)) {
|
|
683
|
-
const k = Array.isArray(childNodes) ? i : key;
|
|
684
|
-
registerBinding(stack, childScopeId, f, k, key);
|
|
685
|
-
}
|
|
686
|
-
else {
|
|
687
|
-
registerBindings(stack, childScopeId, f);
|
|
688
|
-
}
|
|
689
|
-
stack.pop();
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (childScopeId != scopeId && typeof scopes.get(childScopeId) == "number") { // Scope has not been populated
|
|
693
|
-
scopes.set(childScopeId, scopes.get(scopeId));
|
|
694
|
-
removedScopes++;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
function traverseInner(node, visitor, scopeId, functionScopeId, state, path) {
|
|
698
|
-
const nodePath = path ?? createNodePath(node, undefined, undefined, scopeId, functionScopeId);
|
|
699
|
-
const keys = nodeutils_1.VISITOR_KEYS[node.type] ?? [];
|
|
700
|
-
if (nodePath.parentPath)
|
|
701
|
-
registerBindings([nodePath.parentPath.parentPath?.node, nodePath.parentPath.node, nodePath.node].filter(utils_1.isDefined), nodePath.scopeId, nodePath.functionScopeId);
|
|
702
|
-
for (const key of keys) {
|
|
703
|
-
const childNodes = node[key];
|
|
704
|
-
const children = Array.isArray(childNodes) ? childNodes : childNodes ? [childNodes] : [];
|
|
705
|
-
const nodePaths = [];
|
|
706
|
-
for (const [i, child] of children.entries()) {
|
|
707
|
-
if ((0, nodeutils_1.isNode)(child)) {
|
|
708
|
-
const childPath = createNodePath(child, Array.isArray(childNodes) ? i : key, key, nodePath.scopeId, nodePath.functionScopeId, nodePath);
|
|
709
|
-
nodePaths.push(childPath);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
for (const childPath of nodePaths) {
|
|
713
|
-
visitor.enter(childPath, state);
|
|
714
|
-
traverseInner(childPath.node, visitor, nodePath.scopeId, nodePath.functionScopeId, state, childPath);
|
|
715
|
-
visitor.exit(childPath, state);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
const sOut = [];
|
|
720
|
-
function traverse(node, visitor, scopeId, state, path) {
|
|
721
|
-
const fscope = path?.functionScopeId ?? node.extra?.functionScopeId ?? scopeId;
|
|
722
|
-
traverseInner(node, visitor, scopeId, fscope, state, path);
|
|
723
|
-
if (!sOut.includes(scopeIdCounter)) {
|
|
724
|
-
log?.debug("Scopes created", scopeIdCounter, " Scopes removed", removedScopes, "Paths created", pathsCreated, bindingNodesVisited);
|
|
725
|
-
sOut.push(scopeIdCounter);
|
|
726
|
-
const k = Object.fromEntries(Object.entries(nodePathsCreated).sort((a, b) => a[1] - b[1]));
|
|
727
|
-
log?.debug("Node paths created", k);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
return {
|
|
731
|
-
traverse,
|
|
732
|
-
createNodePath,
|
|
733
|
-
getChildren,
|
|
734
|
-
getPrimitiveChildren,
|
|
735
|
-
getPrimitiveChildrenOrNodePaths,
|
|
736
|
-
getBinding
|
|
737
|
-
};
|
|
738
|
-
}
|