visaljs 0.0.7 → 0.0.9

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 (434) hide show
  1. package/README.md +68 -4
  2. package/THIRD_PARTY_LICENSES +1216 -0
  3. package/cli.js +4461 -321
  4. package/node/include/js_node.h +57 -1
  5. package/node/include/js_uv.h +8 -1
  6. package/node/prelude/_http_agent.js +5 -0
  7. package/node/prelude/_http_server.js +7 -0
  8. package/node/prelude/_stream_duplex.js +4 -0
  9. package/node/prelude/_stream_passthrough.js +4 -0
  10. package/node/prelude/_stream_readable.js +4 -0
  11. package/node/prelude/_stream_transform.js +4 -0
  12. package/node/prelude/_stream_writable.js +4 -0
  13. package/node/prelude/assert.js +1334 -0
  14. package/node/prelude/assert_strict.js +12 -0
  15. package/node/prelude/async_hooks.js +1 -1
  16. package/node/prelude/buffer.js +43 -3
  17. package/node/prelude/child_process.js +1098 -0
  18. package/node/prelude/cluster.js +52 -0
  19. package/node/prelude/console.js +328 -0
  20. package/node/prelude/constants.js +10 -0
  21. package/node/prelude/crypto.js +1 -1
  22. package/node/prelude/diagnostics_channel.js +1 -1
  23. package/node/prelude/dns.js +8 -2
  24. package/node/prelude/domain.js +115 -0
  25. package/node/prelude/events.js +148 -16
  26. package/node/prelude/fs.js +1138 -151
  27. package/node/prelude/fs_promises.js +117 -11
  28. package/node/prelude/http.js +784 -301
  29. package/node/prelude/http2.js +1 -1
  30. package/node/prelude/https.js +159 -0
  31. package/node/prelude/inspector.js +27 -0
  32. package/node/prelude/inspector_promises.js +4 -0
  33. package/node/prelude/internal/async_context.js +1 -1
  34. package/node/prelude/internal/buffer_transcode.js +44 -0
  35. package/node/prelude/internal/comparisons.js +916 -0
  36. package/node/prelude/internal/compression_streams.js +153 -0
  37. package/node/prelude/internal/crypto/asym.js +27 -14
  38. package/node/prelude/internal/crypto/cipher.js +16 -5
  39. package/node/prelude/internal/crypto/diffiehellman.js +3 -2
  40. package/node/prelude/internal/crypto/hash.js +2 -1
  41. package/node/prelude/internal/crypto/kdf.js +14 -9
  42. package/node/prelude/internal/crypto/keys.js +63 -50
  43. package/node/prelude/internal/crypto/random.js +2 -1
  44. package/node/prelude/internal/crypto/util.js +4 -4
  45. package/node/prelude/internal/dotenv.js +98 -0
  46. package/node/prelude/internal/errors.js +21 -5
  47. package/node/prelude/internal/events_extras.js +113 -0
  48. package/node/prelude/internal/events_on.js +100 -0
  49. package/node/prelude/internal/features.js +72 -0
  50. package/node/prelude/internal/fetch.js +364 -0
  51. package/node/prelude/internal/form_data.js +376 -0
  52. package/node/prelude/internal/fs_bigint_stats.js +41 -0
  53. package/node/prelude/internal/fs_blob.js +19 -0
  54. package/node/prelude/internal/fs_cp.js +709 -0
  55. package/node/prelude/internal/fs_dir.js +166 -0
  56. package/node/prelude/internal/fs_filehandle.js +287 -0
  57. package/node/prelude/internal/fs_glob.js +296 -0
  58. package/node/prelude/internal/fs_statfs.js +42 -0
  59. package/node/prelude/internal/fs_stats.js +89 -0
  60. package/node/prelude/internal/fs_streams.js +541 -0
  61. package/node/prelude/internal/fs_utils.js +286 -0
  62. package/node/prelude/internal/fs_watch.js +580 -0
  63. package/node/prelude/internal/http_agent.js +114 -2
  64. package/node/prelude/internal/http_symbols.js +3 -0
  65. package/node/prelude/internal/mime.js +249 -0
  66. package/node/prelude/internal/net.js +1 -0
  67. package/node/prelude/internal/net_bound.js +123 -0
  68. package/node/prelude/internal/net_onread.js +73 -0
  69. package/node/prelude/internal/net_tos.js +54 -0
  70. package/node/prelude/internal/parse_args.js +288 -0
  71. package/node/prelude/internal/perf_histogram.js +435 -0
  72. package/node/prelude/internal/perf_observe.js +125 -0
  73. package/node/prelude/internal/performance_global.js +19 -0
  74. package/node/prelude/internal/process_events.js +49 -1
  75. package/node/prelude/internal/process_memory.js +14 -0
  76. package/node/prelude/internal/process_more.js +414 -0
  77. package/node/prelude/internal/process_signals.js +2 -1
  78. package/node/prelude/internal/process_stdin.js +52 -0
  79. package/node/prelude/internal/process_stdio.js +36 -0
  80. package/node/prelude/internal/querystring.js +0 -0
  81. package/node/prelude/internal/readline.js +338 -0
  82. package/node/prelude/internal/socketaddress.js +8 -4
  83. package/node/prelude/internal/source_map.js +122 -0
  84. package/node/prelude/internal/stream_compose.js +74 -0
  85. package/node/prelude/internal/stream_from.js +6 -0
  86. package/node/prelude/internal/stream_operators.js +23 -0
  87. package/node/prelude/internal/stream_pipeline.js +7 -0
  88. package/node/prelude/internal/stream_transform.js +10 -0
  89. package/node/prelude/internal/stream_web_adapters.js +143 -0
  90. package/node/prelude/internal/streams/add_abort_signal.js +58 -0
  91. package/node/prelude/internal/streams/compose.js +244 -0
  92. package/node/prelude/internal/streams/destroy.js +358 -0
  93. package/node/prelude/internal/streams/duplex.js +199 -0
  94. package/node/prelude/internal/streams/duplexify.js +378 -0
  95. package/node/prelude/internal/streams/end_of_stream.js +387 -0
  96. package/node/prelude/internal/streams/errors.js +216 -0
  97. package/node/prelude/internal/streams/from.js +211 -0
  98. package/node/prelude/internal/streams/legacy.js +120 -0
  99. package/node/prelude/internal/streams/operators.js +375 -0
  100. package/node/prelude/internal/streams/passthrough.js +45 -0
  101. package/node/prelude/internal/streams/pipeline.js +468 -0
  102. package/node/prelude/internal/streams/readable.js +1835 -0
  103. package/node/prelude/internal/streams/state.js +48 -0
  104. package/node/prelude/internal/streams/transform.js +203 -0
  105. package/node/prelude/internal/streams/utils.js +355 -0
  106. package/node/prelude/internal/streams/validators.js +108 -0
  107. package/node/prelude/internal/streams/writable.js +1160 -0
  108. package/node/prelude/internal/structured_clone.js +238 -0
  109. package/node/prelude/internal/system_errors.js +37 -0
  110. package/node/prelude/internal/test_runner/mock.js +431 -0
  111. package/node/prelude/internal/test_runner/reporters.js +404 -0
  112. package/node/prelude/internal/test_runner/test.js +1571 -0
  113. package/node/prelude/internal/timers.js +38 -7
  114. package/node/prelude/internal/timers_global.js +1 -1
  115. package/node/prelude/internal/tls/common.js +8 -2
  116. package/node/prelude/internal/tls/wrap.js +5 -16
  117. package/node/prelude/internal/tls/x509.js +1 -1
  118. package/node/prelude/internal/tty_read_stream.js +39 -0
  119. package/node/prelude/internal/tty_streams.js +3 -0
  120. package/node/prelude/internal/util_debuglog.js +68 -0
  121. package/node/prelude/internal/util_diff.js +63 -0
  122. package/node/prelude/internal/util_more.js +111 -0
  123. package/node/prelude/internal/util_styles.js +76 -0
  124. package/node/prelude/internal/zlib_engines.js +1 -1
  125. package/node/prelude/module.js +219 -8
  126. package/node/prelude/net.js +197 -49
  127. package/node/prelude/os.js +88 -11
  128. package/node/prelude/path.js +11 -7
  129. package/node/prelude/path_posix.js +1 -1
  130. package/node/prelude/path_win32.js +1 -1
  131. package/node/prelude/perf_hooks.js +151 -0
  132. package/node/prelude/process.js +36 -1
  133. package/node/prelude/punycode.js +188 -0
  134. package/node/prelude/querystring.js +1 -1
  135. package/node/prelude/readline.js +8 -0
  136. package/node/prelude/readline_promises.js +88 -0
  137. package/node/prelude/repl.js +38 -0
  138. package/node/prelude/sea.js +23 -0
  139. package/node/prelude/stream.js +70 -1332
  140. package/node/prelude/stream_consumers.js +34 -0
  141. package/node/prelude/stream_promises.js +1 -1
  142. package/node/prelude/stream_web.js +15 -2
  143. package/node/prelude/string_decoder.js +1 -1
  144. package/node/prelude/sys.js +7 -0
  145. package/node/prelude/test.js +56 -0
  146. package/node/prelude/test_reporters.js +269 -0
  147. package/node/prelude/timers.js +7 -84
  148. package/node/prelude/timers_promises.js +1 -1
  149. package/node/prelude/tls.js +2 -1
  150. package/node/prelude/trace_events.js +52 -0
  151. package/node/prelude/tty.js +10 -4
  152. package/node/prelude/url.js +88 -27
  153. package/node/prelude/util.js +121 -5
  154. package/node/prelude/util_types.js +4 -3
  155. package/node/prelude/v8.js +814 -0
  156. package/node/prelude/vm.js +86 -0
  157. package/node/prelude/wasi.js +10 -0
  158. package/node/prelude/worker_threads.js +56 -0
  159. package/node/prelude/zlib.js +58 -25
  160. package/node/src/host_brotli.c +59 -11
  161. package/node/src/host_fs.c +342 -11
  162. package/node/src/host_fswatch.c +170 -0
  163. package/node/src/host_http.c +292 -39
  164. package/node/src/host_loop.c +25 -2
  165. package/node/src/host_net.c +130 -16
  166. package/node/src/host_os.c +55 -1
  167. package/node/src/host_proc.c +291 -0
  168. package/node/src/host_process.c +488 -0
  169. package/node/src/host_sys.c +64 -2
  170. package/node/src/host_zlib.c +27 -7
  171. package/node/src/host_zstd.c +41 -6
  172. package/node/third_party/hdrhistogram/LICENSE +42 -0
  173. package/node/third_party/hdrhistogram/README.md +5 -0
  174. package/node/third_party/libuv/LICENSE +0 -0
  175. package/node/third_party/libuv/LICENSE-extra +36 -0
  176. package/node/third_party/libuv/include/uv/aix.h +0 -0
  177. package/node/third_party/libuv/include/uv/bsd.h +0 -0
  178. package/node/third_party/libuv/include/uv/darwin.h +0 -0
  179. package/node/third_party/libuv/include/uv/errno.h +0 -0
  180. package/node/third_party/libuv/include/uv/linux.h +0 -0
  181. package/node/third_party/libuv/include/uv/os390.h +0 -0
  182. package/node/third_party/libuv/include/uv/posix.h +0 -0
  183. package/node/third_party/libuv/include/uv/sunos.h +0 -0
  184. package/node/third_party/libuv/include/uv/threadpool.h +0 -0
  185. package/node/third_party/libuv/include/uv/tree.h +0 -0
  186. package/node/third_party/libuv/include/uv/unix.h +0 -0
  187. package/node/third_party/libuv/include/uv/version.h +0 -0
  188. package/node/third_party/libuv/include/uv/win.h +0 -0
  189. package/node/third_party/libuv/include/uv.h +0 -0
  190. package/node/third_party/libuv/src/fs-poll.c +0 -0
  191. package/node/third_party/libuv/src/heap-inl.h +0 -0
  192. package/node/third_party/libuv/src/idna.c +0 -0
  193. package/node/third_party/libuv/src/idna.h +0 -0
  194. package/node/third_party/libuv/src/inet.c +0 -0
  195. package/node/third_party/libuv/src/queue.h +0 -0
  196. package/node/third_party/libuv/src/random.c +0 -0
  197. package/node/third_party/libuv/src/strscpy.c +0 -0
  198. package/node/third_party/libuv/src/strscpy.h +0 -0
  199. package/node/third_party/libuv/src/strtok.c +0 -0
  200. package/node/third_party/libuv/src/strtok.h +0 -0
  201. package/node/third_party/libuv/src/thread-common.c +0 -0
  202. package/node/third_party/libuv/src/threadpool.c +0 -0
  203. package/node/third_party/libuv/src/timer.c +0 -0
  204. package/node/third_party/libuv/src/unix/async.c +0 -0
  205. package/node/third_party/libuv/src/unix/bsd-ifaddrs.c +0 -0
  206. package/node/third_party/libuv/src/unix/core.c +0 -0
  207. package/node/third_party/libuv/src/unix/darwin-proctitle.c +0 -0
  208. package/node/third_party/libuv/src/unix/darwin-stub.h +0 -0
  209. package/node/third_party/libuv/src/unix/darwin-syscalls.h +0 -0
  210. package/node/third_party/libuv/src/unix/darwin.c +0 -0
  211. package/node/third_party/libuv/src/unix/dl.c +0 -0
  212. package/node/third_party/libuv/src/unix/fs.c +0 -0
  213. package/node/third_party/libuv/src/unix/fsevents.c +0 -0
  214. package/node/third_party/libuv/src/unix/getaddrinfo.c +0 -0
  215. package/node/third_party/libuv/src/unix/getnameinfo.c +0 -0
  216. package/node/third_party/libuv/src/unix/internal.h +0 -0
  217. package/node/third_party/libuv/src/unix/kqueue.c +0 -0
  218. package/node/third_party/libuv/src/unix/linux.c +0 -0
  219. package/node/third_party/libuv/src/unix/loop-watcher.c +0 -0
  220. package/node/third_party/libuv/src/unix/loop.c +0 -0
  221. package/node/third_party/libuv/src/unix/pipe.c +0 -0
  222. package/node/third_party/libuv/src/unix/poll.c +0 -0
  223. package/node/third_party/libuv/src/unix/process.c +0 -0
  224. package/node/third_party/libuv/src/unix/procfs-exepath.c +0 -0
  225. package/node/third_party/libuv/src/unix/proctitle.c +0 -0
  226. package/node/third_party/libuv/src/unix/random-devurandom.c +0 -0
  227. package/node/third_party/libuv/src/unix/random-getentropy.c +0 -0
  228. package/node/third_party/libuv/src/unix/random-getrandom.c +0 -0
  229. package/node/third_party/libuv/src/unix/random-sysctl-linux.c +0 -0
  230. package/node/third_party/libuv/src/unix/signal.c +0 -0
  231. package/node/third_party/libuv/src/unix/stream.c +0 -0
  232. package/node/third_party/libuv/src/unix/tcp.c +0 -0
  233. package/node/third_party/libuv/src/unix/thread.c +0 -0
  234. package/node/third_party/libuv/src/unix/tty.c +0 -0
  235. package/node/third_party/libuv/src/unix/udp.c +0 -0
  236. package/node/third_party/libuv/src/uv-common.c +0 -0
  237. package/node/third_party/libuv/src/uv-common.h +0 -0
  238. package/node/third_party/libuv/src/uv-data-getter-setters.c +0 -0
  239. package/node/third_party/libuv/src/version.c +0 -0
  240. package/node/third_party/llhttp/LICENSE +0 -0
  241. package/node/third_party/llhttp/api.c +0 -0
  242. package/node/third_party/llhttp/http.c +0 -0
  243. package/node/third_party/llhttp/llhttp.c +0 -0
  244. package/node/third_party/llhttp/llhttp.h +0 -0
  245. package/node/third_party/nodejs/LICENSE +47 -0
  246. package/node/third_party/nodejs/README.md +5 -0
  247. package/node/third_party/parseargs/LICENSE +21 -0
  248. package/node/third_party/parseargs/README.md +5 -0
  249. package/node/third_party/punycode/LICENSE +20 -0
  250. package/node/third_party/punycode/README.md +5 -0
  251. package/node/third_party/zlib/LICENSE.chromium +27 -0
  252. package/package.json +1 -1
  253. package/prebuilt/darwin-arm64/boringssl-4a47438eaf7e73ba.a +0 -0
  254. package/prebuilt/darwin-arm64/brotli-7995bbdacc52e51c.a +0 -0
  255. package/prebuilt/darwin-arm64/uv-72ab666eae197cd8.a +0 -0
  256. package/prebuilt/darwin-arm64/zlib-4ce2317a4c3f5fb5.a +0 -0
  257. package/prebuilt/darwin-arm64/zstd-015315ac7c784c73.a +0 -0
  258. package/prebuilt/darwin-x64/boringssl-4a47438eaf7e73ba.a +0 -0
  259. package/prebuilt/darwin-x64/brotli-7995bbdacc52e51c.a +0 -0
  260. package/prebuilt/darwin-x64/uv-72ab666eae197cd8.a +0 -0
  261. package/prebuilt/darwin-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  262. package/prebuilt/darwin-x64/zstd-015315ac7c784c73.a +0 -0
  263. package/prebuilt/linux-arm64/boringssl-4a47438eaf7e73ba.a +0 -0
  264. package/prebuilt/linux-arm64/brotli-65481ff838ce9def.a +0 -0
  265. package/prebuilt/linux-arm64/uv-f1353f50ff983f3c.a +0 -0
  266. package/prebuilt/linux-arm64/zlib-4ce2317a4c3f5fb5.a +0 -0
  267. package/prebuilt/linux-arm64/zstd-015315ac7c784c73.a +0 -0
  268. package/prebuilt/linux-arm64-musl/boringssl-4a47438eaf7e73ba.a +0 -0
  269. package/prebuilt/linux-arm64-musl/brotli-65481ff838ce9def.a +0 -0
  270. package/prebuilt/linux-arm64-musl/uv-f1353f50ff983f3c.a +0 -0
  271. package/prebuilt/linux-arm64-musl/zlib-4ce2317a4c3f5fb5.a +0 -0
  272. package/prebuilt/linux-arm64-musl/zstd-015315ac7c784c73.a +0 -0
  273. package/prebuilt/linux-x64/boringssl-4a47438eaf7e73ba.a +0 -0
  274. package/prebuilt/linux-x64/brotli-65481ff838ce9def.a +0 -0
  275. package/prebuilt/linux-x64/uv-f1353f50ff983f3c.a +0 -0
  276. package/prebuilt/linux-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  277. package/prebuilt/linux-x64/zstd-015315ac7c784c73.a +0 -0
  278. package/prebuilt/linux-x64-musl/boringssl-4a47438eaf7e73ba.a +0 -0
  279. package/prebuilt/linux-x64-musl/brotli-65481ff838ce9def.a +0 -0
  280. package/prebuilt/linux-x64-musl/uv-f1353f50ff983f3c.a +0 -0
  281. package/prebuilt/linux-x64-musl/zlib-4ce2317a4c3f5fb5.a +0 -0
  282. package/prebuilt/linux-x64-musl/zstd-015315ac7c784c73.a +0 -0
  283. package/prebuilt/win32-x64/boringssl-ce573858472b7fc9.a +0 -0
  284. package/prebuilt/win32-x64/brotli-20d86a61f30baeb3.a +0 -0
  285. package/prebuilt/win32-x64/uv-b11bae65d7fced82.a +0 -0
  286. package/prebuilt/win32-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  287. package/prebuilt/win32-x64/zstd-015315ac7c784c73.a +0 -0
  288. package/runtime/include/js_atoms.gen.h +0 -0
  289. package/runtime/include/js_atoms.h +5 -1
  290. package/runtime/include/js_bigint.h +1 -1
  291. package/runtime/include/js_buffer.h +4 -4
  292. package/runtime/include/js_builtins.h +41 -3
  293. package/runtime/include/js_console.h +9 -4
  294. package/runtime/include/js_convert.h +1 -1
  295. package/runtime/include/js_core.def +5 -4
  296. package/runtime/include/js_crypto.h +1 -1
  297. package/runtime/include/js_error.h +1 -1
  298. package/runtime/include/js_exception.h +21 -1
  299. package/runtime/include/js_function.h +33 -9
  300. package/runtime/include/js_gc.h +172 -30
  301. package/runtime/include/js_generator.h +2 -2
  302. package/runtime/include/js_host.h +19 -1
  303. package/runtime/include/js_jobs.h +5 -5
  304. package/runtime/include/js_module.h +1 -1
  305. package/runtime/include/js_object.h +142 -15
  306. package/runtime/include/js_ops.h +107 -5
  307. package/runtime/include/js_promise.h +3 -3
  308. package/runtime/include/js_regexp.h +1 -1
  309. package/runtime/include/js_runtime.h +0 -0
  310. package/runtime/include/js_symbol.h +1 -1
  311. package/runtime/include/js_web.h +5 -1
  312. package/runtime/include/jscell.h +22 -15
  313. package/runtime/include/jscontext.h +82 -39
  314. package/runtime/include/jsnum.h +1 -1
  315. package/runtime/include/jsstring.h +19 -6
  316. package/runtime/include/jsvalue.h +7 -3
  317. package/runtime/src/arguments.c +2 -2
  318. package/runtime/src/array.c +4 -1
  319. package/runtime/src/arraybuffer.c +19 -7
  320. package/runtime/src/async_iter.c +4 -3
  321. package/runtime/src/atoms.c +38 -4
  322. package/runtime/src/base64.c +2 -2
  323. package/runtime/src/bigint.c +1 -1
  324. package/runtime/src/blob.c +22 -9
  325. package/runtime/src/boringssl_support.cc +1 -1
  326. package/runtime/src/buffer.c +299 -91
  327. package/runtime/src/builtin_table.c +1 -1
  328. package/runtime/src/builtins.c +30 -4
  329. package/runtime/src/builtins_util.h +0 -0
  330. package/runtime/src/collections.c +18 -3
  331. package/runtime/src/components.c +1 -1
  332. package/runtime/src/console.c +14 -7
  333. package/runtime/src/convert.c +0 -0
  334. package/runtime/src/core_all.c +1 -1
  335. package/runtime/src/crypto.c +1 -1
  336. package/runtime/src/crypto_asym.c +1 -1
  337. package/runtime/src/crypto_bn.c +1 -1
  338. package/runtime/src/crypto_cipher.c +10 -3
  339. package/runtime/src/crypto_hash.c +1 -1
  340. package/runtime/src/crypto_host.c +1 -1
  341. package/runtime/src/crypto_internal.h +1 -1
  342. package/runtime/src/crypto_kdf.c +1 -1
  343. package/runtime/src/crypto_key.c +14 -1
  344. package/runtime/src/crypto_pkey.c +1 -1
  345. package/runtime/src/crypto_subtle.c +142 -58
  346. package/runtime/src/crypto_tls.c +1 -1
  347. package/runtime/src/date.c +5 -2
  348. package/runtime/src/domexception.c +2 -2
  349. package/runtime/src/elements.c +56 -17
  350. package/runtime/src/elements.h +7 -2
  351. package/runtime/src/encoding.c +1 -1
  352. package/runtime/src/error.c +4 -4
  353. package/runtime/src/events.c +42 -14
  354. package/runtime/src/exception.c +1 -1
  355. package/runtime/src/fetch.c +241 -17
  356. package/runtime/src/function.c +31 -19
  357. package/runtime/src/gc.c +1720 -211
  358. package/runtime/src/gc_visit.h +87 -0
  359. package/runtime/src/generator.c +5 -3
  360. package/runtime/src/global.c +14 -6
  361. package/runtime/src/headers.c +10 -10
  362. package/runtime/src/inspect.c +76 -17
  363. package/runtime/src/internal.h +9 -6
  364. package/runtime/src/iterate.c +94 -2
  365. package/runtime/src/iterator.c +1 -1
  366. package/runtime/src/jobs.c +11 -5
  367. package/runtime/src/jsnum.c +2 -2
  368. package/runtime/src/json.c +1 -1
  369. package/runtime/src/math.c +9 -1
  370. package/runtime/src/module.c +3 -3
  371. package/runtime/src/number.c +0 -0
  372. package/runtime/src/object.c +107 -74
  373. package/runtime/src/ops.c +21 -3
  374. package/runtime/src/os.c +192 -1
  375. package/runtime/src/os.h +33 -2
  376. package/runtime/src/process.c +73 -8
  377. package/runtime/src/promise.c +4 -4
  378. package/runtime/src/proxy.c +1 -1
  379. package/runtime/src/reflect.c +1 -1
  380. package/runtime/src/regexp.c +700 -11
  381. package/runtime/src/regexp_anchor.h +1 -1
  382. package/runtime/src/regexp_message.h +1 -1
  383. package/runtime/src/shape.c +78 -20
  384. package/runtime/src/shape.h +0 -0
  385. package/runtime/src/streams.c +22 -8
  386. package/runtime/src/streams.h +0 -0
  387. package/runtime/src/string.c +64 -25
  388. package/runtime/src/string_builtins.c +7 -7
  389. package/runtime/src/symbol.c +2 -7
  390. package/runtime/src/test_host.c +3 -3
  391. package/runtime/src/tls_roots.gen.h +102 -620
  392. package/runtime/src/typedarray.c +8 -3
  393. package/runtime/src/tznames.gen.h +2 -1
  394. package/runtime/src/uri.c +1 -1
  395. package/runtime/src/url.c +42 -39
  396. package/runtime/src/weak.c +110 -36
  397. package/runtime/src/web.c +21 -3
  398. package/runtime/src/wrapper.c +0 -0
  399. package/runtime/src/writable.c +7 -6
  400. package/runtime/third_party/ada-idna/LICENSE-MIT +0 -0
  401. package/runtime/third_party/ada-idna/README.md +7 -7
  402. package/runtime/third_party/ada-idna/convert.mjs +89 -27
  403. package/runtime/third_party/ada-idna/idna.c +30 -31
  404. package/runtime/third_party/ada-idna/idna.h +0 -0
  405. package/runtime/third_party/ada-idna/idna_tables.h +2272 -1952
  406. package/runtime/third_party/boringssl/third_party/fiat/LICENSE +15 -0
  407. package/runtime/third_party/mozilla-ca/LICENSE +373 -0
  408. package/runtime/third_party/mozilla-ca/README.md +9 -0
  409. package/runtime/third_party/nodejs/LICENSE +47 -0
  410. package/runtime/third_party/nodejs/README.md +7 -0
  411. package/runtime/third_party/quickjs-dtoa/LICENSE +0 -0
  412. package/runtime/third_party/quickjs-dtoa/README.md +1 -1
  413. package/runtime/third_party/quickjs-dtoa/dtoa.c +0 -0
  414. package/runtime/third_party/quickjs-dtoa/dtoa.h +0 -0
  415. package/runtime/third_party/quickjs-dtoa/dtoa_compat.h +0 -0
  416. package/runtime/third_party/quickjs-regexp/LICENSE +0 -0
  417. package/runtime/third_party/quickjs-regexp/README.md +2 -2
  418. package/runtime/third_party/quickjs-regexp/cutils.c +0 -0
  419. package/runtime/third_party/quickjs-regexp/cutils.h +0 -0
  420. package/runtime/third_party/quickjs-regexp/libregexp-opcode.h +0 -0
  421. package/runtime/third_party/quickjs-regexp/libregexp.c +0 -0
  422. package/runtime/third_party/quickjs-regexp/libregexp.h +0 -0
  423. package/runtime/third_party/quickjs-regexp/libunicode-table.h +0 -0
  424. package/runtime/third_party/quickjs-regexp/libunicode.c +0 -0
  425. package/runtime/third_party/quickjs-regexp/libunicode.h +0 -0
  426. package/runtime/third_party/unicode/LICENSE +39 -0
  427. package/runtime/third_party/unicode/README.md +9 -0
  428. package/runtime/third_party/v8-ieee754/LICENSE +0 -0
  429. package/runtime/third_party/v8-ieee754/LICENSE.fdlibm +10 -0
  430. package/runtime/third_party/v8-ieee754/README.md +3 -2
  431. package/runtime/third_party/v8-ieee754/convert.py +0 -0
  432. package/runtime/third_party/v8-ieee754/ieee754.c +0 -0
  433. package/runtime/third_party/v8-ieee754/ieee754.h +0 -0
  434. package/runtime/tools/regexp_compile.c +2 -2
@@ -1,4 +1,4 @@
1
- /* Host primitives for node:http (ADR 0012, host prelude): llhttp (Node's parser) on node:net's
1
+ /* Host primitives for node:http: llhttp (Node's parser) on node:net's
2
2
  * sockets, for a server's requests and a client's responses. As in Node, a connection is a
3
3
  * net.Socket, but its bytes go to the parser in C, not through JS: host_net.c's hook hands them
4
4
  * over. The prelude's http.js builds Node's objects from what the parser finds; C does the
@@ -22,6 +22,12 @@
22
22
  * writes goes out in one write when it (and its microtasks) returns
23
23
  * httpFlush(conn) sends the corked output now (before the socket is ended)
24
24
  * httpDate() → the Date header's value
25
+ * A socket whose bytes aren't its handle's (a TLS socket's are decrypted in JS, a Duplex has no
26
+ * handle) is a fed connection, with a negative id: JS gives its parser the bytes, and its output
27
+ * goes to a JS writer (which the TLS socket encrypts).
28
+ * httpFedOpen(writer) → conn writer(bytes) gets what the connection's output flushes
29
+ * httpFeed(conn, bytes | null) → whether the parser took them (null: the end of the input)
30
+ * httpFedClose(conn) the connection is done with (its socket closed)
25
31
  * The loop is host_loop.c's; the sockets are host_net.c's. */
26
32
  #define _POSIX_C_SOURCE 200809L /* libuv's headers: pthread_rwlock_t, struct addrinfo */
27
33
  #include <stdio.h>
@@ -44,11 +50,12 @@
44
50
  static void flush_pending(void);
45
51
  typedef struct Conn Conn;
46
52
  static void flush_conn(Conn *c);
53
+ static size_t pending_bytes(Conn *c);
47
54
 
48
55
  /* ---- Parsers and connections ------------------------------------------------------------- */
49
56
 
50
57
  typedef struct Parsers {
51
- JSValue on_request, on_body, on_complete, on_upgrade, on_error; /* roots */
58
+ JSValue on_request, on_body, on_complete, on_upgrade, on_error, on_drain; /* roots */
52
59
  } Parsers;
53
60
 
54
61
  typedef struct Buf {
@@ -64,9 +71,13 @@ struct Conn {
64
71
  bool detached; /* upgraded, or a parse error: the parser doesn't read any more */
65
72
  bool executing; /* llhttp is running on it: it can't be freed yet */
66
73
  bool released; /* let go of while executing: freed when llhttp returns */
74
+ bool detach_after; /* detached when llhttp is done with the read (httpDetach's afterRead) */
67
75
  bool upgrading; /* JS took the upgrade the head asked for */
68
76
  bool active; /* a message is under way (or the connection is new): timeouts count */
69
77
  bool head_done; /* its head is complete: what follows are its body and trailers */
78
+ bool in_message; /* a message has begun and isn't complete: the connection isn't idle */
79
+ llhttp_errno_t failed; /* the parse error it stopped at: more bytes report it again, as Node's */
80
+ bool need_drain; /* JS waits for its output to drain (a write over the high-water mark) */
70
81
  bool overflow; /* its head is over max_header bytes */
71
82
  uint64_t begin_ms; /* when the message began (the loop's time) */
72
83
  size_t header_bytes, max_header;
@@ -77,10 +88,18 @@ struct Conn {
77
88
  Buf out; /* written but not sent: corked, as Node corks a response */
78
89
  };
79
90
 
91
+ /* A fed connection: its writer, and the parser it has now (a new one per kept-alive request). */
92
+ typedef struct Fed {
93
+ JSValue writer; /* a root */
94
+ Conn *conn;
95
+ } Fed;
96
+
80
97
  static Parsers **parsers;
81
98
  static size_t nparsers;
82
99
  static Conn **conns; /* by net handle id */
83
100
  static size_t nconns;
101
+ static Fed **feds; /* fed connections: id -(k + 1) is feds[k] */
102
+ static size_t nfeds;
84
103
  static int *pending; /* ids of connections with corked output */
85
104
  static size_t npending, pending_cap;
86
105
  static llhttp_settings_t settings;
@@ -136,6 +155,7 @@ static int on_message_begin(llhttp_t *p) {
136
155
  c->headers = js_new_array(ctx_(), 0);
137
156
  c->active = true;
138
157
  c->head_done = false;
158
+ c->in_message = true;
139
159
  c->header_bytes = 0;
140
160
  c->begin_ms = uv_now(js_uv_loop(ctx_()));
141
161
  return 0;
@@ -206,21 +226,40 @@ static int on_message_complete(llhttp_t *p) {
206
226
  if (c->detached) return -1; /* let go of by an earlier callback */
207
227
  if (c->in_value || c->field.n) push_header(c); /* the last trailer */
208
228
  c->active = false;
229
+ c->in_message = false;
209
230
  JSValue args[2] = { js_int32(c->id), c->headers };
210
231
  c->headers = JS_UNDEFINED;
211
232
  return js_uv_call(c->parsers->on_complete, 2, args, NULL) ? 0 : -1;
212
233
  }
213
234
 
214
- static Conn *conn_of(int id) { return id >= 0 && (size_t)id < nconns ? conns[id] : NULL; }
235
+ static Fed *fed_of(int id) {
236
+ if (id >= 0) return NULL;
237
+ size_t k = (size_t)(-(id + 1));
238
+ return k < nfeds ? feds[k] : NULL;
239
+ }
240
+
241
+ static Conn *conn_of(int id) {
242
+ if (id < 0) {
243
+ Fed *f = fed_of(id);
244
+ return f ? f->conn : NULL;
245
+ }
246
+ return (size_t)id < nconns ? conns[id] : NULL;
247
+ }
215
248
 
216
- static void parse_error(Conn *c, llhttp_errno_t e) {
249
+ /* the parse error, with Node's bytesParsed and rawPacket: how far into the read llhttp got, and
250
+ * the read (none for a message cut short at the end of the stream) */
251
+ static void parse_error(Conn *c, llhttp_errno_t e, const char *bytes, size_t n) {
217
252
  c->detached = true;
253
+ c->failed = e;
218
254
  c->active = false;
219
255
  JSContext *ctx = ctx_();
220
256
  const char *code = c->overflow ? "HPE_HEADER_OVERFLOW" : llhttp_errno_name(e);
221
257
  const char *reason = c->overflow ? "Header overflow" : llhttp_get_error_reason(&c->parser);
222
- JSValue args[3] = { js_int32(c->id), js_new_string_cstr(ctx, code), js_new_string_cstr(ctx, reason ? reason : "") };
223
- (void)js_uv_call(c->parsers->on_error, 3, args, NULL);
258
+ const char *pos = bytes ? llhttp_get_error_pos(&c->parser) : NULL;
259
+ int32_t parsed = pos && pos >= bytes && pos <= bytes + n ? (int32_t)(pos - bytes) : 0;
260
+ JSValue args[5] = { js_int32(c->id), js_new_string_cstr(ctx, code), js_new_string_cstr(ctx, reason ? reason : ""), js_int32(parsed),
261
+ bytes ? bytes_value(ctx, bytes, n) : JS_UNDEFINED };
262
+ (void)js_uv_call(c->parsers->on_error, 5, args, NULL);
224
263
  }
225
264
 
226
265
  static void free_conn(Conn *c) {
@@ -233,16 +272,45 @@ static void free_conn(Conn *c) {
233
272
  * when llhttp returns if a callback let go of it (a client frees its parser in the response's
234
273
  * last callback, and starts the next request in a microtask). */
235
274
  static void release_conn(Conn *c) {
236
- if (conns[c->id] == c) conns[c->id] = NULL;
275
+ Fed *f = fed_of(c->id);
276
+ if (f) {
277
+ if (f->conn == c) f->conn = NULL;
278
+ } else if (conns[c->id] == c) {
279
+ conns[c->id] = NULL;
280
+ }
237
281
  c->detached = true;
238
282
  if (c->executing) c->released = true;
239
283
  else free_conn(c);
240
284
  }
241
285
 
242
- /* The socket's bytes, before JS sees them: parsed while attached; EOF and errors go on to JS
243
- * (the socket's 'end' and 'error'). */
244
- static bool hook_read(void *data, ssize_t n, const char *bytes) {
245
- Conn *c = data;
286
+ /* The socket's bytes go to JS again: the corked output first, then the parser let go of. */
287
+ static void detach_conn(Conn *c) {
288
+ if (c->queued) flush_conn(c);
289
+ if (c->id >= 0) js_net_hook(c->id, NULL, NULL);
290
+ release_conn(c);
291
+ }
292
+
293
+ /* llhttp is done with a read: a parser let go of meanwhile is freed, or detached if asked to be. */
294
+ static void read_done(Conn *c) {
295
+ c->executing = false;
296
+ if (c->released) {
297
+ free_conn(c);
298
+ } else if (c->detach_after) {
299
+ c->detach_after = false;
300
+ detach_conn(c);
301
+ }
302
+ }
303
+
304
+ /* A connection's bytes: parsed while attached; EOF and errors go on to JS (the socket's 'end'
305
+ * and 'error'). False when the parser doesn't take them. */
306
+ static bool parse_input(Conn *c, ssize_t n, const char *bytes) {
307
+ if (c->detached && c->failed != HPE_OK && n > 0 && !c->executing) {
308
+ /* a parser that failed fails again on what follows, with those bytes (Node's execute) */
309
+ c->executing = true;
310
+ parse_error(c, c->failed, bytes, (size_t)n);
311
+ read_done(c);
312
+ return true;
313
+ }
246
314
  if (c->detached) return false;
247
315
  c->executing = true;
248
316
  if (n < 0) {
@@ -250,10 +318,9 @@ static bool hook_read(void *data, ssize_t n, const char *bytes) {
250
318
  /* a request cut short is the server's parse error; a client's response cut short shows
251
319
  * as its 'aborted', when the socket closes (as Node's socketOnEnd ignores finish()) */
252
320
  llhttp_errno_t e = llhttp_finish(&c->parser);
253
- if (e != HPE_OK && !c->detached && !c->response) parse_error(c, e);
321
+ if (e != HPE_OK && !c->detached && !c->response) parse_error(c, e, NULL, 0);
254
322
  }
255
- c->executing = false;
256
- if (c->released) free_conn(c);
323
+ read_done(c);
257
324
  return false;
258
325
  }
259
326
  const char *at = bytes, *end = bytes + n;
@@ -261,7 +328,7 @@ static bool hook_read(void *data, ssize_t n, const char *bytes) {
261
328
  llhttp_errno_t e = llhttp_execute(&c->parser, at, (size_t)(end - at));
262
329
  if (e == HPE_OK || c->detached) break; /* released or upgraded by a callback: stop here */
263
330
  if (e != HPE_PAUSED_UPGRADE) {
264
- parse_error(c, e); /* nothing runs once a callback failed in JS: the loop is ending */
331
+ parse_error(c, e, bytes, (size_t)n); /* nothing runs once a callback failed in JS: the loop is ending */
265
332
  break;
266
333
  }
267
334
  const char *pos = llhttp_get_error_pos(&c->parser);
@@ -276,16 +343,66 @@ static bool hook_read(void *data, ssize_t n, const char *bytes) {
276
343
  (void)js_uv_call(c->parsers->on_upgrade, 2, args, NULL);
277
344
  break;
278
345
  }
279
- c->executing = false;
280
- if (c->released) free_conn(c);
346
+ read_done(c);
281
347
  return true;
282
348
  }
283
349
 
350
+ /* A socket's bytes, before JS sees them. */
351
+ /* a socket's read, parsed in C: its callbacks (a body and its end) run before the microtasks and
352
+ * nextTicks do, as in Node, where one read is one callback scope */
353
+ static bool hook_read(void *data, ssize_t n, const char *bytes) {
354
+ js_uv_nest(1);
355
+ bool ok = parse_input(data, n, bytes);
356
+ js_uv_nest(-1);
357
+ return js_uv_drain() && ok;
358
+ }
359
+
284
360
  static void hook_close(void *data) { release_conn(data); }
285
361
 
286
362
  static const JSNetHook http_hook = { hook_read, hook_close };
287
363
 
288
- /* httpParsers(onHead, onBody, onComplete, onUpgrade, onError) → id */
364
+ /* ---- An idle client socket's guard --------------------------------------------------------- */
365
+
366
+ /* Bytes a socket reads while it waits in an agent's pool (no request on it): a server sending what
367
+ * nobody asked for, which the next request would take for its response. Node's free socket data
368
+ * guard: the bytes are dropped and JS destroys the socket. Its end and errors go on to JS. */
369
+ static JSValue guard_callback = JS_UNDEFINED;
370
+ static bool guard_rooted;
371
+
372
+ static bool guard_read(void *data, ssize_t n, const char *bytes) {
373
+ (void)bytes;
374
+ if (n <= 0) return false;
375
+ int id = (int)(intptr_t)data;
376
+ js_net_hook(id, NULL, NULL);
377
+ if (js_is_callable(guard_callback)) {
378
+ JSValue arg = js_int32(id);
379
+ js_uv_nest(1);
380
+ (void)js_uv_call(guard_callback, 1, &arg, NULL);
381
+ js_uv_nest(-1);
382
+ (void)js_uv_drain();
383
+ }
384
+ return true;
385
+ }
386
+
387
+ static void guard_close(void *data) { (void)data; }
388
+
389
+ static const JSNetHook guard_hook = { guard_read, guard_close };
390
+
391
+ /* httpGuard(conn, onData) → whether it's guarded: onData(conn) when the socket reads while idle */
392
+ JSValue js_host_http_guard(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
393
+ (void)callee, (void)this_val, (void)new_target;
394
+ if (argc < 2 || !js_is_int32(argv[0])) return JS_FALSE;
395
+ int id = js_as_int32(argv[0]);
396
+ if (id < 0 || ((size_t)id < nconns && conns[id])) return JS_FALSE; /* a parser has it */
397
+ if (!guard_rooted) {
398
+ js_add_root(ctx->rt, &guard_callback);
399
+ guard_rooted = true;
400
+ }
401
+ guard_callback = argv[1];
402
+ return js_bool(js_net_hook(id, &guard_hook, (void *)(intptr_t)id));
403
+ }
404
+
405
+ /* httpParsers(onHead, onBody, onComplete, onUpgrade, onError, onDrain) → id */
289
406
  JSValue js_host_http_parsers(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
290
407
  (void)callee, (void)this_val, (void)new_target;
291
408
  if (argc < 5) return js_throw_type_error(ctx, "httpParsers: 5 arguments expected");
@@ -305,8 +422,9 @@ JSValue js_host_http_parsers(JSContext *ctx, JSValue callee, JSValue this_val, u
305
422
  Parsers *p = malloc(sizeof *p);
306
423
  if (!p) js_fatal("out of memory in http");
307
424
  p->on_request = argv[0], p->on_body = argv[1], p->on_complete = argv[2], p->on_upgrade = argv[3], p->on_error = argv[4];
425
+ p->on_drain = argc > 5 ? argv[5] : JS_UNDEFINED;
308
426
  js_add_root(ctx->rt, &p->on_request), js_add_root(ctx->rt, &p->on_body), js_add_root(ctx->rt, &p->on_complete);
309
- js_add_root(ctx->rt, &p->on_upgrade), js_add_root(ctx->rt, &p->on_error);
427
+ js_add_root(ctx->rt, &p->on_upgrade), js_add_root(ctx->rt, &p->on_error), js_add_root(ctx->rt, &p->on_drain);
310
428
  Parsers **v = realloc(parsers, (nparsers + 1) * sizeof *v);
311
429
  if (!v) js_fatal("out of memory in http");
312
430
  parsers = v;
@@ -320,8 +438,11 @@ JSValue js_host_http_attach(JSContext *ctx, JSValue callee, JSValue this_val, ui
320
438
  if (argc < 2 || !js_is_int32(argv[0]) || !js_is_int32(argv[1])) return js_throw_type_error(ctx, "httpAttach: (conn, parsers) expected");
321
439
  int id = js_as_int32(argv[0]);
322
440
  int32_t pi = js_as_int32(argv[1]);
323
- if (pi < 0 || (size_t)pi >= nparsers || !js_net_stream(id)) return js_int32(UV_EBADF);
324
- if ((size_t)id >= nconns) {
441
+ Fed *f = fed_of(id);
442
+ if (pi < 0 || (size_t)pi >= nparsers || (id < 0 ? !f : !js_net_stream(id))) return js_int32(UV_EBADF);
443
+ if (f) {
444
+ if (f->conn) release_conn(f->conn);
445
+ } else if ((size_t)id >= nconns) {
325
446
  size_t n = nconns ? nconns : 64;
326
447
  while (n <= (size_t)id) n *= 2;
327
448
  Conn **v = realloc(conns, n * sizeof *v);
@@ -330,7 +451,7 @@ JSValue js_host_http_attach(JSContext *ctx, JSValue callee, JSValue this_val, ui
330
451
  conns = v;
331
452
  nconns = n;
332
453
  }
333
- if (conns[id]) release_conn(conns[id]); /* a kept-alive socket's next request: a fresh parser */
454
+ if (!f && conns[id]) release_conn(conns[id]); /* a kept-alive socket's next request: a fresh parser */
334
455
  Conn *c = calloc(1, sizeof *c);
335
456
  if (!c) js_fatal("out of memory in http");
336
457
  c->id = id;
@@ -343,23 +464,52 @@ JSValue js_host_http_attach(JSContext *ctx, JSValue callee, JSValue this_val, ui
343
464
  js_add_root(ctx->rt, &c->headers);
344
465
  llhttp_init(&c->parser, c->response ? HTTP_RESPONSE : HTTP_REQUEST, &settings);
345
466
  c->parser.data = c;
346
- conns[id] = c;
347
- js_net_hook(id, &http_hook, c);
467
+ if (f) {
468
+ f->conn = c; /* its bytes come from httpFeed */
469
+ } else {
470
+ conns[id] = c;
471
+ js_net_hook(id, &http_hook, c);
472
+ }
348
473
  return js_int32(0);
349
474
  }
350
475
 
351
- /* httpDetach(conn): the socket's bytes go to JS again (its corked output goes first) */
476
+ /* httpDetach(conn, afterRead): the socket's bytes go to JS again (its corked output goes first);
477
+ * with afterRead, from a parser callback, once llhttp is done with the read, as Node's client frees
478
+ * its parser after the read (what follows a response in it is still parsed) */
352
479
  JSValue js_host_http_detach(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
353
480
  (void)ctx, (void)callee, (void)this_val, (void)new_target;
354
481
  Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
355
- if (c) {
356
- if (c->queued) flush_conn(c);
357
- js_net_hook(c->id, NULL, NULL);
358
- release_conn(c);
359
- }
482
+ if (!c) return JS_UNDEFINED;
483
+ if (argc > 1 && js_truthy(argv[1]) && c->executing) c->detach_after = true;
484
+ else detach_conn(c);
360
485
  return JS_UNDEFINED;
361
486
  }
362
487
 
488
+ /* httpBusy(conn): whether a message is under way on the connection (begun, not complete), as Node's
489
+ * ConnectionsList tells an idle connection from an active one */
490
+ JSValue js_host_http_busy(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
491
+ (void)ctx, (void)callee, (void)this_val, (void)new_target;
492
+ Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
493
+ return js_bool(c && c->in_message && !c->detached);
494
+ }
495
+
496
+ /* httpPending(conn) → the bytes written to it that haven't gone out yet (a response's backpressure) */
497
+ JSValue js_host_http_pending(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
498
+ (void)ctx, (void)callee, (void)this_val, (void)new_target;
499
+ Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
500
+ return js_number(c ? (double)pending_bytes(c) : 0);
501
+ }
502
+
503
+ /* httpWatchDrain(conn) → true when nothing is pending (drained already), else the parsers' onDrain
504
+ * is called once it all has gone out */
505
+ JSValue js_host_http_watch_drain(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
506
+ (void)ctx, (void)callee, (void)this_val, (void)new_target;
507
+ Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
508
+ if (!c || pending_bytes(c) == 0) return JS_TRUE;
509
+ c->need_drain = true;
510
+ return JS_FALSE;
511
+ }
512
+
363
513
  /* httpExpired(parsers, headersTimeout, requestTimeout) → the connections over time, as Node's
364
514
  * ConnectionsList::Expired: a head not complete within headersTimeout, or a request not
365
515
  * complete within requestTimeout, from its start (or the connection's); 0 turns one off */
@@ -372,8 +522,8 @@ JSValue js_host_http_expired(JSContext *ctx, JSValue callee, JSValue this_val, u
372
522
  JSValue list = js_new_array(ctx, 0);
373
523
  if (pi < 0 || (size_t)pi >= nparsers) return list;
374
524
  uint64_t now = uv_now(js_uv_loop(ctx));
375
- for (size_t i = 0; i < nconns; i++) {
376
- Conn *c = conns[i];
525
+ for (size_t i = 0; i < nconns + nfeds; i++) {
526
+ Conn *c = i < nconns ? conns[i] : feds[i - nconns] ? feds[i - nconns]->conn : NULL;
377
527
  if (!c || c->parsers != parsers[pi] || !c->active || c->detached) continue;
378
528
  uint64_t age = now - c->begin_ms;
379
529
  if ((!c->head_done && headers_timeout > 0 && (double)age > headers_timeout) || (request_timeout > 0 && (double)age > request_timeout)) {
@@ -389,18 +539,44 @@ JSValue js_host_http_expired(JSContext *ctx, JSValue callee, JSValue this_val, u
389
539
  typedef struct WriteReq {
390
540
  uv_write_t req;
391
541
  char *data;
542
+ int id; /* the connection's: whether its output has drained, once written */
392
543
  } WriteReq;
393
544
 
545
+ /* bytes written to the connection but not yet sent: corked, or in libuv's write queue */
546
+ static size_t pending_bytes(Conn *c) {
547
+ uv_stream_t *s = c->id >= 0 ? js_net_stream(c->id) : NULL;
548
+ return c->out.n + (s ? uv_stream_get_write_queue_size(s) : 0);
549
+ }
550
+
394
551
  static void on_written(uv_write_t *req, int status) {
395
552
  (void)status; /* a failed write shows as the socket's read error, or its close */
396
553
  WriteReq *w = (WriteReq *)req;
554
+ int id = w->id;
397
555
  free(w->data);
398
556
  free(w);
557
+ /* JS waited for the output to drain (Node's 'drain' on the response) */
558
+ Conn *c = conn_of(id);
559
+ if (c && c->need_drain && pending_bytes(c) == 0) {
560
+ c->need_drain = false;
561
+ if (js_is_callable(c->parsers->on_drain)) {
562
+ JSValue arg = js_int32(id);
563
+ (void)js_uv_call(c->parsers->on_drain, 1, &arg, NULL);
564
+ }
565
+ }
399
566
  }
400
567
 
401
568
  /* Sends a connection's corked output as one write. */
402
569
  static void flush_conn(Conn *c) {
403
570
  c->queued = false;
571
+ Fed *f = fed_of(c->id);
572
+ if (f) { /* to its writer: the connection may be gone when it returns */
573
+ if (c->out.n == 0) return;
574
+ JSValue bytes = bytes_value(ctx_(), c->out.v, c->out.n);
575
+ c->out.n = 0;
576
+ JSValue writer = f->writer;
577
+ (void)js_uv_call(writer, 1, &bytes, NULL);
578
+ return;
579
+ }
404
580
  uv_stream_t *s = js_net_stream(c->id);
405
581
  if (!s || c->out.n == 0) {
406
582
  c->out.n = 0;
@@ -409,6 +585,7 @@ static void flush_conn(Conn *c) {
409
585
  WriteReq *w = malloc(sizeof *w);
410
586
  if (!w) js_fatal("out of memory in http");
411
587
  w->data = c->out.v; /* the buffer goes with the write; the connection starts a new one */
588
+ w->id = c->id;
412
589
  uv_buf_t b = uv_buf_init(c->out.v, (unsigned)c->out.n);
413
590
  c->out = (Buf){ 0 };
414
591
  if (uv_write(&w->req, s, &b, 1, on_written) < 0) {
@@ -417,20 +594,35 @@ static void flush_conn(Conn *c) {
417
594
  }
418
595
  }
419
596
 
597
+ /* Taken over before it runs: a fed connection's writer runs JS, which may write (and flush) more. */
420
598
  static void flush_pending(void) {
421
- for (size_t i = 0; i < npending; i++) {
422
- Conn *c = conn_of(pending[i]);
423
- if (c && c->queued) flush_conn(c);
599
+ while (npending > 0) {
600
+ int *ids = pending;
601
+ size_t n = npending;
602
+ pending = NULL;
603
+ npending = pending_cap = 0;
604
+ for (size_t i = 0; i < n; i++) {
605
+ Conn *c = conn_of(ids[i]);
606
+ if (c && c->queued) flush_conn(c);
607
+ }
608
+ free(ids);
424
609
  }
425
- npending = 0;
426
610
  }
427
611
 
428
- /* httpWrite(conn, data): corked until the current callback (and its microtasks) returns */
612
+ /* httpWrite(conn, data, latin1): corked until the current callback (and its microtasks) returns; a
613
+ * string as UTF-8, or with latin1 a byte a character (its low byte), as Node writes a head */
429
614
  JSValue js_host_http_write(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
430
615
  (void)callee, (void)this_val, (void)new_target;
431
616
  Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
432
- if (!c || argc < 2 || !js_net_stream(c->id)) return JS_FALSE;
433
- if (js_is_string(argv[1])) {
617
+ if (!c || argc < 2 || (c->id >= 0 && !js_net_stream(c->id))) return JS_FALSE;
618
+ if (js_is_string(argv[1]) && argc > 2 && js_truthy(argv[2])) {
619
+ JSStrView v = js_string_view(ctx, argv[1]);
620
+ if (v.length == 0) return JS_TRUE;
621
+ buf_reserve(&c->out, v.length);
622
+ if (v.latin1) memcpy(c->out.v + c->out.n, v.chars, v.length);
623
+ else for (uint32_t i = 0; i < v.length; i++) c->out.v[c->out.n + i] = (char)(js_view_at(v, i) & 0xff);
624
+ c->out.n += v.length;
625
+ } else if (js_is_string(argv[1])) {
434
626
  JSStrView v = js_string_view(ctx, argv[1]);
435
627
  size_t n = js_view_to_utf8(v, NULL, 0);
436
628
  if (n == 0) return JS_TRUE;
@@ -465,6 +657,67 @@ JSValue js_host_http_flush(JSContext *ctx, JSValue callee, JSValue this_val, uin
465
657
  return JS_UNDEFINED;
466
658
  }
467
659
 
660
+ /* ---- Fed connections --------------------------------------------------------------------- */
661
+
662
+ /* httpFedOpen(writer) → conn: a connection whose bytes JS feeds */
663
+ JSValue js_host_http_fed_open(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
664
+ (void)callee, (void)this_val, (void)new_target;
665
+ if (argc < 1 || !js_is_callable(argv[0])) return js_throw_type_error(ctx, "httpFedOpen: a writer expected");
666
+ size_t k = 0;
667
+ while (k < nfeds && feds[k]) k++;
668
+ if (k == nfeds) {
669
+ size_t n = nfeds ? nfeds * 2 : 16;
670
+ Fed **v = realloc(feds, n * sizeof *v);
671
+ if (!v) js_fatal("out of memory in http");
672
+ memset(v + nfeds, 0, (n - nfeds) * sizeof *v);
673
+ feds = v;
674
+ nfeds = n;
675
+ }
676
+ Fed *f = calloc(1, sizeof *f); /* by itself: its writer is a root at a fixed address */
677
+ if (!f) js_fatal("out of memory in http");
678
+ f->writer = argv[0];
679
+ js_add_root(ctx->rt, &f->writer);
680
+ feds[k] = f;
681
+ return js_int32(-(int32_t)k - 1);
682
+ }
683
+
684
+ /* httpFeed(conn, bytes | null) → whether the parser took them; null: the input ended */
685
+ JSValue js_host_http_feed(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
686
+ (void)callee, (void)this_val, (void)new_target;
687
+ /* a fed connection's bytes; or a socket's that JS read before the parser took the socket */
688
+ Conn *c = argc > 0 && js_is_int32(argv[0]) ? conn_of(js_as_int32(argv[0])) : NULL;
689
+ if (!c) return JS_FALSE;
690
+ /* called from JS: the parser's callbacks run in it, so no microtask or nextTick runs between
691
+ * two of them (a body and its end come in the same turn, as in Node) */
692
+ if (argc < 2 || js_is_null(argv[1]) || js_is_undefined(argv[1])) {
693
+ js_uv_nest(1);
694
+ bool ok = parse_input(c, UV_EOF, NULL);
695
+ js_uv_nest(-1);
696
+ return js_bool(ok);
697
+ }
698
+ uint8_t *bytes;
699
+ size_t n;
700
+ if (!js_buffer_source_bytes(argv[1], &bytes, &n)) return js_throw_type_error(ctx, "httpFeed: bytes expected");
701
+ if (n == 0) return JS_TRUE;
702
+ js_uv_nest(1);
703
+ bool ok = parse_input(c, (ssize_t)n, (const char *)bytes);
704
+ js_uv_nest(-1);
705
+ return js_bool(ok);
706
+ }
707
+
708
+ /* httpFedClose(conn): its parser and writer go */
709
+ JSValue js_host_http_fed_close(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
710
+ (void)callee, (void)this_val, (void)new_target;
711
+ int id = argc > 0 && js_is_int32(argv[0]) ? js_as_int32(argv[0]) : 0;
712
+ Fed *f = fed_of(id);
713
+ if (!f) return JS_UNDEFINED;
714
+ if (f->conn) release_conn(f->conn);
715
+ feds[-(id + 1)] = NULL;
716
+ js_remove_root(ctx->rt, &f->writer);
717
+ free(f);
718
+ return JS_UNDEFINED;
719
+ }
720
+
468
721
  /* httpDate(): the Date header's value, IMF-fixdate, formatted once per second (as Node caches it) */
469
722
  JSValue js_host_http_date(JSContext *ctx, JSValue callee, JSValue this_val, uint32_t argc, const JSValue *argv, JSValue new_target) {
470
723
  (void)callee, (void)this_val, (void)argc, (void)argv, (void)new_target;
@@ -1,4 +1,4 @@
1
- /* The libuv loop the host modules share (ADR 0008's I/O backend): node:http and node:net
1
+ /* The libuv loop the host modules share: node:http and node:net
2
2
  * install it on first use, so programs without I/O don't link libuv. */
3
3
  #define _POSIX_C_SOURCE 200809L /* libuv's headers: pthread_rwlock_t, struct addrinfo */
4
4
  #ifndef _WIN32
@@ -16,6 +16,7 @@ static uv_timer_t wake; /* ends uv_run at the next timer's deadline; unref'
16
16
  static JSContext *loop_ctx; /* the realm callbacks run in */
17
17
  static int failed; /* exit status after an uncaught error in a callback */
18
18
  static void (*flush_hook)(void);
19
+ static int call_depth; /* js_uv_calls under way: one made from JS (a fed http parser's) nests */
19
20
 
20
21
  static void on_wake(uv_timer_t *t) { (void)t; }
21
22
 
@@ -63,13 +64,29 @@ JSContext *js_uv_context(void) { return loop_ctx; }
63
64
 
64
65
  void js_uv_set_flush(void (*fn)(void)) { flush_hook = fn; }
65
66
 
67
+ void js_uv_nest(int delta) { call_depth += delta; }
68
+
69
+ bool js_uv_drain(void) {
70
+ if (failed) return false;
71
+ if (call_depth > 0) return true;
72
+ if (js_run_microtasks(loop_ctx) < 0) {
73
+ failed = loop_ctx->rt->failure;
74
+ uv_stop(loop);
75
+ return false;
76
+ }
77
+ flush();
78
+ return true;
79
+ }
80
+
66
81
  bool js_uv_call(JSValue fn, uint32_t argc, JSValue *argv, JSValue *result) {
67
82
  if (failed) return false;
68
83
  JSContext *ctx = loop_ctx;
69
- /* under no async context (ADR 0020): the prelude binds a callback to the one it was given in */
84
+ /* under no async context: the prelude binds a callback to the one it was given in */
70
85
  JSValue saved = js_async_context(ctx);
71
86
  js_set_async_context(ctx, JS_UNDEFINED);
87
+ call_depth++;
72
88
  JSValue r = js_call(ctx, fn, JS_UNDEFINED, argc, argv);
89
+ call_depth--;
73
90
  js_set_async_context(ctx, saved);
74
91
  if (js_is_exception(r)) {
75
92
  failed = js_report_uncaught(ctx);
@@ -79,6 +96,12 @@ bool js_uv_call(JSValue fn, uint32_t argc, JSValue *argv, JSValue *result) {
79
96
  }
80
97
  r = JS_UNDEFINED; /* handled ('uncaughtException'): the program goes on */
81
98
  }
99
+ /* microtasks run, and output goes out, when the outermost callback returns, as in Node: a call
100
+ * made while JS is running (a parser fed from a 'data' listener) leaves them to it */
101
+ if (call_depth > 0) {
102
+ if (result) *result = r;
103
+ return true;
104
+ }
82
105
  if (js_run_microtasks(ctx) < 0) {
83
106
  failed = ctx->rt->failure;
84
107
  uv_stop(loop);