poe-code 14.0.57 → 14.0.59
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 +461 -417
- 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-N3CN2ACZ.js → chunk-D4YY44EF.js} +456 -413
- package/packages/safe-js/dist/chunks/{chunk-N3CN2ACZ.js.map → chunk-D4YY44EF.js.map} +4 -4
- package/packages/safe-js/dist/chunks/{chunk-H4O5OPM2.js → chunk-YZGYOQK3.js} +2 -2
- 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/interpreter.js +387 -340
- package/packages/safe-js/dist/interp/resources.d.ts +1 -0
- package/packages/safe-js/dist/interp/resources.js +4 -0
- package/packages/safe-js/dist/realm.js +6 -2
- /package/packages/safe-js/dist/chunks/{chunk-H4O5OPM2.js.map → chunk-YZGYOQK3.js.map} +0 -0
|
@@ -4,6 +4,7 @@ import { toPropertyKey } from "./property-key.js";
|
|
|
4
4
|
import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
|
|
5
5
|
import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
|
|
6
6
|
import { withCancellationSignal } from "./cancel.js";
|
|
7
|
+
import { runResources } from "./resources.js";
|
|
7
8
|
import { attachErrorSpan, formatErrorStack, replaceErrorStack } from "../error/shape.js";
|
|
8
9
|
import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
|
|
9
10
|
import { HostCallResumabilityError } from "./host-call.js";
|
|
@@ -272,89 +273,114 @@ async function evaluateEmptyStatement(_node, _context) {
|
|
|
272
273
|
}
|
|
273
274
|
async function evaluateArrayExpression(node, context) {
|
|
274
275
|
const values = [];
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (
|
|
284
|
-
|
|
276
|
+
const release = retainValues(context.budget, () => [values]);
|
|
277
|
+
try {
|
|
278
|
+
for (const element of node.elements) {
|
|
279
|
+
if (element.type === "UndefinedLiteral" && element.elision === true) {
|
|
280
|
+
values.length += 1;
|
|
281
|
+
context.budget.allocateArrayLength(values.length);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (element.type === "SpreadElement") {
|
|
285
|
+
const spreadValues = await evaluateSpreadElement(element, context);
|
|
286
|
+
if (!spreadValues.ok) {
|
|
287
|
+
return spreadValues.result;
|
|
288
|
+
}
|
|
289
|
+
appendArrayValues(values, spreadValues.value);
|
|
290
|
+
context.budget.allocateArrayLength(values.length);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const result = await evaluateNode(element, context);
|
|
294
|
+
if (result.kind !== "normal") {
|
|
295
|
+
return result;
|
|
285
296
|
}
|
|
286
|
-
|
|
297
|
+
values.push(result.value);
|
|
287
298
|
context.budget.allocateArrayLength(values.length);
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
const result = await evaluateNode(element, context);
|
|
291
|
-
if (result.kind !== "normal") {
|
|
292
|
-
return result;
|
|
293
299
|
}
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
return {
|
|
301
|
+
kind: "normal",
|
|
302
|
+
hasValue: true,
|
|
303
|
+
value: values
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
release();
|
|
296
308
|
}
|
|
297
|
-
return {
|
|
298
|
-
kind: "normal",
|
|
299
|
-
hasValue: true,
|
|
300
|
-
value: values
|
|
301
|
-
};
|
|
302
309
|
}
|
|
303
310
|
async function evaluateObjectExpression(node, context) {
|
|
304
311
|
const object = Object.create(null);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (
|
|
309
|
-
|
|
312
|
+
const release = retainValues(context.budget, () => [object]);
|
|
313
|
+
try {
|
|
314
|
+
for (const property of node.properties) {
|
|
315
|
+
if (property.type === "SpreadElement") {
|
|
316
|
+
const spreadEntries = await evaluateObjectSpread(property, context);
|
|
317
|
+
if (!spreadEntries.ok) {
|
|
318
|
+
return spreadEntries.result;
|
|
319
|
+
}
|
|
320
|
+
for (const [key, value] of spreadEntries.value) {
|
|
321
|
+
defineSandboxProperty(object, key, value);
|
|
322
|
+
}
|
|
323
|
+
continue;
|
|
310
324
|
}
|
|
311
|
-
|
|
312
|
-
|
|
325
|
+
const key = await evaluateObjectPropertyKey(property, context);
|
|
326
|
+
if (!key.ok) {
|
|
327
|
+
return key.result;
|
|
313
328
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
return key.result;
|
|
319
|
-
}
|
|
320
|
-
const value = await evaluateNode(property.value, context);
|
|
321
|
-
if (value.kind !== "normal") {
|
|
322
|
-
return value;
|
|
323
|
-
}
|
|
324
|
-
if (isObjectPrototypeSetterProperty(property, key.value)) {
|
|
325
|
-
if (value.value === null || typeof value.value === "object") {
|
|
326
|
-
setSandboxPrototype(object, value.value, context.budget);
|
|
329
|
+
const releaseKey = retainValues(context.budget, () => [key.value]);
|
|
330
|
+
let value;
|
|
331
|
+
try {
|
|
332
|
+
value = await evaluateNode(property.value, context);
|
|
327
333
|
}
|
|
328
|
-
|
|
334
|
+
finally {
|
|
335
|
+
releaseKey();
|
|
336
|
+
}
|
|
337
|
+
if (value.kind !== "normal") {
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
340
|
+
if (isObjectPrototypeSetterProperty(property, key.value)) {
|
|
341
|
+
if (value.value === null || typeof value.value === "object") {
|
|
342
|
+
setSandboxPrototype(object, value.value, context.budget);
|
|
343
|
+
}
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
defineSandboxProperty(object, String(key.value), value.value);
|
|
329
347
|
}
|
|
330
|
-
|
|
348
|
+
return {
|
|
349
|
+
kind: "normal",
|
|
350
|
+
hasValue: true,
|
|
351
|
+
value: object
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
release();
|
|
331
356
|
}
|
|
332
|
-
return {
|
|
333
|
-
kind: "normal",
|
|
334
|
-
hasValue: true,
|
|
335
|
-
value: object
|
|
336
|
-
};
|
|
337
357
|
}
|
|
338
358
|
function isObjectPrototypeSetterProperty(property, key) {
|
|
339
359
|
return !property.computed && !property.shorthand && key === "__proto__";
|
|
340
360
|
}
|
|
341
361
|
async function evaluateTemplateLiteral(node, context) {
|
|
342
362
|
let value = context.budget.allocateString(node.quasis[0]?.value.cooked ?? "");
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
363
|
+
const release = retainValues(context.budget, () => [value]);
|
|
364
|
+
try {
|
|
365
|
+
for (let index = 0; index < node.expressions.length; index += 1) {
|
|
366
|
+
const expression = await evaluateNode(node.expressions[index], context);
|
|
367
|
+
if (expression.kind !== "normal") {
|
|
368
|
+
return expression;
|
|
369
|
+
}
|
|
370
|
+
const expressionText = context.budget.allocateString(String(expression.value));
|
|
371
|
+
value = context.budget.allocateString(value + expressionText);
|
|
372
|
+
const quasiText = context.budget.allocateString(node.quasis[index + 1]?.value.cooked ?? "");
|
|
373
|
+
value = context.budget.allocateString(value + quasiText);
|
|
347
374
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
375
|
+
return {
|
|
376
|
+
kind: "normal",
|
|
377
|
+
hasValue: true,
|
|
378
|
+
value
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
release();
|
|
352
383
|
}
|
|
353
|
-
return {
|
|
354
|
-
kind: "normal",
|
|
355
|
-
hasValue: true,
|
|
356
|
-
value
|
|
357
|
-
};
|
|
358
384
|
}
|
|
359
385
|
async function evaluateTaggedTemplateExpression(node, context) {
|
|
360
386
|
const tag = await evaluateNode(node.tag, context);
|
|
@@ -376,20 +402,26 @@ async function evaluateTaggedTemplateExpression(node, context) {
|
|
|
376
402
|
}
|
|
377
403
|
async function evaluateTemplateExpressionValues(node, context) {
|
|
378
404
|
const values = [];
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
405
|
+
const release = retainValues(context.budget, () => values);
|
|
406
|
+
try {
|
|
407
|
+
for (const expressionNode of node.expressions) {
|
|
408
|
+
const expression = await evaluateNode(expressionNode, context);
|
|
409
|
+
if (expression.kind !== "normal") {
|
|
410
|
+
return {
|
|
411
|
+
ok: false,
|
|
412
|
+
result: expression
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
values.push(expression.value);
|
|
386
416
|
}
|
|
387
|
-
|
|
417
|
+
return {
|
|
418
|
+
ok: true,
|
|
419
|
+
value: values
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
finally {
|
|
423
|
+
release();
|
|
388
424
|
}
|
|
389
|
-
return {
|
|
390
|
-
ok: true,
|
|
391
|
-
value: values
|
|
392
|
-
};
|
|
393
425
|
}
|
|
394
426
|
function createTaggedTemplateStrings(node, context) {
|
|
395
427
|
context.budget.allocateArrayLength(node.quasis.length);
|
|
@@ -429,23 +461,31 @@ async function evaluateBinaryExpression(node, context) {
|
|
|
429
461
|
if (left.kind !== "normal") {
|
|
430
462
|
return left;
|
|
431
463
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if (typeof right.value !== "object" || right.value === null) {
|
|
439
|
-
throw new TypeError("Right-hand side of 'in' must be an object.");
|
|
464
|
+
let rightValue;
|
|
465
|
+
const release = retainValues(context.budget, () => [left.value, rightValue]);
|
|
466
|
+
try {
|
|
467
|
+
const right = await evaluateNode(node.right, context);
|
|
468
|
+
if (right.kind !== "normal") {
|
|
469
|
+
return right;
|
|
440
470
|
}
|
|
441
|
-
|
|
471
|
+
rightValue = right.value;
|
|
472
|
+
let leftValue = left.value;
|
|
473
|
+
if (node.operator === "in") {
|
|
474
|
+
if (typeof right.value !== "object" || right.value === null) {
|
|
475
|
+
throw new TypeError("Right-hand side of 'in' must be an object.");
|
|
476
|
+
}
|
|
477
|
+
leftValue = await toPropertyKey(leftValue, context.budget, createCoercionContext(context));
|
|
478
|
+
}
|
|
479
|
+
const value = applyBinaryOperator(node, leftValue, right.value, context);
|
|
480
|
+
return {
|
|
481
|
+
kind: "normal",
|
|
482
|
+
hasValue: true,
|
|
483
|
+
value
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
finally {
|
|
487
|
+
release();
|
|
442
488
|
}
|
|
443
|
-
const value = applyBinaryOperator(node, leftValue, right.value, context);
|
|
444
|
-
return {
|
|
445
|
-
kind: "normal",
|
|
446
|
-
hasValue: true,
|
|
447
|
-
value
|
|
448
|
-
};
|
|
449
489
|
}
|
|
450
490
|
async function evaluateAssignmentExpression(node, context) {
|
|
451
491
|
if (node.left.type === "ArrayPattern" || node.left.type === "ObjectPattern") {
|
|
@@ -519,66 +559,70 @@ async function evaluateMemberAssignmentExpression(node, context) {
|
|
|
519
559
|
if (node.left.type !== "MemberExpression") {
|
|
520
560
|
throw new TypeError("Expected member assignment target.");
|
|
521
561
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
return member;
|
|
525
|
-
}
|
|
526
|
-
if (member.kind === "completion") {
|
|
527
|
-
return member.result;
|
|
528
|
-
}
|
|
529
|
-
if (member.kind === "nullish") {
|
|
530
|
-
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
531
|
-
}
|
|
532
|
-
let property;
|
|
533
|
-
let current = undefined;
|
|
534
|
-
if (node.operator !== "=") {
|
|
535
|
-
if (member.object === null || member.object === undefined) {
|
|
562
|
+
return evaluateMemberAccess(node.left, context, async (member) => {
|
|
563
|
+
if (member.kind === "nullish") {
|
|
536
564
|
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
537
565
|
}
|
|
538
|
-
|
|
539
|
-
current =
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
566
|
+
let property;
|
|
567
|
+
let current = undefined;
|
|
568
|
+
if (node.operator !== "=") {
|
|
569
|
+
if (member.object === null || member.object === undefined) {
|
|
570
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
571
|
+
}
|
|
572
|
+
property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
573
|
+
current = getPropertyValue(member.object, property, context);
|
|
574
|
+
}
|
|
575
|
+
if (node.operator === "&&=" && !isTruthy(current)) {
|
|
576
|
+
return {
|
|
577
|
+
kind: "normal",
|
|
578
|
+
hasValue: true,
|
|
579
|
+
value: current
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
if (node.operator === "||=" && isTruthy(current)) {
|
|
583
|
+
return {
|
|
584
|
+
kind: "normal",
|
|
585
|
+
hasValue: true,
|
|
586
|
+
value: current
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (node.operator === "??=" && current !== null && current !== undefined) {
|
|
590
|
+
return {
|
|
591
|
+
kind: "normal",
|
|
592
|
+
hasValue: true,
|
|
593
|
+
value: current
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
let operands = [current, property];
|
|
597
|
+
const release = retainValues(context.budget, () => operands);
|
|
598
|
+
try {
|
|
599
|
+
const right = await evaluateNode(node.right, context);
|
|
600
|
+
if (right.kind !== "normal") {
|
|
601
|
+
return right;
|
|
602
|
+
}
|
|
603
|
+
operands.push(right.value);
|
|
604
|
+
const value = node.operator === "=" ||
|
|
605
|
+
node.operator === "&&=" ||
|
|
606
|
+
node.operator === "||=" ||
|
|
607
|
+
node.operator === "??="
|
|
608
|
+
? right.value
|
|
609
|
+
: await applyCompoundAssignmentOperator(node.operator, current, right.value, context);
|
|
610
|
+
if (member.object === null || member.object === undefined) {
|
|
611
|
+
throw new TypeError("Cannot assign properties of null or undefined.");
|
|
612
|
+
}
|
|
613
|
+
operands = [value];
|
|
614
|
+
property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
615
|
+
setSandboxProperty(member.object, property, value, context.budget);
|
|
616
|
+
return {
|
|
617
|
+
kind: "normal",
|
|
618
|
+
hasValue: true,
|
|
619
|
+
value
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
finally {
|
|
623
|
+
release();
|
|
624
|
+
}
|
|
625
|
+
});
|
|
582
626
|
}
|
|
583
627
|
async function evaluateLogicalExpression(node, context) {
|
|
584
628
|
const left = await evaluateNode(node.left, context);
|
|
@@ -1572,33 +1616,28 @@ async function evaluateDeleteExpression(node, context) {
|
|
|
1572
1616
|
if (node.argument.type !== "MemberExpression") {
|
|
1573
1617
|
throw createError("UNSUPPORTED_NODE", node, "Unary operator 'delete' requires a member target.");
|
|
1574
1618
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
kind: "normal",
|
|
1586
|
-
hasValue: true,
|
|
1587
|
-
value: true
|
|
1588
|
-
};
|
|
1619
|
+
return evaluateMemberAccess(node.argument, context, async (member) => {
|
|
1620
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1621
|
+
if (member.kind === "nullish") {
|
|
1622
|
+
return {
|
|
1623
|
+
kind: "normal",
|
|
1624
|
+
hasValue: true,
|
|
1625
|
+
value: true
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
throw new TypeError("Cannot delete properties of null or undefined.");
|
|
1589
1629
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
};
|
|
1630
|
+
if (!isIndexableSandboxValue(member.object)) {
|
|
1631
|
+
throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
|
|
1632
|
+
}
|
|
1633
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1634
|
+
const deleted = deleteSandboxProperty(member.object, property);
|
|
1635
|
+
return {
|
|
1636
|
+
kind: "normal",
|
|
1637
|
+
hasValue: true,
|
|
1638
|
+
value: deleted
|
|
1639
|
+
};
|
|
1640
|
+
});
|
|
1602
1641
|
}
|
|
1603
1642
|
async function evaluateUpdateExpression(node, context) {
|
|
1604
1643
|
if (node.argument.type === "Identifier") {
|
|
@@ -1630,42 +1669,34 @@ async function evaluateMemberUpdateExpression(node, context) {
|
|
|
1630
1669
|
if (node.argument.type !== "MemberExpression") {
|
|
1631
1670
|
throw new TypeError("Expected member update target.");
|
|
1632
1671
|
}
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
return {
|
|
1648
|
-
kind: "normal",
|
|
1649
|
-
hasValue: true,
|
|
1650
|
-
value: node.prefix ? next : current
|
|
1651
|
-
};
|
|
1672
|
+
return evaluateMemberAccess(node.argument, context, async (member) => {
|
|
1673
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1674
|
+
throw new TypeError("Cannot update properties of null or undefined.");
|
|
1675
|
+
}
|
|
1676
|
+
const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
|
|
1677
|
+
const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
|
|
1678
|
+
const next = node.operator === "++" ? current + 1 : current - 1;
|
|
1679
|
+
setSandboxProperty(member.object, property, next, context.budget);
|
|
1680
|
+
return {
|
|
1681
|
+
kind: "normal",
|
|
1682
|
+
hasValue: true,
|
|
1683
|
+
value: node.prefix ? next : current
|
|
1684
|
+
};
|
|
1685
|
+
});
|
|
1652
1686
|
}
|
|
1653
1687
|
async function evaluateMemberExpression(node, context) {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
hasValue: true,
|
|
1667
|
-
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1668
|
-
};
|
|
1688
|
+
return evaluateMemberAccess(node, context, async (member) => {
|
|
1689
|
+
if (member.kind === "nullish" || member.object === null || member.object === undefined) {
|
|
1690
|
+
if (member.kind === "nullish")
|
|
1691
|
+
return { kind: "normal", hasValue: true, value: undefined };
|
|
1692
|
+
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1693
|
+
}
|
|
1694
|
+
return {
|
|
1695
|
+
kind: "normal",
|
|
1696
|
+
hasValue: true,
|
|
1697
|
+
value: getPropertyValue(member.object, await toPropertyKey(member.property, context.budget, createCoercionContext(context)), context)
|
|
1698
|
+
};
|
|
1699
|
+
});
|
|
1669
1700
|
}
|
|
1670
1701
|
function getPropertyValue(target, property, context) {
|
|
1671
1702
|
if (isGuestHostObject(target))
|
|
@@ -1778,29 +1809,38 @@ function attachFatalSandboxErrorContext(error, node, stackFrames) {
|
|
|
1778
1809
|
attachErrorSpan(error, node.span);
|
|
1779
1810
|
replaceErrorStack(error, stackFrames);
|
|
1780
1811
|
}
|
|
1781
|
-
async function evaluateMemberAccess(node, context) {
|
|
1812
|
+
async function evaluateMemberAccess(node, context, consume) {
|
|
1782
1813
|
const object = await evaluateNode(node.object, context);
|
|
1783
|
-
if (object.kind !== "normal")
|
|
1784
|
-
return
|
|
1785
|
-
kind: "completion",
|
|
1786
|
-
result: object
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1814
|
+
if (object.kind !== "normal")
|
|
1815
|
+
return object;
|
|
1789
1816
|
if ((object.value === null || object.value === undefined) && node.optional) {
|
|
1790
|
-
return {
|
|
1791
|
-
kind: "nullish"
|
|
1792
|
-
};
|
|
1817
|
+
return consume({ kind: "nullish" });
|
|
1793
1818
|
}
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
kind
|
|
1801
|
-
|
|
1802
|
-
property
|
|
1819
|
+
let property;
|
|
1820
|
+
const release = retainValues(context.budget, () => [object.value, property]);
|
|
1821
|
+
try {
|
|
1822
|
+
const result = node.computed
|
|
1823
|
+
? await evaluateNode(node.property, context)
|
|
1824
|
+
: { kind: "normal", value: getStaticPropertyName(node.property) };
|
|
1825
|
+
if (result.kind !== "normal")
|
|
1826
|
+
return result;
|
|
1827
|
+
property = result.value;
|
|
1828
|
+
return await consume({ kind: "resolved", object: object.value, property });
|
|
1829
|
+
}
|
|
1830
|
+
finally {
|
|
1831
|
+
release();
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
function retainValues(budget, values) {
|
|
1835
|
+
const retained = {};
|
|
1836
|
+
budget.setRetainedValues(retained, values);
|
|
1837
|
+
const pending = runResources.getStore()?.referenceReleases;
|
|
1838
|
+
const release = () => {
|
|
1839
|
+
budget.setRetainedValues(retained, undefined);
|
|
1840
|
+
pending?.delete(release);
|
|
1803
1841
|
};
|
|
1842
|
+
pending?.add(release);
|
|
1843
|
+
return release;
|
|
1804
1844
|
}
|
|
1805
1845
|
async function evaluateMemberProperty(node, context) {
|
|
1806
1846
|
const property = await evaluateNode(node, context);
|
|
@@ -1837,89 +1877,84 @@ async function evaluateMemberCallExpression(node, context) {
|
|
|
1837
1877
|
if (node.callee.type !== "MemberExpression") {
|
|
1838
1878
|
throw new TypeError("Expected member call expression.");
|
|
1839
1879
|
}
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
kind: "normal",
|
|
1851
|
-
hasValue: true,
|
|
1852
|
-
value: undefined
|
|
1853
|
-
};
|
|
1880
|
+
return evaluateMemberAccess(node.callee, context, async (reference) => {
|
|
1881
|
+
if (reference.kind === "nullish" || reference.object === null || reference.object === undefined) {
|
|
1882
|
+
if (reference.kind === "nullish") {
|
|
1883
|
+
return {
|
|
1884
|
+
kind: "normal",
|
|
1885
|
+
hasValue: true,
|
|
1886
|
+
value: undefined
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
throw new TypeError("Cannot read properties of null or undefined.");
|
|
1854
1890
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1862
|
-
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
1863
|
-
}
|
|
1864
|
-
if (typeof member.object === "number" && isNumberMethodName(member.property)) {
|
|
1865
|
-
return evaluateNumberMethodCall(node, member.object, member.property, context);
|
|
1866
|
-
}
|
|
1867
|
-
if (Array.isArray(member.object) &&
|
|
1868
|
-
isArrayMethodName(member.property) &&
|
|
1869
|
-
!Object.hasOwn(member.object, member.property)) {
|
|
1870
|
-
return evaluateArrayMethodCall(node, member.object, member.property, context);
|
|
1871
|
-
}
|
|
1872
|
-
if (isSandboxMap(member.object) && isMapMethodName(member.property)) {
|
|
1873
|
-
return evaluateMapMethodCall(node, member.object, member.property, context);
|
|
1874
|
-
}
|
|
1875
|
-
if (isSandboxSet(member.object) && isSetMethodName(member.property)) {
|
|
1876
|
-
return evaluateSetMethodCall(node, member.object, member.property, context);
|
|
1877
|
-
}
|
|
1878
|
-
if (typeof member.object === "string") {
|
|
1879
|
-
return evaluatePrimitiveMemberCall(node, "String", member.property, getStringMember(member.object, member.property, context.budget), context);
|
|
1880
|
-
}
|
|
1881
|
-
if (typeof member.object === "number") {
|
|
1882
|
-
return evaluatePrimitiveMemberCall(node, "Number", member.property, getNumberMember(member.property, context.budget), context);
|
|
1883
|
-
}
|
|
1884
|
-
if (Array.isArray(member.object) && !Object.hasOwn(member.object, member.property)) {
|
|
1885
|
-
return evaluatePrimitiveMemberCall(node, "Array", member.property, getArrayMemberValue(member.object, member.property, context), context);
|
|
1886
|
-
}
|
|
1887
|
-
if (isSandboxMap(member.object)) {
|
|
1888
|
-
return evaluatePrimitiveMemberCall(node, "Map", member.property, getMapMember(member.object, member.property, createMapMethodOptions(context)), context);
|
|
1889
|
-
}
|
|
1890
|
-
if (isSandboxDate(member.object)) {
|
|
1891
|
-
return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
|
|
1892
|
-
}
|
|
1893
|
-
if (isFloat32Array(member.object)) {
|
|
1894
|
-
return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
|
|
1895
|
-
}
|
|
1896
|
-
if (isSandboxSet(member.object)) {
|
|
1897
|
-
return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
|
|
1898
|
-
}
|
|
1899
|
-
if (isSandboxGenerator(member.object)) {
|
|
1900
|
-
const memberValue = getGeneratorMember(member.object, member.property, context.budget);
|
|
1901
|
-
if (memberValue === undefined) {
|
|
1902
|
-
throw new TypeError(`Generator#${String(member.property)} is not a supported method.`);
|
|
1891
|
+
const member = {
|
|
1892
|
+
...reference,
|
|
1893
|
+
property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
|
|
1894
|
+
};
|
|
1895
|
+
if (typeof member.object === "string" && isStringMethodName(member.property)) {
|
|
1896
|
+
return evaluateStringMethodCall(node, member.object, member.property, context);
|
|
1903
1897
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
if (isSandboxClosure(member.object)) {
|
|
1907
|
-
const memberValue = getClosureMemberValue(member.object, member.property, context);
|
|
1908
|
-
if (memberValue === undefined) {
|
|
1909
|
-
throw new TypeError(`Function#${String(member.property)} is not a supported method.`);
|
|
1898
|
+
if (typeof member.object === "number" && isNumberMethodName(member.property)) {
|
|
1899
|
+
return evaluateNumberMethodCall(node, member.object, member.property, context);
|
|
1910
1900
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1901
|
+
if (Array.isArray(member.object) &&
|
|
1902
|
+
isArrayMethodName(member.property) &&
|
|
1903
|
+
!Object.hasOwn(member.object, member.property)) {
|
|
1904
|
+
return evaluateArrayMethodCall(node, member.object, member.property, context);
|
|
1905
|
+
}
|
|
1906
|
+
if (isSandboxMap(member.object) && isMapMethodName(member.property)) {
|
|
1907
|
+
return evaluateMapMethodCall(node, member.object, member.property, context);
|
|
1908
|
+
}
|
|
1909
|
+
if (isSandboxSet(member.object) && isSetMethodName(member.property)) {
|
|
1910
|
+
return evaluateSetMethodCall(node, member.object, member.property, context);
|
|
1911
|
+
}
|
|
1912
|
+
if (typeof member.object === "string") {
|
|
1913
|
+
return evaluatePrimitiveMemberCall(node, "String", member.property, getStringMember(member.object, member.property, context.budget), context);
|
|
1914
|
+
}
|
|
1915
|
+
if (typeof member.object === "number") {
|
|
1916
|
+
return evaluatePrimitiveMemberCall(node, "Number", member.property, getNumberMember(member.property, context.budget), context);
|
|
1917
|
+
}
|
|
1918
|
+
if (Array.isArray(member.object) && !Object.hasOwn(member.object, member.property)) {
|
|
1919
|
+
return evaluatePrimitiveMemberCall(node, "Array", member.property, getArrayMemberValue(member.object, member.property, context), context);
|
|
1920
|
+
}
|
|
1921
|
+
if (isSandboxMap(member.object)) {
|
|
1922
|
+
return evaluatePrimitiveMemberCall(node, "Map", member.property, getMapMember(member.object, member.property, createMapMethodOptions(context)), context);
|
|
1923
|
+
}
|
|
1924
|
+
if (isSandboxDate(member.object)) {
|
|
1925
|
+
return evaluateResolvedCallExpression(node, getDateMember(member.property, context.budget, context.compilation?.owner), context, member.object);
|
|
1926
|
+
}
|
|
1927
|
+
if (isFloat32Array(member.object)) {
|
|
1928
|
+
return evaluateResolvedCallExpression(node, getFloat32Member(member.object, member.property, context.budget), context, member.object);
|
|
1929
|
+
}
|
|
1930
|
+
if (isSandboxSet(member.object)) {
|
|
1931
|
+
return evaluatePrimitiveMemberCall(node, "Set", member.property, getSetMember(member.object, member.property, createSetMethodOptions(context)), context);
|
|
1932
|
+
}
|
|
1933
|
+
if (isSandboxGenerator(member.object)) {
|
|
1934
|
+
const memberValue = getGeneratorMember(member.object, member.property, context.budget);
|
|
1935
|
+
if (memberValue === undefined) {
|
|
1936
|
+
throw new TypeError(`Generator#${String(member.property)} is not a supported method.`);
|
|
1937
|
+
}
|
|
1938
|
+
return evaluateResolvedCallExpression(node, memberValue, context, member.object);
|
|
1939
|
+
}
|
|
1940
|
+
if (isSandboxClosure(member.object)) {
|
|
1941
|
+
const memberValue = getClosureMemberValue(member.object, member.property, context);
|
|
1942
|
+
if (memberValue === undefined) {
|
|
1943
|
+
throw new TypeError(`Function#${String(member.property)} is not a supported method.`);
|
|
1944
|
+
}
|
|
1945
|
+
return evaluateResolvedCallExpression(node, memberValue, context, member.object);
|
|
1946
|
+
}
|
|
1947
|
+
if (isSandboxPromise(member.object)) {
|
|
1948
|
+
return evaluateResolvedCallExpression(node, getPromiseMember(member.property, context.budget), context, member.object);
|
|
1949
|
+
}
|
|
1950
|
+
if (isSandboxRegex(member.object) && isRegexMethodName(member.property)) {
|
|
1951
|
+
return evaluateResolvedCallExpression(node, getRegexMember(member.object, member.property, context.budget), context, member.object);
|
|
1952
|
+
}
|
|
1953
|
+
if (!isIndexableSandboxValue(member.object)) {
|
|
1954
|
+
throw new TypeError("Attempted to read a property from a non-object value.");
|
|
1955
|
+
}
|
|
1956
|
+
return evaluateResolvedCallExpression(node, getMemberValue(member.object, member.property, context), context, member.object);
|
|
1957
|
+
});
|
|
1923
1958
|
}
|
|
1924
1959
|
function evaluatePrimitiveMemberCall(node, receiverType, property, value, context) {
|
|
1925
1960
|
if (value === undefined) {
|
|
@@ -2557,30 +2592,36 @@ async function invokeSandboxClosure(callee, args, context, stack, span, thisValu
|
|
|
2557
2592
|
}
|
|
2558
2593
|
async function evaluateCallArguments(args, context) {
|
|
2559
2594
|
const values = [];
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
if (
|
|
2564
|
-
|
|
2595
|
+
const release = retainValues(context.budget, () => values);
|
|
2596
|
+
try {
|
|
2597
|
+
for (const arg of args) {
|
|
2598
|
+
if (arg.type === "SpreadElement") {
|
|
2599
|
+
const spreadValues = await evaluateSpreadElement(arg, context);
|
|
2600
|
+
if (!spreadValues.ok) {
|
|
2601
|
+
return spreadValues;
|
|
2602
|
+
}
|
|
2603
|
+
appendArrayValues(values, spreadValues.value);
|
|
2604
|
+
context.budget.allocateArrayLength(values.length);
|
|
2605
|
+
continue;
|
|
2565
2606
|
}
|
|
2566
|
-
|
|
2607
|
+
const result = await evaluateNode(arg, context);
|
|
2608
|
+
if (result.kind !== "normal") {
|
|
2609
|
+
return {
|
|
2610
|
+
ok: false,
|
|
2611
|
+
result
|
|
2612
|
+
};
|
|
2613
|
+
}
|
|
2614
|
+
values.push(result.value);
|
|
2567
2615
|
context.budget.allocateArrayLength(values.length);
|
|
2568
|
-
continue;
|
|
2569
2616
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
values.push(result.value);
|
|
2578
|
-
context.budget.allocateArrayLength(values.length);
|
|
2617
|
+
return {
|
|
2618
|
+
ok: true,
|
|
2619
|
+
value: values
|
|
2620
|
+
};
|
|
2621
|
+
}
|
|
2622
|
+
finally {
|
|
2623
|
+
release();
|
|
2579
2624
|
}
|
|
2580
|
-
return {
|
|
2581
|
-
ok: true,
|
|
2582
|
-
value: values
|
|
2583
|
-
};
|
|
2584
2625
|
}
|
|
2585
2626
|
async function evaluateSpreadElement(node, context) {
|
|
2586
2627
|
const value = await evaluateNode(node.argument, context);
|
|
@@ -2595,21 +2636,27 @@ async function evaluateSpreadElement(node, context) {
|
|
|
2595
2636
|
throw new TypeError("Spread arguments must evaluate to an iterable.");
|
|
2596
2637
|
}
|
|
2597
2638
|
const spreadValues = [];
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2639
|
+
const release = retainValues(context.budget, () => [value.value, ...spreadValues]);
|
|
2640
|
+
try {
|
|
2641
|
+
while (true) {
|
|
2642
|
+
const next = await iterator.next();
|
|
2643
|
+
if (typeof next !== "object" || next === null) {
|
|
2644
|
+
throw new TypeError("Iterator result must be an object.");
|
|
2645
|
+
}
|
|
2646
|
+
if (next.done === true) {
|
|
2647
|
+
break;
|
|
2648
|
+
}
|
|
2649
|
+
spreadValues.push(next.value);
|
|
2650
|
+
context.budget.allocateArrayLength(spreadValues.length);
|
|
2605
2651
|
}
|
|
2606
|
-
|
|
2607
|
-
|
|
2652
|
+
return {
|
|
2653
|
+
ok: true,
|
|
2654
|
+
value: spreadValues
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
finally {
|
|
2658
|
+
release();
|
|
2608
2659
|
}
|
|
2609
|
-
return {
|
|
2610
|
-
ok: true,
|
|
2611
|
-
value: spreadValues
|
|
2612
|
-
};
|
|
2613
2660
|
}
|
|
2614
2661
|
async function evaluateObjectSpread(node, context) {
|
|
2615
2662
|
const value = await evaluateNode(node.argument, context);
|