diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/input.mjs new file mode 100644 index 000000000000..924c4ec9897e --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/input.mjs @@ -0,0 +1,3 @@ +export class TypeError { + #message +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/options.json new file mode 100644 index 000000000000..59fe9f6a9225 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["proposal-class-properties"], + "externalHelpers": false +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/output.mjs new file mode 100644 index 000000000000..3cbf7b8d3e93 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/class-shadow-builtins/output.mjs @@ -0,0 +1,12 @@ +function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); } +function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } } +var _message = /*#__PURE__*/new WeakMap(); +class _TypeError { + constructor() { + _classPrivateFieldInitSpec(this, _message, { + writable: true, + value: void 0 + }); + } +} +export { _TypeError as TypeError }; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/input.mjs new file mode 100644 index 000000000000..924c4ec9897e --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/input.mjs @@ -0,0 +1,3 @@ +export class TypeError { + #message +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/options.json new file mode 100644 index 000000000000..59fe9f6a9225 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["proposal-class-properties"], + "externalHelpers": false +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/output.mjs new file mode 100644 index 000000000000..3cbf7b8d3e93 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/class-shadow-builtins/output.mjs @@ -0,0 +1,12 @@ +function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); } +function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } } +var _message = /*#__PURE__*/new WeakMap(); +class _TypeError { + constructor() { + _classPrivateFieldInitSpec(this, _message, { + writable: true, + value: void 0 + }); + } +} +export { _TypeError as TypeError }; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/input.mjs new file mode 100644 index 000000000000..ed88dba1eea0 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/input.mjs @@ -0,0 +1,3 @@ +export class TypeError { + message +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/options.json new file mode 100644 index 000000000000..59fe9f6a9225 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["proposal-class-properties"], + "externalHelpers": false +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/output.mjs new file mode 100644 index 000000000000..9debdcf55680 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/class-shadow-builtins/output.mjs @@ -0,0 +1,9 @@ +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +class _TypeError { + constructor() { + _defineProperty(this, "message", void 0); + } +} +export { _TypeError as TypeError }; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/input.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/input.mjs new file mode 100644 index 000000000000..ed88dba1eea0 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/input.mjs @@ -0,0 +1,3 @@ +export class TypeError { + message +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/options.json new file mode 100644 index 000000000000..59fe9f6a9225 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["proposal-class-properties"], + "externalHelpers": false +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/output.mjs new file mode 100644 index 000000000000..9debdcf55680 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/class-shadow-builtins/output.mjs @@ -0,0 +1,9 @@ +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +class _TypeError { + constructor() { + _defineProperty(this, "message", void 0); + } +} +export { _TypeError as TypeError }; diff --git a/packages/babel-traverse/src/path/modification.ts b/packages/babel-traverse/src/path/modification.ts index 3da582b72f43..bbf90e5e5837 100644 --- a/packages/babel-traverse/src/path/modification.ts +++ b/packages/babel-traverse/src/path/modification.ts @@ -13,6 +13,7 @@ import { expressionStatement, isAssignmentExpression, isCallExpression, + isExportNamedDeclaration, isExpression, isIdentifier, isSequenceExpression, @@ -34,12 +35,19 @@ export function insertBefore( const nodes = this._verifyNodeList(nodes_); - const { parentPath } = this; + const { parentPath, parent } = this; if ( parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || - parentPath.isExportNamedDeclaration() || + // https://github.com/babel/babel/issues/15293 + // When Babel transforms `export class String { field }`, the class properties plugin will inject the defineProperty + // helper, which depends on the builtins e.g. String, Number, Symbol, etc. To prevent them from being shadowed by local + // exports, the helper injector replaces the named export into `class _String { field }; export { _String as String }`, + // with `parentPath` here changed to the moved ClassDeclaration, causing rare inconsistency between `parent` and `parentPath`. + // Here we retrieve the parent type from the `parent` property. This is a temporary fix and we should revisit when + // helpers should get injected. + isExportNamedDeclaration(parent) || (parentPath.isExportDefaultDeclaration() && this.isDeclaration()) ) { return parentPath.insertBefore(nodes); @@ -169,11 +177,12 @@ export function insertAfter( const nodes = this._verifyNodeList(nodes_); - const { parentPath } = this; + const { parentPath, parent } = this; if ( parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || - parentPath.isExportNamedDeclaration() || + // see insertBefore + isExportNamedDeclaration(parent) || (parentPath.isExportDefaultDeclaration() && this.isDeclaration()) ) { return parentPath.insertAfter(