diff --git a/src/cjs_parse.rs b/src/cjs_parse.rs index f64b476d..b7e76f45 100644 --- a/src/cjs_parse.rs +++ b/src/cjs_parse.rs @@ -184,8 +184,10 @@ impl Visit for CjsVisitor { self.visit_object_define(call_expr) } else if is_export_callee(&call_expr.callee) { // __export, __exportStar, tslib.__export, etc... - if let Some(name) = get_export_require_arg(call_expr) { - self.add_reexport(name); + if let Some(name) = + get_export_require_arg(call_expr, &self.var_assignments) + { + self.add_reexport(&name); } } @@ -223,7 +225,10 @@ impl Visit for CjsVisitor { false } - fn get_export_require_arg(call_expr: &CallExpr) -> Option<&str> { + fn get_export_require_arg( + call_expr: &CallExpr, + var_assignments: &HashMap, + ) -> Option { if call_expr.args.iter().any(|a| a.spread.is_some()) { return None; } @@ -233,10 +238,19 @@ impl Visit for CjsVisitor { // (0, tslib_1.__exportStar)(require("./file"), exports); || call_expr.args.len() == 2 && is_exports_expr(&call_expr.args[1].expr) { - get_expr_require_value(&call_expr.args[0].expr) - } else { - None + if let Some(require_value) = + get_expr_require_value(&call_expr.args[0].expr) + { + return Some(require_value.to_string()); + } + if let Some(ident) = call_expr.args[0].expr.as_ident() { + // Handle __export(require("something")) + // https://github.com/nodejs/node/blob/65df9ad6438ca0c852a8f208361ae9507e072c9e/deps/merve/merve.h#L99 + return var_assignments.get(&*ident.sym).cloned(); + } } + + None } } @@ -250,8 +264,6 @@ impl Visit for CjsVisitor { AssignTarget::Simple(SimpleAssignTarget::Ident(left_ident)) => { if is_exports_ident(&left_ident.id) { self.visit_exports_right_expr(&assign_expr.right); - } else if let Some(right_expr) = assign_expr.right.as_assign() { - self.visit_assign_expr(right_expr); } } AssignTarget::Simple(SimpleAssignTarget::Member(left_member)) => { @@ -263,9 +275,6 @@ impl Visit for CjsVisitor { // * `exports.something = other` if let Some(prop_name) = get_member_prop_text(&left_member.prop) { self.add_export(prop_name); - if let Some(right_expr) = assign_expr.right.as_assign() { - self.visit_assign_expr(right_expr); - } } else if let Some(right_member) = assign_expr.right.as_member() { // check for: // * `exports[key] = _something[key]; @@ -278,16 +287,12 @@ impl Visit for CjsVisitor { self.add_reexport(&require_value); } } - } else if let Some(right_expr) = assign_expr.right.as_assign() { - self.visit_assign_expr(right_expr); - } - } - _ => { - if let Some(right_expr) = assign_expr.right.as_assign() { - self.visit_assign_expr(right_expr); } } + _ => {} } + + assign_expr.visit_children_with(self); } } @@ -683,6 +688,49 @@ mod test { ]); } + #[test] + fn typescript_reexports_via_bound_ident() { + let tester = parse_cjs( + r#" + "use strict"; + var reexported_1 = require("./reexported"); + __export(reexported_1); + "#, + ); + + tester.assert_reexports(vec!["./reexported"]); + } + + #[test] + fn typescript_enum_exports() { + let tester = parse_cjs( + r#" + "use strict"; + var MyEnum; + (function (MyEnum) { + MyEnum[MyEnum["A"] = 0] = "A"; + MyEnum[MyEnum["B"] = 1] = "B"; + })(MyEnum || (MyEnum = {})); + exports.MyEnum = MyEnum; + exports.Outer = (exports.Inner = {}); + "#, + ); + + tester.assert_exports(vec!["Inner", "MyEnum", "Outer"]); + } + + #[test] + fn nested_exports_assignment_in_expression() { + let tester = parse_cjs( + r#" + "use strict"; + exports.A = (exports.B = (exports.C = {})); + "#, + ); + + tester.assert_exports(vec!["A", "B", "C"]); + } + #[test] fn rollup_babel_reexport_getter() { let tester = parse_cjs(