Skip to content

Commit

Permalink
Parse new.target.
Browse files Browse the repository at this point in the history
Summary:
Add parsing for the "MetaProperty" `new.target`, which is a `MemberExpression`.
We detect the `.` and create the `MetaPropertyNode` from that.

Reviewed By: tmikov

Differential Revision: D16421942

fbshipit-source-id: 9daf3151bbc04073c34f3a9cea7731e0f191b74e
  • Loading branch information
avp authored and facebook-github-bot committed Aug 14, 2019
1 parent 3cec787 commit c09c446
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 10 deletions.
27 changes: 26 additions & 1 deletion lib/Parser/JSParserImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ void JSParserImpl::initializeIdentifiers() {
methodIdent_ = lexer_.getIdentifier("method");
constructorIdent_ = lexer_.getIdentifier("constructor");
yieldIdent_ = lexer_.getIdentifier("yield");
newIdent_ = lexer_.getIdentifier("new");
targetIdent_ = lexer_.getIdentifier("target");

// Generate the string representation of all tokens.
for (unsigned i = 0; i != NUM_JS_TOKENS; ++i)
Expand Down Expand Up @@ -2544,7 +2546,30 @@ Optional<ESTree::Node *> JSParserImpl::parseNewExpressionOrMemberExpression() {
if (!check(TokenKind::rw_new))
return parseMemberExpressionExceptNew();

SMLoc startLoc = advance().Start;
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");
return None;
}
auto *meta = setLocation(
newRange,
newRange,
new (context_) ESTree::IdentifierNode(newIdent_, nullptr));
auto *prop = setLocation(
tok_,
tok_,
new (context_) ESTree::IdentifierNode(targetIdent_, nullptr));
advance();
return setLocation(
meta, prop, new (context_) ESTree::MetaPropertyNode(meta, prop));
}

auto optExpr = parseNewExpressionOrMemberExpression();
if (!optExpr)
Expand Down
2 changes: 2 additions & 0 deletions lib/Parser/JSParserImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ class JSParserImpl {
UniqueString *methodIdent_;
UniqueString *constructorIdent_;
UniqueString *yieldIdent_;
UniqueString *newIdent_;
UniqueString *targetIdent_;
/// String representation of all tokens.
UniqueString *tokenIdent_[NUM_JS_TOKENS];

Expand Down
3 changes: 1 addition & 2 deletions test/BCGen/HBC/es6/function-kinds.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
// This source code is licensed under the MIT license found in the LICENSE
// file in the root directory of this source tree.
//
// RUN: %hermes -Xflow-parser -target=HBC -dump-bytecode %s | %FileCheck --match-full-lines %s
// REQUIRES: flowparser
// RUN: %hermes -target=HBC -dump-bytecode %s | %FileCheck --match-full-lines %s

function normal() {}
//CHECK-LABEL:Function<normal>(1 params, {{.*}}):
Expand Down
3 changes: 1 addition & 2 deletions test/IRGen/es6/new-target.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
// This source code is licensed under the MIT license found in the LICENSE
// file in the root directory of this source tree.
//
// RUN: %hermesc -Xflow-parser -dump-ir %s | %FileCheck --match-full-lines %s
// REQUIRES: flowparser
// RUN: %hermesc -dump-ir %s | %FileCheck --match-full-lines %s

function func1() {
return new.target;
Expand Down
3 changes: 1 addition & 2 deletions test/Parser/es6/new-target-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
// This source code is licensed under the MIT license found in the LICENSE
// file in the root directory of this source tree.
//
// RUN: (! %hermesc -Xflow-parser -dump-ast -pretty-json %s 2>&1 ) | %FileCheck --match-full-lines %s
// REQUIRES: flowparser
// RUN: (! %hermesc -dump-ast -pretty-json %s 2>&1 ) | %FileCheck --match-full-lines %s

new.target;
// CHECK: {{.*}}:8:1: error: 'new.target' not in a function
Expand Down
49 changes: 49 additions & 0 deletions test/Parser/es6/new-target.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Facebook, Inc. and its affiliates.
//
// This source code is licensed under the MIT license found in the LICENSE
// file in the root directory of this source tree.
//
// RUN: %hermesc -dump-ast -pretty-json %s | %FileCheck %s --match-full-lines

// CHECK: {
// CHECK-NEXT: "type": "Program",
// CHECK-NEXT: "body": [

function foo() {
return new.target;
}
// CHECK-NEXT: {
// CHECK-NEXT: "type": "FunctionDeclaration",
// CHECK-NEXT: "id": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "foo",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// 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": "MetaProperty",
// CHECK-NEXT: "meta": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "new",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: },
// CHECK-NEXT: "property": {
// CHECK-NEXT: "type": "Identifier",
// CHECK-NEXT: "name": "target",
// CHECK-NEXT: "typeAnnotation": null
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "returnType": null,
// CHECK-NEXT: "generator": false
// CHECK-NEXT: }

// CHECK-NEXT: ]
// CHECK-NEXT: }
5 changes: 2 additions & 3 deletions test/hermes/es6/new-target.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
// This source code is licensed under the MIT license found in the LICENSE
// file in the root directory of this source tree.
//
// RUN: %hermes -Xflow-parser %s | %FileCheck --match-full-lines %s
// RUN: %hermes -Xflow-parser -O %s | %FileCheck --match-full-lines %s
// REQUIRES: flowparser
// RUN: %hermes %s | %FileCheck --match-full-lines %s
// RUN: %hermes -O %s | %FileCheck --match-full-lines %s

function foo() {
print(typeof new.target, new.target === foo);
Expand Down

0 comments on commit c09c446

Please sign in to comment.