From 2311ddbe67ca0170195d1a8e3b7648f8e518b8fd Mon Sep 17 00:00:00 2001 From: Mauro Bringolf Date: Thu, 19 Oct 2017 00:00:58 +0200 Subject: [PATCH] Add transform to rename variables that are ES3 reserved words (#6479) * Initial version * Replace .includes with .indexOf and better node set to visit * Alphabetically sort es3 reserved words and make difference helper for readability * Fix second Array.include error that was not polyfilled * Move es3 keywords into separate babel-types helper and use in all es3 transforms * Reference local plugin build directly for tests * Try relative import for babel-types * Update to scoped package name and beta 3 * Fix unscoped package import * Replace local plugin reference with proper plugin name --- .../src/index.js | 2 +- .../src/index.js | 2 +- .../.npmignore | 3 +++ .../package.json | 14 ++++++++++ .../src/index.js | 11 ++++++++ .../fixtures/issue-6477/issue-6477/actual.js | 4 +++ .../issue-6477/issue-6477/expected.js | 4 +++ .../issue-6477/issue-6477/options.json | 3 +++ .../test/index.js | 3 +++ packages/babel-types/src/constants.js | 27 +++++++++++++++++++ packages/babel-types/src/index.js | 1 + packages/babel-types/src/validators.js | 10 ++++++- 12 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 packages/babel-plugin-transform-es3-reserved-words/.npmignore create mode 100644 packages/babel-plugin-transform-es3-reserved-words/package.json create mode 100644 packages/babel-plugin-transform-es3-reserved-words/src/index.js create mode 100644 packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/actual.js create mode 100644 packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/expected.js create mode 100644 packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/options.json create mode 100644 packages/babel-plugin-transform-es3-reserved-words/test/index.js diff --git a/packages/babel-plugin-transform-es3-member-expression-literals/src/index.js b/packages/babel-plugin-transform-es3-member-expression-literals/src/index.js index a4a49f9080..5d83fe057c 100644 --- a/packages/babel-plugin-transform-es3-member-expression-literals/src/index.js +++ b/packages/babel-plugin-transform-es3-member-expression-literals/src/index.js @@ -7,7 +7,7 @@ export default function({ types: t }) { if ( !node.computed && t.isIdentifier(prop) && - !t.isValidIdentifier(prop.name) + !t.isValidES3Identifier(prop.name) ) { // foo.default -> foo["default"] node.property = t.stringLiteral(prop.name); diff --git a/packages/babel-plugin-transform-es3-property-literals/src/index.js b/packages/babel-plugin-transform-es3-property-literals/src/index.js index 558e8ff5fe..bf60ced80e 100644 --- a/packages/babel-plugin-transform-es3-property-literals/src/index.js +++ b/packages/babel-plugin-transform-es3-property-literals/src/index.js @@ -7,7 +7,7 @@ export default function({ types: t }) { if ( !node.computed && t.isIdentifier(key) && - !t.isValidIdentifier(key.name) + !t.isValidES3Identifier(key.name) ) { // default: "bar" -> "default": "bar" node.key = t.stringLiteral(key.name); diff --git a/packages/babel-plugin-transform-es3-reserved-words/.npmignore b/packages/babel-plugin-transform-es3-reserved-words/.npmignore new file mode 100644 index 0000000000..f980694583 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/.npmignore @@ -0,0 +1,3 @@ +src +test +*.log diff --git a/packages/babel-plugin-transform-es3-reserved-words/package.json b/packages/babel-plugin-transform-es3-reserved-words/package.json new file mode 100644 index 0000000000..f11b3e93d4 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/package.json @@ -0,0 +1,14 @@ +{ + "name": "@babel/plugin-transform-es3-reserved-words", + "version": "7.0.0-beta.3", + "description": "Ensure that no reserved words are used.", + "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es3-reserved-words", + "license": "MIT", + "main": "lib/index.js", + "keywords": [ + "babel-plugin" + ], + "devDependencies": { + "@babel/helper-plugin-test-runner": "7.0.0-beta.3" + } +} diff --git a/packages/babel-plugin-transform-es3-reserved-words/src/index.js b/packages/babel-plugin-transform-es3-reserved-words/src/index.js new file mode 100644 index 0000000000..1ce05d3f72 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/src/index.js @@ -0,0 +1,11 @@ +export default function({ types: t }) { + return { + visitor: { + "BindingIdentifier|ReferencedIdentifier"(path) { + if (!t.isValidES3Identifier(path.node.name)) { + path.scope.rename(path.node.name); + } + }, + }, + }; +} diff --git a/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/actual.js b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/actual.js new file mode 100644 index 0000000000..ee0ba0d254 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/actual.js @@ -0,0 +1,4 @@ +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return -1; +} diff --git a/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/expected.js b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/expected.js new file mode 100644 index 0000000000..ae5e84c045 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/expected.js @@ -0,0 +1,4 @@ +function utf8CheckByte(_byte) { + if (_byte <= 0x7F) return 0;else if (_byte >> 5 === 0x06) return 2;else if (_byte >> 4 === 0x0E) return 3;else if (_byte >> 3 === 0x1E) return 4; + return -1; +} diff --git a/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/options.json b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/options.json new file mode 100644 index 0000000000..8908fc24a8 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/test/fixtures/issue-6477/issue-6477/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-es3-reserved-words"] +} diff --git a/packages/babel-plugin-transform-es3-reserved-words/test/index.js b/packages/babel-plugin-transform-es3-reserved-words/test/index.js new file mode 100644 index 0000000000..1b534b8fc6 --- /dev/null +++ b/packages/babel-plugin-transform-es3-reserved-words/test/index.js @@ -0,0 +1,3 @@ +import runner from "@babel/helper-plugin-test-runner"; + +runner(__dirname); diff --git a/packages/babel-types/src/constants.js b/packages/babel-types/src/constants.js index 67bf898068..ec46a48253 100644 --- a/packages/babel-types/src/constants.js +++ b/packages/babel-types/src/constants.js @@ -62,3 +62,30 @@ export const BLOCK_SCOPED_SYMBOL = Symbol.for("var used to be block scoped"); export const NOT_LOCAL_BINDING = Symbol.for( "should not be considered a local binding", ); + +export const RESERVED_WORDS_ES3_ONLY = new Set([ + "abstract", + "boolean", + "byte", + "char", + "double", + "enum", + "final", + "float", + "goto", + "implements", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "synchronized", + "throws", + "transient", + "volatile", +]); diff --git a/packages/babel-types/src/index.js b/packages/babel-types/src/index.js index 172e2d4027..bdffa7c96c 100644 --- a/packages/babel-types/src/index.js +++ b/packages/babel-types/src/index.js @@ -580,6 +580,7 @@ export { isBinding, isReferenced, isValidIdentifier, + isValidES3Identifier, isLet, isBlockScoped, isVar, diff --git a/packages/babel-types/src/validators.js b/packages/babel-types/src/validators.js index 81497ae367..5673b01f3e 100644 --- a/packages/babel-types/src/validators.js +++ b/packages/babel-types/src/validators.js @@ -1,7 +1,7 @@ import { getBindingIdentifiers } from "./retrievers"; import esutils from "esutils"; import * as t from "./index"; -import { BLOCK_SCOPED_SYMBOL } from "./constants"; +import { BLOCK_SCOPED_SYMBOL, RESERVED_WORDS_ES3_ONLY } from "./constants"; /** * Check if the input `node` is a binding identifier. @@ -177,6 +177,14 @@ export function isValidIdentifier(name: string): boolean { return esutils.keyword.isIdentifierNameES6(name); } } +/** + * Check if the input `name` is a valid identifier name according to the ES3 specification. + * + * Additional ES3 reserved words are + */ +export function isValidES3Identifier(name: string): boolean { + return isValidIdentifier(name, true) && !RESERVED_WORDS_ES3_ONLY.has(name); +} /** * Check if the input `node` is a `let` variable declaration.