yuku-analyzer 0.5.35 → 0.5.36

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/README.md CHANGED
@@ -62,6 +62,7 @@ And node-level queries that work directly on AST nodes:
62
62
  module.symbolOf(node) // the symbol a node declares or references
63
63
  module.referenceOf(node) // the reference recorded for an identifier
64
64
  module.scopeOf(node) // the innermost scope containing the node
65
+ module.parentOf(node) // the node that structurally contains it, or null
65
66
  module.resolve("name") // scope-chain lookup, like the engine does at runtime
66
67
  ```
67
68
 
package/decode.js CHANGED
@@ -1331,6 +1331,35 @@ function decode(buffer, source) {
1331
1331
  }
1332
1332
  })(progIdx);
1333
1333
  }
1334
+ let _parentArr;
1335
+ function _parents() {
1336
+ if (_parentArr !== undefined) return _parentArr;
1337
+ const p = new Int32Array(nodeCount).fill(-1);
1338
+ (function visit(i, parent) {
1339
+ const o = _nodesOff + i * 48;
1340
+ const tag = _u8[o];
1341
+ if (TAG_TYPES[tag] !== null) { p[i] = parent; parent = i; }
1342
+ const ops = SCAN_CHILDREN[tag];
1343
+ const b = o >> 2;
1344
+ for (let q = 0; q < ops.length; q += 2) {
1345
+ const slot = ops[q + 1];
1346
+ if (ops[q] === 0) {
1347
+ const c = _u32[b + slot];
1348
+ if (c !== NULL) visit(c, parent);
1349
+ } else {
1350
+ const s = _u32[b + slot];
1351
+ const len = ops[q] === 1
1352
+ ? _u32[b + slot + 1]
1353
+ : _u8[o + 4] | (_u8[o + 5] << 8);
1354
+ for (let j = 0; j < len; j++) {
1355
+ const c = _u32[_extraBase + s + j];
1356
+ if (c !== NULL) visit(c, parent);
1357
+ }
1358
+ }
1359
+ }
1360
+ })(progIdx, -1);
1361
+ return (_parentArr = p);
1362
+ }
1334
1363
  let _semView;
1335
1364
  function _semantic() {
1336
1365
  if (_semView !== undefined) return _semView;
@@ -1459,6 +1488,7 @@ function decode(buffer, source) {
1459
1488
  scan,
1460
1489
  nodeOf: node,
1461
1490
  indexOf: (n) => _nodeIndexes.get(n),
1491
+ parentIndex: (i) => _parents()[i],
1462
1492
  startOf, endOf, str,
1463
1493
  get semantic() { return _semantic(); },
1464
1494
  };
package/index.d.ts CHANGED
@@ -412,6 +412,12 @@ interface Module {
412
412
  referenceOf(node: Node): Reference | null;
413
413
  /** The innermost scope whose extent contains `node`. */
414
414
  scopeOf(node: Node): Scope;
415
+ /**
416
+ * The node that structurally contains `node`. Null at the program
417
+ * root and for a node not part of this module's AST. Lets you walk
418
+ * upward from a node you already hold, with no ancestor stack.
419
+ */
420
+ parentOf(node: Node): Node | null;
415
421
  /**
416
422
  * Walks the scope chain from `from` (default: the root scope) to
417
423
  * find the nearest binding of `name`.
package/module.js CHANGED
@@ -356,6 +356,15 @@ export class Module {
356
356
  return this.scopes[this.#sem.nodeScope(index)];
357
357
  }
358
358
 
359
+ // the node that structurally contains `node`, or null at the program
360
+ // root or for a node not part of this module's AST.
361
+ parentOf(node) {
362
+ const index = this.#r.indexOf(node);
363
+ if (index === undefined) return null;
364
+ const parent = this.#r.parentIndex(index);
365
+ return parent < 0 ? null : this.#r.nodeOf(parent);
366
+ }
367
+
359
368
  resolve(name, from = this.rootScope) {
360
369
  for (let s = from; s; s = s.parent) {
361
370
  const found = s.find(name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yuku-analyzer",
3
- "version": "0.5.35",
3
+ "version": "0.5.36",
4
4
  "description": "High-performance JavaScript/TypeScript semantic analyzer: per-file scopes, symbols, references, and cross-file module linking",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -21,17 +21,17 @@
21
21
  "decode.js"
22
22
  ],
23
23
  "optionalDependencies": {
24
- "@yuku-analyzer/binding-linux-x64-gnu": "0.5.35",
25
- "@yuku-analyzer/binding-linux-arm64-gnu": "0.5.35",
26
- "@yuku-analyzer/binding-linux-arm-gnu": "0.5.35",
27
- "@yuku-analyzer/binding-linux-x64-musl": "0.5.35",
28
- "@yuku-analyzer/binding-linux-arm64-musl": "0.5.35",
29
- "@yuku-analyzer/binding-linux-arm-musl": "0.5.35",
30
- "@yuku-analyzer/binding-darwin-x64": "0.5.35",
31
- "@yuku-analyzer/binding-darwin-arm64": "0.5.35",
32
- "@yuku-analyzer/binding-win32-x64": "0.5.35",
33
- "@yuku-analyzer/binding-win32-arm64": "0.5.35",
34
- "@yuku-analyzer/binding-freebsd-x64": "0.5.35"
24
+ "@yuku-analyzer/binding-linux-x64-gnu": "0.5.36",
25
+ "@yuku-analyzer/binding-linux-arm64-gnu": "0.5.36",
26
+ "@yuku-analyzer/binding-linux-arm-gnu": "0.5.36",
27
+ "@yuku-analyzer/binding-linux-x64-musl": "0.5.36",
28
+ "@yuku-analyzer/binding-linux-arm64-musl": "0.5.36",
29
+ "@yuku-analyzer/binding-linux-arm-musl": "0.5.36",
30
+ "@yuku-analyzer/binding-darwin-x64": "0.5.36",
31
+ "@yuku-analyzer/binding-darwin-arm64": "0.5.36",
32
+ "@yuku-analyzer/binding-win32-x64": "0.5.36",
33
+ "@yuku-analyzer/binding-win32-arm64": "0.5.36",
34
+ "@yuku-analyzer/binding-freebsd-x64": "0.5.36"
35
35
  },
36
36
  "keywords": [
37
37
  "analyzer",