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.
- package/dist/index.js +500 -221
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-34G5WW2O.js → chunk-2LNBLFJ3.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-M4L3EZHL.js → chunk-ZSYBRZU6.js} +431 -206
- package/packages/safe-js/dist/chunks/chunk-ZSYBRZU6.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/async.d.ts +1 -1
- package/packages/safe-js/dist/interp/async.js +65 -43
- package/packages/safe-js/dist/interp/bound-function-state.d.ts +7 -0
- package/packages/safe-js/dist/interp/bound-function-state.js +1 -0
- package/packages/safe-js/dist/interp/bound-function.d.ts +4 -0
- package/packages/safe-js/dist/interp/bound-function.js +18 -0
- package/packages/safe-js/dist/interp/generator-prototypes.d.ts +6 -0
- package/packages/safe-js/dist/interp/generator-prototypes.js +1 -0
- package/packages/safe-js/dist/interp/globals/function.d.ts +1 -1
- package/packages/safe-js/dist/interp/globals/function.js +10 -2
- package/packages/safe-js/dist/interp/globals/generator.d.ts +2 -0
- package/packages/safe-js/dist/interp/globals/generator.js +51 -0
- package/packages/safe-js/dist/interp/globals/object-array.js +19 -1
- package/packages/safe-js/dist/interp/globals.d.ts +1 -0
- package/packages/safe-js/dist/interp/globals.js +3 -1
- package/packages/safe-js/dist/interp/instanceof.d.ts +4 -0
- package/packages/safe-js/dist/interp/instanceof.js +58 -0
- package/packages/safe-js/dist/interp/interpreter.js +3 -40
- package/packages/safe-js/dist/interp/iteration.js +44 -6
- package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/function.js +53 -40
- package/packages/safe-js/dist/interp/methods/generator.d.ts +4 -1
- package/packages/safe-js/dist/interp/methods/generator.js +12 -6
- package/packages/safe-js/dist/interp/object-model.js +2 -0
- package/packages/safe-js/dist/snapshot/guest-heap-validation.js +24 -2
- package/packages/safe-js/dist/snapshot/guest-heap.d.ts +8 -0
- package/packages/safe-js/dist/snapshot/guest-heap.js +7 -0
- package/packages/safe-js/dist/snapshot/restore.js +53 -7
- package/packages/safe-js/dist/chunks/chunk-M4L3EZHL.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-34G5WW2O.js.map → chunk-2LNBLFJ3.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type SandboxCallContext, type SandboxClosure, type SandboxValue } from "../values.js";
|
|
2
|
-
import
|
|
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 =
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
target.properties
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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 (
|
|
105
|
-
throw new TypeError("Function#apply requires an
|
|
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
|
|
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
|
-
|
|
118
|
-
values.push(await
|
|
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
|
-
|
|
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,5 +1,6 @@
|
|
|
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";
|
|
@@ -271,6 +272,7 @@ export function releaseObjectPrototype(budget) {
|
|
|
271
272
|
datePrototypes.delete(budget);
|
|
272
273
|
arrayPrototypes.delete(budget);
|
|
273
274
|
functionPrototypes.delete(budget);
|
|
275
|
+
generatorPrototypes.delete(budget);
|
|
274
276
|
initialRegexDescriptors.delete(budget);
|
|
275
277
|
intrinsicPrototypes.delete(budget);
|
|
276
278
|
}
|
|
@@ -4,6 +4,7 @@ import { createBuiltinBindings } from "../interp/globals.js";
|
|
|
4
4
|
import { getIntrinsicIdentity, listIntrinsicIdentities, resolveIntrinsicIdentity } from "../interp/intrinsics.js";
|
|
5
5
|
import { releaseObjectPrototype } from "../interp/object-model.js";
|
|
6
6
|
import { isSandboxClosure } from "../interp/values.js";
|
|
7
|
+
import { assertSnapshotDataDepth } from "../graph-depth.js";
|
|
7
8
|
let intrinsicKinds;
|
|
8
9
|
function intrinsicCatalogue() {
|
|
9
10
|
if (intrinsicKinds !== undefined)
|
|
@@ -59,7 +60,7 @@ export function validateGuestHeapNode(raw, heap, maxArrayLength = 0xffffffff) {
|
|
|
59
60
|
createRawJson(node.text);
|
|
60
61
|
return true;
|
|
61
62
|
}
|
|
62
|
-
if (!["intrinsic", "guest-function", "guest-class", "guest-generator", "scope-frame", "guest-object", "guest-array", "array-iterator", "map", "set"].includes(String(node.kind)))
|
|
63
|
+
if (!["intrinsic", "bound-function", "guest-function", "guest-class", "guest-generator", "scope-frame", "guest-object", "guest-array", "array-iterator", "map", "set"].includes(String(node.kind)))
|
|
63
64
|
return false;
|
|
64
65
|
const reference = (value, kinds) => {
|
|
65
66
|
const ref = record(value);
|
|
@@ -74,7 +75,7 @@ export function validateGuestHeapNode(raw, heap, maxArrayLength = 0xffffffff) {
|
|
|
74
75
|
const callable = (value) => {
|
|
75
76
|
if (absent(value))
|
|
76
77
|
return;
|
|
77
|
-
const target = reference(value, ["intrinsic", "guest-function", "guest-class"]);
|
|
78
|
+
const target = reference(value, ["intrinsic", "bound-function", "guest-function", "guest-class"]);
|
|
78
79
|
if (target.kind === "intrinsic" && intrinsicCatalogue().get(String(target.id)) !== true)
|
|
79
80
|
throw new TypeError("Guest accessor reference is not callable.");
|
|
80
81
|
};
|
|
@@ -199,6 +200,27 @@ export function validateGuestHeapNode(raw, heap, maxArrayLength = 0xffffffff) {
|
|
|
199
200
|
throw new TypeError("Invalid class prototype descriptor.");
|
|
200
201
|
reference(descriptor.value, ["object", "guest-object"]);
|
|
201
202
|
}
|
|
203
|
+
else if (node.kind === "bound-function") {
|
|
204
|
+
fields(node, ["kind", "target", "thisValue", "args", "length", "state"], ["name"]);
|
|
205
|
+
if (Object.hasOwn(node, "name") && typeof node.name !== "string")
|
|
206
|
+
throw new TypeError("Invalid bound function name.");
|
|
207
|
+
if (array(node.args).length > maxArrayLength)
|
|
208
|
+
throw new TypeError("Bound arguments exceed allocation limit.");
|
|
209
|
+
if (!absent(node.length) && !(typeof node.length === "number" && node.length >= 0) &&
|
|
210
|
+
!(record(node.length).kind === "number" && record(node.length).value === "Infinity"))
|
|
211
|
+
throw new TypeError("Invalid bound function length.");
|
|
212
|
+
const visited = new Set([raw]);
|
|
213
|
+
let current = node;
|
|
214
|
+
while (current.kind === "bound-function") {
|
|
215
|
+
assertSnapshotDataDepth(visited.size, "<bound-target>");
|
|
216
|
+
callable(current.target);
|
|
217
|
+
current = reference(current.target);
|
|
218
|
+
if (visited.has(current))
|
|
219
|
+
throw new TypeError("Cyclic bound function target.");
|
|
220
|
+
visited.add(current);
|
|
221
|
+
}
|
|
222
|
+
state(node.state);
|
|
223
|
+
}
|
|
202
224
|
else if (node.kind === "guest-function") {
|
|
203
225
|
fields(node, ["kind", "astNodeId", "scope", "state"], ["name", "environment"]);
|
|
204
226
|
if (integer(node.astNodeId) < 1)
|
|
@@ -13,6 +13,14 @@ export type GuestObjectState<T> = {
|
|
|
13
13
|
prototype?: T;
|
|
14
14
|
};
|
|
15
15
|
export type GuestHeapNode<T> = {
|
|
16
|
+
kind: "bound-function";
|
|
17
|
+
target: T;
|
|
18
|
+
thisValue: T;
|
|
19
|
+
args: T[];
|
|
20
|
+
name?: string;
|
|
21
|
+
length: T;
|
|
22
|
+
state: GuestObjectState<T>;
|
|
23
|
+
} | {
|
|
16
24
|
kind: "array-iterator";
|
|
17
25
|
source: T;
|
|
18
26
|
index: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getClosureOrigin, getGeneratorOrigin } from "../interp/closure-origin.js";
|
|
2
|
+
import { boundFunctionStates } from "../interp/bound-function-state.js";
|
|
2
3
|
import { getGeneratorProperties } from "../interp/generator-properties.js";
|
|
3
4
|
import { getIntrinsicIdentity } from "../interp/intrinsics.js";
|
|
4
5
|
import { getSandboxPrototype, hasExplicitSandboxPrototype, hasGuestObjectState, isGuestClosure, materializeFunctionProperties } from "../interp/object-model.js";
|
|
@@ -27,6 +28,12 @@ export function captureGuestHeapNode(value, encode) {
|
|
|
27
28
|
const state = captureObjectState(value, encode);
|
|
28
29
|
return { kind: "intrinsic", id: intrinsic, ...(state === undefined ? {} : { state }) };
|
|
29
30
|
}
|
|
31
|
+
const bound = boundFunctionStates.get(value);
|
|
32
|
+
if (bound !== undefined && isSandboxClosure(value)) {
|
|
33
|
+
return { kind: "bound-function", target: encode(bound.target), thisValue: encode(bound.thisValue),
|
|
34
|
+
args: bound.args.map(encode), length: encode(value.length),
|
|
35
|
+
...(value.name === undefined ? {} : { name: value.name }), state: captureObjectState(value, encode) };
|
|
36
|
+
}
|
|
30
37
|
if (isSandboxMap(value))
|
|
31
38
|
return { kind: "map", entries: [...value.entries].map(([key, entry]) => [encode(key), encode(entry)]), ...serializeCollectionProperties(value, encode) };
|
|
32
39
|
if (isSandboxSet(value))
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Budget, SandboxError } from "../interp/budget.js";
|
|
2
|
+
import { createBoundFunction } from "../interp/bound-function.js";
|
|
3
|
+
import { invokeBuiltinClosure } from "../interp/builtin-call.js";
|
|
2
4
|
import { getGeneratorProperties } from "../interp/generator-properties.js";
|
|
3
5
|
import { restoreRegexProperties } from "./regexp-properties.js";
|
|
4
6
|
import { classOrigins, createClassConstructor } from "../interp/classes.js";
|
|
@@ -376,6 +378,29 @@ function isSerializedRegexValue(value) {
|
|
|
376
378
|
typeof value.flags === "string" &&
|
|
377
379
|
typeof value.lastIndex === "number");
|
|
378
380
|
}
|
|
381
|
+
function initializeIntrinsicRealm(state) {
|
|
382
|
+
if (state.intrinsicsInitialized)
|
|
383
|
+
return;
|
|
384
|
+
const prototype = Object.values(state.heap).find(node => node.kind === "intrinsic" && node.id === '["%FunctionPrototype%"]');
|
|
385
|
+
// Older heaps could omit this property or contain a guest-defined hook.
|
|
386
|
+
// Do not preinstall a nonconfigurable property over their captured state.
|
|
387
|
+
const functionHasInstance = prototype?.kind !== "intrinsic" || prototype.state === undefined ||
|
|
388
|
+
prototype.state.properties.properties.some(([key, descriptor]) => {
|
|
389
|
+
if (key === null || typeof key !== "object" || !("kind" in key) || key.kind !== "ref")
|
|
390
|
+
return false;
|
|
391
|
+
const symbol = state.heap[String(key.id)];
|
|
392
|
+
if (symbol?.kind !== "symbol" || symbol.wellKnown !== "hasInstance" || descriptor.kind !== "data" ||
|
|
393
|
+
descriptor.writable || descriptor.enumerable || descriptor.configurable)
|
|
394
|
+
return false;
|
|
395
|
+
const value = descriptor.value;
|
|
396
|
+
if (value === null || typeof value !== "object" || !("kind" in value) || value.kind !== "ref")
|
|
397
|
+
return false;
|
|
398
|
+
const method = state.heap[String(value.id)];
|
|
399
|
+
return method?.kind === "intrinsic" && method.id === '["%FunctionPrototype%",{"symbol":"hasInstance"}]';
|
|
400
|
+
});
|
|
401
|
+
createBuiltinBindings({ budget: state.budget, compileOwner: state.compilation.owner, functionHasInstance });
|
|
402
|
+
state.intrinsicsInitialized = true;
|
|
403
|
+
}
|
|
379
404
|
function restoreHeapValue(id, state) {
|
|
380
405
|
const existing = state.heapValueById.get(id);
|
|
381
406
|
if (existing !== undefined) {
|
|
@@ -531,13 +556,27 @@ function restoreHeapValue(id, state) {
|
|
|
531
556
|
});
|
|
532
557
|
return generator;
|
|
533
558
|
}
|
|
534
|
-
if (serialized.kind === "intrinsic" || serialized.kind === "guest-function" || serialized.kind === "guest-class" || serialized.kind === "guest-object" || serialized.kind === "guest-array" || serialized.kind === "array-iterator") {
|
|
559
|
+
if (serialized.kind === "intrinsic" || serialized.kind === "bound-function" || serialized.kind === "guest-function" || serialized.kind === "guest-class" || serialized.kind === "guest-object" || serialized.kind === "guest-array" || serialized.kind === "array-iterator") {
|
|
535
560
|
let value;
|
|
536
|
-
if (serialized.kind === "
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
561
|
+
if (serialized.kind === "bound-function") {
|
|
562
|
+
initializeIntrinsicRealm(state);
|
|
563
|
+
const target = deserializeValue(serialized.target, state);
|
|
564
|
+
if (!isSandboxClosure(target))
|
|
565
|
+
throw new TypeError("Invalid bound function target.");
|
|
566
|
+
const boundState = { target, thisValue: undefined, args: [] };
|
|
567
|
+
const length = deserializeValue(serialized.length, state);
|
|
568
|
+
if (length !== undefined && typeof length !== "number")
|
|
569
|
+
throw new TypeError("Invalid bound function length.");
|
|
570
|
+
value = createBoundFunction(boundState, serialized.name, length, (callee, args, stack, thisValue, construct, newTarget) => invokeBuiltinClosure(callee, args, state.budget, { stack, thisValue, newTarget }, thisValue, construct));
|
|
571
|
+
// Allocate every bound identity before decoding arguments and receivers:
|
|
572
|
+
// either may point back to this function, including through another bind.
|
|
573
|
+
state.initializeIterators.push(() => {
|
|
574
|
+
boundState.thisValue = deserializeValue(serialized.thisValue, state);
|
|
575
|
+
boundState.args = serialized.args.map(entry => deserializeValue(entry, state));
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
else if (serialized.kind === "intrinsic") {
|
|
579
|
+
initializeIntrinsicRealm(state);
|
|
541
580
|
value = resolveIntrinsicIdentity(state.budget, serialized.id);
|
|
542
581
|
}
|
|
543
582
|
else if (serialized.kind === "guest-class") {
|
|
@@ -578,12 +617,19 @@ function restoreHeapValue(id, state) {
|
|
|
578
617
|
homeObject: serialized.environment.homeObject === undefined ? undefined : deserializeValue(serialized.environment.homeObject, state),
|
|
579
618
|
newTarget: serialized.environment.newTarget === undefined ? undefined : deserializeValue(serialized.environment.newTarget, state)
|
|
580
619
|
};
|
|
620
|
+
// Current generator functions need their realm before creation, not only
|
|
621
|
+
// when a later prototype reference is decoded. Earlier heaps can lack the
|
|
622
|
+
// native nonconfigurable prototype property and retain that legacy shape.
|
|
623
|
+
const initializeGeneratorPrototype = node.type !== "ArrowFunctionExpression" && node.generator &&
|
|
624
|
+
serialized.state.properties.properties.some(([key, descriptor]) => key === "prototype" && descriptor.kind === "data" && !descriptor.configurable);
|
|
625
|
+
if (initializeGeneratorPrototype)
|
|
626
|
+
initializeIntrinsicRealm(state);
|
|
581
627
|
value = createInterpretedClosure(node, {
|
|
582
628
|
scope, budget: state.budget, compilation: state.compilation, rootNode: state.rootNode,
|
|
583
629
|
signal: state.signal, inferredName: serialized.name, functionEnvironment: environment,
|
|
584
630
|
callStack: [], activeLoopIterations: new Map(), restoredLoopIterations: new Map(),
|
|
585
631
|
stats: { currentDataSize: 0, nodeVisits: 0, peakDataSize: 0 }
|
|
586
|
-
}, evaluateNode, environment?.homeObject);
|
|
632
|
+
}, evaluateNode, environment?.homeObject, initializeGeneratorPrototype);
|
|
587
633
|
}
|
|
588
634
|
else
|
|
589
635
|
value = serialized.kind === "guest-array" ? [] : Object.create(null);
|