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

[babel 8] Remove support for the 2018-09 decorators proposal #12712

Merged
merged 10 commits into from Jun 26, 2022
Expand Up @@ -2,5 +2,5 @@

module.exports = {
presets: [["@babel/preset-env", { forceAllTransforms: true }]],
plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
plugins: [["@babel/plugin-proposal-decorators", { version: "legacy" }]],
};
2 changes: 1 addition & 1 deletion eslint/babel-eslint-shared-fixtures/config/babel.config.js
Expand Up @@ -9,7 +9,7 @@ module.exports = {
plugins: [
"@babel/plugin-syntax-export-default-from",
"@babel/plugin-proposal-class-properties",
["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: false }],
["@babel/plugin-proposal-decorators", { version: "2021-12" }],
["@babel/plugin-proposal-pipeline-operator", { proposal: "minimal" }],
"@babel/plugin-proposal-private-methods",
"@babel/plugin-proposal-do-expressions",
Expand Down
Expand Up @@ -16,7 +16,7 @@ exports.default = function () {
[
__dirname +
"/../../../../../babel-plugin-syntax-decorators/lib/index.js",
{ legacy: true },
{ version: "legacy" },
],
],
};
Expand Down
Expand Up @@ -11,7 +11,7 @@ module.exports = function () {
[
__dirname +
"/../../../../../babel-plugin-syntax-decorators/lib/index.js",
{ legacy: true },
{ version: "legacy" },
],
],
};
Expand Down
Expand Up @@ -4,7 +4,7 @@ module.exports = function () {
[
__dirname +
"/../../../../../babel-plugin-syntax-decorators/lib/index.js",
{ legacy: true },
{ version: "legacy" },
],
],
};
Expand Down
Expand Up @@ -4,7 +4,7 @@ module.exports = function () {
[
__dirname +
"/../../../../../babel-plugin-syntax-decorators/lib/index.js",
{ legacy: true },
{ version: "legacy" },
],
],
};
Expand Down
12 changes: 8 additions & 4 deletions packages/babel-generator/src/generators/classes.ts
Expand Up @@ -11,11 +11,15 @@ export function ClassDeclaration(
node: t.ClassDeclaration,
parent: t.Node,
) {
if (
!this.format.decoratorsBeforeExport ||
(!isExportDefaultDeclaration(parent) && !isExportNamedDeclaration(parent))
) {
if (process.env.BABEL_8_BREAKING) {
this.printJoin(node.decorators, node);
} else {
if (
!this.format.decoratorsBeforeExport ||
(!isExportDefaultDeclaration(parent) && !isExportNamedDeclaration(parent))
) {
this.printJoin(node.decorators, node);
}
}

if (node.declare) {
Expand Down
24 changes: 14 additions & 10 deletions packages/babel-generator/src/generators/modules.ts
Expand Up @@ -90,11 +90,13 @@ export function ExportNamedDeclaration(
this: Printer,
node: t.ExportNamedDeclaration,
) {
if (
this.format.decoratorsBeforeExport &&
isClassDeclaration(node.declaration)
) {
this.printJoin(node.declaration.decorators, node);
if (!process.env.BABEL_8_BREAKING) {
if (
this.format.decoratorsBeforeExport &&
isClassDeclaration(node.declaration)
) {
this.printJoin(node.declaration.decorators, node);
}
}

this.word("export");
Expand Down Expand Up @@ -156,11 +158,13 @@ export function ExportDefaultDeclaration(
this: Printer,
node: t.ExportDefaultDeclaration,
) {
if (
this.format.decoratorsBeforeExport &&
isClassDeclaration(node.declaration)
) {
this.printJoin(node.declaration.decorators, node);
if (!process.env.BABEL_8_BREAKING) {
if (
this.format.decoratorsBeforeExport &&
isClassDeclaration(node.declaration)
) {
this.printJoin(node.declaration.decorators, node);
}
}

this.word("export");
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-generator/src/index.ts
Expand Up @@ -66,7 +66,6 @@ function normalizeOptions(
style: " ",
base: 0,
},
decoratorsBeforeExport: !!opts.decoratorsBeforeExport,
jsescOption: {
quotes: "double",
wrap: true,
Expand All @@ -78,6 +77,7 @@ function normalizeOptions(
};

if (!process.env.BABEL_8_BREAKING) {
format.decoratorsBeforeExport = !!opts.decoratorsBeforeExport;
format.jsonCompatibleStrings = opts.jsonCompatibleStrings;
}

Expand Down Expand Up @@ -193,6 +193,7 @@ export interface GeneratorOptions {
/**
* Set to true to enable support for experimental decorators syntax before module exports.
* Defaults to `false`.
* @deprecated Removed in Babel 8
*/
decoratorsBeforeExport?: boolean;

Expand Down
5 changes: 4 additions & 1 deletion packages/babel-generator/src/printer.ts
Expand Up @@ -35,7 +35,6 @@ export type Format = {
style: string;
base: number;
};
decoratorsBeforeExport: boolean;
recordAndTupleSyntaxType: RecordAndTuplePluginOptions["syntaxType"];
jsescOption: jsescOptions;
jsonCompatibleStrings?: boolean;
Expand All @@ -44,6 +43,10 @@ export type Format = {
* Changes what token is used for pipe bodies’ topic references.
*/
topicToken?: PipelineOperatorPluginOptions["topicToken"];
/**
* @deprecated Removed in Babel 8
*/
decoratorsBeforeExport?: boolean;
};

interface AddNewlinesOptions {
Expand Down
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": [["decorators", { "decoratorsBeforeExport": false }]],
"decoratorsBeforeExport": false
}
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": [["decorators", { "decoratorsBeforeExport": false }]],
"decoratorsBeforeExport": true
}
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": [["decorators", { "decoratorsBeforeExport": true }]],
"decoratorsBeforeExport": false
}
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": [["decorators", { "decoratorsBeforeExport": true }]],
"decoratorsBeforeExport": true
}
@@ -1,3 +1,5 @@
// TODO(Babel 8): Remove this file

import { types as t, template } from "@babel/core";
import type { File } from "@babel/core";
import type { NodePath } from "@babel/traverse";
Expand Down
Expand Up @@ -6,6 +6,7 @@ export const FEATURES = Object.freeze({
//classes: 1 << 0,
fields: 1 << 1,
privateMethods: 1 << 2,
// TODO(Babel 8): Remove this
decorators: 1 << 3,
privateIn: 1 << 4,
staticBlocks: 1 << 5,
Expand Down Expand Up @@ -170,10 +171,10 @@ export function shouldTransform(path: NodePath<t.Class>, file: File): boolean {
throw path.buildCodeFrameError(
"Decorators are not enabled." +
"\nIf you are using " +
'["@babel/plugin-proposal-decorators", { "legacy": true }], ' +
'["@babel/plugin-proposal-decorators", { "version": "legacy" }], ' +
'make sure it comes *before* "@babel/plugin-proposal-class-properties" ' +
"and enable loose mode, like so:\n" +
'\t["@babel/plugin-proposal-decorators", { "legacy": true }]\n' +
'\t["@babel/plugin-proposal-decorators", { "version": "legacy" }]\n' +
'\t["@babel/plugin-proposal-class-properties", { "loose": true }]',
);
}
Expand Down
70 changes: 47 additions & 23 deletions packages/babel-helper-create-class-features-plugin/src/index.ts
Expand Up @@ -168,7 +168,11 @@ export function createClassFeaturePlugin({
}
}

if (!props.length && !isDecorated) return;
if (process.env.BABEL_8_BREAKING) {
if (!props.length) return;
} else {
if (!props.length && !isDecorated) return;
}

const innerBinding = path.node.id;
let ref: t.Identifier;
Expand Down Expand Up @@ -207,14 +211,30 @@ export function createClassFeaturePlugin({
pureStaticNodes: t.FunctionDeclaration[],
wrapClass: (path: NodePath<t.Class>) => NodePath;

if (isDecorated) {
staticNodes = pureStaticNodes = keysNodes = [];
({ instanceNodes, wrapClass } = buildDecoratedClass(
ref,
path,
elements,
file,
));
if (!process.env.BABEL_8_BREAKING) {
if (isDecorated) {
staticNodes = pureStaticNodes = keysNodes = [];
({ instanceNodes, wrapClass } = buildDecoratedClass(
ref,
path,
elements,
file,
));
} else {
keysNodes = extractComputedKeys(path, computedPaths, file);
({ staticNodes, pureStaticNodes, instanceNodes, wrapClass } =
buildFieldsInitNodes(
ref,
path.node.superClass,
props,
privateNamesMap,
file,
(setPublicClassFields ?? loose) as boolean,
(privateFieldsAsProperties ?? loose) as boolean,
(constantSuper ?? loose) as boolean,
innerBinding,
));
}
} else {
keysNodes = extractComputedKeys(path, computedPaths, file);
({ staticNodes, pureStaticNodes, instanceNodes, wrapClass } =
Expand All @@ -237,7 +257,9 @@ export function createClassFeaturePlugin({
constructor,
instanceNodes,
(referenceVisitor, state) => {
if (isDecorated) return;
if (!process.env.BABEL_8_BREAKING) {
if (isDecorated) return;
}
for (const prop of props) {
// @ts-expect-error: TS doesn't infer that prop.node is not a StaticBlock
if (t.isStaticBlock?.(prop.node) || prop.node.static) continue;
Expand All @@ -261,21 +283,23 @@ export function createClassFeaturePlugin({
},

ExportDefaultDeclaration(path, { file }) {
if (file.get(versionKey) !== version) return;
if (!process.env.BABEL_8_BREAKING) {
if (file.get(versionKey) !== version) return;

const decl = path.get("declaration");
const decl = path.get("declaration");

if (decl.isClassDeclaration() && hasDecorators(decl.node)) {
if (decl.node.id) {
// export default class Foo {}
// -->
// class Foo {} export { Foo as default }
splitExportDeclaration(path);
} else {
// Annyms class declarations can be
// transformed as if they were expressions
// @ts-expect-error
decl.node.type = "ClassExpression";
if (decl.isClassDeclaration() && hasDecorators(decl.node)) {
if (decl.node.id) {
// export default class Foo {}
// -->
// class Foo {} export { Foo as default }
splitExportDeclaration(path);
} else {
// Annyms class declarations can be
// transformed as if they were expressions
// @ts-expect-error
decl.node.type = "ClassExpression";
}
}
}
},
Expand Down
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"presets": [["typescript"]],
"plugins": [
["proposal-decorators", { "decoratorsBeforeExport": true }],
Expand Down
@@ -1,6 +1,6 @@
{
"plugins": [
["proposal-decorators", { "legacy": true }],
["proposal-decorators", { "version": "legacy" }],
["proposal-class-properties"],
"transform-classes"
]
Expand Down
@@ -1,6 +1,6 @@
{
"plugins": [
["proposal-decorators", { "legacy": true }],
["proposal-decorators", { "version": "legacy" }],
["proposal-class-properties", { "loose": true }],
"transform-classes"
]
Expand Down
@@ -1,6 +1,6 @@
{
"plugins": [
["proposal-decorators", { "legacy": true }],
["proposal-decorators", { "version": "legacy" }],
["proposal-class-properties"],
"transform-classes"
]
Expand Down
@@ -1,7 +1,7 @@
{
"plugins": [
["proposal-class-properties", { "loose": true }],
["proposal-decorators", { "legacy": true }]
["proposal-decorators", { "version": "legacy" }]
],
"throws": "Decorators are not enabled."
}
@@ -1,6 +1,6 @@
{
"plugins": [
["proposal-decorators", { "legacy": true }],
["proposal-decorators", { "version": "legacy" }],
["proposal-class-properties", { "loose": true }],
"transform-classes"
]
Expand Down
18 changes: 15 additions & 3 deletions packages/babel-plugin-proposal-decorators/src/index.ts
Expand Up @@ -21,17 +21,25 @@ export default declare((api, options: Options) => {
api.assertVersion(7);

// Options are validated in @babel/plugin-syntax-decorators
const { legacy, version } = options;
if (!process.env.BABEL_8_BREAKING) {
// eslint-disable-next-line no-var
var { legacy } = options;
}
const { version } = options;

if (legacy || version === "legacy") {
if (
process.env.BABEL_8_BREAKING
? version === "legacy"
: legacy || version === "legacy"
) {
return {
name: "proposal-decorators",
inherits: syntaxDecorators,
visitor: legacyVisitor,
};
} else if (version === "2021-12") {
return transformer2021_12(api, options);
} else {
} else if (!process.env.BABEL_8_BREAKING) {
return createClassFeaturePlugin({
name: "proposal-decorators",

Expand All @@ -40,5 +48,9 @@ export default declare((api, options: Options) => {
inherits: syntaxDecorators,
// loose: options.loose, Not supported
});
} else {
throw new Error(
"The '.version' option must be one of 'legacy' or '2021-12'",
);
}
});
@@ -1,4 +1,5 @@
{
"BABEL_8_BREAKING": false,
"plugins": [
["proposal-decorators", { "decoratorsBeforeExport": false }],
"proposal-class-properties"
Expand Down