Changeset 207798 in webkit


Ignore:
Timestamp:
Oct 24, 2016 7:35:59 PM (7 years ago)
Author:
Yusuke Suzuki
Message:

Arrow functions with concise bodies cannot return regular expressions
https://bugs.webkit.org/show_bug.cgi?id=163162

Reviewed by Filip Pizlo.

JSTests:

  • ChakraCore/test/Operators/instanceof.baseline-jsc:
  • ChakraCore/test/Regex/nul_character.baseline-jsc:
  • ChakraCore/test/es5/Lex_u3.baseline-jsc:
  • stress/parse-regexp-as-token.js: Added.

(shouldBe):

Source/JavaScriptCore:

When we encounter the RegExp in the parser, we first scan it as / or /=.
And if / or /= is parsed under the primary expression context, we rescan it
as RegExp. However, we did not update the token record information. So the
token record still says "I'm / or /=".

When we parse the string "() => /hello/", the last token becomes "/", which is
the first character of the RegExp, instead of "/hello/". Since the arrow
function parsing utilizes the end offset of the last token, we accidentally
recognize the range of the above arrow function as "() => /".

In this patch, we update the token when rescanning under the RegExp context.
This logic is similar to parsing Tail Template Literal token.

We also refine the error message for regular expression literals. And since
the REGEXP token is now introduced, the other error messages using that token
are improved too.

Currently, unterminated error messages can be seen in Parser.cpp. However,
these messages cannot be shown to users if the lexer has m_error. So these
code is meaningless. I'll move these tokenizing errors to the lexer in the
subsequent patch[1].

[1]: https://bugs.webkit.org/show_bug.cgi?id=163928

  • parser/Lexer.cpp:

(JSC::Lexer<T>::fillTokenInfo):
(JSC::Lexer<T>::lex):
(JSC::Lexer<T>::scanRegExp):
(JSC::Lexer<T>::scanTrailingTemplateString):
(JSC::Lexer<T>::skipRegExp): Deleted.

  • parser/Lexer.h:

(JSC::Lexer::getToken):

  • parser/Parser.cpp:

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

  • parser/Parser.h:

(JSC::Parser::getToken):

  • parser/ParserTokens.h:

LayoutTests:

  • fast/regex/dom/non-pattern-characters-expected.txt:
  • js/arrowfunction-syntax-errors-expected.txt:
  • js/regexp-compile-crash-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T4-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.2_T2-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T3-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T3-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.2_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T3-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T1-expected.txt:
  • sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T3-expected.txt:
Location:
trunk
Files:
1 added
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChakraCore/test/Operators/instanceof.baseline-jsc

    r205387 r207798  
    229229 Exception: new Object() instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Object() instanceof new Boolean(false)')
    230230 Exception: new Object() instanceof new Date(). new Date() is not a function. (evaluating 'new Object() instanceof new Date()')
    231  Exception: new Object() instanceof /a+/. / is not a function. (evaluating 'new Object() instanceof /')
     231 Exception: new Object() instanceof /a+/. /a+/ is not a function. (evaluating 'new Object() instanceof /a+/')
    232232 Exception: f instanceof new Object(). new Object() is not a function. (evaluating 'f instanceof new Object()')
    233233 Exception: f instanceof f. f is not a function. (evaluating 'f instanceof f')
     
    250250 Exception: f instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'f instanceof new Boolean(false)')
    251251 Exception: f instanceof new Date(). new Date() is not a function. (evaluating 'f instanceof new Date()')
    252  Exception: f instanceof /a+/. / is not a function. (evaluating 'f instanceof /')
     252 Exception: f instanceof /a+/. /a+/ is not a function. (evaluating 'f instanceof /a+/')
    253253 Exception: b instanceof new Object(). new Object() is not a function. (evaluating 'b instanceof new Object()')
    254254 Exception: b instanceof f. f is not a function. (evaluating 'b instanceof f')
     
    271271 Exception: b instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'b instanceof new Boolean(false)')
    272272 Exception: b instanceof new Date(). new Date() is not a function. (evaluating 'b instanceof new Date()')
    273  Exception: b instanceof /a+/. / is not a function. (evaluating 'b instanceof /')
     273 Exception: b instanceof /a+/. /a+/ is not a function. (evaluating 'b instanceof /a+/')
    274274 Exception: foo instanceof new Object(). new Object() is not a function. (evaluating 'foo instanceof new Object()')
    275275 Exception: foo instanceof f. f is not a function. (evaluating 'foo instanceof f')
     
    292292 Exception: foo instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'foo instanceof new Boolean(false)')
    293293 Exception: foo instanceof new Date(). new Date() is not a function. (evaluating 'foo instanceof new Date()')
    294  Exception: foo instanceof /a+/. / is not a function. (evaluating 'foo instanceof /')
     294 Exception: foo instanceof /a+/. /a+/ is not a function. (evaluating 'foo instanceof /a+/')
    295295 Exception: String.fromCharCode instanceof new Object(). new Object() is not a function. (evaluating 'String.fromCharCode instanceof new Object()')
    296296 Exception: String.fromCharCode instanceof f. f is not a function. (evaluating 'String.fromCharCode instanceof f')
     
    313313 Exception: String.fromCharCode instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'String.fromCharCode instanceof new Boolean(false)')
    314314 Exception: String.fromCharCode instanceof new Date(). new Date() is not a function. (evaluating 'String.fromCharCode instanceof new Date()')
    315  Exception: String.fromCharCode instanceof /a+/. / is not a function. (evaluating 'String.fromCharCode instanceof /')
     315 Exception: String.fromCharCode instanceof /a+/. /a+/ is not a function. (evaluating 'String.fromCharCode instanceof /a+/')
    316316 Exception: Array.prototype.concat instanceof new Object(). new Object() is not a function. (evaluating 'Array.prototype.concat instanceof new Object()')
    317317 Exception: Array.prototype.concat instanceof f. f is not a function. (evaluating 'Array.prototype.concat instanceof f')
     
    334334 Exception: Array.prototype.concat instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'Array.prototype.concat instanceof new Boolean(false)')
    335335 Exception: Array.prototype.concat instanceof new Date(). new Date() is not a function. (evaluating 'Array.prototype.concat instanceof new Date()')
    336  Exception: Array.prototype.concat instanceof /a+/. / is not a function. (evaluating 'Array.prototype.concat instanceof /')
     336 Exception: Array.prototype.concat instanceof /a+/. /a+/ is not a function. (evaluating 'Array.prototype.concat instanceof /a+/')
    337337 Exception: [1,2,3] instanceof new Object(). new Object() is not a function. (evaluating '[1,2,3] instanceof new Object()')
    338338 Exception: [1,2,3] instanceof f. f is not a function. (evaluating '[1,2,3] instanceof f')
     
    355355 Exception: [1,2,3] instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating '[1,2,3] instanceof new Boolean(false)')
    356356 Exception: [1,2,3] instanceof new Date(). new Date() is not a function. (evaluating '[1,2,3] instanceof new Date()')
    357  Exception: [1,2,3] instanceof /a+/. / is not a function. (evaluating '[1,2,3] instanceof /')
     357 Exception: [1,2,3] instanceof /a+/. /a+/ is not a function. (evaluating '[1,2,3] instanceof /a+/')
    358358 Exception: new Array() instanceof new Object(). new Object() is not a function. (evaluating 'new Array() instanceof new Object()')
    359359 Exception: new Array() instanceof f. f is not a function. (evaluating 'new Array() instanceof f')
     
    376376 Exception: new Array() instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Array() instanceof new Boolean(false)')
    377377 Exception: new Array() instanceof new Date(). new Date() is not a function. (evaluating 'new Array() instanceof new Date()')
    378  Exception: new Array() instanceof /a+/. / is not a function. (evaluating 'new Array() instanceof /')
     378 Exception: new Array() instanceof /a+/. /a+/ is not a function. (evaluating 'new Array() instanceof /a+/')
    379379 Exception: fncs instanceof new Object(). new Object() is not a function. (evaluating 'fncs instanceof new Object()')
    380380 Exception: fncs instanceof f. f is not a function. (evaluating 'fncs instanceof f')
     
    397397 Exception: fncs instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'fncs instanceof new Boolean(false)')
    398398 Exception: fncs instanceof new Date(). new Date() is not a function. (evaluating 'fncs instanceof new Date()')
    399  Exception: fncs instanceof /a+/. / is not a function. (evaluating 'fncs instanceof /')
     399 Exception: fncs instanceof /a+/. /a+/ is not a function. (evaluating 'fncs instanceof /a+/')
    400400 Exception: 'hello' instanceof new Object(). new Object() is not a function. (evaluating ''hello' instanceof new Object()')
    401401 Exception: 'hello' instanceof f. f is not a function. (evaluating ''hello' instanceof f')
     
    418418 Exception: 'hello' instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating ''hello' instanceof new Boolean(false)')
    419419 Exception: 'hello' instanceof new Date(). new Date() is not a function. (evaluating ''hello' instanceof new Date()')
    420  Exception: 'hello' instanceof /a+/. / is not a function. (evaluating ''hello' instanceof /')
     420 Exception: 'hello' instanceof /a+/. /a+/ is not a function. (evaluating ''hello' instanceof /a+/')
    421421 Exception: new String('world') instanceof new Object(). new Object() is not a function. (evaluating 'new String('world') instanceof new Object()')
    422422 Exception: new String('world') instanceof f. f is not a function. (evaluating 'new String('world') instanceof f')
     
    439439 Exception: new String('world') instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new String('world') instanceof new Boolean(false)')
    440440 Exception: new String('world') instanceof new Date(). new Date() is not a function. (evaluating 'new String('world') instanceof new Date()')
    441  Exception: new String('world') instanceof /a+/. / is not a function. (evaluating 'new String('world') instanceof /')
     441 Exception: new String('world') instanceof /a+/. /a+/ is not a function. (evaluating 'new String('world') instanceof /a+/')
    442442 Exception: 10 instanceof new Object(). new Object() is not a function. (evaluating '10 instanceof new Object()')
    443443 Exception: 10 instanceof f. f is not a function. (evaluating '10 instanceof f')
     
    460460 Exception: 10 instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating '10 instanceof new Boolean(false)')
    461461 Exception: 10 instanceof new Date(). new Date() is not a function. (evaluating '10 instanceof new Date()')
    462  Exception: 10 instanceof /a+/. / is not a function. (evaluating '10 instanceof /')
     462 Exception: 10 instanceof /a+/. /a+/ is not a function. (evaluating '10 instanceof /a+/')
    463463 Exception: 10.2 instanceof new Object(). new Object() is not a function. (evaluating '10.2 instanceof new Object()')
    464464 Exception: 10.2 instanceof f. f is not a function. (evaluating '10.2 instanceof f')
     
    481481 Exception: 10.2 instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating '10.2 instanceof new Boolean(false)')
    482482 Exception: 10.2 instanceof new Date(). new Date() is not a function. (evaluating '10.2 instanceof new Date()')
    483  Exception: 10.2 instanceof /a+/. / is not a function. (evaluating '10.2 instanceof /')
     483 Exception: 10.2 instanceof /a+/. /a+/ is not a function. (evaluating '10.2 instanceof /a+/')
    484484 Exception: NaN instanceof new Object(). new Object() is not a function. (evaluating 'NaN instanceof new Object()')
    485485 Exception: NaN instanceof f. f is not a function. (evaluating 'NaN instanceof f')
     
    502502 Exception: NaN instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'NaN instanceof new Boolean(false)')
    503503 Exception: NaN instanceof new Date(). new Date() is not a function. (evaluating 'NaN instanceof new Date()')
    504  Exception: NaN instanceof /a+/. / is not a function. (evaluating 'NaN instanceof /')
     504 Exception: NaN instanceof /a+/. /a+/ is not a function. (evaluating 'NaN instanceof /a+/')
    505505 Exception: new Number(3) instanceof new Object(). new Object() is not a function. (evaluating 'new Number(3) instanceof new Object()')
    506506 Exception: new Number(3) instanceof f. f is not a function. (evaluating 'new Number(3) instanceof f')
     
    523523 Exception: new Number(3) instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Number(3) instanceof new Boolean(false)')
    524524 Exception: new Number(3) instanceof new Date(). new Date() is not a function. (evaluating 'new Number(3) instanceof new Date()')
    525  Exception: new Number(3) instanceof /a+/. / is not a function. (evaluating 'new Number(3) instanceof /')
     525 Exception: new Number(3) instanceof /a+/. /a+/ is not a function. (evaluating 'new Number(3) instanceof /a+/')
    526526 Exception: true instanceof new Object(). new Object() is not a function. (evaluating 'true instanceof new Object()')
    527527 Exception: true instanceof f. f is not a function. (evaluating 'true instanceof f')
     
    544544 Exception: true instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'true instanceof new Boolean(false)')
    545545 Exception: true instanceof new Date(). new Date() is not a function. (evaluating 'true instanceof new Date()')
    546  Exception: true instanceof /a+/. / is not a function. (evaluating 'true instanceof /')
     546 Exception: true instanceof /a+/. /a+/ is not a function. (evaluating 'true instanceof /a+/')
    547547 Exception: false instanceof new Object(). new Object() is not a function. (evaluating 'false instanceof new Object()')
    548548 Exception: false instanceof f. f is not a function. (evaluating 'false instanceof f')
     
    565565 Exception: false instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'false instanceof new Boolean(false)')
    566566 Exception: false instanceof new Date(). new Date() is not a function. (evaluating 'false instanceof new Date()')
    567  Exception: false instanceof /a+/. / is not a function. (evaluating 'false instanceof /')
     567 Exception: false instanceof /a+/. /a+/ is not a function. (evaluating 'false instanceof /a+/')
    568568 Exception: new Boolean(true) instanceof new Object(). new Object() is not a function. (evaluating 'new Boolean(true) instanceof new Object()')
    569569 Exception: new Boolean(true) instanceof f. f is not a function. (evaluating 'new Boolean(true) instanceof f')
     
    586586 Exception: new Boolean(true) instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Boolean(true) instanceof new Boolean(false)')
    587587 Exception: new Boolean(true) instanceof new Date(). new Date() is not a function. (evaluating 'new Boolean(true) instanceof new Date()')
    588  Exception: new Boolean(true) instanceof /a+/. / is not a function. (evaluating 'new Boolean(true) instanceof /')
     588 Exception: new Boolean(true) instanceof /a+/. /a+/ is not a function. (evaluating 'new Boolean(true) instanceof /a+/')
    589589 Exception: new Boolean(false) instanceof new Object(). new Object() is not a function. (evaluating 'new Boolean(false) instanceof new Object()')
    590590 Exception: new Boolean(false) instanceof f. f is not a function. (evaluating 'new Boolean(false) instanceof f')
     
    607607 Exception: new Boolean(false) instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Boolean(false) instanceof new Boolean(false)')
    608608 Exception: new Boolean(false) instanceof new Date(). new Date() is not a function. (evaluating 'new Boolean(false) instanceof new Date()')
    609  Exception: new Boolean(false) instanceof /a+/. / is not a function. (evaluating 'new Boolean(false) instanceof /')
     609 Exception: new Boolean(false) instanceof /a+/. /a+/ is not a function. (evaluating 'new Boolean(false) instanceof /a+/')
    610610 Exception: new Date() instanceof new Object(). new Object() is not a function. (evaluating 'new Date() instanceof new Object()')
    611611 Exception: new Date() instanceof f. f is not a function. (evaluating 'new Date() instanceof f')
     
    628628 Exception: new Date() instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating 'new Date() instanceof new Boolean(false)')
    629629 Exception: new Date() instanceof new Date(). new Date() is not a function. (evaluating 'new Date() instanceof new Date()')
    630  Exception: new Date() instanceof /a+/. / is not a function. (evaluating 'new Date() instanceof /')
     630 Exception: new Date() instanceof /a+/. /a+/ is not a function. (evaluating 'new Date() instanceof /a+/')
    631631 Exception: /a+/ instanceof new Object(). new Object() is not a function. (evaluating '/a+/ instanceof new Object()')
    632632 Exception: /a+/ instanceof f. f is not a function. (evaluating '/a+/ instanceof f')
     
    649649 Exception: /a+/ instanceof new Boolean(false). new Boolean(false) is not a function. (evaluating '/a+/ instanceof new Boolean(false)')
    650650 Exception: /a+/ instanceof new Date(). new Date() is not a function. (evaluating '/a+/ instanceof new Date()')
    651  Exception: /a+/ instanceof /a+/. / is not a function. (evaluating '/a+/ instanceof /')
     651 Exception: /a+/ instanceof /a+/. /a+/ is not a function. (evaluating '/a+/ instanceof /a+/')
  • trunk/JSTests/ChakraCore/test/Regex/nul_character.baseline-jsc

    r205387 r207798  
    11--- 1 ---
    225
    3 SyntaxError: Unexpected token '/'. Invalid regular expression.
    4 SyntaxError: Unexpected token '/'. Invalid regular expression.
     3SyntaxError: Unterminated regular expression literal '/'
     4SyntaxError: Unterminated regular expression literal '/'
    55--- 2 ---
    664
    7 SyntaxError: Unexpected token '/'. Invalid regular expression.
    8 SyntaxError: Unexpected token '/'. Invalid regular expression.
    9 SyntaxError: Unexpected token '/'. Invalid regular expression.
    10 SyntaxError: Unexpected token '/'. Invalid regular expression.
    11 SyntaxError: Unexpected token '/'. Invalid regular expression.
     7SyntaxError: Unterminated regular expression literal '/\'
     8SyntaxError: Unterminated regular expression literal '/\'
     9SyntaxError: Unterminated regular expression literal '/\'
     10SyntaxError: Unterminated regular expression literal '/\'
     11SyntaxError: Unterminated regular expression literal '/\'
    12124
    13135
    1414--- 3 ---
    15 SyntaxError: Unexpected token '/'. Invalid regular expression.
    16 SyntaxError: Unexpected token '/'. Invalid regular expression.
    17 SyntaxError: Unexpected token '/'. Invalid regular expression.
    18 SyntaxError: Unexpected token '/'. Invalid regular expression.
     15SyntaxError: Unterminated regular expression literal '/['
     16SyntaxError: Unterminated regular expression literal '/['
     17SyntaxError: Unterminated regular expression literal '/['
     18SyntaxError: Unterminated regular expression literal '/['
    19195
    20 SyntaxError: Unexpected token '/'. Invalid regular expression.
     20SyntaxError: Unterminated regular expression literal '/['
    2121SyntaxError: Invalid regular expression: unmatched parentheses
    2222--- 4 ---
  • trunk/JSTests/ChakraCore/test/es5/Lex_u3.baseline-jsc

    r205387 r207798  
    44 str const right
    55LS in string -  compile failure in ES5: expected.SyntaxError: Unexpected EOF
    6 LS in regex literal -  compile failure in ES5: expected.SyntaxError: Unexpected token '/'. Invalid regular expression.
     6LS in regex literal -  compile failure in ES5: expected.SyntaxError: Unterminated regular expression literal '/str const regex '
    77LS%20in%20escape%20sequence%20string%20literal%20%20%3Amore%20string
    88BOM is WS :  91
  • trunk/JSTests/ChangeLog

    r207781 r207798  
     12016-10-24  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Arrow functions with concise bodies cannot return regular expressions
     4        https://bugs.webkit.org/show_bug.cgi?id=163162
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * ChakraCore/test/Operators/instanceof.baseline-jsc:
     9        * ChakraCore/test/Regex/nul_character.baseline-jsc:
     10        * ChakraCore/test/es5/Lex_u3.baseline-jsc:
     11        * stress/parse-regexp-as-token.js: Added.
     12        (shouldBe):
     13
    1142016-10-24  Keith Miller  <keith_miller@apple.com>
    215
  • trunk/LayoutTests/ChangeLog

    r207797 r207798  
     12016-10-24  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Arrow functions with concise bodies cannot return regular expressions
     4        https://bugs.webkit.org/show_bug.cgi?id=163162
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * fast/regex/dom/non-pattern-characters-expected.txt:
     9        * js/arrowfunction-syntax-errors-expected.txt:
     10        * js/regexp-compile-crash-expected.txt:
     11        * sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T1-expected.txt:
     12        * sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T4-expected.txt:
     13        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.2_T2-expected.txt:
     14        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T1-expected.txt:
     15        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T3-expected.txt:
     16        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T1-expected.txt:
     17        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T3-expected.txt:
     18        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.2_T1-expected.txt:
     19        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T1-expected.txt:
     20        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T3-expected.txt:
     21        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T1-expected.txt:
     22        * sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T3-expected.txt:
     23
    1242016-10-24  Chris Dumez  <cdumez@apple.com>
    225
  • trunk/LayoutTests/fast/regex/dom/non-pattern-characters-expected.txt

    r158014 r207798  
    3434
    3535Testing regexp: [invalid \ variations]
    36 PASS /\/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
    37 PASS /a\/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     36PASS /\/ threw exception SyntaxError: Unterminated regular expression literal '/\/'.
     37PASS /a\/ threw exception SyntaxError: Unterminated regular expression literal '/a\/'.
    3838
    3939Testing regexp: /./
     
    8181
    8282Testing regexp: [invalid [ variations]
    83 PASS /[/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
    84 PASS /a[/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     83PASS /[/ threw exception SyntaxError: Unterminated regular expression literal '/[/'.
     84PASS /a[/ threw exception SyntaxError: Unterminated regular expression literal '/a[/'.
    8585PASS /[b-a]/ threw exception SyntaxError: Invalid regular expression: range out of order in character class.
    8686PASS /a[b-a]/ threw exception SyntaxError: Invalid regular expression: range out of order in character class.
  • trunk/LayoutTests/js/arrowfunction-syntax-errors-expected.txt

    r199927 r207798  
    77PASS x=> threw exception SyntaxError: Unexpected end of script.
    88PASS x=>* threw exception SyntaxError: Unexpected token '*'.
    9 PASS x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     9PASS x=>/ threw exception SyntaxError: Unterminated regular expression literal '/'.
    1010PASS x=>% threw exception SyntaxError: Unexpected token '%'.
    1111PASS x=>+ threw exception SyntaxError: Unexpected end of script.
     
    3333PASS x=>{ threw exception SyntaxError: Unexpected end of script.
    3434PASS x=>{* threw exception SyntaxError: Unexpected token '*'.
    35 PASS x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     35PASS x=>{/ threw exception SyntaxError: Unterminated regular expression literal '/'.
    3636PASS x=>{% threw exception SyntaxError: Unexpected token '%'.
    3737PASS x=>{+ threw exception SyntaxError: Unexpected end of script.
     
    6060PASS var y = x=> threw exception SyntaxError: Unexpected end of script.
    6161PASS var y = x=>* threw exception SyntaxError: Unexpected token '*'.
    62 PASS var y = x=>/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     62PASS var y = x=>/ threw exception SyntaxError: Unterminated regular expression literal '/'.
    6363PASS var y = x=>% threw exception SyntaxError: Unexpected token '%'.
    6464PASS var y = x=>+ threw exception SyntaxError: Unexpected end of script.
     
    8686PASS var y = x=>{ threw exception SyntaxError: Unexpected end of script.
    8787PASS var y = x=>{* threw exception SyntaxError: Unexpected token '*'.
    88 PASS var y = x=>{/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     88PASS var y = x=>{/ threw exception SyntaxError: Unterminated regular expression literal '/'.
    8989PASS var y = x=>{% threw exception SyntaxError: Unexpected token '%'.
    9090PASS var y = x=>{+ threw exception SyntaxError: Unexpected end of script.
  • trunk/LayoutTests/js/regexp-compile-crash-expected.txt

    r158014 r207798  
    55
    66PASS !!/\)[;s]+/ is true
    7 PASS /[/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
    8 PASS /[a/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
    9 PASS /[-/ threw exception SyntaxError: Unexpected token '/'. Invalid regular expression..
     7PASS /[/ threw exception SyntaxError: Unterminated regular expression literal '/[/'.
     8PASS /[a/ threw exception SyntaxError: Unterminated regular expression literal '/[a/'.
     9PASS /[-/ threw exception SyntaxError: Unterminated regular expression literal '/[-/'.
    1010PASS !!/(a)/ is true
    1111PASS !!/(a){1,3}/ is true
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 79: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 79: SyntaxError: Unterminated regular expression literal '/'
    22S7.4_A4_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.4_Comments/S7.4_A4_T4-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 79: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 79: SyntaxError: Unterminated regular expression literal '/'
    22S7.4_A4_T4
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.2_T2-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/\/'
    22S7.8.5_A1.2_T2
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/'
    22S7.8.5_A1.3_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.3_T3-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/'
    22S7.8.5_A1.3_T3
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/\'
    22S7.8.5_A1.5_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A1.5_T3-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/\'
    22S7.8.5_A1.5_T3
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.2_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/a\/'
    22S7.8.5_A2.2_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/a'
    22S7.8.5_A2.3_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.3_T3-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/a'
    22S7.8.5_A2.3_T3
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T1-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/a\'
    22S7.8.5_A2.5_T1
    33
  • trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.8_Literals/7.8.5_Regular_Expression_Literals/S7.8.5_A2.5_T3-expected.txt

    r158014 r207798  
    1 CONSOLE MESSAGE: line 77: SyntaxError: Unexpected token '/'. Invalid regular expression.
     1CONSOLE MESSAGE: line 77: SyntaxError: Unterminated regular expression literal '/a\'
    22S7.8.5_A2.5_T3
    33
  • trunk/Source/JavaScriptCore/ChangeLog

    r207794 r207798  
     12016-10-24  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Arrow functions with concise bodies cannot return regular expressions
     4        https://bugs.webkit.org/show_bug.cgi?id=163162
     5
     6        Reviewed by Filip Pizlo.
     7
     8        When we encounter the RegExp in the parser, we first scan it as / or /=.
     9        And if / or /= is parsed under the primary expression context, we rescan it
     10        as RegExp. However, we did not update the token record information. So the
     11        token record still says "I'm / or /=".
     12
     13        When we parse the string "() => /hello/", the last token becomes "/", which is
     14        the first character of the RegExp, instead of "/hello/". Since the arrow
     15        function parsing utilizes the end offset of the last token, we accidentally
     16        recognize the range of the above arrow function as "() => /".
     17
     18        In this patch, we update the token when rescanning under the RegExp context.
     19        This logic is similar to parsing Tail Template Literal token.
     20
     21        We also refine the error message for regular expression literals. And since
     22        the REGEXP token is now introduced, the other error messages using that token
     23        are improved too.
     24
     25        Currently, unterminated error messages can be seen in Parser.cpp. However,
     26        these messages cannot be shown to users if the lexer has m_error. So these
     27        code is meaningless. I'll move these tokenizing errors to the lexer in the
     28        subsequent patch[1].
     29
     30        [1]: https://bugs.webkit.org/show_bug.cgi?id=163928
     31
     32        * parser/Lexer.cpp:
     33        (JSC::Lexer<T>::fillTokenInfo):
     34        (JSC::Lexer<T>::lex):
     35        (JSC::Lexer<T>::scanRegExp):
     36        (JSC::Lexer<T>::scanTrailingTemplateString):
     37        (JSC::Lexer<T>::skipRegExp): Deleted.
     38        * parser/Lexer.h:
     39        (JSC::Lexer::getToken):
     40        * parser/Parser.cpp:
     41        (JSC::Parser<LexerType>::parseAssignmentExpression):
     42        * parser/Parser.h:
     43        (JSC::Parser::getToken):
     44        * parser/ParserTokens.h:
     45
    1462016-10-24  Per Arne Vollan  <pvollan@apple.com>
    247
  • trunk/Source/JavaScriptCore/parser/Lexer.cpp

    r206333 r207798  
    17841784
    17851785template <typename T>
     1786void Lexer<T>::fillTokenInfo(JSToken* tokenRecord, JSTokenType token, int lineNumber, int endOffset, int lineStartOffset, JSTextPosition endPosition)
     1787{
     1788    JSTokenLocation* tokenLocation = &tokenRecord->m_location;
     1789    tokenLocation->line = lineNumber;
     1790    tokenLocation->endOffset = endOffset;
     1791    tokenLocation->lineStartOffset = lineStartOffset;
     1792    ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset);
     1793    tokenRecord->m_endPosition = endPosition;
     1794    m_lastToken = token;
     1795}
     1796
     1797template <typename T>
    17861798JSTokenType Lexer<T>::lex(JSToken* tokenRecord, unsigned lexerFlags, bool strictMode)
    17871799{
     
    17961808    JSTokenType token = ERRORTOK;
    17971809    m_terminator = false;
    1798 
    1799     auto fillTokenInfo = [&] (int lineNumber, int endOffset, int lineStartOffset, JSTextPosition endPosition) {
    1800         tokenLocation->line = lineNumber;
    1801         tokenLocation->endOffset = endOffset;
    1802         tokenLocation->lineStartOffset = lineStartOffset;
    1803         ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset);
    1804         tokenRecord->m_endPosition = endPosition;
    1805         m_lastToken = token;
    1806     };
    18071810
    18081811start:
     
    23132316
    23142317        token = SEMICOLON;
    2315         fillTokenInfo(lineNumber, endOffset, lineStartOffset, endPosition);
     2318        fillTokenInfo(tokenRecord, token, lineNumber, endOffset, lineStartOffset, endPosition);
    23162319        return token;
    23172320    }
    23182321
    23192322returnToken:
    2320     fillTokenInfo(m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
     2323    fillTokenInfo(tokenRecord, token, m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
    23212324    return token;
    23222325
    23232326returnError:
    23242327    m_error = true;
    2325     fillTokenInfo(m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
     2328    fillTokenInfo(tokenRecord, token, m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
    23262329    RELEASE_ASSERT(token & ErrorTokenFlag);
    23272330    return token;
     
    23412344
    23422345template <typename T>
    2343 bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
    2344 {
     2346JSTokenType Lexer<T>::scanRegExp(JSToken* tokenRecord, UChar patternPrefix)
     2347{
     2348    JSTokenData* tokenData = &tokenRecord->m_data;
    23452349    ASSERT(m_buffer16.isEmpty());
    23462350
     
    23592363        if (isLineTerminator(m_current) || atEnd()) {
    23602364            m_buffer16.shrink(0);
    2361             return false;
     2365            JSTokenType token = UNTERMINATED_REGEXP_LITERAL_ERRORTOK;
     2366            fillTokenInfo(tokenRecord, token, m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
     2367            m_error = true;
     2368            m_lexErrorMessage = makeString("Unterminated regular expression literal '", getToken(*tokenRecord), "'");
     2369            return token;
    23622370        }
    23632371
     
    23902398    }
    23912399
    2392     pattern = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
     2400    tokenData->pattern = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
    23932401
    23942402    m_buffer16.shrink(0);
     
    24012409    }
    24022410
    2403     flags = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
     2411    tokenData->flags = makeRightSizedIdentifier(m_buffer16.data(), m_buffer16.size(), charactersOredTogether);
    24042412    m_buffer16.shrink(0);
    24052413
    2406     return true;
    2407 }
    2408 
    2409 template <typename T>
    2410 bool Lexer<T>::skipRegExp()
    2411 {
    2412     bool lastWasEscape = false;
    2413     bool inBrackets = false;
    2414 
    2415     while (true) {
    2416         if (isLineTerminator(m_current) || atEnd())
    2417             return false;
    2418 
    2419         T prev = m_current;
    2420        
    2421         shift();
    2422 
    2423         if (prev == '/' && !lastWasEscape && !inBrackets)
    2424             break;
    2425 
    2426         if (lastWasEscape) {
    2427             lastWasEscape = false;
    2428             continue;
    2429         }
    2430 
    2431         switch (prev) {
    2432         case '[':
    2433             inBrackets = true;
    2434             break;
    2435         case ']':
    2436             inBrackets = false;
    2437             break;
    2438         case '\\':
    2439             lastWasEscape = true;
    2440             break;
    2441         }
    2442     }
    2443 
    2444     while (isIdentPart(m_current))
    2445         shift();
    2446 
    2447     return true;
     2414    // Since RegExp always ends with /, m_atLineStart always becomes false.
     2415    m_atLineStart = false;
     2416
     2417    JSTokenType token = REGEXP;
     2418    fillTokenInfo(tokenRecord, token, m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
     2419    return token;
    24482420}
    24492421
     
    24522424{
    24532425    JSTokenData* tokenData = &tokenRecord->m_data;
    2454     JSTokenLocation* tokenLocation = &tokenRecord->m_location;
    24552426    ASSERT(!m_error);
    24562427    ASSERT(m_buffer16.isEmpty());
     
    24632434        token = result == StringUnterminated ? UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK : INVALID_TEMPLATE_LITERAL_ERRORTOK;
    24642435        m_error = true;
    2465     } else {
     2436    } else
    24662437        token = TEMPLATE;
    2467         m_lastToken = token;
    2468     }
    24692438
    24702439    // Since TemplateString always ends with ` or }, m_atLineStart always becomes false.
    24712440    m_atLineStart = false;
    2472 
    2473     // Adjust current tokenLocation data for TemplateString.
    2474     tokenLocation->line = m_lineNumber;
    2475     tokenLocation->endOffset = currentOffset();
    2476     tokenLocation->lineStartOffset = currentLineStartOffset();
    2477     ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset);
    2478     tokenRecord->m_endPosition = currentPosition();
     2441    fillTokenInfo(tokenRecord, token, m_lineNumber, currentOffset(), currentLineStartOffset(), currentPosition());
    24792442    return token;
    24802443}
  • trunk/Source/JavaScriptCore/parser/Lexer.h

    r206525 r207798  
    7676    int lastLineNumber() const { return m_lastLineNumber; }
    7777    bool prevTerminator() const { return m_terminator; }
    78     bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
     78    JSTokenType scanRegExp(JSToken*, UChar patternPrefix = 0);
    7979    enum class RawStringsBuildMode { BuildRawStrings, DontBuildRawStrings };
    8080    JSTokenType scanTrailingTemplateString(JSToken*, RawStringsBuildMode);
    81     bool skipRegExp();
    8281
    8382    // Functions for use after parsing.
     
    116115    JSTokenType lexExpectIdentifier(JSToken*, unsigned, bool strictMode);
    117116
     117    ALWAYS_INLINE StringView getToken(const JSToken& token)
     118    {
     119        SourceProvider* sourceProvider = m_source->provider();
     120        ASSERT_WITH_MESSAGE(token.m_location.startOffset <= token.m_location.endOffset, "Calling this function with the baked token.");
     121        return sourceProvider->getRange(token.m_location.startOffset, token.m_location.endOffset);
     122    }
     123
    118124private:
    119125    void record8(int);
     
    181187    template <unsigned length>
    182188    ALWAYS_INLINE bool consume(const char (&input)[length]);
     189
     190    void fillTokenInfo(JSToken*, JSTokenType, int lineNumber, int endOffset, int lineStartOffset, JSTextPosition endPosition);
    183191
    184192    static const size_t initialReadBufferCapacity = 32;
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r207628 r207798  
    43074307    case DIVIDE: {
    43084308        /* regexp */
    4309         const Identifier* pattern;
    4310         const Identifier* flags;
    43114309        if (match(DIVEQUAL))
    4312             failIfFalse(m_lexer->scanRegExp(pattern, flags, '='), "Invalid regular expression");
     4310            m_token.m_type = m_lexer->scanRegExp(&m_token, '=');
    43134311        else
    4314             failIfFalse(m_lexer->scanRegExp(pattern, flags), "Invalid regular expression");
    4315        
     4312            m_token.m_type = m_lexer->scanRegExp(&m_token);
     4313        matchOrFail(REGEXP, "Invalid regular expression");
     4314
     4315        const Identifier* pattern = m_token.m_data.pattern;
     4316        const Identifier* flags = m_token.m_data.flags;
    43164317        JSTextPosition start = tokenStartPosition();
    43174318        JSTokenLocation location(tokenLocation());
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r206653 r207798  
    12891289
    12901290    void printUnexpectedTokenText(WTF::PrintStream&);
    1291     ALWAYS_INLINE StringView getToken() {
    1292         SourceProvider* sourceProvider = m_source->provider();
    1293         return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset);
     1291    ALWAYS_INLINE StringView getToken()
     1292    {
     1293        return m_lexer->getToken(m_token);
    12941294    }
    12951295   
  • trunk/Source/JavaScriptCore/parser/ParserTokens.h

    r206525 r207798  
    9797    STRING,
    9898    TEMPLATE,
     99    REGEXP,
    99100    SEMICOLON,
    100101    COLON,
     
    167168    UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
    168169    UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
    169     INVALID_TEMPLATE_LITERAL_ERRORTOK = 14 | ErrorTokenFlag,
     170    UNTERMINATED_REGEXP_LITERAL_ERRORTOK = 14 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
     171    INVALID_TEMPLATE_LITERAL_ERRORTOK = 15 | ErrorTokenFlag,
    170172};
    171173
     
    200202        bool isTail;
    201203    };
     204    struct {
     205        const Identifier* pattern;
     206        const Identifier* flags;
     207    };
    202208};
    203209
Note: See TracChangeset for help on using the changeset viewer.