0

According to this SO post, a CallExpression always contains a call and thus cannot be part of the expression following the new operator.

However, ECMAScript 2017 states:

MemberExpression:
   PrimaryExpression
   MemberExpression [Expression]
   MemberExpression .IdentifierName
   MemberExpression TemplateLiteral
   SuperProperty
   MetaProperty
   new MemberExpression Arguments

And:

NewExpression:
   MemberExpression
   new NewExpression

And:

CallExpression:
   CoverCallExpressionAndAsyncArrowHead
   SuperCall
   CallExpression Arguments
   CallExpression [Expression]
   CallExpression .IdentifierName
   CallExpression TemplateLiteral

And:

CoverCallExpressionAndAsyncArrowHead:
   MemberExpression Arguments

QUESTIONS

  1. Why is the MemberExpression Arguments production located in section 14.7 Async Arrow Function Definitions? Does Cover mean that the rule covers both CallExpression and AsyncArrowHead, and they just decided to put it in 14.7 instead of 12.3?
  2. According to the above productions, the below would be valid, thus breaking with the SO post linked above. Am I missing something? Why divide it in NewExpression and CallExpression, if NewExpression can contain CallExpression?

Apparently valid:

new new memberExpression(args);

Which is new new MemberExpression Arguments, which is identical to the first CallExpression production.

Magnus
  • 6,791
  • 8
  • 53
  • 84
  • I don't get your second question. Can you rephrase it maybe? `new new memberExpression(args);` is not parsed with a `CallExpression` anywhere. – Bergi Aug 02 '18 at 17:43
  • Hi @bergi. I just meant that `new MemberExpression Arguments` is in fact a valid `NewExpression`, and it also follows the same structure as a `CallExpression`: `const foo = new Bar()`. Note the parenthesis at the end. I guess because the parenthesis are optional, as Logan pointed out. – Magnus Aug 02 '18 at 17:48
  • Well the structure of the `Bar()` part might be identical between the `MemberExpression`/`NewExpression` and the `CallExpression`, but because there is a `new` in front of it the whole thing is not a `CallExpression`. – Bergi Aug 02 '18 at 17:57

1 Answers1

2

Why is the MemberExpression Arguments production located in section 14.7 Async Arrow Function Definitions? Does Cover mean that the rule covers both CallExpression and AsyncArrowHead, and they just decided to put it in 14.7 instead of 12.3?

This is because async isn't a keyword. That means that in a parser

async ()

is just a function call to a function called async. This means that in the context of a snippet like

async () =>

until the => is found, the parser cannot know what type of syntax it is actually parsing. This concept of something being a known set of tokens, with multiple possible output AST structures, is handled in the spec via what are called cover grammars.

What that essentially means in the general case in the spec is that CoverCallExpressionAndAsyncArrowHead defines essentially the union of the possible structures that you could find in an arrow function head, or in a function call. When the parser sees the =>, it says "Okay, the CoverCallExpressionAndAsyncArrowHead that I parsed is the head of an arrow function, and if it finds anything other than => then it knows that it was actually a function call.

According to the above productions, the below would be valid, thus breaking with the SO post linked above. Am I missing something? Why divide it in NewExpression and CallExpression, if NewExpression can contain CallExpression?

I'm also finding the wording in that other answer is a bit hard to follow, though I do think it is accurate. The short answer is that then are split up into NewExpression and CallExpression because CallExpression require parens, and NewExpression requires there not to be parens. For example, in the general sense new is a keyword that constructs whatever is on the right-hand side. If you do new Foo, it will construct Foo. If you do new obj.Foo it will read obj.Foo and then construct an object from it. This means that syntactically you can almost think of these as equivalent:

// 1
var _tmp = Foo;
new _tmp;

// 2
var _tmp = obj.Foo;
new _tmp;

but that's not true, because these are different:

// 3
var _tmp = Foo();
new _tmp;

// 4
new Foo();

The new keyword has optional parentheses, and it is this behavior that necessitates the division in the grammar. If we look at

NewExpression:
  MemberExpression
  new NewExpression

it always jumps straight to MemberExpression meaning that new obj() will treat the () as Arguments in new MemberExpression Arguments. Since CallExpression always handles the () for function calls, the NewExpression grammar is only applicable to the () that are optional for construction, whereas

CallExpression:
  CoverCallExpressionAndAsyncArrowHead
  SuperCall
  CallExpression Arguments
  CallExpression [Expression]
  CallExpression .IdentifierName
  CallExpression TemplateLiteral

handles all of the () cases that involve function calls that don't have new.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Thanks a lot Logan. Quick clarification: Did you mean that in `new obj()`, `obj()` is treated as `new MemberExpression Arguments` (not just the `()`-part)? Here is the grammar replacement I applied: `NewExpression: new NewExpression --> new MemberExpression --> new new MemberExpression Arguments`. Alternatively: `NewExpression: MemberExpression --> new MemberExpression Arguments` – Magnus Aug 02 '18 at 16:50
  • One other thing that was a bit unclear to me: What exactly is a `Left-Hand-Side Expression`, if it is not that which is supposed to be on the left-hand-side of an operator (like in an assignment)? Apparently, an assignment only works to a `LeftHandSideExpression` if the `LeftHandSideExpression` is of `Reference` type. – Magnus Aug 02 '18 at 16:53
  • Oh yeah, I meant that `()` would trigger the usage of the `new MemberExpression Argument` grammar. "Here is the grammar replacement I applied" I'm not sure I follow those examples. One has a single `new` keywords, and one has two, so only `NewExpression: MemberExpression --> new MemberExpression Arguments` would be applicable here. – loganfsmyth Aug 02 '18 at 17:01
  • I generally think of a left-hand side expression is essentially anything that can be assigned to. That behavior is defined nested the way it is because it doesn't know if something is a left-hand thing until you actually get to the `=`, so until then it's just maybe left-hand and maybe not. – loganfsmyth Aug 02 '18 at 17:09
  • Regarding what a LHS-expression is, the following SO post highlights something interesting: https://stackoverflow.com/questions/3709866/whats-a-valid-left-hand-side-expression-in-javascript-grammar. `new Object` is a valid `LeftHandSideExpression`, but it is not possible to assign to it (apparently because it is not a `Reference` type)? – Magnus Aug 02 '18 at 17:45
  • Regarding the double `new`: Got it, thanks. It was probably a bit unrelated, but according to the spec `new new new new Bar()` should be valid, but it gives an error when I try to run it. – Magnus Aug 02 '18 at 17:51
  • Multiple `new`s is fine, but the thing to the right still needs to be a function, so unless `new Bar()` returns a function, and so on down the chain, it will end up throwing an error. For assignment, the important assertions are https://tc39.github.io/ecma262/#sec-assignment-operators-static-semantics-early-errors. The left needs the right AssignmentTargetType, or else it's considered invalid. `new Object` is valid in the grammar, but excluded by early errors because it is `invalid` in https://tc39.github.io/ecma262/#sec-static-semantics-static-semantics-assignmenttargettype – loganfsmyth Aug 02 '18 at 17:57
  • Ah, got it regarding evaluating multiple `new`s. In case others stumble across this, the behavior is specified here: http://www.ecma-international.org/ecma-262/8.0/#sec-new-operator-runtime-semantics-evaluation (particularly `12.3.3.1.1 (7)`). Regarding the `AssignmentTargetType`, it is not listed as invalid here, as far as I can tell: http://www.ecma-international.org/ecma-262/8.0/#sec-assignment-operators-static-semantics-isvalidsimpleassignmenttarget. Seems ok with just `new MemberExpression`? – Magnus Aug 02 '18 at 18:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177299/discussion-between-loganfsmyth-and-magnus). – loganfsmyth Aug 02 '18 at 19:16