@scriptc/cli-darwin-x64 0.2.1 → 0.2.3

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 (198) hide show
  1. package/dist/THIRD_PARTY_NOTICES +1 -1
  2. package/dist/bin/scriptc +0 -0
  3. package/dist/bin/scriptc.json +1 -1
  4. package/dist/lib/declarations/scriptc-node-fallback.d.ts +158 -31
  5. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  6. package/dist/lib/llvm/package.json +1 -1
  7. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_array.o +0 -0
  8. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_assert.o +0 -0
  9. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
  10. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
  11. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
  12. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  13. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
  14. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
  15. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_events.o +0 -0
  16. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_exception.o +0 -0
  17. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  18. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
  19. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  20. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_map.o +0 -0
  21. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
  22. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_qs.o +0 -0
  23. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  24. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
  25. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
  26. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url_params.o +0 -0
  27. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_compare.o +0 -0
  28. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_util_style.o +0 -0
  29. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  30. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
  31. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  32. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
  33. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  34. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  35. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
  36. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
  37. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
  38. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
  39. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  40. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  41. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  42. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  43. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  44. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
  45. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
  46. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  47. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
  48. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  49. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url_params.o +0 -0
  50. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_compare.o +0 -0
  51. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_util_style.o +0 -0
  52. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
  53. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  54. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  55. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  56. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
  57. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  58. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  59. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
  60. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
  61. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  62. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  63. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  64. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
  65. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  66. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
  67. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  68. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url_params.o +0 -0
  69. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  70. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  71. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
  72. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  73. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  74. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
  75. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
  76. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  77. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  78. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  79. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
  80. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  81. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
  82. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  83. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url_params.o +0 -0
  84. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  85. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  86. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
  87. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  88. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  89. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
  90. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
  91. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  92. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  93. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  94. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
  95. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  96. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
  97. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  98. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url_params.o +0 -0
  99. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  100. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  101. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
  102. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  103. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  104. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
  105. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
  106. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  107. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  108. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  109. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
  110. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  111. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
  112. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  113. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url_params.o +0 -0
  114. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  115. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_array.o +0 -0
  116. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_assert.o +0 -0
  117. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
  118. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
  119. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  120. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  121. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
  122. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
  123. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_events.o +0 -0
  124. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_exception.o +0 -0
  125. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  126. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
  127. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
  128. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_map.o +0 -0
  129. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
  130. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_qs.o +0 -0
  131. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
  132. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_symbol.o +0 -0
  133. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
  134. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url_params.o +0 -0
  135. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
  136. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_util_style.o +0 -0
  137. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  138. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
  139. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  140. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
  141. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  142. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  143. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
  144. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
  145. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
  146. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
  147. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  148. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  149. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  150. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  151. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  152. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
  153. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
  154. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  155. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
  156. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  157. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url_params.o +0 -0
  158. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
  159. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_util_style.o +0 -0
  160. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
  161. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  162. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  163. package/dist/lib/runtime-darwin-x64/package.json +1 -1
  164. package/dist/lib/runtime-darwin-x64/runtime-pack.json +423 -297
  165. package/dist/lib/runtime-sources/package.json +1 -1
  166. package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
  167. package/dist/lib/runtime-sources/src/scr_array.c +5 -0
  168. package/dist/lib/runtime-sources/src/scr_assert.c +26 -0
  169. package/dist/lib/runtime-sources/src/scr_async.c +56 -4
  170. package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
  171. package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
  172. package/dist/lib/runtime-sources/src/scr_bytes_io.c +355 -51
  173. package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
  174. package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
  175. package/dist/lib/runtime-sources/src/scr_events.c +9 -0
  176. package/dist/lib/runtime-sources/src/scr_exception.c +1 -0
  177. package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
  178. package/dist/lib/runtime-sources/src/scr_file_handle.c +42 -0
  179. package/dist/lib/runtime-sources/src/scr_island.c +2166 -786
  180. package/dist/lib/runtime-sources/src/scr_island_manifest.h +19 -13
  181. package/dist/lib/runtime-sources/src/scr_json.c +584 -54
  182. package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
  183. package/dist/lib/runtime-sources/src/scr_lib.c +1192 -43
  184. package/dist/lib/runtime-sources/src/scr_map.c +8 -0
  185. package/dist/lib/runtime-sources/src/scr_node_builtin.c +78 -0
  186. package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
  187. package/dist/lib/runtime-sources/src/scr_regex.c +107 -5
  188. package/dist/lib/runtime-sources/src/scr_runtime.h +136 -9
  189. package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
  190. package/dist/lib/runtime-sources/src/scr_system_errors.h +573 -0
  191. package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
  192. package/dist/lib/runtime-sources/src/scr_url.c +547 -64
  193. package/dist/lib/runtime-sources/src/scr_url_internal.h +6 -0
  194. package/dist/lib/runtime-sources/src/scr_url_params.c +10 -0
  195. package/dist/lib/runtime-sources/src/scr_util_compare.c +222 -0
  196. package/dist/lib/runtime-sources/src/scr_util_style.c +337 -0
  197. package/dist/lib/runtime-sources/src/scr_web.c +849 -264
  198. package/package.json +1 -1
@@ -5,9 +5,11 @@
5
5
  * under -DSCR_DYNAMIC, like scr_island.c.
6
6
  *
7
7
  * This file owns the semantics-heavy globals: the streams library
8
- * (ReadableStream, TransformStream), the encoders (TextEncoder,
8
+ * (ReadableStream, WritableStream with queued sink writes and strategy
9
+ * backpressure, TransformStream with readable-side backpressure), the encoders
10
+ * (TextEncoder,
9
11
  * TextDecoder — the WHATWG utf-8 state machine exactly, other labels
10
- * fenced — and TextDecoderStream), URLSearchParams, btoa/atob, Headers,
12
+ * fenced — and TextEncoderStream/TextDecoderStream), URLSearchParams, btoa/atob, Headers,
11
13
  * the fetch value classes (Request/Response with stream-or-bytes bodies,
12
14
  * consumed through text/json/bytes/arrayBuffer; clone() fenced; plus the
13
15
  * __scr_mk_response seam scr_fetch.c's glue builds wire responses
@@ -24,16 +26,12 @@
24
26
  * implementations (the web-streams npm fixture, corpus 1120) plus
25
27
  * scriptc-only fence tests (tests/harness/web-globals.test.ts). OUT,
26
28
  * with clear errors: byte streams ('type': 'bytes') and BYOB readers,
27
- * tee(), pipeTo(), custom queuing strategies (accepted, ignored — HWM is
28
- * always 1), a global WritableStream (TransformStream.writable is an
29
- * internal writable; the class is not exposed), and non-utf-8 TextDecoder
30
- * labels. One documented behavioral divergence: transforms run EAGERLY on
31
- * write (no readable-side backpressure), so writer.write() never blocks
32
- * on downstream demand — order-exact, buffering-different. SEMANTICS.md
33
- * states the subset; keep the three in sync.
29
+ * stream transfer, and non-utf-8 TextDecoder labels. Default-stream piping,
30
+ * teeing, reader/controller lifecycles, and transform backpressure are
31
+ * pinned by differential fixtures; the limitations page records the boundaries.
34
32
  *
35
- * The JS was verified line-for-line against Node's native WHATWG
36
- * implementations (a transcript battery: reader protocol, pull timing,
33
+ * JS behavior is pinned against Node's native WHATWG implementations
34
+ * by differential fixtures (a transcript battery: reader protocol, pull timing,
37
35
  * error propagation both directions, cancel-on-break, flush ordering,
38
36
  * utf-8 maximal-subpart replacement, BOM handling, form encoding, header
39
37
  * combining/sorting) running under BOTH engines before being embedded. */
@@ -62,54 +60,477 @@ static const char web_prelude[] =
62
60
  " * (host.setTimer/host.clearTimer) — REF'd like Node's (an armed\n"
63
61
  " * timer keeps the process alive), FIFO-ordered against static\n"
64
62
  " * timers on one heap, Node's <1ms clamp. Returns a Timeout-shaped\n"
65
- " * object (ref/unref/refresh/close, numeric via toPrimitive) that\n"
66
- " * clearTimeout/clearInterval accept alongside plain ids; unref is\n"
67
- " * accepted but not honored (the entry stays ref'd — a documented\n"
68
- " * approximation). */\n"
63
+ " * object with real ref/unref/refresh/close operations. Immediates\n"
64
+ " * use the native check queue, independently of timer ids. */\n"
65
+ " const timers = new Map();\n"
69
66
  " class Timeout {\n"
70
- " constructor(fn, delay, repeat) {\n"
67
+ " constructor(fn, delay, args, repeat) {\n"
71
68
  " this._fn = fn;\n"
72
69
  " this._delay = delay;\n"
70
+ " this._args = args;\n"
73
71
  " this._repeat = repeat;\n"
74
- " this._id = host.setTimer(fn, delay, repeat);\n"
72
+ " this._reffed = true;\n"
73
+ " this._closed = false;\n"
74
+ " this._callback = () => {\n"
75
+ " if (!this._repeat) { this._destroyed = true; timers.delete(this._id); }\n"
76
+ " this._fn.apply(this, this._args);\n"
77
+ " };\n"
78
+ " this._arm();\n"
75
79
  " }\n"
76
- " ref() { return this; }\n"
77
- " unref() { return this; }\n"
78
- " hasRef() { return true; }\n"
80
+ " _arm() {\n"
81
+ " this._destroyed = false;\n"
82
+ " this._id = host.setTimer(this._callback, this._delay, this._repeat, false);\n"
83
+ " timers.set(this._id, this);\n"
84
+ " if (!this._reffed) host.refTimer(this._id, false, false);\n"
85
+ " }\n"
86
+ " ref() { this._reffed = true; host.refTimer(this._id, true, false); return this; }\n"
87
+ " unref() { this._reffed = false; host.refTimer(this._id, false, false); return this; }\n"
88
+ " hasRef() { return this._reffed; }\n"
79
89
  " refresh() {\n"
80
- " host.clearTimer(this._id);\n"
81
- " this._id = host.setTimer(this._fn, this._delay, this._repeat);\n"
90
+ " if (this._closed) return this;\n"
91
+ " if (this._destroyed) this._arm();\n"
92
+ " else host.refreshTimer(this._id);\n"
82
93
  " return this;\n"
83
94
  " }\n"
84
- " close() { host.clearTimer(this._id); return this; }\n"
95
+ " close() { this._closed = true; this._destroyed = true; timers.delete(this._id); host.clearTimer(this._id, false); return this; }\n"
96
+ " [Symbol.dispose]() { this.close(); }\n"
85
97
  " [Symbol.toPrimitive]() { return this._id; }\n"
86
98
  " }\n"
87
99
  " const mkTimer = (fn, ms, args, repeat) => {\n"
88
100
  " if (typeof fn !== 'function') {\n"
89
101
  " throw new TypeError('The \"callback\" argument must be of type function. Received type ' + typeof fn);\n"
90
102
  " }\n"
91
- " const cb = args.length === 0 ? fn : () => fn(...args);\n"
92
- " return new Timeout(cb, Number(ms), repeat);\n"
103
+ " return new Timeout(fn, Number(ms), args, repeat);\n"
93
104
  " };\n"
94
105
  " g.setTimeout = (fn, ms, ...args) => mkTimer(fn, ms, args, false);\n"
95
106
  " g.setInterval = (fn, ms, ...args) => mkTimer(fn, ms, args, true);\n"
96
107
  " g.clearTimeout = (t) => {\n"
97
108
  " if (t === undefined || t === null) return;\n"
98
109
  " const id = typeof t === 'number' ? t : Number(t);\n"
99
- " if (Number.isFinite(id)) host.clearTimer(id);\n"
110
+ " if (Number.isFinite(id)) {\n"
111
+ " const timer = timers.get(id);\n"
112
+ " if (timer) timer.close(); else host.clearTimer(id, false);\n"
113
+ " }\n"
100
114
  " };\n"
101
115
  " g.clearInterval = g.clearTimeout;\n"
116
+ " class Immediate {\n"
117
+ " constructor(fn, args) {\n"
118
+ " this._reffed = true; this._destroyed = false;\n"
119
+ " this._id = host.setTimer(() => {\n"
120
+ " this._destroyed = true; this._reffed = false; fn.apply(this, args);\n"
121
+ " }, 0, false, true);\n"
122
+ " }\n"
123
+ " ref() { if (!this._destroyed) { this._reffed = true; host.refTimer(this._id, true, true); } return this; }\n"
124
+ " unref() { if (!this._destroyed) { this._reffed = false; host.refTimer(this._id, false, true); } return this; }\n"
125
+ " hasRef() { return this._reffed; }\n"
126
+ " _close() { this._destroyed = true; this._reffed = false; host.clearTimer(this._id, true); }\n"
127
+ " [Symbol.dispose]() { this._close(); }\n"
128
+ " }\n"
129
+ " g.setImmediate = (fn, ...args) => {\n"
130
+ " if (typeof fn !== 'function') throw new TypeError('The \"callback\" argument must be of type function. Received type ' + typeof fn);\n"
131
+ " return new Immediate(fn, args);\n"
132
+ " };\n"
133
+ " g.clearImmediate = (immediate) => { if (immediate instanceof Immediate) immediate._close(); };\n"
134
+ "\n"
135
+ " // Queue sizing is shared by the readable and writable default streams.\n"
136
+ " const streamError = (Ctor, code, message) => Object.assign(new Ctor(message), { code });\n"
137
+ " const streamReceived = (v) => {\n"
138
+ " if (v === null || v === undefined) return String(v);\n"
139
+ " if (typeof v === 'function') return 'function ' + v.name;\n"
140
+ " if (typeof v === 'object') return 'an instance of ' + (v.constructor && v.constructor.name || 'Object');\n"
141
+ " return 'type ' + typeof v + ' (' + (typeof v === 'string' ? \"'\" + v + \"'\" : String(v) + (typeof v === 'bigint' ? 'n' : '')) + ')';\n"
142
+ " };\n"
143
+ " const streamArgument = (name, expected, v) => streamError(TypeError, 'ERR_INVALID_ARG_TYPE',\n"
144
+ " 'The \"' + name + '\" ' + (name.includes('.') ? 'property' : 'argument') + ' must be ' + expected + '. Received ' + streamReceived(v));\n"
145
+ " const streamInvalidThis = (name) => streamError(TypeError, 'ERR_INVALID_THIS', 'Value of \"this\" must be of type ' + name);\n"
146
+ " const streamInvalidState = (message) => streamError(TypeError, 'ERR_INVALID_STATE', 'Invalid state: ' + message);\n"
147
+ " const streamInvalidValue = (name, value) => streamError(RangeError, 'ERR_INVALID_ARG_VALUE',\n"
148
+ " \"The \" + (name.includes('.') ? 'property' : 'argument') + \" '\" + name + \"' is invalid. Received \" + (typeof value === 'string' ? \"'\" + value + \"'\" : String(value)));\n"
149
+ " const streamStrategy = (strategy, fallback) => {\n"
150
+ " if (strategy === undefined || strategy === null) strategy = {};\n"
151
+ " if (typeof strategy !== 'object' && typeof strategy !== 'function') throw streamArgument('strategy', 'of type object', strategy);\n"
152
+ " const size = strategy.size;\n"
153
+ " if (size !== undefined && typeof size !== 'function') throw streamArgument('strategy.size', 'of type function', size);\n"
154
+ " const value = strategy.highWaterMark;\n"
155
+ " const highWaterMark = value === undefined ? fallback : +value;\n"
156
+ " if (Number.isNaN(highWaterMark) || highWaterMark < 0) throw streamInvalidValue('strategy.highWaterMark', highWaterMark);\n"
157
+ " return { size: size === undefined ? () => 1 : size, highWaterMark };\n"
158
+ " };\n"
159
+ " const streamChunkSize = (value) => {\n"
160
+ " const size = +value;\n"
161
+ " if (!Number.isFinite(size) || size < 0) throw streamInvalidValue('size', size);\n"
162
+ " return size;\n"
163
+ " };\n"
164
+ " const streamDeferred = (handled = false) => {\n"
165
+ " const d = { settled: false };\n"
166
+ " d.promise = new Promise((resolve, reject) => {\n"
167
+ " d.resolve = () => { d.settled = true; resolve(); };\n"
168
+ " d.reject = (e) => { d.settled = true; reject(e); };\n"
169
+ " });\n"
170
+ " if (handled) d.promise.catch(() => {});\n"
171
+ " return d;\n"
172
+ " };\n"
173
+ " const streamRejectSlot = (owner, key, e) => {\n"
174
+ " if (owner[key].settled) owner[key] = streamDeferred(true);\n"
175
+ " owner[key].reject(e);\n"
176
+ " };\n"
177
+ " const countStrategyStates = new WeakMap();\n"
178
+ " const byteStrategyStates = new WeakMap();\n"
179
+ " const countSize = Object.defineProperty(() => 1, 'name', { value: 'size' });\n"
180
+ " const byteSize = Object.defineProperty((chunk) => chunk.byteLength, 'name', { value: 'size' });\n"
181
+ " const strategyInit = (init) => {\n"
182
+ " if (init === null || typeof init !== 'object' || Array.isArray(init)) throw streamArgument('init', 'of type object', init);\n"
183
+ " if (init.highWaterMark === undefined) throw streamError(TypeError, 'ERR_MISSING_OPTION', 'init.highWaterMark is required');\n"
184
+ " return +init.highWaterMark;\n"
185
+ " };\n"
186
+ " class CountQueuingStrategy {\n"
187
+ " constructor(init) { countStrategyStates.set(this, strategyInit(init)); }\n"
188
+ " get highWaterMark() { if (!countStrategyStates.has(this)) throw new TypeError('Invalid CountQueuingStrategy receiver'); return countStrategyStates.get(this); }\n"
189
+ " get size() { if (!countStrategyStates.has(this)) throw new TypeError('Invalid CountQueuingStrategy receiver'); return countSize; }\n"
190
+ " }\n"
191
+ " class ByteLengthQueuingStrategy {\n"
192
+ " constructor(init) { byteStrategyStates.set(this, strategyInit(init)); }\n"
193
+ " get highWaterMark() { if (!byteStrategyStates.has(this)) throw new TypeError('Invalid ByteLengthQueuingStrategy receiver'); return byteStrategyStates.get(this); }\n"
194
+ " get size() { if (!byteStrategyStates.has(this)) throw new TypeError('Invalid ByteLengthQueuingStrategy receiver'); return byteSize; }\n"
195
+ " }\n"
196
+ "\n"
197
+ " const writableStreams = new WeakMap();\n"
198
+ " const writableWriters = new WeakMap();\n"
199
+ " const writableControllers = new WeakMap();\n"
200
+ " const writableToken = Symbol('WritableStreamDefaultController');\n"
201
+ " const writableWriterState = (s) => s.writer === undefined ? undefined : writableWriters.get(s.writer);\n"
202
+ " const writableBackpressure = (s) => {\n"
203
+ " const pressure = s.highWaterMark - s.queueSize <= 0;\n"
204
+ " const w = writableWriterState(s);\n"
205
+ " if (w && s.backpressure !== pressure) {\n"
206
+ " if (pressure) w.ready = streamDeferred(true);\n"
207
+ " else w.ready.resolve();\n"
208
+ " }\n"
209
+ " s.backpressure = pressure;\n"
210
+ " };\n"
211
+ " const writableClear = (s) => { s.write = s.close = s.abort = s.size = undefined; };\n"
212
+ " const writableRejectClosed = (s) => {\n"
213
+ " if (s.closeRequest) { s.closeRequest.reject(s.error); s.closeRequest = undefined; }\n"
214
+ " const w = writableWriterState(s);\n"
215
+ " if (w) w.closed.reject(s.error);\n"
216
+ " };\n"
217
+ " const writableFinishError = (s) => {\n"
218
+ " s.state = 'errored';\n"
219
+ " for (const q of s.queue) if (q.kind === 'write') q.request.reject(s.error);\n"
220
+ " s.queue = []; s.queueSize = 0;\n"
221
+ " const a = s.abortRequest;\n"
222
+ " s.abortRequest = undefined;\n"
223
+ " if (!a) { writableRejectClosed(s); return; }\n"
224
+ " if (a.alreadyErroring) { a.request.reject(s.error); writableRejectClosed(s); return; }\n"
225
+ " const result = writableInvoke(s.abort, s.sink, [a.reason]);\n"
226
+ " writableClear(s);\n"
227
+ " result.then(\n"
228
+ " () => { a.request.resolve(); writableRejectClosed(s); },\n"
229
+ " (e) => { a.request.reject(e); writableRejectClosed(s); },\n"
230
+ " );\n"
231
+ " };\n"
232
+ " const writableError = (s, e) => {\n"
233
+ " if (s.state !== 'writable') return;\n"
234
+ " s.state = 'erroring'; s.error = e;\n"
235
+ " const w = writableWriterState(s);\n"
236
+ " if (w) streamRejectSlot(w, 'ready', e);\n"
237
+ " if (s.started && !s.inFlight) writableFinishError(s);\n"
238
+ " };\n"
239
+ " // Async callback wrappers adopt returned thenables and turn sync throws into rejections.\n"
240
+ " const writableInvoke = async (fn, receiver, args) => fn ? fn.apply(receiver, args) : undefined;\n"
241
+ " const writableAdvance = (s) => {\n"
242
+ " if (!s.started || s.inFlight || s.state === 'closed' || s.state === 'errored') return;\n"
243
+ " if (s.state === 'erroring') { writableFinishError(s); return; }\n"
244
+ " if (!s.queue.length) return;\n"
245
+ " const q = s.queue[0];\n"
246
+ " s.inFlight = q;\n"
247
+ " if (q.kind === 'close') {\n"
248
+ " s.queue.shift();\n"
249
+ " const result = writableInvoke(s.close, s.sink, []);\n"
250
+ " writableClear(s);\n"
251
+ " result.then(\n"
252
+ " () => {\n"
253
+ " q.request.resolve(); s.inFlight = undefined;\n"
254
+ " if (s.abortRequest) { s.abortRequest.request.resolve(); s.abortRequest = undefined; }\n"
255
+ " s.state = 'closed'; s.error = undefined; s.closeRequest = undefined;\n"
256
+ " const w = writableWriterState(s);\n"
257
+ " if (w) w.closed.resolve();\n"
258
+ " },\n"
259
+ " (e) => {\n"
260
+ " q.request.reject(e); s.inFlight = undefined; s.closeRequest = undefined;\n"
261
+ " if (s.abortRequest) { s.abortRequest.request.reject(e); s.abortRequest = undefined; }\n"
262
+ " if (s.state === 'writable') writableError(s, e); else writableFinishError(s);\n"
263
+ " },\n"
264
+ " );\n"
265
+ " return;\n"
266
+ " }\n"
267
+ " writableInvoke(s.write, s.sink, [q.chunk, s.controller]).then(\n"
268
+ " () => {\n"
269
+ " q.request.resolve(); s.inFlight = undefined; s.queue.shift();\n"
270
+ " s.queueSize = Math.max(0, s.queueSize - q.size);\n"
271
+ " if (s.state === 'writable' && !s.closeRequest) writableBackpressure(s);\n"
272
+ " writableAdvance(s);\n"
273
+ " },\n"
274
+ " (e) => {\n"
275
+ " q.request.reject(e); s.inFlight = undefined; s.queue.shift();\n"
276
+ " if (s.state === 'writable') { writableClear(s); writableError(s, e); }\n"
277
+ " else writableFinishError(s);\n"
278
+ " },\n"
279
+ " );\n"
280
+ " };\n"
281
+ " const writableAbort = (s, reason) => {\n"
282
+ " if (s.state === 'closed' || s.state === 'errored') return Promise.resolve();\n"
283
+ " s.abortController.abort(reason);\n"
284
+ " if (s.abortRequest) return s.abortRequest.request.promise;\n"
285
+ " // Signal listeners may have closed or errored the stream synchronously.\n"
286
+ " if (s.state === 'closed' || s.state === 'errored') return Promise.resolve();\n"
287
+ " const alreadyErroring = s.state === 'erroring';\n"
288
+ " const request = streamDeferred();\n"
289
+ " s.abortRequest = { request, reason, alreadyErroring };\n"
290
+ " if (!alreadyErroring) writableError(s, reason);\n"
291
+ " return request.promise;\n"
292
+ " };\n"
293
+ " const writableClose = (s, writer) => {\n"
294
+ " if (s.closeRequest) return Promise.reject(streamInvalidState(writer ? 'Failure to close WritableStream' : 'Failure closing WritableStream'));\n"
295
+ " if (s.state === 'closed' || s.state === 'errored') return Promise.reject(streamInvalidState('WritableStream is closed'));\n"
296
+ " const request = streamDeferred();\n"
297
+ " s.closeRequest = request;\n"
298
+ " const w = writableWriterState(s);\n"
299
+ " if (w && s.backpressure && s.state === 'writable') w.ready.resolve();\n"
300
+ " s.queue.push({ kind: 'close', request });\n"
301
+ " writableAdvance(s);\n"
302
+ " return request.promise;\n"
303
+ " };\n"
304
+ " class WritableStream {\n"
305
+ " constructor(sink = {}, strategy) {\n"
306
+ " if (sink === null || (typeof sink !== 'object' && typeof sink !== 'function')) throw streamArgument('sink', 'of type object', sink);\n"
307
+ " const type = sink.type;\n"
308
+ " if (type !== undefined) throw streamInvalidValue('type', type);\n"
309
+ " const { size, highWaterMark } = streamStrategy(strategy, 1);\n"
310
+ " // Capture algorithms once: replacing sink methods later must not change the stream.\n"
311
+ " const start = sink.start, write = sink.write, close = sink.close, abort = sink.abort;\n"
312
+ " for (const [name, fn] of [['write', write], ['close', close], ['abort', abort]]) {\n"
313
+ " if (fn && typeof fn !== 'function') throw streamArgument('sink.' + name, 'of type function', fn);\n"
314
+ " }\n"
315
+ " if (start && typeof start !== 'function') throw new TypeError('Bind must be called on a function');\n"
316
+ " const s = { sink, size, highWaterMark, write, close, abort, state: 'writable', error: undefined,\n"
317
+ " queue: [], queueSize: 0, started: false, inFlight: undefined, writer: undefined,\n"
318
+ " closeRequest: undefined, abortRequest: undefined, backpressure: highWaterMark <= 0, abortController: new g.AbortController() };\n"
319
+ " writableStreams.set(this, s);\n"
320
+ " s.controller = new WritableStreamDefaultController(writableToken, s);\n"
321
+ " const result = start ? start.call(sink, s.controller) : undefined;\n"
322
+ " new Promise((resolve) => resolve(result)).then(\n"
323
+ " () => { s.started = true; writableAdvance(s); },\n"
324
+ " (e) => { s.started = true; if (s.state === 'writable') writableError(s, e); else writableFinishError(s); },\n"
325
+ " );\n"
326
+ " }\n"
327
+ " get locked() { const s = writableStreams.get(this); if (!s) throw streamInvalidThis('WritableStream'); return s.writer !== undefined; }\n"
328
+ " getWriter() { if (!writableStreams.has(this)) throw streamInvalidThis('WritableStream'); return new WritableStreamDefaultWriter(this); }\n"
329
+ " abort(reason) {\n"
330
+ " const s = writableStreams.get(this);\n"
331
+ " if (!s) return Promise.reject(streamInvalidThis('WritableStream'));\n"
332
+ " if (s.writer !== undefined) return Promise.reject(streamInvalidState('WritableStream is locked'));\n"
333
+ " return writableAbort(s, reason);\n"
334
+ " }\n"
335
+ " close() {\n"
336
+ " const s = writableStreams.get(this);\n"
337
+ " if (!s) return Promise.reject(streamInvalidThis('WritableStream'));\n"
338
+ " if (s.writer !== undefined) return Promise.reject(streamInvalidState('WritableStream is locked'));\n"
339
+ " return writableClose(s, false);\n"
340
+ " }\n"
341
+ " }\n"
342
+ " class WritableStreamDefaultWriter {\n"
343
+ " constructor(stream) {\n"
344
+ " const s = writableStreams.get(stream);\n"
345
+ " if (!s) throw streamArgument('stream', 'an instance of WritableStream', stream);\n"
346
+ " if (s.writer !== undefined) throw streamInvalidState('WritableStream is locked');\n"
347
+ " const w = { stream: s, ready: streamDeferred(true), closed: streamDeferred(true) };\n"
348
+ " writableWriters.set(this, w); s.writer = this;\n"
349
+ " if (s.state === 'writable') { if (!s.backpressure || s.closeRequest) w.ready.resolve(); }\n"
350
+ " else if (s.state === 'closed') { w.ready.resolve(); w.closed.resolve(); }\n"
351
+ " else { w.ready.reject(s.error); if (s.state === 'errored') w.closed.reject(s.error); }\n"
352
+ " }\n"
353
+ " get closed() { const w = writableWriters.get(this); return w ? w.closed.promise : Promise.reject(streamInvalidThis('WritableStreamDefaultWriter')); }\n"
354
+ " get ready() { const w = writableWriters.get(this); return w ? w.ready.promise : Promise.reject(streamInvalidThis('WritableStreamDefaultWriter')); }\n"
355
+ " get desiredSize() {\n"
356
+ " const w = writableWriters.get(this);\n"
357
+ " if (!w) throw streamInvalidThis('WritableStreamDefaultWriter');\n"
358
+ " if (!w.stream) throw streamInvalidState('Writer is not bound to a WritableStream');\n"
359
+ " const s = w.stream;\n"
360
+ " return s.state === 'closed' ? 0 : s.state === 'writable' ? s.highWaterMark - s.queueSize : null;\n"
361
+ " }\n"
362
+ " write(chunk) {\n"
363
+ " const w = writableWriters.get(this);\n"
364
+ " if (!w) return Promise.reject(streamInvalidThis('WritableStreamDefaultWriter'));\n"
365
+ " const s = w.stream;\n"
366
+ " if (!s) return Promise.reject(streamInvalidState('Writer is not bound to a WritableStream'));\n"
367
+ " let value = 1;\n"
368
+ " try { if (s.size) value = s.size.call(undefined, chunk); }\n"
369
+ " catch (e) { if (s.state === 'writable') { writableClear(s); writableError(s, e); } }\n"
370
+ " if (w.stream !== s) return Promise.reject(streamInvalidState('Mismatched WritableStreams'));\n"
371
+ " if (s.state === 'errored') return Promise.reject(s.error);\n"
372
+ " if (s.closeRequest || s.state === 'closed') return Promise.reject(streamInvalidState('WritableStream is closed'));\n"
373
+ " if (s.state === 'erroring') return Promise.reject(s.error);\n"
374
+ " const request = streamDeferred();\n"
375
+ " let size;\n"
376
+ " try { size = streamChunkSize(value); }\n"
377
+ " catch (e) {\n"
378
+ " // The write request joins the queue before invalid sizing errors the stream.\n"
379
+ " s.queue.push({ kind: 'write', request }); writableClear(s); writableError(s, e);\n"
380
+ " return request.promise;\n"
381
+ " }\n"
382
+ " s.queue.push({ kind: 'write', chunk, size, request }); s.queueSize += size;\n"
383
+ " writableBackpressure(s); writableAdvance(s);\n"
384
+ " return request.promise;\n"
385
+ " }\n"
386
+ " close() {\n"
387
+ " const w = writableWriters.get(this);\n"
388
+ " if (!w) return Promise.reject(streamInvalidThis('WritableStreamDefaultWriter'));\n"
389
+ " if (!w.stream) return Promise.reject(streamInvalidState('Writer is not bound to a WritableStream'));\n"
390
+ " return writableClose(w.stream, true);\n"
391
+ " }\n"
392
+ " abort(reason) {\n"
393
+ " const w = writableWriters.get(this);\n"
394
+ " if (!w) return Promise.reject(streamInvalidThis('WritableStreamDefaultWriter'));\n"
395
+ " if (!w.stream) return Promise.reject(streamInvalidState('Writer is not bound to a WritableStream'));\n"
396
+ " return writableAbort(w.stream, reason);\n"
397
+ " }\n"
398
+ " releaseLock() {\n"
399
+ " const w = writableWriters.get(this);\n"
400
+ " if (!w) throw streamInvalidThis('WritableStreamDefaultWriter');\n"
401
+ " if (!w.stream) return;\n"
402
+ " const e = streamInvalidState('Writer has been released');\n"
403
+ " streamRejectSlot(w, 'ready', e); streamRejectSlot(w, 'closed', e);\n"
404
+ " w.stream.writer = undefined; w.stream = undefined;\n"
405
+ " }\n"
406
+ " }\n"
407
+ " class WritableStreamDefaultController {\n"
408
+ " constructor(token, stream) {\n"
409
+ " if (token !== writableToken) throw streamError(TypeError, 'ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor');\n"
410
+ " writableControllers.set(this, stream);\n"
411
+ " }\n"
412
+ " get signal() { const s = writableControllers.get(this); if (!s) throw streamInvalidThis('WritableStreamDefaultController'); return s.abortController.signal; }\n"
413
+ " error(e) {\n"
414
+ " const s = writableControllers.get(this);\n"
415
+ " if (!s) throw streamInvalidThis('WritableStreamDefaultController');\n"
416
+ " if (s.state === 'writable') { writableClear(s); writableError(s, e); }\n"
417
+ " }\n"
418
+ " }\n"
419
+ " for (const C of [WritableStream, WritableStreamDefaultWriter, WritableStreamDefaultController, CountQueuingStrategy, ByteLengthQueuingStrategy]) {\n"
420
+ " Object.defineProperty(C.prototype, Symbol.toStringTag, { value: C.name, configurable: true });\n"
421
+ " for (const name of Object.getOwnPropertyNames(C.prototype)) {\n"
422
+ " if (name !== 'constructor') Object.defineProperty(C.prototype, name, { enumerable: true });\n"
423
+ " }\n"
424
+ " g[C.name] = C;\n"
425
+ " }\n"
426
+ "\n"
427
+ " const readableStreams = new WeakSet();\n"
428
+ " const readableReaders = new WeakMap(), readableControllers = new WeakMap();\n"
429
+ " const readableToken = Symbol('ReadableStreamDefaultController');\n"
430
+ " const readableControllerStream = (controller) => {\n"
431
+ " const stream = readableControllers.get(controller);\n"
432
+ " if (!stream) throw new TypeError('Invalid ReadableStreamDefaultController receiver');\n"
433
+ " return stream;\n"
434
+ " };\n"
435
+ " class ReadableStreamDefaultController {\n"
436
+ " constructor(token, stream) {\n"
437
+ " if (token !== readableToken) throw streamError(TypeError, 'ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor');\n"
438
+ " readableControllers.set(this, stream);\n"
439
+ " }\n"
440
+ " get desiredSize() {\n"
441
+ " const s = readableControllerStream(this);\n"
442
+ " return s._state === 'errored' ? null : s._state === 'closed' ? 0 : s._highWaterMark - s._queueSize;\n"
443
+ " }\n"
444
+ " enqueue(chunk) {\n"
445
+ " const s = readableControllerStream(this);\n"
446
+ " if (s._closeRequested || s._state !== 'readable') throw streamInvalidState('Controller is already closed');\n"
447
+ " if (s._reads.length) s._reads.shift().resolve({ value: chunk, done: false });\n"
448
+ " else {\n"
449
+ " let size;\n"
450
+ " try { size = streamChunkSize(s._size.call(undefined, chunk)); }\n"
451
+ " catch (e) { s._errorStream(e); throw e; }\n"
452
+ " s._queue.push({ chunk, size }); s._queueSize += size;\n"
453
+ " }\n"
454
+ " s._maybePull();\n"
455
+ " }\n"
456
+ " close() {\n"
457
+ " const s = readableControllerStream(this);\n"
458
+ " if (s._closeRequested || s._state !== 'readable') throw streamInvalidState('Controller is already closed');\n"
459
+ " s._closeRequested = true;\n"
460
+ " if (!s._queue.length) s._finishClose();\n"
461
+ " }\n"
462
+ " error(e) { readableControllerStream(this)._errorStream(e); }\n"
463
+ " }\n"
464
+ " class ReadableStreamDefaultReader {\n"
465
+ " constructor(stream) {\n"
466
+ " if (!readableStreams.has(stream)) throw streamArgument('stream', 'an instance of ReadableStream', stream);\n"
467
+ " if (stream._locked) throw streamInvalidState('ReadableStream is locked');\n"
468
+ " const r = { stream, closed: streamDeferred(true) };\n"
469
+ " readableReaders.set(this, r); stream._locked = true;\n"
470
+ " stream._closedResolve = r.closed.resolve; stream._closedReject = r.closed.reject;\n"
471
+ " if (stream._state === 'closed') r.closed.resolve();\n"
472
+ " else if (stream._state === 'errored') r.closed.reject(stream._storedError);\n"
473
+ " }\n"
474
+ " get closed() {\n"
475
+ " const r = readableReaders.get(this);\n"
476
+ " return r ? r.closed.promise : Promise.reject(streamInvalidThis('ReadableStreamDefaultReader'));\n"
477
+ " }\n"
478
+ " read() {\n"
479
+ " const r = readableReaders.get(this);\n"
480
+ " if (!r) return Promise.reject(streamInvalidThis('ReadableStreamDefaultReader'));\n"
481
+ " const s = r.stream;\n"
482
+ " if (!s) return Promise.reject(streamInvalidState('The reader is not attached to a stream'));\n"
483
+ " if (s._queue.length) {\n"
484
+ " const queued = s._queue.shift();\n"
485
+ " s._queueSize = Math.max(0, s._queueSize - queued.size);\n"
486
+ " if (s._closeRequested && !s._queue.length) s._finishClose(); else s._maybePull();\n"
487
+ " return Promise.resolve({ value: queued.chunk, done: false });\n"
488
+ " }\n"
489
+ " if (s._state === 'closed') return Promise.resolve({ value: undefined, done: true });\n"
490
+ " if (s._state === 'errored') return Promise.reject(s._storedError);\n"
491
+ " return new Promise((resolve, reject) => { s._reads.push({ resolve, reject }); s._maybePull(); });\n"
492
+ " }\n"
493
+ " cancel(reason) {\n"
494
+ " const r = readableReaders.get(this);\n"
495
+ " if (!r) return Promise.reject(streamInvalidThis('ReadableStreamDefaultReader'));\n"
496
+ " if (!r.stream) return Promise.reject(streamInvalidState('The reader is not attached to a stream'));\n"
497
+ " return r.stream._cancelInternal(reason);\n"
498
+ " }\n"
499
+ " releaseLock() {\n"
500
+ " const r = readableReaders.get(this);\n"
501
+ " if (!r) throw streamInvalidThis('ReadableStreamDefaultReader');\n"
502
+ " const s = r.stream;\n"
503
+ " if (!s) return;\n"
504
+ " streamRejectSlot(r, 'closed', streamInvalidState('Reader released'));\n"
505
+ " const reads = s._reads; s._reads = [];\n"
506
+ " const error = streamInvalidState('Releasing reader');\n"
507
+ " for (const request of reads) request.reject(error);\n"
508
+ " s._locked = false; s._closedResolve = s._closedReject = null; r.stream = undefined;\n"
509
+ " }\n"
510
+ " }\n"
511
+ " for (const C of [ReadableStreamDefaultReader, ReadableStreamDefaultController]) {\n"
512
+ " Object.defineProperty(C.prototype, Symbol.toStringTag, { value: C.name, configurable: true });\n"
513
+ " for (const name of Object.getOwnPropertyNames(C.prototype)) if (name !== 'constructor') Object.defineProperty(C.prototype, name, { enumerable: true });\n"
514
+ " g[C.name] = C;\n"
515
+ " }\n"
102
516
  "\n"
103
517
  " class ReadableStream {\n"
104
- " constructor(source, _strategy) {\n"
518
+ " constructor(source, strategy) {\n"
105
519
  " if (source === undefined) source = {};\n"
106
- " if (source === null || typeof source !== 'object') {\n"
107
- " throw new TypeError('underlying source must be an object');\n"
108
- " }\n"
109
- " if (source.type !== undefined) {\n"
110
- " throw new RangeError(\"byte streams (type: 'bytes') are not supported in the scriptc island\");\n"
520
+ " if (source === null || (typeof source !== 'object' && typeof source !== 'function')) {\n"
521
+ " throw streamArgument('source', 'of type object', source);\n"
111
522
  " }\n"
112
- " this._src = source;\n"
523
+ " if (strategy !== undefined && strategy !== null && typeof strategy !== 'object' && typeof strategy !== 'function') throw streamArgument('strategy', 'of type object', strategy);\n"
524
+ " const size = strategy?.size, mark = strategy?.highWaterMark, type = source.type;\n"
525
+ " if (`${type}` === 'bytes') throw new RangeError(\"byte streams (type: 'bytes') are not supported in the scriptc island\");\n"
526
+ " if (type !== undefined) throw streamError(TypeError, 'ERR_INVALID_ARG_VALUE', \"The property 'source.type' is invalid. Received \" + (typeof type === 'string' ? \"'\" + type + \"'\" : String(type)));\n"
527
+ " const highWaterMark = mark === undefined ? 1 : +mark;\n"
528
+ " if (Number.isNaN(highWaterMark) || highWaterMark < 0) throw streamInvalidValue('strategy.highWaterMark', highWaterMark);\n"
529
+ " const sizing = streamStrategy({ size, highWaterMark }, 1);\n"
530
+ " this._highWaterMark = sizing.highWaterMark;\n"
531
+ " this._size = sizing.size;\n"
532
+ " this._queueSize = 0;\n"
533
+ " this._src = source; readableStreams.add(this);\n"
113
534
  " this._queue = [];\n"
114
535
  " this._state = 'readable';\n"
115
536
  " this._storedError = undefined;\n"
@@ -121,34 +542,15 @@ static const char web_prelude[] =
121
542
  " this._pullAgain = false;\n"
122
543
  " this._closedResolve = null;\n"
123
544
  " this._closedReject = null;\n"
124
- " const self = this;\n"
125
- " this._controller = {\n"
126
- " get desiredSize() {\n"
127
- " if (self._state === 'errored') return null;\n"
128
- " if (self._state === 'closed') return 0;\n"
129
- " return 1 - self._queue.length;\n"
130
- " },\n"
131
- " enqueue(chunk) {\n"
132
- " if (self._closeRequested || self._state !== 'readable') {\n"
133
- " throw new TypeError('cannot enqueue on a stream that is ' + (self._closeRequested ? 'closing' : self._state));\n"
134
- " }\n"
135
- " if (self._reads.length > 0) self._reads.shift().resolve({ value: chunk, done: false });\n"
136
- " else self._queue.push(chunk);\n"
137
- " self._maybePull();\n"
138
- " },\n"
139
- " close() {\n"
140
- " if (self._closeRequested || self._state !== 'readable') {\n"
141
- " throw new TypeError('cannot close a stream that is ' + (self._closeRequested ? 'closing' : self._state));\n"
142
- " }\n"
143
- " self._closeRequested = true;\n"
144
- " if (self._queue.length === 0) self._finishClose();\n"
145
- " },\n"
146
- " error(e) {\n"
147
- " self._errorStream(e);\n"
148
- " },\n"
149
- " };\n"
545
+ " const start = source.start, pull = source.pull, cancel = source.cancel;\n"
546
+ " for (const [name, fn] of [['pull', pull], ['cancel', cancel]]) {\n"
547
+ " if (fn && typeof fn !== 'function') throw streamArgument('source.' + name, 'of type function', fn);\n"
548
+ " }\n"
549
+ " if (start && typeof start !== 'function') throw new TypeError('Bind must be called on a function');\n"
550
+ " this._pull = pull; this._cancel = cancel;\n"
551
+ " this._controller = new ReadableStreamDefaultController(readableToken, this);\n"
150
552
  " let startResult;\n"
151
- " if (source.start) startResult = source.start(this._controller); // a sync throw propagates, per spec\n"
553
+ " if (start) startResult = start.call(source, this._controller); // a sync throw propagates, per spec\n"
152
554
  " Promise.resolve(startResult).then(\n"
153
555
  " () => { this._started = true; this._maybePull(); },\n"
154
556
  " (e) => this._errorStream(e),\n"
@@ -156,7 +558,7 @@ static const char web_prelude[] =
156
558
  " }\n"
157
559
  " _finishClose() {\n"
158
560
  " if (this._state !== 'readable') return;\n"
159
- " this._state = 'closed';\n"
561
+ " this._state = 'closed'; this._pull = this._cancel = this._size = undefined;\n"
160
562
  " const reads = this._reads;\n"
161
563
  " this._reads = [];\n"
162
564
  " for (const r of reads) r.resolve({ value: undefined, done: true });\n"
@@ -165,96 +567,59 @@ static const char web_prelude[] =
165
567
  " _errorStream(e) {\n"
166
568
  " if (this._state !== 'readable') return;\n"
167
569
  " this._state = 'errored';\n"
168
- " this._storedError = e;\n"
169
- " this._queue.length = 0;\n"
570
+ " this._storedError = e; this._pull = this._cancel = this._size = undefined;\n"
571
+ " this._queue.length = 0; this._queueSize = 0;\n"
170
572
  " const reads = this._reads;\n"
171
573
  " this._reads = [];\n"
172
574
  " for (const r of reads) r.reject(e);\n"
173
575
  " if (this._closedReject) this._closedReject(e);\n"
174
576
  " }\n"
175
- " /* Proactive pull, like the spec with the default HWM-1 strategy: pull\n"
176
- " * whenever there is space (queue empty), started, and no pull running. */\n"
577
+ " /* Pull while demand is pending or the strategy has queue capacity. */\n"
177
578
  " _maybePull() {\n"
178
579
  " const src = this._src;\n"
179
- " if (!src.pull || !this._started) return;\n"
580
+ " if (!this._pull || !this._started) return;\n"
180
581
  " if (this._state !== 'readable' || this._closeRequested) return;\n"
181
- " if (this._queue.length >= 1) return;\n"
582
+ " if (!this._reads.length && this._highWaterMark - this._queueSize <= 0) return;\n"
182
583
  " if (this._pulling) { this._pullAgain = true; return; }\n"
183
584
  " this._pulling = true;\n"
184
585
  " Promise.resolve().then(() => {\n"
185
586
  " if (this._state !== 'readable' || this._closeRequested) { this._pulling = false; return; }\n"
186
587
  " let r;\n"
187
- " try { r = src.pull(this._controller); } catch (e) { this._pulling = false; this._errorStream(e); return; }\n"
588
+ " try { r = this._pull.call(src, this._controller); } catch (e) { this._pulling = false; this._errorStream(e); return; }\n"
188
589
  " Promise.resolve(r).then(\n"
189
590
  " () => {\n"
190
591
  " this._pulling = false;\n"
191
- " if (this._pullAgain || this._queue.length === 0) { this._pullAgain = false; this._maybePull(); }\n"
592
+ " if (this._pullAgain) { this._pullAgain = false; this._maybePull(); }\n"
192
593
  " },\n"
193
594
  " (e) => { this._pulling = false; this._errorStream(e); },\n"
194
595
  " );\n"
195
596
  " });\n"
196
597
  " }\n"
197
- " get locked() { return this._locked; }\n"
598
+ " get locked() { if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream'); return this._locked; }\n"
198
599
  " cancel(reason) {\n"
199
- " if (this._locked) return Promise.reject(new TypeError('cannot cancel a locked ReadableStream'));\n"
600
+ " if (!readableStreams.has(this)) return Promise.reject(streamInvalidThis('ReadableStream'));\n"
601
+ " if (this._locked) return Promise.reject(streamInvalidState('ReadableStream is locked'));\n"
200
602
  " return this._cancelInternal(reason);\n"
201
603
  " }\n"
202
604
  " _cancelInternal(reason) {\n"
203
605
  " if (this._state === 'closed') return Promise.resolve();\n"
204
606
  " if (this._state === 'errored') return Promise.reject(this._storedError);\n"
205
- " this._queue.length = 0;\n"
607
+ " const cancel = this._cancel;\n"
608
+ " this._queue.length = 0; this._queueSize = 0;\n"
206
609
  " this._closeRequested = true;\n"
207
610
  " this._finishClose();\n"
208
611
  " const src = this._src;\n"
209
- " return Promise.resolve(src.cancel ? src.cancel(reason) : undefined).then(() => undefined);\n"
612
+ " return writableInvoke(cancel, src, [reason]).then(() => undefined);\n"
210
613
  " }\n"
211
614
  " getReader(options) {\n"
212
- " if (options !== undefined && options !== null && options.mode !== undefined) {\n"
615
+ " if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
616
+ " if (options !== undefined && options !== null && typeof options !== 'object' && typeof options !== 'function') throw streamArgument('options', 'of type object', options);\n"
617
+ " const mode = options?.mode;\n"
618
+ " if (mode !== undefined) {\n"
619
+ " if (`${mode}` !== 'byob') throw streamError(TypeError, 'ERR_INVALID_ARG_VALUE', \"The property 'options.mode' is invalid. Received \" + (typeof mode === 'string' ? \"'\" + mode + \"'\" : String(mode)));\n"
213
620
  " throw new TypeError('BYOB readers are not supported in the scriptc island');\n"
214
621
  " }\n"
215
- " if (this._locked) throw new TypeError('ReadableStream is locked');\n"
216
- " this._locked = true;\n"
217
- " const self = this;\n"
218
- " let res, rej;\n"
219
- " const closed = new Promise((a, b) => { res = a; rej = b; });\n"
220
- " closed.catch(() => {});\n"
221
- " this._closedResolve = res;\n"
222
- " this._closedReject = rej;\n"
223
- " if (this._state === 'closed') res();\n"
224
- " else if (this._state === 'errored') rej(this._storedError);\n"
225
- " let released = false;\n"
226
- " return {\n"
227
- " get closed() { return closed; },\n"
228
- " read() {\n"
229
- " if (released) return Promise.reject(new TypeError('reader has been released'));\n"
230
- " if (self._queue.length > 0) {\n"
231
- " const chunk = self._queue.shift();\n"
232
- " if (self._closeRequested && self._queue.length === 0) self._finishClose();\n"
233
- " else self._maybePull();\n"
234
- " return Promise.resolve({ value: chunk, done: false });\n"
235
- " }\n"
236
- " if (self._state === 'closed') return Promise.resolve({ value: undefined, done: true });\n"
237
- " if (self._state === 'errored') return Promise.reject(self._storedError);\n"
238
- " return new Promise((resolve, reject) => {\n"
239
- " self._reads.push({ resolve, reject });\n"
240
- " self._maybePull();\n"
241
- " });\n"
242
- " },\n"
243
- " releaseLock() {\n"
244
- " if (released) return;\n"
245
- " released = true;\n"
246
- " const reads = self._reads;\n"
247
- " self._reads = [];\n"
248
- " for (const r of reads) r.reject(new TypeError('reader was released'));\n"
249
- " self._locked = false;\n"
250
- " self._closedResolve = null;\n"
251
- " self._closedReject = null;\n"
252
- " },\n"
253
- " cancel(reason) {\n"
254
- " if (released) return Promise.reject(new TypeError('reader has been released'));\n"
255
- " return self._cancelInternal(reason);\n"
256
- " },\n"
257
- " };\n"
622
+ " return new ReadableStreamDefaultReader(this);\n"
258
623
  " }\n"
259
624
  " /* The iterator carries a `finished` latch because the ENGINE's\n"
260
625
  " * for-await closes more eagerly than V8: quickjs-ng calls return()\n"
@@ -267,7 +632,8 @@ static const char web_prelude[] =
267
632
  " * who DO await it — the break path — still see the rejection). */\n"
268
633
  " values(options) {\n"
269
634
  " const preventCancel = options !== undefined && options !== null && !!options.preventCancel;\n"
270
- " const reader = this.getReader();\n"
635
+ " if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
636
+ " const reader = new ReadableStreamDefaultReader(this);\n"
271
637
  " let finished = false;\n"
272
638
  " const it = {\n"
273
639
  " next() {\n"
@@ -351,160 +717,312 @@ static const char web_prelude[] =
351
717
  " });\n"
352
718
  " }\n"
353
719
  " pipeThrough(transform, options) {\n"
354
- " if (transform === null || typeof transform !== 'object' || !transform.writable || !transform.readable) {\n"
355
- " throw new TypeError('pipeThrough requires a { writable, readable } pair');\n"
356
- " }\n"
357
- " if (options !== undefined && options !== null && options.signal !== undefined) {\n"
358
- " throw new Error('scriptc: AbortSignal is not supported by island streams yet');\n"
359
- " }\n"
360
- " pump(this, transform.writable);\n"
361
- " return transform.readable;\n"
362
- " }\n"
363
- " pipeTo() {\n"
364
- " throw new Error('ReadableStream.pipeTo is not supported in the scriptc island (use pipeThrough or a reader)');\n"
720
+ " if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
721
+ " const readable = transform?.readable;\n"
722
+ " if (!readableStreams.has(readable)) throw streamArgument('transform.readable', 'an instance of ReadableStream', readable);\n"
723
+ " const writable = transform?.writable;\n"
724
+ " if (!writableStreams.has(writable)) throw streamArgument('transform.writable', 'an instance of WritableStream', writable);\n"
725
+ " const opts = pipeOptions(options); pipeLocks(this, writable);\n"
726
+ " pipeStreams(this, writable, opts).catch(() => {});\n"
727
+ " return readable;\n"
728
+ " }\n"
729
+ " pipeTo(destination, options) {\n"
730
+ " try {\n"
731
+ " if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
732
+ " if (!writableStreams.has(destination)) throw streamArgument('transform.writable', 'an instance of WritableStream', destination);\n"
733
+ " const opts = pipeOptions(options); pipeLocks(this, destination);\n"
734
+ " return pipeStreams(this, destination, opts);\n"
735
+ " } catch (e) { return Promise.reject(e); }\n"
365
736
  " }\n"
366
737
  " tee() {\n"
367
- " throw new Error('ReadableStream.tee is not supported in the scriptc island');\n"
368
- " }\n"
369
- " }\n"
370
- "\n"
371
- " /* The internal writable half of TransformStream. Deliberately NOT\n"
372
- " * installed as a global WritableStream: the island fences the class\n"
373
- " * (nothing in the supported graph constructs one). */\n"
374
- " class WritableLite {\n"
375
- " constructor(sink) {\n"
376
- " this._sink = sink;\n"
377
- " this._state = 'writable';\n"
378
- " this._err = undefined;\n"
379
- " this._locked = false;\n"
380
- " this._closedRes = null;\n"
381
- " this._closedRej = null;\n"
382
- " }\n"
383
- " get locked() { return this._locked; }\n"
384
- " _error(e) {\n"
385
- " if (this._state === 'errored') return;\n"
386
- " this._state = 'errored';\n"
387
- " this._err = e;\n"
388
- " if (this._closedRej) this._closedRej(e);\n"
389
- " }\n"
390
- " abort(e) {\n"
391
- " if (this._state === 'errored') return Promise.resolve();\n"
392
- " this._error(e);\n"
393
- " return Promise.resolve(this._sink.abort ? this._sink.abort(e) : undefined).then(() => undefined);\n"
394
- " }\n"
395
- " getWriter() {\n"
396
- " if (this._locked) throw new TypeError('WritableStream is locked');\n"
397
- " this._locked = true;\n"
398
- " const self = this;\n"
399
- " let res, rej;\n"
400
- " const closed = new Promise((a, b) => { res = a; rej = b; });\n"
401
- " closed.catch(() => {});\n"
402
- " this._closedRes = res;\n"
403
- " this._closedRej = rej;\n"
404
- " if (this._state === 'errored') rej(this._err);\n"
405
- " return {\n"
406
- " get closed() { return closed; },\n"
407
- " get ready() { return self._state === 'errored' ? Promise.reject(self._err) : Promise.resolve(); },\n"
408
- " get desiredSize() {\n"
409
- " if (self._state === 'errored') return null;\n"
410
- " return self._state === 'writable' ? 1 : 0;\n"
411
- " },\n"
412
- " write(chunk) {\n"
413
- " if (self._state === 'errored') return Promise.reject(self._err);\n"
414
- " if (self._state !== 'writable') return Promise.reject(new TypeError('cannot write to a ' + self._state + ' stream'));\n"
415
- " let r;\n"
416
- " try { r = self._sink.write(chunk); } catch (e) { self._error(e); return Promise.reject(e); }\n"
417
- " return Promise.resolve(r).catch((e) => { self._error(e); throw e; });\n"
418
- " },\n"
419
- " close() {\n"
420
- " if (self._state === 'errored') return Promise.reject(self._err);\n"
421
- " if (self._state !== 'writable') return Promise.reject(new TypeError('cannot close a ' + self._state + ' stream'));\n"
422
- " self._state = 'closed';\n"
423
- " let r;\n"
424
- " try { r = self._sink.close ? self._sink.close() : undefined; } catch (e) { self._state = 'errored'; self._err = e; rej(e); return Promise.reject(e); }\n"
425
- " return Promise.resolve(r).then(\n"
426
- " () => { res(); },\n"
427
- " (e) => { self._state = 'errored'; self._err = e; rej(e); throw e; },\n"
428
- " );\n"
429
- " },\n"
430
- " abort(e) { return self.abort(e); },\n"
431
- " releaseLock() { self._locked = false; },\n"
432
- " };\n"
738
+ " if (!readableStreams.has(this)) throw streamInvalidThis('ReadableStream');\n"
739
+ " return readableTee(this);\n"
433
740
  " }\n"
434
741
  " }\n"
435
742
  "\n"
436
- " const pump = (rs, ws) => {\n"
437
- " const reader = rs.getReader();\n"
438
- " const writer = ws.getWriter();\n"
439
- " const step = () =>\n"
743
+ " const readableTee = (source) => {\n"
744
+ " const reader = new ReadableStreamDefaultReader(source);\n"
745
+ " const canceled = [false, false], reasons = [], branches = [];\n"
746
+ " let reading = false, resolveCancel;\n"
747
+ " const cancelPromise = new Promise((resolve) => { resolveCancel = resolve; });\n"
748
+ " const pull = () => {\n"
749
+ " if (reading) return;\n"
750
+ " reading = true;\n"
440
751
  " reader.read().then((r) => {\n"
441
- " if (r.done) return writer.close();\n"
442
- " return writer.write(r.value).then(step);\n"
752
+ " if (r.done) {\n"
753
+ " // Node defers branch close until its nextTick phase; the island's\n"
754
+ " // next microtask preserves final-chunk delivery before closing.\n"
755
+ " Promise.resolve().then(() => {\n"
756
+ " reading = false;\n"
757
+ " for (let i = 0; i < 2; i++) if (!canceled[i] && branches[i]._state === 'readable' && !branches[i]._closeRequested) branches[i]._controller.close();\n"
758
+ " if (!canceled[0] || !canceled[1]) resolveCancel();\n"
759
+ " });\n"
760
+ " } else {\n"
761
+ " reading = false;\n"
762
+ " for (let i = 0; i < 2; i++) if (!canceled[i] && branches[i]._state === 'readable') branches[i]._controller.enqueue(r.value);\n"
763
+ " }\n"
764
+ " }, () => { reading = false; });\n"
765
+ " };\n"
766
+ " for (let i = 0; i < 2; i++) branches.push(new ReadableStream({\n"
767
+ " pull,\n"
768
+ " cancel(reason) {\n"
769
+ " canceled[i] = true; reasons[i] = reason;\n"
770
+ " if (canceled[0] && canceled[1]) resolveCancel(source._cancelInternal([reasons[0], reasons[1]]));\n"
771
+ " return cancelPromise;\n"
772
+ " },\n"
773
+ " }));\n"
774
+ " reader.closed.catch((e) => {\n"
775
+ " for (const branch of branches) branch._errorStream(e);\n"
776
+ " if (!canceled[0] || !canceled[1]) resolveCancel();\n"
777
+ " });\n"
778
+ " return branches;\n"
779
+ " };\n"
780
+ "\n"
781
+ " const pipeOptions = (options) => {\n"
782
+ " if (options !== undefined && options !== null && typeof options !== 'object' && typeof options !== 'function') throw streamArgument('options', 'of type object', options);\n"
783
+ " const preventAbort = options?.preventAbort, preventCancel = options?.preventCancel, preventClose = options?.preventClose, signal = options?.signal;\n"
784
+ " if (signal !== undefined && (signal === null || typeof signal !== 'object' || !('aborted' in signal))) throw streamArgument('options.signal', 'an instance of AbortSignal', signal);\n"
785
+ " return { preventAbort: !!preventAbort, preventCancel: !!preventCancel, preventClose: !!preventClose, signal };\n"
786
+ " };\n"
787
+ " const pipeLocks = (source, dest) => {\n"
788
+ " if (source._locked) throw streamInvalidState('The ReadableStream is locked');\n"
789
+ " if (writableStreams.get(dest).writer !== undefined) throw streamInvalidState('The WritableStream is locked');\n"
790
+ " };\n"
791
+ " const pipeStreams = (source, dest, { preventClose, preventAbort, preventCancel, signal }) => {\n"
792
+ " const reader = new ReadableStreamDefaultReader(source), writer = new WritableStreamDefaultWriter(dest), sink = writableStreams.get(dest);\n"
793
+ " const completion = streamDeferred();\n"
794
+ " let shuttingDown = false, currentWrite = Promise.resolve(), listening = false;\n"
795
+ " const finalize = (rejected, error) => {\n"
796
+ " writer.releaseLock(); reader.releaseLock();\n"
797
+ " if (listening) signal.removeEventListener('abort', abort);\n"
798
+ " if (rejected) completion.reject(error); else completion.resolve();\n"
799
+ " };\n"
800
+ " const waitForWrites = async () => {\n"
801
+ " let write;\n"
802
+ " do { write = currentWrite; await write; } while (write !== currentWrite);\n"
803
+ " };\n"
804
+ " const shutdown = (action, rejected = false, error) => {\n"
805
+ " if (shuttingDown) return;\n"
806
+ " shuttingDown = true;\n"
807
+ " const waiting = sink.state === 'writable' && !sink.closeRequest ? waitForWrites() : Promise.resolve();\n"
808
+ " waiting.then(() => action ? action() : undefined).then(\n"
809
+ " () => finalize(rejected, error), (e) => finalize(true, e));\n"
810
+ " };\n"
811
+ " const abort = () => {\n"
812
+ " const reason = signal.reason;\n"
813
+ " shutdown(() => {\n"
814
+ " const actions = [];\n"
815
+ " if (!preventAbort && sink.state === 'writable') actions.push(writer.abort(reason));\n"
816
+ " if (!preventCancel && source._state === 'readable') actions.push(reader.cancel(reason));\n"
817
+ " return Promise.all(actions);\n"
818
+ " }, true, reason);\n"
819
+ " };\n"
820
+ " const writeChunk = (chunk) => { currentWrite = writer.write(chunk); currentWrite.catch(() => {}); };\n"
821
+ " // Buffered reads register their write before source.closed observers run. Pending\n"
822
+ " // reads queue the write during enqueue, ahead of a subsequent close notification.\n"
823
+ " const step = async () => {\n"
824
+ " if (shuttingDown) return true;\n"
825
+ " if (sink.backpressure) { await writer.ready; if (shuttingDown) return true; }\n"
826
+ " if (source._state === 'readable' && source._queue.length) {\n"
827
+ " while (source._queue.length) {\n"
828
+ " if (shuttingDown) return true;\n"
829
+ " const queued = source._queue.shift();\n"
830
+ " source._queueSize = Math.max(0, source._queueSize - queued.size);\n"
831
+ " if (source._closeRequested && !source._queue.length) source._finishClose();\n"
832
+ " writeChunk(queued.chunk);\n"
833
+ " if (sink.backpressure || sink.state !== 'writable' || sink.closeRequest) break;\n"
834
+ " }\n"
835
+ " source._maybePull();\n"
836
+ " return source._state === 'closed';\n"
837
+ " }\n"
838
+ " if (source._state === 'closed') return true;\n"
839
+ " if (source._state === 'errored') throw source._storedError;\n"
840
+ " return new Promise((resolve, reject) => {\n"
841
+ " source._reads.push({ resolve(r) {\n"
842
+ " if (r.done) resolve(true);\n"
843
+ " else Promise.resolve().then(() => { writeChunk(r.value); resolve(false); });\n"
844
+ " }, reject });\n"
845
+ " source._maybePull();\n"
443
846
  " });\n"
444
- " step().catch((e) => {\n"
445
- " writer.abort(e).catch(() => {});\n"
446
- " reader.cancel(e).catch(() => {});\n"
847
+ " };\n"
848
+ " if (signal !== undefined) {\n"
849
+ " if (signal.aborted) { abort(); return completion.promise; }\n"
850
+ " signal.addEventListener('abort', abort, { once: true, [Symbol.for('scriptc.events.resistStopPropagation')]: true });\n"
851
+ " listening = true;\n"
852
+ " }\n"
853
+ " (async () => { while (!await step()); })().catch(() => {});\n"
854
+ " const sourceError = (e) => shutdown(preventAbort ? undefined : () => writer.abort(e), true, e);\n"
855
+ " const sinkError = (e) => shutdown(preventCancel ? undefined : () => reader.cancel(e), true, e);\n"
856
+ " const sourceClose = () => shutdown(preventClose ? undefined : () => {\n"
857
+ " if (sink.closeRequest || sink.state === 'closed') return;\n"
858
+ " if (sink.state === 'errored') throw sink.error;\n"
859
+ " return writer.close();\n"
447
860
  " });\n"
861
+ " if (source._state === 'errored') sourceError(source._storedError); else reader.closed.catch(sourceError);\n"
862
+ " if (sink.state === 'errored') sinkError(sink.error); else writer.closed.catch(sinkError);\n"
863
+ " if (source._state === 'closed') sourceClose(); else reader.closed.then(sourceClose, () => {});\n"
864
+ " if (sink.closeRequest || sink.state === 'closed') {\n"
865
+ " const e = streamInvalidState('Destination WritableStream is closed');\n"
866
+ " shutdown(preventCancel ? undefined : () => reader.cancel(e), true, e);\n"
867
+ " }\n"
868
+ " return completion.promise;\n"
448
869
  " };\n"
449
870
  "\n"
871
+ " const transformStreams = new WeakMap(), transformControllers = new WeakMap();\n"
872
+ " const transformToken = Symbol('TransformStreamDefaultController');\n"
873
+ " const transformPressure = (s, pressure) => {\n"
874
+ " if (s.change) s.change.resolve();\n"
875
+ " s.change = streamDeferred(); s.backpressure = pressure;\n"
876
+ " };\n"
877
+ " const transformClear = (s) => { s.transform = s.flush = s.cancel = undefined; };\n"
878
+ " const transformUnblock = (s) => { if (s.backpressure) transformPressure(s, false); };\n"
879
+ " const transformErrorWritable = (s, e) => {\n"
880
+ " transformClear(s);\n"
881
+ " const w = writableStreams.get(s.writable);\n"
882
+ " if (w.state === 'writable') { writableClear(w); writableError(w, e); }\n"
883
+ " transformUnblock(s);\n"
884
+ " };\n"
885
+ " const transformError = (s, e) => { s.readable._errorStream(e); transformErrorWritable(s, e); };\n"
886
+ " const transformFinish = (s, kind, reason) => {\n"
887
+ " if (s.finish) return s.finish;\n"
888
+ " const d = streamDeferred(); s.finish = d.promise;\n"
889
+ " const result = writableInvoke(kind === 'close' ? s.flush : s.cancel, s.transformer, kind === 'close' ? [s.controller] : [reason]);\n"
890
+ " transformClear(s);\n"
891
+ " result.then(() => {\n"
892
+ " if (kind === 'cancel') {\n"
893
+ " const w = writableStreams.get(s.writable);\n"
894
+ " if (w.state === 'errored') { d.reject(w.error); return; }\n"
895
+ " transformErrorWritable(s, reason);\n"
896
+ " } else {\n"
897
+ " if (s.readable._state === 'errored') { d.reject(s.readable._storedError); return; }\n"
898
+ " if (kind === 'close') { if (s.readable._state === 'readable' && !s.readable._closeRequested) s.readable._controller.close(); }\n"
899
+ " else s.readable._errorStream(reason);\n"
900
+ " }\n"
901
+ " d.resolve();\n"
902
+ " }, (e) => {\n"
903
+ " if (kind === 'cancel') transformErrorWritable(s, e); else s.readable._errorStream(e);\n"
904
+ " d.reject(e);\n"
905
+ " }).catch((e) => d.reject(e));\n"
906
+ " return s.finish;\n"
907
+ " };\n"
908
+ " class TransformStreamDefaultController {\n"
909
+ " constructor(token, stream) {\n"
910
+ " if (token !== transformToken) throw streamError(TypeError, 'ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor');\n"
911
+ " transformControllers.set(this, stream);\n"
912
+ " }\n"
913
+ " get desiredSize() {\n"
914
+ " const s = transformControllers.get(this);\n"
915
+ " if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
916
+ " return s.readable._controller.desiredSize;\n"
917
+ " }\n"
918
+ " enqueue(chunk) {\n"
919
+ " const s = transformControllers.get(this);\n"
920
+ " if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
921
+ " const r = s.readable;\n"
922
+ " if (r._state !== 'readable' || r._closeRequested) throw streamInvalidState('Unable to enqueue');\n"
923
+ " try { r._controller.enqueue(chunk); }\n"
924
+ " catch (e) { transformErrorWritable(s, e); throw r._storedError; }\n"
925
+ " if (!r._reads.length && r._controller.desiredSize <= 0 && !s.backpressure) transformPressure(s, true);\n"
926
+ " }\n"
927
+ " error(e) {\n"
928
+ " const s = transformControllers.get(this);\n"
929
+ " if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
930
+ " transformError(s, e);\n"
931
+ " }\n"
932
+ " terminate() {\n"
933
+ " const s = transformControllers.get(this);\n"
934
+ " if (!s) throw streamInvalidThis('TransformStreamDefaultController');\n"
935
+ " if (s.readable._state === 'readable' && !s.readable._closeRequested) s.readable._controller.close();\n"
936
+ " transformErrorWritable(s, streamInvalidState('TransformStream has been terminated'));\n"
937
+ " }\n"
938
+ " }\n"
450
939
  " class TransformStream {\n"
451
- " constructor(transformer, _ws, _rs) {\n"
452
- " if (transformer === undefined || transformer === null) transformer = {};\n"
453
- " if (transformer.readableType !== undefined || transformer.writableType !== undefined) {\n"
454
- " throw new RangeError('readableType/writableType are not supported in the scriptc island');\n"
940
+ " constructor(transformer = {}, ws, rs) {\n"
941
+ " if (transformer === null || (typeof transformer !== 'object' && typeof transformer !== 'function')) throw streamArgument('transformer', 'of type object', transformer);\n"
942
+ " for (const [name, value] of [['writableStrategy', ws], ['readableStrategy', rs]]) {\n"
943
+ " if (value !== undefined && value !== null && typeof value !== 'object' && typeof value !== 'function') throw streamArgument(name, 'of type object', value);\n"
455
944
  " }\n"
456
- " const t = transformer;\n"
457
- " const self = this;\n"
458
- " let rc = null;\n"
459
- " this._readable = new ReadableStream({\n"
460
- " start(c) { rc = c; },\n"
461
- " cancel(reason) { self._writable._error(reason); },\n"
462
- " });\n"
463
- " const tc = {\n"
464
- " enqueue(chunk) { rc.enqueue(chunk); },\n"
465
- " error(e) {\n"
466
- " self._readable._errorStream(e);\n"
467
- " self._writable._error(e);\n"
468
- " },\n"
469
- " terminate() {\n"
470
- " if (self._readable._state === 'readable' && !self._readable._closeRequested) rc.close();\n"
471
- " self._writable._error(new TypeError('The transform stream has been terminated'));\n"
472
- " },\n"
473
- " get desiredSize() { return rc.desiredSize; },\n"
474
- " };\n"
475
- " this._controller = tc;\n"
476
- " this._writable = new WritableLite({\n"
477
- " /* Eager transform: writes run the transformer immediately (no\n"
478
- " * readable-side backpressure) — order-exact, documented. */\n"
479
- " write(chunk) {\n"
480
- " let r;\n"
481
- " try { r = t.transform ? t.transform(chunk, tc) : tc.enqueue(chunk); } catch (e) { tc.error(e); throw e; }\n"
482
- " return Promise.resolve(r).catch((e) => { tc.error(e); throw e; });\n"
483
- " },\n"
484
- " close() {\n"
485
- " let r;\n"
486
- " try { r = t.flush ? t.flush(tc) : undefined; } catch (e) { tc.error(e); throw e; }\n"
487
- " return Promise.resolve(r).then(\n"
488
- " () => {\n"
489
- " if (self._readable._state === 'readable' && !self._readable._closeRequested) rc.close();\n"
490
- " },\n"
491
- " (e) => { tc.error(e); throw e; },\n"
492
- " );\n"
945
+ " const readableType = transformer.readableType, writableType = transformer.writableType, start = transformer.start;\n"
946
+ " if (readableType !== undefined) throw streamInvalidValue('transformer.readableType', readableType);\n"
947
+ " if (writableType !== undefined) throw streamInvalidValue('transformer.writableType', writableType);\n"
948
+ " const readableSizing = streamStrategy(rs, 0), writableSizing = streamStrategy(ws, 1);\n"
949
+ " const s = { transformer, finish: undefined, backpressure: true };\n"
950
+ " transformPressure(s, true); transformStreams.set(this, s);\n"
951
+ " let resolveStart;\n"
952
+ " const startGate = new Promise((resolve) => { resolveStart = resolve; });\n"
953
+ " s.writable = new WritableStream({\n"
954
+ " start() { return startGate; },\n"
955
+ " async write(chunk) {\n"
956
+ " if (s.backpressure) {\n"
957
+ " await s.change.promise;\n"
958
+ " const w = writableStreams.get(s.writable);\n"
959
+ " if (w.state === 'erroring' || w.state === 'errored') throw w.error;\n"
960
+ " }\n"
961
+ " try { if (s.transform) await s.transform.call(transformer, chunk, s.controller); }\n"
962
+ " catch (e) { transformError(s, e); throw e; }\n"
493
963
  " },\n"
494
- " abort(e) { self._readable._errorStream(e); },\n"
495
- " });\n"
496
- " if (t.start) t.start(tc); // sync start, like eventsource-parser needs\n"
964
+ " close() { return transformFinish(s, 'close'); },\n"
965
+ " abort(reason) { return transformFinish(s, 'abort', reason); },\n"
966
+ " }, writableSizing);\n"
967
+ " s.readable = new ReadableStream({\n"
968
+ " start() { return startGate; },\n"
969
+ " pull() { transformPressure(s, false); return s.change.promise; },\n"
970
+ " cancel(reason) { return transformFinish(s, 'cancel', reason); },\n"
971
+ " }, readableSizing);\n"
972
+ " s.controller = new TransformStreamDefaultController(transformToken, s);\n"
973
+ " const transform = transformer.transform, flush = transformer.flush, cancel = transformer.cancel;\n"
974
+ " for (const [name, fn] of [['transform', transform], ['flush', flush], ['cancel', cancel]]) {\n"
975
+ " if (fn && typeof fn !== 'function') throw streamArgument('transformer.' + name, 'of type function', fn);\n"
976
+ " }\n"
977
+ " s.transform = transform || ((chunk, controller) => controller.enqueue(chunk)); s.flush = flush; s.cancel = cancel;\n"
978
+ " const startResult = start === undefined ? undefined : start.call(transformer, s.controller);\n"
979
+ " resolveStart(Promise.resolve(startResult).catch((e) => { transformError(s, e); throw e; }));\n"
497
980
  " }\n"
498
- " get readable() { return this._readable; }\n"
499
- " get writable() { return this._writable; }\n"
981
+ " get readable() { const s = transformStreams.get(this); if (!s) throw streamInvalidThis('TransformStream'); return s.readable; }\n"
982
+ " get writable() { const s = transformStreams.get(this); if (!s) throw streamInvalidThis('TransformStream'); return s.writable; }\n"
983
+ " }\n"
984
+ " for (const C of [TransformStream, TransformStreamDefaultController]) {\n"
985
+ " Object.defineProperty(C.prototype, Symbol.toStringTag, { value: C.name, configurable: true });\n"
986
+ " for (const name of Object.getOwnPropertyNames(C.prototype)) if (name !== 'constructor') Object.defineProperty(C.prototype, name, { enumerable: true });\n"
987
+ " g[C.name] = C;\n"
500
988
  " }\n"
501
- "\n"
502
989
  " g.ReadableStream = ReadableStream;\n"
503
- " g.TransformStream = TransformStream;\n"
504
- "\n"
505
990
  "\n"
991
+ " const textEncoders = new WeakSet();\n"
506
992
  " class TextEncoder {\n"
993
+ " constructor() { textEncoders.add(this); }\n"
507
994
  " get encoding() { return 'utf-8'; }\n"
995
+ " encodeInto(src, dest) {\n"
996
+ " const fail = (name, expected, value) => {\n"
997
+ " let received;\n"
998
+ " if (value === null || value === undefined) received = String(value);\n"
999
+ " else if (typeof value === 'object' || typeof value === 'function') received = 'an instance of ' + (value.constructor && value.constructor.name || 'Object');\n"
1000
+ " else if (typeof value === 'string') received = \"type string ('\" + value + \"')\";\n"
1001
+ " else received = 'type ' + typeof value + ' (' + String(value) + (typeof value === 'bigint' ? 'n' : '') + ')';\n"
1002
+ " const error = new TypeError('The \"' + name + '\" argument must be ' + expected + '. Received ' + received);\n"
1003
+ " error.code = 'ERR_INVALID_ARG_TYPE'; throw error;\n"
1004
+ " };\n"
1005
+ " if (!textEncoders.has(this)) { const error = new TypeError('Value of \"this\" must be of type TextEncoder'); error.code = 'ERR_INVALID_THIS'; throw error; }\n"
1006
+ " if (typeof src !== 'string') fail('src', 'of type string', src);\n"
1007
+ " if (!(dest instanceof Uint8Array)) fail('dest', 'an instance of Uint8Array', dest);\n"
1008
+ " let read = 0, written = 0;\n"
1009
+ " while (read < src.length) {\n"
1010
+ " let cp = src.charCodeAt(read), units = 1;\n"
1011
+ " if (cp >= 0xd800 && cp <= 0xdbff) {\n"
1012
+ " const low = src.charCodeAt(read + 1);\n"
1013
+ " if (low >= 0xdc00 && low <= 0xdfff) { cp = 0x10000 + ((cp - 0xd800) << 10) + low - 0xdc00; units = 2; }\n"
1014
+ " else cp = 0xfffd;\n"
1015
+ " } else if (cp >= 0xdc00 && cp <= 0xdfff) cp = 0xfffd;\n"
1016
+ " const size = cp < 0x80 ? 1 : cp < 0x800 ? 2 : cp < 0x10000 ? 3 : 4;\n"
1017
+ " if (written + size > dest.length) break;\n"
1018
+ " if (size === 1) dest[written++] = cp;\n"
1019
+ " else if (size === 2) { dest[written++] = 0xc0 | (cp >> 6); dest[written++] = 0x80 | (cp & 63); }\n"
1020
+ " else if (size === 3) { dest[written++] = 0xe0 | (cp >> 12); dest[written++] = 0x80 | ((cp >> 6) & 63); dest[written++] = 0x80 | (cp & 63); }\n"
1021
+ " else { dest[written++] = 0xf0 | (cp >> 18); dest[written++] = 0x80 | ((cp >> 12) & 63); dest[written++] = 0x80 | ((cp >> 6) & 63); dest[written++] = 0x80 | (cp & 63); }\n"
1022
+ " read += units;\n"
1023
+ " }\n"
1024
+ " return { read, written };\n"
1025
+ " }\n"
508
1026
  " encode(input) {\n"
509
1027
  " const s = input === undefined ? '' : String(input);\n"
510
1028
  " const bytes = [];\n"
@@ -608,6 +1126,37 @@ static const char web_prelude[] =
608
1126
  " }\n"
609
1127
  " }\n"
610
1128
  "\n"
1129
+ " class TextEncoderStream {\n"
1130
+ " #transform;\n"
1131
+ " constructor() {\n"
1132
+ " const encoder = new TextEncoder();\n"
1133
+ " let pending = null;\n"
1134
+ " this.#transform = new TransformStream({\n"
1135
+ " transform(chunk, controller) {\n"
1136
+ " chunk = String(chunk);\n"
1137
+ " let text = '';\n"
1138
+ " for (let i = 0; i < chunk.length; i++) {\n"
1139
+ " const unit = chunk.charCodeAt(i), item = chunk[i];\n"
1140
+ " if (pending !== null) {\n"
1141
+ " const high = pending; pending = null;\n"
1142
+ " if (unit >= 0xdc00 && unit <= 0xdfff) { text += high + item; continue; }\n"
1143
+ " text += '\\ufffd';\n"
1144
+ " }\n"
1145
+ " if (unit >= 0xd800 && unit <= 0xdbff) pending = item;\n"
1146
+ " else text += unit >= 0xdc00 && unit <= 0xdfff ? '\\ufffd' : item;\n"
1147
+ " }\n"
1148
+ " if (text) controller.enqueue(encoder.encode(text));\n"
1149
+ " },\n"
1150
+ " flush(controller) { if (pending !== null) controller.enqueue(new Uint8Array([0xef, 0xbf, 0xbd])); },\n"
1151
+ " });\n"
1152
+ " }\n"
1153
+ " get encoding() { this.#transform; return 'utf-8'; }\n"
1154
+ " get readable() { return this.#transform.readable; }\n"
1155
+ " get writable() { return this.#transform.writable; }\n"
1156
+ " }\n"
1157
+ " for (const name of ['encoding', 'readable', 'writable']) Object.defineProperty(TextEncoderStream.prototype, name, { enumerable: true });\n"
1158
+ " g.TextEncoderStream = TextEncoderStream;\n"
1159
+ "\n"
611
1160
  " class TextDecoderStream extends g.TransformStream {\n"
612
1161
  " constructor(label, options) {\n"
613
1162
  " const dec = new TextDecoder(label, options);\n"
@@ -891,13 +1440,14 @@ static const char web_prelude[] =
891
1440
  " const once = !!(options !== null && typeof options === 'object' && options.once);\n"
892
1441
  " const list = this._et[t] || (this._et[t] = []);\n"
893
1442
  " for (const e of list) { if (e.listener === listener) return; }\n"
894
- " list.push({ listener, once });\n"
1443
+ " const resistant = !!(options && options[Symbol.for('scriptc.events.resistStopPropagation')]);\n"
1444
+ " list.push({ listener, once, resistant });\n"
895
1445
  " }\n"
896
1446
  " removeEventListener(type, listener) {\n"
897
1447
  " const list = this._et[String(type)];\n"
898
1448
  " if (!list) return;\n"
899
1449
  " const i = list.findIndex((e) => e.listener === listener);\n"
900
- " if (i >= 0) list.splice(i, 1);\n"
1450
+ " if (i >= 0) list.splice(i, 1)[0].removed = true;\n"
901
1451
  " }\n"
902
1452
  " dispatchEvent(event) {\n"
903
1453
  " if (!(event instanceof Event)) throw new TypeError('The \"event\" argument must be an instance of Event.');\n"
@@ -907,7 +1457,8 @@ static const char web_prelude[] =
907
1457
  " const list = this._et[event.type];\n"
908
1458
  " if (list) {\n"
909
1459
  " for (const e of [...list]) {\n"
910
- " if (event._stopImmediate) break;\n"
1460
+ " if (e.removed) continue;\n"
1461
+ " if (event._stopImmediate && !e.resistant) continue;\n"
911
1462
  " if (e.once) this.removeEventListener(event.type, e.listener);\n"
912
1463
  " if (typeof e.listener === 'function') e.listener.call(this, event);\n"
913
1464
  " else if (e.listener !== null && typeof e.listener.handleEvent === 'function') e.listener.handleEvent(event);\n"
@@ -1054,13 +1605,16 @@ static const char web_prelude[] =
1054
1605
  " if (s._aborted) return;\n"
1055
1606
  " s._aborted = true;\n"
1056
1607
  " s._reason = reason === undefined ? mkAbortError() : reason;\n"
1057
- " const ev = { type: 'abort', target: s, currentTarget: s };\n"
1608
+ " const ev = new Event('abort');\n"
1609
+ " ev.target = s; ev.currentTarget = s; ev.eventPhase = Event.AT_TARGET; ev.isTrusted = true;\n"
1058
1610
  " let firstErr;\n"
1059
1611
  " let threw = false;\n"
1060
1612
  " if (s._onabort !== null) {\n"
1061
1613
  " try { s._onabort.call(s, ev); } catch (e) { firstErr = e; threw = true; }\n"
1062
1614
  " }\n"
1063
1615
  " for (const l of s._listeners.slice()) {\n"
1616
+ " if (l.removed) continue;\n"
1617
+ " if (ev._stopImmediate && !l.resistant) continue;\n"
1064
1618
  " if (l.once) s.removeEventListener('abort', l.fn);\n"
1065
1619
  " try { l.fn.call(s, ev); } catch (e) { if (!threw) { firstErr = e; threw = true; } }\n"
1066
1620
  " }\n"
@@ -1076,13 +1630,15 @@ static const char web_prelude[] =
1076
1630
  " throwIfAborted() { if (this._aborted) throw this._reason; }\n"
1077
1631
  " addEventListener(type, fn, options) {\n"
1078
1632
  " if (String(type) !== 'abort' || typeof fn !== 'function') return;\n"
1633
+ " if (this._listeners.some(l => l.fn === fn)) return;\n"
1079
1634
  " const once = options !== undefined && options !== null && !!options.once;\n"
1080
- " this._listeners.push({ fn, once });\n"
1635
+ " const resistant = !!(options && options[Symbol.for('scriptc.events.resistStopPropagation')]);\n"
1636
+ " this._listeners.push({ fn, once, resistant });\n"
1081
1637
  " }\n"
1082
1638
  " removeEventListener(type, fn) {\n"
1083
1639
  " if (String(type) !== 'abort') return;\n"
1084
1640
  " const i = this._listeners.findIndex((l) => l.fn === fn);\n"
1085
- " if (i >= 0) this._listeners.splice(i, 1);\n"
1641
+ " if (i >= 0) this._listeners.splice(i, 1)[0].removed = true;\n"
1086
1642
  " }\n"
1087
1643
  " static abort(reason) {\n"
1088
1644
  " const s = mkSignal();\n"
@@ -1633,7 +2189,6 @@ static void web_timer_fire_cb(ScrClosure *env) {
1633
2189
  static JSValue web_host_set_timer(JSContext *ctx, JSValueConst this_val,
1634
2190
  int argc, JSValueConst *argv) {
1635
2191
  (void)this_val;
1636
- (void)argc;
1637
2192
  double ms = 0;
1638
2193
  if (JS_ToFloat64(ctx, &ms, argv[1])) return JS_EXCEPTION;
1639
2194
  bool repeat = JS_ToBool(ctx, argv[2]) > 0;
@@ -1649,17 +2204,45 @@ static JSValue web_host_set_timer(JSContext *ctx, JSValueConst this_val,
1649
2204
  scr_box_set_ref(box, h); /* the box owns the +1 */
1650
2205
  ScrClosure *cb = scr_closure_new((void *)web_timer_fire_cb, 1);
1651
2206
  cb->caps[0] = box;
1652
- double id = repeat ? scr_set_interval(cb, ms) : scr_set_timeout_handle(cb, ms);
2207
+ bool immediate = argc > 3 && JS_ToBool(ctx, argv[3]) > 0;
2208
+ double id = immediate ? scr_set_immediate(cb)
2209
+ : repeat ? scr_set_interval(cb, ms) : scr_set_timeout_handle(cb, ms);
1653
2210
  return JS_NewFloat64(ctx, id);
1654
2211
  }
1655
2212
 
1656
2213
  static JSValue web_host_clear_timer(JSContext *ctx, JSValueConst this_val,
1657
2214
  int argc, JSValueConst *argv) {
1658
2215
  (void)this_val;
2216
+ double id = 0;
2217
+ if (JS_ToFloat64(ctx, &id, argv[0])) return JS_EXCEPTION;
2218
+ if (argc > 1 && JS_ToBool(ctx, argv[1]) > 0) scr_clear_immediate(id);
2219
+ else scr_clear_interval(id);
2220
+ return JS_UNDEFINED;
2221
+ }
2222
+
2223
+ static JSValue web_host_ref_timer(JSContext *ctx, JSValueConst this_val,
2224
+ int argc, JSValueConst *argv) {
2225
+ (void)this_val;
2226
+ (void)argc;
2227
+ double id = 0;
2228
+ if (JS_ToFloat64(ctx, &id, argv[0])) return JS_EXCEPTION;
2229
+ bool reffed = JS_ToBool(ctx, argv[1]) > 0;
2230
+ bool immediate = JS_ToBool(ctx, argv[2]) > 0;
2231
+ if (immediate) {
2232
+ if (reffed) scr_immediate_ref(id); else scr_immediate_unref(id);
2233
+ } else {
2234
+ if (reffed) scr_timer_ref(id); else scr_timer_unref(id);
2235
+ }
2236
+ return JS_UNDEFINED;
2237
+ }
2238
+
2239
+ static JSValue web_host_refresh_timer(JSContext *ctx, JSValueConst this_val,
2240
+ int argc, JSValueConst *argv) {
2241
+ (void)this_val;
1659
2242
  (void)argc;
1660
2243
  double id = 0;
1661
2244
  if (JS_ToFloat64(ctx, &id, argv[0])) return JS_EXCEPTION;
1662
- scr_clear_interval(id);
2245
+ scr_timer_refresh(id);
1663
2246
  return JS_UNDEFINED;
1664
2247
  }
1665
2248
 
@@ -1837,8 +2420,10 @@ void scr_island_web_boot(void *jsctx) {
1837
2420
  JS_SetPropertyStr(ctx, host, "write", JS_NewCFunction(ctx, web_host_write, "write", 2));
1838
2421
  JS_SetPropertyStr(ctx, host, "tzname", JS_NewCFunction(ctx, web_host_tzname, "tzname", 1));
1839
2422
  JS_SetPropertyStr(ctx, host, "timer", JS_NewCFunction(ctx, web_host_timer, "timer", 2));
1840
- JS_SetPropertyStr(ctx, host, "setTimer", JS_NewCFunction(ctx, web_host_set_timer, "setTimer", 3));
1841
- JS_SetPropertyStr(ctx, host, "clearTimer", JS_NewCFunction(ctx, web_host_clear_timer, "clearTimer", 1));
2423
+ JS_SetPropertyStr(ctx, host, "setTimer", JS_NewCFunction(ctx, web_host_set_timer, "setTimer", 4));
2424
+ JS_SetPropertyStr(ctx, host, "clearTimer", JS_NewCFunction(ctx, web_host_clear_timer, "clearTimer", 2));
2425
+ JS_SetPropertyStr(ctx, host, "refTimer", JS_NewCFunction(ctx, web_host_ref_timer, "refTimer", 3));
2426
+ JS_SetPropertyStr(ctx, host, "refreshTimer", JS_NewCFunction(ctx, web_host_refresh_timer, "refreshTimer", 1));
1842
2427
  JSValue r = JS_Call(ctx, fn, JS_UNDEFINED, 1, (JSValueConst *)&host);
1843
2428
  JS_FreeValue(ctx, host);
1844
2429
  JS_FreeValue(ctx, fn);