poe-code 14.0.65 → 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.
Files changed (42) hide show
  1. package/dist/index.js +1723 -797
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-4VT2M7WL.js → chunk-MKTUVVEB.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-WBWD7ZCM.js → chunk-YKISHTWT.js} +1675 -772
  7. package/packages/safe-js/dist/chunks/chunk-YKISHTWT.js.map +7 -0
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.js +2 -2
  11. package/packages/safe-js/dist/interp/accessors.d.ts +9 -0
  12. package/packages/safe-js/dist/interp/accessors.js +68 -0
  13. package/packages/safe-js/dist/interp/async.js +3 -3
  14. package/packages/safe-js/dist/interp/classes.js +10 -4
  15. package/packages/safe-js/dist/interp/exceptions.d.ts +1 -1
  16. package/packages/safe-js/dist/interp/exceptions.js +47 -8
  17. package/packages/safe-js/dist/interp/globals/collections.js +53 -16
  18. package/packages/safe-js/dist/interp/globals/console-json.js +41 -26
  19. package/packages/safe-js/dist/interp/globals/object-array.js +229 -68
  20. package/packages/safe-js/dist/interp/globals/object.js +6 -3
  21. package/packages/safe-js/dist/interp/globals/primitives.js +11 -5
  22. package/packages/safe-js/dist/interp/interpreter.d.ts +2 -2
  23. package/packages/safe-js/dist/interp/interpreter.js +83 -44
  24. package/packages/safe-js/dist/interp/iteration.js +13 -0
  25. package/packages/safe-js/dist/interp/methods/array.d.ts +1 -1
  26. package/packages/safe-js/dist/interp/methods/array.js +368 -109
  27. package/packages/safe-js/dist/interp/methods/function.js +56 -20
  28. package/packages/safe-js/dist/interp/methods/regex.js +1 -1
  29. package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
  30. package/packages/safe-js/dist/interp/object-model.js +48 -10
  31. package/packages/safe-js/dist/interp/patterns.d.ts +2 -2
  32. package/packages/safe-js/dist/interp/patterns.js +35 -16
  33. package/packages/safe-js/dist/interp/promise.d.ts +1 -1
  34. package/packages/safe-js/dist/interp/promise.js +103 -63
  35. package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
  36. package/packages/safe-js/dist/interp/string-coercion.js +47 -37
  37. package/packages/safe-js/dist/interp/values.d.ts +2 -1
  38. package/packages/safe-js/dist/interp/values.js +26 -1
  39. package/packages/safe-js/dist/parse/parser.d.ts +1 -1
  40. package/packages/safe-js/dist/parse/parser.js +37 -8
  41. package/packages/safe-js/dist/chunks/chunk-WBWD7ZCM.js.map +0 -7
  42. /package/packages/safe-js/dist/chunks/{chunk-4VT2M7WL.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 { getHostObjectKeys, isGuestHostObject } from "../host-capabilities.js";
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 getOwnEnumerableEntries } from "../values.js";
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]) => allocateProducedSandboxValue(getOwnEnumerableValues(value), options.budget),
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]) => allocateProducedSandboxValue(getOwnEnumerableEntries(value), options.budget),
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 !== undefined && !("value" in descriptor))
53
- throw new TypeError("Only data property descriptors are supported.");
54
- return descriptor === undefined ? undefined : allocateProducedSandboxValue(descriptor, options.budget);
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
- defineDataProperty(value, await sandboxString(key, options.budget, context), dataDescriptor(descriptor), options.budget);
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
- const properties = getOwnEnumerableEntries(descriptors).map(([key, descriptor]) => [key, dataDescriptor(descriptor)]);
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
- const properties = getOwnEnumerableEntries(descriptors).map(([key, descriptor]) => [key, dataDescriptor(descriptor)]);
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, [{ [Symbol.iterator]: () => iterator }]), null), options.budget);
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, () => [items, iterator.retainedValue, object, entry, key, value, failure]);
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 = context?.getProperty !== undefined
291
- ? context.getProperty(entry, 0)
292
- : getSandboxDataProperty(entry, 0, budget);
293
- value = context?.getProperty !== undefined
294
- ? context.getProperty(entry, 1)
295
- : getSandboxDataProperty(entry, 1, budget);
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 + 1 +
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
- for (const source of sources) {
327
- if (source === null || source === undefined) {
328
- continue;
329
- }
330
- for (const [key, value] of getOwnEnumerableEntries(source)) {
331
- setSandboxProperty(target, key, value, budget);
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 target;
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,22 +398,85 @@ function objectProperties(value, mutable = false) {
352
398
  throw new TypeError("Expected a sandbox object or function.");
353
399
  return value;
354
400
  }
355
- function dataDescriptor(input) {
356
- const source = objectProperties(input);
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
- for (const field of ["get", "set", "value", "writable", "enumerable", "configurable"]) {
359
- const entry = Object.getOwnPropertyDescriptor(source, field);
360
- if (entry === undefined)
361
- continue;
362
- if (!("value" in entry) || field === "get" || field === "set") {
363
- throw new TypeError("Only data property descriptors are supported.");
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
- if (field === "value")
366
- descriptor.value = entry.value;
367
- else
368
- descriptor[field] = Boolean(entry.value);
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
481
  export function defineDataProperty(target, key, descriptor, budget) {
373
482
  budget.visitNode();
@@ -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, () => [items, iterator?.retainedValue, mapFn, constructor, result, currentValue, failure]);
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 = Number.isNaN(number) || number <= 0 ? 0 : Math.min(Math.trunc(number), Number.MAX_SAFE_INTEGER);
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 = isSandboxClosure(constructor) && constructor.construct !== undefined
437
- ? await invokeBuiltinClosure(constructor, iterator === undefined ? [length] : [], budget, context, undefined, true)
438
- : createArrayFromConstructorArgs([length], budget);
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 + 1 +
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 getOwnEnumerableKeys(value) {
509
- if (isGuestHostObject(value))
510
- return getHostObjectKeys(value);
511
- return getOwnEnumerableEntries(value).map(([key]) => key);
512
- }
513
- function getOwnEnumerableValues(value) {
514
- return getOwnEnumerableEntries(value).map(([, entryValue]) => entryValue);
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) {
@@ -33,9 +33,12 @@ export function createObjectGlobal(methods, budget) {
33
33
  return construct(args);
34
34
  const value = construct([]);
35
35
  const prototype = context.getProperty(context.newTarget, "prototype");
36
- if (typeof prototype === "object" && prototype !== null)
37
- setSandboxPrototype(value, prototype, budget);
38
- return value;
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);
39
42
  }
40
43
  });
41
44
  const properties = materializeFunctionProperties(constructor);
@@ -9,13 +9,17 @@ export function createPrimitiveConstructor(options, budget) {
9
9
  const prototype = createSandboxBox(initial);
10
10
  const allocate = (value, context) => {
11
11
  const box = createSandboxBox(value);
12
- if (context?.newTarget !== undefined && context.newTarget !== constructor) {
13
- const prototype = context.getProperty(context.newTarget, "prototype");
12
+ const finish = (prototype) => {
14
13
  if (typeof prototype === "object" && prototype !== null)
15
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);
16
21
  }
17
- budget.chargeDataUsage(measureSandboxData([box]));
18
- return box;
22
+ return finish(undefined);
19
23
  };
20
24
  const constructor = createSandboxClosure({
21
25
  guest: true,
@@ -25,7 +29,9 @@ export function createPrimitiveConstructor(options, budget) {
25
29
  call: options.call,
26
30
  construct: (args, context) => {
27
31
  const value = options.call(args, context);
28
- return value instanceof Promise ? value.then(result => allocate(result, context)) : allocate(value, context);
32
+ return value instanceof Promise
33
+ ? value.then((result) => allocate(result, context))
34
+ : allocate(value, context);
29
35
  }
30
36
  });
31
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, checkInherited?: boolean): void;
74
+ export declare function setSandboxProperty(target: SandboxValue, property: string | number, value: SandboxValue, budget: Budget, checkInherited?: boolean, context?: SandboxCallContext): void | Promise<void>;