@@ -31,9 +31,11 @@ const sourceFiles = walk(DEMO_DIR).filter(
3131) ;
3232
3333function importSpecifiers ( source : string ) : string [ ] {
34- return [ ...source . matchAll ( / (?: i m p o r t | e x p o r t ) [ \s \S ] * ?f r o m \s + [ " ' ] ( [ ^ " ' ] + ) [ " ' ] / g) ] . map (
35- ( match ) => match [ 1 ] !
36- ) ;
34+ return [
35+ ...source . matchAll ( / (?: i m p o r t | e x p o r t ) [ \s \S ] * ?f r o m \s + [ " ' ] ( [ ^ " ' ] + ) [ " ' ] / g) ,
36+ // A side-effect or dynamic import binds nothing, so it never reaches a `from`.
37+ ...source . matchAll ( / \b i m p o r t \s * \( ? \s * [ " ' ] ( [ ^ " ' ] + ) [ " ' ] / g) ,
38+ ] . map ( ( match ) => match [ 1 ] ! ) ;
3739}
3840
3941describe ( "demo ids" , ( ) => {
@@ -289,6 +291,26 @@ describe("chart fixtures", () => {
289291} ) ;
290292
291293describe ( "isolation" , ( ) => {
294+ it ( "reads every form an import can take, including the ones that bind nothing" , ( ) => {
295+ const source = [
296+ `import { a } from "./a";` ,
297+ `import "~/db.server";` ,
298+ `import type { B } from "./b";` ,
299+ `export * from "./c";` ,
300+ `const d = await import("~/routes/thing");` ,
301+ `import("./lazy").then((m) => m.go());` ,
302+ ] . join ( "\n" ) ;
303+
304+ expect ( importSpecifiers ( source ) . sort ( ) ) . toEqual ( [
305+ "./a" ,
306+ "./b" ,
307+ "./c" ,
308+ "./lazy" ,
309+ "~/db.server" ,
310+ "~/routes/thing" ,
311+ ] ) ;
312+ } ) ;
313+
292314 it ( "imports no server module and no route" , ( ) => {
293315 for ( const path of sourceFiles ) {
294316 const specifiers = importSpecifiers ( readFileSync ( path , "utf8" ) ) ;
0 commit comments