@@ -27,13 +27,13 @@ pub struct CJSLexer {
27
27
pub fn_returned : bool ,
28
28
pub exports_alias : IndexSet < String > ,
29
29
pub idents : IndexMap < String , IdentKind > ,
30
- pub exports : IndexSet < String > ,
30
+ pub named_exports : IndexSet < String > ,
31
31
pub reexports : IndexSet < String > ,
32
32
}
33
33
34
34
impl CJSLexer {
35
35
fn clear ( & mut self ) {
36
- self . exports . clear ( ) ;
36
+ self . named_exports . clear ( ) ;
37
37
self . reexports . clear ( ) ;
38
38
}
39
39
@@ -51,15 +51,15 @@ impl CJSLexer {
51
51
} else if let Some ( class) = self . as_class ( expr) {
52
52
self . clear ( ) ;
53
53
for name in get_class_static_names ( & class) {
54
- self . exports . insert ( name) ;
54
+ self . named_exports . insert ( name) ;
55
55
}
56
56
} else if let Some ( FnDesc { stmts, extends } ) = self . as_function ( expr) {
57
57
self . clear ( ) ;
58
58
if self . call_mode {
59
59
self . walk_body ( stmts, true ) ;
60
60
} else {
61
61
for name in extends {
62
- self . exports . insert ( name) ;
62
+ self . named_exports . insert ( name) ;
63
63
}
64
64
}
65
65
} else if let Expr :: Call ( call) = expr {
@@ -316,7 +316,7 @@ impl CJSLexer {
316
316
_ => None ,
317
317
} ;
318
318
if let Some ( name) = name {
319
- self . exports . insert ( name) ;
319
+ self . named_exports . insert ( name) ;
320
320
}
321
321
}
322
322
PropOrSpread :: Spread ( SpreadElement { expr, .. } ) => match expr. as_ref ( ) {
@@ -426,11 +426,17 @@ impl CJSLexer {
426
426
427
427
fn is_exports_expr ( & self , expr : & Expr ) -> bool {
428
428
match expr {
429
+ // (0, exports)
430
+ Expr :: Seq ( SeqExpr { exprs, .. } ) => {
431
+ let last_expr = exprs. last ( ) . unwrap ( ) ;
432
+ self . is_exports_expr ( last_expr)
433
+ }
429
434
Expr :: Ident ( id) => {
430
435
let id = id. sym . as_ref ( ) ;
431
436
self . is_exports_ident ( id)
432
437
}
433
438
Expr :: Member ( _) => is_member ( expr, "module" , "exports" ) ,
439
+ Expr :: Paren ( ParenExpr { expr, .. } ) => self . is_exports_expr ( expr) ,
434
440
_ => false ,
435
441
}
436
442
}
@@ -448,9 +454,9 @@ impl CJSLexer {
448
454
449
455
// exports.foo || (exports.foo = {})
450
456
// foo = exports.foo || (exports.foo = {})
451
- fn get_bare_export_names ( & mut self , expr : & Expr ) -> Option < String > {
457
+ fn get_export_name_of_call_arg ( & mut self , expr : & Expr ) -> Option < String > {
452
458
if let Expr :: Assign ( assign) = expr {
453
- return self . get_bare_export_names ( assign. right . as_ref ( ) ) ;
459
+ return self . get_export_name_of_call_arg ( assign. right . as_ref ( ) ) ;
454
460
}
455
461
456
462
if let Expr :: Bin ( bin) = expr {
@@ -499,7 +505,7 @@ impl CJSLexer {
499
505
let obj_name = obj. sym . as_ref ( ) ;
500
506
if self . is_exports_ident ( obj_name) {
501
507
// exports.foo = 'bar'
502
- self . exports . insert ( prop) ;
508
+ self . named_exports . insert ( prop) ;
503
509
if let Expr :: Assign ( dep_assign) = assign. right . as_ref ( ) {
504
510
self . get_exports_from_assign ( dep_assign) ;
505
511
}
@@ -511,15 +517,15 @@ impl CJSLexer {
511
517
}
512
518
Expr :: Member ( _) => {
513
519
if is_member ( obj, "module" , "exports" ) {
514
- self . exports . insert ( prop) ;
520
+ self . named_exports . insert ( prop) ;
515
521
}
516
522
}
517
523
_ => { }
518
524
}
519
525
}
520
526
} else {
521
- if let Some ( bare_export_name ) = self . get_bare_export_names ( assign. right . as_ref ( ) ) {
522
- self . exports . insert ( bare_export_name ) ;
527
+ if let Some ( name ) = self . get_export_name_of_call_arg ( assign. right . as_ref ( ) ) {
528
+ self . named_exports . insert ( name ) ;
523
529
}
524
530
}
525
531
}
@@ -545,13 +551,13 @@ impl CJSLexer {
545
551
( & * * obj, & * prop)
546
552
{
547
553
if obj_sym. as_ref ( ) . eq ( webpack_require_sym) && prop_sym. as_ref ( ) . eq ( "r" ) {
548
- self . exports . insert ( "__esModule" . to_string ( ) ) ;
554
+ self . named_exports . insert ( "__esModule" . to_string ( ) ) ;
549
555
}
550
556
if obj_sym. as_ref ( ) . eq ( webpack_require_sym) && prop_sym. as_ref ( ) . eq ( "d" ) {
551
557
let CallExpr { args, .. } = & * call;
552
558
if let Some ( ExprOrSpread { expr, .. } ) = args. get ( 1 ) {
553
559
if let Expr :: Lit ( Lit :: Str ( Str { value, .. } ) ) = & * * expr {
554
- self . exports . insert ( value. as_ref ( ) . to_string ( ) ) ;
560
+ self . named_exports . insert ( value. as_ref ( ) . to_string ( ) ) ;
555
561
}
556
562
}
557
563
}
@@ -587,7 +593,7 @@ impl CJSLexer {
587
593
if sym. as_ref ( ) . eq ( webpack_exports_sym) {
588
594
if let MemberProp :: Ident ( prop) = prop {
589
595
if prop. sym . as_ref ( ) . eq ( "default" ) {
590
- self . exports . insert ( "default" . to_string ( ) ) ;
596
+ self . named_exports . insert ( "default" . to_string ( ) ) ;
591
597
}
592
598
}
593
599
}
@@ -616,7 +622,7 @@ impl CJSLexer {
616
622
let prop_sym_ref = prop_sym. as_ref ( ) ;
617
623
618
624
if prop_sym_ref. eq ( "r" ) {
619
- self . exports . insert ( "__esModule" . to_string ( ) ) ;
625
+ self . named_exports . insert ( "__esModule" . to_string ( ) ) ;
620
626
found_webpack_require_exprs = true ;
621
627
}
622
628
if prop_sym_ref. eq ( "d" ) {
@@ -630,7 +636,7 @@ impl CJSLexer {
630
636
..
631
637
} ) = & * * prop
632
638
{
633
- self . exports . insert ( sym. as_ref ( ) . to_string ( ) ) ;
639
+ self . named_exports . insert ( sym. as_ref ( ) . to_string ( ) ) ;
634
640
found_webpack_require_exprs = true ;
635
641
}
636
642
}
@@ -747,6 +753,7 @@ impl CJSLexer {
747
753
} )
748
754
. sum ( ) ;
749
755
}
756
+
750
757
fn is_umd_iife_call ( & mut self , call : & CallExpr ) -> Option < Vec < Stmt > > {
751
758
if call. args . len ( ) == 2 {
752
759
let mut arg1 = call. args . get ( 1 ) . unwrap ( ) . expr . as_ref ( ) ;
@@ -953,21 +960,22 @@ impl CJSLexer {
953
960
954
961
fn parse_expr ( & mut self , expr : & Expr ) {
955
962
match expr {
963
+ Expr :: Seq ( SeqExpr { exprs, .. } ) => {
964
+ for expr in exprs {
965
+ self . parse_expr ( expr) ;
966
+ }
967
+ }
956
968
// exports.foo = 'bar'
957
969
// module.exports.foo = 'bar'
958
970
// module.exports = { foo: 'bar' }
959
971
// module.exports = { ...require('a'), ...require('b') }
960
972
// module.exports = require('lib')
961
973
// foo = exports.foo || (exports.foo = {})
962
- Expr :: Seq ( SeqExpr { exprs, .. } ) => {
963
- for expr in exprs {
964
- self . parse_expr ( expr) ;
965
- }
966
- }
967
974
Expr :: Assign ( assign) => {
968
975
self . get_exports_from_assign ( & assign) ;
969
976
}
970
977
// Object.defineProperty(exports, 'foo', { value: 'bar' })
978
+ // Object.defineProperty((0, exports), 'foo', { value: 'bar' })
971
979
// Object.defineProperty(module.exports, 'foo', { value: 'bar' })
972
980
// Object.defineProperty(module, 'exports', { value: { foo: 'bar' }})
973
981
// Object.assign(exports, { foo: 'bar' })
@@ -1016,7 +1024,7 @@ impl CJSLexer {
1016
1024
}
1017
1025
if is_exports && with_value_or_getter {
1018
1026
if let Some ( name) = name {
1019
- self . exports . insert ( name) ;
1027
+ self . named_exports . insert ( name) ;
1020
1028
}
1021
1029
}
1022
1030
if is_module {
@@ -1028,7 +1036,7 @@ impl CJSLexer {
1028
1036
let is_module = is_module_ident ( call. args [ 0 ] . expr . as_ref ( ) ) ;
1029
1037
let is_exports = self . is_exports_expr ( call. args [ 0 ] . expr . as_ref ( ) ) ;
1030
1038
for arg in & call. args [ 1 ..] {
1031
- if let Some ( props) = self . as_obj ( arg. expr . as_ref ( ) ) {
1039
+ if let Some ( props) = self . as_obj ( & arg. expr ) {
1032
1040
if is_module {
1033
1041
let mut with_exports: Option < Expr > = None ;
1034
1042
for prop in props {
@@ -1050,7 +1058,7 @@ impl CJSLexer {
1050
1058
} else if is_exports {
1051
1059
self . use_object_as_exports ( props) ;
1052
1060
}
1053
- } else if let Some ( reexport) = self . as_reexport ( arg. expr . as_ref ( ) ) {
1061
+ } else if let Some ( reexport) = self . as_reexport ( & arg. expr ) {
1054
1062
if is_exports {
1055
1063
self . reexports . insert ( reexport) ;
1056
1064
}
@@ -1077,8 +1085,8 @@ impl CJSLexer {
1077
1085
for arg in & call. args {
1078
1086
if arg. spread . is_none ( ) {
1079
1087
// (function() { ... })(exports.foo || (exports.foo = {}))
1080
- if let Some ( bare_export_name ) = self . get_bare_export_names ( arg. expr . as_ref ( ) ) {
1081
- self . exports . insert ( bare_export_name ) ;
1088
+ if let Some ( name ) = self . get_export_name_of_call_arg ( & arg. expr ) {
1089
+ self . named_exports . insert ( name ) ;
1082
1090
}
1083
1091
}
1084
1092
}
@@ -1096,8 +1104,8 @@ impl CJSLexer {
1096
1104
// (function() { ... })(exports.foo || (exports.foo = {}))
1097
1105
for arg in & call. args {
1098
1106
if arg. spread . is_none ( ) {
1099
- if let Some ( bare_export_name ) = self . get_bare_export_names ( arg. expr . as_ref ( ) ) {
1100
- self . exports . insert ( bare_export_name ) ;
1107
+ if let Some ( name ) = self . get_export_name_of_call_arg ( & arg. expr ) {
1108
+ self . named_exports . insert ( name ) ;
1101
1109
}
1102
1110
}
1103
1111
}
@@ -1117,13 +1125,28 @@ impl CJSLexer {
1117
1125
) ;
1118
1126
}
1119
1127
// 0 && (module.exports = { foo })
1120
- Expr :: Bin ( BinExpr { op, right, .. } ) => {
1128
+ // process.env.NODE_ENV === 'production' && (() => { module.exports = { foo } })()
1129
+ Expr :: Bin ( BinExpr { left, op, right, .. } ) => {
1121
1130
if matches ! ( op, BinaryOp :: LogicalAnd ) {
1122
- if let Expr :: Assign ( assign) = right. as_ref ( ) {
1123
- self . get_exports_from_assign ( assign) ;
1131
+ if let Expr :: Call ( call) = right. as_ref ( ) {
1132
+ if let Some ( body) = is_iife_call ( & call) {
1133
+ if self . is_true ( left) {
1134
+ for arg in & call. args {
1135
+ if arg. spread . is_none ( ) {
1136
+ // (function() { ... })(exports.foo || (exports.foo = {}))
1137
+ if let Some ( name) = self . get_export_name_of_call_arg ( & arg. expr ) {
1138
+ self . named_exports . insert ( name) ;
1139
+ }
1140
+ }
1141
+ }
1142
+ self . walk_body ( body, false ) ;
1143
+ }
1144
+ }
1124
1145
} else if let Expr :: Paren ( paren) = right. as_ref ( ) {
1125
1146
if let Expr :: Assign ( assign) = paren. expr . as_ref ( ) {
1126
- self . get_exports_from_assign ( assign) ;
1147
+ if is_lit_number ( & left) || self . is_true ( & left) {
1148
+ self . get_exports_from_assign ( assign) ;
1149
+ }
1127
1150
}
1128
1151
}
1129
1152
}
@@ -1172,8 +1195,8 @@ impl CJSLexer {
1172
1195
for decl in var. as_ref ( ) . decls . iter ( ) {
1173
1196
self . try_to_mark_exports_alias ( decl) ;
1174
1197
if let Some ( init_expr) = & decl. init {
1175
- if let Some ( bare_export_name ) = self . get_bare_export_names ( init_expr) {
1176
- self . exports . insert ( bare_export_name ) ;
1198
+ if let Some ( name ) = self . get_export_name_of_call_arg ( init_expr) {
1199
+ self . named_exports . insert ( name ) ;
1177
1200
}
1178
1201
}
1179
1202
}
@@ -1475,12 +1498,12 @@ impl CJSLexer {
1475
1498
fn_returned : false ,
1476
1499
idents : self . idents . clone ( ) ,
1477
1500
exports_alias : self . exports_alias . clone ( ) ,
1478
- exports : self . exports . clone ( ) ,
1501
+ named_exports : self . named_exports . clone ( ) ,
1479
1502
reexports : self . reexports . clone ( ) ,
1480
1503
} ;
1481
1504
lexer. walk ( body, as_fn) ;
1482
1505
self . fn_returned = lexer. fn_returned ;
1483
- self . exports = lexer. exports ;
1506
+ self . named_exports = lexer. named_exports ;
1484
1507
self . reexports = lexer. reexports ;
1485
1508
}
1486
1509
}
@@ -1588,6 +1611,13 @@ fn is_string_literal(expr: &Expr, value: &str) -> bool {
1588
1611
}
1589
1612
}
1590
1613
1614
+ fn is_lit_number ( expr : & Expr ) -> bool {
1615
+ match expr {
1616
+ Expr :: Lit ( Lit :: Num ( _) ) => true ,
1617
+ _ => false ,
1618
+ }
1619
+ }
1620
+
1591
1621
fn is_typeof ( expr : & Expr , identifier : & str ) -> bool {
1592
1622
match & * expr {
1593
1623
Expr :: Unary ( UnaryExpr { arg, op, .. } ) => match op {
0 commit comments