poe-code 14.0.79 → 14.0.81

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 (47) hide show
  1. package/dist/index.js +772 -341
  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-B3AL4KJ3.js → chunk-2LNBLFJ3.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-BGSPSHLP.js → chunk-ZSYBRZU6.js} +644 -292
  7. package/packages/safe-js/dist/chunks/chunk-ZSYBRZU6.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/graph-depth.js +2 -1
  11. package/packages/safe-js/dist/index.js +2 -2
  12. package/packages/safe-js/dist/interp/async.d.ts +1 -1
  13. package/packages/safe-js/dist/interp/async.js +65 -43
  14. package/packages/safe-js/dist/interp/bound-function-state.d.ts +7 -0
  15. package/packages/safe-js/dist/interp/bound-function-state.js +1 -0
  16. package/packages/safe-js/dist/interp/bound-function.d.ts +4 -0
  17. package/packages/safe-js/dist/interp/bound-function.js +18 -0
  18. package/packages/safe-js/dist/interp/generator-properties.d.ts +3 -0
  19. package/packages/safe-js/dist/interp/generator-properties.js +9 -0
  20. package/packages/safe-js/dist/interp/generator-prototypes.d.ts +6 -0
  21. package/packages/safe-js/dist/interp/generator-prototypes.js +1 -0
  22. package/packages/safe-js/dist/interp/globals/function.d.ts +2 -0
  23. package/packages/safe-js/dist/interp/globals/function.js +32 -0
  24. package/packages/safe-js/dist/interp/globals/generator.d.ts +2 -0
  25. package/packages/safe-js/dist/interp/globals/generator.js +51 -0
  26. package/packages/safe-js/dist/interp/globals/object-array.js +28 -7
  27. package/packages/safe-js/dist/interp/globals/object.js +2 -1
  28. package/packages/safe-js/dist/interp/globals.d.ts +1 -0
  29. package/packages/safe-js/dist/interp/globals.js +4 -0
  30. package/packages/safe-js/dist/interp/instanceof.d.ts +4 -0
  31. package/packages/safe-js/dist/interp/instanceof.js +58 -0
  32. package/packages/safe-js/dist/interp/interpreter.js +16 -47
  33. package/packages/safe-js/dist/interp/iteration.js +76 -5
  34. package/packages/safe-js/dist/interp/methods/function.d.ts +5 -2
  35. package/packages/safe-js/dist/interp/methods/function.js +55 -42
  36. package/packages/safe-js/dist/interp/methods/generator.d.ts +4 -1
  37. package/packages/safe-js/dist/interp/methods/generator.js +12 -6
  38. package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
  39. package/packages/safe-js/dist/interp/object-model.js +69 -17
  40. package/packages/safe-js/dist/interp/string-coercion.js +3 -2
  41. package/packages/safe-js/dist/interp/values.js +21 -3
  42. package/packages/safe-js/dist/snapshot/guest-heap-validation.js +27 -3
  43. package/packages/safe-js/dist/snapshot/guest-heap.d.ts +9 -0
  44. package/packages/safe-js/dist/snapshot/guest-heap.js +11 -0
  45. package/packages/safe-js/dist/snapshot/restore.js +61 -7
  46. package/packages/safe-js/dist/chunks/chunk-BGSPSHLP.js.map +0 -7
  47. /package/packages/safe-js/dist/chunks/{chunk-B3AL4KJ3.js.map → chunk-2LNBLFJ3.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-B3AL4KJ3.js";
25
+ } from "./chunks/chunk-2LNBLFJ3.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-BGSPSHLP.js";
37
+ } from "./chunks/chunk-ZSYBRZU6.js";
38
38
  import "./chunks/chunk-M2DLCGEF.js";
39
39
  import "./chunks/chunk-Q7USUEL7.js";
40
40
  import "./chunks/chunk-4YIDX44G.js";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-BGSPSHLP.js";
8
+ } from "./chunks/chunk-ZSYBRZU6.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -7,6 +7,7 @@ import { regexpIteratorState, isSandboxRegExpIterator } from "./interp/regexp-it
7
7
  import { isSandboxMap, isSandboxSet } from "./interp/collection-brands.js";
8
8
  import { boxedDataProperties, isSandboxBox } from "./interp/boxed.js";
9
9
  import { regexGuestProperties } from "./interp/regexp-properties.js";
10
+ import { generatorGuestProperties } from "./interp/generator-properties.js";
10
11
  export const MAX_DATA_DEPTH = 1_024;
11
12
  export class SnapshotBudgetError extends Error {
12
13
  code = "budgetExceeded";
@@ -67,7 +68,7 @@ function walkGraphDepth(root, rootPath, assertDepth) {
67
68
  }
68
69
  }
69
70
  function graphEntries(value) {
70
- const properties = regexGuestProperties.get(value);
71
+ const properties = regexGuestProperties.get(value) ?? generatorGuestProperties.get(value);
71
72
  if (properties !== undefined)
72
73
  return Reflect.ownKeys(properties).flatMap(key => {
73
74
  const descriptor = Object.getOwnPropertyDescriptor(properties, key);
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-B3AL4KJ3.js";
29
+ } from "./chunks/chunk-2LNBLFJ3.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-BGSPSHLP.js";
53
+ } from "./chunks/chunk-ZSYBRZU6.js";
54
54
  import "./chunks/chunk-M2DLCGEF.js";
55
55
  import "./chunks/chunk-Q7USUEL7.js";
56
56
  import "./chunks/chunk-4YIDX44G.js";
@@ -70,7 +70,7 @@ export type EvaluateAsyncNode = (node: ParseResult, context: AsyncEvaluationCont
70
70
  export declare function emitResumeBreakpoint(context: AsyncEvaluationContext, breakpoint: ResumeBreakpoint): void;
71
71
  export declare function evaluateArrowFunctionExpression(node: ArrowFunctionExpression, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode): Promise<AsyncEvaluationResult>;
72
72
  export declare function evaluateFunctionExpression(node: FunctionExpression, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode): Promise<AsyncEvaluationResult>;
73
- export declare function createInterpretedClosure(node: ArrowFunctionExpression | FunctionDeclaration | FunctionExpression, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode, homeObject?: SandboxObject | SandboxClosure): SandboxClosure;
73
+ export declare function createInterpretedClosure(node: ArrowFunctionExpression | FunctionDeclaration | FunctionExpression, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode, homeObject?: SandboxObject | SandboxClosure, initializeGeneratorPrototype?: boolean): SandboxClosure;
74
74
  export declare function executeAsyncFunction(execute: (onSuspend: () => void) => Promise<SandboxValue>, budget: Budget, signal?: AbortSignal, callContext?: SandboxCallContext): import("./values.js").SandboxPromise;
75
75
  export declare function evaluateAwaitExpression(node: AwaitExpression, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode): Promise<AsyncEvaluationResult>;
76
76
  export declare function executeClosure(node: ArrowFunctionExpression | FunctionDeclaration | FunctionExpression, args: readonly SandboxValue[], thisValue: SandboxValue, context: AsyncEvaluationContext, evaluateNode: EvaluateAsyncNode): Promise<SandboxValue>;
@@ -7,7 +7,9 @@ import { CompileScope } from "./regex/compile-guard.js";
7
7
  import { awaitSandboxValue } from "./cancel.js";
8
8
  import { hoistVarDeclarations } from "./var-hoist.js";
9
9
  import { createCoercionContext, createPatternContext } from "./interpreter.js";
10
- import { getGuestFunctionProperty, setSandboxPrototype } from "./object-model.js";
10
+ import { getGuestFunctionProperty, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "./object-model.js";
11
+ import { generatorPrototypes } from "./generator-prototypes.js";
12
+ import { retainValues, runResources } from "./resources.js";
11
13
  import { functionSources } from "../parse/function-source.js";
12
14
  import { registerClosureOrigin, registerGeneratorOrigin } from "./closure-origin.js";
13
15
  import { boundIdentifiers, containsParameterExpression, getFunctionLength, hoistedVarDeclarations } from "../parse/bindings.js";
@@ -42,12 +44,12 @@ export async function evaluateFunctionExpression(node, context, evaluateNode) {
42
44
  value: closure
43
45
  };
44
46
  }
45
- export function createInterpretedClosure(node, context, evaluateNode, homeObject) {
47
+ export function createInterpretedClosure(node, context, evaluateNode, homeObject, initializeGeneratorPrototype = true) {
46
48
  if (node.type !== "ArrowFunctionExpression") {
47
49
  context = { ...context, functionEnvironment: { homeObject } };
48
50
  }
49
51
  if (node.type !== "ArrowFunctionExpression" && node.generator) {
50
- return createGeneratorClosure(node, context, evaluateNode);
52
+ return createGeneratorClosure(node, context, evaluateNode, initializeGeneratorPrototype);
51
53
  }
52
54
  const construct = node.type !== "ArrowFunctionExpression" &&
53
55
  !(node.type === "FunctionExpression" && node.method === true) &&
@@ -123,7 +125,9 @@ export function executeAsyncFunction(execute, budget, signal, callContext) {
123
125
  });
124
126
  return createSandboxPromise(promise, { synchronousPrefix });
125
127
  }
126
- function createGeneratorClosure(node, context, evaluateNode) {
128
+ function createGeneratorClosure(node, context, evaluateNode, initializePrototype) {
129
+ const prototypes = !initializePrototype || runResources.getStore()?.functionSourceText === false ? undefined
130
+ : generatorPrototypes.get(context.budget)?.get(node.async === true);
127
131
  const closure = createSandboxClosure({
128
132
  sourceRange: functionSources.get(node),
129
133
  guest: true,
@@ -133,48 +137,66 @@ function createGeneratorClosure(node, context, evaluateNode) {
133
137
  ...(node.id === undefined ? { name: context.inferredName } : { name: node.id.name }),
134
138
  retainedValues: () => [...context.scope.retainedValues(), context.functionEnvironment?.homeObject, context.functionEnvironment?.newTarget],
135
139
  call: async (args, callContext) => {
136
- const closureContext = {
137
- ...context,
138
- compilation: callContext?.compilation ?? context.compilation,
139
- callStack: [...(callContext?.stack ?? context.callStack)]
140
- };
141
- const scope = await createClosureScope(node, args, callContext?.thisValue, closureContext, evaluateNode);
142
- const channel = createGeneratorChannel((generatorYield) => {
143
- const execute = async () => {
144
- const result = await evaluateNode(node.body, {
145
- ...closureContext,
146
- functionBody: node.body,
147
- asyncGenerator: node.async,
148
- generatorBlockScopes: new Map(),
149
- generatorExpressionStates: new Map(),
150
- captureGeneratorScope: (suspendedScope, blocks, completions, expressions) => {
151
- origin.suspendedScope = suspendedScope;
152
- origin.blockScopes = blocks;
153
- origin.finallyCompletions = completions;
154
- origin.expressionStates = expressions;
155
- },
156
- generatorYield: (value, yieldNodeId) => {
157
- generator.state = "suspended";
158
- return generatorYield(value, yieldNodeId);
159
- },
160
- scope
161
- });
162
- if (result.kind === "error") {
163
- throw result.error;
164
- }
165
- if (result.kind === "throw") {
166
- throw result.value;
167
- }
168
- const value = result.hasValue ? result.value : undefined;
169
- return node.async ? awaitSandboxValue(value, context.signal, context.budget, createCoercionContext(context)) : value;
140
+ // Native generators select their instance prototype before initializing parameters.
141
+ const candidate = prototypes === undefined ? undefined : getGuestFunctionProperty(closure, "prototype");
142
+ const prototype = typeof candidate === "object" && candidate !== null ? candidate : prototypes?.instancePrototype;
143
+ const releasePrototype = prototype === undefined ? undefined : retainValues(context.budget, () => [prototype]);
144
+ try {
145
+ const closureContext = {
146
+ ...context,
147
+ compilation: callContext?.compilation ?? context.compilation,
148
+ callStack: [...(callContext?.stack ?? context.callStack)]
170
149
  };
171
- return node.async ? runAsyncPrefix(execute) : execute();
172
- });
173
- const generator = createSandboxGenerator(channel, { async: node.async });
174
- const origin = registerGeneratorOrigin(generator, node, scope, closureContext);
175
- return generator;
150
+ const scope = await createClosureScope(node, args, callContext?.thisValue, closureContext, evaluateNode);
151
+ const channel = createGeneratorChannel((generatorYield) => {
152
+ const execute = async () => {
153
+ const result = await evaluateNode(node.body, {
154
+ ...closureContext,
155
+ functionBody: node.body,
156
+ asyncGenerator: node.async,
157
+ generatorBlockScopes: new Map(),
158
+ generatorExpressionStates: new Map(),
159
+ captureGeneratorScope: (suspendedScope, blocks, completions, expressions) => {
160
+ origin.suspendedScope = suspendedScope;
161
+ origin.blockScopes = blocks;
162
+ origin.finallyCompletions = completions;
163
+ origin.expressionStates = expressions;
164
+ },
165
+ generatorYield: (value, yieldNodeId) => {
166
+ generator.state = "suspended";
167
+ return generatorYield(value, yieldNodeId);
168
+ },
169
+ scope
170
+ });
171
+ if (result.kind === "error") {
172
+ throw result.error;
173
+ }
174
+ if (result.kind === "throw") {
175
+ throw result.value;
176
+ }
177
+ const value = result.hasValue ? result.value : undefined;
178
+ return node.async ? awaitSandboxValue(value, context.signal, context.budget, createCoercionContext(context)) : value;
179
+ };
180
+ return node.async ? runAsyncPrefix(execute) : execute();
181
+ });
182
+ const generator = createSandboxGenerator(channel, { async: node.async });
183
+ if (prototype !== undefined)
184
+ setSandboxPrototype(generator, prototype, context.budget);
185
+ const origin = registerGeneratorOrigin(generator, node, scope, closureContext);
186
+ return generator;
187
+ }
188
+ finally {
189
+ releasePrototype?.();
190
+ }
176
191
  }
177
192
  });
193
+ if (prototypes !== undefined) {
194
+ const prototype = Object.create(null);
195
+ markDescriptorObject(prototype);
196
+ setSandboxPrototype(prototype, prototypes.instancePrototype);
197
+ Object.defineProperty(materializeFunctionProperties(closure), "prototype", { value: prototype, writable: true });
198
+ setSandboxPrototype(closure, prototypes.functionPrototype);
199
+ }
178
200
  registerClosureOrigin(closure, node, context);
179
201
  return closure;
180
202
  }
@@ -0,0 +1,7 @@
1
+ import type { SandboxClosure, SandboxValue } from "./values.js";
2
+ export type BoundFunctionState = {
3
+ target: SandboxClosure;
4
+ thisValue: SandboxValue;
5
+ args: SandboxValue[];
6
+ };
7
+ export declare const boundFunctionStates: WeakMap<object, BoundFunctionState>;
@@ -0,0 +1 @@
1
+ export const boundFunctionStates = new WeakMap();
@@ -0,0 +1,4 @@
1
+ import { type SandboxClosure } from "./values.js";
2
+ import { type BoundFunctionState } from "./bound-function-state.js";
3
+ import type { FunctionMethodOptions } from "./methods/function.js";
4
+ export declare function createBoundFunction(state: BoundFunctionState, name: string | undefined, length: number | undefined, callClosure: FunctionMethodOptions["callClosure"]): SandboxClosure;
@@ -0,0 +1,18 @@
1
+ import { createSandboxClosure } from "./values.js";
2
+ import { boundFunctionStates } from "./bound-function-state.js";
3
+ export function createBoundFunction(state, name, length, callClosure) {
4
+ const bound = createSandboxClosure({
5
+ guest: true,
6
+ sandbox: true,
7
+ name,
8
+ length,
9
+ boundTarget: state.target,
10
+ retainedValues: () => [state.target, state.thisValue, ...state.args, bound.name],
11
+ call: (args, context) => callClosure(state.target, [...state.args, ...args], context?.stack ?? [], state.thisValue),
12
+ ...(state.target.construct === undefined ? {} : {
13
+ construct: (args, context) => callClosure(state.target, [...state.args, ...args], context?.stack ?? [], undefined, true, context?.newTarget === bound ? state.target : context?.newTarget)
14
+ })
15
+ });
16
+ boundFunctionStates.set(bound, state);
17
+ return bound;
18
+ }
@@ -0,0 +1,3 @@
1
+ import type { SandboxGenerator, SandboxObject } from "./values.js";
2
+ export declare const generatorGuestProperties: WeakMap<object, SandboxObject>;
3
+ export declare function getGeneratorProperties(value: SandboxGenerator): SandboxObject;
@@ -0,0 +1,9 @@
1
+ export const generatorGuestProperties = new WeakMap();
2
+ export function getGeneratorProperties(value) {
3
+ let properties = generatorGuestProperties.get(value);
4
+ if (properties === undefined) {
5
+ properties = Object.create(null);
6
+ generatorGuestProperties.set(value, properties);
7
+ }
8
+ return properties;
9
+ }
@@ -0,0 +1,6 @@
1
+ import type { Budget } from "./budget.js";
2
+ import type { SandboxObject } from "./values.js";
3
+ export declare const generatorPrototypes: WeakMap<Budget, Map<boolean, {
4
+ functionPrototype: SandboxObject;
5
+ instancePrototype: SandboxObject;
6
+ }>>;
@@ -0,0 +1 @@
1
+ export const generatorPrototypes = new WeakMap();
@@ -0,0 +1,2 @@
1
+ import type { Budget } from "../budget.js";
2
+ export declare function createFunctionPrototype(budget: Budget, installHasInstance?: boolean): void;
@@ -0,0 +1,32 @@
1
+ import { invokeBuiltinClosure } from "../builtin-call.js";
2
+ import { callFunctionMethod } from "../methods/function.js";
3
+ import { getSandboxPrototype, installFunctionPrototype, materializeFunctionProperties, registerIntrinsicFunction, setSandboxPrototype } from "../object-model.js";
4
+ import { createSandboxClosure } from "../values.js";
5
+ import { ordinaryHasInstance } from "../instanceof.js";
6
+ export function createFunctionPrototype(budget, installHasInstance = true) {
7
+ const prototype = createSandboxClosure({ guest: true, sandbox: true, name: "", length: 0, call: () => undefined });
8
+ const properties = materializeFunctionProperties(prototype);
9
+ // Invocation support does not grant the host's dynamic source constructor.
10
+ Object.defineProperty(properties, "constructor", { value: undefined, writable: true, configurable: true });
11
+ for (const [name, length] of [["call", 1], ["apply", 2], ["bind", 1], ["toString", 0]]) {
12
+ Object.defineProperty(properties, name, { writable: true, configurable: true,
13
+ value: createSandboxClosure({ guest: true, sandbox: true, name, length,
14
+ call: (args, context) => callFunctionMethod(context?.thisValue, name, args, {
15
+ budget,
16
+ callClosure: (target, values, stack, thisValue, construct, newTarget) => context?.invokeClosure !== undefined
17
+ ? context.invokeClosure(target, values, thisValue, construct, newTarget)
18
+ : invokeBuiltinClosure(target, values, budget, { ...context, stack, thisValue, newTarget }, thisValue, construct)
19
+ }, context?.stack ?? [], context)
20
+ })
21
+ });
22
+ }
23
+ const hasInstance = installHasInstance ? createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.hasInstance]", length: 1,
24
+ call: ([value], context) => ordinaryHasInstance(value, context?.thisValue, budget, context)
25
+ }) : undefined;
26
+ if (hasInstance !== undefined)
27
+ Object.defineProperty(properties, Symbol.hasInstance, { value: hasInstance });
28
+ setSandboxPrototype(prototype, getSandboxPrototype(Object.create(null), budget));
29
+ installFunctionPrototype(budget, prototype);
30
+ if (hasInstance !== undefined)
31
+ registerIntrinsicFunction(budget, hasInstance);
32
+ }
@@ -0,0 +1,2 @@
1
+ import type { Budget } from "../budget.js";
2
+ export declare function createGeneratorPrototypes(budget: Budget): void;
@@ -0,0 +1,51 @@
1
+ import { generatorPrototypes } from "../generator-prototypes.js";
2
+ import { registerBuiltinIdentities, resolveIntrinsicIdentity } from "../intrinsics.js";
3
+ import { callGeneratorMethod } from "../methods/generator.js";
4
+ import { getSandboxPrototype, registerIntrinsicFunction, registerIntrinsicObject, setSandboxPrototype } from "../object-model.js";
5
+ import { createSandboxClosure } from "../values.js";
6
+ export function createGeneratorPrototypes(budget) {
7
+ const asyncIteratorPrototype = Object.create(null);
8
+ const asyncIterator = createSandboxClosure({ guest: true, sandbox: true,
9
+ name: "[Symbol.asyncIterator]", length: 0, call: (_args, context) => context?.thisValue });
10
+ Object.defineProperty(asyncIteratorPrototype, Symbol.asyncIterator, {
11
+ value: asyncIterator, writable: true, configurable: true
12
+ });
13
+ setSandboxPrototype(asyncIteratorPrototype, getSandboxPrototype(Object.create(null), budget));
14
+ registerBuiltinIdentities(budget, { "%AsyncIteratorPrototype%": asyncIteratorPrototype });
15
+ registerIntrinsicObject(budget, asyncIteratorPrototype);
16
+ registerIntrinsicFunction(budget, asyncIterator);
17
+ const state = new Map();
18
+ for (const async of [false, true]) {
19
+ const tag = async ? "AsyncGenerator" : "Generator";
20
+ const functionPrototype = Object.create(null);
21
+ const instancePrototype = Object.create(null);
22
+ setSandboxPrototype(functionPrototype, resolveIntrinsicIdentity(budget, JSON.stringify(["%FunctionPrototype%"])));
23
+ setSandboxPrototype(instancePrototype, async ? asyncIteratorPrototype
24
+ : resolveIntrinsicIdentity(budget, JSON.stringify(["%IteratorPrototype%"])));
25
+ Object.defineProperties(functionPrototype, {
26
+ prototype: { value: instancePrototype, configurable: true },
27
+ // Do not expose native dynamic-source constructors through this graph.
28
+ constructor: { value: undefined, configurable: true },
29
+ [Symbol.toStringTag]: { value: `${tag}Function`, configurable: true }
30
+ });
31
+ Object.defineProperties(instancePrototype, {
32
+ constructor: { value: functionPrototype, configurable: true },
33
+ [Symbol.toStringTag]: { value: tag, configurable: true }
34
+ });
35
+ for (const method of ["next", "return", "throw"]) {
36
+ Object.defineProperty(instancePrototype, method, { writable: true, configurable: true,
37
+ value: createSandboxClosure({ guest: true, sandbox: true, name: method, length: 1,
38
+ call: ([value], context) => callGeneratorMethod(context?.thisValue, method, value, budget, context, async)
39
+ })
40
+ });
41
+ }
42
+ registerBuiltinIdentities(budget, {
43
+ [`%${tag}Prototype%`]: instancePrototype,
44
+ [`%${tag}FunctionPrototype%`]: functionPrototype
45
+ });
46
+ registerIntrinsicObject(budget, functionPrototype);
47
+ registerIntrinsicObject(budget, instancePrototype);
48
+ state.set(async, { functionPrototype, instancePrototype });
49
+ }
50
+ generatorPrototypes.set(budget, state);
51
+ }
@@ -1,4 +1,5 @@
1
1
  import { isFatalSandboxError } from "../budget.js";
2
+ import { getGeneratorProperties } from "../generator-properties.js";
2
3
  import { accessorAdapter, accessorClosure, readPropertyDescriptor, retainedAccessorClosures } from "../accessors.js";
3
4
  import { invokeBuiltinClosure } from "../builtin-call.js";
4
5
  import { createDataCheckpoint } from "../data-checkpoint.js";
@@ -19,7 +20,7 @@ import { toPropertyKey } from "../property-key.js";
19
20
  import { createNumericParsers } from "./numeric-parsers.js";
20
21
  import { createPrimitiveConstructor } from "./primitives.js";
21
22
  import { arrayMethodNames, callArrayMethod } from "../methods/array.js";
22
- 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";
23
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";
24
25
  export function createObjectArrayGlobals(options) {
25
26
  return {
@@ -180,14 +181,14 @@ export function createObjectArrayGlobals(options) {
180
181
  call: ([value]) => {
181
182
  if (isGuestHostObject(value))
182
183
  throw new TypeError("Live host objects cannot be made non-extensible.");
183
- Object.preventExtensions(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
184
+ Object.preventExtensions(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
184
185
  return value;
185
186
  },
186
187
  name: "preventExtensions"
187
188
  }),
188
189
  isExtensible: createSandboxClosure({
189
190
  sandbox: true,
190
- call: ([value]) => Object.isExtensible(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
191
+ call: ([value]) => Object.isExtensible(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
191
192
  name: "isExtensible"
192
193
  }),
193
194
  seal: createSandboxClosure({
@@ -195,14 +196,14 @@ export function createObjectArrayGlobals(options) {
195
196
  call: ([value]) => {
196
197
  if (isGuestHostObject(value))
197
198
  throw new TypeError("Live host objects cannot be sealed.");
198
- Object.seal(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
199
+ Object.seal(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
199
200
  return value;
200
201
  },
201
202
  name: "seal"
202
203
  }),
203
204
  isSealed: createSandboxClosure({
204
205
  sandbox: true,
205
- call: ([value]) => Object.isSealed(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
206
+ call: ([value]) => Object.isSealed(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
206
207
  name: "isSealed"
207
208
  }),
208
209
  freeze: createSandboxClosure({
@@ -211,7 +212,7 @@ export function createObjectArrayGlobals(options) {
211
212
  if (isGuestHostObject(value))
212
213
  throw new TypeError("Live host objects cannot be frozen.");
213
214
  if (typeof value === "object" && value !== null) {
214
- Object.freeze(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
215
+ Object.freeze(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value);
215
216
  }
216
217
  return value;
217
218
  },
@@ -219,7 +220,7 @@ export function createObjectArrayGlobals(options) {
219
220
  }),
220
221
  isFrozen: createSandboxClosure({
221
222
  sandbox: true,
222
- call: ([value]) => Object.isFrozen(isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
223
+ call: ([value]) => Object.isFrozen(isSandboxGenerator(value) ? getGeneratorProperties(value) : isSandboxPromise(value) ? getPromiseProperties(value) : isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : isSandboxMap(value) || isSandboxSet(value) ? getCollectionProperties(value) : value),
223
224
  name: "isFrozen"
224
225
  }),
225
226
  assign: createSandboxClosure({
@@ -331,6 +332,21 @@ function createArrayGlobal(budget) {
331
332
  guest: true, sandbox: true, name: "[Symbol.iterator]", length: 0,
332
333
  call: (_args, context) => context?.thisValue
333
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
+ });
334
350
  setSandboxPrototype(iterablePrototype, getSandboxPrototype(Object.create(null), budget));
335
351
  setSandboxPrototype(iteratorPrototype, iterablePrototype);
336
352
  Object.defineProperties(iteratorPrototype, {
@@ -340,6 +356,9 @@ function createArrayGlobal(budget) {
340
356
  [Symbol.toStringTag]: { value: "Array Iterator", configurable: true }
341
357
  });
342
358
  registerBuiltinIdentities(budget, { "%ArrayIteratorPrototype%": iteratorPrototype, "%IteratorPrototype%": iterablePrototype });
359
+ registerIntrinsicFunction(budget, iterablePrototype[Symbol.iterator]);
360
+ registerIntrinsicFunction(budget, iteratorTagGetter);
361
+ registerIntrinsicFunction(budget, iteratorTagSetter);
343
362
  registerIntrinsicObject(budget, iterablePrototype);
344
363
  registerIntrinsicObject(budget, iteratorPrototype);
345
364
  for (const method of ["keys", "values", "entries"]) {
@@ -556,6 +575,8 @@ function reflectionProperties(value) {
556
575
  return objectProperties(value);
557
576
  }
558
577
  export function objectProperties(value, mutable = false) {
578
+ if (isSandboxGenerator(value))
579
+ return getGeneratorProperties(value);
559
580
  if (isSandboxPromise(value))
560
581
  return getPromiseProperties(value);
561
582
  if (isSandboxMap(value) || isSandboxSet(value))
@@ -1,4 +1,5 @@
1
1
  import { assertSandboxDataDepth } from "../../graph-depth.js";
2
+ import { getGeneratorProperties } from "../generator-properties.js";
2
3
  import { readPropertyDescriptor } from "../accessors.js";
3
4
  import { isSandboxArguments } from "../arguments.js";
4
5
  import { isSandboxDate } from "../date.js";
@@ -153,7 +154,7 @@ export function hasOwnSandboxProperty(value, key, enumerable) {
153
154
  else if (isSandboxPromise(value))
154
155
  properties = getPromiseProperties(value);
155
156
  else if (isSandboxGenerator(value))
156
- return false;
157
+ properties = getGeneratorProperties(value);
157
158
  else if (isSandboxRegex(value))
158
159
  properties = getRegexProperties(value);
159
160
  else
@@ -3,6 +3,7 @@ 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;
6
7
  }): {
7
8
  RegExp: import("./values.js").SandboxClosure;
8
9
  Promise: import("./values.js").SandboxClosure;
@@ -7,6 +7,8 @@ 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
+ import { createFunctionPrototype } from "./globals/function.js";
11
+ import { createGeneratorPrototypes } from "./globals/generator.js";
10
12
  import { createPromiseGlobals } from "./promise.js";
11
13
  import { createDateGlobal } from "./globals/date.js";
12
14
  import { createSymbolGlobal } from "./globals/symbol.js";
@@ -28,6 +30,8 @@ export function createBuiltinBindings(options) {
28
30
  ...createPromiseGlobals(options),
29
31
  ...createRegexGlobals(options)
30
32
  };
33
+ createFunctionPrototype(options.budget, options.functionHasInstance);
34
+ createGeneratorPrototypes(options.budget);
31
35
  registerBuiltinIdentities(options.budget, bindings);
32
36
  return bindings;
33
37
  }
@@ -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,58 @@
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, 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 (isSandboxErrorConstructorInstance(value, constructor))
33
+ return true;
34
+ if (!isGuestClosure(constructor) || typeof value !== "object" || value === null)
35
+ return false;
36
+ const prototype = await readInstanceProperty(constructor, "prototype", budget, context);
37
+ if (typeof prototype !== "object" || prototype === null)
38
+ throw new TypeError("Function has a non-object prototype in instanceof check.");
39
+ let depth = 0;
40
+ for (let current = getSandboxPrototype(value, budget); current !== null; current = getSandboxPrototype(current, budget)) {
41
+ budget.visitNode();
42
+ assertSandboxDataDepth(depth++);
43
+ if (current === prototype)
44
+ return true;
45
+ }
46
+ return false;
47
+ }
48
+ async function readInstanceProperty(value, key, budget, context) {
49
+ if (context?.getProperty !== undefined)
50
+ return context.getProperty(value, key);
51
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
52
+ if (descriptor === undefined)
53
+ return undefined;
54
+ return readPropertyDescriptor(descriptor, value, {
55
+ ...context, stack: context?.stack ?? [], thisValue: value,
56
+ invokeClosure: context?.invokeClosure ?? ((closure, args, receiver) => invokeBuiltinClosure(closure, args, budget, context, receiver))
57
+ });
58
+ }