Handle private access chained on an optional chain (#11248)

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>
This commit is contained in:
Justin Ridgewell
2020-05-26 16:16:50 -04:00
committed by Nicolò Ribaudo
parent 852520eff5
commit bda759ac3d
104 changed files with 6964 additions and 37 deletions

View File

@@ -128,8 +128,12 @@ const privateNameVisitor = privateNameVisitorFactory({
const { privateNamesMap, redeclared } = this;
const { node, parentPath } = path;
if (!parentPath.isMemberExpression({ property: node })) return;
if (
!parentPath.isMemberExpression({ property: node }) &&
!parentPath.isOptionalMemberExpression({ property: node })
) {
return;
}
const { name } = node.id;
if (!privateNamesMap.has(name)) return;
if (redeclared && redeclared.includes(name)) return;
@@ -296,23 +300,43 @@ const privateNameHandlerSpec = {
// The first access (the get) should do the memo assignment.
this.memoise(member, 1);
return optimiseCall(this.get(member), this.receiver(member), args);
return optimiseCall(this.get(member), this.receiver(member), args, false);
},
optionalCall(member, args) {
this.memoise(member, 1);
return optimiseCall(this.get(member), this.receiver(member), args, true);
},
};
const privateNameHandlerLoose = {
handle(member) {
get(member) {
const { privateNamesMap, file } = this;
const { object } = member.node;
const { name } = member.node.property.id;
member.replaceWith(
template.expression`BASE(REF, PROP)[PROP]`({
BASE: file.addHelper("classPrivateFieldLooseBase"),
REF: object,
PROP: privateNamesMap.get(name).id,
}),
);
return template.expression`BASE(REF, PROP)[PROP]`({
BASE: file.addHelper("classPrivateFieldLooseBase"),
REF: object,
PROP: privateNamesMap.get(name).id,
});
},
simpleSet(member) {
return this.get(member);
},
destructureSet(member) {
return this.get(member);
},
call(member, args) {
return t.callExpression(this.get(member), args);
},
optionalCall(member, args) {
return t.optionalCallExpression(this.get(member), args, true);
},
};
@@ -326,21 +350,14 @@ export function transformPrivateNamesUsage(
if (!privateNamesMap.size) return;
const body = path.get("body");
const handler = loose ? privateNameHandlerLoose : privateNameHandlerSpec;
if (loose) {
body.traverse(privateNameVisitor, {
privateNamesMap,
file: state,
...privateNameHandlerLoose,
});
} else {
memberExpressionToFunctions(body, privateNameVisitor, {
privateNamesMap,
classRef: ref,
file: state,
...privateNameHandlerSpec,
});
}
memberExpressionToFunctions(body, privateNameVisitor, {
privateNamesMap,
classRef: ref,
file: state,
...handler,
});
body.traverse(privateInVisitor, {
privateNamesMap,
classRef: ref,