@ricsam/isolate 0.0.1 → 0.1.1

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 (299) hide show
  1. package/README.md +243 -34
  2. package/dist/cjs/bridge/diagnostics.cjs +58 -0
  3. package/dist/cjs/bridge/diagnostics.cjs.map +10 -0
  4. package/dist/cjs/bridge/legacy-adapters.cjs +242 -0
  5. package/dist/cjs/bridge/legacy-adapters.cjs.map +10 -0
  6. package/dist/cjs/bridge/request-context.cjs +59 -0
  7. package/dist/cjs/bridge/request-context.cjs.map +10 -0
  8. package/dist/cjs/bridge/runtime-bindings.cjs +367 -0
  9. package/dist/cjs/bridge/runtime-bindings.cjs.map +10 -0
  10. package/dist/cjs/browser/browser-runtime.cjs +157 -0
  11. package/dist/cjs/browser/browser-runtime.cjs.map +10 -0
  12. package/dist/cjs/daemon.cjs +91 -0
  13. package/dist/cjs/daemon.cjs.map +10 -0
  14. package/dist/cjs/files/index.cjs +140 -0
  15. package/dist/cjs/files/index.cjs.map +10 -0
  16. package/dist/cjs/host/create-isolate-host.cjs +235 -0
  17. package/dist/cjs/host/create-isolate-host.cjs.map +10 -0
  18. package/dist/cjs/host/index.cjs +47 -0
  19. package/dist/cjs/host/index.cjs.map +10 -0
  20. package/dist/cjs/index.cjs +55 -0
  21. package/dist/cjs/index.cjs.map +10 -0
  22. package/dist/cjs/internal/client/connection.cjs +1919 -0
  23. package/dist/cjs/internal/client/connection.cjs.map +10 -0
  24. package/dist/cjs/internal/client/index.cjs +48 -0
  25. package/dist/cjs/internal/client/index.cjs.map +10 -0
  26. package/dist/cjs/internal/client/types.cjs +30 -0
  27. package/dist/cjs/internal/client/types.cjs.map +9 -0
  28. package/dist/cjs/internal/console/index.cjs +506 -0
  29. package/dist/cjs/internal/console/index.cjs.map +10 -0
  30. package/dist/cjs/internal/console/utils.cjs +70 -0
  31. package/dist/cjs/internal/console/utils.cjs.map +10 -0
  32. package/dist/cjs/internal/core/index.cjs +2745 -0
  33. package/dist/cjs/internal/core/index.cjs.map +10 -0
  34. package/dist/cjs/internal/crypto/index.cjs +470 -0
  35. package/dist/cjs/internal/crypto/index.cjs.map +10 -0
  36. package/dist/cjs/internal/daemon/callback-fs-handler.cjs +355 -0
  37. package/dist/cjs/internal/daemon/callback-fs-handler.cjs.map +10 -0
  38. package/dist/cjs/internal/daemon/connection.cjs +1952 -0
  39. package/dist/cjs/internal/daemon/connection.cjs.map +10 -0
  40. package/dist/cjs/internal/daemon/daemon.cjs +98 -0
  41. package/dist/cjs/internal/daemon/daemon.cjs.map +10 -0
  42. package/dist/cjs/internal/daemon/index.cjs +145 -0
  43. package/dist/cjs/internal/daemon/index.cjs.map +10 -0
  44. package/dist/cjs/internal/daemon/runtime-pool.cjs +106 -0
  45. package/dist/cjs/internal/daemon/runtime-pool.cjs.map +10 -0
  46. package/dist/cjs/internal/daemon/types.cjs +30 -0
  47. package/dist/cjs/internal/daemon/types.cjs.map +9 -0
  48. package/dist/cjs/internal/encoding/index.cjs +419 -0
  49. package/dist/cjs/internal/encoding/index.cjs.map +10 -0
  50. package/dist/cjs/internal/fetch/consistency/origins.cjs +598 -0
  51. package/dist/cjs/internal/fetch/consistency/origins.cjs.map +10 -0
  52. package/dist/cjs/internal/fetch/index.cjs +2640 -0
  53. package/dist/cjs/internal/fetch/index.cjs.map +10 -0
  54. package/dist/cjs/internal/fetch/stream-state.cjs +256 -0
  55. package/dist/cjs/internal/fetch/stream-state.cjs.map +10 -0
  56. package/dist/cjs/internal/fs/index.cjs +847 -0
  57. package/dist/cjs/internal/fs/index.cjs.map +10 -0
  58. package/dist/cjs/internal/fs/node-adapter.cjs +254 -0
  59. package/dist/cjs/internal/fs/node-adapter.cjs.map +10 -0
  60. package/dist/cjs/internal/module-loader/bundle.cjs +482 -0
  61. package/dist/cjs/internal/module-loader/bundle.cjs.map +10 -0
  62. package/dist/cjs/internal/module-loader/index.cjs +240 -0
  63. package/dist/cjs/internal/module-loader/index.cjs.map +10 -0
  64. package/dist/cjs/internal/module-loader/mappings.cjs +120 -0
  65. package/dist/cjs/internal/module-loader/mappings.cjs.map +10 -0
  66. package/dist/cjs/internal/module-loader/resolve.cjs +177 -0
  67. package/dist/cjs/internal/module-loader/resolve.cjs.map +10 -0
  68. package/dist/cjs/internal/module-loader/strip-types.cjs +236 -0
  69. package/dist/cjs/internal/module-loader/strip-types.cjs.map +10 -0
  70. package/dist/cjs/internal/path/index.cjs +503 -0
  71. package/dist/cjs/internal/path/index.cjs.map +10 -0
  72. package/dist/cjs/internal/playwright/client.cjs +49 -0
  73. package/dist/cjs/internal/playwright/client.cjs.map +10 -0
  74. package/dist/cjs/internal/playwright/handler.cjs +1416 -0
  75. package/dist/cjs/internal/playwright/handler.cjs.map +10 -0
  76. package/dist/cjs/internal/playwright/index.cjs +1289 -0
  77. package/dist/cjs/internal/playwright/index.cjs.map +10 -0
  78. package/dist/cjs/internal/playwright/types.cjs +47 -0
  79. package/dist/cjs/internal/playwright/types.cjs.map +10 -0
  80. package/dist/cjs/internal/protocol/codec.cjs +510 -0
  81. package/dist/cjs/internal/protocol/codec.cjs.map +10 -0
  82. package/dist/cjs/internal/protocol/framing.cjs +141 -0
  83. package/dist/cjs/internal/protocol/framing.cjs.map +10 -0
  84. package/dist/cjs/internal/protocol/index.cjs +110 -0
  85. package/dist/cjs/internal/protocol/index.cjs.map +10 -0
  86. package/dist/cjs/internal/protocol/marshalValue.cjs +518 -0
  87. package/dist/cjs/internal/protocol/marshalValue.cjs.map +10 -0
  88. package/dist/cjs/internal/protocol/serialization.cjs +109 -0
  89. package/dist/cjs/internal/protocol/serialization.cjs.map +10 -0
  90. package/dist/cjs/internal/protocol/types.cjs +181 -0
  91. package/dist/cjs/internal/protocol/types.cjs.map +10 -0
  92. package/dist/cjs/internal/runtime/index.cjs +1235 -0
  93. package/dist/cjs/internal/runtime/index.cjs.map +10 -0
  94. package/dist/cjs/internal/server/index.cjs +223 -0
  95. package/dist/cjs/internal/server/index.cjs.map +10 -0
  96. package/dist/cjs/internal/test-environment/index.cjs +1415 -0
  97. package/dist/cjs/internal/test-environment/index.cjs.map +10 -0
  98. package/dist/cjs/internal/timers/index.cjs +200 -0
  99. package/dist/cjs/internal/timers/index.cjs.map +10 -0
  100. package/dist/cjs/internal/transform/index.cjs +361 -0
  101. package/dist/cjs/internal/transform/index.cjs.map +10 -0
  102. package/dist/cjs/internal/typecheck/index.cjs +60 -0
  103. package/dist/cjs/internal/typecheck/index.cjs.map +10 -0
  104. package/dist/cjs/internal/typecheck/isolate-types.cjs +2614 -0
  105. package/dist/cjs/internal/typecheck/isolate-types.cjs.map +10 -0
  106. package/dist/cjs/internal/typecheck/typecheck.cjs +131 -0
  107. package/dist/cjs/internal/typecheck/typecheck.cjs.map +10 -0
  108. package/dist/cjs/modules/index.cjs +160 -0
  109. package/dist/cjs/modules/index.cjs.map +10 -0
  110. package/dist/cjs/package.json +5 -0
  111. package/dist/cjs/runtime/script-runtime.cjs +97 -0
  112. package/dist/cjs/runtime/script-runtime.cjs.map +10 -0
  113. package/dist/cjs/server/app-server.cjs +158 -0
  114. package/dist/cjs/server/app-server.cjs.map +10 -0
  115. package/dist/cjs/testing/integration-helpers.cjs +127 -0
  116. package/dist/cjs/testing/integration-helpers.cjs.map +10 -0
  117. package/dist/cjs/typecheck/index.cjs +96 -0
  118. package/dist/cjs/typecheck/index.cjs.map +10 -0
  119. package/dist/cjs/types.cjs +30 -0
  120. package/dist/cjs/types.cjs.map +9 -0
  121. package/dist/mjs/bridge/diagnostics.mjs +18 -0
  122. package/dist/mjs/bridge/diagnostics.mjs.map +10 -0
  123. package/dist/mjs/bridge/legacy-adapters.mjs +178 -0
  124. package/dist/mjs/bridge/legacy-adapters.mjs.map +10 -0
  125. package/dist/mjs/bridge/request-context.mjs +19 -0
  126. package/dist/mjs/bridge/request-context.mjs.map +10 -0
  127. package/dist/mjs/bridge/runtime-bindings.mjs +303 -0
  128. package/dist/mjs/bridge/runtime-bindings.mjs.map +10 -0
  129. package/dist/mjs/browser/browser-runtime.mjs +93 -0
  130. package/dist/mjs/browser/browser-runtime.mjs.map +10 -0
  131. package/dist/mjs/daemon.mjs +91 -0
  132. package/dist/mjs/daemon.mjs.map +10 -0
  133. package/dist/mjs/files/index.mjs +76 -0
  134. package/dist/mjs/files/index.mjs.map +10 -0
  135. package/dist/mjs/host/create-isolate-host.mjs +171 -0
  136. package/dist/mjs/host/create-isolate-host.mjs.map +10 -0
  137. package/dist/mjs/host/index.mjs +7 -0
  138. package/dist/mjs/host/index.mjs.map +10 -0
  139. package/dist/mjs/index.mjs +15 -0
  140. package/dist/mjs/index.mjs.map +10 -0
  141. package/dist/mjs/internal/client/connection.mjs +1872 -0
  142. package/dist/mjs/internal/client/connection.mjs.map +10 -0
  143. package/dist/mjs/internal/client/index.mjs +8 -0
  144. package/dist/mjs/internal/client/index.mjs.map +10 -0
  145. package/dist/mjs/internal/client/types.mjs +2 -0
  146. package/dist/mjs/internal/client/types.mjs.map +9 -0
  147. package/dist/mjs/internal/console/index.mjs +442 -0
  148. package/dist/mjs/internal/console/index.mjs.map +10 -0
  149. package/dist/mjs/internal/console/utils.mjs +30 -0
  150. package/dist/mjs/internal/console/utils.mjs.map +10 -0
  151. package/dist/mjs/internal/core/index.mjs +2681 -0
  152. package/dist/mjs/internal/core/index.mjs.map +10 -0
  153. package/dist/mjs/internal/crypto/index.mjs +406 -0
  154. package/dist/mjs/internal/crypto/index.mjs.map +10 -0
  155. package/dist/mjs/internal/daemon/callback-fs-handler.mjs +315 -0
  156. package/dist/mjs/internal/daemon/callback-fs-handler.mjs.map +10 -0
  157. package/dist/mjs/internal/daemon/connection.mjs +1931 -0
  158. package/dist/mjs/internal/daemon/connection.mjs.map +10 -0
  159. package/dist/mjs/internal/daemon/daemon.mjs +98 -0
  160. package/dist/mjs/internal/daemon/daemon.mjs.map +10 -0
  161. package/dist/mjs/internal/daemon/index.mjs +105 -0
  162. package/dist/mjs/internal/daemon/index.mjs.map +10 -0
  163. package/dist/mjs/internal/daemon/runtime-pool.mjs +66 -0
  164. package/dist/mjs/internal/daemon/runtime-pool.mjs.map +10 -0
  165. package/dist/mjs/internal/daemon/types.mjs +2 -0
  166. package/dist/mjs/internal/daemon/types.mjs.map +9 -0
  167. package/dist/mjs/internal/encoding/index.mjs +379 -0
  168. package/dist/mjs/internal/encoding/index.mjs.map +10 -0
  169. package/dist/mjs/internal/fetch/consistency/origins.mjs +558 -0
  170. package/dist/mjs/internal/fetch/consistency/origins.mjs.map +10 -0
  171. package/dist/mjs/internal/fetch/index.mjs +2580 -0
  172. package/dist/mjs/internal/fetch/index.mjs.map +10 -0
  173. package/dist/mjs/internal/fetch/stream-state.mjs +216 -0
  174. package/dist/mjs/internal/fetch/stream-state.mjs.map +10 -0
  175. package/dist/mjs/internal/fs/index.mjs +783 -0
  176. package/dist/mjs/internal/fs/index.mjs.map +10 -0
  177. package/dist/mjs/internal/fs/node-adapter.mjs +190 -0
  178. package/dist/mjs/internal/fs/node-adapter.mjs.map +10 -0
  179. package/dist/mjs/internal/module-loader/bundle.mjs +418 -0
  180. package/dist/mjs/internal/module-loader/bundle.mjs.map +10 -0
  181. package/dist/mjs/internal/module-loader/index.mjs +185 -0
  182. package/dist/mjs/internal/module-loader/index.mjs.map +10 -0
  183. package/dist/mjs/internal/module-loader/mappings.mjs +80 -0
  184. package/dist/mjs/internal/module-loader/mappings.mjs.map +10 -0
  185. package/dist/mjs/internal/module-loader/resolve.mjs +113 -0
  186. package/dist/mjs/internal/module-loader/resolve.mjs.map +10 -0
  187. package/dist/mjs/internal/module-loader/strip-types.mjs +172 -0
  188. package/dist/mjs/internal/module-loader/strip-types.mjs.map +10 -0
  189. package/dist/mjs/internal/path/index.mjs +463 -0
  190. package/dist/mjs/internal/path/index.mjs.map +10 -0
  191. package/dist/mjs/internal/playwright/client.mjs +13 -0
  192. package/dist/mjs/internal/playwright/client.mjs.map +10 -0
  193. package/dist/mjs/internal/playwright/handler.mjs +1378 -0
  194. package/dist/mjs/internal/playwright/handler.mjs.map +10 -0
  195. package/dist/mjs/internal/playwright/index.mjs +1234 -0
  196. package/dist/mjs/internal/playwright/index.mjs.map +10 -0
  197. package/dist/mjs/internal/playwright/types.mjs +7 -0
  198. package/dist/mjs/internal/playwright/types.mjs.map +10 -0
  199. package/dist/mjs/internal/protocol/codec.mjs +470 -0
  200. package/dist/mjs/internal/protocol/codec.mjs.map +10 -0
  201. package/dist/mjs/internal/protocol/framing.mjs +101 -0
  202. package/dist/mjs/internal/protocol/framing.mjs.map +10 -0
  203. package/dist/mjs/internal/protocol/index.mjs +98 -0
  204. package/dist/mjs/internal/protocol/index.mjs.map +10 -0
  205. package/dist/mjs/internal/protocol/marshalValue.mjs +494 -0
  206. package/dist/mjs/internal/protocol/marshalValue.mjs.map +10 -0
  207. package/dist/mjs/internal/protocol/serialization.mjs +69 -0
  208. package/dist/mjs/internal/protocol/serialization.mjs.map +10 -0
  209. package/dist/mjs/internal/protocol/types.mjs +141 -0
  210. package/dist/mjs/internal/protocol/types.mjs.map +10 -0
  211. package/dist/mjs/internal/runtime/index.mjs +1198 -0
  212. package/dist/mjs/internal/runtime/index.mjs.map +10 -0
  213. package/dist/mjs/internal/server/index.mjs +183 -0
  214. package/dist/mjs/internal/server/index.mjs.map +10 -0
  215. package/dist/mjs/internal/test-environment/index.mjs +1351 -0
  216. package/dist/mjs/internal/test-environment/index.mjs.map +10 -0
  217. package/dist/mjs/internal/timers/index.mjs +136 -0
  218. package/dist/mjs/internal/timers/index.mjs.map +10 -0
  219. package/dist/mjs/internal/transform/index.mjs +321 -0
  220. package/dist/mjs/internal/transform/index.mjs.map +10 -0
  221. package/dist/mjs/internal/typecheck/index.mjs +35 -0
  222. package/dist/mjs/internal/typecheck/index.mjs.map +10 -0
  223. package/dist/mjs/internal/typecheck/isolate-types.mjs +2574 -0
  224. package/dist/mjs/internal/typecheck/isolate-types.mjs.map +10 -0
  225. package/dist/mjs/internal/typecheck/typecheck.mjs +91 -0
  226. package/dist/mjs/internal/typecheck/typecheck.mjs.map +10 -0
  227. package/dist/mjs/modules/index.mjs +96 -0
  228. package/dist/mjs/modules/index.mjs.map +10 -0
  229. package/dist/mjs/package.json +5 -0
  230. package/dist/mjs/runtime/script-runtime.mjs +57 -0
  231. package/dist/mjs/runtime/script-runtime.mjs.map +10 -0
  232. package/dist/mjs/server/app-server.mjs +118 -0
  233. package/dist/mjs/server/app-server.mjs.map +10 -0
  234. package/dist/mjs/testing/integration-helpers.mjs +63 -0
  235. package/dist/mjs/testing/integration-helpers.mjs.map +10 -0
  236. package/dist/mjs/typecheck/index.mjs +56 -0
  237. package/dist/mjs/typecheck/index.mjs.map +10 -0
  238. package/dist/mjs/types.mjs +2 -0
  239. package/dist/mjs/types.mjs.map +9 -0
  240. package/dist/types/bridge/diagnostics.d.ts +12 -0
  241. package/dist/types/bridge/legacy-adapters.d.ts +14 -0
  242. package/dist/types/bridge/request-context.d.ts +10 -0
  243. package/dist/types/bridge/runtime-bindings.d.ts +14 -0
  244. package/dist/types/browser/browser-runtime.d.ts +3 -0
  245. package/dist/types/daemon.d.ts +2 -0
  246. package/dist/types/files/index.d.ts +5 -0
  247. package/dist/types/host/create-isolate-host.d.ts +2 -0
  248. package/dist/types/host/index.d.ts +1 -0
  249. package/dist/types/index.d.ts +5 -0
  250. package/dist/types/internal/client/connection.d.ts +9 -0
  251. package/dist/types/internal/client/index.d.ts +8 -0
  252. package/dist/types/internal/client/types.d.ts +198 -0
  253. package/dist/types/internal/console/index.d.ts +108 -0
  254. package/dist/types/internal/console/utils.d.ts +27 -0
  255. package/dist/types/internal/core/index.d.ts +119 -0
  256. package/dist/types/internal/crypto/index.d.ts +18 -0
  257. package/dist/types/internal/daemon/callback-fs-handler.d.ts +28 -0
  258. package/dist/types/internal/daemon/connection.d.ts +9 -0
  259. package/dist/types/internal/daemon/daemon.d.ts +2 -0
  260. package/dist/types/internal/daemon/index.d.ts +14 -0
  261. package/dist/types/internal/daemon/runtime-pool.d.ts +16 -0
  262. package/dist/types/internal/daemon/types.d.ts +211 -0
  263. package/dist/types/internal/encoding/index.d.ts +21 -0
  264. package/dist/types/internal/fetch/consistency/origins.d.ts +179 -0
  265. package/dist/types/internal/fetch/index.d.ts +93 -0
  266. package/dist/types/internal/fetch/stream-state.d.ts +65 -0
  267. package/dist/types/internal/fs/index.d.ts +70 -0
  268. package/dist/types/internal/fs/node-adapter.d.ts +24 -0
  269. package/dist/types/internal/module-loader/bundle.d.ts +33 -0
  270. package/dist/types/internal/module-loader/index.d.ts +30 -0
  271. package/dist/types/internal/module-loader/mappings.d.ts +47 -0
  272. package/dist/types/internal/module-loader/resolve.d.ts +26 -0
  273. package/dist/types/internal/module-loader/strip-types.d.ts +19 -0
  274. package/dist/types/internal/path/index.d.ts +23 -0
  275. package/dist/types/internal/playwright/client.d.ts +7 -0
  276. package/dist/types/internal/playwright/handler.d.ts +44 -0
  277. package/dist/types/internal/playwright/index.d.ts +14 -0
  278. package/dist/types/internal/playwright/types.d.ts +145 -0
  279. package/dist/types/internal/protocol/codec.d.ts +242 -0
  280. package/dist/types/internal/protocol/framing.d.ts +89 -0
  281. package/dist/types/internal/protocol/index.d.ts +10 -0
  282. package/dist/types/internal/protocol/marshalValue.d.ts +79 -0
  283. package/dist/types/internal/protocol/serialization.d.ts +23 -0
  284. package/dist/types/internal/protocol/types.d.ts +996 -0
  285. package/dist/types/internal/runtime/index.d.ts +200 -0
  286. package/dist/types/internal/server/index.d.ts +42 -0
  287. package/dist/types/internal/test-environment/index.d.ts +112 -0
  288. package/dist/types/internal/timers/index.d.ts +22 -0
  289. package/dist/types/internal/transform/index.d.ts +36 -0
  290. package/dist/types/internal/typecheck/index.d.ts +7 -0
  291. package/dist/types/internal/typecheck/isolate-types.d.ts +94 -0
  292. package/dist/types/internal/typecheck/typecheck.d.ts +148 -0
  293. package/dist/types/modules/index.d.ts +2 -0
  294. package/dist/types/runtime/script-runtime.d.ts +6 -0
  295. package/dist/types/server/app-server.d.ts +3 -0
  296. package/dist/types/testing/integration-helpers.d.ts +9 -0
  297. package/dist/types/typecheck/index.d.ts +8 -0
  298. package/dist/types/types.d.ts +233 -0
  299. package/package.json +82 -6
@@ -0,0 +1,2681 @@
1
+ // src/internal/core/index.ts
2
+ import ivm from "isolated-vm";
3
+ import { readFileSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { createRequire } from "node:module";
6
+ var runtimeRequire = createRequire(path.join(process.cwd(), "package.json"));
7
+ var KNOWN_ERROR_TYPES = [
8
+ "TypeError",
9
+ "RangeError",
10
+ "SyntaxError",
11
+ "ReferenceError",
12
+ "URIError",
13
+ "EvalError"
14
+ ];
15
+ function getErrorConstructorName(errorType) {
16
+ return KNOWN_ERROR_TYPES.includes(errorType) ? errorType : "Error";
17
+ }
18
+ function encodeErrorForTransfer(err) {
19
+ const errorType = getErrorConstructorName(err.name);
20
+ return new Error(`[${errorType}]${err.message}`);
21
+ }
22
+ function toError(err) {
23
+ if (err instanceof Error) {
24
+ return err;
25
+ }
26
+ if (typeof err === "string") {
27
+ return new Error(err);
28
+ }
29
+ try {
30
+ return new Error(JSON.stringify(err));
31
+ } catch {
32
+ return new Error(String(err ?? "Unknown error"));
33
+ }
34
+ }
35
+ var DECODE_ERROR_JS = `
36
+ function __decodeError(err) {
37
+ if (!(err instanceof Error)) return err;
38
+ const match = err.message.match(/^\\[(TypeError|RangeError|SyntaxError|ReferenceError|URIError|EvalError|Error)\\](.*)$/);
39
+ if (match) {
40
+ const ErrorType = globalThis[match[1]] || Error;
41
+ return new ErrorType(match[2]);
42
+ }
43
+ return err;
44
+ }
45
+ `.trim();
46
+ var domParserInjectedContexts = new WeakSet;
47
+ var linkedomWorkerInjectionCode = null;
48
+ var instanceStateMap = new WeakMap;
49
+ var nextInstanceId = 1;
50
+ function getInstanceStateMapForContext(context) {
51
+ let map = instanceStateMap.get(context);
52
+ if (!map) {
53
+ map = new Map;
54
+ instanceStateMap.set(context, map);
55
+ }
56
+ return map;
57
+ }
58
+ function clearAllInstanceState() {
59
+ nextInstanceId = 1;
60
+ }
61
+ var unmarshaledHandles = new WeakMap;
62
+ function trackUnmarshaledHandle(context, ref) {
63
+ let set = unmarshaledHandles.get(context);
64
+ if (!set) {
65
+ set = new Set;
66
+ unmarshaledHandles.set(context, set);
67
+ }
68
+ set.add(ref);
69
+ }
70
+ function cleanupUnmarshaledHandles(context) {
71
+ const set = unmarshaledHandles.get(context);
72
+ if (set) {
73
+ for (const ref of set) {
74
+ try {
75
+ ref.release();
76
+ } catch {}
77
+ }
78
+ set.clear();
79
+ }
80
+ }
81
+ var DEFAULT_MAX_DEPTH = 100;
82
+ function marshal(context, value, options) {
83
+ const maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;
84
+ const seen = new Set;
85
+ function marshalValue(val, depth) {
86
+ if (depth > maxDepth) {
87
+ throw new Error(`Max depth of ${maxDepth} exceeded during marshalling`);
88
+ }
89
+ if (val === null || val === undefined) {
90
+ return val;
91
+ }
92
+ const type = typeof val;
93
+ if (type === "string" || type === "number" || type === "boolean") {
94
+ return val;
95
+ }
96
+ if (type === "function") {
97
+ return new ivm.Callback((...args) => {
98
+ try {
99
+ return val(...args);
100
+ } catch (err) {
101
+ if (err instanceof Error) {
102
+ throw err;
103
+ }
104
+ throw new Error(String(err));
105
+ }
106
+ });
107
+ }
108
+ if (type === "object") {
109
+ const obj = val;
110
+ if (seen.has(obj)) {
111
+ throw new Error("Circular reference detected during marshalling");
112
+ }
113
+ seen.add(obj);
114
+ try {
115
+ if (ArrayBuffer.isView(obj)) {
116
+ if (obj instanceof Uint8Array) {
117
+ return new ivm.ExternalCopy(obj).copyInto();
118
+ }
119
+ return Array.from(new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength));
120
+ }
121
+ if (obj instanceof ArrayBuffer) {
122
+ return new ivm.ExternalCopy(new Uint8Array(obj)).copyInto();
123
+ }
124
+ if (obj instanceof Date) {
125
+ return obj.toISOString();
126
+ }
127
+ if (obj instanceof RegExp) {
128
+ return {
129
+ __type: "RegExp",
130
+ source: obj.source,
131
+ flags: obj.flags
132
+ };
133
+ }
134
+ if (obj instanceof Error) {
135
+ return {
136
+ __type: "Error",
137
+ name: obj.name,
138
+ message: obj.message,
139
+ stack: obj.stack
140
+ };
141
+ }
142
+ if (Array.isArray(obj)) {
143
+ const result3 = [];
144
+ for (let i = 0;i < obj.length; i++) {
145
+ result3[i] = marshalValue(obj[i], depth + 1);
146
+ }
147
+ return result3;
148
+ }
149
+ const result2 = {};
150
+ for (const key of Object.keys(obj)) {
151
+ result2[key] = marshalValue(obj[key], depth + 1);
152
+ }
153
+ return result2;
154
+ } finally {
155
+ seen.delete(obj);
156
+ }
157
+ }
158
+ return;
159
+ }
160
+ const marshaled = marshalValue(value, 0);
161
+ if (marshaled instanceof ivm.Reference || marshaled instanceof ivm.Callback) {
162
+ return marshaled;
163
+ }
164
+ const copy = new ivm.ExternalCopy(marshaled);
165
+ const result = copy.copyInto();
166
+ copy.release();
167
+ return result;
168
+ }
169
+ function unmarshal(context, value, options) {
170
+ const maxDepth = options?.maxDepth ?? DEFAULT_MAX_DEPTH;
171
+ function unmarshalValue(val, depth) {
172
+ if (depth > maxDepth) {
173
+ throw new Error(`Max depth of ${maxDepth} exceeded during unmarshalling`);
174
+ }
175
+ if (val === null || val === undefined) {
176
+ return val;
177
+ }
178
+ const type = typeof val;
179
+ if (type === "string" || type === "number" || type === "boolean") {
180
+ return val;
181
+ }
182
+ if (val instanceof ivm.Reference) {
183
+ try {
184
+ const copied = val.copySync();
185
+ trackUnmarshaledHandle(context, val);
186
+ return unmarshalValue(copied, depth);
187
+ } catch {
188
+ return val;
189
+ }
190
+ }
191
+ if (type === "object") {
192
+ const obj = val;
193
+ if (obj.__type === "Error") {
194
+ const ErrorConstructor = globalThis[obj.name];
195
+ const error = new (ErrorConstructor || Error)(obj.message);
196
+ error.name = obj.name;
197
+ if (obj.stack) {
198
+ error.stack = obj.stack;
199
+ }
200
+ return error;
201
+ }
202
+ if (obj.__type === "RegExp") {
203
+ return new RegExp(obj.source, obj.flags);
204
+ }
205
+ if (Array.isArray(obj)) {
206
+ return obj.map((item) => unmarshalValue(item, depth + 1));
207
+ }
208
+ const result = {};
209
+ for (const key of Object.keys(obj)) {
210
+ result[key] = unmarshalValue(obj[key], depth + 1);
211
+ }
212
+ return result;
213
+ }
214
+ return val;
215
+ }
216
+ if (value instanceof ivm.Reference) {
217
+ try {
218
+ const copied = value.copySync();
219
+ return unmarshalValue(copied, 0);
220
+ } catch {
221
+ return value;
222
+ }
223
+ }
224
+ return unmarshalValue(value, 0);
225
+ }
226
+ function withScope(context, callback) {
227
+ const refs = [];
228
+ const scope = {
229
+ manage(ref) {
230
+ refs.push(ref);
231
+ return ref;
232
+ },
233
+ marshal(value, options) {
234
+ const ref = marshal(context, value, options);
235
+ refs.push(ref);
236
+ return ref;
237
+ }
238
+ };
239
+ try {
240
+ return callback(scope);
241
+ } finally {
242
+ for (let i = refs.length - 1;i >= 0; i--) {
243
+ try {
244
+ refs[i].release();
245
+ } catch {}
246
+ }
247
+ }
248
+ }
249
+ async function withScopeAsync(context, callback) {
250
+ const refs = [];
251
+ const scope = {
252
+ manage(ref) {
253
+ refs.push(ref);
254
+ return ref;
255
+ },
256
+ marshal(value, options) {
257
+ const ref = marshal(context, value, options);
258
+ refs.push(ref);
259
+ return ref;
260
+ }
261
+ };
262
+ try {
263
+ return await callback(scope);
264
+ } finally {
265
+ for (let i = refs.length - 1;i >= 0; i--) {
266
+ try {
267
+ refs[i].release();
268
+ } catch {}
269
+ }
270
+ }
271
+ }
272
+ function defineFunction(context, name, fn) {
273
+ const callback = new ivm.Callback((...args) => {
274
+ return fn(...args);
275
+ }, { sync: true });
276
+ const global = context.global;
277
+ global.setSync(name, callback);
278
+ return global.getSync(name);
279
+ }
280
+ function defineAsyncFunction(context, name, fn) {
281
+ const global = context.global;
282
+ const refName = `__async_ref_${name}`;
283
+ const asyncRef = new ivm.Reference(async (...args) => {
284
+ return await fn(...args);
285
+ });
286
+ global.setSync(refName, asyncRef);
287
+ const wrapperCode = `
288
+ (function() {
289
+ ${DECODE_ERROR_JS}
290
+
291
+ globalThis.${name} = async function(...args) {
292
+ try {
293
+ return await ${refName}.apply(undefined, args, { result: { promise: true, copy: true } });
294
+ } catch (err) {
295
+ throw __decodeError(err);
296
+ }
297
+ };
298
+ })();
299
+ `;
300
+ context.evalSync(wrapperCode);
301
+ return global.getSync(name);
302
+ }
303
+ function defineClass(context, definition) {
304
+ const {
305
+ name,
306
+ construct,
307
+ methods = {},
308
+ properties = {},
309
+ staticMethods = {},
310
+ staticProperties = {},
311
+ extends: parentClassName
312
+ } = definition;
313
+ const stateMap = getInstanceStateMapForContext(context);
314
+ const methodCallbacks = {};
315
+ const methodReferences = {};
316
+ for (const [methodName, methodDef] of Object.entries(methods)) {
317
+ if (methodDef.async) {
318
+ methodReferences[`__${name}_${methodName}_ref`] = new ivm.Reference(async (instanceId, ...args) => {
319
+ const state = stateMap.get(instanceId);
320
+ if (!state) {
321
+ throw new Error(`Instance ${instanceId} not found`);
322
+ }
323
+ try {
324
+ return await methodDef.fn(state, ...args);
325
+ } catch (err) {
326
+ throw encodeErrorForTransfer(toError(err));
327
+ }
328
+ });
329
+ } else {
330
+ methodCallbacks[`__${name}_${methodName}`] = new ivm.Callback((instanceId, ...args) => {
331
+ const state = stateMap.get(instanceId);
332
+ if (!state) {
333
+ throw new Error(`Instance ${instanceId} not found`);
334
+ }
335
+ try {
336
+ return methodDef.fn(state, ...args);
337
+ } catch (err) {
338
+ throw encodeErrorForTransfer(toError(err));
339
+ }
340
+ });
341
+ }
342
+ }
343
+ const propertyCallbacks = {};
344
+ for (const [propName, propDef] of Object.entries(properties)) {
345
+ if (propDef.get) {
346
+ const getter = propDef.get;
347
+ propertyCallbacks[`__${name}_get_${propName}`] = new ivm.Callback((instanceId) => {
348
+ const state = stateMap.get(instanceId);
349
+ if (!state) {
350
+ throw new Error(`Instance ${instanceId} not found`);
351
+ }
352
+ try {
353
+ return getter(state);
354
+ } catch (err) {
355
+ throw encodeErrorForTransfer(toError(err));
356
+ }
357
+ });
358
+ }
359
+ if (propDef.set) {
360
+ const setter = propDef.set;
361
+ propertyCallbacks[`__${name}_set_${propName}`] = new ivm.Callback((instanceId, value) => {
362
+ const state = stateMap.get(instanceId);
363
+ if (!state) {
364
+ throw new Error(`Instance ${instanceId} not found`);
365
+ }
366
+ try {
367
+ setter(state, value);
368
+ } catch (err) {
369
+ throw encodeErrorForTransfer(toError(err));
370
+ }
371
+ });
372
+ }
373
+ }
374
+ const staticMethodCallbacks = {};
375
+ const staticMethodReferences = {};
376
+ for (const [methodName, methodDef] of Object.entries(staticMethods)) {
377
+ if (methodDef.async) {
378
+ staticMethodReferences[`__${name}_static_${methodName}_ref`] = new ivm.Reference(async (...args) => {
379
+ try {
380
+ return await methodDef.fn(...args);
381
+ } catch (err) {
382
+ throw encodeErrorForTransfer(toError(err));
383
+ }
384
+ });
385
+ } else {
386
+ staticMethodCallbacks[`__${name}_static_${methodName}`] = new ivm.Callback((...args) => {
387
+ try {
388
+ return methodDef.fn(...args);
389
+ } catch (err) {
390
+ throw encodeErrorForTransfer(toError(err));
391
+ }
392
+ });
393
+ }
394
+ }
395
+ const constructorCallback = new ivm.Callback((...args) => {
396
+ const instanceId = nextInstanceId++;
397
+ if (construct) {
398
+ try {
399
+ const state = construct(args);
400
+ stateMap.set(instanceId, state);
401
+ } catch (err) {
402
+ throw encodeErrorForTransfer(toError(err));
403
+ }
404
+ } else {
405
+ stateMap.set(instanceId, {});
406
+ }
407
+ return instanceId;
408
+ });
409
+ const global = context.global;
410
+ global.setSync(`__${name}_construct`, constructorCallback);
411
+ for (const [callbackName, callback] of Object.entries(methodCallbacks)) {
412
+ global.setSync(callbackName, callback);
413
+ }
414
+ for (const [refName, ref] of Object.entries(methodReferences)) {
415
+ global.setSync(refName, ref);
416
+ }
417
+ for (const [callbackName, callback] of Object.entries(propertyCallbacks)) {
418
+ global.setSync(callbackName, callback);
419
+ }
420
+ for (const [callbackName, callback] of Object.entries(staticMethodCallbacks)) {
421
+ global.setSync(callbackName, callback);
422
+ }
423
+ for (const [refName, ref] of Object.entries(staticMethodReferences)) {
424
+ global.setSync(refName, ref);
425
+ }
426
+ const extendsClause = parentClassName ? ` extends globalThis.${parentClassName}` : "";
427
+ let classCode = `
428
+ (function() {
429
+ // Helper to decode error type from message
430
+ function __decodeError(err) {
431
+ const match = err.message.match(/^\\[(TypeError|RangeError|SyntaxError|ReferenceError|URIError|EvalError|Error)\\](.*)$/);
432
+ if (match) {
433
+ const ErrorType = globalThis[match[1]] || Error;
434
+ return new ErrorType(match[2]);
435
+ }
436
+ return err;
437
+ }
438
+
439
+ // Marker to indicate a class is being extended (skip parent state creation)
440
+ const __EXTENDING_MARKER = Symbol.for('__defineClass_extending__');
441
+ // WeakMap to store instance IDs (shared across inheritance chain)
442
+ const _${name}_instanceIds = new WeakMap();
443
+
444
+ class ${name}${extendsClause} {
445
+ constructor(...args) {
446
+ try {
447
+ ${parentClassName ? "super(__EXTENDING_MARKER);" : ""}
448
+ // Skip state creation if being extended (child will create state)
449
+ if (args[0] === __EXTENDING_MARKER) {
450
+ return;
451
+ }
452
+ const instanceId = __${name}_construct(...args);
453
+ _${name}_instanceIds.set(this, instanceId);
454
+ } catch (err) {
455
+ throw __decodeError(err);
456
+ }
457
+ }
458
+
459
+ _getInstanceId() {
460
+ return _${name}_instanceIds.get(this);
461
+ }
462
+ `;
463
+ for (const [methodName, methodDef] of Object.entries(methods)) {
464
+ if (methodDef.async) {
465
+ classCode += `
466
+ async ${methodName}(...args) {
467
+ try {
468
+ return await __${name}_${methodName}_ref.apply(
469
+ undefined,
470
+ [this._getInstanceId(), ...args],
471
+ { result: { promise: true, copy: true } }
472
+ );
473
+ } catch (err) {
474
+ throw __decodeError(err);
475
+ }
476
+ }
477
+ `;
478
+ } else {
479
+ classCode += `
480
+ ${methodName}(...args) {
481
+ try {
482
+ return __${name}_${methodName}(this._getInstanceId(), ...args);
483
+ } catch (err) {
484
+ throw __decodeError(err);
485
+ }
486
+ }
487
+ `;
488
+ }
489
+ }
490
+ for (const [propName, propDef] of Object.entries(properties)) {
491
+ if (propDef.get || propDef.set) {
492
+ if (propDef.get) {
493
+ classCode += `
494
+ get ${propName}() {
495
+ try {
496
+ return __${name}_get_${propName}(this._getInstanceId());
497
+ } catch (err) {
498
+ throw __decodeError(err);
499
+ }
500
+ }
501
+ `;
502
+ }
503
+ if (propDef.set) {
504
+ classCode += `
505
+ set ${propName}(value) {
506
+ try {
507
+ __${name}_set_${propName}(this._getInstanceId(), value);
508
+ } catch (err) {
509
+ throw __decodeError(err);
510
+ }
511
+ }
512
+ `;
513
+ }
514
+ }
515
+ }
516
+ classCode += `
517
+ }
518
+ `;
519
+ for (const [methodName, methodDef] of Object.entries(staticMethods)) {
520
+ if (methodDef.async) {
521
+ classCode += `
522
+ ${name}.${methodName} = async function(...args) {
523
+ try {
524
+ return await __${name}_static_${methodName}_ref.apply(
525
+ undefined,
526
+ args,
527
+ { result: { promise: true, copy: true } }
528
+ );
529
+ } catch (err) {
530
+ throw __decodeError(err);
531
+ }
532
+ };
533
+ `;
534
+ } else {
535
+ classCode += `
536
+ ${name}.${methodName} = function(...args) {
537
+ try {
538
+ return __${name}_static_${methodName}(...args);
539
+ } catch (err) {
540
+ throw __decodeError(err);
541
+ }
542
+ };
543
+ `;
544
+ }
545
+ }
546
+ for (const [propName, propValue] of Object.entries(staticProperties)) {
547
+ classCode += `
548
+ ${name}.${propName} = ${JSON.stringify(propValue)};
549
+ `;
550
+ }
551
+ classCode += `
552
+ globalThis.${name} = ${name};
553
+ return ${name};
554
+ })()
555
+ `;
556
+ context.evalSync(classCode);
557
+ return global.getSync(name);
558
+ }
559
+ async function setupCore(context, options) {
560
+ const opts = {
561
+ textEncoding: true,
562
+ url: true,
563
+ blob: true,
564
+ streams: true,
565
+ domParser: true,
566
+ ...options
567
+ };
568
+ const stateMap = getInstanceStateMapForContext(context);
569
+ if (opts.textEncoding) {
570
+ await injectTextEncoding(context);
571
+ }
572
+ if (opts.url) {
573
+ await injectURL(context);
574
+ }
575
+ await injectDOMException(context);
576
+ await injectStructuredClone(context);
577
+ await injectAbortController(context);
578
+ if (opts.blob) {
579
+ await injectBlob(context, stateMap);
580
+ }
581
+ if (opts.streams) {
582
+ await injectStreams(context, stateMap);
583
+ }
584
+ if (opts.textEncoding && opts.streams) {
585
+ await injectTextEncodingStreams(context);
586
+ }
587
+ if (opts.domParser) {
588
+ await injectDOMParser(context);
589
+ }
590
+ return {
591
+ dispose() {
592
+ cleanupUnmarshaledHandles(context);
593
+ }
594
+ };
595
+ }
596
+ function getLinkedomWorkerInjectionCode() {
597
+ if (linkedomWorkerInjectionCode) {
598
+ return linkedomWorkerInjectionCode;
599
+ }
600
+ const linkedomPackageJsonPath = runtimeRequire.resolve("linkedom/package.json");
601
+ const workerPath = path.join(path.dirname(linkedomPackageJsonPath), "worker.js");
602
+ const workerSource = readFileSync(workerPath, "utf8");
603
+ const exportBlockPattern = /export\s*\{[\s\S]*?\};?\s*$/;
604
+ if (!exportBlockPattern.test(workerSource)) {
605
+ throw new Error("Failed to locate linkedom worker exports");
606
+ }
607
+ const workerWithoutExports = workerSource.replace(exportBlockPattern, "");
608
+ linkedomWorkerInjectionCode = `
609
+ (function() {
610
+ ${workerWithoutExports}
611
+ globalThis.__linkedomExports = {
612
+ DOMParser,
613
+ Node,
614
+ Document,
615
+ DocumentFragment,
616
+ DocumentType,
617
+ Element,
618
+ Attr,
619
+ Text,
620
+ Comment,
621
+ Event: GlobalEvent,
622
+ EventTarget: DOMEventTarget,
623
+ CustomEvent,
624
+ };
625
+ })();
626
+ `.trim();
627
+ return linkedomWorkerInjectionCode;
628
+ }
629
+ async function injectDOMParser(context) {
630
+ if (domParserInjectedContexts.has(context)) {
631
+ return;
632
+ }
633
+ context.evalSync(getLinkedomWorkerInjectionCode());
634
+ const code = `
635
+ (function() {
636
+ const linkedom = globalThis.__linkedomExports;
637
+ if (!linkedom) {
638
+ throw new Error("DOMParser initialization failed: missing linkedom exports");
639
+ }
640
+
641
+ const supportedMimeTypes = new Set([
642
+ "text/html",
643
+ "text/xml",
644
+ "application/xml",
645
+ "application/xhtml+xml",
646
+ "image/svg+xml",
647
+ ]);
648
+
649
+ const OriginalDOMParser = linkedom.DOMParser;
650
+
651
+ class DOMParser extends OriginalDOMParser {
652
+ parseFromString(input, mimeType) {
653
+ const normalizedMimeType = String(mimeType);
654
+ if (!supportedMimeTypes.has(normalizedMimeType)) {
655
+ throw new TypeError(
656
+ "Failed to execute 'parseFromString' on 'DOMParser': The provided value '" +
657
+ normalizedMimeType +
658
+ "' is not a valid enumeration value of type SupportedType."
659
+ );
660
+ }
661
+ const document = super.parseFromString(input, normalizedMimeType);
662
+ // Normalize adjacent text nodes to match browser parser behavior expected by some SDKs.
663
+ if (
664
+ normalizedMimeType !== "text/html" &&
665
+ document &&
666
+ typeof document.normalize === "function"
667
+ ) {
668
+ document.normalize();
669
+ }
670
+ return document;
671
+ }
672
+ }
673
+
674
+ globalThis.DOMParser = DOMParser;
675
+ globalThis.Node = linkedom.Node;
676
+ globalThis.Document = linkedom.Document;
677
+ globalThis.DocumentFragment = linkedom.DocumentFragment;
678
+ globalThis.DocumentType = linkedom.DocumentType;
679
+ globalThis.Element = linkedom.Element;
680
+ globalThis.Attr = linkedom.Attr;
681
+ globalThis.Text = linkedom.Text;
682
+ globalThis.Comment = linkedom.Comment;
683
+ globalThis.Event = linkedom.Event;
684
+ globalThis.EventTarget = linkedom.EventTarget;
685
+ globalThis.CustomEvent = linkedom.CustomEvent;
686
+
687
+ delete globalThis.__linkedomExports;
688
+ })();
689
+ `;
690
+ try {
691
+ context.evalSync(code);
692
+ domParserInjectedContexts.add(context);
693
+ } catch (err) {
694
+ try {
695
+ context.evalSync("delete globalThis.__linkedomExports;");
696
+ } catch {}
697
+ throw err;
698
+ }
699
+ }
700
+ async function injectTextEncoding(context) {
701
+ const code = `
702
+ (function() {
703
+ class TextEncoder {
704
+ constructor(encoding = 'utf-8') {
705
+ const normalizedEncoding = String(encoding).toLowerCase().trim();
706
+ if (normalizedEncoding !== 'utf-8' && normalizedEncoding !== 'utf8') {
707
+ throw new RangeError('TextEncoder only supports UTF-8 encoding');
708
+ }
709
+ }
710
+
711
+ get encoding() { return 'utf-8'; }
712
+
713
+ encode(input = '') {
714
+ const str = String(input);
715
+ const octets = [];
716
+ for (let i = 0; i < str.length; i++) {
717
+ let codePoint = str.codePointAt(i);
718
+ if (codePoint > 0xFFFF) {
719
+ i++; // Skip the next code unit for surrogate pairs
720
+ }
721
+ if (codePoint < 0x80) {
722
+ octets.push(codePoint);
723
+ } else if (codePoint < 0x800) {
724
+ octets.push(0xC0 | (codePoint >> 6));
725
+ octets.push(0x80 | (codePoint & 0x3F));
726
+ } else if (codePoint < 0x10000) {
727
+ octets.push(0xE0 | (codePoint >> 12));
728
+ octets.push(0x80 | ((codePoint >> 6) & 0x3F));
729
+ octets.push(0x80 | (codePoint & 0x3F));
730
+ } else {
731
+ octets.push(0xF0 | (codePoint >> 18));
732
+ octets.push(0x80 | ((codePoint >> 12) & 0x3F));
733
+ octets.push(0x80 | ((codePoint >> 6) & 0x3F));
734
+ octets.push(0x80 | (codePoint & 0x3F));
735
+ }
736
+ }
737
+ return new Uint8Array(octets);
738
+ }
739
+
740
+ encodeInto(source, destination) {
741
+ const encoded = this.encode(source);
742
+ const len = Math.min(encoded.length, destination.length);
743
+ for (let i = 0; i < len; i++) {
744
+ destination[i] = encoded[i];
745
+ }
746
+ return { read: source.length, written: len };
747
+ }
748
+ }
749
+
750
+ class TextDecoder {
751
+ #encoding;
752
+ #fatal;
753
+ #ignoreBOM;
754
+
755
+ constructor(encoding = 'utf-8', options = {}) {
756
+ const normalizedEncoding = String(encoding).toLowerCase().trim();
757
+ if (normalizedEncoding !== 'utf-8' && normalizedEncoding !== 'utf8') {
758
+ throw new RangeError('TextDecoder only supports UTF-8 encoding');
759
+ }
760
+ this.#encoding = 'utf-8';
761
+ this.#fatal = Boolean(options.fatal);
762
+ this.#ignoreBOM = Boolean(options.ignoreBOM);
763
+ }
764
+
765
+ get encoding() { return this.#encoding; }
766
+ get fatal() { return this.#fatal; }
767
+ get ignoreBOM() { return this.#ignoreBOM; }
768
+
769
+ decode(input, options = {}) {
770
+ if (input === undefined) return '';
771
+
772
+ let bytes;
773
+ if (input instanceof ArrayBuffer) {
774
+ bytes = new Uint8Array(input);
775
+ } else if (ArrayBuffer.isView(input)) {
776
+ bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
777
+ } else {
778
+ throw new TypeError('Input must be ArrayBuffer or ArrayBufferView');
779
+ }
780
+
781
+ let result = '';
782
+ let i = 0;
783
+
784
+ // Skip BOM if present and not ignored
785
+ if (!this.#ignoreBOM && bytes.length >= 3 &&
786
+ bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF) {
787
+ i = 3;
788
+ }
789
+
790
+ while (i < bytes.length) {
791
+ const byte1 = bytes[i++];
792
+
793
+ if (byte1 < 0x80) {
794
+ result += String.fromCodePoint(byte1);
795
+ } else if ((byte1 & 0xE0) === 0xC0) {
796
+ const byte2 = bytes[i++];
797
+ if ((byte2 & 0xC0) !== 0x80) {
798
+ if (this.#fatal) throw new TypeError('Invalid UTF-8');
799
+ result += '\\uFFFD';
800
+ continue;
801
+ }
802
+ result += String.fromCodePoint(((byte1 & 0x1F) << 6) | (byte2 & 0x3F));
803
+ } else if ((byte1 & 0xF0) === 0xE0) {
804
+ const byte2 = bytes[i++];
805
+ const byte3 = bytes[i++];
806
+ if ((byte2 & 0xC0) !== 0x80 || (byte3 & 0xC0) !== 0x80) {
807
+ if (this.#fatal) throw new TypeError('Invalid UTF-8');
808
+ result += '\\uFFFD';
809
+ continue;
810
+ }
811
+ result += String.fromCodePoint(((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F));
812
+ } else if ((byte1 & 0xF8) === 0xF0) {
813
+ const byte2 = bytes[i++];
814
+ const byte3 = bytes[i++];
815
+ const byte4 = bytes[i++];
816
+ if ((byte2 & 0xC0) !== 0x80 || (byte3 & 0xC0) !== 0x80 || (byte4 & 0xC0) !== 0x80) {
817
+ if (this.#fatal) throw new TypeError('Invalid UTF-8');
818
+ result += '\\uFFFD';
819
+ continue;
820
+ }
821
+ const codePoint = ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) << 6) | (byte4 & 0x3F);
822
+ result += String.fromCodePoint(codePoint);
823
+ } else {
824
+ if (this.#fatal) throw new TypeError('Invalid UTF-8');
825
+ result += '\\uFFFD';
826
+ }
827
+ }
828
+
829
+ return result;
830
+ }
831
+ }
832
+
833
+ globalThis.TextEncoder = TextEncoder;
834
+ globalThis.TextDecoder = TextDecoder;
835
+ })();
836
+ `;
837
+ context.evalSync(code);
838
+ }
839
+ async function injectTextEncodingStreams(context) {
840
+ const code = `
841
+ (function() {
842
+ class TextEncoderStream extends TransformStream {
843
+ constructor() {
844
+ const encoder = new TextEncoder();
845
+ let pendingHighSurrogate = null;
846
+
847
+ super({
848
+ transform(chunk, controller) {
849
+ let text = String(chunk);
850
+
851
+ // Handle pending high surrogate from previous chunk
852
+ if (pendingHighSurrogate !== null) {
853
+ text = pendingHighSurrogate + text;
854
+ pendingHighSurrogate = null;
855
+ }
856
+
857
+ // Check if chunk ends with a high surrogate (incomplete pair)
858
+ const lastChar = text.charCodeAt(text.length - 1);
859
+ if (lastChar >= 0xD800 && lastChar <= 0xDBFF) {
860
+ pendingHighSurrogate = text.slice(-1);
861
+ text = text.slice(0, -1);
862
+ }
863
+
864
+ if (text.length > 0) {
865
+ controller.enqueue(encoder.encode(text));
866
+ }
867
+ },
868
+ flush(controller) {
869
+ // If there's a pending high surrogate without a low surrogate, encode as replacement
870
+ if (pendingHighSurrogate !== null) {
871
+ controller.enqueue(encoder.encode('�'));
872
+ }
873
+ }
874
+ });
875
+ }
876
+
877
+ get encoding() { return 'utf-8'; }
878
+ }
879
+
880
+ class TextDecoderStream extends TransformStream {
881
+ #encoding = 'utf-8';
882
+ #fatal;
883
+ #ignoreBOM;
884
+
885
+ constructor(encoding = 'utf-8', options = {}) {
886
+ const normalizedEncoding = String(encoding).toLowerCase().trim();
887
+ if (normalizedEncoding !== 'utf-8' && normalizedEncoding !== 'utf8') {
888
+ throw new RangeError('TextDecoderStream only supports UTF-8 encoding');
889
+ }
890
+
891
+ const fatal = Boolean(options.fatal);
892
+ const ignoreBOM = Boolean(options.ignoreBOM);
893
+ const decoder = new TextDecoder(encoding, { fatal, ignoreBOM });
894
+ let buffer = new Uint8Array(0);
895
+
896
+ super({
897
+ transform(chunk, controller) {
898
+ // Combine with any leftover bytes from previous chunk
899
+ let bytes;
900
+ if (chunk instanceof ArrayBuffer) {
901
+ bytes = new Uint8Array(chunk);
902
+ } else if (ArrayBuffer.isView(chunk)) {
903
+ bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength);
904
+ } else {
905
+ throw new TypeError('Input must be ArrayBuffer or ArrayBufferView');
906
+ }
907
+
908
+ if (buffer.length > 0) {
909
+ const combined = new Uint8Array(buffer.length + bytes.length);
910
+ combined.set(buffer);
911
+ combined.set(bytes, buffer.length);
912
+ bytes = combined;
913
+ buffer = new Uint8Array(0);
914
+ }
915
+
916
+ // Find the last complete UTF-8 sequence
917
+ let validEnd = bytes.length;
918
+ for (let i = bytes.length - 1; i >= Math.max(0, bytes.length - 4); i--) {
919
+ const byte = bytes[i];
920
+ if ((byte & 0xC0) !== 0x80) { // Start of a multi-byte sequence or ASCII
921
+ const expectedLength = byte < 0x80 ? 1 :
922
+ (byte & 0xE0) === 0xC0 ? 2 :
923
+ (byte & 0xF0) === 0xE0 ? 3 :
924
+ (byte & 0xF8) === 0xF0 ? 4 : 1;
925
+ if (i + expectedLength > bytes.length) {
926
+ validEnd = i;
927
+ }
928
+ break;
929
+ }
930
+ }
931
+
932
+ // Save incomplete sequence for next chunk
933
+ if (validEnd < bytes.length) {
934
+ buffer = bytes.slice(validEnd);
935
+ bytes = bytes.slice(0, validEnd);
936
+ }
937
+
938
+ if (bytes.length > 0) {
939
+ const text = decoder.decode(bytes, { stream: true });
940
+ if (text.length > 0) {
941
+ controller.enqueue(text);
942
+ }
943
+ }
944
+ },
945
+ flush(controller) {
946
+ // Decode any remaining bytes
947
+ if (buffer.length > 0) {
948
+ const text = decoder.decode(buffer);
949
+ if (text.length > 0) {
950
+ controller.enqueue(text);
951
+ }
952
+ }
953
+ }
954
+ });
955
+
956
+ this.#fatal = fatal;
957
+ this.#ignoreBOM = ignoreBOM;
958
+ }
959
+
960
+ get encoding() { return this.#encoding; }
961
+ get fatal() { return this.#fatal; }
962
+ get ignoreBOM() { return this.#ignoreBOM; }
963
+ }
964
+
965
+ globalThis.TextEncoderStream = TextEncoderStream;
966
+ globalThis.TextDecoderStream = TextDecoderStream;
967
+ })();
968
+ `;
969
+ context.evalSync(code);
970
+ }
971
+ async function injectURL(context) {
972
+ const code = `
973
+ (function() {
974
+ // Helper for application/x-www-form-urlencoded encoding (spaces as +)
975
+ function urlEncode(str) {
976
+ return encodeURIComponent(String(str)).replace(/%20/g, '+');
977
+ }
978
+
979
+ class URLSearchParams {
980
+ #params = [];
981
+ #url = null;
982
+
983
+ constructor(init = '', url = null) {
984
+ this.#url = url;
985
+ this._parseInit(init);
986
+ }
987
+
988
+ _parseInit(init) {
989
+ this.#params = [];
990
+ if (typeof init === 'string') {
991
+ const query = init.startsWith('?') ? init.slice(1) : init;
992
+ if (query) {
993
+ for (const pair of query.split('&')) {
994
+ const idx = pair.indexOf('=');
995
+ if (idx === -1) {
996
+ this.#params.push([decodeURIComponent(pair.replace(/\\+/g, ' ')), '']);
997
+ } else {
998
+ this.#params.push([
999
+ decodeURIComponent(pair.slice(0, idx).replace(/\\+/g, ' ')),
1000
+ decodeURIComponent(pair.slice(idx + 1).replace(/\\+/g, ' '))
1001
+ ]);
1002
+ }
1003
+ }
1004
+ }
1005
+ } else if (Array.isArray(init)) {
1006
+ for (const pair of init) {
1007
+ if (Array.isArray(pair) && pair.length >= 2) {
1008
+ this.#params.push([String(pair[0]), String(pair[1])]);
1009
+ }
1010
+ }
1011
+ } else if (init instanceof URLSearchParams) {
1012
+ for (const [key, value] of init) {
1013
+ this.#params.push([String(key), String(value)]);
1014
+ }
1015
+ } else if (init && typeof init === 'object') {
1016
+ for (const [key, value] of Object.entries(init)) {
1017
+ this.#params.push([String(key), String(value)]);
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ _updateFromSearch(search) {
1023
+ this._parseInit(search);
1024
+ }
1025
+
1026
+ #notifyUpdate() {
1027
+ if (this.#url) {
1028
+ this.#url._updateSearchFromParams(this.toString());
1029
+ }
1030
+ }
1031
+
1032
+ get size() {
1033
+ return this.#params.length;
1034
+ }
1035
+
1036
+ append(name, value) {
1037
+ this.#params.push([String(name), String(value)]);
1038
+ this.#notifyUpdate();
1039
+ }
1040
+
1041
+ delete(name, value) {
1042
+ const nameStr = String(name);
1043
+ if (value === undefined) {
1044
+ this.#params = this.#params.filter(([k]) => k !== nameStr);
1045
+ } else {
1046
+ const valueStr = String(value);
1047
+ this.#params = this.#params.filter(([k, v]) => !(k === nameStr && v === valueStr));
1048
+ }
1049
+ this.#notifyUpdate();
1050
+ }
1051
+
1052
+ get(name) {
1053
+ const nameStr = String(name);
1054
+ const pair = this.#params.find(([k]) => k === nameStr);
1055
+ return pair ? pair[1] : null;
1056
+ }
1057
+
1058
+ getAll(name) {
1059
+ const nameStr = String(name);
1060
+ return this.#params.filter(([k]) => k === nameStr).map(([, v]) => v);
1061
+ }
1062
+
1063
+ has(name, value) {
1064
+ const nameStr = String(name);
1065
+ if (value === undefined) {
1066
+ return this.#params.some(([k]) => k === nameStr);
1067
+ }
1068
+ const valueStr = String(value);
1069
+ return this.#params.some(([k, v]) => k === nameStr && v === valueStr);
1070
+ }
1071
+
1072
+ set(name, value) {
1073
+ const nameStr = String(name);
1074
+ const valueStr = String(value);
1075
+ let found = false;
1076
+ this.#params = this.#params.filter(([k]) => {
1077
+ if (k === nameStr) {
1078
+ if (!found) {
1079
+ found = true;
1080
+ return true;
1081
+ }
1082
+ return false;
1083
+ }
1084
+ return true;
1085
+ });
1086
+ if (found) {
1087
+ const idx = this.#params.findIndex(([k]) => k === nameStr);
1088
+ if (idx !== -1) {
1089
+ this.#params[idx] = [nameStr, valueStr];
1090
+ }
1091
+ } else {
1092
+ this.#params.push([nameStr, valueStr]);
1093
+ }
1094
+ this.#notifyUpdate();
1095
+ }
1096
+
1097
+ sort() {
1098
+ this.#params.sort((a, b) => a[0].localeCompare(b[0]));
1099
+ this.#notifyUpdate();
1100
+ }
1101
+
1102
+ toString() {
1103
+ return this.#params
1104
+ .map(([k, v]) => urlEncode(k) + '=' + urlEncode(v))
1105
+ .join('&');
1106
+ }
1107
+
1108
+ *entries() {
1109
+ for (const pair of this.#params) {
1110
+ yield [pair[0], pair[1]];
1111
+ }
1112
+ }
1113
+
1114
+ *keys() {
1115
+ for (const [k] of this.#params) {
1116
+ yield k;
1117
+ }
1118
+ }
1119
+
1120
+ *values() {
1121
+ for (const [, v] of this.#params) {
1122
+ yield v;
1123
+ }
1124
+ }
1125
+
1126
+ forEach(callback, thisArg) {
1127
+ for (const [k, v] of this.#params) {
1128
+ callback.call(thisArg, v, k, this);
1129
+ }
1130
+ }
1131
+
1132
+ [Symbol.iterator]() {
1133
+ return this.entries();
1134
+ }
1135
+ }
1136
+
1137
+ class URL {
1138
+ #protocol = '';
1139
+ #username = '';
1140
+ #password = '';
1141
+ #hostname = '';
1142
+ #port = '';
1143
+ #pathname = '/';
1144
+ #search = '';
1145
+ #hash = '';
1146
+ #searchParams = null;
1147
+
1148
+ constructor(url, base) {
1149
+ if (arguments.length === 0) {
1150
+ throw new TypeError("Failed to construct 'URL': 1 argument required, but only 0 present.");
1151
+ }
1152
+
1153
+ let urlStr = String(url);
1154
+
1155
+ if (base !== undefined) {
1156
+ const baseUrl = new URL(String(base));
1157
+ if (urlStr.startsWith('//')) {
1158
+ urlStr = baseUrl.protocol + urlStr;
1159
+ } else if (urlStr.startsWith('/')) {
1160
+ urlStr = baseUrl.origin + urlStr;
1161
+ } else if (!urlStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/)) {
1162
+ const basePath = baseUrl.pathname.substring(0, baseUrl.pathname.lastIndexOf('/') + 1);
1163
+ urlStr = baseUrl.origin + basePath + urlStr;
1164
+ }
1165
+ }
1166
+
1167
+ // Parse the URL
1168
+ const match = urlStr.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):(\\/\\/)?(.*)$/);
1169
+ if (!match) {
1170
+ throw new TypeError("Failed to construct 'URL': Invalid URL");
1171
+ }
1172
+
1173
+ this.#protocol = match[1].toLowerCase() + ':';
1174
+ let rest = match[3];
1175
+
1176
+ if (match[2]) {
1177
+ // Has authority (//...)
1178
+ let authEnd = rest.indexOf('/');
1179
+ if (authEnd === -1) authEnd = rest.indexOf('?');
1180
+ if (authEnd === -1) authEnd = rest.indexOf('#');
1181
+ if (authEnd === -1) authEnd = rest.length;
1182
+
1183
+ const authority = rest.substring(0, authEnd);
1184
+ rest = rest.substring(authEnd);
1185
+
1186
+ // Parse authority: [userinfo@]host[:port]
1187
+ let hostPart = authority;
1188
+ const atIdx = authority.indexOf('@');
1189
+ if (atIdx !== -1) {
1190
+ const userinfo = authority.substring(0, atIdx);
1191
+ hostPart = authority.substring(atIdx + 1);
1192
+ const colonIdx = userinfo.indexOf(':');
1193
+ if (colonIdx !== -1) {
1194
+ this.#username = decodeURIComponent(userinfo.substring(0, colonIdx));
1195
+ this.#password = decodeURIComponent(userinfo.substring(colonIdx + 1));
1196
+ } else {
1197
+ this.#username = decodeURIComponent(userinfo);
1198
+ }
1199
+ }
1200
+
1201
+ // Handle IPv6
1202
+ if (hostPart.startsWith('[')) {
1203
+ const bracketEnd = hostPart.indexOf(']');
1204
+ if (bracketEnd !== -1) {
1205
+ this.#hostname = hostPart.substring(0, bracketEnd + 1);
1206
+ if (hostPart.length > bracketEnd + 1 && hostPart[bracketEnd + 1] === ':') {
1207
+ this.#port = hostPart.substring(bracketEnd + 2);
1208
+ }
1209
+ }
1210
+ } else {
1211
+ const colonIdx = hostPart.lastIndexOf(':');
1212
+ if (colonIdx !== -1) {
1213
+ this.#hostname = hostPart.substring(0, colonIdx);
1214
+ this.#port = hostPart.substring(colonIdx + 1);
1215
+ } else {
1216
+ this.#hostname = hostPart;
1217
+ }
1218
+ }
1219
+ }
1220
+
1221
+ // Parse path, query, fragment
1222
+ let hashIdx = rest.indexOf('#');
1223
+ if (hashIdx !== -1) {
1224
+ this.#hash = rest.substring(hashIdx);
1225
+ rest = rest.substring(0, hashIdx);
1226
+ }
1227
+
1228
+ let queryIdx = rest.indexOf('?');
1229
+ if (queryIdx !== -1) {
1230
+ this.#search = rest.substring(queryIdx);
1231
+ rest = rest.substring(0, queryIdx);
1232
+ }
1233
+
1234
+ this.#pathname = rest || '/';
1235
+ if (!this.#pathname.startsWith('/') && this.#hostname) {
1236
+ this.#pathname = '/' + this.#pathname;
1237
+ }
1238
+ }
1239
+
1240
+ get protocol() { return this.#protocol; }
1241
+ set protocol(value) { this.#protocol = String(value).toLowerCase() + (String(value).endsWith(':') ? '' : ':'); }
1242
+
1243
+ get username() { return this.#username; }
1244
+ set username(value) { this.#username = String(value); }
1245
+
1246
+ get password() { return this.#password; }
1247
+ set password(value) { this.#password = String(value); }
1248
+
1249
+ get hostname() { return this.#hostname; }
1250
+ set hostname(value) { this.#hostname = String(value); }
1251
+
1252
+ get port() { return this.#port; }
1253
+ set port(value) { this.#port = String(value); }
1254
+
1255
+ get pathname() { return this.#pathname; }
1256
+ set pathname(value) { this.#pathname = String(value); }
1257
+
1258
+ get search() { return this.#search; }
1259
+ set search(value) {
1260
+ const str = String(value);
1261
+ this.#search = str.startsWith('?') ? str : (str ? '?' + str : '');
1262
+ if (this.#searchParams) {
1263
+ this.#searchParams._updateFromSearch(this.#search);
1264
+ }
1265
+ }
1266
+
1267
+ _updateSearchFromParams(search) {
1268
+ this.#search = search ? '?' + search : '';
1269
+ }
1270
+
1271
+ get hash() { return this.#hash; }
1272
+ set hash(value) {
1273
+ const str = String(value);
1274
+ this.#hash = str.startsWith('#') ? str : (str ? '#' + str : '');
1275
+ }
1276
+
1277
+ get host() {
1278
+ return this.#port ? this.#hostname + ':' + this.#port : this.#hostname;
1279
+ }
1280
+ set host(value) {
1281
+ const str = String(value);
1282
+ const colonIdx = str.lastIndexOf(':');
1283
+ if (colonIdx !== -1 && !str.includes('[')) {
1284
+ this.#hostname = str.substring(0, colonIdx);
1285
+ this.#port = str.substring(colonIdx + 1);
1286
+ } else {
1287
+ this.#hostname = str;
1288
+ this.#port = '';
1289
+ }
1290
+ }
1291
+
1292
+ get origin() {
1293
+ if (this.#protocol === 'blob:') {
1294
+ try {
1295
+ return new URL(this.#pathname).origin;
1296
+ } catch {
1297
+ return 'null';
1298
+ }
1299
+ }
1300
+ return this.#protocol + '//' + this.host;
1301
+ }
1302
+
1303
+ get href() {
1304
+ let result = this.#protocol;
1305
+ if (this.#hostname) {
1306
+ result += '//';
1307
+ if (this.#username) {
1308
+ result += encodeURIComponent(this.#username);
1309
+ if (this.#password) {
1310
+ result += ':' + encodeURIComponent(this.#password);
1311
+ }
1312
+ result += '@';
1313
+ }
1314
+ result += this.host;
1315
+ }
1316
+ result += this.#pathname + this.#search + this.#hash;
1317
+ return result;
1318
+ }
1319
+ set href(value) {
1320
+ const newUrl = new URL(String(value));
1321
+ this.#protocol = newUrl.protocol;
1322
+ this.#username = newUrl.username;
1323
+ this.#password = newUrl.password;
1324
+ this.#hostname = newUrl.hostname;
1325
+ this.#port = newUrl.port;
1326
+ this.#pathname = newUrl.pathname;
1327
+ this.#search = newUrl.search;
1328
+ this.#hash = newUrl.hash;
1329
+ this.#searchParams = null;
1330
+ }
1331
+
1332
+ get searchParams() {
1333
+ if (!this.#searchParams) {
1334
+ this.#searchParams = new URLSearchParams(this.#search, this);
1335
+ }
1336
+ return this.#searchParams;
1337
+ }
1338
+
1339
+ toString() { return this.href; }
1340
+ toJSON() { return this.href; }
1341
+
1342
+ static canParse(url, base) {
1343
+ try {
1344
+ new URL(url, base);
1345
+ return true;
1346
+ } catch {
1347
+ return false;
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ globalThis.URL = URL;
1353
+ globalThis.URLSearchParams = URLSearchParams;
1354
+ })();
1355
+ `;
1356
+ context.evalSync(code);
1357
+ }
1358
+ async function injectBlob(context, stateMap) {
1359
+ const partsToBytes = (parts) => {
1360
+ return parts.map((part) => {
1361
+ if (typeof part === "string") {
1362
+ return new TextEncoder().encode(part);
1363
+ }
1364
+ if (part instanceof Uint8Array) {
1365
+ return part;
1366
+ }
1367
+ if (part instanceof ArrayBuffer) {
1368
+ return new Uint8Array(part);
1369
+ }
1370
+ if (ArrayBuffer.isView(part)) {
1371
+ return new Uint8Array(part.buffer, part.byteOffset, part.byteLength);
1372
+ }
1373
+ return new TextEncoder().encode(String(part));
1374
+ });
1375
+ };
1376
+ const global = context.global;
1377
+ global.setSync("__Blob_construct", new ivm.Callback((parts, options) => {
1378
+ const instanceId = nextInstanceId++;
1379
+ const bytes = partsToBytes(parts || []);
1380
+ const size = bytes.reduce((acc, b) => acc + b.length, 0);
1381
+ const state = {
1382
+ parts: bytes,
1383
+ type: options?.type?.toLowerCase() || "",
1384
+ size
1385
+ };
1386
+ stateMap.set(instanceId, state);
1387
+ return instanceId;
1388
+ }));
1389
+ global.setSync("__Blob_get_size", new ivm.Callback((instanceId) => {
1390
+ const state = stateMap.get(instanceId);
1391
+ return state?.size ?? 0;
1392
+ }));
1393
+ global.setSync("__Blob_get_type", new ivm.Callback((instanceId) => {
1394
+ const state = stateMap.get(instanceId);
1395
+ return state?.type ?? "";
1396
+ }));
1397
+ global.setSync("__Blob_text", new ivm.Callback((instanceId) => {
1398
+ const state = stateMap.get(instanceId);
1399
+ if (!state)
1400
+ return "";
1401
+ const combined = new Uint8Array(state.size);
1402
+ let offset = 0;
1403
+ for (const part of state.parts) {
1404
+ combined.set(part, offset);
1405
+ offset += part.length;
1406
+ }
1407
+ return new TextDecoder().decode(combined);
1408
+ }));
1409
+ global.setSync("__Blob_arrayBuffer", new ivm.Callback((instanceId) => {
1410
+ const state = stateMap.get(instanceId);
1411
+ if (!state)
1412
+ return new ivm.ExternalCopy(new ArrayBuffer(0)).copyInto();
1413
+ const combined = new Uint8Array(state.size);
1414
+ let offset = 0;
1415
+ for (const part of state.parts) {
1416
+ combined.set(part, offset);
1417
+ offset += part.length;
1418
+ }
1419
+ return new ivm.ExternalCopy(combined.buffer).copyInto();
1420
+ }));
1421
+ global.setSync("__Blob_bytes", new ivm.Callback((instanceId) => {
1422
+ const state = stateMap.get(instanceId);
1423
+ if (!state)
1424
+ return new ivm.ExternalCopy(new Uint8Array(0)).copyInto();
1425
+ const combined = new Uint8Array(state.size);
1426
+ let offset = 0;
1427
+ for (const part of state.parts) {
1428
+ combined.set(part, offset);
1429
+ offset += part.length;
1430
+ }
1431
+ return new ivm.ExternalCopy(combined).copyInto();
1432
+ }));
1433
+ global.setSync("__Blob_slice", new ivm.Callback((instanceId, start, end, contentType) => {
1434
+ const state = stateMap.get(instanceId);
1435
+ if (!state) {
1436
+ const newId2 = nextInstanceId++;
1437
+ stateMap.set(newId2, { parts: [], type: "", size: 0 });
1438
+ return newId2;
1439
+ }
1440
+ const combined = new Uint8Array(state.size);
1441
+ let offset = 0;
1442
+ for (const part of state.parts) {
1443
+ combined.set(part, offset);
1444
+ offset += part.length;
1445
+ }
1446
+ let s = start ?? 0;
1447
+ let e = end ?? state.size;
1448
+ if (s < 0)
1449
+ s = Math.max(0, state.size + s);
1450
+ if (e < 0)
1451
+ e = Math.max(0, state.size + e);
1452
+ s = Math.min(s, state.size);
1453
+ e = Math.min(e, state.size);
1454
+ const sliced = combined.slice(s, e);
1455
+ const newId = nextInstanceId++;
1456
+ const newState = {
1457
+ parts: [sliced],
1458
+ type: contentType ?? state.type,
1459
+ size: sliced.length
1460
+ };
1461
+ stateMap.set(newId, newState);
1462
+ return newId;
1463
+ }));
1464
+ global.setSync("__File_construct", new ivm.Callback((parts, name, options) => {
1465
+ const instanceId = nextInstanceId++;
1466
+ const bytes = partsToBytes(parts || []);
1467
+ const size = bytes.reduce((acc, b) => acc + b.length, 0);
1468
+ const state = {
1469
+ parts: bytes,
1470
+ type: options?.type?.toLowerCase() || "",
1471
+ size,
1472
+ name: String(name),
1473
+ lastModified: options?.lastModified ?? Date.now()
1474
+ };
1475
+ stateMap.set(instanceId, state);
1476
+ return instanceId;
1477
+ }));
1478
+ global.setSync("__File_get_name", new ivm.Callback((instanceId) => {
1479
+ const state = stateMap.get(instanceId);
1480
+ return state?.name ?? "";
1481
+ }));
1482
+ global.setSync("__File_get_lastModified", new ivm.Callback((instanceId) => {
1483
+ const state = stateMap.get(instanceId);
1484
+ return state?.lastModified ?? 0;
1485
+ }));
1486
+ const blobCode = `
1487
+ (function() {
1488
+ const _blobInstanceIds = new WeakMap();
1489
+
1490
+ class Blob {
1491
+ constructor(parts = [], options = {}) {
1492
+ if (parts === null && options === null) {
1493
+ // Internal: creating from existing instance ID (set via _setInstanceId)
1494
+ return;
1495
+ }
1496
+ // Pre-process parts: extract bytes from Blob/File instances
1497
+ const processedParts = [];
1498
+ for (const part of (parts || [])) {
1499
+ if (part instanceof Blob) {
1500
+ // Get bytes synchronously via host callback
1501
+ processedParts.push(__Blob_bytes(part._getInstanceId()));
1502
+ } else {
1503
+ processedParts.push(part);
1504
+ }
1505
+ }
1506
+ const instanceId = __Blob_construct(processedParts, options);
1507
+ _blobInstanceIds.set(this, instanceId);
1508
+ }
1509
+
1510
+ static _createFromInstanceId(instanceId) {
1511
+ const blob = new Blob(null, null);
1512
+ _blobInstanceIds.set(blob, instanceId);
1513
+ return blob;
1514
+ }
1515
+
1516
+ _getInstanceId() {
1517
+ return _blobInstanceIds.get(this);
1518
+ }
1519
+
1520
+ get size() {
1521
+ return __Blob_get_size(this._getInstanceId());
1522
+ }
1523
+
1524
+ get type() {
1525
+ return __Blob_get_type(this._getInstanceId());
1526
+ }
1527
+
1528
+ async text() {
1529
+ return await __Blob_text(this._getInstanceId());
1530
+ }
1531
+
1532
+ async arrayBuffer() {
1533
+ return await __Blob_arrayBuffer(this._getInstanceId());
1534
+ }
1535
+
1536
+ async bytes() {
1537
+ return await __Blob_bytes(this._getInstanceId());
1538
+ }
1539
+
1540
+ slice(start, end, contentType) {
1541
+ const newInstanceId = __Blob_slice(this._getInstanceId(), start, end, contentType);
1542
+ return Blob._createFromInstanceId(newInstanceId);
1543
+ }
1544
+
1545
+ stream() {
1546
+ const blob = this;
1547
+ return new ReadableStream({
1548
+ async start(controller) {
1549
+ const buffer = await blob.arrayBuffer();
1550
+ controller.enqueue(new Uint8Array(buffer));
1551
+ controller.close();
1552
+ }
1553
+ });
1554
+ }
1555
+ }
1556
+
1557
+ class File extends Blob {
1558
+ constructor(parts, name, options = {}) {
1559
+ // Create file through host callback
1560
+ super(null, null);
1561
+ // Pre-process parts: extract bytes from Blob/File instances
1562
+ const processedParts = [];
1563
+ for (const part of (parts || [])) {
1564
+ if (part instanceof Blob) {
1565
+ processedParts.push(__Blob_bytes(part._getInstanceId()));
1566
+ } else {
1567
+ processedParts.push(part);
1568
+ }
1569
+ }
1570
+ const instanceId = __File_construct(processedParts, name, options);
1571
+ _blobInstanceIds.set(this, instanceId);
1572
+ }
1573
+
1574
+ get name() {
1575
+ return __File_get_name(this._getInstanceId());
1576
+ }
1577
+
1578
+ get lastModified() {
1579
+ return __File_get_lastModified(this._getInstanceId());
1580
+ }
1581
+
1582
+ get webkitRelativePath() {
1583
+ return "";
1584
+ }
1585
+
1586
+ slice(start, end, contentType) {
1587
+ const newInstanceId = __Blob_slice(this._getInstanceId(), start, end, contentType);
1588
+ return Blob._createFromInstanceId(newInstanceId);
1589
+ }
1590
+ }
1591
+
1592
+ globalThis.Blob = Blob;
1593
+ globalThis.File = File;
1594
+ })();
1595
+ `;
1596
+ context.evalSync(blobCode);
1597
+ }
1598
+ async function injectDOMException(context) {
1599
+ const code = `
1600
+ (function() {
1601
+ class DOMException extends Error {
1602
+ #code;
1603
+
1604
+ static INDEX_SIZE_ERR = 1;
1605
+ static DOMSTRING_SIZE_ERR = 2;
1606
+ static HIERARCHY_REQUEST_ERR = 3;
1607
+ static WRONG_DOCUMENT_ERR = 4;
1608
+ static INVALID_CHARACTER_ERR = 5;
1609
+ static NO_DATA_ALLOWED_ERR = 6;
1610
+ static NO_MODIFICATION_ALLOWED_ERR = 7;
1611
+ static NOT_FOUND_ERR = 8;
1612
+ static NOT_SUPPORTED_ERR = 9;
1613
+ static INUSE_ATTRIBUTE_ERR = 10;
1614
+ static INVALID_STATE_ERR = 11;
1615
+ static SYNTAX_ERR = 12;
1616
+ static INVALID_MODIFICATION_ERR = 13;
1617
+ static NAMESPACE_ERR = 14;
1618
+ static INVALID_ACCESS_ERR = 15;
1619
+ static VALIDATION_ERR = 16;
1620
+ static TYPE_MISMATCH_ERR = 17;
1621
+ static SECURITY_ERR = 18;
1622
+ static NETWORK_ERR = 19;
1623
+ static ABORT_ERR = 20;
1624
+ static URL_MISMATCH_ERR = 21;
1625
+ static QUOTA_EXCEEDED_ERR = 22;
1626
+ static TIMEOUT_ERR = 23;
1627
+ static INVALID_NODE_TYPE_ERR = 24;
1628
+ static DATA_CLONE_ERR = 25;
1629
+
1630
+ constructor(message = '', name = 'Error') {
1631
+ super(message);
1632
+ this.name = name;
1633
+ this.#code = this.#getCode(name);
1634
+ }
1635
+
1636
+ get code() {
1637
+ return this.#code;
1638
+ }
1639
+
1640
+ #getCode(name) {
1641
+ const codes = {
1642
+ 'IndexSizeError': 1,
1643
+ 'HierarchyRequestError': 3,
1644
+ 'WrongDocumentError': 4,
1645
+ 'InvalidCharacterError': 5,
1646
+ 'NoModificationAllowedError': 7,
1647
+ 'NotFoundError': 8,
1648
+ 'NotSupportedError': 9,
1649
+ 'InUseAttributeError': 10,
1650
+ 'InvalidStateError': 11,
1651
+ 'SyntaxError': 12,
1652
+ 'InvalidModificationError': 13,
1653
+ 'NamespaceError': 14,
1654
+ 'InvalidAccessError': 15,
1655
+ 'TypeMismatchError': 17,
1656
+ 'SecurityError': 18,
1657
+ 'NetworkError': 19,
1658
+ 'AbortError': 20,
1659
+ 'URLMismatchError': 21,
1660
+ 'QuotaExceededError': 22,
1661
+ 'TimeoutError': 23,
1662
+ 'InvalidNodeTypeError': 24,
1663
+ 'DataCloneError': 25,
1664
+ };
1665
+ return codes[name] ?? 0;
1666
+ }
1667
+ }
1668
+
1669
+ globalThis.DOMException = DOMException;
1670
+ })();
1671
+ `;
1672
+ context.evalSync(code);
1673
+ }
1674
+ async function injectAbortController(context) {
1675
+ const code = `
1676
+ (function() {
1677
+ // Use WeakMap for private state (similar to Blob pattern)
1678
+ const _abortSignalState = new WeakMap();
1679
+
1680
+ class AbortSignal {
1681
+ constructor() {
1682
+ // AbortSignal should not be constructed directly
1683
+ // Only AbortController can create it
1684
+ _abortSignalState.set(this, { aborted: false, reason: undefined, listeners: [], onabortHandler: null });
1685
+ }
1686
+
1687
+ get aborted() {
1688
+ return _abortSignalState.get(this)?.aborted ?? false;
1689
+ }
1690
+
1691
+ get reason() {
1692
+ return _abortSignalState.get(this)?.reason;
1693
+ }
1694
+
1695
+ get onabort() {
1696
+ return _abortSignalState.get(this)?.onabortHandler ?? null;
1697
+ }
1698
+
1699
+ set onabort(handler) {
1700
+ const state = _abortSignalState.get(this);
1701
+ if (!state) return;
1702
+
1703
+ // Remove previous handler if it was a listener
1704
+ if (state.onabortHandler) {
1705
+ this.removeEventListener('abort', state.onabortHandler);
1706
+ }
1707
+
1708
+ state.onabortHandler = typeof handler === 'function' ? handler : null;
1709
+
1710
+ // Add new handler as listener
1711
+ if (state.onabortHandler) {
1712
+ this.addEventListener('abort', state.onabortHandler);
1713
+ }
1714
+ }
1715
+
1716
+ throwIfAborted() {
1717
+ const state = _abortSignalState.get(this);
1718
+ if (state?.aborted) {
1719
+ throw state.reason;
1720
+ }
1721
+ }
1722
+
1723
+ addEventListener(type, listener) {
1724
+ if (type !== 'abort') return;
1725
+ const state = _abortSignalState.get(this);
1726
+ if (state) {
1727
+ state.listeners.push(listener);
1728
+ }
1729
+ }
1730
+
1731
+ removeEventListener(type, listener) {
1732
+ if (type !== 'abort') return;
1733
+ const state = _abortSignalState.get(this);
1734
+ if (state) {
1735
+ const idx = state.listeners.indexOf(listener);
1736
+ if (idx !== -1) state.listeners.splice(idx, 1);
1737
+ }
1738
+ }
1739
+
1740
+ _abort(reason) {
1741
+ const state = _abortSignalState.get(this);
1742
+ if (!state || state.aborted) return;
1743
+ state.aborted = true;
1744
+ state.reason = reason !== undefined ? reason : new DOMException('The operation was aborted.', 'AbortError');
1745
+ const event = { type: 'abort', target: this };
1746
+ for (const listener of state.listeners) {
1747
+ try {
1748
+ listener(event);
1749
+ } catch (e) {
1750
+ // Ignore listener errors
1751
+ }
1752
+ }
1753
+ }
1754
+
1755
+ static abort(reason) {
1756
+ const controller = new AbortController();
1757
+ controller.abort(reason);
1758
+ return controller.signal;
1759
+ }
1760
+
1761
+ static timeout(milliseconds) {
1762
+ const controller = new AbortController();
1763
+ setTimeout(() => {
1764
+ controller.abort(new DOMException('The operation timed out.', 'TimeoutError'));
1765
+ }, milliseconds);
1766
+ return controller.signal;
1767
+ }
1768
+
1769
+ static any(signals) {
1770
+ if (!Array.isArray(signals)) {
1771
+ throw new TypeError('signals must be an iterable');
1772
+ }
1773
+
1774
+ // If any signal is already aborted, return an aborted signal with that reason
1775
+ for (const signal of signals) {
1776
+ if (signal.aborted) {
1777
+ return AbortSignal.abort(signal.reason);
1778
+ }
1779
+ }
1780
+
1781
+ // Create a new controller that will abort when any input signal aborts
1782
+ const controller = new AbortController();
1783
+
1784
+ for (const signal of signals) {
1785
+ signal.addEventListener('abort', () => {
1786
+ if (!controller.signal.aborted) {
1787
+ controller.abort(signal.reason);
1788
+ }
1789
+ });
1790
+ }
1791
+
1792
+ return controller.signal;
1793
+ }
1794
+ }
1795
+
1796
+ class AbortController {
1797
+ #signal = null;
1798
+
1799
+ constructor() {
1800
+ this.#signal = new AbortSignal();
1801
+ }
1802
+
1803
+ get signal() {
1804
+ return this.#signal;
1805
+ }
1806
+
1807
+ abort(reason) {
1808
+ this.#signal._abort(reason);
1809
+ }
1810
+ }
1811
+
1812
+ globalThis.AbortController = AbortController;
1813
+ globalThis.AbortSignal = AbortSignal;
1814
+ })();
1815
+ `;
1816
+ context.evalSync(code);
1817
+ }
1818
+ async function injectStructuredClone(context) {
1819
+ const code = `
1820
+ (function() {
1821
+ globalThis.structuredClone = function structuredClone(value, options) {
1822
+ const transfer = options?.transfer;
1823
+ const transferSet = transfer ? new Set(transfer) : null;
1824
+ const seen = new Map();
1825
+
1826
+ function clone(val) {
1827
+ // Primitives
1828
+ if (val === null || val === undefined) return val;
1829
+ const type = typeof val;
1830
+ if (type === 'string' || type === 'number' || type === 'boolean' || type === 'bigint') {
1831
+ return val;
1832
+ }
1833
+
1834
+ // Non-cloneable types
1835
+ if (type === 'function') {
1836
+ throw new DOMException('Function cannot be cloned.', 'DataCloneError');
1837
+ }
1838
+ if (type === 'symbol') {
1839
+ throw new DOMException('Symbol cannot be cloned.', 'DataCloneError');
1840
+ }
1841
+
1842
+ // Circular reference check
1843
+ if (seen.has(val)) {
1844
+ return seen.get(val);
1845
+ }
1846
+
1847
+ // Date
1848
+ if (val instanceof Date) {
1849
+ const cloned = new Date(val.getTime());
1850
+ seen.set(val, cloned);
1851
+ return cloned;
1852
+ }
1853
+
1854
+ // RegExp
1855
+ if (val instanceof RegExp) {
1856
+ const cloned = new RegExp(val.source, val.flags);
1857
+ seen.set(val, cloned);
1858
+ return cloned;
1859
+ }
1860
+
1861
+ // Error types
1862
+ if (val instanceof Error) {
1863
+ const ErrorCtor = globalThis[val.name] || Error;
1864
+ const cloned = new ErrorCtor(val.message);
1865
+ seen.set(val, cloned);
1866
+ cloned.stack = val.stack;
1867
+ if (val.cause !== undefined) cloned.cause = clone(val.cause);
1868
+ return cloned;
1869
+ }
1870
+
1871
+ // ArrayBuffer
1872
+ if (val instanceof ArrayBuffer) {
1873
+ const cloned = val.slice(0);
1874
+ seen.set(val, cloned);
1875
+ return cloned;
1876
+ }
1877
+
1878
+ // TypedArrays
1879
+ if (ArrayBuffer.isView(val) && !(val instanceof DataView)) {
1880
+ const TypedArrayCtor = val.constructor;
1881
+ const bufferClone = clone(val.buffer);
1882
+ const cloned = new TypedArrayCtor(bufferClone, val.byteOffset, val.length);
1883
+ seen.set(val, cloned);
1884
+ return cloned;
1885
+ }
1886
+
1887
+ // DataView
1888
+ if (val instanceof DataView) {
1889
+ const bufferClone = clone(val.buffer);
1890
+ const cloned = new DataView(bufferClone, val.byteOffset, val.byteLength);
1891
+ seen.set(val, cloned);
1892
+ return cloned;
1893
+ }
1894
+
1895
+ // Map
1896
+ if (val instanceof Map) {
1897
+ const cloned = new Map();
1898
+ seen.set(val, cloned);
1899
+ for (const [k, v] of val) cloned.set(clone(k), clone(v));
1900
+ return cloned;
1901
+ }
1902
+
1903
+ // Set
1904
+ if (val instanceof Set) {
1905
+ const cloned = new Set();
1906
+ seen.set(val, cloned);
1907
+ for (const v of val) cloned.add(clone(v));
1908
+ return cloned;
1909
+ }
1910
+
1911
+ // Array
1912
+ if (Array.isArray(val)) {
1913
+ const cloned = new Array(val.length);
1914
+ seen.set(val, cloned);
1915
+ for (let i = 0; i < val.length; i++) {
1916
+ if (i in val) cloned[i] = clone(val[i]);
1917
+ }
1918
+ return cloned;
1919
+ }
1920
+
1921
+ // WeakMap/WeakSet - not cloneable
1922
+ if (val instanceof WeakMap) {
1923
+ throw new DOMException('WeakMap cannot be cloned.', 'DataCloneError');
1924
+ }
1925
+ if (val instanceof WeakSet) {
1926
+ throw new DOMException('WeakSet cannot be cloned.', 'DataCloneError');
1927
+ }
1928
+
1929
+ // Plain objects
1930
+ const cloned = {};
1931
+ seen.set(val, cloned);
1932
+ for (const key of Object.keys(val)) {
1933
+ cloned[key] = clone(val[key]);
1934
+ }
1935
+ return cloned;
1936
+ }
1937
+
1938
+ return clone(value);
1939
+ };
1940
+ })();
1941
+ `;
1942
+ context.evalSync(code);
1943
+ }
1944
+ async function injectStreams(context, _stateMap) {
1945
+ const streamsCode = `
1946
+ (function() {
1947
+ // Simple queue implementation
1948
+ class SimpleQueue {
1949
+ #items = [];
1950
+
1951
+ enqueue(item) {
1952
+ this.#items.push(item);
1953
+ }
1954
+
1955
+ dequeue() {
1956
+ return this.#items.shift();
1957
+ }
1958
+
1959
+ peek() {
1960
+ return this.#items[0];
1961
+ }
1962
+
1963
+ get length() {
1964
+ return this.#items.length;
1965
+ }
1966
+
1967
+ isEmpty() {
1968
+ return this.#items.length === 0;
1969
+ }
1970
+ }
1971
+
1972
+ // ReadableStream
1973
+ class ReadableStream {
1974
+ #state = 'readable';
1975
+ #reader = null;
1976
+ #storedError = undefined;
1977
+ #controller = null;
1978
+ #underlyingSource = null;
1979
+
1980
+ constructor(underlyingSource = {}, strategy = {}) {
1981
+ this.#underlyingSource = underlyingSource;
1982
+
1983
+ const controller = {
1984
+ stream: this,
1985
+ queue: new SimpleQueue(),
1986
+ started: false,
1987
+ closeRequested: false,
1988
+ pullAgain: false,
1989
+ pulling: false,
1990
+
1991
+ close: () => {
1992
+ if (this.#state !== 'readable') return;
1993
+ controller.closeRequested = true;
1994
+ if (controller.queue.isEmpty()) {
1995
+ this.#state = 'closed';
1996
+ if (this.#reader) {
1997
+ // Resolve any pending read with done: true
1998
+ if (this.#reader._pendingRead) {
1999
+ const { resolve } = this.#reader._pendingRead;
2000
+ this.#reader._pendingRead = null;
2001
+ resolve({ value: undefined, done: true });
2002
+ }
2003
+ this.#reader._resolveClose?.();
2004
+ }
2005
+ }
2006
+ },
2007
+
2008
+ enqueue: (chunk) => {
2009
+ if (this.#state !== 'readable') return;
2010
+ controller.queue.enqueue(chunk);
2011
+ if (this.#reader && this.#reader._pendingRead) {
2012
+ const { resolve } = this.#reader._pendingRead;
2013
+ this.#reader._pendingRead = null;
2014
+ const chunk = controller.queue.dequeue();
2015
+ resolve({ value: chunk, done: false });
2016
+ if (controller.closeRequested && controller.queue.isEmpty()) {
2017
+ this.#state = 'closed';
2018
+ this.#reader._resolveClose?.();
2019
+ }
2020
+ }
2021
+ },
2022
+
2023
+ error: (e) => {
2024
+ if (this.#state !== 'readable') return;
2025
+ this.#state = 'errored';
2026
+ this.#storedError = e;
2027
+ if (this.#reader && this.#reader._pendingRead) {
2028
+ const { reject } = this.#reader._pendingRead;
2029
+ this.#reader._pendingRead = null;
2030
+ reject(e);
2031
+ }
2032
+ },
2033
+
2034
+ desiredSize: strategy.highWaterMark ?? 1
2035
+ };
2036
+
2037
+ this.#controller = controller;
2038
+
2039
+ // Start the underlying source
2040
+ if (underlyingSource.start) {
2041
+ const startPromise = Promise.resolve(underlyingSource.start(controller));
2042
+ startPromise.then(() => {
2043
+ controller.started = true;
2044
+ // If pulls were queued while starting, process them now
2045
+ if (controller.pullAgain) {
2046
+ controller.pullAgain = false;
2047
+ this._pull();
2048
+ }
2049
+ }).catch((e) => {
2050
+ controller.error(e);
2051
+ });
2052
+ } else {
2053
+ // No start callback - mark as started immediately
2054
+ controller.started = true;
2055
+ }
2056
+ }
2057
+
2058
+ get locked() {
2059
+ return this.#reader !== null;
2060
+ }
2061
+
2062
+ cancel(reason) {
2063
+ if (this.#reader) {
2064
+ return Promise.reject(new TypeError('Cannot cancel a stream that has a reader'));
2065
+ }
2066
+ return this._cancelInternal(reason);
2067
+ }
2068
+
2069
+ // Internal cancel method - used by reader.cancel() which is allowed even when locked
2070
+ _cancelInternal(reason) {
2071
+ this.#state = 'closed';
2072
+ // Resolve any pending reads with done: true
2073
+ if (this.#reader) {
2074
+ if (this.#reader._pendingRead) {
2075
+ this.#reader._pendingRead.resolve({ value: undefined, done: true });
2076
+ this.#reader._pendingRead = null;
2077
+ }
2078
+ // Resolve the reader's closed promise
2079
+ this.#reader._resolveClose?.();
2080
+ }
2081
+ return Promise.resolve(this.#underlyingSource?.cancel?.(reason));
2082
+ }
2083
+
2084
+ getReader(options = {}) {
2085
+ if (this.#reader) {
2086
+ throw new TypeError('ReadableStream is already locked');
2087
+ }
2088
+ const reader = new ReadableStreamDefaultReader(this);
2089
+ this.#reader = reader;
2090
+ return reader;
2091
+ }
2092
+
2093
+ pipeThrough(transform, options = {}) {
2094
+ const readable = transform.readable;
2095
+ const writable = transform.writable;
2096
+ this.pipeTo(writable, options);
2097
+ return readable;
2098
+ }
2099
+
2100
+ async pipeTo(destination, options = {}) {
2101
+ const reader = this.getReader();
2102
+ const writer = destination.getWriter();
2103
+
2104
+ try {
2105
+ while (true) {
2106
+ const { value, done } = await reader.read();
2107
+ if (done) break;
2108
+ await writer.write(value);
2109
+ }
2110
+ await writer.close();
2111
+ } catch (e) {
2112
+ await writer.abort(e);
2113
+ throw e;
2114
+ } finally {
2115
+ reader.releaseLock();
2116
+ writer.releaseLock();
2117
+ }
2118
+ }
2119
+
2120
+ tee() {
2121
+ const reader = this.getReader();
2122
+ let reading = false;
2123
+ let canceled1 = false;
2124
+ let canceled2 = false;
2125
+ let reason1;
2126
+ let reason2;
2127
+
2128
+ const pullAlgorithm = async () => {
2129
+ if (reading) return;
2130
+ reading = true;
2131
+
2132
+ try {
2133
+ const { value, done } = await reader.read();
2134
+ reading = false;
2135
+
2136
+ if (done) {
2137
+ if (!canceled1) branch1Controller.close();
2138
+ if (!canceled2) branch2Controller.close();
2139
+ return;
2140
+ }
2141
+
2142
+ // Enqueue directly to controllers (not to unused queues)
2143
+ if (!canceled1) branch1Controller.enqueue(value);
2144
+ if (!canceled2) branch2Controller.enqueue(value);
2145
+ } catch (e) {
2146
+ if (!canceled1) branch1Controller.error(e);
2147
+ if (!canceled2) branch2Controller.error(e);
2148
+ }
2149
+ };
2150
+
2151
+ let branch1Controller;
2152
+ let branch2Controller;
2153
+
2154
+ const branch1 = new ReadableStream({
2155
+ start(controller) {
2156
+ branch1Controller = controller;
2157
+ },
2158
+ pull(controller) {
2159
+ return pullAlgorithm();
2160
+ },
2161
+ cancel(reason) {
2162
+ canceled1 = true;
2163
+ reason1 = reason;
2164
+ if (canceled2) {
2165
+ reader.cancel([reason1, reason2]);
2166
+ }
2167
+ }
2168
+ });
2169
+
2170
+ const branch2 = new ReadableStream({
2171
+ start(controller) {
2172
+ branch2Controller = controller;
2173
+ },
2174
+ pull(controller) {
2175
+ return pullAlgorithm();
2176
+ },
2177
+ cancel(reason) {
2178
+ canceled2 = true;
2179
+ reason2 = reason;
2180
+ if (canceled1) {
2181
+ reader.cancel([reason1, reason2]);
2182
+ }
2183
+ }
2184
+ });
2185
+
2186
+ return [branch1, branch2];
2187
+ }
2188
+
2189
+ async *[Symbol.asyncIterator]() {
2190
+ const reader = this.getReader();
2191
+ try {
2192
+ while (true) {
2193
+ const { value, done } = await reader.read();
2194
+ if (done) return;
2195
+ yield value;
2196
+ }
2197
+ } finally {
2198
+ reader.releaseLock();
2199
+ }
2200
+ }
2201
+
2202
+ // Internal methods for reader access
2203
+ _getController() {
2204
+ return this.#controller;
2205
+ }
2206
+
2207
+ _getState() {
2208
+ return this.#state;
2209
+ }
2210
+
2211
+ _setState(state) {
2212
+ this.#state = state;
2213
+ }
2214
+
2215
+ _getStoredError() {
2216
+ return this.#storedError;
2217
+ }
2218
+
2219
+ _setReader(reader) {
2220
+ this.#reader = reader;
2221
+ }
2222
+
2223
+ _pull() {
2224
+ const controller = this.#controller;
2225
+ // If not started yet, queue the pull request to run when started
2226
+ if (!controller.started) {
2227
+ controller.pullAgain = true;
2228
+ return;
2229
+ }
2230
+ if (controller.pulling) return;
2231
+ controller.pulling = true;
2232
+
2233
+ Promise.resolve(this.#underlyingSource?.pull?.(controller))
2234
+ .then(() => {
2235
+ controller.pulling = false;
2236
+ if (controller.pullAgain) {
2237
+ controller.pullAgain = false;
2238
+ this._pull();
2239
+ }
2240
+ })
2241
+ .catch((e) => {
2242
+ controller.error(e);
2243
+ });
2244
+ }
2245
+
2246
+ static from(asyncIterable) {
2247
+ const iterator = asyncIterable[Symbol.asyncIterator]?.() ?? asyncIterable[Symbol.iterator]?.();
2248
+
2249
+ return new ReadableStream({
2250
+ async pull(controller) {
2251
+ const { value, done } = await iterator.next();
2252
+ if (done) {
2253
+ controller.close();
2254
+ } else {
2255
+ controller.enqueue(value);
2256
+ }
2257
+ },
2258
+ cancel(reason) {
2259
+ iterator.return?.(reason);
2260
+ }
2261
+ });
2262
+ }
2263
+ }
2264
+
2265
+ // ReadableStreamDefaultReader
2266
+ class ReadableStreamDefaultReader {
2267
+ #stream = null;
2268
+ _pendingRead = null;
2269
+ _resolveClose = null;
2270
+ _rejectClose = null;
2271
+ #closed = null;
2272
+
2273
+ constructor(stream) {
2274
+ if (stream.locked) {
2275
+ throw new TypeError('ReadableStream is already locked');
2276
+ }
2277
+ this.#stream = stream;
2278
+ stream._setReader(this);
2279
+
2280
+ this.#closed = new Promise((resolve, reject) => {
2281
+ this._resolveClose = resolve;
2282
+ this._rejectClose = reject;
2283
+ });
2284
+ }
2285
+
2286
+ get closed() {
2287
+ return this.#closed;
2288
+ }
2289
+
2290
+ async read() {
2291
+ if (!this.#stream) {
2292
+ throw new TypeError('Reader has been released');
2293
+ }
2294
+
2295
+ const controller = this.#stream._getController();
2296
+ const state = this.#stream._getState();
2297
+
2298
+ if (state === 'closed') {
2299
+ return { value: undefined, done: true };
2300
+ }
2301
+
2302
+ if (state === 'errored') {
2303
+ throw this.#stream._getStoredError();
2304
+ }
2305
+
2306
+ if (!controller.queue.isEmpty()) {
2307
+ const chunk = controller.queue.dequeue();
2308
+ if (controller.closeRequested && controller.queue.isEmpty()) {
2309
+ this.#stream._setState('closed');
2310
+ this._resolveClose?.();
2311
+ }
2312
+ return { value: chunk, done: false };
2313
+ }
2314
+
2315
+ // Queue is empty - check if stream was requested to close
2316
+ if (controller.closeRequested) {
2317
+ this.#stream._setState('closed');
2318
+ this._resolveClose?.();
2319
+ return { value: undefined, done: true };
2320
+ }
2321
+
2322
+ // Need to wait for data
2323
+ return new Promise((resolve, reject) => {
2324
+ this._pendingRead = { resolve, reject };
2325
+ this.#stream._pull();
2326
+ });
2327
+ }
2328
+
2329
+ cancel(reason) {
2330
+ if (!this.#stream) {
2331
+ return Promise.reject(new TypeError('Reader has been released'));
2332
+ }
2333
+ // Use internal cancel - reader is allowed to cancel even when stream is locked
2334
+ return this.#stream._cancelInternal(reason);
2335
+ }
2336
+
2337
+ releaseLock() {
2338
+ if (!this.#stream) return;
2339
+ if (this._pendingRead) {
2340
+ this._pendingRead.reject(new TypeError('Reader was released'));
2341
+ this._pendingRead = null;
2342
+ }
2343
+ this.#stream._setReader(null);
2344
+ this.#stream = null;
2345
+ }
2346
+ }
2347
+
2348
+ // WritableStream
2349
+ class WritableStream {
2350
+ #state = 'writable';
2351
+ #writer = null;
2352
+ #storedError = undefined;
2353
+ #controller = null;
2354
+ #underlyingSink = null;
2355
+ #writeQueue = [];
2356
+ #closePromise = null;
2357
+
2358
+ constructor(underlyingSink = {}, strategy = {}) {
2359
+ this.#underlyingSink = underlyingSink;
2360
+
2361
+ const controller = {
2362
+ stream: this,
2363
+ signal: new AbortController().signal,
2364
+ error: (e) => {
2365
+ if (this.#state !== 'writable') return;
2366
+ this.#state = 'errored';
2367
+ this.#storedError = e;
2368
+ }
2369
+ };
2370
+
2371
+ this.#controller = controller;
2372
+
2373
+ Promise.resolve(underlyingSink.start?.(controller))
2374
+ .catch((e) => {
2375
+ controller.error(e);
2376
+ });
2377
+ }
2378
+
2379
+ get locked() {
2380
+ return this.#writer !== null;
2381
+ }
2382
+
2383
+ abort(reason) {
2384
+ if (this.#writer) {
2385
+ return Promise.reject(new TypeError('Cannot abort a stream that has a writer'));
2386
+ }
2387
+ this.#state = 'errored';
2388
+ this.#storedError = reason;
2389
+ return Promise.resolve(this.#underlyingSink?.abort?.(reason));
2390
+ }
2391
+
2392
+ close() {
2393
+ if (this.#writer) {
2394
+ return Promise.reject(new TypeError('Cannot close a stream that has a writer'));
2395
+ }
2396
+ return this._close();
2397
+ }
2398
+
2399
+ _close() {
2400
+ if (this.#closePromise) return this.#closePromise;
2401
+
2402
+ this.#closePromise = Promise.resolve(this.#underlyingSink?.close?.())
2403
+ .then(() => {
2404
+ this.#state = 'closed';
2405
+ });
2406
+
2407
+ return this.#closePromise;
2408
+ }
2409
+
2410
+ _abort(reason) {
2411
+ this.#state = 'errored';
2412
+ this.#storedError = reason;
2413
+ // Reject any pending write promises
2414
+ for (const pending of this.#writeQueue) {
2415
+ pending.reject?.(reason);
2416
+ }
2417
+ this.#writeQueue = [];
2418
+ return Promise.resolve(this.#underlyingSink?.abort?.(reason));
2419
+ }
2420
+
2421
+ getWriter() {
2422
+ if (this.#writer) {
2423
+ throw new TypeError('WritableStream is already locked');
2424
+ }
2425
+ const writer = new WritableStreamDefaultWriter(this);
2426
+ this.#writer = writer;
2427
+ return writer;
2428
+ }
2429
+
2430
+ // Internal methods
2431
+ _getState() {
2432
+ return this.#state;
2433
+ }
2434
+
2435
+ _getStoredError() {
2436
+ return this.#storedError;
2437
+ }
2438
+
2439
+ _setWriter(writer) {
2440
+ this.#writer = writer;
2441
+ }
2442
+
2443
+ _write(chunk) {
2444
+ if (this.#state !== 'writable') {
2445
+ return Promise.reject(this.#storedError || new TypeError('Stream is not writable'));
2446
+ }
2447
+
2448
+ let resolve, reject;
2449
+ const pendingPromise = new Promise((res, rej) => {
2450
+ resolve = res;
2451
+ reject = rej;
2452
+ });
2453
+
2454
+ const pending = { resolve, reject };
2455
+ this.#writeQueue.push(pending);
2456
+
2457
+ const cleanup = () => {
2458
+ const index = this.#writeQueue.indexOf(pending);
2459
+ if (index !== -1) {
2460
+ this.#writeQueue.splice(index, 1);
2461
+ }
2462
+ };
2463
+
2464
+ Promise.resolve(this.#underlyingSink?.write?.(chunk, this.#controller))
2465
+ .then((result) => {
2466
+ cleanup();
2467
+ resolve(result);
2468
+ })
2469
+ .catch((e) => {
2470
+ cleanup();
2471
+ reject(e);
2472
+ });
2473
+
2474
+ return pendingPromise;
2475
+ }
2476
+ }
2477
+
2478
+ // WritableStreamDefaultWriter
2479
+ class WritableStreamDefaultWriter {
2480
+ #stream = null;
2481
+ #ready = null;
2482
+ #closed = null;
2483
+ #closedResolve = null;
2484
+ #closedReject = null;
2485
+ #closedSettled = false;
2486
+
2487
+ constructor(stream) {
2488
+ if (stream.locked) {
2489
+ throw new TypeError('WritableStream is already locked');
2490
+ }
2491
+ this.#stream = stream;
2492
+ stream._setWriter(this);
2493
+
2494
+ this.#ready = Promise.resolve();
2495
+ this.#closed = new Promise((resolve, reject) => {
2496
+ this.#closedResolve = resolve;
2497
+ this.#closedReject = reject;
2498
+ });
2499
+ }
2500
+
2501
+ get closed() {
2502
+ return this.#closed;
2503
+ }
2504
+
2505
+ get ready() {
2506
+ return this.#ready;
2507
+ }
2508
+
2509
+ get desiredSize() {
2510
+ return 1;
2511
+ }
2512
+
2513
+ abort(reason) {
2514
+ if (!this.#stream) {
2515
+ return Promise.reject(new TypeError('Writer has been released'));
2516
+ }
2517
+ // Mark closed as settled since abort will reject the closed promise
2518
+ this.#closedSettled = true;
2519
+ const abortPromise = this.#stream._abort(reason);
2520
+ // DON'T reject closed here - see if test passes without it
2521
+ return abortPromise;
2522
+ }
2523
+
2524
+ close() {
2525
+ if (!this.#stream) {
2526
+ return Promise.reject(new TypeError('Writer has been released'));
2527
+ }
2528
+ return this.#stream._close().then(() => {
2529
+ if (!this.#closedSettled) {
2530
+ this.#closedSettled = true;
2531
+ this.#closedResolve?.();
2532
+ }
2533
+ }).catch((e) => {
2534
+ if (!this.#closedSettled) {
2535
+ this.#closedSettled = true;
2536
+ this.#closedReject?.(e);
2537
+ }
2538
+ throw e;
2539
+ });
2540
+ }
2541
+
2542
+ write(chunk) {
2543
+ if (!this.#stream) {
2544
+ return Promise.reject(new TypeError('Writer has been released'));
2545
+ }
2546
+ return this.#stream._write(chunk);
2547
+ }
2548
+
2549
+ releaseLock() {
2550
+ if (!this.#stream) return;
2551
+ this.#stream._setWriter(null);
2552
+ this.#stream = null;
2553
+ // Only reject the closed promise if it hasn't been settled yet
2554
+ // (i.e., the stream wasn't closed or aborted before release)
2555
+ if (!this.#closedSettled) {
2556
+ this.#closedSettled = true;
2557
+ this.#closedReject?.(new TypeError('Writer was released'));
2558
+ }
2559
+ }
2560
+ }
2561
+
2562
+ // TransformStream
2563
+ class TransformStream {
2564
+ #readable;
2565
+ #writable;
2566
+
2567
+ constructor(transformer = {}, writableStrategy = {}, readableStrategy = {}) {
2568
+ let readableController;
2569
+
2570
+ this.#readable = new ReadableStream({
2571
+ start(controller) {
2572
+ readableController = controller;
2573
+ }
2574
+ }, readableStrategy);
2575
+
2576
+ const transformerController = {
2577
+ enqueue: (chunk) => {
2578
+ readableController.enqueue(chunk);
2579
+ },
2580
+ error: (e) => {
2581
+ readableController.error(e);
2582
+ },
2583
+ terminate: () => {
2584
+ readableController.close();
2585
+ },
2586
+ desiredSize: readableController?.desiredSize ?? 1
2587
+ };
2588
+
2589
+ this.#writable = new WritableStream({
2590
+ start() {
2591
+ return transformer.start?.(transformerController);
2592
+ },
2593
+ write(chunk) {
2594
+ // If no transform function is provided, act as identity transform
2595
+ if (transformer.transform) {
2596
+ return transformer.transform(chunk, transformerController);
2597
+ } else {
2598
+ transformerController.enqueue(chunk);
2599
+ }
2600
+ },
2601
+ close() {
2602
+ const result = transformer.flush?.(transformerController);
2603
+ return Promise.resolve(result).then(() => {
2604
+ readableController.close();
2605
+ });
2606
+ },
2607
+ abort(reason) {
2608
+ readableController.error(reason);
2609
+ return Promise.resolve();
2610
+ }
2611
+ }, writableStrategy);
2612
+ }
2613
+
2614
+ get readable() {
2615
+ return this.#readable;
2616
+ }
2617
+
2618
+ get writable() {
2619
+ return this.#writable;
2620
+ }
2621
+ }
2622
+
2623
+ // ByteLengthQueuingStrategy
2624
+ class ByteLengthQueuingStrategy {
2625
+ #highWaterMark;
2626
+
2627
+ constructor({ highWaterMark }) {
2628
+ this.#highWaterMark = highWaterMark;
2629
+ }
2630
+
2631
+ get highWaterMark() {
2632
+ return this.#highWaterMark;
2633
+ }
2634
+
2635
+ get size() {
2636
+ return (chunk) => chunk.byteLength;
2637
+ }
2638
+ }
2639
+
2640
+ // CountQueuingStrategy
2641
+ class CountQueuingStrategy {
2642
+ #highWaterMark;
2643
+
2644
+ constructor({ highWaterMark }) {
2645
+ this.#highWaterMark = highWaterMark;
2646
+ }
2647
+
2648
+ get highWaterMark() {
2649
+ return this.#highWaterMark;
2650
+ }
2651
+
2652
+ get size() {
2653
+ return () => 1;
2654
+ }
2655
+ }
2656
+
2657
+ globalThis.ReadableStream = ReadableStream;
2658
+ globalThis.ReadableStreamDefaultReader = ReadableStreamDefaultReader;
2659
+ globalThis.WritableStream = WritableStream;
2660
+ globalThis.WritableStreamDefaultWriter = WritableStreamDefaultWriter;
2661
+ globalThis.TransformStream = TransformStream;
2662
+ globalThis.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy;
2663
+ globalThis.CountQueuingStrategy = CountQueuingStrategy;
2664
+ })();
2665
+ `;
2666
+ context.evalSync(streamsCode);
2667
+ }
2668
+ export {
2669
+ withScopeAsync,
2670
+ withScope,
2671
+ unmarshal,
2672
+ setupCore,
2673
+ marshal,
2674
+ defineFunction,
2675
+ defineClass,
2676
+ defineAsyncFunction,
2677
+ clearAllInstanceState,
2678
+ cleanupUnmarshaledHandles
2679
+ };
2680
+
2681
+ //# debugId=58642E58B9C2142364756E2164756E21