fix(es/parser): Fix parsing of import type from from (#8309)

**Related issue:**

- Closes #8308.
This commit is contained in:
magic-akari 2023-11-20 14:20:06 +08:00 committed by GitHub
parent af8c1d33f5
commit 00b88399a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 193 additions and 37 deletions

View File

@ -42,15 +42,6 @@ impl<I: Tokens> Parser<I> {
expect!(self, "import");
if self.input.syntax().typescript() && is!(self, IdentRef) && peeked_is!(self, '=') {
return self
.parse_ts_import_equals_decl(
start, /* is_export */ false, /* is_type_only */ false,
)
.map(ModuleDecl::from)
.map(ModuleItem::from);
}
// Handle import 'mod.js'
let str_start = cur_pos!(self);
if let Ok(&Token::Str { .. }) = cur!(self, false) {
@ -84,35 +75,46 @@ impl<I: Tokens> Parser<I> {
})));
}
let type_only = self.input.syntax().typescript()
&& is!(self, "type")
&& (peeked_is!(self, '{') || !peeked_is!(self, "from") && !peeked_is!(self, ','));
if type_only {
assert_and_bump!(self, "type");
if is!(self, IdentRef) && peeked_is!(self, '=') {
return self
.parse_ts_import_equals_decl(
start, /* is_export */ false, /* is_type_only */ true,
)
.map(ModuleDecl::from)
.map(ModuleItem::from);
}
}
let mut type_only = false;
let mut specifiers = vec![];
if is!(self, BindingIdent) {
let local = self.parse_imported_default_binding()?;
//TODO: Better error reporting
if !is!(self, "from") {
expect!(self, ',');
'import_maybe_ident: {
if is!(self, BindingIdent) {
let mut local = self.parse_imported_default_binding()?;
if self.input.syntax().typescript() && local.sym == "type" {
if is_one_of!(self, '*', '{') {
type_only = true;
break 'import_maybe_ident;
}
if is!(self, BindingIdent) {
if !is!(self, "from") || peeked_is!(self, "from") {
type_only = true;
local = self.parse_imported_default_binding()?;
} else if peeked_is!(self, '=') {
type_only = true;
local = self.parse_ident_name()?;
}
}
}
if self.input.syntax().typescript() && is!(self, '=') {
return self
.parse_ts_import_equals_decl(start, local, false, type_only)
.map(ModuleDecl::from)
.map(ModuleItem::from);
}
//TODO: Better error reporting
if !is!(self, "from") {
expect!(self, ',');
}
specifiers.push(ImportSpecifier::Default(ImportDefaultSpecifier {
span: local.span,
local,
}));
}
specifiers.push(ImportSpecifier::Default(ImportDefaultSpecifier {
span: local.span,
local,
}));
}
{
@ -373,9 +375,11 @@ impl<I: Tokens> Parser<I> {
assert_and_bump!(self, "type");
}
let id = self.parse_ident_name()?;
// export import A = B
return self
.parse_ts_import_equals_decl(start, /* is_export */ true, is_type_only)
.parse_ts_import_equals_decl(start, id, /* is_export */ true, is_type_only)
.map(From::from);
}

View File

@ -1133,12 +1133,12 @@ impl<I: Tokens> Parser<I> {
pub(super) fn parse_ts_import_equals_decl(
&mut self,
start: BytePos,
id: Ident,
is_export: bool,
is_type_only: bool,
) -> PResult<Box<TsImportEqualsDecl>> {
debug_assert!(self.input.syntax().typescript());
let id = self.parse_ident_name()?;
expect!(self, '=');
let module_ref = self.parse_ts_module_ref()?;

View File

@ -0,0 +1 @@
import type from from "foo";

View File

@ -0,0 +1,51 @@
{
"type": "Module",
"span": {
"start": 1,
"end": 29,
"ctxt": 0
},
"body": [
{
"type": "ImportDeclaration",
"span": {
"start": 1,
"end": 29,
"ctxt": 0
},
"specifiers": [
{
"type": "ImportDefaultSpecifier",
"span": {
"start": 13,
"end": 17,
"ctxt": 0
},
"local": {
"type": "Identifier",
"span": {
"start": 13,
"end": 17,
"ctxt": 0
},
"value": "from",
"optional": false
}
}
],
"source": {
"type": "StringLiteral",
"span": {
"start": 23,
"end": 28,
"ctxt": 0
},
"value": "foo",
"raw": "\"foo\""
},
"typeOnly": true,
"with": null
}
],
"interpreter": null
}

View File

@ -0,0 +1 @@
import type from = require("foo");

View File

@ -0,0 +1,49 @@
{
"type": "Module",
"span": {
"start": 1,
"end": 35,
"ctxt": 0
},
"body": [
{
"type": "TsImportEqualsDeclaration",
"span": {
"start": 1,
"end": 35,
"ctxt": 0
},
"isExport": false,
"isTypeOnly": true,
"id": {
"type": "Identifier",
"span": {
"start": 13,
"end": 17,
"ctxt": 0
},
"value": "from",
"optional": false
},
"moduleRef": {
"type": "TsExternalModuleReference",
"span": {
"start": 20,
"end": 34,
"ctxt": 0
},
"expression": {
"type": "StringLiteral",
"span": {
"start": 28,
"end": 33,
"ctxt": 0
},
"value": "foo",
"raw": "\"foo\""
}
}
}
],
"interpreter": null
}

View File

@ -0,0 +1 @@
import type async = require("foo");

View File

@ -0,0 +1,49 @@
{
"type": "Module",
"span": {
"start": 1,
"end": 36,
"ctxt": 0
},
"body": [
{
"type": "TsImportEqualsDeclaration",
"span": {
"start": 1,
"end": 36,
"ctxt": 0
},
"isExport": false,
"isTypeOnly": true,
"id": {
"type": "Identifier",
"span": {
"start": 13,
"end": 18,
"ctxt": 0
},
"value": "async",
"optional": false
},
"moduleRef": {
"type": "TsExternalModuleReference",
"span": {
"start": 21,
"end": 35,
"ctxt": 0
},
"expression": {
"type": "StringLiteral",
"span": {
"start": 29,
"end": 34,
"ctxt": 0
},
"value": "foo",
"raw": "\"foo\""
}
}
}
],
"interpreter": null
}