Arrow function followed by divide or syntax error?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Arrow function followed by divide or syntax error?

Gareth Heyes
Hi all

I'd like to discuss this:-

x=x=>{}/alert(1)/+alert(2)// alerts on edge, syntax error on other browsers

So on Edge it results in two alerts but every other browser it's a syntax error. Personally I think Edge is right here because it's a function expression so why can't you use divide after.

x=>{}
/alert(1)/+alert(2)//alerts twice on edge, once on other browsers

Cheers
Gareth

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Claude Pache
> Le 23 mai 2017 à 16:34, Gareth Heyes <[hidden email]> a écrit :
>
> Hi all
>
> I'd like to discuss this:-
>
> x=x=>{}/alert(1)/+alert(2)// alerts on edge, syntax error on other browsers
>
> So on Edge it results in two alerts but every other browser it's a syntax error. Personally I think Edge is right here because it's a function expression so why can't you use divide after.

This is not specific to the divide operator. If you try:

```js
x => {} * alert(1)
```

you'll get a SyntaxError in all browsers but Edge, which interprets it as `(x => {}) * alert(1)`.

Given how confusing that expression is, I think that the SyntaxError is the right choice.

>
> x=>{}
> /alert(1)/+alert(2)//alerts twice on edge, once on other browsers

This follows from the ASI rules: non-Edge browsers add a missing semicolon between the two lines, because otherwise it would be a syntax error for them.

—Claude

>
> Cheers
> Gareth
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Gareth Heyes
On 23 May 2017 at 17:01, Claude Pache <[hidden email]> wrote:
This is not specific to the divide operator. If you try:

```js
x => {} * alert(1)
```


Yeah of course I mentioned divide because it's more interesting because it can lead to js sandbox escapes.
 
you'll get a SyntaxError in all browsers but Edge, which interprets it as `(x => {}) * alert(1)`.

Given how confusing that expression is, I think that the SyntaxError is the right choice.

 Well it is a function expression. So IMO Edge is right. It's equivalent to:
x=function(){} * alert(1)

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Andreas Rossberg-4
On 24 May 2017 at 08:57, Gareth Heyes <[hidden email]> wrote:
 
you'll get a SyntaxError in all browsers but Edge, which interprets it as `(x => {}) * alert(1)`.

Given how confusing that expression is, I think that the SyntaxError is the right choice.

 Well it is a function expression. So IMO Edge is right. It's equivalent to:
x=function(){} * alert(1)

Edge is wrong. Unlike an ordinary function expression, which is a PrimaryExpression, an arrow function is merely an AssigmentExpression, so has much lower precedence than any arithmetic operator. The rationale is that its body doesn't necessarily have braces, so `x => x * 1` would be ambiguous.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Peter van der Zee
> Unlike an ordinary function expression, which is a PrimaryExpression, an arrow function is merely an AssigmentExpression, so has much lower precedence than any arithmetic operator.

I'm curious how this should be parsed so let's break this down.

Given the following "Script" (I don't think the actual goal matters much here):
```
x=x=>{}/alert(1)/+alert(2)//
```

Script :
  ScriptBody opt

ScriptBody :
  StatementList

StatementList [Yield, Return] :
  StatementListItem [?Yield, ?Return]
  StatementList [?Yield, ?Return] StatementListItem [?Yield, ?Return]

StatementListItem [Yield, Return] :
  Statement [?Yield, ?Return]
  Declaration [?Yield]

Statement [Yield, Return] :
  BlockStatement [?Yield, ?Return]
  VariableStatement [?Yield]
  EmptyStatement
  ExpressionStatement [?Yield]
  ... (trunced)

ExpressionStatement [Yield] :
  [lookahead ∉ { { , function , class , let [ }] Expression [In, ?Yield] ;

Expression [In, Yield] :
  AssignmentExpression [?In, ?Yield]
  Expression [?In, ?Yield] , AssignmentExpression [?In, ?Yield]

AssignmentExpression [In, Yield] :
  ConditionalExpression [?In, ?Yield]
  [+Yield]
  YieldExpression [?In]
  ArrowFunction [?In, ?Yield]LeftHandSideExpression [?Yield] =
AssignmentExpression [?In, ?Yield]
  LeftHandSideExpression [?Yield] AssignmentOperator
AssignmentExpression [?In, ?Yield]

I hope we can agree that the leading `x=` is consumed by
"LeftHandSideExpression [?Yield] AssignmentOperator" in the very last
rule above. Proceeding with "AssignmentExpression" from the arrow arg.

Note that there is no other rule that applies up to this point.

ArrowFunction [In, Yield] :
  ArrowParameters [?Yield] [no LineTerminator here] => ConciseBody [?In]

ArrowParameters [Yield] :
  BindingIdentifier [?Yield]
  CoverParenthesizedExpressionAndArrowParameterList [?Yield]

Here "CoverParenthesizedExpressionAndArrowParameterList" will consume
the second `x` and then the only rule in "ArrowFunction" will consume
the arrow (`=>`). Continueing to parse the remainder
`{}/alert(1)/+alert(2)//` starting at "ConciseBody".

ConciseBody [In] :
  [lookahead ≠ {] AssignmentExpression [?In]
  { FunctionBody }

Obviously only the second rule applies so we parse the function body
and the curlies. We parse greedy but the function body is empty so
only the next two chars are consumed (`{}`). Parser has
`/alert(1)/+alert(2)//` left to parse and the "Statement" rule has
depleted it's options. So we go back to "StatementList" and parse
another statement. This should result in a regular expression, a plus
operator, a call expression, and a single line comment.

I don't think there's a rule here that allows parsing operators after
an explicit arrow function body as being part of the arrow function.
In fact, I remember that this was explicitly designed this way to
prevent this ambiguity. Beyond that I agree that it parses similar to
function expressions.

If this was wrong I'd love to know the right way to parse this.

- peter



On Wed, May 24, 2017 at 9:18 AM, Andreas Rossberg <[hidden email]> wrote:

> On 24 May 2017 at 08:57, Gareth Heyes <[hidden email]> wrote:
>>
>>
>>>
>>> you'll get a SyntaxError in all browsers but Edge, which interprets it as
>>> `(x => {}) * alert(1)`.
>>>
>>> Given how confusing that expression is, I think that the SyntaxError is
>>> the right choice.
>>
>>
>>  Well it is a function expression. So IMO Edge is right. It's equivalent
>> to:
>> x=function(){} * alert(1)
>
>
> Edge is wrong. Unlike an ordinary function expression, which is a
> PrimaryExpression, an arrow function is merely an AssigmentExpression, so
> has much lower precedence than any arithmetic operator. The rationale is
> that its body doesn't necessarily have braces, so `x => x * 1` would be
> ambiguous.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Andreas Rossberg-4
Note that the arrow function can only form an ExpressionStatement, which requires a terminating semicolon. There is none in this example, nor a line break that would allow one to be inserted implicitly. So when reaching the first `/` a syntax error is apparent, since there is no way the input can still form a well-formed statement at that point.

On 24 May 2017 at 10:32, Peter van der Zee <[hidden email]> wrote:
> Unlike an ordinary function expression, which is a PrimaryExpression, an arrow function is merely an AssigmentExpression, so has much lower precedence than any arithmetic operator.

I'm curious how this should be parsed so let's break this down.

Given the following "Script" (I don't think the actual goal matters much here):
```
x=x=>{}/alert(1)/+alert(2)//
```

Script :
  ScriptBody opt

ScriptBody :
  StatementList

StatementList [Yield, Return] :
  StatementListItem [?Yield, ?Return]
  StatementList [?Yield, ?Return] StatementListItem [?Yield, ?Return]

StatementListItem [Yield, Return] :
  Statement [?Yield, ?Return]
  Declaration [?Yield]

Statement [Yield, Return] :
  BlockStatement [?Yield, ?Return]
  VariableStatement [?Yield]
  EmptyStatement
  ExpressionStatement [?Yield]
  ... (trunced)

ExpressionStatement [Yield] :
  [lookahead ∉ { { , function , class , let [ }] Expression [In, ?Yield] ;

Expression [In, Yield] :
  AssignmentExpression [?In, ?Yield]
  Expression [?In, ?Yield] , AssignmentExpression [?In, ?Yield]

AssignmentExpression [In, Yield] :
  ConditionalExpression [?In, ?Yield]
  [+Yield]
  YieldExpression [?In]
  ArrowFunction [?In, ?Yield]LeftHandSideExpression [?Yield] =
AssignmentExpression [?In, ?Yield]
  LeftHandSideExpression [?Yield] AssignmentOperator
AssignmentExpression [?In, ?Yield]

I hope we can agree that the leading `x=` is consumed by
"LeftHandSideExpression [?Yield] AssignmentOperator" in the very last
rule above. Proceeding with "AssignmentExpression" from the arrow arg.

Note that there is no other rule that applies up to this point.

ArrowFunction [In, Yield] :
  ArrowParameters [?Yield] [no LineTerminator here] => ConciseBody [?In]

ArrowParameters [Yield] :
  BindingIdentifier [?Yield]
  CoverParenthesizedExpressionAndArrowParameterList [?Yield]

Here "CoverParenthesizedExpressionAndArrowParameterList" will consume
the second `x` and then the only rule in "ArrowFunction" will consume
the arrow (`=>`). Continueing to parse the remainder
`{}/alert(1)/+alert(2)//` starting at "ConciseBody".

ConciseBody [In] :
  [lookahead ≠ {] AssignmentExpression [?In]
  { FunctionBody }

Obviously only the second rule applies so we parse the function body
and the curlies. We parse greedy but the function body is empty so
only the next two chars are consumed (`{}`). Parser has
`/alert(1)/+alert(2)//` left to parse and the "Statement" rule has
depleted it's options. So we go back to "StatementList" and parse
another statement. This should result in a regular expression, a plus
operator, a call expression, and a single line comment.

I don't think there's a rule here that allows parsing operators after
an explicit arrow function body as being part of the arrow function.
In fact, I remember that this was explicitly designed this way to
prevent this ambiguity. Beyond that I agree that it parses similar to
function expressions.

If this was wrong I'd love to know the right way to parse this.

- peter



On Wed, May 24, 2017 at 9:18 AM, Andreas Rossberg <[hidden email]> wrote:
> On 24 May 2017 at 08:57, Gareth Heyes <[hidden email]> wrote:
>>
>>
>>>
>>> you'll get a SyntaxError in all browsers but Edge, which interprets it as
>>> `(x => {}) * alert(1)`.
>>>
>>> Given how confusing that expression is, I think that the SyntaxError is
>>> the right choice.
>>
>>
>>  Well it is a function expression. So IMO Edge is right. It's equivalent
>> to:
>> x=function(){} * alert(1)
>
>
> Edge is wrong. Unlike an ordinary function expression, which is a
> PrimaryExpression, an arrow function is merely an AssigmentExpression, so
> has much lower precedence than any arithmetic operator. The rationale is
> that its body doesn't necessarily have braces, so `x => x * 1` would be
> ambiguous.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Peter van der Zee
Oh, so subtle. You're right, the missing semi makes it a syntax error.
Thanks for clearing that up :)

- peter

On Wed, May 24, 2017 at 11:10 AM, Andreas Rossberg <[hidden email]> wrote:

> Note that the arrow function can only form an ExpressionStatement, which
> requires a terminating semicolon. There is none in this example, nor a line
> break that would allow one to be inserted implicitly. So when reaching the
> first `/` a syntax error is apparent, since there is no way the input can
> still form a well-formed statement at that point.
>
> On 24 May 2017 at 10:32, Peter van der Zee <[hidden email]> wrote:
>>
>> > Unlike an ordinary function expression, which is a PrimaryExpression, an
>> > arrow function is merely an AssigmentExpression, so has much lower
>> > precedence than any arithmetic operator.
>>
>> I'm curious how this should be parsed so let's break this down.
>>
>> Given the following "Script" (I don't think the actual goal matters much
>> here):
>> ```
>> x=x=>{}/alert(1)/+alert(2)//
>> ```
>>
>> Script :
>>   ScriptBody opt
>>
>> ScriptBody :
>>   StatementList
>>
>> StatementList [Yield, Return] :
>>   StatementListItem [?Yield, ?Return]
>>   StatementList [?Yield, ?Return] StatementListItem [?Yield, ?Return]
>>
>> StatementListItem [Yield, Return] :
>>   Statement [?Yield, ?Return]
>>   Declaration [?Yield]
>>
>> Statement [Yield, Return] :
>>   BlockStatement [?Yield, ?Return]
>>   VariableStatement [?Yield]
>>   EmptyStatement
>>   ExpressionStatement [?Yield]
>>   ... (trunced)
>>
>> ExpressionStatement [Yield] :
>>   [lookahead ∉ { { , function , class , let [ }] Expression [In, ?Yield] ;
>>
>> Expression [In, Yield] :
>>   AssignmentExpression [?In, ?Yield]
>>   Expression [?In, ?Yield] , AssignmentExpression [?In, ?Yield]
>>
>> AssignmentExpression [In, Yield] :
>>   ConditionalExpression [?In, ?Yield]
>>   [+Yield]
>>   YieldExpression [?In]
>>   ArrowFunction [?In, ?Yield]LeftHandSideExpression [?Yield] =
>> AssignmentExpression [?In, ?Yield]
>>   LeftHandSideExpression [?Yield] AssignmentOperator
>> AssignmentExpression [?In, ?Yield]
>>
>> I hope we can agree that the leading `x=` is consumed by
>> "LeftHandSideExpression [?Yield] AssignmentOperator" in the very last
>> rule above. Proceeding with "AssignmentExpression" from the arrow arg.
>>
>> Note that there is no other rule that applies up to this point.
>>
>> ArrowFunction [In, Yield] :
>>   ArrowParameters [?Yield] [no LineTerminator here] => ConciseBody [?In]
>>
>> ArrowParameters [Yield] :
>>   BindingIdentifier [?Yield]
>>   CoverParenthesizedExpressionAndArrowParameterList [?Yield]
>>
>> Here "CoverParenthesizedExpressionAndArrowParameterList" will consume
>> the second `x` and then the only rule in "ArrowFunction" will consume
>> the arrow (`=>`). Continueing to parse the remainder
>> `{}/alert(1)/+alert(2)//` starting at "ConciseBody".
>>
>> ConciseBody [In] :
>>   [lookahead ≠ {] AssignmentExpression [?In]
>>   { FunctionBody }
>>
>> Obviously only the second rule applies so we parse the function body
>> and the curlies. We parse greedy but the function body is empty so
>> only the next two chars are consumed (`{}`). Parser has
>> `/alert(1)/+alert(2)//` left to parse and the "Statement" rule has
>> depleted it's options. So we go back to "StatementList" and parse
>> another statement. This should result in a regular expression, a plus
>> operator, a call expression, and a single line comment.
>>
>> I don't think there's a rule here that allows parsing operators after
>> an explicit arrow function body as being part of the arrow function.
>> In fact, I remember that this was explicitly designed this way to
>> prevent this ambiguity. Beyond that I agree that it parses similar to
>> function expressions.
>>
>> If this was wrong I'd love to know the right way to parse this.
>>
>> - peter
>>
>>
>>
>> On Wed, May 24, 2017 at 9:18 AM, Andreas Rossberg <[hidden email]>
>> wrote:
>> > On 24 May 2017 at 08:57, Gareth Heyes <[hidden email]>
>> > wrote:
>> >>
>> >>
>> >>>
>> >>> you'll get a SyntaxError in all browsers but Edge, which interprets it
>> >>> as
>> >>> `(x => {}) * alert(1)`.
>> >>>
>> >>> Given how confusing that expression is, I think that the SyntaxError
>> >>> is
>> >>> the right choice.
>> >>
>> >>
>> >>  Well it is a function expression. So IMO Edge is right. It's
>> >> equivalent
>> >> to:
>> >> x=function(){} * alert(1)
>> >
>> >
>> > Edge is wrong. Unlike an ordinary function expression, which is a
>> > PrimaryExpression, an arrow function is merely an AssigmentExpression,
>> > so
>> > has much lower precedence than any arithmetic operator. The rationale is
>> > that its body doesn't necessarily have braces, so `x => x * 1` would be
>> > ambiguous.
>> >
>> > _______________________________________________
>> > es-discuss mailing list
>> > [hidden email]
>> > https://mail.mozilla.org/listinfo/es-discuss
>> >
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Michał Wadas
I have filled an issue for Babylon.

On Wed, May 24, 2017 at 11:14 AM, Peter van der Zee <[hidden email]> wrote:
Oh, so subtle. You're right, the missing semi makes it a syntax error.
Thanks for clearing that up :)

- peter

On Wed, May 24, 2017 at 11:10 AM, Andreas Rossberg <[hidden email]> wrote:
> Note that the arrow function can only form an ExpressionStatement, which
> requires a terminating semicolon. There is none in this example, nor a line
> break that would allow one to be inserted implicitly. So when reaching the
> first `/` a syntax error is apparent, since there is no way the input can
> still form a well-formed statement at that point.
>
> On 24 May 2017 at 10:32, Peter van der Zee <[hidden email]> wrote:
>>
>> > Unlike an ordinary function expression, which is a PrimaryExpression, an
>> > arrow function is merely an AssigmentExpression, so has much lower
>> > precedence than any arithmetic operator.
>>
>> I'm curious how this should be parsed so let's break this down.
>>
>> Given the following "Script" (I don't think the actual goal matters much
>> here):
>> ```
>> x=x=>{}/alert(1)/+alert(2)//
>> ```
>>
>> Script :
>>   ScriptBody opt
>>
>> ScriptBody :
>>   StatementList
>>
>> StatementList [Yield, Return] :
>>   StatementListItem [?Yield, ?Return]
>>   StatementList [?Yield, ?Return] StatementListItem [?Yield, ?Return]
>>
>> StatementListItem [Yield, Return] :
>>   Statement [?Yield, ?Return]
>>   Declaration [?Yield]
>>
>> Statement [Yield, Return] :
>>   BlockStatement [?Yield, ?Return]
>>   VariableStatement [?Yield]
>>   EmptyStatement
>>   ExpressionStatement [?Yield]
>>   ... (trunced)
>>
>> ExpressionStatement [Yield] :
>>   [lookahead ∉ { { , function , class , let [ }] Expression [In, ?Yield] ;
>>
>> Expression [In, Yield] :
>>   AssignmentExpression [?In, ?Yield]
>>   Expression [?In, ?Yield] , AssignmentExpression [?In, ?Yield]
>>
>> AssignmentExpression [In, Yield] :
>>   ConditionalExpression [?In, ?Yield]
>>   [+Yield]
>>   YieldExpression [?In]
>>   ArrowFunction [?In, ?Yield]LeftHandSideExpression [?Yield] =
>> AssignmentExpression [?In, ?Yield]
>>   LeftHandSideExpression [?Yield] AssignmentOperator
>> AssignmentExpression [?In, ?Yield]
>>
>> I hope we can agree that the leading `x=` is consumed by
>> "LeftHandSideExpression [?Yield] AssignmentOperator" in the very last
>> rule above. Proceeding with "AssignmentExpression" from the arrow arg.
>>
>> Note that there is no other rule that applies up to this point.
>>
>> ArrowFunction [In, Yield] :
>>   ArrowParameters [?Yield] [no LineTerminator here] => ConciseBody [?In]
>>
>> ArrowParameters [Yield] :
>>   BindingIdentifier [?Yield]
>>   CoverParenthesizedExpressionAndArrowParameterList [?Yield]
>>
>> Here "CoverParenthesizedExpressionAndArrowParameterList" will consume
>> the second `x` and then the only rule in "ArrowFunction" will consume
>> the arrow (`=>`). Continueing to parse the remainder
>> `{}/alert(1)/+alert(2)//` starting at "ConciseBody".
>>
>> ConciseBody [In] :
>>   [lookahead ≠ {] AssignmentExpression [?In]
>>   { FunctionBody }
>>
>> Obviously only the second rule applies so we parse the function body
>> and the curlies. We parse greedy but the function body is empty so
>> only the next two chars are consumed (`{}`). Parser has
>> `/alert(1)/+alert(2)//` left to parse and the "Statement" rule has
>> depleted it's options. So we go back to "StatementList" and parse
>> another statement. This should result in a regular expression, a plus
>> operator, a call expression, and a single line comment.
>>
>> I don't think there's a rule here that allows parsing operators after
>> an explicit arrow function body as being part of the arrow function.
>> In fact, I remember that this was explicitly designed this way to
>> prevent this ambiguity. Beyond that I agree that it parses similar to
>> function expressions.
>>
>> If this was wrong I'd love to know the right way to parse this.
>>
>> - peter
>>
>>
>>
>> On Wed, May 24, 2017 at 9:18 AM, Andreas Rossberg <[hidden email]>
>> wrote:
>> > On 24 May 2017 at 08:57, Gareth Heyes <[hidden email]>
>> > wrote:
>> >>
>> >>
>> >>>
>> >>> you'll get a SyntaxError in all browsers but Edge, which interprets it
>> >>> as
>> >>> `(x => {}) * alert(1)`.
>> >>>
>> >>> Given how confusing that expression is, I think that the SyntaxError
>> >>> is
>> >>> the right choice.
>> >>
>> >>
>> >>  Well it is a function expression. So IMO Edge is right. It's
>> >> equivalent
>> >> to:
>> >> x=function(){} * alert(1)
>> >
>> >
>> > Edge is wrong. Unlike an ordinary function expression, which is a
>> > PrimaryExpression, an arrow function is merely an AssigmentExpression,
>> > so
>> > has much lower precedence than any arithmetic operator. The rationale is
>> > that its body doesn't necessarily have braces, so `x => x * 1` would be
>> > ambiguous.
>> >
>> > _______________________________________________
>> > es-discuss mailing list
>> > [hidden email]
>> > https://mail.mozilla.org/listinfo/es-discuss
>> >
>
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Arrow function followed by divide or syntax error?

Waldemar Horwat
x=x=>{}/alert(1)/+alert(2)// is a syntax error. We deliberately specified it that way in the standard for the precedence reasons stated earlier in the thread.

Brian Terlson is filing a bug as we speak.

    Waldemar


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss