sh-ast 0.0.0 → 0.2.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/README.md +147 -0
- package/dist/analyze/ansi-c-escapes.d.ts +53 -0
- package/dist/analyze/ansi-c-escapes.d.ts.map +1 -0
- package/dist/analyze/ansi-c-escapes.js +255 -0
- package/dist/analyze/ansi-c-escapes.js.map +1 -0
- package/dist/analyze/decode-lit.d.ts +74 -0
- package/dist/analyze/decode-lit.d.ts.map +1 -0
- package/dist/analyze/decode-lit.js +114 -0
- package/dist/analyze/decode-lit.js.map +1 -0
- package/dist/analyze/enumerate-commands.d.ts +165 -0
- package/dist/analyze/enumerate-commands.d.ts.map +1 -0
- package/dist/analyze/enumerate-commands.js +396 -0
- package/dist/analyze/enumerate-commands.js.map +1 -0
- package/dist/analyze/index.d.ts +26 -0
- package/dist/analyze/index.d.ts.map +1 -0
- package/dist/analyze/index.js +30 -0
- package/dist/analyze/index.js.map +1 -0
- package/dist/analyze/node-helpers.d.ts +28 -0
- package/dist/analyze/node-helpers.d.ts.map +1 -0
- package/dist/analyze/node-helpers.js +37 -0
- package/dist/analyze/node-helpers.js.map +1 -0
- package/dist/analyze/resolve-argv0.d.ts +335 -0
- package/dist/analyze/resolve-argv0.d.ts.map +1 -0
- package/dist/analyze/resolve-argv0.js +510 -0
- package/dist/analyze/resolve-argv0.js.map +1 -0
- package/dist/analyze/resolve-word.d.ts +151 -0
- package/dist/analyze/resolve-word.d.ts.map +1 -0
- package/dist/analyze/resolve-word.js +207 -0
- package/dist/analyze/resolve-word.js.map +1 -0
- package/dist/analyze.d.ts +771 -0
- package/dist/deep-freeze.d.ts +14 -0
- package/dist/deep-freeze.d.ts.map +1 -0
- package/dist/deep-freeze.js +25 -0
- package/dist/deep-freeze.js.map +1 -0
- package/dist/errors.d.ts +180 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +179 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize.d.ts +52 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +260 -0
- package/dist/normalize.js.map +1 -0
- package/dist/parse-depth-guard.d.ts +11 -0
- package/dist/parse-depth-guard.d.ts.map +1 -0
- package/dist/parse-depth-guard.js +633 -0
- package/dist/parse-depth-guard.js.map +1 -0
- package/dist/parse.d.ts +50 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +125 -0
- package/dist/parse.js.map +1 -0
- package/dist/sh-ast.d.ts +1346 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/visitor-keys.d.ts +21 -0
- package/dist/visitor-keys.d.ts.map +1 -0
- package/dist/visitor-keys.js +23 -0
- package/dist/visitor-keys.js.map +1 -0
- package/dist/walk.d.ts +18 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +40 -0
- package/dist/walk.js.map +1 -0
- package/dist/wasm-instance.d.ts +13 -0
- package/dist/wasm-instance.d.ts.map +1 -0
- package/dist/wasm-instance.js +88 -0
- package/dist/wasm-instance.js.map +1 -0
- package/generated/child-type-schema.d.ts +14 -0
- package/generated/child-type-schema.js +188 -0
- package/generated/node-types.d.ts +958 -0
- package/generated/position-fields.d.ts +21 -0
- package/generated/position-fields.js +50 -0
- package/generated/visitor-keys.d.ts +11 -0
- package/generated/visitor-keys.js +50 -0
- package/package.json +93 -10
- package/shim/sh-ast.wasm +0 -0
- package/shim/wasm_exec.js +654 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively freezes `value` and every object/array it (transitively)
|
|
3
|
+
* contains, so a frozen shared table's immutability holds at every level —
|
|
4
|
+
* not just its own top-level keys — rather than relying on every caller to
|
|
5
|
+
* treat it as read-only by convention.
|
|
6
|
+
*
|
|
7
|
+
* Generic, structural recursion over an unknown shape needs a cast to index
|
|
8
|
+
* into `value`'s own properties; contained to this one small, well-tested
|
|
9
|
+
* utility rather than spread across every table that uses it.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare function deepFreeze<T>(value: T): Readonly<T>;
|
|
14
|
+
//# sourceMappingURL=deep-freeze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-freeze.d.ts","sourceRoot":"","sources":["../src/deep-freeze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAWnD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively freezes `value` and every object/array it (transitively)
|
|
3
|
+
* contains, so a frozen shared table's immutability holds at every level —
|
|
4
|
+
* not just its own top-level keys — rather than relying on every caller to
|
|
5
|
+
* treat it as read-only by convention.
|
|
6
|
+
*
|
|
7
|
+
* Generic, structural recursion over an unknown shape needs a cast to index
|
|
8
|
+
* into `value`'s own properties; contained to this one small, well-tested
|
|
9
|
+
* utility rather than spread across every table that uses it.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export function deepFreeze(value) {
|
|
14
|
+
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
|
|
15
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
16
|
+
const prop = value[key];
|
|
17
|
+
if (prop !== null && typeof prop === 'object') {
|
|
18
|
+
deepFreeze(prop);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
Object.freeze(value);
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=deep-freeze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-freeze.js","sourceRoot":"","sources":["../src/deep-freeze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAI,KAAQ;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,CAAC,EAAE,CAAC;QACjF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAC;YACrD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9C,UAAU,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { ShellDialect } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Common base class for every error this package throws — originally just
|
|
4
|
+
* {@link sh-ast#parseSync | parseSync}'s errors, now also the
|
|
5
|
+
* `sh-ast/analyze` layer's (see {@link ShAnalyzeMaxDepthError},
|
|
6
|
+
* {@link ShAnalyzeInvalidWrapperSpecError}). Provides a stable, documented
|
|
7
|
+
* `code` discriminator (e.g. `"SH_AST_PARSE_ERROR"`) alongside the usual
|
|
8
|
+
* `instanceof` narrowing, so consumers can branch on failure kind
|
|
9
|
+
* programmatically without parsing `.message` strings. Never thrown directly
|
|
10
|
+
* — only via its concrete subclasses
|
|
11
|
+
* ({@link sh-ast#ShParseError | ShParseError},
|
|
12
|
+
* {@link sh-ast#ShInvalidDialectError | ShInvalidDialectError},
|
|
13
|
+
* {@link sh-ast#ShInternalError | ShInternalError},
|
|
14
|
+
* {@link ShAnalyzeMaxDepthError},
|
|
15
|
+
* {@link sh-ast#ShParseMaxDepthError | ShParseMaxDepthError},
|
|
16
|
+
* {@link ShAnalyzeInvalidWrapperSpecError}).
|
|
17
|
+
*
|
|
18
|
+
* Re-exported from `sh-ast/analyze` as well as the root `sh-ast` entry
|
|
19
|
+
* point (see #23) — every subclass thrown by `sh-ast/analyze`'s own
|
|
20
|
+
* functions extends this, so a consumer of that subpath alone can
|
|
21
|
+
* `catch`/reference the base without also importing from root.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export declare abstract class ShAstError extends Error {
|
|
26
|
+
/**
|
|
27
|
+
* Stable, machine-readable discriminator for this error kind. Distinct
|
|
28
|
+
* per subclass and will not change once published.
|
|
29
|
+
*/
|
|
30
|
+
abstract readonly code: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Position info attached to a {@link ShParseError}.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export interface ShParseErrorInfo {
|
|
38
|
+
/** 1-based line number, exactly as reported by mvdan/sh. */
|
|
39
|
+
line: number;
|
|
40
|
+
/**
|
|
41
|
+
* 1-based column number, in **UTF-16 code units** — converted from
|
|
42
|
+
* mvdan/sh's own byte-counting column so it agrees with
|
|
43
|
+
* {@link ShNode.loc}'s columns (mvdan/sh reports `column` as a byte count
|
|
44
|
+
* on the source line, not a UTF-16 code unit count; see
|
|
45
|
+
* design/ARCHITECTURE.md's "Byte→UTF-16 conversion"). For ASCII-only
|
|
46
|
+
* source text this is numerically identical to mvdan/sh's own column.
|
|
47
|
+
*/
|
|
48
|
+
column: number;
|
|
49
|
+
/** The filename used for the parse (see {@link ParseOptions.filename}). */
|
|
50
|
+
filename: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Thrown by {@link parseSync} when shell source fails to parse. Carries the
|
|
54
|
+
* real position mvdan/sh reported — never 1:1 placeholders: `.line` is
|
|
55
|
+
* 1-based exactly as mvdan/sh reports it, and `.column` is converted to
|
|
56
|
+
* UTF-16 code units so it agrees with {@link ShNode.loc}'s columns (mvdan/sh
|
|
57
|
+
* itself reports `column` as a byte count on the source line — see
|
|
58
|
+
* {@link ShParseErrorInfo.column}). The unconverted, raw byte-column
|
|
59
|
+
* position appears only inside `.message`, mvdan/sh's own formatted string,
|
|
60
|
+
* verbatim.
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
export declare class ShParseError extends ShAstError {
|
|
65
|
+
readonly code = "SH_AST_PARSE_ERROR";
|
|
66
|
+
readonly line: number;
|
|
67
|
+
readonly column: number;
|
|
68
|
+
readonly filename: string;
|
|
69
|
+
constructor(message: string, info: ShParseErrorInfo);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Thrown by {@link parseSync} when {@link ParseOptions.dialect} is not one
|
|
73
|
+
* of the supported {@link ShellDialect} values. Carries the rejected value
|
|
74
|
+
* as `.dialect`; `.message` lists the supported dialects. A foreseeable,
|
|
75
|
+
* actionable user mistake — never an instance of {@link ShParseError}.
|
|
76
|
+
*
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
export declare class ShInvalidDialectError extends ShAstError {
|
|
80
|
+
readonly code = "SH_AST_INVALID_DIALECT";
|
|
81
|
+
/** The rejected dialect value, exactly as passed to {@link parseSync}. */
|
|
82
|
+
readonly dialect: string;
|
|
83
|
+
constructor(dialect: string, supportedDialects: readonly ShellDialect[]);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Thrown by {@link parseSync} for failures that should never happen given a
|
|
87
|
+
* correctly-behaving WASM shim: a malformed result envelope, an unexpected
|
|
88
|
+
* root node type, or any other shim contract violation. Distinct from
|
|
89
|
+
* {@link ShInvalidDialectError} and {@link ShParseError}, both of which
|
|
90
|
+
* indicate a foreseeable, actionable user mistake rather than an internal
|
|
91
|
+
* defect.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
export declare class ShInternalError extends ShAstError {
|
|
96
|
+
readonly code = "SH_AST_INTERNAL";
|
|
97
|
+
constructor(message: string);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Thrown by `sh-ast/analyze`'s `enumerateCommands` when a tree's genuinely
|
|
101
|
+
* nested structure — subshells within subshells, chained command/process
|
|
102
|
+
* substitutions, deeply nested `if`/`case`/loop/function/`time`/`{ }`
|
|
103
|
+
* bodies, deeply chained `elif` — exceeds its defensive recursion-depth
|
|
104
|
+
* guard. **Not** thrown for a long *linear* chain (`|`/`|&`/`&&`/`||` of
|
|
105
|
+
* any realistic length): `enumerateCommands` traverses those iteratively,
|
|
106
|
+
* so chain length alone never grows this guard's depth counter — only
|
|
107
|
+
* genuine tree nesting does.
|
|
108
|
+
*
|
|
109
|
+
* `enumerateCommands` deliberately fails closed here rather than returning
|
|
110
|
+
* a truncated, partial result: a partial `CommandSite[]` silently omits
|
|
111
|
+
* real command sites, which is a false negative for a permission-hook-style
|
|
112
|
+
* consumer that treats "command not found in the enumeration" as "nothing
|
|
113
|
+
* to worry about" — an explicit, documented throw is safer than a silent
|
|
114
|
+
* under-report. Gate-style consumers should treat this error as `deny`,
|
|
115
|
+
* not fall back to "no commands found, so allow".
|
|
116
|
+
*
|
|
117
|
+
* @public
|
|
118
|
+
*/
|
|
119
|
+
export declare class ShAnalyzeMaxDepthError extends ShAstError {
|
|
120
|
+
readonly code = "SH_AST_ANALYZE_MAX_DEPTH";
|
|
121
|
+
/** The maximum nesting depth `enumerateCommands` supports; the same value every time (not caller-configurable). */
|
|
122
|
+
readonly maxDepth: number;
|
|
123
|
+
constructor(maxDepth: number);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Thrown by {@link parseSync} when `text`'s conservatively estimated
|
|
127
|
+
* structural nesting depth (subshells, command/process substitutions,
|
|
128
|
+
* `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
|
|
129
|
+
* command substitution, `$((...))` arithmetic — see
|
|
130
|
+
* `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
|
|
131
|
+
* limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
|
|
132
|
+
* WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
|
|
133
|
+
* for exhausting its call stack on pathologically deep input (a stack
|
|
134
|
+
* overflow deep inside the shared WASM instance is not a normal, catchable
|
|
135
|
+
* JS error the way a parse syntax error is), so this bridge estimates the
|
|
136
|
+
* risk up front and fails closed with a typed error instead of ever making
|
|
137
|
+
* that call — the shared WASM instance is therefore never put at risk of
|
|
138
|
+
* wedging on this class of input; a `parseSync` call right after catching
|
|
139
|
+
* this error works exactly as it would if this input had never been
|
|
140
|
+
* attempted.
|
|
141
|
+
*
|
|
142
|
+
* Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
|
|
143
|
+
* protection, not a normal-usage ceiling: a legitimately deep (but
|
|
144
|
+
* realistic) script parses fine. The estimate can *over*-count relative to
|
|
145
|
+
* mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
|
|
146
|
+
* input) but is designed to never *under*-count relative to it — see
|
|
147
|
+
* `parse-depth-guard.ts` for the documented false-positive sources this
|
|
148
|
+
* trades off against ever letting a genuinely crash-inducing input
|
|
149
|
+
* through.
|
|
150
|
+
*
|
|
151
|
+
* @public
|
|
152
|
+
*/
|
|
153
|
+
export declare class ShParseMaxDepthError extends ShAstError {
|
|
154
|
+
readonly code = "SH_AST_PARSE_MAX_DEPTH";
|
|
155
|
+
/** The maximum structural nesting depth `parseSync` accepts; the same value every time (not caller-configurable). */
|
|
156
|
+
readonly maxDepth: number;
|
|
157
|
+
/**
|
|
158
|
+
* The conservatively estimated nesting depth that tripped the guard.
|
|
159
|
+
* Not necessarily `text`'s "true" nesting depth under a real parse — see
|
|
160
|
+
* {@link ShParseMaxDepthError}'s doc comment — only ever `> maxDepth`.
|
|
161
|
+
*/
|
|
162
|
+
readonly estimatedDepth: number;
|
|
163
|
+
constructor(maxDepth: number, estimatedDepth: number);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Thrown by `sh-ast/analyze`'s `resolveArgv0` when a caller-supplied
|
|
167
|
+
* `options.transparentWrappers` array contains a malformed `WrapperSpec`
|
|
168
|
+
* entry — e.g. a non-array or empty `names`, or a flag field that isn't an
|
|
169
|
+
* array of strings. Fails closed with a clear, specific message at the
|
|
170
|
+
* point the malformed table is supplied, rather than letting the bad shape
|
|
171
|
+
* reach flag-matching logic and surface as a confusing native `TypeError`
|
|
172
|
+
* (or, worse, a silently wrong match) far from its actual cause.
|
|
173
|
+
*
|
|
174
|
+
* @public
|
|
175
|
+
*/
|
|
176
|
+
export declare class ShAnalyzeInvalidWrapperSpecError extends ShAstError {
|
|
177
|
+
readonly code = "SH_AST_ANALYZE_INVALID_WRAPPER_SPEC";
|
|
178
|
+
constructor(message: string);
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,8BAAsB,UAAW,SAAQ,KAAK;IAC5C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,YAAa,SAAQ,UAAU;IAC1C,QAAQ,CAAC,IAAI,wBAAwB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB;CAOpD;AAED;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;IACnD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,YAAY,EAAE;CAOxE;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"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common base class for every error this package throws — originally just
|
|
3
|
+
* {@link sh-ast#parseSync | parseSync}'s errors, now also the
|
|
4
|
+
* `sh-ast/analyze` layer's (see {@link ShAnalyzeMaxDepthError},
|
|
5
|
+
* {@link ShAnalyzeInvalidWrapperSpecError}). Provides a stable, documented
|
|
6
|
+
* `code` discriminator (e.g. `"SH_AST_PARSE_ERROR"`) alongside the usual
|
|
7
|
+
* `instanceof` narrowing, so consumers can branch on failure kind
|
|
8
|
+
* programmatically without parsing `.message` strings. Never thrown directly
|
|
9
|
+
* — only via its concrete subclasses
|
|
10
|
+
* ({@link sh-ast#ShParseError | ShParseError},
|
|
11
|
+
* {@link sh-ast#ShInvalidDialectError | ShInvalidDialectError},
|
|
12
|
+
* {@link sh-ast#ShInternalError | ShInternalError},
|
|
13
|
+
* {@link ShAnalyzeMaxDepthError},
|
|
14
|
+
* {@link sh-ast#ShParseMaxDepthError | ShParseMaxDepthError},
|
|
15
|
+
* {@link ShAnalyzeInvalidWrapperSpecError}).
|
|
16
|
+
*
|
|
17
|
+
* Re-exported from `sh-ast/analyze` as well as the root `sh-ast` entry
|
|
18
|
+
* point (see #23) — every subclass thrown by `sh-ast/analyze`'s own
|
|
19
|
+
* functions extends this, so a consumer of that subpath alone can
|
|
20
|
+
* `catch`/reference the base without also importing from root.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export class ShAstError extends Error {
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Thrown by {@link parseSync} when shell source fails to parse. Carries the
|
|
28
|
+
* real position mvdan/sh reported — never 1:1 placeholders: `.line` is
|
|
29
|
+
* 1-based exactly as mvdan/sh reports it, and `.column` is converted to
|
|
30
|
+
* UTF-16 code units so it agrees with {@link ShNode.loc}'s columns (mvdan/sh
|
|
31
|
+
* itself reports `column` as a byte count on the source line — see
|
|
32
|
+
* {@link ShParseErrorInfo.column}). The unconverted, raw byte-column
|
|
33
|
+
* position appears only inside `.message`, mvdan/sh's own formatted string,
|
|
34
|
+
* verbatim.
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export class ShParseError extends ShAstError {
|
|
39
|
+
code = 'SH_AST_PARSE_ERROR';
|
|
40
|
+
line;
|
|
41
|
+
column;
|
|
42
|
+
filename;
|
|
43
|
+
constructor(message, info) {
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = 'ShParseError';
|
|
46
|
+
this.line = info.line;
|
|
47
|
+
this.column = info.column;
|
|
48
|
+
this.filename = info.filename;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Thrown by {@link parseSync} when {@link ParseOptions.dialect} is not one
|
|
53
|
+
* of the supported {@link ShellDialect} values. Carries the rejected value
|
|
54
|
+
* as `.dialect`; `.message` lists the supported dialects. A foreseeable,
|
|
55
|
+
* actionable user mistake — never an instance of {@link ShParseError}.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export class ShInvalidDialectError extends ShAstError {
|
|
60
|
+
code = 'SH_AST_INVALID_DIALECT';
|
|
61
|
+
/** The rejected dialect value, exactly as passed to {@link parseSync}. */
|
|
62
|
+
dialect;
|
|
63
|
+
constructor(dialect, supportedDialects) {
|
|
64
|
+
super(`bridge: unrecognized shell dialect "${dialect}"; supported dialects are: ${supportedDialects.join(', ')}`);
|
|
65
|
+
this.name = 'ShInvalidDialectError';
|
|
66
|
+
this.dialect = dialect;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Thrown by {@link parseSync} for failures that should never happen given a
|
|
71
|
+
* correctly-behaving WASM shim: a malformed result envelope, an unexpected
|
|
72
|
+
* root node type, or any other shim contract violation. Distinct from
|
|
73
|
+
* {@link ShInvalidDialectError} and {@link ShParseError}, both of which
|
|
74
|
+
* indicate a foreseeable, actionable user mistake rather than an internal
|
|
75
|
+
* defect.
|
|
76
|
+
*
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
export class ShInternalError extends ShAstError {
|
|
80
|
+
code = 'SH_AST_INTERNAL';
|
|
81
|
+
constructor(message) {
|
|
82
|
+
super(message);
|
|
83
|
+
this.name = 'ShInternalError';
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Thrown by `sh-ast/analyze`'s `enumerateCommands` when a tree's genuinely
|
|
88
|
+
* nested structure — subshells within subshells, chained command/process
|
|
89
|
+
* substitutions, deeply nested `if`/`case`/loop/function/`time`/`{ }`
|
|
90
|
+
* bodies, deeply chained `elif` — exceeds its defensive recursion-depth
|
|
91
|
+
* guard. **Not** thrown for a long *linear* chain (`|`/`|&`/`&&`/`||` of
|
|
92
|
+
* any realistic length): `enumerateCommands` traverses those iteratively,
|
|
93
|
+
* so chain length alone never grows this guard's depth counter — only
|
|
94
|
+
* genuine tree nesting does.
|
|
95
|
+
*
|
|
96
|
+
* `enumerateCommands` deliberately fails closed here rather than returning
|
|
97
|
+
* a truncated, partial result: a partial `CommandSite[]` silently omits
|
|
98
|
+
* real command sites, which is a false negative for a permission-hook-style
|
|
99
|
+
* consumer that treats "command not found in the enumeration" as "nothing
|
|
100
|
+
* to worry about" — an explicit, documented throw is safer than a silent
|
|
101
|
+
* under-report. Gate-style consumers should treat this error as `deny`,
|
|
102
|
+
* not fall back to "no commands found, so allow".
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
export class ShAnalyzeMaxDepthError extends ShAstError {
|
|
107
|
+
code = 'SH_AST_ANALYZE_MAX_DEPTH';
|
|
108
|
+
/** The maximum nesting depth `enumerateCommands` supports; the same value every time (not caller-configurable). */
|
|
109
|
+
maxDepth;
|
|
110
|
+
constructor(maxDepth) {
|
|
111
|
+
super(`enumerateCommands: exceeded the maximum supported structural nesting depth (${String(maxDepth)} frames) — refusing to return a partial result. Treat this as a deny signal, not "no commands found".`);
|
|
112
|
+
this.name = 'ShAnalyzeMaxDepthError';
|
|
113
|
+
this.maxDepth = maxDepth;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Thrown by {@link parseSync} when `text`'s conservatively estimated
|
|
118
|
+
* structural nesting depth (subshells, command/process substitutions,
|
|
119
|
+
* `if`/`case`/loop/function bodies, `{ }` blocks, backtick or `$(...)`
|
|
120
|
+
* command substitution, `$((...))` arithmetic — see
|
|
121
|
+
* `parse-depth-guard.ts`'s module doc for the exact heuristic) exceeds the
|
|
122
|
+
* limit `parseSync` accepts. Thrown *before* `text` is ever handed to the
|
|
123
|
+
* WASM shim: mvdan/sh's own recursive-descent parser has no recovery path
|
|
124
|
+
* for exhausting its call stack on pathologically deep input (a stack
|
|
125
|
+
* overflow deep inside the shared WASM instance is not a normal, catchable
|
|
126
|
+
* JS error the way a parse syntax error is), so this bridge estimates the
|
|
127
|
+
* risk up front and fails closed with a typed error instead of ever making
|
|
128
|
+
* that call — the shared WASM instance is therefore never put at risk of
|
|
129
|
+
* wedging on this class of input; a `parseSync` call right after catching
|
|
130
|
+
* this error works exactly as it would if this input had never been
|
|
131
|
+
* attempted.
|
|
132
|
+
*
|
|
133
|
+
* Like {@link ShAnalyzeMaxDepthError}, this is pathological-input
|
|
134
|
+
* protection, not a normal-usage ceiling: a legitimately deep (but
|
|
135
|
+
* realistic) script parses fine. The estimate can *over*-count relative to
|
|
136
|
+
* mvdan/sh's real grammar (rejecting some legitimate-but-unusually-deep
|
|
137
|
+
* input) but is designed to never *under*-count relative to it — see
|
|
138
|
+
* `parse-depth-guard.ts` for the documented false-positive sources this
|
|
139
|
+
* trades off against ever letting a genuinely crash-inducing input
|
|
140
|
+
* through.
|
|
141
|
+
*
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
export class ShParseMaxDepthError extends ShAstError {
|
|
145
|
+
code = 'SH_AST_PARSE_MAX_DEPTH';
|
|
146
|
+
/** The maximum structural nesting depth `parseSync` accepts; the same value every time (not caller-configurable). */
|
|
147
|
+
maxDepth;
|
|
148
|
+
/**
|
|
149
|
+
* The conservatively estimated nesting depth that tripped the guard.
|
|
150
|
+
* Not necessarily `text`'s "true" nesting depth under a real parse — see
|
|
151
|
+
* {@link ShParseMaxDepthError}'s doc comment — only ever `> maxDepth`.
|
|
152
|
+
*/
|
|
153
|
+
estimatedDepth;
|
|
154
|
+
constructor(maxDepth, estimatedDepth) {
|
|
155
|
+
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".`);
|
|
156
|
+
this.name = 'ShParseMaxDepthError';
|
|
157
|
+
this.maxDepth = maxDepth;
|
|
158
|
+
this.estimatedDepth = estimatedDepth;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Thrown by `sh-ast/analyze`'s `resolveArgv0` when a caller-supplied
|
|
163
|
+
* `options.transparentWrappers` array contains a malformed `WrapperSpec`
|
|
164
|
+
* entry — e.g. a non-array or empty `names`, or a flag field that isn't an
|
|
165
|
+
* array of strings. Fails closed with a clear, specific message at the
|
|
166
|
+
* point the malformed table is supplied, rather than letting the bad shape
|
|
167
|
+
* reach flag-matching logic and surface as a confusing native `TypeError`
|
|
168
|
+
* (or, worse, a silently wrong match) far from its actual cause.
|
|
169
|
+
*
|
|
170
|
+
* @public
|
|
171
|
+
*/
|
|
172
|
+
export class ShAnalyzeInvalidWrapperSpecError extends ShAstError {
|
|
173
|
+
code = 'SH_AST_ANALYZE_INVALID_WRAPPER_SPEC';
|
|
174
|
+
constructor(message) {
|
|
175
|
+
super(`resolveArgv0: invalid transparentWrappers entry — ${message}`);
|
|
176
|
+
this.name = 'ShAnalyzeInvalidWrapperSpecError';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAgB,UAAW,SAAQ,KAAK;CAM7C;AAuBD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,YAAa,SAAQ,UAAU;IACjC,IAAI,GAAG,oBAAoB,CAAC;IAC5B,IAAI,CAAS;IACb,MAAM,CAAS;IACf,QAAQ,CAAS;IAE1B,YAAY,OAAe,EAAE,IAAsB;QACjD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAChC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,qBAAsB,SAAQ,UAAU;IAC1C,IAAI,GAAG,wBAAwB,CAAC;IACzC,0EAA0E;IACjE,OAAO,CAAS;IAEzB,YAAY,OAAe,EAAE,iBAA0C;QACrE,KAAK,CACH,uCAAuC,OAAO,8BAA8B,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3G,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { parseSync } from './parse.js';
|
|
2
|
+
export { ShAnalyzeInvalidWrapperSpecError, ShAnalyzeMaxDepthError, ShAstError, ShInternalError, ShInvalidDialectError, ShParseError, ShParseMaxDepthError, } from './errors.js';
|
|
3
|
+
export type { ShParseErrorInfo } from './errors.js';
|
|
4
|
+
export type { ParseOptions, Position, ShellDialect, ShFile, ShNode } from './types.js';
|
|
5
|
+
export { visitorKeys } from './visitor-keys.js';
|
|
6
|
+
export { walk } from './walk.js';
|
|
7
|
+
/**
|
|
8
|
+
* Strongly-typed `ShNode` subtypes for every mvdan/sh node type — generated
|
|
9
|
+
* by `tools/gen-visitor-keys` alongside {@link visitorKeys} (see
|
|
10
|
+
* design/ARCHITECTURE.md, "The schema table is generated, not
|
|
11
|
+
* hand-written"). {@link ShNode}'s index signature remains the base
|
|
12
|
+
* contract; these are an additive, opt-in stronger typing for consumers
|
|
13
|
+
* that want e.g. `ShNodes.ShCallExprNode` instead of a generic `ShNode`.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export type * as ShNodes from '../generated/node-types.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;GASG;AACH,YAAY,KAAK,OAAO,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { parseSync } from './parse.js';
|
|
2
|
+
export { ShAnalyzeInvalidWrapperSpecError, ShAnalyzeMaxDepthError, ShAstError, ShInternalError, ShInvalidDialectError, ShParseError, ShParseMaxDepthError, } from './errors.js';
|
|
3
|
+
export { visitorKeys } from './visitor-keys.js';
|
|
4
|
+
export { walk } from './walk.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EACL,gCAAgC,EAChC,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ShNode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A JSON value as produced by `JSON.parse`.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
8
|
+
[key: string]: JsonValue;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Builds a byte-offset -> UTF-16-index lookup for `text`. mvdan/sh reports
|
|
12
|
+
* byte offsets; ESLint (and JavaScript strings generally) index by UTF-16
|
|
13
|
+
* code unit, so every position needs this conversion. Throws if asked to
|
|
14
|
+
* convert an offset that does not fall on a UTF-8 code-point boundary — an
|
|
15
|
+
* invariant every offset the parser emits must satisfy (see
|
|
16
|
+
* design/ARCHITECTURE.md's "Serialization contract").
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare function makeByteToUtf16(text: string): (byteOffset: number) => number;
|
|
21
|
+
/**
|
|
22
|
+
* Converts a byte offset and the 1-based line mvdan/sh already computed for
|
|
23
|
+
* it into a 1-based, UTF-16-code-unit column — the same conversion
|
|
24
|
+
* `normalize` applies to every node's `loc.start`/`loc.end` below, extracted
|
|
25
|
+
* so a parse error's reported position (see `errors.ts`'s
|
|
26
|
+
* `ShParseErrorInfo`) can use the identical algorithm instead of the raw
|
|
27
|
+
* byte-counting column mvdan/sh itself reports. See design/ARCHITECTURE.md's
|
|
28
|
+
* "Byte→UTF-16 conversion".
|
|
29
|
+
*
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function toUtf16Column(text: string, byteOffset: number, line: number): number;
|
|
33
|
+
/**
|
|
34
|
+
* Normalizes mvdan/sh's typedjson tree into the shape ESLint expects: every
|
|
35
|
+
* node gets `type`, `range` (UTF-16), `loc` (1-based, UTF-16 columns), and
|
|
36
|
+
* every other field copied over with its name lowercased. See
|
|
37
|
+
* design/ARCHITECTURE.md's "Normalized node shape".
|
|
38
|
+
*
|
|
39
|
+
* Three of mvdan/sh's struct types — `Slice`, `Replace`, `Expansion`, all
|
|
40
|
+
* reachable only via `ParamExp.Slice`/`.Repl`/`.Exp` — do not implement
|
|
41
|
+
* `syntax.Node` (no `Pos()`/`End()`), so typedjson never gives them a `Pos`/
|
|
42
|
+
* `End` pair, let alone a `Type` discriminator. They still hold real child
|
|
43
|
+
* nodes (`Slice.Offset`/`.Length`, `Replace.Orig`/`.With`,
|
|
44
|
+
* `Expansion.Word`), so dropping them would silently lose that subtree (see
|
|
45
|
+
* issue #13 — `${USER:-nobody}`'s `nobody` literal). This function
|
|
46
|
+
* synthesizes a `type`/`range`/`loc` for these from their own children's
|
|
47
|
+
* already-computed positions instead, via `walkSynthetic` below.
|
|
48
|
+
*
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalize(root: JsonValue, text: string): ShNode;
|
|
52
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBnD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACnB,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAoEhF;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAsB5E;AAkBD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsI/D"}
|