funicular 0.2.1 → 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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -0
  3. data/README.md +2 -2
  4. data/Rakefile +23 -15
  5. data/demo/test_chartjs.html +8 -8
  6. data/demo/test_component.html +8 -8
  7. data/demo/test_error_boundary.html +8 -5
  8. data/demo/test_router.html +11 -11
  9. data/demo/tic-tac-toe.html +4 -4
  10. data/docs/architecture.md +80 -30
  11. data/lib/funicular/compiler.rb +13 -13
  12. data/lib/funicular/helpers/picoruby_helper.rb +24 -1
  13. data/lib/funicular/ssr/runtime.rb +3 -0
  14. data/lib/funicular/ssr.rb +2 -1
  15. data/lib/funicular/testing/node_runner.rb +1 -1
  16. data/lib/funicular/vendor/mrbc/VERSION +1 -0
  17. data/lib/funicular/vendor/{picorbc/picorbc.js → mrbc/mrbc.js} +626 -486
  18. data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
  19. data/lib/funicular/vendor/picoruby/VERSION +1 -1
  20. data/lib/funicular/vendor/picoruby/debug/init.iife.js +19 -4
  21. data/lib/funicular/vendor/picoruby/debug/picoruby.js +675 -449
  22. data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
  23. data/lib/funicular/vendor/picoruby/dist/init.iife.js +19 -4
  24. data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
  25. data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
  26. data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
  27. data/lib/funicular/vendor/picoruby-test-node/picoruby.js +860 -567
  28. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
  29. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +1 -1
  30. data/lib/funicular/version.rb +1 -1
  31. data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +25 -25
  32. data/lib/tasks/funicular.rake +1 -1
  33. data/minitest/commands_routes_test.rb +97 -0
  34. data/minitest/compiler_test.rb +195 -0
  35. data/minitest/configuration_test.rb +64 -0
  36. data/minitest/dsl_test.rb +237 -0
  37. data/minitest/fixtures/funicular_app/components/greeting_component.rb +2 -2
  38. data/minitest/funicular_test.rb +28 -2
  39. data/minitest/middleware_test.rb +154 -0
  40. data/minitest/picoruby_helper_test.rb +139 -0
  41. data/minitest/route_parser_test.rb +139 -0
  42. data/minitest/schema_test.rb +23 -0
  43. data/minitest/sig_tags_test.rb +30 -0
  44. data/minitest/ssr_test.rb +57 -0
  45. data/minitest/support/rails_stub.rb +59 -0
  46. data/minitest/test_helper.rb +20 -0
  47. data/minitest/testing_test.rb +267 -0
  48. data/minitest/view_context_test.rb +101 -0
  49. data/mrblib/0_tags.rb +62 -0
  50. data/mrblib/component.rb +255 -244
  51. data/mrblib/debug.rb +7 -6
  52. data/mrblib/differ.rb +3 -1
  53. data/mrblib/error_boundary.rb +11 -13
  54. data/mrblib/form_builder.rb +28 -24
  55. data/mrblib/funicular.rb +2 -1
  56. data/mrblib/html_serializer.rb +14 -13
  57. data/mrblib/http.rb +12 -1
  58. data/mrblib/patcher.rb +12 -9
  59. data/mrblib/router.rb +9 -5
  60. data/mrblib/runtime.rb +28 -0
  61. data/mrblib/styles.rb +107 -21
  62. data/mrblib/vdom.rb +90 -9
  63. data/mrblib/view_context.rb +106 -0
  64. data/sig/component.rbs +47 -84
  65. data/sig/form_builder.rbs +2 -1
  66. data/sig/html_serializer.rbs +2 -1
  67. data/sig/http.rbs +1 -0
  68. data/sig/patcher.rbs +1 -1
  69. data/sig/router.rbs +2 -13
  70. data/sig/runtime.rbs +13 -0
  71. data/sig/styles.rbs +19 -7
  72. data/sig/tags.rbs +54 -0
  73. data/sig/vdom.rbs +11 -2
  74. data/sig/view_context.rbs +60 -0
  75. metadata +22 -5
  76. data/lib/funicular/vendor/picorbc/VERSION +0 -1
  77. data/lib/funicular/vendor/picorbc/picorbc.wasm +0 -0
@@ -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;
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
+ }
369
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
  /**
@@ -755,6 +792,14 @@ async function createWasm() {
755
792
 
756
793
  var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
757
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
+ */
758
803
  var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
759
804
  var maxIdx = idx + maxBytesToRead;
760
805
  if (ignoreNul) return maxIdx;
@@ -799,7 +844,7 @@ async function createWasm() {
799
844
  if ((u0 & 0xF0) == 0xE0) {
800
845
  u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
801
846
  } else {
802
- 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!`);
803
848
  u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
804
849
  }
805
850
 
@@ -843,7 +888,7 @@ async function createWasm() {
843
888
  wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
844
889
  }
845
890
  /** @suppress {checkTypes} */
846
- assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
891
+ assert(wasmTable.get(funcPtr) == func, 'table mirror is out of date');
847
892
  return func;
848
893
  };
849
894
  var ___call_sighandler = (fp, sig) => getWasmTableEntry(fp)(sig);
@@ -862,15 +907,12 @@ async function createWasm() {
862
907
  // This block is not needed on v19+ since crypto.getRandomValues is builtin
863
908
  if (ENVIRONMENT_IS_NODE) {
864
909
  var nodeCrypto = require('node:crypto');
865
- return (view) => nodeCrypto.randomFillSync(view);
910
+ return (view) => (nodeCrypto.randomFillSync(view), 0);
866
911
  }
867
912
 
868
- return (view) => crypto.getRandomValues(view);
869
- };
870
- var randomFill = (view) => {
871
- // Lazily init on the first invocation.
872
- (randomFill = initRandomFill())(view);
913
+ return (view) => (crypto.getRandomValues(view), 0);
873
914
  };
915
+ var randomFill = (view) => (randomFill = initRandomFill())(view);
874
916
 
875
917
 
876
918
 
@@ -936,7 +978,7 @@ async function createWasm() {
936
978
  heap[outIdx++] = 0x80 | (u & 63);
937
979
  } else {
938
980
  if (outIdx + 3 >= endIdx) break;
939
- 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).`);
940
982
  heap[outIdx++] = 0xF0 | (u >> 18);
941
983
  heap[outIdx++] = 0x80 | ((u >> 12) & 63);
942
984
  heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1144,7 +1186,7 @@ async function createWasm() {
1144
1186
  var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
1145
1187
 
1146
1188
  var alignMemory = (size, alignment) => {
1147
- assert(alignment, "alignment argument is required");
1189
+ assert(alignment, 'alignment argument is required');
1148
1190
  return Math.ceil(size / alignment) * alignment;
1149
1191
  };
1150
1192
  var mmapAlloc = (size) => {
@@ -1217,11 +1259,14 @@ async function createWasm() {
1217
1259
  } else if (FS.isFile(node.mode)) {
1218
1260
  node.node_ops = MEMFS.ops_table.file.node;
1219
1261
  node.stream_ops = MEMFS.ops_table.file.stream;
1220
- node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
1221
- // 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
1222
- // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
1223
- // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
1224
- 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);
1225
1270
  } else if (FS.isLink(node.mode)) {
1226
1271
  node.node_ops = MEMFS.ops_table.link.node;
1227
1272
  node.stream_ops = MEMFS.ops_table.link.stream;
@@ -1238,36 +1283,30 @@ async function createWasm() {
1238
1283
  return node;
1239
1284
  },
1240
1285
  getFileDataAsTypedArray(node) {
1241
- if (!node.contents) return new Uint8Array(0);
1242
- if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1243
- 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.
1244
1288
  },
1245
1289
  expandFileStorage(node, newCapacity) {
1246
- var prevCapacity = node.contents ? node.contents.length : 0;
1290
+ var prevCapacity = node.contents.length;
1247
1291
  if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
1248
- // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
1249
- // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
1250
- // 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.
1251
1297
  var CAPACITY_DOUBLING_MAX = 1024 * 1024;
1252
1298
  newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
1253
- if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1254
- 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);
1255
1301
  node.contents = new Uint8Array(newCapacity); // Allocate new storage.
1256
- 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);
1257
1303
  },
1258
1304
  resizeFileStorage(node, newSize) {
1259
1305
  if (node.usedBytes == newSize) return;
1260
- if (newSize == 0) {
1261
- node.contents = null; // Fully decommit when requesting a resize to zero.
1262
- node.usedBytes = 0;
1263
- } else {
1264
- var oldContents = node.contents;
1265
- node.contents = new Uint8Array(newSize); // Allocate new storage.
1266
- if (oldContents) {
1267
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1268
- }
1269
- node.usedBytes = newSize;
1270
- }
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;
1271
1310
  },
1272
1311
  node_ops:{
1273
1312
  getattr(node) {
@@ -1367,16 +1406,11 @@ async function createWasm() {
1367
1406
  if (position >= stream.node.usedBytes) return 0;
1368
1407
  var size = Math.min(stream.node.usedBytes - position, length);
1369
1408
  assert(size >= 0);
1370
- if (size > 8 && contents.subarray) { // non-trivial, and typed array
1371
- buffer.set(contents.subarray(position, position + size), offset);
1372
- } else {
1373
- for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
1374
- }
1409
+ buffer.set(contents.subarray(position, position + size), offset);
1375
1410
  return size;
1376
1411
  },
1377
1412
  write(stream, buffer, offset, length, position, canOwn) {
1378
- // The data buffer should be a typed array view
1379
- assert(!(buffer instanceof ArrayBuffer));
1413
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
1380
1414
  // If the buffer is located in main memory (HEAP), and if
1381
1415
  // memory can grow, we can't hold on to references of the
1382
1416
  // memory buffer, as they may get invalidated. That means we
@@ -1389,33 +1423,19 @@ async function createWasm() {
1389
1423
  var node = stream.node;
1390
1424
  node.mtime = node.ctime = Date.now();
1391
1425
 
1392
- if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
1393
- if (canOwn) {
1394
- assert(position === 0, 'canOwn must imply no weird position inside the file');
1395
- node.contents = buffer.subarray(offset, offset + length);
1396
- node.usedBytes = length;
1397
- return length;
1398
- } 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.
1399
- node.contents = buffer.slice(offset, offset + length);
1400
- node.usedBytes = length;
1401
- return length;
1402
- } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
1403
- node.contents.set(buffer.subarray(offset, offset + length), position);
1404
- return length;
1405
- }
1406
- }
1407
-
1408
- // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
1409
- MEMFS.expandFileStorage(node, position+length);
1410
- 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);
1411
1435
  // Use typed array write which is available.
1412
1436
  node.contents.set(buffer.subarray(offset, offset + length), position);
1413
- } else {
1414
- for (var i = 0; i < length; i++) {
1415
- node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
1416
- }
1437
+ node.usedBytes = Math.max(node.usedBytes, position + length);
1417
1438
  }
1418
- node.usedBytes = Math.max(node.usedBytes, position + length);
1419
1439
  return length;
1420
1440
  },
1421
1441
  llseek(stream, offset, whence) {
@@ -1440,7 +1460,7 @@ async function createWasm() {
1440
1460
  var allocated;
1441
1461
  var contents = stream.node.contents;
1442
1462
  // Only make a new copy when MAP_PRIVATE is specified.
1443
- if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
1463
+ if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
1444
1464
  // We can't emulate MAP_SHARED when the file is not backed by the
1445
1465
  // buffer we're mapping to (e.g. the HEAP buffer).
1446
1466
  allocated = false;
@@ -1474,6 +1494,7 @@ async function createWasm() {
1474
1494
  };
1475
1495
 
1476
1496
  var FS_modeStringToFlags = (str) => {
1497
+ if (typeof str != 'string') return str;
1477
1498
  var flagModes = {
1478
1499
  'r': 0,
1479
1500
  'r+': 2,
@@ -1489,6 +1510,16 @@ async function createWasm() {
1489
1510
  return flags;
1490
1511
  };
1491
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
+
1492
1523
  var FS_getMode = (canRead, canWrite) => {
1493
1524
  var mode = 0;
1494
1525
  if (canRead) mode |= 292 | 73;
@@ -1782,7 +1813,11 @@ async function createWasm() {
1782
1813
  if (attr.mode != null && attr.dontFollow) {
1783
1814
  throw new FS.ErrnoError(52);
1784
1815
  }
1785
- 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);
1786
1821
  },
1787
1822
  lookup(parent, name) {
1788
1823
  var path = PATH.join2(NODEFS.realPath(parent), name);
@@ -1914,6 +1949,70 @@ async function createWasm() {
1914
1949
 
1915
1950
 
1916
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
+ };
1917
2016
  var NODERAWFS = {
1918
2017
  lookup(parent, name) {
1919
2018
  assert(parent)
@@ -1929,11 +2028,10 @@ async function createWasm() {
1929
2028
  return { path, node: { id: st.ino, mode, node_ops: NODERAWFS, path }};
1930
2029
  },
1931
2030
  createStandardStreams() {
1932
- // FIXME: tty is set to true to appease isatty(), the underlying ioctl syscalls still need to be implemented, see issue #22264.
1933
- 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);
1934
2032
  var paths = [,'/dev/stdout', '/dev/stderr'];
1935
2033
  for (var i = 1; i < 3; i++) {
1936
- 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);
1937
2035
  }
1938
2036
  },
1939
2037
  cwd() { return process.cwd(); },
@@ -1947,6 +2045,14 @@ async function createWasm() {
1947
2045
  },
1948
2046
  mkdir(...args) { fs.mkdirSync(...args); },
1949
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
+ },
1950
2056
  rename(...args) { fs.renameSync(...args); },
1951
2057
  rmdir(...args) { fs.rmdirSync(...args); },
1952
2058
  readdir(...args) { return ['.', '..'].concat(fs.readdirSync(...args)); },
@@ -1963,6 +2069,12 @@ async function createWasm() {
1963
2069
  },
1964
2070
  fstat(fd) {
1965
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
+ }
1966
2078
  return fs.fstatSync(stream.nfd);
1967
2079
  },
1968
2080
  statfs(path) {
@@ -2016,21 +2128,23 @@ async function createWasm() {
2016
2128
  var stream = FS.getStreamChecked(fd);
2017
2129
  fs.ftruncateSync(stream.nfd, len);
2018
2130
  },
2019
- utime(path, atime, mtime) {
2131
+ utime(path, atime, mtime, dontFollow) {
2020
2132
  // null here for atime or mtime means UTIME_OMIT was passed. Since node
2021
2133
  // doesn't support this concept we need to first find the existing
2022
2134
  // timestamps in order to preserve them.
2023
2135
  if ((atime === null) || (mtime === null)) {
2024
- var st = fs.statSync(path);
2136
+ var st = dontFollow ? fs.lstatSync(path) : fs.statSync(path);
2025
2137
  atime ||= st.atimeMs;
2026
2138
  mtime ||= st.mtimeMs;
2027
2139
  }
2028
- 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
+ }
2029
2145
  },
2030
2146
  open(path, flags, mode) {
2031
- if (typeof flags == "string") {
2032
- flags = FS_modeStringToFlags(flags)
2033
- }
2147
+ flags = FS_modeStringToFlags(flags);
2034
2148
  var pathTruncated = path.split('/').map((s) => s.slice(0, 255)).join('/');
2035
2149
  var nfd = fs.openSync(pathTruncated, NODEFS.flagsForNode(flags), mode);
2036
2150
  var st = fs.fstatSync(nfd);
@@ -2045,96 +2159,14 @@ async function createWasm() {
2045
2159
  createStream(stream, fd) {
2046
2160
  // Call the original FS.createStream
2047
2161
  var rtn = VFS.createStream(stream, fd);
2048
- if (typeof rtn.shared.refcnt == 'undefined') {
2049
- rtn.shared.refcnt = 1;
2050
- } else {
2162
+ // Detect PIPEFS streams and skip the refcnt/tty initialization in that case.
2163
+ if (!stream.stream_ops) {
2164
+ rtn.shared.refcnt ??= 0;
2051
2165
  rtn.shared.refcnt++;
2166
+ rtn.tty = nodeTTY.isatty(rtn.nfd);
2052
2167
  }
2053
2168
  return rtn;
2054
2169
  },
2055
- close(stream) {
2056
- VFS.closeStream(stream.fd);
2057
- // Don't close stdin/stdout/stderr since they are used by node itself.
2058
- if (!stream.stream_ops && --stream.shared.refcnt <= 0 && stream.nfd > 2) {
2059
- // This stream is created by our Node.js filesystem, close the
2060
- // native file descriptor when its reference count drops to 0.
2061
- fs.closeSync(stream.nfd);
2062
- }
2063
- },
2064
- llseek(stream, offset, whence) {
2065
- if (stream.stream_ops) {
2066
- // this stream is created by in-memory filesystem
2067
- return VFS.llseek(stream, offset, whence);
2068
- }
2069
- var position = offset;
2070
- if (whence === 1) {
2071
- position += stream.position;
2072
- } else if (whence === 2) {
2073
- position += fs.fstatSync(stream.nfd).size;
2074
- } else if (whence !== 0) {
2075
- throw new FS.ErrnoError(28);
2076
- }
2077
-
2078
- if (position < 0) {
2079
- throw new FS.ErrnoError(28);
2080
- }
2081
- stream.position = position;
2082
- return position;
2083
- },
2084
- read(stream, buffer, offset, length, position) {
2085
- if (stream.stream_ops) {
2086
- // this stream is created by in-memory filesystem
2087
- return VFS.read(stream, buffer, offset, length, position);
2088
- }
2089
- var seeking = typeof position != 'undefined';
2090
- if (!seeking && stream.seekable) position = stream.position;
2091
- var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
2092
- // update position marker when non-seeking
2093
- if (!seeking) stream.position += bytesRead;
2094
- return bytesRead;
2095
- },
2096
- write(stream, buffer, offset, length, position) {
2097
- if (stream.stream_ops) {
2098
- // this stream is created by in-memory filesystem
2099
- return VFS.write(stream, buffer, offset, length, position);
2100
- }
2101
- if (stream.flags & +"1024") {
2102
- // seek to the end before writing in append mode
2103
- FS.llseek(stream, 0, +"2");
2104
- }
2105
- var seeking = typeof position != 'undefined';
2106
- if (!seeking && stream.seekable) position = stream.position;
2107
- var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
2108
- // update position marker when non-seeking
2109
- if (!seeking) stream.position += bytesWritten;
2110
- return bytesWritten;
2111
- },
2112
- mmap(stream, length, position, prot, flags) {
2113
- if (!length) {
2114
- throw new FS.ErrnoError(28);
2115
- }
2116
- if (stream.stream_ops) {
2117
- // this stream is created by in-memory filesystem
2118
- return VFS.mmap(stream, length, position, prot, flags);
2119
- }
2120
-
2121
- var ptr = mmapAlloc(length);
2122
- FS.read(stream, HEAP8, ptr, length, position);
2123
- return { ptr, allocated: true };
2124
- },
2125
- msync(stream, buffer, offset, length, mmapFlags) {
2126
- if (stream.stream_ops) {
2127
- // this stream is created by in-memory filesystem
2128
- return VFS.msync(stream, buffer, offset, length, mmapFlags);
2129
- }
2130
-
2131
- FS.write(stream, buffer, 0, length, offset);
2132
- // should we check if bytesWritten and length are the same?
2133
- return 0;
2134
- },
2135
- ioctl() {
2136
- throw new FS.ErrnoError(59);
2137
- },
2138
2170
  };
2139
2171
 
2140
2172
 
@@ -2159,10 +2191,12 @@ async function createWasm() {
2159
2191
  }
2160
2192
  };
2161
2193
 
2194
+ var dependenciesPromise = null;
2195
+ var resolveRunDependencies = async () => dependenciesPromise;
2162
2196
  var runDependencies = 0;
2163
2197
 
2164
2198
 
2165
- var dependenciesFulfilled = null;
2199
+ var dependenciesPromiseResolve = null;
2166
2200
 
2167
2201
  var runDependencyTracking = {
2168
2202
  };
@@ -2176,21 +2210,22 @@ async function createWasm() {
2176
2210
  assert(id, 'removeRunDependency requires an ID');
2177
2211
  assert(runDependencyTracking[id]);
2178
2212
  delete runDependencyTracking[id];
2179
- if (runDependencies == 0) {
2213
+ if (!runDependencies) {
2180
2214
  if (runDependencyWatcher !== null) {
2181
2215
  clearInterval(runDependencyWatcher);
2182
2216
  runDependencyWatcher = null;
2183
2217
  }
2184
- if (dependenciesFulfilled) {
2185
- var callback = dependenciesFulfilled;
2186
- dependenciesFulfilled = null;
2187
- callback(); // can add another dependenciesFulfilled
2188
- }
2218
+ dependenciesPromiseResolve();
2189
2219
  }
2190
2220
  };
2191
2221
 
2192
2222
 
2223
+
2224
+
2193
2225
  var addRunDependency = (id) => {
2226
+ if (!runDependencies) {
2227
+ dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve);
2228
+ }
2194
2229
  runDependencies++;
2195
2230
 
2196
2231
  Module['monitorRunDependencies']?.(runDependencies);
@@ -2363,6 +2398,48 @@ async function createWasm() {
2363
2398
  get isDevice() {
2364
2399
  return FS.isChrdev(this.mode);
2365
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
+ }
2366
2443
  },
2367
2444
  lookupPath(path, opts = {}) {
2368
2445
  if (!path) {
@@ -2374,7 +2451,7 @@ async function createWasm() {
2374
2451
  path = FS.cwd() + '/' + path;
2375
2452
  }
2376
2453
 
2377
- // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
2454
+ // limit max consecutive symlinks to SYMLOOP_MAX.
2378
2455
  linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
2379
2456
  // split the absolute path
2380
2457
  var parts = path.split('/').filter((p) => !!p);
@@ -2666,7 +2743,14 @@ async function createWasm() {
2666
2743
  var arg = setattr ? stream : node;
2667
2744
  setattr ??= node.node_ops.setattr;
2668
2745
  FS.checkOpExists(setattr, 63)
2669
- 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
+ }
2670
2754
  },
2671
2755
  chrdev_stream_ops:{
2672
2756
  open(stream) {
@@ -2933,6 +3017,25 @@ async function createWasm() {
2933
3017
  }
2934
3018
  return parent.node_ops.symlink(parent, newname, oldpath);
2935
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
+ },
2936
3039
  rename(old_path, new_path) {
2937
3040
  var old_dirname = PATH.dirname(old_path);
2938
3041
  var new_dirname = PATH.dirname(new_path);
@@ -3179,20 +3282,19 @@ async function createWasm() {
3179
3282
  }
3180
3283
  FS.doTruncate(stream, stream.node, len);
3181
3284
  },
3182
- utime(path, atime, mtime) {
3183
- var lookup = FS.lookupPath(path, { follow: true });
3184
- var node = lookup.node;
3185
- var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
3186
- setattr(node, {
3285
+ utime(path, atime, mtime, dontFollow) {
3286
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
3287
+ FS.doSetAttr(null, lookup.node, {
3187
3288
  atime: atime,
3188
- mtime: mtime
3289
+ mtime: mtime,
3290
+ dontFollow
3189
3291
  });
3190
3292
  },
3191
3293
  open(path, flags, mode = 0o666) {
3192
3294
  if (path === "") {
3193
3295
  throw new FS.ErrnoError(44);
3194
3296
  }
3195
- flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags;
3297
+ flags = FS_modeStringToFlags(flags);
3196
3298
  if ((flags & 64)) {
3197
3299
  mode = (mode & 4095) | 32768;
3198
3300
  } else {
@@ -3286,6 +3388,11 @@ async function createWasm() {
3286
3388
  throw new FS.ErrnoError(8);
3287
3389
  }
3288
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);
3289
3396
  try {
3290
3397
  if (stream.stream_ops.close) {
3291
3398
  stream.stream_ops.close(stream);
@@ -3343,6 +3450,7 @@ async function createWasm() {
3343
3450
  },
3344
3451
  write(stream, buffer, offset, length, position, canOwn) {
3345
3452
  assert(offset >= 0);
3453
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
3346
3454
  if (length < 0 || position < 0) {
3347
3455
  throw new FS.ErrnoError(28);
3348
3456
  }
@@ -3409,8 +3517,8 @@ async function createWasm() {
3409
3517
  return stream.stream_ops.ioctl(stream, cmd, arg);
3410
3518
  },
3411
3519
  readFile(path, opts = {}) {
3412
- opts.flags = opts.flags || 0;
3413
- opts.encoding = opts.encoding || 'binary';
3520
+ opts.flags = opts.flags ?? 0;
3521
+ opts.encoding = opts.encoding ?? 'binary';
3414
3522
  if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
3415
3523
  abort(`Invalid encoding type "${opts.encoding}"`);
3416
3524
  }
@@ -3426,16 +3534,10 @@ async function createWasm() {
3426
3534
  return buf;
3427
3535
  },
3428
3536
  writeFile(path, data, opts = {}) {
3429
- opts.flags = opts.flags || 577;
3537
+ opts.flags = opts.flags ?? 577;
3430
3538
  var stream = FS.open(path, opts.flags, opts.mode);
3431
- if (typeof data == 'string') {
3432
- data = new Uint8Array(intArrayFromString(data, true));
3433
- }
3434
- if (ArrayBuffer.isView(data)) {
3435
- FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3436
- } else {
3437
- abort('Unsupported data type');
3438
- }
3539
+ data = FS_fileDataToTypedArray(data);
3540
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3439
3541
  FS.close(stream);
3440
3542
  },
3441
3543
  cwd:() => FS.currentPath,
@@ -3661,11 +3763,7 @@ async function createWasm() {
3661
3763
  var mode = FS_getMode(canRead, canWrite);
3662
3764
  var node = FS.create(path, mode);
3663
3765
  if (data) {
3664
- if (typeof data == 'string') {
3665
- var arr = new Array(data.length);
3666
- for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
3667
- data = arr;
3668
- }
3766
+ data = FS_fileDataToTypedArray(data);
3669
3767
  // make sure we can write to the file
3670
3768
  FS.chmod(node, mode | 146);
3671
3769
  var stream = FS.open(node, 577);
@@ -3774,8 +3872,8 @@ async function createWasm() {
3774
3872
 
3775
3873
  // Function to get a range from the remote URL.
3776
3874
  var doXHR = (from, to) => {
3777
- if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
3778
- 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!`);
3779
3877
 
3780
3878
  // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
3781
3879
  var xhr = new XMLHttpRequest();
@@ -3793,7 +3891,7 @@ async function createWasm() {
3793
3891
  if (xhr.response !== undefined) {
3794
3892
  return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
3795
3893
  }
3796
- return intArrayFromString(xhr.responseText || '', true);
3894
+ return intArrayFromString(xhr.responseText ?? '', true);
3797
3895
  };
3798
3896
  var lazyArray = this;
3799
3897
  lazyArray.setDataGetter((chunkNum) => {
@@ -3900,27 +3998,10 @@ async function createWasm() {
3900
3998
  node.stream_ops = stream_ops;
3901
3999
  return node;
3902
4000
  },
3903
- absolutePath() {
3904
- abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
3905
- },
3906
- createFolder() {
3907
- abort('FS.createFolder has been removed; use FS.mkdir instead');
3908
- },
3909
- createLink() {
3910
- abort('FS.createLink has been removed; use FS.symlink instead');
3911
- },
3912
- joinPath() {
3913
- abort('FS.joinPath has been removed; use PATH.join instead');
3914
- },
3915
- mmapAlloc() {
3916
- abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
3917
- },
3918
- standardizePath() {
3919
- abort('FS.standardizePath has been removed; use PATH.normalize instead');
3920
- },
3921
4001
  };
3922
4002
 
3923
4003
  var SYSCALLS = {
4004
+ currentUmask:18,
3924
4005
  calculateAt(dirfd, path, allowEmpty) {
3925
4006
  if (PATH.isAbs(path)) {
3926
4007
  return path;
@@ -3983,7 +4064,7 @@ async function createWasm() {
3983
4064
  // MAP_PRIVATE calls need not to be synced back to underlying fs
3984
4065
  return 0;
3985
4066
  }
3986
- var buffer = HEAPU8.slice(addr, addr + len);
4067
+ var buffer = HEAPU8.subarray(addr, addr + len);
3987
4068
  FS.msync(stream, buffer, offset, len, flags);
3988
4069
  },
3989
4070
  getStreamFromFD(fd) {
@@ -4007,6 +4088,7 @@ async function createWasm() {
4007
4088
  return -e.errno;
4008
4089
  }
4009
4090
  }
4091
+
4010
4092
 
4011
4093
  function ___syscall_chmod(path, mode) {
4012
4094
  try {
@@ -4019,6 +4101,7 @@ async function createWasm() {
4019
4101
  return -e.errno;
4020
4102
  }
4021
4103
  }
4104
+
4022
4105
 
4023
4106
  function ___syscall_dup(fd) {
4024
4107
  try {
@@ -4030,23 +4113,29 @@ async function createWasm() {
4030
4113
  return -e.errno;
4031
4114
  }
4032
4115
  }
4116
+
4033
4117
 
4034
4118
  function ___syscall_dup3(fd, newfd, flags) {
4035
4119
  try {
4036
4120
 
4121
+ if (fd === newfd) return -28;
4122
+ if (flags & ~524288) return -28;
4037
4123
  var old = SYSCALLS.getStreamFromFD(fd);
4038
- assert(!flags);
4039
- if (old.fd === newfd) return -28;
4040
4124
  // Check newfd is within range of valid open file descriptors.
4041
4125
  if (newfd < 0 || newfd >= FS.MAX_OPEN_FDS) return -8;
4042
4126
  var existing = FS.getStream(newfd);
4043
4127
  if (existing) FS.close(existing);
4044
- 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;
4045
4133
  } catch (e) {
4046
4134
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4047
4135
  return -e.errno;
4048
4136
  }
4049
4137
  }
4138
+
4050
4139
 
4051
4140
  var syscallGetVarargI = () => {
4052
4141
  assert(SYSCALLS.varargs != undefined);
@@ -4083,7 +4172,8 @@ async function createWasm() {
4083
4172
  return stream.flags;
4084
4173
  case 4: {
4085
4174
  var arg = syscallGetVarargI();
4086
- stream.flags |= arg;
4175
+ var mask = 289792;
4176
+ stream.flags = (stream.flags & ~mask) | (arg & mask);
4087
4177
  return 0;
4088
4178
  }
4089
4179
  case 12: {
@@ -4107,6 +4197,7 @@ async function createWasm() {
4107
4197
  return -e.errno;
4108
4198
  }
4109
4199
  }
4200
+
4110
4201
 
4111
4202
  function ___syscall_fstat64(fd, buf) {
4112
4203
  try {
@@ -4117,6 +4208,7 @@ async function createWasm() {
4117
4208
  return -e.errno;
4118
4209
  }
4119
4210
  }
4211
+
4120
4212
 
4121
4213
  var INT53_MAX = 9007199254740992;
4122
4214
 
@@ -4128,7 +4220,7 @@ async function createWasm() {
4128
4220
 
4129
4221
  try {
4130
4222
 
4131
- if (isNaN(length)) return -61;
4223
+ if (isNaN(length)) return -22;
4132
4224
  FS.ftruncate(fd, length);
4133
4225
  return 0;
4134
4226
  } catch (e) {
@@ -4140,7 +4232,7 @@ async function createWasm() {
4140
4232
 
4141
4233
 
4142
4234
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
4143
- 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');
4144
4236
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
4145
4237
  };
4146
4238
  function ___syscall_getcwd(buf, size) {
@@ -4157,6 +4249,7 @@ async function createWasm() {
4157
4249
  return -e.errno;
4158
4250
  }
4159
4251
  }
4252
+
4160
4253
 
4161
4254
 
4162
4255
  function ___syscall_getdents64(fd, dirp, count) {
@@ -4217,6 +4310,7 @@ async function createWasm() {
4217
4310
  return -e.errno;
4218
4311
  }
4219
4312
  }
4313
+
4220
4314
 
4221
4315
 
4222
4316
  function ___syscall_ioctl(fd, op, varargs) {
@@ -4314,6 +4408,7 @@ async function createWasm() {
4314
4408
  return -e.errno;
4315
4409
  }
4316
4410
  }
4411
+
4317
4412
 
4318
4413
  function ___syscall_lstat64(path, buf) {
4319
4414
  try {
@@ -4325,12 +4420,14 @@ async function createWasm() {
4325
4420
  return -e.errno;
4326
4421
  }
4327
4422
  }
4423
+
4328
4424
 
4329
4425
  function ___syscall_mkdirat(dirfd, path, mode) {
4330
4426
  try {
4331
4427
 
4332
4428
  path = SYSCALLS.getStr(path);
4333
4429
  path = SYSCALLS.calculateAt(dirfd, path);
4430
+ mode &= ~SYSCALLS.currentUmask;
4334
4431
  FS.mkdir(path, mode, 0);
4335
4432
  return 0;
4336
4433
  } catch (e) {
@@ -4338,6 +4435,7 @@ async function createWasm() {
4338
4435
  return -e.errno;
4339
4436
  }
4340
4437
  }
4438
+
4341
4439
 
4342
4440
  function ___syscall_newfstatat(dirfd, path, buf, flags) {
4343
4441
  try {
@@ -4354,6 +4452,7 @@ async function createWasm() {
4354
4452
  return -e.errno;
4355
4453
  }
4356
4454
  }
4455
+
4357
4456
 
4358
4457
 
4359
4458
  function ___syscall_openat(dirfd, path, flags, varargs) {
@@ -4363,12 +4462,16 @@ async function createWasm() {
4363
4462
  path = SYSCALLS.getStr(path);
4364
4463
  path = SYSCALLS.calculateAt(dirfd, path);
4365
4464
  var mode = varargs ? syscallGetVarargI() : 0;
4465
+ if (flags & 64) {
4466
+ mode &= ~SYSCALLS.currentUmask;
4467
+ }
4366
4468
  return FS.open(path, flags, mode).fd;
4367
4469
  } catch (e) {
4368
4470
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4369
4471
  return -e.errno;
4370
4472
  }
4371
4473
  }
4474
+
4372
4475
 
4373
4476
  var PIPEFS = {
4374
4477
  BUCKET_BUFFER_SIZE:8192,
@@ -4380,9 +4483,15 @@ async function createWasm() {
4380
4483
  createPipe() {
4381
4484
  var pipe = {
4382
4485
  buckets: [],
4383
- // refcnt 2 because pipe has a read end and a write end. We need to be
4384
- // able to read from the read end after write end is closed.
4385
- 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,
4386
4495
  timestamp: new Date(),
4387
4496
  };
4388
4497
 
@@ -4399,6 +4508,10 @@ async function createWasm() {
4399
4508
 
4400
4509
  rNode.pipe = pipe;
4401
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;
4402
4515
 
4403
4516
  var readableStream = FS.createStream({
4404
4517
  path: rName,
@@ -4443,24 +4556,50 @@ async function createWasm() {
4443
4556
  blocks: 0,
4444
4557
  };
4445
4558
  },
4446
- poll(stream, timeout, notifyCallback) {
4559
+ poll(stream) {
4447
4560
  var pipe = stream.node.pipe;
4448
4561
 
4449
4562
  if ((stream.flags & 2097155) === 1) {
4450
- 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;
4451
4570
  }
4571
+ var mask = 0;
4452
4572
  for (var bucket of pipe.buckets) {
4453
4573
  if (bucket.offset - bucket.roffset > 0) {
4454
- return (64 | 1);
4574
+ mask = 64 | 1;
4575
+ break;
4455
4576
  }
4456
4577
  }
4457
-
4458
- 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;
4459
4584
  },
4460
4585
  dup(stream) {
4461
- 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
+ }
4462
4592
  },
4463
- 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
+ }
4464
4603
  return 28;
4465
4604
  },
4466
4605
  fsync(stream) {
@@ -4553,6 +4692,7 @@ async function createWasm() {
4553
4692
  if (freeBytesInCurrBuffer >= dataLen) {
4554
4693
  currBucket.buffer.set(data, currBucket.offset);
4555
4694
  currBucket.offset += dataLen;
4695
+ pipe.readNode.notifyListeners(64 | 1);
4556
4696
  return dataLen;
4557
4697
  } else if (freeBytesInCurrBuffer > 0) {
4558
4698
  currBucket.buffer.set(data.subarray(0, freeBytesInCurrBuffer), currBucket.offset);
@@ -4584,12 +4724,25 @@ async function createWasm() {
4584
4724
  newBucket.buffer.set(data);
4585
4725
  }
4586
4726
 
4727
+ pipe.readNode.notifyListeners(64 | 1);
4587
4728
  return dataLen;
4588
4729
  },
4589
4730
  close(stream) {
4590
4731
  var pipe = stream.node.pipe;
4591
- pipe.refcnt--;
4592
- 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) {
4593
4746
  pipe.buckets = null;
4594
4747
  }
4595
4748
  },
@@ -4601,15 +4754,24 @@ async function createWasm() {
4601
4754
  return 'pipe[' + (PIPEFS.nextname.current++) + ']';
4602
4755
  },
4603
4756
  };
4604
- function ___syscall_pipe(fdPtr) {
4757
+ function ___syscall_pipe2(fdPtr, flags) {
4605
4758
  try {
4606
4759
 
4607
4760
  if (fdPtr == 0) {
4608
4761
  throw new FS.ErrnoError(21);
4609
4762
  }
4763
+ var validFlags = 524288 | 2048;
4764
+ if (flags & ~validFlags) {
4765
+ throw new FS.ErrnoError(138);
4766
+ }
4610
4767
 
4611
4768
  var res = PIPEFS.createPipe();
4612
4769
 
4770
+ if (flags & 2048) {
4771
+ FS.getStream(res.readable_fd).flags |= 2048;
4772
+ FS.getStream(res.writable_fd).flags |= 2048;
4773
+ }
4774
+
4613
4775
  HEAP32[((fdPtr)>>2)] = res.readable_fd;
4614
4776
  HEAP32[(((fdPtr)+(4))>>2)] = res.writable_fd;
4615
4777
 
@@ -4619,30 +4781,33 @@ async function createWasm() {
4619
4781
  return -e.errno;
4620
4782
  }
4621
4783
  }
4622
-
4623
- function ___syscall_poll(fds, nfds, timeout) {
4624
- try {
4625
-
4626
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) => {
4627
4797
  var count = 0;
4628
- for (var i = 0; i < nfds; i++) {
4629
- var pollfd = fds + 8 * i;
4630
- var fd = HEAP32[((pollfd)>>2)];
4631
- var events = HEAP16[(((pollfd)+(4))>>1)];
4632
- var flags = 32;
4633
- var stream = FS.getStream(fd);
4634
- if (stream) {
4635
- if (stream.stream_ops.poll) {
4636
- flags = stream.stream_ops.poll(stream, -1);
4637
- } else {
4638
- flags = 5;
4639
- }
4640
- }
4641
- flags &= events | 8 | 16;
4642
- if (flags) count++;
4643
- 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;
4644
4804
  }
4805
+ return count;
4806
+ };
4807
+ function ___syscall_poll(fds, nfds, timeout) {
4808
+ try {
4645
4809
 
4810
+ var count = doPollSync(fds, nfds);
4646
4811
  if (!count && timeout != 0) warnOnce('non-zero poll() timeout not supported: ' + timeout)
4647
4812
  return count;
4648
4813
  } catch (e) {
@@ -4650,6 +4815,18 @@ async function createWasm() {
4650
4815
  return -e.errno;
4651
4816
  }
4652
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
+
4653
4830
 
4654
4831
 
4655
4832
 
@@ -4673,6 +4850,7 @@ async function createWasm() {
4673
4850
  return -e.errno;
4674
4851
  }
4675
4852
  }
4853
+
4676
4854
 
4677
4855
  function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
4678
4856
  try {
@@ -4688,6 +4866,7 @@ async function createWasm() {
4688
4866
  return -e.errno;
4689
4867
  }
4690
4868
  }
4869
+
4691
4870
 
4692
4871
  function ___syscall_rmdir(path) {
4693
4872
  try {
@@ -4700,6 +4879,7 @@ async function createWasm() {
4700
4879
  return -e.errno;
4701
4880
  }
4702
4881
  }
4882
+
4703
4883
 
4704
4884
  function ___syscall_stat64(path, buf) {
4705
4885
  try {
@@ -4711,6 +4891,7 @@ async function createWasm() {
4711
4891
  return -e.errno;
4712
4892
  }
4713
4893
  }
4894
+
4714
4895
 
4715
4896
  function ___syscall_symlinkat(target, dirfd, linkpath) {
4716
4897
  try {
@@ -4725,6 +4906,20 @@ async function createWasm() {
4725
4906
  return -e.errno;
4726
4907
  }
4727
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
+
4728
4923
 
4729
4924
  function ___syscall_unlinkat(dirfd, path, flags) {
4730
4925
  try {
@@ -4744,6 +4939,7 @@ async function createWasm() {
4744
4939
  return -e.errno;
4745
4940
  }
4746
4941
  }
4942
+
4747
4943
 
4748
4944
  var __abort_js = () =>
4749
4945
  abort('native code called abort()');
@@ -4755,7 +4951,7 @@ async function createWasm() {
4755
4951
  };
4756
4952
 
4757
4953
  var __emscripten_throw_longjmp = () => {
4758
- throw Infinity;
4954
+ throw new EmscriptenSjLj;
4759
4955
  };
4760
4956
 
4761
4957
  var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0);
@@ -4776,6 +4972,9 @@ async function createWasm() {
4776
4972
 
4777
4973
 
4778
4974
  var date = new Date(time*1000);
4975
+ if (isNaN(date.getTime())) {
4976
+ return 1;
4977
+ }
4779
4978
  HEAP32[((tmPtr)>>2)] = date.getSeconds();
4780
4979
  HEAP32[(((tmPtr)+(4))>>2)] = date.getMinutes();
4781
4980
  HEAP32[(((tmPtr)+(8))>>2)] = date.getHours();
@@ -4794,6 +4993,7 @@ async function createWasm() {
4794
4993
  var winterOffset = start.getTimezoneOffset();
4795
4994
  var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0;
4796
4995
  HEAP32[(((tmPtr)+(32))>>2)] = dst;
4996
+ return 0;
4797
4997
  ;
4798
4998
  }
4799
4999
 
@@ -4808,6 +5008,9 @@ async function createWasm() {
4808
5008
  HEAP32[(((tmPtr)+(4))>>2)],
4809
5009
  HEAP32[((tmPtr)>>2)],
4810
5010
  0);
5011
+ if (isNaN(date.getTime())) {
5012
+ return -1;
5013
+ }
4811
5014
 
4812
5015
  // There's an ambiguous hour when the time goes back; the tm_isdst field is
4813
5016
  // used to disambiguate it. Date() basically guesses, so we fix it up if it
@@ -4820,14 +5023,18 @@ async function createWasm() {
4820
5023
  var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South
4821
5024
  if (dst < 0) {
4822
5025
  // Attention: some regions don't have DST at all.
4823
- HEAP32[(((tmPtr)+(32))>>2)] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
5026
+ dst = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
4824
5027
  } else if ((dst > 0) != (dstOffset == guessedOffset)) {
4825
5028
  var nonDstOffset = Math.max(winterOffset, summerOffset);
4826
5029
  var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
4827
5030
  // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up.
4828
5031
  date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000);
5032
+ if (isNaN(date.getTime())) {
5033
+ return -1;
5034
+ }
4829
5035
  }
4830
5036
 
5037
+ HEAP32[(((tmPtr)+(32))>>2)] = dst;
4831
5038
  HEAP32[(((tmPtr)+(24))>>2)] = date.getDay();
4832
5039
  var yday = ydayFromDate(date)|0;
4833
5040
  HEAP32[(((tmPtr)+(28))>>2)] = yday;
@@ -4839,12 +5046,8 @@ async function createWasm() {
4839
5046
  HEAP32[(((tmPtr)+(16))>>2)] = date.getMonth();
4840
5047
  HEAP32[(((tmPtr)+(20))>>2)] = date.getYear();
4841
5048
 
4842
- var timeMs = date.getTime();
4843
- if (isNaN(timeMs)) {
4844
- return -1;
4845
- }
4846
- // Return time in microseconds
4847
- return timeMs / 1000;
5049
+ // Return time in seconds
5050
+ return date.getTime() / 1000;
4848
5051
  })();
4849
5052
  return BigInt(ret);
4850
5053
  };
@@ -5076,11 +5279,10 @@ async function createWasm() {
5076
5279
  var ENV = {
5077
5280
  };
5078
5281
 
5079
- var getExecutableName = () => thisProgram || './this.program';
5282
+ var getExecutableName = () => thisProgram;
5080
5283
  var getEnvStrings = () => {
5081
5284
  if (!getEnvStrings.strings) {
5082
5285
  // Default values.
5083
- // Browser language detection #8751
5084
5286
  var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8';
5085
5287
  var env = {
5086
5288
  'USER': 'web_user',
@@ -5157,7 +5359,6 @@ async function createWasm() {
5157
5359
  // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
5158
5360
  if (keepRuntimeAlive() && !implicit) {
5159
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)`;
5160
- readyPromiseReject?.(msg);
5161
5362
  err(msg);
5162
5363
  }
5163
5364
 
@@ -5176,6 +5377,7 @@ async function createWasm() {
5176
5377
  return e.errno;
5177
5378
  }
5178
5379
  }
5380
+
5179
5381
 
5180
5382
  function _fd_fdstat_get(fd, pbuf) {
5181
5383
  try {
@@ -5202,6 +5404,7 @@ async function createWasm() {
5202
5404
  return e.errno;
5203
5405
  }
5204
5406
  }
5407
+
5205
5408
 
5206
5409
  /** @param {number=} offset */
5207
5410
  var doReadv = (stream, iov, iovcnt, offset) => {
@@ -5210,7 +5413,18 @@ async function createWasm() {
5210
5413
  var ptr = HEAPU32[((iov)>>2)];
5211
5414
  var len = HEAPU32[(((iov)+(4))>>2)];
5212
5415
  iov += 8;
5213
- 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
+ }
5214
5428
  if (curr < 0) return -1;
5215
5429
  ret += curr;
5216
5430
  if (curr < len) break; // nothing more to read
@@ -5228,7 +5442,7 @@ async function createWasm() {
5228
5442
 
5229
5443
  try {
5230
5444
 
5231
- if (isNaN(offset)) return 61;
5445
+ if (isNaN(offset)) return 22;
5232
5446
  var stream = SYSCALLS.getStreamFromFD(fd)
5233
5447
  var num = doReadv(stream, iov, iovcnt, offset);
5234
5448
  HEAPU32[((pnum)>>2)] = num;
@@ -5242,23 +5456,27 @@ async function createWasm() {
5242
5456
 
5243
5457
  /** @param {number=} offset */
5244
5458
  var doWritev = (stream, iov, iovcnt, offset) => {
5245
- var ret = 0;
5246
- 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) {
5247
5474
  var ptr = HEAPU32[((iov)>>2)];
5248
5475
  var len = HEAPU32[(((iov)+(4))>>2)];
5249
- iov += 8;
5250
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
5251
- if (curr < 0) return -1;
5252
- ret += curr;
5253
- if (curr < len) {
5254
- // No more space to write.
5255
- break;
5256
- }
5257
- if (typeof offset != 'undefined') {
5258
- offset += curr;
5259
- }
5476
+ view.set(HEAPU8.subarray(ptr, ptr + len), voff);
5477
+ voff += len;
5260
5478
  }
5261
- return ret;
5479
+ return FS.write(stream, view, 0, total, offset);
5262
5480
  };
5263
5481
 
5264
5482
 
@@ -5268,7 +5486,7 @@ async function createWasm() {
5268
5486
 
5269
5487
  try {
5270
5488
 
5271
- if (isNaN(offset)) return 61;
5489
+ if (isNaN(offset)) return 22;
5272
5490
  var stream = SYSCALLS.getStreamFromFD(fd)
5273
5491
  var num = doWritev(stream, iov, iovcnt, offset);
5274
5492
  HEAPU32[((pnum)>>2)] = num;
@@ -5293,6 +5511,7 @@ async function createWasm() {
5293
5511
  return e.errno;
5294
5512
  }
5295
5513
  }
5514
+
5296
5515
 
5297
5516
 
5298
5517
  function _fd_seek(fd, offset, whence, newOffset) {
@@ -5301,7 +5520,7 @@ async function createWasm() {
5301
5520
 
5302
5521
  try {
5303
5522
 
5304
- if (isNaN(offset)) return 61;
5523
+ if (isNaN(offset)) return 22;
5305
5524
  var stream = SYSCALLS.getStreamFromFD(fd);
5306
5525
  FS.llseek(stream, offset, whence);
5307
5526
  HEAP64[((newOffset)>>3)] = BigInt(stream.position);
@@ -5325,6 +5544,7 @@ async function createWasm() {
5325
5544
  return e.errno;
5326
5545
  }
5327
5546
  }
5547
+
5328
5548
 
5329
5549
 
5330
5550
  function _fd_write(fd, iov, iovcnt, pnum) {
@@ -5339,12 +5559,13 @@ async function createWasm() {
5339
5559
  return e.errno;
5340
5560
  }
5341
5561
  }
5562
+
5342
5563
 
5343
5564
 
5344
5565
 
5345
5566
  var getCFunc = (ident) => {
5346
5567
  var func = Module['_' + ident]; // closure exported function
5347
- 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`);
5348
5569
  return func;
5349
5570
  };
5350
5571
 
@@ -5401,7 +5622,7 @@ async function createWasm() {
5401
5622
  var func = getCFunc(ident);
5402
5623
  var cArgs = [];
5403
5624
  var stack = 0;
5404
- assert(returnType !== 'array', 'Return type should not be "array".');
5625
+ assert(returnType !== 'array', 'return type should not be "array"');
5405
5626
  if (args) {
5406
5627
  for (var i = 0; i < args.length; i++) {
5407
5628
  var converter = toC[argTypes[i]];
@@ -5438,6 +5659,7 @@ async function createWasm() {
5438
5659
 
5439
5660
 
5440
5661
 
5662
+
5441
5663
  FS.createPreloadedFile = FS_createPreloadedFile;
5442
5664
  FS.preloadFile = FS_preloadFile;
5443
5665
  FS.staticInit();;
@@ -5446,8 +5668,9 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5446
5668
  if (!ENVIRONMENT_IS_NODE) {
5447
5669
  throw new Error("NODERAWFS is currently only supported on Node.js environment.")
5448
5670
  }
5449
- var _wrapNodeError = function(func) {
5450
- return function(...args) {
5671
+ var nodeTTY = require('node:tty');
5672
+ function _wrapNodeError(func) {
5673
+ return (...args) => {
5451
5674
  try {
5452
5675
  return func(...args)
5453
5676
  } catch (e) {
@@ -5462,14 +5685,26 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5462
5685
  throw e;
5463
5686
  }
5464
5687
  }
5465
- };
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
+ }
5466
5698
  // Use this to reference our in-memory filesystem
5467
5699
  /** @suppress {partialAlias} */
5468
5700
  var VFS = {...FS};
5469
5701
  // Wrap the whole in-memory filesystem API with
5470
5702
  // our Node.js based functions
5471
- for (var _key in NODERAWFS) {
5472
- 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]);
5473
5708
  };
5474
5709
  // End JS library code
5475
5710
 
@@ -5481,15 +5716,14 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
5481
5716
 
5482
5717
  // Begin ATMODULES hooks
5483
5718
  if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
5484
- if (Module['preloadPlugins']) preloadPlugins = Module['preloadPlugins'];
5719
+
5485
5720
  if (Module['print']) out = Module['print'];
5486
5721
  if (Module['printErr']) err = Module['printErr'];
5487
- if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5488
5722
  // End ATMODULES hooks
5489
5723
 
5490
5724
  checkIncomingModuleAPI();
5491
5725
 
5492
- if (Module['arguments']) arguments_ = Module['arguments'];
5726
+ if (Module['arguments']) programArgs = Module['arguments'];
5493
5727
  if (Module['thisProgram']) thisProgram = Module['thisProgram'];
5494
5728
 
5495
5729
  // Assertions on removed incoming Module JS APIs.
@@ -5508,10 +5742,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5508
5742
  assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
5509
5743
  assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
5510
5744
 
5511
- if (Module['preInit']) {
5512
- if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
5513
- while (Module['preInit'].length > 0) {
5514
- 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()();
5515
5752
  }
5516
5753
  }
5517
5754
  consumedModuleProp('preInit');
@@ -5599,12 +5836,14 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5599
5836
  'registerOrientationChangeEventCallback',
5600
5837
  'fillFullscreenChangeEventData',
5601
5838
  'registerFullscreenChangeEventCallback',
5839
+ 'callCanvasResizedCallback',
5602
5840
  'JSEvents_requestFullscreen',
5603
5841
  'JSEvents_resizeCanvasForFullscreen',
5604
5842
  'registerRestoreOldStyle',
5605
5843
  'hideEverythingExceptGivenElement',
5606
5844
  'restoreHiddenElements',
5607
5845
  'setLetterbox',
5846
+ 'currentFullscreenStrategy',
5608
5847
  'softFullscreenResizeWebGLRenderTarget',
5609
5848
  'doRequestFullscreen',
5610
5849
  'fillPointerlockChangeEventData',
@@ -5634,10 +5873,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5634
5873
  'registerPreMainLoop',
5635
5874
  'getPromise',
5636
5875
  'makePromise',
5876
+ 'addPromise',
5637
5877
  'idsToPromises',
5638
5878
  'makePromiseCallback',
5639
5879
  'ExceptionInfo',
5640
5880
  'findMatchingCatch',
5881
+ 'incrementUncaughtExceptionCount',
5882
+ 'decrementUncaughtExceptionCount',
5641
5883
  'Browser_asyncPrepareDataCounter',
5642
5884
  'arraySum',
5643
5885
  'addDays',
@@ -5659,6 +5901,7 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
5659
5901
  'colorChannelsInGlTextureFormat',
5660
5902
  'emscriptenWebGLGetTexPixelData',
5661
5903
  'emscriptenWebGLGetUniform',
5904
+ 'webglGetProgramUniformLocation',
5662
5905
  'webglGetUniformLocation',
5663
5906
  'webglPrepareUniformLocationsBeforeFirstUse',
5664
5907
  'webglGetLeftBracePos',
@@ -5687,20 +5930,20 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5687
5930
  'callMain',
5688
5931
  'abort',
5689
5932
  'wasmExports',
5690
- 'HEAPF32',
5691
- 'HEAPF64',
5933
+ 'writeStackCookie',
5934
+ 'checkStackCookie',
5935
+ 'INT53_MAX',
5936
+ 'INT53_MIN',
5937
+ 'bigintToI53Checked',
5692
5938
  'HEAP8',
5693
5939
  'HEAP16',
5694
5940
  'HEAPU16',
5695
5941
  'HEAP32',
5696
5942
  'HEAPU32',
5943
+ 'HEAPF32',
5944
+ 'HEAPF64',
5697
5945
  'HEAP64',
5698
5946
  'HEAPU64',
5699
- 'writeStackCookie',
5700
- 'checkStackCookie',
5701
- 'INT53_MAX',
5702
- 'INT53_MIN',
5703
- 'bigintToI53Checked',
5704
5947
  'stackSave',
5705
5948
  'stackRestore',
5706
5949
  'stackAlloc',
@@ -5749,7 +5992,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5749
5992
  'JSEvents',
5750
5993
  'specialHTMLTargets',
5751
5994
  'findCanvasEventTarget',
5752
- 'currentFullscreenStrategy',
5753
5995
  'restoreOldWindowedStyle',
5754
5996
  'UNWIND_CACHE',
5755
5997
  'ExitStatus',
@@ -5764,7 +6006,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5764
6006
  'emClearImmediate',
5765
6007
  'promiseMap',
5766
6008
  'uncaughtExceptionCount',
5767
- 'exceptionLast',
5768
6009
  'exceptionCaught',
5769
6010
  'Browser',
5770
6011
  'requestFullscreen',
@@ -5786,6 +6027,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5786
6027
  'FS_preloadFile',
5787
6028
  'FS_modeStringToFlags',
5788
6029
  'FS_getMode',
6030
+ 'FS_fileDataToTypedArray',
5789
6031
  'FS_stdin_getChar_buffer',
5790
6032
  'FS_stdin_getChar',
5791
6033
  'FS_unlink',
@@ -5853,6 +6095,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5853
6095
  'FS_mkdir',
5854
6096
  'FS_mkdev',
5855
6097
  'FS_symlink',
6098
+ 'FS_link',
5856
6099
  'FS_rename',
5857
6100
  'FS_rmdir',
5858
6101
  'FS_readdir',
@@ -5897,18 +6140,13 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5897
6140
  'FS_createDataFile',
5898
6141
  'FS_forceLoadFile',
5899
6142
  'FS_createLazyFile',
5900
- 'FS_absolutePath',
5901
- 'FS_createFolder',
5902
- 'FS_createLink',
5903
- 'FS_joinPath',
5904
- 'FS_mmapAlloc',
5905
- 'FS_standardizePath',
5906
6143
  'MEMFS',
5907
6144
  'TTY',
5908
6145
  'PIPEFS',
5909
6146
  'SOCKFS',
5910
6147
  'NODEFS',
5911
6148
  'NODERAWFS',
6149
+ 'NODERAWFS_stream_funcs',
5912
6150
  'nodePath',
5913
6151
  'tempFixedLengthArray',
5914
6152
  'miniTempWebGLFloatBuffers',
@@ -5937,16 +6175,40 @@ function checkIncomingModuleAPI() {
5937
6175
  ignoredModuleProp('fetchSettings');
5938
6176
  ignoredModuleProp('logReadFiles');
5939
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');
5940
6202
  }
5941
6203
  var ASM_CONSTS = {
5942
- 2633744: ($0) => { globalThis.picorubyRefs[$0] = null; },
5943
- 2633784: ($0) => { globalThis.picorubyRefs[$0] = true; },
5944
- 2633824: ($0) => { globalThis.picorubyRefs[$0] = false; },
5945
- 2633865: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5946
- 2633903: ($0, $1) => { globalThis.picorubyRefs[$0] = $1; },
5947
- 2633941: ($0, $1, $2) => { const str = UTF8ToString($1, $2); globalThis.picorubyRefs[$0] = str; },
5948
- 2634014: ($0, $1) => { const arr = globalThis.picorubyRefs[$0]; const elem = globalThis.picorubyRefs[$1]; arr.push(elem); delete globalThis.picorubyRefs[$1]; },
5949
- 2634153: ($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]; }
5950
6212
  };
5951
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; } }
5952
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; } }
@@ -6035,7 +6297,7 @@ function serial_capture_start(ref_id) { try { const port = globalThis.picorubyRe
6035
6297
  function serial_binary_capture_start(ref_id) { try { const port = globalThis.picorubyRefs[ref_id]; if (!port) return; if (!globalThis.picorubySerialBinCap) { const buffers = new WeakMap(); const active = new WeakSet(); const MAX_BYTES = 256 * 1024; globalThis.picorubySerialBinCap = { start(p) { buffers.set(p, { chunks: [], totalBytes: 0 }); active.add(p); }, isActive(p) { return active.has(p); }, append(p, value) { const buf = buffers.get(p); if (!buf) return; const copy = new Uint8Array(value); buf.chunks.push(copy); buf.totalBytes += copy.length; while (buf.totalBytes > MAX_BYTES && buf.chunks.length > 1) { const removed = buf.chunks.shift(); buf.totalBytes -= removed.length; } }, read(p, outPtr, maxBytes) { const buf = buffers.get(p); if (!buf || buf.totalBytes === 0) return 0; let written = 0; while (written < maxBytes && buf.chunks.length > 0) { const chunk = buf.chunks[0]; const needed = maxBytes - written; if (chunk.length <= needed) { HEAPU8.set(chunk, outPtr + written); written += chunk.length; buf.chunks.shift(); } else { HEAPU8.set(chunk.subarray(0, needed), outPtr + written); buf.chunks[0] = chunk.subarray(needed); written += needed; } } buf.totalBytes -= written; return written; }, stop(p) { active.delete(p); buffers.delete(p); }, }; } globalThis.picorubySerialBinCap.start(port); } catch (e) { console.error('serial_binary_capture_start failed:', e); } }
6036
6298
  function serial_binary_capture_read(ref_id,out_buf,max_bytes) { try { const port = globalThis.picorubyRefs[ref_id]; if (!port || !globalThis.picorubySerialBinCap) return 0; return globalThis.picorubySerialBinCap.read(port, out_buf, max_bytes); } catch (e) { console.error('serial_binary_capture_read failed:', e); return 0; } }
6037
6299
  function serial_binary_capture_stop(ref_id) { try { const port = globalThis.picorubyRefs[ref_id]; if (!port || !globalThis.picorubySerialBinCap) return; globalThis.picorubySerialBinCap.stop(port); } catch (e) { console.error('serial_binary_capture_stop failed:', e); } }
6038
- function serial_capture_get(ref_id,stop) { try { const port = globalThis.picorubyRefs[ref_id]; if (!port || !globalThis.picorubySerialCapture) { return globalThis.picorubyRefs.push("") - 1; } const cap = globalThis.picorubySerialCapture; const out = stop ? cap.stop(port) : cap.peek(port); return globalThis.picorubyRefs.push(out) - 1; } catch (e) { console.error('serial_capture_get failed:', e); return globalThis.picorubyRefs.push("") - 1; } }
6300
+ function serial_capture_copy(ref_id,stop,out_buf,max_bytes) { try { const port = globalThis.picorubyRefs[ref_id]; if (!port || !globalThis.picorubySerialCapture) { if (max_bytes > 0) HEAPU8[out_buf] = 0; return 0; } const cap = globalThis.picorubySerialCapture; const out = stop ? cap.stop(port) : cap.peek(port); const bytes = new TextEncoder().encode(out); const n = Math.min(bytes.length, Math.max(0, max_bytes - 1)); if (n > 0) { HEAPU8.set(bytes.subarray(0, n), out_buf); } if (max_bytes > 0) { HEAPU8[out_buf + n] = 0; } return n; } catch (e) { console.error('serial_capture_copy failed:', e); if (max_bytes > 0) HEAPU8[out_buf] = 0; return 0; } }
6039
6301
  function ws_new(url) { try { const ws = new WebSocket(UTF8ToString(url)); const refId = globalThis.picorubyRefs.push(ws) - 1; return refId; } catch(e) { console.error('WebSocket creation failed:', e); return -1; } }
6040
6302
  function ws_send(ref_id,data) { try { const ws = globalThis.picorubyRefs[ref_id]; if (ws && ws.readyState === WebSocket.OPEN) { ws.send(UTF8ToString(data)); } } catch(e) { console.error('WebSocket send failed:', e); } }
6041
6303
  function ws_send_binary(ref_id,data,length) { try { const ws = globalThis.picorubyRefs[ref_id]; if (ws && ws.readyState === WebSocket.OPEN) { const buffer = new Uint8Array(HEAPU8.buffer, data, length); const copy = new Uint8Array(buffer); ws.send(copy.buffer); } } catch(e) { console.error('WebSocket send_binary failed:', e); } }
@@ -6073,6 +6335,8 @@ var _resume_binary_task = Module['_resume_binary_task'] = makeInvalidEarlyAccess
6073
6335
  var _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = makeInvalidEarlyAccess('_call_ruby_callback_sync_generic');
6074
6336
  var _mrb_tick_wasm = Module['_mrb_tick_wasm'] = makeInvalidEarlyAccess('_mrb_tick_wasm');
6075
6337
  var _mrb_run_step = Module['_mrb_run_step'] = makeInvalidEarlyAccess('_mrb_run_step');
6338
+ var _mrb_run_step_status = Module['_mrb_run_step_status'] = makeInvalidEarlyAccess('_mrb_run_step_status');
6339
+ var _mrb_gc_scheduler_pending_wasm = Module['_mrb_gc_scheduler_pending_wasm'] = makeInvalidEarlyAccess('_mrb_gc_scheduler_pending_wasm');
6076
6340
  var _picorb_init = Module['_picorb_init'] = makeInvalidEarlyAccess('_picorb_init');
6077
6341
  var _picorb_create_task = Module['_picorb_create_task'] = makeInvalidEarlyAccess('_picorb_create_task');
6078
6342
  var _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = makeInvalidEarlyAccess('_picorb_create_task_with_filename');
@@ -6119,6 +6383,8 @@ function assignWasmExports(wasmExports) {
6119
6383
  assert(typeof wasmExports['call_ruby_callback_sync_generic'] != 'undefined', 'missing Wasm export: call_ruby_callback_sync_generic');
6120
6384
  assert(typeof wasmExports['mrb_tick_wasm'] != 'undefined', 'missing Wasm export: mrb_tick_wasm');
6121
6385
  assert(typeof wasmExports['mrb_run_step'] != 'undefined', 'missing Wasm export: mrb_run_step');
6386
+ assert(typeof wasmExports['mrb_run_step_status'] != 'undefined', 'missing Wasm export: mrb_run_step_status');
6387
+ assert(typeof wasmExports['mrb_gc_scheduler_pending_wasm'] != 'undefined', 'missing Wasm export: mrb_gc_scheduler_pending_wasm');
6122
6388
  assert(typeof wasmExports['picorb_init'] != 'undefined', 'missing Wasm export: picorb_init');
6123
6389
  assert(typeof wasmExports['picorb_create_task'] != 'undefined', 'missing Wasm export: picorb_create_task');
6124
6390
  assert(typeof wasmExports['picorb_create_task_with_filename'] != 'undefined', 'missing Wasm export: picorb_create_task_with_filename');
@@ -6141,39 +6407,41 @@ function assignWasmExports(wasmExports) {
6141
6407
  assert(typeof wasmExports['emscripten_stack_get_current'] != 'undefined', 'missing Wasm export: emscripten_stack_get_current');
6142
6408
  assert(typeof wasmExports['memory'] != 'undefined', 'missing Wasm export: memory');
6143
6409
  assert(typeof wasmExports['__indirect_function_table'] != 'undefined', 'missing Wasm export: __indirect_function_table');
6144
- _ble_notify_callback = Module['_ble_notify_callback'] = createExportWrapper('ble_notify_callback', 3);
6145
- _mrb_get_globals_json = Module['_mrb_get_globals_json'] = createExportWrapper('mrb_get_globals_json', 0);
6146
- _mrb_get_component_debug_info = Module['_mrb_get_component_debug_info'] = createExportWrapper('mrb_get_component_debug_info', 1);
6147
- _mrb_get_component_state_by_id = Module['_mrb_get_component_state_by_id'] = createExportWrapper('mrb_get_component_state_by_id', 1);
6148
- _mrb_eval_string = Module['_mrb_eval_string'] = createExportWrapper('mrb_eval_string', 1);
6149
- _mrb_debug_get_status = Module['_mrb_debug_get_status'] = createExportWrapper('mrb_debug_get_status', 0);
6150
- _mrb_debug_continue = Module['_mrb_debug_continue'] = createExportWrapper('mrb_debug_continue', 0);
6151
- _mrb_debug_get_locals = Module['_mrb_debug_get_locals'] = createExportWrapper('mrb_debug_get_locals', 0);
6152
- _mrb_debug_eval_in_binding = Module['_mrb_debug_eval_in_binding'] = createExportWrapper('mrb_debug_eval_in_binding', 1);
6153
- _mrb_debug_step = Module['_mrb_debug_step'] = createExportWrapper('mrb_debug_step', 0);
6154
- _mrb_debug_next = Module['_mrb_debug_next'] = createExportWrapper('mrb_debug_next', 0);
6155
- _mrb_debug_get_callstack = Module['_mrb_debug_get_callstack'] = createExportWrapper('mrb_debug_get_callstack', 0);
6156
- _call_ruby_callback = Module['_call_ruby_callback'] = createExportWrapper('call_ruby_callback', 2);
6157
- _call_ruby_callback_oneshot = Module['_call_ruby_callback_oneshot'] = createExportWrapper('call_ruby_callback_oneshot', 2);
6158
- _resume_promise_task = Module['_resume_promise_task'] = createExportWrapper('resume_promise_task', 4);
6159
- _resume_promise_error_task = Module['_resume_promise_error_task'] = createExportWrapper('resume_promise_error_task', 4);
6160
- _resume_binary_task = Module['_resume_binary_task'] = createExportWrapper('resume_binary_task', 5);
6161
- _call_ruby_callback_sync_generic = Module['_call_ruby_callback_sync_generic'] = createExportWrapper('call_ruby_callback_sync_generic', 3);
6162
- _mrb_tick_wasm = Module['_mrb_tick_wasm'] = createExportWrapper('mrb_tick_wasm', 0);
6163
- _mrb_run_step = Module['_mrb_run_step'] = createExportWrapper('mrb_run_step', 0);
6164
- _picorb_init = Module['_picorb_init'] = createExportWrapper('picorb_init', 0);
6165
- _picorb_create_task = Module['_picorb_create_task'] = createExportWrapper('picorb_create_task', 1);
6166
- _picorb_create_task_with_filename = Module['_picorb_create_task_with_filename'] = createExportWrapper('picorb_create_task_with_filename', 2);
6167
- _picorb_create_task_from_mrb = Module['_picorb_create_task_from_mrb'] = createExportWrapper('picorb_create_task_from_mrb', 2);
6168
- _serial_data_received = Module['_serial_data_received'] = createExportWrapper('serial_data_received', 3);
6169
- _serial_disconnect_callback = Module['_serial_disconnect_callback'] = createExportWrapper('serial_disconnect_callback', 1);
6170
- _call_ruby_callback_with_binary_data = Module['_call_ruby_callback_with_binary_data'] = createExportWrapper('call_ruby_callback_with_binary_data', 3);
6171
- _fflush = createExportWrapper('fflush', 1);
6172
- _strerror = createExportWrapper('strerror', 1);
6173
- _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
6174
- _malloc = Module['_malloc'] = createExportWrapper('malloc', 1);
6175
- _free = Module['_free'] = createExportWrapper('free', 1);
6176
- _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);
6177
6445
  _emscripten_stack_init = wasmExports['emscripten_stack_init'];
6178
6446
  _emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'];
6179
6447
  _emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'];
@@ -6219,10 +6487,12 @@ var wasmImports = {
6219
6487
  /** @export */
6220
6488
  __syscall_openat: ___syscall_openat,
6221
6489
  /** @export */
6222
- __syscall_pipe: ___syscall_pipe,
6490
+ __syscall_pipe2: ___syscall_pipe2,
6223
6491
  /** @export */
6224
6492
  __syscall_poll: ___syscall_poll,
6225
6493
  /** @export */
6494
+ __syscall_poll_nonblocking: ___syscall_poll_nonblocking,
6495
+ /** @export */
6226
6496
  __syscall_readlinkat: ___syscall_readlinkat,
6227
6497
  /** @export */
6228
6498
  __syscall_renameat: ___syscall_renameat,
@@ -6233,6 +6503,8 @@ var wasmImports = {
6233
6503
  /** @export */
6234
6504
  __syscall_symlinkat: ___syscall_symlinkat,
6235
6505
  /** @export */
6506
+ __syscall_umask: ___syscall_umask,
6507
+ /** @export */
6236
6508
  __syscall_unlinkat: ___syscall_unlinkat,
6237
6509
  /** @export */
6238
6510
  _abort_js: __abort_js,
@@ -6343,12 +6615,18 @@ var wasmImports = {
6343
6615
  /** @export */
6344
6616
  invoke_ddd,
6345
6617
  /** @export */
6618
+ invoke_ii,
6619
+ /** @export */
6346
6620
  invoke_iii,
6347
6621
  /** @export */
6348
6622
  invoke_iiii,
6349
6623
  /** @export */
6350
6624
  invoke_iiiii,
6351
6625
  /** @export */
6626
+ invoke_iij,
6627
+ /** @export */
6628
+ invoke_iijiiiiii,
6629
+ /** @export */
6352
6630
  invoke_ji,
6353
6631
  /** @export */
6354
6632
  invoke_jii,
@@ -6363,6 +6641,8 @@ var wasmImports = {
6363
6641
  /** @export */
6364
6642
  invoke_viiiii,
6365
6643
  /** @export */
6644
+ invoke_viiiiiii,
6645
+ /** @export */
6366
6646
  invoke_viiiij,
6367
6647
  /** @export */
6368
6648
  invoke_viiiijii,
@@ -6373,14 +6653,14 @@ var wasmImports = {
6373
6653
  /** @export */
6374
6654
  invoke_viiji,
6375
6655
  /** @export */
6656
+ invoke_viijiii,
6657
+ /** @export */
6376
6658
  invoke_viijj,
6377
6659
  /** @export */
6378
6660
  invoke_vij,
6379
6661
  /** @export */
6380
6662
  invoke_vijii,
6381
6663
  /** @export */
6382
- invoke_vijiii,
6383
- /** @export */
6384
6664
  js_add_event_listener,
6385
6665
  /** @export */
6386
6666
  js_append_child,
@@ -6463,7 +6743,7 @@ var wasmImports = {
6463
6743
  /** @export */
6464
6744
  serial_binary_capture_stop,
6465
6745
  /** @export */
6466
- serial_capture_get,
6746
+ serial_capture_copy,
6467
6747
  /** @export */
6468
6748
  serial_capture_start,
6469
6749
  /** @export */
@@ -6534,29 +6814,29 @@ function invoke_viii(index,a1,a2,a3) {
6534
6814
  getWasmTableEntry(index)(a1,a2,a3);
6535
6815
  } catch(e) {
6536
6816
  stackRestore(sp);
6537
- if (e !== e+0) throw e;
6817
+ if (!(e instanceof EmscriptenEH)) throw e;
6538
6818
  _setThrew(1, 0);
6539
6819
  }
6540
6820
  }
6541
6821
 
6542
- function invoke_iiii(index,a1,a2,a3) {
6822
+ function invoke_vii(index,a1,a2) {
6543
6823
  var sp = stackSave();
6544
6824
  try {
6545
- return getWasmTableEntry(index)(a1,a2,a3);
6825
+ getWasmTableEntry(index)(a1,a2);
6546
6826
  } catch(e) {
6547
6827
  stackRestore(sp);
6548
- if (e !== e+0) throw e;
6828
+ if (!(e instanceof EmscriptenEH)) throw e;
6549
6829
  _setThrew(1, 0);
6550
6830
  }
6551
6831
  }
6552
6832
 
6553
- function invoke_vii(index,a1,a2) {
6833
+ function invoke_ii(index,a1) {
6554
6834
  var sp = stackSave();
6555
6835
  try {
6556
- getWasmTableEntry(index)(a1,a2);
6836
+ return getWasmTableEntry(index)(a1);
6557
6837
  } catch(e) {
6558
6838
  stackRestore(sp);
6559
- if (e !== e+0) throw e;
6839
+ if (!(e instanceof EmscriptenEH)) throw e;
6560
6840
  _setThrew(1, 0);
6561
6841
  }
6562
6842
  }
@@ -6567,7 +6847,7 @@ function invoke_ji(index,a1) {
6567
6847
  return getWasmTableEntry(index)(a1);
6568
6848
  } catch(e) {
6569
6849
  stackRestore(sp);
6570
- if (e !== e+0) throw e;
6850
+ if (!(e instanceof EmscriptenEH)) throw e;
6571
6851
  _setThrew(1, 0);
6572
6852
  return 0n;
6573
6853
  }
@@ -6579,62 +6859,62 @@ function invoke_vi(index,a1) {
6579
6859
  getWasmTableEntry(index)(a1);
6580
6860
  } catch(e) {
6581
6861
  stackRestore(sp);
6582
- if (e !== e+0) throw e;
6862
+ if (!(e instanceof EmscriptenEH)) throw e;
6583
6863
  _setThrew(1, 0);
6584
6864
  }
6585
6865
  }
6586
6866
 
6587
- function invoke_viiiii(index,a1,a2,a3,a4,a5) {
6867
+ function invoke_iijiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8) {
6588
6868
  var sp = stackSave();
6589
6869
  try {
6590
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6870
+ return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8);
6591
6871
  } catch(e) {
6592
6872
  stackRestore(sp);
6593
- if (e !== e+0) throw e;
6873
+ if (!(e instanceof EmscriptenEH)) throw e;
6594
6874
  _setThrew(1, 0);
6595
6875
  }
6596
6876
  }
6597
6877
 
6598
- function invoke_vijiii(index,a1,a2,a3,a4,a5) {
6878
+ function invoke_viijiii(index,a1,a2,a3,a4,a5,a6) {
6599
6879
  var sp = stackSave();
6600
6880
  try {
6601
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6881
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6);
6602
6882
  } catch(e) {
6603
6883
  stackRestore(sp);
6604
- if (e !== e+0) throw e;
6884
+ if (!(e instanceof EmscriptenEH)) throw e;
6605
6885
  _setThrew(1, 0);
6606
6886
  }
6607
6887
  }
6608
6888
 
6609
- function invoke_viiji(index,a1,a2,a3,a4) {
6889
+ function invoke_iii(index,a1,a2) {
6610
6890
  var sp = stackSave();
6611
6891
  try {
6612
- getWasmTableEntry(index)(a1,a2,a3,a4);
6892
+ return getWasmTableEntry(index)(a1,a2);
6613
6893
  } catch(e) {
6614
6894
  stackRestore(sp);
6615
- if (e !== e+0) throw e;
6895
+ if (!(e instanceof EmscriptenEH)) throw e;
6616
6896
  _setThrew(1, 0);
6617
6897
  }
6618
6898
  }
6619
6899
 
6620
- function invoke_iiiii(index,a1,a2,a3,a4) {
6900
+ function invoke_viiiii(index,a1,a2,a3,a4,a5) {
6621
6901
  var sp = stackSave();
6622
6902
  try {
6623
- return getWasmTableEntry(index)(a1,a2,a3,a4);
6903
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6624
6904
  } catch(e) {
6625
6905
  stackRestore(sp);
6626
- if (e !== e+0) throw e;
6906
+ if (!(e instanceof EmscriptenEH)) throw e;
6627
6907
  _setThrew(1, 0);
6628
6908
  }
6629
6909
  }
6630
6910
 
6631
- function invoke_vij(index,a1,a2) {
6911
+ function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
6632
6912
  var sp = stackSave();
6633
6913
  try {
6634
- getWasmTableEntry(index)(a1,a2);
6914
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6635
6915
  } catch(e) {
6636
6916
  stackRestore(sp);
6637
- if (e !== e+0) throw e;
6917
+ if (!(e instanceof EmscriptenEH)) throw e;
6638
6918
  _setThrew(1, 0);
6639
6919
  }
6640
6920
  }
@@ -6645,40 +6925,62 @@ function invoke_viiii(index,a1,a2,a3,a4) {
6645
6925
  getWasmTableEntry(index)(a1,a2,a3,a4);
6646
6926
  } catch(e) {
6647
6927
  stackRestore(sp);
6648
- if (e !== e+0) throw e;
6928
+ if (!(e instanceof EmscriptenEH)) throw e;
6649
6929
  _setThrew(1, 0);
6650
6930
  }
6651
6931
  }
6652
6932
 
6653
- function invoke_viiiij(index,a1,a2,a3,a4,a5) {
6933
+ function invoke_viiiijii(index,a1,a2,a3,a4,a5,a6,a7) {
6654
6934
  var sp = stackSave();
6655
6935
  try {
6656
- getWasmTableEntry(index)(a1,a2,a3,a4,a5);
6936
+ getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6657
6937
  } catch(e) {
6658
6938
  stackRestore(sp);
6659
- if (e !== e+0) throw e;
6939
+ if (!(e instanceof EmscriptenEH)) throw e;
6660
6940
  _setThrew(1, 0);
6661
6941
  }
6662
6942
  }
6663
6943
 
6664
- function invoke_viiiijii(index,a1,a2,a3,a4,a5,a6,a7) {
6944
+ function invoke_iiii(index,a1,a2,a3) {
6665
6945
  var sp = stackSave();
6666
6946
  try {
6667
- getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7);
6947
+ return getWasmTableEntry(index)(a1,a2,a3);
6668
6948
  } catch(e) {
6669
6949
  stackRestore(sp);
6670
- if (e !== e+0) throw e;
6950
+ if (!(e instanceof EmscriptenEH)) throw e;
6671
6951
  _setThrew(1, 0);
6672
6952
  }
6673
6953
  }
6674
6954
 
6675
- function invoke_iii(index,a1,a2) {
6955
+ function invoke_iiiii(index,a1,a2,a3,a4) {
6676
6956
  var sp = stackSave();
6677
6957
  try {
6678
- 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);
6679
6981
  } catch(e) {
6680
6982
  stackRestore(sp);
6681
- if (e !== e+0) throw e;
6983
+ if (!(e instanceof EmscriptenEH)) throw e;
6682
6984
  _setThrew(1, 0);
6683
6985
  }
6684
6986
  }
@@ -6689,7 +6991,7 @@ function invoke_viij(index,a1,a2,a3) {
6689
6991
  getWasmTableEntry(index)(a1,a2,a3);
6690
6992
  } catch(e) {
6691
6993
  stackRestore(sp);
6692
- if (e !== e+0) throw e;
6994
+ if (!(e instanceof EmscriptenEH)) throw e;
6693
6995
  _setThrew(1, 0);
6694
6996
  }
6695
6997
  }
@@ -6700,7 +7002,18 @@ function invoke_viiij(index,a1,a2,a3,a4) {
6700
7002
  getWasmTableEntry(index)(a1,a2,a3,a4);
6701
7003
  } catch(e) {
6702
7004
  stackRestore(sp);
6703
- 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;
6704
7017
  _setThrew(1, 0);
6705
7018
  }
6706
7019
  }
@@ -6711,7 +7024,7 @@ function invoke_viijj(index,a1,a2,a3,a4) {
6711
7024
  getWasmTableEntry(index)(a1,a2,a3,a4);
6712
7025
  } catch(e) {
6713
7026
  stackRestore(sp);
6714
- if (e !== e+0) throw e;
7027
+ if (!(e instanceof EmscriptenEH)) throw e;
6715
7028
  _setThrew(1, 0);
6716
7029
  }
6717
7030
  }
@@ -6722,7 +7035,18 @@ function invoke_ddd(index,a1,a2) {
6722
7035
  return getWasmTableEntry(index)(a1,a2);
6723
7036
  } catch(e) {
6724
7037
  stackRestore(sp);
6725
- 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;
6726
7050
  _setThrew(1, 0);
6727
7051
  }
6728
7052
  }
@@ -6733,7 +7057,7 @@ function invoke_jii(index,a1,a2) {
6733
7057
  return getWasmTableEntry(index)(a1,a2);
6734
7058
  } catch(e) {
6735
7059
  stackRestore(sp);
6736
- if (e !== e+0) throw e;
7060
+ if (!(e instanceof EmscriptenEH)) throw e;
6737
7061
  _setThrew(1, 0);
6738
7062
  return 0n;
6739
7063
  }
@@ -6745,7 +7069,7 @@ function invoke_vijii(index,a1,a2,a3,a4) {
6745
7069
  getWasmTableEntry(index)(a1,a2,a3,a4);
6746
7070
  } catch(e) {
6747
7071
  stackRestore(sp);
6748
- if (e !== e+0) throw e;
7072
+ if (!(e instanceof EmscriptenEH)) throw e;
6749
7073
  _setThrew(1, 0);
6750
7074
  }
6751
7075
  }
@@ -6765,54 +7089,37 @@ function stackCheckInit() {
6765
7089
  writeStackCookie();
6766
7090
  }
6767
7091
 
6768
- function run() {
6769
-
6770
- if (runDependencies > 0) {
6771
- dependenciesFulfilled = run;
6772
- return;
6773
- }
7092
+ async function run() {
7093
+ assert(!calledRun);
7094
+ calledRun = true;
6774
7095
 
6775
7096
  stackCheckInit();
6776
7097
 
6777
7098
  preRun();
6778
7099
 
6779
- // a preRun added a dependency, run will be called later
6780
- if (runDependencies > 0) {
6781
- dependenciesFulfilled = run;
6782
- return;
7100
+ if (runDependencies) {
7101
+ await resolveRunDependencies();
6783
7102
  }
6784
7103
 
6785
- function doRun() {
6786
- // run may have just been called through dependencies being fulfilled just in this very frame,
6787
- // or while the async setStatus time below was happening
6788
- assert(!calledRun);
6789
- calledRun = true;
6790
- Module['calledRun'] = true;
6791
-
6792
- 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
+ }
6793
7112
 
6794
- initRuntime();
7113
+ if (ABORT) return;
6795
7114
 
6796
- readyPromiseResolve?.(Module);
6797
- Module['onRuntimeInitialized']?.();
6798
- consumedModuleProp('onRuntimeInitialized');
7115
+ initRuntime();
6799
7116
 
6800
- 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');
6801
7119
 
6802
- postRun();
6803
- }
7120
+ assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');
6804
7121
 
6805
- if (Module['setStatus']) {
6806
- Module['setStatus']('Running...');
6807
- setTimeout(() => {
6808
- setTimeout(() => Module['setStatus'](''), 1);
6809
- doRun();
6810
- }, 1);
6811
- } else
6812
- {
6813
- doRun();
6814
- }
6815
- checkStackCookie();
7122
+ postRun();
6816
7123
  }
6817
7124
 
6818
7125
  function checkUnflushedContent() {
@@ -6858,28 +7165,14 @@ var wasmExports;
6858
7165
 
6859
7166
  // In modularize mode the generated code is within a factory function so we
6860
7167
  // can use await here (since it's not top-level-await).
6861
- wasmExports = await (createWasm());
6862
-
6863
- run();
7168
+ wasmExports = await createWasm();
7169
+ await run();
6864
7170
 
6865
7171
  // end include: postamble.js
6866
7172
 
6867
7173
  // include: postamble_modularize.js
6868
7174
  // In MODULARIZE mode we wrap the generated code in a factory function
6869
7175
  // and return either the Module itself, or a promise of the module.
6870
- //
6871
- // We assign to the `moduleRtn` global here and configure closure to see
6872
- // this as an extern so it won't get minified.
6873
-
6874
- if (runtimeInitialized) {
6875
- moduleRtn = Module;
6876
- } else {
6877
- // Set up the promise that indicates the Module is initialized
6878
- moduleRtn = new Promise((resolve, reject) => {
6879
- readyPromiseResolve = resolve;
6880
- readyPromiseReject = reject;
6881
- });
6882
- }
6883
7176
 
6884
7177
  // Assertion for attempting to access module properties on the incoming
6885
7178
  // moduleArg. In the past we used this object as the prototype of the module
@@ -6900,7 +7193,7 @@ for (const prop of Object.keys(Module)) {
6900
7193
 
6901
7194
 
6902
7195
 
6903
- return moduleRtn;
7196
+ return Module;
6904
7197
  }
6905
7198
 
6906
7199
  // Export using a UMD style export, or ES6 exports if selected