poe-code 5.0.4 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/index.js +3181 -2636
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safejs/dist/interp/async.js +31 -9
  6. package/packages/safejs/dist/interp/cancel.d.ts +7 -2
  7. package/packages/safejs/dist/interp/cancel.js +128 -92
  8. package/packages/safejs/dist/interp/exceptions.js +7 -3
  9. package/packages/safejs/dist/interp/globals/collections.js +2 -0
  10. package/packages/safejs/dist/interp/globals/console-json.js +4 -0
  11. package/packages/safejs/dist/interp/globals/error.js +1 -5
  12. package/packages/safejs/dist/interp/globals/math.js +2 -4
  13. package/packages/safejs/dist/interp/globals/misc.js +5 -0
  14. package/packages/safejs/dist/interp/globals/object-array.js +25 -0
  15. package/packages/safejs/dist/interp/globals/regex.js +1 -1
  16. package/packages/safejs/dist/interp/host-bridge.js +8 -5
  17. package/packages/safejs/dist/interp/interpreter.js +26 -32
  18. package/packages/safejs/dist/interp/iteration.d.ts +3 -3
  19. package/packages/safejs/dist/interp/iteration.js +20 -9
  20. package/packages/safejs/dist/interp/methods/array.js +1 -0
  21. package/packages/safejs/dist/interp/methods/function.d.ts +1 -1
  22. package/packages/safejs/dist/interp/methods/function.js +17 -1
  23. package/packages/safejs/dist/interp/methods/generator.js +1 -0
  24. package/packages/safejs/dist/interp/methods/map.js +1 -0
  25. package/packages/safejs/dist/interp/methods/number.js +1 -0
  26. package/packages/safejs/dist/interp/methods/regex.js +1 -0
  27. package/packages/safejs/dist/interp/methods/set.js +1 -0
  28. package/packages/safejs/dist/interp/methods/string.js +1 -0
  29. package/packages/safejs/dist/interp/promise-tracker.d.ts +12 -2
  30. package/packages/safejs/dist/interp/promise-tracker.js +65 -7
  31. package/packages/safejs/dist/interp/promise.d.ts +7 -5
  32. package/packages/safejs/dist/interp/promise.js +531 -148
  33. package/packages/safejs/dist/interp/values.d.ts +6 -0
  34. package/packages/safejs/dist/interp/values.js +25 -5
  35. package/packages/safejs/dist/lint/rules/AS001.js +0 -5
  36. package/packages/safejs/dist/snapshot/dump-format.d.ts +1 -1
  37. package/packages/safejs/dist/snapshot/dump-format.js +1 -1
  38. package/packages/safejs/dist/snapshot/replay-data.js +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-code",
3
- "version": "5.0.4",
3
+ "version": "6.0.0",
4
4
  "description": "CLI tool to configure Poe API for developer workflows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -5,7 +5,7 @@ import { getThenable, resolveSandboxValue } from "./promise.js";
5
5
  import { runAsyncPrefix, suspendJob } from "./jobs.js";
6
6
  import { awaitSandboxValue } from "./cancel.js";
7
7
  import { hoistVarDeclarations } from "./var-hoist.js";
8
- import { createSandboxArguments, createSandboxClosure, createSandboxGenerator, createSandboxPromise, isSandboxPromise } from "./values.js";
8
+ import { createSandboxArguments, createSandboxClosure, createSandboxGenerator, createSandboxPromise, allocateProducedSandboxValue, isSandboxPromise } from "./values.js";
9
9
  export function emitResumeBreakpoint(context, breakpoint) {
10
10
  context.onYield?.({
11
11
  ...breakpoint,
@@ -53,6 +53,7 @@ export function createInterpretedClosure(node, context, evaluateNode) {
53
53
  }
54
54
  : undefined;
55
55
  return createSandboxClosure({
56
+ sandbox: true,
56
57
  ...(node.async ? { async: true } : {}),
57
58
  ...(node.type === "FunctionDeclaration" || node.type === "FunctionExpression"
58
59
  ? node.id === undefined
@@ -72,16 +73,34 @@ export function createInterpretedClosure(node, context, evaluateNode) {
72
73
  const synchronousPrefix = new Promise((resolve) => {
73
74
  completePrefix = resolve;
74
75
  });
75
- const execution = runAsyncPrefix(() => executeClosure(node, args, callContext?.thisValue, { ...invocationContext, onSuspend: completePrefix }, evaluateNode));
76
- execution.then(completePrefix, completePrefix);
77
- return createSandboxPromise(resolveSandboxValue(execution.then((value) => isSandboxPromise(value) || getThenable(value) !== undefined
78
- ? awaitSandboxValue(value, context.signal)
79
- : value), { budget: context.budget }), { synchronousPrefix });
76
+ const promise = new Promise((resolve, reject) => {
77
+ runAsyncPrefix(async () => {
78
+ try {
79
+ const value = await executeClosure(node, args, callContext?.thisValue, { ...invocationContext, onSuspend: completePrefix }, evaluateNode);
80
+ resolve(isSandboxPromise(value) || getThenable(value) !== undefined
81
+ ? awaitSandboxValue(createSandboxPromise(resolveSandboxValue(value, { budget: context.budget }), {
82
+ trackReplay: false
83
+ }), context.signal, context.budget)
84
+ : allocateProducedSandboxValue(value, context.budget));
85
+ }
86
+ catch (error) {
87
+ reject(error);
88
+ }
89
+ finally {
90
+ completePrefix();
91
+ }
92
+ }).catch((error) => {
93
+ reject(error);
94
+ completePrefix();
95
+ });
96
+ });
97
+ return createSandboxPromise(promise, { synchronousPrefix });
80
98
  }
81
99
  });
82
100
  }
83
101
  function createGeneratorClosure(node, context, evaluateNode) {
84
102
  return createSandboxClosure({
103
+ sandbox: true,
85
104
  ...(node.id === undefined ? {} : { name: node.id.name }),
86
105
  retainedValues: () => context.scope.retainedValues(),
87
106
  call: async (args, callContext) => {
@@ -136,7 +155,7 @@ export async function evaluateAwaitExpression(node, context, evaluateNode) {
136
155
  return {
137
156
  kind: "normal",
138
157
  hasValue: true,
139
- value: await suspendJob(awaitSandboxValue(argument.value, context.signal))
158
+ value: await suspendJob(awaitSandboxValue(argument.value, context.signal, context.budget))
140
159
  };
141
160
  }
142
161
  finally {
@@ -230,8 +249,11 @@ function getParameterBindingNames(pattern) {
230
249
  }
231
250
  }
232
251
  export function normalizeClosureResult(result, budget) {
233
- if (isSandboxPromise(result)) {
252
+ if (isSandboxPromise(result) &&
253
+ (result.synchronousPrefix !== undefined || result.hostCall !== undefined)) {
234
254
  return result;
235
255
  }
236
- return createSandboxPromise(resolveSandboxValue(result, { budget }));
256
+ return createSandboxPromise(resolveSandboxValue(result, { budget }), {
257
+ ...(isSandboxPromise(result) ? { synchronousPrefix: Promise.resolve() } : {})
258
+ });
237
259
  }
@@ -1,3 +1,8 @@
1
- import { type SandboxValue } from "./values.js";
1
+ import { type SandboxCallContext, type SandboxClosure, type SandboxPromise, type SandboxValue } from "./values.js";
2
+ import type { Budget } from "./budget.js";
3
+ export declare function withCancellationSignal<T>(signal: AbortSignal | undefined, task: () => T): T;
4
+ export declare function invokeCancelableClosure(closure: SandboxClosure, operation: SandboxClosure["call"], args: readonly SandboxValue[], context?: SandboxCallContext, construct?: boolean): SandboxValue | Promise<SandboxValue>;
2
5
  export declare function wrapCancelableBindings(bindings: Record<string, SandboxValue>, signal?: AbortSignal): Record<string, SandboxValue>;
3
- export declare function awaitSandboxValue(value: SandboxValue, signal?: AbortSignal): Promise<SandboxValue>;
6
+ export declare function registerPromiseCancellation(promise: SandboxPromise): void;
7
+ export declare function readPromiseCancellation(promise: SandboxPromise, original: Promise<SandboxValue>): Promise<SandboxValue>;
8
+ export declare function awaitSandboxValue(value: SandboxValue, signal?: AbortSignal, budget?: Budget): Promise<SandboxValue>;
@@ -1,90 +1,139 @@
1
- import { createSandboxClosure, createSandboxPromise, isSandboxClosure, isSandboxPromise } from "./values.js";
2
- import { observeSandboxPromise } from "./promise-tracker.js";
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { createSandboxPromise, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet } from "./values.js";
3
+ import { assertPromiseExecutionAllowed, interruptOnFatalPromiseRejection, onFatalPromiseRejection, observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
3
4
  import { replaceErrorStack } from "../error/shape.js";
4
- import { resolveSandboxValue } from "./promise.js";
5
- const cancellationSignals = new WeakMap();
6
- export function wrapCancelableBindings(bindings, signal) {
7
- if (signal === undefined) {
8
- return bindings;
9
- }
10
- return wrapCancelableValue(bindings, signal, new WeakMap());
5
+ import { consumeSettledHostCall, resolveSandboxValue } from "./promise.js";
6
+ const activeCancellation = new AsyncLocalStorage();
7
+ const sandboxPromises = new WeakSet();
8
+ const cancelableOutcomes = new WeakMap();
9
+ export function withCancellationSignal(signal, task) {
10
+ return activeCancellation.run({ signal, host: false }, task);
11
11
  }
12
- function wrapCancelableValue(value, signal, seen) {
13
- if (typeof value !== "object" || value === null) {
14
- return value;
12
+ export function invokeCancelableClosure(closure, operation, args, context, construct = false) {
13
+ assertPromiseExecutionAllowed();
14
+ const active = activeCancellation.getStore();
15
+ if (active === undefined)
16
+ return operation(args, context);
17
+ if (closure.sandbox === true) {
18
+ return activeCancellation.run({ signal: active.signal, host: false }, () => operation(args, context));
15
19
  }
16
- const existing = seen.get(value);
17
- if (existing !== undefined) {
18
- return existing;
20
+ const signal = active.signal;
21
+ const managed = signal !== undefined && closure.cancellationSignal === signal;
22
+ if (signal?.aborted && !managed) {
23
+ if (!construct && closure.async === true)
24
+ return createRejectedSandboxPromise(readAbortReason(signal));
25
+ throw readAbortReason(signal);
19
26
  }
20
- if (isSandboxClosure(value)) {
21
- const wrapped = createSandboxClosure({
22
- ...(value.async === true ? { async: true } : {}),
23
- call: (args, context) => {
24
- if (signal.aborted) {
25
- if (value.async === true) {
26
- return createRejectedSandboxPromise(readAbortReason(signal));
27
- }
28
- throw readAbortReason(signal);
29
- }
30
- return wrapCancelableResult(value.call(args, context), signal, seen);
31
- },
32
- name: value.name
33
- });
34
- seen.set(value, wrapped);
35
- return wrapped;
27
+ return activeCancellation.run({ signal, host: true }, () => {
28
+ const result = operation(args, context);
29
+ if (signal === undefined || managed)
30
+ return result;
31
+ if (isPromiseLike(result))
32
+ return awaitWithSignal(result, signal).then((value) => {
33
+ registerCancelablePromises(value, signal);
34
+ return value;
35
+ });
36
+ registerCancelablePromises(result, signal);
37
+ return result;
38
+ });
39
+ }
40
+ export function wrapCancelableBindings(bindings, signal) {
41
+ if (signal !== undefined)
42
+ registerCancelablePromises(bindings, signal);
43
+ return bindings;
44
+ }
45
+ export function registerPromiseCancellation(promise) {
46
+ const active = activeCancellation.getStore();
47
+ if (active?.host === false)
48
+ sandboxPromises.add(promise);
49
+ else if (active?.signal !== undefined)
50
+ managePromiseCancellation(promise, active.signal);
51
+ }
52
+ export function readPromiseCancellation(promise, original) {
53
+ const signal = activeCancellation.getStore()?.signal;
54
+ return signal === undefined
55
+ ? original
56
+ : (cancelableOutcomes.get(promise)?.get(signal) ?? original);
57
+ }
58
+ function managePromiseCancellation(promise, signal) {
59
+ let outcomes = cancelableOutcomes.get(promise);
60
+ if (outcomes?.has(signal))
61
+ return;
62
+ if (outcomes === undefined) {
63
+ outcomes = new WeakMap();
64
+ cancelableOutcomes.set(promise, outcomes);
65
+ }
66
+ const outcome = awaitWithSignal(promise.promise, signal);
67
+ outcomes.set(signal, outcome);
68
+ trackSandboxPromise(promise, outcome);
69
+ }
70
+ function registerCancelablePromises(value, signal) {
71
+ const seen = new WeakSet();
72
+ const pending = [value];
73
+ while (pending.length > 0) {
74
+ const current = pending.pop();
75
+ if (typeof current !== "object" || current === null || seen.has(current))
76
+ continue;
77
+ seen.add(current);
78
+ if (isSandboxPromise(current)) {
79
+ if (!sandboxPromises.has(current))
80
+ managePromiseCancellation(current, signal);
81
+ continue;
82
+ }
83
+ if (isSandboxClosure(current)) {
84
+ if (current.properties !== undefined)
85
+ pending.push(current.properties);
86
+ }
87
+ else if (isSandboxMap(current)) {
88
+ for (const [key, entry] of current.entries)
89
+ pending.push(key, entry);
90
+ }
91
+ else if (isSandboxSet(current)) {
92
+ for (const entry of current.values)
93
+ pending.push(entry);
94
+ }
95
+ else {
96
+ for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(current))) {
97
+ if ("value" in descriptor)
98
+ pending.push(descriptor.value);
99
+ }
100
+ }
36
101
  }
102
+ }
103
+ export function awaitSandboxValue(value, signal, budget) {
104
+ let resolved;
37
105
  if (isSandboxPromise(value)) {
38
- // The wrapper delivers this promise's rejection to the sandbox in its place, so
39
- // the sandbox never awaits the original and it would otherwise read as unhandled.
40
106
  observeSandboxPromise(value);
41
- const wrapped = createSandboxPromise(wrapCancelablePromise(value.promise, signal, seen), {
42
- trackReplay: false,
43
- ...(value.synchronousPrefix === undefined
44
- ? {}
45
- : { synchronousPrefix: value.synchronousPrefix }),
46
- ...(value.hostCall === undefined ? {} : { hostCall: value.hostCall }),
47
- ...(value.hostCallJournal === undefined ? {} : { hostCallJournal: value.hostCallJournal }),
48
- ...(value.span === undefined ? {} : { span: value.span })
107
+ const outcome = signal === undefined
108
+ ? value.promise
109
+ : (cancelableOutcomes.get(value)?.get(signal) ?? value.promise);
110
+ resolved = new Promise((resolve, reject) => {
111
+ const detach = onFatalPromiseRejection(reject);
112
+ const complete = (state, result) => {
113
+ detach?.();
114
+ try {
115
+ consumeSettledHostCall(value);
116
+ if (state === "fulfilled")
117
+ resolve(result);
118
+ else
119
+ reject(result);
120
+ }
121
+ catch (error) {
122
+ reject(error);
123
+ }
124
+ };
125
+ outcome.then((result) => complete("fulfilled", result), (reason) => complete("rejected", reason));
49
126
  });
50
- seen.set(value, wrapped);
51
- cancellationSignals.set(wrapped, signal);
52
- return wrapped;
53
- }
54
- if (Array.isArray(value)) {
55
- const wrapped = new Array(value.length);
56
- seen.set(value, wrapped);
57
- for (let index = 0; index < value.length; index += 1) {
58
- wrapped[index] = wrapCancelableValue(value[index], signal, seen);
59
- }
60
- return wrapped;
61
127
  }
62
- const wrapped = Object.create(Object.getPrototypeOf(value));
63
- seen.set(value, wrapped);
64
- for (const [key, entry] of Object.entries(value)) {
65
- wrapped[key] = wrapCancelableValue(entry, signal, seen);
128
+ else {
129
+ resolved = resolveSandboxValue(value, { budget });
66
130
  }
67
- return wrapped;
68
- }
69
- function wrapCancelableResult(result, signal, seen) {
70
- if (!isPromiseLike(result)) {
71
- return wrapCancelableValue(result, signal, seen);
72
- }
73
- return wrapCancelablePromise(result, signal, seen);
74
- }
75
- function wrapCancelablePromise(promise, signal, seen) {
76
- return awaitWithSignal(promise, signal).then((value) => wrapCancelableValue(value, signal, seen), (reason) => {
77
- if (signal.aborted && reason === signal.reason)
78
- throw reason;
79
- throw wrapCancelableUnknown(reason, signal, seen);
80
- });
81
- }
82
- export function awaitSandboxValue(value, signal) {
83
- const resolved = resolveSandboxValue(value);
84
- return isSandboxPromise(value) &&
85
- (value.synchronousPrefix !== undefined || cancellationSignals.get(value) === signal)
131
+ const pending = isSandboxPromise(value) &&
132
+ (value.synchronousPrefix !== undefined ||
133
+ (signal !== undefined && cancelableOutcomes.get(value)?.has(signal)))
86
134
  ? resolved
87
135
  : awaitWithSignal(resolved, signal);
136
+ return isSandboxPromise(value) ? pending : interruptOnFatalPromiseRejection(pending);
88
137
  }
89
138
  function awaitWithSignal(promise, signal) {
90
139
  if (signal === undefined)
@@ -125,22 +174,6 @@ function awaitWithSignal(promise, signal) {
125
174
  });
126
175
  });
127
176
  }
128
- function wrapCancelableUnknown(value, signal, seen) {
129
- if (value === null ||
130
- value === undefined ||
131
- typeof value === "string" ||
132
- typeof value === "number" ||
133
- typeof value === "boolean") {
134
- return value;
135
- }
136
- if (isSandboxClosure(value) ||
137
- isSandboxPromise(value) ||
138
- Array.isArray(value) ||
139
- (typeof value === "object" && value !== null)) {
140
- return wrapCancelableValue(value, signal, seen);
141
- }
142
- return value;
143
- }
144
177
  function readAbortReason(signal) {
145
178
  return signal.reason ?? createAbortError();
146
179
  }
@@ -161,5 +194,8 @@ function createRejectedSandboxPromise(reason) {
161
194
  return createSandboxPromise(promise);
162
195
  }
163
196
  function isPromiseLike(value) {
164
- return typeof value === "object" && value !== null && "then" in value;
197
+ return (typeof value === "object" &&
198
+ value !== null &&
199
+ "then" in value &&
200
+ typeof value.then === "function");
165
201
  }
@@ -1,6 +1,7 @@
1
1
  import { attachErrorSpan, attachWrappedErrorCause, describeThrownValue, formatErrorStack, readErrorCause, readErrorSpan } from "../error/shape.js";
2
2
  import { SandboxError } from "./budget.js";
3
3
  import { HostCallResumabilityError } from "./host-call.js";
4
+ import { withFatalPromiseCleanup } from "./promise-tracker.js";
4
5
  import { deepCopyToSandbox } from "./values.js";
5
6
  const capturedExceptionBrand = Symbol("CapturedException");
6
7
  const sandboxErrorBrand = Symbol("SandboxError");
@@ -50,9 +51,12 @@ export async function evaluateTryStatement(node, context, evaluateNode) {
50
51
  if (node.finalizer === undefined || tryOrCatchResult.kind === "error") {
51
52
  return tryOrCatchResult;
52
53
  }
53
- const finalizerResult = fatalBudgetError?.budget === "deadline"
54
- ? await evaluateWithoutDeadlineChecks(context, () => evaluateBlockCompletion(node.finalizer, context, evaluateNode))
55
- : await evaluateBlockCompletion(node.finalizer, context, evaluateNode);
54
+ const evaluateFinalizer = () => fatalBudgetError?.budget === "deadline"
55
+ ? evaluateWithoutDeadlineChecks(context, () => evaluateBlockCompletion(node.finalizer, context, evaluateNode))
56
+ : evaluateBlockCompletion(node.finalizer, context, evaluateNode);
57
+ const finalizerResult = await (fatalBudgetError === undefined
58
+ ? evaluateFinalizer()
59
+ : withFatalPromiseCleanup(evaluateFinalizer));
56
60
  if (fatalBudgetError !== undefined) {
57
61
  throw fatalBudgetError;
58
62
  }
@@ -4,6 +4,7 @@ const mapConstructors = new WeakSet();
4
4
  const setConstructors = new WeakSet();
5
5
  export function createCollectionGlobals(options) {
6
6
  const mapConstructor = createSandboxClosure({
7
+ sandbox: true,
7
8
  call: () => {
8
9
  throw new TypeError("Constructor Map requires 'new'.");
9
10
  },
@@ -17,6 +18,7 @@ export function createCollectionGlobals(options) {
17
18
  name: "Map"
18
19
  });
19
20
  const setConstructor = createSandboxClosure({
21
+ sandbox: true,
20
22
  call: () => {
21
23
  throw new TypeError("Constructor Set requires 'new'.");
22
24
  },
@@ -5,10 +5,12 @@ export function createConsoleJsonGlobals(options) {
5
5
  return {
6
6
  JSON: {
7
7
  parse: createSandboxClosure({
8
+ sandbox: true,
8
9
  call: async ([text]) => parseJson(text, options.budget),
9
10
  name: "parse"
10
11
  }),
11
12
  stringify: createSandboxClosure({
13
+ sandbox: true,
12
14
  call: async ([value, replacer, indent]) => stringifyJson(value, replacer, indent, options.budget),
13
15
  name: "stringify"
14
16
  })
@@ -16,6 +18,7 @@ export function createConsoleJsonGlobals(options) {
16
18
  console: options.hostCalls === undefined
17
19
  ? {
18
20
  error: createSandboxClosure({
21
+ sandbox: true,
19
22
  call: async (args) => {
20
23
  sink.error(...args.map((value) => deepCopyFromSandbox(value)));
21
24
  return undefined;
@@ -23,6 +26,7 @@ export function createConsoleJsonGlobals(options) {
23
26
  name: "error"
24
27
  }),
25
28
  log: createSandboxClosure({
29
+ sandbox: true,
26
30
  call: async (args) => {
27
31
  sink.log(...args.map((value) => deepCopyFromSandbox(value)));
28
32
  return undefined;
@@ -27,11 +27,7 @@ export function isSandboxErrorConstructor(value) {
27
27
  }
28
28
  function createErrorConstructor(name, budget) {
29
29
  const call = (args, context) => createSubsetError(name, args, context?.stack ?? [], budget);
30
- const closure = createSandboxClosure({
31
- call,
32
- construct: call,
33
- name
34
- });
30
+ const closure = createSandboxClosure({ sandbox: true, call, construct: call, name });
35
31
  errorConstructorNames.set(closure, name);
36
32
  return closure;
37
33
  }
@@ -46,13 +46,11 @@ export function createMathGlobals(options = {}) {
46
46
  PI: Math.PI,
47
47
  SQRT1_2: Math.SQRT1_2,
48
48
  SQRT2: Math.SQRT2,
49
- random: createSandboxClosure({
50
- call: () => random(),
51
- name: "random"
52
- })
49
+ random: createSandboxClosure({ sandbox: true, call: () => random(), name: "random" })
53
50
  };
54
51
  for (const [name, method] of Object.entries(mathMethods)) {
55
52
  mathObject[name] = createSandboxClosure({
53
+ sandbox: true,
56
54
  call: (args) => Reflect.apply(method, Math, args),
57
55
  name
58
56
  });
@@ -3,22 +3,27 @@ import { allocateProducedSandboxValue, cloneSandboxValue, createSandboxClosure,
3
3
  export function createMiscGlobals(options) {
4
4
  return {
5
5
  structuredClone: createSandboxClosure({
6
+ sandbox: true,
6
7
  call: ([value]) => structuredCloneSandboxValue(value, options.budget),
7
8
  name: "structuredClone"
8
9
  }),
9
10
  parseInt: createSandboxClosure({
11
+ sandbox: true,
10
12
  call: (args) => Reflect.apply(globalThis.parseInt, globalThis, [...args]),
11
13
  name: "parseInt"
12
14
  }),
13
15
  parseFloat: createSandboxClosure({
16
+ sandbox: true,
14
17
  call: (args) => Reflect.apply(globalThis.parseFloat, globalThis, [...args]),
15
18
  name: "parseFloat"
16
19
  }),
17
20
  isNaN: createSandboxClosure({
21
+ sandbox: true,
18
22
  call: ([value]) => globalThis.isNaN(value),
19
23
  name: "isNaN"
20
24
  }),
21
25
  isFinite: createSandboxClosure({
26
+ sandbox: true,
22
27
  call: ([value]) => globalThis.isFinite(value),
23
28
  name: "isFinite"
24
29
  })
@@ -4,30 +4,37 @@ export function createObjectArrayGlobals(options) {
4
4
  return {
5
5
  Object: {
6
6
  keys: createSandboxClosure({
7
+ sandbox: true,
7
8
  call: ([value]) => budgetSandboxValue(getOwnEnumerableKeys(value), options.budget),
8
9
  name: "keys"
9
10
  }),
10
11
  values: createSandboxClosure({
12
+ sandbox: true,
11
13
  call: ([value]) => budgetSandboxValue(getOwnEnumerableValues(value), options.budget),
12
14
  name: "values"
13
15
  }),
14
16
  entries: createSandboxClosure({
17
+ sandbox: true,
15
18
  call: ([value]) => budgetSandboxValue(getOwnEnumerableEntries(value), options.budget),
16
19
  name: "entries"
17
20
  }),
18
21
  hasOwn: createSandboxClosure({
22
+ sandbox: true,
19
23
  call: ([value, key]) => Reflect.apply(Object.hasOwn, Object, [value, key]),
20
24
  name: "hasOwn"
21
25
  }),
22
26
  is: createSandboxClosure({
27
+ sandbox: true,
23
28
  call: ([left, right]) => Reflect.apply(Object.is, Object, [left, right]),
24
29
  name: "is"
25
30
  }),
26
31
  fromEntries: createSandboxClosure({
32
+ sandbox: true,
27
33
  call: ([value]) => budgetSandboxValue(Reflect.apply(Object.fromEntries, Object, [value]), options.budget),
28
34
  name: "fromEntries"
29
35
  }),
30
36
  freeze: createSandboxClosure({
37
+ sandbox: true,
31
38
  call: ([value]) => {
32
39
  if (typeof value === "object" && value !== null) {
33
40
  Object.freeze(value);
@@ -37,76 +44,93 @@ export function createObjectArrayGlobals(options) {
37
44
  name: "freeze"
38
45
  }),
39
46
  isFrozen: createSandboxClosure({
47
+ sandbox: true,
40
48
  call: ([value]) => Object.isFrozen(value),
41
49
  name: "isFrozen"
42
50
  }),
43
51
  assign: createSandboxClosure({
52
+ sandbox: true,
44
53
  call: ([target, ...sources]) => assignSandboxValues(target, sources),
45
54
  name: "assign"
46
55
  })
47
56
  },
48
57
  Array: createSandboxClosure({
58
+ sandbox: true,
49
59
  call: (args) => createArrayFromConstructorArgs(args, options.budget),
50
60
  construct: (args) => createArrayFromConstructorArgs(args, options.budget),
51
61
  name: "Array",
52
62
  properties: {
53
63
  isArray: createSandboxClosure({
64
+ sandbox: true,
54
65
  call: ([value]) => Array.isArray(value),
55
66
  name: "isArray"
56
67
  }),
57
68
  from: createSandboxClosure({
69
+ sandbox: true,
58
70
  call: (args) => arrayFromSandboxValues(args, options.budget),
59
71
  name: "from"
60
72
  }),
61
73
  of: createSandboxClosure({
74
+ sandbox: true,
62
75
  call: (args) => budgetSandboxValue(Reflect.apply(Array.of, Array, [...args]), options.budget),
63
76
  name: "of"
64
77
  })
65
78
  }
66
79
  }),
67
80
  String: createSandboxClosure({
81
+ sandbox: true,
68
82
  call: ([value]) => options.budget.allocateString(String(value)),
69
83
  name: "String",
70
84
  properties: {
71
85
  raw: createSandboxClosure({
86
+ sandbox: true,
72
87
  call: (args) => stringRaw(args, options.budget),
73
88
  name: "raw"
74
89
  }),
75
90
  fromCharCode: createSandboxClosure({
91
+ sandbox: true,
76
92
  call: (args) => options.budget.allocateString(Reflect.apply(String.fromCharCode, String, [...args])),
77
93
  name: "fromCharCode"
78
94
  }),
79
95
  fromCodePoint: createSandboxClosure({
96
+ sandbox: true,
80
97
  call: (args) => options.budget.allocateString(Reflect.apply(String.fromCodePoint, String, [...args])),
81
98
  name: "fromCodePoint"
82
99
  })
83
100
  }
84
101
  }),
85
102
  Number: createSandboxClosure({
103
+ sandbox: true,
86
104
  call: ([value]) => Number(value),
87
105
  name: "Number",
88
106
  properties: {
89
107
  isFinite: createSandboxClosure({
108
+ sandbox: true,
90
109
  call: ([value]) => typeof value === "number" && Number.isFinite(value),
91
110
  name: "isFinite"
92
111
  }),
93
112
  isNaN: createSandboxClosure({
113
+ sandbox: true,
94
114
  call: ([value]) => typeof value === "number" && Number.isNaN(value),
95
115
  name: "isNaN"
96
116
  }),
97
117
  isInteger: createSandboxClosure({
118
+ sandbox: true,
98
119
  call: ([value]) => typeof value === "number" && Number.isInteger(value),
99
120
  name: "isInteger"
100
121
  }),
101
122
  parseInt: createSandboxClosure({
123
+ sandbox: true,
102
124
  call: (args) => Reflect.apply(Number.parseInt, Number, [...args]),
103
125
  name: "parseInt"
104
126
  }),
105
127
  parseFloat: createSandboxClosure({
128
+ sandbox: true,
106
129
  call: (args) => Reflect.apply(Number.parseFloat, Number, [...args]),
107
130
  name: "parseFloat"
108
131
  }),
109
132
  isSafeInteger: createSandboxClosure({
133
+ sandbox: true,
110
134
  call: ([value]) => typeof value === "number" && Number.isSafeInteger(value),
111
135
  name: "isSafeInteger"
112
136
  }),
@@ -118,6 +142,7 @@ export function createObjectArrayGlobals(options) {
118
142
  }
119
143
  }),
120
144
  Boolean: createSandboxClosure({
145
+ sandbox: true,
121
146
  call: ([value]) => Boolean(value),
122
147
  name: "Boolean"
123
148
  })
@@ -2,6 +2,6 @@ import { createSandboxClosure, createSandboxRegex } from "../values.js";
2
2
  export function createRegexGlobals() {
3
3
  const construct = (args) => createSandboxRegex(String(args[0] ?? ""), String(args[1] ?? ""));
4
4
  return {
5
- RegExp: createSandboxClosure({ name: "RegExp", call: construct, construct })
5
+ RegExp: createSandboxClosure({ sandbox: true, name: "RegExp", call: construct, construct })
6
6
  };
7
7
  }