poe-code 14.0.47 → 14.0.48
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 +141 -75
- 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-WQY27BRL.js → chunk-6GXMEFMD.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-XC53RECY.js → chunk-PCHV72VT.js} +131 -75
- package/packages/safe-js/dist/chunks/chunk-PCHV72VT.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/builtin-call.d.ts +3 -0
- package/packages/safe-js/dist/interp/builtin-call.js +24 -0
- package/packages/safe-js/dist/interp/globals/object-array.d.ts +1 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +111 -48
- package/packages/safe-js/dist/interp/interpreter.js +7 -3
- package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
- package/packages/safe-js/dist/interp/string-coercion.js +24 -35
- package/packages/safe-js/dist/interp/values.d.ts +3 -1
- package/packages/safe-js/dist/chunks/chunk-XC53RECY.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-WQY27BRL.js.map → chunk-6GXMEFMD.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveFsConfig,
|
|
23
23
|
splitFrontmatter,
|
|
24
24
|
withBrokenPipeGuard
|
|
25
|
-
} from "./chunks/chunk-
|
|
25
|
+
} from "./chunks/chunk-6GXMEFMD.js";
|
|
26
26
|
import {
|
|
27
27
|
Budget,
|
|
28
28
|
SandboxError,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
replaceErrorStack,
|
|
35
35
|
restore,
|
|
36
36
|
run
|
|
37
|
-
} from "./chunks/chunk-
|
|
37
|
+
} from "./chunks/chunk-PCHV72VT.js";
|
|
38
38
|
import "./chunks/chunk-UXMKEUH3.js";
|
|
39
39
|
import "./chunks/chunk-5DYEOCT5.js";
|
|
40
40
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
runWithSpawnUsageAccumulator,
|
|
27
27
|
splitFrontmatter,
|
|
28
28
|
supportsSpawnMode
|
|
29
|
-
} from "./chunks/chunk-
|
|
29
|
+
} from "./chunks/chunk-6GXMEFMD.js";
|
|
30
30
|
import {
|
|
31
31
|
Budget,
|
|
32
32
|
FileSnapshotBackend,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
registerPendingHostCallPolicy,
|
|
51
51
|
restore,
|
|
52
52
|
run
|
|
53
|
-
} from "./chunks/chunk-
|
|
53
|
+
} from "./chunks/chunk-PCHV72VT.js";
|
|
54
54
|
import "./chunks/chunk-UXMKEUH3.js";
|
|
55
55
|
import "./chunks/chunk-5DYEOCT5.js";
|
|
56
56
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Budget } from "./budget.js";
|
|
2
|
+
import { type SandboxCallContext, type SandboxClosure, type SandboxValue } from "./values.js";
|
|
3
|
+
export declare function invokeBuiltinClosure(closure: SandboxClosure, args: readonly SandboxValue[], budget: Budget, context: SandboxCallContext | undefined, thisValue: SandboxValue, construct?: boolean): Promise<SandboxValue>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { isSandboxPromise } from "./values.js";
|
|
2
|
+
export async function invokeBuiltinClosure(closure, args, budget, context, thisValue, construct = false) {
|
|
3
|
+
if (context?.invokeClosure !== undefined) {
|
|
4
|
+
return context.invokeClosure(closure, args, thisValue, construct);
|
|
5
|
+
}
|
|
6
|
+
const leaveCall = budget.enterCall();
|
|
7
|
+
try {
|
|
8
|
+
const invoke = construct ? closure.construct : closure.call;
|
|
9
|
+
if (invoke === undefined)
|
|
10
|
+
throw new TypeError("Value is not a constructor.");
|
|
11
|
+
const result = await invoke(args, {
|
|
12
|
+
...context,
|
|
13
|
+
stack: context?.stack ?? [],
|
|
14
|
+
thisValue,
|
|
15
|
+
invokeClosure: (target, values, receiver, asConstructor) => invokeBuiltinClosure(target, values, budget, context, receiver, asConstructor)
|
|
16
|
+
});
|
|
17
|
+
if (isSandboxPromise(result))
|
|
18
|
+
await result.synchronousPrefix;
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
leaveCall();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFatalSandboxError } from "../budget.js";
|
|
2
|
+
import { invokeBuiltinClosure } from "../builtin-call.js";
|
|
3
|
+
import { isCapturedException } from "../exceptions.js";
|
|
4
|
+
import { isSandboxDate } from "../date.js";
|
|
2
5
|
import { getDatePrototype } from "./date.js";
|
|
3
6
|
import { createObjectGlobal, hasOwnSandboxProperty } from "./object.js";
|
|
4
7
|
import { getHostObjectKeys, isGuestHostObject } from "../host-capabilities.js";
|
|
5
8
|
import { isFloat32Array } from "../float32.js";
|
|
6
9
|
import { setSandboxProperty } from "../interpreter.js";
|
|
7
10
|
import { getSandboxIterator } from "../iteration.js";
|
|
8
|
-
import { sandboxString } from "../string-coercion.js";
|
|
9
|
-
import { getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
10
|
-
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, ownEnumerableSandboxEntries as getOwnEnumerableEntries } from "../values.js";
|
|
11
|
+
import { sandboxNumber, sandboxString } from "../string-coercion.js";
|
|
12
|
+
import { getSandboxDataProperty, getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
13
|
+
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, ownEnumerableSandboxEntries as getOwnEnumerableEntries, reconcileCompiledValues } from "../values.js";
|
|
11
14
|
export function createObjectArrayGlobals(options) {
|
|
12
15
|
return {
|
|
13
16
|
Object: createObjectGlobal({
|
|
@@ -165,7 +168,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
165
168
|
}),
|
|
166
169
|
from: createSandboxClosure({
|
|
167
170
|
sandbox: true,
|
|
168
|
-
call: (args) => arrayFromSandboxValues(args, options.budget),
|
|
171
|
+
call: (args, context) => arrayFromSandboxValues(args, options.budget, context),
|
|
169
172
|
name: "from"
|
|
170
173
|
}),
|
|
171
174
|
of: createSandboxClosure({
|
|
@@ -199,7 +202,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
199
202
|
}),
|
|
200
203
|
Number: createSandboxClosure({
|
|
201
204
|
sandbox: true,
|
|
202
|
-
call: (
|
|
205
|
+
call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context),
|
|
203
206
|
name: "Number",
|
|
204
207
|
properties: {
|
|
205
208
|
isFinite: createSandboxClosure({
|
|
@@ -365,45 +368,108 @@ function isAssignableSandboxTarget(value) {
|
|
|
365
368
|
!isSandboxPromise(value) &&
|
|
366
369
|
!isSandboxRegex(value));
|
|
367
370
|
}
|
|
368
|
-
async function arrayFromSandboxValues(args, budget) {
|
|
371
|
+
async function arrayFromSandboxValues(args, budget, context) {
|
|
369
372
|
const [items, mapFn, thisValue] = args;
|
|
373
|
+
if (mapFn !== undefined && !isSandboxClosure(mapFn)) {
|
|
374
|
+
throw new TypeError("Array.from mapping callback must be a function.");
|
|
375
|
+
}
|
|
376
|
+
if (items === null || items === undefined) {
|
|
377
|
+
throw new TypeError("Array.from requires a non-null input.");
|
|
378
|
+
}
|
|
379
|
+
const read = (property) => context?.getProperty !== undefined
|
|
380
|
+
? context.getProperty(items, property)
|
|
381
|
+
: getSandboxDataProperty(items, property, budget);
|
|
370
382
|
const iterator = getSandboxIterator(items);
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
const constructor = context?.thisValue;
|
|
384
|
+
let result;
|
|
385
|
+
let currentValue;
|
|
386
|
+
let failure;
|
|
387
|
+
let estimatedDataSize = 0;
|
|
388
|
+
const retained = {};
|
|
389
|
+
budget.setRetainedValues(retained, () => [items, mapFn, constructor, result, currentValue, failure]);
|
|
390
|
+
const checkData = (growth = 0, force = false) => {
|
|
391
|
+
const limit = budget.limits.dataSize;
|
|
392
|
+
if (limit === undefined)
|
|
393
|
+
return;
|
|
394
|
+
estimatedDataSize = Math.max(estimatedDataSize, budget.currentDataSize) + growth;
|
|
395
|
+
// Primitive writes have bounded growth; changed graphs require an exact check.
|
|
396
|
+
if (!force && estimatedDataSize <= limit)
|
|
397
|
+
return;
|
|
398
|
+
if (context?.reconcileData !== undefined)
|
|
399
|
+
context.reconcileData(result);
|
|
400
|
+
else
|
|
401
|
+
reconcileCompiledValues(budget, [], context?.compilation);
|
|
402
|
+
estimatedDataSize = budget.currentDataSize;
|
|
403
|
+
};
|
|
404
|
+
const closeOnThrow = async (error) => {
|
|
405
|
+
failure = isCapturedException(error) ? error.reason : error;
|
|
406
|
+
try {
|
|
407
|
+
await iterator?.return?.();
|
|
386
408
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
? Reflect.apply(Array.from, Array, [items])
|
|
391
|
-
: await collectIteratorValues(iterator);
|
|
392
|
-
if (mapFn === undefined || !isSandboxClosure(mapFn)) {
|
|
393
|
-
if (mapFn !== undefined) {
|
|
394
|
-
throw new TypeError("Array.from mapping callback must be a function.");
|
|
409
|
+
catch (closeError) {
|
|
410
|
+
if (!isFatalSandboxError(error) && isFatalSandboxError(closeError))
|
|
411
|
+
throw closeError;
|
|
395
412
|
}
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
413
|
+
throw error;
|
|
414
|
+
};
|
|
415
|
+
try {
|
|
416
|
+
let length = 0;
|
|
417
|
+
if (iterator === undefined) {
|
|
418
|
+
const number = await sandboxNumber(read("length"), budget, context);
|
|
419
|
+
length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
403
420
|
}
|
|
404
|
-
|
|
421
|
+
result = isSandboxClosure(constructor) && constructor.construct !== undefined
|
|
422
|
+
? await invokeBuiltinClosure(constructor, iterator === undefined ? [length] : [], budget, context, undefined, true)
|
|
423
|
+
: createArrayFromConstructorArgs([length], budget);
|
|
424
|
+
checkData(0, true);
|
|
425
|
+
let index = 0;
|
|
426
|
+
while (iterator !== undefined || index < length) {
|
|
427
|
+
try {
|
|
428
|
+
budget.visitNode();
|
|
429
|
+
if (iterator !== undefined && index >= Number.MAX_SAFE_INTEGER)
|
|
430
|
+
throw new TypeError("Array.from input is too long.");
|
|
431
|
+
}
|
|
432
|
+
catch (error) {
|
|
433
|
+
await closeOnThrow(error);
|
|
434
|
+
}
|
|
435
|
+
if (iterator !== undefined) {
|
|
436
|
+
const next = await iterator.next();
|
|
437
|
+
if (typeof next !== "object" || next === null)
|
|
438
|
+
throw new TypeError("Iterator result must be an object.");
|
|
439
|
+
if (next.done)
|
|
440
|
+
break;
|
|
441
|
+
currentValue = next.value;
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
currentValue = read(index);
|
|
445
|
+
}
|
|
446
|
+
try {
|
|
447
|
+
if (Array.isArray(result))
|
|
448
|
+
budget.allocateArrayLength(index + 1);
|
|
449
|
+
if (mapFn !== undefined)
|
|
450
|
+
currentValue = await invokeBuiltinClosure(mapFn, [currentValue, index], budget, context, thisValue);
|
|
451
|
+
const key = String(index);
|
|
452
|
+
const growth = key.length + 1 +
|
|
453
|
+
(Array.isArray(result) ? Math.max(0, index + 1 - result.length) : 0) +
|
|
454
|
+
(typeof currentValue === "string" ? currentValue.length : 0);
|
|
455
|
+
const graphChanged = (typeof currentValue === "object" && currentValue !== null) || isSandboxClosure(result);
|
|
456
|
+
budget.visitNode();
|
|
457
|
+
defineOwnDataProperty(objectProperties(result, true), key, currentValue);
|
|
458
|
+
currentValue = undefined;
|
|
459
|
+
checkData(growth, graphChanged);
|
|
460
|
+
}
|
|
461
|
+
catch (error) {
|
|
462
|
+
await closeOnThrow(error);
|
|
463
|
+
}
|
|
464
|
+
index += 1;
|
|
465
|
+
}
|
|
466
|
+
setSandboxProperty(result, "length", index, budget);
|
|
467
|
+
checkData(0, true);
|
|
468
|
+
return allocateProducedSandboxValue(result, budget);
|
|
469
|
+
}
|
|
470
|
+
finally {
|
|
471
|
+
budget.setRetainedValues(retained, undefined);
|
|
405
472
|
}
|
|
406
|
-
return budgetSandboxValue(mappedValues, budget);
|
|
407
473
|
}
|
|
408
474
|
function createArrayFromConstructorArgs(args, budget) {
|
|
409
475
|
if (args.length !== 1) {
|
|
@@ -417,15 +483,12 @@ function createArrayFromConstructorArgs(args, budget) {
|
|
|
417
483
|
throw new RangeError("Invalid array length.");
|
|
418
484
|
}
|
|
419
485
|
budget.allocateArrayLength(lengthOrValue);
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (result.done)
|
|
427
|
-
return values;
|
|
428
|
-
values.push(result.value);
|
|
486
|
+
const release = budget.provisionDataUsage(lengthOrValue + 1);
|
|
487
|
+
try {
|
|
488
|
+
return new Array(lengthOrValue);
|
|
489
|
+
}
|
|
490
|
+
finally {
|
|
491
|
+
release();
|
|
429
492
|
}
|
|
430
493
|
}
|
|
431
494
|
function getOwnEnumerableKeys(value) {
|
|
@@ -231,7 +231,7 @@ async function evaluateNode(node, context) {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
function reconcileDataBudget(budget, stats, scope, transient, compilation, parent) {
|
|
234
|
-
reconcileCompiledValues(budget, [...scope.retainedValues(),
|
|
234
|
+
reconcileCompiledValues(budget, [...scope.retainedValues(), transient], compilation, parent, [transient]);
|
|
235
235
|
stats.currentDataSize = budget.currentDataSize;
|
|
236
236
|
stats.peakDataSize = budget.peakDataSize;
|
|
237
237
|
}
|
|
@@ -2127,7 +2127,9 @@ function createCoercionContext(context) {
|
|
|
2127
2127
|
stack: context.callStack,
|
|
2128
2128
|
thisValue: undefined,
|
|
2129
2129
|
compilation: context.compilation,
|
|
2130
|
-
|
|
2130
|
+
getProperty: (value, property) => getPropertyValue(value, property, context),
|
|
2131
|
+
reconcileData: value => reconcileDataBudget(context.budget, context.stats, context.scope, value, context.compilation, context.compilation?.parent),
|
|
2132
|
+
invokeClosure: (closure, args, thisValue, construct) => invokeSandboxClosure(closure, args, context, context.callStack, undefined, thisValue, construct)
|
|
2131
2133
|
};
|
|
2132
2134
|
}
|
|
2133
2135
|
function hasSandboxProperty(value, key, context) {
|
|
@@ -2518,7 +2520,9 @@ async function invokeSandboxClosure(callee, args, context, stack, span, thisValu
|
|
|
2518
2520
|
stack,
|
|
2519
2521
|
thisValue,
|
|
2520
2522
|
compilation: context.compilation,
|
|
2521
|
-
|
|
2523
|
+
getProperty: (value, property) => getPropertyValue(value, property, context),
|
|
2524
|
+
reconcileData: (value) => reconcileDataBudget(context.budget, context.stats, context.scope, value, context.compilation, context.compilation?.parent),
|
|
2525
|
+
invokeClosure: (closure, argumentsList, receiver, asConstructor) => invokeSandboxClosure(closure, argumentsList, context, stack, span, receiver, asConstructor),
|
|
2522
2526
|
...(span === undefined ? {} : { span })
|
|
2523
2527
|
}
|
|
2524
2528
|
]);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Budget } from "./budget.js";
|
|
2
2
|
import { type SandboxCallContext, type SandboxValue } from "./values.js";
|
|
3
|
+
export declare function sandboxNumber(value: SandboxValue, budget: Budget, context?: SandboxCallContext): number | Promise<number>;
|
|
3
4
|
export declare function sandboxString(value: SandboxValue, budget: Budget, context?: SandboxCallContext, joining?: Set<object>): string | Promise<string>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
2
|
-
import { dateString, isSandboxDate } from "./date.js";
|
|
2
|
+
import { dateString, dateTime, isSandboxDate } from "./date.js";
|
|
3
|
+
import { invokeBuiltinClosure } from "./builtin-call.js";
|
|
3
4
|
import { float32Storage, isFloat32Array } from "./float32.js";
|
|
4
5
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
5
6
|
import { isGuestHostObject } from "./host-capabilities.js";
|
|
@@ -7,55 +8,46 @@ import { getGuestFunctionProperties, getSandboxPrototype, hasExplicitSandboxProt
|
|
|
7
8
|
import { getRegexMember } from "./methods/regex.js";
|
|
8
9
|
import { isSandboxClosure, isSandboxPromise, isSandboxMap, isSandboxSet, isSandboxRegex, isSandboxGenerator } from "./values.js";
|
|
9
10
|
const defaultStringHook = Symbol("defaultStringHook");
|
|
11
|
+
const defaultValueHook = Symbol("defaultValueHook");
|
|
12
|
+
export function sandboxNumber(value, budget, context) {
|
|
13
|
+
if (value === null || typeof value !== "object") {
|
|
14
|
+
if (typeof value === "function")
|
|
15
|
+
throw new TypeError("Expected a sandbox value.");
|
|
16
|
+
return Number(value);
|
|
17
|
+
}
|
|
18
|
+
return objectToPrimitive(value, budget, context, new Set(), "number").then(Number);
|
|
19
|
+
}
|
|
10
20
|
export function sandboxString(value, budget, context, joining = new Set()) {
|
|
11
21
|
if (value === null || typeof value !== "object") {
|
|
12
22
|
if (typeof value === "function")
|
|
13
23
|
throw new TypeError("Expected a sandbox value.");
|
|
14
24
|
return budget.allocateString(String(value));
|
|
15
25
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
: {
|
|
19
|
-
...context,
|
|
20
|
-
stack: context?.stack ?? [],
|
|
21
|
-
thisValue: context?.thisValue,
|
|
22
|
-
invokeClosure: async (closure, args, thisValue) => {
|
|
23
|
-
const leaveCall = budget.enterCall();
|
|
24
|
-
try {
|
|
25
|
-
const result = closure.call(args, { ...invocation, thisValue });
|
|
26
|
-
if (isSandboxPromise(result)) {
|
|
27
|
-
await result.synchronousPrefix;
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
return await result;
|
|
31
|
-
}
|
|
32
|
-
finally {
|
|
33
|
-
leaveCall();
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
return stringifyObject(value, budget, invocation, joining);
|
|
26
|
+
return objectToPrimitive(value, budget, context, joining, "string")
|
|
27
|
+
.then(primitive => budget.allocateString(String(primitive)));
|
|
38
28
|
}
|
|
39
|
-
async function
|
|
29
|
+
async function objectToPrimitive(value, budget, context, joining, hint) {
|
|
40
30
|
const leaveCall = budget.enterCall();
|
|
41
31
|
try {
|
|
42
32
|
budget.visitNode();
|
|
43
|
-
for (const name of ["toString", "valueOf"]) {
|
|
33
|
+
for (const name of hint === "string" ? ["toString", "valueOf"] : ["valueOf", "toString"]) {
|
|
44
34
|
const hook = conversionHook(value, name, budget);
|
|
45
35
|
let result;
|
|
46
36
|
if (hook === defaultStringHook) {
|
|
47
37
|
result = await defaultToString(value, budget, context, joining);
|
|
48
38
|
}
|
|
39
|
+
else if (hook === defaultValueHook) {
|
|
40
|
+
result = isSandboxDate(value) ? dateTime(value) : value;
|
|
41
|
+
}
|
|
49
42
|
else {
|
|
50
43
|
if (!isSandboxClosure(hook))
|
|
51
44
|
continue;
|
|
52
|
-
|
|
53
|
-
throw new TypeError("String hooks require a sandbox call context.");
|
|
54
|
-
}
|
|
55
|
-
result = await context.invokeClosure(hook, [], value);
|
|
45
|
+
result = await invokeBuiltinClosure(hook, [], budget, context, value);
|
|
56
46
|
}
|
|
57
47
|
if (result === null || typeof result !== "object") {
|
|
58
|
-
|
|
48
|
+
if (typeof result === "function")
|
|
49
|
+
throw new TypeError("Expected a sandbox value.");
|
|
50
|
+
return result;
|
|
59
51
|
}
|
|
60
52
|
}
|
|
61
53
|
throw new TypeError("Cannot convert object to primitive value");
|
|
@@ -90,7 +82,7 @@ function conversionHook(value, name, budget) {
|
|
|
90
82
|
const parent = getSandboxPrototype(current, budget);
|
|
91
83
|
if (current === value &&
|
|
92
84
|
(implicitBuiltin || (parent === null && !hasExplicitSandboxPrototype(value)))) {
|
|
93
|
-
return name === "toString" ? defaultStringHook :
|
|
85
|
+
return name === "toString" ? defaultStringHook : defaultValueHook;
|
|
94
86
|
}
|
|
95
87
|
current = parent;
|
|
96
88
|
if (current !== null) {
|
|
@@ -117,10 +109,7 @@ async function defaultToString(value, budget, context, joining) {
|
|
|
117
109
|
const join = ownDataValue(value, "join");
|
|
118
110
|
if (!isSandboxClosure(join))
|
|
119
111
|
return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
|
|
120
|
-
|
|
121
|
-
throw new TypeError("String hooks require a sandbox call context.");
|
|
122
|
-
}
|
|
123
|
-
return context.invokeClosure(join, [], value);
|
|
112
|
+
return invokeBuiltinClosure(join, [], budget, context, value);
|
|
124
113
|
}
|
|
125
114
|
if (joining.has(value))
|
|
126
115
|
return "";
|
|
@@ -51,7 +51,9 @@ export type SandboxCallContext = {
|
|
|
51
51
|
};
|
|
52
52
|
readonly stack: readonly string[];
|
|
53
53
|
readonly thisValue: SandboxValue;
|
|
54
|
-
readonly
|
|
54
|
+
readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue;
|
|
55
|
+
readonly reconcileData?: (value: SandboxValue) => void;
|
|
56
|
+
readonly invokeClosure?: (closure: SandboxClosure, args: readonly SandboxValue[], thisValue: SandboxValue, construct?: boolean) => Promise<SandboxValue>;
|
|
55
57
|
};
|
|
56
58
|
export type SandboxClosure = {
|
|
57
59
|
readonly async?: true;
|