oxc-parser 0.54.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -100,6 +100,14 @@ export declare const enum ExportLocalNameKind {
100
100
  None = 'None'
101
101
  }
102
102
 
103
+ /**
104
+ * Get offset within a `Uint8Array` which is aligned on 4 GiB.
105
+ *
106
+ * Does not check that the offset is within bounds of `buffer`.
107
+ * To ensure it always is, provide a `Uint8Array` of at least 4 GiB size.
108
+ */
109
+ export declare function getBufferOffset(buffer: Uint8Array): number
110
+
103
111
  export interface ImportName {
104
112
  kind: ImportNameKind
105
113
  name?: string
@@ -134,6 +142,14 @@ export interface ParserOptions {
134
142
  sourceType?: 'script' | 'module' | 'unambiguous' | undefined
135
143
  /** Treat the source text as `js`, `jsx`, `ts`, or `tsx`. */
136
144
  lang?: 'js' | 'jsx' | 'ts' | 'tsx'
145
+ /**
146
+ * Return an AST which includes TypeScript-related properties, or excludes them.
147
+ *
148
+ * `'js'` is default for JS / JSX files.
149
+ * `'ts'` is default for TS / TSX files.
150
+ * The type of the file is determined from `lang` option, or extension of provided `filename`.
151
+ */
152
+ astType?: 'js' | 'ts'
137
153
  /**
138
154
  * Emit `ParenthesizedExpression` in AST.
139
155
  *
@@ -157,6 +173,37 @@ export interface ParserOptions {
157
173
  /** Parse synchronously. */
158
174
  export declare function parseSync(filename: string, sourceText: string, options?: ParserOptions | undefined | null): ParseResult
159
175
 
176
+ /**
177
+ * Parses AST into provided `Uint8Array` buffer.
178
+ *
179
+ * Source text must be written into the start of the buffer, and its length (in UTF-8 bytes)
180
+ * provided as `source_len`.
181
+ *
182
+ * This function will parse the source, and write the AST into the buffer, starting at the end.
183
+ *
184
+ * It also writes to the very end of the buffer the offset of `Program` within the buffer.
185
+ *
186
+ * Caller can deserialize data from the buffer on JS side.
187
+ *
188
+ * # SAFETY
189
+ *
190
+ * Caller must ensure:
191
+ * * Source text is written into start of the buffer.
192
+ * * Source text's UTF-8 byte length is `source_len`.
193
+ * * The 1st `source_len` bytes of the buffer comprises a valid UTF-8 string.
194
+ *
195
+ * If source text is originally a JS string on JS side, and converted to a buffer with
196
+ * `Buffer.from(str)` or `new TextEncoder().encode(str)`, this guarantees it's valid UTF-8.
197
+ *
198
+ * # Panics
199
+ *
200
+ * Panics if source text is too long, or AST takes more memory than is available in the buffer.
201
+ */
202
+ export declare function parseSyncRaw(filename: string, buffer: Uint8Array, sourceLen: number, options?: ParserOptions | undefined | null): void
203
+
204
+ /** Returns `true` if raw transfer is supported on this platform. */
205
+ export declare function rawTransferSupported(): boolean
206
+
160
207
  export declare const enum Severity {
161
208
  Error = 'Error',
162
209
  Warning = 'Warning',
package/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  const bindings = require('./bindings.js');
2
+ const deserializeJS = require('./deserialize-js.js');
3
+ const deserializeTS = require('./deserialize-ts.js');
2
4
 
3
5
  module.exports.ParseResult = bindings.ParseResult;
4
6
  module.exports.ExportExportNameKind = bindings.ExportExportNameKind;
@@ -55,6 +57,99 @@ module.exports.parseAsync = async function parseAsync(...args) {
55
57
  return wrap(await bindings.parseAsync(...args));
56
58
  };
57
59
 
58
- module.exports.parseSync = function parseSync(...args) {
59
- return wrap(bindings.parseSync(...args));
60
+ module.exports.parseSync = function parseSync(filename, sourceText, options) {
61
+ if (options?.experimentalRawTransfer) {
62
+ return parseSyncRaw(filename, sourceText, options);
63
+ }
64
+
65
+ return wrap(bindings.parseSync(filename, sourceText, options));
60
66
  };
67
+
68
+ let buffer, encoder;
69
+
70
+ function parseSyncRaw(filename, sourceText, options) {
71
+ if (!rawTransferSupported()) {
72
+ throw new Error('`experimentalRawTransfer` option is not supported on 32-bit or big-endian systems');
73
+ }
74
+
75
+ // Delete `experimentalRawTransfer` option
76
+ let experimentalRawTransfer;
77
+ ({ experimentalRawTransfer, ...options } = options);
78
+
79
+ // Create buffer and `TextEncoder`
80
+ if (!buffer) {
81
+ buffer = createBuffer();
82
+ encoder = new TextEncoder();
83
+ }
84
+
85
+ // Write source into start of buffer.
86
+ // `TextEncoder` cannot write into a `Uint8Array` larger than 1 GiB,
87
+ // so create a view into buffer of this size to write into.
88
+ const sourceBuffer = new Uint8Array(buffer.buffer, buffer.byteOffset, ONE_GIB);
89
+ const { read, written: sourceByteLen } = encoder.encodeInto(sourceText, sourceBuffer);
90
+ if (read !== sourceText.length) {
91
+ throw new Error('Failed to write source text into buffer');
92
+ }
93
+
94
+ // Parse
95
+ bindings.parseSyncRaw(filename, buffer, sourceByteLen, options);
96
+
97
+ // Deserialize.
98
+ // We cannot lazily deserialize in the getters, because the buffer might be re-used to parse
99
+ // another file before the getter is called.
100
+
101
+ // (2 * 1024 * 1024 * 1024 - 12)
102
+ const astTypeFlagPos = 2147483636;
103
+ let isJsAst = buffer[astTypeFlagPos] === 0;
104
+
105
+ const data = isJsAst
106
+ ? deserializeJS(buffer, sourceText, sourceByteLen)
107
+ : deserializeTS(buffer, sourceText, sourceByteLen);
108
+
109
+ return {
110
+ get program() {
111
+ return data.program;
112
+ },
113
+ get module() {
114
+ return data.module;
115
+ },
116
+ get comments() {
117
+ return data.comments;
118
+ },
119
+ get errors() {
120
+ return data.errors;
121
+ },
122
+ };
123
+ }
124
+
125
+ const ONE_GIB = 1 << 30,
126
+ TWO_GIB = ONE_GIB * 2,
127
+ SIX_GIB = ONE_GIB * 6;
128
+
129
+ // Create a `Uint8Array` which is 2 GiB in size, with its start aligned on 4 GiB.
130
+ //
131
+ // Achieve this by creating a 6 GiB `ArrayBuffer`, getting the offset within it that's aligned to 4 GiB,
132
+ // chopping off that number of bytes from the start, and shortening to 2 GiB.
133
+ //
134
+ // It's always possible to obtain a 2 GiB slice aligned on 4 GiB within a 6 GiB buffer,
135
+ // no matter how the 6 GiB buffer is aligned.
136
+ //
137
+ // Note: On systems with virtual memory, this only consumes 6 GiB of *virtual* memory.
138
+ // It does not consume physical memory until data is actually written to the `Uint8Array`.
139
+ // Physical memory consumed corresponds to the quantity of data actually written.
140
+ function createBuffer() {
141
+ const arrayBuffer = new ArrayBuffer(SIX_GIB);
142
+ const offset = bindings.getBufferOffset(new Uint8Array(arrayBuffer));
143
+ return new Uint8Array(arrayBuffer, offset, TWO_GIB);
144
+ }
145
+
146
+ let rawTransferIsSupported = null;
147
+
148
+ // Returns `true` if `experimentalRawTransfer` is option is supported.
149
+ // Raw transfer is only available on 64-bit little-endian systems.
150
+ function rawTransferSupported() {
151
+ if (rawTransferIsSupported === null) rawTransferIsSupported = bindings.rawTransferSupported();
152
+ return rawTransferIsSupported;
153
+ }
154
+
155
+ module.exports.rawTransferSupported = rawTransferSupported;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxc-parser",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "Oxc Parser Node API",
5
5
  "keywords": [
6
6
  "Parser"
@@ -21,19 +21,21 @@
21
21
  "files": [
22
22
  "index.d.ts",
23
23
  "index.js",
24
- "bindings.js"
24
+ "bindings.js",
25
+ "deserialize-js.js",
26
+ "deserialize-ts.js"
25
27
  ],
26
28
  "dependencies": {
27
- "@oxc-project/types": "^0.54.0"
29
+ "@oxc-project/types": "^0.56.0"
28
30
  },
29
31
  "optionalDependencies": {
30
- "@oxc-parser/binding-win32-x64-msvc": "0.54.0",
31
- "@oxc-parser/binding-win32-arm64-msvc": "0.54.0",
32
- "@oxc-parser/binding-linux-x64-gnu": "0.54.0",
33
- "@oxc-parser/binding-linux-arm64-gnu": "0.54.0",
34
- "@oxc-parser/binding-linux-x64-musl": "0.54.0",
35
- "@oxc-parser/binding-linux-arm64-musl": "0.54.0",
36
- "@oxc-parser/binding-darwin-x64": "0.54.0",
37
- "@oxc-parser/binding-darwin-arm64": "0.54.0"
32
+ "@oxc-parser/binding-win32-x64-msvc": "0.56.0",
33
+ "@oxc-parser/binding-win32-arm64-msvc": "0.56.0",
34
+ "@oxc-parser/binding-linux-x64-gnu": "0.56.0",
35
+ "@oxc-parser/binding-linux-arm64-gnu": "0.56.0",
36
+ "@oxc-parser/binding-linux-x64-musl": "0.56.0",
37
+ "@oxc-parser/binding-linux-arm64-musl": "0.56.0",
38
+ "@oxc-parser/binding-darwin-x64": "0.56.0",
39
+ "@oxc-parser/binding-darwin-arm64": "0.56.0"
38
40
  }
39
41
  }