Skip to content

Commit 19bbe6d

Browse files
committed
add JavaScript support for new private fields syntax
1 parent d1a7fee commit 19bbe6d

File tree

9 files changed

+288
-198
lines changed

9 files changed

+288
-198
lines changed

javascript/extractor/src/com/semmle/jcorn/Parser.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,15 @@ protected Expression parseExprAtom(DestructuringErrors refDestructuringErrors) {
16461646
node = new ThisExpression(new SourceLocation(this.startLoc));
16471647
this.next();
16481648
return this.finishNode(node);
1649+
} else if (this.type == TokenType.pound) {
1650+
Position startLoc = this.startLoc;
1651+
// there is only one case where this is valid, and that is "Ergonomic brand checks for Private Fields", i.e. `#name in obj`.
1652+
Identifier id = parseIdent(true);
1653+
String op = String.valueOf(this.value);
1654+
if (!op.equals("in")) {
1655+
this.unexpected(startLoc);
1656+
}
1657+
return this.parseExprOp(id, this.start, startLoc, -1, false);
16491658
} else if (this.type == TokenType.name) {
16501659
Position startLoc = this.startLoc;
16511660
Identifier id = this.parseIdent(this.type != TokenType.name);
@@ -3314,9 +3323,6 @@ protected MemberDefinition<?> parseClassPropertyBody(
33143323
if (pi.kind.equals("set") && node.getValue().hasRest())
33153324
this.raiseRecoverable(params.get(params.size() - 1), "Setter cannot use rest params");
33163325
}
3317-
if (pi.key instanceof Identifier && ((Identifier)pi.key).getName().startsWith("#")) {
3318-
raiseRecoverable(pi.key, "Only fields, not methods, can be declared private.");
3319-
}
33203326
return node;
33213327
}
33223328

javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,8 +847,15 @@ public Label visit(AssignmentExpression nd, Context c) {
847847
@Override
848848
public Label visit(BinaryExpression nd, Context c) {
849849
Label key = super.visit(nd, c);
850-
visit(nd.getLeft(), key, 0, true);
850+
if (nd.getOperator().equals("in") && nd.getLeft() instanceof Identifier && ((Identifier)nd.getLeft()).getName().startsWith("#")) {
851+
// this happens with Ergonomic brand checks for Private Fields (see https://github.com/tc39/proposal-private-fields-in-in).
852+
// it's the only case where private field identifiers are used not as a field.
853+
visit(nd.getLeft(), key, 0, IdContext.LABEL, true);
854+
} else {
855+
visit(nd.getLeft(), key, 0, true);
856+
}
851857
visit(nd.getRight(), key, 1, true);
858+
852859
extractRegxpFromBinop(nd, c);
853860
return key;
854861
}

0 commit comments

Comments
 (0)