poe-code 4.0.57 → 4.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/cli/program.js +2 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/index.js +1755 -2241
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safejs/dist/graph-depth.js +4 -0
- package/packages/safejs/dist/interp/arguments.d.ts +10 -0
- package/packages/safejs/dist/interp/arguments.js +44 -0
- package/packages/safejs/dist/interp/async.js +3 -1
- package/packages/safejs/dist/interp/values.d.ts +1 -1
- package/packages/safejs/dist/interp/values.js +27 -2
- package/packages/safejs/dist/lint/index.js +0 -4
- package/packages/safejs/dist/lint/rules/AS-async-not-needed.d.ts +1 -1
- package/packages/safejs/dist/lint/rules/AS-async-not-needed.js +15 -3
- package/packages/safejs/dist/lint/rules/AS-await-non-promise.js +10 -0
- package/packages/safejs/dist/lint/rules/AS-destructure-null-default.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-export-import-meta.js +17 -0
- package/packages/safejs/dist/lint/rules/AS-floating-promise.js +23 -2
- package/packages/safejs/dist/lint/rules/AS-frontmatter-field-unused.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-jsdoc-type.js +10 -0
- package/packages/safejs/dist/lint/rules/AS-large-literal.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-missing-async.d.ts +1 -1
- package/packages/safejs/dist/lint/rules/AS-missing-async.js +9 -1
- package/packages/safejs/dist/lint/rules/AS-mutating-frozen.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-needless-template.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-shadow-global.js +12 -0
- package/packages/safejs/dist/lint/rules/AS-unbounded-loop.js +9 -0
- package/packages/safejs/dist/lint/rules/AS-unreachable.js +9 -1
- package/packages/safejs/dist/lint/rules/AS-unused-import.js +22 -0
- package/packages/safejs/dist/lint/rules/AS001.js +0 -6
- package/packages/safejs/dist/lint/rules/AS003.js +22 -0
- package/packages/safejs/dist/lint/rules/AS006-007.js +19 -0
- package/packages/safejs/dist/lint/rules/AS008.js +9 -0
- package/packages/safejs/dist/lint/rules/AS009.js +9 -0
- package/packages/safejs/dist/lint/rules/AS010.js +9 -0
- package/packages/safejs/dist/lint/rules/AS011.js +9 -0
- package/packages/safejs/dist/lint/rules/AS015.js +9 -0
- package/packages/safejs/dist/parse/parser.d.ts +1 -0
- package/packages/safejs/dist/parse/parser.js +4 -7
- package/packages/safejs/dist/snapshot/arguments.d.ts +17 -0
- package/packages/safejs/dist/snapshot/arguments.js +34 -0
- package/packages/safejs/dist/snapshot/dump-format.js +15 -3
- package/packages/safejs/dist/snapshot/restore.js +27 -1
- package/packages/safejs/dist/snapshot/serialize.d.ts +2 -1
- package/packages/safejs/dist/snapshot/serialize.js +20 -10
- package/packages/safejs/dist/snapshot/validation.js +50 -1
- package/packages/safejs/dist/lint/rules/AS002.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS002.js +0 -525
- package/packages/safejs/dist/lint/rules/AS012.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS012.js +0 -384
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { replaceErrorStack } from "./error/shape.js";
|
|
2
2
|
import { SandboxError } from "./interp/budget.js";
|
|
3
|
+
import { getSandboxArgumentEntries, isSandboxArguments } from "./interp/arguments.js";
|
|
3
4
|
export const MAX_DATA_DEPTH = 1_024;
|
|
4
5
|
export class SnapshotBudgetError extends Error {
|
|
5
6
|
code = "budgetExceeded";
|
|
@@ -60,6 +61,9 @@ function walkGraphDepth(root, rootPath, assertDepth) {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
function graphEntries(value) {
|
|
64
|
+
if (isSandboxArguments(value)) {
|
|
65
|
+
return getSandboxArgumentEntries(value).map(([key, entry]) => [`.${key}`, entry]);
|
|
66
|
+
}
|
|
63
67
|
if (Array.isArray(value))
|
|
64
68
|
return value.map((entry, index) => [`[${index}]`, entry]);
|
|
65
69
|
if (value instanceof Map) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SandboxObject, SandboxValue } from "./values.js";
|
|
2
|
+
declare const sandboxArgumentsBrand: unique symbol;
|
|
3
|
+
export type SandboxArguments = SandboxObject & {
|
|
4
|
+
readonly [sandboxArgumentsBrand]: true;
|
|
5
|
+
};
|
|
6
|
+
export declare function createSandboxArguments(values: readonly SandboxValue[]): SandboxArguments;
|
|
7
|
+
export declare function isSandboxArguments(value: unknown): value is SandboxArguments;
|
|
8
|
+
export declare function getSandboxArgumentEntries(value: SandboxObject): Array<[string, SandboxValue]>;
|
|
9
|
+
export declare function copySandboxArgumentProperties(source: SandboxObject, target: object, copyValue: (value: SandboxValue, key: string) => unknown): void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const sandboxArgumentsBrand = Symbol("SandboxArguments");
|
|
2
|
+
export function createSandboxArguments(values) {
|
|
3
|
+
const result = (function () {
|
|
4
|
+
return arguments;
|
|
5
|
+
})();
|
|
6
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
7
|
+
result[index] = values[index];
|
|
8
|
+
}
|
|
9
|
+
result.length = values.length;
|
|
10
|
+
Object.defineProperty(result, sandboxArgumentsBrand, { value: true });
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
export function isSandboxArguments(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && Object.hasOwn(value, sandboxArgumentsBrand);
|
|
15
|
+
}
|
|
16
|
+
export function getSandboxArgumentEntries(value) {
|
|
17
|
+
return Object.entries(Object.getOwnPropertyDescriptors(value)).flatMap(([key, descriptor]) => "value" in descriptor ? [[key, descriptor.value]] : []);
|
|
18
|
+
}
|
|
19
|
+
export function copySandboxArgumentProperties(source, target, copyValue) {
|
|
20
|
+
const names = Object.getOwnPropertyNames(source);
|
|
21
|
+
if (!names.includes("length") || names.indexOf("length") > names.indexOf("callee")) {
|
|
22
|
+
Reflect.deleteProperty(target, "length");
|
|
23
|
+
}
|
|
24
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(source))) {
|
|
25
|
+
if (!("value" in descriptor)) {
|
|
26
|
+
if (key !== "callee")
|
|
27
|
+
throw new TypeError(`Cannot copy arguments accessor '${key}'.`);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(target, key, { ...descriptor, value: copyValue(descriptor.value, key) });
|
|
31
|
+
}
|
|
32
|
+
const iterator = Object.getOwnPropertyDescriptor(source, Symbol.iterator);
|
|
33
|
+
if (iterator === undefined) {
|
|
34
|
+
Reflect.deleteProperty(target, Symbol.iterator);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (iterator.value !== Array.prototype.values) {
|
|
38
|
+
throw new TypeError("Cannot copy a replaced arguments iterator.");
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(target, Symbol.iterator, iterator);
|
|
41
|
+
}
|
|
42
|
+
if (!Object.isExtensible(source))
|
|
43
|
+
Object.preventExtensions(target);
|
|
44
|
+
}
|
|
@@ -3,7 +3,7 @@ import { getBoundOtelSpan } from "../observability/otel.js";
|
|
|
3
3
|
import { bindPattern } from "./patterns.js";
|
|
4
4
|
import { resolveSandboxValue } from "./promise.js";
|
|
5
5
|
import { hoistVarDeclarations } from "./var-hoist.js";
|
|
6
|
-
import { createSandboxClosure, createSandboxGenerator, createSandboxPromise, isSandboxPromise } from "./values.js";
|
|
6
|
+
import { createSandboxArguments, createSandboxClosure, createSandboxGenerator, createSandboxPromise, isSandboxPromise } from "./values.js";
|
|
7
7
|
export function emitResumeBreakpoint(context, breakpoint) {
|
|
8
8
|
context.onYield?.({
|
|
9
9
|
...breakpoint,
|
|
@@ -154,6 +154,8 @@ async function createClosureScope(node, args, thisValue, context, evaluateNode)
|
|
|
154
154
|
const scope = context.scope.child({}, { functionBoundary: true });
|
|
155
155
|
if (node.type !== "ArrowFunctionExpression") {
|
|
156
156
|
scope.declare("this", "const", thisValue);
|
|
157
|
+
context.budget.allocateArrayLength(args.length);
|
|
158
|
+
scope.declare("arguments", "let", createSandboxArguments(args));
|
|
157
159
|
}
|
|
158
160
|
await bindParameters(node.params, args, scope, context, evaluateNode);
|
|
159
161
|
hoistVarDeclarations(node.body, scope);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Budget } from "./budget.js";
|
|
2
2
|
import type { GeneratorChannel } from "./generator.js";
|
|
3
3
|
import { type RegexPattern } from "./regex/parse.js";
|
|
4
|
+
export { createSandboxArguments, isSandboxArguments } from "./arguments.js";
|
|
4
5
|
declare const sandboxClosureBrand: unique symbol;
|
|
5
6
|
declare const sandboxGeneratorBrand: unique symbol;
|
|
6
7
|
declare const sandboxMapBrand: unique symbol;
|
|
@@ -111,4 +112,3 @@ export declare function allocateProducedSandboxValue(value: SandboxValue, budget
|
|
|
111
112
|
export declare function measureSandboxData(values: Iterable<unknown>): number;
|
|
112
113
|
export declare function deepCopyFromSandbox(value: SandboxPromise, options?: CopyFromSandboxOptions): Promise<unknown>;
|
|
113
114
|
export declare function deepCopyFromSandbox(value: SandboxValue, options?: CopyFromSandboxOptions): unknown;
|
|
114
|
-
export {};
|
|
@@ -3,6 +3,8 @@ import { SandboxError } from "./budget.js";
|
|
|
3
3
|
import { trackSandboxPromise } from "./promise-tracker.js";
|
|
4
4
|
import { parseRegex } from "./regex/parse.js";
|
|
5
5
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
6
|
+
import { copySandboxArgumentProperties, createSandboxArguments, getSandboxArgumentEntries, isSandboxArguments } from "./arguments.js";
|
|
7
|
+
export { createSandboxArguments, isSandboxArguments } from "./arguments.js";
|
|
6
8
|
const sandboxClosureBrand = Symbol("SandboxClosure");
|
|
7
9
|
const sandboxGeneratorBrand = Symbol("SandboxGenerator");
|
|
8
10
|
const sandboxMapBrand = Symbol("SandboxMap");
|
|
@@ -203,7 +205,9 @@ export function measureSandboxData(values) {
|
|
|
203
205
|
usage += value.source.length + value.flags.length;
|
|
204
206
|
return;
|
|
205
207
|
}
|
|
206
|
-
const entries =
|
|
208
|
+
const entries = isSandboxArguments(value)
|
|
209
|
+
? getSandboxArgumentEntries(value)
|
|
210
|
+
: Object.entries(value);
|
|
207
211
|
usage += entries.length;
|
|
208
212
|
for (const [key, entry] of entries) {
|
|
209
213
|
usage += key.length;
|
|
@@ -302,6 +306,15 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
|
|
|
302
306
|
}
|
|
303
307
|
return copy;
|
|
304
308
|
}
|
|
309
|
+
if (isSandboxArguments(value)) {
|
|
310
|
+
const existing = state.seen.get(value);
|
|
311
|
+
if (existing !== undefined)
|
|
312
|
+
return existing;
|
|
313
|
+
const copy = createSandboxArguments([]);
|
|
314
|
+
state.seen.set(value, copy);
|
|
315
|
+
copySandboxArgumentProperties(value, copy, (entry, key) => copyToSandbox(entry, state, joinPath(path, key), cloneSandboxCollections, depth + 1));
|
|
316
|
+
return copy;
|
|
317
|
+
}
|
|
305
318
|
if (isPlainObject(value)) {
|
|
306
319
|
const existing = state.seen.get(value);
|
|
307
320
|
if (existing !== undefined) {
|
|
@@ -382,6 +395,15 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
|
|
|
382
395
|
}
|
|
383
396
|
return copy;
|
|
384
397
|
}
|
|
398
|
+
if (isSandboxArguments(value)) {
|
|
399
|
+
const existing = state.seen.get(value);
|
|
400
|
+
if (existing !== undefined)
|
|
401
|
+
return existing;
|
|
402
|
+
const copy = createSandboxArguments([]);
|
|
403
|
+
state.seen.set(value, copy);
|
|
404
|
+
copySandboxArgumentProperties(value, copy, (entry, key) => copyFromSandbox(entry, state, joinPath(path, key), options, depth + 1));
|
|
405
|
+
return copy;
|
|
406
|
+
}
|
|
385
407
|
if (isPlainObject(value)) {
|
|
386
408
|
const existing = state.seen.get(value);
|
|
387
409
|
if (existing !== undefined) {
|
|
@@ -457,7 +479,10 @@ function allocateSandboxValue(value, budget, seen) {
|
|
|
457
479
|
return;
|
|
458
480
|
}
|
|
459
481
|
seen.add(value);
|
|
460
|
-
|
|
482
|
+
const entries = isSandboxArguments(value)
|
|
483
|
+
? getSandboxArgumentEntries(value).map(([, entry]) => entry)
|
|
484
|
+
: Object.values(value);
|
|
485
|
+
for (const entry of entries) {
|
|
461
486
|
allocateSandboxValue(entry, budget, seen);
|
|
462
487
|
}
|
|
463
488
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AS001 } from "./rules/AS001.js";
|
|
2
|
-
import { AS002 } from "./rules/AS002.js";
|
|
3
2
|
import { AS003 } from "./rules/AS003.js";
|
|
4
3
|
import { AS004 } from "./rules/AS004.js";
|
|
5
4
|
import { AS005 } from "./rules/AS005.js";
|
|
@@ -8,7 +7,6 @@ import { AS008 } from "./rules/AS008.js";
|
|
|
8
7
|
import { AS009 } from "./rules/AS009.js";
|
|
9
8
|
import { AS010 } from "./rules/AS010.js";
|
|
10
9
|
import { AS011 } from "./rules/AS011.js";
|
|
11
|
-
import { AS012 } from "./rules/AS012.js";
|
|
12
10
|
import { AS013 } from "./rules/AS013.js";
|
|
13
11
|
import { AS015 } from "./rules/AS015.js";
|
|
14
12
|
import { AS_ASYNC_NOT_NEEDED } from "./rules/AS-async-not-needed.js";
|
|
@@ -30,7 +28,6 @@ import { AS_UNUSED_IMPORT } from "./rules/AS-unused-import.js";
|
|
|
30
28
|
import { collectComments, tokenize } from "../parse/tokenizer.js";
|
|
31
29
|
import { parseModule } from "../parse/parser.js";
|
|
32
30
|
const RULES = [
|
|
33
|
-
AS002,
|
|
34
31
|
AS003,
|
|
35
32
|
AS004,
|
|
36
33
|
AS005,
|
|
@@ -42,7 +39,6 @@ const RULES = [
|
|
|
42
39
|
AS009,
|
|
43
40
|
AS010,
|
|
44
41
|
AS011,
|
|
45
|
-
AS012,
|
|
46
42
|
AS013,
|
|
47
43
|
AS015,
|
|
48
44
|
AS_IMPORT_CYCLE,
|
|
@@ -12,7 +12,7 @@ export type Diagnostic = {
|
|
|
12
12
|
replacement: string;
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
|
-
export declare const AS_ASYNC_NOT_NEEDED_MESSAGE = "Async
|
|
15
|
+
export declare const AS_ASYNC_NOT_NEEDED_MESSAGE = "Async functions without await should remove the async keyword.";
|
|
16
16
|
export declare function AS_ASYNC_NOT_NEEDED(source: string, options?: {
|
|
17
17
|
filename?: string;
|
|
18
18
|
}): Diagnostic[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseModule } from "../../parse/parser.js";
|
|
2
|
-
export const AS_ASYNC_NOT_NEEDED_MESSAGE = "Async
|
|
2
|
+
export const AS_ASYNC_NOT_NEEDED_MESSAGE = "Async functions without await should remove the async keyword.";
|
|
3
3
|
export function AS_ASYNC_NOT_NEEDED(source, options = {}) {
|
|
4
4
|
return new ASAsyncNotNeededScanner(source, options.filename ?? "<input>").scan();
|
|
5
5
|
}
|
|
@@ -33,6 +33,9 @@ class ASAsyncNotNeededScanner {
|
|
|
33
33
|
}
|
|
34
34
|
visitStatement(node) {
|
|
35
35
|
switch (node.type) {
|
|
36
|
+
case "FunctionDeclaration":
|
|
37
|
+
this.visitFunctionExpression(node);
|
|
38
|
+
return;
|
|
36
39
|
case "BlockStatement":
|
|
37
40
|
this.visitBlockStatement(node);
|
|
38
41
|
return;
|
|
@@ -73,6 +76,10 @@ class ASAsyncNotNeededScanner {
|
|
|
73
76
|
this.visitArrowFunction(node.declaration, true);
|
|
74
77
|
return;
|
|
75
78
|
}
|
|
79
|
+
if (node.declaration.type === "FunctionExpression") {
|
|
80
|
+
this.visitFunctionExpression(node.declaration, true);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
76
83
|
this.visitExpression(node.declaration);
|
|
77
84
|
return;
|
|
78
85
|
case "ImportDeclaration":
|
|
@@ -160,6 +167,11 @@ class ASAsyncNotNeededScanner {
|
|
|
160
167
|
}
|
|
161
168
|
visitExpression(node) {
|
|
162
169
|
switch (node.type) {
|
|
170
|
+
case "YieldExpression":
|
|
171
|
+
if (node.argument !== undefined) {
|
|
172
|
+
this.visitExpression(node.argument);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
163
175
|
case "ArrowFunctionExpression":
|
|
164
176
|
this.visitArrowFunction(node, false);
|
|
165
177
|
return;
|
|
@@ -224,8 +236,8 @@ class ASAsyncNotNeededScanner {
|
|
|
224
236
|
}
|
|
225
237
|
this.visitExpression(node.body);
|
|
226
238
|
}
|
|
227
|
-
visitFunctionExpression(node) {
|
|
228
|
-
if (node.async && !bodyContainsAwait(node.body)) {
|
|
239
|
+
visitFunctionExpression(node, isDefaultExport = false) {
|
|
240
|
+
if (node.async && !isDefaultExport && !bodyContainsAwait(node.body)) {
|
|
229
241
|
this.report(createAsyncKeywordSpan(node.span));
|
|
230
242
|
}
|
|
231
243
|
for (const param of node.params) {
|
|
@@ -19,6 +19,9 @@ class ASAwaitNonPromiseScanner {
|
|
|
19
19
|
}
|
|
20
20
|
visitStatement(node) {
|
|
21
21
|
switch (node.type) {
|
|
22
|
+
case "FunctionDeclaration":
|
|
23
|
+
this.visitArrowFunction(node);
|
|
24
|
+
return;
|
|
22
25
|
case "BlockStatement":
|
|
23
26
|
this.visitBlockStatement(node);
|
|
24
27
|
return;
|
|
@@ -135,6 +138,12 @@ class ASAwaitNonPromiseScanner {
|
|
|
135
138
|
}
|
|
136
139
|
visitExpression(node) {
|
|
137
140
|
switch (node.type) {
|
|
141
|
+
case "YieldExpression":
|
|
142
|
+
if (node.argument !== undefined) {
|
|
143
|
+
this.visitExpression(node.argument);
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
case "FunctionExpression":
|
|
138
147
|
case "ArrowFunctionExpression":
|
|
139
148
|
this.visitArrowFunction(node);
|
|
140
149
|
return;
|
|
@@ -274,6 +283,7 @@ class ASAwaitNonPromiseScanner {
|
|
|
274
283
|
}
|
|
275
284
|
function isKnownNonPromiseExpression(node) {
|
|
276
285
|
switch (node.type) {
|
|
286
|
+
case "FunctionExpression":
|
|
277
287
|
case "ArrowFunctionExpression":
|
|
278
288
|
case "ArrayExpression":
|
|
279
289
|
case "BinaryExpression":
|
|
@@ -21,6 +21,9 @@ class ASDestructureNullDefaultScanner {
|
|
|
21
21
|
}
|
|
22
22
|
visitStatement(node) {
|
|
23
23
|
switch (node.type) {
|
|
24
|
+
case "FunctionDeclaration":
|
|
25
|
+
this.visitArrowFunction(node);
|
|
26
|
+
return;
|
|
24
27
|
case "BlockStatement":
|
|
25
28
|
this.visitBlockStatement(node);
|
|
26
29
|
return;
|
|
@@ -145,6 +148,12 @@ class ASDestructureNullDefaultScanner {
|
|
|
145
148
|
}
|
|
146
149
|
visitExpression(node) {
|
|
147
150
|
switch (node.type) {
|
|
151
|
+
case "YieldExpression":
|
|
152
|
+
if (node.argument !== undefined) {
|
|
153
|
+
this.visitExpression(node.argument);
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
case "FunctionExpression":
|
|
148
157
|
case "ArrowFunctionExpression":
|
|
149
158
|
this.visitArrowFunction(node);
|
|
150
159
|
return;
|
|
@@ -36,6 +36,12 @@ class Scanner {
|
|
|
36
36
|
}
|
|
37
37
|
visitStatement(node) {
|
|
38
38
|
switch (node.type) {
|
|
39
|
+
case "FunctionDeclaration":
|
|
40
|
+
for (const param of node.params) {
|
|
41
|
+
this.visitAssignmentTarget(param);
|
|
42
|
+
}
|
|
43
|
+
this.visitStatement(node.body);
|
|
44
|
+
return;
|
|
39
45
|
case "ExportNamedDeclaration":
|
|
40
46
|
this.visitExportNamedDeclaration(node.declaration);
|
|
41
47
|
return;
|
|
@@ -171,7 +177,15 @@ class Scanner {
|
|
|
171
177
|
}
|
|
172
178
|
visitExpression(node) {
|
|
173
179
|
switch (node.type) {
|
|
180
|
+
case "YieldExpression":
|
|
181
|
+
if (node.argument !== undefined) {
|
|
182
|
+
this.visitExpression(node.argument);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
174
185
|
case "ArrowFunctionExpression":
|
|
186
|
+
for (const param of node.params) {
|
|
187
|
+
this.visitAssignmentTarget(param);
|
|
188
|
+
}
|
|
175
189
|
if (node.body.type === "BlockStatement") {
|
|
176
190
|
this.visitStatement(node.body);
|
|
177
191
|
}
|
|
@@ -180,6 +194,9 @@ class Scanner {
|
|
|
180
194
|
}
|
|
181
195
|
return;
|
|
182
196
|
case "FunctionExpression":
|
|
197
|
+
for (const param of node.params) {
|
|
198
|
+
this.visitAssignmentTarget(param);
|
|
199
|
+
}
|
|
183
200
|
this.visitStatement(node.body);
|
|
184
201
|
return;
|
|
185
202
|
case "AwaitExpression":
|
|
@@ -29,6 +29,9 @@ class ASFloatingPromiseScanner {
|
|
|
29
29
|
}
|
|
30
30
|
visitStatement(node) {
|
|
31
31
|
switch (node.type) {
|
|
32
|
+
case "FunctionDeclaration":
|
|
33
|
+
this.visitArrowFunction(node);
|
|
34
|
+
return;
|
|
32
35
|
case "BlockStatement":
|
|
33
36
|
this.visitBlockStatement(node);
|
|
34
37
|
return;
|
|
@@ -161,6 +164,12 @@ class ASFloatingPromiseScanner {
|
|
|
161
164
|
}
|
|
162
165
|
visitExpression(node) {
|
|
163
166
|
switch (node.type) {
|
|
167
|
+
case "YieldExpression":
|
|
168
|
+
if (node.argument !== undefined) {
|
|
169
|
+
this.visitExpression(node.argument);
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
case "FunctionExpression":
|
|
164
173
|
case "ArrowFunctionExpression":
|
|
165
174
|
this.visitArrowFunction(node);
|
|
166
175
|
return;
|
|
@@ -369,6 +378,7 @@ class ASFloatingPromiseScanner {
|
|
|
369
378
|
this.reportUnhandledLikelyPromiseStatementExpression(node.alternate);
|
|
370
379
|
return;
|
|
371
380
|
case "CallExpression":
|
|
381
|
+
case "FunctionExpression":
|
|
372
382
|
case "ArrowFunctionExpression":
|
|
373
383
|
case "AwaitExpression":
|
|
374
384
|
case "ArrayExpression":
|
|
@@ -481,6 +491,11 @@ class ASFloatingPromiseScanner {
|
|
|
481
491
|
}
|
|
482
492
|
collectBlockBindings(statements) {
|
|
483
493
|
return statements.flatMap((statement) => {
|
|
494
|
+
if (statement.type === "FunctionDeclaration") {
|
|
495
|
+
return [
|
|
496
|
+
{ async: statement.async && !statement.generator, kind: "local", name: statement.id.name }
|
|
497
|
+
];
|
|
498
|
+
}
|
|
484
499
|
if (statement.type === "VariableDeclaration") {
|
|
485
500
|
return this.collectDeclarationBindings(statement);
|
|
486
501
|
}
|
|
@@ -492,7 +507,9 @@ class ASFloatingPromiseScanner {
|
|
|
492
507
|
}
|
|
493
508
|
collectDeclarationBindings(node) {
|
|
494
509
|
return node.declarations.flatMap((declarator) => this.collectDeclaratorBindings(declarator).map((name) => ({
|
|
495
|
-
async: declarator.init?.type === "ArrowFunctionExpression"
|
|
510
|
+
async: (declarator.init?.type === "ArrowFunctionExpression" ||
|
|
511
|
+
(declarator.init?.type === "FunctionExpression" && !declarator.init.generator)) &&
|
|
512
|
+
declarator.init.async,
|
|
496
513
|
kind: "local",
|
|
497
514
|
name
|
|
498
515
|
})));
|
|
@@ -501,11 +518,15 @@ class ASFloatingPromiseScanner {
|
|
|
501
518
|
return this.collectPatternBindingNames(node.id);
|
|
502
519
|
}
|
|
503
520
|
collectArrowFunctionBindings(node) {
|
|
504
|
-
|
|
521
|
+
const bindings = node.params.flatMap((param) => this.collectParameterBindingNames(param).map((name) => ({
|
|
505
522
|
async: false,
|
|
506
523
|
kind: "local",
|
|
507
524
|
name
|
|
508
525
|
})));
|
|
526
|
+
if (node.type === "FunctionExpression" && node.id !== undefined) {
|
|
527
|
+
bindings.unshift({ async: node.async && !node.generator, kind: "local", name: node.id.name });
|
|
528
|
+
}
|
|
529
|
+
return bindings;
|
|
509
530
|
}
|
|
510
531
|
collectPatternBindings(node) {
|
|
511
532
|
return this.collectPatternBindingNames(node).map((name) => ({
|
|
@@ -35,6 +35,9 @@ class ASFrontmatterFieldUnusedScanner {
|
|
|
35
35
|
}
|
|
36
36
|
visitStatement(node) {
|
|
37
37
|
switch (node.type) {
|
|
38
|
+
case "FunctionDeclaration":
|
|
39
|
+
this.visitArrowFunction(node);
|
|
40
|
+
return;
|
|
38
41
|
case "BlockStatement":
|
|
39
42
|
this.visitBlockStatement(node);
|
|
40
43
|
return;
|
|
@@ -160,6 +163,12 @@ class ASFrontmatterFieldUnusedScanner {
|
|
|
160
163
|
}
|
|
161
164
|
visitExpression(node) {
|
|
162
165
|
switch (node.type) {
|
|
166
|
+
case "YieldExpression":
|
|
167
|
+
if (node.argument !== undefined) {
|
|
168
|
+
this.visitExpression(node.argument);
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
case "FunctionExpression":
|
|
163
172
|
case "ArrowFunctionExpression":
|
|
164
173
|
this.visitArrowFunction(node);
|
|
165
174
|
return;
|
|
@@ -28,6 +28,9 @@ class ASJsdocTypeScanner {
|
|
|
28
28
|
}
|
|
29
29
|
visitStatement(node) {
|
|
30
30
|
switch (node.type) {
|
|
31
|
+
case "FunctionDeclaration":
|
|
32
|
+
this.visitArrowFunction(node);
|
|
33
|
+
return;
|
|
31
34
|
case "BlockStatement":
|
|
32
35
|
this.visitBlockStatement(node);
|
|
33
36
|
return;
|
|
@@ -164,6 +167,12 @@ class ASJsdocTypeScanner {
|
|
|
164
167
|
}
|
|
165
168
|
visitExpression(node) {
|
|
166
169
|
switch (node.type) {
|
|
170
|
+
case "YieldExpression":
|
|
171
|
+
if (node.argument !== undefined) {
|
|
172
|
+
this.visitExpression(node.argument);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
case "FunctionExpression":
|
|
167
176
|
case "ArrowFunctionExpression":
|
|
168
177
|
this.visitArrowFunction(node);
|
|
169
178
|
return;
|
|
@@ -632,6 +641,7 @@ function inferExpressionKind(expression) {
|
|
|
632
641
|
return "boolean";
|
|
633
642
|
}
|
|
634
643
|
return undefined;
|
|
644
|
+
case "FunctionExpression":
|
|
635
645
|
case "ArrowFunctionExpression":
|
|
636
646
|
case "AssignmentExpression":
|
|
637
647
|
case "AwaitExpression":
|
|
@@ -22,6 +22,9 @@ class ASLargeLiteralScanner {
|
|
|
22
22
|
}
|
|
23
23
|
visitStatement(node) {
|
|
24
24
|
switch (node.type) {
|
|
25
|
+
case "FunctionDeclaration":
|
|
26
|
+
this.visitArrowFunction(node);
|
|
27
|
+
return;
|
|
25
28
|
case "BlockStatement":
|
|
26
29
|
this.visitBlockStatement(node);
|
|
27
30
|
return;
|
|
@@ -142,6 +145,12 @@ class ASLargeLiteralScanner {
|
|
|
142
145
|
}
|
|
143
146
|
visitExpression(node) {
|
|
144
147
|
switch (node.type) {
|
|
148
|
+
case "YieldExpression":
|
|
149
|
+
if (node.argument !== undefined) {
|
|
150
|
+
this.visitExpression(node.argument);
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
case "FunctionExpression":
|
|
145
154
|
case "ArrowFunctionExpression":
|
|
146
155
|
this.visitArrowFunction(node);
|
|
147
156
|
return;
|
|
@@ -12,7 +12,7 @@ export type Diagnostic = {
|
|
|
12
12
|
replacement: string;
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
|
-
export declare const AS_MISSING_ASYNC_MESSAGE = "
|
|
15
|
+
export declare const AS_MISSING_ASYNC_MESSAGE = "Functions that contain await must be marked async.";
|
|
16
16
|
export declare function AS_MISSING_ASYNC(source: string, options?: {
|
|
17
17
|
filename?: string;
|
|
18
18
|
}): Diagnostic[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseModule } from "../../parse/parser.js";
|
|
2
|
-
export const AS_MISSING_ASYNC_MESSAGE = "
|
|
2
|
+
export const AS_MISSING_ASYNC_MESSAGE = "Functions that contain await must be marked async.";
|
|
3
3
|
export function AS_MISSING_ASYNC(source, options = {}) {
|
|
4
4
|
return new ASMissingAsyncScanner(options.filename ?? "<input>").scan(source);
|
|
5
5
|
}
|
|
@@ -28,6 +28,9 @@ class ASMissingAsyncScanner {
|
|
|
28
28
|
}
|
|
29
29
|
visitStatement(node) {
|
|
30
30
|
switch (node.type) {
|
|
31
|
+
case "FunctionDeclaration":
|
|
32
|
+
this.visitFunctionExpression(node);
|
|
33
|
+
return;
|
|
31
34
|
case "BlockStatement":
|
|
32
35
|
this.visitBlockStatement(node);
|
|
33
36
|
return;
|
|
@@ -148,6 +151,11 @@ class ASMissingAsyncScanner {
|
|
|
148
151
|
}
|
|
149
152
|
visitExpression(node) {
|
|
150
153
|
switch (node.type) {
|
|
154
|
+
case "YieldExpression":
|
|
155
|
+
if (node.argument !== undefined) {
|
|
156
|
+
this.visitExpression(node.argument);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
151
159
|
case "ArrowFunctionExpression":
|
|
152
160
|
this.visitArrowFunction(node);
|
|
153
161
|
return;
|
|
@@ -33,6 +33,9 @@ class ASMutatingFrozenScanner {
|
|
|
33
33
|
}
|
|
34
34
|
visitStatement(node) {
|
|
35
35
|
switch (node.type) {
|
|
36
|
+
case "FunctionDeclaration":
|
|
37
|
+
this.visitArrowFunction(node);
|
|
38
|
+
return;
|
|
36
39
|
case "BlockStatement":
|
|
37
40
|
this.visitBlockStatement(node);
|
|
38
41
|
return;
|
|
@@ -170,6 +173,12 @@ class ASMutatingFrozenScanner {
|
|
|
170
173
|
}
|
|
171
174
|
visitExpression(node) {
|
|
172
175
|
switch (node.type) {
|
|
176
|
+
case "YieldExpression":
|
|
177
|
+
if (node.argument !== undefined) {
|
|
178
|
+
this.visitExpression(node.argument);
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
case "FunctionExpression":
|
|
173
182
|
case "ArrowFunctionExpression":
|
|
174
183
|
this.visitArrowFunction(node);
|
|
175
184
|
return;
|
|
@@ -45,6 +45,9 @@ class ASNeedlessTemplateScanner {
|
|
|
45
45
|
}
|
|
46
46
|
visitStatement(node) {
|
|
47
47
|
switch (node.type) {
|
|
48
|
+
case "FunctionDeclaration":
|
|
49
|
+
this.visitArrowFunction(node);
|
|
50
|
+
return;
|
|
48
51
|
case "BlockStatement":
|
|
49
52
|
this.visitBlockStatement(node);
|
|
50
53
|
return;
|
|
@@ -168,6 +171,12 @@ class ASNeedlessTemplateScanner {
|
|
|
168
171
|
}
|
|
169
172
|
visitExpression(node) {
|
|
170
173
|
switch (node.type) {
|
|
174
|
+
case "YieldExpression":
|
|
175
|
+
if (node.argument !== undefined) {
|
|
176
|
+
this.visitExpression(node.argument);
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
case "FunctionExpression":
|
|
171
180
|
case "ArrowFunctionExpression":
|
|
172
181
|
this.visitArrowFunction(node);
|
|
173
182
|
return;
|
|
@@ -22,6 +22,9 @@ class ASShadowGlobalScanner {
|
|
|
22
22
|
}
|
|
23
23
|
visitStatement(node) {
|
|
24
24
|
switch (node.type) {
|
|
25
|
+
case "FunctionDeclaration":
|
|
26
|
+
this.visitArrowFunctionExpression(node);
|
|
27
|
+
return;
|
|
25
28
|
case "BlockStatement":
|
|
26
29
|
this.visitBlockStatement(node);
|
|
27
30
|
return;
|
|
@@ -145,6 +148,12 @@ class ASShadowGlobalScanner {
|
|
|
145
148
|
}
|
|
146
149
|
visitExpression(node) {
|
|
147
150
|
switch (node.type) {
|
|
151
|
+
case "YieldExpression":
|
|
152
|
+
if (node.argument !== undefined) {
|
|
153
|
+
this.visitExpression(node.argument);
|
|
154
|
+
}
|
|
155
|
+
return;
|
|
156
|
+
case "FunctionExpression":
|
|
148
157
|
case "ArrowFunctionExpression":
|
|
149
158
|
this.visitArrowFunctionExpression(node);
|
|
150
159
|
return;
|
|
@@ -196,6 +205,9 @@ class ASShadowGlobalScanner {
|
|
|
196
205
|
}
|
|
197
206
|
}
|
|
198
207
|
visitArrowFunctionExpression(node) {
|
|
208
|
+
if (node.type !== "ArrowFunctionExpression" && node.id !== undefined) {
|
|
209
|
+
this.reportIfGlobalShadow(node.id);
|
|
210
|
+
}
|
|
199
211
|
for (const parameter of node.params) {
|
|
200
212
|
this.visitBindingElement(parameter);
|
|
201
213
|
}
|
|
@@ -21,6 +21,9 @@ class ASUnboundedLoopScanner {
|
|
|
21
21
|
}
|
|
22
22
|
visitStatement(node) {
|
|
23
23
|
switch (node.type) {
|
|
24
|
+
case "FunctionDeclaration":
|
|
25
|
+
this.visitArrowFunction(node);
|
|
26
|
+
return;
|
|
24
27
|
case "BlockStatement":
|
|
25
28
|
this.visitBlockStatement(node);
|
|
26
29
|
return;
|
|
@@ -157,6 +160,12 @@ class ASUnboundedLoopScanner {
|
|
|
157
160
|
}
|
|
158
161
|
visitExpression(node) {
|
|
159
162
|
switch (node.type) {
|
|
163
|
+
case "YieldExpression":
|
|
164
|
+
if (node.argument !== undefined) {
|
|
165
|
+
this.visitExpression(node.argument);
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
case "FunctionExpression":
|
|
160
169
|
case "ArrowFunctionExpression":
|
|
161
170
|
this.visitArrowFunction(node);
|
|
162
171
|
return;
|