poe-code 14.0.80 → 14.0.82

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 (49) hide show
  1. package/dist/index.js +876 -404
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-34G5WW2O.js → chunk-7LGBDF56.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-M4L3EZHL.js → chunk-V6LQP64H.js} +733 -334
  7. package/packages/safe-js/dist/chunks/chunk-V6LQP64H.js.map +7 -0
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.js +2 -2
  11. package/packages/safe-js/dist/interp/async.d.ts +1 -1
  12. package/packages/safe-js/dist/interp/async.js +65 -43
  13. package/packages/safe-js/dist/interp/bound-function-state.d.ts +7 -0
  14. package/packages/safe-js/dist/interp/bound-function-state.js +1 -0
  15. package/packages/safe-js/dist/interp/bound-function.d.ts +4 -0
  16. package/packages/safe-js/dist/interp/bound-function.js +18 -0
  17. package/packages/safe-js/dist/interp/error-prototypes.d.ts +3 -0
  18. package/packages/safe-js/dist/interp/error-prototypes.js +1 -0
  19. package/packages/safe-js/dist/interp/exceptions.d.ts +1 -0
  20. package/packages/safe-js/dist/interp/exceptions.js +39 -15
  21. package/packages/safe-js/dist/interp/generator-prototypes.d.ts +6 -0
  22. package/packages/safe-js/dist/interp/generator-prototypes.js +1 -0
  23. package/packages/safe-js/dist/interp/globals/error.d.ts +2 -0
  24. package/packages/safe-js/dist/interp/globals/error.js +104 -4
  25. package/packages/safe-js/dist/interp/globals/function.d.ts +1 -1
  26. package/packages/safe-js/dist/interp/globals/function.js +10 -2
  27. package/packages/safe-js/dist/interp/globals/generator.d.ts +2 -0
  28. package/packages/safe-js/dist/interp/globals/generator.js +51 -0
  29. package/packages/safe-js/dist/interp/globals/object-array.js +19 -1
  30. package/packages/safe-js/dist/interp/globals.d.ts +2 -0
  31. package/packages/safe-js/dist/interp/globals.js +7 -3
  32. package/packages/safe-js/dist/interp/host-bridge.js +4 -2
  33. package/packages/safe-js/dist/interp/instanceof.d.ts +4 -0
  34. package/packages/safe-js/dist/interp/instanceof.js +59 -0
  35. package/packages/safe-js/dist/interp/interpreter.js +3 -40
  36. package/packages/safe-js/dist/interp/iteration.js +44 -6
  37. package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
  38. package/packages/safe-js/dist/interp/methods/function.js +53 -40
  39. package/packages/safe-js/dist/interp/methods/generator.d.ts +4 -1
  40. package/packages/safe-js/dist/interp/methods/generator.js +12 -6
  41. package/packages/safe-js/dist/interp/object-model.js +13 -0
  42. package/packages/safe-js/dist/interp/values.js +47 -2
  43. package/packages/safe-js/dist/snapshot/guest-heap-validation.js +28 -3
  44. package/packages/safe-js/dist/snapshot/guest-heap.d.ts +10 -0
  45. package/packages/safe-js/dist/snapshot/guest-heap.js +13 -2
  46. package/packages/safe-js/dist/snapshot/restore.js +69 -8
  47. package/packages/safe-js/dist/snapshot/validation.js +1 -1
  48. package/packages/safe-js/dist/chunks/chunk-M4L3EZHL.js.map +0 -7
  49. /package/packages/safe-js/dist/chunks/{chunk-34G5WW2O.js.map → chunk-7LGBDF56.js.map} +0 -0
@@ -20,7 +20,7 @@ import { toPropertyKey } from "../property-key.js";
20
20
  import { createNumericParsers } from "./numeric-parsers.js";
21
21
  import { createPrimitiveConstructor } from "./primitives.js";
22
22
  import { arrayMethodNames, callArrayMethod } from "../methods/array.js";
23
- import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, installArrayPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, registerIntrinsicObject, setSandboxPrototype } from "../object-model.js";
23
+ import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, installArrayPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, registerIntrinsicObject, registerIntrinsicFunction, setSandboxPrototype } from "../object-model.js";
24
24
  import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownSandboxSymbolKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
25
25
  export function createObjectArrayGlobals(options) {
26
26
  return {
@@ -332,6 +332,21 @@ function createArrayGlobal(budget) {
332
332
  guest: true, sandbox: true, name: "[Symbol.iterator]", length: 0,
333
333
  call: (_args, context) => context?.thisValue
334
334
  }), writable: true, configurable: true });
335
+ const iteratorTagGetter = createSandboxClosure({ guest: true, sandbox: true,
336
+ name: "get [Symbol.toStringTag]", length: 0, call: () => "Iterator" });
337
+ const iteratorTagSetter = createSandboxClosure({ guest: true, sandbox: true,
338
+ name: "set [Symbol.toStringTag]", length: 1, call: ([value], context) => {
339
+ const receiver = context?.thisValue;
340
+ if (receiver === iterablePrototype || receiver === null || typeof receiver !== "object")
341
+ throw new TypeError("Iterator tag setter requires a distinct object receiver.");
342
+ defineOwnDataProperty(objectProperties(receiver, true), Symbol.toStringTag, value);
343
+ createDataCheckpoint(budget, context)(receiver, 0, true);
344
+ return undefined;
345
+ }
346
+ });
347
+ Object.defineProperty(iterablePrototype, Symbol.toStringTag, {
348
+ get: accessorAdapter(iteratorTagGetter, "get"), set: accessorAdapter(iteratorTagSetter, "set"), configurable: true
349
+ });
335
350
  setSandboxPrototype(iterablePrototype, getSandboxPrototype(Object.create(null), budget));
336
351
  setSandboxPrototype(iteratorPrototype, iterablePrototype);
337
352
  Object.defineProperties(iteratorPrototype, {
@@ -341,6 +356,9 @@ function createArrayGlobal(budget) {
341
356
  [Symbol.toStringTag]: { value: "Array Iterator", configurable: true }
342
357
  });
343
358
  registerBuiltinIdentities(budget, { "%ArrayIteratorPrototype%": iteratorPrototype, "%IteratorPrototype%": iterablePrototype });
359
+ registerIntrinsicFunction(budget, iterablePrototype[Symbol.iterator]);
360
+ registerIntrinsicFunction(budget, iteratorTagGetter);
361
+ registerIntrinsicFunction(budget, iteratorTagSetter);
344
362
  registerIntrinsicObject(budget, iterablePrototype);
345
363
  registerIntrinsicObject(budget, iteratorPrototype);
346
364
  for (const method of ["keys", "values", "entries"]) {
@@ -3,6 +3,8 @@ import type { RunClock } from "../run.js";
3
3
  export declare function createBuiltinBindings(options: Parameters<typeof createConsoleJsonGlobals>[0] & {
4
4
  random?: () => number;
5
5
  clock?: RunClock;
6
+ functionHasInstance?: boolean;
7
+ errorPrototypes?: boolean;
6
8
  }): {
7
9
  RegExp: import("./values.js").SandboxClosure;
8
10
  Promise: import("./values.js").SandboxClosure;
@@ -1,13 +1,14 @@
1
1
  import { createConsoleJsonGlobals } from "./globals/console-json.js";
2
2
  import { createCollectionGlobals } from "./globals/collections.js";
3
3
  import { createFloat32ArrayGlobal } from "./globals/float32array.js";
4
- import { createErrorGlobals } from "./globals/error.js";
4
+ import { createErrorGlobals, createErrorPrototypes } from "./globals/error.js";
5
5
  import { createMathGlobals } from "./globals/math.js";
6
6
  import { createRegexGlobals } from "./globals/regex.js";
7
7
  import { createMiscGlobals } from "./globals/misc.js";
8
8
  import { createUriGlobals } from "./globals/uri.js";
9
9
  import { createObjectArrayGlobals } from "./globals/object-array.js";
10
10
  import { createFunctionPrototype } from "./globals/function.js";
11
+ import { createGeneratorPrototypes } from "./globals/generator.js";
11
12
  import { createPromiseGlobals } from "./promise.js";
12
13
  import { createDateGlobal } from "./globals/date.js";
13
14
  import { createSymbolGlobal } from "./globals/symbol.js";
@@ -21,7 +22,7 @@ export function createBuiltinBindings(options) {
21
22
  Date: createDateGlobal(options),
22
23
  Symbol: createSymbolGlobal(options.budget),
23
24
  BigInt: createBigIntGlobal(options.budget),
24
- ...createErrorGlobals(options),
25
+ ...createErrorGlobals({ ...options, errorPrototypes: options.errorPrototypes !== false }),
25
26
  ...createMathGlobals({ random: options.random, budget: options.budget }),
26
27
  ...createObjectArrayGlobals(options),
27
28
  ...createMiscGlobals(options),
@@ -29,7 +30,10 @@ export function createBuiltinBindings(options) {
29
30
  ...createPromiseGlobals(options),
30
31
  ...createRegexGlobals(options)
31
32
  };
32
- createFunctionPrototype(options.budget);
33
+ createFunctionPrototype(options.budget, options.functionHasInstance);
34
+ if (options.errorPrototypes !== false)
35
+ createErrorPrototypes(options.budget, bindings);
36
+ createGeneratorPrototypes(options.budget);
33
37
  registerBuiltinIdentities(options.budget, bindings);
34
38
  return bindings;
35
39
  }
@@ -408,10 +408,12 @@ function createHostErrorValue(reason, stackFrames, budget, span, state = { seen:
408
408
  const error = reason instanceof Error
409
409
  ? createSubsetErrorValue(reason.name, reason.message, stackFrames, budget, {
410
410
  cause: reason,
411
- chargeBudget
411
+ chargeBudget,
412
+ transport: true
412
413
  })
413
414
  : createSubsetErrorValue("Error", describeThrownReason(reason), stackFrames, budget, {
414
- chargeBudget: false
415
+ chargeBudget: false,
416
+ transport: true
415
417
  });
416
418
  if (reason instanceof Error) {
417
419
  state.seen.set(reason, error);
@@ -0,0 +1,4 @@
1
+ import type { Budget } from "./budget.js";
2
+ import { type SandboxCallContext, type SandboxValue } from "./values.js";
3
+ export declare function evaluateInstanceof(value: SandboxValue, constructor: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<boolean>;
4
+ export declare function ordinaryHasInstance(value: SandboxValue, constructor: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<boolean>;
@@ -0,0 +1,59 @@
1
+ import { assertSandboxDataDepth } from "../graph-depth.js";
2
+ import { readPropertyDescriptor } from "./accessors.js";
3
+ import { invokeBuiltinClosure } from "./builtin-call.js";
4
+ import { isFloat32Array } from "./float32.js";
5
+ import { isFloat32ArrayConstructor } from "./globals/float32array.js";
6
+ import { isSandboxErrorConstructorInstance } from "./globals/error.js";
7
+ import { getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure } from "./object-model.js";
8
+ import { isSandboxClosure } from "./values.js";
9
+ export async function evaluateInstanceof(value, constructor, budget, context) {
10
+ if (constructor === null || typeof constructor !== "object")
11
+ throw new TypeError("Right-hand side of 'instanceof' must be an object.");
12
+ const method = await readInstanceProperty(constructor, Symbol.hasInstance, budget, context);
13
+ if (method !== undefined && method !== null) {
14
+ if (!isSandboxClosure(method))
15
+ throw new TypeError("Symbol.hasInstance must be callable.");
16
+ return Boolean(await invokeBuiltinClosure(method, [value], budget, context, constructor));
17
+ }
18
+ if (!isSandboxClosure(constructor))
19
+ throw new TypeError("Right-hand side of 'instanceof' is not a function.");
20
+ return ordinaryHasInstance(value, constructor, budget, context);
21
+ }
22
+ export async function ordinaryHasInstance(value, constructor, budget, context) {
23
+ if (!isSandboxClosure(constructor))
24
+ return false;
25
+ if (constructor.boundTarget !== undefined) {
26
+ budget.visitNode();
27
+ return evaluateInstanceof(value, constructor.boundTarget, budget, context);
28
+ }
29
+ // These existing built-ins do not yet have ordinary prototype graphs.
30
+ if (isFloat32ArrayConstructor(constructor))
31
+ return isFloat32Array(value);
32
+ if ((!isGuestClosure(constructor) || (value !== null && typeof value === "object" && !hasExplicitSandboxPrototype(value))) &&
33
+ isSandboxErrorConstructorInstance(value, constructor))
34
+ return true;
35
+ if (!isGuestClosure(constructor) || typeof value !== "object" || value === null)
36
+ return false;
37
+ const prototype = await readInstanceProperty(constructor, "prototype", budget, context);
38
+ if (typeof prototype !== "object" || prototype === null)
39
+ throw new TypeError("Function has a non-object prototype in instanceof check.");
40
+ let depth = 0;
41
+ for (let current = getSandboxPrototype(value, budget); current !== null; current = getSandboxPrototype(current, budget)) {
42
+ budget.visitNode();
43
+ assertSandboxDataDepth(depth++);
44
+ if (current === prototype)
45
+ return true;
46
+ }
47
+ return false;
48
+ }
49
+ async function readInstanceProperty(value, key, budget, context) {
50
+ if (context?.getProperty !== undefined)
51
+ return context.getProperty(value, key);
52
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
53
+ if (descriptor === undefined)
54
+ return undefined;
55
+ return readPropertyDescriptor(descriptor, value, {
56
+ ...context, stack: context?.stack ?? [], thisValue: value,
57
+ invokeClosure: context?.invokeClosure ?? ((closure, args, receiver) => invokeBuiltinClosure(closure, args, budget, context, receiver))
58
+ });
59
+ }
@@ -34,13 +34,13 @@ import { getRegexMember, setRegexMember } from "./methods/regex.js";
34
34
  import { bindPattern } from "./patterns.js";
35
35
  import { callStringMethod, getStringMember, isStringMethodName, validateStringMethodArguments } from "./methods/string.js";
36
36
  import { callSetMethod, getSetMember, isSetMethodName } from "./methods/set.js";
37
- import { isSandboxErrorConstructorInstance } from "./globals/error.js";
37
+ import { evaluateInstanceof } from "./instanceof.js";
38
38
  import { hasOwnSandboxProperty } from "./globals/object.js";
39
39
  import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
40
40
  import { getCollectionIteratorMember } from "./methods/collection-iterator.js";
41
41
  import { isSandboxRegExpIterator, regexpIteratorState } from "./regexp-iterator.js";
42
42
  import { getRegExpIteratorMember } from "./methods/regexp-iterator.js";
43
- import { getFloat32Member, isFloat32ArrayConstructor, setFloat32Member } from "./globals/float32array.js";
43
+ import { getFloat32Member, setFloat32Member } from "./globals/float32array.js";
44
44
  import { isFloat32Array } from "./float32.js";
45
45
  import { dateString, dateTime, isSandboxDate } from "./date.js";
46
46
  import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet, reconcileCompiledValues } from "./values.js";
@@ -2604,48 +2604,11 @@ function applyBinaryOperator(node, left, right, context) {
2604
2604
  case ">>>":
2605
2605
  return toNumber(left) >>> toNumber(right);
2606
2606
  case "instanceof":
2607
- return evaluateInstanceof(left, right, context);
2607
+ return evaluateInstanceof(left, right, context.budget, createCoercionContext(context));
2608
2608
  case "in":
2609
2609
  return hasSandboxProperty(right, left, context);
2610
2610
  }
2611
2611
  }
2612
- async function evaluateInstanceof(left, right, context) {
2613
- while (true) {
2614
- if (right === null || (typeof right !== "object" && typeof right !== "function"))
2615
- throw new TypeError("Right-hand side of 'instanceof' must be an object.");
2616
- const method = await getPropertyValue(right, Symbol.hasInstance, context);
2617
- if (method !== undefined && method !== null) {
2618
- if (!isSandboxClosure(method))
2619
- throw new TypeError("Symbol.hasInstance must be callable.");
2620
- return Boolean(await invokeSandboxClosure(method, [left], context, context.callStack, undefined, right));
2621
- }
2622
- if (!isSandboxClosure(right))
2623
- throw new TypeError("Right-hand side of 'instanceof' is not a function.");
2624
- if (right.boundTarget === undefined)
2625
- break;
2626
- context.budget.visitNode();
2627
- right = right.boundTarget;
2628
- }
2629
- if (isFloat32ArrayConstructor(right))
2630
- return isFloat32Array(left);
2631
- if (isSandboxErrorConstructorInstance(left, right))
2632
- return true;
2633
- if (isGuestClosure(right)) {
2634
- if (typeof left !== "object" || left === null)
2635
- return false;
2636
- const prototype = await getPropertyValue(right, "prototype", context);
2637
- if (typeof prototype !== "object" || prototype === null)
2638
- throw new TypeError("Function has a non-object prototype in instanceof check.");
2639
- let depth = 0;
2640
- for (let current = getSandboxPrototype(left, context.budget); current !== null; current = getSandboxPrototype(current, context.budget)) {
2641
- context.budget.visitNode();
2642
- assertSandboxDataDepth(depth++);
2643
- if (current === prototype)
2644
- return true;
2645
- }
2646
- }
2647
- return false;
2648
- }
2649
2612
  export function createCoercionContext(context) {
2650
2613
  return {
2651
2614
  stack: context.callStack,
@@ -14,6 +14,7 @@ import { suspendJob } from "./jobs.js";
14
14
  import { invokeBuiltinClosure } from "./builtin-call.js";
15
15
  import { getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype } from "./object-model.js";
16
16
  import { getIntrinsicIdentity } from "./intrinsics.js";
17
+ import { readPropertyDescriptor } from "./accessors.js";
17
18
  export function mapIteratorSnapshot(snapshot, map) {
18
19
  if (snapshot.kind === "unsupported")
19
20
  throw new TypeError("Host-owned iterator cannot be portably snapshotted.");
@@ -51,16 +52,14 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
51
52
  if (getSandboxPropertyDescriptor(value, key, budget) === undefined &&
52
53
  !(isSandboxRegExpIterator(value) && !asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)) {
53
54
  if (isSandboxGenerator(value)) {
54
- if (hasExplicitSandboxPrototype(value))
55
- return undefined;
56
- if ((value.async === true) === asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)
55
+ if (!hasExplicitSandboxPrototype(value) && (value.async === true) === asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)
57
56
  return guestIterator(value, await context.getProperty(value, "next"), asyncProtocol, budget, context, signal);
58
57
  }
59
58
  if (!asyncProtocol && Array.isArray(value) && getSandboxPrototype(value, budget) !== null)
60
59
  return undefined;
61
60
  if (!asyncProtocol)
62
61
  return getSandboxIterator(value, budget, context);
63
- if (isSandboxGenerator(value) && value.async)
62
+ if (isSandboxGenerator(value) && value.async && !hasExplicitSandboxPrototype(value))
64
63
  return getSandboxAsyncIterator(value, budget, context, signal);
65
64
  const iterator = await acquireSandboxIterator(value, budget, context);
66
65
  return iterator === undefined ? undefined : asyncFromSyncIterator(iterator, budget, signal, context);
@@ -137,7 +136,8 @@ export async function readIteratorResult(iterator, result, property) {
137
136
  }
138
137
  export function getSandboxAsyncIterator(value, budget, context, signal) {
139
138
  if (isSandboxGenerator(value) && value.async) {
140
- return hasExplicitSandboxPrototype(value) ? undefined
139
+ return hasExplicitSandboxPrototype(value) ? context?.getProperty === undefined
140
+ ? generatorProtocolAdapter(value, budget, context, true, signal) : undefined
141
141
  : { ...generatorObjectIterator(value, budget, context), asyncProtocol: true };
142
142
  }
143
143
  if (value !== null &&
@@ -296,7 +296,12 @@ export function getSandboxIterator(value, budget, context) {
296
296
  return syncIterator(Float32Array.prototype.values.call(value));
297
297
  }
298
298
  if (isSandboxGenerator(value)) {
299
- return value.async || hasExplicitSandboxPrototype(value) ? undefined : generatorObjectIterator(value, budget, context);
299
+ if (value.async)
300
+ return undefined;
301
+ if (hasExplicitSandboxPrototype(value))
302
+ return context?.getProperty === undefined
303
+ ? generatorProtocolAdapter(value, budget ?? new Budget(), context, false) : undefined;
304
+ return generatorObjectIterator(value, budget, context);
300
305
  }
301
306
  if (typeof value === "string") {
302
307
  const iterator = value[Symbol.iterator]();
@@ -381,6 +386,39 @@ function collectionIterator(collection, value) {
381
386
  return adapter;
382
387
  }
383
388
  const asyncGeneratorRequests = new WeakMap();
389
+ function generatorProtocolAdapter(value, budget, context, asyncProtocol, signal) {
390
+ // Direct host adapters still need guest property reads, receiver binding and
391
+ // cached next methods, but retain their asynchronous generator result channel.
392
+ const bridge = {
393
+ ...context,
394
+ stack: context?.stack ?? [],
395
+ thisValue: value,
396
+ invokeClosure: (closure, args, receiver, construct) => invokeBuiltinClosure(closure, args, budget, context, receiver, construct),
397
+ getProperty: (target, key) => {
398
+ const descriptor = getSandboxPropertyDescriptor(target, key, budget);
399
+ return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, target, bridge, true);
400
+ }
401
+ };
402
+ let resolved;
403
+ let pending;
404
+ const initialize = () => pending ??= acquireSandboxIterator(value, budget, bridge, asyncProtocol, signal).then(iterator => {
405
+ if (iterator === undefined)
406
+ throw new TypeError("Generator does not provide an iterator protocol.");
407
+ return resolved = iterator;
408
+ });
409
+ return {
410
+ asynchronous: true,
411
+ ...(asyncProtocol ? { asyncProtocol: true } : {}),
412
+ get retainedValue() { return [value, resolved?.retainedValue]; },
413
+ snapshot: () => resolved?.snapshot?.() ?? { kind: "unsupported" },
414
+ next: async (...args) => (await initialize()).next(...args),
415
+ getOperation: async (method) => {
416
+ const iterator = await initialize();
417
+ return iterator.getOperation === undefined ? iterator[method] : iterator.getOperation(method);
418
+ },
419
+ readResultProperty: async (result, property) => readIteratorResult(await initialize(), result, property)
420
+ };
421
+ }
384
422
  function generatorObjectIterator(generator, budget, context) {
385
423
  const iterator = generatorIterator(generator, budget, context);
386
424
  if (context?.getProperty === undefined)
@@ -1,5 +1,5 @@
1
1
  import { type SandboxCallContext, type SandboxClosure, type SandboxValue } from "../values.js";
2
- import type { Budget } from "../budget.js";
2
+ import { Budget } from "../budget.js";
3
3
  export type FunctionMethodOptions = {
4
4
  budget?: Budget;
5
5
  callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue: SandboxValue, construct?: boolean, newTarget?: SandboxClosure) => Promise<SandboxValue> | SandboxValue;
@@ -1,8 +1,12 @@
1
1
  import { createSandboxClosure, isSandboxClosure } from "../values.js";
2
- import { getGuestFunctionProperty, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure, setSandboxPrototype } from "../object-model.js";
2
+ import { getGuestFunctionProperty, getSandboxPropertyDescriptor, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure, setSandboxPrototype } from "../object-model.js";
3
3
  import { assertSandboxDataDepth } from "../../graph-depth.js";
4
+ import { Budget } from "../budget.js";
4
5
  import { functionString } from "../function-string.js";
5
- import { runResources } from "../resources.js";
6
+ import { retainValues, runResources } from "../resources.js";
7
+ import { createBoundFunction } from "../bound-function.js";
8
+ import { sandboxNumber } from "../string-coercion.js";
9
+ import { readPropertyDescriptor } from "../accessors.js";
6
10
  const functionMethodNames = new Set(["apply", "bind", "call", "toString"]);
7
11
  export function getFunctionMember(target, property, options) {
8
12
  let current = target;
@@ -58,40 +62,36 @@ export function callFunctionMethod(target, methodName, args, options, stack, con
58
62
  const thisValue = args[0];
59
63
  if (methodName === "bind") {
60
64
  const boundArgs = args.slice(1);
65
+ const explicitPrototype = hasExplicitSandboxPrototype(target);
66
+ const prototype = getSandboxPrototype(target, options.budget);
61
67
  const bind = (length, name) => {
62
- const bound = createSandboxClosure({
63
- guest: true,
64
- sandbox: true,
65
- name: `bound ${name}`,
66
- length,
67
- boundTarget: target,
68
- retainedValues: () => [target, thisValue, ...boundArgs, bound.name],
69
- call: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], thisValue),
70
- ...(target.construct === undefined
71
- ? {}
72
- : {
73
- construct: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], undefined, true, context?.newTarget === bound ? target : context?.newTarget)
74
- })
75
- });
76
- if (hasExplicitSandboxPrototype(target))
77
- setSandboxPrototype(bound, getSandboxPrototype(target, options.budget), options.budget);
68
+ const bound = createBoundFunction({ target, thisValue, args: boundArgs }, `bound ${name}`, length, options.callClosure);
69
+ if (explicitPrototype)
70
+ setSandboxPrototype(bound, prototype, options.budget);
78
71
  return bound;
79
72
  };
80
73
  if (context?.getProperty === undefined)
81
74
  return bind(target.length === undefined ? undefined : Math.max(0, target.length - boundArgs.length), target.name ?? "");
82
75
  return (async () => {
83
- const properties = target.properties;
84
- const defaultName = target.name;
85
- const hasLength = !isGuestClosure(target) ||
86
- target.properties === undefined ||
87
- Object.hasOwn(target.properties, "length");
88
- const length = hasLength ? await context.getProperty(target, "length") : undefined;
89
- const name = !isGuestClosure(target) && !Object.hasOwn(properties ?? {}, "name")
90
- ? defaultName
91
- : await context.getProperty(target, "name");
92
- return bind(typeof length === "number" && !Number.isNaN(length)
93
- ? Math.max(0, Math.trunc(length) - boundArgs.length)
94
- : 0, typeof name === "string" ? name : "");
76
+ const release = options.budget !== undefined && explicitPrototype && prototype !== null
77
+ ? retainValues(options.budget, () => [prototype]) : undefined;
78
+ try {
79
+ const properties = target.properties;
80
+ const defaultName = target.name;
81
+ const hasLength = !isGuestClosure(target) ||
82
+ target.properties === undefined ||
83
+ Object.hasOwn(target.properties, "length");
84
+ const length = hasLength ? await context.getProperty(target, "length") : undefined;
85
+ const name = !isGuestClosure(target) && !Object.hasOwn(properties ?? {}, "name")
86
+ ? defaultName
87
+ : await context.getProperty(target, "name");
88
+ return bind(typeof length === "number" && !Number.isNaN(length)
89
+ ? Math.max(0, Math.trunc(length) - boundArgs.length)
90
+ : 0, typeof name === "string" ? name : "");
91
+ }
92
+ finally {
93
+ release?.();
94
+ }
95
95
  })();
96
96
  }
97
97
  if (methodName === "call") {
@@ -101,26 +101,39 @@ export function callFunctionMethod(target, methodName, args, options, stack, con
101
101
  if (applyArgs === null || applyArgs === undefined) {
102
102
  return options.callClosure(target, [], stack, thisValue);
103
103
  }
104
- if (!Array.isArray(applyArgs)) {
105
- throw new TypeError("Function#apply requires an array or nullish arguments value.");
104
+ if (typeof applyArgs !== "object") {
105
+ throw new TypeError("Function#apply requires an object or nullish arguments value.");
106
106
  }
107
- if (context?.getProperty === undefined)
107
+ if (context?.getProperty === undefined && Array.isArray(applyArgs))
108
108
  return options.callClosure(target, applyArgs, stack, thisValue);
109
109
  return (async () => {
110
+ const budget = options.budget ?? new Budget();
111
+ const invocationContext = {
112
+ ...context,
113
+ stack,
114
+ thisValue: context?.thisValue,
115
+ invokeClosure: context?.invokeClosure ?? ((callee, values, receiver) => Promise.resolve(options.callClosure(callee, values, stack, receiver)))
116
+ };
117
+ const read = (value, key) => {
118
+ if (context?.getProperty !== undefined)
119
+ return context.getProperty(value, key);
120
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
121
+ return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, value, invocationContext);
122
+ };
110
123
  const values = [];
111
- const length = applyArgs.length;
112
- options.budget?.allocateArrayLength(length);
113
- const retained = {};
114
- options.budget?.setRetainedValues(retained, () => values);
124
+ const release = retainValues(budget, () => [applyArgs, ...values]);
115
125
  try {
126
+ const number = await sandboxNumber(await read(applyArgs, "length"), budget, invocationContext);
127
+ const length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
128
+ budget.allocateArrayLength(length);
116
129
  for (let index = 0; index < length; index++) {
117
- options.budget?.visitNode();
118
- values.push(await context.getProperty(applyArgs, index));
130
+ budget.visitNode();
131
+ values.push(await read(applyArgs, String(index)));
119
132
  }
120
133
  return await options.callClosure(target, values, stack, thisValue);
121
134
  }
122
135
  finally {
123
- options.budget?.setRetainedValues(retained, undefined);
136
+ release();
124
137
  }
125
138
  })();
126
139
  }
@@ -1,3 +1,6 @@
1
- import { type SandboxGenerator, type SandboxValue } from "../values.js";
1
+ import { type SandboxCallContext, type SandboxGenerator, type SandboxValue } from "../values.js";
2
2
  import type { Budget } from "../budget.js";
3
+ type GeneratorMethodName = "next" | "return" | "throw";
3
4
  export declare function getGeneratorMember(target: SandboxGenerator, property: string | number, budget: Budget): SandboxValue | undefined;
5
+ export declare function callGeneratorMethod(target: SandboxValue, method: GeneratorMethodName, value: SandboxValue, budget: Budget, context: SandboxCallContext | undefined, async: boolean): SandboxValue | Promise<SandboxValue>;
6
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { generatorIterator } from "../iteration.js";
2
- import { allocateProducedSandboxValue, createSandboxClosure, createSandboxPromise } from "../values.js";
2
+ import { allocateProducedSandboxValue, createSandboxClosure, createSandboxPromise, isSandboxGenerator } from "../values.js";
3
3
  const generatorMethodNames = new Set(["next", "return", "throw"]);
4
4
  export function getGeneratorMember(target, property, budget) {
5
5
  if (typeof property !== "string" || !generatorMethodNames.has(property)) {
@@ -8,10 +8,16 @@ export function getGeneratorMember(target, property, budget) {
8
8
  return createSandboxClosure({
9
9
  sandbox: true,
10
10
  name: property,
11
- call: ([value], context) => {
12
- const iterator = generatorIterator(target, budget, context);
13
- const result = Promise.resolve(iterator[property](value)).then(result => allocateProducedSandboxValue({ value: result.value, done: result.done === true }, budget));
14
- return target.async ? createSandboxPromise(result) : result;
15
- }
11
+ call: ([value], context) => callGeneratorMethod(target, property, value, budget, context, target.async === true)
16
12
  });
17
13
  }
14
+ export function callGeneratorMethod(target, method, value, budget, context, async) {
15
+ const result = (async () => {
16
+ if (!isSandboxGenerator(target) || (target.async === true) !== async)
17
+ throw new TypeError(`${async ? "AsyncGenerator" : "Generator"}.${method} requires a matching generator receiver.`);
18
+ const iterator = generatorIterator(target, budget, context);
19
+ const result = await iterator[method](value);
20
+ return allocateProducedSandboxValue({ value: result.value, done: result.done === true }, budget);
21
+ })();
22
+ return async ? createSandboxPromise(result) : result;
23
+ }
@@ -1,11 +1,14 @@
1
1
  import { assertSandboxDataDepth } from "../graph-depth.js";
2
2
  import { getGeneratorProperties } from "./generator-properties.js";
3
+ import { generatorPrototypes } from "./generator-prototypes.js";
3
4
  import { runResources } from "./resources.js";
4
5
  import { getIntrinsicIdentity, registerBuiltinIdentities, releaseIntrinsicIdentities } from "./intrinsics.js";
5
6
  import { releaseTemplateObjects } from "./template-objects.js";
6
7
  import { isSandboxDate } from "./date.js";
7
8
  import { retainedAccessorClosures } from "./accessors.js";
8
9
  import { getHostObjectMember, isGuestHostObject, isLiveCapability } from "./host-capabilities.js";
10
+ import { errorPrototypes } from "./error-prototypes.js";
11
+ import { sandboxErrorTypes } from "../error/shape.js";
9
12
  import { boxedValue, isSandboxBox } from "./boxed.js";
10
13
  import { isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, getPromiseProperties, isSandboxRegex, getRegexProperties, getCollectionProperties, isSandboxSet } from "./values.js";
11
14
  const guestClosures = new WeakSet();
@@ -271,12 +274,22 @@ export function releaseObjectPrototype(budget) {
271
274
  datePrototypes.delete(budget);
272
275
  arrayPrototypes.delete(budget);
273
276
  functionPrototypes.delete(budget);
277
+ generatorPrototypes.delete(budget);
278
+ errorPrototypes.delete(budget);
274
279
  initialRegexDescriptors.delete(budget);
275
280
  intrinsicPrototypes.delete(budget);
276
281
  }
277
282
  export function getSandboxPrototype(value, budget) {
278
283
  if (prototypes.has(value))
279
284
  return prototypes.get(value) ?? null;
285
+ // Host transport records are data-only. Resolve their default prototype in
286
+ // the receiving realm without persisting executable intrinsic graphs.
287
+ const errorType = sandboxErrorTypes.get(value);
288
+ if (budget !== undefined && errorType !== undefined) {
289
+ const prototype = errorPrototypes.get(budget)?.get(errorType);
290
+ if (prototype !== undefined)
291
+ return prototype;
292
+ }
280
293
  if (budget !== undefined && isGuestClosure(value) && runResources.getStore()?.functionSourceText !== false)
281
294
  return functionPrototypes.get(budget) ?? null;
282
295
  if (budget !== undefined && Array.isArray(value))
@@ -1,5 +1,6 @@
1
1
  import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
2
2
  import { internalSymbols } from "./internal-symbols.js";
3
+ import { getIntrinsicIdentity } from "./intrinsics.js";
3
4
  import { getGeneratorProperties } from "./generator-properties.js";
4
5
  import { getRegexProperties, regexGuestProperties } from "./regexp-properties.js";
5
6
  import { getCollectionProperties, collectionGuestProperties, copyCollectionProperties } from "./collection-properties.js";
@@ -24,7 +25,7 @@ import { invokeCancelableClosure, readPromiseCancellation, registerPromiseCancel
24
25
  import { parseRegex } from "./regex/parse.js";
25
26
  import { assertSandboxDataDepth } from "../graph-depth.js";
26
27
  import { sandboxErrorTypes } from "../error/shape.js";
27
- import { getGuestFunctionProperties, getSandboxPrototype, hasGuestObjectState, hasManagedDescriptors, hasNullObjectPrototype, isGuestClosure, isIntrinsicFunction, registerGuestClosure, setSandboxPrototype } from "./object-model.js";
28
+ import { getGuestFunctionProperties, getSandboxPrototype, hasExplicitSandboxPrototype, hasGuestObjectState, hasManagedDescriptors, hasNullObjectPrototype, isGuestClosure, isIntrinsicFunction, registerGuestClosure, setSandboxPrototype } from "./object-model.js";
28
29
  import { copySandboxArgumentProperties, createSandboxArguments, getSandboxArgumentEntries, isSandboxArguments } from "./arguments.js";
29
30
  export { createSandboxArguments, isSandboxArguments } from "./arguments.js";
30
31
  export { isSandboxMap, isSandboxSet } from "./collection-brands.js";
@@ -578,7 +579,7 @@ export function measureSandboxData(values, options = {}) {
578
579
  if (descriptor !== undefined)
579
580
  descriptors.push([key, descriptor]);
580
581
  }
581
- const includeNonEnumerable = isSandboxDate(value) || hasManagedDescriptors(value);
582
+ const includeNonEnumerable = isSandboxDate(value) || sandboxErrorTypes.has(value) || hasManagedDescriptors(value);
582
583
  for (const [key, descriptor] of descriptors) {
583
584
  if (!descriptor.enumerable && !includeNonEnumerable)
584
585
  continue;
@@ -908,6 +909,50 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
908
909
  }
909
910
  if (nodeTypes.isProxy(value))
910
911
  throw new TypeError("Unsupported proxy sandbox value.");
912
+ if (sandboxErrorTypes.has(value) && hasExplicitSandboxPrototype(value)) {
913
+ const prototype = getSandboxPrototype(value);
914
+ let nativePrototype = null;
915
+ if (prototype !== null) {
916
+ const identity = getIntrinsicIdentity(prototype);
917
+ const nativePrototypes = {
918
+ Error: Error.prototype, TypeError: TypeError.prototype, RangeError: RangeError.prototype,
919
+ ReferenceError: ReferenceError.prototype, SyntaxError: SyntaxError.prototype,
920
+ URIError: URIError.prototype, EvalError: EvalError.prototype, AggregateError: AggregateError.prototype
921
+ };
922
+ const path = identity === undefined ? [] : JSON.parse(identity);
923
+ if (path.length !== 2 || typeof path[0] !== "string" || path[1] !== "prototype" || !Object.hasOwn(nativePrototypes, path[0]))
924
+ throw new TypeError("Custom Error prototype links cannot be copied as data.");
925
+ nativePrototype = nativePrototypes[path[0]];
926
+ let current = prototype;
927
+ let prototypeDepth = 0;
928
+ while (current !== null) {
929
+ assertSandboxDataDepth(++prototypeDepth);
930
+ const objectPrototype = getIntrinsicIdentity(current) === '["Object","prototype"]';
931
+ const owner = objectPrototype ? Object.getOwnPropertyDescriptor(current, "constructor")?.value : current;
932
+ if (owner === null || typeof owner !== "object" ||
933
+ (objectPrototype && getIntrinsicIdentity(owner) !== '["Object"]') || hasGuestObjectState(owner))
934
+ throw new TypeError("Modified Error prototype links cannot be copied as data.");
935
+ current = getSandboxPrototype(current);
936
+ }
937
+ }
938
+ const existing = state.seen.get(value);
939
+ if (existing !== undefined)
940
+ return existing;
941
+ const descriptors = Reflect.ownKeys(value).filter(key => typeof key !== "symbol" || !internalSymbols.has(key))
942
+ .map(key => [key, Object.getOwnPropertyDescriptor(value, key)]);
943
+ if (descriptors.some(([, descriptor]) => !("value" in descriptor)))
944
+ throw new TypeError("Error accessor properties cannot be copied as data.");
945
+ const copy = new Error();
946
+ delete copy.stack;
947
+ Object.setPrototypeOf(copy, nativePrototype);
948
+ state.seen.set(value, copy);
949
+ for (const [key, descriptor] of descriptors)
950
+ Object.defineProperty(copy, key, { ...descriptor,
951
+ value: copyFromSandbox(descriptor.value, state, joinPath(path, key), options, depth + 1) });
952
+ if (!Object.isExtensible(value))
953
+ Object.preventExtensions(copy);
954
+ return copy;
955
+ }
911
956
  if (!isSandboxClosure(value) && hasGuestObjectState(value)) {
912
957
  throw new TypeError("Guest prototype links and custom descriptors cannot be copied as data.");
913
958
  }