diff --git a/changelog_unreleased/javascript/14863.md b/changelog_unreleased/javascript/14863.md new file mode 100644 index 000000000..e53a682ae --- /dev/null +++ b/changelog_unreleased/javascript/14863.md @@ -0,0 +1,9 @@ +#### Support Import Attributes (#14861, #14863 by @sosukesuzuki) + +Support [Import Attributes](https://github.com/tc39/proposal-import-attributes) proposal. + + +```jsx +import json from "./foo.json" with { type: "json" }; +import("./foo.json", { with: { type: "json" } }); +``` diff --git a/package.json b/package.json index a73a07289..d9b4b686f 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "dependencies": { "@angular/compiler": "16.0.3", "@babel/code-frame": "7.21.4", - "@babel/parser": "7.22.3", - "@babel/types": "7.22.3", + "@babel/parser": "7.22.4", + "@babel/types": "7.22.4", "@glimmer/syntax": "0.84.3", "@iarna/toml": "2.2.5", "@prettier/is-es5-identifier-name": "0.1.0", diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index 8f2efee10..be2e6bf3e 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -36,7 +36,6 @@ const parseOptions = { "throwExpressions", "partialApplication", "decorators", - "importAssertions", "decimal", "moduleBlocks", "asyncDoExpressions", @@ -45,6 +44,7 @@ const parseOptions = { "decoratorAutoAccessors", "importReflection", "explicitResourceManagement", + ["importAttributes", { deprecatedAssertSyntax: true }], ], tokens: true, ranges: true, @@ -62,6 +62,7 @@ const pipelineOperatorPlugins = [ ["pipelineOperator", { proposal: "minimal" }], ["pipelineOperator", { proposal: "fsharp" }], ]; + const appendPlugins = (plugins, options = parseOptions) => ({ ...options, plugins: [...options.plugins, ...plugins], diff --git a/src/language-js/print/module.js b/src/language-js/print/module.js index d6feb2cd6..e76cc2d1a 100644 --- a/src/language-js/print/module.js +++ b/src/language-js/print/module.js @@ -37,7 +37,7 @@ function printImportDeclaration(path, options, print) { printImportKind(node), printModuleSpecifiers(path, options, print), printModuleSource(path, options, print), - printImportAssertions(path, options, print), + printImportAttributes(path, options, print), options.semi ? ";" : "", ]; } @@ -93,7 +93,7 @@ function printExportDeclaration(path, options, print) { parts.push( printModuleSource(path, options, print), - printImportAssertions(path, options, print) + printImportAttributes(path, options, print) ); } @@ -246,16 +246,31 @@ function shouldNotPrintSpecifiers(node, options) { ); } -function printImportAssertions(path, options, print) { +/** + * Print Import Attributes syntax. + * If old ImportAssertions syntax is used, print them here. + */ +function printImportAttributes(path, options, print) { const { node } = path; - if (!isNonEmptyArray(node.assertions)) { + + const property = isNonEmptyArray(node.attributes) + ? "attributes" + : isNonEmptyArray(node.assertions) + ? "assertions" + : undefined; + + if (!property) { return ""; } + const keyword = + property === "assertions" || node.extra?.deprecatedAssertSyntax + ? "assert" + : "with"; return [ - " assert {", + ` ${keyword} {`, options.bracketSpacing ? " " : "", - join(", ", path.map(print, "assertions")), + join(", ", path.map(print, property)), options.bracketSpacing ? " " : "", "}", ]; diff --git a/tests/format/js/babel-plugins/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/babel-plugins/__snapshots__/jsfmt.spec.js.snap index 1cb76a765..e9a270e44 100644 --- a/tests/format/js/babel-plugins/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/babel-plugins/__snapshots__/jsfmt.spec.js.snap @@ -1239,6 +1239,76 @@ import json from "./foo.json" assert { type: "json" }; ================================================================================ `; +exports[`import-attributes-dynamic.js [acorn] format 1`] = ` +"Unexpected token (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`import-attributes-dynamic.js [espree] format 1`] = ` +"Unexpected token , (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`import-attributes-dynamic.js [meriyah] format 1`] = ` +"Expected ')' (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`import-attributes-dynamic.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "babel-ts", "babel-flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +import("./foo.json", { with: { type: "json" } }); + +=====================================output===================================== +import("./foo.json", { with: { type: "json" } }); + +================================================================================ +`; + +exports[`import-attributes-static.js [acorn] format 1`] = ` +"Unexpected token (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`import-attributes-static.js [espree] format 1`] = ` +"Unexpected token with (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`import-attributes-static.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:34) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`import-attributes-static.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "babel-ts", "babel-flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +import json from "./foo.json" with { type: "json" }; + +=====================================output===================================== +import json from "./foo.json" with { type: "json" }; + +================================================================================ +`; + exports[`import-meta.js format 1`] = ` ====================================options===================================== parsers: ["babel", "babel-ts", "babel-flow"] diff --git a/tests/format/js/babel-plugins/import-attributes-dynamic.js b/tests/format/js/babel-plugins/import-attributes-dynamic.js new file mode 100644 index 000000000..717b72d4a --- /dev/null +++ b/tests/format/js/babel-plugins/import-attributes-dynamic.js @@ -0,0 +1 @@ +import("./foo.json", { with: { type: "json" } }); diff --git a/tests/format/js/babel-plugins/import-attributes-static.js b/tests/format/js/babel-plugins/import-attributes-static.js new file mode 100644 index 000000000..7770ae1f0 --- /dev/null +++ b/tests/format/js/babel-plugins/import-attributes-static.js @@ -0,0 +1 @@ +import json from "./foo.json" with { type: "json" }; diff --git a/tests/format/js/babel-plugins/jsfmt.spec.js b/tests/format/js/babel-plugins/jsfmt.spec.js index c4227da02..2d63adff2 100644 --- a/tests/format/js/babel-plugins/jsfmt.spec.js +++ b/tests/format/js/babel-plugins/jsfmt.spec.js @@ -14,6 +14,8 @@ run_spec(import.meta, ["babel", "babel-ts", "babel-flow"], { "function-sent.js", "import-assertions-dynamic.js", "import-assertions-static.js", + "import-attributes-dynamic.js", + "import-attributes-static.js", "partial-application.js", "pipeline-operator-fsharp.js", "pipeline-operator-minimal.js", @@ -42,6 +44,8 @@ run_spec(import.meta, ["babel", "babel-ts", "babel-flow"], { "function-sent.js", "import-assertions-dynamic.js", "import-assertions-static.js", + "import-attributes-dynamic.js", + "import-attributes-static.js", "partial-application.js", "pipeline-operator-fsharp.js", "pipeline-operator-minimal.js", @@ -80,6 +84,8 @@ run_spec(import.meta, ["babel", "babel-ts", "babel-flow"], { "v8intrinsic.js", "import-assertions-dynamic.js", "import-assertions-static.js", + "import-attributes-dynamic.js", + "import-attributes-static.js", "module-string-names.js", "module-blocks.js", "async-do-expressions.js", diff --git a/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..08fa4fda4 --- /dev/null +++ b/tests/format/js/import-attributes/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,324 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`dynamic-import.js [acorn] format 1`] = ` +"Unexpected token (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js [espree] format 1`] = ` +"Unexpected token , (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js [meriyah] format 1`] = ` +"Expected ')' (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import("./foo.json", { with: { type: "json" } }); + +=====================================output===================================== +import("./foo.json", { with: { type: "json" } }); + +================================================================================ +`; + +exports[`empty.js [acorn] format 1`] = ` +"Unexpected token (2:33) + 1 | export * as foo from "foo.json" +> 2 | export * as bar from "bar.json" with { } + | ^ + 3 | export * as baz from "baz.json" with { /* comment */ } + 4 | + 5 | import * as foo from "foo.json"" +`; + +exports[`empty.js [espree] format 1`] = ` +"Unexpected token with (2:33) + 1 | export * as foo from "foo.json" +> 2 | export * as bar from "bar.json" with { } + | ^ + 3 | export * as baz from "baz.json" with { /* comment */ } + 4 | + 5 | import * as foo from "foo.json"" +`; + +exports[`empty.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (2:36) + 1 | export * as foo from "foo.json" +> 2 | export * as bar from "bar.json" with { } + | ^ + 3 | export * as baz from "baz.json" with { /* comment */ } + 4 | + 5 | import * as foo from "foo.json"" +`; + +exports[`empty.js [typescript] format 1`] = ` +"';' expected. (2:33) + 1 | export * as foo from "foo.json" +> 2 | export * as bar from "bar.json" with { } + | ^ + 3 | export * as baz from "baz.json" with { /* comment */ } + 4 | + 5 | import * as foo from "foo.json"" +`; + +exports[`empty.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +export * as foo from "foo.json" +export * as bar from "bar.json" with { } +export * as baz from "baz.json" with { /* comment */ } + +import * as foo from "foo.json" +import * as bar from "bar.json" with { } +import * as baz from "baz.json" with { /* comment */ } + +=====================================output===================================== +export * as foo from "foo.json"; +export * as bar from "bar.json"; +export * as baz from "baz.json" /* comment */; + +import * as foo from "foo.json"; +import * as bar from "bar.json"; +import * as baz from "baz.json" /* comment */; + +================================================================================ +`; + +exports[`multi-types.js [acorn] format 1`] = ` +"Unexpected token (1:31) +> 1 | import json from "./foo.json" with { type: "json", type: "bar" }; + | ^ + 2 |" +`; + +exports[`multi-types.js [espree] format 1`] = ` +"Unexpected token with (1:31) +> 1 | import json from "./foo.json" with { type: "json", type: "bar" }; + | ^ + 2 |" +`; + +exports[`multi-types.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:34) +> 1 | import json from "./foo.json" with { type: "json", type: "bar" }; + | ^ + 2 |" +`; + +exports[`multi-types.js [typescript] format 1`] = ` +"';' expected. (1:31) +> 1 | import json from "./foo.json" with { type: "json", type: "bar" }; + | ^ + 2 |" +`; + +exports[`multi-types.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import json from "./foo.json" with { type: "json", type: "bar" }; + +=====================================output===================================== +import json from "./foo.json" with { type: "json", type: "bar" }; + +================================================================================ +`; + +exports[`non-type.js [acorn] format 1`] = ` +"Unexpected token (1:28) +> 1 | import foo from "foo.json" with { lazy: "true" }; + | ^ + 2 |" +`; + +exports[`non-type.js [espree] format 1`] = ` +"Unexpected token with (1:28) +> 1 | import foo from "foo.json" with { lazy: "true" }; + | ^ + 2 |" +`; + +exports[`non-type.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:31) +> 1 | import foo from "foo.json" with { lazy: "true" }; + | ^ + 2 |" +`; + +exports[`non-type.js [typescript] format 1`] = ` +"';' expected. (1:28) +> 1 | import foo from "foo.json" with { lazy: "true" }; + | ^ + 2 |" +`; + +exports[`non-type.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import foo from "foo.json" with { lazy: "true" }; + +=====================================output===================================== +import foo from "foo.json" with { lazy: "true" }; + +================================================================================ +`; + +exports[`re-export.js [acorn] format 1`] = ` +"Unexpected token (1:44) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 | export * from "foo.json" with { type: "json" }; + 3 | export * as foo3 from "foo.json" with { type: "json" }; + 4 |" +`; + +exports[`re-export.js [espree] format 1`] = ` +"Unexpected token with (1:44) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 | export * from "foo.json" with { type: "json" }; + 3 | export * as foo3 from "foo.json" with { type: "json" }; + 4 |" +`; + +exports[`re-export.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:47) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 | export * from "foo.json" with { type: "json" }; + 3 | export * as foo3 from "foo.json" with { type: "json" }; + 4 |" +`; + +exports[`re-export.js [typescript] format 1`] = ` +"';' expected. (1:44) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 | export * from "foo.json" with { type: "json" }; + 3 | export * as foo3 from "foo.json" with { type: "json" }; + 4 |" +`; + +exports[`re-export.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +export { default as foo2 } from "foo.json" with { type: "json" }; +export * from "foo.json" with { type: "json" }; +export * as foo3 from "foo.json" with { type: "json" }; + +=====================================output===================================== +export { default as foo2 } from "foo.json" with { type: "json" }; +export * from "foo.json" with { type: "json" }; +export * as foo3 from "foo.json" with { type: "json" }; + +================================================================================ +`; + +exports[`static-import.js [acorn] format 1`] = ` +"Unexpected token (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js [espree] format 1`] = ` +"Unexpected token with (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:34) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js [typescript] format 1`] = ` +"';' expected. (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import json from "./foo.json" with { type: "json" }; + +=====================================output===================================== +import json from "./foo.json" with { type: "json" }; + +================================================================================ +`; + +exports[`without-from.js [acorn] format 1`] = ` +"Unexpected token (1:14) +> 1 | import "foo" with { type: "json" } + | ^ + 2 |" +`; + +exports[`without-from.js [espree] format 1`] = ` +"Unexpected token with (1:14) +> 1 | import "foo" with { type: "json" } + | ^ + 2 |" +`; + +exports[`without-from.js [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:17) +> 1 | import "foo" with { type: "json" } + | ^ + 2 |" +`; + +exports[`without-from.js [typescript] format 1`] = ` +"';' expected. (1:14) +> 1 | import "foo" with { type: "json" } + | ^ + 2 |" +`; + +exports[`without-from.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import "foo" with { type: "json" } + +=====================================output===================================== +import "foo" with { type: "json" }; + +================================================================================ +`; diff --git a/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..828d539d1 --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,141 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`dynamic-import.js - {"bracketSpacing":false} [acorn] format 1`] = ` +"Unexpected token (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js - {"bracketSpacing":false} [espree] format 1`] = ` +"Unexpected token , (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js - {"bracketSpacing":false} [meriyah] format 1`] = ` +"Expected ')' (1:20) +> 1 | import("./foo.json", { with: { type: "json" } }); + | ^ + 2 |" +`; + +exports[`dynamic-import.js - {"bracketSpacing":false} format 1`] = ` +====================================options===================================== +bracketSpacing: false +parsers: ["babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +import("./foo.json", { with: { type: "json" } }); + +=====================================output===================================== +import("./foo.json", {with: {type: "json"}}); + +================================================================================ +`; + +exports[`empty.js - {"bracketSpacing":false} [acorn] format 1`] = ` +"Unexpected token (1:33) +> 1 | export * as bar from "bar.json" with { } + | ^" +`; + +exports[`empty.js - {"bracketSpacing":false} [espree] format 1`] = ` +"Unexpected token with (1:33) +> 1 | export * as bar from "bar.json" with { } + | ^" +`; + +exports[`empty.js - {"bracketSpacing":false} [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:36) +> 1 | export * as bar from "bar.json" with { } + | ^" +`; + +exports[`empty.js - {"bracketSpacing":false} format 1`] = ` +====================================options===================================== +bracketSpacing: false +parsers: ["babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +export * as bar from "bar.json" with { } +=====================================output===================================== +export * as bar from "bar.json"; + +================================================================================ +`; + +exports[`re-export.js - {"bracketSpacing":false} [acorn] format 1`] = ` +"Unexpected token (1:44) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`re-export.js - {"bracketSpacing":false} [espree] format 1`] = ` +"Unexpected token with (1:44) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`re-export.js - {"bracketSpacing":false} [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:47) +> 1 | export { default as foo2 } from "foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`re-export.js - {"bracketSpacing":false} format 1`] = ` +====================================options===================================== +bracketSpacing: false +parsers: ["babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +export { default as foo2 } from "foo.json" with { type: "json" }; + +=====================================output===================================== +export {default as foo2} from "foo.json" with {type: "json"}; + +================================================================================ +`; + +exports[`static-import.js - {"bracketSpacing":false} [acorn] format 1`] = ` +"Unexpected token (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js - {"bracketSpacing":false} [espree] format 1`] = ` +"Unexpected token with (1:31) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js - {"bracketSpacing":false} [meriyah] format 1`] = ` +"Unexpected token: 'with' (1:34) +> 1 | import json from "./foo.json" with { type: "json" }; + | ^ + 2 |" +`; + +exports[`static-import.js - {"bracketSpacing":false} format 1`] = ` +====================================options===================================== +bracketSpacing: false +parsers: ["babel"] +printWidth: 80 + | printWidth +=====================================input====================================== +import json from "./foo.json" with { type: "json" }; + +=====================================output===================================== +import json from "./foo.json" with {type: "json"}; + +================================================================================ +`; diff --git a/tests/format/js/import-attributes/bracket-spacing/dynamic-import.js b/tests/format/js/import-attributes/bracket-spacing/dynamic-import.js new file mode 100644 index 000000000..717b72d4a --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/dynamic-import.js @@ -0,0 +1 @@ +import("./foo.json", { with: { type: "json" } }); diff --git a/tests/format/js/import-attributes/bracket-spacing/empty.js b/tests/format/js/import-attributes/bracket-spacing/empty.js new file mode 100644 index 000000000..22cfde938 --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/empty.js @@ -0,0 +1 @@ +export * as bar from "bar.json" with { } \ No newline at end of file diff --git a/tests/format/js/import-attributes/bracket-spacing/jsfmt.spec.js b/tests/format/js/import-attributes/bracket-spacing/jsfmt.spec.js new file mode 100644 index 000000000..404ff2cc7 --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/jsfmt.spec.js @@ -0,0 +1,23 @@ +run_spec(import.meta, ["babel"], { + bracketSpacing: false, + errors: { + acorn: [ + "dynamic-import.js", + "static-import.js", + "re-export.js", + "empty.js", + ], + espree: [ + "dynamic-import.js", + "static-import.js", + "re-export.js", + "empty.js", + ], + meriyah: [ + "dynamic-import.js", + "static-import.js", + "re-export.js", + "empty.js", + ], + }, +}); diff --git a/tests/format/js/import-attributes/bracket-spacing/re-export.js b/tests/format/js/import-attributes/bracket-spacing/re-export.js new file mode 100644 index 000000000..12b98b761 --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/re-export.js @@ -0,0 +1 @@ +export { default as foo2 } from "foo.json" with { type: "json" }; diff --git a/tests/format/js/import-attributes/bracket-spacing/static-import.js b/tests/format/js/import-attributes/bracket-spacing/static-import.js new file mode 100644 index 000000000..7770ae1f0 --- /dev/null +++ b/tests/format/js/import-attributes/bracket-spacing/static-import.js @@ -0,0 +1 @@ +import json from "./foo.json" with { type: "json" }; diff --git a/tests/format/js/import-attributes/dynamic-import.js b/tests/format/js/import-attributes/dynamic-import.js new file mode 100644 index 000000000..717b72d4a --- /dev/null +++ b/tests/format/js/import-attributes/dynamic-import.js @@ -0,0 +1 @@ +import("./foo.json", { with: { type: "json" } }); diff --git a/tests/format/js/import-attributes/empty.js b/tests/format/js/import-attributes/empty.js new file mode 100644 index 000000000..ab1ee6f33 --- /dev/null +++ b/tests/format/js/import-attributes/empty.js @@ -0,0 +1,7 @@ +export * as foo from "foo.json" +export * as bar from "bar.json" with { } +export * as baz from "baz.json" with { /* comment */ } + +import * as foo from "foo.json" +import * as bar from "bar.json" with { } +import * as baz from "baz.json" with { /* comment */ } diff --git a/tests/format/js/import-attributes/jsfmt.spec.js b/tests/format/js/import-attributes/jsfmt.spec.js new file mode 100644 index 000000000..168477a66 --- /dev/null +++ b/tests/format/js/import-attributes/jsfmt.spec.js @@ -0,0 +1,39 @@ +run_spec(import.meta, ["babel", "typescript"], { + errors: { + acorn: [ + "dynamic-import.js", + "empty.js", + "multi-types.js", + "static-import.js", + "re-export.js", + "without-from.js", + "non-type.js", + ], + espree: [ + "dynamic-import.js", + "empty.js", + "multi-types.js", + "static-import.js", + "re-export.js", + "without-from.js", + "non-type.js", + ], + meriyah: [ + "dynamic-import.js", + "empty.js", + "multi-types.js", + "static-import.js", + "re-export.js", + "without-from.js", + "non-type.js", + ], + typescript: [ + "empty.js", + "multi-types.js", + "static-import.js", + "re-export.js", + "without-from.js", + "non-type.js", + ], + }, +}); diff --git a/tests/format/js/import-attributes/multi-types.js b/tests/format/js/import-attributes/multi-types.js new file mode 100644 index 000000000..0f0e7115f --- /dev/null +++ b/tests/format/js/import-attributes/multi-types.js @@ -0,0 +1 @@ +import json from "./foo.json" with { type: "json", type: "bar" }; diff --git a/tests/format/js/import-attributes/non-type.js b/tests/format/js/import-attributes/non-type.js new file mode 100644 index 000000000..1858e49c2 --- /dev/null +++ b/tests/format/js/import-attributes/non-type.js @@ -0,0 +1 @@ +import foo from "foo.json" with { lazy: "true" }; diff --git a/tests/format/js/import-attributes/re-export.js b/tests/format/js/import-attributes/re-export.js new file mode 100644 index 000000000..8b7f8a817 --- /dev/null +++ b/tests/format/js/import-attributes/re-export.js @@ -0,0 +1,3 @@ +export { default as foo2 } from "foo.json" with { type: "json" }; +export * from "foo.json" with { type: "json" }; +export * as foo3 from "foo.json" with { type: "json" }; diff --git a/tests/format/js/import-attributes/static-import.js b/tests/format/js/import-attributes/static-import.js new file mode 100644 index 000000000..7770ae1f0 --- /dev/null +++ b/tests/format/js/import-attributes/static-import.js @@ -0,0 +1 @@ +import json from "./foo.json" with { type: "json" }; diff --git a/tests/format/js/import-attributes/without-from.js b/tests/format/js/import-attributes/without-from.js new file mode 100644 index 000000000..5009c441a --- /dev/null +++ b/tests/format/js/import-attributes/without-from.js @@ -0,0 +1 @@ +import "foo" with { type: "json" } diff --git a/tests/format/misc/errors/js/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/__snapshots__/jsfmt.spec.js.snap index b516876a8..0716d16c6 100644 --- a/tests/format/misc/errors/js/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/__snapshots__/jsfmt.spec.js.snap @@ -25,6 +25,20 @@ exports[`import-assertions-with-parens.js [babel] format 1`] = ` 2 |" `; +exports[`import-attributes-for-export-without-from.js [babel] format 1`] = ` +"Unexpected token, expected "(" (1:32) +> 1 | export { default as foo } with { type: "json" }; + | ^ + 2 |" +`; + +exports[`import-attributes-with-parens.js [babel] format 1`] = ` +"Unexpected token, expected "{" (1:17) +> 1 | import "x" with ({type: 'json'}); + | ^ + 2 |" +`; + exports[`invalid-escape-in-identifier.js [babel] format 1`] = ` "Invalid Unicode escape. (1:7) > 1 | const \\u{20} = 1 diff --git a/tests/format/misc/errors/js/import-assertions/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/import-assertions/__snapshots__/jsfmt.spec.js.snap index 67a088742..2d4b1f73a 100644 --- a/tests/format/misc/errors/js/import-assertions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/import-assertions/__snapshots__/jsfmt.spec.js.snap @@ -1,12 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`invalid-assertions.mjs [babel] format 1`] = ` -"\`import module x\` cannot have assertions. (1:15) -> 1 | import module foo from "./module.json" assert { type: "json" } - | ^ - 2 |" -`; - exports[`invalid-default-named-import.mjs [babel] format 1`] = ` "Only \`import module x from "./module"\` is valid. (1:15) > 1 | import module foo, {bar} from "./module.wasm"; diff --git a/tests/format/misc/errors/js/import-assertions/invalid-assertions.mjs b/tests/format/misc/errors/js/import-assertions/invalid-assertions.mjs deleted file mode 100644 index 3db160892..000000000 --- a/tests/format/misc/errors/js/import-assertions/invalid-assertions.mjs +++ /dev/null @@ -1 +0,0 @@ -import module foo from "./module.json" assert { type: "json" } diff --git a/tests/format/misc/errors/js/import-attributes-for-export-without-from.js b/tests/format/misc/errors/js/import-attributes-for-export-without-from.js new file mode 100644 index 000000000..460c24e86 --- /dev/null +++ b/tests/format/misc/errors/js/import-attributes-for-export-without-from.js @@ -0,0 +1 @@ +export { default as foo } with { type: "json" }; diff --git a/tests/format/misc/errors/js/import-attributes-with-parens.js b/tests/format/misc/errors/js/import-attributes-with-parens.js new file mode 100644 index 000000000..74567fa36 --- /dev/null +++ b/tests/format/misc/errors/js/import-attributes-with-parens.js @@ -0,0 +1 @@ +import "x" with ({type: 'json'}); diff --git a/tests/unit/__snapshots__/visitor-keys.js.snap b/tests/unit/__snapshots__/visitor-keys.js.snap index 9fd2234a1..8264e2829 100644 --- a/tests/unit/__snapshots__/visitor-keys.js.snap +++ b/tests/unit/__snapshots__/visitor-keys.js.snap @@ -263,8 +263,9 @@ exports[`visitor keys estree 1`] = ` ], "ExportAllDeclaration": [ "source", - "exported", + "attributes", "assertions", + "exported", ], "ExportDefaultDeclaration": [ "declaration", @@ -276,6 +277,7 @@ exports[`visitor keys estree 1`] = ` "declaration", "specifiers", "source", + "attributes", "assertions", ], "ExportNamespaceSpecifier": [ @@ -354,6 +356,7 @@ exports[`visitor keys estree 1`] = ` "ImportDeclaration": [ "specifiers", "source", + "attributes", "assertions", ], "ImportDefaultSpecifier": [ diff --git a/yarn.lock b/yarn.lock index 1477b6b8e..0e83723a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -230,12 +230,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:7.22.3, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.5, @babel/parser@npm:^7.21.8": - version: 7.22.3 - resolution: "@babel/parser@npm:7.22.3" +"@babel/parser@npm:7.22.4, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.5, @babel/parser@npm:^7.21.8": + version: 7.22.4 + resolution: "@babel/parser@npm:7.22.4" bin: parser: ./bin/babel-parser.js - checksum: 016f2960212fd86817e15d90b9b3450d2b51af189b1c17a20ade5735d9ec69e76e29def317e09188ecd5fa6eab4f9ab72d88b8b829c1b2994400a6a2c2dc1958 + checksum: 0ca6d3a2d9aae2504ba1bc494704b64a83140884f7379f609de69bd39b60adb58a4f8ec692fe53fef8657dd82705d01b7e6efb65e18296326bdd66f71d52d9a9 languageName: node linkType: hard @@ -422,14 +422,14 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:7.22.3, @babel/types@npm:^7.0.0, @babel/types@npm:^7.18.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.0, @babel/types@npm:^7.21.4, @babel/types@npm:^7.21.5, @babel/types@npm:^7.22.3, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": - version: 7.22.3 - resolution: "@babel/types@npm:7.22.3" +"@babel/types@npm:7.22.4, @babel/types@npm:^7.0.0, @babel/types@npm:^7.18.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.0, @babel/types@npm:^7.21.4, @babel/types@npm:^7.21.5, @babel/types@npm:^7.22.3, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": + version: 7.22.4 + resolution: "@babel/types@npm:7.22.4" dependencies: "@babel/helper-string-parser": ^7.21.5 "@babel/helper-validator-identifier": ^7.19.1 to-fast-properties: ^2.0.0 - checksum: 6111fa5990635dfba8812a84bb4889429feb41a2c03c89de2654724e88a85b5740d4795c64a480d188d2f7109e7b47f3f0ba3d56da1b697cd31c65922f4decf7 + checksum: ffe36bb4f4a99ad13c426a98c3b508d70736036cae4e471d9c862e3a579847ed4f480686af0fce2633f6f7c0f0d3bf02da73da36e7edd3fde0b2061951dcba9a languageName: node linkType: hard @@ -6784,8 +6784,8 @@ __metadata: "@angular/compiler": 16.0.3 "@babel/code-frame": 7.21.4 "@babel/generator": 7.22.3 - "@babel/parser": 7.22.3 - "@babel/types": 7.22.3 + "@babel/parser": 7.22.4 + "@babel/types": 7.22.4 "@esbuild-plugins/node-modules-polyfill": 0.2.2 "@glimmer/reference": 0.84.3 "@glimmer/syntax": 0.84.3