import { NodePath } from "../lib/index.js"; import { parse } from "@babel/parser"; import * as t from "@babel/types"; import _generate from "@babel/generator"; const generate = _generate.default; function assertConversion( input, output, { methodName = "method", extend = false, arrowOpts } = {}, ) { const inputAst = wrapMethod(input, methodName, extend); const outputAst = wrapMethod(output, methodName, extend); const rootPath = NodePath.get({ hub: { addHelper(helperName) { return t.memberExpression( t.identifier("babelHelpers"), t.identifier(helperName), ); }, }, parentPath: null, parent: inputAst, container: inputAst, key: "program", }).setContext(); rootPath.traverse({ ClassMethod(path) { path.get("body.body.0.expression").arrowFunctionToExpression(arrowOpts); }, }); expect(generate(inputAst).code).toBe(generate(outputAst).code); } function wrapMethod(body, methodName, extend) { return parse( ` class Example ${extend ? "extends class {}" : ""} { ${methodName}() {${body} } } `, { plugins: ["jsx"] }, ); } describe("arrow function conversion", () => { it("should convert super calls in constructors", () => { assertConversion( ` () => { super(345); }; super(); () => super(); `, ` var _supercall = (..._args) => super(..._args); (function () { _supercall(345); }); _supercall(); () => _supercall(); `, { methodName: "constructor", extend: true }, ); }); it("should convert super calls in constructors used in computed method keys", () => { assertConversion( ` () => ({ [super()]: 123, get [super() + "1"]() {}, [super()]() {}, }); `, ` var _supercall = (..._args) => super(..._args); (function () { return { [_supercall()]: 123, get [_supercall() + "1"]() {}, [_supercall()]() {}, }; }); `, { methodName: "constructor", extend: true }, ); }); it("should convert super calls and this references in constructors", () => { assertConversion( ` () => { super(345); this; }; super(); this; () => super(); () => this; `, ` var _supercall = (..._args) => (super(..._args), _this = this), _this; (function () { _supercall(345); _this; }); _supercall(); this; () => _supercall(); () => this; `, { methodName: "constructor", extend: true }, ); }); it("should convert this references in constructors", () => { assertConversion( ` () => { this; }; super(); this; () => super(); () => this; `, ` var _this; (function () { _this; }); super(); _this = this; this; () => (super(), _this = this); () => this; `, { methodName: "constructor", extend: true }, ); }); it("should convert this references in constructors with super() used in computed method keys", () => { assertConversion( ` () => this; ({ [super()]: 123, get [super() + "1"]() {}, [super()]() {}, }); `, ` var _this; (function () { return _this; }); ({ [(super(), _this = this)]: 123, get [(super(), _this = this) + "1"]() {}, [(super(), _this = this)]() {}, }); `, { methodName: "constructor", extend: true }, ); }); it("should convert this references in constructors with spec compliance", () => { assertConversion( ` () => { this; }; super(); this; () => super(); () => this; `, ` var _this, _arrowCheckId = {}; (function () { babelHelpers.newArrowCheck(this, _arrowCheckId); _this; }).bind(_arrowCheckId); super(); _this = this; this; () => (super(), _this = this); () => this; `, { methodName: "constructor", extend: true, arrowOpts: { specCompliant: true }, }, ); }); it("should convert this references in constructors without extension", () => { assertConversion( ` () => { this; }; this; () => this; `, ` var _this = this; (function () { _this; }); this; () => this; `, { methodName: "constructor" }, ); }); it("should convert this references in constructors with spec compliance without extension", () => { assertConversion( ` () => { this; }; this; () => this; `, ` var _this = this; (function () { babelHelpers.newArrowCheck(this, _this); this; }).bind(this); this; () => this; `, { methodName: "constructor", arrowOpts: { specCompliant: true } }, ); }); it("should convert this references in methods", () => { assertConversion( ` () => { this; }; this; () => this; `, ` var _this = this; (function () { _this; }); this; () => this; `, ); }); it("should convert this references in methods with spec compliance", () => { assertConversion( ` () => { this; }; this; () => this; `, ` var _this = this; (function () { babelHelpers.newArrowCheck(this, _this); this; }).bind(this); this; () => this; `, { arrowOpts: { specCompliant: true } }, ); }); it("should convert this references inside JSX in methods", () => { assertConversion( ` () => { ; }; ; () => ; `, ` var _this = this; (function () { <_this.this this="" />; }); ; () => ; `, ); }); it("should convert this references used in computed method keys", () => { assertConversion( ` () => ({ [this]: 123, get [this + "1"]() {}, [this]() {}, }); `, ` var _this = this; (function () { return { [_this]: 123, get [_this + "1"]() {}, [_this]() {}, }; }); `, ); }); it("should convert arguments references", () => { assertConversion( ` () => { arguments; }; arguments; () => arguments; `, ` var _arguments = arguments; (function () { _arguments; }); arguments; () => arguments; `, ); }); it("should convert new.target references", () => { assertConversion( ` () => { new.target; }; new.target; () => new.target; `, ` var _newtarget = new.target; (function () { _newtarget; }); new.target; () => new.target; `, ); }); it("should convert super.prop references", () => { assertConversion( ` () => { var tmp = super.foo; }; super.foo; () => super.foo; `, ` var _superprop_getFoo = () => super.foo; (function () { var tmp = _superprop_getFoo(); }); super.foo; () => super.foo; `, ); }); it("should convert super[prop] references", () => { assertConversion( ` () => { var tmp = super[foo]; }; super[foo]; () => super[foo]; `, ` var _superprop_get = _prop => super[_prop]; (function () { var tmp = _superprop_get(foo); }); super[foo]; () => super[foo]; `, ); }); it("should convert super.prop assignment", () => { assertConversion( ` () => { super.foo = 4; }; super.foo = 4; () => super.foo = 4; `, ` var _superprop_setFoo = _value => super.foo = _value; (function () { _superprop_setFoo(4); }); super.foo = 4; () => super.foo = 4; `, ); }); it("should convert super[prop] assignment", () => { assertConversion( ` () => { super[foo] = 4; }; super[foo] = 4; () => super[foo] = 4; `, ` var _superprop_set = (_prop, _value) => super[_prop] = _value; (function () { _superprop_set(foo, 4); }); super[foo] = 4; () => super[foo] = 4; `, ); }); it("should convert super.prop operator assign", () => { assertConversion( ` () => { super.foo **= 4; }; super.foo **= 4; () => super.foo **= 4; `, ` var _superprop_setFoo = _value => super.foo = _value, _superprop_getFoo = () => super.foo; (function () { _superprop_setFoo(_superprop_getFoo() ** 4); }); super.foo **= 4; () => super.foo **= 4; `, ); }); it("should convert super[prop] operator assign", () => { assertConversion( ` () => { super[foo] **= 4; }; super[foo] **= 4; () => super[foo] **= 4; `, ` var _superprop_set = (_prop, _value) => super[_prop] = _value, _superprop_get = _prop2 => super[_prop2]; (function () { var _tmp; _superprop_set(_tmp = foo, _superprop_get(_tmp) ** 4); }); super[foo] **= 4; () => super[foo] **= 4; `, ); }); it("should convert super.prop prefix update", () => { assertConversion( ` () => { ++super.foo; }; ++super.foo; () => ++super.foo; `, ` var _superprop_getFoo = () => super.foo, _superprop_setFoo = _value => super.foo = _value; (function () { var _tmp; _tmp = _superprop_getFoo(), _superprop_setFoo(_tmp + 1); }); ++super.foo; () => ++super.foo; `, ); }); it("should convert super[prop] prefix update", () => { assertConversion( ` () => { ++super[foo]; }; ++super[foo]; () => ++super[foo]; `, ` var _superprop_get = _prop2 => super[_prop2], _superprop_set = (_prop3, _value) => super[_prop3] = _value; (function () { var _tmp, _prop; _tmp = _superprop_get(_prop = foo), _superprop_set(_prop, _tmp + 1); }); ++super[foo]; () => ++super[foo]; `, ); }); it("should convert super.prop suffix update", () => { assertConversion( ` () => { super.foo++; }; super.foo++; () => super.foo++; `, ` var _superprop_getFoo = () => super.foo, _superprop_setFoo = _value => super.foo = _value; (function () { var _tmp; _tmp = _superprop_getFoo(), _superprop_setFoo(_tmp + 1), _tmp; }); super.foo++; () => super.foo++; `, ); }); it("should convert super[prop] suffix update", () => { assertConversion( ` () => { super[foo]++; }; super[foo]++; () => super[foo]++; `, ` var _superprop_get = _prop2 => super[_prop2], _superprop_set = (_prop3, _value) => super[_prop3] = _value; (function () { var _tmp, _prop; _tmp = _superprop_get(_prop = foo), _superprop_set(_prop, _tmp + 1), _tmp; }); super[foo]++; () => super[foo]++; `, ); }); it("should convert super.prop() calls without params", () => { assertConversion( ` () => { super.foo(); }; super.foo(); () => super.foo(); `, ` var _superprop_getFoo = () => super.foo, _this = this; (function () { _superprop_getFoo().call(_this); }); super.foo(); () => super.foo(); `, ); }); it("should convert super.prop() calls with params", () => { assertConversion( ` () => { super.foo(a, b, ...c); }; super.foo(a, b, ...c); () => super.foo(a, b, ...c); `, ` var _superprop_getFoo = () => super.foo, _this = this; (function () { _superprop_getFoo().call(_this, a, b, ...c); }); super.foo(a, b, ...c); () => super.foo(a, b, ...c); `, ); }); it("should convert super[prop]() calls", () => { assertConversion( ` () => { super[foo](); }; super[foo](); () => super[foo](); `, ` var _superprop_get = _prop => super[_prop], _this = this; (function () { _superprop_get(foo).call(_this); }); super[foo](); () => super[foo](); `, ); }); });