poe-code 14.0.82 → 14.0.83
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 +543 -156
- 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-7LGBDF56.js → chunk-37V6Q4K3.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-V6LQP64H.js → chunk-PT7PBLVT.js} +457 -91
- package/packages/safe-js/dist/chunks/chunk-PT7PBLVT.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/float32-prototypes.d.ts +3 -0
- package/packages/safe-js/dist/interp/float32-prototypes.js +1 -0
- package/packages/safe-js/dist/interp/float32.d.ts +1 -0
- package/packages/safe-js/dist/interp/float32.js +12 -4
- package/packages/safe-js/dist/interp/globals/float32array.d.ts +3 -2
- package/packages/safe-js/dist/interp/globals/float32array.js +371 -65
- package/packages/safe-js/dist/interp/globals/object-array.js +3 -3
- package/packages/safe-js/dist/interp/globals.d.ts +1 -0
- package/packages/safe-js/dist/interp/globals.js +4 -2
- package/packages/safe-js/dist/interp/instanceof.js +1 -1
- package/packages/safe-js/dist/interp/interpreter.js +2 -4
- package/packages/safe-js/dist/interp/iteration.js +15 -6
- package/packages/safe-js/dist/interp/object-model.js +16 -1
- package/packages/safe-js/dist/interp/values.js +12 -4
- package/packages/safe-js/dist/parse/parser.js +8 -3
- package/packages/safe-js/dist/parse/tokenizer.js +45 -3
- package/packages/safe-js/dist/snapshot/float32array.d.ts +3 -0
- package/packages/safe-js/dist/snapshot/float32array.js +20 -1
- package/packages/safe-js/dist/snapshot/restore.js +17 -2
- package/packages/safe-js/dist/snapshot/serialize.d.ts +2 -1
- package/packages/safe-js/dist/snapshot/serialize.js +10 -9
- package/packages/safe-js/dist/snapshot/validation.js +10 -0
- package/packages/safe-js/dist/chunks/chunk-V6LQP64H.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-7LGBDF56.js.map → chunk-37V6Q4K3.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveFsConfig,
|
|
23
23
|
splitFrontmatter,
|
|
24
24
|
withBrokenPipeGuard
|
|
25
|
-
} from "./chunks/chunk-
|
|
25
|
+
} from "./chunks/chunk-37V6Q4K3.js";
|
|
26
26
|
import {
|
|
27
27
|
Budget,
|
|
28
28
|
SandboxError,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
replaceErrorStack,
|
|
35
35
|
restore,
|
|
36
36
|
run
|
|
37
|
-
} from "./chunks/chunk-
|
|
37
|
+
} from "./chunks/chunk-PT7PBLVT.js";
|
|
38
38
|
import "./chunks/chunk-M2DLCGEF.js";
|
|
39
39
|
import "./chunks/chunk-Q7USUEL7.js";
|
|
40
40
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
runWithSpawnUsageAccumulator,
|
|
27
27
|
splitFrontmatter,
|
|
28
28
|
supportsSpawnMode
|
|
29
|
-
} from "./chunks/chunk-
|
|
29
|
+
} from "./chunks/chunk-37V6Q4K3.js";
|
|
30
30
|
import {
|
|
31
31
|
Budget,
|
|
32
32
|
FileSnapshotBackend,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
registerPendingHostCallPolicy,
|
|
51
51
|
restore,
|
|
52
52
|
run
|
|
53
|
-
} from "./chunks/chunk-
|
|
53
|
+
} from "./chunks/chunk-PT7PBLVT.js";
|
|
54
54
|
import "./chunks/chunk-M2DLCGEF.js";
|
|
55
55
|
import "./chunks/chunk-Q7USUEL7.js";
|
|
56
56
|
import "./chunks/chunk-4YIDX44G.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const float32Prototypes = new WeakMap();
|
|
@@ -6,6 +6,7 @@ export declare function float32Storage(value: Float32Array): {
|
|
|
6
6
|
length: number;
|
|
7
7
|
byteLength: number;
|
|
8
8
|
};
|
|
9
|
+
export declare function float32Properties(value: Float32Array): Array<[PropertyKey, PropertyDescriptor]>;
|
|
9
10
|
export declare function float32DataProperties(value: Float32Array): Array<[string, PropertyDescriptor]>;
|
|
10
11
|
export declare function isFloat32Index(key: string): boolean;
|
|
11
12
|
export declare function float32Number(value: unknown): number;
|
|
@@ -23,14 +23,22 @@ export function float32Storage(value) {
|
|
|
23
23
|
byteLength: Reflect.apply(bufferLength, buffer, [])
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
export function float32Properties(value) {
|
|
27
|
+
const properties = [];
|
|
28
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
29
|
+
if (typeof key === "string" && isFloat32Index(key))
|
|
30
|
+
continue;
|
|
31
|
+
properties.push([key, Object.getOwnPropertyDescriptor(value, key)]);
|
|
32
|
+
}
|
|
33
|
+
return properties;
|
|
34
|
+
}
|
|
26
35
|
export function float32DataProperties(value) {
|
|
27
36
|
if (Object.getOwnPropertySymbols(value).length > 0)
|
|
28
37
|
throw new TypeError("Float32Array symbol properties are not supported.");
|
|
29
38
|
const properties = [];
|
|
30
|
-
for (const key of
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
39
|
+
for (const [key, descriptor] of float32Properties(value)) {
|
|
40
|
+
if (typeof key !== "string")
|
|
41
|
+
throw new TypeError("Float32Array symbol properties are not supported.");
|
|
34
42
|
if (!("value" in descriptor))
|
|
35
43
|
throw new TypeError(`Float32Array accessor property '${key}' is not supported.`);
|
|
36
44
|
properties.push([key, descriptor]);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Budget } from "../budget.js";
|
|
2
2
|
import { type SandboxClosure, type SandboxValue } from "../values.js";
|
|
3
|
-
export declare function createFloat32ArrayGlobal(budget: Budget): SandboxClosure;
|
|
3
|
+
export declare function createFloat32ArrayGlobal(budget: Budget, nativePrototype?: boolean): SandboxClosure;
|
|
4
|
+
export declare function createFloat32ArrayPrototypes(budget: Budget, constructor: SandboxClosure): void;
|
|
4
5
|
export declare function isFloat32ArrayConstructor(value: unknown): boolean;
|
|
5
6
|
export declare function getFloat32Member(value: Float32Array, property: string | number, budget: Budget): SandboxValue;
|
|
6
|
-
export declare function setFloat32Member(value: Float32Array, property:
|
|
7
|
+
export declare function setFloat32Member(value: Float32Array, property: PropertyKey, entry: SandboxValue, budget?: Budget): void;
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { checkFloat32Allocation, float32Number, float32Storage, isFloat32Array, isFloat32Index } from "../float32.js";
|
|
2
|
-
import { createSandboxClosure } from "../values.js";
|
|
2
|
+
import { createSandboxClosure, isSandboxClosure, measureSandboxData } from "../values.js";
|
|
3
|
+
import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
|
|
4
|
+
import { float32Prototypes } from "../float32-prototypes.js";
|
|
5
|
+
import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, materializeFunctionProperties, registerIntrinsicFunction, registerIntrinsicObject, setSandboxPrototype } from "../object-model.js";
|
|
6
|
+
import { registerBuiltinIdentities, resolveIntrinsicIdentity } from "../intrinsics.js";
|
|
7
|
+
import { invokeBuiltinClosure } from "../builtin-call.js";
|
|
8
|
+
import { retainValues } from "../resources.js";
|
|
9
|
+
import { sandboxNumber, sandboxString } from "../string-coercion.js";
|
|
10
|
+
import { acquireSandboxIterator, readIteratorResult } from "../iteration.js";
|
|
11
|
+
import { createDataCheckpoint } from "../data-checkpoint.js";
|
|
12
|
+
import { createSandboxBox } from "../boxed.js";
|
|
3
13
|
const constructors = new WeakSet();
|
|
4
|
-
export function createFloat32ArrayGlobal(budget) {
|
|
14
|
+
export function createFloat32ArrayGlobal(budget, nativePrototype = false) {
|
|
5
15
|
const constructor = createSandboxClosure({
|
|
16
|
+
guest: nativePrototype,
|
|
6
17
|
sandbox: true,
|
|
7
18
|
name: "Float32Array",
|
|
8
19
|
length: 3,
|
|
@@ -10,33 +21,294 @@ export function createFloat32ArrayGlobal(budget) {
|
|
|
10
21
|
call: () => {
|
|
11
22
|
throw new TypeError("Constructor Float32Array requires 'new'.");
|
|
12
23
|
},
|
|
13
|
-
construct: (
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
construct: (args, context) => {
|
|
25
|
+
if (!nativePrototype)
|
|
26
|
+
return allocateFloat32Array(args[0], budget);
|
|
27
|
+
return (async () => {
|
|
28
|
+
const newTarget = context?.newTarget ?? constructor;
|
|
29
|
+
const candidate = context?.getProperty === undefined
|
|
30
|
+
? getSandboxDataProperty(newTarget, "prototype", budget)
|
|
31
|
+
: await context.getProperty(newTarget, "prototype");
|
|
32
|
+
const prototype = candidate !== null && typeof candidate === "object" ? candidate : float32Prototypes.get(budget);
|
|
33
|
+
const release = retainValues(budget, () => [prototype, ...args]);
|
|
34
|
+
try {
|
|
35
|
+
const result = args[0] !== null && typeof args[0] === "object" && !isFloat32Array(args[0])
|
|
36
|
+
? await allocateFloat32Input(args[0], budget, context)
|
|
37
|
+
: allocateFloat32Array(args[0], budget);
|
|
38
|
+
setSandboxPrototype(result, prototype, budget);
|
|
39
|
+
return result;
|
|
26
40
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (length < 0 || !Number.isSafeInteger(length))
|
|
32
|
-
throw new RangeError("Invalid typed array length.");
|
|
33
|
-
checkFloat32Allocation(length, budget);
|
|
34
|
-
return new Float32Array(length);
|
|
41
|
+
finally {
|
|
42
|
+
release();
|
|
43
|
+
}
|
|
44
|
+
})();
|
|
35
45
|
}
|
|
36
46
|
});
|
|
37
47
|
constructors.add(constructor);
|
|
38
48
|
return constructor;
|
|
39
49
|
}
|
|
50
|
+
async function allocateFloat32Input(source, budget, context) {
|
|
51
|
+
const callerContext = context;
|
|
52
|
+
const bridge = {
|
|
53
|
+
...callerContext, stack: callerContext?.stack ?? [], thisValue: undefined,
|
|
54
|
+
getProperty: callerContext?.getProperty ?? ((value, key) => {
|
|
55
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, budget);
|
|
56
|
+
return descriptor === undefined ? getSandboxDataProperty(value, key, budget)
|
|
57
|
+
: readPropertyDescriptor(descriptor, value, bridge);
|
|
58
|
+
}),
|
|
59
|
+
invokeClosure: callerContext?.invokeClosure ?? ((callee, values, receiver, construct) => invokeBuiltinClosure(callee, values, budget, callerContext, receiver, construct))
|
|
60
|
+
};
|
|
61
|
+
const values = [];
|
|
62
|
+
let iterator;
|
|
63
|
+
let current;
|
|
64
|
+
let result;
|
|
65
|
+
const release = retainValues(budget, () => [source, values, iterator?.retainedValue, current, result]);
|
|
66
|
+
const checkData = createDataCheckpoint(budget, bridge);
|
|
67
|
+
try {
|
|
68
|
+
iterator = await acquireSandboxIterator(source, budget, bridge);
|
|
69
|
+
let length;
|
|
70
|
+
if (iterator !== undefined) {
|
|
71
|
+
while (true) {
|
|
72
|
+
budget.visitNode();
|
|
73
|
+
const next = await iterator.next();
|
|
74
|
+
if (typeof next !== "object" || next === null)
|
|
75
|
+
throw new TypeError("Iterator result must be an object.");
|
|
76
|
+
if ((await readIteratorResult(iterator, next, "done")).value)
|
|
77
|
+
break;
|
|
78
|
+
current = (await readIteratorResult(iterator, next, "value")).value;
|
|
79
|
+
budget.allocateArrayLength(values.length + 1);
|
|
80
|
+
values.push(current);
|
|
81
|
+
checkData(values, 1 + (budget.limits.dataSize === undefined ? 0 : measureSandboxData([current])));
|
|
82
|
+
}
|
|
83
|
+
length = values.length;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
current = await bridge.getProperty(source, "length");
|
|
87
|
+
const number = await sandboxNumber(current, budget, bridge);
|
|
88
|
+
length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
89
|
+
}
|
|
90
|
+
checkFloat32Allocation(length, budget);
|
|
91
|
+
result = new Float32Array(length);
|
|
92
|
+
checkData(result, 0, true);
|
|
93
|
+
for (let index = 0; index < length; index++) {
|
|
94
|
+
budget.visitNode();
|
|
95
|
+
current = iterator === undefined ? await bridge.getProperty(source, String(index)) : values[index];
|
|
96
|
+
result[index] = await sandboxNumber(current, budget, bridge);
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
release();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function allocateFloat32Array(source, budget) {
|
|
105
|
+
if (Array.isArray(source) || isFloat32Array(source)) {
|
|
106
|
+
const length = isFloat32Array(source) ? float32Storage(source).length : source.length;
|
|
107
|
+
checkFloat32Allocation(length, budget);
|
|
108
|
+
if (isFloat32Array(source))
|
|
109
|
+
return new Float32Array(source);
|
|
110
|
+
const result = new Float32Array(length);
|
|
111
|
+
for (let index = 0; index < length; index += 1) {
|
|
112
|
+
budget.visitNode();
|
|
113
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, index);
|
|
114
|
+
if (descriptor !== undefined && !("value" in descriptor))
|
|
115
|
+
throw new TypeError("Float32Array input accessors are not supported.");
|
|
116
|
+
result[index] = float32Number(descriptor?.value);
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
const number = float32Number(source);
|
|
121
|
+
const length = Number.isNaN(number) ? 0 : Math.trunc(number);
|
|
122
|
+
if (length < 0 || !Number.isSafeInteger(length))
|
|
123
|
+
throw new RangeError("Invalid typed array length.");
|
|
124
|
+
checkFloat32Allocation(length, budget);
|
|
125
|
+
return new Float32Array(length);
|
|
126
|
+
}
|
|
127
|
+
export function createFloat32ArrayPrototypes(budget, constructor) {
|
|
128
|
+
const prototype = Object.create(null);
|
|
129
|
+
const shared = Object.create(null);
|
|
130
|
+
const abstractCall = () => { throw new TypeError("Abstract TypedArray constructor cannot be called."); };
|
|
131
|
+
const typedArray = createSandboxClosure({ guest: true, sandbox: true, name: "TypedArray", length: 0,
|
|
132
|
+
call: abstractCall, construct: abstractCall });
|
|
133
|
+
Object.defineProperty(materializeFunctionProperties(typedArray), "prototype", { value: shared, writable: false });
|
|
134
|
+
Object.defineProperty(materializeFunctionProperties(typedArray), "from", {
|
|
135
|
+
writable: true, configurable: true,
|
|
136
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "from", length: 1,
|
|
137
|
+
call: async (args, context) => {
|
|
138
|
+
const target = context?.thisValue;
|
|
139
|
+
const [source, mapper, receiver] = args;
|
|
140
|
+
if (!isSandboxClosure(target) || target.construct === undefined)
|
|
141
|
+
throw new TypeError("TypedArray.from requires a constructor receiver.");
|
|
142
|
+
if (mapper !== undefined && !isSandboxClosure(mapper))
|
|
143
|
+
throw new TypeError("TypedArray.from mapper must be callable.");
|
|
144
|
+
if (source === null || source === undefined)
|
|
145
|
+
throw new TypeError("TypedArray.from requires a non-null source.");
|
|
146
|
+
const callerContext = context;
|
|
147
|
+
context = {
|
|
148
|
+
...callerContext,
|
|
149
|
+
stack: callerContext?.stack ?? [],
|
|
150
|
+
thisValue: target,
|
|
151
|
+
getProperty: callerContext?.getProperty ?? ((value, key) => {
|
|
152
|
+
const descriptor = getSandboxPropertyDescriptor(value, key, budget);
|
|
153
|
+
return descriptor === undefined ? getSandboxDataProperty(value, key, budget)
|
|
154
|
+
: readPropertyDescriptor(descriptor, value, context);
|
|
155
|
+
}),
|
|
156
|
+
invokeClosure: callerContext?.invokeClosure ?? ((callee, values, thisValue, construct) => invokeBuiltinClosure(callee, values, budget, callerContext, thisValue, construct))
|
|
157
|
+
};
|
|
158
|
+
let result;
|
|
159
|
+
let current;
|
|
160
|
+
let iterator;
|
|
161
|
+
const values = [];
|
|
162
|
+
const release = retainValues(budget, () => [target, result, current, iterator?.retainedValue, values, ...args]);
|
|
163
|
+
const checkData = createDataCheckpoint(budget, context);
|
|
164
|
+
const read = (key) => context?.getProperty === undefined
|
|
165
|
+
? getSandboxDataProperty(source, key, budget) : context.getProperty(source, key);
|
|
166
|
+
try {
|
|
167
|
+
iterator = await acquireSandboxIterator(source, budget, context);
|
|
168
|
+
let length;
|
|
169
|
+
if (iterator !== undefined) {
|
|
170
|
+
while (true) {
|
|
171
|
+
budget.visitNode();
|
|
172
|
+
const next = await iterator.next();
|
|
173
|
+
if (typeof next !== "object" || next === null)
|
|
174
|
+
throw new TypeError("Iterator result must be an object.");
|
|
175
|
+
if ((await readIteratorResult(iterator, next, "done")).value)
|
|
176
|
+
break;
|
|
177
|
+
current = (await readIteratorResult(iterator, next, "value")).value;
|
|
178
|
+
budget.allocateArrayLength(values.length + 1);
|
|
179
|
+
values.push(current);
|
|
180
|
+
checkData(values, 1 + (budget.limits.dataSize === undefined ? 0 : measureSandboxData([current])));
|
|
181
|
+
}
|
|
182
|
+
length = values.length;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const number = await sandboxNumber(await read("length"), budget, context);
|
|
186
|
+
length = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
187
|
+
}
|
|
188
|
+
result = await invokeBuiltinClosure(target, [length], budget, context, undefined, true);
|
|
189
|
+
if (!isFloat32Array(result) || float32Storage(result).length < length)
|
|
190
|
+
throw new TypeError("TypedArray.from constructor must return sufficient typed storage.");
|
|
191
|
+
checkData(result, 0, true);
|
|
192
|
+
for (let index = 0; index < length; index++) {
|
|
193
|
+
budget.visitNode();
|
|
194
|
+
current = iterator === undefined ? await read(String(index)) : values[index];
|
|
195
|
+
if (mapper !== undefined)
|
|
196
|
+
current = await invokeBuiltinClosure(mapper, [current, index], budget, context, receiver);
|
|
197
|
+
result[index] = await sandboxNumber(current, budget, context);
|
|
198
|
+
}
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
release();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
Object.defineProperty(materializeFunctionProperties(typedArray), "of", {
|
|
208
|
+
writable: true, configurable: true,
|
|
209
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "of", length: 0,
|
|
210
|
+
call: async (args, context) => {
|
|
211
|
+
const target = context?.thisValue;
|
|
212
|
+
if (!isSandboxClosure(target) || target.construct === undefined)
|
|
213
|
+
throw new TypeError("TypedArray.of requires a constructor receiver.");
|
|
214
|
+
let result;
|
|
215
|
+
const release = retainValues(budget, () => [target, result, ...args]);
|
|
216
|
+
try {
|
|
217
|
+
result = await invokeBuiltinClosure(target, [args.length], budget, context, undefined, true);
|
|
218
|
+
if (!isFloat32Array(result) || float32Storage(result).length < args.length)
|
|
219
|
+
throw new TypeError("TypedArray.of constructor must return sufficient typed storage.");
|
|
220
|
+
for (let index = 0; index < args.length; index++) {
|
|
221
|
+
budget.visitNode();
|
|
222
|
+
result[index] = await sandboxNumber(args[index], budget, context);
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
release();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
});
|
|
232
|
+
Object.defineProperties(materializeFunctionProperties(constructor), {
|
|
233
|
+
prototype: { value: prototype, writable: false },
|
|
234
|
+
BYTES_PER_ELEMENT: { value: 4, writable: false, enumerable: false, configurable: false }
|
|
235
|
+
});
|
|
236
|
+
Object.defineProperties(prototype, {
|
|
237
|
+
constructor: { value: constructor, writable: true, configurable: true },
|
|
238
|
+
BYTES_PER_ELEMENT: { value: 4 }
|
|
239
|
+
});
|
|
240
|
+
Object.defineProperty(shared, "constructor", { value: typedArray, writable: true, configurable: true });
|
|
241
|
+
setSandboxPrototype(constructor, typedArray);
|
|
242
|
+
setSandboxPrototype(prototype, shared);
|
|
243
|
+
setSandboxPrototype(shared, getSandboxPrototype(Object.create(null), budget));
|
|
244
|
+
const getters = [];
|
|
245
|
+
for (const key of ["length", "byteLength", "byteOffset"]) {
|
|
246
|
+
const getter = createSandboxClosure({ guest: true, sandbox: true, name: `get ${key}`, length: 0,
|
|
247
|
+
call: (_args, context) => {
|
|
248
|
+
if (!isFloat32Array(context?.thisValue))
|
|
249
|
+
throw new TypeError(`TypedArray ${key} requires a typed array receiver.`);
|
|
250
|
+
const storage = float32Storage(context.thisValue);
|
|
251
|
+
return key === "byteLength" ? storage.length * 4 : storage[key];
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
getters.push(getter);
|
|
255
|
+
Object.defineProperty(shared, key, { get: accessorAdapter(getter, "get"), configurable: true });
|
|
256
|
+
}
|
|
257
|
+
for (const key of ["set", "slice", "subarray"])
|
|
258
|
+
Object.defineProperty(shared, key, { value: getFloat32Member(new Float32Array(0), key, budget), writable: true, configurable: true });
|
|
259
|
+
const arrayPrototype = resolveIntrinsicIdentity(budget, '["Array","prototype"]');
|
|
260
|
+
Object.defineProperty(shared, "toString", { value: getSandboxDataProperty(arrayPrototype, "toString", budget), writable: true, configurable: true });
|
|
261
|
+
Object.defineProperty(shared, "join", { writable: true, configurable: true,
|
|
262
|
+
value: createSandboxClosure({ guest: true, sandbox: true, name: "join", length: 1,
|
|
263
|
+
call: async (args, context) => {
|
|
264
|
+
if (!isFloat32Array(context?.thisValue))
|
|
265
|
+
throw new TypeError("TypedArray join requires a typed array receiver.");
|
|
266
|
+
const receiver = context.thisValue;
|
|
267
|
+
const length = float32Storage(receiver).length;
|
|
268
|
+
let separator = ",";
|
|
269
|
+
let text = "";
|
|
270
|
+
const release = retainValues(budget, () => [receiver, separator, text, ...args]);
|
|
271
|
+
try {
|
|
272
|
+
if (args[0] !== undefined)
|
|
273
|
+
separator = await sandboxString(args[0], budget, context);
|
|
274
|
+
for (let index = 0; index < length; index++) {
|
|
275
|
+
budget.visitNode();
|
|
276
|
+
text = budget.allocateString(text + (index === 0 ? "" : separator) + String(receiver[index]));
|
|
277
|
+
}
|
|
278
|
+
return text;
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
release();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
});
|
|
286
|
+
const tagGetter = createSandboxClosure({ guest: true, sandbox: true, name: "get [Symbol.toStringTag]", length: 0,
|
|
287
|
+
call: (_args, context) => isFloat32Array(context?.thisValue) ? "Float32Array" : undefined });
|
|
288
|
+
getters.push(tagGetter);
|
|
289
|
+
Object.defineProperty(shared, Symbol.toStringTag, { get: accessorAdapter(tagGetter, "get"), configurable: true });
|
|
290
|
+
for (const key of ["values", "keys", "entries"]) {
|
|
291
|
+
const method = getSandboxDataProperty(arrayPrototype, key, budget);
|
|
292
|
+
const closure = createSandboxClosure({ guest: true, sandbox: true, name: key, length: 0,
|
|
293
|
+
call: (args, context) => {
|
|
294
|
+
if (!isFloat32Array(context?.thisValue))
|
|
295
|
+
throw new TypeError(`TypedArray ${key} requires a typed array receiver.`);
|
|
296
|
+
return invokeBuiltinClosure(method, args, budget, context, context.thisValue);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
Object.defineProperty(shared, key, { value: closure, writable: true, configurable: true });
|
|
300
|
+
if (key === "values")
|
|
301
|
+
Object.defineProperty(shared, Symbol.iterator, { value: closure, writable: true, configurable: true });
|
|
302
|
+
}
|
|
303
|
+
float32Prototypes.set(budget, prototype);
|
|
304
|
+
registerBuiltinIdentities(budget, { Float32Array: constructor, "%TypedArray%": typedArray });
|
|
305
|
+
registerIntrinsicFunction(budget, constructor);
|
|
306
|
+
registerIntrinsicFunction(budget, typedArray);
|
|
307
|
+
registerIntrinsicObject(budget, prototype);
|
|
308
|
+
registerIntrinsicObject(budget, shared);
|
|
309
|
+
for (const getter of getters)
|
|
310
|
+
registerIntrinsicFunction(budget, getter);
|
|
311
|
+
}
|
|
40
312
|
export function isFloat32ArrayConstructor(value) {
|
|
41
313
|
return typeof value === "object" && value !== null && constructors.has(value);
|
|
42
314
|
}
|
|
@@ -48,6 +320,8 @@ export function getFloat32Member(value, property, budget) {
|
|
|
48
320
|
throw new TypeError("Float32Array accessors are not supported.");
|
|
49
321
|
return descriptor.value;
|
|
50
322
|
}
|
|
323
|
+
if (float32Prototypes.has(budget))
|
|
324
|
+
return undefined;
|
|
51
325
|
const storage = float32Storage(value);
|
|
52
326
|
if (key === "length")
|
|
53
327
|
return storage.length;
|
|
@@ -60,6 +334,7 @@ export function getFloat32Member(value, property, budget) {
|
|
|
60
334
|
if (!["set", "slice", "subarray"].includes(key))
|
|
61
335
|
return undefined;
|
|
62
336
|
return createSandboxClosure({
|
|
337
|
+
guest: true,
|
|
63
338
|
sandbox: true,
|
|
64
339
|
name: key,
|
|
65
340
|
length: key === "set" ? 1 : 2,
|
|
@@ -68,63 +343,94 @@ export function getFloat32Member(value, property, budget) {
|
|
|
68
343
|
if (!isFloat32Array(receiver))
|
|
69
344
|
throw new TypeError(`Float32Array#${key} requires a Float32Array receiver.`);
|
|
70
345
|
const storage = float32Storage(receiver);
|
|
346
|
+
const bridge = {
|
|
347
|
+
...context, stack: context?.stack ?? [], thisValue: receiver,
|
|
348
|
+
getProperty: context?.getProperty ?? ((value, property) => {
|
|
349
|
+
const descriptor = getSandboxPropertyDescriptor(value, property, budget);
|
|
350
|
+
return descriptor === undefined ? getSandboxDataProperty(value, property, budget)
|
|
351
|
+
: readPropertyDescriptor(descriptor, value, bridge);
|
|
352
|
+
}),
|
|
353
|
+
invokeClosure: context?.invokeClosure ?? ((callee, values, thisValue, construct) => invokeBuiltinClosure(callee, values, budget, context, thisValue, construct))
|
|
354
|
+
};
|
|
71
355
|
if (key === "set") {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
356
|
+
return (async () => {
|
|
357
|
+
const [source, offsetValue = 0] = args;
|
|
358
|
+
let current;
|
|
359
|
+
let sourceObject;
|
|
360
|
+
const release = retainValues(budget, () => [receiver, sourceObject, current, ...args]);
|
|
361
|
+
try {
|
|
362
|
+
const number = await sandboxNumber(offsetValue, budget, bridge);
|
|
363
|
+
const offset = Number.isNaN(number) ? 0 : Math.trunc(number);
|
|
364
|
+
if (offset < 0)
|
|
365
|
+
throw new RangeError("Float32Array#set offset is out of bounds.");
|
|
366
|
+
if (source === null || source === undefined)
|
|
367
|
+
throw new TypeError("Float32Array#set requires a non-null source.");
|
|
368
|
+
let length;
|
|
369
|
+
if (isFloat32Array(source))
|
|
370
|
+
length = float32Storage(source).length;
|
|
371
|
+
else {
|
|
372
|
+
sourceObject = typeof source === "object" ? source : createSandboxBox(source);
|
|
373
|
+
current = await bridge.getProperty(sourceObject, "length");
|
|
374
|
+
const size = await sandboxNumber(current, budget, bridge);
|
|
375
|
+
length = Number.isNaN(size) || size <= 0 ? 0 : Math.min(Math.trunc(size), Number.MAX_SAFE_INTEGER);
|
|
376
|
+
}
|
|
377
|
+
if (offset + length > storage.length)
|
|
378
|
+
throw new RangeError("Float32Array#set source is out of bounds.");
|
|
379
|
+
if (isFloat32Array(source))
|
|
380
|
+
Float32Array.prototype.set.call(receiver, source, offset);
|
|
381
|
+
else
|
|
382
|
+
for (let index = 0; index < length; index++) {
|
|
383
|
+
budget.visitNode();
|
|
384
|
+
current = await bridge.getProperty(sourceObject, String(index));
|
|
385
|
+
receiver[offset + index] = await sandboxNumber(current, budget, bridge);
|
|
386
|
+
}
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
finally {
|
|
390
|
+
release();
|
|
391
|
+
}
|
|
392
|
+
})();
|
|
393
|
+
}
|
|
394
|
+
return (async () => {
|
|
395
|
+
const release = retainValues(budget, () => [receiver, ...args]);
|
|
396
|
+
try {
|
|
397
|
+
const start = relativeIndex(await sandboxNumber(args[0], budget, bridge), storage.length);
|
|
398
|
+
const end = args[1] === undefined ? storage.length
|
|
399
|
+
: relativeIndex(await sandboxNumber(args[1], budget, bridge), storage.length);
|
|
400
|
+
const length = Math.max(end - start, 0);
|
|
401
|
+
if (key === "subarray")
|
|
402
|
+
return new Float32Array(storage.buffer, storage.byteOffset + start * 4, length);
|
|
403
|
+
checkFloat32Allocation(length, budget);
|
|
404
|
+
const result = new Float32Array(length);
|
|
405
|
+
new Uint8Array(result.buffer).set(new Uint8Array(storage.buffer, storage.byteOffset + start * 4, length * 4));
|
|
406
|
+
return result;
|
|
83
407
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
for (let index = 0; index < length; index += 1) {
|
|
87
|
-
budget.visitNode();
|
|
88
|
-
const entry = Object.getOwnPropertyDescriptor(source, index);
|
|
89
|
-
if (entry !== undefined && !("value" in entry))
|
|
90
|
-
throw new TypeError("Float32Array input accessors are not supported.");
|
|
91
|
-
copied[index] = float32Number(entry?.value);
|
|
408
|
+
finally {
|
|
409
|
+
release();
|
|
92
410
|
}
|
|
93
|
-
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
const start = relativeIndex(args[0], storage.length, 0);
|
|
97
|
-
const end = relativeIndex(args[1], storage.length, storage.length);
|
|
98
|
-
const length = Math.max(end - start, 0);
|
|
99
|
-
if (key === "subarray")
|
|
100
|
-
return new Float32Array(storage.buffer, storage.byteOffset + start * 4, length);
|
|
101
|
-
checkFloat32Allocation(length, budget);
|
|
102
|
-
const result = new Float32Array(length);
|
|
103
|
-
new Uint8Array(result.buffer).set(new Uint8Array(storage.buffer, storage.byteOffset + start * 4, length * 4));
|
|
104
|
-
return result;
|
|
411
|
+
})();
|
|
105
412
|
}
|
|
106
413
|
});
|
|
107
414
|
}
|
|
108
|
-
export function setFloat32Member(value, property, entry) {
|
|
109
|
-
const key = String(property);
|
|
110
|
-
if (isFloat32Index(key)) {
|
|
415
|
+
export function setFloat32Member(value, property, entry, budget) {
|
|
416
|
+
const key = typeof property === "symbol" ? property : String(property);
|
|
417
|
+
if (typeof key !== "symbol" && isFloat32Index(key)) {
|
|
111
418
|
Reflect.set(value, key, float32Number(entry));
|
|
112
419
|
return;
|
|
113
420
|
}
|
|
114
421
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
115
|
-
|
|
422
|
+
const inherited = descriptor ?? (budget === undefined ? undefined : getSandboxPropertyDescriptor(value, key, budget));
|
|
423
|
+
if (descriptor === undefined && typeof key === "string" &&
|
|
424
|
+
(budget === undefined || !float32Prototypes.has(budget)) &&
|
|
116
425
|
["length", "byteLength", "byteOffset", "buffer", "BYTES_PER_ELEMENT"].includes(key))
|
|
117
|
-
throw new TypeError(`Cannot assign to read only property '${key}'.`);
|
|
118
|
-
if (
|
|
119
|
-
throw new TypeError(`Cannot assign to read only property '${key}'.`);
|
|
426
|
+
throw new TypeError(`Cannot assign to read only property '${String(key)}'.`);
|
|
427
|
+
if (inherited !== undefined && (!("value" in inherited) || !inherited.writable))
|
|
428
|
+
throw new TypeError(`Cannot assign to read only property '${String(key)}'.`);
|
|
120
429
|
Object.defineProperty(value, key, descriptor === undefined
|
|
121
430
|
? { value: entry, configurable: true, enumerable: true, writable: true }
|
|
122
431
|
: { value: entry });
|
|
123
432
|
}
|
|
124
|
-
function relativeIndex(
|
|
125
|
-
if (value === undefined)
|
|
126
|
-
return fallback;
|
|
127
|
-
const numeric = float32Number(value);
|
|
433
|
+
function relativeIndex(numeric, length) {
|
|
128
434
|
const integer = Number.isNaN(numeric) ? 0 : Math.trunc(numeric);
|
|
129
435
|
return integer < 0 ? Math.max(length + integer, 0) : Math.min(integer, length);
|
|
130
436
|
}
|
|
@@ -12,7 +12,7 @@ import { isSandboxDate } from "../date.js";
|
|
|
12
12
|
import { createSandboxBox } from "../boxed.js";
|
|
13
13
|
import { createObjectGlobal, hasOwnSandboxProperty } from "./object.js";
|
|
14
14
|
import { isGuestHostObject } from "../host-capabilities.js";
|
|
15
|
-
import { isFloat32Array } from "../float32.js";
|
|
15
|
+
import { float32Number, isFloat32Array, isFloat32Index } from "../float32.js";
|
|
16
16
|
import { deleteSandboxProperty, setSandboxProperty } from "../interpreter.js";
|
|
17
17
|
import { acquireSandboxIterator, closeIterator, getSandboxIterator, readIteratorResult } from "../iteration.js";
|
|
18
18
|
import { sandboxNumber, sandboxString } from "../string-coercion.js";
|
|
@@ -681,8 +681,8 @@ async function definePropertiesFromObject(target, descriptors, budget, context)
|
|
|
681
681
|
}
|
|
682
682
|
export function defineDataProperty(target, key, descriptor, budget) {
|
|
683
683
|
budget.visitNode();
|
|
684
|
-
if (isFloat32Array(target))
|
|
685
|
-
|
|
684
|
+
if (isFloat32Array(target) && typeof key !== "symbol" && isFloat32Index(String(key)) && "value" in descriptor)
|
|
685
|
+
descriptor = { ...descriptor, value: float32Number(descriptor.value) };
|
|
686
686
|
const properties = objectProperties(target, true);
|
|
687
687
|
if (Array.isArray(properties)) {
|
|
688
688
|
if (key === "length" && "value" in descriptor)
|
|
@@ -5,6 +5,7 @@ export declare function createBuiltinBindings(options: Parameters<typeof createC
|
|
|
5
5
|
clock?: RunClock;
|
|
6
6
|
functionHasInstance?: boolean;
|
|
7
7
|
errorPrototypes?: boolean;
|
|
8
|
+
float32Prototypes?: boolean;
|
|
8
9
|
}): {
|
|
9
10
|
RegExp: import("./values.js").SandboxClosure;
|
|
10
11
|
Promise: import("./values.js").SandboxClosure;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createConsoleJsonGlobals } from "./globals/console-json.js";
|
|
2
2
|
import { createCollectionGlobals } from "./globals/collections.js";
|
|
3
|
-
import { createFloat32ArrayGlobal } from "./globals/float32array.js";
|
|
3
|
+
import { createFloat32ArrayGlobal, createFloat32ArrayPrototypes } from "./globals/float32array.js";
|
|
4
4
|
import { createErrorGlobals, createErrorPrototypes } from "./globals/error.js";
|
|
5
5
|
import { createMathGlobals } from "./globals/math.js";
|
|
6
6
|
import { createRegexGlobals } from "./globals/regex.js";
|
|
@@ -18,7 +18,7 @@ export function createBuiltinBindings(options) {
|
|
|
18
18
|
const bindings = {
|
|
19
19
|
...createConsoleJsonGlobals(options),
|
|
20
20
|
...createCollectionGlobals(options),
|
|
21
|
-
Float32Array: createFloat32ArrayGlobal(options.budget),
|
|
21
|
+
Float32Array: createFloat32ArrayGlobal(options.budget, options.float32Prototypes !== false),
|
|
22
22
|
Date: createDateGlobal(options),
|
|
23
23
|
Symbol: createSymbolGlobal(options.budget),
|
|
24
24
|
BigInt: createBigIntGlobal(options.budget),
|
|
@@ -31,6 +31,8 @@ export function createBuiltinBindings(options) {
|
|
|
31
31
|
...createRegexGlobals(options)
|
|
32
32
|
};
|
|
33
33
|
createFunctionPrototype(options.budget, options.functionHasInstance);
|
|
34
|
+
if (options.float32Prototypes !== false)
|
|
35
|
+
createFloat32ArrayPrototypes(options.budget, bindings.Float32Array);
|
|
34
36
|
if (options.errorPrototypes !== false)
|
|
35
37
|
createErrorPrototypes(options.budget, bindings);
|
|
36
38
|
createGeneratorPrototypes(options.budget);
|