@secure-exec/core 0.1.0 → 0.1.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge/child-process.js +8 -22
- package/dist/bridge/fs.js +25 -29
- package/dist/bridge/module.js +3 -12
- package/dist/bridge/network.d.ts +1 -0
- package/dist/bridge/network.js +47 -30
- package/dist/bridge/process.d.ts +3 -0
- package/dist/bridge/process.js +40 -22
- package/dist/bridge.js +113 -96
- package/dist/generated/isolate-runtime.d.ts +5 -5
- package/dist/generated/isolate-runtime.js +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/isolate-runtime/apply-custom-global-policy.js +2 -3
- package/dist/isolate-runtime/bridge-initial-globals.js +143 -4
- package/dist/isolate-runtime/require-setup.js +3 -3
- package/dist/isolate-runtime/setup-dynamic-import.js +1 -5
- package/dist/isolate-runtime/setup-fs-facade.js +60 -21
- package/dist/module-resolver.js +49 -3
- package/dist/shared/api-types.d.ts +6 -0
- package/dist/shared/bridge-contract.d.ts +97 -80
- package/dist/shared/bridge-contract.js +4 -2
- package/dist/shared/console-formatter.js +4 -4
- package/dist/shared/global-exposure.js +5 -0
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -21,12 +21,17 @@
|
|
|
21
21
|
return createRuntimeGlobalExposer(true);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// isolate-runtime/src/common/global-access.ts
|
|
25
|
+
function setGlobalValue(name, value) {
|
|
26
|
+
Reflect.set(globalThis, name, value);
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
// isolate-runtime/src/inject/bridge-initial-globals.ts
|
|
25
30
|
var __runtimeExposeMutableGlobal = getRuntimeExposeMutableGlobal();
|
|
26
31
|
var __bridgeSetupConfig = globalThis.__runtimeBridgeSetupConfig ?? {};
|
|
27
32
|
var __initialCwd = typeof __bridgeSetupConfig.initialCwd === "string" ? __bridgeSetupConfig.initialCwd : "/";
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
globalThis.__runtimeJsonPayloadLimitBytes = typeof __bridgeSetupConfig.jsonPayloadLimitBytes === "number" && Number.isFinite(__bridgeSetupConfig.jsonPayloadLimitBytes) ? Math.max(0, Math.floor(__bridgeSetupConfig.jsonPayloadLimitBytes)) : 4 * 1024 * 1024;
|
|
34
|
+
globalThis.__runtimePayloadLimitErrorCode = typeof __bridgeSetupConfig.payloadLimitErrorCode === "string" && __bridgeSetupConfig.payloadLimitErrorCode.length > 0 ? __bridgeSetupConfig.payloadLimitErrorCode : "ERR_SANDBOX_PAYLOAD_TOO_LARGE";
|
|
30
35
|
function __scEncode(value, seen) {
|
|
31
36
|
if (value === null) return null;
|
|
32
37
|
if (value === void 0) return { t: "undef" };
|
|
@@ -224,9 +229,11 @@
|
|
|
224
229
|
);
|
|
225
230
|
},
|
|
226
231
|
deserialize: function(buffer) {
|
|
227
|
-
|
|
232
|
+
const limit = globalThis.__runtimeJsonPayloadLimitBytes ?? 4 * 1024 * 1024;
|
|
233
|
+
const errorCode = globalThis.__runtimePayloadLimitErrorCode ?? "ERR_SANDBOX_PAYLOAD_TOO_LARGE";
|
|
234
|
+
if (buffer.length > limit) {
|
|
228
235
|
throw new Error(
|
|
229
|
-
|
|
236
|
+
errorCode + ": v8.deserialize exceeds " + String(limit) + " bytes"
|
|
230
237
|
);
|
|
231
238
|
}
|
|
232
239
|
const text = buffer.toString();
|
|
@@ -243,4 +250,136 @@
|
|
|
243
250
|
}
|
|
244
251
|
__runtimeExposeMutableGlobal("_pendingModules", {});
|
|
245
252
|
__runtimeExposeMutableGlobal("_currentModule", { dirname: __initialCwd });
|
|
253
|
+
globalThis.__runtimeApplyConfig = function(config) {
|
|
254
|
+
if (typeof config.payloadLimitBytes === "number" && Number.isFinite(config.payloadLimitBytes)) {
|
|
255
|
+
globalThis.__runtimeJsonPayloadLimitBytes = Math.max(
|
|
256
|
+
0,
|
|
257
|
+
Math.floor(config.payloadLimitBytes)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
if (typeof config.payloadLimitErrorCode === "string" && config.payloadLimitErrorCode.length > 0) {
|
|
261
|
+
globalThis.__runtimePayloadLimitErrorCode = config.payloadLimitErrorCode;
|
|
262
|
+
}
|
|
263
|
+
if (config.timingMitigation === "freeze") {
|
|
264
|
+
const frozenTimeMs = typeof config.frozenTimeMs === "number" && Number.isFinite(config.frozenTimeMs) ? config.frozenTimeMs : Date.now();
|
|
265
|
+
const frozenDateNow = () => frozenTimeMs;
|
|
266
|
+
try {
|
|
267
|
+
Object.defineProperty(Date, "now", {
|
|
268
|
+
value: frozenDateNow,
|
|
269
|
+
configurable: false,
|
|
270
|
+
writable: false
|
|
271
|
+
});
|
|
272
|
+
} catch {
|
|
273
|
+
Date.now = frozenDateNow;
|
|
274
|
+
}
|
|
275
|
+
const OrigDate = Date;
|
|
276
|
+
const FrozenDate = function Date2(...args) {
|
|
277
|
+
if (new.target) {
|
|
278
|
+
if (args.length === 0) {
|
|
279
|
+
return new OrigDate(frozenTimeMs);
|
|
280
|
+
}
|
|
281
|
+
return new OrigDate(...args);
|
|
282
|
+
}
|
|
283
|
+
return OrigDate();
|
|
284
|
+
};
|
|
285
|
+
Object.defineProperty(FrozenDate, "prototype", {
|
|
286
|
+
value: OrigDate.prototype,
|
|
287
|
+
writable: false,
|
|
288
|
+
configurable: false
|
|
289
|
+
});
|
|
290
|
+
FrozenDate.now = frozenDateNow;
|
|
291
|
+
FrozenDate.parse = OrigDate.parse;
|
|
292
|
+
FrozenDate.UTC = OrigDate.UTC;
|
|
293
|
+
Object.defineProperty(FrozenDate, "now", {
|
|
294
|
+
value: frozenDateNow,
|
|
295
|
+
configurable: false,
|
|
296
|
+
writable: false
|
|
297
|
+
});
|
|
298
|
+
try {
|
|
299
|
+
Object.defineProperty(globalThis, "Date", {
|
|
300
|
+
value: FrozenDate,
|
|
301
|
+
configurable: false,
|
|
302
|
+
writable: false
|
|
303
|
+
});
|
|
304
|
+
} catch {
|
|
305
|
+
globalThis.Date = FrozenDate;
|
|
306
|
+
}
|
|
307
|
+
const frozenPerformanceNow = () => 0;
|
|
308
|
+
const origPerf = globalThis.performance;
|
|
309
|
+
const frozenPerf = /* @__PURE__ */ Object.create(null);
|
|
310
|
+
if (typeof origPerf !== "undefined" && origPerf !== null) {
|
|
311
|
+
const src = origPerf;
|
|
312
|
+
for (const key of Object.getOwnPropertyNames(
|
|
313
|
+
Object.getPrototypeOf(origPerf) ?? origPerf
|
|
314
|
+
)) {
|
|
315
|
+
if (key !== "now") {
|
|
316
|
+
try {
|
|
317
|
+
const val = src[key];
|
|
318
|
+
if (typeof val === "function") {
|
|
319
|
+
frozenPerf[key] = val.bind(origPerf);
|
|
320
|
+
} else {
|
|
321
|
+
frozenPerf[key] = val;
|
|
322
|
+
}
|
|
323
|
+
} catch {
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
Object.defineProperty(frozenPerf, "now", {
|
|
329
|
+
value: frozenPerformanceNow,
|
|
330
|
+
configurable: false,
|
|
331
|
+
writable: false
|
|
332
|
+
});
|
|
333
|
+
Object.freeze(frozenPerf);
|
|
334
|
+
try {
|
|
335
|
+
Object.defineProperty(globalThis, "performance", {
|
|
336
|
+
value: frozenPerf,
|
|
337
|
+
configurable: false,
|
|
338
|
+
writable: false
|
|
339
|
+
});
|
|
340
|
+
} catch {
|
|
341
|
+
globalThis.performance = frozenPerf;
|
|
342
|
+
}
|
|
343
|
+
const OrigSAB = globalThis.SharedArrayBuffer;
|
|
344
|
+
if (typeof OrigSAB === "function") {
|
|
345
|
+
try {
|
|
346
|
+
const proto = OrigSAB.prototype;
|
|
347
|
+
if (proto) {
|
|
348
|
+
for (const key of [
|
|
349
|
+
"byteLength",
|
|
350
|
+
"slice",
|
|
351
|
+
"grow",
|
|
352
|
+
"maxByteLength",
|
|
353
|
+
"growable"
|
|
354
|
+
]) {
|
|
355
|
+
try {
|
|
356
|
+
Object.defineProperty(proto, key, {
|
|
357
|
+
get() {
|
|
358
|
+
throw new TypeError(
|
|
359
|
+
"SharedArrayBuffer is not available in sandbox"
|
|
360
|
+
);
|
|
361
|
+
},
|
|
362
|
+
configurable: false
|
|
363
|
+
});
|
|
364
|
+
} catch {
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
} catch {
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
Object.defineProperty(globalThis, "SharedArrayBuffer", {
|
|
373
|
+
value: void 0,
|
|
374
|
+
configurable: false,
|
|
375
|
+
writable: false,
|
|
376
|
+
enumerable: false
|
|
377
|
+
});
|
|
378
|
+
} catch {
|
|
379
|
+
Reflect.deleteProperty(globalThis, "SharedArrayBuffer");
|
|
380
|
+
setGlobalValue("SharedArrayBuffer", void 0);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
delete globalThis.__runtimeApplyConfig;
|
|
384
|
+
};
|
|
246
385
|
})();
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
};
|
|
277
277
|
__requireExposeCustomGlobal("require", __require);
|
|
278
278
|
function _resolveFrom(moduleName2, fromDir2) {
|
|
279
|
-
const resolved2 = _resolveModule
|
|
279
|
+
const resolved2 = _resolveModule(moduleName2, fromDir2);
|
|
280
280
|
if (resolved2 === null) {
|
|
281
281
|
const err = new Error("Cannot find module '" + moduleName2 + "'");
|
|
282
282
|
err.code = "MODULE_NOT_FOUND";
|
|
@@ -549,7 +549,7 @@
|
|
|
549
549
|
if (_unsupportedCoreModules.has(name)) {
|
|
550
550
|
throw new Error(name + " is not supported in sandbox");
|
|
551
551
|
}
|
|
552
|
-
const polyfillCode = _loadPolyfill
|
|
552
|
+
const polyfillCode = _loadPolyfill(name);
|
|
553
553
|
if (polyfillCode !== null) {
|
|
554
554
|
if (__internalModuleCache[name]) return __internalModuleCache[name];
|
|
555
555
|
const moduleObj = { exports: {} };
|
|
@@ -576,7 +576,7 @@
|
|
|
576
576
|
_debugRequire("pending-hit", name, cacheKey);
|
|
577
577
|
return _pendingModules[cacheKey].exports;
|
|
578
578
|
}
|
|
579
|
-
const source = _loadFile
|
|
579
|
+
const source = _loadFile(resolved);
|
|
580
580
|
if (source === null) {
|
|
581
581
|
const err = new Error("Cannot find module '" + resolved + "'");
|
|
582
582
|
err.code = "MODULE_NOT_FOUND";
|
|
@@ -34,11 +34,7 @@
|
|
|
34
34
|
const request = String(specifier);
|
|
35
35
|
const referrer = typeof fromPath === "string" && fromPath.length > 0 ? fromPath : __fallbackReferrer;
|
|
36
36
|
const allowRequireFallback = request.endsWith(".cjs") || request.endsWith(".json");
|
|
37
|
-
const namespace = await globalThis._dynamicImport
|
|
38
|
-
void 0,
|
|
39
|
-
[request, referrer],
|
|
40
|
-
{ result: { promise: true } }
|
|
41
|
-
);
|
|
37
|
+
const namespace = await globalThis._dynamicImport(request, referrer);
|
|
42
38
|
if (namespace !== null) {
|
|
43
39
|
return namespace;
|
|
44
40
|
}
|
|
@@ -23,26 +23,65 @@
|
|
|
23
23
|
|
|
24
24
|
// isolate-runtime/src/inject/setup-fs-facade.ts
|
|
25
25
|
var __runtimeExposeCustomGlobal = getRuntimeExposeCustomGlobal();
|
|
26
|
-
var __fsFacade = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
26
|
+
var __fsFacade = {};
|
|
27
|
+
Object.defineProperties(__fsFacade, {
|
|
28
|
+
readFile: { get() {
|
|
29
|
+
return globalThis._fsReadFile;
|
|
30
|
+
}, enumerable: true },
|
|
31
|
+
writeFile: { get() {
|
|
32
|
+
return globalThis._fsWriteFile;
|
|
33
|
+
}, enumerable: true },
|
|
34
|
+
readFileBinary: { get() {
|
|
35
|
+
return globalThis._fsReadFileBinary;
|
|
36
|
+
}, enumerable: true },
|
|
37
|
+
writeFileBinary: { get() {
|
|
38
|
+
return globalThis._fsWriteFileBinary;
|
|
39
|
+
}, enumerable: true },
|
|
40
|
+
readDir: { get() {
|
|
41
|
+
return globalThis._fsReadDir;
|
|
42
|
+
}, enumerable: true },
|
|
43
|
+
mkdir: { get() {
|
|
44
|
+
return globalThis._fsMkdir;
|
|
45
|
+
}, enumerable: true },
|
|
46
|
+
rmdir: { get() {
|
|
47
|
+
return globalThis._fsRmdir;
|
|
48
|
+
}, enumerable: true },
|
|
49
|
+
exists: { get() {
|
|
50
|
+
return globalThis._fsExists;
|
|
51
|
+
}, enumerable: true },
|
|
52
|
+
stat: { get() {
|
|
53
|
+
return globalThis._fsStat;
|
|
54
|
+
}, enumerable: true },
|
|
55
|
+
unlink: { get() {
|
|
56
|
+
return globalThis._fsUnlink;
|
|
57
|
+
}, enumerable: true },
|
|
58
|
+
rename: { get() {
|
|
59
|
+
return globalThis._fsRename;
|
|
60
|
+
}, enumerable: true },
|
|
61
|
+
chmod: { get() {
|
|
62
|
+
return globalThis._fsChmod;
|
|
63
|
+
}, enumerable: true },
|
|
64
|
+
chown: { get() {
|
|
65
|
+
return globalThis._fsChown;
|
|
66
|
+
}, enumerable: true },
|
|
67
|
+
link: { get() {
|
|
68
|
+
return globalThis._fsLink;
|
|
69
|
+
}, enumerable: true },
|
|
70
|
+
symlink: { get() {
|
|
71
|
+
return globalThis._fsSymlink;
|
|
72
|
+
}, enumerable: true },
|
|
73
|
+
readlink: { get() {
|
|
74
|
+
return globalThis._fsReadlink;
|
|
75
|
+
}, enumerable: true },
|
|
76
|
+
lstat: { get() {
|
|
77
|
+
return globalThis._fsLstat;
|
|
78
|
+
}, enumerable: true },
|
|
79
|
+
truncate: { get() {
|
|
80
|
+
return globalThis._fsTruncate;
|
|
81
|
+
}, enumerable: true },
|
|
82
|
+
utimes: { get() {
|
|
83
|
+
return globalThis._fsUtimes;
|
|
84
|
+
}, enumerable: true }
|
|
85
|
+
});
|
|
47
86
|
__runtimeExposeCustomGlobal("_fs", __fsFacade);
|
|
48
87
|
})();
|
package/dist/module-resolver.js
CHANGED
|
@@ -9,12 +9,58 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Everything else falls through to node-stdlib-browser polyfills or node_modules.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Static set of Node.js stdlib module names that have browser polyfills
|
|
14
|
+
* available via node-stdlib-browser. Hardcoded to avoid importing
|
|
15
|
+
* node-stdlib-browser at runtime (its ESM entry crashes on missing
|
|
16
|
+
* mock/empty.js in published builds).
|
|
17
|
+
*/
|
|
18
|
+
const STDLIB_BROWSER_MODULES = new Set([
|
|
19
|
+
"assert",
|
|
20
|
+
"buffer",
|
|
21
|
+
"child_process",
|
|
22
|
+
"cluster",
|
|
23
|
+
"console",
|
|
24
|
+
"constants",
|
|
25
|
+
"crypto",
|
|
26
|
+
"dgram",
|
|
27
|
+
"dns",
|
|
28
|
+
"domain",
|
|
29
|
+
"events",
|
|
30
|
+
"fs",
|
|
31
|
+
"http",
|
|
32
|
+
"https",
|
|
33
|
+
"http2",
|
|
34
|
+
"module",
|
|
35
|
+
"net",
|
|
36
|
+
"os",
|
|
37
|
+
"path",
|
|
38
|
+
"punycode",
|
|
39
|
+
"process",
|
|
40
|
+
"querystring",
|
|
41
|
+
"readline",
|
|
42
|
+
"repl",
|
|
43
|
+
"stream",
|
|
44
|
+
"_stream_duplex",
|
|
45
|
+
"_stream_passthrough",
|
|
46
|
+
"_stream_readable",
|
|
47
|
+
"_stream_transform",
|
|
48
|
+
"_stream_writable",
|
|
49
|
+
"string_decoder",
|
|
50
|
+
"sys",
|
|
51
|
+
"timers/promises",
|
|
52
|
+
"timers",
|
|
53
|
+
"tls",
|
|
54
|
+
"tty",
|
|
55
|
+
"url",
|
|
56
|
+
"util",
|
|
57
|
+
"vm",
|
|
58
|
+
"zlib",
|
|
59
|
+
]);
|
|
13
60
|
/** Check if a module has a polyfill available via node-stdlib-browser. */
|
|
14
61
|
function hasPolyfill(moduleName) {
|
|
15
62
|
const name = moduleName.replace(/^node:/, "");
|
|
16
|
-
|
|
17
|
-
return polyfill !== undefined && polyfill !== null;
|
|
63
|
+
return STDLIB_BROWSER_MODULES.has(name);
|
|
18
64
|
}
|
|
19
65
|
/** Modules with full bridge implementations injected into the isolate. */
|
|
20
66
|
const BRIDGE_MODULES = [
|
|
@@ -23,6 +23,12 @@ export interface ProcessConfig {
|
|
|
23
23
|
timingMitigation?: TimingMitigation;
|
|
24
24
|
/** Internal frozen clock source used when timing mitigation is enabled */
|
|
25
25
|
frozenTimeMs?: number;
|
|
26
|
+
/** Whether stdin is a TTY (PTY slave attached) */
|
|
27
|
+
stdinIsTTY?: boolean;
|
|
28
|
+
/** Whether stdout is a TTY (PTY slave attached) */
|
|
29
|
+
stdoutIsTTY?: boolean;
|
|
30
|
+
/** Whether stderr is a TTY (PTY slave attached) */
|
|
31
|
+
stderrIsTTY?: boolean;
|
|
26
32
|
}
|
|
27
33
|
export interface OSConfig {
|
|
28
34
|
platform?: string;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* host (Node.js) and the isolate (sandbox V8 context).
|
|
4
4
|
*
|
|
5
5
|
* Two categories:
|
|
6
|
-
* - Host bridge globals: set by the host before bridge code runs (fs
|
|
6
|
+
* - Host bridge globals: set by the host before bridge code runs (fs fns, timers, etc.)
|
|
7
7
|
* - Runtime bridge globals: installed by the bridge bundle itself (active handles, modules, etc.)
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Each type alias is a plain function signature. The Rust V8 runtime registers
|
|
10
|
+
* these as real JS functions on the global; bridge code calls them directly.
|
|
10
11
|
*/
|
|
11
12
|
export type ValueOf<T> = T[keyof T];
|
|
12
13
|
/** Globals injected by the host before the bridge bundle executes. */
|
|
@@ -47,6 +48,7 @@ export declare const HOST_BRIDGE_GLOBAL_KEYS: {
|
|
|
47
48
|
readonly networkHttpRequestRaw: "_networkHttpRequestRaw";
|
|
48
49
|
readonly networkHttpServerListenRaw: "_networkHttpServerListenRaw";
|
|
49
50
|
readonly networkHttpServerCloseRaw: "_networkHttpServerCloseRaw";
|
|
51
|
+
readonly ptySetRawMode: "_ptySetRawMode";
|
|
50
52
|
readonly processConfig: "_processConfig";
|
|
51
53
|
readonly osConfig: "_osConfig";
|
|
52
54
|
readonly log: "_log";
|
|
@@ -112,6 +114,7 @@ export declare const HOST_BRIDGE_GLOBAL_KEY_LIST: ValueOf<{
|
|
|
112
114
|
readonly networkHttpRequestRaw: "_networkHttpRequestRaw";
|
|
113
115
|
readonly networkHttpServerListenRaw: "_networkHttpServerListenRaw";
|
|
114
116
|
readonly networkHttpServerCloseRaw: "_networkHttpServerCloseRaw";
|
|
117
|
+
readonly ptySetRawMode: "_ptySetRawMode";
|
|
115
118
|
readonly processConfig: "_processConfig";
|
|
116
119
|
readonly osConfig: "_osConfig";
|
|
117
120
|
readonly log: "_log";
|
|
@@ -173,6 +176,7 @@ export declare const BRIDGE_GLOBAL_KEY_LIST: readonly (ValueOf<{
|
|
|
173
176
|
readonly networkHttpRequestRaw: "_networkHttpRequestRaw";
|
|
174
177
|
readonly networkHttpServerListenRaw: "_networkHttpServerListenRaw";
|
|
175
178
|
readonly networkHttpServerCloseRaw: "_networkHttpServerCloseRaw";
|
|
179
|
+
readonly ptySetRawMode: "_ptySetRawMode";
|
|
176
180
|
readonly processConfig: "_processConfig";
|
|
177
181
|
readonly osConfig: "_osConfig";
|
|
178
182
|
readonly log: "_log";
|
|
@@ -196,65 +200,52 @@ export declare const BRIDGE_GLOBAL_KEY_LIST: readonly (ValueOf<{
|
|
|
196
200
|
readonly moduleCache: "_moduleCache";
|
|
197
201
|
readonly processExitError: "ProcessExitError";
|
|
198
202
|
}>)[];
|
|
199
|
-
|
|
200
|
-
export
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
promise: true;
|
|
204
|
-
};
|
|
205
|
-
}): Promise<TResult>;
|
|
206
|
-
}
|
|
207
|
-
/** An isolated-vm Reference called synchronously (blocks the isolate). */
|
|
208
|
-
export interface BridgeApplySyncRef<TArgs extends unknown[], TResult> {
|
|
209
|
-
applySync(ctx: undefined, args: TArgs): TResult;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* An isolated-vm Reference that blocks the isolate while the host resolves
|
|
213
|
-
* a Promise. Used for sync-looking APIs (require, readFileSync) that need
|
|
214
|
-
* async host operations.
|
|
215
|
-
*/
|
|
216
|
-
export interface BridgeApplySyncPromiseRef<TArgs extends unknown[], TResult> {
|
|
217
|
-
applySyncPromise(ctx: undefined, args: TArgs): TResult;
|
|
218
|
-
}
|
|
219
|
-
export type DynamicImportBridgeRef = BridgeApplyRef<[
|
|
220
|
-
string,
|
|
221
|
-
string
|
|
222
|
-
], Record<string, unknown> | null>;
|
|
223
|
-
export type LoadPolyfillBridgeRef = BridgeApplyRef<[string], string | null>;
|
|
224
|
-
export type ResolveModuleBridgeRef = BridgeApplySyncPromiseRef<[
|
|
225
|
-
string,
|
|
226
|
-
string
|
|
227
|
-
], string | null>;
|
|
228
|
-
export type LoadFileBridgeRef = BridgeApplySyncPromiseRef<[string], string | null>;
|
|
203
|
+
export type DynamicImportBridgeRef = (specifier: string, fromPath: string) => Promise<Record<string, unknown> | null>;
|
|
204
|
+
export type LoadPolyfillBridgeRef = (moduleName: string) => string | null;
|
|
205
|
+
export type ResolveModuleBridgeRef = (request: string, fromDir: string) => string | null;
|
|
206
|
+
export type LoadFileBridgeRef = (path: string) => string | null;
|
|
229
207
|
export type RequireFromBridgeFn = (request: string, dirname: string) => unknown;
|
|
230
208
|
export type ModuleCacheBridgeRecord = Record<string, unknown>;
|
|
231
|
-
export type ProcessLogBridgeRef =
|
|
232
|
-
export type ProcessErrorBridgeRef =
|
|
233
|
-
export type ScheduleTimerBridgeRef =
|
|
234
|
-
export type CryptoRandomFillBridgeRef =
|
|
235
|
-
export type CryptoRandomUuidBridgeRef =
|
|
236
|
-
export type FsReadFileBridgeRef =
|
|
237
|
-
export type FsWriteFileBridgeRef =
|
|
238
|
-
export type FsReadFileBinaryBridgeRef =
|
|
239
|
-
export type FsWriteFileBinaryBridgeRef =
|
|
240
|
-
|
|
241
|
-
string
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
export type
|
|
245
|
-
export type
|
|
246
|
-
export type
|
|
247
|
-
export type
|
|
248
|
-
export type
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
export type
|
|
209
|
+
export type ProcessLogBridgeRef = (msg: string) => void;
|
|
210
|
+
export type ProcessErrorBridgeRef = (msg: string) => void;
|
|
211
|
+
export type ScheduleTimerBridgeRef = (delayMs: number) => Promise<void>;
|
|
212
|
+
export type CryptoRandomFillBridgeRef = (byteLength: number) => Uint8Array;
|
|
213
|
+
export type CryptoRandomUuidBridgeRef = () => string;
|
|
214
|
+
export type FsReadFileBridgeRef = (path: string) => string;
|
|
215
|
+
export type FsWriteFileBridgeRef = (path: string, content: string) => void;
|
|
216
|
+
export type FsReadFileBinaryBridgeRef = (path: string) => Uint8Array;
|
|
217
|
+
export type FsWriteFileBinaryBridgeRef = (path: string, content: Uint8Array) => void;
|
|
218
|
+
export type FsReadDirEntry = {
|
|
219
|
+
name: string;
|
|
220
|
+
isDirectory: boolean;
|
|
221
|
+
};
|
|
222
|
+
export type FsReadDirBridgeRef = (path: string) => FsReadDirEntry[];
|
|
223
|
+
export type FsMkdirBridgeRef = (path: string, recursive: boolean) => void;
|
|
224
|
+
export type FsRmdirBridgeRef = (path: string) => void;
|
|
225
|
+
export type FsExistsBridgeRef = (path: string) => boolean;
|
|
226
|
+
export type FsStatResult = {
|
|
227
|
+
mode: number;
|
|
228
|
+
size: number;
|
|
229
|
+
isDirectory: boolean;
|
|
230
|
+
atimeMs: number;
|
|
231
|
+
mtimeMs: number;
|
|
232
|
+
ctimeMs: number;
|
|
233
|
+
birthtimeMs: number;
|
|
234
|
+
};
|
|
235
|
+
export type FsStatBridgeRef = (path: string) => FsStatResult;
|
|
236
|
+
export type FsUnlinkBridgeRef = (path: string) => void;
|
|
237
|
+
export type FsRenameBridgeRef = (oldPath: string, newPath: string) => void;
|
|
238
|
+
export type FsChmodBridgeRef = (path: string, mode: number) => void;
|
|
239
|
+
export type FsChownBridgeRef = (path: string, uid: number, gid: number) => void;
|
|
240
|
+
export type FsLinkBridgeRef = (existingPath: string, newPath: string) => void;
|
|
241
|
+
export type FsSymlinkBridgeRef = (target: string, path: string) => void;
|
|
242
|
+
export type FsReadlinkBridgeRef = (path: string) => string;
|
|
243
|
+
export type FsLstatResult = FsStatResult & {
|
|
244
|
+
isSymbolicLink: boolean;
|
|
245
|
+
};
|
|
246
|
+
export type FsLstatBridgeRef = (path: string) => FsLstatResult;
|
|
247
|
+
export type FsTruncateBridgeRef = (path: string, length: number) => void;
|
|
248
|
+
export type FsUtimesBridgeRef = (path: string, atime: number, mtime: number) => void;
|
|
258
249
|
/** Combined filesystem bridge facade installed as `globalThis._fs` in the isolate. */
|
|
259
250
|
export interface FsFacadeBridge {
|
|
260
251
|
readFile: FsReadFileBridgeRef;
|
|
@@ -277,26 +268,52 @@ export interface FsFacadeBridge {
|
|
|
277
268
|
truncate: FsTruncateBridgeRef;
|
|
278
269
|
utimes: FsUtimesBridgeRef;
|
|
279
270
|
}
|
|
280
|
-
export type ChildProcessSpawnStartBridgeRef =
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
export type
|
|
291
|
-
export type
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
string
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
export type
|
|
271
|
+
export type ChildProcessSpawnStartBridgeRef = (command: string, argsJson: string, optionsJson: string) => number;
|
|
272
|
+
export type ChildProcessStdinWriteBridgeRef = (sessionId: number, data: Uint8Array) => void;
|
|
273
|
+
export type ChildProcessStdinCloseBridgeRef = (sessionId: number) => void;
|
|
274
|
+
export type ChildProcessKillBridgeRef = (sessionId: number, signal: number) => void;
|
|
275
|
+
export type SpawnSyncBridgeResult = {
|
|
276
|
+
stdout: string;
|
|
277
|
+
stderr: string;
|
|
278
|
+
code: number;
|
|
279
|
+
maxBufferExceeded?: boolean;
|
|
280
|
+
};
|
|
281
|
+
export type ChildProcessSpawnSyncBridgeRef = (command: string, argsJson: string, optionsJson: string) => SpawnSyncBridgeResult;
|
|
282
|
+
export type NetworkFetchResult = {
|
|
283
|
+
ok: boolean;
|
|
284
|
+
status: number;
|
|
285
|
+
statusText: string;
|
|
286
|
+
headers?: Record<string, string>;
|
|
287
|
+
url?: string;
|
|
288
|
+
redirected?: boolean;
|
|
289
|
+
body?: string;
|
|
290
|
+
};
|
|
291
|
+
export type NetworkFetchRawBridgeRef = (url: string, optionsJson: string) => Promise<NetworkFetchResult>;
|
|
292
|
+
export type NetworkDnsLookupResult = {
|
|
293
|
+
error?: string;
|
|
294
|
+
code?: string;
|
|
295
|
+
address?: string;
|
|
296
|
+
family?: number;
|
|
297
|
+
};
|
|
298
|
+
export type NetworkDnsLookupRawBridgeRef = (hostname: string) => Promise<NetworkDnsLookupResult>;
|
|
299
|
+
export type NetworkHttpRequestResult = {
|
|
300
|
+
headers?: Record<string, string>;
|
|
301
|
+
url?: string;
|
|
302
|
+
status?: number;
|
|
303
|
+
statusText?: string;
|
|
304
|
+
body?: string;
|
|
305
|
+
trailers?: Record<string, string>;
|
|
306
|
+
};
|
|
307
|
+
export type NetworkHttpRequestRawBridgeRef = (url: string, optionsJson: string) => Promise<NetworkHttpRequestResult>;
|
|
308
|
+
export type NetworkHttpServerListenResult = {
|
|
309
|
+
address: {
|
|
310
|
+
address: string;
|
|
311
|
+
family: string;
|
|
312
|
+
port: number;
|
|
313
|
+
} | null;
|
|
314
|
+
};
|
|
315
|
+
export type NetworkHttpServerListenRawBridgeRef = (optionsJson: string) => Promise<NetworkHttpServerListenResult>;
|
|
316
|
+
export type NetworkHttpServerCloseRawBridgeRef = (serverId: number) => Promise<void>;
|
|
317
|
+
export type PtySetRawModeBridgeRef = (mode: boolean) => void;
|
|
301
318
|
export type RegisterHandleBridgeFn = (id: string, description: string) => void;
|
|
302
319
|
export type UnregisterHandleBridgeFn = (id: string) => void;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* host (Node.js) and the isolate (sandbox V8 context).
|
|
4
4
|
*
|
|
5
5
|
* Two categories:
|
|
6
|
-
* - Host bridge globals: set by the host before bridge code runs (fs
|
|
6
|
+
* - Host bridge globals: set by the host before bridge code runs (fs fns, timers, etc.)
|
|
7
7
|
* - Runtime bridge globals: installed by the bridge bundle itself (active handles, modules, etc.)
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Each type alias is a plain function signature. The Rust V8 runtime registers
|
|
10
|
+
* these as real JS functions on the global; bridge code calls them directly.
|
|
10
11
|
*/
|
|
11
12
|
function valuesOf(object) {
|
|
12
13
|
return Object.values(object);
|
|
@@ -49,6 +50,7 @@ export const HOST_BRIDGE_GLOBAL_KEYS = {
|
|
|
49
50
|
networkHttpRequestRaw: "_networkHttpRequestRaw",
|
|
50
51
|
networkHttpServerListenRaw: "_networkHttpServerListenRaw",
|
|
51
52
|
networkHttpServerCloseRaw: "_networkHttpServerCloseRaw",
|
|
53
|
+
ptySetRawMode: "_ptySetRawMode",
|
|
52
54
|
processConfig: "_processConfig",
|
|
53
55
|
osConfig: "_osConfig",
|
|
54
56
|
log: "_log",
|
|
@@ -148,10 +148,10 @@ export function getConsoleSetupCode(budget = DEFAULT_CONSOLE_SERIALIZATION_BUDGE
|
|
|
148
148
|
const formatConsoleArgs = ${formatConsoleArgs.toString()};
|
|
149
149
|
|
|
150
150
|
globalThis.console = {
|
|
151
|
-
log: (...args) => _log
|
|
152
|
-
error: (...args) => _error
|
|
153
|
-
warn: (...args) => _error
|
|
154
|
-
info: (...args) => _log
|
|
151
|
+
log: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
|
|
152
|
+
error: (...args) => _error(formatConsoleArgs(args, __consoleBudget)),
|
|
153
|
+
warn: (...args) => _error(formatConsoleArgs(args, __consoleBudget)),
|
|
154
|
+
info: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
|
|
155
155
|
};
|
|
156
156
|
`;
|
|
157
157
|
}
|
|
@@ -275,6 +275,11 @@ export const NODE_CUSTOM_GLOBAL_INVENTORY = [
|
|
|
275
275
|
classification: "hardened",
|
|
276
276
|
rationale: "Host network bridge reference.",
|
|
277
277
|
},
|
|
278
|
+
{
|
|
279
|
+
name: "_ptySetRawMode",
|
|
280
|
+
classification: "hardened",
|
|
281
|
+
rationale: "Host PTY bridge reference for stdin.setRawMode().",
|
|
282
|
+
},
|
|
278
283
|
{
|
|
279
284
|
name: "require",
|
|
280
285
|
classification: "hardened",
|