@volter/tabnode 0.2.14-volter.88

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 (429) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +78 -0
  3. package/THIRD-PARTY-NOTICES.md +12 -0
  4. package/dist/__sw__.js +526 -0
  5. package/dist/assets/runtime-worker-4MKaHFVb.js +75221 -0
  6. package/dist/assets/runtime-worker-4MKaHFVb.js.map +1 -0
  7. package/dist/code-transforms.d.ts +21 -0
  8. package/dist/code-transforms.d.ts.map +1 -0
  9. package/dist/config/cdn.d.ts +12 -0
  10. package/dist/config/cdn.d.ts.map +1 -0
  11. package/dist/create-runtime.d.ts +22 -0
  12. package/dist/create-runtime.d.ts.map +1 -0
  13. package/dist/host-globals.d.ts +62 -0
  14. package/dist/host-globals.d.ts.map +1 -0
  15. package/dist/index.cjs +36021 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.ts +127 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.mjs +36020 -0
  20. package/dist/index.mjs.map +1 -0
  21. package/dist/node-internals.d.ts +68 -0
  22. package/dist/node-internals.d.ts.map +1 -0
  23. package/dist/node-lib/binding/blob.d.ts +12 -0
  24. package/dist/node-lib/binding/blob.d.ts.map +1 -0
  25. package/dist/node-lib/binding/buffer.d.ts +144 -0
  26. package/dist/node-lib/binding/buffer.d.ts.map +1 -0
  27. package/dist/node-lib/binding/cares_wrap.d.ts +14 -0
  28. package/dist/node-lib/binding/cares_wrap.d.ts.map +1 -0
  29. package/dist/node-lib/binding/fds.d.ts +30 -0
  30. package/dist/node-lib/binding/fds.d.ts.map +1 -0
  31. package/dist/node-lib/binding/fs.d.ts +157 -0
  32. package/dist/node-lib/binding/fs.d.ts.map +1 -0
  33. package/dist/node-lib/binding/handles.d.ts +81 -0
  34. package/dist/node-lib/binding/handles.d.ts.map +1 -0
  35. package/dist/node-lib/binding/http_parser.d.ts +122 -0
  36. package/dist/node-lib/binding/http_parser.d.ts.map +1 -0
  37. package/dist/node-lib/binding/index.d.ts +3 -0
  38. package/dist/node-lib/binding/index.d.ts.map +1 -0
  39. package/dist/node-lib/binding/llhttp-wasm.d.ts +22 -0
  40. package/dist/node-lib/binding/llhttp-wasm.d.ts.map +1 -0
  41. package/dist/node-lib/binding/misc.d.ts +123 -0
  42. package/dist/node-lib/binding/misc.d.ts.map +1 -0
  43. package/dist/node-lib/binding/pipe_wrap.d.ts +84 -0
  44. package/dist/node-lib/binding/pipe_wrap.d.ts.map +1 -0
  45. package/dist/node-lib/binding/process_wrap.d.ts +173 -0
  46. package/dist/node-lib/binding/process_wrap.d.ts.map +1 -0
  47. package/dist/node-lib/binding/spawn_sync.d.ts +30 -0
  48. package/dist/node-lib/binding/spawn_sync.d.ts.map +1 -0
  49. package/dist/node-lib/binding/stream_wrap.d.ts +191 -0
  50. package/dist/node-lib/binding/stream_wrap.d.ts.map +1 -0
  51. package/dist/node-lib/binding/stubs.d.ts +23 -0
  52. package/dist/node-lib/binding/stubs.d.ts.map +1 -0
  53. package/dist/node-lib/binding/tcp_wrap.d.ts +98 -0
  54. package/dist/node-lib/binding/tcp_wrap.d.ts.map +1 -0
  55. package/dist/node-lib/binding/tty_wrap.d.ts +36 -0
  56. package/dist/node-lib/binding/tty_wrap.d.ts.map +1 -0
  57. package/dist/node-lib/binding/util.d.ts +126 -0
  58. package/dist/node-lib/binding/util.d.ts.map +1 -0
  59. package/dist/node-lib/binding/uv.d.ts +32 -0
  60. package/dist/node-lib/binding/uv.d.ts.map +1 -0
  61. package/dist/node-lib/binding/zlib-pako.d.ts +22 -0
  62. package/dist/node-lib/binding/zlib-pako.d.ts.map +1 -0
  63. package/dist/node-lib/binding/zlib.d.ts +38 -0
  64. package/dist/node-lib/binding/zlib.d.ts.map +1 -0
  65. package/dist/node-lib/buffer-module.d.ts +51 -0
  66. package/dist/node-lib/buffer-module.d.ts.map +1 -0
  67. package/dist/node-lib/child-process-module.d.ts +26 -0
  68. package/dist/node-lib/child-process-module.d.ts.map +1 -0
  69. package/dist/node-lib/events-module.d.ts +58 -0
  70. package/dist/node-lib/events-module.d.ts.map +1 -0
  71. package/dist/node-lib/fs-module.d.ts +5 -0
  72. package/dist/node-lib/fs-module.d.ts.map +1 -0
  73. package/dist/node-lib/http-bridge.d.ts +43 -0
  74. package/dist/node-lib/http-bridge.d.ts.map +1 -0
  75. package/dist/node-lib/http-module.d.ts +35 -0
  76. package/dist/node-lib/http-module.d.ts.map +1 -0
  77. package/dist/node-lib/internals/addresses.d.ts +40 -0
  78. package/dist/node-lib/internals/addresses.d.ts.map +1 -0
  79. package/dist/node-lib/internals/buffer-and-streams.d.ts +96 -0
  80. package/dist/node-lib/internals/buffer-and-streams.d.ts.map +1 -0
  81. package/dist/node-lib/internals/child-process.d.ts +27 -0
  82. package/dist/node-lib/internals/child-process.d.ts.map +1 -0
  83. package/dist/node-lib/internals/events-util.d.ts +83 -0
  84. package/dist/node-lib/internals/events-util.d.ts.map +1 -0
  85. package/dist/node-lib/internals/index.d.ts +2 -0
  86. package/dist/node-lib/internals/index.d.ts.map +1 -0
  87. package/dist/node-lib/internals/modules.d.ts +67 -0
  88. package/dist/node-lib/internals/modules.d.ts.map +1 -0
  89. package/dist/node-lib/internals/readline-access.d.ts +2 -0
  90. package/dist/node-lib/internals/readline-access.d.ts.map +1 -0
  91. package/dist/node-lib/internals/runtime.d.ts +150 -0
  92. package/dist/node-lib/internals/runtime.d.ts.map +1 -0
  93. package/dist/node-lib/internals/util.d.ts +33 -0
  94. package/dist/node-lib/internals/util.d.ts.map +1 -0
  95. package/dist/node-lib/lazy.d.ts +31 -0
  96. package/dist/node-lib/lazy.d.ts.map +1 -0
  97. package/dist/node-lib/load.d.ts +27 -0
  98. package/dist/node-lib/load.d.ts.map +1 -0
  99. package/dist/node-lib/module-hooks.d.ts +89 -0
  100. package/dist/node-lib/module-hooks.d.ts.map +1 -0
  101. package/dist/node-lib/net-module.d.ts +181 -0
  102. package/dist/node-lib/net-module.d.ts.map +1 -0
  103. package/dist/node-lib/node-versions.d.ts +27 -0
  104. package/dist/node-lib/node-versions.d.ts.map +1 -0
  105. package/dist/node-lib/public-modules.d.ts +2 -0
  106. package/dist/node-lib/public-modules.d.ts.map +1 -0
  107. package/dist/node-lib/require-hook.d.ts +15 -0
  108. package/dist/node-lib/require-hook.d.ts.map +1 -0
  109. package/dist/node-lib/small-modules.d.ts +16 -0
  110. package/dist/node-lib/small-modules.d.ts.map +1 -0
  111. package/dist/node-lib/sources.d.ts +4 -0
  112. package/dist/node-lib/sources.d.ts.map +1 -0
  113. package/dist/node-lib/stream-module.d.ts +77 -0
  114. package/dist/node-lib/stream-module.d.ts.map +1 -0
  115. package/dist/node-lib/timers.d.ts +19 -0
  116. package/dist/node-lib/timers.d.ts.map +1 -0
  117. package/dist/node-lib/util-module.d.ts +76 -0
  118. package/dist/node-lib/util-module.d.ts.map +1 -0
  119. package/dist/node-resolution.d.ts +50 -0
  120. package/dist/node-resolution.d.ts.map +1 -0
  121. package/dist/node-resolver.d.ts +7 -0
  122. package/dist/node-resolver.d.ts.map +1 -0
  123. package/dist/npm/index.d.ts +73 -0
  124. package/dist/npm/index.d.ts.map +1 -0
  125. package/dist/npm/registry.d.ts +111 -0
  126. package/dist/npm/registry.d.ts.map +1 -0
  127. package/dist/npm/resolver.d.ts +79 -0
  128. package/dist/npm/resolver.d.ts.map +1 -0
  129. package/dist/npm/tarball.d.ts +28 -0
  130. package/dist/npm/tarball.d.ts.map +1 -0
  131. package/dist/process-tokens.d.ts +77 -0
  132. package/dist/process-tokens.d.ts.map +1 -0
  133. package/dist/punycode-source.d.ts +3 -0
  134. package/dist/punycode-source.d.ts.map +1 -0
  135. package/dist/runtime-interface.d.ts +74 -0
  136. package/dist/runtime-interface.d.ts.map +1 -0
  137. package/dist/runtime.d.ts +144 -0
  138. package/dist/runtime.d.ts.map +1 -0
  139. package/dist/server-bridge.d.ts +147 -0
  140. package/dist/server-bridge.d.ts.map +1 -0
  141. package/dist/shims/async_hooks.d.ts +50 -0
  142. package/dist/shims/async_hooks.d.ts.map +1 -0
  143. package/dist/shims/child_process.d.ts +104 -0
  144. package/dist/shims/child_process.d.ts.map +1 -0
  145. package/dist/shims/cluster.d.ts +52 -0
  146. package/dist/shims/cluster.d.ts.map +1 -0
  147. package/dist/shims/command-line.d.ts +43 -0
  148. package/dist/shims/command-line.d.ts.map +1 -0
  149. package/dist/shims/constants.d.ts +222 -0
  150. package/dist/shims/constants.d.ts.map +1 -0
  151. package/dist/shims/crypto-constants.d.ts +12 -0
  152. package/dist/shims/crypto-constants.d.ts.map +1 -0
  153. package/dist/shims/crypto.d.ts +144 -0
  154. package/dist/shims/crypto.d.ts.map +1 -0
  155. package/dist/shims/dgram.d.ts +34 -0
  156. package/dist/shims/dgram.d.ts.map +1 -0
  157. package/dist/shims/dns.d.ts +91 -0
  158. package/dist/shims/dns.d.ts.map +1 -0
  159. package/dist/shims/domain.d.ts +25 -0
  160. package/dist/shims/domain.d.ts.map +1 -0
  161. package/dist/shims/esbuild.d.ts +205 -0
  162. package/dist/shims/esbuild.d.ts.map +1 -0
  163. package/dist/shims/fs.d.ts +25 -0
  164. package/dist/shims/fs.d.ts.map +1 -0
  165. package/dist/shims/http2.d.ts +81 -0
  166. package/dist/shims/http2.d.ts.map +1 -0
  167. package/dist/shims/inspector.d.ts +25 -0
  168. package/dist/shims/inspector.d.ts.map +1 -0
  169. package/dist/shims/module.d.ts +22 -0
  170. package/dist/shims/module.d.ts.map +1 -0
  171. package/dist/shims/os.d.ts +159 -0
  172. package/dist/shims/os.d.ts.map +1 -0
  173. package/dist/shims/path.d.ts +52 -0
  174. package/dist/shims/path.d.ts.map +1 -0
  175. package/dist/shims/perf_hooks.d.ts +50 -0
  176. package/dist/shims/perf_hooks.d.ts.map +1 -0
  177. package/dist/shims/process.d.ts +226 -0
  178. package/dist/shims/process.d.ts.map +1 -0
  179. package/dist/shims/rollup.d.ts +71 -0
  180. package/dist/shims/rollup.d.ts.map +1 -0
  181. package/dist/shims/string_decoder.d.ts +41 -0
  182. package/dist/shims/string_decoder.d.ts.map +1 -0
  183. package/dist/shims/sync-child.d.ts +64 -0
  184. package/dist/shims/sync-child.d.ts.map +1 -0
  185. package/dist/shims/tls.d.ts +53 -0
  186. package/dist/shims/tls.d.ts.map +1 -0
  187. package/dist/shims/url.d.ts +84 -0
  188. package/dist/shims/url.d.ts.map +1 -0
  189. package/dist/shims/v8.d.ts +73 -0
  190. package/dist/shims/v8.d.ts.map +1 -0
  191. package/dist/shims/vfs-adapter.d.ts +126 -0
  192. package/dist/shims/vfs-adapter.d.ts.map +1 -0
  193. package/dist/shims/vm.d.ts +52 -0
  194. package/dist/shims/vm.d.ts.map +1 -0
  195. package/dist/shims/wasi.d.ts +78 -0
  196. package/dist/shims/wasi.d.ts.map +1 -0
  197. package/dist/shims/worker_threads.d.ts +66 -0
  198. package/dist/shims/worker_threads.d.ts.map +1 -0
  199. package/dist/shims/zlib-constants.d.ts +66 -0
  200. package/dist/shims/zlib-constants.d.ts.map +1 -0
  201. package/dist/shims/zlib.d.ts +102 -0
  202. package/dist/shims/zlib.d.ts.map +1 -0
  203. package/dist/transform.d.ts +24 -0
  204. package/dist/transform.d.ts.map +1 -0
  205. package/dist/types/package-json.d.ts +18 -0
  206. package/dist/types/package-json.d.ts.map +1 -0
  207. package/dist/utils/binary-encoding.d.ts +13 -0
  208. package/dist/utils/binary-encoding.d.ts.map +1 -0
  209. package/dist/utils/glob.d.ts +19 -0
  210. package/dist/utils/glob.d.ts.map +1 -0
  211. package/dist/utils/hash.d.ts +6 -0
  212. package/dist/utils/hash.d.ts.map +1 -0
  213. package/dist/virtual-fs.d.ts +259 -0
  214. package/dist/virtual-fs.d.ts.map +1 -0
  215. package/dist/vite-plugin.cjs +50 -0
  216. package/dist/vite-plugin.cjs.map +1 -0
  217. package/dist/vite-plugin.d.ts +36 -0
  218. package/dist/vite-plugin.d.ts.map +1 -0
  219. package/dist/vite-plugin.mjs +31 -0
  220. package/dist/vite-plugin.mjs.map +1 -0
  221. package/dist/worker/runtime-worker.d.ts +8 -0
  222. package/dist/worker/runtime-worker.d.ts.map +1 -0
  223. package/dist/worker-runtime.d.ts +50 -0
  224. package/dist/worker-runtime.d.ts.map +1 -0
  225. package/package.json +88 -0
  226. package/src/code-transforms.ts +560 -0
  227. package/src/config/cdn.ts +13 -0
  228. package/src/create-runtime.ts +89 -0
  229. package/src/host-globals.ts +121 -0
  230. package/src/index.ts +235 -0
  231. package/src/node-internals.ts +283 -0
  232. package/src/node-lib/LICENSE +47 -0
  233. package/src/node-lib/_http_agent.js +547 -0
  234. package/src/node-lib/_http_client.js +996 -0
  235. package/src/node-lib/_http_common.js +269 -0
  236. package/src/node-lib/_http_incoming.js +453 -0
  237. package/src/node-lib/_http_outgoing.js +1262 -0
  238. package/src/node-lib/_http_server.js +1230 -0
  239. package/src/node-lib/assert/strict.js +3 -0
  240. package/src/node-lib/assert.js +844 -0
  241. package/src/node-lib/binding/blob.ts +35 -0
  242. package/src/node-lib/binding/buffer.ts +465 -0
  243. package/src/node-lib/binding/cares_wrap.ts +57 -0
  244. package/src/node-lib/binding/fds.ts +80 -0
  245. package/src/node-lib/binding/fs.ts +857 -0
  246. package/src/node-lib/binding/handles.ts +187 -0
  247. package/src/node-lib/binding/http_parser.ts +536 -0
  248. package/src/node-lib/binding/index.ts +77 -0
  249. package/src/node-lib/binding/llhttp-wasm.ts +670 -0
  250. package/src/node-lib/binding/misc.ts +252 -0
  251. package/src/node-lib/binding/pipe_wrap.ts +166 -0
  252. package/src/node-lib/binding/process_wrap.ts +371 -0
  253. package/src/node-lib/binding/spawn_sync.ts +141 -0
  254. package/src/node-lib/binding/stream_wrap.ts +413 -0
  255. package/src/node-lib/binding/stubs.ts +19 -0
  256. package/src/node-lib/binding/tcp_wrap.ts +254 -0
  257. package/src/node-lib/binding/tty_wrap.ts +56 -0
  258. package/src/node-lib/binding/util.ts +274 -0
  259. package/src/node-lib/binding/uv.ts +102 -0
  260. package/src/node-lib/binding/zlib-pako.ts +50 -0
  261. package/src/node-lib/binding/zlib.ts +259 -0
  262. package/src/node-lib/buffer-module.ts +70 -0
  263. package/src/node-lib/buffer.js +1373 -0
  264. package/src/node-lib/child-process-module.ts +58 -0
  265. package/src/node-lib/child_process.js +1046 -0
  266. package/src/node-lib/constants.js +41 -0
  267. package/src/node-lib/diagnostics_channel.js +438 -0
  268. package/src/node-lib/events-module.ts +80 -0
  269. package/src/node-lib/events.js +1223 -0
  270. package/src/node-lib/fs-module.ts +43 -0
  271. package/src/node-lib/fs.js +3377 -0
  272. package/src/node-lib/http-bridge.ts +299 -0
  273. package/src/node-lib/http-module.ts +53 -0
  274. package/src/node-lib/http.js +198 -0
  275. package/src/node-lib/https.js +429 -0
  276. package/src/node-lib/internal/assert/assertion_error.js +417 -0
  277. package/src/node-lib/internal/assert/calltracker.js +153 -0
  278. package/src/node-lib/internal/assert/myers_diff.js +177 -0
  279. package/src/node-lib/internal/assert/utils.js +278 -0
  280. package/src/node-lib/internal/buffer.js +1120 -0
  281. package/src/node-lib/internal/child_process/serialization.js +169 -0
  282. package/src/node-lib/internal/child_process.js +1135 -0
  283. package/src/node-lib/internal/constants.js +56 -0
  284. package/src/node-lib/internal/deps/minimatch/index.js +1628 -0
  285. package/src/node-lib/internal/errors.js +1912 -0
  286. package/src/node-lib/internal/events/abort_listener.js +54 -0
  287. package/src/node-lib/internal/events/symbols.js +11 -0
  288. package/src/node-lib/internal/fixed_queue.js +119 -0
  289. package/src/node-lib/internal/freelist.js +30 -0
  290. package/src/node-lib/internal/fs/cp/cp-sync.js +242 -0
  291. package/src/node-lib/internal/fs/cp/cp.js +382 -0
  292. package/src/node-lib/internal/fs/dir.js +369 -0
  293. package/src/node-lib/internal/fs/glob.js +763 -0
  294. package/src/node-lib/internal/fs/promises.js +1312 -0
  295. package/src/node-lib/internal/fs/read/context.js +129 -0
  296. package/src/node-lib/internal/fs/recursive_watch.js +275 -0
  297. package/src/node-lib/internal/fs/rimraf.js +311 -0
  298. package/src/node-lib/internal/fs/streams.js +571 -0
  299. package/src/node-lib/internal/fs/sync_write_stream.js +49 -0
  300. package/src/node-lib/internal/fs/utils.js +987 -0
  301. package/src/node-lib/internal/fs/watchers.js +418 -0
  302. package/src/node-lib/internal/http.js +62 -0
  303. package/src/node-lib/internal/mime.js +389 -0
  304. package/src/node-lib/internal/modules/customization_hooks.js +406 -0
  305. package/src/node-lib/internal/net.js +95 -0
  306. package/src/node-lib/internal/querystring.js +119 -0
  307. package/src/node-lib/internal/readline/callbacks.js +132 -0
  308. package/src/node-lib/internal/readline/emitKeypressEvents.js +99 -0
  309. package/src/node-lib/internal/readline/interface.js +1418 -0
  310. package/src/node-lib/internal/readline/promises.js +144 -0
  311. package/src/node-lib/internal/readline/utils.js +405 -0
  312. package/src/node-lib/internal/socket_list.js +108 -0
  313. package/src/node-lib/internal/stream_base_commons.js +280 -0
  314. package/src/node-lib/internal/streams/add-abort-signal.js +60 -0
  315. package/src/node-lib/internal/streams/compose.js +257 -0
  316. package/src/node-lib/internal/streams/destroy.js +361 -0
  317. package/src/node-lib/internal/streams/duplex.js +203 -0
  318. package/src/node-lib/internal/streams/duplexify.js +379 -0
  319. package/src/node-lib/internal/streams/duplexpair.js +62 -0
  320. package/src/node-lib/internal/streams/end-of-stream.js +331 -0
  321. package/src/node-lib/internal/streams/from.js +208 -0
  322. package/src/node-lib/internal/streams/lazy_transform.js +57 -0
  323. package/src/node-lib/internal/streams/legacy.js +125 -0
  324. package/src/node-lib/internal/streams/operators.js +436 -0
  325. package/src/node-lib/internal/streams/passthrough.js +47 -0
  326. package/src/node-lib/internal/streams/pipeline.js +465 -0
  327. package/src/node-lib/internal/streams/readable.js +1762 -0
  328. package/src/node-lib/internal/streams/state.js +51 -0
  329. package/src/node-lib/internal/streams/transform.js +204 -0
  330. package/src/node-lib/internal/streams/utils.js +363 -0
  331. package/src/node-lib/internal/streams/writable.js +1163 -0
  332. package/src/node-lib/internal/tty.js +260 -0
  333. package/src/node-lib/internal/util/colors.js +40 -0
  334. package/src/node-lib/internal/util/comparisons.js +1028 -0
  335. package/src/node-lib/internal/util/debuglog.js +524 -0
  336. package/src/node-lib/internal/util/inspect.js +2535 -0
  337. package/src/node-lib/internal/util/parse_args/parse_args.js +412 -0
  338. package/src/node-lib/internal/util/parse_args/utils.js +197 -0
  339. package/src/node-lib/internal/util.js +1003 -0
  340. package/src/node-lib/internal/validators.js +654 -0
  341. package/src/node-lib/internals/addresses.ts +159 -0
  342. package/src/node-lib/internals/buffer-and-streams.ts +224 -0
  343. package/src/node-lib/internals/child-process.ts +64 -0
  344. package/src/node-lib/internals/events-util.ts +105 -0
  345. package/src/node-lib/internals/index.ts +66 -0
  346. package/src/node-lib/internals/modules.ts +117 -0
  347. package/src/node-lib/internals/readline-access.ts +16 -0
  348. package/src/node-lib/internals/runtime.ts +277 -0
  349. package/src/node-lib/internals/util.ts +98 -0
  350. package/src/node-lib/lazy.ts +158 -0
  351. package/src/node-lib/load.ts +390 -0
  352. package/src/node-lib/module-hooks.ts +281 -0
  353. package/src/node-lib/net-module.ts +248 -0
  354. package/src/node-lib/net.js +2540 -0
  355. package/src/node-lib/node-versions.ts +34 -0
  356. package/src/node-lib/os.js +356 -0
  357. package/src/node-lib/path.js +1694 -0
  358. package/src/node-lib/primordials.js +743 -0
  359. package/src/node-lib/public-modules.ts +109 -0
  360. package/src/node-lib/punycode.js +455 -0
  361. package/src/node-lib/querystring.js +484 -0
  362. package/src/node-lib/readline/promises.js +73 -0
  363. package/src/node-lib/readline.js +523 -0
  364. package/src/node-lib/require-hook.ts +27 -0
  365. package/src/node-lib/small-modules.ts +35 -0
  366. package/src/node-lib/sources.ts +200 -0
  367. package/src/node-lib/stream/promises.js +44 -0
  368. package/src/node-lib/stream-module.ts +101 -0
  369. package/src/node-lib/stream.js +152 -0
  370. package/src/node-lib/timers.ts +33 -0
  371. package/src/node-lib/tty.js +168 -0
  372. package/src/node-lib/util-module.ts +104 -0
  373. package/src/node-lib/util.js +689 -0
  374. package/src/node-lib/wasi.js +179 -0
  375. package/src/node-lib/zlib.js +1036 -0
  376. package/src/node-resolution.ts +241 -0
  377. package/src/node-resolver.ts +33 -0
  378. package/src/npm/index.ts +425 -0
  379. package/src/npm/registry.ts +235 -0
  380. package/src/npm/resolver.ts +589 -0
  381. package/src/npm/tarball.ts +246 -0
  382. package/src/process-tokens.ts +156 -0
  383. package/src/punycode-source.ts +6 -0
  384. package/src/runtime-interface.ts +85 -0
  385. package/src/runtime.ts +3073 -0
  386. package/src/server-bridge.ts +971 -0
  387. package/src/shims/async_hooks.ts +181 -0
  388. package/src/shims/child_process.ts +1591 -0
  389. package/src/shims/cluster.ts +79 -0
  390. package/src/shims/command-line.ts +79 -0
  391. package/src/shims/constants.ts +68 -0
  392. package/src/shims/crypto-constants.ts +11 -0
  393. package/src/shims/crypto.ts +1061 -0
  394. package/src/shims/dgram.ts +47 -0
  395. package/src/shims/dns.ts +185 -0
  396. package/src/shims/domain.ts +58 -0
  397. package/src/shims/esbuild.ts +1638 -0
  398. package/src/shims/fs.ts +82 -0
  399. package/src/shims/http2.ts +96 -0
  400. package/src/shims/inspector.ts +30 -0
  401. package/src/shims/module.ts +86 -0
  402. package/src/shims/os.ts +195 -0
  403. package/src/shims/path.ts +246 -0
  404. package/src/shims/perf_hooks.ts +92 -0
  405. package/src/shims/process.ts +804 -0
  406. package/src/shims/rollup.ts +149 -0
  407. package/src/shims/string_decoder.ts +396 -0
  408. package/src/shims/sync-child.ts +469 -0
  409. package/src/shims/tls.ts +94 -0
  410. package/src/shims/url.ts +217 -0
  411. package/src/shims/v8.ts +113 -0
  412. package/src/shims/vfs-adapter.ts +408 -0
  413. package/src/shims/vm.ts +132 -0
  414. package/src/shims/wasi.ts +1440 -0
  415. package/src/shims/worker_threads.ts +114 -0
  416. package/src/shims/zlib-constants.ts +65 -0
  417. package/src/shims/zlib.ts +228 -0
  418. package/src/transform.ts +324 -0
  419. package/src/types/external.d.ts +55 -0
  420. package/src/types/package-json.ts +17 -0
  421. package/src/types/pako-zlib.d.ts +30 -0
  422. package/src/types/sha.js.d.ts +14 -0
  423. package/src/utils/binary-encoding.ts +43 -0
  424. package/src/utils/glob.ts +54 -0
  425. package/src/utils/hash.ts +12 -0
  426. package/src/virtual-fs.ts +1048 -0
  427. package/src/vite-plugin.ts +76 -0
  428. package/src/worker/runtime-worker.ts +128 -0
  429. package/src/worker-runtime.ts +145 -0
@@ -0,0 +1,857 @@
1
+ /**
2
+ * `internalBinding('fs')`: the filesystem calls Node's own `fs.js` makes,
3
+ * over the engine's virtual filesystem.
4
+ *
5
+ * Node's `fs` is a thin, careful layer over libuv's syscalls: it validates,
6
+ * it decides encodings, it owns `Stats`, `Dirent`, the streams and the
7
+ * promises, and then it calls one of about forty operations. The engine's
8
+ * `fs` was a hand-written 1,764-line imitation of that whole layer over the
9
+ * same virtual filesystem, and Node's own `test-fs-*` passed 52 of 246.
10
+ *
11
+ * So this file is the forty operations and nothing above them. Everything
12
+ * about paths, flags, encodings, `Stats` objects, `Dirent`, recursion,
13
+ * `mkdtemp`'s template, `rm -rf`'s retries and every error message is Node's
14
+ * own code now.
15
+ *
16
+ * WHAT A DESCRIPTOR IS HERE: the virtual filesystem is addressed by path, so
17
+ * an open file is a path, a set of flags and a position, kept in this file's
18
+ * own table. Reads and writes are whole-file reads and writes underneath,
19
+ * which is what the filesystem offers; a program that seeks and writes gets
20
+ * the bytes it asked for, at the cost of the copy.
21
+ *
22
+ * WHICH FILESYSTEM: a run's own. The engine holds one per run and swaps the
23
+ * guest's `process` when it enters one, so the filesystem is read off that
24
+ * process at call time -- the same way a vendored file gets the right
25
+ * `process` at all. An asynchronous call captures the tree here and carries
26
+ * it into the tick, because that tick can run after another guest has put
27
+ * its own process on the realm. One `fs` module, many runs, each seeing its
28
+ * own tree.
29
+ */
30
+ import { createNodeError as vfsError } from '../../virtual-fs';
31
+
32
+ /**
33
+ * An errno error, as the filesystem makes one. The tree's own maker knows the
34
+ * codes it raises; a descriptor code is this file's to raise, so it is made
35
+ * the same shape here rather than widened there.
36
+ */
37
+ function createNodeError(code: string, syscall: string, path: string): Error {
38
+ const known = ['EEXIST', 'EINVAL', 'EISDIR', 'ENOENT', 'ENOTDIR', 'ENOTEMPTY', 'ELOOP'];
39
+ if (known.includes(code)) return vfsError(code as 'ENOENT', syscall, path);
40
+ return Object.assign(new Error(`${code}: ${syscall} '${path}'`), { code, syscall, path, errno: -9 });
41
+ }
42
+
43
+ /**
44
+ * The tab's filesystem holds no links. `link` and `symlink` refuse with
45
+ * EPERM rather than copying, which pretended a second name existed.
46
+ */
47
+ function refuseLinks(syscall: string, path: string): never {
48
+ throw Object.assign(
49
+ new Error(`EPERM: the tab's filesystem holds no links, ${syscall} '${path}'`),
50
+ { code: 'EPERM', errno: -1, syscall, path },
51
+ );
52
+ }
53
+
54
+ /** Modes `chmod` has set, keyed by the path Node handed the binding. */
55
+ const pathModes = new Map<string, number>();
56
+
57
+ function treeHoldsLinks(): boolean {
58
+ return (vfs() as VirtualFS & { holdsLinks?: boolean }).holdsLinks === true;
59
+ }
60
+ import type { VirtualFS, Stats as VfsStats } from '../../virtual-fs';
61
+ import { constantsBinding } from './misc';
62
+ import { Buffer as NodeBuffer } from '../buffer-module';
63
+
64
+ /** The key the engine hangs a run's filesystem off its guest process. */
65
+ export const kRunFilesystem = Symbol.for('tabnode.run.vfs');
66
+
67
+ /**
68
+ * A tree named for the length of one call, which is how the engine's own
69
+ * parts use `fs` outside a run: the substrate builds with rolldown over a
70
+ * project's tree, and the engine hands WASI a tree of its own. Node's `fs` is
71
+ * one module and reads the run's tree off the run's process; this is the
72
+ * door for a caller that has a tree but is not a run.
73
+ */
74
+ // eslint-disable-next-line no-var, vars-on-top
75
+ var overrideTree: VirtualFS | null = null;
76
+ export function withFilesystem<T>(tree: VirtualFS, work: () => T): T {
77
+ const previous = overrideTree;
78
+ overrideTree = tree;
79
+ try { return work(); } finally { overrideTree = previous; }
80
+ }
81
+
82
+ /** The cwd named for the length of one call, captured with the tree. */
83
+ // eslint-disable-next-line no-var, vars-on-top
84
+ var overrideCwd: string | null = null;
85
+ function withCwd<T>(cwd: string, work: () => T): T {
86
+ const previous = overrideCwd;
87
+ overrideCwd = cwd;
88
+ try { return work(); } finally { overrideCwd = previous; }
89
+ }
90
+
91
+ /** The filesystem of the run whose code is executing. */
92
+ function vfs(): VirtualFS {
93
+ if (overrideTree !== null) return overrideTree;
94
+ const realm = globalThis as unknown as { process?: Record<symbol, unknown> };
95
+ const found = realm.process?.[kRunFilesystem] as VirtualFS | undefined;
96
+ if (!found) {
97
+ throw Object.assign(new Error('fs: this realm has no filesystem; the engine gives a run one when it starts'), { code: 'ENOSYS' });
98
+ }
99
+ return found;
100
+ }
101
+
102
+ /** The cwd of the run whose code is executing. */
103
+ function callingCwd(): string {
104
+ if (overrideCwd !== null) return overrideCwd;
105
+ const realm = globalThis as unknown as { process?: { cwd?: () => string } };
106
+ if (typeof realm.process?.cwd !== 'function') {
107
+ throw Object.assign(new Error('fs: this realm has no process cwd; the engine gives a run one when it starts'), { code: 'ENOSYS' });
108
+ }
109
+ return realm.process.cwd();
110
+ }
111
+
112
+ /**
113
+ * The open flags, read from the same constants table `fs.js` turned a string
114
+ * like `'w'` into. Written down here they were Linux's numbers while the
115
+ * engine's table carries another platform's, so `openSync(path, 'w')` tested
116
+ * the wrong bit and answered ENOENT for a file it was being asked to create.
117
+ * One table, one answer.
118
+ */
119
+ function flagBits(): { create: number; excl: number; truncate: number; append: number } {
120
+ const fs = (constantsBinding as unknown as { fs?: Record<string, number> }).fs ?? {};
121
+ return {
122
+ create: fs.O_CREAT ?? 0o100,
123
+ excl: fs.O_EXCL ?? 0o200,
124
+ truncate: fs.O_TRUNC ?? 0o1000,
125
+ append: fs.O_APPEND ?? 0o2000,
126
+ };
127
+ }
128
+
129
+ /** The file-type bits a `mode` carries, which is how `Stats` answers `isFile()`. */
130
+ const S_IFREG = 0o100000;
131
+ const S_IFDIR = 0o040000;
132
+ const S_IFLNK = 0o120000;
133
+
134
+ interface OpenFile {
135
+ path: string;
136
+ flags: number;
137
+ position: number;
138
+ /** A directory opened for reading, which `opendir` does. */
139
+ directory: boolean;
140
+ /** The tree this descriptor was opened on, so a later fstat/read/write
141
+ * does not re-resolve `process` after another run has taken the realm. */
142
+ tree: VirtualFS;
143
+ /**
144
+ * Bytes this descriptor holds after its first read. A kernel page cache
145
+ * does the same: `open` for reading, then every later `read` on that fd
146
+ * is answered from memory. Node's `fs.readFile` issues 512 KiB
147
+ * (`kReadFileBufferLength`) async `read`s; without this, each one was a
148
+ * whole-file trip to the store, and openvscode-server's extension host
149
+ * stalled on a cold boot of its ~20 MB `extensionHostProcess.js` before
150
+ * it could send ready.
151
+ */
152
+ cached?: Uint8Array;
153
+ }
154
+
155
+ /** Every descriptor this engine has open, and the next number to hand out. */
156
+ const openFiles = new Map<number, OpenFile>();
157
+ let nextFd = 20;
158
+
159
+ function fileFor(fd: number): OpenFile {
160
+ const file = openFiles.get(fd);
161
+ if (!file) throw createNodeError('EBADF', 'read', String(fd));
162
+ return file;
163
+ }
164
+
165
+ /** Node's stat array: eighteen numbers, with each time a second and a nanosecond. */
166
+ function statArray(stats: VfsStats, bigint: boolean, path?: string): Float64Array | BigInt64Array {
167
+ const mtime = stats.mtime instanceof Date ? stats.mtime.getTime() : Number(stats.mtimeMs ?? 0);
168
+ const atime = stats.atime instanceof Date ? stats.atime.getTime() : Number(stats.atimeMs ?? mtime);
169
+ const ctime = stats.ctime instanceof Date ? stats.ctime.getTime() : Number(stats.ctimeMs ?? mtime);
170
+ const birth = stats.birthtime instanceof Date ? stats.birthtime.getTime() : Number(stats.birthtimeMs ?? mtime);
171
+ const seconds = (ms: number): number => Math.floor(ms / 1000);
172
+ const nanos = (ms: number): number => Math.floor((ms % 1000) * 1e6);
173
+ // The tree keeps permissions but not the type bits; `Stats.isFile()` is
174
+ // `mode & S_IFMT`, so the type the tree does know is put where Node looks.
175
+ // `chmod` stores what it set; a path it has not touched keeps the tree's.
176
+ const stored = path !== undefined ? pathModes.get(path) : undefined;
177
+ const permissions = (stored !== undefined ? stored : Number(stats.mode ?? 0)) & 0o7777;
178
+ const type = stats.isDirectory?.() ? S_IFDIR : stats.isSymbolicLink?.() ? S_IFLNK : S_IFREG;
179
+ const values = [
180
+ Number(stats.dev ?? 0), type | (permissions || (type === S_IFDIR ? 0o755 : 0o644)), Number(stats.nlink ?? 1),
181
+ Number(stats.uid ?? 0), Number(stats.gid ?? 0), Number(stats.rdev ?? 0),
182
+ Number(stats.blksize ?? 4096), Number(stats.ino ?? 0), Number(stats.size ?? 0),
183
+ Number(stats.blocks ?? Math.ceil(Number(stats.size ?? 0) / 512)),
184
+ seconds(atime), nanos(atime),
185
+ seconds(mtime), nanos(mtime),
186
+ seconds(ctime), nanos(ctime),
187
+ seconds(birth), nanos(birth),
188
+ ];
189
+ return bigint ? BigInt64Array.from(values, (value) => BigInt(Math.floor(value))) : Float64Array.from(values);
190
+ }
191
+
192
+ /** A request object `fs.js` hands an asynchronous call, answered on a tick. */
193
+ interface FSReq { oncomplete?: (error: Error | null, ...rest: unknown[]) => void }
194
+
195
+ /** The next tick of whatever realm this is: a guest's process, else the microtask queue. */
196
+ function onNextTick(fn: () => void): void {
197
+ const tick = (globalThis as unknown as { process?: { nextTick?: (fn: () => void) => void } }).process?.nextTick;
198
+ if (typeof tick === 'function') tick(fn); else queueMicrotask(fn);
199
+ }
200
+
201
+ /**
202
+ * Every operation below is written once, synchronously, and this is what
203
+ * makes one asynchronous: Node passes a request object as the last argument
204
+ * when it wants a callback, and the answer arrives on the next tick rather
205
+ * than in the caller's own stack -- which is the whole of the difference a
206
+ * program can observe between `fs.readFile` and `fs.readFileSync` here.
207
+ *
208
+ * The tree and the cwd are captured on this stack, not on that tick. The
209
+ * realm's process is swapped per run, so a `vfs()` or `process.cwd()` inside
210
+ * the work would read whichever guest is executing then -- another run's
211
+ * view, or none -- and a file `ls` listed (synchronous readdir) was ENOENT
212
+ * through `open` and `readFile`, and a relative `made.txt` landed at the
213
+ * root.
214
+ *
215
+ * Node's third flavour is the one `fs.promises` uses: the last argument is
216
+ * `kUsePromises` and the call answers a promise. `internal/fs/promises.js`
217
+ * passes it to every binding call it makes and hands what comes back to
218
+ * `PromisePrototypeThen`, so a value returned there reads as `TypeError:
219
+ * Method Promise.prototype.then called on incompatible receiver [object
220
+ * Float64Array]` -- which is what `fs.promises.readFile` answered for every
221
+ * program, openvscode-server reading its own `nls.messages.json` among them,
222
+ * and it died of it after binding its port. The declared return type is the
223
+ * value flavour's; with `kUsePromises` it is a promise of that value, as
224
+ * Node's own binding is untyped C++ with the same three shapes.
225
+ */
226
+ function answer<T>(req: FSReq | undefined, work: () => T): T | undefined {
227
+ const usePromises = (req as unknown) === kUsePromises;
228
+ const useCallback = req !== undefined && typeof req === 'object' && typeof req.oncomplete === 'function';
229
+ if (!usePromises && !useCallback) return work();
230
+ const tree = vfs();
231
+ const cwd = callingCwd();
232
+ const run = (): T => withFilesystem(tree, () => withCwd(cwd, work));
233
+ if (usePromises) {
234
+ return new Promise<T>((resolve, reject) => {
235
+ onNextTick(() => { try { resolve(run()); } catch (error) { reject(error); } });
236
+ }) as unknown as T;
237
+ }
238
+ // Node's binding invokes `req.oncomplete` as a method of the request:
239
+ // `readFileAfterOpen` reads `this.context`, the `ReadFileContext`.
240
+ // Capturing the function and calling it detached left `this` undefined
241
+ // and a guest `fs.readFile(path, cb)` threw `TypeError: Cannot read
242
+ // properties of undefined (reading 'context')` at `node:fs:297:24`.
243
+ const request = req as FSReq;
244
+ const complete = request.oncomplete!;
245
+ onNextTick(() => {
246
+ let value: T;
247
+ try { value = run(); } catch (error) { complete.call(request, error as Error); return; }
248
+ complete.call(request, null, value as unknown);
249
+ });
250
+ return undefined;
251
+ }
252
+
253
+ /**
254
+ * A name the binding answers, in the encoding Node handed. `fs.rm` recursive
255
+ * (rimraf) readdir's with encoding `buffer` and `Buffer.concat`s each child
256
+ * onto the path; a string child threw `list[1]`/`list[2]` must be a Buffer,
257
+ * received `'exthost1'`.
258
+ */
259
+ function encodeFsName(name: string, encoding: unknown): string | Uint8Array {
260
+ if (encoding !== 'buffer' && encoding !== 6) {
261
+ if (typeof encoding === 'string' && encoding.length > 0 && encoding !== 'utf8' && encoding !== 'utf-8') {
262
+ return (NodeBuffer.from(name) as { toString(enc: string): string }).toString(encoding);
263
+ }
264
+ return name;
265
+ }
266
+ return NodeBuffer.from(name);
267
+ }
268
+
269
+ /** The path as Node handed it, with a Buffer decoded. A symlink's target is this, not resolved. */
270
+ function asWritten(path: unknown): string {
271
+ if (typeof path === 'string') return path;
272
+ if (path instanceof Uint8Array) return new TextDecoder().decode(path);
273
+ return String(path);
274
+ }
275
+
276
+ /**
277
+ * A path as this filesystem takes one. Node's `fs.js` hands the binding the
278
+ * path as written; libuv resolves a relative name against the process's cwd.
279
+ * The tree used to prefix `/` and land `made.txt` at `/made.txt` while
280
+ * `process.cwd()` was `/workspace`. The cwd is the calling run's, captured
281
+ * at the call's entry together with the tree.
282
+ */
283
+ function asPath(path: unknown): string {
284
+ const name = asWritten(path);
285
+ if (name.startsWith('/')) return name;
286
+ const cwd = callingCwd();
287
+ const combined = cwd.endsWith('/') ? `${cwd}${name}` : `${cwd}/${name}`;
288
+ const parts: string[] = [];
289
+ for (const part of combined.split('/')) {
290
+ if (!part || part === '.') continue;
291
+ if (part === '..') parts.pop();
292
+ else parts.push(part);
293
+ }
294
+ return `/${parts.join('/')}`;
295
+ }
296
+
297
+ /**
298
+ * The request object `fs.js` makes for every asynchronous call and hangs its
299
+ * callback off. Node's is a C++ handle the event loop owns; here it carries
300
+ * the callback and nothing else, because `answer` above is the whole of what
301
+ * makes a call asynchronous in a realm with one thread.
302
+ */
303
+ export class FSReqCallback {
304
+ oncomplete: ((error: Error | null, ...rest: unknown[]) => void) | undefined;
305
+ context: unknown;
306
+ constructor(public bigint = false) {}
307
+ }
308
+
309
+ /** The symbol `fs.promises` passes where a callback would go. */
310
+ export const kUsePromises = Symbol('kUsePromises');
311
+
312
+ /**
313
+ * `internalBinding('fs_dir')`'s handle: an open directory, read a batch at a
314
+ * time. Node's own `Dir` and `Dirent` are built on it; what a handle owes is
315
+ * a flat list of name and type, and `null` when there is nothing left.
316
+ */
317
+ export class DirHandle {
318
+ #entries: Array<[string, number]>;
319
+ #at = 0;
320
+ #encoding: unknown;
321
+ constructor(path: string, encoding?: unknown) {
322
+ const tree = vfs();
323
+ const base = path.endsWith('/') ? path.slice(0, -1) : path;
324
+ this.#encoding = encoding;
325
+ // `readdirSync` throws for a path that is not a directory, which is the
326
+ // answer `opendir` owes too.
327
+ this.#entries = tree.readdirSync(path).map((name) => {
328
+ try {
329
+ const stats = tree.lstatSync(`${base}/${name}`);
330
+ return [name, stats.isDirectory() ? 2 : stats.isSymbolicLink() ? 10 : 1] as [string, number];
331
+ } catch { return [name, 0] as [string, number]; }
332
+ });
333
+ }
334
+ read(encoding?: string, bufferSize = 32, req?: FSReq): unknown {
335
+ return answer(req, () => {
336
+ if (this.#at >= this.#entries.length) return null;
337
+ const batch: unknown[] = [];
338
+ const enc = encoding ?? this.#encoding;
339
+ for (let taken = 0; taken < bufferSize && this.#at < this.#entries.length; taken += 1) {
340
+ const [name, type] = this.#entries[this.#at++]!;
341
+ batch.push(encodeFsName(name, enc), type);
342
+ }
343
+ return batch;
344
+ });
345
+ }
346
+ close(req?: FSReq): undefined {
347
+ return answer(req, () => { this.#at = this.#entries.length; return undefined; });
348
+ }
349
+ }
350
+
351
+ export const fsDirBinding = {
352
+ opendirSync(path: unknown, encoding?: unknown): DirHandle { return new DirHandle(asPath(path), encoding); },
353
+ opendir(path: unknown, encoding: string, req?: FSReq): DirHandle | undefined {
354
+ return answer(req, () => new DirHandle(asPath(path), encoding));
355
+ },
356
+ };
357
+
358
+ /**
359
+ * `internalBinding('fs_event_wrap')`'s `FSEvent`: what `fs.watch` is. The
360
+ * engine's tree reports its own changes, and this is the shape Node's
361
+ * `FSWatcher` expects around them -- a start that takes a path and answers
362
+ * an errno, a close, and `onchange(status, event, filename)`.
363
+ */
364
+ export class FSEvent {
365
+ onchange: ((status: number, event: string, filename: string) => void) | null = null;
366
+ #watcher: { close(): void } | null = null;
367
+ initialized = false;
368
+
369
+ start(path: unknown, _persistent?: boolean, recursive?: boolean, _encoding?: string): number {
370
+ const name = asPath(path);
371
+ const tree = vfs();
372
+ try {
373
+ this.#watcher = tree.watch(name, { recursive: Boolean(recursive) }, ((event: string, filename: string | null) => {
374
+ // libuv names a change `change` and a create or a remove `rename`,
375
+ // which is what Node's `FSWatcher` turns into its own two events.
376
+ this.onchange?.(0, event === 'rename' ? 'rename' : 'change', filename ?? '');
377
+ }) as never) as unknown as { close(): void };
378
+ this.initialized = true;
379
+ return 0;
380
+ } catch (error) {
381
+ const code = (error as { code?: string }).code;
382
+ return code === 'ENOENT' ? -2 : -22;
383
+ }
384
+ }
385
+
386
+ close(): void {
387
+ this.initialized = false;
388
+ try { this.#watcher?.close(); } catch { /* a watcher already closed is closed */ }
389
+ this.#watcher = null;
390
+ }
391
+
392
+ ref(): void {}
393
+ unref(): void {}
394
+ getAsyncId(): number { return 0; }
395
+ hasRef(): boolean { return this.initialized; }
396
+ }
397
+
398
+ /**
399
+ * `StatWatcher`: what `fs.watchFile` is. It polls, as libuv's does, and the
400
+ * interval is the one the program asked for.
401
+ */
402
+ export class StatWatcher {
403
+ onchange: ((current: Float64Array | BigInt64Array, previous: Float64Array | BigInt64Array) => void) | null = null;
404
+ #timer: ReturnType<typeof setInterval> | null = null;
405
+ #previous: Float64Array | BigInt64Array | null = null;
406
+ constructor(public bigint = false) {}
407
+
408
+ start(path: unknown, interval = 5007): number {
409
+ const name = asPath(path);
410
+ const tree = vfs();
411
+ const read = (): Float64Array | BigInt64Array => {
412
+ try { return statArray(tree.statSync(name), this.bigint); }
413
+ catch { return this.bigint ? new BigInt64Array(18) : new Float64Array(18); }
414
+ };
415
+ this.#previous = read();
416
+ this.#timer = setInterval(() => {
417
+ const current = read();
418
+ const previous = this.#previous!;
419
+ let changed = false;
420
+ for (let index = 0; index < current.length; index += 1) {
421
+ if (current[index] !== previous[index]) { changed = true; break; }
422
+ }
423
+ if (changed) { this.#previous = current; this.onchange?.(current, previous); }
424
+ }, interval);
425
+ (this.#timer as unknown as { unref?: () => void }).unref?.();
426
+ return 0;
427
+ }
428
+
429
+ stop(): void { if (this.#timer !== null) { clearInterval(this.#timer); this.#timer = null; } }
430
+ close(): void { this.stop(); }
431
+ ref(): void {}
432
+ unref(): void {}
433
+ getAsyncId(): number { return 0; }
434
+ hasRef(): boolean { return this.#timer !== null; }
435
+ }
436
+
437
+ export const fsEventWrapBinding = { FSEvent };
438
+
439
+ /**
440
+ * What `fs.promises.open` is handed: a descriptor with a close of its own.
441
+ * Node's is a C++ handle whose destructor closes the file; here it is the
442
+ * same number this file's table keeps, with the same close.
443
+ */
444
+ export class FileHandle {
445
+ constructor(public fd: number) {}
446
+ close(): Promise<void> { openFiles.delete(this.fd); return Promise.resolve(); }
447
+ release(): void { openFiles.delete(this.fd); }
448
+ getAsyncId(): number { return this.fd; }
449
+ }
450
+
451
+ export const fsBinding = {
452
+ FSReqCallback,
453
+ kUsePromises,
454
+ StatWatcher,
455
+
456
+ /** `fs.promises.open`: the same open, answered as a promise with a handle. */
457
+ openFileHandle(path: unknown, flags: number, mode: number, usePromises?: unknown): Promise<FileHandle> | FileHandle {
458
+ const fd = fsBinding.open(path, flags, mode) as number;
459
+ const handle = new FileHandle(fd);
460
+ return usePromises === kUsePromises ? Promise.resolve(handle) : handle;
461
+ },
462
+ // ---- opening and closing ------------------------------------------------
463
+ open(path: unknown, flags: number, _mode: number, req?: FSReq): number | undefined {
464
+ return answer(req, () => {
465
+ const name = asPath(path);
466
+ const tree = vfs();
467
+ const bits = flagBits();
468
+ const exists = tree.existsSync(name);
469
+ if ((flags & bits.excl) !== 0 && (flags & bits.create) !== 0 && exists) throw createNodeError('EEXIST', 'open', name);
470
+ if (!exists) {
471
+ if ((flags & bits.create) === 0) throw createNodeError('ENOENT', 'open', name);
472
+ tree.writeFileSync(name, '');
473
+ } else if ((flags & bits.truncate) !== 0) {
474
+ tree.writeFileSync(name, '');
475
+ }
476
+ const fd = nextFd++;
477
+ const position = (flags & bits.append) !== 0 && exists ? (tree.readFileSync(name) as Uint8Array).length : 0;
478
+ openFiles.set(fd, { path: name, flags, position, directory: false, tree });
479
+ return fd;
480
+ });
481
+ },
482
+
483
+ close(fd: number, req?: FSReq): undefined {
484
+ return answer(req, () => { openFiles.delete(fd); return undefined; });
485
+ },
486
+
487
+ // ---- reading ------------------------------------------------------------
488
+ read(fd: number, buffer: Uint8Array, offset: number, length: number, position: number, req?: FSReq): number | undefined {
489
+ return answer(req, () => {
490
+ const file = fileFor(fd);
491
+ if (file.cached === undefined) file.cached = file.tree.readFileSync(file.path) as Uint8Array;
492
+ const bytes = file.cached;
493
+ const from = position === null || position === undefined || position < 0 ? file.position : position;
494
+ const end = Math.min(from + length, bytes.length);
495
+ const read = end > from ? end - from : 0;
496
+ if (read > 0) buffer.set(bytes.subarray(from, end), offset);
497
+ if (position === null || position === undefined || position < 0) file.position = from + read;
498
+ return read;
499
+ });
500
+ },
501
+
502
+ readBuffers(fd: number, buffers: Uint8Array[], position: number, req?: FSReq): number | undefined {
503
+ return answer(req, () => {
504
+ let total = 0;
505
+ for (const buffer of buffers) {
506
+ const read = fsBinding.read(fd, buffer, 0, buffer.length, position === undefined ? -1 : position + total) as number;
507
+ total += read;
508
+ if (read < buffer.length) break;
509
+ }
510
+ return total;
511
+ });
512
+ },
513
+
514
+ /** Node's fast path for `readFile` with an encoding it can decode itself. */
515
+ readFileUtf8(path: unknown, _flags: number): string {
516
+ return vfs().readFileSync(asPath(path), 'utf8') as string;
517
+ },
518
+
519
+ // ---- writing ------------------------------------------------------------
520
+ writeBuffer(fd: number, buffer: Uint8Array, offset: number, length: number, position: number | null, req?: FSReq): number | undefined {
521
+ return answer(req, () => {
522
+ const file = fileFor(fd);
523
+ const tree = file.tree;
524
+ const slice = buffer.subarray(offset, offset + length);
525
+ const existing = file.cached ?? (tree.existsSync(file.path) ? tree.readFileSync(file.path) as Uint8Array : new Uint8Array(0));
526
+ const at = position === null || position === undefined || position < 0 ? file.position : position;
527
+ const size = Math.max(existing.length, at + slice.length);
528
+ const next = new Uint8Array(size);
529
+ next.set(existing, 0);
530
+ next.set(slice, at);
531
+ tree.writeFileSync(file.path, next);
532
+ file.cached = next;
533
+ if (position === null || position === undefined || position < 0) file.position = at + slice.length;
534
+ return slice.length;
535
+ });
536
+ },
537
+
538
+ writeBuffers(fd: number, buffers: Uint8Array[], position: number | null, req?: FSReq): number | undefined {
539
+ return answer(req, () => {
540
+ let total = 0;
541
+ for (const buffer of buffers) {
542
+ total += fsBinding.writeBuffer(fd, buffer, 0, buffer.length,
543
+ position === null || position === undefined ? null : position + total) as number;
544
+ }
545
+ return total;
546
+ });
547
+ },
548
+
549
+ writeString(fd: number, value: string, position: number | null, encoding: string | undefined, req?: FSReq): number | undefined {
550
+ const bytes = encoding === 'utf8' || encoding === undefined || encoding === 'utf-8'
551
+ ? new TextEncoder().encode(value)
552
+ : Uint8Array.from(value, (character) => character.charCodeAt(0) & 0xff);
553
+ return fsBinding.writeBuffer(fd, bytes, 0, bytes.length, position ?? null, req);
554
+ },
555
+
556
+ writeFileUtf8(path: unknown, data: string, flags: number, _mode: number): undefined {
557
+ const tree = vfs();
558
+ const name = asPath(path);
559
+ if ((flags & flagBits().append) !== 0 && tree.existsSync(name)) {
560
+ const existing = tree.readFileSync(name, 'utf8') as string;
561
+ tree.writeFileSync(name, existing + data);
562
+ return undefined;
563
+ }
564
+ tree.writeFileSync(name, data);
565
+ return undefined;
566
+ },
567
+
568
+ // ---- metadata -----------------------------------------------------------
569
+ stat(path: unknown, bigint: boolean, req?: FSReq, throwIfNoEntry = true): Float64Array | BigInt64Array | undefined {
570
+ const work = (): Float64Array | BigInt64Array | undefined => {
571
+ const name = asPath(path);
572
+ try { return statArray(vfs().statSync(name), bigint, name); }
573
+ catch (error) {
574
+ if (throwIfNoEntry === false && (error as { code?: string }).code === 'ENOENT') return undefined;
575
+ throw error;
576
+ }
577
+ };
578
+ return answer(req, work);
579
+ },
580
+
581
+ lstat(path: unknown, bigint: boolean, req?: FSReq, throwIfNoEntry = true): Float64Array | BigInt64Array | undefined {
582
+ const work = (): Float64Array | BigInt64Array | undefined => {
583
+ const name = asPath(path);
584
+ try { return statArray(vfs().lstatSync(name), bigint, name); }
585
+ catch (error) {
586
+ if (throwIfNoEntry === false && (error as { code?: string }).code === 'ENOENT') return undefined;
587
+ throw error;
588
+ }
589
+ };
590
+ return answer(req, work);
591
+ },
592
+
593
+ fstat(fd: number, bigint: boolean, req?: FSReq): Float64Array | BigInt64Array | undefined {
594
+ return answer(req, () => {
595
+ const file = fileFor(fd);
596
+ return statArray(file.tree.statSync(file.path), bigint, file.path);
597
+ });
598
+ },
599
+
600
+ /**
601
+ * `statfs`: a tab's filesystem is the page's memory, and it has no device
602
+ * of its own. The numbers are a filesystem's shape rather than a lie about
603
+ * a disk: a block size, and a count no program can exhaust.
604
+ */
605
+ statfs(_path: unknown, bigint: boolean, req?: FSReq): Float64Array | BigInt64Array | undefined {
606
+ // The order Node's `getStatFsFromBinding` reads: type, bsize, blocks,
607
+ // bfree, bavail, files, ffree. `fs.statfs` and `fs.promises.statfs` pass
608
+ // their flavour here like every other call, and it was read as nothing.
609
+ return answer(req, () => {
610
+ const values = [0, 4096, 2 ** 31, 2 ** 31, 2 ** 31, 2 ** 20, 2 ** 20];
611
+ return bigint ? BigInt64Array.from(values.map((value) => BigInt(value))) : Float64Array.from(values);
612
+ });
613
+ },
614
+
615
+ access(path: unknown, _mode: number, req?: FSReq): undefined {
616
+ return answer(req, () => {
617
+ const name = asPath(path);
618
+ if (!vfs().existsSync(name)) throw createNodeError('ENOENT', 'access', name);
619
+ return undefined;
620
+ });
621
+ },
622
+
623
+ existsSync(path: unknown): boolean {
624
+ try { return vfs().existsSync(asPath(path)); } catch { return false; }
625
+ },
626
+
627
+ /**
628
+ * Node's `cpSync` asks this before it copies: a directory is not a file,
629
+ * and without `recursive` the copy of one is `ERR_FS_EISDIR`.
630
+ */
631
+ cpSyncCheckPaths(src: unknown, dest: unknown, dereference: boolean, recursive: boolean): undefined {
632
+ const source = asPath(src);
633
+ const tree = vfs();
634
+ const srcStat = dereference ? tree.statSync(source) : tree.lstatSync(source);
635
+ if (srcStat.isDirectory() && !recursive) {
636
+ throw Object.assign(new Error(`EISDIR: illegal operation on a directory, cp '${source}' -> '${asPath(dest)}'`), {
637
+ code: 'ERR_FS_EISDIR',
638
+ syscall: 'cp',
639
+ path: source,
640
+ dest: asPath(dest),
641
+ });
642
+ }
643
+ return undefined;
644
+ },
645
+
646
+ /** Node's C++ `cp` of a file onto an existing dest. */
647
+ cpSyncOverrideFile(src: unknown, dest: unknown, _mode: number, _preserveTimestamps: boolean): undefined {
648
+ const tree = vfs();
649
+ tree.writeFileSync(asPath(dest), tree.readFileSync(asPath(src)));
650
+ return undefined;
651
+ },
652
+
653
+ /** Node's C++ recursive directory copy, without a JS filter. */
654
+ cpSyncCopyDir(
655
+ src: unknown, dest: unknown,
656
+ force: boolean, dereference: boolean, errorOnExist: boolean,
657
+ _verbatimSymlinks: boolean, _preserveTimestamps: boolean,
658
+ ): undefined {
659
+ const tree = vfs();
660
+ const walk = (from: string, to: string): void => {
661
+ const stats = dereference ? tree.statSync(from) : tree.lstatSync(from);
662
+ if (stats.isDirectory()) {
663
+ if (!tree.existsSync(to)) tree.mkdirSync(to, { recursive: true });
664
+ else if (!tree.statSync(to).isDirectory()) {
665
+ throw Object.assign(new Error(`EEXIST: file already exists, cp '${from}' -> '${to}'`), { code: 'EEXIST', syscall: 'cp', path: from });
666
+ }
667
+ for (const name of tree.readdirSync(from)) walk(`${from}/${name}`, `${to}/${name}`);
668
+ return;
669
+ }
670
+ if (tree.existsSync(to)) {
671
+ if (errorOnExist) throw Object.assign(new Error(`EEXIST: file already exists, cp '${from}' -> '${to}'`), { code: 'EEXIST', syscall: 'cp', path: from });
672
+ if (!force) return;
673
+ }
674
+ const parent = to.slice(0, to.lastIndexOf('/')) || '/';
675
+ if (parent !== '/' && !tree.existsSync(parent)) tree.mkdirSync(parent, { recursive: true });
676
+ tree.writeFileSync(to, tree.readFileSync(from));
677
+ };
678
+ walk(asPath(src), asPath(dest));
679
+ return undefined;
680
+ },
681
+
682
+ /**
683
+ * What the module loader asks of a path before it reads it: 0 for a file,
684
+ * 1 for a directory, and a negative errno for neither.
685
+ *
686
+ * Node has called this with a receiver in front of the path and without
687
+ * one across versions; the three vendored call sites here -- `fs.js`'s
688
+ * `glob` twice and `internal/fs/promises.js`'s once -- pass the path alone,
689
+ * so the path is whichever argument is one.
690
+ */
691
+ internalModuleStat(receiver: unknown, path?: unknown): number {
692
+ const name = path === undefined ? receiver : path;
693
+ try {
694
+ const stats = vfs().statSync(asPath(name));
695
+ return stats.isDirectory() ? 1 : 0;
696
+ } catch { return -2; }
697
+ },
698
+
699
+ // ---- the tree -----------------------------------------------------------
700
+ readdir(path: unknown, encoding: string, withFileTypes: boolean, req?: FSReq): unknown {
701
+ return answer(req, () => {
702
+ const name = asPath(path);
703
+ const tree = vfs();
704
+ const names = tree.readdirSync(name).map((entry) => encodeFsName(entry, encoding));
705
+ if (!withFileTypes) return names;
706
+ // Node's own `Dirent` is built from a name and a type number, and the
707
+ // binding answers the two lists side by side. Types are matched to the
708
+ // tree's string names; the encoding only changes what the caller reads.
709
+ const types = tree.readdirSync(name).map((entry) => {
710
+ try {
711
+ const stats = tree.lstatSync(`${name.endsWith('/') ? name.slice(0, -1) : name}/${entry}`);
712
+ if (stats.isDirectory()) return 2;
713
+ if (stats.isSymbolicLink()) return 10;
714
+ return 1;
715
+ } catch { return 0; }
716
+ });
717
+ return [names, types];
718
+ });
719
+ },
720
+
721
+ mkdir(path: unknown, mode: number, recursive: boolean, req?: FSReq): string | undefined {
722
+ return answer(req, () => {
723
+ const name = asPath(path);
724
+ const tree = vfs();
725
+ const wanted = mode & 0o777;
726
+ if (tree.existsSync(name)) {
727
+ const stats = tree.statSync(name);
728
+ if (!recursive || !stats.isDirectory()) throw createNodeError('EEXIST', 'mkdir', name);
729
+ const stored = pathModes.get(name);
730
+ if (stored !== undefined && (stored & 0o777) !== wanted) throw createNodeError('EEXIST', 'mkdir', name);
731
+ pathModes.set(name, wanted);
732
+ return undefined;
733
+ }
734
+ tree.mkdirSync(name, { recursive });
735
+ pathModes.set(name, wanted);
736
+ return undefined;
737
+ });
738
+ },
739
+
740
+ rmdir(path: unknown, req?: FSReq): undefined {
741
+ return answer(req, () => { vfs().rmdirSync(asPath(path)); return undefined; });
742
+ },
743
+
744
+ unlink(path: unknown, req?: FSReq): undefined {
745
+ return answer(req, () => { vfs().unlinkSync(asPath(path)); return undefined; });
746
+ },
747
+
748
+ rename(from: unknown, to: unknown, req?: FSReq): undefined {
749
+ return answer(req, () => { vfs().renameSync(asPath(from), asPath(to)); return undefined; });
750
+ },
751
+
752
+ copyFile(from: unknown, to: unknown, mode: number, req?: FSReq): undefined {
753
+ return answer(req, () => {
754
+ const tree = vfs();
755
+ const source = asPath(from);
756
+ const target = asPath(to);
757
+ // `COPYFILE_EXCL` is the one mode a filesystem without clones can honour.
758
+ if ((mode & 1) !== 0 && tree.existsSync(target)) throw createNodeError('EEXIST', 'copyfile', target);
759
+ tree.writeFileSync(target, tree.readFileSync(source));
760
+ return undefined;
761
+ });
762
+ },
763
+
764
+ link(from: unknown, to: unknown, req?: FSReq): undefined {
765
+ return answer(req, () => {
766
+ const target = asPath(to);
767
+ if (treeHoldsLinks()) {
768
+ vfs().writeFileSync(target, vfs().readFileSync(asPath(from)));
769
+ return undefined;
770
+ }
771
+ refuseLinks('link', target);
772
+ });
773
+ },
774
+
775
+ symlink(target: unknown, path: unknown, _type: unknown, req?: FSReq): undefined {
776
+ return answer(req, () => {
777
+ const name = asPath(path);
778
+ if (treeHoldsLinks()) {
779
+ vfs().symlinkSync(asWritten(target), name);
780
+ return undefined;
781
+ }
782
+ refuseLinks('symlink', name);
783
+ });
784
+ },
785
+
786
+ readlink(path: unknown, encoding: string, req?: FSReq): string | Uint8Array | undefined {
787
+ return answer(req, () => encodeFsName(vfs().readlinkSync(asPath(path)), encoding));
788
+ },
789
+
790
+ realpath(path: unknown, encoding: string, req?: FSReq): string | Uint8Array | undefined {
791
+ return answer(req, () => encodeFsName(vfs().realpathSync(asPath(path)), encoding));
792
+ },
793
+
794
+ mkdtemp(prefix: unknown, encoding: string, req?: FSReq): string | Uint8Array | undefined {
795
+ return answer(req, () => {
796
+ const tree = vfs();
797
+ const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
798
+ for (;;) {
799
+ let suffix = '';
800
+ for (let index = 0; index < 6; index += 1) suffix += alphabet[Math.floor(Math.random() * alphabet.length)];
801
+ const name = `${asPath(prefix)}${suffix}`;
802
+ if (tree.existsSync(name)) continue;
803
+ tree.mkdirSync(name, { recursive: true });
804
+ return encodeFsName(name, encoding);
805
+ }
806
+ });
807
+ },
808
+
809
+ // ---- the calls a page's filesystem has nothing to do -------------------
810
+ // Ownership and times are a kernel's bookkeeping. Permissions `chmod` sets
811
+ // are kept here, because a program that sets a mode and stats it back must
812
+ // see what it set, and a missing path is ENOENT as Node's is.
813
+ chmod(path: unknown, mode: number, req?: FSReq): undefined {
814
+ return answer(req, () => {
815
+ const name = asPath(path);
816
+ if (!vfs().existsSync(name)) throw createNodeError('ENOENT', 'chmod', name);
817
+ pathModes.set(name, mode & 0o7777);
818
+ return undefined;
819
+ });
820
+ },
821
+ fchmod(fd: number, mode: number, req?: FSReq): undefined {
822
+ return answer(req, () => {
823
+ const file = fileFor(fd);
824
+ pathModes.set(file.path, mode & 0o7777);
825
+ return undefined;
826
+ });
827
+ },
828
+ chown(path: unknown, _uid: number, _gid: number, req?: FSReq): undefined {
829
+ return answer(req, () => {
830
+ const name = asPath(path);
831
+ if (!vfs().existsSync(name)) throw createNodeError('ENOENT', 'chown', name);
832
+ return undefined;
833
+ });
834
+ },
835
+ fchown(_fd: number, _uid: number, _gid: number, req?: FSReq): undefined { return answer(req, () => undefined); },
836
+ lchown(_path: unknown, _uid: number, _gid: number, req?: FSReq): undefined { return answer(req, () => undefined); },
837
+ utimes(_path: unknown, _atime: number, _mtime: number, req?: FSReq): undefined { return answer(req, () => undefined); },
838
+ futimes(_fd: number, _atime: number, _mtime: number, req?: FSReq): undefined { return answer(req, () => undefined); },
839
+ lutimes(_path: unknown, _atime: number, _mtime: number, req?: FSReq): undefined { return answer(req, () => undefined); },
840
+ fsync(_fd: number, req?: FSReq): undefined { return answer(req, () => undefined); },
841
+ fdatasync(_fd: number, req?: FSReq): undefined { return answer(req, () => undefined); },
842
+
843
+ ftruncate(fd: number, length: number, req?: FSReq): undefined {
844
+ return answer(req, () => {
845
+ const file = fileFor(fd);
846
+ const tree = file.tree;
847
+ const bytes = file.cached ?? (tree.readFileSync(file.path) as Uint8Array);
848
+ const next = new Uint8Array(length);
849
+ next.set(bytes.subarray(0, Math.min(length, bytes.length)));
850
+ tree.writeFileSync(file.path, next);
851
+ file.cached = next;
852
+ return undefined;
853
+ });
854
+ },
855
+ };
856
+
857
+ export default fsBinding;