diff --git a/packages/babel-plugin-transform-typescript/src/enum.ts b/packages/babel-plugin-transform-typescript/src/enum.ts index 3cc49ba12776..dc13399a80d7 100644 --- a/packages/babel-plugin-transform-typescript/src/enum.ts +++ b/packages/babel-plugin-transform-typescript/src/enum.ts @@ -98,47 +98,51 @@ function enumFill(path, t, id) { * Z = X | Y, * } */ -type PreviousEnumMembers = { - [name: string]: number | string; -}; +type PreviousEnumMembers = Map; export function translateEnumValues( path: NodePath, t: typeof import("@babel/types"), ): Array<[name: string, value: t.Expression]> { - const seen: PreviousEnumMembers = Object.create(null); + const seen: PreviousEnumMembers = new Map(); // Start at -1 so the first enum member is its increment, 0. - let prev: number | typeof undefined = -1; + let constValue: number | string | undefined = -1; + let lastName: string; + return path.node.members.map(member => { const name = t.isIdentifier(member.id) ? member.id.name : member.id.value; const initializer = member.initializer; let value: t.Expression; if (initializer) { - const constValue = evaluate(initializer, seen); + constValue = evaluate(initializer, seen); if (constValue !== undefined) { - seen[name] = constValue; + seen.set(name, constValue); if (typeof constValue === "number") { value = t.numericLiteral(constValue); - prev = constValue; } else { assert(typeof constValue === "string"); value = t.stringLiteral(constValue); - prev = undefined; } } else { value = initializer; - prev = undefined; } + } else if (typeof constValue === "number") { + constValue += 1; + value = t.numericLiteral(constValue); + seen.set(name, constValue); + } else if (typeof constValue === "string") { + throw path.buildCodeFrameError("Enum member must have initializer."); } else { - if (prev !== undefined) { - prev++; - value = t.numericLiteral(prev); - seen[name] = prev; - } else { - throw path.buildCodeFrameError("Enum member must have initializer."); - } + // create dynamic initializer: 1 + ENUM["PREVIOUS"] + const lastRef = t.memberExpression( + t.cloneNode(path.node.id), + t.stringLiteral(lastName), + true, + ); + value = t.binaryExpression("+", t.numericLiteral(1), lastRef); } + lastName = name; return [name, value]; }); } @@ -163,7 +167,7 @@ function evaluate( case "ParenthesizedExpression": return evalConstant(expr.expression); case "Identifier": - return seen[expr.name]; + return seen.get(expr.name); case "TemplateLiteral": if (expr.quasis.length === 1) { return expr.quasis[0].value.cooked; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/options.json deleted file mode 100644 index f0cc17142b58..000000000000 --- a/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Enum member must have initializer." -} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/output.js new file mode 100644 index 000000000000..90d6e1087ef8 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/enum/non-foldable-constant/output.js @@ -0,0 +1,6 @@ +var E; + +(function (E) { + E[E["a"] = Math.sin(1)] = "a"; + E[E["b"] = 1 + E["a"]] = "b"; +})(E || (E = {})); diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/input.ts new file mode 100644 index 000000000000..25fb6d7b0769 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/input.ts @@ -0,0 +1,13 @@ +enum socketType { + SOCKET, + SERVER, + IPC, +} + +enum constants { + SOCKET = socketType.SOCKET, + SERVER = socketType.SERVER, + IPC = socketType.IPC, + UV_READABLE, + UV_WRITABLE, +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/output.js b/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/output.js new file mode 100644 index 000000000000..8e6616d8e88d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/enum/outer-references/output.js @@ -0,0 +1,17 @@ +var socketType; + +(function (socketType) { + socketType[socketType["SOCKET"] = 0] = "SOCKET"; + socketType[socketType["SERVER"] = 1] = "SERVER"; + socketType[socketType["IPC"] = 2] = "IPC"; +})(socketType || (socketType = {})); + +var constants; + +(function (constants) { + constants[constants["SOCKET"] = socketType.SOCKET] = "SOCKET"; + constants[constants["SERVER"] = socketType.SERVER] = "SERVER"; + constants[constants["IPC"] = socketType.IPC] = "IPC"; + constants[constants["UV_READABLE"] = 1 + constants["IPC"]] = "UV_READABLE"; + constants[constants["UV_WRITABLE"] = 1 + constants["UV_READABLE"]] = "UV_WRITABLE"; +})(constants || (constants = {}));