astronomical 2.0.1 → 2.1.1-rc.1
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/index.js +221 -73
- package/lib/cjs/parseQuery.js +109 -65
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/cjs/types/parseQuery.d.ts +36 -7
- package/lib/cjs/types/parseQuery.d.ts.map +1 -1
- package/lib/esm/{index.mjs → index.js} +221 -73
- package/lib/esm/parseQuery.js +109 -65
- package/lib/esm/types/index.d.ts.map +1 -1
- package/lib/esm/types/parseQuery.d.ts +36 -7
- package/lib/esm/types/parseQuery.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.js
CHANGED
|
@@ -34,9 +34,16 @@ exports.functions = {
|
|
|
34
34
|
},
|
|
35
35
|
"concat": {
|
|
36
36
|
fn: (result) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// Optimize: combine empty check with manual flattening
|
|
38
|
+
const flattened = [];
|
|
39
|
+
for (let i = 0; i < result.length; i++) {
|
|
40
|
+
if (result[i].length === 0)
|
|
41
|
+
return [];
|
|
42
|
+
for (let j = 0; j < result[i].length; j++) {
|
|
43
|
+
flattened.push(result[i][j]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [flattened.join("")];
|
|
40
47
|
}
|
|
41
48
|
},
|
|
42
49
|
"first": {
|
|
@@ -45,7 +52,7 @@ exports.functions = {
|
|
|
45
52
|
throw new Error("Invalid number of arugments for first");
|
|
46
53
|
if (result[0].length == 0)
|
|
47
54
|
return [];
|
|
48
|
-
return [result
|
|
55
|
+
return [result[0][0]];
|
|
49
56
|
}
|
|
50
57
|
},
|
|
51
58
|
"nthchild": {
|
|
@@ -79,14 +86,14 @@ function createQuerier() {
|
|
|
79
86
|
const traverser = createTraverser();
|
|
80
87
|
const { getChildren, getPrimitiveChildren, getPrimitiveChildrenOrNodePaths, getBinding, createNodePath, traverse } = traverser;
|
|
81
88
|
function createFilter(filter, filterResult) {
|
|
82
|
-
if (filter.type ==
|
|
89
|
+
if (filter.type == parseQuery_1.NodeType.AND || filter.type == parseQuery_1.NodeType.OR || filter.type == parseQuery_1.NodeType.EQUALS) {
|
|
83
90
|
return {
|
|
84
91
|
type: filter.type,
|
|
85
92
|
left: createFilter(filter.left, []),
|
|
86
93
|
right: createFilter(filter.right, [])
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
|
-
else if (filter.type ==
|
|
96
|
+
else if (filter.type == parseQuery_1.NodeType.LITERAL) {
|
|
90
97
|
const r = [filter.value];
|
|
91
98
|
return {
|
|
92
99
|
node: filter,
|
|
@@ -102,16 +109,16 @@ function createQuerier() {
|
|
|
102
109
|
};
|
|
103
110
|
}
|
|
104
111
|
function addFilterChildrenToState(filter, state) {
|
|
105
|
-
if ("type" in filter && (filter.type ==
|
|
112
|
+
if ("type" in filter && (filter.type == parseQuery_1.NodeType.AND || filter.type == parseQuery_1.NodeType.OR || filter.type == parseQuery_1.NodeType.EQUALS)) {
|
|
106
113
|
addFilterChildrenToState(filter.left, state);
|
|
107
114
|
addFilterChildrenToState(filter.right, state);
|
|
108
115
|
}
|
|
109
116
|
else if ("node" in filter) {
|
|
110
|
-
if (filter.node.type ==
|
|
117
|
+
if (filter.node.type == parseQuery_1.NodeType.CHILD) {
|
|
111
118
|
log?.debug("ADDING FILTER CHILD", filter.node);
|
|
112
119
|
state.child[state.depth + 1].push(filter);
|
|
113
120
|
}
|
|
114
|
-
if (filter.node.type ==
|
|
121
|
+
if (filter.node.type == parseQuery_1.NodeType.DESCENDANT) {
|
|
115
122
|
log?.debug("ADDING FILTER DESCENDANT", filter.node);
|
|
116
123
|
state.descendant[state.depth + 1].push(filter);
|
|
117
124
|
}
|
|
@@ -120,10 +127,10 @@ function createQuerier() {
|
|
|
120
127
|
function createFNodeAndAddToState(token, result, state) {
|
|
121
128
|
log?.debug("ADDING FNODE", token);
|
|
122
129
|
const fnode = createFNode(token, result);
|
|
123
|
-
if (token.type ==
|
|
130
|
+
if (token.type == parseQuery_1.NodeType.CHILD) {
|
|
124
131
|
state.child[state.depth + 1].push(fnode);
|
|
125
132
|
}
|
|
126
|
-
else if (token.type ==
|
|
133
|
+
else if (token.type == parseQuery_1.NodeType.DESCENDANT) {
|
|
127
134
|
state.descendant[state.depth + 1].push(fnode);
|
|
128
135
|
}
|
|
129
136
|
return fnode;
|
|
@@ -161,7 +168,7 @@ function createQuerier() {
|
|
|
161
168
|
addFilterChildrenToState(filter, state);
|
|
162
169
|
const child = fnode.node.child;
|
|
163
170
|
if (child) {
|
|
164
|
-
if (child.type ==
|
|
171
|
+
if (child.type == parseQuery_1.NodeType.FUNCTION) {
|
|
165
172
|
const fr = addFunction(fnode, child, path, state);
|
|
166
173
|
state.functionCalls[state.depth].push(fr);
|
|
167
174
|
}
|
|
@@ -172,7 +179,7 @@ function createQuerier() {
|
|
|
172
179
|
}
|
|
173
180
|
else {
|
|
174
181
|
const child = fnode.node.child;
|
|
175
|
-
if (child?.type ==
|
|
182
|
+
if (child?.type == parseQuery_1.NodeType.FUNCTION) {
|
|
176
183
|
const fr = addFunction(fnode, child, path, state);
|
|
177
184
|
state.functionCalls[state.depth].push(fr);
|
|
178
185
|
}
|
|
@@ -184,11 +191,11 @@ function createQuerier() {
|
|
|
184
191
|
function addFunction(rootNode, functionCall, path, state) {
|
|
185
192
|
const functionNode = { node: rootNode.node, functionCall: functionCall, parameters: [], result: [] };
|
|
186
193
|
for (const param of functionCall.parameters) {
|
|
187
|
-
if (param.type ==
|
|
194
|
+
if (param.type == parseQuery_1.NodeType.LITERAL) {
|
|
188
195
|
functionNode.parameters.push({ node: param, result: [param.value] });
|
|
189
196
|
}
|
|
190
197
|
else {
|
|
191
|
-
if (param.type ==
|
|
198
|
+
if (param.type == parseQuery_1.NodeType.FUNCTION) {
|
|
192
199
|
functionNode.parameters.push(addFunction(functionNode, param, path, state));
|
|
193
200
|
}
|
|
194
201
|
else {
|
|
@@ -214,7 +221,7 @@ function createQuerier() {
|
|
|
214
221
|
function evaluateFilter(filter, path) {
|
|
215
222
|
log?.debug("EVALUATING FILTER", filter, breadCrumb(path));
|
|
216
223
|
if ("type" in filter) {
|
|
217
|
-
if (filter.type ==
|
|
224
|
+
if (filter.type == parseQuery_1.NodeType.AND) {
|
|
218
225
|
const left = evaluateFilter(filter.left, path);
|
|
219
226
|
if (left.length == 0) {
|
|
220
227
|
return [];
|
|
@@ -222,7 +229,7 @@ function createQuerier() {
|
|
|
222
229
|
const r = evaluateFilter(filter.right, path);
|
|
223
230
|
return r;
|
|
224
231
|
}
|
|
225
|
-
if (filter.type ==
|
|
232
|
+
if (filter.type == parseQuery_1.NodeType.OR) {
|
|
226
233
|
const left = evaluateFilter(filter.left, path);
|
|
227
234
|
if (left.length > 0) {
|
|
228
235
|
return left;
|
|
@@ -230,15 +237,30 @@ function createQuerier() {
|
|
|
230
237
|
const r = evaluateFilter(filter.right, path);
|
|
231
238
|
return r;
|
|
232
239
|
}
|
|
233
|
-
if (filter.type ==
|
|
240
|
+
if (filter.type == parseQuery_1.NodeType.EQUALS) {
|
|
234
241
|
const left = evaluateFilter(filter.left, path);
|
|
235
242
|
const right = evaluateFilter(filter.right, path);
|
|
236
|
-
|
|
243
|
+
// Optimize: use Set for O(1) lookups instead of O(n) includes
|
|
244
|
+
if (right.length > 3) {
|
|
245
|
+
const rightSet = new Set(right);
|
|
246
|
+
const r = [];
|
|
247
|
+
for (let i = 0; i < left.length; i++) {
|
|
248
|
+
if (rightSet.has(left[i]))
|
|
249
|
+
r.push(left[i]);
|
|
250
|
+
}
|
|
251
|
+
return r;
|
|
252
|
+
}
|
|
253
|
+
// For small arrays, includes is faster than Set creation
|
|
254
|
+
const r = [];
|
|
255
|
+
for (let i = 0; i < left.length; i++) {
|
|
256
|
+
if (right.includes(left[i]))
|
|
257
|
+
r.push(left[i]);
|
|
258
|
+
}
|
|
237
259
|
return r;
|
|
238
260
|
}
|
|
239
261
|
throw new Error("Unknown filter type: " + filter.type);
|
|
240
262
|
}
|
|
241
|
-
if (filter.node.type ==
|
|
263
|
+
if (filter.node.type == parseQuery_1.NodeType.PARENT) {
|
|
242
264
|
const r = resolveFilterWithParent(filter.node, path);
|
|
243
265
|
return r;
|
|
244
266
|
}
|
|
@@ -261,7 +283,7 @@ function createQuerier() {
|
|
|
261
283
|
function resolveFilterWithParent(node, path) {
|
|
262
284
|
let startNode = node;
|
|
263
285
|
let startPath = path;
|
|
264
|
-
while (startNode.type ==
|
|
286
|
+
while (startNode.type == parseQuery_1.NodeType.PARENT) {
|
|
265
287
|
if (!startNode.child)
|
|
266
288
|
throw new Error("Parent filter must have child");
|
|
267
289
|
if (!startPath.parentPath)
|
|
@@ -272,40 +294,80 @@ function createQuerier() {
|
|
|
272
294
|
}
|
|
273
295
|
return resolveDirectly(startNode, startPath);
|
|
274
296
|
}
|
|
275
|
-
function isDefined(value) {
|
|
276
|
-
return value != undefined && value != null;
|
|
277
|
-
}
|
|
278
297
|
let subQueryCounter = 0;
|
|
279
298
|
const memo = new Map();
|
|
280
299
|
function resolveDirectly(node, path) {
|
|
281
300
|
let startNode = node;
|
|
282
301
|
const startPath = path;
|
|
283
302
|
let paths = [startPath];
|
|
284
|
-
while (startNode.attribute && startNode.type ==
|
|
303
|
+
while (startNode.attribute && startNode.type == parseQuery_1.NodeType.CHILD) {
|
|
285
304
|
const lookup = startNode.value;
|
|
286
305
|
if (!lookup)
|
|
287
306
|
throw new Error("Selector must have a value");
|
|
288
307
|
//log?.debug("STEP IN ", lookup, paths.map(p => breadCrumb(p)));
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
308
|
+
// Optimize: avoid filter().map().flat() chain - use single loop
|
|
309
|
+
const nodes = [];
|
|
310
|
+
for (let i = 0; i < paths.length; i++) {
|
|
311
|
+
const p = paths[i];
|
|
312
|
+
if (!(0, nodeutils_1.isNodePath)(p))
|
|
313
|
+
continue;
|
|
314
|
+
const arr = getPrimitiveChildrenOrNodePaths(lookup, p);
|
|
315
|
+
for (let j = 0; j < arr.length; j++) {
|
|
316
|
+
nodes.push(arr[j]);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
292
319
|
if (nodes.length == 0)
|
|
293
320
|
return [];
|
|
294
321
|
paths = nodes;
|
|
295
322
|
if (startNode.resolve) {
|
|
296
|
-
const resolved =
|
|
323
|
+
const resolved = [];
|
|
324
|
+
for (let i = 0; i < paths.length; i++) {
|
|
325
|
+
const p = paths[i];
|
|
326
|
+
if (!(0, nodeutils_1.isNodePath)(p))
|
|
327
|
+
continue;
|
|
328
|
+
const binding = resolveBinding(p);
|
|
329
|
+
if (!binding)
|
|
330
|
+
continue;
|
|
331
|
+
const children = getChildren("init", binding);
|
|
332
|
+
for (let j = 0; j < children.length; j++) {
|
|
333
|
+
resolved.push(children[j]);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
297
336
|
if (resolved.length > 0)
|
|
298
337
|
paths = resolved;
|
|
299
338
|
}
|
|
300
339
|
else if (startNode.binding) {
|
|
301
|
-
|
|
340
|
+
const bindings = [];
|
|
341
|
+
for (let i = 0; i < paths.length; i++) {
|
|
342
|
+
const p = paths[i];
|
|
343
|
+
if (!(0, nodeutils_1.isNodePath)(p))
|
|
344
|
+
continue;
|
|
345
|
+
const binding = resolveBinding(p);
|
|
346
|
+
if (binding)
|
|
347
|
+
bindings.push(binding);
|
|
348
|
+
}
|
|
349
|
+
paths = bindings;
|
|
302
350
|
}
|
|
303
351
|
const filter = startNode.filter;
|
|
304
352
|
if (filter) {
|
|
305
|
-
|
|
353
|
+
const filtered = [];
|
|
354
|
+
for (let i = 0; i < paths.length; i++) {
|
|
355
|
+
const p = paths[i];
|
|
356
|
+
if (!(0, nodeutils_1.isNodePath)(p))
|
|
357
|
+
continue;
|
|
358
|
+
if (travHandle({ subquery: filter }, p).subquery.length > 0) {
|
|
359
|
+
filtered.push(p);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
paths = filtered;
|
|
306
363
|
}
|
|
307
364
|
if (!startNode.child) {
|
|
308
|
-
|
|
365
|
+
const results = new Array(paths.length);
|
|
366
|
+
for (let i = 0; i < paths.length; i++) {
|
|
367
|
+
const p = paths[i];
|
|
368
|
+
results[i] = (0, nodeutils_1.isPrimitive)(p) ? p : p.node;
|
|
369
|
+
}
|
|
370
|
+
return results;
|
|
309
371
|
}
|
|
310
372
|
startNode = startNode.child;
|
|
311
373
|
}
|
|
@@ -315,7 +377,10 @@ function createQuerier() {
|
|
|
315
377
|
for (const path of paths) {
|
|
316
378
|
if ((0, nodeutils_1.isNodePath)(path)) {
|
|
317
379
|
if (memo.has(startNode) && memo.get(startNode).has(path)) {
|
|
318
|
-
|
|
380
|
+
const cached = memo.get(startNode).get(path);
|
|
381
|
+
for (let i = 0; i < cached.length; i++) {
|
|
382
|
+
result.push(cached[i]);
|
|
383
|
+
}
|
|
319
384
|
}
|
|
320
385
|
else {
|
|
321
386
|
const subQueryKey = "subquery-" + subQueryCounter++;
|
|
@@ -323,7 +388,9 @@ function createQuerier() {
|
|
|
323
388
|
if (!memo.has(startNode))
|
|
324
389
|
memo.set(startNode, new Map());
|
|
325
390
|
memo.get(startNode)?.set(path, subQueryResult);
|
|
326
|
-
|
|
391
|
+
for (let i = 0; i < subQueryResult.length; i++) {
|
|
392
|
+
result.push(subQueryResult[i]);
|
|
393
|
+
}
|
|
327
394
|
}
|
|
328
395
|
}
|
|
329
396
|
}
|
|
@@ -336,14 +403,16 @@ function createQuerier() {
|
|
|
336
403
|
const filters = [];
|
|
337
404
|
const nodeFilters = state.filtersMap[state.depth].get(fnode.node);
|
|
338
405
|
if (nodeFilters) {
|
|
339
|
-
for (
|
|
406
|
+
for (let i = 0; i < nodeFilters.length; i++) {
|
|
407
|
+
const f = nodeFilters[i];
|
|
340
408
|
if (f.qNode !== fnode.node)
|
|
341
409
|
continue;
|
|
342
410
|
if (f.node !== path.node)
|
|
343
411
|
continue;
|
|
344
412
|
filters.push(f);
|
|
345
413
|
}
|
|
346
|
-
for (
|
|
414
|
+
for (let i = 0; i < filters.length; i++) {
|
|
415
|
+
const f = filters[i];
|
|
347
416
|
if (evaluateFilter(f.filter, path).length > 0) {
|
|
348
417
|
matchingFilters.push(f);
|
|
349
418
|
}
|
|
@@ -356,7 +425,9 @@ function createQuerier() {
|
|
|
356
425
|
const resolved = binding ? getChildren("init", binding)[0] : undefined;
|
|
357
426
|
if (fnode.node.child) {
|
|
358
427
|
const result = resolveDirectly(fnode.node.child, resolved ?? path);
|
|
359
|
-
|
|
428
|
+
for (let i = 0; i < result.length; i++) {
|
|
429
|
+
fnode.result.push(result[i]);
|
|
430
|
+
}
|
|
360
431
|
}
|
|
361
432
|
else {
|
|
362
433
|
fnode.result.push(path.node);
|
|
@@ -367,7 +438,9 @@ function createQuerier() {
|
|
|
367
438
|
if (binding) {
|
|
368
439
|
if (fnode.node.child) {
|
|
369
440
|
const result = resolveDirectly(fnode.node.child, binding);
|
|
370
|
-
|
|
441
|
+
for (let i = 0; i < result.length; i++) {
|
|
442
|
+
fnode.result.push(result[i]);
|
|
443
|
+
}
|
|
371
444
|
}
|
|
372
445
|
else {
|
|
373
446
|
fnode.result.push(binding.node);
|
|
@@ -377,7 +450,7 @@ function createQuerier() {
|
|
|
377
450
|
else if (!fnode.node.child) {
|
|
378
451
|
fnode.result.push(path.node);
|
|
379
452
|
}
|
|
380
|
-
else if (fnode.node.child.type ==
|
|
453
|
+
else if (fnode.node.child.type == parseQuery_1.NodeType.FUNCTION) {
|
|
381
454
|
const functionCallResult = state.functionCalls[state.depth].find(f => f.node == fnode.node);
|
|
382
455
|
if (!functionCallResult)
|
|
383
456
|
throw new Error("Did not find expected function call for " + fnode.node.child.function);
|
|
@@ -385,12 +458,18 @@ function createQuerier() {
|
|
|
385
458
|
}
|
|
386
459
|
else if (matchingFilters.length > 0) {
|
|
387
460
|
log?.debug("HAS MATCHING FILTER", fnode.result.length, matchingFilters.length, breadCrumb(path));
|
|
388
|
-
|
|
461
|
+
for (let i = 0; i < matchingFilters.length; i++) {
|
|
462
|
+
const filterResult = matchingFilters[i].result;
|
|
463
|
+
for (let j = 0; j < filterResult.length; j++) {
|
|
464
|
+
fnode.result.push(filterResult[j]);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
389
467
|
}
|
|
390
468
|
}
|
|
391
469
|
function resolveFunctionCalls(fnode, functionCallResult, path, state) {
|
|
392
470
|
const parameterResults = [];
|
|
393
|
-
for (
|
|
471
|
+
for (let i = 0; i < functionCallResult.parameters.length; i++) {
|
|
472
|
+
const p = functionCallResult.parameters[i];
|
|
394
473
|
if ("parameters" in p) {
|
|
395
474
|
resolveFunctionCalls(p, p, path, state);
|
|
396
475
|
parameterResults.push(p.result);
|
|
@@ -401,10 +480,17 @@ function createQuerier() {
|
|
|
401
480
|
}
|
|
402
481
|
const functionResult = exports.functions[functionCallResult.functionCall.function].fn(parameterResults);
|
|
403
482
|
log?.debug("PARAMETER RESULTS", functionCallResult.functionCall.function, parameterResults, functionResult);
|
|
404
|
-
|
|
483
|
+
for (let i = 0; i < functionResult.length; i++) {
|
|
484
|
+
fnode.result.push(functionResult[i]);
|
|
485
|
+
}
|
|
405
486
|
}
|
|
406
487
|
function travHandle(queries, root) {
|
|
407
|
-
|
|
488
|
+
// Optimize: create results object directly instead of Object.fromEntries + map
|
|
489
|
+
const results = {};
|
|
490
|
+
const queryKeys = Object.keys(queries);
|
|
491
|
+
for (let i = 0; i < queryKeys.length; i++) {
|
|
492
|
+
results[queryKeys[i]] = [];
|
|
493
|
+
}
|
|
408
494
|
const state = {
|
|
409
495
|
depth: 0,
|
|
410
496
|
child: [[], []],
|
|
@@ -417,8 +503,18 @@ function createQuerier() {
|
|
|
417
503
|
for (const [name, node] of Object.entries(queries)) {
|
|
418
504
|
createFNodeAndAddToState(node, results[name], state);
|
|
419
505
|
}
|
|
420
|
-
|
|
421
|
-
state.
|
|
506
|
+
// Optimize: replace forEach with for loop
|
|
507
|
+
const childAtDepth = state.child[state.depth + 1];
|
|
508
|
+
for (let i = 0; i < childAtDepth.length; i++) {
|
|
509
|
+
addPrimitiveAttributeIfMatch(childAtDepth[i], root);
|
|
510
|
+
}
|
|
511
|
+
const descendantSlice = state.descendant.slice(0, state.depth + 1);
|
|
512
|
+
for (let i = 0; i < descendantSlice.length; i++) {
|
|
513
|
+
const fnodes = descendantSlice[i];
|
|
514
|
+
for (let j = 0; j < fnodes.length; j++) {
|
|
515
|
+
addPrimitiveAttributeIfMatch(fnodes[j], root);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
422
518
|
traverse(root.node, {
|
|
423
519
|
enter(path, state) {
|
|
424
520
|
//log?.debug("ENTER", breadCrumb(path));
|
|
@@ -441,14 +537,20 @@ function createQuerier() {
|
|
|
441
537
|
exit(path, state) {
|
|
442
538
|
log?.debug("EXIT", breadCrumb(path));
|
|
443
539
|
// Check for attributes as not all attributes are visited
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
540
|
+
// Optimize: replace forEach with for loop
|
|
541
|
+
const childAtDepthPlusOne = state.child[state.depth + 1];
|
|
542
|
+
for (let i = 0; i < childAtDepthPlusOne.length; i++) {
|
|
543
|
+
addPrimitiveAttributeIfMatch(childAtDepthPlusOne[i], path);
|
|
544
|
+
}
|
|
545
|
+
for (let i = 0; i < state.descendant.length; i++) {
|
|
546
|
+
const fnodes = state.descendant[i];
|
|
547
|
+
for (let j = 0; j < fnodes.length; j++) {
|
|
548
|
+
addPrimitiveAttributeIfMatch(fnodes[j], path);
|
|
448
549
|
}
|
|
449
550
|
}
|
|
450
|
-
|
|
451
|
-
|
|
551
|
+
const matchesAtDepth = state.matches[state.depth];
|
|
552
|
+
for (let i = 0; i < matchesAtDepth.length; i++) {
|
|
553
|
+
addResultIfTokenMatch(matchesAtDepth[i][0], matchesAtDepth[i][1], state);
|
|
452
554
|
}
|
|
453
555
|
state.depth--;
|
|
454
556
|
state.child.pop();
|
|
@@ -486,7 +588,13 @@ function multiQuery(code, namedQueries, returnAST) {
|
|
|
486
588
|
const ast = typeof code == "string" ? parseSource(code) : code;
|
|
487
589
|
if (ast == null)
|
|
488
590
|
throw new Error("Could not pase code");
|
|
489
|
-
|
|
591
|
+
// Optimize: parse queries directly instead of Object.fromEntries + map
|
|
592
|
+
const queries = {};
|
|
593
|
+
const entries = Object.entries(namedQueries);
|
|
594
|
+
for (let i = 0; i < entries.length; i++) {
|
|
595
|
+
const [name, queryStr] = entries[i];
|
|
596
|
+
queries[name] = (0, parseQuery_1.parse)(queryStr);
|
|
597
|
+
}
|
|
490
598
|
const querier = createQuerier();
|
|
491
599
|
const result = querier.beginHandle(queries, ast);
|
|
492
600
|
log?.debug("Query time: ", Date.now() - start);
|
|
@@ -554,7 +662,12 @@ function createTraverser() {
|
|
|
554
662
|
if (key in path.node) {
|
|
555
663
|
const r = path.node[key];
|
|
556
664
|
if (Array.isArray(r)) {
|
|
557
|
-
|
|
665
|
+
const len = r.length;
|
|
666
|
+
const result = new Array(len);
|
|
667
|
+
for (let i = 0; i < len; i++) {
|
|
668
|
+
result[i] = createNodePath(r[i], i, key, path.scopeId, path.functionScopeId, path);
|
|
669
|
+
}
|
|
670
|
+
return result;
|
|
558
671
|
}
|
|
559
672
|
else if (r != undefined) {
|
|
560
673
|
return [createNodePath(r, key, key, path.scopeId, path.functionScopeId, path)];
|
|
@@ -565,7 +678,16 @@ function createTraverser() {
|
|
|
565
678
|
function getPrimitiveChildren(key, path) {
|
|
566
679
|
if (key in path.node) {
|
|
567
680
|
const r = path.node[key];
|
|
568
|
-
|
|
681
|
+
const arr = (0, utils_1.toArray)(r);
|
|
682
|
+
// Optimize: single loop instead of chained filter()
|
|
683
|
+
const result = [];
|
|
684
|
+
for (let i = 0; i < arr.length; i++) {
|
|
685
|
+
const item = arr[i];
|
|
686
|
+
if ((0, utils_1.isDefined)(item) && (0, nodeutils_1.isPrimitive)(item)) {
|
|
687
|
+
result.push(item);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return result;
|
|
569
691
|
}
|
|
570
692
|
return [];
|
|
571
693
|
}
|
|
@@ -573,23 +695,29 @@ function createTraverser() {
|
|
|
573
695
|
if (key in path.node) {
|
|
574
696
|
const r = path.node[key];
|
|
575
697
|
if (Array.isArray(r)) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
698
|
+
const len = r.length;
|
|
699
|
+
const result = new Array(len);
|
|
700
|
+
for (let i = 0; i < len; i++) {
|
|
701
|
+
const n = r[i];
|
|
702
|
+
result[i] = (0, nodeutils_1.isPrimitive)(n) ? n : createNodePath(n, i, key, path.scopeId, path.functionScopeId, path);
|
|
703
|
+
}
|
|
704
|
+
return result;
|
|
579
705
|
}
|
|
580
706
|
else if (r != undefined) {
|
|
581
707
|
return [
|
|
582
708
|
(0, nodeutils_1.isPrimitive)(r) ? r :
|
|
583
|
-
// isLiteral(r) ? r.value as PrimitiveValue :
|
|
584
709
|
createNodePath(r, key, key, path.scopeId, path.functionScopeId, path)
|
|
585
710
|
];
|
|
586
711
|
}
|
|
587
712
|
}
|
|
588
713
|
return [];
|
|
589
714
|
}
|
|
715
|
+
const nodePathMap = new WeakMap();
|
|
590
716
|
function createNodePath(node, key, parentKey, scopeId, functionScopeId, nodePath) {
|
|
591
|
-
if (node
|
|
592
|
-
|
|
717
|
+
if (nodePathMap.has(node)) {
|
|
718
|
+
//if (node.extra?.nodePath) {
|
|
719
|
+
//const path = node.extra.nodePath;
|
|
720
|
+
const path = nodePathMap.get(node);
|
|
593
721
|
if (nodePath && (0, nodeutils_1.isExportSpecifier)(nodePath.node) && key == "exported" && path.key == "local") {
|
|
594
722
|
//Special handling for "export { someName }" as id is both local and exported
|
|
595
723
|
path.key = "exported";
|
|
@@ -615,9 +743,10 @@ function createTraverser() {
|
|
|
615
743
|
parentKey
|
|
616
744
|
};
|
|
617
745
|
if ((0, nodeutils_1.isNode)(node)) {
|
|
618
|
-
node.extra = node.extra ?? {};
|
|
619
|
-
node.extra.nodePath = path;
|
|
620
|
-
Object.defineProperty(node.extra, "nodePath", { enumerable: false });
|
|
746
|
+
//node.extra = node.extra ?? {};
|
|
747
|
+
//node.extra.nodePath = path;
|
|
748
|
+
//Object.defineProperty(node.extra, "nodePath", { enumerable: false });
|
|
749
|
+
nodePathMap.set(node, path);
|
|
621
750
|
}
|
|
622
751
|
nodePathsCreated[node.type] = (nodePathsCreated[node.type] ?? 0) + 1;
|
|
623
752
|
pathsCreated++;
|
|
@@ -671,11 +800,13 @@ function createTraverser() {
|
|
|
671
800
|
if ((0, nodeutils_1.isScopable)(node)) {
|
|
672
801
|
childScopeId = createScope(scopeId);
|
|
673
802
|
}
|
|
674
|
-
for (
|
|
803
|
+
for (let keyIdx = 0; keyIdx < keys.length; keyIdx++) {
|
|
804
|
+
const key = keys[keyIdx];
|
|
675
805
|
const childNodes = node[key];
|
|
676
|
-
const children = (0, utils_1.toArray)(childNodes)
|
|
677
|
-
for (
|
|
678
|
-
|
|
806
|
+
const children = (0, utils_1.toArray)(childNodes);
|
|
807
|
+
for (let i = 0; i < children.length; i++) {
|
|
808
|
+
const child = children[i];
|
|
809
|
+
if (!(0, utils_1.isDefined)(child) || !(0, nodeutils_1.isNode)(child))
|
|
679
810
|
continue;
|
|
680
811
|
const f = key === "body" && ((0, nodeutils_1.isFunctionDeclaration)(node) || (0, nodeutils_1.isFunctionExpression)(node)) ? childScopeId : functionScopeId;
|
|
681
812
|
stack.push(child);
|
|
@@ -696,20 +827,37 @@ function createTraverser() {
|
|
|
696
827
|
}
|
|
697
828
|
function traverseInner(node, visitor, scopeId, functionScopeId, state, path) {
|
|
698
829
|
const nodePath = path ?? createNodePath(node, undefined, undefined, scopeId, functionScopeId);
|
|
699
|
-
const keys = nodeutils_1.VISITOR_KEYS[node.type]
|
|
700
|
-
if (nodePath.parentPath)
|
|
701
|
-
|
|
702
|
-
|
|
830
|
+
const keys = nodeutils_1.VISITOR_KEYS[node.type];
|
|
831
|
+
if (nodePath.parentPath) {
|
|
832
|
+
const stack = [];
|
|
833
|
+
if (nodePath.parentPath.parentPath?.node)
|
|
834
|
+
stack.push(nodePath.parentPath.parentPath.node);
|
|
835
|
+
stack.push(nodePath.parentPath.node, nodePath.node);
|
|
836
|
+
registerBindings(stack, nodePath.scopeId, nodePath.functionScopeId);
|
|
837
|
+
}
|
|
838
|
+
// Optimization: Check if we need to traverse children at all
|
|
839
|
+
// If there are no descendant queries and no child queries at next depth, skip traversal
|
|
840
|
+
const stateTyped = state;
|
|
841
|
+
const hasDescendantQueries = stateTyped.descendant && stateTyped.descendant.some(arr => arr.length > 0);
|
|
842
|
+
const hasChildQueriesAtNextDepth = stateTyped.child && stateTyped.child[stateTyped.depth + 1] && stateTyped.child[stateTyped.depth + 1].length > 0;
|
|
843
|
+
// If no queries would match in this subtree, skip traversal entirely
|
|
844
|
+
if (!hasDescendantQueries && !hasChildQueriesAtNextDepth) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
for (let keyIdx = 0; keyIdx < keys.length; keyIdx++) {
|
|
848
|
+
const key = keys[keyIdx];
|
|
703
849
|
const childNodes = node[key];
|
|
704
850
|
const children = Array.isArray(childNodes) ? childNodes : childNodes ? [childNodes] : [];
|
|
705
851
|
const nodePaths = [];
|
|
706
|
-
for (
|
|
852
|
+
for (let i = 0; i < children.length; i++) {
|
|
853
|
+
const child = children[i];
|
|
707
854
|
if ((0, nodeutils_1.isNode)(child)) {
|
|
708
855
|
const childPath = createNodePath(child, Array.isArray(childNodes) ? i : key, key, nodePath.scopeId, nodePath.functionScopeId, nodePath);
|
|
709
856
|
nodePaths.push(childPath);
|
|
710
857
|
}
|
|
711
858
|
}
|
|
712
|
-
for (
|
|
859
|
+
for (let i = 0; i < nodePaths.length; i++) {
|
|
860
|
+
const childPath = nodePaths[i];
|
|
713
861
|
visitor.enter(childPath, state);
|
|
714
862
|
traverseInner(childPath.node, visitor, nodePath.scopeId, nodePath.functionScopeId, state, childPath);
|
|
715
863
|
visitor.exit(childPath, state);
|