poe-code 6.0.0 → 7.0.0
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 +307 -937
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safejs/dist/interp/async.d.ts +2 -1
- package/packages/safejs/dist/interp/async.js +25 -24
- package/packages/safejs/dist/interp/interpreter.js +7 -5
- package/packages/safejs/dist/interp/patterns.d.ts +1 -0
- package/packages/safejs/dist/interp/patterns.js +1 -1
- package/packages/safejs/dist/interp/var-hoist.js +5 -135
- package/packages/safejs/dist/lint/index.js +0 -4
- package/packages/safejs/dist/lint/rules/AS001.js +4 -4
- package/packages/safejs/dist/lint/rules/AS003.js +47 -7
- package/packages/safejs/dist/lint/rules/AS006-007.js +48 -7
- package/packages/safejs/dist/parse/bindings.d.ts +6 -0
- package/packages/safejs/dist/parse/bindings.js +90 -0
- package/packages/safejs/dist/parse/parser.js +70 -37
- package/packages/safejs/dist/snapshot/dump-format.d.ts +1 -1
- package/packages/safejs/dist/snapshot/dump-format.js +1 -1
- package/packages/safejs/dist/lint/rules/AS-await-non-promise.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS-await-non-promise.js +0 -301
- package/packages/safejs/dist/lint/rules/AS008.d.ts +0 -13
- package/packages/safejs/dist/lint/rules/AS008.js +0 -386
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export function* boundIdentifiers(pattern) {
|
|
2
|
+
switch (pattern.type) {
|
|
3
|
+
case "Identifier":
|
|
4
|
+
yield pattern;
|
|
5
|
+
return;
|
|
6
|
+
case "AssignmentPattern":
|
|
7
|
+
yield* boundIdentifiers(pattern.left);
|
|
8
|
+
return;
|
|
9
|
+
case "RestElement":
|
|
10
|
+
yield* boundIdentifiers(pattern.argument);
|
|
11
|
+
return;
|
|
12
|
+
case "ArrayPattern":
|
|
13
|
+
for (const element of pattern.elements) {
|
|
14
|
+
if (element !== null)
|
|
15
|
+
yield* boundIdentifiers(element);
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
case "ObjectPattern":
|
|
19
|
+
for (const property of pattern.properties) {
|
|
20
|
+
yield* boundIdentifiers(property.type === "RestElement" ? property : property.value);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
case "MemberExpression":
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function containsParameterExpression(pattern) {
|
|
28
|
+
switch (pattern.type) {
|
|
29
|
+
case "AssignmentPattern":
|
|
30
|
+
case "MemberExpression":
|
|
31
|
+
return true;
|
|
32
|
+
case "RestElement":
|
|
33
|
+
return containsParameterExpression(pattern.argument);
|
|
34
|
+
case "ArrayPattern":
|
|
35
|
+
return pattern.elements.some((element) => element !== null && containsParameterExpression(element));
|
|
36
|
+
case "ObjectPattern":
|
|
37
|
+
return pattern.properties.some((property) => property.type === "RestElement"
|
|
38
|
+
? containsParameterExpression(property.argument)
|
|
39
|
+
: property.computed || containsParameterExpression(property.value));
|
|
40
|
+
case "Identifier":
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function* hoistedVarDeclarations(nodes) {
|
|
45
|
+
for (const node of nodes) {
|
|
46
|
+
switch (node.type) {
|
|
47
|
+
case "VariableDeclaration":
|
|
48
|
+
if (node.kind === "var")
|
|
49
|
+
yield node;
|
|
50
|
+
break;
|
|
51
|
+
case "BlockStatement":
|
|
52
|
+
yield* hoistedVarDeclarations(node.body);
|
|
53
|
+
break;
|
|
54
|
+
case "IfStatement":
|
|
55
|
+
yield* hoistedVarDeclarations([node.consequent]);
|
|
56
|
+
if (node.alternate !== undefined)
|
|
57
|
+
yield* hoistedVarDeclarations([node.alternate]);
|
|
58
|
+
break;
|
|
59
|
+
case "ForStatement":
|
|
60
|
+
if (node.init?.type === "VariableDeclaration")
|
|
61
|
+
yield* hoistedVarDeclarations([node.init]);
|
|
62
|
+
yield* hoistedVarDeclarations([node.body]);
|
|
63
|
+
break;
|
|
64
|
+
case "ForInStatement":
|
|
65
|
+
case "ForOfStatement":
|
|
66
|
+
if (node.left.type === "VariableDeclaration")
|
|
67
|
+
yield* hoistedVarDeclarations([node.left]);
|
|
68
|
+
yield* hoistedVarDeclarations([node.body]);
|
|
69
|
+
break;
|
|
70
|
+
case "WhileStatement":
|
|
71
|
+
case "DoWhileStatement":
|
|
72
|
+
yield* hoistedVarDeclarations([node.body]);
|
|
73
|
+
break;
|
|
74
|
+
case "TryStatement":
|
|
75
|
+
yield* hoistedVarDeclarations([node.block]);
|
|
76
|
+
if (node.handler !== undefined)
|
|
77
|
+
yield* hoistedVarDeclarations([node.handler.body]);
|
|
78
|
+
if (node.finalizer !== undefined)
|
|
79
|
+
yield* hoistedVarDeclarations([node.finalizer]);
|
|
80
|
+
break;
|
|
81
|
+
case "SwitchStatement":
|
|
82
|
+
for (const switchCase of node.cases)
|
|
83
|
+
yield* hoistedVarDeclarations(switchCase.consequent);
|
|
84
|
+
break;
|
|
85
|
+
case "ExportNamedDeclaration":
|
|
86
|
+
yield* hoistedVarDeclarations([node.declaration]);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { boundIdentifiers } from "./bindings.js";
|
|
1
2
|
import { tokenize } from "./tokenizer.js";
|
|
2
3
|
import { assignIds } from "./assign-ids.js";
|
|
3
4
|
import { formatParseError } from "./format-error.js";
|
|
@@ -104,8 +105,11 @@ class Parser {
|
|
|
104
105
|
loopDepth = 0;
|
|
105
106
|
generatorBody = false;
|
|
106
107
|
scopes = [new Map()];
|
|
108
|
+
functionScopes = new WeakSet();
|
|
109
|
+
varNames = new WeakMap();
|
|
107
110
|
constructor(tokens) {
|
|
108
111
|
this.tokens = tokens;
|
|
112
|
+
this.functionScopes.add(this.scopes[0]);
|
|
109
113
|
}
|
|
110
114
|
parseTopLevel() {
|
|
111
115
|
if (this.isExportToken(this.currentToken())) {
|
|
@@ -244,8 +248,14 @@ class Parser {
|
|
|
244
248
|
return undefined;
|
|
245
249
|
}
|
|
246
250
|
finishArrowFunctionExpression(start, isAsync, params) {
|
|
251
|
+
this.withScope(() => {
|
|
252
|
+
for (const param of params) {
|
|
253
|
+
for (const identifier of boundIdentifiers(param))
|
|
254
|
+
this.declareBinding(identifier);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
247
257
|
this.expectPunctuator("=>");
|
|
248
|
-
const body = this.parseArrowFunctionBody();
|
|
258
|
+
const body = this.parseArrowFunctionBody(params);
|
|
249
259
|
return {
|
|
250
260
|
type: "ArrowFunctionExpression",
|
|
251
261
|
async: isAsync,
|
|
@@ -284,15 +294,27 @@ class Parser {
|
|
|
284
294
|
this.conditionalExpressionDepth -= 1;
|
|
285
295
|
}
|
|
286
296
|
}
|
|
287
|
-
parseArrowFunctionBody() {
|
|
297
|
+
parseArrowFunctionBody(params) {
|
|
288
298
|
if (this.currentToken().type === "punctuator" && this.currentToken().value === "{") {
|
|
289
|
-
return this.withFunctionContext(false, () => this.parseBlockStatement());
|
|
299
|
+
return this.withFunctionContext(false, () => this.parseBlockStatement(params));
|
|
290
300
|
}
|
|
291
301
|
return this.withFunctionContext(false, () => this.parseExpression().node);
|
|
292
302
|
}
|
|
293
|
-
parseBlockStatement() {
|
|
303
|
+
parseBlockStatement(params, catchParam) {
|
|
294
304
|
const start = this.expectPunctuator("{");
|
|
295
|
-
return this.withScope(() =>
|
|
305
|
+
return this.withScope(() => {
|
|
306
|
+
for (const param of params ?? []) {
|
|
307
|
+
for (const identifier of boundIdentifiers(param)) {
|
|
308
|
+
this.declareBinding(identifier, "parameter");
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (catchParam !== undefined) {
|
|
312
|
+
for (const identifier of boundIdentifiers(catchParam)) {
|
|
313
|
+
this.declareBinding(identifier, catchParam.type === "Identifier" ? "catch" : "lexical");
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return this.parseBlockStatementBody(start);
|
|
317
|
+
}, params !== undefined);
|
|
296
318
|
}
|
|
297
319
|
parseBlockStatementBody(start) {
|
|
298
320
|
const body = [];
|
|
@@ -819,7 +841,7 @@ class Parser {
|
|
|
819
841
|
param = this.parseBindingTarget();
|
|
820
842
|
this.expectPunctuator(")");
|
|
821
843
|
}
|
|
822
|
-
const body = this.parseBlockStatement();
|
|
844
|
+
const body = this.parseBlockStatement(undefined, param);
|
|
823
845
|
return {
|
|
824
846
|
type: "CatchClause",
|
|
825
847
|
param,
|
|
@@ -840,6 +862,11 @@ class Parser {
|
|
|
840
862
|
if (kindToken.value !== "var") {
|
|
841
863
|
this.declarePatternBindings(declarator.id);
|
|
842
864
|
}
|
|
865
|
+
else {
|
|
866
|
+
for (const identifier of boundIdentifiers(declarator.id)) {
|
|
867
|
+
this.declareVarBinding(identifier);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
843
870
|
declarations.push(declarator);
|
|
844
871
|
const comma = this.consumePunctuator(",");
|
|
845
872
|
if (comma === undefined) {
|
|
@@ -861,18 +888,18 @@ class Parser {
|
|
|
861
888
|
throw new Error(`async function* is not supported at line ${asyncToken.start.line}, column ${asyncToken.start.column}.`);
|
|
862
889
|
}
|
|
863
890
|
const id = this.parseBindingIdentifier();
|
|
864
|
-
this.declareBinding(id);
|
|
891
|
+
this.declareBinding(id, "function");
|
|
865
892
|
const params = this.withScope(() => {
|
|
866
893
|
const parsedParams = this.parseArrowParameters();
|
|
867
894
|
for (const param of parsedParams) {
|
|
868
|
-
for (const identifier of
|
|
895
|
+
for (const identifier of boundIdentifiers(param)) {
|
|
869
896
|
this.declareBinding(identifier);
|
|
870
897
|
}
|
|
871
898
|
}
|
|
872
899
|
return parsedParams;
|
|
873
900
|
});
|
|
874
901
|
const generator = generatorToken !== undefined;
|
|
875
|
-
const body = this.withFunctionContext(generator, () => this.parseBlockStatement());
|
|
902
|
+
const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
|
|
876
903
|
return {
|
|
877
904
|
type: "FunctionDeclaration",
|
|
878
905
|
async: asyncToken !== undefined,
|
|
@@ -1809,14 +1836,14 @@ class Parser {
|
|
|
1809
1836
|
const params = this.withScope(() => {
|
|
1810
1837
|
const parsedParams = this.parseArrowParameters();
|
|
1811
1838
|
for (const param of parsedParams) {
|
|
1812
|
-
for (const identifier of
|
|
1839
|
+
for (const identifier of boundIdentifiers(param)) {
|
|
1813
1840
|
this.declareBinding(identifier);
|
|
1814
1841
|
}
|
|
1815
1842
|
}
|
|
1816
1843
|
return parsedParams;
|
|
1817
1844
|
});
|
|
1818
1845
|
const generator = generatorToken !== undefined;
|
|
1819
|
-
const body = this.withFunctionContext(generator, () => this.parseBlockStatement());
|
|
1846
|
+
const body = this.withFunctionContext(generator, () => this.parseBlockStatement(params));
|
|
1820
1847
|
return {
|
|
1821
1848
|
type: "FunctionExpression",
|
|
1822
1849
|
async: asyncToken !== undefined,
|
|
@@ -2071,13 +2098,13 @@ class Parser {
|
|
|
2071
2098
|
const params = this.withScope(() => {
|
|
2072
2099
|
const parsedParams = this.parseArrowParameters();
|
|
2073
2100
|
for (const param of parsedParams) {
|
|
2074
|
-
for (const identifier of
|
|
2101
|
+
for (const identifier of boundIdentifiers(param)) {
|
|
2075
2102
|
this.declareBinding(identifier);
|
|
2076
2103
|
}
|
|
2077
2104
|
}
|
|
2078
2105
|
return parsedParams;
|
|
2079
2106
|
});
|
|
2080
|
-
const body = this.withFunctionContext(false, () => this.parseBlockStatement());
|
|
2107
|
+
const body = this.withFunctionContext(false, () => this.parseBlockStatement(params));
|
|
2081
2108
|
return {
|
|
2082
2109
|
type: "FunctionExpression",
|
|
2083
2110
|
async: asyncToken !== undefined,
|
|
@@ -2524,8 +2551,11 @@ class Parser {
|
|
|
2524
2551
|
this.breakableDepth -= 1;
|
|
2525
2552
|
}
|
|
2526
2553
|
}
|
|
2527
|
-
withScope(callback) {
|
|
2528
|
-
|
|
2554
|
+
withScope(callback, functionBody = false) {
|
|
2555
|
+
const scope = new Map();
|
|
2556
|
+
if (functionBody)
|
|
2557
|
+
this.functionScopes.add(scope);
|
|
2558
|
+
this.scopes.push(scope);
|
|
2529
2559
|
try {
|
|
2530
2560
|
return callback();
|
|
2531
2561
|
}
|
|
@@ -2534,19 +2564,40 @@ class Parser {
|
|
|
2534
2564
|
}
|
|
2535
2565
|
}
|
|
2536
2566
|
declarePatternBindings(pattern) {
|
|
2537
|
-
for (const identifier of
|
|
2567
|
+
for (const identifier of boundIdentifiers(pattern)) {
|
|
2538
2568
|
this.declareBinding(identifier);
|
|
2539
2569
|
}
|
|
2540
2570
|
}
|
|
2541
|
-
declareBinding(identifier) {
|
|
2571
|
+
declareBinding(identifier, kind = "lexical") {
|
|
2542
2572
|
const scope = this.scopes[this.scopes.length - 1];
|
|
2543
2573
|
if (scope === undefined) {
|
|
2544
2574
|
return;
|
|
2545
2575
|
}
|
|
2546
|
-
|
|
2576
|
+
const existing = scope.get(identifier.name);
|
|
2577
|
+
const variableFunction = kind === "function" && this.functionScopes.has(scope);
|
|
2578
|
+
if ((existing !== undefined &&
|
|
2579
|
+
!(variableFunction && (existing === "function" || existing === "parameter"))) ||
|
|
2580
|
+
(!variableFunction && this.varNames.get(scope)?.has(identifier.name))) {
|
|
2547
2581
|
throw new Error(`Cannot redeclare binding '${identifier.name}' at line ${identifier.span.start.line}, column ${identifier.span.start.column}.`);
|
|
2548
2582
|
}
|
|
2549
|
-
scope.set(identifier.name,
|
|
2583
|
+
scope.set(identifier.name, kind);
|
|
2584
|
+
}
|
|
2585
|
+
declareVarBinding(identifier) {
|
|
2586
|
+
for (let index = this.scopes.length - 1; index >= 0; index--) {
|
|
2587
|
+
const scope = this.scopes[index];
|
|
2588
|
+
const existing = scope.get(identifier.name);
|
|
2589
|
+
if (existing === "lexical" || (existing === "function" && !this.functionScopes.has(scope))) {
|
|
2590
|
+
throw new Error(`Cannot redeclare binding '${identifier.name}' at line ${identifier.span.start.line}, column ${identifier.span.start.column}.`);
|
|
2591
|
+
}
|
|
2592
|
+
let names = this.varNames.get(scope);
|
|
2593
|
+
if (names === undefined) {
|
|
2594
|
+
names = new Set();
|
|
2595
|
+
this.varNames.set(scope, names);
|
|
2596
|
+
}
|
|
2597
|
+
names.add(identifier.name);
|
|
2598
|
+
if (this.functionScopes.has(scope))
|
|
2599
|
+
return;
|
|
2600
|
+
}
|
|
2550
2601
|
}
|
|
2551
2602
|
consumePunctuator(value) {
|
|
2552
2603
|
const token = this.currentToken();
|
|
@@ -2638,24 +2689,6 @@ function createIdentifierName(token) {
|
|
|
2638
2689
|
span: createTokenSpan(token)
|
|
2639
2690
|
};
|
|
2640
2691
|
}
|
|
2641
|
-
function collectBindingIdentifiers(pattern) {
|
|
2642
|
-
switch (pattern.type) {
|
|
2643
|
-
case "Identifier":
|
|
2644
|
-
return [pattern];
|
|
2645
|
-
case "MemberExpression":
|
|
2646
|
-
return [];
|
|
2647
|
-
case "AssignmentPattern":
|
|
2648
|
-
return collectBindingIdentifiers(pattern.left);
|
|
2649
|
-
case "RestElement":
|
|
2650
|
-
return collectBindingIdentifiers(pattern.argument);
|
|
2651
|
-
case "ArrayPattern":
|
|
2652
|
-
return pattern.elements.flatMap((element) => element === null ? [] : collectBindingIdentifiers(element));
|
|
2653
|
-
case "ObjectPattern":
|
|
2654
|
-
return pattern.properties.flatMap((property) => property.type === "RestElement"
|
|
2655
|
-
? collectBindingIdentifiers(property)
|
|
2656
|
-
: collectBindingIdentifiers(property.value));
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
2692
|
function createLoopLabelFields(labels) {
|
|
2660
2693
|
if (labels === undefined || labels.length === 0) {
|
|
2661
2694
|
return {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const DUMP_FORMAT_VERSION = 1;
|
|
2
|
-
export const EXECUTION_SEMANTICS = "jobs-
|
|
2
|
+
export const EXECUTION_SEMANTICS = "jobs-v3";
|
|
3
3
|
import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
4
4
|
import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/arguments.js";
|
|
5
5
|
import { serializeArguments } from "./arguments.js";
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type SourceSpan } from "../../parse/parser.js";
|
|
2
|
-
export type Diagnostic = {
|
|
3
|
-
code: "AS-AWAIT-NON-PROMISE";
|
|
4
|
-
severity: "warning";
|
|
5
|
-
message: string;
|
|
6
|
-
filename: string;
|
|
7
|
-
line: number;
|
|
8
|
-
column: number;
|
|
9
|
-
span: SourceSpan;
|
|
10
|
-
};
|
|
11
|
-
export declare function AS_AWAIT_NON_PROMISE(source: string, options?: {
|
|
12
|
-
filename?: string;
|
|
13
|
-
}): Diagnostic[];
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { parseModule } from "../../parse/parser.js";
|
|
2
|
-
export function AS_AWAIT_NON_PROMISE(source, options = {}) {
|
|
3
|
-
return new ASAwaitNonPromiseScanner(options.filename ?? "<input>").scan(source);
|
|
4
|
-
}
|
|
5
|
-
class ASAwaitNonPromiseScanner {
|
|
6
|
-
filename;
|
|
7
|
-
diagnostics = [];
|
|
8
|
-
constructor(filename) {
|
|
9
|
-
this.filename = filename;
|
|
10
|
-
}
|
|
11
|
-
scan(source) {
|
|
12
|
-
this.visitModule(parseModule(source, this.filename));
|
|
13
|
-
return this.diagnostics;
|
|
14
|
-
}
|
|
15
|
-
visitModule(node) {
|
|
16
|
-
for (const statement of node.body) {
|
|
17
|
-
this.visitStatement(statement);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
visitStatement(node) {
|
|
21
|
-
switch (node.type) {
|
|
22
|
-
case "FunctionDeclaration":
|
|
23
|
-
this.visitArrowFunction(node);
|
|
24
|
-
return;
|
|
25
|
-
case "BlockStatement":
|
|
26
|
-
this.visitBlockStatement(node);
|
|
27
|
-
return;
|
|
28
|
-
case "ExpressionStatement":
|
|
29
|
-
this.visitExpression(node.expression);
|
|
30
|
-
return;
|
|
31
|
-
case "IfStatement":
|
|
32
|
-
this.visitIfStatement(node);
|
|
33
|
-
return;
|
|
34
|
-
case "ForStatement":
|
|
35
|
-
this.visitForStatement(node);
|
|
36
|
-
return;
|
|
37
|
-
case "ForInStatement":
|
|
38
|
-
case "ForOfStatement":
|
|
39
|
-
this.visitForOfStatement(node);
|
|
40
|
-
return;
|
|
41
|
-
case "WhileStatement":
|
|
42
|
-
case "DoWhileStatement":
|
|
43
|
-
this.visitWhileStatement(node);
|
|
44
|
-
return;
|
|
45
|
-
case "TryStatement":
|
|
46
|
-
this.visitTryStatement(node);
|
|
47
|
-
return;
|
|
48
|
-
case "VariableDeclaration":
|
|
49
|
-
this.visitVariableDeclaration(node);
|
|
50
|
-
return;
|
|
51
|
-
case "ReturnStatement":
|
|
52
|
-
this.visitReturnStatement(node);
|
|
53
|
-
return;
|
|
54
|
-
case "ThrowStatement":
|
|
55
|
-
this.visitThrowStatement(node);
|
|
56
|
-
return;
|
|
57
|
-
case "ExportNamedDeclaration":
|
|
58
|
-
this.visitVariableDeclaration(node.declaration);
|
|
59
|
-
return;
|
|
60
|
-
case "ExportDefaultDeclaration":
|
|
61
|
-
this.visitExpression(node.declaration);
|
|
62
|
-
return;
|
|
63
|
-
case "ImportDeclaration":
|
|
64
|
-
case "BreakStatement":
|
|
65
|
-
case "ContinueStatement":
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
visitBlockStatement(node) {
|
|
70
|
-
for (const statement of node.body) {
|
|
71
|
-
this.visitStatement(statement);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
visitIfStatement(node) {
|
|
75
|
-
this.visitExpression(node.test);
|
|
76
|
-
this.visitStatement(node.consequent);
|
|
77
|
-
if (node.alternate !== undefined) {
|
|
78
|
-
this.visitStatement(node.alternate);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
visitForStatement(node) {
|
|
82
|
-
if (node.init !== undefined) {
|
|
83
|
-
if (node.init.type === "VariableDeclaration") {
|
|
84
|
-
this.visitVariableDeclaration(node.init);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.visitExpression(node.init);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (node.test !== undefined) {
|
|
91
|
-
this.visitExpression(node.test);
|
|
92
|
-
}
|
|
93
|
-
if (node.update !== undefined) {
|
|
94
|
-
this.visitExpression(node.update);
|
|
95
|
-
}
|
|
96
|
-
this.visitStatement(node.body);
|
|
97
|
-
}
|
|
98
|
-
visitForOfStatement(node) {
|
|
99
|
-
if (node.left.type === "VariableDeclaration") {
|
|
100
|
-
this.visitVariableDeclaration(node.left);
|
|
101
|
-
}
|
|
102
|
-
this.visitExpression(node.right);
|
|
103
|
-
this.visitStatement(node.body);
|
|
104
|
-
}
|
|
105
|
-
visitWhileStatement(node) {
|
|
106
|
-
this.visitExpression(node.test);
|
|
107
|
-
this.visitStatement(node.body);
|
|
108
|
-
}
|
|
109
|
-
visitTryStatement(node) {
|
|
110
|
-
this.visitBlockStatement(node.block);
|
|
111
|
-
if (node.handler !== undefined) {
|
|
112
|
-
this.visitCatchClause(node.handler);
|
|
113
|
-
}
|
|
114
|
-
if (node.finalizer !== undefined) {
|
|
115
|
-
this.visitBlockStatement(node.finalizer);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
visitCatchClause(node) {
|
|
119
|
-
this.visitBlockStatement(node.body);
|
|
120
|
-
}
|
|
121
|
-
visitVariableDeclaration(node) {
|
|
122
|
-
for (const declarator of node.declarations) {
|
|
123
|
-
this.visitVariableDeclarator(declarator);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
visitVariableDeclarator(node) {
|
|
127
|
-
if (node.init !== undefined) {
|
|
128
|
-
this.visitExpression(node.init);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
visitReturnStatement(node) {
|
|
132
|
-
if (node.argument !== undefined) {
|
|
133
|
-
this.visitExpression(node.argument);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
visitThrowStatement(node) {
|
|
137
|
-
this.visitExpression(node.argument);
|
|
138
|
-
}
|
|
139
|
-
visitExpression(node) {
|
|
140
|
-
switch (node.type) {
|
|
141
|
-
case "YieldExpression":
|
|
142
|
-
if (node.argument !== undefined) {
|
|
143
|
-
this.visitExpression(node.argument);
|
|
144
|
-
}
|
|
145
|
-
return;
|
|
146
|
-
case "FunctionExpression":
|
|
147
|
-
case "ArrowFunctionExpression":
|
|
148
|
-
this.visitArrowFunction(node);
|
|
149
|
-
return;
|
|
150
|
-
case "AwaitExpression":
|
|
151
|
-
this.visitAwaitExpression(node);
|
|
152
|
-
return;
|
|
153
|
-
case "ArrayExpression":
|
|
154
|
-
this.visitArrayExpression(node);
|
|
155
|
-
return;
|
|
156
|
-
case "ObjectExpression":
|
|
157
|
-
this.visitObjectExpression(node);
|
|
158
|
-
return;
|
|
159
|
-
case "UnaryExpression":
|
|
160
|
-
this.visitUnaryExpression(node);
|
|
161
|
-
return;
|
|
162
|
-
case "BinaryExpression":
|
|
163
|
-
case "LogicalExpression":
|
|
164
|
-
this.visitBinaryLikeExpression(node);
|
|
165
|
-
return;
|
|
166
|
-
case "ConditionalExpression":
|
|
167
|
-
this.visitConditionalExpression(node);
|
|
168
|
-
return;
|
|
169
|
-
case "MemberExpression":
|
|
170
|
-
this.visitMemberExpression(node);
|
|
171
|
-
return;
|
|
172
|
-
case "AssignmentExpression":
|
|
173
|
-
this.visitAssignmentExpression(node);
|
|
174
|
-
return;
|
|
175
|
-
case "CallExpression":
|
|
176
|
-
this.visitCallExpression(node);
|
|
177
|
-
return;
|
|
178
|
-
case "TemplateLiteral":
|
|
179
|
-
this.visitTemplateLiteral(node);
|
|
180
|
-
return;
|
|
181
|
-
case "TaggedTemplateExpression":
|
|
182
|
-
this.visitTaggedTemplateExpression(node);
|
|
183
|
-
return;
|
|
184
|
-
case "Identifier":
|
|
185
|
-
case "BooleanLiteral":
|
|
186
|
-
case "MetaProperty":
|
|
187
|
-
case "NullLiteral":
|
|
188
|
-
case "NumericLiteral":
|
|
189
|
-
case "RegexLiteral":
|
|
190
|
-
case "StringLiteral":
|
|
191
|
-
case "UndefinedLiteral":
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
visitArrowFunction(node) {
|
|
196
|
-
if (node.body.type === "BlockStatement") {
|
|
197
|
-
this.visitBlockStatement(node.body);
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
this.visitExpression(node.body);
|
|
201
|
-
}
|
|
202
|
-
visitAwaitExpression(node) {
|
|
203
|
-
if (isKnownNonPromiseExpression(node.argument)) {
|
|
204
|
-
this.report(node.argument.span);
|
|
205
|
-
}
|
|
206
|
-
this.visitExpression(node.argument);
|
|
207
|
-
}
|
|
208
|
-
visitArrayExpression(node) {
|
|
209
|
-
for (const element of node.elements) {
|
|
210
|
-
if (element.type === "SpreadElement") {
|
|
211
|
-
this.visitExpression(element.argument);
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
this.visitExpression(element);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
visitObjectExpression(node) {
|
|
218
|
-
for (const property of node.properties) {
|
|
219
|
-
if (property.type === "SpreadElement") {
|
|
220
|
-
this.visitExpression(property.argument);
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
this.visitProperty(property);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
visitProperty(node) {
|
|
227
|
-
if (node.computed) {
|
|
228
|
-
this.visitExpression(node.key);
|
|
229
|
-
}
|
|
230
|
-
this.visitExpression(node.value);
|
|
231
|
-
}
|
|
232
|
-
visitUnaryExpression(node) {
|
|
233
|
-
this.visitExpression(node.argument);
|
|
234
|
-
}
|
|
235
|
-
visitBinaryLikeExpression(node) {
|
|
236
|
-
this.visitExpression(node.left);
|
|
237
|
-
this.visitExpression(node.right);
|
|
238
|
-
}
|
|
239
|
-
visitConditionalExpression(node) {
|
|
240
|
-
this.visitExpression(node.test);
|
|
241
|
-
this.visitExpression(node.consequent);
|
|
242
|
-
this.visitExpression(node.alternate);
|
|
243
|
-
}
|
|
244
|
-
visitMemberExpression(node) {
|
|
245
|
-
this.visitExpression(node.object);
|
|
246
|
-
if (node.computed) {
|
|
247
|
-
this.visitExpression(node.property);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
visitAssignmentExpression(node) {
|
|
251
|
-
this.visitExpression(node.right);
|
|
252
|
-
}
|
|
253
|
-
visitCallExpression(node) {
|
|
254
|
-
this.visitExpression(node.callee);
|
|
255
|
-
for (const argument of node.arguments) {
|
|
256
|
-
if (argument.type === "SpreadElement") {
|
|
257
|
-
this.visitExpression(argument.argument);
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
this.visitExpression(argument);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
visitTemplateLiteral(node) {
|
|
264
|
-
for (const expression of node.expressions) {
|
|
265
|
-
this.visitExpression(expression);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
visitTaggedTemplateExpression(node) {
|
|
269
|
-
this.visitExpression(node.tag);
|
|
270
|
-
this.visitTemplateLiteral(node.quasi);
|
|
271
|
-
}
|
|
272
|
-
report(span) {
|
|
273
|
-
this.diagnostics.push({
|
|
274
|
-
code: "AS-AWAIT-NON-PROMISE",
|
|
275
|
-
severity: "warning",
|
|
276
|
-
message: "Awaiting a known non-promise value has no effect.",
|
|
277
|
-
filename: this.filename,
|
|
278
|
-
line: span.start.line,
|
|
279
|
-
column: span.start.column,
|
|
280
|
-
span
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
function isKnownNonPromiseExpression(node) {
|
|
285
|
-
switch (node.type) {
|
|
286
|
-
case "FunctionExpression":
|
|
287
|
-
case "ArrowFunctionExpression":
|
|
288
|
-
case "ArrayExpression":
|
|
289
|
-
case "BinaryExpression":
|
|
290
|
-
case "BooleanLiteral":
|
|
291
|
-
case "NullLiteral":
|
|
292
|
-
case "NumericLiteral":
|
|
293
|
-
case "ObjectExpression":
|
|
294
|
-
case "StringLiteral":
|
|
295
|
-
case "TemplateLiteral":
|
|
296
|
-
case "UnaryExpression":
|
|
297
|
-
return true;
|
|
298
|
-
default:
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type SourceSpan } from "../../parse/parser.js";
|
|
2
|
-
export type Diagnostic = {
|
|
3
|
-
code: "AS008";
|
|
4
|
-
severity: "error";
|
|
5
|
-
message: string;
|
|
6
|
-
filename: string;
|
|
7
|
-
line: number;
|
|
8
|
-
column: number;
|
|
9
|
-
span: SourceSpan;
|
|
10
|
-
};
|
|
11
|
-
export declare function AS008(source: string, options?: {
|
|
12
|
-
filename?: string;
|
|
13
|
-
}): Diagnostic[];
|