yuku-parser 0.5.11 → 0.5.15
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 +81 -36
- package/decode.js +392 -74
- package/index.d.ts +74 -49
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -15,8 +15,7 @@ import { parse } from "yuku-parser";
|
|
|
15
15
|
|
|
16
16
|
const result = parse("const x = 1 + 2;");
|
|
17
17
|
|
|
18
|
-
console.log(result.program);
|
|
19
|
-
console.log(result.comments); // all comments
|
|
18
|
+
console.log(result.program); // ESTree / TypeScript-ESTree Program node
|
|
20
19
|
console.log(result.diagnostics); // errors and warnings
|
|
21
20
|
```
|
|
22
21
|
|
|
@@ -26,10 +25,15 @@ For JavaScript and JSX, the AST is fully conformant with the [ESTree](https://gi
|
|
|
26
25
|
|
|
27
26
|
For TypeScript, the AST conforms to the [TypeScript-ESTree](https://www.npmjs.com/package/@typescript-eslint/typescript-estree) format used by `@typescript-eslint`.
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
Yuku also matches [Oxc](https://oxc.rs) for both JS and TS, with two intentional deviations from the base specs:
|
|
30
29
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
30
|
+
- **Comments are attached to the AST nodes they belong to** rather than exposed as a separate offset-indexed array. See [Comments](#comments) for why.
|
|
31
|
+
- **`Identifier` carries a `kind` field** (`"reference" | "binding" | "name" | "label" | "this"`) naming its role in the tree. ESTree collapses these distinct roles onto one `Identifier` type, so consumers normally have to walk the parent context to tell them apart. The parser already knows which is which, so it surfaces the answer as a free field.
|
|
32
|
+
|
|
33
|
+
On top of the base specs, the AST also carries:
|
|
34
|
+
|
|
35
|
+
- Stage 3 [decorators](https://github.com/tc39/proposal-decorators).
|
|
36
|
+
- Stage 3 [import defer](https://github.com/tc39/proposal-defer-import-eval) and [import source](https://github.com/tc39/proposal-source-phase-imports). Dynamic forms (`import.defer(...)`, `import.source(...)`) are represented as an `ImportExpression` with a `phase` field set to `"defer"` or `"source"`, following the ESTree convention.
|
|
33
37
|
- A non-standard `hashbang` field on `Program` for `#!/usr/bin/env node` lines.
|
|
34
38
|
|
|
35
39
|
Any other deviation from Acorn's ESTree or `@typescript-eslint`'s TypeScript-ESTree would be considered a bug.
|
|
@@ -51,12 +55,27 @@ Two small helpers are exported for resolving the `lang` and `sourceType` options
|
|
|
51
55
|
```ts
|
|
52
56
|
import { langFromPath, sourceTypeFromPath } from "yuku-parser";
|
|
53
57
|
|
|
54
|
-
langFromPath("foo.tsx");
|
|
55
|
-
langFromPath("types.d.ts");
|
|
56
|
-
sourceTypeFromPath("foo.cjs");
|
|
57
|
-
sourceTypeFromPath("foo.mjs");
|
|
58
|
+
langFromPath("foo.tsx"); // "tsx"
|
|
59
|
+
langFromPath("types.d.ts"); // "dts"
|
|
60
|
+
sourceTypeFromPath("foo.cjs"); // "script"
|
|
61
|
+
sourceTypeFromPath("foo.mjs"); // "module"
|
|
58
62
|
```
|
|
59
63
|
|
|
64
|
+
## Resolving offsets to `(line, column)`
|
|
65
|
+
|
|
66
|
+
Nodes and diagnostics carry `start`/`end` offsets (UTF-16 code units). To turn an offset into a `{ line, column }` pair, call `locOf` on the parse result:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { parse } from "yuku-parser";
|
|
70
|
+
|
|
71
|
+
const result = parse(source);
|
|
72
|
+
const { line, column } = result.locOf(result.program.body[0].start);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Lines are 1-based and columns are 0-based, matching ESTree's `loc` convention. The lookup is an O(log n) binary search: tens of nanoseconds per call, safe to invoke per node during a walk.
|
|
76
|
+
|
|
77
|
+
For bulk work — building your own line/column index, integrating with another source-map or diagnostics library, or skipping the per-call binary search — read `result.lineStarts` directly. It's a sorted array of UTF-16 offsets where each line begins: `lineStarts[i]` is the start of line `i + 1`. Decoded lazily on first access and cached.
|
|
78
|
+
|
|
60
79
|
## Walking the AST
|
|
61
80
|
|
|
62
81
|
The AST is standard ESTree, so any ESTree-compatible walker works. For example, with [zimmerframe](https://github.com/sveltejs/zimmerframe):
|
|
@@ -91,6 +110,7 @@ const result = parse(source, {
|
|
|
91
110
|
preserveParens: true,
|
|
92
111
|
allowReturnOutsideFunction: false,
|
|
93
112
|
semanticErrors: false,
|
|
113
|
+
attachComments: false,
|
|
94
114
|
});
|
|
95
115
|
```
|
|
96
116
|
|
|
@@ -101,6 +121,7 @@ const result = parse(source, {
|
|
|
101
121
|
| `preserveParens` | `true`, `false` | `true` | Keep `ParenthesizedExpression` nodes in the AST. When false, parentheses are stripped and only the inner expression is kept. |
|
|
102
122
|
| `allowReturnOutsideFunction` | `true`, `false` | `false` | Allow `return` statements outside of functions, at the top level. |
|
|
103
123
|
| `semanticErrors` | `true`, `false` | `false` | Run semantic analysis and report semantic errors alongside syntax errors. |
|
|
124
|
+
| `attachComments` | `true`, `false` | `false` | Collect comments and attach them to host AST nodes. See [Comments](#comments). |
|
|
104
125
|
|
|
105
126
|
## Result
|
|
106
127
|
|
|
@@ -109,13 +130,13 @@ const result = parse(source, {
|
|
|
109
130
|
```ts
|
|
110
131
|
interface ParseResult {
|
|
111
132
|
program: Program;
|
|
112
|
-
comments: Comment[];
|
|
113
|
-
lineStarts: number[];
|
|
114
133
|
diagnostics: Diagnostic[];
|
|
134
|
+
lineStarts: number[];
|
|
135
|
+
locOf(offset: number): { line: number; column: number };
|
|
115
136
|
}
|
|
116
137
|
```
|
|
117
138
|
|
|
118
|
-
The parser is error-tolerant
|
|
139
|
+
The parser is error-tolerant: an AST is always produced even when diagnostics are present.
|
|
119
140
|
|
|
120
141
|
### Diagnostics
|
|
121
142
|
|
|
@@ -140,41 +161,65 @@ const result = parse(`let x = 1; let x = 2;`, { semanticErrors: true });
|
|
|
140
161
|
|
|
141
162
|
This incurs a very small performance overhead. If your build pipeline already handles semantic validation (e.g. through a linter or type checker), you can leave this off for faster parsing.
|
|
142
163
|
|
|
143
|
-
|
|
164
|
+
## Comments
|
|
165
|
+
|
|
166
|
+
Comments are attached to the AST node they sit next to. Enable collection with `attachComments`, then read them off any node:
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
const { program } = parse(
|
|
170
|
+
`// header\nfunction foo() {} // trailing`,
|
|
171
|
+
{ attachComments: true },
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const fn = program.body[0];
|
|
175
|
+
for (const c of fn.comments ?? []) {
|
|
176
|
+
console.log(c.position, c.type, c.value);
|
|
177
|
+
}
|
|
178
|
+
// before Line " header"
|
|
179
|
+
// after Line " trailing"
|
|
180
|
+
```
|
|
144
181
|
|
|
145
|
-
|
|
182
|
+
Each comment is:
|
|
146
183
|
|
|
147
184
|
```ts
|
|
148
185
|
interface Comment {
|
|
149
186
|
type: "Line" | "Block";
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
value: string; // text without the surrounding delimiters
|
|
154
|
-
start: number; // byte offset
|
|
155
|
-
end: number; // byte offset
|
|
187
|
+
position: "before" | "after" | "inside";
|
|
188
|
+
sameLine: boolean;
|
|
189
|
+
value: string; // body without delimiters
|
|
156
190
|
}
|
|
157
|
-
|
|
158
|
-
type CommentKind =
|
|
159
|
-
| "normal" // plain comment, no special meaning
|
|
160
|
-
| "legal" // /*! ... */ or contains @license / @preserve / @cc_on
|
|
161
|
-
| "jsdoc" // /** ... */ block
|
|
162
|
-
| "annotation" // /*# ... */ or /*@ ... */ other than tree-shaking
|
|
163
|
-
| "pure" // /*#__PURE__*/ or /*@__PURE__*/
|
|
164
|
-
| "no_side_effects"; // /*#__NO_SIDE_EFFECTS__*/ or /*@__NO_SIDE_EFFECTS__*/
|
|
165
191
|
```
|
|
166
192
|
|
|
167
|
-
|
|
193
|
+
`position` tells you where the comment sits relative to its host:
|
|
168
194
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
195
|
+
- `"before"`: leading the host node.
|
|
196
|
+
- `"after"`: trailing the host node.
|
|
197
|
+
- `"inside"`: interior to an otherwise empty host, like `function f() { /* hi */ }`.
|
|
172
198
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
199
|
+
`sameLine` is `true` when the comment shares a source line with the host's adjacent edge (host's start for `before`, host's end for `after`). For `inside` it is always `false`.
|
|
200
|
+
|
|
201
|
+
When `attachComments` is disabled (the default), comments are skipped like whitespace and no `comments` field appears on any node.
|
|
202
|
+
|
|
203
|
+
### Why comments are attached to nodes
|
|
204
|
+
|
|
205
|
+
Comments are part of the source. Any tool that reads or rewrites code needs to know which comments belong with which node, and that link has to survive AST transforms. Yuku puts a single `comments` array on each node, with a `position` field on each comment (`"before"`, `"after"`, `"inside"`). It is the simplest shape that holds up under transforms and stays cheap to decode. Every other approach trades away one of those properties.
|
|
206
|
+
|
|
207
|
+
**Flat offset-indexed array (ESTree default, Oxc).** A separate `comments: [...]` array on the parse result, sibling to the program, each entry pointing at a source range. Fine for read-only analysis. It falls apart the moment you transform the tree.
|
|
208
|
+
|
|
209
|
+
- *Transforms desync the array.* Insert, delete, or move a node and every offset downstream of the edit is wrong. The comment that used to sit between `a` and `b` may now sit inside something unrelated, or hang in empty space between two nodes. Re-syncing means walking the entire array and rewriting offsets on every edit, and even then the meaning of "the comment between these two things" cannot really be preserved by offsets alone.
|
|
210
|
+
- *Codegen cannot trust the offsets.* A printer takes whatever AST it is handed. With offset-based comments, a transformed AST will either print comments in the wrong places or drop them entirely. With attached comments, when you move a node its comments come with it. The printer reads them off `node.comments` and emits them next to the node, no reconciliation needed.
|
|
211
|
+
- *Lookup is awkward.* "Give me the comments belonging to this node" with a flat array is a binary search at best and a linear scan at worst. `node.comments` is O(1) and always exact.
|
|
212
|
+
|
|
213
|
+
**Parser returns a flat list, you attach on the JS side (Acorn).** Acorn's `onComment` option pushes every comment into an array you provide, and that is all it does. To get them onto AST nodes you have to run a separate JS pass like `escodegen.attachComments`, which walks the tree, scans the comment list alongside it, and tags each comment as leading or trailing on the nearest node. That work is unavoidable if you want to transform the tree, and doing it in JavaScript is slow. Yuku does the same attachment in Zig as part of the parse. On the 7.8 MB `typescript.js` (30k+ comments), turning `attachComments` on adds only around 4ms.
|
|
214
|
+
|
|
215
|
+
**Three separate fields per node (Babel).** `leadingComments`, `trailingComments`, and `innerComments`. Same idea as Yuku, but split across three arrays. Two costs come with the split.
|
|
216
|
+
|
|
217
|
+
- *Decode work.* Three fields per node means three slots to check, three potential array allocations, and roughly 3x the work on the JS side for the same information.
|
|
218
|
+
- *Duplication.* A comment that sits between two nodes is the `trailingComments` of one and the `leadingComments` of the other. Transforms have to track both copies and keep them in sync.
|
|
219
|
+
|
|
220
|
+
A single `comments` array with a `position` field carries the same meaning, with one entry per comment and one place to look.
|
|
176
221
|
|
|
177
|
-
|
|
222
|
+
Even with `attachComments` enabled, Yuku still parses the same file roughly 4x faster than Babel does without comments attached at all. When the flag is off (the default), comments are skipped like whitespace and there is no attachment work at all.
|
|
178
223
|
|
|
179
224
|
## License
|
|
180
225
|
|
package/decode.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// generated by tools/gen_estree_decoder.zig, do not edit
|
|
2
|
-
|
|
2
|
+
// `_u32` is an Int32Array so NodeIndex NULL reads as -1 and fits in
|
|
3
|
+
// an SMI/int32, avoiding heap-number boxing on every field read in JSC.
|
|
4
|
+
const NULL = -1;
|
|
3
5
|
const _td = new TextDecoder("utf-8", { ignoreBOM: true });
|
|
4
6
|
const BINARY_OPS = ["==", "!=", "===", "!==", "<", "<=", ">", ">=", "+", "-", "*", "/", "%", "**", "|", "^", "&", "<<", ">>", ">>>", "in", "instanceof"];
|
|
5
7
|
const LOGICAL_OPS = ["&&", "||", "??"];
|
|
@@ -11,8 +13,6 @@ const PROPERTY_KINDS = ["init", "get", "set"];
|
|
|
11
13
|
const METHOD_KINDS = ["constructor", "method", "get", "set"];
|
|
12
14
|
const FUNCTION_TYPES = ["FunctionDeclaration", "FunctionExpression", "TSDeclareFunction", "TSEmptyBodyFunctionExpression"];
|
|
13
15
|
const CLASS_TYPES = ["ClassDeclaration", "ClassExpression"];
|
|
14
|
-
const COMMENT_TYPES = ["Line", "Block"];
|
|
15
|
-
const COMMENT_KINDS = ["normal", "legal", "jsdoc", "annotation", "pure", "no_side_effects"];
|
|
16
16
|
const SEVERITY = ["error", "warning", "hint", "info"];
|
|
17
17
|
const IMPORT_EXPORT_KINDS = ["value", "type"];
|
|
18
18
|
const ACCESSIBILITY = [null, "public", "private", "protected"];
|
|
@@ -33,7 +33,9 @@ function buildPosMap(src, byteLen, startByte) {
|
|
|
33
33
|
while (i < len) {
|
|
34
34
|
if (i + 16 <= len) {
|
|
35
35
|
let allAscii = true;
|
|
36
|
-
for (let k = 0; k < 16; k++)
|
|
36
|
+
for (let k = 0; k < 16; k++) {
|
|
37
|
+
if (src.charCodeAt(i + k) >= 0x80) { allAscii = false; break; }
|
|
38
|
+
}
|
|
37
39
|
if (allAscii) {
|
|
38
40
|
for (let k = 0; k < 16; k++) m[bp + k] = u16p + k;
|
|
39
41
|
bp += 16; u16p += 16; i += 16;
|
|
@@ -44,8 +46,14 @@ function buildPosMap(src, byteLen, startByte) {
|
|
|
44
46
|
m[bp] = u16p;
|
|
45
47
|
if (cu < 0x80) { bp++; u16p++; i++; }
|
|
46
48
|
else if (cu < 0x800) { m[bp + 1] = u16p + 1; bp += 2; u16p++; i++; }
|
|
47
|
-
else if (cu < 0xD800 || cu >= 0xE000) {
|
|
48
|
-
|
|
49
|
+
else if (cu < 0xD800 || cu >= 0xE000) {
|
|
50
|
+
m[bp + 1] = u16p + 1; m[bp + 2] = u16p + 1;
|
|
51
|
+
bp += 3; u16p++; i++;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
m[bp + 1] = u16p + 1; m[bp + 2] = u16p + 2; m[bp + 3] = u16p + 2;
|
|
55
|
+
bp += 4; u16p += 2; i += 2;
|
|
56
|
+
}
|
|
49
57
|
}
|
|
50
58
|
m[byteLen - startByte] = u16p;
|
|
51
59
|
return m;
|
|
@@ -53,17 +61,29 @@ function buildPosMap(src, byteLen, startByte) {
|
|
|
53
61
|
function decode(buffer, source) {
|
|
54
62
|
const _u8 = new Uint8Array(buffer);
|
|
55
63
|
const aLen = (buffer.byteLength >> 2) << 2;
|
|
56
|
-
const _u32 = new
|
|
64
|
+
const _u32 = new Int32Array(buffer, 0, aLen >> 2);
|
|
57
65
|
const _src = source;
|
|
58
66
|
const _srcLen = _u32[3];
|
|
59
|
-
const nodeCount = _u32[0],
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
const nodeCount = _u32[0],
|
|
68
|
+
extraCount = _u32[1],
|
|
69
|
+
spLen = _u32[2];
|
|
70
|
+
const commentCount = _u32[4],
|
|
71
|
+
lineStartsCount = _u32[5],
|
|
72
|
+
diagCount = _u32[6],
|
|
73
|
+
progIdx = _u32[7];
|
|
74
|
+
const _flags = _u32[8];
|
|
75
|
+
const _isTs = !!(_flags & 1);
|
|
76
|
+
const _attachComments = !!(_flags & 2);
|
|
62
77
|
const _firstNa = _u32[9];
|
|
63
78
|
const _nodesOff = 40;
|
|
64
79
|
const eOff = _nodesOff + nodeCount * 48;
|
|
65
80
|
const _extraBase = eOff >> 2;
|
|
66
81
|
const _spOff = eOff + extraCount * 4;
|
|
82
|
+
// sections after the variable-length string pool may be at any
|
|
83
|
+
// byte alignment, so reads against them use `dv`, not `_u32`.
|
|
84
|
+
const dv = new DataView(buffer);
|
|
85
|
+
const _coOff = _spOff + spLen;
|
|
86
|
+
const _cOff = _attachComments ? _coOff + (nodeCount + 1) * 4 : _coOff;
|
|
67
87
|
function _poolDecode(s, e) {
|
|
68
88
|
const a = _spOff + s - _srcLen, b = _spOff + e - _srcLen;
|
|
69
89
|
let hasEd = false;
|
|
@@ -73,9 +93,23 @@ function decode(buffer, source) {
|
|
|
73
93
|
for (let i = a; i < b; ) {
|
|
74
94
|
const c = _u8[i];
|
|
75
95
|
if (c < 0x80) { r += String.fromCharCode(c); i++; }
|
|
76
|
-
else if (c < 0xE0) {
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
else if (c < 0xE0) {
|
|
97
|
+
r += String.fromCharCode(((c & 0x1F) << 6) | (_u8[i+1] & 0x3F));
|
|
98
|
+
i += 2;
|
|
99
|
+
}
|
|
100
|
+
else if (c < 0xF0) {
|
|
101
|
+
r += String.fromCharCode(
|
|
102
|
+
((c & 0x0F) << 12) | ((_u8[i+1] & 0x3F) << 6) | (_u8[i+2] & 0x3F)
|
|
103
|
+
);
|
|
104
|
+
i += 3;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
r += String.fromCodePoint(
|
|
108
|
+
((c & 0x07) << 18) | ((_u8[i+1] & 0x3F) << 12) |
|
|
109
|
+
((_u8[i+2] & 0x3F) << 6) | (_u8[i+3] & 0x3F)
|
|
110
|
+
);
|
|
111
|
+
i += 4;
|
|
112
|
+
}
|
|
79
113
|
}
|
|
80
114
|
return r;
|
|
81
115
|
}
|
|
@@ -105,7 +139,10 @@ function decode(buffer, source) {
|
|
|
105
139
|
}
|
|
106
140
|
function nodeArrHoles(s, len) {
|
|
107
141
|
const r = new Array(len);
|
|
108
|
-
for (let j = 0; j < len; j++) {
|
|
142
|
+
for (let j = 0; j < len; j++) {
|
|
143
|
+
const x = _u32[_extraBase + s + j];
|
|
144
|
+
r[j] = x !== NULL ? node(x) : null;
|
|
145
|
+
}
|
|
109
146
|
return r;
|
|
110
147
|
}
|
|
111
148
|
function fnParams(idx) {
|
|
@@ -118,19 +155,77 @@ function decode(buffer, source) {
|
|
|
118
155
|
if (rest !== NULL) p.push(node(rest));
|
|
119
156
|
return p;
|
|
120
157
|
}
|
|
158
|
+
function _commentsOf(a, e) {
|
|
159
|
+
const out = new Array(e - a);
|
|
160
|
+
for (let j = a; j < e; j++) {
|
|
161
|
+
const o = _cOff + j * 12;
|
|
162
|
+
const cf = _u8[o + 0];
|
|
163
|
+
const vs = dv.getUint32(o + 4, true),
|
|
164
|
+
ve = dv.getUint32(o + 8, true);
|
|
165
|
+
out[j - a] = {
|
|
166
|
+
type: (cf & 1) ? "Block" : "Line",
|
|
167
|
+
position: ["before", "after", "inside"][(cf >> 1) & 3],
|
|
168
|
+
sameLine: (cf & 8) !== 0,
|
|
169
|
+
value: str(vs, ve),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
121
174
|
function node(i) {
|
|
175
|
+
const r = _decode(i);
|
|
176
|
+
// skip unwrap cases whose inner node already carries its own
|
|
177
|
+
// comments (e.g. formal_parameter returning its pattern)
|
|
178
|
+
if (_attachComments && r && r.type !== undefined && r.comments === undefined) {
|
|
179
|
+
const off = _coOff + i * 4;
|
|
180
|
+
const a = dv.getUint32(off, true), e = dv.getUint32(off + 4, true);
|
|
181
|
+
if (a !== e) r.comments = _commentsOf(a, e);
|
|
182
|
+
}
|
|
183
|
+
return r;
|
|
184
|
+
}
|
|
185
|
+
function _decode(i) {
|
|
122
186
|
const o = _nodesOff + i * 48;
|
|
123
187
|
const tag = _u8[o];
|
|
124
188
|
const flags = _u8[o + 2] | (_u8[o + 3] << 8);
|
|
125
189
|
const f0 = _u8[o + 4] | (_u8[o + 5] << 8);
|
|
126
190
|
const b = o >> 2;
|
|
127
|
-
const f1 = _u32[b + 2], f2 = _u32[b + 3],
|
|
191
|
+
const f1 = _u32[b + 2], f2 = _u32[b + 3],
|
|
192
|
+
f3 = _u32[b + 4], f4 = _u32[b + 5],
|
|
193
|
+
f5 = _u32[b + 6], f6 = _u32[b + 7],
|
|
194
|
+
f7 = _u32[b + 8], f8 = _u32[b + 9];
|
|
128
195
|
const start = _p(_u32[b + 10]), end = _p(_u32[b + 11]);
|
|
129
196
|
switch (tag) {
|
|
130
197
|
case 0: return { type: "SequenceExpression", start, end, expressions: nodeArr(f1, f0) };
|
|
131
198
|
case 1: return { type: "ParenthesizedExpression", start, end, expression: f1 !== NULL ? node(f1) : null };
|
|
132
|
-
case 2: {
|
|
133
|
-
|
|
199
|
+
case 2: {
|
|
200
|
+
const r = {
|
|
201
|
+
type: "ArrowFunctionExpression", start, end,
|
|
202
|
+
id: null, generator: false, async: !!(flags & 2),
|
|
203
|
+
params: f1 !== NULL ? fnParams(f1) : [],
|
|
204
|
+
body: node(f2), expression: !!(flags & 1),
|
|
205
|
+
};
|
|
206
|
+
if (_isTs) {
|
|
207
|
+
r.typeParameters = f3 !== NULL ? node(f3) : null;
|
|
208
|
+
r.returnType = f4 !== NULL ? node(f4) : null;
|
|
209
|
+
}
|
|
210
|
+
return r;
|
|
211
|
+
}
|
|
212
|
+
case 3: {
|
|
213
|
+
const ft = flags & 3;
|
|
214
|
+
const r = {
|
|
215
|
+
type: FUNCTION_TYPES[ft], start, end,
|
|
216
|
+
id: f1 !== NULL ? node(f1) : null,
|
|
217
|
+
generator: !!(flags & 4), async: !!(flags & 8),
|
|
218
|
+
params: f2 !== NULL ? fnParams(f2) : [],
|
|
219
|
+
body: f3 !== NULL ? node(f3) : null,
|
|
220
|
+
expression: false,
|
|
221
|
+
};
|
|
222
|
+
if (_isTs) {
|
|
223
|
+
r.typeParameters = f4 !== NULL ? node(f4) : null;
|
|
224
|
+
r.returnType = f5 !== NULL ? node(f5) : null;
|
|
225
|
+
r.declare = !!(flags & 16);
|
|
226
|
+
}
|
|
227
|
+
return r;
|
|
228
|
+
}
|
|
134
229
|
case 4: return { type: "BlockStatement", start, end, body: nodeArr(f1, f0) };
|
|
135
230
|
case 5: return { type: "BlockStatement", start, end, body: nodeArr(f1, f0) };
|
|
136
231
|
case 6: return { params: fnParams(i) };
|
|
@@ -138,7 +233,11 @@ function decode(buffer, source) {
|
|
|
138
233
|
case 8: return { type: "BinaryExpression", start, end, left: f1 !== NULL ? node(f1) : null, right: f2 !== NULL ? node(f2) : null, operator: BINARY_OPS[flags & 31] };
|
|
139
234
|
case 9: return { type: "LogicalExpression", start, end, left: f1 !== NULL ? node(f1) : null, right: f2 !== NULL ? node(f2) : null, operator: LOGICAL_OPS[flags & 3] };
|
|
140
235
|
case 10: return { type: "ConditionalExpression", start, end, test: f1 !== NULL ? node(f1) : null, consequent: f2 !== NULL ? node(f2) : null, alternate: f3 !== NULL ? node(f3) : null };
|
|
141
|
-
case 11: return {
|
|
236
|
+
case 11: return {
|
|
237
|
+
type: "UnaryExpression", start, end,
|
|
238
|
+
operator: UNARY_OPS[flags & 7], prefix: true,
|
|
239
|
+
argument: f1 !== NULL ? node(f1) : null,
|
|
240
|
+
};
|
|
142
241
|
case 12: return { type: "UpdateExpression", start, end, argument: f1 !== NULL ? node(f1) : null, operator: UPDATE_OPS[flags & 1], prefix: !!(flags & 2) };
|
|
143
242
|
case 13: return { type: "AssignmentExpression", start, end, left: f1 !== NULL ? node(f1) : null, right: f2 !== NULL ? node(f2) : null, operator: ASSIGNMENT_OPS[flags & 15] };
|
|
144
243
|
case 14: return { type: "ArrayExpression", start, end, elements: nodeArrHoles(f1, f0) };
|
|
@@ -154,26 +253,133 @@ function decode(buffer, source) {
|
|
|
154
253
|
case 24: return { type: "YieldExpression", start, end, argument: f1 !== NULL ? node(f1) : null, delegate: !!(flags & 1) };
|
|
155
254
|
case 25: return { type: "MetaProperty", start, end, meta: f1 !== NULL ? node(f1) : null, property: f2 !== NULL ? node(f2) : null };
|
|
156
255
|
case 26: return { type: "Decorator", start, end, expression: f1 !== NULL ? node(f1) : null };
|
|
157
|
-
case 27: {
|
|
256
|
+
case 27: {
|
|
257
|
+
const r = {
|
|
258
|
+
type: CLASS_TYPES[flags & 1], start, end,
|
|
259
|
+
decorators: nodeArr(f1, f0),
|
|
260
|
+
id: f2 !== NULL ? node(f2) : null,
|
|
261
|
+
superClass: f3 !== NULL ? node(f3) : null,
|
|
262
|
+
body: node(f4),
|
|
263
|
+
};
|
|
264
|
+
if (_isTs) {
|
|
265
|
+
r.typeParameters = f5 !== NULL ? node(f5) : null;
|
|
266
|
+
r.superTypeArguments = f6 !== NULL ? node(f6) : null;
|
|
267
|
+
r.implements = nodeArr(f7, f8);
|
|
268
|
+
r.abstract = !!(flags & 2);
|
|
269
|
+
r.declare = !!(flags & 4);
|
|
270
|
+
}
|
|
271
|
+
return r;
|
|
272
|
+
}
|
|
158
273
|
case 28: return { type: "ClassBody", start, end, body: nodeArr(f1, f0) };
|
|
159
|
-
case 29: {
|
|
160
|
-
|
|
274
|
+
case 29: {
|
|
275
|
+
const r = {
|
|
276
|
+
type: "MethodDefinition", start, end,
|
|
277
|
+
decorators: nodeArr(f1, f0),
|
|
278
|
+
key: node(f2), value: node(f3),
|
|
279
|
+
kind: METHOD_KINDS[flags & 3],
|
|
280
|
+
computed: !!(flags & 4), static: !!(flags & 8),
|
|
281
|
+
};
|
|
282
|
+
if (_isTs) {
|
|
283
|
+
r.override = !!(flags & 16);
|
|
284
|
+
r.optional = !!(flags & 32);
|
|
285
|
+
const _abs = !!(flags & 64);
|
|
286
|
+
r.accessibility = ACCESSIBILITY[(flags >> 7) & 3];
|
|
287
|
+
if (_abs) r.type = "TSAbstractMethodDefinition";
|
|
288
|
+
}
|
|
289
|
+
return r;
|
|
290
|
+
}
|
|
291
|
+
case 30: {
|
|
292
|
+
const _acc = !!(flags & 4);
|
|
293
|
+
const r = {
|
|
294
|
+
type: _acc ? "AccessorProperty" : "PropertyDefinition",
|
|
295
|
+
start, end,
|
|
296
|
+
decorators: nodeArr(f1, f0),
|
|
297
|
+
key: node(f2),
|
|
298
|
+
value: f3 !== NULL ? node(f3) : null,
|
|
299
|
+
computed: !!(flags & 1), static: !!(flags & 2),
|
|
300
|
+
};
|
|
301
|
+
if (_isTs) {
|
|
302
|
+
r.typeAnnotation = f4 !== NULL ? node(f4) : null;
|
|
303
|
+
r.declare = !!(flags & 8);
|
|
304
|
+
r.override = !!(flags & 16);
|
|
305
|
+
r.optional = !!(flags & 32);
|
|
306
|
+
r.definite = !!(flags & 64);
|
|
307
|
+
r.readonly = !!(flags & 128);
|
|
308
|
+
const _abs = !!(flags & 256);
|
|
309
|
+
r.accessibility = ACCESSIBILITY[(flags >> 9) & 3];
|
|
310
|
+
if (_abs)
|
|
311
|
+
r.type = _acc
|
|
312
|
+
? "TSAbstractAccessorProperty"
|
|
313
|
+
: "TSAbstractPropertyDefinition";
|
|
314
|
+
}
|
|
315
|
+
return r;
|
|
316
|
+
}
|
|
161
317
|
case 31: return { type: "StaticBlock", start, end, body: nodeArr(f1, f0) };
|
|
162
318
|
case 32: return { type: "Super", start, end };
|
|
163
|
-
case 33: return {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
319
|
+
case 33: return {
|
|
320
|
+
type: "Literal", start, end,
|
|
321
|
+
value: str(f1, f2), raw: _src.slice(start, end),
|
|
322
|
+
};
|
|
323
|
+
case 34: {
|
|
324
|
+
const r = _src.slice(start, end);
|
|
325
|
+
const s = r.indexOf("_") === -1 ? r : r.replace(/_/g, "");
|
|
326
|
+
const v = (flags & 3) === 2 && s[1] !== "o" && s[1] !== "O"
|
|
327
|
+
? parseInt(s.slice(1), 8)
|
|
328
|
+
: +s;
|
|
329
|
+
return {
|
|
330
|
+
type: "Literal", start, end,
|
|
331
|
+
value: v === v && isFinite(v) ? v : null,
|
|
332
|
+
raw: r,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
case 35: {
|
|
336
|
+
const r = _src.slice(start, end);
|
|
337
|
+
const d = str(f1, f2).replace(/_/g, "");
|
|
338
|
+
const v = BigInt(d);
|
|
339
|
+
return {
|
|
340
|
+
type: "Literal", start, end,
|
|
341
|
+
value: v, raw: r, bigint: v.toString(),
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
case 36: {
|
|
345
|
+
const v = !!(flags & 1);
|
|
346
|
+
return {
|
|
347
|
+
type: "Literal", start, end,
|
|
348
|
+
value: v, raw: v ? "true" : "false",
|
|
349
|
+
};
|
|
350
|
+
}
|
|
167
351
|
case 37: return { type: "Literal", start, end, value: null, raw: "null" };
|
|
168
352
|
case 38: return { type: "ThisExpression", start, end };
|
|
169
|
-
case 39: {
|
|
353
|
+
case 39: {
|
|
354
|
+
const p = str(f1, f2), fl = str(f3, f4);
|
|
355
|
+
let v = null;
|
|
356
|
+
try { v = new RegExp(p, fl); } catch {}
|
|
357
|
+
return {
|
|
358
|
+
type: "Literal", start, end,
|
|
359
|
+
value: v, raw: "/" + p + "/" + fl,
|
|
360
|
+
regex: { pattern: p, flags: fl.split("").sort().join("") },
|
|
361
|
+
};
|
|
362
|
+
}
|
|
170
363
|
case 40: return { type: "TemplateLiteral", start, end, quasis: nodeArr(f1, f0), expressions: nodeArr(f2, f3) };
|
|
171
|
-
case 41: {
|
|
172
|
-
|
|
364
|
+
case 41: {
|
|
365
|
+
const raw = _src.slice(start, end).replace(/\r\n?/g, "\n");
|
|
366
|
+
const tl = !!(flags & 1);
|
|
367
|
+
const s = _isTs ? start - 1 : start;
|
|
368
|
+
const e = _isTs ? (tl ? end + 1 : end + 2) : end;
|
|
369
|
+
return {
|
|
370
|
+
type: "TemplateElement", start: s, end: e,
|
|
371
|
+
value: {
|
|
372
|
+
raw,
|
|
373
|
+
cooked: (flags & 2) ? null : str(f1, f2),
|
|
374
|
+
},
|
|
375
|
+
tail: tl,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
case 42: { const r = { type: "Identifier", start, end, name: str(f1, f2), kind: "reference" }; if (_isTs) { r.decorators = []; r.optional = false; r.typeAnnotation = null; } return r; }
|
|
173
379
|
case 43: return { type: "PrivateIdentifier", start, end, name: str(f1, f2) };
|
|
174
|
-
case 44: { const r = { type: "Identifier", start, end, name: str(f1, f2) }; if (_isTs) { r.decorators = nodeArr(f3, f0); r.typeAnnotation = f4 !== NULL ? node(f4) : null; r.optional = !!(flags & 1); } return r; }
|
|
175
|
-
case 45: { const r = { type: "Identifier", start, end, name: str(f1, f2) }; if (_isTs) { r.decorators = []; r.optional = false; r.typeAnnotation = null; } return r; }
|
|
176
|
-
case 46: { const r = { type: "Identifier", start, end, name: str(f1, f2) }; if (_isTs) { r.decorators = []; r.optional = false; r.typeAnnotation = null; } return r; }
|
|
380
|
+
case 44: { const r = { type: "Identifier", start, end, name: str(f1, f2), kind: "binding" }; if (_isTs) { r.decorators = nodeArr(f3, f0); r.typeAnnotation = f4 !== NULL ? node(f4) : null; r.optional = !!(flags & 1); } return r; }
|
|
381
|
+
case 45: { const r = { type: "Identifier", start, end, name: str(f1, f2), kind: "name" }; if (_isTs) { r.decorators = []; r.optional = false; r.typeAnnotation = null; } return r; }
|
|
382
|
+
case 46: { const r = { type: "Identifier", start, end, name: str(f1, f2), kind: "label" }; if (_isTs) { r.decorators = []; r.optional = false; r.typeAnnotation = null; } return r; }
|
|
177
383
|
case 47: { const r = { type: "ExpressionStatement", start, end, expression: f1 !== NULL ? node(f1) : null }; if (_isTs) { r.directive = null; } return r; }
|
|
178
384
|
case 48: return { type: "IfStatement", start, end, test: f1 !== NULL ? node(f1) : null, consequent: f2 !== NULL ? node(f2) : null, alternate: f3 !== NULL ? node(f3) : null };
|
|
179
385
|
case 49: return { type: "SwitchStatement", start, end, discriminant: f1 !== NULL ? node(f1) : null, cases: nodeArr(f2, f0) };
|
|
@@ -195,13 +401,53 @@ function decode(buffer, source) {
|
|
|
195
401
|
case 65: return { type: "EmptyStatement", start, end };
|
|
196
402
|
case 66: { const r = { type: "VariableDeclaration", start, end, kind: VAR_KINDS[flags & 7], declarations: nodeArr(f1, f0) }; if (_isTs) { r.declare = !!(flags & 8); } return r; }
|
|
197
403
|
case 67: { const r = { type: "VariableDeclarator", start, end, id: f1 !== NULL ? node(f1) : null, init: f2 !== NULL ? node(f2) : null }; if (_isTs) { r.definite = !!(flags & 1); } return r; }
|
|
198
|
-
case 68: return {
|
|
404
|
+
case 68: return {
|
|
405
|
+
type: "ExpressionStatement", start, end,
|
|
406
|
+
expression: node(f1), directive: str(f2, f3),
|
|
407
|
+
};
|
|
199
408
|
case 69: { const r = { type: "AssignmentPattern", start, end, left: f1 !== NULL ? node(f1) : null, right: f2 !== NULL ? node(f2) : null }; if (_isTs) { r.decorators = nodeArr(f3, f0); r.typeAnnotation = f4 !== NULL ? node(f4) : null; r.optional = !!(flags & 1); } return r; }
|
|
200
409
|
case 70: { const r = { type: "RestElement", start, end, argument: f1 !== NULL ? node(f1) : null }; if (_isTs) { r.decorators = nodeArr(f2, f0); r.typeAnnotation = f3 !== NULL ? node(f3) : null; r.optional = !!(flags & 1); r.value = null; } return r; }
|
|
201
|
-
case 71: {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
410
|
+
case 71: {
|
|
411
|
+
const el = nodeArrHoles(f1, f0);
|
|
412
|
+
if (f2 !== NULL) el.push(node(f2));
|
|
413
|
+
const r = { type: "ArrayPattern", start, end, elements: el };
|
|
414
|
+
if (_isTs) {
|
|
415
|
+
r.decorators = nodeArr(f3, f4);
|
|
416
|
+
r.optional = !!(flags & 1);
|
|
417
|
+
r.typeAnnotation = f5 !== NULL ? node(f5) : null;
|
|
418
|
+
}
|
|
419
|
+
return r;
|
|
420
|
+
}
|
|
421
|
+
case 72: {
|
|
422
|
+
const pr = nodeArr(f1, f0);
|
|
423
|
+
if (f2 !== NULL) pr.push(node(f2));
|
|
424
|
+
const r = { type: "ObjectPattern", start, end, properties: pr };
|
|
425
|
+
if (_isTs) {
|
|
426
|
+
r.decorators = nodeArr(f3, f4);
|
|
427
|
+
r.optional = !!(flags & 1);
|
|
428
|
+
r.typeAnnotation = f5 !== NULL ? node(f5) : null;
|
|
429
|
+
}
|
|
430
|
+
return r;
|
|
431
|
+
}
|
|
432
|
+
case 73: {
|
|
433
|
+
const r = {
|
|
434
|
+
type: "Property", start, end,
|
|
435
|
+
kind: "init",
|
|
436
|
+
key: node(f1), value: node(f2),
|
|
437
|
+
method: false,
|
|
438
|
+
shorthand: !!(flags & 1),
|
|
439
|
+
computed: !!(flags & 2),
|
|
440
|
+
}; if (_isTs) { r.optional = false; } return r; }
|
|
441
|
+
case 74: return {
|
|
442
|
+
type: "Program", start, end,
|
|
443
|
+
sourceType: (flags & 1) ? "module" : "script",
|
|
444
|
+
hashbang: (flags & 2) ? {
|
|
445
|
+
type: "Hashbang",
|
|
446
|
+
start: _p(f2 - 2), end: _p(f3),
|
|
447
|
+
value: str(f2, f3),
|
|
448
|
+
} : null,
|
|
449
|
+
body: nodeArr(f1, f0),
|
|
450
|
+
};
|
|
205
451
|
case 75: return { type: "ImportExpression", start, end, source: f1 !== NULL ? node(f1) : null, options: f2 !== NULL ? node(f2) : null, phase: (flags & 1) ? ["source", "defer"][(flags >> 1) & 1] : null };
|
|
206
452
|
case 76: { const r = { type: "ImportDeclaration", start, end, specifiers: nodeArr(f1, f0), source: f2 !== NULL ? node(f2) : null, attributes: nodeArr(f3, f4), phase: (flags & 1) ? ["source", "defer"][(flags >> 1) & 1] : null }; if (_isTs) { r.importKind = IMPORT_EXPORT_KINDS[(flags >> 2) & 1]; } return r; }
|
|
207
453
|
case 77: { const r = { type: "ImportSpecifier", start, end, imported: f1 !== NULL ? node(f1) : null, local: f2 !== NULL ? node(f2) : null }; if (_isTs) { r.importKind = IMPORT_EXPORT_KINDS[flags & 1]; } return r; }
|
|
@@ -251,15 +497,54 @@ function decode(buffer, source) {
|
|
|
251
497
|
case 121: return { type: "TSInferType", start, end, typeParameter: f1 !== NULL ? node(f1) : null };
|
|
252
498
|
case 122: return { type: "TSTypeOperator", start, end, operator: TS_TYPE_OPERATORS[flags & 3], typeAnnotation: f1 !== NULL ? node(f1) : null };
|
|
253
499
|
case 123: return { type: "TSParenthesizedType", start, end, typeAnnotation: f1 !== NULL ? node(f1) : null };
|
|
254
|
-
case 124: return {
|
|
255
|
-
|
|
500
|
+
case 124: return {
|
|
501
|
+
type: "TSFunctionType", start, end,
|
|
502
|
+
typeParameters: f1 !== NULL ? node(f1) : null,
|
|
503
|
+
params: f2 !== NULL ? fnParams(f2) : [],
|
|
504
|
+
returnType: f3 !== NULL ? node(f3) : null,
|
|
505
|
+
};
|
|
506
|
+
case 125: return {
|
|
507
|
+
type: "TSConstructorType", start, end,
|
|
508
|
+
abstract: !!(flags & 1),
|
|
509
|
+
typeParameters: f1 !== NULL ? node(f1) : null,
|
|
510
|
+
params: f2 !== NULL ? fnParams(f2) : [],
|
|
511
|
+
returnType: f3 !== NULL ? node(f3) : null,
|
|
512
|
+
};
|
|
256
513
|
case 126: return { type: "TSTypePredicate", start, end, parameterName: f1 !== NULL ? node(f1) : null, typeAnnotation: f2 !== NULL ? node(f2) : null, asserts: !!(flags & 1) };
|
|
257
514
|
case 127: return { type: "TSTypeLiteral", start, end, members: nodeArr(f1, f0) };
|
|
258
|
-
case 128: return {
|
|
515
|
+
case 128: return {
|
|
516
|
+
type: "TSMappedType", start, end,
|
|
517
|
+
key: node(f1),
|
|
518
|
+
constraint: node(f2),
|
|
519
|
+
nameType: f3 !== NULL ? node(f3) : null,
|
|
520
|
+
typeAnnotation: f4 !== NULL ? node(f4) : null,
|
|
521
|
+
optional: TS_MAPPED_OPTIONAL[(flags >> 0) & 3],
|
|
522
|
+
readonly: TS_MAPPED_READONLY[(flags >> 2) & 3],
|
|
523
|
+
};
|
|
259
524
|
case 129: { const r = { type: "TSPropertySignature", start, end, key: f1 !== NULL ? node(f1) : null, typeAnnotation: f2 !== NULL ? node(f2) : null, computed: !!(flags & 1), optional: !!(flags & 2), readonly: !!(flags & 4) }; if (_isTs) { r.accessibility = null; r.static = false; } return r; }
|
|
260
|
-
case 130: return {
|
|
261
|
-
|
|
262
|
-
|
|
525
|
+
case 130: return {
|
|
526
|
+
type: "TSMethodSignature", start, end,
|
|
527
|
+
key: node(f1),
|
|
528
|
+
computed: !!(flags & 4),
|
|
529
|
+
optional: !!(flags & 8),
|
|
530
|
+
kind: TS_METHOD_SIGNATURE_KINDS[(flags >> 0) & 3],
|
|
531
|
+
typeParameters: f2 !== NULL ? node(f2) : null,
|
|
532
|
+
params: f3 !== NULL ? fnParams(f3) : [],
|
|
533
|
+
returnType: f4 !== NULL ? node(f4) : null,
|
|
534
|
+
accessibility: null, readonly: false, static: false,
|
|
535
|
+
};
|
|
536
|
+
case 131: return {
|
|
537
|
+
type: "TSCallSignatureDeclaration", start, end,
|
|
538
|
+
typeParameters: f1 !== NULL ? node(f1) : null,
|
|
539
|
+
params: f2 !== NULL ? fnParams(f2) : [],
|
|
540
|
+
returnType: f3 !== NULL ? node(f3) : null,
|
|
541
|
+
};
|
|
542
|
+
case 132: return {
|
|
543
|
+
type: "TSConstructSignatureDeclaration", start, end,
|
|
544
|
+
typeParameters: f1 !== NULL ? node(f1) : null,
|
|
545
|
+
params: f2 !== NULL ? fnParams(f2) : [],
|
|
546
|
+
returnType: f3 !== NULL ? node(f3) : null,
|
|
547
|
+
};
|
|
263
548
|
case 133: { const r = { type: "TSIndexSignature", start, end, parameters: nodeArr(f1, f0), typeAnnotation: f2 !== NULL ? node(f2) : null, readonly: !!(flags & 1) }; if (_isTs) { r.static = !!(flags & 2); r.accessibility = null; } return r; }
|
|
264
549
|
case 134: return { type: "TSTypeAliasDeclaration", start, end, id: f1 !== NULL ? node(f1) : null, typeParameters: f2 !== NULL ? node(f2) : null, typeAnnotation: f3 !== NULL ? node(f3) : null, declare: !!(flags & 1) };
|
|
265
550
|
case 135: return { type: "TSInterfaceDeclaration", start, end, id: f1 !== NULL ? node(f1) : null, typeParameters: f2 !== NULL ? node(f2) : null, extends: nodeArr(f3, f0), body: f4 !== NULL ? node(f4) : null, declare: !!(flags & 1) };
|
|
@@ -269,11 +554,32 @@ function decode(buffer, source) {
|
|
|
269
554
|
case 139: return { type: "TSEnumDeclaration", start, end, id: f1 !== NULL ? node(f1) : null, body: f2 !== NULL ? node(f2) : null, const: !!(flags & 1), declare: !!(flags & 2) };
|
|
270
555
|
case 140: return { type: "TSEnumBody", start, end, members: nodeArr(f1, f0) };
|
|
271
556
|
case 141: return { type: "TSEnumMember", start, end, id: f1 !== NULL ? node(f1) : null, initializer: f2 !== NULL ? node(f2) : null, computed: !!(flags & 1) };
|
|
272
|
-
case 142: {
|
|
557
|
+
case 142: {
|
|
558
|
+
const r = {
|
|
559
|
+
type: "TSModuleDeclaration", start, end,
|
|
560
|
+
id: node(f1),
|
|
561
|
+
kind: TS_MODULE_KINDS[(flags >> 0) & 1],
|
|
562
|
+
declare: !!(flags & 2),
|
|
563
|
+
global: false,
|
|
564
|
+
};
|
|
565
|
+
if (f2 !== NULL) r.body = node(f2);
|
|
566
|
+
return r;
|
|
567
|
+
}
|
|
273
568
|
case 143: return { type: "TSModuleBlock", start, end, body: nodeArr(f1, f0) };
|
|
274
|
-
case 144: return {
|
|
569
|
+
case 144: return {
|
|
570
|
+
type: "TSModuleDeclaration", start, end,
|
|
571
|
+
id: node(f1), body: node(f2),
|
|
572
|
+
kind: "global",
|
|
573
|
+
declare: !!(flags & 1),
|
|
574
|
+
global: true,
|
|
575
|
+
};
|
|
275
576
|
case 145: { const r = { type: "TSParameterProperty", start, end, decorators: nodeArr(f1, f0), parameter: f2 !== NULL ? node(f2) : null, override: !!(flags & 1), readonly: !!(flags & 2), accessibility: ACCESSIBILITY[(flags >> 2) & 3] }; if (_isTs) { r.static = false; } return r; }
|
|
276
|
-
case 146: return {
|
|
577
|
+
case 146: return {
|
|
578
|
+
type: "Identifier", start, end,
|
|
579
|
+
decorators: [],
|
|
580
|
+
name: "this", kind: "this", optional: false,
|
|
581
|
+
typeAnnotation: f1 !== NULL ? node(f1) : null,
|
|
582
|
+
};
|
|
277
583
|
case 147: return { type: "TSAsExpression", start, end, expression: f1 !== NULL ? node(f1) : null, typeAnnotation: f2 !== NULL ? node(f2) : null };
|
|
278
584
|
case 148: return { type: "TSSatisfiesExpression", start, end, expression: f1 !== NULL ? node(f1) : null, typeAnnotation: f2 !== NULL ? node(f2) : null };
|
|
279
585
|
case 149: return { type: "TSTypeAssertion", start, end, typeAnnotation: f1 !== NULL ? node(f1) : null, expression: f2 !== NULL ? node(f2) : null };
|
|
@@ -296,35 +602,21 @@ function decode(buffer, source) {
|
|
|
296
602
|
case 166: return { type: "JSXSpreadAttribute", start, end, argument: f1 !== NULL ? node(f1) : null };
|
|
297
603
|
case 167: return { type: "JSXExpressionContainer", start, end, expression: f1 !== NULL ? node(f1) : null };
|
|
298
604
|
case 168: return { type: "JSXEmptyExpression", start, end };
|
|
299
|
-
case 169: {
|
|
605
|
+
case 169: {
|
|
606
|
+
const t = str(f1, f2);
|
|
607
|
+
return { type: "JSXText", start, end, value: t, raw: t };
|
|
608
|
+
}
|
|
300
609
|
case 170: return { type: "JSXSpreadChild", start, end, expression: f1 !== NULL ? node(f1) : null };
|
|
301
610
|
}
|
|
302
611
|
}
|
|
303
|
-
const
|
|
304
|
-
const lsOff = cOff + commentCount * 20;
|
|
612
|
+
const lsOff = _cOff + commentCount * 12;
|
|
305
613
|
const dOff = lsOff + lineStartsCount * 4;
|
|
306
|
-
const dv = new DataView(buffer);
|
|
307
|
-
function _decodeComments() {
|
|
308
|
-
const out = new Array(commentCount);
|
|
309
|
-
for (let j = 0; j < commentCount; j++) {
|
|
310
|
-
const o = cOff + j * 20;
|
|
311
|
-
const flags = _u8[o + 2];
|
|
312
|
-
out[j] = {
|
|
313
|
-
type: COMMENT_TYPES[_u8[o + 0]],
|
|
314
|
-
kind: COMMENT_KINDS[_u8[o + 1]],
|
|
315
|
-
precededByNewline: (flags & 1) !== 0,
|
|
316
|
-
followedByNewline: (flags & 2) !== 0,
|
|
317
|
-
value: str(dv.getUint32(o + 12, true), dv.getUint32(o + 16, true)),
|
|
318
|
-
start: _p(dv.getUint32(o + 4, true)),
|
|
319
|
-
end: _p(dv.getUint32(o + 8, true)),
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
return out;
|
|
323
|
-
}
|
|
324
614
|
function _decodeLineStarts() {
|
|
325
615
|
const out = new Array(lineStartsCount);
|
|
326
616
|
if (_firstNa >= _srcLen) {
|
|
327
|
-
for (let j = 0; j < lineStartsCount; j++)
|
|
617
|
+
for (let j = 0; j < lineStartsCount; j++) {
|
|
618
|
+
out[j] = dv.getUint32(lsOff + j * 4, true);
|
|
619
|
+
}
|
|
328
620
|
return out;
|
|
329
621
|
}
|
|
330
622
|
if (pm === null) pm = buildPosMap(_src, _srcLen, _firstNa);
|
|
@@ -345,25 +637,51 @@ function decode(buffer, source) {
|
|
|
345
637
|
const msg = _td.decode(_u8.subarray(dp, dp + ml)); dp += ml;
|
|
346
638
|
const hh = _u8[dp]; dp++;
|
|
347
639
|
let help = null;
|
|
348
|
-
if (hh) {
|
|
640
|
+
if (hh) {
|
|
641
|
+
const hl = dv.getUint32(dp, true); dp += 4;
|
|
642
|
+
help = _td.decode(_u8.subarray(dp, dp + hl)); dp += hl;
|
|
643
|
+
}
|
|
349
644
|
const lc = dv.getUint32(dp, true); dp += 4;
|
|
350
645
|
const labels = new Array(lc);
|
|
351
646
|
for (let k = 0; k < lc; k++) {
|
|
352
647
|
const ls = _p(dv.getUint32(dp, true)); dp += 4;
|
|
353
648
|
const le = _p(dv.getUint32(dp, true)); dp += 4;
|
|
354
649
|
const lml = dv.getUint32(dp, true); dp += 4;
|
|
355
|
-
labels[k] = {
|
|
650
|
+
labels[k] = {
|
|
651
|
+
start: ls,
|
|
652
|
+
end: le,
|
|
653
|
+
message: _td.decode(_u8.subarray(dp, dp + lml)),
|
|
654
|
+
};
|
|
655
|
+
dp += lml;
|
|
356
656
|
}
|
|
357
657
|
out[j] = { severity: sev, message: msg, start: ds, end: de, help, labels };
|
|
358
658
|
}
|
|
359
659
|
return out;
|
|
360
660
|
}
|
|
361
|
-
let _program,
|
|
661
|
+
let _program, _lineStarts, _diagnostics;
|
|
662
|
+
function _getLineStarts() {
|
|
663
|
+
if (_lineStarts === undefined) _lineStarts = _decodeLineStarts();
|
|
664
|
+
return _lineStarts;
|
|
665
|
+
}
|
|
362
666
|
return {
|
|
363
|
-
get program() {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
get diagnostics() {
|
|
667
|
+
get program() {
|
|
668
|
+
return _program !== undefined ? _program : (_program = node(progIdx));
|
|
669
|
+
},
|
|
670
|
+
get diagnostics() {
|
|
671
|
+
return _diagnostics !== undefined
|
|
672
|
+
? _diagnostics
|
|
673
|
+
: (_diagnostics = _decodeDiagnostics());
|
|
674
|
+
},
|
|
675
|
+
get lineStarts() { return _getLineStarts(); },
|
|
676
|
+
locOf(offset) {
|
|
677
|
+
const ls = _getLineStarts();
|
|
678
|
+
let lo = 0, hi = ls.length;
|
|
679
|
+
while (lo < hi) {
|
|
680
|
+
const mid = (lo + hi) >>> 1;
|
|
681
|
+
if (ls[mid] <= offset) lo = mid + 1; else hi = mid;
|
|
682
|
+
}
|
|
683
|
+
return { line: lo, column: offset - ls[lo - 1] };
|
|
684
|
+
},
|
|
367
685
|
};
|
|
368
686
|
}
|
|
369
687
|
export { decode };
|
package/index.d.ts
CHANGED
|
@@ -40,38 +40,39 @@ interface ParseOptions {
|
|
|
40
40
|
* @default false
|
|
41
41
|
*/
|
|
42
42
|
semanticErrors?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Collect comments and attach them to host AST nodes via
|
|
45
|
+
* {@link BaseNode.comments}.
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
attachComments?: boolean;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
/** Whether a {@link Comment} came from a line or block source comment. */
|
|
46
52
|
type CommentType = "Line" | "Block";
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
|
-
*
|
|
50
|
-
* consumers can route comments without rescanning their value.
|
|
55
|
+
* Position of a {@link Comment} relative to its host node.
|
|
51
56
|
*
|
|
52
|
-
* - `
|
|
53
|
-
* - `
|
|
54
|
-
* - `
|
|
55
|
-
* - `"annotation"`: `/*# ... *\/` or `/*@ ... *\/` other than tree-shaking.
|
|
56
|
-
* - `"pure"`: `/*#__PURE__*\/` or `/*@__PURE__*\/`.
|
|
57
|
-
* - `"no_side_effects"`: `/*#__NO_SIDE_EFFECTS__*\/` or `/*@__NO_SIDE_EFFECTS__*\/`.
|
|
57
|
+
* - `before`: leading the host.
|
|
58
|
+
* - `after`: trailing the host.
|
|
59
|
+
* - `inside`: interior to an otherwise empty host.
|
|
58
60
|
*/
|
|
59
|
-
type
|
|
61
|
+
type CommentPosition = "before" | "after" | "inside";
|
|
60
62
|
|
|
61
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* A source code comment attached to a single host AST node.
|
|
65
|
+
*
|
|
66
|
+
* `sameLine` is true when the comment shares a source line with the
|
|
67
|
+
* host's adjacent edge (host's start for `before`, host's end for
|
|
68
|
+
* `after`). For `inside` it is always `false`.
|
|
69
|
+
*/
|
|
62
70
|
interface Comment {
|
|
63
71
|
type: CommentType;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
precededByNewline: boolean;
|
|
67
|
-
/** True when a line terminator immediately follows this comment. */
|
|
68
|
-
followedByNewline: boolean;
|
|
72
|
+
position: CommentPosition;
|
|
73
|
+
sameLine: boolean;
|
|
69
74
|
/** Comment text without the delimiters. */
|
|
70
75
|
value: string;
|
|
71
|
-
/** Byte offset. */
|
|
72
|
-
start: number;
|
|
73
|
-
/** Byte offset. */
|
|
74
|
-
end: number;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
/** A labeled source span attached to a {@link Diagnostic}. */
|
|
@@ -103,16 +104,34 @@ interface Diagnostic {
|
|
|
103
104
|
labels: DiagnosticLabel[];
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
/**
|
|
108
|
+
* A `(line, column)` pair into the source, matching ESTree's `loc` convention.
|
|
109
|
+
* Lines are 1-based; columns are 0-based.
|
|
110
|
+
*/
|
|
111
|
+
interface SourceLocation {
|
|
112
|
+
/** 1-based line number. */
|
|
113
|
+
line: number;
|
|
114
|
+
/** 0-based column number within the line. */
|
|
115
|
+
column: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
106
118
|
/** The result returned by the parser. */
|
|
107
119
|
interface ParseResult {
|
|
108
120
|
/** Root ESTree/TypeScript-ESTree AST node. */
|
|
109
121
|
program: Program;
|
|
110
|
-
/** All comments in source order. */
|
|
111
|
-
comments: Comment[];
|
|
112
|
-
/** Byte offset where each source line begins. Index 0 is always 0. */
|
|
113
|
-
lineStarts: number[];
|
|
114
122
|
/** Syntax diagnostics, and semantic diagnostics when {@link ParseOptions.semanticErrors} is enabled. */
|
|
115
123
|
diagnostics: Diagnostic[];
|
|
124
|
+
/**
|
|
125
|
+
* Sorted UTF-16 offsets where each line begins. Index `i` is the start of
|
|
126
|
+
* line `i + 1`. Used internally by {@link locOf}, and required by
|
|
127
|
+
* `yuku-codegen` for source maps.
|
|
128
|
+
*/
|
|
129
|
+
lineStarts: number[];
|
|
130
|
+
/**
|
|
131
|
+
* Resolves an offset to a `{ line, column }` pair. Lines are
|
|
132
|
+
* 1-based, columns are 0-based, matching ESTree's `loc` convention.
|
|
133
|
+
*/
|
|
134
|
+
locOf(offset: number): SourceLocation;
|
|
116
135
|
}
|
|
117
136
|
|
|
118
137
|
/**
|
|
@@ -144,6 +163,11 @@ export function sourceTypeFromPath(path: string): SourceType;
|
|
|
144
163
|
interface BaseNode {
|
|
145
164
|
start: number;
|
|
146
165
|
end: number;
|
|
166
|
+
/**
|
|
167
|
+
* Comments attached to this node in source order. Present only when
|
|
168
|
+
* {@link ParseOptions.attachComments} is enabled.
|
|
169
|
+
*/
|
|
170
|
+
comments?: Comment[];
|
|
147
171
|
}
|
|
148
172
|
|
|
149
173
|
type Span = BaseNode;
|
|
@@ -230,39 +254,37 @@ type PropertyDefinitionType = "PropertyDefinition" | "TSAbstractPropertyDefiniti
|
|
|
230
254
|
|
|
231
255
|
type AccessorPropertyType = "AccessorProperty" | "TSAbstractAccessorProperty";
|
|
232
256
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
optional?: false;
|
|
246
|
-
typeAnnotation?: null;
|
|
247
|
-
}
|
|
257
|
+
/**
|
|
258
|
+
* Role of an `Identifier` within the AST. Yuku exposes the four ESTree-collapsed
|
|
259
|
+
* identifier flavors as a discriminator, plus `"this"` for a TS `this`-parameter
|
|
260
|
+
* (which TS-ESTree also encodes as an `Identifier` with `name: "this"`).
|
|
261
|
+
*
|
|
262
|
+
* - `"reference"`: identifier read as a value (`x` in `x + 1`, `console`).
|
|
263
|
+
* - `"binding"`: identifier being declared (parameters, `let x`, function/class names).
|
|
264
|
+
* - `"name"`: identifier in a non-binding name slot (property/method names like `log` in `console.log`).
|
|
265
|
+
* - `"label"`: loop label (`outer` in `outer: for (...) {}`).
|
|
266
|
+
* - `"this"`: the TS `this`-parameter (`function f(this: T)`).
|
|
267
|
+
*/
|
|
268
|
+
type IdentifierKind = "reference" | "binding" | "name" | "label" | "this";
|
|
248
269
|
|
|
249
|
-
interface
|
|
270
|
+
interface Identifier extends BaseNode {
|
|
250
271
|
type: "Identifier";
|
|
251
272
|
name: string;
|
|
273
|
+
/**
|
|
274
|
+
* ESTree collapses several distinct identifier
|
|
275
|
+
* roles onto one `Identifier` node, `kind` lets you tell them apart without
|
|
276
|
+
* walking the parent context. See {@link IdentifierKind}.
|
|
277
|
+
*/
|
|
278
|
+
kind: IdentifierKind;
|
|
252
279
|
decorators?: Decorator[];
|
|
253
280
|
optional?: boolean;
|
|
254
281
|
typeAnnotation?: TSTypeAnnotation | null;
|
|
255
282
|
}
|
|
256
283
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
optional?: false;
|
|
262
|
-
typeAnnotation?: null;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
type Identifier = IdentifierName | IdentifierReference | BindingIdentifier | LabelIdentifier;
|
|
284
|
+
type IdentifierName = Identifier;
|
|
285
|
+
type IdentifierReference = Identifier;
|
|
286
|
+
type BindingIdentifier = Identifier;
|
|
287
|
+
type LabelIdentifier = Identifier;
|
|
266
288
|
|
|
267
289
|
interface PrivateIdentifier extends BaseNode {
|
|
268
290
|
type: "PrivateIdentifier";
|
|
@@ -1693,6 +1715,7 @@ type Node =
|
|
|
1693
1715
|
| TSAbstractAccessorProperty
|
|
1694
1716
|
| StaticBlock
|
|
1695
1717
|
| Decorator
|
|
1718
|
+
| TSEmptyBodyFunctionExpression
|
|
1696
1719
|
| ImportSpecifier
|
|
1697
1720
|
| ImportDefaultSpecifier
|
|
1698
1721
|
| ImportNamespaceSpecifier
|
|
@@ -1738,13 +1761,14 @@ export type {
|
|
|
1738
1761
|
ParseResult,
|
|
1739
1762
|
Comment,
|
|
1740
1763
|
CommentType,
|
|
1741
|
-
|
|
1764
|
+
CommentPosition,
|
|
1742
1765
|
Diagnostic,
|
|
1743
1766
|
DiagnosticLabel,
|
|
1744
1767
|
DiagnosticSeverity,
|
|
1745
1768
|
SourceType,
|
|
1746
1769
|
ModuleKind,
|
|
1747
1770
|
SourceLang,
|
|
1771
|
+
SourceLocation,
|
|
1748
1772
|
BaseNode,
|
|
1749
1773
|
Span,
|
|
1750
1774
|
Program,
|
|
@@ -1769,6 +1793,7 @@ export type {
|
|
|
1769
1793
|
ModuleExportName,
|
|
1770
1794
|
PropertyKey,
|
|
1771
1795
|
Identifier,
|
|
1796
|
+
IdentifierKind,
|
|
1772
1797
|
IdentifierName,
|
|
1773
1798
|
IdentifierReference,
|
|
1774
1799
|
BindingIdentifier,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yuku-parser",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.15",
|
|
4
4
|
"description": "High-performance JavaScript/TypeScript parser",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"decode.js"
|
|
18
18
|
],
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@yuku-parser/binding-linux-x64-gnu": "0.5.
|
|
21
|
-
"@yuku-parser/binding-linux-arm64-gnu": "0.5.
|
|
22
|
-
"@yuku-parser/binding-linux-arm-gnu": "0.5.
|
|
23
|
-
"@yuku-parser/binding-linux-x64-musl": "0.5.
|
|
24
|
-
"@yuku-parser/binding-linux-arm64-musl": "0.5.
|
|
25
|
-
"@yuku-parser/binding-linux-arm-musl": "0.5.
|
|
26
|
-
"@yuku-parser/binding-darwin-x64": "0.5.
|
|
27
|
-
"@yuku-parser/binding-darwin-arm64": "0.5.
|
|
28
|
-
"@yuku-parser/binding-win32-x64": "0.5.
|
|
29
|
-
"@yuku-parser/binding-win32-arm64": "0.5.
|
|
30
|
-
"@yuku-parser/binding-freebsd-x64": "0.5.
|
|
20
|
+
"@yuku-parser/binding-linux-x64-gnu": "0.5.15",
|
|
21
|
+
"@yuku-parser/binding-linux-arm64-gnu": "0.5.15",
|
|
22
|
+
"@yuku-parser/binding-linux-arm-gnu": "0.5.15",
|
|
23
|
+
"@yuku-parser/binding-linux-x64-musl": "0.5.15",
|
|
24
|
+
"@yuku-parser/binding-linux-arm64-musl": "0.5.15",
|
|
25
|
+
"@yuku-parser/binding-linux-arm-musl": "0.5.15",
|
|
26
|
+
"@yuku-parser/binding-darwin-x64": "0.5.15",
|
|
27
|
+
"@yuku-parser/binding-darwin-arm64": "0.5.15",
|
|
28
|
+
"@yuku-parser/binding-win32-x64": "0.5.15",
|
|
29
|
+
"@yuku-parser/binding-win32-arm64": "0.5.15",
|
|
30
|
+
"@yuku-parser/binding-freebsd-x64": "0.5.15"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
|
33
33
|
"acorn",
|