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