From b707842dd0ce3084ea497d1f8109f5c4d5fffa68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 3 Aug 2021 23:57:09 +0200 Subject: [PATCH] Support TypeScript const enums (#13324) --- .../src/const-enum.ts | 89 +++++++++++++++++++ .../src/enum.ts | 8 +- .../src/index.ts | 8 +- .../declarations/const-enum/options.json | 1 - .../declarations/export-declare-enum/input.ts | 3 + .../export-declare-enum/options.json | 3 + .../export-declare-enum/output.mjs | 1 + .../test/fixtures/enum/const/input.ts | 3 +- .../test/fixtures/enum/const/options.json | 1 - .../test/fixtures/enum/const/output.js | 4 + .../custom-values-exported/input.ts | 11 +++ .../custom-values-exported/output.mjs | 10 +++ .../custom-values/input.ts | 11 +++ .../custom-values/output.mjs | 4 + .../optimize-const-enums/declare/input.ts | 3 + .../optimize-const-enums/declare/output.mjs | 1 + .../export-const-enum/input.ts | 3 + .../export-const-enum/output.mjs | 4 + .../optimize-const-enums/exported/input.ts | 5 ++ .../optimize-const-enums/exported/output.mjs | 5 ++ .../local-shadowed/input.ts | 8 ++ .../local-shadowed/output.mjs | 5 ++ .../optimize-const-enums/local/input.ts | 8 ++ .../optimize-const-enums/local/output.mjs | 4 + .../merged-exported/input.ts | 13 +++ .../merged-exported/output.mjs | 12 +++ .../optimize-const-enums/merged/input.ts | 13 +++ .../optimize-const-enums/merged/output.mjs | 5 ++ .../optimize-const-enums/options.json | 4 + packages/babel-preset-typescript/src/index.js | 3 + .../src/normalize-options.js | 36 +++++--- .../fixtures/opts/optimizeConstEnums/input.ts | 3 + .../opts/optimizeConstEnums/output.js | 1 + .../test/fixtures/opts/options.json | 3 + .../test/normalize-options.spec.js | 5 +- 35 files changed, 280 insertions(+), 21 deletions(-) create mode 100644 packages/babel-plugin-transform-typescript/src/const-enum.ts delete mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/declarations/const-enum/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/output.mjs delete mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/enum/const/options.json create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/enum/const/output.js create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/input.ts create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/output.mjs create mode 100644 packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/options.json create mode 100644 packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/input.ts create mode 100644 packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/output.js create mode 100644 packages/babel-preset-typescript/test/fixtures/opts/options.json diff --git a/packages/babel-plugin-transform-typescript/src/const-enum.ts b/packages/babel-plugin-transform-typescript/src/const-enum.ts new file mode 100644 index 0000000000..171fa56b6b --- /dev/null +++ b/packages/babel-plugin-transform-typescript/src/const-enum.ts @@ -0,0 +1,89 @@ +import type * as t from "@babel/types"; +import type { NodePath } from "@babel/traverse"; + +import { translateEnumValues } from "./enum"; + +export default function transpileConstEnum( + path: NodePath, + t: typeof import("@babel/types"), +) { + const { name } = path.node.id; + + const parentIsExport = path.parentPath.isExportNamedDeclaration(); + let isExported = parentIsExport; + if (!isExported && t.isProgram(path.parent)) { + isExported = path.parent.body.some( + stmt => + t.isExportNamedDeclaration(stmt) && + !stmt.source && + stmt.specifiers.some( + spec => t.isExportSpecifier(spec) && spec.local.name === name, + ), + ); + } + + const entries = translateEnumValues(path, t); + + if (isExported) { + const obj = t.objectExpression( + entries.map(([name, value]) => + t.objectProperty( + t.isValidIdentifier(name) + ? t.identifier(name) + : t.stringLiteral(name), + value, + ), + ), + ); + + if (path.scope.hasOwnBinding(name)) { + (parentIsExport ? path.parentPath : path).replaceWith( + t.expressionStatement( + t.callExpression( + t.memberExpression(t.identifier("Object"), t.identifier("assign")), + [path.node.id, obj], + ), + ), + ); + } else { + path.replaceWith( + t.variableDeclaration("var", [t.variableDeclarator(path.node.id, obj)]), + ); + path.scope.registerDeclaration(path); + } + + return; + } + + const entriesMap = new Map(entries); + + // TODO: After fixing https://github.com/babel/babel/pull/11065, we can + // use path.scope.getBinding(name).referencePaths rather than doing + // a full traversal. + path.scope.path.traverse({ + Scope(path) { + if (path.scope.hasOwnBinding(name)) path.skip(); + }, + MemberExpression(path) { + if (!t.isIdentifier(path.node.object, { name })) return; + + let key: string; + if (path.node.computed) { + if (t.isStringLiteral(path.node.property)) { + key = path.node.property.value; + } else { + return; + } + } else if (t.isIdentifier(path.node.property)) { + key = path.node.property.name; + } else { + return; + } + if (!entriesMap.has(key)) return; + + path.replaceWith(t.cloneNode(entriesMap.get(key))); + }, + }); + + path.remove(); +} diff --git a/packages/babel-plugin-transform-typescript/src/enum.ts b/packages/babel-plugin-transform-typescript/src/enum.ts index 156ccda524..3cc49ba127 100644 --- a/packages/babel-plugin-transform-typescript/src/enum.ts +++ b/packages/babel-plugin-transform-typescript/src/enum.ts @@ -5,9 +5,6 @@ import type { NodePath } from "@babel/traverse"; export default function transpileEnum(path, t) { const { node } = path; - if (node.const) { - throw path.buildCodeFrameError("'const' enums are not supported."); - } if (node.declare) { path.remove(); @@ -105,7 +102,10 @@ type PreviousEnumMembers = { [name: string]: number | string; }; -function translateEnumValues(path, t) { +export function translateEnumValues( + path: NodePath, + t: typeof import("@babel/types"), +): Array<[name: string, value: t.Expression]> { const seen: PreviousEnumMembers = Object.create(null); // Start at -1 so the first enum member is its increment, 0. let prev: number | typeof undefined = -1; diff --git a/packages/babel-plugin-transform-typescript/src/index.ts b/packages/babel-plugin-transform-typescript/src/index.ts index 066759f1d6..3ce2557e4d 100644 --- a/packages/babel-plugin-transform-typescript/src/index.ts +++ b/packages/babel-plugin-transform-typescript/src/index.ts @@ -3,6 +3,7 @@ import syntaxTypeScript from "@babel/plugin-syntax-typescript"; import { types as t, template } from "@babel/core"; import { injectInitialization } from "@babel/helper-create-class-features-plugin"; +import transpileConstEnum from "./const-enum"; import transpileEnum from "./enum"; import transpileNamespace from "./namespace"; import type { NodePath } from "@babel/traverse"; @@ -60,6 +61,7 @@ export default declare((api, opts) => { jsxPragma = "React.createElement", jsxPragmaFrag = "React.Fragment", onlyRemoveTypeImports = false, + optimizeConstEnums = false, } = opts; if (!process.env.BABEL_8_BREAKING) { @@ -462,7 +464,11 @@ export default declare((api, opts) => { }, TSEnumDeclaration(path) { - transpileEnum(path, t); + if (optimizeConstEnums && path.node.const) { + transpileConstEnum(path, t); + } else { + transpileEnum(path, t); + } }, TSImportEqualsDeclaration(path: NodePath) { diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/declarations/const-enum/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/const-enum/options.json deleted file mode 100644 index 26f55acbbd..0000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/declarations/const-enum/options.json +++ /dev/null @@ -1 +0,0 @@ -{ "throws": "'const' enums are not supported." } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/input.ts new file mode 100644 index 0000000000..a5ff19e60d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/input.ts @@ -0,0 +1,3 @@ +export declare enum A {} + +; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/options.json new file mode 100644 index 0000000000..2104ca4328 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "module" +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/output.mjs new file mode 100644 index 0000000000..092bc2b041 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/declarations/export-declare-enum/output.mjs @@ -0,0 +1 @@ +; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/input.ts index c8a36474cb..74a3825571 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/input.ts +++ b/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/input.ts @@ -1 +1,2 @@ -const enum E {} \ No newline at end of file +// With --isolatedModules, TSC ignores the "const" modifier when compiling enums +const enum E {} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/options.json deleted file mode 100644 index 26f55acbbd..0000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/options.json +++ /dev/null @@ -1 +0,0 @@ -{ "throws": "'const' enums are not supported." } diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/output.js new file mode 100644 index 0000000000..3bf954ce13 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/enum/const/output.js @@ -0,0 +1,4 @@ +// With --isolatedModules, TSC ignores the "const" modifier when compiling enums +var E; + +(function (E) {})(E || (E = {})); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/input.ts new file mode 100644 index 0000000000..f529407643 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/input.ts @@ -0,0 +1,11 @@ +export const enum A { + x = 3, + y = "f", + z = 4 << 2, + w = y +} + +A.x; +A.y; +A.z; +A.w; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/output.mjs new file mode 100644 index 0000000000..5fea498b31 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values-exported/output.mjs @@ -0,0 +1,10 @@ +export var A = { + x: 3, + y: "f", + z: 16, + w: "f" +}; +A.x; +A.y; +A.z; +A.w; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/input.ts new file mode 100644 index 0000000000..505aa9a4fc --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/input.ts @@ -0,0 +1,11 @@ +const enum A { + x = 3, + y = "f", + z = 4 << 2, + w = y +} + +A.x; +A.y; +A.z; +A.w; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/output.mjs new file mode 100644 index 0000000000..2e56af68ca --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/custom-values/output.mjs @@ -0,0 +1,4 @@ +3; +"f"; +16; +"f"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/input.ts new file mode 100644 index 0000000000..bb7773e0ef --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/input.ts @@ -0,0 +1,3 @@ +declare const enum A { x } + +A.x; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/output.mjs new file mode 100644 index 0000000000..0f57817f75 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/declare/output.mjs @@ -0,0 +1 @@ +0; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/input.ts new file mode 100644 index 0000000000..3f592f3db6 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/input.ts @@ -0,0 +1,3 @@ +export const enum A { y } + +let x = A.y; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/output.mjs new file mode 100644 index 0000000000..a7e19e1b69 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/export-const-enum/output.mjs @@ -0,0 +1,4 @@ +export var A = { + y: 0 +}; +let x = A.y; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/input.ts new file mode 100644 index 0000000000..1e77fc59b9 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/input.ts @@ -0,0 +1,5 @@ +const enum A { y } + +let x = A.y; + +export { A }; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/output.mjs new file mode 100644 index 0000000000..e7b5e34889 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/exported/output.mjs @@ -0,0 +1,5 @@ +var A = { + y: 0 +}; +let x = A.y; +export { A }; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/input.ts new file mode 100644 index 0000000000..a98c71ecc2 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/input.ts @@ -0,0 +1,8 @@ +const enum A { x } + +{ + let A = {}; + A.x; +} + +A.x; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/output.mjs new file mode 100644 index 0000000000..e73688dada --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local-shadowed/output.mjs @@ -0,0 +1,5 @@ +{ + let A = {}; + A.x; +} +0; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/input.ts new file mode 100644 index 0000000000..d5d8f86295 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/input.ts @@ -0,0 +1,8 @@ +const enum A { + x, y +} + +A.x; +A["y"]; +A.z; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/output.mjs new file mode 100644 index 0000000000..a238ac8a56 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/local/output.mjs @@ -0,0 +1,4 @@ +0; +1; +A.z; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/input.ts new file mode 100644 index 0000000000..7f7e641321 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/input.ts @@ -0,0 +1,13 @@ +export const enum A { + x, y +} + +export const enum A { + z +} + +A.x; +A["y"]; +A.z; +A.w; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/output.mjs new file mode 100644 index 0000000000..e73c89ed76 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged-exported/output.mjs @@ -0,0 +1,12 @@ +export var A = { + x: 0, + y: 1 +}; +Object.assign(A, { + z: 0 +}); +A.x; +A["y"]; +A.z; +A.w; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/input.ts new file mode 100644 index 0000000000..68546f2642 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/input.ts @@ -0,0 +1,13 @@ +const enum A { + x, y +} + +const enum A { + z +} + +A.x; +A["y"]; +A.z; +A.w; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/output.mjs new file mode 100644 index 0000000000..a609a8503e --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/merged/output.mjs @@ -0,0 +1,5 @@ +0; +1; +0; +A.w; +A; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/options.json new file mode 100644 index 0000000000..97badaf461 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/optimize-const-enums/options.json @@ -0,0 +1,4 @@ +{ + "plugins": [["transform-typescript", { "optimizeConstEnums": true }]], + "sourceType": "module" +} diff --git a/packages/babel-preset-typescript/src/index.js b/packages/babel-preset-typescript/src/index.js index 94534d0473..e384e41c24 100644 --- a/packages/babel-preset-typescript/src/index.js +++ b/packages/babel-preset-typescript/src/index.js @@ -12,6 +12,7 @@ export default declare((api, opts) => { jsxPragma, jsxPragmaFrag, onlyRemoveTypeImports, + optimizeConstEnums, } = normalizeOptions(opts); const pluginOptions = process.env.BABEL_8_BREAKING @@ -21,6 +22,7 @@ export default declare((api, opts) => { jsxPragma, jsxPragmaFrag, onlyRemoveTypeImports, + optimizeConstEnums, }) : isTSX => ({ allowDeclareFields: opts.allowDeclareFields, @@ -29,6 +31,7 @@ export default declare((api, opts) => { jsxPragma, jsxPragmaFrag, onlyRemoveTypeImports, + optimizeConstEnums, }); return { diff --git a/packages/babel-preset-typescript/src/normalize-options.js b/packages/babel-preset-typescript/src/normalize-options.js index 71d0f2b722..6812fac324 100644 --- a/packages/babel-preset-typescript/src/normalize-options.js +++ b/packages/babel-preset-typescript/src/normalize-options.js @@ -4,15 +4,17 @@ const v = new OptionValidator("@babel/preset-typescript"); export default function normalizeOptions(options = {}) { let { allowNamespaces = true, jsxPragma, onlyRemoveTypeImports } = options; + const TopLevelOptions = { + allExtensions: "allExtensions", + allowNamespaces: "allowNamespaces", + isTSX: "isTSX", + jsxPragma: "jsxPragma", + jsxPragmaFrag: "jsxPragmaFrag", + onlyRemoveTypeImports: "onlyRemoveTypeImports", + optimizeConstEnums: "optimizeConstEnums", + }; + if (process.env.BABEL_8_BREAKING) { - const TopLevelOptions = { - allExtensions: "allExtensions", - allowNamespaces: "allowNamespaces", - isTSX: "isTSX", - jsxPragma: "jsxPragma", - jsxPragmaFrag: "jsxPragmaFrag", - onlyRemoveTypeImports: "onlyRemoveTypeImports", - }; v.validateTopLevelOptions(options, TopLevelOptions); allowNamespaces = v.validateBooleanOption( TopLevelOptions.allowNamespaces, @@ -32,23 +34,32 @@ export default function normalizeOptions(options = {}) { } const jsxPragmaFrag = v.validateStringOption( - "jsxPragmaFrag", + TopLevelOptions.jsxPragmaFrag, options.jsxPragmaFrag, "React.Fragment", ); const allExtensions = v.validateBooleanOption( - "allExtensions", + TopLevelOptions.allExtensions, options.allExtensions, false, ); - const isTSX = v.validateBooleanOption("isTSX", options.isTSX, false); - + const isTSX = v.validateBooleanOption( + TopLevelOptions.isTSX, + options.isTSX, + false, + ); if (isTSX) { v.invariant(allExtensions, "isTSX:true requires allExtensions:true"); } + const optimizeConstEnums = v.validateBooleanOption( + TopLevelOptions.optimizeConstEnums, + options.optimizeConstEnums, + false, + ); + return { allExtensions, allowNamespaces, @@ -56,5 +67,6 @@ export default function normalizeOptions(options = {}) { jsxPragma, jsxPragmaFrag, onlyRemoveTypeImports, + optimizeConstEnums, }; } diff --git a/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/input.ts b/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/input.ts new file mode 100644 index 0000000000..185fd286a1 --- /dev/null +++ b/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/input.ts @@ -0,0 +1,3 @@ +const enum A { x } + +A.x; diff --git a/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/output.js b/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/output.js new file mode 100644 index 0000000000..0f57817f75 --- /dev/null +++ b/packages/babel-preset-typescript/test/fixtures/opts/optimizeConstEnums/output.js @@ -0,0 +1 @@ +0; diff --git a/packages/babel-preset-typescript/test/fixtures/opts/options.json b/packages/babel-preset-typescript/test/fixtures/opts/options.json new file mode 100644 index 0000000000..5d0c4ceac9 --- /dev/null +++ b/packages/babel-preset-typescript/test/fixtures/opts/options.json @@ -0,0 +1,3 @@ +{ + "presets": [["typescript", { "optimizeConstEnums": true }]] +} diff --git a/packages/babel-preset-typescript/test/normalize-options.spec.js b/packages/babel-preset-typescript/test/normalize-options.spec.js index 0b99d8e4b9..d0a10d1808 100644 --- a/packages/babel-preset-typescript/test/normalize-options.spec.js +++ b/packages/babel-preset-typescript/test/normalize-options.spec.js @@ -11,6 +11,7 @@ describe("normalize options", () => { "allowNamespaces", "isTSX", "onlyRemoveTypeImports", + "optimizeConstEnums", ])("should throw when `%p` is not a boolean", optionName => { expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( `@babel/preset-typescript: '${optionName}' option must be a boolean.`, @@ -36,6 +37,7 @@ describe("normalize options", () => { "jsxPragma": "React", "jsxPragmaFrag": "React.Fragment", "onlyRemoveTypeImports": true, + "optimizeConstEnums": false, } `); }); @@ -58,7 +60,7 @@ describe("normalize options", () => { expect(() => normalizeOptions({ [optionName]: 0 })).not.toThrowError(); }, ); - it.each(["allExtensions", "isTSX"])( + it.each(["allExtensions", "isTSX", "optimizeConstEnums"])( "should throw when `%p` is not a boolean", optionName => { expect(() => normalizeOptions({ [optionName]: 0 })).toThrow( @@ -83,6 +85,7 @@ describe("normalize options", () => { "jsxPragma": undefined, "jsxPragmaFrag": "React.Fragment", "onlyRemoveTypeImports": undefined, + "optimizeConstEnums": false, } `); });