@nodetool-ai/sandbox-runtime 0.0.0-stage → 0.8.9-beta.2

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 (218) hide show
  1. package/README.md +24 -2
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/host-access-gate.d.ts +24 -0
  4. package/dist/host-access-gate.d.ts.map +1 -0
  5. package/dist/host-access-gate.js +31 -0
  6. package/dist/host-access-gate.js.map +1 -0
  7. package/dist/index.d.ts +32 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +318 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/js-sandbox-worker/engine.d.ts +4 -0
  12. package/dist/js-sandbox-worker/engine.d.ts.map +1 -0
  13. package/dist/js-sandbox-worker/engine.js +82 -0
  14. package/dist/js-sandbox-worker/engine.js.map +1 -0
  15. package/dist/js-sandbox-worker/host.d.ts +136 -0
  16. package/dist/js-sandbox-worker/host.d.ts.map +1 -0
  17. package/dist/js-sandbox-worker/host.js +482 -0
  18. package/dist/js-sandbox-worker/host.js.map +1 -0
  19. package/dist/js-sandbox-worker/interpreter.d.ts +276 -0
  20. package/dist/js-sandbox-worker/interpreter.d.ts.map +1 -0
  21. package/dist/js-sandbox-worker/interpreter.js +1318 -0
  22. package/dist/js-sandbox-worker/interpreter.js.map +1 -0
  23. package/dist/js-sandbox-worker/protocol.d.ts +168 -0
  24. package/dist/js-sandbox-worker/protocol.d.ts.map +1 -0
  25. package/dist/js-sandbox-worker/protocol.js +217 -0
  26. package/dist/js-sandbox-worker/protocol.js.map +1 -0
  27. package/dist/js-sandbox-worker/worker-entry.d.ts +26 -0
  28. package/dist/js-sandbox-worker/worker-entry.d.ts.map +1 -0
  29. package/dist/js-sandbox-worker/worker-entry.js +308 -0
  30. package/dist/js-sandbox-worker/worker-entry.js.map +1 -0
  31. package/dist/limits.d.ts +77 -0
  32. package/dist/limits.d.ts.map +1 -0
  33. package/dist/limits.js +56 -0
  34. package/dist/limits.js.map +1 -0
  35. package/dist/sandbox-bootstrap-modules.d.ts +54 -0
  36. package/dist/sandbox-bootstrap-modules.d.ts.map +1 -0
  37. package/dist/sandbox-bootstrap-modules.js +104 -0
  38. package/dist/sandbox-bootstrap-modules.js.map +1 -0
  39. package/dist/sandbox-bytes.d.ts +43 -0
  40. package/dist/sandbox-bytes.d.ts.map +1 -0
  41. package/dist/sandbox-bytes.js +61 -0
  42. package/dist/sandbox-bytes.js.map +1 -0
  43. package/dist/sandbox-canvas-api.d.ts +30 -0
  44. package/dist/sandbox-canvas-api.d.ts.map +1 -0
  45. package/dist/sandbox-canvas-api.js +81 -0
  46. package/dist/sandbox-canvas-api.js.map +1 -0
  47. package/dist/sandbox-constants.d.ts +5 -0
  48. package/dist/sandbox-constants.d.ts.map +1 -0
  49. package/dist/sandbox-constants.js +13 -0
  50. package/dist/sandbox-constants.js.map +1 -0
  51. package/dist/sandbox-json-transport.d.ts +107 -0
  52. package/dist/sandbox-json-transport.d.ts.map +1 -0
  53. package/dist/sandbox-json-transport.js +324 -0
  54. package/dist/sandbox-json-transport.js.map +1 -0
  55. package/dist/timeline-capture.d.ts +21 -0
  56. package/dist/timeline-capture.d.ts.map +1 -0
  57. package/dist/timeline-capture.js +564 -0
  58. package/dist/timeline-capture.js.map +1 -0
  59. package/dist/utils/type-guards.d.ts +26 -0
  60. package/dist/utils/type-guards.d.ts.map +1 -0
  61. package/dist/utils/type-guards.js +44 -0
  62. package/dist/utils/type-guards.js.map +1 -0
  63. package/package.json +138 -4
  64. package/vendor/README.md +17 -0
  65. package/vendor/quickjs/LICENSE +21 -0
  66. package/vendor/quickjs/PROVENANCE.json +8 -0
  67. package/vendor/quickjs/adapter/fetch.d.ts +56 -0
  68. package/vendor/quickjs/adapter/fetch.js +140 -0
  69. package/vendor/quickjs/createTimeInterval.d.ts +9 -0
  70. package/vendor/quickjs/createTimeInterval.js +22 -0
  71. package/vendor/quickjs/createVirtualFileSystem.d.ts +13 -0
  72. package/vendor/quickjs/createVirtualFileSystem.js +191 -0
  73. package/vendor/quickjs/index.d.ts +77 -0
  74. package/vendor/quickjs/index.js +77 -0
  75. package/vendor/quickjs/loadAsyncQuickJs.d.ts +12 -0
  76. package/vendor/quickjs/loadAsyncQuickJs.js +66 -0
  77. package/vendor/quickjs/loadQuickJs.d.ts +12 -0
  78. package/vendor/quickjs/loadQuickJs.js +73 -0
  79. package/vendor/quickjs/modules/assert.d.ts +2 -0
  80. package/vendor/quickjs/modules/assert.js +47 -0
  81. package/vendor/quickjs/modules/buffer.d.ts +2 -0
  82. package/vendor/quickjs/modules/buffer.js +106 -0
  83. package/vendor/quickjs/modules/build/test-lib.js +2 -0
  84. package/vendor/quickjs/modules/events.d.ts +2 -0
  85. package/vendor/quickjs/modules/events.js +4 -0
  86. package/vendor/quickjs/modules/fs.d.ts +2 -0
  87. package/vendor/quickjs/modules/fs.js +76 -0
  88. package/vendor/quickjs/modules/fs_promises.d.ts +2 -0
  89. package/vendor/quickjs/modules/fs_promises.js +328 -0
  90. package/vendor/quickjs/modules/module.d.ts +2 -0
  91. package/vendor/quickjs/modules/module.js +33 -0
  92. package/vendor/quickjs/modules/nodeCompatibility/headers.d.ts +2 -0
  93. package/vendor/quickjs/modules/nodeCompatibility/headers.js +58 -0
  94. package/vendor/quickjs/modules/nodeCompatibility/request.d.ts +2 -0
  95. package/vendor/quickjs/modules/nodeCompatibility/request.js +5 -0
  96. package/vendor/quickjs/modules/nodeCompatibility/response.d.ts +2 -0
  97. package/vendor/quickjs/modules/nodeCompatibility/response.js +5 -0
  98. package/vendor/quickjs/modules/path.d.ts +2 -0
  99. package/vendor/quickjs/modules/path.js +504 -0
  100. package/vendor/quickjs/modules/process.d.ts +2 -0
  101. package/vendor/quickjs/modules/process.js +309 -0
  102. package/vendor/quickjs/modules/punycode.d.ts +2 -0
  103. package/vendor/quickjs/modules/punycode.js +443 -0
  104. package/vendor/quickjs/modules/querystring.d.ts +2 -0
  105. package/vendor/quickjs/modules/querystring.js +15 -0
  106. package/vendor/quickjs/modules/string_decoder.d.ts +2 -0
  107. package/vendor/quickjs/modules/string_decoder.js +223 -0
  108. package/vendor/quickjs/modules/timers.d.ts +2 -0
  109. package/vendor/quickjs/modules/timers.js +10 -0
  110. package/vendor/quickjs/modules/timers_promises.d.ts +2 -0
  111. package/vendor/quickjs/modules/timers_promises.js +40 -0
  112. package/vendor/quickjs/modules/url.d.ts +2 -0
  113. package/vendor/quickjs/modules/url.js +104 -0
  114. package/vendor/quickjs/modules/util.d.ts +2 -0
  115. package/vendor/quickjs/modules/util.js +233 -0
  116. package/vendor/quickjs/package.json +3 -0
  117. package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.d.ts +4 -0
  118. package/vendor/quickjs/sandbox/asyncVersion/createAsyncEvalCodeFunction.js +76 -0
  119. package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.d.ts +3 -0
  120. package/vendor/quickjs/sandbox/asyncVersion/createAsyncValidateCodeFunction.js +22 -0
  121. package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.d.ts +12 -0
  122. package/vendor/quickjs/sandbox/asyncVersion/executeAsyncSandboxFunction.js +9 -0
  123. package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.d.ts +4 -0
  124. package/vendor/quickjs/sandbox/asyncVersion/getAsyncModuleLoader.js +30 -0
  125. package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.d.ts +2 -0
  126. package/vendor/quickjs/sandbox/asyncVersion/modulePathNormalizerAsync.js +12 -0
  127. package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.d.ts +3 -0
  128. package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncNodeCompatibility.js +11 -0
  129. package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.d.ts +4 -0
  130. package/vendor/quickjs/sandbox/asyncVersion/prepareAsyncSandbox.js +10 -0
  131. package/vendor/quickjs/sandbox/expose/expose.d.ts +3 -0
  132. package/vendor/quickjs/sandbox/expose/expose.js +155 -0
  133. package/vendor/quickjs/sandbox/expose/isES2015Class.d.ts +1 -0
  134. package/vendor/quickjs/sandbox/expose/isES2015Class.js +4 -0
  135. package/vendor/quickjs/sandbox/expose/isObject.d.ts +1 -0
  136. package/vendor/quickjs/sandbox/expose/isObject.js +4 -0
  137. package/vendor/quickjs/sandbox/expose/pendingHostPromises.d.ts +6 -0
  138. package/vendor/quickjs/sandbox/expose/pendingHostPromises.js +40 -0
  139. package/vendor/quickjs/sandbox/getMaxIntervalAmount.d.ts +8 -0
  140. package/vendor/quickjs/sandbox/getMaxIntervalAmount.js +12 -0
  141. package/vendor/quickjs/sandbox/getMaxTimeoutAmount.d.ts +8 -0
  142. package/vendor/quickjs/sandbox/getMaxTimeoutAmount.js +12 -0
  143. package/vendor/quickjs/sandbox/handleEvalError.d.ts +2 -0
  144. package/vendor/quickjs/sandbox/handleEvalError.js +21 -0
  145. package/vendor/quickjs/sandbox/handleToNative/handleToNative.d.ts +9 -0
  146. package/vendor/quickjs/sandbox/handleToNative/handleToNative.js +153 -0
  147. package/vendor/quickjs/sandbox/handleToNative/serializer/index.d.ts +10 -0
  148. package/vendor/quickjs/sandbox/handleToNative/serializer/index.js +36 -0
  149. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.d.ts +2 -0
  150. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeArrayBuffer.js +4 -0
  151. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.d.ts +2 -0
  152. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeBuffer.js +16 -0
  153. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.d.ts +2 -0
  154. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeDate.js +16 -0
  155. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.d.ts +2 -0
  156. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeError.js +18 -0
  157. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.d.ts +2 -0
  158. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeHeaders.js +17 -0
  159. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.d.ts +2 -0
  160. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeMap.js +18 -0
  161. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.d.ts +2 -0
  162. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeSet.js +16 -0
  163. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.d.ts +2 -0
  164. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeURLSearchParams.js +17 -0
  165. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.d.ts +2 -0
  166. package/vendor/quickjs/sandbox/handleToNative/serializer/serializeUrl.js +17 -0
  167. package/vendor/quickjs/sandbox/helper.d.ts +2 -0
  168. package/vendor/quickjs/sandbox/helper.js +14 -0
  169. package/vendor/quickjs/sandbox/provide/provideConsole.d.ts +6 -0
  170. package/vendor/quickjs/sandbox/provide/provideConsole.js +53 -0
  171. package/vendor/quickjs/sandbox/provide/provideEnv.d.ts +3 -0
  172. package/vendor/quickjs/sandbox/provide/provideEnv.js +10 -0
  173. package/vendor/quickjs/sandbox/provide/provideFs.d.ts +4 -0
  174. package/vendor/quickjs/sandbox/provide/provideFs.js +159 -0
  175. package/vendor/quickjs/sandbox/provide/provideHttp.d.ts +9 -0
  176. package/vendor/quickjs/sandbox/provide/provideHttp.js +42 -0
  177. package/vendor/quickjs/sandbox/provide/provideTimingFunctions.d.ts +7 -0
  178. package/vendor/quickjs/sandbox/provide/provideTimingFunctions.js +119 -0
  179. package/vendor/quickjs/sandbox/setupFileSystem.d.ts +3 -0
  180. package/vendor/quickjs/sandbox/setupFileSystem.js +13 -0
  181. package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.d.ts +4 -0
  182. package/vendor/quickjs/sandbox/syncVersion/createEvalCodeFunction.js +76 -0
  183. package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.d.ts +3 -0
  184. package/vendor/quickjs/sandbox/syncVersion/createValidateCodeFunction.js +22 -0
  185. package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.d.ts +12 -0
  186. package/vendor/quickjs/sandbox/syncVersion/executeSandboxFunction.js +9 -0
  187. package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.d.ts +4 -0
  188. package/vendor/quickjs/sandbox/syncVersion/getModuleLoader.js +30 -0
  189. package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.d.ts +2 -0
  190. package/vendor/quickjs/sandbox/syncVersion/modulePathNormalizer.js +12 -0
  191. package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.d.ts +3 -0
  192. package/vendor/quickjs/sandbox/syncVersion/prepareNodeCompatibility.js +11 -0
  193. package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.d.ts +4 -0
  194. package/vendor/quickjs/sandbox/syncVersion/prepareSandbox.js +10 -0
  195. package/vendor/quickjs/types/CodeFunctionInput.d.ts +12 -0
  196. package/vendor/quickjs/types/CodeFunctionInput.js +1 -0
  197. package/vendor/quickjs/types/ErrorResponse.d.ts +9 -0
  198. package/vendor/quickjs/types/ErrorResponse.js +1 -0
  199. package/vendor/quickjs/types/LoadQuickJsOptions.d.ts +3 -0
  200. package/vendor/quickjs/types/LoadQuickJsOptions.js +1 -0
  201. package/vendor/quickjs/types/OkResponse.d.ts +4 -0
  202. package/vendor/quickjs/types/OkResponse.js +1 -0
  203. package/vendor/quickjs/types/OkResponseCheck.d.ts +3 -0
  204. package/vendor/quickjs/types/OkResponseCheck.js +1 -0
  205. package/vendor/quickjs/types/Prettify.d.ts +3 -0
  206. package/vendor/quickjs/types/Prettify.js +1 -0
  207. package/vendor/quickjs/types/RuntimeOptions.d.ts +87 -0
  208. package/vendor/quickjs/types/RuntimeOptions.js +1 -0
  209. package/vendor/quickjs/types/SandboxEvalCode.d.ts +5 -0
  210. package/vendor/quickjs/types/SandboxEvalCode.js +1 -0
  211. package/vendor/quickjs/types/SandboxFunction.d.ts +16 -0
  212. package/vendor/quickjs/types/SandboxFunction.js +1 -0
  213. package/vendor/quickjs/types/SandboxOptions.d.ts +152 -0
  214. package/vendor/quickjs/types/SandboxOptions.js +1 -0
  215. package/vendor/quickjs/types/SandboxValidateCode.d.ts +9 -0
  216. package/vendor/quickjs/types/SandboxValidateCode.js +1 -0
  217. package/vendor/quickjs/types/Serializer.d.ts +2 -0
  218. package/vendor/quickjs/types/Serializer.js +1 -0
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Worker main for the off-thread QuickJS sandbox.
3
+ *
4
+ * One engine per worker, one run at a time. Everything the guest reaches that
5
+ * lives on the main thread — every bridge, every dispatcher, every
6
+ * function-valued caller global — is rebuilt here as a proxy that posts an RPC
7
+ * and awaits the reply, which is indistinguishable from an ordinary async host
8
+ * function to the library's `expose()`.
9
+ *
10
+ * Three things are deliberately *not* proxied, because the guest reads them
11
+ * synchronously and a round trip has no synchronous answer: `crypto.randomUUID`
12
+ * and `crypto.getRandomValues`, which are reimplemented over the worker's own
13
+ * WebCrypto, and `stream.open`, which is served from a mirror seeded at run
14
+ * start and push-updated when a handle closes.
15
+ *
16
+ * This module is never statically imported by `js-sandbox.ts` — it is loaded
17
+ * only as a worker entry.
18
+ */
19
+ import { createLogger, importNodeBuiltin } from "@nodetool-ai/config";
20
+ import { loadSandboxEngine } from "./engine.js";
21
+ import { toGuestBytes } from "../sandbox-bytes.js";
22
+ import { MAX_RANDOM_BYTES } from "../sandbox-constants.js";
23
+ import { registerTypedArraySerializers, runInterpreter, SANDBOX_STREAM_OPEN_BINDING } from "./interpreter.js";
24
+ import { interpreterResultMessage, isHostToWorkerMessage, SANDBOX_DISPATCHER_BINDINGS } from "./protocol.js";
25
+ import * as quickJsVariantModule from "@jitl/quickjs-ng-wasmfile-release-sync";
26
+ import { isFiniteNumber, isObjectLike } from "../utils/type-guards.js";
27
+ /**
28
+ * The variant package is CJS with a `default` export, so `ns.default` is the
29
+ * variant at runtime.
30
+ */
31
+ // SAFETY: TypeScript's CJS interop synthesizes `default` as the whole module
32
+ // object, contradicting the package's own `.d.ts`, which declares it as the
33
+ // `QuickJSSyncVariant` this reads.
34
+ const quickJsVariant = quickJsVariantModule.default;
35
+ const log = createLogger("nodetool.agents.sandbox-worker");
36
+ const SLOW_SANDBOX_RUN_MS = 1_000;
37
+ // ---------------------------------------------------------------------------
38
+ // Engine
39
+ // ---------------------------------------------------------------------------
40
+ let enginePromise = null;
41
+ /**
42
+ * One engine per worker.
43
+ *
44
+ * `registerTypedArraySerializers` mutates the library's module-global
45
+ * serializer table, and a worker holds its own module instance, so it registers
46
+ * its own before the first run.
47
+ */
48
+ function getEngine() {
49
+ registerTypedArraySerializers();
50
+ if (!enginePromise)
51
+ enginePromise = loadSandboxEngine(quickJsVariant);
52
+ return enginePromise;
53
+ }
54
+ class RunSession {
55
+ port;
56
+ run;
57
+ pending = new Map();
58
+ nextRpcId = 0;
59
+ suspended = 0;
60
+ streamOpen;
61
+ constructor(port, run) {
62
+ this.port = port;
63
+ this.run = run;
64
+ this.streamOpen = new Map(Object.entries(run.streamOpenSeed ?? {}));
65
+ }
66
+ suspendedMs = () => this.suspended;
67
+ setSuspendedMs(value) {
68
+ this.suspended = value;
69
+ }
70
+ closeStream(handle) {
71
+ this.streamOpen.set(handle, false);
72
+ }
73
+ /**
74
+ * Answer `stream.open(handle)` from the mirror.
75
+ *
76
+ * `null` means the run carries no input stream at all — the prelude turns
77
+ * that into the no-input-stream throw, matching the in-process binding. A
78
+ * stale `true` is harmless: streams are close-only, so the worst case is
79
+ * one extra take that comes back done.
80
+ */
81
+ isStreamOpen = (handle) => this.run.streamOpenSeed === null
82
+ ? null
83
+ : this.streamOpen.get(String(handle)) === true;
84
+ settleRpc(id, ok, value, error) {
85
+ const pending = this.pending.get(id);
86
+ if (pending === undefined)
87
+ return;
88
+ this.pending.delete(id);
89
+ if (ok)
90
+ pending.resolve(value);
91
+ else
92
+ pending.reject(error ?? new Error("the sandbox bridge call failed"));
93
+ }
94
+ call(path, args) {
95
+ const id = this.nextRpcId++;
96
+ return new Promise((resolve, reject) => {
97
+ this.pending.set(id, { resolve, reject });
98
+ this.port.postMessage({ type: "rpc", id, path, args });
99
+ });
100
+ }
101
+ log(line) {
102
+ this.port.postMessage({ type: "log", line });
103
+ }
104
+ progress(percent, message) {
105
+ this.port.postMessage(message === undefined
106
+ ? { type: "progress", percent }
107
+ : { type: "progress", percent, message });
108
+ }
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Bridge reconstruction
112
+ // ---------------------------------------------------------------------------
113
+ /** Random bytes, tagged the way the host bridge tags them. */
114
+ function getRandomValues(requested) {
115
+ const size = isFiniteNumber(requested)
116
+ ? Math.min(Math.max(Math.floor(requested), 0), MAX_RANDOM_BYTES)
117
+ : 0;
118
+ const bytes = new Uint8Array(size);
119
+ if (size > 0)
120
+ globalThis.crypto.getRandomValues(bytes);
121
+ return toGuestBytes(bytes);
122
+ }
123
+ /** One RPC proxy, indistinguishable from an async host function to `expose()`. */
124
+ function proxyFor(session, path) {
125
+ return (...args) => session.call(path, args);
126
+ }
127
+ /**
128
+ * Rebuild the record `buildSandbox` would have produced, from names alone.
129
+ *
130
+ * Every entry is an RPC proxy, a value that travelled by clone, or one of the
131
+ * three synchronous locals this worker owns. Those three are handed over
132
+ * unwrapped and the interpreter passes them through unwrapped: a round trip has
133
+ * no synchronous answer, and `stream.open` in particular is a function that
134
+ * must never be wrapped.
135
+ */
136
+ function buildSandboxRecord(shape, session) {
137
+ const sandbox = {};
138
+ for (const name of shape.flat)
139
+ sandbox[name] = proxyFor(session, [name]);
140
+ for (const [name, value] of Object.entries(shape.values))
141
+ sandbox[name] = value;
142
+ for (const [name, members] of Object.entries(shape.objects)) {
143
+ const table = {};
144
+ for (const member of members)
145
+ table[member] = proxyFor(session, [name, member]);
146
+ sandbox[name] = table;
147
+ }
148
+ // `crypto.digest`/`hmac` stay proxied; the other two are worker-local.
149
+ const crypto = (sandbox.crypto ?? {});
150
+ crypto.randomUUID = () => globalThis.crypto.randomUUID();
151
+ crypto.getRandomValues = getRandomValues;
152
+ sandbox.crypto = crypto;
153
+ sandbox[SANDBOX_STREAM_OPEN_BINDING] = session.isStreamOpen;
154
+ return sandbox;
155
+ }
156
+ /**
157
+ * Caller globals, kept apart from the sandbox record.
158
+ *
159
+ * The interpreter applies them last so a global can shadow a non-reserved
160
+ * name, and it is the only place where "function → wrap, value → pass through"
161
+ * is the right rule. Merging them into the sandbox record would lose that.
162
+ */
163
+ function buildGlobalsRecord(shape, session) {
164
+ const globals = {};
165
+ for (const [name, global] of Object.entries(shape.globals)) {
166
+ globals[name] =
167
+ global.kind === "fn" ? proxyFor(session, [name]) : global.value;
168
+ }
169
+ return globals;
170
+ }
171
+ /** Object-typed globals, whose contents are read back out of the guest. */
172
+ function syncTargetNames(shape) {
173
+ return Object.entries(shape.globals)
174
+ .filter(([, global]) => global.kind === "value" &&
175
+ isObjectLike(global.value))
176
+ .map(([name]) => name);
177
+ }
178
+ /**
179
+ * A dispatcher proxy, present only when the run declared that kind.
180
+ *
181
+ * Presence is what decides the guest binding and the init prelude's
182
+ * conditional text, so the three travel as named optionals rather than as keys
183
+ * in an untyped record.
184
+ */
185
+ function dispatcherCall(shape, session, kind) {
186
+ if (!shape.dispatchers.includes(kind))
187
+ return undefined;
188
+ const binding = SANDBOX_DISPATCHER_BINDINGS[kind];
189
+ const proxy = proxyFor(session, [binding]);
190
+ return (moduleKey, exportName, args) => proxy(moduleKey, exportName, args);
191
+ }
192
+ // ---------------------------------------------------------------------------
193
+ // Worker main
194
+ // ---------------------------------------------------------------------------
195
+ /**
196
+ * An optional param, omitted rather than passed as `undefined`.
197
+ *
198
+ * The interpreter reads presence, not value: a `wasmCall` key that is there and
199
+ * undefined would still be a declared dispatcher.
200
+ */
201
+ function spreadIfSet(key, value) {
202
+ return value === undefined ? {} : { [key]: value };
203
+ }
204
+ async function executeRun(port, run, session) {
205
+ const startedAt = performance.now();
206
+ const engineStartedAt = performance.now();
207
+ const { runSandboxed } = await getEngine();
208
+ const engineMs = performance.now() - engineStartedAt;
209
+ const shape = run.bridgeShape;
210
+ let interpreterTiming;
211
+ let outcome;
212
+ let failed = false;
213
+ try {
214
+ outcome = await runInterpreter({
215
+ runSandboxed,
216
+ code: run.code,
217
+ sandbox: buildSandboxRecord(shape, session),
218
+ globals: buildGlobalsRecord(shape, session),
219
+ syncTargetNames: syncTargetNames(shape),
220
+ ...spreadIfSet("wasmCall", dispatcherCall(shape, session, "wasm")),
221
+ ...spreadIfSet("hostCall", dispatcherCall(shape, session, "host")),
222
+ ...spreadIfSet("capabilityCall", dispatcherCall(shape, session, "capability")),
223
+ ...spreadIfSet("modules", run.modules),
224
+ ...spreadIfSet("capabilityFacades", run.capabilityFacades),
225
+ timeoutMs: run.timeoutMs,
226
+ limits: run.limits,
227
+ suspendAllowanceMs: run.suspendAllowanceMs,
228
+ hasClock: run.hasClock,
229
+ // No isAborted: cancellation from the host is `worker.terminate()`, so the
230
+ // interrupt handler in here enforces only the deadline.
231
+ suspendedMs: session.suspendedMs,
232
+ onTiming: (timing) => {
233
+ interpreterTiming = timing;
234
+ }
235
+ });
236
+ }
237
+ catch (error) {
238
+ failed = true;
239
+ throw error;
240
+ }
241
+ finally {
242
+ const totalMs = performance.now() - startedAt;
243
+ if (totalMs >= SLOW_SANDBOX_RUN_MS) {
244
+ log.warn("Slow sandbox worker run", {
245
+ runId: run.runId,
246
+ engineMs,
247
+ interpreter: interpreterTiming,
248
+ failed,
249
+ totalMs
250
+ });
251
+ }
252
+ }
253
+ port.postMessage(interpreterResultMessage(run.runId, outcome));
254
+ }
255
+ export async function startWorker(port) {
256
+ let session;
257
+ port.on("message", (raw) => {
258
+ if (!isHostToWorkerMessage(raw))
259
+ return;
260
+ switch (raw.type) {
261
+ case "run": {
262
+ const active = new RunSession(port, raw);
263
+ session = active;
264
+ void executeRun(port, raw, active).catch((error) => {
265
+ const failed = {
266
+ type: "result",
267
+ runId: raw.runId,
268
+ evalOk: false,
269
+ failure: "worker",
270
+ errorName: error instanceof Error ? error.name : "Error",
271
+ errorMessage: error instanceof Error ? error.message : String(error)
272
+ };
273
+ if (error instanceof Error && error.stack !== undefined) {
274
+ failed.errorStack = error.stack;
275
+ }
276
+ port.postMessage(failed);
277
+ });
278
+ return;
279
+ }
280
+ case "suspend-update":
281
+ session?.setSuspendedMs(raw.suspendedMs);
282
+ return;
283
+ case "stream-closed":
284
+ session?.closeStream(raw.handle);
285
+ return;
286
+ case "rpc-reply":
287
+ if (raw.ok)
288
+ session?.settleRpc(raw.id, true, raw.value);
289
+ else {
290
+ const error = new Error(raw.message);
291
+ error.name = raw.name;
292
+ session?.settleRpc(raw.id, false, undefined, error);
293
+ }
294
+ }
295
+ });
296
+ }
297
+ /**
298
+ * Boot only under `worker_threads`.
299
+ *
300
+ * Importing this module on the main thread — a stray import, a bundler that
301
+ * pulled it into a graph — must do nothing rather than install a message
302
+ * handler on a port that is not a worker's.
303
+ */
304
+ const threads = await importNodeBuiltin("node:worker_threads");
305
+ if (threads?.parentPort != null) {
306
+ await startWorker(threads.parentPort);
307
+ }
308
+ //# sourceMappingURL=worker-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-entry.js","sourceRoot":"","sources":["../../src/js-sandbox-worker/worker-entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
2
+ export declare const MAX_OUTPUT_SIZE = 100000;
3
+ export declare const MAX_LOOP_ITERATIONS = 10000;
4
+ export declare const MAX_FETCH_CALLS = 20;
5
+ export declare const MAX_RESPONSE_BODY_SIZE = 1000000;
6
+ /** Guest heap cap. QuickJS aborts if the guest tries to allocate beyond this. */
7
+ export declare const GUEST_MEMORY_LIMIT: number;
8
+ /** Guest stack cap — protects against deeply recursive code. */
9
+ export declare const GUEST_STACK_LIMIT: number;
10
+ /** Per-request wall-clock cap for the fetch bridge. */
11
+ export declare const FETCH_TIMEOUT_MS = 15000;
12
+ /** Redirect hops the fetch bridge follows before giving up. */
13
+ export declare const MAX_FETCH_REDIRECTS = 5;
14
+ /** Locale used by the `format` bridge when the caller names none. */
15
+ export declare const DEFAULT_FORMAT_LOCALE = "en-US";
16
+ export interface SandboxLimits {
17
+ maxFetchCalls?: number;
18
+ maxResponseBodyBytes?: number;
19
+ maxOutputSize?: number;
20
+ memoryLimitBytes?: number;
21
+ /**
22
+ * Total bytes of media one run may hold host-side for its handles. The
23
+ * aggregate the per-call image/media ceilings never bounded.
24
+ */
25
+ runMediaBytes?: number;
26
+ stackLimitBytes?: number;
27
+ fetchTimeoutMs?: number;
28
+ /**
29
+ * Permit fetches to loopback, link-local and private address ranges.
30
+ *
31
+ * Off by default: guest code is untrusted, so the SSRF guard is the norm and
32
+ * this is the exception. It exists because the trusted `lib.http` nodes have
33
+ * always been able to reach a local service, and a Code node replacing one
34
+ * must be able to do the same — a workflow pointing at `http://localhost:8000`
35
+ * would otherwise silently stop working.
36
+ *
37
+ * Host-set only: it is read from {@link RunSandboxOptions.limits} and never
38
+ * exposed to the guest, so sandboxed code cannot turn it on for itself.
39
+ */
40
+ allowPrivateNetwork?: boolean;
41
+ /** `User-Agent` for bridge fetches. Guest-set headers still win. */
42
+ userAgent?: string;
43
+ /**
44
+ * `"workspace"` (default) confines every `workspace.*` call to the workspace
45
+ * root, symlinks included. `"host"` lifts that to the whole filesystem the
46
+ * process can reach, with `~` expanded.
47
+ *
48
+ * Off by default for the same reason as {@link allowPrivateNetwork}, and the
49
+ * stakes are higher — host mode can read credential files. It exists because
50
+ * roughly half the `lib.os` nodes already operate on arbitrary host paths
51
+ * (`expandUser` + raw `node:fs`), so a Code node replacing one needs the same
52
+ * reach. Host-set only, and the graph migration sets it only on nodes
53
+ * rewritten from such a node — a hand-written or model-authored Code node
54
+ * stays confined.
55
+ */
56
+ filesystemAccess?: "workspace" | "host";
57
+ /**
58
+ * The secret names this run may read, or `null`/absent for every secret the
59
+ * store holds.
60
+ *
61
+ * A script that talks to an external service needs one credential, and
62
+ * nothing about `getSecret` used to say so: a node written to send a Slack
63
+ * message could read the AWS keys. Declaring the scope makes the credential
64
+ * a node reaches part of the node, visible in the graph and refused at the
65
+ * bridge rather than trusted to the code.
66
+ *
67
+ * Host-set only, like {@link allowPrivateNetwork}. A run reads its own scope
68
+ * through `nodetool.secrets.list()` but cannot widen it, and an empty array
69
+ * means no secret at all — a stricter thing than an absent scope, not a
70
+ * looser one.
71
+ */
72
+ secretScope?: readonly string[] | null;
73
+ }
74
+ export type ResolvedSandboxLimits = Required<SandboxLimits>;
75
+ /** Apply defaults and ceilings to a caller-supplied {@link SandboxLimits}. */
76
+ export declare function resolveSandboxLimits(limits?: SandboxLimits): ResolvedSandboxLimits;
77
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,eAAe,SAAU,CAAC;AACvC,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAC1C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAChD,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,QAAmB,CAAC;AACnD,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,QAAa,CAAC;AAC5C,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AACvC,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;;;OAYG;IACH,gBAAgB,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IACxC;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;AA0B5D,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,MAAM,CAAC,EAAE,aAAa,GACrB,qBAAqB,CAmDvB"}
package/dist/limits.js ADDED
@@ -0,0 +1,56 @@
1
+ import { isHostAccessEnabled } from "./host-access-gate.js";
2
+ const MAX_RUN_MEDIA_BYTES = 256 * 1024 * 1024;
3
+ export const DEFAULT_TIMEOUT_MS = 30_000;
4
+ export const MAX_OUTPUT_SIZE = 100_000;
5
+ export const MAX_LOOP_ITERATIONS = 10_000;
6
+ export const MAX_FETCH_CALLS = 20;
7
+ export const MAX_RESPONSE_BODY_SIZE = 1_000_000;
8
+ /** Guest heap cap. QuickJS aborts if the guest tries to allocate beyond this. */
9
+ export const GUEST_MEMORY_LIMIT = 64 * 1024 * 1024;
10
+ /** Guest stack cap — protects against deeply recursive code. */
11
+ export const GUEST_STACK_LIMIT = 512 * 1024;
12
+ /** Per-request wall-clock cap for the fetch bridge. */
13
+ export const FETCH_TIMEOUT_MS = 15_000;
14
+ /** Redirect hops the fetch bridge follows before giving up. */
15
+ export const MAX_FETCH_REDIRECTS = 5;
16
+ /** Locale used by the `format` bridge when the caller names none. */
17
+ export const DEFAULT_FORMAT_LOCALE = "en-US";
18
+ /**
19
+ * Normalize a declared secret scope: a list of non-empty names, or `null` for
20
+ * an unscoped run. An empty declared list stays empty — it denies everything.
21
+ */
22
+ function resolveSecretScope(scope) {
23
+ if (!Array.isArray(scope))
24
+ return null;
25
+ return scope
26
+ .filter((name) => typeof name === "string" && name !== "")
27
+ .map((name) => name.trim())
28
+ .filter((name) => name !== "");
29
+ }
30
+ function clampLimit(value, fallback, min, max) {
31
+ if (value == null || !Number.isFinite(value))
32
+ return fallback;
33
+ return Math.min(Math.max(Math.floor(value), min), max);
34
+ }
35
+ /** Apply defaults and ceilings to a caller-supplied {@link SandboxLimits}. */
36
+ export function resolveSandboxLimits(limits) {
37
+ return {
38
+ maxFetchCalls: clampLimit(limits?.maxFetchCalls, MAX_FETCH_CALLS, 0, 100),
39
+ maxResponseBodyBytes: clampLimit(limits?.maxResponseBodyBytes, MAX_RESPONSE_BODY_SIZE, 1024, 50 * 1024 * 1024),
40
+ maxOutputSize: clampLimit(limits?.maxOutputSize, MAX_OUTPUT_SIZE, 1024, 10 * 1024 * 1024),
41
+ memoryLimitBytes: clampLimit(limits?.memoryLimitBytes, GUEST_MEMORY_LIMIT, 1024 * 1024, 512 * 1024 * 1024),
42
+ runMediaBytes: clampLimit(limits?.runMediaBytes, MAX_RUN_MEDIA_BYTES, 1024 * 1024, 2 * 1024 * 1024 * 1024),
43
+ stackLimitBytes: clampLimit(limits?.stackLimitBytes, GUEST_STACK_LIMIT, 16 * 1024, 8 * 1024 * 1024),
44
+ fetchTimeoutMs: clampLimit(limits?.fetchTimeoutMs, FETCH_TIMEOUT_MS, 100, 120_000),
45
+ // Not clamped — these are capability switches, not magnitudes. Both
46
+ // resolve to the restrictive value unless the host explicitly opts out,
47
+ // and the cloud profile never lets them out (see isHostAccessEnabled).
48
+ allowPrivateNetwork: limits?.allowPrivateNetwork === true && isHostAccessEnabled(),
49
+ userAgent: limits?.userAgent ?? "",
50
+ filesystemAccess: limits?.filesystemAccess === "host" && isHostAccessEnabled()
51
+ ? "host"
52
+ : "workspace",
53
+ secretScope: resolveSecretScope(limits?.secretScope)
54
+ };
55
+ }
56
+ //# sourceMappingURL=limits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.js","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * What the guest's Node-compat bootstrap loads, in place of the wrapper's own
3
+ * polyfills.
4
+ *
5
+ * Before our sandboxed function is called, `@sebastianwessel/quickjs` evaluates
6
+ * a fixed preamble in the fresh context:
7
+ *
8
+ * ```js
9
+ * import 'node:buffer'; import 'node:util'; import 'node:url';
10
+ * import '@node_compatibility/headers'; import '@node_compatibility/request';
11
+ * import '@node_compatibility/response';
12
+ * ```
13
+ *
14
+ * Twelve kilobytes of JavaScript, compiled and evaluated into a new runtime on
15
+ * **every run** — 4.3 ms of a 12 ms empty run, against 0.34 ms for a bare
16
+ * QuickJS context. And most of it is thrown away immediately: the init prelude
17
+ * deletes `Buffer`, `Headers`, `Request` and `Response` before user code exists,
18
+ * because guest code has no business with host-shaped Node globals.
19
+ *
20
+ * Those imports resolve through the run's own module loader
21
+ * (`createGuestModuleHost`), which is ours, so the bootstrap can be served
22
+ * something cheaper instead of being fought. Four of the six become empty
23
+ * modules. `node:util` becomes the two classes the guest actually keeps, in
24
+ * place of promisify/callbackify/inherits/deprecate/types it never sees.
25
+ * `node:url` is served by the wrapper unchanged, because `URL` and
26
+ * `URLSearchParams` are guest capabilities and a hand-rolled URL parser is not
27
+ * a saving worth making.
28
+ *
29
+ * Measured on this repo's engine: wrapper setup 5.96 ms → 3.28 ms per run.
30
+ *
31
+ * The failure modes are deliberately lopsided. A wrapper release that renames
32
+ * or moves these modules makes the map miss, the real polyfill loads, and the
33
+ * only loss is the saving — pinned by "the compat bootstrap loads our stubs" in
34
+ * `tests/js-sandbox-modules.test.ts`, which fails loudly rather than silently
35
+ * costing 2.7 ms. A release that imports something our `node:util` does not
36
+ * export fails every sandbox run in the suite, which is as loud as it gets.
37
+ *
38
+ * Browser-safe: nothing here imports a Node builtin.
39
+ */
40
+ /**
41
+ * Module id → the source served during the wrapper's bootstrap phase. The ids
42
+ * are what its own normalizer produces for the specifiers above; anything not
43
+ * listed loads from the wrapper as before.
44
+ */
45
+ export declare const BOOTSTRAP_MODULE_SOURCES: ReadonlyMap<string, string>;
46
+ /** Use one module-id shape across the wrapper's POSIX and Windows normalizers. */
47
+ export declare function normalizeBootstrapModuleId(moduleId: string): string;
48
+ /**
49
+ * The globals the bootstrap no longer installs, in the order a reader would
50
+ * check them. Exported so a test can assert they are gone at the source rather
51
+ * than after the prelude's `delete`, which would hide a missed stub.
52
+ */
53
+ export declare const BOOTSTRAP_DROPPED_GLOBALS: readonly ["Buffer", "Headers", "Request", "Response"];
54
+ //# sourceMappingURL=sandbox-bootstrap-modules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-bootstrap-modules.d.ts","sourceRoot":"","sources":["../src/sandbox-bootstrap-modules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAuCH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAQ/D,CAAC;AAEH,kFAAkF;AAClF,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,YACpC,QAAQ,EACR,SAAS,EACT,SAAS,EACT,UAAU,CACF,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * What the guest's Node-compat bootstrap loads, in place of the wrapper's own
3
+ * polyfills.
4
+ *
5
+ * Before our sandboxed function is called, `@sebastianwessel/quickjs` evaluates
6
+ * a fixed preamble in the fresh context:
7
+ *
8
+ * ```js
9
+ * import 'node:buffer'; import 'node:util'; import 'node:url';
10
+ * import '@node_compatibility/headers'; import '@node_compatibility/request';
11
+ * import '@node_compatibility/response';
12
+ * ```
13
+ *
14
+ * Twelve kilobytes of JavaScript, compiled and evaluated into a new runtime on
15
+ * **every run** — 4.3 ms of a 12 ms empty run, against 0.34 ms for a bare
16
+ * QuickJS context. And most of it is thrown away immediately: the init prelude
17
+ * deletes `Buffer`, `Headers`, `Request` and `Response` before user code exists,
18
+ * because guest code has no business with host-shaped Node globals.
19
+ *
20
+ * Those imports resolve through the run's own module loader
21
+ * (`createGuestModuleHost`), which is ours, so the bootstrap can be served
22
+ * something cheaper instead of being fought. Four of the six become empty
23
+ * modules. `node:util` becomes the two classes the guest actually keeps, in
24
+ * place of promisify/callbackify/inherits/deprecate/types it never sees.
25
+ * `node:url` is served by the wrapper unchanged, because `URL` and
26
+ * `URLSearchParams` are guest capabilities and a hand-rolled URL parser is not
27
+ * a saving worth making.
28
+ *
29
+ * Measured on this repo's engine: wrapper setup 5.96 ms → 3.28 ms per run.
30
+ *
31
+ * The failure modes are deliberately lopsided. A wrapper release that renames
32
+ * or moves these modules makes the map miss, the real polyfill loads, and the
33
+ * only loss is the saving — pinned by "the compat bootstrap loads our stubs" in
34
+ * `tests/js-sandbox-modules.test.ts`, which fails loudly rather than silently
35
+ * costing 2.7 ms. A release that imports something our `node:util` does not
36
+ * export fails every sandbox run in the suite, which is as loud as it gets.
37
+ *
38
+ * Browser-safe: nothing here imports a Node builtin.
39
+ */
40
+ /** A module whose only job is to exist, for an `import` that wants no export. */
41
+ const EMPTY_MODULE = "export default {};";
42
+ /**
43
+ * `TextEncoder`/`TextDecoder`, which the wrapper's `node:util` installs as
44
+ * globals and which the guest surface documents.
45
+ *
46
+ * The `encodeURIComponent`/`unescape` pair is UTF-8 the way the wrapper's own
47
+ * polyfill does it, so the bytes a guest sees are the bytes it saw before. Both
48
+ * classes are also exported by name: the wrapper's `node:buffer` imports them
49
+ * that way, and although that module is empty here, a future one may not be.
50
+ */
51
+ const UTIL_MODULE = `
52
+ class TextEncoder {
53
+ encode(input = "") {
54
+ const utf8 = unescape(encodeURIComponent(input));
55
+ const out = new Uint8Array(utf8.length);
56
+ for (let i = 0; i < utf8.length; i++) out[i] = utf8.charCodeAt(i);
57
+ return out;
58
+ }
59
+ }
60
+ class TextDecoder {
61
+ constructor(encoding = "utf-8") {
62
+ if (encoding !== "utf-8") throw new Error("Only utf-8 encoding is supported");
63
+ }
64
+ decode(input = new Uint8Array()) {
65
+ let text = "";
66
+ for (let i = 0; i < input.length; i++) text += String.fromCharCode(input[i]);
67
+ return decodeURIComponent(escape(text));
68
+ }
69
+ }
70
+ globalThis.TextEncoder = TextEncoder;
71
+ globalThis.TextDecoder = TextDecoder;
72
+ export { TextEncoder, TextDecoder };
73
+ export default { TextEncoder, TextDecoder };
74
+ `;
75
+ /**
76
+ * Module id → the source served during the wrapper's bootstrap phase. The ids
77
+ * are what its own normalizer produces for the specifiers above; anything not
78
+ * listed loads from the wrapper as before.
79
+ */
80
+ export const BOOTSTRAP_MODULE_SOURCES = new Map([
81
+ // Deleted by the init prelude the moment the bootstrap finishes.
82
+ ["/node_modules/buffer", EMPTY_MODULE],
83
+ ["/node_modules/@node_compatibility/headers", EMPTY_MODULE],
84
+ ["/node_modules/@node_compatibility/request", EMPTY_MODULE],
85
+ ["/node_modules/@node_compatibility/response", EMPTY_MODULE],
86
+ // Kept, minus everything the guest cannot reach.
87
+ ["/node_modules/util", UTIL_MODULE]
88
+ ]);
89
+ /** Use one module-id shape across the wrapper's POSIX and Windows normalizers. */
90
+ export function normalizeBootstrapModuleId(moduleId) {
91
+ return moduleId.replaceAll("\\", "/");
92
+ }
93
+ /**
94
+ * The globals the bootstrap no longer installs, in the order a reader would
95
+ * check them. Exported so a test can assert they are gone at the source rather
96
+ * than after the prelude's `delete`, which would hide a missed stub.
97
+ */
98
+ export const BOOTSTRAP_DROPPED_GLOBALS = [
99
+ "Buffer",
100
+ "Headers",
101
+ "Request",
102
+ "Response"
103
+ ];
104
+ //# sourceMappingURL=sandbox-bootstrap-modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-bootstrap-modules.js","sourceRoot":"","sources":["../src/sandbox-bootstrap-modules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,iFAAiF;AACjF,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;CAuBnB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAgC,IAAI,GAAG,CAAC;IAC3E,iEAAiE;IACjE,CAAC,sBAAsB,EAAE,YAAY,CAAC;IACtC,CAAC,2CAA2C,EAAE,YAAY,CAAC;IAC3D,CAAC,2CAA2C,EAAE,YAAY,CAAC;IAC3D,CAAC,4CAA4C,EAAE,YAAY,CAAC;IAC5D,iDAAiD;IACjD,CAAC,oBAAoB,EAAE,WAAW,CAAC;CACpC,CAAC,CAAC;AAEH,kFAAkF;AAClF,MAAM,UAAU,0BAA0B,CAAC,QAAgB;IACzD,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,QAAQ;IACR,SAAS;IACT,SAAS;IACT,UAAU;CACF,CAAC"}