Skip to content

Commit a270cb0

Browse files
authored
fix(es/parser): Parse export default from; with exportDefaultFrom: true option (#10373)
**Related issue:** - Closes #10372
1 parent e9eeba1 commit a270cb0

File tree

7 files changed

+111
-10
lines changed

7 files changed

+111
-10
lines changed

.changeset/weak-coins-cheat.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_ecma_parser: patch
3+
swc_core: patch
4+
---
5+
6+
fix(es/parser): Parse `export default from;` with `exportDefaultFrom: true` option

crates/swc_ecma_parser/src/parser/macros.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ macro_rules! peeked_is {
111111
}
112112
}};
113113

114+
($p:expr, Str) => {{
115+
match peek!($p) {
116+
Some(&Token::Str { .. }) => true,
117+
_ => false,
118+
}
119+
}};
120+
114121
($p:expr, ';') => {{
115122
compile_error!("peeked_is!(self, ';') is invalid");
116123
}};

crates/swc_ecma_parser/src/parser/stmt/module_item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ impl<I: Tokens> Parser<I> {
491491
let decl = self.parse_default_fn(start, decorators)?;
492492
return Ok(decl.into());
493493
} else if self.input.syntax().export_default_from()
494-
&& (is!(self, "from")
494+
&& ((is!(self, "from") && peeked_is!(self, Str))
495495
|| (is!(self, ',') && (peeked_is!(self, '{') || peeked_is!(self, '*'))))
496496
{
497497
export_default = Some(Ident::new_no_ctxt("default".into(), self.input.prev_span()))

crates/swc_ecma_parser/tests/js.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ fn spec(file: PathBuf) {
2323
"{}.json",
2424
file.file_name().unwrap().to_string_lossy()
2525
));
26-
run_spec(&file, &output);
26+
let config_path = file.parent().unwrap().join("config.json");
27+
run_spec(&file, &output, &config_path);
2728
}
2829

29-
fn run_spec(file: &Path, output_json: &Path) {
30+
fn run_spec(file: &Path, output_json: &Path, config_path: &Path) {
3031
let file_name = file
3132
.display()
3233
.to_string()
@@ -50,7 +51,7 @@ fn run_spec(file: &Path, output_json: &Path) {
5051
);
5152
}
5253

53-
with_parser(false, file, false, |p, _| {
54+
with_parser(false, file, false, config_path, |p, _| {
5455
let program = p.parse_program()?.fold_with(&mut Normalizer {
5556
drop_span: false,
5657
is_test262: false,
@@ -73,6 +74,7 @@ fn with_parser<F, Ret>(
7374
treat_error_as_bug: bool,
7475
file_name: &Path,
7576
shift: bool,
77+
config_path: &Path,
7678
f: F,
7779
) -> Result<Ret, StdErr>
7880
where
@@ -89,17 +91,30 @@ where
8991
.load_file(file_name)
9092
.unwrap_or_else(|e| panic!("failed to load {}: {}", file_name.display(), e));
9193

92-
let lexer = Lexer::new(
94+
// Try to load EsSyntax configuration from config.json in the same directory as
95+
// the test file
96+
let syntax = {
97+
let mut config_str = String::new();
98+
File::open(config_path)
99+
.ok()
100+
.and_then(|mut file| file.read_to_string(&mut config_str).ok())
101+
.and_then(|_| serde_json::from_str::<EsSyntax>(&config_str).ok())
102+
}
103+
.map(Syntax::Es)
104+
.unwrap_or_else(|| {
105+
eprintln!(
106+
"Failed to load or parse {}, using default configuration",
107+
config_path.display()
108+
);
93109
Syntax::Es(EsSyntax {
94110
explicit_resource_management: true,
95111
import_attributes: true,
96112
decorators: true,
97113
..Default::default()
98-
}),
99-
EsVersion::Es2015,
100-
(&*fm).into(),
101-
Some(&comments),
102-
);
114+
})
115+
});
116+
117+
let lexer = Lexer::new(syntax, EsVersion::Es2015, (&*fm).into(), Some(&comments));
103118

104119
let mut p = Parser::new_from(lexer);
105120

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"syntax": "ecmascript",
3+
"exportDefaultFrom": true,
4+
"jsx": false
5+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const from = {};
2+
export default from;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"type": "Module",
3+
"span": {
4+
"start": 1,
5+
"end": 38
6+
},
7+
"body": [
8+
{
9+
"type": "VariableDeclaration",
10+
"span": {
11+
"start": 1,
12+
"end": 17
13+
},
14+
"ctxt": 0,
15+
"kind": "const",
16+
"declare": false,
17+
"declarations": [
18+
{
19+
"type": "VariableDeclarator",
20+
"span": {
21+
"start": 7,
22+
"end": 16
23+
},
24+
"id": {
25+
"type": "Identifier",
26+
"span": {
27+
"start": 7,
28+
"end": 11
29+
},
30+
"ctxt": 0,
31+
"value": "from",
32+
"optional": false,
33+
"typeAnnotation": null
34+
},
35+
"init": {
36+
"type": "ObjectExpression",
37+
"span": {
38+
"start": 14,
39+
"end": 16
40+
},
41+
"properties": []
42+
},
43+
"definite": false
44+
}
45+
]
46+
},
47+
{
48+
"type": "ExportDefaultExpression",
49+
"span": {
50+
"start": 18,
51+
"end": 38
52+
},
53+
"expression": {
54+
"type": "Identifier",
55+
"span": {
56+
"start": 33,
57+
"end": 37
58+
},
59+
"ctxt": 0,
60+
"value": "from",
61+
"optional": false
62+
}
63+
}
64+
],
65+
"interpreter": null
66+
}

0 commit comments

Comments
 (0)