poe-code 14.0.80 → 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 (40) hide show
  1. package/dist/index.js +500 -221
  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-2LNBLFJ3.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-M4L3EZHL.js → chunk-ZSYBRZU6.js} +431 -206
  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/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/generator-prototypes.d.ts +6 -0
  18. package/packages/safe-js/dist/interp/generator-prototypes.js +1 -0
  19. package/packages/safe-js/dist/interp/globals/function.d.ts +1 -1
  20. package/packages/safe-js/dist/interp/globals/function.js +10 -2
  21. package/packages/safe-js/dist/interp/globals/generator.d.ts +2 -0
  22. package/packages/safe-js/dist/interp/globals/generator.js +51 -0
  23. package/packages/safe-js/dist/interp/globals/object-array.js +19 -1
  24. package/packages/safe-js/dist/interp/globals.d.ts +1 -0
  25. package/packages/safe-js/dist/interp/globals.js +3 -1
  26. package/packages/safe-js/dist/interp/instanceof.d.ts +4 -0
  27. package/packages/safe-js/dist/interp/instanceof.js +58 -0
  28. package/packages/safe-js/dist/interp/interpreter.js +3 -40
  29. package/packages/safe-js/dist/interp/iteration.js +44 -6
  30. package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
  31. package/packages/safe-js/dist/interp/methods/function.js +53 -40
  32. package/packages/safe-js/dist/interp/methods/generator.d.ts +4 -1
  33. package/packages/safe-js/dist/interp/methods/generator.js +12 -6
  34. package/packages/safe-js/dist/interp/object-model.js +2 -0
  35. package/packages/safe-js/dist/snapshot/guest-heap-validation.js +24 -2
  36. package/packages/safe-js/dist/snapshot/guest-heap.d.ts +8 -0
  37. package/packages/safe-js/dist/snapshot/guest-heap.js +7 -0
  38. package/packages/safe-js/dist/snapshot/restore.js +53 -7
  39. package/packages/safe-js/dist/chunks/chunk-M4L3EZHL.js.map +0 -7
  40. /package/packages/safe-js/dist/chunks/{chunk-34G5WW2O.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-34G5WW2O.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-M4L3EZHL.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-M4L3EZHL.js";
8
+ } from "./chunks/chunk-ZSYBRZU6.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-34G5WW2O.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-M4L3EZHL.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,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();
@@ -1,2 +1,2 @@
1
1
  import type { Budget } from "../budget.js";
2
- export declare function createFunctionPrototype(budget: Budget): void;
2
+ export declare function createFunctionPrototype(budget: Budget, installHasInstance?: boolean): void;
@@ -1,8 +1,9 @@
1
1
  import { invokeBuiltinClosure } from "../builtin-call.js";
2
2
  import { callFunctionMethod } from "../methods/function.js";
3
- import { getSandboxPrototype, installFunctionPrototype, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
3
+ import { getSandboxPrototype, installFunctionPrototype, materializeFunctionProperties, registerIntrinsicFunction, setSandboxPrototype } from "../object-model.js";
4
4
  import { createSandboxClosure } from "../values.js";
5
- export function createFunctionPrototype(budget) {
5
+ import { ordinaryHasInstance } from "../instanceof.js";
6
+ export function createFunctionPrototype(budget, installHasInstance = true) {
6
7
  const prototype = createSandboxClosure({ guest: true, sandbox: true, name: "", length: 0, call: () => undefined });
7
8
  const properties = materializeFunctionProperties(prototype);
8
9
  // Invocation support does not grant the host's dynamic source constructor.
@@ -19,6 +20,13 @@ export function createFunctionPrototype(budget) {
19
20
  })
20
21
  });
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 });
22
28
  setSandboxPrototype(prototype, getSandboxPrototype(Object.create(null), budget));
23
29
  installFunctionPrototype(budget, prototype);
30
+ if (hasInstance !== undefined)
31
+ registerIntrinsicFunction(budget, hasInstance);
24
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
+ }
@@ -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,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;
@@ -8,6 +8,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";
@@ -29,7 +30,8 @@ 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
+ createGeneratorPrototypes(options.budget);
33
35
  registerBuiltinIdentities(options.budget, bindings);
34
36
  return bindings;
35
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
+ }
@@ -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)