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