Changeset 217200 in webkit


Ignore:
Timestamp:
May 21, 2017 10:47:33 PM (7 years ago)
Author:
sbarati@apple.com
Message:

We incorrectly throw a syntax error when declaring a top level for-loop iteration variable the same as a parameter
https://bugs.webkit.org/show_bug.cgi?id=171041
<rdar://problem/32082516>

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/lexical-scoping-for-loop.js: Added.

(assert):
(test1):
(test2):
(test3):
(test4):
(test5):
(test6):
(let.test7):
(let.test8):
(let.test9):
(let.test10):
(let.test11):
(let.test12):

Source/JavaScriptCore:

We were treating a for-loop variable declaration potentially as a top
level statement, e.g, in a program like this:
`
function foo() {

for (let variable of expr) { }

}
`
But we should not be. This had the consequence of making this type of program
throw a syntax error:
`
function foo(arg) {

for (let arg of expr) { }

}
`
even though it should not. The fix is simple, we just need to increment the
statement depth before parsing anything inside the for loop.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseForStatement):

LayoutTests:

  • js/parser-syntax-check-expected.txt:
  • js/script-tests/parser-syntax-check.js:
Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r217199 r217200  
     12017-05-21  Saam Barati  <sbarati@apple.com>
     2
     3        We incorrectly throw a syntax error when declaring a top level for-loop iteration variable the same as a parameter
     4        https://bugs.webkit.org/show_bug.cgi?id=171041
     5        <rdar://problem/32082516>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * stress/lexical-scoping-for-loop.js: Added.
     10        (assert):
     11        (test1):
     12        (test2):
     13        (test3):
     14        (test4):
     15        (test5):
     16        (test6):
     17        (let.test7):
     18        (let.test8):
     19        (let.test9):
     20        (let.test10):
     21        (let.test11):
     22        (let.test12):
     23
    1242017-05-19  Yusuke Suzuki  <utatane.tea@gmail.com>
    225
  • trunk/LayoutTests/ChangeLog

    r217197 r217200  
     12017-05-21  Saam Barati  <sbarati@apple.com>
     2
     3        We incorrectly throw a syntax error when declaring a top level for-loop iteration variable the same as a parameter
     4        https://bugs.webkit.org/show_bug.cgi?id=171041
     5        <rdar://problem/32082516>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * js/parser-syntax-check-expected.txt:
     10        * js/script-tests/parser-syntax-check.js:
     11
    1122017-05-21  Antti Koivisto  <antti@apple.com>
    213
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r216934 r217200  
    557557PASS Invalid: "for (let {i} = 20 in b) { }". Produced the following syntax error: "SyntaxError: Cannot assign to the loop variable inside a for-in loop header."
    558558PASS Invalid: "function f() { for (let {i} = 20 in b) { } }". Produced the following syntax error: "SyntaxError: Cannot assign to the loop variable inside a for-in loop header."
     559PASS Valid:   "function x(i) { for (let i in {}) { } }"
     560PASS Valid:   "function f() { function x(i) { for (let i in {}) { } } }"
     561PASS Valid:   "function x(i) { for (let i of []) { } }"
     562PASS Valid:   "function f() { function x(i) { for (let i of []) { } } }"
     563PASS Valid:   "function x(i) { for (let i of []) { } }"
     564PASS Valid:   "function f() { function x(i) { for (let i of []) { } } }"
     565PASS Valid:   "function x(i) { for (let i; false; ) { } }"
     566PASS Valid:   "function f() { function x(i) { for (let i; false; ) { } } }"
     567PASS Valid:   "let f = (i) => { for (let i in {}) { } }"
     568PASS Valid:   "function f() { let f = (i) => { for (let i in {}) { } } }"
     569PASS Valid:   "let f = (i) => { for (let i of []) { } }"
     570PASS Valid:   "function f() { let f = (i) => { for (let i of []) { } } }"
     571PASS Valid:   "let f = (i) => { for (let i of []) { } }"
     572PASS Valid:   "function f() { let f = (i) => { for (let i of []) { } } }"
     573PASS Valid:   "let f = (i) => { for (let i; false; ) { } }"
     574PASS Valid:   "function f() { let f = (i) => { for (let i; false; ) { } } }"
     575PASS Valid:   "function* x(i) { for (let i in {}) { } }"
     576PASS Valid:   "function f() { function* x(i) { for (let i in {}) { } } }"
     577PASS Valid:   "function* x(i) { for (let i of []) { } }"
     578PASS Valid:   "function f() { function* x(i) { for (let i of []) { } } }"
     579PASS Valid:   "function* x(i) { for (let i of []) { } }"
     580PASS Valid:   "function f() { function* x(i) { for (let i of []) { } } }"
     581PASS Valid:   "function* x(i) { for (let i; false; ) { } }"
     582PASS Valid:   "function f() { function* x(i) { for (let i; false; ) { } } }"
     583PASS Valid:   "function x(i) { for (const i in {}) { } }"
     584PASS Valid:   "function f() { function x(i) { for (const i in {}) { } } }"
     585PASS Valid:   "function x(i) { for (const i of []) { } }"
     586PASS Valid:   "function f() { function x(i) { for (const i of []) { } } }"
     587PASS Valid:   "function x(i) { for (const i of []) { } }"
     588PASS Valid:   "function f() { function x(i) { for (const i of []) { } } }"
     589PASS Valid:   "function x(i) { for (const i = 20; false; ) { } }"
     590PASS Valid:   "function f() { function x(i) { for (const i = 20; false; ) { } } }"
     591PASS Valid:   "let f = (i) => { for (const i in {}) { } }"
     592PASS Valid:   "function f() { let f = (i) => { for (const i in {}) { } } }"
     593PASS Valid:   "let f = (i) => { for (const i of []) { } }"
     594PASS Valid:   "function f() { let f = (i) => { for (const i of []) { } } }"
     595PASS Valid:   "let f = (i) => { for (const i of []) { } }"
     596PASS Valid:   "function f() { let f = (i) => { for (const i of []) { } } }"
     597PASS Valid:   "let f = (i) => { for (const i = 20; false; ) { } }"
     598PASS Valid:   "function f() { let f = (i) => { for (const i = 20; false; ) { } } }"
     599PASS Valid:   "function* x(i) { for (const i in {}) { } }"
     600PASS Valid:   "function f() { function* x(i) { for (const i in {}) { } } }"
     601PASS Valid:   "function* x(i) { for (const i of []) { } }"
     602PASS Valid:   "function f() { function* x(i) { for (const i of []) { } } }"
     603PASS Valid:   "function* x(i) { for (const i of []) { } }"
     604PASS Valid:   "function f() { function* x(i) { for (const i of []) { } } }"
     605PASS Valid:   "function* x(i) { for (const i = 20; false; ) { } }"
     606PASS Valid:   "function f() { function* x(i) { for (const i = 20; false; ) { } } }"
    559607try statement
    560608PASS Invalid: "try { break } catch(e) {}". Produced the following syntax error: "SyntaxError: 'break' is only valid inside a switch or loop statement."
  • trunk/LayoutTests/js/script-tests/parser-syntax-check.js

    r216934 r217200  
    372372invalid("for (const {i} = 20 in b) { }");
    373373invalid("for (let {i} = 20 in b) { }");
     374valid("function x(i) { for (let i in {}) { } }");
     375valid("function x(i) { for (let i of []) { } }");
     376valid("function x(i) { for (let i of []) { } }");
     377valid("function x(i) { for (let i; false; ) { } }");
     378valid("let f = (i) => { for (let i in {}) { } }");
     379valid("let f = (i) => { for (let i of []) { } }");
     380valid("let f = (i) => { for (let i of []) { } }");
     381valid("let f = (i) => { for (let i; false; ) { } }");
     382valid("function* x(i) { for (let i in {}) { } }");
     383valid("function* x(i) { for (let i of []) { } }");
     384valid("function* x(i) { for (let i of []) { } }");
     385valid("function* x(i) { for (let i; false; ) { } }");
     386valid("function x(i) { for (const i in {}) { } }");
     387valid("function x(i) { for (const i of []) { } }");
     388valid("function x(i) { for (const i of []) { } }");
     389valid("function x(i) { for (const i = 20; false; ) { } }");
     390valid("let f = (i) => { for (const i in {}) { } }");
     391valid("let f = (i) => { for (const i of []) { } }");
     392valid("let f = (i) => { for (const i of []) { } }");
     393valid("let f = (i) => { for (const i = 20; false; ) { } }");
     394valid("function* x(i) { for (const i in {}) { } }");
     395valid("function* x(i) { for (const i of []) { } }");
     396valid("function* x(i) { for (const i of []) { } }");
     397valid("function* x(i) { for (const i = 20; false; ) { } }");
    374398
    375399debug  ("try statement");
  • trunk/Source/JavaScriptCore/ChangeLog

    r217199 r217200  
     12017-05-21  Saam Barati  <sbarati@apple.com>
     2
     3        We incorrectly throw a syntax error when declaring a top level for-loop iteration variable the same as a parameter
     4        https://bugs.webkit.org/show_bug.cgi?id=171041
     5        <rdar://problem/32082516>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        We were treating a for-loop variable declaration potentially as a top
     10        level statement, e.g, in a program like this:
     11        ```
     12        function foo() {
     13            for (let variable of expr) { }
     14        }
     15        ```
     16        But we should not be. This had the consequence of making this type of program
     17        throw a syntax error:
     18        ```
     19        function foo(arg) {
     20            for (let arg of expr) { }
     21        }
     22        ```
     23        even though it should not. The fix is simple, we just need to increment the
     24        statement depth before parsing anything inside the for loop.
     25
     26        * parser/Parser.cpp:
     27        (JSC::Parser<LexerType>::parseForStatement):
     28
    1292017-05-19  Yusuke Suzuki  <utatane.tea@gmail.com>
    230
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r216891 r217200  
    11341134    int startLine = tokenLine();
    11351135    next();
     1136
     1137    DepthManager statementDepth(&m_statementDepth);
     1138    m_statementDepth++;
     1139
    11361140    handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
    11371141    int nonLHSCount = m_parserState.nonLHSCount;
Note: See TracChangeset for help on using the changeset viewer.