Arrow function followed by divide or syntax error?

# Gareth Heyes (8 years ago)

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

# Claude Pache (8 years ago)

Le 23 mai 2017 à 16:34, Gareth Heyes <gareth.heyes at portswigger.net> 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:

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.

# Gareth Heyes (8 years ago)

On 23 May 2017 at 17:01, Claude Pache <claude.pache at gmail.com> wrote:

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

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)

# Andreas Rossberg (8 years ago)

On 24 May 2017 at 08:57, Gareth Heyes <gareth.heyes at portswigger.net> 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.

# Peter van der Zee (8 years ago)

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.

# Andreas Rossberg (8 years ago)

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.

# Peter van der Zee (8 years ago)

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

# Michał Wadas (8 years ago)

I have filled an issue for Babylon babel/babylon#536.

# Waldemar Horwat (8 years ago)

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