poe-code 14.0.64 → 14.0.65

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 (57) hide show
  1. package/dist/index.js +7442 -6809
  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-3EXDJDQM.js → chunk-4VT2M7WL.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-XO7B4P27.js → chunk-WBWD7ZCM.js} +8189 -7596
  7. package/packages/safe-js/dist/chunks/chunk-WBWD7ZCM.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/index.js.map +1 -1
  12. package/packages/safe-js/dist/interp/async.d.ts +13 -2
  13. package/packages/safe-js/dist/interp/async.js +16 -6
  14. package/packages/safe-js/dist/interp/classes.d.ts +4 -0
  15. package/packages/safe-js/dist/interp/classes.js +176 -0
  16. package/packages/safe-js/dist/interp/exceptions.js +4 -1
  17. package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
  18. package/packages/safe-js/dist/interp/globals/object-array.js +1 -1
  19. package/packages/safe-js/dist/interp/globals/object.js +10 -2
  20. package/packages/safe-js/dist/interp/globals/primitives.js +8 -3
  21. package/packages/safe-js/dist/interp/interpreter.d.ts +1 -1
  22. package/packages/safe-js/dist/interp/interpreter.js +95 -27
  23. package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
  24. package/packages/safe-js/dist/interp/methods/function.js +1 -1
  25. package/packages/safe-js/dist/interp/patterns.d.ts +1 -1
  26. package/packages/safe-js/dist/interp/patterns.js +1 -1
  27. package/packages/safe-js/dist/interp/values.d.ts +2 -1
  28. package/packages/safe-js/dist/lint/class-elements.d.ts +5 -0
  29. package/packages/safe-js/dist/lint/class-elements.js +20 -0
  30. package/packages/safe-js/dist/lint/rules/AS-async-not-needed.js +16 -0
  31. package/packages/safe-js/dist/lint/rules/AS-destructure-null-default.js +9 -0
  32. package/packages/safe-js/dist/lint/rules/AS-export-import-meta.js +9 -0
  33. package/packages/safe-js/dist/lint/rules/AS-floating-promise.js +9 -0
  34. package/packages/safe-js/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
  35. package/packages/safe-js/dist/lint/rules/AS-jsdoc-type.js +9 -0
  36. package/packages/safe-js/dist/lint/rules/AS-large-literal.js +9 -0
  37. package/packages/safe-js/dist/lint/rules/AS-missing-async.js +16 -0
  38. package/packages/safe-js/dist/lint/rules/AS-mutating-frozen.js +9 -0
  39. package/packages/safe-js/dist/lint/rules/AS-needless-template.js +9 -0
  40. package/packages/safe-js/dist/lint/rules/AS-shadow-global.js +12 -0
  41. package/packages/safe-js/dist/lint/rules/AS-unbounded-loop.js +11 -0
  42. package/packages/safe-js/dist/lint/rules/AS-unreachable.js +9 -0
  43. package/packages/safe-js/dist/lint/rules/AS-unused-import.js +16 -2
  44. package/packages/safe-js/dist/lint/rules/AS001.js +0 -1
  45. package/packages/safe-js/dist/lint/rules/AS003.js +16 -2
  46. package/packages/safe-js/dist/lint/rules/AS006-007.js +16 -2
  47. package/packages/safe-js/dist/lint/rules/AS009.js +20 -1
  48. package/packages/safe-js/dist/lint/rules/AS010.js +9 -0
  49. package/packages/safe-js/dist/lint/rules/AS011.js +9 -0
  50. package/packages/safe-js/dist/lint/rules/AS015.js +9 -0
  51. package/packages/safe-js/dist/parse/function-source.d.ts +2 -2
  52. package/packages/safe-js/dist/parse/parser.d.ts +42 -2
  53. package/packages/safe-js/dist/parse/parser.js +180 -36
  54. package/packages/safe-js/dist/parse/tokenizer.js +3 -0
  55. package/packages/safe-js/dist/parse.d.ts +1 -1
  56. package/packages/safe-js/dist/chunks/chunk-XO7B4P27.js.map +0 -7
  57. /package/packages/safe-js/dist/chunks/{chunk-3EXDJDQM.js.map → chunk-4VT2M7WL.js.map} +0 -0
@@ -5,6 +5,7 @@ import { assertPromiseExecutionAllowed } from "./promise-tracker.js";
5
5
  import { SandboxJobQueue, runAsyncPrefix, suspendJob } from "./jobs.js";
6
6
  import { withCancellationSignal } from "./cancel.js";
7
7
  import { retainValues } from "./resources.js";
8
+ import { evaluateClass } from "./classes.js";
8
9
  import { sandboxString } from "./string-coercion.js";
9
10
  import { attachErrorSpan, formatErrorStack, replaceErrorStack } from "../error/shape.js";
10
11
  import { evaluateArrowFunctionExpression, evaluateFunctionExpression, evaluateAwaitExpression, emitResumeBreakpoint, createInterpretedClosure, normalizeClosureResult } from "./async.js";
@@ -50,6 +51,15 @@ const dispatchTable = {
50
51
  BlockStatement: evaluateBlockStatement,
51
52
  BooleanLiteral: evaluatePrimitiveLiteral,
52
53
  CallExpression: evaluateCallExpression,
54
+ ClassDeclaration: (node, context) => evaluateClass(node, context, evaluateNode, createCoercionContext(context)),
55
+ ClassExpression: (node, context) => evaluateClass(node, context, evaluateNode, createCoercionContext(context)),
56
+ NewTargetExpression: async (_node, context) => ({ kind: "normal", hasValue: true, value: context.functionEnvironment?.newTarget }),
57
+ Super: async (_node, context) => {
58
+ const home = context.functionEnvironment?.homeObject;
59
+ if (home === undefined)
60
+ throw new ReferenceError("Super binding is unavailable.");
61
+ return { kind: "normal", hasValue: true, value: getSandboxPrototype(home, context.budget) };
62
+ },
53
63
  ConditionalExpression: evaluateConditionalExpression,
54
64
  ContinueStatement: evaluateContinueStatement,
55
65
  DoWhileStatement: evaluateDoWhileStatement,
@@ -182,6 +192,8 @@ export async function interpret(node, options = {}) {
182
192
  export { Scope } from "./scope.js";
183
193
  async function evaluateNode(node, context) {
184
194
  context.assertActive?.();
195
+ if (context.inferredName !== undefined && node.type !== "ClassExpression")
196
+ context = { ...context, inferredName: undefined };
185
197
  const replayWait = promiseReplayContext.getStore()?.beforeNode(node.nodeId);
186
198
  if (replayWait !== undefined)
187
199
  await suspendJob(replayWait);
@@ -332,7 +344,7 @@ async function evaluateObjectExpression(node, context) {
332
344
  const releaseKey = retainValues(context.budget, () => [key.value]);
333
345
  let value;
334
346
  try {
335
- value = await evaluateNode(property.value, context);
347
+ value = await evaluateNode(property.value, { ...context, inferredName: String(key.value) });
336
348
  }
337
349
  finally {
338
350
  releaseKey();
@@ -390,22 +402,32 @@ async function evaluateTemplateLiteral(node, context) {
390
402
  }
391
403
  }
392
404
  async function evaluateTaggedTemplateExpression(node, context) {
393
- const tag = await evaluateNode(node.tag, context);
394
- if (tag.kind !== "normal") {
395
- return tag;
396
- }
397
- if (!isSandboxClosure(tag.value)) {
398
- throw new TypeError("Tagged template tag must be a function.");
399
- }
400
- const values = await evaluateTemplateExpressionValues(node.quasi, context);
401
- if (!values.ok) {
402
- return values.result;
403
- }
404
- return {
405
- kind: "normal",
406
- hasValue: true,
407
- value: await invokeSandboxClosure(tag.value, [createTaggedTemplateStrings(node.quasi, context), ...values.value], context, [...context.callStack, formatStackFrame(node, tag.value.name)])
405
+ const invokeTag = async (tag, receiver) => {
406
+ if (!isSandboxClosure(tag))
407
+ throw new TypeError("Tagged template tag must be a function.");
408
+ const release = retainValues(context.budget, () => [tag, receiver]);
409
+ try {
410
+ const values = await evaluateTemplateExpressionValues(node.quasi, context);
411
+ if (!values.ok)
412
+ return values.result;
413
+ return {
414
+ kind: "normal", hasValue: true,
415
+ value: await invokeSandboxClosure(tag, [createTaggedTemplateStrings(node.quasi, context), ...values.value], context, [...context.callStack, formatStackFrame(node, tag.name)], node.span, receiver)
416
+ };
417
+ }
418
+ finally {
419
+ release();
420
+ }
408
421
  };
422
+ if (node.tag.type === "MemberExpression")
423
+ return evaluateMemberAccess(node.tag, context, async (member) => {
424
+ if (member.kind === "nullish")
425
+ throw new TypeError("Tagged template tag must be a function.");
426
+ const key = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
427
+ return invokeTag(getPropertyValue(member.object, key, context), member.superReceiver === undefined ? member.object : member.superReceiver.value);
428
+ });
429
+ const tag = await evaluateNode(node.tag, context);
430
+ return tag.kind === "normal" ? invokeTag(tag.value, undefined) : tag;
409
431
  }
410
432
  async function evaluateTemplateExpressionValues(node, context) {
411
433
  const values = [];
@@ -552,7 +574,7 @@ async function evaluateAssignmentExpression(node, context) {
552
574
  value: current
553
575
  };
554
576
  }
555
- const right = await evaluateNode(node.right, context);
577
+ const right = await evaluateNode(node.right, { ...context, inferredName: node.left.type === "Identifier" ? node.left.name : undefined });
556
578
  if (right.kind !== "normal") {
557
579
  return right;
558
580
  }
@@ -626,7 +648,10 @@ async function evaluateMemberAssignmentExpression(node, context) {
626
648
  }
627
649
  operands = [value];
628
650
  property ??= await toPropertyKey(member.property, context.budget, createCoercionContext(context));
629
- setSandboxProperty(member.object, property, value, context.budget);
651
+ if (member.superReceiver === undefined)
652
+ setSandboxProperty(member.object, property, value, context.budget);
653
+ else
654
+ setSuperProperty(member.object, member.superReceiver.value, property, value, context.budget);
630
655
  return {
631
656
  kind: "normal",
632
657
  hasValue: true,
@@ -772,7 +797,7 @@ async function evaluateVariableDeclaration(node, context) {
772
797
  hasValue: true,
773
798
  value: undefined
774
799
  }
775
- : await evaluateNode(declarator.init, context);
800
+ : await evaluateNode(declarator.init, { ...context, inferredName: declarator.id.type === "Identifier" ? declarator.id.name : undefined });
776
801
  if (value.kind !== "normal") {
777
802
  return value;
778
803
  }
@@ -946,6 +971,11 @@ function predeclareStatementListBindings(statements, context, functionBody = fal
946
971
  const { scope } = context;
947
972
  const names = new Set();
948
973
  for (const statement of statements) {
974
+ if (statement.type === "ClassDeclaration") {
975
+ scope.predeclare(statement.id.name, "let");
976
+ names.add(statement.id.name);
977
+ continue;
978
+ }
949
979
  if (statement.type === "FunctionDeclaration") {
950
980
  const name = statement.id.name;
951
981
  if (names.has(name) && !(functionBody && scope.getOwnBindingKind(name) === "var")) {
@@ -1646,6 +1676,8 @@ async function evaluateDeleteExpression(node, context) {
1646
1676
  throw createError("UNSUPPORTED_NODE", node, "Unary operator 'delete' requires a member target.");
1647
1677
  }
1648
1678
  return evaluateMemberAccess(node.argument, context, async (member) => {
1679
+ if (member.kind === "resolved" && member.superReceiver !== undefined)
1680
+ throw new ReferenceError("Cannot delete a super property.");
1649
1681
  if (member.kind === "nullish" || member.object === null || member.object === undefined) {
1650
1682
  if (member.kind === "nullish") {
1651
1683
  return {
@@ -1705,7 +1737,10 @@ async function evaluateMemberUpdateExpression(node, context) {
1705
1737
  const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
1706
1738
  const current = toNumber(await toNumericPrimitive(getPropertyValue(member.object, property, context), context));
1707
1739
  const next = node.operator === "++" ? current + 1 : current - 1;
1708
- setSandboxProperty(member.object, property, next, context.budget);
1740
+ if (member.superReceiver === undefined)
1741
+ setSandboxProperty(member.object, property, next, context.budget);
1742
+ else
1743
+ setSuperProperty(member.object, member.superReceiver.value, property, next, context.budget);
1709
1744
  return {
1710
1745
  kind: "normal",
1711
1746
  hasValue: true,
@@ -1771,13 +1806,22 @@ export function createPatternContext(context, scope = context.scope, evaluate =
1771
1806
  const evaluationContext = { ...context, scope };
1772
1807
  return {
1773
1808
  budget: context.budget,
1774
- evaluate: node => evaluate(node, evaluationContext),
1809
+ evaluate: (node, inferredName) => evaluate(node, { ...evaluationContext, inferredName }),
1775
1810
  toPropertyKey: value => toPropertyKey(value, context.budget, createCoercionContext(evaluationContext)),
1776
1811
  getProperty: (value, key) => getPropertyValue(value, key, evaluationContext),
1777
1812
  setProperty: (target, key, value) => setSandboxProperty(target, key, value, context.budget)
1778
1813
  };
1779
1814
  }
1780
1815
  async function evaluateCallExpression(node, context) {
1816
+ if (node.callee.type === "Super") {
1817
+ const construction = context.functionEnvironment?.construction;
1818
+ if (construction === undefined)
1819
+ throw new ReferenceError("Super constructor binding is unavailable.");
1820
+ const args = await evaluateCallArguments(node.arguments, context);
1821
+ if (!args.ok)
1822
+ return args.result;
1823
+ return { kind: "normal", hasValue: true, value: await construction.superCall(args.value) };
1824
+ }
1781
1825
  if (node.callee.type === "MemberExpression") {
1782
1826
  context.budget.visitNode();
1783
1827
  context.stats.nodeVisits += 1;
@@ -1847,6 +1891,7 @@ function attachFatalSandboxErrorContext(error, node, stackFrames) {
1847
1891
  replaceErrorStack(error, stackFrames);
1848
1892
  }
1849
1893
  async function evaluateMemberAccess(node, context, consume) {
1894
+ const superReceiver = node.object.type === "Super" ? { value: context.scope.lookup("this") } : undefined;
1850
1895
  const object = await evaluateNode(node.object, context);
1851
1896
  if (object.kind !== "normal")
1852
1897
  return object;
@@ -1862,7 +1907,8 @@ async function evaluateMemberAccess(node, context, consume) {
1862
1907
  if (result.kind !== "normal")
1863
1908
  return result;
1864
1909
  property = result.value;
1865
- return await consume({ kind: "resolved", object: object.value, property });
1910
+ return await consume({ kind: "resolved", object: object.value, property,
1911
+ ...(superReceiver === undefined ? {} : { superReceiver: { value: superReceiver.value.found ? superReceiver.value.value : undefined } }) });
1866
1912
  }
1867
1913
  finally {
1868
1914
  release();
@@ -1918,6 +1964,8 @@ async function evaluateMemberCallExpression(node, context) {
1918
1964
  ...reference,
1919
1965
  property: await toPropertyKey(reference.property, context.budget, createCoercionContext(context))
1920
1966
  };
1967
+ if (member.superReceiver !== undefined)
1968
+ return evaluateResolvedCallExpression(node, getPropertyValue(member.object, member.property, context), context, member.superReceiver.value);
1921
1969
  if ((typeof member.object === "string" || typeof member.object === "number" || typeof member.object === "boolean") &&
1922
1970
  getBoxedPrototype(member.object, context.budget) !== undefined) {
1923
1971
  if (isDefaultBoxedMethod(member.object, member.property, context.budget)) {
@@ -2468,7 +2516,7 @@ function getArrayMemberValue(target, property, context) {
2468
2516
  }
2469
2517
  return getArrayMember(target, property, createArrayMethodOptions(context));
2470
2518
  }
2471
- export function setSandboxProperty(target, property, value, budget) {
2519
+ export function setSandboxProperty(target, property, value, budget, checkInherited = true) {
2472
2520
  if (isSandboxDate(target))
2473
2521
  throw new TypeError("Date own properties are not supported.");
2474
2522
  if (isGuestHostObject(target)) {
@@ -2505,7 +2553,7 @@ export function setSandboxProperty(target, property, value, budget) {
2505
2553
  Object.defineProperty(target, key, { value });
2506
2554
  }
2507
2555
  else {
2508
- if (typeof prototypeOwner === "object" && prototypeOwner !== null) {
2556
+ if (checkInherited && typeof prototypeOwner === "object" && prototypeOwner !== null) {
2509
2557
  let depth = 0;
2510
2558
  for (let prototype = getSandboxPrototype(prototypeOwner, budget); prototype !== null; prototype = getSandboxPrototype(prototype, budget)) {
2511
2559
  budget.visitNode();
@@ -2522,6 +2570,25 @@ export function setSandboxProperty(target, property, value, budget) {
2522
2570
  defineSandboxProperty(target, key, value);
2523
2571
  }
2524
2572
  }
2573
+ function setSuperProperty(base, receiver, key, value, budget) {
2574
+ if (typeof base !== "object" || base === null)
2575
+ throw new TypeError("Cannot assign a property of null.");
2576
+ let depth = 0;
2577
+ for (let current = base; current !== null; current = getSandboxPrototype(current, budget)) {
2578
+ budget.visitNode();
2579
+ assertSandboxDataDepth(depth++);
2580
+ const properties = isSandboxClosure(current) ? current.properties : current;
2581
+ const descriptor = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, key);
2582
+ if (descriptor === undefined)
2583
+ continue;
2584
+ if (descriptor.writable !== true)
2585
+ throw new TypeError(`Cannot assign to read only property '${key}'.`);
2586
+ break;
2587
+ }
2588
+ if (typeof receiver !== "object" || receiver === null)
2589
+ throw new TypeError("Super assignment requires an object receiver.");
2590
+ setSandboxProperty(receiver, key, value, budget, false);
2591
+ }
2525
2592
  function deleteSandboxProperty(target, property) {
2526
2593
  if (isGuestHostObject(target))
2527
2594
  return deleteHostObjectMember(target, String(property));
@@ -2600,10 +2667,10 @@ function createSetMethodOptions(context) {
2600
2667
  function createFunctionMethodOptions(context) {
2601
2668
  return {
2602
2669
  budget: context.budget,
2603
- callClosure: (closure, args, stack, thisValue, construct) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue, construct)
2670
+ callClosure: (closure, args, stack, thisValue, construct, newTarget) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue, construct, newTarget)
2604
2671
  };
2605
2672
  }
2606
- async function invokeSandboxClosure(callee, args, context, stack, span, thisValue = undefined, construct = false) {
2673
+ async function invokeSandboxClosure(callee, args, context, stack, span, thisValue = undefined, construct = false, newTarget) {
2607
2674
  const leaveCall = context.budget.enterCall();
2608
2675
  try {
2609
2676
  const invoke = construct ? callee.construct : callee.call;
@@ -2614,10 +2681,11 @@ async function invokeSandboxClosure(callee, args, context, stack, span, thisValu
2614
2681
  {
2615
2682
  stack,
2616
2683
  thisValue,
2684
+ newTarget: construct ? newTarget ?? callee : undefined,
2617
2685
  compilation: context.compilation,
2618
2686
  getProperty: (value, property) => getPropertyValue(value, property, context),
2619
2687
  reconcileData: (value) => reconcileDataBudget(context.budget, context.stats, context.scope, value, context.compilation, context.compilation?.parent),
2620
- invokeClosure: (closure, argumentsList, receiver, asConstructor) => invokeSandboxClosure(closure, argumentsList, context, stack, span, receiver, asConstructor),
2688
+ invokeClosure: (closure, argumentsList, receiver, asConstructor, target) => invokeSandboxClosure(closure, argumentsList, context, stack, span, receiver, asConstructor, target),
2621
2689
  ...(span === undefined ? {} : { span })
2622
2690
  }
2623
2691
  ]);
@@ -2,6 +2,6 @@ import { type SandboxClosure, type SandboxValue } from "../values.js";
2
2
  import type { Budget } from "../budget.js";
3
3
  export type FunctionMethodOptions = {
4
4
  budget?: Budget;
5
- callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue: SandboxValue, construct?: boolean) => Promise<SandboxValue> | SandboxValue;
5
+ callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue: SandboxValue, construct?: boolean, newTarget?: SandboxClosure) => Promise<SandboxValue> | SandboxValue;
6
6
  };
7
7
  export declare function getFunctionMember(target: SandboxClosure, property: string | number, options: FunctionMethodOptions): SandboxValue | undefined;
@@ -69,7 +69,7 @@ function callFunctionMethod(target, methodName, args, options, stack) {
69
69
  ...(target.construct === undefined
70
70
  ? {}
71
71
  : {
72
- construct: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], undefined, true)
72
+ construct: (callArgs, context) => options.callClosure(target, [...boundArgs, ...callArgs], context?.stack ?? [], undefined, true, context?.newTarget === bound ? target : context?.newTarget)
73
73
  })
74
74
  });
75
75
  if (hasExplicitSandboxPrototype(target))
@@ -12,7 +12,7 @@ export type PatternTarget = {
12
12
  };
13
13
  export type PatternContext = {
14
14
  budget?: Budget;
15
- evaluate(node: ParseResult): Promise<AsyncEvaluationResult>;
15
+ evaluate(node: ParseResult, inferredName?: string): Promise<AsyncEvaluationResult>;
16
16
  toPropertyKey(value: SandboxValue): Promise<string>;
17
17
  getProperty(value: SandboxValue, key: string | number): SandboxValue;
18
18
  setProperty(target: SandboxValue, key: string | number, value: SandboxValue): void;
@@ -40,7 +40,7 @@ async function bindAssignmentPattern(pattern, value, target, scope, context) {
40
40
  if (value !== undefined) {
41
41
  return bindPattern(pattern.left, value, target, scope, context);
42
42
  }
43
- const defaultValue = await context.evaluate(pattern.right);
43
+ const defaultValue = await context.evaluate(pattern.right, pattern.left.type === "Identifier" ? pattern.left.name : undefined);
44
44
  if (defaultValue.kind !== "normal") {
45
45
  return { ok: false, result: defaultValue };
46
46
  }
@@ -38,6 +38,7 @@ export type SandboxRegex = {
38
38
  readonly [sandboxRegexPattern]: RegexPattern;
39
39
  };
40
40
  export type SandboxCallContext = {
41
+ readonly newTarget?: SandboxClosure;
41
42
  readonly compilation?: CompileScope;
42
43
  readonly span?: {
43
44
  readonly end: {
@@ -55,7 +56,7 @@ export type SandboxCallContext = {
55
56
  readonly thisValue: SandboxValue;
56
57
  readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue;
57
58
  readonly reconcileData?: (value: SandboxValue) => void;
58
- readonly invokeClosure?: (closure: SandboxClosure, args: readonly SandboxValue[], thisValue: SandboxValue, construct?: boolean) => Promise<SandboxValue>;
59
+ readonly invokeClosure?: (closure: SandboxClosure, args: readonly SandboxValue[], thisValue: SandboxValue, construct?: boolean, newTarget?: SandboxClosure) => Promise<SandboxValue>;
59
60
  };
60
61
  export type SandboxClosure = {
61
62
  readonly sourceRange?: FunctionSource;
@@ -0,0 +1,5 @@
1
+ import type { BlockStatement, ClassNode, Expression } from "../parse.js";
2
+ /** Visit both definition-time expressions and deferred element bodies. */
3
+ export declare function visitClassElements(node: ClassNode, expression: (node: Expression) => void, statement: (node: BlockStatement) => void): void;
4
+ /** Await in a computed key belongs to the defining function, unlike methods. */
5
+ export declare function classDefinitionContains(node: ClassNode, expression: (node: Expression) => boolean): boolean;
@@ -0,0 +1,20 @@
1
+ /** Visit both definition-time expressions and deferred element bodies. */
2
+ export function visitClassElements(node, expression, statement) {
3
+ if (node.superClass !== undefined)
4
+ expression(node.superClass);
5
+ for (const element of node.body.body) {
6
+ if (element.type === "StaticBlock") {
7
+ statement(element.body);
8
+ continue;
9
+ }
10
+ if (element.computed)
11
+ expression(element.key);
12
+ if (element.value !== undefined)
13
+ expression(element.value);
14
+ }
15
+ }
16
+ /** Await in a computed key belongs to the defining function, unlike methods. */
17
+ export function classDefinitionContains(node, expression) {
18
+ return (node.superClass !== undefined && expression(node.superClass)) ||
19
+ node.body.body.some(element => element.type !== "StaticBlock" && element.computed && expression(element.key));
20
+ }
@@ -1,3 +1,4 @@
1
+ import { classDefinitionContains, visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  export const AS_ASYNC_NOT_NEEDED_MESSAGE = "Async functions without await should remove the async keyword.";
3
4
  export function AS_ASYNC_NOT_NEEDED(source, options = {}) {
@@ -32,6 +33,10 @@ class ASAsyncNotNeededScanner {
32
33
  }
33
34
  }
34
35
  visitStatement(node) {
36
+ if (node.type === "ClassDeclaration") {
37
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
38
+ return;
39
+ }
35
40
  switch (node.type) {
36
41
  case "FunctionDeclaration":
37
42
  this.visitFunctionExpression(node);
@@ -166,6 +171,10 @@ class ASAsyncNotNeededScanner {
166
171
  this.visitExpression(node.argument);
167
172
  }
168
173
  visitExpression(node) {
174
+ if (node.type === "ClassExpression") {
175
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
176
+ return;
177
+ }
169
178
  switch (node.type) {
170
179
  case "YieldExpression":
171
180
  if (node.argument !== undefined) {
@@ -406,6 +415,8 @@ function statementListContainsAwait(statements) {
406
415
  }
407
416
  function statementContainsAwait(node) {
408
417
  switch (node.type) {
418
+ case "ClassDeclaration":
419
+ return classDefinitionContains(node, expressionContainsAwait);
409
420
  case "BlockStatement":
410
421
  return statementListContainsAwait(node.body);
411
422
  case "ExpressionStatement":
@@ -468,6 +479,11 @@ function variableDeclarationContainsAwait(node) {
468
479
  }
469
480
  function expressionContainsAwait(node) {
470
481
  switch (node.type) {
482
+ case "ClassExpression":
483
+ return classDefinitionContains(node, expressionContainsAwait);
484
+ case "NewTargetExpression":
485
+ case "Super":
486
+ return false;
471
487
  case "AwaitExpression":
472
488
  return true;
473
489
  case "YieldExpression":
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  const MESSAGE = "Destructuring default values only apply to undefined, not null.";
3
4
  const HINT = "Handle null explicitly before destructuring or use ?? after binding.";
@@ -20,6 +21,10 @@ class ASDestructureNullDefaultScanner {
20
21
  }
21
22
  }
22
23
  visitStatement(node) {
24
+ if (node.type === "ClassDeclaration") {
25
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
26
+ return;
27
+ }
23
28
  switch (node.type) {
24
29
  case "FunctionDeclaration":
25
30
  this.visitArrowFunction(node);
@@ -147,6 +152,10 @@ class ASDestructureNullDefaultScanner {
147
152
  this.visitExpression(node.argument);
148
153
  }
149
154
  visitExpression(node) {
155
+ if (node.type === "ClassExpression") {
156
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
157
+ return;
158
+ }
150
159
  switch (node.type) {
151
160
  case "YieldExpression":
152
161
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  export function AS_EXPORT_IMPORT_META(source, options = {}) {
3
4
  return new Scanner(options.filename ?? "<input>", new Set(options.allowedExportNames ?? []), options.defaultExport).scan(source);
@@ -35,6 +36,10 @@ class Scanner {
35
36
  }
36
37
  }
37
38
  visitStatement(node) {
39
+ if (node.type === "ClassDeclaration") {
40
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
41
+ return;
42
+ }
38
43
  switch (node.type) {
39
44
  case "FunctionDeclaration":
40
45
  for (const param of node.params) {
@@ -176,6 +181,10 @@ class Scanner {
176
181
  this.visitExpression(node.argument);
177
182
  }
178
183
  visitExpression(node) {
184
+ if (node.type === "ClassExpression") {
185
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
186
+ return;
187
+ }
179
188
  switch (node.type) {
180
189
  case "YieldExpression":
181
190
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  import { normalizeModuleRegistrations } from "./module-registry.js";
3
4
  const AS_FLOATING_PROMISE_MESSAGE = "Promise-returning call is not awaited, returned, stored, or chained.";
@@ -28,6 +29,10 @@ class ASFloatingPromiseScanner {
28
29
  });
29
30
  }
30
31
  visitStatement(node) {
32
+ if (node.type === "ClassDeclaration") {
33
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
34
+ return;
35
+ }
31
36
  switch (node.type) {
32
37
  case "FunctionDeclaration":
33
38
  this.visitArrowFunction(node);
@@ -163,6 +168,10 @@ class ASFloatingPromiseScanner {
163
168
  this.visitExpression(node.argument);
164
169
  }
165
170
  visitExpression(node) {
171
+ if (node.type === "ClassExpression") {
172
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
173
+ return;
174
+ }
166
175
  switch (node.type) {
167
176
  case "YieldExpression":
168
177
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  export function AS_FRONTMATTER_FIELD_UNUSED(source, options = {}) {
3
4
  if (options.frontmatterFields === undefined) {
@@ -34,6 +35,10 @@ class ASFrontmatterFieldUnusedScanner {
34
35
  }
35
36
  }
36
37
  visitStatement(node) {
38
+ if (node.type === "ClassDeclaration") {
39
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
40
+ return;
41
+ }
37
42
  switch (node.type) {
38
43
  case "FunctionDeclaration":
39
44
  this.visitArrowFunction(node);
@@ -162,6 +167,10 @@ class ASFrontmatterFieldUnusedScanner {
162
167
  this.visitExpression(node.argument);
163
168
  }
164
169
  visitExpression(node) {
170
+ if (node.type === "ClassExpression") {
171
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
172
+ return;
173
+ }
165
174
  switch (node.type) {
166
175
  case "YieldExpression":
167
176
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  import { hasTypedModuleRegistrations } from "./module-registry.js";
3
4
  export function AS_JSDOC_TYPE(source, options = {}) {
@@ -27,6 +28,10 @@ class ASJsdocTypeScanner {
27
28
  }
28
29
  }
29
30
  visitStatement(node) {
31
+ if (node.type === "ClassDeclaration") {
32
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
33
+ return;
34
+ }
30
35
  switch (node.type) {
31
36
  case "FunctionDeclaration":
32
37
  this.visitArrowFunction(node);
@@ -166,6 +171,10 @@ class ASJsdocTypeScanner {
166
171
  }
167
172
  }
168
173
  visitExpression(node) {
174
+ if (node.type === "ClassExpression") {
175
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
176
+ return;
177
+ }
169
178
  switch (node.type) {
170
179
  case "YieldExpression":
171
180
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  const DEFAULT_LARGE_LITERAL_THRESHOLD = 1000;
3
4
  export function AS_LARGE_LITERAL(source, options = {}) {
@@ -21,6 +22,10 @@ class ASLargeLiteralScanner {
21
22
  }
22
23
  }
23
24
  visitStatement(node) {
25
+ if (node.type === "ClassDeclaration") {
26
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
27
+ return;
28
+ }
24
29
  switch (node.type) {
25
30
  case "FunctionDeclaration":
26
31
  this.visitArrowFunction(node);
@@ -144,6 +149,10 @@ class ASLargeLiteralScanner {
144
149
  this.visitExpression(node.argument);
145
150
  }
146
151
  visitExpression(node) {
152
+ if (node.type === "ClassExpression") {
153
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
154
+ return;
155
+ }
147
156
  switch (node.type) {
148
157
  case "YieldExpression":
149
158
  if (node.argument !== undefined) {
@@ -1,3 +1,4 @@
1
+ import { classDefinitionContains, visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  export const AS_MISSING_ASYNC_MESSAGE = "Functions that contain await must be marked async.";
3
4
  export function AS_MISSING_ASYNC(source, options = {}) {
@@ -27,6 +28,10 @@ class ASMissingAsyncScanner {
27
28
  }
28
29
  }
29
30
  visitStatement(node) {
31
+ if (node.type === "ClassDeclaration") {
32
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
33
+ return;
34
+ }
30
35
  switch (node.type) {
31
36
  case "FunctionDeclaration":
32
37
  this.visitFunctionExpression(node);
@@ -150,6 +155,10 @@ class ASMissingAsyncScanner {
150
155
  this.visitExpression(node.argument);
151
156
  }
152
157
  visitExpression(node) {
158
+ if (node.type === "ClassExpression") {
159
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
160
+ return;
161
+ }
153
162
  switch (node.type) {
154
163
  case "YieldExpression":
155
164
  if (node.argument !== undefined) {
@@ -377,6 +386,8 @@ function statementListContainsAwait(statements) {
377
386
  }
378
387
  function statementContainsAwait(node) {
379
388
  switch (node.type) {
389
+ case "ClassDeclaration":
390
+ return classDefinitionContains(node, expressionContainsAwait);
380
391
  case "BlockStatement":
381
392
  return statementListContainsAwait(node.body);
382
393
  case "ExpressionStatement":
@@ -439,6 +450,11 @@ function variableDeclarationContainsAwait(node) {
439
450
  }
440
451
  function expressionContainsAwait(node) {
441
452
  switch (node.type) {
453
+ case "ClassExpression":
454
+ return classDefinitionContains(node, expressionContainsAwait);
455
+ case "NewTargetExpression":
456
+ case "Super":
457
+ return false;
442
458
  case "AwaitExpression":
443
459
  return true;
444
460
  case "YieldExpression":
@@ -1,3 +1,4 @@
1
+ import { visitClassElements } from "../class-elements.js";
1
2
  import { parseModule } from "../../parse/parser.js";
2
3
  const MUTATING_ARRAY_METHODS = new Set([
3
4
  "copyWithin",
@@ -32,6 +33,10 @@ class ASMutatingFrozenScanner {
32
33
  });
33
34
  }
34
35
  visitStatement(node) {
36
+ if (node.type === "ClassDeclaration") {
37
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
38
+ return;
39
+ }
35
40
  switch (node.type) {
36
41
  case "FunctionDeclaration":
37
42
  this.visitArrowFunction(node);
@@ -172,6 +177,10 @@ class ASMutatingFrozenScanner {
172
177
  this.visitExpression(node.argument);
173
178
  }
174
179
  visitExpression(node) {
180
+ if (node.type === "ClassExpression") {
181
+ visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
182
+ return;
183
+ }
175
184
  switch (node.type) {
176
185
  case "YieldExpression":
177
186
  if (node.argument !== undefined) {