Skip to content

Commit 7d724d8

Browse files
authoredFeb 6, 2024
fix(es/parser): Fix parsing of dynamic source phase imports (#8611)
1 parent 7a3b554 commit 7d724d8

File tree

4 files changed

+54
-74
lines changed

4 files changed

+54
-74
lines changed
 

‎crates/swc_ecma_parser/src/parser/expr.rs

+42-62
Original file line numberDiff line numberDiff line change
@@ -267,21 +267,6 @@ impl<I: Tokens> Parser<I> {
267267
})));
268268
}
269269

270-
tok!("import") => {
271-
let import = self.parse_ident_name()?;
272-
273-
if is!(self, '.') {
274-
self.state.found_module_item = true;
275-
if !self.ctx().can_be_module {
276-
let span = span!(self, start);
277-
self.emit_err(span, SyntaxError::ImportMetaInScript);
278-
}
279-
return self.parse_import_meta_prop(start, import.span);
280-
}
281-
282-
return self.parse_dynamic_import(start, import.span, ImportPhase::Evaluation);
283-
}
284-
285270
tok!("async") => {
286271
if peeked_is!(self, "function")
287272
&& !self.input.has_linebreak_between_cur_and_peeked()
@@ -548,30 +533,6 @@ impl<I: Tokens> Parser<I> {
548533
self.parse_member_expr_or_new_expr(false)
549534
}
550535

551-
/// `parseImportMetaProperty`
552-
pub(super) fn parse_import_meta_prop(
553-
&mut self,
554-
start: BytePos,
555-
import_span: Span,
556-
) -> PResult<Box<Expr>> {
557-
expect!(self, '.');
558-
559-
let ident = self.parse_ident_name()?;
560-
561-
match &*ident.sym {
562-
"meta" => Ok(MetaPropExpr {
563-
span: span!(self, import_span.lo()),
564-
kind: MetaPropKind::ImportMeta,
565-
}
566-
.into()),
567-
"source" => self.parse_dynamic_import(start, import_span, ImportPhase::Source),
568-
// TODO: The proposal doesn't mention import.defer yet because it was
569-
// pending on a decision for import.source. Wait to enable it until it's
570-
// included in the proposal.
571-
_ => unexpected!(self, "meta"),
572-
}
573-
}
574-
575536
/// `is_new_expr`: true iff we are parsing production 'NewExpression'.
576537
#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
577538
fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult<Box<Expr>> {
@@ -690,11 +651,7 @@ impl<I: Tokens> Parser<I> {
690651
return self.parse_subscripts(base, true, false);
691652
}
692653
if eat!(self, "import") {
693-
let base = Callee::Import(Import {
694-
span: span!(self, start),
695-
phase: Default::default(),
696-
});
697-
return self.parse_subscripts(base, true, false);
654+
return self.parse_dynamic_import_or_import_meta(start, true);
698655
}
699656
let obj = self.parse_primary_expr()?;
700657
return_if_arrow!(self, obj);
@@ -1633,11 +1590,7 @@ impl<I: Tokens> Parser<I> {
16331590
return self.parse_subscripts(obj, false, false);
16341591
}
16351592
if eat!(self, "import") {
1636-
let obj = Callee::Import(Import {
1637-
span: span!(self, start),
1638-
phase: Default::default(),
1639-
});
1640-
return self.parse_subscripts(obj, false, false);
1593+
return self.parse_dynamic_import_or_import_meta(start, false);
16411594
}
16421595

16431596
let callee = self.parse_new_expr()?;
@@ -2104,24 +2057,51 @@ impl<I: Tokens> Parser<I> {
21042057
Ok(v)
21052058
}
21062059

2107-
pub(super) fn parse_dynamic_import(
2060+
pub(super) fn parse_dynamic_import_or_import_meta(
21082061
&mut self,
21092062
start: BytePos,
2110-
import_span: Span,
2063+
no_call: bool,
2064+
) -> PResult<Box<Expr>> {
2065+
if eat!(self, '.') {
2066+
self.state.found_module_item = true;
2067+
2068+
let ident = self.parse_ident_name()?;
2069+
2070+
match &*ident.sym {
2071+
"meta" => {
2072+
let span = span!(self, start);
2073+
if !self.ctx().can_be_module {
2074+
self.emit_err(span, SyntaxError::ImportMetaInScript);
2075+
}
2076+
let expr = MetaPropExpr {
2077+
span,
2078+
kind: MetaPropKind::ImportMeta,
2079+
};
2080+
self.parse_subscripts(Callee::Expr(expr.into()), no_call, false)
2081+
}
2082+
"source" => self.parse_dynamic_import_call(start, no_call, ImportPhase::Source),
2083+
// TODO: The proposal doesn't mention import.defer yet because it was
2084+
// pending on a decision for import.source. Wait to enable it until it's
2085+
// included in the proposal.
2086+
_ => unexpected!(self, "meta"),
2087+
}
2088+
} else {
2089+
self.parse_dynamic_import_call(start, no_call, ImportPhase::Evaluation)
2090+
}
2091+
}
2092+
2093+
fn parse_dynamic_import_call(
2094+
&mut self,
2095+
start: BytePos,
2096+
no_call: bool,
21112097
phase: ImportPhase,
21122098
) -> PResult<Box<Expr>> {
2113-
let args = self.parse_args(true)?;
2114-
let import = Box::new(Expr::Call(CallExpr {
2099+
let import = Callee::Import(Import {
21152100
span: span!(self, start),
2116-
callee: Callee::Import(Import {
2117-
span: import_span,
2118-
phase,
2119-
}),
2120-
args,
2121-
type_args: Default::default(),
2122-
}));
2123-
2124-
self.parse_subscripts(Callee::Expr(import), true, false)
2101+
phase,
2102+
});
2103+
2104+
self.parse_subscripts(import, no_call, false)
21252105
}
21262106

21272107
pub(super) fn check_assign_target(&mut self, expr: &Expr, deny_call: bool) {

‎crates/swc_ecma_parser/tests/js/source-phase-imports/attributes-expression/input.js.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"type": "Script",
2+
"type": "Module",
33
"span": {
44
"start": 1,
55
"end": 47,
@@ -17,17 +17,17 @@
1717
"type": "CallExpression",
1818
"span": {
1919
"start": 1,
20-
"end": 14,
20+
"end": 46,
2121
"ctxt": 0
2222
},
2323
"callee": {
2424
"type": "Import",
2525
"span": {
2626
"start": 1,
27-
"end": 7,
27+
"end": 14,
2828
"ctxt": 0
2929
},
30-
"phase": "evaluation"
30+
"phase": "source"
3131
},
3232
"arguments": [
3333
{

‎crates/swc_ecma_parser/tests/js/source-phase-imports/dynamic-import-no-createImportExpressions/input.js.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"type": "Script",
2+
"type": "Module",
33
"span": {
44
"start": 1,
55
"end": 22,
@@ -17,17 +17,17 @@
1717
"type": "CallExpression",
1818
"span": {
1919
"start": 1,
20-
"end": 14,
20+
"end": 21,
2121
"ctxt": 0
2222
},
2323
"callee": {
2424
"type": "Import",
2525
"span": {
2626
"start": 1,
27-
"end": 7,
27+
"end": 14,
2828
"ctxt": 0
2929
},
30-
"phase": "evaluation"
30+
"phase": "source"
3131
},
3232
"arguments": [
3333
{

‎crates/swc_ecma_parser/tests/js/source-phase-imports/dynamic-import/input.js.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"type": "Script",
2+
"type": "Module",
33
"span": {
44
"start": 1,
55
"end": 22,
@@ -17,17 +17,17 @@
1717
"type": "CallExpression",
1818
"span": {
1919
"start": 1,
20-
"end": 14,
20+
"end": 21,
2121
"ctxt": 0
2222
},
2323
"callee": {
2424
"type": "Import",
2525
"span": {
2626
"start": 1,
27-
"end": 7,
27+
"end": 14,
2828
"ctxt": 0
2929
},
30-
"phase": "evaluation"
30+
"phase": "source"
3131
},
3232
"arguments": [
3333
{

0 commit comments

Comments
 (0)
Please sign in to comment.