Never extract class fields into an initializer function. (#7659)

It was needed to avoid collision of identifiers used in fields
initializers with variables declared in the constructor, but it
broke `this` handling.
This commit removes that behavior and instead renames the
colliding variables.
This commit is contained in:
Nicolò Ribaudo 2018-04-05 17:20:47 +02:00 committed by Justin Ridgewell
parent 43040a4181
commit fa2c6c5164
6 changed files with 44 additions and 77 deletions

View File

@ -22,7 +22,7 @@ export default declare((api, options) => {
},
ReferencedIdentifier(path) {
if (this.scope.hasOwnBinding(path.node.name)) {
this.collision = true;
this.scope.rename(path.node.name);
path.skip();
}
},
@ -115,7 +115,7 @@ export default declare((api, options) => {
const computedNodes = [];
const staticNodes = [];
let instanceBody = [];
const instanceBody = [];
for (const computedPath of computedPaths) {
const computedNode = computedPath.node;
@ -175,46 +175,8 @@ export default declare((api, options) => {
[constructor] = body.unshiftContainer("body", newConstructor);
}
const collisionState = {
collision: false,
scope: constructor.scope,
};
for (const prop of props) {
prop.traverse(referenceVisitor, collisionState);
if (collisionState.collision) break;
}
if (collisionState.collision) {
const initialisePropsRef = path.scope.generateUidIdentifier(
"initialiseProps",
);
afterNodes.push(
t.variableDeclaration("var", [
t.variableDeclarator(
initialisePropsRef,
t.functionExpression(
null,
[],
t.blockStatement(instanceBody),
),
),
]),
);
instanceBody = [
t.expressionStatement(
t.callExpression(
t.memberExpression(
t.cloneNode(initialisePropsRef),
t.identifier("call"),
),
[t.thisExpression()],
),
),
];
}
const state = { scope: constructor.scope };
for (const prop of props) prop.traverse(referenceVisitor, state);
//

View File

@ -2,17 +2,11 @@ var foo = "bar";
var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_initialiseProps.call(this);
var foo = "foo";
};
var _initialiseProps = function () {
Object.defineProperty(this, "bar", {
configurable: true,
enumerable: true,
writable: true,
value: foo
});
var _foo = "foo";
};

View File

@ -0,0 +1,6 @@
class A {
force = force;
foo = super.method();
constructor(force) {}
}

View File

@ -0,0 +1,15 @@
var A = function A(_force) {
babelHelpers.classCallCheck(this, A);
Object.defineProperty(this, "force", {
configurable: true,
enumerable: true,
writable: true,
value: force
});
Object.defineProperty(this, "foo", {
configurable: true,
enumerable: true,
writable: true,
value: babelHelpers.get(A.prototype.__proto__ || Object.getPrototypeOf(A.prototype), "method", babelHelpers.assertThisInitialized(this)).call(this)
});
};

View File

@ -2,12 +2,6 @@ var foo = "bar";
var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_initialiseProps.call(this);
var foo = "foo";
};
var _initialiseProps = function () {
this.bar = foo;
var _foo = "foo";
};

View File

@ -56,8 +56,23 @@ var _this = this;
(function () {
class Baz {
constructor(force) {
_initialiseProps.call(this);
constructor(_force) {
var _this4 = this;
Object.defineProperty(this, "fn", {
configurable: true,
enumerable: true,
writable: true,
value: function () {
return console.log(_this4);
}
});
Object.defineProperty(this, "force", {
configurable: true,
enumerable: true,
writable: true,
value: force
});
}
}
@ -70,25 +85,6 @@ var _this = this;
return console.log(_this);
}
});
var _initialiseProps = function () {
var _this4 = this;
Object.defineProperty(this, "fn", {
configurable: true,
enumerable: true,
writable: true,
value: function () {
return console.log(_this4);
}
});
Object.defineProperty(this, "force", {
configurable: true,
enumerable: true,
writable: true,
value: force
});
};
});
var qux = function () {