poe-code 14.0.64 → 14.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +8832 -7273
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-3EXDJDQM.js → chunk-MKTUVVEB.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-XO7B4P27.js → chunk-YKISHTWT.js} +4474 -2978
- package/packages/safe-js/dist/chunks/chunk-YKISHTWT.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/index.js.map +1 -1
- package/packages/safe-js/dist/interp/accessors.d.ts +9 -0
- package/packages/safe-js/dist/interp/accessors.js +68 -0
- package/packages/safe-js/dist/interp/async.d.ts +13 -2
- package/packages/safe-js/dist/interp/async.js +19 -9
- package/packages/safe-js/dist/interp/classes.d.ts +4 -0
- package/packages/safe-js/dist/interp/classes.js +182 -0
- package/packages/safe-js/dist/interp/exceptions.d.ts +1 -1
- package/packages/safe-js/dist/interp/exceptions.js +51 -9
- package/packages/safe-js/dist/interp/globals/collections.js +53 -16
- package/packages/safe-js/dist/interp/globals/console-json.js +41 -26
- package/packages/safe-js/dist/interp/globals/object-array.d.ts +2 -1
- package/packages/safe-js/dist/interp/globals/object-array.js +230 -69
- package/packages/safe-js/dist/interp/globals/object.js +13 -2
- package/packages/safe-js/dist/interp/globals/primitives.js +16 -5
- package/packages/safe-js/dist/interp/interpreter.d.ts +2 -2
- package/packages/safe-js/dist/interp/interpreter.js +168 -61
- package/packages/safe-js/dist/interp/iteration.js +13 -0
- package/packages/safe-js/dist/interp/methods/array.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/array.js +368 -109
- package/packages/safe-js/dist/interp/methods/function.d.ts +1 -1
- package/packages/safe-js/dist/interp/methods/function.js +56 -20
- package/packages/safe-js/dist/interp/methods/regex.js +1 -1
- package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
- package/packages/safe-js/dist/interp/object-model.js +48 -10
- package/packages/safe-js/dist/interp/patterns.d.ts +3 -3
- package/packages/safe-js/dist/interp/patterns.js +36 -17
- package/packages/safe-js/dist/interp/promise.d.ts +1 -1
- package/packages/safe-js/dist/interp/promise.js +103 -63
- package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -0
- package/packages/safe-js/dist/interp/string-coercion.js +47 -37
- package/packages/safe-js/dist/interp/values.d.ts +4 -2
- package/packages/safe-js/dist/interp/values.js +26 -1
- package/packages/safe-js/dist/lint/class-elements.d.ts +5 -0
- package/packages/safe-js/dist/lint/class-elements.js +20 -0
- package/packages/safe-js/dist/lint/rules/AS-async-not-needed.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-destructure-null-default.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-export-import-meta.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-floating-promise.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-jsdoc-type.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-large-literal.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-missing-async.js +16 -0
- package/packages/safe-js/dist/lint/rules/AS-mutating-frozen.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-needless-template.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-shadow-global.js +12 -0
- package/packages/safe-js/dist/lint/rules/AS-unbounded-loop.js +11 -0
- package/packages/safe-js/dist/lint/rules/AS-unreachable.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS-unused-import.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS001.js +0 -1
- package/packages/safe-js/dist/lint/rules/AS003.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS006-007.js +16 -2
- package/packages/safe-js/dist/lint/rules/AS009.js +20 -1
- package/packages/safe-js/dist/lint/rules/AS010.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS011.js +9 -0
- package/packages/safe-js/dist/lint/rules/AS015.js +9 -0
- package/packages/safe-js/dist/parse/function-source.d.ts +2 -2
- package/packages/safe-js/dist/parse/parser.d.ts +42 -2
- package/packages/safe-js/dist/parse/parser.js +208 -35
- package/packages/safe-js/dist/parse/tokenizer.js +3 -0
- package/packages/safe-js/dist/parse.d.ts +1 -1
- package/packages/safe-js/dist/chunks/chunk-XO7B4P27.js.map +0 -7
- /package/packages/safe-js/dist/chunks/{chunk-3EXDJDQM.js.map → chunk-MKTUVVEB.js.map} +0 -0
|
@@ -2,3 +2,4 @@ import type { Budget } from "./budget.js";
|
|
|
2
2
|
import { type SandboxCallContext, type SandboxValue } from "./values.js";
|
|
3
3
|
export declare function sandboxNumber(value: SandboxValue, budget: Budget, context?: SandboxCallContext): number | Promise<number>;
|
|
4
4
|
export declare function sandboxString(value: SandboxValue, budget: Budget, context?: SandboxCallContext, joining?: Set<object>): string | Promise<string>;
|
|
5
|
+
export declare function joinSandboxArray(value: SandboxValue & object, length: number, separator: string, budget: Budget, context?: SandboxCallContext, joining?: Set<object>): Promise<string>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
2
|
+
import { readPropertyDescriptor } from "./accessors.js";
|
|
2
3
|
import { dateString, dateTime, isSandboxDate } from "./date.js";
|
|
3
4
|
import { invokeBuiltinClosure } from "./builtin-call.js";
|
|
4
5
|
import { float32Storage, isFloat32Array } from "./float32.js";
|
|
@@ -13,6 +14,7 @@ import { boxedValue, isSandboxBox } from "./boxed.js";
|
|
|
13
14
|
import { isSandboxClosure, isSandboxPromise, isSandboxMap, isSandboxSet, isSandboxRegex, isSandboxGenerator } from "./values.js";
|
|
14
15
|
const defaultStringHook = Symbol("defaultStringHook");
|
|
15
16
|
const defaultValueHook = Symbol("defaultValueHook");
|
|
17
|
+
const joiningArrays = new WeakSet();
|
|
16
18
|
export function sandboxNumber(value, budget, context) {
|
|
17
19
|
if (value === null || typeof value !== "object") {
|
|
18
20
|
if (typeof value === "function")
|
|
@@ -30,18 +32,44 @@ export function sandboxString(value, budget, context, joining = new Set()) {
|
|
|
30
32
|
return objectToPrimitive(value, budget, context, joining, "string")
|
|
31
33
|
.then(primitive => budget.allocateString(String(primitive)));
|
|
32
34
|
}
|
|
35
|
+
export async function joinSandboxArray(value, length, separator, budget, context, joining = new Set()) {
|
|
36
|
+
if (joiningArrays.has(value))
|
|
37
|
+
return "";
|
|
38
|
+
joiningArrays.add(value);
|
|
39
|
+
let text = "";
|
|
40
|
+
const release = retainValues(budget, () => [value, text, separator]);
|
|
41
|
+
try {
|
|
42
|
+
for (let index = 0; index < length; index++) {
|
|
43
|
+
budget.visitNode();
|
|
44
|
+
const element = await readCoercionProperty(value, String(index), context);
|
|
45
|
+
const part = element === null || element === undefined
|
|
46
|
+
? ""
|
|
47
|
+
: await sandboxString(element, budget, context, joining);
|
|
48
|
+
text = budget.allocateString(text + (index === 0 ? "" : separator) + part);
|
|
49
|
+
}
|
|
50
|
+
return text;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
release();
|
|
54
|
+
joiningArrays.delete(value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
33
57
|
async function objectToPrimitive(value, budget, context, joining, hint) {
|
|
34
58
|
const leaveCall = budget.enterCall();
|
|
35
59
|
try {
|
|
36
60
|
budget.visitNode();
|
|
37
61
|
for (const name of hint === "string" ? ["toString", "valueOf"] : ["valueOf", "toString"]) {
|
|
38
|
-
const hook = conversionHook(value, name, budget);
|
|
62
|
+
const hook = await conversionHook(value, name, budget, context);
|
|
39
63
|
let result;
|
|
40
64
|
if (hook === defaultStringHook) {
|
|
41
65
|
result = await defaultToString(value, budget, context, joining);
|
|
42
66
|
}
|
|
43
67
|
else if (hook === defaultValueHook) {
|
|
44
|
-
result = isSandboxDate(value)
|
|
68
|
+
result = isSandboxDate(value)
|
|
69
|
+
? dateTime(value)
|
|
70
|
+
: isSandboxBox(value)
|
|
71
|
+
? boxedValue(value)
|
|
72
|
+
: value;
|
|
45
73
|
}
|
|
46
74
|
else {
|
|
47
75
|
if (!isSandboxClosure(hook))
|
|
@@ -60,7 +88,7 @@ async function objectToPrimitive(value, budget, context, joining, hint) {
|
|
|
60
88
|
leaveCall();
|
|
61
89
|
}
|
|
62
90
|
}
|
|
63
|
-
function conversionHook(value, name, budget) {
|
|
91
|
+
function conversionHook(value, name, budget, context) {
|
|
64
92
|
const implicitBuiltin = !hasExplicitSandboxPrototype(value) &&
|
|
65
93
|
(Array.isArray(value) ||
|
|
66
94
|
isSandboxDate(value) ||
|
|
@@ -80,9 +108,7 @@ function conversionHook(value, name, budget) {
|
|
|
80
108
|
const properties = isGuestClosure(current) ? getGuestFunctionProperties(current) : current;
|
|
81
109
|
const descriptor = properties === undefined ? undefined : Object.getOwnPropertyDescriptor(properties, name);
|
|
82
110
|
if (descriptor !== undefined) {
|
|
83
|
-
|
|
84
|
-
throw new TypeError("String conversion requires sandbox data properties.");
|
|
85
|
-
return descriptor.value;
|
|
111
|
+
return readPropertyDescriptor(descriptor, value, context);
|
|
86
112
|
}
|
|
87
113
|
const parent = getSandboxPrototype(current, budget);
|
|
88
114
|
if (current === value &&
|
|
@@ -107,7 +133,9 @@ async function defaultToString(value, budget, context, joining) {
|
|
|
107
133
|
if (isSandboxSet(value))
|
|
108
134
|
return "[object Set]";
|
|
109
135
|
if (isSandboxCollectionIterator(value))
|
|
110
|
-
return collectionIteratorState(value).collectionKind === "map"
|
|
136
|
+
return collectionIteratorState(value).collectionKind === "map"
|
|
137
|
+
? "[object Map Iterator]"
|
|
138
|
+
: "[object Set Iterator]";
|
|
111
139
|
if (isSandboxGenerator(value))
|
|
112
140
|
return "[object Generator]";
|
|
113
141
|
if (isSandboxRegex(value)) {
|
|
@@ -117,40 +145,23 @@ async function defaultToString(value, budget, context, joining) {
|
|
|
117
145
|
return budget.allocateString(dateString(value));
|
|
118
146
|
if (Array.isArray(value) || isFloat32Array(value)) {
|
|
119
147
|
if (Object.hasOwn(value, "join")) {
|
|
120
|
-
const join =
|
|
148
|
+
const join = await readCoercionProperty(value, "join", context);
|
|
121
149
|
if (!isSandboxClosure(join))
|
|
122
150
|
return isFloat32Array(value) ? "[object Float32Array]" : "[object Array]";
|
|
123
151
|
return invokeBuiltinClosure(join, [], budget, context, value);
|
|
124
152
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
joining.add(value);
|
|
128
|
-
let text = "";
|
|
129
|
-
const release = retainValues(budget, () => [text]);
|
|
130
|
-
try {
|
|
131
|
-
const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
|
|
132
|
-
for (let index = 0; index < length; index++) {
|
|
133
|
-
budget.visitNode();
|
|
134
|
-
const element = ownDataValue(value, String(index));
|
|
135
|
-
const part = element === null || element === undefined
|
|
136
|
-
? ""
|
|
137
|
-
: await sandboxString(element, budget, context, joining);
|
|
138
|
-
text = budget.allocateString(text + (index === 0 ? "" : ",") + part);
|
|
139
|
-
}
|
|
140
|
-
return text;
|
|
141
|
-
}
|
|
142
|
-
finally {
|
|
143
|
-
release();
|
|
144
|
-
joining.delete(value);
|
|
145
|
-
}
|
|
153
|
+
const length = isFloat32Array(value) ? float32Storage(value).length : value.length;
|
|
154
|
+
return joinSandboxArray(value, length, ",", budget, context, joining);
|
|
146
155
|
}
|
|
147
156
|
if (sandboxErrorTypes.has(value)) {
|
|
148
|
-
const nameValue =
|
|
157
|
+
const nameValue = await readCoercionProperty(value, "name", context);
|
|
149
158
|
const name = nameValue === undefined ? "Error" : await sandboxString(nameValue, budget, context, joining);
|
|
150
159
|
const release = retainValues(budget, () => [name]);
|
|
151
160
|
try {
|
|
152
|
-
const messageValue =
|
|
153
|
-
const message = messageValue === undefined
|
|
161
|
+
const messageValue = await readCoercionProperty(value, "message", context);
|
|
162
|
+
const message = messageValue === undefined
|
|
163
|
+
? ""
|
|
164
|
+
: await sandboxString(messageValue, budget, context, joining);
|
|
154
165
|
return name === "" ? message : message === "" ? name : `${name}: ${message}`;
|
|
155
166
|
}
|
|
156
167
|
finally {
|
|
@@ -159,10 +170,9 @@ async function defaultToString(value, budget, context, joining) {
|
|
|
159
170
|
}
|
|
160
171
|
return isSandboxPromise(value) ? "[object Promise]" : "[object Object]";
|
|
161
172
|
}
|
|
162
|
-
function
|
|
173
|
+
function readCoercionProperty(value, name, context) {
|
|
174
|
+
if (context?.getProperty !== undefined)
|
|
175
|
+
return context.getProperty(value, name);
|
|
163
176
|
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
164
|
-
|
|
165
|
-
throw new TypeError("String conversion requires sandbox data properties.");
|
|
166
|
-
}
|
|
167
|
-
return descriptor?.value;
|
|
177
|
+
return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, value, context);
|
|
168
178
|
}
|
|
@@ -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: {
|
|
@@ -53,9 +54,9 @@ export type SandboxCallContext = {
|
|
|
53
54
|
};
|
|
54
55
|
readonly stack: readonly string[];
|
|
55
56
|
readonly thisValue: SandboxValue;
|
|
56
|
-
readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue
|
|
57
|
+
readonly getProperty?: (value: SandboxValue, property: string | number) => SandboxValue | Promise<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;
|
|
@@ -111,6 +112,7 @@ export declare function createSandboxClosure(input: {
|
|
|
111
112
|
retainedValues?: () => Iterable<SandboxValue>;
|
|
112
113
|
}): SandboxClosure;
|
|
113
114
|
export declare function ownEnumerableSandboxEntries(value: SandboxValue, excludedKeys?: ReadonlySet<string>): Array<[string, SandboxValue]>;
|
|
115
|
+
export declare function ownEnumerableSandboxKeys(value: SandboxValue): string[];
|
|
114
116
|
export declare function createSandboxPromise(promise: Promise<SandboxValue>, metadata?: {
|
|
115
117
|
trackReplay?: boolean;
|
|
116
118
|
synchronousPrefix?: Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { bindOtelSpan, getBoundOtelSpan } from "../observability/otel.js";
|
|
2
|
+
import { retainedAccessorClosures } from "./accessors.js";
|
|
2
3
|
import { isSandboxMap, isSandboxSet, sandboxMapBrand, sandboxSetBrand } from "./collection-brands.js";
|
|
3
4
|
import { collectionIteratorState, isSandboxCollectionIterator, restoreSandboxCollectionIterator, snapshotCollectionIterator } from "./collection-iterator.js";
|
|
4
5
|
import { copyNativeDate, exportDate, isSandboxDate } from "./date.js";
|
|
@@ -100,6 +101,17 @@ export function ownEnumerableSandboxEntries(value, excludedKeys) {
|
|
|
100
101
|
entries = Object.entries(Object(value));
|
|
101
102
|
return excludedKeys === undefined ? entries : entries.filter(([key]) => !excludedKeys.has(key));
|
|
102
103
|
}
|
|
104
|
+
export function ownEnumerableSandboxKeys(value) {
|
|
105
|
+
if (isGuestHostObject(value))
|
|
106
|
+
return getHostObjectKeys(value);
|
|
107
|
+
if (value === null || value === undefined)
|
|
108
|
+
throw new TypeError("Cannot convert undefined or null to object.");
|
|
109
|
+
if (isGuestClosure(value))
|
|
110
|
+
return Object.keys(value.properties ?? {});
|
|
111
|
+
if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxPromise(value) || isSandboxRegex(value))
|
|
112
|
+
return [];
|
|
113
|
+
return Object.keys(Object(value));
|
|
114
|
+
}
|
|
103
115
|
export function createSandboxPromise(promise, metadata = {}) {
|
|
104
116
|
const original = metadata.trackReplay === false
|
|
105
117
|
? promise
|
|
@@ -254,6 +266,9 @@ export function measureSandboxData(values, options = {}) {
|
|
|
254
266
|
usage += key.length + 1;
|
|
255
267
|
if ("value" in descriptor)
|
|
256
268
|
visit(descriptor.value, depth + 1);
|
|
269
|
+
else
|
|
270
|
+
for (const closure of retainedAccessorClosures(descriptor))
|
|
271
|
+
visit(closure, depth + 1);
|
|
257
272
|
}
|
|
258
273
|
return;
|
|
259
274
|
}
|
|
@@ -289,6 +304,9 @@ export function measureSandboxData(values, options = {}) {
|
|
|
289
304
|
usage += key.length + 1;
|
|
290
305
|
if ("value" in descriptor)
|
|
291
306
|
visit(descriptor.value, depth + 1);
|
|
307
|
+
else
|
|
308
|
+
for (const closure of retainedAccessorClosures(descriptor))
|
|
309
|
+
visit(closure, depth + 1);
|
|
292
310
|
}
|
|
293
311
|
return;
|
|
294
312
|
}
|
|
@@ -333,6 +351,9 @@ export function measureSandboxData(values, options = {}) {
|
|
|
333
351
|
usage += key.length + 1;
|
|
334
352
|
if ("value" in descriptor)
|
|
335
353
|
visit(descriptor.value, depth + 1);
|
|
354
|
+
else
|
|
355
|
+
for (const closure of retainedAccessorClosures(descriptor))
|
|
356
|
+
visit(closure, depth + 1);
|
|
336
357
|
}
|
|
337
358
|
}
|
|
338
359
|
else
|
|
@@ -386,7 +407,11 @@ export function measureSandboxData(values, options = {}) {
|
|
|
386
407
|
if (!descriptor.enumerable && !hasManagedDescriptors(value))
|
|
387
408
|
continue;
|
|
388
409
|
usage += key.length;
|
|
389
|
-
|
|
410
|
+
if ("value" in descriptor)
|
|
411
|
+
visit(descriptor.value, depth + 1);
|
|
412
|
+
else
|
|
413
|
+
for (const closure of retainedAccessorClosures(descriptor))
|
|
414
|
+
visit(closure, depth + 1);
|
|
390
415
|
}
|
|
391
416
|
};
|
|
392
417
|
for (const value of values)
|
|
@@ -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) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { visitClassElements } from "../class-elements.js";
|
|
1
2
|
import { parseModule } from "../../parse/parser.js";
|
|
2
3
|
export const AS_NEEDLESS_TEMPLATE_MESSAGE = "Template literals with only one interpolation should use the value or String(value).";
|
|
3
4
|
export function AS_NEEDLESS_TEMPLATE(source, options = {}) {
|
|
@@ -44,6 +45,10 @@ class ASNeedlessTemplateScanner {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
visitStatement(node) {
|
|
48
|
+
if (node.type === "ClassDeclaration") {
|
|
49
|
+
visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
47
52
|
switch (node.type) {
|
|
48
53
|
case "FunctionDeclaration":
|
|
49
54
|
this.visitArrowFunction(node);
|
|
@@ -170,6 +175,10 @@ class ASNeedlessTemplateScanner {
|
|
|
170
175
|
this.visitExpression(node.argument);
|
|
171
176
|
}
|
|
172
177
|
visitExpression(node) {
|
|
178
|
+
if (node.type === "ClassExpression") {
|
|
179
|
+
visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
173
182
|
switch (node.type) {
|
|
174
183
|
case "YieldExpression":
|
|
175
184
|
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 { KNOWN_RUNTIME_GLOBALS } from "./known-globals.js";
|
|
3
4
|
export function AS_SHADOW_GLOBAL(source, options = {}) {
|
|
@@ -21,6 +22,11 @@ class ASShadowGlobalScanner {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
visitStatement(node) {
|
|
25
|
+
if (node.type === "ClassDeclaration") {
|
|
26
|
+
this.reportIfGlobalShadow(node.id);
|
|
27
|
+
visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
24
30
|
switch (node.type) {
|
|
25
31
|
case "FunctionDeclaration":
|
|
26
32
|
this.visitArrowFunctionExpression(node);
|
|
@@ -147,6 +153,12 @@ class ASShadowGlobalScanner {
|
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
visitExpression(node) {
|
|
156
|
+
if (node.type === "ClassExpression") {
|
|
157
|
+
if (node.id !== undefined)
|
|
158
|
+
this.reportIfGlobalShadow(node.id);
|
|
159
|
+
visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
150
162
|
switch (node.type) {
|
|
151
163
|
case "YieldExpression":
|
|
152
164
|
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 MESSAGE = "Unbounded loop or generator source has no static exit with break, return, or throw.";
|
|
3
4
|
export function AS_UNBOUNDED_LOOP(source, options = {}) {
|
|
@@ -20,6 +21,10 @@ class ASUnboundedLoopScanner {
|
|
|
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);
|
|
@@ -159,6 +164,10 @@ class ASUnboundedLoopScanner {
|
|
|
159
164
|
this.visitExpression(node.argument);
|
|
160
165
|
}
|
|
161
166
|
visitExpression(node) {
|
|
167
|
+
if (node.type === "ClassExpression") {
|
|
168
|
+
visitClassElements(node, expression => this.visitExpression(expression), statement => this.visitStatement(statement));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
162
171
|
switch (node.type) {
|
|
163
172
|
case "YieldExpression":
|
|
164
173
|
if (node.argument !== undefined) {
|
|
@@ -330,6 +339,8 @@ function isTrueLiteral(node) {
|
|
|
330
339
|
}
|
|
331
340
|
function bodyHasExit(node, exitingLabels, allowUnlabeledBreak) {
|
|
332
341
|
switch (node.type) {
|
|
342
|
+
case "ClassDeclaration":
|
|
343
|
+
return false;
|
|
333
344
|
case "BlockStatement":
|
|
334
345
|
return node.body.some((statement) => bodyHasExit(statement, exitingLabels, allowUnlabeledBreak));
|
|
335
346
|
case "IfStatement":
|