poe-code 14.0.64 → 14.0.66
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 +8832 -7273
- 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-3EXDJDQM.js → chunk-MKTUVVEB.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-XO7B4P27.js → chunk-YKISHTWT.js} +4474 -2978
- package/packages/safe-js/dist/chunks/chunk-YKISHTWT.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/index.js.map +1 -1
- package/packages/safe-js/dist/interp/accessors.d.ts +9 -0
- package/packages/safe-js/dist/interp/accessors.js +68 -0
- package/packages/safe-js/dist/interp/async.d.ts +13 -2
- package/packages/safe-js/dist/interp/async.js +19 -9
- package/packages/safe-js/dist/interp/classes.d.ts +4 -0
- package/packages/safe-js/dist/interp/classes.js +182 -0
- package/packages/safe-js/dist/interp/exceptions.d.ts +1 -1
- package/packages/safe-js/dist/interp/exceptions.js +51 -9
- package/packages/safe-js/dist/interp/globals/collections.js +53 -16
- package/packages/safe-js/dist/interp/globals/console-json.js +41 -26
- package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +230 -69
- package/packages/safe-js/dist/interp/globals/object.js +13 -2
- package/packages/safe-js/dist/interp/globals/primitives.js +16 -5
- package/packages/safe-js/dist/interp/interpreter.d.ts +2 -2
- package/packages/safe-js/dist/interp/interpreter.js +168 -61
- package/packages/safe-js/dist/interp/iteration.js +13 -0
- package/packages/safe-js/dist/interp/methods/array.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/array.js +368 -109
- package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/function.js +56 -20
- package/packages/safe-js/dist/interp/methods/regex.js +1 -1
- package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
- package/packages/safe-js/dist/interp/object-model.js +48 -10
- package/packages/safe-js/dist/interp/patterns.d.ts +3 -3
- package/packages/safe-js/dist/interp/patterns.js +36 -17
- package/packages/safe-js/dist/interp/promise.d.ts +1 -1
- package/packages/safe-js/dist/interp/promise.js +103 -63
- package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
- package/packages/safe-js/dist/interp/string-coercion.js +47 -37
- package/packages/safe-js/dist/interp/values.d.ts +4 -2
- package/packages/safe-js/dist/interp/values.js +26 -1
- package/packages/safe-js/dist/lint/class-elements.d.ts +5 -0
- package/packages/safe-js/dist/lint/class-elements.js +20 -0
- package/packages/safe-js/dist/lint/rules/AS-async-not-needed.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-destructure-null-default.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-export-import-meta.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-floating-promise.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-jsdoc-type.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-large-literal.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-missing-async.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-mutating-frozen.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-needless-template.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-shadow-global.js +12 -0
- package/packages/safe-js/dist/lint/rules/AS-unbounded-loop.js +11 -0
- package/packages/safe-js/dist/lint/rules/AS-unreachable.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-unused-import.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS001.js +0 -1
- package/packages/safe-js/dist/lint/rules/AS003.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS006-007.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS009.js +20 -1
- package/packages/safe-js/dist/lint/rules/AS010.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS011.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS015.js +9 -0
- package/packages/safe-js/dist/parse/function-source.d.ts +2 -2
- package/packages/safe-js/dist/parse/parser.d.ts +42 -2
- package/packages/safe-js/dist/parse/parser.js +208 -35
- package/packages/safe-js/dist/parse/tokenizer.js +3 -0
- package/packages/safe-js/dist/parse.d.ts +1 -1
- package/packages/safe-js/dist/chunks/chunk-XO7B4P27.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-3EXDJDQM.js.map → chunk-MKTUVVEB.js.map} +0 -0
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { isFatalSandboxError } from "../budget.js";
|
|
2
|
+
import { accessorAdapter, accessorClosure, retainedAccessorClosures } from "../accessors.js";
|
|
2
3
|
import { invokeBuiltinClosure } from "../builtin-call.js";
|
|
3
4
|
import { createDataCheckpoint } from "../data-checkpoint.js";
|
|
5
|
+
import { retainValues } from "../resources.js";
|
|
4
6
|
import { isCapturedException } from "../exceptions.js";
|
|
5
7
|
import { isSandboxDate } from "../date.js";
|
|
6
8
|
import { createSandboxBox } from "../boxed.js";
|
|
7
9
|
import { getDatePrototype } from "./date.js";
|
|
8
10
|
import { createObjectGlobal, hasOwnSandboxProperty } from "./object.js";
|
|
9
|
-
import {
|
|
11
|
+
import { isGuestHostObject } from "../host-capabilities.js";
|
|
10
12
|
import { isFloat32Array } from "../float32.js";
|
|
11
13
|
import { setSandboxProperty } from "../interpreter.js";
|
|
12
14
|
import { getSandboxIterator } from "../iteration.js";
|
|
13
15
|
import { sandboxNumber, sandboxString } from "../string-coercion.js";
|
|
14
16
|
import { createNumericParsers } from "./numeric-parsers.js";
|
|
15
17
|
import { createPrimitiveConstructor } from "./primitives.js";
|
|
16
|
-
import { getSandboxDataProperty, getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
17
|
-
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, measureSandboxData, ownEnumerableSandboxEntries as
|
|
18
|
+
import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
19
|
+
import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
|
|
18
20
|
export function createObjectArrayGlobals(options) {
|
|
19
21
|
return {
|
|
20
22
|
Object: createObjectGlobal({
|
|
@@ -25,12 +27,16 @@ export function createObjectArrayGlobals(options) {
|
|
|
25
27
|
}),
|
|
26
28
|
values: createSandboxClosure({
|
|
27
29
|
sandbox: true,
|
|
28
|
-
call: ([value]) =>
|
|
30
|
+
call: ([value], context) => context === undefined
|
|
31
|
+
? allocateProducedSandboxValue(getDirectEntries(value).map(([, entry]) => entry), options.budget)
|
|
32
|
+
: getOwnEnumerableEntries(value, options.budget, context).then((entries) => allocateProducedSandboxValue(entries.map(([, entry]) => entry), options.budget)),
|
|
29
33
|
name: "values"
|
|
30
34
|
}),
|
|
31
35
|
entries: createSandboxClosure({
|
|
32
36
|
sandbox: true,
|
|
33
|
-
call: ([value]) =>
|
|
37
|
+
call: ([value], context) => context === undefined
|
|
38
|
+
? allocateProducedSandboxValue(getDirectEntries(value), options.budget)
|
|
39
|
+
: getOwnEnumerableEntries(value, options.budget, context).then((entries) => allocateProducedSandboxValue(entries, options.budget)),
|
|
34
40
|
name: "entries"
|
|
35
41
|
}),
|
|
36
42
|
hasOwn: createSandboxClosure({
|
|
@@ -41,7 +47,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
41
47
|
const name = sandboxString(key, options.budget, context);
|
|
42
48
|
return typeof name === "string"
|
|
43
49
|
? hasOwnSandboxProperty(value, name, false)
|
|
44
|
-
: name.then(property => hasOwnSandboxProperty(value, property, false));
|
|
50
|
+
: name.then((property) => hasOwnSandboxProperty(value, property, false));
|
|
45
51
|
},
|
|
46
52
|
name: "hasOwn"
|
|
47
53
|
}),
|
|
@@ -49,12 +55,22 @@ export function createObjectArrayGlobals(options) {
|
|
|
49
55
|
sandbox: true,
|
|
50
56
|
call: async ([value, key], context) => {
|
|
51
57
|
const descriptor = Object.getOwnPropertyDescriptor(objectProperties(value), await sandboxString(key, options.budget, context));
|
|
52
|
-
if (descriptor
|
|
53
|
-
|
|
54
|
-
return
|
|
58
|
+
if (descriptor === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
return allocateProducedSandboxValue(exposePropertyDescriptor(descriptor), options.budget);
|
|
55
61
|
},
|
|
56
62
|
name: "getOwnPropertyDescriptor"
|
|
57
63
|
}),
|
|
64
|
+
getOwnPropertyDescriptors: createSandboxClosure({
|
|
65
|
+
sandbox: true,
|
|
66
|
+
call: ([value]) => {
|
|
67
|
+
const descriptors = Object.create(null);
|
|
68
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(objectProperties(value))))
|
|
69
|
+
defineOwnDataProperty(descriptors, key, exposePropertyDescriptor(descriptor));
|
|
70
|
+
return allocateProducedSandboxValue(descriptors, options.budget);
|
|
71
|
+
},
|
|
72
|
+
name: "getOwnPropertyDescriptors"
|
|
73
|
+
}),
|
|
58
74
|
getOwnPropertyNames: createSandboxClosure({
|
|
59
75
|
sandbox: true,
|
|
60
76
|
call: ([value]) => budgetSandboxValue(Object.getOwnPropertyNames(objectProperties(value)), options.budget),
|
|
@@ -63,18 +79,17 @@ export function createObjectArrayGlobals(options) {
|
|
|
63
79
|
defineProperty: createSandboxClosure({
|
|
64
80
|
sandbox: true,
|
|
65
81
|
call: async ([value, key, descriptor], context) => {
|
|
66
|
-
|
|
82
|
+
objectProperties(value, true);
|
|
83
|
+
const property = await sandboxString(key, options.budget, context);
|
|
84
|
+
defineDataProperty(value, property, await propertyDescriptor(descriptor, options.budget, context), options.budget);
|
|
67
85
|
return value;
|
|
68
86
|
},
|
|
69
87
|
name: "defineProperty"
|
|
70
88
|
}),
|
|
71
89
|
defineProperties: createSandboxClosure({
|
|
72
90
|
sandbox: true,
|
|
73
|
-
call: ([value, descriptors]) => {
|
|
74
|
-
|
|
75
|
-
for (const [key, descriptor] of properties) {
|
|
76
|
-
defineDataProperty(value, key, descriptor, options.budget);
|
|
77
|
-
}
|
|
91
|
+
call: async ([value, descriptors], context) => {
|
|
92
|
+
await definePropertiesFromObject(value, descriptors, options.budget, context);
|
|
78
93
|
return value;
|
|
79
94
|
},
|
|
80
95
|
name: "defineProperties"
|
|
@@ -104,16 +119,13 @@ export function createObjectArrayGlobals(options) {
|
|
|
104
119
|
}),
|
|
105
120
|
create: createSandboxClosure({
|
|
106
121
|
sandbox: true,
|
|
107
|
-
call: ([prototype, descriptors]) => {
|
|
122
|
+
call: async ([prototype, descriptors], context) => {
|
|
108
123
|
if (prototype !== null)
|
|
109
124
|
objectProperties(prototype);
|
|
110
125
|
const value = Object.create(null);
|
|
111
126
|
setSandboxPrototype(value, prototype, options.budget);
|
|
112
127
|
if (descriptors !== undefined) {
|
|
113
|
-
|
|
114
|
-
for (const [key, descriptor] of properties) {
|
|
115
|
-
defineDataProperty(value, key, descriptor, options.budget);
|
|
116
|
-
}
|
|
128
|
+
await definePropertiesFromObject(value, descriptors, options.budget, context);
|
|
117
129
|
}
|
|
118
130
|
return allocateProducedSandboxValue(value, options.budget);
|
|
119
131
|
},
|
|
@@ -133,7 +145,9 @@ export function createObjectArrayGlobals(options) {
|
|
|
133
145
|
}
|
|
134
146
|
if (context === undefined && !iterator.generator && !iterator.asynchronous) {
|
|
135
147
|
// The direct host adapter preserves synchronous results and native hooks.
|
|
136
|
-
return allocateProducedSandboxValue(Object.setPrototypeOf(Reflect.apply(Object.fromEntries, Object, [
|
|
148
|
+
return allocateProducedSandboxValue(Object.setPrototypeOf(Reflect.apply(Object.fromEntries, Object, [
|
|
149
|
+
{ [Symbol.iterator]: () => iterator }
|
|
150
|
+
]), null), options.budget);
|
|
137
151
|
}
|
|
138
152
|
return objectFromSandboxEntries(value, iterator, options.budget, context);
|
|
139
153
|
},
|
|
@@ -158,7 +172,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
158
172
|
}),
|
|
159
173
|
assign: createSandboxClosure({
|
|
160
174
|
sandbox: true,
|
|
161
|
-
call: ([target, ...sources]) => assignSandboxValues(target, sources, options.budget),
|
|
175
|
+
call: ([target, ...sources], context) => assignSandboxValues(target, sources, options.budget, context),
|
|
162
176
|
name: "assign"
|
|
163
177
|
})
|
|
164
178
|
}, options.budget),
|
|
@@ -191,7 +205,7 @@ export function createObjectArrayGlobals(options) {
|
|
|
191
205
|
properties: {
|
|
192
206
|
raw: createSandboxClosure({
|
|
193
207
|
sandbox: true,
|
|
194
|
-
call: (args) => stringRaw(args, options.budget),
|
|
208
|
+
call: (args, context) => stringRaw(args, options.budget, context),
|
|
195
209
|
name: "raw"
|
|
196
210
|
}),
|
|
197
211
|
fromCharCode: createSandboxClosure({
|
|
@@ -254,7 +268,15 @@ async function objectFromSandboxEntries(items, iterator, budget, context) {
|
|
|
254
268
|
let value;
|
|
255
269
|
let failure;
|
|
256
270
|
const retained = {};
|
|
257
|
-
budget.setRetainedValues(retained, () => [
|
|
271
|
+
budget.setRetainedValues(retained, () => [
|
|
272
|
+
items,
|
|
273
|
+
iterator.retainedValue,
|
|
274
|
+
object,
|
|
275
|
+
entry,
|
|
276
|
+
key,
|
|
277
|
+
value,
|
|
278
|
+
failure
|
|
279
|
+
]);
|
|
258
280
|
const checkData = createDataCheckpoint(budget, context);
|
|
259
281
|
const closeOnThrow = async (error) => {
|
|
260
282
|
failure = isCapturedException(error) ? error.reason : error;
|
|
@@ -287,14 +309,17 @@ async function objectFromSandboxEntries(items, iterator, budget, context) {
|
|
|
287
309
|
if (typeof entry !== "object" || entry === null) {
|
|
288
310
|
throw new TypeError("Object.fromEntries requires entry objects.");
|
|
289
311
|
}
|
|
290
|
-
key =
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
312
|
+
key =
|
|
313
|
+
context?.getProperty !== undefined
|
|
314
|
+
? await context.getProperty(entry, 0)
|
|
315
|
+
: getSandboxDataProperty(entry, 0, budget);
|
|
316
|
+
value =
|
|
317
|
+
context?.getProperty !== undefined
|
|
318
|
+
? await context.getProperty(entry, 1)
|
|
319
|
+
: getSandboxDataProperty(entry, 1, budget);
|
|
296
320
|
const property = await sandboxString(key, budget, context);
|
|
297
|
-
const growth = property.length +
|
|
321
|
+
const growth = property.length +
|
|
322
|
+
1 +
|
|
298
323
|
(budget.limits.dataSize === undefined ? 0 : measureSandboxData([value]));
|
|
299
324
|
budget.visitNode();
|
|
300
325
|
defineOwnDataProperty(object, property, value);
|
|
@@ -312,7 +337,7 @@ async function objectFromSandboxEntries(items, iterator, budget, context) {
|
|
|
312
337
|
budget.setRetainedValues(retained, undefined);
|
|
313
338
|
}
|
|
314
339
|
}
|
|
315
|
-
function assignSandboxValues(target, sources, budget) {
|
|
340
|
+
function assignSandboxValues(target, sources, budget, context) {
|
|
316
341
|
if (target === null || target === undefined) {
|
|
317
342
|
throw new TypeError("Object.assign(target, ...sources) requires a non-null target.");
|
|
318
343
|
}
|
|
@@ -323,15 +348,36 @@ function assignSandboxValues(target, sources, budget) {
|
|
|
323
348
|
if (!isGuestClosure(target) && !isAssignableSandboxTarget(target)) {
|
|
324
349
|
throw new TypeError("Object.assign(target, ...sources) requires an object or array target.");
|
|
325
350
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
351
|
+
if (context === undefined) {
|
|
352
|
+
for (const source of sources) {
|
|
353
|
+
if (source === null || source === undefined)
|
|
354
|
+
continue;
|
|
355
|
+
for (const [key, value] of getDirectEntries(source))
|
|
356
|
+
setSandboxProperty(target, key, value, budget);
|
|
332
357
|
}
|
|
358
|
+
return target;
|
|
333
359
|
}
|
|
334
|
-
return
|
|
360
|
+
return (async () => {
|
|
361
|
+
const release = retainValues(budget, () => [target, ...sources]);
|
|
362
|
+
try {
|
|
363
|
+
for (const source of sources) {
|
|
364
|
+
if (source === null || source === undefined)
|
|
365
|
+
continue;
|
|
366
|
+
for (const key of getOwnEnumerableKeys(source)) {
|
|
367
|
+
if (!hasOwnSandboxProperty(source, key, true))
|
|
368
|
+
continue;
|
|
369
|
+
const value = await (context.getProperty !== undefined
|
|
370
|
+
? context.getProperty(source, key)
|
|
371
|
+
: getSandboxDataProperty(source, key, budget));
|
|
372
|
+
await setSandboxProperty(target, key, value, budget, true, context);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return target;
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
release();
|
|
379
|
+
}
|
|
380
|
+
})();
|
|
335
381
|
}
|
|
336
382
|
function objectProperties(value, mutable = false) {
|
|
337
383
|
if (isSandboxDate(value)) {
|
|
@@ -352,24 +398,87 @@ function objectProperties(value, mutable = false) {
|
|
|
352
398
|
throw new TypeError("Expected a sandbox object or function.");
|
|
353
399
|
return value;
|
|
354
400
|
}
|
|
355
|
-
function
|
|
356
|
-
|
|
401
|
+
function exposePropertyDescriptor(descriptor) {
|
|
402
|
+
return ("value" in descriptor
|
|
403
|
+
? descriptor
|
|
404
|
+
: {
|
|
405
|
+
get: accessorClosure(descriptor.get),
|
|
406
|
+
set: accessorClosure(descriptor.set),
|
|
407
|
+
enumerable: descriptor.enumerable,
|
|
408
|
+
configurable: descriptor.configurable
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
async function propertyDescriptor(input, budget, context) {
|
|
412
|
+
objectProperties(input);
|
|
357
413
|
const descriptor = {};
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
414
|
+
const release = retainValues(budget, () => [
|
|
415
|
+
input,
|
|
416
|
+
descriptor.value,
|
|
417
|
+
...retainedAccessorClosures(descriptor)
|
|
418
|
+
]);
|
|
419
|
+
try {
|
|
420
|
+
for (const field of [
|
|
421
|
+
"enumerable",
|
|
422
|
+
"configurable",
|
|
423
|
+
"value",
|
|
424
|
+
"writable",
|
|
425
|
+
"get",
|
|
426
|
+
"set"
|
|
427
|
+
]) {
|
|
428
|
+
if (getSandboxPropertyDescriptor(input, field, budget) === undefined &&
|
|
429
|
+
!hasOwnSandboxProperty(input, field, false))
|
|
430
|
+
continue;
|
|
431
|
+
const value = await (context?.getProperty !== undefined
|
|
432
|
+
? context.getProperty(input, field)
|
|
433
|
+
: getSandboxDataProperty(input, field, budget));
|
|
434
|
+
if (field === "get" || field === "set") {
|
|
435
|
+
if (value !== undefined && !isSandboxClosure(value))
|
|
436
|
+
throw new TypeError("Accessor must be a function or undefined.");
|
|
437
|
+
descriptor[field] =
|
|
438
|
+
value === undefined ? undefined : accessorAdapter(value, field);
|
|
439
|
+
}
|
|
440
|
+
else if (field === "value") {
|
|
441
|
+
descriptor.value = value;
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
descriptor[field] = Boolean(value);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (("get" in descriptor || "set" in descriptor) &&
|
|
448
|
+
("value" in descriptor || "writable" in descriptor))
|
|
449
|
+
throw new TypeError("A property cannot be both a data property and an accessor.");
|
|
450
|
+
return descriptor;
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
release();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
async function definePropertiesFromObject(target, descriptors, budget, context) {
|
|
457
|
+
objectProperties(target, true);
|
|
458
|
+
const properties = [];
|
|
459
|
+
const release = retainValues(budget, () => [
|
|
460
|
+
target,
|
|
461
|
+
descriptors,
|
|
462
|
+
properties,
|
|
463
|
+
...properties.flatMap(([, descriptor]) => retainedAccessorClosures(descriptor))
|
|
464
|
+
]);
|
|
465
|
+
try {
|
|
466
|
+
for (const key of getOwnEnumerableKeys(descriptors)) {
|
|
467
|
+
if (!hasOwnSandboxProperty(descriptors, key, true))
|
|
468
|
+
continue;
|
|
469
|
+
const descriptor = await (context?.getProperty !== undefined
|
|
470
|
+
? context.getProperty(descriptors, key)
|
|
471
|
+
: getSandboxDataProperty(descriptors, key, budget));
|
|
472
|
+
properties.push([key, await propertyDescriptor(descriptor, budget, context)]);
|
|
364
473
|
}
|
|
365
|
-
|
|
366
|
-
descriptor
|
|
367
|
-
|
|
368
|
-
|
|
474
|
+
for (const [key, descriptor] of properties)
|
|
475
|
+
defineDataProperty(target, key, descriptor, budget);
|
|
476
|
+
}
|
|
477
|
+
finally {
|
|
478
|
+
release();
|
|
369
479
|
}
|
|
370
|
-
return descriptor;
|
|
371
480
|
}
|
|
372
|
-
function defineDataProperty(target, key, descriptor, budget) {
|
|
481
|
+
export function defineDataProperty(target, key, descriptor, budget) {
|
|
373
482
|
budget.visitNode();
|
|
374
483
|
if (isFloat32Array(target))
|
|
375
484
|
throw new TypeError("Typed array property descriptors are not supported.");
|
|
@@ -414,7 +523,15 @@ async function arrayFromSandboxValues(args, budget, context) {
|
|
|
414
523
|
let currentValue;
|
|
415
524
|
let failure;
|
|
416
525
|
const retained = {};
|
|
417
|
-
budget.setRetainedValues(retained, () => [
|
|
526
|
+
budget.setRetainedValues(retained, () => [
|
|
527
|
+
items,
|
|
528
|
+
iterator?.retainedValue,
|
|
529
|
+
mapFn,
|
|
530
|
+
constructor,
|
|
531
|
+
result,
|
|
532
|
+
currentValue,
|
|
533
|
+
failure
|
|
534
|
+
]);
|
|
418
535
|
const checkData = createDataCheckpoint(budget, context);
|
|
419
536
|
const closeOnThrow = async (error) => {
|
|
420
537
|
failure = isCapturedException(error) ? error.reason : error;
|
|
@@ -430,12 +547,16 @@ async function arrayFromSandboxValues(args, budget, context) {
|
|
|
430
547
|
try {
|
|
431
548
|
let length = 0;
|
|
432
549
|
if (iterator === undefined) {
|
|
433
|
-
const number = await sandboxNumber(read("length"), budget, context);
|
|
434
|
-
length =
|
|
550
|
+
const number = await sandboxNumber(await read("length"), budget, context);
|
|
551
|
+
length =
|
|
552
|
+
Number.isNaN(number) || number <= 0
|
|
553
|
+
? 0
|
|
554
|
+
: Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
435
555
|
}
|
|
436
|
-
result =
|
|
437
|
-
|
|
438
|
-
|
|
556
|
+
result =
|
|
557
|
+
isSandboxClosure(constructor) && constructor.construct !== undefined
|
|
558
|
+
? await invokeBuiltinClosure(constructor, iterator === undefined ? [length] : [], budget, context, undefined, true)
|
|
559
|
+
: createArrayFromConstructorArgs([length], budget);
|
|
439
560
|
checkData(result, 0, true);
|
|
440
561
|
let index = 0;
|
|
441
562
|
while (iterator !== undefined || index < length) {
|
|
@@ -456,7 +577,7 @@ async function arrayFromSandboxValues(args, budget, context) {
|
|
|
456
577
|
currentValue = next.value;
|
|
457
578
|
}
|
|
458
579
|
else {
|
|
459
|
-
currentValue = read(index);
|
|
580
|
+
currentValue = await read(index);
|
|
460
581
|
}
|
|
461
582
|
try {
|
|
462
583
|
if (Array.isArray(result))
|
|
@@ -464,7 +585,8 @@ async function arrayFromSandboxValues(args, budget, context) {
|
|
|
464
585
|
if (mapFn !== undefined)
|
|
465
586
|
currentValue = await invokeBuiltinClosure(mapFn, [currentValue, index], budget, context, thisValue);
|
|
466
587
|
const key = String(index);
|
|
467
|
-
const growth = key.length +
|
|
588
|
+
const growth = key.length +
|
|
589
|
+
1 +
|
|
468
590
|
(Array.isArray(result) ? Math.max(0, index + 1 - result.length) : 0) +
|
|
469
591
|
(budget.limits.dataSize === undefined ? 0 : measureSandboxData([currentValue]));
|
|
470
592
|
budget.visitNode();
|
|
@@ -505,20 +627,59 @@ function createArrayFromConstructorArgs(args, budget) {
|
|
|
505
627
|
release();
|
|
506
628
|
}
|
|
507
629
|
}
|
|
508
|
-
function
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
630
|
+
async function getOwnEnumerableEntries(value, budget, context) {
|
|
631
|
+
const entries = [];
|
|
632
|
+
const release = retainValues(budget, () => [value, entries]);
|
|
633
|
+
try {
|
|
634
|
+
for (const key of getOwnEnumerableKeys(value)) {
|
|
635
|
+
if (!hasOwnSandboxProperty(value, key, true))
|
|
636
|
+
continue;
|
|
637
|
+
entries.push([
|
|
638
|
+
key,
|
|
639
|
+
await (context?.getProperty !== undefined
|
|
640
|
+
? context.getProperty(value, key)
|
|
641
|
+
: getSandboxDataProperty(value, key, budget))
|
|
642
|
+
]);
|
|
643
|
+
}
|
|
644
|
+
return entries;
|
|
645
|
+
}
|
|
646
|
+
finally {
|
|
647
|
+
release();
|
|
648
|
+
}
|
|
515
649
|
}
|
|
516
650
|
function budgetSandboxValue(value, budget) {
|
|
517
651
|
const sandboxValue = deepCopyToSandbox(value);
|
|
518
652
|
return allocateProducedSandboxValue(sandboxValue, budget);
|
|
519
653
|
}
|
|
520
|
-
function stringRaw(args, budget) {
|
|
654
|
+
function stringRaw(args, budget, context) {
|
|
521
655
|
const [template, ...substitutions] = args;
|
|
656
|
+
if (context?.getProperty !== undefined)
|
|
657
|
+
return (async () => {
|
|
658
|
+
if (template === null || template === undefined)
|
|
659
|
+
throw new TypeError("String.raw requires a template object.");
|
|
660
|
+
const raw = await context.getProperty(template, "raw");
|
|
661
|
+
if (raw === null || raw === undefined)
|
|
662
|
+
throw new TypeError("String.raw requires raw strings.");
|
|
663
|
+
const number = await sandboxNumber(await context.getProperty(raw, "length"), budget, context);
|
|
664
|
+
const length = Number.isNaN(number) || number <= 0
|
|
665
|
+
? 0
|
|
666
|
+
: Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
|
|
667
|
+
let result = "";
|
|
668
|
+
const retained = {};
|
|
669
|
+
budget.setRetainedValues(retained, () => [raw, result]);
|
|
670
|
+
try {
|
|
671
|
+
for (let index = 0; index < length; index++) {
|
|
672
|
+
budget.visitNode();
|
|
673
|
+
result = budget.allocateString(result + (await sandboxString(await context.getProperty(raw, index), budget, context)));
|
|
674
|
+
if (index + 1 < length && index < substitutions.length)
|
|
675
|
+
result = budget.allocateString(result + (await sandboxString(substitutions[index], budget, context)));
|
|
676
|
+
}
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
679
|
+
finally {
|
|
680
|
+
budget.setRetainedValues(retained, undefined);
|
|
681
|
+
}
|
|
682
|
+
})();
|
|
522
683
|
const raw = getTemplateRawParts(template);
|
|
523
684
|
let result = "";
|
|
524
685
|
for (let index = 0; index < raw.length; index += 1) {
|
|
@@ -5,7 +5,7 @@ import { isSandboxErrorConstructorInstance } from "../exceptions.js";
|
|
|
5
5
|
import { isFloat32Array } from "../float32.js";
|
|
6
6
|
import { hasHostObjectMember, isGuestHostObject } from "../host-capabilities.js";
|
|
7
7
|
import { collectionIteratorState, isSandboxCollectionIterator } from "../collection-iterator.js";
|
|
8
|
-
import { getSandboxPrototype, installObjectPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties } from "../object-model.js";
|
|
8
|
+
import { getSandboxPrototype, installObjectPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
9
9
|
import { sandboxString } from "../string-coercion.js";
|
|
10
10
|
import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../values.js";
|
|
11
11
|
import { measureSandboxData } from "../values.js";
|
|
@@ -28,7 +28,18 @@ export function createObjectGlobal(methods, budget) {
|
|
|
28
28
|
name: "Object",
|
|
29
29
|
length: 1,
|
|
30
30
|
call: construct,
|
|
31
|
-
construct
|
|
31
|
+
construct: (args, context) => {
|
|
32
|
+
if (context?.newTarget === undefined || context.newTarget === constructor)
|
|
33
|
+
return construct(args);
|
|
34
|
+
const value = construct([]);
|
|
35
|
+
const prototype = context.getProperty(context.newTarget, "prototype");
|
|
36
|
+
const finish = (prototype) => {
|
|
37
|
+
if (typeof prototype === "object" && prototype !== null)
|
|
38
|
+
setSandboxPrototype(value, prototype, budget);
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
return prototype instanceof Promise ? prototype.then(finish) : finish(prototype);
|
|
42
|
+
}
|
|
32
43
|
});
|
|
33
44
|
const properties = materializeFunctionProperties(constructor);
|
|
34
45
|
const prototype = properties.prototype;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSandboxBox, primitiveReceiver } from "../boxed.js";
|
|
2
|
-
import { installBoxedPrototype, materializeFunctionProperties } from "../object-model.js";
|
|
2
|
+
import { installBoxedPrototype, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
|
|
3
3
|
import { getNumberMember, numberMethodNames } from "../methods/number.js";
|
|
4
4
|
import { getStringMember, stringMethodNames } from "../methods/string.js";
|
|
5
5
|
import { createSandboxClosure, isSandboxClosure, measureSandboxData } from "../values.js";
|
|
@@ -7,10 +7,19 @@ export function createPrimitiveConstructor(options, budget) {
|
|
|
7
7
|
const initial = { Number: 0, String: "", Boolean: false }[options.name];
|
|
8
8
|
const kind = typeof initial;
|
|
9
9
|
const prototype = createSandboxBox(initial);
|
|
10
|
-
const allocate = (value) => {
|
|
10
|
+
const allocate = (value, context) => {
|
|
11
11
|
const box = createSandboxBox(value);
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const finish = (prototype) => {
|
|
13
|
+
if (typeof prototype === "object" && prototype !== null)
|
|
14
|
+
setSandboxPrototype(box, prototype, budget);
|
|
15
|
+
budget.chargeDataUsage(measureSandboxData([box]));
|
|
16
|
+
return box;
|
|
17
|
+
};
|
|
18
|
+
if (context?.newTarget !== undefined && context.newTarget !== constructor) {
|
|
19
|
+
const prototype = context.getProperty(context.newTarget, "prototype");
|
|
20
|
+
return prototype instanceof Promise ? prototype.then(finish) : finish(prototype);
|
|
21
|
+
}
|
|
22
|
+
return finish(undefined);
|
|
14
23
|
};
|
|
15
24
|
const constructor = createSandboxClosure({
|
|
16
25
|
guest: true,
|
|
@@ -20,7 +29,9 @@ export function createPrimitiveConstructor(options, budget) {
|
|
|
20
29
|
call: options.call,
|
|
21
30
|
construct: (args, context) => {
|
|
22
31
|
const value = options.call(args, context);
|
|
23
|
-
return value instanceof Promise
|
|
32
|
+
return value instanceof Promise
|
|
33
|
+
? value.then((result) => allocate(result, context))
|
|
34
|
+
: allocate(value, context);
|
|
24
35
|
}
|
|
25
36
|
});
|
|
26
37
|
const properties = materializeFunctionProperties(constructor);
|
|
@@ -5,7 +5,7 @@ import type { GeneratorCompletion } from "./generator.js";
|
|
|
5
5
|
import { Budget, type CompileOwner } from "./budget.js";
|
|
6
6
|
import { CompileScope } from "./regex/compile-guard.js";
|
|
7
7
|
import { type PatternContext } from "./patterns.js";
|
|
8
|
-
import { type SandboxValue } from "./values.js";
|
|
8
|
+
import { type SandboxCallContext, type SandboxValue } from "./values.js";
|
|
9
9
|
import { Scope } from "./scope.js";
|
|
10
10
|
export type InterpreterValue = SandboxValue;
|
|
11
11
|
export type InterpreterStats = {
|
|
@@ -71,4 +71,4 @@ export declare function interpret(node: ParseResult, options?: InterpretOptions)
|
|
|
71
71
|
export { Scope } from "./scope.js";
|
|
72
72
|
declare function evaluateNode(node: ParseResult, context: EvaluationContext): Promise<EvaluationResult>;
|
|
73
73
|
export declare function createPatternContext(context: AsyncEvaluationContext, scope?: Scope, evaluate?: typeof evaluateNode): PatternContext;
|
|
74
|
-
export declare function setSandboxProperty(target: SandboxValue, property: string | number, value: SandboxValue, budget: Budget): void
|
|
74
|
+
export declare function setSandboxProperty(target: SandboxValue, property: string | number, value: SandboxValue, budget: Budget, checkInherited?: boolean, context?: SandboxCallContext): void | Promise<void>;
|