1
- import assert from " node:assert/strict" ;
2
- import { describe , it } from " node:test" ;
1
+ import assert from ' node:assert/strict' ;
2
+ import { describe , it } from ' node:test' ;
3
3
import astGrep from '@ast-grep/napi' ;
4
4
import dedent from 'dedent' ;
5
- import { getNodeImportStatements , getNodeImportCalls } from "./import-statement.ts" ;
5
+ import {
6
+ getNodeImportStatements ,
7
+ getNodeImportCalls ,
8
+ } from './import-statement.ts' ;
6
9
7
- describe ( " import-statement" , ( ) => {
8
- it ( " should return import statements" , ( ) => {
10
+ describe ( ' import-statement' , ( ) => {
11
+ it ( ' should return import statements' , ( ) => {
9
12
const code = dedent `
10
13
import fs from 'fs';
11
14
import { join } from 'node:path';
@@ -31,14 +34,17 @@ describe("import-statement", () => {
31
34
32
35
const childProcessImports = getNodeImportStatements ( ast , 'child_process' ) ;
33
36
assert . strictEqual ( childProcessImports . length , 1 ) ;
34
- assert . strictEqual ( childProcessImports [ 0 ] . field ( 'source' ) ?. text ( ) , '"child_process"' ) ;
37
+ assert . strictEqual (
38
+ childProcessImports [ 0 ] . field ( 'source' ) ?. text ( ) ,
39
+ '"child_process"' ,
40
+ ) ;
35
41
36
42
const utilImports = getNodeImportStatements ( ast , 'util' ) ;
37
43
assert . strictEqual ( utilImports . length , 1 ) ;
38
44
assert . strictEqual ( utilImports [ 0 ] . field ( 'source' ) ?. text ( ) , '"node:util"' ) ;
39
45
} ) ;
40
46
41
- it ( " should return import calls" , ( ) => {
47
+ it ( ' should return import calls' , ( ) => {
42
48
const code = dedent `
43
49
const fs = await import('fs');
44
50
var { join } = await import('node:path');
@@ -57,25 +63,54 @@ describe("import-statement", () => {
57
63
assert . strictEqual ( fsCalls . length , 1 ) ;
58
64
const fsCallExpr = fsCalls [ 0 ] . field ( 'value' ) ?. children ( ) [ 1 ] ; // await_expression -> call_expression
59
65
assert . strictEqual ( fsCallExpr ?. field ( 'function' ) ?. text ( ) , 'import' ) ;
60
- assert . strictEqual ( fsCallExpr ?. field ( 'arguments' ) ?. find ( { rule : { kind : "string" } } ) ?. text ( ) , "'fs'" ) ;
66
+ assert . strictEqual (
67
+ fsCallExpr
68
+ ?. field ( 'arguments' )
69
+ ?. find ( { rule : { kind : 'string' } } )
70
+ ?. text ( ) ,
71
+ "'fs'" ,
72
+ ) ;
61
73
62
74
const pathCalls = getNodeImportCalls ( ast , 'path' ) ;
63
75
assert . strictEqual ( pathCalls . length , 1 ) ;
64
76
const pathCallExpr = pathCalls [ 0 ] . field ( 'value' ) ?. children ( ) [ 1 ] ; // await_expression -> call_expression
65
77
assert . strictEqual ( pathCallExpr ?. field ( 'function' ) ?. text ( ) , 'import' ) ;
66
- assert . strictEqual ( pathCallExpr ?. field ( 'arguments' ) ?. find ( { rule : { kind : "string" } } ) ?. text ( ) , "'node:path'" ) ;
78
+ assert . strictEqual (
79
+ pathCallExpr
80
+ ?. field ( 'arguments' )
81
+ ?. find ( { rule : { kind : 'string' } } )
82
+ ?. text ( ) ,
83
+ "'node:path'" ,
84
+ ) ;
67
85
68
86
const childProcessCalls = getNodeImportCalls ( ast , 'child_process' ) ;
69
87
assert . strictEqual ( childProcessCalls . length , 1 ) ;
70
- const childProcessCallExpr = childProcessCalls [ 0 ] . field ( 'value' ) ?. children ( ) [ 1 ] ; // await_expression -> call_expression
71
- assert . strictEqual ( childProcessCallExpr ?. field ( 'function' ) ?. text ( ) , 'import' ) ;
72
- assert . strictEqual ( childProcessCallExpr ?. field ( 'arguments' ) ?. find ( { rule : { kind : "string" } } ) ?. text ( ) , '"child_process"' ) ;
88
+ const childProcessCallExpr = childProcessCalls [ 0 ]
89
+ . field ( 'value' )
90
+ ?. children ( ) [ 1 ] ; // await_expression -> call_expression
91
+ assert . strictEqual (
92
+ childProcessCallExpr ?. field ( 'function' ) ?. text ( ) ,
93
+ 'import' ,
94
+ ) ;
95
+ assert . strictEqual (
96
+ childProcessCallExpr
97
+ ?. field ( 'arguments' )
98
+ ?. find ( { rule : { kind : 'string' } } )
99
+ ?. text ( ) ,
100
+ '"child_process"' ,
101
+ ) ;
73
102
74
103
const utilCalls = getNodeImportCalls ( ast , 'util' ) ;
75
104
assert . strictEqual ( utilCalls . length , 1 ) ;
76
105
const utilCallExpr = utilCalls [ 0 ] . field ( 'value' ) ?. children ( ) [ 1 ] ; // await_expression -> call_expression
77
106
assert . strictEqual ( utilCallExpr ?. field ( 'function' ) ?. text ( ) , 'import' ) ;
78
- assert . strictEqual ( utilCallExpr ?. field ( 'arguments' ) ?. find ( { rule : { kind : "string" } } ) ?. text ( ) , '"node:util"' ) ;
107
+ assert . strictEqual (
108
+ utilCallExpr
109
+ ?. field ( 'arguments' )
110
+ ?. find ( { rule : { kind : 'string' } } )
111
+ ?. text ( ) ,
112
+ '"node:util"' ,
113
+ ) ;
79
114
} ) ;
80
115
81
116
it ( "shouldn't catch pending promises during import calls" , ( ) => {
@@ -85,6 +120,96 @@ describe("import-statement", () => {
85
120
const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
86
121
87
122
const moduleCalls = getNodeImportCalls ( ast , 'module' ) ;
88
- assert . strictEqual ( moduleCalls . length , 0 , "Pending import calls should not be caught" ) ;
123
+ assert . strictEqual (
124
+ moduleCalls . length ,
125
+ 0 ,
126
+ 'Pending import calls should not be caught' ,
127
+ ) ;
89
128
} ) ;
90
- } )
129
+
130
+ it ( 'should catch thenable during import calls' , ( ) => {
131
+ const code = dedent `
132
+ import("node:fs").then((mdl) => {
133
+ const readFile = mdl.readFile;
134
+
135
+ readFile("package.json", "utf8", (err, data) => {
136
+ if (err) throw err;
137
+ console.log({ data });
138
+ });
139
+ });
140
+ ` ;
141
+ const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
142
+
143
+ const moduleCalls = getNodeImportCalls ( ast , 'fs' ) ;
144
+ assert . strictEqual (
145
+ moduleCalls . length ,
146
+ 1 ,
147
+ 'thenable import calls should be caught' ,
148
+ ) ;
149
+ } ) ;
150
+
151
+ it ( 'should catch thenable during import calls with catch block' , ( ) => {
152
+ const code = dedent `
153
+ import("node:fs").then((mdl) => {
154
+ const readFile = mdl.readFile;
155
+
156
+ readFile("package.json", "utf8", (err, data) => {
157
+ if (err) throw err;
158
+ console.log({ data });
159
+ });
160
+ }).catch(console.log);
161
+ ` ;
162
+ const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
163
+
164
+ const moduleCalls = getNodeImportCalls ( ast , 'fs' ) ;
165
+ assert . strictEqual (
166
+ moduleCalls . length ,
167
+ 1 ,
168
+ 'thenable import calls should be caught' ,
169
+ ) ;
170
+ } ) ;
171
+
172
+ it ( "shouldn't catch when there is no 'then'" , ( ) => {
173
+ const code = dedent `
174
+ import("node:fs").catch(console.log);
175
+ ` ;
176
+ const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
177
+
178
+ const moduleCalls = getNodeImportCalls ( ast , 'fs' ) ;
179
+ assert . strictEqual (
180
+ moduleCalls . length ,
181
+ 0 ,
182
+ "dynamic import without then shouldn't be caught" ,
183
+ ) ;
184
+ } ) ;
185
+
186
+ it ( 'should get variable declarator with module' , ( ) => {
187
+ const code = dedent `
188
+ const variable = 'node:fs'
189
+ import(variable).then(console.log);
190
+ ` ;
191
+ const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
192
+
193
+ const moduleCalls = getNodeImportCalls ( ast , 'fs' ) ;
194
+ assert . strictEqual (
195
+ moduleCalls . length ,
196
+ 1 ,
197
+ 'dynamic import using variable need to be caught' ,
198
+ ) ;
199
+ } ) ;
200
+
201
+ it ( 'should not capture function calls that are not import() expressions' , ( ) => {
202
+ const code = dedent `
203
+ var test = anyFn("fs");
204
+ var test2 = anyFn("node:fs");
205
+ ` ;
206
+ const ast = astGrep . parse ( astGrep . Lang . JavaScript , code ) ;
207
+
208
+ const moduleCalls = getNodeImportCalls ( ast , 'fs' ) ;
209
+ assert . strictEqual (
210
+ moduleCalls . length ,
211
+ 0 ,
212
+ "functions that aren't import shouldn't be caught" ,
213
+ ) ;
214
+ } ) ;
215
+ } ) ;
0 commit comments