Bug 189914 - Throws incorrectly a syntax error when declaring a top level catch variable the same as a parameter
Summary: Throws incorrectly a syntax error when declaring a top level catch variable t...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Keith Miller
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-09-24 06:46 PDT by seba kerckhof
Modified: 2020-03-11 13:50 PDT (History)
15 users (show)

See Also:


Attachments
Test case (109 bytes, text/html)
2020-03-11 09:17 PDT, Simon Fraser (smfr)
no flags Details
Patch (8.60 KB, patch)
2020-03-11 11:03 PDT, Keith Miller
no flags Details | Formatted Diff | Diff
Patch for landing (10.09 KB, patch)
2020-03-11 12:39 PDT, Keith Miller
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description seba kerckhof 2018-09-24 06:46:27 PDT
I wouldn't write code like this (below) myself, but it was emitted by the minifier and so my app doesn't work in Safari, or Safari TP (build 65 / 10 september 2018).
The code looks legal to me ...

class Foo{
  foo(o){
    try{

    }catch({ o }){

    }
  }
}
results in "SyntaxError: unexpected token: '}'. Cannot declare a lexical variable twice: 'o'."

And the variation:
class Foo{
  foo(o){
    try{

    }catch({ prop: o }){

    }
  }
}

results in "SyntaxError: unexpected identifier 'o'. Cannot declare a lexical variable twice: 'o'."
Comment 1 seba kerckhof 2018-09-25 03:29:24 PDT
Other variations with same problem:

Normal function:
function foo(c){try{}catch({c}){}}

Arrow function:
const foo=c=>{try{}catch({c}){}};

Object shorthand literal:
const foo = {
  bar(c){try{}catch({c}){}}
}


Note that it only seems related to destructuring catch clause arguments, e.g. this works:
function foo(c){try{}catch(c){}}
Comment 2 Radar WebKit Bug Importer 2020-03-10 23:01:25 PDT
<rdar://problem/60309235>
Comment 3 Simon Fraser (smfr) 2020-03-11 09:17:40 PDT
Created attachment 393248 [details]
Test case
Comment 4 Keith Miller 2020-03-11 10:10:52 PDT
Ah, thanks for the report. I think this is happening because we were not incrementing the statement depth (we use the numeric depth as an optimization for determining if we should do the hash table lookup for parameter shadowing) when parsing catch parameters. Should be an easy fix.
Comment 5 Keith Miller 2020-03-11 10:12:07 PDT
For what it's worth, sorry about the the delay on this. I think this got lost in our bug tracking system... :(
Comment 6 Ross Kirsling 2020-03-11 10:27:17 PDT
Test262 evidently does not have a spec conformance test for this behavior.

Note that the shorthand destructuring syntax also makes the problem a bit less clear (since Error objects are only guaranteed to have a `message` field).

It's specifically this that fails:
> function foo(m) { try {} catch ({ message: m }) {} }
Comment 7 Keith Miller 2020-03-11 10:30:39 PDT
(In reply to Ross Kirsling from comment #6)
> Test262 evidently does not have a spec conformance test for this behavior.

There's nothing inside a function but test/language/statements/try/scope-catch-param-lex-open.js has array destructing at the top level with a lexical variable of the same name.

> 
> Note that the shorthand destructuring syntax also makes the problem a bit
> less clear (since Error objects are only guaranteed to have a `message`
> field).

Well you don't have the throw an Error object you can throw anything you want! :P

> 
> It's specifically this that fails:
> > function foo(m) { try {} catch ({ message: m }) {} }
Comment 8 Ross Kirsling 2020-03-11 10:49:58 PDT
(In reply to Keith Miller from comment #7)
> There's nothing inside a function but
> test/language/statements/try/scope-catch-param-lex-open.js has array
> destructing at the top level with a lexical variable of the same name.

That's a good find! I'm surprised that `var x; try {} catch ([x]) {}` fails, because it doesn't fail with let/const.

> Well you don't have the throw an Error object you can throw anything you
> want! :P

Oh geez, apparently I've not had enough coffee this morning. 😅
Comment 9 Keith Miller 2020-03-11 11:03:18 PDT
Created attachment 393267 [details]
Patch
Comment 10 Saam Barati 2020-03-11 11:12:08 PDT
Comment on attachment 393267 [details]
Patch

r=me
Comment 11 Ross Kirsling 2020-03-11 11:13:02 PDT
Comment on attachment 393267 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=393267&action=review

r=me if EWS is green and Test262 is locally happy

> JSTests/ChangeLog:8
> +        * stress/catch-destructing-shadow-lexical-const-variable-global.js: Added.

nit: destructing -> destructuring

> JSTests/stress/catch-destructing-shadow-lexical-variable-global.js:2
> +let o = value;

Maybe combine this file with the const one and add a var case too?
Comment 12 Keith Miller 2020-03-11 11:15:22 PDT
Comment on attachment 393267 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=393267&action=review

>> JSTests/stress/catch-destructing-shadow-lexical-variable-global.js:2
>> +let o = value;
> 
> Maybe combine this file with the const one and add a var case too?

I didn't combine them because it would be an error to declare a const and let with the same name. I guess I could choose a new variable name but that's too clever for me. :P
Comment 13 Ross Kirsling 2020-03-11 11:17:19 PDT
(In reply to Keith Miller from comment #12)
> I didn't combine them because it would be an error to declare a const and
> let with the same name. I guess I could choose a new variable name but
> that's too clever for me. :P

I mean, you could use blocks. :P But either way.
Comment 14 Keith Miller 2020-03-11 11:28:55 PDT
(In reply to Ross Kirsling from comment #13)
> (In reply to Keith Miller from comment #12)
> > I didn't combine them because it would be an error to declare a const and
> > let with the same name. I guess I could choose a new variable name but
> > that's too clever for me. :P
> 
> I mean, you could use blocks. :P But either way.

That wouldn't be m_statementDepth == 1 though. So it wouldn't really be testing the issue.
Comment 15 Keith Miller 2020-03-11 12:39:45 PDT
Created attachment 393276 [details]
Patch for landing
Comment 16 WebKit Commit Bot 2020-03-11 13:26:12 PDT
Comment on attachment 393276 [details]
Patch for landing

Clearing flags on attachment: 393276

Committed r258279: <https://trac.webkit.org/changeset/258279>
Comment 17 WebKit Commit Bot 2020-03-11 13:26:14 PDT
All reviewed patches have been landed.  Closing bug.