LCOV - code coverage report
Current view: top level - test/cctest - test-parsing.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2335 2412 96.8 %
Date: 2019-01-20 Functions: 273 299 91.3 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <stdio.h>
      29             : #include <stdlib.h>
      30             : #include <string.h>
      31             : 
      32             : #include <memory>
      33             : 
      34             : #include "src/v8.h"
      35             : 
      36             : #include "src/api-inl.h"
      37             : #include "src/ast/ast-value-factory.h"
      38             : #include "src/ast/ast.h"
      39             : #include "src/base/enum-set.h"
      40             : #include "src/compiler.h"
      41             : #include "src/execution.h"
      42             : #include "src/flags.h"
      43             : #include "src/isolate.h"
      44             : #include "src/objects-inl.h"
      45             : #include "src/objects.h"
      46             : #include "src/parsing/parse-info.h"
      47             : #include "src/parsing/parser.h"
      48             : #include "src/parsing/parsing.h"
      49             : #include "src/parsing/preparser.h"
      50             : #include "src/parsing/rewriter.h"
      51             : #include "src/parsing/scanner-character-streams.h"
      52             : #include "src/parsing/token.h"
      53             : 
      54             : #include "test/cctest/cctest.h"
      55             : #include "test/cctest/scope-test-helper.h"
      56             : #include "test/cctest/unicode-helpers.h"
      57             : 
      58             : namespace v8 {
      59             : namespace internal {
      60             : namespace test_parsing {
      61             : 
      62             : namespace {
      63             : 
      64             : int* global_use_counts = nullptr;
      65             : 
      66          30 : void MockUseCounterCallback(v8::Isolate* isolate,
      67             :                             v8::Isolate::UseCounterFeature feature) {
      68          30 :   ++global_use_counts[feature];
      69          30 : }
      70             : 
      71             : }  // namespace
      72             : 
      73           0 : bool TokenIsAutoSemicolon(Token::Value token) {
      74         550 :   switch (token) {
      75             :     case Token::SEMICOLON:
      76             :     case Token::EOS:
      77             :     case Token::RBRACE:
      78             :       return true;
      79             :     default:
      80           0 :       return false;
      81             :   }
      82             : }
      83             : 
      84       28342 : TEST(AutoSemicolonToken) {
      85         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
      86             :     Token::Value token = static_cast<Token::Value>(i);
      87        1100 :     CHECK_EQ(TokenIsAutoSemicolon(token), Token::IsAutoSemicolon(token));
      88             :   }
      89           5 : }
      90             : 
      91           0 : bool TokenIsAnyIdentifier(Token::Value token) {
      92         550 :   switch (token) {
      93             :     case Token::IDENTIFIER:
      94             :     case Token::ASYNC:
      95             :     case Token::AWAIT:
      96             :     case Token::YIELD:
      97             :     case Token::LET:
      98             :     case Token::STATIC:
      99             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     100             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     101             :       return true;
     102             :     default:
     103           0 :       return false;
     104             :   }
     105             : }
     106             : 
     107       28342 : TEST(AnyIdentifierToken) {
     108         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     109             :     Token::Value token = static_cast<Token::Value>(i);
     110        1100 :     CHECK_EQ(TokenIsAnyIdentifier(token), Token::IsAnyIdentifier(token));
     111             :   }
     112           5 : }
     113             : 
     114           0 : bool TokenIsCallable(Token::Value token) {
     115         550 :   switch (token) {
     116             :     case Token::SUPER:
     117             :     case Token::IDENTIFIER:
     118             :     case Token::ASYNC:
     119             :     case Token::AWAIT:
     120             :     case Token::YIELD:
     121             :     case Token::LET:
     122             :     case Token::STATIC:
     123             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     124             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     125             :       return true;
     126             :     default:
     127           0 :       return false;
     128             :   }
     129             : }
     130             : 
     131       28342 : TEST(CallableToken) {
     132         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     133             :     Token::Value token = static_cast<Token::Value>(i);
     134        1100 :     CHECK_EQ(TokenIsCallable(token), Token::IsCallable(token));
     135             :   }
     136           5 : }
     137             : 
     138           0 : bool TokenIsValidIdentifier(Token::Value token, LanguageMode language_mode,
     139             :                             bool is_generator, bool disallow_await) {
     140        4400 :   switch (token) {
     141             :     case Token::IDENTIFIER:
     142             :     case Token::ASYNC:
     143             :       return true;
     144             :     case Token::YIELD:
     145          40 :       return !is_generator && is_sloppy(language_mode);
     146             :     case Token::AWAIT:
     147          40 :       return !disallow_await;
     148             :     case Token::LET:
     149             :     case Token::STATIC:
     150             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     151             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     152           0 :       return is_sloppy(language_mode);
     153             :     default:
     154           0 :       return false;
     155             :   }
     156             :   UNREACHABLE();
     157             : }
     158             : 
     159       28342 : TEST(IsValidIdentifierToken) {
     160         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     161             :     Token::Value token = static_cast<Token::Value>(i);
     162        1100 :     for (size_t raw_language_mode = 0; raw_language_mode < LanguageModeSize;
     163             :          raw_language_mode++) {
     164        1100 :       LanguageMode mode = static_cast<LanguageMode>(raw_language_mode);
     165        3300 :       for (int is_generator = 0; is_generator < 2; is_generator++) {
     166        4400 :         for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
     167        8800 :           CHECK_EQ(
     168             :               TokenIsValidIdentifier(token, mode, is_generator, disallow_await),
     169             :               Token::IsValidIdentifier(token, mode, is_generator,
     170             :                                        disallow_await));
     171             :         }
     172             :       }
     173             :     }
     174             :   }
     175           5 : }
     176             : 
     177           0 : bool TokenIsStrictReservedWord(Token::Value token) {
     178         550 :   switch (token) {
     179             :     case Token::LET:
     180             :     case Token::YIELD:
     181             :     case Token::STATIC:
     182             :     case Token::FUTURE_STRICT_RESERVED_WORD:
     183             :     case Token::ESCAPED_STRICT_RESERVED_WORD:
     184             :       return true;
     185             :     default:
     186           0 :       return false;
     187             :   }
     188             :   UNREACHABLE();
     189             : }
     190             : 
     191       28342 : TEST(IsStrictReservedWord) {
     192         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     193             :     Token::Value token = static_cast<Token::Value>(i);
     194        1100 :     CHECK_EQ(TokenIsStrictReservedWord(token),
     195             :              Token::IsStrictReservedWord(token));
     196             :   }
     197           5 : }
     198             : 
     199           0 : bool TokenIsLiteral(Token::Value token) {
     200         550 :   switch (token) {
     201             :     case Token::NULL_LITERAL:
     202             :     case Token::TRUE_LITERAL:
     203             :     case Token::FALSE_LITERAL:
     204             :     case Token::NUMBER:
     205             :     case Token::SMI:
     206             :     case Token::BIGINT:
     207             :     case Token::STRING:
     208             :       return true;
     209             :     default:
     210           0 :       return false;
     211             :   }
     212             :   UNREACHABLE();
     213             : }
     214             : 
     215       28342 : TEST(IsLiteralToken) {
     216         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     217             :     Token::Value token = static_cast<Token::Value>(i);
     218        1100 :     CHECK_EQ(TokenIsLiteral(token), Token::IsLiteral(token));
     219             :   }
     220           5 : }
     221             : 
     222           0 : bool TokenIsAssignmentOp(Token::Value token) {
     223        1095 :   switch (token) {
     224             :     case Token::INIT:
     225             :     case Token::ASSIGN:
     226             : #define T(name, string, precedence) case Token::name:
     227             :       BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_ASSIGN_TOKEN)
     228             : #undef T
     229             :       return true;
     230             :     default:
     231           0 :       return false;
     232             :   }
     233             : }
     234             : 
     235       28342 : TEST(AssignmentOp) {
     236         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     237             :     Token::Value token = static_cast<Token::Value>(i);
     238        1100 :     CHECK_EQ(TokenIsAssignmentOp(token), Token::IsAssignmentOp(token));
     239             :   }
     240           5 : }
     241             : 
     242           0 : bool TokenIsArrowOrAssignmentOp(Token::Value token) {
     243        1095 :   return token == Token::ARROW || TokenIsAssignmentOp(token);
     244             : }
     245             : 
     246       28342 : TEST(ArrowOrAssignmentOp) {
     247         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     248             :     Token::Value token = static_cast<Token::Value>(i);
     249        1100 :     CHECK_EQ(TokenIsArrowOrAssignmentOp(token),
     250             :              Token::IsArrowOrAssignmentOp(token));
     251             :   }
     252           5 : }
     253             : 
     254           0 : bool TokenIsBinaryOp(Token::Value token) {
     255         550 :   switch (token) {
     256             :     case Token::COMMA:
     257             :     case Token::OR:
     258             :     case Token::AND:
     259             : #define T(name, string, precedence) case Token::name:
     260             :       BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_TOKEN)
     261             : #undef T
     262             :       return true;
     263             :     default:
     264           0 :       return false;
     265             :   }
     266             : }
     267             : 
     268       28342 : TEST(BinaryOp) {
     269         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     270             :     Token::Value token = static_cast<Token::Value>(i);
     271        1100 :     CHECK_EQ(TokenIsBinaryOp(token), Token::IsBinaryOp(token));
     272             :   }
     273           5 : }
     274             : 
     275           0 : bool TokenIsCompareOp(Token::Value token) {
     276         550 :   switch (token) {
     277             :     case Token::EQ:
     278             :     case Token::EQ_STRICT:
     279             :     case Token::NE:
     280             :     case Token::NE_STRICT:
     281             :     case Token::LT:
     282             :     case Token::GT:
     283             :     case Token::LTE:
     284             :     case Token::GTE:
     285             :     case Token::INSTANCEOF:
     286             :     case Token::IN:
     287             :       return true;
     288             :     default:
     289           0 :       return false;
     290             :   }
     291             : }
     292             : 
     293       28342 : TEST(CompareOp) {
     294         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     295             :     Token::Value token = static_cast<Token::Value>(i);
     296        1100 :     CHECK_EQ(TokenIsCompareOp(token), Token::IsCompareOp(token));
     297             :   }
     298           5 : }
     299             : 
     300           0 : bool TokenIsOrderedRelationalCompareOp(Token::Value token) {
     301         550 :   switch (token) {
     302             :     case Token::LT:
     303             :     case Token::GT:
     304             :     case Token::LTE:
     305             :     case Token::GTE:
     306             :       return true;
     307             :     default:
     308           0 :       return false;
     309             :   }
     310             : }
     311             : 
     312       28342 : TEST(IsOrderedRelationalCompareOp) {
     313         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     314             :     Token::Value token = static_cast<Token::Value>(i);
     315        1100 :     CHECK_EQ(TokenIsOrderedRelationalCompareOp(token),
     316             :              Token::IsOrderedRelationalCompareOp(token));
     317             :   }
     318           5 : }
     319             : 
     320           0 : bool TokenIsEqualityOp(Token::Value token) {
     321         550 :   switch (token) {
     322             :     case Token::EQ:
     323             :     case Token::EQ_STRICT:
     324             :       return true;
     325             :     default:
     326           0 :       return false;
     327             :   }
     328             : }
     329             : 
     330       28342 : TEST(IsEqualityOp) {
     331         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     332             :     Token::Value token = static_cast<Token::Value>(i);
     333        1100 :     CHECK_EQ(TokenIsEqualityOp(token), Token::IsEqualityOp(token));
     334             :   }
     335           5 : }
     336             : 
     337           0 : bool TokenIsBitOp(Token::Value token) {
     338             :   switch (token) {
     339             :     case Token::BIT_OR:
     340             :     case Token::BIT_XOR:
     341             :     case Token::BIT_AND:
     342             :     case Token::SHL:
     343             :     case Token::SAR:
     344             :     case Token::SHR:
     345             :     case Token::BIT_NOT:
     346             :       return true;
     347             :     default:
     348           0 :       return false;
     349             :   }
     350             : }
     351             : 
     352       28342 : TEST(IsBitOp) {
     353         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     354             :     Token::Value token = static_cast<Token::Value>(i);
     355        1100 :     CHECK_EQ(TokenIsBitOp(token), Token::IsBitOp(token));
     356             :   }
     357           5 : }
     358             : 
     359           0 : bool TokenIsUnaryOp(Token::Value token) {
     360        1100 :   switch (token) {
     361             :     case Token::NOT:
     362             :     case Token::BIT_NOT:
     363             :     case Token::DELETE:
     364             :     case Token::TYPEOF:
     365             :     case Token::VOID:
     366             :     case Token::ADD:
     367             :     case Token::SUB:
     368             :       return true;
     369             :     default:
     370           0 :       return false;
     371             :   }
     372             : }
     373             : 
     374       28342 : TEST(IsUnaryOp) {
     375         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     376             :     Token::Value token = static_cast<Token::Value>(i);
     377        1100 :     CHECK_EQ(TokenIsUnaryOp(token), Token::IsUnaryOp(token));
     378             :   }
     379           5 : }
     380             : 
     381           0 : bool TokenIsPropertyOrCall(Token::Value token) {
     382         550 :   switch (token) {
     383             :     case Token::TEMPLATE_SPAN:
     384             :     case Token::TEMPLATE_TAIL:
     385             :     case Token::PERIOD:
     386             :     case Token::LBRACK:
     387             :     case Token::LPAREN:
     388             :       return true;
     389             :     default:
     390           0 :       return false;
     391             :   }
     392             : }
     393             : 
     394       28342 : TEST(IsPropertyOrCall) {
     395         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     396             :     Token::Value token = static_cast<Token::Value>(i);
     397        1100 :     CHECK_EQ(TokenIsPropertyOrCall(token), Token::IsPropertyOrCall(token));
     398             :   }
     399           5 : }
     400             : 
     401           0 : bool TokenIsMember(Token::Value token) {
     402         550 :   switch (token) {
     403             :     case Token::TEMPLATE_SPAN:
     404             :     case Token::TEMPLATE_TAIL:
     405             :     case Token::PERIOD:
     406             :     case Token::LBRACK:
     407             :       return true;
     408             :     default:
     409           0 :       return false;
     410             :   }
     411             : }
     412             : 
     413           0 : bool TokenIsTemplate(Token::Value token) {
     414         550 :   switch (token) {
     415             :     case Token::TEMPLATE_SPAN:
     416             :     case Token::TEMPLATE_TAIL:
     417             :       return true;
     418             :     default:
     419           0 :       return false;
     420             :   }
     421             : }
     422             : 
     423           0 : bool TokenIsProperty(Token::Value token) {
     424         550 :   switch (token) {
     425             :     case Token::PERIOD:
     426             :     case Token::LBRACK:
     427             :       return true;
     428             :     default:
     429           0 :       return false;
     430             :   }
     431             : }
     432             : 
     433       28342 : TEST(IsMember) {
     434         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     435             :     Token::Value token = static_cast<Token::Value>(i);
     436        1100 :     CHECK_EQ(TokenIsMember(token), Token::IsMember(token));
     437             :   }
     438           5 : }
     439             : 
     440       28342 : TEST(IsTemplate) {
     441         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     442             :     Token::Value token = static_cast<Token::Value>(i);
     443        1100 :     CHECK_EQ(TokenIsTemplate(token), Token::IsTemplate(token));
     444             :   }
     445           5 : }
     446             : 
     447       28342 : TEST(IsProperty) {
     448         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     449             :     Token::Value token = static_cast<Token::Value>(i);
     450        1100 :     CHECK_EQ(TokenIsProperty(token), Token::IsProperty(token));
     451             :   }
     452           5 : }
     453             : 
     454           0 : bool TokenIsCountOp(Token::Value token) {
     455        1065 :   switch (token) {
     456             :     case Token::INC:
     457             :     case Token::DEC:
     458             :       return true;
     459             :     default:
     460           0 :       return false;
     461             :   }
     462             : }
     463             : 
     464       28342 : TEST(IsCountOp) {
     465         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     466             :     Token::Value token = static_cast<Token::Value>(i);
     467        1100 :     CHECK_EQ(TokenIsCountOp(token), Token::IsCountOp(token));
     468             :   }
     469           5 : }
     470             : 
     471       28342 : TEST(IsUnaryOrCountOp) {
     472         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     473             :     Token::Value token = static_cast<Token::Value>(i);
     474        1615 :     CHECK_EQ(TokenIsUnaryOp(token) || TokenIsCountOp(token),
     475             :              Token::IsUnaryOrCountOp(token));
     476             :   }
     477           5 : }
     478             : 
     479           0 : bool TokenIsShiftOp(Token::Value token) {
     480         550 :   switch (token) {
     481             :     case Token::SHL:
     482             :     case Token::SAR:
     483             :     case Token::SHR:
     484             :       return true;
     485             :     default:
     486           0 :       return false;
     487             :   }
     488             : }
     489             : 
     490       28342 : TEST(IsShiftOp) {
     491         555 :   for (int i = 0; i < Token::NUM_TOKENS; i++) {
     492             :     Token::Value token = static_cast<Token::Value>(i);
     493        1100 :     CHECK_EQ(TokenIsShiftOp(token), Token::IsShiftOp(token));
     494             :   }
     495           5 : }
     496             : 
     497       28342 : TEST(ScanKeywords) {
     498             :   struct KeywordToken {
     499             :     const char* keyword;
     500             :     i::Token::Value token;
     501             :   };
     502             : 
     503             :   static const KeywordToken keywords[] = {
     504             : #define KEYWORD(t, s, d) { s, i::Token::t },
     505             :       TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
     506             : #undef KEYWORD
     507             :           {nullptr, i::Token::IDENTIFIER}};
     508             : 
     509             :   KeywordToken key_token;
     510             :   char buffer[32];
     511         210 :   for (int i = 0; (key_token = keywords[i]).keyword != nullptr; i++) {
     512             :     const char* keyword = key_token.keyword;
     513         205 :     size_t length = strlen(key_token.keyword);
     514         205 :     CHECK(static_cast<int>(sizeof(buffer)) >= length);
     515             :     {
     516         205 :       auto stream = i::ScannerStream::ForTesting(keyword, length);
     517         410 :       i::Scanner scanner(stream.get(), false);
     518         205 :       scanner.Initialize();
     519         205 :       CHECK_EQ(key_token.token, scanner.Next());
     520         205 :       CHECK_EQ(i::Token::EOS, scanner.Next());
     521             :     }
     522             :     // Removing characters will make keyword matching fail.
     523             :     {
     524         205 :       auto stream = i::ScannerStream::ForTesting(keyword, length - 1);
     525         410 :       i::Scanner scanner(stream.get(), false);
     526         205 :       scanner.Initialize();
     527         205 :       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     528         205 :       CHECK_EQ(i::Token::EOS, scanner.Next());
     529             :     }
     530             :     // Adding characters will make keyword matching fail.
     531             :     static const char chars_to_append[] = { 'z', '0', '_' };
     532         820 :     for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
     533             :       i::MemMove(buffer, keyword, length);
     534         615 :       buffer[length] = chars_to_append[j];
     535         615 :       auto stream = i::ScannerStream::ForTesting(buffer, length + 1);
     536        1230 :       i::Scanner scanner(stream.get(), false);
     537         615 :       scanner.Initialize();
     538         615 :       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     539         615 :       CHECK_EQ(i::Token::EOS, scanner.Next());
     540             :     }
     541             :     // Replacing characters will make keyword matching fail.
     542             :     {
     543             :       i::MemMove(buffer, keyword, length);
     544         205 :       buffer[length - 1] = '_';
     545         205 :       auto stream = i::ScannerStream::ForTesting(buffer, length);
     546         410 :       i::Scanner scanner(stream.get(), false);
     547         205 :       scanner.Initialize();
     548         205 :       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     549         205 :       CHECK_EQ(i::Token::EOS, scanner.Next());
     550             :     }
     551             :   }
     552           5 : }
     553             : 
     554             : 
     555       28342 : TEST(ScanHTMLEndComments) {
     556           5 :   v8::V8::Initialize();
     557           5 :   v8::Isolate* isolate = CcTest::isolate();
     558         360 :   i::Isolate* i_isolate = CcTest::i_isolate();
     559           5 :   v8::HandleScope handles(isolate);
     560             : 
     561             :   // Regression test. See:
     562             :   //    http://code.google.com/p/chromium/issues/detail?id=53548
     563             :   // Tests that --> is correctly interpreted as comment-to-end-of-line if there
     564             :   // is only whitespace before it on the line (with comments considered as
     565             :   // whitespace, even a multiline-comment containing a newline).
     566             :   // This was not the case if it occurred before the first real token
     567             :   // in the input.
     568             :   // clang-format off
     569             :   const char* tests[] = {
     570             :       // Before first real token.
     571             :       "-->",
     572             :       "--> is eol-comment",
     573             :       "--> is eol-comment\nvar y = 37;\n",
     574             :       "\n --> is eol-comment\nvar y = 37;\n",
     575             :       "\n-->is eol-comment\nvar y = 37;\n",
     576             :       "\n-->\nvar y = 37;\n",
     577             :       "/* precomment */ --> is eol-comment\nvar y = 37;\n",
     578             :       "/* precomment */-->eol-comment\nvar y = 37;\n",
     579             :       "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
     580             :       "\n/*precomment*/-->eol-comment\nvar y = 37;\n",
     581             :       // After first real token.
     582             :       "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
     583             :       "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
     584             :       "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
     585             :       "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
     586             :       "var x = 42;/*\n*/-->is eol-comment\nvar y = 37;\n",
     587             :       // With multiple comments preceding HTMLEndComment
     588             :       "/* MLC \n */ /* SLDC */ --> is eol-comment\nvar y = 37;\n",
     589             :       "/* MLC \n */ /* SLDC1 */ /* SLDC2 */ --> is eol-comment\nvar y = 37;\n",
     590             :       "/* MLC1 \n */ /* MLC2 \n */ --> is eol-comment\nvar y = 37;\n",
     591             :       "/* SLDC */ /* MLC \n */ --> is eol-comment\nvar y = 37;\n",
     592             :       "/* MLC1 \n */ /* SLDC1 */ /* MLC2 \n */ /* SLDC2 */ --> is eol-comment\n"
     593             :           "var y = 37;\n",
     594             :       nullptr
     595           5 :   };
     596             : 
     597             :   const char* fail_tests[] = {
     598             :       "x --> is eol-comment\nvar y = 37;\n",
     599             :       "\"\\n\" --> is eol-comment\nvar y = 37;\n",
     600             :       "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
     601             :       "var x = 42; --> is eol-comment\nvar y = 37;\n",
     602             :       nullptr
     603           5 :   };
     604             :   // clang-format on
     605             : 
     606             :   // Parser/Scanner needs a stack limit.
     607           5 :   i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
     608           5 :                                           128 * 1024);
     609           5 :   uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
     610         105 :   for (int i = 0; tests[i]; i++) {
     611             :     const char* source = tests[i];
     612         100 :     auto stream = i::ScannerStream::ForTesting(source);
     613         200 :     i::Scanner scanner(stream.get(), false);
     614         100 :     scanner.Initialize();
     615         200 :     i::Zone zone(i_isolate->allocator(), ZONE_NAME);
     616             :     i::AstValueFactory ast_value_factory(&zone,
     617             :                                          i_isolate->ast_string_constants(),
     618         200 :                                          i_isolate->heap()->HashSeed());
     619             :     i::PendingCompilationErrorHandler pending_error_handler;
     620             :     i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
     621             :                            &pending_error_handler,
     622             :                            i_isolate->counters()->runtime_call_stats(),
     623         100 :                            i_isolate->logger());
     624         100 :     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     625         100 :     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     626         100 :     CHECK(!pending_error_handler.has_pending_error());
     627             :   }
     628             : 
     629          20 :   for (int i = 0; fail_tests[i]; i++) {
     630             :     const char* source = fail_tests[i];
     631          20 :     auto stream = i::ScannerStream::ForTesting(source);
     632          40 :     i::Scanner scanner(stream.get(), false);
     633          20 :     scanner.Initialize();
     634          40 :     i::Zone zone(i_isolate->allocator(), ZONE_NAME);
     635             :     i::AstValueFactory ast_value_factory(&zone,
     636             :                                          i_isolate->ast_string_constants(),
     637          40 :                                          i_isolate->heap()->HashSeed());
     638             :     i::PendingCompilationErrorHandler pending_error_handler;
     639             :     i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
     640             :                            &pending_error_handler,
     641             :                            i_isolate->counters()->runtime_call_stats(),
     642          20 :                            i_isolate->logger());
     643          20 :     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     644             :     // Even in the case of a syntax error, kPreParseSuccess is returned.
     645          20 :     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     646          20 :     CHECK(pending_error_handler.has_pending_error() ||
     647             :           pending_error_handler.has_error_unidentifiable_by_preparser());
     648           5 :   }
     649           5 : }
     650             : 
     651       28342 : TEST(ScanHtmlComments) {
     652             :   const char* src = "a <!-- b --> c";
     653             :   // Disallow HTML comments.
     654             :   {
     655           5 :     auto stream = i::ScannerStream::ForTesting(src);
     656          10 :     i::Scanner scanner(stream.get(), true);
     657           5 :     scanner.Initialize();
     658           5 :     CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     659           5 :     CHECK_EQ(i::Token::ILLEGAL, scanner.Next());
     660             :   }
     661             : 
     662             :   // Skip HTML comments:
     663             :   {
     664           5 :     auto stream = i::ScannerStream::ForTesting(src);
     665          10 :     i::Scanner scanner(stream.get(), false);
     666           5 :     scanner.Initialize();
     667           5 :     CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     668           5 :     CHECK_EQ(i::Token::EOS, scanner.Next());
     669             :   }
     670           5 : }
     671             : 
     672           0 : class ScriptResource : public v8::String::ExternalOneByteStringResource {
     673             :  public:
     674             :   ScriptResource(const char* data, size_t length)
     675             :       : data_(data), length_(length) { }
     676             : 
     677           0 :   const char* data() const override { return data_; }
     678           0 :   size_t length() const override { return length_; }
     679             : 
     680             :  private:
     681             :   const char* data_;
     682             :   size_t length_;
     683             : };
     684             : 
     685             : 
     686       28342 : TEST(StandAlonePreParser) {
     687           5 :   v8::V8::Initialize();
     688          90 :   i::Isolate* i_isolate = CcTest::i_isolate();
     689             : 
     690           5 :   i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
     691           5 :                                           128 * 1024);
     692             : 
     693             :   const char* programs[] = {"{label: 42}",
     694             :                             "var x = 42;",
     695             :                             "function foo(x, y) { return x + y; }",
     696             :                             "%ArgleBargle(glop);",
     697             :                             "var x = new new Function('this.x = 42');",
     698             :                             "var f = (x, y) => x + y;",
     699           5 :                             nullptr};
     700             : 
     701           5 :   uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
     702          35 :   for (int i = 0; programs[i]; i++) {
     703          30 :     auto stream = i::ScannerStream::ForTesting(programs[i]);
     704          60 :     i::Scanner scanner(stream.get(), false);
     705          30 :     scanner.Initialize();
     706             : 
     707          60 :     i::Zone zone(i_isolate->allocator(), ZONE_NAME);
     708             :     i::AstValueFactory ast_value_factory(&zone,
     709             :                                          i_isolate->ast_string_constants(),
     710          60 :                                          i_isolate->heap()->HashSeed());
     711             :     i::PendingCompilationErrorHandler pending_error_handler;
     712             :     i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
     713             :                            &pending_error_handler,
     714             :                            i_isolate->counters()->runtime_call_stats(),
     715          30 :                            i_isolate->logger());
     716             :     preparser.set_allow_natives(true);
     717          30 :     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     718          30 :     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     719          30 :     CHECK(!pending_error_handler.has_pending_error());
     720             :   }
     721           5 : }
     722             : 
     723             : 
     724       28342 : TEST(StandAlonePreParserNoNatives) {
     725           5 :   v8::V8::Initialize();
     726             : 
     727          10 :   i::Isolate* isolate = CcTest::i_isolate();
     728             :   CcTest::i_isolate()->stack_guard()->SetStackLimit(
     729          10 :       i::GetCurrentStackPosition() - 128 * 1024);
     730             : 
     731             :   const char* programs[] = {"%ArgleBargle(glop);", "var x = %_IsSmi(42);",
     732           5 :                             nullptr};
     733             : 
     734           5 :   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
     735          15 :   for (int i = 0; programs[i]; i++) {
     736          10 :     auto stream = i::ScannerStream::ForTesting(programs[i]);
     737          20 :     i::Scanner scanner(stream.get(), false);
     738          10 :     scanner.Initialize();
     739             : 
     740             :     // Preparser defaults to disallowing natives syntax.
     741          20 :     i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
     742             :     i::AstValueFactory ast_value_factory(
     743             :         &zone, CcTest::i_isolate()->ast_string_constants(),
     744          20 :         CcTest::i_isolate()->heap()->HashSeed());
     745             :     i::PendingCompilationErrorHandler pending_error_handler;
     746             :     i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
     747             :                            &pending_error_handler,
     748             :                            isolate->counters()->runtime_call_stats(),
     749          10 :                            isolate->logger());
     750          10 :     i::PreParser::PreParseResult result = preparser.PreParseProgram();
     751          10 :     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     752          10 :     CHECK(pending_error_handler.has_pending_error() ||
     753             :           pending_error_handler.has_error_unidentifiable_by_preparser());
     754             :   }
     755           5 : }
     756             : 
     757             : 
     758       28342 : TEST(RegressChromium62639) {
     759           5 :   v8::V8::Initialize();
     760           5 :   i::Isolate* isolate = CcTest::i_isolate();
     761             : 
     762           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
     763           5 :                                         128 * 1024);
     764             : 
     765             :   const char* program = "var x = 'something';\n"
     766             :                         "escape: function() {}";
     767             :   // Fails parsing expecting an identifier after "function".
     768             :   // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
     769             :   // and then used the invalid currently scanned literal. This always
     770             :   // failed in debug mode, and sometimes crashed in release mode.
     771             : 
     772           5 :   auto stream = i::ScannerStream::ForTesting(program);
     773          10 :   i::Scanner scanner(stream.get(), false);
     774           5 :   scanner.Initialize();
     775          10 :   i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
     776             :   i::AstValueFactory ast_value_factory(
     777             :       &zone, CcTest::i_isolate()->ast_string_constants(),
     778          10 :       CcTest::i_isolate()->heap()->HashSeed());
     779             :   i::PendingCompilationErrorHandler pending_error_handler;
     780             :   i::PreParser preparser(
     781             :       &zone, &scanner, CcTest::i_isolate()->stack_guard()->real_climit(),
     782             :       &ast_value_factory, &pending_error_handler,
     783          10 :       isolate->counters()->runtime_call_stats(), isolate->logger());
     784           5 :   i::PreParser::PreParseResult result = preparser.PreParseProgram();
     785             :   // Even in the case of a syntax error, kPreParseSuccess is returned.
     786           5 :   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
     787           5 :   CHECK(pending_error_handler.has_pending_error() ||
     788             :         pending_error_handler.has_error_unidentifiable_by_preparser());
     789           5 : }
     790             : 
     791             : 
     792       28342 : TEST(PreParseOverflow) {
     793           5 :   v8::V8::Initialize();
     794           5 :   i::Isolate* isolate = CcTest::i_isolate();
     795             : 
     796           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
     797           5 :                                         128 * 1024);
     798             : 
     799             :   size_t kProgramSize = 1024 * 1024;
     800           5 :   std::unique_ptr<char[]> program(i::NewArray<char>(kProgramSize + 1));
     801             :   memset(program.get(), '(', kProgramSize);
     802           5 :   program[kProgramSize] = '\0';
     803             : 
     804           5 :   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
     805             : 
     806           5 :   auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize);
     807          10 :   i::Scanner scanner(stream.get(), false);
     808           5 :   scanner.Initialize();
     809             : 
     810          10 :   i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
     811             :   i::AstValueFactory ast_value_factory(
     812             :       &zone, CcTest::i_isolate()->ast_string_constants(),
     813          10 :       CcTest::i_isolate()->heap()->HashSeed());
     814             :   i::PendingCompilationErrorHandler pending_error_handler;
     815             :   i::PreParser preparser(
     816             :       &zone, &scanner, stack_limit, &ast_value_factory, &pending_error_handler,
     817           5 :       isolate->counters()->runtime_call_stats(), isolate->logger());
     818           5 :   i::PreParser::PreParseResult result = preparser.PreParseProgram();
     819           5 :   CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
     820           5 : }
     821             : 
     822          35 : void TestStreamScanner(i::Utf16CharacterStream* stream,
     823             :                        i::Token::Value* expected_tokens,
     824             :                        int skip_pos = 0,  // Zero means not skipping.
     825             :                        int skip_to = 0) {
     826          35 :   i::Scanner scanner(stream, false);
     827          35 :   scanner.Initialize();
     828             : 
     829             :   int i = 0;
     830         190 :   do {
     831         190 :     i::Token::Value expected = expected_tokens[i];
     832         190 :     i::Token::Value actual = scanner.Next();
     833         190 :     CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
     834         190 :     if (scanner.location().end_pos == skip_pos) {
     835          30 :       scanner.SeekForward(skip_to);
     836             :     }
     837         190 :     i++;
     838         225 :   } while (expected_tokens[i] != i::Token::ILLEGAL);
     839          35 : }
     840             : 
     841             : 
     842       28342 : TEST(StreamScanner) {
     843           5 :   v8::V8::Initialize();
     844             :   const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
     845             :   std::unique_ptr<i::Utf16CharacterStream> stream1(
     846           5 :       i::ScannerStream::ForTesting(str1));
     847             :   i::Token::Value expectations1[] = {
     848             :       i::Token::LBRACE,
     849             :       i::Token::IDENTIFIER,
     850             :       i::Token::IDENTIFIER,
     851             :       i::Token::FOR,
     852             :       i::Token::COLON,
     853             :       i::Token::MUL,
     854             :       i::Token::DIV,
     855             :       i::Token::LT,
     856             :       i::Token::SUB,
     857             :       i::Token::IDENTIFIER,
     858             :       i::Token::EOS,
     859             :       i::Token::ILLEGAL
     860           5 :   };
     861           5 :   TestStreamScanner(stream1.get(), expectations1, 0, 0);
     862             : 
     863             :   const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
     864             :   std::unique_ptr<i::Utf16CharacterStream> stream2(
     865           5 :       i::ScannerStream::ForTesting(str2));
     866             :   i::Token::Value expectations2[] = {
     867             :       i::Token::CASE,
     868             :       i::Token::DEFAULT,
     869             :       i::Token::CONST,
     870             :       i::Token::LBRACE,
     871             :       // Skipped part here
     872             :       i::Token::RBRACE,
     873             :       i::Token::DO,
     874             :       i::Token::EOS,
     875             :       i::Token::ILLEGAL
     876           5 :   };
     877             :   CHECK_EQ('{', str2[19]);
     878             :   CHECK_EQ('}', str2[37]);
     879           5 :   TestStreamScanner(stream2.get(), expectations2, 20, 37);
     880             : 
     881             :   const char* str3 = "{}}}}";
     882             :   i::Token::Value expectations3[] = {
     883             :       i::Token::LBRACE,
     884             :       i::Token::RBRACE,
     885             :       i::Token::RBRACE,
     886             :       i::Token::RBRACE,
     887             :       i::Token::RBRACE,
     888             :       i::Token::EOS,
     889             :       i::Token::ILLEGAL
     890           5 :   };
     891             :   // Skip zero-four RBRACEs.
     892          35 :   for (int i = 0; i <= 4; i++) {
     893          25 :      expectations3[6 - i] = i::Token::ILLEGAL;
     894          25 :      expectations3[5 - i] = i::Token::EOS;
     895             :      std::unique_ptr<i::Utf16CharacterStream> stream3(
     896          25 :          i::ScannerStream::ForTesting(str3));
     897          50 :      TestStreamScanner(stream3.get(), expectations3, 1, 1 + i);
     898             :   }
     899           5 : }
     900             : 
     901         110 : void TestScanRegExp(const char* re_source, const char* expected) {
     902         110 :   auto stream = i::ScannerStream::ForTesting(re_source);
     903             :   i::HandleScope scope(CcTest::i_isolate());
     904         220 :   i::Scanner scanner(stream.get(), false);
     905         110 :   scanner.Initialize();
     906             : 
     907             :   i::Token::Value start = scanner.peek();
     908         110 :   CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
     909         110 :   CHECK(scanner.ScanRegExpPattern());
     910         110 :   scanner.Next();  // Current token is now the regexp literal.
     911         220 :   i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
     912             :   i::AstValueFactory ast_value_factory(
     913             :       &zone, CcTest::i_isolate()->ast_string_constants(),
     914         220 :       CcTest::i_isolate()->heap()->HashSeed());
     915         110 :   const i::AstRawString* current_symbol =
     916         110 :       scanner.CurrentSymbol(&ast_value_factory);
     917         110 :   ast_value_factory.Internalize(CcTest::i_isolate());
     918             :   i::Handle<i::String> val = current_symbol->string();
     919             :   i::DisallowHeapAllocation no_alloc;
     920         110 :   i::String::FlatContent content = val->GetFlatContent(no_alloc);
     921         110 :   CHECK(content.IsOneByte());
     922         110 :   i::Vector<const uint8_t> actual = content.ToOneByteVector();
     923         510 :   for (int i = 0; i < actual.length(); i++) {
     924         400 :     CHECK_NE('\0', expected[i]);
     925         800 :     CHECK_EQ(expected[i], actual[i]);
     926             :   }
     927         110 : }
     928             : 
     929             : 
     930       28342 : TEST(RegExpScanning) {
     931           5 :   v8::V8::Initialize();
     932             : 
     933             :   // RegExp token with added garbage at the end. The scanner should only
     934             :   // scan the RegExp until the terminating slash just before "flipperwald".
     935           5 :   TestScanRegExp("/b/flipperwald", "b");
     936             :   // Incomplete escape sequences doesn't hide the terminating slash.
     937           5 :   TestScanRegExp("/\\x/flipperwald", "\\x");
     938           5 :   TestScanRegExp("/\\u/flipperwald", "\\u");
     939           5 :   TestScanRegExp("/\\u1/flipperwald", "\\u1");
     940           5 :   TestScanRegExp("/\\u12/flipperwald", "\\u12");
     941           5 :   TestScanRegExp("/\\u123/flipperwald", "\\u123");
     942           5 :   TestScanRegExp("/\\c/flipperwald", "\\c");
     943           5 :   TestScanRegExp("/\\c//flipperwald", "\\c");
     944             :   // Slashes inside character classes are not terminating.
     945           5 :   TestScanRegExp("/[/]/flipperwald", "[/]");
     946           5 :   TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
     947             :   // Incomplete escape sequences inside a character class doesn't hide
     948             :   // the end of the character class.
     949           5 :   TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
     950           5 :   TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
     951           5 :   TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
     952           5 :   TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
     953           5 :   TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
     954           5 :   TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
     955           5 :   TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
     956           5 :   TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
     957             :   // Escaped ']'s wont end the character class.
     958           5 :   TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
     959             :   // Escaped slashes are not terminating.
     960           5 :   TestScanRegExp("/\\//flipperwald", "\\/");
     961             :   // Starting with '=' works too.
     962           5 :   TestScanRegExp("/=/", "=");
     963           5 :   TestScanRegExp("/=?/", "=?");
     964           5 : }
     965             : 
     966       28342 : TEST(ScopeUsesArgumentsSuperThis) {
     967             :   static const struct {
     968             :     const char* prefix;
     969             :     const char* suffix;
     970             :   } surroundings[] = {
     971             :     { "function f() {", "}" },
     972             :     { "var f = () => {", "};" },
     973             :     { "class C { constructor() {", "} }" },
     974             :   };
     975             : 
     976             :   enum Expected {
     977             :     NONE = 0,
     978             :     ARGUMENTS = 1,
     979             :     SUPER_PROPERTY = 1 << 1,
     980             :     THIS = 1 << 2,
     981             :     EVAL = 1 << 4
     982             :   };
     983             : 
     984             :   // clang-format off
     985             :   static const struct {
     986             :     const char* body;
     987             :     int expected;
     988             :   } source_data[] = {
     989             :     {"", NONE},
     990             :     {"return this", THIS},
     991             :     {"return arguments", ARGUMENTS},
     992             :     {"return super.x", SUPER_PROPERTY},
     993             :     {"return arguments[0]", ARGUMENTS},
     994             :     {"return this + arguments[0]", ARGUMENTS | THIS},
     995             :     {"return this + arguments[0] + super.x",
     996             :      ARGUMENTS | SUPER_PROPERTY | THIS},
     997             :     {"return x => this + x", THIS},
     998             :     {"return x => super.f() + x", SUPER_PROPERTY},
     999             :     {"this.foo = 42;", THIS},
    1000             :     {"this.foo();", THIS},
    1001             :     {"if (foo()) { this.f() }", THIS},
    1002             :     {"if (foo()) { super.f() }", SUPER_PROPERTY},
    1003             :     {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
    1004             :     {"while (true) { this.f() }", THIS},
    1005             :     {"while (true) { super.f() }", SUPER_PROPERTY},
    1006             :     {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
    1007             :     // Multiple nesting levels must work as well.
    1008             :     {"while (true) { while (true) { while (true) return this } }", THIS},
    1009             :     {"while (true) { while (true) { while (true) return super.f() } }",
    1010             :      SUPER_PROPERTY},
    1011             :     {"if (1) { return () => { while (true) new this() } }", THIS},
    1012             :     {"return function (x) { return this + x }", NONE},
    1013             :     {"return { m(x) { return super.m() + x } }", NONE},
    1014             :     {"var x = function () { this.foo = 42 };", NONE},
    1015             :     {"var x = { m() { super.foo = 42 } };", NONE},
    1016             :     {"if (1) { return function () { while (true) new this() } }", NONE},
    1017             :     {"if (1) { return { m() { while (true) super.m() } } }", NONE},
    1018             :     {"return function (x) { return () => this }", NONE},
    1019             :     {"return { m(x) { return () => super.m() } }", NONE},
    1020             :     // Flags must be correctly set when using block scoping.
    1021             :     {"\"use strict\"; while (true) { let x; this, arguments; }",
    1022             :      THIS},
    1023             :     {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
    1024             :      SUPER_PROPERTY | THIS},
    1025             :     {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
    1026             :     {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
    1027             :     {"\"use strict\"; if (1) {"
    1028             :      "  let x; return { m() { return this + super.m() + arguments } }"
    1029             :      "}",
    1030             :      NONE},
    1031             :     {"eval(42)", EVAL},
    1032             :     {"if (1) { eval(42) }", EVAL},
    1033             :     {"eval('super.x')", EVAL},
    1034             :     {"eval('this.x')", EVAL},
    1035             :     {"eval('arguments')", EVAL},
    1036             :   };
    1037             :   // clang-format on
    1038             : 
    1039             :   i::Isolate* isolate = CcTest::i_isolate();
    1040             :   i::Factory* factory = isolate->factory();
    1041             : 
    1042           5 :   v8::HandleScope handles(CcTest::isolate());
    1043           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1044             :   v8::Context::Scope context_scope(context);
    1045             : 
    1046           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    1047           5 :                                         128 * 1024);
    1048             : 
    1049          20 :   for (unsigned j = 0; j < arraysize(surroundings); ++j) {
    1050         570 :     for (unsigned i = 0; i < arraysize(source_data); ++i) {
    1051             :       // Super property is only allowed in constructor and method.
    1052         570 :       if (((source_data[i].expected & SUPER_PROPERTY) ||
    1053         270 :            (source_data[i].expected == NONE)) && j != 2) {
    1054         180 :         continue;
    1055             :       }
    1056         780 :       int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
    1057         390 :                              i::StrLength(surroundings[j].suffix) +
    1058         780 :                              i::StrLength(source_data[i].body);
    1059         390 :       i::ScopedVector<char> program(kProgramByteSize + 1);
    1060             :       i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
    1061         390 :                   source_data[i].body, surroundings[j].suffix);
    1062             :       i::Handle<i::String> source =
    1063             :           factory->NewStringFromUtf8(i::CStrVector(program.start()))
    1064         780 :               .ToHandleChecked();
    1065         390 :       i::Handle<i::Script> script = factory->NewScript(source);
    1066         780 :       i::ParseInfo info(isolate, script);
    1067             :       // The information we're checking is only produced when eager parsing.
    1068             :       info.set_allow_lazy_parsing(false);
    1069         390 :       CHECK(i::parsing::ParseProgram(&info, isolate));
    1070         390 :       CHECK(i::Rewriter::Rewrite(&info));
    1071         390 :       info.ast_value_factory()->Internalize(isolate);
    1072         390 :       CHECK(i::DeclarationScope::Analyze(&info));
    1073         390 :       i::DeclarationScope::AllocateScopeInfos(&info, isolate);
    1074         390 :       CHECK_NOT_NULL(info.literal());
    1075             : 
    1076         390 :       i::DeclarationScope* script_scope = info.literal()->scope();
    1077         390 :       CHECK(script_scope->is_script_scope());
    1078             : 
    1079         190 :       i::Scope* scope = script_scope->inner_scope();
    1080             :       DCHECK_NOT_NULL(scope);
    1081             :       DCHECK_NULL(scope->sibling());
    1082             :       // Adjust for constructor scope.
    1083         390 :       if (j == 2) {
    1084             :         scope = scope->inner_scope();
    1085             :         DCHECK_NOT_NULL(scope);
    1086             :         DCHECK_NULL(scope->sibling());
    1087             :       }
    1088             :       // Arrows themselves never get an arguments object.
    1089         470 :       if ((source_data[i].expected & ARGUMENTS) != 0 &&
    1090          80 :           !scope->AsDeclarationScope()->is_arrow_scope()) {
    1091          55 :         CHECK_NOT_NULL(scope->AsDeclarationScope()->arguments());
    1092             :       }
    1093         780 :       if (IsClassConstructor(scope->AsDeclarationScope()->function_kind())) {
    1094         190 :         CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0 ||
    1095             :                      (source_data[i].expected & EVAL) != 0,
    1096             :                  scope->AsDeclarationScope()->NeedsHomeObject());
    1097             :       } else {
    1098         200 :         CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
    1099             :                  scope->AsDeclarationScope()->NeedsHomeObject());
    1100             :       }
    1101         390 :       if ((source_data[i].expected & THIS) != 0) {
    1102             :         // Currently the is_used() flag is conservative; all variables in a
    1103             :         // script scope are marked as used.
    1104         615 :         CHECK(scope->LookupForTesting(info.ast_value_factory()->this_string())
    1105             :                   ->is_used());
    1106             :       }
    1107         390 :       if (is_sloppy(scope->language_mode())) {
    1108         360 :         CHECK_EQ((source_data[i].expected & EVAL) != 0,
    1109             :                  scope->AsDeclarationScope()->calls_sloppy_eval());
    1110             :       }
    1111             :     }
    1112           5 :   }
    1113           5 : }
    1114             : 
    1115          75 : static void CheckParsesToNumber(const char* source) {
    1116          75 :   v8::V8::Initialize();
    1117          75 :   HandleAndZoneScope handles;
    1118             : 
    1119             :   i::Isolate* isolate = CcTest::i_isolate();
    1120             :   i::Factory* factory = isolate->factory();
    1121             : 
    1122          75 :   std::string full_source = "function f() { return ";
    1123             :   full_source += source;
    1124             :   full_source += "; }";
    1125             : 
    1126             :   i::Handle<i::String> source_code =
    1127             :       factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
    1128         150 :           .ToHandleChecked();
    1129             : 
    1130          75 :   i::Handle<i::Script> script = factory->NewScript(source_code);
    1131             : 
    1132         150 :   i::ParseInfo info(isolate, script);
    1133             :   info.set_allow_lazy_parsing(false);
    1134             :   info.set_toplevel(true);
    1135             : 
    1136          75 :   CHECK(i::parsing::ParseProgram(&info, isolate));
    1137             : 
    1138         150 :   CHECK_EQ(1, info.scope()->declarations()->LengthForTest());
    1139          75 :   i::Declaration* decl = info.scope()->declarations()->AtForTest(0);
    1140         150 :   i::FunctionLiteral* fun = decl->AsFunctionDeclaration()->fun();
    1141          75 :   CHECK_EQ(fun->body()->length(), 1);
    1142         150 :   CHECK(fun->body()->at(0)->IsReturnStatement());
    1143         150 :   i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
    1144          75 :   i::Literal* lit = ret->expression()->AsLiteral();
    1145         150 :   CHECK(lit->IsNumberLiteral());
    1146          75 : }
    1147             : 
    1148             : 
    1149       28342 : TEST(ParseNumbers) {
    1150           5 :   CheckParsesToNumber("1.");
    1151           5 :   CheckParsesToNumber("1.34");
    1152           5 :   CheckParsesToNumber("134");
    1153           5 :   CheckParsesToNumber("134e44");
    1154           5 :   CheckParsesToNumber("134.e44");
    1155           5 :   CheckParsesToNumber("134.44e44");
    1156           5 :   CheckParsesToNumber(".44");
    1157             : 
    1158           5 :   CheckParsesToNumber("-1.");
    1159           5 :   CheckParsesToNumber("-1.0");
    1160           5 :   CheckParsesToNumber("-1.34");
    1161           5 :   CheckParsesToNumber("-134");
    1162           5 :   CheckParsesToNumber("-134e44");
    1163           5 :   CheckParsesToNumber("-134.e44");
    1164           5 :   CheckParsesToNumber("-134.44e44");
    1165           5 :   CheckParsesToNumber("-.44");
    1166           5 : }
    1167             : 
    1168             : 
    1169       28342 : TEST(ScopePositions) {
    1170             :   // Test the parser for correctly setting the start and end positions
    1171             :   // of a scope. We check the scope positions of exactly one scope
    1172             :   // nested in the global scope of a program. 'inner source' is the
    1173             :   // source code that determines the part of the source belonging
    1174             :   // to the nested scope. 'outer_prefix' and 'outer_suffix' are
    1175             :   // parts of the source that belong to the global scope.
    1176             :   struct SourceData {
    1177             :     const char* outer_prefix;
    1178             :     const char* inner_source;
    1179             :     const char* outer_suffix;
    1180             :     i::ScopeType scope_type;
    1181             :     i::LanguageMode language_mode;
    1182             :   };
    1183             : 
    1184             :   const SourceData source_data[] = {
    1185             :       {"  with ({}) ", "{ block; }", " more;", i::WITH_SCOPE,
    1186             :        i::LanguageMode::kSloppy},
    1187             :       {"  with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE,
    1188             :        i::LanguageMode::kSloppy},
    1189             :       {"  with ({}) ",
    1190             :        "{\n"
    1191             :        "    block;\n"
    1192             :        "  }",
    1193             :        "\n"
    1194             :        "  more;",
    1195             :        i::WITH_SCOPE, i::LanguageMode::kSloppy},
    1196             :       {"  with ({}) ", "statement;", " more;", i::WITH_SCOPE,
    1197             :        i::LanguageMode::kSloppy},
    1198             :       {"  with ({}) ", "statement",
    1199             :        "\n"
    1200             :        "  more;",
    1201             :        i::WITH_SCOPE, i::LanguageMode::kSloppy},
    1202             :       {"  with ({})\n"
    1203             :        "    ",
    1204             :        "statement;",
    1205             :        "\n"
    1206             :        "  more;",
    1207             :        i::WITH_SCOPE, i::LanguageMode::kSloppy},
    1208             :       {"  try {} catch ", "(e) { block; }", " more;", i::CATCH_SCOPE,
    1209             :        i::LanguageMode::kSloppy},
    1210             :       {"  try {} catch ", "(e) { block; }", "; more;", i::CATCH_SCOPE,
    1211             :        i::LanguageMode::kSloppy},
    1212             :       {"  try {} catch ",
    1213             :        "(e) {\n"
    1214             :        "    block;\n"
    1215             :        "  }",
    1216             :        "\n"
    1217             :        "  more;",
    1218             :        i::CATCH_SCOPE, i::LanguageMode::kSloppy},
    1219             :       {"  try {} catch ", "(e) { block; }", " finally { block; } more;",
    1220             :        i::CATCH_SCOPE, i::LanguageMode::kSloppy},
    1221             :       {"  start;\n"
    1222             :        "  ",
    1223             :        "{ let block; }", " more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1224             :       {"  start;\n"
    1225             :        "  ",
    1226             :        "{ let block; }", "; more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1227             :       {"  start;\n"
    1228             :        "  ",
    1229             :        "{\n"
    1230             :        "    let block;\n"
    1231             :        "  }",
    1232             :        "\n"
    1233             :        "  more;",
    1234             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1235             :       {"  start;\n"
    1236             :        "  function fun",
    1237             :        "(a,b) { infunction; }", " more;", i::FUNCTION_SCOPE,
    1238             :        i::LanguageMode::kSloppy},
    1239             :       {"  start;\n"
    1240             :        "  function fun",
    1241             :        "(a,b) {\n"
    1242             :        "    infunction;\n"
    1243             :        "  }",
    1244             :        "\n"
    1245             :        "  more;",
    1246             :        i::FUNCTION_SCOPE, i::LanguageMode::kSloppy},
    1247             :       {"  start;\n", "(a,b) => a + b", "; more;", i::FUNCTION_SCOPE,
    1248             :        i::LanguageMode::kSloppy},
    1249             :       {"  start;\n", "(a,b) => { return a+b; }", "\nmore;", i::FUNCTION_SCOPE,
    1250             :        i::LanguageMode::kSloppy},
    1251             :       {"  start;\n"
    1252             :        "  (function fun",
    1253             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1254             :        i::LanguageMode::kSloppy},
    1255             :       {"  for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
    1256             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1257             :       {"  for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
    1258             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1259             :       {"  for ",
    1260             :        "(let x = 1 ; x < 10; ++ x) {\n"
    1261             :        "    block;\n"
    1262             :        "  }",
    1263             :        "\n"
    1264             :        "  more;",
    1265             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1266             :       {"  for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
    1267             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1268             :       {"  for ", "(let x = 1 ; x < 10; ++ x) statement",
    1269             :        "\n"
    1270             :        "  more;",
    1271             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1272             :       {"  for ",
    1273             :        "(let x = 1 ; x < 10; ++ x)\n"
    1274             :        "    statement;",
    1275             :        "\n"
    1276             :        "  more;",
    1277             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1278             :       {"  for ", "(let x in {}) { block; }", " more;", i::BLOCK_SCOPE,
    1279             :        i::LanguageMode::kStrict},
    1280             :       {"  for ", "(let x in {}) { block; }", "; more;", i::BLOCK_SCOPE,
    1281             :        i::LanguageMode::kStrict},
    1282             :       {"  for ",
    1283             :        "(let x in {}) {\n"
    1284             :        "    block;\n"
    1285             :        "  }",
    1286             :        "\n"
    1287             :        "  more;",
    1288             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1289             :       {"  for ", "(let x in {}) statement;", " more;", i::BLOCK_SCOPE,
    1290             :        i::LanguageMode::kStrict},
    1291             :       {"  for ", "(let x in {}) statement",
    1292             :        "\n"
    1293             :        "  more;",
    1294             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1295             :       {"  for ",
    1296             :        "(let x in {})\n"
    1297             :        "    statement;",
    1298             :        "\n"
    1299             :        "  more;",
    1300             :        i::BLOCK_SCOPE, i::LanguageMode::kStrict},
    1301             :       // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
    1302             :       // the preparser off in terms of byte offsets.
    1303             :       // 2 surrogates, encode a character that doesn't need a surrogate.
    1304             :       {"  'foo\xED\xA0\x81\xED\xB0\x89';\n"
    1305             :        "  (function fun",
    1306             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1307             :        i::LanguageMode::kSloppy},
    1308             :       // 4-byte encoding.
    1309             :       {"  'foo\xF0\x90\x90\x8A';\n"
    1310             :        "  (function fun",
    1311             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1312             :        i::LanguageMode::kSloppy},
    1313             :       // 3-byte encoding of \u0FFF.
    1314             :       {"  'foo\xE0\xBF\xBF';\n"
    1315             :        "  (function fun",
    1316             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1317             :        i::LanguageMode::kSloppy},
    1318             :       // 3-byte surrogate, followed by broken 2-byte surrogate w/ impossible 2nd
    1319             :       // byte and last byte missing.
    1320             :       {"  'foo\xED\xA0\x81\xED\x89';\n"
    1321             :        "  (function fun",
    1322             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1323             :        i::LanguageMode::kSloppy},
    1324             :       // Broken 3-byte encoding of \u0FFF with missing last byte.
    1325             :       {"  'foo\xE0\xBF';\n"
    1326             :        "  (function fun",
    1327             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1328             :        i::LanguageMode::kSloppy},
    1329             :       // Broken 3-byte encoding of \u0FFF with missing 2 last bytes.
    1330             :       {"  'foo\xE0';\n"
    1331             :        "  (function fun",
    1332             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1333             :        i::LanguageMode::kSloppy},
    1334             :       // Broken 3-byte encoding of \u00FF should be a 2-byte encoding.
    1335             :       {"  'foo\xE0\x83\xBF';\n"
    1336             :        "  (function fun",
    1337             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1338             :        i::LanguageMode::kSloppy},
    1339             :       // Broken 3-byte encoding of \u007F should be a 2-byte encoding.
    1340             :       {"  'foo\xE0\x81\xBF';\n"
    1341             :        "  (function fun",
    1342             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1343             :        i::LanguageMode::kSloppy},
    1344             :       // Unpaired lead surrogate.
    1345             :       {"  'foo\xED\xA0\x81';\n"
    1346             :        "  (function fun",
    1347             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1348             :        i::LanguageMode::kSloppy},
    1349             :       // Unpaired lead surrogate where the following code point is a 3-byte
    1350             :       // sequence.
    1351             :       {"  'foo\xED\xA0\x81\xE0\xBF\xBF';\n"
    1352             :        "  (function fun",
    1353             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1354             :        i::LanguageMode::kSloppy},
    1355             :       // Unpaired lead surrogate where the following code point is a 4-byte
    1356             :       // encoding of a trail surrogate.
    1357             :       {"  'foo\xED\xA0\x81\xF0\x8D\xB0\x89';\n"
    1358             :        "  (function fun",
    1359             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1360             :        i::LanguageMode::kSloppy},
    1361             :       // Unpaired trail surrogate.
    1362             :       {"  'foo\xED\xB0\x89';\n"
    1363             :        "  (function fun",
    1364             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1365             :        i::LanguageMode::kSloppy},
    1366             :       // 2-byte encoding of \u00FF.
    1367             :       {"  'foo\xC3\xBF';\n"
    1368             :        "  (function fun",
    1369             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1370             :        i::LanguageMode::kSloppy},
    1371             :       // Broken 2-byte encoding of \u00FF with missing last byte.
    1372             :       {"  'foo\xC3';\n"
    1373             :        "  (function fun",
    1374             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1375             :        i::LanguageMode::kSloppy},
    1376             :       // Broken 2-byte encoding of \u007F should be a 1-byte encoding.
    1377             :       {"  'foo\xC1\xBF';\n"
    1378             :        "  (function fun",
    1379             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1380             :        i::LanguageMode::kSloppy},
    1381             :       // Illegal 5-byte encoding.
    1382             :       {"  'foo\xF8\xBF\xBF\xBF\xBF';\n"
    1383             :        "  (function fun",
    1384             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1385             :        i::LanguageMode::kSloppy},
    1386             :       // Illegal 6-byte encoding.
    1387             :       {"  'foo\xFC\xBF\xBF\xBF\xBF\xBF';\n"
    1388             :        "  (function fun",
    1389             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1390             :        i::LanguageMode::kSloppy},
    1391             :       // Illegal 0xFE byte
    1392             :       {"  'foo\xFE\xBF\xBF\xBF\xBF\xBF\xBF';\n"
    1393             :        "  (function fun",
    1394             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1395             :        i::LanguageMode::kSloppy},
    1396             :       // Illegal 0xFF byte
    1397             :       {"  'foo\xFF\xBF\xBF\xBF\xBF\xBF\xBF\xBF';\n"
    1398             :        "  (function fun",
    1399             :        "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
    1400             :        i::LanguageMode::kSloppy},
    1401             :       {"  'foo';\n"
    1402             :        "  (function fun",
    1403             :        "(a,b) { 'bar\xED\xA0\x81\xED\xB0\x8B'; }", ")();", i::FUNCTION_SCOPE,
    1404             :        i::LanguageMode::kSloppy},
    1405             :       {"  'foo';\n"
    1406             :        "  (function fun",
    1407             :        "(a,b) { 'bar\xF0\x90\x90\x8C'; }", ")();", i::FUNCTION_SCOPE,
    1408             :        i::LanguageMode::kSloppy},
    1409           5 :       {nullptr, nullptr, nullptr, i::EVAL_SCOPE, i::LanguageMode::kSloppy}};
    1410             : 
    1411             :   i::Isolate* isolate = CcTest::i_isolate();
    1412             :   i::Factory* factory = isolate->factory();
    1413             : 
    1414           5 :   v8::HandleScope handles(CcTest::isolate());
    1415           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1416             :   v8::Context::Scope context_scope(context);
    1417             : 
    1418           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    1419           5 :                                         128 * 1024);
    1420             : 
    1421         260 :   for (int i = 0; source_data[i].outer_prefix; i++) {
    1422         255 :     int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
    1423         255 :     int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
    1424         255 :     int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
    1425             :     int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
    1426             :     int kInnerByteLen = i::StrLength(source_data[i].inner_source);
    1427             :     int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
    1428         255 :     int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
    1429         255 :     int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
    1430         255 :     i::ScopedVector<char> program(kProgramByteSize + 1);
    1431             :     i::SNPrintF(program, "%s%s%s",
    1432             :                          source_data[i].outer_prefix,
    1433             :                          source_data[i].inner_source,
    1434         255 :                          source_data[i].outer_suffix);
    1435             : 
    1436             :     // Parse program source.
    1437             :     i::Handle<i::String> source = factory->NewStringFromUtf8(
    1438         510 :         i::CStrVector(program.start())).ToHandleChecked();
    1439         255 :     CHECK_EQ(source->length(), kProgramSize);
    1440         255 :     i::Handle<i::Script> script = factory->NewScript(source);
    1441         510 :     i::ParseInfo info(isolate, script);
    1442         255 :     info.set_language_mode(source_data[i].language_mode);
    1443         255 :     i::parsing::ParseProgram(&info, isolate);
    1444         255 :     CHECK_NOT_NULL(info.literal());
    1445             : 
    1446             :     // Check scope types and positions.
    1447        1020 :     i::Scope* scope = info.literal()->scope();
    1448         255 :     CHECK(scope->is_script_scope());
    1449         255 :     CHECK_EQ(0, scope->start_position());
    1450         255 :     CHECK_EQ(scope->end_position(), kProgramSize);
    1451             : 
    1452         765 :     i::Scope* inner_scope = scope->inner_scope();
    1453             :     DCHECK_NOT_NULL(inner_scope);
    1454             :     DCHECK_NULL(inner_scope->sibling());
    1455         510 :     CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
    1456         255 :     CHECK_EQ(inner_scope->start_position(), kPrefixLen);
    1457             :     // The end position of a token is one position after the last
    1458             :     // character belonging to that token.
    1459         255 :     CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
    1460           5 :   }
    1461           5 : }
    1462             : 
    1463             : 
    1464       28342 : TEST(DiscardFunctionBody) {
    1465             :   // Test that inner function bodies are discarded if possible.
    1466             :   // See comments in ParseFunctionLiteral in parser.cc.
    1467             :   const char* discard_sources[] = {
    1468             :       "(function f() { function g() { var a; } })();",
    1469             :       "(function f() { function g() { { function h() { } } } })();",
    1470             :       /* TODO(conradw): In future it may be possible to apply this optimisation
    1471             :        * to these productions.
    1472             :       "(function f() { 0, function g() { var a; } })();",
    1473             :       "(function f() { 0, { g() { var a; } } })();",
    1474             :       "(function f() { 0, class c { g() { var a; } } })();", */
    1475           5 :       nullptr};
    1476             : 
    1477             :   i::Isolate* isolate = CcTest::i_isolate();
    1478             :   i::Factory* factory = isolate->factory();
    1479           5 :   v8::HandleScope handles(CcTest::isolate());
    1480             :   i::FunctionLiteral* function;
    1481             : 
    1482          15 :   for (int i = 0; discard_sources[i]; i++) {
    1483             :     const char* source = discard_sources[i];
    1484             :     i::Handle<i::String> source_code =
    1485          20 :         factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
    1486          10 :     i::Handle<i::Script> script = factory->NewScript(source_code);
    1487          10 :     i::ParseInfo info(isolate, script);
    1488          10 :     i::parsing::ParseProgram(&info, isolate);
    1489          10 :     function = info.literal();
    1490          10 :     CHECK_NOT_NULL(function);
    1491          10 :     CHECK_EQ(1, function->body()->length());
    1492          10 :     i::FunctionLiteral* inner =
    1493          20 :         function->body()->first()->AsExpressionStatement()->expression()->
    1494          20 :         AsCall()->expression()->AsFunctionLiteral();
    1495             :     i::Scope* inner_scope = inner->scope();
    1496             :     i::FunctionLiteral* fun = nullptr;
    1497          10 :     if (!inner_scope->declarations()->is_empty()) {
    1498             :       fun = inner_scope->declarations()
    1499             :                 ->AtForTest(0)
    1500             :                 ->AsFunctionDeclaration()
    1501          20 :                 ->fun();
    1502             :     } else {
    1503             :       // TODO(conradw): This path won't be hit until the other test cases can be
    1504             :       // uncommented.
    1505           0 :       UNREACHABLE();
    1506             :       CHECK(inner->ShouldEagerCompile());
    1507             :       CHECK_GE(2, inner->body()->length());
    1508             :       i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
    1509             :                            expression()->AsBinaryOperation()->right();
    1510             :       if (exp->IsFunctionLiteral()) {
    1511             :         fun = exp->AsFunctionLiteral();
    1512             :       } else if (exp->IsObjectLiteral()) {
    1513             :         fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
    1514             :               AsFunctionLiteral();
    1515             :       } else {
    1516             :         fun = exp->AsClassLiteral()->properties()->at(0)->value()->
    1517             :               AsFunctionLiteral();
    1518             :       }
    1519             :     }
    1520          10 :     CHECK(!fun->ShouldEagerCompile());
    1521          15 :   }
    1522           5 : }
    1523             : 
    1524             : 
    1525           0 : const char* ReadString(unsigned* start) {
    1526           0 :   int length = start[0];
    1527           0 :   char* result = i::NewArray<char>(length + 1);
    1528           0 :   for (int i = 0; i < length; i++) {
    1529           0 :     result[i] = start[i + 1];
    1530             :   }
    1531           0 :   result[length] = '\0';
    1532           0 :   return result;
    1533             : }
    1534             : 
    1535             : enum ParserFlag {
    1536             :   kAllowLazy,
    1537             :   kAllowNatives,
    1538             :   kAllowHarmonyPublicFields,
    1539             :   kAllowHarmonyPrivateFields,
    1540             :   kAllowHarmonyPrivateMethods,
    1541             :   kAllowHarmonyStaticFields,
    1542             :   kAllowHarmonyDynamicImport,
    1543             :   kAllowHarmonyImportMeta,
    1544             :   kAllowHarmonyNumericSeparator
    1545             : };
    1546             : 
    1547             : enum ParserSyncTestResult {
    1548             :   kSuccessOrError,
    1549             :   kSuccess,
    1550             :   kError
    1551             : };
    1552             : 
    1553      510389 : void SetGlobalFlags(base::EnumSet<ParserFlag> flags) {
    1554      510389 :   i::FLAG_allow_natives_syntax = flags.contains(kAllowNatives);
    1555      510389 :   i::FLAG_harmony_public_fields = flags.contains(kAllowHarmonyPublicFields);
    1556      510389 :   i::FLAG_harmony_private_fields = flags.contains(kAllowHarmonyPrivateFields);
    1557      510389 :   i::FLAG_harmony_private_methods = flags.contains(kAllowHarmonyPrivateMethods);
    1558      510389 :   i::FLAG_harmony_static_fields = flags.contains(kAllowHarmonyStaticFields);
    1559      510389 :   i::FLAG_harmony_dynamic_import = flags.contains(kAllowHarmonyDynamicImport);
    1560      510389 :   i::FLAG_harmony_import_meta = flags.contains(kAllowHarmonyImportMeta);
    1561             :   i::FLAG_harmony_numeric_separator =
    1562      510389 :       flags.contains(kAllowHarmonyNumericSeparator);
    1563      510389 : }
    1564             : 
    1565      509409 : void SetParserFlags(i::PreParser* parser, base::EnumSet<ParserFlag> flags) {
    1566             :   parser->set_allow_natives(flags.contains(kAllowNatives));
    1567             :   parser->set_allow_harmony_public_fields(
    1568             :       flags.contains(kAllowHarmonyPublicFields));
    1569             :   parser->set_allow_harmony_private_fields(
    1570             :       flags.contains(kAllowHarmonyPrivateFields));
    1571             :   parser->set_allow_harmony_private_methods(
    1572             :       flags.contains(kAllowHarmonyPrivateMethods));
    1573             :   parser->set_allow_harmony_static_fields(
    1574             :       flags.contains(kAllowHarmonyStaticFields));
    1575             :   parser->set_allow_harmony_dynamic_import(
    1576             :       flags.contains(kAllowHarmonyDynamicImport));
    1577             :   parser->set_allow_harmony_import_meta(
    1578             :       flags.contains(kAllowHarmonyImportMeta));
    1579             :   parser->set_allow_harmony_numeric_separator(
    1580             :       flags.contains(kAllowHarmonyNumericSeparator));
    1581      509409 : }
    1582             : 
    1583      510389 : void TestParserSyncWithFlags(i::Handle<i::String> source,
    1584             :                              base::EnumSet<ParserFlag> flags,
    1585             :                              ParserSyncTestResult result,
    1586             :                              bool is_module = false, bool test_preparser = true,
    1587             :                              bool ignore_error_msg = false) {
    1588      509409 :   i::Isolate* isolate = CcTest::i_isolate();
    1589             :   i::Factory* factory = isolate->factory();
    1590             : 
    1591      510389 :   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
    1592             : 
    1593             :   // Preparse the data.
    1594             :   i::PendingCompilationErrorHandler pending_error_handler;
    1595      510389 :   if (test_preparser) {
    1596             :     std::unique_ptr<i::Utf16CharacterStream> stream(
    1597      509409 :         i::ScannerStream::For(isolate, source));
    1598     1018818 :     i::Scanner scanner(stream.get(), is_module);
    1599     1018818 :     i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
    1600             :     i::AstValueFactory ast_value_factory(
    1601             :         &zone, CcTest::i_isolate()->ast_string_constants(),
    1602     1018818 :         CcTest::i_isolate()->heap()->HashSeed());
    1603             :     i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
    1604             :                            &pending_error_handler,
    1605             :                            isolate->counters()->runtime_call_stats(),
    1606      509409 :                            isolate->logger(), -1, is_module);
    1607      509409 :     SetParserFlags(&preparser, flags);
    1608      509409 :     scanner.Initialize();
    1609      509409 :     i::PreParser::PreParseResult result = preparser.PreParseProgram();
    1610      509409 :     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    1611             :   }
    1612             : 
    1613             :   // Parse the data
    1614             :   i::FunctionLiteral* function;
    1615             :   {
    1616      510389 :     SetGlobalFlags(flags);
    1617      510389 :     i::Handle<i::Script> script = factory->NewScript(source);
    1618      510389 :     i::ParseInfo info(isolate, script);
    1619             :     info.set_allow_lazy_parsing(flags.contains(kAllowLazy));
    1620      510389 :     if (is_module) info.set_module();
    1621      510389 :     i::parsing::ParseProgram(&info, isolate);
    1622      510389 :     function = info.literal();
    1623             :   }
    1624             : 
    1625             :   // Check that preparsing fails iff parsing fails.
    1626      510389 :   if (function == nullptr) {
    1627             :     // Extract exception from the parser.
    1628      262030 :     CHECK(isolate->has_pending_exception());
    1629             :     i::Handle<i::JSObject> exception_handle(
    1630             :         i::JSObject::cast(isolate->pending_exception()), isolate);
    1631             :     i::Handle<i::String> message_string = i::Handle<i::String>::cast(
    1632      262030 :         i::JSReceiver::GetProperty(isolate, exception_handle, "message")
    1633      524060 :             .ToHandleChecked());
    1634      262030 :     isolate->clear_pending_exception();
    1635             : 
    1636      262030 :     if (result == kSuccess) {
    1637           0 :       FATAL(
    1638             :           "Parser failed on:\n"
    1639             :           "\t%s\n"
    1640             :           "with error:\n"
    1641             :           "\t%s\n"
    1642             :           "However, we expected no error.",
    1643           0 :           source->ToCString().get(), message_string->ToCString().get());
    1644             :     }
    1645             : 
    1646      262030 :     if (test_preparser && !pending_error_handler.has_pending_error() &&
    1647           0 :         !pending_error_handler.has_error_unidentifiable_by_preparser()) {
    1648           0 :       FATAL(
    1649             :           "Parser failed on:\n"
    1650             :           "\t%s\n"
    1651             :           "with error:\n"
    1652             :           "\t%s\n"
    1653             :           "However, the preparser succeeded",
    1654           0 :           source->ToCString().get(), message_string->ToCString().get());
    1655             :     }
    1656             :     // Check that preparser and parser produce the same error, except for cases
    1657             :     // where we do not track errors in the preparser.
    1658      511820 :     if (test_preparser && !ignore_error_msg &&
    1659      249790 :         !pending_error_handler.has_error_unidentifiable_by_preparser()) {
    1660             :       i::Handle<i::String> preparser_message =
    1661        2502 :           pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate());
    1662        2502 :       if (!i::String::Equals(isolate, message_string, preparser_message)) {
    1663           0 :         FATAL(
    1664             :             "Expected parser and preparser to produce the same error on:\n"
    1665             :             "\t%s\n"
    1666             :             "However, found the following error messages\n"
    1667             :             "\tparser:    %s\n"
    1668             :             "\tpreparser: %s\n",
    1669             :             source->ToCString().get(), message_string->ToCString().get(),
    1670           0 :             preparser_message->ToCString().get());
    1671             :       }
    1672             :     }
    1673      248359 :   } else if (test_preparser && pending_error_handler.has_pending_error()) {
    1674           0 :     FATAL(
    1675             :         "Preparser failed on:\n"
    1676             :         "\t%s\n"
    1677             :         "with error:\n"
    1678             :         "\t%s\n"
    1679             :         "However, the parser succeeded",
    1680             :         source->ToCString().get(),
    1681             :         pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate())
    1682             :             ->ToCString()
    1683           0 :             .get());
    1684      248359 :   } else if (result == kError) {
    1685           0 :     FATAL(
    1686             :         "Expected error on:\n"
    1687             :         "\t%s\n"
    1688             :         "However, parser and preparser succeeded",
    1689           0 :         source->ToCString().get());
    1690             :   }
    1691      510389 : }
    1692             : 
    1693      130488 : void TestParserSync(const char* source, const ParserFlag* varying_flags,
    1694             :                     size_t varying_flags_length,
    1695             :                     ParserSyncTestResult result = kSuccessOrError,
    1696             :                     const ParserFlag* always_true_flags = nullptr,
    1697             :                     size_t always_true_flags_length = 0,
    1698             :                     const ParserFlag* always_false_flags = nullptr,
    1699             :                     size_t always_false_flags_length = 0,
    1700             :                     bool is_module = false, bool test_preparser = true,
    1701             :                     bool ignore_error_msg = false) {
    1702             :   i::Handle<i::String> str =
    1703             :       CcTest::i_isolate()
    1704             :           ->factory()
    1705      260976 :           ->NewStringFromUtf8(Vector<const char>(source, strlen(source)))
    1706      260976 :           .ToHandleChecked();
    1707      640877 :   for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
    1708             :     base::EnumSet<ParserFlag> flags;
    1709     1011492 :     for (size_t flag_index = 0; flag_index < varying_flags_length;
    1710             :          ++flag_index) {
    1711     1011492 :       if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
    1712             :     }
    1713      146530 :     for (size_t flag_index = 0; flag_index < always_true_flags_length;
    1714             :          ++flag_index) {
    1715      146530 :       flags.Add(always_true_flags[flag_index]);
    1716             :     }
    1717           0 :     for (size_t flag_index = 0; flag_index < always_false_flags_length;
    1718             :          ++flag_index) {
    1719           0 :       flags.Remove(always_false_flags[flag_index]);
    1720             :     }
    1721             :     TestParserSyncWithFlags(str, flags, result, is_module, test_preparser,
    1722      510389 :                             ignore_error_msg);
    1723             :   }
    1724      130488 : }
    1725             : 
    1726             : 
    1727       28338 : TEST(ParserSync) {
    1728             :   const char* context_data[][2] = {{"", ""},
    1729             :                                    {"{", "}"},
    1730             :                                    {"if (true) ", " else {}"},
    1731             :                                    {"if (true) {} else ", ""},
    1732             :                                    {"if (true) ", ""},
    1733             :                                    {"do ", " while (false)"},
    1734             :                                    {"while (false) ", ""},
    1735             :                                    {"for (;;) ", ""},
    1736             :                                    {"with ({})", ""},
    1737             :                                    {"switch (12) { case 12: ", "}"},
    1738             :                                    {"switch (12) { default: ", "}"},
    1739             :                                    {"switch (12) { ", "case 12: }"},
    1740             :                                    {"label2: ", ""},
    1741           1 :                                    {nullptr, nullptr}};
    1742             : 
    1743             :   const char* statement_data[] = {
    1744             :       "{}", "var x", "var x = 1", "const x", "const x = 1", ";", "12",
    1745             :       "if (false) {} else ;", "if (false) {} else {}", "if (false) {} else 12",
    1746             :       "if (false) ;", "if (false) {}", "if (false) 12", "do {} while (false)",
    1747             :       "for (;;) ;", "for (;;) {}", "for (;;) 12", "continue", "continue label",
    1748             :       "continue\nlabel", "break", "break label", "break\nlabel",
    1749             :       // TODO(marja): activate once parsing 'return' is merged into ParserBase.
    1750             :       // "return",
    1751             :       // "return  12",
    1752             :       // "return\n12",
    1753             :       "with ({}) ;", "with ({}) {}", "with ({}) 12", "switch ({}) { default: }",
    1754             :       "label3: ", "throw", "throw  12", "throw\n12", "try {} catch(e) {}",
    1755             :       "try {} finally {}", "try {} catch(e) {} finally {}", "debugger",
    1756           1 :       nullptr};
    1757             : 
    1758           1 :   const char* termination_data[] = {"", ";", "\n", ";\n", "\n;", nullptr};
    1759             : 
    1760           1 :   v8::HandleScope handles(CcTest::isolate());
    1761           1 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1762             :   v8::Context::Scope context_scope(context);
    1763             : 
    1764             :   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    1765           2 :       i::GetCurrentStackPosition() - 128 * 1024);
    1766             : 
    1767          14 :   for (int i = 0; context_data[i][0] != nullptr; ++i) {
    1768         455 :     for (int j = 0; statement_data[j] != nullptr; ++j) {
    1769        2275 :       for (int k = 0; termination_data[k] != nullptr; ++k) {
    1770             :         int kPrefixLen = i::StrLength(context_data[i][0]);
    1771             :         int kStatementLen = i::StrLength(statement_data[j]);
    1772             :         int kTerminationLen = i::StrLength(termination_data[k]);
    1773        2275 :         int kSuffixLen = i::StrLength(context_data[i][1]);
    1774        2275 :         int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
    1775        2275 :             + kSuffixLen + i::StrLength("label: for (;;) {  }");
    1776             : 
    1777             :         // Plug the source code pieces together.
    1778        2275 :         i::ScopedVector<char> program(kProgramSize + 1);
    1779             :         int length = i::SNPrintF(program,
    1780             :             "label: for (;;) { %s%s%s%s }",
    1781             :             context_data[i][0],
    1782             :             statement_data[j],
    1783             :             termination_data[k],
    1784        2275 :             context_data[i][1]);
    1785        2275 :         CHECK_EQ(length, kProgramSize);
    1786        2275 :         TestParserSync(program.start(), nullptr, 0);
    1787             :       }
    1788             :     }
    1789             :   }
    1790             : 
    1791             :   // Neither Harmony numeric literals nor our natives syntax have any
    1792             :   // interaction with the flags above, so test these separately to reduce
    1793             :   // the combinatorial explosion.
    1794           1 :   TestParserSync("0o1234", nullptr, 0);
    1795           1 :   TestParserSync("0b1011", nullptr, 0);
    1796             : 
    1797             :   static const ParserFlag flags3[] = { kAllowNatives };
    1798           2 :   TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
    1799           1 : }
    1800             : 
    1801             : 
    1802       28342 : TEST(StrictOctal) {
    1803             :   // Test that syntax error caused by octal literal is reported correctly as
    1804             :   // such (issue 2220).
    1805           5 :   v8::V8::Initialize();
    1806           5 :   v8::Isolate* isolate = CcTest::isolate();
    1807           5 :   v8::HandleScope scope(isolate);
    1808          10 :   v8::Context::Scope context_scope(v8::Context::New(isolate));
    1809             : 
    1810          10 :   v8::TryCatch try_catch(isolate);
    1811             :   const char* script =
    1812             :       "\"use strict\";       \n"
    1813             :       "a = function() {      \n"
    1814             :       "  b = function() {    \n"
    1815             :       "    01;               \n"
    1816             :       "  };                  \n"
    1817             :       "};                    \n";
    1818           5 :   v8_compile(v8_str(script));
    1819           5 :   CHECK(try_catch.HasCaught());
    1820          10 :   v8::String::Utf8Value exception(isolate, try_catch.Exception());
    1821           5 :   CHECK_EQ(0,
    1822             :            strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
    1823           5 :                   *exception));
    1824           5 : }
    1825             : 
    1826        1570 : void RunParserSyncTest(
    1827             :     const char* context_data[][2], const char* statement_data[],
    1828             :     ParserSyncTestResult result, const ParserFlag* flags = nullptr,
    1829             :     int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
    1830             :     int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
    1831             :     int always_false_len = 0, bool is_module = false,
    1832             :     bool test_preparser = true, bool ignore_error_msg = false) {
    1833        1570 :   v8::HandleScope handles(CcTest::isolate());
    1834        1570 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1835             :   v8::Context::Scope context_scope(context);
    1836             : 
    1837             :   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    1838        3140 :       i::GetCurrentStackPosition() - 128 * 1024);
    1839             : 
    1840             :   // Experimental feature flags should not go here; pass the flags as
    1841             :   // always_true_flags if the test needs them.
    1842             :   static const ParserFlag default_flags[] = {
    1843             :     kAllowLazy,
    1844             :     kAllowNatives,
    1845             :   };
    1846             :   ParserFlag* generated_flags = nullptr;
    1847        1570 :   if (flags == nullptr) {
    1848             :     flags = default_flags;
    1849             :     flags_len = arraysize(default_flags);
    1850        1550 :     if (always_true_flags != nullptr || always_false_flags != nullptr) {
    1851             :       // Remove always_true/false_flags from default_flags (if present).
    1852         185 :       CHECK((always_true_flags != nullptr) == (always_true_len > 0));
    1853         185 :       CHECK((always_false_flags != nullptr) == (always_false_len > 0));
    1854         185 :       generated_flags = new ParserFlag[flags_len + always_true_len];
    1855             :       int flag_index = 0;
    1856         555 :       for (int i = 0; i < flags_len; ++i) {
    1857             :         bool use_flag = true;
    1858         560 :         for (int j = 0; use_flag && j < always_true_len; ++j) {
    1859         560 :           if (flags[i] == always_true_flags[j]) use_flag = false;
    1860             :         }
    1861           0 :         for (int j = 0; use_flag && j < always_false_len; ++j) {
    1862           0 :           if (flags[i] == always_false_flags[j]) use_flag = false;
    1863             :         }
    1864         370 :         if (use_flag) generated_flags[flag_index++] = flags[i];
    1865             :       }
    1866             :       flags_len = flag_index;
    1867             :       flags = generated_flags;
    1868             :     }
    1869             :   }
    1870        8285 :   for (int i = 0; context_data[i][0] != nullptr; ++i) {
    1871      128210 :     for (int j = 0; statement_data[j] != nullptr; ++j) {
    1872      128210 :       int kPrefixLen = i::StrLength(context_data[i][0]);
    1873             :       int kStatementLen = i::StrLength(statement_data[j]);
    1874      128210 :       int kSuffixLen = i::StrLength(context_data[i][1]);
    1875      128210 :       int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
    1876             : 
    1877             :       // Plug the source code pieces together.
    1878      128210 :       i::ScopedVector<char> program(kProgramSize + 1);
    1879             :       int length = i::SNPrintF(program,
    1880             :                                "%s%s%s",
    1881             :                                context_data[i][0],
    1882             :                                statement_data[j],
    1883      128210 :                                context_data[i][1]);
    1884      128210 :       PrintF("%s\n", program.start());
    1885      128210 :       CHECK_EQ(length, kProgramSize);
    1886             :       TestParserSync(program.start(), flags, flags_len, result,
    1887             :                      always_true_flags, always_true_len, always_false_flags,
    1888             :                      always_false_len, is_module, test_preparser,
    1889      128210 :                      ignore_error_msg);
    1890             :     }
    1891             :   }
    1892        3140 :   delete[] generated_flags;
    1893        1570 : }
    1894             : 
    1895           0 : void RunModuleParserSyncTest(
    1896             :     const char* context_data[][2], const char* statement_data[],
    1897             :     ParserSyncTestResult result, const ParserFlag* flags = nullptr,
    1898             :     int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
    1899             :     int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
    1900             :     int always_false_len = 0, bool test_preparser = true,
    1901             :     bool ignore_error_msg = false) {
    1902             :   RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
    1903             :                     always_true_flags, always_true_len, always_false_flags,
    1904          95 :                     always_false_len, true, test_preparser, ignore_error_msg);
    1905           0 : }
    1906             : 
    1907       28342 : TEST(NumericSeparator) {
    1908           5 :   v8::HandleScope handles(CcTest::isolate());
    1909           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1910             :   v8::Context::Scope context_scope(context);
    1911             : 
    1912             :   const char* context_data[][2] = {
    1913           5 :       {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
    1914             :   const char* statement_data[] = {
    1915             :       "1_0_0_0", "1_0e+1",  "1_0e+1_0", "0xF_F_FF", "0o7_7_7", "0b0_1_0_1_0",
    1916           5 :       ".3_2_1",  "0.0_2_1", "1_0.0_1",  ".0_1_2",   nullptr};
    1917             : 
    1918             :   static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
    1919             :   RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0, flags,
    1920           5 :                     1);
    1921             : 
    1922          10 :   RunParserSyncTest(context_data, statement_data, kError);
    1923           5 : }
    1924             : 
    1925       28342 : TEST(NumericSeparatorErrors) {
    1926           5 :   v8::HandleScope handles(CcTest::isolate());
    1927           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1928             :   v8::Context::Scope context_scope(context);
    1929             : 
    1930             :   const char* context_data[][2] = {
    1931           5 :       {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
    1932             :   const char* statement_data[] = {
    1933             :       "1_0_0_0_", "1e_1",    "1e+_1", "1_e+1",  "1__0",    "0x_1",
    1934             :       "0x1__1",   "0x1_",    "0_x1",  "0_x_1",  "0b_0101", "0b11_",
    1935             :       "0b1__1",   "0_b1",    "0_b_1", "0o777_", "0o_777",  "0o7__77",
    1936           5 :       "0.0_2_1_", "0.0__21", "0_.01", "0._01",  nullptr};
    1937             : 
    1938             :   static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
    1939             :   RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
    1940           5 :                     nullptr, 0, false, true, true);
    1941             : 
    1942          10 :   RunParserSyncTest(context_data, statement_data, kError);
    1943           5 : }
    1944             : 
    1945       28342 : TEST(NumericSeparatorImplicitOctalsErrors) {
    1946           5 :   v8::HandleScope handles(CcTest::isolate());
    1947           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1948             :   v8::Context::Scope context_scope(context);
    1949             : 
    1950             :   const char* context_data[][2] = {
    1951           5 :       {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
    1952             :   const char* statement_data[] = {"00_122",  "0_012",  "07_7_7",
    1953             :                                   "0_7_7_7", "0_777",  "07_7_7_",
    1954           5 :                                   "07__77",  "0__777", nullptr};
    1955             : 
    1956             :   static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
    1957             :   RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
    1958           5 :                     nullptr, 0, false, true, true);
    1959             : 
    1960          10 :   RunParserSyncTest(context_data, statement_data, kError);
    1961           5 : }
    1962             : 
    1963       28342 : TEST(NumericSeparatorUnicodeEscapeSequencesErrors) {
    1964           5 :   v8::HandleScope handles(CcTest::isolate());
    1965           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    1966             :   v8::Context::Scope context_scope(context);
    1967             : 
    1968             :   const char* context_data[][2] = {
    1969           5 :       {"", ""}, {"'use strict'", ""}, {nullptr, nullptr}};
    1970             :   // https://github.com/tc39/proposal-numeric-separator/issues/25
    1971           5 :   const char* statement_data[] = {"\\u{10_FFFF}", nullptr};
    1972             : 
    1973             :   static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
    1974           5 :   RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1);
    1975             : 
    1976          10 :   RunParserSyncTest(context_data, statement_data, kError);
    1977           5 : }
    1978             : 
    1979       28342 : TEST(ErrorsEvalAndArguments) {
    1980             :   // Tests that both preparsing and parsing produce the right kind of errors for
    1981             :   // using "eval" and "arguments" as identifiers. Without the strict mode, it's
    1982             :   // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
    1983             :   // isn't.
    1984             :   const char* context_data[][2] = {
    1985             :       {"\"use strict\";", ""},
    1986             :       {"var eval; function test_func() {\"use strict\"; ", "}"},
    1987           5 :       {nullptr, nullptr}};
    1988             : 
    1989             :   const char* statement_data[] = {"var eval;",
    1990             :                                   "var arguments",
    1991             :                                   "var foo, eval;",
    1992             :                                   "var foo, arguments;",
    1993             :                                   "try { } catch (eval) { }",
    1994             :                                   "try { } catch (arguments) { }",
    1995             :                                   "function eval() { }",
    1996             :                                   "function arguments() { }",
    1997             :                                   "function foo(eval) { }",
    1998             :                                   "function foo(arguments) { }",
    1999             :                                   "function foo(bar, eval) { }",
    2000             :                                   "function foo(bar, arguments) { }",
    2001             :                                   "(eval) => { }",
    2002             :                                   "(arguments) => { }",
    2003             :                                   "(foo, eval) => { }",
    2004             :                                   "(foo, arguments) => { }",
    2005             :                                   "eval = 1;",
    2006             :                                   "arguments = 1;",
    2007             :                                   "var foo = eval = 1;",
    2008             :                                   "var foo = arguments = 1;",
    2009             :                                   "++eval;",
    2010             :                                   "++arguments;",
    2011             :                                   "eval++;",
    2012             :                                   "arguments++;",
    2013           5 :                                   nullptr};
    2014             : 
    2015           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2016           5 : }
    2017             : 
    2018             : 
    2019       28342 : TEST(NoErrorsEvalAndArgumentsSloppy) {
    2020             :   // Tests that both preparsing and parsing accept "eval" and "arguments" as
    2021             :   // identifiers when needed.
    2022             :   const char* context_data[][2] = {
    2023           5 :       {"", ""}, {"function test_func() {", "}"}, {nullptr, nullptr}};
    2024             : 
    2025             :   const char* statement_data[] = {"var eval;",
    2026             :                                   "var arguments",
    2027             :                                   "var foo, eval;",
    2028             :                                   "var foo, arguments;",
    2029             :                                   "try { } catch (eval) { }",
    2030             :                                   "try { } catch (arguments) { }",
    2031             :                                   "function eval() { }",
    2032             :                                   "function arguments() { }",
    2033             :                                   "function foo(eval) { }",
    2034             :                                   "function foo(arguments) { }",
    2035             :                                   "function foo(bar, eval) { }",
    2036             :                                   "function foo(bar, arguments) { }",
    2037             :                                   "eval = 1;",
    2038             :                                   "arguments = 1;",
    2039             :                                   "var foo = eval = 1;",
    2040             :                                   "var foo = arguments = 1;",
    2041             :                                   "++eval;",
    2042             :                                   "++arguments;",
    2043             :                                   "eval++;",
    2044             :                                   "arguments++;",
    2045           5 :                                   nullptr};
    2046             : 
    2047           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2048           5 : }
    2049             : 
    2050             : 
    2051       28342 : TEST(NoErrorsEvalAndArgumentsStrict) {
    2052             :   const char* context_data[][2] = {
    2053             :       {"\"use strict\";", ""},
    2054             :       {"function test_func() { \"use strict\";", "}"},
    2055             :       {"() => { \"use strict\"; ", "}"},
    2056           5 :       {nullptr, nullptr}};
    2057             : 
    2058             :   const char* statement_data[] = {"eval;",
    2059             :                                   "arguments;",
    2060             :                                   "var foo = eval;",
    2061             :                                   "var foo = arguments;",
    2062             :                                   "var foo = { eval: 1 };",
    2063             :                                   "var foo = { arguments: 1 };",
    2064             :                                   "var foo = { }; foo.eval = {};",
    2065             :                                   "var foo = { }; foo.arguments = {};",
    2066           5 :                                   nullptr};
    2067             : 
    2068           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2069           5 : }
    2070             : 
    2071             : #define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
    2072             :   V(implements)                                \
    2073             :   V(interface)                                 \
    2074             :   V(package)                                   \
    2075             :   V(private)                                   \
    2076             :   V(protected)                                 \
    2077             :   V(public)                                    \
    2078             :   V(static)                                    \
    2079             :   V(yield)
    2080             : 
    2081             : #define FUTURE_STRICT_RESERVED_WORDS(V) \
    2082             :   V(let)                                \
    2083             :   FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
    2084             : 
    2085             : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
    2086             :   V(implements)                                        \
    2087             :   V(static)                                            \
    2088             :   V(yield)
    2089             : 
    2090             : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
    2091             :   V(let)                                        \
    2092             :   LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
    2093             : 
    2094             : #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
    2095             :   "var " #NAME ";",                             \
    2096             :   "var foo, " #NAME ";",                        \
    2097             :   "try { } catch (" #NAME ") { }",              \
    2098             :   "function " #NAME "() { }",                   \
    2099             :   "(function " #NAME "() { })",                 \
    2100             :   "function foo(" #NAME ") { }",                \
    2101             :   "function foo(bar, " #NAME ") { }",           \
    2102             :   #NAME " = 1;",                                \
    2103             :   #NAME " += 1;",                               \
    2104             :   "var foo = " #NAME " = 1;",                   \
    2105             :   "++" #NAME ";",                               \
    2106             :   #NAME " ++;",
    2107             : 
    2108             : // clang-format off
    2109             : #define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
    2110             :   "let " #NAME ";",                               \
    2111             :   "for (let " #NAME "; false; ) {}",              \
    2112             :   "for (let " #NAME " in {}) {}",                 \
    2113             :   "for (let " #NAME " of []) {}",                 \
    2114             :   "const " #NAME " = null;",                      \
    2115             :   "for (const " #NAME " = null; false; ) {}",     \
    2116             :   "for (const " #NAME " in {}) {}",               \
    2117             :   "for (const " #NAME " of []) {}",
    2118             : // clang-format on
    2119             : 
    2120       28342 : TEST(ErrorsFutureStrictReservedWords) {
    2121             :   // Tests that both preparsing and parsing produce the right kind of errors for
    2122             :   // using future strict reserved words as identifiers. Without the strict mode,
    2123             :   // it's ok to use future strict reserved words as identifiers. With the strict
    2124             :   // mode, it isn't.
    2125             :   const char* strict_contexts[][2] = {
    2126             :       {"function test_func() {\"use strict\"; ", "}"},
    2127             :       {"() => { \"use strict\"; ", "}"},
    2128           5 :       {nullptr, nullptr}};
    2129             : 
    2130             :   // clang-format off
    2131             :   const char* statement_data[] {
    2132             :     LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
    2133             :     LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
    2134             :     nullptr
    2135           5 :   };
    2136             :   // clang-format on
    2137             : 
    2138           5 :   RunParserSyncTest(strict_contexts, statement_data, kError);
    2139             : 
    2140             :   // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
    2141             :   //
    2142             :   // > LexicalDeclaration : LetOrConst BindingList ;
    2143             :   // >
    2144             :   // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
    2145             :   const char* non_strict_contexts[][2] = {{"", ""},
    2146             :                                           {"function test_func() {", "}"},
    2147             :                                           {"() => {", "}"},
    2148           5 :                                           {nullptr, nullptr}};
    2149             :   const char* invalid_statements[] = {
    2150           5 :       FUTURE_STRICT_RESERVED_LEX_BINDINGS(let) nullptr};
    2151             : 
    2152           5 :   RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
    2153           5 : }
    2154             : 
    2155             : #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
    2156             : 
    2157             : 
    2158       28342 : TEST(NoErrorsFutureStrictReservedWords) {
    2159             :   const char* context_data[][2] = {{"", ""},
    2160             :                                    {"function test_func() {", "}"},
    2161             :                                    {"() => {", "}"},
    2162           5 :                                    {nullptr, nullptr}};
    2163             : 
    2164             :   // clang-format off
    2165             :   const char* statement_data[] = {
    2166             :     FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
    2167             :     FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
    2168             :     nullptr
    2169           5 :   };
    2170             :   // clang-format on
    2171             : 
    2172           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2173           5 : }
    2174             : 
    2175             : 
    2176       28342 : TEST(ErrorsReservedWords) {
    2177             :   // Tests that both preparsing and parsing produce the right kind of errors for
    2178             :   // using future reserved words as identifiers. These tests don't depend on the
    2179             :   // strict mode.
    2180             :   const char* context_data[][2] = {
    2181             :       {"", ""},
    2182             :       {"\"use strict\";", ""},
    2183             :       {"var eval; function test_func() {", "}"},
    2184             :       {"var eval; function test_func() {\"use strict\"; ", "}"},
    2185             :       {"var eval; () => {", "}"},
    2186             :       {"var eval; () => {\"use strict\"; ", "}"},
    2187           5 :       {nullptr, nullptr}};
    2188             : 
    2189             :   const char* statement_data[] = {"var super;",
    2190             :                                   "var foo, super;",
    2191             :                                   "try { } catch (super) { }",
    2192             :                                   "function super() { }",
    2193             :                                   "function foo(super) { }",
    2194             :                                   "function foo(bar, super) { }",
    2195             :                                   "(super) => { }",
    2196             :                                   "(bar, super) => { }",
    2197             :                                   "super = 1;",
    2198             :                                   "var foo = super = 1;",
    2199             :                                   "++super;",
    2200             :                                   "super++;",
    2201             :                                   "function foo super",
    2202           5 :                                   nullptr};
    2203             : 
    2204           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2205           5 : }
    2206             : 
    2207             : 
    2208       28342 : TEST(NoErrorsLetSloppyAllModes) {
    2209             :   // In sloppy mode, it's okay to use "let" as identifier.
    2210             :   const char* context_data[][2] = {{"", ""},
    2211             :                                    {"function f() {", "}"},
    2212             :                                    {"(function f() {", "})"},
    2213           5 :                                    {nullptr, nullptr}};
    2214             : 
    2215             :   const char* statement_data[] = {
    2216             :       "var let;",
    2217             :       "var foo, let;",
    2218             :       "try { } catch (let) { }",
    2219             :       "function let() { }",
    2220             :       "(function let() { })",
    2221             :       "function foo(let) { }",
    2222             :       "function foo(bar, let) { }",
    2223             :       "let = 1;",
    2224             :       "var foo = let = 1;",
    2225             :       "let * 2;",
    2226             :       "++let;",
    2227             :       "let++;",
    2228             :       "let: 34",
    2229             :       "function let(let) { let: let(let + let(0)); }",
    2230             :       "({ let: 1 })",
    2231             :       "({ get let() { 1 } })",
    2232             :       "let(100)",
    2233             :       "L: let\nx",
    2234             :       "L: let\n{x}",
    2235           5 :       nullptr};
    2236             : 
    2237           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2238           5 : }
    2239             : 
    2240             : 
    2241       28342 : TEST(NoErrorsYieldSloppyAllModes) {
    2242             :   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
    2243             :   // generator (see other test).
    2244             :   const char* context_data[][2] = {{"", ""},
    2245             :                                    {"function not_gen() {", "}"},
    2246             :                                    {"(function not_gen() {", "})"},
    2247           5 :                                    {nullptr, nullptr}};
    2248             : 
    2249             :   const char* statement_data[] = {
    2250             :       "var yield;",
    2251             :       "var foo, yield;",
    2252             :       "try { } catch (yield) { }",
    2253             :       "function yield() { }",
    2254             :       "(function yield() { })",
    2255             :       "function foo(yield) { }",
    2256             :       "function foo(bar, yield) { }",
    2257             :       "yield = 1;",
    2258             :       "var foo = yield = 1;",
    2259             :       "yield * 2;",
    2260             :       "++yield;",
    2261             :       "yield++;",
    2262             :       "yield: 34",
    2263             :       "function yield(yield) { yield: yield (yield + yield(0)); }",
    2264             :       "({ yield: 1 })",
    2265             :       "({ get yield() { 1 } })",
    2266             :       "yield(100)",
    2267             :       "yield[100]",
    2268           5 :       nullptr};
    2269             : 
    2270           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2271           5 : }
    2272             : 
    2273             : 
    2274       28342 : TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
    2275             :   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
    2276             :   // generator (see next test).
    2277             :   const char* context_data[][2] = {
    2278             :       {"", ""},
    2279             :       {"function not_gen() {", "}"},
    2280             :       {"function * gen() { function not_gen() {", "} }"},
    2281             :       {"(function not_gen() {", "})"},
    2282             :       {"(function * gen() { (function not_gen() {", "}) })"},
    2283           5 :       {nullptr, nullptr}};
    2284             : 
    2285             :   const char* statement_data[] = {
    2286             :       "var yield;",
    2287             :       "var foo, yield;",
    2288             :       "try { } catch (yield) { }",
    2289             :       "function yield() { }",
    2290             :       "(function yield() { })",
    2291             :       "function foo(yield) { }",
    2292             :       "function foo(bar, yield) { }",
    2293             :       "function * yield() { }",
    2294             :       "yield = 1;",
    2295             :       "var foo = yield = 1;",
    2296             :       "yield * 2;",
    2297             :       "++yield;",
    2298             :       "yield++;",
    2299             :       "yield: 34",
    2300             :       "function yield(yield) { yield: yield (yield + yield(0)); }",
    2301             :       "({ yield: 1 })",
    2302             :       "({ get yield() { 1 } })",
    2303             :       "yield(100)",
    2304             :       "yield[100]",
    2305           5 :       nullptr};
    2306             : 
    2307           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2308           5 : }
    2309             : 
    2310             : 
    2311       28342 : TEST(ErrorsYieldStrict) {
    2312             :   const char* context_data[][2] = {
    2313             :       {"\"use strict\";", ""},
    2314             :       {"\"use strict\"; function not_gen() {", "}"},
    2315             :       {"function test_func() {\"use strict\"; ", "}"},
    2316             :       {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
    2317             :       {"\"use strict\"; (function not_gen() {", "})"},
    2318             :       {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
    2319             :       {"() => {\"use strict\"; ", "}"},
    2320           5 :       {nullptr, nullptr}};
    2321             : 
    2322             :   const char* statement_data[] = {"var yield;",
    2323             :                                   "var foo, yield;",
    2324             :                                   "try { } catch (yield) { }",
    2325             :                                   "function yield() { }",
    2326             :                                   "(function yield() { })",
    2327             :                                   "function foo(yield) { }",
    2328             :                                   "function foo(bar, yield) { }",
    2329             :                                   "function * yield() { }",
    2330             :                                   "(function * yield() { })",
    2331             :                                   "yield = 1;",
    2332             :                                   "var foo = yield = 1;",
    2333             :                                   "++yield;",
    2334             :                                   "yield++;",
    2335             :                                   "yield: 34;",
    2336           5 :                                   nullptr};
    2337             : 
    2338           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2339           5 : }
    2340             : 
    2341             : 
    2342       28342 : TEST(ErrorsYieldSloppy) {
    2343             :   const char* context_data[][2] = {{"", ""},
    2344             :                                    {"function not_gen() {", "}"},
    2345             :                                    {"(function not_gen() {", "})"},
    2346           5 :                                    {nullptr, nullptr}};
    2347             : 
    2348           5 :   const char* statement_data[] = {"(function * yield() { })", nullptr};
    2349             : 
    2350           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2351           5 : }
    2352             : 
    2353             : 
    2354       28342 : TEST(NoErrorsGenerator) {
    2355             :   // clang-format off
    2356             :   const char* context_data[][2] = {
    2357             :     { "function * gen() {", "}" },
    2358             :     { "(function * gen() {", "})" },
    2359             :     { "(function * () {", "})" },
    2360             :     { nullptr, nullptr }
    2361           5 :   };
    2362             : 
    2363             :   const char* statement_data[] = {
    2364             :     // A generator without a body is valid.
    2365             :     ""
    2366             :     // Valid yield expressions inside generators.
    2367             :     "yield 2;",
    2368             :     "yield * 2;",
    2369             :     "yield * \n 2;",
    2370             :     "yield yield 1;",
    2371             :     "yield * yield * 1;",
    2372             :     "yield 3 + (yield 4);",
    2373             :     "yield * 3 + (yield * 4);",
    2374             :     "(yield * 3) + (yield * 4);",
    2375             :     "yield 3; yield 4;",
    2376             :     "yield * 3; yield * 4;",
    2377             :     "(function (yield) { })",
    2378             :     "(function yield() { })",
    2379             :     "yield { yield: 12 }",
    2380             :     "yield /* comment */ { yield: 12 }",
    2381             :     "yield * \n { yield: 12 }",
    2382             :     "yield /* comment */ * \n { yield: 12 }",
    2383             :     // You can return in a generator.
    2384             :     "yield 1; return",
    2385             :     "yield * 1; return",
    2386             :     "yield 1; return 37",
    2387             :     "yield * 1; return 37",
    2388             :     "yield 1; return 37; yield 'dead';",
    2389             :     "yield * 1; return 37; yield * 'dead';",
    2390             :     // Yield is still a valid key in object literals.
    2391             :     "({ yield: 1 })",
    2392             :     "({ get yield() { } })",
    2393             :     // And in assignment pattern computed properties
    2394             :     "({ [yield]: x } = { })",
    2395             :     // Yield without RHS.
    2396             :     "yield;",
    2397             :     "yield",
    2398             :     "yield\n",
    2399             :     "yield /* comment */"
    2400             :     "yield // comment\n"
    2401             :     "(yield)",
    2402             :     "[yield]",
    2403             :     "{yield}",
    2404             :     "yield, yield",
    2405             :     "yield; yield",
    2406             :     "(yield) ? yield : yield",
    2407             :     "(yield) \n ? yield : yield",
    2408             :     // If there is a newline before the next token, we don't look for RHS.
    2409             :     "yield\nfor (;;) {}",
    2410             :     "x = class extends (yield) {}",
    2411             :     "x = class extends f(yield) {}",
    2412             :     "x = class extends (null, yield) { }",
    2413             :     "x = class extends (a ? null : yield) { }",
    2414             :     nullptr
    2415           5 :   };
    2416             :   // clang-format on
    2417             : 
    2418           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2419           5 : }
    2420             : 
    2421             : 
    2422       28342 : TEST(ErrorsYieldGenerator) {
    2423             :   // clang-format off
    2424             :   const char* context_data[][2] = {
    2425             :     { "function * gen() {", "}" },
    2426             :     { "\"use strict\"; function * gen() {", "}" },
    2427             :     { nullptr, nullptr }
    2428           5 :   };
    2429             : 
    2430             :   const char* statement_data[] = {
    2431             :     // Invalid yield expressions inside generators.
    2432             :     "var yield;",
    2433             :     "var foo, yield;",
    2434             :     "try { } catch (yield) { }",
    2435             :     "function yield() { }",
    2436             :     // The name of the NFE is bound in the generator, which does not permit
    2437             :     // yield to be an identifier.
    2438             :     "(function * yield() { })",
    2439             :     // Yield isn't valid as a formal parameter for generators.
    2440             :     "function * foo(yield) { }",
    2441             :     "(function * foo(yield) { })",
    2442             :     "yield = 1;",
    2443             :     "var foo = yield = 1;",
    2444             :     "++yield;",
    2445             :     "yield++;",
    2446             :     "yield *",
    2447             :     "(yield *)",
    2448             :     // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
    2449             :     // is invalid.
    2450             :     "yield 3 + yield 4;",
    2451             :     "yield: 34",
    2452             :     "yield ? 1 : 2",
    2453             :     // Parses as yield (/ yield): invalid.
    2454             :     "yield / yield",
    2455             :     "+ yield",
    2456             :     "+ yield 3",
    2457             :     // Invalid (no newline allowed between yield and *).
    2458             :     "yield\n*3",
    2459             :     // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
    2460             :     // object literal, and yield is not a valid label).
    2461             :     "yield\n{yield: 42}",
    2462             :     "yield /* comment */\n {yield: 42}",
    2463             :     "yield //comment\n {yield: 42}",
    2464             :     // Destructuring binding and assignment are both disallowed
    2465             :     "var [yield] = [42];",
    2466             :     "var {foo: yield} = {a: 42};",
    2467             :     "[yield] = [42];",
    2468             :     "({a: yield} = {a: 42});",
    2469             :     // Also disallow full yield expressions on LHS
    2470             :     "var [yield 24] = [42];",
    2471             :     "var {foo: yield 24} = {a: 42};",
    2472             :     "[yield 24] = [42];",
    2473             :     "({a: yield 24} = {a: 42});",
    2474             :     "for (yield 'x' in {});",
    2475             :     "for (yield 'x' of {});",
    2476             :     "for (yield 'x' in {} in {});",
    2477             :     "for (yield 'x' in {} of {});",
    2478             :     "class C extends yield { }",
    2479             :     nullptr
    2480           5 :   };
    2481             :   // clang-format on
    2482             : 
    2483           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2484           5 : }
    2485             : 
    2486             : 
    2487       28342 : TEST(ErrorsNameOfStrictFunction) {
    2488             :   // Tests that illegal tokens as names of a strict function produce the correct
    2489             :   // errors.
    2490             :   const char* context_data[][2] = {{"function ", ""},
    2491             :                                    {"\"use strict\"; function", ""},
    2492             :                                    {"function * ", ""},
    2493             :                                    {"\"use strict\"; function * ", ""},
    2494           5 :                                    {nullptr, nullptr}};
    2495             : 
    2496             :   const char* statement_data[] = {
    2497             :       "eval() {\"use strict\";}", "arguments() {\"use strict\";}",
    2498             :       "interface() {\"use strict\";}", "yield() {\"use strict\";}",
    2499             :       // Future reserved words are always illegal
    2500           5 :       "super() { }", "super() {\"use strict\";}", nullptr};
    2501             : 
    2502           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2503           5 : }
    2504             : 
    2505             : 
    2506       28342 : TEST(NoErrorsNameOfStrictFunction) {
    2507           5 :   const char* context_data[][2] = {{"function ", ""}, {nullptr, nullptr}};
    2508             : 
    2509             :   const char* statement_data[] = {"eval() { }", "arguments() { }",
    2510           5 :                                   "interface() { }", "yield() { }", nullptr};
    2511             : 
    2512           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2513           5 : }
    2514             : 
    2515             : 
    2516       28342 : TEST(NoErrorsNameOfStrictGenerator) {
    2517           5 :   const char* context_data[][2] = {{"function * ", ""}, {nullptr, nullptr}};
    2518             : 
    2519             :   const char* statement_data[] = {"eval() { }", "arguments() { }",
    2520           5 :                                   "interface() { }", "yield() { }", nullptr};
    2521             : 
    2522           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2523           5 : }
    2524             : 
    2525             : 
    2526       28342 : TEST(ErrorsIllegalWordsAsLabelsSloppy) {
    2527             :   // Using future reserved words as labels is always an error.
    2528             :   const char* context_data[][2] = {{"", ""},
    2529             :                                    {"function test_func() {", "}"},
    2530             :                                    {"() => {", "}"},
    2531           5 :                                    {nullptr, nullptr}};
    2532             : 
    2533             :   const char* statement_data[] = {"super: while(true) { break super; }",
    2534           5 :                                   nullptr};
    2535             : 
    2536           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2537           5 : }
    2538             : 
    2539             : 
    2540       28342 : TEST(ErrorsIllegalWordsAsLabelsStrict) {
    2541             :   // Tests that illegal tokens as labels produce the correct errors.
    2542             :   const char* context_data[][2] = {
    2543             :       {"\"use strict\";", ""},
    2544             :       {"function test_func() {\"use strict\"; ", "}"},
    2545             :       {"() => {\"use strict\"; ", "}"},
    2546           5 :       {nullptr, nullptr}};
    2547             : 
    2548             : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
    2549             :   const char* statement_data[] = {
    2550             :       "super: while(true) { break super; }",
    2551           5 :       FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
    2552             : #undef LABELLED_WHILE
    2553             : 
    2554           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2555           5 : }
    2556             : 
    2557             : 
    2558       28342 : TEST(NoErrorsIllegalWordsAsLabels) {
    2559             :   // Using eval and arguments as labels is legal even in strict mode.
    2560             :   const char* context_data[][2] = {
    2561             :       {"", ""},
    2562             :       {"function test_func() {", "}"},
    2563             :       {"() => {", "}"},
    2564             :       {"\"use strict\";", ""},
    2565             :       {"\"use strict\"; function test_func() {", "}"},
    2566             :       {"\"use strict\"; () => {", "}"},
    2567           5 :       {nullptr, nullptr}};
    2568             : 
    2569             :   const char* statement_data[] = {"mylabel: while(true) { break mylabel; }",
    2570             :                                   "eval: while(true) { break eval; }",
    2571             :                                   "arguments: while(true) { break arguments; }",
    2572           5 :                                   nullptr};
    2573             : 
    2574           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2575           5 : }
    2576             : 
    2577             : 
    2578       28342 : TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
    2579             :   const char* context_data[][2] = {{"", ""},
    2580             :                                    {"function test_func() {", "}"},
    2581             :                                    {"() => {", "}"},
    2582           5 :                                    {nullptr, nullptr}};
    2583             : 
    2584             : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
    2585             :   const char* statement_data[]{
    2586           5 :       FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
    2587             : #undef LABELLED_WHILE
    2588             : 
    2589           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2590           5 : }
    2591             : 
    2592             : 
    2593       28342 : TEST(ErrorsParenthesizedLabels) {
    2594             :   // Parenthesized identifiers shouldn't be recognized as labels.
    2595             :   const char* context_data[][2] = {{"", ""},
    2596             :                                    {"function test_func() {", "}"},
    2597             :                                    {"() => {", "}"},
    2598           5 :                                    {nullptr, nullptr}};
    2599             : 
    2600             :   const char* statement_data[] = {"(mylabel): while(true) { break mylabel; }",
    2601           5 :                                   nullptr};
    2602             : 
    2603           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2604           5 : }
    2605             : 
    2606             : 
    2607       28342 : TEST(NoErrorsParenthesizedDirectivePrologue) {
    2608             :   // Parenthesized directive prologue shouldn't be recognized.
    2609           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    2610             : 
    2611           5 :   const char* statement_data[] = {"(\"use strict\"); var eval;", nullptr};
    2612             : 
    2613           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2614           5 : }
    2615             : 
    2616             : 
    2617       28342 : TEST(ErrorsNotAnIdentifierName) {
    2618             :   const char* context_data[][2] = {
    2619           5 :       {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
    2620             : 
    2621             :   const char* statement_data[] = {"var foo = {}; foo.{;",
    2622             :                                   "var foo = {}; foo.};",
    2623             :                                   "var foo = {}; foo.=;",
    2624             :                                   "var foo = {}; foo.888;",
    2625             :                                   "var foo = {}; foo.-;",
    2626             :                                   "var foo = {}; foo.--;",
    2627           5 :                                   nullptr};
    2628             : 
    2629           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2630           5 : }
    2631             : 
    2632             : 
    2633       28342 : TEST(NoErrorsIdentifierNames) {
    2634             :   // Keywords etc. are valid as property names.
    2635             :   const char* context_data[][2] = {
    2636           5 :       {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
    2637             : 
    2638             :   const char* statement_data[] = {"var foo = {}; foo.if;",
    2639             :                                   "var foo = {}; foo.yield;",
    2640             :                                   "var foo = {}; foo.super;",
    2641             :                                   "var foo = {}; foo.interface;",
    2642             :                                   "var foo = {}; foo.eval;",
    2643             :                                   "var foo = {}; foo.arguments;",
    2644           5 :                                   nullptr};
    2645             : 
    2646           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2647           5 : }
    2648             : 
    2649       28342 : TEST(FunctionDeclaresItselfStrict) {
    2650             :   // Tests that we produce the right kinds of errors when a function declares
    2651             :   // itself strict (we cannot produce there errors as soon as we see the
    2652             :   // offending identifiers, because we don't know at that point whether the
    2653             :   // function is strict or not).
    2654             :   const char* context_data[][2] = {{"function eval() {", "}"},
    2655             :                                    {"function arguments() {", "}"},
    2656             :                                    {"function yield() {", "}"},
    2657             :                                    {"function interface() {", "}"},
    2658             :                                    {"function foo(eval) {", "}"},
    2659             :                                    {"function foo(arguments) {", "}"},
    2660             :                                    {"function foo(yield) {", "}"},
    2661             :                                    {"function foo(interface) {", "}"},
    2662             :                                    {"function foo(bar, eval) {", "}"},
    2663             :                                    {"function foo(bar, arguments) {", "}"},
    2664             :                                    {"function foo(bar, yield) {", "}"},
    2665             :                                    {"function foo(bar, interface) {", "}"},
    2666             :                                    {"function foo(bar, bar) {", "}"},
    2667           5 :                                    {nullptr, nullptr}};
    2668             : 
    2669           5 :   const char* strict_statement_data[] = {"\"use strict\";", nullptr};
    2670             : 
    2671           5 :   const char* non_strict_statement_data[] = {";", nullptr};
    2672             : 
    2673           5 :   RunParserSyncTest(context_data, strict_statement_data, kError);
    2674           5 :   RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
    2675           5 : }
    2676             : 
    2677             : 
    2678       28342 : TEST(ErrorsTryWithoutCatchOrFinally) {
    2679           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    2680             : 
    2681             :   const char* statement_data[] = {"try { }", "try { } foo();",
    2682             :                                   "try { } catch (e) foo();",
    2683           5 :                                   "try { } finally foo();", nullptr};
    2684             : 
    2685           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2686           5 : }
    2687             : 
    2688             : 
    2689       28342 : TEST(NoErrorsTryCatchFinally) {
    2690           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    2691             : 
    2692             :   const char* statement_data[] = {"try { } catch (e) { }",
    2693             :                                   "try { } catch (e) { } finally { }",
    2694           5 :                                   "try { } finally { }", nullptr};
    2695             : 
    2696           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2697           5 : }
    2698             : 
    2699       28342 : TEST(OptionalCatchBinding) {
    2700             :   // clang-format off
    2701             :   const char* context_data[][2] = {
    2702             :     {"", ""},
    2703             :     {"'use strict';", ""},
    2704             :     {"try {", "} catch (e) { }"},
    2705             :     {"try {} catch (e) {", "}"},
    2706             :     {"try {", "} catch ({e}) { }"},
    2707             :     {"try {} catch ({e}) {", "}"},
    2708             :     {"function f() {", "}"},
    2709             :     { nullptr, nullptr }
    2710           5 :   };
    2711             : 
    2712             :   const char* statement_data[] = {
    2713             :     "try { } catch { }",
    2714             :     "try { } catch { } finally { }",
    2715             :     "try { let e; } catch { let e; }",
    2716             :     "try { let e; } catch { let e; } finally { let e; }",
    2717             :     nullptr
    2718           5 :   };
    2719             :   // clang-format on
    2720             : 
    2721           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2722           5 : }
    2723             : 
    2724       28342 : TEST(ErrorsRegexpLiteral) {
    2725           5 :   const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
    2726             : 
    2727           5 :   const char* statement_data[] = {"/unterminated", nullptr};
    2728             : 
    2729           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2730           5 : }
    2731             : 
    2732             : 
    2733       28342 : TEST(NoErrorsRegexpLiteral) {
    2734           5 :   const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
    2735             : 
    2736           5 :   const char* statement_data[] = {"/foo/", "/foo/g", nullptr};
    2737             : 
    2738           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2739           5 : }
    2740             : 
    2741             : 
    2742       28342 : TEST(NoErrorsNewExpression) {
    2743             :   const char* context_data[][2] = {
    2744           5 :       {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
    2745             : 
    2746             :   const char* statement_data[] = {
    2747             :       "new foo", "new foo();", "new foo(1);", "new foo(1, 2);",
    2748             :       // The first () will be processed as a part of the NewExpression and the
    2749             :       // second () will be processed as part of LeftHandSideExpression.
    2750             :       "new foo()();",
    2751             :       // The first () will be processed as a part of the inner NewExpression and
    2752             :       // the second () will be processed as a part of the outer NewExpression.
    2753             :       "new new foo()();", "new foo.bar;", "new foo.bar();", "new foo.bar.baz;",
    2754             :       "new foo.bar().baz;", "new foo[bar];", "new foo[bar]();",
    2755             :       "new foo[bar][baz];", "new foo[bar]()[baz];",
    2756             :       "new foo[bar].baz(baz)()[bar].baz;",
    2757             :       "new \"foo\"",  // Runtime error
    2758             :       "new 1",        // Runtime error
    2759             :       // This even runs:
    2760             :       "(new new Function(\"this.x = 1\")).x;",
    2761           5 :       "new new Test_Two(String, 2).v(0123).length;", nullptr};
    2762             : 
    2763           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2764           5 : }
    2765             : 
    2766             : 
    2767       28342 : TEST(ErrorsNewExpression) {
    2768             :   const char* context_data[][2] = {
    2769           5 :       {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
    2770             : 
    2771             :   const char* statement_data[] = {"new foo bar", "new ) foo", "new ++foo",
    2772           5 :                                   "new foo ++", nullptr};
    2773             : 
    2774           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2775           5 : }
    2776             : 
    2777             : 
    2778       28342 : TEST(StrictObjectLiteralChecking) {
    2779             :   const char* context_data[][2] = {{"\"use strict\"; var myobject = {", "};"},
    2780             :                                    {"\"use strict\"; var myobject = {", ",};"},
    2781             :                                    {"var myobject = {", "};"},
    2782             :                                    {"var myobject = {", ",};"},
    2783           5 :                                    {nullptr, nullptr}};
    2784             : 
    2785             :   // These are only errors in strict mode.
    2786             :   const char* statement_data[] = {
    2787             :       "foo: 1, foo: 2", "\"foo\": 1, \"foo\": 2", "foo: 1, \"foo\": 2",
    2788             :       "1: 1, 1: 2",     "1: 1, \"1\": 2",
    2789             :       "get: 1, get: 2",  // Not a getter for real, just a property called get.
    2790             :       "set: 1, set: 2",  // Not a setter for real, just a property called set.
    2791           5 :       nullptr};
    2792             : 
    2793           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2794           5 : }
    2795             : 
    2796             : 
    2797       28342 : TEST(ErrorsObjectLiteralChecking) {
    2798             :   // clang-format off
    2799             :   const char* context_data[][2] = {
    2800             :     {"\"use strict\"; var myobject = {", "};"},
    2801             :     {"var myobject = {", "};"},
    2802             :     { nullptr, nullptr }
    2803           5 :   };
    2804             : 
    2805             :   const char* statement_data[] = {
    2806             :     ",",
    2807             :     // Wrong number of parameters
    2808             :     "get bar(x) {}",
    2809             :     "get bar(x, y) {}",
    2810             :     "set bar() {}",
    2811             :     "set bar(x, y) {}",
    2812             :     // Parsing FunctionLiteral for getter or setter fails
    2813             :     "get foo( +",
    2814             :     "get foo() \"error\"",
    2815             :     // Various forbidden forms
    2816             :     "static x: 0",
    2817             :     "static x(){}",
    2818             :     "static async x(){}",
    2819             :     "static get x(){}",
    2820             :     "static get x : 0",
    2821             :     "static x",
    2822             :     "static 0",
    2823             :     "*x: 0",
    2824             :     "*x",
    2825             :     "*get x(){}",
    2826             :     "*set x(y){}",
    2827             :     "get *x(){}",
    2828             :     "set *x(y){}",
    2829             :     "get x*(){}",
    2830             :     "set x*(y){}",
    2831             :     "x = 0",
    2832             :     "* *x(){}",
    2833             :     "x*(){}",
    2834             :     "static async x(){}",
    2835             :     "static async x : 0",
    2836             :     "static async get x : 0",
    2837             :     "async static x(){}",
    2838             :     "*async x(){}",
    2839             :     "async x*(){}",
    2840             :     "async x : 0",
    2841             :     "async 0 : 0",
    2842             :     "async get x(){}",
    2843             :     "async get *x(){}",
    2844             :     "async set x(y){}",
    2845             :     "async get : 0",
    2846             :     nullptr
    2847           5 :   };
    2848             :   // clang-format on
    2849             : 
    2850           5 :   RunParserSyncTest(context_data, statement_data, kError);
    2851           5 : }
    2852             : 
    2853             : 
    2854       28342 : TEST(NoErrorsObjectLiteralChecking) {
    2855             :   // clang-format off
    2856             :   const char* context_data[][2] = {
    2857             :     {"var myobject = {", "};"},
    2858             :     {"var myobject = {", ",};"},
    2859             :     {"\"use strict\"; var myobject = {", "};"},
    2860             :     {"\"use strict\"; var myobject = {", ",};"},
    2861             :     { nullptr, nullptr }
    2862           5 :   };
    2863             : 
    2864             :   const char* statement_data[] = {
    2865             :     "foo: 1, get foo() {}",
    2866             :     "foo: 1, set foo(v) {}",
    2867             :     "\"foo\": 1, get \"foo\"() {}",
    2868             :     "\"foo\": 1, set \"foo\"(v) {}",
    2869             :     "1: 1, get 1() {}",
    2870             :     "1: 1, set 1(v) {}",
    2871             :     "get foo() {}, get foo() {}",
    2872             :     "set foo(_) {}, set foo(v) {}",
    2873             :     "foo: 1, get \"foo\"() {}",
    2874             :     "foo: 1, set \"foo\"(v) {}",
    2875             :     "\"foo\": 1, get foo() {}",
    2876             :     "\"foo\": 1, set foo(v) {}",
    2877             :     "1: 1, get \"1\"() {}",
    2878             :     "1: 1, set \"1\"(v) {}",
    2879             :     "\"1\": 1, get 1() {}",
    2880             :     "\"1\": 1, set 1(v) {}",
    2881             :     "foo: 1, bar: 2",
    2882             :     "\"foo\": 1, \"bar\": 2",
    2883             :     "1: 1, 2: 2",
    2884             :     // Syntax: IdentifierName ':' AssignmentExpression
    2885             :     "foo: bar = 5 + baz",
    2886             :     // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
    2887             :     "get foo() {}",
    2888             :     "get \"foo\"() {}",
    2889             :     "get 1() {}",
    2890             :     // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
    2891             :     //     '{' FunctionBody '}'
    2892             :     "set foo(v) {}",
    2893             :     "set \"foo\"(v) {}",
    2894             :     "set 1(v) {}",
    2895             :     // Non-colliding getters and setters -> no errors
    2896             :     "foo: 1, get bar() {}",
    2897             :     "foo: 1, set bar(v) {}",
    2898             :     "\"foo\": 1, get \"bar\"() {}",
    2899             :     "\"foo\": 1, set \"bar\"(v) {}",
    2900             :     "1: 1, get 2() {}",
    2901             :     "1: 1, set 2(v) {}",
    2902             :     "get: 1, get foo() {}",
    2903             :     "set: 1, set foo(_) {}",
    2904             :     // Potentially confusing cases
    2905             :     "get(){}",
    2906             :     "set(){}",
    2907             :     "static(){}",
    2908             :     "async(){}",
    2909             :     "*get() {}",
    2910             :     "*set() {}",
    2911             :     "*static() {}",
    2912             :     "*async(){}",
    2913             :     "get : 0",
    2914             :     "set : 0",
    2915             :     "static : 0",
    2916             :     "async : 0",
    2917             :     // Keywords, future reserved and strict future reserved are also allowed as
    2918             :     // property names.
    2919             :     "if: 4",
    2920             :     "interface: 5",
    2921             :     "super: 6",
    2922             :     "eval: 7",
    2923             :     "arguments: 8",
    2924             :     "async x(){}",
    2925             :     "async 0(){}",
    2926             :     "async get(){}",
    2927             :     "async set(){}",
    2928             :     "async static(){}",
    2929             :     "async async(){}",
    2930             :     "async : 0",
    2931             :     "async(){}",
    2932             :     "*async(){}",
    2933             :     nullptr
    2934           5 :   };
    2935             :   // clang-format on
    2936             : 
    2937           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    2938           5 : }
    2939             : 
    2940             : 
    2941       28342 : TEST(TooManyArguments) {
    2942           5 :   const char* context_data[][2] = {{"foo(", "0)"}, {nullptr, nullptr}};
    2943             : 
    2944             :   using v8::internal::Code;
    2945             :   char statement[Code::kMaxArguments * 2 + 1];
    2946      327675 :   for (int i = 0; i < Code::kMaxArguments; ++i) {
    2947      327670 :     statement[2 * i] = '0';
    2948      327670 :     statement[2 * i + 1] = ',';
    2949             :   }
    2950           5 :   statement[Code::kMaxArguments * 2] = 0;
    2951             : 
    2952           5 :   const char* statement_data[] = {statement, nullptr};
    2953             : 
    2954             :   // The test is quite slow, so run it with a reduced set of flags.
    2955             :   static const ParserFlag empty_flags[] = {kAllowLazy};
    2956           5 :   RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
    2957           5 : }
    2958             : 
    2959             : 
    2960       28342 : TEST(StrictDelete) {
    2961             :   // "delete <Identifier>" is not allowed in strict mode.
    2962             :   const char* strict_context_data[][2] = {{"\"use strict\"; ", ""},
    2963           5 :                                           {nullptr, nullptr}};
    2964             : 
    2965           5 :   const char* sloppy_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    2966             : 
    2967             :   // These are errors in the strict mode.
    2968             :   const char* sloppy_statement_data[] = {"delete foo;",       "delete foo + 1;",
    2969             :                                          "delete (foo);",     "delete eval;",
    2970           5 :                                          "delete interface;", nullptr};
    2971             : 
    2972             :   // These are always OK
    2973             :   const char* good_statement_data[] = {"delete this;",
    2974             :                                        "delete 1;",
    2975             :                                        "delete 1 + 2;",
    2976             :                                        "delete foo();",
    2977             :                                        "delete foo.bar;",
    2978             :                                        "delete foo[bar];",
    2979             :                                        "delete foo--;",
    2980             :                                        "delete --foo;",
    2981             :                                        "delete new foo();",
    2982             :                                        "delete new foo(bar);",
    2983           5 :                                        nullptr};
    2984             : 
    2985             :   // These are always errors
    2986           5 :   const char* bad_statement_data[] = {"delete if;", nullptr};
    2987             : 
    2988           5 :   RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
    2989           5 :   RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
    2990             : 
    2991           5 :   RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
    2992           5 :   RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
    2993             : 
    2994           5 :   RunParserSyncTest(strict_context_data, bad_statement_data, kError);
    2995           5 :   RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
    2996           5 : }
    2997             : 
    2998             : 
    2999       28342 : TEST(NoErrorsDeclsInCase) {
    3000             :   const char* context_data[][2] = {
    3001             :     {"'use strict'; switch(x) { case 1:", "}"},
    3002             :     {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
    3003             :     {"'use strict'; switch(x) { case 1: case 2:", "}"},
    3004             :     {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
    3005             :     {"'use strict'; switch(x) { default:", "}"},
    3006             :     {"function foo() {'use strict'; switch(x) { default:", "}}"},
    3007             :     {"'use strict'; switch(x) { case 1: default:", "}"},
    3008             :     {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
    3009             :     { nullptr, nullptr }
    3010           5 :   };
    3011             : 
    3012             :   const char* statement_data[] = {
    3013             :     "function f() { }",
    3014             :     "class C { }",
    3015             :     "class C extends Q {}",
    3016             :     "function f() { } class C {}",
    3017             :     "function f() { }; class C {}",
    3018             :     "class C {}; function f() {}",
    3019             :     nullptr
    3020           5 :   };
    3021             : 
    3022           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    3023           5 : }
    3024             : 
    3025             : 
    3026       28342 : TEST(InvalidLeftHandSide) {
    3027             :   const char* assignment_context_data[][2] = {
    3028           5 :       {"", " = 1;"}, {"\"use strict\"; ", " = 1;"}, {nullptr, nullptr}};
    3029             : 
    3030             :   const char* prefix_context_data[][2] = {
    3031             :       {"++", ";"}, {"\"use strict\"; ++", ";"}, {nullptr, nullptr},
    3032           5 :   };
    3033             : 
    3034             :   const char* postfix_context_data[][2] = {
    3035           5 :       {"", "++;"}, {"\"use strict\"; ", "++;"}, {nullptr, nullptr}};
    3036             : 
    3037             :   // Good left hand sides for assigment or prefix / postfix operations.
    3038             :   const char* good_statement_data[] = {"foo",
    3039             :                                        "foo.bar",
    3040             :                                        "foo[bar]",
    3041             :                                        "foo()[bar]",
    3042             :                                        "foo().bar",
    3043             :                                        "this.foo",
    3044             :                                        "this[foo]",
    3045             :                                        "new foo()[bar]",
    3046             :                                        "new foo().bar",
    3047             :                                        "foo()",
    3048             :                                        "foo(bar)",
    3049             :                                        "foo[bar]()",
    3050             :                                        "foo.bar()",
    3051             :                                        "this()",
    3052             :                                        "this.foo()",
    3053             :                                        "this[foo].bar()",
    3054             :                                        "this.foo[foo].bar(this)(bar)[foo]()",
    3055           5 :                                        nullptr};
    3056             : 
    3057             :   // Bad left hand sides for assigment or prefix / postfix operations.
    3058             :   const char* bad_statement_data_common[] = {
    3059             :       "2",
    3060             :       "new foo",
    3061             :       "new foo()",
    3062             :       "null",
    3063             :       "if",      // Unexpected token
    3064             :       "{x: 1}",  // Unexpected token
    3065             :       "this",
    3066             :       "\"bar\"",
    3067             :       "(foo + bar)",
    3068             :       "new new foo()[bar]",  // means: new (new foo()[bar])
    3069             :       "new new foo().bar",   // means: new (new foo()[bar])
    3070           5 :       nullptr};
    3071             : 
    3072             :   // These are not okay for assignment, but okay for prefix / postix.
    3073             :   const char* bad_statement_data_for_assignment[] = {"++foo", "foo++",
    3074           5 :                                                      "foo + bar", nullptr};
    3075             : 
    3076           5 :   RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
    3077           5 :   RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
    3078             :   RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
    3079           5 :                     kError);
    3080             : 
    3081           5 :   RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
    3082           5 :   RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
    3083             : 
    3084           5 :   RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
    3085           5 :   RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
    3086           5 : }
    3087             : 
    3088             : 
    3089       28342 : TEST(FuncNameInferrerBasic) {
    3090             :   // Tests that function names are inferred properly.
    3091           5 :   i::FLAG_allow_natives_syntax = true;
    3092           5 :   v8::Isolate* isolate = CcTest::isolate();
    3093           5 :   v8::HandleScope scope(isolate);
    3094          10 :   LocalContext env;
    3095             :   CompileRun("var foo1 = function() {}; "
    3096             :              "var foo2 = function foo3() {}; "
    3097             :              "function not_ctor() { "
    3098             :              "  var foo4 = function() {}; "
    3099             :              "  return %FunctionGetInferredName(foo4); "
    3100             :              "} "
    3101             :              "function Ctor() { "
    3102             :              "  var foo5 = function() {}; "
    3103             :              "  return %FunctionGetInferredName(foo5); "
    3104             :              "} "
    3105             :              "var obj1 = { foo6: function() {} }; "
    3106             :              "var obj2 = { 'foo7': function() {} }; "
    3107             :              "var obj3 = {}; "
    3108             :              "obj3[1] = function() {}; "
    3109             :              "var obj4 = {}; "
    3110             :              "obj4[1] = function foo8() {}; "
    3111             :              "var obj5 = {}; "
    3112             :              "obj5['foo9'] = function() {}; "
    3113             :              "var obj6 = { obj7 : { foo10: function() {} } };");
    3114           5 :   ExpectString("%FunctionGetInferredName(foo1)", "foo1");
    3115             :   // foo2 is not unnamed -> its name is not inferred.
    3116           5 :   ExpectString("%FunctionGetInferredName(foo2)", "");
    3117           5 :   ExpectString("not_ctor()", "foo4");
    3118           5 :   ExpectString("Ctor()", "Ctor.foo5");
    3119           5 :   ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
    3120           5 :   ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
    3121             :   ExpectString("%FunctionGetInferredName(obj3[1])",
    3122           5 :                "obj3.(anonymous function)");
    3123           5 :   ExpectString("%FunctionGetInferredName(obj4[1])", "");
    3124           5 :   ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
    3125          10 :   ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
    3126           5 : }
    3127             : 
    3128             : 
    3129       28342 : TEST(FuncNameInferrerTwoByte) {
    3130             :   // Tests function name inferring in cases where some parts of the inferred
    3131             :   // function name are two-byte strings.
    3132           5 :   i::FLAG_allow_natives_syntax = true;
    3133           5 :   v8::Isolate* isolate = CcTest::isolate();
    3134           5 :   v8::HandleScope scope(isolate);
    3135          10 :   LocalContext env;
    3136             :   uint16_t* two_byte_source = AsciiToTwoByteString(
    3137             :       "var obj1 = { oXj2 : { foo1: function() {} } }; "
    3138           5 :       "%FunctionGetInferredName(obj1.oXj2.foo1)");
    3139           5 :   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
    3140             :   // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
    3141           5 :   two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010D;
    3142             :   v8::Local<v8::String> source =
    3143             :       v8::String::NewFromTwoByte(isolate, two_byte_source,
    3144             :                                  v8::NewStringType::kNormal)
    3145          10 :           .ToLocalChecked();
    3146           5 :   v8::Local<v8::Value> result = CompileRun(source);
    3147           5 :   CHECK(result->IsString());
    3148             :   v8::Local<v8::String> expected_name =
    3149             :       v8::String::NewFromTwoByte(isolate, two_byte_name,
    3150             :                                  v8::NewStringType::kNormal)
    3151           5 :           .ToLocalChecked();
    3152          10 :   CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
    3153             :   i::DeleteArray(two_byte_source);
    3154           5 :   i::DeleteArray(two_byte_name);
    3155           5 : }
    3156             : 
    3157             : 
    3158       28342 : TEST(FuncNameInferrerEscaped) {
    3159             :   // The same as FuncNameInferrerTwoByte, except that we express the two-byte
    3160             :   // character as a Unicode escape.
    3161           5 :   i::FLAG_allow_natives_syntax = true;
    3162           5 :   v8::Isolate* isolate = CcTest::isolate();
    3163           5 :   v8::HandleScope scope(isolate);
    3164          10 :   LocalContext env;
    3165             :   uint16_t* two_byte_source = AsciiToTwoByteString(
    3166             :       "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
    3167           5 :       "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
    3168           5 :   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
    3169             :   // Fix to correspond to the non-ASCII name in two_byte_source.
    3170           5 :   two_byte_name[6] = 0x010D;
    3171             :   v8::Local<v8::String> source =
    3172             :       v8::String::NewFromTwoByte(isolate, two_byte_source,
    3173             :                                  v8::NewStringType::kNormal)
    3174          10 :           .ToLocalChecked();
    3175           5 :   v8::Local<v8::Value> result = CompileRun(source);
    3176           5 :   CHECK(result->IsString());
    3177             :   v8::Local<v8::String> expected_name =
    3178             :       v8::String::NewFromTwoByte(isolate, two_byte_name,
    3179             :                                  v8::NewStringType::kNormal)
    3180           5 :           .ToLocalChecked();
    3181          10 :   CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
    3182             :   i::DeleteArray(two_byte_source);
    3183           5 :   i::DeleteArray(two_byte_name);
    3184           5 : }
    3185             : 
    3186             : 
    3187       28342 : TEST(RegressionLazyFunctionWithErrorWithArg) {
    3188             :   // Test only applies when lazy parsing.
    3189           5 :   if (!i::FLAG_lazy) return;
    3190             : 
    3191             :   // The bug occurred when a lazy function had an error which requires a
    3192             :   // parameter (such as "unknown label" here). The error message was processed
    3193             :   // before the AstValueFactory containing the error message string was
    3194             :   // internalized.
    3195           5 :   v8::Isolate* isolate = CcTest::isolate();
    3196           5 :   v8::HandleScope scope(isolate);
    3197          10 :   LocalContext env;
    3198           5 :   i::FLAG_lazy = true;
    3199             :   CompileRun("function this_is_lazy() {\n"
    3200             :              "  break p;\n"
    3201             :              "}\n"
    3202           5 :              "this_is_lazy();\n");
    3203             : }
    3204             : 
    3205             : 
    3206       28342 : TEST(SerializationOfMaybeAssignmentFlag) {
    3207           5 :   i::Isolate* isolate = CcTest::i_isolate();
    3208             :   i::Factory* factory = isolate->factory();
    3209             :   i::HandleScope scope(isolate);
    3210          10 :   LocalContext env;
    3211             : 
    3212             :   const char* src =
    3213             :       "function h() {"
    3214             :       "  var result = [];"
    3215             :       "  function f() {"
    3216             :       "    result.push(2);"
    3217             :       "  }"
    3218             :       "  function assertResult(r) {"
    3219             :       "    f();"
    3220             :       "    result = [];"
    3221             :       "  }"
    3222             :       "  assertResult([2]);"
    3223             :       "  assertResult([2]);"
    3224             :       "  return f;"
    3225             :       "};"
    3226             :       "h();";
    3227             : 
    3228           5 :   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
    3229           5 :   i::SNPrintF(program, "%s", src);
    3230           5 :   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
    3231          10 :   source->PrintOn(stdout);
    3232             :   printf("\n");
    3233          10 :   i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
    3234             :   v8::Local<v8::Value> v = CompileRun(src);
    3235           5 :   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
    3236           5 :   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
    3237           5 :   i::Context context = f->context();
    3238             :   i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
    3239          10 :                          isolate->heap()->HashSeed());
    3240          10 :   const i::AstRawString* name = avf.GetOneByteString("result");
    3241           5 :   avf.Internalize(isolate);
    3242             :   i::Handle<i::String> str = name->string();
    3243          10 :   CHECK(str->IsInternalizedString());
    3244             :   i::DeclarationScope* script_scope =
    3245           5 :       new (&zone) i::DeclarationScope(&zone, &avf);
    3246             :   i::Scope* s = i::Scope::DeserializeScopeChain(
    3247             :       isolate, &zone, context->scope_info(), script_scope, &avf,
    3248           5 :       i::Scope::DeserializationMode::kIncludingVariables);
    3249           5 :   CHECK(s != script_scope);
    3250           5 :   CHECK_NOT_NULL(name);
    3251             : 
    3252             :   // Get result from h's function context (that is f's context)
    3253           5 :   i::Variable* var = s->LookupForTesting(name);
    3254             : 
    3255           5 :   CHECK_NOT_NULL(var);
    3256             :   // Maybe assigned should survive deserialization
    3257           5 :   CHECK_EQ(var->maybe_assigned(), i::kMaybeAssigned);
    3258             :   // TODO(sigurds) Figure out if is_used should survive context serialization.
    3259           5 : }
    3260             : 
    3261             : 
    3262       28342 : TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
    3263          10 :   i::Isolate* isolate = CcTest::i_isolate();
    3264             :   i::Factory* factory = isolate->factory();
    3265             :   i::HandleScope scope(isolate);
    3266          10 :   LocalContext env;
    3267             : 
    3268             :   const char* src =
    3269             :       "function f(x) {"
    3270             :       "    var a = arguments;"
    3271             :       "    function g(i) {"
    3272             :       "      ++a[0];"
    3273             :       "    };"
    3274             :       "    return g;"
    3275             :       "  }"
    3276             :       "f(0);";
    3277             : 
    3278           5 :   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
    3279           5 :   i::SNPrintF(program, "%s", src);
    3280           5 :   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
    3281          10 :   source->PrintOn(stdout);
    3282             :   printf("\n");
    3283          10 :   i::Zone zone(isolate->allocator(), ZONE_NAME);
    3284             :   v8::Local<v8::Value> v = CompileRun(src);
    3285           5 :   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
    3286           5 :   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
    3287           5 :   i::Context context = f->context();
    3288             :   i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
    3289          10 :                          isolate->heap()->HashSeed());
    3290           5 :   const i::AstRawString* name_x = avf.GetOneByteString("x");
    3291           5 :   avf.Internalize(isolate);
    3292             : 
    3293             :   i::DeclarationScope* script_scope =
    3294           5 :       new (&zone) i::DeclarationScope(&zone, &avf);
    3295             :   i::Scope* s = i::Scope::DeserializeScopeChain(
    3296             :       isolate, &zone, context->scope_info(), script_scope, &avf,
    3297           5 :       i::Scope::DeserializationMode::kIncludingVariables);
    3298           5 :   CHECK(s != script_scope);
    3299             : 
    3300             :   // Get result from f's function context (that is g's outer context)
    3301           5 :   i::Variable* var_x = s->LookupForTesting(name_x);
    3302           5 :   CHECK_NOT_NULL(var_x);
    3303           5 :   CHECK_EQ(var_x->maybe_assigned(), i::kMaybeAssigned);
    3304           5 : }
    3305             : 
    3306             : 
    3307       28342 : TEST(InnerAssignment) {
    3308             :   i::Isolate* isolate = CcTest::i_isolate();
    3309             :   i::Factory* factory = isolate->factory();
    3310             :   i::HandleScope scope(isolate);
    3311          10 :   LocalContext env;
    3312             : 
    3313             :   const char* prefix = "function f() {";
    3314             :   const char* midfix = " function g() {";
    3315             :   const char* suffix = "}}; f";
    3316             :   struct {
    3317             :     const char* source;
    3318             :     bool assigned;
    3319             :     bool strict;
    3320             :   } outers[] = {
    3321             :       // Actual assignments.
    3322             :       {"var x; var x = 5;", true, false},
    3323             :       {"var x; { var x = 5; }", true, false},
    3324             :       {"'use strict'; let x; x = 6;", true, true},
    3325             :       {"var x = 5; function x() {}", true, false},
    3326             :       {"var x = 4; var x = 5;", true, false},
    3327             :       {"var [x, x] = [4, 5];", true, false},
    3328             :       {"var x; [x, x] = [4, 5];", true, false},
    3329             :       {"var {a: x, b: x} = {a: 4, b: 5};", true, false},
    3330             :       {"var x = {a: 4, b: (x = 5)};", true, false},
    3331             :       {"var {x=1} = {a: 4, b: (x = 5)};", true, false},
    3332             :       {"var {x} = {x: 4, b: (x = 5)};", true, false},
    3333             :       // Actual non-assignments.
    3334             :       {"var x;", false, false},
    3335             :       {"var x = 5;", false, false},
    3336             :       {"'use strict'; let x;", false, true},
    3337             :       {"'use strict'; let x = 6;", false, true},
    3338             :       {"'use strict'; var x = 0; { let x = 6; }", false, true},
    3339             :       {"'use strict'; var x = 0; { let x; x = 6; }", false, true},
    3340             :       {"'use strict'; let x = 0; { let x = 6; }", false, true},
    3341             :       {"'use strict'; let x = 0; { let x; x = 6; }", false, true},
    3342             :       {"var x; try {} catch (x) { x = 5; }", false, false},
    3343             :       {"function x() {}", false, false},
    3344             :       // Eval approximation.
    3345             :       {"var x; eval('');", true, false},
    3346             :       {"eval(''); var x;", true, false},
    3347             :       {"'use strict'; let x; eval('');", true, true},
    3348             :       {"'use strict'; eval(''); let x;", true, true},
    3349             :       // Non-assignments not recognized, because the analysis is approximative.
    3350             :       {"var x; var x;", true, false},
    3351             :       {"var x = 5; var x;", true, false},
    3352             :       {"var x; { var x; }", true, false},
    3353             :       {"var x; function x() {}", true, false},
    3354             :       {"function x() {}; var x;", true, false},
    3355             :       {"var x; try {} catch (x) { var x = 5; }", true, false},
    3356           5 :   };
    3357             : 
    3358             :   // We set allow_error_in_inner_function to true in cases where our handling of
    3359             :   // assigned variables in lazy inner functions is currently overly pessimistic.
    3360             :   // FIXME(marja): remove it when no longer needed.
    3361             :   struct {
    3362             :     const char* source;
    3363             :     bool assigned;
    3364             :     bool with;
    3365             :     bool allow_error_in_inner_function;
    3366             :   } inners[] = {
    3367             :       // Actual assignments.
    3368             :       {"x = 1;", true, false, false},
    3369             :       {"x++;", true, false, false},
    3370             :       {"++x;", true, false, false},
    3371             :       {"x--;", true, false, false},
    3372             :       {"--x;", true, false, false},
    3373             :       {"{ x = 1; }", true, false, false},
    3374             :       {"'use strict'; { let x; }; x = 0;", true, false, false},
    3375             :       {"'use strict'; { const x = 1; }; x = 0;", true, false, false},
    3376             :       {"'use strict'; { function x() {} }; x = 0;", true, false, false},
    3377             :       {"with ({}) { x = 1; }", true, true, false},
    3378             :       {"eval('');", true, false, false},
    3379             :       {"'use strict'; { let y; eval('') }", true, false, false},
    3380             :       {"function h() { x = 0; }", true, false, false},
    3381             :       {"(function() { x = 0; })", true, false, false},
    3382             :       {"(function() { x = 0; })", true, false, false},
    3383             :       {"with ({}) (function() { x = 0; })", true, true, false},
    3384             :       {"for (x of [1,2,3]) {}", true, false, false},
    3385             :       {"for (x in {a: 1}) {}", true, false, false},
    3386             :       {"for ([x] of [[1],[2],[3]]) {}", true, false, false},
    3387             :       {"for ([x] in {ab: 1}) {}", true, false, false},
    3388             :       {"for ([...x] in {ab: 1}) {}", true, false, false},
    3389             :       {"[x] = [1]", true, false, false},
    3390             :       // Actual non-assignments.
    3391             :       {"", false, false, false},
    3392             :       {"x;", false, false, false},
    3393             :       {"var x;", false, false, false},
    3394             :       {"var x = 8;", false, false, false},
    3395             :       {"var x; x = 8;", false, false, false},
    3396             :       {"'use strict'; let x;", false, false, false},
    3397             :       {"'use strict'; let x = 8;", false, false, false},
    3398             :       {"'use strict'; let x; x = 8;", false, false, false},
    3399             :       {"'use strict'; const x = 8;", false, false, false},
    3400             :       {"function x() {}", false, false, false},
    3401             :       {"function x() { x = 0; }", false, false, true},
    3402             :       {"function h(x) { x = 0; }", false, false, false},
    3403             :       {"'use strict'; { let x; x = 0; }", false, false, false},
    3404             :       {"{ var x; }; x = 0;", false, false, false},
    3405             :       {"with ({}) {}", false, true, false},
    3406             :       {"var x; { with ({}) { x = 1; } }", false, true, false},
    3407             :       {"try {} catch(x) { x = 0; }", false, false, true},
    3408             :       {"try {} catch(x) { with ({}) { x = 1; } }", false, true, true},
    3409             :       // Eval approximation.
    3410             :       {"eval('');", true, false, false},
    3411             :       {"function h() { eval(''); }", true, false, false},
    3412             :       {"(function() { eval(''); })", true, false, false},
    3413             :       // Shadowing not recognized because of eval approximation.
    3414             :       {"var x; eval('');", true, false, false},
    3415             :       {"'use strict'; let x; eval('');", true, false, false},
    3416             :       {"try {} catch(x) { eval(''); }", true, false, false},
    3417             :       {"function x() { eval(''); }", true, false, false},
    3418             :       {"(function(x) { eval(''); })", true, false, false},
    3419           5 :   };
    3420             : 
    3421           5 :   int prefix_len = Utf8LengthHelper(prefix);
    3422           5 :   int midfix_len = Utf8LengthHelper(midfix);
    3423           5 :   int suffix_len = Utf8LengthHelper(suffix);
    3424         160 :   for (unsigned i = 0; i < arraysize(outers); ++i) {
    3425         155 :     const char* outer = outers[i].source;
    3426         155 :     int outer_len = Utf8LengthHelper(outer);
    3427        7595 :     for (unsigned j = 0; j < arraysize(inners); ++j) {
    3428       14880 :       for (unsigned lazy = 0; lazy < 2; ++lazy) {
    3429       15330 :         if (outers[i].strict && inners[j].with) continue;
    3430       14430 :         const char* inner = inners[j].source;
    3431       14430 :         int inner_len = Utf8LengthHelper(inner);
    3432             : 
    3433       14430 :         int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len;
    3434       14430 :         i::ScopedVector<char> program(len + 1);
    3435             : 
    3436             :         i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner,
    3437       14430 :                     suffix);
    3438             : 
    3439             :         std::unique_ptr<i::ParseInfo> info;
    3440       14430 :         if (lazy) {
    3441             :           printf("%s\n", program.start());
    3442             :           v8::Local<v8::Value> v = CompileRun(program.start());
    3443        7215 :           i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
    3444        7215 :           i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
    3445             :           i::Handle<i::SharedFunctionInfo> shared =
    3446       14430 :               i::handle(f->shared(), isolate);
    3447       14430 :           info =
    3448        7215 :               std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
    3449        7215 :           CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
    3450             :         } else {
    3451             :           i::Handle<i::String> source =
    3452        7215 :               factory->InternalizeUtf8String(program.start());
    3453       14430 :           source->PrintOn(stdout);
    3454             :           printf("\n");
    3455        7215 :           i::Handle<i::Script> script = factory->NewScript(source);
    3456       14430 :           info =
    3457        7215 :               std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
    3458             :           info->set_allow_lazy_parsing(false);
    3459        7215 :           CHECK(i::parsing::ParseProgram(info.get(), isolate));
    3460             :         }
    3461       14430 :         CHECK(i::Compiler::Analyze(info.get()));
    3462       14430 :         CHECK_NOT_NULL(info->literal());
    3463             : 
    3464       21645 :         i::Scope* scope = info->literal()->scope();
    3465       14430 :         if (!lazy) {
    3466             :           scope = scope->inner_scope();
    3467             :         }
    3468             :         DCHECK_NOT_NULL(scope);
    3469             :         DCHECK_NULL(scope->sibling());
    3470             :         DCHECK(scope->is_function_scope());
    3471             :         const i::AstRawString* var_name =
    3472       14430 :             info->ast_value_factory()->GetOneByteString("x");
    3473       14430 :         i::Variable* var = scope->LookupForTesting(var_name);
    3474       14430 :         bool expected = outers[i].assigned || inners[j].assigned;
    3475       14430 :         CHECK_NOT_NULL(var);
    3476       14430 :         CHECK(var->is_used() || !expected);
    3477       14430 :         bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
    3478       14430 :         CHECK(is_maybe_assigned == expected ||
    3479             :               (is_maybe_assigned && inners[j].allow_error_in_inner_function));
    3480             :       }
    3481             :     }
    3482             :   }
    3483           5 : }
    3484             : 
    3485       28342 : TEST(MaybeAssignedParameters) {
    3486             :   i::Isolate* isolate = CcTest::i_isolate();
    3487             :   i::HandleScope scope(isolate);
    3488          10 :   LocalContext env;
    3489             : 
    3490             :   struct {
    3491             :     bool arg_assigned;
    3492             :     const char* source;
    3493             :   } tests[] = {
    3494             :       {false, "function f(arg) {}"},
    3495             :       {false, "function f(arg) {g(arg)}"},
    3496             :       {false, "function f(arg) {function h() { g(arg) }; h()}"},
    3497             :       {false, "function f(arg) {function h() { g(arg) }; return h}"},
    3498             :       {false, "function f(arg=1) {}"},
    3499             :       {false, "function f(arg=1) {g(arg)}"},
    3500             :       {false, "function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)}"},
    3501             :       {false,
    3502             :        "function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)}"},
    3503             :       {false,
    3504             :        "function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)}"},
    3505             :       {false, "function f(...arg) {g(arg); arguments[0] = 42; g(arg)}"},
    3506             :       {false,
    3507             :        "function f(arg) {g(arg); g(function() {arguments[0] = 42}); g(arg)}"},
    3508             : 
    3509             :       // strict arguments object
    3510             :       {false, "function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)}"},
    3511             :       {false, "function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)}"},
    3512             :       {false, "function f(arg=1) {g(arg); arguments[0] = 42; g(arg)}"},
    3513             :       {false,
    3514             :        "function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)}"},
    3515             :       {false, "function f(arg) {g(arg); f.arguments[0] = 42; g(arg)}"},
    3516             :       {false, "function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)}"},
    3517             : 
    3518             :       {true, "function f(arg) {g(arg); arg = 42; g(arg)}"},
    3519             :       {true, "function f(arg) {g(arg); eval('arg = 42'); g(arg)}"},
    3520             :       {true, "function f(arg) {g(arg); var arg = 42; g(arg)}"},
    3521             :       {true, "function f(arg, x=1) {g(arg); arg = 42; g(arg)}"},
    3522             :       {true, "function f(arg, ...x) {g(arg); arg = 42; g(arg)}"},
    3523             :       {true, "function f(arg=1) {g(arg); arg = 42; g(arg)}"},
    3524             :       {true, "function f(arg) {'use strict'; g(arg); arg = 42; g(arg)}"},
    3525             :       {true, "function f(arg, {a=(g(arg), arg=42)}) {g(arg)}"},
    3526             :       {true, "function f(arg) {g(arg); g(function() {arg = 42}); g(arg)}"},
    3527             :       {true,
    3528             :        "function f(arg) {g(arg); g(function() {eval('arg = 42')}); g(arg)}"},
    3529             :       {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"},
    3530             :       {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"},
    3531             :       {true, "function f(...arg) {g(arg); eval('arg = 42'); g(arg)}"},
    3532             : 
    3533             :       // sloppy arguments object
    3534             :       {true, "function f(arg) {g(arg); arguments[0] = 42; g(arg)}"},
    3535             :       {true, "function f(arg) {g(arg); h(arguments); g(arg)}"},
    3536             :       {true,
    3537             :        "function f(arg) {((args) => {arguments[0] = 42})(arguments); "
    3538             :        "g(arg)}"},
    3539             :       {true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"},
    3540             :       {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
    3541           5 :   };
    3542             : 
    3543             :   const char* suffix = "; f";
    3544             : 
    3545         180 :   for (unsigned i = 0; i < arraysize(tests); ++i) {
    3546         175 :     bool assigned = tests[i].arg_assigned;
    3547         175 :     const char* source = tests[i].source;
    3548         525 :     for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) {
    3549         700 :       i::ScopedVector<char> program(Utf8LengthHelper(source) +
    3550         700 :                                     Utf8LengthHelper(suffix) + 1);
    3551         350 :       i::SNPrintF(program, "%s%s", source, suffix);
    3552             :       std::unique_ptr<i::ParseInfo> info;
    3553             :       printf("%s\n", program.start());
    3554             :       v8::Local<v8::Value> v = CompileRun(program.start());
    3555         350 :       i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
    3556         350 :       i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
    3557         700 :       i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
    3558         350 :       info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
    3559             :       info->set_allow_lazy_parsing(allow_lazy);
    3560         350 :       CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
    3561         350 :       CHECK(i::Compiler::Analyze(info.get()));
    3562         350 :       CHECK_NOT_NULL(info->literal());
    3563             : 
    3564        1050 :       i::Scope* scope = info->literal()->scope();
    3565         700 :       CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
    3566         350 :       CHECK_NULL(scope->sibling());
    3567         350 :       CHECK(scope->is_function_scope());
    3568             :       const i::AstRawString* var_name =
    3569         350 :           info->ast_value_factory()->GetOneByteString("arg");
    3570         350 :       i::Variable* var = scope->LookupForTesting(var_name);
    3571         350 :       CHECK(var->is_used() || !assigned);
    3572         350 :       bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
    3573         350 :       CHECK_EQ(is_maybe_assigned, assigned);
    3574             :     }
    3575             :   }
    3576           5 : }
    3577             : 
    3578       65800 : struct Input {
    3579             :   bool assigned;
    3580             :   std::string source;
    3581             :   std::vector<unsigned> location;  // "Directions" to the relevant scope.
    3582             : };
    3583             : 
    3584       15000 : static void TestMaybeAssigned(Input input, const char* variable, bool module,
    3585             :                               bool allow_lazy_parsing) {
    3586             :   i::Isolate* isolate = CcTest::i_isolate();
    3587             :   i::Factory* factory = isolate->factory();
    3588             :   i::Handle<i::String> string =
    3589       15000 :       factory->InternalizeUtf8String(input.source.c_str());
    3590       30000 :   string->PrintOn(stdout);
    3591             :   printf("\n");
    3592       15000 :   i::Handle<i::Script> script = factory->NewScript(string);
    3593             : 
    3594             :   std::unique_ptr<i::ParseInfo> info;
    3595       15000 :   info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
    3596             :   info->set_module(module);
    3597             :   info->set_allow_lazy_parsing(allow_lazy_parsing);
    3598             : 
    3599       15000 :   CHECK(i::parsing::ParseProgram(info.get(), isolate));
    3600       15000 :   CHECK(i::Compiler::Analyze(info.get()));
    3601             : 
    3602       15000 :   CHECK_NOT_NULL(info->literal());
    3603       45000 :   i::Scope* scope = info->literal()->scope();
    3604       30000 :   CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
    3605       15000 :   CHECK_NULL(scope->sibling());
    3606       30000 :   CHECK(module ? scope->is_module_scope() : scope->is_script_scope());
    3607             : 
    3608       15000 :   i::Variable* var;
    3609             :   {
    3610             :     // Find the variable.
    3611       15000 :     scope = i::ScopeTestHelper::FindScope(scope, input.location);
    3612             :     const i::AstRawString* var_name =
    3613       15000 :         info->ast_value_factory()->GetOneByteString(variable);
    3614             :     var = scope->LookupForTesting(var_name);
    3615             :   }
    3616             : 
    3617       15000 :   CHECK_NOT_NULL(var);
    3618       15000 :   CHECK(var->is_used());
    3619             :   STATIC_ASSERT(true == i::kMaybeAssigned);
    3620       15000 :   CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
    3621       15000 : }
    3622             : 
    3623        4200 : static Input wrap(Input input) {
    3624             :   Input result;
    3625        4200 :   result.assigned = input.assigned;
    3626       16800 :   result.source = "function WRAPPED() { " + input.source + " }";
    3627        8400 :   result.location.push_back(0);
    3628       11780 :   for (auto n : input.location) {
    3629        3380 :     result.location.push_back(n);
    3630             :   }
    3631        4200 :   return result;
    3632             : }
    3633             : 
    3634       28342 : TEST(MaybeAssignedInsideLoop) {
    3635             :   i::Isolate* isolate = CcTest::i_isolate();
    3636             :   i::HandleScope scope(isolate);
    3637          10 :   LocalContext env;
    3638             : 
    3639             :   std::vector<unsigned> top;  // Can't use {} in initializers below.
    3640             : 
    3641             :   Input module_and_script_tests[] = {
    3642             :       {true, "for (j=x; j<10; ++j) { foo = j }", top},
    3643             :       {true, "for (j=x; j<10; ++j) { [foo] = [j] }", top},
    3644             :       {true, "for (j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3645             :       {true, "for (j=x; j<10; ++j) { var foo = j }", top},
    3646             :       {true, "for (j=x; j<10; ++j) { var [foo] = [j] }", top},
    3647             :       {true, "for (j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3648             :       {true, "for (j=x; j<10; ++j) { var foo; foo = j }", top},
    3649             :       {true, "for (j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3650             :       {true, "for (j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3651             :       {true, "for (j=x; j<10; ++j) { let foo; foo = j }", {0}},
    3652             :       {true, "for (j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
    3653             :       {true, "for (j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
    3654             :       {false, "for (j=x; j<10; ++j) { let foo = j }", {0}},
    3655             :       {false, "for (j=x; j<10; ++j) { let [foo] = [j] }", {0}},
    3656             :       {false, "for (j=x; j<10; ++j) { const foo = j }", {0}},
    3657             :       {false, "for (j=x; j<10; ++j) { const [foo] = [j] }", {0}},
    3658             :       {false, "for (j=x; j<10; ++j) { function foo() {return j} }", {0}},
    3659             : 
    3660             :       {true, "for ({j}=x; j<10; ++j) { foo = j }", top},
    3661             :       {true, "for ({j}=x; j<10; ++j) { [foo] = [j] }", top},
    3662             :       {true, "for ({j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3663             :       {true, "for ({j}=x; j<10; ++j) { var foo = j }", top},
    3664             :       {true, "for ({j}=x; j<10; ++j) { var [foo] = [j] }", top},
    3665             :       {true, "for ({j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3666             :       {true, "for ({j}=x; j<10; ++j) { var foo; foo = j }", top},
    3667             :       {true, "for ({j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3668             :       {true, "for ({j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3669             :       {true, "for ({j}=x; j<10; ++j) { let foo; foo = j }", {0}},
    3670             :       {true, "for ({j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
    3671             :       {true, "for ({j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
    3672             :       {false, "for ({j}=x; j<10; ++j) { let foo = j }", {0}},
    3673             :       {false, "for ({j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
    3674             :       {false, "for ({j}=x; j<10; ++j) { const foo = j }", {0}},
    3675             :       {false, "for ({j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
    3676             :       {false, "for ({j}=x; j<10; ++j) { function foo() {return j} }", {0}},
    3677             : 
    3678             :       {true, "for (var j=x; j<10; ++j) { foo = j }", top},
    3679             :       {true, "for (var j=x; j<10; ++j) { [foo] = [j] }", top},
    3680             :       {true, "for (var j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3681             :       {true, "for (var j=x; j<10; ++j) { var foo = j }", top},
    3682             :       {true, "for (var j=x; j<10; ++j) { var [foo] = [j] }", top},
    3683             :       {true, "for (var j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3684             :       {true, "for (var j=x; j<10; ++j) { var foo; foo = j }", top},
    3685             :       {true, "for (var j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3686             :       {true, "for (var j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3687             :       {true, "for (var j=x; j<10; ++j) { let foo; foo = j }", {0}},
    3688             :       {true, "for (var j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
    3689             :       {true, "for (var j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
    3690             :       {false, "for (var j=x; j<10; ++j) { let foo = j }", {0}},
    3691             :       {false, "for (var j=x; j<10; ++j) { let [foo] = [j] }", {0}},
    3692             :       {false, "for (var j=x; j<10; ++j) { const foo = j }", {0}},
    3693             :       {false, "for (var j=x; j<10; ++j) { const [foo] = [j] }", {0}},
    3694             :       {false, "for (var j=x; j<10; ++j) { function foo() {return j} }", {0}},
    3695             : 
    3696             :       {true, "for (var {j}=x; j<10; ++j) { foo = j }", top},
    3697             :       {true, "for (var {j}=x; j<10; ++j) { [foo] = [j] }", top},
    3698             :       {true, "for (var {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3699             :       {true, "for (var {j}=x; j<10; ++j) { var foo = j }", top},
    3700             :       {true, "for (var {j}=x; j<10; ++j) { var [foo] = [j] }", top},
    3701             :       {true, "for (var {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3702             :       {true, "for (var {j}=x; j<10; ++j) { var foo; foo = j }", top},
    3703             :       {true, "for (var {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3704             :       {true, "for (var {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3705             :       {true, "for (var {j}=x; j<10; ++j) { let foo; foo = j }", {0}},
    3706             :       {true, "for (var {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
    3707             :       {true, "for (var {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
    3708             :       {false, "for (var {j}=x; j<10; ++j) { let foo = j }", {0}},
    3709             :       {false, "for (var {j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
    3710             :       {false, "for (var {j}=x; j<10; ++j) { const foo = j }", {0}},
    3711             :       {false, "for (var {j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
    3712             :       {false, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", {0}},
    3713             : 
    3714             :       {true, "for (let j=x; j<10; ++j) { foo = j }", top},
    3715             :       {true, "for (let j=x; j<10; ++j) { [foo] = [j] }", top},
    3716             :       {true, "for (let j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3717             :       {true, "for (let j=x; j<10; ++j) { var foo = j }", top},
    3718             :       {true, "for (let j=x; j<10; ++j) { var [foo] = [j] }", top},
    3719             :       {true, "for (let j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3720             :       {true, "for (let j=x; j<10; ++j) { var foo; foo = j }", top},
    3721             :       {true, "for (let j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3722             :       {true, "for (let j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3723             :       {true, "for (let j=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
    3724             :       {true, "for (let j=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
    3725             :       {true, "for (let j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0, 0}},
    3726             :       {false, "for (let j=x; j<10; ++j) { let foo = j }", {0, 0}},
    3727             :       {false, "for (let j=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
    3728             :       {false, "for (let j=x; j<10; ++j) { const foo = j }", {0, 0}},
    3729             :       {false, "for (let j=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
    3730             :       {false,
    3731             :        "for (let j=x; j<10; ++j) { function foo() {return j} }",
    3732             :        {0, 0, 0}},
    3733             : 
    3734             :       {true, "for (let {j}=x; j<10; ++j) { foo = j }", top},
    3735             :       {true, "for (let {j}=x; j<10; ++j) { [foo] = [j] }", top},
    3736             :       {true, "for (let {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
    3737             :       {true, "for (let {j}=x; j<10; ++j) { var foo = j }", top},
    3738             :       {true, "for (let {j}=x; j<10; ++j) { var [foo] = [j] }", top},
    3739             :       {true, "for (let {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
    3740             :       {true, "for (let {j}=x; j<10; ++j) { var foo; foo = j }", top},
    3741             :       {true, "for (let {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
    3742             :       {true, "for (let {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
    3743             :       {true, "for (let {j}=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
    3744             :       {true, "for (let {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
    3745             :       {true,
    3746             :        "for (let {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }",
    3747             :        {0, 0}},
    3748             :       {false, "for (let {j}=x; j<10; ++j) { let foo = j }", {0, 0}},
    3749             :       {false, "for (let {j}=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
    3750             :       {false, "for (let {j}=x; j<10; ++j) { const foo = j }", {0, 0}},
    3751             :       {false, "for (let {j}=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
    3752             :       {false,
    3753             :        "for (let {j}=x; j<10; ++j) { function foo(){return j} }",
    3754             :        {0, 0, 0}},
    3755             : 
    3756             :       {true, "for (j of x) { foo = j }", top},
    3757             :       {true, "for (j of x) { [foo] = [j] }", top},
    3758             :       {true, "for (j of x) { [[foo]=[42]] = [] }", top},
    3759             :       {true, "for (j of x) { var foo = j }", top},
    3760             :       {true, "for (j of x) { var [foo] = [j] }", top},
    3761             :       {true, "for (j of x) { var [[foo]=[42]] = [] }", top},
    3762             :       {true, "for (j of x) { var foo; foo = j }", top},
    3763             :       {true, "for (j of x) { var foo; [foo] = [j] }", top},
    3764             :       {true, "for (j of x) { var foo; [[foo]=[42]] = [] }", top},
    3765             :       {true, "for (j of x) { let foo; foo = j }", {0}},
    3766             :       {true, "for (j of x) { let foo; [foo] = [j] }", {0}},
    3767             :       {true, "for (j of x) { let foo; [[foo]=[42]] = [] }", {0}},
    3768             :       {false, "for (j of x) { let foo = j }", {0}},
    3769             :       {false, "for (j of x) { let [foo] = [j] }", {0}},
    3770             :       {false, "for (j of x) { const foo = j }", {0}},
    3771             :       {false, "for (j of x) { const [foo] = [j] }", {0}},
    3772             :       {false, "for (j of x) { function foo() {return j} }", {0}},
    3773             : 
    3774             :       {true, "for ({j} of x) { foo = j }", top},
    3775             :       {true, "for ({j} of x) { [foo] = [j] }", top},
    3776             :       {true, "for ({j} of x) { [[foo]=[42]] = [] }", top},
    3777             :       {true, "for ({j} of x) { var foo = j }", top},
    3778             :       {true, "for ({j} of x) { var [foo] = [j] }", top},
    3779             :       {true, "for ({j} of x) { var [[foo]=[42]] = [] }", top},
    3780             :       {true, "for ({j} of x) { var foo; foo = j }", top},
    3781             :       {true, "for ({j} of x) { var foo; [foo] = [j] }", top},
    3782             :       {true, "for ({j} of x) { var foo; [[foo]=[42]] = [] }", top},
    3783             :       {true, "for ({j} of x) { let foo; foo = j }", {0}},
    3784             :       {true, "for ({j} of x) { let foo; [foo] = [j] }", {0}},
    3785             :       {true, "for ({j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
    3786             :       {false, "for ({j} of x) { let foo = j }", {0}},
    3787             :       {false, "for ({j} of x) { let [foo] = [j] }", {0}},
    3788             :       {false, "for ({j} of x) { const foo = j }", {0}},
    3789             :       {false, "for ({j} of x) { const [foo] = [j] }", {0}},
    3790             :       {false, "for ({j} of x) { function foo() {return j} }", {0}},
    3791             : 
    3792             :       {true, "for (var j of x) { foo = j }", top},
    3793             :       {true, "for (var j of x) { [foo] = [j] }", top},
    3794             :       {true, "for (var j of x) { [[foo]=[42]] = [] }", top},
    3795             :       {true, "for (var j of x) { var foo = j }", top},
    3796             :       {true, "for (var j of x) { var [foo] = [j] }", top},
    3797             :       {true, "for (var j of x) { var [[foo]=[42]] = [] }", top},
    3798             :       {true, "for (var j of x) { var foo; foo = j }", top},
    3799             :       {true, "for (var j of x) { var foo; [foo] = [j] }", top},
    3800             :       {true, "for (var j of x) { var foo; [[foo]=[42]] = [] }", top},
    3801             :       {true, "for (var j of x) { let foo; foo = j }", {0}},
    3802             :       {true, "for (var j of x) { let foo; [foo] = [j] }", {0}},
    3803             :       {true, "for (var j of x) { let foo; [[foo]=[42]] = [] }", {0}},
    3804             :       {false, "for (var j of x) { let foo = j }", {0}},
    3805             :       {false, "for (var j of x) { let [foo] = [j] }", {0}},
    3806             :       {false, "for (var j of x) { const foo = j }", {0}},
    3807             :       {false, "for (var j of x) { const [foo] = [j] }", {0}},
    3808             :       {false, "for (var j of x) { function foo() {return j} }", {0}},
    3809             : 
    3810             :       {true, "for (var {j} of x) { foo = j }", top},
    3811             :       {true, "for (var {j} of x) { [foo] = [j] }", top},
    3812             :       {true, "for (var {j} of x) { [[foo]=[42]] = [] }", top},
    3813             :       {true, "for (var {j} of x) { var foo = j }", top},
    3814             :       {true, "for (var {j} of x) { var [foo] = [j] }", top},
    3815             :       {true, "for (var {j} of x) { var [[foo]=[42]] = [] }", top},
    3816             :       {true, "for (var {j} of x) { var foo; foo = j }", top},
    3817             :       {true, "for (var {j} of x) { var foo; [foo] = [j] }", top},
    3818             :       {true, "for (var {j} of x) { var foo; [[foo]=[42]] = [] }", top},
    3819             :       {true, "for (var {j} of x) { let foo; foo = j }", {0}},
    3820             :       {true, "for (var {j} of x) { let foo; [foo] = [j] }", {0}},
    3821             :       {true, "for (var {j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
    3822             :       {false, "for (var {j} of x) { let foo = j }", {0}},
    3823             :       {false, "for (var {j} of x) { let [foo] = [j] }", {0}},
    3824             :       {false, "for (var {j} of x) { const foo = j }", {0}},
    3825             :       {false, "for (var {j} of x) { const [foo] = [j] }", {0}},
    3826             :       {false, "for (var {j} of x) { function foo() {return j} }", {0}},
    3827             : 
    3828             :       {true, "for (let j of x) { foo = j }", top},
    3829             :       {true, "for (let j of x) { [foo] = [j] }", top},
    3830             :       {true, "for (let j of x) { [[foo]=[42]] = [] }", top},
    3831             :       {true, "for (let j of x) { var foo = j }", top},
    3832             :       {true, "for (let j of x) { var [foo] = [j] }", top},
    3833             :       {true, "for (let j of x) { var [[foo]=[42]] = [] }", top},
    3834             :       {true, "for (let j of x) { var foo; foo = j }", top},
    3835             :       {true, "for (let j of x) { var foo; [foo] = [j] }", top},
    3836             :       {true, "for (let j of x) { var foo; [[foo]=[42]] = [] }", top},
    3837             :       {true, "for (let j of x) { let foo; foo = j }", {0, 0, 0}},
    3838             :       {true, "for (let j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
    3839             :       {true, "for (let j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    3840             :       {false, "for (let j of x) { let foo = j }", {0, 0, 0}},
    3841             :       {false, "for (let j of x) { let [foo] = [j] }", {0, 0, 0}},
    3842             :       {false, "for (let j of x) { const foo = j }", {0, 0, 0}},
    3843             :       {false, "for (let j of x) { const [foo] = [j] }", {0, 0, 0}},
    3844             :       {false, "for (let j of x) { function foo() {return j} }", {0, 0, 0}},
    3845             : 
    3846             :       {true, "for (let {j} of x) { foo = j }", top},
    3847             :       {true, "for (let {j} of x) { [foo] = [j] }", top},
    3848             :       {true, "for (let {j} of x) { [[foo]=[42]] = [] }", top},
    3849             :       {true, "for (let {j} of x) { var foo = j }", top},
    3850             :       {true, "for (let {j} of x) { var [foo] = [j] }", top},
    3851             :       {true, "for (let {j} of x) { var [[foo]=[42]] = [] }", top},
    3852             :       {true, "for (let {j} of x) { var foo; foo = j }", top},
    3853             :       {true, "for (let {j} of x) { var foo; [foo] = [j] }", top},
    3854             :       {true, "for (let {j} of x) { var foo; [[foo]=[42]] = [] }", top},
    3855             :       {true, "for (let {j} of x) { let foo; foo = j }", {0, 0, 0}},
    3856             :       {true, "for (let {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
    3857             :       {true, "for (let {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    3858             :       {false, "for (let {j} of x) { let foo = j }", {0, 0, 0}},
    3859             :       {false, "for (let {j} of x) { let [foo] = [j] }", {0, 0, 0}},
    3860             :       {false, "for (let {j} of x) { const foo = j }", {0, 0, 0}},
    3861             :       {false, "for (let {j} of x) { const [foo] = [j] }", {0, 0, 0}},
    3862             :       {false, "for (let {j} of x) { function foo() {return j} }", {0, 0, 0}},
    3863             : 
    3864             :       {true, "for (const j of x) { foo = j }", top},
    3865             :       {true, "for (const j of x) { [foo] = [j] }", top},
    3866             :       {true, "for (const j of x) { [[foo]=[42]] = [] }", top},
    3867             :       {true, "for (const j of x) { var foo = j }", top},
    3868             :       {true, "for (const j of x) { var [foo] = [j] }", top},
    3869             :       {true, "for (const j of x) { var [[foo]=[42]] = [] }", top},
    3870             :       {true, "for (const j of x) { var foo; foo = j }", top},
    3871             :       {true, "for (const j of x) { var foo; [foo] = [j] }", top},
    3872             :       {true, "for (const j of x) { var foo; [[foo]=[42]] = [] }", top},
    3873             :       {true, "for (const j of x) { let foo; foo = j }", {0, 0, 0}},
    3874             :       {true, "for (const j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
    3875             :       {true, "for (const j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    3876             :       {false, "for (const j of x) { let foo = j }", {0, 0, 0}},
    3877             :       {false, "for (const j of x) { let [foo] = [j] }", {0, 0, 0}},
    3878             :       {false, "for (const j of x) { const foo = j }", {0, 0, 0}},
    3879             :       {false, "for (const j of x) { const [foo] = [j] }", {0, 0, 0}},
    3880             :       {false, "for (const j of x) { function foo() {return j} }", {0, 0, 0}},
    3881             : 
    3882             :       {true, "for (const {j} of x) { foo = j }", top},
    3883             :       {true, "for (const {j} of x) { [foo] = [j] }", top},
    3884             :       {true, "for (const {j} of x) { [[foo]=[42]] = [] }", top},
    3885             :       {true, "for (const {j} of x) { var foo = j }", top},
    3886             :       {true, "for (const {j} of x) { var [foo] = [j] }", top},
    3887             :       {true, "for (const {j} of x) { var [[foo]=[42]] = [] }", top},
    3888             :       {true, "for (const {j} of x) { var foo; foo = j }", top},
    3889             :       {true, "for (const {j} of x) { var foo; [foo] = [j] }", top},
    3890             :       {true, "for (const {j} of x) { var foo; [[foo]=[42]] = [] }", top},
    3891             :       {true, "for (const {j} of x) { let foo; foo = j }", {0, 0, 0}},
    3892             :       {true, "for (const {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
    3893             :       {true, "for (const {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    3894             :       {false, "for (const {j} of x) { let foo = j }", {0, 0, 0}},
    3895             :       {false, "for (const {j} of x) { let [foo] = [j] }", {0, 0, 0}},
    3896             :       {false, "for (const {j} of x) { const foo = j }", {0, 0, 0}},
    3897             :       {false, "for (const {j} of x) { const [foo] = [j] }", {0, 0, 0}},
    3898             :       {false, "for (const {j} of x) { function foo() {return j} }", {0, 0, 0}},
    3899             : 
    3900             :       {true, "for (j in x) { foo = j }", top},
    3901             :       {true, "for (j in x) { [foo] = [j] }", top},
    3902             :       {true, "for (j in x) { [[foo]=[42]] = [] }", top},
    3903             :       {true, "for (j in x) { var foo = j }", top},
    3904             :       {true, "for (j in x) { var [foo] = [j] }", top},
    3905             :       {true, "for (j in x) { var [[foo]=[42]] = [] }", top},
    3906             :       {true, "for (j in x) { var foo; foo = j }", top},
    3907             :       {true, "for (j in x) { var foo; [foo] = [j] }", top},
    3908             :       {true, "for (j in x) { var foo; [[foo]=[42]] = [] }", top},
    3909             :       {true, "for (j in x) { let foo; foo = j }", {0}},
    3910             :       {true, "for (j in x) { let foo; [foo] = [j] }", {0}},
    3911             :       {true, "for (j in x) { let foo; [[foo]=[42]] = [] }", {0}},
    3912             :       {false, "for (j in x) { let foo = j }", {0}},
    3913             :       {false, "for (j in x) { let [foo] = [j] }", {0}},
    3914             :       {false, "for (j in x) { const foo = j }", {0}},
    3915             :       {false, "for (j in x) { const [foo] = [j] }", {0}},
    3916             :       {false, "for (j in x) { function foo() {return j} }", {0}},
    3917             : 
    3918             :       {true, "for ({j} in x) { foo = j }", top},
    3919             :       {true, "for ({j} in x) { [foo] = [j] }", top},
    3920             :       {true, "for ({j} in x) { [[foo]=[42]] = [] }", top},
    3921             :       {true, "for ({j} in x) { var foo = j }", top},
    3922             :       {true, "for ({j} in x) { var [foo] = [j] }", top},
    3923             :       {true, "for ({j} in x) { var [[foo]=[42]] = [] }", top},
    3924             :       {true, "for ({j} in x) { var foo; foo = j }", top},
    3925             :       {true, "for ({j} in x) { var foo; [foo] = [j] }", top},
    3926             :       {true, "for ({j} in x) { var foo; [[foo]=[42]] = [] }", top},
    3927             :       {true, "for ({j} in x) { let foo; foo = j }", {0}},
    3928             :       {true, "for ({j} in x) { let foo; [foo] = [j] }", {0}},
    3929             :       {true, "for ({j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
    3930             :       {false, "for ({j} in x) { let foo = j }", {0}},
    3931             :       {false, "for ({j} in x) { let [foo] = [j] }", {0}},
    3932             :       {false, "for ({j} in x) { const foo = j }", {0}},
    3933             :       {false, "for ({j} in x) { const [foo] = [j] }", {0}},
    3934             :       {false, "for ({j} in x) { function foo() {return j} }", {0}},
    3935             : 
    3936             :       {true, "for (var j in x) { foo = j }", top},
    3937             :       {true, "for (var j in x) { [foo] = [j] }", top},
    3938             :       {true, "for (var j in x) { [[foo]=[42]] = [] }", top},
    3939             :       {true, "for (var j in x) { var foo = j }", top},
    3940             :       {true, "for (var j in x) { var [foo] = [j] }", top},
    3941             :       {true, "for (var j in x) { var [[foo]=[42]] = [] }", top},
    3942             :       {true, "for (var j in x) { var foo; foo = j }", top},
    3943             :       {true, "for (var j in x) { var foo; [foo] = [j] }", top},
    3944             :       {true, "for (var j in x) { var foo; [[foo]=[42]] = [] }", top},
    3945             :       {true, "for (var j in x) { let foo; foo = j }", {0}},
    3946             :       {true, "for (var j in x) { let foo; [foo] = [j] }", {0}},
    3947             :       {true, "for (var j in x) { let foo; [[foo]=[42]] = [] }", {0}},
    3948             :       {false, "for (var j in x) { let foo = j }", {0}},
    3949             :       {false, "for (var j in x) { let [foo] = [j] }", {0}},
    3950             :       {false, "for (var j in x) { const foo = j }", {0}},
    3951             :       {false, "for (var j in x) { const [foo] = [j] }", {0}},
    3952             :       {false, "for (var j in x) { function foo() {return j} }", {0}},
    3953             : 
    3954             :       {true, "for (var {j} in x) { foo = j }", top},
    3955             :       {true, "for (var {j} in x) { [foo] = [j] }", top},
    3956             :       {true, "for (var {j} in x) { [[foo]=[42]] = [] }", top},
    3957             :       {true, "for (var {j} in x) { var foo = j }", top},
    3958             :       {true, "for (var {j} in x) { var [foo] = [j] }", top},
    3959             :       {true, "for (var {j} in x) { var [[foo]=[42]] = [] }", top},
    3960             :       {true, "for (var {j} in x) { var foo; foo = j }", top},
    3961             :       {true, "for (var {j} in x) { var foo; [foo] = [j] }", top},
    3962             :       {true, "for (var {j} in x) { var foo; [[foo]=[42]] = [] }", top},
    3963             :       {true, "for (var {j} in x) { let foo; foo = j }", {0}},
    3964             :       {true, "for (var {j} in x) { let foo; [foo] = [j] }", {0}},
    3965             :       {true, "for (var {j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
    3966             :       {false, "for (var {j} in x) { let foo = j }", {0}},
    3967             :       {false, "for (var {j} in x) { let [foo] = [j] }", {0}},
    3968             :       {false, "for (var {j} in x) { const foo = j }", {0}},
    3969             :       {false, "for (var {j} in x) { const [foo] = [j] }", {0}},
    3970             :       {false, "for (var {j} in x) { function foo() {return j} }", {0}},
    3971             : 
    3972             :       {true, "for (let j in x) { foo = j }", top},
    3973             :       {true, "for (let j in x) { [foo] = [j] }", top},
    3974             :       {true, "for (let j in x) { [[foo]=[42]] = [] }", top},
    3975             :       {true, "for (let j in x) { var foo = j }", top},
    3976             :       {true, "for (let j in x) { var [foo] = [j] }", top},
    3977             :       {true, "for (let j in x) { var [[foo]=[42]] = [] }", top},
    3978             :       {true, "for (let j in x) { var foo; foo = j }", top},
    3979             :       {true, "for (let j in x) { var foo; [foo] = [j] }", top},
    3980             :       {true, "for (let j in x) { var foo; [[foo]=[42]] = [] }", top},
    3981             :       {true, "for (let j in x) { let foo; foo = j }", {0, 0, 0}},
    3982             :       {true, "for (let j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
    3983             :       {true, "for (let j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    3984             :       {false, "for (let j in x) { let foo = j }", {0, 0, 0}},
    3985             :       {false, "for (let j in x) { let [foo] = [j] }", {0, 0, 0}},
    3986             :       {false, "for (let j in x) { const foo = j }", {0, 0, 0}},
    3987             :       {false, "for (let j in x) { const [foo] = [j] }", {0, 0, 0}},
    3988             :       {false, "for (let j in x) { function foo() {return j} }", {0, 0, 0}},
    3989             : 
    3990             :       {true, "for (let {j} in x) { foo = j }", top},
    3991             :       {true, "for (let {j} in x) { [foo] = [j] }", top},
    3992             :       {true, "for (let {j} in x) { [[foo]=[42]] = [] }", top},
    3993             :       {true, "for (let {j} in x) { var foo = j }", top},
    3994             :       {true, "for (let {j} in x) { var [foo] = [j] }", top},
    3995             :       {true, "for (let {j} in x) { var [[foo]=[42]] = [] }", top},
    3996             :       {true, "for (let {j} in x) { var foo; foo = j }", top},
    3997             :       {true, "for (let {j} in x) { var foo; [foo] = [j] }", top},
    3998             :       {true, "for (let {j} in x) { var foo; [[foo]=[42]] = [] }", top},
    3999             :       {true, "for (let {j} in x) { let foo; foo = j }", {0, 0, 0}},
    4000             :       {true, "for (let {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
    4001             :       {true, "for (let {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    4002             :       {false, "for (let {j} in x) { let foo = j }", {0, 0, 0}},
    4003             :       {false, "for (let {j} in x) { let [foo] = [j] }", {0, 0, 0}},
    4004             :       {false, "for (let {j} in x) { const foo = j }", {0, 0, 0}},
    4005             :       {false, "for (let {j} in x) { const [foo] = [j] }", {0, 0, 0}},
    4006             :       {false, "for (let {j} in x) { function foo() {return j} }", {0, 0, 0}},
    4007             : 
    4008             :       {true, "for (const j in x) { foo = j }", top},
    4009             :       {true, "for (const j in x) { [foo] = [j] }", top},
    4010             :       {true, "for (const j in x) { [[foo]=[42]] = [] }", top},
    4011             :       {true, "for (const j in x) { var foo = j }", top},
    4012             :       {true, "for (const j in x) { var [foo] = [j] }", top},
    4013             :       {true, "for (const j in x) { var [[foo]=[42]] = [] }", top},
    4014             :       {true, "for (const j in x) { var foo; foo = j }", top},
    4015             :       {true, "for (const j in x) { var foo; [foo] = [j] }", top},
    4016             :       {true, "for (const j in x) { var foo; [[foo]=[42]] = [] }", top},
    4017             :       {true, "for (const j in x) { let foo; foo = j }", {0, 0, 0}},
    4018             :       {true, "for (const j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
    4019             :       {true, "for (const j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    4020             :       {false, "for (const j in x) { let foo = j }", {0, 0, 0}},
    4021             :       {false, "for (const j in x) { let [foo] = [j] }", {0, 0, 0}},
    4022             :       {false, "for (const j in x) { const foo = j }", {0, 0, 0}},
    4023             :       {false, "for (const j in x) { const [foo] = [j] }", {0, 0, 0}},
    4024             :       {false, "for (const j in x) { function foo() {return j} }", {0, 0, 0}},
    4025             : 
    4026             :       {true, "for (const {j} in x) { foo = j }", top},
    4027             :       {true, "for (const {j} in x) { [foo] = [j] }", top},
    4028             :       {true, "for (const {j} in x) { [[foo]=[42]] = [] }", top},
    4029             :       {true, "for (const {j} in x) { var foo = j }", top},
    4030             :       {true, "for (const {j} in x) { var [foo] = [j] }", top},
    4031             :       {true, "for (const {j} in x) { var [[foo]=[42]] = [] }", top},
    4032             :       {true, "for (const {j} in x) { var foo; foo = j }", top},
    4033             :       {true, "for (const {j} in x) { var foo; [foo] = [j] }", top},
    4034             :       {true, "for (const {j} in x) { var foo; [[foo]=[42]] = [] }", top},
    4035             :       {true, "for (const {j} in x) { let foo; foo = j }", {0, 0, 0}},
    4036             :       {true, "for (const {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
    4037             :       {true, "for (const {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
    4038             :       {false, "for (const {j} in x) { let foo = j }", {0, 0, 0}},
    4039             :       {false, "for (const {j} in x) { let [foo] = [j] }", {0, 0, 0}},
    4040             :       {false, "for (const {j} in x) { const foo = j }", {0, 0, 0}},
    4041             :       {false, "for (const {j} in x) { const [foo] = [j] }", {0, 0, 0}},
    4042             :       {false, "for (const {j} in x) { function foo() {return j} }", {0, 0, 0}},
    4043             : 
    4044             :       {true, "while (j) { foo = j }", top},
    4045             :       {true, "while (j) { [foo] = [j] }", top},
    4046             :       {true, "while (j) { [[foo]=[42]] = [] }", top},
    4047             :       {true, "while (j) { var foo = j }", top},
    4048             :       {true, "while (j) { var [foo] = [j] }", top},
    4049             :       {true, "while (j) { var [[foo]=[42]] = [] }", top},
    4050             :       {true, "while (j) { var foo; foo = j }", top},
    4051             :       {true, "while (j) { var foo; [foo] = [j] }", top},
    4052             :       {true, "while (j) { var foo; [[foo]=[42]] = [] }", top},
    4053             :       {true, "while (j) { let foo; foo = j }", {0}},
    4054             :       {true, "while (j) { let foo; [foo] = [j] }", {0}},
    4055             :       {true, "while (j) { let foo; [[foo]=[42]] = [] }", {0}},
    4056             :       {false, "while (j) { let foo = j }", {0}},
    4057             :       {false, "while (j) { let [foo] = [j] }", {0}},
    4058             :       {false, "while (j) { const foo = j }", {0}},
    4059             :       {false, "while (j) { const [foo] = [j] }", {0}},
    4060             :       {false, "while (j) { function foo() {return j} }", {0}},
    4061             : 
    4062             :       {true, "do { foo = j } while (j)", top},
    4063             :       {true, "do { [foo] = [j] } while (j)", top},
    4064             :       {true, "do { [[foo]=[42]] = [] } while (j)", top},
    4065             :       {true, "do { var foo = j } while (j)", top},
    4066             :       {true, "do { var [foo] = [j] } while (j)", top},
    4067             :       {true, "do { var [[foo]=[42]] = [] } while (j)", top},
    4068             :       {true, "do { var foo; foo = j } while (j)", top},
    4069             :       {true, "do { var foo; [foo] = [j] } while (j)", top},
    4070             :       {true, "do { var foo; [[foo]=[42]] = [] } while (j)", top},
    4071             :       {true, "do { let foo; foo = j } while (j)", {0}},
    4072             :       {true, "do { let foo; [foo] = [j] } while (j)", {0}},
    4073             :       {true, "do { let foo; [[foo]=[42]] = [] } while (j)", {0}},
    4074             :       {false, "do { let foo = j } while (j)", {0}},
    4075             :       {false, "do { let [foo] = [j] } while (j)", {0}},
    4076             :       {false, "do { const foo = j } while (j)", {0}},
    4077             :       {false, "do { const [foo] = [j] } while (j)", {0}},
    4078             :       {false, "do { function foo() {return j} } while (j)", {0}},
    4079        3010 :   };
    4080             : 
    4081             :   Input script_only_tests[] = {
    4082             :       {true, "for (j=x; j<10; ++j) { function foo() {return j} }", top},
    4083             :       {true, "for ({j}=x; j<10; ++j) { function foo() {return j} }", top},
    4084             :       {true, "for (var j=x; j<10; ++j) { function foo() {return j} }", top},
    4085             :       {true, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", top},
    4086             :       {true, "for (let j=x; j<10; ++j) { function foo() {return j} }", top},
    4087             :       {true, "for (let {j}=x; j<10; ++j) { function foo() {return j} }", top},
    4088             :       {true, "for (j of x) { function foo() {return j} }", top},
    4089             :       {true, "for ({j} of x) { function foo() {return j} }", top},
    4090             :       {true, "for (var j of x) { function foo() {return j} }", top},
    4091             :       {true, "for (var {j} of x) { function foo() {return j} }", top},
    4092             :       {true, "for (let j of x) { function foo() {return j} }", top},
    4093             :       {true, "for (let {j} of x) { function foo() {return j} }", top},
    4094             :       {true, "for (const j of x) { function foo() {return j} }", top},
    4095             :       {true, "for (const {j} of x) { function foo() {return j} }", top},
    4096             :       {true, "for (j in x) { function foo() {return j} }", top},
    4097             :       {true, "for ({j} in x) { function foo() {return j} }", top},
    4098             :       {true, "for (var j in x) { function foo() {return j} }", top},
    4099             :       {true, "for (var {j} in x) { function foo() {return j} }", top},
    4100             :       {true, "for (let j in x) { function foo() {return j} }", top},
    4101             :       {true, "for (let {j} in x) { function foo() {return j} }", top},
    4102             :       {true, "for (const j in x) { function foo() {return j} }", top},
    4103             :       {true, "for (const {j} in x) { function foo() {return j} }", top},
    4104             :       {true, "while (j) { function foo() {return j} }", top},
    4105             :       {true, "do { function foo() {return j} } while (j)", top},
    4106         130 :   };
    4107             : 
    4108        2045 :   for (unsigned i = 0; i < arraysize(module_and_script_tests); ++i) {
    4109        2040 :     Input input = module_and_script_tests[i];
    4110        6120 :     for (unsigned module = 0; module <= 1; ++module) {
    4111        8160 :       for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
    4112             :            ++allow_lazy_parsing) {
    4113        8160 :         TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
    4114             :       }
    4115        4080 :       TestMaybeAssigned(wrap(input), "foo", module, false);
    4116             :     }
    4117        2040 :   }
    4118             : 
    4119         120 :   for (unsigned i = 0; i < arraysize(script_only_tests); ++i) {
    4120         120 :     Input input = script_only_tests[i];
    4121         360 :     for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
    4122             :          ++allow_lazy_parsing) {
    4123         240 :       TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
    4124             :     }
    4125         120 :     TestMaybeAssigned(wrap(input), "foo", false, false);
    4126         120 :   }
    4127           5 : }
    4128             : 
    4129       28342 : TEST(MaybeAssignedTopLevel) {
    4130             :   i::Isolate* isolate = CcTest::i_isolate();
    4131             :   i::HandleScope scope(isolate);
    4132          10 :   LocalContext env;
    4133             : 
    4134             :   const char* prefixes[] = {
    4135             :       "let foo; ",
    4136             :       "let foo = 0; ",
    4137             :       "let [foo] = [1]; ",
    4138             :       "let {foo} = {foo: 2}; ",
    4139             :       "let {foo=3} = {}; ",
    4140             :       "var foo; ",
    4141             :       "var foo = 0; ",
    4142             :       "var [foo] = [1]; ",
    4143             :       "var {foo} = {foo: 2}; ",
    4144             :       "var {foo=3} = {}; ",
    4145             :       "{ var foo; }; ",
    4146             :       "{ var foo = 0; }; ",
    4147             :       "{ var [foo] = [1]; }; ",
    4148             :       "{ var {foo} = {foo: 2}; }; ",
    4149             :       "{ var {foo=3} = {}; }; ",
    4150             :       "function foo() {}; ",
    4151             :       "function* foo() {}; ",
    4152             :       "async function foo() {}; ",
    4153             :       "class foo {}; ",
    4154             :       "class foo extends null {}; ",
    4155           5 :   };
    4156             : 
    4157             :   const char* module_and_script_tests[] = {
    4158             :       "function bar() {foo = 42}; ext(bar); ext(foo)",
    4159             :       "ext(function() {foo++}); ext(foo)",
    4160             :       "bar = () => --foo; ext(bar); ext(foo)",
    4161             :       "function* bar() {eval(ext)}; ext(bar); ext(foo)",
    4162           5 :   };
    4163             : 
    4164             :   const char* script_only_tests[] = {
    4165             :       "",
    4166             :       "{ function foo() {}; }; ",
    4167             :       "{ function* foo() {}; }; ",
    4168             :       "{ async function foo() {}; }; ",
    4169           5 :   };
    4170             : 
    4171         105 :   for (unsigned i = 0; i < arraysize(prefixes); ++i) {
    4172         400 :     for (unsigned j = 0; j < arraysize(module_and_script_tests); ++j) {
    4173         400 :       std::string source(prefixes[i]);
    4174         400 :       source += module_and_script_tests[j];
    4175             :       std::vector<unsigned> top;
    4176         800 :       Input input({true, source, top});
    4177        1200 :       for (unsigned module = 0; module <= 1; ++module) {
    4178        1600 :         for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
    4179             :              ++allow_lazy_parsing) {
    4180        1600 :           TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
    4181             :         }
    4182             :       }
    4183             :     }
    4184             :   }
    4185             : 
    4186         100 :   for (unsigned i = 0; i < arraysize(prefixes); ++i) {
    4187         400 :     for (unsigned j = 0; j < arraysize(script_only_tests); ++j) {
    4188         400 :       std::string source(prefixes[i]);
    4189         400 :       source += script_only_tests[j];
    4190             :       std::vector<unsigned> top;
    4191         800 :       Input input({true, source, top});
    4192        1200 :       for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
    4193             :            ++allow_lazy_parsing) {
    4194         800 :         TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
    4195             :       }
    4196             :     }
    4197             :   }
    4198           5 : }
    4199             : 
    4200             : namespace {
    4201             : 
    4202          10 : i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone,
    4203             :                                    i::Handle<i::JSObject> m, const char* name) {
    4204             :   i::AstValueFactory avf(zone, isolate->ast_string_constants(),
    4205          10 :                          isolate->heap()->HashSeed());
    4206             :   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(
    4207          10 :       i::JSReceiver::GetProperty(isolate, m, name).ToHandleChecked());
    4208             :   i::DeclarationScope* script_scope =
    4209           5 :       new (zone) i::DeclarationScope(zone, &avf);
    4210             :   i::Scope* s = i::Scope::DeserializeScopeChain(
    4211          10 :       isolate, zone, f->context()->scope_info(), script_scope, &avf,
    4212           5 :       i::Scope::DeserializationMode::kIncludingVariables);
    4213           5 :   return s;
    4214             : }
    4215             : 
    4216             : }  // namespace
    4217             : 
    4218       28342 : TEST(AsmModuleFlag) {
    4219           5 :   i::FLAG_validate_asm = false;
    4220           5 :   i::Isolate* isolate = CcTest::i_isolate();
    4221             :   i::HandleScope scope(isolate);
    4222          10 :   LocalContext env;
    4223             : 
    4224             :   const char* src =
    4225             :       "function m() {"
    4226             :       "  'use asm';"
    4227             :       "  function f() { return 0 };"
    4228             :       "  return { f:f };"
    4229             :       "}"
    4230             :       "m();";
    4231             : 
    4232          10 :   i::Zone zone(isolate->allocator(), ZONE_NAME);
    4233             :   v8::Local<v8::Value> v = CompileRun(src);
    4234           5 :   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
    4235           5 :   i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o);
    4236             : 
    4237             :   // The asm.js module should be marked as such.
    4238           5 :   i::Scope* s = DeserializeFunctionScope(isolate, &zone, m, "f");
    4239          10 :   CHECK(s->IsAsmModule() && s->AsDeclarationScope()->is_asm_module());
    4240           5 : }
    4241             : 
    4242             : 
    4243       28342 : TEST(UseAsmUseCount) {
    4244             :   i::Isolate* isolate = CcTest::i_isolate();
    4245             :   i::HandleScope scope(isolate);
    4246          10 :   LocalContext env;
    4247           5 :   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
    4248           5 :   global_use_counts = use_counts;
    4249           5 :   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
    4250             :   CompileRun("\"use asm\";\n"
    4251             :              "var foo = 1;\n"
    4252             :              "function bar() { \"use asm\"; var baz = 1; }");
    4253           5 :   CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
    4254           5 : }
    4255             : 
    4256             : 
    4257       28342 : TEST(StrictModeUseCount) {
    4258             :   i::Isolate* isolate = CcTest::i_isolate();
    4259             :   i::HandleScope scope(isolate);
    4260          10 :   LocalContext env;
    4261           5 :   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
    4262           5 :   global_use_counts = use_counts;
    4263           5 :   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
    4264             :   CompileRun(
    4265             :       "\"use strict\";\n"
    4266             :       "function bar() { var baz = 1; }");  // strict mode inherits
    4267           5 :   CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
    4268           5 :   CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
    4269           5 : }
    4270             : 
    4271             : 
    4272       28342 : TEST(SloppyModeUseCount) {
    4273             :   i::Isolate* isolate = CcTest::i_isolate();
    4274             :   i::HandleScope scope(isolate);
    4275          10 :   LocalContext env;
    4276           5 :   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
    4277           5 :   global_use_counts = use_counts;
    4278             :   // Force eager parsing (preparser doesn't update use counts).
    4279           5 :   i::FLAG_lazy = false;
    4280           5 :   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
    4281             :   CompileRun("function bar() { var baz = 1; }");
    4282           5 :   CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
    4283           5 :   CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
    4284           5 : }
    4285             : 
    4286             : 
    4287       28342 : TEST(BothModesUseCount) {
    4288             :   i::Isolate* isolate = CcTest::i_isolate();
    4289             :   i::HandleScope scope(isolate);
    4290          10 :   LocalContext env;
    4291           5 :   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
    4292           5 :   global_use_counts = use_counts;
    4293             :   // Force eager parsing (preparser doesn't update use counts).
    4294           5 :   i::FLAG_lazy = false;
    4295           5 :   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
    4296             :   CompileRun("function bar() { 'use strict'; var baz = 1; }");
    4297           5 :   CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
    4298           5 :   CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
    4299           5 : }
    4300             : 
    4301       28342 : TEST(LineOrParagraphSeparatorAsLineTerminator) {
    4302             :   // Tests that both preparsing and parsing accept U+2028 LINE SEPARATOR and
    4303             :   // U+2029 PARAGRAPH SEPARATOR as LineTerminator symbols outside of string
    4304             :   // literals.
    4305           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    4306             :   const char* statement_data[] = {"\x31\xE2\x80\xA8\x32",  // 1<U+2028>2
    4307             :                                   "\x31\xE2\x80\xA9\x32",  // 1<U+2029>2
    4308           5 :                                   nullptr};
    4309             : 
    4310           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    4311           5 : }
    4312             : 
    4313       28342 : TEST(LineOrParagraphSeparatorInStringLiteral) {
    4314             :   // Tests that both preparsing and parsing don't treat U+2028 LINE SEPARATOR
    4315             :   // and U+2029 PARAGRAPH SEPARATOR as line terminators within string literals.
    4316             :   // https://github.com/tc39/proposal-json-superset
    4317             :   const char* context_data[][2] = {
    4318           5 :       {"\"", "\""}, {"'", "'"}, {nullptr, nullptr}};
    4319             :   const char* statement_data[] = {"\x31\xE2\x80\xA8\x32",  // 1<U+2028>2
    4320             :                                   "\x31\xE2\x80\xA9\x32",  // 1<U+2029>2
    4321           5 :                                   nullptr};
    4322             : 
    4323           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    4324           5 : }
    4325             : 
    4326       28342 : TEST(ErrorsArrowFormalParameters) {
    4327             :   const char* context_data[][2] = {
    4328             :     { "()", "=>{}" },
    4329             :     { "()", "=>{};" },
    4330             :     { "var x = ()", "=>{}" },
    4331             :     { "var x = ()", "=>{};" },
    4332             : 
    4333             :     { "a", "=>{}" },
    4334             :     { "a", "=>{};" },
    4335             :     { "var x = a", "=>{}" },
    4336             :     { "var x = a", "=>{};" },
    4337             : 
    4338             :     { "(a)", "=>{}" },
    4339             :     { "(a)", "=>{};" },
    4340             :     { "var x = (a)", "=>{}" },
    4341             :     { "var x = (a)", "=>{};" },
    4342             : 
    4343             :     { "(...a)", "=>{}" },
    4344             :     { "(...a)", "=>{};" },
    4345             :     { "var x = (...a)", "=>{}" },
    4346             :     { "var x = (...a)", "=>{};" },
    4347             : 
    4348             :     { "(a,b)", "=>{}" },
    4349             :     { "(a,b)", "=>{};" },
    4350             :     { "var x = (a,b)", "=>{}" },
    4351             :     { "var x = (a,b)", "=>{};" },
    4352             : 
    4353             :     { "(a,...b)", "=>{}" },
    4354             :     { "(a,...b)", "=>{};" },
    4355             :     { "var x = (a,...b)", "=>{}" },
    4356             :     { "var x = (a,...b)", "=>{};" },
    4357             : 
    4358             :     { nullptr, nullptr }
    4359           5 :   };
    4360             :   const char* assignment_expression_suffix_data[] = {
    4361             :     "?c:d=>{}",
    4362             :     "=c=>{}",
    4363             :     "()",
    4364             :     "(c)",
    4365             :     "[1]",
    4366             :     "[c]",
    4367             :     ".c",
    4368             :     "-c",
    4369             :     "+c",
    4370             :     "c++",
    4371             :     "`c`",
    4372             :     "`${c}`",
    4373             :     "`template-head${c}`",
    4374             :     "`${c}template-tail`",
    4375             :     "`template-head${c}template-tail`",
    4376             :     "`${c}template-tail`",
    4377             :     nullptr
    4378           5 :   };
    4379             : 
    4380           5 :   RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
    4381           5 : }
    4382             : 
    4383             : 
    4384       28342 : TEST(ErrorsArrowFunctions) {
    4385             :   // Tests that parser and preparser generate the same kind of errors
    4386             :   // on invalid arrow function syntax.
    4387             : 
    4388             :   // clang-format off
    4389             :   const char* context_data[][2] = {
    4390             :     {"", ";"},
    4391             :     {"v = ", ";"},
    4392             :     {"bar ? (", ") : baz;"},
    4393             :     {"bar ? baz : (", ");"},
    4394             :     {"bar[", "];"},
    4395             :     {"bar, ", ";"},
    4396             :     {"", ", bar;"},
    4397             :     {nullptr, nullptr}
    4398           5 :   };
    4399             : 
    4400             :   const char* statement_data[] = {
    4401             :     "=> 0",
    4402             :     "=>",
    4403             :     "() =>",
    4404             :     "=> {}",
    4405             :     ") => {}",
    4406             :     ", => {}",
    4407             :     "(,) => {}",
    4408             :     "return => {}",
    4409             :     "() => {'value': 42}",
    4410             : 
    4411             :     // Check that the early return introduced in ParsePrimaryExpression
    4412             :     // does not accept stray closing parentheses.
    4413             :     ")",
    4414             :     ") => 0",
    4415             :     "foo[()]",
    4416             :     "()",
    4417             : 
    4418             :     // Parameter lists with extra parens should be recognized as errors.
    4419             :     "(()) => 0",
    4420             :     "((x)) => 0",
    4421             :     "((x, y)) => 0",
    4422             :     "(x, (y)) => 0",
    4423             :     "((x, y, z)) => 0",
    4424             :     "(x, (y, z)) => 0",
    4425             :     "((x, y), z) => 0",
    4426             : 
    4427             :     // Arrow function formal parameters are parsed as StrictFormalParameters,
    4428             :     // which confusingly only implies that there are no duplicates.  Words
    4429             :     // reserved in strict mode, and eval or arguments, are indeed valid in
    4430             :     // sloppy mode.
    4431             :     "eval => { 'use strict'; 0 }",
    4432             :     "arguments => { 'use strict'; 0 }",
    4433             :     "yield => { 'use strict'; 0 }",
    4434             :     "interface => { 'use strict'; 0 }",
    4435             :     "(eval) => { 'use strict'; 0 }",
    4436             :     "(arguments) => { 'use strict'; 0 }",
    4437             :     "(yield) => { 'use strict'; 0 }",
    4438             :     "(interface) => { 'use strict'; 0 }",
    4439             :     "(eval, bar) => { 'use strict'; 0 }",
    4440             :     "(bar, eval) => { 'use strict'; 0 }",
    4441             :     "(bar, arguments) => { 'use strict'; 0 }",
    4442             :     "(bar, yield) => { 'use strict'; 0 }",
    4443             :     "(bar, interface) => { 'use strict'; 0 }",
    4444             :     // TODO(aperez): Detecting duplicates does not work in PreParser.
    4445             :     // "(bar, bar) => {}",
    4446             : 
    4447             :     // The parameter list is parsed as an expression, but only
    4448             :     // a comma-separated list of identifier is valid.
    4449             :     "32 => {}",
    4450             :     "(32) => {}",
    4451             :     "(a, 32) => {}",
    4452             :     "if => {}",
    4453             :     "(if) => {}",
    4454             :     "(a, if) => {}",
    4455             :     "a + b => {}",
    4456             :     "(a + b) => {}",
    4457             :     "(a + b, c) => {}",
    4458             :     "(a, b - c) => {}",
    4459             :     "\"a\" => {}",
    4460             :     "(\"a\") => {}",
    4461             :     "(\"a\", b) => {}",
    4462             :     "(a, \"b\") => {}",
    4463             :     "-a => {}",
    4464             :     "(-a) => {}",
    4465             :     "(-a, b) => {}",
    4466             :     "(a, -b) => {}",
    4467             :     "{} => {}",
    4468             :     "a++ => {}",
    4469             :     "(a++) => {}",
    4470             :     "(a++, b) => {}",
    4471             :     "(a, b++) => {}",
    4472             :     "[] => {}",
    4473             :     "(foo ? bar : baz) => {}",
    4474             :     "(a, foo ? bar : baz) => {}",
    4475             :     "(foo ? bar : baz, a) => {}",
    4476             :     "(a.b, c) => {}",
    4477             :     "(c, a.b) => {}",
    4478             :     "(a['b'], c) => {}",
    4479             :     "(c, a['b']) => {}",
    4480             :     "(...a = b) => b",
    4481             : 
    4482             :     // crbug.com/582626
    4483             :     "(...rest - a) => b",
    4484             :     "(a, ...b - 10) => b",
    4485             : 
    4486             :     nullptr
    4487           5 :   };
    4488             :   // clang-format on
    4489             : 
    4490             :   // The test is quite slow, so run it with a reduced set of flags.
    4491             :   static const ParserFlag flags[] = {kAllowLazy};
    4492             :   RunParserSyncTest(context_data, statement_data, kError, flags,
    4493           5 :                     arraysize(flags));
    4494             : 
    4495             :   // In a context where a concise arrow body is parsed with [~In] variant,
    4496             :   // ensure that an error is reported in both full parser and preparser.
    4497             :   const char* loop_context_data[][2] = {{"for (", "; 0;);"},
    4498           5 :                                         {nullptr, nullptr}};
    4499           5 :   const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
    4500             :   RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
    4501           5 :                     arraysize(flags));
    4502           5 : }
    4503             : 
    4504             : 
    4505       28342 : TEST(NoErrorsArrowFunctions) {
    4506             :   // Tests that parser and preparser accept valid arrow functions syntax.
    4507             :   // clang-format off
    4508             :   const char* context_data[][2] = {
    4509             :     {"", ";"},
    4510             :     {"bar ? (", ") : baz;"},
    4511             :     {"bar ? baz : (", ");"},
    4512             :     {"bar, ", ";"},
    4513             :     {"", ", bar;"},
    4514             :     {nullptr, nullptr}
    4515           5 :   };
    4516             : 
    4517             :   const char* statement_data[] = {
    4518             :     "() => {}",
    4519             :     "() => { return 42 }",
    4520             :     "x => { return x; }",
    4521             :     "(x) => { return x; }",
    4522             :     "(x, y) => { return x + y; }",
    4523             :     "(x, y, z) => { return x + y + z; }",
    4524             :     "(x, y) => { x.a = y; }",
    4525             :     "() => 42",
    4526             :     "x => x",
    4527             :     "x => x * x",
    4528             :     "(x) => x",
    4529             :     "(x) => x * x",
    4530             :     "(x, y) => x + y",
    4531             :     "(x, y, z) => x, y, z",
    4532             :     "(x, y) => x.a = y",
    4533             :     "() => ({'value': 42})",
    4534             :     "x => y => x + y",
    4535             :     "(x, y) => (u, v) => x*u + y*v",
    4536             :     "(x, y) => z => z * (x + y)",
    4537             :     "x => (y, z) => z * (x + y)",
    4538             : 
    4539             :     // Those are comma-separated expressions, with arrow functions as items.
    4540             :     // They stress the code for validating arrow function parameter lists.
    4541             :     "a, b => 0",
    4542             :     "a, b, (c, d) => 0",
    4543             :     "(a, b, (c, d) => 0)",
    4544             :     "(a, b) => 0, (c, d) => 1",
    4545             :     "(a, b => {}, a => a + 1)",
    4546             :     "((a, b) => {}, (a => a + 1))",
    4547             :     "(a, (a, (b, c) => 0))",
    4548             : 
    4549             :     // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
    4550             :     "foo ? bar : baz => {}",
    4551             : 
    4552             :     // Arrows with non-simple parameters.
    4553             :     "({}) => {}",
    4554             :     "(a, {}) => {}",
    4555             :     "({}, a) => {}",
    4556             :     "([]) => {}",
    4557             :     "(a, []) => {}",
    4558             :     "([], a) => {}",
    4559             :     "(a = b) => {}",
    4560             :     "(a = b, c) => {}",
    4561             :     "(a, b = c) => {}",
    4562             :     "({a}) => {}",
    4563             :     "(x = 9) => {}",
    4564             :     "(x, y = 9) => {}",
    4565             :     "(x = 9, y) => {}",
    4566             :     "(x, y = 9, z) => {}",
    4567             :     "(x, y = 9, z = 8) => {}",
    4568             :     "(...a) => {}",
    4569             :     "(x, ...a) => {}",
    4570             :     "(x = 9, ...a) => {}",
    4571             :     "(x, y = 9, ...a) => {}",
    4572             :     "(x, y = 9, {b}, z = 8, ...a) => {}",
    4573             :     "({a} = {}) => {}",
    4574             :     "([x] = []) => {}",
    4575             :     "({a = 42}) => {}",
    4576             :     "([x = 0]) => {}",
    4577             :     nullptr
    4578           5 :   };
    4579             :   // clang-format on
    4580             : 
    4581           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    4582             : 
    4583             :   static const ParserFlag flags[] = {kAllowLazy};
    4584             :   // In a context where a concise arrow body is parsed with [~In] variant,
    4585             :   // ensure that nested expressions can still use the 'in' operator,
    4586             :   const char* loop_context_data[][2] = {{"for (", "; 0;);"},
    4587           5 :                                         {nullptr, nullptr}};
    4588           5 :   const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
    4589             :   RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
    4590           5 :                     arraysize(flags));
    4591           5 : }
    4592             : 
    4593             : 
    4594       28342 : TEST(ArrowFunctionsSloppyParameterNames) {
    4595             :   const char* strict_context_data[][2] = {{"'use strict'; ", ";"},
    4596             :                                           {"'use strict'; bar ? (", ") : baz;"},
    4597             :                                           {"'use strict'; bar ? baz : (", ");"},
    4598             :                                           {"'use strict'; bar, ", ";"},
    4599             :                                           {"'use strict'; ", ", bar;"},
    4600           5 :                                           {nullptr, nullptr}};
    4601             : 
    4602             :   const char* sloppy_context_data[][2] = {
    4603             :       {"", ";"},      {"bar ? (", ") : baz;"}, {"bar ? baz : (", ");"},
    4604           5 :       {"bar, ", ";"}, {"", ", bar;"},          {nullptr, nullptr}};
    4605             : 
    4606             :   const char* statement_data[] = {"eval => {}",
    4607             :                                   "arguments => {}",
    4608             :                                   "yield => {}",
    4609             :                                   "interface => {}",
    4610             :                                   "(eval) => {}",
    4611             :                                   "(arguments) => {}",
    4612             :                                   "(yield) => {}",
    4613             :                                   "(interface) => {}",
    4614             :                                   "(eval, bar) => {}",
    4615             :                                   "(bar, eval) => {}",
    4616             :                                   "(bar, arguments) => {}",
    4617             :                                   "(bar, yield) => {}",
    4618             :                                   "(bar, interface) => {}",
    4619             :                                   "(interface, eval) => {}",
    4620             :                                   "(interface, arguments) => {}",
    4621             :                                   "(eval, interface) => {}",
    4622             :                                   "(arguments, interface) => {}",
    4623           5 :                                   nullptr};
    4624             : 
    4625           5 :   RunParserSyncTest(strict_context_data, statement_data, kError);
    4626           5 :   RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
    4627           5 : }
    4628             : 
    4629             : 
    4630       28342 : TEST(ArrowFunctionsYieldParameterNameInGenerator) {
    4631             :   const char* sloppy_function_context_data[][2] = {
    4632           5 :       {"(function f() { (", "); });"}, {nullptr, nullptr}};
    4633             : 
    4634             :   const char* strict_function_context_data[][2] = {
    4635           5 :       {"(function f() {'use strict'; (", "); });"}, {nullptr, nullptr}};
    4636             : 
    4637             :   const char* generator_context_data[][2] = {
    4638             :       {"(function *g() {'use strict'; (", "); });"},
    4639             :       {"(function *g() { (", "); });"},
    4640           5 :       {nullptr, nullptr}};
    4641             : 
    4642             :   const char* arrow_data[] = {
    4643             :       "yield => {}",      "(yield) => {}",       "(a, yield) => {}",
    4644             :       "(yield, a) => {}", "(yield, ...a) => {}", "(a, ...yield) => {}",
    4645           5 :       "({yield}) => {}",  "([yield]) => {}",     nullptr};
    4646             : 
    4647           5 :   RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
    4648           5 :   RunParserSyncTest(strict_function_context_data, arrow_data, kError);
    4649           5 :   RunParserSyncTest(generator_context_data, arrow_data, kError);
    4650           5 : }
    4651             : 
    4652             : 
    4653       28342 : TEST(SuperNoErrors) {
    4654             :   // Tests that parser and preparser accept 'super' keyword in right places.
    4655             :   const char* context_data[][2] = {{"class C { m() { ", "; } }"},
    4656             :                                    {"class C { m() { k = ", "; } }"},
    4657             :                                    {"class C { m() { foo(", "); } }"},
    4658             :                                    {"class C { m() { () => ", "; } }"},
    4659           5 :                                    {nullptr, nullptr}};
    4660             : 
    4661             :   const char* statement_data[] = {"super.x",       "super[27]",
    4662             :                                   "new super.x",   "new super.x()",
    4663             :                                   "new super[27]", "new super[27]()",
    4664             :                                   "z.super",  // Ok, property lookup.
    4665           5 :                                   nullptr};
    4666             : 
    4667           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    4668           5 : }
    4669             : 
    4670             : 
    4671       28342 : TEST(SuperErrors) {
    4672             :   const char* context_data[][2] = {{"class C { m() { ", "; } }"},
    4673             :                                    {"class C { m() { k = ", "; } }"},
    4674             :                                    {"class C { m() { foo(", "); } }"},
    4675             :                                    {"class C { m() { () => ", "; } }"},
    4676           5 :                                    {nullptr, nullptr}};
    4677             : 
    4678             :   const char* expression_data[] = {"super",
    4679             :                                    "super = x",
    4680             :                                    "y = super",
    4681             :                                    "f(super)",
    4682             :                                    "new super",
    4683             :                                    "new super()",
    4684             :                                    "new super(12, 45)",
    4685             :                                    "new new super",
    4686             :                                    "new new super()",
    4687             :                                    "new new super()()",
    4688           5 :                                    nullptr};
    4689             : 
    4690           5 :   RunParserSyncTest(context_data, expression_data, kError);
    4691           5 : }
    4692             : 
    4693       28342 : TEST(ImportExpressionSuccess) {
    4694             :   // clang-format off
    4695             :   const char* context_data[][2] = {
    4696             :     {"", ""},
    4697             :     {nullptr, nullptr}
    4698           5 :   };
    4699             : 
    4700             :   const char* data[] = {
    4701             :     "import(1)",
    4702             :     "import(y=x)",
    4703             :     "f(...[import(y=x)])",
    4704             :     "x = {[import(y=x)]: 1}",
    4705             :     "var {[import(y=x)]: x} = {}",
    4706             :     "({[import(y=x)]: x} = {})",
    4707             :     "async () => { await import(x) }",
    4708             :     "() => { import(x) }",
    4709             :     "(import(y=x))",
    4710             :     "{import(y=x)}",
    4711             :     "import(import(x))",
    4712             :     "x = import(x)",
    4713             :     "var x = import(x)",
    4714             :     "let x = import(x)",
    4715             :     "for(x of import(x)) {}",
    4716             :     "import(x).then()",
    4717             :     nullptr
    4718           5 :   };
    4719             : 
    4720             :   // clang-format on
    4721             : 
    4722             :   // We ignore test error messages because the error message from the
    4723             :   // parser/preparser is different for the same data depending on the
    4724             :   // context.
    4725             :   // For example, a top level "import(" is parsed as an
    4726             :   // import declaration. The parser parses the import token correctly
    4727             :   // and then shows an "Unexpected token (" error message. The
    4728             :   // preparser does not understand the import keyword (this test is
    4729             :   // run without kAllowHarmonyDynamicImport flag), so this results in
    4730             :   // an "Unexpected token import" error.
    4731           5 :   RunParserSyncTest(context_data, data, kError);
    4732             :   RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
    4733             :                           nullptr, 0, true, true);
    4734             :   static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
    4735             :   RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
    4736           5 :                     arraysize(flags));
    4737             :   RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
    4738             :                           arraysize(flags));
    4739           5 : }
    4740             : 
    4741       28342 : TEST(ImportExpressionErrors) {
    4742             :   {
    4743             :     // clang-format off
    4744             :     const char* context_data[][2] = {
    4745             :       {"", ""},
    4746             :       {"var ", ""},
    4747             :       {"let ", ""},
    4748             :       {"new ", ""},
    4749             :       {nullptr, nullptr}
    4750           5 :     };
    4751             : 
    4752             :     const char* data[] = {
    4753             :       "import(",
    4754             :       "import)",
    4755             :       "import()",
    4756             :       "import('x",
    4757             :       "import('x']",
    4758             :       "import['x')",
    4759             :       "import = x",
    4760             :       "import[",
    4761             :       "import[]",
    4762             :       "import]",
    4763             :       "import[x]",
    4764             :       "import{",
    4765             :       "import{x",
    4766             :       "import{x}",
    4767             :       "import(x, y)",
    4768             :       "import(...y)",
    4769             :       "import(x,)",
    4770             :       "import(,)",
    4771             :       "import(,y)",
    4772             :       "import(;)",
    4773             :       "[import]",
    4774             :       "{import}",
    4775             :       "import+",
    4776             :       "import = 1",
    4777             :       "import.wat",
    4778             :       "new import(x)",
    4779             :       nullptr
    4780           5 :     };
    4781             : 
    4782             :     // clang-format on
    4783           5 :     RunParserSyncTest(context_data, data, kError);
    4784             :     // We ignore the error messages for the reason explained in the
    4785             :     // ImportExpressionSuccess test.
    4786             :     RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
    4787             :                             nullptr, 0, true, true);
    4788             :     static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
    4789             :     RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4790           5 :                       arraysize(flags));
    4791             : 
    4792             :     // We ignore test error messages because the error message from
    4793             :     // the parser/preparser is different for the same data depending
    4794             :     // on the context.  For example, a top level "import{" is parsed
    4795             :     // as an import declaration. The parser parses the import token
    4796             :     // correctly and then shows an "Unexpected end of input" error
    4797             :     // message because of the '{'. The preparser shows an "Unexpected
    4798             :     // token {" because it's not a valid token in a CallExpression.
    4799             :     RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4800             :                             arraysize(flags), nullptr, 0, true, true);
    4801             :   }
    4802             : 
    4803             :   {
    4804             :     // clang-format off
    4805             :     const char* context_data[][2] = {
    4806             :       {"var ", ""},
    4807             :       {"let ", ""},
    4808             :       {nullptr, nullptr}
    4809           5 :     };
    4810             : 
    4811             :     const char* data[] = {
    4812             :       "import('x')",
    4813             :       nullptr
    4814           5 :     };
    4815             : 
    4816             :     // clang-format on
    4817           5 :     RunParserSyncTest(context_data, data, kError);
    4818             :     RunModuleParserSyncTest(context_data, data, kError);
    4819             : 
    4820             :     static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
    4821             :     RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4822           5 :                       arraysize(flags));
    4823             :     RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4824             :                             arraysize(flags));
    4825             :   }
    4826             : 
    4827             :   // Import statements as arrow function params and destructuring targets.
    4828             :   {
    4829             :     // clang-format off
    4830             :     const char* context_data[][2] = {
    4831             :       {"(", ") => {}"},
    4832             :       {"(a, ", ") => {}"},
    4833             :       {"(1, ", ") => {}"},
    4834             :       {"let f = ", " => {}"},
    4835             :       {"[", "] = [1];"},
    4836             :       {"{", "} = {'a': 1};"},
    4837             :       {nullptr, nullptr}
    4838           5 :     };
    4839             : 
    4840             :     const char* data[] = {
    4841             :       "import(foo)",
    4842             :       "import(1)",
    4843             :       "import(y=x)",
    4844             :       "import(import(x))",
    4845             :       "import(x).then()",
    4846             :       nullptr
    4847           5 :     };
    4848             : 
    4849             :     // clang-format on
    4850           5 :     RunParserSyncTest(context_data, data, kError);
    4851             :     RunModuleParserSyncTest(context_data, data, kError);
    4852             : 
    4853             :     static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
    4854             :     RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4855           5 :                       arraysize(flags));
    4856             :     RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    4857             :                             arraysize(flags));
    4858             :   }
    4859           5 : }
    4860             : 
    4861       28342 : TEST(SuperCall) {
    4862           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    4863             : 
    4864             :   const char* success_data[] = {
    4865             :       "class C extends B { constructor() { super(); } }",
    4866           5 :       "class C extends B { constructor() { () => super(); } }", nullptr};
    4867             : 
    4868           5 :   RunParserSyncTest(context_data, success_data, kSuccess);
    4869             : 
    4870             :   const char* error_data[] = {"class C { constructor() { super(); } }",
    4871             :                               "class C { method() { super(); } }",
    4872             :                               "class C { method() { () => super(); } }",
    4873             :                               "class C { *method() { super(); } }",
    4874             :                               "class C { get x() { super(); } }",
    4875             :                               "class C { set x(_) { super(); } }",
    4876             :                               "({ method() { super(); } })",
    4877             :                               "({ *method() { super(); } })",
    4878             :                               "({ get x() { super(); } })",
    4879             :                               "({ set x(_) { super(); } })",
    4880             :                               "({ f: function() { super(); } })",
    4881             :                               "(function() { super(); })",
    4882             :                               "var f = function() { super(); }",
    4883             :                               "({ f: function*() { super(); } })",
    4884             :                               "(function*() { super(); })",
    4885             :                               "var f = function*() { super(); }",
    4886           5 :                               nullptr};
    4887             : 
    4888           5 :   RunParserSyncTest(context_data, error_data, kError);
    4889           5 : }
    4890             : 
    4891             : 
    4892       28342 : TEST(SuperNewNoErrors) {
    4893             :   const char* context_data[][2] = {{"class C { constructor() { ", " } }"},
    4894             :                                    {"class C { *method() { ", " } }"},
    4895             :                                    {"class C { get x() { ", " } }"},
    4896             :                                    {"class C { set x(_) { ", " } }"},
    4897             :                                    {"({ method() { ", " } })"},
    4898             :                                    {"({ *method() { ", " } })"},
    4899             :                                    {"({ get x() { ", " } })"},
    4900             :                                    {"({ set x(_) { ", " } })"},
    4901           5 :                                    {nullptr, nullptr}};
    4902             : 
    4903             :   const char* expression_data[] = {"new super.x;", "new super.x();",
    4904             :                                    "() => new super.x;", "() => new super.x();",
    4905           5 :                                    nullptr};
    4906             : 
    4907           5 :   RunParserSyncTest(context_data, expression_data, kSuccess);
    4908           5 : }
    4909             : 
    4910             : 
    4911       28342 : TEST(SuperNewErrors) {
    4912             :   const char* context_data[][2] = {{"class C { method() { ", " } }"},
    4913             :                                    {"class C { *method() { ", " } }"},
    4914             :                                    {"class C { get x() { ", " } }"},
    4915             :                                    {"class C { set x(_) { ", " } }"},
    4916             :                                    {"({ method() { ", " } })"},
    4917             :                                    {"({ *method() { ", " } })"},
    4918             :                                    {"({ get x() { ", " } })"},
    4919             :                                    {"({ set x(_) { ", " } })"},
    4920             :                                    {"({ f: function() { ", " } })"},
    4921             :                                    {"(function() { ", " })"},
    4922             :                                    {"var f = function() { ", " }"},
    4923             :                                    {"({ f: function*() { ", " } })"},
    4924             :                                    {"(function*() { ", " })"},
    4925             :                                    {"var f = function*() { ", " }"},
    4926           5 :                                    {nullptr, nullptr}};
    4927             : 
    4928             :   const char* statement_data[] = {"new super;", "new super();",
    4929             :                                   "() => new super;", "() => new super();",
    4930           5 :                                   nullptr};
    4931             : 
    4932           5 :   RunParserSyncTest(context_data, statement_data, kError);
    4933           5 : }
    4934             : 
    4935             : 
    4936       28342 : TEST(SuperErrorsNonMethods) {
    4937             :   // super is only allowed in methods, accessors and constructors.
    4938             :   const char* context_data[][2] = {{"", ";"},
    4939             :                                    {"k = ", ";"},
    4940             :                                    {"foo(", ");"},
    4941             :                                    {"if (", ") {}"},
    4942             :                                    {"if (true) {", "}"},
    4943             :                                    {"if (false) {} else {", "}"},
    4944             :                                    {"while (true) {", "}"},
    4945             :                                    {"function f() {", "}"},
    4946             :                                    {"class C extends (", ") {}"},
    4947             :                                    {"class C { m() { function f() {", "} } }"},
    4948             :                                    {"({ m() { function f() {", "} } })"},
    4949           5 :                                    {nullptr, nullptr}};
    4950             : 
    4951             :   const char* statement_data[] = {
    4952             :       "super",           "super = x",   "y = super",     "f(super)",
    4953             :       "super.x",         "super[27]",   "super.x()",     "super[27]()",
    4954             :       "super()",         "new super.x", "new super.x()", "new super[27]",
    4955           5 :       "new super[27]()", nullptr};
    4956             : 
    4957           5 :   RunParserSyncTest(context_data, statement_data, kError);
    4958           5 : }
    4959             : 
    4960             : 
    4961       28342 : TEST(NoErrorsMethodDefinition) {
    4962             :   const char* context_data[][2] = {{"({", "});"},
    4963             :                                    {"'use strict'; ({", "});"},
    4964             :                                    {"({*", "});"},
    4965             :                                    {"'use strict'; ({*", "});"},
    4966           5 :                                    {nullptr, nullptr}};
    4967             : 
    4968             :   const char* object_literal_body_data[] = {
    4969             :       "m() {}",       "m(x) { return x; }", "m(x, y) {}, n() {}",
    4970           5 :       "set(x, y) {}", "get(x, y) {}",       nullptr};
    4971             : 
    4972           5 :   RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
    4973           5 : }
    4974             : 
    4975             : 
    4976       28342 : TEST(MethodDefinitionNames) {
    4977             :   const char* context_data[][2] = {{"({", "(x, y) {}});"},
    4978             :                                    {"'use strict'; ({", "(x, y) {}});"},
    4979             :                                    {"({*", "(x, y) {}});"},
    4980             :                                    {"'use strict'; ({*", "(x, y) {}});"},
    4981           5 :                                    {nullptr, nullptr}};
    4982             : 
    4983             :   const char* name_data[] = {
    4984             :       "m", "'m'", "\"m\"", "\"m n\"", "true", "false", "null", "0", "1.2",
    4985             :       "1e1", "1E1", "1e+1", "1e-1",
    4986             : 
    4987             :       // Keywords
    4988             :       "async", "await", "break", "case", "catch", "class", "const", "continue",
    4989             :       "debugger", "default", "delete", "do", "else", "enum", "export",
    4990             :       "extends", "finally", "for", "function", "if", "implements", "import",
    4991             :       "in", "instanceof", "interface", "let", "new", "package", "private",
    4992             :       "protected", "public", "return", "static", "super", "switch", "this",
    4993             :       "throw", "try", "typeof", "var", "void", "while", "with", "yield",
    4994           5 :       nullptr};
    4995             : 
    4996           5 :   RunParserSyncTest(context_data, name_data, kSuccess);
    4997           5 : }
    4998             : 
    4999             : 
    5000       28342 : TEST(MethodDefinitionStrictFormalParamereters) {
    5001             :   const char* context_data[][2] = {{"({method(", "){}});"},
    5002             :                                    {"'use strict'; ({method(", "){}});"},
    5003             :                                    {"({*method(", "){}});"},
    5004             :                                    {"'use strict'; ({*method(", "){}});"},
    5005           5 :                                    {nullptr, nullptr}};
    5006             : 
    5007           5 :   const char* params_data[] = {"x, x", "x, y, x", "var", "const", nullptr};
    5008             : 
    5009           5 :   RunParserSyncTest(context_data, params_data, kError);
    5010           5 : }
    5011             : 
    5012             : 
    5013       28342 : TEST(MethodDefinitionEvalArguments) {
    5014             :   const char* strict_context_data[][2] = {
    5015             :       {"'use strict'; ({method(", "){}});"},
    5016             :       {"'use strict'; ({*method(", "){}});"},
    5017           5 :       {nullptr, nullptr}};
    5018             :   const char* sloppy_context_data[][2] = {
    5019           5 :       {"({method(", "){}});"}, {"({*method(", "){}});"}, {nullptr, nullptr}};
    5020             : 
    5021           5 :   const char* data[] = {"eval", "arguments", nullptr};
    5022             : 
    5023             :   // Fail in strict mode
    5024           5 :   RunParserSyncTest(strict_context_data, data, kError);
    5025             : 
    5026             :   // OK in sloppy mode
    5027           5 :   RunParserSyncTest(sloppy_context_data, data, kSuccess);
    5028           5 : }
    5029             : 
    5030             : 
    5031       28342 : TEST(MethodDefinitionDuplicateEvalArguments) {
    5032             :   const char* context_data[][2] = {{"'use strict'; ({method(", "){}});"},
    5033             :                                    {"'use strict'; ({*method(", "){}});"},
    5034             :                                    {"({method(", "){}});"},
    5035             :                                    {"({*method(", "){}});"},
    5036           5 :                                    {nullptr, nullptr}};
    5037             : 
    5038             :   const char* data[] = {"eval, eval", "eval, a, eval", "arguments, arguments",
    5039           5 :                         "arguments, a, arguments", nullptr};
    5040             : 
    5041             :   // In strict mode, the error is using "eval" or "arguments" as parameter names
    5042             :   // In sloppy mode, the error is that eval / arguments are duplicated
    5043           5 :   RunParserSyncTest(context_data, data, kError);
    5044           5 : }
    5045             : 
    5046             : 
    5047       28342 : TEST(MethodDefinitionDuplicateProperty) {
    5048             :   const char* context_data[][2] = {{"'use strict'; ({", "});"},
    5049           5 :                                    {nullptr, nullptr}};
    5050             : 
    5051             :   const char* params_data[] = {"x: 1, x() {}",
    5052             :                                "x() {}, x: 1",
    5053             :                                "x() {}, get x() {}",
    5054             :                                "x() {}, set x(_) {}",
    5055             :                                "x() {}, x() {}",
    5056             :                                "x() {}, y() {}, x() {}",
    5057             :                                "x() {}, \"x\"() {}",
    5058             :                                "x() {}, 'x'() {}",
    5059             :                                "0() {}, '0'() {}",
    5060             :                                "1.0() {}, 1: 1",
    5061             : 
    5062             :                                "x: 1, *x() {}",
    5063             :                                "*x() {}, x: 1",
    5064             :                                "*x() {}, get x() {}",
    5065             :                                "*x() {}, set x(_) {}",
    5066             :                                "*x() {}, *x() {}",
    5067             :                                "*x() {}, y() {}, *x() {}",
    5068             :                                "*x() {}, *\"x\"() {}",
    5069             :                                "*x() {}, *'x'() {}",
    5070             :                                "*0() {}, *'0'() {}",
    5071             :                                "*1.0() {}, 1: 1",
    5072             : 
    5073           5 :                                nullptr};
    5074             : 
    5075           5 :   RunParserSyncTest(context_data, params_data, kSuccess);
    5076           5 : }
    5077             : 
    5078             : 
    5079       28342 : TEST(ClassExpressionNoErrors) {
    5080             :   const char* context_data[][2] = {
    5081           5 :       {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
    5082             :   const char* class_data[] = {"class {}",
    5083             :                               "class name {}",
    5084             :                               "class extends F {}",
    5085             :                               "class name extends F {}",
    5086             :                               "class extends (F, G) {}",
    5087             :                               "class name extends (F, G) {}",
    5088             :                               "class extends class {} {}",
    5089             :                               "class name extends class {} {}",
    5090             :                               "class extends class base {} {}",
    5091             :                               "class name extends class base {} {}",
    5092           5 :                               nullptr};
    5093             : 
    5094           5 :   RunParserSyncTest(context_data, class_data, kSuccess);
    5095           5 : }
    5096             : 
    5097             : 
    5098       28342 : TEST(ClassDeclarationNoErrors) {
    5099             :   const char* context_data[][2] = {{"'use strict'; ", ""},
    5100             :                                    {"'use strict'; {", "}"},
    5101             :                                    {"'use strict'; if (true) {", "}"},
    5102           5 :                                    {nullptr, nullptr}};
    5103             :   const char* statement_data[] = {"class name {}",
    5104             :                                   "class name extends F {}",
    5105             :                                   "class name extends (F, G) {}",
    5106             :                                   "class name extends class {} {}",
    5107             :                                   "class name extends class base {} {}",
    5108           5 :                                   nullptr};
    5109             : 
    5110           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    5111           5 : }
    5112             : 
    5113             : 
    5114       28342 : TEST(ClassBodyNoErrors) {
    5115             :   // clang-format off
    5116             :   // Tests that parser and preparser accept valid class syntax.
    5117             :   const char* context_data[][2] = {{"(class {", "});"},
    5118             :                                    {"(class extends Base {", "});"},
    5119             :                                    {"class C {", "}"},
    5120             :                                    {"class C extends Base {", "}"},
    5121           5 :                                    {nullptr, nullptr}};
    5122             :   const char* class_body_data[] = {
    5123             :     ";",
    5124             :     ";;",
    5125             :     "m() {}",
    5126             :     "m() {};",
    5127             :     "; m() {}",
    5128             :     "m() {}; n(x) {}",
    5129             :     "get x() {}",
    5130             :     "set x(v) {}",
    5131             :     "get() {}",
    5132             :     "set() {}",
    5133             :     "*g() {}",
    5134             :     "*g() {};",
    5135             :     "; *g() {}",
    5136             :     "*g() {}; *h(x) {}",
    5137             :     "async *x(){}",
    5138             :     "static() {}",
    5139             :     "get static() {}",
    5140             :     "set static(v) {}",
    5141             :     "static m() {}",
    5142             :     "static get x() {}",
    5143             :     "static set x(v) {}",
    5144             :     "static get() {}",
    5145             :     "static set() {}",
    5146             :     "static static() {}",
    5147             :     "static get static() {}",
    5148             :     "static set static(v) {}",
    5149             :     "*static() {}",
    5150             :     "static *static() {}",
    5151             :     "*get() {}",
    5152             :     "*set() {}",
    5153             :     "static *g() {}",
    5154             :     "async(){}",
    5155             :     "*async(){}",
    5156             :     "static async(){}",
    5157             :     "static *async(){}",
    5158             :     "static async *x(){}",
    5159             : 
    5160             :     // Escaped 'static' should be allowed anywhere
    5161             :     // static-as-PropertyName is.
    5162             :     "st\\u0061tic() {}",
    5163             :     "get st\\u0061tic() {}",
    5164             :     "set st\\u0061tic(v) {}",
    5165             :     "static st\\u0061tic() {}",
    5166             :     "static get st\\u0061tic() {}",
    5167             :     "static set st\\u0061tic(v) {}",
    5168             :     "*st\\u0061tic() {}",
    5169             :     "static *st\\u0061tic() {}",
    5170             : 
    5171             :     "static async x(){}",
    5172             :     "static async(){}",
    5173             :     "static *async(){}",
    5174             :     "async x(){}",
    5175             :     "async 0(){}",
    5176             :     "async get(){}",
    5177             :     "async set(){}",
    5178             :     "async static(){}",
    5179             :     "async async(){}",
    5180             :     "async(){}",
    5181             :     "*async(){}",
    5182           5 :     nullptr};
    5183             :   // clang-format on
    5184             : 
    5185           5 :   RunParserSyncTest(context_data, class_body_data, kSuccess);
    5186           5 : }
    5187             : 
    5188             : 
    5189       28342 : TEST(ClassPropertyNameNoErrors) {
    5190             :   const char* context_data[][2] = {{"(class {", "() {}});"},
    5191             :                                    {"(class { get ", "() {}});"},
    5192             :                                    {"(class { set ", "(v) {}});"},
    5193             :                                    {"(class { static ", "() {}});"},
    5194             :                                    {"(class { static get ", "() {}});"},
    5195             :                                    {"(class { static set ", "(v) {}});"},
    5196             :                                    {"(class { *", "() {}});"},
    5197             :                                    {"(class { static *", "() {}});"},
    5198             :                                    {"class C {", "() {}}"},
    5199             :                                    {"class C { get ", "() {}}"},
    5200             :                                    {"class C { set ", "(v) {}}"},
    5201             :                                    {"class C { static ", "() {}}"},
    5202             :                                    {"class C { static get ", "() {}}"},
    5203             :                                    {"class C { static set ", "(v) {}}"},
    5204             :                                    {"class C { *", "() {}}"},
    5205             :                                    {"class C { static *", "() {}}"},
    5206           5 :                                    {nullptr, nullptr}};
    5207             :   const char* name_data[] = {
    5208             :       "42",       "42.5",  "42e2",  "42e+2",   "42e-2",  "null",
    5209             :       "false",    "true",  "'str'", "\"str\"", "static", "get",
    5210             :       "set",      "var",   "const", "let",     "this",   "class",
    5211             :       "function", "yield", "if",    "else",    "for",    "while",
    5212           5 :       "do",       "try",   "catch", "finally", nullptr};
    5213             : 
    5214           5 :   RunParserSyncTest(context_data, name_data, kSuccess);
    5215           5 : }
    5216             : 
    5217       28342 : TEST(StaticClassFieldsNoErrors) {
    5218             :   // clang-format off
    5219             :   // Tests proposed class fields syntax.
    5220             :   const char* context_data[][2] = {{"(class {", "});"},
    5221             :                                    {"(class extends Base {", "});"},
    5222             :                                    {"class C {", "}"},
    5223             :                                    {"class C extends Base {", "}"},
    5224           5 :                                    {nullptr, nullptr}};
    5225             :   const char* class_body_data[] = {
    5226             :     // Basic syntax
    5227             :     "static a = 0;",
    5228             :     "static a = 0; b",
    5229             :     "static a = 0; b(){}",
    5230             :     "static a = 0; *b(){}",
    5231             :     "static a = 0; ['b'](){}",
    5232             :     "static a;",
    5233             :     "static a; b;",
    5234             :     "static a; b(){}",
    5235             :     "static a; *b(){}",
    5236             :     "static a; ['b'](){}",
    5237             :     "static ['a'] = 0;",
    5238             :     "static ['a'] = 0; b",
    5239             :     "static ['a'] = 0; b(){}",
    5240             :     "static ['a'] = 0; *b(){}",
    5241             :     "static ['a'] = 0; ['b'](){}",
    5242             :     "static ['a'];",
    5243             :     "static ['a']; b;",
    5244             :     "static ['a']; b(){}",
    5245             :     "static ['a']; *b(){}",
    5246             :     "static ['a']; ['b'](){}",
    5247             : 
    5248             :     "static 0 = 0;",
    5249             :     "static 0;",
    5250             :     "static 'a' = 0;",
    5251             :     "static 'a';",
    5252             : 
    5253             :     "static c = [c] = c",
    5254             : 
    5255             :     // ASI
    5256             :     "static a = 0\n",
    5257             :     "static a = 0\n b",
    5258             :     "static a = 0\n b(){}",
    5259             :     "static a\n",
    5260             :     "static a\n b\n",
    5261             :     "static a\n b(){}",
    5262             :     "static a\n *b(){}",
    5263             :     "static a\n ['b'](){}",
    5264             :     "static ['a'] = 0\n",
    5265             :     "static ['a'] = 0\n b",
    5266             :     "static ['a'] = 0\n b(){}",
    5267             :     "static ['a']\n",
    5268             :     "static ['a']\n b\n",
    5269             :     "static ['a']\n b(){}",
    5270             :     "static ['a']\n *b(){}",
    5271             :     "static ['a']\n ['b'](){}",
    5272             : 
    5273             :     "static a = function t() { arguments; }",
    5274             :     "static a = () => function t() { arguments; }",
    5275             : 
    5276             :     // ASI edge cases
    5277             :     "static a\n get",
    5278             :     "static get\n *a(){}",
    5279             :     "static a\n static",
    5280             : 
    5281             :     // Misc edge cases
    5282             :     "static yield",
    5283             :     "static yield = 0",
    5284             :     "static yield\n a",
    5285             :     "static async;",
    5286             :     "static async = 0;",
    5287             :     "static async",
    5288             :     "static async = 0",
    5289             :     "static async\n a(){}",  // a field named async, and a method named a.
    5290             :     "static async\n a",
    5291             :     "static await;",
    5292             :     "static await = 0;",
    5293             :     "static await\n a",
    5294             :     nullptr
    5295           5 :   };
    5296             :   // clang-format on
    5297             : 
    5298             :   static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
    5299             :                                             kAllowHarmonyStaticFields};
    5300             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5301           5 :                     always_flags, arraysize(always_flags));
    5302             : 
    5303             :   // Without the static flag, all of these are errors
    5304             :   static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
    5305             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5306           5 :                     no_static_flags, arraysize(no_static_flags));
    5307           5 : }
    5308             : 
    5309       28342 : TEST(ClassFieldsNoErrors) {
    5310             :   // clang-format off
    5311             :   // Tests proposed class fields syntax.
    5312             :   const char* context_data[][2] = {{"(class {", "});"},
    5313             :                                    {"(class extends Base {", "});"},
    5314             :                                    {"class C {", "}"},
    5315             :                                    {"class C extends Base {", "}"},
    5316           5 :                                    {nullptr, nullptr}};
    5317             :   const char* class_body_data[] = {
    5318             :     // Basic syntax
    5319             :     "a = 0;",
    5320             :     "a = 0; b",
    5321             :     "a = 0; b(){}",
    5322             :     "a = 0; *b(){}",
    5323             :     "a = 0; ['b'](){}",
    5324             :     "a;",
    5325             :     "a; b;",
    5326             :     "a; b(){}",
    5327             :     "a; *b(){}",
    5328             :     "a; ['b'](){}",
    5329             :     "['a'] = 0;",
    5330             :     "['a'] = 0; b",
    5331             :     "['a'] = 0; b(){}",
    5332             :     "['a'] = 0; *b(){}",
    5333             :     "['a'] = 0; ['b'](){}",
    5334             :     "['a'];",
    5335             :     "['a']; b;",
    5336             :     "['a']; b(){}",
    5337             :     "['a']; *b(){}",
    5338             :     "['a']; ['b'](){}",
    5339             : 
    5340             :     "0 = 0;",
    5341             :     "0;",
    5342             :     "'a' = 0;",
    5343             :     "'a';",
    5344             : 
    5345             :     "c = [c] = c",
    5346             : 
    5347             :     // ASI
    5348             :     "a = 0\n",
    5349             :     "a = 0\n b",
    5350             :     "a = 0\n b(){}",
    5351             :     "a\n",
    5352             :     "a\n b\n",
    5353             :     "a\n b(){}",
    5354             :     "a\n *b(){}",
    5355             :     "a\n ['b'](){}",
    5356             :     "['a'] = 0\n",
    5357             :     "['a'] = 0\n b",
    5358             :     "['a'] = 0\n b(){}",
    5359             :     "['a']\n",
    5360             :     "['a']\n b\n",
    5361             :     "['a']\n b(){}",
    5362             :     "['a']\n *b(){}",
    5363             :     "['a']\n ['b'](){}",
    5364             : 
    5365             :     // ASI edge cases
    5366             :     "a\n get",
    5367             :     "get\n *a(){}",
    5368             :     "a\n static",
    5369             : 
    5370             :     "a = function t() { arguments; }",
    5371             :     "a = () => function() { arguments; }",
    5372             : 
    5373             :     // Misc edge cases
    5374             :     "yield",
    5375             :     "yield = 0",
    5376             :     "yield\n a",
    5377             :     "async;",
    5378             :     "async = 0;",
    5379             :     "async",
    5380             :     "async = 0",
    5381             :     "async\n a(){}",  // a field named async, and a method named a.
    5382             :     "async\n a",
    5383             :     "await;",
    5384             :     "await = 0;",
    5385             :     "await\n a",
    5386             :     nullptr
    5387           5 :   };
    5388             :   // clang-format on
    5389             : 
    5390             :   static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
    5391             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5392           5 :                     always_flags, arraysize(always_flags));
    5393             : 
    5394             :   static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
    5395             :                                             kAllowHarmonyStaticFields};
    5396             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5397           5 :                     static_flags, arraysize(static_flags));
    5398           5 : }
    5399             : 
    5400       28342 : TEST(PrivateMethodsNoErrors) {
    5401             :   // clang-format off
    5402             :   // Tests proposed class methods syntax.
    5403             :   const char* context_data[][2] = {{"(class {", "});"},
    5404             :                                    {"(class extends Base {", "});"},
    5405             :                                    {"class C {", "}"},
    5406             :                                    {"class C extends Base {", "}"},
    5407           5 :                                    {nullptr, nullptr}};
    5408             :   const char* class_body_data[] = {
    5409             :     // Basic syntax
    5410             :     "#a() { }",
    5411             :     "get #a() { }",
    5412             :     "set #a(foo) { }",
    5413             :     "*#a() { }",
    5414             :     "async #a() { }",
    5415             :     "async *#a() { }",
    5416             : 
    5417             :     "#a() { } #b() {}",
    5418             :     "get #a() { } set #a(foo) {}",
    5419             :     "get #a() { } get #b() {} set #a(foo) {}",
    5420             :     "get #a() { } get #b() {} set #a(foo) {} set #b(foo) {}",
    5421             :     "set #a(foo) { } set #b(foo) {}",
    5422             :     "get #a() { } get #b() {}",
    5423             : 
    5424             :     "#a() { } static a() {}",
    5425             :     "#a() { } a() {}",
    5426             :     "#a() { } a() {} static a() {}",
    5427             :     "get #a() { } get a() {} static get a() {}",
    5428             :     "set #a(foo) { } set a(foo) {} static set a(foo) {}",
    5429             : 
    5430             :     "#a() { } get #b() {}",
    5431             :     "#a() { } async #b() {}",
    5432             :     "#a() { } async *#b() {}",
    5433             : 
    5434             :     // With arguments
    5435             :     "#a(...args) { }",
    5436             :     "#a(a = 1) { }",
    5437             :     "get #a() { }",
    5438             :     "set #a(a = (...args) => {}) { }",
    5439             : 
    5440             :     // Misc edge cases
    5441             :     "#get() {}",
    5442             :     "#set() {}",
    5443             :     "#yield() {}",
    5444             :     "#await() {}",
    5445             :     "#async() {}",
    5446             :     "#static() {}",
    5447             :     "#arguments() {}",
    5448             :     "get #yield() {}",
    5449             :     "get #await() {}",
    5450             :     "get #async() {}",
    5451             :     "get #get() {}",
    5452             :     "get #static() {}",
    5453             :     "get #arguments() {}",
    5454             :     "set #yield(test) {}",
    5455             :     "set #async(test) {}",
    5456             :     "set #await(test) {}",
    5457             :     "set #set(test) {}",
    5458             :     "set #static(test) {}",
    5459             :     "set #arguments(test) {}",
    5460             :     "async #yield() {}",
    5461             :     "async #async() {}",
    5462             :     "async #await() {}",
    5463             :     "async #get() {}",
    5464             :     "async #set() {}",
    5465             :     "async #static() {}",
    5466             :     "async #arguments() {}",
    5467             :     "*#async() {}",
    5468             :     "*#await() {}",
    5469             :     "*#yield() {}",
    5470             :     "*#get() {}",
    5471             :     "*#set() {}",
    5472             :     "*#static() {}",
    5473             :     "*#arguments() {}",
    5474             :     "async *#yield() {}",
    5475             :     "async *#async() {}",
    5476             :     "async *#await() {}",
    5477             :     "async *#get() {}",
    5478             :     "async *#set() {}",
    5479             :     "async *#static() {}",
    5480             :     "async *#arguments() {}",
    5481             :     nullptr
    5482           5 :   };
    5483             :   // clang-format on
    5484             : 
    5485           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5486             : 
    5487             :   static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
    5488             :                                                kAllowHarmonyPrivateMethods};
    5489             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5490           5 :                     private_methods, arraysize(private_methods));
    5491           5 : }
    5492             : 
    5493       28342 : TEST(PrivateMethodsAndFieldsNoErrors) {
    5494             :   // clang-format off
    5495             :   // Tests proposed class methods syntax in combination with fields
    5496             :   const char* context_data[][2] = {{"(class {", "});"},
    5497             :                                    {"(class extends Base {", "});"},
    5498             :                                    {"class C {", "}"},
    5499             :                                    {"class C extends Base {", "}"},
    5500           5 :                                    {nullptr, nullptr}};
    5501             :   const char* class_body_data[] = {
    5502             :     // Basic syntax
    5503             :     "#b;#a() { }",
    5504             :     "#b;get #a() { }",
    5505             :     "#b;set #a(foo) { }",
    5506             :     "#b;*#a() { }",
    5507             :     "#b;async #a() { }",
    5508             :     "#b;async *#a() { }",
    5509             :     "#b = 1;#a() { }",
    5510             :     "#b = 1;get #a() { }",
    5511             :     "#b = 1;set #a(foo) { }",
    5512             :     "#b = 1;*#a() { }",
    5513             :     "#b = 1;async #a() { }",
    5514             :     "#b = 1;async *#a() { }",
    5515             : 
    5516             :     // With public fields
    5517             :     "a;#a() { }",
    5518             :     "a;get #a() { }",
    5519             :     "a;set #a(foo) { }",
    5520             :     "a;*#a() { }",
    5521             :     "a;async #a() { }",
    5522             :     "a;async *#a() { }",
    5523             :     "a = 1;#a() { }",
    5524             :     "a = 1;get #a() { }",
    5525             :     "a = 1;set #a(foo) { }",
    5526             :     "a = 1;*#a() { }",
    5527             :     "a = 1;async #a() { }",
    5528             :     "a = 1;async *#a() { }",
    5529             : 
    5530             :     // ASI
    5531             :     "#a = 0\n #b(){}",
    5532             :     "#a\n *#b(){}",
    5533             :     "#a = 0\n get #b(){}",
    5534             :     "#a\n *#b(){}",
    5535             : 
    5536             :     "b = 0\n #b(){}",
    5537             :     "b\n *#b(){}",
    5538             :     "b = 0\n get #b(){}",
    5539             :     "b\n *#b(){}",
    5540             :     nullptr
    5541           5 :   };
    5542             :   // clang-format on
    5543             : 
    5544           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5545             : 
    5546             :   static const ParserFlag private_methods_and_fields[] = {
    5547             :       kAllowHarmonyPrivateFields, kAllowHarmonyPublicFields,
    5548             :       kAllowHarmonyPrivateMethods};
    5549             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5550             :                     private_methods_and_fields,
    5551           5 :                     arraysize(private_methods_and_fields));
    5552           5 : }
    5553             : 
    5554       28342 : TEST(PrivateMethodsErrors) {
    5555             :   // clang-format off
    5556             :   // Tests proposed class methods syntax in combination with fields
    5557             :   const char* context_data[][2] = {{"(class {", "});"},
    5558             :                                    {"(class extends Base {", "});"},
    5559             :                                    {"class C {", "}"},
    5560             :                                    {"class C extends Base {", "}"},
    5561           5 :                                    {nullptr, nullptr}};
    5562             :   const char* class_body_data[] = {
    5563             :     "#a() : 0",
    5564             :     "#a() =",
    5565             :     "#a() => {}",
    5566             :     "#a => {}",
    5567             :     "*#a() = 0",
    5568             :     "*#a() => 0",
    5569             :     "*#a() => {}",
    5570             :     "get #a()[]",
    5571             :     "yield #a()[]",
    5572             :     "yield #a => {}",
    5573             :     "async #a() = 0",
    5574             :     "async #a => {}",
    5575             :     "#a(arguments) {}",
    5576             :     "set #a(arguments) {}",
    5577             : 
    5578             :     "#['a']() { }",
    5579             :     "get #['a']() { }",
    5580             :     "set #['a'](foo) { }",
    5581             :     "*#['a']() { }",
    5582             :     "async #['a']() { }",
    5583             :     "async *#['a]() { }",
    5584             : 
    5585             :     // TODO(joyee): check duplicate accessors
    5586             : 
    5587             :     "#a\n#",
    5588             :     "#a() c",
    5589             :     "#a() #",
    5590             :     "#a(arg) c",
    5591             :     "#a(arg) #",
    5592             :     "#a(arg) #c",
    5593             :     "#a#",
    5594             :     "#a#b",
    5595             :     "#a#b(){}",
    5596             :     "#[test](){}",
    5597             : 
    5598             :     "async *#constructor() {}",
    5599             :     "*#constructor() {}",
    5600             :     "async #constructor() {}",
    5601             :     "set #constructor(test) {}",
    5602             :     "#constructor() {}",
    5603             :     "get #constructor() {}",
    5604             :     nullptr
    5605           5 :   };
    5606             :   // clang-format on
    5607             : 
    5608           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5609             : 
    5610             :   static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
    5611             :                                                kAllowHarmonyPrivateMethods};
    5612             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5613           5 :                     private_methods, arraysize(private_methods));
    5614           5 : }
    5615             : 
    5616             : // Test that private members do not parse outside class bodies
    5617       28342 : TEST(PrivateMembersInNonClassNoErrors) {
    5618             :   // clang-format off
    5619             :   const char* context_data[][2] = {{"", ""},
    5620             :                                    {"({", "})"},
    5621             :                                    {"'use strict'; ({", "});"},
    5622             :                                    {"function() {", "}"},
    5623             :                                    {"() => {", "}"},
    5624             :                                    {"class C { test() {", "} }"},
    5625           5 :                                    {nullptr, nullptr}};
    5626             :   const char* class_body_data[] = {
    5627             :     "#a = 1",
    5628             :     "#a = () => {}",
    5629             :     "#a",
    5630             :     "#a() { }",
    5631             :     "get #a() { }",
    5632             :     "set #a(foo) { }",
    5633             :     "*#a() { }",
    5634             :     "async #a() { }",
    5635             :     "async *#a() { }",
    5636             :     nullptr
    5637           5 :   };
    5638             :   // clang-format on
    5639             : 
    5640           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5641             : 
    5642             :   static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
    5643             :                                                kAllowHarmonyPrivateMethods};
    5644             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5645           5 :                     private_methods, arraysize(private_methods));
    5646           5 : }
    5647             : 
    5648       28342 : TEST(PrivateClassFieldsNoErrors) {
    5649             :   // clang-format off
    5650             :   // Tests proposed class fields syntax.
    5651             :   const char* context_data[][2] = {{"(class {", "});"},
    5652             :                                    {"(class extends Base {", "});"},
    5653             :                                    {"class C {", "}"},
    5654             :                                    {"class C extends Base {", "}"},
    5655           5 :                                    {nullptr, nullptr}};
    5656             :   const char* class_body_data[] = {
    5657             :     // Basic syntax
    5658             :     "#a = 0;",
    5659             :     "#a = 0; #b",
    5660             :     "#a = 0; b",
    5661             :     "#a = 0; b(){}",
    5662             :     "#a = 0; *b(){}",
    5663             :     "#a = 0; ['b'](){}",
    5664             :     "#a;",
    5665             :     "#a; #b;",
    5666             :     "#a; b;",
    5667             :     "#a; b(){}",
    5668             :     "#a; *b(){}",
    5669             :     "#a; ['b'](){}",
    5670             : 
    5671             :     // ASI
    5672             :     "#a = 0\n",
    5673             :     "#a = 0\n #b",
    5674             :     "#a = 0\n b",
    5675             :     "#a = 0\n b(){}",
    5676             :     "#a\n",
    5677             :     "#a\n #b\n",
    5678             :     "#a\n b\n",
    5679             :     "#a\n b(){}",
    5680             :     "#a\n *b(){}",
    5681             :     "#a\n ['b'](){}",
    5682             : 
    5683             :     // ASI edge cases
    5684             :     "#a\n get",
    5685             :     "#get\n *a(){}",
    5686             :     "#a\n static",
    5687             : 
    5688             :     "#a = function t() { arguments; }",
    5689             :     "#a = () => function() { arguments; }",
    5690             : 
    5691             :     // Misc edge cases
    5692             :     "#yield",
    5693             :     "#yield = 0",
    5694             :     "#yield\n a",
    5695             :     "#async;",
    5696             :     "#async = 0;",
    5697             :     "#async",
    5698             :     "#async = 0",
    5699             :     "#async\n a(){}",  // a field named async, and a method named a.
    5700             :     "#async\n a",
    5701             :     "#await;",
    5702             :     "#await = 0;",
    5703             :     "#await\n a",
    5704             :     nullptr
    5705           5 :   };
    5706             :   // clang-format on
    5707             : 
    5708           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5709             : 
    5710             :   static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
    5711             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5712           5 :                     private_fields, arraysize(private_fields));
    5713           5 : }
    5714             : 
    5715       28342 : TEST(StaticClassFieldsErrors) {
    5716             :   // clang-format off
    5717             :   // Tests proposed class fields syntax.
    5718             :   const char* context_data[][2] = {{"(class {", "});"},
    5719             :                                    {"(class extends Base {", "});"},
    5720             :                                    {"class C {", "}"},
    5721             :                                    {"class C extends Base {", "}"},
    5722           5 :                                    {nullptr, nullptr}};
    5723             :   const char* class_body_data[] = {
    5724             :     "static a : 0",
    5725             :     "static a =",
    5726             :     "static constructor",
    5727             :     "static prototype",
    5728             :     "static *a = 0",
    5729             :     "static *a",
    5730             :     "static get a",
    5731             :     "static get\n a",
    5732             :     "static yield a",
    5733             :     "static async a = 0",
    5734             :     "static async a",
    5735             : 
    5736             :     "static a = arguments",
    5737             :     "static a = () => arguments",
    5738             :     "static a = () => { arguments }",
    5739             :     "static a = arguments[0]",
    5740             :     "static a = delete arguments[0]",
    5741             :     "static a = f(arguments)",
    5742             :     "static a = () => () => arguments",
    5743             : 
    5744             :     // ASI requires a linebreak
    5745             :     "static a b",
    5746             :     "static a = 0 b",
    5747             : 
    5748             :     "static c = [1] = [c]",
    5749             : 
    5750             :     // ASI requires that the next token is not part of any legal production
    5751             :     "static a = 0\n *b(){}",
    5752             :     "static a = 0\n ['b'](){}",
    5753             :     nullptr
    5754           5 :   };
    5755             :   // clang-format on
    5756             : 
    5757             :   static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
    5758             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5759           5 :                     no_static_flags, arraysize(no_static_flags));
    5760             : 
    5761             :   static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
    5762             :                                             kAllowHarmonyStaticFields};
    5763             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5764           5 :                     always_flags, arraysize(always_flags));
    5765           5 : }
    5766             : 
    5767       28342 : TEST(ClassFieldsErrors) {
    5768             :   // clang-format off
    5769             :   // Tests proposed class fields syntax.
    5770             :   const char* context_data[][2] = {{"(class {", "});"},
    5771             :                                    {"(class extends Base {", "});"},
    5772             :                                    {"class C {", "}"},
    5773             :                                    {"class C extends Base {", "}"},
    5774           5 :                                    {nullptr, nullptr}};
    5775             :   const char* class_body_data[] = {
    5776             :     "a : 0",
    5777             :     "a =",
    5778             :     "constructor",
    5779             :     "*a = 0",
    5780             :     "*a",
    5781             :     "get a",
    5782             :     "yield a",
    5783             :     "async a = 0",
    5784             :     "async a",
    5785             : 
    5786             :     "a = arguments",
    5787             :     "a = () => arguments",
    5788             :     "a = () => { arguments }",
    5789             :     "a = arguments[0]",
    5790             :     "a = delete arguments[0]",
    5791             :     "a = f(arguments)",
    5792             :     "a = () => () => arguments",
    5793             : 
    5794             :     // ASI requires a linebreak
    5795             :     "a b",
    5796             :     "a = 0 b",
    5797             : 
    5798             :     "c = [1] = [c]",
    5799             : 
    5800             :     // ASI requires that the next token is not part of any legal production
    5801             :     "a = 0\n *b(){}",
    5802             :     "a = 0\n ['b'](){}",
    5803             :     "get\n a",
    5804             :     nullptr
    5805           5 :   };
    5806             :   // clang-format on
    5807             : 
    5808             :   static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
    5809             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5810           5 :                     always_flags, arraysize(always_flags));
    5811             : 
    5812             :   static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
    5813             :                                             kAllowHarmonyStaticFields};
    5814             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5815           5 :                     static_flags, arraysize(static_flags));
    5816           5 : }
    5817             : 
    5818       28342 : TEST(PrivateClassFieldsErrors) {
    5819             :   // clang-format off
    5820             :   // Tests proposed class fields syntax.
    5821             :   const char* context_data[][2] = {{"(class {", "});"},
    5822             :                                    {"(class extends Base {", "});"},
    5823             :                                    {"class C {", "}"},
    5824             :                                    {"class C extends Base {", "}"},
    5825           5 :                                    {nullptr, nullptr}};
    5826             :   const char* class_body_data[] = {
    5827             :     "#a : 0",
    5828             :     "#a =",
    5829             :     "#*a = 0",
    5830             :     "#*a",
    5831             :     "#get a",
    5832             :     "#yield a",
    5833             :     "#async a = 0",
    5834             :     "#async a",
    5835             : 
    5836             :     "#a; #a",
    5837             :     "#a = 1; #a",
    5838             :     "#a; #a = 1;",
    5839             : 
    5840             :     "#constructor",
    5841             :     "#constructor = function() {}",
    5842             : 
    5843             :     "# a = 0",
    5844             :     "#a() { }",
    5845             :     "get #a() { }",
    5846             :     "#get a() { }",
    5847             :     "set #a() { }",
    5848             :     "#set a() { }",
    5849             :     "*#a() { }",
    5850             :     "#*a() { }",
    5851             :     "async #a() { }",
    5852             :     "async *#a() { }",
    5853             :     "async #*a() { }",
    5854             : 
    5855             :     "#0 = 0;",
    5856             :     "#0;",
    5857             :     "#'a' = 0;",
    5858             :     "#'a';",
    5859             : 
    5860             :     "#['a']",
    5861             :     "#['a'] = 1",
    5862             :     "#[a]",
    5863             :     "#[a] = 1",
    5864             : 
    5865             :     "#a = arguments",
    5866             :     "#a = () => arguments",
    5867             :     "#a = () => { arguments }",
    5868             :     "#a = arguments[0]",
    5869             :     "#a = delete arguments[0]",
    5870             :     "#a = f(arguments)",
    5871             :     "#a = () => () => arguments",
    5872             : 
    5873             :     "foo() { delete this.#a }",
    5874             :     "foo() { delete this.x.#a }",
    5875             :     "foo() { delete this.x().#a }",
    5876             : 
    5877             :     "foo() { delete f.#a }",
    5878             :     "foo() { delete f.x.#a }",
    5879             :     "foo() { delete f.x().#a }",
    5880             : 
    5881             :     // ASI requires a linebreak
    5882             :     "#a b",
    5883             :     "#a = 0 b",
    5884             : 
    5885             :     // ASI requires that the next token is not part of any legal production
    5886             :     "#a = 0\n *b(){}",
    5887             :     "#a = 0\n ['b'](){}",
    5888             :     nullptr
    5889           5 :   };
    5890             :   // clang-format on
    5891             : 
    5892           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5893             : 
    5894             :   static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
    5895             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5896           5 :                     private_fields, arraysize(private_fields));
    5897           5 : }
    5898             : 
    5899       28342 : TEST(PrivateStaticClassFieldsNoErrors) {
    5900             :   // clang-format off
    5901             :   // Tests proposed class fields syntax.
    5902             :   const char* context_data[][2] = {{"(class {", "});"},
    5903             :                                    {"(class extends Base {", "});"},
    5904             :                                    {"class C {", "}"},
    5905             :                                    {"class C extends Base {", "}"},
    5906           5 :                                    {nullptr, nullptr}};
    5907             :   const char* class_body_data[] = {
    5908             :     // Basic syntax
    5909             :     "static #a = 0;",
    5910             :     "static #a = 0; b",
    5911             :     "static #a = 0; #b",
    5912             :     "static #a = 0; b(){}",
    5913             :     "static #a = 0; *b(){}",
    5914             :     "static #a = 0; ['b'](){}",
    5915             :     "static #a;",
    5916             :     "static #a; b;",
    5917             :     "static #a; b(){}",
    5918             :     "static #a; *b(){}",
    5919             :     "static #a; ['b'](){}",
    5920             : 
    5921             :     "#prototype",
    5922             :     "#prototype = function() {}",
    5923             : 
    5924             :     // ASI
    5925             :     "static #a = 0\n",
    5926             :     "static #a = 0\n b",
    5927             :     "static #a = 0\n #b",
    5928             :     "static #a = 0\n b(){}",
    5929             :     "static #a\n",
    5930             :     "static #a\n b\n",
    5931             :     "static #a\n #b\n",
    5932             :     "static #a\n b(){}",
    5933             :     "static #a\n *b(){}",
    5934             :     "static #a\n ['b'](){}",
    5935             : 
    5936             :     "static #a = function t() { arguments; }",
    5937             :     "static #a = () => function t() { arguments; }",
    5938             : 
    5939             :     // ASI edge cases
    5940             :     "static #a\n get",
    5941             :     "static #get\n *a(){}",
    5942             :     "static #a\n static",
    5943             : 
    5944             :     // Misc edge cases
    5945             :     "static #yield",
    5946             :     "static #yield = 0",
    5947             :     "static #yield\n a",
    5948             :     "static #async;",
    5949             :     "static #async = 0;",
    5950             :     "static #async",
    5951             :     "static #async = 0",
    5952             :     "static #async\n a(){}",  // a field named async, and a method named a.
    5953             :     "static #async\n a",
    5954             :     "static #await;",
    5955             :     "static #await = 0;",
    5956             :     "static #await\n a",
    5957             :     nullptr
    5958           5 :   };
    5959             :   // clang-format on
    5960             : 
    5961           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    5962             : 
    5963             :   static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
    5964             :                                                     kAllowHarmonyStaticFields};
    5965             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    5966           5 :                     public_static_fields, arraysize(public_static_fields));
    5967             : 
    5968             :   static const ParserFlag private_static_fields[] = {
    5969             :       kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
    5970             :       kAllowHarmonyPrivateFields};
    5971             :   RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
    5972           5 :                     private_static_fields, arraysize(private_static_fields));
    5973           5 : }
    5974             : 
    5975       28342 : TEST(PrivateStaticClassFieldsErrors) {
    5976             :   // clang-format off
    5977             :   // Tests proposed class fields syntax.
    5978             :   const char* context_data[][2] = {{"(class {", "});"},
    5979             :                                    {"(class extends Base {", "});"},
    5980             :                                    {"class C {", "}"},
    5981             :                                    {"class C extends Base {", "}"},
    5982           5 :                                    {nullptr, nullptr}};
    5983             :   const char* class_body_data[] = {
    5984             :     // Basic syntax
    5985             :     "static #['a'] = 0;",
    5986             :     "static #['a'] = 0; b",
    5987             :     "static #['a'] = 0; #b",
    5988             :     "static #['a'] = 0; b(){}",
    5989             :     "static #['a'] = 0; *b(){}",
    5990             :     "static #['a'] = 0; ['b'](){}",
    5991             :     "static #['a'];",
    5992             :     "static #['a']; b;",
    5993             :     "static #['a']; #b;",
    5994             :     "static #['a']; b(){}",
    5995             :     "static #['a']; *b(){}",
    5996             :     "static #['a']; ['b'](){}",
    5997             : 
    5998             :     "static #0 = 0;",
    5999             :     "static #0;",
    6000             :     "static #'a' = 0;",
    6001             :     "static #'a';",
    6002             : 
    6003             :     "static # a = 0",
    6004             :     "static #get a() { }",
    6005             :     "static #set a() { }",
    6006             :     "static #*a() { }",
    6007             :     "static async #*a() { }",
    6008             : 
    6009             :     "#a = arguments",
    6010             :     "#a = () => arguments",
    6011             :     "#a = () => { arguments }",
    6012             :     "#a = arguments[0]",
    6013             :     "#a = delete arguments[0]",
    6014             :     "#a = f(arguments)",
    6015             :     "#a = () => () => arguments",
    6016             : 
    6017             :     "#a; static #a",
    6018             :     "static #a; #a",
    6019             : 
    6020             :     // TODO(joyee): support static private methods
    6021             :     "static #a() { }",
    6022             :     "static get #a() { }",
    6023             :     "static set #a() { }",
    6024             :     "static *#a() { }",
    6025             :     "static async #a() { }",
    6026             :     "static async *#a() { }",
    6027             : 
    6028             :     // ASI
    6029             :     "static #['a'] = 0\n",
    6030             :     "static #['a'] = 0\n b",
    6031             :     "static #['a'] = 0\n #b",
    6032             :     "static #['a'] = 0\n b(){}",
    6033             :     "static #['a']\n",
    6034             :     "static #['a']\n b\n",
    6035             :     "static #['a']\n #b\n",
    6036             :     "static #['a']\n b(){}",
    6037             :     "static #['a']\n *b(){}",
    6038             :     "static #['a']\n ['b'](){}",
    6039             : 
    6040             :     // ASI requires a linebreak
    6041             :     "static #a b",
    6042             :     "static #a = 0 b",
    6043             : 
    6044             :     // ASI requires that the next token is not part of any legal production
    6045             :     "static #a = 0\n *b(){}",
    6046             :     "static #a = 0\n ['b'](){}",
    6047             : 
    6048             :     "static #a : 0",
    6049             :     "static #a =",
    6050             :     "static #*a = 0",
    6051             :     "static #*a",
    6052             :     "static #get a",
    6053             :     "static #yield a",
    6054             :     "static #async a = 0",
    6055             :     "static #async a",
    6056             :     "static # a = 0",
    6057             : 
    6058             :     "#constructor",
    6059             :     "#constructor = function() {}",
    6060             : 
    6061             :     "foo() { delete this.#a }",
    6062             :     "foo() { delete this.x.#a }",
    6063             :     "foo() { delete this.x().#a }",
    6064             : 
    6065             :     "foo() { delete f.#a }",
    6066             :     "foo() { delete f.x.#a }",
    6067             :     "foo() { delete f.x().#a }",
    6068             :     nullptr
    6069           5 :   };
    6070             :   // clang-format on
    6071             : 
    6072           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    6073             : 
    6074             :   static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
    6075             :                                                     kAllowHarmonyStaticFields};
    6076             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    6077           5 :                     public_static_fields, arraysize(public_static_fields));
    6078             : 
    6079             :   static const ParserFlag private_static_fields[] = {
    6080             :       kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
    6081             :       kAllowHarmonyPrivateFields};
    6082             :   RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
    6083           5 :                     private_static_fields, arraysize(private_static_fields));
    6084           5 : }
    6085             : 
    6086       28342 : TEST(PrivateNameNoErrors) {
    6087             :   // clang-format off
    6088             :   const char* context_data[][2] = {
    6089             :       {"", ""},
    6090             :       {"\"use strict\";", ""},
    6091             :       {nullptr, nullptr}
    6092           5 :   };
    6093             : 
    6094             :   const char* statement_data[] = {
    6095             :     "this.#a",
    6096             :     "this.#a()",
    6097             :     "this.#b.#a",
    6098             :     "this.#b.#a()",
    6099             : 
    6100             :     "foo.#a",
    6101             :     "foo.#a()",
    6102             :     "foo.#b.#a",
    6103             :     "foo.#b.#a()",
    6104             : 
    6105             :     "foo().#a",
    6106             :     "foo().b.#a",
    6107             :     "foo().b().#a",
    6108             :     "foo().b().#a()",
    6109             :     "foo().b().#a.bar",
    6110             :     "foo().b().#a.bar()",
    6111             : 
    6112             :     "foo(this.#a)",
    6113             :     "foo(bar().#a)",
    6114             : 
    6115             :     "new foo.#a",
    6116             :     "new foo.#b.#a",
    6117             :     "new foo.#b.#a()",
    6118             : 
    6119             :     "foo.#if;",
    6120             :     "foo.#yield;",
    6121             :     "foo.#super;",
    6122             :     "foo.#interface;",
    6123             :     "foo.#eval;",
    6124             :     "foo.#arguments;",
    6125             : 
    6126             :     nullptr
    6127           5 :   };
    6128             : 
    6129             :   // clang-format on
    6130           5 :   RunParserSyncTest(context_data, statement_data, kError);
    6131             : 
    6132             :   static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
    6133             :   RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
    6134           5 :                     private_fields, arraysize(private_fields));
    6135           5 : }
    6136             : 
    6137       28342 : TEST(PrivateNameErrors) {
    6138             :   // clang-format off
    6139             :   const char* context_data[][2] = {
    6140             :       {"", ""},
    6141             :       {"\"use strict\";", ""},
    6142             :       {nullptr, nullptr}
    6143           5 :   };
    6144             : 
    6145             :   const char* statement_data[] = {
    6146             :     "#foo",
    6147             :     "#foo = 1",
    6148             : 
    6149             :     "# a;",
    6150             :     "#\n a;",
    6151             :     "a, # b",
    6152             :     "a, #, b;",
    6153             : 
    6154             :     "foo.#[a];",
    6155             :     "foo.#['a'];",
    6156             : 
    6157             :     "foo()#a",
    6158             :     "foo()#[a]",
    6159             :     "foo()#['a']",
    6160             : 
    6161             :     "super.#a;",
    6162             :     "super.#a = 1;",
    6163             :     "super.#['a']",
    6164             :     "super.#[a]",
    6165             : 
    6166             :     "new.#a",
    6167             :     "new.#[a]",
    6168             : 
    6169             :     "foo.#{;",
    6170             :     "foo.#};",
    6171             :     "foo.#=;",
    6172             :     "foo.#888;",
    6173             :     "foo.#-;",
    6174             :     "foo.#--;",
    6175             :     nullptr
    6176           5 :   };
    6177             : 
    6178             :   // clang-format on
    6179           5 :   RunParserSyncTest(context_data, statement_data, kError);
    6180             : 
    6181             :   static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
    6182             :   RunParserSyncTest(context_data, statement_data, kError, nullptr, 0,
    6183           5 :                     private_fields, arraysize(private_fields));
    6184           5 : }
    6185             : 
    6186       28342 : TEST(ClassExpressionErrors) {
    6187             :   const char* context_data[][2] = {
    6188           5 :       {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
    6189             :   const char* class_data[] = {
    6190             :       "class",
    6191             :       "class name",
    6192             :       "class name extends",
    6193             :       "class extends",
    6194             :       "class {",
    6195             :       "class { m }",
    6196             :       "class { m; n }",
    6197             :       "class { m: 1 }",
    6198             :       "class { m(); n() }",
    6199             :       "class { get m }",
    6200             :       "class { get m() }",
    6201             :       "class { get m() { }",
    6202             :       "class { set m() {} }",      // Missing required parameter.
    6203             :       "class { m() {}, n() {} }",  // No commas allowed.
    6204           5 :       nullptr};
    6205             : 
    6206           5 :   RunParserSyncTest(context_data, class_data, kError);
    6207           5 : }
    6208             : 
    6209             : 
    6210       28342 : TEST(ClassDeclarationErrors) {
    6211             :   const char* context_data[][2] = {
    6212           5 :       {"", ""}, {"{", "}"}, {"if (true) {", "}"}, {nullptr, nullptr}};
    6213             :   const char* class_data[] = {
    6214             :       "class",
    6215             :       "class name",
    6216             :       "class name extends",
    6217             :       "class extends",
    6218             :       "class name {",
    6219             :       "class name { m }",
    6220             :       "class name { m; n }",
    6221             :       "class name { m: 1 }",
    6222             :       "class name { m(); n() }",
    6223             :       "class name { get x }",
    6224             :       "class name { get x() }",
    6225             :       "class name { set x() {) }",  // missing required param
    6226             :       "class {}",                   // Name is required for declaration
    6227             :       "class extends base {}",
    6228             :       "class name { *",
    6229             :       "class name { * }",
    6230             :       "class name { *; }",
    6231             :       "class name { *get x() {} }",
    6232             :       "class name { *set x(_) {} }",
    6233             :       "class name { *static m() {} }",
    6234           5 :       nullptr};
    6235             : 
    6236           5 :   RunParserSyncTest(context_data, class_data, kError);
    6237           5 : }
    6238             : 
    6239       28342 : TEST(ClassAsyncErrors) {
    6240             :   // clang-format off
    6241             :   const char* context_data[][2] = {{"(class {", "});"},
    6242             :                                    {"(class extends Base {", "});"},
    6243             :                                    {"class C {", "}"},
    6244             :                                    {"class C extends Base {", "}"},
    6245           5 :                                    {nullptr, nullptr}};
    6246             :   const char* async_data[] = {
    6247             :     "*async x(){}",
    6248             :     "async *(){}",
    6249             :     "async get x(){}",
    6250             :     "async set x(y){}",
    6251             :     "async x : 0",
    6252             :     "async : 0",
    6253             : 
    6254             :     "async static x(){}",
    6255             : 
    6256             :     "static *async x(){}",
    6257             :     "static async *(){}",
    6258             :     "static async get x(){}",
    6259             :     "static async set x(y){}",
    6260             :     "static async x : 0",
    6261             :     "static async : 0",
    6262             :     nullptr
    6263           5 :   };
    6264             :   // clang-format on
    6265             : 
    6266           5 :   RunParserSyncTest(context_data, async_data, kError);
    6267           5 : }
    6268             : 
    6269       28342 : TEST(ClassNameErrors) {
    6270             :   const char* context_data[][2] = {{"class ", "{}"},
    6271             :                                    {"(class ", "{});"},
    6272             :                                    {"'use strict'; class ", "{}"},
    6273             :                                    {"'use strict'; (class ", "{});"},
    6274           5 :                                    {nullptr, nullptr}};
    6275             :   const char* class_name[] = {"arguments", "eval",    "implements", "interface",
    6276             :                               "let",       "package", "private",    "protected",
    6277             :                               "public",    "static",  "var",        "yield",
    6278           5 :                               nullptr};
    6279             : 
    6280           5 :   RunParserSyncTest(context_data, class_name, kError);
    6281           5 : }
    6282             : 
    6283             : 
    6284       28342 : TEST(ClassGetterParamNameErrors) {
    6285             :   const char* context_data[][2] = {
    6286             :       {"class C { get name(", ") {} }"},
    6287             :       {"(class { get name(", ") {} });"},
    6288             :       {"'use strict'; class C { get name(", ") {} }"},
    6289             :       {"'use strict'; (class { get name(", ") {} })"},
    6290           5 :       {nullptr, nullptr}};
    6291             : 
    6292             :   const char* class_name[] = {"arguments", "eval",    "implements", "interface",
    6293             :                               "let",       "package", "private",    "protected",
    6294             :                               "public",    "static",  "var",        "yield",
    6295           5 :                               nullptr};
    6296             : 
    6297           5 :   RunParserSyncTest(context_data, class_name, kError);
    6298           5 : }
    6299             : 
    6300             : 
    6301       28342 : TEST(ClassStaticPrototypeErrors) {
    6302             :   const char* context_data[][2] = {
    6303           5 :       {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
    6304             : 
    6305             :   const char* class_body_data[] = {"static prototype() {}",
    6306             :                                    "static get prototype() {}",
    6307             :                                    "static set prototype(_) {}",
    6308             :                                    "static *prototype() {}",
    6309             :                                    "static 'prototype'() {}",
    6310             :                                    "static *'prototype'() {}",
    6311             :                                    "static prot\\u006ftype() {}",
    6312             :                                    "static 'prot\\u006ftype'() {}",
    6313             :                                    "static get 'prot\\u006ftype'() {}",
    6314             :                                    "static set 'prot\\u006ftype'(_) {}",
    6315             :                                    "static *'prot\\u006ftype'() {}",
    6316           5 :                                    nullptr};
    6317             : 
    6318           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    6319           5 : }
    6320             : 
    6321             : 
    6322       28342 : TEST(ClassSpecialConstructorErrors) {
    6323             :   const char* context_data[][2] = {
    6324           5 :       {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
    6325             : 
    6326             :   const char* class_body_data[] = {"get constructor() {}",
    6327             :                                    "get constructor(_) {}",
    6328             :                                    "*constructor() {}",
    6329             :                                    "get 'constructor'() {}",
    6330             :                                    "*'constructor'() {}",
    6331             :                                    "get c\\u006fnstructor() {}",
    6332             :                                    "*c\\u006fnstructor() {}",
    6333             :                                    "get 'c\\u006fnstructor'() {}",
    6334             :                                    "get 'c\\u006fnstructor'(_) {}",
    6335             :                                    "*'c\\u006fnstructor'() {}",
    6336           5 :                                    nullptr};
    6337             : 
    6338           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    6339           5 : }
    6340             : 
    6341             : 
    6342       28342 : TEST(ClassConstructorNoErrors) {
    6343             :   const char* context_data[][2] = {
    6344           5 :       {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
    6345             : 
    6346             :   const char* class_body_data[] = {"constructor() {}",
    6347             :                                    "static constructor() {}",
    6348             :                                    "static get constructor() {}",
    6349             :                                    "static set constructor(_) {}",
    6350             :                                    "static *constructor() {}",
    6351           5 :                                    nullptr};
    6352             : 
    6353           5 :   RunParserSyncTest(context_data, class_body_data, kSuccess);
    6354           5 : }
    6355             : 
    6356             : 
    6357       28342 : TEST(ClassMultipleConstructorErrors) {
    6358             :   const char* context_data[][2] = {
    6359           5 :       {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
    6360             : 
    6361             :   const char* class_body_data[] = {"constructor() {}; constructor() {}",
    6362           5 :                                    nullptr};
    6363             : 
    6364           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    6365           5 : }
    6366             : 
    6367             : 
    6368       28342 : TEST(ClassMultiplePropertyNamesNoErrors) {
    6369             :   const char* context_data[][2] = {
    6370           5 :       {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
    6371             : 
    6372             :   const char* class_body_data[] = {
    6373             :       "constructor() {}; static constructor() {}",
    6374             :       "m() {}; static m() {}",
    6375             :       "m() {}; m() {}",
    6376             :       "static m() {}; static m() {}",
    6377             :       "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
    6378           5 :       nullptr};
    6379             : 
    6380           5 :   RunParserSyncTest(context_data, class_body_data, kSuccess);
    6381           5 : }
    6382             : 
    6383             : 
    6384       28342 : TEST(ClassesAreStrictErrors) {
    6385           5 :   const char* context_data[][2] = {{"", ""}, {"(", ");"}, {nullptr, nullptr}};
    6386             : 
    6387             :   const char* class_body_data[] = {
    6388             :       "class C { method() { with ({}) {} } }",
    6389             :       "class C extends function() { with ({}) {} } {}",
    6390           5 :       "class C { *method() { with ({}) {} } }", nullptr};
    6391             : 
    6392           5 :   RunParserSyncTest(context_data, class_body_data, kError);
    6393           5 : }
    6394             : 
    6395             : 
    6396       28342 : TEST(ObjectLiteralPropertyShorthandKeywordsError) {
    6397             :   const char* context_data[][2] = {
    6398           5 :       {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
    6399             : 
    6400             :   const char* name_data[] = {
    6401             :       "break",    "case",    "catch",  "class",      "const", "continue",
    6402             :       "debugger", "default", "delete", "do",         "else",  "enum",
    6403             :       "export",   "extends", "false",  "finally",    "for",   "function",
    6404             :       "if",       "import",  "in",     "instanceof", "new",   "null",
    6405             :       "return",   "super",   "switch", "this",       "throw", "true",
    6406             :       "try",      "typeof",  "var",    "void",       "while", "with",
    6407           5 :       nullptr};
    6408             : 
    6409           5 :   RunParserSyncTest(context_data, name_data, kError);
    6410           5 : }
    6411             : 
    6412             : 
    6413       28342 : TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
    6414           5 :   const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
    6415             : 
    6416             :   const char* name_data[] = {"implements", "interface", "let",    "package",
    6417             :                              "private",    "protected", "public", "static",
    6418           5 :                              "yield",      nullptr};
    6419             : 
    6420           5 :   RunParserSyncTest(context_data, name_data, kSuccess);
    6421             : 
    6422             :   const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
    6423           5 :                                           {nullptr, nullptr}};
    6424           5 :   RunParserSyncTest(context_strict_data, name_data, kError);
    6425           5 : }
    6426             : 
    6427             : 
    6428       28342 : TEST(ObjectLiteralPropertyShorthandError) {
    6429             :   const char* context_data[][2] = {
    6430           5 :       {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
    6431             : 
    6432             :   const char* name_data[] = {"1",   "1.2", "0",     "0.1", "1.0",
    6433           5 :                              "1e1", "0x1", "\"s\"", "'s'", nullptr};
    6434             : 
    6435           5 :   RunParserSyncTest(context_data, name_data, kError);
    6436           5 : }
    6437             : 
    6438             : 
    6439       28342 : TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
    6440           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    6441             : 
    6442           5 :   const char* name_data[] = {"function* g() { ({yield}); }", nullptr};
    6443             : 
    6444           5 :   RunParserSyncTest(context_data, name_data, kError);
    6445           5 : }
    6446             : 
    6447             : 
    6448       28342 : TEST(ConstParsingInForIn) {
    6449             :   const char* context_data[][2] = {{"'use strict';", ""},
    6450             :                                    {"function foo(){ 'use strict';", "}"},
    6451           5 :                                    {nullptr, nullptr}};
    6452             : 
    6453             :   const char* data[] = {
    6454             :       "for(const x = 1; ; ) {}", "for(const x = 1, y = 2;;){}",
    6455           5 :       "for(const x in [1,2,3]) {}", "for(const x of [1,2,3]) {}", nullptr};
    6456           5 :   RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
    6457           5 : }
    6458             : 
    6459             : 
    6460       28342 : TEST(StatementParsingInForIn) {
    6461             :   const char* context_data[][2] = {{"", ""},
    6462             :                                    {"'use strict';", ""},
    6463             :                                    {"function foo(){ 'use strict';", "}"},
    6464           5 :                                    {nullptr, nullptr}};
    6465             : 
    6466             :   const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
    6467             :                         "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
    6468           5 :                         nullptr};
    6469             : 
    6470           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6471           5 : }
    6472             : 
    6473             : 
    6474       28342 : TEST(ConstParsingInForInError) {
    6475             :   const char* context_data[][2] = {{"'use strict';", ""},
    6476             :                                    {"function foo(){ 'use strict';", "}"},
    6477           5 :                                    {nullptr, nullptr}};
    6478             : 
    6479             :   const char* data[] = {
    6480             :       "for(const x,y = 1; ; ) {}",         "for(const x = 4 in [1,2,3]) {}",
    6481             :       "for(const x = 4, y in [1,2,3]) {}", "for(const x = 4 of [1,2,3]) {}",
    6482             :       "for(const x = 4, y of [1,2,3]) {}", "for(const x = 1, y = 2 in []) {}",
    6483             :       "for(const x,y in []) {}",           "for(const x = 1, y = 2 of []) {}",
    6484           5 :       "for(const x,y of []) {}",           nullptr};
    6485           5 :   RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
    6486           5 : }
    6487             : 
    6488       28342 : TEST(InitializedDeclarationsInForInOf) {
    6489             :   // https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads
    6490             : 
    6491             :   // Initialized declarations only allowed for
    6492             :   // - sloppy mode (not strict mode)
    6493             :   // - for-in (not for-of)
    6494             :   // - var (not let / const)
    6495             : 
    6496             :   // clang-format off
    6497             :   const char* strict_context[][2] = {{"'use strict';", ""},
    6498             :                                      {"function foo(){ 'use strict';", "}"},
    6499             :                                      {"function* foo(){ 'use strict';", "}"},
    6500           5 :                                      {nullptr, nullptr}};
    6501             : 
    6502             :   const char* sloppy_context[][2] = {{"", ""},
    6503             :                                      {"function foo(){ ", "}"},
    6504             :                                      {"function* foo(){ ", "}"},
    6505             :                                      {"function foo(){ var yield = 0; ", "}"},
    6506           5 :                                      {nullptr, nullptr}};
    6507             : 
    6508             :   const char* let_const_var_for_of[] = {
    6509             :       "for (let i = 1 of {}) {}",
    6510             :       "for (let i = void 0 of [1, 2, 3]) {}",
    6511             :       "for (const i = 1 of {}) {}",
    6512             :       "for (const i = void 0 of [1, 2, 3]) {}",
    6513             :       "for (var i = 1 of {}) {}",
    6514             :       "for (var i = void 0 of [1, 2, 3]) {}",
    6515           5 :       nullptr};
    6516             : 
    6517             :   const char* let_const_for_in[] = {
    6518             :       "for (let i = 1 in {}) {}",
    6519             :       "for (let i = void 0 in [1, 2, 3]) {}",
    6520             :       "for (const i = 1 in {}) {}",
    6521             :       "for (const i = void 0 in [1, 2, 3]) {}",
    6522           5 :       nullptr};
    6523             : 
    6524             :   const char* var_for_in[] = {
    6525             :       "for (var i = 1 in {}) {}",
    6526             :       "for (var i = void 0 in [1, 2, 3]) {}",
    6527             :       "for (var i = yield in [1, 2, 3]) {}",
    6528           5 :       nullptr};
    6529             :   // clang-format on
    6530             : 
    6531             :   // The only allowed case is sloppy + var + for-in.
    6532           5 :   RunParserSyncTest(sloppy_context, var_for_in, kSuccess);
    6533             : 
    6534             :   // Everything else is disallowed.
    6535           5 :   RunParserSyncTest(sloppy_context, let_const_var_for_of, kError);
    6536           5 :   RunParserSyncTest(sloppy_context, let_const_for_in, kError);
    6537             : 
    6538           5 :   RunParserSyncTest(strict_context, let_const_var_for_of, kError);
    6539           5 :   RunParserSyncTest(strict_context, let_const_for_in, kError);
    6540           5 :   RunParserSyncTest(strict_context, var_for_in, kError);
    6541           5 : }
    6542             : 
    6543       28342 : TEST(ForInMultipleDeclarationsError) {
    6544             :   const char* context_data[][2] = {{"", ""},
    6545             :                                    {"function foo(){", "}"},
    6546             :                                    {"'use strict';", ""},
    6547             :                                    {"function foo(){ 'use strict';", "}"},
    6548           5 :                                    {nullptr, nullptr}};
    6549             : 
    6550             :   const char* data[] = {"for (var i, j in {}) {}",
    6551             :                         "for (var i, j in [1, 2, 3]) {}",
    6552             :                         "for (var i, j = 1 in {}) {}",
    6553             :                         "for (var i, j = void 0 in [1, 2, 3]) {}",
    6554             : 
    6555             :                         "for (let i, j in {}) {}",
    6556             :                         "for (let i, j in [1, 2, 3]) {}",
    6557             :                         "for (let i, j = 1 in {}) {}",
    6558             :                         "for (let i, j = void 0 in [1, 2, 3]) {}",
    6559             : 
    6560             :                         "for (const i, j in {}) {}",
    6561             :                         "for (const i, j in [1, 2, 3]) {}",
    6562             :                         "for (const i, j = 1 in {}) {}",
    6563             :                         "for (const i, j = void 0 in [1, 2, 3]) {}",
    6564           5 :                         nullptr};
    6565           5 :   RunParserSyncTest(context_data, data, kError);
    6566           5 : }
    6567             : 
    6568             : 
    6569       28342 : TEST(ForOfMultipleDeclarationsError) {
    6570             :   const char* context_data[][2] = {{"", ""},
    6571             :                                    {"function foo(){", "}"},
    6572             :                                    {"'use strict';", ""},
    6573             :                                    {"function foo(){ 'use strict';", "}"},
    6574           5 :                                    {nullptr, nullptr}};
    6575             : 
    6576             :   const char* data[] = {"for (var i, j of {}) {}",
    6577             :                         "for (var i, j of [1, 2, 3]) {}",
    6578             :                         "for (var i, j = 1 of {}) {}",
    6579             :                         "for (var i, j = void 0 of [1, 2, 3]) {}",
    6580             : 
    6581             :                         "for (let i, j of {}) {}",
    6582             :                         "for (let i, j of [1, 2, 3]) {}",
    6583             :                         "for (let i, j = 1 of {}) {}",
    6584             :                         "for (let i, j = void 0 of [1, 2, 3]) {}",
    6585             : 
    6586             :                         "for (const i, j of {}) {}",
    6587             :                         "for (const i, j of [1, 2, 3]) {}",
    6588             :                         "for (const i, j = 1 of {}) {}",
    6589             :                         "for (const i, j = void 0 of [1, 2, 3]) {}",
    6590           5 :                         nullptr};
    6591           5 :   RunParserSyncTest(context_data, data, kError);
    6592           5 : }
    6593             : 
    6594             : 
    6595       28342 : TEST(ForInNoDeclarationsError) {
    6596             :   const char* context_data[][2] = {{"", ""},
    6597             :                                    {"function foo(){", "}"},
    6598             :                                    {"'use strict';", ""},
    6599             :                                    {"function foo(){ 'use strict';", "}"},
    6600           5 :                                    {nullptr, nullptr}};
    6601             : 
    6602           5 :   const char* data[] = {"for (var in {}) {}", "for (const in {}) {}", nullptr};
    6603           5 :   RunParserSyncTest(context_data, data, kError);
    6604           5 : }
    6605             : 
    6606             : 
    6607       28342 : TEST(ForOfNoDeclarationsError) {
    6608             :   const char* context_data[][2] = {{"", ""},
    6609             :                                    {"function foo(){", "}"},
    6610             :                                    {"'use strict';", ""},
    6611             :                                    {"function foo(){ 'use strict';", "}"},
    6612           5 :                                    {nullptr, nullptr}};
    6613             : 
    6614             :   const char* data[] = {"for (var of [1, 2, 3]) {}",
    6615           5 :                         "for (const of [1, 2, 3]) {}", nullptr};
    6616           5 :   RunParserSyncTest(context_data, data, kError);
    6617           5 : }
    6618             : 
    6619             : 
    6620       28342 : TEST(ForOfInOperator) {
    6621             :   const char* context_data[][2] = {{"", ""},
    6622             :                                    {"'use strict';", ""},
    6623             :                                    {"function foo(){ 'use strict';", "}"},
    6624           5 :                                    {nullptr, nullptr}};
    6625             : 
    6626             :   const char* data[] = {"for(x of 'foo' in {}) {}",
    6627             :                         "for(var x of 'foo' in {}) {}",
    6628             :                         "for(let x of 'foo' in {}) {}",
    6629           5 :                         "for(const x of 'foo' in {}) {}", nullptr};
    6630             : 
    6631           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6632           5 : }
    6633             : 
    6634             : 
    6635       28342 : TEST(ForOfYieldIdentifier) {
    6636           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    6637             : 
    6638             :   const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
    6639             :                         "for(let x of yield) {}", "for(const x of yield) {}",
    6640           5 :                         nullptr};
    6641             : 
    6642           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6643           5 : }
    6644             : 
    6645             : 
    6646       28342 : TEST(ForOfYieldExpression) {
    6647             :   const char* context_data[][2] = {{"", ""},
    6648             :                                    {"'use strict';", ""},
    6649             :                                    {"function foo(){ 'use strict';", "}"},
    6650           5 :                                    {nullptr, nullptr}};
    6651             : 
    6652             :   const char* data[] = {"function* g() { for(x of yield) {} }",
    6653             :                         "function* g() { for(var x of yield) {} }",
    6654             :                         "function* g() { for(let x of yield) {} }",
    6655           5 :                         "function* g() { for(const x of yield) {} }", nullptr};
    6656             : 
    6657           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6658           5 : }
    6659             : 
    6660             : 
    6661       28342 : TEST(ForOfExpressionError) {
    6662             :   const char* context_data[][2] = {{"", ""},
    6663             :                                    {"'use strict';", ""},
    6664             :                                    {"function foo(){ 'use strict';", "}"},
    6665           5 :                                    {nullptr, nullptr}};
    6666             : 
    6667             :   const char* data[] = {
    6668             :       "for(x of [], []) {}", "for(var x of [], []) {}",
    6669             :       "for(let x of [], []) {}", "for(const x of [], []) {}",
    6670             : 
    6671             :       // AssignmentExpression should be validated statically:
    6672             :       "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
    6673           5 :       "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", nullptr};
    6674             : 
    6675           5 :   RunParserSyncTest(context_data, data, kError);
    6676           5 : }
    6677             : 
    6678             : 
    6679       28342 : TEST(InvalidUnicodeEscapes) {
    6680             :   const char* context_data[][2] = {
    6681           5 :       {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
    6682             :   const char* data[] = {
    6683             :       "var foob\\u123r = 0;", "var \\u123roo = 0;", "\"foob\\u123rr\"",
    6684             :       // No escapes allowed in regexp flags
    6685             :       "/regex/\\u0069g", "/regex/\\u006g",
    6686             :       // Braces gone wrong
    6687             :       "var foob\\u{c481r = 0;", "var foob\\uc481}r = 0;", "var \\u{0052oo = 0;",
    6688             :       "var \\u0052}oo = 0;", "\"foob\\u{c481r\"", "var foob\\u{}ar = 0;",
    6689             :       // Too high value for the Unicode code point escape
    6690             :       "\"\\u{110000}\"",
    6691             :       // Not a Unicode code point escape
    6692             :       "var foob\\v1234r = 0;", "var foob\\U1234r = 0;",
    6693           5 :       "var foob\\v{1234}r = 0;", "var foob\\U{1234}r = 0;", nullptr};
    6694           5 :   RunParserSyncTest(context_data, data, kError);
    6695           5 : }
    6696             : 
    6697             : 
    6698       28342 : TEST(UnicodeEscapes) {
    6699             :   const char* context_data[][2] = {
    6700           5 :       {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
    6701             :   const char* data[] = {
    6702             :       // Identifier starting with escape
    6703             :       "var \\u0052oo = 0;", "var \\u{0052}oo = 0;", "var \\u{52}oo = 0;",
    6704             :       "var \\u{00000000052}oo = 0;",
    6705             :       // Identifier with an escape but not starting with an escape
    6706             :       "var foob\\uc481r = 0;", "var foob\\u{c481}r = 0;",
    6707             :       // String with an escape
    6708             :       "\"foob\\uc481r\"", "\"foob\\{uc481}r\"",
    6709             :       // This character is a valid Unicode character, representable as a
    6710             :       // surrogate pair, not representable as 4 hex digits.
    6711             :       "\"foo\\u{10e6d}\"",
    6712             :       // Max value for the Unicode code point escape
    6713           5 :       "\"\\u{10ffff}\"", nullptr};
    6714           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6715           5 : }
    6716             : 
    6717       28342 : TEST(OctalEscapes) {
    6718             :   const char* sloppy_context_data[][2] = {{"", ""},    // as a directive
    6719             :                                           {"0;", ""},  // as a string literal
    6720           5 :                                           {nullptr, nullptr}};
    6721             : 
    6722             :   const char* strict_context_data[][2] = {
    6723             :       {"'use strict';", ""},     // as a directive before 'use strict'
    6724             :       {"", ";'use strict';"},    // as a directive after 'use strict'
    6725             :       {"'use strict'; 0;", ""},  // as a string literal
    6726           5 :       {nullptr, nullptr}};
    6727             : 
    6728             :   // clang-format off
    6729             :   const char* data[] = {
    6730             :     "'\\1'",
    6731             :     "'\\01'",
    6732             :     "'\\001'",
    6733             :     "'\\08'",
    6734             :     "'\\09'",
    6735           5 :     nullptr};
    6736             :   // clang-format on
    6737             : 
    6738             :   // Permitted in sloppy mode
    6739           5 :   RunParserSyncTest(sloppy_context_data, data, kSuccess);
    6740             : 
    6741             :   // Error in strict mode
    6742           5 :   RunParserSyncTest(strict_context_data, data, kError);
    6743           5 : }
    6744             : 
    6745       28342 : TEST(ScanTemplateLiterals) {
    6746             :   const char* context_data[][2] = {{"'use strict';", ""},
    6747             :                                    {"function foo(){ 'use strict';"
    6748             :                                     "  var a, b, c; return ",
    6749             :                                     "}"},
    6750           5 :                                    {nullptr, nullptr}};
    6751             : 
    6752             :   const char* data[] = {"``",
    6753             :                         "`no-subst-template`",
    6754             :                         "`template-head${a}`",
    6755             :                         "`${a}`",
    6756             :                         "`${a}template-tail`",
    6757             :                         "`template-head${a}template-tail`",
    6758             :                         "`${a}${b}${c}`",
    6759             :                         "`a${a}b${b}c${c}`",
    6760             :                         "`${a}a${b}b${c}c`",
    6761             :                         "`foo\n\nbar\r\nbaz`",
    6762             :                         "`foo\n\n${  bar  }\r\nbaz`",
    6763             :                         "`foo${a /* comment */}`",
    6764             :                         "`foo${a // comment\n}`",
    6765             :                         "`foo${a \n}`",
    6766             :                         "`foo${a \r\n}`",
    6767             :                         "`foo${a \r}`",
    6768             :                         "`foo${/* comment */ a}`",
    6769             :                         "`foo${// comment\na}`",
    6770             :                         "`foo${\n a}`",
    6771             :                         "`foo${\r\n a}`",
    6772             :                         "`foo${\r a}`",
    6773             :                         "`foo${'a' in a}`",
    6774           5 :                         nullptr};
    6775           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6776           5 : }
    6777             : 
    6778             : 
    6779       28342 : TEST(ScanTaggedTemplateLiterals) {
    6780             :   const char* context_data[][2] = {{"'use strict';", ""},
    6781             :                                    {"function foo(){ 'use strict';"
    6782             :                                     "  function tag() {}"
    6783             :                                     "  var a, b, c; return ",
    6784             :                                     "}"},
    6785           5 :                                    {nullptr, nullptr}};
    6786             : 
    6787             :   const char* data[] = {"tag ``",
    6788             :                         "tag `no-subst-template`",
    6789             :                         "tag`template-head${a}`",
    6790             :                         "tag `${a}`",
    6791             :                         "tag `${a}template-tail`",
    6792             :                         "tag   `template-head${a}template-tail`",
    6793             :                         "tag\n`${a}${b}${c}`",
    6794             :                         "tag\r\n`a${a}b${b}c${c}`",
    6795             :                         "tag    `${a}a${b}b${c}c`",
    6796             :                         "tag\t`foo\n\nbar\r\nbaz`",
    6797             :                         "tag\r`foo\n\n${  bar  }\r\nbaz`",
    6798             :                         "tag`foo${a /* comment */}`",
    6799             :                         "tag`foo${a // comment\n}`",
    6800             :                         "tag`foo${a \n}`",
    6801             :                         "tag`foo${a \r\n}`",
    6802             :                         "tag`foo${a \r}`",
    6803             :                         "tag`foo${/* comment */ a}`",
    6804             :                         "tag`foo${// comment\na}`",
    6805             :                         "tag`foo${\n a}`",
    6806             :                         "tag`foo${\r\n a}`",
    6807             :                         "tag`foo${\r a}`",
    6808             :                         "tag`foo${'a' in a}`",
    6809           5 :                         nullptr};
    6810           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6811           5 : }
    6812             : 
    6813             : 
    6814       28342 : TEST(TemplateMaterializedLiterals) {
    6815             :   const char* context_data[][2] = {{"'use strict';\n"
    6816             :                                     "function tag() {}\n"
    6817             :                                     "var a, b, c;\n"
    6818             :                                     "(",
    6819             :                                     ")"},
    6820           5 :                                    {nullptr, nullptr}};
    6821             : 
    6822             :   const char* data[] = {"tag``", "tag`a`", "tag`a${1}b`", "tag`a${1}b${2}c`",
    6823             :                         "``",    "`a`",    "`a${1}b`",    "`a${1}b${2}c`",
    6824           5 :                         nullptr};
    6825             : 
    6826           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6827           5 : }
    6828             : 
    6829             : 
    6830       28342 : TEST(ScanUnterminatedTemplateLiterals) {
    6831             :   const char* context_data[][2] = {{"'use strict';", ""},
    6832             :                                    {"function foo(){ 'use strict';"
    6833             :                                     "  var a, b, c; return ",
    6834             :                                     "}"},
    6835           5 :                                    {nullptr, nullptr}};
    6836             : 
    6837             :   const char* data[] = {"`no-subst-template",
    6838             :                         "`template-head${a}",
    6839             :                         "`${a}template-tail",
    6840             :                         "`template-head${a}template-tail",
    6841             :                         "`${a}${b}${c}",
    6842             :                         "`a${a}b${b}c${c}",
    6843             :                         "`${a}a${b}b${c}c",
    6844             :                         "`foo\n\nbar\r\nbaz",
    6845             :                         "`foo\n\n${  bar  }\r\nbaz",
    6846             :                         "`foo${a /* comment } */`",
    6847             :                         "`foo${a /* comment } `*/",
    6848             :                         "`foo${a // comment}`",
    6849             :                         "`foo${a \n`",
    6850             :                         "`foo${a \r\n`",
    6851             :                         "`foo${a \r`",
    6852             :                         "`foo${/* comment */ a`",
    6853             :                         "`foo${// commenta}`",
    6854             :                         "`foo${\n a`",
    6855             :                         "`foo${\r\n a`",
    6856             :                         "`foo${\r a`",
    6857             :                         "`foo${fn(}`",
    6858             :                         "`foo${1 if}`",
    6859           5 :                         nullptr};
    6860           5 :   RunParserSyncTest(context_data, data, kError);
    6861           5 : }
    6862             : 
    6863             : 
    6864       28342 : TEST(TemplateLiteralsIllegalTokens) {
    6865             :   const char* context_data[][2] = {{"'use strict';", ""},
    6866             :                                    {"function foo(){ 'use strict';"
    6867             :                                     "  var a, b, c; return ",
    6868             :                                     "}"},
    6869           5 :                                    {nullptr, nullptr}};
    6870             :   const char* data[] = {
    6871             :       "`hello\\x`",         "`hello\\x${1}`",       "`hello${1}\\x`",
    6872             :       "`hello${1}\\x${2}`", "`hello\\x\n`",         "`hello\\x\n${1}`",
    6873           5 :       "`hello${1}\\x\n`",   "`hello${1}\\x\n${2}`", nullptr};
    6874             : 
    6875           5 :   RunParserSyncTest(context_data, data, kError);
    6876           5 : }
    6877             : 
    6878             : 
    6879       28342 : TEST(ParseRestParameters) {
    6880             :   const char* context_data[][2] = {{"'use strict';(function(",
    6881             :                                     "){ return args;})(1, [], /regexp/, 'str',"
    6882             :                                     "function(){});"},
    6883             :                                    {"(function(",
    6884             :                                     "){ return args;})(1, [],"
    6885             :                                     "/regexp/, 'str', function(){});"},
    6886           5 :                                    {nullptr, nullptr}};
    6887             : 
    6888             :   const char* data[] = {"...args",
    6889             :                         "a, ...args",
    6890             :                         "...   args",
    6891             :                         "a, ...   args",
    6892             :                         "...\targs",
    6893             :                         "a, ...\targs",
    6894             :                         "...\r\nargs",
    6895             :                         "a, ...\r\nargs",
    6896             :                         "...\rargs",
    6897             :                         "a, ...\rargs",
    6898             :                         "...\t\n\t\t\n  args",
    6899             :                         "a, ...  \n  \n  args",
    6900             :                         "...{ length, 0: a, 1: b}",
    6901             :                         "...{}",
    6902             :                         "...[a, b]",
    6903             :                         "...[]",
    6904             :                         "...[...[a, b, ...c]]",
    6905           5 :                         nullptr};
    6906           5 :   RunParserSyncTest(context_data, data, kSuccess);
    6907           5 : }
    6908             : 
    6909             : 
    6910       28342 : TEST(ParseRestParametersErrors) {
    6911             :   const char* context_data[][2] = {{"'use strict';(function(",
    6912             :                                     "){ return args;}(1, [], /regexp/, 'str',"
    6913             :                                     "function(){});"},
    6914             :                                    {"(function(",
    6915             :                                     "){ return args;}(1, [],"
    6916             :                                     "/regexp/, 'str', function(){});"},
    6917           5 :                                    {nullptr, nullptr}};
    6918             : 
    6919             :   const char* data[] = {"...args, b",
    6920             :                         "a, ...args, b",
    6921             :                         "...args,   b",
    6922             :                         "a, ...args,   b",
    6923             :                         "...args,\tb",
    6924             :                         "a,...args\t,b",
    6925             :                         "...args\r\n, b",
    6926             :                         "a, ... args,\r\nb",
    6927             :                         "...args\r,b",
    6928             :                         "a, ... args,\rb",
    6929             :                         "...args\t\n\t\t\n,  b",
    6930             :                         "a, ... args,  \n  \n  b",
    6931             :                         "a, a, ...args",
    6932             :                         "a,\ta, ...args",
    6933             :                         "a,\ra, ...args",
    6934             :                         "a,\na, ...args",
    6935           5 :                         nullptr};
    6936           5 :   RunParserSyncTest(context_data, data, kError);
    6937           5 : }
    6938             : 
    6939             : 
    6940       28342 : TEST(RestParameterInSetterMethodError) {
    6941             :   const char* context_data[][2] = {
    6942             :       {"'use strict';({ set prop(", ") {} }).prop = 1;"},
    6943             :       {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
    6944             :       {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
    6945             :       {"({ set prop(", ") {} }).prop = 1;"},
    6946             :       {"(class { static set prop(", ") {} }).prop = 1;"},
    6947             :       {"(new (class { set prop(", ") {} })).prop = 1;"},
    6948           5 :       {nullptr, nullptr}};
    6949           5 :   const char* data[] = {"...a", "...arguments", "...eval", nullptr};
    6950             : 
    6951           5 :   RunParserSyncTest(context_data, data, kError);
    6952           5 : }
    6953             : 
    6954             : 
    6955       28342 : TEST(RestParametersEvalArguments) {
    6956             :   // clang-format off
    6957             :   const char* strict_context_data[][2] =
    6958             :       {{"'use strict';(function(",
    6959             :         "){ return;})(1, [], /regexp/, 'str',function(){});"},
    6960           5 :        {nullptr, nullptr}};
    6961             :   const char* sloppy_context_data[][2] =
    6962             :       {{"(function(",
    6963             :         "){ return;})(1, [],/regexp/, 'str', function(){});"},
    6964           5 :        {nullptr, nullptr}};
    6965             : 
    6966             :   const char* data[] = {
    6967             :       "...eval",
    6968             :       "eval, ...args",
    6969             :       "...arguments",
    6970             :       // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
    6971             :       // "arguments, ...args",
    6972           5 :       nullptr};
    6973             :   // clang-format on
    6974             : 
    6975             :   // Fail in strict mode
    6976           5 :   RunParserSyncTest(strict_context_data, data, kError);
    6977             : 
    6978             :   // OK in sloppy mode
    6979           5 :   RunParserSyncTest(sloppy_context_data, data, kSuccess);
    6980           5 : }
    6981             : 
    6982             : 
    6983       28342 : TEST(RestParametersDuplicateEvalArguments) {
    6984             :   const char* context_data[][2] = {
    6985             :       {"'use strict';(function(",
    6986             :        "){ return;})(1, [], /regexp/, 'str',function(){});"},
    6987             :       {"(function(", "){ return;})(1, [],/regexp/, 'str', function(){});"},
    6988           5 :       {nullptr, nullptr}};
    6989             : 
    6990             :   const char* data[] = {"eval, ...eval", "eval, eval, ...args",
    6991             :                         "arguments, ...arguments",
    6992           5 :                         "arguments, arguments, ...args", nullptr};
    6993             : 
    6994             :   // In strict mode, the error is using "eval" or "arguments" as parameter names
    6995             :   // In sloppy mode, the error is that eval / arguments are duplicated
    6996           5 :   RunParserSyncTest(context_data, data, kError);
    6997           5 : }
    6998             : 
    6999             : 
    7000       28342 : TEST(SpreadCall) {
    7001             :   const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
    7002             :                                    {"function fn() {} fn(", ");"},
    7003           5 :                                    {nullptr, nullptr}};
    7004             : 
    7005             :   const char* data[] = {"...([1, 2, 3])",
    7006             :                         "...'123', ...'456'",
    7007             :                         "...new Set([1, 2, 3]), 4",
    7008             :                         "1, ...[2, 3], 4",
    7009             :                         "...Array(...[1,2,3,4])",
    7010             :                         "...NaN",
    7011             :                         "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
    7012             :                         "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
    7013             :                         "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
    7014             :                         "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]",
    7015           5 :                         nullptr};
    7016             : 
    7017           5 :   RunParserSyncTest(context_data, data, kSuccess);
    7018           5 : }
    7019             : 
    7020             : 
    7021       28342 : TEST(SpreadCallErrors) {
    7022             :   const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
    7023             :                                    {"function fn() {} fn(", ");"},
    7024           5 :                                    {nullptr, nullptr}};
    7025             : 
    7026           5 :   const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", nullptr};
    7027             : 
    7028           5 :   RunParserSyncTest(context_data, data, kError);
    7029           5 : }
    7030             : 
    7031             : 
    7032       28342 : TEST(BadRestSpread) {
    7033             :   const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
    7034             :                                    {"function fn() { ", "} fn();"},
    7035           5 :                                    {nullptr, nullptr}};
    7036             :   const char* data[] = {"return ...[1,2,3];",
    7037             :                         "var ...x = [1,2,3];",
    7038             :                         "var [...x,] = [1,2,3];",
    7039             :                         "var [...x, y] = [1,2,3];",
    7040             :                         "var { x } = {x: ...[1,2,3]}",
    7041           5 :                         nullptr};
    7042           5 :   RunParserSyncTest(context_data, data, kError);
    7043           5 : }
    7044             : 
    7045             : 
    7046       28342 : TEST(LexicalScopingSloppyMode) {
    7047             :   const char* context_data[][2] = {
    7048           5 :       {"", ""}, {"function f() {", "}"}, {"{", "}"}, {nullptr, nullptr}};
    7049             : 
    7050           5 :   const char* good_data[] = {"let = 1;", "for(let = 1;;){}", nullptr};
    7051           5 :   RunParserSyncTest(context_data, good_data, kSuccess);
    7052           5 : }
    7053             : 
    7054             : 
    7055       28342 : TEST(ComputedPropertyName) {
    7056             :   const char* context_data[][2] = {{"({[", "]: 1});"},
    7057             :                                    {"({get [", "]() {}});"},
    7058             :                                    {"({set [", "](_) {}});"},
    7059             :                                    {"({[", "]() {}});"},
    7060             :                                    {"({*[", "]() {}});"},
    7061             :                                    {"(class {get [", "]() {}});"},
    7062             :                                    {"(class {set [", "](_) {}});"},
    7063             :                                    {"(class {[", "]() {}});"},
    7064             :                                    {"(class {*[", "]() {}});"},
    7065           5 :                                    {nullptr, nullptr}};
    7066           5 :   const char* error_data[] = {"1, 2", "var name", nullptr};
    7067             : 
    7068           5 :   RunParserSyncTest(context_data, error_data, kError);
    7069             : 
    7070             :   const char* name_data[] = {"1",  "1 + 2", "'name'", "\"name\"",
    7071           5 :                              "[]", "{}",    nullptr};
    7072             : 
    7073           5 :   RunParserSyncTest(context_data, name_data, kSuccess);
    7074           5 : }
    7075             : 
    7076             : 
    7077       28342 : TEST(ComputedPropertyNameShorthandError) {
    7078           5 :   const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
    7079           5 :   const char* error_data[] = {"a: 1, [2]", "[1], a: 1", nullptr};
    7080             : 
    7081           5 :   RunParserSyncTest(context_data, error_data, kError);
    7082           5 : }
    7083             : 
    7084             : 
    7085       28342 : TEST(BasicImportExportParsing) {
    7086             :   // clang-format off
    7087             :   const char* kSources[] = {
    7088             :       "export let x = 0;",
    7089             :       "export var y = 0;",
    7090             :       "export const z = 0;",
    7091             :       "export function func() { };",
    7092             :       "export class C { };",
    7093             :       "export { };",
    7094             :       "function f() {}; f(); export { f };",
    7095             :       "var a, b, c; export { a, b as baz, c };",
    7096             :       "var d, e; export { d as dreary, e, };",
    7097             :       "export default function f() {}",
    7098             :       "export default function() {}",
    7099             :       "export default function*() {}",
    7100             :       "export default class C {}",
    7101             :       "export default class {}",
    7102             :       "export default class extends C {}",
    7103             :       "export default 42",
    7104             :       "var x; export default x = 7",
    7105             :       "export { Q } from 'somemodule.js';",
    7106             :       "export * from 'somemodule.js';",
    7107             :       "var foo; export { foo as for };",
    7108             :       "export { arguments } from 'm.js';",
    7109             :       "export { for } from 'm.js';",
    7110             :       "export { yield } from 'm.js'",
    7111             :       "export { static } from 'm.js'",
    7112             :       "export { let } from 'm.js'",
    7113             :       "var a; export { a as b, a as c };",
    7114             :       "var a; export { a as await };",
    7115             :       "var a; export { a as enum };",
    7116             : 
    7117             :       "import 'somemodule.js';",
    7118             :       "import { } from 'm.js';",
    7119             :       "import { a } from 'm.js';",
    7120             :       "import { a, b as d, c, } from 'm.js';",
    7121             :       "import * as thing from 'm.js';",
    7122             :       "import thing from 'm.js';",
    7123             :       "import thing, * as rest from 'm.js';",
    7124             :       "import thing, { a, b, c } from 'm.js';",
    7125             :       "import { arguments as a } from 'm.js';",
    7126             :       "import { for as f } from 'm.js';",
    7127             :       "import { yield as y } from 'm.js';",
    7128             :       "import { static as s } from 'm.js';",
    7129             :       "import { let as l } from 'm.js';",
    7130             : 
    7131             :       "import thing from 'a.js'; export {thing};",
    7132             :       "export {thing}; import thing from 'a.js';",
    7133             :       "import {thing} from 'a.js'; export {thing};",
    7134             :       "export {thing}; import {thing} from 'a.js';",
    7135             :       "import * as thing from 'a.js'; export {thing};",
    7136             :       "export {thing}; import * as thing from 'a.js';",
    7137           5 :   };
    7138             :   // clang-format on
    7139             : 
    7140             :   i::Isolate* isolate = CcTest::i_isolate();
    7141             :   i::Factory* factory = isolate->factory();
    7142             : 
    7143           5 :   v8::HandleScope handles(CcTest::isolate());
    7144           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7145             :   v8::Context::Scope context_scope(context);
    7146             : 
    7147           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7148           5 :                                         128 * 1024);
    7149             : 
    7150         240 :   for (unsigned i = 0; i < arraysize(kSources); ++i) {
    7151             :     i::Handle<i::String> source =
    7152         235 :         factory->NewStringFromAsciiChecked(kSources[i]);
    7153             : 
    7154             :     // Show that parsing as a module works
    7155             :     {
    7156         235 :       i::Handle<i::Script> script = factory->NewScript(source);
    7157         235 :       i::ParseInfo info(isolate, script);
    7158             :       info.set_module();
    7159         235 :       if (!i::parsing::ParseProgram(&info, isolate)) {
    7160             :         i::Handle<i::JSObject> exception_handle(
    7161             :             i::JSObject::cast(isolate->pending_exception()), isolate);
    7162             :         i::Handle<i::String> message_string = i::Handle<i::String>::cast(
    7163           0 :             i::JSReceiver::GetProperty(isolate, exception_handle, "message")
    7164           0 :                 .ToHandleChecked());
    7165           0 :         isolate->clear_pending_exception();
    7166             : 
    7167           0 :         FATAL(
    7168             :             "Parser failed on:\n"
    7169             :             "\t%s\n"
    7170             :             "with error:\n"
    7171             :             "\t%s\n"
    7172             :             "However, we expected no error.",
    7173           0 :             source->ToCString().get(), message_string->ToCString().get());
    7174         235 :       }
    7175             :     }
    7176             : 
    7177             :     // And that parsing a script does not.
    7178             :     {
    7179         235 :       i::Handle<i::Script> script = factory->NewScript(source);
    7180         235 :       i::ParseInfo info(isolate, script);
    7181         235 :       CHECK(!i::parsing::ParseProgram(&info, isolate));
    7182         235 :       isolate->clear_pending_exception();
    7183             :     }
    7184           5 :   }
    7185           5 : }
    7186             : 
    7187       28342 : TEST(NamespaceExportParsing) {
    7188             :   // clang-format off
    7189             :   const char* kSources[] = {
    7190             :       "export * as arguments from 'bar'",
    7191             :       "export * as await from 'bar'",
    7192             :       "export * as default from 'bar'",
    7193             :       "export * as enum from 'bar'",
    7194             :       "export * as foo from 'bar'",
    7195             :       "export * as for from 'bar'",
    7196             :       "export * as let from 'bar'",
    7197             :       "export * as static from 'bar'",
    7198             :       "export * as yield from 'bar'",
    7199           5 :   };
    7200             :   // clang-format on
    7201             : 
    7202           5 :   i::FLAG_harmony_namespace_exports = true;
    7203             :   i::Isolate* isolate = CcTest::i_isolate();
    7204             :   i::Factory* factory = isolate->factory();
    7205             : 
    7206           5 :   v8::HandleScope handles(CcTest::isolate());
    7207           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7208             :   v8::Context::Scope context_scope(context);
    7209             : 
    7210           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7211           5 :                                         128 * 1024);
    7212             : 
    7213          50 :   for (unsigned i = 0; i < arraysize(kSources); ++i) {
    7214             :     i::Handle<i::String> source =
    7215          45 :         factory->NewStringFromAsciiChecked(kSources[i]);
    7216          45 :     i::Handle<i::Script> script = factory->NewScript(source);
    7217          45 :     i::ParseInfo info(isolate, script);
    7218             :     info.set_module();
    7219          45 :     CHECK(i::parsing::ParseProgram(&info, isolate));
    7220          50 :   }
    7221           5 : }
    7222             : 
    7223       28342 : TEST(ImportExportParsingErrors) {
    7224             :   // clang-format off
    7225             :   const char* kErrorSources[] = {
    7226             :       "export {",
    7227             :       "var a; export { a",
    7228             :       "var a; export { a,",
    7229             :       "var a; export { a, ;",
    7230             :       "var a; export { a as };",
    7231             :       "var a, b; export { a as , b};",
    7232             :       "export }",
    7233             :       "var foo, bar; export { foo bar };",
    7234             :       "export { foo };",
    7235             :       "export { , };",
    7236             :       "export default;",
    7237             :       "export default var x = 7;",
    7238             :       "export default let x = 7;",
    7239             :       "export default const x = 7;",
    7240             :       "export *;",
    7241             :       "export * from;",
    7242             :       "export { Q } from;",
    7243             :       "export default from 'module.js';",
    7244             :       "export { for }",
    7245             :       "export { for as foo }",
    7246             :       "export { arguments }",
    7247             :       "export { arguments as foo }",
    7248             :       "var a; export { a, a };",
    7249             :       "var a, b; export { a as b, b };",
    7250             :       "var a, b; export { a as c, b as c };",
    7251             :       "export default function f(){}; export default class C {};",
    7252             :       "export default function f(){}; var a; export { a as default };",
    7253             :       "export function() {}",
    7254             :       "export function*() {}",
    7255             :       "export class {}",
    7256             :       "export class extends C {}",
    7257             : 
    7258             :       "import from;",
    7259             :       "import from 'm.js';",
    7260             :       "import { };",
    7261             :       "import {;",
    7262             :       "import };",
    7263             :       "import { , };",
    7264             :       "import { , } from 'm.js';",
    7265             :       "import { a } from;",
    7266             :       "import { a } 'm.js';",
    7267             :       "import , from 'm.js';",
    7268             :       "import a , from 'm.js';",
    7269             :       "import a { b, c } from 'm.js';",
    7270             :       "import arguments from 'm.js';",
    7271             :       "import eval from 'm.js';",
    7272             :       "import { arguments } from 'm.js';",
    7273             :       "import { eval } from 'm.js';",
    7274             :       "import { a as arguments } from 'm.js';",
    7275             :       "import { for } from 'm.js';",
    7276             :       "import { y as yield } from 'm.js'",
    7277             :       "import { s as static } from 'm.js'",
    7278             :       "import { l as let } from 'm.js'",
    7279             :       "import { a as await } from 'm.js';",
    7280             :       "import { a as enum } from 'm.js';",
    7281             :       "import { x }, def from 'm.js';",
    7282             :       "import def, def2 from 'm.js';",
    7283             :       "import * as x, def from 'm.js';",
    7284             :       "import * as x, * as y from 'm.js';",
    7285             :       "import {x}, {y} from 'm.js';",
    7286             :       "import * as x, {y} from 'm.js';",
    7287             : 
    7288             :       "export *;",
    7289             :       "export * as;",
    7290             :       "export * as foo;",
    7291             :       "export * as foo from;",
    7292             :       "export * as foo from ';",
    7293             :       "export * as ,foo from 'bar'",
    7294           5 :   };
    7295             :   // clang-format on
    7296             : 
    7297             :   i::Isolate* isolate = CcTest::i_isolate();
    7298             :   i::Factory* factory = isolate->factory();
    7299             : 
    7300           5 :   v8::HandleScope handles(CcTest::isolate());
    7301           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7302             :   v8::Context::Scope context_scope(context);
    7303             : 
    7304           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7305           5 :                                         128 * 1024);
    7306             : 
    7307         335 :   for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
    7308             :     i::Handle<i::String> source =
    7309         330 :         factory->NewStringFromAsciiChecked(kErrorSources[i]);
    7310             : 
    7311         330 :     i::Handle<i::Script> script = factory->NewScript(source);
    7312         330 :     i::ParseInfo info(isolate, script);
    7313             :     info.set_module();
    7314         330 :     CHECK(!i::parsing::ParseProgram(&info, isolate));
    7315         330 :     isolate->clear_pending_exception();
    7316         335 :   }
    7317           5 : }
    7318             : 
    7319       28342 : TEST(ModuleTopLevelFunctionDecl) {
    7320             :   // clang-format off
    7321             :   const char* kErrorSources[] = {
    7322             :       "function f() {} function f() {}",
    7323             :       "var f; function f() {}",
    7324             :       "function f() {} var f;",
    7325             :       "function* f() {} function* f() {}",
    7326             :       "var f; function* f() {}",
    7327             :       "function* f() {} var f;",
    7328             :       "function f() {} function* f() {}",
    7329             :       "function* f() {} function f() {}",
    7330           5 :   };
    7331             :   // clang-format on
    7332             : 
    7333             :   i::Isolate* isolate = CcTest::i_isolate();
    7334             :   i::Factory* factory = isolate->factory();
    7335             : 
    7336           5 :   v8::HandleScope handles(CcTest::isolate());
    7337           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7338             :   v8::Context::Scope context_scope(context);
    7339             : 
    7340           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7341           5 :                                         128 * 1024);
    7342             : 
    7343          45 :   for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
    7344             :     i::Handle<i::String> source =
    7345          40 :         factory->NewStringFromAsciiChecked(kErrorSources[i]);
    7346             : 
    7347          40 :     i::Handle<i::Script> script = factory->NewScript(source);
    7348          40 :     i::ParseInfo info(isolate, script);
    7349             :     info.set_module();
    7350          40 :     CHECK(!i::parsing::ParseProgram(&info, isolate));
    7351          40 :     isolate->clear_pending_exception();
    7352          45 :   }
    7353           5 : }
    7354             : 
    7355       28342 : TEST(ModuleAwaitReserved) {
    7356             :   // clang-format off
    7357             :   const char* kErrorSources[] = {
    7358             :       "await;",
    7359             :       "await: ;",
    7360             :       "var await;",
    7361             :       "var [await] = [];",
    7362             :       "var { await } = {};",
    7363             :       "var { x: await } = {};",
    7364             :       "{ var await; }",
    7365             :       "let await;",
    7366             :       "let [await] = [];",
    7367             :       "let { await } = {};",
    7368             :       "let { x: await } = {};",
    7369             :       "{ let await; }",
    7370             :       "const await = null;",
    7371             :       "const [await] = [];",
    7372             :       "const { await } = {};",
    7373             :       "const { x: await } = {};",
    7374             :       "{ const await = null; }",
    7375             :       "function await() {}",
    7376             :       "function f(await) {}",
    7377             :       "function* await() {}",
    7378             :       "function* g(await) {}",
    7379             :       "(function await() {});",
    7380             :       "(function (await) {});",
    7381             :       "(function* await() {});",
    7382             :       "(function* (await) {});",
    7383             :       "(await) => {};",
    7384             :       "await => {};",
    7385             :       "class await {}",
    7386             :       "class C { constructor(await) {} }",
    7387             :       "class C { m(await) {} }",
    7388             :       "class C { static m(await) {} }",
    7389             :       "class C { *m(await) {} }",
    7390             :       "class C { static *m(await) {} }",
    7391             :       "(class await {})",
    7392             :       "(class { constructor(await) {} });",
    7393             :       "(class { m(await) {} });",
    7394             :       "(class { static m(await) {} });",
    7395             :       "(class { *m(await) {} });",
    7396             :       "(class { static *m(await) {} });",
    7397             :       "({ m(await) {} });",
    7398             :       "({ *m(await) {} });",
    7399             :       "({ set p(await) {} });",
    7400             :       "try {} catch (await) {}",
    7401             :       "try {} catch (await) {} finally {}",
    7402             :       nullptr
    7403           5 :   };
    7404             :   // clang-format on
    7405           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    7406             : 
    7407             :   RunModuleParserSyncTest(context_data, kErrorSources, kError);
    7408           5 : }
    7409             : 
    7410       28342 : TEST(ModuleAwaitReservedPreParse) {
    7411           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    7412           5 :   const char* error_data[] = {"function f() { var await = 0; }", nullptr};
    7413             : 
    7414             :   RunModuleParserSyncTest(context_data, error_data, kError);
    7415           5 : }
    7416             : 
    7417       28342 : TEST(ModuleAwaitPermitted) {
    7418             :   // clang-format off
    7419             :   const char* kValidSources[] = {
    7420             :     "({}).await;",
    7421             :     "({ await: null });",
    7422             :     "({ await() {} });",
    7423             :     "({ get await() {} });",
    7424             :     "({ set await(x) {} });",
    7425             :     "(class { await() {} });",
    7426             :     "(class { static await() {} });",
    7427             :     "(class { *await() {} });",
    7428             :     "(class { static *await() {} });",
    7429             :     nullptr
    7430           5 :   };
    7431             :   // clang-format on
    7432           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    7433             : 
    7434             :   RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
    7435           5 : }
    7436             : 
    7437       28342 : TEST(EnumReserved) {
    7438             :   // clang-format off
    7439             :   const char* kErrorSources[] = {
    7440             :       "enum;",
    7441             :       "enum: ;",
    7442             :       "var enum;",
    7443             :       "var [enum] = [];",
    7444             :       "var { enum } = {};",
    7445             :       "var { x: enum } = {};",
    7446             :       "{ var enum; }",
    7447             :       "let enum;",
    7448             :       "let [enum] = [];",
    7449             :       "let { enum } = {};",
    7450             :       "let { x: enum } = {};",
    7451             :       "{ let enum; }",
    7452             :       "const enum = null;",
    7453             :       "const [enum] = [];",
    7454             :       "const { enum } = {};",
    7455             :       "const { x: enum } = {};",
    7456             :       "{ const enum = null; }",
    7457             :       "function enum() {}",
    7458             :       "function f(enum) {}",
    7459             :       "function* enum() {}",
    7460             :       "function* g(enum) {}",
    7461             :       "(function enum() {});",
    7462             :       "(function (enum) {});",
    7463             :       "(function* enum() {});",
    7464             :       "(function* (enum) {});",
    7465             :       "(enum) => {};",
    7466             :       "enum => {};",
    7467             :       "class enum {}",
    7468             :       "class C { constructor(enum) {} }",
    7469             :       "class C { m(enum) {} }",
    7470             :       "class C { static m(enum) {} }",
    7471             :       "class C { *m(enum) {} }",
    7472             :       "class C { static *m(enum) {} }",
    7473             :       "(class enum {})",
    7474             :       "(class { constructor(enum) {} });",
    7475             :       "(class { m(enum) {} });",
    7476             :       "(class { static m(enum) {} });",
    7477             :       "(class { *m(enum) {} });",
    7478             :       "(class { static *m(enum) {} });",
    7479             :       "({ m(enum) {} });",
    7480             :       "({ *m(enum) {} });",
    7481             :       "({ set p(enum) {} });",
    7482             :       "try {} catch (enum) {}",
    7483             :       "try {} catch (enum) {} finally {}",
    7484             :       nullptr
    7485           5 :   };
    7486             :   // clang-format on
    7487           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
    7488             : 
    7489             :   RunModuleParserSyncTest(context_data, kErrorSources, kError);
    7490           5 : }
    7491             : 
    7492          85 : static void CheckEntry(const i::ModuleDescriptor::Entry* entry,
    7493             :                        const char* export_name, const char* local_name,
    7494             :                        const char* import_name, int module_request) {
    7495          85 :   CHECK_NOT_NULL(entry);
    7496          85 :   if (export_name == nullptr) {
    7497          35 :     CHECK_NULL(entry->export_name);
    7498             :   } else {
    7499          50 :     CHECK(entry->export_name->IsOneByteEqualTo(export_name));
    7500             :   }
    7501          85 :   if (local_name == nullptr) {
    7502          15 :     CHECK_NULL(entry->local_name);
    7503             :   } else {
    7504          70 :     CHECK(entry->local_name->IsOneByteEqualTo(local_name));
    7505             :   }
    7506          85 :   if (import_name == nullptr) {
    7507          55 :     CHECK_NULL(entry->import_name);
    7508             :   } else {
    7509          30 :     CHECK(entry->import_name->IsOneByteEqualTo(import_name));
    7510             :   }
    7511          85 :   CHECK_EQ(entry->module_request, module_request);
    7512          85 : }
    7513             : 
    7514       28342 : TEST(ModuleParsingInternals) {
    7515             :   i::Isolate* isolate = CcTest::i_isolate();
    7516             :   i::Factory* factory = isolate->factory();
    7517           5 :   v8::HandleScope handles(CcTest::isolate());
    7518           5 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7519             :   v8::Context::Scope context_scope(context);
    7520           5 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7521           5 :                                         128 * 1024);
    7522             : 
    7523             :   static const char kSource[] =
    7524             :       "let x = 5;"
    7525             :       "export { x as y };"
    7526             :       "import { q as z } from 'm.js';"
    7527             :       "import n from 'n.js';"
    7528             :       "export { a as b } from 'm.js';"
    7529             :       "export * from 'p.js';"
    7530             :       "export var foo;"
    7531             :       "export function goo() {};"
    7532             :       "export let hoo;"
    7533             :       "export const joo = 42;"
    7534             :       "export default (function koo() {});"
    7535             :       "import 'q.js';"
    7536             :       "let nonexport = 42;"
    7537             :       "import {m as mm} from 'm.js';"
    7538             :       "import {aa} from 'm.js';"
    7539             :       "export {aa as bb, x};"
    7540             :       "import * as loo from 'bar.js';"
    7541             :       "import * as foob from 'bar.js';"
    7542             :       "export {foob};";
    7543           5 :   i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
    7544           5 :   i::Handle<i::Script> script = factory->NewScript(source);
    7545          10 :   i::ParseInfo info(isolate, script);
    7546             :   info.set_module();
    7547           5 :   CHECK(i::parsing::ParseProgram(&info, isolate));
    7548           5 :   CHECK(i::Compiler::Analyze(&info));
    7549           5 :   i::FunctionLiteral* func = info.literal();
    7550          10 :   i::ModuleScope* module_scope = func->scope()->AsModuleScope();
    7551          15 :   i::Scope* outer_scope = module_scope->outer_scope();
    7552           5 :   CHECK(outer_scope->is_script_scope());
    7553           5 :   CHECK_NULL(outer_scope->outer_scope());
    7554           5 :   CHECK(module_scope->is_module_scope());
    7555             :   const i::ModuleDescriptor::Entry* entry;
    7556             :   i::Declaration::List* declarations = module_scope->declarations();
    7557           5 :   CHECK_EQ(13, declarations->LengthForTest());
    7558             : 
    7559           5 :   CHECK(declarations->AtForTest(0)->var()->raw_name()->IsOneByteEqualTo("x"));
    7560          10 :   CHECK(declarations->AtForTest(0)->var()->mode() == i::VariableMode::kLet);
    7561           5 :   CHECK(declarations->AtForTest(0)->var()->binding_needs_init());
    7562           5 :   CHECK(declarations->AtForTest(0)->var()->location() ==
    7563             :         i::VariableLocation::MODULE);
    7564             : 
    7565           5 :   CHECK(declarations->AtForTest(1)->var()->raw_name()->IsOneByteEqualTo("z"));
    7566          10 :   CHECK(declarations->AtForTest(1)->var()->mode() == i::VariableMode::kConst);
    7567           5 :   CHECK(declarations->AtForTest(1)->var()->binding_needs_init());
    7568          10 :   CHECK(declarations->AtForTest(1)->var()->location() ==
    7569             :         i::VariableLocation::MODULE);
    7570             : 
    7571           5 :   CHECK(declarations->AtForTest(2)->var()->raw_name()->IsOneByteEqualTo("n"));
    7572          10 :   CHECK(declarations->AtForTest(2)->var()->mode() == i::VariableMode::kConst);
    7573           5 :   CHECK(declarations->AtForTest(2)->var()->binding_needs_init());
    7574          10 :   CHECK(declarations->AtForTest(2)->var()->location() ==
    7575             :         i::VariableLocation::MODULE);
    7576             : 
    7577           5 :   CHECK(declarations->AtForTest(3)->var()->raw_name()->IsOneByteEqualTo("foo"));
    7578          10 :   CHECK(declarations->AtForTest(3)->var()->mode() == i::VariableMode::kVar);
    7579           5 :   CHECK(!declarations->AtForTest(3)->var()->binding_needs_init());
    7580          10 :   CHECK(declarations->AtForTest(3)->var()->location() ==
    7581             :         i::VariableLocation::MODULE);
    7582             : 
    7583           5 :   CHECK(declarations->AtForTest(4)->var()->raw_name()->IsOneByteEqualTo("goo"));
    7584          10 :   CHECK(declarations->AtForTest(4)->var()->mode() == i::VariableMode::kLet);
    7585           5 :   CHECK(!declarations->AtForTest(4)->var()->binding_needs_init());
    7586          10 :   CHECK(declarations->AtForTest(4)->var()->location() ==
    7587             :         i::VariableLocation::MODULE);
    7588             : 
    7589           5 :   CHECK(declarations->AtForTest(5)->var()->raw_name()->IsOneByteEqualTo("hoo"));
    7590          10 :   CHECK(declarations->AtForTest(5)->var()->mode() == i::VariableMode::kLet);
    7591           5 :   CHECK(declarations->AtForTest(5)->var()->binding_needs_init());
    7592          10 :   CHECK(declarations->AtForTest(5)->var()->location() ==
    7593             :         i::VariableLocation::MODULE);
    7594             : 
    7595           5 :   CHECK(declarations->AtForTest(6)->var()->raw_name()->IsOneByteEqualTo("joo"));
    7596          10 :   CHECK(declarations->AtForTest(6)->var()->mode() == i::VariableMode::kConst);
    7597           5 :   CHECK(declarations->AtForTest(6)->var()->binding_needs_init());
    7598          10 :   CHECK(declarations->AtForTest(6)->var()->location() ==
    7599             :         i::VariableLocation::MODULE);
    7600             : 
    7601           5 :   CHECK(declarations->AtForTest(7)->var()->raw_name()->IsOneByteEqualTo(
    7602             :       "*default*"));
    7603          10 :   CHECK(declarations->AtForTest(7)->var()->mode() == i::VariableMode::kConst);
    7604           5 :   CHECK(declarations->AtForTest(7)->var()->binding_needs_init());
    7605          10 :   CHECK(declarations->AtForTest(7)->var()->location() ==
    7606             :         i::VariableLocation::MODULE);
    7607             : 
    7608           5 :   CHECK(declarations->AtForTest(8)->var()->raw_name()->IsOneByteEqualTo(
    7609             :       "nonexport"));
    7610           5 :   CHECK(!declarations->AtForTest(8)->var()->binding_needs_init());
    7611          10 :   CHECK(declarations->AtForTest(8)->var()->location() ==
    7612             :         i::VariableLocation::LOCAL);
    7613             : 
    7614           5 :   CHECK(declarations->AtForTest(9)->var()->raw_name()->IsOneByteEqualTo("mm"));
    7615          10 :   CHECK(declarations->AtForTest(9)->var()->mode() == i::VariableMode::kConst);
    7616           5 :   CHECK(declarations->AtForTest(9)->var()->binding_needs_init());
    7617          10 :   CHECK(declarations->AtForTest(9)->var()->location() ==
    7618             :         i::VariableLocation::MODULE);
    7619             : 
    7620           5 :   CHECK(declarations->AtForTest(10)->var()->raw_name()->IsOneByteEqualTo("aa"));
    7621          10 :   CHECK(declarations->AtForTest(10)->var()->mode() == i::VariableMode::kConst);
    7622           5 :   CHECK(declarations->AtForTest(10)->var()->binding_needs_init());
    7623          10 :   CHECK(declarations->AtForTest(10)->var()->location() ==
    7624             :         i::VariableLocation::MODULE);
    7625             : 
    7626           5 :   CHECK(
    7627             :       declarations->AtForTest(11)->var()->raw_name()->IsOneByteEqualTo("loo"));
    7628          10 :   CHECK(declarations->AtForTest(11)->var()->mode() == i::VariableMode::kConst);
    7629           5 :   CHECK(!declarations->AtForTest(11)->var()->binding_needs_init());
    7630          10 :   CHECK(declarations->AtForTest(11)->var()->location() !=
    7631             :         i::VariableLocation::MODULE);
    7632             : 
    7633           5 :   CHECK(
    7634             :       declarations->AtForTest(12)->var()->raw_name()->IsOneByteEqualTo("foob"));
    7635          10 :   CHECK(declarations->AtForTest(12)->var()->mode() == i::VariableMode::kConst);
    7636           5 :   CHECK(!declarations->AtForTest(12)->var()->binding_needs_init());
    7637          10 :   CHECK(declarations->AtForTest(12)->var()->location() ==
    7638             :         i::VariableLocation::MODULE);
    7639             : 
    7640             :   i::ModuleDescriptor* descriptor = module_scope->module();
    7641           5 :   CHECK_NOT_NULL(descriptor);
    7642             : 
    7643           5 :   CHECK_EQ(5u, descriptor->module_requests().size());
    7644          35 :   for (const auto& elem : descriptor->module_requests()) {
    7645          25 :     if (elem.first->IsOneByteEqualTo("m.js")) {
    7646           5 :       CHECK_EQ(0, elem.second.index);
    7647           5 :       CHECK_EQ(51, elem.second.position);
    7648          20 :     } else if (elem.first->IsOneByteEqualTo("n.js")) {
    7649           5 :       CHECK_EQ(1, elem.second.index);
    7650           5 :       CHECK_EQ(72, elem.second.position);
    7651          15 :     } else if (elem.first->IsOneByteEqualTo("p.js")) {
    7652           5 :       CHECK_EQ(2, elem.second.index);
    7653           5 :       CHECK_EQ(123, elem.second.position);
    7654          10 :     } else if (elem.first->IsOneByteEqualTo("q.js")) {
    7655           5 :       CHECK_EQ(3, elem.second.index);
    7656           5 :       CHECK_EQ(249, elem.second.position);
    7657           5 :     } else if (elem.first->IsOneByteEqualTo("bar.js")) {
    7658           5 :       CHECK_EQ(4, elem.second.index);
    7659           5 :       CHECK_EQ(370, elem.second.position);
    7660             :     } else {
    7661           0 :       UNREACHABLE();
    7662             :     }
    7663             :   }
    7664             : 
    7665          10 :   CHECK_EQ(3, descriptor->special_exports().size());
    7666           5 :   CheckEntry(descriptor->special_exports().at(0), "b", nullptr, "a", 0);
    7667           5 :   CheckEntry(descriptor->special_exports().at(1), nullptr, nullptr, nullptr, 2);
    7668             :   CheckEntry(descriptor->special_exports().at(2), "bb", nullptr, "aa",
    7669           5 :              0);  // !!!
    7670             : 
    7671           5 :   CHECK_EQ(8u, descriptor->regular_exports().size());
    7672             :   entry = descriptor->regular_exports()
    7673          10 :               .find(declarations->AtForTest(3)->var()->raw_name())
    7674           5 :               ->second;
    7675           5 :   CheckEntry(entry, "foo", "foo", nullptr, -1);
    7676             :   entry = descriptor->regular_exports()
    7677          10 :               .find(declarations->AtForTest(4)->var()->raw_name())
    7678           5 :               ->second;
    7679           5 :   CheckEntry(entry, "goo", "goo", nullptr, -1);
    7680             :   entry = descriptor->regular_exports()
    7681          10 :               .find(declarations->AtForTest(5)->var()->raw_name())
    7682           5 :               ->second;
    7683           5 :   CheckEntry(entry, "hoo", "hoo", nullptr, -1);
    7684             :   entry = descriptor->regular_exports()
    7685          10 :               .find(declarations->AtForTest(6)->var()->raw_name())
    7686           5 :               ->second;
    7687           5 :   CheckEntry(entry, "joo", "joo", nullptr, -1);
    7688             :   entry = descriptor->regular_exports()
    7689          10 :               .find(declarations->AtForTest(7)->var()->raw_name())
    7690           5 :               ->second;
    7691           5 :   CheckEntry(entry, "default", "*default*", nullptr, -1);
    7692             :   entry = descriptor->regular_exports()
    7693          10 :               .find(declarations->AtForTest(12)->var()->raw_name())
    7694           5 :               ->second;
    7695           5 :   CheckEntry(entry, "foob", "foob", nullptr, -1);
    7696             :   // TODO(neis): The next lines are terrible. Find a better way.
    7697           5 :   auto name_x = declarations->AtForTest(0)->var()->raw_name();
    7698           5 :   CHECK_EQ(2u, descriptor->regular_exports().count(name_x));
    7699             :   auto it = descriptor->regular_exports().equal_range(name_x).first;
    7700           5 :   entry = it->second;
    7701           5 :   if (entry->export_name->IsOneByteEqualTo("y")) {
    7702           5 :     CheckEntry(entry, "y", "x", nullptr, -1);
    7703           5 :     entry = (++it)->second;
    7704           5 :     CheckEntry(entry, "x", "x", nullptr, -1);
    7705             :   } else {
    7706           0 :     CheckEntry(entry, "x", "x", nullptr, -1);
    7707           0 :     entry = (++it)->second;
    7708           0 :     CheckEntry(entry, "y", "x", nullptr, -1);
    7709             :   }
    7710             : 
    7711          10 :   CHECK_EQ(2, descriptor->namespace_imports().size());
    7712           5 :   CheckEntry(descriptor->namespace_imports().at(0), nullptr, "loo", nullptr, 4);
    7713             :   CheckEntry(descriptor->namespace_imports().at(1), nullptr, "foob", nullptr,
    7714           5 :              4);
    7715             : 
    7716           5 :   CHECK_EQ(4u, descriptor->regular_imports().size());
    7717             :   entry = descriptor->regular_imports()
    7718          10 :               .find(declarations->AtForTest(1)->var()->raw_name())
    7719           5 :               ->second;
    7720           5 :   CheckEntry(entry, nullptr, "z", "q", 0);
    7721             :   entry = descriptor->regular_imports()
    7722          10 :               .find(declarations->AtForTest(2)->var()->raw_name())
    7723           5 :               ->second;
    7724           5 :   CheckEntry(entry, nullptr, "n", "default", 1);
    7725             :   entry = descriptor->regular_imports()
    7726          10 :               .find(declarations->AtForTest(9)->var()->raw_name())
    7727           5 :               ->second;
    7728           5 :   CheckEntry(entry, nullptr, "mm", "m", 0);
    7729             :   entry = descriptor->regular_imports()
    7730          10 :               .find(declarations->AtForTest(10)->var()->raw_name())
    7731           5 :               ->second;
    7732          10 :   CheckEntry(entry, nullptr, "aa", "aa", 0);
    7733           5 : }
    7734             : 
    7735             : 
    7736       28342 : TEST(DuplicateProtoError) {
    7737             :   const char* context_data[][2] = {
    7738           5 :       {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
    7739             :   const char* error_data[] = {"__proto__: {}, __proto__: {}",
    7740             :                               "__proto__: {}, \"__proto__\": {}",
    7741             :                               "__proto__: {}, \"__\x70roto__\": {}",
    7742           5 :                               "__proto__: {}, a: 1, __proto__: {}", nullptr};
    7743             : 
    7744           5 :   RunParserSyncTest(context_data, error_data, kError);
    7745           5 : }
    7746             : 
    7747             : 
    7748       28342 : TEST(DuplicateProtoNoError) {
    7749             :   const char* context_data[][2] = {
    7750           5 :       {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
    7751             :   const char* error_data[] = {
    7752             :       "__proto__: {}, ['__proto__']: {}",  "__proto__: {}, __proto__() {}",
    7753             :       "__proto__: {}, get __proto__() {}", "__proto__: {}, set __proto__(v) {}",
    7754           5 :       "__proto__: {}, __proto__",          nullptr};
    7755             : 
    7756           5 :   RunParserSyncTest(context_data, error_data, kSuccess);
    7757           5 : }
    7758             : 
    7759             : 
    7760       28342 : TEST(DeclarationsError) {
    7761             :   const char* context_data[][2] = {{"'use strict'; if (true)", ""},
    7762             :                                    {"'use strict'; if (false) {} else", ""},
    7763             :                                    {"'use strict'; while (false)", ""},
    7764             :                                    {"'use strict'; for (;;)", ""},
    7765             :                                    {"'use strict'; for (x in y)", ""},
    7766             :                                    {"'use strict'; do ", " while (false)"},
    7767           5 :                                    {nullptr, nullptr}};
    7768             : 
    7769             :   const char* statement_data[] = {"let x = 1;", "const x = 1;", "class C {}",
    7770           5 :                                   nullptr};
    7771             : 
    7772           5 :   RunParserSyncTest(context_data, statement_data, kError);
    7773           5 : }
    7774             : 
    7775             : 
    7776          20 : void TestLanguageMode(const char* source,
    7777             :                       i::LanguageMode expected_language_mode) {
    7778             :   i::Isolate* isolate = CcTest::i_isolate();
    7779             :   i::Factory* factory = isolate->factory();
    7780          20 :   v8::HandleScope handles(CcTest::isolate());
    7781          20 :   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
    7782             :   v8::Context::Scope context_scope(context);
    7783          20 :   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    7784          20 :                                         128 * 1024);
    7785             : 
    7786             :   i::Handle<i::Script> script =
    7787          20 :       factory->NewScript(factory->NewStringFromAsciiChecked(source));
    7788          40 :   i::ParseInfo info(isolate, script);
    7789          20 :   i::parsing::ParseProgram(&info, isolate);
    7790          20 :   CHECK_NOT_NULL(info.literal());
    7791          40 :   CHECK_EQ(expected_language_mode, info.literal()->language_mode());
    7792          20 : }
    7793             : 
    7794             : 
    7795       28342 : TEST(LanguageModeDirectives) {
    7796           5 :   TestLanguageMode("\"use nothing\"", i::LanguageMode::kSloppy);
    7797           5 :   TestLanguageMode("\"use strict\"", i::LanguageMode::kStrict);
    7798             : 
    7799           5 :   TestLanguageMode("var x = 1; \"use strict\"", i::LanguageMode::kSloppy);
    7800             : 
    7801             :   TestLanguageMode("\"use some future directive\"; \"use strict\";",
    7802           5 :                    i::LanguageMode::kStrict);
    7803           5 : }
    7804             : 
    7805             : 
    7806       28342 : TEST(PropertyNameEvalArguments) {
    7807           5 :   const char* context_data[][2] = {{"'use strict';", ""}, {nullptr, nullptr}};
    7808             : 
    7809             :   const char* statement_data[] = {"({eval: 1})",
    7810             :                                   "({arguments: 1})",
    7811             :                                   "({eval() {}})",
    7812             :                                   "({arguments() {}})",
    7813             :                                   "({*eval() {}})",
    7814             :                                   "({*arguments() {}})",
    7815             :                                   "({get eval() {}})",
    7816             :                                   "({get arguments() {}})",
    7817             :                                   "({set eval(_) {}})",
    7818             :                                   "({set arguments(_) {}})",
    7819             : 
    7820             :                                   "class C {eval() {}}",
    7821             :                                   "class C {arguments() {}}",
    7822             :                                   "class C {*eval() {}}",
    7823             :                                   "class C {*arguments() {}}",
    7824             :                                   "class C {get eval() {}}",
    7825             :                                   "class C {get arguments() {}}",
    7826             :                                   "class C {set eval(_) {}}",
    7827             :                                   "class C {set arguments(_) {}}",
    7828             : 
    7829             :                                   "class C {static eval() {}}",
    7830             :                                   "class C {static arguments() {}}",
    7831             :                                   "class C {static *eval() {}}",
    7832             :                                   "class C {static *arguments() {}}",
    7833             :                                   "class C {static get eval() {}}",
    7834             :                                   "class C {static get arguments() {}}",
    7835             :                                   "class C {static set eval(_) {}}",
    7836             :                                   "class C {static set arguments(_) {}}",
    7837             : 
    7838           5 :                                   nullptr};
    7839             : 
    7840           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
    7841           5 : }
    7842             : 
    7843             : 
    7844       28342 : TEST(FunctionLiteralDuplicateParameters) {
    7845             :   const char* strict_context_data[][2] = {
    7846             :       {"'use strict';(function(", "){})();"},
    7847             :       {"(function(", ") { 'use strict'; })();"},
    7848             :       {"'use strict'; function fn(", ") {}; fn();"},
    7849             :       {"function fn(", ") { 'use strict'; }; fn();"},
    7850           5 :       {nullptr, nullptr}};
    7851             : 
    7852             :   const char* sloppy_context_data[][2] = {{"(function(", "){})();"},
    7853             :                                           {"(function(", ") {})();"},
    7854             :                                           {"function fn(", ") {}; fn();"},
    7855             :                                           {"function fn(", ") {}; fn();"},
    7856           5 :                                           {nullptr, nullptr}};
    7857             : 
    7858             :   const char* data[] = {
    7859             :       "a, a",
    7860             :       "a, a, a",
    7861             :       "b, a, a",
    7862             :       "a, b, c, c",
    7863             :       "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
    7864           5 :       nullptr};
    7865             : 
    7866           5 :   RunParserSyncTest(strict_context_data, data, kError);
    7867           5 :   RunParserSyncTest(sloppy_context_data, data, kSuccess);
    7868           5 : }
    7869             : 
    7870             : 
    7871       28342 : TEST(ArrowFunctionASIErrors) {
    7872             :   const char* context_data[][2] = {
    7873           5 :       {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
    7874             : 
    7875             :   const char* data[] = {"(a\n=> a)(1)",
    7876             :                         "(a/*\n*/=> a)(1)",
    7877             :                         "((a)\n=> a)(1)",
    7878             :                         "((a)/*\n*/=> a)(1)",
    7879             :                         "((a, b)\n=> a + b)(1, 2)",
    7880             :                         "((a, b)/*\n*/=> a + b)(1, 2)",
    7881           5 :                         nullptr};
    7882           5 :   RunParserSyncTest(context_data, data, kError);
    7883           5 : }
    7884             : 
    7885       28342 : TEST(ObjectSpreadPositiveTests) {
    7886             :   // clang-format off
    7887             :   const char* context_data[][2] = {
    7888             :     {"x = ", ""},
    7889             :     {"'use strict'; x = ", ""},
    7890           5 :     {nullptr, nullptr}};
    7891             : 
    7892             :   // clang-format off
    7893             :   const char* data[] = {
    7894             :     "{ ...y }",
    7895             :     "{ a: 1, ...y }",
    7896             :     "{ b: 1, ...y }",
    7897             :     "{ y, ...y}",
    7898             :     "{ ...z = y}",
    7899             :     "{ ...y, y }",
    7900             :     "{ ...y, ...y}",
    7901             :     "{ a: 1, ...y, b: 1}",
    7902             :     "{ ...y, b: 1}",
    7903             :     "{ ...1}",
    7904             :     "{ ...null}",
    7905             :     "{ ...undefined}",
    7906             :     "{ ...1 in {}}",
    7907             :     "{ ...[]}",
    7908             :     "{ ...async function() { }}",
    7909             :     "{ ...async () => { }}",
    7910             :     "{ ...new Foo()}",
    7911           5 :     nullptr};
    7912             :   // clang-format on
    7913             : 
    7914           5 :   RunParserSyncTest(context_data, data, kSuccess);
    7915           5 : }
    7916             : 
    7917       28342 : TEST(ObjectSpreadNegativeTests) {
    7918             :   const char* context_data[][2] = {
    7919           5 :       {"x = ", ""}, {"'use strict'; x = ", ""}, {nullptr, nullptr}};
    7920             : 
    7921             :   // clang-format off
    7922             :   const char* data[] = {
    7923             :     "{ ...var z = y}",
    7924             :     "{ ...var}",
    7925             :     "{ ...foo bar}",
    7926             :     "{* ...foo}",
    7927             :     "{get ...foo}",
    7928             :     "{set ...foo}",
    7929             :     "{async ...foo}",
    7930           5 :     nullptr};
    7931             : 
    7932           5 :   RunParserSyncTest(context_data, data, kError);
    7933           5 : }
    7934             : 
    7935       28342 : TEST(TemplateEscapesPositiveTests) {
    7936             :   // clang-format off
    7937             :   const char* context_data[][2] = {
    7938             :     {"", ""},
    7939             :     {"'use strict';", ""},
    7940           5 :     {nullptr, nullptr}};
    7941             : 
    7942             :   // clang-format off
    7943             :   const char* data[] = {
    7944             :     "tag`\\08`",
    7945             :     "tag`\\01`",
    7946             :     "tag`\\01${0}right`",
    7947             :     "tag`left${0}\\01`",
    7948             :     "tag`left${0}\\01${1}right`",
    7949             :     "tag`\\1`",
    7950             :     "tag`\\1${0}right`",
    7951             :     "tag`left${0}\\1`",
    7952             :     "tag`left${0}\\1${1}right`",
    7953             :     "tag`\\xg`",
    7954             :     "tag`\\xg${0}right`",
    7955             :     "tag`left${0}\\xg`",
    7956             :     "tag`left${0}\\xg${1}right`",
    7957             :     "tag`\\xAg`",
    7958             :     "tag`\\xAg${0}right`",
    7959             :     "tag`left${0}\\xAg`",
    7960             :     "tag`left${0}\\xAg${1}right`",
    7961             :     "tag`\\u0`",
    7962             :     "tag`\\u0${0}right`",
    7963             :     "tag`left${0}\\u0`",
    7964             :     "tag`left${0}\\u0${1}right`",
    7965             :     "tag`\\u0g`",
    7966             :     "tag`\\u0g${0}right`",
    7967             :     "tag`left${0}\\u0g`",
    7968             :     "tag`left${0}\\u0g${1}right`",
    7969             :     "tag`\\u00g`",
    7970             :     "tag`\\u00g${0}right`",
    7971             :     "tag`left${0}\\u00g`",
    7972             :     "tag`left${0}\\u00g${1}right`",
    7973             :     "tag`\\u000g`",
    7974             :     "tag`\\u000g${0}right`",
    7975             :     "tag`left${0}\\u000g`",
    7976             :     "tag`left${0}\\u000g${1}right`",
    7977             :     "tag`\\u{}`",
    7978             :     "tag`\\u{}${0}right`",
    7979             :     "tag`left${0}\\u{}`",
    7980             :     "tag`left${0}\\u{}${1}right`",
    7981             :     "tag`\\u{-0}`",
    7982             :     "tag`\\u{-0}${0}right`",
    7983             :     "tag`left${0}\\u{-0}`",
    7984             :     "tag`left${0}\\u{-0}${1}right`",
    7985             :     "tag`\\u{g}`",
    7986             :     "tag`\\u{g}${0}right`",
    7987             :     "tag`left${0}\\u{g}`",
    7988             :     "tag`left${0}\\u{g}${1}right`",
    7989             :     "tag`\\u{0`",
    7990             :     "tag`\\u{0${0}right`",
    7991             :     "tag`left${0}\\u{0`",
    7992             :     "tag`left${0}\\u{0${1}right`",
    7993             :     "tag`\\u{\\u{0}`",
    7994             :     "tag`\\u{\\u{0}${0}right`",
    7995             :     "tag`left${0}\\u{\\u{0}`",
    7996             :     "tag`left${0}\\u{\\u{0}${1}right`",
    7997             :     "tag`\\u{110000}`",
    7998             :     "tag`\\u{110000}${0}right`",
    7999             :     "tag`left${0}\\u{110000}`",
    8000             :     "tag`left${0}\\u{110000}${1}right`",
    8001             :     "tag` ${tag`\\u`}`",
    8002             :     "tag` ``\\u`",
    8003             :     "tag`\\u`` `",
    8004             :     "tag`\\u``\\u`",
    8005             :     "` ${tag`\\u`}`",
    8006             :     "` ``\\u`",
    8007           5 :     nullptr};
    8008             :   // clang-format on
    8009             : 
    8010           5 :   RunParserSyncTest(context_data, data, kSuccess);
    8011           5 : }
    8012             : 
    8013       28342 : TEST(TemplateEscapesNegativeTests) {
    8014             :   // clang-format off
    8015             :   const char* context_data[][2] = {
    8016             :     {"", ""},
    8017             :     {"'use strict';", ""},
    8018           5 :     {nullptr, nullptr}};
    8019             : 
    8020             :   // clang-format off
    8021             :   const char* data[] = {
    8022             :     "`\\08`",
    8023             :     "`\\01`",
    8024             :     "`\\01${0}right`",
    8025             :     "`left${0}\\01`",
    8026             :     "`left${0}\\01${1}right`",
    8027             :     "`\\1`",
    8028             :     "`\\1${0}right`",
    8029             :     "`left${0}\\1`",
    8030             :     "`left${0}\\1${1}right`",
    8031             :     "`\\xg`",
    8032             :     "`\\xg${0}right`",
    8033             :     "`left${0}\\xg`",
    8034             :     "`left${0}\\xg${1}right`",
    8035             :     "`\\xAg`",
    8036             :     "`\\xAg${0}right`",
    8037             :     "`left${0}\\xAg`",
    8038             :     "`left${0}\\xAg${1}right`",
    8039             :     "`\\u0`",
    8040             :     "`\\u0${0}right`",
    8041             :     "`left${0}\\u0`",
    8042             :     "`left${0}\\u0${1}right`",
    8043             :     "`\\u0g`",
    8044             :     "`\\u0g${0}right`",
    8045             :     "`left${0}\\u0g`",
    8046             :     "`left${0}\\u0g${1}right`",
    8047             :     "`\\u00g`",
    8048             :     "`\\u00g${0}right`",
    8049             :     "`left${0}\\u00g`",
    8050             :     "`left${0}\\u00g${1}right`",
    8051             :     "`\\u000g`",
    8052             :     "`\\u000g${0}right`",
    8053             :     "`left${0}\\u000g`",
    8054             :     "`left${0}\\u000g${1}right`",
    8055             :     "`\\u{}`",
    8056             :     "`\\u{}${0}right`",
    8057             :     "`left${0}\\u{}`",
    8058             :     "`left${0}\\u{}${1}right`",
    8059             :     "`\\u{-0}`",
    8060             :     "`\\u{-0}${0}right`",
    8061             :     "`left${0}\\u{-0}`",
    8062             :     "`left${0}\\u{-0}${1}right`",
    8063             :     "`\\u{g}`",
    8064             :     "`\\u{g}${0}right`",
    8065             :     "`left${0}\\u{g}`",
    8066             :     "`left${0}\\u{g}${1}right`",
    8067             :     "`\\u{0`",
    8068             :     "`\\u{0${0}right`",
    8069             :     "`left${0}\\u{0`",
    8070             :     "`left${0}\\u{0${1}right`",
    8071             :     "`\\u{\\u{0}`",
    8072             :     "`\\u{\\u{0}${0}right`",
    8073             :     "`left${0}\\u{\\u{0}`",
    8074             :     "`left${0}\\u{\\u{0}${1}right`",
    8075             :     "`\\u{110000}`",
    8076             :     "`\\u{110000}${0}right`",
    8077             :     "`left${0}\\u{110000}`",
    8078             :     "`left${0}\\u{110000}${1}right`",
    8079             :     "`\\1``\\2`",
    8080             :     "tag` ${`\\u`}`",
    8081             :     "`\\u```",
    8082           5 :     nullptr};
    8083             :   // clang-format on
    8084             : 
    8085           5 :   RunParserSyncTest(context_data, data, kError);
    8086           5 : }
    8087             : 
    8088       28342 : TEST(DestructuringPositiveTests) {
    8089             :   const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
    8090             :                                    {"var ", " = {};"},
    8091             :                                    {"'use strict'; const ", " = {};"},
    8092             :                                    {"function f(", ") {}"},
    8093             :                                    {"function f(argument1, ", ") {}"},
    8094             :                                    {"var f = (", ") => {};"},
    8095             :                                    {"var f = (argument1,", ") => {};"},
    8096             :                                    {"try {} catch(", ") {}"},
    8097           5 :                                    {nullptr, nullptr}};
    8098             : 
    8099             :   // clang-format off
    8100             :   const char* data[] = {
    8101             :     "a",
    8102             :     "{ x : y }",
    8103             :     "{ x : y = 1 }",
    8104             :     "{ get, set }",
    8105             :     "{ get = 1, set = 2 }",
    8106             :     "[a]",
    8107             :     "[a = 1]",
    8108             :     "[a,b,c]",
    8109             :     "[a, b = 42, c]",
    8110             :     "{ x : x, y : y }",
    8111             :     "{ x : x = 1, y : y }",
    8112             :     "{ x : x, y : y = 42 }",
    8113             :     "[]",
    8114             :     "{}",
    8115             :     "[{x:x, y:y}, [a,b,c]]",
    8116             :     "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
    8117             :     "{x}",
    8118             :     "{x, y}",
    8119             :     "{x = 42, y = 15}",
    8120             :     "[a,,b]",
    8121             :     "{42 : x}",
    8122             :     "{42 : x = 42}",
    8123             :     "{42e-2 : x}",
    8124             :     "{42e-2 : x = 42}",
    8125             :     "{x : y, x : z}",
    8126             :     "{'hi' : x}",
    8127             :     "{'hi' : x = 42}",
    8128             :     "{var: x}",
    8129             :     "{var: x = 42}",
    8130             :     "{[x] : z}",
    8131             :     "{[1+1] : z}",
    8132             :     "{[foo()] : z}",
    8133             :     "{}",
    8134             :     "[...rest]",
    8135             :     "[a,b,...rest]",
    8136             :     "[a,,...rest]",
    8137             :     "{ __proto__: x, __proto__: y}",
    8138             :     "{arguments: x}",
    8139             :     "{eval: x}",
    8140             :     "{ x : y, ...z }",
    8141             :     "{ x : y = 1, ...z }",
    8142             :     "{ x : x, y : y, ...z }",
    8143             :     "{ x : x = 1, y : y, ...z }",
    8144             :     "{ x : x, y : y = 42, ...z }",
    8145             :     "[{x:x, y:y, ...z}, [a,b,c]]",
    8146             :     "[{x:x = 1, y:y = 2, ...z}, [a = 3, b = 4, c = 5]]",
    8147             :     "{...x}",
    8148             :     "{x, ...y}",
    8149             :     "{x = 42, y = 15, ...z}",
    8150             :     "{42 : x = 42, ...y}",
    8151             :     "{'hi' : x, ...z}",
    8152             :     "{'hi' : x = 42, ...z}",
    8153             :     "{var: x = 42, ...z}",
    8154             :     "{[x] : z, ...y}",
    8155             :     "{[1+1] : z, ...x}",
    8156             :     "{arguments: x, ...z}",
    8157             :     "{ __proto__: x, __proto__: y, ...z}",
    8158             :     nullptr
    8159           5 :   };
    8160             : 
    8161             :   // clang-format on
    8162           5 :   RunParserSyncTest(context_data, data, kSuccess);
    8163             : 
    8164             :   // v8:5201
    8165             :   {
    8166             :     // clang-format off
    8167             :     const char* sloppy_context_data[][2] = {
    8168             :       {"var ", " = {};"},
    8169             :       {"function f(", ") {}"},
    8170             :       {"function f(argument1, ", ") {}"},
    8171             :       {"var f = (", ") => {};"},
    8172             :       {"var f = (argument1,", ") => {};"},
    8173             :       {"try {} catch(", ") {}"},
    8174             :       {nullptr, nullptr}
    8175           5 :     };
    8176             : 
    8177             :     const char* data[] = {
    8178             :       "{arguments}",
    8179             :       "{eval}",
    8180             :       "{x: arguments}",
    8181             :       "{x: eval}",
    8182             :       "{arguments = false}",
    8183             :       "{eval = false}",
    8184             :       "{...arguments}",
    8185             :       "{...eval}",
    8186             :       nullptr
    8187           5 :     };
    8188             :     // clang-format on
    8189           5 :     RunParserSyncTest(sloppy_context_data, data, kSuccess);
    8190             :   }
    8191           5 : }
    8192             : 
    8193             : 
    8194       28342 : TEST(DestructuringNegativeTests) {
    8195             :   {  // All modes.
    8196             :     const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
    8197             :                                      {"var ", " = {};"},
    8198             :                                      {"'use strict'; const ", " = {};"},
    8199             :                                      {"function f(", ") {}"},
    8200             :                                      {"function f(argument1, ", ") {}"},
    8201             :                                      {"var f = (", ") => {};"},
    8202             :                                      {"var f = ", " => {};"},
    8203             :                                      {"var f = (argument1,", ") => {};"},
    8204             :                                      {"try {} catch(", ") {}"},
    8205           5 :                                      {nullptr, nullptr}};
    8206             : 
    8207             :     // clang-format off
    8208             :     const char* data[] = {
    8209             :         "a++",
    8210             :         "++a",
    8211             :         "delete a",
    8212             :         "void a",
    8213             :         "typeof a",
    8214             :         "--a",
    8215             :         "+a",
    8216             :         "-a",
    8217             :         "~a",
    8218             :         "!a",
    8219             :         "{ x : y++ }",
    8220             :         "[a++]",
    8221             :         "(x => y)",
    8222             :         "(async x => y)",
    8223             :         "((x, z) => y)",
    8224             :         "(async (x, z) => y)",
    8225             :         "a[i]", "a()",
    8226             :         "a.b",
    8227             :         "new a",
    8228             :         "a + a",
    8229             :         "a - a",
    8230             :         "a * a",
    8231             :         "a / a",
    8232             :         "a == a",
    8233             :         "a != a",
    8234             :         "a > a",
    8235             :         "a < a",
    8236             :         "a <<< a",
    8237             :         "a >>> a",
    8238             :         "function a() {}",
    8239             :         "function* a() {}",
    8240             :         "async function a() {}",
    8241             :         "a`bcd`",
    8242             :         "this",
    8243             :         "null",
    8244             :         "true",
    8245             :         "false",
    8246             :         "1",
    8247             :         "'abc'",
    8248             :         "/abc/",
    8249             :         "`abc`",
    8250             :         "class {}",
    8251             :         "{+2 : x}",
    8252             :         "{-2 : x}",
    8253             :         "var",
    8254             :         "[var]",
    8255             :         "{x : {y : var}}",
    8256             :         "{x : x = a+}",
    8257             :         "{x : x = (a+)}",
    8258             :         "{x : x += a}",
    8259             :         "{m() {} = 0}",
    8260             :         "{[1+1]}",
    8261             :         "[...rest, x]",
    8262             :         "[a,b,...rest, x]",
    8263             :         "[a,,...rest, x]",
    8264             :         "[...rest,]",
    8265             :         "[a,b,...rest,]",
    8266             :         "[a,,...rest,]",
    8267             :         "[...rest,...rest1]",
    8268             :         "[a,b,...rest,...rest1]",
    8269             :         "[a,,..rest,...rest1]",
    8270             :         "[x, y, ...z = 1]",
    8271             :         "[...z = 1]",
    8272             :         "[x, y, ...[z] = [1]]",
    8273             :         "[...[z] = [1]]",
    8274             :         "{ x : 3 }",
    8275             :         "{ x : 'foo' }",
    8276             :         "{ x : /foo/ }",
    8277             :         "{ x : `foo` }",
    8278             :         "{ get a() {} }",
    8279             :         "{ set a() {} }",
    8280             :         "{ method() {} }",
    8281             :         "{ *method() {} }",
    8282             :         "...a++",
    8283             :         "...++a",
    8284             :         "...typeof a",
    8285             :         "...[a++]",
    8286             :         "...(x => y)",
    8287             :         "{ ...x, }",
    8288             :         "{ ...x, y }",
    8289             :         "{ y, ...x, y }",
    8290             :         "{ ...x, ...y }",
    8291             :         "{ ...x, ...x }",
    8292             :         "{ ...x, ...x = {} }",
    8293             :         "{ ...x, ...x = ...x }",
    8294             :         "{ ...x, ...x = ...{ x } }",
    8295             :         "{ ,, ...x }",
    8296             :         "{ ...get a() {} }",
    8297             :         "{ ...set a() {} }",
    8298             :         "{ ...method() {} }",
    8299             :         "{ ...function() {} }",
    8300             :         "{ ...*method() {} }",
    8301             :         "{...{x} }",
    8302             :         "{...[x] }",
    8303             :         "{...{ x = 5 } }",
    8304             :         "{...[ x = 5 ] }",
    8305             :         "{...x.f }",
    8306             :         "{...x[0] }",
    8307             :         "async function* a() {}",
    8308             :         nullptr
    8309           5 :     };
    8310             : 
    8311             :     // clang-format on
    8312           5 :     RunParserSyncTest(context_data, data, kError);
    8313             :   }
    8314             : 
    8315             :   {  // All modes.
    8316             :     const char* context_data[][2] = {
    8317             :         {"'use strict'; let ", " = {};"},    {"var ", " = {};"},
    8318             :         {"'use strict'; const ", " = {};"},  {"function f(", ") {}"},
    8319             :         {"function f(argument1, ", ") {}"},  {"var f = (", ") => {};"},
    8320           5 :         {"var f = (argument1,", ") => {};"}, {nullptr, nullptr}};
    8321             : 
    8322             :     // clang-format off
    8323             :     const char* data[] = {
    8324             :         "x => x",
    8325             :         "() => x",
    8326           5 :         nullptr};
    8327             :     // clang-format on
    8328           5 :     RunParserSyncTest(context_data, data, kError);
    8329             :   }
    8330             : 
    8331             :   {  // Strict mode.
    8332             :     const char* context_data[][2] = {
    8333             :         {"'use strict'; var ", " = {};"},
    8334             :         {"'use strict'; let ", " = {};"},
    8335             :         {"'use strict'; const ", " = {};"},
    8336             :         {"'use strict'; function f(", ") {}"},
    8337             :         {"'use strict'; function f(argument1, ", ") {}"},
    8338           5 :         {nullptr, nullptr}};
    8339             : 
    8340             :     // clang-format off
    8341             :     const char* data[] = {
    8342             :       "[arguments]",
    8343             :       "[eval]",
    8344             :       "{ a : arguments }",
    8345             :       "{ a : eval }",
    8346             :       "[public]",
    8347             :       "{ x : private }",
    8348             :       "{ x : arguments }",
    8349             :       "{ x : eval }",
    8350             :       "{ arguments }",
    8351             :       "{ eval }",
    8352             :       "{ arguments = false }"
    8353             :       "{ eval = false }",
    8354             :       "{ ...eval }",
    8355             :       "{ ...arguments }",
    8356           5 :       nullptr};
    8357             : 
    8358             :     // clang-format on
    8359           5 :     RunParserSyncTest(context_data, data, kError);
    8360             :   }
    8361             : 
    8362             :   {  // 'yield' in generators.
    8363             :     const char* context_data[][2] = {
    8364             :         {"function*() { var ", " = {};"},
    8365             :         {"function*() { 'use strict'; let ", " = {};"},
    8366             :         {"function*() { 'use strict'; const ", " = {};"},
    8367           5 :         {nullptr, nullptr}};
    8368             : 
    8369             :     // clang-format off
    8370             :     const char* data[] = {
    8371             :       "yield",
    8372             :       "[yield]",
    8373             :       "{ x : yield }",
    8374           5 :       nullptr};
    8375             :     // clang-format on
    8376           5 :     RunParserSyncTest(context_data, data, kError);
    8377             :   }
    8378             : 
    8379             :   { // Declaration-specific errors
    8380             :     const char* context_data[][2] = {{"'use strict'; var ", ""},
    8381             :                                      {"'use strict'; let ", ""},
    8382             :                                      {"'use strict'; const ", ""},
    8383             :                                      {"'use strict'; for (var ", ";;) {}"},
    8384             :                                      {"'use strict'; for (let ", ";;) {}"},
    8385             :                                      {"'use strict'; for (const ", ";;) {}"},
    8386             :                                      {"var ", ""},
    8387             :                                      {"let ", ""},
    8388             :                                      {"const ", ""},
    8389             :                                      {"for (var ", ";;) {}"},
    8390             :                                      {"for (let ", ";;) {}"},
    8391             :                                      {"for (const ", ";;) {}"},
    8392           5 :                                      {nullptr, nullptr}};
    8393             : 
    8394             :     // clang-format off
    8395             :     const char* data[] = {
    8396             :       "{ a }",
    8397             :       "[ a ]",
    8398             :       "{ ...a }",
    8399             :       nullptr
    8400           5 :     };
    8401             :     // clang-format on
    8402           5 :     RunParserSyncTest(context_data, data, kError);
    8403             :   }
    8404           5 : }
    8405             : 
    8406       28342 : TEST(ObjectRestNegativeTestSlow) {
    8407             :   // clang-format off
    8408             :   const char* context_data[][2] = {
    8409             :     {"var { ", " } = { a: 1};"},
    8410             :     { nullptr, nullptr }
    8411           5 :   };
    8412             : 
    8413             :   using v8::internal::Code;
    8414             :   std::string statement;
    8415      327675 :   for (int i = 0; i < Code::kMaxArguments; ++i) {
    8416      983010 :     statement += std::to_string(i) + " : " + "x, ";
    8417             :   }
    8418             :   statement += "...y";
    8419             : 
    8420             :   const char* statement_data[] = {
    8421             :     statement.c_str(),
    8422             :     nullptr
    8423          10 :   };
    8424             : 
    8425             :   // clang-format on
    8426             :   // The test is quite slow, so run it with a reduced set of flags.
    8427             :   static const ParserFlag flags[] = {kAllowLazy};
    8428             :   RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags,
    8429           5 :                     arraysize(flags));
    8430           5 : }
    8431             : 
    8432       28342 : TEST(DestructuringAssignmentPositiveTests) {
    8433             :   const char* context_data[][2] = {
    8434             :       {"'use strict'; let x, y, z; (", " = {});"},
    8435             :       {"var x, y, z; (", " = {});"},
    8436             :       {"'use strict'; let x, y, z; for (x in ", " = {});"},
    8437             :       {"'use strict'; let x, y, z; for (x of ", " = {});"},
    8438             :       {"var x, y, z; for (x in ", " = {});"},
    8439             :       {"var x, y, z; for (x of ", " = {});"},
    8440             :       {"var x, y, z; for (", " in {});"},
    8441             :       {"var x, y, z; for (", " of {});"},
    8442             :       {"'use strict'; var x, y, z; for (", " in {});"},
    8443             :       {"'use strict'; var x, y, z; for (", " of {});"},
    8444             :       {"var x, y, z; m(['a']) ? ", " = {} : rhs"},
    8445             :       {"var x, y, z; m(['b']) ? lhs : ", " = {}"},
    8446             :       {"'use strict'; var x, y, z; m(['a']) ? ", " = {} : rhs"},
    8447             :       {"'use strict'; var x, y, z; m(['b']) ? lhs : ", " = {}"},
    8448           5 :       {nullptr, nullptr}};
    8449             : 
    8450             :   const char* mixed_assignments_context_data[][2] = {
    8451             :       {"'use strict'; let x, y, z; (", " = z = {});"},
    8452             :       {"var x, y, z; (", " = z = {});"},
    8453             :       {"'use strict'; let x, y, z; (x = ", " = z = {});"},
    8454             :       {"var x, y, z; (x = ", " = z = {});"},
    8455             :       {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
    8456             :       {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
    8457             :       {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
    8458             :       {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
    8459             :       {"var x, y, z; for (x in ", " = z = {});"},
    8460             :       {"var x, y, z; for (x in x = ", " = z = {});"},
    8461             :       {"var x, y, z; for (x of ", " = z = {});"},
    8462             :       {"var x, y, z; for (x of x = ", " = z = {});"},
    8463           5 :       {nullptr, nullptr}};
    8464             : 
    8465             :   // clang-format off
    8466             :   const char* data[] = {
    8467             :     "x",
    8468             : 
    8469             :     "{ x : y }",
    8470             :     "{ x : foo().y }",
    8471             :     "{ x : foo()[y] }",
    8472             :     "{ x : y.z }",
    8473             :     "{ x : y[z] }",
    8474             :     "{ x : { y } }",
    8475             :     "{ x : { foo: y } }",
    8476             :     "{ x : { foo: foo().y } }",
    8477             :     "{ x : { foo: foo()[y] } }",
    8478             :     "{ x : { foo: y.z } }",
    8479             :     "{ x : { foo: y[z] } }",
    8480             :     "{ x : [ y ] }",
    8481             :     "{ x : [ foo().y ] }",
    8482             :     "{ x : [ foo()[y] ] }",
    8483             :     "{ x : [ y.z ] }",
    8484             :     "{ x : [ y[z] ] }",
    8485             : 
    8486             :     "{ x : y = 10 }",
    8487             :     "{ x : foo().y = 10 }",
    8488             :     "{ x : foo()[y] = 10 }",
    8489             :     "{ x : y.z = 10 }",
    8490             :     "{ x : y[z] = 10 }",
    8491             :     "{ x : { y = 10 } = {} }",
    8492             :     "{ x : { foo: y = 10 } = {} }",
    8493             :     "{ x : { foo: foo().y = 10 } = {} }",
    8494             :     "{ x : { foo: foo()[y] = 10 } = {} }",
    8495             :     "{ x : { foo: y.z = 10 } = {} }",
    8496             :     "{ x : { foo: y[z] = 10 } = {} }",
    8497             :     "{ x : [ y = 10 ] = {} }",
    8498             :     "{ x : [ foo().y = 10 ] = {} }",
    8499             :     "{ x : [ foo()[y] = 10 ] = {} }",
    8500             :     "{ x : [ y.z = 10 ] = {} }",
    8501             :     "{ x : [ y[z] = 10 ] = {} }",
    8502             :     "{ z : { __proto__: x, __proto__: y } = z }"
    8503             : 
    8504             :     "[ x ]",
    8505             :     "[ foo().x ]",
    8506             :     "[ foo()[x] ]",
    8507             :     "[ x.y ]",
    8508             :     "[ x[y] ]",
    8509             :     "[ { x } ]",
    8510             :     "[ { x : y } ]",
    8511             :     "[ { x : foo().y } ]",
    8512             :     "[ { x : foo()[y] } ]",
    8513             :     "[ { x : x.y } ]",
    8514             :     "[ { x : x[y] } ]",
    8515             :     "[ [ x ] ]",
    8516             :     "[ [ foo().x ] ]",
    8517             :     "[ [ foo()[x] ] ]",
    8518             :     "[ [ x.y ] ]",
    8519             :     "[ [ x[y] ] ]",
    8520             : 
    8521             :     "[ x = 10 ]",
    8522             :     "[ foo().x = 10 ]",
    8523             :     "[ foo()[x] = 10 ]",
    8524             :     "[ x.y = 10 ]",
    8525             :     "[ x[y] = 10 ]",
    8526             :     "[ { x = 10 } = {} ]",
    8527             :     "[ { x : y = 10 } = {} ]",
    8528             :     "[ { x : foo().y = 10 } = {} ]",
    8529             :     "[ { x : foo()[y] = 10 } = {} ]",
    8530             :     "[ { x : x.y = 10 } = {} ]",
    8531             :     "[ { x : x[y] = 10 } = {} ]",
    8532             :     "[ [ x = 10 ] = {} ]",
    8533             :     "[ [ foo().x = 10 ] = {} ]",
    8534             :     "[ [ foo()[x] = 10 ] = {} ]",
    8535             :     "[ [ x.y = 10 ] = {} ]",
    8536             :     "[ [ x[y] = 10 ] = {} ]",
    8537             :     "{ x : y = 1 }",
    8538             :     "{ x }",
    8539             :     "{ x, y, z }",
    8540             :     "{ x = 1, y: z, z: y }",
    8541             :     "{x = 42, y = 15}",
    8542             :     "[x]",
    8543             :     "[x = 1]",
    8544             :     "[x,y,z]",
    8545             :     "[x, y = 42, z]",
    8546             :     "{ x : x, y : y }",
    8547             :     "{ x : x = 1, y : y }",
    8548             :     "{ x : x, y : y = 42 }",
    8549             :     "[]",
    8550             :     "{}",
    8551             :     "[{x:x, y:y}, [,x,z,]]",
    8552             :     "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
    8553             :     "[x,,y]",
    8554             :     "[(x),,(y)]",
    8555             :     "[(x)]",
    8556             :     "{42 : x}",
    8557             :     "{42 : x = 42}",
    8558             :     "{42e-2 : x}",
    8559             :     "{42e-2 : x = 42}",
    8560             :     "{'hi' : x}",
    8561             :     "{'hi' : x = 42}",
    8562             :     "{var: x}",
    8563             :     "{var: x = 42}",
    8564             :     "{var: (x) = 42}",
    8565             :     "{[x] : z}",
    8566             :     "{[1+1] : z}",
    8567             :     "{[1+1] : (z)}",
    8568             :     "{[foo()] : z}",
    8569             :     "{[foo()] : (z)}",
    8570             :     "{[foo()] : foo().bar}",
    8571             :     "{[foo()] : foo()['bar']}",
    8572             :     "{[foo()] : this.bar}",
    8573             :     "{[foo()] : this['bar']}",
    8574             :     "{[foo()] : 'foo'.bar}",
    8575             :     "{[foo()] : 'foo'['bar']}",
    8576             :     "[...x]",
    8577             :     "[x,y,...z]",
    8578             :     "[x,,...z]",
    8579             :     "{ x: y }",
    8580             :     "[x, y]",
    8581             :     "[((x, y) => z).x]",
    8582             :     "{x: ((y, z) => z).x}",
    8583             :     "[((x, y) => z)['x']]",
    8584             :     "{x: ((y, z) => z)['x']}",
    8585             : 
    8586             :     "{x: { y = 10 } }",
    8587             :     "[(({ x } = { x: 1 }) => x).a]",
    8588             : 
    8589             :     "{ ...d.x }",
    8590             :     "{ ...c[0]}",
    8591             : 
    8592             :     // v8:4662
    8593             :     "{ x: (y) }",
    8594             :     "{ x: (y) = [] }",
    8595             :     "{ x: (foo.bar) }",
    8596             :     "{ x: (foo['bar']) }",
    8597             :     "[ ...(a) ]",
    8598             :     "[ ...(foo['bar']) ]",
    8599             :     "[ ...(foo.bar) ]",
    8600             :     "[ (y) ]",
    8601             :     "[ (foo.bar) ]",
    8602             :     "[ (foo['bar']) ]",
    8603             : 
    8604           5 :     nullptr};
    8605             :   // clang-format on
    8606           5 :   RunParserSyncTest(context_data, data, kSuccess);
    8607             : 
    8608           5 :   RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
    8609             : 
    8610             :   const char* empty_context_data[][2] = {
    8611           5 :       {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
    8612             : 
    8613             :   // CoverInitializedName ambiguity handling in various contexts
    8614             :   const char* ambiguity_data[] = {
    8615             :       "var foo = { x = 10 } = {};",
    8616             :       "var foo = { q } = { x = 10 } = {};",
    8617             :       "var foo; foo = { x = 10 } = {};",
    8618             :       "var foo; foo = { q } = { x = 10 } = {};",
    8619             :       "var x; ({ x = 10 } = {});",
    8620             :       "var q, x; ({ q } = { x = 10 } = {});",
    8621             :       "var x; [{ x = 10 } = {}]",
    8622             :       "var x; (true ? { x = true } = {} : { x = false } = {})",
    8623             :       "var q, x; (q, { x = 10 } = {});",
    8624             :       "var { x = 10 } = { x = 20 } = {};",
    8625             :       "var { __proto__: x, __proto__: y } = {}",
    8626             :       "({ __proto__: x, __proto__: y } = {})",
    8627             :       "var { x = 10 } = (o = { x = 20 } = {});",
    8628             :       "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
    8629             :       nullptr,
    8630           5 :   };
    8631           5 :   RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
    8632           5 : }
    8633             : 
    8634             : 
    8635       28342 : TEST(DestructuringAssignmentNegativeTests) {
    8636             :   const char* context_data[][2] = {
    8637             :       {"'use strict'; let x, y, z; (", " = {});"},
    8638             :       {"var x, y, z; (", " = {});"},
    8639             :       {"'use strict'; let x, y, z; for (x in ", " = {});"},
    8640             :       {"'use strict'; let x, y, z; for (x of ", " = {});"},
    8641             :       {"var x, y, z; for (x in ", " = {});"},
    8642             :       {"var x, y, z; for (x of ", " = {});"},
    8643           5 :       {nullptr, nullptr}};
    8644             : 
    8645             :   // clang-format off
    8646             :   const char* data[] = {
    8647             :     "{ x : ++y }",
    8648             :     "{ x : y * 2 }",
    8649             :     "{ get x() {} }",
    8650             :     "{ set x() {} }",
    8651             :     "{ x: y() }",
    8652             :     "{ this }",
    8653             :     "{ x: this }",
    8654             :     "{ x: this = 1 }",
    8655             :     "{ super }",
    8656             :     "{ x: super }",
    8657             :     "{ x: super = 1 }",
    8658             :     "{ new.target }",
    8659             :     "{ x: new.target }",
    8660             :     "{ x: new.target = 1 }",
    8661             :     "{ import.meta }",
    8662             :     "{ x: import.meta }",
    8663             :     "{ x: import.meta = 1 }",
    8664             :     "[x--]",
    8665             :     "[--x = 1]",
    8666             :     "[x()]",
    8667             :     "[this]",
    8668             :     "[this = 1]",
    8669             :     "[new.target]",
    8670             :     "[new.target = 1]",
    8671             :     "[import.meta]",
    8672             :     "[import.meta = 1]",
    8673             :     "[super]",
    8674             :     "[super = 1]",
    8675             :     "[function f() {}]",
    8676             :     "[async function f() {}]",
    8677             :     "[function* f() {}]",
    8678             :     "[50]",
    8679             :     "[(50)]",
    8680             :     "[(function() {})]",
    8681             :     "[(async function() {})]",
    8682             :     "[(function*() {})]",
    8683             :     "[(foo())]",
    8684             :     "{ x: 50 }",
    8685             :     "{ x: (50) }",
    8686             :     "['str']",
    8687             :     "{ x: 'str' }",
    8688             :     "{ x: ('str') }",
    8689             :     "{ x: (foo()) }",
    8690             :     "{ x: function() {} }",
    8691             :     "{ x: async function() {} }",
    8692             :     "{ x: function*() {} }",
    8693             :     "{ x: (function() {}) }",
    8694             :     "{ x: (async function() {}) }",
    8695             :     "{ x: (function*() {}) }",
    8696             :     "{ x: y } = 'str'",
    8697             :     "[x, y] = 'str'",
    8698             :     "[(x,y) => z]",
    8699             :     "[async(x,y) => z]",
    8700             :     "[async x => z]",
    8701             :     "{x: (y) => z}",
    8702             :     "{x: (y,w) => z}",
    8703             :     "{x: async (y) => z}",
    8704             :     "{x: async (y,w) => z}",
    8705             :     "[x, ...y, z]",
    8706             :     "[...x,]",
    8707             :     "[x, y, ...z = 1]",
    8708             :     "[...z = 1]",
    8709             :     "[x, y, ...[z] = [1]]",
    8710             :     "[...[z] = [1]]",
    8711             : 
    8712             :     "[...++x]",
    8713             :     "[...x--]",
    8714             :     "[...!x]",
    8715             :     "[...x + y]",
    8716             : 
    8717             :     // v8:4657
    8718             :     "({ x: x4, x: (x+=1e4) })",
    8719             :     "(({ x: x4, x: (x+=1e4) }))",
    8720             :     "({ x: x4, x: (x+=1e4) } = {})",
    8721             :     "(({ x: x4, x: (x+=1e4) } = {}))",
    8722             :     "(({ x: x4, x: (x+=1e4) }) = {})",
    8723             :     "({ x: y } = {})",
    8724             :     "(({ x: y } = {}))",
    8725             :     "(({ x: y }) = {})",
    8726             :     "([a])",
    8727             :     "(([a]))",
    8728             :     "([a] = [])",
    8729             :     "(([a] = []))",
    8730             :     "(([a]) = [])",
    8731             : 
    8732             :     // v8:4662
    8733             :     "{ x: ([y]) }",
    8734             :     "{ x: ([y] = []) }",
    8735             :     "{ x: ({y}) }",
    8736             :     "{ x: ({y} = {}) }",
    8737             :     "{ x: (++y) }",
    8738             :     "[ (...[a]) ]",
    8739             :     "[ ...([a]) ]",
    8740             :     "[ ...([a] = [])",
    8741             :     "[ ...[ ( [ a ] ) ] ]",
    8742             :     "[ ([a]) ]",
    8743             :     "[ (...[a]) ]",
    8744             :     "[ ([a] = []) ]",
    8745             :     "[ (++y) ]",
    8746             :     "[ ...(++y) ]",
    8747             : 
    8748             :     "[ x += x ]",
    8749             :     "{ foo: x += x }",
    8750             : 
    8751           5 :     nullptr};
    8752             :   // clang-format on
    8753           5 :   RunParserSyncTest(context_data, data, kError);
    8754             : 
    8755             :   const char* empty_context_data[][2] = {
    8756           5 :       {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
    8757             : 
    8758             :   // CoverInitializedName ambiguity handling in various contexts
    8759             :   const char* ambiguity_data[] = {
    8760             :       "var foo = { x = 10 };", "var foo = { q } = { x = 10 };",
    8761             :       "var foo; foo = { x = 10 };", "var foo; foo = { q } = { x = 10 };",
    8762             :       "var x; ({ x = 10 });", "var q, x; ({ q } = { x = 10 });",
    8763             :       "var x; [{ x = 10 }]", "var x; (true ? { x = true } : { x = false })",
    8764             :       "var q, x; (q, { x = 10 });", "var { x = 10 } = { x = 20 };",
    8765             :       "var { x = 10 } = (o = { x = 20 });",
    8766             :       "var x; (({ x = 10 } = { x = 20 }) => x)({})",
    8767             : 
    8768             :       // Not ambiguous, but uses same context data
    8769             :       "switch([window %= []] = []) { default: }",
    8770             : 
    8771             :       nullptr,
    8772           5 :   };
    8773           5 :   RunParserSyncTest(empty_context_data, ambiguity_data, kError);
    8774             : 
    8775             :   // Strict mode errors
    8776             :   const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
    8777             :                                           {"'use strict'; for (", " of {}) {}"},
    8778             :                                           {"'use strict'; for (", " in {}) {}"},
    8779           5 :                                           {nullptr, nullptr}};
    8780             :   const char* strict_data[] = {
    8781             :       "{ eval }", "{ arguments }", "{ foo: eval }", "{ foo: arguments }",
    8782             :       "{ eval = 0 }", "{ arguments = 0 }", "{ foo: eval = 0 }",
    8783             :       "{ foo: arguments = 0 }", "[ eval ]", "[ arguments ]", "[ eval = 0 ]",
    8784             :       "[ arguments = 0 ]",
    8785             : 
    8786             :       // v8:4662
    8787             :       "{ x: (eval) }", "{ x: (arguments) }", "{ x: (eval = 0) }",
    8788             :       "{ x: (arguments = 0) }", "{ x: (eval) = 0 }", "{ x: (arguments) = 0 }",
    8789             :       "[ (eval) ]", "[ (arguments) ]", "[ (eval = 0) ]", "[ (arguments = 0) ]",
    8790             :       "[ (eval) = 0 ]", "[ (arguments) = 0 ]", "[ ...(eval) ]",
    8791             :       "[ ...(arguments) ]", "[ ...(eval = 0) ]", "[ ...(arguments = 0) ]",
    8792             :       "[ ...(eval) = 0 ]", "[ ...(arguments) = 0 ]",
    8793             : 
    8794           5 :       nullptr};
    8795           5 :   RunParserSyncTest(strict_context_data, strict_data, kError);
    8796           5 : }
    8797             : 
    8798             : 
    8799       28342 : TEST(DestructuringDisallowPatternsInForVarIn) {
    8800             :   const char* context_data[][2] = {
    8801           5 :       {"", ""}, {"function f() {", "}"}, {nullptr, nullptr}};
    8802             :   // clang-format off
    8803             :   const char* error_data[] = {
    8804             :     "for (let x = {} in null);",
    8805             :     "for (let x = {} of null);",
    8806           5 :     nullptr};
    8807             :   // clang-format on
    8808           5 :   RunParserSyncTest(context_data, error_data, kError);
    8809             : 
    8810             :   // clang-format off
    8811             :   const char* success_data[] = {
    8812             :     "for (var x = {} in null);",
    8813           5 :     nullptr};
    8814             :   // clang-format on
    8815           5 :   RunParserSyncTest(context_data, success_data, kSuccess);
    8816           5 : }
    8817             : 
    8818             : 
    8819       28342 : TEST(DestructuringDuplicateParams) {
    8820             :   const char* context_data[][2] = {{"'use strict';", ""},
    8821             :                                    {"function outer() { 'use strict';", "}"},
    8822           5 :                                    {nullptr, nullptr}};
    8823             : 
    8824             : 
    8825             :   // clang-format off
    8826             :   const char* error_data[] = {
    8827             :     "function f(x,x){}",
    8828             :     "function f(x, {x : x}){}",
    8829             :     "function f(x, {x}){}",
    8830             :     "function f({x,x}) {}",
    8831             :     "function f([x,x]) {}",
    8832             :     "function f(x, [y,{z:x}]) {}",
    8833             :     "function f([x,{y:x}]) {}",
    8834             :     // non-simple parameter list causes duplicates to be errors in sloppy mode.
    8835             :     "function f(x, x, {a}) {}",
    8836           5 :     nullptr};
    8837             :   // clang-format on
    8838           5 :   RunParserSyncTest(context_data, error_data, kError);
    8839           5 : }
    8840             : 
    8841             : 
    8842       28342 : TEST(DestructuringDuplicateParamsSloppy) {
    8843             :   const char* context_data[][2] = {
    8844           5 :       {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
    8845             : 
    8846             : 
    8847             :   // clang-format off
    8848             :   const char* error_data[] = {
    8849             :     // non-simple parameter list causes duplicates to be errors in sloppy mode.
    8850             :     "function f(x, {x : x}){}",
    8851             :     "function f(x, {x}){}",
    8852             :     "function f({x,x}) {}",
    8853             :     "function f(x, x, {a}) {}",
    8854           5 :     nullptr};
    8855             :   // clang-format on
    8856           5 :   RunParserSyncTest(context_data, error_data, kError);
    8857           5 : }
    8858             : 
    8859             : 
    8860       28342 : TEST(DestructuringDisallowPatternsInSingleParamArrows) {
    8861             :   const char* context_data[][2] = {{"'use strict';", ""},
    8862             :                                    {"function outer() { 'use strict';", "}"},
    8863             :                                    {"", ""},
    8864             :                                    {"function outer() { ", "}"},
    8865           5 :                                    {nullptr, nullptr}};
    8866             : 
    8867             :   // clang-format off
    8868             :   const char* error_data[] = {
    8869             :     "var f = {x} => {};",
    8870             :     "var f = {x,y} => {};",
    8871           5 :     nullptr};
    8872             :   // clang-format on
    8873           5 :   RunParserSyncTest(context_data, error_data, kError);
    8874           5 : }
    8875             : 
    8876             : 
    8877       28342 : TEST(DefaultParametersYieldInInitializers) {
    8878             :   // clang-format off
    8879             :   const char* sloppy_function_context_data[][2] = {
    8880             :     {"(function f(", ") { });"},
    8881             :     {nullptr, nullptr}
    8882           5 :   };
    8883             : 
    8884             :   const char* strict_function_context_data[][2] = {
    8885             :     {"'use strict'; (function f(", ") { });"},
    8886             :     {nullptr, nullptr}
    8887           5 :   };
    8888             : 
    8889             :   const char* sloppy_arrow_context_data[][2] = {
    8890             :     {"((", ")=>{});"},
    8891             :     {nullptr, nullptr}
    8892           5 :   };
    8893             : 
    8894             :   const char* strict_arrow_context_data[][2] = {
    8895             :     {"'use strict'; ((", ")=>{});"},
    8896             :     {nullptr, nullptr}
    8897           5 :   };
    8898             : 
    8899             :   const char* generator_context_data[][2] = {
    8900             :     {"'use strict'; (function *g(", ") { });"},
    8901             :     {"(function *g(", ") { });"},
    8902             :     // Arrow function within generator has the same rules.
    8903             :     {"'use strict'; (function *g() { (", ") => {} });"},
    8904             :     {"(function *g() { (", ") => {} });"},
    8905             :     // And similarly for arrow functions in the parameter list.
    8906             :     {"'use strict'; (function *g(z = (", ") => {}) { });"},
    8907             :     {"(function *g(z = (", ") => {}) { });"},
    8908             :     {nullptr, nullptr}
    8909           5 :   };
    8910             : 
    8911             :   const char* parameter_data[] = {
    8912             :     "x=yield",
    8913             :     "x, y=yield",
    8914             :     "{x=yield}",
    8915             :     "[x=yield]",
    8916             : 
    8917             :     "x=(yield)",
    8918             :     "x, y=(yield)",
    8919             :     "{x=(yield)}",
    8920             :     "[x=(yield)]",
    8921             : 
    8922             :     "x=f(yield)",
    8923             :     "x, y=f(yield)",
    8924             :     "{x=f(yield)}",
    8925             :     "[x=f(yield)]",
    8926             : 
    8927             :     "{x}=yield",
    8928             :     "[x]=yield",
    8929             : 
    8930             :     "{x}=(yield)",
    8931             :     "[x]=(yield)",
    8932             : 
    8933             :     "{x}=f(yield)",
    8934             :     "[x]=f(yield)",
    8935             :     nullptr
    8936           5 :   };
    8937             : 
    8938             :   // Because classes are always in strict mode, these are always errors.
    8939             :   const char* always_error_param_data[] = {
    8940             :     "x = class extends (yield) { }",
    8941             :     "x = class extends f(yield) { }",
    8942             :     "x = class extends (null, yield) { }",
    8943             :     "x = class extends (a ? null : yield) { }",
    8944             :     "[x] = [class extends (a ? null : yield) { }]",
    8945             :     "[x = class extends (a ? null : yield) { }]",
    8946             :     "[x = class extends (a ? null : yield) { }] = [null]",
    8947             :     "x = class { [yield]() { } }",
    8948             :     "x = class { static [yield]() { } }",
    8949             :     "x = class { [(yield, 1)]() { } }",
    8950             :     "x = class { [y = (yield, 1)]() { } }",
    8951             :     nullptr
    8952           5 :   };
    8953             :   // clang-format on
    8954             : 
    8955           5 :   RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
    8956           5 :   RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
    8957             : 
    8958           5 :   RunParserSyncTest(strict_function_context_data, parameter_data, kError);
    8959           5 :   RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
    8960             : 
    8961           5 :   RunParserSyncTest(generator_context_data, parameter_data, kError);
    8962           5 :   RunParserSyncTest(generator_context_data, always_error_param_data, kError);
    8963           5 : }
    8964             : 
    8965       28342 : TEST(SpreadArray) {
    8966             :   const char* context_data[][2] = {
    8967           5 :       {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
    8968             : 
    8969             :   // clang-format off
    8970             :   const char* data[] = {
    8971             :     "[...a]",
    8972             :     "[a, ...b]",
    8973             :     "[...a,]",
    8974             :     "[...a, ,]",
    8975             :     "[, ...a]",
    8976             :     "[...a, ...b]",
    8977             :     "[...a, , ...b]",
    8978             :     "[...[...a]]",
    8979             :     "[, ...a]",
    8980             :     "[, , ...a]",
    8981           5 :     nullptr};
    8982             :   // clang-format on
    8983           5 :   RunParserSyncTest(context_data, data, kSuccess);
    8984           5 : }
    8985             : 
    8986             : 
    8987       28342 : TEST(SpreadArrayError) {
    8988             :   const char* context_data[][2] = {
    8989           5 :       {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
    8990             : 
    8991             :   // clang-format off
    8992             :   const char* data[] = {
    8993             :     "[...]",
    8994             :     "[a, ...]",
    8995             :     "[..., ]",
    8996             :     "[..., ...]",
    8997             :     "[ (...a)]",
    8998           5 :     nullptr};
    8999             :   // clang-format on
    9000           5 :   RunParserSyncTest(context_data, data, kError);
    9001           5 : }
    9002             : 
    9003             : 
    9004       28342 : TEST(NewTarget) {
    9005             :   // clang-format off
    9006             :   const char* good_context_data[][2] = {
    9007             :     {"function f() {", "}"},
    9008             :     {"'use strict'; function f() {", "}"},
    9009             :     {"var f = function() {", "}"},
    9010             :     {"'use strict'; var f = function() {", "}"},
    9011             :     {"({m: function() {", "}})"},
    9012             :     {"'use strict'; ({m: function() {", "}})"},
    9013             :     {"({m() {", "}})"},
    9014             :     {"'use strict'; ({m() {", "}})"},
    9015             :     {"({get x() {", "}})"},
    9016             :     {"'use strict'; ({get x() {", "}})"},
    9017             :     {"({set x(_) {", "}})"},
    9018             :     {"'use strict'; ({set x(_) {", "}})"},
    9019             :     {"class C {m() {", "}}"},
    9020             :     {"class C {get x() {", "}}"},
    9021             :     {"class C {set x(_) {", "}}"},
    9022             :     {nullptr}
    9023           5 :   };
    9024             : 
    9025             :   const char* bad_context_data[][2] = {
    9026             :     {"", ""},
    9027             :     {"'use strict';", ""},
    9028             :     {nullptr}
    9029           5 :   };
    9030             : 
    9031             :   const char* data[] = {
    9032             :     "new.target",
    9033             :     "{ new.target }",
    9034             :     "() => { new.target }",
    9035             :     "() => new.target",
    9036             :     "if (1) { new.target }",
    9037             :     "if (1) {} else { new.target }",
    9038             :     "while (0) { new.target }",
    9039             :     "do { new.target } while (0)",
    9040             :     nullptr
    9041           5 :   };
    9042             : 
    9043             :   // clang-format on
    9044             : 
    9045           5 :   RunParserSyncTest(good_context_data, data, kSuccess);
    9046           5 :   RunParserSyncTest(bad_context_data, data, kError);
    9047           5 : }
    9048             : 
    9049       28342 : TEST(ImportMetaSuccess) {
    9050             :   // clang-format off
    9051             :   const char* context_data[][2] = {
    9052             :     {"", ""},
    9053             :     {"'use strict';", ""},
    9054             :     {"function f() {", "}"},
    9055             :     {"'use strict'; function f() {", "}"},
    9056             :     {"var f = function() {", "}"},
    9057             :     {"'use strict'; var f = function() {", "}"},
    9058             :     {"({m: function() {", "}})"},
    9059             :     {"'use strict'; ({m: function() {", "}})"},
    9060             :     {"({m() {", "}})"},
    9061             :     {"'use strict'; ({m() {", "}})"},
    9062             :     {"({get x() {", "}})"},
    9063             :     {"'use strict'; ({get x() {", "}})"},
    9064             :     {"({set x(_) {", "}})"},
    9065             :     {"'use strict'; ({set x(_) {", "}})"},
    9066             :     {"class C {m() {", "}}"},
    9067             :     {"class C {get x() {", "}}"},
    9068             :     {"class C {set x(_) {", "}}"},
    9069             :     {nullptr}
    9070           5 :   };
    9071             : 
    9072             :   const char* data[] = {
    9073             :     "import.meta",
    9074             :     "() => { import.meta }",
    9075             :     "() => import.meta",
    9076             :     "if (1) { import.meta }",
    9077             :     "if (1) {} else { import.meta }",
    9078             :     "while (0) { import.meta }",
    9079             :     "do { import.meta } while (0)",
    9080             :     "import.meta.url",
    9081             :     "import.meta[0]",
    9082             :     "import.meta.couldBeMutable = true",
    9083             :     "import.meta()",
    9084             :     "new import.meta.MagicClass",
    9085             :     "new import.meta",
    9086             :     "t = [...import.meta]",
    9087             :     "f = {...import.meta}",
    9088             :     "delete import.meta",
    9089             :     nullptr
    9090           5 :   };
    9091             : 
    9092             :   // clang-format on
    9093             : 
    9094             :   // Making sure the same *wouldn't* parse without the flags
    9095             :   RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
    9096             :                           nullptr, 0, true, true);
    9097             : 
    9098             :   static const ParserFlag flags[] = {
    9099             :       kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
    9100             :   };
    9101             :   // 2.1.1 Static Semantics: Early Errors
    9102             :   // ImportMeta
    9103             :   // * It is an early Syntax Error if Module is not the syntactic goal symbol.
    9104             :   RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    9105           5 :                     arraysize(flags));
    9106             :   // Making sure the same wouldn't parse without the flags either
    9107           5 :   RunParserSyncTest(context_data, data, kError);
    9108             : 
    9109             :   RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
    9110             :                           arraysize(flags));
    9111           5 : }
    9112             : 
    9113       28342 : TEST(ImportMetaFailure) {
    9114             :   // clang-format off
    9115             :   const char* context_data[][2] = {
    9116             :     {"var ", ""},
    9117             :     {"let ", ""},
    9118             :     {"const ", ""},
    9119             :     {"var [", "] = [1]"},
    9120             :     {"([", "] = [1])"},
    9121             :     {"({", "} = {1})"},
    9122             :     {"var {", " = 1} = 1"},
    9123             :     {"for (var ", " of [1]) {}"},
    9124             :     {"(", ") => {}"},
    9125             :     {"let f = ", " => {}"},
    9126             :     {nullptr}
    9127           5 :   };
    9128             : 
    9129             :   const char* data[] = {
    9130             :     "import.meta",
    9131             :     nullptr
    9132           5 :   };
    9133             : 
    9134             :   // clang-format on
    9135             : 
    9136             :   static const ParserFlag flags[] = {
    9137             :       kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
    9138             :   };
    9139             : 
    9140             :   RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    9141           5 :                     arraysize(flags));
    9142             :   RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
    9143             :                           arraysize(flags));
    9144             : 
    9145             :   RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
    9146             :                           nullptr, 0, true, true);
    9147           5 :   RunParserSyncTest(context_data, data, kError);
    9148           5 : }
    9149             : 
    9150       28342 : TEST(ConstSloppy) {
    9151             :   // clang-format off
    9152             :   const char* context_data[][2] = {
    9153             :     {"", ""},
    9154             :     {"{", "}"},
    9155             :     {nullptr, nullptr}
    9156           5 :   };
    9157             : 
    9158             :   const char* data[] = {
    9159             :     "const x = 1",
    9160             :     "for (const x = 1; x < 1; x++) {}",
    9161             :     "for (const x in {}) {}",
    9162             :     "for (const x of []) {}",
    9163             :     nullptr
    9164           5 :   };
    9165             :   // clang-format on
    9166           5 :   RunParserSyncTest(context_data, data, kSuccess);
    9167           5 : }
    9168             : 
    9169             : 
    9170       28342 : TEST(LetSloppy) {
    9171             :   // clang-format off
    9172             :   const char* context_data[][2] = {
    9173             :     {"", ""},
    9174             :     {"'use strict';", ""},
    9175             :     {"{", "}"},
    9176             :     {nullptr, nullptr}
    9177           5 :   };
    9178             : 
    9179             :   const char* data[] = {
    9180             :     "let x",
    9181             :     "let x = 1",
    9182             :     "for (let x = 1; x < 1; x++) {}",
    9183             :     "for (let x in {}) {}",
    9184             :     "for (let x of []) {}",
    9185             :     nullptr
    9186           5 :   };
    9187             :   // clang-format on
    9188             : 
    9189           5 :   RunParserSyncTest(context_data, data, kSuccess);
    9190           5 : }
    9191             : 
    9192             : 
    9193       28342 : TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
    9194             :   // TC39 deemed "use strict" directives to be an error when occurring in the
    9195             :   // body of a function with non-simple parameter list, on 29/7/2015.
    9196             :   // https://goo.gl/ueA7Ln
    9197             :   const char* context_data[][2] = {
    9198             :       {"function f(", ") { 'use strict'; }"},
    9199             :       {"function* g(", ") { 'use strict'; }"},
    9200             :       {"class c { foo(", ") { 'use strict' }"},
    9201             :       {"var a = (", ") => { 'use strict'; }"},
    9202             :       {"var o = { m(", ") { 'use strict'; }"},
    9203             :       {"var o = { *gm(", ") { 'use strict'; }"},
    9204             :       {"var c = { m(", ") { 'use strict'; }"},
    9205             :       {"var c = { *gm(", ") { 'use strict'; }"},
    9206             : 
    9207             :       {"'use strict'; function f(", ") { 'use strict'; }"},
    9208             :       {"'use strict'; function* g(", ") { 'use strict'; }"},
    9209             :       {"'use strict'; class c { foo(", ") { 'use strict' }"},
    9210             :       {"'use strict'; var a = (", ") => { 'use strict'; }"},
    9211             :       {"'use strict'; var o = { m(", ") { 'use strict'; }"},
    9212             :       {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
    9213             :       {"'use strict'; var c = { m(", ") { 'use strict'; }"},
    9214             :       {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
    9215             : 
    9216           5 :       {nullptr, nullptr}};
    9217             : 
    9218             :   const char* data[] = {
    9219             :       // TODO(@caitp): support formal parameter initializers
    9220             :       "{}",
    9221             :       "[]",
    9222             :       "[{}]",
    9223             :       "{a}",
    9224             :       "a, {b}",
    9225             :       "a, b, {c, d, e}",
    9226             :       "initializer = true",
    9227             :       "a, b, c = 1",
    9228             :       "...args",
    9229             :       "a, b, ...rest",
    9230             :       "[a, b, ...rest]",
    9231             :       "{ bindingPattern = {} }",
    9232             :       "{ initializedBindingPattern } = { initializedBindingPattern: true }",
    9233           5 :       nullptr};
    9234             : 
    9235           5 :   RunParserSyncTest(context_data, data, kError);
    9236           5 : }
    9237             : 
    9238             : 
    9239       28342 : TEST(LetSloppyOnly) {
    9240             :   // clang-format off
    9241             :   const char* context_data[][2] = {
    9242             :     {"", ""},
    9243             :     {"{", "}"},
    9244             :     {"(function() {", "})()"},
    9245             :     {nullptr, nullptr}
    9246           5 :   };
    9247             : 
    9248             :   const char* data[] = {
    9249             :     "let",
    9250             :     "let = 1",
    9251             :     "for (let = 1; let < 1; let++) {}",
    9252             :     "for (let in {}) {}",
    9253             :     "for (var let = 1; let < 1; let++) {}",
    9254             :     "for (var let in {}) {}",
    9255             :     "for (var [let] = 1; let < 1; let++) {}",
    9256             :     "for (var [let] in {}) {}",
    9257             :     "var let",
    9258             :     "var [let] = []",
    9259             :     nullptr
    9260           5 :   };
    9261             :   // clang-format on
    9262             : 
    9263           5 :   RunParserSyncTest(context_data, data, kSuccess);
    9264             : 
    9265             :   // Some things should be rejected even in sloppy mode
    9266             :   // This addresses BUG(v8:4403).
    9267             : 
    9268             :   // clang-format off
    9269             :   const char* fail_data[] = {
    9270             :     "let let = 1",
    9271             :     "for (let let = 1; let < 1; let++) {}",
    9272             :     "for (let let in {}) {}",
    9273             :     "for (let let of []) {}",
    9274             :     "const let = 1",
    9275             :     "for (const let = 1; let < 1; let++) {}",
    9276             :     "for (const let in {}) {}",
    9277             :     "for (const let of []) {}",
    9278             :     "let [let] = 1",
    9279             :     "for (let [let] = 1; let < 1; let++) {}",
    9280             :     "for (let [let] in {}) {}",
    9281             :     "for (let [let] of []) {}",
    9282             :     "const [let] = 1",
    9283             :     "for (const [let] = 1; let < 1; let++) {}",
    9284             :     "for (const [let] in {}) {}",
    9285             :     "for (const [let] of []) {}",
    9286             : 
    9287             :     // Sprinkle in the escaped version too.
    9288             :     "let l\\u0065t = 1",
    9289             :     "const l\\u0065t = 1",
    9290             :     "let [l\\u0065t] = 1",
    9291             :     "const [l\\u0065t] = 1",
    9292             :     "for (let l\\u0065t in {}) {}",
    9293             :     nullptr
    9294           5 :   };
    9295             :   // clang-format on
    9296             : 
    9297           5 :   RunParserSyncTest(context_data, fail_data, kError);
    9298           5 : }
    9299             : 
    9300             : 
    9301       28342 : TEST(EscapedKeywords) {
    9302             :   // clang-format off
    9303             :   const char* sloppy_context_data[][2] = {
    9304             :     {"", ""},
    9305             :     {nullptr, nullptr}
    9306           5 :   };
    9307             : 
    9308             :   const char* strict_context_data[][2] = {
    9309             :     {"'use strict';", ""},
    9310             :     {nullptr, nullptr}
    9311           5 :   };
    9312             : 
    9313             :   const char* fail_data[] = {
    9314             :     "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
    9315             :     "cl\\u0061ss Foo {}",
    9316             :     "var x = cl\\u0061ss {}",
    9317             :     "\\u0063onst foo = 1;",
    9318             :     "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
    9319             :     "d\\u0065bugger;",
    9320             :     "d\\u0065lete this.a;",
    9321             :     "\\u0063o { } while(0)",
    9322             :     "if (d\\u006f { true }) {}",
    9323             :     "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
    9324             :     "e\\u0078port var foo;",
    9325             :     "try { } catch (e) {} f\\u0069nally { }",
    9326             :     "f\\u006fr (var i = 0; i < 10; ++i);",
    9327             :     "f\\u0075nction fn() {}",
    9328             :     "var f = f\\u0075nction() {}",
    9329             :     "\\u0069f (true) { }",
    9330             :     "\\u0069mport blah from './foo.js';",
    9331             :     "n\\u0065w function f() {}",
    9332             :     "(function() { r\\u0065turn; })()",
    9333             :     "class C extends function() {} { constructor() { sup\\u0065r() } }",
    9334             :     "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
    9335             :     "sw\\u0069tch (this.a) {}",
    9336             :     "var x = th\\u0069s;",
    9337             :     "th\\u0069s.a = 1;",
    9338             :     "thr\\u006fw 'boo';",
    9339             :     "t\\u0072y { true } catch (e) {}",
    9340             :     "var x = typ\\u0065of 'blah'",
    9341             :     "v\\u0061r a = true",
    9342             :     "var v\\u0061r = true",
    9343             :     "(function() { return v\\u006fid 0; })()",
    9344             :     "wh\\u0069le (true) { }",
    9345             :     "w\\u0069th (this.scope) { }",
    9346             :     "(function*() { y\\u0069eld 1; })()",
    9347             :     "(function*() { var y\\u0069eld = 1; })()",
    9348             : 
    9349             :     "var \\u0065num = 1;",
    9350             :     "var { \\u0065num } = {}",
    9351             :     "(\\u0065num = 1);",
    9352             : 
    9353             :     // Null / Boolean literals
    9354             :     "(x === n\\u0075ll);",
    9355             :     "var x = n\\u0075ll;",
    9356             :     "var n\\u0075ll = 1;",
    9357             :     "var { n\\u0075ll } = { 1 };",
    9358             :     "n\\u0075ll = 1;",
    9359             :     "(x === tr\\u0075e);",
    9360             :     "var x = tr\\u0075e;",
    9361             :     "var tr\\u0075e = 1;",
    9362             :     "var { tr\\u0075e } = {};",
    9363             :     "tr\\u0075e = 1;",
    9364             :     "(x === f\\u0061lse);",
    9365             :     "var x = f\\u0061lse;",
    9366             :     "var f\\u0061lse = 1;",
    9367             :     "var { f\\u0061lse } = {};",
    9368             :     "f\\u0061lse = 1;",
    9369             : 
    9370             :     // TODO(caitp): consistent error messages for labeled statements and
    9371             :     // expressions
    9372             :     "switch (this.a) { c\\u0061se 6: break; }",
    9373             :     "try { } c\\u0061tch (e) {}",
    9374             :     "switch (this.a) { d\\u0065fault: break; }",
    9375             :     "class C \\u0065xtends function B() {} {}",
    9376             :     "for (var a i\\u006e this) {}",
    9377             :     "if ('foo' \\u0069n this) {}",
    9378             :     "if (this \\u0069nstanceof Array) {}",
    9379             :     "(n\\u0065w function f() {})",
    9380             :     "(typ\\u0065of 123)",
    9381             :     "(v\\u006fid 0)",
    9382             :     "do { ; } wh\\u0069le (true) { }",
    9383             :     "(function*() { return (n++, y\\u0069eld 1); })()",
    9384             :     "class C { st\\u0061tic bar() {} }",
    9385             :     "class C { st\\u0061tic *bar() {} }",
    9386             :     "class C { st\\u0061tic get bar() {} }",
    9387             :     "class C { st\\u0061tic set bar() {} }",
    9388             : 
    9389             :     // TODO(adamk): These should not be errors in sloppy mode.
    9390             :     "(y\\u0069eld);",
    9391             :     "var y\\u0069eld = 1;",
    9392             :     "var { y\\u0069eld } = {};",
    9393             :     nullptr
    9394           5 :   };
    9395             :   // clang-format on
    9396             : 
    9397           5 :   RunParserSyncTest(sloppy_context_data, fail_data, kError);
    9398           5 :   RunParserSyncTest(strict_context_data, fail_data, kError);
    9399             :   RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
    9400             : 
    9401             :   // clang-format off
    9402             :   const char* let_data[] = {
    9403             :     "var l\\u0065t = 1;",
    9404             :     "l\\u0065t = 1;",
    9405             :     "(l\\u0065t === 1);",
    9406             :     nullptr
    9407           5 :   };
    9408             :   // clang-format on
    9409             : 
    9410           5 :   RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
    9411           5 :   RunParserSyncTest(strict_context_data, let_data, kError);
    9412             : 
    9413             :   // Non-errors in sloppy mode
    9414             :   const char* valid_data[] = {"(\\u0069mplements = 1);",
    9415             :                               "var impl\\u0065ments = 1;",
    9416             :                               "var { impl\\u0065ments  } = {};",
    9417             :                               "(\\u0069nterface = 1);",
    9418             :                               "var int\\u0065rface = 1;",
    9419             :                               "var { int\\u0065rface  } = {};",
    9420             :                               "(p\\u0061ckage = 1);",
    9421             :                               "var packa\\u0067e = 1;",
    9422             :                               "var { packa\\u0067e  } = {};",
    9423             :                               "(p\\u0072ivate = 1);",
    9424             :                               "var p\\u0072ivate;",
    9425             :                               "var { p\\u0072ivate } = {};",
    9426             :                               "(prot\\u0065cted);",
    9427             :                               "var prot\\u0065cted = 1;",
    9428             :                               "var { prot\\u0065cted  } = {};",
    9429             :                               "(publ\\u0069c);",
    9430             :                               "var publ\\u0069c = 1;",
    9431             :                               "var { publ\\u0069c } = {};",
    9432             :                               "(st\\u0061tic);",
    9433             :                               "var st\\u0061tic = 1;",
    9434             :                               "var { st\\u0061tic } = {};",
    9435           5 :                               nullptr};
    9436           5 :   RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
    9437           5 :   RunParserSyncTest(strict_context_data, valid_data, kError);
    9438             :   RunModuleParserSyncTest(strict_context_data, valid_data, kError);
    9439           5 : }
    9440             : 
    9441             : 
    9442       28342 : TEST(MiscSyntaxErrors) {
    9443             :   // clang-format off
    9444             :   const char* context_data[][2] = {
    9445             :     { "'use strict'", "" },
    9446             :     { "", "" },
    9447             :     { nullptr, nullptr }
    9448           5 :   };
    9449             :   const char* error_data[] = {
    9450             :     "for (();;) {}",
    9451             : 
    9452             :     // crbug.com/582626
    9453             :     "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
    9454             :     nullptr
    9455           5 :   };
    9456             :   // clang-format on
    9457             : 
    9458           5 :   RunParserSyncTest(context_data, error_data, kError);
    9459           5 : }
    9460             : 
    9461             : 
    9462       28342 : TEST(EscapeSequenceErrors) {
    9463             :   // clang-format off
    9464             :   const char* context_data[][2] = {
    9465             :     { "'", "'" },
    9466             :     { "\"", "\"" },
    9467             :     { "`", "`" },
    9468             :     { "`${'", "'}`" },
    9469             :     { "`${\"", "\"}`" },
    9470             :     { "`${`", "`}`" },
    9471             :     { nullptr, nullptr }
    9472           5 :   };
    9473             :   const char* error_data[] = {
    9474             :     "\\uABCG",
    9475             :     "\\u{ZZ}",
    9476             :     "\\u{FFZ}",
    9477             :     "\\u{FFFFFFFFFF }",
    9478             :     "\\u{110000}",
    9479             :     "\\u{110000",
    9480             :     "\\u{FFFD }",
    9481             :     "\\xZF",
    9482             :     nullptr
    9483           5 :   };
    9484             :   // clang-format on
    9485             : 
    9486           5 :   RunParserSyncTest(context_data, error_data, kError);
    9487           5 : }
    9488             : 
    9489       28342 : TEST(NewTargetErrors) {
    9490             :   // clang-format off
    9491             :   const char* context_data[][2] = {
    9492             :     { "'use strict'", "" },
    9493             :     { "", "" },
    9494             :     { nullptr, nullptr }
    9495           5 :   };
    9496             :   const char* error_data[] = {
    9497             :     "var x = new.target",
    9498             :     "function f() { return new.t\\u0061rget; }",
    9499             :     nullptr
    9500           5 :   };
    9501             :   // clang-format on
    9502           5 :   RunParserSyncTest(context_data, error_data, kError);
    9503           5 : }
    9504             : 
    9505       28342 : TEST(FunctionDeclarationError) {
    9506             :   // clang-format off
    9507             :   const char* strict_context[][2] = {
    9508             :     { "'use strict';", "" },
    9509             :     { "'use strict'; { ", "}" },
    9510             :     {"(function() { 'use strict';", "})()"},
    9511             :     {"(function() { 'use strict'; {", "} })()"},
    9512             :     { nullptr, nullptr }
    9513           5 :   };
    9514             :   const char* sloppy_context[][2] = {
    9515             :     { "", "" },
    9516             :     { "{", "}" },
    9517             :     {"(function() {", "})()"},
    9518             :     {"(function() { {", "} })()"},
    9519             :     { nullptr, nullptr }
    9520           5 :   };
    9521             :   // Invalid in all contexts
    9522             :   const char* error_data[] = {
    9523             :     "try function foo() {} catch (e) {}",
    9524             :     "do function foo() {} while (0);",
    9525             :     "for (;false;) function foo() {}",
    9526             :     "for (var i = 0; i < 1; i++) function f() { };",
    9527             :     "for (var x in {a: 1}) function f() { };",
    9528             :     "for (var x in {}) function f() { };",
    9529             :     "for (var x in {}) function foo() {}",
    9530             :     "for (x in {a: 1}) function f() { };",
    9531             :     "for (x in {}) function f() { };",
    9532             :     "var x; for (x in {}) function foo() {}",
    9533             :     "with ({}) function f() { };",
    9534             :     "do label: function foo() {} while (0);",
    9535             :     "for (;false;) label: function foo() {}",
    9536             :     "for (var i = 0; i < 1; i++) label: function f() { };",
    9537             :     "for (var x in {a: 1}) label: function f() { };",
    9538             :     "for (var x in {}) label: function f() { };",
    9539             :     "for (var x in {}) label: function foo() {}",
    9540             :     "for (x in {a: 1}) label: function f() { };",
    9541             :     "for (x in {}) label: function f() { };",
    9542             :     "var x; for (x in {}) label: function foo() {}",
    9543             :     "with ({}) label: function f() { };",
    9544             :     "if (true) label: function f() {}",
    9545             :     "if (true) {} else label: function f() {}",
    9546             :     "if (true) function* f() { }",
    9547             :     "label: function* f() { }",
    9548             :     "if (true) async function f() { }",
    9549             :     "label: async function f() { }",
    9550             :     "if (true) async function* f() { }",
    9551             :     "label: async function* f() { }",
    9552             :     nullptr
    9553           5 :   };
    9554             :   // Valid only in sloppy mode.
    9555             :   const char* sloppy_data[] = {
    9556             :     "if (true) function foo() {}",
    9557             :     "if (false) {} else function f() { };",
    9558             :     "label: function f() { }",
    9559             :     "label: if (true) function f() { }",
    9560             :     "label: if (true) {} else function f() { }",
    9561             :     "label: label2: function f() { }",
    9562             :     nullptr
    9563           5 :   };
    9564             :   // clang-format on
    9565             : 
    9566             :   // Nothing parses in strict mode without a SyntaxError
    9567           5 :   RunParserSyncTest(strict_context, error_data, kError);
    9568           5 :   RunParserSyncTest(strict_context, sloppy_data, kError);
    9569             : 
    9570             :   // In sloppy mode, sloppy_data is successful
    9571           5 :   RunParserSyncTest(sloppy_context, error_data, kError);
    9572           5 :   RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
    9573           5 : }
    9574             : 
    9575       28342 : TEST(ExponentiationOperator) {
    9576             :   // clang-format off
    9577             :   const char* context_data[][2] = {
    9578             :     { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
    9579             :     { "var O = { p: 1 }, x = 10; ; (", ")" },
    9580             :     { "var O = { p: 1 }, x = 10; foo(", ")" },
    9581             :     { nullptr, nullptr }
    9582           5 :   };
    9583             :   const char* data[] = {
    9584             :     "(delete O.p) ** 10",
    9585             :     "(delete x) ** 10",
    9586             :     "(~O.p) ** 10",
    9587             :     "(~x) ** 10",
    9588             :     "(!O.p) ** 10",
    9589             :     "(!x) ** 10",
    9590             :     "(+O.p) ** 10",
    9591             :     "(+x) ** 10",
    9592             :     "(-O.p) ** 10",
    9593             :     "(-x) ** 10",
    9594             :     "(typeof O.p) ** 10",
    9595             :     "(typeof x) ** 10",
    9596             :     "(void 0) ** 10",
    9597             :     "(void O.p) ** 10",
    9598             :     "(void x) ** 10",
    9599             :     "++O.p ** 10",
    9600             :     "++x ** 10",
    9601             :     "--O.p ** 10",
    9602             :     "--x ** 10",
    9603             :     "O.p++ ** 10",
    9604             :     "x++ ** 10",
    9605             :     "O.p-- ** 10",
    9606             :     "x-- ** 10",
    9607             :     nullptr
    9608           5 :   };
    9609             :   // clang-format on
    9610             : 
    9611           5 :   RunParserSyncTest(context_data, data, kSuccess);
    9612           5 : }
    9613             : 
    9614       28342 : TEST(ExponentiationOperatorErrors) {
    9615             :   // clang-format off
    9616             :   const char* context_data[][2] = {
    9617             :     { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
    9618             :     { "var O = { p: 1 }, x = 10; ; (", ")" },
    9619             :     { "var O = { p: 1 }, x = 10; foo(", ")" },
    9620             :     { nullptr, nullptr }
    9621           5 :   };
    9622             :   const char* error_data[] = {
    9623             :     "delete O.p ** 10",
    9624             :     "delete x ** 10",
    9625             :     "~O.p ** 10",
    9626             :     "~x ** 10",
    9627             :     "!O.p ** 10",
    9628             :     "!x ** 10",
    9629             :     "+O.p ** 10",
    9630             :     "+x ** 10",
    9631             :     "-O.p ** 10",
    9632             :     "-x ** 10",
    9633             :     "typeof O.p ** 10",
    9634             :     "typeof x ** 10",
    9635             :     "void ** 10",
    9636             :     "void O.p ** 10",
    9637             :     "void x ** 10",
    9638             :     "++delete O.p ** 10",
    9639             :     "--delete O.p ** 10",
    9640             :     "++~O.p ** 10",
    9641             :     "++~x ** 10",
    9642             :     "--!O.p ** 10",
    9643             :     "--!x ** 10",
    9644             :     "++-O.p ** 10",
    9645             :     "++-x ** 10",
    9646             :     "--+O.p ** 10",
    9647             :     "--+x ** 10",
    9648             :     "[ x ] **= [ 2 ]",
    9649             :     "[ x **= 2 ] = [ 2 ]",
    9650             :     "{ x } **= { x: 2 }",
    9651             :     "{ x: x **= 2 ] = { x: 2 }",
    9652             :     // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
    9653             :     // "Array() **= 10",
    9654             :     nullptr
    9655           5 :   };
    9656             :   // clang-format on
    9657             : 
    9658           5 :   RunParserSyncTest(context_data, error_data, kError);
    9659           5 : }
    9660             : 
    9661       28342 : TEST(AsyncAwait) {
    9662             :   // clang-format off
    9663             :   const char* context_data[][2] = {
    9664             :     { "'use strict';", "" },
    9665             :     { "", "" },
    9666             :     { nullptr, nullptr }
    9667           5 :   };
    9668             : 
    9669             :   const char* data[] = {
    9670             :     "var asyncFn = async function() { await 1; };",
    9671             :     "var asyncFn = async function withName() { await 1; };",
    9672             :     "var asyncFn = async () => await 'test';",
    9673             :     "var asyncFn = async x => await x + 'test';",
    9674             :     "async function asyncFn() { await 1; }",
    9675             :     "var O = { async method() { await 1; } }",
    9676             :     "var O = { async ['meth' + 'od']() { await 1; } }",
    9677             :     "var O = { async 'method'() { await 1; } }",
    9678             :     "var O = { async 0() { await 1; } }",
    9679             :     "async function await() {}",
    9680             : 
    9681             :     "var asyncFn = async({ foo = 1 }) => foo;",
    9682             :     "var asyncFn = async({ foo = 1 } = {}) => foo;",
    9683             : 
    9684             :     "function* g() { var f = async(yield); }",
    9685             :     "function* g() { var f = async(x = yield); }",
    9686             : 
    9687             :     // v8:7817 assert that `await` is still allowed in the body of an arrow fn
    9688             :     // within formal parameters
    9689             :     "async(a = a => { var await = 1; return 1; }) => a()",
    9690             :     "async(a = await => 1); async(a) => 1",
    9691             :     "(async(a = await => 1), async(a) => 1)",
    9692             :     "async(a = await => 1, b = async() => 1);",
    9693             : 
    9694             :     nullptr
    9695           5 :   };
    9696             :   // clang-format on
    9697             : 
    9698           5 :   RunParserSyncTest(context_data, data, kSuccess);
    9699             : 
    9700             :   // clang-format off
    9701             :   const char* async_body_context_data[][2] = {
    9702             :     { "async function f() {", "}" },
    9703             :     { "var f = async function() {", "}" },
    9704             :     { "var f = async() => {", "}" },
    9705             :     { "var O = { async method() {", "} }" },
    9706             :     { "'use strict'; async function f() {", "}" },
    9707             :     { "'use strict'; var f = async function() {", "}" },
    9708             :     { "'use strict'; var f = async() => {", "}" },
    9709             :     { "'use strict'; var O = { async method() {", "} }" },
    9710             :     { nullptr, nullptr }
    9711           5 :   };
    9712             : 
    9713             :   const char* body_context_data[][2] = {
    9714             :     { "function f() {", "}" },
    9715             :     { "function* g() {", "}" },
    9716             :     { "var f = function() {", "}" },
    9717             :     { "var g = function*() {", "}" },
    9718             :     { "var O = { method() {", "} }" },
    9719             :     { "var O = { *method() {", "} }" },
    9720             :     { "var f = () => {", "}" },
    9721             :     { "'use strict'; function f() {", "}" },
    9722             :     { "'use strict'; function* g() {", "}" },
    9723             :     { "'use strict'; var f = function() {", "}" },
    9724             :     { "'use strict'; var g = function*() {", "}" },
    9725             :     { "'use strict'; var O = { method() {", "} }" },
    9726             :     { "'use strict'; var O = { *method() {", "} }" },
    9727             :     { "'use strict'; var f = () => {", "}" },
    9728             :     { nullptr, nullptr }
    9729           5 :   };
    9730             : 
    9731             :   const char* body_data[] = {
    9732             :     "var async = 1; return async;",
    9733             :     "let async = 1; return async;",
    9734             :     "const async = 1; return async;",
    9735             :     "function async() {} return async();",
    9736             :     "var async = async => async; return async();",
    9737             :     "function foo() { var await = 1; return await; }",
    9738             :     "function foo(await) { return await; }",
    9739             :     "function* foo() { var await = 1; return await; }",
    9740             :     "function* foo(await) { return await; }",
    9741             :     "var f = () => { var await = 1; return await; }",
    9742             :     "var O = { method() { var await = 1; return await; } };",
    9743             :     "var O = { method(await) { return await; } };",
    9744             :     "var O = { *method() { var await = 1; return await; } };",
    9745             :     "var O = { *method(await) { return await; } };",
    9746             :     "var asyncFn = async function*() {}",
    9747             :     "async function* f() {}",
    9748             :     "var O = { async *method() {} };",
    9749             : 
    9750             :     "(function await() {})",
    9751             :     nullptr
    9752           5 :   };
    9753             :   // clang-format on
    9754             : 
    9755           5 :   RunParserSyncTest(async_body_context_data, body_data, kSuccess);
    9756           5 :   RunParserSyncTest(body_context_data, body_data, kSuccess);
    9757           5 : }
    9758             : 
    9759       28342 : TEST(AsyncAwaitErrors) {
    9760             :   // clang-format off
    9761             :   const char* context_data[][2] = {
    9762             :     { "'use strict';", "" },
    9763             :     { "", "" },
    9764             :     { nullptr, nullptr }
    9765           5 :   };
    9766             : 
    9767             :   const char* strict_context_data[][2] = {
    9768             :     { "'use strict';", "" },
    9769             :     { nullptr, nullptr }
    9770           5 :   };
    9771             : 
    9772             :   const char* error_data[] = {
    9773             :     "var asyncFn = async function await() {};",
    9774             :     "var asyncFn = async () => var await = 'test';",
    9775             :     "var asyncFn = async await => await + 'test';",
    9776             :     "var asyncFn = async function(await) {};",
    9777             :     "var asyncFn = async (await) => 'test';",
    9778             :     "async function f(await) {}",
    9779             : 
    9780             :     "var O = { async method(a, a) {} }",
    9781             :     "var O = { async ['meth' + 'od'](a, a) {} }",
    9782             :     "var O = { async 'method'(a, a) {} }",
    9783             :     "var O = { async 0(a, a) {} }",
    9784             : 
    9785             :     "var f = async() => await;",
    9786             : 
    9787             :     "var O = { *async method() {} };",
    9788             :     "var O = { async method*() {} };",
    9789             : 
    9790             :     "var asyncFn = async function(x = await 1) { return x; }",
    9791             :     "async function f(x = await 1) { return x; }",
    9792             :     "var f = async(x = await 1) => x;",
    9793             :     "var O = { async method(x = await 1) { return x; } };",
    9794             : 
    9795             :     "function* g() { var f = async yield => 1; }",
    9796             :     "function* g() { var f = async(yield) => 1; }",
    9797             :     "function* g() { var f = async(x = yield) => 1; }",
    9798             :     "function* g() { var f = async({x = yield}) => 1; }",
    9799             : 
    9800             :     "class C { async constructor() {} }",
    9801             :     "class C {}; class C2 extends C { async constructor() {} }",
    9802             :     "class C { static async prototype() {} }",
    9803             :     "class C {}; class C2 extends C { static async prototype() {} }",
    9804             : 
    9805             :     "var f = async() => ((async(x = await 1) => x)();",
    9806             : 
    9807             :     // Henrique Ferreiro's bug (tm)
    9808             :     "(async function foo1() { } foo2 => 1)",
    9809             :     "(async function foo3() { } () => 1)",
    9810             :     "(async function foo4() { } => 1)",
    9811             :     "(async function() { } foo5 => 1)",
    9812             :     "(async function() { } () => 1)",
    9813             :     "(async function() { } => 1)",
    9814             :     "(async.foo6 => 1)",
    9815             :     "(async.foo7 foo8 => 1)",
    9816             :     "(async.foo9 () => 1)",
    9817             :     "(async().foo10 => 1)",
    9818             :     "(async().foo11 foo12 => 1)",
    9819             :     "(async().foo13 () => 1)",
    9820             :     "(async['foo14'] => 1)",
    9821             :     "(async['foo15'] foo16 => 1)",
    9822             :     "(async['foo17'] () => 1)",
    9823             :     "(async()['foo18'] => 1)",
    9824             :     "(async()['foo19'] foo20 => 1)",
    9825             :     "(async()['foo21'] () => 1)",
    9826             :     "(async`foo22` => 1)",
    9827             :     "(async`foo23` foo24 => 1)",
    9828             :     "(async`foo25` () => 1)",
    9829             :     "(async`foo26`.bar27 => 1)",
    9830             :     "(async`foo28`.bar29 foo30 => 1)",
    9831             :     "(async`foo31`.bar32 () => 1)",
    9832             : 
    9833             :     // v8:5148 assert that errors are still thrown for calls that may have been
    9834             :     // async functions
    9835             :     "async({ foo33 = 1 })",
    9836             : 
    9837             :     "async(...a = b) => b",
    9838             :     "async(...a,) => b",
    9839             :     "async(...a, b) => b",
    9840             : 
    9841             :     // v8:7817 assert that `await` is an invalid identifier in arrow formal
    9842             :     // parameters nested within an async arrow function
    9843             :     "async(a = await => 1) => a",
    9844             :     "async(a = (await) => 1) => a",
    9845             :     "async(a = (...await) => 1) => a",
    9846             :     nullptr
    9847           5 :   };
    9848             : 
    9849             :   const char* strict_error_data[] = {
    9850             :     "var O = { async method(eval) {} }",
    9851             :     "var O = { async ['meth' + 'od'](eval) {} }",
    9852             :     "var O = { async 'method'(eval) {} }",
    9853             :     "var O = { async 0(eval) {} }",
    9854             : 
    9855             :     "var O = { async method(arguments) {} }",
    9856             :     "var O = { async ['meth' + 'od'](arguments) {} }",
    9857             :     "var O = { async 'method'(arguments) {} }",
    9858             :     "var O = { async 0(arguments) {} }",
    9859             : 
    9860             :     "var O = { async method(dupe, dupe) {} }",
    9861             : 
    9862             :     // TODO(caitp): preparser needs to report duplicate parameter errors, too.
    9863             :     // "var f = async(dupe, dupe) => {}",
    9864             : 
    9865             :     nullptr
    9866           5 :   };
    9867             : 
    9868           5 :   RunParserSyncTest(context_data, error_data, kError);
    9869           5 :   RunParserSyncTest(strict_context_data, strict_error_data, kError);
    9870             : 
    9871             :   // clang-format off
    9872             :   const char* async_body_context_data[][2] = {
    9873             :     { "async function f() {", "}" },
    9874             :     { "var f = async function() {", "}" },
    9875             :     { "var f = async() => {", "}" },
    9876             :     { "var O = { async method() {", "} }" },
    9877             :     { "'use strict'; async function f() {", "}" },
    9878             :     { "'use strict'; var f = async function() {", "}" },
    9879             :     { "'use strict'; var f = async() => {", "}" },
    9880             :     { "'use strict'; var O = { async method() {", "} }" },
    9881             :     { nullptr, nullptr }
    9882           5 :   };
    9883             : 
    9884             :   const char* async_body_error_data[] = {
    9885             :     "var await = 1;",
    9886             :     "var { await } = 1;",
    9887             :     "var [ await ] = 1;",
    9888             :     "return async (await) => {};",
    9889             :     "var O = { async [await](a, a) {} }",
    9890             :     "await;",
    9891             : 
    9892             :     "function await() {}",
    9893             : 
    9894             :     "var f = await => 42;",
    9895             :     "var f = (await) => 42;",
    9896             :     "var f = (await, a) => 42;",
    9897             :     "var f = (...await) => 42;",
    9898             : 
    9899             :     "var e = (await);",
    9900             :     "var e = (await, f);",
    9901             :     "var e = (await = 42)",
    9902             : 
    9903             :     "var e = [await];",
    9904             :     "var e = {await};",
    9905             : 
    9906             :     nullptr
    9907           5 :   };
    9908             :   // clang-format on
    9909             : 
    9910           5 :   RunParserSyncTest(async_body_context_data, async_body_error_data, kError);
    9911           5 : }
    9912             : 
    9913       28342 : TEST(Regress7173) {
    9914             :   // Await expression is an invalid destructuring target, and should not crash
    9915             : 
    9916             :   // clang-format off
    9917             :   const char* error_context_data[][2] = {
    9918             :     { "'use strict'; async function f() {", "}" },
    9919             :     { "async function f() {", "}" },
    9920             :     { "'use strict'; function f() {", "}" },
    9921             :     { "function f() {", "}" },
    9922             :     { "let f = async() => {", "}" },
    9923             :     { "let f = () => {", "}" },
    9924             :     { "'use strict'; async function* f() {", "}" },
    9925             :     { "async function* f() {", "}" },
    9926             :     { "'use strict'; function* f() {", "}" },
    9927             :     { "function* f() {", "}" },
    9928             :     { nullptr, nullptr }
    9929           5 :   };
    9930             : 
    9931             :   const char* error_data[] = {
    9932             :     "var [await f] = [];",
    9933             :     "let [await f] = [];",
    9934             :     "const [await f] = [];",
    9935             : 
    9936             :     "var [...await f] = [];",
    9937             :     "let [...await f] = [];",
    9938             :     "const [...await f] = [];",
    9939             : 
    9940             :     "var { await f } = {};",
    9941             :     "let { await f } = {};",
    9942             :     "const { await f } = {};",
    9943             : 
    9944             :     "var { ...await f } = {};",
    9945             :     "let { ...await f } = {};",
    9946             :     "const { ...await f } = {};",
    9947             : 
    9948             :     "var { f: await f } = {};",
    9949             :     "let { f: await f } = {};",
    9950             :     "const { f: await f } = {};"
    9951             : 
    9952             :     "var { f: ...await f } = {};",
    9953             :     "let { f: ...await f } = {};",
    9954             :     "const { f: ...await f } = {};"
    9955             : 
    9956             :     "var { [f]: await f } = {};",
    9957             :     "let { [f]: await f } = {};",
    9958             :     "const { [f]: await f } = {};",
    9959             : 
    9960             :     "var { [f]: ...await f } = {};",
    9961             :     "let { [f]: ...await f } = {};",
    9962             :     "const { [f]: ...await f } = {};",
    9963             : 
    9964             :     nullptr
    9965           5 :   };
    9966             :   // clang-format on
    9967             : 
    9968           5 :   RunParserSyncTest(error_context_data, error_data, kError);
    9969           5 : }
    9970             : 
    9971       28342 : TEST(AsyncAwaitFormalParameters) {
    9972             :   // clang-format off
    9973             :   const char* context_for_formal_parameters[][2] = {
    9974             :     { "async function f(", ") {}" },
    9975             :     { "var f = async function f(", ") {}" },
    9976             :     { "var f = async(", ") => {}" },
    9977             :     { "'use strict'; async function f(", ") {}" },
    9978             :     { "'use strict'; var f = async function f(", ") {}" },
    9979             :     { "'use strict'; var f = async(", ") => {}" },
    9980             :     { nullptr, nullptr }
    9981           5 :   };
    9982             : 
    9983             :   const char* good_formal_parameters[] = {
    9984             :     "x = function await() {}",
    9985             :     "x = function *await() {}",
    9986             :     "x = function() { let await = 0; }",
    9987             :     "x = () => { let await = 0; }",
    9988             :     nullptr
    9989           5 :   };
    9990             : 
    9991             :   const char* bad_formal_parameters[] = {
    9992             :     "{ await }",
    9993             :     "{ await = 1 }",
    9994             :     "{ await } = {}",
    9995             :     "{ await = 1 } = {}",
    9996             :     "[await]",
    9997             :     "[await] = []",
    9998             :     "[await = 1]",
    9999             :     "[await = 1] = []",
   10000             :     "...await",
   10001             :     "await",
   10002             :     "await = 1",
   10003             :     "...[await]",
   10004             :     "x = await",
   10005             : 
   10006             :     // v8:5190
   10007             :     "1) => 1",
   10008             :     "'str') => 1",
   10009             :     "/foo/) => 1",
   10010             :     "{ foo = async(1) => 1 }) => 1",
   10011             :     "{ foo = async(a) => 1 })",
   10012             : 
   10013             :     "x = async(await)",
   10014             :     "x = { [await]: 1 }",
   10015             :     "x = class extends (await) { }",
   10016             :     "x = class { static [await]() {} }",
   10017             :     "{ x = await }",
   10018             : 
   10019             :     // v8:6714
   10020             :     "x = class await {}",
   10021             :     "x = 1 ? class await {} : 0",
   10022             :     "x = async function await() {}",
   10023             : 
   10024             :     "x = y[await]",
   10025             :     "x = `${await}`",
   10026             :     "x = y()[await]",
   10027             : 
   10028             :     nullptr
   10029           5 :   };
   10030             :   // clang-format on
   10031             : 
   10032             :   RunParserSyncTest(context_for_formal_parameters, good_formal_parameters,
   10033           5 :                     kSuccess);
   10034             : 
   10035             :   RunParserSyncTest(context_for_formal_parameters, bad_formal_parameters,
   10036           5 :                     kError);
   10037           5 : }
   10038             : 
   10039       28342 : TEST(AsyncAwaitModule) {
   10040             :   // clang-format off
   10041             :   const char* context_data[][2] = {
   10042             :     { "", "" },
   10043             :     { nullptr, nullptr }
   10044           5 :   };
   10045             : 
   10046             :   const char* data[] = {
   10047             :     "export default async function() { await 1; }",
   10048             :     "export default async function async() { await 1; }",
   10049             :     "export async function async() { await 1; }",
   10050             :     nullptr
   10051           5 :   };
   10052             :   // clang-format on
   10053             : 
   10054             :   RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
   10055             :                           nullptr, 0, false);
   10056           5 : }
   10057             : 
   10058       28342 : TEST(AsyncAwaitModuleErrors) {
   10059             :   // clang-format off
   10060             :   const char* context_data[][2] = {
   10061             :     { "", "" },
   10062             :     { nullptr, nullptr }
   10063           5 :   };
   10064             : 
   10065             :   const char* error_data[] = {
   10066             :     "export default (async function await() {})",
   10067             :     "export default async function await() {}",
   10068             :     "export async function await() {}",
   10069             :     "export async function() {}",
   10070             :     "export async",
   10071             :     "export async\nfunction async() { await 1; }",
   10072             :     nullptr
   10073           5 :   };
   10074             :   // clang-format on
   10075             : 
   10076             :   RunModuleParserSyncTest(context_data, error_data, kError, nullptr, 0, nullptr,
   10077             :                           0, nullptr, 0, false);
   10078           5 : }
   10079             : 
   10080       28342 : TEST(RestrictiveForInErrors) {
   10081             :   // clang-format off
   10082             :   const char* strict_context_data[][2] = {
   10083             :     { "'use strict'", "" },
   10084             :     { nullptr, nullptr }
   10085           5 :   };
   10086             :   const char* sloppy_context_data[][2] = {
   10087             :     { "", "" },
   10088             :     { nullptr, nullptr }
   10089           5 :   };
   10090             :   const char* error_data[] = {
   10091             :     "for (const x = 0 in {});",
   10092             :     "for (let x = 0 in {});",
   10093             :     nullptr
   10094           5 :   };
   10095             :   const char* sloppy_data[] = {
   10096             :     "for (var x = 0 in {});",
   10097             :     nullptr
   10098           5 :   };
   10099             :   // clang-format on
   10100             : 
   10101           5 :   RunParserSyncTest(strict_context_data, error_data, kError);
   10102           5 :   RunParserSyncTest(strict_context_data, sloppy_data, kError);
   10103           5 :   RunParserSyncTest(sloppy_context_data, error_data, kError);
   10104           5 :   RunParserSyncTest(sloppy_context_data, sloppy_data, kSuccess);
   10105           5 : }
   10106             : 
   10107       28342 : TEST(NoDuplicateGeneratorsInBlock) {
   10108             :   const char* block_context_data[][2] = {
   10109             :       {"'use strict'; {", "}"},
   10110             :       {"{", "}"},
   10111             :       {"(function() { {", "} })()"},
   10112             :       {"(function() {'use strict'; {", "} })()"},
   10113           5 :       {nullptr, nullptr}};
   10114             :   const char* top_level_context_data[][2] = {
   10115             :       {"'use strict';", ""},
   10116             :       {"", ""},
   10117             :       {"(function() {", "})()"},
   10118             :       {"(function() {'use strict';", "})()"},
   10119           5 :       {nullptr, nullptr}};
   10120             :   const char* error_data[] = {"function* x() {} function* x() {}",
   10121             :                               "function x() {} function* x() {}",
   10122           5 :                               "function* x() {} function x() {}", nullptr};
   10123             :   // The preparser doesn't enforce the restriction, so turn it off.
   10124             :   bool test_preparser = false;
   10125             :   RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
   10126           5 :                     0, nullptr, 0, false, test_preparser);
   10127           5 :   RunParserSyncTest(top_level_context_data, error_data, kSuccess);
   10128           5 : }
   10129             : 
   10130       28342 : TEST(NoDuplicateAsyncFunctionInBlock) {
   10131             :   const char* block_context_data[][2] = {
   10132             :       {"'use strict'; {", "}"},
   10133             :       {"{", "}"},
   10134             :       {"(function() { {", "} })()"},
   10135             :       {"(function() {'use strict'; {", "} })()"},
   10136           5 :       {nullptr, nullptr}};
   10137             :   const char* top_level_context_data[][2] = {
   10138             :       {"'use strict';", ""},
   10139             :       {"", ""},
   10140             :       {"(function() {", "})()"},
   10141             :       {"(function() {'use strict';", "})()"},
   10142           5 :       {nullptr, nullptr}};
   10143             :   const char* error_data[] = {"async function x() {} async function x() {}",
   10144             :                               "function x() {} async function x() {}",
   10145             :                               "async function x() {} function x() {}",
   10146             :                               "function* x() {} async function x() {}",
   10147             :                               "function* x() {} async function x() {}",
   10148             :                               "async function x() {} function* x() {}",
   10149             :                               "function* x() {} async function x() {}",
   10150           5 :                               nullptr};
   10151             :   // The preparser doesn't enforce the restriction, so turn it off.
   10152             :   bool test_preparser = false;
   10153             :   RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
   10154           5 :                     0, nullptr, 0, false, test_preparser);
   10155           5 :   RunParserSyncTest(top_level_context_data, error_data, kSuccess);
   10156           5 : }
   10157             : 
   10158       28342 : TEST(TrailingCommasInParameters) {
   10159             :   // clang-format off
   10160             :   const char* context_data[][2] = {
   10161             :     { "", "" },
   10162             :     { "'use strict';", "" },
   10163             :     { "function foo() {", "}" },
   10164             :     { "function foo() {'use strict';", "}" },
   10165             :     { nullptr, nullptr }
   10166           5 :   };
   10167             : 
   10168             :   const char* data[] = {
   10169             :     " function  a(b,) {}",
   10170             :     " function* a(b,) {}",
   10171             :     "(function  a(b,) {});",
   10172             :     "(function* a(b,) {});",
   10173             :     "(function   (b,) {});",
   10174             :     "(function*  (b,) {});",
   10175             :     " function  a(b,c,d,) {}",
   10176             :     " function* a(b,c,d,) {}",
   10177             :     "(function  a(b,c,d,) {});",
   10178             :     "(function* a(b,c,d,) {});",
   10179             :     "(function   (b,c,d,) {});",
   10180             :     "(function*  (b,c,d,) {});",
   10181             :     "(b,) => {};",
   10182             :     "(b,c,d,) => {};",
   10183             :     "a(1,);",
   10184             :     "a(1,2,3,);",
   10185             :     "a(...[],);",
   10186             :     "a(1, 2, ...[],);",
   10187             :     "a(...[], 2, ...[],);",
   10188             :     nullptr
   10189           5 :   };
   10190             :   // clang-format on
   10191             : 
   10192           5 :   RunParserSyncTest(context_data, data, kSuccess);
   10193           5 : }
   10194             : 
   10195       28342 : TEST(TrailingCommasInParametersErrors) {
   10196             :   // clang-format off
   10197             :   const char* context_data[][2] = {
   10198             :     { "", "" },
   10199             :     { "'use strict';", "" },
   10200             :     { "function foo() {", "}" },
   10201             :     { "function foo() {'use strict';", "}" },
   10202             :     { nullptr, nullptr }
   10203           5 :   };
   10204             : 
   10205             :   const char* data[] = {
   10206             :     // too many trailing commas
   10207             :     " function  a(b,,) {}",
   10208             :     " function* a(b,,) {}",
   10209             :     "(function  a(b,,) {});",
   10210             :     "(function* a(b,,) {});",
   10211             :     "(function   (b,,) {});",
   10212             :     "(function*  (b,,) {});",
   10213             :     " function  a(b,c,d,,) {}",
   10214             :     " function* a(b,c,d,,) {}",
   10215             :     "(function  a(b,c,d,,) {});",
   10216             :     "(function* a(b,c,d,,) {});",
   10217             :     "(function   (b,c,d,,) {});",
   10218             :     "(function*  (b,c,d,,) {});",
   10219             :     "(b,,) => {};",
   10220             :     "(b,c,d,,) => {};",
   10221             :     "a(1,,);",
   10222             :     "a(1,2,3,,);",
   10223             :     // only a trailing comma and no parameters
   10224             :     " function  a1(,) {}",
   10225             :     " function* a2(,) {}",
   10226             :     "(function  a3(,) {});",
   10227             :     "(function* a4(,) {});",
   10228             :     "(function    (,) {});",
   10229             :     "(function*   (,) {});",
   10230             :     "(,) => {};",
   10231             :     "a1(,);",
   10232             :     // no trailing commas after rest parameter declaration
   10233             :     " function  a(...b,) {}",
   10234             :     " function* a(...b,) {}",
   10235             :     "(function  a(...b,) {});",
   10236             :     "(function* a(...b,) {});",
   10237             :     "(function   (...b,) {});",
   10238             :     "(function*  (...b,) {});",
   10239             :     " function  a(b, c, ...d,) {}",
   10240             :     " function* a(b, c, ...d,) {}",
   10241             :     "(function  a(b, c, ...d,) {});",
   10242             :     "(function* a(b, c, ...d,) {});",
   10243             :     "(function   (b, c, ...d,) {});",
   10244             :     "(function*  (b, c, ...d,) {});",
   10245             :     "(...b,) => {};",
   10246             :     "(b, c, ...d,) => {};",
   10247             :     // parenthesized trailing comma without arrow is still an error
   10248             :     "(,);",
   10249             :     "(a,);",
   10250             :     "(a,b,c,);",
   10251             :     nullptr
   10252           5 :   };
   10253             :   // clang-format on
   10254             : 
   10255           5 :   RunParserSyncTest(context_data, data, kError);
   10256           5 : }
   10257             : 
   10258       28342 : TEST(ArgumentsRedeclaration) {
   10259             :   {
   10260             :     // clang-format off
   10261             :     const char* context_data[][2] = {
   10262             :       { "function f(", ") {}" },
   10263             :       { nullptr, nullptr }
   10264           5 :     };
   10265             :     const char* success_data[] = {
   10266             :       "{arguments}",
   10267             :       "{arguments = false}",
   10268             :       "arg1, arguments",
   10269             :       "arg1, ...arguments",
   10270             :       nullptr
   10271           5 :     };
   10272             :     // clang-format on
   10273           5 :     RunParserSyncTest(context_data, success_data, kSuccess);
   10274             :   }
   10275             : 
   10276             :   {
   10277             :     // clang-format off
   10278             :     const char* context_data[][2] = {
   10279             :       { "function f() {", "}" },
   10280             :       { nullptr, nullptr }
   10281           5 :     };
   10282             :     const char* data[] = {
   10283             :       "const arguments = 1",
   10284             :       "let arguments",
   10285             :       "var arguments",
   10286             :       nullptr
   10287           5 :     };
   10288             :     // clang-format on
   10289           5 :     RunParserSyncTest(context_data, data, kSuccess);
   10290             :   }
   10291           5 : }
   10292             : 
   10293             : 
   10294             : // Test that lazily parsed inner functions don't result in overly pessimistic
   10295             : // context allocations.
   10296       28342 : TEST(NoPessimisticContextAllocation) {
   10297             :   i::Isolate* isolate = CcTest::i_isolate();
   10298             :   i::Factory* factory = isolate->factory();
   10299             :   i::HandleScope scope(isolate);
   10300          10 :   LocalContext env;
   10301             : 
   10302             :   const char* prefix = "(function outer() { var my_var; ";
   10303             :   const char* suffix = " })();";
   10304           5 :   int prefix_len = Utf8LengthHelper(prefix);
   10305           5 :   int suffix_len = Utf8LengthHelper(suffix);
   10306             : 
   10307             :   // Test both normal inner functions and inner arrow functions.
   10308             :   const char* inner_functions[] = {"function inner(%s) { %s }",
   10309           5 :                                    "(%s) => { %s }"};
   10310             : 
   10311             :   struct {
   10312             :     const char* params;
   10313             :     const char* source;
   10314             :     bool ctxt_allocate;
   10315             :   } inners[] = {
   10316             :       // Context allocating because we need to:
   10317             :       {"", "my_var;", true},
   10318             :       {"", "if (true) { let my_var; } my_var;", true},
   10319             :       {"", "eval('foo');", true},
   10320             :       {"", "function inner2() { my_var; }", true},
   10321             :       {"", "function inner2() { eval('foo'); }", true},
   10322             :       {"", "var {my_var : a} = {my_var};", true},
   10323             :       {"", "let {my_var : a} = {my_var};", true},
   10324             :       {"", "const {my_var : a} = {my_var};", true},
   10325             :       {"", "var [a, b = my_var] = [1, 2];", true},
   10326             :       {"", "var [a, b = my_var] = [1, 2]; my_var;", true},
   10327             :       {"", "let [a, b = my_var] = [1, 2];", true},
   10328             :       {"", "let [a, b = my_var] = [1, 2]; my_var;", true},
   10329             :       {"", "const [a, b = my_var] = [1, 2];", true},
   10330             :       {"", "const [a, b = my_var] = [1, 2]; my_var;", true},
   10331             :       {"", "var {a = my_var} = {}", true},
   10332             :       {"", "var {a: b = my_var} = {}", true},
   10333             :       {"", "let {a = my_var} = {}", true},
   10334             :       {"", "let {a: b = my_var} = {}", true},
   10335             :       {"", "const {a = my_var} = {}", true},
   10336             :       {"", "const {a: b = my_var} = {}", true},
   10337             :       {"a = my_var", "", true},
   10338             :       {"a = my_var", "let my_var;", true},
   10339             :       {"", "function inner2(a = my_var) { }", true},
   10340             :       {"", "(a = my_var) => { }", true},
   10341             :       {"{a} = {a: my_var}", "", true},
   10342             :       {"", "function inner2({a} = {a: my_var}) { }", true},
   10343             :       {"", "({a} = {a: my_var}) => { }", true},
   10344             :       {"[a] = [my_var]", "", true},
   10345             :       {"", "function inner2([a] = [my_var]) { }", true},
   10346             :       {"", "([a] = [my_var]) => { }", true},
   10347             :       {"", "function inner2(a = eval('')) { }", true},
   10348             :       {"", "(a = eval('')) => { }", true},
   10349             :       {"", "try { } catch (my_var) { } my_var;", true},
   10350             :       {"", "for (my_var in {}) { my_var; }", true},
   10351             :       {"", "for (my_var in {}) { }", true},
   10352             :       {"", "for (my_var of []) { my_var; }", true},
   10353             :       {"", "for (my_var of []) { }", true},
   10354             :       {"", "for ([a, my_var, b] in {}) { my_var; }", true},
   10355             :       {"", "for ([a, my_var, b] of []) { my_var; }", true},
   10356             :       {"", "for ({x: my_var} in {}) { my_var; }", true},
   10357             :       {"", "for ({x: my_var} of []) { my_var; }", true},
   10358             :       {"", "for ({my_var} in {}) { my_var; }", true},
   10359             :       {"", "for ({my_var} of []) { my_var; }", true},
   10360             :       {"", "for ({y, x: my_var} in {}) { my_var; }", true},
   10361             :       {"", "for ({y, x: my_var} of []) { my_var; }", true},
   10362             :       {"", "for ({a, my_var} in {}) { my_var; }", true},
   10363             :       {"", "for ({a, my_var} of []) { my_var; }", true},
   10364             :       {"", "for (let my_var in {}) { } my_var;", true},
   10365             :       {"", "for (let my_var of []) { } my_var;", true},
   10366             :       {"", "for (let [a, my_var, b] in {}) { } my_var;", true},
   10367             :       {"", "for (let [a, my_var, b] of []) { } my_var;", true},
   10368             :       {"", "for (let {x: my_var} in {}) { } my_var;", true},
   10369             :       {"", "for (let {x: my_var} of []) { } my_var;", true},
   10370             :       {"", "for (let {my_var} in {}) { } my_var;", true},
   10371             :       {"", "for (let {my_var} of []) { } my_var;", true},
   10372             :       {"", "for (let {y, x: my_var} in {}) { } my_var;", true},
   10373             :       {"", "for (let {y, x: my_var} of []) { } my_var;", true},
   10374             :       {"", "for (let {a, my_var} in {}) { } my_var;", true},
   10375             :       {"", "for (let {a, my_var} of []) { } my_var;", true},
   10376             :       {"", "for (let my_var = 0; my_var < 1; ++my_var) { } my_var;", true},
   10377             :       {"", "'use strict'; if (true) { function my_var() {} } my_var;", true},
   10378             :       {"",
   10379             :        "'use strict'; function inner2() { if (true) { function my_var() {} }  "
   10380             :        "my_var; }",
   10381             :        true},
   10382             :       {"",
   10383             :        "function inner2() { 'use strict'; if (true) { function my_var() {} }  "
   10384             :        "my_var; }",
   10385             :        true},
   10386             :       {"",
   10387             :        "() => { 'use strict'; if (true) { function my_var() {} }  my_var; }",
   10388             :        true},
   10389             :       {"",
   10390             :        "if (true) { let my_var; if (true) { function my_var() {} } } my_var;",
   10391             :        true},
   10392             :       {"", "function inner2(a = my_var) {}", true},
   10393             :       {"", "function inner2(a = my_var) { let my_var; }", true},
   10394             :       {"", "(a = my_var) => {}", true},
   10395             :       {"", "(a = my_var) => { let my_var; }", true},
   10396             :       // No pessimistic context allocation:
   10397             :       {"", "var my_var; my_var;", false},
   10398             :       {"", "var my_var;", false},
   10399             :       {"", "var my_var = 0;", false},
   10400             :       {"", "if (true) { var my_var; } my_var;", false},
   10401             :       {"", "let my_var; my_var;", false},
   10402             :       {"", "let my_var;", false},
   10403             :       {"", "let my_var = 0;", false},
   10404             :       {"", "const my_var = 0; my_var;", false},
   10405             :       {"", "const my_var = 0;", false},
   10406             :       {"", "var [a, my_var] = [1, 2]; my_var;", false},
   10407             :       {"", "let [a, my_var] = [1, 2]; my_var;", false},
   10408             :       {"", "const [a, my_var] = [1, 2]; my_var;", false},
   10409             :       {"", "var {a: my_var} = {a: 3}; my_var;", false},
   10410             :       {"", "let {a: my_var} = {a: 3}; my_var;", false},
   10411             :       {"", "const {a: my_var} = {a: 3}; my_var;", false},
   10412             :       {"", "var {my_var} = {my_var: 3}; my_var;", false},
   10413             :       {"", "let {my_var} = {my_var: 3}; my_var;", false},
   10414             :       {"", "const {my_var} = {my_var: 3}; my_var;", false},
   10415             :       {"my_var", "my_var;", false},
   10416             :       {"my_var", "", false},
   10417             :       {"my_var = 5", "my_var;", false},
   10418             :       {"my_var = 5", "", false},
   10419             :       {"...my_var", "my_var;", false},
   10420             :       {"...my_var", "", false},
   10421             :       {"[a, my_var, b]", "my_var;", false},
   10422             :       {"[a, my_var, b]", "", false},
   10423             :       {"[a, my_var, b] = [1, 2, 3]", "my_var;", false},
   10424             :       {"[a, my_var, b] = [1, 2, 3]", "", false},
   10425             :       {"{x: my_var}", "my_var;", false},
   10426             :       {"{x: my_var}", "", false},
   10427             :       {"{x: my_var} = {x: 0}", "my_var;", false},
   10428             :       {"{x: my_var} = {x: 0}", "", false},
   10429             :       {"{my_var}", "my_var;", false},
   10430             :       {"{my_var}", "", false},
   10431             :       {"{my_var} = {my_var: 0}", "my_var;", false},
   10432             :       {"{my_var} = {my_var: 0}", "", false},
   10433             :       {"", "function inner2(my_var) { my_var; }", false},
   10434             :       {"", "function inner2(my_var) { }", false},
   10435             :       {"", "function inner2(my_var = 5) { my_var; }", false},
   10436             :       {"", "function inner2(my_var = 5) { }", false},
   10437             :       {"", "function inner2(...my_var) { my_var; }", false},
   10438             :       {"", "function inner2(...my_var) { }", false},
   10439             :       {"", "function inner2([a, my_var, b]) { my_var; }", false},
   10440             :       {"", "function inner2([a, my_var, b]) { }", false},
   10441             :       {"", "function inner2([a, my_var, b] = [1, 2, 3]) { my_var; }", false},
   10442             :       {"", "function inner2([a, my_var, b] = [1, 2, 3]) { }", false},
   10443             :       {"", "function inner2({x: my_var}) { my_var; }", false},
   10444             :       {"", "function inner2({x: my_var}) { }", false},
   10445             :       {"", "function inner2({x: my_var} = {x: 0}) { my_var; }", false},
   10446             :       {"", "function inner2({x: my_var} = {x: 0}) { }", false},
   10447             :       {"", "function inner2({my_var}) { my_var; }", false},
   10448             :       {"", "function inner2({my_var}) { }", false},
   10449             :       {"", "function inner2({my_var} = {my_var: 8}) { my_var; } ", false},
   10450             :       {"", "function inner2({my_var} = {my_var: 8}) { }", false},
   10451             :       {"", "my_var => my_var;", false},
   10452             :       {"", "my_var => { }", false},
   10453             :       {"", "(my_var = 5) => my_var;", false},
   10454             :       {"", "(my_var = 5) => { }", false},
   10455             :       {"", "(...my_var) => my_var;", false},
   10456             :       {"", "(...my_var) => { }", false},
   10457             :       {"", "([a, my_var, b]) => my_var;", false},
   10458             :       {"", "([a, my_var, b]) => { }", false},
   10459             :       {"", "([a, my_var, b] = [1, 2, 3]) => my_var;", false},
   10460             :       {"", "([a, my_var, b] = [1, 2, 3]) => { }", false},
   10461             :       {"", "({x: my_var}) => my_var;", false},
   10462             :       {"", "({x: my_var}) => { }", false},
   10463             :       {"", "({x: my_var} = {x: 0}) => my_var;", false},
   10464             :       {"", "({x: my_var} = {x: 0}) => { }", false},
   10465             :       {"", "({my_var}) => my_var;", false},
   10466             :       {"", "({my_var}) => { }", false},
   10467             :       {"", "({my_var} = {my_var: 5}) => my_var;", false},
   10468             :       {"", "({my_var} = {my_var: 5}) => { }", false},
   10469             :       {"", "({a, my_var}) => my_var;", false},
   10470             :       {"", "({a, my_var}) => { }", false},
   10471             :       {"", "({a, my_var} = {a: 0, my_var: 5}) => my_var;", false},
   10472             :       {"", "({a, my_var} = {a: 0, my_var: 5}) => { }", false},
   10473             :       {"", "({y, x: my_var}) => my_var;", false},
   10474             :       {"", "({y, x: my_var}) => { }", false},
   10475             :       {"", "({y, x: my_var} = {y: 0, x: 0}) => my_var;", false},
   10476             :       {"", "({y, x: my_var} = {y: 0, x: 0}) => { }", false},
   10477             :       {"", "try { } catch (my_var) { my_var; }", false},
   10478             :       {"", "try { } catch ([a, my_var, b]) { my_var; }", false},
   10479             :       {"", "try { } catch ({x: my_var}) { my_var; }", false},
   10480             :       {"", "try { } catch ({y, x: my_var}) { my_var; }", false},
   10481             :       {"", "try { } catch ({my_var}) { my_var; }", false},
   10482             :       {"", "for (let my_var in {}) { my_var; }", false},
   10483             :       {"", "for (let my_var in {}) { }", false},
   10484             :       {"", "for (let my_var of []) { my_var; }", false},
   10485             :       {"", "for (let my_var of []) { }", false},
   10486             :       {"", "for (let [a, my_var, b] in {}) { my_var; }", false},
   10487             :       {"", "for (let [a, my_var, b] of []) { my_var; }", false},
   10488             :       {"", "for (let {x: my_var} in {}) { my_var; }", false},
   10489             :       {"", "for (let {x: my_var} of []) { my_var; }", false},
   10490             :       {"", "for (let {my_var} in {}) { my_var; }", false},
   10491             :       {"", "for (let {my_var} of []) { my_var; }", false},
   10492             :       {"", "for (let {y, x: my_var} in {}) { my_var; }", false},
   10493             :       {"", "for (let {y, x: my_var} of []) { my_var; }", false},
   10494             :       {"", "for (let {a, my_var} in {}) { my_var; }", false},
   10495             :       {"", "for (let {a, my_var} of []) { my_var; }", false},
   10496             :       {"", "for (var my_var in {}) { my_var; }", false},
   10497             :       {"", "for (var my_var in {}) { }", false},
   10498             :       {"", "for (var my_var of []) { my_var; }", false},
   10499             :       {"", "for (var my_var of []) { }", false},
   10500             :       {"", "for (var [a, my_var, b] in {}) { my_var; }", false},
   10501             :       {"", "for (var [a, my_var, b] of []) { my_var; }", false},
   10502             :       {"", "for (var {x: my_var} in {}) { my_var; }", false},
   10503             :       {"", "for (var {x: my_var} of []) { my_var; }", false},
   10504             :       {"", "for (var {my_var} in {}) { my_var; }", false},
   10505             :       {"", "for (var {my_var} of []) { my_var; }", false},
   10506             :       {"", "for (var {y, x: my_var} in {}) { my_var; }", false},
   10507             :       {"", "for (var {y, x: my_var} of []) { my_var; }", false},
   10508             :       {"", "for (var {a, my_var} in {}) { my_var; }", false},
   10509             :       {"", "for (var {a, my_var} of []) { my_var; }", false},
   10510             :       {"", "for (var my_var in {}) { } my_var;", false},
   10511             :       {"", "for (var my_var of []) { } my_var;", false},
   10512             :       {"", "for (var [a, my_var, b] in {}) { } my_var;", false},
   10513             :       {"", "for (var [a, my_var, b] of []) { } my_var;", false},
   10514             :       {"", "for (var {x: my_var} in {}) { } my_var;", false},
   10515             :       {"", "for (var {x: my_var} of []) { } my_var;", false},
   10516             :       {"", "for (var {my_var} in {}) { } my_var;", false},
   10517             :       {"", "for (var {my_var} of []) { } my_var;", false},
   10518             :       {"", "for (var {y, x: my_var} in {}) { } my_var;", false},
   10519             :       {"", "for (var {y, x: my_var} of []) { } my_var;", false},
   10520             :       {"", "for (var {a, my_var} in {}) { } my_var;", false},
   10521             :       {"", "for (var {a, my_var} of []) { } my_var;", false},
   10522             :       {"", "for (let my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
   10523             :       {"", "for (var my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
   10524             :       {"", "for (var my_var = 0; my_var < 1; ++my_var) { } my_var; ", false},
   10525             :       {"", "for (let a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
   10526             :        false},
   10527             :       {"", "for (var a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
   10528             :        false},
   10529             :       {"", "class my_var {}; my_var; ", false},
   10530             :       {"", "function my_var() {} my_var;", false},
   10531             :       {"", "if (true) { function my_var() {} }  my_var;", false},
   10532             :       {"", "function inner2() { if (true) { function my_var() {} }  my_var; }",
   10533             :        false},
   10534             :       {"", "() => { if (true) { function my_var() {} }  my_var; }", false},
   10535             :       {"",
   10536             :        "if (true) { var my_var; if (true) { function my_var() {} } }  my_var;",
   10537             :        false},
   10538           5 :   };
   10539             : 
   10540          15 :   for (unsigned inner_ix = 0; inner_ix < arraysize(inner_functions);
   10541             :        ++inner_ix) {
   10542          10 :     const char* inner_function = inner_functions[inner_ix];
   10543          10 :     int inner_function_len = Utf8LengthHelper(inner_function) - 4;
   10544             : 
   10545        2060 :     for (unsigned i = 0; i < arraysize(inners); ++i) {
   10546        2050 :       int params_len = Utf8LengthHelper(inners[i].params);
   10547        2050 :       int source_len = Utf8LengthHelper(inners[i].source);
   10548        2050 :       int len = prefix_len + inner_function_len + params_len + source_len +
   10549        2050 :                 suffix_len;
   10550             : 
   10551        2050 :       i::ScopedVector<char> program(len + 1);
   10552        2050 :       i::SNPrintF(program, "%s", prefix);
   10553             :       i::SNPrintF(program + prefix_len, inner_function, inners[i].params,
   10554        4100 :                   inners[i].source);
   10555             :       i::SNPrintF(
   10556        2050 :           program + prefix_len + inner_function_len + params_len + source_len,
   10557        4100 :           "%s", suffix);
   10558             : 
   10559             :       i::Handle<i::String> source =
   10560        2050 :           factory->InternalizeUtf8String(program.start());
   10561        4100 :       source->PrintOn(stdout);
   10562             :       printf("\n");
   10563             : 
   10564        2050 :       i::Handle<i::Script> script = factory->NewScript(source);
   10565        4100 :       i::ParseInfo info(isolate, script);
   10566             : 
   10567        2050 :       CHECK(i::parsing::ParseProgram(&info, isolate));
   10568        2050 :       CHECK(i::Compiler::Analyze(&info));
   10569        2050 :       CHECK_NOT_NULL(info.literal());
   10570             : 
   10571        2050 :       i::Scope* scope = info.literal()->scope()->inner_scope();
   10572             :       DCHECK_NOT_NULL(scope);
   10573             :       DCHECK_NULL(scope->sibling());
   10574             :       DCHECK(scope->is_function_scope());
   10575             :       const i::AstRawString* var_name =
   10576        2050 :           info.ast_value_factory()->GetOneByteString("my_var");
   10577             :       i::Variable* var = scope->LookupForTesting(var_name);
   10578        2050 :       CHECK_EQ(inners[i].ctxt_allocate,
   10579             :                i::ScopeTestHelper::MustAllocateInContext(var));
   10580             :     }
   10581             :   }
   10582           5 : }
   10583             : 
   10584       28342 : TEST(EscapedStrictReservedWord) {
   10585             :   // Test that identifiers which are both escaped and only reserved in the
   10586             :   // strict mode are accepted in non-strict mode.
   10587           5 :   const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
   10588             : 
   10589             :   const char* statement_data[] = {"if (true) l\\u0065t: ;",
   10590             :                                   "function l\\u0065t() { }",
   10591             :                                   "(function l\\u0065t() { })",
   10592             :                                   "async function l\\u0065t() { }",
   10593             :                                   "(async function l\\u0065t() { })",
   10594             :                                   "l\\u0065t => 42",
   10595             :                                   "async l\\u0065t => 42",
   10596             :                                   "function packag\\u0065() {}",
   10597             :                                   "function impl\\u0065ments() {}",
   10598             :                                   "function privat\\u0065() {}",
   10599           5 :                                   nullptr};
   10600             : 
   10601           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
   10602           5 : }
   10603             : 
   10604       28342 : TEST(ForAwaitOf) {
   10605             :   // clang-format off
   10606             :   const char* context_data[][2] = {
   10607             :     { "async function f() { for await ", " ; }" },
   10608             :     { "async function f() { for await ", " { } }" },
   10609             :     { "async function * f() { for await ", " { } }" },
   10610             :     { "async function f() { 'use strict'; for await ", " ; }" },
   10611             :     { "async function f() { 'use strict'; for await ", "  { } }" },
   10612             :     { "async function * f() { 'use strict'; for await ", "  { } }" },
   10613             :     { "async function f() { for\nawait ", " ; }" },
   10614             :     { "async function f() { for\nawait ", " { } }" },
   10615             :     { "async function * f() { for\nawait ", " { } }" },
   10616             :     { "async function f() { 'use strict'; for\nawait ", " ; }" },
   10617             :     { "async function f() { 'use strict'; for\nawait ", " { } }" },
   10618             :     { "async function * f() { 'use strict'; for\nawait ", " { } }" },
   10619             :     { "async function f() { for await\n", " ; }" },
   10620             :     { "async function f() { for await\n", " { } }" },
   10621             :     { "async function * f() { for await\n", " { } }" },
   10622             :     { "async function f() { 'use strict'; for await\n", " ; }" },
   10623             :     { "async function f() { 'use strict'; for await\n", " { } }" },
   10624             :     { "async function * f() { 'use strict'; for await\n", " { } }" },
   10625             :     { nullptr, nullptr }
   10626           5 :   };
   10627             : 
   10628             :   const char* context_data2[][2] = {
   10629             :     { "async function f() { let a; for await ", " ; }" },
   10630             :     { "async function f() { let a; for await ", " { } }" },
   10631             :     { "async function * f() { let a; for await ", " { } }" },
   10632             :     { "async function f() { 'use strict'; let a; for await ", " ; }" },
   10633             :     { "async function f() { 'use strict'; let a; for await ", "  { } }" },
   10634             :     { "async function * f() { 'use strict'; let a; for await ", "  { } }" },
   10635             :     { "async function f() { let a; for\nawait ", " ; }" },
   10636             :     { "async function f() { let a; for\nawait ", " { } }" },
   10637             :     { "async function * f() { let a; for\nawait ", " { } }" },
   10638             :     { "async function f() { 'use strict'; let a; for\nawait ", " ; }" },
   10639             :     { "async function f() { 'use strict'; let a; for\nawait ", " { } }" },
   10640             :     { "async function * f() { 'use strict'; let a; for\nawait ", " { } }" },
   10641             :     { "async function f() { let a; for await\n", " ; }" },
   10642             :     { "async function f() { let a; for await\n", " { } }" },
   10643             :     { "async function * f() { let a; for await\n", " { } }" },
   10644             :     { "async function f() { 'use strict'; let a; for await\n", " ; }" },
   10645             :     { "async function f() { 'use strict'; let a; for await\n", " { } }" },
   10646             :     { "async function * f() { 'use strict'; let a; for await\n", " { } }" },
   10647             :     { nullptr, nullptr }
   10648           5 :   };
   10649             : 
   10650             :   const char* expr_data[] = {
   10651             :     // Primary Expressions
   10652             :     "(a of [])",
   10653             :     "(a.b of [])",
   10654             :     "([a] of [])",
   10655             :     "([a = 1] of [])",
   10656             :     "([a = 1, ...b] of [])",
   10657             :     "({a} of [])",
   10658             :     "({a: a} of [])",
   10659             :     "({'a': a} of [])",
   10660             :     "({\"a\": a} of [])",
   10661             :     "({[Symbol.iterator]: a} of [])",
   10662             :     "({0: a} of [])",
   10663             :     "({a = 1} of [])",
   10664             :     "({a: a = 1} of [])",
   10665             :     "({'a': a = 1} of [])",
   10666             :     "({\"a\": a = 1} of [])",
   10667             :     "({[Symbol.iterator]: a = 1} of [])",
   10668             :     "({0: a = 1} of [])",
   10669             :     nullptr
   10670           5 :   };
   10671             : 
   10672             :   const char* var_data[] = {
   10673             :     // VarDeclarations
   10674             :     "(var a of [])",
   10675             :     "(var [a] of [])",
   10676             :     "(var [a = 1] of [])",
   10677             :     "(var [a = 1, ...b] of [])",
   10678             :     "(var {a} of [])",
   10679             :     "(var {a: a} of [])",
   10680             :     "(var {'a': a} of [])",
   10681             :     "(var {\"a\": a} of [])",
   10682             :     "(var {[Symbol.iterator]: a} of [])",
   10683             :     "(var {0: a} of [])",
   10684             :     "(var {a = 1} of [])",
   10685             :     "(var {a: a = 1} of [])",
   10686             :     "(var {'a': a = 1} of [])",
   10687             :     "(var {\"a\": a = 1} of [])",
   10688             :     "(var {[Symbol.iterator]: a = 1} of [])",
   10689             :     "(var {0: a = 1} of [])",
   10690             :     nullptr
   10691           5 :   };
   10692             : 
   10693             :   const char* lexical_data[] = {
   10694             :     // LexicalDeclartions
   10695             :     "(let a of [])",
   10696             :     "(let [a] of [])",
   10697             :     "(let [a = 1] of [])",
   10698             :     "(let [a = 1, ...b] of [])",
   10699             :     "(let {a} of [])",
   10700             :     "(let {a: a} of [])",
   10701             :     "(let {'a': a} of [])",
   10702             :     "(let {\"a\": a} of [])",
   10703             :     "(let {[Symbol.iterator]: a} of [])",
   10704             :     "(let {0: a} of [])",
   10705             :     "(let {a = 1} of [])",
   10706             :     "(let {a: a = 1} of [])",
   10707             :     "(let {'a': a = 1} of [])",
   10708             :     "(let {\"a\": a = 1} of [])",
   10709             :     "(let {[Symbol.iterator]: a = 1} of [])",
   10710             :     "(let {0: a = 1} of [])",
   10711             : 
   10712             :     "(const a of [])",
   10713             :     "(const [a] of [])",
   10714             :     "(const [a = 1] of [])",
   10715             :     "(const [a = 1, ...b] of [])",
   10716             :     "(const {a} of [])",
   10717             :     "(const {a: a} of [])",
   10718             :     "(const {'a': a} of [])",
   10719             :     "(const {\"a\": a} of [])",
   10720             :     "(const {[Symbol.iterator]: a} of [])",
   10721             :     "(const {0: a} of [])",
   10722             :     "(const {a = 1} of [])",
   10723             :     "(const {a: a = 1} of [])",
   10724             :     "(const {'a': a = 1} of [])",
   10725             :     "(const {\"a\": a = 1} of [])",
   10726             :     "(const {[Symbol.iterator]: a = 1} of [])",
   10727             :     "(const {0: a = 1} of [])",
   10728             :     nullptr
   10729           5 :   };
   10730             :   // clang-format on
   10731           5 :   RunParserSyncTest(context_data, expr_data, kSuccess);
   10732           5 :   RunParserSyncTest(context_data2, expr_data, kSuccess);
   10733             : 
   10734           5 :   RunParserSyncTest(context_data, var_data, kSuccess);
   10735             :   // TODO(marja): PreParser doesn't report early errors.
   10736             :   //              (https://bugs.chromium.org/p/v8/issues/detail?id=2728)
   10737             :   // RunParserSyncTest(context_data2, var_data, kError, nullptr, 0,
   10738             :   // always_flags,
   10739             :   //                   arraysize(always_flags));
   10740             : 
   10741           5 :   RunParserSyncTest(context_data, lexical_data, kSuccess);
   10742           5 :   RunParserSyncTest(context_data2, lexical_data, kSuccess);
   10743           5 : }
   10744             : 
   10745       28342 : TEST(ForAwaitOfErrors) {
   10746             :   // clang-format off
   10747             :   const char* context_data[][2] = {
   10748             :     { "async function f() { for await ", " ; }" },
   10749             :     { "async function f() { for await ", " { } }" },
   10750             :     { "async function f() { 'use strict'; for await ", " ; }" },
   10751             :     { "async function f() { 'use strict'; for await ", "  { } }" },
   10752             :     { "async function * f() { for await ", " ; }" },
   10753             :     { "async function * f() { for await ", " { } }" },
   10754             :     { "async function * f() { 'use strict'; for await ", " ; }" },
   10755             :     { "async function * f() { 'use strict'; for await ", "  { } }" },
   10756             :     { nullptr, nullptr }
   10757           5 :   };
   10758             : 
   10759             :   const char* data[] = {
   10760             :     // Primary Expressions
   10761             :     "(a = 1 of [])",
   10762             :     "(a = 1) of [])",
   10763             :     "(a.b = 1 of [])",
   10764             :     "((a.b = 1) of [])",
   10765             :     "([a] = 1 of [])",
   10766             :     "(([a] = 1) of [])",
   10767             :     "([a = 1] = 1 of [])",
   10768             :     "(([a = 1] = 1) of [])",
   10769             :     "([a = 1 = 1, ...b] = 1 of [])",
   10770             :     "(([a = 1 = 1, ...b] = 1) of [])",
   10771             :     "({a} = 1 of [])",
   10772             :     "(({a} = 1) of [])",
   10773             :     "({a: a} = 1 of [])",
   10774             :     "(({a: a} = 1) of [])",
   10775             :     "({'a': a} = 1 of [])",
   10776             :     "(({'a': a} = 1) of [])",
   10777             :     "({\"a\": a} = 1 of [])",
   10778             :     "(({\"a\": a} = 1) of [])",
   10779             :     "({[Symbol.iterator]: a} = 1 of [])",
   10780             :     "(({[Symbol.iterator]: a} = 1) of [])",
   10781             :     "({0: a} = 1 of [])",
   10782             :     "(({0: a} = 1) of [])",
   10783             :     "({a = 1} = 1 of [])",
   10784             :     "(({a = 1} = 1) of [])",
   10785             :     "({a: a = 1} = 1 of [])",
   10786             :     "(({a: a = 1} = 1) of [])",
   10787             :     "({'a': a = 1} = 1 of [])",
   10788             :     "(({'a': a = 1} = 1) of [])",
   10789             :     "({\"a\": a = 1} = 1 of [])",
   10790             :     "(({\"a\": a = 1} = 1) of [])",
   10791             :     "({[Symbol.iterator]: a = 1} = 1 of [])",
   10792             :     "(({[Symbol.iterator]: a = 1} = 1) of [])",
   10793             :     "({0: a = 1} = 1 of [])",
   10794             :     "(({0: a = 1} = 1) of [])",
   10795             :     "(function a() {} of [])",
   10796             :     "([1] of [])",
   10797             :     "({a: 1} of [])"
   10798             : 
   10799             :     // VarDeclarations
   10800             :     "(var a = 1 of [])",
   10801             :     "(var a, b of [])",
   10802             :     "(var [a] = 1 of [])",
   10803             :     "(var [a], b of [])",
   10804             :     "(var [a = 1] = 1 of [])",
   10805             :     "(var [a = 1], b of [])",
   10806             :     "(var [a = 1 = 1, ...b] of [])",
   10807             :     "(var [a = 1, ...b], c of [])",
   10808             :     "(var {a} = 1 of [])",
   10809             :     "(var {a}, b of [])",
   10810             :     "(var {a: a} = 1 of [])",
   10811             :     "(var {a: a}, b of [])",
   10812             :     "(var {'a': a} = 1 of [])",
   10813             :     "(var {'a': a}, b of [])",
   10814             :     "(var {\"a\": a} = 1 of [])",
   10815             :     "(var {\"a\": a}, b of [])",
   10816             :     "(var {[Symbol.iterator]: a} = 1 of [])",
   10817             :     "(var {[Symbol.iterator]: a}, b of [])",
   10818             :     "(var {0: a} = 1 of [])",
   10819             :     "(var {0: a}, b of [])",
   10820             :     "(var {a = 1} = 1 of [])",
   10821             :     "(var {a = 1}, b of [])",
   10822             :     "(var {a: a = 1} = 1 of [])",
   10823             :     "(var {a: a = 1}, b of [])",
   10824             :     "(var {'a': a = 1} = 1 of [])",
   10825             :     "(var {'a': a = 1}, b of [])",
   10826             :     "(var {\"a\": a = 1} = 1 of [])",
   10827             :     "(var {\"a\": a = 1}, b of [])",
   10828             :     "(var {[Symbol.iterator]: a = 1} = 1 of [])",
   10829             :     "(var {[Symbol.iterator]: a = 1}, b of [])",
   10830             :     "(var {0: a = 1} = 1 of [])",
   10831             :     "(var {0: a = 1}, b of [])",
   10832             : 
   10833             :     // LexicalDeclartions
   10834             :     "(let a = 1 of [])",
   10835             :     "(let a, b of [])",
   10836             :     "(let [a] = 1 of [])",
   10837             :     "(let [a], b of [])",
   10838             :     "(let [a = 1] = 1 of [])",
   10839             :     "(let [a = 1], b of [])",
   10840             :     "(let [a = 1, ...b] = 1 of [])",
   10841             :     "(let [a = 1, ...b], c of [])",
   10842             :     "(let {a} = 1 of [])",
   10843             :     "(let {a}, b of [])",
   10844             :     "(let {a: a} = 1 of [])",
   10845             :     "(let {a: a}, b of [])",
   10846             :     "(let {'a': a} = 1 of [])",
   10847             :     "(let {'a': a}, b of [])",
   10848             :     "(let {\"a\": a} = 1 of [])",
   10849             :     "(let {\"a\": a}, b of [])",
   10850             :     "(let {[Symbol.iterator]: a} = 1 of [])",
   10851             :     "(let {[Symbol.iterator]: a}, b of [])",
   10852             :     "(let {0: a} = 1 of [])",
   10853             :     "(let {0: a}, b of [])",
   10854             :     "(let {a = 1} = 1 of [])",
   10855             :     "(let {a = 1}, b of [])",
   10856             :     "(let {a: a = 1} = 1 of [])",
   10857             :     "(let {a: a = 1}, b of [])",
   10858             :     "(let {'a': a = 1} = 1 of [])",
   10859             :     "(let {'a': a = 1}, b of [])",
   10860             :     "(let {\"a\": a = 1} = 1 of [])",
   10861             :     "(let {\"a\": a = 1}, b of [])",
   10862             :     "(let {[Symbol.iterator]: a = 1} = 1 of [])",
   10863             :     "(let {[Symbol.iterator]: a = 1}, b of [])",
   10864             :     "(let {0: a = 1} = 1 of [])",
   10865             :     "(let {0: a = 1}, b of [])",
   10866             : 
   10867             :     "(const a = 1 of [])",
   10868             :     "(const a, b of [])",
   10869             :     "(const [a] = 1 of [])",
   10870             :     "(const [a], b of [])",
   10871             :     "(const [a = 1] = 1 of [])",
   10872             :     "(const [a = 1], b of [])",
   10873             :     "(const [a = 1, ...b] = 1 of [])",
   10874             :     "(const [a = 1, ...b], b of [])",
   10875             :     "(const {a} = 1 of [])",
   10876             :     "(const {a}, b of [])",
   10877             :     "(const {a: a} = 1 of [])",
   10878             :     "(const {a: a}, b of [])",
   10879             :     "(const {'a': a} = 1 of [])",
   10880             :     "(const {'a': a}, b of [])",
   10881             :     "(const {\"a\": a} = 1 of [])",
   10882             :     "(const {\"a\": a}, b of [])",
   10883             :     "(const {[Symbol.iterator]: a} = 1 of [])",
   10884             :     "(const {[Symbol.iterator]: a}, b of [])",
   10885             :     "(const {0: a} = 1 of [])",
   10886             :     "(const {0: a}, b of [])",
   10887             :     "(const {a = 1} = 1 of [])",
   10888             :     "(const {a = 1}, b of [])",
   10889             :     "(const {a: a = 1} = 1 of [])",
   10890             :     "(const {a: a = 1}, b of [])",
   10891             :     "(const {'a': a = 1} = 1 of [])",
   10892             :     "(const {'a': a = 1}, b of [])",
   10893             :     "(const {\"a\": a = 1} = 1 of [])",
   10894             :     "(const {\"a\": a = 1}, b of [])",
   10895             :     "(const {[Symbol.iterator]: a = 1} = 1 of [])",
   10896             :     "(const {[Symbol.iterator]: a = 1}, b of [])",
   10897             :     "(const {0: a = 1} = 1 of [])",
   10898             :     "(const {0: a = 1}, b of [])",
   10899             : 
   10900             :     nullptr
   10901           5 :   };
   10902             :   // clang-format on
   10903           5 :   RunParserSyncTest(context_data, data, kError);
   10904           5 : }
   10905             : 
   10906       28342 : TEST(ForAwaitOfFunctionDeclaration) {
   10907             :   // clang-format off
   10908             :   const char* context_data[][2] = {
   10909             :     { "async function f() {", "}" },
   10910             :     { "async function f() { 'use strict'; ", "}" },
   10911             :     { nullptr, nullptr }
   10912           5 :   };
   10913             : 
   10914             :   const char* data[] = {
   10915             :     "for await (x of []) function d() {};",
   10916             :     "for await (x of []) function d() {}; return d;",
   10917             :     "for await (x of []) function* g() {};",
   10918             :     "for await (x of []) function* g() {}; return g;",
   10919             :     // TODO(caitp): handle async function declarations in ParseScopedStatement.
   10920             :     // "for await (x of []) async function a() {};",
   10921             :     // "for await (x of []) async function a() {}; return a;",
   10922             :     nullptr
   10923           5 :   };
   10924             : 
   10925             :   // clang-format on
   10926           5 :   RunParserSyncTest(context_data, data, kError);
   10927           5 : }
   10928             : 
   10929       28342 : TEST(AsyncGenerator) {
   10930             :   // clang-format off
   10931             :   const char* context_data[][2] = {
   10932             :     { "async function * gen() {", "}" },
   10933             :     { "(async function * gen() {", "})" },
   10934             :     { "(async function * () {", "})" },
   10935             :     { "({ async * gen () {", "} })" },
   10936             :     { nullptr, nullptr }
   10937           5 :   };
   10938             : 
   10939             :   const char* statement_data[] = {
   10940             :     // An async generator without a body is valid.
   10941             :     ""
   10942             :     // Valid yield expressions inside generators.
   10943             :     "yield 2;",
   10944             :     "yield * 2;",
   10945             :     "yield * \n 2;",
   10946             :     "yield yield 1;",
   10947             :     "yield * yield * 1;",
   10948             :     "yield 3 + (yield 4);",
   10949             :     "yield * 3 + (yield * 4);",
   10950             :     "(yield * 3) + (yield * 4);",
   10951             :     "yield 3; yield 4;",
   10952             :     "yield * 3; yield * 4;",
   10953             :     "(function (yield) { })",
   10954             :     "(function yield() { })",
   10955             :     "(function (await) { })",
   10956             :     "(function await() { })",
   10957             :     "yield { yield: 12 }",
   10958             :     "yield /* comment */ { yield: 12 }",
   10959             :     "yield * \n { yield: 12 }",
   10960             :     "yield /* comment */ * \n { yield: 12 }",
   10961             :     // You can return in an async generator.
   10962             :     "yield 1; return",
   10963             :     "yield * 1; return",
   10964             :     "yield 1; return 37",
   10965             :     "yield * 1; return 37",
   10966             :     "yield 1; return 37; yield 'dead';",
   10967             :     "yield * 1; return 37; yield * 'dead';",
   10968             :     // Yield/Await are still a valid key in object literals.
   10969             :     "({ yield: 1 })",
   10970             :     "({ get yield() { } })",
   10971             :     "({ await: 1 })",
   10972             :     "({ get await() { } })",
   10973             :     // And in assignment pattern computed properties
   10974             :     "({ [yield]: x } = { })",
   10975             :     "({ [await 1]: x } = { })",
   10976             :     // Yield without RHS.
   10977             :     "yield;",
   10978             :     "yield",
   10979             :     "yield\n",
   10980             :     "yield /* comment */"
   10981             :     "yield // comment\n"
   10982             :     "(yield)",
   10983             :     "[yield]",
   10984             :     "{yield}",
   10985             :     "yield, yield",
   10986             :     "yield; yield",
   10987             :     "(yield) ? yield : yield",
   10988             :     "(yield) \n ? yield : yield",
   10989             :     // If there is a newline before the next token, we don't look for RHS.
   10990             :     "yield\nfor (;;) {}",
   10991             :     "x = class extends (yield) {}",
   10992             :     "x = class extends f(yield) {}",
   10993             :     "x = class extends (null, yield) { }",
   10994             :     "x = class extends (a ? null : yield) { }",
   10995             :     "x = class extends (await 10) {}",
   10996             :     "x = class extends f(await 10) {}",
   10997             :     "x = class extends (null, await 10) { }",
   10998             :     "x = class extends (a ? null : await 10) { }",
   10999             : 
   11000             :     // More tests featuring AwaitExpressions
   11001             :     "await 10",
   11002             :     "await 10; return",
   11003             :     "await 10; return 20",
   11004             :     "await 10; return 20; yield 'dead'",
   11005             :     "await (yield 10)",
   11006             :     "await (yield 10); return",
   11007             :     "await (yield 10); return 20",
   11008             :     "await (yield 10); return 20; yield 'dead'",
   11009             :     "yield await 10",
   11010             :     "yield await 10; return",
   11011             :     "yield await 10; return 20",
   11012             :     "yield await 10; return 20; yield 'dead'",
   11013             :     "await /* comment */ 10",
   11014             :     "await // comment\n 10",
   11015             :     "yield await /* comment\n */ 10",
   11016             :     "yield await // comment\n 10",
   11017             :     "await (yield /* comment */)",
   11018             :     "await (yield // comment\n)",
   11019             :     nullptr
   11020           5 :   };
   11021             :   // clang-format on
   11022             : 
   11023           5 :   RunParserSyncTest(context_data, statement_data, kSuccess);
   11024           5 : }
   11025             : 
   11026       28342 : TEST(AsyncGeneratorErrors) {
   11027             :   // clang-format off
   11028             :   const char* context_data[][2] = {
   11029             :     { "async function * gen() {", "}" },
   11030             :     { "\"use strict\"; async function * gen() {", "}" },
   11031             :     { nullptr, nullptr }
   11032           5 :   };
   11033             : 
   11034             :   const char* statement_data[] = {
   11035             :     // Invalid yield expressions inside generators.
   11036             :     "var yield;",
   11037             :     "var await;",
   11038             :     "var foo, yield;",
   11039             :     "var foo, await;",
   11040             :     "try { } catch (yield) { }",
   11041             :     "try { } catch (await) { }",
   11042             :     "function yield() { }",
   11043             :     "function await() { }",
   11044             :     // The name of the NFE is bound in the generator, which does not permit
   11045             :     // yield or await to be identifiers.
   11046             :     "(async function * yield() { })",
   11047             :     "(async function * await() { })",
   11048             :     // Yield and Await aren't valid as a formal parameter for generators.
   11049             :     "async function * foo(yield) { }",
   11050             :     "(async function * foo(yield) { })",
   11051             :     "async function * foo(await) { }",
   11052             :     "(async function * foo(await) { })",
   11053             :     "yield = 1;",
   11054             :     "await = 1;",
   11055             :     "var foo = yield = 1;",
   11056             :     "var foo = await = 1;",
   11057             :     "++yield;",
   11058             :     "++await;",
   11059             :     "yield++;",
   11060             :     "await++;",
   11061             :     "yield *",
   11062             :     "(yield *)",
   11063             :     // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
   11064             :     // is invalid.
   11065             :     "yield 3 + yield 4;",
   11066             :     "yield: 34",
   11067             :     "yield ? 1 : 2",
   11068             :     // Parses as yield (/ yield): invalid.
   11069             :     "yield / yield",
   11070             :     "+ yield",
   11071             :     "+ yield 3",
   11072             :     // Invalid (no newline allowed between yield and *).
   11073             :     "yield\n*3",
   11074             :     // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
   11075             :     // object literal, and yield is not a valid label).
   11076             :     "yield\n{yield: 42}",
   11077             :     "yield /* comment */\n {yield: 42}",
   11078             :     "yield //comment\n {yield: 42}",
   11079             :     // Destructuring binding and assignment are both disallowed
   11080             :     "var [yield] = [42];",
   11081             :     "var [await] = [42];",
   11082             :     "var {foo: yield} = {a: 42};",
   11083             :     "var {foo: await} = {a: 42};",
   11084             :     "[yield] = [42];",
   11085             :     "[await] = [42];",
   11086             :     "({a: yield} = {a: 42});",
   11087             :     "({a: await} = {a: 42});",
   11088             :     // Also disallow full yield/await expressions on LHS
   11089             :     "var [yield 24] = [42];",
   11090             :     "var [await 24] = [42];",
   11091             :     "var {foo: yield 24} = {a: 42};",
   11092             :     "var {foo: await 24} = {a: 42};",
   11093             :     "[yield 24] = [42];",
   11094             :     "[await 24] = [42];",
   11095             :     "({a: yield 24} = {a: 42});",
   11096             :     "({a: await 24} = {a: 42});",
   11097             :     "for (yield 'x' in {});",
   11098             :     "for (await 'x' in {});",
   11099             :     "for (yield 'x' of {});",
   11100             :     "for (await 'x' of {});",
   11101             :     "for (yield 'x' in {} in {});",
   11102             :     "for (await 'x' in {} in {});",
   11103             :     "for (yield 'x' in {} of {});",
   11104             :     "for (await 'x' in {} of {});",
   11105             :     "class C extends yield { }",
   11106             :     "class C extends await { }",
   11107             :     nullptr
   11108           5 :   };
   11109             :   // clang-format on
   11110             : 
   11111           5 :   RunParserSyncTest(context_data, statement_data, kError);
   11112           5 : }
   11113             : 
   11114       28342 : TEST(LexicalLoopVariable) {
   11115             :   i::Isolate* isolate = CcTest::i_isolate();
   11116             :   i::HandleScope scope(isolate);
   11117          10 :   LocalContext env;
   11118             :   typedef std::function<void(const i::ParseInfo& info, i::DeclarationScope*)>
   11119             :       TestCB;
   11120          50 :   auto TestProgram = [isolate](const char* program, TestCB test) {
   11121          50 :     i::Factory* const factory = isolate->factory();
   11122             :     i::Handle<i::String> source =
   11123         100 :         factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
   11124          50 :     i::Handle<i::Script> script = factory->NewScript(source);
   11125          50 :     i::ParseInfo info(isolate, script);
   11126             : 
   11127             :     info.set_allow_lazy_parsing(false);
   11128          50 :     CHECK(i::parsing::ParseProgram(&info, isolate));
   11129          50 :     CHECK(i::Rewriter::Rewrite(&info));
   11130          50 :     CHECK(i::DeclarationScope::Analyze(&info));
   11131          50 :     i::DeclarationScope::AllocateScopeInfos(&info, isolate);
   11132          50 :     CHECK_NOT_NULL(info.literal());
   11133             : 
   11134          50 :     i::DeclarationScope* script_scope = info.literal()->scope();
   11135          50 :     CHECK(script_scope->is_script_scope());
   11136             : 
   11137          50 :     test(info, script_scope);
   11138          55 :   };
   11139             : 
   11140             :   // Check `let` loop variables is a stack local when not captured by
   11141             :   // an eval or closure within the area of the loop body.
   11142             :   const char* local_bindings[] = {
   11143             :       "function loop() {"
   11144             :       "  for (let loop_var = 0; loop_var < 10; ++loop_var) {"
   11145             :       "  }"
   11146             :       "  eval('0');"
   11147             :       "}",
   11148             : 
   11149             :       "function loop() {"
   11150             :       "  for (let loop_var = 0; loop_var < 10; ++loop_var) {"
   11151             :       "  }"
   11152             :       "  function foo() {}"
   11153             :       "  foo();"
   11154             :       "}",
   11155           5 :   };
   11156          15 :   for (const char* source : local_bindings) {
   11157          10 :     TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
   11158          20 :       i::Scope* fn = s->inner_scope();
   11159          10 :       CHECK(fn->is_function_scope());
   11160             : 
   11161          25 :       i::Scope* loop_block = fn->inner_scope();
   11162          10 :       if (loop_block->is_function_scope()) loop_block = loop_block->sibling();
   11163          10 :       CHECK(loop_block->is_block_scope());
   11164             : 
   11165             :       const i::AstRawString* var_name =
   11166          10 :           info.ast_value_factory()->GetOneByteString("loop_var");
   11167             :       i::Variable* loop_var = loop_block->LookupLocal(var_name);
   11168          10 :       CHECK_NOT_NULL(loop_var);
   11169          10 :       CHECK(loop_var->IsStackLocal());
   11170          10 :       CHECK_EQ(loop_block->ContextLocalCount(), 0);
   11171          10 :       CHECK_NULL(loop_block->inner_scope());
   11172          30 :     });
   11173             :   }
   11174             : 
   11175             :   // Check `let` loop variable is not a stack local, and is duplicated in the
   11176             :   // loop body to ensure capturing can work correctly.
   11177             :   // In this version of the test, the inner loop block's duplicate `loop_var`
   11178             :   // binding is not captured, and is a local.
   11179             :   const char* context_bindings1[] = {
   11180             :       "function loop() {"
   11181             :       "  for (let loop_var = eval('0'); loop_var < 10; ++loop_var) {"
   11182             :       "  }"
   11183             :       "}",
   11184             : 
   11185             :       "function loop() {"
   11186             :       "  for (let loop_var = (() => (loop_var, 0))(); loop_var < 10;"
   11187             :       "       ++loop_var) {"
   11188             :       "  }"
   11189           5 :       "}"};
   11190          15 :   for (const char* source : context_bindings1) {
   11191          10 :     TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
   11192          20 :       i::Scope* fn = s->inner_scope();
   11193          10 :       CHECK(fn->is_function_scope());
   11194             : 
   11195          30 :       i::Scope* loop_block = fn->inner_scope();
   11196          10 :       CHECK(loop_block->is_block_scope());
   11197             : 
   11198             :       const i::AstRawString* var_name =
   11199          10 :           info.ast_value_factory()->GetOneByteString("loop_var");
   11200             :       i::Variable* loop_var = loop_block->LookupLocal(var_name);
   11201          10 :       CHECK_NOT_NULL(loop_var);
   11202          10 :       CHECK(loop_var->IsContextSlot());
   11203          10 :       CHECK_EQ(loop_block->ContextLocalCount(), 1);
   11204             : 
   11205             :       i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
   11206          10 :       CHECK_NE(loop_var, loop_var2);
   11207          10 :       CHECK(loop_var2->IsStackLocal());
   11208          10 :       CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
   11209          30 :     });
   11210             :   }
   11211             : 
   11212             :   // Check `let` loop variable is not a stack local, and is duplicated in the
   11213             :   // loop body to ensure capturing can work correctly.
   11214             :   // In this version of the test, the inner loop block's duplicate `loop_var`
   11215             :   // binding is captured, and must be context allocated.
   11216             :   const char* context_bindings2[] = {
   11217             :       "function loop() {"
   11218             :       "  for (let loop_var = 0; loop_var < 10; ++loop_var) {"
   11219             :       "    eval('0');"
   11220             :       "  }"
   11221             :       "}",
   11222             : 
   11223             :       "function loop() {"
   11224             :       "  for (let loop_var = 0; loop_var < eval('10'); ++loop_var) {"
   11225             :       "  }"
   11226             :       "}",
   11227             : 
   11228             :       "function loop() {"
   11229             :       "  for (let loop_var = 0; loop_var < 10; eval('++loop_var')) {"
   11230             :       "  }"
   11231             :       "}",
   11232           5 :   };
   11233             : 
   11234          20 :   for (const char* source : context_bindings2) {
   11235          15 :     TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
   11236          30 :       i::Scope* fn = s->inner_scope();
   11237          15 :       CHECK(fn->is_function_scope());
   11238             : 
   11239          45 :       i::Scope* loop_block = fn->inner_scope();
   11240          15 :       CHECK(loop_block->is_block_scope());
   11241             : 
   11242             :       const i::AstRawString* var_name =
   11243          15 :           info.ast_value_factory()->GetOneByteString("loop_var");
   11244             :       i::Variable* loop_var = loop_block->LookupLocal(var_name);
   11245          15 :       CHECK_NOT_NULL(loop_var);
   11246          15 :       CHECK(loop_var->IsContextSlot());
   11247          15 :       CHECK_EQ(loop_block->ContextLocalCount(), 1);
   11248             : 
   11249             :       i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
   11250          15 :       CHECK_NE(loop_var, loop_var2);
   11251          15 :       CHECK(loop_var2->IsContextSlot());
   11252          15 :       CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
   11253          45 :     });
   11254             :   }
   11255             : 
   11256             :   // Similar to the above, but the first block scope's variables are not
   11257             :   // captured due to the closure occurring in a nested scope.
   11258             :   const char* context_bindings3[] = {
   11259             :       "function loop() {"
   11260             :       "  for (let loop_var = 0; loop_var < 10; ++loop_var) {"
   11261             :       "    (() => loop_var)();"
   11262             :       "  }"
   11263             :       "}",
   11264             : 
   11265             :       "function loop() {"
   11266             :       "  for (let loop_var = 0; loop_var < (() => (loop_var, 10))();"
   11267             :       "       ++loop_var) {"
   11268             :       "  }"
   11269             :       "}",
   11270             : 
   11271             :       "function loop() {"
   11272             :       "  for (let loop_var = 0; loop_var < 10; (() => ++loop_var)()) {"
   11273             :       "  }"
   11274             :       "}",
   11275           5 :   };
   11276             : 
   11277          20 :   for (const char* source : context_bindings3) {
   11278          15 :     TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
   11279          30 :       i::Scope* fn = s->inner_scope();
   11280          15 :       CHECK(fn->is_function_scope());
   11281             : 
   11282          45 :       i::Scope* loop_block = fn->inner_scope();
   11283          15 :       CHECK(loop_block->is_block_scope());
   11284             : 
   11285             :       const i::AstRawString* var_name =
   11286          15 :           info.ast_value_factory()->GetOneByteString("loop_var");
   11287             :       i::Variable* loop_var = loop_block->LookupLocal(var_name);
   11288          15 :       CHECK_NOT_NULL(loop_var);
   11289          15 :       CHECK(loop_var->IsStackLocal());
   11290          15 :       CHECK_EQ(loop_block->ContextLocalCount(), 0);
   11291             : 
   11292             :       i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
   11293          15 :       CHECK_NE(loop_var, loop_var2);
   11294          15 :       CHECK(loop_var2->IsContextSlot());
   11295          15 :       CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
   11296          45 :     });
   11297             :   }
   11298           5 : }
   11299             : 
   11300       28342 : TEST(PrivateNamesSyntaxError) {
   11301             :   i::Isolate* isolate = CcTest::i_isolate();
   11302             :   i::HandleScope scope(isolate);
   11303          10 :   LocalContext env;
   11304             : 
   11305         155 :   auto test = [isolate](const char* program, bool is_lazy) {
   11306         155 :     i::FLAG_harmony_private_fields = true;
   11307         155 :     i::Factory* const factory = isolate->factory();
   11308             :     i::Handle<i::String> source =
   11309         310 :         factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
   11310         155 :     i::Handle<i::Script> script = factory->NewScript(source);
   11311         155 :     i::ParseInfo info(isolate, script);
   11312             : 
   11313             :     info.set_allow_lazy_parsing(is_lazy);
   11314         155 :     CHECK(i::parsing::ParseProgram(&info, isolate));
   11315         155 :     CHECK(i::Rewriter::Rewrite(&info));
   11316         155 :     CHECK(!i::DeclarationScope::Analyze(&info));
   11317         310 :     return info.pending_error_handler()->has_pending_error();
   11318         160 :   };
   11319             : 
   11320             :   const char* data[] = {
   11321             :       "class A {"
   11322             :       "  foo() { return this.#bar; }"
   11323             :       "}",
   11324             : 
   11325             :       "let A = class {"
   11326             :       "  foo() { return this.#bar; }"
   11327             :       "}",
   11328             : 
   11329             :       "class A {"
   11330             :       "  #foo;  "
   11331             :       "  bar() { return this.#baz; }"
   11332             :       "}",
   11333             : 
   11334             :       "let A = class {"
   11335             :       "  #foo;  "
   11336             :       "  bar() { return this.#baz; }"
   11337             :       "}",
   11338             : 
   11339             :       "class A {"
   11340             :       "  bar() {"
   11341             :       "    class D { #baz = 1; };"
   11342             :       "    return this.#baz;"
   11343             :       "  }"
   11344             :       "}",
   11345             : 
   11346             :       "let A = class {"
   11347             :       "  bar() {"
   11348             :       "    class D { #baz = 1; };"
   11349             :       "    return this.#baz;"
   11350             :       "  }"
   11351             :       "}",
   11352             : 
   11353             :       "a.#bar",
   11354             : 
   11355             :       "class Foo {};"
   11356             :       "Foo.#bar;",
   11357             : 
   11358             :       "let Foo = class {};"
   11359             :       "Foo.#bar;",
   11360             : 
   11361             :       "class Foo {};"
   11362             :       "(new Foo).#bar;",
   11363             : 
   11364             :       "let Foo = class {};"
   11365             :       "(new Foo).#bar;",
   11366             : 
   11367             :       "class Foo { #bar; };"
   11368             :       "(new Foo).#bar;",
   11369             : 
   11370             :       "let Foo = class { #bar; };"
   11371             :       "(new Foo).#bar;",
   11372             : 
   11373             :       "function t(){"
   11374             :       "  class Foo { getA() { return this.#foo; } }"
   11375             :       "}",
   11376             : 
   11377             :       "function t(){"
   11378             :       "  return class { getA() { return this.#foo; } }"
   11379             :       "}",
   11380           5 :   };
   11381             : 
   11382             :   // TODO(gsathya): The preparser does not track unresolved
   11383             :   // variables in top level function which fails this test.
   11384             :   // https://bugs.chromium.org/p/v8/issues/detail?id=7468
   11385             :   const char* parser_data[] = {
   11386             :       "function t() {"
   11387             :       "  return this.#foo;"
   11388             :       "}",
   11389           5 :   };
   11390             : 
   11391          80 :   for (const char* source : data) {
   11392          75 :     CHECK(test(source, true));
   11393          75 :     CHECK(test(source, false));
   11394             :   }
   11395             : 
   11396          10 :   for (const char* source : parser_data) {
   11397           5 :     CHECK(test(source, false));
   11398             :   }
   11399           5 : }
   11400             : 
   11401       28342 : TEST(HashbangSyntax) {
   11402             :   const char* context_data[][2] = {
   11403           5 :       {"#!\n", ""}, {"#!---IGNORED---\n", ""}, {nullptr, nullptr}};
   11404             : 
   11405           5 :   const char* data[] = {"function\nFN\n(\n)\n {\n}\nFN();", nullptr};
   11406             : 
   11407           5 :   i::FLAG_harmony_hashbang = true;
   11408           5 :   RunParserSyncTest(context_data, data, kSuccess);
   11409             :   RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
   11410           5 :                     nullptr, 0, true);
   11411             : 
   11412           5 :   i::FLAG_harmony_hashbang = false;
   11413           5 :   RunParserSyncTest(context_data, data, kError);
   11414             :   RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0, nullptr,
   11415           5 :                     0, true);
   11416           5 : }
   11417             : 
   11418       28342 : TEST(HashbangSyntaxErrors) {
   11419           5 :   const char* file_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
   11420             :   const char* other_context_data[][2] = {{"/**/", ""},
   11421             :                                          {"//---\n", ""},
   11422             :                                          {";", ""},
   11423             :                                          {"function fn() {", "}"},
   11424             :                                          {"function* fn() {", "}"},
   11425             :                                          {"async function fn() {", "}"},
   11426             :                                          {"async function* fn() {", "}"},
   11427             :                                          {"() => {", "}"},
   11428             :                                          {"() => ", ""},
   11429             :                                          {"function fn(a = ", ") {}"},
   11430             :                                          {"function* fn(a = ", ") {}"},
   11431             :                                          {"async function fn(a = ", ") {}"},
   11432             :                                          {"async function* fn(a = ", ") {}"},
   11433             :                                          {"(a = ", ") => {}"},
   11434             :                                          {"(a = ", ") => a"},
   11435             :                                          {"class k {", "}"},
   11436             :                                          {"[", "]"},
   11437             :                                          {"{", "}"},
   11438             :                                          {"({", "})"},
   11439           5 :                                          {nullptr, nullptr}};
   11440             : 
   11441             :   const char* invalid_hashbang_data[] = {// Encoded characters are not allowed
   11442             :                                          "#\\u0021\n"
   11443             :                                          "\\u0023!\n",
   11444             :                                          "\\u0023\\u0021\n",
   11445             : 
   11446             :                                          "\n#!---IGNORED---\n",
   11447           5 :                                          " #!---IGNORED---\n", nullptr};
   11448           5 :   const char* hashbang_data[] = {"#!\n", "#!---IGNORED---\n", nullptr};
   11449             : 
   11450          15 :   auto SyntaxErrorTest = [](const char* context_data[][2], const char* data[]) {
   11451          15 :     i::FLAG_harmony_hashbang = true;
   11452          15 :     RunParserSyncTest(context_data, data, kError);
   11453             :     RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
   11454          15 :                       nullptr, 0, true);
   11455             : 
   11456          15 :     i::FLAG_harmony_hashbang = false;
   11457          15 :     RunParserSyncTest(context_data, data, kError);
   11458             :     RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
   11459          15 :                       nullptr, 0, true);
   11460          15 :   };
   11461             : 
   11462           5 :   SyntaxErrorTest(file_context_data, invalid_hashbang_data);
   11463           5 :   SyntaxErrorTest(other_context_data, invalid_hashbang_data);
   11464           5 :   SyntaxErrorTest(other_context_data, hashbang_data);
   11465           5 : }
   11466             : 
   11467             : }  // namespace test_parsing
   11468             : }  // namespace internal
   11469       85011 : }  // namespace v8

Generated by: LCOV version 1.10