Fix class properties after nested class' bare super (#7671)

* Fix class properties after nested class' bare super

Fixes #7371.

* Fix node 4 test

* This damn node 4 test

* All of the ClassBody, but not the methods or field inits

* tmp

* tmp

* Use common class environment visitor

* Tests

* Use skipKey to avoid recursive traversal

* Remove old state

* Use jest expect
This commit is contained in:
Justin Ridgewell
2018-04-14 13:48:38 -04:00
committed by GitHub
parent 39b05598a0
commit 668358c4d0
12 changed files with 436 additions and 100 deletions

View File

@@ -1,25 +1,31 @@
import { declare } from "@babel/helper-plugin-utils";
import nameFunction from "@babel/helper-function-name";
import syntaxClassProperties from "@babel/plugin-syntax-class-properties";
import { template, types as t } from "@babel/core";
import { template, traverse, types as t } from "@babel/core";
import { environmentVisitor } from "@babel/helper-replace-supers";
export default declare((api, options) => {
api.assertVersion(7);
const { loose } = options;
const findBareSupers = {
Super(path) {
if (path.parentPath.isCallExpression({ callee: path.node })) {
this.push(path.parentPath);
}
const findBareSupers = traverse.visitors.merge([
{
Super(path) {
const { node, parentPath } = path;
if (parentPath.isCallExpression({ callee: node })) {
this.push(parentPath);
}
},
},
};
environmentVisitor,
]);
const referenceVisitor = {
"TSTypeAnnotation|TypeAnnotation"(path) {
path.skip();
},
ReferencedIdentifier(path) {
if (this.scope.hasOwnBinding(path.node.name)) {
this.scope.rename(path.node.name);
@@ -28,25 +34,22 @@ export default declare((api, options) => {
},
};
const ClassFieldDefinitionEvaluationTDZVisitor = {
Expression(path) {
if (path === this.shouldSkip) {
path.skip();
}
},
const classFieldDefinitionEvaluationTDZVisitor = traverse.visitors.merge([
{
ReferencedIdentifier(path) {
if (this.classRef === path.scope.getBinding(path.node.name)) {
const classNameTDZError = this.file.addHelper("classNameTDZError");
const throwNode = t.callExpression(classNameTDZError, [
t.stringLiteral(path.node.name),
]);
ReferencedIdentifier(path) {
if (this.classRef === path.scope.getBinding(path.node.name)) {
const classNameTDZError = this.file.addHelper("classNameTDZError");
const throwNode = t.callExpression(classNameTDZError, [
t.stringLiteral(path.node.name),
]);
path.replaceWith(t.sequenceExpression([throwNode, path.node]));
path.skip();
}
path.replaceWith(t.sequenceExpression([throwNode, path.node]));
path.skip();
}
},
},
};
environmentVisitor,
]);
const buildClassPropertySpec = (ref, { key, value, computed }, scope) => {
return template.statement`
@@ -122,10 +125,9 @@ export default declare((api, options) => {
// Make sure computed property names are only evaluated once (upon class definition)
// and in the right order in combination with static properties
if (!computedPath.get("key").isConstantExpression()) {
computedPath.traverse(ClassFieldDefinitionEvaluationTDZVisitor, {
computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, {
classRef: path.scope.getBinding(ref.name),
file: this.file,
shouldSkip: computedPath.get("value"),
});
const ident = path.scope.generateUidIdentifierBasedOnNode(
computedNode.key,