just-bash 2.12.8 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +89 -3
  2. package/dist/AGENTS.md +1 -1
  3. package/dist/Bash.d.ts +17 -0
  4. package/dist/bin/chunks/{awk2-J2PNSA7C.js → awk2-VTJMI54B.js} +1 -1
  5. package/dist/bin/chunks/chunk-3YMCKZTY.js +14 -0
  6. package/dist/bin/chunks/{chunk-O5B6WWQQ.js → chunk-A3HQTYHR.js} +1 -1
  7. package/dist/bin/chunks/chunk-AAW7UMPO.js +9 -0
  8. package/dist/bin/chunks/{chunk-2V53PP6G.js → chunk-B3RU2PUI.js} +27 -27
  9. package/dist/bin/chunks/chunk-CQG2HEAL.js +5 -0
  10. package/dist/bin/chunks/chunk-DOXYBGNA.js +12 -0
  11. package/dist/bin/{shell/chunks/chunk-YAEF6X2N.js → chunks/chunk-GR23MPTT.js} +1 -1
  12. package/dist/bin/{shell/chunks/chunk-35JD7YEM.js → chunks/chunk-HJEHIH4P.js} +13 -13
  13. package/dist/bin/chunks/{chunk-UG4GMDQL.js → chunk-LGF54XJQ.js} +1 -1
  14. package/dist/bin/chunks/chunk-N6KA6G3Q.js +11 -0
  15. package/dist/bin/chunks/{chunk-2BC3N3L2.js → chunk-ORUYSLP4.js} +4 -4
  16. package/dist/bin/chunks/{chunk-REGSV3X5.js → chunk-SDLWFYVT.js} +1 -1
  17. package/dist/bin/chunks/{chunk-STOAUD75.js → chunk-THNL3XFF.js} +8 -8
  18. package/dist/bin/chunks/{chunk-ZJGIBTWD.js → chunk-V7ZOPVQS.js} +1 -1
  19. package/dist/bin/chunks/{chunk-ZYQQ6B7B.js → chunk-ZO5PSLKR.js} +2 -2
  20. package/dist/bin/{shell/chunks/curl-3GMIPMCI.js → chunks/curl-B64SIJOD.js} +1 -1
  21. package/dist/bin/chunks/env-NTPN5QYM.js +2 -0
  22. package/dist/bin/{shell/chunks/expansion-JBCP2CHQ.js → chunks/expansion-2RO5M3QC.js} +1 -1
  23. package/dist/bin/{shell/chunks/find-MTLF23HX.js → chunks/find-GAYRV4IF.js} +1 -1
  24. package/dist/bin/{shell/chunks/flag-coverage-CFWN3JJN.js → chunks/flag-coverage-IRM4GISL.js} +1 -1
  25. package/dist/bin/{shell/chunks/help-4H52JYYC.js → chunks/help-DVG4AAGE.js} +1 -1
  26. package/dist/bin/{shell/chunks/jq-JFXEKNLN.js → chunks/jq-V7FYGIKO.js} +1 -1
  27. package/dist/bin/chunks/js-exec-YGYYZEEQ.js +97 -0
  28. package/dist/bin/chunks/js-exec-worker.js +4368 -0
  29. package/dist/bin/chunks/python3-EIXZW3LO.js +12 -0
  30. package/dist/bin/chunks/rg-C6KMBFNG.js +2 -0
  31. package/dist/bin/{shell/chunks/time-GZSHCM77.js → chunks/time-VSKBXRQH.js} +1 -1
  32. package/dist/bin/chunks/{timeout-JJWIFL7W.js → timeout-Z24MNWOP.js} +1 -1
  33. package/dist/bin/chunks/worker.js +87 -33
  34. package/dist/bin/chunks/{xan-M6MLWZCU.js → xan-MOZFJGMY.js} +1 -1
  35. package/dist/bin/chunks/xargs-SCYIFXOW.js +2 -0
  36. package/dist/bin/chunks/{yq-YWUQUXJJ.js → yq-JJLSDDST.js} +1 -1
  37. package/dist/bin/just-bash.js +158 -157
  38. package/dist/bin/shell/chunks/{awk2-J2PNSA7C.js → awk2-VTJMI54B.js} +1 -1
  39. package/dist/bin/shell/chunks/chunk-3YMCKZTY.js +14 -0
  40. package/dist/bin/shell/chunks/{chunk-O5B6WWQQ.js → chunk-A3HQTYHR.js} +1 -1
  41. package/dist/bin/shell/chunks/chunk-AAW7UMPO.js +9 -0
  42. package/dist/bin/shell/chunks/{chunk-2V53PP6G.js → chunk-B3RU2PUI.js} +27 -27
  43. package/dist/bin/shell/chunks/chunk-CQG2HEAL.js +5 -0
  44. package/dist/bin/shell/chunks/chunk-DOXYBGNA.js +12 -0
  45. package/dist/bin/{chunks/chunk-YAEF6X2N.js → shell/chunks/chunk-GR23MPTT.js} +1 -1
  46. package/dist/bin/{chunks/chunk-35JD7YEM.js → shell/chunks/chunk-HJEHIH4P.js} +13 -13
  47. package/dist/bin/shell/chunks/{chunk-UG4GMDQL.js → chunk-LGF54XJQ.js} +1 -1
  48. package/dist/bin/shell/chunks/chunk-N6KA6G3Q.js +11 -0
  49. package/dist/bin/shell/chunks/{chunk-2BC3N3L2.js → chunk-ORUYSLP4.js} +4 -4
  50. package/dist/bin/shell/chunks/{chunk-REGSV3X5.js → chunk-SDLWFYVT.js} +1 -1
  51. package/dist/bin/shell/chunks/{chunk-STOAUD75.js → chunk-THNL3XFF.js} +8 -8
  52. package/dist/bin/shell/chunks/{chunk-ZJGIBTWD.js → chunk-V7ZOPVQS.js} +1 -1
  53. package/dist/bin/shell/chunks/{chunk-ZYQQ6B7B.js → chunk-ZO5PSLKR.js} +2 -2
  54. package/dist/bin/{chunks/curl-3GMIPMCI.js → shell/chunks/curl-B64SIJOD.js} +1 -1
  55. package/dist/bin/shell/chunks/env-NTPN5QYM.js +2 -0
  56. package/dist/bin/{chunks/expansion-JBCP2CHQ.js → shell/chunks/expansion-2RO5M3QC.js} +1 -1
  57. package/dist/bin/{chunks/find-MTLF23HX.js → shell/chunks/find-GAYRV4IF.js} +1 -1
  58. package/dist/bin/{chunks/flag-coverage-CFWN3JJN.js → shell/chunks/flag-coverage-IRM4GISL.js} +1 -1
  59. package/dist/bin/{chunks/help-4H52JYYC.js → shell/chunks/help-DVG4AAGE.js} +1 -1
  60. package/dist/bin/{chunks/jq-JFXEKNLN.js → shell/chunks/jq-V7FYGIKO.js} +1 -1
  61. package/dist/bin/shell/chunks/js-exec-VYG74FQ3.js +97 -0
  62. package/dist/bin/shell/chunks/python3-WO3WFGMS.js +12 -0
  63. package/dist/bin/shell/chunks/rg-C6KMBFNG.js +2 -0
  64. package/dist/bin/{chunks/time-GZSHCM77.js → shell/chunks/time-VSKBXRQH.js} +1 -1
  65. package/dist/bin/shell/chunks/{timeout-JJWIFL7W.js → timeout-Z24MNWOP.js} +1 -1
  66. package/dist/bin/shell/chunks/{xan-M6MLWZCU.js → xan-MOZFJGMY.js} +1 -1
  67. package/dist/bin/shell/chunks/xargs-SCYIFXOW.js +2 -0
  68. package/dist/bin/shell/chunks/{yq-YWUQUXJJ.js → yq-JJLSDDST.js} +1 -1
  69. package/dist/bin/shell/shell.js +164 -164
  70. package/dist/bundle/browser.js +534 -534
  71. package/dist/bundle/chunks/{awk2-FUVZGMX2.js → awk2-POPGKRAI.js} +1 -1
  72. package/dist/bundle/chunks/{chunk-DZZS6SJP.js → chunk-7TSDKFEO.js} +1 -1
  73. package/dist/bundle/chunks/{chunk-D4QDMGEB.js → chunk-BBXLRYSX.js} +2 -2
  74. package/dist/bundle/chunks/{chunk-TRD56HID.js → chunk-FEIOJCZD.js} +1 -1
  75. package/dist/bundle/chunks/chunk-JCMONG3T.js +13 -0
  76. package/dist/bundle/chunks/{chunk-D2FZX7A2.js → chunk-LPQPILI2.js} +8 -8
  77. package/dist/bundle/chunks/chunk-MJWMXCEJ.js +10 -0
  78. package/dist/bundle/chunks/{chunk-2GOYXRRP.js → chunk-MLXIYONF.js} +4 -4
  79. package/dist/bundle/chunks/chunk-NAERJDUW.js +8 -0
  80. package/dist/bundle/chunks/{chunk-OKEHYWBE.js → chunk-NYQYO467.js} +13 -13
  81. package/dist/bundle/chunks/{chunk-JKLUDNMU.js → chunk-O2DBFL6Z.js} +1 -1
  82. package/dist/bundle/chunks/{chunk-JDMQDJYE.js → chunk-OARHFVLG.js} +1 -1
  83. package/dist/bundle/chunks/{chunk-AKVMAONP.js → chunk-RUF7WQ7U.js} +1 -1
  84. package/dist/bundle/chunks/chunk-TOMNU26N.js +4 -0
  85. package/dist/bundle/chunks/{chunk-ZLJ5TCLC.js → chunk-UNYNJIFU.js} +27 -27
  86. package/dist/bundle/chunks/chunk-YTNYSM6T.js +11 -0
  87. package/dist/bundle/chunks/{curl-KM2ZAUR6.js → curl-FCIO57JJ.js} +1 -1
  88. package/dist/bundle/chunks/env-5EPCWSXR.js +1 -0
  89. package/dist/bundle/chunks/{expansion-XG7G47TX.js → expansion-ENLSRCXJ.js} +1 -1
  90. package/dist/bundle/chunks/{find-DOIVMX6X.js → find-TPUOAIUQ.js} +1 -1
  91. package/dist/bundle/chunks/{flag-coverage-VML3BMJT.js → flag-coverage-SPT2DN2I.js} +1 -1
  92. package/dist/bundle/chunks/{help-IA5CMGR4.js → help-VVWX7SA5.js} +1 -1
  93. package/dist/bundle/chunks/{jq-SSCW4AAA.js → jq-DIRZBOTX.js} +1 -1
  94. package/dist/bundle/chunks/js-exec-R2LSP7M4.js +96 -0
  95. package/dist/bundle/chunks/js-exec-worker.js +4368 -0
  96. package/dist/bundle/chunks/python3-DH2SBOI3.js +11 -0
  97. package/dist/bundle/chunks/rg-FOQSCCX3.js +1 -0
  98. package/dist/bundle/chunks/{time-XL42Z4U5.js → time-FABCOJJU.js} +1 -1
  99. package/dist/bundle/chunks/{timeout-QCU4INQT.js → timeout-VRKMCG72.js} +1 -1
  100. package/dist/bundle/chunks/worker.js +87 -33
  101. package/dist/bundle/chunks/{xan-K7XYDHFV.js → xan-BXDXYEIB.js} +1 -1
  102. package/dist/bundle/chunks/xargs-I6EZUCYF.js +1 -0
  103. package/dist/bundle/chunks/{yq-WTK3HUOR.js → yq-XMVSIL6Z.js} +1 -1
  104. package/dist/bundle/index.cjs +956 -857
  105. package/dist/bundle/index.js +145 -145
  106. package/dist/commands/js-exec/fetch-polyfill.d.ts +6 -0
  107. package/dist/commands/js-exec/js-exec.d.ts +11 -0
  108. package/dist/commands/js-exec/module-shims.d.ts +29 -0
  109. package/dist/commands/js-exec/path-polyfill.d.ts +6 -0
  110. package/dist/commands/js-exec/worker.d.ts +30 -0
  111. package/dist/commands/python3/worker.d.ts +1 -0
  112. package/dist/commands/query-engine/safe-object.d.ts +11 -0
  113. package/dist/commands/registry.d.ts +13 -2
  114. package/dist/commands/{python3/fs-bridge-handler.d.ts → worker-bridge/bridge-handler.d.ts} +25 -8
  115. package/dist/commands/{python3 → worker-bridge}/protocol.d.ts +6 -3
  116. package/dist/commands/{python3/sync-fs-backend.d.ts → worker-bridge/sync-backend.d.ts} +25 -4
  117. package/dist/index.d.cts +3 -3
  118. package/dist/index.d.ts +3 -3
  119. package/dist/interpreter/interpreter.d.ts +3 -0
  120. package/dist/interpreter/types.d.ts +8 -0
  121. package/dist/limits.d.ts +3 -1
  122. package/dist/types.d.ts +12 -0
  123. package/package.json +12 -11
  124. package/dist/bin/chunks/chunk-47HZU3SY.js +0 -5
  125. package/dist/bin/chunks/chunk-CZFRRDQC.js +0 -12
  126. package/dist/bin/chunks/chunk-N4EU64Y4.js +0 -9
  127. package/dist/bin/chunks/chunk-VIYJJTN2.js +0 -14
  128. package/dist/bin/chunks/env-HOVBNLUR.js +0 -2
  129. package/dist/bin/chunks/python3-KI2FQWSN.js +0 -17
  130. package/dist/bin/chunks/rg-34GE6REQ.js +0 -2
  131. package/dist/bin/chunks/xargs-GBL6PZ2K.js +0 -2
  132. package/dist/bin/shell/chunks/chunk-47HZU3SY.js +0 -5
  133. package/dist/bin/shell/chunks/chunk-CZFRRDQC.js +0 -12
  134. package/dist/bin/shell/chunks/chunk-N4EU64Y4.js +0 -9
  135. package/dist/bin/shell/chunks/chunk-VIYJJTN2.js +0 -14
  136. package/dist/bin/shell/chunks/env-HOVBNLUR.js +0 -2
  137. package/dist/bin/shell/chunks/python3-E5X6WBBU.js +0 -17
  138. package/dist/bin/shell/chunks/rg-34GE6REQ.js +0 -2
  139. package/dist/bin/shell/chunks/xargs-GBL6PZ2K.js +0 -2
  140. package/dist/bundle/chunks/chunk-3RA5L262.js +0 -8
  141. package/dist/bundle/chunks/chunk-EX62JIX3.js +0 -13
  142. package/dist/bundle/chunks/chunk-WECLUBEQ.js +0 -11
  143. package/dist/bundle/chunks/chunk-ZSJYNBAF.js +0 -4
  144. package/dist/bundle/chunks/env-XZY4LKEO.js +0 -1
  145. package/dist/bundle/chunks/python3-2OHR6PZU.js +0 -16
  146. package/dist/bundle/chunks/rg-RAICUFGG.js +0 -1
  147. package/dist/bundle/chunks/xargs-2BBAQDTC.js +0 -1
@@ -0,0 +1,4368 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/commands/js-exec/worker.ts
9
+ import { stripTypeScriptTypes } from "node:module";
10
+ import { parentPort } from "node:worker_threads";
11
+ import {
12
+ getQuickJS
13
+ } from "quickjs-emscripten";
14
+
15
+ // src/security/blocked-globals.ts
16
+ function getBlockedGlobals() {
17
+ const globals = [
18
+ // Direct code execution vectors
19
+ {
20
+ prop: "Function",
21
+ target: globalThis,
22
+ violationType: "function_constructor",
23
+ strategy: "throw",
24
+ reason: "Function constructor allows arbitrary code execution"
25
+ },
26
+ {
27
+ prop: "eval",
28
+ target: globalThis,
29
+ violationType: "eval",
30
+ strategy: "throw",
31
+ reason: "eval() allows arbitrary code execution"
32
+ },
33
+ // Timer functions with string argument allow code execution
34
+ {
35
+ prop: "setTimeout",
36
+ target: globalThis,
37
+ violationType: "setTimeout",
38
+ strategy: "throw",
39
+ reason: "setTimeout with string argument allows code execution"
40
+ },
41
+ {
42
+ prop: "setInterval",
43
+ target: globalThis,
44
+ violationType: "setInterval",
45
+ strategy: "throw",
46
+ reason: "setInterval with string argument allows code execution"
47
+ },
48
+ {
49
+ prop: "setImmediate",
50
+ target: globalThis,
51
+ violationType: "setImmediate",
52
+ strategy: "throw",
53
+ reason: "setImmediate could be used to escape sandbox context"
54
+ },
55
+ // Note: We intentionally do NOT block `process` entirely because:
56
+ // 1. Node.js internals (Promise resolution, etc.) use process.nextTick
57
+ // 2. Blocking process entirely breaks normal async operation
58
+ // 3. The primary code execution vectors (Function, eval) are already blocked
59
+ // However, we DO block specific dangerous process properties.
60
+ {
61
+ prop: "env",
62
+ target: process,
63
+ violationType: "process_env",
64
+ strategy: "throw",
65
+ reason: "process.env could leak sensitive environment variables",
66
+ // Node.js internals and bundled dependencies read these env vars
67
+ // during module loading, file watching, and I/O within the
68
+ // AsyncLocalStorage context. None are user secrets.
69
+ allowedKeys: /* @__PURE__ */ new Set([
70
+ // Node.js core
71
+ "NODE_V8_COVERAGE",
72
+ "NODE_DEBUG",
73
+ "NODE_DEBUG_NATIVE",
74
+ "NODE_COMPILE_CACHE",
75
+ "WATCH_REPORT_DEPENDENCIES",
76
+ // Dependencies
77
+ "FORCE_COLOR",
78
+ // chalk/supports-color
79
+ "DEBUG",
80
+ // debug package
81
+ "UNDICI_NO_FG",
82
+ // undici (Node.js fetch)
83
+ "JEST_WORKER_ID",
84
+ // jest/vitest worker detection
85
+ "__MINIMATCH_TESTING_PLATFORM__",
86
+ // minimatch
87
+ "LOG_TOKENS",
88
+ // query engine debug logging
89
+ "LOG_STREAM"
90
+ // query engine debug logging
91
+ ])
92
+ },
93
+ {
94
+ prop: "binding",
95
+ target: process,
96
+ violationType: "process_binding",
97
+ strategy: "throw",
98
+ reason: "process.binding provides access to native Node.js modules"
99
+ },
100
+ {
101
+ prop: "_linkedBinding",
102
+ target: process,
103
+ violationType: "process_binding",
104
+ strategy: "throw",
105
+ reason: "process._linkedBinding provides access to native Node.js modules"
106
+ },
107
+ {
108
+ prop: "dlopen",
109
+ target: process,
110
+ violationType: "process_dlopen",
111
+ strategy: "throw",
112
+ reason: "process.dlopen allows loading native addons"
113
+ },
114
+ {
115
+ prop: "getBuiltinModule",
116
+ target: process,
117
+ violationType: "process_get_builtin_module",
118
+ strategy: "throw",
119
+ reason: "process.getBuiltinModule allows loading native Node.js modules (fs, child_process, vm)"
120
+ },
121
+ // Note: process.mainModule is handled specially in defense-in-depth-box.ts
122
+ // and worker-defense-in-depth.ts because it may be undefined in ESM contexts
123
+ // but we still want to block both reading and setting it.
124
+ // Process control vectors
125
+ {
126
+ prop: "exit",
127
+ target: process,
128
+ violationType: "process_exit",
129
+ strategy: "throw",
130
+ reason: "process.exit could terminate the interpreter"
131
+ },
132
+ {
133
+ prop: "abort",
134
+ target: process,
135
+ violationType: "process_exit",
136
+ strategy: "throw",
137
+ reason: "process.abort could crash the interpreter"
138
+ },
139
+ {
140
+ prop: "kill",
141
+ target: process,
142
+ violationType: "process_kill",
143
+ strategy: "throw",
144
+ reason: "process.kill could signal other processes"
145
+ },
146
+ // Privilege escalation vectors
147
+ {
148
+ prop: "setuid",
149
+ target: process,
150
+ violationType: "process_setuid",
151
+ strategy: "throw",
152
+ reason: "process.setuid could escalate privileges"
153
+ },
154
+ {
155
+ prop: "setgid",
156
+ target: process,
157
+ violationType: "process_setuid",
158
+ strategy: "throw",
159
+ reason: "process.setgid could escalate privileges"
160
+ },
161
+ {
162
+ prop: "seteuid",
163
+ target: process,
164
+ violationType: "process_setuid",
165
+ strategy: "throw",
166
+ reason: "process.seteuid could escalate effective user privileges"
167
+ },
168
+ {
169
+ prop: "setegid",
170
+ target: process,
171
+ violationType: "process_setuid",
172
+ strategy: "throw",
173
+ reason: "process.setegid could escalate effective group privileges"
174
+ },
175
+ {
176
+ prop: "initgroups",
177
+ target: process,
178
+ violationType: "process_setuid",
179
+ strategy: "throw",
180
+ reason: "process.initgroups could modify supplementary group IDs"
181
+ },
182
+ {
183
+ prop: "setgroups",
184
+ target: process,
185
+ violationType: "process_setuid",
186
+ strategy: "throw",
187
+ reason: "process.setgroups could modify supplementary group IDs"
188
+ },
189
+ // File permission manipulation
190
+ {
191
+ prop: "umask",
192
+ target: process,
193
+ violationType: "process_umask",
194
+ strategy: "throw",
195
+ reason: "process.umask could modify file creation permissions"
196
+ },
197
+ // Information disclosure vectors
198
+ // Note: process.argv is an array (object) so gets an object proxy
199
+ {
200
+ prop: "argv",
201
+ target: process,
202
+ violationType: "process_argv",
203
+ strategy: "throw",
204
+ reason: "process.argv may contain secrets in CLI arguments"
205
+ },
206
+ // Note: process.execPath is a string primitive, handled specially
207
+ // in defense-in-depth-box.ts and worker-defense-in-depth.ts
208
+ // Note: process.connected is a boolean primitive, handled specially
209
+ // in defense-in-depth-box.ts and worker-defense-in-depth.ts
210
+ // Working directory access/manipulation
211
+ {
212
+ prop: "cwd",
213
+ target: process,
214
+ violationType: "process_chdir",
215
+ strategy: "throw",
216
+ reason: "process.cwd could disclose real host working directory path"
217
+ },
218
+ {
219
+ prop: "chdir",
220
+ target: process,
221
+ violationType: "process_chdir",
222
+ strategy: "throw",
223
+ reason: "process.chdir could confuse the interpreter's CWD tracking"
224
+ },
225
+ // Diagnostic report (leaks full environment, host paths, system info)
226
+ {
227
+ prop: "report",
228
+ target: process,
229
+ violationType: "process_report",
230
+ strategy: "throw",
231
+ reason: "process.report could disclose full environment, host paths, and system info"
232
+ },
233
+ // Environment file loading (Node 21.7+)
234
+ {
235
+ prop: "loadEnvFile",
236
+ target: process,
237
+ violationType: "process_env",
238
+ strategy: "throw",
239
+ reason: "process.loadEnvFile could load env files bypassing env proxy"
240
+ },
241
+ // Exception handler manipulation
242
+ {
243
+ prop: "setUncaughtExceptionCaptureCallback",
244
+ target: process,
245
+ violationType: "process_exception_handler",
246
+ strategy: "throw",
247
+ reason: "setUncaughtExceptionCaptureCallback could intercept security errors"
248
+ },
249
+ // IPC communication vectors (may be undefined in non-IPC contexts)
250
+ {
251
+ prop: "send",
252
+ target: process,
253
+ violationType: "process_send",
254
+ strategy: "throw",
255
+ reason: "process.send could communicate with parent process in IPC contexts"
256
+ },
257
+ {
258
+ prop: "channel",
259
+ target: process,
260
+ violationType: "process_channel",
261
+ strategy: "throw",
262
+ reason: "process.channel could access IPC channel to parent process"
263
+ },
264
+ // Timing side-channel vectors
265
+ {
266
+ prop: "cpuUsage",
267
+ target: process,
268
+ violationType: "process_timing",
269
+ strategy: "throw",
270
+ reason: "process.cpuUsage could enable timing side-channel attacks"
271
+ },
272
+ {
273
+ prop: "memoryUsage",
274
+ target: process,
275
+ violationType: "process_timing",
276
+ strategy: "throw",
277
+ reason: "process.memoryUsage could enable timing side-channel attacks"
278
+ },
279
+ {
280
+ prop: "hrtime",
281
+ target: process,
282
+ violationType: "process_timing",
283
+ strategy: "throw",
284
+ reason: "process.hrtime could enable timing side-channel attacks"
285
+ },
286
+ // We also don't block `require` because:
287
+ // 1. It may not exist in all environments (ESM)
288
+ // 2. import() is the modern escape vector and can't be blocked this way
289
+ // Reference leak vectors
290
+ {
291
+ prop: "WeakRef",
292
+ target: globalThis,
293
+ violationType: "weak_ref",
294
+ strategy: "throw",
295
+ reason: "WeakRef could be used to leak references outside sandbox"
296
+ },
297
+ {
298
+ prop: "FinalizationRegistry",
299
+ target: globalThis,
300
+ violationType: "finalization_registry",
301
+ strategy: "throw",
302
+ reason: "FinalizationRegistry could be used to leak references outside sandbox"
303
+ },
304
+ // Introspection/interception vectors (freeze instead of throw)
305
+ // SECURITY RATIONALE: Reflect is frozen (not blocked) because:
306
+ // 1. Defense infrastructure uses Reflect.apply/get/set/construct internally
307
+ // 2. Frozen Reflect cannot be mutated but remains fully functional
308
+ // 3. Reflect.construct(Function, ['code']) IS safe because globalThis.Function
309
+ // is replaced with a blocking proxy — Reflect.construct receives the proxy
310
+ // 4. Security depends on NEVER leaking original Function/eval references.
311
+ // If an unpatched Function ref leaked, Reflect.construct would bypass defense.
312
+ {
313
+ prop: "Reflect",
314
+ target: globalThis,
315
+ violationType: "reflect",
316
+ strategy: "freeze",
317
+ reason: "Reflect provides introspection capabilities"
318
+ },
319
+ {
320
+ prop: "Proxy",
321
+ target: globalThis,
322
+ violationType: "proxy",
323
+ strategy: "throw",
324
+ reason: "Proxy allows intercepting and modifying object behavior"
325
+ },
326
+ // WebAssembly allows arbitrary code execution
327
+ {
328
+ prop: "WebAssembly",
329
+ target: globalThis,
330
+ violationType: "webassembly",
331
+ strategy: "throw",
332
+ reason: "WebAssembly allows executing arbitrary compiled code"
333
+ },
334
+ // SharedArrayBuffer and Atomics can enable side-channel attacks
335
+ {
336
+ prop: "SharedArrayBuffer",
337
+ target: globalThis,
338
+ violationType: "shared_array_buffer",
339
+ strategy: "throw",
340
+ reason: "SharedArrayBuffer could enable side-channel communication or timing attacks"
341
+ },
342
+ {
343
+ prop: "Atomics",
344
+ target: globalThis,
345
+ violationType: "atomics",
346
+ strategy: "throw",
347
+ reason: "Atomics could enable side-channel communication or timing attacks"
348
+ },
349
+ // Note: Error.prepareStackTrace is handled specially in defense-in-depth-box.ts
350
+ // because we only want to block SETTING it, not reading (V8 reads it internally)
351
+ // Timing side-channel: performance.now() provides sub-millisecond resolution
352
+ // Note: Date.now() is intentionally NOT blocked — it's used for $SECONDS,
353
+ // date command, and has only ~1ms resolution (vs process.hrtime at ns).
354
+ {
355
+ prop: "performance",
356
+ target: globalThis,
357
+ violationType: "performance_timing",
358
+ strategy: "throw",
359
+ reason: "performance.now() provides sub-millisecond timing for side-channel attacks"
360
+ },
361
+ // Block direct access to process.stdout and process.stderr to prevent
362
+ // writing to the host's actual stdout/stderr, bypassing the interpreter's
363
+ // output accumulation.
364
+ {
365
+ prop: "stdout",
366
+ target: process,
367
+ violationType: "process_stdout",
368
+ strategy: "throw",
369
+ reason: "process.stdout could bypass interpreter output to write to host stdout"
370
+ },
371
+ {
372
+ prop: "stderr",
373
+ target: process,
374
+ violationType: "process_stderr",
375
+ strategy: "throw",
376
+ reason: "process.stderr could bypass interpreter output to write to host stderr"
377
+ },
378
+ // Prototype pollution vectors
379
+ {
380
+ prop: "__defineGetter__",
381
+ target: Object.prototype,
382
+ violationType: "prototype_mutation",
383
+ strategy: "throw",
384
+ reason: "__defineGetter__ allows prototype pollution via getter injection"
385
+ },
386
+ {
387
+ prop: "__defineSetter__",
388
+ target: Object.prototype,
389
+ violationType: "prototype_mutation",
390
+ strategy: "throw",
391
+ reason: "__defineSetter__ allows prototype pollution via setter injection"
392
+ },
393
+ {
394
+ prop: "__lookupGetter__",
395
+ target: Object.prototype,
396
+ violationType: "prototype_mutation",
397
+ strategy: "throw",
398
+ reason: "__lookupGetter__ enables introspection for prototype pollution attacks"
399
+ },
400
+ {
401
+ prop: "__lookupSetter__",
402
+ target: Object.prototype,
403
+ violationType: "prototype_mutation",
404
+ strategy: "throw",
405
+ reason: "__lookupSetter__ enables introspection for prototype pollution attacks"
406
+ },
407
+ // Freeze JSON and Math to prevent mutation of built-in utility objects
408
+ {
409
+ prop: "JSON",
410
+ target: globalThis,
411
+ violationType: "json_mutation",
412
+ strategy: "freeze",
413
+ reason: "Freeze JSON to prevent mutation of parsing/serialization"
414
+ },
415
+ {
416
+ prop: "Math",
417
+ target: globalThis,
418
+ violationType: "math_mutation",
419
+ strategy: "freeze",
420
+ reason: "Freeze Math to prevent mutation of math utilities"
421
+ }
422
+ ];
423
+ try {
424
+ const AsyncFunction = Object.getPrototypeOf(async () => {
425
+ }).constructor;
426
+ if (AsyncFunction && AsyncFunction !== Function) {
427
+ globals.push({
428
+ prop: "constructor",
429
+ target: Object.getPrototypeOf(async () => {
430
+ }),
431
+ violationType: "async_function_constructor",
432
+ strategy: "throw",
433
+ reason: "AsyncFunction constructor allows arbitrary async code execution"
434
+ });
435
+ }
436
+ } catch {
437
+ }
438
+ try {
439
+ const GeneratorFunction = Object.getPrototypeOf(
440
+ function* () {
441
+ }
442
+ ).constructor;
443
+ if (GeneratorFunction && GeneratorFunction !== Function) {
444
+ globals.push({
445
+ prop: "constructor",
446
+ target: Object.getPrototypeOf(function* () {
447
+ }),
448
+ violationType: "generator_function_constructor",
449
+ strategy: "throw",
450
+ reason: "GeneratorFunction constructor allows arbitrary generator code execution"
451
+ });
452
+ }
453
+ } catch {
454
+ }
455
+ try {
456
+ const AsyncGeneratorFunction = Object.getPrototypeOf(
457
+ async function* () {
458
+ }
459
+ ).constructor;
460
+ if (AsyncGeneratorFunction && AsyncGeneratorFunction !== Function && AsyncGeneratorFunction !== Object.getPrototypeOf(async () => {
461
+ }).constructor) {
462
+ globals.push({
463
+ prop: "constructor",
464
+ target: Object.getPrototypeOf(async function* () {
465
+ }),
466
+ violationType: "async_generator_function_constructor",
467
+ strategy: "throw",
468
+ reason: "AsyncGeneratorFunction constructor allows arbitrary async generator code execution"
469
+ });
470
+ }
471
+ } catch {
472
+ }
473
+ return globals.filter((g) => {
474
+ try {
475
+ return g.target[g.prop] !== void 0;
476
+ } catch {
477
+ return false;
478
+ }
479
+ });
480
+ }
481
+
482
+ // src/security/defense-in-depth-box.ts
483
+ var IS_BROWSER = typeof __BROWSER__ !== "undefined" && __BROWSER__;
484
+ var AsyncLocalStorageClass = null;
485
+ if (!IS_BROWSER) {
486
+ try {
487
+ const { AsyncLocalStorage } = __require("node:async_hooks");
488
+ AsyncLocalStorageClass = AsyncLocalStorage;
489
+ } catch {
490
+ }
491
+ }
492
+ var executionContext = !IS_BROWSER && AsyncLocalStorageClass ? new AsyncLocalStorageClass() : null;
493
+
494
+ // src/security/worker-defense-in-depth.ts
495
+ var DEFENSE_IN_DEPTH_NOTICE = "\n\nThis is a defense-in-depth measure and indicates a bug in just-bash. Please report this at security@vercel.com";
496
+ var WorkerSecurityViolationError = class extends Error {
497
+ constructor(message, violation) {
498
+ super(message + DEFENSE_IN_DEPTH_NOTICE);
499
+ this.violation = violation;
500
+ this.name = "WorkerSecurityViolationError";
501
+ }
502
+ };
503
+ var MAX_STORED_VIOLATIONS = 1e3;
504
+ function generateExecutionId() {
505
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
506
+ return crypto.randomUUID();
507
+ }
508
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
509
+ const r = Math.random() * 16 | 0;
510
+ const v = c === "x" ? r : r & 3 | 8;
511
+ return v.toString(16);
512
+ });
513
+ }
514
+ var WorkerDefenseInDepth = class {
515
+ config;
516
+ isActivated = false;
517
+ originalDescriptors = [];
518
+ violations = [];
519
+ executionId;
520
+ /**
521
+ * Original Proxy constructor, captured before patching.
522
+ * This is captured at instance creation time to ensure we get the unpatched version.
523
+ */
524
+ originalProxy;
525
+ /**
526
+ * Recursion guard to prevent infinite loops when proxy traps trigger
527
+ * code that accesses the same proxied object (e.g., process.env).
528
+ */
529
+ inTrap = false;
530
+ /**
531
+ * Create and activate the worker defense layer.
532
+ *
533
+ * @param config - Configuration for the defense layer
534
+ */
535
+ constructor(config) {
536
+ this.originalProxy = Proxy;
537
+ this.config = config;
538
+ this.executionId = generateExecutionId();
539
+ if (config.enabled !== false) {
540
+ this.activate();
541
+ }
542
+ }
543
+ /**
544
+ * Get statistics about the defense layer.
545
+ */
546
+ getStats() {
547
+ return {
548
+ violationsBlocked: this.violations.length,
549
+ violations: [...this.violations],
550
+ isActive: this.isActivated
551
+ };
552
+ }
553
+ /**
554
+ * Clear stored violations. Useful for testing.
555
+ */
556
+ clearViolations() {
557
+ this.violations = [];
558
+ }
559
+ /**
560
+ * Get the execution ID for this worker.
561
+ */
562
+ getExecutionId() {
563
+ return this.executionId;
564
+ }
565
+ /**
566
+ * Deactivate the defense layer and restore original globals.
567
+ * Typically only needed for testing.
568
+ */
569
+ deactivate() {
570
+ if (!this.isActivated) {
571
+ return;
572
+ }
573
+ this.restorePatches();
574
+ this.isActivated = false;
575
+ }
576
+ /**
577
+ * Activate the defense layer by applying patches.
578
+ */
579
+ activate() {
580
+ if (this.isActivated) {
581
+ return;
582
+ }
583
+ this.applyPatches();
584
+ this.isActivated = true;
585
+ }
586
+ /**
587
+ * Get a human-readable path for a target object and property.
588
+ */
589
+ getPathForTarget(target, prop) {
590
+ if (target === globalThis) {
591
+ return `globalThis.${prop}`;
592
+ }
593
+ if (typeof process !== "undefined" && target === process) {
594
+ return `process.${prop}`;
595
+ }
596
+ if (target === Error) {
597
+ return `Error.${prop}`;
598
+ }
599
+ if (target === Function.prototype) {
600
+ return `Function.prototype.${prop}`;
601
+ }
602
+ if (target === Object.prototype) {
603
+ return `Object.prototype.${prop}`;
604
+ }
605
+ return `<object>.${prop}`;
606
+ }
607
+ /**
608
+ * Record a violation and invoke the callback.
609
+ * In worker context, blocking always happens (no audit mode context check).
610
+ */
611
+ recordViolation(type, path, message) {
612
+ const violation = {
613
+ timestamp: Date.now(),
614
+ type,
615
+ message,
616
+ path,
617
+ stack: new Error().stack,
618
+ executionId: this.executionId
619
+ };
620
+ if (this.violations.length < MAX_STORED_VIOLATIONS) {
621
+ this.violations.push(violation);
622
+ }
623
+ if (this.config.onViolation) {
624
+ try {
625
+ this.config.onViolation(violation);
626
+ } catch (e) {
627
+ console.debug(
628
+ "[WorkerDefenseInDepth] onViolation callback threw:",
629
+ e instanceof Error ? e.message : e
630
+ );
631
+ }
632
+ }
633
+ return violation;
634
+ }
635
+ /**
636
+ * Create a blocking proxy for a function.
637
+ * In worker context, always blocks (no context check needed).
638
+ */
639
+ createBlockingProxy(original, path, violationType) {
640
+ const self = this;
641
+ const auditMode = this.config.auditMode;
642
+ return new this.originalProxy(original, {
643
+ apply(target, thisArg, args) {
644
+ const message = `${path} is blocked in worker context`;
645
+ const violation = self.recordViolation(violationType, path, message);
646
+ if (!auditMode) {
647
+ throw new WorkerSecurityViolationError(message, violation);
648
+ }
649
+ return Reflect.apply(target, thisArg, args);
650
+ },
651
+ construct(target, args, newTarget) {
652
+ const message = `${path} constructor is blocked in worker context`;
653
+ const violation = self.recordViolation(violationType, path, message);
654
+ if (!auditMode) {
655
+ throw new WorkerSecurityViolationError(message, violation);
656
+ }
657
+ return Reflect.construct(target, args, newTarget);
658
+ }
659
+ });
660
+ }
661
+ /**
662
+ * Create a blocking proxy for an object (blocks all property access).
663
+ */
664
+ createBlockingObjectProxy(original, path, violationType, allowedKeys) {
665
+ const self = this;
666
+ const auditMode = this.config.auditMode;
667
+ return new this.originalProxy(original, {
668
+ get(target, prop, receiver) {
669
+ if (self.inTrap) {
670
+ return Reflect.get(target, prop, receiver);
671
+ }
672
+ if (allowedKeys && typeof prop === "string" && allowedKeys.has(prop)) {
673
+ return Reflect.get(target, prop, receiver);
674
+ }
675
+ self.inTrap = true;
676
+ try {
677
+ const fullPath = `${path}.${String(prop)}`;
678
+ const message = `${fullPath} is blocked in worker context`;
679
+ const violation = self.recordViolation(
680
+ violationType,
681
+ fullPath,
682
+ message
683
+ );
684
+ if (!auditMode) {
685
+ throw new WorkerSecurityViolationError(message, violation);
686
+ }
687
+ return Reflect.get(target, prop, receiver);
688
+ } finally {
689
+ self.inTrap = false;
690
+ }
691
+ },
692
+ set(target, prop, value, receiver) {
693
+ if (self.inTrap) {
694
+ return Reflect.set(target, prop, value, receiver);
695
+ }
696
+ self.inTrap = true;
697
+ try {
698
+ const fullPath = `${path}.${String(prop)}`;
699
+ const message = `${fullPath} modification is blocked in worker context`;
700
+ const violation = self.recordViolation(
701
+ violationType,
702
+ fullPath,
703
+ message
704
+ );
705
+ if (!auditMode) {
706
+ throw new WorkerSecurityViolationError(message, violation);
707
+ }
708
+ return Reflect.set(target, prop, value, receiver);
709
+ } finally {
710
+ self.inTrap = false;
711
+ }
712
+ },
713
+ ownKeys(target) {
714
+ if (self.inTrap) {
715
+ return Reflect.ownKeys(target);
716
+ }
717
+ self.inTrap = true;
718
+ try {
719
+ const message = `${path} enumeration is blocked in worker context`;
720
+ const violation = self.recordViolation(violationType, path, message);
721
+ if (!auditMode) {
722
+ throw new WorkerSecurityViolationError(message, violation);
723
+ }
724
+ return Reflect.ownKeys(target);
725
+ } finally {
726
+ self.inTrap = false;
727
+ }
728
+ },
729
+ getOwnPropertyDescriptor(target, prop) {
730
+ if (self.inTrap) {
731
+ return Reflect.getOwnPropertyDescriptor(target, prop);
732
+ }
733
+ self.inTrap = true;
734
+ try {
735
+ const fullPath = `${path}.${String(prop)}`;
736
+ const message = `${fullPath} descriptor access is blocked in worker context`;
737
+ const violation = self.recordViolation(
738
+ violationType,
739
+ fullPath,
740
+ message
741
+ );
742
+ if (!auditMode) {
743
+ throw new WorkerSecurityViolationError(message, violation);
744
+ }
745
+ return Reflect.getOwnPropertyDescriptor(target, prop);
746
+ } finally {
747
+ self.inTrap = false;
748
+ }
749
+ },
750
+ has(target, prop) {
751
+ if (self.inTrap) {
752
+ return Reflect.has(target, prop);
753
+ }
754
+ self.inTrap = true;
755
+ try {
756
+ const fullPath = `${path}.${String(prop)}`;
757
+ const message = `${fullPath} existence check is blocked in worker context`;
758
+ const violation = self.recordViolation(
759
+ violationType,
760
+ fullPath,
761
+ message
762
+ );
763
+ if (!auditMode) {
764
+ throw new WorkerSecurityViolationError(message, violation);
765
+ }
766
+ return Reflect.has(target, prop);
767
+ } finally {
768
+ self.inTrap = false;
769
+ }
770
+ },
771
+ deleteProperty(target, prop) {
772
+ if (self.inTrap) {
773
+ return Reflect.deleteProperty(target, prop);
774
+ }
775
+ self.inTrap = true;
776
+ try {
777
+ const fullPath = `${path}.${String(prop)}`;
778
+ const message = `${fullPath} deletion is blocked in worker context`;
779
+ const violation = self.recordViolation(
780
+ violationType,
781
+ fullPath,
782
+ message
783
+ );
784
+ if (!auditMode) {
785
+ throw new WorkerSecurityViolationError(message, violation);
786
+ }
787
+ return Reflect.deleteProperty(target, prop);
788
+ } finally {
789
+ self.inTrap = false;
790
+ }
791
+ },
792
+ setPrototypeOf(target, proto) {
793
+ if (self.inTrap) {
794
+ return Reflect.setPrototypeOf(target, proto);
795
+ }
796
+ self.inTrap = true;
797
+ try {
798
+ const message = `${path} setPrototypeOf is blocked in worker context`;
799
+ const violation = self.recordViolation(violationType, path, message);
800
+ if (!auditMode) {
801
+ throw new WorkerSecurityViolationError(message, violation);
802
+ }
803
+ return Reflect.setPrototypeOf(target, proto);
804
+ } finally {
805
+ self.inTrap = false;
806
+ }
807
+ },
808
+ defineProperty(target, prop, descriptor) {
809
+ if (self.inTrap) {
810
+ return Reflect.defineProperty(target, prop, descriptor);
811
+ }
812
+ self.inTrap = true;
813
+ try {
814
+ const fullPath = `${path}.${String(prop)}`;
815
+ const message = `${fullPath} defineProperty is blocked in worker context`;
816
+ const violation = self.recordViolation(
817
+ violationType,
818
+ fullPath,
819
+ message
820
+ );
821
+ if (!auditMode) {
822
+ throw new WorkerSecurityViolationError(message, violation);
823
+ }
824
+ return Reflect.defineProperty(target, prop, descriptor);
825
+ } finally {
826
+ self.inTrap = false;
827
+ }
828
+ }
829
+ });
830
+ }
831
+ /**
832
+ * Apply security patches to dangerous globals.
833
+ */
834
+ applyPatches() {
835
+ const blockedGlobals = getBlockedGlobals();
836
+ const excludeTypes = new Set(this.config.excludeViolationTypes ?? []);
837
+ for (const blocked of blockedGlobals) {
838
+ if (excludeTypes.has(blocked.violationType)) {
839
+ continue;
840
+ }
841
+ this.applyPatch(blocked);
842
+ }
843
+ if (!excludeTypes.has("function_constructor")) {
844
+ this.protectConstructorChain(excludeTypes);
845
+ }
846
+ if (!excludeTypes.has("error_prepare_stack_trace")) {
847
+ this.protectErrorPrepareStackTrace();
848
+ }
849
+ if (!excludeTypes.has("module_load")) {
850
+ this.protectModuleLoad();
851
+ }
852
+ if (!excludeTypes.has("module_resolve_filename")) {
853
+ this.protectModuleResolveFilename();
854
+ }
855
+ if (!excludeTypes.has("process_main_module")) {
856
+ this.protectProcessMainModule();
857
+ }
858
+ if (!excludeTypes.has("process_exec_path")) {
859
+ this.protectProcessExecPath();
860
+ }
861
+ if (!excludeTypes.has("process_connected")) {
862
+ this.protectProcessConnected();
863
+ }
864
+ this.lockWellKnownSymbols();
865
+ if (!excludeTypes.has("proxy")) {
866
+ this.protectProxyRevocable();
867
+ }
868
+ }
869
+ /**
870
+ * Lock well-known Symbol properties on built-in constructors/prototypes.
871
+ */
872
+ lockWellKnownSymbols() {
873
+ const lock = (obj, sym) => {
874
+ try {
875
+ const desc = Object.getOwnPropertyDescriptor(obj, sym);
876
+ if (desc?.configurable) {
877
+ if ("value" in desc) {
878
+ Object.defineProperty(obj, sym, {
879
+ ...desc,
880
+ configurable: false,
881
+ writable: false
882
+ });
883
+ return;
884
+ }
885
+ Object.defineProperty(obj, sym, { ...desc, configurable: false });
886
+ }
887
+ } catch {
888
+ }
889
+ };
890
+ for (const ctor of [Array, Map, Set, RegExp, Promise]) {
891
+ lock(ctor, Symbol.species);
892
+ }
893
+ for (const proto of [
894
+ Array.prototype,
895
+ String.prototype,
896
+ Map.prototype,
897
+ Set.prototype
898
+ ]) {
899
+ lock(proto, Symbol.iterator);
900
+ }
901
+ lock(Symbol.prototype, Symbol.toPrimitive);
902
+ lock(Date.prototype, Symbol.toPrimitive);
903
+ for (const sym of [
904
+ Symbol.match,
905
+ Symbol.matchAll,
906
+ Symbol.replace,
907
+ Symbol.search,
908
+ Symbol.split
909
+ ]) {
910
+ lock(RegExp.prototype, sym);
911
+ }
912
+ lock(Function.prototype, Symbol.hasInstance);
913
+ lock(Array.prototype, Symbol.unscopables);
914
+ for (const proto of [
915
+ Map.prototype,
916
+ Set.prototype,
917
+ Promise.prototype,
918
+ ArrayBuffer.prototype
919
+ ]) {
920
+ lock(proto, Symbol.toStringTag);
921
+ }
922
+ try {
923
+ const stackDesc = Object.getOwnPropertyDescriptor(
924
+ Error,
925
+ "stackTraceLimit"
926
+ );
927
+ this.originalDescriptors.push({
928
+ target: Error,
929
+ prop: "stackTraceLimit",
930
+ descriptor: stackDesc
931
+ });
932
+ Object.defineProperty(Error, "stackTraceLimit", {
933
+ value: Error.stackTraceLimit,
934
+ writable: false,
935
+ configurable: true
936
+ });
937
+ } catch {
938
+ }
939
+ }
940
+ /**
941
+ * Block Proxy.revocable to prevent bypassing Proxy constructor blocking.
942
+ *
943
+ * Proxy.revocable internally uses the real Proxy constructor, so it bypasses
944
+ * our blocking proxy on globalThis.Proxy. We replace it with a wrapper that
945
+ * always blocks in worker context.
946
+ */
947
+ protectProxyRevocable() {
948
+ const self = this;
949
+ const auditMode = this.config.auditMode;
950
+ try {
951
+ const originalRevocable = this.originalProxy.revocable;
952
+ if (typeof originalRevocable !== "function") return;
953
+ const descriptor = Object.getOwnPropertyDescriptor(
954
+ this.originalProxy,
955
+ "revocable"
956
+ );
957
+ this.originalDescriptors.push({
958
+ target: this.originalProxy,
959
+ prop: "revocable",
960
+ descriptor
961
+ });
962
+ Object.defineProperty(this.originalProxy, "revocable", {
963
+ value: function revocable(_target, _handler) {
964
+ const message = "Proxy.revocable is blocked in worker context";
965
+ const violation = self.recordViolation(
966
+ "proxy",
967
+ "Proxy.revocable",
968
+ message
969
+ );
970
+ if (!auditMode) {
971
+ throw new WorkerSecurityViolationError(message, violation);
972
+ }
973
+ return originalRevocable(_target, _handler);
974
+ },
975
+ writable: false,
976
+ configurable: true
977
+ // Must be configurable for restoration
978
+ });
979
+ } catch {
980
+ }
981
+ }
982
+ /**
983
+ * Protect against .constructor.constructor escape vector.
984
+ * @param excludeTypes - Set of violation types to skip
985
+ */
986
+ protectConstructorChain(excludeTypes) {
987
+ let AsyncFunction = null;
988
+ let GeneratorFunction = null;
989
+ let AsyncGeneratorFunction = null;
990
+ try {
991
+ AsyncFunction = Object.getPrototypeOf(async () => {
992
+ }).constructor;
993
+ } catch {
994
+ }
995
+ try {
996
+ GeneratorFunction = Object.getPrototypeOf(function* () {
997
+ }).constructor;
998
+ } catch {
999
+ }
1000
+ try {
1001
+ AsyncGeneratorFunction = Object.getPrototypeOf(
1002
+ async function* () {
1003
+ }
1004
+ ).constructor;
1005
+ } catch {
1006
+ }
1007
+ this.patchPrototypeConstructor(
1008
+ Function.prototype,
1009
+ "Function.prototype.constructor",
1010
+ "function_constructor"
1011
+ );
1012
+ if (!excludeTypes.has("async_function_constructor") && AsyncFunction && AsyncFunction !== Function) {
1013
+ this.patchPrototypeConstructor(
1014
+ AsyncFunction.prototype,
1015
+ "AsyncFunction.prototype.constructor",
1016
+ "async_function_constructor"
1017
+ );
1018
+ }
1019
+ if (!excludeTypes.has("generator_function_constructor") && GeneratorFunction && GeneratorFunction !== Function) {
1020
+ this.patchPrototypeConstructor(
1021
+ GeneratorFunction.prototype,
1022
+ "GeneratorFunction.prototype.constructor",
1023
+ "generator_function_constructor"
1024
+ );
1025
+ }
1026
+ if (!excludeTypes.has("async_generator_function_constructor") && AsyncGeneratorFunction && AsyncGeneratorFunction !== Function && AsyncGeneratorFunction !== AsyncFunction) {
1027
+ this.patchPrototypeConstructor(
1028
+ AsyncGeneratorFunction.prototype,
1029
+ "AsyncGeneratorFunction.prototype.constructor",
1030
+ "async_generator_function_constructor"
1031
+ );
1032
+ }
1033
+ }
1034
+ /**
1035
+ * Protect Error.prepareStackTrace from being set.
1036
+ */
1037
+ protectErrorPrepareStackTrace() {
1038
+ const self = this;
1039
+ const auditMode = this.config.auditMode;
1040
+ try {
1041
+ const originalDescriptor = Object.getOwnPropertyDescriptor(
1042
+ Error,
1043
+ "prepareStackTrace"
1044
+ );
1045
+ this.originalDescriptors.push({
1046
+ target: Error,
1047
+ prop: "prepareStackTrace",
1048
+ descriptor: originalDescriptor
1049
+ });
1050
+ let currentValue = originalDescriptor?.value;
1051
+ Object.defineProperty(Error, "prepareStackTrace", {
1052
+ get() {
1053
+ return currentValue;
1054
+ },
1055
+ set(value) {
1056
+ const message = "Error.prepareStackTrace modification is blocked in worker context";
1057
+ const violation = self.recordViolation(
1058
+ "error_prepare_stack_trace",
1059
+ "Error.prepareStackTrace",
1060
+ message
1061
+ );
1062
+ if (!auditMode) {
1063
+ throw new WorkerSecurityViolationError(message, violation);
1064
+ }
1065
+ currentValue = value;
1066
+ },
1067
+ configurable: true
1068
+ });
1069
+ } catch {
1070
+ }
1071
+ }
1072
+ /**
1073
+ * Patch a prototype's constructor property.
1074
+ *
1075
+ * Returns a proxy that allows reading properties (like .name) but blocks
1076
+ * calling the constructor as a function (which would allow code execution).
1077
+ */
1078
+ patchPrototypeConstructor(prototype, path, violationType) {
1079
+ const self = this;
1080
+ const auditMode = this.config.auditMode;
1081
+ try {
1082
+ const originalDescriptor = Object.getOwnPropertyDescriptor(
1083
+ prototype,
1084
+ "constructor"
1085
+ );
1086
+ this.originalDescriptors.push({
1087
+ target: prototype,
1088
+ prop: "constructor",
1089
+ descriptor: originalDescriptor
1090
+ });
1091
+ const originalValue = originalDescriptor?.value;
1092
+ const constructorProxy = originalValue && typeof originalValue === "function" ? new this.originalProxy(originalValue, {
1093
+ apply(_target, _thisArg, _args) {
1094
+ const message = `${path} invocation is blocked in worker context`;
1095
+ const violation = self.recordViolation(
1096
+ violationType,
1097
+ path,
1098
+ message
1099
+ );
1100
+ if (!auditMode) {
1101
+ throw new WorkerSecurityViolationError(message, violation);
1102
+ }
1103
+ return void 0;
1104
+ },
1105
+ construct(_target, _args, _newTarget) {
1106
+ const message = `${path} construction is blocked in worker context`;
1107
+ const violation = self.recordViolation(
1108
+ violationType,
1109
+ path,
1110
+ message
1111
+ );
1112
+ if (!auditMode) {
1113
+ throw new WorkerSecurityViolationError(message, violation);
1114
+ }
1115
+ return {};
1116
+ },
1117
+ // Allow all property access (like .name, .prototype, etc.)
1118
+ get(target, prop, receiver) {
1119
+ return Reflect.get(target, prop, receiver);
1120
+ },
1121
+ getPrototypeOf(target) {
1122
+ return Reflect.getPrototypeOf(target);
1123
+ },
1124
+ has(target, prop) {
1125
+ return Reflect.has(target, prop);
1126
+ },
1127
+ ownKeys(target) {
1128
+ return Reflect.ownKeys(target);
1129
+ },
1130
+ getOwnPropertyDescriptor(target, prop) {
1131
+ return Reflect.getOwnPropertyDescriptor(target, prop);
1132
+ }
1133
+ }) : originalValue;
1134
+ Object.defineProperty(prototype, "constructor", {
1135
+ get() {
1136
+ return constructorProxy;
1137
+ },
1138
+ set(value) {
1139
+ const message = `${path} modification is blocked in worker context`;
1140
+ const violation = self.recordViolation(violationType, path, message);
1141
+ if (!auditMode) {
1142
+ throw new WorkerSecurityViolationError(message, violation);
1143
+ }
1144
+ Object.defineProperty(this, "constructor", {
1145
+ value,
1146
+ writable: true,
1147
+ configurable: true
1148
+ });
1149
+ },
1150
+ configurable: true
1151
+ });
1152
+ } catch {
1153
+ }
1154
+ }
1155
+ /**
1156
+ * Protect process.mainModule from being accessed or set.
1157
+ *
1158
+ * The attack vector is:
1159
+ * ```
1160
+ * process.mainModule.require('child_process').execSync('whoami')
1161
+ * process.mainModule.constructor._load('vm')
1162
+ * ```
1163
+ *
1164
+ * process.mainModule may be undefined in ESM contexts but could exist in
1165
+ * CommonJS workers. We block both reading and setting.
1166
+ */
1167
+ protectProcessMainModule() {
1168
+ if (typeof process === "undefined") return;
1169
+ const self = this;
1170
+ const auditMode = this.config.auditMode;
1171
+ try {
1172
+ const originalDescriptor = Object.getOwnPropertyDescriptor(
1173
+ process,
1174
+ "mainModule"
1175
+ );
1176
+ this.originalDescriptors.push({
1177
+ target: process,
1178
+ prop: "mainModule",
1179
+ descriptor: originalDescriptor
1180
+ });
1181
+ const currentValue = originalDescriptor?.value;
1182
+ if (currentValue !== void 0) {
1183
+ Object.defineProperty(process, "mainModule", {
1184
+ get() {
1185
+ const message = "process.mainModule access is blocked in worker context";
1186
+ const violation = self.recordViolation(
1187
+ "process_main_module",
1188
+ "process.mainModule",
1189
+ message
1190
+ );
1191
+ if (!auditMode) {
1192
+ throw new WorkerSecurityViolationError(message, violation);
1193
+ }
1194
+ return currentValue;
1195
+ },
1196
+ set(value) {
1197
+ const message = "process.mainModule modification is blocked in worker context";
1198
+ const violation = self.recordViolation(
1199
+ "process_main_module",
1200
+ "process.mainModule",
1201
+ message
1202
+ );
1203
+ if (!auditMode) {
1204
+ throw new WorkerSecurityViolationError(message, violation);
1205
+ }
1206
+ Object.defineProperty(process, "mainModule", {
1207
+ value,
1208
+ writable: true,
1209
+ configurable: true
1210
+ });
1211
+ },
1212
+ configurable: true
1213
+ });
1214
+ }
1215
+ } catch {
1216
+ }
1217
+ }
1218
+ /**
1219
+ * Protect process.execPath from being read or set in worker context.
1220
+ *
1221
+ * process.execPath is a string primitive (not an object), so it cannot be
1222
+ * proxied via the normal blocked globals mechanism. We use Object.defineProperty
1223
+ * with getter/setter (same pattern as protectProcessMainModule).
1224
+ */
1225
+ protectProcessExecPath() {
1226
+ if (typeof process === "undefined") return;
1227
+ const self = this;
1228
+ const auditMode = this.config.auditMode;
1229
+ try {
1230
+ const originalDescriptor = Object.getOwnPropertyDescriptor(
1231
+ process,
1232
+ "execPath"
1233
+ );
1234
+ this.originalDescriptors.push({
1235
+ target: process,
1236
+ prop: "execPath",
1237
+ descriptor: originalDescriptor
1238
+ });
1239
+ const currentValue = originalDescriptor?.value ?? process.execPath;
1240
+ Object.defineProperty(process, "execPath", {
1241
+ get() {
1242
+ const message = "process.execPath access is blocked in worker context";
1243
+ const violation = self.recordViolation(
1244
+ "process_exec_path",
1245
+ "process.execPath",
1246
+ message
1247
+ );
1248
+ if (!auditMode) {
1249
+ throw new WorkerSecurityViolationError(message, violation);
1250
+ }
1251
+ return currentValue;
1252
+ },
1253
+ set(value) {
1254
+ const message = "process.execPath modification is blocked in worker context";
1255
+ const violation = self.recordViolation(
1256
+ "process_exec_path",
1257
+ "process.execPath",
1258
+ message
1259
+ );
1260
+ if (!auditMode) {
1261
+ throw new WorkerSecurityViolationError(message, violation);
1262
+ }
1263
+ Object.defineProperty(process, "execPath", {
1264
+ value,
1265
+ writable: true,
1266
+ configurable: true
1267
+ });
1268
+ },
1269
+ configurable: true
1270
+ });
1271
+ } catch {
1272
+ }
1273
+ }
1274
+ /**
1275
+ * Protect process.connected from being read or set in worker context.
1276
+ *
1277
+ * process.connected is a boolean primitive (not an object), so it cannot be
1278
+ * proxied via the normal blocked globals mechanism. We use Object.defineProperty
1279
+ * with getter/setter (same pattern as protectProcessExecPath).
1280
+ *
1281
+ * Only protects if process.connected exists (IPC contexts).
1282
+ */
1283
+ protectProcessConnected() {
1284
+ if (typeof process === "undefined") return;
1285
+ if (process.connected === void 0) return;
1286
+ const self = this;
1287
+ const auditMode = this.config.auditMode;
1288
+ try {
1289
+ const originalDescriptor = Object.getOwnPropertyDescriptor(
1290
+ process,
1291
+ "connected"
1292
+ );
1293
+ this.originalDescriptors.push({
1294
+ target: process,
1295
+ prop: "connected",
1296
+ descriptor: originalDescriptor
1297
+ });
1298
+ const currentValue = originalDescriptor?.value ?? process.connected;
1299
+ Object.defineProperty(process, "connected", {
1300
+ get() {
1301
+ const message = "process.connected access is blocked in worker context";
1302
+ const violation = self.recordViolation(
1303
+ "process_connected",
1304
+ "process.connected",
1305
+ message
1306
+ );
1307
+ if (!auditMode) {
1308
+ throw new WorkerSecurityViolationError(message, violation);
1309
+ }
1310
+ return currentValue;
1311
+ },
1312
+ set(value) {
1313
+ const message = "process.connected modification is blocked in worker context";
1314
+ const violation = self.recordViolation(
1315
+ "process_connected",
1316
+ "process.connected",
1317
+ message
1318
+ );
1319
+ if (!auditMode) {
1320
+ throw new WorkerSecurityViolationError(message, violation);
1321
+ }
1322
+ Object.defineProperty(process, "connected", {
1323
+ value,
1324
+ writable: true,
1325
+ configurable: true
1326
+ });
1327
+ },
1328
+ configurable: true
1329
+ });
1330
+ } catch {
1331
+ }
1332
+ }
1333
+ /**
1334
+ * Protect Module._load from being called.
1335
+ *
1336
+ * The attack vector is:
1337
+ * ```
1338
+ * module.constructor._load('child_process')
1339
+ * require.main.constructor._load('vm')
1340
+ * ```
1341
+ *
1342
+ * We access the Module class and replace _load with a blocking proxy.
1343
+ */
1344
+ protectModuleLoad() {
1345
+ const self = this;
1346
+ const auditMode = this.config.auditMode;
1347
+ try {
1348
+ let ModuleClass = null;
1349
+ if (typeof process !== "undefined") {
1350
+ const mainModule = process.mainModule;
1351
+ if (mainModule && typeof mainModule === "object") {
1352
+ ModuleClass = mainModule.constructor;
1353
+ }
1354
+ }
1355
+ if (!ModuleClass && typeof __require !== "undefined" && typeof __require.main !== "undefined") {
1356
+ ModuleClass = __require.main.constructor;
1357
+ }
1358
+ if (!ModuleClass || typeof ModuleClass._load !== "function") {
1359
+ return;
1360
+ }
1361
+ const original = ModuleClass._load;
1362
+ const descriptor = Object.getOwnPropertyDescriptor(ModuleClass, "_load");
1363
+ this.originalDescriptors.push({
1364
+ target: ModuleClass,
1365
+ prop: "_load",
1366
+ descriptor
1367
+ });
1368
+ const path = "Module._load";
1369
+ const proxy = new this.originalProxy(original, {
1370
+ apply(_target, _thisArg, _args) {
1371
+ const message = `${path} is blocked in worker context`;
1372
+ const violation = self.recordViolation("module_load", path, message);
1373
+ if (!auditMode) {
1374
+ throw new WorkerSecurityViolationError(message, violation);
1375
+ }
1376
+ return Reflect.apply(_target, _thisArg, _args);
1377
+ }
1378
+ });
1379
+ Object.defineProperty(ModuleClass, "_load", {
1380
+ value: proxy,
1381
+ writable: true,
1382
+ configurable: true
1383
+ });
1384
+ } catch {
1385
+ }
1386
+ }
1387
+ /**
1388
+ * Protect Module._resolveFilename from being called in worker context.
1389
+ *
1390
+ * Module._resolveFilename is called for both require() and import() resolution.
1391
+ * Blocking it catches file-based import() specifiers.
1392
+ *
1393
+ * data: and blob: URLs are handled by ESM loader hooks registered
1394
+ * in the main thread (DefenseInDepthBox.protectDynamicImport).
1395
+ */
1396
+ protectModuleResolveFilename() {
1397
+ const self = this;
1398
+ const auditMode = this.config.auditMode;
1399
+ try {
1400
+ let ModuleClass = null;
1401
+ if (typeof process !== "undefined") {
1402
+ const mainModule = process.mainModule;
1403
+ if (mainModule && typeof mainModule === "object") {
1404
+ ModuleClass = mainModule.constructor;
1405
+ }
1406
+ }
1407
+ if (!ModuleClass && typeof __require !== "undefined" && typeof __require.main !== "undefined") {
1408
+ ModuleClass = __require.main.constructor;
1409
+ }
1410
+ if (!ModuleClass || typeof ModuleClass._resolveFilename !== "function") {
1411
+ return;
1412
+ }
1413
+ const original = ModuleClass._resolveFilename;
1414
+ const descriptor = Object.getOwnPropertyDescriptor(
1415
+ ModuleClass,
1416
+ "_resolveFilename"
1417
+ );
1418
+ this.originalDescriptors.push({
1419
+ target: ModuleClass,
1420
+ prop: "_resolveFilename",
1421
+ descriptor
1422
+ });
1423
+ const path = "Module._resolveFilename";
1424
+ const proxy = new this.originalProxy(original, {
1425
+ apply(_target, _thisArg, _args) {
1426
+ const message = `${path} is blocked in worker context`;
1427
+ const violation = self.recordViolation(
1428
+ "module_resolve_filename",
1429
+ path,
1430
+ message
1431
+ );
1432
+ if (!auditMode) {
1433
+ throw new WorkerSecurityViolationError(message, violation);
1434
+ }
1435
+ return Reflect.apply(_target, _thisArg, _args);
1436
+ }
1437
+ });
1438
+ Object.defineProperty(ModuleClass, "_resolveFilename", {
1439
+ value: proxy,
1440
+ writable: true,
1441
+ configurable: true
1442
+ });
1443
+ } catch {
1444
+ }
1445
+ }
1446
+ /**
1447
+ * Apply a single patch to a blocked global.
1448
+ */
1449
+ applyPatch(blocked) {
1450
+ const { target, prop, violationType, strategy } = blocked;
1451
+ try {
1452
+ const original = target[prop];
1453
+ if (original === void 0) {
1454
+ return;
1455
+ }
1456
+ const descriptor = Object.getOwnPropertyDescriptor(target, prop);
1457
+ this.originalDescriptors.push({ target, prop, descriptor });
1458
+ if (strategy === "freeze") {
1459
+ if (typeof original === "object" && original !== null) {
1460
+ Object.freeze(original);
1461
+ }
1462
+ } else {
1463
+ const path = this.getPathForTarget(target, prop);
1464
+ const proxy = typeof original === "function" ? this.createBlockingProxy(
1465
+ original,
1466
+ path,
1467
+ violationType
1468
+ ) : this.createBlockingObjectProxy(
1469
+ original,
1470
+ path,
1471
+ violationType,
1472
+ blocked.allowedKeys
1473
+ );
1474
+ Object.defineProperty(target, prop, {
1475
+ value: proxy,
1476
+ writable: true,
1477
+ configurable: true
1478
+ });
1479
+ }
1480
+ } catch {
1481
+ }
1482
+ }
1483
+ /**
1484
+ * Restore all original values.
1485
+ */
1486
+ restorePatches() {
1487
+ for (let i = this.originalDescriptors.length - 1; i >= 0; i--) {
1488
+ const { target, prop, descriptor } = this.originalDescriptors[i];
1489
+ try {
1490
+ if (descriptor) {
1491
+ Object.defineProperty(target, prop, descriptor);
1492
+ } else {
1493
+ delete target[prop];
1494
+ }
1495
+ } catch {
1496
+ }
1497
+ }
1498
+ this.originalDescriptors = [];
1499
+ }
1500
+ };
1501
+
1502
+ // src/security/trusted-globals.ts
1503
+ var _SharedArrayBuffer = globalThis.SharedArrayBuffer;
1504
+ var _Atomics = globalThis.Atomics;
1505
+ var _performanceNow = performance.now.bind(performance);
1506
+
1507
+ // src/commands/worker-bridge/protocol.ts
1508
+ var OpCode = {
1509
+ NOOP: 0,
1510
+ READ_FILE: 1,
1511
+ WRITE_FILE: 2,
1512
+ STAT: 3,
1513
+ READDIR: 4,
1514
+ MKDIR: 5,
1515
+ RM: 6,
1516
+ EXISTS: 7,
1517
+ APPEND_FILE: 8,
1518
+ SYMLINK: 9,
1519
+ READLINK: 10,
1520
+ LSTAT: 11,
1521
+ CHMOD: 12,
1522
+ REALPATH: 13,
1523
+ RENAME: 14,
1524
+ COPY_FILE: 15,
1525
+ // Special operations for I/O
1526
+ WRITE_STDOUT: 100,
1527
+ WRITE_STDERR: 101,
1528
+ EXIT: 102,
1529
+ // HTTP operations
1530
+ HTTP_REQUEST: 200,
1531
+ // Sub-shell execution
1532
+ EXEC_COMMAND: 300
1533
+ };
1534
+ var Status = {
1535
+ PENDING: 0,
1536
+ READY: 1,
1537
+ SUCCESS: 2,
1538
+ ERROR: 3
1539
+ };
1540
+ var ErrorCode = {
1541
+ NONE: 0,
1542
+ NOT_FOUND: 1,
1543
+ IS_DIRECTORY: 2,
1544
+ NOT_DIRECTORY: 3,
1545
+ EXISTS: 4,
1546
+ PERMISSION_DENIED: 5,
1547
+ INVALID_PATH: 6,
1548
+ IO_ERROR: 7,
1549
+ TIMEOUT: 8,
1550
+ NETWORK_ERROR: 9,
1551
+ NETWORK_NOT_CONFIGURED: 10
1552
+ };
1553
+ var Offset = {
1554
+ OP_CODE: 0,
1555
+ STATUS: 4,
1556
+ PATH_LENGTH: 8,
1557
+ DATA_LENGTH: 12,
1558
+ RESULT_LENGTH: 16,
1559
+ ERROR_CODE: 20,
1560
+ FLAGS: 24,
1561
+ MODE: 28,
1562
+ PATH_BUFFER: 32,
1563
+ DATA_BUFFER: 4128
1564
+ // 32 + 4096
1565
+ };
1566
+ var Size = {
1567
+ CONTROL_REGION: 32,
1568
+ PATH_BUFFER: 4096,
1569
+ // 1MB limit applies to all FS read/write operations through the bridge.
1570
+ // Files larger than this will be truncated. This is tight — consider
1571
+ // increasing if real workloads hit the cap. Reduced from 16MB for faster tests.
1572
+ DATA_BUFFER: 1048576,
1573
+ TOTAL: 1052704
1574
+ // 32 + 4096 + 1MB
1575
+ };
1576
+ var Flags = {
1577
+ NONE: 0,
1578
+ RECURSIVE: 1,
1579
+ FORCE: 2,
1580
+ MKDIR_RECURSIVE: 1
1581
+ };
1582
+ var StatLayout = {
1583
+ IS_FILE: 0,
1584
+ IS_DIRECTORY: 1,
1585
+ IS_SYMLINK: 2,
1586
+ MODE: 4,
1587
+ SIZE: 8,
1588
+ MTIME: 16,
1589
+ TOTAL: 24
1590
+ };
1591
+ var ProtocolBuffer = class {
1592
+ int32View;
1593
+ uint8View;
1594
+ dataView;
1595
+ constructor(buffer) {
1596
+ this.int32View = new Int32Array(buffer);
1597
+ this.uint8View = new Uint8Array(buffer);
1598
+ this.dataView = new DataView(buffer);
1599
+ }
1600
+ getOpCode() {
1601
+ return _Atomics.load(this.int32View, Offset.OP_CODE / 4);
1602
+ }
1603
+ setOpCode(code) {
1604
+ _Atomics.store(this.int32View, Offset.OP_CODE / 4, code);
1605
+ }
1606
+ getStatus() {
1607
+ return _Atomics.load(this.int32View, Offset.STATUS / 4);
1608
+ }
1609
+ setStatus(status) {
1610
+ _Atomics.store(this.int32View, Offset.STATUS / 4, status);
1611
+ }
1612
+ getPathLength() {
1613
+ return _Atomics.load(this.int32View, Offset.PATH_LENGTH / 4);
1614
+ }
1615
+ setPathLength(length) {
1616
+ _Atomics.store(this.int32View, Offset.PATH_LENGTH / 4, length);
1617
+ }
1618
+ getDataLength() {
1619
+ return _Atomics.load(this.int32View, Offset.DATA_LENGTH / 4);
1620
+ }
1621
+ setDataLength(length) {
1622
+ _Atomics.store(this.int32View, Offset.DATA_LENGTH / 4, length);
1623
+ }
1624
+ getResultLength() {
1625
+ return _Atomics.load(this.int32View, Offset.RESULT_LENGTH / 4);
1626
+ }
1627
+ setResultLength(length) {
1628
+ _Atomics.store(this.int32View, Offset.RESULT_LENGTH / 4, length);
1629
+ }
1630
+ getErrorCode() {
1631
+ return _Atomics.load(
1632
+ this.int32View,
1633
+ Offset.ERROR_CODE / 4
1634
+ );
1635
+ }
1636
+ setErrorCode(code) {
1637
+ _Atomics.store(this.int32View, Offset.ERROR_CODE / 4, code);
1638
+ }
1639
+ getFlags() {
1640
+ return _Atomics.load(this.int32View, Offset.FLAGS / 4);
1641
+ }
1642
+ setFlags(flags) {
1643
+ _Atomics.store(this.int32View, Offset.FLAGS / 4, flags);
1644
+ }
1645
+ getMode() {
1646
+ return _Atomics.load(this.int32View, Offset.MODE / 4);
1647
+ }
1648
+ setMode(mode) {
1649
+ _Atomics.store(this.int32View, Offset.MODE / 4, mode);
1650
+ }
1651
+ getPath() {
1652
+ const length = this.getPathLength();
1653
+ const bytes = this.uint8View.slice(
1654
+ Offset.PATH_BUFFER,
1655
+ Offset.PATH_BUFFER + length
1656
+ );
1657
+ return new TextDecoder().decode(bytes);
1658
+ }
1659
+ setPath(path) {
1660
+ const encoded = new TextEncoder().encode(path);
1661
+ if (encoded.length > Size.PATH_BUFFER) {
1662
+ throw new Error(`Path too long: ${encoded.length} > ${Size.PATH_BUFFER}`);
1663
+ }
1664
+ this.uint8View.set(encoded, Offset.PATH_BUFFER);
1665
+ this.setPathLength(encoded.length);
1666
+ }
1667
+ getData() {
1668
+ const length = this.getDataLength();
1669
+ return this.uint8View.slice(
1670
+ Offset.DATA_BUFFER,
1671
+ Offset.DATA_BUFFER + length
1672
+ );
1673
+ }
1674
+ setData(data) {
1675
+ if (data.length > Size.DATA_BUFFER) {
1676
+ throw new Error(`Data too large: ${data.length} > ${Size.DATA_BUFFER}`);
1677
+ }
1678
+ this.uint8View.set(data, Offset.DATA_BUFFER);
1679
+ this.setDataLength(data.length);
1680
+ }
1681
+ getDataAsString() {
1682
+ const data = this.getData();
1683
+ return new TextDecoder().decode(data);
1684
+ }
1685
+ setDataFromString(str) {
1686
+ const encoded = new TextEncoder().encode(str);
1687
+ this.setData(encoded);
1688
+ }
1689
+ getResult() {
1690
+ const length = this.getResultLength();
1691
+ return this.uint8View.slice(
1692
+ Offset.DATA_BUFFER,
1693
+ Offset.DATA_BUFFER + length
1694
+ );
1695
+ }
1696
+ setResult(data) {
1697
+ if (data.length > Size.DATA_BUFFER) {
1698
+ throw new Error(`Result too large: ${data.length} > ${Size.DATA_BUFFER}`);
1699
+ }
1700
+ this.uint8View.set(data, Offset.DATA_BUFFER);
1701
+ this.setResultLength(data.length);
1702
+ }
1703
+ getResultAsString() {
1704
+ const result = this.getResult();
1705
+ return new TextDecoder().decode(result);
1706
+ }
1707
+ setResultFromString(str) {
1708
+ const encoded = new TextEncoder().encode(str);
1709
+ this.setResult(encoded);
1710
+ }
1711
+ encodeStat(stat) {
1712
+ this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_FILE] = stat.isFile ? 1 : 0;
1713
+ this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_DIRECTORY] = stat.isDirectory ? 1 : 0;
1714
+ this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_SYMLINK] = stat.isSymbolicLink ? 1 : 0;
1715
+ this.dataView.setInt32(
1716
+ Offset.DATA_BUFFER + StatLayout.MODE,
1717
+ stat.mode,
1718
+ true
1719
+ );
1720
+ const size = Math.min(stat.size, Number.MAX_SAFE_INTEGER);
1721
+ this.dataView.setFloat64(Offset.DATA_BUFFER + StatLayout.SIZE, size, true);
1722
+ this.dataView.setFloat64(
1723
+ Offset.DATA_BUFFER + StatLayout.MTIME,
1724
+ stat.mtime.getTime(),
1725
+ true
1726
+ );
1727
+ this.setResultLength(StatLayout.TOTAL);
1728
+ }
1729
+ decodeStat() {
1730
+ return {
1731
+ isFile: this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_FILE] === 1,
1732
+ isDirectory: this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_DIRECTORY] === 1,
1733
+ isSymbolicLink: this.uint8View[Offset.DATA_BUFFER + StatLayout.IS_SYMLINK] === 1,
1734
+ mode: this.dataView.getInt32(Offset.DATA_BUFFER + StatLayout.MODE, true),
1735
+ size: this.dataView.getFloat64(
1736
+ Offset.DATA_BUFFER + StatLayout.SIZE,
1737
+ true
1738
+ ),
1739
+ mtime: new Date(
1740
+ this.dataView.getFloat64(Offset.DATA_BUFFER + StatLayout.MTIME, true)
1741
+ )
1742
+ };
1743
+ }
1744
+ waitForReady(timeout) {
1745
+ return _Atomics.wait(
1746
+ this.int32View,
1747
+ Offset.STATUS / 4,
1748
+ Status.PENDING,
1749
+ timeout
1750
+ );
1751
+ }
1752
+ waitForReadyAsync(timeout) {
1753
+ return _Atomics.waitAsync(
1754
+ this.int32View,
1755
+ Offset.STATUS / 4,
1756
+ Status.PENDING,
1757
+ timeout
1758
+ );
1759
+ }
1760
+ /**
1761
+ * Wait for status to become READY.
1762
+ * Returns immediately if status is already READY, or waits until it changes.
1763
+ */
1764
+ async waitUntilReady(timeout) {
1765
+ const startTime = Date.now();
1766
+ while (true) {
1767
+ const status = this.getStatus();
1768
+ if (status === Status.READY) {
1769
+ return true;
1770
+ }
1771
+ const elapsed = Date.now() - startTime;
1772
+ if (elapsed >= timeout) {
1773
+ return false;
1774
+ }
1775
+ const remainingMs = timeout - elapsed;
1776
+ const result = _Atomics.waitAsync(
1777
+ this.int32View,
1778
+ Offset.STATUS / 4,
1779
+ status,
1780
+ remainingMs
1781
+ );
1782
+ if (result.async) {
1783
+ const waitResult = await result.value;
1784
+ if (waitResult === "timed-out") {
1785
+ return false;
1786
+ }
1787
+ }
1788
+ }
1789
+ }
1790
+ waitForResult(timeout) {
1791
+ return _Atomics.wait(
1792
+ this.int32View,
1793
+ Offset.STATUS / 4,
1794
+ Status.READY,
1795
+ timeout
1796
+ );
1797
+ }
1798
+ notify() {
1799
+ return _Atomics.notify(this.int32View, Offset.STATUS / 4);
1800
+ }
1801
+ reset() {
1802
+ this.setOpCode(OpCode.NOOP);
1803
+ this.setStatus(Status.PENDING);
1804
+ this.setPathLength(0);
1805
+ this.setDataLength(0);
1806
+ this.setResultLength(0);
1807
+ this.setErrorCode(ErrorCode.NONE);
1808
+ this.setFlags(Flags.NONE);
1809
+ this.setMode(0);
1810
+ }
1811
+ };
1812
+
1813
+ // src/commands/worker-bridge/sync-backend.ts
1814
+ var SyncBackend = class {
1815
+ protocol;
1816
+ operationTimeoutMs;
1817
+ constructor(sharedBuffer, operationTimeoutMs = 3e4) {
1818
+ this.protocol = new ProtocolBuffer(sharedBuffer);
1819
+ this.operationTimeoutMs = operationTimeoutMs;
1820
+ }
1821
+ execSync(opCode, path, data, flags = 0, mode = 0) {
1822
+ this.protocol.reset();
1823
+ this.protocol.setOpCode(opCode);
1824
+ this.protocol.setPath(path);
1825
+ this.protocol.setFlags(flags);
1826
+ this.protocol.setMode(mode);
1827
+ if (data) {
1828
+ this.protocol.setData(data);
1829
+ }
1830
+ this.protocol.setStatus(Status.READY);
1831
+ this.protocol.notify();
1832
+ const waitResult = this.protocol.waitForResult(this.operationTimeoutMs);
1833
+ if (waitResult === "timed-out") {
1834
+ return { success: false, error: "Operation timed out" };
1835
+ }
1836
+ const status = this.protocol.getStatus();
1837
+ if (status === Status.SUCCESS) {
1838
+ return { success: true, result: this.protocol.getResult() };
1839
+ }
1840
+ return {
1841
+ success: false,
1842
+ error: this.protocol.getResultAsString() || `Error code: ${this.protocol.getErrorCode()}`
1843
+ };
1844
+ }
1845
+ readFile(path) {
1846
+ const result = this.execSync(OpCode.READ_FILE, path);
1847
+ if (!result.success) {
1848
+ throw new Error(result.error || "Failed to read file");
1849
+ }
1850
+ return result.result ?? new Uint8Array(0);
1851
+ }
1852
+ writeFile(path, data) {
1853
+ const result = this.execSync(OpCode.WRITE_FILE, path, data);
1854
+ if (!result.success) {
1855
+ throw new Error(result.error || "Failed to write file");
1856
+ }
1857
+ }
1858
+ stat(path) {
1859
+ const result = this.execSync(OpCode.STAT, path);
1860
+ if (!result.success) {
1861
+ throw new Error(result.error || "Failed to stat");
1862
+ }
1863
+ return this.protocol.decodeStat();
1864
+ }
1865
+ lstat(path) {
1866
+ const result = this.execSync(OpCode.LSTAT, path);
1867
+ if (!result.success) {
1868
+ throw new Error(result.error || "Failed to lstat");
1869
+ }
1870
+ return this.protocol.decodeStat();
1871
+ }
1872
+ readdir(path) {
1873
+ const result = this.execSync(OpCode.READDIR, path);
1874
+ if (!result.success) {
1875
+ throw new Error(result.error || "Failed to readdir");
1876
+ }
1877
+ return JSON.parse(this.protocol.getResultAsString());
1878
+ }
1879
+ mkdir(path, recursive = false) {
1880
+ const flags = recursive ? Flags.MKDIR_RECURSIVE : 0;
1881
+ const result = this.execSync(OpCode.MKDIR, path, void 0, flags);
1882
+ if (!result.success) {
1883
+ throw new Error(result.error || "Failed to mkdir");
1884
+ }
1885
+ }
1886
+ rm(path, recursive = false, force = false) {
1887
+ let flags = 0;
1888
+ if (recursive) flags |= Flags.RECURSIVE;
1889
+ if (force) flags |= Flags.FORCE;
1890
+ const result = this.execSync(OpCode.RM, path, void 0, flags);
1891
+ if (!result.success) {
1892
+ throw new Error(result.error || "Failed to rm");
1893
+ }
1894
+ }
1895
+ exists(path) {
1896
+ const result = this.execSync(OpCode.EXISTS, path);
1897
+ if (!result.success) {
1898
+ return false;
1899
+ }
1900
+ return result.result?.[0] === 1;
1901
+ }
1902
+ appendFile(path, data) {
1903
+ const result = this.execSync(OpCode.APPEND_FILE, path, data);
1904
+ if (!result.success) {
1905
+ throw new Error(result.error || "Failed to append file");
1906
+ }
1907
+ }
1908
+ symlink(target, linkPath) {
1909
+ const targetData = new TextEncoder().encode(target);
1910
+ const result = this.execSync(OpCode.SYMLINK, linkPath, targetData);
1911
+ if (!result.success) {
1912
+ throw new Error(result.error || "Failed to symlink");
1913
+ }
1914
+ }
1915
+ readlink(path) {
1916
+ const result = this.execSync(OpCode.READLINK, path);
1917
+ if (!result.success) {
1918
+ throw new Error(result.error || "Failed to readlink");
1919
+ }
1920
+ return this.protocol.getResultAsString();
1921
+ }
1922
+ chmod(path, mode) {
1923
+ const result = this.execSync(OpCode.CHMOD, path, void 0, 0, mode);
1924
+ if (!result.success) {
1925
+ throw new Error(result.error || "Failed to chmod");
1926
+ }
1927
+ }
1928
+ realpath(path) {
1929
+ const result = this.execSync(OpCode.REALPATH, path);
1930
+ if (!result.success) {
1931
+ throw new Error(result.error || "Failed to realpath");
1932
+ }
1933
+ return this.protocol.getResultAsString();
1934
+ }
1935
+ rename(oldPath, newPath) {
1936
+ const newPathData = new TextEncoder().encode(newPath);
1937
+ const result = this.execSync(OpCode.RENAME, oldPath, newPathData);
1938
+ if (!result.success) {
1939
+ throw new Error(result.error || "Failed to rename");
1940
+ }
1941
+ }
1942
+ copyFile(src, dest) {
1943
+ const destData = new TextEncoder().encode(dest);
1944
+ const result = this.execSync(OpCode.COPY_FILE, src, destData);
1945
+ if (!result.success) {
1946
+ throw new Error(result.error || "Failed to copyFile");
1947
+ }
1948
+ }
1949
+ writeStdout(data) {
1950
+ const encoded = new TextEncoder().encode(data);
1951
+ const result = this.execSync(OpCode.WRITE_STDOUT, "", encoded);
1952
+ if (!result.success) {
1953
+ throw new Error(result.error || "Failed to write stdout");
1954
+ }
1955
+ }
1956
+ writeStderr(data) {
1957
+ const encoded = new TextEncoder().encode(data);
1958
+ const result = this.execSync(OpCode.WRITE_STDERR, "", encoded);
1959
+ if (!result.success) {
1960
+ throw new Error(result.error || "Failed to write stderr");
1961
+ }
1962
+ }
1963
+ exit(code) {
1964
+ this.execSync(OpCode.EXIT, "", void 0, code);
1965
+ }
1966
+ /**
1967
+ * Make an HTTP request through the main thread's secureFetch.
1968
+ * Returns the response as a parsed object.
1969
+ */
1970
+ httpRequest(url, options) {
1971
+ const requestData = options ? new TextEncoder().encode(JSON.stringify(options)) : void 0;
1972
+ const result = this.execSync(OpCode.HTTP_REQUEST, url, requestData);
1973
+ if (!result.success) {
1974
+ throw new Error(result.error || "HTTP request failed");
1975
+ }
1976
+ const responseJson = new TextDecoder().decode(result.result);
1977
+ return JSON.parse(responseJson);
1978
+ }
1979
+ /**
1980
+ * Execute a shell command through the main thread's exec function.
1981
+ * Returns the result as { stdout, stderr, exitCode }.
1982
+ */
1983
+ execCommand(command, stdin) {
1984
+ const requestData = stdin ? new TextEncoder().encode(JSON.stringify({ stdin })) : void 0;
1985
+ const result = this.execSync(OpCode.EXEC_COMMAND, command, requestData);
1986
+ if (!result.success) {
1987
+ throw new Error(result.error || "Command execution failed");
1988
+ }
1989
+ const responseJson = new TextDecoder().decode(result.result);
1990
+ return JSON.parse(responseJson);
1991
+ }
1992
+ /**
1993
+ * Execute a shell command with structured args (shell-escaped on the main thread).
1994
+ * Prevents command injection from unsanitized args.
1995
+ */
1996
+ execCommandArgs(command, args) {
1997
+ const requestData = new TextEncoder().encode(JSON.stringify({ args }));
1998
+ const result = this.execSync(OpCode.EXEC_COMMAND, command, requestData);
1999
+ if (!result.success) {
2000
+ throw new Error(result.error || "Command execution failed");
2001
+ }
2002
+ const responseJson = new TextDecoder().decode(result.result);
2003
+ return JSON.parse(responseJson);
2004
+ }
2005
+ };
2006
+
2007
+ // src/commands/js-exec/fetch-polyfill.ts
2008
+ var FETCH_POLYFILL_SOURCE = `
2009
+ (function() {
2010
+ // --- URLSearchParams ---
2011
+ function URLSearchParams(init) {
2012
+ this._entries = [];
2013
+ if (!init) return;
2014
+ if (typeof init === 'string') {
2015
+ var s = init;
2016
+ if (s.charAt(0) === '?') s = s.slice(1);
2017
+ var pairs = s.split('&');
2018
+ for (var i = 0; i < pairs.length; i++) {
2019
+ var pair = pairs[i];
2020
+ if (pair === '') continue;
2021
+ var eq = pair.indexOf('=');
2022
+ if (eq === -1) {
2023
+ this._entries.push([decodeURIComponent(pair), '']);
2024
+ } else {
2025
+ this._entries.push([
2026
+ decodeURIComponent(pair.slice(0, eq)),
2027
+ decodeURIComponent(pair.slice(eq + 1))
2028
+ ]);
2029
+ }
2030
+ }
2031
+ } else if (typeof init === 'object' && init !== null) {
2032
+ if (init instanceof URLSearchParams) {
2033
+ this._entries = init._entries.slice();
2034
+ } else {
2035
+ var keys = Object.keys(init);
2036
+ for (var i = 0; i < keys.length; i++) {
2037
+ this._entries.push([keys[i], String(init[keys[i]])]);
2038
+ }
2039
+ }
2040
+ }
2041
+ }
2042
+
2043
+ URLSearchParams.prototype.append = function(name, value) {
2044
+ this._entries.push([String(name), String(value)]);
2045
+ };
2046
+
2047
+ URLSearchParams.prototype.delete = function(name) {
2048
+ var n = String(name);
2049
+ this._entries = this._entries.filter(function(e) { return e[0] !== n; });
2050
+ };
2051
+
2052
+ URLSearchParams.prototype.get = function(name) {
2053
+ var n = String(name);
2054
+ for (var i = 0; i < this._entries.length; i++) {
2055
+ if (this._entries[i][0] === n) return this._entries[i][1];
2056
+ }
2057
+ return null;
2058
+ };
2059
+
2060
+ URLSearchParams.prototype.getAll = function(name) {
2061
+ var n = String(name);
2062
+ var result = [];
2063
+ for (var i = 0; i < this._entries.length; i++) {
2064
+ if (this._entries[i][0] === n) result.push(this._entries[i][1]);
2065
+ }
2066
+ return result;
2067
+ };
2068
+
2069
+ URLSearchParams.prototype.has = function(name) {
2070
+ var n = String(name);
2071
+ for (var i = 0; i < this._entries.length; i++) {
2072
+ if (this._entries[i][0] === n) return true;
2073
+ }
2074
+ return false;
2075
+ };
2076
+
2077
+ URLSearchParams.prototype.set = function(name, value) {
2078
+ var n = String(name);
2079
+ var v = String(value);
2080
+ var found = false;
2081
+ var newEntries = [];
2082
+ for (var i = 0; i < this._entries.length; i++) {
2083
+ if (this._entries[i][0] === n) {
2084
+ if (!found) {
2085
+ newEntries.push([n, v]);
2086
+ found = true;
2087
+ }
2088
+ } else {
2089
+ newEntries.push(this._entries[i]);
2090
+ }
2091
+ }
2092
+ if (!found) newEntries.push([n, v]);
2093
+ this._entries = newEntries;
2094
+ };
2095
+
2096
+ URLSearchParams.prototype.sort = function() {
2097
+ this._entries.sort(function(a, b) {
2098
+ if (a[0] < b[0]) return -1;
2099
+ if (a[0] > b[0]) return 1;
2100
+ return 0;
2101
+ });
2102
+ };
2103
+
2104
+ URLSearchParams.prototype.toString = function() {
2105
+ return this._entries.map(function(e) {
2106
+ return encodeURIComponent(e[0]) + '=' + encodeURIComponent(e[1]);
2107
+ }).join('&');
2108
+ };
2109
+
2110
+ URLSearchParams.prototype.forEach = function(callback, thisArg) {
2111
+ for (var i = 0; i < this._entries.length; i++) {
2112
+ callback.call(thisArg, this._entries[i][1], this._entries[i][0], this);
2113
+ }
2114
+ };
2115
+
2116
+ URLSearchParams.prototype.entries = function() {
2117
+ var idx = 0;
2118
+ var entries = this._entries;
2119
+ return {
2120
+ next: function() {
2121
+ if (idx >= entries.length) return { done: true, value: undefined };
2122
+ return { done: false, value: entries[idx++].slice() };
2123
+ },
2124
+ [Symbol.iterator]: function() { return this; }
2125
+ };
2126
+ };
2127
+
2128
+ URLSearchParams.prototype.keys = function() {
2129
+ var idx = 0;
2130
+ var entries = this._entries;
2131
+ return {
2132
+ next: function() {
2133
+ if (idx >= entries.length) return { done: true, value: undefined };
2134
+ return { done: false, value: entries[idx++][0] };
2135
+ },
2136
+ [Symbol.iterator]: function() { return this; }
2137
+ };
2138
+ };
2139
+
2140
+ URLSearchParams.prototype.values = function() {
2141
+ var idx = 0;
2142
+ var entries = this._entries;
2143
+ return {
2144
+ next: function() {
2145
+ if (idx >= entries.length) return { done: true, value: undefined };
2146
+ return { done: false, value: entries[idx++][1] };
2147
+ },
2148
+ [Symbol.iterator]: function() { return this; }
2149
+ };
2150
+ };
2151
+
2152
+ URLSearchParams.prototype[Symbol.iterator] = URLSearchParams.prototype.entries;
2153
+
2154
+ Object.defineProperty(URLSearchParams.prototype, 'size', {
2155
+ get: function() { return this._entries.length; }
2156
+ });
2157
+
2158
+ // --- URL ---
2159
+ var urlRegex = /^([a-zA-Z][a-zA-Z0-9+.-]*):(?:\\/\\/(?:([^:@/?#]*)(?::([^@/?#]*))?@)?([^:/?#]*)(?::([0-9]+))?)?(\\/[^?#]*)?(?:\\?([^#]*))?(?:#(.*))?$/;
2160
+
2161
+ function URL(url, base) {
2162
+ var input = String(url);
2163
+
2164
+ if (base !== undefined) {
2165
+ var baseUrl = (base instanceof URL) ? base : new URL(String(base));
2166
+ // Resolve relative URL against base
2167
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(input)) {
2168
+ // Absolute URL - parse as-is
2169
+ } else if (input.charAt(0) === '/' && input.charAt(1) === '/') {
2170
+ // Protocol-relative
2171
+ input = baseUrl.protocol + input;
2172
+ } else if (input.charAt(0) === '/') {
2173
+ // Absolute path
2174
+ input = baseUrl.origin + input;
2175
+ } else if (input.charAt(0) === '?' || input.charAt(0) === '#') {
2176
+ // Query or hash only
2177
+ var basePath = baseUrl.protocol + '//' + baseUrl.host + baseUrl.pathname;
2178
+ if (input.charAt(0) === '#') {
2179
+ input = basePath + baseUrl.search + input;
2180
+ } else {
2181
+ input = basePath + input;
2182
+ }
2183
+ } else {
2184
+ // Relative path
2185
+ var basePath = baseUrl.protocol + '//' + baseUrl.host;
2186
+ var dirPath = baseUrl.pathname;
2187
+ var lastSlash = dirPath.lastIndexOf('/');
2188
+ if (lastSlash >= 0) dirPath = dirPath.slice(0, lastSlash + 1);
2189
+ else dirPath = '/';
2190
+ input = basePath + dirPath + input;
2191
+ }
2192
+ }
2193
+
2194
+ var m = urlRegex.exec(input);
2195
+ if (!m) throw new TypeError("Invalid URL: " + String(url));
2196
+
2197
+ this.protocol = m[1].toLowerCase() + ':';
2198
+ this.username = m[2] ? decodeURIComponent(m[2]) : '';
2199
+ this.password = m[3] ? decodeURIComponent(m[3]) : '';
2200
+ this.hostname = m[4] || '';
2201
+ this.port = m[5] || '';
2202
+ this.pathname = m[6] || '/';
2203
+ this.hash = m[8] ? '#' + m[8] : '';
2204
+
2205
+ // Normalize pathname (resolve . and ..)
2206
+ var parts = this.pathname.split('/');
2207
+ var resolved = [];
2208
+ for (var i = 0; i < parts.length; i++) {
2209
+ if (parts[i] === '..') { if (resolved.length > 1) resolved.pop(); }
2210
+ else if (parts[i] !== '.') resolved.push(parts[i]);
2211
+ }
2212
+ this.pathname = resolved.join('/') || '/';
2213
+
2214
+ // searchParams is live
2215
+ this._searchParamsStr = m[7] || '';
2216
+ this.searchParams = new URLSearchParams(this._searchParamsStr);
2217
+ }
2218
+
2219
+ Object.defineProperty(URL.prototype, 'search', {
2220
+ get: function() {
2221
+ var s = this.searchParams.toString();
2222
+ return s ? '?' + s : '';
2223
+ },
2224
+ set: function(v) {
2225
+ this.searchParams = new URLSearchParams(String(v));
2226
+ }
2227
+ });
2228
+
2229
+ Object.defineProperty(URL.prototype, 'host', {
2230
+ get: function() {
2231
+ return this.port ? this.hostname + ':' + this.port : this.hostname;
2232
+ }
2233
+ });
2234
+
2235
+ Object.defineProperty(URL.prototype, 'origin', {
2236
+ get: function() {
2237
+ return this.protocol + '//' + this.host;
2238
+ }
2239
+ });
2240
+
2241
+ Object.defineProperty(URL.prototype, 'href', {
2242
+ get: function() {
2243
+ var auth = '';
2244
+ if (this.username) {
2245
+ auth = this.username;
2246
+ if (this.password) auth += ':' + this.password;
2247
+ auth += '@';
2248
+ }
2249
+ return this.protocol + '//' + auth + this.host + this.pathname + this.search + this.hash;
2250
+ },
2251
+ set: function(v) {
2252
+ var parsed = new URL(String(v));
2253
+ this.protocol = parsed.protocol;
2254
+ this.username = parsed.username;
2255
+ this.password = parsed.password;
2256
+ this.hostname = parsed.hostname;
2257
+ this.port = parsed.port;
2258
+ this.pathname = parsed.pathname;
2259
+ this.searchParams = parsed.searchParams;
2260
+ this.hash = parsed.hash;
2261
+ }
2262
+ });
2263
+
2264
+ URL.prototype.toString = function() { return this.href; };
2265
+ URL.prototype.toJSON = function() { return this.href; };
2266
+
2267
+ // --- Headers ---
2268
+ function Headers(init) {
2269
+ this._map = {};
2270
+ if (!init) return;
2271
+ if (init instanceof Headers) {
2272
+ var keys = Object.keys(init._map);
2273
+ for (var i = 0; i < keys.length; i++) {
2274
+ this._map[keys[i]] = init._map[keys[i]].slice();
2275
+ }
2276
+ } else if (typeof init === 'object') {
2277
+ var keys = Object.keys(init);
2278
+ for (var i = 0; i < keys.length; i++) {
2279
+ this._map[keys[i].toLowerCase()] = [String(init[keys[i]])];
2280
+ }
2281
+ }
2282
+ }
2283
+
2284
+ Headers.prototype.append = function(name, value) {
2285
+ var key = String(name).toLowerCase();
2286
+ if (!this._map[key]) this._map[key] = [];
2287
+ this._map[key].push(String(value));
2288
+ };
2289
+
2290
+ Headers.prototype.delete = function(name) {
2291
+ delete this._map[String(name).toLowerCase()];
2292
+ };
2293
+
2294
+ Headers.prototype.get = function(name) {
2295
+ var vals = this._map[String(name).toLowerCase()];
2296
+ return vals ? vals.join(', ') : null;
2297
+ };
2298
+
2299
+ Headers.prototype.has = function(name) {
2300
+ return String(name).toLowerCase() in this._map;
2301
+ };
2302
+
2303
+ Headers.prototype.set = function(name, value) {
2304
+ this._map[String(name).toLowerCase()] = [String(value)];
2305
+ };
2306
+
2307
+ Headers.prototype.forEach = function(callback, thisArg) {
2308
+ var keys = Object.keys(this._map).sort();
2309
+ for (var i = 0; i < keys.length; i++) {
2310
+ callback.call(thisArg, this._map[keys[i]].join(', '), keys[i], this);
2311
+ }
2312
+ };
2313
+
2314
+ Headers.prototype.entries = function() {
2315
+ var keys = Object.keys(this._map).sort();
2316
+ var map = this._map;
2317
+ var idx = 0;
2318
+ return {
2319
+ next: function() {
2320
+ if (idx >= keys.length) return { done: true, value: undefined };
2321
+ var k = keys[idx++];
2322
+ return { done: false, value: [k, map[k].join(', ')] };
2323
+ },
2324
+ [Symbol.iterator]: function() { return this; }
2325
+ };
2326
+ };
2327
+
2328
+ Headers.prototype.keys = function() {
2329
+ var keys = Object.keys(this._map).sort();
2330
+ var idx = 0;
2331
+ return {
2332
+ next: function() {
2333
+ if (idx >= keys.length) return { done: true, value: undefined };
2334
+ return { done: false, value: keys[idx++] };
2335
+ },
2336
+ [Symbol.iterator]: function() { return this; }
2337
+ };
2338
+ };
2339
+
2340
+ Headers.prototype.values = function() {
2341
+ var keys = Object.keys(this._map).sort();
2342
+ var map = this._map;
2343
+ var idx = 0;
2344
+ return {
2345
+ next: function() {
2346
+ if (idx >= keys.length) return { done: true, value: undefined };
2347
+ return { done: false, value: map[keys[idx++]].join(', ') };
2348
+ },
2349
+ [Symbol.iterator]: function() { return this; }
2350
+ };
2351
+ };
2352
+
2353
+ Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
2354
+
2355
+ // --- Response ---
2356
+ function Response(body, init) {
2357
+ if (init === undefined) init = {};
2358
+ this.status = init.status !== undefined ? init.status : 200;
2359
+ this.statusText = init.statusText !== undefined ? init.statusText : '';
2360
+ this.headers = init.headers instanceof Headers ? init.headers : new Headers(init.headers);
2361
+ this.body = body !== undefined && body !== null ? String(body) : '';
2362
+ this.ok = this.status >= 200 && this.status <= 299;
2363
+ this.url = '';
2364
+ this.redirected = false;
2365
+ this.type = 'basic';
2366
+ this.bodyUsed = false;
2367
+ }
2368
+
2369
+ Response.prototype.text = function() {
2370
+ this.bodyUsed = true;
2371
+ return Promise.resolve(this.body);
2372
+ };
2373
+
2374
+ Response.prototype.json = function() {
2375
+ this.bodyUsed = true;
2376
+ try {
2377
+ return Promise.resolve(JSON.parse(this.body));
2378
+ } catch (e) {
2379
+ return Promise.reject(e);
2380
+ }
2381
+ };
2382
+
2383
+ Response.prototype.clone = function() {
2384
+ var r = new Response(this.body, {
2385
+ status: this.status,
2386
+ statusText: this.statusText,
2387
+ headers: new Headers(this.headers)
2388
+ });
2389
+ r.url = this.url;
2390
+ r.redirected = this.redirected;
2391
+ r.type = this.type;
2392
+ return r;
2393
+ };
2394
+
2395
+ Response.json = function(data, init) {
2396
+ if (init === undefined) init = {};
2397
+ var headers = init.headers instanceof Headers ? init.headers : new Headers(init.headers);
2398
+ if (!headers.has('content-type')) {
2399
+ headers.set('content-type', 'application/json');
2400
+ }
2401
+ return new Response(JSON.stringify(data), {
2402
+ status: init.status !== undefined ? init.status : 200,
2403
+ statusText: init.statusText || '',
2404
+ headers: headers
2405
+ });
2406
+ };
2407
+
2408
+ Response.error = function() {
2409
+ var r = new Response(null, { status: 0, statusText: '' });
2410
+ r.type = 'error';
2411
+ r.ok = false;
2412
+ return r;
2413
+ };
2414
+
2415
+ Response.redirect = function(url, status) {
2416
+ if (status === undefined) status = 302;
2417
+ var r = new Response(null, {
2418
+ status: status,
2419
+ statusText: '',
2420
+ headers: new Headers({ location: String(url) })
2421
+ });
2422
+ r.redirected = true;
2423
+ return r;
2424
+ };
2425
+
2426
+ // --- Request ---
2427
+ function Request(input, init) {
2428
+ if (init === undefined) init = {};
2429
+ if (input instanceof Request) {
2430
+ this.url = input.url;
2431
+ this.method = input.method;
2432
+ this.headers = new Headers(input.headers);
2433
+ this.body = input.body;
2434
+ } else {
2435
+ this.url = String(input);
2436
+ this.method = 'GET';
2437
+ this.headers = new Headers();
2438
+ this.body = null;
2439
+ }
2440
+ if (init.method !== undefined) this.method = String(init.method).toUpperCase();
2441
+ if (init.headers !== undefined) this.headers = init.headers instanceof Headers ? init.headers : new Headers(init.headers);
2442
+ if (init.body !== undefined) this.body = init.body !== null ? String(init.body) : null;
2443
+ }
2444
+
2445
+ Request.prototype.clone = function() {
2446
+ return new Request(this);
2447
+ };
2448
+
2449
+ // --- Assign to globalThis ---
2450
+ globalThis.URLSearchParams = URLSearchParams;
2451
+ globalThis.URL = URL;
2452
+ globalThis.Headers = Headers;
2453
+ globalThis.Response = Response;
2454
+ globalThis.Request = Request;
2455
+
2456
+ // --- Wrap native fetch ---
2457
+ var _nativeFetch = globalThis[Symbol.for('jb:fetch')];
2458
+ globalThis.fetch = function fetch(input, init) {
2459
+ try {
2460
+ var url, method, headers, body;
2461
+
2462
+ if (input instanceof Request) {
2463
+ url = input.url;
2464
+ method = input.method;
2465
+ headers = {};
2466
+ input.headers.forEach(function(v, k) { headers[k] = v; });
2467
+ body = input.body;
2468
+ } else {
2469
+ url = String(input);
2470
+ method = undefined;
2471
+ headers = undefined;
2472
+ body = undefined;
2473
+ }
2474
+
2475
+ if (init) {
2476
+ if (init.method !== undefined) method = String(init.method).toUpperCase();
2477
+ if (init.headers !== undefined) {
2478
+ var h = init.headers instanceof Headers ? init.headers : new Headers(init.headers);
2479
+ headers = {};
2480
+ h.forEach(function(v, k) { headers[k] = v; });
2481
+ }
2482
+ if (init.body !== undefined) body = init.body !== null ? String(init.body) : undefined;
2483
+ }
2484
+
2485
+ var opts = Object.create(null);
2486
+ if (method) opts.method = method;
2487
+ if (headers) opts.headers = headers;
2488
+ if (body) opts.body = body;
2489
+
2490
+ var raw = _nativeFetch(url, opts);
2491
+
2492
+ var respHeaders = new Headers(raw.headers || {});
2493
+ var response = new Response(raw.body, {
2494
+ status: raw.status,
2495
+ statusText: raw.statusText || '',
2496
+ headers: respHeaders
2497
+ });
2498
+ response.url = raw.url || url;
2499
+
2500
+ return Promise.resolve(response);
2501
+ } catch (e) {
2502
+ return Promise.reject(new TypeError(e.message || 'fetch failed'));
2503
+ }
2504
+ };
2505
+ })();
2506
+ `;
2507
+
2508
+ // src/commands/js-exec/module-shims.ts
2509
+ var EVENTS_MODULE_SOURCE = `
2510
+ var EventEmitter = (function() {
2511
+ function EE() {
2512
+ this._events = {};
2513
+ this._maxListeners = 10;
2514
+ }
2515
+ EE.prototype.on = function(event, listener) {
2516
+ if (!this._events[event]) this._events[event] = [];
2517
+ this._events[event].push(listener);
2518
+ return this;
2519
+ };
2520
+ EE.prototype.addListener = EE.prototype.on;
2521
+ EE.prototype.once = function(event, listener) {
2522
+ var self = this;
2523
+ function wrapper() {
2524
+ self.removeListener(event, wrapper);
2525
+ listener.apply(this, arguments);
2526
+ }
2527
+ wrapper._original = listener;
2528
+ return this.on(event, wrapper);
2529
+ };
2530
+ EE.prototype.off = function(event, listener) {
2531
+ return this.removeListener(event, listener);
2532
+ };
2533
+ EE.prototype.removeListener = function(event, listener) {
2534
+ var list = this._events[event];
2535
+ if (list) {
2536
+ this._events[event] = list.filter(function(fn) {
2537
+ return fn !== listener && fn._original !== listener;
2538
+ });
2539
+ }
2540
+ return this;
2541
+ };
2542
+ EE.prototype.removeAllListeners = function(event) {
2543
+ if (event) delete this._events[event];
2544
+ else this._events = {};
2545
+ return this;
2546
+ };
2547
+ EE.prototype.emit = function(event) {
2548
+ var list = this._events[event];
2549
+ if (!list || list.length === 0) return false;
2550
+ var args = Array.prototype.slice.call(arguments, 1);
2551
+ var fns = list.slice();
2552
+ for (var i = 0; i < fns.length; i++) fns[i].apply(this, args);
2553
+ return true;
2554
+ };
2555
+ EE.prototype.listeners = function(event) {
2556
+ return (this._events[event] || []).slice();
2557
+ };
2558
+ EE.prototype.listenerCount = function(event) {
2559
+ return (this._events[event] || []).length;
2560
+ };
2561
+ EE.prototype.setMaxListeners = function(n) {
2562
+ this._maxListeners = n;
2563
+ return this;
2564
+ };
2565
+ EE.prototype.eventNames = function() {
2566
+ return Object.keys(this._events);
2567
+ };
2568
+ EE.prototype.prependListener = function(event, listener) {
2569
+ if (!this._events[event]) this._events[event] = [];
2570
+ this._events[event].unshift(listener);
2571
+ return this;
2572
+ };
2573
+ return EE;
2574
+ })();
2575
+ globalThis[Symbol.for('jb:events')] = { EventEmitter: EventEmitter };
2576
+ `;
2577
+ var OS_MODULE_SOURCE = `
2578
+ var _os = {
2579
+ platform: function() { return globalThis.process.platform; },
2580
+ arch: function() { return globalThis.process.arch; },
2581
+ homedir: function() { return '/home/user'; },
2582
+ tmpdir: function() { return '/tmp'; },
2583
+ type: function() { return 'Linux'; },
2584
+ hostname: function() { return 'sandbox'; },
2585
+ EOL: '\\n',
2586
+ cpus: function() { return []; },
2587
+ totalmem: function() { return 0; },
2588
+ freemem: function() { return 0; },
2589
+ endianness: function() { return 'LE'; }
2590
+ };
2591
+ globalThis[Symbol.for('jb:os')] = _os;
2592
+ `;
2593
+ var URL_MODULE_SOURCE = `
2594
+ var _urlMod = {
2595
+ URL: globalThis.URL,
2596
+ URLSearchParams: globalThis.URLSearchParams,
2597
+ parse: function(urlStr) {
2598
+ try {
2599
+ var u = new URL(urlStr);
2600
+ return {
2601
+ protocol: u.protocol, host: u.host, hostname: u.hostname,
2602
+ port: u.port, pathname: u.pathname, search: u.search,
2603
+ hash: u.hash, href: u.href, path: u.pathname + u.search
2604
+ };
2605
+ } catch(e) {
2606
+ return {
2607
+ protocol: null, host: null, hostname: null, port: null,
2608
+ pathname: urlStr, search: '', hash: '', href: urlStr, path: urlStr
2609
+ };
2610
+ }
2611
+ },
2612
+ format: function(obj) {
2613
+ if (typeof obj === 'string') return obj;
2614
+ if (obj instanceof URL) return obj.href;
2615
+ var auth = obj.auth ? obj.auth + '@' : '';
2616
+ var host = obj.host || ((obj.hostname || '') + (obj.port ? ':' + obj.port : ''));
2617
+ return (obj.protocol ? obj.protocol + '//' : '') + auth + host +
2618
+ (obj.pathname || '/') + (obj.search || '') + (obj.hash || '');
2619
+ }
2620
+ };
2621
+ globalThis[Symbol.for('jb:url')] = _urlMod;
2622
+ `;
2623
+ var ASSERT_MODULE_SOURCE = `
2624
+ var _deepEqual = function(a, b) {
2625
+ if (a === b) return true;
2626
+ if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false;
2627
+ if (Array.isArray(a) !== Array.isArray(b)) return false;
2628
+ var ka = Object.keys(a), kb = Object.keys(b);
2629
+ if (ka.length !== kb.length) return false;
2630
+ for (var i = 0; i < ka.length; i++) {
2631
+ if (!_deepEqual(a[ka[i]], b[ka[i]])) return false;
2632
+ }
2633
+ return true;
2634
+ };
2635
+ var _assert = function(val, msg) {
2636
+ if (!val) throw new Error(msg || 'AssertionError: expected truthy value');
2637
+ };
2638
+ _assert.ok = _assert;
2639
+ _assert.equal = function(a, b, msg) {
2640
+ if (a != b) throw new Error(msg || 'AssertionError: ' + a + ' != ' + b);
2641
+ };
2642
+ _assert.notEqual = function(a, b, msg) {
2643
+ if (a == b) throw new Error(msg || 'AssertionError: ' + a + ' == ' + b);
2644
+ };
2645
+ _assert.strictEqual = function(a, b, msg) {
2646
+ if (a !== b) throw new Error(msg || 'AssertionError: ' + a + ' !== ' + b);
2647
+ };
2648
+ _assert.notStrictEqual = function(a, b, msg) {
2649
+ if (a === b) throw new Error(msg || 'AssertionError: ' + a + ' === ' + b);
2650
+ };
2651
+ _assert.deepEqual = function(a, b, msg) {
2652
+ if (!_deepEqual(a, b)) throw new Error(msg || 'AssertionError: objects not deep equal');
2653
+ };
2654
+ _assert.deepStrictEqual = _assert.deepEqual;
2655
+ _assert.notDeepEqual = function(a, b, msg) {
2656
+ if (_deepEqual(a, b)) throw new Error(msg || 'AssertionError: objects are deep equal');
2657
+ };
2658
+ _assert.throws = function(fn, expected, msg) {
2659
+ var threw = false;
2660
+ try { fn(); } catch(e) {
2661
+ threw = true;
2662
+ if (expected instanceof RegExp && !expected.test(e.message))
2663
+ throw new Error(msg || 'AssertionError: error message did not match');
2664
+ }
2665
+ if (!threw) throw new Error(msg || 'AssertionError: function did not throw');
2666
+ };
2667
+ _assert.doesNotThrow = function(fn, msg) {
2668
+ // @banned-pattern-ignore: sandbox-internal assertion helper; e.message is from user code inside QuickJS, not host details
2669
+ try { fn(); } catch(e) {
2670
+ throw new Error(msg || 'AssertionError: function threw: ' + e.message);
2671
+ }
2672
+ };
2673
+ _assert.fail = function(msg) {
2674
+ throw new Error(msg || 'AssertionError: assert.fail()');
2675
+ };
2676
+ globalThis[Symbol.for('jb:assert')] = _assert;
2677
+ `;
2678
+ var UTIL_MODULE_SOURCE = `
2679
+ var _util = {
2680
+ format: function() {
2681
+ var args = Array.prototype.slice.call(arguments);
2682
+ if (args.length === 0) return '';
2683
+ var fmt = args[0];
2684
+ if (typeof fmt !== 'string') {
2685
+ return args.map(function(a) {
2686
+ return typeof a === 'string' ? a : JSON.stringify(a);
2687
+ }).join(' ');
2688
+ }
2689
+ var i = 1;
2690
+ var str = fmt.replace(/%[sdjifoO%]/g, function(m) {
2691
+ if (m === '%%') return '%';
2692
+ if (i >= args.length) return m;
2693
+ var v = args[i++];
2694
+ if (m === '%s') return String(v);
2695
+ if (m === '%d') return Number(v).toString();
2696
+ if (m === '%i') { var n = Number(v); return (isNaN(n) ? 'NaN' : Math.trunc(n)).toString(); }
2697
+ if (m === '%j') return JSON.stringify(v);
2698
+ if (m === '%f') return parseFloat(v).toString();
2699
+ if (m === '%o' || m === '%O') return JSON.stringify(v);
2700
+ return m;
2701
+ });
2702
+ while (i < args.length) {
2703
+ str += ' ' + (typeof args[i] === 'string' ? args[i] : JSON.stringify(args[i]));
2704
+ i++;
2705
+ }
2706
+ return str;
2707
+ },
2708
+ inspect: function(obj, opts) {
2709
+ if (obj === null) return 'null';
2710
+ if (obj === undefined) return 'undefined';
2711
+ if (typeof obj === 'string') return "'" + obj + "'";
2712
+ if (typeof obj === 'function') return '[Function: ' + (obj.name || 'anonymous') + ']';
2713
+ var seen = [];
2714
+ try {
2715
+ return JSON.stringify(obj, function(key, val) {
2716
+ if (typeof val === 'object' && val !== null) {
2717
+ if (seen.indexOf(val) !== -1) return '[Circular]';
2718
+ seen.push(val);
2719
+ }
2720
+ return val;
2721
+ });
2722
+ } catch(e) { return String(obj); }
2723
+ },
2724
+ promisify: function(fn) {
2725
+ return function() {
2726
+ var args = Array.prototype.slice.call(arguments);
2727
+ return new Promise(function(resolve, reject) {
2728
+ args.push(function(err, val) { if (err) reject(err); else resolve(val); });
2729
+ fn.apply(null, args);
2730
+ });
2731
+ };
2732
+ },
2733
+ types: {
2734
+ isDate: function(v) { return v instanceof Date; },
2735
+ isRegExp: function(v) { return v instanceof RegExp; },
2736
+ isArray: function(v) { return Array.isArray(v); },
2737
+ isMap: function(v) { return typeof Map !== 'undefined' && v instanceof Map; },
2738
+ isSet: function(v) { return typeof Set !== 'undefined' && v instanceof Set; }
2739
+ },
2740
+ inherits: function(ctor, superCtor) {
2741
+ ctor.prototype = Object.create(superCtor.prototype);
2742
+ ctor.prototype.constructor = ctor;
2743
+ }
2744
+ };
2745
+ globalThis[Symbol.for('jb:util')] = _util;
2746
+ `;
2747
+ var BUFFER_MODULE_SOURCE = `
2748
+ function _utf8Encode(str) {
2749
+ var bytes = [];
2750
+ for (var i = 0; i < str.length; i++) {
2751
+ var c = str.charCodeAt(i);
2752
+ if (c < 0x80) {
2753
+ bytes.push(c);
2754
+ } else if (c < 0x800) {
2755
+ bytes.push(0xC0 | (c >> 6), 0x80 | (c & 0x3F));
2756
+ } else if (c >= 0xD800 && c <= 0xDBFF && i + 1 < str.length) {
2757
+ var lo = str.charCodeAt(++i);
2758
+ var cp = ((c - 0xD800) * 0x400) + (lo - 0xDC00) + 0x10000;
2759
+ bytes.push(0xF0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3F), 0x80 | ((cp >> 6) & 0x3F), 0x80 | (cp & 0x3F));
2760
+ } else {
2761
+ bytes.push(0xE0 | (c >> 12), 0x80 | ((c >> 6) & 0x3F), 0x80 | (c & 0x3F));
2762
+ }
2763
+ }
2764
+ return bytes;
2765
+ }
2766
+ function _utf8Decode(bytes) {
2767
+ var str = '';
2768
+ var i = 0;
2769
+ while (i < bytes.length) {
2770
+ var b = bytes[i];
2771
+ if (b < 0x80) { str += String.fromCharCode(b); i++; }
2772
+ else if ((b & 0xE0) === 0xC0) { str += String.fromCharCode(((b & 0x1F) << 6) | (bytes[i+1] & 0x3F)); i += 2; }
2773
+ else if ((b & 0xF0) === 0xE0) { str += String.fromCharCode(((b & 0x0F) << 12) | ((bytes[i+1] & 0x3F) << 6) | (bytes[i+2] & 0x3F)); i += 3; }
2774
+ else if ((b & 0xF8) === 0xF0) { var cp = ((b & 0x07) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F); cp -= 0x10000; str += String.fromCharCode((cp >> 10) + 0xD800, (cp & 0x3FF) + 0xDC00); i += 4; }
2775
+ else { i++; }
2776
+ }
2777
+ return str;
2778
+ }
2779
+ // _utf8Encode/_utf8Decode are IIFE-local vars, available to all module shims
2780
+
2781
+ function Buffer(arg) {
2782
+ if (typeof arg === 'number') {
2783
+ this._data = new Uint8Array(arg);
2784
+ } else if (arg instanceof ArrayBuffer) {
2785
+ this._data = new Uint8Array(arg);
2786
+ } else if (arg instanceof Uint8Array) {
2787
+ this._data = new Uint8Array(arg);
2788
+ } else if (Array.isArray(arg)) {
2789
+ this._data = new Uint8Array(arg);
2790
+ } else {
2791
+ this._data = new Uint8Array(0);
2792
+ }
2793
+ this.length = this._data.length;
2794
+ }
2795
+ Buffer.from = function(data, encoding) {
2796
+ if (typeof data === 'string') {
2797
+ return new Buffer(_utf8Encode(data));
2798
+ }
2799
+ if (data instanceof ArrayBuffer) return new Buffer(data);
2800
+ if (data instanceof Uint8Array) return new Buffer(data);
2801
+ if (Array.isArray(data)) return new Buffer(data);
2802
+ if (data && data._data) return new Buffer(data._data.slice());
2803
+ return new Buffer(0);
2804
+ };
2805
+ Buffer.alloc = function(size, fill) {
2806
+ var buf = new Buffer(size);
2807
+ if (fill !== undefined) {
2808
+ var fillByte = typeof fill === 'number' ? fill : 0;
2809
+ buf._data.fill(fillByte);
2810
+ }
2811
+ return buf;
2812
+ };
2813
+ Buffer.allocUnsafe = Buffer.alloc;
2814
+ Buffer.isBuffer = function(obj) { return obj instanceof Buffer; };
2815
+ Buffer.concat = function(list, totalLength) {
2816
+ if (!totalLength) {
2817
+ totalLength = 0;
2818
+ for (var i = 0; i < list.length; i++) totalLength += list[i].length;
2819
+ }
2820
+ var result = new Uint8Array(totalLength);
2821
+ var offset = 0;
2822
+ for (var i = 0; i < list.length; i++) {
2823
+ result.set(list[i]._data, offset);
2824
+ offset += list[i].length;
2825
+ }
2826
+ return new Buffer(result);
2827
+ };
2828
+ Buffer.byteLength = function(str) {
2829
+ return _utf8Encode(str).length;
2830
+ };
2831
+ Buffer.prototype.toString = function(encoding) {
2832
+ return _utf8Decode(this._data);
2833
+ };
2834
+ Buffer.prototype.toJSON = function() {
2835
+ return { type: 'Buffer', data: Array.from(this._data) };
2836
+ };
2837
+ Buffer.prototype.slice = function(start, end) {
2838
+ return new Buffer(this._data.slice(start, end));
2839
+ };
2840
+ Buffer.prototype.copy = function(target, targetStart, sourceStart, sourceEnd) {
2841
+ targetStart = targetStart || 0;
2842
+ sourceStart = sourceStart || 0;
2843
+ sourceEnd = sourceEnd || this.length;
2844
+ var sub = this._data.subarray(sourceStart, sourceEnd);
2845
+ target._data.set(sub, targetStart);
2846
+ return sub.length;
2847
+ };
2848
+ Buffer.prototype.write = function(str, offset) {
2849
+ var bytes = _utf8Encode(str);
2850
+ offset = offset || 0;
2851
+ this._data.set(bytes, offset);
2852
+ return bytes.length;
2853
+ };
2854
+ Buffer.prototype.fill = function(val, offset, end) {
2855
+ this._data.fill(typeof val === 'number' ? val : 0, offset, end);
2856
+ return this;
2857
+ };
2858
+ Buffer.prototype.equals = function(other) {
2859
+ if (this.length !== other.length) return false;
2860
+ for (var i = 0; i < this.length; i++) {
2861
+ if (this._data[i] !== other._data[i]) return false;
2862
+ }
2863
+ return true;
2864
+ };
2865
+ Buffer.prototype.readUInt8 = function(offset) { return this._data[offset]; };
2866
+ Buffer.prototype.writeUInt8 = function(value, offset) { this._data[offset] = value; return offset + 1; };
2867
+ globalThis[Symbol.for('jb:buffer')] = { Buffer: Buffer };
2868
+ globalThis.Buffer = Buffer;
2869
+ `;
2870
+ var STREAM_MODULE_SOURCE = `
2871
+ var _EE = globalThis[Symbol.for('jb:events')].EventEmitter;
2872
+
2873
+ function Stream() { _EE.call(this); }
2874
+ Stream.prototype = Object.create(_EE.prototype);
2875
+ Stream.prototype.constructor = Stream;
2876
+ Stream.prototype.pipe = function(dest) {
2877
+ this.on('data', function(chunk) { dest.write(chunk); });
2878
+ this.on('end', function() { if (dest.end) dest.end(); });
2879
+ return dest;
2880
+ };
2881
+
2882
+ function Readable(opts) {
2883
+ Stream.call(this);
2884
+ this.readable = true;
2885
+ this._readableState = { ended: false, buffer: [] };
2886
+ }
2887
+ Readable.prototype = Object.create(Stream.prototype);
2888
+ Readable.prototype.constructor = Readable;
2889
+ Readable.prototype.read = function() { return null; };
2890
+ Readable.prototype.push = function(chunk) {
2891
+ if (chunk === null) { this._readableState.ended = true; this.emit('end'); return false; }
2892
+ this.emit('data', chunk);
2893
+ return true;
2894
+ };
2895
+ Readable.prototype.destroy = function() { this.emit('close'); return this; };
2896
+
2897
+ function Writable(opts) {
2898
+ Stream.call(this);
2899
+ this.writable = true;
2900
+ this._writableState = { ended: false };
2901
+ }
2902
+ Writable.prototype = Object.create(Stream.prototype);
2903
+ Writable.prototype.constructor = Writable;
2904
+ Writable.prototype.write = function(chunk) { return true; };
2905
+ Writable.prototype.end = function(chunk) {
2906
+ if (chunk) this.write(chunk);
2907
+ this._writableState.ended = true;
2908
+ this.emit('finish');
2909
+ return this;
2910
+ };
2911
+ Writable.prototype.destroy = function() { this.emit('close'); return this; };
2912
+
2913
+ function Duplex(opts) {
2914
+ Readable.call(this, opts);
2915
+ Writable.call(this, opts);
2916
+ }
2917
+ Duplex.prototype = Object.create(Readable.prototype);
2918
+ var _wKeys = Object.keys(Writable.prototype);
2919
+ for (var _wi = 0; _wi < _wKeys.length; _wi++) {
2920
+ if (!Duplex.prototype[_wKeys[_wi]]) Duplex.prototype[_wKeys[_wi]] = Writable.prototype[_wKeys[_wi]];
2921
+ }
2922
+ Duplex.prototype.constructor = Duplex;
2923
+
2924
+ function Transform(opts) { Duplex.call(this, opts); }
2925
+ Transform.prototype = Object.create(Duplex.prototype);
2926
+ Transform.prototype.constructor = Transform;
2927
+ Transform.prototype._transform = function(chunk, encoding, cb) { if (cb) cb(null, chunk); };
2928
+
2929
+ function PassThrough(opts) { Transform.call(this, opts); }
2930
+ PassThrough.prototype = Object.create(Transform.prototype);
2931
+ PassThrough.prototype.constructor = PassThrough;
2932
+
2933
+ function pipeline() {
2934
+ var streams = Array.prototype.slice.call(arguments);
2935
+ var cb = typeof streams[streams.length - 1] === 'function' ? streams.pop() : null;
2936
+ for (var i = 0; i < streams.length - 1; i++) streams[i].pipe(streams[i + 1]);
2937
+ if (cb) {
2938
+ var last = streams[streams.length - 1];
2939
+ last.on('finish', function() { cb(null); });
2940
+ last.on('error', function(e) { cb(e); });
2941
+ }
2942
+ return streams[streams.length - 1];
2943
+ }
2944
+
2945
+ globalThis[Symbol.for('jb:stream')] = {
2946
+ Stream: Stream, Readable: Readable, Writable: Writable,
2947
+ Duplex: Duplex, Transform: Transform, PassThrough: PassThrough,
2948
+ pipeline: pipeline
2949
+ };
2950
+ `;
2951
+ var STRING_DECODER_MODULE_SOURCE = `
2952
+ function StringDecoder(encoding) {
2953
+ this.encoding = (encoding || 'utf-8').toLowerCase();
2954
+ if (this.encoding === 'utf8') this.encoding = 'utf-8';
2955
+ }
2956
+ StringDecoder.prototype.write = function(buf) {
2957
+ if (typeof buf === 'string') return buf;
2958
+ var data = buf instanceof Uint8Array ? buf : (buf && buf._data ? buf._data : new Uint8Array(0));
2959
+ return _utf8Decode(data);
2960
+ };
2961
+ StringDecoder.prototype.end = function(buf) {
2962
+ if (buf) return this.write(buf);
2963
+ return '';
2964
+ };
2965
+ globalThis[Symbol.for('jb:string_decoder')] = { StringDecoder: StringDecoder };
2966
+ `;
2967
+ var QUERYSTRING_MODULE_SOURCE = `
2968
+ var _qs = {
2969
+ parse: function(str, sep, eq) {
2970
+ sep = sep || '&'; eq = eq || '=';
2971
+ var result = Object.create(null);
2972
+ if (!str || typeof str !== 'string') return result;
2973
+ var pairs = str.split(sep);
2974
+ for (var i = 0; i < pairs.length; i++) {
2975
+ var idx = pairs[i].indexOf(eq);
2976
+ var key, val;
2977
+ if (idx >= 0) {
2978
+ key = decodeURIComponent(pairs[i].slice(0, idx).replace(/\\+/g, ' '));
2979
+ val = decodeURIComponent(pairs[i].slice(idx + 1).replace(/\\+/g, ' '));
2980
+ } else {
2981
+ key = decodeURIComponent(pairs[i].replace(/\\+/g, ' '));
2982
+ val = '';
2983
+ }
2984
+ if (result[key] !== undefined) {
2985
+ if (Array.isArray(result[key])) result[key].push(val);
2986
+ else result[key] = [result[key], val];
2987
+ } else {
2988
+ result[key] = val;
2989
+ }
2990
+ }
2991
+ return result;
2992
+ },
2993
+ stringify: function(obj, sep, eq) {
2994
+ sep = sep || '&'; eq = eq || '=';
2995
+ var pairs = [];
2996
+ var keys = Object.keys(obj);
2997
+ for (var i = 0; i < keys.length; i++) {
2998
+ var key = keys[i];
2999
+ var val = obj[key];
3000
+ if (Array.isArray(val)) {
3001
+ for (var j = 0; j < val.length; j++) {
3002
+ pairs.push(encodeURIComponent(key) + eq + encodeURIComponent(val[j]));
3003
+ }
3004
+ } else {
3005
+ pairs.push(encodeURIComponent(key) + eq + encodeURIComponent(val));
3006
+ }
3007
+ }
3008
+ return pairs.join(sep);
3009
+ },
3010
+ escape: function(str) { return encodeURIComponent(str); },
3011
+ unescape: function(str) { return decodeURIComponent(str); }
3012
+ };
3013
+ _qs.decode = _qs.parse;
3014
+ _qs.encode = _qs.stringify;
3015
+ globalThis[Symbol.for('jb:querystring')] = _qs;
3016
+ `;
3017
+ var UNSUPPORTED_MODULES = Object.assign(
3018
+ /* @__PURE__ */ Object.create(null),
3019
+ {
3020
+ http: "Use fetch() for HTTP requests.",
3021
+ https: "Use fetch() for HTTP requests.",
3022
+ http2: "Use fetch() for HTTP requests.",
3023
+ net: "Network socket APIs are not supported.",
3024
+ tls: "Network socket APIs are not supported.",
3025
+ dgram: "Network socket APIs are not supported.",
3026
+ dns: "DNS APIs are not supported.",
3027
+ cluster: "Cluster APIs are not supported.",
3028
+ worker_threads: "Worker thread APIs are not supported.",
3029
+ vm: "VM APIs are not supported.",
3030
+ v8: "V8 APIs are not supported.",
3031
+ inspector: "Inspector APIs are not supported.",
3032
+ readline: "Readline APIs are not supported.",
3033
+ repl: "REPL APIs are not supported.",
3034
+ module: "Module APIs are not supported.",
3035
+ perf_hooks: "Performance hooks are not supported.",
3036
+ async_hooks: "Async hooks are not supported.",
3037
+ diagnostics_channel: "Diagnostics channel is not supported.",
3038
+ trace_events: "Trace events are not supported.",
3039
+ crypto: "Crypto APIs are not available in this sandbox.",
3040
+ zlib: "Compression APIs are not supported.",
3041
+ tty: "TTY APIs are not supported.",
3042
+ domain: "Domain APIs are not supported."
3043
+ }
3044
+ );
3045
+
3046
+ // src/commands/js-exec/path-polyfill.ts
3047
+ var PATH_MODULE_SOURCE = `
3048
+ (function() {
3049
+ var sep = '/';
3050
+ var delimiter = ':';
3051
+
3052
+ function normalize(p) {
3053
+ if (p === '') return '.';
3054
+ var isAbs = p.charCodeAt(0) === 47;
3055
+ var trailingSlash = p.charCodeAt(p.length - 1) === 47;
3056
+ var parts = p.split('/');
3057
+ var out = [];
3058
+ for (var i = 0; i < parts.length; i++) {
3059
+ var seg = parts[i];
3060
+ if (seg === '' || seg === '.') continue;
3061
+ if (seg === '..') {
3062
+ if (out.length > 0 && out[out.length - 1] !== '..') out.pop();
3063
+ else if (!isAbs) out.push('..');
3064
+ } else {
3065
+ out.push(seg);
3066
+ }
3067
+ }
3068
+ var result = out.join('/');
3069
+ if (isAbs) result = '/' + result;
3070
+ if (trailingSlash && result[result.length - 1] !== '/') result += '/';
3071
+ return result || (isAbs ? '/' : '.');
3072
+ }
3073
+
3074
+ function join() {
3075
+ var joined = '';
3076
+ for (var i = 0; i < arguments.length; i++) {
3077
+ var arg = arguments[i];
3078
+ if (typeof arg !== 'string') throw new TypeError('Path must be a string');
3079
+ if (arg.length > 0) {
3080
+ if (joined.length > 0) joined += '/' + arg;
3081
+ else joined = arg;
3082
+ }
3083
+ }
3084
+ if (joined.length === 0) return '.';
3085
+ return normalize(joined);
3086
+ }
3087
+
3088
+ function resolve() {
3089
+ var resolved = '';
3090
+ var resolvedAbsolute = false;
3091
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
3092
+ var path = i >= 0 ? arguments[i] : globalThis.process.cwd();
3093
+ if (typeof path !== 'string') throw new TypeError('Path must be a string');
3094
+ if (path.length === 0) continue;
3095
+ if (resolved.length > 0) resolved = path + '/' + resolved;
3096
+ else resolved = path;
3097
+ resolvedAbsolute = path.charCodeAt(0) === 47;
3098
+ }
3099
+ resolved = normalize(resolved);
3100
+ if (resolvedAbsolute) return '/' + resolved.replace(/^\\/+/, '');
3101
+ return resolved.length > 0 ? resolved : '.';
3102
+ }
3103
+
3104
+ function isAbsolute(p) {
3105
+ return typeof p === 'string' && p.length > 0 && p.charCodeAt(0) === 47;
3106
+ }
3107
+
3108
+ function dirname(p) {
3109
+ if (p.length === 0) return '.';
3110
+ var hasRoot = p.charCodeAt(0) === 47;
3111
+ var end = -1;
3112
+ for (var i = p.length - 1; i >= 1; i--) {
3113
+ if (p.charCodeAt(i) === 47) { end = i; break; }
3114
+ }
3115
+ if (end === -1) return hasRoot ? '/' : '.';
3116
+ if (hasRoot && end === 0) return '/';
3117
+ return p.slice(0, end);
3118
+ }
3119
+
3120
+ function basename(p, ext) {
3121
+ var start = 0;
3122
+ for (var i = p.length - 1; i >= 0; i--) {
3123
+ if (p.charCodeAt(i) === 47) { start = i + 1; break; }
3124
+ }
3125
+ var base = p.slice(start);
3126
+ if (ext && base.endsWith(ext)) {
3127
+ base = base.slice(0, base.length - ext.length);
3128
+ }
3129
+ return base;
3130
+ }
3131
+
3132
+ function extname(p) {
3133
+ var startDot = -1;
3134
+ var startPart = 0;
3135
+ for (var i = p.length - 1; i >= 0; i--) {
3136
+ var code = p.charCodeAt(i);
3137
+ if (code === 47) { startPart = i + 1; break; }
3138
+ if (code === 46 && startDot === -1) startDot = i;
3139
+ }
3140
+ if (startDot === -1 || startDot === startPart ||
3141
+ (startDot === startPart + 1 && p.charCodeAt(startPart) === 46)) {
3142
+ return '';
3143
+ }
3144
+ return p.slice(startDot);
3145
+ }
3146
+
3147
+ function relative(from, to) {
3148
+ if (from === to) return '';
3149
+ from = resolve(from);
3150
+ to = resolve(to);
3151
+ if (from === to) return '';
3152
+ var fromParts = from.split('/').filter(Boolean);
3153
+ var toParts = to.split('/').filter(Boolean);
3154
+ var common = 0;
3155
+ var length = Math.min(fromParts.length, toParts.length);
3156
+ for (var i = 0; i < length; i++) {
3157
+ if (fromParts[i] !== toParts[i]) break;
3158
+ common++;
3159
+ }
3160
+ var ups = [];
3161
+ for (var i = common; i < fromParts.length; i++) ups.push('..');
3162
+ return ups.concat(toParts.slice(common)).join('/') || '.';
3163
+ }
3164
+
3165
+ function parse(p) {
3166
+ var root = p.charCodeAt(0) === 47 ? '/' : '';
3167
+ var dir = dirname(p);
3168
+ var base = basename(p);
3169
+ var ext = extname(p);
3170
+ var name = ext ? base.slice(0, base.length - ext.length) : base;
3171
+ return { root: root, dir: dir, base: base, ext: ext, name: name };
3172
+ }
3173
+
3174
+ function format(obj) {
3175
+ var dir = obj.dir || obj.root || '';
3176
+ var base = obj.base || ((obj.name || '') + (obj.ext || ''));
3177
+ if (!dir) return base;
3178
+ if (dir === obj.root) return dir + base;
3179
+ return dir + '/' + base;
3180
+ }
3181
+
3182
+ var posix = { sep: sep, delimiter: delimiter, join: join, resolve: resolve, normalize: normalize, isAbsolute: isAbsolute, dirname: dirname, basename: basename, extname: extname, relative: relative, parse: parse, format: format };
3183
+ posix.posix = posix;
3184
+
3185
+ globalThis[Symbol.for('jb:path')] = posix;
3186
+ })();
3187
+ `;
3188
+
3189
+ // src/commands/js-exec/worker.ts
3190
+ var quickjsModule = null;
3191
+ var quickjsLoading = null;
3192
+ async function getQuickJSModule() {
3193
+ if (quickjsModule) {
3194
+ return quickjsModule;
3195
+ }
3196
+ if (quickjsLoading) {
3197
+ return quickjsLoading;
3198
+ }
3199
+ quickjsLoading = getQuickJS();
3200
+ quickjsModule = await quickjsLoading;
3201
+ return quickjsModule;
3202
+ }
3203
+ var MEMORY_LIMIT = 64 * 1024 * 1024;
3204
+ var INTERRUPT_CYCLES = 1e5;
3205
+ function formatError(errorVal) {
3206
+ if (typeof errorVal === "object" && errorVal !== null && "message" in errorVal) {
3207
+ const err = errorVal;
3208
+ const msg = err.message;
3209
+ if (err.stack) {
3210
+ const lines = err.stack.split("\n");
3211
+ for (const line of lines) {
3212
+ const trimmed = line.trim();
3213
+ if (trimmed.startsWith("at ")) {
3214
+ const cleaned = trimmed.replace(/^at <eval> \((\/.+)\)$/, "at $1");
3215
+ return `${cleaned}: ${msg}`;
3216
+ }
3217
+ }
3218
+ }
3219
+ return msg;
3220
+ }
3221
+ return String(errorVal);
3222
+ }
3223
+ function throwError(context, message) {
3224
+ return { error: context.newError(message) };
3225
+ }
3226
+ function jsToHandle(context, value) {
3227
+ if (value === null || value === void 0) {
3228
+ return context.undefined;
3229
+ }
3230
+ if (typeof value === "string") {
3231
+ return context.newString(value);
3232
+ }
3233
+ if (typeof value === "number") {
3234
+ return context.newNumber(value);
3235
+ }
3236
+ if (typeof value === "boolean") {
3237
+ return value ? context.true : context.false;
3238
+ }
3239
+ if (Array.isArray(value)) {
3240
+ const arr = context.newArray();
3241
+ for (let i = 0; i < value.length; i++) {
3242
+ const elemHandle = jsToHandle(context, value[i]);
3243
+ context.setProp(arr, i, elemHandle);
3244
+ elemHandle.dispose();
3245
+ }
3246
+ return arr;
3247
+ }
3248
+ if (typeof value === "object") {
3249
+ const obj = context.newObject();
3250
+ for (const [k, v] of Object.entries(value)) {
3251
+ const valHandle = jsToHandle(context, v);
3252
+ context.setProp(obj, k, valHandle);
3253
+ valHandle.dispose();
3254
+ }
3255
+ return obj;
3256
+ }
3257
+ return context.undefined;
3258
+ }
3259
+ function resolveModulePath(name, fromFile, cwd) {
3260
+ if (name.startsWith("/")) return name;
3261
+ const base = fromFile ? fromFile.substring(0, fromFile.lastIndexOf("/")) || "/" : cwd;
3262
+ const parts = `${base}/${name}`.split("/").filter(Boolean);
3263
+ const resolved = [];
3264
+ for (const p of parts) {
3265
+ if (p === "..") resolved.pop();
3266
+ else if (p !== ".") resolved.push(p);
3267
+ }
3268
+ return `/${resolved.join("/")}`;
3269
+ }
3270
+ var VIRTUAL_MODULES = Object.assign(
3271
+ /* @__PURE__ */ Object.create(null),
3272
+ {
3273
+ fs: `
3274
+ const _fs = globalThis.fs;
3275
+ export const readFile = _fs.readFile;
3276
+ export const readFileSync = function(path, opts) { return _fs.readFileSync(path, opts); };
3277
+ export const readFileBuffer = _fs.readFileBuffer;
3278
+ export const writeFile = _fs.writeFile;
3279
+ export const writeFileSync = _fs.writeFileSync;
3280
+ export const stat = _fs.stat;
3281
+ export const statSync = _fs.statSync;
3282
+ export const lstat = _fs.lstat;
3283
+ export const lstatSync = _fs.lstatSync;
3284
+ export const readdir = _fs.readdir;
3285
+ export const readdirSync = _fs.readdirSync;
3286
+ export const mkdir = _fs.mkdir;
3287
+ export const mkdirSync = _fs.mkdirSync;
3288
+ export const rm = _fs.rm;
3289
+ export const rmSync = _fs.rmSync;
3290
+ export const exists = _fs.exists;
3291
+ export const existsSync = _fs.existsSync;
3292
+ export const appendFile = _fs.appendFile;
3293
+ export const appendFileSync = _fs.appendFileSync;
3294
+ export const symlink = _fs.symlink;
3295
+ export const symlinkSync = _fs.symlinkSync;
3296
+ export const readlink = _fs.readlink;
3297
+ export const readlinkSync = _fs.readlinkSync;
3298
+ export const chmod = _fs.chmod;
3299
+ export const chmodSync = _fs.chmodSync;
3300
+ export const realpath = _fs.realpath;
3301
+ export const realpathSync = _fs.realpathSync;
3302
+ export const rename = _fs.rename;
3303
+ export const renameSync = _fs.renameSync;
3304
+ export const copyFile = _fs.copyFile;
3305
+ export const copyFileSync = _fs.copyFileSync;
3306
+ export const unlinkSync = _fs.unlinkSync;
3307
+ export const unlink = _fs.unlink;
3308
+ export const rmdirSync = _fs.rmdirSync;
3309
+ export const rmdir = _fs.rmdir;
3310
+ export const promises = _fs.promises;
3311
+ export default _fs;
3312
+ `,
3313
+ path: `${PATH_MODULE_SOURCE}
3314
+ const _path = globalThis[Symbol.for('jb:path')];
3315
+ export const join = _path.join;
3316
+ export const resolve = _path.resolve;
3317
+ export const normalize = _path.normalize;
3318
+ export const isAbsolute = _path.isAbsolute;
3319
+ export const dirname = _path.dirname;
3320
+ export const basename = _path.basename;
3321
+ export const extname = _path.extname;
3322
+ export const relative = _path.relative;
3323
+ export const parse = _path.parse;
3324
+ export const format = _path.format;
3325
+ export const sep = _path.sep;
3326
+ export const delimiter = _path.delimiter;
3327
+ export const posix = _path.posix;
3328
+ export default _path;
3329
+ `,
3330
+ process: `
3331
+ const _process = globalThis.process;
3332
+ export const argv = _process.argv;
3333
+ export const cwd = _process.cwd;
3334
+ export const exit = _process.exit;
3335
+ export const env = _process.env;
3336
+ export const platform = _process.platform;
3337
+ export const arch = _process.arch;
3338
+ export const versions = _process.versions;
3339
+ export const version = _process.version;
3340
+ export default _process;
3341
+ `,
3342
+ child_process: `
3343
+ const _exec = globalThis[Symbol.for('jb:exec')];
3344
+ const _execArgs = globalThis[Symbol.for('jb:execArgs')];
3345
+ export function execSync(cmd, opts) {
3346
+ var r = _exec(cmd, opts);
3347
+ if (r.exitCode !== 0) {
3348
+ var e = new Error('Command failed: ' + cmd);
3349
+ e.status = r.exitCode;
3350
+ e.stderr = r.stderr;
3351
+ e.stdout = r.stdout;
3352
+ throw e;
3353
+ }
3354
+ return r.stdout;
3355
+ }
3356
+ export function exec(cmd, opts) { return _exec(cmd, opts); }
3357
+ export function spawnSync(cmd, args, opts) {
3358
+ var r = _execArgs(cmd, args || []);
3359
+ return { stdout: r.stdout, stderr: r.stderr, status: r.exitCode };
3360
+ }
3361
+ export default { exec: exec, execSync: execSync, spawnSync: spawnSync };
3362
+ `,
3363
+ os: `
3364
+ const _os = globalThis[Symbol.for('jb:os')];
3365
+ export const platform = _os.platform;
3366
+ export const arch = _os.arch;
3367
+ export const homedir = _os.homedir;
3368
+ export const tmpdir = _os.tmpdir;
3369
+ export const type = _os.type;
3370
+ export const hostname = _os.hostname;
3371
+ export const EOL = _os.EOL;
3372
+ export const cpus = _os.cpus;
3373
+ export const totalmem = _os.totalmem;
3374
+ export const freemem = _os.freemem;
3375
+ export const endianness = _os.endianness;
3376
+ export default _os;
3377
+ `,
3378
+ url: `
3379
+ const _url = globalThis[Symbol.for('jb:url')];
3380
+ export const URL = _url.URL;
3381
+ export const URLSearchParams = _url.URLSearchParams;
3382
+ export const parse = _url.parse;
3383
+ export const format = _url.format;
3384
+ export default _url;
3385
+ `,
3386
+ assert: `
3387
+ const _assert = globalThis[Symbol.for('jb:assert')];
3388
+ export const ok = _assert.ok;
3389
+ export const equal = _assert.equal;
3390
+ export const notEqual = _assert.notEqual;
3391
+ export const strictEqual = _assert.strictEqual;
3392
+ export const notStrictEqual = _assert.notStrictEqual;
3393
+ export const deepEqual = _assert.deepEqual;
3394
+ export const deepStrictEqual = _assert.deepStrictEqual;
3395
+ export const notDeepEqual = _assert.notDeepEqual;
3396
+ export const throws = _assert.throws;
3397
+ export const doesNotThrow = _assert.doesNotThrow;
3398
+ export const fail = _assert.fail;
3399
+ export default _assert;
3400
+ `,
3401
+ util: `
3402
+ const _util = globalThis[Symbol.for('jb:util')];
3403
+ export const format = _util.format;
3404
+ export const inspect = _util.inspect;
3405
+ export const promisify = _util.promisify;
3406
+ export const types = _util.types;
3407
+ export const inherits = _util.inherits;
3408
+ export default _util;
3409
+ `,
3410
+ events: `
3411
+ const _events = globalThis[Symbol.for('jb:events')];
3412
+ export const EventEmitter = _events.EventEmitter;
3413
+ export default _events;
3414
+ `,
3415
+ buffer: `
3416
+ const _buffer = globalThis[Symbol.for('jb:buffer')];
3417
+ export const Buffer = _buffer.Buffer;
3418
+ export default _buffer;
3419
+ `,
3420
+ stream: `
3421
+ const _stream = globalThis[Symbol.for('jb:stream')];
3422
+ export const Stream = _stream.Stream;
3423
+ export const Readable = _stream.Readable;
3424
+ export const Writable = _stream.Writable;
3425
+ export const Duplex = _stream.Duplex;
3426
+ export const Transform = _stream.Transform;
3427
+ export const PassThrough = _stream.PassThrough;
3428
+ export const pipeline = _stream.pipeline;
3429
+ export default _stream;
3430
+ `,
3431
+ string_decoder: `
3432
+ const _sd = globalThis[Symbol.for('jb:string_decoder')];
3433
+ export const StringDecoder = _sd.StringDecoder;
3434
+ export default _sd;
3435
+ `,
3436
+ querystring: `
3437
+ const _qs = globalThis[Symbol.for('jb:querystring')];
3438
+ export const parse = _qs.parse;
3439
+ export const stringify = _qs.stringify;
3440
+ export const escape = _qs.escape;
3441
+ export const unescape = _qs.unescape;
3442
+ export const decode = _qs.decode;
3443
+ export const encode = _qs.encode;
3444
+ export default _qs;
3445
+ `
3446
+ }
3447
+ );
3448
+ for (const [name, hint] of Object.entries(UNSUPPORTED_MODULES)) {
3449
+ VIRTUAL_MODULES[name] = `throw new Error("Module '${name}' is not available in the js-exec sandbox. ${hint} Run 'js-exec --help' for available modules.");`;
3450
+ }
3451
+ function setupContext(context, backend, input) {
3452
+ const consoleObj = context.newObject();
3453
+ const logFn = context.newFunction("log", (...args) => {
3454
+ const parts = args.map((a) => {
3455
+ const val = context.dump(a);
3456
+ return typeof val === "string" ? val : JSON.stringify(val);
3457
+ });
3458
+ try {
3459
+ backend.writeStdout(`${parts.join(" ")}
3460
+ `);
3461
+ } catch (e) {
3462
+ return throwError(context, e.message || "write failed");
3463
+ }
3464
+ return context.undefined;
3465
+ });
3466
+ context.setProp(consoleObj, "log", logFn);
3467
+ logFn.dispose();
3468
+ const errorFn = context.newFunction("error", (...args) => {
3469
+ const parts = args.map((a) => {
3470
+ const val = context.dump(a);
3471
+ return typeof val === "string" ? val : JSON.stringify(val);
3472
+ });
3473
+ try {
3474
+ backend.writeStderr(`${parts.join(" ")}
3475
+ `);
3476
+ } catch (e) {
3477
+ return throwError(context, e.message || "write failed");
3478
+ }
3479
+ return context.undefined;
3480
+ });
3481
+ context.setProp(consoleObj, "error", errorFn);
3482
+ errorFn.dispose();
3483
+ const warnFn = context.newFunction("warn", (...args) => {
3484
+ const parts = args.map((a) => {
3485
+ const val = context.dump(a);
3486
+ return typeof val === "string" ? val : JSON.stringify(val);
3487
+ });
3488
+ try {
3489
+ backend.writeStderr(`${parts.join(" ")}
3490
+ `);
3491
+ } catch (e) {
3492
+ return throwError(context, e.message || "write failed");
3493
+ }
3494
+ return context.undefined;
3495
+ });
3496
+ context.setProp(consoleObj, "warn", warnFn);
3497
+ warnFn.dispose();
3498
+ context.setProp(context.global, "console", consoleObj);
3499
+ consoleObj.dispose();
3500
+ const fsObj = context.newObject();
3501
+ const readFileFn = context.newFunction(
3502
+ "readFile",
3503
+ (pathHandle) => {
3504
+ const path = context.getString(pathHandle);
3505
+ try {
3506
+ const data = backend.readFile(path);
3507
+ return context.newString(new TextDecoder().decode(data));
3508
+ } catch (e) {
3509
+ return throwError(context, e.message || "readFile failed");
3510
+ }
3511
+ }
3512
+ );
3513
+ context.setProp(fsObj, "readFile", readFileFn);
3514
+ readFileFn.dispose();
3515
+ const readFileBufferFn = context.newFunction(
3516
+ "readFileBuffer",
3517
+ (pathHandle) => {
3518
+ const path = context.getString(pathHandle);
3519
+ try {
3520
+ const data = backend.readFile(path);
3521
+ return context.newArrayBuffer(
3522
+ data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)
3523
+ );
3524
+ } catch (e) {
3525
+ return throwError(
3526
+ context,
3527
+ e.message || "readFileBuffer failed"
3528
+ );
3529
+ }
3530
+ }
3531
+ );
3532
+ context.setProp(fsObj, "readFileBuffer", readFileBufferFn);
3533
+ readFileBufferFn.dispose();
3534
+ const writeFileFn = context.newFunction(
3535
+ "writeFile",
3536
+ (pathHandle, dataHandle) => {
3537
+ const path = context.getString(pathHandle);
3538
+ const data = context.getString(dataHandle);
3539
+ try {
3540
+ backend.writeFile(path, new TextEncoder().encode(data));
3541
+ return context.undefined;
3542
+ } catch (e) {
3543
+ return throwError(context, e.message || "writeFile failed");
3544
+ }
3545
+ }
3546
+ );
3547
+ context.setProp(fsObj, "writeFile", writeFileFn);
3548
+ writeFileFn.dispose();
3549
+ const statFn = context.newFunction("stat", (pathHandle) => {
3550
+ const path = context.getString(pathHandle);
3551
+ try {
3552
+ const stat = backend.stat(path);
3553
+ return jsToHandle(context, {
3554
+ isFile: stat.isFile,
3555
+ isDirectory: stat.isDirectory,
3556
+ isSymbolicLink: stat.isSymbolicLink,
3557
+ mode: stat.mode,
3558
+ size: stat.size,
3559
+ mtime: stat.mtime.toISOString()
3560
+ });
3561
+ } catch (e) {
3562
+ return throwError(context, e.message || "stat failed");
3563
+ }
3564
+ });
3565
+ context.setProp(fsObj, "stat", statFn);
3566
+ statFn.dispose();
3567
+ const readdirFn = context.newFunction(
3568
+ "readdir",
3569
+ (pathHandle) => {
3570
+ const path = context.getString(pathHandle);
3571
+ try {
3572
+ const entries = backend.readdir(path);
3573
+ return jsToHandle(context, entries);
3574
+ } catch (e) {
3575
+ return throwError(context, e.message || "readdir failed");
3576
+ }
3577
+ }
3578
+ );
3579
+ context.setProp(fsObj, "readdir", readdirFn);
3580
+ readdirFn.dispose();
3581
+ const mkdirFn = context.newFunction(
3582
+ "mkdir",
3583
+ (pathHandle, optsHandle) => {
3584
+ const path = context.getString(pathHandle);
3585
+ let recursive = false;
3586
+ if (optsHandle) {
3587
+ const opts = context.dump(optsHandle);
3588
+ if (opts && typeof opts === "object" && "recursive" in opts) {
3589
+ recursive = Boolean(opts.recursive);
3590
+ }
3591
+ }
3592
+ try {
3593
+ backend.mkdir(path, recursive);
3594
+ return context.undefined;
3595
+ } catch (e) {
3596
+ return throwError(context, e.message || "mkdir failed");
3597
+ }
3598
+ }
3599
+ );
3600
+ context.setProp(fsObj, "mkdir", mkdirFn);
3601
+ mkdirFn.dispose();
3602
+ const rmFn = context.newFunction(
3603
+ "rm",
3604
+ (pathHandle, optsHandle) => {
3605
+ const path = context.getString(pathHandle);
3606
+ let recursive = false;
3607
+ let force = false;
3608
+ if (optsHandle) {
3609
+ const opts = context.dump(optsHandle);
3610
+ if (opts && typeof opts === "object") {
3611
+ if ("recursive" in opts) recursive = Boolean(opts.recursive);
3612
+ if ("force" in opts) force = Boolean(opts.force);
3613
+ }
3614
+ }
3615
+ try {
3616
+ backend.rm(path, recursive, force);
3617
+ return context.undefined;
3618
+ } catch (e) {
3619
+ return throwError(context, e.message || "rm failed");
3620
+ }
3621
+ }
3622
+ );
3623
+ context.setProp(fsObj, "rm", rmFn);
3624
+ rmFn.dispose();
3625
+ const existsFn = context.newFunction(
3626
+ "exists",
3627
+ (pathHandle) => {
3628
+ const path = context.getString(pathHandle);
3629
+ return backend.exists(path) ? context.true : context.false;
3630
+ }
3631
+ );
3632
+ context.setProp(fsObj, "exists", existsFn);
3633
+ existsFn.dispose();
3634
+ const appendFileFn = context.newFunction(
3635
+ "appendFile",
3636
+ (pathHandle, dataHandle) => {
3637
+ const path = context.getString(pathHandle);
3638
+ const data = context.getString(dataHandle);
3639
+ try {
3640
+ backend.appendFile(path, new TextEncoder().encode(data));
3641
+ return context.undefined;
3642
+ } catch (e) {
3643
+ return throwError(context, e.message || "appendFile failed");
3644
+ }
3645
+ }
3646
+ );
3647
+ context.setProp(fsObj, "appendFile", appendFileFn);
3648
+ appendFileFn.dispose();
3649
+ const lstatFn = context.newFunction("lstat", (pathHandle) => {
3650
+ const path = context.getString(pathHandle);
3651
+ try {
3652
+ const s = backend.lstat(path);
3653
+ return jsToHandle(context, {
3654
+ isFile: s.isFile,
3655
+ isDirectory: s.isDirectory,
3656
+ isSymbolicLink: s.isSymbolicLink,
3657
+ mode: s.mode,
3658
+ size: s.size,
3659
+ mtime: s.mtime.toISOString()
3660
+ });
3661
+ } catch (e) {
3662
+ return throwError(context, e.message || "lstat failed");
3663
+ }
3664
+ });
3665
+ context.setProp(fsObj, "lstat", lstatFn);
3666
+ lstatFn.dispose();
3667
+ const symlinkFn = context.newFunction(
3668
+ "symlink",
3669
+ (targetHandle, pathHandle) => {
3670
+ const target = context.getString(targetHandle);
3671
+ const linkPath = context.getString(pathHandle);
3672
+ try {
3673
+ backend.symlink(target, linkPath);
3674
+ return context.undefined;
3675
+ } catch (e) {
3676
+ return throwError(context, e.message || "symlink failed");
3677
+ }
3678
+ }
3679
+ );
3680
+ context.setProp(fsObj, "symlink", symlinkFn);
3681
+ symlinkFn.dispose();
3682
+ const readlinkFn = context.newFunction(
3683
+ "readlink",
3684
+ (pathHandle) => {
3685
+ const path = context.getString(pathHandle);
3686
+ try {
3687
+ const target = backend.readlink(path);
3688
+ return context.newString(target);
3689
+ } catch (e) {
3690
+ return throwError(context, e.message || "readlink failed");
3691
+ }
3692
+ }
3693
+ );
3694
+ context.setProp(fsObj, "readlink", readlinkFn);
3695
+ readlinkFn.dispose();
3696
+ const chmodFn = context.newFunction(
3697
+ "chmod",
3698
+ (pathHandle, modeHandle) => {
3699
+ const path = context.getString(pathHandle);
3700
+ const mode = context.dump(modeHandle);
3701
+ try {
3702
+ backend.chmod(path, typeof mode === "number" ? mode : 0);
3703
+ return context.undefined;
3704
+ } catch (e) {
3705
+ return throwError(context, e.message || "chmod failed");
3706
+ }
3707
+ }
3708
+ );
3709
+ context.setProp(fsObj, "chmod", chmodFn);
3710
+ chmodFn.dispose();
3711
+ const realpathFn = context.newFunction(
3712
+ "realpath",
3713
+ (pathHandle) => {
3714
+ const path = context.getString(pathHandle);
3715
+ try {
3716
+ const resolved = backend.realpath(path);
3717
+ return context.newString(resolved);
3718
+ } catch (e) {
3719
+ return throwError(context, e.message || "realpath failed");
3720
+ }
3721
+ }
3722
+ );
3723
+ context.setProp(fsObj, "realpath", realpathFn);
3724
+ realpathFn.dispose();
3725
+ const renameFn = context.newFunction(
3726
+ "rename",
3727
+ (oldHandle, newHandle) => {
3728
+ const oldPath = context.getString(oldHandle);
3729
+ const newPath = context.getString(newHandle);
3730
+ try {
3731
+ backend.rename(oldPath, newPath);
3732
+ return context.undefined;
3733
+ } catch (e) {
3734
+ return throwError(context, e.message || "rename failed");
3735
+ }
3736
+ }
3737
+ );
3738
+ context.setProp(fsObj, "rename", renameFn);
3739
+ renameFn.dispose();
3740
+ const copyFileFn = context.newFunction(
3741
+ "copyFile",
3742
+ (srcHandle, destHandle) => {
3743
+ const src = context.getString(srcHandle);
3744
+ const dest = context.getString(destHandle);
3745
+ try {
3746
+ backend.copyFile(src, dest);
3747
+ return context.undefined;
3748
+ } catch (e) {
3749
+ return throwError(context, e.message || "copyFile failed");
3750
+ }
3751
+ }
3752
+ );
3753
+ context.setProp(fsObj, "copyFile", copyFileFn);
3754
+ copyFileFn.dispose();
3755
+ context.setProp(context.global, "fs", fsObj);
3756
+ fsObj.dispose();
3757
+ const fetchFn = context.newFunction(
3758
+ "fetch",
3759
+ (urlHandle, optsHandle) => {
3760
+ const url = context.getString(urlHandle);
3761
+ let options;
3762
+ if (optsHandle) {
3763
+ options = context.dump(optsHandle);
3764
+ }
3765
+ try {
3766
+ const result = backend.httpRequest(url, {
3767
+ method: options?.method,
3768
+ headers: options?.headers,
3769
+ body: options?.body
3770
+ });
3771
+ return jsToHandle(context, result);
3772
+ } catch (e) {
3773
+ return throwError(context, e.message || "fetch failed");
3774
+ }
3775
+ }
3776
+ );
3777
+ context.setProp(context.global, "__fetch", fetchFn);
3778
+ fetchFn.dispose();
3779
+ const execFn = context.newFunction(
3780
+ "exec",
3781
+ (cmdHandle, optsHandle) => {
3782
+ const command = context.getString(cmdHandle);
3783
+ let stdin;
3784
+ if (optsHandle) {
3785
+ const opts = context.dump(optsHandle);
3786
+ if (opts?.stdin) {
3787
+ stdin = String(opts.stdin);
3788
+ }
3789
+ }
3790
+ try {
3791
+ const result = backend.execCommand(command, stdin);
3792
+ return jsToHandle(context, result);
3793
+ } catch (e) {
3794
+ return throwError(context, e.message || "exec failed");
3795
+ }
3796
+ }
3797
+ );
3798
+ context.setProp(context.global, "__exec", execFn);
3799
+ execFn.dispose();
3800
+ const execArgsFn = context.newFunction(
3801
+ "execArgs",
3802
+ (cmdHandle, argsHandle) => {
3803
+ const command = context.getString(cmdHandle);
3804
+ const args = context.dump(argsHandle);
3805
+ try {
3806
+ const result = backend.execCommandArgs(command, args);
3807
+ return jsToHandle(context, result);
3808
+ } catch (e) {
3809
+ return throwError(context, e.message || "exec failed");
3810
+ }
3811
+ }
3812
+ );
3813
+ context.setProp(context.global, "__execArgs", execArgsFn);
3814
+ execArgsFn.dispose();
3815
+ const envObj = jsToHandle(context, input.env);
3816
+ context.setProp(context.global, "env", envObj);
3817
+ envObj.dispose();
3818
+ const processObj = context.newObject();
3819
+ const argv = [input.scriptPath || "js-exec", ...input.args];
3820
+ const argvHandle = jsToHandle(context, argv);
3821
+ context.setProp(processObj, "argv", argvHandle);
3822
+ argvHandle.dispose();
3823
+ const cwdFn = context.newFunction("cwd", () => {
3824
+ return context.newString(input.cwd);
3825
+ });
3826
+ context.setProp(processObj, "cwd", cwdFn);
3827
+ cwdFn.dispose();
3828
+ const exitFn = context.newFunction("exit", (codeHandle) => {
3829
+ let code = 0;
3830
+ if (codeHandle) {
3831
+ const val = context.dump(codeHandle);
3832
+ code = typeof val === "number" ? val : 0;
3833
+ }
3834
+ backend.exit(code);
3835
+ return throwError(context, "__EXIT__");
3836
+ });
3837
+ context.setProp(processObj, "exit", exitFn);
3838
+ exitFn.dispose();
3839
+ context.setProp(context.global, "process", processObj);
3840
+ processObj.dispose();
3841
+ const compatResult = context.evalCode(
3842
+ `(function() {
3843
+ // Bridge native handles from string keys (set by QuickJS setProp) to symbol keys
3844
+ globalThis[Symbol.for('jb:fetch')] = globalThis.__fetch;
3845
+ globalThis[Symbol.for('jb:exec')] = globalThis.__exec;
3846
+ globalThis[Symbol.for('jb:execArgs')] = globalThis.__execArgs;
3847
+ delete globalThis.__fetch;
3848
+ delete globalThis.__exec;
3849
+ delete globalThis.__execArgs;
3850
+
3851
+ var _fs = globalThis.fs;
3852
+ // Save original native functions
3853
+ var orig = Object.create(null);
3854
+ var allNames = [
3855
+ 'readFile', 'readFileBuffer', 'writeFile', 'stat', 'lstat', 'readdir',
3856
+ 'mkdir', 'rm', 'exists', 'appendFile', 'symlink', 'readlink',
3857
+ 'chmod', 'realpath', 'rename', 'copyFile'
3858
+ ];
3859
+ for (var i = 0; i < allNames.length; i++) {
3860
+ orig[allNames[i]] = _fs[allNames[i]];
3861
+ }
3862
+
3863
+ // Wrap async-style methods to always throw (matching Node.js which requires a callback).
3864
+ // In Node.js, calling fs.readFile() without a callback throws TypeError.
3865
+ // We don't support callbacks, so the async form always errors.
3866
+ function wrapCb(fn, name) {
3867
+ return function() {
3868
+ throw new Error(
3869
+ "fs." + name + "() with callbacks is not supported. " +
3870
+ "Use fs." + name + "Sync() or fs.promises." + name + "() instead."
3871
+ );
3872
+ };
3873
+ }
3874
+ var cbNames = [
3875
+ 'readFile', 'writeFile', 'stat', 'lstat', 'readdir', 'mkdir',
3876
+ 'rm', 'appendFile', 'symlink', 'readlink', 'chmod', 'realpath',
3877
+ 'rename', 'copyFile'
3878
+ ];
3879
+ for (var i = 0; i < cbNames.length; i++) {
3880
+ if (orig[cbNames[i]]) _fs[cbNames[i]] = wrapCb(orig[cbNames[i]], cbNames[i]);
3881
+ }
3882
+ // exists: callback is especially common in legacy Node.js
3883
+ _fs.exists = wrapCb(orig.exists, 'exists');
3884
+
3885
+ // readFileSync: match Node.js behavior
3886
+ // - No encoding: return Buffer
3887
+ // - With encoding (e.g. 'utf8'): return string
3888
+ _fs.readFileSync = function(path, opts) {
3889
+ var encoding = typeof opts === 'string' ? opts : (opts && opts.encoding);
3890
+ if (encoding) return orig.readFile(path);
3891
+ return Buffer.from(orig.readFileBuffer(path));
3892
+ };
3893
+ _fs.writeFileSync = orig.writeFile;
3894
+ _fs.statSync = orig.stat;
3895
+ _fs.lstatSync = orig.lstat;
3896
+ _fs.readdirSync = orig.readdir;
3897
+ _fs.mkdirSync = orig.mkdir;
3898
+ _fs.rmSync = orig.rm;
3899
+ _fs.existsSync = orig.exists;
3900
+ _fs.appendFileSync = orig.appendFile;
3901
+ _fs.symlinkSync = orig.symlink;
3902
+ _fs.readlinkSync = orig.readlink;
3903
+ _fs.chmodSync = orig.chmod;
3904
+ _fs.realpathSync = orig.realpath;
3905
+ _fs.renameSync = orig.rename;
3906
+ _fs.copyFileSync = orig.copyFile;
3907
+ _fs.unlinkSync = orig.rm;
3908
+ _fs.rmdirSync = orig.rm;
3909
+ _fs.unlink = wrapCb(orig.rm, 'unlink');
3910
+ _fs.rmdir = wrapCb(orig.rm, 'rmdir');
3911
+
3912
+ // promises namespace
3913
+ _fs.promises = {};
3914
+ for (var i = 0; i < allNames.length; i++) {
3915
+ var m = allNames[i];
3916
+ (function(fn) {
3917
+ _fs.promises[m] = function() {
3918
+ try { return Promise.resolve(fn.apply(null, arguments)); }
3919
+ catch(e) { return Promise.reject(e); }
3920
+ };
3921
+ })(orig[m]);
3922
+ }
3923
+ // Override promises.readFile to match Node.js behavior (Buffer vs string)
3924
+ _fs.promises.readFile = function(path, opts) {
3925
+ var encoding = typeof opts === 'string' ? opts : (opts && opts.encoding);
3926
+ try {
3927
+ if (encoding) return Promise.resolve(orig.readFile(path));
3928
+ return Promise.resolve(Buffer.from(orig.readFileBuffer(path)));
3929
+ } catch(e) { return Promise.reject(e); }
3930
+ };
3931
+ _fs.promises.unlink = _fs.promises.rm;
3932
+ _fs.promises.rmdir = _fs.promises.rm;
3933
+ _fs.promises.access = function(p) {
3934
+ return orig.exists(p) ? Promise.resolve() : Promise.reject(new Error('ENOENT: no such file or directory: ' + p));
3935
+ };
3936
+
3937
+ // process enhancements
3938
+ var _p = globalThis.process;
3939
+ _p.env = globalThis.env;
3940
+ _p.platform = 'linux';
3941
+ _p.arch = 'x64';
3942
+ _p.versions = { node: '22.0.0', quickjs: '2024' };
3943
+ _p.version = 'v22.0.0';
3944
+
3945
+ // Initialize path module on globalThis so require('path') works
3946
+ ${PATH_MODULE_SOURCE}
3947
+
3948
+ // Initialize fetch polyfill (URL, Headers, Request, Response, fetch)
3949
+ ${FETCH_POLYFILL_SOURCE}
3950
+
3951
+ // Initialize additional module shims
3952
+ ${EVENTS_MODULE_SOURCE}
3953
+ ${OS_MODULE_SOURCE}
3954
+ ${URL_MODULE_SOURCE}
3955
+ ${ASSERT_MODULE_SOURCE}
3956
+ ${UTIL_MODULE_SOURCE}
3957
+ ${BUFFER_MODULE_SOURCE}
3958
+ ${STREAM_MODULE_SOURCE}
3959
+ ${STRING_DECODER_MODULE_SOURCE}
3960
+ ${QUERYSTRING_MODULE_SOURCE}
3961
+
3962
+ // Wrap console methods to auto-stringify Buffer arguments.
3963
+ // In Node.js, console.log(buffer) calls util.inspect \u2192 toString().
3964
+ (function() {
3965
+ var _cl = console.log;
3966
+ var _ce = console.error;
3967
+ var _cw = console.warn;
3968
+ function fix(a) { return a instanceof Buffer ? a.toString() : a; }
3969
+ function wrap(fn) {
3970
+ return function() {
3971
+ var a = [];
3972
+ for (var i = 0; i < arguments.length; i++) a.push(fix(arguments[i]));
3973
+ return fn.apply(console, a);
3974
+ };
3975
+ }
3976
+ console.log = wrap(_cl);
3977
+ console.error = wrap(_ce);
3978
+ console.warn = wrap(_cw);
3979
+ })();
3980
+
3981
+ // require() shim for CommonJS compatibility
3982
+ var _execFn = globalThis[Symbol.for('jb:exec')];
3983
+ var _execArgsFn = globalThis[Symbol.for('jb:execArgs')];
3984
+ var _childProcess = {
3985
+ exec: function(cmd, opts) { return _execFn(cmd, opts); },
3986
+ execSync: function(cmd, opts) {
3987
+ var r = _execFn(cmd, opts);
3988
+ if (r.exitCode !== 0) {
3989
+ var e = new Error('Command failed: ' + cmd);
3990
+ e.status = r.exitCode;
3991
+ e.stderr = r.stderr;
3992
+ e.stdout = r.stdout;
3993
+ throw e;
3994
+ }
3995
+ return r.stdout;
3996
+ },
3997
+ spawnSync: function(cmd, args, opts) {
3998
+ var r = _execArgsFn(cmd, args || []);
3999
+ return { stdout: r.stdout, stderr: r.stderr, status: r.exitCode };
4000
+ }
4001
+ };
4002
+
4003
+ var _modules = Object.create(null);
4004
+ _modules.fs = _fs;
4005
+ _modules.path = globalThis[Symbol.for('jb:path')];
4006
+ _modules.child_process = _childProcess;
4007
+ _modules.process = _p;
4008
+ _modules.console = globalThis.console;
4009
+ _modules.os = globalThis[Symbol.for('jb:os')];
4010
+ _modules.url = globalThis[Symbol.for('jb:url')];
4011
+ _modules.assert = globalThis[Symbol.for('jb:assert')];
4012
+ _modules.util = globalThis[Symbol.for('jb:util')];
4013
+ _modules.events = globalThis[Symbol.for('jb:events')];
4014
+ _modules.buffer = globalThis[Symbol.for('jb:buffer')];
4015
+ _modules.stream = globalThis[Symbol.for('jb:stream')];
4016
+ _modules.string_decoder = globalThis[Symbol.for('jb:string_decoder')];
4017
+ _modules.querystring = globalThis[Symbol.for('jb:querystring')];
4018
+
4019
+ var _unsupported = Object.create(null);
4020
+ var _unsupportedRaw = ${JSON.stringify(UNSUPPORTED_MODULES)};
4021
+ Object.keys(_unsupportedRaw).forEach(function(_key) {
4022
+ _unsupported[_key] = _unsupportedRaw[_key];
4023
+ });
4024
+
4025
+ globalThis.require = function(name) {
4026
+ if (name.startsWith('node:')) name = name.slice(5);
4027
+ if (Object.prototype.hasOwnProperty.call(_modules, name)) {
4028
+ return _modules[name];
4029
+ }
4030
+ if (Object.prototype.hasOwnProperty.call(_unsupported, name)) {
4031
+ var hint = _unsupported[name];
4032
+ throw new Error("Module '" + name + "' is not available in the js-exec sandbox. " + hint + " Run 'js-exec --help' for available modules.");
4033
+ }
4034
+ throw new Error("Cannot find module '" + name + "'. Run 'js-exec --help' for available modules.");
4035
+ };
4036
+ globalThis.require.resolve = function(name) { return name; };
4037
+ })();`,
4038
+ "<compat>"
4039
+ );
4040
+ if (compatResult.error) {
4041
+ compatResult.error.dispose();
4042
+ } else {
4043
+ compatResult.value.dispose();
4044
+ }
4045
+ }
4046
+ var originalProcessExit = process.exit.bind(process);
4047
+ process.on("uncaughtException", () => {
4048
+ originalProcessExit(1);
4049
+ });
4050
+ var defense = null;
4051
+ async function initializeWithDefense() {
4052
+ await getQuickJSModule();
4053
+ try {
4054
+ stripTypeScriptTypes("const x = 1;");
4055
+ } catch {
4056
+ }
4057
+ await new Promise((r) => setTimeout(r, 0));
4058
+ defense = new WorkerDefenseInDepth({
4059
+ excludeViolationTypes: [
4060
+ // SharedArrayBuffer/Atomics: Used by sync-backend for synchronous
4061
+ // filesystem communication between the worker and main thread.
4062
+ "shared_array_buffer",
4063
+ "atomics",
4064
+ // process.stdout/stderr: Emscripten (quickjs-emscripten) routes WASM
4065
+ // stdout/stderr through Node.js console which uses process.stdout/stderr.
4066
+ // User code runs inside QuickJS with no access to Node.js process.
4067
+ "process_stdout",
4068
+ "process_stderr"
4069
+ ]
4070
+ });
4071
+ }
4072
+ async function executeCode(input) {
4073
+ const qjs = await getQuickJSModule();
4074
+ const backend = new SyncBackend(input.sharedBuffer, input.timeoutMs);
4075
+ let runtime;
4076
+ let context;
4077
+ try {
4078
+ runtime = qjs.newRuntime();
4079
+ runtime.setMemoryLimit(MEMORY_LIMIT);
4080
+ let interruptCount = 0;
4081
+ runtime.setInterruptHandler(() => {
4082
+ interruptCount++;
4083
+ return interruptCount > INTERRUPT_CYCLES;
4084
+ });
4085
+ context = runtime.newContext();
4086
+ setupContext(context, backend, input);
4087
+ {
4088
+ const initResult = context.evalCode(
4089
+ `{
4090
+ // --- Block dynamic code compilation ---
4091
+ // @banned-pattern-ignore: intentional sandbox hardening \u2014 removes eval/Function inside QuickJS guest, not the host
4092
+ Object.defineProperty(globalThis, 'eval', {
4093
+ value: undefined,
4094
+ writable: false,
4095
+ configurable: false,
4096
+ });
4097
+ const BlockedFunction = function () {
4098
+ throw new TypeError('Function constructor is not allowed');
4099
+ };
4100
+ const OrigFunction = Function;
4101
+ BlockedFunction.prototype = OrigFunction.prototype;
4102
+
4103
+ // Capture function-type constructors before we patch them
4104
+ const AsyncFunction = (async function(){}).constructor;
4105
+ const GeneratorFunction = (function*(){}).constructor;
4106
+ const AsyncGeneratorFunction = (async function*(){}).constructor;
4107
+
4108
+ // Patch .constructor on all function-type prototypes
4109
+ for (const proto of [
4110
+ OrigFunction.prototype,
4111
+ AsyncFunction.prototype,
4112
+ GeneratorFunction.prototype,
4113
+ AsyncGeneratorFunction.prototype,
4114
+ ]) {
4115
+ Object.defineProperty(proto, 'constructor', {
4116
+ value: BlockedFunction,
4117
+ writable: false,
4118
+ configurable: false,
4119
+ });
4120
+ }
4121
+ // @banned-pattern-ignore: intentional sandbox hardening \u2014 replaces Function constructor inside QuickJS guest
4122
+ Object.defineProperty(globalThis, 'Function', {
4123
+ value: BlockedFunction,
4124
+ writable: false,
4125
+ configurable: false,
4126
+ });
4127
+
4128
+ // --- Freeze all intrinsic prototypes ---
4129
+ // Prevents prototype pollution (e.g. Array.prototype.x = ...).
4130
+ // Only language intrinsics \u2014 not sandbox-injected objects
4131
+ // (process, console, require) which need to stay mutable.
4132
+ // Error prototypes are excluded: freezing them makes the inherited
4133
+ // "message" property non-writable, which prevents new Error instances
4134
+ // from having their own "message" set (JS spec OrdinarySet step 4).
4135
+ const g = globalThis;
4136
+ const toFreeze = [
4137
+ Object, Object.prototype,
4138
+ OrigFunction, OrigFunction.prototype,
4139
+ AsyncFunction, AsyncFunction.prototype,
4140
+ GeneratorFunction, GeneratorFunction.prototype,
4141
+ AsyncGeneratorFunction, AsyncGeneratorFunction.prototype,
4142
+ Array, Array.prototype,
4143
+ String, String.prototype,
4144
+ Number, Number.prototype,
4145
+ Boolean, Boolean.prototype,
4146
+ g.Symbol, g.Symbol && g.Symbol.prototype,
4147
+ RegExp, RegExp.prototype,
4148
+ Date, Date.prototype,
4149
+ Map, Map.prototype,
4150
+ Set, Set.prototype,
4151
+ WeakMap, WeakMap.prototype,
4152
+ WeakSet, WeakSet.prototype,
4153
+ g.WeakRef, g.WeakRef && g.WeakRef.prototype,
4154
+ Promise, Promise.prototype,
4155
+ ArrayBuffer, ArrayBuffer.prototype,
4156
+ g.SharedArrayBuffer, g.SharedArrayBuffer && g.SharedArrayBuffer.prototype,
4157
+ g.DataView, g.DataView && g.DataView.prototype,
4158
+ JSON, Math, g.Reflect, g.Proxy, g.Atomics,
4159
+ g.BigInt, g.BigInt && g.BigInt.prototype,
4160
+ BlockedFunction,
4161
+ ];
4162
+ // TypedArrays (guard against missing globals in QuickJS)
4163
+ for (const name of [
4164
+ 'Int8Array','Uint8Array','Uint8ClampedArray',
4165
+ 'Int16Array','Uint16Array','Int32Array','Uint32Array',
4166
+ 'Float32Array','Float64Array',
4167
+ 'BigInt64Array','BigUint64Array',
4168
+ ]) {
4169
+ if (g[name]) {
4170
+ toFreeze.push(g[name], g[name].prototype);
4171
+ }
4172
+ }
4173
+ // %TypedArray% intrinsic (shared base)
4174
+ if (g.Uint8Array) {
4175
+ const taProto = Object.getPrototypeOf(g.Uint8Array.prototype);
4176
+ if (taProto && taProto !== Object.prototype) toFreeze.push(taProto);
4177
+ const taCtor = Object.getPrototypeOf(g.Uint8Array);
4178
+ if (taCtor && taCtor !== OrigFunction.prototype) toFreeze.push(taCtor);
4179
+ }
4180
+ // Iterator prototypes
4181
+ try {
4182
+ const arrIterProto = Object.getPrototypeOf(
4183
+ Object.getPrototypeOf([][Symbol.iterator]())
4184
+ );
4185
+ if (arrIterProto) {
4186
+ toFreeze.push(arrIterProto);
4187
+ const iterProto = Object.getPrototypeOf(arrIterProto);
4188
+ if (iterProto) toFreeze.push(iterProto);
4189
+ }
4190
+ } catch {}
4191
+ try {
4192
+ toFreeze.push(Object.getPrototypeOf(new Map()[Symbol.iterator]()));
4193
+ } catch {}
4194
+ try {
4195
+ toFreeze.push(Object.getPrototypeOf(new Set()[Symbol.iterator]()));
4196
+ } catch {}
4197
+ try {
4198
+ toFreeze.push(Object.getPrototypeOf(''[Symbol.iterator]()));
4199
+ } catch {}
4200
+ try {
4201
+ const genObj = (function*(){})();
4202
+ toFreeze.push(Object.getPrototypeOf(genObj));
4203
+ toFreeze.push(Object.getPrototypeOf(Object.getPrototypeOf(genObj)));
4204
+ } catch {}
4205
+ try {
4206
+ const asyncGenObj = (async function*(){})();
4207
+ toFreeze.push(Object.getPrototypeOf(asyncGenObj));
4208
+ toFreeze.push(Object.getPrototypeOf(Object.getPrototypeOf(asyncGenObj)));
4209
+ } catch {}
4210
+
4211
+ for (const obj of toFreeze) {
4212
+ if (obj != null) {
4213
+ try { Object.freeze(obj); } catch {}
4214
+ }
4215
+ }
4216
+ }`,
4217
+ "<sandbox-init>"
4218
+ );
4219
+ if (initResult.error) {
4220
+ const errVal = context.dump(initResult.error);
4221
+ initResult.error.dispose();
4222
+ const msg = typeof errVal === "object" && errVal !== null && "message" in errVal ? errVal.message : String(errVal);
4223
+ backend.writeStderr(`js-exec: sandbox hardening failed: ${msg}
4224
+ `);
4225
+ backend.exit(1);
4226
+ return { success: true };
4227
+ }
4228
+ initResult.value.dispose();
4229
+ }
4230
+ if (input.isModule) {
4231
+ runtime.setModuleLoader(
4232
+ (moduleName) => {
4233
+ if (Object.hasOwn(VIRTUAL_MODULES, moduleName)) {
4234
+ return VIRTUAL_MODULES[moduleName];
4235
+ }
4236
+ try {
4237
+ const data = backend.readFile(moduleName);
4238
+ let source = new TextDecoder().decode(data);
4239
+ if (moduleName.endsWith(".ts") || moduleName.endsWith(".mts")) {
4240
+ source = stripTypeScriptTypes(source);
4241
+ }
4242
+ return source;
4243
+ } catch (e) {
4244
+ return {
4245
+ error: new Error(
4246
+ `Cannot find module '${moduleName}': ${e.message}`
4247
+ )
4248
+ };
4249
+ }
4250
+ },
4251
+ (baseModuleName, requestedName) => {
4252
+ if (requestedName.startsWith("node:")) {
4253
+ requestedName = requestedName.slice(5);
4254
+ }
4255
+ if (!requestedName.startsWith("./") && !requestedName.startsWith("../") && !requestedName.startsWith("/")) {
4256
+ return requestedName;
4257
+ }
4258
+ const fromFile = baseModuleName === "<eval>" ? void 0 : baseModuleName;
4259
+ return resolveModulePath(requestedName, fromFile, input.cwd);
4260
+ }
4261
+ );
4262
+ }
4263
+ if (input.bootstrapCode) {
4264
+ const bootstrapResult = context.evalCode(
4265
+ input.bootstrapCode,
4266
+ "bootstrap.js"
4267
+ );
4268
+ if (bootstrapResult.error) {
4269
+ const errorVal = context.dump(bootstrapResult.error);
4270
+ bootstrapResult.error.dispose();
4271
+ const errorMsg = formatError(errorVal);
4272
+ backend.writeStderr(`js-exec: bootstrap error: ${errorMsg}
4273
+ `);
4274
+ backend.exit(1);
4275
+ return { success: true };
4276
+ }
4277
+ bootstrapResult.value.dispose();
4278
+ }
4279
+ const filename = input.scriptPath || "<eval>";
4280
+ let jsCode = input.jsCode;
4281
+ if (input.stripTypes) {
4282
+ jsCode = stripTypeScriptTypes(jsCode);
4283
+ }
4284
+ const result = input.isModule ? context.evalCode(jsCode, filename, { type: "module" }) : context.evalCode(jsCode, filename);
4285
+ if (result.error) {
4286
+ const errorVal = context.dump(result.error);
4287
+ result.error.dispose();
4288
+ const rawMsg = typeof errorVal === "object" && errorVal !== null && "message" in errorVal ? errorVal.message : String(errorVal);
4289
+ if (rawMsg === "__EXIT__") {
4290
+ return { success: true };
4291
+ }
4292
+ const errorMsg = formatError(errorVal);
4293
+ try {
4294
+ backend.writeStderr(`${errorMsg}
4295
+ `);
4296
+ } catch {
4297
+ }
4298
+ backend.exit(1);
4299
+ return { success: true };
4300
+ }
4301
+ {
4302
+ const pendingResult = runtime.executePendingJobs();
4303
+ if ("error" in pendingResult && pendingResult.error) {
4304
+ const errorVal = context.dump(pendingResult.error);
4305
+ pendingResult.error.dispose();
4306
+ const rawPendingMsg = typeof errorVal === "object" && errorVal !== null && "message" in errorVal ? errorVal.message : String(errorVal);
4307
+ if (rawPendingMsg !== "__EXIT__") {
4308
+ const errorMsg = formatError(errorVal);
4309
+ try {
4310
+ backend.writeStderr(`${errorMsg}
4311
+ `);
4312
+ } catch {
4313
+ }
4314
+ backend.exit(1);
4315
+ return { success: true };
4316
+ }
4317
+ return { success: true };
4318
+ }
4319
+ }
4320
+ result.value.dispose();
4321
+ backend.exit(0);
4322
+ return {
4323
+ success: true,
4324
+ defenseStats: defense?.getStats()
4325
+ };
4326
+ } catch (e) {
4327
+ const message = e instanceof Error ? e.message : String(e);
4328
+ try {
4329
+ backend.writeStderr(`js-exec: ${message}
4330
+ `);
4331
+ } catch {
4332
+ }
4333
+ try {
4334
+ backend.exit(1);
4335
+ } catch {
4336
+ return { success: false, error: message };
4337
+ }
4338
+ return { success: true };
4339
+ } finally {
4340
+ context?.dispose();
4341
+ runtime?.dispose();
4342
+ }
4343
+ }
4344
+ var initPromise = initializeWithDefense().catch((e) => {
4345
+ parentPort?.postMessage({
4346
+ success: false,
4347
+ // @banned-pattern-ignore: worker-internal init error; message stays within worker protocol, sanitized by js-exec.ts before user output
4348
+ error: e.message,
4349
+ defenseStats: defense?.getStats()
4350
+ });
4351
+ });
4352
+ parentPort?.on("message", async (input) => {
4353
+ try {
4354
+ await initPromise;
4355
+ const result = await executeCode(input);
4356
+ result.defenseStats = defense?.getStats();
4357
+ result.protocolToken = input.protocolToken;
4358
+ parentPort?.postMessage(result);
4359
+ } catch (e) {
4360
+ parentPort?.postMessage({
4361
+ protocolToken: input.protocolToken,
4362
+ success: false,
4363
+ // @banned-pattern-ignore: worker-internal error; message stays within worker protocol, sanitized by js-exec.ts before user output
4364
+ error: e.message,
4365
+ defenseStats: defense?.getStats()
4366
+ });
4367
+ }
4368
+ });