@speclynx/apidom-core 4.10.0 → 4.11.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/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [4.11.1](https://github.com/speclynx/apidom/compare/v4.11.0...v4.11.1) (2026-06-10)
7
+
8
+ **Note:** Version bump only for package @speclynx/apidom-core
9
+
10
+ # [4.11.0](https://github.com/speclynx/apidom/compare/v4.10.1...v4.11.0) (2026-06-10)
11
+
12
+ ### Features
13
+
14
+ - **traverse:** skipVisited 'enter-only' mode and path.revisited ([#333](https://github.com/speclynx/apidom/issues/333)) ([fe944df](https://github.com/speclynx/apidom/commit/fe944df0eaab437a65d5761e6a3e14d490d2d3d6))
15
+
16
+ ## [4.10.1](https://github.com/speclynx/apidom/compare/v4.10.0...v4.10.1) (2026-05-20)
17
+
18
+ **Note:** Version bump only for package @speclynx/apidom-core
19
+
6
20
  # [4.10.0](https://github.com/speclynx/apidom/compare/v4.9.1...v4.10.0) (2026-05-12)
7
21
 
8
22
  **Note:** Version bump only for package @speclynx/apidom-core
@@ -16343,8 +16343,10 @@ class Composer {
16343
16343
  }
16344
16344
  }
16345
16345
  if (afterDoc) {
16346
- Array.prototype.push.apply(doc.errors, this.errors);
16347
- Array.prototype.push.apply(doc.warnings, this.warnings);
16346
+ for (let i = 0; i < this.errors.length; ++i)
16347
+ doc.errors.push(this.errors[i]);
16348
+ for (let i = 0; i < this.warnings.length; ++i)
16349
+ doc.warnings.push(this.warnings[i]);
16348
16350
  }
16349
16351
  else {
16350
16352
  doc.errors = this.errors;
@@ -20418,7 +20420,7 @@ class Lexer {
20418
20420
  const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
20419
20421
  this.indentNext = this.indentValue + 1;
20420
20422
  this.indentValue += n;
20421
- return yield* this.parseBlockStart();
20423
+ return 'block-start';
20422
20424
  }
20423
20425
  return 'doc';
20424
20426
  }
@@ -20739,32 +20741,36 @@ class Lexer {
20739
20741
  return 0;
20740
20742
  }
20741
20743
  *pushIndicators() {
20742
- switch (this.charAt(0)) {
20743
- case '!':
20744
- return ((yield* this.pushTag()) +
20745
- (yield* this.pushSpaces(true)) +
20746
- (yield* this.pushIndicators()));
20747
- case '&':
20748
- return ((yield* this.pushUntil(isNotAnchorChar)) +
20749
- (yield* this.pushSpaces(true)) +
20750
- (yield* this.pushIndicators()));
20751
- case '-': // this is an error
20752
- case '?': // this is an error outside flow collections
20753
- case ':': {
20754
- const inFlow = this.flowLevel > 0;
20755
- const ch1 = this.charAt(1);
20756
- if (isEmpty(ch1) || (inFlow && flowIndicatorChars.has(ch1))) {
20757
- if (!inFlow)
20758
- this.indentNext = this.indentValue + 1;
20759
- else if (this.flowKey)
20760
- this.flowKey = false;
20761
- return ((yield* this.pushCount(1)) +
20762
- (yield* this.pushSpaces(true)) +
20763
- (yield* this.pushIndicators()));
20744
+ let n = 0;
20745
+ loop: while (true) {
20746
+ switch (this.charAt(0)) {
20747
+ case '!':
20748
+ n += yield* this.pushTag();
20749
+ n += yield* this.pushSpaces(true);
20750
+ continue loop;
20751
+ case '&':
20752
+ n += yield* this.pushUntil(isNotAnchorChar);
20753
+ n += yield* this.pushSpaces(true);
20754
+ continue loop;
20755
+ case '-': // this is an error
20756
+ case '?': // this is an error outside flow collections
20757
+ case ':': {
20758
+ const inFlow = this.flowLevel > 0;
20759
+ const ch1 = this.charAt(1);
20760
+ if (isEmpty(ch1) || (inFlow && flowIndicatorChars.has(ch1))) {
20761
+ if (!inFlow)
20762
+ this.indentNext = this.indentValue + 1;
20763
+ else if (this.flowKey)
20764
+ this.flowKey = false;
20765
+ n += yield* this.pushCount(1);
20766
+ n += yield* this.pushSpaces(true);
20767
+ continue loop;
20768
+ }
20764
20769
  }
20765
20770
  }
20771
+ break loop;
20766
20772
  }
20767
- return 0;
20773
+ return n;
20768
20774
  }
20769
20775
  *pushTag() {
20770
20776
  if (this.charAt(1) === '<') {
@@ -20955,6 +20961,14 @@ function getFirstKeyStartProps(prev) {
20955
20961
  }
20956
20962
  return prev.splice(i, prev.length);
20957
20963
  }
20964
+ function arrayPushArray(target, source) {
20965
+ // May exhaust call stack with large `source` array
20966
+ if (source.length < 1e5)
20967
+ Array.prototype.push.apply(target, source);
20968
+ else
20969
+ for (let i = 0; i < source.length; ++i)
20970
+ target.push(source[i]);
20971
+ }
20958
20972
  function fixFlowSeqItems(fc) {
20959
20973
  if (fc.start.type === 'flow-seq-start') {
20960
20974
  for (const it of fc.items) {
@@ -20967,12 +20981,12 @@ function fixFlowSeqItems(fc) {
20967
20981
  delete it.key;
20968
20982
  if (isFlowToken(it.value)) {
20969
20983
  if (it.value.end)
20970
- Array.prototype.push.apply(it.value.end, it.sep);
20984
+ arrayPushArray(it.value.end, it.sep);
20971
20985
  else
20972
20986
  it.value.end = it.sep;
20973
20987
  }
20974
20988
  else
20975
- Array.prototype.push.apply(it.start, it.sep);
20989
+ arrayPushArray(it.start, it.sep);
20976
20990
  delete it.sep;
20977
20991
  }
20978
20992
  }
@@ -21390,7 +21404,7 @@ class Parser {
21390
21404
  const prev = map.items[map.items.length - 2];
21391
21405
  const end = prev?.value?.end;
21392
21406
  if (Array.isArray(end)) {
21393
- Array.prototype.push.apply(end, it.start);
21407
+ arrayPushArray(end, it.start);
21394
21408
  end.push(this.sourceToken);
21395
21409
  map.items.pop();
21396
21410
  return;
@@ -21605,7 +21619,7 @@ class Parser {
21605
21619
  const prev = seq.items[seq.items.length - 2];
21606
21620
  const end = prev?.value?.end;
21607
21621
  if (Array.isArray(end)) {
21608
- Array.prototype.push.apply(end, it.start);
21622
+ arrayPushArray(end, it.start);
21609
21623
  end.push(this.sourceToken);
21610
21624
  seq.items.pop();
21611
21625
  return;
@@ -27992,6 +28006,14 @@ class Path {
27992
28006
  */
27993
28007
  inList;
27994
28008
 
28009
+ /**
28010
+ * True when this node is a non-descending revisit of an already-visited node
28011
+ * (only under skipVisited: 'enter-only'). Children are not traversed.
28012
+ * Set on both the enter and the matching leave phase, so it is meaningful
28013
+ * in either phase.
28014
+ */
28015
+ revisited = false;
28016
+
27995
28017
  /**
27996
28018
  * Internal state for traversal control.
27997
28019
  */
@@ -28576,6 +28598,10 @@ __webpack_require__.r(__webpack_exports__);
28576
28598
 
28577
28599
 
28578
28600
 
28601
+ /**
28602
+ * Controls handling of already-visited nodes during traversal.
28603
+ * @public
28604
+ */
28579
28605
  /**
28580
28606
  * Options for the traverse function.
28581
28607
  * @public
@@ -28583,6 +28609,12 @@ __webpack_require__.r(__webpack_exports__);
28583
28609
  // =============================================================================
28584
28610
  // Internal types for generator
28585
28611
  // =============================================================================
28612
+
28613
+ const normalizeSkipVisited = v => {
28614
+ if (v === true) return 'skip';
28615
+ if (v === false || v === undefined) return 'never';
28616
+ return v;
28617
+ };
28586
28618
  // =============================================================================
28587
28619
  // Core generator
28588
28620
  // =============================================================================
@@ -28600,7 +28632,7 @@ function* traverseGenerator(root, visitor, options) {
28600
28632
  mutationFn
28601
28633
  } = options;
28602
28634
  const keyMapIsFunction = typeof keyMap === 'function';
28603
- const visitedNodes = skipVisited ? new WeakSet() : null;
28635
+ const visitedNodes = skipVisited !== 'never' ? new WeakSet() : null;
28604
28636
  let stack;
28605
28637
  let inArray = Array.isArray(root);
28606
28638
  let keys = [root];
@@ -28615,6 +28647,7 @@ function* traverseGenerator(root, visitor, options) {
28615
28647
  index += 1;
28616
28648
  const isLeaving = index === keys.length;
28617
28649
  let key;
28650
+ let revisitNoDescend = false;
28618
28651
  const isEdited = isLeaving && edits.length !== 0;
28619
28652
  if (isLeaving) {
28620
28653
  key = ancestors.length === 0 ? undefined : currentPath?.key;
@@ -28656,6 +28689,7 @@ function* traverseGenerator(root, visitor, options) {
28656
28689
  edits = stack.edits;
28657
28690
  const parentInArray = stack.inArray;
28658
28691
  parentPath = stack.parentPath;
28692
+ revisitNoDescend = stack.revisitNoDescend;
28659
28693
  stack = stack.prev;
28660
28694
 
28661
28695
  // Push the edited node to parent's edits for propagation up the tree
@@ -28687,15 +28721,22 @@ function* traverseGenerator(root, visitor, options) {
28687
28721
  }
28688
28722
 
28689
28723
  // Skip already-visited nodes (handles DAG structures from cloneShallow)
28690
- if (skipVisited && !isLeaving) {
28724
+ if (skipVisited !== 'never' && !isLeaving) {
28691
28725
  if (visitedNodes.has(node)) {
28692
- continue;
28726
+ if (skipVisited === 'enter-only') {
28727
+ // fire enter/leave for this occurrence, but don't re-descend
28728
+ revisitNoDescend = true;
28729
+ } else {
28730
+ continue;
28731
+ }
28732
+ } else {
28733
+ visitedNodes.add(node);
28693
28734
  }
28694
- visitedNodes.add(node);
28695
28735
  }
28696
28736
 
28697
28737
  // Always create Path for the current node (needed for parentPath chain)
28698
28738
  currentPath = new _Path_mjs__WEBPACK_IMPORTED_MODULE_2__.Path(node, parent, parentPath, key, inArray);
28739
+ currentPath.revisited = revisitNoDescend;
28699
28740
  const visitFn = (0,_visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.getVisitFn)(visitor, nodeTypeGetter(node), isLeaving);
28700
28741
  if (visitFn) {
28701
28742
  // Assign state to visitor
@@ -28759,10 +28800,13 @@ function* traverseGenerator(root, visitor, options) {
28759
28800
  keys,
28760
28801
  edits,
28761
28802
  parentPath,
28803
+ revisitNoDescend,
28762
28804
  prev: stack
28763
28805
  };
28764
28806
  inArray = Array.isArray(node);
28765
- if (inArray) {
28807
+ if (revisitNoDescend) {
28808
+ keys = [];
28809
+ } else if (inArray) {
28766
28810
  keys = node;
28767
28811
  } else if (keyMapIsFunction) {
28768
28812
  keys = keyMap(node);
@@ -28837,7 +28881,7 @@ const traverse = (root, visitor, options = {}) => {
28837
28881
  nodePredicate: options.nodePredicate ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.isNode,
28838
28882
  nodeCloneFn: options.nodeCloneFn ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.cloneNode,
28839
28883
  detectCycles: options.detectCycles ?? true,
28840
- skipVisited: options.skipVisited ?? false,
28884
+ skipVisited: normalizeSkipVisited(options.skipVisited),
28841
28885
  mutable: options.mutable ?? false,
28842
28886
  mutationFn: options.mutationFn ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.mutateNode
28843
28887
  };
@@ -28869,7 +28913,7 @@ const traverseAsync = async (root, visitor, options = {}) => {
28869
28913
  nodePredicate: options.nodePredicate ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.isNode,
28870
28914
  nodeCloneFn: options.nodeCloneFn ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.cloneNode,
28871
28915
  detectCycles: options.detectCycles ?? true,
28872
- skipVisited: options.skipVisited ?? false,
28916
+ skipVisited: normalizeSkipVisited(options.skipVisited),
28873
28917
  mutable: options.mutable ?? false,
28874
28918
  mutationFn: options.mutationFn ?? _visitors_mjs__WEBPACK_IMPORTED_MODULE_3__.mutateNode
28875
28919
  };
@@ -29337,7 +29381,9 @@ mergeVisitors[Symbol.for('nodejs.util.promisify.custom')] = mergeVisitorsAsync;
29337
29381
  * @internal
29338
29382
  */
29339
29383
  function createPathProxy(originalPath, currentNode) {
29340
- return new _Path_mjs__WEBPACK_IMPORTED_MODULE_4__.Path(currentNode, originalPath.parent, originalPath.parentPath, originalPath.key, originalPath.inList);
29384
+ const proxy = new _Path_mjs__WEBPACK_IMPORTED_MODULE_4__.Path(currentNode, originalPath.parent, originalPath.parentPath, originalPath.key, originalPath.inList);
29385
+ proxy.revisited = originalPath.revisited;
29386
+ return proxy;
29341
29387
  }
29342
29388
 
29343
29389
  /***/ }