diff --git a/packages/babel-helper-replace-supers/src/index.js b/packages/babel-helper-replace-supers/src/index.js index 2d24a92df7..58bfb0591d 100644 --- a/packages/babel-helper-replace-supers/src/index.js +++ b/packages/babel-helper-replace-supers/src/index.js @@ -134,11 +134,14 @@ const specHandlers = { }; const looseHandlers = { + memoize: specHandlers.memoize, + call: specHandlers.call, + get(superMember) { const { isStatic, superRef } = this; const { property, computed } = superMember.node; - let object; + let object; if (isStatic) { object = superRef ? t.cloneNode(superRef) @@ -152,18 +155,34 @@ const looseHandlers = { : t.memberExpression(t.identifier("Object"), t.identifier("prototype")); } - return t.memberExpression(object, property, computed); + let prop; + if (computed && memoized.has(property)) { + prop = t.cloneNode(memoized.get(property)); + } else { + prop = property; + } + + return t.memberExpression(object, prop, computed); }, set(superMember, value) { - // TODO https://github.com/babel/babel/pull/7553#issuecomment-381434519 - return t.assignmentExpression("=", this.get(superMember), value); - }, + const { property, computed } = superMember.node; - call(superMember, args) { - return t.callExpression( - t.memberExpression(this.get(superMember), t.identifier("call")), - [t.thisExpression(), ...args], + let prop; + if (computed && memoized.has(property)) { + prop = t.assignmentExpression( + "=", + t.cloneNode(memoized.get(property)), + property, + ); + } else { + prop = property; + } + + return t.assignmentExpression( + "=", + t.memberExpression(t.thisExpression(), prop, computed), + value, ); }, }; diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/exec.js new file mode 100644 index 0000000000..2e635915b7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/input.js new file mode 100644 index 0000000000..2e635915b7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/output.js new file mode 100644 index 0000000000..ae36d3d2a7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-data-defined-on-parent/output.js @@ -0,0 +1,50 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + var _proto = Base.prototype; + + _proto.test = function test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto2 = Obj.prototype; + + _proto2.call = function call() { + _Base.prototype.test.call(this, 1, 2, 3); + + _Base.prototype.test.call(this, 1, ...[2, 3]); + + _Base.prototype.test.call(this, ...[1, 2, 3]); + + return _Base.prototype.test.apply(this, arguments); + }; + + _proto2.test = function test() { + throw new Error("called"); + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/exec.js new file mode 100644 index 0000000000..c7139df28b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/exec.js @@ -0,0 +1,30 @@ +"use strict"; +class Base { + get test() { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + + return function(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/input.js new file mode 100644 index 0000000000..c7139df28b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/input.js @@ -0,0 +1,30 @@ +"use strict"; +class Base { + get test() { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + + return function(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/output.js new file mode 100644 index 0000000000..2824c04351 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-getter-defined-on-parent/output.js @@ -0,0 +1,60 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + get: function () { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + return function (...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.call = function call() { + _Base.prototype.test.call(this, 1, 2, 3); + + _Base.prototype.test.call(this, 1, ...[2, 3]); + + _Base.prototype.test.call(this, ...[1, 2, 3]); + + return _Base.prototype.test.apply(this, arguments); + }; + + _proto.test = function test() { + throw new Error("called"); + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/exec.js new file mode 100644 index 0000000000..8ff77f1411 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/exec.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/input.js new file mode 100644 index 0000000000..8ff77f1411 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/input.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/output.js new file mode 100644 index 0000000000..6f9f337e13 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-not-defined-on-parent/output.js @@ -0,0 +1,33 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.call = function call() { + return _Base.prototype.test.call(this); + }; + + _proto.test = function test() { + throw new Error("gobbledygook"); + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(() => { + obj.call(); // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/exec.js new file mode 100644 index 0000000000..184778853f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("gobbledygook"); + } +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/input.js new file mode 100644 index 0000000000..184778853f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("gobbledygook"); + } +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/output.js new file mode 100644 index 0000000000..a83c1b384c --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/call-semantics-setter-defined-on-parent/output.js @@ -0,0 +1,50 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + set: function (v) { + throw new Error("gobbledygook"); + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.call = function call() { + return _Base.prototype.test.call(this); + }; + + _proto.test = function test() { + throw new Error("gobbledygook"); + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(() => { + obj.call(); // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/exec.js new file mode 100644 index 0000000000..b68b503253 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/exec.js @@ -0,0 +1,23 @@ +"use strict"; +class Base { +} +Object.defineProperty(Base.prototype, 'test', { + value: 1, + writable: true, + configurable: true, +}); + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/input.js new file mode 100644 index 0000000000..1abe3f6b7f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/input.js @@ -0,0 +1,15 @@ +"use strict"; +class Base { +} +Base.prototype.test = 1; + +class Obj extends Base { + get() { + return super.test; + } +} +Obj.prototype.test = 2; + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/output.js new file mode 100644 index 0000000000..5a17f1cea7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-data-defined-on-parent/output.js @@ -0,0 +1,30 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +Base.prototype.test = 1; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.get = function get() { + return _Base.prototype.test; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Obj.prototype.test = 2; +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/exec.js new file mode 100644 index 0000000000..e9ebfb274a --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + get test() { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + return 1; + } +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/input.js new file mode 100644 index 0000000000..e9ebfb274a --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + get test() { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + return 1; + } +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/output.js new file mode 100644 index 0000000000..e68392944e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-getter-defined-on-parent/output.js @@ -0,0 +1,52 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + get: function () { + // This is incorrect according to the spec, + // but close enough for loose. + expect(this).toBe(Base.prototype); + return 1; + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.get = function get() { + return _Base.prototype.test; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/exec.js new file mode 100644 index 0000000000..ad5dc5806d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/exec.js @@ -0,0 +1,18 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/input.js new file mode 100644 index 0000000000..ad5dc5806d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/input.js @@ -0,0 +1,18 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/output.js new file mode 100644 index 0000000000..9f2e940a4b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-not-defined-on-parent/output.js @@ -0,0 +1,32 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.get = function get() { + return _Base.prototype.test; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/exec.js new file mode 100644 index 0000000000..f8fd1a8709 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/exec.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("called"); + } +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/input.js new file mode 100644 index 0000000000..f8fd1a8709 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/input.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("called"); + } +} + +class Obj extends Base { + get() { + return super.test; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/output.js new file mode 100644 index 0000000000..c6eae6269f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/get-semantics-setter-defined-on-parent/output.js @@ -0,0 +1,49 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + set: function (v) { + throw new Error("called"); + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.get = function get() { + return _Base.prototype.test; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.test).toBe(2); +expect(obj.get()).toBeUndefined(); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/exec.js new file mode 100644 index 0000000000..0c22e74295 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/exec.js @@ -0,0 +1,41 @@ +"use strict"; +class Base {} +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true, +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true, +}); + +let i = 0; +const proper = { + get prop() { + return i++; + }, +}; + +class Obj extends Base { + assign() { + super[proper.prop] += 1; + } + + assign2() { + super[i] += 1; + } +} + +const obj = new Obj(); + +obj.assign(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); + +obj.assign2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/input.js new file mode 100644 index 0000000000..0c22e74295 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/input.js @@ -0,0 +1,41 @@ +"use strict"; +class Base {} +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true, +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true, +}); + +let i = 0; +const proper = { + get prop() { + return i++; + }, +}; + +class Obj extends Base { + assign() { + super[proper.prop] += 1; + } + + assign2() { + super[i] += 1; + } +} + +const obj = new Obj(); + +obj.assign(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); + +obj.assign2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/output.js new file mode 100644 index 0000000000..ea392256b2 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-assign/output.js @@ -0,0 +1,59 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true +}); +let i = 0; +const proper = { + get prop() { + return i++; + } + +}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.assign = function assign() { + var _proper$prop; + + this[_proper$prop = proper.prop] = _Base.prototype[_proper$prop] + 1; + }; + + _proto.assign2 = function assign2() { + var _i; + + this[_i = i] = _Base.prototype[_i] + 1; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +obj.assign(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); +obj.assign2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/exec.js new file mode 100644 index 0000000000..c1761230f6 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/exec.js @@ -0,0 +1,41 @@ +"use strict"; +class Base {} +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true, +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true, +}); + +let i = 0; +const proper = { + get prop() { + return i++; + }, +}; + +class Obj extends Base { + update() { + super[proper.prop]++; + } + + update2() { + super[i]++; + } +} + +const obj = new Obj(); + +obj.update(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); + +obj.update2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/input.js new file mode 100644 index 0000000000..c1761230f6 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/input.js @@ -0,0 +1,41 @@ +"use strict"; +class Base {} +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true, +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true, +}); + +let i = 0; +const proper = { + get prop() { + return i++; + }, +}; + +class Obj extends Base { + update() { + super[proper.prop]++; + } + + update2() { + super[i]++; + } +} + +const obj = new Obj(); + +obj.update(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); + +obj.update2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/output.js new file mode 100644 index 0000000000..81e19c7b7e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/memoized-update/output.js @@ -0,0 +1,59 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +Object.defineProperty(Base.prototype, 0, { + value: 0, + writable: true, + configurable: true +}); +Object.defineProperty(Base.prototype, 1, { + value: 1, + writable: true, + configurable: true +}); +let i = 0; +const proper = { + get prop() { + return i++; + } + +}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.update = function update() { + var _proper$prop, _super$proper$prop; + + this[_proper$prop = proper.prop] = (_super$proper$prop = +_Base.prototype[_proper$prop]) + 1, _super$proper$prop; + }; + + _proto.update2 = function update2() { + var _i, _super$i; + + this[_i = i] = (_super$i = +_Base.prototype[_i]) + 1, _super$i; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +obj.update(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(1); +obj.update2(); +expect(i).toBe(1); +expect(obj[0]).toBe(1); +expect(obj[1]).toBe(2); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/options.json b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/options.json new file mode 100644 index 0000000000..a5decfd973 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/options.json @@ -0,0 +1,3 @@ +{ + "plugins": [["transform-classes", {"loose": true}]] +} diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/exec.js new file mode 100644 index 0000000000..c92b28377e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/exec.js @@ -0,0 +1,25 @@ +"use strict"; +class Base { +} +Object.defineProperty(Base.prototype, 'test', { + value: 1, + writable: true, + configurable: true, +}); + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/input.js new file mode 100644 index 0000000000..c92b28377e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/input.js @@ -0,0 +1,25 @@ +"use strict"; +class Base { +} +Object.defineProperty(Base.prototype, 'test', { + value: 1, + writable: true, + configurable: true, +}); + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/output.js new file mode 100644 index 0000000000..eeac9da0ae --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-data-defined-on-parent/output.js @@ -0,0 +1,40 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +Object.defineProperty(Base.prototype, 'test', { + value: 1, + writable: true, + configurable: true +}); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/exec.js new file mode 100644 index 0000000000..4980795f6e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/exec.js @@ -0,0 +1,32 @@ +"use strict"; +let called = false; +class Base { + get test() { + called = true; + return 1; + } +}; + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); + +// This is incorrect according to the spec, +// but close enough for loose. +// expect(() => { + expect(obj.set()).toBe(3); +// }).toThrow(); + +expect(called).toBe(false); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/input.js new file mode 100644 index 0000000000..4980795f6e --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/input.js @@ -0,0 +1,32 @@ +"use strict"; +let called = false; +class Base { + get test() { + called = true; + return 1; + } +}; + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); + +// This is incorrect according to the spec, +// but close enough for loose. +// expect(() => { + expect(obj.set()).toBe(3); +// }).toThrow(); + +expect(called).toBe(false); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/output.js new file mode 100644 index 0000000000..95b7323824 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-getter-defined-on-parent/output.js @@ -0,0 +1,61 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let called = false; + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + get: function () { + called = true; + return 1; + } + }]); + + return Base; +}(); + +; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); // This is incorrect according to the spec, +// but close enough for loose. +// expect(() => { + +expect(obj.set()).toBe(3); // }).toThrow(); + +expect(called).toBe(false); +expect(Base.prototype.test).toBe(1); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/exec.js new file mode 100644 index 0000000000..5a1625194c --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/exec.js @@ -0,0 +1,20 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/input.js new file mode 100644 index 0000000000..5a1625194c --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/input.js @@ -0,0 +1,20 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/output.js new file mode 100644 index 0000000000..9032cd8c5d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-data-on-obj/output.js @@ -0,0 +1,34 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/exec.js new file mode 100644 index 0000000000..57ce198e81 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/exec.js @@ -0,0 +1,27 @@ +"use strict"; +class Base { +} + +let called = false; +class Obj extends Base { + get test() { + called = true; + } + + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +// This is incorrect according to the spec, +// but close enough for loose. +// expect(obj.set()).toBe(3); +expect(() => { + obj.set(); +}).toThrow(); + +expect(called).toBe(false); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/input.js new file mode 100644 index 0000000000..57ce198e81 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/input.js @@ -0,0 +1,27 @@ +"use strict"; +class Base { +} + +let called = false; +class Obj extends Base { + get test() { + called = true; + } + + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +// This is incorrect according to the spec, +// but close enough for loose. +// expect(obj.set()).toBe(3); +expect(() => { + obj.set(); +}).toThrow(); + +expect(called).toBe(false); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/output.js new file mode 100644 index 0000000000..469af6ac4a --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-getter-on-obj/output.js @@ -0,0 +1,48 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = function Base() {}; + +let called = false; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _createClass(Obj, [{ + key: "test", + get: function () { + called = true; + } + }]); + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); // This is incorrect according to the spec, +// but close enough for loose. +// expect(obj.set()).toBe(3); + +expect(() => { + obj.set(); +}).toThrow(); +expect(called).toBe(false); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/exec.js new file mode 100644 index 0000000000..bf9d73d74d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/exec.js @@ -0,0 +1,15 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/input.js new file mode 100644 index 0000000000..bf9d73d74d --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/input.js @@ -0,0 +1,15 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/output.js new file mode 100644 index 0000000000..740f625c11 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-not-on-obj/output.js @@ -0,0 +1,29 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +let Base = function Base() {}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/exec.js new file mode 100644 index 0000000000..a9a09060bb --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/exec.js @@ -0,0 +1,25 @@ +"use strict"; +class Base { +} + +let value = 2; +class Obj extends Base { + set test(v) { + value = v; + } + + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); + +// This is incorrect according to the spec, +// but close enough for loose. +expect(value).toBe(3); + +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/input.js new file mode 100644 index 0000000000..a9a09060bb --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/input.js @@ -0,0 +1,25 @@ +"use strict"; +class Base { +} + +let value = 2; +class Obj extends Base { + set test(v) { + value = v; + } + + set() { + return super.test = 3; + } +} + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); + +// This is incorrect according to the spec, +// but close enough for loose. +expect(value).toBe(3); + +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/output.js new file mode 100644 index 0000000000..3fdea483c1 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-not-defined-on-parent-setter-on-obj/output.js @@ -0,0 +1,45 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = function Base() {}; + +let value = 2; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _createClass(Obj, [{ + key: "test", + set: function (v) { + value = v; + } + }]); + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBeUndefined(); // This is incorrect according to the spec, +// but close enough for loose. + +expect(value).toBe(3); +expect(obj.test).toBe(undefined); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/exec.js new file mode 100644 index 0000000000..62ed8391e6 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/exec.js @@ -0,0 +1,27 @@ +"use strict"; +let value = 1; +class Base { + set test(v) { + value = v; + } +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); +// todo +expect(value).toBe(1); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); +// todo +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/input.js new file mode 100644 index 0000000000..daaccdb5ef --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/input.js @@ -0,0 +1,34 @@ +"use strict"; +let value = 1; +class Base { + set test(v) { + value = v; + } +} + +class Obj extends Base { + set() { + return super.test = 3; + } +} +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true, +}); + +const obj = new Obj(); +expect(obj.set()).toBe(3); + +// This is incorrect according to the spec, +// but close enough for loose. +// expect(value).toBe(3); +expect(value).toBe(1); + +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); + +// This is incorrect according to the spec, +// but close enough for loose. +// expect(obj.test).toBe(2); +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/output.js new file mode 100644 index 0000000000..8cec605e4c --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set-loose/set-semantics-setter-defined-on-parent/output.js @@ -0,0 +1,60 @@ +"use strict"; + +function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let value = 1; + +let Base = +/*#__PURE__*/ +function () { + function Base() {} + + _createClass(Base, [{ + key: "test", + set: function (v) { + value = v; + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + return _Base.apply(this, arguments) || this; + } + + var _proto = Obj.prototype; + + _proto.set = function set() { + return this.test = 3; + }; + + _inheritsLoose(Obj, _Base); + + return Obj; +}(Base); + +Object.defineProperty(Obj.prototype, 'test', { + value: 2, + writable: true, + configurable: true +}); +const obj = new Obj(); +expect(obj.set()).toBe(3); // This is incorrect according to the spec, +// but close enough for loose. +// expect(value).toBe(3); + +expect(value).toBe(1); +expect(Base.prototype.test).toBeUndefined(); +expect(Obj.prototype.test).toBe(2); // This is incorrect according to the spec, +// but close enough for loose. +// expect(obj.test).toBe(2); + +expect(obj.test).toBe(3); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/exec.js new file mode 100644 index 0000000000..2e635915b7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/input.js new file mode 100644 index 0000000000..2e635915b7 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/output.js new file mode 100644 index 0000000000..dbb3a5192f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-data-defined-on-parent/output.js @@ -0,0 +1,75 @@ +"use strict"; + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } _setPrototypeOf(subClass.prototype, superClass && superClass.prototype); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +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); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() { + _classCallCheck(this, Base); + } + + _createClass(Base, [{ + key: "test", + value: function test(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + _classCallCheck(this, Obj); + + return _possibleConstructorReturn(this, _getPrototypeOf(Obj).apply(this, arguments)); + } + + _createClass(Obj, [{ + key: "call", + value: function call() { + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, 1, 2, 3); + + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, 1, ...[2, 3]); + + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, ...[1, 2, 3]); + + return _get(_getPrototypeOf(Obj.prototype), "test", this).apply(this, arguments); + } + }, { + key: "test", + value: function test() { + throw new Error("called"); + } + }]); + + _inherits(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/exec.js new file mode 100644 index 0000000000..53543b215b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/exec.js @@ -0,0 +1,27 @@ +"use strict"; +class Base { + get test() { + expect(this).toBe(obj); + return function(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/input.js new file mode 100644 index 0000000000..53543b215b --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/input.js @@ -0,0 +1,27 @@ +"use strict"; +class Base { + get test() { + expect(this).toBe(obj); + return function(...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } +} + +class Obj extends Base { + call() { + super.test(1, 2, 3); + super.test(1, ...[2, 3]); + super.test(...[1, 2, 3]); + return super.test(...arguments); + } + + test() { + throw new Error("called"); + } +} + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/output.js new file mode 100644 index 0000000000..a31f9975dd --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-getter-defined-on-parent/output.js @@ -0,0 +1,78 @@ +"use strict"; + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } _setPrototypeOf(subClass.prototype, superClass && superClass.prototype); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +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); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() { + _classCallCheck(this, Base); + } + + _createClass(Base, [{ + key: "test", + get: function () { + expect(this).toBe(obj); + return function (...args) { + expect(this).toBe(obj); + expect(args).toEqual([1, 2, 3]); + return 1; + }; + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + _classCallCheck(this, Obj); + + return _possibleConstructorReturn(this, _getPrototypeOf(Obj).apply(this, arguments)); + } + + _createClass(Obj, [{ + key: "call", + value: function call() { + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, 1, 2, 3); + + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, 1, ...[2, 3]); + + _get(_getPrototypeOf(Obj.prototype), "test", this).call(this, ...[1, 2, 3]); + + return _get(_getPrototypeOf(Obj.prototype), "test", this).apply(this, arguments); + } + }, { + key: "test", + value: function test() { + throw new Error("called"); + } + }]); + + _inherits(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(obj.call(1, 2, 3)).toBe(1); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/exec.js new file mode 100644 index 0000000000..8ff77f1411 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/exec.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/input.js new file mode 100644 index 0000000000..8ff77f1411 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/input.js @@ -0,0 +1,21 @@ +"use strict"; +class Base { +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/output.js new file mode 100644 index 0000000000..97fc2b487f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-not-defined-on-parent/output.js @@ -0,0 +1,57 @@ +"use strict"; + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } _setPrototypeOf(subClass.prototype, superClass && superClass.prototype); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +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); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +let Base = function Base() { + _classCallCheck(this, Base); +}; + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + _classCallCheck(this, Obj); + + return _possibleConstructorReturn(this, _getPrototypeOf(Obj).apply(this, arguments)); + } + + _createClass(Obj, [{ + key: "call", + value: function call() { + return _get(_getPrototypeOf(Obj.prototype), "test", this).call(this); + } + }, { + key: "test", + value: function test() { + throw new Error("gobbledygook"); + } + }]); + + _inherits(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(() => { + obj.call(); // Asser that this throws, but that it's not + // Obj.p.test's error that is thrown +}).toThrowError(TypeError); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/exec.js new file mode 100644 index 0000000000..184778853f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/exec.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("gobbledygook"); + } +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/input.js new file mode 100644 index 0000000000..184778853f --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/input.js @@ -0,0 +1,24 @@ +"use strict"; +class Base { + set test(v) { + throw new Error("gobbledygook"); + } +} + +class Obj extends Base { + call() { + return super.test(); + } + + test() { + throw new Error("gobbledygook"); + } +} + +const obj = new Obj(); +expect(() => { + obj.call(); + + // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError) diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/output.js new file mode 100644 index 0000000000..cadc3fc0b5 --- /dev/null +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/call-semantics-setter-defined-on-parent/output.js @@ -0,0 +1,70 @@ +"use strict"; + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } _setPrototypeOf(subClass.prototype, superClass && superClass.prototype); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +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); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +let Base = +/*#__PURE__*/ +function () { + function Base() { + _classCallCheck(this, Base); + } + + _createClass(Base, [{ + key: "test", + set: function (v) { + throw new Error("gobbledygook"); + } + }]); + + return Base; +}(); + +let Obj = +/*#__PURE__*/ +function (_Base) { + function Obj() { + _classCallCheck(this, Obj); + + return _possibleConstructorReturn(this, _getPrototypeOf(Obj).apply(this, arguments)); + } + + _createClass(Obj, [{ + key: "call", + value: function call() { + return _get(_getPrototypeOf(Obj.prototype), "test", this).call(this); + } + }, { + key: "test", + value: function test() { + throw new Error("gobbledygook"); + } + }]); + + _inherits(Obj, _Base); + + return Obj; +}(Base); + +const obj = new Obj(); +expect(() => { + obj.call(); // Asser that this throws, but that it's not + // a gobbledygook error that is thrown +}).toThrowError(TypeError); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js index 94d8d54a9c..f8fd1a8709 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js @@ -1,7 +1,7 @@ "use strict"; class Base { set test(v) { - throw new Error("not called"); + throw new Error("called"); } } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js index 94d8d54a9c..f8fd1a8709 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js @@ -1,7 +1,7 @@ "use strict"; class Base { set test(v) { - throw new Error("not called"); + throw new Error("called"); } } diff --git a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js index e13df74d89..45b558114a 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js @@ -30,7 +30,7 @@ function () { _createClass(Base, [{ key: "test", set: function (v) { - throw new Error("not called"); + throw new Error("called"); } }]); diff --git a/packages/babel-plugin-transform-classes/test/fixtures/loose/accessing-super-class/output.js b/packages/babel-plugin-transform-classes/test/fixtures/loose/accessing-super-class/output.js index d2dc86f73b..1c0a333441 100644 --- a/packages/babel-plugin-transform-classes/test/fixtures/loose/accessing-super-class/output.js +++ b/packages/babel-plugin-transform-classes/test/fixtures/loose/accessing-super-class/output.js @@ -4,7 +4,7 @@ function (_Foo) { "use strict"; function Test() { - var _Foo$prototype$test, _Foo$prototype$test2; + var _Foo$prototype$test; var _this; @@ -16,9 +16,9 @@ function (_Foo) { _this = _Foo.apply(this, arguments) || this; _this = _Foo.call.apply(_Foo, [this, "test"].concat(Array.prototype.slice.call(arguments))) || this; - (_Foo$prototype$test = _Foo.prototype.test).call.apply(_Foo$prototype$test, [babelHelpers.assertThisInitialized(_this)].concat(Array.prototype.slice.call(arguments))); + _Foo.prototype.test.apply(babelHelpers.assertThisInitialized(_this), arguments); - (_Foo$prototype$test2 = _Foo.prototype.test).call.apply(_Foo$prototype$test2, [babelHelpers.assertThisInitialized(_this), "test"].concat(Array.prototype.slice.call(arguments))); + (_Foo$prototype$test = _Foo.prototype.test).call.apply(_Foo$prototype$test, [babelHelpers.assertThisInitialized(_this), "test"].concat(Array.prototype.slice.call(arguments))); return _this; } diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js index 74b5f59f94..4c720a33e8 100644 --- a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js +++ b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/exec.js @@ -1,7 +1,7 @@ "use strict"; const Base = { set test(v) { - throw new Error("not called"); + throw new Error("called"); } }; diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js index 74b5f59f94..4c720a33e8 100644 --- a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js +++ b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/input.js @@ -1,7 +1,7 @@ "use strict"; const Base = { set test(v) { - throw new Error("not called"); + throw new Error("called"); } }; diff --git a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js index dda72efc33..a764ffde6a 100644 --- a/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js +++ b/packages/babel-plugin-transform-object-super/test/fixtures/get-set/get-semantics-setter-defined-on-parent/output.js @@ -10,7 +10,7 @@ function _getPrototypeOf(o) { _getPrototypeOf = Object.getPrototypeOf || functio const Base = { set test(v) { - throw new Error("not called"); + throw new Error("called"); } };