@teasel/parser 0.0.0 → 0.0.2
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 +138 -2
- package/api.js +185 -0
- package/decode.js +282 -0
- package/identifier.js +218 -0
- package/index.d.ts +256 -0
- package/index.js +26 -0
- package/native.js +22 -0
- package/package.json +54 -3
- package/teasel.wasm +0 -0
- package/wasm.d.ts +1 -0
- package/wasm.js +62 -0
package/README.md
CHANGED
|
@@ -1,3 +1,139 @@
|
|
|
1
|
-
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="banner-dark.svg">
|
|
3
|
+
<img src="banner.svg" width="100%" alt="">
|
|
4
|
+
</picture>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
<h1 align="center">teasel</h1>
|
|
7
|
+
<p align="center">A JavaScript and TypeScript parser in Rust. It answers in ESTree.</p>
|
|
8
|
+
|
|
9
|
+
<br>
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { Source } from '@teasel/parser';
|
|
13
|
+
|
|
14
|
+
const source = new Source(text, { typescript: true, scopes: true });
|
|
15
|
+
const { node } = source.parse();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Every parse is `source.parse(entry, offset, { end, stopAt })`. Every answer is `{ node, end }` and what the options add. A source is disposable: `using source = new Source(text)` releases what the engine holds for it at the end of the block, and the collector does otherwise.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
source.parse() Program
|
|
22
|
+
source.parse('expression', 7) the expression that starts at 7
|
|
23
|
+
source.parse('pattern', 7) an assignment target: a name or a destructuring
|
|
24
|
+
source.parse('params', 7) the patterns of a (a, b = 1)
|
|
25
|
+
source.parse('statement', 7) one statement
|
|
26
|
+
source.parse('typeParameters', 7) a <T extends U>
|
|
27
|
+
source.parse('program', 12, { end: 40 }) the program inside 12..40, positions of the whole
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Inside a larger syntax
|
|
31
|
+
|
|
32
|
+
A host that embeds JavaScript in its own reads one piece at a time, from an offset, and gets back where its own syntax resumes.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
{{ items as item, index }}
|
|
36
|
+
▲ ▲
|
|
37
|
+
3 8
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const { node, end } = source.parse('expression', 3, { stopAt: ['as', ','] });
|
|
42
|
+
// node Identifier items
|
|
43
|
+
// end 8
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`stopAt` lists the host's own tokens. One read outside every bracket the parse opened, where the expression could end, ends the parse: `,` does not start a sequence, `/>` is not a division. A `then` after `.` is a property name. A TypeScript `as` is the host's unless another `as` follows the assertion, so `xs as T[] as item` ends after the type.
|
|
47
|
+
|
|
48
|
+
## What the options add
|
|
49
|
+
|
|
50
|
+
| option | on the tree | on the answer |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| `locations` | `loc` with line and column on every node | |
|
|
53
|
+
| `comments` | `leadingComments`, `trailingComments`, `innerComments` | `comments`, every comment read |
|
|
54
|
+
| `scopes` | | `scopes`, `bindings`, `references`, and the four questions below |
|
|
55
|
+
| `parenthesized` | `parenthesized: true` on a node the source wraps in parens | |
|
|
56
|
+
| `errorRecovery` | an `Identifier` named `''` of no width where something is missing | `errors`, instead of a throw |
|
|
57
|
+
| `typescript` | TypeScript nodes | |
|
|
58
|
+
| `decorators: 'legacy'` or `'proposal'` | restricts decorator syntax; unset reads both | |
|
|
59
|
+
| `typescript: 'erase'` | JavaScript, the types gone | `typescript`, what could not be erased: enums, namespaces with values, parameter properties, `export =`, `import =`, decorators, accessor fields |
|
|
60
|
+
| `sourceType: 'module'` | strict code, `import`, `export`, top-level `await` | |
|
|
61
|
+
|
|
62
|
+
A key is on the answer exactly when its option is on. `allowReturnOutsideFunction`, `allowAwaitOutsideFunction`, `allowSuperOutsideMethod` and `allowUndeclaredExports` loosen the early errors as their names say.
|
|
63
|
+
|
|
64
|
+
## Scopes
|
|
65
|
+
|
|
66
|
+
The tree stays plain ESTree. The facts hang beside it, reached from a node.
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { Source, scopeOf, bindingOf, referenceOf, parentOf } from '@teasel/parser';
|
|
70
|
+
|
|
71
|
+
const { node } = new Source('let x = 1; function f(y) { x = y; }', { scopes: true }).parse();
|
|
72
|
+
const [declaration, fn] = node.body;
|
|
73
|
+
const assignment = fn.body.body[0].expression;
|
|
74
|
+
|
|
75
|
+
bindingOf(declaration.declarations[0].id) // { name: 'x', kind: 'let', scope, node, declaration }
|
|
76
|
+
referenceOf(assignment.left) // { scope, binding, write: true, read: false, mutate: false, node, writeExpr }
|
|
77
|
+
scopeOf(fn) // { kind: 'function', parent, node, topLevelAwait: false }
|
|
78
|
+
parentOf(assignment.left) // the assignment
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Program ──────────────────── scope: module
|
|
83
|
+
├─ let x = 1 x binding let
|
|
84
|
+
└─ function f(y) { scope: function
|
|
85
|
+
│ y binding param
|
|
86
|
+
└─ x = y x reference write y reference read
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
A reference to a name no scope declares has `binding: null`. A copy of a node carries no facts.
|
|
90
|
+
|
|
91
|
+
## Errors
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
try {
|
|
95
|
+
new Source('x = ;').parse();
|
|
96
|
+
} catch (e) {
|
|
97
|
+
e.code; // 'unexpected_token'
|
|
98
|
+
e.pos; // 4
|
|
99
|
+
e.end; // 5
|
|
100
|
+
e.loc; // { line: 1, column: 4 }
|
|
101
|
+
e.message; // 'Unexpected token'
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
With `errorRecovery`, the parse comes back and the errors come with it.
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
{ f(a, }
|
|
109
|
+
▲
|
|
110
|
+
errors [{ code: 'unexpected_token', pos: 7, end: 7, loc }]
|
|
111
|
+
node Identifier '' at 7..7
|
|
112
|
+
end 7
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Rust and the command line
|
|
116
|
+
|
|
117
|
+
```rust
|
|
118
|
+
let (ast, roots, end) = teasel::parse_at(source, 0, None, Entry::Program, options, "")?;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
teasel --typescript --scopes file.ts
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Build
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
cargo build --release
|
|
129
|
+
cd package
|
|
130
|
+
bun run build # the Node addon
|
|
131
|
+
bun run build:wasm # the WebAssembly module
|
|
132
|
+
bun test.js
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Node resolves `@teasel/parser` to the addon and everything else to the WebAssembly module, with the same API.
|
|
136
|
+
|
|
137
|
+
<br>
|
|
138
|
+
|
|
139
|
+
<p align="center"><sub>Named after the plant whose dried heads were used to tease apart wool fibres and raise the nap on cloth.</sub></p>
|
package/api.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { decode, facts } from './decode.js';
|
|
2
|
+
import { isIdentifierStart, isIdentifierChar } from './identifier.js';
|
|
3
|
+
|
|
4
|
+
// acorn's option names, which `Request::set` of json.rs takes as they are
|
|
5
|
+
const OPTIONS = new Set(['sourceType', 'typescript', 'decorators', 'comments', 'scopes', 'locations', 'parenthesized', 'allowReturnOutsideFunction', 'allowAwaitOutsideFunction', 'allowSuperOutsideMethod', 'allowUndeclaredExports', 'errorRecovery']);
|
|
6
|
+
|
|
7
|
+
// the engine takes the options that are on as their names
|
|
8
|
+
export function names(options) {
|
|
9
|
+
if (options === undefined) return '';
|
|
10
|
+
const on = [];
|
|
11
|
+
for (const key in options) {
|
|
12
|
+
const value = options[key];
|
|
13
|
+
if (key === 'host') {
|
|
14
|
+
if (value !== undefined && typeof value !== 'string') throw new TypeError('host must be the grammar as a string');
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (!OPTIONS.has(key)) throw new TypeError(`${key} is not an option`);
|
|
18
|
+
if (value === undefined || value === false) continue;
|
|
19
|
+
if (key === 'decorators') {
|
|
20
|
+
if (value !== 'legacy' && value !== 'proposal') throw new TypeError(`decorators must be "legacy" or "proposal", not ${JSON.stringify(value)}`);
|
|
21
|
+
on.push(`${value}Decorators`);
|
|
22
|
+
} else if (key === 'sourceType') {
|
|
23
|
+
if (value !== 'script' && value !== 'module') throw new TypeError(`sourceType must be "script" or "module", not ${JSON.stringify(value)}`);
|
|
24
|
+
if (value === 'module') on.push('module');
|
|
25
|
+
} else if (value === true) on.push(key);
|
|
26
|
+
else if (key === 'typescript' && value === 'erase') on.push('typescript', 'erase');
|
|
27
|
+
else throw new TypeError(`${key} must be a boolean, not ${JSON.stringify(value)}`);
|
|
28
|
+
}
|
|
29
|
+
return on.join(' ');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// `Entry` of parser/mod.rs by index
|
|
33
|
+
export const ENTRY = { program: 0, expression: 1, pattern: 2, params: 3, statement: 4, typeParameters: 5 };
|
|
34
|
+
|
|
35
|
+
// the engine takes the stop tokens as one string
|
|
36
|
+
function stops(list) {
|
|
37
|
+
if (list === undefined) return '';
|
|
38
|
+
if (!Array.isArray(list) || !list.every((stop) => typeof stop === 'string' && stop !== '' && !/\s/.test(stop))) {
|
|
39
|
+
throw new TypeError('stopAt must be a list of words and punctuators');
|
|
40
|
+
}
|
|
41
|
+
return list.join(' ');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {ArrayBuffer | Uint32Array | string} Answer
|
|
46
|
+
* @typedef {object} Engine
|
|
47
|
+
* @property {(source: string, names: string, host: string) => any} create
|
|
48
|
+
* @property {(held: any, entry: number, offset: number, end: number | undefined, stop: string) => Answer} parse
|
|
49
|
+
* @property {(held: any) => void} [free]
|
|
50
|
+
* @property {() => string[]} constants
|
|
51
|
+
* @property {() => ArrayLike<number>} shapes
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
// words the engine has to judge: keywords, the strict-mode reserved words and the contextual ones
|
|
55
|
+
const KEYWORD = new Set('await break case catch class const continue debugger default delete do else enum export extends false finally for function if implements import in instanceof interface let new null package private protected public return static super switch this throw true try typeof var void while with yield'.split(' '));
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The offset after an identifier the host's syntax follows directly, so the answer needs no
|
|
59
|
+
* engine: a name, then optional space, then an unmatched closer, the cut, or one of `stopAt`.
|
|
60
|
+
* Anything the grammar could continue with, a dot or an operator or a TypeScript `as`, and any
|
|
61
|
+
* word the engine has to judge, is left to it.
|
|
62
|
+
* @param {string} source @param {number} at @param {number} end @param {string[] | undefined} stopAt
|
|
63
|
+
* @returns {[number, number] | null} the identifier's end and where the parse ends
|
|
64
|
+
*/
|
|
65
|
+
function bare(source, at, end, stopAt, typescript) {
|
|
66
|
+
let i = at;
|
|
67
|
+
const first = source.codePointAt(i);
|
|
68
|
+
if (first === undefined || !isIdentifierStart(first) || first === 0x5c) return null;
|
|
69
|
+
i += first > 0xffff ? 2 : 1;
|
|
70
|
+
while (i < end) {
|
|
71
|
+
const code = /** @type {number} */ (source.codePointAt(i));
|
|
72
|
+
if (code === 0x5c) return null;
|
|
73
|
+
if (!isIdentifierChar(code)) break;
|
|
74
|
+
i += code > 0xffff ? 2 : 1;
|
|
75
|
+
}
|
|
76
|
+
const name_end = i;
|
|
77
|
+
if (KEYWORD.has(source.slice(at, name_end))) return null;
|
|
78
|
+
while (i < end && /\s/.test(source[i])) i++;
|
|
79
|
+
if (i === end) return [name_end, name_end];
|
|
80
|
+
const c = source[i];
|
|
81
|
+
if (c === '}' || c === ')' || c === ']') return [name_end, name_end];
|
|
82
|
+
if (stopAt !== undefined) {
|
|
83
|
+
for (const stop of stopAt) {
|
|
84
|
+
if (!source.startsWith(stop, i)) continue;
|
|
85
|
+
const after = source.codePointAt(i + stop.length);
|
|
86
|
+
if (isIdentifierStart(/** @type {number} */ (stop.codePointAt(0))) && after !== undefined && isIdentifierChar(after)) continue;
|
|
87
|
+
// a stop TypeScript reads as its own is the engine's to judge
|
|
88
|
+
if (typescript && (stop === 'as' || stop === 'satisfies')) return null;
|
|
89
|
+
return [name_end, name_end];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** @param {Engine} engine */
|
|
96
|
+
export function bind(engine) {
|
|
97
|
+
const registry = engine.free && typeof FinalizationRegistry !== 'undefined' ? new FinalizationRegistry(engine.free) : null;
|
|
98
|
+
|
|
99
|
+
function result(answer, source) {
|
|
100
|
+
if (typeof answer !== 'string') return decode(answer, source, engine);
|
|
101
|
+
const { message, ...error } = JSON.parse(answer).error;
|
|
102
|
+
throw Object.assign(new SyntaxError(message), error);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return class Source {
|
|
106
|
+
#held;
|
|
107
|
+
#source;
|
|
108
|
+
#options;
|
|
109
|
+
/** @type {number[] | undefined} */
|
|
110
|
+
#lines;
|
|
111
|
+
|
|
112
|
+
constructor(source, options) {
|
|
113
|
+
this.#held = engine.create(source, names(options), options?.host ?? '');
|
|
114
|
+
this.#source = source;
|
|
115
|
+
this.#options = options ?? {};
|
|
116
|
+
registry?.register(this, this.#held, this);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {keyof typeof ENTRY} [entry] what to read
|
|
121
|
+
* @param {number} [offset] where it starts
|
|
122
|
+
* @param {{ end?: number, stopAt?: string[] }} [at] where the source is cut, and the host's tokens that end the parse
|
|
123
|
+
*/
|
|
124
|
+
parse(entry = 'program', offset = 0, { end, stopAt } = {}) {
|
|
125
|
+
if (this.#held === undefined) throw new TypeError('the source is freed');
|
|
126
|
+
const index = ENTRY[entry];
|
|
127
|
+
if (index === undefined) throw new TypeError(`${JSON.stringify(entry)} is not an entry`);
|
|
128
|
+
const stop = stops(stopAt);
|
|
129
|
+
if (this.#options.host !== undefined && index === ENTRY.program) return result(engine.parse(this.#held, index, 0, undefined, ''), this.#source);
|
|
130
|
+
if ((index === ENTRY.expression || index === ENTRY.pattern) && Number.isInteger(offset) && offset >= 0) {
|
|
131
|
+
const cut = end === undefined ? this.#source.length : end;
|
|
132
|
+
const found = Number.isInteger(cut) && cut <= this.#source.length && offset <= cut ? bare(this.#source, offset, cut, index === ENTRY.pattern ? [',', '(', ':', '='] : stopAt, !!this.#options.typescript) : null;
|
|
133
|
+
if (found !== null && (index === ENTRY.expression || !this.#source.startsWith(':', found[0]))) return this.#identifier(offset, found[0], index === ENTRY.pattern);
|
|
134
|
+
}
|
|
135
|
+
return result(engine.parse(this.#held, index, offset, end, stop), this.#source);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** The answer the engine would give for a bare identifier, built here. */
|
|
139
|
+
#identifier(start, end, pattern) {
|
|
140
|
+
const o = this.#options;
|
|
141
|
+
/** @type {any} */
|
|
142
|
+
const node = { type: 'Identifier', start, end, name: this.#source.slice(start, end) };
|
|
143
|
+
if (o.locations) node.loc = { start: this.#position(start), end: this.#position(end) };
|
|
144
|
+
/** @type {any} */
|
|
145
|
+
const answer = { node, end };
|
|
146
|
+
if (o.comments) answer.comments = [];
|
|
147
|
+
if (o.errorRecovery) answer.errors = [];
|
|
148
|
+
if (o.typescript === 'erase') answer.typescript = [];
|
|
149
|
+
if (o.scopes) {
|
|
150
|
+
const scope = { kind: 'fragment', parent: null, topLevelAwait: false, node };
|
|
151
|
+
const binding = pattern ? { name: node.name, kind: 'pattern', scope, node, declaration: null } : null;
|
|
152
|
+
const reference = pattern ? null : { scope, binding: null, write: false, read: true, mutate: false, node, writeExpr: null };
|
|
153
|
+
answer.scopes = [scope];
|
|
154
|
+
answer.bindings = binding === null ? [] : [binding];
|
|
155
|
+
answer.references = reference === null ? [] : [reference];
|
|
156
|
+
facts(node, scope, binding, reference);
|
|
157
|
+
} else {
|
|
158
|
+
facts(node, undefined, undefined, undefined);
|
|
159
|
+
}
|
|
160
|
+
return answer;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Line and column of an offset, from a line table built on first use. */
|
|
164
|
+
#position(offset) {
|
|
165
|
+
if (this.#lines === undefined) {
|
|
166
|
+
this.#lines = [0];
|
|
167
|
+
for (let i = this.#source.indexOf('\n'); i !== -1; i = this.#source.indexOf('\n', i + 1)) this.#lines.push(i + 1);
|
|
168
|
+
}
|
|
169
|
+
let lo = 0, hi = this.#lines.length - 1;
|
|
170
|
+
while (lo < hi) {
|
|
171
|
+
const mid = (lo + hi + 1) >> 1;
|
|
172
|
+
if (this.#lines[mid] <= offset) lo = mid;
|
|
173
|
+
else hi = mid - 1;
|
|
174
|
+
}
|
|
175
|
+
return { line: lo + 1, column: offset - this.#lines[lo] };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
[Symbol.dispose]() {
|
|
179
|
+
if (this.#held === undefined) return;
|
|
180
|
+
registry?.unregister(this);
|
|
181
|
+
engine.free?.(this.#held);
|
|
182
|
+
this.#held = undefined;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
package/decode.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
// Turns the addon's shape-coded stream into ESTree objects: what `JSON.parse` did, without the
|
|
2
|
+
// text. The layout is `teasel::estree::Binary`, the kinds `teasel::estree::kind`.
|
|
3
|
+
const HEADER = 7;
|
|
4
|
+
// in a node's place
|
|
5
|
+
const NULL = 0;
|
|
6
|
+
const END = 1;
|
|
7
|
+
|
|
8
|
+
const little = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
|
|
9
|
+
// a leading U+FEFF is text, not a mark
|
|
10
|
+
const utf8 = new TextDecoder('utf-8', { ignoreBOM: true });
|
|
11
|
+
|
|
12
|
+
// symbol keys: ten times cheaper than a WeakMap entry, and skipped by JSON, Object.keys and for-in
|
|
13
|
+
const SCOPE = Symbol('scope');
|
|
14
|
+
const BINDING = Symbol('binding');
|
|
15
|
+
const REFERENCE = Symbol('reference');
|
|
16
|
+
const PARENT = Symbol('parent');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/** @param {import('estree').Node} node @returns {import('./index.js').Scope | undefined} the scope the node opens */
|
|
20
|
+
export const scopeOf = (node) => (node == null ? undefined : node[SCOPE]);
|
|
21
|
+
/** @param {import('estree').Node} node @returns {import('./index.js').Binding | null | undefined} what the identifier declares or refers to; null for a global, undefined when it names no value */
|
|
22
|
+
export const bindingOf = (node) => (node == null ? undefined : node[BINDING]);
|
|
23
|
+
/** @param {import('estree').Node} node @returns {import('./index.js').Reference | undefined} the reference an identifier makes, a global's included */
|
|
24
|
+
export const referenceOf = (node) => (node == null ? undefined : node[REFERENCE]);
|
|
25
|
+
/** @param {import('estree').Node} node @returns {import('estree').Node | undefined} the node it is a child of; undefined for the root of an answer */
|
|
26
|
+
export const parentOf = (node) => (node == null ? undefined : node[PARENT]);
|
|
27
|
+
|
|
28
|
+
const FACTS = new Set(['scope', 'declares', 'reference', 'defines', 'writes', 'root']);
|
|
29
|
+
|
|
30
|
+
/** Files a node built outside the stream as the decoder would: no parent, and its facts when it has them. */
|
|
31
|
+
export function facts(node, scope, binding, reference) {
|
|
32
|
+
node[PARENT] = undefined;
|
|
33
|
+
if (scope !== undefined) node[SCOPE] = scope;
|
|
34
|
+
if (node.type === 'Identifier' || binding !== undefined) node[BINDING] = binding === null ? null : binding;
|
|
35
|
+
if (node.type === 'Identifier' || reference !== undefined) node[REFERENCE] = reference === null ? undefined : reference;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* One decode at a time; the builders are generated once and read through this.
|
|
40
|
+
* @type {{ w: Uint32Array, at: number, strings: string[], floats: Float64Array | null, source: string, constants: string[], scopes: any[], bindings: any[], build: (() => any)[] }}
|
|
41
|
+
*/
|
|
42
|
+
const EMPTY = [];
|
|
43
|
+
|
|
44
|
+
function node(S) {
|
|
45
|
+
const id = S.w[S.at++];
|
|
46
|
+
return id === NULL ? null : S.build[id](S);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function nodes(S) {
|
|
50
|
+
const list = [];
|
|
51
|
+
for (;;) {
|
|
52
|
+
const id = S.w[S.at++];
|
|
53
|
+
if (id === END) return list;
|
|
54
|
+
list.push(id === NULL ? null : S.build[id](S));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ints(S) {
|
|
59
|
+
const n = S.w[S.at++];
|
|
60
|
+
const list = new Array(n);
|
|
61
|
+
for (let i = 0; i < n; i++) list[i] = S.w[S.at++];
|
|
62
|
+
return list;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function strs(S) {
|
|
66
|
+
const n = S.w[S.at++];
|
|
67
|
+
const list = new Array(n);
|
|
68
|
+
for (let i = 0; i < n; i++) list[i] = S.strings[S.w[S.at++]];
|
|
69
|
+
return list;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** @typedef {{ type: string | null, keys: string[], kinds: number[] }} Shape */
|
|
73
|
+
|
|
74
|
+
// one reader per kind, as source for the generated builders and as a function for the interpreter
|
|
75
|
+
const READ = ['node(S)', 'S.w[S.at++]', 'S.floats[S.w[S.at++]]', 'S.w[S.at++] === 1', 'S.constants[S.w[S.at++]]', 'S.strings[S.w[S.at++]]', 'S.source.slice(S.w[S.at++], S.w[S.at++])', '{ start: { line: S.w[S.at++], column: S.w[S.at++] }, end: { line: S.w[S.at++], column: S.w[S.at++] } }', 'nodes(S)', 'ints(S)', 'strs(S)'];
|
|
76
|
+
const READERS = [node, (S) => S.w[S.at++], (S) => /** @type {Float64Array} */ (S.floats)[S.w[S.at++]], (S) => S.w[S.at++] === 1, (S) => S.constants[S.w[S.at++]], (S) => S.strings[S.w[S.at++]], (S) => S.source.slice(S.w[S.at++], S.w[S.at++]), (S) => ({ start: { line: S.w[S.at++], column: S.w[S.at++] }, end: { line: S.w[S.at++], column: S.w[S.at++] } }), nodes, ints, strs];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* One object literal per shape, its facts and its parent link as symbol slots of the literal:
|
|
80
|
+
* V8 allocates it in one hidden class with nothing added later. Facts, and everything the stream
|
|
81
|
+
* puts before the last of them, are read into locals first.
|
|
82
|
+
* @param {Shape} shape @param {boolean} link
|
|
83
|
+
*/
|
|
84
|
+
function generate({ type, keys, kinds }, link) {
|
|
85
|
+
let last = -1;
|
|
86
|
+
if (link && type !== null) for (let i = 0; i < keys.length; i++) if (FACTS.has(keys[i]) || kinds[i] === 0 || kinds[i] === 8) last = i;
|
|
87
|
+
const lead = [];
|
|
88
|
+
const props = type === null ? [] : [`type: ${JSON.stringify(type)}`];
|
|
89
|
+
// what the node points at, set once it exists
|
|
90
|
+
const after = [];
|
|
91
|
+
let scope = null, binding = null, reference = null;
|
|
92
|
+
for (let i = 0; i < keys.length; i++) {
|
|
93
|
+
const key = keys[i];
|
|
94
|
+
if (i > last) props.push(`${JSON.stringify(key)}: ${READ[kinds[i]]}`);
|
|
95
|
+
else {
|
|
96
|
+
lead.push(`const v${i} = ${READ[kinds[i]]};`);
|
|
97
|
+
if (key === 'scope') { scope = `S.scopes[v${i}]`; lead.push(`const s = ${scope};`); after.push('s.node = n;'); }
|
|
98
|
+
else if (key === 'declares') { binding = 'd'; lead.push(`const d = S.bindings[v${i}];`); after.push('if (d.node === null) d.node = n;'); }
|
|
99
|
+
else if (key === 'reference') { reference = 'r'; binding = 'r.binding'; lead.push(`const r = S.references[v${i}];`); after.push('r.node = n;'); }
|
|
100
|
+
else if (key === 'defines') after.push(`for (let i = 0; i < v${i}.length; i++) S.bindings[v${i}[i]].declaration = n;`);
|
|
101
|
+
else if (key === 'writes') after.push(`for (let i = 0; i < v${i}.length; i++) S.references[v${i}[i]].writeExpr = n;`);
|
|
102
|
+
else if (key === 'root') after.push(`S.roots[v${i}].node = n;`);
|
|
103
|
+
else {
|
|
104
|
+
props.push(`${JSON.stringify(key)}: v${i}`);
|
|
105
|
+
// a child with a type is a node; a literal's regex or a template element's value is not
|
|
106
|
+
if (link && kinds[i] === 0) after.push(`if (v${i} !== null && v${i}.type !== undefined) v${i}[PARENT] = n;`);
|
|
107
|
+
else if (link && kinds[i] === 8) after.push(`for (let i = 0; i < v${i}.length; i++) if (v${i}[i] !== null) v${i}[i][PARENT] = n;`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (link && type !== null) {
|
|
112
|
+
props.push('[PARENT]: undefined');
|
|
113
|
+
if (scope !== null) props.push('[SCOPE]: s');
|
|
114
|
+
// every identifier has the two slots, so those with facts and those without share a class
|
|
115
|
+
if (type === 'Identifier' || binding !== null) props.push(`[BINDING]: ${binding ?? 'undefined'}`);
|
|
116
|
+
if (type === 'Identifier' || reference !== null) props.push(`[REFERENCE]: ${reference ?? 'undefined'}`);
|
|
117
|
+
}
|
|
118
|
+
const body = `${lead.join(' ')} const n = { ${props.join(', ')} }; ${after.join(' ')} return n;`;
|
|
119
|
+
return new Function('node', 'nodes', 'ints', 'strs', 'PARENT', 'SCOPE', 'BINDING', 'REFERENCE', `return (S) => { ${body} };`)(node, nodes, ints, strs, PARENT, SCOPE, BINDING, REFERENCE);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** The same without code generation, for a host whose policy forbids it. @param {Shape} shape @param {boolean} link */
|
|
123
|
+
function interpret({ type, keys, kinds }, link) {
|
|
124
|
+
const linked = link && type !== null;
|
|
125
|
+
return (S) => {
|
|
126
|
+
const n = type === null ? {} : linked ? { type, [PARENT]: undefined, [SCOPE]: undefined, [BINDING]: undefined, [REFERENCE]: undefined } : { type };
|
|
127
|
+
for (let i = 0; i < keys.length; i++) {
|
|
128
|
+
const key = keys[i];
|
|
129
|
+
const value = READERS[kinds[i]](S);
|
|
130
|
+
if (linked && kinds[i] === 0 && value !== null && value.type !== undefined) value[PARENT] = n;
|
|
131
|
+
else if (linked && kinds[i] === 8) for (const child of value) if (child !== null) child[PARENT] = n;
|
|
132
|
+
if (!linked || !FACTS.has(key)) n[key] = value;
|
|
133
|
+
else if (key === 'scope') { const s = S.scopes[value]; n[SCOPE] = s; s.node = n; }
|
|
134
|
+
else if (key === 'declares') { const d = S.bindings[value]; n[BINDING] = d; if (d.node === null) d.node = n; }
|
|
135
|
+
else if (key === 'reference') { const r = S.references[value]; n[REFERENCE] = r; n[BINDING] = r.binding; r.node = n; }
|
|
136
|
+
else if (key === 'defines') for (const b of value) S.bindings[b].declaration = n;
|
|
137
|
+
else if (key === 'root') S.roots[value].node = n;
|
|
138
|
+
else for (const w of value) S.references[w].writeExpr = n;
|
|
139
|
+
}
|
|
140
|
+
return n;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const compile = (() => {
|
|
145
|
+
try {
|
|
146
|
+
new Function('');
|
|
147
|
+
return generate;
|
|
148
|
+
} catch {
|
|
149
|
+
return interpret;
|
|
150
|
+
}
|
|
151
|
+
})();
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @typedef {{ constants: () => string[], shapes: () => ArrayLike<number> }} Tables the engine's numbering
|
|
155
|
+
* @type {WeakMap<Tables, { constants: string[], shapes: (Shape | null)[], linked: (() => any)[], plain: (() => any)[] }>}
|
|
156
|
+
*/
|
|
157
|
+
const tables = new WeakMap();
|
|
158
|
+
|
|
159
|
+
/** @param {Tables} engine @param {number} known constants @param {number} known_shapes */
|
|
160
|
+
function table_of(engine, known, known_shapes) {
|
|
161
|
+
let table = tables.get(engine);
|
|
162
|
+
if (table === undefined) tables.set(engine, (table = { constants: [], shapes: [null, null], linked: [], plain: [] }));
|
|
163
|
+
if (known > table.constants.length) table.constants = engine.constants();
|
|
164
|
+
if (known_shapes > table.shapes.length) {
|
|
165
|
+
const { constants, shapes } = table;
|
|
166
|
+
const flat = engine.shapes();
|
|
167
|
+
let at = 0;
|
|
168
|
+
for (let id = 2; at < flat.length; id++) {
|
|
169
|
+
const n = flat[at++];
|
|
170
|
+
if (id === shapes.length) {
|
|
171
|
+
const keys = [], kinds = [];
|
|
172
|
+
for (let i = 1; i < n; i++) {
|
|
173
|
+
keys.push(constants[flat[at + i] >>> 4]);
|
|
174
|
+
kinds.push(flat[at + i] & 15);
|
|
175
|
+
}
|
|
176
|
+
shapes.push({ type: flat[at] === 0 ? null : constants[flat[at] - 1], keys, kinds });
|
|
177
|
+
}
|
|
178
|
+
at += n;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return table;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** @param {ReturnType<typeof table_of>} table @param {boolean} link */
|
|
185
|
+
function builders(table, link) {
|
|
186
|
+
const list = link ? table.linked : table.plain;
|
|
187
|
+
if (list.length === 0) list.push(null, null);
|
|
188
|
+
while (list.length < table.shapes.length) list.push(compile(/** @type {Shape} */ (table.shapes[list.length]), link));
|
|
189
|
+
return list;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function unaligned_floats(buffer, start, count) {
|
|
193
|
+
const view = new DataView(buffer, start, count * 8);
|
|
194
|
+
const floats = new Float64Array(count);
|
|
195
|
+
for (let i = 0; i < count; i++) floats[i] = view.getFloat64(i * 8, little);
|
|
196
|
+
return floats;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** @param {any[]} scopes @param {any[]} bindings @param {any[]} references */
|
|
200
|
+
function link_tables(scopes, bindings, references) {
|
|
201
|
+
for (const scope of scopes) {
|
|
202
|
+
scope.parent = scope.parent === null ? null : scopes[scope.parent];
|
|
203
|
+
scope.node = null;
|
|
204
|
+
}
|
|
205
|
+
for (const binding of bindings) {
|
|
206
|
+
binding.scope = scopes[binding.scope];
|
|
207
|
+
binding.node = null;
|
|
208
|
+
binding.declaration = null;
|
|
209
|
+
}
|
|
210
|
+
for (const reference of references) {
|
|
211
|
+
reference.scope = scopes[reference.scope];
|
|
212
|
+
reference.binding = reference.binding === null ? null : bindings[reference.binding];
|
|
213
|
+
reference.node = null;
|
|
214
|
+
reference.writeExpr = null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** @param {any[]} roots @param {any[]} scopes @param {any[]} bindings @param {any[]} references */
|
|
219
|
+
function link_roots(roots, scopes, bindings, references) {
|
|
220
|
+
for (const root of roots) {
|
|
221
|
+
root.node = null;
|
|
222
|
+
root.scope = scopes[root.scope];
|
|
223
|
+
root.scopes = scopes.slice(root.scopes[0], root.scopes[1]);
|
|
224
|
+
root.bindings = bindings.slice(root.bindings[0], root.bindings[1]);
|
|
225
|
+
root.references = references.slice(root.references[0], root.references[1]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @param {ArrayBuffer | Uint32Array} answer the words, or a view of them inside a larger buffer
|
|
231
|
+
* @param {string} source
|
|
232
|
+
* @param {Tables} engine
|
|
233
|
+
* @param {boolean} [link] replace the scope and binding numbers with the objects they index
|
|
234
|
+
*/
|
|
235
|
+
export function decode(answer, source, engine, link = true) {
|
|
236
|
+
const words = answer instanceof Uint32Array ? answer : new Uint32Array(answer);
|
|
237
|
+
const { buffer, byteOffset } = words;
|
|
238
|
+
// read by index: destructuring a typed array goes through its iterator, a tenth of a small decode
|
|
239
|
+
const tree = words[0], ends_count = words[1], floats_count = words[2], bytes = words[3], known = words[4], known_shapes = words[5], tables_at = words[6];
|
|
240
|
+
const table = table_of(engine, known, known_shapes);
|
|
241
|
+
const text_at = HEADER + tree + ends_count;
|
|
242
|
+
const text = bytes ? utf8.decode(new Uint8Array(buffer, byteOffset + text_at * 4, bytes)) : '';
|
|
243
|
+
let floats_at = text_at + ((bytes + 3) >> 2);
|
|
244
|
+
if (floats_at % 2 === 1) floats_at++;
|
|
245
|
+
const floats_start = byteOffset + floats_at * 4;
|
|
246
|
+
const floats = !floats_count ? null : floats_start % 8 === 0 ? new Float64Array(buffer, floats_start, floats_count) : unaligned_floats(buffer, floats_start, floats_count);
|
|
247
|
+
const strings = new Array(ends_count);
|
|
248
|
+
let from = 0;
|
|
249
|
+
for (let i = 0; i < ends_count; i++) {
|
|
250
|
+
const end = words[HEADER + tree + i];
|
|
251
|
+
strings[i] = text.slice(from, end);
|
|
252
|
+
from = end;
|
|
253
|
+
}
|
|
254
|
+
// one state object per decode, young like everything it points at: no write barriers
|
|
255
|
+
const S = { w: words, at: HEADER, strings, floats, source, constants: table.constants, scopes: EMPTY, bindings: EMPTY, references: EMPTY, roots: EMPTY, build: builders(table, link) };
|
|
256
|
+
let scopes = null, bindings = null, references = null, roots = null;
|
|
257
|
+
if (tables_at !== 0) {
|
|
258
|
+
// the writer's `all_scopes` order; the roots table is there when a host document has pieces of JavaScript
|
|
259
|
+
S.at = HEADER + tables_at;
|
|
260
|
+
scopes = nodes(S);
|
|
261
|
+
bindings = nodes(S);
|
|
262
|
+
references = nodes(S);
|
|
263
|
+
if (S.at < HEADER + tree) roots = nodes(S);
|
|
264
|
+
if (link) {
|
|
265
|
+
link_tables(scopes, bindings, references);
|
|
266
|
+
if (roots !== null) link_roots(roots, scopes, bindings, references);
|
|
267
|
+
}
|
|
268
|
+
S.scopes = scopes;
|
|
269
|
+
S.bindings = bindings;
|
|
270
|
+
S.references = references;
|
|
271
|
+
if (roots !== null) S.roots = roots;
|
|
272
|
+
S.at = HEADER;
|
|
273
|
+
}
|
|
274
|
+
const root = node(S);
|
|
275
|
+
if (scopes !== null) {
|
|
276
|
+
root.scopes = scopes;
|
|
277
|
+
root.bindings = bindings;
|
|
278
|
+
root.references = references;
|
|
279
|
+
if (roots !== null) root.roots = roots;
|
|
280
|
+
}
|
|
281
|
+
return root;
|
|
282
|
+
}
|
package/identifier.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Generated by scripts/unicode.js from Unicode 17.0.0. Do not edit.
|
|
2
|
+
// The parser's own identifier tables, so a host tokenizing around embedded JavaScript agrees with
|
|
3
|
+
// it whatever Unicode its engine has. Each table is a flat list of inclusive ranges.
|
|
4
|
+
const ID_START = [
|
|
5
|
+
0xaa, 0xaa, 0xb5, 0xb5, 0xba, 0xba, 0xc0, 0xd6, 0xd8, 0xf6, 0xf8, 0x2c1, 0x2c6, 0x2d1, 0x2e0, 0x2e4,
|
|
6
|
+
0x2ec, 0x2ec, 0x2ee, 0x2ee, 0x370, 0x374, 0x376, 0x377, 0x37a, 0x37d, 0x37f, 0x37f, 0x386, 0x386, 0x388, 0x38a,
|
|
7
|
+
0x38c, 0x38c, 0x38e, 0x3a1, 0x3a3, 0x3f5, 0x3f7, 0x481, 0x48a, 0x52f, 0x531, 0x556, 0x559, 0x559, 0x560, 0x588,
|
|
8
|
+
0x5d0, 0x5ea, 0x5ef, 0x5f2, 0x620, 0x64a, 0x66e, 0x66f, 0x671, 0x6d3, 0x6d5, 0x6d5, 0x6e5, 0x6e6, 0x6ee, 0x6ef,
|
|
9
|
+
0x6fa, 0x6fc, 0x6ff, 0x6ff, 0x710, 0x710, 0x712, 0x72f, 0x74d, 0x7a5, 0x7b1, 0x7b1, 0x7ca, 0x7ea, 0x7f4, 0x7f5,
|
|
10
|
+
0x7fa, 0x7fa, 0x800, 0x815, 0x81a, 0x81a, 0x824, 0x824, 0x828, 0x828, 0x840, 0x858, 0x860, 0x86a, 0x870, 0x887,
|
|
11
|
+
0x889, 0x88f, 0x8a0, 0x8c9, 0x904, 0x939, 0x93d, 0x93d, 0x950, 0x950, 0x958, 0x961, 0x971, 0x980, 0x985, 0x98c,
|
|
12
|
+
0x98f, 0x990, 0x993, 0x9a8, 0x9aa, 0x9b0, 0x9b2, 0x9b2, 0x9b6, 0x9b9, 0x9bd, 0x9bd, 0x9ce, 0x9ce, 0x9dc, 0x9dd,
|
|
13
|
+
0x9df, 0x9e1, 0x9f0, 0x9f1, 0x9fc, 0x9fc, 0xa05, 0xa0a, 0xa0f, 0xa10, 0xa13, 0xa28, 0xa2a, 0xa30, 0xa32, 0xa33,
|
|
14
|
+
0xa35, 0xa36, 0xa38, 0xa39, 0xa59, 0xa5c, 0xa5e, 0xa5e, 0xa72, 0xa74, 0xa85, 0xa8d, 0xa8f, 0xa91, 0xa93, 0xaa8,
|
|
15
|
+
0xaaa, 0xab0, 0xab2, 0xab3, 0xab5, 0xab9, 0xabd, 0xabd, 0xad0, 0xad0, 0xae0, 0xae1, 0xaf9, 0xaf9, 0xb05, 0xb0c,
|
|
16
|
+
0xb0f, 0xb10, 0xb13, 0xb28, 0xb2a, 0xb30, 0xb32, 0xb33, 0xb35, 0xb39, 0xb3d, 0xb3d, 0xb5c, 0xb5d, 0xb5f, 0xb61,
|
|
17
|
+
0xb71, 0xb71, 0xb83, 0xb83, 0xb85, 0xb8a, 0xb8e, 0xb90, 0xb92, 0xb95, 0xb99, 0xb9a, 0xb9c, 0xb9c, 0xb9e, 0xb9f,
|
|
18
|
+
0xba3, 0xba4, 0xba8, 0xbaa, 0xbae, 0xbb9, 0xbd0, 0xbd0, 0xc05, 0xc0c, 0xc0e, 0xc10, 0xc12, 0xc28, 0xc2a, 0xc39,
|
|
19
|
+
0xc3d, 0xc3d, 0xc58, 0xc5a, 0xc5c, 0xc5d, 0xc60, 0xc61, 0xc80, 0xc80, 0xc85, 0xc8c, 0xc8e, 0xc90, 0xc92, 0xca8,
|
|
20
|
+
0xcaa, 0xcb3, 0xcb5, 0xcb9, 0xcbd, 0xcbd, 0xcdc, 0xcde, 0xce0, 0xce1, 0xcf1, 0xcf2, 0xd04, 0xd0c, 0xd0e, 0xd10,
|
|
21
|
+
0xd12, 0xd3a, 0xd3d, 0xd3d, 0xd4e, 0xd4e, 0xd54, 0xd56, 0xd5f, 0xd61, 0xd7a, 0xd7f, 0xd85, 0xd96, 0xd9a, 0xdb1,
|
|
22
|
+
0xdb3, 0xdbb, 0xdbd, 0xdbd, 0xdc0, 0xdc6, 0xe01, 0xe30, 0xe32, 0xe33, 0xe40, 0xe46, 0xe81, 0xe82, 0xe84, 0xe84,
|
|
23
|
+
0xe86, 0xe8a, 0xe8c, 0xea3, 0xea5, 0xea5, 0xea7, 0xeb0, 0xeb2, 0xeb3, 0xebd, 0xebd, 0xec0, 0xec4, 0xec6, 0xec6,
|
|
24
|
+
0xedc, 0xedf, 0xf00, 0xf00, 0xf40, 0xf47, 0xf49, 0xf6c, 0xf88, 0xf8c, 0x1000, 0x102a, 0x103f, 0x103f, 0x1050, 0x1055,
|
|
25
|
+
0x105a, 0x105d, 0x1061, 0x1061, 0x1065, 0x1066, 0x106e, 0x1070, 0x1075, 0x1081, 0x108e, 0x108e, 0x10a0, 0x10c5, 0x10c7, 0x10c7,
|
|
26
|
+
0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288,
|
|
27
|
+
0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310,
|
|
28
|
+
0x1312, 0x1315, 0x1318, 0x135a, 0x1380, 0x138f, 0x13a0, 0x13f5, 0x13f8, 0x13fd, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a,
|
|
29
|
+
0x16a0, 0x16ea, 0x16ee, 0x16f8, 0x1700, 0x1711, 0x171f, 0x1731, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3,
|
|
30
|
+
0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x1820, 0x1878, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191e, 0x1950, 0x196d,
|
|
31
|
+
0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x1a00, 0x1a16, 0x1a20, 0x1a54, 0x1aa7, 0x1aa7, 0x1b05, 0x1b33, 0x1b45, 0x1b4c,
|
|
32
|
+
0x1b83, 0x1ba0, 0x1bae, 0x1baf, 0x1bba, 0x1be5, 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, 0x1c80, 0x1c8a, 0x1c90, 0x1cba,
|
|
33
|
+
0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, 0x1cee, 0x1cf3, 0x1cf5, 0x1cf6, 0x1cfa, 0x1cfa, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d,
|
|
34
|
+
0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4,
|
|
35
|
+
0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4,
|
|
36
|
+
0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115,
|
|
37
|
+
0x2118, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e,
|
|
38
|
+
0x2160, 0x2188, 0x2c00, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67,
|
|
39
|
+
0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce,
|
|
40
|
+
0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309b, 0x309f,
|
|
41
|
+
0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, 0x31a0, 0x31bf, 0x31f0, 0x31ff, 0x3400, 0x4dbf, 0x4e00, 0xa48c,
|
|
42
|
+
0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa640, 0xa66e, 0xa67f, 0xa69d, 0xa6a0, 0xa6ef, 0xa717, 0xa71f,
|
|
43
|
+
0xa722, 0xa788, 0xa78b, 0xa7dc, 0xa7f1, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, 0xa840, 0xa873, 0xa882, 0xa8b3,
|
|
44
|
+
0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa8fd, 0xa8fe, 0xa90a, 0xa925, 0xa930, 0xa946, 0xa960, 0xa97c, 0xa984, 0xa9b2, 0xa9cf, 0xa9cf,
|
|
45
|
+
0xa9e0, 0xa9e4, 0xa9e6, 0xa9ef, 0xa9fa, 0xa9fe, 0xaa00, 0xaa28, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a,
|
|
46
|
+
0xaa7e, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaea,
|
|
47
|
+
0xaaf2, 0xaaf4, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xab30, 0xab5a, 0xab5c, 0xab69,
|
|
48
|
+
0xab70, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17,
|
|
49
|
+
0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1,
|
|
50
|
+
0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff21, 0xff3a, 0xff41, 0xff5a,
|
|
51
|
+
0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a,
|
|
52
|
+
0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031f,
|
|
53
|
+
0x1032d, 0x1034a, 0x10350, 0x10375, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104b0, 0x104d3,
|
|
54
|
+
0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, 0x10570, 0x1057a, 0x1057c, 0x1058a, 0x1058c, 0x10592, 0x10594, 0x10595, 0x10597, 0x105a1,
|
|
55
|
+
0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, 0x10780, 0x10785,
|
|
56
|
+
0x10787, 0x107b0, 0x107b2, 0x107ba, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855,
|
|
57
|
+
0x10860, 0x10876, 0x10880, 0x1089e, 0x108e0, 0x108f2, 0x108f4, 0x108f5, 0x10900, 0x10915, 0x10920, 0x10939, 0x10940, 0x10959, 0x10980, 0x109b7,
|
|
58
|
+
0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a35, 0x10a60, 0x10a7c, 0x10a80, 0x10a9c, 0x10ac0, 0x10ac7,
|
|
59
|
+
0x10ac9, 0x10ae4, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10b80, 0x10b91, 0x10c00, 0x10c48, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2,
|
|
60
|
+
0x10d00, 0x10d23, 0x10d4a, 0x10d65, 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eb0, 0x10eb1, 0x10ec2, 0x10ec7, 0x10f00, 0x10f1c, 0x10f27, 0x10f27,
|
|
61
|
+
0x10f30, 0x10f45, 0x10f70, 0x10f81, 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11003, 0x11037, 0x11071, 0x11072, 0x11075, 0x11075, 0x11083, 0x110af,
|
|
62
|
+
0x110d0, 0x110e8, 0x11103, 0x11126, 0x11144, 0x11144, 0x11147, 0x11147, 0x11150, 0x11172, 0x11176, 0x11176, 0x11183, 0x111b2, 0x111c1, 0x111c4,
|
|
63
|
+
0x111da, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x1122b, 0x1123f, 0x11240, 0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d,
|
|
64
|
+
0x1128f, 0x1129d, 0x1129f, 0x112a8, 0x112b0, 0x112de, 0x11305, 0x1130c, 0x1130f, 0x11310, 0x11313, 0x11328, 0x1132a, 0x11330, 0x11332, 0x11333,
|
|
65
|
+
0x11335, 0x11339, 0x1133d, 0x1133d, 0x11350, 0x11350, 0x1135d, 0x11361, 0x11380, 0x11389, 0x1138b, 0x1138b, 0x1138e, 0x1138e, 0x11390, 0x113b5,
|
|
66
|
+
0x113b7, 0x113b7, 0x113d1, 0x113d1, 0x113d3, 0x113d3, 0x11400, 0x11434, 0x11447, 0x1144a, 0x1145f, 0x11461, 0x11480, 0x114af, 0x114c4, 0x114c5,
|
|
67
|
+
0x114c7, 0x114c7, 0x11580, 0x115ae, 0x115d8, 0x115db, 0x11600, 0x1162f, 0x11644, 0x11644, 0x11680, 0x116aa, 0x116b8, 0x116b8, 0x11700, 0x1171a,
|
|
68
|
+
0x11740, 0x11746, 0x11800, 0x1182b, 0x118a0, 0x118df, 0x118ff, 0x11906, 0x11909, 0x11909, 0x1190c, 0x11913, 0x11915, 0x11916, 0x11918, 0x1192f,
|
|
69
|
+
0x1193f, 0x1193f, 0x11941, 0x11941, 0x119a0, 0x119a7, 0x119aa, 0x119d0, 0x119e1, 0x119e1, 0x119e3, 0x119e3, 0x11a00, 0x11a00, 0x11a0b, 0x11a32,
|
|
70
|
+
0x11a3a, 0x11a3a, 0x11a50, 0x11a50, 0x11a5c, 0x11a89, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c2e,
|
|
71
|
+
0x11c40, 0x11c40, 0x11c72, 0x11c8f, 0x11d00, 0x11d06, 0x11d08, 0x11d09, 0x11d0b, 0x11d30, 0x11d46, 0x11d46, 0x11d60, 0x11d65, 0x11d67, 0x11d68,
|
|
72
|
+
0x11d6a, 0x11d89, 0x11d98, 0x11d98, 0x11db0, 0x11ddb, 0x11ee0, 0x11ef2, 0x11f02, 0x11f02, 0x11f04, 0x11f10, 0x11f12, 0x11f33, 0x11fb0, 0x11fb0,
|
|
73
|
+
0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543, 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, 0x13460, 0x143fa, 0x14400, 0x14646,
|
|
74
|
+
0x16100, 0x1611d, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, 0x16ad0, 0x16aed, 0x16b00, 0x16b2f, 0x16b40, 0x16b43, 0x16b63, 0x16b77,
|
|
75
|
+
0x16b7d, 0x16b8f, 0x16d40, 0x16d6c, 0x16e40, 0x16e7f, 0x16ea0, 0x16eb8, 0x16ebb, 0x16ed3, 0x16f00, 0x16f4a, 0x16f50, 0x16f50, 0x16f93, 0x16f9f,
|
|
76
|
+
0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, 0x16ff2, 0x16ff6, 0x17000, 0x18cd5, 0x18cff, 0x18d1e, 0x18d80, 0x18df2, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb,
|
|
77
|
+
0x1affd, 0x1affe, 0x1b000, 0x1b122, 0x1b132, 0x1b132, 0x1b150, 0x1b152, 0x1b155, 0x1b155, 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a,
|
|
78
|
+
0x1bc70, 0x1bc7c, 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6,
|
|
79
|
+
0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c,
|
|
80
|
+
0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da,
|
|
81
|
+
0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2,
|
|
82
|
+
0x1d7c4, 0x1d7cb, 0x1df00, 0x1df1e, 0x1df25, 0x1df2a, 0x1e030, 0x1e06d, 0x1e100, 0x1e12c, 0x1e137, 0x1e13d, 0x1e14e, 0x1e14e, 0x1e290, 0x1e2ad,
|
|
83
|
+
0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4eb, 0x1e5d0, 0x1e5ed, 0x1e5f0, 0x1e5f0, 0x1e6c0, 0x1e6de, 0x1e6e0, 0x1e6e2, 0x1e6e4, 0x1e6e5, 0x1e6e7, 0x1e6ed,
|
|
84
|
+
0x1e6f0, 0x1e6f4, 0x1e6fe, 0x1e6ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, 0x1e7f0, 0x1e7fe, 0x1e800, 0x1e8c4, 0x1e900, 0x1e943,
|
|
85
|
+
0x1e94b, 0x1e94b, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37,
|
|
86
|
+
0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52,
|
|
87
|
+
0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64,
|
|
88
|
+
0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3,
|
|
89
|
+
0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6df, 0x2a700, 0x2b81d, 0x2b820, 0x2cead, 0x2ceb0, 0x2ebe0, 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d,
|
|
90
|
+
0x30000, 0x3134a, 0x31350, 0x33479,
|
|
91
|
+
];
|
|
92
|
+
const ID_CONTINUE = [
|
|
93
|
+
0xaa, 0xaa, 0xb5, 0xb5, 0xb7, 0xb7, 0xba, 0xba, 0xc0, 0xd6, 0xd8, 0xf6, 0xf8, 0x2c1, 0x2c6, 0x2d1,
|
|
94
|
+
0x2e0, 0x2e4, 0x2ec, 0x2ec, 0x2ee, 0x2ee, 0x300, 0x374, 0x376, 0x377, 0x37a, 0x37d, 0x37f, 0x37f, 0x386, 0x38a,
|
|
95
|
+
0x38c, 0x38c, 0x38e, 0x3a1, 0x3a3, 0x3f5, 0x3f7, 0x481, 0x483, 0x487, 0x48a, 0x52f, 0x531, 0x556, 0x559, 0x559,
|
|
96
|
+
0x560, 0x588, 0x591, 0x5bd, 0x5bf, 0x5bf, 0x5c1, 0x5c2, 0x5c4, 0x5c5, 0x5c7, 0x5c7, 0x5d0, 0x5ea, 0x5ef, 0x5f2,
|
|
97
|
+
0x610, 0x61a, 0x620, 0x669, 0x66e, 0x6d3, 0x6d5, 0x6dc, 0x6df, 0x6e8, 0x6ea, 0x6fc, 0x6ff, 0x6ff, 0x710, 0x74a,
|
|
98
|
+
0x74d, 0x7b1, 0x7c0, 0x7f5, 0x7fa, 0x7fa, 0x7fd, 0x7fd, 0x800, 0x82d, 0x840, 0x85b, 0x860, 0x86a, 0x870, 0x887,
|
|
99
|
+
0x889, 0x88f, 0x897, 0x8e1, 0x8e3, 0x963, 0x966, 0x96f, 0x971, 0x983, 0x985, 0x98c, 0x98f, 0x990, 0x993, 0x9a8,
|
|
100
|
+
0x9aa, 0x9b0, 0x9b2, 0x9b2, 0x9b6, 0x9b9, 0x9bc, 0x9c4, 0x9c7, 0x9c8, 0x9cb, 0x9ce, 0x9d7, 0x9d7, 0x9dc, 0x9dd,
|
|
101
|
+
0x9df, 0x9e3, 0x9e6, 0x9f1, 0x9fc, 0x9fc, 0x9fe, 0x9fe, 0xa01, 0xa03, 0xa05, 0xa0a, 0xa0f, 0xa10, 0xa13, 0xa28,
|
|
102
|
+
0xa2a, 0xa30, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39, 0xa3c, 0xa3c, 0xa3e, 0xa42, 0xa47, 0xa48, 0xa4b, 0xa4d,
|
|
103
|
+
0xa51, 0xa51, 0xa59, 0xa5c, 0xa5e, 0xa5e, 0xa66, 0xa75, 0xa81, 0xa83, 0xa85, 0xa8d, 0xa8f, 0xa91, 0xa93, 0xaa8,
|
|
104
|
+
0xaaa, 0xab0, 0xab2, 0xab3, 0xab5, 0xab9, 0xabc, 0xac5, 0xac7, 0xac9, 0xacb, 0xacd, 0xad0, 0xad0, 0xae0, 0xae3,
|
|
105
|
+
0xae6, 0xaef, 0xaf9, 0xaff, 0xb01, 0xb03, 0xb05, 0xb0c, 0xb0f, 0xb10, 0xb13, 0xb28, 0xb2a, 0xb30, 0xb32, 0xb33,
|
|
106
|
+
0xb35, 0xb39, 0xb3c, 0xb44, 0xb47, 0xb48, 0xb4b, 0xb4d, 0xb55, 0xb57, 0xb5c, 0xb5d, 0xb5f, 0xb63, 0xb66, 0xb6f,
|
|
107
|
+
0xb71, 0xb71, 0xb82, 0xb83, 0xb85, 0xb8a, 0xb8e, 0xb90, 0xb92, 0xb95, 0xb99, 0xb9a, 0xb9c, 0xb9c, 0xb9e, 0xb9f,
|
|
108
|
+
0xba3, 0xba4, 0xba8, 0xbaa, 0xbae, 0xbb9, 0xbbe, 0xbc2, 0xbc6, 0xbc8, 0xbca, 0xbcd, 0xbd0, 0xbd0, 0xbd7, 0xbd7,
|
|
109
|
+
0xbe6, 0xbef, 0xc00, 0xc0c, 0xc0e, 0xc10, 0xc12, 0xc28, 0xc2a, 0xc39, 0xc3c, 0xc44, 0xc46, 0xc48, 0xc4a, 0xc4d,
|
|
110
|
+
0xc55, 0xc56, 0xc58, 0xc5a, 0xc5c, 0xc5d, 0xc60, 0xc63, 0xc66, 0xc6f, 0xc80, 0xc83, 0xc85, 0xc8c, 0xc8e, 0xc90,
|
|
111
|
+
0xc92, 0xca8, 0xcaa, 0xcb3, 0xcb5, 0xcb9, 0xcbc, 0xcc4, 0xcc6, 0xcc8, 0xcca, 0xccd, 0xcd5, 0xcd6, 0xcdc, 0xcde,
|
|
112
|
+
0xce0, 0xce3, 0xce6, 0xcef, 0xcf1, 0xcf3, 0xd00, 0xd0c, 0xd0e, 0xd10, 0xd12, 0xd44, 0xd46, 0xd48, 0xd4a, 0xd4e,
|
|
113
|
+
0xd54, 0xd57, 0xd5f, 0xd63, 0xd66, 0xd6f, 0xd7a, 0xd7f, 0xd81, 0xd83, 0xd85, 0xd96, 0xd9a, 0xdb1, 0xdb3, 0xdbb,
|
|
114
|
+
0xdbd, 0xdbd, 0xdc0, 0xdc6, 0xdca, 0xdca, 0xdcf, 0xdd4, 0xdd6, 0xdd6, 0xdd8, 0xddf, 0xde6, 0xdef, 0xdf2, 0xdf3,
|
|
115
|
+
0xe01, 0xe3a, 0xe40, 0xe4e, 0xe50, 0xe59, 0xe81, 0xe82, 0xe84, 0xe84, 0xe86, 0xe8a, 0xe8c, 0xea3, 0xea5, 0xea5,
|
|
116
|
+
0xea7, 0xebd, 0xec0, 0xec4, 0xec6, 0xec6, 0xec8, 0xece, 0xed0, 0xed9, 0xedc, 0xedf, 0xf00, 0xf00, 0xf18, 0xf19,
|
|
117
|
+
0xf20, 0xf29, 0xf35, 0xf35, 0xf37, 0xf37, 0xf39, 0xf39, 0xf3e, 0xf47, 0xf49, 0xf6c, 0xf71, 0xf84, 0xf86, 0xf97,
|
|
118
|
+
0xf99, 0xfbc, 0xfc6, 0xfc6, 0x1000, 0x1049, 0x1050, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa,
|
|
119
|
+
0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0,
|
|
120
|
+
0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a,
|
|
121
|
+
0x135d, 0x135f, 0x1369, 0x1371, 0x1380, 0x138f, 0x13a0, 0x13f5, 0x13f8, 0x13fd, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a,
|
|
122
|
+
0x16a0, 0x16ea, 0x16ee, 0x16f8, 0x1700, 0x1715, 0x171f, 0x1734, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773,
|
|
123
|
+
0x1780, 0x17d3, 0x17d7, 0x17d7, 0x17dc, 0x17dd, 0x17e0, 0x17e9, 0x180b, 0x180d, 0x180f, 0x1819, 0x1820, 0x1878, 0x1880, 0x18aa,
|
|
124
|
+
0x18b0, 0x18f5, 0x1900, 0x191e, 0x1920, 0x192b, 0x1930, 0x193b, 0x1946, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9,
|
|
125
|
+
0x19d0, 0x19da, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1ab0, 0x1abd,
|
|
126
|
+
0x1abf, 0x1add, 0x1ae0, 0x1aeb, 0x1b00, 0x1b4c, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, 0x1b80, 0x1bf3, 0x1c00, 0x1c37, 0x1c40, 0x1c49,
|
|
127
|
+
0x1c4d, 0x1c7d, 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1cd0, 0x1cd2, 0x1cd4, 0x1cfa, 0x1d00, 0x1f15, 0x1f18, 0x1f1d,
|
|
128
|
+
0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4,
|
|
129
|
+
0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4,
|
|
130
|
+
0x1ff6, 0x1ffc, 0x200c, 0x200d, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x20d0, 0x20dc,
|
|
131
|
+
0x20e1, 0x20e1, 0x20e5, 0x20f0, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124,
|
|
132
|
+
0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c00, 0x2ce4,
|
|
133
|
+
0x2ceb, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d7f, 0x2d96, 0x2da0, 0x2da6,
|
|
134
|
+
0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff,
|
|
135
|
+
0x3005, 0x3007, 0x3021, 0x302f, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x3099, 0x309f, 0x30a1, 0x30ff, 0x3105, 0x312f,
|
|
136
|
+
0x3131, 0x318e, 0x31a0, 0x31bf, 0x31f0, 0x31ff, 0x3400, 0x4dbf, 0x4e00, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa62b,
|
|
137
|
+
0xa640, 0xa66f, 0xa674, 0xa67d, 0xa67f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa7dc, 0xa7f1, 0xa827, 0xa82c, 0xa82c,
|
|
138
|
+
0xa840, 0xa873, 0xa880, 0xa8c5, 0xa8d0, 0xa8d9, 0xa8e0, 0xa8f7, 0xa8fb, 0xa8fb, 0xa8fd, 0xa92d, 0xa930, 0xa953, 0xa960, 0xa97c,
|
|
139
|
+
0xa980, 0xa9c0, 0xa9cf, 0xa9d9, 0xa9e0, 0xa9fe, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa60, 0xaa76, 0xaa7a, 0xaac2,
|
|
140
|
+
0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e,
|
|
141
|
+
0xab30, 0xab5a, 0xab5c, 0xab69, 0xab70, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb,
|
|
142
|
+
0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e,
|
|
143
|
+
0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe00, 0xfe0f,
|
|
144
|
+
0xfe20, 0xfe2f, 0xfe33, 0xfe34, 0xfe4d, 0xfe4f, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff10, 0xff19, 0xff21, 0xff3a, 0xff3f, 0xff3f,
|
|
145
|
+
0xff41, 0xff5a, 0xff65, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026,
|
|
146
|
+
0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x101fd, 0x101fd, 0x10280, 0x1029c,
|
|
147
|
+
0x102a0, 0x102d0, 0x102e0, 0x102e0, 0x10300, 0x1031f, 0x1032d, 0x1034a, 0x10350, 0x1037a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf,
|
|
148
|
+
0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x104b0, 0x104d3, 0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, 0x10570, 0x1057a,
|
|
149
|
+
0x1057c, 0x1058a, 0x1058c, 0x10592, 0x10594, 0x10595, 0x10597, 0x105a1, 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x105c0, 0x105f3,
|
|
150
|
+
0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, 0x10780, 0x10785, 0x10787, 0x107b0, 0x107b2, 0x107ba, 0x10800, 0x10805, 0x10808, 0x10808,
|
|
151
|
+
0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10860, 0x10876, 0x10880, 0x1089e, 0x108e0, 0x108f2, 0x108f4, 0x108f5,
|
|
152
|
+
0x10900, 0x10915, 0x10920, 0x10939, 0x10940, 0x10959, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13,
|
|
153
|
+
0x10a15, 0x10a17, 0x10a19, 0x10a35, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x10a60, 0x10a7c, 0x10a80, 0x10a9c, 0x10ac0, 0x10ac7, 0x10ac9, 0x10ae6,
|
|
154
|
+
0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10b80, 0x10b91, 0x10c00, 0x10c48, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d27,
|
|
155
|
+
0x10d30, 0x10d39, 0x10d40, 0x10d65, 0x10d69, 0x10d6d, 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, 0x10ec2, 0x10ec7,
|
|
156
|
+
0x10efa, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, 0x10f70, 0x10f85, 0x10fb0, 0x10fc4, 0x10fe0, 0x10ff6, 0x11000, 0x11046, 0x11066, 0x11075,
|
|
157
|
+
0x1107f, 0x110ba, 0x110c2, 0x110c2, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, 0x11144, 0x11147, 0x11150, 0x11173,
|
|
158
|
+
0x11176, 0x11176, 0x11180, 0x111c4, 0x111c9, 0x111cc, 0x111ce, 0x111da, 0x111dc, 0x111dc, 0x11200, 0x11211, 0x11213, 0x11237, 0x1123e, 0x11241,
|
|
159
|
+
0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d, 0x1128f, 0x1129d, 0x1129f, 0x112a8, 0x112b0, 0x112ea, 0x112f0, 0x112f9, 0x11300, 0x11303,
|
|
160
|
+
0x11305, 0x1130c, 0x1130f, 0x11310, 0x11313, 0x11328, 0x1132a, 0x11330, 0x11332, 0x11333, 0x11335, 0x11339, 0x1133b, 0x11344, 0x11347, 0x11348,
|
|
161
|
+
0x1134b, 0x1134d, 0x11350, 0x11350, 0x11357, 0x11357, 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, 0x11380, 0x11389, 0x1138b, 0x1138b,
|
|
162
|
+
0x1138e, 0x1138e, 0x11390, 0x113b5, 0x113b7, 0x113c0, 0x113c2, 0x113c2, 0x113c5, 0x113c5, 0x113c7, 0x113ca, 0x113cc, 0x113d3, 0x113e1, 0x113e2,
|
|
163
|
+
0x11400, 0x1144a, 0x11450, 0x11459, 0x1145e, 0x11461, 0x11480, 0x114c5, 0x114c7, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, 0x115b8, 0x115c0,
|
|
164
|
+
0x115d8, 0x115dd, 0x11600, 0x11640, 0x11644, 0x11644, 0x11650, 0x11659, 0x11680, 0x116b8, 0x116c0, 0x116c9, 0x116d0, 0x116e3, 0x11700, 0x1171a,
|
|
165
|
+
0x1171d, 0x1172b, 0x11730, 0x11739, 0x11740, 0x11746, 0x11800, 0x1183a, 0x118a0, 0x118e9, 0x118ff, 0x11906, 0x11909, 0x11909, 0x1190c, 0x11913,
|
|
166
|
+
0x11915, 0x11916, 0x11918, 0x11935, 0x11937, 0x11938, 0x1193b, 0x11943, 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e1,
|
|
167
|
+
0x119e3, 0x119e4, 0x11a00, 0x11a3e, 0x11a47, 0x11a47, 0x11a50, 0x11a99, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, 0x11b60, 0x11b67, 0x11bc0, 0x11be0,
|
|
168
|
+
0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c40, 0x11c50, 0x11c59, 0x11c72, 0x11c8f, 0x11c92, 0x11ca7, 0x11ca9, 0x11cb6,
|
|
169
|
+
0x11d00, 0x11d06, 0x11d08, 0x11d09, 0x11d0b, 0x11d36, 0x11d3a, 0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d47, 0x11d50, 0x11d59, 0x11d60, 0x11d65,
|
|
170
|
+
0x11d67, 0x11d68, 0x11d6a, 0x11d8e, 0x11d90, 0x11d91, 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11db0, 0x11ddb, 0x11de0, 0x11de9, 0x11ee0, 0x11ef6,
|
|
171
|
+
0x11f00, 0x11f10, 0x11f12, 0x11f3a, 0x11f3e, 0x11f42, 0x11f50, 0x11f5a, 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12480, 0x12543,
|
|
172
|
+
0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13440, 0x13455, 0x13460, 0x143fa, 0x14400, 0x14646, 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e,
|
|
173
|
+
0x16a60, 0x16a69, 0x16a70, 0x16abe, 0x16ac0, 0x16ac9, 0x16ad0, 0x16aed, 0x16af0, 0x16af4, 0x16b00, 0x16b36, 0x16b40, 0x16b43, 0x16b50, 0x16b59,
|
|
174
|
+
0x16b63, 0x16b77, 0x16b7d, 0x16b8f, 0x16d40, 0x16d6c, 0x16d70, 0x16d79, 0x16e40, 0x16e7f, 0x16ea0, 0x16eb8, 0x16ebb, 0x16ed3, 0x16f00, 0x16f4a,
|
|
175
|
+
0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe4, 0x16ff0, 0x16ff6, 0x17000, 0x18cd5, 0x18cff, 0x18d1e, 0x18d80, 0x18df2,
|
|
176
|
+
0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, 0x1b000, 0x1b122, 0x1b132, 0x1b132, 0x1b150, 0x1b152, 0x1b155, 0x1b155, 0x1b164, 0x1b167,
|
|
177
|
+
0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9d, 0x1bc9e, 0x1ccf0, 0x1ccf9, 0x1cf00, 0x1cf2d,
|
|
178
|
+
0x1cf30, 0x1cf46, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0x1d400, 0x1d454,
|
|
179
|
+
0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3,
|
|
180
|
+
0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546,
|
|
181
|
+
0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e,
|
|
182
|
+
0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1da00, 0x1da36, 0x1da3b, 0x1da6c,
|
|
183
|
+
0x1da75, 0x1da75, 0x1da84, 0x1da84, 0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, 0x1df00, 0x1df1e, 0x1df25, 0x1df2a, 0x1e000, 0x1e006, 0x1e008, 0x1e018,
|
|
184
|
+
0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, 0x1e030, 0x1e06d, 0x1e08f, 0x1e08f, 0x1e100, 0x1e12c, 0x1e130, 0x1e13d, 0x1e140, 0x1e149,
|
|
185
|
+
0x1e14e, 0x1e14e, 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e4d0, 0x1e4f9, 0x1e5d0, 0x1e5fa, 0x1e6c0, 0x1e6de, 0x1e6e0, 0x1e6f5, 0x1e6fe, 0x1e6ff,
|
|
186
|
+
0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, 0x1e7f0, 0x1e7fe, 0x1e800, 0x1e8c4, 0x1e8d0, 0x1e8d6, 0x1e900, 0x1e94b, 0x1e950, 0x1e959,
|
|
187
|
+
0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39,
|
|
188
|
+
0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54,
|
|
189
|
+
0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a,
|
|
190
|
+
0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9,
|
|
191
|
+
0x1eeab, 0x1eebb, 0x1fbf0, 0x1fbf9, 0x20000, 0x2a6df, 0x2a700, 0x2b81d, 0x2b820, 0x2cead, 0x2ceb0, 0x2ebe0, 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d,
|
|
192
|
+
0x30000, 0x3134a, 0x31350, 0x33479, 0xe0100, 0xe01ef,
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
/** @param {number[]} table @param {number} code */
|
|
196
|
+
function lookup(table, code) {
|
|
197
|
+
let lo = 0;
|
|
198
|
+
let hi = table.length >> 1;
|
|
199
|
+
while (lo < hi) {
|
|
200
|
+
const mid = (lo + hi) >> 1;
|
|
201
|
+
if (code < table[mid * 2]) hi = mid;
|
|
202
|
+
else if (code > table[mid * 2 + 1]) lo = mid + 1;
|
|
203
|
+
else return true;
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Whether a code point can start an identifier. @param {number} code */
|
|
209
|
+
export function isIdentifierStart(code) {
|
|
210
|
+
if (code < 128) return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || code === 36 || code === 95;
|
|
211
|
+
return lookup(ID_START, code);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Whether a code point can continue an identifier. @param {number} code */
|
|
215
|
+
export function isIdentifierChar(code) {
|
|
216
|
+
if (code < 128) return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || (code >= 48 && code <= 57) || code === 36 || code === 95;
|
|
217
|
+
return lookup(ID_CONTINUE, code);
|
|
218
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { Expression, Identifier, Node, Pattern, Program, SourceLocation, Statement } from 'estree';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface SymbolConstructor {
|
|
5
|
+
readonly dispose: unique symbol;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Options {
|
|
10
|
+
/**
|
|
11
|
+
* The grammar of a host language the whole source is a document of: a template language
|
|
12
|
+
* with JavaScript inside it. The program entry then answers with the document's root, the
|
|
13
|
+
* host's own nodes around the JavaScript ones, in one tree; the other entries read
|
|
14
|
+
* JavaScript at an offset as before. TypeScript turns on by what the grammar says of a
|
|
15
|
+
* script tag.
|
|
16
|
+
*/
|
|
17
|
+
host?: string;
|
|
18
|
+
/** `script` by default, as in acorn. */
|
|
19
|
+
sourceType?: 'script' | 'module';
|
|
20
|
+
/**
|
|
21
|
+
* Parse TypeScript. `'erase'` parses it and emits JavaScript: annotations, type-only
|
|
22
|
+
* declarations and imports go, assertions give way to their expression, and what erasure
|
|
23
|
+
* cannot express (enums, namespaces with values, parameter properties, `export =`, `import =`)
|
|
24
|
+
* stays in the tree and is listed as `typescript` on the answer, as are the proposals
|
|
25
|
+
* JavaScript itself has: decorators and accessor fields (`AccessorProperty`).
|
|
26
|
+
*/
|
|
27
|
+
typescript?: boolean | 'erase';
|
|
28
|
+
/**
|
|
29
|
+
* Which decorators are read. 'legacy' refuses decorators on private elements, class
|
|
30
|
+
* expressions and their members; 'proposal' refuses parameter decorators and decorators
|
|
31
|
+
* on abstract or declared fields. Unset reads both syntaxes.
|
|
32
|
+
*/
|
|
33
|
+
decorators?: 'legacy' | 'proposal';
|
|
34
|
+
/** Attach `leadingComments`, `trailingComments` and `innerComments` to nodes, and list every comment read as `comments` on the answer. */
|
|
35
|
+
comments?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Scope analysis: the answer lists `scopes`, `bindings` and `references`, and `scopeOf`,
|
|
38
|
+
* `bindingOf` and `referenceOf` answer for a node. The tree itself carries nothing, and a copy
|
|
39
|
+
* of a node carries no facts. TypeScript type positions bind nothing.
|
|
40
|
+
*/
|
|
41
|
+
scopes?: boolean;
|
|
42
|
+
/** Add `loc` with line and column to every node, as in acorn; off by default. */
|
|
43
|
+
locations?: boolean;
|
|
44
|
+
/** Mark a node the source wraps in parens with `parenthesized: true`, absent otherwise. */
|
|
45
|
+
parenthesized?: boolean;
|
|
46
|
+
allowReturnOutsideFunction?: boolean;
|
|
47
|
+
allowAwaitOutsideFunction?: boolean;
|
|
48
|
+
allowSuperOutsideMethod?: boolean;
|
|
49
|
+
allowUndeclaredExports?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* List syntax errors on the answer as `errors` instead of throwing the first: a missing
|
|
52
|
+
* operand, name or pattern is an `Identifier` named `''` of no width where it was expected,
|
|
53
|
+
* and a statement or entry that cannot be read is skipped to the next stop token or
|
|
54
|
+
* unmatched closing bracket, an empty identifier standing for it. Placeholders are neither
|
|
55
|
+
* bindings nor references.
|
|
56
|
+
*/
|
|
57
|
+
errorRecovery?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Thrown for a syntax error. `code` names what went wrong, for a host to branch on, and
|
|
62
|
+
* `message` says it in words, without a position. An error at the token being read spans it
|
|
63
|
+
* with `pos` and `end`; one reported elsewhere, at a declaration seen earlier say, has `end`
|
|
64
|
+
* equal to `pos`. `unexpected_eof` is the end of what was parsed: the `end` the parse was given,
|
|
65
|
+
* else the end of the source. A bad offset from the host is an `invalid_request` without a `loc`.
|
|
66
|
+
*/
|
|
67
|
+
export interface ParseError extends SyntaxError {
|
|
68
|
+
code: string;
|
|
69
|
+
pos: number;
|
|
70
|
+
end: number;
|
|
71
|
+
loc?: { line: number; column: number };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** A scope, as one of `scopes` on the answer. */
|
|
75
|
+
export interface Scope {
|
|
76
|
+
kind:
|
|
77
|
+
| 'module'
|
|
78
|
+
| 'script'
|
|
79
|
+
| 'function'
|
|
80
|
+
| 'function-name'
|
|
81
|
+
| 'class'
|
|
82
|
+
| 'block'
|
|
83
|
+
| 'catch'
|
|
84
|
+
| 'for'
|
|
85
|
+
| 'switch'
|
|
86
|
+
| 'static-block'
|
|
87
|
+
| 'with'
|
|
88
|
+
| 'namespace'
|
|
89
|
+
| 'enum'
|
|
90
|
+
| 'fragment';
|
|
91
|
+
/** The node that opens it; null for a function-name scope and for the scope around a parameter list parsed on its own. */
|
|
92
|
+
node: Node | null;
|
|
93
|
+
parent: Scope | null;
|
|
94
|
+
/** An `await` or `for await` runs directly in it, no function around; only a program or fragment scope can say so. */
|
|
95
|
+
topLevelAwait: boolean;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** A binding, as one of `bindings` on the answer. */
|
|
99
|
+
export interface Binding {
|
|
100
|
+
name: string;
|
|
101
|
+
kind:
|
|
102
|
+
| 'var'
|
|
103
|
+
| 'let'
|
|
104
|
+
| 'const'
|
|
105
|
+
| 'using'
|
|
106
|
+
| 'await using'
|
|
107
|
+
| 'function'
|
|
108
|
+
| 'class'
|
|
109
|
+
| 'param'
|
|
110
|
+
| 'catch'
|
|
111
|
+
| 'import'
|
|
112
|
+
| 'function-name'
|
|
113
|
+
| 'class-name'
|
|
114
|
+
| 'arguments'
|
|
115
|
+
| 'enum'
|
|
116
|
+
| 'enum-member'
|
|
117
|
+
| 'namespace'
|
|
118
|
+
| 'pattern';
|
|
119
|
+
scope: Scope;
|
|
120
|
+
/** The identifier that declares it; null for `arguments`. */
|
|
121
|
+
node: Identifier | null;
|
|
122
|
+
/** What declares it: the declarator, function, class, import specifier, catch clause or enum, as eslint-scope's definition node; null for `arguments` and for a pattern or parameter list parsed on its own. */
|
|
123
|
+
declaration: Node | null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** A piece of JavaScript a host read on its own, as one of `roots` on a document's answer, with what the tables hold for it. */
|
|
127
|
+
export interface Root {
|
|
128
|
+
node: Node;
|
|
129
|
+
/** The scope the piece sits in. */
|
|
130
|
+
scope: Scope;
|
|
131
|
+
/** The scopes opened inside it, the bindings declared and the references made there. */
|
|
132
|
+
scopes: Scope[];
|
|
133
|
+
bindings: Binding[];
|
|
134
|
+
references: Reference[];
|
|
135
|
+
}
|
|
136
|
+
/** A reference, as one of `references` on the answer. */
|
|
137
|
+
export interface Reference {
|
|
138
|
+
node: Identifier;
|
|
139
|
+
/** The scope the reference is made from. */
|
|
140
|
+
scope: Scope;
|
|
141
|
+
/** Null for a global. */
|
|
142
|
+
binding: Binding | null;
|
|
143
|
+
/** The identifier is assigned to, updated or bound by a destructuring assignment. */
|
|
144
|
+
write: boolean;
|
|
145
|
+
/** A member of the identifier's value is assigned to, updated or deleted. */
|
|
146
|
+
mutate: boolean;
|
|
147
|
+
/** The identifier's value is read: every reference but a plain assignment's target or a destructuring one's; a compound assignment or an update reads and writes. */
|
|
148
|
+
read: boolean;
|
|
149
|
+
/** What a write assigns: the right side of the assignment or the iterated expression of a `for-in` or `for-of`, as eslint-scope's `writeExpr`; null for an update. */
|
|
150
|
+
writeExpr: Expression | null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** The node `node` is a child of; undefined for the root of an answer. A literal's `regex` and a template element's `value` are not nodes and have none. */
|
|
154
|
+
export function parentOf(node: Node): Node | undefined;
|
|
155
|
+
/** With `scopes`: the scope `node` opens, when it opens one. */
|
|
156
|
+
export function scopeOf(node: Node): Scope | undefined;
|
|
157
|
+
/** With `scopes`: what an identifier declares or refers to; null for a global, undefined when it names no value, a property key say. */
|
|
158
|
+
export function bindingOf(node: Node): Binding | null | undefined;
|
|
159
|
+
/** With `scopes`: the reference an identifier makes, with its `write` and `mutate`; a global's too, which no binding lists. */
|
|
160
|
+
export function referenceOf(node: Node): Reference | undefined;
|
|
161
|
+
|
|
162
|
+
/** A range of the source, with `loc` when `locations` is on. */
|
|
163
|
+
export interface Span {
|
|
164
|
+
start: number;
|
|
165
|
+
end: number;
|
|
166
|
+
loc?: { start: { line: number; column: number }; end: { line: number; column: number } };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface Comment extends Span {
|
|
170
|
+
type: 'Line' | 'Block';
|
|
171
|
+
value: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** A node erasure left in place, by type. */
|
|
175
|
+
export interface Kept extends Span {
|
|
176
|
+
type: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** A recovered error: what the thrown `SyntaxError` carries, as a plain object. */
|
|
180
|
+
export type Recovered = Pick<ParseError, 'code' | 'message' | 'pos' | 'end'> & { loc: { line: number; column: number } };
|
|
181
|
+
|
|
182
|
+
/** What a parse returns: the node, or the patterns of a parameter list, and what the options add; a key is there exactly when its option is on. */
|
|
183
|
+
export interface Parsed<T> {
|
|
184
|
+
node: T;
|
|
185
|
+
/** The offset after everything the parse consumed: the node, its closing parens and the comments after it; a program's is the end it was given. */
|
|
186
|
+
end: number;
|
|
187
|
+
/** Every comment read, in source order; with `comments`. */
|
|
188
|
+
comments?: Comment[];
|
|
189
|
+
/** What erasure left in place; with `typescript: 'erase'`. */
|
|
190
|
+
typescript?: Kept[];
|
|
191
|
+
/** The errors recovered from, in source order; with `errorRecovery`. */
|
|
192
|
+
errors?: Recovered[];
|
|
193
|
+
/** With `scopes`. */
|
|
194
|
+
scopes?: Scope[];
|
|
195
|
+
bindings?: Binding[];
|
|
196
|
+
references?: Reference[];
|
|
197
|
+
/** With `scopes`, for a document read by a host grammar: its pieces of JavaScript in source order. */
|
|
198
|
+
roots?: Root[];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* What a parse reads: a program, or what a host embedding JavaScript in a larger syntax reads at
|
|
203
|
+
* a point of it. A type parameter list `<...>` is TypeScript only, `not_typescript` otherwise.
|
|
204
|
+
*/
|
|
205
|
+
export type Entry = 'program' | 'expression' | 'pattern' | 'params' | 'statement' | 'typeParameters';
|
|
206
|
+
|
|
207
|
+
export interface At {
|
|
208
|
+
/** Where the source is cut, a UTF-16 offset; the end of the source by default. A program reads to it. */
|
|
209
|
+
end?: number;
|
|
210
|
+
/**
|
|
211
|
+
* The host's own tokens, words or punctuators, that follow what is parsed. One read outside
|
|
212
|
+
* every bracket the parse opened, where the expression could end, ends it: `,` ends an
|
|
213
|
+
* expression before a sequence would, and `/>` is never a division. A `then` after `.` is a
|
|
214
|
+
* property name. A TypeScript `as` is the host's unless another `as` follows the assertion,
|
|
215
|
+
* so `xs as T[] as item` ends after the type.
|
|
216
|
+
*/
|
|
217
|
+
stopAt?: string[];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* A node of a host language, as its grammar names the type and the fields; the JavaScript under
|
|
222
|
+
* it is ESTree.
|
|
223
|
+
*/
|
|
224
|
+
export interface HostNode {
|
|
225
|
+
type: string;
|
|
226
|
+
start: number;
|
|
227
|
+
end: number;
|
|
228
|
+
loc?: SourceLocation;
|
|
229
|
+
[field: string]: unknown;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* A source kept with its options: the parses out of it share the source copy and the position
|
|
234
|
+
* tables. Offsets are UTF-16, as in acorn; positions stay those of the whole source. `Root` is
|
|
235
|
+
* what the program entry answers with: the program, or the document's root with a `host`.
|
|
236
|
+
*/
|
|
237
|
+
export class Source<Root = Program> {
|
|
238
|
+
constructor(source: string, options?: Options);
|
|
239
|
+
/** The program starting at `offset`, the whole source by default; the document with a `host`. */
|
|
240
|
+
parse(entry?: 'program', offset?: number, at?: At): Parsed<Root>;
|
|
241
|
+
parse(entry: 'expression', offset: number, at?: At): Parsed<Expression>;
|
|
242
|
+
/** An assignment target: an identifier or a destructuring pattern. */
|
|
243
|
+
parse(entry: 'pattern', offset: number, at?: At): Parsed<Pattern>;
|
|
244
|
+
/** A parenthesized parameter list, as an arrow function's is read. */
|
|
245
|
+
parse(entry: 'params', offset: number, at?: At): Parsed<Pattern[]>;
|
|
246
|
+
parse(entry: 'statement', offset: number, at?: At): Parsed<Statement>;
|
|
247
|
+
/** A `TSTypeParameterDeclaration`. */
|
|
248
|
+
parse(entry: 'typeParameters', offset: number, at?: At): Parsed<Node>;
|
|
249
|
+
/** Releases what the engine holds for the source, as `using` does at the end of its block; the collector does it otherwise. */
|
|
250
|
+
[Symbol.dispose](): void;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Whether a code point can start an identifier, as acorn decides it. */
|
|
254
|
+
export function isIdentifierStart(code: number): boolean;
|
|
255
|
+
/** Whether a code point can continue an identifier. */
|
|
256
|
+
export function isIdentifierChar(code: number): boolean;
|
package/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// the source goes over as bytes: V8's encoder is 14x faster than the host reading a string out
|
|
2
|
+
import { bind } from './api.js';
|
|
3
|
+
import { load } from './native.js';
|
|
4
|
+
|
|
5
|
+
export { isIdentifierStart, isIdentifierChar } from './identifier.js';
|
|
6
|
+
export { scopeOf, bindingOf, referenceOf, parentOf } from './decode.js';
|
|
7
|
+
|
|
8
|
+
const native = load();
|
|
9
|
+
const encoder = new TextEncoder();
|
|
10
|
+
let scratch = new Uint8Array(1 << 16);
|
|
11
|
+
|
|
12
|
+
function bytes(text) {
|
|
13
|
+
const size = text.length * 3;
|
|
14
|
+
if (scratch.length < size && size <= 1 << 20) scratch = new Uint8Array(size);
|
|
15
|
+
const room = size <= scratch.length ? scratch : new Uint8Array(size);
|
|
16
|
+
const { written } = encoder.encodeInto(text, room);
|
|
17
|
+
return room.subarray(0, written);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const Source = bind({
|
|
21
|
+
create: (source, names, host) => native.create(bytes(source), names, host),
|
|
22
|
+
parse: native.parse,
|
|
23
|
+
free: native.free,
|
|
24
|
+
constants: native.constants,
|
|
25
|
+
shapes: native.shapes,
|
|
26
|
+
});
|
package/native.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
|
|
3
|
+
export const platforms = {
|
|
4
|
+
'linux-x64-gnu': { target: 'x86_64-unknown-linux-gnu', os: 'linux', cpu: 'x64', libc: 'glibc' },
|
|
5
|
+
'linux-arm64-gnu': { target: 'aarch64-unknown-linux-gnu', os: 'linux', cpu: 'arm64', libc: 'glibc' },
|
|
6
|
+
'darwin-x64': { target: 'x86_64-apple-darwin', os: 'darwin', cpu: 'x64' },
|
|
7
|
+
'darwin-arm64': { target: 'aarch64-apple-darwin', os: 'darwin', cpu: 'arm64' },
|
|
8
|
+
'win32-x64-msvc': { target: 'x86_64-pc-windows-msvc', os: 'win32', cpu: 'x64' },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const here = `${process.platform}-${process.arch}${{ linux: '-gnu', win32: '-msvc' }[process.platform] ?? ''}`;
|
|
12
|
+
|
|
13
|
+
export function load() {
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const file = `teasel.${here}.node`;
|
|
16
|
+
try {
|
|
17
|
+
return require(`./${file}`);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
if (e.code !== 'MODULE_NOT_FOUND') throw e;
|
|
20
|
+
return require(`@teasel/parser-${here}/${file}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teasel/parser",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "A JavaScript parser in Rust
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "A JavaScript and TypeScript parser in Rust. It answers in ESTree.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/Nic-Polumeyv/teasel.git"
|
|
9
9
|
},
|
|
10
|
-
"
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "index.js",
|
|
12
|
+
"types": "index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"node": {
|
|
16
|
+
"types": "./index.d.ts",
|
|
17
|
+
"default": "./index.js"
|
|
18
|
+
},
|
|
19
|
+
"default": {
|
|
20
|
+
"types": "./wasm.d.ts",
|
|
21
|
+
"default": "./wasm.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"./wasm": {
|
|
25
|
+
"types": "./wasm.d.ts",
|
|
26
|
+
"default": "./wasm.js"
|
|
27
|
+
},
|
|
28
|
+
"./teasel.wasm": "./teasel.wasm"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"index.js",
|
|
32
|
+
"index.d.ts",
|
|
33
|
+
"wasm.js",
|
|
34
|
+
"wasm.d.ts",
|
|
35
|
+
"native.js",
|
|
36
|
+
"api.js",
|
|
37
|
+
"decode.js",
|
|
38
|
+
"identifier.js",
|
|
39
|
+
"teasel.wasm"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "bun addon.js",
|
|
43
|
+
"build:wasm": "cargo build --release -p teasel-wasm --target wasm32-unknown-unknown && cp ../target/wasm32-unknown-unknown/release/teasel_wasm.wasm teasel.wasm",
|
|
44
|
+
"test": "bun test.js && bun test.js interpret",
|
|
45
|
+
"check": "node check.js",
|
|
46
|
+
"changeset:version": "changeset version && bun versions.js && git add --all"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@types/estree": "^1.0.6"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@changesets/changelog-github": "^1.0.0",
|
|
53
|
+
"@changesets/cli": "^3.0.1"
|
|
54
|
+
},
|
|
55
|
+
"optionalDependencies": {
|
|
56
|
+
"@teasel/parser-linux-x64-gnu": "0.0.2",
|
|
57
|
+
"@teasel/parser-linux-arm64-gnu": "0.0.2",
|
|
58
|
+
"@teasel/parser-darwin-x64": "0.0.2",
|
|
59
|
+
"@teasel/parser-darwin-arm64": "0.0.2",
|
|
60
|
+
"@teasel/parser-win32-x64-msvc": "0.0.2"
|
|
61
|
+
}
|
|
11
62
|
}
|
package/teasel.wasm
ADDED
|
Binary file
|
package/wasm.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './index.js';
|
package/wasm.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { bind } from './api.js';
|
|
2
|
+
|
|
3
|
+
export { isIdentifierStart, isIdentifierChar } from './identifier.js';
|
|
4
|
+
export { scopeOf, bindingOf, referenceOf, parentOf } from './decode.js';
|
|
5
|
+
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
const utf8 = new TextDecoder();
|
|
8
|
+
|
|
9
|
+
// `teasel.wasm` next to this file, read where there is a file system and fetched elsewhere
|
|
10
|
+
const url = new URL('./teasel.wasm', import.meta.url);
|
|
11
|
+
const { instance } =
|
|
12
|
+
url.protocol === 'file:'
|
|
13
|
+
? await WebAssembly.instantiate(await (await import('node:fs/promises')).readFile(url), {})
|
|
14
|
+
: await WebAssembly.instantiateStreaming(fetch(url), {});
|
|
15
|
+
/** @type {WebAssembly.Exports & Record<string, Function> & { memory: WebAssembly.Memory }} */
|
|
16
|
+
const wasm = /** @type {any} */ (instance.exports);
|
|
17
|
+
/** @type {string[]} */
|
|
18
|
+
let constants = [];
|
|
19
|
+
/** @type {number[]} */
|
|
20
|
+
let shapes = [];
|
|
21
|
+
let shapes_known = 0;
|
|
22
|
+
|
|
23
|
+
// the module takes the bytes over
|
|
24
|
+
function bytes(text) {
|
|
25
|
+
const capacity = text.length * 3;
|
|
26
|
+
const ptr = wasm.alloc(capacity);
|
|
27
|
+
const { written } = encoder.encodeInto(text, new Uint8Array(wasm.memory.buffer, ptr, capacity));
|
|
28
|
+
return [ptr, written, capacity];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function create(source, names, host) {
|
|
32
|
+
const handle = wasm.source_new(...bytes(source), ...bytes(names), ...bytes(host));
|
|
33
|
+
if (handle === 0) throw new Error(JSON.parse(text()).error.message);
|
|
34
|
+
return handle;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const text = () => utf8.decode(new Uint8Array(wasm.memory.buffer, wasm.text_ptr(), wasm.text_len()));
|
|
38
|
+
const words = () => new Uint32Array(wasm.memory.buffer, wasm.words_ptr(), wasm.words_len());
|
|
39
|
+
|
|
40
|
+
// the constants and shapes come first: writing them can grow the memory and detach a view taken before
|
|
41
|
+
function answer(status) {
|
|
42
|
+
if (status !== 0) return text();
|
|
43
|
+
if (words()[4] > constants.length) {
|
|
44
|
+
wasm.constants();
|
|
45
|
+
constants = JSON.parse(text());
|
|
46
|
+
}
|
|
47
|
+
if (words()[5] > shapes_known) {
|
|
48
|
+
shapes_known = words()[5];
|
|
49
|
+
wasm.shapes();
|
|
50
|
+
shapes = JSON.parse(text());
|
|
51
|
+
}
|
|
52
|
+
return words();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const Source = bind({
|
|
56
|
+
create,
|
|
57
|
+
// the words outlive the source: they sit in the answer buffer until the next parse
|
|
58
|
+
parse: (held, entry, offset, end, stop) => answer(wasm.source_parse(held, entry, offset, end ?? 0, end === undefined ? 0 : 1, ...bytes(stop))),
|
|
59
|
+
free: (held) => wasm.source_free(held),
|
|
60
|
+
constants: () => constants,
|
|
61
|
+
shapes: () => shapes,
|
|
62
|
+
});
|