@sirajchokshi/wa-sqlite 1.1.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -0
  3. package/dist/mc-wa-sqlite-async.mjs +2 -0
  4. package/dist/mc-wa-sqlite-async.wasm +0 -0
  5. package/dist/mc-wa-sqlite-jspi.mjs +2 -0
  6. package/dist/mc-wa-sqlite-jspi.wasm +0 -0
  7. package/dist/mc-wa-sqlite.mjs +2 -0
  8. package/dist/mc-wa-sqlite.wasm +0 -0
  9. package/dist/wa-sqlite-async.mjs +2 -0
  10. package/dist/wa-sqlite-async.wasm +0 -0
  11. package/dist/wa-sqlite-jspi.mjs +2 -0
  12. package/dist/wa-sqlite-jspi.wasm +0 -0
  13. package/dist/wa-sqlite.mjs +2 -0
  14. package/dist/wa-sqlite.wasm +0 -0
  15. package/package.json +48 -0
  16. package/src/FacadeVFS.js +720 -0
  17. package/src/VFS.js +222 -0
  18. package/src/WebLocksMixin.js +411 -0
  19. package/src/examples/AccessHandlePoolVFS.js +458 -0
  20. package/src/examples/IDBBatchAtomicVFS.js +827 -0
  21. package/src/examples/IDBMirrorVFS.js +889 -0
  22. package/src/examples/MemoryAsyncVFS.js +100 -0
  23. package/src/examples/MemoryVFS.js +176 -0
  24. package/src/examples/OPFSAdaptiveVFS.js +437 -0
  25. package/src/examples/OPFSAnyContextVFS.js +300 -0
  26. package/src/examples/OPFSCoopSyncVFS.js +597 -0
  27. package/src/examples/OPFSPermutedVFS.js +1217 -0
  28. package/src/examples/README.md +89 -0
  29. package/src/examples/tag.js +82 -0
  30. package/src/sqlite-api.js +912 -0
  31. package/src/sqlite-constants.js +275 -0
  32. package/src/types/globals.d.ts +60 -0
  33. package/src/types/index.d.ts +1343 -0
  34. package/src/types/tsconfig.json +6 -0
  35. package/test/AccessHandlePoolVFS.test.js +27 -0
  36. package/test/IDBBatchAtomicVFS.test.js +97 -0
  37. package/test/IDBMirrorVFS.test.js +27 -0
  38. package/test/MemoryAsyncVFS.test.js +27 -0
  39. package/test/MemoryVFS.test.js +27 -0
  40. package/test/OPFSAdaptiveVFS.test.js +27 -0
  41. package/test/OPFSAnyContextVFS.test.js +27 -0
  42. package/test/OPFSCoopSyncVFS.test.js +27 -0
  43. package/test/OPFSPermutedVFS.test.js +27 -0
  44. package/test/TestContext.js +96 -0
  45. package/test/WebLocksMixin.test.js +521 -0
  46. package/test/api.test.js +49 -0
  47. package/test/api_exec.js +89 -0
  48. package/test/api_misc.js +63 -0
  49. package/test/api_statements.js +447 -0
  50. package/test/callbacks.test.js +581 -0
  51. package/test/data/idbv5.json +1 -0
  52. package/test/sql.test.js +64 -0
  53. package/test/sql_0001.js +49 -0
  54. package/test/sql_0002.js +52 -0
  55. package/test/sql_0003.js +83 -0
  56. package/test/sql_0004.js +81 -0
  57. package/test/sql_0005.js +76 -0
  58. package/test/test-worker.js +204 -0
  59. package/test/vfs_xAccess.js +2 -0
  60. package/test/vfs_xClose.js +52 -0
  61. package/test/vfs_xOpen.js +91 -0
  62. package/test/vfs_xRead.js +38 -0
  63. package/test/vfs_xWrite.js +36 -0
@@ -0,0 +1,720 @@
1
+ // Copyright 2024 Roy T. Hashimoto. All Rights Reserved.
2
+ import * as VFS from './VFS.js';
3
+
4
+ const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
5
+
6
+ // Milliseconds since Julian epoch as a BigInt.
7
+ // https://github.com/sqlite/sqlite/blob/e57527c14f7b7cfa6e32eeab5c549d50c4fa3674/src/os_unix.c#L6872-L6882
8
+ const UNIX_EPOCH = 24405875n * 8640000n;
9
+
10
+ // Convenience base class for a JavaScript VFS.
11
+ // The raw xOpen, xRead, etc. function signatures receive only C primitives
12
+ // which aren't easy to work with. This class provides corresponding calls
13
+ // like jOpen, jRead, etc., which receive JavaScript-friendlier arguments
14
+ // such as string, Uint8Array, and DataView.
15
+ export class FacadeVFS extends VFS.Base {
16
+ /**
17
+ * @param {string} name
18
+ * @param {object} module
19
+ */
20
+ constructor(name, module) {
21
+ super(name, module);
22
+ }
23
+
24
+ /**
25
+ * Override to indicate which methods are asynchronous.
26
+ * @param {string} methodName
27
+ * @returns {boolean}
28
+ */
29
+ hasAsyncMethod(methodName) {
30
+ // The input argument is a string like "xOpen", so convert to "jOpen".
31
+ // Then check if the method exists and is async.
32
+ const jMethodName = `j${methodName.slice(1)}`;
33
+ return this[jMethodName] instanceof AsyncFunction;
34
+ }
35
+
36
+ /**
37
+ * Return the filename for a file id for use by mixins.
38
+ * @param {number} pFile
39
+ * @returns {string}
40
+ */
41
+ getFilename(pFile) {
42
+ throw new Error('unimplemented');
43
+ }
44
+
45
+ /**
46
+ * @param {string?} filename
47
+ * @param {number} pFile
48
+ * @param {number} flags
49
+ * @param {DataView} pOutFlags
50
+ * @returns {number|Promise<number>}
51
+ */
52
+ jOpen(filename, pFile, flags, pOutFlags) {
53
+ return VFS.SQLITE_CANTOPEN;
54
+ }
55
+
56
+ /**
57
+ * @param {string} filename
58
+ * @param {number} syncDir
59
+ * @returns {number|Promise<number>}
60
+ */
61
+ jDelete(filename, syncDir) {
62
+ return VFS.SQLITE_OK;
63
+ }
64
+
65
+ /**
66
+ * @param {string} filename
67
+ * @param {number} flags
68
+ * @param {DataView} pResOut
69
+ * @returns {number|Promise<number>}
70
+ */
71
+ jAccess(filename, flags, pResOut) {
72
+ return VFS.SQLITE_OK;
73
+ }
74
+
75
+ /**
76
+ * @param {string} filename
77
+ * @param {Uint8Array} zOut
78
+ * @returns {number|Promise<number>}
79
+ */
80
+ jFullPathname(filename, zOut) {
81
+ // Copy the filename to the output buffer.
82
+ const { read, written } = new TextEncoder().encodeInto(filename, zOut);
83
+ if (read < filename.length) return VFS.SQLITE_IOERR;
84
+ if (written >= zOut.length) return VFS.SQLITE_IOERR;
85
+ zOut[written] = 0;
86
+ return VFS.SQLITE_OK;
87
+ }
88
+
89
+ /**
90
+ * @param {Uint8Array} zBuf
91
+ * @returns {number|Promise<number>}
92
+ */
93
+ jGetLastError(zBuf) {
94
+ return VFS.SQLITE_OK;
95
+ }
96
+
97
+ /**
98
+ * @param {number} pFile
99
+ * @returns {number|Promise<number>}
100
+ */
101
+ jClose(pFile) {
102
+ return VFS.SQLITE_OK;
103
+ }
104
+
105
+ /**
106
+ * @param {number} pFile
107
+ * @param {Uint8Array} pData
108
+ * @param {number} iOffset
109
+ * @returns {number|Promise<number>}
110
+ */
111
+ jRead(pFile, pData, iOffset) {
112
+ pData.fill(0);
113
+ return VFS.SQLITE_IOERR_SHORT_READ;
114
+ }
115
+
116
+ /**
117
+ * @param {number} pFile
118
+ * @param {Uint8Array} pData
119
+ * @param {number} iOffset
120
+ * @returns {number|Promise<number>}
121
+ */
122
+ jWrite(pFile, pData, iOffset) {
123
+ return VFS.SQLITE_IOERR_WRITE;
124
+ }
125
+
126
+ /**
127
+ * @param {number} pFile
128
+ * @param {number} size
129
+ * @returns {number|Promise<number>}
130
+ */
131
+ jTruncate(pFile, size) {
132
+ return VFS.SQLITE_OK;
133
+ }
134
+
135
+ /**
136
+ * @param {number} pFile
137
+ * @param {number} flags
138
+ * @returns {number|Promise<number>}
139
+ */
140
+ jSync(pFile, flags) {
141
+ return VFS.SQLITE_OK;
142
+ }
143
+
144
+ /**
145
+ * @param {number} pFile
146
+ * @param {DataView} pSize
147
+ * @returns {number|Promise<number>}
148
+ */
149
+ jFileSize(pFile, pSize) {
150
+ return VFS.SQLITE_OK;
151
+ }
152
+
153
+ /**
154
+ * @param {number} pFile
155
+ * @param {number} lockType
156
+ * @returns {number|Promise<number>}
157
+ */
158
+ jLock(pFile, lockType) {
159
+ return VFS.SQLITE_OK;
160
+ }
161
+
162
+ /**
163
+ * @param {number} pFile
164
+ * @param {number} lockType
165
+ * @returns {number|Promise<number>}
166
+ */
167
+ jUnlock(pFile, lockType) {
168
+ return VFS.SQLITE_OK;
169
+ }
170
+
171
+ /**
172
+ * @param {number} pFile
173
+ * @param {DataView} pResOut
174
+ * @returns {number|Promise<number>}
175
+ */
176
+ jCheckReservedLock(pFile, pResOut) {
177
+ pResOut.setInt32(0, 0, true);
178
+ return VFS.SQLITE_OK;
179
+ }
180
+
181
+ /**
182
+ * @param {number} pFile
183
+ * @param {number} op
184
+ * @param {DataView} pArg
185
+ * @returns {number|Promise<number>}
186
+ */
187
+ jFileControl(pFile, op, pArg) {
188
+ return VFS.SQLITE_NOTFOUND;
189
+ }
190
+
191
+ /**
192
+ * @param {number} pFile
193
+ * @returns {number|Promise<number>}
194
+ */
195
+ jSectorSize(pFile) {
196
+ return super.xSectorSize(pFile);
197
+ }
198
+
199
+ /**
200
+ * @param {number} pFile
201
+ * @returns {number|Promise<number>}
202
+ */
203
+ jDeviceCharacteristics(pFile) {
204
+ return 0;
205
+ }
206
+
207
+ /**
208
+ * @param {number} pVfs
209
+ * @param {number} zName
210
+ * @param {number} pFile
211
+ * @param {number} flags
212
+ * @param {number} pOutFlags
213
+ * @returns {number|Promise<number>}
214
+ */
215
+ xOpen(pVfs, zName, pFile, flags, pOutFlags) {
216
+ const filename = this.#decodeFilename(zName, flags);
217
+ const pOutFlagsView = this.#makeTypedDataView('Int32', pOutFlags);
218
+ this['log']?.('jOpen', filename, pFile, '0x' + flags.toString(16));
219
+ return this.jOpen(filename, pFile, flags, pOutFlagsView);
220
+ }
221
+
222
+ /**
223
+ * @param {number} pVfs
224
+ * @param {number} nByte
225
+ * @param {number} pCharOut
226
+ * @returns {number|Promise<number>}
227
+ */
228
+ xRandomness(pVfs, nByte, pCharOut) {
229
+ const randomArray = new Uint8Array(nByte);
230
+ crypto.getRandomValues(randomArray);
231
+ // Copy randomArray to the WebAssembly memory
232
+ const buffer = pCharOut; // Pointer to memory in WebAssembly
233
+ this._module.HEAPU8.set(randomArray, buffer); // Copy randomArray into memory starting at buffer
234
+ return nByte;
235
+ }
236
+
237
+ /**
238
+ * Gets the current time as milliseconds since Unix epoch
239
+ * @param {number} pVfs pointer to the VFS
240
+ * @param {number} pTime pointer to write the time value
241
+ * @returns {number} SQLite error code
242
+ */
243
+ xCurrentTimeInt64(pVfs, pTime) {
244
+ // Create a DataView to write the current time
245
+ const timeView = this.#makeTypedDataView('BigInt64', pTime);
246
+
247
+ const currentTime = BigInt(Date.now());
248
+ // Convert the current time to milliseconds since Unix epoch
249
+ const value = UNIX_EPOCH + currentTime;
250
+
251
+ // Write the time value to the pointer location
252
+ timeView.setBigInt64(0, value, true);
253
+
254
+ return VFS.SQLITE_OK;
255
+ }
256
+
257
+ /**
258
+ * @param {number} pVfs
259
+ * @param {number} zName
260
+ * @param {number} syncDir
261
+ * @returns {number|Promise<number>}
262
+ */
263
+ xDelete(pVfs, zName, syncDir) {
264
+ const filename = this._module.UTF8ToString(zName);
265
+ this['log']?.('jDelete', filename, syncDir);
266
+ return this.jDelete(filename, syncDir);
267
+ }
268
+
269
+ /**
270
+ * @param {number} pVfs
271
+ * @param {number} zName
272
+ * @param {number} flags
273
+ * @param {number} pResOut
274
+ * @returns {number|Promise<number>}
275
+ */
276
+ xAccess(pVfs, zName, flags, pResOut) {
277
+ const filename = this._module.UTF8ToString(zName);
278
+ const pResOutView = this.#makeTypedDataView('Int32', pResOut);
279
+ this['log']?.('jAccess', filename, flags);
280
+ return this.jAccess(filename, flags, pResOutView);
281
+ }
282
+
283
+ /**
284
+ * @param {number} pVfs
285
+ * @param {number} zName
286
+ * @param {number} nOut
287
+ * @param {number} zOut
288
+ * @returns {number|Promise<number>}
289
+ */
290
+ xFullPathname(pVfs, zName, nOut, zOut) {
291
+ const filename = this._module.UTF8ToString(zName);
292
+ const zOutArray = this._module.HEAPU8.subarray(zOut, zOut + nOut);
293
+ this['log']?.('jFullPathname', filename, nOut);
294
+ return this.jFullPathname(filename, zOutArray);
295
+ }
296
+
297
+ /**
298
+ * @param {number} pVfs
299
+ * @param {number} nBuf
300
+ * @param {number} zBuf
301
+ * @returns {number|Promise<number>}
302
+ */
303
+ xGetLastError(pVfs, nBuf, zBuf) {
304
+ const zBufArray = this._module.HEAPU8.subarray(zBuf, zBuf + nBuf);
305
+ this['log']?.('jGetLastError', nBuf);
306
+ return this.jGetLastError(zBufArray);
307
+ }
308
+
309
+ /**
310
+ * @param {number} pFile
311
+ * @returns {number|Promise<number>}
312
+ */
313
+ xClose(pFile) {
314
+ this['log']?.('jClose', pFile);
315
+ return this.jClose(pFile);
316
+ }
317
+
318
+ /**
319
+ * @param {number} pFile
320
+ * @param {number} pData
321
+ * @param {number} iAmt
322
+ * @param {number} iOffsetLo
323
+ * @param {number} iOffsetHi
324
+ * @returns {number|Promise<number>}
325
+ */
326
+ xRead(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
327
+ const pDataArray = this.#makeDataArray(pData, iAmt);
328
+ const iOffset = delegalize(iOffsetLo, iOffsetHi);
329
+ this['log']?.('jRead', pFile, iAmt, iOffset);
330
+ return this.jRead(pFile, pDataArray, iOffset);
331
+ }
332
+
333
+ /**
334
+ * @param {number} pFile
335
+ * @param {number} pData
336
+ * @param {number} iAmt
337
+ * @param {number} iOffsetLo
338
+ * @param {number} iOffsetHi
339
+ * @returns {number|Promise<number>}
340
+ */
341
+ xWrite(pFile, pData, iAmt, iOffsetLo, iOffsetHi) {
342
+ const pDataArray = this.#makeDataArray(pData, iAmt);
343
+ const iOffset = delegalize(iOffsetLo, iOffsetHi);
344
+ this['log']?.('jWrite', pFile, pDataArray, iOffset);
345
+ return this.jWrite(pFile, pDataArray, iOffset);
346
+ }
347
+
348
+ /**
349
+ * @param {number} pFile
350
+ * @param {number} sizeLo
351
+ * @param {number} sizeHi
352
+ * @returns {number|Promise<number>}
353
+ */
354
+ xTruncate(pFile, sizeLo, sizeHi) {
355
+ const size = delegalize(sizeLo, sizeHi);
356
+ this['log']?.('jTruncate', pFile, size);
357
+ return this.jTruncate(pFile, size);
358
+ }
359
+
360
+ /**
361
+ * @param {number} pFile
362
+ * @param {number} flags
363
+ * @returns {number|Promise<number>}
364
+ */
365
+ xSync(pFile, flags) {
366
+ this['log']?.('jSync', pFile, flags);
367
+ return this.jSync(pFile, flags);
368
+ }
369
+
370
+ /**
371
+ *
372
+ * @param {number} pFile
373
+ * @param {number} pSize
374
+ * @returns {number|Promise<number>}
375
+ */
376
+ xFileSize(pFile, pSize) {
377
+ const pSizeView = this.#makeTypedDataView('BigInt64', pSize);
378
+ this['log']?.('jFileSize', pFile);
379
+ return this.jFileSize(pFile, pSizeView);
380
+ }
381
+
382
+ /**
383
+ * @param {number} pFile
384
+ * @param {number} lockType
385
+ * @returns {number|Promise<number>}
386
+ */
387
+ xLock(pFile, lockType) {
388
+ this['log']?.('jLock', pFile, lockType);
389
+ return this.jLock(pFile, lockType);
390
+ }
391
+
392
+ /**
393
+ * @param {number} pFile
394
+ * @param {number} lockType
395
+ * @returns {number|Promise<number>}
396
+ */
397
+ xUnlock(pFile, lockType) {
398
+ this['log']?.('jUnlock', pFile, lockType);
399
+ return this.jUnlock(pFile, lockType);
400
+ }
401
+
402
+ /**
403
+ * @param {number} pFile
404
+ * @param {number} pResOut
405
+ * @returns {number|Promise<number>}
406
+ */
407
+ xCheckReservedLock(pFile, pResOut) {
408
+ const pResOutView = this.#makeTypedDataView('Int32', pResOut);
409
+ this['log']?.('jCheckReservedLock', pFile);
410
+ return this.jCheckReservedLock(pFile, pResOutView);
411
+ }
412
+
413
+ /**
414
+ * @param {number} pFile
415
+ * @param {number} op
416
+ * @param {number} pArg
417
+ * @returns {number|Promise<number>}
418
+ */
419
+ xFileControl(pFile, op, pArg) {
420
+ const pArgView = new DataView(
421
+ this._module.HEAPU8.buffer,
422
+ this._module.HEAPU8.byteOffset + pArg);
423
+ this['log']?.('jFileControl', pFile, op, pArgView);
424
+ return this.jFileControl(pFile, op, pArgView);
425
+ }
426
+
427
+ /**
428
+ * @param {number} pFile
429
+ * @returns {number|Promise<number>}
430
+ */
431
+ xSectorSize(pFile) {
432
+ this['log']?.('jSectorSize', pFile);
433
+ return this.jSectorSize(pFile);
434
+ }
435
+
436
+ /**
437
+ * @param {number} pFile
438
+ * @returns {number|Promise<number>}
439
+ */
440
+ xDeviceCharacteristics(pFile) {
441
+ this['log']?.('jDeviceCharacteristics', pFile);
442
+ return this.jDeviceCharacteristics(pFile);
443
+ }
444
+
445
+ /**
446
+ * Wrapped DataView for pointer arguments.
447
+ * Pointers to a single value are passed using a DataView-like class.
448
+ * This wrapper class prevents use of incorrect type or endianness, and
449
+ * reacquires the underlying buffer when the WebAssembly memory is resized.
450
+ * @param {'Int32'|'BigInt64'} type
451
+ * @param {number} byteOffset
452
+ * @returns {DataView}
453
+ */
454
+ #makeTypedDataView(type, byteOffset) {
455
+ // @ts-ignore
456
+ return new DataViewProxy(this._module, byteOffset, type);
457
+ }
458
+
459
+ /**
460
+ * Wrapped Uint8Array for buffer arguments.
461
+ * Memory blocks are passed as a Uint8Array-like class. This wrapper
462
+ * class reacquires the underlying buffer when the WebAssembly memory
463
+ * is resized.
464
+ * @param {number} byteOffset
465
+ * @param {number} byteLength
466
+ * @returns {Uint8Array}
467
+ */
468
+ #makeDataArray(byteOffset, byteLength) {
469
+ // @ts-ignore
470
+ return new Uint8ArrayProxy(this._module, byteOffset, byteLength);
471
+ }
472
+
473
+ #decodeFilename(zName, flags) {
474
+ if (flags & VFS.SQLITE_OPEN_URI) {
475
+ // The first null-terminated string is the URI path. Subsequent
476
+ // strings are query parameter keys and values.
477
+ // https://www.sqlite.org/c3ref/open.html#urifilenamesinsqlite3open
478
+ let pName = zName;
479
+ let state = 1;
480
+ const charCodes = [];
481
+ while (state) {
482
+ const charCode = this._module.HEAPU8[pName++];
483
+ if (charCode) {
484
+ charCodes.push(charCode);
485
+ } else {
486
+ if (!this._module.HEAPU8[pName]) state = null;
487
+ switch (state) {
488
+ case 1: // path
489
+ charCodes.push('?'.charCodeAt(0));
490
+ state = 2;
491
+ break;
492
+ case 2: // key
493
+ charCodes.push('='.charCodeAt(0));
494
+ state = 3;
495
+ break;
496
+ case 3: // value
497
+ charCodes.push('&'.charCodeAt(0));
498
+ state = 2;
499
+ break;
500
+ }
501
+ }
502
+ }
503
+ return new TextDecoder().decode(new Uint8Array(charCodes));
504
+ }
505
+ return zName ? this._module.UTF8ToString(zName) : null;
506
+ }
507
+ }
508
+
509
+ // Emscripten "legalizes" 64-bit integer arguments by passing them as
510
+ // two 32-bit signed integers.
511
+ function delegalize(lo32, hi32) {
512
+ return (hi32 * 0x100000000) + lo32 + (lo32 < 0 ? 2**32 : 0);
513
+ }
514
+
515
+ // This class provides a Uint8Array-like interface for a WebAssembly memory
516
+ // buffer. It is used to access memory blocks passed as arguments to
517
+ // xRead, xWrite, etc. The class reacquires the underlying buffer when the
518
+ // WebAssembly memory is resized, which can happen when the memory is
519
+ // detached and resized by the WebAssembly module.
520
+ //
521
+ // Note that although this class implements the same methods as Uint8Array,
522
+ // it is not a real Uint8Array and passing it to functions that expect
523
+ // a Uint8Array may not work. Use subarray() to get a real Uint8Array
524
+ // if needed.
525
+ class Uint8ArrayProxy {
526
+ #module;
527
+
528
+ #_array = new Uint8Array()
529
+ get #array() {
530
+ if (this.#_array.buffer.byteLength === 0) {
531
+ // WebAssembly memory resize detached the buffer so re-create the
532
+ // array with the new buffer.
533
+ this.#_array = this.#module.HEAPU8.subarray(
534
+ this.byteOffset,
535
+ this.byteOffset + this.byteLength);
536
+ }
537
+ return this.#_array;
538
+ }
539
+
540
+ /**
541
+ * @param {*} module
542
+ * @param {number} byteOffset
543
+ * @param {number} byteLength
544
+ */
545
+ constructor(module, byteOffset, byteLength) {
546
+ this.#module = module;
547
+ this.byteOffset = byteOffset;
548
+ this.length = this.byteLength = byteLength;
549
+ }
550
+
551
+ get buffer() {
552
+ return this.#array.buffer;
553
+ }
554
+
555
+ at(index) {
556
+ return this.#array.at(index);
557
+ }
558
+ copyWithin(target, start, end) {
559
+ this.#array.copyWithin(target, start, end);
560
+ }
561
+ entries() {
562
+ return this.#array.entries();
563
+ }
564
+ every(predicate) {
565
+ return this.#array.every(predicate);
566
+ }
567
+ fill(value, start, end) {
568
+ this.#array.fill(value, start, end);
569
+ }
570
+ filter(predicate) {
571
+ return this.#array.filter(predicate);
572
+ }
573
+ find(predicate) {
574
+ return this.#array.find(predicate);
575
+ }
576
+ findIndex(predicate) {
577
+ return this.#array.findIndex(predicate);
578
+ }
579
+ findLast(predicate) {
580
+ return this.#array.findLast(predicate);
581
+ }
582
+ findLastIndex(predicate) {
583
+ return this.#array.findLastIndex(predicate);
584
+ }
585
+ forEach(callback) {
586
+ this.#array.forEach(callback);
587
+ }
588
+ includes(value, start) {
589
+ return this.#array.includes(value, start);
590
+ }
591
+ indexOf(value, start) {
592
+ return this.#array.indexOf(value, start);
593
+ }
594
+ join(separator) {
595
+ return this.#array.join(separator);
596
+ }
597
+ keys() {
598
+ return this.#array.keys();
599
+ }
600
+ lastIndexOf(value, start) {
601
+ return this.#array.lastIndexOf(value, start);
602
+ }
603
+ map(callback) {
604
+ return this.#array.map(callback);
605
+ }
606
+ reduce(callback, initialValue) {
607
+ return this.#array.reduce(callback, initialValue);
608
+ }
609
+ reduceRight(callback, initialValue) {
610
+ return this.#array.reduceRight(callback, initialValue);
611
+ }
612
+ reverse() {
613
+ this.#array.reverse();
614
+ }
615
+ set(array, offset) {
616
+ this.#array.set(array, offset);
617
+ }
618
+ slice(start, end) {
619
+ return this.#array.slice(start, end);
620
+ }
621
+ some(predicate) {
622
+ return this.#array.some(predicate);
623
+ }
624
+ sort(compareFn) {
625
+ this.#array.sort(compareFn);
626
+ }
627
+ subarray(begin, end) {
628
+ return this.#array.subarray(begin, end);
629
+ }
630
+ toLocaleString(locales, options) {
631
+ // @ts-ignore
632
+ return this.#array.toLocaleString(locales, options);
633
+ }
634
+ toReversed() {
635
+ return this.#array.toReversed();
636
+ }
637
+ toSorted(compareFn) {
638
+ return this.#array.toSorted(compareFn);
639
+ }
640
+ toString() {
641
+ return this.#array.toString();
642
+ }
643
+ values() {
644
+ return this.#array.values();
645
+ }
646
+ with(index, value) {
647
+ return this.#array.with(index, value);
648
+ }
649
+ [Symbol.iterator]() {
650
+ return this.#array[Symbol.iterator]();
651
+ }
652
+ }
653
+
654
+ // This class provides a DataView-like interface for a WebAssembly memory
655
+ // buffer, restricted to either Int32 or BigInt64 types. It also reacquires
656
+ // the underlying buffer when the WebAssembly memory is resized, which can
657
+ // happen when the memory is detached and resized by the WebAssembly module.
658
+ class DataViewProxy {
659
+ #module;
660
+ #type;
661
+
662
+ #_view = new DataView(new ArrayBuffer(0));
663
+ get #view() {
664
+ if (this.#_view.buffer.byteLength === 0) {
665
+ // WebAssembly memory resize detached the buffer so re-create the
666
+ // view with the new buffer.
667
+ this.#_view = new DataView(
668
+ this.#module.HEAPU8.buffer,
669
+ this.#module.HEAPU8.byteOffset + this.byteOffset);
670
+ }
671
+ return this.#_view;
672
+ }
673
+
674
+ /**
675
+ * @param {*} module
676
+ * @param {number} byteOffset
677
+ * @param {'Int32'|'BigInt64'} type
678
+ */
679
+ constructor(module, byteOffset, type) {
680
+ this.#module = module;
681
+ this.byteOffset = byteOffset;
682
+ this.#type = type;
683
+ }
684
+
685
+ get buffer() {
686
+ return this.#view.buffer;
687
+ }
688
+ get byteLength() {
689
+ return this.#type === 'Int32' ? 4 : 8;
690
+ }
691
+
692
+ getInt32(byteOffset, littleEndian) {
693
+ if (this.#type !== 'Int32') {
694
+ throw new Error('invalid type');
695
+ }
696
+ if (!littleEndian) throw new Error('must be little endian');
697
+ return this.#view.getInt32(byteOffset, littleEndian);
698
+ }
699
+ setInt32(byteOffset, value, littleEndian) {
700
+ if (this.#type !== 'Int32') {
701
+ throw new Error('invalid type');
702
+ }
703
+ if (!littleEndian) throw new Error('must be little endian');
704
+ this.#view.setInt32(byteOffset, value, littleEndian);
705
+ }
706
+ getBigInt64(byteOffset, littleEndian) {
707
+ if (this.#type !== 'BigInt64') {
708
+ throw new Error('invalid type');
709
+ }
710
+ if (!littleEndian) throw new Error('must be little endian');
711
+ return this.#view.getBigInt64(byteOffset, littleEndian);
712
+ }
713
+ setBigInt64(byteOffset, value, littleEndian) {
714
+ if (this.#type !== 'BigInt64') {
715
+ throw new Error('invalid type');
716
+ }
717
+ if (!littleEndian) throw new Error('must be little endian');
718
+ this.#view.setBigInt64(byteOffset, value, littleEndian);
719
+ }
720
+ }