[decorators] Correctly insert _initialize(this) after super(). (#8970)
* [decorators] Correctly insert `_initialize(this)` after `super()`. This commit fixes to problem: 1) After `super();` statements, `_initialize(this)` was inserted without a trailing semicolon. 2) `(0, super())` causes an infinite recursion. * Fix tests * Add test
This commit is contained in:
parent
5d5cd8612f
commit
b706e34fc8
@ -113,6 +113,10 @@ const bareSupersVisitor = {
|
|||||||
CallExpression(path, { initializeInstanceElements }) {
|
CallExpression(path, { initializeInstanceElements }) {
|
||||||
if (path.get("callee").isSuper()) {
|
if (path.get("callee").isSuper()) {
|
||||||
path.insertAfter(t.cloneNode(initializeInstanceElements));
|
path.insertAfter(t.cloneNode(initializeInstanceElements));
|
||||||
|
|
||||||
|
// Sometimes this path gets requeued (e.g. in (super(), foo)), and
|
||||||
|
// it leads to infinite recursion.
|
||||||
|
path.skip();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Function(path) {
|
Function(path) {
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
@decorator(parameter)
|
||||||
|
class Sub extends Super {
|
||||||
|
constructor() {
|
||||||
|
super().method();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
let Sub = babelHelpers.decorate([decorator(parameter)], function (_initialize, _Super) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class Sub extends _Super {
|
||||||
|
constructor() {
|
||||||
|
var _temp;
|
||||||
|
|
||||||
|
(_temp = super(), _initialize(this), _temp).method();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
F: Sub,
|
||||||
|
d: []
|
||||||
|
};
|
||||||
|
}, Super);
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
@dec
|
||||||
|
class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
[];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
let B = babelHelpers.decorate([dec], function (_initialize, _A) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class B extends _A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
|
||||||
|
[];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
F: B,
|
||||||
|
d: []
|
||||||
|
};
|
||||||
|
}, A);
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
@dec
|
||||||
|
class B extends A {
|
||||||
|
constructor() {
|
||||||
|
(0, super());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
let B = babelHelpers.decorate([dec], function (_initialize, _A) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class B extends _A {
|
||||||
|
constructor() {
|
||||||
|
var _temp;
|
||||||
|
|
||||||
|
0, (_temp = super(), _initialize(this), _temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
F: B,
|
||||||
|
d: []
|
||||||
|
};
|
||||||
|
}, A);
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
@dec
|
||||||
|
class B extends A {
|
||||||
|
constructor() {
|
||||||
|
const foo = () => { super(); };
|
||||||
|
|
||||||
|
if (a) { super(); }
|
||||||
|
else { foo(); }
|
||||||
|
|
||||||
|
while (0) { super(); }
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
let B = babelHelpers.decorate([dec], function (_initialize, _A) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class B extends _A {
|
||||||
|
constructor() {
|
||||||
|
const foo = () => {
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (a) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
} else {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (0) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
F: B,
|
||||||
|
d: []
|
||||||
|
};
|
||||||
|
}, A);
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
@dec
|
||||||
|
class B extends A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
let B = babelHelpers.decorate([dec], function (_initialize, _A) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
class B extends _A {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
_initialize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
F: B,
|
||||||
|
d: []
|
||||||
|
};
|
||||||
|
}, A);
|
||||||
@ -105,7 +105,17 @@ export function insertAfter(nodes) {
|
|||||||
parentPath.isExportNamedDeclaration() ||
|
parentPath.isExportNamedDeclaration() ||
|
||||||
(parentPath.isExportDefaultDeclaration() && this.isDeclaration())
|
(parentPath.isExportDefaultDeclaration() && this.isDeclaration())
|
||||||
) {
|
) {
|
||||||
return parentPath.insertAfter(nodes);
|
return parentPath.insertAfter(
|
||||||
|
nodes.map(node => {
|
||||||
|
// Usually after an expression we can safely insert another expression:
|
||||||
|
// A.insertAfter(B)
|
||||||
|
// foo = A; -> foo = (A, B);
|
||||||
|
// If A is an expression statement, it isn't safe anymore so we need to
|
||||||
|
// convert B to an expression statement
|
||||||
|
// A; -> A; B // No semicolon! It could break if followed by [!
|
||||||
|
return t.isExpression(node) ? t.expressionStatement(node) : node;
|
||||||
|
}),
|
||||||
|
);
|
||||||
} else if (
|
} else if (
|
||||||
(this.isNodeType("Expression") && !this.isJSXElement()) ||
|
(this.isNodeType("Expression") && !this.isJSXElement()) ||
|
||||||
(parentPath.isForStatement() && this.key === "init")
|
(parentPath.isForStatement() && this.key === "init")
|
||||||
|
|||||||
@ -235,7 +235,9 @@ describe("modification", function() {
|
|||||||
fnPath.insertAfter(t.identifier("x"));
|
fnPath.insertAfter(t.identifier("x"));
|
||||||
|
|
||||||
expect(bodyPath.get("body")).toHaveLength(2);
|
expect(bodyPath.get("body")).toHaveLength(2);
|
||||||
expect(bodyPath.get("body.1").node).toEqual(t.identifier("x"));
|
expect(bodyPath.get("body.1").node).toEqual(
|
||||||
|
t.expressionStatement(t.identifier("x")),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("the ExportDefaultDeclaration, if a declaration is exported", function() {
|
it("the ExportDefaultDeclaration, if a declaration is exported", function() {
|
||||||
@ -246,7 +248,9 @@ describe("modification", function() {
|
|||||||
fnPath.insertAfter(t.identifier("x"));
|
fnPath.insertAfter(t.identifier("x"));
|
||||||
|
|
||||||
expect(bodyPath.get("body")).toHaveLength(2);
|
expect(bodyPath.get("body")).toHaveLength(2);
|
||||||
expect(bodyPath.get("body.1").node).toEqual(t.identifier("x"));
|
expect(bodyPath.get("body.1").node).toEqual(
|
||||||
|
t.expressionStatement(t.identifier("x")),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("the exported expression", function() {
|
it("the exported expression", function() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user