Skip to content

Commit 3e292be

Browse files
committed
lexer: support reexport extendtion
1 parent 659a717 commit 3e292be

File tree

2 files changed

+59
-19
lines changed

2 files changed

+59
-19
lines changed

lexer/src/lexer.rs

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub enum IdentKind {
1010
Object(Vec<PropOrSpread>),
1111
Class(Class),
1212
Fn(FnDesc),
13-
Reexport(String),
13+
Reexport(Reexport),
1414
Unkonwn,
1515
}
1616

@@ -20,6 +20,12 @@ pub struct FnDesc {
2020
extends: Vec<String>,
2121
}
2222

23+
#[derive(Clone, Debug)]
24+
pub struct Reexport {
25+
path: String,
26+
extends: Vec<String>,
27+
}
28+
2329
pub struct ModuleLexer {
2430
pub node_env: String,
2531
pub call_mode: bool,
@@ -44,10 +50,13 @@ impl ModuleLexer {
4450

4551
if let Some(reexport) = self.as_reexport(expr) {
4652
self.clear();
47-
self.reexports.insert(reexport);
53+
for name in reexport.extends {
54+
self.named_exports.insert(name);
55+
}
56+
self.reexports.insert(reexport.path);
4857
} else if let Some(props) = self.as_obj(expr) {
4958
self.clear();
50-
self.use_object_as_exports(props);
59+
self.update_exports_from_object(props);
5160
} else if let Some(class) = self.as_class(expr) {
5261
self.clear();
5362
for name in get_class_static_names(&class) {
@@ -67,7 +76,10 @@ impl ModuleLexer {
6776
if let Some(callee) = with_expr_callee(call) {
6877
if let Some(reexport) = self.as_reexport(callee) {
6978
self.clear();
70-
self.reexports.insert(format!("{}()", reexport));
79+
for name in reexport.extends {
80+
self.named_exports.insert(name);
81+
}
82+
self.reexports.insert(format!("{}()", reexport.path));
7183
} else if let Some(FnDesc { stmts, .. }) = self.as_function(callee) {
7284
self.walk_body(stmts, true);
7385
}
@@ -104,8 +116,10 @@ impl ModuleLexer {
104116
}
105117
}
106118
Expr::Call(call) => {
107-
if let Some(file) = with_require_call(&call) {
108-
self.idents.insert(name.into(), IdentKind::Reexport(file));
119+
if let Some(path) = with_require_call(&call) {
120+
self
121+
.idents
122+
.insert(name.into(), IdentKind::Reexport(Reexport { path, extends: vec![] }));
109123
}
110124
}
111125
Expr::Object(obj) => {
@@ -244,14 +258,20 @@ impl ModuleLexer {
244258
}
245259
}
246260

247-
fn as_reexport(&self, expr: &Expr) -> Option<String> {
261+
fn as_reexport(&self, expr: &Expr) -> Option<Reexport> {
248262
match expr {
249263
Expr::Paren(ParenExpr { expr, .. }) => return self.as_reexport(expr),
250-
Expr::Call(call) => with_require_call(&call),
264+
Expr::Call(call) => {
265+
if let Some(path) = with_require_call(&call) {
266+
return Some(Reexport { path, extends: vec![] });
267+
} else {
268+
None
269+
}
270+
}
251271
Expr::Ident(id) => {
252272
if let Some(value) = self.idents.get(id.sym.as_ref()) {
253273
match value {
254-
IdentKind::Reexport(file) => return Some(file.to_owned()),
274+
IdentKind::Reexport(reexport) => return Some(reexport.clone()),
255275
IdentKind::Alias(id) => return self.as_reexport(&Expr::Ident(quote_ident(id))),
256276
_ => {}
257277
}
@@ -307,8 +327,8 @@ impl ModuleLexer {
307327
}
308328
}
309329

310-
fn use_object_as_exports(&mut self, props: Vec<PropOrSpread>) {
311-
for prop in props {
330+
fn update_exports_from_object(&mut self, obj_props: Vec<PropOrSpread>) {
331+
for prop in obj_props {
312332
match prop {
313333
PropOrSpread::Prop(prop) => {
314334
let name = match prop.as_ref() {
@@ -324,10 +344,10 @@ impl ModuleLexer {
324344
PropOrSpread::Spread(SpreadElement { expr, .. }) => match expr.as_ref() {
325345
Expr::Ident(_) => {
326346
if let Some(props) = self.as_obj(expr.as_ref()) {
327-
self.use_object_as_exports(props);
347+
self.update_exports_from_object(props);
328348
}
329349
if let Some(reexport) = self.as_reexport(expr.as_ref()) {
330-
self.reexports.insert(reexport);
350+
self.reexports.insert(reexport.path);
331351
}
332352
}
333353
Expr::Call(call) => {
@@ -927,6 +947,11 @@ impl ModuleLexer {
927947
self
928948
.idents
929949
.insert(obj_name.into(), IdentKind::Fn(FnDesc { stmts, extends }));
950+
} else if let Some(Reexport { path, mut extends }) = self.as_reexport(&obj) {
951+
extends.push(key.to_owned());
952+
self
953+
.idents
954+
.insert(obj_name.into(), IdentKind::Reexport(Reexport { path, extends }));
930955
}
931956
}
932957
}
@@ -1064,28 +1089,28 @@ impl ModuleLexer {
10641089
self.replace_exports_from_expr(&exports_expr);
10651090
}
10661091
} else if is_exports {
1067-
self.use_object_as_exports(props);
1092+
self.update_exports_from_object(props);
10681093
}
10691094
} else if let Some(reexport) = self.as_reexport(&arg.expr) {
10701095
if is_exports {
1071-
self.reexports.insert(reexport);
1096+
self.reexports.insert(reexport.path);
10721097
}
10731098
}
10741099
}
10751100
} else if is_tslib_export_star_call(&call) && call.args.len() >= 2 {
10761101
let is_exports = self.is_exports_expr(call.args[1].expr.as_ref());
10771102
if is_exports {
10781103
if let Some(props) = self.as_obj(call.args[0].expr.as_ref()) {
1079-
self.use_object_as_exports(props);
1104+
self.update_exports_from_object(props);
10801105
} else if let Some(reexport) = self.as_reexport(call.args[0].expr.as_ref()) {
1081-
self.reexports.insert(reexport);
1106+
self.reexports.insert(reexport.path);
10821107
}
10831108
}
10841109
} else if is_export_call(&call) && call.args.len() > 0 {
10851110
if let Some(props) = self.as_obj(call.args[0].expr.as_ref()) {
1086-
self.use_object_as_exports(props);
1111+
self.update_exports_from_object(props);
10871112
} else if let Some(reexport) = self.as_reexport(call.args[0].expr.as_ref()) {
1088-
self.reexports.insert(reexport);
1113+
self.reexports.insert(reexport.path);
10891114
}
10901115
} else if let Some(body) = self.is_umd_iife_call(&call) {
10911116
self.walk_body(body, false);

lexer/src/test.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ mod tests {
130130
assert_eq!(reexports.join(","), "lib");
131131
}
132132

133+
134+
133135
#[test]
134136
fn parse_cjs_exports_case_10() {
135137
let source = r#"
@@ -166,6 +168,19 @@ mod tests {
166168
assert_eq!(exports.join(","), "foo");
167169
}
168170

171+
#[test]
172+
fn parse_cjs_exports_case_10_3() {
173+
let source = r#"
174+
var lib = require("lib")
175+
lib.foo = 'bar'
176+
module.exports = lib
177+
"#;
178+
let lexer = CommonJSModuleLexer::init("index.cjs", source).expect("could not parse the module");
179+
let (exports, reexports) = lexer.analyze("development", false);
180+
assert_eq!(exports.join(","), "foo");
181+
assert_eq!(reexports.join(","), "lib");
182+
}
183+
169184
#[test]
170185
fn parse_cjs_exports_case_11() {
171186
let source = r#"

0 commit comments

Comments
 (0)