diff --git a/packages/babel-helpers/src/helpers.js b/packages/babel-helpers/src/helpers.js index 87c1cbea20..8ff523b252 100644 --- a/packages/babel-helpers/src/helpers.js +++ b/packages/babel-helpers/src/helpers.js @@ -362,7 +362,7 @@ helpers.get = template(` helpers.inherits = template(` (function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); + throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/options.json b/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/options.json index e5e9ad8a9a..23d21f802d 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/options.json +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/options.json @@ -1,3 +1,3 @@ { - "plugins": ["transform-es2015-classes", "transform-es2015-block-scoping"] + "plugins": ["transform-es2015-classes", "transform-es2015-block-scoping", "transform-es2015-typeof-symbol"] } diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/return-symbol.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/return-symbol.js new file mode 100644 index 0000000000..425fec9fea --- /dev/null +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/exec/return-symbol.js @@ -0,0 +1,9 @@ +class Foo { + constructor() { + return Symbol(); + } +} + +const f = new Foo; +assert.ok(f instanceof Foo); +assert.ok(typeof f === "object"); diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T7537/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T7537/expected.js index 57019fadbb..915863627d 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T7537/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T7537/expected.js @@ -1,8 +1,10 @@ "use strict"; -function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } diff --git a/packages/babel-plugin-transform-es2015-typeof-symbol/src/index.js b/packages/babel-plugin-transform-es2015-typeof-symbol/src/index.js index 145cf41ff6..2a10a7de5b 100644 --- a/packages/babel-plugin-transform-es2015-typeof-symbol/src/index.js +++ b/packages/babel-plugin-transform-es2015-typeof-symbol/src/index.js @@ -1,6 +1,4 @@ export default function({ types: t }) { - const IGNORE = Symbol(); - return { visitor: { Scope({ scope }) { @@ -13,8 +11,7 @@ export default function({ types: t }) { UnaryExpression(path) { const { node, parent } = path; - if (node[IGNORE]) return; - if (path.find(path => path.node && !!path.node._generated)) return; + if (node.operator !== "typeof") return; if ( path.parentPath.isBinaryExpression() && @@ -32,24 +29,29 @@ export default function({ types: t }) { } } - if (node.operator === "typeof") { - const call = t.callExpression(this.addHelper("typeof"), [ - node.argument, - ]); - if (path.get("argument").isIdentifier()) { - const undefLiteral = t.stringLiteral("undefined"); - const unary = t.unaryExpression("typeof", node.argument); - unary[IGNORE] = true; - path.replaceWith( - t.conditionalExpression( - t.binaryExpression("===", unary, undefLiteral), - undefLiteral, - call, - ), - ); - } else { - path.replaceWith(call); - } + const helper = this.addHelper("typeof"); + const isUnderHelper = path.findParent(path => { + return path.isVariableDeclarator() && path.node.id === helper; + }); + + if (isUnderHelper) { + return; + } + + const call = t.callExpression(helper, [node.argument]); + const arg = path.get("argument"); + if (arg.isIdentifier() && !path.scope.hasBinding(arg.node.name)) { + const undefLiteral = t.stringLiteral("undefined"); + const unary = t.unaryExpression("typeof", node.argument); + path.replaceWith( + t.conditionalExpression( + t.binaryExpression("===", unary, undefLiteral), + undefLiteral, + call, + ), + ); + } else { + path.replaceWith(call); } }, }, diff --git a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/actual.js b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/actual.js index 872484bd9c..527af8d790 100644 --- a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/actual.js +++ b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/actual.js @@ -3,3 +3,7 @@ assert.ok(typeof s === "symbol"); assert.equal(typeof s, "symbol"); assert.equal(typeof typeof s.foo, "symbol"); typeof s === "string"; +assert.isNotOk(typeof o === "symbol"); +assert.notEqual(typeof o, "symbol"); +assert.notEqual(typeof typeof o.foo, "symbol"); +typeof o === "string"; diff --git a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/exec.js b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/exec.js index d89051afe7..72906c476c 100644 --- a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/exec.js +++ b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/exec.js @@ -2,3 +2,7 @@ var s = Symbol("s"); assert.equal(typeof s, "symbol"); assert.ok(typeof s === "symbol"); assert.ok(typeof Symbol.prototype === 'object', "`typeof Symbol.prototype` should be 'object'"); +assert.isNotOk(typeof o === "symbol"); +assert.notEqual(typeof o, "symbol"); +assert.notEqual(typeof typeof o, "symbol"); +typeof o === "string"; diff --git a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/expected.js b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/expected.js index 26a766f3d5..d2ef134ade 100644 --- a/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/expected.js +++ b/packages/babel-plugin-transform-es2015-typeof-symbol/test/fixtures/symbols/typeof/expected.js @@ -1,5 +1,9 @@ var s = Symbol("s"); -assert.ok((typeof s === "undefined" ? "undefined" : babelHelpers.typeof(s)) === "symbol"); -assert.equal(typeof s === "undefined" ? "undefined" : babelHelpers.typeof(s), "symbol"); +assert.ok(babelHelpers.typeof(s) === "symbol"); +assert.equal(babelHelpers.typeof(s), "symbol"); assert.equal(babelHelpers.typeof(babelHelpers.typeof(s.foo)), "symbol"); typeof s === "string"; +assert.isNotOk((typeof o === "undefined" ? "undefined" : babelHelpers.typeof(o)) === "symbol"); +assert.notEqual(typeof o === "undefined" ? "undefined" : babelHelpers.typeof(o), "symbol"); +assert.notEqual(babelHelpers.typeof(babelHelpers.typeof(o.foo)), "symbol"); +typeof o === "string";