diff --git a/crates/swc_ecma_parser/src/error.rs b/crates/swc_ecma_parser/src/error.rs index c42ae4ddbeb..10773cb0dc8 100644 --- a/crates/swc_ecma_parser/src/error.rs +++ b/crates/swc_ecma_parser/src/error.rs @@ -174,6 +174,9 @@ pub enum SyntaxError { NumericSeparatorIsAllowedOnlyBetweenTwoDigits, + ImportBindingIsString(JsWord), + ExportBindingIsString, + TS1003, TS1005, TS1009, @@ -461,6 +464,17 @@ impl SyntaxError { SyntaxError::GeneratorConstructor => "A constructor cannot be generator".into(), + SyntaxError::ImportBindingIsString(str) => format!( + "A string literal cannot be used as an imported binding.\n- Did you mean `import \ + {{ \"{}\" as foo }}`?", + str + ) + .into(), + + SyntaxError::ExportBindingIsString => { + "A string literal cannot be used as an exported binding without `from`.".into() + } + SyntaxError::TS1003 => "Expected an identifier".into(), SyntaxError::TS1005 => "Expected a semicolon".into(), SyntaxError::TS1009 => "Trailing comma is not allowed".into(), diff --git a/crates/swc_ecma_parser/src/parser/ident.rs b/crates/swc_ecma_parser/src/parser/ident.rs index 44fd52ec2fb..5c4658cd28b 100644 --- a/crates/swc_ecma_parser/src/parser/ident.rs +++ b/crates/swc_ecma_parser/src/parser/ident.rs @@ -73,6 +73,21 @@ impl<'a, I: Tokens> Parser { Ok(Ident::new(w, span!(self, start))) } + // https://tc39.es/ecma262/#prod-ModuleExportName + pub(super) fn parse_module_export_name(&mut self) -> PResult { + let module_export_name = match cur!(self, false) { + Ok(&Token::Str { .. }) => match self.parse_lit()? { + Lit::Str(str_lit) => ModuleExportName::Str(str_lit), + _ => unreachable!(), + }, + Ok(&Word(..)) => ModuleExportName::Ident(self.parse_ident_name()?), + _ => { + unexpected!(self, "identifier or string"); + } + }; + Ok(module_export_name) + } + /// Identifier /// /// In strict mode, "yield" is SyntaxError if matched. diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs index b5f0c5d6e09..62f1793432f 100644 --- a/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/crates/swc_ecma_parser/src/parser/stmt.rs @@ -2174,4 +2174,23 @@ export default function waitUntil(callback, options = {}) { p.parse_module() }); } + + #[test] + #[should_panic( + expected = "A string literal cannot be used as an imported binding.\n- Did you mean \ + `import { \"str\" as foo }`?" + )] + fn error_for_string_literal_is_import_binding() { + let src = "import { \"str\" } from \"mod\""; + test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module()); + } + + #[test] + #[should_panic( + expected = "A string literal cannot be used as an exported binding without `from`." + )] + fn error_for_string_literal_is_export_binding() { + let src = "export { 'foo' };"; + test_parser(src, Syntax::Es(Default::default()), |p| p.parse_module()); + } } diff --git a/crates/swc_ecma_parser/src/parser/stmt/module_item.rs b/crates/swc_ecma_parser/src/parser/stmt/module_item.rs index 5f582e2f5bc..b27cea78e72 100644 --- a/crates/swc_ecma_parser/src/parser/stmt/module_item.rs +++ b/crates/swc_ecma_parser/src/parser/stmt/module_item.rs @@ -190,11 +190,9 @@ impl<'a, I: Tokens> Parser { /// Parse `foo`, `foo2 as bar` in `import { foo, foo2 as bar }` fn parse_import_specifier(&mut self, type_only: bool) -> PResult { let start = cur_pos!(self); - match cur!(self, false) { - Ok(&Word(..)) => { + match self.parse_module_export_name()? { + ModuleExportName::Ident(mut orig_name) => { let mut is_type_only = false; - let mut orig_name = self.parse_ident_name()?; - // Handle: // `import { type xx } from 'mod'` // `import { type xx as yy } from 'mod'` @@ -302,7 +300,23 @@ impl<'a, I: Tokens> Parser { is_type_only, })) } - _ => unexpected!(self, "an identifier"), + ModuleExportName::Str(orig_str) => { + if eat!(self, "as") { + let local = self.parse_binding_ident()?.id; + Ok(ImportSpecifier::Named(ImportNamedSpecifier { + span: Span::new(start, local.span.hi(), Default::default()), + local, + imported: Some(ModuleExportName::Str(orig_str)), + is_type_only: false, + })) + } else { + syntax_error!( + self, + orig_str.span, + SyntaxError::ImportBindingIsString(orig_str.value) + ) + } + } } } @@ -422,10 +436,10 @@ impl<'a, I: Tokens> Parser { if eat!(self, "as") { let _ = cur!(self, false); - let name = self.parse_ident_name()?; + let name = self.parse_module_export_name()?; export_ns = Some(ExportSpecifier::Namespace(ExportNamespaceSpecifier { span: span!(self, ns_export_specifier_start), - name: ModuleExportName::Ident(name), + name, })); } } @@ -609,11 +623,13 @@ impl<'a, I: Tokens> Parser { exported: default, })) } + let mut string_export_binding_span = None; while !eof!(self) && !is!(self, '}') { - specifiers.push( - self.parse_named_export_specifier(type_only) - .map(ExportSpecifier::Named)?, - ); + let specifier = self.parse_named_export_specifier(type_only)?; + if let ModuleExportName::Str(str_export) = &specifier.orig { + string_export_binding_span = Some(str_export.span); + } + specifiers.push(ExportSpecifier::Named(specifier)); if is!(self, '}') { break; @@ -634,6 +650,9 @@ impl<'a, I: Tokens> Parser { SyntaxError::ExportDefaultWithOutFrom ); } + if let Some(span) = string_export_binding_span { + syntax_error!(self, span, SyntaxError::ExportBindingIsString); + } None }; let (src, asserts) = match opt { @@ -659,87 +678,104 @@ impl<'a, I: Tokens> Parser { let start = cur_pos!(self); let mut is_type_only = false; - let mut orig = self.parse_ident_name()?; - // Handle: - // `export { type xx }` - // `export { type xx as yy }` - // `export { type as }` - // `export { type as as }` - // `export { type as as as }` - if self.syntax().typescript() && orig.sym == js_word!("type") && is!(self, IdentName) { - let possibly_orig = self.parse_ident_name()?; - if possibly_orig.sym == js_word!("as") { - // `export { type as }` - if !is!(self, IdentName) { - if type_only { - self.emit_err(orig.span, SyntaxError::TS2207); - } - - return Ok(ExportNamedSpecifier { - span: span!(self, start), - orig: ModuleExportName::Ident(possibly_orig), - exported: None, - is_type_only: true, - }); - } - - let maybe_as = self.parse_ident_name()?; - if maybe_as.sym == js_word!("as") { - if is!(self, IdentName) { - // `export { type as as as }` - // `export { type as as foo }` - let exported = self.parse_ident_name()?; - - if type_only { - self.emit_err(orig.span, SyntaxError::TS2207); - } - - return Ok(ExportNamedSpecifier { - span: Span::new(start, orig.span.hi(), Default::default()), - orig: ModuleExportName::Ident(possibly_orig), - exported: Some(ModuleExportName::Ident(exported)), - is_type_only: true, - }); - } else { - // `export { type as as }` - return Ok(ExportNamedSpecifier { - span: Span::new(start, orig.span.hi(), Default::default()), - orig: ModuleExportName::Ident(orig), - exported: Some(ModuleExportName::Ident(maybe_as)), - is_type_only: false, - }); - } - } else { - // `export { type as xxx }` - return Ok(ExportNamedSpecifier { - span: Span::new(start, orig.span.hi(), Default::default()), - orig: ModuleExportName::Ident(orig), - exported: Some(ModuleExportName::Ident(maybe_as)), - is_type_only: false, - }); - } - } else { + let orig = match self.parse_module_export_name()? { + ModuleExportName::Ident(orig_ident) => { + // Handle: // `export { type xx }` // `export { type xx as yy }` - if type_only { - self.emit_err(orig.span, SyntaxError::TS2207); - } + // `export { type as }` + // `export { type as as }` + // `export { type as as as }` + if self.syntax().typescript() + && orig_ident.sym == js_word!("type") + && is!(self, IdentName) + { + let possibly_orig = self.parse_ident_name()?; + if possibly_orig.sym == js_word!("as") { + // `export { type as }` + if !is!(self, IdentName) { + if type_only { + self.emit_err(orig_ident.span, SyntaxError::TS2207); + } - orig = possibly_orig; - is_type_only = true; + return Ok(ExportNamedSpecifier { + span: span!(self, start), + orig: ModuleExportName::Ident(possibly_orig), + exported: None, + is_type_only: true, + }); + } + + let maybe_as = self.parse_ident_name()?; + if maybe_as.sym == js_word!("as") { + if is!(self, IdentName) { + // `export { type as as as }` + // `export { type as as foo }` + let exported = self.parse_ident_name()?; + + if type_only { + self.emit_err(orig_ident.span, SyntaxError::TS2207); + } + + return Ok(ExportNamedSpecifier { + span: Span::new( + start, + orig_ident.span.hi(), + Default::default(), + ), + orig: ModuleExportName::Ident(possibly_orig), + exported: Some(ModuleExportName::Ident(exported)), + is_type_only: true, + }); + } else { + // `export { type as as }` + return Ok(ExportNamedSpecifier { + span: Span::new( + start, + orig_ident.span.hi(), + Default::default(), + ), + orig: ModuleExportName::Ident(orig_ident), + exported: Some(ModuleExportName::Ident(maybe_as)), + is_type_only: false, + }); + } + } else { + // `export { type as xxx }` + return Ok(ExportNamedSpecifier { + span: Span::new(start, orig_ident.span.hi(), Default::default()), + orig: ModuleExportName::Ident(orig_ident), + exported: Some(ModuleExportName::Ident(maybe_as)), + is_type_only: false, + }); + } + } else { + // `export { type xx }` + // `export { type xx as yy }` + if type_only { + self.emit_err(orig_ident.span, SyntaxError::TS2207); + } + + is_type_only = true; + ModuleExportName::Ident(possibly_orig) + } + } else { + ModuleExportName::Ident(orig_ident) + } } - } + module_export_name => module_export_name, + }; let exported = if eat!(self, "as") { - Some(ModuleExportName::Ident(self.parse_ident_name()?)) + Some(self.parse_module_export_name()?) } else { None }; Ok(ExportNamedSpecifier { span: span!(self, start), - orig: ModuleExportName::Ident(orig), + orig, exported, is_type_only, }) diff --git a/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js b/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js new file mode 100644 index 00000000000..3019a40fd98 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js @@ -0,0 +1 @@ +import { "default" as quotation } from "Confucius" diff --git a/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js.spans new file mode 100644 index 00000000000..746f170fecd --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/default-import-string-names.js.spans @@ -0,0 +1,54 @@ +warning: Module + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:1 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:1 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:1 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportDecl + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:1 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportSpecifier + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:10 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportNamedSpecifier + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:10 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:23 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:10 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/default-import-string-names.js:1:40 + | +1 | import { "default" as quotation } from "Confucius" + | ^^^^^^^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js new file mode 100644 index 00000000000..49957ddfa8d --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js @@ -0,0 +1,2 @@ +const foo = 3; +export { foo as "str" }; diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js.spans new file mode 100644 index 00000000000..1e3ccc91681 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-1.js.spans @@ -0,0 +1,109 @@ +warning: Module + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:1 + | +1 | / const foo = 3; +2 | | export { foo as "str" }; + | |________________________^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:1 + | +1 | const foo = 3; + | ^^^^^^^^^^^^^^ + +warning: Stmt + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:1 + | +1 | const foo = 3; + | ^^^^^^^^^^^^^^ + +warning: Decl + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:1 + | +1 | const foo = 3; + | ^^^^^^^^^^^^^^ + +warning: VarDecl + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:1 + | +1 | const foo = 3; + | ^^^^^^^^^^^^^^ + +warning: VarDeclarator + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:7 + | +1 | const foo = 3; + | ^^^^^^^ + +warning: Pat + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:7 + | +1 | const foo = 3; + | ^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:7 + | +1 | const foo = 3; + | ^^^ + +warning: Expr + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:13 + | +1 | const foo = 3; + | ^ + +warning: Lit + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:13 + | +1 | const foo = 3; + | ^ + +warning: Number + --> $DIR/tests/span/js/decl/export-string-names-1.js:1:13 + | +1 | const foo = 3; + | ^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:1 + | +2 | export { foo as "str" }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:1 + | +2 | export { foo as "str" }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: NamedExport + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:1 + | +2 | export { foo as "str" }; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ExportSpecifier + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:10 + | +2 | export { foo as "str" }; + | ^^^^^^^^^^^^ + +warning: ExportNamedSpecifier + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:10 + | +2 | export { foo as "str" }; + | ^^^^^^^^^^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:10 + | +2 | export { foo as "str" }; + | ^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-1.js:2:17 + | +2 | export { foo as "str" }; + | ^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js new file mode 100644 index 00000000000..aed41a1ef34 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js @@ -0,0 +1 @@ +export { "str" } from "mod"; diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js.spans new file mode 100644 index 00000000000..497bc3b3a87 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-2.js.spans @@ -0,0 +1,48 @@ +warning: Module + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:1 + | +1 | export { "str" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:1 + | +1 | export { "str" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:1 + | +1 | export { "str" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: NamedExport + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:1 + | +1 | export { "str" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ExportSpecifier + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:10 + | +1 | export { "str" } from "mod"; + | ^^^^^ + +warning: ExportNamedSpecifier + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:10 + | +1 | export { "str" } from "mod"; + | ^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:10 + | +1 | export { "str" } from "mod"; + | ^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-2.js:1:23 + | +1 | export { "str" } from "mod"; + | ^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js new file mode 100644 index 00000000000..ac6a64ee5fb --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js @@ -0,0 +1 @@ +export { "str1" as "str2" } from "mod"; diff --git a/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js.spans new file mode 100644 index 00000000000..6621a6984c7 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/export-string-names-3.js.spans @@ -0,0 +1,54 @@ +warning: Module + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:1 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:1 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:1 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: NamedExport + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:1 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ExportSpecifier + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:10 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^ + +warning: ExportNamedSpecifier + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:10 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^^^^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:10 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:20 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/export-string-names-3.js:1:34 + | +1 | export { "str1" as "str2" } from "mod"; + | ^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js new file mode 100644 index 00000000000..5e21d35b793 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js @@ -0,0 +1 @@ +import { "str" as foo } from "mod" diff --git a/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js.spans new file mode 100644 index 00000000000..90969ca473b --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-1.js.spans @@ -0,0 +1,54 @@ +warning: Module + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:1 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:1 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:1 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportDecl + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:1 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportSpecifier + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:10 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^ + +warning: ImportNamedSpecifier + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:10 + | +1 | import { "str" as foo } from "mod" + | ^^^^^^^^^^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:19 + | +1 | import { "str" as foo } from "mod" + | ^^^ + +warning: Str + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:10 + | +1 | import { "str" as foo } from "mod" + | ^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/import-string-names-1.js:1:30 + | +1 | import { "str" as foo } from "mod" + | ^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js new file mode 100644 index 00000000000..69120638611 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js @@ -0,0 +1 @@ +import { "foo" as bar, "default" as qux } from "module-a" diff --git a/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js.spans new file mode 100644 index 00000000000..d66e6981438 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/import-string-names-2.js.spans @@ -0,0 +1,78 @@ +warning: Module + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:1 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:1 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:1 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportDecl + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:1 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ImportSpecifier + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:10 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^ + +warning: ImportNamedSpecifier + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:10 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:19 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^ + +warning: Str + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:10 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^ + +warning: ImportSpecifier + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:24 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^ + +warning: ImportNamedSpecifier + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:24 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^^^^^^^ + +warning: Ident + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:37 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^ + +warning: Str + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:24 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/import-string-names-2.js:1:48 + | +1 | import { "foo" as bar, "default" as qux } from "module-a" + | ^^^^^^^^^^ + diff --git a/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js b/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js new file mode 100644 index 00000000000..8535d9abc4c --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js @@ -0,0 +1 @@ +export * as "忠恕。" from "Confucius" diff --git a/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js.spans b/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js.spans new file mode 100644 index 00000000000..f3953944848 --- /dev/null +++ b/crates/swc_ecma_parser/tests/span/js/decl/namespace-export-string-names.js.spans @@ -0,0 +1,48 @@ +warning: Module + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:1 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleItem + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:1 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ModuleDecl + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:1 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: NamedExport + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:1 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: ExportSpecifier + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:8 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^ + +warning: ExportNamespaceSpecifier + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:8 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:13 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^ + +warning: Str + --> $DIR/tests/span/js/decl/namespace-export-string-names.js:1:24 + | +1 | export * as "忠恕。" from "Confucius" + | ^^^^^^^^^^^ + diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/0557c70da3f698b5.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/0557c70da3f698b5.module.js.stderr index c3e4fc31e1a..1f282819250 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/0557c70da3f698b5.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/0557c70da3f698b5.module.js.stderr @@ -1,4 +1,4 @@ -error: Unexpected token `,`. Expected an identifier +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/0557c70da3f698b5.module.js:1:11 | 1 | import {b,,c} from 'a'; diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/455c19cd6608ab5d.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/455c19cd6608ab5d.module.js.stderr index c6af8303589..0d172f9b9ff 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/455c19cd6608ab5d.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/455c19cd6608ab5d.module.js.stderr @@ -1,4 +1,4 @@ -error: Expected ident +error: Unexpected token `}`. Expected identifier or string --> $DIR/tests/test262-parser/fail/455c19cd6608ab5d.module.js:1:13 | 1 | export {a as} from a diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/7222f595c694ef81.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/7222f595c694ef81.module.js.stderr index c1646d85a2a..d4c72b43b75 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/7222f595c694ef81.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/7222f595c694ef81.module.js.stderr @@ -1,4 +1,4 @@ -error: Expected ident +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/7222f595c694ef81.module.js:1:11 | 1 | export {a,,} diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/87d2d99776638ab6.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/87d2d99776638ab6.module.js.stderr index 096e45056e9..22c95a45ee9 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/87d2d99776638ab6.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/87d2d99776638ab6.module.js.stderr @@ -1,4 +1,4 @@ -error: Unexpected token `,`. Expected an identifier +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/87d2d99776638ab6.module.js:1:11 | 1 | import {b,,} from 'a'; diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/89ace2a47ff50b0d.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/89ace2a47ff50b0d.module.js.stderr index 2304523a767..39df317d125 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/89ace2a47ff50b0d.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/89ace2a47ff50b0d.module.js.stderr @@ -1,4 +1,4 @@ -error: Unexpected token `,`. Expected an identifier +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/89ace2a47ff50b0d.module.js:1:9 | 1 | import {,} from 'a'; diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/9f08fdb641588efc.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/9f08fdb641588efc.module.js.stderr index d0c6402d38a..f616a33b729 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/9f08fdb641588efc.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/9f08fdb641588efc.module.js.stderr @@ -1,4 +1,4 @@ -error: Unexpected token `,`. Expected an identifier +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/9f08fdb641588efc.module.js:1:13 | 1 | import {b,c,,} from 'a'; diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/b23c154206fb45fa.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/b23c154206fb45fa.module.js.stderr index f1d0384a405..5d464b0e0c4 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/b23c154206fb45fa.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/b23c154206fb45fa.module.js.stderr @@ -1,4 +1,4 @@ -error: Expected ident +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/b23c154206fb45fa.module.js:1:11 | 1 | export {a,,b} diff --git a/crates/swc_ecma_parser/tests/test262-error-references/fail/e07ef2bccb56a292.module.js.stderr b/crates/swc_ecma_parser/tests/test262-error-references/fail/e07ef2bccb56a292.module.js.stderr index f204398cd99..590907aaa59 100644 --- a/crates/swc_ecma_parser/tests/test262-error-references/fail/e07ef2bccb56a292.module.js.stderr +++ b/crates/swc_ecma_parser/tests/test262-error-references/fail/e07ef2bccb56a292.module.js.stderr @@ -1,4 +1,4 @@ -error: Expected ident +error: Unexpected token `,`. Expected identifier or string --> $DIR/tests/test262-parser/fail/e07ef2bccb56a292.module.js:1:9 | 1 | export {,,} diff --git a/crates/swc_ecma_parser/tests/typescript-errors/type-only-export-specifier/missing-local/input.ts.stderr b/crates/swc_ecma_parser/tests/typescript-errors/type-only-export-specifier/missing-local/input.ts.stderr index a3b8fd1b4fe..29aeb55a780 100644 --- a/crates/swc_ecma_parser/tests/typescript-errors/type-only-export-specifier/missing-local/input.ts.stderr +++ b/crates/swc_ecma_parser/tests/typescript-errors/type-only-export-specifier/missing-local/input.ts.stderr @@ -1,4 +1,4 @@ -error: Expected ident +error: Unexpected token `}`. Expected identifier or string --> $DIR/tests/typescript-errors/type-only-export-specifier/missing-local/input.ts:1:22 | 1 | export { type foo as }