oxc-parser 0.73.2 → 0.75.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.
@@ -1,14 +1,74 @@
1
1
  'use strict';
2
2
 
3
- const { parseSyncRawImpl, parseAsyncRawImpl, returnBufferToCache } = require('./index.js');
3
+ const { parseSyncRawImpl, parseAsyncRawImpl, returnBufferToCache } = require('./common.js'),
4
+ { TOKEN } = require('./lazy-common.js'),
5
+ constructLazyData = require('../generated/deserialize/lazy.js').construct,
6
+ walkProgram = require('../generated/deserialize/lazy-visit.js'),
7
+ { Visitor, getVisitorsArr } = require('./visitor.js');
4
8
 
5
- module.exports = { parseSyncLazy, parseAsyncLazy };
9
+ module.exports = { parseSyncLazy, parseAsyncLazy, Visitor };
6
10
 
11
+ /**
12
+ * Parse JS/TS source synchronously on current thread.
13
+ *
14
+ * The data in buffer is not deserialized. Is deserialized to JS objects lazily, when accessing the
15
+ * properties of objects.
16
+ *
17
+ * e.g. `program` in returned object is an instance of `Program` class, with getters for `start`, `end`,
18
+ * `body` etc.
19
+ *
20
+ * Returned object contains a `visit` function which can be used to visit the AST with a `Visitor`
21
+ * (`Visitor` class can be obtained by calling `experimentalGetLazyVisitor()`).
22
+ *
23
+ * Returned object contains a `dispose` method. When finished with this AST, it's advisable to call
24
+ * `dispose`, to return the buffer to the cache, so it can be reused.
25
+ * Garbage collector should do this anyway at some point, but on an unpredictable schedule,
26
+ * so it's preferable to call `dispose` manually, to ensure the buffer can be reused immediately.
27
+ *
28
+ * @param {string} filename - Filename
29
+ * @param {string} sourceText - Source text of file
30
+ * @param {Object} options - Parsing options
31
+ * @returns {Object} - Object with property getters for `program`, `module`, `comments`, and `errors`,
32
+ * and `dispose` and `visit` methods
33
+ * @throws {Error} - If raw transfer is not supported on this platform
34
+ */
7
35
  function parseSyncLazy(filename, sourceText, options) {
36
+ let _;
37
+ ({ experimentalLazy: _, ...options } = options);
8
38
  return parseSyncRawImpl(filename, sourceText, options, construct);
9
39
  }
10
40
 
41
+ /**
42
+ * Parse JS/TS source asynchronously on a separate thread.
43
+ *
44
+ * The data in buffer is not deserialized. Is deserialized to JS objects lazily, when accessing the
45
+ * properties of objects.
46
+ *
47
+ * e.g. `program` in returned object is an instance of `Program` class, with getters for `start`, `end`,
48
+ * `body` etc.
49
+ *
50
+ * Because this function does not deserialize the AST, unlike `parseAsyncRaw`, very little work happens
51
+ * on current thread in this function. Deserialization work only occurs when properties of the objects
52
+ * are accessed.
53
+ *
54
+ * Returned object contains a `visit` function which can be used to visit the AST with a `Visitor`
55
+ * (`Visitor` class can be obtained by calling `experimentalGetLazyVisitor()`).
56
+ *
57
+ * Returned object contains a `dispose` method. When finished with this AST, it's advisable to call
58
+ * `dispose`, to return the buffer to the cache, so it can be reused.
59
+ * Garbage collector should do this anyway at some point, but on an unpredictable schedule,
60
+ * so it's preferable to call `dispose` manually, to ensure the buffer can be reused immediately.
61
+ *
62
+ * @param {string} filename - Filename
63
+ * @param {string} sourceText - Source text of file
64
+ * @param {Object} options - Parsing options
65
+ * @returns {Object} - Object with property getters for `program`, `module`, `comments`, and `errors`,
66
+ * and `dispose` and `visit` methods
67
+ * @throws {Error} - If raw transfer is not supported on this platform
68
+ */
11
69
  function parseAsyncLazy(filename, sourceText, options) {
70
+ let _;
71
+ ({ experimentalLazy: _, ...options } = options);
12
72
  return parseAsyncRawImpl(filename, sourceText, options, construct);
13
73
  }
14
74
 
@@ -23,15 +83,18 @@ const bufferRecycleRegistry = typeof FinalizationRegistry === 'undefined'
23
83
  ? null
24
84
  : new FinalizationRegistry(returnBufferToCache);
25
85
 
26
- let constructLazyData = null, TOKEN;
27
-
28
- // Get an object with getters which lazy deserialize AST from buffer
86
+ /**
87
+ * Get an object with getters which lazy deserialize AST and other data from buffer.
88
+ *
89
+ * Object also includes `dispose` and `visit` functions.
90
+ *
91
+ * @param {Uint8Array} buffer - Buffer containing AST in raw form
92
+ * @param {string} sourceText - Source for the file
93
+ * @param {number} sourceByteLen - Length of source text in UTF-8 bytes
94
+ * @returns {Object} - Object with property getters for `program`, `module`, `comments`, and `errors`,
95
+ * and `dispose` and `visit` methods
96
+ */
29
97
  function construct(buffer, sourceText, sourceLen) {
30
- // Lazy load deserializer, and get `TOKEN` to store in `ast` objects
31
- if (constructLazyData === null) {
32
- ({ construct: constructLazyData, TOKEN } = require('../generated/deserialize/lazy.js'));
33
- }
34
-
35
98
  // Create AST object
36
99
  const sourceIsAscii = sourceText.length === sourceLen;
37
100
  const ast = { buffer, sourceText, sourceLen, sourceIsAscii, nodes: new Map(), token: TOKEN };
@@ -57,21 +120,32 @@ function construct(buffer, sourceText, sourceLen) {
57
120
  return data.errors;
58
121
  },
59
122
  dispose: dispose.bind(null, ast),
123
+ visit(visitor) {
124
+ // (2 * 1024 * 1024 * 1024 - 16) >> 2
125
+ const metadataPos32 = 536870908;
126
+ const pos = buffer.uint32[metadataPos32];
127
+ walkProgram(pos, ast, getVisitorsArr(visitor));
128
+ },
60
129
  };
61
130
  }
62
131
 
63
- // Dispose of this AST.
64
- //
65
- // After calling this method, trying to read any nodes from this AST may cause an error.
66
- //
67
- // Buffer is returned to the cache to be reused.
68
- //
69
- // The buffer would be returned to the cache anyway, once all nodes of the AST are garbage collected,
70
- // but calling `dispose` is preferable, as it will happen immediately.
71
- // Otherwise, garbage collector may take time to collect the `ast` object, and new buffers may be created
72
- // in the meantime, when we could have reused this one.
132
+ /**
133
+ * Dispose of this AST.
134
+ *
135
+ * After calling this method, trying to read any nodes from this AST may cause an error.
136
+ *
137
+ * Buffer is returned to the cache to be reused.
138
+ *
139
+ * The buffer would be returned to the cache anyway, once all nodes of the AST are garbage collected,
140
+ * but calling `dispose` is preferable, as it will happen immediately.
141
+ * Otherwise, garbage collector may take time to collect the `ast` object, and new buffers may be created
142
+ * in the meantime, when we could have reused this one.
143
+ *
144
+ * @param {Object} ast - AST object containing buffer etc
145
+ * @returns {undefined}
146
+ */
73
147
  function dispose(ast) {
74
- // Return buffer to cache to be reused
148
+ // Return buffer to cache, to be reused
75
149
  returnBufferToCache(ast.buffer);
76
150
 
77
151
  // Remove connection between `ast` and the buffer
@@ -2,22 +2,27 @@
2
2
 
3
3
  const { TOKEN, constructorError } = require('./lazy-common.js');
4
4
 
5
- // Mapping from a proxy to the `NodeArray` that it wraps.
6
- // Used by `slice`, `values`, `key` and `elements` methods.
5
+ // Internal symbol to get `NodeArray` from a proxy wrapping a `NodeArray`.
7
6
  //
8
- // TODO: Is there any way to avoid this?
9
- // Seems necessary because `this` in methods is a proxy, so accessing `this.#internal` throws.
10
- const nodeArrays = new WeakMap();
7
+ // Methods of `NodeArray` are called with `this` being the proxy, rather than the `NodeArray` itself.
8
+ // They can "unwrap" the proxy by getting `this[ARRAY]`, and the `get` proxy trap will return
9
+ // the actual `NodeArray`.
10
+ //
11
+ // This symbol is not exported, and it is not actually defined on `NodeArray`s, so user cannot obtain it
12
+ // via `Object.getOwnPropertySymbols` or `Reflect.ownKeys`. Therefore user code cannot unwrap the proxy.
13
+ const ARRAY = Symbol();
11
14
 
12
- // Function to get element from an array. Initialized in class static block below.
13
- let getElement;
15
+ // Functions to get internal properties of a `NodeArray`. Initialized in class static block below.
16
+ let getInternalFromProxy, getLength, getElement;
14
17
 
15
- // An array of AST nodes where elements are deserialized lazily upon access.
16
- //
17
- // Extends `Array` to make `Array.isArray` return `true` for a `NodeArray`.
18
- //
19
- // TODO: Other methods could maybe be more optimal, avoiding going via proxy multiple times
20
- // e.g. `some`, `indexOf`.
18
+ /**
19
+ * An array of AST nodes where elements are deserialized lazily upon access.
20
+ *
21
+ * Extends `Array` to make `Array.isArray` return `true` for a `NodeArray`.
22
+ *
23
+ * TODO: Other methods could maybe be more optimal, avoiding going via proxy multiple times
24
+ * e.g. `some`, `indexOf`.
25
+ */
21
26
  class NodeArray extends Array {
22
27
  #internal;
23
28
 
@@ -39,12 +44,9 @@ class NodeArray extends Array {
39
44
  constructor(pos, length, stride, construct, ast) {
40
45
  if (ast?.token !== TOKEN) constructorError();
41
46
 
42
- super(length);
43
- this.#internal = { pos, ast, stride, construct };
44
-
45
- const proxy = new Proxy(this, PROXY_HANDLERS);
46
- nodeArrays.set(proxy, this);
47
- return proxy;
47
+ super();
48
+ this.#internal = { pos, length, ast, stride, construct };
49
+ return new Proxy(this, PROXY_HANDLERS);
48
50
  }
49
51
 
50
52
  // Allow `arr.filter`, `arr.map` etc.
@@ -53,66 +55,63 @@ class NodeArray extends Array {
53
55
  // Override `values` method with a more efficient one that avoids going via proxy for every iteration.
54
56
  // TODO: Benchmark to check that this is actually faster.
55
57
  values() {
56
- // Get actual `NodeArray`. `this` is a proxy.
57
- const arr = nodeArrays.get(this);
58
- return new NodeArrayValuesIterator(arr.#internal, arr.length);
58
+ return new NodeArrayValuesIterator(this);
59
59
  }
60
60
 
61
61
  // Override `keys` method with a more efficient one that avoids going via proxy for every iteration.
62
62
  // TODO: Benchmark to check that this is actually faster.
63
63
  keys() {
64
- // Get actual `NodeArray`. `this` is a proxy.
65
- // TODO: `this.length` would work here.
66
- // Not sure which is more expensive - property lookup via proxy, or `WeakMap` lookup.
67
- const arr = nodeArrays.get(this);
68
- return new NodeArrayKeysIterator(arr.length);
64
+ return new NodeArrayKeysIterator(this);
69
65
  }
70
66
 
71
67
  // Override `entries` method with a more efficient one that avoids going via proxy for every iteration.
72
68
  // TODO: Benchmark to check that this is actually faster.
73
69
  entries() {
74
- // Get actual `NodeArray`. `this` is a proxy.
75
- const arr = nodeArrays.get(this);
76
- return new NodeArrayEntriesIterator(arr.#internal, arr.length);
70
+ return new NodeArrayEntriesIterator(this);
77
71
  }
78
72
 
79
73
  // This method is overwritten with reference to `values` method below.
80
74
  // Defining dummy method here to prevent the later assignment altering the shape of class prototype.
81
75
  [Symbol.iterator]() {}
82
76
 
83
- // Override `slice` method to return a `NodeArray`.
77
+ /**
78
+ * Override `slice` method to return a `NodeArray`.
79
+ *
80
+ * @this {NodeArray}
81
+ * @param {*} start - Start of slice
82
+ * @param {*} end - End of slice
83
+ * @returns {NodeArray} - `NodeArray` containing slice of this one
84
+ */
84
85
  slice(start, end) {
85
- // Get actual `NodeArray`. `this` is a proxy.
86
- const arr = nodeArrays.get(this);
87
- if (arr === void 0) throw new Error('`slice` called on a value which is not a `NodeArray`');
86
+ const internal = this[ARRAY].#internal,
87
+ { length } = internal;
88
88
 
89
89
  start = toInt(start);
90
90
  if (start < 0) {
91
- start = arr.length + start;
91
+ start = length + start;
92
92
  if (start < 0) start = 0;
93
93
  }
94
94
 
95
95
  if (end === void 0) {
96
- end = arr.length;
96
+ end = length;
97
97
  } else {
98
98
  end = toInt(end);
99
99
  if (end < 0) {
100
- end = arr.length + end;
100
+ end += length;
101
101
  if (end < 0) end = 0;
102
- } else if (end > arr.length) {
103
- end = arr.length;
102
+ } else if (end > length) {
103
+ end = length;
104
104
  }
105
105
  }
106
106
 
107
- let length = end - start;
108
- if (length <= 0 || start >= arr.length) {
107
+ let sliceLength = end - start;
108
+ if (sliceLength <= 0 || start >= length) {
109
109
  start = 0;
110
- length = 0;
110
+ sliceLength = 0;
111
111
  }
112
112
 
113
- const internal = arr.#internal,
114
- { stride } = internal;
115
- return new NodeArray(internal.pos + start * stride, length, stride, internal.construct, internal.ast);
113
+ const { stride } = internal;
114
+ return new NodeArray(internal.pos + start * stride, sliceLength, stride, internal.construct, internal.ast);
116
115
  }
117
116
 
118
117
  // Make `console.log` deserialize all elements.
@@ -123,16 +122,30 @@ class NodeArray extends Array {
123
122
  }
124
123
 
125
124
  static {
125
+ /**
126
+ * Get internal properties of `NodeArray`, given a proxy wrapping a `NodeArray`.
127
+ * @param {Proxy} proxy - Proxy wrapping `NodeArray` object
128
+ * @returns {Object} - Internal properties object
129
+ */
130
+ getInternalFromProxy = proxy => proxy[ARRAY].#internal;
131
+
132
+ /**
133
+ * Get length of `NodeArray`.
134
+ * @param {NodeArray} arr - `NodeArray` object
135
+ * @returns {number} - Array length
136
+ */
137
+ getLength = arr => arr.#internal.length;
138
+
126
139
  /**
127
140
  * Get element of `NodeArray` at index `index`.
128
- * `index` must be in bounds (i.e. `< arr.length`).
129
141
  *
130
142
  * @param {NodeArray} arr - `NodeArray` object
131
143
  * @param {number} index - Index of element to get
132
- * @returns {*} - Element at index `index`
144
+ * @returns {*|undefined} - Element at index `index`, or `undefined` if out of bounds
133
145
  */
134
146
  getElement = (arr, index) => {
135
147
  const internal = arr.#internal;
148
+ if (index >= internal.length) return void 0;
136
149
  return (0, internal.construct)(internal.pos + index * internal.stride, internal.ast);
137
150
  };
138
151
  }
@@ -142,20 +155,22 @@ NodeArray.prototype[Symbol.iterator] = NodeArray.prototype.values;
142
155
 
143
156
  module.exports = NodeArray;
144
157
 
145
- // Iterator over values of a `NodeArray`.
146
- // Returned by `values` method, and also used as iterator for `for (const node of nodeArray) {}`.
158
+ /**
159
+ * Iterator over values of a `NodeArray`.
160
+ * Returned by `values` method, and also used as iterator for `for (const node of nodeArray) {}`.
161
+ */
147
162
  class NodeArrayValuesIterator {
148
163
  #internal;
149
164
 
150
- constructor(arrInternal, length) {
151
- const { ast, pos, stride } = arrInternal || {};
152
- if (ast?.token !== TOKEN) constructorError();
165
+ constructor(proxy) {
166
+ const internal = getInternalFromProxy(proxy),
167
+ { pos, stride } = internal;
153
168
 
154
169
  this.#internal = {
155
170
  pos,
156
- endPos: pos + length * stride,
157
- ast,
158
- construct: arrInternal.construct,
171
+ endPos: pos + internal.length * stride,
172
+ ast: internal.ast,
173
+ construct: internal.construct,
159
174
  stride,
160
175
  };
161
176
  }
@@ -173,14 +188,15 @@ class NodeArrayValuesIterator {
173
188
  }
174
189
  }
175
190
 
176
- // Iterator over keys of a `NodeArray`. Returned by `keys` method.
191
+ /**
192
+ * Iterator over keys of a `NodeArray`. Returned by `keys` method.
193
+ */
177
194
  class NodeArrayKeysIterator {
178
195
  #internal;
179
196
 
180
- constructor(length) {
181
- // Don't bother gating constructor with `TOKEN` check.
182
- // This iterator doesn't access the buffer, so is harmless.
183
- this.#internal = { index: 0, length };
197
+ constructor(proxy) {
198
+ const internal = getInternalFromProxy(proxy);
199
+ this.#internal = { index: 0, length: internal.length };
184
200
  }
185
201
 
186
202
  next() {
@@ -196,21 +212,22 @@ class NodeArrayKeysIterator {
196
212
  }
197
213
  }
198
214
 
199
- // Iterator over values of a `NodeArray`. Returned by `entries` method.
215
+ /**
216
+ * Iterator over values of a `NodeArray`. Returned by `entries` method.
217
+ */
200
218
  class NodeArrayEntriesIterator {
201
219
  #internal;
202
220
 
203
- constructor(arrInternal, length) {
204
- const { ast } = arrInternal || {};
205
- if (ast?.token !== TOKEN) constructorError();
221
+ constructor(proxy) {
222
+ const internal = getInternalFromProxy(proxy);
206
223
 
207
224
  this.#internal = {
208
225
  index: 0,
209
- length,
210
- pos: arrInternal.pos,
211
- ast,
212
- construct: arrInternal.construct,
213
- stride: arrInternal.stride,
226
+ length: internal.length,
227
+ pos: internal.pos,
228
+ ast: internal.ast,
229
+ construct: internal.construct,
230
+ stride: internal.stride,
214
231
  };
215
232
  }
216
233
 
@@ -241,29 +258,38 @@ const PROXY_HANDLERS = {
241
258
  // Return `true` for indexes which are in bounds.
242
259
  // e.g. `'0' in arr`.
243
260
  has(arr, key) {
244
- if (isIndex(key)) return key * 1 < arr.length;
261
+ const index = toIndex(key);
262
+ if (index !== null) return index < getLength(arr);
245
263
  return Reflect.has(arr, key);
246
264
  },
247
265
 
248
- // Get entries which are in bounds.
266
+ // Get elements and length.
249
267
  get(arr, key) {
250
- if (isIndex(key)) {
251
- key *= 1;
252
- if (key >= arr.length) return void 0;
253
- return getElement(arr, key);
254
- }
268
+ // Methods of `NodeArray` are called with `this` being the proxy, rather than the `NodeArray` itself.
269
+ // They can "unwrap" the proxy by getting `this[ARRAY]`.
270
+ if (key === ARRAY) return arr;
271
+ if (key === 'length') return getLength(arr);
272
+ const index = toIndex(key);
273
+ if (index !== null) return getElement(arr, index);
274
+
255
275
  return Reflect.get(arr, key);
256
276
  },
257
277
 
258
- // Get descriptors which are in bounds.
278
+ // Get descriptors for elements and length.
259
279
  getOwnPropertyDescriptor(arr, key) {
260
- if (isIndex(key)) {
261
- key *= 1;
262
- if (key >= arr.length) return void 0;
280
+ if (key === 'length') {
281
+ // Cannot return `writable: false` unfortunately
282
+ return { value: getLength(arr), writable: true, enumerable: false, configurable: false };
283
+ }
284
+
285
+ const index = toIndex(key);
286
+ if (index !== null) {
287
+ const value = getElement(arr, index);
288
+ if (value === void 0) return void 0;
263
289
  // Cannot return `configurable: false` unfortunately
264
- return { value: getElement(arr, key), writable: false, enumerable: true, configurable: true };
290
+ return { value, writable: false, enumerable: true, configurable: true };
265
291
  }
266
- // Cannot return `writable: false` for `length` property unfortunately
292
+
267
293
  return Reflect.getOwnPropertyDescriptor(arr, key);
268
294
  },
269
295
 
@@ -275,21 +301,22 @@ const PROXY_HANDLERS = {
275
301
  // * `Object.defineProperty(arr, 'length', {value: 0})`.
276
302
  // * Other operations which mutate entries e.g. `arr.push(123)`.
277
303
  defineProperty(arr, key, descriptor) {
278
- if (key === 'length' || isIndex(key)) return false;
304
+ if (key === 'length' || toIndex(key) !== null) return false;
279
305
  return Reflect.defineProperty(arr, key, descriptor);
280
306
  },
281
307
 
282
308
  // Prevent deleting entries.
283
309
  deleteProperty(arr, key) {
284
310
  // Note: `Reflect.deleteProperty(arr, 'length')` already returns `false`
285
- if (isIndex(key)) return false;
311
+ if (toIndex(key) !== null) return false;
286
312
  return Reflect.deleteProperty(arr, key);
287
313
  },
288
314
 
289
315
  // Get keys, including element indexes.
290
316
  ownKeys(arr) {
291
- const keys = [];
292
- for (let i = 0; i < arr.length; i++) {
317
+ const keys = [],
318
+ length = getLength(arr);
319
+ for (let i = 0; i < length; i++) {
293
320
  keys.push(i + '');
294
321
  }
295
322
  keys.push(...Reflect.ownKeys(arr));
@@ -298,16 +325,24 @@ const PROXY_HANDLERS = {
298
325
  };
299
326
 
300
327
  /**
301
- * Check if a key is a valid array index.
328
+ * Convert key to array index, if it is a valid array index.
329
+ *
302
330
  * Only strings comprising a plain integer are valid indexes.
303
331
  * e.g. `"-1"`, `"01"`, `"0xFF"`, `"1e1"`, `"1 "` are not valid indexes.
332
+ * Integers >= 4294967295 are not valid indexes.
304
333
  *
305
- * @param {*} - Key used for property lookup.
306
- * @returns {boolean} - `true` if `key` is a valid array index.
334
+ * @param {string|Symbol} - Key used for property lookup.
335
+ * @returns {number|null} - `key` converted to integer, if it's a valid array index, otherwise `null`.
307
336
  */
308
- function isIndex(key) {
309
- // TODO: Any way to do this without a regex?
310
- return typeof key === 'string' && (key === '0' || INDEX_REGEX.test(key));
337
+ function toIndex(key) {
338
+ if (typeof key === 'string') {
339
+ if (key === '0') return 0;
340
+ if (INDEX_REGEX.test(key)) {
341
+ const index = +key;
342
+ if (index < 4294967295) return index;
343
+ }
344
+ }
345
+ return null;
311
346
  }
312
347
 
313
348
  const INDEX_REGEX = /^[1-9]\d*$/;
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const rawTransferSupportedBinding = require('../bindings.js').rawTransferSupported;
4
+
5
+ module.exports = rawTransferSupported;
6
+
7
+ let rawTransferIsSupported = null;
8
+
9
+ /**
10
+ * Returns `true` if `experimentalRawTransfer` is option is supported.
11
+ *
12
+ * Raw transfer is only supported on 64-bit little-endian systems,
13
+ * and NodeJS >= v22.0.0 or Deno >= v2.0.0.
14
+ *
15
+ * Versions of NodeJS prior to v22.0.0 do not support creating an `ArrayBuffer` larger than 4 GiB.
16
+ * Bun (as at v1.2.4) also does not support creating an `ArrayBuffer` larger than 4 GiB.
17
+ * Support on Deno v1 is unknown and it's EOL, so treating Deno before v2.0.0 as unsupported.
18
+ *
19
+ * No easy way to determining pointer width (64 bit or 32 bit) in JS,
20
+ * so call a function on Rust side to find out.
21
+ *
22
+ * @returns {boolean} - `true` if raw transfer is supported on this platform
23
+ */
24
+ function rawTransferSupported() {
25
+ if (rawTransferIsSupported === null) {
26
+ rawTransferIsSupported = rawTransferRuntimeSupported() && rawTransferSupportedBinding();
27
+ }
28
+ return rawTransferIsSupported;
29
+ }
30
+
31
+ // Checks copied from:
32
+ // https://github.com/unjs/std-env/blob/ab15595debec9e9115a9c1d31bc7597a8e71dbfd/src/runtimes.ts
33
+ // MIT license: https://github.com/unjs/std-env/blob/ab15595debec9e9115a9c1d31bc7597a8e71dbfd/LICENCE
34
+ function rawTransferRuntimeSupported() {
35
+ let global;
36
+ try {
37
+ global = globalThis;
38
+ } catch (e) {
39
+ return false;
40
+ }
41
+
42
+ const isBun = !!global.Bun || !!global.process?.versions?.bun;
43
+ if (isBun) return false;
44
+
45
+ const isDeno = !!global.Deno;
46
+ if (isDeno) {
47
+ const match = Deno.version?.deno?.match(/^(\d+)\./);
48
+ return !!match && match[1] * 1 >= 2;
49
+ }
50
+
51
+ const isNode = global.process?.release?.name === 'node';
52
+ if (!isNode) return false;
53
+
54
+ const match = process.version?.match(/^v(\d+)\./);
55
+ return !!match && match[1] * 1 >= 22;
56
+ }