sh-ast 0.3.0 → 0.3.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.
Files changed (2) hide show
  1. package/README.md +60 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -45,6 +45,66 @@ zsh`, mapped to mvdan/sh's `LangVariant` by string name.
45
45
  - `walk(node, visit)` — visits every node in a normalized tree; discovers children structurally
46
46
  rather than depending on `visitorKeys`.
47
47
 
48
+ ## Dialect enforcement
49
+
50
+ `dialect` maps directly onto mvdan/sh's `LangVariant` (`LangBash`, `LangPOSIX`, `LangMirBSDKorn`,
51
+ `LangBats`, `LangZsh`). mvdan/sh gates most dialect-specific syntax with a hard parse error
52
+ (`checkLang` in its `syntax/parser.go`) when the requested dialect isn't in that construct's
53
+ allowed set — but two dialect-specific keywords (`[[` test clauses and `let`) have **no such gate**:
54
+ outside the dialects that recognize them, they silently fall through to ordinary word/command
55
+ parsing instead of erroring. The table below is derived by hand from that source, not from
56
+ guessing at current behavior, and is pinned by `test/dialect-matrix.test.ts`.
57
+
58
+ | Construct | bash | posix | mksh | bats | zsh |
59
+ | -------------------------- | :--------: | :--------------------: | :--------: | :--------: | :----------------------------: |
60
+ | Test clause `[[ ]]` | parses | **parses** (see below) | parses | parses | parses |
61
+ | Regex test `[[ a =~ b ]]` | parses | parses\* | **error** | parses | parses |
62
+ | Array literal `a=(1 2 3)` | parses | **error** | parses | parses | parses |
63
+ | Process substitution `<()` | parses | **error** | **error** | parses | parses |
64
+ | Brace expansion `{a,b}` | parses\*\* | parses\*\* | parses\*\* | parses\*\* | parses\*\* |
65
+ | `function` keyword | parses | **error** | parses | parses | parses |
66
+ | C-style `for (( ; ; ))` | parses | **error** | **error** | parses | parses |
67
+ | Extended glob `@(a\|b)` | parses | **error** | parses | parses | parses\*\*\* (no ExtGlob node) |
68
+ | Herestring `<<<` | parses | **error** | parses | parses | parses |
69
+ | `let` clause | parses | **parses** (see below) | parses | parses | parses |
70
+
71
+ \* Under posix, `[[` is already an ordinary command word (see below), so `[[ a =~ b ]]` never
72
+ reaches the regex-test parser at all — `=~` is just another literal argument to a command named
73
+ `[[`.
74
+
75
+ \*\* Brace expansion is never split into a `BraceExp` node by this bridge, in any dialect — mvdan/sh
76
+ only produces `BraceExp` nodes when the caller explicitly runs its `syntax.SplitBraces()`
77
+ post-processing pass, which `shim/main.go` does not invoke. `{a,b}` always parses as an ordinary
78
+ `Lit` word part, identically in every dialect.
79
+
80
+ \*\*\* zsh's lexer never tokenizes `@(` as an extended-glob opener at all — deliberately, to avoid
81
+ ambiguity with zsh's own glob qualifiers like `*(N)`. So `ls @(a|b)` parses without error under
82
+ `dialect: 'zsh'`, but produces plain `Lit` word parts rather than an `ExtGlob` node; the
83
+ `checkLang` gate that rejects extended globs under posix is never reached for zsh.
84
+
85
+ ### `[[ ... ]]` and `let` under posix: accepted by design
86
+
87
+ `dialect: 'posix'` accepting `[[ a == b ]]` and `let x=1` is **intentional upstream behavior, not
88
+ a bridge bug**. POSIX sh has no `[[` test clause or `let` builtin as syntax — so mvdan/sh's parser
89
+ doesn't special-case those keywords at all outside bash-like/mksh/zsh; it falls through to
90
+ ordinary word/command parsing, exactly as a real POSIX-mode shell would tokenize `[[` as a command
91
+ name. By contrast, dialect-specific constructs that cannot be read as ordinary commands—arrays,
92
+ C-style `for`, `<()`, `<<<`, extended globs, and the `function` form—are rejected in POSIX mode,
93
+ either by an explicit `checkLang` gate or, for process substitution, after lexer fallback. A regex
94
+ operator inside `[[ a =~ b ]]` remains ordinary command text because POSIX mode never enters the
95
+ test-clause parser.
96
+
97
+ Concretely, under `dialect: 'posix'`:
98
+
99
+ ```ts
100
+ const file = parseSync('[[ a == b ]]', { dialect: 'posix' });
101
+ file.stmts[0].cmd.type; // "CallExpr" — a command literally named "[[", not "TestClause"
102
+ ```
103
+
104
+ Evidence: mvdan/sh's own test suite (`syntax/filetests_test.go`) asserts this exact shape for
105
+ `LangPOSIX`, and `shim/main.go` passes the requested dialect through to mvdan/sh's
106
+ `LangVariant.Set` unmodified — the bridge does not special-case or mis-map `[[`.
107
+
48
108
  ## Regenerating the schema tables
49
109
 
50
110
  After bumping the pinned mvdan/sh version (`shim/go.mod` _and_ `../../tools/gen-visitor-keys/go.mod`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sh-ast",
3
3
  "description": "Synchronous shell-script parser (mvdan/sh via WASM) with a normalized, UTF-16-safe AST.",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "author": "Mike North <michael.l.north@gmail.com>",
6
6
  "repository": {
7
7
  "type": "git",