Skip to content

Commit 69f1ceb

Browse files
authored
fix: detect bound require reexports in cjs analysis (#328)
1 parent 6444ba5 commit 69f1ceb

File tree

1 file changed

+66
-18
lines changed

1 file changed

+66
-18
lines changed

src/cjs_parse.rs

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,10 @@ impl Visit for CjsVisitor {
184184
self.visit_object_define(call_expr)
185185
} else if is_export_callee(&call_expr.callee) {
186186
// __export, __exportStar, tslib.__export, etc...
187-
if let Some(name) = get_export_require_arg(call_expr) {
188-
self.add_reexport(name);
187+
if let Some(name) =
188+
get_export_require_arg(call_expr, &self.var_assignments)
189+
{
190+
self.add_reexport(&name);
189191
}
190192
}
191193

@@ -223,7 +225,10 @@ impl Visit for CjsVisitor {
223225
false
224226
}
225227

226-
fn get_export_require_arg(call_expr: &CallExpr) -> Option<&str> {
228+
fn get_export_require_arg(
229+
call_expr: &CallExpr,
230+
var_assignments: &HashMap<String, String>,
231+
) -> Option<String> {
227232
if call_expr.args.iter().any(|a| a.spread.is_some()) {
228233
return None;
229234
}
@@ -233,10 +238,19 @@ impl Visit for CjsVisitor {
233238
// (0, tslib_1.__exportStar)(require("./file"), exports);
234239
|| call_expr.args.len() == 2 && is_exports_expr(&call_expr.args[1].expr)
235240
{
236-
get_expr_require_value(&call_expr.args[0].expr)
237-
} else {
238-
None
241+
if let Some(require_value) =
242+
get_expr_require_value(&call_expr.args[0].expr)
243+
{
244+
return Some(require_value.to_string());
245+
}
246+
if let Some(ident) = call_expr.args[0].expr.as_ident() {
247+
// Handle __export(require("something"))
248+
// https://github.com/nodejs/node/blob/65df9ad6438ca0c852a8f208361ae9507e072c9e/deps/merve/merve.h#L99
249+
return var_assignments.get(&*ident.sym).cloned();
250+
}
239251
}
252+
253+
None
240254
}
241255
}
242256

@@ -250,8 +264,6 @@ impl Visit for CjsVisitor {
250264
AssignTarget::Simple(SimpleAssignTarget::Ident(left_ident)) => {
251265
if is_exports_ident(&left_ident.id) {
252266
self.visit_exports_right_expr(&assign_expr.right);
253-
} else if let Some(right_expr) = assign_expr.right.as_assign() {
254-
self.visit_assign_expr(right_expr);
255267
}
256268
}
257269
AssignTarget::Simple(SimpleAssignTarget::Member(left_member)) => {
@@ -263,9 +275,6 @@ impl Visit for CjsVisitor {
263275
// * `exports.something = other`
264276
if let Some(prop_name) = get_member_prop_text(&left_member.prop) {
265277
self.add_export(prop_name);
266-
if let Some(right_expr) = assign_expr.right.as_assign() {
267-
self.visit_assign_expr(right_expr);
268-
}
269278
} else if let Some(right_member) = assign_expr.right.as_member() {
270279
// check for:
271280
// * `exports[key] = _something[key];
@@ -278,16 +287,12 @@ impl Visit for CjsVisitor {
278287
self.add_reexport(&require_value);
279288
}
280289
}
281-
} else if let Some(right_expr) = assign_expr.right.as_assign() {
282-
self.visit_assign_expr(right_expr);
283-
}
284-
}
285-
_ => {
286-
if let Some(right_expr) = assign_expr.right.as_assign() {
287-
self.visit_assign_expr(right_expr);
288290
}
289291
}
292+
_ => {}
290293
}
294+
295+
assign_expr.visit_children_with(self);
291296
}
292297
}
293298

@@ -683,6 +688,49 @@ mod test {
683688
]);
684689
}
685690

691+
#[test]
692+
fn typescript_reexports_via_bound_ident() {
693+
let tester = parse_cjs(
694+
r#"
695+
"use strict";
696+
var reexported_1 = require("./reexported");
697+
__export(reexported_1);
698+
"#,
699+
);
700+
701+
tester.assert_reexports(vec!["./reexported"]);
702+
}
703+
704+
#[test]
705+
fn typescript_enum_exports() {
706+
let tester = parse_cjs(
707+
r#"
708+
"use strict";
709+
var MyEnum;
710+
(function (MyEnum) {
711+
MyEnum[MyEnum["A"] = 0] = "A";
712+
MyEnum[MyEnum["B"] = 1] = "B";
713+
})(MyEnum || (MyEnum = {}));
714+
exports.MyEnum = MyEnum;
715+
exports.Outer = (exports.Inner = {});
716+
"#,
717+
);
718+
719+
tester.assert_exports(vec!["Inner", "MyEnum", "Outer"]);
720+
}
721+
722+
#[test]
723+
fn nested_exports_assignment_in_expression() {
724+
let tester = parse_cjs(
725+
r#"
726+
"use strict";
727+
exports.A = (exports.B = (exports.C = {}));
728+
"#,
729+
);
730+
731+
tester.assert_exports(vec!["A", "B", "C"]);
732+
}
733+
686734
#[test]
687735
fn rollup_babel_reexport_getter() {
688736
let tester = parse_cjs(

0 commit comments

Comments
 (0)