• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(ScanKeywords)50 TEST(ScanKeywords) {
51   struct KeywordToken {
52     const char* keyword;
53     i::Token::Value token;
54   };
55 
56   static const KeywordToken keywords[] = {
57 #define KEYWORD(t, s, d) { s, i::Token::t },
58       TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
59 #undef KEYWORD
60       { NULL, i::Token::IDENTIFIER }
61   };
62 
63   KeywordToken key_token;
64   i::UnicodeCache unicode_cache;
65   i::byte buffer[32];
66   for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
67     const i::byte* keyword =
68         reinterpret_cast<const i::byte*>(key_token.keyword);
69     int length = i::StrLength(key_token.keyword);
70     CHECK(static_cast<int>(sizeof(buffer)) >= length);
71     {
72       i::Utf8ToUtf16CharacterStream stream(keyword, length);
73       i::Scanner scanner(&unicode_cache);
74       scanner.Initialize(&stream);
75       CHECK_EQ(key_token.token, scanner.Next());
76       CHECK_EQ(i::Token::EOS, scanner.Next());
77     }
78     // Removing characters will make keyword matching fail.
79     {
80       i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
81       i::Scanner scanner(&unicode_cache);
82       scanner.Initialize(&stream);
83       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
84       CHECK_EQ(i::Token::EOS, scanner.Next());
85     }
86     // Adding characters will make keyword matching fail.
87     static const char chars_to_append[] = { 'z', '0', '_' };
88     for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
89       i::MemMove(buffer, keyword, length);
90       buffer[length] = chars_to_append[j];
91       i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
92       i::Scanner scanner(&unicode_cache);
93       scanner.Initialize(&stream);
94       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
95       CHECK_EQ(i::Token::EOS, scanner.Next());
96     }
97     // Replacing characters will make keyword matching fail.
98     {
99       i::MemMove(buffer, keyword, length);
100       buffer[length - 1] = '_';
101       i::Utf8ToUtf16CharacterStream stream(buffer, length);
102       i::Scanner scanner(&unicode_cache);
103       scanner.Initialize(&stream);
104       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
105       CHECK_EQ(i::Token::EOS, scanner.Next());
106     }
107   }
108 }
109 
110 
TEST(ScanHTMLEndComments)111 TEST(ScanHTMLEndComments) {
112   v8::V8::Initialize();
113   v8::Isolate* isolate = CcTest::isolate();
114   v8::HandleScope handles(isolate);
115 
116   // Regression test. See:
117   //    http://code.google.com/p/chromium/issues/detail?id=53548
118   // Tests that --> is correctly interpreted as comment-to-end-of-line if there
119   // is only whitespace before it on the line (with comments considered as
120   // whitespace, even a multiline-comment containing a newline).
121   // This was not the case if it occurred before the first real token
122   // in the input.
123   const char* tests[] = {
124       // Before first real token.
125       "--> is eol-comment\nvar y = 37;\n",
126       "\n --> is eol-comment\nvar y = 37;\n",
127       "/* precomment */ --> is eol-comment\nvar y = 37;\n",
128       "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
129       // After first real token.
130       "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
131       "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
132       NULL
133   };
134 
135   const char* fail_tests[] = {
136       "x --> is eol-comment\nvar y = 37;\n",
137       "\"\\n\" --> is eol-comment\nvar y = 37;\n",
138       "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
139       "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
140       "var x = 42; --> is eol-comment\nvar y = 37;\n",
141       "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
142       NULL
143   };
144 
145   // Parser/Scanner needs a stack limit.
146   CcTest::i_isolate()->stack_guard()->SetStackLimit(
147       i::GetCurrentStackPosition() - 128 * 1024);
148   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
149   for (int i = 0; tests[i]; i++) {
150     const i::byte* source =
151         reinterpret_cast<const i::byte*>(tests[i]);
152     i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
153     i::CompleteParserRecorder log;
154     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
155     scanner.Initialize(&stream);
156     i::Zone zone(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 
188 class ScriptResource : public v8::String::ExternalOneByteStringResource {
189  public:
ScriptResource(const char * data,size_t length)190   ScriptResource(const char* data, size_t length)
191       : data_(data), length_(length) { }
192 
data() const193   const char* data() const { return data_; }
length() const194   size_t length() const { return length_; }
195 
196  private:
197   const char* data_;
198   size_t length_;
199 };
200 
201 
TEST(UsingCachedData)202 TEST(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 
TEST(PreparseFunctionDataIsUsed)255 TEST(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 
TEST(StandAlonePreParser)309 TEST(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 
TEST(StandAlonePreParserNoNatives)349 TEST(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 
TEST(PreparsingObjectLiterals)385 TEST(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 
TEST(RegressChromium62639)421 TEST(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 
TEST(Regress928)454 TEST(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 
TEST(PreParseOverflow)508 TEST(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 
540 class TestExternalResource: public v8::String::ExternalStringResource {
541  public:
TestExternalResource(uint16_t * data,int length)542   explicit TestExternalResource(uint16_t* data, int length)
543       : data_(data), length_(static_cast<size_t>(length)) { }
544 
~TestExternalResource()545   ~TestExternalResource() { }
546 
data() const547   const uint16_t* data() const {
548     return data_;
549   }
550 
length() const551   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 
TestCharacterStream(const char * one_byte_source,unsigned length,unsigned start=0,unsigned end=0)562 void 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 
TEST(CharacterStreams)674 TEST(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 
TEST(Utf8CharacterStream)695 TEST(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 
TestStreamScanner(i::Utf16CharacterStream * stream,i::Token::Value * expected_tokens,int skip_pos=0,int skip_to=0)752 void 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 
TEST(StreamScanner)772 TEST(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 
TestScanRegExp(const char * re_source,const char * expected)834 void 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 
TEST(RegExpScanning)863 TEST(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 
Utf8LengthHelper(const char * s)900 static 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 
TEST(ScopeUsesArgumentsSuperThis)970 TEST(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 
CheckParsesToNumber(const char * source,bool with_dot)1105 static 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 
TEST(ParseNumbers)1153 TEST(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 
TEST(ScopePositions)1175 TEST(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 
TEST(DiscardFunctionBody)1411 TEST(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 
ReadString(unsigned * start)1473 const 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 
FormatMessage(i::Vector<unsigned> data)1484 i::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 
1505 enum ParserFlag {
1506   kAllowLazy,
1507   kAllowNatives,
1508   kAllowHarmonyFunctionSent,
1509   kAllowHarmonyRestrictiveDeclarations,
1510   kAllowHarmonyExponentiationOperator,
1511   kAllowHarmonyForIn,
1512   kAllowHarmonyAsyncAwait,
1513   kAllowHarmonyRestrictiveGenerators,
1514 };
1515 
1516 enum ParserSyncTestResult {
1517   kSuccessOrError,
1518   kSuccess,
1519   kError
1520 };
1521 
1522 template <typename Traits>
SetParserFlags(i::ParserBase<Traits> * parser,i::EnumSet<ParserFlag> flags)1523 void 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 
TestParserSyncWithFlags(i::Handle<i::String> source,i::EnumSet<ParserFlag> flags,ParserSyncTestResult result,bool is_module=false,bool test_preparser=true)1541 void 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 
TestParserSync(const char * source,const ParserFlag * varying_flags,size_t varying_flags_length,ParserSyncTestResult result=kSuccessOrError,const ParserFlag * always_true_flags=NULL,size_t always_true_flags_length=0,const ParserFlag * always_false_flags=NULL,size_t always_false_flags_length=0,bool is_module=false,bool test_preparser=true)1669 void 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 
TEST(ParserSync)1698 TEST(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 
TEST(StrictOctal)1810 TEST(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 
RunParserSyncTest(const char * context_data[][2],const char * statement_data[],ParserSyncTestResult result,const ParserFlag * flags=NULL,int flags_len=0,const ParserFlag * always_true_flags=NULL,int always_true_len=0,const ParserFlag * always_false_flags=NULL,int always_false_len=0,bool is_module=false,bool test_preparser=true)1834 void 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 
RunModuleParserSyncTest(const char * context_data[][2],const char * statement_data[],ParserSyncTestResult result,const ParserFlag * flags=NULL,int flags_len=0,const ParserFlag * always_true_flags=NULL,int always_true_len=0,const ParserFlag * always_false_flags=NULL,int always_false_len=0,bool test_preparser=true)1904 void RunModuleParserSyncTest(const char* context_data[][2],
1905                              const char* statement_data[],
1906                              ParserSyncTestResult result,
1907                              const ParserFlag* flags = NULL, int flags_len = 0,
1908                              const ParserFlag* always_true_flags = NULL,
1909                              int always_true_len = 0,
1910                              const ParserFlag* always_false_flags = NULL,
1911                              int always_false_len = 0,
1912                              bool 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 
TEST(ErrorsEvalAndArguments)1919 TEST(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 
TEST(NoErrorsEvalAndArgumentsSloppy)1961 TEST(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 
TEST(NoErrorsEvalAndArgumentsStrict)1998 TEST(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 
TEST(ErrorsFutureStrictReservedWords)2070 TEST(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 
TEST(NoErrorsFutureStrictReservedWords)2108 TEST(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 
TEST(ErrorsReservedWords)2128 TEST(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 
TEST(NoErrorsLetSloppyAllModes)2163 TEST(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 
TEST(NoErrorsYieldSloppyAllModes)2197 TEST(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 
TEST(NoErrorsYieldSloppyGeneratorsEnabled)2233 TEST(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 
TEST(ErrorsYieldStrict)2272 TEST(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 
TEST(ErrorsYieldSloppy)2305 TEST(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 
TEST(NoErrorsGenerator)2322 TEST(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 
TEST(ErrorsYieldGenerator)2390 TEST(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 
TEST(ErrorsNameOfStrictFunction)2455 TEST(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 
TEST(NoErrorsNameOfStrictFunction)2481 TEST(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 
TEST(NoErrorsNameOfStrictGenerator)2499 TEST(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 
TEST(ErrorsIllegalWordsAsLabelsSloppy)2517 TEST(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 
TEST(ErrorsIllegalWordsAsLabelsStrict)2535 TEST(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 
TEST(NoErrorsIllegalWordsAsLabels)2555 TEST(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 
TEST(NoErrorsFutureStrictReservedAsLabelsSloppy)2578 TEST(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 
TEST(ErrorsParenthesizedLabels)2597 TEST(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 
TEST(NoErrorsParenthesizedDirectivePrologue)2615 TEST(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 
TEST(ErrorsNotAnIdentifierName)2631 TEST(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 
TEST(NoErrorsIdentifierNames)2652 TEST(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 
TEST(DontRegressPreParserDataSizes)2674 TEST(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 
TEST(FunctionDeclaresItselfStrict)2731 TEST(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 
TEST(ErrorsTryWithoutCatchOrFinally)2768 TEST(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 
TEST(NoErrorsTryCatchFinally)2787 TEST(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 
TEST(ErrorsRegexpLiteral)2804 TEST(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 
TEST(NoErrorsRegexpLiteral)2819 TEST(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 
TEST(NoErrorsNewExpression)2835 TEST(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 
TEST(ErrorsNewExpression)2874 TEST(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 
TEST(StrictObjectLiteralChecking)2893 TEST(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 
TEST(ErrorsObjectLiteralChecking)2918 TEST(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 
TEST(NoErrorsObjectLiteralChecking)2942 TEST(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 
TEST(TooManyArguments)3005 TEST(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 
TEST(StrictDelete)3030 TEST(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 
TEST(NoErrorsDeclsInCase)3084 TEST(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 
TEST(InvalidLeftHandSide)3111 TEST(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 
TEST(FuncNameInferrerBasic)3189 TEST(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 
TEST(FuncNameInferrerTwoByte)3229 TEST(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 
TEST(FuncNameInferrerEscaped)3258 TEST(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 
TEST(RegressionLazyFunctionWithErrorWithArg)3287 TEST(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 
TEST(SerializationOfMaybeAssignmentFlag)3307 TEST(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 
TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned)3362 TEST(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 
TEST(InnerAssignment)3407 TEST(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 
3551 namespace {
3552 
3553 int* global_use_counts = NULL;
3554 
MockUseCounterCallback(v8::Isolate * isolate,v8::Isolate::UseCounterFeature feature)3555 void MockUseCounterCallback(v8::Isolate* isolate,
3556                             v8::Isolate::UseCounterFeature feature) {
3557   ++global_use_counts[feature];
3558 }
3559 
3560 }
3561 
3562 
TEST(UseAsmUseCount)3563 TEST(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 
TEST(StrictModeUseCount)3577 TEST(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 
TEST(SloppyModeUseCount)3592 TEST(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 
TEST(BothModesUseCount)3605 TEST(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 
TEST(ErrorsArrowFormalParameters)3618 TEST(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 
TEST(ErrorsArrowFunctions)3676 TEST(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 
TEST(NoErrorsArrowFunctions)3796 TEST(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 
TEST(ArrowFunctionsSloppyParameterNames)3885 TEST(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 
TEST(ArrowFunctionsYieldParameterNameInGenerator)3930 TEST(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 
TEST(SuperNoErrors)3965 TEST(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 
TEST(SuperErrors)3990 TEST(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 
TEST(SuperCall)4017 TEST(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 
TEST(SuperNewNoErrors)4053 TEST(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 
TEST(SuperNewErrors)4078 TEST(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 
TEST(SuperErrorsNonMethods)4109 TEST(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 
TEST(NoErrorsMethodDefinition)4147 TEST(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 
TEST(MethodDefinitionNames)4167 TEST(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 
TEST(MethodDefinitionStrictFormalParamereters)4241 TEST(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 
TEST(MethodDefinitionEvalArguments)4260 TEST(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 
TEST(MethodDefinitionDuplicateEvalArguments)4283 TEST(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 
TEST(MethodDefinitionDuplicateProperty)4304 TEST(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 
TEST(ClassExpressionNoErrors)4338 TEST(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 
TEST(ClassDeclarationNoErrors)4360 TEST(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 
TEST(ClassBodyNoErrors)4377 TEST(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 
TEST(ClassPropertyNameNoErrors)4434 TEST(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 
TEST(ClassExpressionErrors)4487 TEST(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 
TEST(ClassDeclarationErrors)4513 TEST(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 
TEST(ClassNameErrors)4545 TEST(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 
TEST(ClassGetterParamNameErrors)4570 TEST(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 
TEST(ClassStaticPrototypeErrors)4598 TEST(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 
TEST(ClassSpecialConstructorErrors)4621 TEST(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 
TEST(ClassConstructorNoErrors)4643 TEST(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 
TEST(ClassMultipleConstructorErrors)4660 TEST(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 
TEST(ClassMultiplePropertyNamesNoErrors)4673 TEST(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 
TEST(ClassesAreStrictErrors)4690 TEST(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 
TEST(ObjectLiteralPropertyShorthandKeywordsError)4705 TEST(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 
TEST(ObjectLiteralPropertyShorthandStrictKeywords)4754 TEST(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 
TEST(ObjectLiteralPropertyShorthandError)4779 TEST(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 
TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError)4801 TEST(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 
TEST(ConstParsingInForIn)4814 TEST(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 
TEST(StatementParsingInForIn)4829 TEST(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 
TEST(ConstParsingInForInError)4843 TEST(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 
TEST(InitializedDeclarationsInStrictForInError)4863 TEST(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 
TEST(InitializedDeclarationsInStrictForOfError)4880 TEST(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 
TEST(InitializedDeclarationsInSloppyForInError)4897 TEST(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 
TEST(InitializedDeclarationsInSloppyForOfError)4911 TEST(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 
TEST(ForInMultipleDeclarationsError)4924 TEST(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 
TEST(ForOfMultipleDeclarationsError)4951 TEST(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 
TEST(ForInNoDeclarationsError)4978 TEST(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 
TEST(ForOfNoDeclarationsError)4993 TEST(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 
TEST(ForOfInOperator)5008 TEST(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 
TEST(ForOfYieldIdentifier)5022 TEST(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 
TEST(ForOfYieldExpression)5033 TEST(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 
TEST(ForOfExpressionError)5048 TEST(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 
TEST(InvalidUnicodeEscapes)5066 TEST(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 
TEST(UnicodeEscapes)5096 TEST(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 
TEST(ScanTemplateLiterals)5122 TEST(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 
TEST(ScanTaggedTemplateLiterals)5156 TEST(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 
TEST(TemplateMaterializedLiterals)5191 TEST(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 
TEST(ScanUnterminatedTemplateLiterals)5218 TEST(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 
TEST(TemplateLiteralsIllegalTokens)5252 TEST(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 
TEST(ParseRestParameters)5272 TEST(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 
TEST(ParseRestParametersErrors)5302 TEST(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 
TEST(RestParameterInSetterMethodError)5332 TEST(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 
TEST(RestParametersEvalArguments)5347 TEST(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 
TEST(RestParametersDuplicateEvalArguments)5375 TEST(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 
TEST(SpreadCall)5396 TEST(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 
TEST(SpreadCallErrors)5413 TEST(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 
TEST(BadRestSpread)5424 TEST(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 
TEST(LexicalScopingSloppyMode)5436 TEST(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 
TEST(ComputedPropertyName)5451 TEST(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 
TEST(ComputedPropertyNameShorthandError)5482 TEST(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 
TEST(BasicImportExportParsing)5494 TEST(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 
TEST(ImportExportParsingErrors)5594 TEST(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 
TEST(ModuleTopLevelFunctionDecl)5684 TEST(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 
TEST(ModuleAwaitReserved)5721 TEST(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 
TEST(ModuleAwaitReservedPreParse)5776 TEST(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 
TEST(ModuleAwaitPermitted)5783 TEST(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 
TEST(EnumReserved)5803 TEST(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 
TEST(ModuleParsingInternals)5858 TEST(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 
TEST(DuplicateProtoError)5922 TEST(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 
TEST(DuplicateProtoNoError)5940 TEST(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 
TEST(DeclarationsError)5959 TEST(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 
TestLanguageMode(const char * source,i::LanguageMode expected_language_mode)5978 void 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 
TEST(LanguageModeDirectives)6000 TEST(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 
TEST(PropertyNameEvalArguments)6010 TEST(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 
TEST(FunctionLiteralDuplicateParameters)6050 TEST(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 
TEST(ArrowFunctionASIErrors)6078 TEST(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 
TEST(DestructuringPositiveTests)6094 TEST(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 
TEST(DestructuringNegativeTests)6149 TEST(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 
TEST(DestructuringAssignmentPositiveTests)6318 TEST(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 
TEST(DestructuringAssignmentNegativeTests)6511 TEST(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 
TEST(DestructuringDisallowPatternsInForVarIn)6676 TEST(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 
TEST(DestructuringDuplicateParams)6696 TEST(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 
TEST(DestructuringDuplicateParamsSloppy)6719 TEST(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 
TEST(DestructuringDisallowPatternsInSingleParamArrows)6737 TEST(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 
TEST(DefaultParametersYieldInInitializers)6754 TEST(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 
TEST(SpreadArray)6842 TEST(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 
TEST(SpreadArrayError)6864 TEST(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 
TEST(NewTarget)6881 TEST(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 
TEST(ConstSloppy)6927 TEST(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 
TEST(LetSloppy)6947 TEST(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 
TEST(LanguageModeDirectivesNonSimpleParameterListErrors)6970 TEST(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 
TEST(LetSloppyOnly)7016 TEST(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 
TEST(EscapedKeywords)7078 TEST(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 
TEST(MiscSyntaxErrors)7219 TEST(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 
TEST(EscapeSequenceErrors)7239 TEST(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 
TEST(FunctionSentErrors)7268 TEST(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 
TEST(NewTargetErrors)7287 TEST(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 
TEST(FunctionDeclarationError)7303 TEST(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 
TEST(ExponentiationOperator)7396 TEST(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 
TEST(ExponentiationOperatorErrors)7438 TEST(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 
TEST(AsyncAwait)7488 TEST(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 
TEST(AsyncAwaitErrors)7577 TEST(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 
TEST(AsyncAwaitModule)7724 TEST(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 
TEST(AsyncAwaitModuleErrors)7744 TEST(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 
TEST(RestrictiveForInErrors)7767 TEST(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 
TEST(NoDuplicateGeneratorsInBlock)7787 TEST(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 
TEST(NoDuplicateAsyncFunctionInBlock)7813 TEST(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