Skip to content

Commit

Permalink
Parse super property accesses.
Browse files Browse the repository at this point in the history
Summary:
We need to parse MemberExpressionExceptNew here because `super` is not
`new`. Check for `super` and use the `SuperNode` instead of parsing
a primary expression.

Reviewed By: tmikov

Differential Revision: D16421943

fbshipit-source-id: ac20ee332805e58a297862cc6b194c510433edd8
  • Loading branch information
avp authored and facebook-github-bot committed Aug 14, 2019
1 parent c09c446 commit 695a898
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 9 deletions.
33 changes: 24 additions & 9 deletions lib/Parser/JSParserImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2372,11 +2372,20 @@ Optional<ESTree::Node *> JSParserImpl::parseMemberExpressionExceptNew() {
SMLoc startLoc = tok_->getStartLoc();

ESTree::NodePtr expr;
bool allowTemplateLiteral = true;

auto primExpr = parsePrimaryExpression();
if (!primExpr)
return None;
expr = primExpr.getValue();
if (check(TokenKind::rw_super)) {
// SuperProperty can be used the same way as PrimaryExpression, but
// must not have a TemplateLiteral immediately after the `super` keyword.
expr = setLocation(tok_, tok_, new (context_) ESTree::SuperNode());
advance();
allowTemplateLiteral = false;
} else {
auto primExpr = parsePrimaryExpression();
if (!primExpr)
return None;
expr = primExpr.getValue();
}

SMLoc objectLoc = startLoc;
while (check(TokenKind::l_square, TokenKind::period) ||
Expand All @@ -2392,6 +2401,12 @@ Optional<ESTree::Node *> JSParserImpl::parseMemberExpressionExceptNew() {
expr = msel.getValue();
} else {
assert(checkTemplateLiteral());
if (!allowTemplateLiteral) {
sm_.error(
expr->getSourceRange(),
"invalid use of 'super' as a template literal tag");
return None;
}
// MemberExpression TemplateLiteral
auto optTemplate = parseTemplateLiteral(ParamTagged);
if (!optTemplate)
Expand All @@ -2403,6 +2418,7 @@ Optional<ESTree::Node *> JSParserImpl::parseMemberExpressionExceptNew() {
expr, optTemplate.getValue()));
objectLoc = nextObjectLoc;
}
allowTemplateLiteral = true;
}

return expr;
Expand Down Expand Up @@ -2547,15 +2563,14 @@ Optional<ESTree::Node *> JSParserImpl::parseNewExpressionOrMemberExpression() {
return parseMemberExpressionExceptNew();

SMRange newRange = advance();
SMLoc startLoc = newRange.Start;

if (checkAndEat(TokenKind::period)) {
// NewTarget: new . target
// ^
if (!check(targetIdent_)) {
sm_.error(
tok_->getSourceRange(), "'target' expected in member expression");
sm_.note(startLoc, "start of member expression");
sm_.note(newRange.Start, "start of member expression");
return None;
}
auto *meta = setLocation(
Expand All @@ -2580,7 +2595,7 @@ Optional<ESTree::Node *> JSParserImpl::parseNewExpressionOrMemberExpression() {
// was a 'new MemberExpression(args)', otherwise it is a NewExpression
if (!check(TokenKind::l_paren)) {
return setLocation(
startLoc,
newRange,
expr,
new (context_) ESTree::NewExpressionNode(expr, ESTree::NodeList{}));
}
Expand All @@ -2592,12 +2607,12 @@ Optional<ESTree::Node *> JSParserImpl::parseNewExpressionOrMemberExpression() {
return None;

expr = setLocation(
startLoc,
newRange,
endLoc,
debugLoc,
new (context_) ESTree::NewExpressionNode(expr, std::move(argList)));

SMLoc objectLoc = startLoc;
SMLoc objectLoc = newRange.Start;
while (check(TokenKind::l_square, TokenKind::period)) {
SMLoc nextObjectLoc = tok_->getStartLoc();
auto optMSel = parseMemberSelect(objectLoc, expr);
Expand Down
9 changes: 9 additions & 0 deletions test/Parser/es6/class-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@
// CHECK: {{.*}}:9:3: note: first constructor definition
// CHECK: 'constructor'() {}
// CHECK: ^~~~~~~~~~~~~~~~~~

(class Foo {
constructor() {
super`asdf`;
}
});
// CHECK: {{.*}}:21:5: error: invalid use of 'super' as a template literal tag
// CHECK: super`asdf`;
// CHECK: ^~~~~
143 changes: 143 additions & 0 deletions test/Parser/es6/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,149 @@
// CHECK-NEXT: "directive": null
// CHECK-NEXT: },

class UseSuperProps {
constructor() {
super();
}

foo() {
return super.x.y;
}

bar() {
return super['x'];
}
}
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ClassDeclaration",
// CHECK-NEXT: "id": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "UseSuperProps",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "superClass": null,
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "ClassBody",
// CHECK-NEXT: "body": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "MethodDefinition",
// CHECK-NEXT: "key": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "constructor",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "FunctionExpression",
// CHECK-NEXT: "id": null,
// CHECK-NEXT: "params": [],
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "BlockStatement",
// CHECK-NEXT: "body": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ExpressionStatement",
// CHECK-NEXT: "expression": {
// CHECK-NEXT: "type": "CallExpression",
// CHECK-NEXT: "callee": {
// CHECK-NEXT: "type": "Super"
// CHECK-NEXT: },
// CHECK-NEXT: "arguments": []
// CHECK-NEXT: },
// CHECK-NEXT: "directive": null
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "generator": false
// CHECK-NEXT: },
// CHECK-NEXT: "kind": "constructor",
// CHECK-NEXT: "computed": false,
// CHECK-NEXT: "static": false
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "type": "MethodDefinition",
// CHECK-NEXT: "key": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "foo",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "FunctionExpression",
// CHECK-NEXT: "id": null,
// CHECK-NEXT: "params": [],
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "BlockStatement",
// CHECK-NEXT: "body": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ReturnStatement",
// CHECK-NEXT: "argument": {
// CHECK-NEXT: "type": "MemberExpression",
// CHECK-NEXT: "object": {
// CHECK-NEXT: "type": "MemberExpression",
// CHECK-NEXT: "object": {
// CHECK-NEXT: "type": "Super"
// CHECK-NEXT: },
// CHECK-NEXT: "property": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "x",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "computed": false
// CHECK-NEXT: },
// CHECK-NEXT: "property": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "y",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "computed": false
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "generator": false
// CHECK-NEXT: },
// CHECK-NEXT: "kind": "method",
// CHECK-NEXT: "computed": false,
// CHECK-NEXT: "static": false
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "type": "MethodDefinition",
// CHECK-NEXT: "key": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "bar",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "value": {
// CHECK-NEXT: "type": "FunctionExpression",
// CHECK-NEXT: "id": null,
// CHECK-NEXT: "params": [],
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "BlockStatement",
// CHECK-NEXT: "body": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ReturnStatement",
// CHECK-NEXT: "argument": {
// CHECK-NEXT: "type": "MemberExpression",
// CHECK-NEXT: "object": {
// CHECK-NEXT: "type": "Super"
// CHECK-NEXT: },
// CHECK-NEXT: "property": {
// CHECK-NEXT: "type": "StringLiteral",
// CHECK-NEXT: "value": "x"
// CHECK-NEXT: },
// CHECK-NEXT: "computed": true
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "generator": false
// CHECK-NEXT: },
// CHECK-NEXT: "kind": "method",
// CHECK-NEXT: "computed": false,
// CHECK-NEXT: "static": false
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: },

(class ConsProperty {
get ['constructor']() {}
set ['constructor'](val) {}
Expand Down

0 comments on commit 695a898

Please sign in to comment.