@@ -3,9 +3,9 @@ use std::{collections::HashMap, ffi::OsStr, path::Path};
3
3
use swc_core:: {
4
4
common:: { sync:: Lrc , Mark , SourceMap , SyntaxContext , DUMMY_SP } ,
5
5
ecma:: {
6
- ast,
7
- ast:: MemberProp ,
6
+ ast:: { self , MemberProp } ,
8
7
atoms:: JsWord ,
8
+ utils:: member_expr,
9
9
visit:: { VisitMut , VisitMutWith } ,
10
10
} ,
11
11
} ;
@@ -26,6 +26,7 @@ pub struct NodeReplacer<'a> {
26
26
pub global_mark : Mark ,
27
27
pub globals : HashMap < JsWord , ( SyntaxContext , ast:: Stmt ) > ,
28
28
pub filename : & ' a Path ,
29
+ pub is_esm : bool ,
29
30
pub unresolved_mark : Mark ,
30
31
/// This will be set to true if the file has either __dirname or __filename replacements inserted
31
32
pub has_node_replacements : & ' a mut bool ,
@@ -50,6 +51,7 @@ impl<'a> VisitMut for NodeReplacer<'a> {
50
51
let replace_me_value = swc_core:: ecma:: atoms:: JsWord :: from ( "$parcel$filenameReplace" ) ;
51
52
52
53
let unresolved_mark = self . unresolved_mark ;
54
+ let is_esm = self . is_esm ;
53
55
let expr = |this : & NodeReplacer | {
54
56
let filename = if let Some ( name) = this. filename . file_name ( ) {
55
57
name
@@ -63,14 +65,9 @@ impl<'a> VisitMut for NodeReplacer<'a> {
63
65
args : vec ! [
64
66
ast:: ExprOrSpread {
65
67
spread: None ,
66
- expr: Box :: new( ast:: Expr :: Ident ( ast:: Ident {
67
- optional: false ,
68
- span: DUMMY_SP ,
69
- ctxt: SyntaxContext :: empty( ) ,
70
- // This also uses __dirname as later in the path.join call the hierarchy is then correct
71
- // Otherwise path.join(__filename, '..') would be one level to shallow (due to the /filename.js at the end)
72
- sym: swc_core:: ecma:: atoms:: JsWord :: from( "__dirname" ) ,
73
- } ) ) ,
68
+ // This also uses __dirname as later in the path.join call the hierarchy is then correct
69
+ // Otherwise path.join(__filename, '..') would be one level to shallow (due to the /filename.js at the end)
70
+ expr: Box :: new( dirname( is_esm, unresolved_mark) ) ,
74
71
} ,
75
72
ast:: ExprOrSpread {
76
73
spread: None ,
@@ -119,6 +116,7 @@ impl<'a> VisitMut for NodeReplacer<'a> {
119
116
let replace_me_value = swc_core:: ecma:: atoms:: JsWord :: from ( "$parcel$dirnameReplace" ) ;
120
117
121
118
let unresolved_mark = self . unresolved_mark ;
119
+ let is_esm = self . is_esm ;
122
120
if self . update_binding ( id, "$parcel$__dirname" . into ( ) , |_| {
123
121
Call ( ast:: CallExpr {
124
122
span : DUMMY_SP ,
@@ -127,12 +125,7 @@ impl<'a> VisitMut for NodeReplacer<'a> {
127
125
args : vec ! [
128
126
ast:: ExprOrSpread {
129
127
spread: None ,
130
- expr: Box :: new( ast:: Expr :: Ident ( ast:: Ident {
131
- optional: false ,
132
- span: DUMMY_SP ,
133
- ctxt: SyntaxContext :: empty( ) ,
134
- sym: swc_core:: ecma:: atoms:: JsWord :: from( "__dirname" ) ,
135
- } ) ) ,
128
+ expr: Box :: new( dirname( is_esm, unresolved_mark) ) ,
136
129
} ,
137
130
ast:: ExprOrSpread {
138
131
spread: None ,
@@ -220,6 +213,43 @@ impl NodeReplacer<'_> {
220
213
}
221
214
}
222
215
216
+ fn dirname ( is_esm : bool , unresolved_mark : Mark ) -> ast:: Expr {
217
+ if is_esm {
218
+ use ast:: * ;
219
+ // require('path').dirname(require('url').fileURLToPath(import.meta.url))
220
+ // TODO: use import.meta.dirname if available?
221
+ Expr :: Call ( CallExpr {
222
+ callee : Callee :: Expr ( Box :: new ( Expr :: Member ( MemberExpr {
223
+ obj : Box :: new ( Expr :: Call ( create_require ( "path" . into ( ) , unresolved_mark) ) ) ,
224
+ prop : MemberProp :: Ident ( IdentName :: new ( "dirname" . into ( ) , DUMMY_SP ) ) ,
225
+ span : DUMMY_SP ,
226
+ } ) ) ) ,
227
+ args : vec ! [ ExprOrSpread {
228
+ expr: Box :: new( Expr :: Call ( CallExpr {
229
+ callee: Callee :: Expr ( Box :: new( Expr :: Member ( MemberExpr {
230
+ obj: Box :: new( Expr :: Call ( create_require( "url" . into( ) , unresolved_mark) ) ) ,
231
+ prop: MemberProp :: Ident ( IdentName :: new( "fileURLToPath" . into( ) , DUMMY_SP ) ) ,
232
+ span: DUMMY_SP ,
233
+ } ) ) ) ,
234
+ args: vec![ ExprOrSpread {
235
+ expr: Box :: new( Expr :: Member ( member_expr!(
236
+ Default :: default ( ) ,
237
+ DUMMY_SP ,
238
+ import. meta. url
239
+ ) ) ) ,
240
+ spread: None ,
241
+ } ] ,
242
+ ..Default :: default ( )
243
+ } ) ) ,
244
+ spread: None ,
245
+ } ] ,
246
+ ..Default :: default ( )
247
+ } )
248
+ } else {
249
+ ast:: Expr :: Ident ( ast:: Ident :: new_no_ctxt ( "__dirname" . into ( ) , DUMMY_SP ) )
250
+ }
251
+ }
252
+
223
253
#[ cfg( test) ]
224
254
mod test {
225
255
use crate :: test_utils:: run_visit;
@@ -243,6 +273,7 @@ console.log(__filename);
243
273
has_node_replacements : & mut has_node_replacements,
244
274
items : & mut items,
245
275
unresolved_mark : context. unresolved_mark ,
276
+ is_esm : false ,
246
277
} )
247
278
. output_code ;
248
279
@@ -277,6 +308,7 @@ console.log(__dirname);
277
308
has_node_replacements : & mut has_node_replacements,
278
309
items : & mut items,
279
310
unresolved_mark : context. unresolved_mark ,
311
+ is_esm : false ,
280
312
} )
281
313
. output_code ;
282
314
@@ -314,6 +346,7 @@ function something(__filename, __dirname) {
314
346
has_node_replacements : & mut has_node_replacements,
315
347
items : & mut items,
316
348
unresolved_mark : context. unresolved_mark ,
349
+ is_esm : false ,
317
350
} )
318
351
. output_code ;
319
352
@@ -346,6 +379,7 @@ const filename = obj.__filename;
346
379
has_node_replacements : & mut has_node_replacements,
347
380
items : & mut items,
348
381
unresolved_mark : context. unresolved_mark ,
382
+ is_esm : false ,
349
383
} )
350
384
. output_code ;
351
385
@@ -374,6 +408,7 @@ const filename = obj[__filename];
374
408
has_node_replacements : & mut has_node_replacements,
375
409
items : & mut items,
376
410
unresolved_mark : context. unresolved_mark ,
411
+ is_esm : false ,
377
412
} )
378
413
. output_code ;
379
414
@@ -386,4 +421,37 @@ const filename = obj[$parcel$__filename];
386
421
assert_eq ! ( has_node_replacements, true ) ;
387
422
assert_eq ! ( items. len( ) , 1 ) ;
388
423
}
424
+
425
+ #[ test]
426
+ fn test_esm ( ) {
427
+ let mut has_node_replacements = false ;
428
+ let mut items = vec ! [ ] ;
429
+
430
+ let code = r#"
431
+ console.log(__filename);
432
+ console.log(__dirname);
433
+ "# ;
434
+ let output_code = run_visit ( code, |context| NodeReplacer {
435
+ source_map : context. source_map . clone ( ) ,
436
+ global_mark : context. global_mark ,
437
+ globals : HashMap :: new ( ) ,
438
+ filename : Path :: new ( "/path/random.js" ) ,
439
+ has_node_replacements : & mut has_node_replacements,
440
+ items : & mut items,
441
+ unresolved_mark : context. unresolved_mark ,
442
+ is_esm : true ,
443
+ } )
444
+ . output_code ;
445
+
446
+ let expected_code = r#"
447
+ var $parcel$__filename = require("path").resolve(require("path").dirname(require("url").fileURLToPath(import.meta.url)), "$parcel$filenameReplace", "random.js");
448
+ var $parcel$__dirname = require("path").resolve(require("path").dirname(require("url").fileURLToPath(import.meta.url)), "$parcel$dirnameReplace");
449
+ console.log($parcel$__filename);
450
+ console.log($parcel$__dirname);
451
+ "#
452
+ . trim_start ( ) ;
453
+ assert_eq ! ( output_code, expected_code) ;
454
+ assert_eq ! ( has_node_replacements, true ) ;
455
+ assert_eq ! ( items. len( ) , 2 ) ;
456
+ }
389
457
}
0 commit comments