#![feature(test)] use swc_common::chain; use swc_ecma_parser::{EsConfig, Syntax, TsConfig}; use swc_ecma_transforms::{ compat::{ es2015::{arrow, block_scoping, function_name, Classes}, es2016::exponentation, es2017::async_to_generator, es2020::class_properties, es3::ReservedWord, }, proposals::decorators, resolver, typescript, }; use swc_ecma_visit::Fold; #[macro_use] mod common; fn ts() -> Syntax { Syntax::Typescript(TsConfig { ..Default::default() }) } fn syntax() -> Syntax { Syntax::Es(EsConfig { class_private_props: true, class_props: true, ..Default::default() }) } fn tr() -> impl Fold { chain!( resolver(), function_name(), class_properties(), Classes::default(), block_scoping(), ReservedWord { preserve_import: false }, ) } test!( syntax(), |_| tr(), public_static_infer_name, r#" var Foo = class { static num = 0; } "#, r#" var Foo = function() { var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); }; _defineProperty(Foo, 'num', 0); return Foo; }(); "# ); test_exec!( syntax(), |_| tr(), public_call_exec, r#" class Foo { foo = function() { return this; } test(other) { return [this.foo(), other.foo()]; } } const f = new Foo; const o = new Foo; const test = f.test(o); expect(test[0]).toBe(f); expect(test[1]).toBe(o); "# ); test!( syntax(), |_| tr(), public_instance_computed, r#" function test(x) { class F { [x] = 1; constructor() {} } x = 'deadbeef'; expect(new F().foo).toBe(1); x = 'wrong'; expect(new F().foo).toBe(1); } test('foo'); "#, r#" function test(x) { var _x = x; var F = function F() { 'use strict'; _classCallCheck(this, F); _defineProperty(this, _x, 1); }; x = 'deadbeef'; expect(new F().foo).toBe(1); x = 'wrong'; expect(new F().foo).toBe(1); } test('foo'); "# ); test!( syntax(), |_| tr(), public_super_statement, r#" class Foo extends Bar { bar = "foo"; constructor() { super(); } } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _defineProperty(_assertThisInitialized(_this), "bar", "foo"); return _this; } return Foo; }(Bar); "# ); test!( syntax(), |_| tr(), private_foobar, r#" class Child extends Parent { constructor() { super(); } #scopedFunctionWithThis = () => { this.name = {}; } } "#, r#" var Child = /*#__PURE__*/ function (Parent) { 'use strict'; _inherits(Child, Parent); function Child() { _classCallCheck(this, Child); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(Child).call(this)); _scopedFunctionWithThis.set(_assertThisInitialized(_this), { writable: true, value: () => { _this.name = {}; } }); return _this; } return Child; }(Parent); var _scopedFunctionWithThis = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_call_exec, r#" class Foo { #foo = function() { return this; } test(other) { return [this.#foo(), other.#foo()]; } } const f = new Foo; const o = new Foo; const test = f.test(o); expect(test[0]).toBe(f); expect(test[1]).toBe(o); "# ); test!( syntax(), |_| tr(), public_derived_multiple_supers, r#" class Foo extends Bar { bar = "foo"; constructor() { if (condition) { super(); } else { super(); } } } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; if (condition) { _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _defineProperty(_assertThisInitialized(_this), "bar", "foo"); } else { _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _defineProperty(_assertThisInitialized(_this), "bar", "foo"); } return _possibleConstructorReturn(_this); } return Foo; }(Bar); "# ); test_exec!( syntax(), |_| tr(), private_static_call_exec, r#" class Foo { static #foo = function(x) { return x; } test(x) { return Foo.#foo(x); } } const f = new Foo; const test = f.test(); expect(f.test("bar")).toBe("bar"); "# ); test_exec!( syntax(), |_| tr(), private_instance_undefined_exec, r#" class Foo { #bar; test() { return this.#bar; } } expect(new Foo().test()).toBe(undefined); "# ); test_exec!( syntax(), |_| tr(), private_instance_exec, r#" class Foo { #bar = "foo"; test() { return this.#bar; } update() { this.#bar++; } set(val) { this.#bar = val; } static test(foo) { return foo.#bar; } static update(foo) { foo.#bar **= 2; } } const f = new Foo(); expect(f.test()).toBe("foo"); expect(Foo.test(f)).toBe("foo"); expect("bar" in f).toBe(false); f.set(1); expect(f.test()).toBe(1); f.update(); expect(Foo.test(f)).toBe(2); Foo.update(f); expect(f.test()).toBe(4); "# ); test!( syntax(), |_| tr(), public_regression_t6719, r#" function withContext(ComposedComponent) { return class WithContext extends Component { static propTypes = { context: PropTypes.shape( { addCss: PropTypes.func, setTitle: PropTypes.func, setMeta: PropTypes.func, } ), }; }; } "#, r#" function withContext(ComposedComponent) { return (function() { var WithContext = function(Component) { 'use strict'; _inherits(WithContext, Component); function WithContext() { _classCallCheck(this, WithContext); return _possibleConstructorReturn(this, _getPrototypeOf(WithContext).apply(this, arguments)); } return WithContext; }(Component); _defineProperty(WithContext, 'propTypes', { context: PropTypes.shape({ addCss: PropTypes.func, setTitle: PropTypes.func, setMeta: PropTypes.func }) }); return WithContext; })(); } "# ); test!( syntax(), |_| tr(), public_super_with_collision, r#" class A { force = force; foo = super.method(); constructor(force) {} } "#, r#" var A = function A(force1) { 'use strict'; _classCallCheck(this, A); _defineProperty(this, "force", force); _defineProperty(this, "foo", _get(_getPrototypeOf(A.prototype), "method", this).call(this)); }; "# ); test!( syntax(), |_| tr(), public_call, r#" class Foo { foo = function() { return this; } test(other) { this.foo(); other.obj.foo(); } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _defineProperty(this, "foo", function () { return this; }); } _createClass(Foo, [{ key: "test", value: function test(other) { this.foo(); other.obj.foo(); } }]); return Foo; }(); "# ); test_exec!( syntax(), |_| tr(), public_instance_computed_exec, r#" function test(x) { class F { [x] = 1; constructor() {} } x = 'deadbeef'; expect(new F().foo).toBe(1); x = 'wrong'; expect(new F().foo).toBe(1); } test('foo'); "# ); test!( syntax(), |_| tr(), private_declaration_order, r#" class C { y = this.#x; #x; } expect(() => { new C(); }).toThrow(); "#, r#" var C = function C() { 'use strict'; _classCallCheck(this, C); _defineProperty(this, "y", _classPrivateFieldGet(this, _x)); _x.set(this, { writable: true, value: void 0 }); }; var _x = new WeakMap(); expect(() => { new C(); }).toThrow(); "# ); test!( syntax(), |_| tr(), nested_class_super_call_in_key, r#" class Hello { constructor() { return { toString() { return 'hello'; }, }; } } class Outer extends Hello { constructor() { class Inner { [super()] = "hello"; } return new Inner(); } } expect(new Outer().hello).toBe('hello'); "#, r#" var Hello = function Hello() { 'use strict'; _classCallCheck(this, Hello); return { toString() { return 'hello'; } }; }; var Outer = function (Hello) { 'use strict'; _inherits(Outer, Hello); function Outer() { _classCallCheck(this, Outer); var _this; var _ref = _this = _possibleConstructorReturn(this, _getPrototypeOf(Outer).call(this)); var Inner = function Inner() { _classCallCheck(this, Inner); _defineProperty(this, _ref, "hello"); }; return _possibleConstructorReturn(_this, new Inner()); } return Outer; }(Hello); expect(new Outer().hello).toBe('hello'); "# ); test!( syntax(), |_| tr(), public_instance_undefined, r#" class Foo { bar; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, "bar", void 0); }; "# ); test!( syntax(), |_| tr(), private_derived_multiple_supers, r#" class Foo extends Bar { #bar = "foo"; constructor() { if (condition) { super(); } else { super(); } } } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; if (condition) { _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _bar.set(_assertThisInitialized(_this), { writable: true, value: "foo" }); } else { _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _bar.set(_assertThisInitialized(_this), { writable: true, value: "foo" }); } return _possibleConstructorReturn(_this); } return Foo; }(Bar); var _bar = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), public_native_classes_exec, r#" class Foo { static foo = "foo"; bar = "bar"; static test() { return Foo.foo; } test() { return this.bar; } } const f = new Foo(); expect("foo" in Foo).toBe(true) expect("bar" in f).toBe(true) expect(Foo.test()).toBe("foo") expect(f.test()).toBe("bar") "# ); test!( syntax(), |_| tr(), public_regression_t2983, r#" call(class { static test = true }); export default class { static test = true } "#, r#" call(function() { var _class = function _class() { 'use strict'; _classCallCheck(this, _class); }; _defineProperty(_class, 'test', true); return _class; }()); var _class = function _class() { 'use strict'; _classCallCheck(this, _class); }; _defineProperty(_class, 'test', true); export { _class as default } "# ); test!( syntax(), |_| tr(), public_static, r#" class Foo { static bar = "foo"; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); }; _defineProperty(Foo, "bar", "foo"); "# ); test!( syntax(), |_| tr(), private_instance_undefined, r#" class Foo { #bar; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _bar.set(this, { writable: true, value: void 0 }); }; var _bar = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_declaration_order_exec, r#" class C { y = this.#x; #x; } expect(() => { new C(); }).toThrow(); "# ); test!( syntax(), |_| tr(), public_update, r#" class Foo { foo = 0; test(other) { this.foo++; ++this.foo; other.obj.foo++; ++other.obj.foo; } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _defineProperty(this, "foo", 0); } _createClass(Foo, [{ key: "test", value: function test(other) { this.foo++; ++this.foo; other.obj.foo++; ++other.obj.foo; } }]); return Foo; }(); "# ); test!( syntax(), |_| tr(), public_super_call, r#" class A { foo() { return "bar"; } } class B extends A { foo = super.foo(); } "#, r#" var A = /*#__PURE__*/ function () { 'use strict'; function A() { _classCallCheck(this, A); } _createClass(A, [{ key: "foo", value: function foo() { return "bar"; } }]); return A; }(); var B = /*#__PURE__*/ function (A) { 'use strict'; _inherits(B, A); function B() { _classCallCheck(this, B); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(B).apply(this, arguments)); _defineProperty(_assertThisInitialized(_this), "foo", _get(_getPrototypeOf(B.prototype), "foo", _assertThisInitialized(_this)).call(_this)); return _this; } return B; }(A); "# ); test!( syntax(), |_| tr(), private_constructor_collision, r#" var foo = "bar"; class Foo { #bar = foo; constructor() { var foo = "foo"; } } "#, r#" var foo = "bar"; var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _bar.set(this, { writable: true, value: foo }); var foo1 = "foo"; }; var _bar = new WeakMap(); "# ); test!( syntax(), |_| tr(), public_constructor_collision, r#" var foo = "bar"; class Foo { bar = foo; static bar = baz; constructor() { var foo = "foo"; var baz = "baz"; } } "#, r#" var foo = "bar"; var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, "bar", foo); var foo1 = "foo"; var baz = "baz"; }; _defineProperty(Foo, "bar", baz); "# ); test!( syntax(), |_| tr(), public_computed, r#" const foo = "foo"; const bar = () => {}; const four = 4; class MyClass { static [one()] = "test"; static [2 * 4 + 7] = "247"; static [2 * four + 7] = "247"; static [2 * four + seven] = "247"; [null] = "null"; [undefined] = "undefined"; [void 0] = "void 0"; get ["whatever"]() {} set ["whatever"](value) {} get [computed()]() {} set [computed()](value) {} ["test" + one]() {} static [10]() {} [/regex/] = "regex"; [foo] = "foo"; [bar] = "bar"; [baz] = "baz"; [`template`] = "template"; [`template${expression}`] = "template-with-expression"; } "#, r#" var foo = 'foo'; var bar = ()=>{ }; var four = 4; var _ref = one(), _ref1 = 2 * 4 + 7, _ref2 = 2 * four + 7, _ref3 = 2 * four + seven, _ref4 = null, _undefined = undefined, _ref5 = void 0, tmp = 'whatever', tmp1 = 'whatever', tmp2 = computed(), tmp3 = computed(), tmp4 = 'test' + one, tmp5 = 10, _ref6 = /regex/, _foo = foo, _bar = bar, _baz = baz, _ref7 = `template`, _ref8 = `template${expression}`; var MyClass = function() { 'use strict'; function MyClass() { _classCallCheck(this, MyClass); _defineProperty(this, _ref4, 'null'); _defineProperty(this, _undefined, 'undefined'); _defineProperty(this, _ref5, 'void 0'); _defineProperty(this, _ref6, 'regex'); _defineProperty(this, _foo, 'foo'); _defineProperty(this, _bar, 'bar'); _defineProperty(this, _baz, 'baz'); _defineProperty(this, _ref7, 'template'); _defineProperty(this, _ref8, 'template-with-expression'); } _createClass(MyClass, [{ key: tmp, get: function () { } }, { key: tmp1, set: function (value) { } }, { key: tmp2, get: function () { } }, { key: tmp3, set: function (value) { } }, { key: tmp4, value: function () { } }], [{ key: tmp5, value: function () { } }]); return MyClass; }(); _defineProperty(MyClass, _ref, 'test'); _defineProperty(MyClass, _ref1, '247'); _defineProperty(MyClass, _ref2, '247'); _defineProperty(MyClass, _ref3, '247'); "# ); test!( syntax(), |_| tr(), public_assignment, r#" class Foo { foo = 0; test(other) { this.foo++; this.foo += 1; this.foo = 2; other.obj.foo++; other.obj.foo += 1; other.obj.foo = 2; } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _defineProperty(this, "foo", 0); } _createClass(Foo, [{ key: "test", value: function test(other) { this.foo++; this.foo += 1; this.foo = 2; other.obj.foo++; other.obj.foo += 1; other.obj.foo = 2; } }]); return Foo; }(); "# ); test_exec!( syntax(), |_| tr(), public_static_exec, r#" class Foo { static num = 0; static str = "foo"; } expect(Foo.num).toBe(0); expect(Foo.num = 1).toBe(1); expect(Foo.str).toBe("foo"); expect(Foo.str = "bar").toBe("bar"); "# ); test_exec!( syntax(), |_| tr(), regression_7371_exec_1, r#" class C { } class A extends C { field = 1; constructor() { super(); class B extends C { constructor() { super(); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1) new B(); } } new A(); "# ); test_exec!( syntax(), |_| tr(), regression_7371_exec_2, r#" class Obj { constructor() { return {}; } } // ensure superClass is still transformed class SuperClass extends Obj { field = 1; constructor() { class B extends (super(), Obj) { constructor() { super(); expect(this.field).toBeUndefined() } } expect(this.field).toBe(1) new B(); } } new SuperClass(); // ensure ComputedKey Method is still transformed class ComputedMethod extends Obj { field = 1; constructor() { class B extends Obj { constructor() { super(); expect(this.field).toBeUndefined() } [super()]() { } } expect(this.field).toBe(1) new B(); } } new ComputedMethod(); // ensure ComputedKey Field is still transformed class ComputedField extends Obj { field = 1; constructor() { class B extends Obj { constructor() { super(); expect(this.field).toBeUndefined() } [super()] = 1; } expect(this.field).toBe(1) new B(); } } new ComputedField(); "# ); test_exec!( syntax(), |_| tr(), private_static_inherited_exec, r#" class Base { static #foo = 1; static getThis() { return this.#foo; } static updateThis(val) { return (this.#foo = val); } static getClass() { return Base.#foo; } static updateClass(val) { return (Base.#foo = val); } } class Sub1 extends Base { static #foo = 2; static update(val) { return (this.#foo = val); } } class Sub2 extends Base {} expect(Base.getThis()).toBe(1); expect(Base.getClass()).toBe(1); expect(() => Sub1.getThis()).toThrow(); expect(Sub1.getClass()).toBe(1); expect(() => Sub2.getThis()).toThrow(); expect(Sub2.getClass()).toBe(1); expect(Sub1.update(3)).toBe(3); expect(Base.getThis()).toBe(1); expect(Base.getClass()).toBe(1); expect(() => Sub1.getThis()).toThrow(); expect(Sub1.getClass()).toBe(1); expect(() => Sub2.getThis()).toThrow(); expect(Sub2.getClass()).toBe(1); expect(Base.updateThis(4)).toBe(4); expect(Base.getThis()).toBe(4); expect(Base.getClass()).toBe(4); expect(() => Sub1.getThis()).toThrow(); expect(Sub1.getClass()).toBe(4); expect(() => Sub2.getThis()).toThrow(); expect(Sub2.getClass()).toBe(4); expect(Base.updateClass(5)).toBe(5); expect(Base.getThis()).toBe(5); expect(Base.getClass()).toBe(5); expect(() => Sub1.getThis()).toThrow(); expect(Sub1.getClass()).toBe(5); expect(() => Sub2.getThis()).toThrow(); expect(Sub2.getClass()).toBe(5); expect(() => Sub2.updateThis(6)).toThrow(); expect(Sub2.updateClass(7)).toBe(7); expect(Base.getThis()).toBe(7); expect(Base.getClass()).toBe(7); expect(() => Sub1.getThis()).toThrow(); expect(Sub1.getClass()).toBe(7); expect(() => Sub2.getThis()).toThrow(); expect(Sub2.getClass()).toBe(7); "# ); test_exec!( syntax(), |_| tr(), nested_class_super_property_in_key_exec, r#" class Hello { toString() { return 'hello'; } } class Outer extends Hello { constructor() { super(); class Inner { [super.toString()] = 'hello'; } return new Inner(); } } expect(new Outer().hello).toBe('hello'); "# ); test!( syntax(), |_| tr(), private_super_statement, r#" class Foo extends Bar { #bar = "foo"; constructor() { super(); } } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)); _bar.set(_assertThisInitialized(_this), { writable: true, value: "foo" }); return _this; } return Foo; }(Bar); var _bar = new WeakMap(); "# ); test!( syntax(), |_| tr(), private_private_in_derived, r#" class Outer { #outer; constructor() { class Test extends this.#outer { } } } "#, r#" var Outer = function Outer() { 'use strict'; _classCallCheck(this, Outer); var _this = this; _outer.set(this, { writable: true, value: void 0 }); var Test = function (_super) { _inherits(Test, _super); function Test() { _classCallCheck(this, Test); return _possibleConstructorReturn(this, _getPrototypeOf(Test).apply(this, arguments)); } return Test; }(_classPrivateFieldGet(_this, _outer)); }; var _outer = new WeakMap(); "# ); test!( syntax(), |_| tr(), private_update, r#" class Foo { #foo = 0; test(other) { this.#foo++; ++this.#foo; other.obj.#foo++; ++other.obj.#foo; } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _foo.set(this, { writable: true, value: 0 }); } _createClass(Foo, [{ key: "test", value: function test(other) { var old, _obj, old1, _obj1; _classPrivateFieldSet(this, _foo, (old = +_classPrivateFieldGet(this, _foo)) + 1), old; _classPrivateFieldSet(this, _foo, +_classPrivateFieldGet(this, _foo) + 1); _classPrivateFieldSet(_obj = other.obj, _foo, (old1 = +_classPrivateFieldGet(_obj, _foo)) + 1), old1; _classPrivateFieldSet(_obj1 = other.obj, _foo, +_classPrivateFieldGet(_obj1, _foo) + 1); } }]); return Foo; }(); var _foo = new WeakMap(); "# ); test!( syntax(), |_| tr(), public_super_expression, r#" class Foo extends Bar { bar = "foo"; constructor() { foo(super()); } } "#, r#" var Foo = function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; var _temp; foo((_temp = _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)), _defineProperty(_assertThisInitialized(_this), "bar", "foo"), _temp)); return _possibleConstructorReturn(_this); } return Foo; }(Bar); "# ); test_exec!( syntax(), |_| tr(), public_computed_initialization_order_exec, r#" const actualOrder = []; const track = i => { actualOrder.push(i); return i; }; class MyClass { static [track(1)] = track(10); [track(2)] = track(13); get [track(3)]() { return "foo"; } set [track(4)](value) { this.bar = value; } [track(5)] = track(14); static [track(6)] = track(11); static [track(7)] = track(12); [track(8)]() {} [track(9)] = track(15); } const inst = new MyClass(); const expectedOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; expect(actualOrder).toEqual(expectedOrder); expect(MyClass[1]).toBe(10); expect(inst[2]).toBe(13); expect(inst[3]).toBe("foo"); inst[4] = "baz"; expect(inst.bar).toBe("baz"); expect(inst[5]).toBe(14); expect(MyClass[6]).toBe(11); expect(MyClass[7]).toBe(12); expect(typeof inst[8]).toBe("function"); expect(inst[9]).toBe(15); "# ); test_exec!( syntax(), |_| tr(), nested_class_super_call_in_key_exec, r#" class Hello { constructor() { return { toString() { return 'hello'; }, }; } } class Outer extends Hello { constructor() { class Inner { [super()] = "hello"; } return new Inner(); } } expect(new Outer().hello).toBe('hello'); "# ); test_exec!( syntax(), |_| tr(), private_update_exec, r#" class Foo { #foo = 0; test(other) { return [ this.#foo++, this.#foo, ++this.#foo, this.#foo, other.obj.#foo++, other.obj.#foo, ++other.obj.#foo, other.obj.#foo, ]; } } const f = new Foo; const results = f.test({ obj: f }); expect(results[0]).toBe(0); expect(results[1]).toBe(1); expect(results[2]).toBe(2); expect(results[3]).toBe(2); expect(results[4]).toBe(2); expect(results[5]).toBe(3); expect(results[6]).toBe(4); expect(results[7]).toBe(4); "# ); test!( syntax(), |_| tr(), public_extracted_this, r#" var foo = "bar"; class Foo { bar = this; baz = foo; constructor(foo) { } } "#, r#" var foo = "bar"; var Foo = function Foo(foo1) { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, "bar", this); _defineProperty(this, "baz", foo); }; "# ); test!( syntax(), |_| tr(), private_derived, r#" class Foo { #prop = "foo"; } class Bar extends Foo { #prop = "bar"; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _prop1.set(this, { writable: true, value: "foo" }); }; var _prop1 = new WeakMap(); var Bar = /*#__PURE__*/ function (Foo) { 'use strict'; _inherits(Bar, Foo); function Bar() { _classCallCheck(this, Bar); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(Bar).apply(this, arguments)); _prop2.set(_assertThisInitialized(_this), { writable: true, value: "bar" }); return _this; } return Bar; }(Foo); var _prop2 = new WeakMap(); "# ); test!( syntax(), |_| tr(), private_super_call, r#" class A { foo() { return "bar"; } } class B extends A { #foo = super.foo(); } "#, r#" var A = function () { 'use strict'; function A() { _classCallCheck(this, A); } _createClass(A, [{ key: "foo", value: function foo() { return "bar"; } }]); return A; }(); var B = /*#__PURE__*/ function (A) { 'use strict'; _inherits(B, A); function B() { _classCallCheck(this, B); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(B).apply(this, arguments)); _foo.set(_assertThisInitialized(_this), { writable: true, value: _get(_getPrototypeOf(B.prototype), "foo", _assertThisInitialized(_this))() }); return _this; } return B; }(A); var _foo = new WeakMap(); "# ); test!( syntax(), |_| tr(), private_reference_in_other_property, r#" class Foo { one = this.#private; #two = this.#private; #private = 0; three = this.#private; #four = this.#private; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, "one", _classPrivateFieldGet(this, _private)); _two.set(this, { writable: true, value: _classPrivateFieldGet(this, _private) }); _private.set(this, { writable: true, value: 0 }); _defineProperty(this, "three", _classPrivateFieldGet(this, _private)); _four.set(this, { writable: true, value: _classPrivateFieldGet(this, _private) }); }; var _two = new WeakMap(); var _private = new WeakMap(); var _four = new WeakMap(); "# ); test!( syntax(), |_| tr(), nested_class_super_property_in_key, r#" class Hello { toString() { return 'hello'; } } class Outer extends Hello { constructor() { super(); class Inner { [super.toString()] = 'hello'; } return new Inner(); } } expect(new Outer().hello).toBe('hello'); "#, r#" var Hello = function () { 'use strict'; function Hello() { _classCallCheck(this, Hello); } _createClass(Hello, [{ key: "toString", value: function toString() { return 'hello'; } }]); return Hello; }(); var Outer = function (Hello) { 'use strict'; _inherits(Outer, Hello); function Outer() { _classCallCheck(this, Outer); var _this = _possibleConstructorReturn(this, _getPrototypeOf(Outer).call(this)); var _ref = _get(_getPrototypeOf(Outer.prototype), 'toString', _assertThisInitialized(_this)).call(_this); var Inner = function Inner() { _classCallCheck(this, Inner); _defineProperty(this, _ref, 'hello'); }; return _possibleConstructorReturn(_this, new Inner()); } return Outer; }(Hello); expect(new Outer().hello).toBe('hello'); "# ); test_exec!( syntax(), |_| tr(), private_reevaluated_exec, r#" function classFactory() { return class Foo { #foo = "foo"; static #bar = "bar"; instance() { return this.#foo; } static() { return Foo.#bar; } static instance(inst) { return inst.#foo; } static static() { return Foo.#bar; } }; } const Foo1 = classFactory(); const Foo2 = classFactory(); const f1 = new Foo1(); const f2 = new Foo2(); expect(f1.instance()).toBe("foo"); expect(f1.static()).toBe("bar"); expect(f2.instance()).toBe("foo"); expect(f2.static()).toBe("bar"); expect(Foo1.instance(f1)).toBe("foo"); expect(Foo1.static()).toBe("bar"); expect(Foo2.instance(f2)).toBe("foo"); expect(Foo2.static()).toBe("bar"); expect(() => { f1.instance.call(f2), undefined; }).toThrow(); expect(() => { f2.instance.call(f1), undefined; }).toThrow(); expect(() => { Foo1.instance(f2), undefined; }).toThrow(); expect(() => { Foo2.instance(f1), undefined; }).toThrow(); "# ); test!( syntax(), |_| tr(), public_numeric, r#" class Foo { 0 = "foo"; 1 = "bar"; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, 0, "foo"); _defineProperty(this, 1, "bar"); }; "# ); test!( syntax(), |_| tr(), private_assignment, r#" class Foo { #foo = 0; test(other) { this.#foo += 1; this.#foo = 2; other.obj.#foo += 1; other.obj.#foo = 2; } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _foo.set(this, { writable: true, value: 0 }); } _createClass(Foo, [{ key: "test", value: function test(other) { var _obj; _classPrivateFieldSet(this, _foo, _classPrivateFieldGet(this, _foo) + 1); _classPrivateFieldSet(this, _foo, 2); _classPrivateFieldSet(_obj = other.obj, _foo, _classPrivateFieldGet(_obj, _foo) + 1); _classPrivateFieldSet(other.obj, _foo, 2); } }]); return Foo; }(); var _foo = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_constructor_collision_exec, r#" var foo = "bar"; class Foo { #bar = foo; constructor() { var foo = "foo"; } test() { return this.#bar; } } const f = new Foo; expect(f.test()).toBe(foo); expect("bar" in f).toBe(false); "# ); test!( syntax(), |_| tr(), public_static_export, r#" export class MyClass { static property = value; } export default class MyClass2 { static property = value; } "#, r#" export var MyClass = function MyClass() { 'use strict'; _classCallCheck(this, MyClass); }; _defineProperty(MyClass, "property", value); var MyClass2 = function MyClass2() { 'use strict'; _classCallCheck(this, MyClass2); }; _defineProperty(MyClass2, "property", value); export { MyClass2 as default }; "# ); test!( syntax(), |_| tr(), private_multiple, r#" class Foo { #x = 0; #y = this.#x; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _x.set(this, { writable: true, value: 0 }); _y.set(this, { writable: true, value: _classPrivateFieldGet(this, _x) }); }; var _x = new WeakMap(); var _y = new WeakMap(); "# ); test!( syntax(), |_| tr(), public_derived, r#" class Foo extends Bar { bar = "foo"; } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).apply(this, arguments)) _defineProperty(_assertThisInitialized(_this), "bar", "foo"); return _this; } return Foo; }(Bar); "# ); test_exec!( syntax(), |_| tr(), public_static_undefined_exec, r#" class Foo { static num; } expect("num" in Foo).toBe(true); expect(Foo.num).toBeUndefined(); "# ); test!( syntax(), |_| tr(), public_instance, r#" class Foo { bar = "foo"; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, "bar", "foo"); }; "# ); test_exec!( syntax(), |_| tr(), static_property_tdz_edgest_case_exec, r#" expect(() => { class A { static [{ x: A || 0 }.x]; } }).toThrow(); "# ); test!( syntax(), |_| tr(), public_non_block_arrow_func, r#" export default param => class App { static props = { prop1: 'prop1', prop2: 'prop2' } getParam() { return param; } } "#, r#" export default ((param)=>{ var App = function() { 'use strict'; function App() { _classCallCheck(this, App); } _createClass(App, [{ key: 'getParam', value: function getParam() { return param; } }]); return App; }(); _defineProperty(App, 'props', { prop1: 'prop1', prop2: 'prop2' }); return App; }); "# ); test!( syntax(), |_| tr(), public_static_undefined, r#" class Foo { static bar; } "#, r#" var Foo = function Foo() { 'use strict'; _classCallCheck(this, Foo); }; _defineProperty(Foo, "bar", void 0); "# ); test_exec!( syntax(), |_| tr(), public_static_infer_name_exec, r#" var Foo = class { static num = 0; } expect(Foo.num).toBe(0); expect(Foo.num = 1).toBe(1); expect(Foo.name).toBe("Foo"); "# ); test_exec!( syntax(), |_| tr(), static_property_tdz_general_exec, r#" expect(() => { class C { static [C + 3] = 3; } }).toThrow(); "# ); test!( syntax(), |_| tr(), private_call, r#" class Foo { #foo = function() { return this; } test(other) { this.#foo(); other.obj.#foo(); } } "#, r#" var Foo = function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); var _this = this; _foo.set(this, { writable: true, value: function () { return _this; } }); } _createClass(Foo, [{ key: "test", value: function test(other) { var _obj; _classPrivateFieldGet(this, _foo).call(this); _classPrivateFieldGet(_obj = other.obj, _foo).call(_obj); } }]); return Foo; }(); var _foo = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_derived_exec, r#" class Foo { #prop = "foo"; foo() { return this.#prop; } } class Bar extends Foo { #prop = "bar"; bar() { return this.#prop; } } const f = new Foo; expect(f.foo()).toBe("foo"); const b = new Bar; expect(b.foo()).toBe("foo"); expect(b.bar()).toBe("bar"); "# ); test!( syntax(), |_| tr(), private_extracted_this, r#" var foo = "bar"; class Foo { #bar = this; #baz = foo; constructor(foo) { } } "#, r#" var foo = "bar"; var Foo = function Foo(foo1) { 'use strict'; _classCallCheck(this, Foo); _bar.set(this, { writable: true, value: this }); _baz.set(this, { writable: true, value: foo }); }; var _bar = new WeakMap(); var _baz = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_canonical_exec, r#" class Point { #x; #y; constructor(x = 0, y = 0) { this.#x = +x; this.#y = +y; } get x() { return this.#x } set x(value) { this.#x = +value } get y() { return this.#y } set y(value) { this.#y = +value } equals(p) { return this.#x === p.#x && this.#y === p.#y } toString() { return `Point<${ this.#x },${ this.#y }>` } } const p1 = new Point(1, 2); const p2 = new Point(2, 3); const p3 = new Point(1, 2); expect(p1.x).toBe(1); expect(p1.y).toBe(2); expect(p2.x).toBe(2); expect(p2.y).toBe(3); expect(p3.x).toBe(1); expect(p3.y).toBe(2); expect(p1.equals(p1)).toBe(true) expect(p1.equals(p2)).toBe(false) expect(p1.equals(p3)).toBe(true) expect(p2.equals(p1)).toBe(false) expect(p2.equals(p2)).toBe(true) expect(p2.equals(p3)).toBe(false) expect(p3.equals(p1)).toBe(true) expect(p3.equals(p2)).toBe(false) expect(p3.equals(p3)).toBe(true) expect(p1.toString()).toBe("Point<1,2>") expect(p2.toString()).toBe("Point<2,3>") expect(p3.toString()).toBe("Point<1,2>") p1.x += 1; p1.y = 3; p2.x -= 1; p2.y = 3; p3.x = 0; p3.y = 0; expect(p1.x).toBe(2); expect(p1.y).toBe(3); expect(p2.x).toBe(1); expect(p2.y).toBe(3); expect(p3.x).toBe(0); expect(p3.y).toBe(0); expect(p1.equals(p1)).toBe(true) expect(p1.equals(p2)).toBe(false) expect(p1.equals(p3)).toBe(false) expect(p2.equals(p1)).toBe(false) expect(p2.equals(p2)).toBe(true) expect(p2.equals(p3)).toBe(false) expect(p3.equals(p1)).toBe(false) expect(p3.equals(p2)).toBe(false) expect(p3.equals(p3)).toBe(true) expect(p1.toString()).toBe("Point<2,3>") expect(p2.toString()).toBe("Point<1,3>") expect(p3.toString()).toBe("Point<0,0>") "# ); test_exec!( syntax(), |_| tr(), private_static_undefined_exec, r#" class Foo { static #bar; static test() { return Foo.#bar; } test() { return Foo.#bar; } } expect("bar" in Foo).toBe(false); expect(Foo.test()).toBe(undefined); expect(Foo.test()).toBe(undefined); "# ); test_exec!( syntax(), |_| tr(), public_update_exec, r#" class Foo { foo = 0; test(other) { return [ this.foo++, this.foo, ++this.foo, this.foo, other.obj.foo++, other.obj.foo, ++other.obj.foo, other.obj.foo, ]; } } const f = new Foo; const results = f.test({ obj: f }); expect(results[0]).toBe(0); expect(results[1]).toBe(1); expect(results[2]).toBe(2); expect(results[3]).toBe(2); expect(results[4]).toBe(2); expect(results[5]).toBe(3); expect(results[6]).toBe(4); expect(results[7]).toBe(4); "# ); test!( syntax(), |_| tr(), private_static_call, r#" class Foo { static #foo = function(x) { return x; } test(x) { return Foo.#foo(x); } } "#, r#" var Foo = /*#__PURE__*/ function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); } _createClass(Foo, [{ key: "test", value: function test(x) { return _classStaticPrivateFieldSpecGet(Foo, Foo, _foo).call(Foo, x); } }]); return Foo; }(); var _foo = { writable: true, value: function (x) { return x; } }; "# ); test!( syntax(), |_| tr(), private_super_expression, r#" class Foo extends Bar { #bar = "foo"; constructor() { foo(super()); } } "#, r#" var Foo = /*#__PURE__*/ function (Bar) { 'use strict'; _inherits(Foo, Bar); function Foo() { _classCallCheck(this, Foo); var _this; var _temp; foo((_temp = _this = _possibleConstructorReturn(this, _getPrototypeOf(Foo).call(this)), _bar.set(_assertThisInitialized(_this), { writable: true, value: "foo" }), _temp)); return _possibleConstructorReturn(_this); } return Foo; }(Bar); var _bar = new WeakMap(); "# ); test_exec!( syntax(), |_| tr(), private_native_classes_exec, r#" class Foo { static #foo = "foo"; #bar = "bar"; static test() { return Foo.#foo; } test() { return this.#bar; } } const f = new Foo(); expect("foo" in Foo).toBe(false) expect("bar" in f).toBe(false) expect(Foo.test()).toBe("foo") expect(f.test()).toBe("bar") "# ); test_exec!( syntax(), |_| tr(), private_multiple_exec, r#" class Foo { #x = 0; #y = this.#x + 1; test() { return this.#y; } } const f = new Foo(); expect(f.test()).toBe(1); "# ); test!( syntax(), |_| tr(), custom_instance_update, " class Foo { #x = 0; test() { this.#x++; ++this.#x; } } ", " var Foo = function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); _x.set(this, { writable: true, value: 0 }); } _createClass(Foo, [{ key: 'test', value: function test() { var old; _classPrivateFieldSet(this, _x, (old = +_classPrivateFieldGet(this, _x)) + 1), old; _classPrivateFieldSet(this, _x, +_classPrivateFieldGet(this, _x) + 1); } }]); return Foo; }(); var _x = new WeakMap(); " ); test!( syntax(), |_| tr(), custom_static_update, " class Foo { static #x = 0; test() { Foo.#x++; ++Foo.#x; } } ", " var Foo = function () { 'use strict'; function Foo() { _classCallCheck(this, Foo); } _createClass(Foo, [{ key: 'test', value: function test() { var old; _classStaticPrivateFieldSpecSet(Foo, Foo, _x, (old = +_classStaticPrivateFieldSpecGet(Foo, \ Foo, _x)) + 1), old; _classStaticPrivateFieldSpecSet(Foo, Foo, _x, +_classStaticPrivateFieldSpecGet(Foo, Foo, _x) \ + 1); } }]); return Foo; }(); var _x = { writable: true, value: 0 };" ); test!( syntax(), |_| chain!(resolver(), class_properties()), issue_308, "function bar(props) {} class Foo { constructor() { super(); bar(); } onBar = () => { bar(); }; }", "function bar(props) { } class Foo{ constructor(){ super(); _defineProperty(this, 'onBar', ()=>{ bar(); }); bar(); } } " ); test!( syntax(), |_| chain!(resolver(), class_properties(), Classes::default()), issue_342, "class Foo { constructor(bar) { this._bar = bar; } qux = { frob: (bar) => {}, }; }", " let Foo = function Foo(bar) { 'use strict'; _classCallCheck(this, Foo); _defineProperty(this, 'qux', { frob: (bar1)=>{ } }); this._bar = bar; };" ); test!( syntax(), |_| chain!(resolver(), class_properties(), block_scoping()), issue_443, " const MODE = 1; class foo { static MODE = MODE; constructor() { this.mode = MODE; } } ", "var MODE = 1; class foo{ constructor(){ this.mode = MODE; } } _defineProperty(foo, 'MODE', MODE);" ); // public_regression_t7364 test!( syntax(), |_| chain!(class_properties(), async_to_generator()), public_regression_t7364, r#" class MyClass { myAsyncMethod = async () => { console.log(this); } } (class MyClass2 { myAsyncMethod = async () => { console.log(this); } }) export default class MyClass3 { myAsyncMethod = async () => { console.log(this); } } "#, r#" class MyClass { constructor() { _defineProperty(this, 'myAsyncMethod', (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this)); } } (function() { class MyClass2{ constructor(){ _defineProperty(this, 'myAsyncMethod', (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this)); } } return MyClass2; })(); class MyClass3{ constructor(){ _defineProperty(this, 'myAsyncMethod', (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this)); } } export { MyClass3 as default } "# ); // private_regression_t6719 test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_regression_t6719, r#" function withContext(ComposedComponent) { return class WithContext extends Component { static #propTypes = { context: PropTypes.shape( { addCss: PropTypes.func, setTitle: PropTypes.func, setMeta: PropTypes.func, } ), }; }; } "#, r#" function withContext(ComposedComponent) { return (function() { class WithContext extends Component{ } var _propTypes = { writable: true, value: { context: PropTypes.shape({ addCss: PropTypes.func, setTitle: PropTypes.func, setMeta: PropTypes.func }) } }; return WithContext; })(); } "# ); // public_foobar //test!(syntax(),|_| tr("{ // "plugins": [ "proposal-class-properties"], // "presets": ["env"] //} //"), public_foobar, r#" //class Child extends Parent { // constructor() { // super(); // } // // scopedFunctionWithThis = () => { // this.name = {}; // } //} // //"#, r#" //var Child = // /*#__PURE__*/ //function (_Parent) { // "use strict"; // // _inherits(Child, _Parent); // // function Child() { // var _this; // // _classCallCheck(this, Child); // _this = _possibleConstructorReturn(this, // _getPrototypeOf(Child).call(this)); // _defineProperty(_assertThisInitialized(_this), "scopedFunctionWithThis", // function () { _this.name = {}; // }); // return _this; // } // // return Child; //}(Parent); // //"#); // private_reevaluated test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_reevaluated, r#" function classFactory() { return class Foo { #foo = "foo"; static #bar = "bar"; instance() { return this.#foo; } static() { return Foo.#bar; } static instance(inst) { return inst.#foo; } static static() { return Foo.#bar; } }; } "#, r#" function classFactory() { return (function() { class Foo{ instance() { return _classPrivateFieldGet(this, _foo); } static() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } static instance(inst) { return _classPrivateFieldGet(inst, _foo); } static static() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } constructor(){ _foo.set(this, { writable: true, value: 'foo' }); } } var _foo = new WeakMap(); var _bar = { writable: true, value: 'bar' }; return Foo; })(); } "# ); // private_static test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_static, r#" class Foo { static #bar = "foo"; static test() { return Foo.#bar; } test() { return Foo.#bar; } } expect("bar" in Foo).toBe(false) expect(Foo.test()).toBe("foo") expect(Foo.test()).toBe("foo") "#, r#" class Foo { static test() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } test() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } } var _bar = { writable: true, value: "foo" }; expect("bar" in Foo).toBe(false); expect(Foo.test()).toBe("foo"); expect(Foo.test()).toBe("foo"); "# ); // private_destructuring_object_pattern_1 test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_destructuring_object_pattern_1, r#" class Foo { #client constructor(props) { this.#client = 'foo'; ({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props) } } "#, r#" var Foo = function Foo(props) { "use strict"; _classCallCheck(this, Foo); _client.set(this, { writable: true, value: void 0 }); _classPrivateFieldSet(this, _client, 'foo'); ({ x: this.x = _classPrivateFieldGet(this, _client), y: _classPrivateFieldDestructureSet(this, _client).value, z: this.z = _classPrivateFieldGet(this, _client) } = props); }; var _client = new WeakMap(); "# ); // private_static_inherited test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_static_inherited, r#" class Base { static #foo = 1; static getThis() { return this.#foo; } static updateThis(val) { return (this.#foo = val); } static getClass() { return Base.#foo; } static updateClass(val) { return (Base.#foo = val); } } class Sub1 extends Base { static #foo = 2; static update(val) { return (this.#foo = val); } } class Sub2 extends Base {} "#, r#" class Base { static getThis() { return _classStaticPrivateFieldSpecGet(this, Base, _foo1); } static updateThis(val) { return _classStaticPrivateFieldSpecSet(this, Base, _foo1, val); } static getClass() { return _classStaticPrivateFieldSpecGet(Base, Base, _foo1); } static updateClass(val) { return _classStaticPrivateFieldSpecSet(Base, Base, _foo1, val); } } var _foo1 = { writable: true, value: 1 }; class Sub1 extends Base { static update(val) { return _classStaticPrivateFieldSpecSet(this, Sub1, _foo2, val); } } var _foo2 = { writable: true, value: 2 }; class Sub2 extends Base {} "# ); // private_destructuring_object_pattern_1_exec test_exec!( syntax(), |_| class_properties(), private_destructuring_object_pattern_1_exec, r#" class Foo { #client constructor(props) { this.#client = 'foo'; ;({ x: this.x = this.#client, y: this.#client, z: this.z = this.#client } = props) } getClient() { return this.#client; } } const foo = new Foo({ y: 'bar' }); expect(foo.getClient()).toBe('bar'); expect(foo.x).toBe('foo'); expect(foo.z).toBe('bar'); "# ); // private_static_undefined test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_static_undefined, r#" class Foo { static #bar; static test() { return Foo.#bar; } test() { return Foo.#bar; } } "#, r#" class Foo { static test() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } test() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _bar); } } var _bar = { writable: true, value: void 0 }; "# ); // private_destructuring_array_pattern test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_destructuring_array_pattern, r#" class Foo { #client constructor(props) { ([this.#client] = props); } } "#, r#" var Foo = function Foo(props) { "use strict"; _classCallCheck(this, Foo); _client.set(this, { writable: true, value: void 0 }); [_classPrivateFieldDestructureSet(this, _client).value] = props; }; var _client = new WeakMap(); "# ); // private_regression_t2983 test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_regression_t2983, r#" call(class { static #test = true }); export default class { static #test = true } "#, r#" call(function() { class _class{ } var _test = { writable: true, value: true }; return _class; }()); class _class{ } var _test = { writable: true, value: true }; export { _class as default } "# ); // private_regression_t7364 test!( syntax(), |_| chain!(class_properties(), async_to_generator(), block_scoping()), private_regression_t7364, r#" class MyClass { #myAsyncMethod = async () => { console.log(this); } } (class MyClass2 { #myAsyncMethod = async () => { console.log(this); } }) export default class MyClass3 { #myAsyncMethod = async () => { console.log(this); } } "#, r#" class MyClass{ constructor(){ _myAsyncMethod1.set(this, { writable: true, value: (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this) }); } } var _myAsyncMethod1 = new WeakMap(); (function() { class MyClass2{ constructor(){ _myAsyncMethod2.set(this, { writable: true, value: (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this) }); } } var _myAsyncMethod2 = new WeakMap(); return MyClass2; })(); class MyClass3{ constructor(){ _myAsyncMethod2.set(this, { writable: true, value: (function() { var _ref = _asyncToGenerator((function*() { console.log(this); }).bind(this)); return function() { return _ref.apply(this, arguments); }; })().bind(this) }); } } var _myAsyncMethod2 = new WeakMap(); export { MyClass3 as default } "# ); // private_destructuring_array_pattern_1 test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_destructuring_array_pattern_1, r#" class Foo { #client constructor(props) { this.#client = 1; ([this.x = this.#client, this.#client, this.y = this.#client] = props); } } "#, r#" var Foo = function Foo(props) { "use strict"; _classCallCheck(this, Foo); _client.set(this, { writable: true, value: void 0 }); _classPrivateFieldSet(this, _client, 1); [this.x = _classPrivateFieldGet(this, _client), _classPrivateFieldDestructureSet(this, _client).value, this.y = _classPrivateFieldGet(this, _client)] = props; }; var _client = new WeakMap(); "# ); // decorators_legacy_interop_strict test!( // See: https://github.com/swc-project/swc/issues/421 ignore, syntax(), |_| chain!( decorators(decorators::Config { legacy: true, ..Default::default() }), class_properties(), Classes::default(), ), decorators_legacy_interop_strict, r#" function dec() {} class A { @dec a; @dec b = 123; c = 456; } "#, r#" var _class, _descriptor, _descriptor2, _temp; function dec() {} let A = (_class = (_temp = function A() { "use strict"; _classCallCheck(this, A); _initializerDefineProperty(this, "a", _descriptor, this); _initializerDefineProperty(this, "b", _descriptor2, this); _defineProperty(this, "c", 456); }, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "a", [dec], { configurable: true, enumerable: true, writable: true, initializer: null }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "b", [dec], { configurable: true, enumerable: true, writable: true, initializer: function () { return 123; } })), _class); "# ); // regression_8882_exec test_exec!( syntax(), |_| class_properties(), regression_8882_exec, r#" const classes = []; for (let i = 0; i <= 10; ++i) { classes.push( class A { [i] = `computed field ${i}`; static foo = `static field ${i}`; #bar = `private field ${i}`; getBar() { return this.#bar; } } ); } for(let i=0; i<= 10; ++i) { const clazz = classes[i]; expect(clazz.foo).toBe('static field ' + i); const instance = new clazz(); expect(Object.getOwnPropertyNames(instance)).toEqual([String(i)]) expect(instance[i]).toBe('computed field ' + i); expect(instance.getBar()).toBe('private field ' + i); } "# ); //// regression_6154 //test!(syntax(),|_| tr("{ // "presets": ["env"], // "plugins": class_properties() //} //"), regression_6154, r#" //class Test { // constructor() { // class Other extends Test { // a = () => super.test; // static a = () => super.test; // } // } //} // //"#, r#" //function _typeof(obj) { if (typeof Symbol === "function" && typeof // Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return // typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && // typeof Symbol === "function" && obj.constructor === Symbol && obj !== // Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } // //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 _inherits(subClass, superClass) { if (typeof superClass !== // "function" && superClass !== null) { throw new TypeError("Super expression // must either be null or a function"); } subClass.prototype = // Object.create(superClass && superClass.prototype, { constructor: { value: // subClass, writable: true, configurable: true } }); 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 _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.setPrototypeOf ? // Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || // Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } // //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 _classCallCheck(instance, Constructor) { if (!(instance instanceof // Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // //var Test = function Test() { // "use strict"; // // _classCallCheck(this, Test); // // var Other = // /*#__PURE__*/ // function (_Test) { // _inherits(Other, _Test); // // function Other() { // var _getPrototypeOf2; // // var _this; // // _classCallCheck(this, Other); // // for (var _len = arguments.length, args = new Array(_len), _key = 0; _key // < _len; _key++) { args[_key] = arguments[_key]; // } // // _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = // _getPrototypeOf(Other)).call.apply(_getPrototypeOf2, [this].concat(args))); // // _defineProperty(_assertThisInitialized(_this), "a", function () { // return _get(_getPrototypeOf(Other.prototype), "test", // _assertThisInitialized(_this)); }); // // return _this; // } // // return Other; // }(Test); // // _defineProperty(Other, "a", function () { // return _get(_getPrototypeOf(Other), "test", Other); // }); //}; // //"#); // private_static_export test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_static_export, r#" export class MyClass { static #property = value; } export default class MyClass2 { static #property = value; } "#, r#" export class MyClass {} var _property = { writable: true, value: value }; class MyClass2{ } var _property1 = { writable: true, value: value }; export { MyClass2 as default } "# ); // static_property_tdz_edgest_case test!( syntax(), |_| chain!(class_properties(), Classes::default()), static_property_tdz_edgest_case, r#" class A { static [{ x: A || 0 }.x]; } "#, r#" var _x = { x: (_classNameTDZError("A"), A) || 0 }.x; let A = function A() { "use strict"; _classCallCheck(this, A); }; _defineProperty(A, _x, void 0); "# ); // regression_6153 test!( syntax(), |_| chain!(class_properties(), arrow()), regression_6153, r#" () => { class Foo { fn = () => console.log(this); static fn = () => console.log(this); } }; () => class Bar { fn = () => console.log(this); static fn = () => console.log(this); }; () => { class Baz { fn = () => console.log(this); force = force static fn = () => console.log(this); constructor(force) {} } }; var qux = function() { class Qux { fn = () => console.log(this); static fn = () => console.log(this); } }.bind(this) "#, r#" (function () { class Foo { constructor() { _defineProperty(this, 'fn', (function() { return console.log(this); }).bind(this)); } } _defineProperty(Foo, "fn", function () { return console.log(Foo); }); }); (function () { class Bar { constructor() { _defineProperty(this, 'fn', (function() { return console.log(this); }).bind(this)); } } _defineProperty(Bar, "fn", function () { return console.log(Bar); }); return Bar; }); (function () { class Baz { constructor(force1){ _defineProperty(this, 'fn', (function() { return console.log(this); }).bind(this)); _defineProperty(this, "force", force); } } _defineProperty(Baz, "fn", function () { return console.log(Baz); }); }); var qux = (function () { class Qux { constructor() { _defineProperty(this, 'fn', (function() { return console.log(this); }).bind(this)); } } _defineProperty(Qux, "fn", function () { return console.log(Qux); }); }).bind(this); "# ); // regression_7371 test!( syntax(), |_| chain!(class_properties(), arrow()), regression_7371, r#" "use strict"; class C { } class A extends C { field = 1; constructor() { super(); class B extends C { constructor() { super(); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1) new B(); } } new A(); class Obj { constructor() { return {}; } } // ensure superClass is still transformed class SuperClass extends Obj { field = 1; constructor() { class B extends (super(), Obj) { constructor() { super(); expect(this.field).toBeUndefined() } } expect(this.field).toBe(1) new B(); } } new SuperClass(); // ensure ComputedKey Method is still transformed class ComputedMethod extends Obj { field = 1; constructor() { class B extends Obj { constructor() { super(); expect(this.field).toBeUndefined() } [super()]() { } } expect(this.field).toBe(1) new B(); } } new ComputedMethod(); // ensure ComputedKey Field is still transformed class ComputedField extends Obj { field = 1; constructor() { class B extends Obj { constructor() { super(); expect(this.field).toBeUndefined() } [super()] = 1; } expect(this.field).toBe(1) new B(); } } new ComputedField(); "#, r#" "use strict"; class C {} class A extends C { constructor() { super(); _defineProperty(this, "field", 1); class B extends C { constructor() { super(); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1); new B(); } } new A(); class Obj { constructor() { return {}; } } // ensure superClass is still transformed class SuperClass extends Obj { constructor() { var _temp; class B extends (_temp = super(), _defineProperty(this, 'field', 1), Obj) { constructor() { super(); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1); new B(); } } new SuperClass(); // ensure ComputedKey Method is still transformed class ComputedMethod extends Obj { constructor() { var _temp1; var tmp = (_temp1 = super(), _defineProperty(this, "field", 1), _temp1); class B extends Obj { [tmp]() {} constructor() { super(); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1); new B(); } } new ComputedMethod(); // ensure ComputedKey Field is still transformed class ComputedField extends Obj { constructor() { var _temp2; var _ref = (_temp2 = super(), _defineProperty(this, "field", 1), _temp2); class B extends Obj { constructor() { super(); _defineProperty(this, _ref, 1); expect(this.field).toBeUndefined(); } } expect(this.field).toBe(1); new B(); } } new ComputedField(); "# ); // private_canonical test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_canonical, r#" class Point { #x; #y; constructor(x = 0, y = 0) { this.#x = +x; this.#y = +y; } get x() { return this.#x } set x(value) { this.#x = +value } get y() { return this.#y } set y(value) { this.#y = +value } equals(p) { return this.#x === p.#x && this.#y === p.#y } toString() { return `Point<${ this.#x },${ this.#y }>` } } "#, r#" var Point = /*#__PURE__*/ function () { "use strict"; function Point(x = 0, y = 0) { _classCallCheck(this, Point); _x.set(this, { writable: true, value: void 0 }); _y.set(this, { writable: true, value: void 0 }); _classPrivateFieldSet(this, _x, +x); _classPrivateFieldSet(this, _y, +y); } _createClass(Point, [{ key: "x", get: function () { return _classPrivateFieldGet(this, _x); }, set: function (value) { _classPrivateFieldSet(this, _x, +value); } }, { key: "y", get: function () { return _classPrivateFieldGet(this, _y); }, set: function (value) { _classPrivateFieldSet(this, _y, +value); } }, { key: "equals", value: function equals(p) { return _classPrivateFieldGet(this, _x) === _classPrivateFieldGet(p, _x) && _classPrivateFieldGet(this, _y) === _classPrivateFieldGet(p, _y); } }, { key: "toString", value: function toString() { return `Point<${_classPrivateFieldGet(this, _x)},${_classPrivateFieldGet(this, _y)}>`; } }]); return Point; }(); var _x = new WeakMap(); var _y = new WeakMap(); "# ); // regression_8882 test!( syntax(), |_| class_properties(), regression_8882, r#" const classes = []; for(let i = 0; i <= 10; ++i){ classes.push(function() { class A{ getBar() { return _classPrivateFieldGet(this, _bar); } constructor(){ _defineProperty(this, i, `computed field ${i}`); _bar.set(this, { writable: true, value: `private field ${i}` }); } } _defineProperty(A, 'foo', `static field ${i}`); var _bar = new WeakMap(); return A; }()); } "#, r#" const classes = []; for(let i = 0; i <= 10; ++i){ classes.push(function() { class A{ getBar() { return _classPrivateFieldGet(this, _bar); } constructor(){ _defineProperty(this, i, `computed field ${i}`); _bar.set(this, { writable: true, value: `private field ${i}` }); } } _defineProperty(A, 'foo', `static field ${i}`); var _bar = new WeakMap(); return A; }()); } "# ); // compile_to_class_constructor_collision_ignores_types test!( ts(), |_| chain!(typescript::strip(), class_properties()), compile_to_class_constructor_collision_ignores_types, r#" class C { // Output should not use `_initialiseProps` x: T; y = 0; constructor(T) {} } "#, r#" class C { // Output should not use `_initialiseProps` constructor(T) { _defineProperty(this, "y", 0); } } "# ); // private_destructuring_array_pattern_3 test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_destructuring_array_pattern_3, r#" class Foo { #client constructor(props) { ([this.#client = 5] = props); } } "#, r#" var Foo = function Foo(props) { "use strict"; _classCallCheck(this, Foo); _client.set(this, { writable: true, value: void 0 }); [_classPrivateFieldDestructureSet(this, _client).value = 5] = props; }; var _client = new WeakMap(); "# ); // public_static_super_exec test_exec!( syntax(), |_| class_properties(), public_static_super_exec, r#" class A { static prop = 1; } class B extends A { static prop = 2; static propA = super.prop; static getPropA = () => super.prop; } const { prop, propA, getPropA } = B; expect(prop).toBe(2); expect(propA).toBe(1); expect(getPropA()).toBe(1); "# ); // private_destructuring_array_pattern_2 test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), private_destructuring_array_pattern_2, r#" class Foo { #client constructor(props) { ([x, ...this.#client] = props); } } "#, r#" var Foo = function Foo(props) { "use strict"; _classCallCheck(this, Foo); _client.set(this, { writable: true, value: void 0 }); [x, ..._classPrivateFieldDestructureSet(this, _client).value] = props; }; var _client = new WeakMap(); "# ); // private_non_block_arrow_func test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_non_block_arrow_func, r#" export default param => class App { static #props = { prop1: 'prop1', prop2: 'prop2' } getParam() { return param; } } "#, r#" export default ((param)=>{ class App{ getParam() { return param; } } var _props = { writable: true, value: { prop1: 'prop1', prop2: 'prop2' } }; return App; }); "# ); // regression_8110 test!( syntax(), |_| class_properties(), regression_8110, r#" const field = Symbol('field'); class A { [field] = 10; } "#, r#" const field = Symbol('field'); var _field = field; class A{ constructor(){ _defineProperty(this, _field, 10); } } "# ); // decorators_legacy_interop_local_define_property test!( // See: https://github.com/swc-project/swc/issues/421 ignore, syntax(), |_| chain!( decorators(decorators::Config { legacy: true, ..Default::default() }), class_properties(), Classes::default() ), decorators_legacy_interop_local_define_property, r#" function dec() {} // Create a local function binding so babel has to change the name of the helper function _defineProperty() {} class A { @dec a; @dec b = 123; c = 456; } "#, r#" var _class, _descriptor, _descriptor2, _temp; function dec() {} // Create a local function binding so babel has to change the name of the helper function _defineProperty() {} let A = (_class = (_temp = function A() { "use strict"; _classCallCheck(this, A); _initializerDefineProperty(this, "a", _descriptor, this); _initializerDefineProperty(this, "b", _descriptor2, this); _defineProperty2(this, "c", 456); }, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "a", [dec], { configurable: true, enumerable: true, writable: true, initializer: null }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "b", [dec], { configurable: true, enumerable: true, writable: true, initializer: function () { return 123; } })), _class); "# ); // public_computed_without_block_exec test_exec!( syntax(), |_| class_properties(), public_computed_without_block_exec, r#" const createClass = (k) => class { [k()] = 2 }; const clazz = createClass(() => 'foo'); const instance = new clazz(); expect(instance.foo).toBe(2); "# ); // private_instance test!( syntax(), |_| chain!( class_properties(), exponentation(), Classes::default(), block_scoping(), ), private_instance, r#" class Foo { #bar = "foo"; } "#, r#" var Foo = function Foo() { "use strict"; _classCallCheck(this, Foo); _bar.set(this, { writable: true, value: "foo" }); }; var _bar = new WeakMap(); "# ); // static_property_tdz_general test!( syntax(), |_| chain!(class_properties(), Classes::default()), static_property_tdz_general, r#" class C { static [C + 3] = 3; } "#, r#" var _ref = (_classNameTDZError('C'), C) + 3; let C = function C() { "use strict"; _classCallCheck(this, C); }; _defineProperty(C, _ref, 3); "# ); // public_native_classes test!( syntax(), |_| chain!(class_properties(), block_scoping()), public_native_classes, r#" class Foo { static foo = "foo"; bar = "bar"; } "#, r#" class Foo { constructor() { _defineProperty(this, "bar", "bar"); } } _defineProperty(Foo, "foo", "foo"); "# ); // public_arrow_static_this_without_transform test!( // Emitting class properties is not supported yet. ignore, syntax(), |_| arrow(), public_arrow_static_this_without_transform, r#" class Foo { static fn = () => console.log(this); } "#, r#" var _this = this; class Foo { static fn = function () { return console.log(_this); }; } "# ); // private_static_infer_name test!( // Seems useless, while being hard to implement. ignore, syntax(), |_| chain!(class_properties(), block_scoping()), private_static_infer_name, r#" var Foo = class { static #num = 0; } "#, r#" var _class, _temp, _num; var Foo = (_temp = _class = class Foo {}, _num = { writable: true, value: 0 }, _temp); "# ); // regression_7951 test!( syntax(), |_| chain!(resolver(), class_properties()), regression_7951, r#" export class Foo extends Bar { static foo = {}; test = args; } "#, r#" export class Foo extends Bar { constructor(...args1) { super(...args1); _defineProperty(this, "test", args); } } _defineProperty(Foo, "foo", {}); "# ); // private_native_classes test!( syntax(), |_| chain!(class_properties(), block_scoping()), private_native_classes, r#" class Foo { static #foo = "foo"; #bar = "bar"; static test() { return Foo.#foo; } test() { return this.#bar; } } "#, r#" class Foo { static test() { return _classStaticPrivateFieldSpecGet(Foo, Foo, _foo); } test() { return _classPrivateFieldGet(this, _bar); } constructor() { _bar.set(this, { writable: true, value: "bar" }); } } var _foo = { writable: true, value: "foo" }; var _bar = new WeakMap(); "# ); // public_computed_without_block test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), public_computed_without_block, r#" const createClass = (k) => class { [k()] = 2 }; "#, r#" var createClass = (k)=>{ var _ref = k(); var _class = function _class() { 'use strict'; _classCallCheck(this, _class); _defineProperty(this, _ref, 2); }; return _class; }; "# ); // private_destructuring_array_pattern_2_exec test_exec!( syntax(), |_| class_properties(), private_destructuring_array_pattern_2_exec, r#" class Foo { #client constructor(props) { let x; ;([x, ...this.#client] = props); } getClient() { return this.#client; } } const foo = new Foo(['foo', 'bar', 'baz', 'quu']); expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']); "# ); // public_static_super test!( syntax(), |_| chain!(class_properties(), Classes::default(), block_scoping()), public_static_super, r#" class A { static prop = 1; } class B extends A { static prop = 2; static propA = super.prop; static getPropA = () => super.prop; } "#, r#" var A = function A() { "use strict"; _classCallCheck(this, A); }; _defineProperty(A, "prop", 1); var B = /*#__PURE__*/ function (A) { "use strict"; _inherits(B, A); function B() { _classCallCheck(this, B); return _possibleConstructorReturn(this, _getPrototypeOf(B).apply(this, arguments)); } return B; }(A); _defineProperty(B, "prop", 2); _defineProperty(B, "propA", _get(_getPrototypeOf(B), "prop", B)); _defineProperty(B, "getPropA", () => _get(_getPrototypeOf(B), "prop", B)); "# ); // private_destructuring_array_pattern_exec test_exec!( syntax(), |_| class_properties(), private_destructuring_array_pattern_exec, r#" class Foo { #client constructor(props) { ;([this.#client] = props); } getClient() { return this.#client; } } const foo = new Foo(['bar']); expect(foo.getClient()).toBe('bar'); "# ); // private_destructuring_array_pattern_1_exec test_exec!( syntax(), |_| class_properties(), private_destructuring_array_pattern_1_exec, r#" class Foo { #client constructor(props) { this.#client = 1; ;([this.x = this.#client, this.#client, this.y = this.#client] = props); } getClient() { return this.#client; } } const foo = new Foo([undefined, 'bar']); expect(foo.getClient()).toBe('bar'); expect(foo.x).toBe(1); expect(foo.y).toBe('bar'); "# );