sh-ast 0.7.0 → 0.9.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/dist/analyze.d.ts CHANGED
@@ -210,7 +210,10 @@ export declare interface Argv0Resolution {
210
210
  * - `'embedded-command'` — a wrapper flag whose value structurally embeds
211
211
  * the real command rather than naming it as a separate word (e.g.
212
212
  * `env -S 'rm -rf /'` — see {@link WrapperSpec.unresolvableFlags}'s doc
213
- * comment).
213
+ * comment), or a shell interpreter's `-c` option (`bash -c 'rm x'`, see
214
+ * {@link EmbeddedCommandInterpreterSpec}). In both cases the chain's
215
+ * second-to-last element is the wrapper or interpreter word, so its name
216
+ * stays available.
214
217
  * - `'ambiguous-assignment'` — a statically known assignment operand whose
215
218
  * acceptance differs across supported utility implementations, such as
216
219
  * `env =value cmd` (GNU/glibc accepts an empty name; BSD rejects it).
@@ -1292,6 +1295,38 @@ export declare interface DeclClause {
1292
1295
  Variant: Lit | null;
1293
1296
  }
1294
1297
 
1298
+ /**
1299
+ * `sh-ast/analyze`'s default {@link EmbeddedCommandInterpreterSpec} table:
1300
+ * the shells whose `-c` option makes {@link resolveArgv0} report
1301
+ * `'embedded-command'`. Each entry's option grammar is hand-derived from the
1302
+ * cited manual. Basic clusters and required operands were cross-checked on
1303
+ * Linux bash 5.2.21, dash 0.5.12, zsh 5.9, ksh93u+m 1.0.8 and mksh R59.
1304
+ * Long-option, termination and omitted-operand cases were checked on macOS
1305
+ * bash 5.3.9 and 3.2.57 (also `/bin/sh`), Apple dash-16, zsh 5.9 and ksh93u+
1306
+ * AJM 2012-08-01. Omitted `-o`/`+o` operands before another signed option
1307
+ * were confirmed only on that ksh93u+ build, not ksh93u+m or mksh. Builds can
1308
+ * differ: macOS's ksh93u+ differs from the cited 93u+m for `ksh -o c "echo X"`.
1309
+ * The `sh` entry also models bash's long options because `sh` can be bash.
1310
+ * Named options that change the option grammar itself (such as zsh's
1311
+ * `shoptionletters`) are not interpreted; a custom table is needed for that
1312
+ * grammar. It is data, not policy:
1313
+ * it names no dangerous commands and a caller can replace or extend it via
1314
+ * {@link ResolveArgv0Options.embeddedCommandInterpreters}; an empty array
1315
+ * restores the behavior in which an interpreter is an ordinary effective
1316
+ * command.
1317
+ *
1318
+ * Frozen, including each entry and its arrays.
1319
+ *
1320
+ * @see https://www.gnu.org/software/bash/manual/bash.html#Invoking-Bash — bash
1321
+ * @see https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html — POSIX `sh`
1322
+ * @see https://man7.org/linux/man-pages/man1/dash.1.html — dash(1)
1323
+ * @see https://zsh.sourceforge.io/Doc/Release/Invocation-and-Startup.html — zsh
1324
+ * @see https://github.com/ksh93/ksh — ksh93u+m `sh(1)`
1325
+ * @see https://man.mirbsd.org/mksh.1 — mksh(1)
1326
+ * @public
1327
+ */
1328
+ export declare const DEFAULT_EMBEDDED_COMMAND_INTERPRETERS: readonly EmbeddedCommandInterpreterSpec[];
1329
+
1295
1330
  /**
1296
1331
  * `sh-ast/analyze`'s default {@link WrapperSpec} table — every entry's
1297
1332
  * flag/operand handling is hand-derived from that wrapper's own manual
@@ -1374,6 +1409,115 @@ export declare const DplIn: 67;
1374
1409
  */
1375
1410
  export declare const DplOut: 68;
1376
1411
 
1412
+ /**
1413
+ * A data-only description of one shell interpreter whose `-c` option makes the
1414
+ * next operand a command string run by that shell (`bash -c 'rm x'`). Like
1415
+ * `env -S`, the command that runs lives *inside* an operand, so
1416
+ * {@link resolveArgv0} reports `'embedded-command'` instead of the
1417
+ * interpreter's own name as the effective command.
1418
+ * The selector `c` is reserved: exact-token fields (`noOperandLongOptions`,
1419
+ * `operandLongOptions`, `optionTerminatorWords`) cannot contain `-c`.
1420
+ *
1421
+ * Only the option grammar needed to decide *whether `-c` is an option* is
1422
+ * described: which options consume an operand word (so that `-o c` or
1423
+ * `-o pipefail -c` are not misread) and where option parsing ends. Everything
1424
+ * else about the interpreter — what its other options mean, whether a given
1425
+ * option name is valid — is irrelevant to that decision and unmodeled; an
1426
+ * invalid invocation that a real shell would reject is still reported
1427
+ * conservatively, since nothing is guessed about what it would run.
1428
+ *
1429
+ * Option parsing ends at the first statically known word that is not an
1430
+ * option, at `--`, at a lone `-`, or at a table-defined terminator; afterwards
1431
+ * a word shaped like `-c` is an ordinary script operand. A dynamic word in
1432
+ * option position leaves the question undecidable, so scanning stops and the interpreter is reported
1433
+ * exactly as before (its own static name). In that case `static: true` means
1434
+ * only that the interpreter's name is known; it does not mean the command is a
1435
+ * plain shell invocation, because `bash "$f" -c x` runs `x` when `$f` is `-x`.
1436
+ *
1437
+ * This shape may grow new optional fields in a **minor** release; existing
1438
+ * fields' meaning never changes.
1439
+ *
1440
+ * @public
1441
+ */
1442
+ export declare interface EmbeddedCommandInterpreterSpec {
1443
+ /**
1444
+ * The interpreter's name, matched against a static command word's final
1445
+ * path segment: `bash`, `/bin/bash` and `/usr/local/bin/bash` all match
1446
+ * `['bash']`. Only the command word is reduced to its final segment;
1447
+ * entries containing `/` (such as `['/bin/bash']`) are rejected with
1448
+ * {@link ShAnalyzeInvalidWrapperSpecError}. Use `['bash']` to recognize
1449
+ * path-qualified invocations. The first entry containing the segment wins.
1450
+ *
1451
+ * Unlike {@link WrapperSpec.names}, which tries exact names first and
1452
+ * falls back to the final segment only for absolute paths, interpreter
1453
+ * matching uses only the final segment, including for relative paths
1454
+ * such as `./bash`. The question here is whether a command string is
1455
+ * embedded, not which executable would be located.
1456
+ */
1457
+ readonly names: readonly string[];
1458
+ /**
1459
+ * Single option letters (without a sign) that take a name or value operand
1460
+ * under both `-` and `+`, e.g. `['o']` for `-o pipefail` / `+o pipefail`.
1461
+ * A letter listed here never selects the command string itself, so
1462
+ * `bash -o c script` keeps `c` as an option *name*.
1463
+ * The selector `c` is reserved and cannot be listed as an operand option;
1464
+ * conflicting entries throw {@link ShAnalyzeInvalidWrapperSpecError}.
1465
+ */
1466
+ readonly operandOptions: readonly string[];
1467
+ /**
1468
+ * How an {@link EmbeddedCommandInterpreterSpec.operandOptions} letter
1469
+ * receives its operand inside a clustered word:
1470
+ *
1471
+ * - `'separate-word'` — always the next word; remaining letters in the
1472
+ * cluster are still options (`bash -oc errexit 'cmd'` is `-o errexit -c`).
1473
+ * - `'rest-of-cluster'` — the remainder of the word if any, else the next
1474
+ * word; later letters in the same word are part of the operand
1475
+ * (`zsh -oc` names an option `c`).
1476
+ */
1477
+ readonly operandAttachment: 'separate-word' | 'rest-of-cluster';
1478
+ /**
1479
+ * Letters from {@link EmbeddedCommandInterpreterSpec.operandOptions} whose
1480
+ * separate operand may be omitted before a word beginning with `-` or `+`.
1481
+ * An attached operand still belongs to the option. For example, ksh93u+
1482
+ * treats `-o -c cmd` and `+o -c cmd` as an operand-free option listing
1483
+ * followed by `-c`; bash, dash and zsh consume `-c` as the option name.
1484
+ * A dynamic potential operand makes this distinction undecidable.
1485
+ */
1486
+ readonly optionalOperandOptions?: readonly string[];
1487
+ /**
1488
+ * No-operand letters that end option scanning after the current cluster,
1489
+ * under either sign. Remaining letters in that cluster still take effect:
1490
+ * zsh's `-b -c script` runs the file `-c`, but `-bc cmd` selects a string.
1491
+ * These letters must not include `c` or an operand-taking letter.
1492
+ */
1493
+ readonly optionTerminatorLetters?: readonly string[];
1494
+ /**
1495
+ * Additional whole words that end option scanning, like zsh's `+` and `+-`.
1496
+ * The terminator is not a command string; an already-selected `-c` needs
1497
+ * a following word. `--` and a lone `-` are always terminators.
1498
+ */
1499
+ readonly optionTerminatorWords?: readonly string[];
1500
+ /**
1501
+ * Exact long-option words that take a separate operand, recognized before
1502
+ * short-option clusters regardless of prefix: bash's `--rcfile FILE` and
1503
+ * `-rcfile FILE`, or zsh's `--emulate sh`. A dynamic operand stops scanning
1504
+ * because its expansion may produce multiple actual arguments.
1505
+ */
1506
+ readonly operandLongOptions?: readonly string[];
1507
+ /**
1508
+ * Exact long-option words with no operand, recognized before short-option
1509
+ * clusters. Bash's `-restricted` and `-noprofile` are whole long options,
1510
+ * not clusters containing `c` or `o`. Unlisted `--name` / `+-name` words
1511
+ * are also treated as operand-free; option validity is not checked.
1512
+ */
1513
+ readonly noOperandLongOptions?: readonly string[];
1514
+ /**
1515
+ * `true` if the interpreter also treats `+c` as selecting the command
1516
+ * string. Other shells do not select command mode with `+c`.
1517
+ */
1518
+ readonly plusCSelectsCommand?: boolean;
1519
+ }
1520
+
1377
1521
  /**
1378
1522
  * Enumerates every command invocation (`CallExpr`) reachable from `root`,
1379
1523
  * with its resolved words ({@link resolveWord}) and the path used to reach
@@ -2705,7 +2849,7 @@ export declare const DplOut: 68;
2705
2849
  * command) or add their own (e.g. a project's `with-retry` helper) and
2706
2850
  * both directions are followed identically to any built-in entry.
2707
2851
  *
2708
- * **A statically-unknowable word is never guessed through** — three
2852
+ * **A statically-unknowable word is never guessed through** — four
2709
2853
  * distinct cases all stop the chain immediately at that word rather than
2710
2854
  * falling back to any other guess:
2711
2855
  *
@@ -2726,6 +2870,30 @@ export declare const DplOut: 68;
2726
2870
  * reports `effective: { static: false, reason: 'embedded-command' }`
2727
2871
  * (see {@link WrapperSpec.unresolvableFlags}'s doc comment).
2728
2872
  *
2873
+ * 4. The effective command is a shell interpreter
2874
+ * ({@link DEFAULT_EMBEDDED_COMMAND_INTERPRETERS}) invoked with `-c` —
2875
+ * `bash -c "$x"`, `sudo sh -ec ls` — and the command that runs is
2876
+ * inside the string operand. The result is the same
2877
+ * `'embedded-command'` shape `env -S` produces: the interpreter word is
2878
+ * `chain.at(-2)` and `chainIndices.at(-1)` is the option word that
2879
+ * selected `-c`. `bash script.sh`, `bash -e script.sh`, `bash -- -c`
2880
+ * and `bash -o c` are not `-c` invocations and resolve to `bash` as
2881
+ * before. A dynamic word in option position (`bash "$f" -c x`,
2882
+ * `bash -c"$y" x`) is undecidable, so the interpreter stays a static
2883
+ * `bash`: `static: true` then means only that the name is known, not that
2884
+ * the command is a plain shell invocation. The `-c` string itself is never
2885
+ * parsed.
2886
+ *
2887
+ * Known limits: the table models common option spellings, not a full
2888
+ * emulation of each shell's option parser. Unusual spellings can be
2889
+ * misclassified in either direction:
2890
+ *
2891
+ * - Bash/sh single-dash long options after a short option, e.g. `bash -e -rcfile M`.
2892
+ * - `ksh -c +c M`, or a dynamic word after `-c` that expands to an option.
2893
+ * - mksh's selector-bearing operands in `mksh -o -c M` and `mksh -o +c M`.
2894
+ * - A lone `+` before `-c`, e.g. `bash + -c M`.
2895
+ * - Zsh grammar switches, e.g. `zsh -o shoptionletters -b -c M`.
2896
+ *
2729
2897
  * `VAR=val` shell-assignment prefixes on the `CallExpr` itself
2730
2898
  * (`CommandSite.node.Assigns`, e.g. `FOO=bar rm x`) are always skipped and
2731
2899
  * counted in {@link Argv0Resolution.assignmentsSkipped} — a mechanism
@@ -2740,7 +2908,8 @@ export declare const DplOut: 68;
2740
2908
  * least one argv word; see its doc comment), not a "malformed shell
2741
2909
  * source" case.
2742
2910
  * @throws {@link ShAnalyzeInvalidWrapperSpecError} if
2743
- * `options.transparentWrappers` contains a malformed entry (see
2911
+ * `options.transparentWrappers` or `options.embeddedCommandInterpreters`
2912
+ * contains a malformed entry (see
2744
2913
  * {@link ResolveArgv0Options.transparentWrappers}'s doc comment).
2745
2914
  * @public
2746
2915
  */
@@ -2767,6 +2936,19 @@ export declare const DplOut: 68;
2767
2936
  * flag matching.
2768
2937
  */
2769
2938
  readonly transparentWrappers?: readonly WrapperSpec[];
2939
+ /**
2940
+ * The shell interpreters whose `-c` operand is reported as an
2941
+ * `'embedded-command'`. Defaults to
2942
+ * {@link DEFAULT_EMBEDDED_COMMAND_INTERPRETERS}. Pass a replacement array to
2943
+ * add or drop interpreters; an empty array disables the behavior, so every
2944
+ * interpreter resolves as an ordinary effective command.
2945
+ *
2946
+ * Validated at the {@link resolveArgv0} boundary like
2947
+ * {@link ResolveArgv0Options.transparentWrappers}: the table must be an
2948
+ * array. A non-array value (including `null`) or malformed entry throws
2949
+ * {@link ShAnalyzeInvalidWrapperSpecError}; only `undefined` uses defaults.
2950
+ */
2951
+ readonly embeddedCommandInterpreters?: readonly EmbeddedCommandInterpreterSpec[];
2770
2952
  }
2771
2953
 
2772
2954
  /**
@@ -4068,22 +4250,47 @@ export declare const DplOut: 68;
4068
4250
  */
4069
4251
  export declare interface WrapperSpec {
4070
4252
  /**
4071
- * The literal, exact argv0 text (after quote/escape removal) that
4072
- * identifies this wrapper — e.g. `['env']`. Matched only against a
4073
- * `static: true` word; see {@link WrapperSpec}'s doc comment.
4253
+ * The command name that identifies this wrapper — e.g. `['env']`.
4254
+ * Matched only against a `static: true` word; see {@link WrapperSpec}'s
4255
+ * doc comment.
4256
+ *
4257
+ * Matching first searches the entire table for an exact name. Only when
4258
+ * no exact entry exists does it try an absolute path's final segment:
4074
4259
  *
4075
- * Matching is **exact-name-only** — never basename matching. `sudo` does
4076
- * not match `/usr/bin/sudo` or `./sudo`; only a word whose *entire*
4077
- * resolved text equals one of `names` is recognized. This is a
4078
- * deliberate, narrower-than-real-world policy choice (a real shell would
4079
- * happily run `/usr/bin/sudo`), not an oversight: silently treating any
4080
- * path *ending in* a known wrapper name as that wrapper would be a
4081
- * different, broader matching policy this package isn't making on a
4082
- * caller's behalf. A caller who wants path-aware matching can express it
4083
- * explicitly via a custom {@link ResolveArgv0Options.transparentWrappers}
4084
- * table (e.g. `names: ['sudo', '/usr/bin/sudo']`).
4260
+ * 1. Its entire resolved text (after quote/escape removal) equals one of
4261
+ * `names`: `env`, or a path a caller listed verbatim. An exact path
4262
+ * entry takes precedence over a plain-name entry even if listed later.
4263
+ * 2. The spec does not declare {@link WrapperSpec.shellBuiltin | shellBuiltin: true},
4264
+ * and the word is an **absolute path** (starts with `/`) whose final segment
4265
+ * equals one of `names`: `/usr/bin/env`, `/usr/bin/sudo`, `/opt/x/nice`
4266
+ * and `/usr//bin/env` resolve as `env`, `sudo` and `nice`. The chain
4267
+ * keeps the word as written, so a consumer still sees the path.
4268
+ *
4269
+ * Relative paths and paths with a trailing slash do not use the
4270
+ * final-segment fallback. They can still match an explicitly listed name,
4271
+ * such as `./with-retry` or `/opt/with-retry/`. Custom plain names also
4272
+ * acquire absolute-path aliases unless `shellBuiltin: true`; a path-only
4273
+ * name does not acquire aliases for other paths with the same final segment.
4274
+ *
4275
+ * This is a lexical analysis assumption, not executable identity:
4276
+ * `PATH` is not consulted and the filesystem is not read. Without an
4277
+ * exact override, an unrelated executable named `/opt/mytools/env` uses
4278
+ * the `env` entry's grammar. The chain preserves the original path so
4279
+ * callers can apply their own policy. A word with an expansion
4280
+ * (`"$dir/env"`) is not `static` and is never matched.
4085
4281
  */
4086
4282
  readonly names: readonly string[];
4283
+ /**
4284
+ * Whether this wrapper represents a shell builtin rather than an external
4285
+ * utility. A path cannot reach a builtin: `/tmp/command` names an external
4286
+ * executable, so its arguments must not be interpreted as builtin operands.
4287
+ * When true, only exact entries in {@link WrapperSpec.names} match; the
4288
+ * absolute-path final-segment fallback is disabled. Explicitly listed path
4289
+ * entries still match exactly. False or omitted preserves utility matching.
4290
+ * The defaults mark `command` and `exec`; custom tables may mark their own
4291
+ * builtins, such as `builtin`.
4292
+ */
4293
+ readonly shellBuiltin?: boolean;
4087
4294
  /**
4088
4295
  * Legacy shorthand for {@link WrapperSpec.assignmentOperands}'s
4089
4296
  * `'shell-identifier'` grammar: skip statically resolved `NAME=value`
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,9 @@ 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.
2268
2269
  * The returned File and its Node subtrees are plain syntax data: ordinary
2269
2270
  * structuredClone(node), without transfers, makes an independent editable copy
2270
2271
  * while retaining position values, byte strings, typed nils and internal aliases.
@@ -2835,41 +2836,28 @@ export declare const Shl: 71;
2835
2836
  export declare const ShlAssgn: 57;
2836
2837
 
2837
2838
  /**
2838
- * Thrown by {@link parseSync} when `text`'s conservatively estimated
2839
- * structural nesting depth (subshells, command/process substitutions,
2840
- * `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
2841
- * command substitution, `$((...))` arithmetic — see
2842
- * `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
2843
- * limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
2844
- * WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
2845
- * for exhausting its call stack on pathologically deep input (a stack
2846
- * overflow deep inside the shared WASM instance is not a normal, catchable
2847
- * JS error the way a parse syntax error is), so this bridge estimates the
2848
- * risk up front and fails closed with a typed error instead of ever making
2849
- * that call — the shared WASM instance is therefore never put at risk of
2850
- * wedging on this class of input; a `parseSync` call right after catching
2851
- * this error works exactly as it would if this input had never been
2852
- * attempted.
2853
- *
2854
- * Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
2855
- * protection, not a normal-usage ceiling: a legitimately deep (but
2856
- * realistic) script parses fine. The estimate can *over*-count relative to
2857
- * mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
2858
- * input) but is designed to never *under*-count relative to it — see
2859
- * `parse-depth-guard.ts` for the documented false-positive sources this
2860
- * trades off against ever letting a genuinely crash-inducing input
2861
- * 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.
2862
2850
  *
2863
2851
  * @public
2864
2852
  */
2865
2853
  export declare class ShParseMaxDepthError extends ShAstError {
2866
2854
  readonly code = "SH_AST_PARSE_MAX_DEPTH";
2867
- /** 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. */
2868
2856
  readonly maxDepth: number;
2869
2857
  /**
2870
- * The conservatively estimated nesting depth that tripped the guard.
2871
- * Not necessarily `text`'s "true" nesting depth under a real parse — see
2872
- * {@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.
2873
2861
  */
2874
2862
  readonly estimatedDepth: number;
2875
2863
  constructor(maxDepth: number, estimatedDepth: number);
@@ -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;;;;;;;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;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"}