poe-code 14.0.5 → 14.0.6
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/index.js +1176 -242
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-B7H4ZL65.js → chunk-2M6MNQBY.js} +1937 -1008
- package/packages/safe-js/dist/chunks/chunk-2M6MNQBY.js.map +7 -0
- package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js → chunk-QSSQJNKE.js} +2 -2
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.d.ts +3 -0
- package/packages/safe-js/dist/core.js +5 -1
- package/packages/safe-js/dist/extensions.d.ts +42 -0
- package/packages/safe-js/dist/extensions.js +83 -0
- package/packages/safe-js/dist/index.d.ts +4 -1
- package/packages/safe-js/dist/index.js +6 -2
- package/packages/safe-js/dist/index.js.map +2 -2
- package/packages/safe-js/dist/interp/async.d.ts +1 -0
- package/packages/safe-js/dist/interp/globals/object-array.js +5 -0
- package/packages/safe-js/dist/interp/globals.d.ts +31 -0
- package/packages/safe-js/dist/interp/globals.js +22 -0
- package/packages/safe-js/dist/interp/host-bridge.d.ts +14 -1
- package/packages/safe-js/dist/interp/host-bridge.js +19 -4
- package/packages/safe-js/dist/interp/host-capabilities.d.ts +43 -0
- package/packages/safe-js/dist/interp/host-capabilities.js +123 -0
- package/packages/safe-js/dist/interp/interpreter.d.ts +4 -0
- package/packages/safe-js/dist/interp/interpreter.js +22 -4
- package/packages/safe-js/dist/interp/object-model.js +7 -0
- package/packages/safe-js/dist/interp/values.d.ts +1 -0
- package/packages/safe-js/dist/interp/values.js +15 -0
- package/packages/safe-js/dist/modules/registry.d.ts +3 -1
- package/packages/safe-js/dist/modules/registry.js +2 -1
- package/packages/safe-js/dist/realm.d.ts +43 -0
- package/packages/safe-js/dist/realm.js +713 -0
- package/packages/safe-js/dist/run.d.ts +5 -1
- package/packages/safe-js/dist/run.js +6 -35
- package/packages/safe-js/dist/chunks/chunk-B7H4ZL65.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-7B7BKWVF.js.map → chunk-QSSQJNKE.js.map} +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readDataRecord } from "../extensions.js";
|
|
2
|
+
const hostObjects = new WeakMap();
|
|
3
|
+
const guestObjects = new WeakMap();
|
|
4
|
+
const guestCallbacks = new WeakMap();
|
|
5
|
+
export function createLiveHostObject(definition, controller) {
|
|
6
|
+
const input = readDataRecord(definition, "Host object definition");
|
|
7
|
+
if (Object.keys(input).some((key) => key !== "properties" && key !== "methods"))
|
|
8
|
+
throw new TypeError("Unknown host object definition field.");
|
|
9
|
+
const properties = new Map();
|
|
10
|
+
for (const [name, inputProperty] of Object.entries(readDataRecord(input.properties ?? {}, "Host properties"))) {
|
|
11
|
+
const property = readDataRecord(inputProperty, `Host property '${name}'`);
|
|
12
|
+
if (Object.keys(property).some((key) => key !== "get" && key !== "set"))
|
|
13
|
+
throw new TypeError("Unknown host property field.");
|
|
14
|
+
if ((property.get !== undefined && typeof property.get !== "function") ||
|
|
15
|
+
(property.set !== undefined && typeof property.set !== "function"))
|
|
16
|
+
throw new TypeError("Host property operations must be functions.");
|
|
17
|
+
properties.set(name, property);
|
|
18
|
+
}
|
|
19
|
+
const operations = readDataRecord(input.methods ?? {}, "Host methods");
|
|
20
|
+
for (const [name, operation] of Object.entries(operations)) {
|
|
21
|
+
if (typeof operation !== "function")
|
|
22
|
+
throw new TypeError("Host methods must be functions.");
|
|
23
|
+
if (properties.has(name))
|
|
24
|
+
throw new TypeError(`Conflicting host member '${name}'.`);
|
|
25
|
+
}
|
|
26
|
+
for (const name of [...properties.keys(), ...Object.keys(operations)]) {
|
|
27
|
+
if (["constructor", "prototype", "__proto__"].includes(name))
|
|
28
|
+
throw new TypeError(`Reserved host member '${name}'.`);
|
|
29
|
+
}
|
|
30
|
+
controller.assertActive();
|
|
31
|
+
controller.chargeWork(properties.size + Object.keys(operations).length + 1);
|
|
32
|
+
const host = Object.freeze(Object.create(null));
|
|
33
|
+
const guest = Object.freeze(Object.create(null));
|
|
34
|
+
const methods = new Map(Object.entries(operations).map(([name, operation]) => [
|
|
35
|
+
name,
|
|
36
|
+
controller.method(operation)
|
|
37
|
+
]));
|
|
38
|
+
const state = { host, guest, controller, properties, methods };
|
|
39
|
+
hostObjects.set(host, state);
|
|
40
|
+
guestObjects.set(guest, state);
|
|
41
|
+
return host;
|
|
42
|
+
}
|
|
43
|
+
export function isGuestHostObject(value) {
|
|
44
|
+
return typeof value === "object" && value !== null && guestObjects.has(value);
|
|
45
|
+
}
|
|
46
|
+
export function isLiveCapability(value) {
|
|
47
|
+
return (((typeof value === "object" && value !== null) || typeof value === "function") &&
|
|
48
|
+
(hostObjects.has(value) || guestObjects.has(value) || guestCallbacks.has(value)));
|
|
49
|
+
}
|
|
50
|
+
export function importHostCapability(value, owner) {
|
|
51
|
+
const object = hostObjects.get(value);
|
|
52
|
+
if (object !== undefined) {
|
|
53
|
+
if (object.controller.owner !== owner)
|
|
54
|
+
throw new TypeError("Foreign realm host capability.");
|
|
55
|
+
object.controller.assertActive();
|
|
56
|
+
return object.guest;
|
|
57
|
+
}
|
|
58
|
+
const callback = guestCallbacks.get(value);
|
|
59
|
+
if (callback !== undefined) {
|
|
60
|
+
if (callback.owner !== owner)
|
|
61
|
+
throw new TypeError("Foreign realm guest callback.");
|
|
62
|
+
callback.assertActive();
|
|
63
|
+
if (callback.closure === undefined)
|
|
64
|
+
throw new TypeError("Guest callback is revoked.");
|
|
65
|
+
return callback.closure;
|
|
66
|
+
}
|
|
67
|
+
throw new TypeError("Unsupported live capability conversion.");
|
|
68
|
+
}
|
|
69
|
+
export function exportHostCapability(value, owner) {
|
|
70
|
+
const state = guestObjects.get(value);
|
|
71
|
+
if (state === undefined || state.controller.owner !== owner)
|
|
72
|
+
throw new TypeError("Foreign realm host capability.");
|
|
73
|
+
state.controller.assertActive();
|
|
74
|
+
return state.host;
|
|
75
|
+
}
|
|
76
|
+
export function registerGuestCallback(callback, state) {
|
|
77
|
+
guestCallbacks.set(callback, state);
|
|
78
|
+
}
|
|
79
|
+
export function readGuestCallback(callback, owner) {
|
|
80
|
+
const state = typeof callback === "function" ? guestCallbacks.get(callback) : undefined;
|
|
81
|
+
if (state === undefined || state.owner !== owner)
|
|
82
|
+
throw new TypeError("Foreign or invalid guest callback.");
|
|
83
|
+
state.assertActive();
|
|
84
|
+
if (state.closure === undefined)
|
|
85
|
+
throw new TypeError("Guest callback is revoked.");
|
|
86
|
+
return state.closure;
|
|
87
|
+
}
|
|
88
|
+
export function revokeGuestCallback(callback, owner) {
|
|
89
|
+
const state = guestCallbacks.get(callback);
|
|
90
|
+
if (state === undefined || state.owner !== owner)
|
|
91
|
+
throw new TypeError("Foreign guest callback.");
|
|
92
|
+
state.closure = undefined;
|
|
93
|
+
}
|
|
94
|
+
export function revokeHostObject(value, owner) {
|
|
95
|
+
const state = hostObjects.get(value);
|
|
96
|
+
if (state === undefined || state.controller.owner !== owner)
|
|
97
|
+
throw new TypeError("Foreign host object.");
|
|
98
|
+
state.properties.clear();
|
|
99
|
+
state.methods.clear();
|
|
100
|
+
}
|
|
101
|
+
export function getHostObjectMember(value, key) {
|
|
102
|
+
const state = guestObjects.get(value);
|
|
103
|
+
state.controller.assertActive();
|
|
104
|
+
state.controller.chargeWork();
|
|
105
|
+
const property = state.properties.get(key);
|
|
106
|
+
if (property !== undefined)
|
|
107
|
+
return property.get === undefined ? undefined : state.controller.read(property.get);
|
|
108
|
+
return state.methods.get(key);
|
|
109
|
+
}
|
|
110
|
+
export function setHostObjectMember(value, key, entry) {
|
|
111
|
+
const state = guestObjects.get(value);
|
|
112
|
+
state.controller.assertActive();
|
|
113
|
+
state.controller.chargeWork();
|
|
114
|
+
const property = state.properties.get(key);
|
|
115
|
+
if (property?.set === undefined)
|
|
116
|
+
throw new TypeError(`Host property '${key}' is not writable.`);
|
|
117
|
+
state.controller.write(property.set, entry);
|
|
118
|
+
}
|
|
119
|
+
export function getHostObjectKeys(value) {
|
|
120
|
+
const state = guestObjects.get(value);
|
|
121
|
+
state.controller.assertActive();
|
|
122
|
+
return [...state.properties.keys(), ...state.methods.keys()];
|
|
123
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SandboxJobQueue } from "./jobs.js";
|
|
1
2
|
import type { ParseResult, SourceSpan } from "../parse.js";
|
|
2
3
|
import { type AsyncEvaluationContext, type AsyncEvaluationResult, type InterpreterYieldPoint } from "./async.js";
|
|
3
4
|
import type { GeneratorCompletion } from "./generator.js";
|
|
@@ -43,6 +44,9 @@ export type InterpreterResult = {
|
|
|
43
44
|
stats: InterpreterStats;
|
|
44
45
|
};
|
|
45
46
|
export type InterpretOptions = {
|
|
47
|
+
assertActive?: () => void;
|
|
48
|
+
jobs?: SandboxJobQueue;
|
|
49
|
+
nested?: boolean;
|
|
46
50
|
compilation?: CompileScope;
|
|
47
51
|
compileOwner?: CompileOwner;
|
|
48
52
|
captureReplayState?: () => unknown;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promiseReplayContext } from "./promise-replay.js";
|
|
2
|
+
import { getHostObjectKeys, getHostObjectMember, isGuestHostObject, setHostObjectMember } from "./host-capabilities.js";
|
|
2
3
|
import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
|
|
3
|
-
import { SandboxJobQueue, suspendJob } from "./jobs.js";
|
|
4
|
+
import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
|
|
4
5
|
import { withCancellationSignal } from "./cancel.js";
|
|
5
6
|
import { attachErrorSpan, formatErrorStack, readErrorSpan, replaceErrorStack } from "../error/shape.js";
|
|
6
7
|
import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
|
|
@@ -98,9 +99,10 @@ export async function interpret(node, options = {}) {
|
|
|
98
99
|
peakDataSize: { enumerable: false, value: 0, writable: true }
|
|
99
100
|
});
|
|
100
101
|
const activeLoopIterations = new Map();
|
|
101
|
-
const jobs = new SandboxJobQueue();
|
|
102
|
+
const jobs = options.jobs ?? new SandboxJobQueue();
|
|
102
103
|
hoistVarDeclarations(node, scope);
|
|
103
104
|
const context = {
|
|
105
|
+
assertActive: options.assertActive,
|
|
104
106
|
compilation,
|
|
105
107
|
budget,
|
|
106
108
|
callStack: [],
|
|
@@ -119,8 +121,9 @@ export async function interpret(node, options = {}) {
|
|
|
119
121
|
generatorYield: options.generatorYield,
|
|
120
122
|
resumeTarget: { nodeId: options.snapshot?.resumeNodeId }
|
|
121
123
|
};
|
|
122
|
-
const evaluation = await withCancellationSignal(options.signal, () => jobs.run(() => evaluateNode(node, context)));
|
|
123
|
-
|
|
124
|
+
const evaluation = await withCancellationSignal(options.signal, () => options.nested ? runAsyncPrefix(() => evaluateNode(node, context)) : jobs.run(() => evaluateNode(node, context)));
|
|
125
|
+
if (!options.nested)
|
|
126
|
+
await jobs.drain();
|
|
124
127
|
const snapshot = scope.snapshot();
|
|
125
128
|
reconcileDataBudget(budget, stats, scope, "hasValue" in evaluation && evaluation.hasValue ? evaluation.value : undefined, compilation, options.compilation);
|
|
126
129
|
if (evaluation.kind === "error") {
|
|
@@ -167,6 +170,7 @@ export async function interpret(node, options = {}) {
|
|
|
167
170
|
}
|
|
168
171
|
export { Scope } from "./scope.js";
|
|
169
172
|
async function evaluateNode(node, context) {
|
|
173
|
+
context.assertActive?.();
|
|
170
174
|
const replayWait = promiseReplayContext.getStore()?.beforeNode(node.nodeId);
|
|
171
175
|
if (replayWait !== undefined)
|
|
172
176
|
await suspendJob(replayWait);
|
|
@@ -1119,6 +1123,8 @@ function forInObject(value) {
|
|
|
1119
1123
|
return undefined;
|
|
1120
1124
|
}
|
|
1121
1125
|
function forInKeys(object, budget) {
|
|
1126
|
+
if (isGuestHostObject(object))
|
|
1127
|
+
return getHostObjectKeys(object);
|
|
1122
1128
|
const keys = [];
|
|
1123
1129
|
const seen = new Set();
|
|
1124
1130
|
let depth = 0;
|
|
@@ -1140,6 +1146,8 @@ function forInKeys(object, budget) {
|
|
|
1140
1146
|
return keys;
|
|
1141
1147
|
}
|
|
1142
1148
|
function hasForInProperty(object, key, budget) {
|
|
1149
|
+
if (isGuestHostObject(object))
|
|
1150
|
+
return getHostObjectKeys(object).includes(key);
|
|
1143
1151
|
let depth = 0;
|
|
1144
1152
|
for (let current = object; current !== null; current = getSandboxPrototype(current)) {
|
|
1145
1153
|
if (depth > 0)
|
|
@@ -1630,6 +1638,8 @@ async function evaluateMemberExpression(node, context) {
|
|
|
1630
1638
|
};
|
|
1631
1639
|
}
|
|
1632
1640
|
function getPropertyValue(target, property, context) {
|
|
1641
|
+
if (isGuestHostObject(target))
|
|
1642
|
+
return getHostObjectMember(target, String(property));
|
|
1633
1643
|
if (typeof target === "string")
|
|
1634
1644
|
return getStringMember(target, property, context.budget);
|
|
1635
1645
|
if (typeof target === "number")
|
|
@@ -2284,6 +2294,8 @@ function isPlainSandboxObject(value) {
|
|
|
2284
2294
|
!isSandboxRegex(value));
|
|
2285
2295
|
}
|
|
2286
2296
|
function getMemberValue(target, property, context) {
|
|
2297
|
+
if (isGuestHostObject(target))
|
|
2298
|
+
return getHostObjectMember(target, String(property));
|
|
2287
2299
|
let current = target;
|
|
2288
2300
|
let depth = 0;
|
|
2289
2301
|
while (typeof current === "object" && current !== null) {
|
|
@@ -2311,6 +2323,10 @@ function getArrayMemberValue(target, property, context) {
|
|
|
2311
2323
|
return getArrayMember(target, property, createArrayMethodOptions(context));
|
|
2312
2324
|
}
|
|
2313
2325
|
export function setSandboxProperty(target, property, value, budget) {
|
|
2326
|
+
if (isGuestHostObject(target)) {
|
|
2327
|
+
setHostObjectMember(target, String(property), value);
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2314
2330
|
const prototypeOwner = target;
|
|
2315
2331
|
if (isGuestClosure(target))
|
|
2316
2332
|
target = materializeFunctionProperties(target);
|
|
@@ -2359,6 +2375,8 @@ export function setSandboxProperty(target, property, value, budget) {
|
|
|
2359
2375
|
}
|
|
2360
2376
|
}
|
|
2361
2377
|
function deleteSandboxProperty(target, property) {
|
|
2378
|
+
if (isGuestHostObject(target))
|
|
2379
|
+
throw new TypeError("Live host properties cannot be deleted.");
|
|
2362
2380
|
if (isGuestClosure(target))
|
|
2363
2381
|
target = materializeFunctionProperties(target);
|
|
2364
2382
|
if (Array.isArray(target)) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
2
|
+
import { getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
|
|
2
3
|
import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "./values.js";
|
|
3
4
|
const guestClosures = new WeakSet();
|
|
4
5
|
const functionProperties = new WeakMap();
|
|
@@ -62,6 +63,8 @@ export function getSandboxDataProperty(value, key, budget) {
|
|
|
62
63
|
let current = value;
|
|
63
64
|
let depth = 0;
|
|
64
65
|
while (typeof current === "object" && current !== null) {
|
|
66
|
+
if (isGuestHostObject(current))
|
|
67
|
+
return getHostObjectMember(current, String(key));
|
|
65
68
|
if (isGuestClosure(current))
|
|
66
69
|
return getGuestFunctionProperty(current, String(key));
|
|
67
70
|
if (isSandboxClosure(current)) {
|
|
@@ -108,6 +111,8 @@ export function setSandboxPrototype(value, prototype, budget) {
|
|
|
108
111
|
prototypes.set(value, prototype);
|
|
109
112
|
}
|
|
110
113
|
function isPrototypeRecord(value) {
|
|
114
|
+
if (isGuestHostObject(value))
|
|
115
|
+
return false;
|
|
111
116
|
if (isSandboxClosure(value) ||
|
|
112
117
|
isSandboxGenerator(value) ||
|
|
113
118
|
isSandboxMap(value) ||
|
|
@@ -125,6 +130,8 @@ export function hasManagedDescriptors(value) {
|
|
|
125
130
|
return descriptorObjects.has(value);
|
|
126
131
|
}
|
|
127
132
|
export function hasGuestObjectState(value) {
|
|
133
|
+
if (isLiveCapability(value))
|
|
134
|
+
return true;
|
|
128
135
|
if (functionProperties.has(value) || prototypes.has(value))
|
|
129
136
|
return true;
|
|
130
137
|
return (descriptorObjects.has(value) &&
|
|
@@ -86,6 +86,7 @@ export type SandboxGenerator = {
|
|
|
86
86
|
};
|
|
87
87
|
type CopyFromSandboxOptions = {
|
|
88
88
|
wrapClosure?: (value: SandboxClosure) => unknown;
|
|
89
|
+
unwrapHostObject?: (value: SandboxObject) => unknown;
|
|
89
90
|
compilation?: CompileScope;
|
|
90
91
|
};
|
|
91
92
|
export declare function createSandboxClosure(input: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
|
|
2
|
+
import { getHostObjectKeys, getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
|
|
2
3
|
import { types as nodeTypes } from "node:util";
|
|
3
4
|
import { CompileScope, RegexCompileGuard, regexCompiledData } from "./regex/compile-guard.js";
|
|
4
5
|
import { copyFloat32Storage, float32DataProperties, float32Storage, isFloat32Array } from "./float32.js";
|
|
@@ -70,6 +71,8 @@ export function createSandboxClosure(input) {
|
|
|
70
71
|
return Object.freeze(closure);
|
|
71
72
|
}
|
|
72
73
|
export function ownEnumerableSandboxEntries(value) {
|
|
74
|
+
if (isGuestHostObject(value))
|
|
75
|
+
return getHostObjectKeys(value).map(key => [key, getHostObjectMember(value, key)]);
|
|
73
76
|
if (value === null || value === undefined)
|
|
74
77
|
throw new TypeError("Cannot convert undefined or null to object.");
|
|
75
78
|
if (isGuestClosure(value))
|
|
@@ -222,6 +225,11 @@ export function measureSandboxData(values, options = {}) {
|
|
|
222
225
|
assertSandboxDataDepth(depth);
|
|
223
226
|
seen.add(value);
|
|
224
227
|
usage += 1;
|
|
228
|
+
if (isGuestHostObject(value)) {
|
|
229
|
+
for (const key of getHostObjectKeys(value))
|
|
230
|
+
usage += key.length + 1;
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
225
233
|
const prototype = getSandboxPrototype(value);
|
|
226
234
|
if (prototype !== null)
|
|
227
235
|
visit(prototype, depth + 1);
|
|
@@ -376,6 +384,8 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
376
384
|
if (isSandboxPrimitive(value)) {
|
|
377
385
|
return value;
|
|
378
386
|
}
|
|
387
|
+
if (isLiveCapability(value))
|
|
388
|
+
throw new TypeError("Live capabilities require their owning realm bridge.");
|
|
379
389
|
if (isSandboxClosure(value) ||
|
|
380
390
|
isSandboxGenerator(value) ||
|
|
381
391
|
isSandboxRegex(value) ||
|
|
@@ -508,6 +518,11 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
508
518
|
if (isSandboxPrimitive(value)) {
|
|
509
519
|
return value;
|
|
510
520
|
}
|
|
521
|
+
if (isGuestHostObject(value)) {
|
|
522
|
+
if (options.unwrapHostObject === undefined)
|
|
523
|
+
throw new TypeError("Live capabilities require their owning realm bridge.");
|
|
524
|
+
return options.unwrapHostObject(value);
|
|
525
|
+
}
|
|
511
526
|
if (nodeTypes.isProxy(value))
|
|
512
527
|
throw new TypeError("Unsupported proxy sandbox value.");
|
|
513
528
|
if (!isSandboxClosure(value) && hasGuestObjectState(value)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Budget, CompileOwner } from "../interp/budget.js";
|
|
2
2
|
import type { HostCallJournal } from "../interp/host-call.js";
|
|
3
|
-
import { type CallerInjectedBinding } from "../interp/host-bridge.js";
|
|
3
|
+
import { type RealmBridge, type CallerInjectedBinding } from "../interp/host-bridge.js";
|
|
4
4
|
import type { SandboxValue } from "../interp/values.js";
|
|
5
5
|
import type { Module } from "../parse/parser.js";
|
|
6
6
|
export type ModuleExports = ReadonlyMap<string, CallerInjectedBinding> | Record<string, CallerInjectedBinding>;
|
|
@@ -9,6 +9,8 @@ export declare function createUnknownModuleMessage(moduleName: string, moduleNam
|
|
|
9
9
|
export declare function createUnknownExportMessage(moduleName: string, exportName: string, availableExports: readonly string[]): string;
|
|
10
10
|
export declare function resolveModuleImports(module: Module, modules: ModuleRegistry | undefined, options: {
|
|
11
11
|
budget: Budget;
|
|
12
|
+
realm?: RealmBridge;
|
|
13
|
+
wrappedModules?: Map<string, Record<string, SandboxValue>>;
|
|
12
14
|
compileOwner?: CompileOwner;
|
|
13
15
|
hostCalls?: HostCallJournal;
|
|
14
16
|
signal?: AbortSignal;
|
|
@@ -17,7 +17,7 @@ export function createUnknownExportMessage(moduleName, exportName, availableExpo
|
|
|
17
17
|
export function resolveModuleImports(module, modules, options) {
|
|
18
18
|
const registry = normalizeModuleRegistry(modules);
|
|
19
19
|
const bindings = createBindingRecord();
|
|
20
|
-
const wrappedModules = new Map();
|
|
20
|
+
const wrappedModules = options.wrappedModules ?? new Map();
|
|
21
21
|
for (const statement of module.body) {
|
|
22
22
|
if (statement.type !== "ImportDeclaration") {
|
|
23
23
|
continue;
|
|
@@ -36,6 +36,7 @@ function bindImportDeclaration(declaration, registry, wrappedModules, bindings,
|
|
|
36
36
|
}
|
|
37
37
|
const wrappedExports = wrappedModules.get(moduleName) ??
|
|
38
38
|
createBindingRecord(wrapCancelableBindings(wrapCallerInjectedBindings(Object.fromEntries(moduleExports), {
|
|
39
|
+
realm: options.realm,
|
|
39
40
|
budget: options.budget,
|
|
40
41
|
compileOwner: options.compileOwner,
|
|
41
42
|
hostCalls: options.hostCalls,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Budget } from "./interp/budget.js";
|
|
2
|
+
import { type InterpreterResult } from "./interp/interpreter.js";
|
|
3
|
+
import { type CallerInjectedBinding } from "./interp/host-bridge.js";
|
|
4
|
+
import { type CallbackOptions, type SafeJSExtension } from "./extensions.js";
|
|
5
|
+
import { type ModuleRegistry } from "./modules/registry.js";
|
|
6
|
+
import type { ConsoleSink } from "./interp/globals/console-json.js";
|
|
7
|
+
import type { RunOptions, RunResult } from "./run.js";
|
|
8
|
+
export type RealmLimits = {
|
|
9
|
+
extensions?: number;
|
|
10
|
+
hostObjects?: number;
|
|
11
|
+
callbacks?: number;
|
|
12
|
+
cleanups?: number;
|
|
13
|
+
nestedEvaluations?: number;
|
|
14
|
+
};
|
|
15
|
+
export type RealmOptions = {
|
|
16
|
+
bindings?: Record<string, CallerInjectedBinding>;
|
|
17
|
+
modules?: ModuleRegistry;
|
|
18
|
+
extensions?: readonly SafeJSExtension[];
|
|
19
|
+
grants?: readonly string[];
|
|
20
|
+
budget?: Budget;
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
sink?: ConsoleSink;
|
|
23
|
+
randomSeed?: number;
|
|
24
|
+
limits?: RealmLimits;
|
|
25
|
+
};
|
|
26
|
+
export type RealmResult = (Omit<Extract<InterpreterResult, {
|
|
27
|
+
ok: true;
|
|
28
|
+
}>, "snapshot" | "returnValue"> & {
|
|
29
|
+
returnValue?: unknown;
|
|
30
|
+
}) | Omit<Extract<InterpreterResult, {
|
|
31
|
+
ok: false;
|
|
32
|
+
}>, "snapshot">;
|
|
33
|
+
export type SafeJSRealm = {
|
|
34
|
+
readonly extensions: readonly SafeJSExtension["manifest"][];
|
|
35
|
+
evaluate(source: string, options?: {
|
|
36
|
+
filename?: string;
|
|
37
|
+
}): Promise<RealmResult>;
|
|
38
|
+
invokeCallback(callback: unknown, options?: CallbackOptions): Promise<unknown>;
|
|
39
|
+
releaseCallback(callback: unknown): void;
|
|
40
|
+
close(): Promise<void>;
|
|
41
|
+
};
|
|
42
|
+
export declare function createRealm(options?: RealmOptions): SafeJSRealm;
|
|
43
|
+
export declare function runWithExtensions(source: string, options: RunOptions): Promise<RunResult>;
|