funicular 0.3.0 → 0.5.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +486 -1
  3. data/demo/local_notes.html +207 -0
  4. data/demo/test_chartjs.html +9 -9
  5. data/demo/test_component.html +8 -8
  6. data/demo/test_error_boundary.html +44 -41
  7. data/demo/test_router.html +48 -48
  8. data/demo/tic-tac-toe.html +25 -25
  9. data/docs/architecture.md +227 -12
  10. data/docs/local_database.md +1035 -0
  11. data/lib/funicular/assets/funicular.rb +14 -0
  12. data/lib/funicular/configuration.rb +65 -0
  13. data/lib/funicular/epoch_header.rb +69 -0
  14. data/lib/funicular/epoch_stamping.rb +66 -0
  15. data/lib/funicular/helpers/picoruby_helper.rb +96 -1
  16. data/lib/funicular/railtie.rb +30 -0
  17. data/lib/funicular/schema.rb +45 -12
  18. data/lib/funicular/session_epoch.rb +110 -0
  19. data/lib/funicular/ssr/runtime.rb +58 -12
  20. data/lib/funicular/ssr.rb +25 -0
  21. data/lib/funicular/testing/node_runner.mjs +19 -0
  22. data/lib/funicular/testing.rb +47 -0
  23. data/lib/funicular/vendor/mrbc/VERSION +1 -1
  24. data/lib/funicular/vendor/mrbc/mrbc.js +655 -574
  25. data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
  26. data/lib/funicular/vendor/picoruby/VERSION +1 -1
  27. data/lib/funicular/vendor/picoruby/debug/picoruby.js +800 -530
  28. data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
  29. data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
  30. data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
  31. data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
  32. data/lib/funicular/vendor/picoruby-test-node/picoruby.js +2 -6909
  33. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
  34. data/lib/funicular/version.rb +1 -1
  35. data/lib/funicular.rb +1 -0
  36. data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +37 -38
  37. data/lib/tasks/funicular.rake +10 -2
  38. data/minitest/callback_error_visibility_test.rb +48 -0
  39. data/minitest/configuration_test.rb +78 -0
  40. data/minitest/dsl_test.rb +264 -0
  41. data/minitest/epoch_header_test.rb +149 -0
  42. data/minitest/epoch_stamping_test.rb +225 -0
  43. data/minitest/fixtures/funicular_app/components/greeting_component.rb +5 -5
  44. data/minitest/fixtures/funicular_app/components/probe_component.rb +15 -0
  45. data/minitest/form_for_test.rb +2 -2
  46. data/minitest/hydration_test.rb +2 -2
  47. data/minitest/navigation_guard_test.rb +65 -0
  48. data/minitest/picoruby_helper_test.rb +236 -0
  49. data/minitest/schema_test.rb +47 -0
  50. data/minitest/session_epoch_test.rb +122 -0
  51. data/minitest/sig_tags_test.rb +30 -0
  52. data/minitest/ssr_database_test.rb +78 -0
  53. data/minitest/ssr_reload_test.rb +106 -0
  54. data/minitest/ssr_test.rb +41 -0
  55. data/minitest/testing_ensure_compiled_test.rb +52 -0
  56. data/minitest/validations_test.rb +35 -5
  57. data/minitest/view_context_test.rb +15 -15
  58. data/mrbgem.rake +2 -0
  59. data/mrblib/0_tags.rb +62 -0
  60. data/mrblib/cable.rb +1 -1
  61. data/mrblib/component.rb +226 -24
  62. data/mrblib/db.rb +3116 -0
  63. data/mrblib/error_boundary.rb +25 -19
  64. data/mrblib/file_upload.rb +17 -7
  65. data/mrblib/form_builder.rb +10 -10
  66. data/mrblib/funicular.rb +136 -17
  67. data/mrblib/http.rb +84 -107
  68. data/mrblib/model.rb +1178 -23
  69. data/mrblib/relation.rb +342 -0
  70. data/mrblib/router.rb +45 -4
  71. data/mrblib/styles.rb +122 -12
  72. data/mrblib/view_context.rb +3 -32
  73. data/sig/component.rbs +25 -4
  74. data/sig/db.rbs +328 -0
  75. data/sig/error_boundary.rbs +4 -4
  76. data/sig/funicular.rbs +5 -0
  77. data/sig/http.rbs +8 -21
  78. data/sig/model.rbs +101 -7
  79. data/sig/relation.rbs +44 -0
  80. data/sig/router.rbs +1 -0
  81. data/sig/styles.rbs +19 -5
  82. data/sig/tags.rbs +54 -0
  83. data/sig/view_context.rbs +47 -34
  84. metadata +23 -2
  85. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +0 -1
@@ -17,9 +17,14 @@
17
17
 
18
18
  // Note: We use a typeof check here instead of optional chaining using
19
19
  // globalThis because older browsers might not have globalThis defined.
20
- var currentNodeVersion = typeof process !== 'undefined' && process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
21
- if (currentNodeVersion < 160000) {
22
- throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(160000) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
20
+
21
+ // We skip the node version checking when running on Bun/Deno since the node
22
+ // version they report doesn't seem to be useful.
23
+ if (typeof process !== 'undefined' && !process.versions?.bun && typeof Deno == "undefined") {
24
+ var currentNodeVersion = process.versions?.node ? humanReadableVersionToPacked(process.versions.node) : TARGET_NOT_SUPPORTED;
25
+ if (currentNodeVersion < 180300) {
26
+ throw new Error(`This emscripten-generated code requires node v${ packedVersionToHumanReadable(180300) } (detected v${packedVersionToHumanReadable(currentNodeVersion)})`);
27
+ }
23
28
  }
24
29
 
25
30
  var userAgent = typeof navigator !== 'undefined' && navigator.userAgent;
@@ -74,7 +79,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
74
79
  // refer to Module (if they choose; they can also define Module)
75
80
 
76
81
 
77
- var arguments_ = [];
82
+ var programArgs = [];
78
83
  var thisProgram = './this.program';
79
84
  var quit_ = (status, toThrow) => {
80
85
  throw toThrow;
@@ -134,7 +139,7 @@ readAsync = async (filename, binary = true) => {
134
139
  thisProgram = process.argv[1].replace(/\\/g, '/');
135
140
  }
136
141
 
137
- arguments_ = process.argv.slice(2);
142
+ programArgs = process.argv.slice(2);
138
143
 
139
144
  // MODULARIZE will export the module in the proper place outside, we don't need to export here
140
145
  if (typeof module != 'undefined') {
@@ -224,7 +229,7 @@ var OPFS = 'OPFS is no longer included by default; build with -lopfs.js';
224
229
  // perform assertions in shell.js after we set up out() and err(), as otherwise
225
230
  // if an assertion fails it cannot print the message
226
231
 
227
- assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time. Add `shell` to `-sENVIRONMENT` to enable.');
232
+ assert(!ENVIRONMENT_IS_SHELL, 'shell environment detected but not enabled at build time (add `shell` to `-sENVIRONMENT` to enable)');
228
233
 
229
234
  // end include: shell.js
230
235
 
@@ -288,45 +293,12 @@ function _free() {
288
293
  var isFileURI = (filename) => filename.startsWith('file://');
289
294
 
290
295
  // include: runtime_common.js
291
- // include: runtime_stack_check.js
292
- // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
293
- function writeStackCookie() {
294
- var max = _emscripten_stack_get_end();
295
- assert((max & 3) == 0);
296
- // If the stack ends at address zero we write our cookies 4 bytes into the
297
- // stack. This prevents interference with SAFE_HEAP and ASAN which also
298
- // monitor writes to address zero.
299
- if (max == 0) {
300
- max += 4;
301
- }
302
- // The stack grow downwards towards _emscripten_stack_get_end.
303
- // We write cookies to the final two words in the stack and detect if they are
304
- // ever overwritten.
305
- HEAPU32[((max)>>2)] = 0x02135467;
306
- HEAPU32[(((max)+(4))>>2)] = 0x89BACDFE;
307
- // Also test the global address 0 for integrity.
308
- HEAPU32[((0)>>2)] = 1668509029;
309
- }
310
-
311
- function checkStackCookie() {
312
- if (ABORT) return;
313
- var max = _emscripten_stack_get_end();
314
- // See writeStackCookie().
315
- if (max == 0) {
316
- max += 4;
317
- }
318
- var cookie1 = HEAPU32[((max)>>2)];
319
- var cookie2 = HEAPU32[(((max)+(4))>>2)];
320
- if (cookie1 != 0x02135467 || cookie2 != 0x89BACDFE) {
321
- abort(`Stack overflow! Stack cookie has been overwritten at ${ptrToString(max)}, expected hex dwords 0x89BACDFE and 0x2135467, but received ${ptrToString(cookie2)} ${ptrToString(cookie1)}`);
322
- }
323
- // Also test the global address 0 for integrity.
324
- if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
325
- abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
326
- }
327
- }
328
- // end include: runtime_stack_check.js
329
296
  // include: runtime_exceptions.js
297
+ // Base Emscripten EH error class
298
+ class EmscriptenEH {}
299
+
300
+ class EmscriptenSjLj extends EmscriptenEH {}
301
+
330
302
  // end include: runtime_exceptions.js
331
303
  // include: runtime_debug.js
332
304
  var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times
@@ -348,15 +320,31 @@ function dbg(...args) {
348
320
  })();
349
321
 
350
322
  function consumedModuleProp(prop) {
351
- if (!Object.getOwnPropertyDescriptor(Module, prop)) {
352
- Object.defineProperty(Module, prop, {
353
- configurable: true,
354
- set() {
355
- 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'`);
356
-
323
+ var value = Module[prop];
324
+ 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'`;
325
+ if (Array.isArray(value)) {
326
+ value = new Proxy(value, {
327
+ set(target, key, val) {
328
+ abort(msg);
329
+ return false;
330
+ },
331
+ defineProperty(target, key, descriptor) {
332
+ abort(msg);
333
+ return false;
334
+ },
335
+ deleteProperty(target, key) {
336
+ abort(msg);
337
+ return false;
357
338
  }
358
339
  });
359
340
  }
341
+ Object.defineProperty(Module, prop, {
342
+ configurable: true,
343
+ get() { return value; },
344
+ set() {
345
+ abort(msg);
346
+ }
347
+ });
360
348
  }
361
349
 
362
350
  function makeInvalidEarlyAccess(name) {
@@ -453,32 +441,52 @@ function unexportedRuntimeSymbol(sym) {
453
441
  }
454
442
 
455
443
  // end include: runtime_debug.js
444
+ // include: runtime_stack_check.js
445
+ const stackCookie1 = 0x02135467;
446
+ const stackCookie2 = 0x89BACDFE;
447
+
448
+ // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
449
+ function writeStackCookie() {
450
+ var max = _emscripten_stack_get_end();
451
+ assert((max & 3) == 0);
452
+ // If the stack ends at address zero we write our cookies 4 bytes into the
453
+ // stack. This prevents interference with SAFE_HEAP and ASAN which also
454
+ // monitor writes to address zero.
455
+ if (max == 0) {
456
+ max += 4;
457
+ }
458
+ // The stack grow downwards towards _emscripten_stack_get_end.
459
+ // We write cookies to the final two words in the stack and detect if they are
460
+ // ever overwritten.
461
+ HEAPU32[((max)>>2)] = stackCookie1;
462
+ HEAPU32[(((max)+(4))>>2)] = stackCookie2;
463
+ // Also test the global address 0 for integrity.
464
+ HEAPU32[((0)>>2)] = 1668509029;
465
+ }
466
+
467
+ function u32ToHexString(num) {
468
+ return '0x' + (num >>> 0).toString(16).padStart(8, '0');
469
+ }
470
+
471
+ function checkStackCookie() {
472
+ if (ABORT) return;
473
+ var max = _emscripten_stack_get_end();
474
+ // See writeStackCookie().
475
+ if (max == 0) {
476
+ max += 4;
477
+ }
478
+ var val1 = HEAPU32[((max)>>2)];
479
+ var val2 = HEAPU32[(((max)+(4))>>2)];
480
+ if (val1 != stackCookie1 || val2 != stackCookie2) {
481
+ 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)}`);
482
+ }
483
+ // Also test the global address 0 for integrity.
484
+ if (HEAPU32[((0)>>2)] != 0x63736d65 /* 'emsc' */) {
485
+ abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
486
+ }
487
+ }
488
+ // end include: runtime_stack_check.js
456
489
  // Memory management
457
- var
458
- /** @type {!Int8Array} */
459
- HEAP8,
460
- /** @type {!Uint8Array} */
461
- HEAPU8,
462
- /** @type {!Int16Array} */
463
- HEAP16,
464
- /** @type {!Uint16Array} */
465
- HEAPU16,
466
- /** @type {!Int32Array} */
467
- HEAP32,
468
- /** @type {!Uint32Array} */
469
- HEAPU32,
470
- /** @type {!Float32Array} */
471
- HEAPF32,
472
- /** @type {!Float64Array} */
473
- HEAPF64;
474
-
475
- // BigInt64Array type is not correctly defined in closure
476
- var
477
- /** not-@type {!BigInt64Array} */
478
- HEAP64,
479
- /* BigUint64Array type is not correctly defined in closure
480
- /** not-@type {!BigUint64Array} */
481
- HEAPU64;
482
490
 
483
491
  var runtimeInitialized = false;
484
492
 
@@ -486,18 +494,27 @@ var runtimeExited = false;
486
494
 
487
495
 
488
496
 
497
+ // When ALLOW_MEMORY_GROWTH is enabled, the conversion from Wasm
498
+ // memory to ArrayBuffer requires some additional logic.
499
+ function getMemoryBuffer() {
500
+ return wasmMemory.buffer;
501
+ }
502
+
489
503
  function updateMemoryViews() {
490
- var b = wasmMemory.buffer;
504
+ // If we already have a heap that is resizeable/growable buffer we don't
505
+ // need to do anything in updateMemoryViews.
506
+ if (HEAP8?.buffer?.resizable) return;
507
+ var b = getMemoryBuffer();
491
508
  HEAP8 = new Int8Array(b);
492
509
  HEAP16 = new Int16Array(b);
493
510
  HEAPU8 = new Uint8Array(b);
494
- HEAPU16 = new Uint16Array(b);
511
+
495
512
  HEAP32 = new Int32Array(b);
496
513
  HEAPU32 = new Uint32Array(b);
497
- HEAPF32 = new Float32Array(b);
498
- HEAPF64 = new Float64Array(b);
514
+
515
+
499
516
  HEAP64 = new BigInt64Array(b);
500
- HEAPU64 = new BigUint64Array(b);
517
+
501
518
  }
502
519
 
503
520
  // include: memoryprofiler.js
@@ -507,11 +524,10 @@ assert(globalThis.Int32Array && globalThis.Float64Array && Int32Array.prototype.
507
524
  'JS engine does not provide full typed array support');
508
525
 
509
526
  function preRun() {
510
- if (Module['preRun']) {
511
- if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
512
- while (Module['preRun'].length) {
513
- addOnPreRun(Module['preRun'].shift());
514
- }
527
+ var preRun = Module['preRun'];
528
+ if (preRun) {
529
+ if (typeof preRun == 'function') preRun = [preRun];
530
+ onPreRuns.push(...preRun);
515
531
  }
516
532
  consumedModuleProp('preRun');
517
533
  // Begin ATPRERUNS hooks
@@ -535,17 +551,17 @@ TTY.init();
535
551
  // Begin ATPOSTCTORS hooks
536
552
  FS.ignorePermissions = false;
537
553
  // End ATPOSTCTORS hooks
538
- }
539
554
 
540
- function preMain() {
541
555
  checkStackCookie();
542
- // No ATMAINS hooks
543
556
  }
544
557
 
558
+ var runtimeExiting = false;
559
+
545
560
  function exitRuntime() {
546
561
  assert(!runtimeExited);
562
+ assert(!runtimeExiting, 'Re-entrant call to exitRuntime()! This can happen if an atexit() registered callback throws an exception.');
563
+ runtimeExiting = true;
547
564
  checkStackCookie();
548
- // PThreads reuse the runtime from the main thread.
549
565
  ___funcs_on_exit(); // Native atexit() functions
550
566
  // Begin ATEXITS hooks
551
567
  FS.quit();
@@ -556,13 +572,11 @@ TTY.shutdown();
556
572
 
557
573
  function postRun() {
558
574
  checkStackCookie();
559
- // PThreads reuse the runtime from the main thread.
560
575
 
561
- if (Module['postRun']) {
562
- if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
563
- while (Module['postRun'].length) {
564
- addOnPostRun(Module['postRun'].shift());
565
- }
576
+ var postRun = Module['postRun'];
577
+ if (postRun) {
578
+ if (typeof postRun == 'function') postRun = [postRun];
579
+ onPostRuns.push(...postRun);
566
580
  }
567
581
  consumedModuleProp('postRun');
568
582
 
@@ -571,11 +585,13 @@ function postRun() {
571
585
  // End ATPOSTRUNS hooks
572
586
  }
573
587
 
574
- /** @param {string|number=} what */
588
+ /**
589
+ * @param {string|number=} what
590
+ */
575
591
  function abort(what) {
576
592
  Module['onAbort']?.(what);
577
593
 
578
- what = 'Aborted(' + what + ')';
594
+ what = `Aborted(${what})`;
579
595
  // TODO(sbc): Should we remove printing and leave it up to whoever
580
596
  // catches the exception?
581
597
  err(what);
@@ -604,15 +620,14 @@ function abort(what) {
604
620
  throw e;
605
621
  }
606
622
 
607
- function createExportWrapper(name, nargs) {
623
+ function createExportWrapper(name, func, nargs) {
624
+ assert(func);
608
625
  return (...args) => {
609
626
  assert(runtimeInitialized, `native function \`${name}\` called before runtime initialization`);
610
627
  assert(!runtimeExited, `native function \`${name}\` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)`);
611
- var f = wasmExports[name];
612
- assert(f, `exported native function \`${name}\` not found`);
613
628
  // Only assert for too many arguments. Too few can be valid since the missing arguments will be zero filled.
614
629
  assert(args.length <= nargs, `native function \`${name}\` called with ${args.length} args but expects ${nargs}`);
615
- return f(...args);
630
+ return func(...args);
616
631
  };
617
632
  }
618
633
 
@@ -623,9 +638,6 @@ function findWasmBinary() {
623
638
  }
624
639
 
625
640
  function getBinarySync(file) {
626
- if (file == wasmBinaryFile && wasmBinary) {
627
- return new Uint8Array(wasmBinary);
628
- }
629
641
  if (readBinary) {
630
642
  return readBinary(file);
631
643
  }
@@ -708,18 +720,15 @@ async function createWasm() {
708
720
  // Load the wasm module and create an instance of using native support in the JS engine.
709
721
  // handle a generated wasm instance, receiving its exports and
710
722
  // performing other necessary setup
711
- /** @param {WebAssembly.Module=} module*/
712
- function receiveInstance(instance, module) {
723
+ function receiveInstance(instance) {
713
724
  wasmExports = instance.exports;
714
725
 
715
726
  assignWasmExports(wasmExports);
716
727
 
717
728
  updateMemoryViews();
718
729
 
719
- removeRunDependency('wasm-instantiate');
720
730
  return wasmExports;
721
731
  }
722
- addRunDependency('wasm-instantiate');
723
732
 
724
733
  // Prefer streaming instantiation if available.
725
734
  // Async compilation can be confusing when an error on the page overwrites Module
@@ -744,15 +753,14 @@ async function createWasm() {
744
753
  // performing.
745
754
  // Also pthreads and wasm workers initialize the wasm instance through this
746
755
  // path.
747
- if (Module['instantiateWasm']) {
748
- return new Promise((resolve, reject) => {
756
+ var instantiateWasm = Module['instantiateWasm'];
757
+ if (instantiateWasm) {
758
+ return new Promise((resolve) => {
749
759
  try {
750
- Module['instantiateWasm'](info, (inst, mod) => {
751
- resolve(receiveInstance(inst, mod));
752
- });
760
+ instantiateWasm(info, (inst) => resolve(receiveInstance(inst)));
753
761
  } catch(e) {
754
762
  err(`Module.instantiateWasm callback failed with error: ${e}`);
755
- reject(e);
763
+ throw e;
756
764
  }
757
765
  });
758
766
  }
@@ -776,6 +784,15 @@ async function createWasm() {
776
784
  }
777
785
  }
778
786
 
787
+ /** @type {!Int32Array} */
788
+ var HEAP32;
789
+
790
+ /** @type {!Int8Array} */
791
+ var HEAP8;
792
+
793
+ /** @type {!Uint32Array} */
794
+ var HEAPU32;
795
+
779
796
  var callRuntimeCallbacks = (callbacks) => {
780
797
  while (callbacks.length > 0) {
781
798
  // Pass the module as the first argument.
@@ -788,122 +805,15 @@ async function createWasm() {
788
805
  var onPreRuns = [];
789
806
  var addOnPreRun = (cb) => onPreRuns.push(cb);
790
807
 
791
- var runDependencies = 0;
792
-
793
-
794
- var dependenciesFulfilled = null;
795
-
796
- var runDependencyTracking = {
797
- };
798
-
799
- var runDependencyWatcher = null;
800
- var removeRunDependency = (id) => {
801
- runDependencies--;
802
-
803
- Module['monitorRunDependencies']?.(runDependencies);
804
-
805
- assert(id, 'removeRunDependency requires an ID');
806
- assert(runDependencyTracking[id]);
807
- delete runDependencyTracking[id];
808
- if (runDependencies == 0) {
809
- if (runDependencyWatcher !== null) {
810
- clearInterval(runDependencyWatcher);
811
- runDependencyWatcher = null;
812
- }
813
- if (dependenciesFulfilled) {
814
- var callback = dependenciesFulfilled;
815
- dependenciesFulfilled = null;
816
- callback(); // can add another dependenciesFulfilled
817
- }
818
- }
819
- };
820
-
821
-
822
- var addRunDependency = (id) => {
823
- runDependencies++;
824
-
825
- Module['monitorRunDependencies']?.(runDependencies);
826
-
827
- assert(id, 'addRunDependency requires an ID')
828
- assert(!runDependencyTracking[id]);
829
- runDependencyTracking[id] = 1;
830
- if (runDependencyWatcher === null && globalThis.setInterval) {
831
- // Check for missing dependencies every few seconds
832
- runDependencyWatcher = setInterval(() => {
833
- if (ABORT) {
834
- clearInterval(runDependencyWatcher);
835
- runDependencyWatcher = null;
836
- return;
837
- }
838
- var shown = false;
839
- for (var dep in runDependencyTracking) {
840
- if (!shown) {
841
- shown = true;
842
- err('still waiting on run dependencies:');
843
- }
844
- err(`dependency: ${dep}`);
845
- }
846
- if (shown) {
847
- err('(end of list)');
848
- }
849
- }, 10000);
850
- // Prevent this timer from keeping the runtime alive if nothing
851
- // else is.
852
- runDependencyWatcher.unref?.()
853
- }
854
- };
855
-
856
-
857
-
858
- /**
859
- * @param {number} ptr
860
- * @param {string} type
861
- */
862
- function getValue(ptr, type = 'i8') {
863
- if (type.endsWith('*')) type = '*';
864
- switch (type) {
865
- case 'i1': return HEAP8[ptr];
866
- case 'i8': return HEAP8[ptr];
867
- case 'i16': return HEAP16[((ptr)>>1)];
868
- case 'i32': return HEAP32[((ptr)>>2)];
869
- case 'i64': return HEAP64[((ptr)>>3)];
870
- case 'float': return HEAPF32[((ptr)>>2)];
871
- case 'double': return HEAPF64[((ptr)>>3)];
872
- case '*': return HEAPU32[((ptr)>>2)];
873
- default: abort(`invalid type for getValue: ${type}`);
874
- }
875
- }
876
808
 
877
809
  var noExitRuntime = false;
878
810
 
879
- var ptrToString = (ptr) => {
811
+ function ptrToString(ptr) {
880
812
  assert(typeof ptr === 'number', `ptrToString expects a number, got ${typeof ptr}`);
881
813
  // Convert to 32-bit unsigned value
882
814
  ptr >>>= 0;
883
815
  return '0x' + ptr.toString(16).padStart(8, '0');
884
- };
885
-
886
-
887
-
888
- /**
889
- * @param {number} ptr
890
- * @param {number} value
891
- * @param {string} type
892
- */
893
- function setValue(ptr, value, type = 'i8') {
894
- if (type.endsWith('*')) type = '*';
895
- switch (type) {
896
- case 'i1': HEAP8[ptr] = value; break;
897
- case 'i8': HEAP8[ptr] = value; break;
898
- case 'i16': HEAP16[((ptr)>>1)] = value; break;
899
- case 'i32': HEAP32[((ptr)>>2)] = value; break;
900
- case 'i64': HEAP64[((ptr)>>3)] = BigInt(value); break;
901
- case 'float': HEAPF32[((ptr)>>2)] = value; break;
902
- case 'double': HEAPF64[((ptr)>>3)] = value; break;
903
- case '*': HEAPU32[((ptr)>>2)] = value; break;
904
- default: abort(`invalid type for setValue: ${type}`);
905
816
  }
906
- }
907
817
 
908
818
  var stackRestore = (val) => __emscripten_stack_restore(val);
909
819
 
@@ -922,6 +832,14 @@ async function createWasm() {
922
832
 
923
833
  var UTF8Decoder = globalThis.TextDecoder && new TextDecoder();
924
834
 
835
+
836
+ /**
837
+ * heapOrArray is either a regular array, or a JavaScript typed array view.
838
+ * @param {number} idx
839
+ * @param {number=} maxBytesToRead
840
+ * @param {boolean=} ignoreNul
841
+ * @return {number}
842
+ */
925
843
  var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => {
926
844
  var maxIdx = idx + maxBytesToRead;
927
845
  if (ignoreNul) return maxIdx;
@@ -966,7 +884,7 @@ async function createWasm() {
966
884
  if ((u0 & 0xF0) == 0xE0) {
967
885
  u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
968
886
  } else {
969
- 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!');
887
+ 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!`);
970
888
  u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63);
971
889
  }
972
890
 
@@ -980,6 +898,9 @@ async function createWasm() {
980
898
  return str;
981
899
  };
982
900
 
901
+ /** @type {!Uint8Array} */
902
+ var HEAPU8;
903
+
983
904
  /**
984
905
  * Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the
985
906
  * emscripten HEAP, returns a copy of that string as a Javascript String object.
@@ -1024,15 +945,12 @@ async function createWasm() {
1024
945
  // This block is not needed on v19+ since crypto.getRandomValues is builtin
1025
946
  if (ENVIRONMENT_IS_NODE) {
1026
947
  var nodeCrypto = require('node:crypto');
1027
- return (view) => nodeCrypto.randomFillSync(view);
948
+ return (view) => (nodeCrypto.randomFillSync(view), 0);
1028
949
  }
1029
950
 
1030
- return (view) => crypto.getRandomValues(view);
1031
- };
1032
- var randomFill = (view) => {
1033
- // Lazily init on the first invocation.
1034
- (randomFill = initRandomFill())(view);
951
+ return (view) => (crypto.getRandomValues(view), 0);
1035
952
  };
953
+ var randomFill = (view) => (randomFill = initRandomFill())(view);
1036
954
 
1037
955
 
1038
956
 
@@ -1098,7 +1016,7 @@ async function createWasm() {
1098
1016
  heap[outIdx++] = 0x80 | (u & 63);
1099
1017
  } else {
1100
1018
  if (outIdx + 3 >= endIdx) break;
1101
- 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).');
1019
+ 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).`);
1102
1020
  heap[outIdx++] = 0xF0 | (u >> 18);
1103
1021
  heap[outIdx++] = 0x80 | ((u >> 12) & 63);
1104
1022
  heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1222,7 +1140,7 @@ async function createWasm() {
1222
1140
  } catch (e) {
1223
1141
  throw new FS.ErrnoError(29);
1224
1142
  }
1225
- if (result === undefined && bytesRead === 0) {
1143
+ if (result === undefined && !bytesRead) {
1226
1144
  throw new FS.ErrnoError(6);
1227
1145
  }
1228
1146
  if (result === null || result === undefined) break;
@@ -1313,7 +1231,7 @@ async function createWasm() {
1313
1231
  var zeroMemory = (ptr, size) => HEAPU8.fill(0, ptr, ptr + size);
1314
1232
 
1315
1233
  var alignMemory = (size, alignment) => {
1316
- assert(alignment, "alignment argument is required");
1234
+ assert(alignment, 'alignment argument is required');
1317
1235
  return Math.ceil(size / alignment) * alignment;
1318
1236
  };
1319
1237
  var mmapAlloc = (size) => {
@@ -1322,6 +1240,7 @@ async function createWasm() {
1322
1240
  if (ptr) zeroMemory(ptr, size);
1323
1241
  return ptr;
1324
1242
  };
1243
+
1325
1244
  var MEMFS = {
1326
1245
  ops_table:null,
1327
1246
  mount(mount) {
@@ -1386,11 +1305,14 @@ async function createWasm() {
1386
1305
  } else if (FS.isFile(node.mode)) {
1387
1306
  node.node_ops = MEMFS.ops_table.file.node;
1388
1307
  node.stream_ops = MEMFS.ops_table.file.stream;
1389
- node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
1390
- // 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
1391
- // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
1392
- // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
1393
- node.contents = null;
1308
+ // The actual number of bytes used in the typed array, as opposed to
1309
+ // contents.length which gives the whole capacity.
1310
+ node.usedBytes = 0;
1311
+ // The byte data of the file is stored in a typed array.
1312
+ // Note: typed arrays are not resizable like normal JS arrays are, so
1313
+ // there is a small penalty involved for appending file writes that
1314
+ // continuously grow a file similar to std::vector capacity vs used.
1315
+ node.contents = MEMFS.emptyFileContents ??= new Uint8Array(0);
1394
1316
  } else if (FS.isLink(node.mode)) {
1395
1317
  node.node_ops = MEMFS.ops_table.link.node;
1396
1318
  node.stream_ops = MEMFS.ops_table.link.stream;
@@ -1407,36 +1329,30 @@ async function createWasm() {
1407
1329
  return node;
1408
1330
  },
1409
1331
  getFileDataAsTypedArray(node) {
1410
- if (!node.contents) return new Uint8Array(0);
1411
- if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1412
- return new Uint8Array(node.contents);
1332
+ assert(FS.isFile(node.mode), 'getFileDataAsTypedArray called on non-file');
1333
+ return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
1413
1334
  },
1414
1335
  expandFileStorage(node, newCapacity) {
1415
- var prevCapacity = node.contents ? node.contents.length : 0;
1336
+ var prevCapacity = node.contents.length;
1416
1337
  if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
1417
- // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
1418
- // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
1419
- // avoid overshooting the allocation cap by a very large margin.
1338
+ // Don't expand strictly to the given requested limit if it's only a very
1339
+ // small increase, but instead geometrically grow capacity.
1340
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for
1341
+ // large sizes, do a much more conservative size*1.125 increase to avoid
1342
+ // overshooting the allocation cap by a very large margin.
1420
1343
  var CAPACITY_DOUBLING_MAX = 1024 * 1024;
1421
1344
  newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
1422
- if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1423
- var oldContents = node.contents;
1345
+ if (prevCapacity) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1346
+ var oldContents = MEMFS.getFileDataAsTypedArray(node);
1424
1347
  node.contents = new Uint8Array(newCapacity); // Allocate new storage.
1425
- if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
1348
+ node.contents.set(oldContents);
1426
1349
  },
1427
1350
  resizeFileStorage(node, newSize) {
1428
1351
  if (node.usedBytes == newSize) return;
1429
- if (newSize == 0) {
1430
- node.contents = null; // Fully decommit when requesting a resize to zero.
1431
- node.usedBytes = 0;
1432
- } else {
1433
- var oldContents = node.contents;
1434
- node.contents = new Uint8Array(newSize); // Allocate new storage.
1435
- if (oldContents) {
1436
- node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1437
- }
1438
- node.usedBytes = newSize;
1439
- }
1352
+ var oldContents = node.contents;
1353
+ node.contents = new Uint8Array(newSize); // Allocate new storage.
1354
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
1355
+ node.usedBytes = newSize;
1440
1356
  },
1441
1357
  node_ops:{
1442
1358
  getattr(node) {
@@ -1468,7 +1384,7 @@ async function createWasm() {
1468
1384
  return attr;
1469
1385
  },
1470
1386
  setattr(node, attr) {
1471
- for (const key of ["mode", "atime", "mtime", "ctime"]) {
1387
+ for (const key of ['mode', 'atime', 'mtime', 'ctime']) {
1472
1388
  if (attr[key] != null) {
1473
1389
  node[key] = attr[key];
1474
1390
  }
@@ -1536,16 +1452,11 @@ async function createWasm() {
1536
1452
  if (position >= stream.node.usedBytes) return 0;
1537
1453
  var size = Math.min(stream.node.usedBytes - position, length);
1538
1454
  assert(size >= 0);
1539
- if (size > 8 && contents.subarray) { // non-trivial, and typed array
1540
- buffer.set(contents.subarray(position, position + size), offset);
1541
- } else {
1542
- for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
1543
- }
1455
+ buffer.set(contents.subarray(position, position + size), offset);
1544
1456
  return size;
1545
1457
  },
1546
1458
  write(stream, buffer, offset, length, position, canOwn) {
1547
- // The data buffer should be a typed array view
1548
- assert(!(buffer instanceof ArrayBuffer));
1459
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
1549
1460
  // If the buffer is located in main memory (HEAP), and if
1550
1461
  // memory can grow, we can't hold on to references of the
1551
1462
  // memory buffer, as they may get invalidated. That means we
@@ -1558,33 +1469,19 @@ async function createWasm() {
1558
1469
  var node = stream.node;
1559
1470
  node.mtime = node.ctime = Date.now();
1560
1471
 
1561
- if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
1562
- if (canOwn) {
1563
- assert(position === 0, 'canOwn must imply no weird position inside the file');
1564
- node.contents = buffer.subarray(offset, offset + length);
1565
- node.usedBytes = length;
1566
- return length;
1567
- } 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.
1568
- node.contents = buffer.slice(offset, offset + length);
1569
- node.usedBytes = length;
1570
- return length;
1571
- } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
1572
- node.contents.set(buffer.subarray(offset, offset + length), position);
1573
- return length;
1574
- }
1575
- }
1576
-
1577
- // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
1578
- MEMFS.expandFileStorage(node, position+length);
1579
- if (node.contents.subarray && buffer.subarray) {
1472
+ if (canOwn) {
1473
+ assert(!position, 'canOwn must imply no weird position inside the file');
1474
+ node.contents = buffer.subarray(offset, offset + length);
1475
+ node.usedBytes = length;
1476
+ } else if (!node.usedBytes && !position) { // 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.
1477
+ node.contents = buffer.slice(offset, offset + length);
1478
+ node.usedBytes = length;
1479
+ } else {
1480
+ MEMFS.expandFileStorage(node, position+length);
1580
1481
  // Use typed array write which is available.
1581
1482
  node.contents.set(buffer.subarray(offset, offset + length), position);
1582
- } else {
1583
- for (var i = 0; i < length; i++) {
1584
- node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
1585
- }
1483
+ node.usedBytes = Math.max(node.usedBytes, position + length);
1586
1484
  }
1587
- node.usedBytes = Math.max(node.usedBytes, position + length);
1588
1485
  return length;
1589
1486
  },
1590
1487
  llseek(stream, offset, whence) {
@@ -1609,7 +1506,7 @@ async function createWasm() {
1609
1506
  var allocated;
1610
1507
  var contents = stream.node.contents;
1611
1508
  // Only make a new copy when MAP_PRIVATE is specified.
1612
- if (!(flags & 2) && contents && contents.buffer === HEAP8.buffer) {
1509
+ if (!(flags & 2) && contents.buffer === HEAP8.buffer) {
1613
1510
  // We can't emulate MAP_SHARED when the file is not backed by the
1614
1511
  // buffer we're mapping to (e.g. the HEAP buffer).
1615
1512
  allocated = false;
@@ -1643,6 +1540,7 @@ async function createWasm() {
1643
1540
  };
1644
1541
 
1645
1542
  var FS_modeStringToFlags = (str) => {
1543
+ if (typeof str != 'string') return str;
1646
1544
  var flagModes = {
1647
1545
  'r': 0,
1648
1546
  'r+': 2,
@@ -1658,6 +1556,16 @@ async function createWasm() {
1658
1556
  return flags;
1659
1557
  };
1660
1558
 
1559
+ var FS_fileDataToTypedArray = (data) => {
1560
+ if (typeof data == 'string') {
1561
+ data = intArrayFromString(data, true);
1562
+ }
1563
+ if (!data.subarray) {
1564
+ data = new Uint8Array(data);
1565
+ }
1566
+ return data;
1567
+ };
1568
+
1661
1569
  var FS_getMode = (canRead, canWrite) => {
1662
1570
  var mode = 0;
1663
1571
  if (canRead) mode |= 292 | 73;
@@ -1792,26 +1700,27 @@ async function createWasm() {
1792
1700
  'ESTRPIPE': 135,
1793
1701
  };
1794
1702
 
1703
+
1795
1704
  var NODEFS = {
1796
1705
  isWindows:false,
1797
1706
  staticInit() {
1798
1707
  NODEFS.isWindows = !!process.platform.match(/^win/);
1799
- var flags = process.binding("constants")["fs"];
1708
+ var flags = process.binding('constants')['fs'];
1800
1709
  NODEFS.flagsForNodeMap = {
1801
- "1024": flags["O_APPEND"],
1802
- "64": flags["O_CREAT"],
1803
- "128": flags["O_EXCL"],
1804
- "256": flags["O_NOCTTY"],
1805
- "0": flags["O_RDONLY"],
1806
- "2": flags["O_RDWR"],
1807
- "4096": flags["O_SYNC"],
1808
- "512": flags["O_TRUNC"],
1809
- "1": flags["O_WRONLY"],
1810
- "131072": flags["O_NOFOLLOW"],
1710
+ '1024': flags['O_APPEND'],
1711
+ '64': flags['O_CREAT'],
1712
+ '128': flags['O_EXCL'],
1713
+ '256': flags['O_NOCTTY'],
1714
+ '0': flags['O_RDONLY'],
1715
+ '2': flags['O_RDWR'],
1716
+ '4096': flags['O_SYNC'],
1717
+ '512': flags['O_TRUNC'],
1718
+ '1': flags['O_WRONLY'],
1719
+ '131072': flags['O_NOFOLLOW'],
1811
1720
  };
1812
1721
  // The 0 define must match on both sides, as otherwise we would not
1813
1722
  // know to add it.
1814
- assert(NODEFS.flagsForNodeMap["0"] === 0);
1723
+ assert(NODEFS.flagsForNodeMap['0'] === 0);
1815
1724
  },
1816
1725
  convertNodeCode(e) {
1817
1726
  var code = e.code;
@@ -1926,7 +1835,7 @@ async function createWasm() {
1926
1835
  // update the common node structure mode as well
1927
1836
  node.mode = attr.mode;
1928
1837
  }
1929
- if (typeof (attr.atime ?? attr.mtime) === "number") {
1838
+ if (typeof (attr.atime ?? attr.mtime) === 'number') {
1930
1839
  // Unfortunately, we have to stat the current value if we don't want
1931
1840
  // to change it. On top of that, since the times don't round trip
1932
1841
  // this will only keep the value nearly unchanged not exactly
@@ -1951,7 +1860,11 @@ async function createWasm() {
1951
1860
  if (attr.mode != null && attr.dontFollow) {
1952
1861
  throw new FS.ErrnoError(52);
1953
1862
  }
1954
- NODEFS.setattr(path, node, attr, fs.chmodSync, fs.utimesSync, fs.truncateSync, fs.lstatSync);
1863
+ // `dontFollow` (AT_SYMLINK_NOFOLLOW): use lutimes so the symlink's own
1864
+ // timestamps are set without the host resolving it, which would
1865
+ // otherwise escape the NODEFS mount root.
1866
+ var utimes = attr.dontFollow ? fs.lutimesSync : fs.utimesSync;
1867
+ NODEFS.setattr(path, node, attr, fs.chmodSync, utimes, fs.truncateSync, fs.lstatSync);
1955
1868
  },
1956
1869
  lookup(parent, name) {
1957
1870
  var path = PATH.join2(NODEFS.realPath(parent), name);
@@ -2024,7 +1937,7 @@ async function createWasm() {
2024
1937
  },
2025
1938
  close(stream) {
2026
1939
  NODEFS.tryFSOperation(() => {
2027
- if (stream.nfd && --stream.shared.refcount === 0) {
1940
+ if (stream.nfd && !--stream.shared.refcount) {
2028
1941
  fs.closeSync(stream.nfd);
2029
1942
  }
2030
1943
  });
@@ -2083,6 +1996,70 @@ async function createWasm() {
2083
1996
 
2084
1997
 
2085
1998
 
1999
+
2000
+ var NODERAWFS_stream_funcs = {
2001
+ close(stream) {
2002
+ VFS.closeStream(stream.fd);
2003
+ // Don't close stdin/stdout/stderr since they are used by node itself.
2004
+ if (--stream.shared.refcnt <= 0 && stream.nfd > 2) {
2005
+ // This stream is created by our Node.js filesystem, close the
2006
+ // native file descriptor when its reference count drops to 0.
2007
+ fs.closeSync(stream.nfd);
2008
+ }
2009
+ },
2010
+ llseek(stream, offset, whence) {
2011
+ var position = offset;
2012
+ if (whence === 1) {
2013
+ position += stream.position;
2014
+ } else if (whence === 2) {
2015
+ position += fs.fstatSync(stream.nfd).size;
2016
+ } else if (whence !== 0) {
2017
+ throw new FS.ErrnoError(28);
2018
+ }
2019
+
2020
+ if (position < 0) {
2021
+ throw new FS.ErrnoError(28);
2022
+ }
2023
+ stream.position = position;
2024
+ return position;
2025
+ },
2026
+ read(stream, buffer, offset, length, position) {
2027
+ var seeking = typeof position != 'undefined';
2028
+ if (!seeking && stream.seekable) position = stream.position;
2029
+ var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
2030
+ // update position marker when non-seeking
2031
+ if (!seeking) stream.position += bytesRead;
2032
+ return bytesRead;
2033
+ },
2034
+ write(stream, buffer, offset, length, position) {
2035
+ if (stream.flags & 1024) {
2036
+ // seek to the end before writing in append mode
2037
+ FS.llseek(stream, 0, 2);
2038
+ }
2039
+ var seeking = typeof position != 'undefined';
2040
+ if (!seeking && stream.seekable) position = stream.position;
2041
+ var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
2042
+ // update position marker when non-seeking
2043
+ if (!seeking) stream.position += bytesWritten;
2044
+ return bytesWritten;
2045
+ },
2046
+ mmap(stream, length, position, prot, flags) {
2047
+ if (!length) {
2048
+ throw new FS.ErrnoError(28);
2049
+ }
2050
+ var ptr = mmapAlloc(length);
2051
+ FS.read(stream, HEAP8, ptr, length, position);
2052
+ return { ptr, allocated: true };
2053
+ },
2054
+ msync(stream, buffer, offset, length, mmapFlags) {
2055
+ FS.write(stream, buffer, 0, length, offset);
2056
+ // should we check if bytesWritten and length are the same?
2057
+ return 0;
2058
+ },
2059
+ ioctl(stream, cmd, arg) {
2060
+ throw new FS.ErrnoError(59);
2061
+ },
2062
+ };
2086
2063
  var NODERAWFS = {
2087
2064
  lookup(parent, name) {
2088
2065
  assert(parent)
@@ -2098,11 +2075,10 @@ async function createWasm() {
2098
2075
  return { path, node: { id: st.ino, mode, node_ops: NODERAWFS, path }};
2099
2076
  },
2100
2077
  createStandardStreams() {
2101
- // FIXME: tty is set to true to appease isatty(), the underlying ioctl syscalls still need to be implemented, see issue #22264.
2102
- FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, tty: true, seekable: false }, 0);
2078
+ FS.createStream({ nfd: 0, position: 0, path: '/dev/stdin', flags: 0, seekable: false }, 0);
2103
2079
  var paths = [,'/dev/stdout', '/dev/stderr'];
2104
2080
  for (var i = 1; i < 3; i++) {
2105
- FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577, tty: true, seekable: false }, i);
2081
+ FS.createStream({ nfd: i, position: 0, path: paths[i], flags: 577, seekable: false }, i);
2106
2082
  }
2107
2083
  },
2108
2084
  cwd() { return process.cwd(); },
@@ -2116,6 +2092,14 @@ async function createWasm() {
2116
2092
  },
2117
2093
  mkdir(...args) { fs.mkdirSync(...args); },
2118
2094
  symlink(...args) { fs.symlinkSync(...args); },
2095
+ link(oldpath, newpath, flags) {
2096
+ // AT_SYMLINK_FOLLOW (0x400): dereference oldpath if it is a symlink,
2097
+ // since node's link(2) links to the symlink itself by default.
2098
+ if (flags & 0x400) {
2099
+ oldpath = fs.realpathSync(oldpath);
2100
+ }
2101
+ fs.linkSync(oldpath, newpath);
2102
+ },
2119
2103
  rename(...args) { fs.renameSync(...args); },
2120
2104
  rmdir(...args) { fs.rmdirSync(...args); },
2121
2105
  readdir(...args) { return ['.', '..'].concat(fs.readdirSync(...args)); },
@@ -2132,6 +2116,12 @@ async function createWasm() {
2132
2116
  },
2133
2117
  fstat(fd) {
2134
2118
  var stream = FS.getStreamChecked(fd);
2119
+ // Virtual streams (pipes, sockets) have no backing node fd; defer to their
2120
+ // own getattr rather than node's fs.fstatSync.
2121
+ var getattr = stream.stream_ops?.getattr ?? stream.node.node_ops?.getattr;
2122
+ if (getattr) {
2123
+ return getattr(stream.stream_ops?.getattr ? stream : stream.node);
2124
+ }
2135
2125
  return fs.fstatSync(stream.nfd);
2136
2126
  },
2137
2127
  statfs(path) {
@@ -2185,21 +2175,23 @@ async function createWasm() {
2185
2175
  var stream = FS.getStreamChecked(fd);
2186
2176
  fs.ftruncateSync(stream.nfd, len);
2187
2177
  },
2188
- utime(path, atime, mtime) {
2178
+ utime(path, atime, mtime, dontFollow) {
2189
2179
  // null here for atime or mtime means UTIME_OMIT was passed. Since node
2190
2180
  // doesn't support this concept we need to first find the existing
2191
2181
  // timestamps in order to preserve them.
2192
2182
  if ((atime === null) || (mtime === null)) {
2193
- var st = fs.statSync(path);
2183
+ var st = dontFollow ? fs.lstatSync(path) : fs.statSync(path);
2194
2184
  atime ||= st.atimeMs;
2195
2185
  mtime ||= st.mtimeMs;
2196
2186
  }
2197
- fs.utimesSync(path, atime/1000, mtime/1000);
2187
+ if (dontFollow) {
2188
+ fs.lutimesSync(path, atime/1000, mtime/1000);
2189
+ } else {
2190
+ fs.utimesSync(path, atime/1000, mtime/1000);
2191
+ }
2198
2192
  },
2199
2193
  open(path, flags, mode) {
2200
- if (typeof flags == "string") {
2201
- flags = FS_modeStringToFlags(flags)
2202
- }
2194
+ flags = FS_modeStringToFlags(flags);
2203
2195
  var pathTruncated = path.split('/').map((s) => s.slice(0, 255)).join('/');
2204
2196
  var nfd = fs.openSync(pathTruncated, NODEFS.flagsForNode(flags), mode);
2205
2197
  var st = fs.fstatSync(nfd);
@@ -2214,96 +2206,14 @@ async function createWasm() {
2214
2206
  createStream(stream, fd) {
2215
2207
  // Call the original FS.createStream
2216
2208
  var rtn = VFS.createStream(stream, fd);
2217
- if (typeof rtn.shared.refcnt == 'undefined') {
2218
- rtn.shared.refcnt = 1;
2219
- } else {
2209
+ // Detect PIPEFS streams and skip the refcnt/tty initialization in that case.
2210
+ if (!stream.stream_ops) {
2211
+ rtn.shared.refcnt ??= 0;
2220
2212
  rtn.shared.refcnt++;
2213
+ rtn.tty = nodeTTY.isatty(rtn.nfd);
2221
2214
  }
2222
2215
  return rtn;
2223
2216
  },
2224
- close(stream) {
2225
- VFS.closeStream(stream.fd);
2226
- // Don't close stdin/stdout/stderr since they are used by node itself.
2227
- if (!stream.stream_ops && --stream.shared.refcnt <= 0 && stream.nfd > 2) {
2228
- // This stream is created by our Node.js filesystem, close the
2229
- // native file descriptor when its reference count drops to 0.
2230
- fs.closeSync(stream.nfd);
2231
- }
2232
- },
2233
- llseek(stream, offset, whence) {
2234
- if (stream.stream_ops) {
2235
- // this stream is created by in-memory filesystem
2236
- return VFS.llseek(stream, offset, whence);
2237
- }
2238
- var position = offset;
2239
- if (whence === 1) {
2240
- position += stream.position;
2241
- } else if (whence === 2) {
2242
- position += fs.fstatSync(stream.nfd).size;
2243
- } else if (whence !== 0) {
2244
- throw new FS.ErrnoError(28);
2245
- }
2246
-
2247
- if (position < 0) {
2248
- throw new FS.ErrnoError(28);
2249
- }
2250
- stream.position = position;
2251
- return position;
2252
- },
2253
- read(stream, buffer, offset, length, position) {
2254
- if (stream.stream_ops) {
2255
- // this stream is created by in-memory filesystem
2256
- return VFS.read(stream, buffer, offset, length, position);
2257
- }
2258
- var seeking = typeof position != 'undefined';
2259
- if (!seeking && stream.seekable) position = stream.position;
2260
- var bytesRead = fs.readSync(stream.nfd, buffer, offset, length, position);
2261
- // update position marker when non-seeking
2262
- if (!seeking) stream.position += bytesRead;
2263
- return bytesRead;
2264
- },
2265
- write(stream, buffer, offset, length, position) {
2266
- if (stream.stream_ops) {
2267
- // this stream is created by in-memory filesystem
2268
- return VFS.write(stream, buffer, offset, length, position);
2269
- }
2270
- if (stream.flags & +"1024") {
2271
- // seek to the end before writing in append mode
2272
- FS.llseek(stream, 0, +"2");
2273
- }
2274
- var seeking = typeof position != 'undefined';
2275
- if (!seeking && stream.seekable) position = stream.position;
2276
- var bytesWritten = fs.writeSync(stream.nfd, buffer, offset, length, position);
2277
- // update position marker when non-seeking
2278
- if (!seeking) stream.position += bytesWritten;
2279
- return bytesWritten;
2280
- },
2281
- mmap(stream, length, position, prot, flags) {
2282
- if (!length) {
2283
- throw new FS.ErrnoError(28);
2284
- }
2285
- if (stream.stream_ops) {
2286
- // this stream is created by in-memory filesystem
2287
- return VFS.mmap(stream, length, position, prot, flags);
2288
- }
2289
-
2290
- var ptr = mmapAlloc(length);
2291
- FS.read(stream, HEAP8, ptr, length, position);
2292
- return { ptr, allocated: true };
2293
- },
2294
- msync(stream, buffer, offset, length, mmapFlags) {
2295
- if (stream.stream_ops) {
2296
- // this stream is created by in-memory filesystem
2297
- return VFS.msync(stream, buffer, offset, length, mmapFlags);
2298
- }
2299
-
2300
- FS.write(stream, buffer, 0, length, offset);
2301
- // should we check if bytesWritten and length are the same?
2302
- return 0;
2303
- },
2304
- ioctl() {
2305
- throw new FS.ErrnoError(59);
2306
- },
2307
2217
  };
2308
2218
 
2309
2219
 
@@ -2328,6 +2238,73 @@ async function createWasm() {
2328
2238
  }
2329
2239
  };
2330
2240
 
2241
+ var dependenciesPromise = null;
2242
+ var resolveRunDependencies = async () => dependenciesPromise;
2243
+ var runDependencies = 0;
2244
+
2245
+
2246
+ var dependenciesPromiseResolve = null;
2247
+
2248
+ var runDependencyTracking = {
2249
+ };
2250
+
2251
+ var runDependencyWatcher = null;
2252
+ var removeRunDependency = (id) => {
2253
+ runDependencies--;
2254
+
2255
+ Module['monitorRunDependencies']?.(runDependencies);
2256
+
2257
+ assert(id, 'removeRunDependency requires an ID');
2258
+ assert(runDependencyTracking[id]);
2259
+ delete runDependencyTracking[id];
2260
+ if (!runDependencies) {
2261
+ if (runDependencyWatcher !== null) {
2262
+ clearInterval(runDependencyWatcher);
2263
+ runDependencyWatcher = null;
2264
+ }
2265
+ dependenciesPromiseResolve();
2266
+ }
2267
+ };
2268
+
2269
+
2270
+
2271
+
2272
+ var addRunDependency = (id) => {
2273
+ if (!runDependencies) {
2274
+ dependenciesPromise = new Promise((resolve) => dependenciesPromiseResolve = resolve);
2275
+ }
2276
+ runDependencies++;
2277
+
2278
+ Module['monitorRunDependencies']?.(runDependencies);
2279
+
2280
+ assert(id, 'addRunDependency requires an ID')
2281
+ assert(!runDependencyTracking[id]);
2282
+ runDependencyTracking[id] = 1;
2283
+ if (!runDependencyWatcher && globalThis.setInterval) {
2284
+ // Check for missing dependencies every few seconds
2285
+ runDependencyWatcher = setInterval(() => {
2286
+ if (ABORT) {
2287
+ clearInterval(runDependencyWatcher);
2288
+ runDependencyWatcher = null;
2289
+ return;
2290
+ }
2291
+ var shown = false;
2292
+ for (var dep in runDependencyTracking) {
2293
+ if (!shown) {
2294
+ shown = true;
2295
+ err('still waiting on run dependencies:');
2296
+ }
2297
+ err(`dependency: ${dep}`);
2298
+ }
2299
+ if (shown) {
2300
+ err('(end of list)');
2301
+ }
2302
+ }, 10000);
2303
+ // Prevent this timer from keeping the runtime alive if nothing
2304
+ // else is.
2305
+ runDependencyWatcher.unref?.()
2306
+ }
2307
+ };
2331
2308
 
2332
2309
 
2333
2310
  var preloadPlugins = [];
@@ -2370,6 +2347,7 @@ async function createWasm() {
2370
2347
  var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
2371
2348
  FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror);
2372
2349
  };
2350
+
2373
2351
  var FS = {
2374
2352
  root:null,
2375
2353
  mounts:[],
@@ -2468,6 +2446,48 @@ async function createWasm() {
2468
2446
  get isDevice() {
2469
2447
  return FS.isChrdev(this.mode);
2470
2448
  }
2449
+ // The per-inode readiness wait-queue. The node carries a Set of listener
2450
+ // entries {cb}; producers (SOCKFS, PIPEFS) call notifyListeners on a
2451
+ // readiness transition, and poll()/epoll consume it. It lives on the node
2452
+ // (not the fd) so dup'd fds share one queue. Only nodes that derive real
2453
+ // readiness (sockets, pipes, and an epoll's own node) ever use this -
2454
+ // always-ready types (regular files, ttys) never register or notify.
2455
+ addListener(cb, exclusive = false) {
2456
+ var entry = {cb, exclusive};
2457
+ var listeners = (this.listeners ??= new Set());
2458
+ listeners.add(entry);
2459
+ return {listeners, entry};
2460
+ }
2461
+ notifyListeners(flags) {
2462
+ // Iterates the set without copying, which is safe ONLY under a
2463
+ // load-bearing contract that every internal listener must honour:
2464
+ // 1. A listener must not run user code synchronously (a poll waiter only
2465
+ // resolves a Promise; an epoll registration only re-lists +
2466
+ // re-notifies; the epoll callback only schedules a tick). User code
2467
+ // runs on a later tick, never inside this loop.
2468
+ // 2. A listener may delete entries only from ITS OWN waiter, never from
2469
+ // a sibling node's set that may be mid-iteration. (Deleting an entry
2470
+ // of the set being iterated here is fine - a Set tolerates removal of
2471
+ // a not-yet-visited entry mid-iteration; mutating a *different* node's
2472
+ // set is fine because that set is not being iterated.)
2473
+ // Violating either gives silently skipped wakeups that are near-impossible
2474
+ // to reproduce. Any new producer/listener must preserve it.
2475
+ if (!this.listeners) return;
2476
+ // Fire every non-exclusive listener. Among EPOLLEXCLUSIVE registrations
2477
+ // (one fd watched by several epolls) wake only one, rotating round-robin
2478
+ // per node, to avoid a thundering herd. (Only epoll registrations are ever
2479
+ // exclusive; poll waiters and a node's own consumers are not.)
2480
+ var excl;
2481
+ for (var entry of this.listeners) {
2482
+ if (entry.exclusive) (excl ||= []).push(entry);
2483
+ else entry.cb(flags);
2484
+ }
2485
+ if (excl) {
2486
+ var i = (this.exclTurn || 0) % excl.length;
2487
+ this.exclTurn = i + 1;
2488
+ excl[i].cb(flags);
2489
+ }
2490
+ }
2471
2491
  },
2472
2492
  lookupPath(path, opts = {}) {
2473
2493
  if (!path) {
@@ -2479,7 +2499,7 @@ async function createWasm() {
2479
2499
  path = FS.cwd() + '/' + path;
2480
2500
  }
2481
2501
 
2482
- // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
2502
+ // limit max consecutive symlinks to SYMLOOP_MAX.
2483
2503
  linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
2484
2504
  // split the absolute path
2485
2505
  var parts = path.split('/').filter((p) => !!p);
@@ -2771,7 +2791,14 @@ async function createWasm() {
2771
2791
  var arg = setattr ? stream : node;
2772
2792
  setattr ??= node.node_ops.setattr;
2773
2793
  FS.checkOpExists(setattr, 63)
2774
- setattr(arg, attr);
2794
+ try {
2795
+ setattr(arg, attr);
2796
+ } catch (e) {
2797
+ if (e instanceof RangeError) {
2798
+ throw new FS.ErrnoError(22);
2799
+ }
2800
+ throw e;
2801
+ }
2775
2802
  },
2776
2803
  chrdev_stream_ops:{
2777
2804
  open(stream) {
@@ -3038,6 +3065,25 @@ async function createWasm() {
3038
3065
  }
3039
3066
  return parent.node_ops.symlink(parent, newname, oldpath);
3040
3067
  },
3068
+ link(oldpath, newpath, flags) {
3069
+ var lookup = FS.lookupPath(newpath, { parent: true });
3070
+ var parent = lookup.node;
3071
+ if (!parent) {
3072
+ throw new FS.ErrnoError(44);
3073
+ }
3074
+ var newname = PATH.basename(newpath);
3075
+ var errCode = FS.mayCreate(parent, newname);
3076
+ if (errCode) {
3077
+ throw new FS.ErrnoError(errCode);
3078
+ }
3079
+ // Hardlinks are only supported by filesystem backends that provide a
3080
+ // `link` node op (e.g. NODERAWFS backed by the host). NODEFS omits it:
3081
+ // a host hardlink cannot be confined to the mount root.
3082
+ if (!parent.node_ops.link) {
3083
+ throw new FS.ErrnoError(34);
3084
+ }
3085
+ return parent.node_ops.link(parent, newname, oldpath, flags);
3086
+ },
3041
3087
  rename(old_path, new_path) {
3042
3088
  var old_dirname = PATH.dirname(old_path);
3043
3089
  var new_dirname = PATH.dirname(new_path);
@@ -3284,20 +3330,19 @@ async function createWasm() {
3284
3330
  }
3285
3331
  FS.doTruncate(stream, stream.node, len);
3286
3332
  },
3287
- utime(path, atime, mtime) {
3288
- var lookup = FS.lookupPath(path, { follow: true });
3289
- var node = lookup.node;
3290
- var setattr = FS.checkOpExists(node.node_ops.setattr, 63);
3291
- setattr(node, {
3333
+ utime(path, atime, mtime, dontFollow) {
3334
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
3335
+ FS.doSetAttr(null, lookup.node, {
3292
3336
  atime: atime,
3293
- mtime: mtime
3337
+ mtime: mtime,
3338
+ dontFollow
3294
3339
  });
3295
3340
  },
3296
3341
  open(path, flags, mode = 0o666) {
3297
- if (path === "") {
3342
+ if (path === '') {
3298
3343
  throw new FS.ErrnoError(44);
3299
3344
  }
3300
- flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags;
3345
+ flags = FS_modeStringToFlags(flags);
3301
3346
  if ((flags & 64)) {
3302
3347
  mode = (mode & 4095) | 32768;
3303
3348
  } else {
@@ -3308,7 +3353,7 @@ async function createWasm() {
3308
3353
  if (typeof path == 'object') {
3309
3354
  node = path;
3310
3355
  } else {
3311
- isDirPath = path.endsWith("/");
3356
+ isDirPath = path.endsWith('/');
3312
3357
  // noent_okay makes it so that if the final component of the path
3313
3358
  // doesn't exist, lookupPath returns `node: undefined`. `path` will be
3314
3359
  // updated to point to the target of all symlinks.
@@ -3391,6 +3436,11 @@ async function createWasm() {
3391
3436
  throw new FS.ErrnoError(8);
3392
3437
  }
3393
3438
  if (stream.getdents) stream.getdents = null; // free readdir state
3439
+ // The fd is going away: wake anything waiting on it (poll/epoll) with
3440
+ // POLLNVAL so a blocking wait unblocks and an epoll registration is evicted
3441
+ // on its next derive. Only sockets/pipes/epoll ever carry a wait-queue, so
3442
+ // for every other stream (incl. nodeless noderawfs stdio) this is a no-op.
3443
+ stream.node?.notifyListeners(32);
3394
3444
  try {
3395
3445
  if (stream.stream_ops.close) {
3396
3446
  stream.stream_ops.close(stream);
@@ -3448,6 +3498,7 @@ async function createWasm() {
3448
3498
  },
3449
3499
  write(stream, buffer, offset, length, position, canOwn) {
3450
3500
  assert(offset >= 0);
3501
+ assert(buffer.subarray, 'FS.write expects a TypedArray');
3451
3502
  if (length < 0 || position < 0) {
3452
3503
  throw new FS.ErrnoError(28);
3453
3504
  }
@@ -3484,8 +3535,8 @@ async function createWasm() {
3484
3535
  // to write to file opened in read-only mode with MAP_PRIVATE flag,
3485
3536
  // as all modifications will be visible only in the memory of
3486
3537
  // the current process.
3487
- if ((prot & 2) !== 0
3488
- && (flags & 2) === 0
3538
+ if ((prot & 2)
3539
+ && !(flags & 2)
3489
3540
  && (stream.flags & 2097155) !== 2) {
3490
3541
  throw new FS.ErrnoError(2);
3491
3542
  }
@@ -3514,8 +3565,8 @@ async function createWasm() {
3514
3565
  return stream.stream_ops.ioctl(stream, cmd, arg);
3515
3566
  },
3516
3567
  readFile(path, opts = {}) {
3517
- opts.flags = opts.flags || 0;
3518
- opts.encoding = opts.encoding || 'binary';
3568
+ opts.flags = opts.flags ?? 0;
3569
+ opts.encoding = opts.encoding ?? 'binary';
3519
3570
  if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
3520
3571
  abort(`Invalid encoding type "${opts.encoding}"`);
3521
3572
  }
@@ -3531,16 +3582,10 @@ async function createWasm() {
3531
3582
  return buf;
3532
3583
  },
3533
3584
  writeFile(path, data, opts = {}) {
3534
- opts.flags = opts.flags || 577;
3585
+ opts.flags = opts.flags ?? 577;
3535
3586
  var stream = FS.open(path, opts.flags, opts.mode);
3536
- if (typeof data == 'string') {
3537
- data = new Uint8Array(intArrayFromString(data, true));
3538
- }
3539
- if (ArrayBuffer.isView(data)) {
3540
- FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3541
- } else {
3542
- abort('Unsupported data type');
3543
- }
3587
+ data = FS_fileDataToTypedArray(data);
3588
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
3544
3589
  FS.close(stream);
3545
3590
  },
3546
3591
  cwd:() => FS.currentPath,
@@ -3584,7 +3629,7 @@ async function createWasm() {
3584
3629
  // use a buffer to avoid overhead of individual crypto calls per byte
3585
3630
  var randomBuffer = new Uint8Array(1024), randomLeft = 0;
3586
3631
  var randomByte = () => {
3587
- if (randomLeft === 0) {
3632
+ if (!randomLeft) {
3588
3633
  randomFill(randomBuffer);
3589
3634
  randomLeft = randomBuffer.byteLength;
3590
3635
  }
@@ -3766,11 +3811,7 @@ async function createWasm() {
3766
3811
  var mode = FS_getMode(canRead, canWrite);
3767
3812
  var node = FS.create(path, mode);
3768
3813
  if (data) {
3769
- if (typeof data == 'string') {
3770
- var arr = new Array(data.length);
3771
- for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
3772
- data = arr;
3773
- }
3814
+ data = FS_fileDataToTypedArray(data);
3774
3815
  // make sure we can write to the file
3775
3816
  FS.chmod(node, mode | 146);
3776
3817
  var stream = FS.open(node, 577);
@@ -3805,7 +3846,7 @@ async function createWasm() {
3805
3846
  } catch (e) {
3806
3847
  throw new FS.ErrnoError(29);
3807
3848
  }
3808
- if (result === undefined && bytesRead === 0) {
3849
+ if (result === undefined && !bytesRead) {
3809
3850
  throw new FS.ErrnoError(6);
3810
3851
  }
3811
3852
  if (result === null || result === undefined) break;
@@ -3836,7 +3877,7 @@ async function createWasm() {
3836
3877
  forceLoadFile(obj) {
3837
3878
  if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
3838
3879
  if (globalThis.XMLHttpRequest) {
3839
- abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
3880
+ abort('Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.');
3840
3881
  } else { // Command-line.
3841
3882
  try {
3842
3883
  obj.contents = readBinary(obj.url);
@@ -3867,11 +3908,11 @@ async function createWasm() {
3867
3908
  var xhr = new XMLHttpRequest();
3868
3909
  xhr.open('HEAD', url, false);
3869
3910
  xhr.send(null);
3870
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
3871
- var datalength = Number(xhr.getResponseHeader("Content-length"));
3911
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`);
3912
+ var datalength = Number(xhr.getResponseHeader('Content-length'));
3872
3913
  var header;
3873
- var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
3874
- var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
3914
+ var hasByteServing = (header = xhr.getResponseHeader('Accept-Ranges')) && header === 'bytes';
3915
+ var usesGzip = (header = xhr.getResponseHeader('Content-Encoding')) && header === 'gzip';
3875
3916
 
3876
3917
  var chunkSize = 1024*1024; // Chunk size in bytes
3877
3918
 
@@ -3879,13 +3920,13 @@ async function createWasm() {
3879
3920
 
3880
3921
  // Function to get a range from the remote URL.
3881
3922
  var doXHR = (from, to) => {
3882
- if (from > to) abort("invalid range (" + from + ", " + to + ") or no bytes requested!");
3883
- if (to > datalength-1) abort("only " + datalength + " bytes available! programmer error!");
3923
+ if (from > to) abort(`invalid range (${from}, ${to}) or no bytes requested!`);
3924
+ if (to > datalength-1) abort(`only ${datalength} bytes available! programmer error!`);
3884
3925
 
3885
3926
  // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
3886
3927
  var xhr = new XMLHttpRequest();
3887
3928
  xhr.open('GET', url, false);
3888
- if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
3929
+ if (datalength !== chunkSize) xhr.setRequestHeader('Range', `bytes=${from}-${to}`);
3889
3930
 
3890
3931
  // Some hints to the browser that we want binary data.
3891
3932
  xhr.responseType = 'arraybuffer';
@@ -3894,11 +3935,11 @@ async function createWasm() {
3894
3935
  }
3895
3936
 
3896
3937
  xhr.send(null);
3897
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort("Couldn't load " + url + ". Status: " + xhr.status);
3938
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) abort(`Couldn't load ${url}. Status: ${xhr.status}`);
3898
3939
  if (xhr.response !== undefined) {
3899
3940
  return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
3900
3941
  }
3901
- return intArrayFromString(xhr.responseText || '', true);
3942
+ return intArrayFromString(xhr.responseText ?? '', true);
3902
3943
  };
3903
3944
  var lazyArray = this;
3904
3945
  lazyArray.setDataGetter((chunkNum) => {
@@ -3917,7 +3958,7 @@ async function createWasm() {
3917
3958
  chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
3918
3959
  datalength = this.getter(0).length;
3919
3960
  chunkSize = datalength;
3920
- out("LazyFiles on gzip forces download of the whole file when length is accessed");
3961
+ out('LazyFiles on gzip forces download of the whole file when length is accessed');
3921
3962
  }
3922
3963
 
3923
3964
  this._length = datalength;
@@ -4005,27 +4046,16 @@ async function createWasm() {
4005
4046
  node.stream_ops = stream_ops;
4006
4047
  return node;
4007
4048
  },
4008
- absolutePath() {
4009
- abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
4010
- },
4011
- createFolder() {
4012
- abort('FS.createFolder has been removed; use FS.mkdir instead');
4013
- },
4014
- createLink() {
4015
- abort('FS.createLink has been removed; use FS.symlink instead');
4016
- },
4017
- joinPath() {
4018
- abort('FS.joinPath has been removed; use PATH.join instead');
4019
- },
4020
- mmapAlloc() {
4021
- abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
4022
- },
4023
- standardizePath() {
4024
- abort('FS.standardizePath has been removed; use PATH.normalize instead');
4025
- },
4026
4049
  };
4027
4050
 
4051
+
4052
+
4053
+
4054
+
4055
+ /** not-@type {!BigInt64Array} */
4056
+ var HEAP64;
4028
4057
  var SYSCALLS = {
4058
+ currentUmask:18,
4029
4059
  calculateAt(dirfd, path, allowEmpty) {
4030
4060
  if (PATH.isAbs(path)) {
4031
4061
  return path;
@@ -4088,7 +4118,7 @@ async function createWasm() {
4088
4118
  // MAP_PRIVATE calls need not to be synced back to underlying fs
4089
4119
  return 0;
4090
4120
  }
4091
- var buffer = HEAPU8.slice(addr, addr + len);
4121
+ var buffer = HEAPU8.subarray(addr, addr + len);
4092
4122
  FS.msync(stream, buffer, offset, len, flags);
4093
4123
  },
4094
4124
  getStreamFromFD(fd) {
@@ -4101,6 +4131,9 @@ async function createWasm() {
4101
4131
  return ret;
4102
4132
  },
4103
4133
  };
4134
+
4135
+ /** @type {!Int16Array} */
4136
+ var HEAP16;
4104
4137
  function ___syscall_fcntl64(fd, cmd, varargs) {
4105
4138
  SYSCALLS.varargs = varargs;
4106
4139
  try {
@@ -4126,7 +4159,8 @@ async function createWasm() {
4126
4159
  return stream.flags;
4127
4160
  case 4: {
4128
4161
  var arg = syscallGetVarargI();
4129
- stream.flags |= arg;
4162
+ var mask = 289792;
4163
+ stream.flags = (stream.flags & ~mask) | (arg & mask);
4130
4164
  return 0;
4131
4165
  }
4132
4166
  case 12: {
@@ -4150,8 +4184,12 @@ async function createWasm() {
4150
4184
  return -e.errno;
4151
4185
  }
4152
4186
  }
4187
+
4153
4188
 
4154
4189
 
4190
+
4191
+
4192
+
4155
4193
  function ___syscall_ioctl(fd, op, varargs) {
4156
4194
  SYSCALLS.varargs = varargs;
4157
4195
  try {
@@ -4247,6 +4285,7 @@ async function createWasm() {
4247
4285
  return -e.errno;
4248
4286
  }
4249
4287
  }
4288
+
4250
4289
 
4251
4290
 
4252
4291
  function ___syscall_openat(dirfd, path, flags, varargs) {
@@ -4256,18 +4295,22 @@ async function createWasm() {
4256
4295
  path = SYSCALLS.getStr(path);
4257
4296
  path = SYSCALLS.calculateAt(dirfd, path);
4258
4297
  var mode = varargs ? syscallGetVarargI() : 0;
4298
+ if (flags & 64) {
4299
+ mode &= ~SYSCALLS.currentUmask;
4300
+ }
4259
4301
  return FS.open(path, flags, mode).fd;
4260
4302
  } catch (e) {
4261
4303
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
4262
4304
  return -e.errno;
4263
4305
  }
4264
4306
  }
4307
+
4265
4308
 
4266
4309
  var __abort_js = () =>
4267
4310
  abort('native code called abort()');
4268
4311
 
4269
4312
  var __emscripten_throw_longjmp = () => {
4270
- throw Infinity;
4313
+ throw new EmscriptenSjLj;
4271
4314
  };
4272
4315
 
4273
4316
 
@@ -4311,9 +4354,10 @@ async function createWasm() {
4311
4354
  } catch(e) {
4312
4355
  err(`growMemory: Attempted to grow heap from ${oldHeapSize} bytes to ${size} bytes, but got error: ${e}`);
4313
4356
  }
4314
- // implicit 0 return to save code size (caller will cast "undefined" into 0
4357
+ // implicit 0 return to save code size (caller will cast 'undefined' into 0
4315
4358
  // anyhow)
4316
4359
  };
4360
+
4317
4361
  var _emscripten_resize_heap = (requestedSize) => {
4318
4362
  var oldSize = HEAPU8.length;
4319
4363
  // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
@@ -4409,7 +4453,9 @@ async function createWasm() {
4409
4453
  return e.errno;
4410
4454
  }
4411
4455
  }
4456
+
4412
4457
 
4458
+
4413
4459
  /** @param {number=} offset */
4414
4460
  var doReadv = (stream, iov, iovcnt, offset) => {
4415
4461
  var ret = 0;
@@ -4417,7 +4463,18 @@ async function createWasm() {
4417
4463
  var ptr = HEAPU32[((iov)>>2)];
4418
4464
  var len = HEAPU32[(((iov)+(4))>>2)];
4419
4465
  iov += 8;
4420
- var curr = FS.read(stream, HEAP8, ptr, len, offset);
4466
+ try {
4467
+ var curr = FS.read(stream, HEAP8, ptr, len, offset);
4468
+ } catch (e) {
4469
+ // On a non-blocking stream a subsequent read may would-block after we
4470
+ // already gathered data. POSIX readv is a single gather-read: return
4471
+ // what we have rather than failing the whole call.
4472
+ if (ret > 0 && e instanceof FS.ErrnoError &&
4473
+ (e.errno == 6 || e.errno == 6)) {
4474
+ break;
4475
+ }
4476
+ throw e;
4477
+ }
4421
4478
  if (curr < 0) return -1;
4422
4479
  ret += curr;
4423
4480
  if (curr < len) break; // nothing more to read
@@ -4428,6 +4485,7 @@ async function createWasm() {
4428
4485
  return ret;
4429
4486
  };
4430
4487
 
4488
+
4431
4489
  function _fd_read(fd, iov, iovcnt, pnum) {
4432
4490
  try {
4433
4491
 
@@ -4440,19 +4498,21 @@ async function createWasm() {
4440
4498
  return e.errno;
4441
4499
  }
4442
4500
  }
4501
+
4443
4502
 
4444
4503
 
4504
+
4445
4505
  function _fd_seek(fd, offset, whence, newOffset) {
4446
4506
  offset = bigintToI53Checked(offset);
4447
4507
 
4448
4508
 
4449
4509
  try {
4450
4510
 
4451
- if (isNaN(offset)) return 61;
4511
+ if (isNaN(offset)) return 22;
4452
4512
  var stream = SYSCALLS.getStreamFromFD(fd);
4453
4513
  FS.llseek(stream, offset, whence);
4454
4514
  HEAP64[((newOffset)>>3)] = BigInt(stream.position);
4455
- if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
4515
+ if (stream.getdents && !offset && whence === 0) stream.getdents = null; // reset readdir state
4456
4516
  return 0;
4457
4517
  } catch (e) {
4458
4518
  if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
@@ -4461,27 +4521,34 @@ async function createWasm() {
4461
4521
  ;
4462
4522
  }
4463
4523
 
4524
+
4525
+
4464
4526
  /** @param {number=} offset */
4465
4527
  var doWritev = (stream, iov, iovcnt, offset) => {
4466
- var ret = 0;
4467
- for (var i = 0; i < iovcnt; i++) {
4528
+ // Gather all iovecs into one contiguous buffer and issue a single
4529
+ // FS.write, matching POSIX writev's single gather-write semantics (as
4530
+ // __syscall_sendmsg already does). Per-iovec writes fragment a stream
4531
+ // socket send into multiple segments, breaking stream byte semantics.
4532
+ if (iovcnt == 1) {
4533
+ // Single iovec: write directly from HEAP8, no gather buffer needed.
4534
+ return FS.write(stream, HEAP8, HEAPU32[((iov)>>2)], HEAPU32[(((iov)+(4))>>2)], offset);
4535
+ }
4536
+ var total = 0;
4537
+ for (var i = 0, p = iov; i < iovcnt; i++, p += 8) {
4538
+ total += HEAPU32[(((p)+(4))>>2)];
4539
+ }
4540
+ var view = new Uint8Array(total);
4541
+ var voff = 0;
4542
+ for (var i = 0; i < iovcnt; i++, iov += 8) {
4468
4543
  var ptr = HEAPU32[((iov)>>2)];
4469
4544
  var len = HEAPU32[(((iov)+(4))>>2)];
4470
- iov += 8;
4471
- var curr = FS.write(stream, HEAP8, ptr, len, offset);
4472
- if (curr < 0) return -1;
4473
- ret += curr;
4474
- if (curr < len) {
4475
- // No more space to write.
4476
- break;
4477
- }
4478
- if (typeof offset != 'undefined') {
4479
- offset += curr;
4480
- }
4545
+ view.set(HEAPU8.subarray(ptr, ptr + len), voff);
4546
+ voff += len;
4481
4547
  }
4482
- return ret;
4548
+ return FS.write(stream, view, 0, total, offset);
4483
4549
  };
4484
4550
 
4551
+
4485
4552
  function _fd_write(fd, iov, iovcnt, pnum) {
4486
4553
  try {
4487
4554
 
@@ -4494,6 +4561,7 @@ async function createWasm() {
4494
4561
  return e.errno;
4495
4562
  }
4496
4563
  }
4564
+
4497
4565
 
4498
4566
 
4499
4567
  var handleException = (e) => {
@@ -4515,8 +4583,9 @@ async function createWasm() {
4515
4583
  };
4516
4584
 
4517
4585
 
4586
+
4518
4587
  var stringToUTF8 = (str, outPtr, maxBytesToWrite) => {
4519
- assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
4588
+ assert(typeof maxBytesToWrite == 'number', 'stringToUTF8 requires a third parameter that specifies the length of the output buffer');
4520
4589
  return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
4521
4590
  };
4522
4591
 
@@ -4528,6 +4597,7 @@ async function createWasm() {
4528
4597
  return ret;
4529
4598
  };
4530
4599
 
4600
+
4531
4601
  var wasmTableMirror = [];
4532
4602
 
4533
4603
 
@@ -4538,7 +4608,7 @@ async function createWasm() {
4538
4608
  wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
4539
4609
  }
4540
4610
  /** @suppress {checkTypes} */
4541
- assert(wasmTable.get(funcPtr) == func, 'JavaScript-side Wasm function table mirror is out of date!');
4611
+ assert(wasmTable.get(funcPtr) == func, 'table mirror is out of date');
4542
4612
  return func;
4543
4613
  };
4544
4614
 
@@ -4548,10 +4618,11 @@ async function createWasm() {
4548
4618
  if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
4549
4619
 
4550
4620
  if (!ENVIRONMENT_IS_NODE) {
4551
- throw new Error("NODERAWFS is currently only supported on Node.js environment.")
4621
+ throw new Error('NODERAWFS is currently only supported on Node.js environment.')
4552
4622
  }
4553
- var _wrapNodeError = function(func) {
4554
- return function(...args) {
4623
+ var nodeTTY = require('node:tty');
4624
+ function _wrapNodeError(func) {
4625
+ return (...args) => {
4555
4626
  try {
4556
4627
  return func(...args)
4557
4628
  } catch (e) {
@@ -4566,14 +4637,26 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
4566
4637
  throw e;
4567
4638
  }
4568
4639
  }
4569
- };
4640
+ }
4641
+ function _wrapNodeStreamFunc(func, vfs_func) {
4642
+ return _wrapNodeError((stream, ...args) => {
4643
+ if (stream.stream_ops) {
4644
+ // this stream was created by some other FS. e.g: PIPEFS.
4645
+ return vfs_func(stream, ...args);
4646
+ }
4647
+ return func(stream, ...args);
4648
+ });
4649
+ }
4570
4650
  // Use this to reference our in-memory filesystem
4571
4651
  /** @suppress {partialAlias} */
4572
4652
  var VFS = {...FS};
4573
4653
  // Wrap the whole in-memory filesystem API with
4574
4654
  // our Node.js based functions
4575
- for (var _key in NODERAWFS) {
4576
- FS[_key] = _wrapNodeError(NODERAWFS[_key]);
4655
+ for (const [key, value] of Object.entries(NODERAWFS)) {
4656
+ FS[key] = _wrapNodeError(value);
4657
+ }
4658
+ for (const [key, value] of Object.entries(NODERAWFS_stream_funcs)) {
4659
+ FS[key] = _wrapNodeStreamFunc(value, FS[key]);
4577
4660
  };
4578
4661
  // End JS library code
4579
4662
 
@@ -4585,15 +4668,14 @@ if (ENVIRONMENT_IS_NODE) { NODEFS.staticInit(); };
4585
4668
 
4586
4669
  // Begin ATMODULES hooks
4587
4670
  if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
4588
- if (Module['preloadPlugins']) preloadPlugins = Module['preloadPlugins'];
4671
+
4589
4672
  if (Module['print']) out = Module['print'];
4590
4673
  if (Module['printErr']) err = Module['printErr'];
4591
- if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4592
4674
  // End ATMODULES hooks
4593
4675
 
4594
4676
  checkIncomingModuleAPI();
4595
4677
 
4596
- if (Module['arguments']) arguments_ = Module['arguments'];
4678
+ if (Module['arguments']) programArgs = Module['arguments'];
4597
4679
  if (Module['thisProgram']) thisProgram = Module['thisProgram'];
4598
4680
 
4599
4681
  // Assertions on removed incoming Module JS APIs.
@@ -4612,10 +4694,13 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4612
4694
  assert(typeof Module['wasmMemory'] == 'undefined', 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally');
4613
4695
  assert(typeof Module['INITIAL_MEMORY'] == 'undefined', 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically');
4614
4696
 
4615
- if (Module['preInit']) {
4616
- if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
4617
- while (Module['preInit'].length > 0) {
4618
- Module['preInit'].shift()();
4697
+ var preInit = Module['preInit'];
4698
+ if (preInit) {
4699
+ if (typeof preInit == 'function') Module['preInit'] = preInit = [preInit];
4700
+ // Written as a loop so that preInit functions that themselves add more
4701
+ // preInit functions. Is this actually needed?
4702
+ while (preInit.length > 0) {
4703
+ preInit.shift()();
4619
4704
  }
4620
4705
  }
4621
4706
  consumedModuleProp('preInit');
@@ -4672,6 +4757,8 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4672
4757
  'getFunctionAddress',
4673
4758
  'addFunction',
4674
4759
  'removeFunction',
4760
+ 'setValue',
4761
+ 'getValue',
4675
4762
  'intArrayToString',
4676
4763
  'AsciiToString',
4677
4764
  'stringToAscii',
@@ -4701,12 +4788,14 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4701
4788
  'registerOrientationChangeEventCallback',
4702
4789
  'fillFullscreenChangeEventData',
4703
4790
  'registerFullscreenChangeEventCallback',
4791
+ 'callCanvasResizedCallback',
4704
4792
  'JSEvents_requestFullscreen',
4705
4793
  'JSEvents_resizeCanvasForFullscreen',
4706
4794
  'registerRestoreOldStyle',
4707
4795
  'hideEverythingExceptGivenElement',
4708
4796
  'restoreHiddenElements',
4709
4797
  'setLetterbox',
4798
+ 'currentFullscreenStrategy',
4710
4799
  'softFullscreenResizeWebGLRenderTarget',
4711
4800
  'doRequestFullscreen',
4712
4801
  'fillPointerlockChangeEventData',
@@ -4738,10 +4827,9 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4738
4827
  'registerPreMainLoop',
4739
4828
  'getPromise',
4740
4829
  'makePromise',
4830
+ 'addPromise',
4741
4831
  'idsToPromises',
4742
4832
  'makePromiseCallback',
4743
- 'ExceptionInfo',
4744
- 'findMatchingCatch',
4745
4833
  'Browser_asyncPrepareDataCounter',
4746
4834
  'isLeapYear',
4747
4835
  'ydayFromDate',
@@ -4765,6 +4853,7 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4765
4853
  'colorChannelsInGlTextureFormat',
4766
4854
  'emscriptenWebGLGetTexPixelData',
4767
4855
  'emscriptenWebGLGetUniform',
4856
+ 'webglGetProgramUniformLocation',
4768
4857
  'webglGetUniformLocation',
4769
4858
  'webglPrepareUniformLocationsBeforeFirstUse',
4770
4859
  'webglGetLeftBracePos',
@@ -4773,14 +4862,10 @@ if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
4773
4862
  'writeGLArray',
4774
4863
  'registerWebGlEventCallback',
4775
4864
  'runAndAbortIfError',
4776
- 'ALLOC_NORMAL',
4777
- 'ALLOC_STACK',
4778
- 'allocate',
4779
4865
  'writeStringToMemory',
4780
4866
  'writeAsciiToMemory',
4781
4867
  'allocateUTF8',
4782
4868
  'allocateUTF8OnStack',
4783
- 'demangle',
4784
4869
  'stackTrace',
4785
4870
  'getNativeTypeSize',
4786
4871
  ];
@@ -4792,21 +4877,21 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4792
4877
  'err',
4793
4878
  'abort',
4794
4879
  'wasmExports',
4795
- 'HEAPF32',
4796
- 'HEAPF64',
4880
+ 'writeStackCookie',
4881
+ 'checkStackCookie',
4882
+ 'INT53_MAX',
4883
+ 'INT53_MIN',
4884
+ 'bigintToI53Checked',
4797
4885
  'HEAP8',
4798
4886
  'HEAPU8',
4799
4887
  'HEAP16',
4800
4888
  'HEAPU16',
4801
4889
  'HEAP32',
4802
4890
  'HEAPU32',
4891
+ 'HEAPF32',
4892
+ 'HEAPF64',
4803
4893
  'HEAP64',
4804
4894
  'HEAPU64',
4805
- 'writeStackCookie',
4806
- 'checkStackCookie',
4807
- 'INT53_MAX',
4808
- 'INT53_MIN',
4809
- 'bigintToI53Checked',
4810
4895
  'stackSave',
4811
4896
  'stackRestore',
4812
4897
  'stackAlloc',
@@ -4839,8 +4924,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4839
4924
  'addOnPostRun',
4840
4925
  'freeTableIndexes',
4841
4926
  'functionsInTableMap',
4842
- 'setValue',
4843
- 'getValue',
4844
4927
  'PATH',
4845
4928
  'PATH_FS',
4846
4929
  'UTF8Decoder',
@@ -4855,7 +4938,6 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4855
4938
  'JSEvents',
4856
4939
  'specialHTMLTargets',
4857
4940
  'findCanvasEventTarget',
4858
- 'currentFullscreenStrategy',
4859
4941
  'restoreOldWindowedStyle',
4860
4942
  'UNWIND_CACHE',
4861
4943
  'ExitStatus',
@@ -4867,12 +4949,8 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4867
4949
  'emClearImmediate_deps',
4868
4950
  'emClearImmediate',
4869
4951
  'promiseMap',
4870
- 'uncaughtExceptionCount',
4871
- 'exceptionLast',
4872
- 'exceptionCaught',
4873
4952
  'Browser',
4874
4953
  'requestFullscreen',
4875
- 'requestFullScreen',
4876
4954
  'setCanvasSize',
4877
4955
  'getUserMedia',
4878
4956
  'createContext',
@@ -4888,6 +4966,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4888
4966
  'FS_preloadFile',
4889
4967
  'FS_modeStringToFlags',
4890
4968
  'FS_getMode',
4969
+ 'FS_fileDataToTypedArray',
4891
4970
  'FS_stdin_getChar_buffer',
4892
4971
  'FS_stdin_getChar',
4893
4972
  'FS_unlink',
@@ -4956,6 +5035,7 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
4956
5035
  'FS_mkdir',
4957
5036
  'FS_mkdev',
4958
5037
  'FS_symlink',
5038
+ 'FS_link',
4959
5039
  'FS_rename',
4960
5040
  'FS_rmdir',
4961
5041
  'FS_readdir',
@@ -5000,18 +5080,13 @@ missingLibrarySymbols.forEach(missingLibrarySymbol)
5000
5080
  'FS_createDataFile',
5001
5081
  'FS_forceLoadFile',
5002
5082
  'FS_createLazyFile',
5003
- 'FS_absolutePath',
5004
- 'FS_createFolder',
5005
- 'FS_createLink',
5006
- 'FS_joinPath',
5007
- 'FS_mmapAlloc',
5008
- 'FS_standardizePath',
5009
5083
  'MEMFS',
5010
5084
  'TTY',
5011
5085
  'PIPEFS',
5012
5086
  'SOCKFS',
5013
5087
  'NODEFS',
5014
5088
  'NODERAWFS',
5089
+ 'NODERAWFS_stream_funcs',
5015
5090
  'nodePath',
5016
5091
  'tempFixedLengthArray',
5017
5092
  'miniTempWebGLFloatBuffers',
@@ -5040,6 +5115,30 @@ function checkIncomingModuleAPI() {
5040
5115
  ignoredModuleProp('fetchSettings');
5041
5116
  ignoredModuleProp('logReadFiles');
5042
5117
  ignoredModuleProp('loadSplitModule');
5118
+ ignoredModuleProp('onMalloc');
5119
+ ignoredModuleProp('onRealloc');
5120
+ ignoredModuleProp('onFree');
5121
+ ignoredModuleProp('onSbrkGrow');
5122
+ ignoredModuleProp('onCOSCacheHit');
5123
+ ignoredModuleProp('onCOSCacheMiss');
5124
+ ignoredModuleProp('onCOSStore');
5125
+ ignoredModuleProp('GL_MAX_TEXTURE_IMAGE_UNITS');
5126
+ ignoredModuleProp('SDL_canPlayWithWebAudio');
5127
+ ignoredModuleProp('SDL_numSimultaneouslyQueuedBuffers');
5128
+ ignoredModuleProp('freePreloadedMediaOnUse');
5129
+ ignoredModuleProp('preinitializedWebGLContext');
5130
+ ignoredModuleProp('keyboardListeningElement');
5131
+ ignoredModuleProp('doNotCaptureKeyboard');
5132
+ ignoredModuleProp('extraStackTrace');
5133
+ ignoredModuleProp('preloadPlugins');
5134
+ ignoredModuleProp('preMainLoop');
5135
+ ignoredModuleProp('postMainLoop');
5136
+ ignoredModuleProp('forcedAspectRatio');
5137
+ ignoredModuleProp('mainScriptUrlOrBlob');
5138
+ ignoredModuleProp('onFullScreen');
5139
+ ignoredModuleProp('INITIAL_MEMORY');
5140
+ ignoredModuleProp('wasmMemory');
5141
+ ignoredModuleProp('wasmBinary');
5043
5142
  }
5044
5143
 
5045
5144
  // Imports from the Wasm binary.
@@ -5077,14 +5176,14 @@ function assignWasmExports(wasmExports) {
5077
5176
  assert(typeof wasmExports['emscripten_stack_get_current'] != 'undefined', 'missing Wasm export: emscripten_stack_get_current');
5078
5177
  assert(typeof wasmExports['memory'] != 'undefined', 'missing Wasm export: memory');
5079
5178
  assert(typeof wasmExports['__indirect_function_table'] != 'undefined', 'missing Wasm export: __indirect_function_table');
5080
- _main = Module['_main'] = createExportWrapper('__main_argc_argv', 2);
5081
- _fflush = createExportWrapper('fflush', 1);
5082
- ___funcs_on_exit = createExportWrapper('__funcs_on_exit', 0);
5083
- _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', 2);
5179
+ _main = Module['_main'] = createExportWrapper('__main_argc_argv', wasmExports['__main_argc_argv'], 2);
5180
+ _fflush = createExportWrapper('fflush', wasmExports['fflush'], 1);
5181
+ ___funcs_on_exit = createExportWrapper('__funcs_on_exit', wasmExports['__funcs_on_exit'], 0);
5182
+ _emscripten_builtin_memalign = createExportWrapper('emscripten_builtin_memalign', wasmExports['emscripten_builtin_memalign'], 2);
5084
5183
  _emscripten_stack_get_end = wasmExports['emscripten_stack_get_end'];
5085
5184
  _emscripten_stack_get_base = wasmExports['emscripten_stack_get_base'];
5086
- _strerror = createExportWrapper('strerror', 1);
5087
- _setThrew = createExportWrapper('setThrew', 2);
5185
+ _strerror = createExportWrapper('strerror', wasmExports['strerror'], 1);
5186
+ _setThrew = createExportWrapper('setThrew', wasmExports['setThrew'], 2);
5088
5187
  _emscripten_stack_init = wasmExports['emscripten_stack_init'];
5089
5188
  _emscripten_stack_get_free = wasmExports['emscripten_stack_get_free'];
5090
5189
  __emscripten_stack_restore = wasmExports['_emscripten_stack_restore'];
@@ -5139,7 +5238,7 @@ function invoke_ii(index,a1) {
5139
5238
  return getWasmTableEntry(index)(a1);
5140
5239
  } catch(e) {
5141
5240
  stackRestore(sp);
5142
- if (e !== e+0) throw e;
5241
+ if (!(e instanceof EmscriptenEH)) throw e;
5143
5242
  _setThrew(1, 0);
5144
5243
  }
5145
5244
  }
@@ -5150,7 +5249,7 @@ function invoke_iii(index,a1,a2) {
5150
5249
  return getWasmTableEntry(index)(a1,a2);
5151
5250
  } catch(e) {
5152
5251
  stackRestore(sp);
5153
- if (e !== e+0) throw e;
5252
+ if (!(e instanceof EmscriptenEH)) throw e;
5154
5253
  _setThrew(1, 0);
5155
5254
  }
5156
5255
  }
@@ -5161,7 +5260,7 @@ function invoke_viii(index,a1,a2,a3) {
5161
5260
  getWasmTableEntry(index)(a1,a2,a3);
5162
5261
  } catch(e) {
5163
5262
  stackRestore(sp);
5164
- if (e !== e+0) throw e;
5263
+ if (!(e instanceof EmscriptenEH)) throw e;
5165
5264
  _setThrew(1, 0);
5166
5265
  }
5167
5266
  }
@@ -5172,7 +5271,7 @@ function invoke_vii(index,a1,a2) {
5172
5271
  getWasmTableEntry(index)(a1,a2);
5173
5272
  } catch(e) {
5174
5273
  stackRestore(sp);
5175
- if (e !== e+0) throw e;
5274
+ if (!(e instanceof EmscriptenEH)) throw e;
5176
5275
  _setThrew(1, 0);
5177
5276
  }
5178
5277
  }
@@ -5183,7 +5282,7 @@ function invoke_vi(index,a1) {
5183
5282
  getWasmTableEntry(index)(a1);
5184
5283
  } catch(e) {
5185
5284
  stackRestore(sp);
5186
- if (e !== e+0) throw e;
5285
+ if (!(e instanceof EmscriptenEH)) throw e;
5187
5286
  _setThrew(1, 0);
5188
5287
  }
5189
5288
  }
@@ -5232,65 +5331,47 @@ function stackCheckInit() {
5232
5331
  writeStackCookie();
5233
5332
  }
5234
5333
 
5235
- function run(args = arguments_) {
5236
-
5237
- if (runDependencies > 0) {
5238
- dependenciesFulfilled = run;
5239
- return;
5240
- }
5334
+ async function run(args = programArgs) {
5335
+ assert(!calledRun);
5336
+ calledRun = true;
5241
5337
 
5242
5338
  stackCheckInit();
5243
5339
 
5244
5340
  preRun();
5245
5341
 
5246
- // a preRun added a dependency, run will be called later
5247
- if (runDependencies > 0) {
5248
- dependenciesFulfilled = run;
5249
- return;
5342
+ if (runDependencies) {
5343
+ await resolveRunDependencies();
5250
5344
  }
5251
5345
 
5252
- function doRun() {
5253
- // run may have just been called through dependencies being fulfilled just in this very frame,
5254
- // or while the async setStatus time below was happening
5255
- assert(!calledRun);
5256
- calledRun = true;
5257
- Module['calledRun'] = true;
5258
-
5259
- if (ABORT) return;
5346
+ var setStatus = Module['setStatus'];
5347
+ if (setStatus) {
5348
+ setStatus('Running...');
5349
+ // Yield to the event loop to allow the browser to paint "Running..."
5350
+ await new Promise((resolve) => setTimeout(resolve, 1));
5351
+ // Then we want to clear the status text, but only after the rest of this function runs.
5352
+ setTimeout(setStatus, 1, '');
5353
+ }
5260
5354
 
5261
- initRuntime();
5355
+ if (ABORT) return;
5262
5356
 
5263
- preMain();
5357
+ initRuntime();
5264
5358
 
5265
- Module['onRuntimeInitialized']?.();
5266
- consumedModuleProp('onRuntimeInitialized');
5359
+ // No ATMAINS hooks
5267
5360
 
5268
- var noInitialRun = Module['noInitialRun'] || false;
5269
- if (!noInitialRun) callMain(args);
5361
+ Module['onRuntimeInitialized']?.();
5362
+ consumedModuleProp('onRuntimeInitialized');
5270
5363
 
5271
- postRun();
5272
- }
5364
+ var noInitialRun = Module['noInitialRun'] || false;
5365
+ if (!noInitialRun) callMain(args);
5273
5366
 
5274
- if (Module['setStatus']) {
5275
- Module['setStatus']('Running...');
5276
- setTimeout(() => {
5277
- setTimeout(() => Module['setStatus'](''), 1);
5278
- doRun();
5279
- }, 1);
5280
- } else
5281
- {
5282
- doRun();
5283
- }
5284
- checkStackCookie();
5367
+ postRun();
5285
5368
  }
5286
5369
 
5287
5370
  var wasmExports;
5288
5371
 
5289
5372
  // With async instantation wasmExports is assigned asynchronously when the
5290
5373
  // instance is received.
5291
- createWasm();
5292
-
5293
- run();
5374
+ createWasm().then(() => run());
5294
5375
 
5295
5376
  // end include: postamble.js
5296
5377