sh-ast 0.6.1 → 0.8.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.
Files changed (48) hide show
  1. package/README.md +147 -15
  2. package/dist/analyze/enumerate-commands.d.ts +5 -1
  3. package/dist/analyze/enumerate-commands.d.ts.map +1 -1
  4. package/dist/analyze/enumerate-commands.js.map +1 -1
  5. package/dist/analyze/index.d.ts +10 -2
  6. package/dist/analyze/index.d.ts.map +1 -1
  7. package/dist/analyze/index.js +11 -1
  8. package/dist/analyze/index.js.map +1 -1
  9. package/dist/analyze/resolve-argv0.d.ts +225 -16
  10. package/dist/analyze/resolve-argv0.d.ts.map +1 -1
  11. package/dist/analyze/resolve-argv0.js +372 -11
  12. package/dist/analyze/resolve-argv0.js.map +1 -1
  13. package/dist/analyze.d.ts +380 -157
  14. package/dist/errors.d.ts +14 -27
  15. package/dist/errors.d.ts.map +1 -1
  16. package/dist/errors.js +15 -28
  17. package/dist/errors.js.map +1 -1
  18. package/dist/sh-ast.d.ts +28 -32
  19. package/dist/syntax-operator.d.ts +9 -0
  20. package/dist/syntax-operator.d.ts.map +1 -0
  21. package/dist/syntax-operator.js +22 -0
  22. package/dist/syntax-operator.js.map +1 -0
  23. package/dist/syntax-print.d.ts +3 -1
  24. package/dist/syntax-print.d.ts.map +1 -1
  25. package/dist/syntax-print.js +3 -1
  26. package/dist/syntax-print.js.map +1 -1
  27. package/dist/syntax-snapshot.d.ts +4 -1
  28. package/dist/syntax-snapshot.d.ts.map +1 -1
  29. package/dist/syntax-snapshot.js +18 -3
  30. package/dist/syntax-snapshot.js.map +1 -1
  31. package/dist/syntax-wire.d.ts +12 -0
  32. package/dist/syntax-wire.d.ts.map +1 -1
  33. package/dist/syntax-wire.js +99 -15
  34. package/dist/syntax-wire.js.map +1 -1
  35. package/dist/syntax.d.ts +12 -10
  36. package/dist/syntax.d.ts.map +1 -1
  37. package/dist/syntax.js +46 -33
  38. package/dist/syntax.js.map +1 -1
  39. package/dist/wasm-instance.d.ts +8 -0
  40. package/dist/wasm-instance.d.ts.map +1 -1
  41. package/dist/wasm-instance.js +36 -8
  42. package/dist/wasm-instance.js.map +1 -1
  43. package/package.json +1 -1
  44. package/shim/sh-ast.wasm +0 -0
  45. package/dist/parse-depth-guard.d.ts +0 -11
  46. package/dist/parse-depth-guard.d.ts.map +0 -1
  47. package/dist/parse-depth-guard.js +0 -633
  48. package/dist/parse-depth-guard.js.map +0 -1
package/dist/errors.d.ts CHANGED
@@ -50,41 +50,28 @@ export declare class ShAnalyzeMaxDepthError extends ShAstError {
50
50
  constructor(maxDepth: number);
51
51
  }
52
52
  /**
53
- * Thrown by {@link parseSync} when `text`'s conservatively estimated
54
- * structural nesting depth (subshells, command/process substitutions,
55
- * `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
56
- * command substitution, `$((...))` arithmetic — see
57
- * `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
58
- * limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
59
- * WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
60
- * for exhausting its call stack on pathologically deep input (a stack
61
- * overflow deep inside the shared WASM instance is not a normal, catchable
62
- * JS error the way a parse syntax error is), so this bridge estimates the
63
- * risk up front and fails closed with a typed error instead of ever making
64
- * that call — the shared WASM instance is therefore never put at risk of
65
- * wedging on this class of input; a `parseSync` call right after catching
66
- * this error works exactly as it would if this input had never been
67
- * attempted.
53
+ * A whole-file parse operation exceeded the binding's native node-nesting budget.
54
+ * The maintained parser counts statement, word, and expression work, including
55
+ * iterative construction of deep operator trees. A refusal returns no partial
56
+ * File or position snapshot and leaves subsequent parse calls available.
68
57
  *
69
- * Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
70
- * protection, not a normal-usage ceiling: a legitimately deep (but
71
- * realistic) script parses fine. The estimate can *over*-count relative to
72
- * mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
73
- * input) but is designed to never *under*-count relative to it — see
74
- * `parse-depth-guard.ts` for the documented false-positive sources this
75
- * trades off against ever letting a genuinely crash-inducing input
76
- * through.
58
+ * This is a binding resource constraint, not an upstream grammar restriction.
59
+ * The fixed 128-unit policy can refuse valid deeply nested input. Units describe
60
+ * native node work, not actual Go/JavaScript frames or necessarily final AST
61
+ * depth. The empirical margin assumes an ordinary caller stack; arbitrary
62
+ * pre-existing JavaScript recursion can exhaust it. This does not establish
63
+ * safety for arbitrary caller-constructed trees or other recursive operations.
77
64
  *
78
65
  * @public
79
66
  */
80
67
  export declare class ShParseMaxDepthError extends ShAstError {
81
68
  readonly code = "SH_AST_PARSE_MAX_DEPTH";
82
- /** The maximum structural nesting depth `parseSync` accepts; the same value every time (not caller-configurable). */
69
+ /** Fixed maximum native node-nesting units; not caller-configurable. */
83
70
  readonly maxDepth: number;
84
71
  /**
85
- * The conservatively estimated nesting depth that tripped the guard.
86
- * Not necessarily `text`'s "true" nesting depth under a real parse — see
87
- * {@link ShParseMaxDepthError}'s doc comment — only ever `> maxDepth`.
72
+ * Native node work at the rejected entry, greater than {@link ShParseMaxDepthError.maxDepth}.
73
+ * The historical field name is retained for compatibility; the value is no
74
+ * longer a lexical estimate and is not a count of runtime stack frames.
88
75
  */
89
76
  readonly estimatedDepth: number;
90
77
  constructor(maxDepth: number, estimatedDepth: number);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;GAKG;AACH,8BAAsB,UAAW,SAAQ,KAAK;IAC5C,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,QAAQ,CAAC,IAAI,qBAAqB;gBAEtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,sBAAuB,SAAQ,UAAU;IACpD,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,mHAAmH;IACnH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;CAO7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,qHAAqH;IACrH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAQrD;AAED;;;;;;;;;;GAUG;AACH,qBAAa,gCAAiC,SAAQ,UAAU;IAC9D,QAAQ,CAAC,IAAI,yCAAyC;gBAE1C,OAAO,EAAE,MAAM;CAI5B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;GAKG;AACH,8BAAsB,UAAW,SAAQ,KAAK;IAC5C,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,QAAQ,CAAC,IAAI,qBAAqB;gBAEtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,sBAAuB,SAAQ,UAAU;IACpD,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,mHAAmH;IACnH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM;CAO7B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAQrD;AAED;;;;;;;;;;GAUG;AACH,qBAAa,gCAAiC,SAAQ,UAAU;IAC9D,QAAQ,CAAC,IAAI,yCAAyC;gBAE1C,OAAO,EAAE,MAAM;CAI5B"}
package/dist/errors.js CHANGED
@@ -55,45 +55,32 @@ export class ShAnalyzeMaxDepthError extends ShAstError {
55
55
  }
56
56
  }
57
57
  /**
58
- * Thrown by {@link parseSync} when `text`'s conservatively estimated
59
- * structural nesting depth (subshells, command/process substitutions,
60
- * `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
61
- * command substitution, `$((...))` arithmetic — see
62
- * `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
63
- * limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
64
- * WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
65
- * for exhausting its call stack on pathologically deep input (a stack
66
- * overflow deep inside the shared WASM instance is not a normal, catchable
67
- * JS error the way a parse syntax error is), so this bridge estimates the
68
- * risk up front and fails closed with a typed error instead of ever making
69
- * that call — the shared WASM instance is therefore never put at risk of
70
- * wedging on this class of input; a `parseSync` call right after catching
71
- * this error works exactly as it would if this input had never been
72
- * attempted.
58
+ * A whole-file parse operation exceeded the binding's native node-nesting budget.
59
+ * The maintained parser counts statement, word, and expression work, including
60
+ * iterative construction of deep operator trees. A refusal returns no partial
61
+ * File or position snapshot and leaves subsequent parse calls available.
73
62
  *
74
- * Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
75
- * protection, not a normal-usage ceiling: a legitimately deep (but
76
- * realistic) script parses fine. The estimate can *over*-count relative to
77
- * mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
78
- * input) but is designed to never *under*-count relative to it — see
79
- * `parse-depth-guard.ts` for the documented false-positive sources this
80
- * trades off against ever letting a genuinely crash-inducing input
81
- * through.
63
+ * This is a binding resource constraint, not an upstream grammar restriction.
64
+ * The fixed 128-unit policy can refuse valid deeply nested input. Units describe
65
+ * native node work, not actual Go/JavaScript frames or necessarily final AST
66
+ * depth. The empirical margin assumes an ordinary caller stack; arbitrary
67
+ * pre-existing JavaScript recursion can exhaust it. This does not establish
68
+ * safety for arbitrary caller-constructed trees or other recursive operations.
82
69
  *
83
70
  * @public
84
71
  */
85
72
  export class ShParseMaxDepthError extends ShAstError {
86
73
  code = 'SH_AST_PARSE_MAX_DEPTH';
87
- /** The maximum structural nesting depth `parseSync` accepts; the same value every time (not caller-configurable). */
74
+ /** Fixed maximum native node-nesting units; not caller-configurable. */
88
75
  maxDepth;
89
76
  /**
90
- * The conservatively estimated nesting depth that tripped the guard.
91
- * Not necessarily `text`'s "true" nesting depth under a real parse — see
92
- * {@link ShParseMaxDepthError}'s doc comment — only ever `> maxDepth`.
77
+ * Native node work at the rejected entry, greater than {@link ShParseMaxDepthError.maxDepth}.
78
+ * The historical field name is retained for compatibility; the value is no
79
+ * longer a lexical estimate and is not a count of runtime stack frames.
93
80
  */
94
81
  estimatedDepth;
95
82
  constructor(maxDepth, estimatedDepth) {
96
- super(`parseSync: input's estimated structural nesting depth (${String(estimatedDepth)}+ frames) exceeds the maximum this bridge accepts (${String(maxDepth)}) — refusing to hand this input to the WASM parser, which would risk exhausting its call stack uncatchably. Treat this as a deny signal, not "input looks fine".`);
83
+ super(`parseSync: native parser node work (${String(estimatedDepth)} units) exceeds the maximum this bridge accepts (${String(maxDepth)}) — refusing this input without a partial result.`);
97
84
  this.name = 'ShParseMaxDepthError';
98
85
  this.maxDepth = maxDepth;
99
86
  this.estimatedDepth = estimatedDepth;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;GAKG;AACH,MAAM,OAAgB,UAAW,SAAQ,KAAK;CAG7C;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IACpC,IAAI,GAAG,iBAAiB,CAAC;IAElC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,sBAAuB,SAAQ,UAAU;IAC3C,IAAI,GAAG,0BAA0B,CAAC;IAC3C,mHAAmH;IAC1G,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC1B,KAAK,CACH,+EAA+E,MAAM,CAAC,QAAQ,CAAC,uGAAuG,CACvM,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IACzC,IAAI,GAAG,wBAAwB,CAAC;IACzC,qHAAqH;IAC5G,QAAQ,CAAS;IAC1B;;;;OAIG;IACM,cAAc,CAAS;IAEhC,YAAY,QAAgB,EAAE,cAAsB;QAClD,KAAK,CACH,0DAA0D,MAAM,CAAC,cAAc,CAAC,sDAAsD,MAAM,CAAC,QAAQ,CAAC,kKAAkK,CACzT,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,gCAAiC,SAAQ,UAAU;IACrD,IAAI,GAAG,qCAAqC,CAAC;IAEtD,YAAY,OAAe;QACzB,KAAK,CAAC,qDAAqD,OAAO,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,kCAAkC,CAAC;IACjD,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;GAKG;AACH,MAAM,OAAgB,UAAW,SAAQ,KAAK;CAG7C;AAED;;;;;;;;;GASG;AACH,MAAM,OAAO,eAAgB,SAAQ,UAAU;IACpC,IAAI,GAAG,iBAAiB,CAAC;IAElC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,sBAAuB,SAAQ,UAAU;IAC3C,IAAI,GAAG,0BAA0B,CAAC;IAC3C,mHAAmH;IAC1G,QAAQ,CAAS;IAE1B,YAAY,QAAgB;QAC1B,KAAK,CACH,+EAA+E,MAAM,CAAC,QAAQ,CAAC,uGAAuG,CACvM,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IACzC,IAAI,GAAG,wBAAwB,CAAC;IACzC,wEAAwE;IAC/D,QAAQ,CAAS;IAC1B;;;;OAIG;IACM,cAAc,CAAS;IAEhC,YAAY,QAAgB,EAAE,cAAsB;QAClD,KAAK,CACH,uCAAuC,MAAM,CAAC,cAAc,CAAC,oDAAoD,MAAM,CAAC,QAAQ,CAAC,mDAAmD,CACrL,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,gCAAiC,SAAQ,UAAU;IACrD,IAAI,GAAG,qCAAqC,CAAC;IAEtD,YAAY,OAAe;QACzB,KAAK,CAAC,qDAAqD,OAAO,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,GAAG,kCAAkC,CAAC;IACjD,CAAC;CACF"}
package/dist/sh-ast.d.ts CHANGED
@@ -2263,8 +2263,12 @@ export declare interface ParseOptions {
2263
2263
 
2264
2264
  /**
2265
2265
  * Parses exact source bytes, or well-formed Unicode text encoded as UTF-8. First
2266
- * use synchronously initializes WASM. The existing conservative nesting guard is
2267
- * an explicit binding resource limit, not an upstream grammar restriction.
2266
+ * use synchronously initializes WASM. Native node-nesting work has a fixed binding
2267
+ * resource budget; exceeding it throws {@link ShParseMaxDepthError}. Subsequent
2268
+ * parse calls remain usable after that refusal.
2269
+ * The returned File and its Node subtrees are plain syntax data: ordinary
2270
+ * structuredClone(node), without transfers, makes an independent editable copy
2271
+ * while retaining position values, byte strings, typed nils and internal aliases.
2268
2272
  * @public
2269
2273
  */
2270
2274
  export declare function parseSync(source: string | Uint8Array, options?: ParseOptions): File_2;
@@ -2307,7 +2311,10 @@ export declare const Plus: 81;
2307
2311
 
2308
2312
  /**
2309
2313
  * Identity-based lookup of the original parse's bounds. A new or copied node has
2310
- * no observation. The index never calls WASM or recalculates edited node bounds.
2314
+ * no observation, including every node in a structuredClone of the syntax tree.
2315
+ * Clone File or a Node subtree, not this function-bearing lookup. Copied position
2316
+ * fields retain their values but do not transfer snapshot identity.
2317
+ * The index never calls WASM or recalculates edited node bounds.
2311
2318
  * @public
2312
2319
  */
2313
2320
  export declare interface PositionSnapshot {
@@ -2398,7 +2405,9 @@ export declare class PrintPanicError extends ShAstError {
2398
2405
  /**
2399
2406
  * Formats the current tree with a fresh upstream printer and collects all output.
2400
2407
  * Supported roots are File, Stmt, Word, Assign, Command and WordPart; other Nodes
2401
- * produce PrintError. Only File output has upstream's trailing-newline behavior.
2408
+ * produce PrintError. An ordinary structuredClone of a supported syntax subtree
2409
+ * is accepted under the same input and failure rules; copying does not make nil
2410
+ * or unsupported roots printable. Only File output has upstream's trailing-newline behavior.
2402
2411
  * Invalid UTF-8 output remains bytes. Upstream formatting can itself consume
2403
2412
  * input bytes, including its tabwriter escape byte, so this is not source replay.
2404
2413
  *
@@ -2827,41 +2836,28 @@ export declare const Shl: 71;
2827
2836
  export declare const ShlAssgn: 57;
2828
2837
 
2829
2838
  /**
2830
- * Thrown by {@link parseSync} when `text`'s conservatively estimated
2831
- * structural nesting depth (subshells, command/process substitutions,
2832
- * `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
2833
- * command substitution, `$((...))` arithmetic — see
2834
- * `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
2835
- * limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
2836
- * WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
2837
- * for exhausting its call stack on pathologically deep input (a stack
2838
- * overflow deep inside the shared WASM instance is not a normal, catchable
2839
- * JS error the way a parse syntax error is), so this bridge estimates the
2840
- * risk up front and fails closed with a typed error instead of ever making
2841
- * that call — the shared WASM instance is therefore never put at risk of
2842
- * wedging on this class of input; a `parseSync` call right after catching
2843
- * this error works exactly as it would if this input had never been
2844
- * attempted.
2845
- *
2846
- * Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
2847
- * protection, not a normal-usage ceiling: a legitimately deep (but
2848
- * realistic) script parses fine. The estimate can *over*-count relative to
2849
- * mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
2850
- * input) but is designed to never *under*-count relative to it — see
2851
- * `parse-depth-guard.ts` for the documented false-positive sources this
2852
- * trades off against ever letting a genuinely crash-inducing input
2853
- * through.
2839
+ * A whole-file parse operation exceeded the binding's native node-nesting budget.
2840
+ * The maintained parser counts statement, word, and expression work, including
2841
+ * iterative construction of deep operator trees. A refusal returns no partial
2842
+ * File or position snapshot and leaves subsequent parse calls available.
2843
+ *
2844
+ * This is a binding resource constraint, not an upstream grammar restriction.
2845
+ * The fixed 128-unit policy can refuse valid deeply nested input. Units describe
2846
+ * native node work, not actual Go/JavaScript frames or necessarily final AST
2847
+ * depth. The empirical margin assumes an ordinary caller stack; arbitrary
2848
+ * pre-existing JavaScript recursion can exhaust it. This does not establish
2849
+ * safety for arbitrary caller-constructed trees or other recursive operations.
2854
2850
  *
2855
2851
  * @public
2856
2852
  */
2857
2853
  export declare class ShParseMaxDepthError extends ShAstError {
2858
2854
  readonly code = "SH_AST_PARSE_MAX_DEPTH";
2859
- /** The maximum structural nesting depth `parseSync` accepts; the same value every time (not caller-configurable). */
2855
+ /** Fixed maximum native node-nesting units; not caller-configurable. */
2860
2856
  readonly maxDepth: number;
2861
2857
  /**
2862
- * The conservatively estimated nesting depth that tripped the guard.
2863
- * Not necessarily `text`'s "true" nesting depth under a real parse — see
2864
- * {@link ShParseMaxDepthError}'s doc comment — only ever `> maxDepth`.
2858
+ * Native node work at the rejected entry, greater than {@link ShParseMaxDepthError.maxDepth}.
2859
+ * The historical field name is retained for compatibility; the value is no
2860
+ * longer a lexical estimate and is not a count of runtime stack frames.
2865
2861
  */
2866
2862
  readonly estimatedDepth: number;
2867
2863
  constructor(maxDepth: number, estimatedDepth: number);
@@ -0,0 +1,9 @@
1
+ import type { OperatorFamily, RawOperator } from '../generated/syntax-constants.js';
2
+ /**
3
+ * Represents an unnamed value in an upstream uint32 operator family. Named
4
+ * constants remain precise literal unions; this explicit path preserves other Go
5
+ * values without claiming an operation such as Print accepts them.
6
+ * @public
7
+ */
8
+ export declare function rawOperator<Family extends OperatorFamily>(family: Family, value: number): RawOperator<Family>;
9
+ //# sourceMappingURL=syntax-operator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntax-operator.d.ts","sourceRoot":"","sources":["../src/syntax-operator.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAGpF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,SAAS,cAAc,EACvD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,MAAM,CAAC,CAarB"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Validates unnamed operator values against the faithful field domains. This
3
+ * shared constructor owns numeric branding only; it does not parse syntax or
4
+ * promise that an upstream operation accepts every representable operator.
5
+ */
6
+ import { SYNTAX_SCHEMA } from '../generated/syntax-schema.js';
7
+ import { InputError } from './syntax-errors.js';
8
+ /**
9
+ * Represents an unnamed value in an upstream uint32 operator family. Named
10
+ * constants remain precise literal unions; this explicit path preserves other Go
11
+ * values without claiming an operation such as Print accepts them.
12
+ * @public
13
+ */
14
+ export function rawOperator(family, value) {
15
+ const knownFamily = Object.values(SYNTAX_SCHEMA).some((record) => Object.values(record.fields).some((field) => field.kind === 'operator' && field.type === family));
16
+ if (!knownFamily || !Number.isInteger(value) || value < 0 || value > 0xffff_ffff) {
17
+ throw new InputError('An operator value must belong to a known family and be an integral uint32');
18
+ }
19
+ // The runtime check establishes the opaque numeric brand; no value is changed.
20
+ return value;
21
+ }
22
+ //# sourceMappingURL=syntax-operator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntax-operator.js","sourceRoot":"","sources":["../src/syntax-operator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,KAAa;IAEb,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC/D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAC9D,CACF,CAAC;IACF,IAAI,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,WAAW,EAAE,CAAC;QACjF,MAAM,IAAI,UAAU,CAClB,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,+EAA+E;IAC/E,OAAO,KAA4B,CAAC;AACtC,CAAC"}
@@ -34,7 +34,9 @@ export interface PrintOptions {
34
34
  /**
35
35
  * Formats the current tree with a fresh upstream printer and collects all output.
36
36
  * Supported roots are File, Stmt, Word, Assign, Command and WordPart; other Nodes
37
- * produce PrintError. Only File output has upstream's trailing-newline behavior.
37
+ * produce PrintError. An ordinary structuredClone of a supported syntax subtree
38
+ * is accepted under the same input and failure rules; copying does not make nil
39
+ * or unsupported roots printable. Only File output has upstream's trailing-newline behavior.
38
40
  * Invalid UTF-8 output remains bytes. Upstream formatting can itself consume
39
41
  * input bytes, including its tabwriter escape byte, so this is not source replay.
40
42
  *
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-print.d.ts","sourceRoot":"","sources":["../src/syntax-print.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAOnE;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,wFAAwF;IACxF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAoC1E"}
1
+ {"version":3,"file":"syntax-print.d.ts","sourceRoot":"","sources":["../src/syntax-print.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAOnE;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,wFAAwF;IACxF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wFAAwF;IACxF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yFAAyF;IACzF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAoC1E"}
@@ -6,7 +6,9 @@ import { callSyntax } from './wasm-instance.js';
6
6
  /**
7
7
  * Formats the current tree with a fresh upstream printer and collects all output.
8
8
  * Supported roots are File, Stmt, Word, Assign, Command and WordPart; other Nodes
9
- * produce PrintError. Only File output has upstream's trailing-newline behavior.
9
+ * produce PrintError. An ordinary structuredClone of a supported syntax subtree
10
+ * is accepted under the same input and failure rules; copying does not make nil
11
+ * or unsupported roots printable. Only File output has upstream's trailing-newline behavior.
10
12
  * Invalid UTF-8 output remains bytes. Upstream formatting can itself consume
11
13
  * input bytes, including its tabwriter escape byte, so this is not source replay.
12
14
  *
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-print.js","sourceRoot":"","sources":["../src/syntax-print.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"syntax-print.js","sourceRoot":"","sources":["../src/syntax-print.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,10 @@ export interface NodePositions {
12
12
  }
13
13
  /**
14
14
  * Identity-based lookup of the original parse's bounds. A new or copied node has
15
- * no observation. The index never calls WASM or recalculates edited node bounds.
15
+ * no observation, including every node in a structuredClone of the syntax tree.
16
+ * Clone File or a Node subtree, not this function-bearing lookup. Copied position
17
+ * fields retain their values but do not transfer snapshot identity.
18
+ * The index never calls WASM or recalculates edited node bounds.
16
19
  * @public
17
20
  */
18
21
  export interface PositionSnapshot {
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-snapshot.d.ts","sourceRoot":"","sources":["../src/syntax-snapshot.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAY,IAAI,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAKpF;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACtC;AAuED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,OAAO,GACjB,gBAAgB,CA4DlB"}
1
+ {"version":3,"file":"syntax-snapshot.d.ts","sourceRoot":"","sources":["../src/syntax-snapshot.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAY,IAAI,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAKpF;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,aAAa,GAAG,SAAS,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACtC;AAyFD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,OAAO,GACjB,gBAAgB,CA4DlB"}
@@ -31,9 +31,7 @@ function visitNodes(file, observe) {
31
31
  observe(value);
32
32
  if (!Object.hasOwn(SYNTAX_SCHEMA, value.Type))
33
33
  return;
34
- for (const [name, field] of Object.entries(SYNTAX_SCHEMA[value.Type].fields)) {
35
- if (field.kind !== 'struct' && field.kind !== 'interface')
36
- continue;
34
+ for (const name of childFields(value.Type)) {
37
35
  const child = value[name];
38
36
  if (Array.isArray(child))
39
37
  child.forEach(visit);
@@ -43,6 +41,23 @@ function visitNodes(file, observe) {
43
41
  };
44
42
  visit(file);
45
43
  }
44
+ /**
45
+ * Child-bearing (struct or interface) field names per record type, in schema
46
+ * order. The generated schema is immutable, so each list is derived once rather
47
+ * than re-filtering every field of every visited record.
48
+ */
49
+ const CHILD_FIELDS = new Map();
50
+ /** Returns the cached child field names for a type known to be in the schema. */
51
+ function childFields(type) {
52
+ let names = CHILD_FIELDS.get(type);
53
+ if (names === undefined) {
54
+ names = Object.entries(SYNTAX_SCHEMA[type].fields)
55
+ .filter(([, field]) => field.kind === 'struct' || field.kind === 'interface')
56
+ .map(([name]) => name);
57
+ CHILD_FIELDS.set(type, names);
58
+ }
59
+ return names;
60
+ }
46
61
  /** Own byte-bearing failures so neither transport holders nor catchers can alter captures. */
47
62
  function copyError(error) {
48
63
  return typeof error === 'string' ? error : error.slice();
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-snapshot.js","sourceRoot":"","sources":["../src/syntax-snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"syntax-snapshot.js","sourceRoot":"","sources":["../src/syntax-snapshot.ts"],"names":[],"mappings":"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"}
@@ -30,4 +30,16 @@ export declare function isSyntaxPos(value: unknown): value is SyntaxPos;
30
30
  export declare function isSyntaxNode(value: unknown): value is Node;
31
31
  /** The public parser's root is the precise upstream File representation. @internal */
32
32
  export declare function isSyntaxFile(value: unknown): value is File;
33
+ /**
34
+ * Validates a parse response's File exactly as isSyntaxFile does while rebuilding
35
+ * its positions. The bridge spells each File position as a compact
36
+ * [Offset, Line, Col, Flags] tuple (flags: bit 0 IsValid, bit 1 IsRecovered,
37
+ * bit 2 OffsetOverflow) because positions are most of a parse response. Each
38
+ * tuple is replaced in place by the identical six-member SyntaxPos record, in
39
+ * its usual member order, and then checked like any other position. Only a
40
+ * freshly decoded response may be passed: the graph is mutated, and a false
41
+ * result can leave it partly restored, so callers must discard it.
42
+ * @internal
43
+ */
44
+ export declare function restoreSyntaxFile(value: unknown): value is File;
33
45
  //# sourceMappingURL=syntax-wire.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syntax-wire.d.ts","sourceRoot":"","sources":["../src/syntax-wire.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEpF,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CASvD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAgCjD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAyChD;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAwB9D;AA4ED,sGAAsG;AACtG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAS1D;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAE1D"}
1
+ {"version":3,"file":"syntax-wire.d.ts","sourceRoot":"","sources":["../src/syntax-wire.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEpF,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CASvD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAgCjD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA0ChD;AAsCD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAwB9D;AA+GD,sGAAsG;AACtG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAS1D;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAE1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAE/D"}
@@ -80,6 +80,8 @@ export function decodeWire(text) {
80
80
  catch (cause) {
81
81
  throw new ShInternalError(`Invalid syntax bridge JSON: ${String(cause)}`);
82
82
  }
83
+ if (!mayContainBytesTag(text))
84
+ return parsed;
83
85
  const visit = (item) => {
84
86
  if (Array.isArray(item)) {
85
87
  for (let index = 0; index < item.length; index++) {
@@ -117,6 +119,39 @@ export function decodeWire(text) {
117
119
  };
118
120
  return visit(parsed);
119
121
  }
122
+ /**
123
+ * Reports whether bridge JSON can contain a Bytes member. The Go producer spells
124
+ * every ASCII key literally (encoding/json escapes only quotes, backslashes,
125
+ * controls, HTML metacharacters and line separators), so a Bytes key always
126
+ * appears as the exact characters `"Bytes"`. Their absence therefore proves no
127
+ * record needs byte restoration. Their presence, including an ordinary string
128
+ * value spelled Bytes, only selects the complete restoration walk.
129
+ */
130
+ function mayContainBytesTag(text) {
131
+ return text.includes('"Bytes"');
132
+ }
133
+ /** Decodes one compact position tuple, or returns undefined when it is malformed. */
134
+ function positionFromTuple(tuple) {
135
+ if (tuple.length !== 4)
136
+ return undefined;
137
+ const [Offset, Line, Col, flags] = tuple;
138
+ if (typeof Offset !== 'number' ||
139
+ typeof Line !== 'number' ||
140
+ typeof Col !== 'number' ||
141
+ typeof flags !== 'number' ||
142
+ !Number.isInteger(flags) ||
143
+ flags < 0 ||
144
+ flags > 7)
145
+ return undefined;
146
+ return {
147
+ Offset,
148
+ Line,
149
+ Col,
150
+ IsValid: (flags & 1) !== 0,
151
+ IsRecovered: (flags & 2) !== 0,
152
+ OffsetOverflow: (flags & 4) !== 0,
153
+ };
154
+ }
120
155
  /** A Go string is text only when every original byte is valid UTF-8. @internal */
121
156
  export function isGoString(value) {
122
157
  return typeof value === 'string' || value instanceof Uint8Array;
@@ -161,34 +196,67 @@ function isTypedNil(value, implementers) {
161
196
  * Validates complete records against the pinned schema, including nil-bearing
162
197
  * boundaries. This is a boundary check, not a semantic shell interpretation.
163
198
  */
164
- function matchesRecord(value, active) {
165
- if (!isRecord(value) || typeof value.Type !== 'string' || active.has(value))
199
+ function matchesRecord(value, check) {
200
+ if (!isRecord(value) || typeof value.Type !== 'string' || check.active?.has(value))
166
201
  return false;
167
202
  if (!Object.hasOwn(SYNTAX_SCHEMA, value.Type))
168
203
  return false;
169
- const descriptor = SYNTAX_SCHEMA[value.Type];
170
- if (Object.keys(value).length !== Object.keys(descriptor.fields).length + 1)
204
+ const fields = fieldEntries(value.Type);
205
+ if (Object.keys(value).length !== fields.length + 1)
171
206
  return false;
172
- active.add(value);
207
+ check.active?.add(value);
173
208
  try {
174
- return Object.entries(descriptor.fields).every(([name, field]) => Object.hasOwn(value, name) && matchesField(value[name], field, active));
209
+ for (const [name, field] of fields) {
210
+ if (!Object.hasOwn(value, name))
211
+ return false;
212
+ let child = value[name];
213
+ if (check.restore && field.kind === 'position' && Array.isArray(child)) {
214
+ const position = positionFromTuple(child);
215
+ if (position === undefined)
216
+ return false;
217
+ value[name] = child = position;
218
+ }
219
+ if (!matchesField(child, field, check))
220
+ return false;
221
+ }
222
+ return true;
175
223
  }
176
224
  finally {
177
- active.delete(value);
225
+ check.active?.delete(value);
226
+ }
227
+ }
228
+ /**
229
+ * Field descriptors in schema order for each record type. The generated schema
230
+ * is immutable, so listing its entries once per type avoids rebuilding the same
231
+ * arrays for every record a large File contains.
232
+ */
233
+ const FIELD_ENTRIES = new Map();
234
+ /** Returns the cached field list for a type already known to be in the schema. */
235
+ function fieldEntries(type) {
236
+ let entries = FIELD_ENTRIES.get(type);
237
+ if (entries === undefined) {
238
+ entries = Object.entries(SYNTAX_SCHEMA[type].fields);
239
+ FIELD_ENTRIES.set(type, entries);
178
240
  }
241
+ return entries;
179
242
  }
180
243
  /** Checks one upstream field without conflating a nil slice with an empty one. */
181
- function matchesField(value, field, active) {
244
+ function matchesField(value, field, check) {
182
245
  if (value === null)
183
246
  return field.nullable;
184
247
  if (field.slice) {
185
- return (Array.isArray(value) &&
186
- value.every((item) => item === null ? field.elementNullable : matchesScalar(item, field, active)));
248
+ if (!Array.isArray(value))
249
+ return false;
250
+ for (const item of value) {
251
+ if (item === null ? !field.elementNullable : !matchesScalar(item, field, check))
252
+ return false;
253
+ }
254
+ return true;
187
255
  }
188
- return matchesScalar(value, field, active);
256
+ return matchesScalar(value, field, check);
189
257
  }
190
258
  /** Each scalar category retains its upstream domain rather than JS coercions. */
191
- function matchesScalar(value, field, active) {
259
+ function matchesScalar(value, field, check) {
192
260
  switch (field.kind) {
193
261
  case 'boolean':
194
262
  return typeof value === 'boolean';
@@ -199,14 +267,14 @@ function matchesScalar(value, field, active) {
199
267
  case 'operator':
200
268
  return (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 0xffff_ffff);
201
269
  case 'struct':
202
- return isRecord(value) && value.Type === field.type && matchesRecord(value, active);
270
+ return isRecord(value) && value.Type === field.type && matchesRecord(value, check);
203
271
  case 'interface':
204
272
  return (isRecord(value) &&
205
273
  typeof value.Type === 'string' &&
206
274
  field.type !== null &&
207
275
  Object.hasOwn(SYNTAX_INTERFACES, field.type) &&
208
276
  (isTypedNil(value, SYNTAX_INTERFACES[field.type]) ||
209
- (SYNTAX_INTERFACES[field.type].includes(value.Type) && matchesRecord(value, active))));
277
+ (SYNTAX_INTERFACES[field.type].includes(value.Type) && matchesRecord(value, check))));
210
278
  }
211
279
  }
212
280
  /** Narrows complete syntax.Nodes or typed nil Node interfaces; auxiliaries are excluded. @internal */
@@ -217,10 +285,26 @@ export function isSyntaxNode(value) {
217
285
  typeof value.Type === 'string' &&
218
286
  Object.hasOwn(SYNTAX_SCHEMA, value.Type) &&
219
287
  SYNTAX_SCHEMA[value.Type].node &&
220
- matchesRecord(value, new Set()));
288
+ matchesRecord(value, { active: new Set(), restore: false }));
221
289
  }
222
290
  /** The public parser's root is the precise upstream File representation. @internal */
223
291
  export function isSyntaxFile(value) {
224
292
  return isSyntaxNode(value) && value.Type === 'File';
225
293
  }
294
+ /**
295
+ * Validates a parse response's File exactly as isSyntaxFile does while rebuilding
296
+ * its positions. The bridge spells each File position as a compact
297
+ * [Offset, Line, Col, Flags] tuple (flags: bit 0 IsValid, bit 1 IsRecovered,
298
+ * bit 2 OffsetOverflow) because positions are most of a parse response. Each
299
+ * tuple is replaced in place by the identical six-member SyntaxPos record, in
300
+ * its usual member order, and then checked like any other position. Only a
301
+ * freshly decoded response may be passed: the graph is mutated, and a false
302
+ * result can leave it partly restored, so callers must discard it.
303
+ * @internal
304
+ */
305
+ export function restoreSyntaxFile(value) {
306
+ return isRecord(value) && value.Type === 'File' && matchesRecord(value, RESTORING);
307
+ }
308
+ /** Restoring validation state; it carries no per-call data and is shared. */
309
+ const RESTORING = { active: null, restore: true };
226
310
  //# sourceMappingURL=syntax-wire.js.map