Home | History | Annotate | Download | only in cctest
      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 "src/v8.h"
     33 
     34 #include "src/ast/ast.h"
     35 #include "src/ast/ast-numbering.h"
     36 #include "src/ast/ast-value-factory.h"
     37 #include "src/compiler.h"
     38 #include "src/execution.h"
     39 #include "src/isolate.h"
     40 #include "src/objects.h"
     41 #include "src/parsing/parser.h"
     42 #include "src/parsing/preparser.h"
     43 #include "src/parsing/rewriter.h"
     44 #include "src/parsing/scanner-character-streams.h"
     45 #include "src/parsing/token.h"
     46 #include "src/utils.h"
     47 
     48 #include "test/cctest/cctest.h"
     49 
     50 TEST(ScanKeywords) {
     51   struct KeywordToken {
     52     const char* keyword;
     53     i::Token::Value token;
     54   };
     55 
     56   static const KeywordToken keywords[] = {
     57 #define KEYWORD(t, s, d) { s, i::Token::t },
     58       TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
     59 #undef KEYWORD
     60       { NULL, i::Token::IDENTIFIER }
     61   };
     62 
     63   KeywordToken key_token;
     64   i::UnicodeCache unicode_cache;
     65   i::byte buffer[32];
     66   for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
     67     const i::byte* keyword =
     68         reinterpret_cast<const i::byte*>(key_token.keyword);
     69     int length = i::StrLength(key_token.keyword);
     70     CHECK(static_cast<int>(sizeof(buffer)) >= length);
     71     {
     72       i::Utf8ToUtf16CharacterStream stream(keyword, length);
     73       i::Scanner scanner(&unicode_cache);
     74       scanner.Initialize(&stream);
     75       CHECK_EQ(key_token.token, scanner.Next());
     76       CHECK_EQ(i::Token::EOS, scanner.Next());
     77     }
     78     // Removing characters will make keyword matching fail.
     79     {
     80       i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
     81       i::Scanner scanner(&unicode_cache);
     82       scanner.Initialize(&stream);
     83       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     84       CHECK_EQ(i::Token::EOS, scanner.Next());
     85     }
     86     // Adding characters will make keyword matching fail.
     87     static const char chars_to_append[] = { 'z', '0', '_' };
     88     for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
     89       i::MemMove(buffer, keyword, length);
     90       buffer[length] = chars_to_append[j];
     91       i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
     92       i::Scanner scanner(&unicode_cache);
     93       scanner.Initialize(&stream);
     94       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
     95       CHECK_EQ(i::Token::EOS, scanner.Next());
     96     }
     97     // Replacing characters will make keyword matching fail.
     98     {
     99       i::MemMove(buffer, keyword, length);
    100       buffer[length - 1] = '_';
    101       i::Utf8ToUtf16CharacterStream stream(buffer, length);
    102       i::Scanner scanner(&unicode_cache);
    103       scanner.Initialize(&stream);
    104       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
    105       CHECK_EQ(i::Token::EOS, scanner.Next());
    106     }
    107   }
    108 }
    109 
    110 
    111 TEST(ScanHTMLEndComments) {
    112   v8::V8::Initialize();
    113   v8::Isolate* isolate = CcTest::isolate();
    114   v8::HandleScope handles(isolate);
    115 
    116   // Regression test. See:
    117   //    http://code.google.com/p/chromium/issues/detail?id=53548
    118   // Tests that --> is correctly interpreted as comment-to-end-of-line if there
    119   // is only whitespace before it on the line (with comments considered as
    120   // whitespace, even a multiline-comment containing a newline).
    121   // This was not the case if it occurred before the first real token
    122   // in the input.
    123   const char* tests[] = {
    124       // Before first real token.
    125       "--> is eol-comment\nvar y = 37;\n",
    126       "\n --> is eol-comment\nvar y = 37;\n",
    127       "/* precomment */ --> is eol-comment\nvar y = 37;\n",
    128       "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
    129       // After first real token.
    130       "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
    131       "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
    132       NULL
    133   };
    134 
    135   const char* fail_tests[] = {
    136       "x --> is eol-comment\nvar y = 37;\n",
    137       "\"\\n\" --> is eol-comment\nvar y = 37;\n",
    138       "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
    139       "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
    140       "var x = 42; --> is eol-comment\nvar y = 37;\n",
    141       "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
    142       NULL
    143   };
    144 
    145   // Parser/Scanner needs a stack limit.
    146   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    147       i::GetCurrentStackPosition() - 128 * 1024);
    148   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
    149   for (int i = 0; tests[i]; i++) {
    150     const i::byte* source =
    151         reinterpret_cast<const i::byte*>(tests[i]);
    152     i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
    153     i::CompleteParserRecorder log;
    154     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    155     scanner.Initialize(&stream);
    156     i::Zone zone;
    157     i::AstValueFactory ast_value_factory(
    158         &zone, CcTest::i_isolate()->heap()->HashSeed());
    159     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    160                            stack_limit);
    161     preparser.set_allow_lazy(true);
    162     i::PreParser::PreParseResult result = preparser.PreParseProgram();
    163     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    164     CHECK(!log.HasError());
    165   }
    166 
    167   for (int i = 0; fail_tests[i]; i++) {
    168     const i::byte* source =
    169         reinterpret_cast<const i::byte*>(fail_tests[i]);
    170     i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
    171     i::CompleteParserRecorder log;
    172     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    173     scanner.Initialize(&stream);
    174     i::Zone zone;
    175     i::AstValueFactory ast_value_factory(
    176         &zone, CcTest::i_isolate()->heap()->HashSeed());
    177     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    178                            stack_limit);
    179     preparser.set_allow_lazy(true);
    180     i::PreParser::PreParseResult result = preparser.PreParseProgram();
    181     // Even in the case of a syntax error, kPreParseSuccess is returned.
    182     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    183     CHECK(log.HasError());
    184   }
    185 }
    186 
    187 
    188 class ScriptResource : public v8::String::ExternalOneByteStringResource {
    189  public:
    190   ScriptResource(const char* data, size_t length)
    191       : data_(data), length_(length) { }
    192 
    193   const char* data() const { return data_; }
    194   size_t length() const { return length_; }
    195 
    196  private:
    197   const char* data_;
    198   size_t length_;
    199 };
    200 
    201 
    202 TEST(UsingCachedData) {
    203   v8::Isolate* isolate = CcTest::isolate();
    204   v8::HandleScope handles(isolate);
    205   v8::Local<v8::Context> context = v8::Context::New(isolate);
    206   v8::Context::Scope context_scope(context);
    207   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    208       i::GetCurrentStackPosition() - 128 * 1024);
    209 
    210   // Source containing functions that might be lazily compiled  and all types
    211   // of symbols (string, propertyName, regexp).
    212   const char* source =
    213       "var x = 42;"
    214       "function foo(a) { return function nolazy(b) { return a + b; } }"
    215       "function bar(a) { if (a) return function lazy(b) { return b; } }"
    216       "var z = {'string': 'string literal', bareword: 'propertyName', "
    217       "         42: 'number literal', for: 'keyword as propertyName', "
    218       "         f\\u006fr: 'keyword propertyname with escape'};"
    219       "var v = /RegExp Literal/;"
    220       "var w = /RegExp Literal\\u0020With Escape/gi;"
    221       "var y = { get getter() { return 42; }, "
    222       "          set setter(v) { this.value = v; }};"
    223       "var f = a => function (b) { return a + b; };"
    224       "var g = a => b => a + b;";
    225   int source_length = i::StrLength(source);
    226 
    227   // ScriptResource will be deleted when the corresponding String is GCd.
    228   v8::ScriptCompiler::Source script_source(
    229       v8::String::NewExternalOneByte(isolate,
    230                                      new ScriptResource(source, source_length))
    231           .ToLocalChecked());
    232   i::FLAG_min_preparse_length = 0;
    233   v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
    234                               v8::ScriptCompiler::kProduceParserCache)
    235       .ToLocalChecked();
    236   CHECK(script_source.GetCachedData());
    237 
    238   // Compile the script again, using the cached data.
    239   bool lazy_flag = i::FLAG_lazy;
    240   i::FLAG_lazy = true;
    241   v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
    242                               v8::ScriptCompiler::kConsumeParserCache)
    243       .ToLocalChecked();
    244   i::FLAG_lazy = false;
    245   v8::ScriptCompiler::CompileUnboundScript(
    246       isolate, &script_source, v8::ScriptCompiler::kConsumeParserCache)
    247       .ToLocalChecked();
    248   i::FLAG_lazy = lazy_flag;
    249 }
    250 
    251 
    252 TEST(PreparseFunctionDataIsUsed) {
    253   // This tests that we actually do use the function data generated by the
    254   // preparser.
    255 
    256   // Make preparsing work for short scripts.
    257   i::FLAG_min_preparse_length = 0;
    258 
    259   v8::Isolate* isolate = CcTest::isolate();
    260   v8::HandleScope handles(isolate);
    261   v8::Local<v8::Context> context = v8::Context::New(isolate);
    262   v8::Context::Scope context_scope(context);
    263   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    264       i::GetCurrentStackPosition() - 128 * 1024);
    265 
    266   const char* good_code[] = {
    267       "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
    268       "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
    269   };
    270 
    271   // Insert a syntax error inside the lazy function.
    272   const char* bad_code[] = {
    273       "function this_is_lazy() { if (   } function foo() { return 25; } foo();",
    274       "var this_is_lazy = () => { if (   }; var foo = () => 25; foo();",
    275   };
    276 
    277   for (unsigned i = 0; i < arraysize(good_code); i++) {
    278     v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
    279     v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &good_source,
    280                                 v8::ScriptCompiler::kProduceParserCache)
    281         .ToLocalChecked();
    282 
    283     const v8::ScriptCompiler::CachedData* cached_data =
    284         good_source.GetCachedData();
    285     CHECK(cached_data->data != NULL);
    286     CHECK_GT(cached_data->length, 0);
    287 
    288     // Now compile the erroneous code with the good preparse data. If the
    289     // preparse data is used, the lazy function is skipped and it should
    290     // compile fine.
    291     v8::ScriptCompiler::Source bad_source(
    292         v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
    293                                  cached_data->data, cached_data->length));
    294     v8::Local<v8::Value> result =
    295         CompileRun(isolate->GetCurrentContext(), &bad_source,
    296                    v8::ScriptCompiler::kConsumeParserCache);
    297     CHECK(result->IsInt32());
    298     CHECK_EQ(25, result->Int32Value(isolate->GetCurrentContext()).FromJust());
    299   }
    300 }
    301 
    302 
    303 TEST(StandAlonePreParser) {
    304   v8::V8::Initialize();
    305 
    306   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    307       i::GetCurrentStackPosition() - 128 * 1024);
    308 
    309   const char* programs[] = {
    310       "{label: 42}",
    311       "var x = 42;",
    312       "function foo(x, y) { return x + y; }",
    313       "%ArgleBargle(glop);",
    314       "var x = new new Function('this.x = 42');",
    315       "var f = (x, y) => x + y;",
    316       NULL
    317   };
    318 
    319   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
    320   for (int i = 0; programs[i]; i++) {
    321     const char* program = programs[i];
    322     i::Utf8ToUtf16CharacterStream stream(
    323         reinterpret_cast<const i::byte*>(program),
    324         static_cast<unsigned>(strlen(program)));
    325     i::CompleteParserRecorder log;
    326     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    327     scanner.Initialize(&stream);
    328 
    329     i::Zone zone;
    330     i::AstValueFactory ast_value_factory(
    331         &zone, CcTest::i_isolate()->heap()->HashSeed());
    332     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    333                            stack_limit);
    334     preparser.set_allow_lazy(true);
    335     preparser.set_allow_natives(true);
    336     i::PreParser::PreParseResult result = preparser.PreParseProgram();
    337     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    338     CHECK(!log.HasError());
    339   }
    340 }
    341 
    342 
    343 TEST(StandAlonePreParserNoNatives) {
    344   v8::V8::Initialize();
    345 
    346   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    347       i::GetCurrentStackPosition() - 128 * 1024);
    348 
    349   const char* programs[] = {
    350       "%ArgleBargle(glop);",
    351       "var x = %_IsSmi(42);",
    352       NULL
    353   };
    354 
    355   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
    356   for (int i = 0; programs[i]; i++) {
    357     const char* program = programs[i];
    358     i::Utf8ToUtf16CharacterStream stream(
    359         reinterpret_cast<const i::byte*>(program),
    360         static_cast<unsigned>(strlen(program)));
    361     i::CompleteParserRecorder log;
    362     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    363     scanner.Initialize(&stream);
    364 
    365     // Preparser defaults to disallowing natives syntax.
    366     i::Zone zone;
    367     i::AstValueFactory ast_value_factory(
    368         &zone, CcTest::i_isolate()->heap()->HashSeed());
    369     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    370                            stack_limit);
    371     preparser.set_allow_lazy(true);
    372     i::PreParser::PreParseResult result = preparser.PreParseProgram();
    373     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    374     CHECK(log.HasError());
    375   }
    376 }
    377 
    378 
    379 TEST(PreparsingObjectLiterals) {
    380   // Regression test for a bug where the symbol stream produced by PreParser
    381   // didn't match what Parser wanted to consume.
    382   v8::Isolate* isolate = CcTest::isolate();
    383   v8::HandleScope handles(isolate);
    384   v8::Local<v8::Context> context = v8::Context::New(isolate);
    385   v8::Context::Scope context_scope(context);
    386   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    387       i::GetCurrentStackPosition() - 128 * 1024);
    388 
    389   {
    390     const char* source = "var myo = {if: \"foo\"}; myo.if;";
    391     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
    392     CHECK(result->IsString());
    393     v8::String::Utf8Value utf8(result);
    394     CHECK_EQ(0, strcmp("foo", *utf8));
    395   }
    396 
    397   {
    398     const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
    399     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
    400     CHECK(result->IsString());
    401     v8::String::Utf8Value utf8(result);
    402     CHECK_EQ(0, strcmp("foo", *utf8));
    403   }
    404 
    405   {
    406     const char* source = "var myo = {1: \"foo\"}; myo[1];";
    407     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
    408     CHECK(result->IsString());
    409     v8::String::Utf8Value utf8(result);
    410     CHECK_EQ(0, strcmp("foo", *utf8));
    411   }
    412 }
    413 
    414 
    415 TEST(RegressChromium62639) {
    416   v8::V8::Initialize();
    417   i::Isolate* isolate = CcTest::i_isolate();
    418 
    419   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    420                                         128 * 1024);
    421 
    422   const char* program = "var x = 'something';\n"
    423                         "escape: function() {}";
    424   // Fails parsing expecting an identifier after "function".
    425   // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
    426   // and then used the invalid currently scanned literal. This always
    427   // failed in debug mode, and sometimes crashed in release mode.
    428 
    429   i::Utf8ToUtf16CharacterStream stream(
    430       reinterpret_cast<const i::byte*>(program),
    431       static_cast<unsigned>(strlen(program)));
    432   i::CompleteParserRecorder log;
    433   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    434   scanner.Initialize(&stream);
    435   i::Zone zone;
    436   i::AstValueFactory ast_value_factory(&zone,
    437                                        CcTest::i_isolate()->heap()->HashSeed());
    438   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    439                          CcTest::i_isolate()->stack_guard()->real_climit());
    440   preparser.set_allow_lazy(true);
    441   i::PreParser::PreParseResult result = preparser.PreParseProgram();
    442   // Even in the case of a syntax error, kPreParseSuccess is returned.
    443   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    444   CHECK(log.HasError());
    445 }
    446 
    447 
    448 TEST(Regress928) {
    449   v8::V8::Initialize();
    450   i::Isolate* isolate = CcTest::i_isolate();
    451   i::Factory* factory = isolate->factory();
    452 
    453   // Preparsing didn't consider the catch clause of a try statement
    454   // as with-content, which made it assume that a function inside
    455   // the block could be lazily compiled, and an extra, unexpected,
    456   // entry was added to the data.
    457   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
    458                                         128 * 1024);
    459 
    460   const char* program =
    461       "try { } catch (e) { var foo = function () { /* first */ } }"
    462       "var bar = function () { /* second */ }";
    463 
    464   v8::HandleScope handles(CcTest::isolate());
    465   i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
    466   i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
    467   i::CompleteParserRecorder log;
    468   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    469   scanner.Initialize(&stream);
    470   i::Zone zone;
    471   i::AstValueFactory ast_value_factory(&zone,
    472                                        CcTest::i_isolate()->heap()->HashSeed());
    473   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    474                          CcTest::i_isolate()->stack_guard()->real_climit());
    475   preparser.set_allow_lazy(true);
    476   i::PreParser::PreParseResult result = preparser.PreParseProgram();
    477   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
    478   i::ScriptData* sd = log.GetScriptData();
    479   i::ParseData* pd = i::ParseData::FromCachedData(sd);
    480   pd->Initialize();
    481 
    482   int first_function =
    483       static_cast<int>(strstr(program, "function") - program);
    484   int first_lbrace = first_function + i::StrLength("function () ");
    485   CHECK_EQ('{', program[first_lbrace]);
    486   i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace);
    487   CHECK(!entry1.is_valid());
    488 
    489   int second_function =
    490       static_cast<int>(strstr(program + first_lbrace, "function") - program);
    491   int second_lbrace =
    492       second_function + i::StrLength("function () ");
    493   CHECK_EQ('{', program[second_lbrace]);
    494   i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace);
    495   CHECK(entry2.is_valid());
    496   CHECK_EQ('}', program[entry2.end_pos() - 1]);
    497   delete sd;
    498   delete pd;
    499 }
    500 
    501 
    502 TEST(PreParseOverflow) {
    503   v8::V8::Initialize();
    504 
    505   CcTest::i_isolate()->stack_guard()->SetStackLimit(
    506       i::GetCurrentStackPosition() - 128 * 1024);
    507 
    508   size_t kProgramSize = 1024 * 1024;
    509   v8::base::SmartArrayPointer<char> program(
    510       i::NewArray<char>(kProgramSize + 1));
    511   memset(program.get(), '(', kProgramSize);
    512   program[kProgramSize] = '\0';
    513 
    514   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
    515 
    516   i::Utf8ToUtf16CharacterStream stream(
    517       reinterpret_cast<const i::byte*>(program.get()),
    518       static_cast<unsigned>(kProgramSize));
    519   i::CompleteParserRecorder log;
    520   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    521   scanner.Initialize(&stream);
    522 
    523   i::Zone zone;
    524   i::AstValueFactory ast_value_factory(&zone,
    525                                        CcTest::i_isolate()->heap()->HashSeed());
    526   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
    527                          stack_limit);
    528   preparser.set_allow_lazy(true);
    529   i::PreParser::PreParseResult result = preparser.PreParseProgram();
    530   CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
    531 }
    532 
    533 
    534 class TestExternalResource: public v8::String::ExternalStringResource {
    535  public:
    536   explicit TestExternalResource(uint16_t* data, int length)
    537       : data_(data), length_(static_cast<size_t>(length)) { }
    538 
    539   ~TestExternalResource() { }
    540 
    541   const uint16_t* data() const {
    542     return data_;
    543   }
    544 
    545   size_t length() const {
    546     return length_;
    547   }
    548  private:
    549   uint16_t* data_;
    550   size_t length_;
    551 };
    552 
    553 
    554 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
    555 
    556 void TestCharacterStream(const char* one_byte_source, unsigned length,
    557                          unsigned start = 0, unsigned end = 0) {
    558   if (end == 0) end = length;
    559   unsigned sub_length = end - start;
    560   i::Isolate* isolate = CcTest::i_isolate();
    561   i::Factory* factory = isolate->factory();
    562   i::HandleScope test_scope(isolate);
    563   v8::base::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
    564   for (unsigned i = 0; i < length; i++) {
    565     uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
    566   }
    567   i::Vector<const char> one_byte_vector(one_byte_source,
    568                                         static_cast<int>(length));
    569   i::Handle<i::String> one_byte_string =
    570       factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
    571   TestExternalResource resource(uc16_buffer.get(), length);
    572   i::Handle<i::String> uc16_string(
    573       factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
    574 
    575   i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
    576       i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
    577   i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
    578                                                      end);
    579   i::Utf8ToUtf16CharacterStream utf8_stream(
    580       reinterpret_cast<const i::byte*>(one_byte_source), end);
    581   utf8_stream.SeekForward(start);
    582 
    583   unsigned i = start;
    584   while (i < end) {
    585     // Read streams one char at a time
    586     CHECK_EQU(i, uc16_stream.pos());
    587     CHECK_EQU(i, string_stream.pos());
    588     CHECK_EQU(i, utf8_stream.pos());
    589     int32_t c0 = one_byte_source[i];
    590     int32_t c1 = uc16_stream.Advance();
    591     int32_t c2 = string_stream.Advance();
    592     int32_t c3 = utf8_stream.Advance();
    593     i++;
    594     CHECK_EQ(c0, c1);
    595     CHECK_EQ(c0, c2);
    596     CHECK_EQ(c0, c3);
    597     CHECK_EQU(i, uc16_stream.pos());
    598     CHECK_EQU(i, string_stream.pos());
    599     CHECK_EQU(i, utf8_stream.pos());
    600   }
    601   while (i > start + sub_length / 4) {
    602     // Pushback, re-read, pushback again.
    603     int32_t c0 = one_byte_source[i - 1];
    604     CHECK_EQU(i, uc16_stream.pos());
    605     CHECK_EQU(i, string_stream.pos());
    606     CHECK_EQU(i, utf8_stream.pos());
    607     uc16_stream.PushBack(c0);
    608     string_stream.PushBack(c0);
    609     utf8_stream.PushBack(c0);
    610     i--;
    611     CHECK_EQU(i, uc16_stream.pos());
    612     CHECK_EQU(i, string_stream.pos());
    613     CHECK_EQU(i, utf8_stream.pos());
    614     int32_t c1 = uc16_stream.Advance();
    615     int32_t c2 = string_stream.Advance();
    616     int32_t c3 = utf8_stream.Advance();
    617     i++;
    618     CHECK_EQU(i, uc16_stream.pos());
    619     CHECK_EQU(i, string_stream.pos());
    620     CHECK_EQU(i, utf8_stream.pos());
    621     CHECK_EQ(c0, c1);
    622     CHECK_EQ(c0, c2);
    623     CHECK_EQ(c0, c3);
    624     uc16_stream.PushBack(c0);
    625     string_stream.PushBack(c0);
    626     utf8_stream.PushBack(c0);
    627     i--;
    628     CHECK_EQU(i, uc16_stream.pos());
    629     CHECK_EQU(i, string_stream.pos());
    630     CHECK_EQU(i, utf8_stream.pos());
    631   }
    632   unsigned halfway = start + sub_length / 2;
    633   uc16_stream.SeekForward(halfway - i);
    634   string_stream.SeekForward(halfway - i);
    635   utf8_stream.SeekForward(halfway - i);
    636   i = halfway;
    637   CHECK_EQU(i, uc16_stream.pos());
    638   CHECK_EQU(i, string_stream.pos());
    639   CHECK_EQU(i, utf8_stream.pos());
    640 
    641   while (i < end) {
    642     // Read streams one char at a time
    643     CHECK_EQU(i, uc16_stream.pos());
    644     CHECK_EQU(i, string_stream.pos());
    645     CHECK_EQU(i, utf8_stream.pos());
    646     int32_t c0 = one_byte_source[i];
    647     int32_t c1 = uc16_stream.Advance();
    648     int32_t c2 = string_stream.Advance();
    649     int32_t c3 = utf8_stream.Advance();
    650     i++;
    651     CHECK_EQ(c0, c1);
    652     CHECK_EQ(c0, c2);
    653     CHECK_EQ(c0, c3);
    654     CHECK_EQU(i, uc16_stream.pos());
    655     CHECK_EQU(i, string_stream.pos());
    656     CHECK_EQU(i, utf8_stream.pos());
    657   }
    658 
    659   int32_t c1 = uc16_stream.Advance();
    660   int32_t c2 = string_stream.Advance();
    661   int32_t c3 = utf8_stream.Advance();
    662   CHECK_LT(c1, 0);
    663   CHECK_LT(c2, 0);
    664   CHECK_LT(c3, 0);
    665 }
    666 
    667 
    668 TEST(CharacterStreams) {
    669   v8::Isolate* isolate = CcTest::isolate();
    670   v8::HandleScope handles(isolate);
    671   v8::Local<v8::Context> context = v8::Context::New(isolate);
    672   v8::Context::Scope context_scope(context);
    673 
    674   TestCharacterStream("abc\0\n\r\x7f", 7);
    675   static const unsigned kBigStringSize = 4096;
    676   char buffer[kBigStringSize + 1];
    677   for (unsigned i = 0; i < kBigStringSize; i++) {
    678     buffer[i] = static_cast<char>(i & 0x7f);
    679   }
    680   TestCharacterStream(buffer, kBigStringSize);
    681 
    682   TestCharacterStream(buffer, kBigStringSize, 576, 3298);
    683 
    684   TestCharacterStream("\0", 1);
    685   TestCharacterStream("", 0);
    686 }
    687 
    688 
    689 TEST(Utf8CharacterStream) {
    690   static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
    691   static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
    692 
    693   static const int kAllUtf8CharsSize =
    694       (unibrow::Utf8::kMaxOneByteChar + 1) +
    695       (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
    696       (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
    697   static const unsigned kAllUtf8CharsSizeU =
    698       static_cast<unsigned>(kAllUtf8CharsSize);
    699 
    700   char buffer[kAllUtf8CharsSizeU];
    701   unsigned cursor = 0;
    702   for (int i = 0; i <= kMaxUC16Char; i++) {
    703     cursor += unibrow::Utf8::Encode(buffer + cursor, i,
    704                                     unibrow::Utf16::kNoPreviousCharacter, true);
    705   }
    706   CHECK(cursor == kAllUtf8CharsSizeU);
    707 
    708   i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
    709                                        kAllUtf8CharsSizeU);
    710   int32_t bad = unibrow::Utf8::kBadChar;
    711   for (int i = 0; i <= kMaxUC16Char; i++) {
    712     CHECK_EQU(i, stream.pos());
    713     int32_t c = stream.Advance();
    714     if (i >= 0xd800 && i <= 0xdfff) {
    715       CHECK_EQ(bad, c);
    716     } else {
    717       CHECK_EQ(i, c);
    718     }
    719     CHECK_EQU(i + 1, stream.pos());
    720   }
    721   for (int i = kMaxUC16Char; i >= 0; i--) {
    722     CHECK_EQU(i + 1, stream.pos());
    723     stream.PushBack(i);
    724     CHECK_EQU(i, stream.pos());
    725   }
    726   int i = 0;
    727   while (stream.pos() < kMaxUC16CharU) {
    728     CHECK_EQU(i, stream.pos());
    729     int progress = static_cast<int>(stream.SeekForward(12));
    730     i += progress;
    731     int32_t c = stream.Advance();
    732     if (i >= 0xd800 && i <= 0xdfff) {
    733       CHECK_EQ(bad, c);
    734     } else if (i <= kMaxUC16Char) {
    735       CHECK_EQ(i, c);
    736     } else {
    737       CHECK_EQ(-1, c);
    738     }
    739     i += 1;
    740     CHECK_EQU(i, stream.pos());
    741   }
    742 }
    743 
    744 #undef CHECK_EQU
    745 
    746 void TestStreamScanner(i::Utf16CharacterStream* stream,
    747                        i::Token::Value* expected_tokens,
    748                        int skip_pos = 0,  // Zero means not skipping.
    749                        int skip_to = 0) {
    750   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    751   scanner.Initialize(stream);
    752 
    753   int i = 0;
    754   do {
    755     i::Token::Value expected = expected_tokens[i];
    756     i::Token::Value actual = scanner.Next();
    757     CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
    758     if (scanner.location().end_pos == skip_pos) {
    759       scanner.SeekForward(skip_to);
    760     }
    761     i++;
    762   } while (expected_tokens[i] != i::Token::ILLEGAL);
    763 }
    764 
    765 
    766 TEST(StreamScanner) {
    767   v8::V8::Initialize();
    768 
    769   const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
    770   i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
    771                                         static_cast<unsigned>(strlen(str1)));
    772   i::Token::Value expectations1[] = {
    773       i::Token::LBRACE,
    774       i::Token::IDENTIFIER,
    775       i::Token::IDENTIFIER,
    776       i::Token::FOR,
    777       i::Token::COLON,
    778       i::Token::MUL,
    779       i::Token::DIV,
    780       i::Token::LT,
    781       i::Token::SUB,
    782       i::Token::IDENTIFIER,
    783       i::Token::EOS,
    784       i::Token::ILLEGAL
    785   };
    786   TestStreamScanner(&stream1, expectations1, 0, 0);
    787 
    788   const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
    789   i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
    790                                         static_cast<unsigned>(strlen(str2)));
    791   i::Token::Value expectations2[] = {
    792       i::Token::CASE,
    793       i::Token::DEFAULT,
    794       i::Token::CONST,
    795       i::Token::LBRACE,
    796       // Skipped part here
    797       i::Token::RBRACE,
    798       i::Token::DO,
    799       i::Token::EOS,
    800       i::Token::ILLEGAL
    801   };
    802   CHECK_EQ('{', str2[19]);
    803   CHECK_EQ('}', str2[37]);
    804   TestStreamScanner(&stream2, expectations2, 20, 37);
    805 
    806   const char* str3 = "{}}}}";
    807   i::Token::Value expectations3[] = {
    808       i::Token::LBRACE,
    809       i::Token::RBRACE,
    810       i::Token::RBRACE,
    811       i::Token::RBRACE,
    812       i::Token::RBRACE,
    813       i::Token::EOS,
    814       i::Token::ILLEGAL
    815   };
    816   // Skip zero-four RBRACEs.
    817   for (int i = 0; i <= 4; i++) {
    818      expectations3[6 - i] = i::Token::ILLEGAL;
    819      expectations3[5 - i] = i::Token::EOS;
    820      i::Utf8ToUtf16CharacterStream stream3(
    821          reinterpret_cast<const i::byte*>(str3),
    822          static_cast<unsigned>(strlen(str3)));
    823      TestStreamScanner(&stream3, expectations3, 1, 1 + i);
    824   }
    825 }
    826 
    827 
    828 void TestScanRegExp(const char* re_source, const char* expected) {
    829   i::Utf8ToUtf16CharacterStream stream(
    830        reinterpret_cast<const i::byte*>(re_source),
    831        static_cast<unsigned>(strlen(re_source)));
    832   i::HandleScope scope(CcTest::i_isolate());
    833   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
    834   scanner.Initialize(&stream);
    835 
    836   i::Token::Value start = scanner.peek();
    837   CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
    838   CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
    839   scanner.Next();  // Current token is now the regexp literal.
    840   i::Zone zone;
    841   i::AstValueFactory ast_value_factory(&zone,
    842                                        CcTest::i_isolate()->heap()->HashSeed());
    843   ast_value_factory.Internalize(CcTest::i_isolate());
    844   i::Handle<i::String> val =
    845       scanner.CurrentSymbol(&ast_value_factory)->string();
    846   i::DisallowHeapAllocation no_alloc;
    847   i::String::FlatContent content = val->GetFlatContent();
    848   CHECK(content.IsOneByte());
    849   i::Vector<const uint8_t> actual = content.ToOneByteVector();
    850   for (int i = 0; i < actual.length(); i++) {
    851     CHECK_NE('\0', expected[i]);
    852     CHECK_EQ(expected[i], actual[i]);
    853   }
    854 }
    855 
    856 
    857 TEST(RegExpScanning) {
    858   v8::V8::Initialize();
    859 
    860   // RegExp token with added garbage at the end. The scanner should only
    861   // scan the RegExp until the terminating slash just before "flipperwald".
    862   TestScanRegExp("/b/flipperwald", "b");
    863   // Incomplete escape sequences doesn't hide the terminating slash.
    864   TestScanRegExp("/\\x/flipperwald", "\\x");
    865   TestScanRegExp("/\\u/flipperwald", "\\u");
    866   TestScanRegExp("/\\u1/flipperwald", "\\u1");
    867   TestScanRegExp("/\\u12/flipperwald", "\\u12");
    868   TestScanRegExp("/\\u123/flipperwald", "\\u123");
    869   TestScanRegExp("/\\c/flipperwald", "\\c");
    870   TestScanRegExp("/\\c//flipperwald", "\\c");
    871   // Slashes inside character classes are not terminating.
    872   TestScanRegExp("/[/]/flipperwald", "[/]");
    873   TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
    874   // Incomplete escape sequences inside a character class doesn't hide
    875   // the end of the character class.
    876   TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
    877   TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
    878   TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
    879   TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
    880   TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
    881   TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
    882   TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
    883   TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
    884   // Escaped ']'s wont end the character class.
    885   TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
    886   // Escaped slashes are not terminating.
    887   TestScanRegExp("/\\//flipperwald", "\\/");
    888   // Starting with '=' works too.
    889   TestScanRegExp("/=/", "=");
    890   TestScanRegExp("/=?/", "=?");
    891 }
    892 
    893 
    894 static int Utf8LengthHelper(const char* s) {
    895   int len = i::StrLength(s);
    896   int character_length = len;
    897   for (int i = 0; i < len; i++) {
    898     unsigned char c = s[i];
    899     int input_offset = 0;
    900     int output_adjust = 0;
    901     if (c > 0x7f) {
    902       if (c < 0xc0) continue;
    903       if (c >= 0xf0) {
    904         if (c >= 0xf8) {
    905           // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
    906           // byte.
    907           continue;  // Handle first UTF-8 byte.
    908         }
    909         if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
    910           // This 4 byte sequence could have been coded as a 3 byte sequence.
    911           // Record a single kBadChar for the first byte and continue.
    912           continue;
    913         }
    914         input_offset = 3;
    915         // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
    916         character_length -= 2;
    917       } else if (c >= 0xe0) {
    918         if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
    919           // This 3 byte sequence could have been coded as a 2 byte sequence.
    920           // Record a single kBadChar for the first byte and continue.
    921           continue;
    922         }
    923         if (c == 0xed) {
    924           unsigned char d = s[i + 1];
    925           if ((d < 0x80) || (d > 0x9f)) {
    926             // This 3 byte sequence is part of a surrogate pair which is not
    927             // supported by UTF-8. Record a single kBadChar for the first byte
    928             // and continue.
    929             continue;
    930           }
    931         }
    932         input_offset = 2;
    933         // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
    934         output_adjust = 2;
    935       } else {
    936         if ((c & 0x1e) == 0) {
    937           // This 2 byte sequence could have been coded as a 1 byte sequence.
    938           // Record a single kBadChar for the first byte and continue.
    939           continue;
    940         }
    941         input_offset = 1;
    942         // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
    943         output_adjust = 1;
    944       }
    945       bool bad = false;
    946       for (int j = 1; j <= input_offset; j++) {
    947         if ((s[i + j] & 0xc0) != 0x80) {
    948           // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
    949           // which is a single UTF-16 code unit.
    950           bad = true;
    951           break;
    952         }
    953       }
    954       if (!bad) {
    955         i += input_offset;
    956         character_length -= output_adjust;
    957       }
    958     }
    959   }
    960   return character_length;
    961 }
    962 
    963 
    964 TEST(ScopeUsesArgumentsSuperThis) {
    965   static const struct {
    966     const char* prefix;
    967     const char* suffix;
    968   } surroundings[] = {
    969     { "function f() {", "}" },
    970     { "var f = () => {", "};" },
    971     { "class C { constructor() {", "} }" },
    972   };
    973 
    974   enum Expected {
    975     NONE = 0,
    976     ARGUMENTS = 1,
    977     SUPER_PROPERTY = 1 << 1,
    978     THIS = 1 << 2,
    979     EVAL = 1 << 4
    980   };
    981 
    982   // clang-format off
    983   static const struct {
    984     const char* body;
    985     int expected;
    986   } source_data[] = {
    987     {"", NONE},
    988     {"return this", THIS},
    989     {"return arguments", ARGUMENTS},
    990     {"return super.x", SUPER_PROPERTY},
    991     {"return arguments[0]", ARGUMENTS},
    992     {"return this + arguments[0]", ARGUMENTS | THIS},
    993     {"return this + arguments[0] + super.x",
    994      ARGUMENTS | SUPER_PROPERTY | THIS},
    995     {"return x => this + x", THIS},
    996     {"return x => super.f() + x", SUPER_PROPERTY},
    997     {"this.foo = 42;", THIS},
    998     {"this.foo();", THIS},
    999     {"if (foo()) { this.f() }", THIS},
   1000     {"if (foo()) { super.f() }", SUPER_PROPERTY},
   1001     {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
   1002     {"while (true) { this.f() }", THIS},
   1003     {"while (true) { super.f() }", SUPER_PROPERTY},
   1004     {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
   1005     // Multiple nesting levels must work as well.
   1006     {"while (true) { while (true) { while (true) return this } }", THIS},
   1007     {"while (true) { while (true) { while (true) return super.f() } }",
   1008      SUPER_PROPERTY},
   1009     {"if (1) { return () => { while (true) new this() } }", THIS},
   1010     {"return function (x) { return this + x }", NONE},
   1011     {"return { m(x) { return super.m() + x } }", NONE},
   1012     {"var x = function () { this.foo = 42 };", NONE},
   1013     {"var x = { m() { super.foo = 42 } };", NONE},
   1014     {"if (1) { return function () { while (true) new this() } }", NONE},
   1015     {"if (1) { return { m() { while (true) super.m() } } }", NONE},
   1016     {"return function (x) { return () => this }", NONE},
   1017     {"return { m(x) { return () => super.m() } }", NONE},
   1018     // Flags must be correctly set when using block scoping.
   1019     {"\"use strict\"; while (true) { let x; this, arguments; }",
   1020      THIS},
   1021     {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
   1022      SUPER_PROPERTY | THIS},
   1023     {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
   1024     {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
   1025     {"\"use strict\"; if (1) {"
   1026      "  let x; return { m() { return this + super.m() + arguments } }"
   1027      "}",
   1028      NONE},
   1029     {"eval(42)", EVAL},
   1030     {"if (1) { eval(42) }", EVAL},
   1031     {"eval('super.x')", EVAL},
   1032     {"eval('this.x')", EVAL},
   1033     {"eval('arguments')", EVAL},
   1034   };
   1035   // clang-format on
   1036 
   1037   i::Isolate* isolate = CcTest::i_isolate();
   1038   i::Factory* factory = isolate->factory();
   1039 
   1040   v8::HandleScope handles(CcTest::isolate());
   1041   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   1042   v8::Context::Scope context_scope(context);
   1043 
   1044   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   1045                                         128 * 1024);
   1046 
   1047   for (unsigned j = 0; j < arraysize(surroundings); ++j) {
   1048     for (unsigned i = 0; i < arraysize(source_data); ++i) {
   1049       // Super property is only allowed in constructor and method.
   1050       if (((source_data[i].expected & SUPER_PROPERTY) ||
   1051            (source_data[i].expected == NONE)) && j != 2) {
   1052         continue;
   1053       }
   1054       int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
   1055                              i::StrLength(surroundings[j].suffix) +
   1056                              i::StrLength(source_data[i].body);
   1057       i::ScopedVector<char> program(kProgramByteSize + 1);
   1058       i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
   1059                   source_data[i].body, surroundings[j].suffix);
   1060       i::Handle<i::String> source =
   1061           factory->NewStringFromUtf8(i::CStrVector(program.start()))
   1062               .ToHandleChecked();
   1063       i::Handle<i::Script> script = factory->NewScript(source);
   1064       i::Zone zone;
   1065       i::ParseInfo info(&zone, script);
   1066       i::Parser parser(&info);
   1067       parser.set_allow_harmony_sloppy(true);
   1068       info.set_global();
   1069       CHECK(parser.Parse(&info));
   1070       CHECK(i::Rewriter::Rewrite(&info));
   1071       CHECK(i::Scope::Analyze(&info));
   1072       CHECK(info.literal() != NULL);
   1073 
   1074       i::Scope* script_scope = info.literal()->scope();
   1075       CHECK(script_scope->is_script_scope());
   1076       CHECK_EQ(1, script_scope->inner_scopes()->length());
   1077 
   1078       i::Scope* scope = script_scope->inner_scopes()->at(0);
   1079       // Adjust for constructor scope.
   1080       if (j == 2) {
   1081         CHECK_EQ(1, scope->inner_scopes()->length());
   1082         scope = scope->inner_scopes()->at(0);
   1083       }
   1084       CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
   1085                scope->uses_arguments());
   1086       CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
   1087                scope->uses_super_property());
   1088       if ((source_data[i].expected & THIS) != 0) {
   1089         // Currently the is_used() flag is conservative; all variables in a
   1090         // script scope are marked as used.
   1091         CHECK(
   1092             scope->Lookup(info.ast_value_factory()->this_string())->is_used());
   1093       }
   1094       CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval());
   1095     }
   1096   }
   1097 }
   1098 
   1099 
   1100 static void CheckParsesToNumber(const char* source, bool with_dot) {
   1101   v8::V8::Initialize();
   1102   HandleAndZoneScope handles;
   1103 
   1104   i::Isolate* isolate = CcTest::i_isolate();
   1105   i::Factory* factory = isolate->factory();
   1106 
   1107   std::string full_source = "function f() { return ";
   1108   full_source += source;
   1109   full_source += "; }";
   1110 
   1111   i::Handle<i::String> source_code =
   1112       factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
   1113           .ToHandleChecked();
   1114 
   1115   i::Handle<i::Script> script = factory->NewScript(source_code);
   1116 
   1117   i::ParseInfo info(handles.main_zone(), script);
   1118   i::Parser parser(&info);
   1119   parser.set_allow_harmony_sloppy(true);
   1120   info.set_global();
   1121   info.set_lazy(false);
   1122   info.set_allow_lazy_parsing(false);
   1123   info.set_toplevel(true);
   1124 
   1125   i::CompilationInfo compilation_info(&info);
   1126   CHECK(i::Compiler::ParseAndAnalyze(&info));
   1127 
   1128   CHECK(info.scope()->declarations()->length() == 1);
   1129   i::FunctionLiteral* fun =
   1130       info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
   1131   CHECK(fun->body()->length() == 1);
   1132   CHECK(fun->body()->at(0)->IsReturnStatement());
   1133   i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
   1134   i::Literal* lit = ret->expression()->AsLiteral();
   1135   if (lit != NULL) {
   1136     const i::AstValue* val = lit->raw_value();
   1137     CHECK(with_dot == val->ContainsDot());
   1138   } else if (with_dot) {
   1139     i::BinaryOperation* bin = ret->expression()->AsBinaryOperation();
   1140     CHECK(bin != NULL);
   1141     CHECK_EQ(i::Token::MUL, bin->op());
   1142     i::Literal* rlit = bin->right()->AsLiteral();
   1143     const i::AstValue* val = rlit->raw_value();
   1144     CHECK(with_dot == val->ContainsDot());
   1145     CHECK_EQ(1.0, val->AsNumber());
   1146   }
   1147 }
   1148 
   1149 
   1150 TEST(ParseNumbers) {
   1151   CheckParsesToNumber("1.", true);
   1152   CheckParsesToNumber("1.34", true);
   1153   CheckParsesToNumber("134", false);
   1154   CheckParsesToNumber("134e44", false);
   1155   CheckParsesToNumber("134.e44", true);
   1156   CheckParsesToNumber("134.44e44", true);
   1157   CheckParsesToNumber(".44", true);
   1158 
   1159   CheckParsesToNumber("-1.", true);
   1160   CheckParsesToNumber("-1.0", true);
   1161   CheckParsesToNumber("-1.34", true);
   1162   CheckParsesToNumber("-134", false);
   1163   CheckParsesToNumber("-134e44", false);
   1164   CheckParsesToNumber("-134.e44", true);
   1165   CheckParsesToNumber("-134.44e44", true);
   1166   CheckParsesToNumber("-.44", true);
   1167 
   1168   CheckParsesToNumber("+x", true);
   1169 }
   1170 
   1171 
   1172 TEST(ScopePositions) {
   1173   // Test the parser for correctly setting the start and end positions
   1174   // of a scope. We check the scope positions of exactly one scope
   1175   // nested in the global scope of a program. 'inner source' is the
   1176   // source code that determines the part of the source belonging
   1177   // to the nested scope. 'outer_prefix' and 'outer_suffix' are
   1178   // parts of the source that belong to the global scope.
   1179   struct SourceData {
   1180     const char* outer_prefix;
   1181     const char* inner_source;
   1182     const char* outer_suffix;
   1183     i::ScopeType scope_type;
   1184     i::LanguageMode language_mode;
   1185   };
   1186 
   1187   const SourceData source_data[] = {
   1188     { "  with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
   1189     { "  with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
   1190     { "  with ({}) ", "{\n"
   1191       "    block;\n"
   1192       "  }", "\n"
   1193       "  more;", i::WITH_SCOPE, i::SLOPPY },
   1194     { "  with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
   1195     { "  with ({}) ", "statement", "\n"
   1196       "  more;", i::WITH_SCOPE, i::SLOPPY },
   1197     { "  with ({})\n"
   1198       "    ", "statement;", "\n"
   1199       "  more;", i::WITH_SCOPE, i::SLOPPY },
   1200     { "  try {} catch ", "(e) { block; }", " more;",
   1201       i::CATCH_SCOPE, i::SLOPPY },
   1202     { "  try {} catch ", "(e) { block; }", "; more;",
   1203       i::CATCH_SCOPE, i::SLOPPY },
   1204     { "  try {} catch ", "(e) {\n"
   1205       "    block;\n"
   1206       "  }", "\n"
   1207       "  more;", i::CATCH_SCOPE, i::SLOPPY },
   1208     { "  try {} catch ", "(e) { block; }", " finally { block; } more;",
   1209       i::CATCH_SCOPE, i::SLOPPY },
   1210     { "  start;\n"
   1211       "  ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
   1212     { "  start;\n"
   1213       "  ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
   1214     { "  start;\n"
   1215       "  ", "{\n"
   1216       "    let block;\n"
   1217       "  }", "\n"
   1218       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1219     { "  start;\n"
   1220       "  function fun", "(a,b) { infunction; }", " more;",
   1221       i::FUNCTION_SCOPE, i::SLOPPY },
   1222     { "  start;\n"
   1223       "  function fun", "(a,b) {\n"
   1224       "    infunction;\n"
   1225       "  }", "\n"
   1226       "  more;", i::FUNCTION_SCOPE, i::SLOPPY },
   1227     { "  start;\n", "(a,b) => a + b", "; more;",
   1228       i::FUNCTION_SCOPE, i::SLOPPY },
   1229     { "  start;\n", "(a,b) => { return a+b; }", "\nmore;",
   1230       i::FUNCTION_SCOPE, i::SLOPPY },
   1231     { "  start;\n"
   1232       "  (function fun", "(a,b) { infunction; }", ")();",
   1233       i::FUNCTION_SCOPE, i::SLOPPY },
   1234     { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
   1235       i::BLOCK_SCOPE, i::STRICT },
   1236     { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
   1237       i::BLOCK_SCOPE, i::STRICT },
   1238     { "  for ", "(let x = 1 ; x < 10; ++ x) {\n"
   1239       "    block;\n"
   1240       "  }", "\n"
   1241       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1242     { "  for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
   1243       i::BLOCK_SCOPE, i::STRICT },
   1244     { "  for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
   1245       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1246     { "  for ", "(let x = 1 ; x < 10; ++ x)\n"
   1247       "    statement;", "\n"
   1248       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1249     { "  for ", "(let x in {}) { block; }", " more;",
   1250       i::BLOCK_SCOPE, i::STRICT },
   1251     { "  for ", "(let x in {}) { block; }", "; more;",
   1252       i::BLOCK_SCOPE, i::STRICT },
   1253     { "  for ", "(let x in {}) {\n"
   1254       "    block;\n"
   1255       "  }", "\n"
   1256       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1257     { "  for ", "(let x in {}) statement;", " more;",
   1258       i::BLOCK_SCOPE, i::STRICT },
   1259     { "  for ", "(let x in {}) statement", "\n"
   1260       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1261     { "  for ", "(let x in {})\n"
   1262       "    statement;", "\n"
   1263       "  more;", i::BLOCK_SCOPE, i::STRICT },
   1264     // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
   1265     // the preparser off in terms of byte offsets.
   1266     // 6 byte encoding.
   1267     { "  'foo\355\240\201\355\260\211';\n"
   1268       "  (function fun", "(a,b) { infunction; }", ")();",
   1269       i::FUNCTION_SCOPE, i::SLOPPY },
   1270     // 4 byte encoding.
   1271     { "  'foo\360\220\220\212';\n"
   1272       "  (function fun", "(a,b) { infunction; }", ")();",
   1273       i::FUNCTION_SCOPE, i::SLOPPY },
   1274     // 3 byte encoding of \u0fff.
   1275     { "  'foo\340\277\277';\n"
   1276       "  (function fun", "(a,b) { infunction; }", ")();",
   1277       i::FUNCTION_SCOPE, i::SLOPPY },
   1278     // Broken 6 byte encoding with missing last byte.
   1279     { "  'foo\355\240\201\355\211';\n"
   1280       "  (function fun", "(a,b) { infunction; }", ")();",
   1281       i::FUNCTION_SCOPE, i::SLOPPY },
   1282     // Broken 3 byte encoding of \u0fff with missing last byte.
   1283     { "  'foo\340\277';\n"
   1284       "  (function fun", "(a,b) { infunction; }", ")();",
   1285       i::FUNCTION_SCOPE, i::SLOPPY },
   1286     // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
   1287     { "  'foo\340';\n"
   1288       "  (function fun", "(a,b) { infunction; }", ")();",
   1289       i::FUNCTION_SCOPE, i::SLOPPY },
   1290     // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
   1291     { "  'foo\340\203\277';\n"
   1292       "  (function fun", "(a,b) { infunction; }", ")();",
   1293       i::FUNCTION_SCOPE, i::SLOPPY },
   1294     // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
   1295     { "  'foo\340\201\277';\n"
   1296       "  (function fun", "(a,b) { infunction; }", ")();",
   1297       i::FUNCTION_SCOPE, i::SLOPPY },
   1298     // Unpaired lead surrogate.
   1299     { "  'foo\355\240\201';\n"
   1300       "  (function fun", "(a,b) { infunction; }", ")();",
   1301       i::FUNCTION_SCOPE, i::SLOPPY },
   1302     // Unpaired lead surrogate where following code point is a 3 byte sequence.
   1303     { "  'foo\355\240\201\340\277\277';\n"
   1304       "  (function fun", "(a,b) { infunction; }", ")();",
   1305       i::FUNCTION_SCOPE, i::SLOPPY },
   1306     // Unpaired lead surrogate where following code point is a 4 byte encoding
   1307     // of a trail surrogate.
   1308     { "  'foo\355\240\201\360\215\260\211';\n"
   1309       "  (function fun", "(a,b) { infunction; }", ")();",
   1310       i::FUNCTION_SCOPE, i::SLOPPY },
   1311     // Unpaired trail surrogate.
   1312     { "  'foo\355\260\211';\n"
   1313       "  (function fun", "(a,b) { infunction; }", ")();",
   1314       i::FUNCTION_SCOPE, i::SLOPPY },
   1315     // 2 byte encoding of \u00ff.
   1316     { "  'foo\303\277';\n"
   1317       "  (function fun", "(a,b) { infunction; }", ")();",
   1318       i::FUNCTION_SCOPE, i::SLOPPY },
   1319     // Broken 2 byte encoding of \u00ff with missing last byte.
   1320     { "  'foo\303';\n"
   1321       "  (function fun", "(a,b) { infunction; }", ")();",
   1322       i::FUNCTION_SCOPE, i::SLOPPY },
   1323     // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
   1324     { "  'foo\301\277';\n"
   1325       "  (function fun", "(a,b) { infunction; }", ")();",
   1326       i::FUNCTION_SCOPE, i::SLOPPY },
   1327     // Illegal 5 byte encoding.
   1328     { "  'foo\370\277\277\277\277';\n"
   1329       "  (function fun", "(a,b) { infunction; }", ")();",
   1330       i::FUNCTION_SCOPE, i::SLOPPY },
   1331     // Illegal 6 byte encoding.
   1332     { "  'foo\374\277\277\277\277\277';\n"
   1333       "  (function fun", "(a,b) { infunction; }", ")();",
   1334       i::FUNCTION_SCOPE, i::SLOPPY },
   1335     // Illegal 0xfe byte
   1336     { "  'foo\376\277\277\277\277\277\277';\n"
   1337       "  (function fun", "(a,b) { infunction; }", ")();",
   1338       i::FUNCTION_SCOPE, i::SLOPPY },
   1339     // Illegal 0xff byte
   1340     { "  'foo\377\277\277\277\277\277\277\277';\n"
   1341       "  (function fun", "(a,b) { infunction; }", ")();",
   1342       i::FUNCTION_SCOPE, i::SLOPPY },
   1343     { "  'foo';\n"
   1344       "  (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
   1345       i::FUNCTION_SCOPE, i::SLOPPY },
   1346     { "  'foo';\n"
   1347       "  (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
   1348       i::FUNCTION_SCOPE, i::SLOPPY },
   1349     { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
   1350   };
   1351 
   1352   i::Isolate* isolate = CcTest::i_isolate();
   1353   i::Factory* factory = isolate->factory();
   1354 
   1355   v8::HandleScope handles(CcTest::isolate());
   1356   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   1357   v8::Context::Scope context_scope(context);
   1358 
   1359   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   1360                                         128 * 1024);
   1361 
   1362   for (int i = 0; source_data[i].outer_prefix; i++) {
   1363     int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
   1364     int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
   1365     int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
   1366     int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
   1367     int kInnerByteLen = i::StrLength(source_data[i].inner_source);
   1368     int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
   1369     int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
   1370     int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
   1371     i::ScopedVector<char> program(kProgramByteSize + 1);
   1372     i::SNPrintF(program, "%s%s%s",
   1373                          source_data[i].outer_prefix,
   1374                          source_data[i].inner_source,
   1375                          source_data[i].outer_suffix);
   1376 
   1377     // Parse program source.
   1378     i::Handle<i::String> source = factory->NewStringFromUtf8(
   1379         i::CStrVector(program.start())).ToHandleChecked();
   1380     CHECK_EQ(source->length(), kProgramSize);
   1381     i::Handle<i::Script> script = factory->NewScript(source);
   1382     i::Zone zone;
   1383     i::ParseInfo info(&zone, script);
   1384     i::Parser parser(&info);
   1385     parser.set_allow_lazy(true);
   1386     info.set_global();
   1387     info.set_language_mode(source_data[i].language_mode);
   1388     parser.Parse(&info);
   1389     CHECK(info.literal() != NULL);
   1390 
   1391     // Check scope types and positions.
   1392     i::Scope* scope = info.literal()->scope();
   1393     CHECK(scope->is_script_scope());
   1394     CHECK_EQ(scope->start_position(), 0);
   1395     CHECK_EQ(scope->end_position(), kProgramSize);
   1396     CHECK_EQ(scope->inner_scopes()->length(), 1);
   1397 
   1398     i::Scope* inner_scope = scope->inner_scopes()->at(0);
   1399     CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
   1400     CHECK_EQ(inner_scope->start_position(), kPrefixLen);
   1401     // The end position of a token is one position after the last
   1402     // character belonging to that token.
   1403     CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
   1404   }
   1405 }
   1406 
   1407 
   1408 TEST(DiscardFunctionBody) {
   1409   // Test that inner function bodies are discarded if possible.
   1410   // See comments in ParseFunctionLiteral in parser.cc.
   1411   const char* discard_sources[] = {
   1412       "(function f() { function g() { var a; } })();",
   1413       "(function f() { function g() { { function h() { } } } })();",
   1414       /* TODO(conradw): In future it may be possible to apply this optimisation
   1415        * to these productions.
   1416       "(function f() { 0, function g() { var a; } })();",
   1417       "(function f() { 0, { g() { var a; } } })();",
   1418       "(function f() { 0, class c { g() { var a; } } })();", */
   1419       NULL};
   1420 
   1421   i::Isolate* isolate = CcTest::i_isolate();
   1422   i::Factory* factory = isolate->factory();
   1423   v8::HandleScope handles(CcTest::isolate());
   1424   i::FunctionLiteral* function;
   1425 
   1426   for (int i = 0; discard_sources[i]; i++) {
   1427     const char* source = discard_sources[i];
   1428     i::Handle<i::String> source_code =
   1429         factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
   1430     i::Handle<i::Script> script = factory->NewScript(source_code);
   1431     i::Zone zone;
   1432     i::ParseInfo info(&zone, script);
   1433     info.set_allow_lazy_parsing();
   1434     i::Parser parser(&info);
   1435     parser.set_allow_harmony_sloppy(true);
   1436     parser.Parse(&info);
   1437     function = info.literal();
   1438     CHECK_NOT_NULL(function);
   1439     CHECK_NOT_NULL(function->body());
   1440     CHECK_EQ(1, function->body()->length());
   1441     i::FunctionLiteral* inner =
   1442         function->body()->first()->AsExpressionStatement()->expression()->
   1443         AsCall()->expression()->AsFunctionLiteral();
   1444     i::Scope* inner_scope = inner->scope();
   1445     i::FunctionLiteral* fun = nullptr;
   1446     if (inner_scope->declarations()->length() > 1) {
   1447       fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun();
   1448     } else {
   1449       // TODO(conradw): This path won't be hit until the other test cases can be
   1450       // uncommented.
   1451       UNREACHABLE();
   1452       CHECK_NOT_NULL(inner->body());
   1453       CHECK_GE(2, inner->body()->length());
   1454       i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
   1455                            expression()->AsBinaryOperation()->right();
   1456       if (exp->IsFunctionLiteral()) {
   1457         fun = exp->AsFunctionLiteral();
   1458       } else if (exp->IsObjectLiteral()) {
   1459         fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
   1460               AsFunctionLiteral();
   1461       } else {
   1462         fun = exp->AsClassLiteral()->properties()->at(0)->value()->
   1463               AsFunctionLiteral();
   1464       }
   1465     }
   1466     CHECK_NULL(fun->body());
   1467   }
   1468 }
   1469 
   1470 
   1471 const char* ReadString(unsigned* start) {
   1472   int length = start[0];
   1473   char* result = i::NewArray<char>(length + 1);
   1474   for (int i = 0; i < length; i++) {
   1475     result[i] = start[i + 1];
   1476   }
   1477   result[length] = '\0';
   1478   return result;
   1479 }
   1480 
   1481 
   1482 i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
   1483   i::Isolate* isolate = CcTest::i_isolate();
   1484   int message = data[i::PreparseDataConstants::kMessageTemplatePos];
   1485   int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
   1486   i::Handle<i::Object> arg_object;
   1487   if (arg_count == 1) {
   1488     // Position after text found by skipping past length field and
   1489     // length field content words.
   1490     const char* arg =
   1491         ReadString(&data[i::PreparseDataConstants::kMessageArgPos]);
   1492     arg_object = v8::Utils::OpenHandle(*v8_str(arg));
   1493     i::DeleteArray(arg);
   1494   } else {
   1495     CHECK_EQ(0, arg_count);
   1496     arg_object = isolate->factory()->undefined_value();
   1497   }
   1498 
   1499   data.Dispose();
   1500   return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
   1501 }
   1502 
   1503 
   1504 enum ParserFlag {
   1505   kAllowLazy,
   1506   kAllowNatives,
   1507   kAllowHarmonyDefaultParameters,
   1508   kAllowHarmonySloppy,
   1509   kAllowHarmonySloppyLet,
   1510   kAllowHarmonyDestructuring,
   1511   kAllowHarmonyDestructuringAssignment,
   1512   kAllowHarmonyNewTarget,
   1513   kAllowStrongMode,
   1514   kNoLegacyConst
   1515 };
   1516 
   1517 
   1518 enum ParserSyncTestResult {
   1519   kSuccessOrError,
   1520   kSuccess,
   1521   kError
   1522 };
   1523 
   1524 template <typename Traits>
   1525 void SetParserFlags(i::ParserBase<Traits>* parser,
   1526                     i::EnumSet<ParserFlag> flags) {
   1527   parser->set_allow_lazy(flags.Contains(kAllowLazy));
   1528   parser->set_allow_natives(flags.Contains(kAllowNatives));
   1529   parser->set_allow_harmony_default_parameters(
   1530       flags.Contains(kAllowHarmonyDefaultParameters));
   1531   parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
   1532   parser->set_allow_harmony_sloppy_let(flags.Contains(kAllowHarmonySloppyLet));
   1533   parser->set_allow_harmony_destructuring_bind(
   1534       flags.Contains(kAllowHarmonyDestructuring));
   1535   parser->set_allow_harmony_destructuring_assignment(
   1536       flags.Contains(kAllowHarmonyDestructuringAssignment));
   1537   parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
   1538   parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst));
   1539 }
   1540 
   1541 
   1542 void TestParserSyncWithFlags(i::Handle<i::String> source,
   1543                              i::EnumSet<ParserFlag> flags,
   1544                              ParserSyncTestResult result,
   1545                              bool is_module = false) {
   1546   i::Isolate* isolate = CcTest::i_isolate();
   1547   i::Factory* factory = isolate->factory();
   1548 
   1549   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
   1550   int preparser_materialized_literals = -1;
   1551   int parser_materialized_literals = -2;
   1552   bool test_preparser = !is_module;
   1553 
   1554   // Preparse the data.
   1555   i::CompleteParserRecorder log;
   1556   if (test_preparser) {
   1557     i::Scanner scanner(isolate->unicode_cache());
   1558     i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
   1559     i::Zone zone;
   1560     i::AstValueFactory ast_value_factory(
   1561         &zone, CcTest::i_isolate()->heap()->HashSeed());
   1562     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
   1563                            stack_limit);
   1564     SetParserFlags(&preparser, flags);
   1565     scanner.Initialize(&stream);
   1566     i::PreParser::PreParseResult result = preparser.PreParseProgram(
   1567         &preparser_materialized_literals);
   1568     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
   1569   }
   1570   bool preparse_error = log.HasError();
   1571 
   1572   // Parse the data
   1573   i::FunctionLiteral* function;
   1574   {
   1575     i::Handle<i::Script> script = factory->NewScript(source);
   1576     i::Zone zone;
   1577     i::ParseInfo info(&zone, script);
   1578     i::Parser parser(&info);
   1579     SetParserFlags(&parser, flags);
   1580     if (is_module) {
   1581       info.set_module();
   1582     } else {
   1583       info.set_global();
   1584     }
   1585     parser.Parse(&info);
   1586     function = info.literal();
   1587     if (function) {
   1588       parser_materialized_literals = function->materialized_literal_count();
   1589     }
   1590   }
   1591 
   1592   // Check that preparsing fails iff parsing fails.
   1593   if (function == NULL) {
   1594     // Extract exception from the parser.
   1595     CHECK(isolate->has_pending_exception());
   1596     i::Handle<i::JSObject> exception_handle(
   1597         i::JSObject::cast(isolate->pending_exception()));
   1598     i::Handle<i::String> message_string =
   1599         i::Handle<i::String>::cast(i::Object::GetProperty(
   1600             isolate, exception_handle, "message").ToHandleChecked());
   1601 
   1602     if (result == kSuccess) {
   1603       v8::base::OS::Print(
   1604           "Parser failed on:\n"
   1605           "\t%s\n"
   1606           "with error:\n"
   1607           "\t%s\n"
   1608           "However, we expected no error.",
   1609           source->ToCString().get(), message_string->ToCString().get());
   1610       CHECK(false);
   1611     }
   1612 
   1613     if (test_preparser && !preparse_error) {
   1614       v8::base::OS::Print(
   1615           "Parser failed on:\n"
   1616           "\t%s\n"
   1617           "with error:\n"
   1618           "\t%s\n"
   1619           "However, the preparser succeeded",
   1620           source->ToCString().get(), message_string->ToCString().get());
   1621       CHECK(false);
   1622     }
   1623     // Check that preparser and parser produce the same error.
   1624     if (test_preparser) {
   1625       i::Handle<i::String> preparser_message =
   1626           FormatMessage(log.ErrorMessageData());
   1627       if (!i::String::Equals(message_string, preparser_message)) {
   1628         v8::base::OS::Print(
   1629             "Expected parser and preparser to produce the same error on:\n"
   1630             "\t%s\n"
   1631             "However, found the following error messages\n"
   1632             "\tparser:    %s\n"
   1633             "\tpreparser: %s\n",
   1634             source->ToCString().get(), message_string->ToCString().get(),
   1635             preparser_message->ToCString().get());
   1636         CHECK(false);
   1637       }
   1638     }
   1639   } else if (test_preparser && preparse_error) {
   1640     v8::base::OS::Print(
   1641         "Preparser failed on:\n"
   1642         "\t%s\n"
   1643         "with error:\n"
   1644         "\t%s\n"
   1645         "However, the parser succeeded",
   1646         source->ToCString().get(),
   1647         FormatMessage(log.ErrorMessageData())->ToCString().get());
   1648     CHECK(false);
   1649   } else if (result == kError) {
   1650     v8::base::OS::Print(
   1651         "Expected error on:\n"
   1652         "\t%s\n"
   1653         "However, parser and preparser succeeded",
   1654         source->ToCString().get());
   1655     CHECK(false);
   1656   } else if (test_preparser &&
   1657              preparser_materialized_literals != parser_materialized_literals) {
   1658     v8::base::OS::Print(
   1659         "Preparser materialized literals (%d) differ from Parser materialized "
   1660         "literals (%d) on:\n"
   1661         "\t%s\n"
   1662         "However, parser and preparser succeeded",
   1663         preparser_materialized_literals, parser_materialized_literals,
   1664         source->ToCString().get());
   1665     CHECK(false);
   1666   }
   1667 }
   1668 
   1669 
   1670 void TestParserSync(const char* source, const ParserFlag* varying_flags,
   1671                     size_t varying_flags_length,
   1672                     ParserSyncTestResult result = kSuccessOrError,
   1673                     const ParserFlag* always_true_flags = NULL,
   1674                     size_t always_true_flags_length = 0,
   1675                     const ParserFlag* always_false_flags = NULL,
   1676                     size_t always_false_flags_length = 0,
   1677                     bool is_module = false) {
   1678   i::Handle<i::String> str =
   1679       CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
   1680   for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
   1681     i::EnumSet<ParserFlag> flags;
   1682     for (size_t flag_index = 0; flag_index < varying_flags_length;
   1683          ++flag_index) {
   1684       if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
   1685     }
   1686     for (size_t flag_index = 0; flag_index < always_true_flags_length;
   1687          ++flag_index) {
   1688       flags.Add(always_true_flags[flag_index]);
   1689     }
   1690     for (size_t flag_index = 0; flag_index < always_false_flags_length;
   1691          ++flag_index) {
   1692       flags.Remove(always_false_flags[flag_index]);
   1693     }
   1694     TestParserSyncWithFlags(str, flags, result, is_module);
   1695   }
   1696 }
   1697 
   1698 
   1699 TEST(ParserSync) {
   1700   const char* context_data[][2] = {
   1701     { "", "" },
   1702     { "{", "}" },
   1703     { "if (true) ", " else {}" },
   1704     { "if (true) {} else ", "" },
   1705     { "if (true) ", "" },
   1706     { "do ", " while (false)" },
   1707     { "while (false) ", "" },
   1708     { "for (;;) ", "" },
   1709     { "with ({})", "" },
   1710     { "switch (12) { case 12: ", "}" },
   1711     { "switch (12) { default: ", "}" },
   1712     { "switch (12) { ", "case 12: }" },
   1713     { "label2: ", "" },
   1714     { NULL, NULL }
   1715   };
   1716 
   1717   const char* statement_data[] = {
   1718     "{}",
   1719     "var x",
   1720     "var x = 1",
   1721     "const x",
   1722     "const x = 1",
   1723     ";",
   1724     "12",
   1725     "if (false) {} else ;",
   1726     "if (false) {} else {}",
   1727     "if (false) {} else 12",
   1728     "if (false) ;",
   1729     "if (false) {}",
   1730     "if (false) 12",
   1731     "do {} while (false)",
   1732     "for (;;) ;",
   1733     "for (;;) {}",
   1734     "for (;;) 12",
   1735     "continue",
   1736     "continue label",
   1737     "continue\nlabel",
   1738     "break",
   1739     "break label",
   1740     "break\nlabel",
   1741     // TODO(marja): activate once parsing 'return' is merged into ParserBase.
   1742     // "return",
   1743     // "return  12",
   1744     // "return\n12",
   1745     "with ({}) ;",
   1746     "with ({}) {}",
   1747     "with ({}) 12",
   1748     "switch ({}) { default: }",
   1749     "label3: ",
   1750     "throw",
   1751     "throw  12",
   1752     "throw\n12",
   1753     "try {} catch(e) {}",
   1754     "try {} finally {}",
   1755     "try {} catch(e) {} finally {}",
   1756     "debugger",
   1757     NULL
   1758   };
   1759 
   1760   const char* termination_data[] = {
   1761     "",
   1762     ";",
   1763     "\n",
   1764     ";\n",
   1765     "\n;",
   1766     NULL
   1767   };
   1768 
   1769   v8::HandleScope handles(CcTest::isolate());
   1770   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   1771   v8::Context::Scope context_scope(context);
   1772 
   1773   CcTest::i_isolate()->stack_guard()->SetStackLimit(
   1774       i::GetCurrentStackPosition() - 128 * 1024);
   1775 
   1776   for (int i = 0; context_data[i][0] != NULL; ++i) {
   1777     for (int j = 0; statement_data[j] != NULL; ++j) {
   1778       for (int k = 0; termination_data[k] != NULL; ++k) {
   1779         int kPrefixLen = i::StrLength(context_data[i][0]);
   1780         int kStatementLen = i::StrLength(statement_data[j]);
   1781         int kTerminationLen = i::StrLength(termination_data[k]);
   1782         int kSuffixLen = i::StrLength(context_data[i][1]);
   1783         int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
   1784             + kSuffixLen + i::StrLength("label: for (;;) {  }");
   1785 
   1786         // Plug the source code pieces together.
   1787         i::ScopedVector<char> program(kProgramSize + 1);
   1788         int length = i::SNPrintF(program,
   1789             "label: for (;;) { %s%s%s%s }",
   1790             context_data[i][0],
   1791             statement_data[j],
   1792             termination_data[k],
   1793             context_data[i][1]);
   1794         CHECK(length == kProgramSize);
   1795         TestParserSync(program.start(), NULL, 0);
   1796       }
   1797     }
   1798   }
   1799 
   1800   // Neither Harmony numeric literals nor our natives syntax have any
   1801   // interaction with the flags above, so test these separately to reduce
   1802   // the combinatorial explosion.
   1803   TestParserSync("0o1234", NULL, 0);
   1804   TestParserSync("0b1011", NULL, 0);
   1805 
   1806   static const ParserFlag flags3[] = { kAllowNatives };
   1807   TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
   1808 }
   1809 
   1810 
   1811 TEST(StrictOctal) {
   1812   // Test that syntax error caused by octal literal is reported correctly as
   1813   // such (issue 2220).
   1814   v8::V8::Initialize();
   1815   v8::HandleScope scope(CcTest::isolate());
   1816   v8::Context::Scope context_scope(
   1817       v8::Context::New(CcTest::isolate()));
   1818   v8::TryCatch try_catch(CcTest::isolate());
   1819   const char* script =
   1820       "\"use strict\";       \n"
   1821       "a = function() {      \n"
   1822       "  b = function() {    \n"
   1823       "    01;               \n"
   1824       "  };                  \n"
   1825       "};                    \n";
   1826   v8_compile(v8_str(script));
   1827   CHECK(try_catch.HasCaught());
   1828   v8::String::Utf8Value exception(try_catch.Exception());
   1829   CHECK_EQ(0,
   1830            strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
   1831                   *exception));
   1832 }
   1833 
   1834 
   1835 void RunParserSyncTest(const char* context_data[][2],
   1836                        const char* statement_data[],
   1837                        ParserSyncTestResult result,
   1838                        const ParserFlag* flags = NULL, int flags_len = 0,
   1839                        const ParserFlag* always_true_flags = NULL,
   1840                        int always_true_len = 0,
   1841                        const ParserFlag* always_false_flags = NULL,
   1842                        int always_false_len = 0, bool is_module = false) {
   1843   v8::HandleScope handles(CcTest::isolate());
   1844   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   1845   v8::Context::Scope context_scope(context);
   1846 
   1847   CcTest::i_isolate()->stack_guard()->SetStackLimit(
   1848       i::GetCurrentStackPosition() - 128 * 1024);
   1849 
   1850   // Experimental feature flags should not go here; pass the flags as
   1851   // always_true_flags if the test needs them.
   1852   static const ParserFlag default_flags[] = {
   1853     kAllowLazy,
   1854     kAllowNatives,
   1855   };
   1856   ParserFlag* generated_flags = NULL;
   1857   if (flags == NULL) {
   1858     flags = default_flags;
   1859     flags_len = arraysize(default_flags);
   1860     if (always_true_flags != NULL || always_false_flags != NULL) {
   1861       // Remove always_true/false_flags from default_flags (if present).
   1862       CHECK((always_true_flags != NULL) == (always_true_len > 0));
   1863       CHECK((always_false_flags != NULL) == (always_false_len > 0));
   1864       generated_flags = new ParserFlag[flags_len + always_true_len];
   1865       int flag_index = 0;
   1866       for (int i = 0; i < flags_len; ++i) {
   1867         bool use_flag = true;
   1868         for (int j = 0; use_flag && j < always_true_len; ++j) {
   1869           if (flags[i] == always_true_flags[j]) use_flag = false;
   1870         }
   1871         for (int j = 0; use_flag && j < always_false_len; ++j) {
   1872           if (flags[i] == always_false_flags[j]) use_flag = false;
   1873         }
   1874         if (use_flag) generated_flags[flag_index++] = flags[i];
   1875       }
   1876       flags_len = flag_index;
   1877       flags = generated_flags;
   1878     }
   1879   }
   1880   for (int i = 0; context_data[i][0] != NULL; ++i) {
   1881     for (int j = 0; statement_data[j] != NULL; ++j) {
   1882       int kPrefixLen = i::StrLength(context_data[i][0]);
   1883       int kStatementLen = i::StrLength(statement_data[j]);
   1884       int kSuffixLen = i::StrLength(context_data[i][1]);
   1885       int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
   1886 
   1887       // Plug the source code pieces together.
   1888       i::ScopedVector<char> program(kProgramSize + 1);
   1889       int length = i::SNPrintF(program,
   1890                                "%s%s%s",
   1891                                context_data[i][0],
   1892                                statement_data[j],
   1893                                context_data[i][1]);
   1894       CHECK(length == kProgramSize);
   1895       TestParserSync(program.start(), flags, flags_len, result,
   1896                      always_true_flags, always_true_len, always_false_flags,
   1897                      always_false_len, is_module);
   1898     }
   1899   }
   1900   delete[] generated_flags;
   1901 }
   1902 
   1903 
   1904 void RunModuleParserSyncTest(const char* context_data[][2],
   1905                              const char* statement_data[],
   1906                              ParserSyncTestResult result,
   1907                              const ParserFlag* flags = NULL, int flags_len = 0,
   1908                              const ParserFlag* always_true_flags = NULL,
   1909                              int always_true_len = 0,
   1910                              const ParserFlag* always_false_flags = NULL,
   1911                              int always_false_len = 0) {
   1912   bool flag = i::FLAG_harmony_modules;
   1913   i::FLAG_harmony_modules = true;
   1914   RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
   1915                     always_true_flags, always_true_len, always_false_flags,
   1916                     always_false_len, true);
   1917   i::FLAG_harmony_modules = flag;
   1918 }
   1919 
   1920 
   1921 TEST(ErrorsEvalAndArguments) {
   1922   // Tests that both preparsing and parsing produce the right kind of errors for
   1923   // using "eval" and "arguments" as identifiers. Without the strict mode, it's
   1924   // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
   1925   // isn't.
   1926   const char* context_data[][2] = {
   1927       {"\"use strict\";", ""},
   1928       {"\"use strong\";", ""},
   1929       {"var eval; function test_func() {\"use strict\"; ", "}"},
   1930       {"var eval; function test_func() {\"use strong\"; ", "}"},
   1931       {NULL, NULL}};
   1932 
   1933   const char* statement_data[] = {
   1934     "var eval;",
   1935     "var arguments",
   1936     "var foo, eval;",
   1937     "var foo, arguments;",
   1938     "try { } catch (eval) { }",
   1939     "try { } catch (arguments) { }",
   1940     "function eval() { }",
   1941     "function arguments() { }",
   1942     "function foo(eval) { }",
   1943     "function foo(arguments) { }",
   1944     "function foo(bar, eval) { }",
   1945     "function foo(bar, arguments) { }",
   1946     "(eval) => { }",
   1947     "(arguments) => { }",
   1948     "(foo, eval) => { }",
   1949     "(foo, arguments) => { }",
   1950     "eval = 1;",
   1951     "arguments = 1;",
   1952     "var foo = eval = 1;",
   1953     "var foo = arguments = 1;",
   1954     "++eval;",
   1955     "++arguments;",
   1956     "eval++;",
   1957     "arguments++;",
   1958     NULL
   1959   };
   1960 
   1961   static const ParserFlag always_flags[] = {kAllowStrongMode};
   1962   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   1963                     arraysize(always_flags));
   1964 }
   1965 
   1966 
   1967 TEST(NoErrorsEvalAndArgumentsSloppy) {
   1968   // Tests that both preparsing and parsing accept "eval" and "arguments" as
   1969   // identifiers when needed.
   1970   const char* context_data[][2] = {
   1971     { "", "" },
   1972     { "function test_func() {", "}"},
   1973     { NULL, NULL }
   1974   };
   1975 
   1976   const char* statement_data[] = {
   1977     "var eval;",
   1978     "var arguments",
   1979     "var foo, eval;",
   1980     "var foo, arguments;",
   1981     "try { } catch (eval) { }",
   1982     "try { } catch (arguments) { }",
   1983     "function eval() { }",
   1984     "function arguments() { }",
   1985     "function foo(eval) { }",
   1986     "function foo(arguments) { }",
   1987     "function foo(bar, eval) { }",
   1988     "function foo(bar, arguments) { }",
   1989     "eval = 1;",
   1990     "arguments = 1;",
   1991     "var foo = eval = 1;",
   1992     "var foo = arguments = 1;",
   1993     "++eval;",
   1994     "++arguments;",
   1995     "eval++;",
   1996     "arguments++;",
   1997     NULL
   1998   };
   1999 
   2000   RunParserSyncTest(context_data, statement_data, kSuccess);
   2001 }
   2002 
   2003 
   2004 TEST(NoErrorsEvalAndArgumentsStrict) {
   2005   const char* context_data[][2] = {
   2006     { "\"use strict\";", "" },
   2007     { "function test_func() { \"use strict\";", "}" },
   2008     { "() => { \"use strict\"; ", "}" },
   2009     { NULL, NULL }
   2010   };
   2011 
   2012   const char* statement_data[] = {
   2013     "eval;",
   2014     "arguments;",
   2015     "var foo = eval;",
   2016     "var foo = arguments;",
   2017     "var foo = { eval: 1 };",
   2018     "var foo = { arguments: 1 };",
   2019     "var foo = { }; foo.eval = {};",
   2020     "var foo = { }; foo.arguments = {};",
   2021     NULL
   2022   };
   2023 
   2024   RunParserSyncTest(context_data, statement_data, kSuccess);
   2025 }
   2026 
   2027 
   2028 #define FUTURE_STRICT_RESERVED_WORDS(V) \
   2029   V(implements)                         \
   2030   V(interface)                          \
   2031   V(let)                                \
   2032   V(package)                            \
   2033   V(private)                            \
   2034   V(protected)                          \
   2035   V(public)                             \
   2036   V(static)                             \
   2037   V(yield)
   2038 
   2039 
   2040 #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
   2041   V(implements)                                 \
   2042   V(let)                                        \
   2043   V(static)                                     \
   2044   V(yield)
   2045 
   2046 
   2047 #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
   2048   "var " #NAME ";",                             \
   2049   "var foo, " #NAME ";",                        \
   2050   "try { } catch (" #NAME ") { }",              \
   2051   "function " #NAME "() { }",                   \
   2052   "(function " #NAME "() { })",                 \
   2053   "function foo(" #NAME ") { }",                \
   2054   "function foo(bar, " #NAME ") { }",           \
   2055   #NAME " = 1;",                                \
   2056   #NAME " += 1;",                               \
   2057   "var foo = " #NAME " = 1;",                   \
   2058   "++" #NAME ";",                               \
   2059   #NAME " ++;",
   2060 
   2061 
   2062 TEST(ErrorsFutureStrictReservedWords) {
   2063   // Tests that both preparsing and parsing produce the right kind of errors for
   2064   // using future strict reserved words as identifiers. Without the strict mode,
   2065   // it's ok to use future strict reserved words as identifiers. With the strict
   2066   // mode, it isn't.
   2067   const char* context_data[][2] = {
   2068       {"function test_func() {\"use strict\"; ", "}"},
   2069       {"() => { \"use strict\"; ", "}"},
   2070       {"function test_func() {\"use strong\"; ", "}"},
   2071       {"() => { \"use strong\"; ", "}"},
   2072       {NULL, NULL}};
   2073 
   2074   const char* statement_data[] {
   2075     LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
   2076     NULL
   2077   };
   2078 
   2079   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2080   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   2081                     arraysize(always_flags));
   2082   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   2083                     arraysize(always_flags));
   2084 }
   2085 
   2086 
   2087 #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
   2088 
   2089 
   2090 TEST(NoErrorsFutureStrictReservedWords) {
   2091   const char* context_data[][2] = {
   2092     { "", "" },
   2093     { "function test_func() {", "}"},
   2094     { "() => {", "}" },
   2095     { NULL, NULL }
   2096   };
   2097 
   2098   const char* statement_data[] = {
   2099     FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
   2100     NULL
   2101   };
   2102 
   2103   RunParserSyncTest(context_data, statement_data, kSuccess);
   2104 }
   2105 
   2106 
   2107 TEST(ErrorsReservedWords) {
   2108   // Tests that both preparsing and parsing produce the right kind of errors for
   2109   // using future reserved words as identifiers. These tests don't depend on the
   2110   // strict mode.
   2111   const char* context_data[][2] = {
   2112     { "", "" },
   2113     { "\"use strict\";", "" },
   2114     { "var eval; function test_func() {", "}"},
   2115     { "var eval; function test_func() {\"use strict\"; ", "}"},
   2116     { "var eval; () => {", "}"},
   2117     { "var eval; () => {\"use strict\"; ", "}"},
   2118     { NULL, NULL }
   2119   };
   2120 
   2121   const char* statement_data[] = {
   2122     "var super;",
   2123     "var foo, super;",
   2124     "try { } catch (super) { }",
   2125     "function super() { }",
   2126     "function foo(super) { }",
   2127     "function foo(bar, super) { }",
   2128     "(super) => { }",
   2129     "(bar, super) => { }",
   2130     "super = 1;",
   2131     "var foo = super = 1;",
   2132     "++super;",
   2133     "super++;",
   2134     "function foo super",
   2135     NULL
   2136   };
   2137 
   2138   RunParserSyncTest(context_data, statement_data, kError);
   2139 }
   2140 
   2141 
   2142 TEST(NoErrorsLetSloppyAllModes) {
   2143   // In sloppy mode, it's okay to use "let" as identifier.
   2144   const char* context_data[][2] = {
   2145     { "", "" },
   2146     { "function f() {", "}" },
   2147     { "(function f() {", "})" },
   2148     { NULL, NULL }
   2149   };
   2150 
   2151   const char* statement_data[] = {
   2152     "var let;",
   2153     "var foo, let;",
   2154     "try { } catch (let) { }",
   2155     "function let() { }",
   2156     "(function let() { })",
   2157     "function foo(let) { }",
   2158     "function foo(bar, let) { }",
   2159     "let = 1;",
   2160     "var foo = let = 1;",
   2161     "let * 2;",
   2162     "++let;",
   2163     "let++;",
   2164     "let: 34",
   2165     "function let(let) { let: let(let + let(0)); }",
   2166     "({ let: 1 })",
   2167     "({ get let() { 1 } })",
   2168     "let(100)",
   2169     NULL
   2170   };
   2171 
   2172   RunParserSyncTest(context_data, statement_data, kSuccess);
   2173 }
   2174 
   2175 
   2176 TEST(NoErrorsYieldSloppyAllModes) {
   2177   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
   2178   // generator (see other test).
   2179   const char* context_data[][2] = {
   2180     { "", "" },
   2181     { "function not_gen() {", "}" },
   2182     { "(function not_gen() {", "})" },
   2183     { NULL, NULL }
   2184   };
   2185 
   2186   const char* statement_data[] = {
   2187     "var yield;",
   2188     "var foo, yield;",
   2189     "try { } catch (yield) { }",
   2190     "function yield() { }",
   2191     "(function yield() { })",
   2192     "function foo(yield) { }",
   2193     "function foo(bar, yield) { }",
   2194     "yield = 1;",
   2195     "var foo = yield = 1;",
   2196     "yield * 2;",
   2197     "++yield;",
   2198     "yield++;",
   2199     "yield: 34",
   2200     "function yield(yield) { yield: yield (yield + yield(0)); }",
   2201     "({ yield: 1 })",
   2202     "({ get yield() { 1 } })",
   2203     "yield(100)",
   2204     "yield[100]",
   2205     NULL
   2206   };
   2207 
   2208   RunParserSyncTest(context_data, statement_data, kSuccess);
   2209 }
   2210 
   2211 
   2212 TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
   2213   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
   2214   // generator (see next test).
   2215   const char* context_data[][2] = {
   2216     { "", "" },
   2217     { "function not_gen() {", "}" },
   2218     { "function * gen() { function not_gen() {", "} }" },
   2219     { "(function not_gen() {", "})" },
   2220     { "(function * gen() { (function not_gen() {", "}) })" },
   2221     { NULL, NULL }
   2222   };
   2223 
   2224   const char* statement_data[] = {
   2225     "var yield;",
   2226     "var foo, yield;",
   2227     "try { } catch (yield) { }",
   2228     "function yield() { }",
   2229     "(function yield() { })",
   2230     "function foo(yield) { }",
   2231     "function foo(bar, yield) { }",
   2232     "function * yield() { }",
   2233     "yield = 1;",
   2234     "var foo = yield = 1;",
   2235     "yield * 2;",
   2236     "++yield;",
   2237     "yield++;",
   2238     "yield: 34",
   2239     "function yield(yield) { yield: yield (yield + yield(0)); }",
   2240     "({ yield: 1 })",
   2241     "({ get yield() { 1 } })",
   2242     "yield(100)",
   2243     "yield[100]",
   2244     NULL
   2245   };
   2246 
   2247   RunParserSyncTest(context_data, statement_data, kSuccess);
   2248 }
   2249 
   2250 
   2251 TEST(ErrorsYieldStrict) {
   2252   const char* context_data[][2] = {
   2253       {"\"use strict\";", ""},
   2254       {"\"use strict\"; function not_gen() {", "}"},
   2255       {"function test_func() {\"use strict\"; ", "}"},
   2256       {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
   2257       {"\"use strict\"; (function not_gen() {", "})"},
   2258       {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
   2259       {"() => {\"use strict\"; ", "}"},
   2260       {"\"use strong\";", ""},
   2261       {"\"use strong\"; function not_gen() {", "}"},
   2262       {"function test_func() {\"use strong\"; ", "}"},
   2263       {"\"use strong\"; function * gen() { function not_gen() {", "} }"},
   2264       {"\"use strong\"; (function not_gen() {", "})"},
   2265       {"\"use strong\"; (function * gen() { (function not_gen() {", "}) })"},
   2266       {"() => {\"use strong\"; ", "}"},
   2267       {NULL, NULL}};
   2268 
   2269   const char* statement_data[] = {
   2270     "var yield;",
   2271     "var foo, yield;",
   2272     "try { } catch (yield) { }",
   2273     "function yield() { }",
   2274     "(function yield() { })",
   2275     "function foo(yield) { }",
   2276     "function foo(bar, yield) { }",
   2277     "function * yield() { }",
   2278     "(function * yield() { })",
   2279     "yield = 1;",
   2280     "var foo = yield = 1;",
   2281     "++yield;",
   2282     "yield++;",
   2283     "yield: 34;",
   2284     NULL
   2285   };
   2286 
   2287   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2288   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   2289                     arraysize(always_flags));
   2290 }
   2291 
   2292 
   2293 TEST(ErrorsYieldSloppy) {
   2294   const char* context_data[][2] = {
   2295     { "", "" },
   2296     { "function not_gen() {", "}" },
   2297     { "(function not_gen() {", "})" },
   2298     { NULL, NULL }
   2299   };
   2300 
   2301   const char* statement_data[] = {
   2302     "(function * yield() { })",
   2303     NULL
   2304   };
   2305 
   2306   RunParserSyncTest(context_data, statement_data, kError);
   2307 }
   2308 
   2309 
   2310 TEST(NoErrorsGenerator) {
   2311   // clang-format off
   2312   const char* context_data[][2] = {
   2313     { "function * gen() {", "}" },
   2314     { "(function * gen() {", "})" },
   2315     { "(function * () {", "})" },
   2316     { NULL, NULL }
   2317   };
   2318 
   2319   const char* statement_data[] = {
   2320     // A generator without a body is valid.
   2321     ""
   2322     // Valid yield expressions inside generators.
   2323     "yield 2;",
   2324     "yield * 2;",
   2325     "yield * \n 2;",
   2326     "yield yield 1;",
   2327     "yield * yield * 1;",
   2328     "yield 3 + (yield 4);",
   2329     "yield * 3 + (yield * 4);",
   2330     "(yield * 3) + (yield * 4);",
   2331     "yield 3; yield 4;",
   2332     "yield * 3; yield * 4;",
   2333     "(function (yield) { })",
   2334     "(function yield() { })",
   2335     "yield { yield: 12 }",
   2336     "yield /* comment */ { yield: 12 }",
   2337     "yield * \n { yield: 12 }",
   2338     "yield /* comment */ * \n { yield: 12 }",
   2339     // You can return in a generator.
   2340     "yield 1; return",
   2341     "yield * 1; return",
   2342     "yield 1; return 37",
   2343     "yield * 1; return 37",
   2344     "yield 1; return 37; yield 'dead';",
   2345     "yield * 1; return 37; yield * 'dead';",
   2346     // Yield is still a valid key in object literals.
   2347     "({ yield: 1 })",
   2348     "({ get yield() { } })",
   2349     // And in assignment pattern computed properties
   2350     "({ [yield]: x } = { })",
   2351     // Yield without RHS.
   2352     "yield;",
   2353     "yield",
   2354     "yield\n",
   2355     "yield /* comment */"
   2356     "yield // comment\n"
   2357     "(yield)",
   2358     "[yield]",
   2359     "{yield}",
   2360     "yield, yield",
   2361     "yield; yield",
   2362     "(yield) ? yield : yield",
   2363     "(yield) \n ? yield : yield",
   2364     // If there is a newline before the next token, we don't look for RHS.
   2365     "yield\nfor (;;) {}",
   2366     NULL
   2367   };
   2368   // clang-format on
   2369 
   2370   static const ParserFlag always_flags[] = {
   2371       kAllowHarmonyDestructuringAssignment};
   2372   RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
   2373                     always_flags, arraysize(always_flags));
   2374 }
   2375 
   2376 
   2377 TEST(ErrorsYieldGenerator) {
   2378   // clang-format off
   2379   const char* context_data[][2] = {
   2380     { "function * gen() {", "}" },
   2381     { "\"use strict\"; function * gen() {", "}" },
   2382     { NULL, NULL }
   2383   };
   2384 
   2385   const char* statement_data[] = {
   2386     // Invalid yield expressions inside generators.
   2387     "var yield;",
   2388     "var foo, yield;",
   2389     "try { } catch (yield) { }",
   2390     "function yield() { }",
   2391     // The name of the NFE is bound in the generator, which does not permit
   2392     // yield to be an identifier.
   2393     "(function * yield() { })",
   2394     // Yield isn't valid as a formal parameter for generators.
   2395     "function * foo(yield) { }",
   2396     "(function * foo(yield) { })",
   2397     "yield = 1;",
   2398     "var foo = yield = 1;",
   2399     "++yield;",
   2400     "yield++;",
   2401     "yield *",
   2402     "(yield *)",
   2403     // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
   2404     // is invalid.
   2405     "yield 3 + yield 4;",
   2406     "yield: 34",
   2407     "yield ? 1 : 2",
   2408     // Parses as yield (/ yield): invalid.
   2409     "yield / yield",
   2410     "+ yield",
   2411     "+ yield 3",
   2412     // Invalid (no newline allowed between yield and *).
   2413     "yield\n*3",
   2414     // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
   2415     // object literal, and yield is not a valid label).
   2416     "yield\n{yield: 42}",
   2417     "yield /* comment */\n {yield: 42}",
   2418     "yield //comment\n {yield: 42}",
   2419     // Destructuring binding and assignment are both disallowed
   2420     "var [yield] = [42];",
   2421     "var {foo: yield} = {a: 42};",
   2422     "[yield] = [42];",
   2423     "({a: yield} = {a: 42});",
   2424     // Also disallow full yield expressions on LHS
   2425     "var [yield 24] = [42];",
   2426     "var {foo: yield 24} = {a: 42};",
   2427     "[yield 24] = [42];",
   2428     "({a: yield 24} = {a: 42});",
   2429     NULL
   2430   };
   2431   // clang-format on
   2432 
   2433   RunParserSyncTest(context_data, statement_data, kError);
   2434 }
   2435 
   2436 
   2437 TEST(ErrorsNameOfStrictFunction) {
   2438   // Tests that illegal tokens as names of a strict function produce the correct
   2439   // errors.
   2440   const char* context_data[][2] = {
   2441     { "function ", ""},
   2442     { "\"use strict\"; function", ""},
   2443     { "\"use strong\"; function", ""},
   2444     { "function * ", ""},
   2445     { "\"use strict\"; function * ", ""},
   2446     { "\"use strong\"; function * ", ""},
   2447     { NULL, NULL }
   2448   };
   2449 
   2450   const char* statement_data[] = {
   2451     "eval() {\"use strict\";}",
   2452     "arguments() {\"use strict\";}",
   2453     "interface() {\"use strict\";}",
   2454     "yield() {\"use strict\";}",
   2455     // Future reserved words are always illegal
   2456     "super() { }",
   2457     "super() {\"use strict\";}",
   2458     NULL
   2459   };
   2460 
   2461   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2462   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   2463                     arraysize(always_flags));
   2464 }
   2465 
   2466 
   2467 TEST(NoErrorsNameOfStrictFunction) {
   2468   const char* context_data[][2] = {
   2469     { "function ", ""},
   2470     { NULL, NULL }
   2471   };
   2472 
   2473   const char* statement_data[] = {
   2474     "eval() { }",
   2475     "arguments() { }",
   2476     "interface() { }",
   2477     "yield() { }",
   2478     NULL
   2479   };
   2480 
   2481   RunParserSyncTest(context_data, statement_data, kSuccess);
   2482 }
   2483 
   2484 
   2485 TEST(NoErrorsNameOfStrictGenerator) {
   2486   const char* context_data[][2] = {
   2487     { "function * ", ""},
   2488     { NULL, NULL }
   2489   };
   2490 
   2491   const char* statement_data[] = {
   2492     "eval() { }",
   2493     "arguments() { }",
   2494     "interface() { }",
   2495     "yield() { }",
   2496     NULL
   2497   };
   2498 
   2499   RunParserSyncTest(context_data, statement_data, kSuccess);
   2500 }
   2501 
   2502 
   2503 TEST(ErrorsIllegalWordsAsLabelsSloppy) {
   2504   // Using future reserved words as labels is always an error.
   2505   const char* context_data[][2] = {
   2506     { "", ""},
   2507     { "function test_func() {", "}" },
   2508     { "() => {", "}" },
   2509     { NULL, NULL }
   2510   };
   2511 
   2512   const char* statement_data[] = {
   2513     "super: while(true) { break super; }",
   2514     NULL
   2515   };
   2516 
   2517   RunParserSyncTest(context_data, statement_data, kError);
   2518 }
   2519 
   2520 
   2521 TEST(ErrorsIllegalWordsAsLabelsStrict) {
   2522   // Tests that illegal tokens as labels produce the correct errors.
   2523   const char* context_data[][2] = {
   2524       {"\"use strict\";", ""},
   2525       {"function test_func() {\"use strict\"; ", "}"},
   2526       {"() => {\"use strict\"; ", "}"},
   2527       {"\"use strong\";", ""},
   2528       {"function test_func() {\"use strong\"; ", "}"},
   2529       {"() => {\"use strong\"; ", "}"},
   2530       {NULL, NULL}};
   2531 
   2532 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
   2533   const char* statement_data[] = {
   2534     "super: while(true) { break super; }",
   2535     FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
   2536     NULL
   2537   };
   2538 #undef LABELLED_WHILE
   2539 
   2540   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2541   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
   2542                     arraysize(always_flags));
   2543 }
   2544 
   2545 
   2546 TEST(NoErrorsIllegalWordsAsLabels) {
   2547   // Using eval and arguments as labels is legal even in strict mode.
   2548   const char* context_data[][2] = {
   2549     { "", ""},
   2550     { "function test_func() {", "}" },
   2551     { "() => {", "}" },
   2552     { "\"use strict\";", "" },
   2553     { "\"use strict\"; function test_func() {", "}" },
   2554     { "\"use strict\"; () => {", "}" },
   2555     { NULL, NULL }
   2556   };
   2557 
   2558   const char* statement_data[] = {
   2559     "mylabel: while(true) { break mylabel; }",
   2560     "eval: while(true) { break eval; }",
   2561     "arguments: while(true) { break arguments; }",
   2562     NULL
   2563   };
   2564 
   2565   RunParserSyncTest(context_data, statement_data, kSuccess);
   2566 }
   2567 
   2568 
   2569 TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
   2570   const char* context_data[][2] = {
   2571     { "", ""},
   2572     { "function test_func() {", "}" },
   2573     { "() => {", "}" },
   2574     { NULL, NULL }
   2575   };
   2576 
   2577 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
   2578   const char* statement_data[] {
   2579     FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
   2580     NULL
   2581   };
   2582 #undef LABELLED_WHILE
   2583 
   2584   RunParserSyncTest(context_data, statement_data, kSuccess);
   2585 }
   2586 
   2587 
   2588 TEST(ErrorsParenthesizedLabels) {
   2589   // Parenthesized identifiers shouldn't be recognized as labels.
   2590   const char* context_data[][2] = {
   2591     { "", ""},
   2592     { "function test_func() {", "}" },
   2593     { "() => {", "}" },
   2594     { NULL, NULL }
   2595   };
   2596 
   2597   const char* statement_data[] = {
   2598     "(mylabel): while(true) { break mylabel; }",
   2599     NULL
   2600   };
   2601 
   2602   RunParserSyncTest(context_data, statement_data, kError);
   2603 }
   2604 
   2605 
   2606 TEST(NoErrorsParenthesizedDirectivePrologue) {
   2607   // Parenthesized directive prologue shouldn't be recognized.
   2608   const char* context_data[][2] = {
   2609     { "", ""},
   2610     { NULL, NULL }
   2611   };
   2612 
   2613   const char* statement_data[] = {
   2614     "(\"use strict\"); var eval;",
   2615     "(\"use strong\"); var eval;",
   2616     NULL
   2617   };
   2618 
   2619   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2620   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
   2621                     always_flags, arraysize(always_flags));
   2622 }
   2623 
   2624 
   2625 TEST(ErrorsNotAnIdentifierName) {
   2626   const char* context_data[][2] = {
   2627     { "", ""},
   2628     { "\"use strict\";", ""},
   2629     { NULL, NULL }
   2630   };
   2631 
   2632   const char* statement_data[] = {
   2633     "var foo = {}; foo.{;",
   2634     "var foo = {}; foo.};",
   2635     "var foo = {}; foo.=;",
   2636     "var foo = {}; foo.888;",
   2637     "var foo = {}; foo.-;",
   2638     "var foo = {}; foo.--;",
   2639     NULL
   2640   };
   2641 
   2642   RunParserSyncTest(context_data, statement_data, kError);
   2643 }
   2644 
   2645 
   2646 TEST(NoErrorsIdentifierNames) {
   2647   // Keywords etc. are valid as property names.
   2648   const char* context_data[][2] = {
   2649     { "", ""},
   2650     { "\"use strict\";", ""},
   2651     { NULL, NULL }
   2652   };
   2653 
   2654   const char* statement_data[] = {
   2655     "var foo = {}; foo.if;",
   2656     "var foo = {}; foo.yield;",
   2657     "var foo = {}; foo.super;",
   2658     "var foo = {}; foo.interface;",
   2659     "var foo = {}; foo.eval;",
   2660     "var foo = {}; foo.arguments;",
   2661     NULL
   2662   };
   2663 
   2664   RunParserSyncTest(context_data, statement_data, kSuccess);
   2665 }
   2666 
   2667 
   2668 TEST(DontRegressPreParserDataSizes) {
   2669   // These tests make sure that Parser doesn't start producing less "preparse
   2670   // data" (data which the embedder can cache).
   2671   v8::V8::Initialize();
   2672   v8::Isolate* isolate = CcTest::isolate();
   2673   v8::HandleScope handles(isolate);
   2674 
   2675   CcTest::i_isolate()->stack_guard()->SetStackLimit(
   2676       i::GetCurrentStackPosition() - 128 * 1024);
   2677 
   2678   struct TestCase {
   2679     const char* program;
   2680     int functions;
   2681   } test_cases[] = {
   2682     // No functions.
   2683     {"var x = 42;", 0},
   2684     // Functions.
   2685     {"function foo() {}", 1},
   2686     {"function foo() {} function bar() {}", 2},
   2687     // Getter / setter functions are recorded as functions if they're on the top
   2688     // level.
   2689     {"var x = {get foo(){} };", 1},
   2690     // Functions insize lazy functions are not recorded.
   2691     {"function lazy() { function a() {} function b() {} function c() {} }", 1},
   2692     {"function lazy() { var x = {get foo(){} } }", 1},
   2693     {NULL, 0}
   2694   };
   2695 
   2696   for (int i = 0; test_cases[i].program; i++) {
   2697     const char* program = test_cases[i].program;
   2698     i::Factory* factory = CcTest::i_isolate()->factory();
   2699     i::Handle<i::String> source =
   2700         factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
   2701     i::Handle<i::Script> script = factory->NewScript(source);
   2702     i::Zone zone;
   2703     i::ParseInfo info(&zone, script);
   2704     i::ScriptData* sd = NULL;
   2705     info.set_cached_data(&sd);
   2706     info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
   2707     info.set_allow_lazy_parsing();
   2708     i::Parser::ParseStatic(&info);
   2709     i::ParseData* pd = i::ParseData::FromCachedData(sd);
   2710 
   2711     if (pd->FunctionCount() != test_cases[i].functions) {
   2712       v8::base::OS::Print(
   2713           "Expected preparse data for program:\n"
   2714           "\t%s\n"
   2715           "to contain %d functions, however, received %d functions.\n",
   2716           program, test_cases[i].functions, pd->FunctionCount());
   2717       CHECK(false);
   2718     }
   2719     delete sd;
   2720     delete pd;
   2721   }
   2722 }
   2723 
   2724 
   2725 TEST(FunctionDeclaresItselfStrict) {
   2726   // Tests that we produce the right kinds of errors when a function declares
   2727   // itself strict (we cannot produce there errors as soon as we see the
   2728   // offending identifiers, because we don't know at that point whether the
   2729   // function is strict or not).
   2730   const char* context_data[][2] = {
   2731     {"function eval() {", "}"},
   2732     {"function arguments() {", "}"},
   2733     {"function yield() {", "}"},
   2734     {"function interface() {", "}"},
   2735     {"function foo(eval) {", "}"},
   2736     {"function foo(arguments) {", "}"},
   2737     {"function foo(yield) {", "}"},
   2738     {"function foo(interface) {", "}"},
   2739     {"function foo(bar, eval) {", "}"},
   2740     {"function foo(bar, arguments) {", "}"},
   2741     {"function foo(bar, yield) {", "}"},
   2742     {"function foo(bar, interface) {", "}"},
   2743     {"function foo(bar, bar) {", "}"},
   2744     { NULL, NULL }
   2745   };
   2746 
   2747   const char* strict_statement_data[] = {
   2748     "\"use strict\";",
   2749     "\"use strong\";",
   2750     NULL
   2751   };
   2752 
   2753   const char* non_strict_statement_data[] = {
   2754     ";",
   2755     NULL
   2756   };
   2757 
   2758   static const ParserFlag always_flags[] = {kAllowStrongMode};
   2759   RunParserSyncTest(context_data, strict_statement_data, kError, NULL, 0,
   2760                     always_flags, arraysize(always_flags));
   2761   RunParserSyncTest(context_data, non_strict_statement_data, kSuccess, NULL, 0,
   2762                     always_flags, arraysize(always_flags));
   2763 }
   2764 
   2765 
   2766 TEST(ErrorsTryWithoutCatchOrFinally) {
   2767   const char* context_data[][2] = {
   2768     {"", ""},
   2769     { NULL, NULL }
   2770   };
   2771 
   2772   const char* statement_data[] = {
   2773     "try { }",
   2774     "try { } foo();",
   2775     "try { } catch (e) foo();",
   2776     "try { } catch { }",
   2777     "try { } finally foo();",
   2778     NULL
   2779   };
   2780 
   2781   RunParserSyncTest(context_data, statement_data, kError);
   2782 }
   2783 
   2784 
   2785 TEST(NoErrorsTryCatchFinally) {
   2786   const char* context_data[][2] = {
   2787     {"", ""},
   2788     { NULL, NULL }
   2789   };
   2790 
   2791   const char* statement_data[] = {
   2792     "try { } catch (e) { }",
   2793     "try { } catch (e) { } finally { }",
   2794     "try { } finally { }",
   2795     NULL
   2796   };
   2797 
   2798   RunParserSyncTest(context_data, statement_data, kSuccess);
   2799 }
   2800 
   2801 
   2802 TEST(ErrorsRegexpLiteral) {
   2803   const char* context_data[][2] = {
   2804     {"var r = ", ""},
   2805     { NULL, NULL }
   2806   };
   2807 
   2808   const char* statement_data[] = {
   2809     "/unterminated",
   2810     NULL
   2811   };
   2812 
   2813   RunParserSyncTest(context_data, statement_data, kError);
   2814 }
   2815 
   2816 
   2817 TEST(NoErrorsRegexpLiteral) {
   2818   const char* context_data[][2] = {
   2819     {"var r = ", ""},
   2820     { NULL, NULL }
   2821   };
   2822 
   2823   const char* statement_data[] = {
   2824     "/foo/",
   2825     "/foo/g",
   2826     NULL
   2827   };
   2828 
   2829   RunParserSyncTest(context_data, statement_data, kSuccess);
   2830 }
   2831 
   2832 
   2833 TEST(NoErrorsNewExpression) {
   2834   const char* context_data[][2] = {
   2835     {"", ""},
   2836     {"var f =", ""},
   2837     { NULL, NULL }
   2838   };
   2839 
   2840   const char* statement_data[] = {
   2841     "new foo",
   2842     "new foo();",
   2843     "new foo(1);",
   2844     "new foo(1, 2);",
   2845     // The first () will be processed as a part of the NewExpression and the
   2846     // second () will be processed as part of LeftHandSideExpression.
   2847     "new foo()();",
   2848     // The first () will be processed as a part of the inner NewExpression and
   2849     // the second () will be processed as a part of the outer NewExpression.
   2850     "new new foo()();",
   2851     "new foo.bar;",
   2852     "new foo.bar();",
   2853     "new foo.bar.baz;",
   2854     "new foo.bar().baz;",
   2855     "new foo[bar];",
   2856     "new foo[bar]();",
   2857     "new foo[bar][baz];",
   2858     "new foo[bar]()[baz];",
   2859     "new foo[bar].baz(baz)()[bar].baz;",
   2860     "new \"foo\"",  // Runtime error
   2861     "new 1",  // Runtime error
   2862     // This even runs:
   2863     "(new new Function(\"this.x = 1\")).x;",
   2864     "new new Test_Two(String, 2).v(0123).length;",
   2865     NULL
   2866   };
   2867 
   2868   RunParserSyncTest(context_data, statement_data, kSuccess);
   2869 }
   2870 
   2871 
   2872 TEST(ErrorsNewExpression) {
   2873   const char* context_data[][2] = {
   2874     {"", ""},
   2875     {"var f =", ""},
   2876     { NULL, NULL }
   2877   };
   2878 
   2879   const char* statement_data[] = {
   2880     "new foo bar",
   2881     "new ) foo",
   2882     "new ++foo",
   2883     "new foo ++",
   2884     NULL
   2885   };
   2886 
   2887   RunParserSyncTest(context_data, statement_data, kError);
   2888 }
   2889 
   2890 
   2891 TEST(StrictObjectLiteralChecking) {
   2892   const char* context_data[][2] = {
   2893     {"\"use strict\"; var myobject = {", "};"},
   2894     {"\"use strict\"; var myobject = {", ",};"},
   2895     {"var myobject = {", "};"},
   2896     {"var myobject = {", ",};"},
   2897     { NULL, NULL }
   2898   };
   2899 
   2900   // These are only errors in strict mode.
   2901   const char* statement_data[] = {
   2902     "foo: 1, foo: 2",
   2903     "\"foo\": 1, \"foo\": 2",
   2904     "foo: 1, \"foo\": 2",
   2905     "1: 1, 1: 2",
   2906     "1: 1, \"1\": 2",
   2907     "get: 1, get: 2",  // Not a getter for real, just a property called get.
   2908     "set: 1, set: 2",  // Not a setter for real, just a property called set.
   2909     NULL
   2910   };
   2911 
   2912   RunParserSyncTest(context_data, statement_data, kSuccess);
   2913 }
   2914 
   2915 
   2916 TEST(ErrorsObjectLiteralChecking) {
   2917   const char* context_data[][2] = {
   2918     {"\"use strict\"; var myobject = {", "};"},
   2919     {"var myobject = {", "};"},
   2920     { NULL, NULL }
   2921   };
   2922 
   2923   const char* statement_data[] = {
   2924     ",",
   2925     // Wrong number of parameters
   2926     "get bar(x) {}",
   2927     "get bar(x, y) {}",
   2928     "set bar() {}",
   2929     "set bar(x, y) {}",
   2930     // Parsing FunctionLiteral for getter or setter fails
   2931     "get foo( +",
   2932     "get foo() \"error\"",
   2933     NULL
   2934   };
   2935 
   2936   RunParserSyncTest(context_data, statement_data, kError);
   2937 }
   2938 
   2939 
   2940 TEST(NoErrorsObjectLiteralChecking) {
   2941   const char* context_data[][2] = {
   2942     {"var myobject = {", "};"},
   2943     {"var myobject = {", ",};"},
   2944     {"\"use strict\"; var myobject = {", "};"},
   2945     {"\"use strict\"; var myobject = {", ",};"},
   2946     { NULL, NULL }
   2947   };
   2948 
   2949   const char* statement_data[] = {
   2950     "foo: 1, get foo() {}",
   2951     "foo: 1, set foo(v) {}",
   2952     "\"foo\": 1, get \"foo\"() {}",
   2953     "\"foo\": 1, set \"foo\"(v) {}",
   2954     "1: 1, get 1() {}",
   2955     "1: 1, set 1(v) {}",
   2956     "get foo() {}, get foo() {}",
   2957     "set foo(_) {}, set foo(v) {}",
   2958     "foo: 1, get \"foo\"() {}",
   2959     "foo: 1, set \"foo\"(v) {}",
   2960     "\"foo\": 1, get foo() {}",
   2961     "\"foo\": 1, set foo(v) {}",
   2962     "1: 1, get \"1\"() {}",
   2963     "1: 1, set \"1\"(v) {}",
   2964     "\"1\": 1, get 1() {}",
   2965     "\"1\": 1, set 1(v) {}",
   2966     "foo: 1, bar: 2",
   2967     "\"foo\": 1, \"bar\": 2",
   2968     "1: 1, 2: 2",
   2969     // Syntax: IdentifierName ':' AssignmentExpression
   2970     "foo: bar = 5 + baz",
   2971     // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
   2972     "get foo() {}",
   2973     "get \"foo\"() {}",
   2974     "get 1() {}",
   2975     // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
   2976     //     '{' FunctionBody '}'
   2977     "set foo(v) {}",
   2978     "set \"foo\"(v) {}",
   2979     "set 1(v) {}",
   2980     // Non-colliding getters and setters -> no errors
   2981     "foo: 1, get bar() {}",
   2982     "foo: 1, set bar(v) {}",
   2983     "\"foo\": 1, get \"bar\"() {}",
   2984     "\"foo\": 1, set \"bar\"(v) {}",
   2985     "1: 1, get 2() {}",
   2986     "1: 1, set 2(v) {}",
   2987     "get: 1, get foo() {}",
   2988     "set: 1, set foo(_) {}",
   2989     // Keywords, future reserved and strict future reserved are also allowed as
   2990     // property names.
   2991     "if: 4",
   2992     "interface: 5",
   2993     "super: 6",
   2994     "eval: 7",
   2995     "arguments: 8",
   2996     NULL
   2997   };
   2998 
   2999   RunParserSyncTest(context_data, statement_data, kSuccess);
   3000 }
   3001 
   3002 
   3003 TEST(TooManyArguments) {
   3004   const char* context_data[][2] = {
   3005     {"foo(", "0)"},
   3006     { NULL, NULL }
   3007   };
   3008 
   3009   using v8::internal::Code;
   3010   char statement[Code::kMaxArguments * 2 + 1];
   3011   for (int i = 0; i < Code::kMaxArguments; ++i) {
   3012     statement[2 * i] = '0';
   3013     statement[2 * i + 1] = ',';
   3014   }
   3015   statement[Code::kMaxArguments * 2] = 0;
   3016 
   3017   const char* statement_data[] = {
   3018     statement,
   3019     NULL
   3020   };
   3021 
   3022   // The test is quite slow, so run it with a reduced set of flags.
   3023   static const ParserFlag empty_flags[] = {kAllowLazy};
   3024   RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
   3025 }
   3026 
   3027 
   3028 TEST(StrictDelete) {
   3029   // "delete <Identifier>" is not allowed in strict mode.
   3030   const char* strong_context_data[][2] = {
   3031     {"\"use strong\"; ", ""},
   3032     { NULL, NULL }
   3033   };
   3034 
   3035   const char* strict_context_data[][2] = {
   3036     {"\"use strict\"; ", ""},
   3037     { NULL, NULL }
   3038   };
   3039 
   3040   const char* sloppy_context_data[][2] = {
   3041     {"", ""},
   3042     { NULL, NULL }
   3043   };
   3044 
   3045   // These are errors in the strict mode.
   3046   const char* sloppy_statement_data[] = {
   3047     "delete foo;",
   3048     "delete foo + 1;",
   3049     "delete (foo);",
   3050     "delete eval;",
   3051     "delete interface;",
   3052     NULL
   3053   };
   3054 
   3055   // These are always OK
   3056   const char* good_statement_data[] = {
   3057     "delete this;",
   3058     "delete 1;",
   3059     "delete 1 + 2;",
   3060     "delete foo();",
   3061     "delete foo.bar;",
   3062     "delete foo[bar];",
   3063     "delete foo--;",
   3064     "delete --foo;",
   3065     "delete new foo();",
   3066     "delete new foo(bar);",
   3067     NULL
   3068   };
   3069 
   3070   // These are always errors
   3071   const char* bad_statement_data[] = {
   3072     "delete if;",
   3073     NULL
   3074   };
   3075 
   3076   static const ParserFlag always_flags[] = {kAllowStrongMode};
   3077   RunParserSyncTest(strong_context_data, sloppy_statement_data, kError, NULL, 0,
   3078                     always_flags, arraysize(always_flags));
   3079   RunParserSyncTest(strict_context_data, sloppy_statement_data, kError, NULL, 0,
   3080                     always_flags, arraysize(always_flags));
   3081   RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess, NULL,
   3082                     0, always_flags, arraysize(always_flags));
   3083 
   3084   RunParserSyncTest(strong_context_data, good_statement_data, kError, NULL, 0,
   3085                     always_flags, arraysize(always_flags));
   3086   RunParserSyncTest(strict_context_data, good_statement_data, kSuccess, NULL, 0,
   3087                     always_flags, arraysize(always_flags));
   3088   RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess, NULL, 0,
   3089                     always_flags, arraysize(always_flags));
   3090 
   3091   RunParserSyncTest(strong_context_data, bad_statement_data, kError, NULL, 0,
   3092                     always_flags, arraysize(always_flags));
   3093   RunParserSyncTest(strict_context_data, bad_statement_data, kError, NULL, 0,
   3094                     always_flags, arraysize(always_flags));
   3095   RunParserSyncTest(sloppy_context_data, bad_statement_data, kError, NULL, 0,
   3096                     always_flags, arraysize(always_flags));
   3097 }
   3098 
   3099 
   3100 TEST(NoErrorsDeclsInCase) {
   3101   const char* context_data[][2] = {
   3102     {"'use strict'; switch(x) { case 1:", "}"},
   3103     {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
   3104     {"'use strict'; switch(x) { case 1: case 2:", "}"},
   3105     {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
   3106     {"'use strict'; switch(x) { default:", "}"},
   3107     {"function foo() {'use strict'; switch(x) { default:", "}}"},
   3108     {"'use strict'; switch(x) { case 1: default:", "}"},
   3109     {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
   3110     { nullptr, nullptr }
   3111   };
   3112 
   3113   const char* statement_data[] = {
   3114     "function f() { }",
   3115     "class C { }",
   3116     "class C extends Q {}",
   3117     "function f() { } class C {}",
   3118     "function f() { }; class C {}",
   3119     "class C {}; function f() {}",
   3120     nullptr
   3121   };
   3122 
   3123   RunParserSyncTest(context_data, statement_data, kSuccess);
   3124 }
   3125 
   3126 
   3127 TEST(InvalidLeftHandSide) {
   3128   const char* assignment_context_data[][2] = {
   3129     {"", " = 1;"},
   3130     {"\"use strict\"; ", " = 1;"},
   3131     { NULL, NULL }
   3132   };
   3133 
   3134   const char* prefix_context_data[][2] = {
   3135     {"++", ";"},
   3136     {"\"use strict\"; ++", ";"},
   3137     {NULL, NULL},
   3138   };
   3139 
   3140   const char* postfix_context_data[][2] = {
   3141     {"", "++;"},
   3142     {"\"use strict\"; ", "++;"},
   3143     { NULL, NULL }
   3144   };
   3145 
   3146   // Good left hand sides for assigment or prefix / postfix operations.
   3147   const char* good_statement_data[] = {
   3148     "foo",
   3149     "foo.bar",
   3150     "foo[bar]",
   3151     "foo()[bar]",
   3152     "foo().bar",
   3153     "this.foo",
   3154     "this[foo]",
   3155     "new foo()[bar]",
   3156     "new foo().bar",
   3157     "foo()",
   3158     "foo(bar)",
   3159     "foo[bar]()",
   3160     "foo.bar()",
   3161     "this()",
   3162     "this.foo()",
   3163     "this[foo].bar()",
   3164     "this.foo[foo].bar(this)(bar)[foo]()",
   3165     NULL
   3166   };
   3167 
   3168   // Bad left hand sides for assigment or prefix / postfix operations.
   3169   const char* bad_statement_data_common[] = {
   3170     "2",
   3171     "new foo",
   3172     "new foo()",
   3173     "null",
   3174     "if",  // Unexpected token
   3175     "{x: 1}",  // Unexpected token
   3176     "this",
   3177     "\"bar\"",
   3178     "(foo + bar)",
   3179     "new new foo()[bar]",  // means: new (new foo()[bar])
   3180     "new new foo().bar",  // means: new (new foo()[bar])
   3181     NULL
   3182   };
   3183 
   3184   // These are not okay for assignment, but okay for prefix / postix.
   3185   const char* bad_statement_data_for_assignment[] = {
   3186     "++foo",
   3187     "foo++",
   3188     "foo + bar",
   3189     NULL
   3190   };
   3191 
   3192   RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
   3193   RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
   3194   RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
   3195                     kError);
   3196 
   3197   RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
   3198   RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
   3199 
   3200   RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
   3201   RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
   3202 }
   3203 
   3204 
   3205 TEST(FuncNameInferrerBasic) {
   3206   // Tests that function names are inferred properly.
   3207   i::FLAG_allow_natives_syntax = true;
   3208   v8::Isolate* isolate = CcTest::isolate();
   3209   v8::HandleScope scope(isolate);
   3210   LocalContext env;
   3211   CompileRun("var foo1 = function() {}; "
   3212              "var foo2 = function foo3() {}; "
   3213              "function not_ctor() { "
   3214              "  var foo4 = function() {}; "
   3215              "  return %FunctionGetInferredName(foo4); "
   3216              "} "
   3217              "function Ctor() { "
   3218              "  var foo5 = function() {}; "
   3219              "  return %FunctionGetInferredName(foo5); "
   3220              "} "
   3221              "var obj1 = { foo6: function() {} }; "
   3222              "var obj2 = { 'foo7': function() {} }; "
   3223              "var obj3 = {}; "
   3224              "obj3[1] = function() {}; "
   3225              "var obj4 = {}; "
   3226              "obj4[1] = function foo8() {}; "
   3227              "var obj5 = {}; "
   3228              "obj5['foo9'] = function() {}; "
   3229              "var obj6 = { obj7 : { foo10: function() {} } };");
   3230   ExpectString("%FunctionGetInferredName(foo1)", "foo1");
   3231   // foo2 is not unnamed -> its name is not inferred.
   3232   ExpectString("%FunctionGetInferredName(foo2)", "");
   3233   ExpectString("not_ctor()", "foo4");
   3234   ExpectString("Ctor()", "Ctor.foo5");
   3235   ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
   3236   ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
   3237   ExpectString("%FunctionGetInferredName(obj3[1])",
   3238                "obj3.(anonymous function)");
   3239   ExpectString("%FunctionGetInferredName(obj4[1])", "");
   3240   ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
   3241   ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
   3242 }
   3243 
   3244 
   3245 TEST(FuncNameInferrerTwoByte) {
   3246   // Tests function name inferring in cases where some parts of the inferred
   3247   // function name are two-byte strings.
   3248   i::FLAG_allow_natives_syntax = true;
   3249   v8::Isolate* isolate = CcTest::isolate();
   3250   v8::HandleScope scope(isolate);
   3251   LocalContext env;
   3252   uint16_t* two_byte_source = AsciiToTwoByteString(
   3253       "var obj1 = { oXj2 : { foo1: function() {} } }; "
   3254       "%FunctionGetInferredName(obj1.oXj2.foo1)");
   3255   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
   3256   // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
   3257   two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
   3258   v8::Local<v8::String> source =
   3259       v8::String::NewFromTwoByte(isolate, two_byte_source,
   3260                                  v8::NewStringType::kNormal)
   3261           .ToLocalChecked();
   3262   v8::Local<v8::Value> result = CompileRun(source);
   3263   CHECK(result->IsString());
   3264   v8::Local<v8::String> expected_name =
   3265       v8::String::NewFromTwoByte(isolate, two_byte_name,
   3266                                  v8::NewStringType::kNormal)
   3267           .ToLocalChecked();
   3268   CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
   3269   i::DeleteArray(two_byte_source);
   3270   i::DeleteArray(two_byte_name);
   3271 }
   3272 
   3273 
   3274 TEST(FuncNameInferrerEscaped) {
   3275   // The same as FuncNameInferrerTwoByte, except that we express the two-byte
   3276   // character as a unicode escape.
   3277   i::FLAG_allow_natives_syntax = true;
   3278   v8::Isolate* isolate = CcTest::isolate();
   3279   v8::HandleScope scope(isolate);
   3280   LocalContext env;
   3281   uint16_t* two_byte_source = AsciiToTwoByteString(
   3282       "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
   3283       "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
   3284   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
   3285   // Fix to correspond to the non-ASCII name in two_byte_source.
   3286   two_byte_name[6] = 0x010d;
   3287   v8::Local<v8::String> source =
   3288       v8::String::NewFromTwoByte(isolate, two_byte_source,
   3289                                  v8::NewStringType::kNormal)
   3290           .ToLocalChecked();
   3291   v8::Local<v8::Value> result = CompileRun(source);
   3292   CHECK(result->IsString());
   3293   v8::Local<v8::String> expected_name =
   3294       v8::String::NewFromTwoByte(isolate, two_byte_name,
   3295                                  v8::NewStringType::kNormal)
   3296           .ToLocalChecked();
   3297   CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
   3298   i::DeleteArray(two_byte_source);
   3299   i::DeleteArray(two_byte_name);
   3300 }
   3301 
   3302 
   3303 TEST(RegressionLazyFunctionWithErrorWithArg) {
   3304   // The bug occurred when a lazy function had an error which requires a
   3305   // parameter (such as "unknown label" here). The error message was processed
   3306   // before the AstValueFactory containing the error message string was
   3307   // internalized.
   3308   v8::Isolate* isolate = CcTest::isolate();
   3309   v8::HandleScope scope(isolate);
   3310   LocalContext env;
   3311   i::FLAG_lazy = true;
   3312   i::FLAG_min_preparse_length = 0;
   3313   CompileRun("function this_is_lazy() {\n"
   3314              "  break p;\n"
   3315              "}\n"
   3316              "this_is_lazy();\n");
   3317 }
   3318 
   3319 
   3320 TEST(SerializationOfMaybeAssignmentFlag) {
   3321   i::Isolate* isolate = CcTest::i_isolate();
   3322   i::Factory* factory = isolate->factory();
   3323   i::HandleScope scope(isolate);
   3324   LocalContext env;
   3325 
   3326   const char* src =
   3327       "function h() {"
   3328       "  var result = [];"
   3329       "  function f() {"
   3330       "    result.push(2);"
   3331       "  }"
   3332       "  function assertResult(r) {"
   3333       "    f();"
   3334       "    result = [];"
   3335       "  }"
   3336       "  assertResult([2]);"
   3337       "  assertResult([2]);"
   3338       "  return f;"
   3339       "};"
   3340       "h();";
   3341 
   3342   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
   3343   i::SNPrintF(program, "%s", src);
   3344   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
   3345   source->PrintOn(stdout);
   3346   printf("\n");
   3347   i::Zone zone;
   3348   v8::Local<v8::Value> v = CompileRun(src);
   3349   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
   3350   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
   3351   i::Context* context = f->context();
   3352   i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
   3353   avf.Internalize(isolate);
   3354   const i::AstRawString* name = avf.GetOneByteString("result");
   3355   i::Handle<i::String> str = name->string();
   3356   CHECK(str->IsInternalizedString());
   3357   i::Scope* script_scope =
   3358       new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
   3359   script_scope->Initialize();
   3360   i::Scope* s =
   3361       i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
   3362   CHECK(s != script_scope);
   3363   CHECK(name != NULL);
   3364 
   3365   // Get result from h's function context (that is f's context)
   3366   i::Variable* var = s->Lookup(name);
   3367 
   3368   CHECK(var != NULL);
   3369   // Maybe assigned should survive deserialization
   3370   CHECK(var->maybe_assigned() == i::kMaybeAssigned);
   3371   // TODO(sigurds) Figure out if is_used should survive context serialization.
   3372 }
   3373 
   3374 
   3375 TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
   3376   i::Isolate* isolate = CcTest::i_isolate();
   3377   i::Factory* factory = isolate->factory();
   3378   i::HandleScope scope(isolate);
   3379   LocalContext env;
   3380 
   3381 
   3382   const char* src =
   3383       "function f(x) {"
   3384       "    var a = arguments;"
   3385       "    function g(i) {"
   3386       "      ++a[0];"
   3387       "    };"
   3388       "    return g;"
   3389       "  }"
   3390       "f(0);";
   3391 
   3392   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
   3393   i::SNPrintF(program, "%s", src);
   3394   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
   3395   source->PrintOn(stdout);
   3396   printf("\n");
   3397   i::Zone zone;
   3398   v8::Local<v8::Value> v = CompileRun(src);
   3399   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
   3400   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
   3401   i::Context* context = f->context();
   3402   i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
   3403   avf.Internalize(isolate);
   3404 
   3405   i::Scope* script_scope =
   3406       new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
   3407   script_scope->Initialize();
   3408   i::Scope* s =
   3409       i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
   3410   CHECK(s != script_scope);
   3411   const i::AstRawString* name_x = avf.GetOneByteString("x");
   3412 
   3413   // Get result from f's function context (that is g's outer context)
   3414   i::Variable* var_x = s->Lookup(name_x);
   3415   CHECK(var_x != NULL);
   3416   CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
   3417 }
   3418 
   3419 
   3420 TEST(InnerAssignment) {
   3421   i::Isolate* isolate = CcTest::i_isolate();
   3422   i::Factory* factory = isolate->factory();
   3423   i::HandleScope scope(isolate);
   3424   LocalContext env;
   3425 
   3426   const char* prefix = "function f() {";
   3427   const char* midfix = " function g() {";
   3428   const char* suffix = "}}";
   3429   struct { const char* source; bool assigned; bool strict; } outers[] = {
   3430     // Actual assignments.
   3431     { "var x; var x = 5;", true, false },
   3432     { "var x; { var x = 5; }", true, false },
   3433     { "'use strict'; let x; x = 6;", true, true },
   3434     { "var x = 5; function x() {}", true, false },
   3435     // Actual non-assignments.
   3436     { "var x;", false, false },
   3437     { "var x = 5;", false, false },
   3438     { "'use strict'; let x;", false, true },
   3439     { "'use strict'; let x = 6;", false, true },
   3440     { "'use strict'; var x = 0; { let x = 6; }", false, true },
   3441     { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
   3442     { "'use strict'; let x = 0; { let x = 6; }", false, true },
   3443     { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
   3444     { "var x; try {} catch (x) { x = 5; }", false, false },
   3445     { "function x() {}", false, false },
   3446     // Eval approximation.
   3447     { "var x; eval('');", true, false },
   3448     { "eval(''); var x;", true, false },
   3449     { "'use strict'; let x; eval('');", true, true },
   3450     { "'use strict'; eval(''); let x;", true, true },
   3451     // Non-assignments not recognized, because the analysis is approximative.
   3452     { "var x; var x;", true, false },
   3453     { "var x = 5; var x;", true, false },
   3454     { "var x; { var x; }", true, false },
   3455     { "var x; function x() {}", true, false },
   3456     { "function x() {}; var x;", true, false },
   3457     { "var x; try {} catch (x) { var x = 5; }", true, false },
   3458   };
   3459   struct { const char* source; bool assigned; bool with; } inners[] = {
   3460     // Actual assignments.
   3461     { "x = 1;", true, false },
   3462     { "x++;", true, false },
   3463     { "++x;", true, false },
   3464     { "x--;", true, false },
   3465     { "--x;", true, false },
   3466     { "{ x = 1; }", true, false },
   3467     { "'use strict'; { let x; }; x = 0;", true, false },
   3468     { "'use strict'; { const x = 1; }; x = 0;", true, false },
   3469     { "'use strict'; { function x() {} }; x = 0;", true, false },
   3470     { "with ({}) { x = 1; }", true, true },
   3471     { "eval('');", true, false },
   3472     { "'use strict'; { let y; eval('') }", true, false },
   3473     { "function h() { x = 0; }", true, false },
   3474     { "(function() { x = 0; })", true, false },
   3475     { "(function() { x = 0; })", true, false },
   3476     { "with ({}) (function() { x = 0; })", true, true },
   3477     // Actual non-assignments.
   3478     { "", false, false },
   3479     { "x;", false, false },
   3480     { "var x;", false, false },
   3481     { "var x = 8;", false, false },
   3482     { "var x; x = 8;", false, false },
   3483     { "'use strict'; let x;", false, false },
   3484     { "'use strict'; let x = 8;", false, false },
   3485     { "'use strict'; let x; x = 8;", false, false },
   3486     { "'use strict'; const x = 8;", false, false },
   3487     { "function x() {}", false, false },
   3488     { "function x() { x = 0; }", false, false },
   3489     { "function h(x) { x = 0; }", false, false },
   3490     { "'use strict'; { let x; x = 0; }", false, false },
   3491     { "{ var x; }; x = 0;", false, false },
   3492     { "with ({}) {}", false, true },
   3493     { "var x; { with ({}) { x = 1; } }", false, true },
   3494     { "try {} catch(x) { x = 0; }", false, false },
   3495     { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
   3496     // Eval approximation.
   3497     { "eval('');", true, false },
   3498     { "function h() { eval(''); }", true, false },
   3499     { "(function() { eval(''); })", true, false },
   3500     // Shadowing not recognized because of eval approximation.
   3501     { "var x; eval('');", true, false },
   3502     { "'use strict'; let x; eval('');", true, false },
   3503     { "try {} catch(x) { eval(''); }", true, false },
   3504     { "function x() { eval(''); }", true, false },
   3505     { "(function(x) { eval(''); })", true, false },
   3506   };
   3507 
   3508   // Used to trigger lazy compilation of function
   3509   int comment_len = 2048;
   3510   i::ScopedVector<char> comment(comment_len + 1);
   3511   i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
   3512   int prefix_len = Utf8LengthHelper(prefix);
   3513   int midfix_len = Utf8LengthHelper(midfix);
   3514   int suffix_len = Utf8LengthHelper(suffix);
   3515   for (unsigned i = 0; i < arraysize(outers); ++i) {
   3516     const char* outer = outers[i].source;
   3517     int outer_len = Utf8LengthHelper(outer);
   3518     for (unsigned j = 0; j < arraysize(inners); ++j) {
   3519       for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
   3520         for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
   3521           if (outers[i].strict && inners[j].with) continue;
   3522           const char* inner = inners[j].source;
   3523           int inner_len = Utf8LengthHelper(inner);
   3524 
   3525           int outer_comment_len = outer_lazy ? comment_len : 0;
   3526           int inner_comment_len = inner_lazy ? comment_len : 0;
   3527           const char* outer_comment = outer_lazy ? comment.start() : "";
   3528           const char* inner_comment = inner_lazy ? comment.start() : "";
   3529           int len = prefix_len + outer_comment_len + outer_len + midfix_len +
   3530                     inner_comment_len + inner_len + suffix_len;
   3531           i::ScopedVector<char> program(len + 1);
   3532 
   3533           i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
   3534                       midfix, inner_comment, inner, suffix);
   3535           i::Handle<i::String> source =
   3536               factory->InternalizeUtf8String(program.start());
   3537           source->PrintOn(stdout);
   3538           printf("\n");
   3539 
   3540           i::Handle<i::Script> script = factory->NewScript(source);
   3541           i::Zone zone;
   3542           i::ParseInfo info(&zone, script);
   3543           i::Parser parser(&info);
   3544           CHECK(parser.Parse(&info));
   3545           CHECK(i::Compiler::Analyze(&info));
   3546           CHECK(info.literal() != NULL);
   3547 
   3548           i::Scope* scope = info.literal()->scope();
   3549           CHECK_EQ(scope->inner_scopes()->length(), 1);
   3550           i::Scope* inner_scope = scope->inner_scopes()->at(0);
   3551           const i::AstRawString* var_name =
   3552               info.ast_value_factory()->GetOneByteString("x");
   3553           i::Variable* var = inner_scope->Lookup(var_name);
   3554           bool expected = outers[i].assigned || inners[j].assigned;
   3555           CHECK(var != NULL);
   3556           CHECK(var->is_used() || !expected);
   3557           CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
   3558         }
   3559       }
   3560     }
   3561   }
   3562 }
   3563 
   3564 namespace {
   3565 
   3566 int* global_use_counts = NULL;
   3567 
   3568 void MockUseCounterCallback(v8::Isolate* isolate,
   3569                             v8::Isolate::UseCounterFeature feature) {
   3570   ++global_use_counts[feature];
   3571 }
   3572 
   3573 }
   3574 
   3575 
   3576 TEST(UseAsmUseCount) {
   3577   i::Isolate* isolate = CcTest::i_isolate();
   3578   i::HandleScope scope(isolate);
   3579   LocalContext env;
   3580   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
   3581   global_use_counts = use_counts;
   3582   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   3583   CompileRun("\"use asm\";\n"
   3584              "var foo = 1;\n"
   3585              "\"use asm\";\n"  // Only the first one counts.
   3586              "function bar() { \"use asm\"; var baz = 1; }");
   3587   // Optimizing will double-count because the source is parsed twice.
   3588   CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
   3589 }
   3590 
   3591 
   3592 TEST(UseConstLegacyCount) {
   3593   i::FLAG_legacy_const = true;
   3594   i::Isolate* isolate = CcTest::i_isolate();
   3595   i::HandleScope scope(isolate);
   3596   LocalContext env;
   3597   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
   3598   global_use_counts = use_counts;
   3599   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   3600   CompileRun(
   3601       "const x = 1;\n"
   3602       "var foo = 1;\n"
   3603       "const y = 1;\n"
   3604       "function bar() {\n"
   3605       "    const z = 1; var baz = 1;\n"
   3606       "    function q() { const k = 42; }\n"
   3607       "}");
   3608   // Optimizing will double-count because the source is parsed twice.
   3609   CHECK_EQ(i::FLAG_always_opt ? 8 : 4, use_counts[v8::Isolate::kLegacyConst]);
   3610 }
   3611 
   3612 
   3613 TEST(StrictModeUseCount) {
   3614   i::Isolate* isolate = CcTest::i_isolate();
   3615   i::HandleScope scope(isolate);
   3616   LocalContext env;
   3617   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
   3618   global_use_counts = use_counts;
   3619   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   3620   CompileRun(
   3621       "\"use strict\";\n"
   3622       "function bar() { var baz = 1; }");  // strict mode inherits
   3623   CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
   3624   CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
   3625 }
   3626 
   3627 
   3628 TEST(SloppyModeUseCount) {
   3629   i::Isolate* isolate = CcTest::i_isolate();
   3630   i::HandleScope scope(isolate);
   3631   LocalContext env;
   3632   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
   3633   global_use_counts = use_counts;
   3634   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   3635   CompileRun("function bar() { var baz = 1; }");
   3636   CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
   3637   CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
   3638 }
   3639 
   3640 
   3641 TEST(BothModesUseCount) {
   3642   i::Isolate* isolate = CcTest::i_isolate();
   3643   i::HandleScope scope(isolate);
   3644   LocalContext env;
   3645   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
   3646   global_use_counts = use_counts;
   3647   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
   3648   CompileRun("function bar() { 'use strict'; var baz = 1; }");
   3649   CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
   3650   CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
   3651 }
   3652 
   3653 
   3654 TEST(ErrorsArrowFormalParameters) {
   3655   const char* context_data[][2] = {
   3656     { "()", "=>{}" },
   3657     { "()", "=>{};" },
   3658     { "var x = ()", "=>{}" },
   3659     { "var x = ()", "=>{};" },
   3660 
   3661     { "a", "=>{}" },
   3662     { "a", "=>{};" },
   3663     { "var x = a", "=>{}" },
   3664     { "var x = a", "=>{};" },
   3665 
   3666     { "(a)", "=>{}" },
   3667     { "(a)", "=>{};" },
   3668     { "var x = (a)", "=>{}" },
   3669     { "var x = (a)", "=>{};" },
   3670 
   3671     { "(...a)", "=>{}" },
   3672     { "(...a)", "=>{};" },
   3673     { "var x = (...a)", "=>{}" },
   3674     { "var x = (...a)", "=>{};" },
   3675 
   3676     { "(a,b)", "=>{}" },
   3677     { "(a,b)", "=>{};" },
   3678     { "var x = (a,b)", "=>{}" },
   3679     { "var x = (a,b)", "=>{};" },
   3680 
   3681     { "(a,...b)", "=>{}" },
   3682     { "(a,...b)", "=>{};" },
   3683     { "var x = (a,...b)", "=>{}" },
   3684     { "var x = (a,...b)", "=>{};" },
   3685 
   3686     { nullptr, nullptr }
   3687   };
   3688   const char* assignment_expression_suffix_data[] = {
   3689     "?c:d=>{}",
   3690     "=c=>{}",
   3691     "()",
   3692     "(c)",
   3693     "[1]",
   3694     "[c]",
   3695     ".c",
   3696     "-c",
   3697     "+c",
   3698     "c++",
   3699     "`c`",
   3700     "`${c}`",
   3701     "`template-head${c}`",
   3702     "`${c}template-tail`",
   3703     "`template-head${c}template-tail`",
   3704     "`${c}template-tail`",
   3705     nullptr
   3706   };
   3707 
   3708   RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
   3709 }
   3710 
   3711 
   3712 TEST(ErrorsArrowFunctions) {
   3713   // Tests that parser and preparser generate the same kind of errors
   3714   // on invalid arrow function syntax.
   3715   const char* context_data[][2] = {
   3716     {"", ";"},
   3717     {"v = ", ";"},
   3718     {"bar ? (", ") : baz;"},
   3719     {"bar ? baz : (", ");"},
   3720     {"bar[", "];"},
   3721     {"bar, ", ";"},
   3722     {"", ", bar;"},
   3723     {NULL, NULL}
   3724   };
   3725 
   3726   const char* statement_data[] = {
   3727     "=> 0",
   3728     "=>",
   3729     "() =>",
   3730     "=> {}",
   3731     ") => {}",
   3732     ", => {}",
   3733     "(,) => {}",
   3734     "return => {}",
   3735     "() => {'value': 42}",
   3736 
   3737     // Check that the early return introduced in ParsePrimaryExpression
   3738     // does not accept stray closing parentheses.
   3739     ")",
   3740     ") => 0",
   3741     "foo[()]",
   3742     "()",
   3743 
   3744     // Parameter lists with extra parens should be recognized as errors.
   3745     "(()) => 0",
   3746     "((x)) => 0",
   3747     "((x, y)) => 0",
   3748     "(x, (y)) => 0",
   3749     "((x, y, z)) => 0",
   3750     "(x, (y, z)) => 0",
   3751     "((x, y), z) => 0",
   3752 
   3753     // Arrow function formal parameters are parsed as StrictFormalParameters,
   3754     // which confusingly only implies that there are no duplicates.  Words
   3755     // reserved in strict mode, and eval or arguments, are indeed valid in
   3756     // sloppy mode.
   3757     "eval => { 'use strict'; 0 }",
   3758     "arguments => { 'use strict'; 0 }",
   3759     "yield => { 'use strict'; 0 }",
   3760     "interface => { 'use strict'; 0 }",
   3761     "(eval) => { 'use strict'; 0 }",
   3762     "(arguments) => { 'use strict'; 0 }",
   3763     "(yield) => { 'use strict'; 0 }",
   3764     "(interface) => { 'use strict'; 0 }",
   3765     "(eval, bar) => { 'use strict'; 0 }",
   3766     "(bar, eval) => { 'use strict'; 0 }",
   3767     "(bar, arguments) => { 'use strict'; 0 }",
   3768     "(bar, yield) => { 'use strict'; 0 }",
   3769     "(bar, interface) => { 'use strict'; 0 }",
   3770     // TODO(aperez): Detecting duplicates does not work in PreParser.
   3771     // "(bar, bar) => {}",
   3772 
   3773     // The parameter list is parsed as an expression, but only
   3774     // a comma-separated list of identifier is valid.
   3775     "32 => {}",
   3776     "(32) => {}",
   3777     "(a, 32) => {}",
   3778     "if => {}",
   3779     "(if) => {}",
   3780     "(a, if) => {}",
   3781     "a + b => {}",
   3782     "(a + b) => {}",
   3783     "(a + b, c) => {}",
   3784     "(a, b - c) => {}",
   3785     "\"a\" => {}",
   3786     "(\"a\") => {}",
   3787     "(\"a\", b) => {}",
   3788     "(a, \"b\") => {}",
   3789     "-a => {}",
   3790     "(-a) => {}",
   3791     "(-a, b) => {}",
   3792     "(a, -b) => {}",
   3793     "{} => {}",
   3794     "({}) => {}",
   3795     "(a, {}) => {}",
   3796     "({}, a) => {}",
   3797     "a++ => {}",
   3798     "(a++) => {}",
   3799     "(a++, b) => {}",
   3800     "(a, b++) => {}",
   3801     "[] => {}",
   3802     "([]) => {}",
   3803     "(a, []) => {}",
   3804     "([], a) => {}",
   3805     "(a = b) => {}",
   3806     "(a = b, c) => {}",
   3807     "(a, b = c) => {}",
   3808     "(foo ? bar : baz) => {}",
   3809     "(a, foo ? bar : baz) => {}",
   3810     "(foo ? bar : baz, a) => {}",
   3811     "(a.b, c) => {}",
   3812     "(c, a.b) => {}",
   3813     "(a['b'], c) => {}",
   3814     "(c, a['b']) => {}",
   3815     NULL
   3816   };
   3817 
   3818   // The test is quite slow, so run it with a reduced set of flags.
   3819   static const ParserFlag flags[] = {kAllowLazy};
   3820   RunParserSyncTest(context_data, statement_data, kError, flags,
   3821                     arraysize(flags));
   3822 
   3823   // In a context where a concise arrow body is parsed with [~In] variant,
   3824   // ensure that an error is reported in both full parser and preparser.
   3825   const char* loop_context_data[][2] = {{"for (", "; 0;);"},
   3826                                         {nullptr, nullptr}};
   3827   const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
   3828   RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
   3829                     arraysize(flags));
   3830 }
   3831 
   3832 
   3833 TEST(NoErrorsArrowFunctions) {
   3834   // Tests that parser and preparser accept valid arrow functions syntax.
   3835   const char* context_data[][2] = {
   3836     {"", ";"},
   3837     {"bar ? (", ") : baz;"},
   3838     {"bar ? baz : (", ");"},
   3839     {"bar, ", ";"},
   3840     {"", ", bar;"},
   3841     {NULL, NULL}
   3842   };
   3843 
   3844   const char* statement_data[] = {
   3845     "() => {}",
   3846     "() => { return 42 }",
   3847     "x => { return x; }",
   3848     "(x) => { return x; }",
   3849     "(x, y) => { return x + y; }",
   3850     "(x, y, z) => { return x + y + z; }",
   3851     "(x, y) => { x.a = y; }",
   3852     "() => 42",
   3853     "x => x",
   3854     "x => x * x",
   3855     "(x) => x",
   3856     "(x) => x * x",
   3857     "(x, y) => x + y",
   3858     "(x, y, z) => x, y, z",
   3859     "(x, y) => x.a = y",
   3860     "() => ({'value': 42})",
   3861     "x => y => x + y",
   3862     "(x, y) => (u, v) => x*u + y*v",
   3863     "(x, y) => z => z * (x + y)",
   3864     "x => (y, z) => z * (x + y)",
   3865 
   3866     // Those are comma-separated expressions, with arrow functions as items.
   3867     // They stress the code for validating arrow function parameter lists.
   3868     "a, b => 0",
   3869     "a, b, (c, d) => 0",
   3870     "(a, b, (c, d) => 0)",
   3871     "(a, b) => 0, (c, d) => 1",
   3872     "(a, b => {}, a => a + 1)",
   3873     "((a, b) => {}, (a => a + 1))",
   3874     "(a, (a, (b, c) => 0))",
   3875 
   3876     // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
   3877     "foo ? bar : baz => {}",
   3878 
   3879     // Arrows with non-simple parameters.
   3880     "({a}) => {}",
   3881     "(x = 9) => {}",
   3882     "(x, y = 9) => {}",
   3883     "(x = 9, y) => {}",
   3884     "(x, y = 9, z) => {}",
   3885     "(x, y = 9, z = 8) => {}",
   3886     "(...a) => {}",
   3887     "(x, ...a) => {}",
   3888     "(x = 9, ...a) => {}",
   3889     "(x, y = 9, ...a) => {}",
   3890     "(x, y = 9, {b}, z = 8, ...a) => {}",
   3891     // TODO(wingo, rossberg): This is not accepted right now.
   3892     // "({a} = {}) => {}",
   3893     // "([x] = []) => {}",
   3894     "({a = 42}) => {}",
   3895     "([x = 0]) => {}",
   3896     NULL
   3897   };
   3898 
   3899   static const ParserFlag always_flags[] = {kAllowHarmonyDefaultParameters,
   3900                                             kAllowHarmonyDestructuring};
   3901   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
   3902                     always_flags, arraysize(always_flags));
   3903 
   3904   static const ParserFlag flags[] = {kAllowLazy};
   3905   // In a context where a concise arrow body is parsed with [~In] variant,
   3906   // ensure that nested expressions can still use the 'in' operator,
   3907   const char* loop_context_data[][2] = {{"for (", "; 0;);"},
   3908                                         {nullptr, nullptr}};
   3909   const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
   3910   RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
   3911                     arraysize(flags));
   3912 }
   3913 
   3914 
   3915 TEST(ArrowFunctionsSloppyParameterNames) {
   3916   const char* strong_context_data[][2] = {
   3917     {"'use strong'; ", ";"},
   3918     {"'use strong'; bar ? (", ") : baz;"},
   3919     {"'use strong'; bar ? baz : (", ");"},
   3920     {"'use strong'; bar, ", ";"},
   3921     {"'use strong'; ", ", bar;"},
   3922     {NULL, NULL}
   3923   };
   3924 
   3925   const char* strict_context_data[][2] = {
   3926     {"'use strict'; ", ";"},
   3927     {"'use strict'; bar ? (", ") : baz;"},
   3928     {"'use strict'; bar ? baz : (", ");"},
   3929     {"'use strict'; bar, ", ";"},
   3930     {"'use strict'; ", ", bar;"},
   3931     {NULL, NULL}
   3932   };
   3933 
   3934   const char* sloppy_context_data[][2] = {
   3935     {"", ";"},
   3936     {"bar ? (", ") : baz;"},
   3937     {"bar ? baz : (", ");"},
   3938     {"bar, ", ";"},
   3939     {"", ", bar;"},
   3940     {NULL, NULL}
   3941   };
   3942 
   3943   const char* statement_data[] = {
   3944     "eval => {}",
   3945     "arguments => {}",
   3946     "yield => {}",
   3947     "interface => {}",
   3948     "(eval) => {}",
   3949     "(arguments) => {}",
   3950     "(yield) => {}",
   3951     "(interface) => {}",
   3952     "(eval, bar) => {}",
   3953     "(bar, eval) => {}",
   3954     "(bar, arguments) => {}",
   3955     "(bar, yield) => {}",
   3956     "(bar, interface) => {}",
   3957     "(interface, eval) => {}",
   3958     "(interface, arguments) => {}",
   3959     "(eval, interface) => {}",
   3960     "(arguments, interface) => {}",
   3961     NULL
   3962   };
   3963 
   3964   static const ParserFlag always_flags[] = {kAllowStrongMode};
   3965   RunParserSyncTest(strong_context_data, statement_data, kError, NULL, 0,
   3966                     always_flags, arraysize(always_flags));
   3967   RunParserSyncTest(strict_context_data, statement_data, kError, NULL, 0,
   3968                     always_flags, arraysize(always_flags));
   3969   RunParserSyncTest(sloppy_context_data, statement_data, kSuccess, NULL, 0,
   3970                     always_flags, arraysize(always_flags));
   3971 }
   3972 
   3973 
   3974 TEST(ArrowFunctionsYieldParameterNameInGenerator) {
   3975   const char* sloppy_function_context_data[][2] = {
   3976     {"(function f() { (", "); });"},
   3977     {NULL, NULL}
   3978   };
   3979 
   3980   const char* strict_function_context_data[][2] = {
   3981     {"(function f() {'use strong'; (", "); });"},
   3982     {"(function f() {'use strict'; (", "); });"},
   3983     {NULL, NULL}
   3984   };
   3985 
   3986   const char* generator_context_data[][2] = {
   3987     {"(function *g() {'use strong'; (", "); });"},
   3988     {"(function *g() {'use strict'; (", "); });"},
   3989     {"(function *g() { (", "); });"},
   3990     {NULL, NULL}
   3991   };
   3992 
   3993   const char* arrow_data[] = {
   3994     "yield => {}",
   3995     "(yield) => {}",
   3996     "(a, yield) => {}",
   3997     "(yield, a) => {}",
   3998     "(yield, ...a) => {}",
   3999     "(a, ...yield) => {}",
   4000     "({yield}) => {}",
   4001     "([yield]) => {}",
   4002     NULL
   4003   };
   4004 
   4005   static const ParserFlag always_flags[] = { kAllowHarmonyDestructuring,
   4006                                              kAllowStrongMode};
   4007   RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess, NULL, 0,
   4008                     always_flags, arraysize(always_flags));
   4009   RunParserSyncTest(strict_function_context_data, arrow_data, kError, NULL, 0,
   4010                     always_flags, arraysize(always_flags));
   4011   RunParserSyncTest(generator_context_data, arrow_data, kError, NULL, 0,
   4012                     always_flags, arraysize(always_flags));
   4013 }
   4014 
   4015 
   4016 TEST(SuperNoErrors) {
   4017   // Tests that parser and preparser accept 'super' keyword in right places.
   4018   const char* context_data[][2] = {
   4019     {"class C { m() { ", "; } }"},
   4020     {"class C { m() { k = ", "; } }"},
   4021     {"class C { m() { foo(", "); } }"},
   4022     {"class C { m() { () => ", "; } }"},
   4023     {NULL, NULL}
   4024   };
   4025 
   4026   const char* statement_data[] = {
   4027     "super.x",
   4028     "super[27]",
   4029     "new super.x",
   4030     "new super.x()",
   4031     "new super[27]",
   4032     "new super[27]()",
   4033     "z.super",  // Ok, property lookup.
   4034     NULL
   4035   };
   4036 
   4037   static const ParserFlag always_flags[] = {
   4038     kAllowHarmonySloppy
   4039   };
   4040   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
   4041                     always_flags, arraysize(always_flags));
   4042 }
   4043 
   4044 
   4045 TEST(SuperErrors) {
   4046   const char* context_data[][2] = {
   4047     {"class C { m() { ", "; } }"},
   4048     {"class C { m() { k = ", "; } }"},
   4049     {"class C { m() { foo(", "); } }"},
   4050     {"class C { m() { () => ", "; } }"},
   4051     {NULL, NULL}
   4052   };
   4053 
   4054   const char* expression_data[] = {
   4055     "super",
   4056     "super = x",
   4057     "y = super",
   4058     "f(super)",
   4059     "new super",
   4060     "new super()",
   4061     "new super(12, 45)",
   4062     "new new super",
   4063     "new new super()",
   4064     "new new super()()",
   4065     NULL
   4066   };
   4067 
   4068   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   4069   RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
   4070                     always_flags, arraysize(always_flags));
   4071 }
   4072 
   4073 
   4074 TEST(SuperCall) {
   4075   const char* context_data[][2] = {{"", ""},
   4076                                    {NULL, NULL}};
   4077 
   4078   const char* success_data[] = {
   4079     "class C extends B { constructor() { super(); } }",
   4080     "class C extends B { constructor() { () => super(); } }",
   4081     NULL
   4082   };
   4083 
   4084   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   4085   RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
   4086                     always_flags, arraysize(always_flags));
   4087 
   4088   const char* error_data[] = {
   4089     "class C { constructor() { super(); } }",
   4090     "class C { method() { super(); } }",
   4091     "class C { method() { () => super(); } }",
   4092     "class C { *method() { super(); } }",
   4093     "class C { get x() { super(); } }",
   4094     "class C { set x(_) { super(); } }",
   4095     "({ method() { super(); } })",
   4096     "({ *method() { super(); } })",
   4097     "({ get x() { super(); } })",
   4098     "({ set x(_) { super(); } })",
   4099     "({ f: function() { super(); } })",
   4100     "(function() { super(); })",
   4101     "var f = function() { super(); }",
   4102     "({ f: function*() { super(); } })",
   4103     "(function*() { super(); })",
   4104     "var f = function*() { super(); }",
   4105     NULL
   4106   };
   4107 
   4108   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
   4109                     always_flags, arraysize(always_flags));
   4110 }
   4111 
   4112 
   4113 TEST(SuperNewNoErrors) {
   4114   const char* context_data[][2] = {
   4115     {"class C { constructor() { ", " } }"},
   4116     {"class C { *method() { ", " } }"},
   4117     {"class C { get x() { ", " } }"},
   4118     {"class C { set x(_) { ", " } }"},
   4119     {"({ method() { ", " } })"},
   4120     {"({ *method() { ", " } })"},
   4121     {"({ get x() { ", " } })"},
   4122     {"({ set x(_) { ", " } })"},
   4123     {NULL, NULL}
   4124   };
   4125 
   4126   const char* expression_data[] = {
   4127     "new super.x;",
   4128     "new super.x();",
   4129     "() => new super.x;",
   4130     "() => new super.x();",
   4131     NULL
   4132   };
   4133 
   4134   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   4135   RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
   4136                     always_flags, arraysize(always_flags));
   4137 }
   4138 
   4139 
   4140 TEST(SuperNewErrors) {
   4141   const char* context_data[][2] = {
   4142     {"class C { method() { ", " } }"},
   4143     {"class C { *method() { ", " } }"},
   4144     {"class C { get x() { ", " } }"},
   4145     {"class C { set x(_) { ", " } }"},
   4146     {"({ method() { ", " } })"},
   4147     {"({ *method() { ", " } })"},
   4148     {"({ get x() { ", " } })"},
   4149     {"({ set x(_) { ", " } })"},
   4150     {"({ f: function() { ", " } })"},
   4151     {"(function() { ", " })"},
   4152     {"var f = function() { ", " }"},
   4153     {"({ f: function*() { ", " } })"},
   4154     {"(function*() { ", " })"},
   4155     {"var f = function*() { ", " }"},
   4156     {NULL, NULL}
   4157   };
   4158 
   4159   const char* statement_data[] = {
   4160     "new super;",
   4161     "new super();",
   4162     "() => new super;",
   4163     "() => new super();",
   4164     NULL
   4165   };
   4166 
   4167   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   4168   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
   4169                     always_flags, arraysize(always_flags));
   4170 }
   4171 
   4172 
   4173 TEST(SuperErrorsNonMethods) {
   4174   // super is only allowed in methods, accessors and constructors.
   4175   const char* context_data[][2] = {
   4176     {"", ";"},
   4177     {"k = ", ";"},
   4178     {"foo(", ");"},
   4179     {"if (", ") {}"},
   4180     {"if (true) {", "}"},
   4181     {"if (false) {} else {", "}"},
   4182     {"while (true) {", "}"},
   4183     {"function f() {", "}"},
   4184     {"class C extends (", ") {}"},
   4185     {"class C { m() { function f() {", "} } }"},
   4186     {"({ m() { function f() {", "} } })"},
   4187     {NULL, NULL}
   4188   };
   4189 
   4190   const char* statement_data[] = {
   4191     "super",
   4192     "super = x",
   4193     "y = super",
   4194     "f(super)",
   4195     "super.x",
   4196     "super[27]",
   4197     "super.x()",
   4198     "super[27]()",
   4199     "super()",
   4200     "new super.x",
   4201     "new super.x()",
   4202     "new super[27]",
   4203     "new super[27]()",
   4204     NULL
   4205   };
   4206 
   4207   static const ParserFlag always_flags[] = {
   4208     kAllowHarmonySloppy
   4209   };
   4210   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
   4211                     always_flags, arraysize(always_flags));
   4212 }
   4213 
   4214 
   4215 TEST(NoErrorsMethodDefinition) {
   4216   const char* context_data[][2] = {{"({", "});"},
   4217                                    {"'use strict'; ({", "});"},
   4218                                    {"({*", "});"},
   4219                                    {"'use strict'; ({*", "});"},
   4220                                    {NULL, NULL}};
   4221 
   4222   const char* object_literal_body_data[] = {
   4223     "m() {}",
   4224     "m(x) { return x; }",
   4225     "m(x, y) {}, n() {}",
   4226     "set(x, y) {}",
   4227     "get(x, y) {}",
   4228     NULL
   4229   };
   4230 
   4231   RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
   4232 }
   4233 
   4234 
   4235 TEST(MethodDefinitionNames) {
   4236   const char* context_data[][2] = {{"({", "(x, y) {}});"},
   4237                                    {"'use strict'; ({", "(x, y) {}});"},
   4238                                    {"({*", "(x, y) {}});"},
   4239                                    {"'use strict'; ({*", "(x, y) {}});"},
   4240                                    {NULL, NULL}};
   4241 
   4242   const char* name_data[] = {
   4243     "m",
   4244     "'m'",
   4245     "\"m\"",
   4246     "\"m n\"",
   4247     "true",
   4248     "false",
   4249     "null",
   4250     "0",
   4251     "1.2",
   4252     "1e1",
   4253     "1E1",
   4254     "1e+1",
   4255     "1e-1",
   4256 
   4257     // Keywords
   4258     "async",
   4259     "await",
   4260     "break",
   4261     "case",
   4262     "catch",
   4263     "class",
   4264     "const",
   4265     "continue",
   4266     "debugger",
   4267     "default",
   4268     "delete",
   4269     "do",
   4270     "else",
   4271     "enum",
   4272     "export",
   4273     "extends",
   4274     "finally",
   4275     "for",
   4276     "function",
   4277     "if",
   4278     "implements",
   4279     "import",
   4280     "in",
   4281     "instanceof",
   4282     "interface",
   4283     "let",
   4284     "new",
   4285     "package",
   4286     "private",
   4287     "protected",
   4288     "public",
   4289     "return",
   4290     "static",
   4291     "super",
   4292     "switch",
   4293     "this",
   4294     "throw",
   4295     "try",
   4296     "typeof",
   4297     "var",
   4298     "void",
   4299     "while",
   4300     "with",
   4301     "yield",
   4302     NULL
   4303   };
   4304 
   4305   RunParserSyncTest(context_data, name_data, kSuccess);
   4306 }
   4307 
   4308 
   4309 TEST(MethodDefinitionStrictFormalParamereters) {
   4310   const char* context_data[][2] = {{"({method(", "){}});"},
   4311                                    {"'use strict'; ({method(", "){}});"},
   4312                                    {"({*method(", "){}});"},
   4313                                    {"'use strict'; ({*method(", "){}});"},
   4314                                    {NULL, NULL}};
   4315 
   4316   const char* params_data[] = {
   4317     "x, x",
   4318     "x, y, x",
   4319     "var",
   4320     "const",
   4321     NULL
   4322   };
   4323 
   4324   RunParserSyncTest(context_data, params_data, kError);
   4325 }
   4326 
   4327 
   4328 TEST(MethodDefinitionEvalArguments) {
   4329   const char* strict_context_data[][2] =
   4330       {{"'use strict'; ({method(", "){}});"},
   4331        {"'use strict'; ({*method(", "){}});"},
   4332        {NULL, NULL}};
   4333   const char* sloppy_context_data[][2] =
   4334       {{"({method(", "){}});"},
   4335        {"({*method(", "){}});"},
   4336        {NULL, NULL}};
   4337 
   4338   const char* data[] = {
   4339       "eval",
   4340       "arguments",
   4341       NULL};
   4342 
   4343   // Fail in strict mode
   4344   RunParserSyncTest(strict_context_data, data, kError);
   4345 
   4346   // OK in sloppy mode
   4347   RunParserSyncTest(sloppy_context_data, data, kSuccess);
   4348 }
   4349 
   4350 
   4351 TEST(MethodDefinitionDuplicateEvalArguments) {
   4352   const char* context_data[][2] =
   4353       {{"'use strict'; ({method(", "){}});"},
   4354        {"'use strict'; ({*method(", "){}});"},
   4355        {"({method(", "){}});"},
   4356        {"({*method(", "){}});"},
   4357        {NULL, NULL}};
   4358 
   4359   const char* data[] = {
   4360       "eval, eval",
   4361       "eval, a, eval",
   4362       "arguments, arguments",
   4363       "arguments, a, arguments",
   4364       NULL};
   4365 
   4366   // In strict mode, the error is using "eval" or "arguments" as parameter names
   4367   // In sloppy mode, the error is that eval / arguments are duplicated
   4368   RunParserSyncTest(context_data, data, kError);
   4369 }
   4370 
   4371 
   4372 TEST(MethodDefinitionDuplicateProperty) {
   4373   const char* context_data[][2] = {{"'use strict'; ({", "});"},
   4374                                    {NULL, NULL}};
   4375 
   4376   const char* params_data[] = {
   4377     "x: 1, x() {}",
   4378     "x() {}, x: 1",
   4379     "x() {}, get x() {}",
   4380     "x() {}, set x(_) {}",
   4381     "x() {}, x() {}",
   4382     "x() {}, y() {}, x() {}",
   4383     "x() {}, \"x\"() {}",
   4384     "x() {}, 'x'() {}",
   4385     "0() {}, '0'() {}",
   4386     "1.0() {}, 1: 1",
   4387 
   4388     "x: 1, *x() {}",
   4389     "*x() {}, x: 1",
   4390     "*x() {}, get x() {}",
   4391     "*x() {}, set x(_) {}",
   4392     "*x() {}, *x() {}",
   4393     "*x() {}, y() {}, *x() {}",
   4394     "*x() {}, *\"x\"() {}",
   4395     "*x() {}, *'x'() {}",
   4396     "*0() {}, *'0'() {}",
   4397     "*1.0() {}, 1: 1",
   4398 
   4399     NULL
   4400   };
   4401 
   4402   RunParserSyncTest(context_data, params_data, kSuccess);
   4403 }
   4404 
   4405 
   4406 TEST(ClassExpressionNoErrors) {
   4407   const char* context_data[][2] = {{"(", ");"},
   4408                                    {"var C = ", ";"},
   4409                                    {"bar, ", ";"},
   4410                                    {NULL, NULL}};
   4411   const char* class_data[] = {
   4412     "class {}",
   4413     "class name {}",
   4414     "class extends F {}",
   4415     "class name extends F {}",
   4416     "class extends (F, G) {}",
   4417     "class name extends (F, G) {}",
   4418     "class extends class {} {}",
   4419     "class name extends class {} {}",
   4420     "class extends class base {} {}",
   4421     "class name extends class base {} {}",
   4422     NULL};
   4423 
   4424   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   4425   RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
   4426                     always_flags, arraysize(always_flags));
   4427 }
   4428 
   4429 
   4430 TEST(ClassDeclarationNoErrors) {
   4431   const char* context_data[][2] = {{"'use strict'; ", ""},
   4432                                    {"'use strict'; {", "}"},
   4433                                    {"'use strict'; if (true) {", "}"},
   4434                                    {NULL, NULL}};
   4435   const char* statement_data[] = {
   4436     "class name {}",
   4437     "class name extends F {}",
   4438     "class name extends (F, G) {}",
   4439     "class name extends class {} {}",
   4440     "class name extends class base {} {}",
   4441     NULL};
   4442 
   4443   RunParserSyncTest(context_data, statement_data, kSuccess);
   4444 }
   4445 
   4446 
   4447 TEST(ClassBodyNoErrors) {
   4448   // Tests that parser and preparser accept valid class syntax.
   4449   const char* context_data[][2] = {{"(class {", "});"},
   4450                                    {"(class extends Base {", "});"},
   4451                                    {"class C {", "}"},
   4452                                    {"class C extends Base {", "}"},
   4453                                    {NULL, NULL}};
   4454   const char* class_body_data[] = {
   4455     ";",
   4456     ";;",
   4457     "m() {}",
   4458     "m() {};",
   4459     "; m() {}",
   4460     "m() {}; n(x) {}",
   4461     "get x() {}",
   4462     "set x(v) {}",
   4463     "get() {}",
   4464     "set() {}",
   4465     "*g() {}",
   4466     "*g() {};",
   4467     "; *g() {}",
   4468     "*g() {}; *h(x) {}",
   4469     "static() {}",
   4470     "static m() {}",
   4471     "static get x() {}",
   4472     "static set x(v) {}",
   4473     "static get() {}",
   4474     "static set() {}",
   4475     "static static() {}",
   4476     "static get static() {}",
   4477     "static set static(v) {}",
   4478     "*static() {}",
   4479     "*get() {}",
   4480     "*set() {}",
   4481     "static *g() {}",
   4482     NULL};
   4483 
   4484   static const ParserFlag always_flags[] = {
   4485     kAllowHarmonySloppy
   4486   };
   4487   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
   4488                     always_flags, arraysize(always_flags));
   4489 }
   4490 
   4491 
   4492 TEST(ClassPropertyNameNoErrors) {
   4493   const char* context_data[][2] = {{"(class {", "() {}});"},
   4494                                    {"(class { get ", "() {}});"},
   4495                                    {"(class { set ", "(v) {}});"},
   4496                                    {"(class { static ", "() {}});"},
   4497                                    {"(class { static get ", "() {}});"},
   4498                                    {"(class { static set ", "(v) {}});"},
   4499                                    {"(class { *", "() {}});"},
   4500                                    {"(class { static *", "() {}});"},
   4501                                    {"class C {", "() {}}"},
   4502                                    {"class C { get ", "() {}}"},
   4503                                    {"class C { set ", "(v) {}}"},
   4504                                    {"class C { static ", "() {}}"},
   4505                                    {"class C { static get ", "() {}}"},
   4506                                    {"class C { static set ", "(v) {}}"},
   4507                                    {"class C { *", "() {}}"},
   4508                                    {"class C { static *", "() {}}"},
   4509                                    {NULL, NULL}};
   4510   const char* name_data[] = {
   4511     "42",
   4512     "42.5",
   4513     "42e2",
   4514     "42e+2",
   4515     "42e-2",
   4516     "null",
   4517     "false",
   4518     "true",
   4519     "'str'",
   4520     "\"str\"",
   4521     "static",
   4522     "get",
   4523     "set",
   4524     "var",
   4525     "const",
   4526     "let",
   4527     "this",
   4528     "class",
   4529     "function",
   4530     "yield",
   4531     "if",
   4532     "else",
   4533     "for",
   4534     "while",
   4535     "do",
   4536     "try",
   4537     "catch",
   4538     "finally",
   4539     NULL};
   4540 
   4541   static const ParserFlag always_flags[] = {
   4542     kAllowHarmonySloppy
   4543   };
   4544   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
   4545                     always_flags, arraysize(always_flags));
   4546 }
   4547 
   4548 
   4549 TEST(ClassExpressionErrors) {
   4550   const char* context_data[][2] = {{"(", ");"},
   4551                                    {"var C = ", ";"},
   4552                                    {"bar, ", ";"},
   4553                                    {NULL, NULL}};
   4554   const char* class_data[] = {
   4555     "class",
   4556     "class name",
   4557     "class name extends",
   4558     "class extends",
   4559     "class {",
   4560     "class { m }",
   4561     "class { m; n }",
   4562     "class { m: 1 }",
   4563     "class { m(); n() }",
   4564     "class { get m }",
   4565     "class { get m() }",
   4566     "class { get m() { }",
   4567     "class { set m() {} }",  // Missing required parameter.
   4568     "class { m() {}, n() {} }",  // No commas allowed.
   4569     NULL};
   4570 
   4571   static const ParserFlag always_flags[] = {
   4572     kAllowHarmonySloppy
   4573   };
   4574   RunParserSyncTest(context_data, class_data, kError, NULL, 0,
   4575                     always_flags, arraysize(always_flags));
   4576 }
   4577 
   4578 
   4579 TEST(ClassDeclarationErrors) {
   4580   const char* context_data[][2] = {{"", ""},
   4581                                    {"{", "}"},
   4582                                    {"if (true) {", "}"},
   4583                                    {NULL, NULL}};
   4584   const char* class_data[] = {
   4585     "class",
   4586     "class name",
   4587     "class name extends",
   4588     "class extends",
   4589     "class name {",
   4590     "class name { m }",
   4591     "class name { m; n }",
   4592     "class name { m: 1 }",
   4593     "class name { m(); n() }",
   4594     "class name { get x }",
   4595     "class name { get x() }",
   4596     "class name { set x() {) }",  // missing required param
   4597     "class {}",  // Name is required for declaration
   4598     "class extends base {}",
   4599     "class name { *",
   4600     "class name { * }",
   4601     "class name { *; }",
   4602     "class name { *get x() {} }",
   4603     "class name { *set x(_) {} }",
   4604     "class name { *static m() {} }",
   4605     NULL};
   4606 
   4607   static const ParserFlag always_flags[] = {
   4608     kAllowHarmonySloppy
   4609   };
   4610   RunParserSyncTest(context_data, class_data, kError, NULL, 0,
   4611                     always_flags, arraysize(always_flags));
   4612 }
   4613 
   4614 
   4615 TEST(ClassNameErrors) {
   4616   const char* context_data[][2] = {{"class ", "{}"},
   4617                                    {"(class ", "{});"},
   4618                                    {"'use strict'; class ", "{}"},
   4619                                    {"'use strict'; (class ", "{});"},
   4620                                    {NULL, NULL}};
   4621   const char* class_name[] = {
   4622     "arguments",
   4623     "eval",
   4624     "implements",
   4625     "interface",
   4626     "let",
   4627     "package",
   4628     "private",
   4629     "protected",
   4630     "public",
   4631     "static",
   4632     "var",
   4633     "yield",
   4634     NULL};
   4635 
   4636   static const ParserFlag always_flags[] = {
   4637     kAllowHarmonySloppy
   4638   };
   4639   RunParserSyncTest(context_data, class_name, kError, NULL, 0,
   4640                     always_flags, arraysize(always_flags));
   4641 }
   4642 
   4643 
   4644 TEST(ClassGetterParamNameErrors) {
   4645   const char* context_data[][2] = {
   4646     {"class C { get name(", ") {} }"},
   4647     {"(class { get name(", ") {} });"},
   4648     {"'use strict'; class C { get name(", ") {} }"},
   4649     {"'use strict'; (class { get name(", ") {} })"},
   4650     {NULL, NULL}
   4651   };
   4652 
   4653   const char* class_name[] = {
   4654     "arguments",
   4655     "eval",
   4656     "implements",
   4657     "interface",
   4658     "let",
   4659     "package",
   4660     "private",
   4661     "protected",
   4662     "public",
   4663     "static",
   4664     "var",
   4665     "yield",
   4666     NULL};
   4667 
   4668   static const ParserFlag always_flags[] = {
   4669     kAllowHarmonySloppy
   4670   };
   4671   RunParserSyncTest(context_data, class_name, kError, NULL, 0,
   4672                     always_flags, arraysize(always_flags));
   4673 }
   4674 
   4675 
   4676 TEST(ClassStaticPrototypeErrors) {
   4677   const char* context_data[][2] = {{"class C {", "}"},
   4678                                    {"(class {", "});"},
   4679                                    {NULL, NULL}};
   4680 
   4681   const char* class_body_data[] = {
   4682     "static prototype() {}",
   4683     "static get prototype() {}",
   4684     "static set prototype(_) {}",
   4685     "static *prototype() {}",
   4686     "static 'prototype'() {}",
   4687     "static *'prototype'() {}",
   4688     "static prot\\u006ftype() {}",
   4689     "static 'prot\\u006ftype'() {}",
   4690     "static get 'prot\\u006ftype'() {}",
   4691     "static set 'prot\\u006ftype'(_) {}",
   4692     "static *'prot\\u006ftype'() {}",
   4693     NULL};
   4694 
   4695   static const ParserFlag always_flags[] = {
   4696     kAllowHarmonySloppy
   4697   };
   4698   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
   4699                     always_flags, arraysize(always_flags));
   4700 }
   4701 
   4702 
   4703 TEST(ClassSpecialConstructorErrors) {
   4704   const char* context_data[][2] = {{"class C {", "}"},
   4705                                    {"(class {", "});"},
   4706                                    {NULL, NULL}};
   4707 
   4708   const char* class_body_data[] = {
   4709     "get constructor() {}",
   4710     "get constructor(_) {}",
   4711     "*constructor() {}",
   4712     "get 'constructor'() {}",
   4713     "*'constructor'() {}",
   4714     "get c\\u006fnstructor() {}",
   4715     "*c\\u006fnstructor() {}",
   4716     "get 'c\\u006fnstructor'() {}",
   4717     "get 'c\\u006fnstructor'(_) {}",
   4718     "*'c\\u006fnstructor'() {}",
   4719     NULL};
   4720 
   4721   static const ParserFlag always_flags[] = {
   4722     kAllowHarmonySloppy
   4723   };
   4724   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
   4725                     always_flags, arraysize(always_flags));
   4726 }
   4727 
   4728 
   4729 TEST(ClassConstructorNoErrors) {
   4730   const char* context_data[][2] = {{"class C {", "}"},
   4731                                    {"(class {", "});"},
   4732                                    {NULL, NULL}};
   4733 
   4734   const char* class_body_data[] = {
   4735     "constructor() {}",
   4736     "static constructor() {}",
   4737     "static get constructor() {}",
   4738     "static set constructor(_) {}",
   4739     "static *constructor() {}",
   4740     NULL};
   4741 
   4742   static const ParserFlag always_flags[] = {
   4743     kAllowHarmonySloppy
   4744   };
   4745   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
   4746                     always_flags, arraysize(always_flags));
   4747 }
   4748 
   4749 
   4750 TEST(ClassMultipleConstructorErrors) {
   4751   const char* context_data[][2] = {{"class C {", "}"},
   4752                                    {"(class {", "});"},
   4753                                    {NULL, NULL}};
   4754 
   4755   const char* class_body_data[] = {
   4756     "constructor() {}; constructor() {}",
   4757     NULL};
   4758 
   4759   static const ParserFlag always_flags[] = {
   4760     kAllowHarmonySloppy
   4761   };
   4762   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
   4763                     always_flags, arraysize(always_flags));
   4764 }
   4765 
   4766 
   4767 TEST(ClassMultiplePropertyNamesNoErrors) {
   4768   const char* context_data[][2] = {{"class C {", "}"},
   4769                                    {"(class {", "});"},
   4770                                    {NULL, NULL}};
   4771 
   4772   const char* class_body_data[] = {
   4773     "constructor() {}; static constructor() {}",
   4774     "m() {}; static m() {}",
   4775     "m() {}; m() {}",
   4776     "static m() {}; static m() {}",
   4777     "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
   4778     NULL};
   4779 
   4780   static const ParserFlag always_flags[] = {
   4781     kAllowHarmonySloppy
   4782   };
   4783   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
   4784                     always_flags, arraysize(always_flags));
   4785 }
   4786 
   4787 
   4788 TEST(ClassesAreStrictErrors) {
   4789   const char* context_data[][2] = {{"", ""},
   4790                                    {"(", ");"},
   4791                                    {NULL, NULL}};
   4792 
   4793   const char* class_body_data[] = {
   4794     "class C { method() { with ({}) {} } }",
   4795     "class C extends function() { with ({}) {} } {}",
   4796     "class C { *method() { with ({}) {} } }",
   4797     NULL};
   4798 
   4799   static const ParserFlag always_flags[] = {
   4800     kAllowHarmonySloppy
   4801   };
   4802   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
   4803                     always_flags, arraysize(always_flags));
   4804 }
   4805 
   4806 
   4807 TEST(ObjectLiteralPropertyShorthandKeywordsError) {
   4808   const char* context_data[][2] = {{"({", "});"},
   4809                                    {"'use strict'; ({", "});"},
   4810                                    {NULL, NULL}};
   4811 
   4812   const char* name_data[] = {
   4813     "break",
   4814     "case",
   4815     "catch",
   4816     "class",
   4817     "const",
   4818     "continue",
   4819     "debugger",
   4820     "default",
   4821     "delete",
   4822     "do",
   4823     "else",
   4824     "enum",
   4825     "export",
   4826     "extends",
   4827     "false",
   4828     "finally",
   4829     "for",
   4830     "function",
   4831     "if",
   4832     "import",
   4833     "in",
   4834     "instanceof",
   4835     "new",
   4836     "null",
   4837     "return",
   4838     "super",
   4839     "switch",
   4840     "this",
   4841     "throw",
   4842     "true",
   4843     "try",
   4844     "typeof",
   4845     "var",
   4846     "void",
   4847     "while",
   4848     "with",
   4849     NULL
   4850   };
   4851 
   4852   RunParserSyncTest(context_data, name_data, kError);
   4853 }
   4854 
   4855 
   4856 TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
   4857   const char* context_data[][2] = {{"({", "});"},
   4858                                    {NULL, NULL}};
   4859 
   4860   const char* name_data[] = {
   4861     "implements",
   4862     "interface",
   4863     "let",
   4864     "package",
   4865     "private",
   4866     "protected",
   4867     "public",
   4868     "static",
   4869     "yield",
   4870     NULL
   4871   };
   4872 
   4873   RunParserSyncTest(context_data, name_data, kSuccess);
   4874 
   4875   const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
   4876                                           {NULL, NULL}};
   4877   RunParserSyncTest(context_strict_data, name_data, kError);
   4878 }
   4879 
   4880 
   4881 TEST(ObjectLiteralPropertyShorthandError) {
   4882   const char* context_data[][2] = {{"({", "});"},
   4883                                    {"'use strict'; ({", "});"},
   4884                                    {NULL, NULL}};
   4885 
   4886   const char* name_data[] = {
   4887     "1",
   4888     "1.2",
   4889     "0",
   4890     "0.1",
   4891     "1.0",
   4892     "1e1",
   4893     "0x1",
   4894     "\"s\"",
   4895     "'s'",
   4896     NULL
   4897   };
   4898 
   4899   RunParserSyncTest(context_data, name_data, kError);
   4900 }
   4901 
   4902 
   4903 TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
   4904   const char* context_data[][2] = {{"", ""},
   4905                                    {NULL, NULL}};
   4906 
   4907   const char* name_data[] = {
   4908     "function* g() { ({yield}); }",
   4909     NULL
   4910   };
   4911 
   4912   RunParserSyncTest(context_data, name_data, kError);
   4913 }
   4914 
   4915 
   4916 TEST(ConstParsingInForIn) {
   4917   const char* context_data[][2] = {{"'use strict';", ""},
   4918                                    {"function foo(){ 'use strict';", "}"},
   4919                                    {NULL, NULL}};
   4920 
   4921   const char* data[] = {
   4922       "for(const x = 1; ; ) {}",
   4923       "for(const x = 1, y = 2;;){}",
   4924       "for(const x in [1,2,3]) {}",
   4925       "for(const x of [1,2,3]) {}",
   4926       NULL};
   4927   RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
   4928 }
   4929 
   4930 
   4931 TEST(ConstParsingInForInError) {
   4932   const char* context_data[][2] = {{"'use strict';", ""},
   4933                                    {"function foo(){ 'use strict';", "}"},
   4934                                    {NULL, NULL}};
   4935 
   4936   const char* data[] = {
   4937       "for(const x,y = 1; ; ) {}",
   4938       "for(const x = 4 in [1,2,3]) {}",
   4939       "for(const x = 4, y in [1,2,3]) {}",
   4940       "for(const x = 4 of [1,2,3]) {}",
   4941       "for(const x = 4, y of [1,2,3]) {}",
   4942       "for(const x = 1, y = 2 in []) {}",
   4943       "for(const x,y in []) {}",
   4944       "for(const x = 1, y = 2 of []) {}",
   4945       "for(const x,y of []) {}",
   4946       NULL};
   4947   RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
   4948 }
   4949 
   4950 
   4951 TEST(InitializedDeclarationsInStrictForInError) {
   4952   const char* context_data[][2] = {{"'use strict';", ""},
   4953                                    {"function foo(){ 'use strict';", "}"},
   4954                                    {NULL, NULL}};
   4955 
   4956   const char* data[] = {
   4957       "for (var i = 1 in {}) {}",
   4958       "for (var i = void 0 in [1, 2, 3]) {}",
   4959       "for (let i = 1 in {}) {}",
   4960       "for (let i = void 0 in [1, 2, 3]) {}",
   4961       "for (const i = 1 in {}) {}",
   4962       "for (const i = void 0 in [1, 2, 3]) {}",
   4963       NULL};
   4964   RunParserSyncTest(context_data, data, kError);
   4965 }
   4966 
   4967 
   4968 TEST(InitializedDeclarationsInStrictForOfError) {
   4969   const char* context_data[][2] = {{"'use strict';", ""},
   4970                                    {"function foo(){ 'use strict';", "}"},
   4971                                    {NULL, NULL}};
   4972 
   4973   const char* data[] = {
   4974       "for (var i = 1 of {}) {}",
   4975       "for (var i = void 0 of [1, 2, 3]) {}",
   4976       "for (let i = 1 of {}) {}",
   4977       "for (let i = void 0 of [1, 2, 3]) {}",
   4978       "for (const i = 1 of {}) {}",
   4979       "for (const i = void 0 of [1, 2, 3]) {}",
   4980       NULL};
   4981   RunParserSyncTest(context_data, data, kError);
   4982 }
   4983 
   4984 
   4985 TEST(InitializedDeclarationsInSloppyForInError) {
   4986   const char* context_data[][2] = {{"", ""},
   4987                                    {"function foo(){", "}"},
   4988                                    {NULL, NULL}};
   4989 
   4990   const char* data[] = {
   4991       "for (var i = 1 in {}) {}",
   4992       "for (var i = void 0 in [1, 2, 3]) {}",
   4993       NULL};
   4994   // TODO(caitp): This should be an error in sloppy mode.
   4995   RunParserSyncTest(context_data, data, kSuccess);
   4996 }
   4997 
   4998 
   4999 TEST(InitializedDeclarationsInSloppyForOfError) {
   5000   const char* context_data[][2] = {{"", ""},
   5001                                    {"function foo(){", "}"},
   5002                                    {NULL, NULL}};
   5003 
   5004   const char* data[] = {
   5005       "for (var i = 1 of {}) {}",
   5006       "for (var i = void 0 of [1, 2, 3]) {}",
   5007       NULL};
   5008   RunParserSyncTest(context_data, data, kError);
   5009 }
   5010 
   5011 
   5012 TEST(ForInMultipleDeclarationsError) {
   5013   const char* context_data[][2] = {{"", ""},
   5014                                    {"function foo(){", "}"},
   5015                                    {"'use strict';", ""},
   5016                                    {"function foo(){ 'use strict';", "}"},
   5017                                    {NULL, NULL}};
   5018 
   5019   const char* data[] = {
   5020       "for (var i, j in {}) {}",
   5021       "for (var i, j in [1, 2, 3]) {}",
   5022       "for (var i, j = 1 in {}) {}",
   5023       "for (var i, j = void 0 in [1, 2, 3]) {}",
   5024 
   5025       "for (let i, j in {}) {}",
   5026       "for (let i, j in [1, 2, 3]) {}",
   5027       "for (let i, j = 1 in {}) {}",
   5028       "for (let i, j = void 0 in [1, 2, 3]) {}",
   5029 
   5030       "for (const i, j in {}) {}",
   5031       "for (const i, j in [1, 2, 3]) {}",
   5032       "for (const i, j = 1 in {}) {}",
   5033       "for (const i, j = void 0 in [1, 2, 3]) {}",
   5034       NULL};
   5035   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   5036   RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
   5037                     arraysize(always_flags));
   5038 }
   5039 
   5040 
   5041 TEST(ForOfMultipleDeclarationsError) {
   5042   const char* context_data[][2] = {{"", ""},
   5043                                    {"function foo(){", "}"},
   5044                                    {"'use strict';", ""},
   5045                                    {"function foo(){ 'use strict';", "}"},
   5046                                    {NULL, NULL}};
   5047 
   5048   const char* data[] = {
   5049       "for (var i, j of {}) {}",
   5050       "for (var i, j of [1, 2, 3]) {}",
   5051       "for (var i, j = 1 of {}) {}",
   5052       "for (var i, j = void 0 of [1, 2, 3]) {}",
   5053 
   5054       "for (let i, j of {}) {}",
   5055       "for (let i, j of [1, 2, 3]) {}",
   5056       "for (let i, j = 1 of {}) {}",
   5057       "for (let i, j = void 0 of [1, 2, 3]) {}",
   5058 
   5059       "for (const i, j of {}) {}",
   5060       "for (const i, j of [1, 2, 3]) {}",
   5061       "for (const i, j = 1 of {}) {}",
   5062       "for (const i, j = void 0 of [1, 2, 3]) {}",
   5063       NULL};
   5064   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   5065   RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
   5066                     arraysize(always_flags));
   5067 }
   5068 
   5069 
   5070 TEST(ForInNoDeclarationsError) {
   5071   const char* context_data[][2] = {{"", ""},
   5072                                    {"function foo(){", "}"},
   5073                                    {"'use strict';", ""},
   5074                                    {"function foo(){ 'use strict';", "}"},
   5075                                    {NULL, NULL}};
   5076 
   5077   const char* data[] = {
   5078       "for (var in {}) {}",
   5079       "for (const in {}) {}",
   5080       NULL};
   5081   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   5082   RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
   5083                     arraysize(always_flags));
   5084 }
   5085 
   5086 
   5087 TEST(ForOfNoDeclarationsError) {
   5088   const char* context_data[][2] = {{"", ""},
   5089                                    {"function foo(){", "}"},
   5090                                    {"'use strict';", ""},
   5091                                    {"function foo(){ 'use strict';", "}"},
   5092                                    {NULL, NULL}};
   5093 
   5094   const char* data[] = {
   5095       "for (var of [1, 2, 3]) {}",
   5096       "for (const of [1, 2, 3]) {}",
   5097       NULL};
   5098   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   5099   RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
   5100                     arraysize(always_flags));
   5101 }
   5102 
   5103 
   5104 TEST(InvalidUnicodeEscapes) {
   5105   const char* context_data[][2] = {{"", ""},
   5106                                    {"'use strict';", ""},
   5107                                    {NULL, NULL}};
   5108   const char* data[] = {
   5109     "var foob\\u123r = 0;",
   5110     "var \\u123roo = 0;",
   5111     "\"foob\\u123rr\"",
   5112     // No escapes allowed in regexp flags
   5113     "/regex/\\u0069g",
   5114     "/regex/\\u006g",
   5115     // Braces gone wrong
   5116     "var foob\\u{c481r = 0;",
   5117     "var foob\\uc481}r = 0;",
   5118     "var \\u{0052oo = 0;",
   5119     "var \\u0052}oo = 0;",
   5120     "\"foob\\u{c481r\"",
   5121     "var foob\\u{}ar = 0;",
   5122     // Too high value for the unicode escape
   5123     "\"\\u{110000}\"",
   5124     // Not an unicode escape
   5125     "var foob\\v1234r = 0;",
   5126     "var foob\\U1234r = 0;",
   5127     "var foob\\v{1234}r = 0;",
   5128     "var foob\\U{1234}r = 0;",
   5129     NULL};
   5130   RunParserSyncTest(context_data, data, kError);
   5131 }
   5132 
   5133 
   5134 TEST(UnicodeEscapes) {
   5135   const char* context_data[][2] = {{"", ""},
   5136                                    {"'use strict';", ""},
   5137                                    {NULL, NULL}};
   5138   const char* data[] = {
   5139     // Identifier starting with escape
   5140     "var \\u0052oo = 0;",
   5141     "var \\u{0052}oo = 0;",
   5142     "var \\u{52}oo = 0;",
   5143     "var \\u{00000000052}oo = 0;",
   5144     // Identifier with an escape but not starting with an escape
   5145     "var foob\\uc481r = 0;",
   5146     "var foob\\u{c481}r = 0;",
   5147     // String with an escape
   5148     "\"foob\\uc481r\"",
   5149     "\"foob\\{uc481}r\"",
   5150     // This character is a valid unicode character, representable as a surrogate
   5151     // pair, not representable as 4 hex digits.
   5152     "\"foo\\u{10e6d}\"",
   5153     // Max value for the unicode escape
   5154     "\"\\u{10ffff}\"",
   5155     NULL};
   5156   RunParserSyncTest(context_data, data, kSuccess);
   5157 }
   5158 
   5159 
   5160 TEST(ScanTemplateLiterals) {
   5161   const char* context_data[][2] = {{"'use strict';", ""},
   5162                                    {"function foo(){ 'use strict';"
   5163                                     "  var a, b, c; return ", "}"},
   5164                                    {NULL, NULL}};
   5165 
   5166   const char* data[] = {
   5167       "``",
   5168       "`no-subst-template`",
   5169       "`template-head${a}`",
   5170       "`${a}`",
   5171       "`${a}template-tail`",
   5172       "`template-head${a}template-tail`",
   5173       "`${a}${b}${c}`",
   5174       "`a${a}b${b}c${c}`",
   5175       "`${a}a${b}b${c}c`",
   5176       "`foo\n\nbar\r\nbaz`",
   5177       "`foo\n\n${  bar  }\r\nbaz`",
   5178       "`foo${a /* comment */}`",
   5179       "`foo${a // comment\n}`",
   5180       "`foo${a \n}`",
   5181       "`foo${a \r\n}`",
   5182       "`foo${a \r}`",
   5183       "`foo${/* comment */ a}`",
   5184       "`foo${// comment\na}`",
   5185       "`foo${\n a}`",
   5186       "`foo${\r\n a}`",
   5187       "`foo${\r a}`",
   5188       "`foo${'a' in a}`",
   5189       NULL};
   5190   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
   5191 }
   5192 
   5193 
   5194 TEST(ScanTaggedTemplateLiterals) {
   5195   const char* context_data[][2] = {{"'use strict';", ""},
   5196                                    {"function foo(){ 'use strict';"
   5197                                     "  function tag() {}"
   5198                                     "  var a, b, c; return ", "}"},
   5199                                    {NULL, NULL}};
   5200 
   5201   const char* data[] = {
   5202       "tag ``",
   5203       "tag `no-subst-template`",
   5204       "tag`template-head${a}`",
   5205       "tag `${a}`",
   5206       "tag `${a}template-tail`",
   5207       "tag   `template-head${a}template-tail`",
   5208       "tag\n`${a}${b}${c}`",
   5209       "tag\r\n`a${a}b${b}c${c}`",
   5210       "tag    `${a}a${b}b${c}c`",
   5211       "tag\t`foo\n\nbar\r\nbaz`",
   5212       "tag\r`foo\n\n${  bar  }\r\nbaz`",
   5213       "tag`foo${a /* comment */}`",
   5214       "tag`foo${a // comment\n}`",
   5215       "tag`foo${a \n}`",
   5216       "tag`foo${a \r\n}`",
   5217       "tag`foo${a \r}`",
   5218       "tag`foo${/* comment */ a}`",
   5219       "tag`foo${// comment\na}`",
   5220       "tag`foo${\n a}`",
   5221       "tag`foo${\r\n a}`",
   5222       "tag`foo${\r a}`",
   5223       "tag`foo${'a' in a}`",
   5224       NULL};
   5225   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
   5226 }
   5227 
   5228 
   5229 TEST(TemplateMaterializedLiterals) {
   5230   const char* context_data[][2] = {
   5231     {
   5232       "'use strict';\n"
   5233       "function tag() {}\n"
   5234       "var a, b, c;\n"
   5235       "(", ")"
   5236     },
   5237     {NULL, NULL}
   5238   };
   5239 
   5240   const char* data[] = {
   5241     "tag``",
   5242     "tag`a`",
   5243     "tag`a${1}b`",
   5244     "tag`a${1}b${2}c`",
   5245     "``",
   5246     "`a`",
   5247     "`a${1}b`",
   5248     "`a${1}b${2}c`",
   5249     NULL
   5250   };
   5251 
   5252   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
   5253 }
   5254 
   5255 
   5256 TEST(ScanUnterminatedTemplateLiterals) {
   5257   const char* context_data[][2] = {{"'use strict';", ""},
   5258                                    {"function foo(){ 'use strict';"
   5259                                     "  var a, b, c; return ", "}"},
   5260                                    {NULL, NULL}};
   5261 
   5262   const char* data[] = {
   5263       "`no-subst-template",
   5264       "`template-head${a}",
   5265       "`${a}template-tail",
   5266       "`template-head${a}template-tail",
   5267       "`${a}${b}${c}",
   5268       "`a${a}b${b}c${c}",
   5269       "`${a}a${b}b${c}c",
   5270       "`foo\n\nbar\r\nbaz",
   5271       "`foo\n\n${  bar  }\r\nbaz",
   5272       "`foo${a /* comment } */`",
   5273       "`foo${a /* comment } `*/",
   5274       "`foo${a // comment}`",
   5275       "`foo${a \n`",
   5276       "`foo${a \r\n`",
   5277       "`foo${a \r`",
   5278       "`foo${/* comment */ a`",
   5279       "`foo${// commenta}`",
   5280       "`foo${\n a`",
   5281       "`foo${\r\n a`",
   5282       "`foo${\r a`",
   5283       "`foo${fn(}`",
   5284       "`foo${1 if}`",
   5285       NULL};
   5286   RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
   5287 }
   5288 
   5289 
   5290 TEST(TemplateLiteralsIllegalTokens) {
   5291   const char* context_data[][2] = {{"'use strict';", ""},
   5292                                    {"function foo(){ 'use strict';"
   5293                                     "  var a, b, c; return ", "}"},
   5294                                    {NULL, NULL}};
   5295   const char* data[] = {
   5296       "`hello\\x`",
   5297       "`hello\\x${1}`",
   5298       "`hello${1}\\x`",
   5299       "`hello${1}\\x${2}`",
   5300       "`hello\\x\n`",
   5301       "`hello\\x\n${1}`",
   5302       "`hello${1}\\x\n`",
   5303       "`hello${1}\\x\n${2}`",
   5304       NULL};
   5305 
   5306   RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
   5307 }
   5308 
   5309 
   5310 TEST(ParseRestParameters) {
   5311   const char* context_data[][2] = {{"'use strict';(function(",
   5312                                     "){ return args;})(1, [], /regexp/, 'str',"
   5313                                     "function(){});"},
   5314                                    {"(function(", "){ return args;})(1, [],"
   5315                                     "/regexp/, 'str', function(){});"},
   5316                                   {NULL, NULL}};
   5317 
   5318   const char* data[] = {"...args",
   5319                         "a, ...args",
   5320                         "...   args",
   5321                         "a, ...   args",
   5322                         "...\targs",
   5323                         "a, ...\targs",
   5324                         "...\r\nargs",
   5325                         "a, ...\r\nargs",
   5326                         "...\rargs",
   5327                         "a, ...\rargs",
   5328                         "...\t\n\t\t\n  args",
   5329                         "a, ...  \n  \n  args",
   5330                         "...{ length, 0: a, 1: b}",
   5331                         "...{}",
   5332                         "...[a, b]",
   5333                         "...[]",
   5334                         "...[...[a, b, ...c]]",
   5335                         NULL};
   5336   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   5337   RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
   5338                     arraysize(always_flags));
   5339 }
   5340 
   5341 
   5342 TEST(ParseRestParametersErrors) {
   5343   const char* context_data[][2] = {{"'use strict';(function(",
   5344                                     "){ return args;}(1, [], /regexp/, 'str',"
   5345                                     "function(){});"},
   5346                                    {"(function(", "){ return args;}(1, [],"
   5347                                     "/regexp/, 'str', function(){});"},
   5348                                    {NULL, NULL}};
   5349 
   5350   const char* data[] = {
   5351       "...args, b",
   5352       "a, ...args, b",
   5353       "...args,   b",
   5354       "a, ...args,   b",
   5355       "...args,\tb",
   5356       "a,...args\t,b",
   5357       "...args\r\n, b",
   5358       "a, ... args,\r\nb",
   5359       "...args\r,b",
   5360       "a, ... args,\rb",
   5361       "...args\t\n\t\t\n,  b",
   5362       "a, ... args,  \n  \n  b",
   5363       "a, a, ...args",
   5364       "a,\ta, ...args",
   5365       "a,\ra, ...args",
   5366       "a,\na, ...args",
   5367       NULL};
   5368   RunParserSyncTest(context_data, data, kError);
   5369 }
   5370 
   5371 
   5372 TEST(RestParameterInSetterMethodError) {
   5373   const char* context_data[][2] = {
   5374       {"'use strict';({ set prop(", ") {} }).prop = 1;"},
   5375       {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
   5376       {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
   5377       {"({ set prop(", ") {} }).prop = 1;"},
   5378       {"(class { static set prop(", ") {} }).prop = 1;"},
   5379       {"(new (class { set prop(", ") {} })).prop = 1;"},
   5380       {nullptr, nullptr}};
   5381   const char* data[] = {"...a", "...arguments", "...eval", nullptr};
   5382 
   5383   static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
   5384   RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
   5385                     arraysize(always_flags));
   5386 }
   5387 
   5388 
   5389 TEST(RestParametersEvalArguments) {
   5390   const char* strict_context_data[][2] =
   5391       {{"'use strict';(function(",
   5392         "){ return;})(1, [], /regexp/, 'str',function(){});"},
   5393        {NULL, NULL}};
   5394   const char* sloppy_context_data[][2] =
   5395       {{"(function(",
   5396         "){ return;})(1, [],/regexp/, 'str', function(){});"},
   5397        {NULL, NULL}};
   5398 
   5399   const char* data[] = {
   5400       "...eval",
   5401       "eval, ...args",
   5402       "...arguments",
   5403       "arguments, ...args",
   5404       NULL};
   5405 
   5406   // Fail in strict mode
   5407   RunParserSyncTest(strict_context_data, data, kError);
   5408 
   5409   // OK in sloppy mode
   5410   RunParserSyncTest(sloppy_context_data, data, kSuccess);
   5411 }
   5412 
   5413 
   5414 TEST(RestParametersDuplicateEvalArguments) {
   5415   const char* context_data[][2] =
   5416       {{"'use strict';(function(",
   5417         "){ return;})(1, [], /regexp/, 'str',function(){});"},
   5418        {"(function(",
   5419         "){ return;})(1, [],/regexp/, 'str', function(){});"},
   5420        {NULL, NULL}};
   5421 
   5422   const char* data[] = {
   5423       "eval, ...eval",
   5424       "eval, eval, ...args",
   5425       "arguments, ...arguments",
   5426       "arguments, arguments, ...args",
   5427       NULL};
   5428 
   5429   // In strict mode, the error is using "eval" or "arguments" as parameter names
   5430   // In sloppy mode, the error is that eval / arguments are duplicated
   5431   RunParserSyncTest(context_data, data, kError);
   5432 }
   5433 
   5434 
   5435 TEST(SpreadCall) {
   5436   const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
   5437                                    {"function fn() {} fn(", ");"},
   5438                                    {NULL, NULL}};
   5439 
   5440   const char* data[] = {
   5441       "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
   5442       "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
   5443       "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
   5444       "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
   5445       "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
   5446       "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
   5447 
   5448   RunParserSyncTest(context_data, data, kSuccess);
   5449 }
   5450 
   5451 
   5452 TEST(SpreadCallErrors) {
   5453   const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
   5454                                    {"function fn() {} fn(", ");"},
   5455                                    {NULL, NULL}};
   5456 
   5457   const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
   5458 
   5459   RunParserSyncTest(context_data, data, kError);
   5460 }
   5461 
   5462 
   5463 TEST(BadRestSpread) {
   5464   const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
   5465                                    {"function fn() { ", "} fn();"},
   5466                                    {NULL, NULL}};
   5467   const char* data[] = {"return ...[1,2,3];",     "var ...x = [1,2,3];",
   5468                         "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
   5469                         "var {...x} = [1,2,3];",  "var { x } = {x: ...[1,2,3]}",
   5470                         NULL};
   5471   RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
   5472 }
   5473 
   5474 
   5475 TEST(LexicalScopingSloppyMode) {
   5476   const char* context_data[][2] = {
   5477       {"", ""},
   5478       {"function f() {", "}"},
   5479       {"{", "}"},
   5480       {NULL, NULL}};
   5481   const char* bad_data[] = {
   5482     "let x = 1;",
   5483     "for(let x = 1;;){}",
   5484     "for(let x of []){}",
   5485     "for(let x in []){}",
   5486     "class C {}",
   5487     "class C extends D {}",
   5488     "(class {})",
   5489     "(class extends D {})",
   5490     "(class C {})",
   5491     "(class C extends D {})",
   5492     NULL};
   5493   static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
   5494   RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0,
   5495                     always_false_flags, arraysize(always_false_flags));
   5496 
   5497   const char* good_data[] = {
   5498     "let = 1;",
   5499     "for(let = 1;;){}",
   5500     NULL};
   5501   RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0,
   5502                     always_false_flags, arraysize(always_false_flags));
   5503 }
   5504 
   5505 
   5506 TEST(ComputedPropertyName) {
   5507   const char* context_data[][2] = {{"({[", "]: 1});"},
   5508                                    {"({get [", "]() {}});"},
   5509                                    {"({set [", "](_) {}});"},
   5510                                    {"({[", "]() {}});"},
   5511                                    {"({*[", "]() {}});"},
   5512                                    {"(class {get [", "]() {}});"},
   5513                                    {"(class {set [", "](_) {}});"},
   5514                                    {"(class {[", "]() {}});"},
   5515                                    {"(class {*[", "]() {}});"},
   5516                                    {NULL, NULL}};
   5517   const char* error_data[] = {
   5518     "1, 2",
   5519     "var name",
   5520     NULL};
   5521 
   5522   static const ParserFlag always_flags[] = {
   5523     kAllowHarmonySloppy,
   5524   };
   5525   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
   5526                     always_flags, arraysize(always_flags));
   5527 
   5528   const char* name_data[] = {
   5529     "1",
   5530     "1 + 2",
   5531     "'name'",
   5532     "\"name\"",
   5533     "[]",
   5534     "{}",
   5535     NULL};
   5536 
   5537   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
   5538                     always_flags, arraysize(always_flags));
   5539 }
   5540 
   5541 
   5542 TEST(ComputedPropertyNameShorthandError) {
   5543   const char* context_data[][2] = {{"({", "});"},
   5544                                    {NULL, NULL}};
   5545   const char* error_data[] = {
   5546     "a: 1, [2]",
   5547     "[1], a: 1",
   5548     NULL};
   5549 
   5550   static const ParserFlag always_flags[] = {
   5551     kAllowHarmonySloppy,
   5552   };
   5553   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
   5554                     always_flags, arraysize(always_flags));
   5555 }
   5556 
   5557 
   5558 TEST(BasicImportExportParsing) {
   5559   i::FLAG_harmony_modules = true;
   5560 
   5561   const char* kSources[] = {
   5562       "export let x = 0;",
   5563       "export var y = 0;",
   5564       "export const z = 0;",
   5565       "export function func() { };",
   5566       "export class C { };",
   5567       "export { };",
   5568       "function f() {}; f(); export { f };",
   5569       "var a, b, c; export { a, b as baz, c };",
   5570       "var d, e; export { d as dreary, e, };",
   5571       "export default function f() {}",
   5572       "export default class C {}",
   5573       "export default 42",
   5574       "var x; export default x = 7",
   5575       "export { Q } from 'somemodule.js';",
   5576       "export * from 'somemodule.js';",
   5577       "var foo; export { foo as for };",
   5578       "export { arguments } from 'm.js';",
   5579       "export { for } from 'm.js';",
   5580       "export { yield } from 'm.js'",
   5581       "export { static } from 'm.js'",
   5582       "export { let } from 'm.js'",
   5583       "var a; export { a as b, a as c };",
   5584 
   5585       "import 'somemodule.js';",
   5586       "import { } from 'm.js';",
   5587       "import { a } from 'm.js';",
   5588       "import { a, b as d, c, } from 'm.js';",
   5589       "import * as thing from 'm.js';",
   5590       "import thing from 'm.js';",
   5591       "import thing, * as rest from 'm.js';",
   5592       "import thing, { a, b, c } from 'm.js';",
   5593       "import { arguments as a } from 'm.js';",
   5594       "import { for as f } from 'm.js';",
   5595       "import { yield as y } from 'm.js';",
   5596       "import { static as s } from 'm.js';",
   5597       "import { let as l } from 'm.js';",
   5598   };
   5599 
   5600   i::Isolate* isolate = CcTest::i_isolate();
   5601   i::Factory* factory = isolate->factory();
   5602 
   5603   v8::HandleScope handles(CcTest::isolate());
   5604   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   5605   v8::Context::Scope context_scope(context);
   5606 
   5607   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   5608                                         128 * 1024);
   5609 
   5610   for (unsigned i = 0; i < arraysize(kSources); ++i) {
   5611     i::Handle<i::String> source =
   5612         factory->NewStringFromAsciiChecked(kSources[i]);
   5613 
   5614     // Show that parsing as a module works
   5615     {
   5616       i::Handle<i::Script> script = factory->NewScript(source);
   5617       i::Zone zone;
   5618       i::ParseInfo info(&zone, script);
   5619       i::Parser parser(&info);
   5620       info.set_module();
   5621       if (!parser.Parse(&info)) {
   5622         i::Handle<i::JSObject> exception_handle(
   5623             i::JSObject::cast(isolate->pending_exception()));
   5624         i::Handle<i::String> message_string =
   5625             i::Handle<i::String>::cast(i::Object::GetProperty(
   5626                   isolate, exception_handle, "message").ToHandleChecked());
   5627 
   5628         v8::base::OS::Print(
   5629             "Parser failed on:\n"
   5630             "\t%s\n"
   5631             "with error:\n"
   5632             "\t%s\n"
   5633             "However, we expected no error.",
   5634             source->ToCString().get(), message_string->ToCString().get());
   5635         CHECK(false);
   5636       }
   5637     }
   5638 
   5639     // And that parsing a script does not.
   5640     {
   5641       i::Handle<i::Script> script = factory->NewScript(source);
   5642       i::Zone zone;
   5643       i::ParseInfo info(&zone, script);
   5644       i::Parser parser(&info);
   5645       info.set_global();
   5646       CHECK(!parser.Parse(&info));
   5647     }
   5648   }
   5649 }
   5650 
   5651 
   5652 TEST(ImportExportParsingErrors) {
   5653   i::FLAG_harmony_modules = true;
   5654 
   5655   const char* kErrorSources[] = {
   5656       "export {",
   5657       "var a; export { a",
   5658       "var a; export { a,",
   5659       "var a; export { a, ;",
   5660       "var a; export { a as };",
   5661       "var a, b; export { a as , b};",
   5662       "export }",
   5663       "var foo, bar; export { foo bar };",
   5664       "export { foo };",
   5665       "export { , };",
   5666       "export default;",
   5667       "export default var x = 7;",
   5668       "export default let x = 7;",
   5669       "export default const x = 7;",
   5670       "export *;",
   5671       "export * from;",
   5672       "export { Q } from;",
   5673       "export default from 'module.js';",
   5674       "export { for }",
   5675       "export { for as foo }",
   5676       "export { arguments }",
   5677       "export { arguments as foo }",
   5678       "var a; export { a, a };",
   5679       "var a, b; export { a as b, b };",
   5680       "var a, b; export { a as c, b as c };",
   5681       "export default function f(){}; export default class C {};",
   5682       "export default function f(){}; var a; export { a as default };",
   5683 
   5684       "import from;",
   5685       "import from 'm.js';",
   5686       "import { };",
   5687       "import {;",
   5688       "import };",
   5689       "import { , };",
   5690       "import { , } from 'm.js';",
   5691       "import { a } from;",
   5692       "import { a } 'm.js';",
   5693       "import , from 'm.js';",
   5694       "import a , from 'm.js';",
   5695       "import a { b, c } from 'm.js';",
   5696       "import arguments from 'm.js';",
   5697       "import eval from 'm.js';",
   5698       "import { arguments } from 'm.js';",
   5699       "import { eval } from 'm.js';",
   5700       "import { a as arguments } from 'm.js';",
   5701       "import { for } from 'm.js';",
   5702       "import { y as yield } from 'm.js'",
   5703       "import { s as static } from 'm.js'",
   5704       "import { l as let } from 'm.js'",
   5705       "import { x }, def from 'm.js';",
   5706       "import def, def2 from 'm.js';",
   5707       "import * as x, def from 'm.js';",
   5708       "import * as x, * as y from 'm.js';",
   5709       "import {x}, {y} from 'm.js';",
   5710       "import * as x, {y} from 'm.js';",
   5711 
   5712       // TODO(ES6): These two forms should be supported
   5713       "export default function() {};",
   5714       "export default class {};"
   5715   };
   5716 
   5717   i::Isolate* isolate = CcTest::i_isolate();
   5718   i::Factory* factory = isolate->factory();
   5719 
   5720   v8::HandleScope handles(CcTest::isolate());
   5721   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   5722   v8::Context::Scope context_scope(context);
   5723 
   5724   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   5725                                         128 * 1024);
   5726 
   5727   for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
   5728     i::Handle<i::String> source =
   5729         factory->NewStringFromAsciiChecked(kErrorSources[i]);
   5730 
   5731     i::Handle<i::Script> script = factory->NewScript(source);
   5732     i::Zone zone;
   5733     i::ParseInfo info(&zone, script);
   5734     i::Parser parser(&info);
   5735     info.set_module();
   5736     CHECK(!parser.Parse(&info));
   5737   }
   5738 }
   5739 
   5740 
   5741 TEST(ModuleParsingInternals) {
   5742   i::FLAG_harmony_modules = true;
   5743 
   5744   i::Isolate* isolate = CcTest::i_isolate();
   5745   i::Factory* factory = isolate->factory();
   5746   v8::HandleScope handles(CcTest::isolate());
   5747   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   5748   v8::Context::Scope context_scope(context);
   5749   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   5750                                         128 * 1024);
   5751 
   5752   static const char kSource[] =
   5753       "let x = 5;"
   5754       "export { x as y };"
   5755       "import { q as z } from 'm.js';"
   5756       "import n from 'n.js';"
   5757       "export { a as b } from 'm.js';"
   5758       "export * from 'p.js';"
   5759       "import 'q.js'";
   5760   i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
   5761   i::Handle<i::Script> script = factory->NewScript(source);
   5762   i::Zone zone;
   5763   i::ParseInfo info(&zone, script);
   5764   i::Parser parser(&info);
   5765   info.set_module();
   5766   CHECK(parser.Parse(&info));
   5767   CHECK(i::Compiler::Analyze(&info));
   5768   i::FunctionLiteral* func = info.literal();
   5769   i::Scope* module_scope = func->scope();
   5770   i::Scope* outer_scope = module_scope->outer_scope();
   5771   CHECK(outer_scope->is_script_scope());
   5772   CHECK_NULL(outer_scope->outer_scope());
   5773   CHECK(module_scope->is_module_scope());
   5774   i::ModuleDescriptor* descriptor = module_scope->module();
   5775   CHECK_NOT_NULL(descriptor);
   5776   CHECK_EQ(1, descriptor->Length());
   5777   const i::AstRawString* export_name =
   5778       info.ast_value_factory()->GetOneByteString("y");
   5779   const i::AstRawString* local_name =
   5780       descriptor->LookupLocalExport(export_name, &zone);
   5781   CHECK_NOT_NULL(local_name);
   5782   CHECK(local_name->IsOneByteEqualTo("x"));
   5783   i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
   5784   CHECK_EQ(3, declarations->length());
   5785   CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
   5786   i::ImportDeclaration* import_decl =
   5787       declarations->at(1)->AsImportDeclaration();
   5788   CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
   5789   CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
   5790   CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
   5791   import_decl = declarations->at(2)->AsImportDeclaration();
   5792   CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
   5793   CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
   5794   CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
   5795   // TODO(adamk): Add test for indirect exports once they're fully implemented.
   5796   // TODO(adamk): Add test for star exports once they're fully implemented.
   5797   const i::ZoneList<const i::AstRawString*>& requested_modules =
   5798       descriptor->requested_modules();
   5799   CHECK_EQ(4, requested_modules.length());
   5800   CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
   5801   CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
   5802   CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
   5803   CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
   5804 }
   5805 
   5806 
   5807 TEST(DuplicateProtoError) {
   5808   const char* context_data[][2] = {
   5809     {"({", "});"},
   5810     {"'use strict'; ({", "});"},
   5811     {NULL, NULL}
   5812   };
   5813   const char* error_data[] = {
   5814     "__proto__: {}, __proto__: {}",
   5815     "__proto__: {}, \"__proto__\": {}",
   5816     "__proto__: {}, \"__\x70roto__\": {}",
   5817     "__proto__: {}, a: 1, __proto__: {}",
   5818     NULL
   5819   };
   5820 
   5821   RunParserSyncTest(context_data, error_data, kError);
   5822 }
   5823 
   5824 
   5825 TEST(DuplicateProtoNoError) {
   5826   const char* context_data[][2] = {
   5827     {"({", "});"},
   5828     {"'use strict'; ({", "});"},
   5829     {NULL, NULL}
   5830   };
   5831   const char* error_data[] = {
   5832     "__proto__: {}, ['__proto__']: {}",
   5833     "__proto__: {}, __proto__() {}",
   5834     "__proto__: {}, get __proto__() {}",
   5835     "__proto__: {}, set __proto__(v) {}",
   5836     "__proto__: {}, __proto__",
   5837     NULL
   5838   };
   5839 
   5840   RunParserSyncTest(context_data, error_data, kSuccess);
   5841 }
   5842 
   5843 
   5844 TEST(DeclarationsError) {
   5845   const char* context_data[][2] = {{"'use strict'; if (true)", ""},
   5846                                    {"'use strict'; if (false) {} else", ""},
   5847                                    {"'use strict'; while (false)", ""},
   5848                                    {"'use strict'; for (;;)", ""},
   5849                                    {"'use strict'; for (x in y)", ""},
   5850                                    {"'use strict'; do ", " while (false)"},
   5851                                    {"'use strong'; if (true)", ""},
   5852                                    {"'use strong'; if (false) {} else", ""},
   5853                                    {"'use strong'; while (false)", ""},
   5854                                    {"'use strong'; for (;;)", ""},
   5855                                    {"'use strong'; for (x in y)", ""},
   5856                                    {"'use strong'; do ", " while (false)"},
   5857                                    {NULL, NULL}};
   5858 
   5859   const char* statement_data[] = {
   5860     "let x = 1;",
   5861     "const x = 1;",
   5862     "class C {}",
   5863     NULL};
   5864 
   5865   static const ParserFlag always_flags[] = {kAllowStrongMode};
   5866   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
   5867                     always_flags, arraysize(always_flags));
   5868 }
   5869 
   5870 
   5871 void TestLanguageMode(const char* source,
   5872                       i::LanguageMode expected_language_mode) {
   5873   i::Isolate* isolate = CcTest::i_isolate();
   5874   i::Factory* factory = isolate->factory();
   5875   v8::HandleScope handles(CcTest::isolate());
   5876   v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
   5877   v8::Context::Scope context_scope(context);
   5878   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
   5879                                         128 * 1024);
   5880 
   5881   i::Handle<i::Script> script =
   5882       factory->NewScript(factory->NewStringFromAsciiChecked(source));
   5883   i::Zone zone;
   5884   i::ParseInfo info(&zone, script);
   5885   i::Parser parser(&info);
   5886   parser.set_allow_strong_mode(true);
   5887   info.set_global();
   5888   parser.Parse(&info);
   5889   CHECK(info.literal() != NULL);
   5890   CHECK_EQ(expected_language_mode, info.literal()->language_mode());
   5891 }
   5892 
   5893 
   5894 TEST(LanguageModeDirectives) {
   5895   TestLanguageMode("\"use nothing\"", i::SLOPPY);
   5896   TestLanguageMode("\"use strict\"", i::STRICT);
   5897   TestLanguageMode("\"use strong\"", i::STRONG);
   5898 
   5899   TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
   5900   TestLanguageMode("var x = 1; \"use strong\"", i::SLOPPY);
   5901 
   5902   // Test that multiple directives ("use strict" / "use strong") put the parser
   5903   // into the correct mode.
   5904   TestLanguageMode("\"use strict\"; \"use strong\";", i::STRONG);
   5905   TestLanguageMode("\"use strong\"; \"use strict\";", i::STRONG);
   5906 
   5907   TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
   5908   TestLanguageMode("\"use some future directive\"; \"use strong\";", i::STRONG);
   5909 }
   5910 
   5911 
   5912 TEST(PropertyNameEvalArguments) {
   5913   const char* context_data[][2] = {{"'use strict';", ""},
   5914                                    {"'use strong';", ""},
   5915                                    {NULL, NULL}};
   5916 
   5917   const char* statement_data[] = {
   5918       "({eval: 1})",
   5919       "({arguments: 1})",
   5920       "({eval() {}})",
   5921       "({arguments() {}})",
   5922       "({*eval() {}})",
   5923       "({*arguments() {}})",
   5924       "({get eval() {}})",
   5925       "({get arguments() {}})",
   5926       "({set eval(_) {}})",
   5927       "({set arguments(_) {}})",
   5928 
   5929       "class C {eval() {}}",
   5930       "class C {arguments() {}}",
   5931       "class C {*eval() {}}",
   5932       "class C {*arguments() {}}",
   5933       "class C {get eval() {}}",
   5934       "class C {get arguments() {}}",
   5935       "class C {set eval(_) {}}",
   5936       "class C {set arguments(_) {}}",
   5937 
   5938       "class C {static eval() {}}",
   5939       "class C {static arguments() {}}",
   5940       "class C {static *eval() {}}",
   5941       "class C {static *arguments() {}}",
   5942       "class C {static get eval() {}}",
   5943       "class C {static get arguments() {}}",
   5944       "class C {static set eval(_) {}}",
   5945       "class C {static set arguments(_) {}}",
   5946 
   5947       NULL};
   5948 
   5949   static const ParserFlag always_flags[] = {kAllowStrongMode};
   5950   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
   5951                     always_flags, arraysize(always_flags));
   5952 }
   5953 
   5954 
   5955 TEST(FunctionLiteralDuplicateParameters) {
   5956   const char* strict_context_data[][2] =
   5957       {{"'use strict';(function(", "){})();"},
   5958        {"(function(", ") { 'use strict'; })();"},
   5959        {"'use strict'; function fn(", ") {}; fn();"},
   5960        {"function fn(", ") { 'use strict'; }; fn();"},
   5961        {"'use strong';(function(", "){})();"},
   5962        {"(function(", ") { 'use strong'; })();"},
   5963        {"'use strong'; function fn(", ") {}; fn();"},
   5964        {"function fn(", ") { 'use strong'; }; fn();"},
   5965        {NULL, NULL}};
   5966 
   5967   const char* sloppy_context_data[][2] =
   5968       {{"(function(", "){})();"},
   5969        {"(function(", ") {})();"},
   5970        {"function fn(", ") {}; fn();"},
   5971        {"function fn(", ") {}; fn();"},
   5972        {NULL, NULL}};
   5973 
   5974   const char* data[] = {
   5975       "a, a",
   5976       "a, a, a",
   5977       "b, a, a",
   5978       "a, b, c, c",
   5979       "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
   5980       NULL};
   5981 
   5982   static const ParserFlag always_flags[] = { kAllowStrongMode };
   5983   RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
   5984                     arraysize(always_flags));
   5985   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, NULL, 0);
   5986 }
   5987 
   5988 
   5989 TEST(VarForbiddenInStrongMode) {
   5990   const char* strong_context_data[][2] =
   5991       {{"'use strong'; ", ""},
   5992        {"function f() {'use strong'; ", "}"},
   5993        {"function f() {'use strong';  while (true) { ", "} }"},
   5994        {NULL, NULL}};
   5995 
   5996   const char* strict_context_data[][2] =
   5997       {{"'use strict'; ", ""},
   5998        {"function f() {'use strict'; ", "}"},
   5999        {"function f() {'use strict'; while (true) { ", "} }"},
   6000        {NULL, NULL}};
   6001 
   6002   const char* sloppy_context_data[][2] =
   6003       {{"", ""},
   6004        {"function f() { ", "}"},
   6005        {NULL, NULL}};
   6006 
   6007   const char* var_declarations[] = {
   6008     "var x = 0;",
   6009     "for (var i = 0; i < 10; i++) { }",
   6010     NULL};
   6011 
   6012   const char* let_declarations[] = {
   6013     "let x = 0;",
   6014     "for (let i = 0; i < 10; i++) { }",
   6015     NULL};
   6016 
   6017   const char* const_declarations[] = {
   6018     "const x = 0;",
   6019     NULL};
   6020 
   6021   static const ParserFlag always_flags[] = {kAllowStrongMode};
   6022   RunParserSyncTest(strong_context_data, var_declarations, kError, NULL, 0,
   6023                     always_flags, arraysize(always_flags));
   6024   RunParserSyncTest(strong_context_data, let_declarations, kSuccess, NULL, 0,
   6025                     always_flags, arraysize(always_flags));
   6026   RunParserSyncTest(strong_context_data, const_declarations, kSuccess, NULL, 0,
   6027                     always_flags, arraysize(always_flags));
   6028 
   6029   RunParserSyncTest(strict_context_data, var_declarations, kSuccess, NULL, 0,
   6030                     always_flags, arraysize(always_flags));
   6031   RunParserSyncTest(strict_context_data, let_declarations, kSuccess, NULL, 0,
   6032                     always_flags, arraysize(always_flags));
   6033 
   6034   RunParserSyncTest(sloppy_context_data, var_declarations, kSuccess, NULL, 0,
   6035                     always_flags, arraysize(always_flags));
   6036   // At the moment, let declarations are only available in strict mode.
   6037   RunParserSyncTest(sloppy_context_data, let_declarations, kError, NULL, 0,
   6038                     always_flags, arraysize(always_flags));
   6039 }
   6040 
   6041 
   6042 TEST(StrongEmptySubStatements) {
   6043   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6044   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6045   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6046 
   6047   const char* data_error[] = {
   6048       "if (1);",
   6049       "if (1) {} else;",
   6050       "while (1);",
   6051       "do; while (1);",
   6052       "for (;;);",
   6053       "for (x in []);",
   6054       "for (x of []);",
   6055       "for (const x = 0;;);",
   6056       "for (const x in []);",
   6057       "for (const x of []);",
   6058       NULL};
   6059 
   6060   const char* data_success[] =  {
   6061       "if (1) {} else {}",
   6062       "switch(1) {}",
   6063       "1+1;;",
   6064       "1+1; ;",
   6065       NULL};
   6066 
   6067   static const ParserFlag always_flags[] = {
   6068       kAllowStrongMode,
   6069   };
   6070   RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
   6071                     always_flags, arraysize(always_flags));
   6072   RunParserSyncTest(strict_context_data, data_error, kSuccess, NULL, 0,
   6073                     always_flags, arraysize(always_flags));
   6074   RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
   6075                     always_flags, arraysize(always_flags));
   6076   RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
   6077                     always_flags, arraysize(always_flags));
   6078 }
   6079 
   6080 
   6081 TEST(StrongForIn) {
   6082   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6083   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6084   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6085 
   6086   const char* data[] = {
   6087       "for (x in []) {}",
   6088       "for (const x in []) {}",
   6089       NULL};
   6090 
   6091   static const ParserFlag always_flags[] = {
   6092       kAllowStrongMode,
   6093   };
   6094   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
   6095                     arraysize(always_flags));
   6096   RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
   6097                     arraysize(always_flags));
   6098   RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
   6099                     arraysize(always_flags));
   6100 }
   6101 
   6102 
   6103 TEST(StrongConstructorThis) {
   6104   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6105   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6106   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6107 
   6108   const char* error_data[] = {
   6109       "class C { constructor() { this; } }",
   6110       "class C { constructor() { this.a; } }",
   6111       "class C { constructor() { this['a']; } }",
   6112       "class C { constructor() { (this); } }",
   6113       "class C { constructor() { this(); } }",
   6114       // TODO(rossberg): arrow functions not handled yet.
   6115       // "class C { constructor() { () => this; } }",
   6116       "class C { constructor() { this.a = 0, 0; } }",
   6117       "class C { constructor() { (this.a = 0); } }",
   6118       // "class C { constructor() { (() => this.a = 0)(); } }",
   6119       "class C { constructor() { { this.a = 0; } } }",
   6120       "class C { constructor() { if (1) this.a = 0; } }",
   6121       "class C { constructor() { label: this.a = 0; } }",
   6122       "class C { constructor() { this.a = this.b; } }",
   6123       "class C { constructor() { this.a = {b: 1}; this.a.b } }",
   6124       "class C { constructor() { this.a = {b: 1}; this.a.b = 0 } }",
   6125       "class C { constructor() { this.a = function(){}; this.a() } }",
   6126       NULL};
   6127 
   6128   const char* success_data[] = {
   6129       "class C { constructor() { this.a = 0; } }",
   6130       "class C { constructor() { label: 0; this.a = 0; this.b = 6; } }",
   6131       NULL};
   6132 
   6133   static const ParserFlag always_flags[] = {kAllowStrongMode};
   6134   RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
   6135                     always_flags, arraysize(always_flags));
   6136   RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
   6137                     always_flags, arraysize(always_flags));
   6138   RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
   6139                     always_flags, arraysize(always_flags));
   6140 
   6141   RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
   6142                     always_flags, arraysize(always_flags));
   6143   RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
   6144                     always_flags, arraysize(always_flags));
   6145   RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
   6146                     always_flags, arraysize(always_flags));
   6147 }
   6148 
   6149 
   6150 TEST(StrongConstructorSuper) {
   6151   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6152   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6153   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6154 
   6155   const char* error_data[] = {
   6156       "class C extends Object { constructor() {} }",
   6157       "class C extends Object { constructor() { super.a; } }",
   6158       "class C extends Object { constructor() { super['a']; } }",
   6159       "class C extends Object { constructor() { super.a = 0; } }",
   6160       "class C extends Object { constructor() { (super.a); } }",
   6161       // TODO(rossberg): arrow functions do not handle super yet.
   6162       // "class C extends Object { constructor() { () => super.a; } }",
   6163       "class C extends Object { constructor() { super(), 0; } }",
   6164       "class C extends Object { constructor() { (super()); } }",
   6165       // "class C extends Object { constructor() { (() => super())(); } }",
   6166       "class C extends Object { constructor() { { super(); } } }",
   6167       "class C extends Object { constructor() { if (1) super(); } }",
   6168       "class C extends Object { constructor() { label: super(); } }",
   6169       "class C extends Object { constructor() { super(), super(); } }",
   6170       "class C extends Object { constructor() { super(); super(); } }",
   6171       "class C extends Object { constructor() { super(); (super()); } }",
   6172       "class C extends Object { constructor() { super(); { super() } } }",
   6173       "class C extends Object { constructor() { this.a = 0, super(); } }",
   6174       "class C extends Object { constructor() { this.a = 0; super(); } }",
   6175       "class C extends Object { constructor() { super(this.a = 0); } }",
   6176       "class C extends Object { constructor() { super().a; } }",
   6177       NULL};
   6178 
   6179   const char* success_data[] = {
   6180       "class C extends Object { constructor() { super(); } }",
   6181       "class C extends Object { constructor() { label: 66; super(); } }",
   6182       "class C extends Object { constructor() { super(3); this.x = 0; } }",
   6183       "class C extends Object { constructor() { 3; super(3); this.x = 0; } }",
   6184       NULL};
   6185 
   6186   static const ParserFlag always_flags[] = {kAllowStrongMode};
   6187   RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
   6188                     always_flags, arraysize(always_flags));
   6189   RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
   6190                     always_flags, arraysize(always_flags));
   6191   RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
   6192                     always_flags, arraysize(always_flags));
   6193 
   6194   RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
   6195                     always_flags, arraysize(always_flags));
   6196   RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
   6197                     always_flags, arraysize(always_flags));
   6198   RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
   6199                     always_flags, arraysize(always_flags));
   6200 }
   6201 
   6202 
   6203 TEST(StrongConstructorReturns) {
   6204   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6205   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6206   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6207 
   6208   const char* error_data[] = {
   6209       "class C extends Object { constructor() { super(); return {}; } }",
   6210       "class C extends Object { constructor() { super(); { return {}; } } }",
   6211       "class C extends Object { constructor() { super(); if (1) return {}; } }",
   6212       "class C extends Object { constructor() { return; super(); } }",
   6213       "class C extends Object { constructor() { { return; } super(); } }",
   6214       "class C extends Object { constructor() { if (0) return; super(); } }",
   6215       "class C { constructor() { return; this.a = 0; } }",
   6216       "class C { constructor() { { return; } this.a = 0; } }",
   6217       "class C { constructor() { if (0) return; this.a = 0; } }",
   6218       "class C { constructor() { this.a = 0; if (0) return; this.b = 0; } }",
   6219       NULL};
   6220 
   6221   const char* success_data[] = {
   6222       "class C extends Object { constructor() { super(); return; } }",
   6223       "class C extends Object { constructor() { super(); { return } } }",
   6224       "class C extends Object { constructor() { super(); if (1) return; } }",
   6225       "class C { constructor() { this.a = 0; return; } }",
   6226       "class C { constructor() { this.a = 0; { return; }  } }",
   6227       "class C { constructor() { this.a = 0; if (0) return; 65; } }",
   6228       "class C extends Array { constructor() { super(); this.a = 9; return } }",
   6229       NULL};
   6230 
   6231   static const ParserFlag always_flags[] = {kAllowStrongMode};
   6232   RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
   6233                     always_flags, arraysize(always_flags));
   6234   RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
   6235                     always_flags, arraysize(always_flags));
   6236   RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
   6237                     always_flags, arraysize(always_flags));
   6238 
   6239   RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
   6240                     always_flags, arraysize(always_flags));
   6241   RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
   6242                     always_flags, arraysize(always_flags));
   6243   RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
   6244                     always_flags, arraysize(always_flags));
   6245 }
   6246 
   6247 
   6248 TEST(StrongConstructorDirective) {
   6249   const char* context_data[][2] = {{"class c { ", " }"},
   6250                                    {"(class c { ", " });"},
   6251                                    {"let a = (class c { ", " });"},
   6252                                    {NULL}};
   6253 
   6254   const char* error_data[] = {
   6255       "constructor() { \"use strong\" }",
   6256       "constructor(...rest) { \"use strong\" }",
   6257       "foo() {} constructor() { \"use strong\" }",
   6258       "foo(...rest) { \"use strict\" } constructor() { \"use strong\" }", NULL};
   6259 
   6260   const char* success_data[] = {
   6261       "constructor() { \"use strict\" }", "foo() { \"use strong\" }",
   6262       "foo() { \"use strong\" } constructor() {}", NULL};
   6263 
   6264   static const ParserFlag always_flags[] = {
   6265       kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowStrongMode};
   6266 
   6267   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
   6268                     arraysize(always_flags));
   6269   RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
   6270                     arraysize(always_flags));
   6271 }
   6272 
   6273 
   6274 TEST(StrongUndefinedLocal) {
   6275   const char* context_data[][2] = {{"", ""}, {NULL}};
   6276 
   6277   const char* data[] = {
   6278       "function undefined() {'use strong';}",
   6279       "function* undefined() {'use strong';}",
   6280       "(function undefined() {'use strong';});",
   6281       "{foo: (function undefined(){'use strong';})};",
   6282       "(function* undefined() {'use strong';})",
   6283       "{foo: (function* undefined(){'use strong';})};",
   6284       "function foo(a, b, undefined, c, d) {'use strong';}",
   6285       "function* foo(a, b, undefined, c, d) {'use strong';}",
   6286       "(function foo(a, b, undefined, c, d) {'use strong';})",
   6287       "{foo: (function foo(a, b, undefined, c, d) {'use strong';})};",
   6288       "(function* foo(a, b, undefined, c, d) {'use strong';})",
   6289       "{foo: (function* foo(a, b, undefined, c, d) {'use strong';})};",
   6290       "class C { foo(a, b, undefined, c, d) {'use strong';} }",
   6291       "class C { *foo(a, b, undefined, c, d) {'use strong';} }",
   6292       "({ foo(a, b, undefined, c, d) {'use strong';} });",
   6293       "{ *foo(a, b, undefined, c, d) {'use strong';} });",
   6294       "class undefined {'use strong'}",
   6295       "(class undefined {'use strong'});",
   6296       NULL};
   6297 
   6298   static const ParserFlag always_flags[] = {
   6299       kAllowStrongMode, kAllowHarmonySloppy
   6300   };
   6301 
   6302   RunParserSyncTest(context_data, data, kError, NULL, 0,
   6303                     always_flags, arraysize(always_flags));
   6304 }
   6305 
   6306 
   6307 TEST(StrongUndefinedArrow) {
   6308   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6309   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
   6310   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6311 
   6312   const char* data[] = {
   6313       "(undefined => {return});",
   6314       "((undefined, b, c) => {return});",
   6315       "((a, undefined, c) => {return});",
   6316       "((a, b, undefined) => {return});",
   6317       NULL};
   6318 
   6319   const char* local_strong[] = {
   6320       "(undefined => {'use strong';});",
   6321       "((undefined, b, c) => {'use strong';});",
   6322       "((a, undefined, c) => {'use strong';});",
   6323       "((a, b, undefined) => {'use strong';});",
   6324       NULL};
   6325 
   6326   static const ParserFlag always_flags[] = {kAllowStrongMode};
   6327   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
   6328                     arraysize(always_flags));
   6329   RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
   6330                     arraysize(always_flags));
   6331   RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
   6332                     arraysize(always_flags));
   6333   RunParserSyncTest(sloppy_context_data, local_strong, kError, NULL, 0,
   6334                     always_flags, arraysize(always_flags));
   6335 }
   6336 
   6337 
   6338 TEST(StrongDirectEval) {
   6339   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
   6340   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
   6341 
   6342   const char* error_data[] = {
   6343       "eval();",
   6344       "eval([]);",
   6345       "(eval)();",
   6346       "(((eval)))();",
   6347       "eval('function f() {}');",
   6348       "function f() {eval()}",
   6349       NULL};
   6350 
   6351   const char* success_data[] = {
   6352       "eval;",
   6353       "eval`foo`;",
   6354       "let foo = eval; foo();",
   6355       "(1, eval)();",
   6356       NULL};
   6357 
   6358   static const ParserFlag always_flags[] = {
   6359       kAllowStrongMode
   6360   };
   6361 
   6362   RunParserSyncTest(sloppy_context_data, error_data, kSuccess, NULL, 0,
   6363                     always_flags, arraysize(always_flags));
   6364   RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
   6365                     always_flags, arraysize(always_flags));
   6366   RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
   6367                     always_flags, arraysize(always_flags));
   6368 }
   6369 
   6370 
   6371 TEST(StrongSwitchFallthrough) {
   6372   const char* sloppy_context_data[][2] = {
   6373       {"function f() { foo:for(;;) { switch(1) {", "};}}"},
   6374       {NULL, NULL}
   6375   };
   6376   const char* strong_context_data[][2] = {
   6377       {"function f() { 'use strong'; foo:for(;;) { switch(1) {", "};}}"},
   6378       {NULL, NULL}
   6379   };
   6380 
   6381   const char* data_success[] = {
   6382       "",
   6383       "case 1:",
   6384       "case 1: case 2:",
   6385       "case 1: break;",
   6386       "default: throw new TypeError();",
   6387       "case 1: case 2: null",
   6388       "case 1: case 2: default: 1+1",
   6389       "case 1: break; case 2: return; default:",
   6390       "case 1: break foo; case 2: return; default:",
   6391       "case 1: case 2: break; case 3: continue; case 4: default:",
   6392       "case 1: case 2: break; case 3: continue foo; case 4: default:",
   6393       "case 1: case 2: {{return;}} case 3: default:",
   6394       "case 1: case 2: case 3: default: {1+1;{continue;}}",
   6395       "case 1: case 2: {1+1;{1+1;{continue;}}} case 3: default:",
   6396       "case 1: if (1) break; else continue; case 2: case 3: default:",
   6397       "case 1: case 2: if (1) {{break;}} else break; case 3: default:",
   6398       "case 1: if (1) break; else {if (1) break; else break;} case 2: default:",
   6399       "case 1: if (1) {if (1) break; else break;} else break; case 2: default:",
   6400       NULL};
   6401 
   6402   const char* data_error[] = {
   6403       "case 1: case 2: (function(){return}); default:",
   6404       "case 1: 1+1; case 2:",
   6405       "case 1: bar: break bar; case 2: break;",
   6406       "case 1: bar:return; case 2:",
   6407       "case 1: bar:{ continue;} case 2:",
   6408       "case 1: break; case 2: bar:{ throw new TypeError() } default:",
   6409       "case 1: case 2: { bar:{ { break;} } } default: break;",
   6410       "case 1: if (1) break; else {}; case 2: default:",
   6411       "case 1: case 2: if (1) break; default:",
   6412       "case 1: case 2: if (1) break; else 0; default:",
   6413       "case 1: case 2: if (1) 0; else break; default:",
   6414       "case 1: case 2: case 3: if (1) {} default:",
   6415       "case 1: bar:if (1) break; else continue; case 2: case 3: default:",
   6416       NULL};
   6417 
   6418   static const ParserFlag always_flags[] = {
   6419       kAllowStrongMode
   6420   };
   6421   RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
   6422                     always_flags, arraysize(always_flags));
   6423   RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
   6424                     always_flags, arraysize(always_flags));
   6425   RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
   6426                     always_flags, arraysize(always_flags));
   6427 }
   6428 
   6429 
   6430 TEST(ArrowFunctionASIErrors) {
   6431   const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
   6432                                    {NULL, NULL}};
   6433 
   6434   const char* data[] = {
   6435       "(a\n=> a)(1)",
   6436       "(a/*\n*/=> a)(1)",
   6437       "((a)\n=> a)(1)",
   6438       "((a)/*\n*/=> a)(1)",
   6439       "((a, b)\n=> a + b)(1, 2)",
   6440       "((a, b)/*\n*/=> a + b)(1, 2)",
   6441       NULL};
   6442   RunParserSyncTest(context_data, data, kError);
   6443 }
   6444 
   6445 
   6446 TEST(StrongModeFreeVariablesDeclaredByPreviousScript) {
   6447   i::FLAG_strong_mode = true;
   6448   i::FLAG_legacy_const = true;
   6449   v8::V8::Initialize();
   6450   v8::HandleScope scope(CcTest::isolate());
   6451   v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
   6452   v8::TryCatch try_catch(CcTest::isolate());
   6453 
   6454   // Introduce a bunch of variables, in all language modes.
   6455   const char* script1 =
   6456       "var my_var1 = 0;        \n"
   6457       "function my_func1() { } \n"
   6458       "const my_const1 = 0;    \n";
   6459   CompileRun(v8_str(script1));
   6460   CHECK(!try_catch.HasCaught());
   6461 
   6462   const char* script2 =
   6463       "\"use strict\";         \n"
   6464       "let my_var2 = 0;        \n"
   6465       "function my_func2() { } \n"
   6466       "const my_const2 = 0     \n";
   6467   CompileRun(v8_str(script2));
   6468   CHECK(!try_catch.HasCaught());
   6469 
   6470   const char* script3 =
   6471       "\"use strong\";         \n"
   6472       "let my_var3 = 0;        \n"
   6473       "function my_func3() { } \n"
   6474       "const my_const3 = 0;    \n";
   6475   CompileRun(v8_str(script3));
   6476   CHECK(!try_catch.HasCaught());
   6477 
   6478   // Sloppy eval introduces variables in the surrounding scope.
   6479   const char* script4 =
   6480       "eval('var my_var4 = 0;')        \n"
   6481       "eval('function my_func4() { }') \n"
   6482       "eval('const my_const4 = 0;')    \n";
   6483   CompileRun(v8_str(script4));
   6484   CHECK(!try_catch.HasCaught());
   6485 
   6486   // Test that referencing these variables work.
   6487   const char* script5 =
   6488       "\"use strong\";         \n"
   6489       "my_var1;                \n"
   6490       "my_func1;               \n"
   6491       "my_const1;              \n"
   6492       "my_var2;                \n"
   6493       "my_func2;               \n"
   6494       "my_const2;              \n"
   6495       "my_var3;                \n"
   6496       "my_func3;               \n"
   6497       "my_const3;              \n"
   6498       "my_var4;                \n"
   6499       "my_func4;               \n"
   6500       "my_const4;              \n";
   6501   CompileRun(v8_str(script5));
   6502   CHECK(!try_catch.HasCaught());
   6503 }
   6504 
   6505 
   6506 TEST(StrongModeFreeVariablesDeclaredByLanguage) {
   6507   i::FLAG_strong_mode = true;
   6508   v8::V8::Initialize();
   6509   v8::HandleScope scope(CcTest::isolate());
   6510   v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
   6511   v8::TryCatch try_catch(CcTest::isolate());
   6512 
   6513   const char* script1 =
   6514       "\"use strong\";         \n"
   6515       "Math;                   \n"
   6516       "RegExp;                 \n";
   6517   CompileRun(v8_str(script1));
   6518   CHECK(!try_catch.HasCaught());
   6519 }
   6520 
   6521 
   6522 TEST(StrongModeFreeVariablesDeclaredInGlobalPrototype) {
   6523   i::FLAG_strong_mode = true;
   6524   v8::V8::Initialize();
   6525   v8::HandleScope scope(CcTest::isolate());
   6526   v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
   6527   v8::TryCatch try_catch(CcTest::isolate());
   6528 
   6529   const char* script1 = "this.__proto__.my_var = 0;\n";
   6530   CompileRun(v8_str(script1));
   6531   CHECK(!try_catch.HasCaught());
   6532 
   6533   const char* script2 =
   6534       "\"use strong\";         \n"
   6535       "my_var;                 \n";
   6536   CompileRun(v8_str(script2));
   6537   CHECK(!try_catch.HasCaught());
   6538 }
   6539 
   6540 
   6541 TEST(StrongModeFreeVariablesNotDeclared) {
   6542   i::FLAG_strong_mode = true;
   6543   v8::V8::Initialize();
   6544   v8::HandleScope scope(CcTest::isolate());
   6545   v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
   6546   v8::TryCatch try_catch(CcTest::isolate());
   6547 
   6548   // Test that referencing unintroduced variables in sloppy mode is ok.
   6549   const char* script1 =
   6550       "if (false) {            \n"
   6551       "  not_there1;           \n"
   6552       "}                       \n";
   6553   CompileRun(v8_str(script1));
   6554   CHECK(!try_catch.HasCaught());
   6555 
   6556   // But not in strong mode.
   6557   {
   6558     const char* script2 =
   6559         "\"use strong\";         \n"
   6560         "if (false) {            \n"
   6561         "  not_there2;           \n"
   6562         "}                       \n";
   6563     v8::TryCatch try_catch2(CcTest::isolate());
   6564     v8_compile(v8_str(script2));
   6565     CHECK(try_catch2.HasCaught());
   6566     v8::String::Utf8Value exception(try_catch2.Exception());
   6567     CHECK_EQ(0,
   6568              strcmp(
   6569                  "ReferenceError: In strong mode, using an undeclared global "
   6570                  "variable 'not_there2' is not allowed",
   6571                  *exception));
   6572   }
   6573 
   6574   // Check that the variable reference is detected inside a strong function too,
   6575   // even if the script scope is not strong.
   6576   {
   6577     const char* script3 =
   6578         "(function not_lazy() {  \n"
   6579         "  \"use strong\";       \n"
   6580         "  if (false) {          \n"
   6581         "    not_there3;         \n"
   6582         "  }                     \n"
   6583         "})();                   \n";
   6584     v8::TryCatch try_catch2(CcTest::isolate());
   6585     v8_compile(v8_str(script3));
   6586     CHECK(try_catch2.HasCaught());
   6587     v8::String::Utf8Value exception(try_catch2.Exception());
   6588     CHECK_EQ(0,
   6589              strcmp(
   6590                  "ReferenceError: In strong mode, using an undeclared global "
   6591                  "variable 'not_there3' is not allowed",
   6592                  *exception));
   6593   }
   6594 }
   6595 
   6596 
   6597 TEST(DestructuringPositiveTests) {
   6598   i::FLAG_harmony_destructuring_bind = true;
   6599 
   6600   const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
   6601                                    {"var ", " = {};"},
   6602                                    {"'use strict'; const ", " = {};"},
   6603                                    {"function f(", ") {}"},
   6604                                    {"function f(argument1, ", ") {}"},
   6605                                    {"var f = (", ") => {};"},
   6606                                    {"var f = (argument1,", ") => {};"},
   6607                                    {"try {} catch(", ") {}"},
   6608                                    {NULL, NULL}};
   6609 
   6610   // clang-format off
   6611   const char* data[] = {
   6612     "a",
   6613     "{ x : y }",
   6614     "{ x : y = 1 }",
   6615     "{ get, set }",
   6616     "{ get = 1, set = 2 }",
   6617     "[a]",
   6618     "[a = 1]",
   6619     "[a,b,c]",
   6620     "[a, b = 42, c]",
   6621     "{ x : x, y : y }",
   6622     "{ x : x = 1, y : y }",
   6623     "{ x : x, y : y = 42 }",
   6624     "[]",
   6625     "{}",
   6626     "[{x:x, y:y}, [a,b,c]]",
   6627     "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
   6628     "{x}",
   6629     "{x, y}",
   6630     "{x = 42, y = 15}",
   6631     "[a,,b]",
   6632     "{42 : x}",
   6633     "{42 : x = 42}",
   6634     "{42e-2 : x}",
   6635     "{42e-2 : x = 42}",
   6636     "{x : y, x : z}",
   6637     "{'hi' : x}",
   6638     "{'hi' : x = 42}",
   6639     "{var: x}",
   6640     "{var: x = 42}",
   6641     "{[x] : z}",
   6642     "{[1+1] : z}",
   6643     "{[foo()] : z}",
   6644     "{}",
   6645     "[...rest]",
   6646     "[a,b,...rest]",
   6647     "[a,,...rest]",
   6648     NULL};
   6649   // clang-format on
   6650   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   6651   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
   6652                     arraysize(always_flags));
   6653 }
   6654 
   6655 
   6656 TEST(DestructuringNegativeTests) {
   6657   i::FLAG_harmony_destructuring_bind = true;
   6658   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   6659 
   6660   {  // All modes.
   6661     const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
   6662                                      {"var ", " = {};"},
   6663                                      {"'use strict'; const ", " = {};"},
   6664                                      {"function f(", ") {}"},
   6665                                      {"function f(argument1, ", ") {}"},
   6666                                      {"var f = (", ") => {};"},
   6667                                      {"var f = ", " => {};"},
   6668                                      {"var f = (argument1,", ") => {};"},
   6669                                      {"try {} catch(", ") {}"},
   6670                                      {NULL, NULL}};
   6671 
   6672     // clang-format off
   6673     const char* data[] = {
   6674         "a++",
   6675         "++a",
   6676         "delete a",
   6677         "void a",
   6678         "typeof a",
   6679         "--a",
   6680         "+a",
   6681         "-a",
   6682         "~a",
   6683         "!a",
   6684         "{ x : y++ }",
   6685         "[a++]",
   6686         "(x => y)",
   6687         "a[i]", "a()",
   6688         "a.b",
   6689         "new a",
   6690         "a + a",
   6691         "a - a",
   6692         "a * a",
   6693         "a / a",
   6694         "a == a",
   6695         "a != a",
   6696         "a > a",
   6697         "a < a",
   6698         "a <<< a",
   6699         "a >>> a",
   6700         "function a() {}",
   6701         "a`bcd`",
   6702         "this",
   6703         "null",
   6704         "true",
   6705         "false",
   6706         "1",
   6707         "'abc'",
   6708         "/abc/",
   6709         "`abc`",
   6710         "class {}",
   6711         "{+2 : x}",
   6712         "{-2 : x}",
   6713         "var",
   6714         "[var]",
   6715         "{x : {y : var}}",
   6716         "{x : x = a+}",
   6717         "{x : x = (a+)}",
   6718         "{x : x += a}",
   6719         "{m() {} = 0}",
   6720         "{[1+1]}",
   6721         "[...rest, x]",
   6722         "[a,b,...rest, x]",
   6723         "[a,,...rest, x]",
   6724         "[...rest,]",
   6725         "[a,b,...rest,]",
   6726         "[a,,...rest,]",
   6727         "[...rest,...rest1]",
   6728         "[a,b,...rest,...rest1]",
   6729         "[a,,..rest,...rest1]",
   6730         "{ x : 3 }",
   6731         "{ x : 'foo' }",
   6732         "{ x : /foo/ }",
   6733         "{ x : `foo` }",
   6734         "{ get a() {} }",
   6735         "{ set a() {} }",
   6736         "{ method() {} }",
   6737         "{ *method() {} }",
   6738         NULL};
   6739     // clang-format on
   6740     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   6741                       arraysize(always_flags));
   6742   }
   6743 
   6744   {  // All modes.
   6745     const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
   6746                                      {"var ", " = {};"},
   6747                                      {"'use strict'; const ", " = {};"},
   6748                                      {"function f(", ") {}"},
   6749                                      {"function f(argument1, ", ") {}"},
   6750                                      {"var f = (", ") => {};"},
   6751                                      {"var f = (argument1,", ") => {};"},
   6752                                      {NULL, NULL}};
   6753 
   6754     // clang-format off
   6755     const char* data[] = {
   6756         "x => x",
   6757         "() => x",
   6758         NULL};
   6759     // clang-format on
   6760     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   6761                       arraysize(always_flags));
   6762   }
   6763 
   6764   {  // Strict mode.
   6765     const char* context_data[][2] = {
   6766         {"'use strict'; let ", " = {};"},
   6767         {"'use strict'; const ", " = {};"},
   6768         {"'use strict'; function f(", ") {}"},
   6769         {"'use strict'; function f(argument1, ", ") {}"},
   6770         {NULL, NULL}};
   6771 
   6772     // clang-format off
   6773     const char* data[] = {
   6774       "[eval]",
   6775       "{ a : arguments }",
   6776       "[public]",
   6777       "{ x : private }",
   6778       NULL};
   6779     // clang-format on
   6780     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   6781                       arraysize(always_flags));
   6782   }
   6783 
   6784   {  // 'yield' in generators.
   6785     const char* context_data[][2] = {
   6786         {"function*() { var ", " = {};"},
   6787         {"function*() { 'use strict'; let ", " = {};"},
   6788         {"function*() { 'use strict'; const ", " = {};"},
   6789         {NULL, NULL}};
   6790 
   6791     // clang-format off
   6792     const char* data[] = {
   6793       "yield",
   6794       "[yield]",
   6795       "{ x : yield }",
   6796       NULL};
   6797     // clang-format on
   6798     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   6799                       arraysize(always_flags));
   6800   }
   6801 
   6802   { // Declaration-specific errors
   6803     const char* context_data[][2] = {{"'use strict'; var ", ""},
   6804                                      {"'use strict'; let ", ""},
   6805                                      {"'use strict'; const ", ""},
   6806                                      {"'use strict'; for (var ", ";;) {}"},
   6807                                      {"'use strict'; for (let ", ";;) {}"},
   6808                                      {"'use strict'; for (const ", ";;) {}"},
   6809                                      {"var ", ""},
   6810                                      {"let ", ""},
   6811                                      {"const ", ""},
   6812                                      {"for (var ", ";;) {}"},
   6813                                      {"for (let ", ";;) {}"},
   6814                                      {"for (const ", ";;) {}"},
   6815                                      {NULL, NULL}};
   6816 
   6817     // clang-format off
   6818     const char* data[] = {
   6819       "{ a }",
   6820       "[ a ]",
   6821       NULL};
   6822     // clang-format on
   6823     static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
   6824                                               kAllowHarmonySloppyLet};
   6825     RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   6826                       arraysize(always_flags));
   6827   }
   6828 }
   6829 
   6830 
   6831 TEST(DestructuringAssignmentPositiveTests) {
   6832   const char* context_data[][2] = {
   6833       {"'use strict'; let x, y, z; (", " = {});"},
   6834       {"var x, y, z; (", " = {});"},
   6835       {"'use strict'; let x, y, z; for (x in ", " = {});"},
   6836       {"'use strict'; let x, y, z; for (x of ", " = {});"},
   6837       {"var x, y, z; for (x in ", " = {});"},
   6838       {"var x, y, z; for (x of ", " = {});"},
   6839       {"var x, y, z; for (", " in {});"},
   6840       {"var x, y, z; for (", " of {});"},
   6841       {"'use strict'; var x, y, z; for (", " in {});"},
   6842       {"'use strict'; var x, y, z; for (", " of {});"},
   6843       {NULL, NULL}};
   6844 
   6845   const char* mixed_assignments_context_data[][2] = {
   6846       {"'use strict'; let x, y, z; (", " = z = {});"},
   6847       {"var x, y, z; (", " = z = {});"},
   6848       {"'use strict'; let x, y, z; (x = ", " = z = {});"},
   6849       {"var x, y, z; (x = ", " = z = {});"},
   6850       {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
   6851       {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
   6852       {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
   6853       {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
   6854       {"var x, y, z; for (x in ", " = z = {});"},
   6855       {"var x, y, z; for (x in x = ", " = z = {});"},
   6856       {"var x, y, z; for (x of ", " = z = {});"},
   6857       {"var x, y, z; for (x of x = ", " = z = {});"},
   6858       {NULL, NULL}};
   6859 
   6860   // clang-format off
   6861   const char* data[] = {
   6862     "x",
   6863 
   6864     "{ x : y }",
   6865     "{ x : foo().y }",
   6866     "{ x : foo()[y] }",
   6867     "{ x : y.z }",
   6868     "{ x : y[z] }",
   6869     "{ x : { y } }",
   6870     "{ x : { foo: y } }",
   6871     "{ x : { foo: foo().y } }",
   6872     "{ x : { foo: foo()[y] } }",
   6873     "{ x : { foo: y.z } }",
   6874     "{ x : { foo: y[z] } }",
   6875     "{ x : [ y ] }",
   6876     "{ x : [ foo().y ] }",
   6877     "{ x : [ foo()[y] ] }",
   6878     "{ x : [ y.z ] }",
   6879     "{ x : [ y[z] ] }",
   6880 
   6881     "{ x : y = 10 }",
   6882     "{ x : foo().y = 10 }",
   6883     "{ x : foo()[y] = 10 }",
   6884     "{ x : y.z = 10 }",
   6885     "{ x : y[z] = 10 }",
   6886     "{ x : { y = 10 } = {} }",
   6887     "{ x : { foo: y = 10 } = {} }",
   6888     "{ x : { foo: foo().y = 10 } = {} }",
   6889     "{ x : { foo: foo()[y] = 10 } = {} }",
   6890     "{ x : { foo: y.z = 10 } = {} }",
   6891     "{ x : { foo: y[z] = 10 } = {} }",
   6892     "{ x : [ y = 10 ] = {} }",
   6893     "{ x : [ foo().y = 10 ] = {} }",
   6894     "{ x : [ foo()[y] = 10 ] = {} }",
   6895     "{ x : [ y.z = 10 ] = {} }",
   6896     "{ x : [ y[z] = 10 ] = {} }",
   6897 
   6898     "[ x ]",
   6899     "[ foo().x ]",
   6900     "[ foo()[x] ]",
   6901     "[ x.y ]",
   6902     "[ x[y] ]",
   6903     "[ { x } ]",
   6904     "[ { x : y } ]",
   6905     "[ { x : foo().y } ]",
   6906     "[ { x : foo()[y] } ]",
   6907     "[ { x : x.y } ]",
   6908     "[ { x : x[y] } ]",
   6909     "[ [ x ] ]",
   6910     "[ [ foo().x ] ]",
   6911     "[ [ foo()[x] ] ]",
   6912     "[ [ x.y ] ]",
   6913     "[ [ x[y] ] ]",
   6914 
   6915     "[ x = 10 ]",
   6916     "[ foo().x = 10 ]",
   6917     "[ foo()[x] = 10 ]",
   6918     "[ x.y = 10 ]",
   6919     "[ x[y] = 10 ]",
   6920     "[ { x = 10 } = {} ]",
   6921     "[ { x : y = 10 } = {} ]",
   6922     "[ { x : foo().y = 10 } = {} ]",
   6923     "[ { x : foo()[y] = 10 } = {} ]",
   6924     "[ { x : x.y = 10 } = {} ]",
   6925     "[ { x : x[y] = 10 } = {} ]",
   6926     "[ [ x = 10 ] = {} ]",
   6927     "[ [ foo().x = 10 ] = {} ]",
   6928     "[ [ foo()[x] = 10 ] = {} ]",
   6929     "[ [ x.y = 10 ] = {} ]",
   6930     "[ [ x[y] = 10 ] = {} ]",
   6931     "{ x : y = 1 }",
   6932     "{ x }",
   6933     "{ x, y, z }",
   6934     "{ x = 1, y: z, z: y }",
   6935     "{x = 42, y = 15}",
   6936     "[x]",
   6937     "[x = 1]",
   6938     "[x,y,z]",
   6939     "[x, y = 42, z]",
   6940     "{ x : x, y : y }",
   6941     "{ x : x = 1, y : y }",
   6942     "{ x : x, y : y = 42 }",
   6943     "[]",
   6944     "{}",
   6945     "[{x:x, y:y}, [,x,z,]]",
   6946     "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
   6947     "[x,,y]",
   6948     "[(x),,(y)]",
   6949     "[(x)]",
   6950     "{42 : x}",
   6951     "{42 : x = 42}",
   6952     "{42e-2 : x}",
   6953     "{42e-2 : x = 42}",
   6954     "{'hi' : x}",
   6955     "{'hi' : x = 42}",
   6956     "{var: x}",
   6957     "{var: x = 42}",
   6958     "{var: (x) = 42}",
   6959     "{[x] : z}",
   6960     "{[1+1] : z}",
   6961     "{[1+1] : (z)}",
   6962     "{[foo()] : z}",
   6963     "{[foo()] : (z)}",
   6964     "{[foo()] : foo().bar}",
   6965     "{[foo()] : foo()['bar']}",
   6966     "{[foo()] : this.bar}",
   6967     "{[foo()] : this['bar']}",
   6968     "{[foo()] : 'foo'.bar}",
   6969     "{[foo()] : 'foo'['bar']}",
   6970     "[...x]",
   6971     "[x,y,...z]",
   6972     "[x,,...z]",
   6973     "{ x: y }",
   6974     "[x, y]",
   6975     "[((x, y) => z).x]",
   6976     "{x: ((y, z) => z).x}",
   6977     "[((x, y) => z)['x']]",
   6978     "{x: ((y, z) => z)['x']}",
   6979 
   6980     "{x: { y = 10 } }",
   6981     "[(({ x } = { x: 1 }) => x).a]",
   6982 
   6983     // v8:4662
   6984     "{ x: (y) }",
   6985     "{ x: (y) = [] }",
   6986     "{ x: (foo.bar) }",
   6987     "{ x: (foo['bar']) }",
   6988     "[ ...(a) ]",
   6989     "[ ...(foo['bar']) ]",
   6990     "[ ...(foo.bar) ]",
   6991     "[ (y) ]",
   6992     "[ (foo.bar) ]",
   6993     "[ (foo['bar']) ]",
   6994 
   6995     NULL};
   6996   // clang-format on
   6997   static const ParserFlag always_flags[] = {
   6998       kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
   6999       kAllowHarmonyDefaultParameters};
   7000   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
   7001                     arraysize(always_flags));
   7002 
   7003   RunParserSyncTest(mixed_assignments_context_data, data, kSuccess, NULL, 0,
   7004                     always_flags, arraysize(always_flags));
   7005 
   7006   const char* empty_context_data[][2] = {
   7007       {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
   7008 
   7009   // CoverInitializedName ambiguity handling in various contexts
   7010   const char* ambiguity_data[] = {
   7011       "var foo = { x = 10 } = {};",
   7012       "var foo = { q } = { x = 10 } = {};",
   7013       "var foo; foo = { x = 10 } = {};",
   7014       "var foo; foo = { q } = { x = 10 } = {};",
   7015       "var x; ({ x = 10 } = {});",
   7016       "var q, x; ({ q } = { x = 10 } = {});",
   7017       "var x; [{ x = 10 } = {}]",
   7018       "var x; (true ? { x = true } = {} : { x = false } = {})",
   7019       "var q, x; (q, { x = 10 } = {});",
   7020       "var { x = 10 } = { x = 20 } = {};",
   7021       "var { x = 10 } = (o = { x = 20 } = {});",
   7022       "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
   7023       NULL,
   7024   };
   7025   RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess, NULL, 0,
   7026                     always_flags, arraysize(always_flags));
   7027 }
   7028 
   7029 
   7030 TEST(DestructuringAssignmentNegativeTests) {
   7031   const char* context_data[][2] = {
   7032       {"'use strict'; let x, y, z; (", " = {});"},
   7033       {"var x, y, z; (", " = {});"},
   7034       {"'use strict'; let x, y, z; for (x in ", " = {});"},
   7035       {"'use strict'; let x, y, z; for (x of ", " = {});"},
   7036       {"var x, y, z; for (x in ", " = {});"},
   7037       {"var x, y, z; for (x of ", " = {});"},
   7038       {NULL, NULL}};
   7039 
   7040   // clang-format off
   7041   const char* data[] = {
   7042     "{ x : ++y }",
   7043     "{ x : y * 2 }",
   7044     "{ ...x }",
   7045     "{ get x() {} }",
   7046     "{ set x() {} }",
   7047     "{ x: y() }",
   7048     "{ this }",
   7049     "{ x: this }",
   7050     "{ x: this = 1 }",
   7051     "{ super }",
   7052     "{ x: super }",
   7053     "{ x: super = 1 }",
   7054     "{ new.target }",
   7055     "{ x: new.target }",
   7056     "{ x: new.target = 1 }",
   7057     "[x--]",
   7058     "[--x = 1]",
   7059     "[x()]",
   7060     "[this]",
   7061     "[this = 1]",
   7062     "[new.target]",
   7063     "[new.target = 1]",
   7064     "[super]",
   7065     "[super = 1]",
   7066     "[function f() {}]",
   7067     "[50]",
   7068     "[(50)]",
   7069     "[(function() {})]",
   7070     "[(foo())]",
   7071     "{ x: 50 }",
   7072     "{ x: (50) }",
   7073     "['str']",
   7074     "{ x: 'str' }",
   7075     "{ x: ('str') }",
   7076     "{ x: (foo()) }",
   7077     "{ x: (function() {}) }",
   7078     "{ x: y } = 'str'",
   7079     "[x, y] = 'str'",
   7080     "[(x,y) => z]",
   7081     "{x: (y) => z}",
   7082     "[x, ...y, z]",
   7083     "[...x,]",
   7084     "[x, y, ...z = 1]",
   7085     "[...z = 1]",
   7086 
   7087     // v8:4657
   7088     "({ x: x4, x: (x+=1e4) })",
   7089     "(({ x: x4, x: (x+=1e4) }))",
   7090     "({ x: x4, x: (x+=1e4) } = {})",
   7091     "(({ x: x4, x: (x+=1e4) } = {}))",
   7092     "(({ x: x4, x: (x+=1e4) }) = {})",
   7093     "({ x: y } = {})",
   7094     "(({ x: y } = {}))",
   7095     "(({ x: y }) = {})",
   7096     "([a])",
   7097     "(([a]))",
   7098     "([a] = [])",
   7099     "(([a] = []))",
   7100     "(([a]) = [])",
   7101 
   7102     // v8:4662
   7103     "{ x: ([y]) }",
   7104     "{ x: ([y] = []) }",
   7105     "{ x: ({y}) }",
   7106     "{ x: ({y} = {}) }",
   7107     "{ x: (++y) }",
   7108     "[ (...[a]) ]",
   7109     "[ ...([a]) ]",
   7110     "[ ...([a] = [])",
   7111     "[ ...[ ( [ a ] ) ] ]",
   7112     "[ ([a]) ]",
   7113     "[ (...[a]) ]",
   7114     "[ ([a] = []) ]",
   7115     "[ (++y) ]",
   7116     "[ ...(++y) ]",
   7117 
   7118     "[ x += x ]",
   7119     "{ foo: x += x }",
   7120 
   7121     NULL};
   7122   // clang-format on
   7123   static const ParserFlag always_flags[] = {
   7124       kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
   7125       kAllowHarmonyDefaultParameters};
   7126   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   7127                     arraysize(always_flags));
   7128 
   7129   const char* empty_context_data[][2] = {
   7130       {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
   7131 
   7132   // CoverInitializedName ambiguity handling in various contexts
   7133   const char* ambiguity_data[] = {
   7134       "var foo = { x = 10 };",
   7135       "var foo = { q } = { x = 10 };",
   7136       "var foo; foo = { x = 10 };",
   7137       "var foo; foo = { q } = { x = 10 };",
   7138       "var x; ({ x = 10 });",
   7139       "var q, x; ({ q } = { x = 10 });",
   7140       "var x; [{ x = 10 }]",
   7141       "var x; (true ? { x = true } : { x = false })",
   7142       "var q, x; (q, { x = 10 });",
   7143       "var { x = 10 } = { x = 20 };",
   7144       "var { x = 10 } = (o = { x = 20 });",
   7145       "var x; (({ x = 10 } = { x = 20 }) => x)({})",
   7146 
   7147       // Not ambiguous, but uses same context data
   7148       "switch([window %= []] = []) { default: }",
   7149 
   7150       NULL,
   7151   };
   7152   RunParserSyncTest(empty_context_data, ambiguity_data, kError, NULL, 0,
   7153                     always_flags, arraysize(always_flags));
   7154 
   7155   // Strict mode errors
   7156   const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
   7157                                           {"'use strict'; for (", " of {}) {}"},
   7158                                           {"'use strict'; for (", " in {}) {}"},
   7159                                           {NULL, NULL}};
   7160   const char* strict_data[] = {"{ eval }",
   7161                                "{ arguments }",
   7162                                "{ foo: eval }",
   7163                                "{ foo: arguments }",
   7164                                "{ eval = 0 }",
   7165                                "{ arguments = 0 }",
   7166                                "{ foo: eval = 0 }",
   7167                                "{ foo: arguments = 0 }",
   7168                                "[ eval ]",
   7169                                "[ arguments ]",
   7170                                "[ eval = 0 ]",
   7171                                "[ arguments = 0 ]",
   7172 
   7173                                // v8:4662
   7174                                "{ x: (eval) }",
   7175                                "{ x: (arguments) }",
   7176                                "{ x: (eval = 0) }",
   7177                                "{ x: (arguments = 0) }",
   7178                                "{ x: (eval) = 0 }",
   7179                                "{ x: (arguments) = 0 }",
   7180                                "[ (eval) ]",
   7181                                "[ (arguments) ]",
   7182                                "[ (eval = 0) ]",
   7183                                "[ (arguments = 0) ]",
   7184                                "[ (eval) = 0 ]",
   7185                                "[ (arguments) = 0 ]",
   7186                                "[ ...(eval) ]",
   7187                                "[ ...(arguments) ]",
   7188                                "[ ...(eval = 0) ]",
   7189                                "[ ...(arguments = 0) ]",
   7190                                "[ ...(eval) = 0 ]",
   7191                                "[ ...(arguments) = 0 ]",
   7192 
   7193                                NULL};
   7194   RunParserSyncTest(strict_context_data, strict_data, kError, NULL, 0,
   7195                     always_flags, arraysize(always_flags));
   7196 }
   7197 
   7198 
   7199 TEST(DestructuringDisallowPatternsInForVarIn) {
   7200   i::FLAG_harmony_destructuring_bind = true;
   7201   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   7202   const char* context_data[][2] = {
   7203       {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
   7204   // clang-format off
   7205   const char* error_data[] = {
   7206     "for (let x = {} in null);",
   7207     "for (let x = {} of null);",
   7208     NULL};
   7209   // clang-format on
   7210   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
   7211                     arraysize(always_flags));
   7212 
   7213   // clang-format off
   7214   const char* success_data[] = {
   7215     "for (var x = {} in null);",
   7216     NULL};
   7217   // clang-format on
   7218   RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
   7219                     arraysize(always_flags));
   7220 }
   7221 
   7222 
   7223 TEST(DestructuringDuplicateParams) {
   7224   i::FLAG_harmony_destructuring_bind = true;
   7225   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   7226   const char* context_data[][2] = {{"'use strict';", ""},
   7227                                    {"function outer() { 'use strict';", "}"},
   7228                                    {nullptr, nullptr}};
   7229 
   7230 
   7231   // clang-format off
   7232   const char* error_data[] = {
   7233     "function f(x,x){}",
   7234     "function f(x, {x : x}){}",
   7235     "function f(x, {x}){}",
   7236     "function f({x,x}) {}",
   7237     "function f([x,x]) {}",
   7238     "function f(x, [y,{z:x}]) {}",
   7239     "function f([x,{y:x}]) {}",
   7240     // non-simple parameter list causes duplicates to be errors in sloppy mode.
   7241     "function f(x, x, {a}) {}",
   7242     nullptr};
   7243   // clang-format on
   7244   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
   7245                     arraysize(always_flags));
   7246 }
   7247 
   7248 
   7249 TEST(DestructuringDuplicateParamsSloppy) {
   7250   i::FLAG_harmony_destructuring_bind = true;
   7251   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   7252   const char* context_data[][2] = {
   7253       {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
   7254 
   7255 
   7256   // clang-format off
   7257   const char* error_data[] = {
   7258     // non-simple parameter list causes duplicates to be errors in sloppy mode.
   7259     "function f(x, {x : x}){}",
   7260     "function f(x, {x}){}",
   7261     "function f({x,x}) {}",
   7262     "function f(x, x, {a}) {}",
   7263     nullptr};
   7264   // clang-format on
   7265   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
   7266                     arraysize(always_flags));
   7267 }
   7268 
   7269 
   7270 TEST(DestructuringDisallowPatternsInSingleParamArrows) {
   7271   i::FLAG_harmony_destructuring_bind = true;
   7272   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
   7273   const char* context_data[][2] = {{"'use strict';", ""},
   7274                                    {"function outer() { 'use strict';", "}"},
   7275                                    {"", ""},
   7276                                    {"function outer() { ", "}"},
   7277                                    {nullptr, nullptr}};
   7278 
   7279   // clang-format off
   7280   const char* error_data[] = {
   7281     "var f = {x} => {};",
   7282     "var f = {x,y} => {};",
   7283     nullptr};
   7284   // clang-format on
   7285   RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
   7286                     arraysize(always_flags));
   7287 }
   7288 
   7289 
   7290 TEST(DefaultParametersYieldInInitializers) {
   7291   // clang-format off
   7292   const char* sloppy_function_context_data[][2] = {
   7293     {"(function f(", ") { });"},
   7294     {NULL, NULL}
   7295   };
   7296 
   7297   const char* strict_function_context_data[][2] = {
   7298     {"'use strong'; (function f(", ") { });"},
   7299     {"'use strict'; (function f(", ") { });"},
   7300     {NULL, NULL}
   7301   };
   7302 
   7303   const char* sloppy_arrow_context_data[][2] = {
   7304     {"((", ")=>{});"},
   7305     {NULL, NULL}
   7306   };
   7307 
   7308   const char* strict_arrow_context_data[][2] = {
   7309     {"'use strong'; ((", ")=>{});"},
   7310     {"'use strict'; ((", ")=>{});"},
   7311     {NULL, NULL}
   7312   };
   7313 
   7314   const char* generator_context_data[][2] = {
   7315     {"'use strong'; (function *g(", ") { });"},
   7316     {"'use strict'; (function *g(", ") { });"},
   7317     {"(function *g(", ") { });"},
   7318     {NULL, NULL}
   7319   };
   7320 
   7321   const char* parameter_data[] = {
   7322     "x=yield",
   7323     "x, y=yield",
   7324     "{x=yield}",
   7325     "[x=yield]",
   7326 
   7327     "x=(yield)",
   7328     "x, y=(yield)",
   7329     "{x=(yield)}",
   7330     "[x=(yield)]",
   7331 
   7332     "x=f(yield)",
   7333     "x, y=f(yield)",
   7334     "{x=f(yield)}",
   7335     "[x=f(yield)]",
   7336     NULL
   7337   };
   7338 
   7339   // TODO(wingo): These aren't really destructuring assignment patterns; we're
   7340   // just splitting them for now until the parser gets support for arrow
   7341   // function arguments that look like destructuring assignments.  When that
   7342   // happens we should unify destructuring_assignment_data and parameter_data.
   7343   const char* destructuring_assignment_data[] = {
   7344     "{x}=yield",
   7345     "[x]=yield",
   7346 
   7347     "{x}=(yield)",
   7348     "[x]=(yield)",
   7349 
   7350     "{x}=f(yield)",
   7351     "[x]=f(yield)",
   7352     NULL
   7353   };
   7354 
   7355   // clang-format on
   7356   static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
   7357                                             kAllowHarmonyDefaultParameters,
   7358                                             kAllowStrongMode};
   7359 
   7360   RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess,
   7361                     NULL, 0, always_flags, arraysize(always_flags));
   7362   RunParserSyncTest(sloppy_function_context_data, destructuring_assignment_data,
   7363                     kSuccess, NULL, 0, always_flags, arraysize(always_flags));
   7364   RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess, NULL,
   7365                     0, always_flags, arraysize(always_flags));
   7366   RunParserSyncTest(sloppy_arrow_context_data, destructuring_assignment_data,
   7367                     kSuccess, NULL, 0, always_flags, arraysize(always_flags));
   7368 
   7369   RunParserSyncTest(strict_function_context_data, parameter_data, kError, NULL,
   7370                     0, always_flags, arraysize(always_flags));
   7371   RunParserSyncTest(strict_function_context_data, destructuring_assignment_data,
   7372                     kError, NULL, 0, always_flags, arraysize(always_flags));
   7373   RunParserSyncTest(strict_arrow_context_data, parameter_data, kError, NULL, 0,
   7374                     always_flags, arraysize(always_flags));
   7375   RunParserSyncTest(strict_arrow_context_data, destructuring_assignment_data,
   7376                     kError, NULL, 0, always_flags, arraysize(always_flags));
   7377 
   7378   RunParserSyncTest(generator_context_data, parameter_data, kError, NULL, 0,
   7379                     always_flags, arraysize(always_flags));
   7380   RunParserSyncTest(generator_context_data, destructuring_assignment_data,
   7381                     kError, NULL, 0, always_flags, arraysize(always_flags));
   7382 }
   7383 
   7384 
   7385 TEST(SpreadArray) {
   7386   const char* context_data[][2] = {
   7387       {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
   7388 
   7389   // clang-format off
   7390   const char* data[] = {
   7391     "[...a]",
   7392     "[a, ...b]",
   7393     "[...a,]",
   7394     "[...a, ,]",
   7395     "[, ...a]",
   7396     "[...a, ...b]",
   7397     "[...a, , ...b]",
   7398     "[...[...a]]",
   7399     "[, ...a]",
   7400     "[, , ...a]",
   7401     NULL};
   7402   // clang-format on
   7403   RunParserSyncTest(context_data, data, kSuccess);
   7404 }
   7405 
   7406 
   7407 TEST(SpreadArrayError) {
   7408   const char* context_data[][2] = {
   7409       {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
   7410 
   7411   // clang-format off
   7412   const char* data[] = {
   7413     "[...]",
   7414     "[a, ...]",
   7415     "[..., ]",
   7416     "[..., ...]",
   7417     "[ (...a)]",
   7418     NULL};
   7419   // clang-format on
   7420   RunParserSyncTest(context_data, data, kError);
   7421 }
   7422 
   7423 
   7424 TEST(NewTarget) {
   7425   // clang-format off
   7426   const char* good_context_data[][2] = {
   7427     {"function f() {", "}"},
   7428     {"'use strict'; function f() {", "}"},
   7429     {"var f = function() {", "}"},
   7430     {"'use strict'; var f = function() {", "}"},
   7431     {"({m: function() {", "}})"},
   7432     {"'use strict'; ({m: function() {", "}})"},
   7433     {"({m() {", "}})"},
   7434     {"'use strict'; ({m() {", "}})"},
   7435     {"({get x() {", "}})"},
   7436     {"'use strict'; ({get x() {", "}})"},
   7437     {"({set x(_) {", "}})"},
   7438     {"'use strict'; ({set x(_) {", "}})"},
   7439     {"class C {m() {", "}}"},
   7440     {"class C {get x() {", "}}"},
   7441     {"class C {set x(_) {", "}}"},
   7442     {NULL}
   7443   };
   7444 
   7445   const char* bad_context_data[][2] = {
   7446     {"", ""},
   7447     {"'use strict';", ""},
   7448     {NULL}
   7449   };
   7450 
   7451   const char* data[] = {
   7452     "new.target",
   7453     "{ new.target }",
   7454     "() => { new.target }",
   7455     "() => new.target",
   7456     "if (1) { new.target }",
   7457     "if (1) {} else { new.target }",
   7458     "while (0) { new.target }",
   7459     "do { new.target } while (0)",
   7460     NULL
   7461   };
   7462 
   7463   static const ParserFlag always_flags[] = {
   7464     kAllowHarmonyNewTarget,
   7465     kAllowHarmonySloppy,
   7466   };
   7467   // clang-format on
   7468 
   7469   RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags,
   7470                     arraysize(always_flags));
   7471   RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags,
   7472                     arraysize(always_flags));
   7473 }
   7474 
   7475 
   7476 TEST(ConstLegacy) {
   7477   // clang-format off
   7478   const char* context_data[][2] = {
   7479     {"", ""},
   7480     {"{", "}"},
   7481     {NULL, NULL}
   7482   };
   7483 
   7484   const char* data[] = {
   7485     "const x",
   7486     "const x = 1",
   7487     "for (const x = 1; x < 1; x++) {}",
   7488     "for (const x in {}) {}",
   7489     "for (const x of []) {}",
   7490     NULL
   7491   };
   7492   // clang-format on
   7493 
   7494 
   7495   static const ParserFlag always_flags[] = {kNoLegacyConst};
   7496   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   7497                     arraysize(always_flags));
   7498   RunParserSyncTest(context_data, data, kSuccess);
   7499 }
   7500 
   7501 
   7502 TEST(ConstSloppy) {
   7503   // clang-format off
   7504   const char* context_data[][2] = {
   7505     {"", ""},
   7506     {"{", "}"},
   7507     {NULL, NULL}
   7508   };
   7509 
   7510   const char* data[] = {
   7511     "const x = 1",
   7512     "for (const x = 1; x < 1; x++) {}",
   7513     "for (const x in {}) {}",
   7514     "for (const x of []) {}",
   7515     NULL
   7516   };
   7517   // clang-format on
   7518   static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
   7519                                             kNoLegacyConst};
   7520   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
   7521                     arraysize(always_flags));
   7522 }
   7523 
   7524 
   7525 TEST(LetSloppy) {
   7526   // clang-format off
   7527   const char* context_data[][2] = {
   7528     {"", ""},
   7529     {"'use strict';", ""},
   7530     {"{", "}"},
   7531     {NULL, NULL}
   7532   };
   7533 
   7534   const char* data[] = {
   7535     "let x",
   7536     "let x = 1",
   7537     "for (let x = 1; x < 1; x++) {}",
   7538     "for (let x in {}) {}",
   7539     "for (let x of []) {}",
   7540     NULL
   7541   };
   7542   // clang-format on
   7543 
   7544   static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
   7545                                             kAllowHarmonySloppyLet};
   7546   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
   7547                     arraysize(always_flags));
   7548 }
   7549 
   7550 
   7551 TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
   7552   // TC39 deemed "use strict" directives to be an error when occurring in the
   7553   // body of a function with non-simple parameter list, on 29/7/2015.
   7554   // https://goo.gl/ueA7Ln
   7555   //
   7556   // In V8, this also applies to "use strong " directives.
   7557   const char* context_data[][2] = {
   7558       {"function f(", ") { 'use strict'; }"},
   7559       {"function f(", ") { 'use strong'; }"},
   7560       {"function* g(", ") { 'use strict'; }"},
   7561       {"function* g(", ") { 'use strong'; }"},
   7562       {"class c { foo(", ") { 'use strict' }"},
   7563       {"class c { foo(", ") { 'use strong' }"},
   7564       {"var a = (", ") => { 'use strict'; }"},
   7565       {"var a = (", ") => { 'use strong'; }"},
   7566       {"var o = { m(", ") { 'use strict'; }"},
   7567       {"var o = { m(", ") { 'use strong'; }"},
   7568       {"var o = { *gm(", ") { 'use strict'; }"},
   7569       {"var o = { *gm(", ") { 'use strong'; }"},
   7570       {"var c = { m(", ") { 'use strict'; }"},
   7571       {"var c = { m(", ") { 'use strong'; }"},
   7572       {"var c = { *gm(", ") { 'use strict'; }"},
   7573       {"var c = { *gm(", ") { 'use strong'; }"},
   7574 
   7575       {"'use strict'; function f(", ") { 'use strict'; }"},
   7576       {"'use strict'; function f(", ") { 'use strong'; }"},
   7577       {"'use strict'; function* g(", ") { 'use strict'; }"},
   7578       {"'use strict'; function* g(", ") { 'use strong'; }"},
   7579       {"'use strict'; class c { foo(", ") { 'use strict' }"},
   7580       {"'use strict'; class c { foo(", ") { 'use strong' }"},
   7581       {"'use strict'; var a = (", ") => { 'use strict'; }"},
   7582       {"'use strict'; var a = (", ") => { 'use strong'; }"},
   7583       {"'use strict'; var o = { m(", ") { 'use strict'; }"},
   7584       {"'use strict'; var o = { m(", ") { 'use strong'; }"},
   7585       {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
   7586       {"'use strict'; var o = { *gm(", ") { 'use strong'; }"},
   7587       {"'use strict'; var c = { m(", ") { 'use strict'; }"},
   7588       {"'use strict'; var c = { m(", ") { 'use strong'; }"},
   7589       {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
   7590       {"'use strict'; var c = { *gm(", ") { 'use strong'; }"},
   7591 
   7592       {"'use strong'; function f(", ") { 'use strict'; }"},
   7593       {"'use strong'; function f(", ") { 'use strong'; }"},
   7594       {"'use strong'; function* g(", ") { 'use strict'; }"},
   7595       {"'use strong'; function* g(", ") { 'use strong'; }"},
   7596       {"'use strong'; class c { foo(", ") { 'use strict' }"},
   7597       {"'use strong'; class c { foo(", ") { 'use strong' }"},
   7598       {"'use strong'; var a = (", ") => { 'use strict'; }"},
   7599       {"'use strong'; var a = (", ") => { 'use strong'; }"},
   7600       {"'use strong'; var o = { m(", ") { 'use strict'; }"},
   7601       {"'use strong'; var o = { m(", ") { 'use strong'; }"},
   7602       {"'use strong'; var o = { *gm(", ") { 'use strict'; }"},
   7603       {"'use strong'; var o = { *gm(", ") { 'use strong'; }"},
   7604       {"'use strong'; var c = { m(", ") { 'use strict'; }"},
   7605       {"'use strong'; var c = { m(", ") { 'use strong'; }"},
   7606       {"'use strong'; var c = { *gm(", ") { 'use strict'; }"},
   7607       {"'use strong'; var c = { *gm(", ") { 'use strong'; }"},
   7608 
   7609       {NULL, NULL}};
   7610 
   7611   const char* data[] = {
   7612       // TODO(@caitp): support formal parameter initializers
   7613       "{}",
   7614       "[]",
   7615       "[{}]",
   7616       "{a}",
   7617       "a, {b}",
   7618       "a, b, {c, d, e}",
   7619       "initializer = true",
   7620       "a, b, c = 1",
   7621       "...args",
   7622       "a, b, ...rest",
   7623       "[a, b, ...rest]",
   7624       "{ bindingPattern = {} }",
   7625       "{ initializedBindingPattern } = { initializedBindingPattern: true }",
   7626       NULL};
   7627 
   7628   static const ParserFlag always_flags[] = {
   7629       kAllowHarmonyDefaultParameters, kAllowHarmonyDestructuring,
   7630       kAllowHarmonySloppy, kAllowStrongMode};
   7631   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
   7632                     arraysize(always_flags));
   7633 }
   7634 
   7635 
   7636 TEST(LetSloppyOnly) {
   7637   // clang-format off
   7638   const char* context_data[][2] = {
   7639     {"", ""},
   7640     {"{", "}"},
   7641     {"(function() {", "})()"},
   7642     {NULL, NULL}
   7643   };
   7644 
   7645   const char* data[] = {
   7646     "let",
   7647     "let = 1",
   7648     "for (let = 1; let < 1; let++) {}",
   7649     "for (let in {}) {}",
   7650     "for (var let = 1; let < 1; let++) {}",
   7651     "for (var let in {}) {}",
   7652     "for (var [let] = 1; let < 1; let++) {}",
   7653     "for (var [let] in {}) {}",
   7654     "var let",
   7655     "var [let] = []",
   7656     "for (const let = 1; let < 1; let++) {}",
   7657     "for (const let in {}) {}",
   7658     "for (const [let] = 1; let < 1; let++) {}",
   7659     "for (const [let] in {}) {}",
   7660     "const let",
   7661     "const [let] = []",
   7662     NULL
   7663   };
   7664   // clang-format on
   7665 
   7666   static const ParserFlag always_flags[] = {
   7667       kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
   7668   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
   7669                     arraysize(always_flags));
   7670 
   7671   // Some things should be rejected even in sloppy mode
   7672   // This addresses BUG(v8:4403).
   7673 
   7674   // clang-format off
   7675   const char* fail_data[] = {
   7676     "let let = 1",
   7677     "for (let let = 1; let < 1; let++) {}",
   7678     "for (let let in {}) {}",
   7679     "for (let let of []) {}",
   7680     "const let = 1",
   7681     "for (const let = 1; let < 1; let++) {}",
   7682     "for (const let in {}) {}",
   7683     "for (const let of []) {}",
   7684     "let [let] = 1",
   7685     "for (let [let] = 1; let < 1; let++) {}",
   7686     "for (let [let] in {}) {}",
   7687     "for (let [let] of []) {}",
   7688     "const [let] = 1",
   7689     "for (const [let] = 1; let < 1; let++) {}",
   7690     "for (const [let] in {}) {}",
   7691     "for (const [let] of []) {}",
   7692     NULL
   7693   };
   7694   // clang-format on
   7695 
   7696   static const ParserFlag fail_flags[] = {
   7697       kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst,
   7698       kAllowHarmonyDestructuring};
   7699   RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags,
   7700                     arraysize(fail_flags));
   7701 }
   7702 
   7703 
   7704 TEST(EscapedKeywords) {
   7705   // clang-format off
   7706   const char* sloppy_context_data[][2] = {
   7707     {"", ""},
   7708     {NULL, NULL}
   7709   };
   7710 
   7711   const char* strict_context_data[][2] = {
   7712     {"'use strict';", ""},
   7713     {NULL, NULL}
   7714   };
   7715 
   7716   const char* fail_data[] = {
   7717     "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
   7718     "cl\\u0061ss Foo {}",
   7719     "var x = cl\\u0061ss {}",
   7720     "\\u0063onst foo = 1;",
   7721     "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
   7722     "d\\u0065bugger;",
   7723     "d\\u0065lete this.a;",
   7724     "\\u0063o { } while(0)",
   7725     "if (d\\u006f { true }) {}",
   7726     "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
   7727     "e\\u0078port var foo;",
   7728     "try { } catch (e) {} f\\u0069nally { }",
   7729     "f\\u006fr (var i = 0; i < 10; ++i);",
   7730     "f\\u0075nction fn() {}",
   7731     "var f = f\\u0075nction() {}",
   7732     "\\u0069f (true) { }",
   7733     "\\u0069mport blah from './foo.js';",
   7734     "n\\u0065w function f() {}",
   7735     "(function() { r\\u0065turn; })()",
   7736     "class C extends function() {} { constructor() { sup\\u0065r() } }",
   7737     "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
   7738     "sw\\u0069tch (this.a) {}",
   7739     "var x = th\\u0069s;",
   7740     "th\\u0069s.a = 1;",
   7741     "thr\\u006fw 'boo';",
   7742     "t\\u0072y { true } catch (e) {}",
   7743     "var x = typ\\u0065of 'blah'",
   7744     "v\\u0061r a = true",
   7745     "var v\\u0061r = true",
   7746     "(function() { return v\\u006fid 0; })()",
   7747     "wh\\u0069le (true) { }",
   7748     "w\\u0069th (this.scope) { }",
   7749     "(function*() { y\\u0069eld 1; })()",
   7750 
   7751     "var \\u0065num = 1;",
   7752     "var { \\u0065num } = {}",
   7753     "(\\u0065num = 1);",
   7754 
   7755     // Null / Boolean literals
   7756     "(x === n\\u0075ll);",
   7757     "var x = n\\u0075ll;",
   7758     "var n\\u0075ll = 1;",
   7759     "var { n\\u0075ll } = { 1 };",
   7760     "n\\u0075ll = 1;",
   7761     "(x === tr\\u0075e);",
   7762     "var x = tr\\u0075e;",
   7763     "var tr\\u0075e = 1;",
   7764     "var { tr\\u0075e } = {};",
   7765     "tr\\u0075e = 1;",
   7766     "(x === f\\u0061lse);",
   7767     "var x = f\\u0061lse;",
   7768     "var f\\u0061lse = 1;",
   7769     "var { f\\u0061lse } = {};",
   7770     "f\\u0061lse = 1;",
   7771 
   7772     // TODO(caitp): consistent error messages for labeled statements and
   7773     // expressions
   7774     "switch (this.a) { c\\u0061se 6: break; }",
   7775     "try { } c\\u0061tch (e) {}",
   7776     "switch (this.a) { d\\u0065fault: break; }",
   7777     "class C \\u0065xtends function B() {} {}",
   7778     "for (var a i\\u006e this) {}",
   7779     "if ('foo' \\u0069n this) {}",
   7780     "if (this \\u0069nstanceof Array) {}",
   7781     "(n\\u0065w function f() {})",
   7782     "(typ\\u0065of 123)",
   7783     "(v\\u006fid 0)",
   7784     "do { ; } wh\\u0069le (true) { }",
   7785     "(function*() { return (n++, y\\u0069eld 1); })()",
   7786     "class C { st\\u0061tic bar() {} }",
   7787 
   7788     "(y\\u0069eld);",
   7789     "var y\\u0069eld = 1;",
   7790     "var { y\\u0069eld } = {};",
   7791     NULL
   7792   };
   7793   // clang-format on
   7794 
   7795   static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
   7796                                             kAllowHarmonyDestructuring};
   7797   RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
   7798                     always_flags, arraysize(always_flags));
   7799   RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0,
   7800                     always_flags, arraysize(always_flags));
   7801   RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
   7802                           always_flags, arraysize(always_flags));
   7803 
   7804   // clang-format off
   7805   const char* let_data[] = {
   7806     "var l\\u0065t = 1;",
   7807     "l\\u0065t = 1;",
   7808     "(l\\u0065t === 1);",
   7809     NULL
   7810   };
   7811   // clang-format on
   7812 
   7813   RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
   7814                     always_flags, arraysize(always_flags));
   7815   RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
   7816                     always_flags, arraysize(always_flags));
   7817 
   7818   static const ParserFlag sloppy_let_flags[] = {
   7819       kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
   7820   RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
   7821                     sloppy_let_flags, arraysize(sloppy_let_flags));
   7822 
   7823   // Non-errors in sloppy mode
   7824   const char* valid_data[] = {"(\\u0069mplements = 1);",
   7825                               "var impl\\u0065ments = 1;",
   7826                               "var { impl\\u0065ments  } = {};",
   7827                               "(\\u0069nterface = 1);",
   7828                               "var int\\u0065rface = 1;",
   7829                               "var { int\\u0065rface  } = {};",
   7830                               "(p\\u0061ckage = 1);",
   7831                               "var packa\\u0067e = 1;",
   7832                               "var { packa\\u0067e  } = {};",
   7833                               "(p\\u0072ivate = 1);",
   7834                               "var p\\u0072ivate;",
   7835                               "var { p\\u0072ivate } = {};",
   7836                               "(prot\\u0065cted);",
   7837                               "var prot\\u0065cted = 1;",
   7838                               "var { prot\\u0065cted  } = {};",
   7839                               "(publ\\u0069c);",
   7840                               "var publ\\u0069c = 1;",
   7841                               "var { publ\\u0069c } = {};",
   7842                               NULL};
   7843   RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
   7844                     always_flags, arraysize(always_flags));
   7845   RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
   7846                     always_flags, arraysize(always_flags));
   7847   RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
   7848                           always_flags, arraysize(always_flags));
   7849 }
   7850 
   7851 
   7852 TEST(MiscSyntaxErrors) {
   7853   const char* context_data[][2] = {
   7854       {"'use strict'", ""}, {"", ""}, {NULL, NULL}};
   7855   const char* error_data[] = {"for (();;) {}", NULL};
   7856 
   7857   RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
   7858 }
   7859