Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the updated import attributes proposal #15536

Merged
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion Makefile.js

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions Makefile.source.mjs
Expand Up @@ -450,14 +450,16 @@ target["bootstrap-flow"] = function () {

target["new-version-checklist"] = function () {
// eslint-disable-next-line no-constant-condition
if (0) {
if (1) {
console.log(
`
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!! !!!!!!
!!!!!! Write any message that should !!!!!!
!!!!!! block the release here !!!!!!
!!!!!! Update the version in !!!!!!
!!!!!! packages/babel-plugin-syntax-import-attributes/src/index.ts
!!!!!! and !!!!!!
!!!!!! /Users/nic/Documents/dev/babel/babel/packages/babel-preset-env/src/available-plugins.ts#L159
!!!!!! !!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Expand Down
8 changes: 8 additions & 0 deletions babel.config.js
Expand Up @@ -236,6 +236,14 @@ module.exports = function (api) {
"flag-IS_STANDALONE",
],

[
pluginToggleBooleanFlag,
{
name: "process.env.IS_PUBLISH",
value: bool(process.env.IS_PUBLISH),
},
],

process.env.STRIP_BABEL_8_FLAG && [
pluginToggleBooleanFlag,
{
Expand Down
13 changes: 10 additions & 3 deletions packages/babel-core/src/parser/util/missing-plugin-helper.ts
Expand Up @@ -84,10 +84,10 @@ const pluginNameMap: Record<
url: "https://github.com/babel/babel/tree/main/packages/babel-preset-react",
},
},
importAssertions: {
importAttributes: {
syntax: {
name: "@babel/plugin-syntax-import-assertions",
url: "https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-import-assertions",
name: "@babel/plugin-syntax-import-attributes",
url: "https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-import-attributes",
},
},
pipelineOperator: {
Expand Down Expand Up @@ -207,6 +207,13 @@ if (!process.env.BABEL_8_BREAKING) {
url: "https://github.com/babel/babel/tree/main/packages/babel-plugin-proposal-export-namespace-from",
},
},
// Will be removed
importAssertions: {
syntax: {
name: "@babel/plugin-syntax-import-assertions",
url: "https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-import-assertions",
},
},
importMeta: {
syntax: {
name: "@babel/plugin-syntax-import-meta",
Expand Down
67 changes: 45 additions & 22 deletions packages/babel-generator/src/generators/modules.ts
Expand Up @@ -66,15 +66,48 @@ export function ExportNamespaceSpecifier(
this.print(node.exported, node);
}

export function _printAssertions(
let warningShown = false;

export function _printAttributes(
this: Printer,
node: Extract<t.Node, { assertions?: t.ImportAttribute[] }>,
node: Extract<t.Node, { attributes?: t.ImportAttribute[] }>,
) {
this.word("assert");
const { importAttributesKeyword } = this.format;
const { attributes, assertions } = node;

if (
attributes &&
!importAttributesKeyword &&
// In the production build only show the warning once.
// We want to show it per-usage locally for tests.
(!process.env.IS_PUBLISH || !warningShown)
) {
warningShown = true;
console.warn(`\
You are using import attributes, without specifying the desired output syntax.
Please specify the "importAttributesKeyword" generator option, whose value can be one of:
- "with" : \`import { a } from "b" with { type: "json" };\`
- "assert" : \`import { a } from "b" assert { type: "json" };\`
- "with-legacy" : \`import { a } from "b" with type: "json";\`
`);
}

const useAssertKeyword =
importAttributesKeyword === "assert" ||
(!importAttributesKeyword && assertions);

this.word(useAssertKeyword ? "assert" : "with");
this.space();

if (!useAssertKeyword && importAttributesKeyword !== "with") {
// with-legacy
this.printList(attributes || assertions, node);
return;
}

this.token("{");
this.space();
this.printList(node.assertions, node);
this.printList(attributes || assertions, node);
this.space();
this.token("}");
}
Expand All @@ -93,12 +126,12 @@ export function ExportAllDeclaration(
this.space();
this.word("from");
this.space();
// @ts-expect-error Fixme: assertions is not defined in DeclareExportAllDeclaration
if (node.assertions?.length) {
// @ts-expect-error Fixme: attributes is not defined in DeclareExportAllDeclaration
if (node.attributes?.length || node.assertions?.length) {
this.print(node.source, node, true);
this.space();
// @ts-expect-error Fixme: assertions is not defined in DeclareExportAllDeclaration
this._printAssertions(node);
// @ts-expect-error Fixme: attributes is not defined in DeclareExportAllDeclaration
this._printAttributes(node);
} else {
this.print(node.source, node);
}
Expand Down Expand Up @@ -173,10 +206,10 @@ export function ExportNamedDeclaration(
this.space();
this.word("from");
this.space();
if (node.assertions?.length) {
if (node.attributes?.length || node.assertions?.length) {
this.print(node.source, node, true);
this.space();
this._printAssertions(node);
this._printAttributes(node);
} else {
this.print(node.source, node);
}
Expand Down Expand Up @@ -251,23 +284,13 @@ export function ImportDeclaration(this: Printer, node: t.ImportDeclaration) {
this.space();
}

if (node.assertions?.length) {
if (node.attributes?.length || node.assertions?.length) {
this.print(node.source, node, true);
this.space();
this._printAssertions(node);
this._printAttributes(node);
} else {
this.print(node.source, node);
}
if (!process.env.BABEL_8_BREAKING) {
// @ts-ignore(Babel 7 vs Babel 8) Babel 7 supports module attributes
if (node.attributes?.length) {
this.space();
this.word("with");
this.space();
// @ts-ignore(Babel 7 vs Babel 8) Babel 7 supports module attributes
this.printList(node.attributes, node);
}
}

this.semicolon();
}
Expand Down
10 changes: 10 additions & 0 deletions packages/babel-generator/src/index.ts
Expand Up @@ -73,6 +73,7 @@ function normalizeOptions(
},
recordAndTupleSyntaxType: opts.recordAndTupleSyntaxType,
topicToken: opts.topicToken,
importAttributesKeyword: opts.importAttributesKeyword,
};

if (!process.env.BABEL_8_BREAKING) {
Expand Down Expand Up @@ -218,11 +219,20 @@ export interface GeneratorOptions {
* For use with the recordAndTuple token.
*/
recordAndTupleSyntaxType?: RecordAndTuplePluginOptions["syntaxType"];

/**
* For use with the Hack-style pipe operator.
* Changes what token is used for pipe bodies’ topic references.
*/
topicToken?: PipelineOperatorPluginOptions["topicToken"];

/**
* The import attributes syntax style:
* - "with" : `import { a } from "b" with { type: "json" };`
* - "assert" : `import { a } from "b" assert { type: "json" };`
* - "with-legacy" : `import { a } from "b" with type: "json";`
*/
importAttributesKeyword?: "with" | "assert" | "with-legacy";
}

export interface GeneratorResult {
Expand Down
11 changes: 10 additions & 1 deletion packages/babel-generator/src/printer.ts
Expand Up @@ -18,7 +18,7 @@ import type { Opts as jsescOptions } from "jsesc";
import * as generatorFunctions from "./generators";
import type SourceMap from "./source-map";
import * as charCodes from "charcodes";
import { type TraceMap } from "@jridgewell/trace-mapping";
import type { TraceMap } from "@jridgewell/trace-mapping";

const SCIENTIFIC_NOTATION = /e/i;
const ZERO_DECIMAL_INTEGER = /\.0+$/;
Expand Down Expand Up @@ -77,6 +77,15 @@ export type Format = {
* @deprecated Removed in Babel 8
*/
decoratorsBeforeExport?: boolean;
/**
* The import attributes syntax style:
* - "with" : `import { a } from "b" with { type: "json" };`
* - "assert" : `import { a } from "b" assert { type: "json" };`
* - "with-legacy" : `import { a } from "b" with type: "json";`
* - "auto-legacy" : "assert" if the AST node has an .assertions property,
* "with-legacy" if it has an .attributes property.
nicolo-ribaudo marked this conversation as resolved.
Show resolved Hide resolved
*/
importAttributesKeyword?: "with" | "assert" | "with-legacy";
};

interface AddNewlinesOptions {
Expand Down
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "assert"
}
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,3 @@
{
"plugins": ["importAssertions"]
}
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "with-legacy",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "with"
}
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "assert"
}
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAssertions"],
"warns": "You are using import attributes, without specifying the desired output syntax.",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "with-legacy",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": ["importAssertions"],
"importAttributesKeyword": "with"
}
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": [["importAttributes", { "deprecatedAssertSyntax": true }]],
"importAttributesKeyword": "assert"
}
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": [["importAttributes", { "deprecatedAssertSyntax": true }]],
"warns": "You are using import attributes, without specifying the desired output syntax.",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": [["importAttributes", { "deprecatedAssertSyntax": true }]],
"importAttributesKeyword": "with-legacy",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": [["importAttributes", { "deprecatedAssertSyntax": true }]],
"importAttributesKeyword": "with"
}
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAttributes"],
"importAttributesKeyword": "assert",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" assert { type: "json" };
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAttributes"],
"warns": "You are using import attributes, without specifying the desired output syntax.",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,5 @@
{
"plugins": ["importAttributes"],
"importAttributesKeyword": "with-legacy",
"expectedReParseError": true
}
@@ -0,0 +1 @@
import "a" with type: "json";
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1,4 @@
{
"plugins": ["importAttributes"],
"importAttributesKeyword": "with"
}
@@ -0,0 +1 @@
import "a" with { type: "json" };
@@ -0,0 +1 @@
import "a" with type: "json";