Repository: swc-project/swc (rust)

Issue:
does not properly parse import clauses with assertions
### Describe the bug

swc indicates this is invalid syntax.  According to the [specification](https://tc39.es/proposal-import-assertions/#prod-ImportDeclaration) this is valid syntax:

> **import** _ModuleSpecifier_ [no _LineTerminator_ here] _AssertClause_ ;


### Input code

```typescript
import "./test.json" assert { type: "json" };
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true
    },
    "target": "es2021",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

https://play.swc.rs/?version=1.2.115&code=H4sIAAAAAAAAA8vMLcgvKlFQ0tMvSS0u0csqzs9TUkgsLk4FClYrlFQWpFopKEFEa625AO%2BrxKUuAAAA&config=H4sIAAAAAAAAA0WOSw7DIAxE7%2BJ1Fm0WXXCHHgIRJyIigGxHKkLcvYamym40n6epsLMDUyFbYqSuuESxHzAgJSM78llgAmG1hE6cYEGXyEoi%2FjlNU0sbim6Q58f81H5IiRHMagPr5PDRr6XTXToyIfMd2biFf7Mp60jL2Y06DgzmC9rNuHae31dxfPgCqp7SockAAAA%3D

### Expected behavior

This parses without issue.

### Actual behavior

It indicates the assert clause is unexpected.

### Version

1.2.115

### Additional context

_No response_

Pull request:
fix(es/parser): Support import assertions in specifier-less imports
swc_ecma_parser:

* Support import assertions in specifier-less imports.

swc_ecma_codegen:

* Add tests for codegen of import assertions in specifier-less imports.

swc_ecma_transforms_proposal:

* Add tests for stripping import assertions in specifier-less imports.

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

Specifier-less import assertions are not currently supported by the parser, even though the spec proposal allows them.

**BREAKING CHANGE:**
<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

None

**Related issue (if exists):**

Fixes #3103.


Patch:
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 8dc4b08a69..b400239fdd 100644
--- a/crates/swc_ecma_parser/src/parser/stmt/module_item.rs
+++ b/crates/swc_ecma_parser/src/parser/stmt/module_item.rs
@@ -65,13 +65,25 @@ impl<'a, I: Tokens> Parser<I> {
                 },
                 _ => unreachable!(),
             };
+            let _ = cur!(self, false);
+            let asserts = if self.input.syntax().import_assertions()
+                && !self.input.had_line_break_before_cur()
+                && eat!(self, "assert")
+            {
+                match *self.parse_object::<Box<Expr>>()? {
+                    Expr::Object(v) => Some(v),
+                    _ => unreachable!(),
+                }
+            } else {
+                None
+            };
             expect!(self, ';');
             return Ok(ModuleDecl::Import(ImportDecl {
                 span: span!(self, start),
                 src,
                 specifiers: vec![],
                 type_only: false,
-                asserts: None,
+                asserts,
             }))
             .map(ModuleItem::from);
         }


Test patch:
diff --git a/crates/swc_ecma_codegen/tests/fixture/issues/3110/input.js b/crates/swc_ecma_codegen/tests/fixture/issues/3110/input.js
index bcf5550b85..0d53b0fac7 100644
--- a/crates/swc_ecma_codegen/tests/fixture/issues/3110/input.js
+++ b/crates/swc_ecma_codegen/tests/fixture/issues/3110/input.js
@@ -1,5 +1,6 @@
 import data from "./data.json" assert { type: "json" };
-export { default as data2 } from "./data2.json" assert { type: "json" };
-export * as data3 from "./data3.json" assert { type: "json" };
+import "./data2.json" assert { type: "json" };
+export { default as data3 } from "./data3.json" assert { type: "json" };
+export * as data4 from "./data4.json" assert { type: "json" };
 
 console.log(data);
diff --git a/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.js b/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.js
index 626916ffe0..6d41a2485a 100644
--- a/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.js
+++ b/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.js
@@ -1,10 +1,13 @@
 import data from "./data.json" assert {
     type: "json"
 };
-export { default as data2 } from "./data2.json" assert {
+import "./data2.json" assert {
     type: "json"
 };
-export * as data3 from "./data3.json" assert {
+export { default as data3 } from "./data3.json" assert {
+    type: "json"
+};
+export * as data4 from "./data4.json" assert {
     type: "json"
 };
 console.log(data);
diff --git a/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.min.js b/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.min.js
index d663075624..b2b064f360 100644
--- a/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.min.js
+++ b/crates/swc_ecma_codegen/tests/fixture/issues/3110/output.min.js
@@ -1,1 +1,1 @@
-import data from"./data.json"assert{type:"json"};export{default as data2}from"./data2.json"assert{type:"json"};export*as data3 from"./data3.json"assert{type:"json"};console.log(data)
+import data from"./data.json"assert{type:"json"};import"./data2.json"assert{type:"json"};export{default as data3}from"./data3.json"assert{type:"json"};export*as data4 from"./data4.json"assert{type:"json"};console.log(data)
diff --git a/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts b/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts
new file mode 100644
index 0000000000..a5eeaaae69
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts
@@ -0,0 +1,1 @@
+import "./foo.json" assert { type: "json" };
diff --git a/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts.json b/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts.json
new file mode 100644
index 0000000000..2055b5ec96
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/typescript/import-assertions/stmt/test2/input.ts.json
@@ -0,0 +1,72 @@
+{
+  "type": "Module",
+  "span": {
+    "start": 0,
+    "end": 44,
+    "ctxt": 0
+  },
+  "body": [
+    {
+      "type": "ImportDeclaration",
+      "span": {
+        "start": 0,
+        "end": 44,
+        "ctxt": 0
+      },
+      "specifiers": [],
+      "source": {
+        "type": "StringLiteral",
+        "span": {
+          "start": 7,
+          "end": 19,
+          "ctxt": 0
+        },
+        "value": "./foo.json",
+        "hasEscape": false,
+        "kind": {
+          "type": "normal",
+          "containsQuote": true
+        }
+      },
+      "typeOnly": false,
+      "asserts": {
+        "type": "ObjectExpression",
+        "span": {
+          "start": 27,
+          "end": 43,
+          "ctxt": 0
+        },
+        "properties": [
+          {
+            "type": "KeyValueProperty",
+            "key": {
+              "type": "Identifier",
+              "span": {
+                "start": 29,
+                "end": 33,
+                "ctxt": 0
+              },
+              "value": "type",
+              "optional": false
+            },
+            "value": {
+              "type": "StringLiteral",
+              "span": {
+                "start": 35,
+                "end": 41,
+                "ctxt": 0
+              },
+              "value": "json",
+              "hasEscape": false,
+              "kind": {
+                "type": "normal",
+                "containsQuote": true
+              }
+            }
+          }
+        ]
+      }
+    }
+  ],
+  "interpreter": null
+}
diff --git a/crates/swc_ecma_transforms_proposal/tests/import_assertions.rs b/crates/swc_ecma_transforms_proposal/tests/import_assertions.rs
index 2756c4455a..e4165c0b35 100644
--- a/crates/swc_ecma_transforms_proposal/tests/import_assertions.rs
+++ b/crates/swc_ecma_transforms_proposal/tests/import_assertions.rs
@@ -22,6 +22,14 @@ test!(
     r#"import test from "./test.json";"#
 );
 
+test!(
+    syntax(),
+    |_| tr(),
+    side_effect_import_with_assertions,
+    r#"import "./test.json" assert {type: "json"};"#,
+    r#"import "./test.json";"#
+);
+
 test!(
     syntax(),
     |_| tr(),