babel/packages/babel-traverse/test/arrow-transform.js
Logan Smyth 14584c218c Kill the "shadow-functions.js" internal plugin in favor of an explicit helper (#5677)
* Handle arrow function processing via shared API rather than default plugin.

* Fix a few small PR comments.

* Preserve existing spec arrow 'this' rewrites, and support spec in subclass constructors.
2017-05-05 13:27:18 -07:00

499 lines
10 KiB
JavaScript

import { NodePath } from "../lib";
import assert from "assert";
import { parse } from "babylon";
import generate from "babel-generator";
import * as t from "babel-types";
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: {
file: {
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);
},
});
assert.equal(generate(inputAst).code, 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" });
});
it("should convert super calls and this references in constructors", () => {
assertConversion(`
() => {
super(345);
this;
};
super();
this;
() => super();
() => this;
`, `
var _supercall = (..._args) => _this = super(..._args),
_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;
});
_this = super();
this;
() => _this = super();
() => 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);
_this = super();
this;
() => _this = super();
() => 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(`
() => {
<this.this this="" />;
};
<this.this this="" />;
() => <this.this this="" />;
`, `
var _this = this;
(function () {
<_this.this this="" />;
});
<this.this this="" />;
() => <this.this 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", () => {
assertConversion(`
() => {
super.foo();
};
super.foo();
() => super.foo();
`, `
var _superprop_callFoo = (..._args) => super.foo(..._args);
(function () {
_superprop_callFoo();
});
super.foo();
() => super.foo();
`);
});
it("should convert super[prop]() calls", () => {
assertConversion(`
() => {
super[foo]();
};
super[foo]();
() => super[foo]();
`, `
var _superprop_call = (_prop, ..._args) => super[_prop](..._args);
(function () {
_superprop_call(foo);
});
super[foo]();
() => super[foo]();
`);
});
});