Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[decorators] Correctly insert _initialize(this) after super(). #8970

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/babel-plugin-proposal-decorators/src/transformer.js
Expand Up @@ -113,6 +113,10 @@ const bareSupersVisitor = {
CallExpression(path, { initializeInstanceElements }) {
if (path.get("callee").isSuper()) {
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) {
Expand Down
@@ -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);
12 changes: 11 additions & 1 deletion packages/babel-traverse/src/path/modification.js
Expand Up @@ -105,7 +105,17 @@ export function insertAfter(nodes) {
parentPath.isExportNamedDeclaration() ||
(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 (
(this.isNodeType("Expression") && !this.isJSXElement()) ||
(parentPath.isForStatement() && this.key === "init")
Expand Down
8 changes: 6 additions & 2 deletions packages/babel-traverse/test/modification.js
Expand Up @@ -235,7 +235,9 @@ describe("modification", function() {
fnPath.insertAfter(t.identifier("x"));

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() {
Expand All @@ -246,7 +248,9 @@ describe("modification", function() {
fnPath.insertAfter(t.identifier("x"));

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() {
Expand Down