funicular 0.3.0 → 0.4.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/demo/test_chartjs.html +9 -9
  4. data/demo/test_component.html +8 -8
  5. data/demo/test_error_boundary.html +44 -41
  6. data/demo/test_router.html +48 -48
  7. data/demo/tic-tac-toe.html +25 -25
  8. data/docs/architecture.md +46 -9
  9. data/lib/funicular/ssr/runtime.rb +1 -0
  10. data/lib/funicular/vendor/mrbc/VERSION +1 -1
  11. data/lib/funicular/vendor/mrbc/mrbc.js +613 -486
  12. data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
  13. data/lib/funicular/vendor/picoruby/VERSION +1 -1
  14. data/lib/funicular/vendor/picoruby/debug/picoruby.js +669 -449
  15. data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
  16. data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
  17. data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
  18. data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
  19. data/lib/funicular/vendor/picoruby-test-node/picoruby.js +921 -629
  20. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
  21. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +1 -1
  22. data/lib/funicular/version.rb +1 -1
  23. data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +37 -38
  24. data/minitest/dsl_test.rb +237 -0
  25. data/minitest/fixtures/funicular_app/components/greeting_component.rb +5 -5
  26. data/minitest/form_for_test.rb +2 -2
  27. data/minitest/hydration_test.rb +2 -2
  28. data/minitest/sig_tags_test.rb +30 -0
  29. data/minitest/view_context_test.rb +15 -15
  30. data/mrblib/0_tags.rb +62 -0
  31. data/mrblib/component.rb +113 -23
  32. data/mrblib/error_boundary.rb +25 -19
  33. data/mrblib/form_builder.rb +10 -10
  34. data/mrblib/funicular.rb +1 -1
  35. data/mrblib/styles.rb +102 -12
  36. data/mrblib/view_context.rb +3 -32
  37. data/sig/component.rbs +18 -4
  38. data/sig/error_boundary.rbs +4 -4
  39. data/sig/styles.rbs +18 -5
  40. data/sig/tags.rbs +54 -0
  41. data/sig/view_context.rbs +47 -34
  42. metadata +5 -1
@@ -4,8 +4,7 @@
4
4
  // When targeting node and ES6 we use `await import ..` in the generated code
5
5
  // so the outer function needs to be marked as async.
6
6
  async function Module(moduleArg = {}) {
7
- var moduleRtn;
8
-
7
+ var Module = moduleArg;
9
8
  // include: shell.js
10
9
  // include: minimum_runtime_check.js
11
10
  (function() {
@@ -24,9 +23,14 @@ async function Module(moduleArg = {}) {
24
23
 
25
24
  // Note: We use a typeof check here instead of optional chaining using
26
25
  // globalThis because older browsers might not have globalThis defined.
27
- var currentNodeVersion = typeof process !== 'undefined' && process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
28
- if (currentNodeVersion < 160000) {
29
- throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(160000) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
26
+
27
+ // We skip the node version checking when running on Bun/Deno since the node
28
+ // version they report doesn't seem to be useful.
29
+ if (typeof process !== 'undefined' && !process.versions?.bun && typeof Deno == "undefined") {
30
+ var currentNodeVersion = process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
31
+ if (currentNodeVersion < 180300) {
32
+ throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(180300) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
33
+ }
30
34
  }
31
35
 
32
36
  var userAgent = typeof navigator !== 'undefined' && navigator.userAgent;
@@ -73,7 +77,6 @@ async function Module(moduleArg = {}) {
73
77
  // after the generated code, you will need to define var Module = {};
74
78
  // before the code. Then that object will be used in the code, and you
75
79
  // can continue to use Module afterwards as well.
76
- var Module = moduleArg;
77
80
 
78
81
  // Determine the runtime environment we are in. You can customize this by
79
82
  // setting the ENVIRONMENT setting at compile time (see settings.js).
@@ -99,7 +102,7 @@ if (ENVIRONMENT_IS_NODE) {
99
102
  // refer to Module (if they choose; they can also define Module)
100
103
 
101
104
 
102
- var arguments_ = [];
105
+ var programArgs = [];
103
106
  var thisProgram = './this.program';
104
107
  var quit_ = (status, toThrow) => {
105
108
  throw toThrow;
@@ -152,7 +155,7 @@ readAsync = async (filename, binary = true) => {
152
155
  thisProgram = process.argv[1].replace(/\\/g, '/');
153
156
  }
154
157
 
155
- arguments_ = process.argv.slice(2);
158
+ programArgs = process.argv.slice(2);
156
159
 
157
160
  quit_ = (status, toThrow) => {
158
161
  process.exitCode = status;
@@ -185,11 +188,11 @@ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
185
188
  // perform assertions in shell.js after we set up out() and err(), as otherwise
186
189
  // if an assertion fails it cannot print the message
187
190
 
188
- assert(!ENVIRONMENT_IS_WEB, 'web environment detected but not enabled at build time. Add `web` to `-sENVIRONMENT` to enable.');
191
+ assert(!ENVIRONMENT_IS_WEB, 'web environment detected but not enabled at build time (add `web` to `-sENVIRONMENT` to enable)');
189
192
 
190
- assert(!ENVIRONMENT_IS_WORKER, 'worker environment detected but not enabled at build time. Add `worker` to `-sENVIRONMENT` to enable.');
193
+ assert(!ENVIRONMENT_IS_WORKER, 'worker environment detected but not enabled at build time (add `worker` to `-sENVIRONMENT` to enable)');
191
194
 
192
- assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
195
+ assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time (add `shell` to `-sENVIRONMENT` to enable)');
193
196
 
194
197
  // end include: shell.js
195
198
 
@@ -246,45 +249,12 @@ function assert(condition, text) {
246
249
  var isFileURI = (filename) => filename.startsWith('file://');
247
250
 
248
251
  // include: runtime_common.js
249
- // include: runtime_stack_check.js
250
- // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
251
- function writeStackCookie() {
252
- var max = _emscripten_stack_get_end();
253
- assert((max & 3) == 0);
254
- // If the stack ends at address zero we write our cookies 4 bytes into the
255
- // stack. This prevents interference with SAFE_HEAP and ASAN which also
256
- // monitor writes to address zero.
257
- if (max == 0) {
258
- max += 4;
259
- }
260
- // The stack grow downwards towards _emscripten_stack_get_end.
261
- // We write cookies to the final two words in the stack and detect if they are
262
- // ever overwritten.
263
- HEAPU32[((max)>>2)] = 0x02135467;
264
- HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
265
- // Also test the global address 0 for integrity.
266
- HEAPU32[((0)>>2)] = 1668509029;
267
- }
268
-
269
- function checkStackCookie() {
270
- if (ABORT) return;
271
- var max = _emscripten_stack_get_end();
272
- // See writeStackCookie().
273
- if (max == 0) {
274
- max += 4;
275
- }
276
- var cookie1 = HEAPU32[((max)>>2)];
277
- var cookie2 = HEAPU32[(((max)+(4))>>2)];
278
- if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
279
- abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
280
- }
281
- // Also test the global address 0 for integrity.
282
- if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
283
- abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
284
- }
285
- }
286
- // end include: runtime_stack_check.js
287
252
  // include: runtime_exceptions.js
253
+ // Base Emscripten EH error class
254
+ class EmscriptenEH {}
255
+
256
+ class EmscriptenSjLj extends EmscriptenEH {}
257
+
288
258
  // end include: runtime_exceptions.js
289
259
  // include: runtime_debug.js
290
260
  var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times
@@ -306,15 +276,31 @@ function dbg(...args) {
306
276
  })();
307
277
 
308
278
  function consumedModuleProp(prop) {
309
- if (!Object.getOwnPropertyDescriptor(Module, prop)) {
310
- Object.defineProperty(Module, prop, {
311
- configurable: true,
312
- set() {
313
- abort(`Attempt to set \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`);
314
-
279
+ var value = Module[prop];
280
+ var msg = `Attempt to modify \`Module.${prop}\` after it has already been processed. This can happen, for example, when code is injected via '--post-js' rather than '--pre-js'`;
281
+ if (Array.isArray(value)) {
282
+ value = new Proxy(value, {
283
+ set(target, key, val) {
284
+ abort(msg);
285
+ return false;
286
+ },
287
+ defineProperty(target, key, descriptor) {
288
+ abort(msg);
289
+ return false;
290
+ },
291
+ deleteProperty(target, key) {
292
+ abort(msg);
293
+ return false;
315
294
  }
316
295
  });
317
296
  }
297
+ Object.defineProperty(Module, prop, {
298
+ configurable: true,
299
+ get() { return value; },
300
+ set() {
301
+ abort(msg);
302
+ }
303
+ });
318
304
  }
319
305
 
320
306
  function makeInvalidEarlyAccess(name) {
@@ -365,41 +351,68 @@ function unexportedRuntimeSymbol(sym) {
365
351
  }
366
352
 
367
353
  // end include: runtime_debug.js
368
- var readyPromiseResolve, readyPromiseReject;
354
+ // include: runtime_stack_check.js
355
+ const stackCookie1 = 0x02135467;
356
+ const stackCookie2 = 0x89BACDFE;
369
357
 
358
+ // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
359
+ function writeStackCookie() {
360
+ var max = _emscripten_stack_get_end();
361
+ assert((max & 3) == 0);
362
+ // If the stack ends at address zero we write our cookies 4 bytes into the
363
+ // stack. This prevents interference with SAFE_HEAP and ASAN which also
364
+ // monitor writes to address zero.
365
+ if (max == 0) {
366
+ max += 4;
367
+ }
368
+ // The stack grow downwards towards _emscripten_stack_get_end.
369
+ // We write cookies to the final two words in the stack and detect if they are
370
+ // ever overwritten.
371
+ HEAPU32[((max)>>2)] = stackCookie1;
372
+ HEAPU32[(((max)+(4))>>2)] = stackCookie2;
373
+ // Also test the global address 0 for integrity.
374
+ HEAPU32[((0)>>2)] = 1668509029;
375
+ }
376
+
377
+ function u32ToHexString(num) {
378
+ return '0x' + (num >>> 0).toString(16).padStart(8, '0');
379
+ }
380
+
381
+ function checkStackCookie() {
382
+ if (ABORT) return;
383
+ var max = _emscripten_stack_get_end();
384
+ // See writeStackCookie().
385
+ if (max == 0) {
386
+ max += 4;
387
+ }
388
+ var val1 = HEAPU32[((max)>>2)];
389
+ var val2 = HEAPU32[(((max)+(4))>>2)];
390
+ if (val1 != stackCookie1 || val2 != stackCookie2) {
391
+ abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords ${u32ToHexString(stackCookie2)} and ${u32ToHexString(stackCookie1)}, but received ${u32ToHexString(val2)} ${u32ToHexString(val1)}`);
392
+ }
393
+ // Also test the global address 0 for integrity.
394
+ if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
395
+ abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
396
+ }
397
+ }
398
+ // end include: runtime_stack_check.js
370
399
  // Memory management
371
- var
372
- /** @type {!Int8Array} */
373
- HEAP8,
374
- /** @type {!Uint8Array} */
375
- HEAPU8,
376
- /** @type {!Int16Array} */
377
- HEAP16,
378
- /** @type {!Uint16Array} */
379
- HEAPU16,
380
- /** @type {!Int32Array} */
381
- HEAP32,
382
- /** @type {!Uint32Array} */
383
- HEAPU32,
384
- /** @type {!Float32Array} */
385
- HEAPF32,
386
- /** @type {!Float64Array} */
387
- HEAPF64;
388
-
389
- // BigInt64Array type is not correctly defined in closure
390
- var
391
- /** not-@type {!BigInt64Array} */
392
- HEAP64,
393
- /* BigUint64Array type is not correctly defined in closure
394
- /** not-@type {!BigUint64Array} */
395
- HEAPU64;
396
400
 
397
401
  var runtimeInitialized = false;
398
402
 
399
403
 
400
404
 
405
+ // When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm
406
+ // memory to ArrayBuffer requires some additional logic.
407
+ function getMemoryBuffer() {
408
+ return wasmMemory.buffer;
409
+ }
410
+
401
411
  function updateMemoryViews() {
402
- var b = wasmMemory.buffer;
412
+ // If we already have a heap that is resizeable/growable buffer we don't
413
+ // need to do anything in updateMemoryViews.
414
+ if (HEAP8?.buffer?.resizable) return;
415
+ var b = getMemoryBuffer();
403
416
  HEAP8 = new Int8Array(b);
404
417
  HEAP16 = new Int16Array(b);
405
418
  Module['HEAPU8'] = HEAPU8 = new Uint8Array(b);
@@ -419,11 +432,10 @@ assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.
419
432
  'JS engine does not provide full typed array support');
420
433
 
421
434
  function preRun() {
422
- if (Module['preRun']) {
423
- if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
424
- while (Module['preRun'].length) {
425
- addOnPreRun(Module['preRun'].shift());
426
- }
435
+ var preRun = Module['preRun'];
436
+ if (preRun) {
437
+ if (typeof preRun == 'function') preRun = [preRun];
438
+ onPreRuns.push(...preRun);
427
439
  }
428
440
  consumedModuleProp('preRun');
429
441
  // Begin ATPRERUNS hooks
@@ -448,17 +460,17 @@ PIPEFS.root = FS.mount(PIPEFS, {}, null);
448
460
  // Begin ATPOSTCTORS hooks
449
461
  FS.ignorePermissions = false;
450
462
  // End ATPOSTCTORS hooks
463
+
464
+ checkStackCookie();
451
465
  }
452
466
 
453
467
  function postRun() {
454
468
  checkStackCookie();
455
- // PThreads reuse the runtime from the main thread.
456
469
 
457
- if (Module['postRun']) {
458
- if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
459
- while (Module['postRun'].length) {
460
- addOnPostRun(Module['postRun'].shift());
461
- }
470
+ var postRun = Module['postRun'];
471
+ if (postRun) {
472
+ if (typeof postRun == 'function') postRun = [postRun];
473
+ onPostRuns.push(...postRun);
462
474
  }
463
475
  consumedModuleProp('postRun');
464
476
 
@@ -467,11 +479,13 @@ function postRun() {
467
479
  // End ATPOSTRUNS hooks
468
480
  }
469
481
 
470
- /** @param {string|number=} what */
482
+ /**
483
+ * @param {string|number=} what
484
+ */
471
485
  function abort(what) {
472
486
  Module['onAbort']?.(what);
473
487
 
474
- what = 'Aborted(' + what + ')';
488
+ what = `Aborted(${what})`;
475
489
  // TODO(sbc): Should we remove printing and leave it up to whoever
476
490
  // catches the exception?
477
491
  err(what);
@@ -494,21 +508,19 @@ function abort(what) {
494
508
  /** @suppress {checkTypes} */
495
509
  var e = new WebAssembly.RuntimeError(what);
496
510
 
497
- readyPromiseReject?.(e);
498
511
  // Throw the error whether or not MODULARIZE is set because abort is used
499
512
  // in code paths apart from instantiation where an exception is expected
500
513
  // to be thrown when abort is called.
501
514
  throw e;
502
515
  }
503
516
 
504
- function createExportWrapper(name, nargs) {
517
+ function createExportWrapper(name, func, nargs) {
518
+ assert(func);
505
519
  return (...args) => {
506
520
  assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
507
- var f = wasmExports[name];
508
- assert(f, `exported native function \`${name}\` not found`);
509
521
  // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
510
522
  assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
511
- return f(...args);
523
+ return func(...args);
512
524
  };
513
525
  }
514
526
 
@@ -526,9 +538,6 @@ function findWasmBinary() {
526
538
  }
527
539
 
528
540
  function getBinarySync(file) {
529
- if (file == wasmBinaryFile && wasmBinary) {
530
- return new Uint8Array(wasmBinary);
531
- }
532
541
  if (readBinary) {
533
542
  return readBinary(file);
534
543
  }
@@ -609,8 +618,7 @@ async function createWasm() {
609
618
  // Load the wasm module and create an instance of using native support in the JS engine.
610
619
  // handle a generated wasm instance, receiving its exports and
611
620
  // performing other necessary setup
612
- /** @param {WebAssembly.Module=} module*/
613
- function receiveInstance(instance, module) {
621
+ function receiveInstance(instance) {
614
622
  wasmExports = instance.exports;
615
623
 
616
624
  assignWasmExports(wasmExports);
@@ -643,15 +651,14 @@ async function createWasm() {
643
651
  // performing.
644
652
  // Also pthreads and wasm workers initialize the wasm instance through this
645
653
  // path.
646
- if (Module['instantiateWasm']) {
647
- return new Promise((resolve, reject) => {
654
+ var instantiateWasm = Module['instantiateWasm'];
655
+ if (instantiateWasm) {
656
+ return new Promise((resolve) => {
648
657
  try {
649
- Module['instantiateWasm'](info, (inst, mod) => {
650
- resolve(receiveInstance(inst, mod));
651
- });
658
+ instantiateWasm(info, (inst) => resolve(receiveInstance(inst)));
652
659
  } catch(e) {
653
660
  err(`Module.instantiateWasm callback failed with error: ${e}`);
654
- reject(e);
661
+ throw e;
655
662
  }
656
663
  });
657
664
  }
@@ -675,6 +682,36 @@ async function createWasm() {
675
682
  }
676
683
  }
677
684
 
685
+ /** @type {!Int16Array} */
686
+ var HEAP16;
687
+
688
+ /** @type {!Int32Array} */
689
+ var HEAP32;
690
+
691
+ /** not-@type {!BigInt64Array} */
692
+ var HEAP64;
693
+
694
+ /** @type {!Int8Array} */
695
+ var HEAP8;
696
+
697
+ /** @type {!Float32Array} */
698
+ var HEAPF32;
699
+
700
+ /** @type {!Float64Array} */
701
+ var HEAPF64;
702
+
703
+ /** @type {!Uint16Array} */
704
+ var HEAPU16;
705
+
706
+ /** @type {!Uint32Array} */
707
+ var HEAPU32;
708
+
709
+ /** not-@type {!BigUint64Array} */
710
+ var HEAPU64;
711
+
712
+ /** @type {!Uint8Array} */
713
+ var HEAPU8;
714
+
678
715
  var callRuntimeCallbacks = (callbacks) => {
679
716
  while (callbacks.length > 0) {
680
717
  // Pass the module as the first argument.
@@ -710,12 +747,12 @@ async function createWasm() {
710
747
 
711
748
  var noExitRuntime = true;
712
749
 
713
- var ptrToString = (ptr) => {
750
+ function ptrToString(ptr) {
714
751
  assert(typeof ptr === 'number', `ptrToString expects a number, got ${typeof ptr}`);
715
752
  // Convert to 32-bit unsigned value
716
753
  ptr >>>= 0;
717
754
  return '0x' + ptr.toString(16).padStart(8, '0');
718
- };
755
+ }
719
756
 
720
757
 
721
758
  /**
@@ -753,59 +790,16 @@ async function createWasm() {
753
790
 
754
791
 
755
792
 
756
- var wasmTableMirror = [];
757
-
758
-
759
- var getWasmTableEntry = (funcPtr) => {
760
- var func = wasmTableMirror[funcPtr];
761
- if (!func) {
762
- /** @suppress {checkTypes} */
763
- wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
764
- }
765
- /** @suppress {checkTypes} */
766
- assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
767
- return func;
768
- };
769
- var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
770
-
771
- var nodePath = require('node:path');
772
- var PATH = {
773
- isAbs: nodePath.isAbsolute,
774
- normalize: nodePath.normalize,
775
- dirname: nodePath.dirname,
776
- basename: nodePath.basename,
777
- join: nodePath.join,
778
- join2: nodePath.join,
779
- };
780
-
781
- var initRandomFill = () => {
782
- // This block is not needed on v19+ since crypto.getRandomValues is builtin
783
- if (ENVIRONMENT_IS_NODE) {
784
- var nodeCrypto = require('node:crypto');
785
- return (view) => nodeCrypto.randomFillSync(view);
786
- }
787
-
788
- return (view) => crypto.getRandomValues(view);
789
- };
790
- var randomFill = (view) => {
791
- // Lazily init on the first invocation.
792
- (randomFill = initRandomFill())(view);
793
- };
794
-
795
-
796
-
797
- /** @type{{resolve: function(...*)}} */
798
- var PATH_FS = {
799
- resolve:(...paths) => {
800
- paths.unshift(FS.cwd());
801
- return nodePath.posix.resolve(...paths);
802
- },
803
- relative:(from, to) => nodePath.posix.relative(from || FS.cwd(), to || FS.cwd()),
804
- };
805
-
806
-
807
793
  var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
808
794
 
795
+
796
+ /**
797
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
798
+ * @param {number} idx
799
+ * @param {number=} maxBytesToRead
800
+ * @param {boolean=} ignoreNul
801
+ * @return {number}
802
+ */
809
803
  var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
810
804
  var maxIdx = idx + maxBytesToRead;
811
805
  if (ignoreNul) return maxIdx;
@@ -850,7 +844,7 @@ async function createWasm() {
850
844
  if ((u0 & 0xF0) == 0xE0) {
851
845
  u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
852
846
  } else {
853
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte ' + ptrToString(u0) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
847
+ if ((u0 & 0xF8) != 0xF0) warnOnce(`Invalid UTF-8 leading byte ${ptrToString(u0)} encountered when deserializing a UTF-8 string in wasm memory to a JS string!`);
854
848
  u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
855
849
  }
856
850
 
@@ -864,6 +858,75 @@ async function createWasm() {
864
858
  return str;
865
859
  };
866
860
 
861
+ /**
862
+ * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
863
+ * emscripten HEAP, returns a copy of that string as a Javascript String object.
864
+ *
865
+ * @param {number} ptr
866
+ * @param {number=} maxBytesToRead - An optional length that specifies the
867
+ * maximum number of bytes to read. You can omit this parameter to scan the
868
+ * string until the first 0 byte. If maxBytesToRead is passed, and the string
869
+ * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
870
+ * string will cut short at that byte index.
871
+ * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
872
+ * @return {string}
873
+ */
874
+ var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
875
+ assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`);
876
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : '';
877
+ };
878
+ var ___assert_fail = (condition, filename, line, func) =>
879
+ abort(`Assertion failed: ${UTF8ToString(condition)}, at: ` + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
880
+
881
+ var wasmTableMirror = [];
882
+
883
+
884
+ var getWasmTableEntry = (funcPtr) => {
885
+ var func = wasmTableMirror[funcPtr];
886
+ if (!func) {
887
+ /** @suppress {checkTypes} */
888
+ wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
889
+ }
890
+ /** @suppress {checkTypes} */
891
+ assert(wasmTable.get(funcPtr) == func, 'table mirror is out of date');
892
+ return func;
893
+ };
894
+ var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
895
+
896
+ var nodePath = require('node:path');
897
+ var PATH = {
898
+ isAbs: nodePath.isAbsolute,
899
+ normalize: nodePath.normalize,
900
+ dirname: nodePath.dirname,
901
+ basename: nodePath.basename,
902
+ join: nodePath.join,
903
+ join2: nodePath.join,
904
+ };
905
+
906
+ var initRandomFill = () => {
907
+ // This block is not needed on v19+ since crypto.getRandomValues is builtin
908
+ if (ENVIRONMENT_IS_NODE) {
909
+ var nodeCrypto = require('node:crypto');
910
+ return (view) => (nodeCrypto.randomFillSync(view), 0);
911
+ }
912
+
913
+ return (view) => (crypto.getRandomValues(view), 0);
914
+ };
915
+ var randomFill = (view) => (randomFill = initRandomFill())(view);
916
+
917
+
918
+
919
+ /** @type{{resolve: function(...*)}} */
920
+ var PATH_FS = {
921
+ resolve:(...paths) => {
922
+ paths.unshift(FS.cwd());
923
+ return nodePath.posix.resolve(...paths);
924
+ },
925
+ relative:(from, to) => nodePath.posix.relative(from || FS.cwd(), to || FS.cwd()),
926
+ };
927
+
928
+
929
+
867
930
  var FS_stdin_getChar_buffer = [];
868
931
 
869
932
  var lengthBytesUTF8 = (str) => {
@@ -915,7 +978,7 @@ async function createWasm() {
915
978
  heap[outIdx++] = 0x80 | (u & 63);
916
979
  } else {
917
980
  if (outIdx + 3 >= endIdx) break;
918
- if (u > 0x10FFFF) warnOnce('Invalid Unicode code point ' + ptrToString(u) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
981
+ if (u > 0x10FFFF) warnOnce(`Invalid Unicode code point ${ptrToString(u)} encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).`);
919
982
  heap[outIdx++] = 0xF0 | (u >> 18);
920
983
  heap[outIdx++] = 0x80 | ((u >> 12) & 63);
921
984
  heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1123,7 +1186,7 @@ async function createWasm() {
1123
1186
  var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
1124
1187
 
1125
1188
  var alignMemory = (size, alignment) => {
1126
- assert(alignment, "alignment argument is required");
1189
+ assert(alignment, 'alignment argument is required');
1127
1190
  return Math.ceil(size / alignment) * alignment;
1128
1191
  };
1129
1192
  var mmapAlloc = (size) => {
@@ -1196,11 +1259,14 @@ async function createWasm() {
1196
1259
  } else if (FS.isFile(node.mode)) {
1197
1260
  node.node_ops = MEMFS.ops_table.file.node;
1198
1261
  node.stream_ops = MEMFS.ops_table.file.stream;
1199
- node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
1200
- // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
1201
- // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
1202
- // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
1203
- node.contents = null;
1262
+ // The actual number of bytes used in the typed array, as opposed to
1263
+ // contents.length which gives the whole capacity.
1264
+ node.usedBytes = 0;
1265
+ // The byte data of the file is stored in a typed array.
1266
+ // Note: typed arrays are not resizable like normal JS arrays are, so
1267
+ // there is a small penalty involved for appending file writes that
1268
+ // continuously grow a file similar to std::vector capacity vs used.
1269
+ node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0);
1204
1270
  } else if (FS.isLink(node.mode)) {
1205
1271
  node.node_ops = MEMFS.ops_table.link.node;
1206
1272
  node.stream_ops = MEMFS.ops_table.link.stream;
@@ -1217,36 +1283,30 @@ async function createWasm() {
1217
1283
  return node;
1218
1284
  },
1219
1285
  getFileDataAsTypedArray(node) {
1220
- if (!node.contents) return new Uint8Array(0);
1221
- if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1222
- return new Uint8Array(node.contents);
1286
+ assert(FS.isFile(node.mode), 'getFileDataAsTypedArray called on non-file');
1287
+ return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1223
1288
  },
1224
1289
  expandFileStorage(node, newCapacity) {
1225
- var prevCapacity = node.contents ? node.contents.length : 0;
1290
+ var prevCapacity = node.contents.length;
1226
1291
  if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
1227
- // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
1228
- // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
1229
- // avoid overshooting the allocation cap by a very large margin.
1292
+ // Don't expand strictly to the given requested limit if it's only a very
1293
+ // small increase, but instead geometrically grow capacity.
1294
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for
1295
+ // large sizes, do a much more conservative size*1.125 increase to avoid
1296
+ // overshooting the allocation cap by a very large margin.
1230
1297
  var CAPACITY_DOUBLING_MAX = 1024 * 1024;
1231
1298
  newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
1232
- if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1233
- var oldContents = node.contents;
1299
+ if (prevCapacity) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1300
+ var oldContents = MEMFS.getFileDataAsTypedArray(node);
1234
1301
  node.contents = new Uint8Array(newCapacity); // Allocate new storage.
1235
- if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
1302
+ node.contents.set(oldContents);
1236
1303
  },
1237
1304
  resizeFileStorage(node, newSize) {
1238
1305
  if (node.usedBytes == newSize) return;
1239
- if (newSize == 0) {
1240
- node.contents = null; // Fully decommit when requesting a resize to zero.
1241
- node.usedBytes = 0;
1242
- } else {
1243
- var oldContents = node.contents;
1244
- node.contents = new Uint8Array(newSize); // Allocate new storage.
1245
- if (oldContents) {
1246
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1247
- }
1248
- node.usedBytes = newSize;
1249
- }
1306
+ var oldContents = node.contents;
1307
+ node.contents = new Uint8Array(newSize); // Allocate new storage.
1308
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1309
+ node.usedBytes = newSize;
1250
1310
  },
1251
1311
  node_ops:{
1252
1312
  getattr(node) {
@@ -1346,16 +1406,11 @@ async function createWasm() {
1346
1406
  if (position >= stream.node.usedBytes) return 0;
1347
1407
  var size = Math.min(stream.node.usedBytes - position, length);
1348
1408
  assert(size >= 0);
1349
- if (size > 8 && contents.subarray) { // non-trivial, and typed array
1350
- buffer.set(contents.subarray(position, position + size), offset);
1351
- } else {
1352
- for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
1353
- }
1409
+ buffer.set(contents.subarray(position, position + size), offset);
1354
1410
  return size;
1355
1411
  },
1356
1412
  write(stream, buffer, offset, length, position, canOwn) {
1357
- // The data buffer should be a typed array view
1358
- assert(!(buffer instanceof ArrayBuffer));
1413
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
1359
1414
  // If the buffer is located in main memory (HEAP), and if
1360
1415
  // memory can grow, we can't hold on to references of the
1361
1416
  // memory buffer, as they may get invalidated. That means we
@@ -1368,33 +1423,19 @@ async function createWasm() {
1368
1423
  var node = stream.node;
1369
1424
  node.mtime = node.ctime = Date.now();
1370
1425
 
1371
- if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
1372
- if (canOwn) {
1373
- assert(position === 0, 'canOwn must imply no weird position inside the file');
1374
- node.contents = buffer.subarray(offset, offset + length);
1375
- node.usedBytes = length;
1376
- return length;
1377
- } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
1378
- node.contents = buffer.slice(offset, offset + length);
1379
- node.usedBytes = length;
1380
- return length;
1381
- } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
1382
- node.contents.set(buffer.subarray(offset, offset + length), position);
1383
- return length;
1384
- }
1385
- }
1386
-
1387
- // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
1388
- MEMFS.expandFileStorage(node, position+length);
1389
- if (node.contents.subarray && buffer.subarray) {
1426
+ if (canOwn) {
1427
+ assert(position === 0, 'canOwn must imply no weird position inside the file');
1428
+ node.contents = buffer.subarray(offset, offset + length);
1429
+ node.usedBytes = length;
1430
+ } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
1431
+ node.contents = buffer.slice(offset, offset + length);
1432
+ node.usedBytes = length;
1433
+ } else {
1434
+ MEMFS.expandFileStorage(node, position+length);
1390
1435
  // Use typed array write which is available.
1391
1436
  node.contents.set(buffer.subarray(offset, offset + length), position);
1392
- } else {
1393
- for (var i = 0; i < length; i++) {
1394
- node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
1395
- }
1437
+ node.usedBytes = Math.max(node.usedBytes, position + length);
1396
1438
  }
1397
- node.usedBytes = Math.max(node.usedBytes, position + length);
1398
1439
  return length;
1399
1440
  },
1400
1441
  llseek(stream, offset, whence) {
@@ -1419,7 +1460,7 @@ async function createWasm() {
1419
1460
  var allocated;
1420
1461
  var contents = stream.node.contents;
1421
1462
  // Only make a new copy when MAP_PRIVATE is specified.
1422
- if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
1463
+ if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
1423
1464
  // We can't emulate MAP_SHARED when the file is not backed by the
1424
1465
  // buffer we're mapping to (e.g. the HEAP buffer).
1425
1466
  allocated = false;
@@ -1453,6 +1494,7 @@ async function createWasm() {
1453
1494
  };
1454
1495
 
1455
1496
  var FS_modeStringToFlags = (str) => {
1497
+ if (typeof str != 'string') return str;
1456
1498
  var flagModes = {
1457
1499
  'r': 0,
1458
1500
  'r+': 2,
@@ -1468,6 +1510,16 @@ async function createWasm() {
1468
1510
  return flags;
1469
1511
  };
1470
1512
 
1513
+ var FS_fileDataToTypedArray = (data) => {
1514
+ if (typeof data == 'string') {
1515
+ data = intArrayFromString(data, true);
1516
+ }
1517
+ if (!data.subarray) {
1518
+ data = new Uint8Array(data);
1519
+ }
1520
+ return data;
1521
+ };
1522
+
1471
1523
  var FS_getMode = (canRead, canWrite) => {
1472
1524
  var mode = 0;
1473
1525
  if (canRead) mode |= 292 | 73;
@@ -1761,7 +1813,11 @@ async function createWasm() {
1761
1813
  if (attr.mode != null && attr.dontFollow) {
1762
1814
  throw new FS.ErrnoError(52);
1763
1815
  }
1764
- NODEFS.setattr(path, node, attr, fs.chmodSync, fs.utimesSync, fs.truncateSync, fs.lstatSync);
1816
+ // `dontFollow` (AT_SYMLINK_NOFOLLOW): use lutimes so the symlink's own
1817
+ // timestamps are set without the host resolving it, which would
1818
+ // otherwise escape the NODEFS mount root.
1819
+ var utimes = attr.dontFollow ? fs.lutimesSync : fs.utimesSync;
1820
+ NODEFS.setattr(path, node, attr, fs.chmodSync, utimes, fs.truncateSync, fs.lstatSync);
1765
1821
  },
1766
1822
  lookup(parent, name) {
1767
1823
  var path = PATH.join2(NODEFS.realPath(parent), name);
@@ -1893,6 +1949,70 @@ async function createWasm() {
1893
1949
 
1894
1950
 
1895
1951
 
1952
+
1953
+ var NODERAWFS_stream_funcs = {
1954
+ close(stream) {
1955
+ VFS.closeStream(stream.fd);
1956
+ // Don't close stdin/stdout/stderr since they are used by node itself.
1957
+ if (--stream.shared.refcnt <= 0 && stream.nfd > 2) {
1958
+ // This stream is created by our Node.js filesystem, close the
1959
+ // native file descriptor when its reference count drops to 0.
1960
+ fs.closeSync(stream.nfd);
1961
+ }
1962
+ },
1963
+ llseek(stream, offset, whence) {
1964
+ var position = offset;
1965
+ if (whence === 1) {
1966
+ position += stream.position;
1967
+ } else if (whence === 2) {
1968
+ position += fs.fstatSync(stream.nfd).size;
1969
+ } else if (whence !== 0) {
1970
+ throw new FS.ErrnoError(28);
1971
+ }
1972
+
1973
+ if (position < 0) {
1974
+ throw new FS.ErrnoError(28);
1975
+ }
1976
+ stream.position = position;
1977
+ return position;
1978
+ },
1979
+ read(stream, buffer, offset, length, position) {
1980
+ var seeking = typeof position != 'undefined';
1981
+ if (!seeking && stream.seekable) position = stream.position;
1982
+ var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
1983
+ // update position marker when non-seeking
1984
+ if (!seeking) stream.position += bytesRead;
1985
+ return bytesRead;
1986
+ },
1987
+ write(stream, buffer, offset, length, position) {
1988
+ if (stream.flags & 1024) {
1989
+ // seek to the end before writing in append mode
1990
+ FS.llseek(stream, 0, 2);
1991
+ }
1992
+ var seeking = typeof position != 'undefined';
1993
+ if (!seeking && stream.seekable) position = stream.position;
1994
+ var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
1995
+ // update position marker when non-seeking
1996
+ if (!seeking) stream.position += bytesWritten;
1997
+ return bytesWritten;
1998
+ },
1999
+ mmap(stream, length, position, prot, flags) {
2000
+ if (!length) {
2001
+ throw new FS.ErrnoError(28);
2002
+ }
2003
+ var ptr = mmapAlloc(length);
2004
+ FS.read(stream, HEAP8, ptr, length, position);
2005
+ return { ptr, allocated: true };
2006
+ },
2007
+ msync(stream, buffer, offset, length, mmapFlags) {
2008
+ FS.write(stream, buffer, 0, length, offset);
2009
+ // should we check if bytesWritten and length are the same?
2010
+ return 0;
2011
+ },
2012
+ ioctl(stream, cmd, arg) {
2013
+ throw new FS.ErrnoError(59);
2014
+ },
2015
+ };
1896
2016
  var NODERAWFS = {
1897
2017
  lookup(parent, name) {
1898
2018
  assert(parent)
@@ -1908,11 +2028,10 @@ async function createWasm() {
1908
2028
  return { path, node: { id: st.ino, mode, node_ops: NODERAWFS, path }};
1909
2029
  },
1910
2030
  createStandardStreams() {
1911
- // FIXME: tty is set to true to appease isatty(), the underlying ioctl syscalls still need to be implemented, see issue #22264.
1912
- FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, tty: true, seekable: false }, 0);
2031
+ FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, seekable: false }, 0);
1913
2032
  var paths = [,'/dev/stdout', '/dev/stderr'];
1914
2033
  for (var i = 1; i < 3; i++) {
1915
- FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577, tty: true, seekable: false }, i);
2034
+ FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577, seekable: false }, i);
1916
2035
  }
1917
2036
  },
1918
2037
  cwd() { return process.cwd(); },
@@ -1926,6 +2045,14 @@ async function createWasm() {
1926
2045
  },
1927
2046
  mkdir(...args) { fs.mkdirSync(...args); },
1928
2047
  symlink(...args) { fs.symlinkSync(...args); },
2048
+ link(oldpath, newpath, flags) {
2049
+ // AT_SYMLINK_FOLLOW (0x400): dereference oldpath if it is a symlink,
2050
+ // since node's link(2) links to the symlink itself by default.
2051
+ if (flags & 0x400) {
2052
+ oldpath = fs.realpathSync(oldpath);
2053
+ }
2054
+ fs.linkSync(oldpath, newpath);
2055
+ },
1929
2056
  rename(...args) { fs.renameSync(...args); },
1930
2057
  rmdir(...args) { fs.rmdirSync(...args); },
1931
2058
  readdir(...args) { return ['.', '..'].concat(fs.readdirSync(...args)); },
@@ -1942,6 +2069,12 @@ async function createWasm() {
1942
2069
  },
1943
2070
  fstat(fd) {
1944
2071
  var stream = FS.getStreamChecked(fd);
2072
+ // Virtual streams (pipes, sockets) have no backing node fd; defer to their
2073
+ // own getattr rather than node's fs.fstatSync.
2074
+ var getattr = stream.stream_ops?.getattr ?? stream.node.node_ops?.getattr;
2075
+ if (getattr) {
2076
+ return getattr(stream.stream_ops?.getattr ? stream : stream.node);
2077
+ }
1945
2078
  return fs.fstatSync(stream.nfd);
1946
2079
  },
1947
2080
  statfs(path) {
@@ -1995,21 +2128,23 @@ async function createWasm() {
1995
2128
  var stream = FS.getStreamChecked(fd);
1996
2129
  fs.ftruncateSync(stream.nfd, len);
1997
2130
  },
1998
- utime(path, atime, mtime) {
2131
+ utime(path, atime, mtime, dontFollow) {
1999
2132
  // null here for atime or mtime means UTIME_OMIT was passed. Since node
2000
2133
  // doesn't support this concept we need to first find the existing
2001
2134
  // timestamps in order to preserve them.
2002
2135
  if ((atime === null) || (mtime === null)) {
2003
- var st = fs.statSync(path);
2136
+ var st = dontFollow ? fs.lstatSync(path) : fs.statSync(path);
2004
2137
  atime ||= st.atimeMs;
2005
2138
  mtime ||= st.mtimeMs;
2006
2139
  }
2007
- fs.utimesSync(path, atime/1000, mtime/1000);
2140
+ if (dontFollow) {
2141
+ fs.lutimesSync(path, atime/1000, mtime/1000);
2142
+ } else {
2143
+ fs.utimesSync(path, atime/1000, mtime/1000);
2144
+ }
2008
2145
  },
2009
2146
  open(path, flags, mode) {
2010
- if (typeof flags == "string") {
2011
- flags = FS_modeStringToFlags(flags)
2012
- }
2147
+ flags = FS_modeStringToFlags(flags);
2013
2148
  var pathTruncated = path.split('/').map((s) => s.slice(0, 255)).join('/');
2014
2149
  var nfd = fs.openSync(pathTruncated, NODEFS.flagsForNode(flags), mode);
2015
2150
  var st = fs.fstatSync(nfd);
@@ -2024,118 +2159,18 @@ async function createWasm() {
2024
2159
  createStream(stream, fd) {
2025
2160
  // Call the original FS.createStream
2026
2161
  var rtn = VFS.createStream(stream, fd);
2027
- if (typeof rtn.shared.refcnt == 'undefined') {
2028
- rtn.shared.refcnt = 1;
2029
- } else {
2162
+ // Detect PIPEFS streams and skip the refcnt/tty initialization in that case.
2163
+ if (!stream.stream_ops) {
2164
+ rtn.shared.refcnt ??= 0;
2030
2165
  rtn.shared.refcnt++;
2166
+ rtn.tty = nodeTTY.isatty(rtn.nfd);
2031
2167
  }
2032
2168
  return rtn;
2033
2169
  },
2034
- close(stream) {
2035
- VFS.closeStream(stream.fd);
2036
- // Don't close stdin/stdout/stderr since they are used by node itself.
2037
- if (!stream.stream_ops && --stream.shared.refcnt <= 0 && stream.nfd > 2) {
2038
- // This stream is created by our Node.js filesystem, close the
2039
- // native file descriptor when its reference count drops to 0.
2040
- fs.closeSync(stream.nfd);
2041
- }
2042
- },
2043
- llseek(stream, offset, whence) {
2044
- if (stream.stream_ops) {
2045
- // this stream is created by in-memory filesystem
2046
- return VFS.llseek(stream, offset, whence);
2047
- }
2048
- var position = offset;
2049
- if (whence === 1) {
2050
- position += stream.position;
2051
- } else if (whence === 2) {
2052
- position += fs.fstatSync(stream.nfd).size;
2053
- } else if (whence !== 0) {
2054
- throw new FS.ErrnoError(28);
2055
- }
2056
-
2057
- if (position < 0) {
2058
- throw new FS.ErrnoError(28);
2059
- }
2060
- stream.position = position;
2061
- return position;
2062
- },
2063
- read(stream, buffer, offset, length, position) {
2064
- if (stream.stream_ops) {
2065
- // this stream is created by in-memory filesystem
2066
- return VFS.read(stream, buffer, offset, length, position);
2067
- }
2068
- var seeking = typeof position != 'undefined';
2069
- if (!seeking && stream.seekable) position = stream.position;
2070
- var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
2071
- // update position marker when non-seeking
2072
- if (!seeking) stream.position += bytesRead;
2073
- return bytesRead;
2074
- },
2075
- write(stream, buffer, offset, length, position) {
2076
- if (stream.stream_ops) {
2077
- // this stream is created by in-memory filesystem
2078
- return VFS.write(stream, buffer, offset, length, position);
2079
- }
2080
- if (stream.flags & +"1024") {
2081
- // seek to the end before writing in append mode
2082
- FS.llseek(stream, 0, +"2");
2083
- }
2084
- var seeking = typeof position != 'undefined';
2085
- if (!seeking && stream.seekable) position = stream.position;
2086
- var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
2087
- // update position marker when non-seeking
2088
- if (!seeking) stream.position += bytesWritten;
2089
- return bytesWritten;
2090
- },
2091
- mmap(stream, length, position, prot, flags) {
2092
- if (!length) {
2093
- throw new FS.ErrnoError(28);
2094
- }
2095
- if (stream.stream_ops) {
2096
- // this stream is created by in-memory filesystem
2097
- return VFS.mmap(stream, length, position, prot, flags);
2098
- }
2099
-
2100
- var ptr = mmapAlloc(length);
2101
- FS.read(stream, HEAP8, ptr, length, position);
2102
- return { ptr, allocated: true };
2103
- },
2104
- msync(stream, buffer, offset, length, mmapFlags) {
2105
- if (stream.stream_ops) {
2106
- // this stream is created by in-memory filesystem
2107
- return VFS.msync(stream, buffer, offset, length, mmapFlags);
2108
- }
2109
-
2110
- FS.write(stream, buffer, 0, length, offset);
2111
- // should we check if bytesWritten and length are the same?
2112
- return 0;
2113
- },
2114
- ioctl() {
2115
- throw new FS.ErrnoError(59);
2116
- },
2117
2170
  };
2118
2171
 
2119
2172
 
2120
2173
 
2121
- /**
2122
- * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
2123
- * emscripten HEAP, returns a copy of that string as a Javascript String object.
2124
- *
2125
- * @param {number} ptr
2126
- * @param {number=} maxBytesToRead - An optional length that specifies the
2127
- * maximum number of bytes to read. You can omit this parameter to scan the
2128
- * string until the first 0 byte. If maxBytesToRead is passed, and the string
2129
- * at [ptr, ptr+maxBytesToReadr[ contains a null byte in the middle, then the
2130
- * string will cut short at that byte index.
2131
- * @param {boolean=} ignoreNul - If true, the function will not stop on a NUL character.
2132
- * @return {string}
2133
- */
2134
- var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => {
2135
- assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`);
2136
- return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : '';
2137
- };
2138
-
2139
2174
  var strError = (errno) => UTF8ToString(_strerror(errno));
2140
2175
 
2141
2176
 
@@ -2156,10 +2191,12 @@ async function createWasm() {
2156
2191
  }
2157
2192
  };
2158
2193
 
2194
+ var dependenciesPromise = null;
2195
+ var resolveRunDependencies = async () => dependenciesPromise;
2159
2196
  var runDependencies = 0;
2160
2197
 
2161
2198
 
2162
- var dependenciesFulfilled = null;
2199
+ var dependenciesPromiseResolve = null;
2163
2200
 
2164
2201
  var runDependencyTracking = {
2165
2202
  };
@@ -2173,21 +2210,22 @@ async function createWasm() {
2173
2210
  assert(id, 'removeRunDependency requires an ID');
2174
2211
  assert(runDependencyTracking[id]);
2175
2212
  delete runDependencyTracking[id];
2176
- if (runDependencies == 0) {
2213
+ if (!runDependencies) {
2177
2214
  if (runDependencyWatcher !== null) {
2178
2215
  clearInterval(runDependencyWatcher);
2179
2216
  runDependencyWatcher = null;
2180
2217
  }
2181
- if (dependenciesFulfilled) {
2182
- var callback = dependenciesFulfilled;
2183
- dependenciesFulfilled = null;
2184
- callback(); // can add another dependenciesFulfilled
2185
- }
2218
+ dependenciesPromiseResolve();
2186
2219
  }
2187
2220
  };
2188
2221
 
2189
2222
 
2223
+
2224
+
2190
2225
  var addRunDependency = (id) => {
2226
+ if (!runDependencies) {
2227
+ dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve);
2228
+ }
2191
2229
  runDependencies++;
2192
2230
 
2193
2231
  Module['monitorRunDependencies']?.(runDependencies);
@@ -2360,6 +2398,48 @@ async function createWasm() {
2360
2398
  get isDevice() {
2361
2399
  return FS.isChrdev(this.mode);
2362
2400
  }
2401
+ // The per-inode readiness wait-queue. The node carries a Set of listener
2402
+ // entries {cb}; producers (SOCKFS, PIPEFS) call notifyListeners on a
2403
+ // readiness transition, and poll()/epoll consume it. It lives on the node
2404
+ // (not the fd) so dup'd fds share one queue. Only nodes that derive real
2405
+ // readiness (sockets, pipes, and an epoll's own node) ever use this -
2406
+ // always-ready types (regular files, ttys) never register or notify.
2407
+ addListener(cb, exclusive = false) {
2408
+ var entry = {cb, exclusive};
2409
+ var listeners = (this.listeners ??= new Set());
2410
+ listeners.add(entry);
2411
+ return {listeners, entry};
2412
+ }
2413
+ notifyListeners(flags) {
2414
+ // Iterates the set without copying, which is safe ONLY under a
2415
+ // load-bearing contract that every internal listener must honour:
2416
+ // 1. A listener must not run user code synchronously (a poll waiter only
2417
+ // resolves a Promise; an epoll registration only re-lists +
2418
+ // re-notifies; the epoll callback only schedules a tick). User code
2419
+ // runs on a later tick, never inside this loop.
2420
+ // 2. A listener may delete entries only from ITS OWN waiter, never from
2421
+ // a sibling node's set that may be mid-iteration. (Deleting an entry
2422
+ // of the set being iterated here is fine - a Set tolerates removal of
2423
+ // a not-yet-visited entry mid-iteration; mutating a *different* node's
2424
+ // set is fine because that set is not being iterated.)
2425
+ // Violating either gives silently skipped wakeups that are near-impossible
2426
+ // to reproduce. Any new producer/listener must preserve it.
2427
+ if (!this.listeners) return;
2428
+ // Fire every non-exclusive listener. Among EPOLLEXCLUSIVE registrations
2429
+ // (one fd watched by several epolls) wake only one, rotating round-robin
2430
+ // per node, to avoid a thundering herd. (Only epoll registrations are ever
2431
+ // exclusive; poll waiters and a node's own consumers are not.)
2432
+ var excl;
2433
+ for (var entry of this.listeners) {
2434
+ if (entry.exclusive) (excl ||= []).push(entry);
2435
+ else entry.cb(flags);
2436
+ }
2437
+ if (excl) {
2438
+ var i = (this.exclTurn || 0) % excl.length;
2439
+ this.exclTurn = i + 1;
2440
+ excl[i].cb(flags);
2441
+ }
2442
+ }
2363
2443
  },
2364
2444
  lookupPath(path, opts = {}) {
2365
2445
  if (!path) {
@@ -2371,7 +2451,7 @@ async function createWasm() {
2371
2451
  path = FS.cwd() + '/' + path;
2372
2452
  }
2373
2453
 
2374
- // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
2454
+ // limit max consecutive symlinks to SYMLOOP_MAX.
2375
2455
  linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
2376
2456
  // split the absolute path
2377
2457
  var parts = path.split('/').filter((p) => !!p);
@@ -2663,7 +2743,14 @@ async function createWasm() {
2663
2743
  var arg = setattr ? stream : node;
2664
2744
  setattr ??= node.node_ops.setattr;
2665
2745
  FS.checkOpExists(setattr, 63)
2666
- setattr(arg, attr);
2746
+ try {
2747
+ setattr(arg, attr);
2748
+ } catch (e) {
2749
+ if (e instanceof RangeError) {
2750
+ throw new FS.ErrnoError(22);
2751
+ }
2752
+ throw e;
2753
+ }
2667
2754
  },
2668
2755
  chrdev_stream_ops:{
2669
2756
  open(stream) {
@@ -2930,6 +3017,25 @@ async function createWasm() {
2930
3017
  }
2931
3018
  return parent.node_ops.symlink(parent, newname, oldpath);
2932
3019
  },
3020
+ link(oldpath, newpath, flags) {
3021
+ var lookup = FS.lookupPath(newpath, { parent: true });
3022
+ var parent = lookup.node;
3023
+ if (!parent) {
3024
+ throw new FS.ErrnoError(44);
3025
+ }
3026
+ var newname = PATH.basename(newpath);
3027
+ var errCode = FS.mayCreate(parent, newname);
3028
+ if (errCode) {
3029
+ throw new FS.ErrnoError(errCode);
3030
+ }
3031
+ // Hardlinks are only supported by filesystem backends that provide a
3032
+ // `link` node op (e.g. NODERAWFS backed by the host). NODEFS omits it:
3033
+ // a host hardlink cannot be confined to the mount root.
3034
+ if (!parent.node_ops.link) {
3035
+ throw new FS.ErrnoError(34);
3036
+ }
3037
+ return parent.node_ops.link(parent, newname, oldpath, flags);
3038
+ },
2933
3039
  rename(old_path, new_path) {
2934
3040
  var old_dirname = PATH.dirname(old_path);
2935
3041
  var new_dirname = PATH.dirname(new_path);
@@ -3176,20 +3282,19 @@ async function createWasm() {
3176
3282
  }
3177
3283
  FS.doTruncate(stream, stream.node, len);
3178
3284
  },
3179
- utime(path, atime, mtime) {
3180
- var lookup = FS.lookupPath(path, { follow: true });
3181
- var node = lookup.node;
3182
- var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
3183
- setattr(node, {
3285
+ utime(path, atime, mtime, dontFollow) {
3286
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
3287
+ FS.doSetAttr(null, lookup.node, {
3184
3288
  atime: atime,
3185
- mtime: mtime
3289
+ mtime: mtime,
3290
+ dontFollow
3186
3291
  });
3187
3292
  },
3188
3293
  open(path, flags, mode = 0o666) {
3189
3294
  if (path === "") {
3190
3295
  throw new FS.ErrnoError(44);
3191
3296
  }
3192
- flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags;
3297
+ flags = FS_modeStringToFlags(flags);
3193
3298
  if ((flags & 64)) {
3194
3299
  mode = (mode & 4095) | 32768;
3195
3300
  } else {
@@ -3283,6 +3388,11 @@ async function createWasm() {
3283
3388
  throw new FS.ErrnoError(8);
3284
3389
  }
3285
3390
  if (stream.getdents) stream.getdents = null; // free readdir state
3391
+ // The fd is going away: wake anything waiting on it (poll/epoll) with
3392
+ // POLLNVAL so a blocking wait unblocks and an epoll registration is evicted
3393
+ // on its next derive. Only sockets/pipes/epoll ever carry a wait-queue, so
3394
+ // for every other stream (incl. nodeless noderawfs stdio) this is a no-op.
3395
+ stream.node?.notifyListeners(32);
3286
3396
  try {
3287
3397
  if (stream.stream_ops.close) {
3288
3398
  stream.stream_ops.close(stream);
@@ -3340,6 +3450,7 @@ async function createWasm() {
3340
3450
  },
3341
3451
  write(stream, buffer, offset, length, position, canOwn) {
3342
3452
  assert(offset >= 0);
3453
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
3343
3454
  if (length < 0 || position < 0) {
3344
3455
  throw new FS.ErrnoError(28);
3345
3456
  }
@@ -3406,8 +3517,8 @@ async function createWasm() {
3406
3517
  return stream.stream_ops.ioctl(stream, cmd, arg);
3407
3518
  },
3408
3519
  readFile(path, opts = {}) {
3409
- opts.flags = opts.flags || 0;
3410
- opts.encoding = opts.encoding || 'binary';
3520
+ opts.flags = opts.flags ?? 0;
3521
+ opts.encoding = opts.encoding ?? 'binary';
3411
3522
  if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
3412
3523
  abort(`Invalid encoding type "${opts.encoding}"`);
3413
3524
  }
@@ -3423,16 +3534,10 @@ async function createWasm() {
3423
3534
  return buf;
3424
3535
  },
3425
3536
  writeFile(path, data, opts = {}) {
3426
- opts.flags = opts.flags || 577;
3537
+ opts.flags = opts.flags ?? 577;
3427
3538
  var stream = FS.open(path, opts.flags, opts.mode);
3428
- if (typeof data == 'string') {
3429
- data = new Uint8Array(intArrayFromString(data, true));
3430
- }
3431
- if (ArrayBuffer.isView(data)) {
3432
- FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3433
- } else {
3434
- abort('Unsupported data type');
3435
- }
3539
+ data = FS_fileDataToTypedArray(data);
3540
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3436
3541
  FS.close(stream);
3437
3542
  },
3438
3543
  cwd:() => FS.currentPath,
@@ -3658,11 +3763,7 @@ async function createWasm() {
3658
3763
  var mode = FS_getMode(canRead, canWrite);
3659
3764
  var node = FS.create(path, mode);
3660
3765
  if (data) {
3661
- if (typeof data == 'string') {
3662
- var arr = new Array(data.length);
3663
- for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
3664
- data = arr;
3665
- }
3766
+ data = FS_fileDataToTypedArray(data);
3666
3767
  // make sure we can write to the file
3667
3768
  FS.chmod(node, mode | 146);
3668
3769
  var stream = FS.open(node, 577);
@@ -3771,8 +3872,8 @@ async function createWasm() {
3771
3872
 
3772
3873
  // Function to get a range from the remote URL.
3773
3874
  var doXHR = (from, to) => {
3774
- if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
3775
- if (to > datalength-1) abort("only " + datalength + " bytes available! programmer error!");
3875
+ if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`);
3876
+ if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`);
3776
3877
 
3777
3878
  // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
3778
3879
  var xhr = new XMLHttpRequest();
@@ -3790,7 +3891,7 @@ async function createWasm() {
3790
3891
  if (xhr.response !== undefined) {
3791
3892
  return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
3792
3893
  }
3793
- return intArrayFromString(xhr.responseText || '', true);
3894
+ return intArrayFromString(xhr.responseText ?? '', true);
3794
3895
  };
3795
3896
  var lazyArray = this;
3796
3897
  lazyArray.setDataGetter((chunkNum) => {
@@ -3897,27 +3998,10 @@ async function createWasm() {
3897
3998
  node.stream_ops = stream_ops;
3898
3999
  return node;
3899
4000
  },
3900
- absolutePath() {
3901
- abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
3902
- },
3903
- createFolder() {
3904
- abort('FS.createFolder has been removed; use FS.mkdir instead');
3905
- },
3906
- createLink() {
3907
- abort('FS.createLink has been removed; use FS.symlink instead');
3908
- },
3909
- joinPath() {
3910
- abort('FS.joinPath has been removed; use PATH.join instead');
3911
- },
3912
- mmapAlloc() {
3913
- abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
3914
- },
3915
- standardizePath() {
3916
- abort('FS.standardizePath has been removed; use PATH.normalize instead');
3917
- },
3918
4001
  };
3919
4002
 
3920
4003
  var SYSCALLS = {
4004
+ currentUmask:18,
3921
4005
  calculateAt(dirfd, path, allowEmpty) {
3922
4006
  if (PATH.isAbs(path)) {
3923
4007
  return path;
@@ -3980,7 +4064,7 @@ async function createWasm() {
3980
4064
  // MAP_PRIVATE calls need not to be synced back to underlying fs
3981
4065
  return 0;
3982
4066
  }
3983
- var buffer = HEAPU8.slice(addr, addr + len);
4067
+ var buffer = HEAPU8.subarray(addr, addr + len);
3984
4068
  FS.msync(stream, buffer, offset, len, flags);
3985
4069
  },
3986
4070
  getStreamFromFD(fd) {
@@ -4004,6 +4088,7 @@ async function createWasm() {
4004
4088
  return -e.errno;
4005
4089
  }
4006
4090
  }
4091
+
4007
4092
 
4008
4093
  function ___syscall_chmod(path, mode) {
4009
4094
  try {
@@ -4016,6 +4101,7 @@ async function createWasm() {
4016
4101
  return -e.errno;
4017
4102
  }
4018
4103
  }
4104
+
4019
4105
 
4020
4106
  function ___syscall_dup(fd) {
4021
4107
  try {
@@ -4027,23 +4113,29 @@ async function createWasm() {
4027
4113
  return -e.errno;
4028
4114
  }
4029
4115
  }
4116
+
4030
4117
 
4031
4118
  function ___syscall_dup3(fd, newfd, flags) {
4032
4119
  try {
4033
4120
 
4121
+ if (fd === newfd) return -28;
4122
+ if (flags & ~524288) return -28;
4034
4123
  var old = SYSCALLS.getStreamFromFD(fd);
4035
- assert(!flags);
4036
- if (old.fd === newfd) return -28;
4037
4124
  // Check newfd is within range of valid open file descriptors.
4038
4125
  if (newfd < 0 || newfd >= FS.MAX_OPEN_FDS) return -8;
4039
4126
  var existing = FS.getStream(newfd);
4040
4127
  if (existing) FS.close(existing);
4041
- return FS.dupStream(old, newfd).fd;
4128
+ var stream = FS.dupStream(old, newfd);
4129
+ if (flags & 524288) {
4130
+ stream.flags |= 524288;
4131
+ }
4132
+ return stream.fd;
4042
4133
  } catch (e) {
4043
4134
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4044
4135
  return -e.errno;
4045
4136
  }
4046
4137
  }
4138
+
4047
4139
 
4048
4140
  var syscallGetVarargI = () => {
4049
4141
  assert(SYSCALLS.varargs != undefined);
@@ -4080,7 +4172,8 @@ async function createWasm() {
4080
4172
  return stream.flags;
4081
4173
  case 4: {
4082
4174
  var arg = syscallGetVarargI();
4083
- stream.flags |= arg;
4175
+ var mask = 289792;
4176
+ stream.flags = (stream.flags & ~mask) | (arg & mask);
4084
4177
  return 0;
4085
4178
  }
4086
4179
  case 12: {
@@ -4104,6 +4197,7 @@ async function createWasm() {
4104
4197
  return -e.errno;
4105
4198
  }
4106
4199
  }
4200
+
4107
4201
 
4108
4202
  function ___syscall_fstat64(fd, buf) {
4109
4203
  try {
@@ -4114,6 +4208,7 @@ async function createWasm() {
4114
4208
  return -e.errno;
4115
4209
  }
4116
4210
  }
4211
+
4117
4212
 
4118
4213
  var INT53_MAX = 9007199254740992;
4119
4214
 
@@ -4125,7 +4220,7 @@ async function createWasm() {
4125
4220
 
4126
4221
  try {
4127
4222
 
4128
- if (isNaN(length)) return -61;
4223
+ if (isNaN(length)) return -22;
4129
4224
  FS.ftruncate(fd, length);
4130
4225
  return 0;
4131
4226
  } catch (e) {
@@ -4137,7 +4232,7 @@ async function createWasm() {
4137
4232
 
4138
4233
 
4139
4234
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
4140
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
4235
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8 requires a third parameter that specifies the length of the output buffer');
4141
4236
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
4142
4237
  };
4143
4238
  function ___syscall_getcwd(buf, size) {
@@ -4154,6 +4249,7 @@ async function createWasm() {
4154
4249
  return -e.errno;
4155
4250
  }
4156
4251
  }
4252
+
4157
4253
 
4158
4254
 
4159
4255
  function ___syscall_getdents64(fd, dirp, count) {
@@ -4214,6 +4310,7 @@ async function createWasm() {
4214
4310
  return -e.errno;
4215
4311
  }
4216
4312
  }
4313
+
4217
4314
 
4218
4315
 
4219
4316
  function ___syscall_ioctl(fd, op, varargs) {
@@ -4311,6 +4408,7 @@ async function createWasm() {
4311
4408
  return -e.errno;
4312
4409
  }
4313
4410
  }
4411
+
4314
4412
 
4315
4413
  function ___syscall_lstat64(path, buf) {
4316
4414
  try {
@@ -4322,12 +4420,14 @@ async function createWasm() {
4322
4420
  return -e.errno;
4323
4421
  }
4324
4422
  }
4423
+
4325
4424
 
4326
4425
  function ___syscall_mkdirat(dirfd, path, mode) {
4327
4426
  try {
4328
4427
 
4329
4428
  path = SYSCALLS.getStr(path);
4330
4429
  path = SYSCALLS.calculateAt(dirfd, path);
4430
+ mode &= ~SYSCALLS.currentUmask;
4331
4431
  FS.mkdir(path, mode, 0);
4332
4432
  return 0;
4333
4433
  } catch (e) {
@@ -4335,6 +4435,7 @@ async function createWasm() {
4335
4435
  return -e.errno;
4336
4436
  }
4337
4437
  }
4438
+
4338
4439
 
4339
4440
  function ___syscall_newfstatat(dirfd, path, buf, flags) {
4340
4441
  try {
@@ -4351,6 +4452,7 @@ async function createWasm() {
4351
4452
  return -e.errno;
4352
4453
  }
4353
4454
  }
4455
+
4354
4456
 
4355
4457
 
4356
4458
  function ___syscall_openat(dirfd, path, flags, varargs) {
@@ -4360,12 +4462,16 @@ async function createWasm() {
4360
4462
  path = SYSCALLS.getStr(path);
4361
4463
  path = SYSCALLS.calculateAt(dirfd, path);
4362
4464
  var mode = varargs ? syscallGetVarargI() : 0;
4465
+ if (flags & 64) {
4466
+ mode &= ~SYSCALLS.currentUmask;
4467
+ }
4363
4468
  return FS.open(path, flags, mode).fd;
4364
4469
  } catch (e) {
4365
4470
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4366
4471
  return -e.errno;
4367
4472
  }
4368
4473
  }
4474
+
4369
4475
 
4370
4476
  var PIPEFS = {
4371
4477
  BUCKET_BUFFER_SIZE:8192,
@@ -4377,9 +4483,15 @@ async function createWasm() {
4377
4483
  createPipe() {
4378
4484
  var pipe = {
4379
4485
  buckets: [],
4380
- // refcnt 2 because pipe has a read end and a write end. We need to be
4381
- // able to read from the read end after write end is closed.
4382
- refcnt : 2,
4486
+ // Open write ends. When it drops to 0 the reader sees EOF and poll must
4487
+ // report POLLHUP (Linux semantics). Buckets are freed once both counts
4488
+ // reach 0.
4489
+ writerCount: 1,
4490
+ writeClosed: false,
4491
+ // Open read ends. When it drops to 0 the writer sees POLLERR (a further
4492
+ // write would get EPIPE).
4493
+ readerCount: 1,
4494
+ readClosed: false,
4383
4495
  timestamp: new Date(),
4384
4496
  };
4385
4497
 
@@ -4396,6 +4508,10 @@ async function createWasm() {
4396
4508
 
4397
4509
  rNode.pipe = pipe;
4398
4510
  wNode.pipe = pipe;
4511
+ // The read end's node carries the reader poll wait-queue (writes wake it);
4512
+ // the write end's node carries the writer wait-queue (read-end close wakes it).
4513
+ pipe.readNode = rNode;
4514
+ pipe.writeNode = wNode;
4399
4515
 
4400
4516
  var readableStream = FS.createStream({
4401
4517
  path: rName,
@@ -4440,24 +4556,50 @@ async function createWasm() {
4440
4556
  blocks: 0,
4441
4557
  };
4442
4558
  },
4443
- poll(stream, timeout, notifyCallback) {
4559
+ poll(stream) {
4444
4560
  var pipe = stream.node.pipe;
4445
4561
 
4446
4562
  if ((stream.flags & 2097155) === 1) {
4447
- return (256 | 4);
4563
+ // Linux keeps the write end writable (the write itself fails with
4564
+ // EPIPE) while also signalling POLLERR once every read end is closed.
4565
+ var mask = 256 | 4;
4566
+ if (pipe.readClosed) {
4567
+ mask |= 8;
4568
+ }
4569
+ return mask;
4448
4570
  }
4571
+ var mask = 0;
4449
4572
  for (var bucket of pipe.buckets) {
4450
4573
  if (bucket.offset - bucket.roffset > 0) {
4451
- return (64 | 1);
4574
+ mask = 64 | 1;
4575
+ break;
4452
4576
  }
4453
4577
  }
4454
-
4455
- return 0;
4578
+ // With every write end closed the read end is at EOF: readable (read
4579
+ // returns 0) and hung up.
4580
+ if (pipe.writeClosed) {
4581
+ mask |= 16 | 1;
4582
+ }
4583
+ return mask;
4456
4584
  },
4457
4585
  dup(stream) {
4458
- stream.node.pipe.refcnt++;
4586
+ var pipe = stream.node.pipe;
4587
+ if ((stream.flags & 2097155) === 1) {
4588
+ pipe.writerCount++;
4589
+ } else {
4590
+ pipe.readerCount++;
4591
+ }
4459
4592
  },
4460
- ioctl(stream, request, varargs) {
4593
+ ioctl(stream, request, argp) {
4594
+ if (request == 21531) {
4595
+ var pipe = stream.node.pipe;
4596
+ var currentLength = 0;
4597
+ for (var bucket of pipe.buckets) {
4598
+ currentLength += bucket.offset - bucket.roffset;
4599
+ }
4600
+ HEAP32[((argp)>>2)] = currentLength;
4601
+ return 0;
4602
+ }
4461
4603
  return 28;
4462
4604
  },
4463
4605
  fsync(stream) {
@@ -4550,6 +4692,7 @@ async function createWasm() {
4550
4692
  if (freeBytesInCurrBuffer >= dataLen) {
4551
4693
  currBucket.buffer.set(data, currBucket.offset);
4552
4694
  currBucket.offset += dataLen;
4695
+ pipe.readNode.notifyListeners(64 | 1);
4553
4696
  return dataLen;
4554
4697
  } else if (freeBytesInCurrBuffer > 0) {
4555
4698
  currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
@@ -4581,12 +4724,25 @@ async function createWasm() {
4581
4724
  newBucket.buffer.set(data);
4582
4725
  }
4583
4726
 
4727
+ pipe.readNode.notifyListeners(64 | 1);
4584
4728
  return dataLen;
4585
4729
  },
4586
4730
  close(stream) {
4587
4731
  var pipe = stream.node.pipe;
4588
- pipe.refcnt--;
4589
- if (pipe.refcnt === 0) {
4732
+ // When the last write end closes, wake any poll/epoll waiter on the read
4733
+ // end with POLLHUP so a reader blocked on the writer dropping unblocks.
4734
+ if ((stream.flags & 2097155) === 1) {
4735
+ if (--pipe.writerCount === 0) {
4736
+ pipe.writeClosed = true;
4737
+ pipe.readNode.notifyListeners(16 | 64 | 1);
4738
+ }
4739
+ } else if (--pipe.readerCount === 0) {
4740
+ // Mirror: when the last read end closes, wake any poll/epoll waiter on
4741
+ // the write end with POLLERR (a further write would get EPIPE).
4742
+ pipe.readClosed = true;
4743
+ pipe.writeNode.notifyListeners(8 | 256 | 4);
4744
+ }
4745
+ if (pipe.readerCount === 0 && pipe.writerCount === 0) {
4590
4746
  pipe.buckets = null;
4591
4747
  }
4592
4748
  },
@@ -4598,15 +4754,24 @@ async function createWasm() {
4598
4754
  return 'pipe[' + (PIPEFS.nextname.current++) + ']';
4599
4755
  },
4600
4756
  };
4601
- function ___syscall_pipe(fdPtr) {
4757
+ function ___syscall_pipe2(fdPtr, flags) {
4602
4758
  try {
4603
4759
 
4604
4760
  if (fdPtr == 0) {
4605
4761
  throw new FS.ErrnoError(21);
4606
4762
  }
4763
+ var validFlags = 524288 | 2048;
4764
+ if (flags & ~validFlags) {
4765
+ throw new FS.ErrnoError(138);
4766
+ }
4607
4767
 
4608
4768
  var res = PIPEFS.createPipe();
4609
4769
 
4770
+ if (flags & 2048) {
4771
+ FS.getStream(res.readable_fd).flags |= 2048;
4772
+ FS.getStream(res.writable_fd).flags |= 2048;
4773
+ }
4774
+
4610
4775
  HEAP32[((fdPtr)>>2)] = res.readable_fd;
4611
4776
  HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd;
4612
4777
 
@@ -4616,30 +4781,33 @@ async function createWasm() {
4616
4781
  return -e.errno;
4617
4782
  }
4618
4783
  }
4619
-
4620
- function ___syscall_poll(fds, nfds, timeout) {
4621
- try {
4622
-
4623
4784
 
4785
+
4786
+ var pollOne = (fd, events) => {
4787
+ var stream = FS.getStream(fd);
4788
+ if (!stream) return 32;
4789
+ // Streams without a poll handler (regular files, incl. NODERAWFS/NODEFS
4790
+ // which leave stream_ops unset) are treated as always readable+writable.
4791
+ var flags = stream.stream_ops?.poll
4792
+ ? stream.stream_ops.poll(stream)
4793
+ : 5;
4794
+ return flags & (events | 8 | 16 | 32);
4795
+ };
4796
+ var doPollSync = (fds, nfds) => {
4624
4797
  var count = 0;
4625
- for (var i = 0; i < nfds; i++) {
4626
- var pollfd = fds + 8 * i;
4627
- var fd = HEAP32[((pollfd)>>2)];
4628
- var events = HEAP16[(((pollfd)+(4))>>1)];
4629
- var flags = 32;
4630
- var stream = FS.getStream(fd);
4631
- if (stream) {
4632
- if (stream.stream_ops.poll) {
4633
- flags = stream.stream_ops.poll(stream, -1);
4634
- } else {
4635
- flags = 5;
4636
- }
4637
- }
4638
- flags &= events | 8 | 16;
4639
- if (flags) count++;
4640
- HEAP16[(((pollfd)+(6))>>1)] = flags;
4798
+ for (var i = 0, pollfd = fds; i < nfds; i++, pollfd += 8) {
4799
+ var revents = pollOne(
4800
+ HEAP32[((pollfd)>>2)],
4801
+ HEAP16[(((pollfd)+(4))>>1)]);
4802
+ if (revents) count++;
4803
+ HEAP16[(((pollfd)+(6))>>1)] = revents;
4641
4804
  }
4805
+ return count;
4806
+ };
4807
+ function ___syscall_poll(fds, nfds, timeout) {
4808
+ try {
4642
4809
 
4810
+ var count = doPollSync(fds, nfds);
4643
4811
  if (!count && timeout != 0) warnOnce('non-zero poll() timeout not supported: ' + timeout)
4644
4812
  return count;
4645
4813
  } catch (e) {
@@ -4647,6 +4815,18 @@ async function createWasm() {
4647
4815
  return -e.errno;
4648
4816
  }
4649
4817
  }
4818
+
4819
+
4820
+ function ___syscall_poll_nonblocking(fds, nfds) {
4821
+ try {
4822
+
4823
+ return doPollSync(fds, nfds);
4824
+ } catch (e) {
4825
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4826
+ return -e.errno;
4827
+ }
4828
+ }
4829
+
4650
4830
 
4651
4831
 
4652
4832
 
@@ -4670,6 +4850,7 @@ async function createWasm() {
4670
4850
  return -e.errno;
4671
4851
  }
4672
4852
  }
4853
+
4673
4854
 
4674
4855
  function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
4675
4856
  try {
@@ -4685,6 +4866,7 @@ async function createWasm() {
4685
4866
  return -e.errno;
4686
4867
  }
4687
4868
  }
4869
+
4688
4870
 
4689
4871
  function ___syscall_rmdir(path) {
4690
4872
  try {
@@ -4697,6 +4879,7 @@ async function createWasm() {
4697
4879
  return -e.errno;
4698
4880
  }
4699
4881
  }
4882
+
4700
4883
 
4701
4884
  function ___syscall_stat64(path, buf) {
4702
4885
  try {
@@ -4708,6 +4891,7 @@ async function createWasm() {
4708
4891
  return -e.errno;
4709
4892
  }
4710
4893
  }
4894
+
4711
4895
 
4712
4896
  function ___syscall_symlinkat(target, dirfd, linkpath) {
4713
4897
  try {
@@ -4722,6 +4906,20 @@ async function createWasm() {
4722
4906
  return -e.errno;
4723
4907
  }
4724
4908
  }
4909
+
4910
+
4911
+ function ___syscall_umask(mask) {
4912
+ try {
4913
+
4914
+ var old = SYSCALLS.currentUmask;
4915
+ SYSCALLS.currentUmask = mask;
4916
+ return old;
4917
+ } catch (e) {
4918
+ if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4919
+ return -e.errno;
4920
+ }
4921
+ }
4922
+
4725
4923
 
4726
4924
  function ___syscall_unlinkat(dirfd, path, flags) {
4727
4925
  try {
@@ -4741,6 +4939,7 @@ async function createWasm() {
4741
4939
  return -e.errno;
4742
4940
  }
4743
4941
  }
4942
+
4744
4943
 
4745
4944
  var __abort_js = () =>
4746
4945
  abort('native code called abort()');
@@ -4752,7 +4951,7 @@ async function createWasm() {
4752
4951
  };
4753
4952
 
4754
4953
  var __emscripten_throw_longjmp = () => {
4755
- throw Infinity;
4954
+ throw new EmscriptenSjLj;
4756
4955
  };
4757
4956
 
4758
4957
  var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0);
@@ -4773,6 +4972,9 @@ async function createWasm() {
4773
4972
 
4774
4973
 
4775
4974
  var date = new Date(time*1000);
4975
+ if (isNaN(date.getTime())) {
4976
+ return 1;
4977
+ }
4776
4978
  HEAP32[((tmPtr)>>2)] = date.getSeconds();
4777
4979
  HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
4778
4980
  HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
@@ -4791,6 +4993,7 @@ async function createWasm() {
4791
4993
  var winterOffset = start.getTimezoneOffset();
4792
4994
  var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
4793
4995
  HEAP32[(((tmPtr)+(32))>>2)] = dst;
4996
+ return 0;
4794
4997
  ;
4795
4998
  }
4796
4999
 
@@ -4805,6 +5008,9 @@ async function createWasm() {
4805
5008
  HEAP32[(((tmPtr)+(4))>>2)],
4806
5009
  HEAP32[((tmPtr)>>2)],
4807
5010
  0);
5011
+ if (isNaN(date.getTime())) {
5012
+ return -1;
5013
+ }
4808
5014
 
4809
5015
  // There's an ambiguous hour when the time goes back; the tm_isdst field is
4810
5016
  // used to disambiguate it. Date() basically guesses, so we fix it up if it
@@ -4817,14 +5023,18 @@ async function createWasm() {
4817
5023
  var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
4818
5024
  if (dst < 0) {
4819
5025
  // Attention: some regions don't have DST at all.
4820
- HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
5026
+ dst = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
4821
5027
  } else if ((dst > 0) != (dstOffset == guessedOffset)) {
4822
5028
  var nonDstOffset = Math.max(winterOffset, summerOffset);
4823
5029
  var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
4824
5030
  // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
4825
5031
  date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
5032
+ if (isNaN(date.getTime())) {
5033
+ return -1;
5034
+ }
4826
5035
  }
4827
5036
 
5037
+ HEAP32[(((tmPtr)+(32))>>2)] = dst;
4828
5038
  HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
4829
5039
  var yday = ydayFromDate(date)|0;
4830
5040
  HEAP32[(((tmPtr)+(28))>>2)] = yday;
@@ -4836,12 +5046,8 @@ async function createWasm() {
4836
5046
  HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
4837
5047
  HEAP32[(((tmPtr)+(20))>>2)] = date.getYear();
4838
5048
 
4839
- var timeMs = date.getTime();
4840
- if (isNaN(timeMs)) {
4841
- return -1;
4842
- }
4843
- // Return time in microseconds
4844
- return timeMs / 1000;
5049
+ // Return time in seconds
5050
+ return date.getTime() / 1000;
4845
5051
  })();
4846
5052
  return BigInt(ret);
4847
5053
  };
@@ -5073,11 +5279,10 @@ async function createWasm() {
5073
5279
  var ENV = {
5074
5280
  };
5075
5281
 
5076
- var getExecutableName = () => thisProgram || './this.program';
5282
+ var getExecutableName = () => thisProgram;
5077
5283
  var getEnvStrings = () => {
5078
5284
  if (!getEnvStrings.strings) {
5079
5285
  // Default values.
5080
- // Browser language detection #8751
5081
5286
  var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8';
5082
5287
  var env = {
5083
5288
  'USER': 'web_user',
@@ -5154,7 +5359,6 @@ async function createWasm() {
5154
5359
  // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
5155
5360
  if (keepRuntimeAlive() && !implicit) {
5156
5361
  var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
5157
- readyPromiseReject?.(msg);
5158
5362
  err(msg);
5159
5363
  }
5160
5364
 
@@ -5173,6 +5377,7 @@ async function createWasm() {
5173
5377
  return e.errno;
5174
5378
  }
5175
5379
  }
5380
+
5176
5381
 
5177
5382
  function _fd_fdstat_get(fd, pbuf) {
5178
5383
  try {
@@ -5199,6 +5404,7 @@ async function createWasm() {
5199
5404
  return e.errno;
5200
5405
  }
5201
5406
  }
5407
+
5202
5408
 
5203
5409
  /** @param {number=} offset */
5204
5410
  var doReadv = (stream, iov, iovcnt, offset) => {
@@ -5207,7 +5413,18 @@ async function createWasm() {
5207
5413
  var ptr = HEAPU32[((iov)>>2)];
5208
5414
  var len = HEAPU32[(((iov)+(4))>>2)];
5209
5415
  iov += 8;
5210
- var curr = FS.read(stream, HEAP8, ptr, len, offset);
5416
+ try {
5417
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
5418
+ } catch (e) {
5419
+ // On a non-blocking stream a subsequent read may would-block after we
5420
+ // already gathered data. POSIX readv is a single gather-read: return
5421
+ // what we have rather than failing the whole call.
5422
+ if (ret > 0 && e instanceof FS.ErrnoError &&
5423
+ (e.errno == 6 || e.errno == 6)) {
5424
+ break;
5425
+ }
5426
+ throw e;
5427
+ }
5211
5428
  if (curr < 0) return -1;
5212
5429
  ret += curr;
5213
5430
  if (curr < len) break; // nothing more to read
@@ -5225,7 +5442,7 @@ async function createWasm() {
5225
5442
 
5226
5443
  try {
5227
5444
 
5228
- if (isNaN(offset)) return 61;
5445
+ if (isNaN(offset)) return 22;
5229
5446
  var stream = SYSCALLS.getStreamFromFD(fd)
5230
5447
  var num = doReadv(stream, iov, iovcnt, offset);
5231
5448
  HEAPU32[((pnum)>>2)] = num;
@@ -5239,23 +5456,27 @@ async function createWasm() {
5239
5456
 
5240
5457
  /** @param {number=} offset */
5241
5458
  var doWritev = (stream, iov, iovcnt, offset) => {
5242
- var ret = 0;
5243
- for (var i = 0; i < iovcnt; i++) {
5459
+ // Gather all iovecs into one contiguous buffer and issue a single
5460
+ // FS.write, matching POSIX writev's single gather-write semantics (as
5461
+ // __syscall_sendmsg already does). Per-iovec writes fragment a stream
5462
+ // socket send into multiple segments, breaking stream byte semantics.
5463
+ if (iovcnt == 1) {
5464
+ // Single iovec: write directly from HEAP8, no gather buffer needed.
5465
+ return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset);
5466
+ }
5467
+ var total = 0;
5468
+ for (var i = 0, p = iov; i < iovcnt; i++, p += 8) {
5469
+ total += HEAPU32[(((p)+(4))>>2)];
5470
+ }
5471
+ var view = new Uint8Array(total);
5472
+ var voff = 0;
5473
+ for (var i = 0; i < iovcnt; i++, iov += 8) {
5244
5474
  var ptr = HEAPU32[((iov)>>2)];
5245
5475
  var len = HEAPU32[(((iov)+(4))>>2)];
5246
- iov += 8;
5247
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
5248
- if (curr < 0) return -1;
5249
- ret += curr;
5250
- if (curr < len) {
5251
- // No more space to write.
5252
- break;
5253
- }
5254
- if (typeof offset != 'undefined') {
5255
- offset += curr;
5256
- }
5476
+ view.set(HEAPU8.subarray(ptr, ptr + len), voff);
5477
+ voff += len;
5257
5478
  }
5258
- return ret;
5479
+ return FS.write(stream, view, 0, total, offset);
5259
5480
  };
5260
5481
 
5261
5482
 
@@ -5265,7 +5486,7 @@ async function createWasm() {
5265
5486
 
5266
5487
  try {
5267
5488
 
5268
- if (isNaN(offset)) return 61;
5489
+ if (isNaN(offset)) return 22;
5269
5490
  var stream = SYSCALLS.getStreamFromFD(fd)
5270
5491
  var num = doWritev(stream, iov, iovcnt, offset);
5271
5492
  HEAPU32[((pnum)>>2)] = num;
@@ -5290,6 +5511,7 @@ async function createWasm() {
5290
5511
  return e.errno;
5291
5512
  }
5292
5513
  }
5514
+
5293
5515
 
5294
5516
 
5295
5517
  function _fd_seek(fd, offset, whence, newOffset) {
@@ -5298,7 +5520,7 @@ async function createWasm() {
5298
5520
 
5299
5521
  try {
5300
5522
 
5301
- if (isNaN(offset)) return 61;
5523
+ if (isNaN(offset)) return 22;
5302
5524
  var stream = SYSCALLS.getStreamFromFD(fd);
5303
5525
  FS.llseek(stream, offset, whence);
5304
5526
  HEAP64[((newOffset)>>3)] = BigInt(stream.position);
@@ -5322,6 +5544,7 @@ async function createWasm() {
5322
5544
  return e.errno;
5323
5545
  }
5324
5546
  }
5547
+
5325
5548
 
5326
5549
 
5327
5550
  function _fd_write(fd, iov, iovcnt, pnum) {
@@ -5336,12 +5559,13 @@ async function createWasm() {
5336
5559
  return e.errno;
5337
5560
  }
5338
5561
  }
5562
+
5339
5563
 
5340
5564
 
5341
5565
 
5342
5566
  var getCFunc = (ident) => {
5343
5567
  var func = Module['_' + ident]; // closure exported function
5344
- assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
5568
+ assert(func, `Cannot call unknown function ${ident}, make sure it is exported`);
5345
5569
  return func;
5346
5570
  };
5347
5571
 
@@ -5398,7 +5622,7 @@ async function createWasm() {
5398
5622
  var func = getCFunc(ident);
5399
5623
  var cArgs = [];
5400
5624
  var stack = 0;
5401
- assert(returnType !== 'array', 'Return type should not be "array".');
5625
+ assert(returnType !== 'array', 'return type should not be "array"');
5402
5626
  if (args) {
5403
5627
  for (var i = 0; i < args.length; i++) {
5404
5628
  var converter = toC[argTypes[i]];
@@ -5435,6 +5659,7 @@ async function createWasm() {
5435
5659
 
5436
5660
 
5437
5661
 
5662
+
5438
5663
  FS.createPreloadedFile = FS_createPreloadedFile;
5439
5664
  FS.preloadFile = FS_preloadFile;
5440
5665
  FS.staticInit();;
@@ -5443,8 +5668,9 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5443
5668
  if (!ENVIRONMENT_IS_NODE) {
5444
5669
  throw new Error("NODERAWFS is currently only supported on Node.js environment.")
5445
5670
  }
5446
- var _wrapNodeError = function(func) {
5447
- return function(...args) {
5671
+ var nodeTTY = require('node:tty');
5672
+ function _wrapNodeError(func) {
5673
+ return (...args) => {
5448
5674
  try {
5449
5675
  return func(...args)
5450
5676
  } catch (e) {
@@ -5459,14 +5685,26 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5459
5685
  throw e;
5460
5686
  }
5461
5687
  }
5462
- };
5688
+ }
5689
+ function _wrapNodeStreamFunc(func, vfs_func) {
5690
+ return _wrapNodeError((stream, ...args) => {
5691
+ if (stream.stream_ops) {
5692
+ // this stream was created by some other FS. e.g: PIPEFS.
5693
+ return vfs_func(stream, ...args);
5694
+ }
5695
+ return func(stream, ...args);
5696
+ });
5697
+ }
5463
5698
  // Use this to reference our in-memory filesystem
5464
5699
  /** @suppress {partialAlias} */
5465
5700
  var VFS = {...FS};
5466
5701
  // Wrap the whole in-memory filesystem API with
5467
5702
  // our Node.js based functions
5468
- for (var _key in NODERAWFS) {
5469
- FS[_key] = _wrapNodeError(NODERAWFS[_key]);
5703
+ for (const [key, value] of Object.entries(NODERAWFS)) {
5704
+ FS[key] = _wrapNodeError(value);
5705
+ }
5706
+ for (const [key, value] of Object.entries(NODERAWFS_stream_funcs)) {
5707
+ FS[key] = _wrapNodeStreamFunc(value, FS[key]);
5470
5708
  };
5471
5709
  // End JS library code
5472
5710
 
@@ -5478,15 +5716,14 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5478
5716
 
5479
5717
  // Begin ATMODULES hooks
5480
5718
  if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
5481
- if (Module['preloadPlugins']) preloadPlugins = Module['preloadPlugins'];
5719
+
5482
5720
  if (Module['print']) out = Module['print'];
5483
5721
  if (Module['printErr']) err = Module['printErr'];
5484
- if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5485
5722
  // End ATMODULES hooks
5486
5723
 
5487
5724
  checkIncomingModuleAPI();
5488
5725
 
5489
- if (Module['arguments']) arguments_ = Module['arguments'];
5726
+ if (Module['arguments']) programArgs = Module['arguments'];
5490
5727
  if (Module['thisProgram']) thisProgram = Module['thisProgram'];
5491
5728
 
5492
5729
  // Assertions on removed incoming Module JS APIs.
@@ -5505,10 +5742,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5505
5742
  assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
5506
5743
  assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
5507
5744
 
5508
- if (Module['preInit']) {
5509
- if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
5510
- while (Module['preInit'].length > 0) {
5511
- Module['preInit'].shift()();
5745
+ var preInit = Module['preInit'];
5746
+ if (preInit) {
5747
+ if (typeof preInit == 'function') Module['preInit'] = preInit = [preInit];
5748
+ // Written as a loop so that preInit functions that themselves add more
5749
+ // preInit functions. Is this actually needed?
5750
+ while (preInit.length > 0) {
5751
+ preInit.shift()();
5512
5752
  }
5513
5753
  }
5514
5754
  consumedModuleProp('preInit');
@@ -5596,12 +5836,14 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5596
5836
  'registerOrientationChangeEventCallback',
5597
5837
  'fillFullscreenChangeEventData',
5598
5838
  'registerFullscreenChangeEventCallback',
5839
+ 'callCanvasResizedCallback',
5599
5840
  'JSEvents_requestFullscreen',
5600
5841
  'JSEvents_resizeCanvasForFullscreen',
5601
5842
  'registerRestoreOldStyle',
5602
5843
  'hideEverythingExceptGivenElement',
5603
5844
  'restoreHiddenElements',
5604
5845
  'setLetterbox',
5846
+ 'currentFullscreenStrategy',
5605
5847
  'softFullscreenResizeWebGLRenderTarget',
5606
5848
  'doRequestFullscreen',
5607
5849
  'fillPointerlockChangeEventData',
@@ -5631,10 +5873,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5631
5873
  'registerPreMainLoop',
5632
5874
  'getPromise',
5633
5875
  'makePromise',
5876
+ 'addPromise',
5634
5877
  'idsToPromises',
5635
5878
  'makePromiseCallback',
5636
5879
  'ExceptionInfo',
5637
5880
  'findMatchingCatch',
5881
+ 'incrementUncaughtExceptionCount',
5882
+ 'decrementUncaughtExceptionCount',
5638
5883
  'Browser_asyncPrepareDataCounter',
5639
5884
  'arraySum',
5640
5885
  'addDays',
@@ -5656,6 +5901,7 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5656
5901
  'colorChannelsInGlTextureFormat',
5657
5902
  'emscriptenWebGLGetTexPixelData',
5658
5903
  'emscriptenWebGLGetUniform',
5904
+ 'webglGetProgramUniformLocation',
5659
5905
  'webglGetUniformLocation',
5660
5906
  'webglPrepareUniformLocationsBeforeFirstUse',
5661
5907
  'webglGetLeftBracePos',
@@ -5684,20 +5930,20 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5684
5930
  'callMain',
5685
5931
  'abort',
5686
5932
  'wasmExports',
5687
- 'HEAPF32',
5688
- 'HEAPF64',
5933
+ 'writeStackCookie',
5934
+ 'checkStackCookie',
5935
+ 'INT53_MAX',
5936
+ 'INT53_MIN',
5937
+ 'bigintToI53Checked',
5689
5938
  'HEAP8',
5690
5939
  'HEAP16',
5691
5940
  'HEAPU16',
5692
5941
  'HEAP32',
5693
5942
  'HEAPU32',
5943
+ 'HEAPF32',
5944
+ 'HEAPF64',
5694
5945
  'HEAP64',
5695
5946
  'HEAPU64',
5696
- 'writeStackCookie',
5697
- 'checkStackCookie',
5698
- 'INT53_MAX',
5699
- 'INT53_MIN',
5700
- 'bigintToI53Checked',
5701
5947
  'stackSave',
5702
5948
  'stackRestore',
5703
5949
  'stackAlloc',
@@ -5746,7 +5992,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5746
5992
  'JSEvents',
5747
5993
  'specialHTMLTargets',
5748
5994
  'findCanvasEventTarget',
5749
- 'currentFullscreenStrategy',
5750
5995
  'restoreOldWindowedStyle',
5751
5996
  'UNWIND_CACHE',
5752
5997
  'ExitStatus',
@@ -5761,7 +6006,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5761
6006
  'emClearImmediate',
5762
6007
  'promiseMap',
5763
6008
  'uncaughtExceptionCount',
5764
- 'exceptionLast',
5765
6009
  'exceptionCaught',
5766
6010
  'Browser',
5767
6011
  'requestFullscreen',
@@ -5783,6 +6027,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5783
6027
  'FS_preloadFile',
5784
6028
  'FS_modeStringToFlags',
5785
6029
  'FS_getMode',
6030
+ 'FS_fileDataToTypedArray',
5786
6031
  'FS_stdin_getChar_buffer',
5787
6032
  'FS_stdin_getChar',
5788
6033
  'FS_unlink',
@@ -5850,6 +6095,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5850
6095
  'FS_mkdir',
5851
6096
  'FS_mkdev',
5852
6097
  'FS_symlink',
6098
+ 'FS_link',
5853
6099
  'FS_rename',
5854
6100
  'FS_rmdir',
5855
6101
  'FS_readdir',
@@ -5894,18 +6140,13 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5894
6140
  'FS_createDataFile',
5895
6141
  'FS_forceLoadFile',
5896
6142
  'FS_createLazyFile',
5897
- 'FS_absolutePath',
5898
- 'FS_createFolder',
5899
- 'FS_createLink',
5900
- 'FS_joinPath',
5901
- 'FS_mmapAlloc',
5902
- 'FS_standardizePath',
5903
6143
  'MEMFS',
5904
6144
  'TTY',
5905
6145
  'PIPEFS',
5906
6146
  'SOCKFS',
5907
6147
  'NODEFS',
5908
6148
  'NODERAWFS',
6149
+ 'NODERAWFS_stream_funcs',
5909
6150
  'nodePath',
5910
6151
  'tempFixedLengthArray',
5911
6152
  'miniTempWebGLFloatBuffers',
@@ -5934,16 +6175,40 @@ function checkIncomingModuleAPI() {
5934
6175
  ignoredModuleProp('fetchSettings');
5935
6176
  ignoredModuleProp('logReadFiles');
5936
6177
  ignoredModuleProp('loadSplitModule');
6178
+ ignoredModuleProp('onMalloc');
6179
+ ignoredModuleProp('onRealloc');
6180
+ ignoredModuleProp('onFree');
6181
+ ignoredModuleProp('onSbrkGrow');
6182
+ ignoredModuleProp('onCOSCacheHit');
6183
+ ignoredModuleProp('onCOSCacheMiss');
6184
+ ignoredModuleProp('onCOSStore');
6185
+ ignoredModuleProp('GL_MAX_TEXTURE_IMAGE_UNITS');
6186
+ ignoredModuleProp('SDL_canPlayWithWebAudio');
6187
+ ignoredModuleProp('SDL_numSimultaneouslyQueuedBuffers');
6188
+ ignoredModuleProp('freePreloadedMediaOnUse');
6189
+ ignoredModuleProp('preinitializedWebGLContext');
6190
+ ignoredModuleProp('keyboardListeningElement');
6191
+ ignoredModuleProp('doNotCaptureKeyboard');
6192
+ ignoredModuleProp('extraStackTrace');
6193
+ ignoredModuleProp('preloadPlugins');
6194
+ ignoredModuleProp('preMainLoop');
6195
+ ignoredModuleProp('postMainLoop');
6196
+ ignoredModuleProp('forcedAspectRatio');
6197
+ ignoredModuleProp('mainScriptUrlOrBlob');
6198
+ ignoredModuleProp('onFullScreen');
6199
+ ignoredModuleProp('INITIAL_MEMORY');
6200
+ ignoredModuleProp('wasmMemory');
6201
+ ignoredModuleProp('wasmBinary');
5937
6202
  }
5938
6203
  var ASM_CONSTS = {
5939
- 2640990: ($0) => { globalThis.picorubyRefs[$0] = null; },
5940
- 2641030: ($0) => { globalThis.picorubyRefs[$0] = true; },
5941
- 2641070: ($0) => { globalThis.picorubyRefs[$0] = false; },
5942
- 2641111: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5943
- 2641149: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5944
- 2641187: ($0, $1, $2) => { const str = UTF8ToString($1, $2); globalThis.picorubyRefs[$0] = str; },
5945
- 2641260: ($0, $1) => { const arr = globalThis.picorubyRefs[$0]; const elem = globalThis.picorubyRefs[$1]; arr.push(elem); delete globalThis.picorubyRefs[$1]; },
5946
- 2641399: ($0, $1, $2) => { const obj = globalThis.picorubyRefs[$0]; const key = UTF8ToString($1); const val = globalThis.picorubyRefs[$2]; obj[key] = val; delete globalThis.picorubyRefs[$2]; }
6204
+ 2645730: ($0) => { globalThis.picorubyRefs[$0] = null; },
6205
+ 2645770: ($0) => { globalThis.picorubyRefs[$0] = true; },
6206
+ 2645810: ($0) => { globalThis.picorubyRefs[$0] = false; },
6207
+ 2645851: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
6208
+ 2645889: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
6209
+ 2645927: ($0, $1, $2) => { const str = UTF8ToString($1, $2); globalThis.picorubyRefs[$0] = str; },
6210
+ 2646000: ($0, $1) => { const arr = globalThis.picorubyRefs[$0]; const elem = globalThis.picorubyRefs[$1]; arr.push(elem); delete globalThis.picorubyRefs[$1]; },
6211
+ 2646139: ($0, $1, $2) => { const obj = globalThis.picorubyRefs[$0]; const key = UTF8ToString($1); const val = globalThis.picorubyRefs[$2]; obj[key] = val; delete globalThis.picorubyRefs[$2]; }
5947
6212
  };
5948
6213
  function ble_dataview_length(ref_id) { try { const dv = globalThis.picorubyRefs[ref_id]; if (dv && dv.byteLength !== undefined) { return dv.byteLength; } return 0; } catch(e) { console.error('ble_dataview_length failed:', e); return 0; } }
5949
6214
  function ble_dataview_read(ref_id,out_buf,max_len) { try { const dv = globalThis.picorubyRefs[ref_id]; if (!dv) return 0; const len = Math.min(dv.byteLength, max_len); for (let i = 0; i < len; i++) { HEAPU8[out_buf + i] = dv.getUint8(i); } return len; } catch(e) { console.error('ble_dataview_read failed:', e); return 0; } }
@@ -6142,41 +6407,41 @@ function assignWasmExports(wasmExports) {
6142
6407
  assert(typeof wasmExports['emscripten_stack_get_current'] != 'undefined', 'missing Wasm export: emscripten_stack_get_current');
6143
6408
  assert(typeof wasmExports['memory'] != 'undefined', 'missing Wasm export: memory');
6144
6409
  assert(typeof wasmExports['__indirect_function_table'] != 'undefined', 'missing Wasm export: __indirect_function_table');
6145
- _ble_notify_callback = Module['_ble_notify_callback'] = createExportWrapper('ble_notify_callback', 3);
6146
- _mrb_get_globals_json = Module['_mrb_get_globals_json'] = createExportWrapper('mrb_get_globals_json', 0);
6147
- _mrb_get_component_debug_info = Module['_mrb_get_component_debug_info'] = createExportWrapper('mrb_get_component_debug_info', 1);
6148
- _mrb_get_component_state_by_id = Module['_mrb_get_component_state_by_id'] = createExportWrapper('mrb_get_component_state_by_id', 1);
6149
- _mrb_eval_string = Module['_mrb_eval_string'] = createExportWrapper('mrb_eval_string', 1);
6150
- _mrb_debug_get_status = Module['_mrb_debug_get_status'] = createExportWrapper('mrb_debug_get_status', 0);
6151
- _mrb_debug_continue = Module['_mrb_debug_continue'] = createExportWrapper('mrb_debug_continue', 0);
6152
- _mrb_debug_get_locals = Module['_mrb_debug_get_locals'] = createExportWrapper('mrb_debug_get_locals', 0);
6153
- _mrb_debug_eval_in_binding = Module['_mrb_debug_eval_in_binding'] = createExportWrapper('mrb_debug_eval_in_binding', 1);
6154
- _mrb_debug_step = Module['_mrb_debug_step'] = createExportWrapper('mrb_debug_step', 0);
6155
- _mrb_debug_next = Module['_mrb_debug_next'] = createExportWrapper('mrb_debug_next', 0);
6156
- _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = createExportWrapper('mrb_debug_get_callstack', 0);
6157
- _call_ruby_callback = Module['_call_ruby_callback'] = createExportWrapper('call_ruby_callback', 2);
6158
- _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = createExportWrapper('call_ruby_callback_oneshot', 2);
6159
- _resume_promise_task = Module['_resume_promise_task'] = createExportWrapper('resume_promise_task', 4);
6160
- _resume_promise_error_task = Module['_resume_promise_error_task'] = createExportWrapper('resume_promise_error_task', 4);
6161
- _resume_binary_task = Module['_resume_binary_task'] = createExportWrapper('resume_binary_task', 5);
6162
- _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = createExportWrapper('call_ruby_callback_sync_generic', 3);
6163
- _mrb_tick_wasm = Module['_mrb_tick_wasm'] = createExportWrapper('mrb_tick_wasm', 0);
6164
- _mrb_run_step = Module['_mrb_run_step'] = createExportWrapper('mrb_run_step', 0);
6165
- _mrb_run_step_status = Module['_mrb_run_step_status'] = createExportWrapper('mrb_run_step_status', 0);
6166
- _mrb_gc_scheduler_pending_wasm = Module['_mrb_gc_scheduler_pending_wasm'] = createExportWrapper('mrb_gc_scheduler_pending_wasm', 0);
6167
- _picorb_init = Module['_picorb_init'] = createExportWrapper('picorb_init', 0);
6168
- _picorb_create_task = Module['_picorb_create_task'] = createExportWrapper('picorb_create_task', 1);
6169
- _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = createExportWrapper('picorb_create_task_with_filename', 2);
6170
- _picorb_create_task_from_mrb = Module['_picorb_create_task_from_mrb'] = createExportWrapper('picorb_create_task_from_mrb', 2);
6171
- _serial_data_received = Module['_serial_data_received'] = createExportWrapper('serial_data_received', 3);
6172
- _serial_disconnect_callback = Module['_serial_disconnect_callback'] = createExportWrapper('serial_disconnect_callback', 1);
6173
- _call_ruby_callback_with_binary_data = Module['_call_ruby_callback_with_binary_data'] = createExportWrapper('call_ruby_callback_with_binary_data', 3);
6174
- _fflush = createExportWrapper('fflush', 1);
6175
- _strerror = createExportWrapper('strerror', 1);
6176
- _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
6177
- _malloc = Module['_malloc'] = createExportWrapper('malloc', 1);
6178
- _free = Module['_free'] = createExportWrapper('free', 1);
6179
- _setThrew = createExportWrapper('setThrew', 2);
6410
+ _ble_notify_callback = Module['_ble_notify_callback'] = createExportWrapper('ble_notify_callback', wasmExports['ble_notify_callback'], 3);
6411
+ _mrb_get_globals_json = Module['_mrb_get_globals_json'] = createExportWrapper('mrb_get_globals_json', wasmExports['mrb_get_globals_json'], 0);
6412
+ _mrb_get_component_debug_info = Module['_mrb_get_component_debug_info'] = createExportWrapper('mrb_get_component_debug_info', wasmExports['mrb_get_component_debug_info'], 1);
6413
+ _mrb_get_component_state_by_id = Module['_mrb_get_component_state_by_id'] = createExportWrapper('mrb_get_component_state_by_id', wasmExports['mrb_get_component_state_by_id'], 1);
6414
+ _mrb_eval_string = Module['_mrb_eval_string'] = createExportWrapper('mrb_eval_string', wasmExports['mrb_eval_string'], 1);
6415
+ _mrb_debug_get_status = Module['_mrb_debug_get_status'] = createExportWrapper('mrb_debug_get_status', wasmExports['mrb_debug_get_status'], 0);
6416
+ _mrb_debug_continue = Module['_mrb_debug_continue'] = createExportWrapper('mrb_debug_continue', wasmExports['mrb_debug_continue'], 0);
6417
+ _mrb_debug_get_locals = Module['_mrb_debug_get_locals'] = createExportWrapper('mrb_debug_get_locals', wasmExports['mrb_debug_get_locals'], 0);
6418
+ _mrb_debug_eval_in_binding = Module['_mrb_debug_eval_in_binding'] = createExportWrapper('mrb_debug_eval_in_binding', wasmExports['mrb_debug_eval_in_binding'], 1);
6419
+ _mrb_debug_step = Module['_mrb_debug_step'] = createExportWrapper('mrb_debug_step', wasmExports['mrb_debug_step'], 0);
6420
+ _mrb_debug_next = Module['_mrb_debug_next'] = createExportWrapper('mrb_debug_next', wasmExports['mrb_debug_next'], 0);
6421
+ _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = createExportWrapper('mrb_debug_get_callstack', wasmExports['mrb_debug_get_callstack'], 0);
6422
+ _call_ruby_callback = Module['_call_ruby_callback'] = createExportWrapper('call_ruby_callback', wasmExports['call_ruby_callback'], 2);
6423
+ _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = createExportWrapper('call_ruby_callback_oneshot', wasmExports['call_ruby_callback_oneshot'], 2);
6424
+ _resume_promise_task = Module['_resume_promise_task'] = createExportWrapper('resume_promise_task', wasmExports['resume_promise_task'], 4);
6425
+ _resume_promise_error_task = Module['_resume_promise_error_task'] = createExportWrapper('resume_promise_error_task', wasmExports['resume_promise_error_task'], 4);
6426
+ _resume_binary_task = Module['_resume_binary_task'] = createExportWrapper('resume_binary_task', wasmExports['resume_binary_task'], 5);
6427
+ _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = createExportWrapper('call_ruby_callback_sync_generic', wasmExports['call_ruby_callback_sync_generic'], 3);
6428
+ _mrb_tick_wasm = Module['_mrb_tick_wasm'] = createExportWrapper('mrb_tick_wasm', wasmExports['mrb_tick_wasm'], 0);
6429
+ _mrb_run_step = Module['_mrb_run_step'] = createExportWrapper('mrb_run_step', wasmExports['mrb_run_step'], 0);
6430
+ _mrb_run_step_status = Module['_mrb_run_step_status'] = createExportWrapper('mrb_run_step_status', wasmExports['mrb_run_step_status'], 0);
6431
+ _mrb_gc_scheduler_pending_wasm = Module['_mrb_gc_scheduler_pending_wasm'] = createExportWrapper('mrb_gc_scheduler_pending_wasm', wasmExports['mrb_gc_scheduler_pending_wasm'], 0);
6432
+ _picorb_init = Module['_picorb_init'] = createExportWrapper('picorb_init', wasmExports['picorb_init'], 0);
6433
+ _picorb_create_task = Module['_picorb_create_task'] = createExportWrapper('picorb_create_task', wasmExports['picorb_create_task'], 1);
6434
+ _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = createExportWrapper('picorb_create_task_with_filename', wasmExports['picorb_create_task_with_filename'], 2);
6435
+ _picorb_create_task_from_mrb = Module['_picorb_create_task_from_mrb'] = createExportWrapper('picorb_create_task_from_mrb', wasmExports['picorb_create_task_from_mrb'], 2);
6436
+ _serial_data_received = Module['_serial_data_received'] = createExportWrapper('serial_data_received', wasmExports['serial_data_received'], 3);
6437
+ _serial_disconnect_callback = Module['_serial_disconnect_callback'] = createExportWrapper('serial_disconnect_callback', wasmExports['serial_disconnect_callback'], 1);
6438
+ _call_ruby_callback_with_binary_data = Module['_call_ruby_callback_with_binary_data'] = createExportWrapper('call_ruby_callback_with_binary_data', wasmExports['call_ruby_callback_with_binary_data'], 3);
6439
+ _fflush = createExportWrapper('fflush', wasmExports['fflush'], 1);
6440
+ _strerror = createExportWrapper('strerror', wasmExports['strerror'], 1);
6441
+ _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', wasmExports['emscripten_builtin_memalign'], 2);
6442
+ _malloc = Module['_malloc'] = createExportWrapper('malloc', wasmExports['malloc'], 1);
6443
+ _free = Module['_free'] = createExportWrapper('free', wasmExports['free'], 1);
6444
+ _setThrew = createExportWrapper('setThrew', wasmExports['setThrew'], 2);
6180
6445
  _emscripten_stack_init = wasmExports['emscripten_stack_init'];
6181
6446
  _emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'];
6182
6447
  _emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'];
@@ -6189,6 +6454,8 @@ function assignWasmExports(wasmExports) {
6189
6454
  }
6190
6455
 
6191
6456
  var wasmImports = {
6457
+ /** @export */
6458
+ __assert_fail: ___assert_fail,
6192
6459
  /** @export */
6193
6460
  __call_sighandler: ___call_sighandler,
6194
6461
  /** @export */
@@ -6220,10 +6487,12 @@ var wasmImports = {
6220
6487
  /** @export */
6221
6488
  __syscall_openat: ___syscall_openat,
6222
6489
  /** @export */
6223
- __syscall_pipe: ___syscall_pipe,
6490
+ __syscall_pipe2: ___syscall_pipe2,
6224
6491
  /** @export */
6225
6492
  __syscall_poll: ___syscall_poll,
6226
6493
  /** @export */
6494
+ __syscall_poll_nonblocking: ___syscall_poll_nonblocking,
6495
+ /** @export */
6227
6496
  __syscall_readlinkat: ___syscall_readlinkat,
6228
6497
  /** @export */
6229
6498
  __syscall_renameat: ___syscall_renameat,
@@ -6234,6 +6503,8 @@ var wasmImports = {
6234
6503
  /** @export */
6235
6504
  __syscall_symlinkat: ___syscall_symlinkat,
6236
6505
  /** @export */
6506
+ __syscall_umask: ___syscall_umask,
6507
+ /** @export */
6237
6508
  __syscall_unlinkat: ___syscall_unlinkat,
6238
6509
  /** @export */
6239
6510
  _abort_js: __abort_js,
@@ -6344,12 +6615,18 @@ var wasmImports = {
6344
6615
  /** @export */
6345
6616
  invoke_ddd,
6346
6617
  /** @export */
6618
+ invoke_ii,
6619
+ /** @export */
6347
6620
  invoke_iii,
6348
6621
  /** @export */
6349
6622
  invoke_iiii,
6350
6623
  /** @export */
6351
6624
  invoke_iiiii,
6352
6625
  /** @export */
6626
+ invoke_iij,
6627
+ /** @export */
6628
+ invoke_iijiiiiii,
6629
+ /** @export */
6353
6630
  invoke_ji,
6354
6631
  /** @export */
6355
6632
  invoke_jii,
@@ -6364,6 +6641,8 @@ var wasmImports = {
6364
6641
  /** @export */
6365
6642
  invoke_viiiii,
6366
6643
  /** @export */
6644
+ invoke_viiiiiii,
6645
+ /** @export */
6367
6646
  invoke_viiiij,
6368
6647
  /** @export */
6369
6648
  invoke_viiiijii,
@@ -6374,14 +6653,14 @@ var wasmImports = {
6374
6653
  /** @export */
6375
6654
  invoke_viiji,
6376
6655
  /** @export */
6656
+ invoke_viijiii,
6657
+ /** @export */
6377
6658
  invoke_viijj,
6378
6659
  /** @export */
6379
6660
  invoke_vij,
6380
6661
  /** @export */
6381
6662
  invoke_vijii,
6382
6663
  /** @export */
6383
- invoke_vijiii,
6384
- /** @export */
6385
6664
  js_add_event_listener,
6386
6665
  /** @export */
6387
6666
  js_append_child,
@@ -6535,29 +6814,29 @@ function invoke_viii(index,a1,a2,a3) {
6535
6814
  getWasmTableEntry(index)(a1,a2,a3);
6536
6815
  } catch(e) {
6537
6816
  stackRestore(sp);
6538
- if (e !== e+0) throw e;
6817
+ if (!(e instanceof EmscriptenEH)) throw e;
6539
6818
  _setThrew(1, 0);
6540
6819
  }
6541
6820
  }
6542
6821
 
6543
- function invoke_iiii(index,a1,a2,a3) {
6822
+ function invoke_vii(index,a1,a2) {
6544
6823
  var sp = stackSave();
6545
6824
  try {
6546
- return getWasmTableEntry(index)(a1,a2,a3);
6825
+ getWasmTableEntry(index)(a1,a2);
6547
6826
  } catch(e) {
6548
6827
  stackRestore(sp);
6549
- if (e !== e+0) throw e;
6828
+ if (!(e instanceof EmscriptenEH)) throw e;
6550
6829
  _setThrew(1, 0);
6551
6830
  }
6552
6831
  }
6553
6832
 
6554
- function invoke_vii(index,a1,a2) {
6833
+ function invoke_ii(index,a1) {
6555
6834
  var sp = stackSave();
6556
6835
  try {
6557
- getWasmTableEntry(index)(a1,a2);
6836
+ return getWasmTableEntry(index)(a1);
6558
6837
  } catch(e) {
6559
6838
  stackRestore(sp);
6560
- if (e !== e+0) throw e;
6839
+ if (!(e instanceof EmscriptenEH)) throw e;
6561
6840
  _setThrew(1, 0);
6562
6841
  }
6563
6842
  }
@@ -6568,7 +6847,7 @@ function invoke_ji(index,a1) {
6568
6847
  return getWasmTableEntry(index)(a1);
6569
6848
  } catch(e) {
6570
6849
  stackRestore(sp);
6571
- if (e !== e+0) throw e;
6850
+ if (!(e instanceof EmscriptenEH)) throw e;
6572
6851
  _setThrew(1, 0);
6573
6852
  return 0n;
6574
6853
  }
@@ -6580,62 +6859,62 @@ function invoke_vi(index,a1) {
6580
6859
  getWasmTableEntry(index)(a1);
6581
6860
  } catch(e) {
6582
6861
  stackRestore(sp);
6583
- if (e !== e+0) throw e;
6862
+ if (!(e instanceof EmscriptenEH)) throw e;
6584
6863
  _setThrew(1, 0);
6585
6864
  }
6586
6865
  }
6587
6866
 
6588
- function invoke_viiiii(index,a1,a2,a3,a4,a5) {
6867
+ function invoke_iijiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8) {
6589
6868
  var sp = stackSave();
6590
6869
  try {
6591
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6870
+ return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8);
6592
6871
  } catch(e) {
6593
6872
  stackRestore(sp);
6594
- if (e !== e+0) throw e;
6873
+ if (!(e instanceof EmscriptenEH)) throw e;
6595
6874
  _setThrew(1, 0);
6596
6875
  }
6597
6876
  }
6598
6877
 
6599
- function invoke_vijiii(index,a1,a2,a3,a4,a5) {
6878
+ function invoke_viijiii(index,a1,a2,a3,a4,a5,a6) {
6600
6879
  var sp = stackSave();
6601
6880
  try {
6602
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6881
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6);
6603
6882
  } catch(e) {
6604
6883
  stackRestore(sp);
6605
- if (e !== e+0) throw e;
6884
+ if (!(e instanceof EmscriptenEH)) throw e;
6606
6885
  _setThrew(1, 0);
6607
6886
  }
6608
6887
  }
6609
6888
 
6610
- function invoke_viiji(index,a1,a2,a3,a4) {
6889
+ function invoke_iii(index,a1,a2) {
6611
6890
  var sp = stackSave();
6612
6891
  try {
6613
- getWasmTableEntry(index)(a1,a2,a3,a4);
6892
+ return getWasmTableEntry(index)(a1,a2);
6614
6893
  } catch(e) {
6615
6894
  stackRestore(sp);
6616
- if (e !== e+0) throw e;
6895
+ if (!(e instanceof EmscriptenEH)) throw e;
6617
6896
  _setThrew(1, 0);
6618
6897
  }
6619
6898
  }
6620
6899
 
6621
- function invoke_iiiii(index,a1,a2,a3,a4) {
6900
+ function invoke_viiiii(index,a1,a2,a3,a4,a5) {
6622
6901
  var sp = stackSave();
6623
6902
  try {
6624
- return getWasmTableEntry(index)(a1,a2,a3,a4);
6903
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6625
6904
  } catch(e) {
6626
6905
  stackRestore(sp);
6627
- if (e !== e+0) throw e;
6906
+ if (!(e instanceof EmscriptenEH)) throw e;
6628
6907
  _setThrew(1, 0);
6629
6908
  }
6630
6909
  }
6631
6910
 
6632
- function invoke_vij(index,a1,a2) {
6911
+ function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
6633
6912
  var sp = stackSave();
6634
6913
  try {
6635
- getWasmTableEntry(index)(a1,a2);
6914
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6636
6915
  } catch(e) {
6637
6916
  stackRestore(sp);
6638
- if (e !== e+0) throw e;
6917
+ if (!(e instanceof EmscriptenEH)) throw e;
6639
6918
  _setThrew(1, 0);
6640
6919
  }
6641
6920
  }
@@ -6646,40 +6925,62 @@ function invoke_viiii(index,a1,a2,a3,a4) {
6646
6925
  getWasmTableEntry(index)(a1,a2,a3,a4);
6647
6926
  } catch(e) {
6648
6927
  stackRestore(sp);
6649
- if (e !== e+0) throw e;
6928
+ if (!(e instanceof EmscriptenEH)) throw e;
6650
6929
  _setThrew(1, 0);
6651
6930
  }
6652
6931
  }
6653
6932
 
6654
- function invoke_viiiij(index,a1,a2,a3,a4,a5) {
6933
+ function invoke_viiiijii(index,a1,a2,a3,a4,a5,a6,a7) {
6655
6934
  var sp = stackSave();
6656
6935
  try {
6657
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6936
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6658
6937
  } catch(e) {
6659
6938
  stackRestore(sp);
6660
- if (e !== e+0) throw e;
6939
+ if (!(e instanceof EmscriptenEH)) throw e;
6661
6940
  _setThrew(1, 0);
6662
6941
  }
6663
6942
  }
6664
6943
 
6665
- function invoke_viiiijii(index,a1,a2,a3,a4,a5,a6,a7) {
6944
+ function invoke_iiii(index,a1,a2,a3) {
6666
6945
  var sp = stackSave();
6667
6946
  try {
6668
- getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6947
+ return getWasmTableEntry(index)(a1,a2,a3);
6669
6948
  } catch(e) {
6670
6949
  stackRestore(sp);
6671
- if (e !== e+0) throw e;
6950
+ if (!(e instanceof EmscriptenEH)) throw e;
6672
6951
  _setThrew(1, 0);
6673
6952
  }
6674
6953
  }
6675
6954
 
6676
- function invoke_iii(index,a1,a2) {
6955
+ function invoke_iiiii(index,a1,a2,a3,a4) {
6677
6956
  var sp = stackSave();
6678
6957
  try {
6679
- return getWasmTableEntry(index)(a1,a2);
6958
+ return getWasmTableEntry(index)(a1,a2,a3,a4);
6959
+ } catch(e) {
6960
+ stackRestore(sp);
6961
+ if (!(e instanceof EmscriptenEH)) throw e;
6962
+ _setThrew(1, 0);
6963
+ }
6964
+ }
6965
+
6966
+ function invoke_viiiij(index,a1,a2,a3,a4,a5) {
6967
+ var sp = stackSave();
6968
+ try {
6969
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6970
+ } catch(e) {
6971
+ stackRestore(sp);
6972
+ if (!(e instanceof EmscriptenEH)) throw e;
6973
+ _setThrew(1, 0);
6974
+ }
6975
+ }
6976
+
6977
+ function invoke_vij(index,a1,a2) {
6978
+ var sp = stackSave();
6979
+ try {
6980
+ getWasmTableEntry(index)(a1,a2);
6680
6981
  } catch(e) {
6681
6982
  stackRestore(sp);
6682
- if (e !== e+0) throw e;
6983
+ if (!(e instanceof EmscriptenEH)) throw e;
6683
6984
  _setThrew(1, 0);
6684
6985
  }
6685
6986
  }
@@ -6690,7 +6991,7 @@ function invoke_viij(index,a1,a2,a3) {
6690
6991
  getWasmTableEntry(index)(a1,a2,a3);
6691
6992
  } catch(e) {
6692
6993
  stackRestore(sp);
6693
- if (e !== e+0) throw e;
6994
+ if (!(e instanceof EmscriptenEH)) throw e;
6694
6995
  _setThrew(1, 0);
6695
6996
  }
6696
6997
  }
@@ -6701,7 +7002,18 @@ function invoke_viiij(index,a1,a2,a3,a4) {
6701
7002
  getWasmTableEntry(index)(a1,a2,a3,a4);
6702
7003
  } catch(e) {
6703
7004
  stackRestore(sp);
6704
- if (e !== e+0) throw e;
7005
+ if (!(e instanceof EmscriptenEH)) throw e;
7006
+ _setThrew(1, 0);
7007
+ }
7008
+ }
7009
+
7010
+ function invoke_viiji(index,a1,a2,a3,a4) {
7011
+ var sp = stackSave();
7012
+ try {
7013
+ getWasmTableEntry(index)(a1,a2,a3,a4);
7014
+ } catch(e) {
7015
+ stackRestore(sp);
7016
+ if (!(e instanceof EmscriptenEH)) throw e;
6705
7017
  _setThrew(1, 0);
6706
7018
  }
6707
7019
  }
@@ -6712,7 +7024,7 @@ function invoke_viijj(index,a1,a2,a3,a4) {
6712
7024
  getWasmTableEntry(index)(a1,a2,a3,a4);
6713
7025
  } catch(e) {
6714
7026
  stackRestore(sp);
6715
- if (e !== e+0) throw e;
7027
+ if (!(e instanceof EmscriptenEH)) throw e;
6716
7028
  _setThrew(1, 0);
6717
7029
  }
6718
7030
  }
@@ -6723,7 +7035,18 @@ function invoke_ddd(index,a1,a2) {
6723
7035
  return getWasmTableEntry(index)(a1,a2);
6724
7036
  } catch(e) {
6725
7037
  stackRestore(sp);
6726
- if (e !== e+0) throw e;
7038
+ if (!(e instanceof EmscriptenEH)) throw e;
7039
+ _setThrew(1, 0);
7040
+ }
7041
+ }
7042
+
7043
+ function invoke_iij(index,a1,a2) {
7044
+ var sp = stackSave();
7045
+ try {
7046
+ return getWasmTableEntry(index)(a1,a2);
7047
+ } catch(e) {
7048
+ stackRestore(sp);
7049
+ if (!(e instanceof EmscriptenEH)) throw e;
6727
7050
  _setThrew(1, 0);
6728
7051
  }
6729
7052
  }
@@ -6734,7 +7057,7 @@ function invoke_jii(index,a1,a2) {
6734
7057
  return getWasmTableEntry(index)(a1,a2);
6735
7058
  } catch(e) {
6736
7059
  stackRestore(sp);
6737
- if (e !== e+0) throw e;
7060
+ if (!(e instanceof EmscriptenEH)) throw e;
6738
7061
  _setThrew(1, 0);
6739
7062
  return 0n;
6740
7063
  }
@@ -6746,7 +7069,7 @@ function invoke_vijii(index,a1,a2,a3,a4) {
6746
7069
  getWasmTableEntry(index)(a1,a2,a3,a4);
6747
7070
  } catch(e) {
6748
7071
  stackRestore(sp);
6749
- if (e !== e+0) throw e;
7072
+ if (!(e instanceof EmscriptenEH)) throw e;
6750
7073
  _setThrew(1, 0);
6751
7074
  }
6752
7075
  }
@@ -6766,54 +7089,37 @@ function stackCheckInit() {
6766
7089
  writeStackCookie();
6767
7090
  }
6768
7091
 
6769
- function run() {
6770
-
6771
- if (runDependencies > 0) {
6772
- dependenciesFulfilled = run;
6773
- return;
6774
- }
7092
+ async function run() {
7093
+ assert(!calledRun);
7094
+ calledRun = true;
6775
7095
 
6776
7096
  stackCheckInit();
6777
7097
 
6778
7098
  preRun();
6779
7099
 
6780
- // a preRun added a dependency, run will be called later
6781
- if (runDependencies > 0) {
6782
- dependenciesFulfilled = run;
6783
- return;
7100
+ if (runDependencies) {
7101
+ await resolveRunDependencies();
6784
7102
  }
6785
7103
 
6786
- function doRun() {
6787
- // run may have just been called through dependencies being fulfilled just in this very frame,
6788
- // or while the async setStatus time below was happening
6789
- assert(!calledRun);
6790
- calledRun = true;
6791
- Module['calledRun'] = true;
6792
-
6793
- if (ABORT) return;
7104
+ var setStatus = Module['setStatus'];
7105
+ if (setStatus) {
7106
+ setStatus('Running...');
7107
+ // Yield to the event loop to allow the browser to paint "Running..."
7108
+ await new Promise((resolve) => setTimeout(resolve, 1));
7109
+ // Then we want to clear the status text, but only after the rest of this function runs.
7110
+ setTimeout(setStatus, 1, '');
7111
+ }
6794
7112
 
6795
- initRuntime();
7113
+ if (ABORT) return;
6796
7114
 
6797
- readyPromiseResolve?.(Module);
6798
- Module['onRuntimeInitialized']?.();
6799
- consumedModuleProp('onRuntimeInitialized');
7115
+ initRuntime();
6800
7116
 
6801
- assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
7117
+ Module['onRuntimeInitialized']?.();
7118
+ consumedModuleProp('onRuntimeInitialized');
6802
7119
 
6803
- postRun();
6804
- }
7120
+ assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
6805
7121
 
6806
- if (Module['setStatus']) {
6807
- Module['setStatus']('Running...');
6808
- setTimeout(() => {
6809
- setTimeout(() => Module['setStatus'](''), 1);
6810
- doRun();
6811
- }, 1);
6812
- } else
6813
- {
6814
- doRun();
6815
- }
6816
- checkStackCookie();
7122
+ postRun();
6817
7123
  }
6818
7124
 
6819
7125
  function checkUnflushedContent() {
@@ -6859,28 +7165,14 @@ var wasmExports;
6859
7165
 
6860
7166
  // In modularize mode the generated code is within a factory function so we
6861
7167
  // can use await here (since it's not top-level-await).
6862
- wasmExports = await (createWasm());
6863
-
6864
- run();
7168
+ wasmExports = await createWasm();
7169
+ await run();
6865
7170
 
6866
7171
  // end include: postamble.js
6867
7172
 
6868
7173
  // include: postamble_modularize.js
6869
7174
  // In MODULARIZE mode we wrap the generated code in a factory function
6870
7175
  // and return either the Module itself, or a promise of the module.
6871
- //
6872
- // We assign to the `moduleRtn` global here and configure closure to see
6873
- // this as an extern so it won't get minified.
6874
-
6875
- if (runtimeInitialized) {
6876
- moduleRtn = Module;
6877
- } else {
6878
- // Set up the promise that indicates the Module is initialized
6879
- moduleRtn = new Promise((resolve, reject) => {
6880
- readyPromiseResolve = resolve;
6881
- readyPromiseReject = reject;
6882
- });
6883
- }
6884
7176
 
6885
7177
  // Assertion for attempting to access module properties on the incoming
6886
7178
  // moduleArg. In the past we used this object as the prototype of the module
@@ -6901,7 +7193,7 @@ for (const prop of Object.keys(Module)) {
6901
7193
 
6902
7194
 
6903
7195
 
6904
- return moduleRtn;
7196
+ return Module;
6905
7197
  }
6906
7198
 
6907
7199
  // Export using a UMD style export, or ES6 exports if selected