diff --git a/packages/babel-helper-replace-supers/src/index.js b/packages/babel-helper-replace-supers/src/index.js index 7fddb8c5a4..0e4a4d68ef 100644 --- a/packages/babel-helper-replace-supers/src/index.js +++ b/packages/babel-helper-replace-supers/src/index.js @@ -5,46 +5,53 @@ import * as t from "@babel/types"; // ✌️ const HARDCORE_THIS_REF = new WeakSet(); -function isIllegalBareSuper(node, parent) { - if (!t.isSuper(node)) return false; - if (t.isMemberExpression(parent, { computed: false })) return false; - if (t.isCallExpression(parent, { callee: node })) return false; - return true; -} - -function isMemberExpressionSuper(node) { - return t.isMemberExpression(node) && t.isSuper(node.object); -} - /** * Creates an expression which result is the proto of objectRef. - * Uses CLASS.__proto__ first for InternetExplorer <= 10 support * * @example isStatic === true * - * CLASS.__proto__ || Object.getPrototypeOf(CLASS) + * helpers.getPrototypeOf(CLASS) * * @example isStatic === false * - * CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype) + * helpers.getPrototypeOf(CLASS.prototype) */ function getPrototypeOfExpression(objectRef, isStatic, file) { + objectRef = t.cloneNode(objectRef); const targetRef = isStatic ? objectRef : t.memberExpression(objectRef, t.identifier("prototype")); - return t.callExpression(file.addHelper("getPrototypeOf"), [ - t.cloneNode(targetRef), - ]); + return t.callExpression(file.addHelper("getPrototypeOf"), [targetRef]); } const visitor = { Function(path) { - if (!path.isArrowFunctionExpression()) path.skip(); + if (path.isMethod()) return; + if (path.isArrowFunctionExpression()) return; + path.skip(); }, - ClassProperty(path) { + Method(path, state) { + // Don't traverse ClassMethod's body + path.skip(); + + // We do have to traverse the key, since it's evaluated in the outer class + // context. + if (path.node.computed) { + path.get("key").traverse(visitor, state); + } + }, + + "ClassProperty|ClassPrivateProperty"(path, state) { + // Don't traverse the ClassProp's value. if (!path.node.static) path.skip(); + + // We do have to traverse the key, since it's evaluated in the outer class + // context. + if (path.node.computed) { + path.get("key").traverse(visitor, state); + } }, ReturnStatement(path, state) { @@ -59,33 +66,15 @@ const visitor = { } }, - enter(path, state) { - let callback = state.specHandle; - if (state.isLoose) callback = state.looseHandle; + Super(path, state) { + state.hasSuper = true; - const isBareSuper = path.isCallExpression() && path.get("callee").isSuper(); - - const result = callback.call(state, path); - - if (result) { - state.hasSuper = true; - } - - if (isBareSuper) { - state.bareSupers.push(path); - } - - if (result === true) { - path.requeue(); - } - - if (result !== true && result) { - if (Array.isArray(result)) { - path.replaceWithMultiple(result); - } else { - path.replaceWith(result); - } + const { node, parentPath } = path; + if (parentPath.isCallExpression({ callee: node })) { + state.bareSupers.add(parentPath); + return; } + state[state.isLoose ? "looseHandle" : "specHandle"](path); }, }; @@ -104,7 +93,7 @@ export default class ReplaceSupers { this.file = opts.file; this.opts = opts; - this.bareSupers = []; + this.bareSupers = new Set(); this.returns = []; this.thises = []; } @@ -141,8 +130,7 @@ export default class ReplaceSupers { * * @example * - * _set(CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", - * this, isStrict) + * _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this, isStrict) * */ @@ -166,7 +154,7 @@ export default class ReplaceSupers { * * @example * - * _get(CLASS.prototype.__proto__ || Object.getPrototypeOf(CLASS.prototype), "METHOD", this) + * _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) * */ @@ -190,144 +178,146 @@ export default class ReplaceSupers { this.methodPath.traverse(visitor, this); } - getLooseSuperProperty(id: Object, parent: Object) { - const methodNode = this.methodNode; - const superRef = this.superRef || t.identifier("Function"); + getLooseSuperProperty(path) { + const { isStatic, superRef } = this; - if (parent.property === id) { - return; - } else if (t.isCallExpression(parent, { callee: id })) { - return; - } else if (t.isMemberExpression(parent) && !methodNode.static) { - // super.test -> objectRef.prototype.test - return t.memberExpression( - t.cloneNode(superRef), - t.identifier("prototype"), - ); + let object; + if (isStatic) { + object = superRef + ? t.cloneNode(superRef) + : t.memberExpression( + t.identifier("Function"), + t.identifier("prototype"), + ); } else { - return t.cloneNode(superRef); + object = superRef + ? t.memberExpression(t.cloneNode(superRef), t.identifier("prototype")) + : t.memberExpression(t.identifier("Object"), t.identifier("prototype")); } + path.get("object").replaceWith(object); } looseHandle(path: NodePath) { - const node = path.node; - if (path.isSuper()) { - return this.getLooseSuperProperty(node, path.parent); - } else if (path.isCallExpression()) { - const callee = node.callee; - if (!t.isMemberExpression(callee)) return; - if (!t.isSuper(callee.object)) return; + const { node, parentPath } = path; - // super.test(); -> objectRef.prototype.MethodName.call(this); - t.appendToMemberExpression(callee, t.identifier("call")); - node.arguments.unshift(t.thisExpression()); - return true; + // super.test + if (parentPath.isMemberExpression({ object: node })) { + this.getLooseSuperProperty(parentPath); + } + + // super.test() + // though, it's SUPER.prototype.test() after the above. + const grandParentPath = parentPath.parentPath; + const callee = parentPath.node; + if (grandParentPath.isCallExpression({ callee })) { + grandParentPath + .get("callee") + .replaceWith(t.memberExpression(callee, t.identifier("call"))); + grandParentPath.node.arguments.unshift(t.thisExpression()); } } - specHandleAssignmentExpression(ref, path, node) { - if (node.operator === "=") { + specHandleAssignmentExpression(path) { + const { node } = path; + const { operator } = node; + const { computed, property } = node.left; + if (operator === "=") { // super.name = "val" // to - // _set(Object.getPrototypeOf(objectRef.prototype), "name", this, isStrict); - return this.setSuperProperty( - node.left.property, + // _set(Object.getPrototypeOf(CLASS.prototype), "name", this); + const setter = this.setSuperProperty( + property, node.right, - node.left.computed, + computed, path.isInStrictMode(), ); - } else { - // super.age += 2 - // to - // let _ref = super.age; super.age = _ref + 2; - ref = ref || path.scope.generateUidIdentifier("ref"); - return [ - t.variableDeclaration("var", [ - t.variableDeclarator(t.cloneNode(ref), t.cloneNode(node.left)), - ]), - t.expressionStatement( - t.assignmentExpression( - "=", - node.left, - t.binaryExpression( - node.operator.slice(0, -1), - t.cloneNode(ref), - node.right, - ), - ), - ), - ]; + return [setter]; } + + // super.age += 2; + // to + // _set( + // Object.getPrototypeOf(CLASS.prototype), + // "name", + // _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this) + 2, + // this, + // true, + // ); + // TODO this needs cleanup. Should be a single proto lookup + const ref = path.scope.generateDeclaredUidIdentifier("ref"); + const setter = this.setSuperProperty( + property, + t.binaryExpression(operator.slice(0, -1), t.cloneNode(ref), node.right), + computed, + path.isInStrictMode(), + ); + return [ + t.assignmentExpression( + "=", + t.cloneNode(ref), + this.getSuperProperty(property, computed), + ), + setter, + ]; } specHandle(path: NodePath) { - let property; - let computed; - let args; + const { node, parentPath } = path; + const grandParentPath = parentPath.parentPath; + let parent = parentPath.node; - const parent = path.parent; - const node = path.node; - - if (isIllegalBareSuper(node, parent)) { - throw path.buildCodeFrameError("Illegal use of bare super"); - } - - if (t.isCallExpression(node)) { - const callee = node.callee; - if (t.isSuper(callee)) { - return; - } else if (isMemberExpressionSuper(callee)) { - // super.test(); - // to - // _get(Object.getPrototypeOf(objectRef.prototype), "test", this).call(this); - property = callee.property; - computed = callee.computed; - args = node.arguments; - } - } else if (t.isMemberExpression(node) && t.isSuper(node.object)) { - // super.name; - // to - // _get(Object.getPrototypeOf(objectRef.prototype), "name", this); - property = node.property; - computed = node.computed; - } else if ( - t.isUpdateExpression(node) && - isMemberExpressionSuper(node.argument) - ) { - const binary = t.assignmentExpression( - node.operator[0] + "=", - node.argument, + if (grandParentPath.isUpdateExpression({ argument: parent })) { + const { operator, prefix } = grandParentPath.node; + const assignment = t.assignmentExpression( + operator[0] + "=", + parent, t.numericLiteral(1), ); - if (node.prefix) { - // ++super.foo; - // to - // super.foo += 1; - return this.specHandleAssignmentExpression(null, path, binary); - } else { - // super.foo++; - // to - // let _ref = super.foo; super.foo = _ref + 1; - const ref = path.scope.generateUidIdentifier("ref"); - return this.specHandleAssignmentExpression(ref, path, binary).concat( - t.expressionStatement(ref), - ); + grandParentPath.replaceWith(assignment); + + // ++super.foo; + // to + // _ref = Number(super.foo), super.foo = _ref + 1 + // super.foo++; + // to + // _ref = Number(super.foo), super.foo = _ref + 1, _ref + const nodes = this.specHandleAssignmentExpression(grandParentPath); + const [first] = nodes; + first.right = t.callExpression(t.identifier("Number"), [first.right]); + + // Postfix returns the old value, not the new. + if (!prefix) { + nodes.push(t.cloneNode(first.left)); } - } else if ( - t.isAssignmentExpression(node) && - isMemberExpressionSuper(node.left) - ) { - return this.specHandleAssignmentExpression(null, path, node); + grandParentPath.replaceWith(t.sequenceExpression(nodes)); + return; } - if (!property) return; + if (grandParentPath.isAssignmentExpression({ left: parent })) { + grandParentPath.replaceWithMultiple( + this.specHandleAssignmentExpression(grandParentPath), + ); + return; + } - const superProperty = this.getSuperProperty(property, computed); + if (parentPath.isMemberExpression({ object: node })) { + // super.name; + // to + // _get(Object.getPrototypeOf(CLASS.prototype), "name", this); + const { node } = parentPath; + const { computed, property } = node; - if (args) { - return this.optimiseCall(superProperty, args); - } else { - return superProperty; + parent = this.getSuperProperty(property, computed); + parentPath.replaceWith(parent); + } + + if (grandParentPath.isCallExpression({ callee: parent })) { + // _get(Object.getPrototypeOf(CLASS.prototype), "test", this)(); + // to + // _get(Object.getPrototypeOf(CLASS.prototype), "test", this).call(this); + const call = this.optimiseCall(parent, grandParentPath.node.arguments); + grandParentPath.replaceWith(call); + return; } } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/options.json new file mode 100644 index 0000000000..e0264b98ba --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", "proposal-class-properties", "transform-classes"] +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/exec.js new file mode 100644 index 0000000000..5a2a7dab94 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/exec.js @@ -0,0 +1,22 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + class Inner { + [super()] = "hello"; + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/input.js new file mode 100644 index 0000000000..5a2a7dab94 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/input.js @@ -0,0 +1,22 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + class Inner { + [super()] = "hello"; + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js new file mode 100644 index 0000000000..e94ddfeba6 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js @@ -0,0 +1,41 @@ +"use strict"; + +let Hello = function Hello() { + babelHelpers.classCallCheck(this, Hello); + return { + toString() { + return 'hello'; + } + + }; +}; + +let Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this; + + babelHelpers.classCallCheck(this, Outer); + + var _this2 = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); + + let Inner = function Inner() { + babelHelpers.classCallCheck(this, Inner); + Object.defineProperty(this, _this2, { + configurable: true, + enumerable: true, + writable: true, + value: "hello" + }); + }; + + return babelHelpers.possibleConstructorReturn(_this, new Inner()); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/exec.js new file mode 100644 index 0000000000..7359814f19 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/exec.js @@ -0,0 +1,19 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + class Inner { + [super.toString()] = 'hello'; + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/input.js new file mode 100644 index 0000000000..7359814f19 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/input.js @@ -0,0 +1,19 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + class Inner { + [super.toString()] = 'hello'; + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js new file mode 100644 index 0000000000..0aa59affa5 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js @@ -0,0 +1,48 @@ +"use strict"; + +let Hello = +/*#__PURE__*/ +function () { + function Hello() { + babelHelpers.classCallCheck(this, Hello); + } + + babelHelpers.createClass(Hello, [{ + key: "toString", + value: function toString() { + return 'hello'; + } + }]); + return Hello; +}(); + +let Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this; + + babelHelpers.classCallCheck(this, Outer); + _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); + + var _babelHelpers$get$cal = babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this)).call(_this); + + let Inner = function Inner() { + babelHelpers.classCallCheck(this, Inner); + Object.defineProperty(this, _babelHelpers$get$cal, { + configurable: true, + enumerable: true, + writable: true, + value: 'hello' + }); + }; + + return babelHelpers.possibleConstructorReturn(_this, new Inner()); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello, 'hello'); diff --git a/packages/babel-plugin-transform-classes/src/transformClass.js b/packages/babel-plugin-transform-classes/src/transformClass.js index b6276f1444..125fdf7519 100644 --- a/packages/babel-plugin-transform-classes/src/transformClass.js +++ b/packages/babel-plugin-transform-classes/src/transformClass.js @@ -57,7 +57,7 @@ export default function transformClass( instancePropRefs: {}, staticPropBody: [], body: [], - bareSupers: [], + bareSupers: new Set(), superThises: [], pushedConstructor: false, pushedInherits: false, @@ -388,7 +388,7 @@ export default function transformClass( path.traverse(findThisesVisitor); - let guaranteedSuperBeforeFinish = !!classState.bareSupers.length; + let guaranteedSuperBeforeFinish = !!classState.bareSupers.size; const superRef = classState.superName || t.identifier("Function"); let thisRef = function() { diff --git a/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/input.js b/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/input.js index 696f6b86e8..46317d841c 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/input.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/input.js @@ -9,12 +9,12 @@ class ColorPoint extends Point { super(); this.x = 2; super.x = 3; - assert.equal(this.x, 3) // A - assert.equal(super.x, undefined) // B + assert.equal(this.x, 3); // A + assert.equal(super.x, undefined); // B } m() { - this.getX() + this.getX(); } } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/output.js b/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/output.js index a76710135f..bb87d170a0 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/regression/5769/output.js @@ -29,7 +29,7 @@ function (_Point) { babelHelpers.classCallCheck(this, ColorPoint); _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(ColorPoint).call(this)); _this.x = 2; - babelHelpers.set(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", 3, _this, true); + babelHelpers.set(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", 3, _this, true) assert.equal(_this.x, 3); // A assert.equal(babelHelpers.get(babelHelpers.getPrototypeOf(ColorPoint.prototype), "x", babelHelpers.assertThisInitialized(_this)), undefined); // B diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/exec.js new file mode 100644 index 0000000000..4dcb62d99f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + class Inner { + [super()]() { + return 'hello'; + } + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/input.js new file mode 100644 index 0000000000..4dcb62d99f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + class Inner { + [super()]() { + return 'hello'; + } + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js new file mode 100644 index 0000000000..744cd7d4b4 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-call-in-key/output.js @@ -0,0 +1,47 @@ +"use strict"; + +var Hello = function Hello() { + babelHelpers.classCallCheck(this, Hello); + return { + toString() { + return 'hello'; + } + + }; +}; + +var Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this2 = this; + + var _this; + + babelHelpers.classCallCheck(this, Outer); + + var Inner = + /*#__PURE__*/ + function () { + function Inner() { + babelHelpers.classCallCheck(this, Inner); + } + + babelHelpers.createClass(Inner, [{ + key: _this = babelHelpers.possibleConstructorReturn(_this2, babelHelpers.getPrototypeOf(Outer).call(_this2)), + value: function value() { + return 'hello'; + } + }]); + return Inner; + }(); + + return babelHelpers.possibleConstructorReturn(_this, new Inner()); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/exec.js new file mode 100644 index 0000000000..e6b8583a0b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/exec.js @@ -0,0 +1,21 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + class Inner { + [super.toString()]() { + return 'hello'; + } + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/input.js new file mode 100644 index 0000000000..e6b8583a0b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/input.js @@ -0,0 +1,21 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + class Inner { + [super.toString()]() { + return 'hello'; + } + } + + return new Inner(); + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js new file mode 100644 index 0000000000..237547f2f9 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-class-super-property-in-key/output.js @@ -0,0 +1,54 @@ +"use strict"; + +var Hello = +/*#__PURE__*/ +function () { + function Hello() { + babelHelpers.classCallCheck(this, Hello); + } + + babelHelpers.createClass(Hello, [{ + key: "toString", + value: function toString() { + return 'hello'; + } + }]); + return Hello; +}(); + +var Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this2 = this; + + var _this; + + babelHelpers.classCallCheck(this, Outer); + _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); + + var Inner = + /*#__PURE__*/ + function () { + function Inner() { + babelHelpers.classCallCheck(this, Inner); + } + + babelHelpers.createClass(Inner, [{ + key: babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this2)).call(_this2), + value: function value() { + return 'hello'; + } + }]); + return Inner; + }(); + + return babelHelpers.possibleConstructorReturn(_this, new Inner()); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/exec.js new file mode 100644 index 0000000000..2140b943f9 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + const Inner = { + [super()]() { + return 'hello'; + }, + }; + + return Inner; + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/input.js new file mode 100644 index 0000000000..2140b943f9 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Hello { + constructor() { + return { + toString() { + return 'hello'; + }, + }; + } +} + +class Outer extends Hello { + constructor() { + const Inner = { + [super()]() { + return 'hello'; + }, + }; + + return Inner; + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/output.js new file mode 100644 index 0000000000..362b5cc2d4 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-call-in-key/output.js @@ -0,0 +1,34 @@ +"use strict"; + +var Hello = function Hello() { + babelHelpers.classCallCheck(this, Hello); + return { + toString() { + return 'hello'; + } + + }; +}; + +var Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this; + + babelHelpers.classCallCheck(this, Outer); + var Inner = { + [_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this))]() { + return 'hello'; + } + + }; + return babelHelpers.possibleConstructorReturn(_this, Inner); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/exec.js new file mode 100644 index 0000000000..0587f1b0f8 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/exec.js @@ -0,0 +1,21 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + const Inner = { + [super.toString()]() { + return 'hello'; + }, + }; + + return Inner; + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/input.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/input.js new file mode 100644 index 0000000000..0587f1b0f8 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/input.js @@ -0,0 +1,21 @@ +"use strict"; +class Hello { + toString() { + return 'hello'; + } +} + +class Outer extends Hello { + constructor() { + super(); + const Inner = { + [super.toString()]() { + return 'hello'; + }, + }; + + return Inner; + } +} + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/output.js b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/output.js new file mode 100644 index 0000000000..1afb4897da --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/spec/nested-object-super-property-in-key/output.js @@ -0,0 +1,41 @@ +"use strict"; + +var Hello = +/*#__PURE__*/ +function () { + function Hello() { + babelHelpers.classCallCheck(this, Hello); + } + + babelHelpers.createClass(Hello, [{ + key: "toString", + value: function toString() { + return 'hello'; + } + }]); + return Hello; +}(); + +var Outer = +/*#__PURE__*/ +function (_Hello) { + babelHelpers.inherits(Outer, _Hello); + + function Outer() { + var _this; + + babelHelpers.classCallCheck(this, Outer); + _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); + var Inner = { + [babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(this)).call(this)]() { + return 'hello'; + } + + }; + return babelHelpers.possibleConstructorReturn(_this, Inner); + } + + return Outer; +}(Hello); + +assert.equal(new Outer().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-exponentiation-operator/test/fixtures/regression/4349/output.js b/packages/babel-plugin-transform-exponentiation-operator/test/fixtures/regression/4349/output.js index d573f7bbe9..67759e662b 100644 --- a/packages/babel-plugin-transform-exponentiation-operator/test/fixtures/regression/4349/output.js +++ b/packages/babel-plugin-transform-exponentiation-operator/test/fixtures/regression/4349/output.js @@ -1,13 +1,13 @@ var _obj; +function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } + function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); } function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } - function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); } diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/exec.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/exec.js new file mode 100644 index 0000000000..f3eef218ab --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/exec.js @@ -0,0 +1,21 @@ +"use strict"; +const Hello = { + toString() { + return 'hello'; + } +}; + +const Outer = { + constructor() { + class Inner { + [super.toString()]() { + return 'hello'; + } + } + + return new Inner(); + } +}; +Object.setPrototypeOf(Outer, Hello); + +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/input.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/input.js new file mode 100644 index 0000000000..f3eef218ab --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/input.js @@ -0,0 +1,21 @@ +"use strict"; +const Hello = { + toString() { + return 'hello'; + } +}; + +const Outer = { + constructor() { + class Inner { + [super.toString()]() { + return 'hello'; + } + } + + return new Inner(); + } +}; +Object.setPrototypeOf(Outer, Hello); + +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/output.js new file mode 100644 index 0000000000..1696ec25b1 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-class-super-property-in-key/output.js @@ -0,0 +1,23 @@ +"use strict"; + +var _obj; + +const Hello = { + toString: function () { + return 'hello'; + } +}; +const Outer = _obj = { + constructor: function () { + class Inner { + [babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "toString", this).call(this)]() { + return 'hello'; + } + + } + + return new Inner(); + } +}; +Object.setPrototypeOf(Outer, Hello); +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/exec.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/exec.js new file mode 100644 index 0000000000..632490b242 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/exec.js @@ -0,0 +1,21 @@ +"use strict"; +const Hello = { + toString() { + return 'hello'; + } +}; + +const Outer = { + constructor() { + const Inner = { + [super.toString()]() { + return 'hello'; + }, + }; + + return Inner; + } +}; +Object.setPrototypeOf(Outer, Hello); + +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/input.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/input.js new file mode 100644 index 0000000000..632490b242 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/input.js @@ -0,0 +1,21 @@ +"use strict"; +const Hello = { + toString() { + return 'hello'; + } +}; + +const Outer = { + constructor() { + const Inner = { + [super.toString()]() { + return 'hello'; + }, + }; + + return Inner; + } +}; +Object.setPrototypeOf(Outer, Hello); + +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/output.js new file mode 100644 index 0000000000..c843f1582d --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/nested-object-super-property-in-key/output.js @@ -0,0 +1,21 @@ +"use strict"; + +var _obj; + +const Hello = { + toString: function () { + return 'hello'; + } +}; +const Outer = _obj = { + constructor: function () { + const Inner = { + [babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "toString", this).call(this)]: function () { + return 'hello'; + } + }; + return Inner; + } +}; +Object.setPrototypeOf(Outer, Hello); +assert.equal(Outer.constructor().hello(), 'hello'); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-exponentiation/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-exponentiation/output.js index d5ae0060ee..cdb11fd275 100644 --- a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-exponentiation/output.js +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-exponentiation/output.js @@ -1,13 +1,13 @@ var _obj; +function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } + function set(target, property, value, receiver) { if (typeof Reflect !== "undefined" && Reflect.set) { set = Reflect.set; } else { set = function set(target, property, value, receiver) { var base = _superPropBase(target, property); var desc; if (base) { desc = Object.getOwnPropertyDescriptor(base, property); if (desc.set) { desc.set.call(receiver, value); return true; } else if (!desc.writable) { return false; } } desc = Object.getOwnPropertyDescriptor(receiver, property); if (desc) { if (!desc.writable) { return false; } desc.value = value; Object.defineProperty(receiver, property, desc); } else { _defineProperty(receiver, property, value); } return true; }; } return set(target, property, value, receiver); } function _set(target, property, value, receiver, isStrict) { const s = set(target, property, value, receiver || target); if (!s && isStrict) { throw new Error('failed to set property'); } return value; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } -function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } - function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || function _getPrototypeOf(o) { return o.__proto__; }; return _getPrototypeOf(o); } diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/exec.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/exec.js new file mode 100644 index 0000000000..c246dd3e5e --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/exec.js @@ -0,0 +1,15 @@ +var Base = { + test: '1', +}; + +var obj = { + bar() { + return super.test++; + } +}; +Object.setPrototypeOf(obj, Base); + +assert.strictEqual(obj.bar(), 1); +assert.strictEqual(Base.test, '1'); +// TODO(jridgewell): Post #7687, uncomment this. +// assert.strictEqual(obj.test, 2); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/input.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/input.js new file mode 100644 index 0000000000..000e2910e5 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/input.js @@ -0,0 +1,14 @@ +var Base = { + test: '1', +}; + +var obj = { + bar() { + return super.test++; + } +}; +Object.setPrototypeOf(obj, Base); + +assert.strictEqual(obj.bar(), 1); +assert.strictEqual(Base.test, '1'); +assert.strictEqual(obj.test, 2); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/output.js new file mode 100644 index 0000000000..e0a624ee19 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-postfix/output.js @@ -0,0 +1,16 @@ +var _obj; + +var Base = { + test: '1' +}; +var obj = _obj = { + bar: function () { + var _ref; + + return _ref = Number(babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this)), babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", _ref + 1, this, false), _ref; + } +}; +Object.setPrototypeOf(obj, Base); +assert.strictEqual(obj.bar(), 1); +assert.strictEqual(Base.test, '1'); +assert.strictEqual(obj.test, 2); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/exec.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/exec.js new file mode 100644 index 0000000000..b58c0b9b8c --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/exec.js @@ -0,0 +1,15 @@ +var Base = { + test: '1', +}; + +var obj = { + bar() { + return ++super.test; + } +}; +Object.setPrototypeOf(obj, Base); + +assert.strictEqual(obj.bar(), 2); +assert.strictEqual(Base.test, '1'); +// TODO(jridgewell): Post #7687, uncomment this. +// assert.strictEqual(obj.test, 2); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/input.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/input.js new file mode 100644 index 0000000000..723f0eecda --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/input.js @@ -0,0 +1,14 @@ +var Base = { + test: '1', +}; + +var obj = { + bar() { + return ++super.test; + } +}; +Object.setPrototypeOf(obj, Base); + +assert.strictEqual(obj.bar(), 2); +assert.strictEqual(Base.test, '1'); +assert.strictEqual(obj.test, 2); diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/output.js new file mode 100644 index 0000000000..ecaa02b050 --- /dev/null +++ b/packages/babel-plugin-transform-object-super/test/fixtures/object-super/super-increment-prefix/output.js @@ -0,0 +1,16 @@ +var _obj; + +var Base = { + test: '1' +}; +var obj = _obj = { + bar: function () { + var _ref; + + return _ref = Number(babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this)), babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", _ref + 1, this, false); + } +}; +Object.setPrototypeOf(obj, Base); +assert.strictEqual(obj.bar(), 2); +assert.strictEqual(Base.test, '1'); +assert.strictEqual(obj.test, 2);