1a17475adad318894c84287b9553db1bc39e8679
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-parsing.cc
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.h"
35 #include "src/ast-numbering.h"
36 #include "src/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/parser.h"
42 #include "src/preparser.h"
43 #include "src/rewriter.h"
44 #include "src/scanner-character-streams.h"
45 #include "src/token.h"
46 #include "src/utils.h"
47
48 #include "test/cctest/cctest.h"
49
50 TEST(ScanKeywords) {
51   struct KeywordToken {
52     const char* keyword;
53     i::Token::Value token;
54   };
55
56   static const KeywordToken keywords[] = {
57 #define KEYWORD(t, s, d) { s, i::Token::t },
58       TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
59 #undef KEYWORD
60       { NULL, i::Token::IDENTIFIER }
61   };
62
63   KeywordToken key_token;
64   i::UnicodeCache unicode_cache;
65   i::byte buffer[32];
66   for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
67     const i::byte* keyword =
68         reinterpret_cast<const i::byte*>(key_token.keyword);
69     int length = i::StrLength(key_token.keyword);
70     CHECK(static_cast<int>(sizeof(buffer)) >= length);
71     {
72       i::Utf8ToUtf16CharacterStream stream(keyword, length);
73       i::Scanner scanner(&unicode_cache);
74       // The scanner should parse Harmony keywords for this test.
75       scanner.SetHarmonyScoping(true);
76       scanner.SetHarmonyModules(true);
77       scanner.SetHarmonyClasses(true);
78       scanner.Initialize(&stream);
79       CHECK_EQ(key_token.token, scanner.Next());
80       CHECK_EQ(i::Token::EOS, scanner.Next());
81     }
82     // Removing characters will make keyword matching fail.
83     {
84       i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
85       i::Scanner scanner(&unicode_cache);
86       scanner.Initialize(&stream);
87       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
88       CHECK_EQ(i::Token::EOS, scanner.Next());
89     }
90     // Adding characters will make keyword matching fail.
91     static const char chars_to_append[] = { 'z', '0', '_' };
92     for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
93       i::MemMove(buffer, keyword, length);
94       buffer[length] = chars_to_append[j];
95       i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
96       i::Scanner scanner(&unicode_cache);
97       scanner.Initialize(&stream);
98       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
99       CHECK_EQ(i::Token::EOS, scanner.Next());
100     }
101     // Replacing characters will make keyword matching fail.
102     {
103       i::MemMove(buffer, keyword, length);
104       buffer[length - 1] = '_';
105       i::Utf8ToUtf16CharacterStream stream(buffer, length);
106       i::Scanner scanner(&unicode_cache);
107       scanner.Initialize(&stream);
108       CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
109       CHECK_EQ(i::Token::EOS, scanner.Next());
110     }
111   }
112 }
113
114
115 TEST(ScanHTMLEndComments) {
116   v8::V8::Initialize();
117   v8::Isolate* isolate = CcTest::isolate();
118   v8::HandleScope handles(isolate);
119
120   // Regression test. See:
121   //    http://code.google.com/p/chromium/issues/detail?id=53548
122   // Tests that --> is correctly interpreted as comment-to-end-of-line if there
123   // is only whitespace before it on the line (with comments considered as
124   // whitespace, even a multiline-comment containing a newline).
125   // This was not the case if it occurred before the first real token
126   // in the input.
127   const char* tests[] = {
128       // Before first real token.
129       "--> is eol-comment\nvar y = 37;\n",
130       "\n --> is eol-comment\nvar y = 37;\n",
131       "/* precomment */ --> is eol-comment\nvar y = 37;\n",
132       "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
133       // After first real token.
134       "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
135       "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
136       NULL
137   };
138
139   const char* fail_tests[] = {
140       "x --> is eol-comment\nvar y = 37;\n",
141       "\"\\n\" --> is eol-comment\nvar y = 37;\n",
142       "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
143       "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
144       "var x = 42; --> is eol-comment\nvar y = 37;\n",
145       "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
146       NULL
147   };
148
149   // Parser/Scanner needs a stack limit.
150   CcTest::i_isolate()->stack_guard()->SetStackLimit(
151       i::GetCurrentStackPosition() - 128 * 1024);
152   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
153   for (int i = 0; tests[i]; i++) {
154     const i::byte* source =
155         reinterpret_cast<const i::byte*>(tests[i]);
156     i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
157     i::CompleteParserRecorder log;
158     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
159     scanner.Initialize(&stream);
160     i::Zone zone;
161     i::AstValueFactory ast_value_factory(
162         &zone, CcTest::i_isolate()->heap()->HashSeed());
163     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
164                            stack_limit);
165     preparser.set_allow_lazy(true);
166     i::PreParser::PreParseResult result = preparser.PreParseProgram();
167     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
168     CHECK(!log.HasError());
169   }
170
171   for (int i = 0; fail_tests[i]; i++) {
172     const i::byte* source =
173         reinterpret_cast<const i::byte*>(fail_tests[i]);
174     i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
175     i::CompleteParserRecorder log;
176     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
177     scanner.Initialize(&stream);
178     i::Zone zone;
179     i::AstValueFactory ast_value_factory(
180         &zone, CcTest::i_isolate()->heap()->HashSeed());
181     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
182                            stack_limit);
183     preparser.set_allow_lazy(true);
184     i::PreParser::PreParseResult result = preparser.PreParseProgram();
185     // Even in the case of a syntax error, kPreParseSuccess is returned.
186     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
187     CHECK(log.HasError());
188   }
189 }
190
191
192 class ScriptResource : public v8::String::ExternalOneByteStringResource {
193  public:
194   ScriptResource(const char* data, size_t length)
195       : data_(data), length_(length) { }
196
197   const char* data() const { return data_; }
198   size_t length() const { return length_; }
199
200  private:
201   const char* data_;
202   size_t length_;
203 };
204
205
206 TEST(UsingCachedData) {
207   v8::Isolate* isolate = CcTest::isolate();
208   v8::HandleScope handles(isolate);
209   v8::Local<v8::Context> context = v8::Context::New(isolate);
210   v8::Context::Scope context_scope(context);
211   CcTest::i_isolate()->stack_guard()->SetStackLimit(
212       i::GetCurrentStackPosition() - 128 * 1024);
213
214   // Source containing functions that might be lazily compiled  and all types
215   // of symbols (string, propertyName, regexp).
216   const char* source =
217       "var x = 42;"
218       "function foo(a) { return function nolazy(b) { return a + b; } }"
219       "function bar(a) { if (a) return function lazy(b) { return b; } }"
220       "var z = {'string': 'string literal', bareword: 'propertyName', "
221       "         42: 'number literal', for: 'keyword as propertyName', "
222       "         f\\u006fr: 'keyword propertyname with escape'};"
223       "var v = /RegExp Literal/;"
224       "var w = /RegExp Literal\\u0020With Escape/gin;"
225       "var y = { get getter() { return 42; }, "
226       "          set setter(v) { this.value = v; }};"
227       "var f = a => function (b) { return a + b; };"
228       "var g = a => b => a + b;";
229   int source_length = i::StrLength(source);
230
231   // ScriptResource will be deleted when the corresponding String is GCd.
232   v8::ScriptCompiler::Source script_source(v8::String::NewExternal(
233       isolate, new ScriptResource(source, source_length)));
234   i::FLAG_harmony_arrow_functions = true;
235   i::FLAG_min_preparse_length = 0;
236   v8::ScriptCompiler::Compile(isolate, &script_source,
237                               v8::ScriptCompiler::kProduceParserCache);
238   CHECK(script_source.GetCachedData());
239
240   // Compile the script again, using the cached data.
241   bool lazy_flag = i::FLAG_lazy;
242   i::FLAG_lazy = true;
243   v8::ScriptCompiler::Compile(isolate, &script_source,
244                               v8::ScriptCompiler::kConsumeParserCache);
245   i::FLAG_lazy = false;
246   v8::ScriptCompiler::CompileUnbound(isolate, &script_source,
247                                      v8::ScriptCompiler::kConsumeParserCache);
248   i::FLAG_lazy = lazy_flag;
249 }
250
251
252 TEST(PreparseFunctionDataIsUsed) {
253   // This tests that we actually do use the function data generated by the
254   // preparser.
255
256   // Make preparsing work for short scripts.
257   i::FLAG_min_preparse_length = 0;
258   i::FLAG_harmony_arrow_functions = true;
259
260   v8::Isolate* isolate = CcTest::isolate();
261   v8::HandleScope handles(isolate);
262   v8::Local<v8::Context> context = v8::Context::New(isolate);
263   v8::Context::Scope context_scope(context);
264   CcTest::i_isolate()->stack_guard()->SetStackLimit(
265       i::GetCurrentStackPosition() - 128 * 1024);
266
267   const char* good_code[] = {
268       "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
269       "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
270   };
271
272   // Insert a syntax error inside the lazy function.
273   const char* bad_code[] = {
274       "function this_is_lazy() { if (   } function foo() { return 25; } foo();",
275       "var this_is_lazy = () => { if (   }; var foo = () => 25; foo();",
276   };
277
278   for (unsigned i = 0; i < arraysize(good_code); i++) {
279     v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
280     v8::ScriptCompiler::Compile(isolate, &good_source,
281                                 v8::ScriptCompiler::kProduceDataToCache);
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         v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
296     CHECK(result->IsInt32());
297     CHECK_EQ(25, result->Int32Value());
298   }
299 }
300
301
302 TEST(StandAlonePreParser) {
303   v8::V8::Initialize();
304
305   CcTest::i_isolate()->stack_guard()->SetStackLimit(
306       i::GetCurrentStackPosition() - 128 * 1024);
307
308   const char* programs[] = {
309       "{label: 42}",
310       "var x = 42;",
311       "function foo(x, y) { return x + y; }",
312       "%ArgleBargle(glop);",
313       "var x = new new Function('this.x = 42');",
314       "var f = (x, y) => x + y;",
315       NULL
316   };
317
318   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
319   for (int i = 0; programs[i]; i++) {
320     const char* program = programs[i];
321     i::Utf8ToUtf16CharacterStream stream(
322         reinterpret_cast<const i::byte*>(program),
323         static_cast<unsigned>(strlen(program)));
324     i::CompleteParserRecorder log;
325     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
326     scanner.Initialize(&stream);
327
328     i::Zone zone;
329     i::AstValueFactory ast_value_factory(
330         &zone, CcTest::i_isolate()->heap()->HashSeed());
331     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
332                            stack_limit);
333     preparser.set_allow_lazy(true);
334     preparser.set_allow_natives(true);
335     preparser.set_allow_harmony_arrow_functions(true);
336     i::PreParser::PreParseResult result = preparser.PreParseProgram();
337     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
338     CHECK(!log.HasError());
339   }
340 }
341
342
343 TEST(StandAlonePreParserNoNatives) {
344   v8::V8::Initialize();
345
346   CcTest::i_isolate()->stack_guard()->SetStackLimit(
347       i::GetCurrentStackPosition() - 128 * 1024);
348
349   const char* programs[] = {
350       "%ArgleBargle(glop);",
351       "var x = %_IsSmi(42);",
352       NULL
353   };
354
355   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
356   for (int i = 0; programs[i]; i++) {
357     const char* program = programs[i];
358     i::Utf8ToUtf16CharacterStream stream(
359         reinterpret_cast<const i::byte*>(program),
360         static_cast<unsigned>(strlen(program)));
361     i::CompleteParserRecorder log;
362     i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
363     scanner.Initialize(&stream);
364
365     // Preparser defaults to disallowing natives syntax.
366     i::Zone zone;
367     i::AstValueFactory ast_value_factory(
368         &zone, CcTest::i_isolate()->heap()->HashSeed());
369     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
370                            stack_limit);
371     preparser.set_allow_lazy(true);
372     i::PreParser::PreParseResult result = preparser.PreParseProgram();
373     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
374     CHECK(log.HasError());
375   }
376 }
377
378
379 TEST(PreparsingObjectLiterals) {
380   // Regression test for a bug where the symbol stream produced by PreParser
381   // didn't match what Parser wanted to consume.
382   v8::Isolate* isolate = CcTest::isolate();
383   v8::HandleScope handles(isolate);
384   v8::Local<v8::Context> context = v8::Context::New(isolate);
385   v8::Context::Scope context_scope(context);
386   CcTest::i_isolate()->stack_guard()->SetStackLimit(
387       i::GetCurrentStackPosition() - 128 * 1024);
388
389   {
390     const char* source = "var myo = {if: \"foo\"}; myo.if;";
391     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
392     CHECK(result->IsString());
393     v8::String::Utf8Value utf8(result);
394     CHECK_EQ(0, strcmp("foo", *utf8));
395   }
396
397   {
398     const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
399     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
400     CHECK(result->IsString());
401     v8::String::Utf8Value utf8(result);
402     CHECK_EQ(0, strcmp("foo", *utf8));
403   }
404
405   {
406     const char* source = "var myo = {1: \"foo\"}; myo[1];";
407     v8::Local<v8::Value> result = ParserCacheCompileRun(source);
408     CHECK(result->IsString());
409     v8::String::Utf8Value utf8(result);
410     CHECK_EQ(0, strcmp("foo", *utf8));
411   }
412 }
413
414
415 TEST(RegressChromium62639) {
416   v8::V8::Initialize();
417   i::Isolate* isolate = CcTest::i_isolate();
418
419   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
420                                         128 * 1024);
421
422   const char* program = "var x = 'something';\n"
423                         "escape: function() {}";
424   // Fails parsing expecting an identifier after "function".
425   // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
426   // and then used the invalid currently scanned literal. This always
427   // failed in debug mode, and sometimes crashed in release mode.
428
429   i::Utf8ToUtf16CharacterStream stream(
430       reinterpret_cast<const i::byte*>(program),
431       static_cast<unsigned>(strlen(program)));
432   i::CompleteParserRecorder log;
433   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
434   scanner.Initialize(&stream);
435   i::Zone zone;
436   i::AstValueFactory ast_value_factory(&zone,
437                                        CcTest::i_isolate()->heap()->HashSeed());
438   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
439                          CcTest::i_isolate()->stack_guard()->real_climit());
440   preparser.set_allow_lazy(true);
441   i::PreParser::PreParseResult result = preparser.PreParseProgram();
442   // Even in the case of a syntax error, kPreParseSuccess is returned.
443   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
444   CHECK(log.HasError());
445 }
446
447
448 TEST(Regress928) {
449   v8::V8::Initialize();
450   i::Isolate* isolate = CcTest::i_isolate();
451   i::Factory* factory = isolate->factory();
452
453   // Preparsing didn't consider the catch clause of a try statement
454   // as with-content, which made it assume that a function inside
455   // the block could be lazily compiled, and an extra, unexpected,
456   // entry was added to the data.
457   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
458                                         128 * 1024);
459
460   const char* program =
461       "try { } catch (e) { var foo = function () { /* first */ } }"
462       "var bar = function () { /* second */ }";
463
464   v8::HandleScope handles(CcTest::isolate());
465   i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
466   i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
467   i::CompleteParserRecorder log;
468   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
469   scanner.Initialize(&stream);
470   i::Zone zone;
471   i::AstValueFactory ast_value_factory(&zone,
472                                        CcTest::i_isolate()->heap()->HashSeed());
473   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
474                          CcTest::i_isolate()->stack_guard()->real_climit());
475   preparser.set_allow_lazy(true);
476   i::PreParser::PreParseResult result = preparser.PreParseProgram();
477   CHECK_EQ(i::PreParser::kPreParseSuccess, result);
478   i::ScriptData* sd = log.GetScriptData();
479   i::ParseData* pd = i::ParseData::FromCachedData(sd);
480   pd->Initialize();
481
482   int first_function =
483       static_cast<int>(strstr(program, "function") - program);
484   int first_lbrace = first_function + i::StrLength("function () ");
485   CHECK_EQ('{', program[first_lbrace]);
486   i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace);
487   CHECK(!entry1.is_valid());
488
489   int second_function =
490       static_cast<int>(strstr(program + first_lbrace, "function") - program);
491   int second_lbrace =
492       second_function + i::StrLength("function () ");
493   CHECK_EQ('{', program[second_lbrace]);
494   i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace);
495   CHECK(entry2.is_valid());
496   CHECK_EQ('}', program[entry2.end_pos() - 1]);
497   delete sd;
498   delete pd;
499 }
500
501
502 TEST(PreParseOverflow) {
503   v8::V8::Initialize();
504
505   CcTest::i_isolate()->stack_guard()->SetStackLimit(
506       i::GetCurrentStackPosition() - 128 * 1024);
507
508   size_t kProgramSize = 1024 * 1024;
509   i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
510   memset(program.get(), '(', kProgramSize);
511   program[kProgramSize] = '\0';
512
513   uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
514
515   i::Utf8ToUtf16CharacterStream stream(
516       reinterpret_cast<const i::byte*>(program.get()),
517       static_cast<unsigned>(kProgramSize));
518   i::CompleteParserRecorder log;
519   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
520   scanner.Initialize(&stream);
521
522   i::Zone zone;
523   i::AstValueFactory ast_value_factory(&zone,
524                                        CcTest::i_isolate()->heap()->HashSeed());
525   i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
526                          stack_limit);
527   preparser.set_allow_lazy(true);
528   preparser.set_allow_harmony_arrow_functions(true);
529   i::PreParser::PreParseResult result = preparser.PreParseProgram();
530   CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
531 }
532
533
534 class TestExternalResource: public v8::String::ExternalStringResource {
535  public:
536   explicit TestExternalResource(uint16_t* data, int length)
537       : data_(data), length_(static_cast<size_t>(length)) { }
538
539   ~TestExternalResource() { }
540
541   const uint16_t* data() const {
542     return data_;
543   }
544
545   size_t length() const {
546     return length_;
547   }
548  private:
549   uint16_t* data_;
550   size_t length_;
551 };
552
553
554 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
555
556 void TestCharacterStream(const char* one_byte_source, unsigned length,
557                          unsigned start = 0, unsigned end = 0) {
558   if (end == 0) end = length;
559   unsigned sub_length = end - start;
560   i::Isolate* isolate = CcTest::i_isolate();
561   i::Factory* factory = isolate->factory();
562   i::HandleScope test_scope(isolate);
563   i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
564   for (unsigned i = 0; i < length; i++) {
565     uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
566   }
567   i::Vector<const char> one_byte_vector(one_byte_source,
568                                         static_cast<int>(length));
569   i::Handle<i::String> one_byte_string =
570       factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
571   TestExternalResource resource(uc16_buffer.get(), length);
572   i::Handle<i::String> uc16_string(
573       factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
574
575   i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
576       i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
577   i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
578                                                      end);
579   i::Utf8ToUtf16CharacterStream utf8_stream(
580       reinterpret_cast<const i::byte*>(one_byte_source), end);
581   utf8_stream.SeekForward(start);
582
583   unsigned i = start;
584   while (i < end) {
585     // Read streams one char at a time
586     CHECK_EQU(i, uc16_stream.pos());
587     CHECK_EQU(i, string_stream.pos());
588     CHECK_EQU(i, utf8_stream.pos());
589     int32_t c0 = one_byte_source[i];
590     int32_t c1 = uc16_stream.Advance();
591     int32_t c2 = string_stream.Advance();
592     int32_t c3 = utf8_stream.Advance();
593     i++;
594     CHECK_EQ(c0, c1);
595     CHECK_EQ(c0, c2);
596     CHECK_EQ(c0, c3);
597     CHECK_EQU(i, uc16_stream.pos());
598     CHECK_EQU(i, string_stream.pos());
599     CHECK_EQU(i, utf8_stream.pos());
600   }
601   while (i > start + sub_length / 4) {
602     // Pushback, re-read, pushback again.
603     int32_t c0 = one_byte_source[i - 1];
604     CHECK_EQU(i, uc16_stream.pos());
605     CHECK_EQU(i, string_stream.pos());
606     CHECK_EQU(i, utf8_stream.pos());
607     uc16_stream.PushBack(c0);
608     string_stream.PushBack(c0);
609     utf8_stream.PushBack(c0);
610     i--;
611     CHECK_EQU(i, uc16_stream.pos());
612     CHECK_EQU(i, string_stream.pos());
613     CHECK_EQU(i, utf8_stream.pos());
614     int32_t c1 = uc16_stream.Advance();
615     int32_t c2 = string_stream.Advance();
616     int32_t c3 = utf8_stream.Advance();
617     i++;
618     CHECK_EQU(i, uc16_stream.pos());
619     CHECK_EQU(i, string_stream.pos());
620     CHECK_EQU(i, utf8_stream.pos());
621     CHECK_EQ(c0, c1);
622     CHECK_EQ(c0, c2);
623     CHECK_EQ(c0, c3);
624     uc16_stream.PushBack(c0);
625     string_stream.PushBack(c0);
626     utf8_stream.PushBack(c0);
627     i--;
628     CHECK_EQU(i, uc16_stream.pos());
629     CHECK_EQU(i, string_stream.pos());
630     CHECK_EQU(i, utf8_stream.pos());
631   }
632   unsigned halfway = start + sub_length / 2;
633   uc16_stream.SeekForward(halfway - i);
634   string_stream.SeekForward(halfway - i);
635   utf8_stream.SeekForward(halfway - i);
636   i = halfway;
637   CHECK_EQU(i, uc16_stream.pos());
638   CHECK_EQU(i, string_stream.pos());
639   CHECK_EQU(i, utf8_stream.pos());
640
641   while (i < end) {
642     // Read streams one char at a time
643     CHECK_EQU(i, uc16_stream.pos());
644     CHECK_EQU(i, string_stream.pos());
645     CHECK_EQU(i, utf8_stream.pos());
646     int32_t c0 = one_byte_source[i];
647     int32_t c1 = uc16_stream.Advance();
648     int32_t c2 = string_stream.Advance();
649     int32_t c3 = utf8_stream.Advance();
650     i++;
651     CHECK_EQ(c0, c1);
652     CHECK_EQ(c0, c2);
653     CHECK_EQ(c0, c3);
654     CHECK_EQU(i, uc16_stream.pos());
655     CHECK_EQU(i, string_stream.pos());
656     CHECK_EQU(i, utf8_stream.pos());
657   }
658
659   int32_t c1 = uc16_stream.Advance();
660   int32_t c2 = string_stream.Advance();
661   int32_t c3 = utf8_stream.Advance();
662   CHECK_LT(c1, 0);
663   CHECK_LT(c2, 0);
664   CHECK_LT(c3, 0);
665 }
666
667
668 TEST(CharacterStreams) {
669   v8::Isolate* isolate = CcTest::isolate();
670   v8::HandleScope handles(isolate);
671   v8::Local<v8::Context> context = v8::Context::New(isolate);
672   v8::Context::Scope context_scope(context);
673
674   TestCharacterStream("abc\0\n\r\x7f", 7);
675   static const unsigned kBigStringSize = 4096;
676   char buffer[kBigStringSize + 1];
677   for (unsigned i = 0; i < kBigStringSize; i++) {
678     buffer[i] = static_cast<char>(i & 0x7f);
679   }
680   TestCharacterStream(buffer, kBigStringSize);
681
682   TestCharacterStream(buffer, kBigStringSize, 576, 3298);
683
684   TestCharacterStream("\0", 1);
685   TestCharacterStream("", 0);
686 }
687
688
689 TEST(Utf8CharacterStream) {
690   static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
691   static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
692
693   static const int kAllUtf8CharsSize =
694       (unibrow::Utf8::kMaxOneByteChar + 1) +
695       (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
696       (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
697   static const unsigned kAllUtf8CharsSizeU =
698       static_cast<unsigned>(kAllUtf8CharsSize);
699
700   char buffer[kAllUtf8CharsSizeU];
701   unsigned cursor = 0;
702   for (int i = 0; i <= kMaxUC16Char; i++) {
703     cursor += unibrow::Utf8::Encode(buffer + cursor,
704                                     i,
705                                     unibrow::Utf16::kNoPreviousCharacter);
706   }
707   DCHECK(cursor == kAllUtf8CharsSizeU);
708
709   i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
710                                        kAllUtf8CharsSizeU);
711   for (int i = 0; i <= kMaxUC16Char; i++) {
712     CHECK_EQU(i, stream.pos());
713     int32_t c = stream.Advance();
714     CHECK_EQ(i, c);
715     CHECK_EQU(i + 1, stream.pos());
716   }
717   for (int i = kMaxUC16Char; i >= 0; i--) {
718     CHECK_EQU(i + 1, stream.pos());
719     stream.PushBack(i);
720     CHECK_EQU(i, stream.pos());
721   }
722   int i = 0;
723   while (stream.pos() < kMaxUC16CharU) {
724     CHECK_EQU(i, stream.pos());
725     int progress = static_cast<int>(stream.SeekForward(12));
726     i += progress;
727     int32_t c = stream.Advance();
728     if (i <= kMaxUC16Char) {
729       CHECK_EQ(i, c);
730     } else {
731       CHECK_EQ(-1, c);
732     }
733     i += 1;
734     CHECK_EQU(i, stream.pos());
735   }
736 }
737
738 #undef CHECK_EQU
739
740 void TestStreamScanner(i::Utf16CharacterStream* stream,
741                        i::Token::Value* expected_tokens,
742                        int skip_pos = 0,  // Zero means not skipping.
743                        int skip_to = 0) {
744   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
745   scanner.Initialize(stream);
746
747   int i = 0;
748   do {
749     i::Token::Value expected = expected_tokens[i];
750     i::Token::Value actual = scanner.Next();
751     CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
752     if (scanner.location().end_pos == skip_pos) {
753       scanner.SeekForward(skip_to);
754     }
755     i++;
756   } while (expected_tokens[i] != i::Token::ILLEGAL);
757 }
758
759
760 TEST(StreamScanner) {
761   v8::V8::Initialize();
762
763   const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
764   i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
765                                         static_cast<unsigned>(strlen(str1)));
766   i::Token::Value expectations1[] = {
767       i::Token::LBRACE,
768       i::Token::IDENTIFIER,
769       i::Token::IDENTIFIER,
770       i::Token::FOR,
771       i::Token::COLON,
772       i::Token::MUL,
773       i::Token::DIV,
774       i::Token::LT,
775       i::Token::SUB,
776       i::Token::IDENTIFIER,
777       i::Token::EOS,
778       i::Token::ILLEGAL
779   };
780   TestStreamScanner(&stream1, expectations1, 0, 0);
781
782   const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
783   i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
784                                         static_cast<unsigned>(strlen(str2)));
785   i::Token::Value expectations2[] = {
786       i::Token::CASE,
787       i::Token::DEFAULT,
788       i::Token::CONST,
789       i::Token::LBRACE,
790       // Skipped part here
791       i::Token::RBRACE,
792       i::Token::DO,
793       i::Token::EOS,
794       i::Token::ILLEGAL
795   };
796   DCHECK_EQ('{', str2[19]);
797   DCHECK_EQ('}', str2[37]);
798   TestStreamScanner(&stream2, expectations2, 20, 37);
799
800   const char* str3 = "{}}}}";
801   i::Token::Value expectations3[] = {
802       i::Token::LBRACE,
803       i::Token::RBRACE,
804       i::Token::RBRACE,
805       i::Token::RBRACE,
806       i::Token::RBRACE,
807       i::Token::EOS,
808       i::Token::ILLEGAL
809   };
810   // Skip zero-four RBRACEs.
811   for (int i = 0; i <= 4; i++) {
812      expectations3[6 - i] = i::Token::ILLEGAL;
813      expectations3[5 - i] = i::Token::EOS;
814      i::Utf8ToUtf16CharacterStream stream3(
815          reinterpret_cast<const i::byte*>(str3),
816          static_cast<unsigned>(strlen(str3)));
817      TestStreamScanner(&stream3, expectations3, 1, 1 + i);
818   }
819 }
820
821
822 void TestScanRegExp(const char* re_source, const char* expected) {
823   i::Utf8ToUtf16CharacterStream stream(
824        reinterpret_cast<const i::byte*>(re_source),
825        static_cast<unsigned>(strlen(re_source)));
826   i::HandleScope scope(CcTest::i_isolate());
827   i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
828   scanner.Initialize(&stream);
829
830   i::Token::Value start = scanner.peek();
831   CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
832   CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
833   scanner.Next();  // Current token is now the regexp literal.
834   i::Zone zone;
835   i::AstValueFactory ast_value_factory(&zone,
836                                        CcTest::i_isolate()->heap()->HashSeed());
837   ast_value_factory.Internalize(CcTest::i_isolate());
838   i::Handle<i::String> val =
839       scanner.CurrentSymbol(&ast_value_factory)->string();
840   i::DisallowHeapAllocation no_alloc;
841   i::String::FlatContent content = val->GetFlatContent();
842   CHECK(content.IsOneByte());
843   i::Vector<const uint8_t> actual = content.ToOneByteVector();
844   for (int i = 0; i < actual.length(); i++) {
845     CHECK_NE('\0', expected[i]);
846     CHECK_EQ(expected[i], actual[i]);
847   }
848 }
849
850
851 TEST(RegExpScanning) {
852   v8::V8::Initialize();
853
854   // RegExp token with added garbage at the end. The scanner should only
855   // scan the RegExp until the terminating slash just before "flipperwald".
856   TestScanRegExp("/b/flipperwald", "b");
857   // Incomplete escape sequences doesn't hide the terminating slash.
858   TestScanRegExp("/\\x/flipperwald", "\\x");
859   TestScanRegExp("/\\u/flipperwald", "\\u");
860   TestScanRegExp("/\\u1/flipperwald", "\\u1");
861   TestScanRegExp("/\\u12/flipperwald", "\\u12");
862   TestScanRegExp("/\\u123/flipperwald", "\\u123");
863   TestScanRegExp("/\\c/flipperwald", "\\c");
864   TestScanRegExp("/\\c//flipperwald", "\\c");
865   // Slashes inside character classes are not terminating.
866   TestScanRegExp("/[/]/flipperwald", "[/]");
867   TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
868   // Incomplete escape sequences inside a character class doesn't hide
869   // the end of the character class.
870   TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
871   TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
872   TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
873   TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
874   TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
875   TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
876   TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
877   TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
878   // Escaped ']'s wont end the character class.
879   TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
880   // Escaped slashes are not terminating.
881   TestScanRegExp("/\\//flipperwald", "\\/");
882   // Starting with '=' works too.
883   TestScanRegExp("/=/", "=");
884   TestScanRegExp("/=?/", "=?");
885 }
886
887
888 static int Utf8LengthHelper(const char* s) {
889   int len = i::StrLength(s);
890   int character_length = len;
891   for (int i = 0; i < len; i++) {
892     unsigned char c = s[i];
893     int input_offset = 0;
894     int output_adjust = 0;
895     if (c > 0x7f) {
896       if (c < 0xc0) continue;
897       if (c >= 0xf0) {
898         if (c >= 0xf8) {
899           // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
900           // byte.
901           continue;  // Handle first UTF-8 byte.
902         }
903         if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
904           // This 4 byte sequence could have been coded as a 3 byte sequence.
905           // Record a single kBadChar for the first byte and continue.
906           continue;
907         }
908         input_offset = 3;
909         // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
910         character_length -= 2;
911       } else if (c >= 0xe0) {
912         if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
913           // This 3 byte sequence could have been coded as a 2 byte sequence.
914           // Record a single kBadChar for the first byte and continue.
915           continue;
916         }
917         input_offset = 2;
918         // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
919         output_adjust = 2;
920       } else {
921         if ((c & 0x1e) == 0) {
922           // This 2 byte sequence could have been coded as a 1 byte sequence.
923           // Record a single kBadChar for the first byte and continue.
924           continue;
925         }
926         input_offset = 1;
927         // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
928         output_adjust = 1;
929       }
930       bool bad = false;
931       for (int j = 1; j <= input_offset; j++) {
932         if ((s[i + j] & 0xc0) != 0x80) {
933           // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
934           // which is a single UTF-16 code unit.
935           bad = true;
936           break;
937         }
938       }
939       if (!bad) {
940         i += input_offset;
941         character_length -= output_adjust;
942       }
943     }
944   }
945   return character_length;
946 }
947
948
949 TEST(ScopeUsesArgumentsSuperThis) {
950   static const struct {
951     const char* prefix;
952     const char* suffix;
953   } surroundings[] = {
954     { "function f() {", "}" },
955     { "var f = () => {", "};" },
956     { "class C { constructor() {", "} }" },
957   };
958
959   enum Expected {
960     NONE = 0,
961     ARGUMENTS = 1,
962     SUPER_PROPERTY = 1 << 1,
963     THIS = 1 << 2,
964     INNER_ARGUMENTS = 1 << 3,
965     INNER_SUPER_PROPERTY = 1 << 4,
966     INNER_THIS = 1 << 5
967   };
968
969   static const struct {
970     const char* body;
971     int expected;
972   } source_data[] = {
973     {"", NONE},
974     {"return this", THIS},
975     {"return arguments", ARGUMENTS},
976     {"return super.x", SUPER_PROPERTY},
977     {"return arguments[0]", ARGUMENTS},
978     {"return this + arguments[0]", ARGUMENTS | THIS},
979     {"return this + arguments[0] + super.x",
980      ARGUMENTS | SUPER_PROPERTY | THIS},
981     {"return x => this + x", INNER_THIS},
982     {"return x => super.f() + x", INNER_SUPER_PROPERTY},
983     {"this.foo = 42;", THIS},
984     {"this.foo();", THIS},
985     {"if (foo()) { this.f() }", THIS},
986     {"if (foo()) { super.f() }", SUPER_PROPERTY},
987     {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
988     {"while (true) { this.f() }", THIS},
989     {"while (true) { super.f() }", SUPER_PROPERTY},
990     {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
991     // Multiple nesting levels must work as well.
992     {"while (true) { while (true) { while (true) return this } }", THIS},
993     {"while (true) { while (true) { while (true) return super.f() } }",
994      SUPER_PROPERTY},
995     {"if (1) { return () => { while (true) new this() } }", INNER_THIS},
996     // Note that propagation of the inner_uses_this() value does not
997     // cross boundaries of normal functions onto parent scopes.
998     {"return function (x) { return this + x }", NONE},
999     {"return { m(x) { return super.m() + x } }", NONE},
1000     {"var x = function () { this.foo = 42 };", NONE},
1001     {"var x = { m() { super.foo = 42 } };", NONE},
1002     {"if (1) { return function () { while (true) new this() } }", NONE},
1003     {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1004     {"return function (x) { return () => this }", NONE},
1005     {"return { m(x) { return () => super.m() } }", NONE},
1006     // Flags must be correctly set when using block scoping.
1007     {"\"use strict\"; while (true) { let x; this, arguments; }",
1008      INNER_ARGUMENTS | INNER_THIS},
1009     {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1010      INNER_ARGUMENTS | INNER_SUPER_PROPERTY | INNER_THIS},
1011     {"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS},
1012     {"\"use strict\"; if (foo()) { let x; super.f() }",
1013      INNER_SUPER_PROPERTY},
1014     {"\"use strict\"; if (1) {"
1015      "  let x; return { m() { return this + super.m() + arguments } }"
1016      "}",
1017      NONE},
1018   };
1019
1020   i::Isolate* isolate = CcTest::i_isolate();
1021   i::Factory* factory = isolate->factory();
1022
1023   v8::HandleScope handles(CcTest::isolate());
1024   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1025   v8::Context::Scope context_scope(context);
1026
1027   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1028                                         128 * 1024);
1029
1030   for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1031     for (unsigned i = 0; i < arraysize(source_data); ++i) {
1032       // Super property is only allowed in constructor and method.
1033       if (((source_data[i].expected & SUPER_PROPERTY) ||
1034            (source_data[i].expected & INNER_SUPER_PROPERTY) ||
1035            (source_data[i].expected == NONE)) && j != 2) {
1036         continue;
1037       }
1038       int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1039                              i::StrLength(surroundings[j].suffix) +
1040                              i::StrLength(source_data[i].body);
1041       i::ScopedVector<char> program(kProgramByteSize + 1);
1042       i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1043                   source_data[i].body, surroundings[j].suffix);
1044       i::Handle<i::String> source =
1045           factory->NewStringFromUtf8(i::CStrVector(program.start()))
1046               .ToHandleChecked();
1047       i::Handle<i::Script> script = factory->NewScript(source);
1048       i::CompilationInfoWithZone info(script);
1049       i::Parser parser(&info, isolate->stack_guard()->real_climit(),
1050                        isolate->heap()->HashSeed(), isolate->unicode_cache());
1051       parser.set_allow_harmony_arrow_functions(true);
1052       parser.set_allow_harmony_classes(true);
1053       parser.set_allow_harmony_object_literals(true);
1054       parser.set_allow_harmony_scoping(true);
1055       parser.set_allow_harmony_sloppy(true);
1056       info.MarkAsGlobal();
1057       CHECK(parser.Parse(&info));
1058       CHECK(i::Rewriter::Rewrite(&info));
1059       CHECK(i::Scope::Analyze(&info));
1060       CHECK(info.function() != NULL);
1061
1062       i::Scope* script_scope = info.function()->scope();
1063       CHECK(script_scope->is_script_scope());
1064       CHECK_EQ(1, script_scope->inner_scopes()->length());
1065
1066       i::Scope* scope = script_scope->inner_scopes()->at(0);
1067       // Adjust for constructor scope.
1068       if (j == 2) {
1069         CHECK_EQ(1, scope->inner_scopes()->length());
1070         scope = scope->inner_scopes()->at(0);
1071       }
1072       CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
1073                scope->uses_arguments());
1074       CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1075                scope->uses_super_property());
1076       CHECK_EQ((source_data[i].expected & THIS) != 0, scope->uses_this());
1077       CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0,
1078                scope->inner_uses_arguments());
1079       CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0,
1080                scope->inner_uses_super_property());
1081       CHECK_EQ((source_data[i].expected & INNER_THIS) != 0,
1082                scope->inner_uses_this());
1083     }
1084   }
1085 }
1086
1087
1088 TEST(ScopePositions) {
1089   v8::internal::FLAG_harmony_scoping = true;
1090
1091   // Test the parser for correctly setting the start and end positions
1092   // of a scope. We check the scope positions of exactly one scope
1093   // nested in the global scope of a program. 'inner source' is the
1094   // source code that determines the part of the source belonging
1095   // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1096   // parts of the source that belong to the global scope.
1097   struct SourceData {
1098     const char* outer_prefix;
1099     const char* inner_source;
1100     const char* outer_suffix;
1101     i::ScopeType scope_type;
1102     i::LanguageMode language_mode;
1103   };
1104
1105   const SourceData source_data[] = {
1106     { "  with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
1107     { "  with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
1108     { "  with ({}) ", "{\n"
1109       "    block;\n"
1110       "  }", "\n"
1111       "  more;", i::WITH_SCOPE, i::SLOPPY },
1112     { "  with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
1113     { "  with ({}) ", "statement", "\n"
1114       "  more;", i::WITH_SCOPE, i::SLOPPY },
1115     { "  with ({})\n"
1116       "    ", "statement;", "\n"
1117       "  more;", i::WITH_SCOPE, i::SLOPPY },
1118     { "  try {} catch ", "(e) { block; }", " more;",
1119       i::CATCH_SCOPE, i::SLOPPY },
1120     { "  try {} catch ", "(e) { block; }", "; more;",
1121       i::CATCH_SCOPE, i::SLOPPY },
1122     { "  try {} catch ", "(e) {\n"
1123       "    block;\n"
1124       "  }", "\n"
1125       "  more;", i::CATCH_SCOPE, i::SLOPPY },
1126     { "  try {} catch ", "(e) { block; }", " finally { block; } more;",
1127       i::CATCH_SCOPE, i::SLOPPY },
1128     { "  start;\n"
1129       "  ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
1130     { "  start;\n"
1131       "  ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
1132     { "  start;\n"
1133       "  ", "{\n"
1134       "    let block;\n"
1135       "  }", "\n"
1136       "  more;", i::BLOCK_SCOPE, i::STRICT },
1137     { "  start;\n"
1138       "  function fun", "(a,b) { infunction; }", " more;",
1139       i::FUNCTION_SCOPE, i::SLOPPY },
1140     { "  start;\n"
1141       "  function fun", "(a,b) {\n"
1142       "    infunction;\n"
1143       "  }", "\n"
1144       "  more;", i::FUNCTION_SCOPE, i::SLOPPY },
1145     { "  start;\n", "(a,b) => a + b", "; more;",
1146       i::ARROW_SCOPE, i::SLOPPY },
1147     { "  start;\n", "(a,b) => { return a+b; }", "\nmore;",
1148       i::ARROW_SCOPE, i::SLOPPY },
1149     { "  start;\n"
1150       "  (function fun", "(a,b) { infunction; }", ")();",
1151       i::FUNCTION_SCOPE, i::SLOPPY },
1152     { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
1153       i::BLOCK_SCOPE, i::STRICT },
1154     { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
1155       i::BLOCK_SCOPE, i::STRICT },
1156     { "  for ", "(let x = 1 ; x < 10; ++ x) {\n"
1157       "    block;\n"
1158       "  }", "\n"
1159       "  more;", i::BLOCK_SCOPE, i::STRICT },
1160     { "  for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
1161       i::BLOCK_SCOPE, i::STRICT },
1162     { "  for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
1163       "  more;", i::BLOCK_SCOPE, i::STRICT },
1164     { "  for ", "(let x = 1 ; x < 10; ++ x)\n"
1165       "    statement;", "\n"
1166       "  more;", i::BLOCK_SCOPE, i::STRICT },
1167     { "  for ", "(let x in {}) { block; }", " more;",
1168       i::BLOCK_SCOPE, i::STRICT },
1169     { "  for ", "(let x in {}) { block; }", "; more;",
1170       i::BLOCK_SCOPE, i::STRICT },
1171     { "  for ", "(let x in {}) {\n"
1172       "    block;\n"
1173       "  }", "\n"
1174       "  more;", i::BLOCK_SCOPE, i::STRICT },
1175     { "  for ", "(let x in {}) statement;", " more;",
1176       i::BLOCK_SCOPE, i::STRICT },
1177     { "  for ", "(let x in {}) statement", "\n"
1178       "  more;", i::BLOCK_SCOPE, i::STRICT },
1179     { "  for ", "(let x in {})\n"
1180       "    statement;", "\n"
1181       "  more;", i::BLOCK_SCOPE, i::STRICT },
1182     // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1183     // the preparser off in terms of byte offsets.
1184     // 6 byte encoding.
1185     { "  'foo\355\240\201\355\260\211';\n"
1186       "  (function fun", "(a,b) { infunction; }", ")();",
1187       i::FUNCTION_SCOPE, i::SLOPPY },
1188     // 4 byte encoding.
1189     { "  'foo\360\220\220\212';\n"
1190       "  (function fun", "(a,b) { infunction; }", ")();",
1191       i::FUNCTION_SCOPE, i::SLOPPY },
1192     // 3 byte encoding of \u0fff.
1193     { "  'foo\340\277\277';\n"
1194       "  (function fun", "(a,b) { infunction; }", ")();",
1195       i::FUNCTION_SCOPE, i::SLOPPY },
1196     // Broken 6 byte encoding with missing last byte.
1197     { "  'foo\355\240\201\355\211';\n"
1198       "  (function fun", "(a,b) { infunction; }", ")();",
1199       i::FUNCTION_SCOPE, i::SLOPPY },
1200     // Broken 3 byte encoding of \u0fff with missing last byte.
1201     { "  'foo\340\277';\n"
1202       "  (function fun", "(a,b) { infunction; }", ")();",
1203       i::FUNCTION_SCOPE, i::SLOPPY },
1204     // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1205     { "  'foo\340';\n"
1206       "  (function fun", "(a,b) { infunction; }", ")();",
1207       i::FUNCTION_SCOPE, i::SLOPPY },
1208     // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1209     { "  'foo\340\203\277';\n"
1210       "  (function fun", "(a,b) { infunction; }", ")();",
1211       i::FUNCTION_SCOPE, i::SLOPPY },
1212     // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1213     { "  'foo\340\201\277';\n"
1214       "  (function fun", "(a,b) { infunction; }", ")();",
1215       i::FUNCTION_SCOPE, i::SLOPPY },
1216     // Unpaired lead surrogate.
1217     { "  'foo\355\240\201';\n"
1218       "  (function fun", "(a,b) { infunction; }", ")();",
1219       i::FUNCTION_SCOPE, i::SLOPPY },
1220     // Unpaired lead surrogate where following code point is a 3 byte sequence.
1221     { "  'foo\355\240\201\340\277\277';\n"
1222       "  (function fun", "(a,b) { infunction; }", ")();",
1223       i::FUNCTION_SCOPE, i::SLOPPY },
1224     // Unpaired lead surrogate where following code point is a 4 byte encoding
1225     // of a trail surrogate.
1226     { "  'foo\355\240\201\360\215\260\211';\n"
1227       "  (function fun", "(a,b) { infunction; }", ")();",
1228       i::FUNCTION_SCOPE, i::SLOPPY },
1229     // Unpaired trail surrogate.
1230     { "  'foo\355\260\211';\n"
1231       "  (function fun", "(a,b) { infunction; }", ")();",
1232       i::FUNCTION_SCOPE, i::SLOPPY },
1233     // 2 byte encoding of \u00ff.
1234     { "  'foo\303\277';\n"
1235       "  (function fun", "(a,b) { infunction; }", ")();",
1236       i::FUNCTION_SCOPE, i::SLOPPY },
1237     // Broken 2 byte encoding of \u00ff with missing last byte.
1238     { "  'foo\303';\n"
1239       "  (function fun", "(a,b) { infunction; }", ")();",
1240       i::FUNCTION_SCOPE, i::SLOPPY },
1241     // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1242     { "  'foo\301\277';\n"
1243       "  (function fun", "(a,b) { infunction; }", ")();",
1244       i::FUNCTION_SCOPE, i::SLOPPY },
1245     // Illegal 5 byte encoding.
1246     { "  'foo\370\277\277\277\277';\n"
1247       "  (function fun", "(a,b) { infunction; }", ")();",
1248       i::FUNCTION_SCOPE, i::SLOPPY },
1249     // Illegal 6 byte encoding.
1250     { "  'foo\374\277\277\277\277\277';\n"
1251       "  (function fun", "(a,b) { infunction; }", ")();",
1252       i::FUNCTION_SCOPE, i::SLOPPY },
1253     // Illegal 0xfe byte
1254     { "  'foo\376\277\277\277\277\277\277';\n"
1255       "  (function fun", "(a,b) { infunction; }", ")();",
1256       i::FUNCTION_SCOPE, i::SLOPPY },
1257     // Illegal 0xff byte
1258     { "  'foo\377\277\277\277\277\277\277\277';\n"
1259       "  (function fun", "(a,b) { infunction; }", ")();",
1260       i::FUNCTION_SCOPE, i::SLOPPY },
1261     { "  'foo';\n"
1262       "  (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
1263       i::FUNCTION_SCOPE, i::SLOPPY },
1264     { "  'foo';\n"
1265       "  (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
1266       i::FUNCTION_SCOPE, i::SLOPPY },
1267     { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
1268   };
1269
1270   i::Isolate* isolate = CcTest::i_isolate();
1271   i::Factory* factory = isolate->factory();
1272
1273   v8::HandleScope handles(CcTest::isolate());
1274   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1275   v8::Context::Scope context_scope(context);
1276
1277   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1278                                         128 * 1024);
1279
1280   for (int i = 0; source_data[i].outer_prefix; i++) {
1281     int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1282     int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1283     int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1284     int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1285     int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1286     int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1287     int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1288     int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1289     i::ScopedVector<char> program(kProgramByteSize + 1);
1290     i::SNPrintF(program, "%s%s%s",
1291                          source_data[i].outer_prefix,
1292                          source_data[i].inner_source,
1293                          source_data[i].outer_suffix);
1294
1295     // Parse program source.
1296     i::Handle<i::String> source = factory->NewStringFromUtf8(
1297         i::CStrVector(program.start())).ToHandleChecked();
1298     CHECK_EQ(source->length(), kProgramSize);
1299     i::Handle<i::Script> script = factory->NewScript(source);
1300     i::CompilationInfoWithZone info(script);
1301     i::Parser parser(&info, isolate->stack_guard()->real_climit(),
1302                      isolate->heap()->HashSeed(), isolate->unicode_cache());
1303     parser.set_allow_lazy(true);
1304     parser.set_allow_harmony_scoping(true);
1305     parser.set_allow_harmony_arrow_functions(true);
1306     info.MarkAsGlobal();
1307     info.SetLanguageMode(source_data[i].language_mode);
1308     parser.Parse(&info);
1309     CHECK(info.function() != NULL);
1310
1311     // Check scope types and positions.
1312     i::Scope* scope = info.function()->scope();
1313     CHECK(scope->is_script_scope());
1314     CHECK_EQ(scope->start_position(), 0);
1315     CHECK_EQ(scope->end_position(), kProgramSize);
1316     CHECK_EQ(scope->inner_scopes()->length(), 1);
1317
1318     i::Scope* inner_scope = scope->inner_scopes()->at(0);
1319     CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1320     CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1321     // The end position of a token is one position after the last
1322     // character belonging to that token.
1323     CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1324   }
1325 }
1326
1327
1328 const char* ReadString(unsigned* start) {
1329   int length = start[0];
1330   char* result = i::NewArray<char>(length + 1);
1331   for (int i = 0; i < length; i++) {
1332     result[i] = start[i + 1];
1333   }
1334   result[length] = '\0';
1335   return result;
1336 }
1337
1338
1339 i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
1340   i::Isolate* isolate = CcTest::i_isolate();
1341   i::Factory* factory = isolate->factory();
1342   const char* message =
1343       ReadString(&data[i::PreparseDataConstants::kMessageTextPos]);
1344   i::Handle<i::String> format = v8::Utils::OpenHandle(
1345       *v8::String::NewFromUtf8(CcTest::isolate(), message));
1346   int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
1347   const char* arg = NULL;
1348   i::Handle<i::JSArray> args_array;
1349   if (arg_count == 1) {
1350     // Position after text found by skipping past length field and
1351     // length field content words.
1352     int pos = i::PreparseDataConstants::kMessageTextPos + 1 +
1353               data[i::PreparseDataConstants::kMessageTextPos];
1354     arg = ReadString(&data[pos]);
1355     args_array = factory->NewJSArray(1);
1356     i::JSArray::SetElement(args_array, 0, v8::Utils::OpenHandle(*v8_str(arg)),
1357                            NONE, i::SLOPPY).Check();
1358   } else {
1359     CHECK_EQ(0, arg_count);
1360     args_array = factory->NewJSArray(0);
1361   }
1362
1363   i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
1364   i::Handle<i::Object> format_fun = i::Object::GetProperty(
1365       isolate, builtins, "FormatMessage").ToHandleChecked();
1366   i::Handle<i::Object> arg_handles[] = { format, args_array };
1367   i::Handle<i::Object> result = i::Execution::Call(
1368       isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
1369   CHECK(result->IsString());
1370   i::DeleteArray(message);
1371   i::DeleteArray(arg);
1372   data.Dispose();
1373   return i::Handle<i::String>::cast(result);
1374 }
1375
1376
1377 enum ParserFlag {
1378   kAllowLazy,
1379   kAllowNatives,
1380   kAllowHarmonyScoping,
1381   kAllowHarmonyModules,
1382   kAllowHarmonyNumericLiterals,
1383   kAllowHarmonyArrowFunctions,
1384   kAllowHarmonyClasses,
1385   kAllowHarmonyObjectLiterals,
1386   kAllowHarmonyRestParameters,
1387   kAllowHarmonyTemplates,
1388   kAllowHarmonySloppy,
1389   kAllowHarmonyUnicode,
1390   kAllowHarmonyComputedPropertyNames,
1391   kAllowStrongMode
1392 };
1393
1394
1395 enum ParserSyncTestResult {
1396   kSuccessOrError,
1397   kSuccess,
1398   kError
1399 };
1400
1401 template <typename Traits>
1402 void SetParserFlags(i::ParserBase<Traits>* parser,
1403                     i::EnumSet<ParserFlag> flags) {
1404   parser->set_allow_lazy(flags.Contains(kAllowLazy));
1405   parser->set_allow_natives(flags.Contains(kAllowNatives));
1406   parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
1407   parser->set_allow_harmony_modules(flags.Contains(kAllowHarmonyModules));
1408   parser->set_allow_harmony_numeric_literals(
1409       flags.Contains(kAllowHarmonyNumericLiterals));
1410   parser->set_allow_harmony_object_literals(
1411       flags.Contains(kAllowHarmonyObjectLiterals));
1412   parser->set_allow_harmony_arrow_functions(
1413       flags.Contains(kAllowHarmonyArrowFunctions));
1414   parser->set_allow_harmony_classes(flags.Contains(kAllowHarmonyClasses));
1415   parser->set_allow_harmony_templates(flags.Contains(kAllowHarmonyTemplates));
1416   parser->set_allow_harmony_rest_params(
1417       flags.Contains(kAllowHarmonyRestParameters));
1418   parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
1419   parser->set_allow_harmony_unicode(flags.Contains(kAllowHarmonyUnicode));
1420   parser->set_allow_harmony_computed_property_names(
1421       flags.Contains(kAllowHarmonyComputedPropertyNames));
1422   parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
1423 }
1424
1425
1426 void TestParserSyncWithFlags(i::Handle<i::String> source,
1427                              i::EnumSet<ParserFlag> flags,
1428                              ParserSyncTestResult result) {
1429   i::Isolate* isolate = CcTest::i_isolate();
1430   i::Factory* factory = isolate->factory();
1431
1432   uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1433   int preparser_materialized_literals = -1;
1434   int parser_materialized_literals = -2;
1435
1436   // Preparse the data.
1437   i::CompleteParserRecorder log;
1438   {
1439     i::Scanner scanner(isolate->unicode_cache());
1440     i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1441     i::Zone zone;
1442     i::AstValueFactory ast_value_factory(
1443         &zone, CcTest::i_isolate()->heap()->HashSeed());
1444     i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
1445                            stack_limit);
1446     SetParserFlags(&preparser, flags);
1447     scanner.Initialize(&stream);
1448     i::PreParser::PreParseResult result = preparser.PreParseProgram(
1449         &preparser_materialized_literals);
1450     CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1451   }
1452
1453   bool preparse_error = log.HasError();
1454
1455   // Parse the data
1456   i::FunctionLiteral* function;
1457   {
1458     i::Handle<i::Script> script = factory->NewScript(source);
1459     i::CompilationInfoWithZone info(script);
1460     i::Parser parser(&info, isolate->stack_guard()->real_climit(),
1461                      isolate->heap()->HashSeed(), isolate->unicode_cache());
1462     SetParserFlags(&parser, flags);
1463     info.MarkAsGlobal();
1464     parser.Parse(&info);
1465     function = info.function();
1466     if (function) {
1467       parser_materialized_literals = function->materialized_literal_count();
1468     }
1469   }
1470
1471   // Check that preparsing fails iff parsing fails.
1472   if (function == NULL) {
1473     // Extract exception from the parser.
1474     CHECK(isolate->has_pending_exception());
1475     i::Handle<i::JSObject> exception_handle(
1476         i::JSObject::cast(isolate->pending_exception()));
1477     i::Handle<i::String> message_string =
1478         i::Handle<i::String>::cast(i::Object::GetProperty(
1479             isolate, exception_handle, "message").ToHandleChecked());
1480
1481     if (result == kSuccess) {
1482       v8::base::OS::Print(
1483           "Parser failed on:\n"
1484           "\t%s\n"
1485           "with error:\n"
1486           "\t%s\n"
1487           "However, we expected no error.",
1488           source->ToCString().get(), message_string->ToCString().get());
1489       CHECK(false);
1490     }
1491
1492     if (!preparse_error) {
1493       v8::base::OS::Print(
1494           "Parser failed on:\n"
1495           "\t%s\n"
1496           "with error:\n"
1497           "\t%s\n"
1498           "However, the preparser succeeded",
1499           source->ToCString().get(), message_string->ToCString().get());
1500       CHECK(false);
1501     }
1502     // Check that preparser and parser produce the same error.
1503     i::Handle<i::String> preparser_message =
1504         FormatMessage(log.ErrorMessageData());
1505     if (!i::String::Equals(message_string, preparser_message)) {
1506       v8::base::OS::Print(
1507           "Expected parser and preparser to produce the same error on:\n"
1508           "\t%s\n"
1509           "However, found the following error messages\n"
1510           "\tparser:    %s\n"
1511           "\tpreparser: %s\n",
1512           source->ToCString().get(),
1513           message_string->ToCString().get(),
1514           preparser_message->ToCString().get());
1515       CHECK(false);
1516     }
1517   } else if (preparse_error) {
1518     v8::base::OS::Print(
1519         "Preparser failed on:\n"
1520         "\t%s\n"
1521         "with error:\n"
1522         "\t%s\n"
1523         "However, the parser succeeded",
1524         source->ToCString().get(),
1525         FormatMessage(log.ErrorMessageData())->ToCString().get());
1526     CHECK(false);
1527   } else if (result == kError) {
1528     v8::base::OS::Print(
1529         "Expected error on:\n"
1530         "\t%s\n"
1531         "However, parser and preparser succeeded",
1532         source->ToCString().get());
1533     CHECK(false);
1534   } else if (preparser_materialized_literals != parser_materialized_literals) {
1535     v8::base::OS::Print(
1536         "Preparser materialized literals (%d) differ from Parser materialized "
1537         "literals (%d) on:\n"
1538         "\t%s\n"
1539         "However, parser and preparser succeeded",
1540         preparser_materialized_literals, parser_materialized_literals,
1541         source->ToCString().get());
1542     CHECK(false);
1543   }
1544 }
1545
1546
1547 void TestParserSync(const char* source,
1548                     const ParserFlag* varying_flags,
1549                     size_t varying_flags_length,
1550                     ParserSyncTestResult result = kSuccessOrError,
1551                     const ParserFlag* always_true_flags = NULL,
1552                     size_t always_true_flags_length = 0,
1553                     const ParserFlag* always_false_flags = NULL,
1554                     size_t always_false_flags_length = 0) {
1555   i::Handle<i::String> str =
1556       CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1557   for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1558     i::EnumSet<ParserFlag> flags;
1559     for (size_t flag_index = 0; flag_index < varying_flags_length;
1560          ++flag_index) {
1561       if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1562     }
1563     for (size_t flag_index = 0; flag_index < always_true_flags_length;
1564          ++flag_index) {
1565       flags.Add(always_true_flags[flag_index]);
1566     }
1567     for (size_t flag_index = 0; flag_index < always_false_flags_length;
1568          ++flag_index) {
1569       flags.Remove(always_false_flags[flag_index]);
1570     }
1571     TestParserSyncWithFlags(str, flags, result);
1572   }
1573 }
1574
1575
1576 TEST(ParserSync) {
1577   const char* context_data[][2] = {
1578     { "", "" },
1579     { "{", "}" },
1580     { "if (true) ", " else {}" },
1581     { "if (true) {} else ", "" },
1582     { "if (true) ", "" },
1583     { "do ", " while (false)" },
1584     { "while (false) ", "" },
1585     { "for (;;) ", "" },
1586     { "with ({})", "" },
1587     { "switch (12) { case 12: ", "}" },
1588     { "switch (12) { default: ", "}" },
1589     { "switch (12) { ", "case 12: }" },
1590     { "label2: ", "" },
1591     { NULL, NULL }
1592   };
1593
1594   const char* statement_data[] = {
1595     "{}",
1596     "var x",
1597     "var x = 1",
1598     "const x",
1599     "const x = 1",
1600     ";",
1601     "12",
1602     "if (false) {} else ;",
1603     "if (false) {} else {}",
1604     "if (false) {} else 12",
1605     "if (false) ;",
1606     "if (false) {}",
1607     "if (false) 12",
1608     "do {} while (false)",
1609     "for (;;) ;",
1610     "for (;;) {}",
1611     "for (;;) 12",
1612     "continue",
1613     "continue label",
1614     "continue\nlabel",
1615     "break",
1616     "break label",
1617     "break\nlabel",
1618     // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1619     // "return",
1620     // "return  12",
1621     // "return\n12",
1622     "with ({}) ;",
1623     "with ({}) {}",
1624     "with ({}) 12",
1625     "switch ({}) { default: }",
1626     "label3: ",
1627     "throw",
1628     "throw  12",
1629     "throw\n12",
1630     "try {} catch(e) {}",
1631     "try {} finally {}",
1632     "try {} catch(e) {} finally {}",
1633     "debugger",
1634     NULL
1635   };
1636
1637   const char* termination_data[] = {
1638     "",
1639     ";",
1640     "\n",
1641     ";\n",
1642     "\n;",
1643     NULL
1644   };
1645
1646   v8::HandleScope handles(CcTest::isolate());
1647   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1648   v8::Context::Scope context_scope(context);
1649
1650   CcTest::i_isolate()->stack_guard()->SetStackLimit(
1651       i::GetCurrentStackPosition() - 128 * 1024);
1652
1653   for (int i = 0; context_data[i][0] != NULL; ++i) {
1654     for (int j = 0; statement_data[j] != NULL; ++j) {
1655       for (int k = 0; termination_data[k] != NULL; ++k) {
1656         int kPrefixLen = i::StrLength(context_data[i][0]);
1657         int kStatementLen = i::StrLength(statement_data[j]);
1658         int kTerminationLen = i::StrLength(termination_data[k]);
1659         int kSuffixLen = i::StrLength(context_data[i][1]);
1660         int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1661             + kSuffixLen + i::StrLength("label: for (;;) {  }");
1662
1663         // Plug the source code pieces together.
1664         i::ScopedVector<char> program(kProgramSize + 1);
1665         int length = i::SNPrintF(program,
1666             "label: for (;;) { %s%s%s%s }",
1667             context_data[i][0],
1668             statement_data[j],
1669             termination_data[k],
1670             context_data[i][1]);
1671         CHECK(length == kProgramSize);
1672         TestParserSync(program.start(), NULL, 0);
1673       }
1674     }
1675   }
1676
1677   // Neither Harmony numeric literals nor our natives syntax have any
1678   // interaction with the flags above, so test these separately to reduce
1679   // the combinatorial explosion.
1680   static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals };
1681   TestParserSync("0o1234", flags2, arraysize(flags2));
1682   TestParserSync("0b1011", flags2, arraysize(flags2));
1683
1684   static const ParserFlag flags3[] = { kAllowNatives };
1685   TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1686 }
1687
1688
1689 TEST(StrictOctal) {
1690   // Test that syntax error caused by octal literal is reported correctly as
1691   // such (issue 2220).
1692   v8::V8::Initialize();
1693   v8::HandleScope scope(CcTest::isolate());
1694   v8::Context::Scope context_scope(
1695       v8::Context::New(CcTest::isolate()));
1696   v8::TryCatch try_catch;
1697   const char* script =
1698       "\"use strict\";       \n"
1699       "a = function() {      \n"
1700       "  b = function() {    \n"
1701       "    01;               \n"
1702       "  };                  \n"
1703       "};                    \n";
1704   v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
1705   CHECK(try_catch.HasCaught());
1706   v8::String::Utf8Value exception(try_catch.Exception());
1707   CHECK_EQ(0,
1708            strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1709                   *exception));
1710 }
1711
1712
1713 void RunParserSyncTest(const char* context_data[][2],
1714                        const char* statement_data[],
1715                        ParserSyncTestResult result,
1716                        const ParserFlag* flags = NULL,
1717                        int flags_len = 0,
1718                        const ParserFlag* always_true_flags = NULL,
1719                        int always_true_len = 0,
1720                        const ParserFlag* always_false_flags = NULL,
1721                        int always_false_len = 0) {
1722   v8::HandleScope handles(CcTest::isolate());
1723   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1724   v8::Context::Scope context_scope(context);
1725
1726   CcTest::i_isolate()->stack_guard()->SetStackLimit(
1727       i::GetCurrentStackPosition() - 128 * 1024);
1728
1729   // Experimental feature flags should not go here; pass the flags as
1730   // always_true_flags if the test needs them.
1731   static const ParserFlag default_flags[] = {
1732     kAllowLazy,
1733     kAllowNatives,
1734   };
1735   ParserFlag* generated_flags = NULL;
1736   if (flags == NULL) {
1737     flags = default_flags;
1738     flags_len = arraysize(default_flags);
1739     if (always_true_flags != NULL || always_false_flags != NULL) {
1740       // Remove always_true/false_flags from default_flags (if present).
1741       CHECK((always_true_flags != NULL) == (always_true_len > 0));
1742       CHECK((always_false_flags != NULL) == (always_false_len > 0));
1743       generated_flags = new ParserFlag[flags_len + always_true_len];
1744       int flag_index = 0;
1745       for (int i = 0; i < flags_len; ++i) {
1746         bool use_flag = true;
1747         for (int j = 0; use_flag && j < always_true_len; ++j) {
1748           if (flags[i] == always_true_flags[j]) use_flag = false;
1749         }
1750         for (int j = 0; use_flag && j < always_false_len; ++j) {
1751           if (flags[i] == always_false_flags[j]) use_flag = false;
1752         }
1753         if (use_flag) generated_flags[flag_index++] = flags[i];
1754       }
1755       flags_len = flag_index;
1756       flags = generated_flags;
1757     }
1758   }
1759   for (int i = 0; context_data[i][0] != NULL; ++i) {
1760     for (int j = 0; statement_data[j] != NULL; ++j) {
1761       int kPrefixLen = i::StrLength(context_data[i][0]);
1762       int kStatementLen = i::StrLength(statement_data[j]);
1763       int kSuffixLen = i::StrLength(context_data[i][1]);
1764       int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1765
1766       // Plug the source code pieces together.
1767       i::ScopedVector<char> program(kProgramSize + 1);
1768       int length = i::SNPrintF(program,
1769                                "%s%s%s",
1770                                context_data[i][0],
1771                                statement_data[j],
1772                                context_data[i][1]);
1773       CHECK(length == kProgramSize);
1774       TestParserSync(program.start(),
1775                      flags,
1776                      flags_len,
1777                      result,
1778                      always_true_flags,
1779                      always_true_len,
1780                      always_false_flags,
1781                      always_false_len);
1782     }
1783   }
1784   delete[] generated_flags;
1785 }
1786
1787
1788 TEST(ErrorsEvalAndArguments) {
1789   // Tests that both preparsing and parsing produce the right kind of errors for
1790   // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1791   // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1792   // isn't.
1793   const char* context_data[][2] = {
1794       {"\"use strict\";", ""},
1795       {"\"use strong\";", ""},
1796       {"var eval; function test_func() {\"use strict\"; ", "}"},
1797       {"var eval; function test_func() {\"use strong\"; ", "}"},
1798       {NULL, NULL}};
1799
1800   const char* statement_data[] = {
1801     "var eval;",
1802     "var arguments",
1803     "var foo, eval;",
1804     "var foo, arguments;",
1805     "try { } catch (eval) { }",
1806     "try { } catch (arguments) { }",
1807     "function eval() { }",
1808     "function arguments() { }",
1809     "function foo(eval) { }",
1810     "function foo(arguments) { }",
1811     "function foo(bar, eval) { }",
1812     "function foo(bar, arguments) { }",
1813     "(eval) => { }",
1814     "(arguments) => { }",
1815     "(foo, eval) => { }",
1816     "(foo, arguments) => { }",
1817     "eval = 1;",
1818     "arguments = 1;",
1819     "var foo = eval = 1;",
1820     "var foo = arguments = 1;",
1821     "++eval;",
1822     "++arguments;",
1823     "eval++;",
1824     "arguments++;",
1825     NULL
1826   };
1827
1828   static const ParserFlag always_flags[] = {kAllowStrongMode};
1829   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1830                     arraysize(always_flags));
1831 }
1832
1833
1834 TEST(NoErrorsEvalAndArgumentsSloppy) {
1835   // Tests that both preparsing and parsing accept "eval" and "arguments" as
1836   // identifiers when needed.
1837   const char* context_data[][2] = {
1838     { "", "" },
1839     { "function test_func() {", "}"},
1840     { NULL, NULL }
1841   };
1842
1843   const char* statement_data[] = {
1844     "var eval;",
1845     "var arguments",
1846     "var foo, eval;",
1847     "var foo, arguments;",
1848     "try { } catch (eval) { }",
1849     "try { } catch (arguments) { }",
1850     "function eval() { }",
1851     "function arguments() { }",
1852     "function foo(eval) { }",
1853     "function foo(arguments) { }",
1854     "function foo(bar, eval) { }",
1855     "function foo(bar, arguments) { }",
1856     "eval = 1;",
1857     "arguments = 1;",
1858     "var foo = eval = 1;",
1859     "var foo = arguments = 1;",
1860     "++eval;",
1861     "++arguments;",
1862     "eval++;",
1863     "arguments++;",
1864     NULL
1865   };
1866
1867   RunParserSyncTest(context_data, statement_data, kSuccess);
1868 }
1869
1870
1871 TEST(NoErrorsEvalAndArgumentsStrict) {
1872   const char* context_data[][2] = {
1873     { "\"use strict\";", "" },
1874     { "function test_func() { \"use strict\";", "}" },
1875     { "() => { \"use strict\"; ", "}" },
1876     { NULL, NULL }
1877   };
1878
1879   const char* statement_data[] = {
1880     "eval;",
1881     "arguments;",
1882     "var foo = eval;",
1883     "var foo = arguments;",
1884     "var foo = { eval: 1 };",
1885     "var foo = { arguments: 1 };",
1886     "var foo = { }; foo.eval = {};",
1887     "var foo = { }; foo.arguments = {};",
1888     NULL
1889   };
1890
1891   static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
1892   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
1893                     always_flags, arraysize(always_flags));
1894 }
1895
1896
1897 #define FUTURE_STRICT_RESERVED_WORDS(V) \
1898   V(implements)                         \
1899   V(interface)                          \
1900   V(let)                                \
1901   V(package)                            \
1902   V(private)                            \
1903   V(protected)                          \
1904   V(public)                             \
1905   V(static)                             \
1906   V(yield)
1907
1908
1909 #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
1910   V(implements)                                 \
1911   V(let)                                        \
1912   V(static)                                     \
1913   V(yield)
1914
1915
1916 #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
1917   "var " #NAME ";",                             \
1918   "var foo, " #NAME ";",                        \
1919   "try { } catch (" #NAME ") { }",              \
1920   "function " #NAME "() { }",                   \
1921   "(function " #NAME "() { })",                 \
1922   "function foo(" #NAME ") { }",                \
1923   "function foo(bar, " #NAME ") { }",           \
1924   #NAME " = 1;",                                \
1925   #NAME " += 1;",                               \
1926   "var foo = " #NAME " = 1;",                   \
1927   "++" #NAME ";",                               \
1928   #NAME " ++;",
1929
1930
1931 TEST(ErrorsFutureStrictReservedWords) {
1932   // Tests that both preparsing and parsing produce the right kind of errors for
1933   // using future strict reserved words as identifiers. Without the strict mode,
1934   // it's ok to use future strict reserved words as identifiers. With the strict
1935   // mode, it isn't.
1936   const char* context_data[][2] = {
1937       {"function test_func() {\"use strict\"; ", "}"},
1938       {"() => { \"use strict\"; ", "}"},
1939       {"function test_func() {\"use strong\"; ", "}"},
1940       {"() => { \"use strong\"; ", "}"},
1941       {NULL, NULL}};
1942
1943   const char* statement_data[] {
1944     LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
1945     NULL
1946   };
1947
1948   static const ParserFlag always_flags[] = {kAllowStrongMode};
1949   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1950                     arraysize(always_flags));
1951   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1952                     arraysize(always_flags));
1953 }
1954
1955
1956 #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
1957
1958
1959 TEST(NoErrorsFutureStrictReservedWords) {
1960   const char* context_data[][2] = {
1961     { "", "" },
1962     { "function test_func() {", "}"},
1963     { "() => {", "}" },
1964     { NULL, NULL }
1965   };
1966
1967   const char* statement_data[] = {
1968     FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
1969     NULL
1970   };
1971
1972   static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
1973   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
1974                     always_flags, arraysize(always_flags));
1975
1976   static const ParserFlag classes_flags[] = {
1977       kAllowHarmonyArrowFunctions, kAllowHarmonyClasses, kAllowHarmonyScoping};
1978   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
1979                     classes_flags, arraysize(classes_flags));
1980 }
1981
1982
1983 TEST(ErrorsReservedWords) {
1984   // Tests that both preparsing and parsing produce the right kind of errors for
1985   // using future reserved words as identifiers. These tests don't depend on the
1986   // strict mode.
1987   const char* context_data[][2] = {
1988     { "", "" },
1989     { "\"use strict\";", "" },
1990     { "var eval; function test_func() {", "}"},
1991     { "var eval; function test_func() {\"use strict\"; ", "}"},
1992     { "var eval; () => {", "}"},
1993     { "var eval; () => {\"use strict\"; ", "}"},
1994     { NULL, NULL }
1995   };
1996
1997   const char* statement_data[] = {
1998     "var super;",
1999     "var foo, super;",
2000     "try { } catch (super) { }",
2001     "function super() { }",
2002     "function foo(super) { }",
2003     "function foo(bar, super) { }",
2004     "(super) => { }",
2005     "(bar, super) => { }",
2006     "super = 1;",
2007     "var foo = super = 1;",
2008     "++super;",
2009     "super++;",
2010     "function foo super",
2011     NULL
2012   };
2013
2014   RunParserSyncTest(context_data, statement_data, kError);
2015 }
2016
2017
2018 TEST(NoErrorsLetSloppyAllModes) {
2019   // In sloppy mode, it's okay to use "let" as identifier.
2020   const char* context_data[][2] = {
2021     { "", "" },
2022     { "function f() {", "}" },
2023     { "(function f() {", "})" },
2024     { NULL, NULL }
2025   };
2026
2027   const char* statement_data[] = {
2028     "var let;",
2029     "var foo, let;",
2030     "try { } catch (let) { }",
2031     "function let() { }",
2032     "(function let() { })",
2033     "function foo(let) { }",
2034     "function foo(bar, let) { }",
2035     "let = 1;",
2036     "var foo = let = 1;",
2037     "let * 2;",
2038     "++let;",
2039     "let++;",
2040     "let: 34",
2041     "function let(let) { let: let(let + let(0)); }",
2042     "({ let: 1 })",
2043     "({ get let() { 1 } })",
2044     "let(100)",
2045     NULL
2046   };
2047
2048   RunParserSyncTest(context_data, statement_data, kSuccess);
2049 }
2050
2051
2052 TEST(NoErrorsYieldSloppyAllModes) {
2053   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2054   // generator (see other test).
2055   const char* context_data[][2] = {
2056     { "", "" },
2057     { "function not_gen() {", "}" },
2058     { "(function not_gen() {", "})" },
2059     { NULL, NULL }
2060   };
2061
2062   const char* statement_data[] = {
2063     "var yield;",
2064     "var foo, yield;",
2065     "try { } catch (yield) { }",
2066     "function yield() { }",
2067     "(function yield() { })",
2068     "function foo(yield) { }",
2069     "function foo(bar, yield) { }",
2070     "yield = 1;",
2071     "var foo = yield = 1;",
2072     "yield * 2;",
2073     "++yield;",
2074     "yield++;",
2075     "yield: 34",
2076     "function yield(yield) { yield: yield (yield + yield(0)); }",
2077     "({ yield: 1 })",
2078     "({ get yield() { 1 } })",
2079     "yield(100)",
2080     "yield[100]",
2081     NULL
2082   };
2083
2084   RunParserSyncTest(context_data, statement_data, kSuccess);
2085 }
2086
2087
2088 TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2089   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2090   // generator (see next test).
2091   const char* context_data[][2] = {
2092     { "", "" },
2093     { "function not_gen() {", "}" },
2094     { "function * gen() { function not_gen() {", "} }" },
2095     { "(function not_gen() {", "})" },
2096     { "(function * gen() { (function not_gen() {", "}) })" },
2097     { NULL, NULL }
2098   };
2099
2100   const char* statement_data[] = {
2101     "var yield;",
2102     "var foo, yield;",
2103     "try { } catch (yield) { }",
2104     "function yield() { }",
2105     "(function yield() { })",
2106     "function foo(yield) { }",
2107     "function foo(bar, yield) { }",
2108     "function * yield() { }",
2109     "(function * yield() { })",
2110     "yield = 1;",
2111     "var foo = yield = 1;",
2112     "yield * 2;",
2113     "++yield;",
2114     "yield++;",
2115     "yield: 34",
2116     "function yield(yield) { yield: yield (yield + yield(0)); }",
2117     "({ yield: 1 })",
2118     "({ get yield() { 1 } })",
2119     "yield(100)",
2120     "yield[100]",
2121     NULL
2122   };
2123
2124   RunParserSyncTest(context_data, statement_data, kSuccess);
2125 }
2126
2127
2128 TEST(ErrorsYieldStrict) {
2129   const char* context_data[][2] = {
2130       {"\"use strict\";", ""},
2131       {"\"use strict\"; function not_gen() {", "}"},
2132       {"function test_func() {\"use strict\"; ", "}"},
2133       {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2134       {"\"use strict\"; (function not_gen() {", "})"},
2135       {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2136       {"() => {\"use strict\"; ", "}"},
2137       {"\"use strong\";", ""},
2138       {"\"use strong\"; function not_gen() {", "}"},
2139       {"function test_func() {\"use strong\"; ", "}"},
2140       {"\"use strong\"; function * gen() { function not_gen() {", "} }"},
2141       {"\"use strong\"; (function not_gen() {", "})"},
2142       {"\"use strong\"; (function * gen() { (function not_gen() {", "}) })"},
2143       {"() => {\"use strong\"; ", "}"},
2144       {NULL, NULL}};
2145
2146   const char* statement_data[] = {
2147     "var yield;",
2148     "var foo, yield;",
2149     "try { } catch (yield) { }",
2150     "function yield() { }",
2151     "(function yield() { })",
2152     "function foo(yield) { }",
2153     "function foo(bar, yield) { }",
2154     "function * yield() { }",
2155     "(function * yield() { })",
2156     "yield = 1;",
2157     "var foo = yield = 1;",
2158     "++yield;",
2159     "yield++;",
2160     "yield: 34;",
2161     NULL
2162   };
2163
2164   static const ParserFlag always_flags[] = {kAllowStrongMode};
2165   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2166                     arraysize(always_flags));
2167 }
2168
2169
2170 TEST(NoErrorsGenerator) {
2171   const char* context_data[][2] = {
2172     { "function * gen() {", "}" },
2173     { "(function * gen() {", "})" },
2174     { "(function * () {", "})" },
2175     { NULL, NULL }
2176   };
2177
2178   const char* statement_data[] = {
2179     // A generator without a body is valid.
2180     ""
2181     // Valid yield expressions inside generators.
2182     "yield 2;",
2183     "yield * 2;",
2184     "yield * \n 2;",
2185     "yield yield 1;",
2186     "yield * yield * 1;",
2187     "yield 3 + (yield 4);",
2188     "yield * 3 + (yield * 4);",
2189     "(yield * 3) + (yield * 4);",
2190     "yield 3; yield 4;",
2191     "yield * 3; yield * 4;",
2192     "(function (yield) { })",
2193     "yield { yield: 12 }",
2194     "yield /* comment */ { yield: 12 }",
2195     "yield * \n { yield: 12 }",
2196     "yield /* comment */ * \n { yield: 12 }",
2197     // You can return in a generator.
2198     "yield 1; return",
2199     "yield * 1; return",
2200     "yield 1; return 37",
2201     "yield * 1; return 37",
2202     "yield 1; return 37; yield 'dead';",
2203     "yield * 1; return 37; yield * 'dead';",
2204     // Yield is still a valid key in object literals.
2205     "({ yield: 1 })",
2206     "({ get yield() { } })",
2207     // Yield without RHS.
2208     "yield;",
2209     "yield",
2210     "yield\n",
2211     "yield /* comment */"
2212     "yield // comment\n"
2213     "(yield)",
2214     "[yield]",
2215     "{yield}",
2216     "yield, yield",
2217     "yield; yield",
2218     "(yield) ? yield : yield",
2219     "(yield) \n ? yield : yield",
2220     // If there is a newline before the next token, we don't look for RHS.
2221     "yield\nfor (;;) {}",
2222     NULL
2223   };
2224
2225   RunParserSyncTest(context_data, statement_data, kSuccess);
2226 }
2227
2228
2229 TEST(ErrorsYieldGenerator) {
2230   const char* context_data[][2] = {
2231     { "function * gen() {", "}" },
2232     { "\"use strict\"; function * gen() {", "}" },
2233     { NULL, NULL }
2234   };
2235
2236   const char* statement_data[] = {
2237     // Invalid yield expressions inside generators.
2238     "var yield;",
2239     "var foo, yield;",
2240     "try { } catch (yield) { }",
2241     "function yield() { }",
2242     // The name of the NFE is let-bound in the generator, which does not permit
2243     // yield to be an identifier.
2244     "(function yield() { })",
2245     "(function * yield() { })",
2246     // Yield isn't valid as a formal parameter for generators.
2247     "function * foo(yield) { }",
2248     "(function * foo(yield) { })",
2249     "yield = 1;",
2250     "var foo = yield = 1;",
2251     "++yield;",
2252     "yield++;",
2253     "yield *",
2254     "(yield *)",
2255     // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2256     // is invalid.
2257     "yield 3 + yield 4;",
2258     "yield: 34",
2259     "yield ? 1 : 2",
2260     // Parses as yield (/ yield): invalid.
2261     "yield / yield",
2262     "+ yield",
2263     "+ yield 3",
2264     // Invalid (no newline allowed between yield and *).
2265     "yield\n*3",
2266     // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2267     // object literal, and yield is not a valid label).
2268     "yield\n{yield: 42}",
2269     "yield /* comment */\n {yield: 42}",
2270     "yield //comment\n {yield: 42}",
2271     NULL
2272   };
2273
2274   RunParserSyncTest(context_data, statement_data, kError);
2275 }
2276
2277
2278 TEST(ErrorsNameOfStrictFunction) {
2279   // Tests that illegal tokens as names of a strict function produce the correct
2280   // errors.
2281   const char* context_data[][2] = {
2282     { "function ", ""},
2283     { "\"use strict\"; function", ""},
2284     { "\"use strong\"; function", ""},
2285     { "function * ", ""},
2286     { "\"use strict\"; function * ", ""},
2287     { "\"use strong\"; function * ", ""},
2288     { NULL, NULL }
2289   };
2290
2291   const char* statement_data[] = {
2292     "eval() {\"use strict\";}",
2293     "arguments() {\"use strict\";}",
2294     "interface() {\"use strict\";}",
2295     "yield() {\"use strict\";}",
2296     // Future reserved words are always illegal
2297     "super() { }",
2298     "super() {\"use strict\";}",
2299     NULL
2300   };
2301
2302   static const ParserFlag always_flags[] = {kAllowStrongMode};
2303   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2304                     arraysize(always_flags));
2305 }
2306
2307
2308 TEST(NoErrorsNameOfStrictFunction) {
2309   const char* context_data[][2] = {
2310     { "function ", ""},
2311     { NULL, NULL }
2312   };
2313
2314   const char* statement_data[] = {
2315     "eval() { }",
2316     "arguments() { }",
2317     "interface() { }",
2318     "yield() { }",
2319     NULL
2320   };
2321
2322   RunParserSyncTest(context_data, statement_data, kSuccess);
2323 }
2324
2325
2326 TEST(NoErrorsNameOfStrictGenerator) {
2327   const char* context_data[][2] = {
2328     { "function * ", ""},
2329     { NULL, NULL }
2330   };
2331
2332   const char* statement_data[] = {
2333     "eval() { }",
2334     "arguments() { }",
2335     "interface() { }",
2336     "yield() { }",
2337     NULL
2338   };
2339
2340   RunParserSyncTest(context_data, statement_data, kSuccess);
2341 }
2342
2343
2344 TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2345   // Using future reserved words as labels is always an error.
2346   const char* context_data[][2] = {
2347     { "", ""},
2348     { "function test_func() {", "}" },
2349     { "() => {", "}" },
2350     { NULL, NULL }
2351   };
2352
2353   const char* statement_data[] = {
2354     "super: while(true) { break super; }",
2355     NULL
2356   };
2357
2358   RunParserSyncTest(context_data, statement_data, kError);
2359 }
2360
2361
2362 TEST(ErrorsIllegalWordsAsLabelsStrict) {
2363   // Tests that illegal tokens as labels produce the correct errors.
2364   const char* context_data[][2] = {
2365       {"\"use strict\";", ""},
2366       {"function test_func() {\"use strict\"; ", "}"},
2367       {"() => {\"use strict\"; ", "}"},
2368       {"\"use strong\";", ""},
2369       {"function test_func() {\"use strong\"; ", "}"},
2370       {"() => {\"use strong\"; ", "}"},
2371       {NULL, NULL}};
2372
2373 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2374   const char* statement_data[] = {
2375     "super: while(true) { break super; }",
2376     FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2377     NULL
2378   };
2379 #undef LABELLED_WHILE
2380
2381   static const ParserFlag always_flags[] = {kAllowStrongMode};
2382   RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2383                     arraysize(always_flags));
2384 }
2385
2386
2387 TEST(NoErrorsIllegalWordsAsLabels) {
2388   // Using eval and arguments as labels is legal even in strict mode.
2389   const char* context_data[][2] = {
2390     { "", ""},
2391     { "function test_func() {", "}" },
2392     { "() => {", "}" },
2393     { "\"use strict\";", "" },
2394     { "\"use strict\"; function test_func() {", "}" },
2395     { "\"use strict\"; () => {", "}" },
2396     { NULL, NULL }
2397   };
2398
2399   const char* statement_data[] = {
2400     "mylabel: while(true) { break mylabel; }",
2401     "eval: while(true) { break eval; }",
2402     "arguments: while(true) { break arguments; }",
2403     NULL
2404   };
2405
2406   static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
2407   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2408                     always_flags, arraysize(always_flags));
2409 }
2410
2411
2412 TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2413   const char* context_data[][2] = {
2414     { "", ""},
2415     { "function test_func() {", "}" },
2416     { "() => {", "}" },
2417     { NULL, NULL }
2418   };
2419
2420 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2421   const char* statement_data[] {
2422     FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2423     NULL
2424   };
2425 #undef LABELLED_WHILE
2426
2427   static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
2428   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2429                     always_flags, arraysize(always_flags));
2430 }
2431
2432
2433 TEST(ErrorsParenthesizedLabels) {
2434   // Parenthesized identifiers shouldn't be recognized as labels.
2435   const char* context_data[][2] = {
2436     { "", ""},
2437     { "function test_func() {", "}" },
2438     { "() => {", "}" },
2439     { NULL, NULL }
2440   };
2441
2442   const char* statement_data[] = {
2443     "(mylabel): while(true) { break mylabel; }",
2444     NULL
2445   };
2446
2447   RunParserSyncTest(context_data, statement_data, kError);
2448 }
2449
2450
2451 TEST(NoErrorsParenthesizedDirectivePrologue) {
2452   // Parenthesized directive prologue shouldn't be recognized.
2453   const char* context_data[][2] = {
2454     { "", ""},
2455     { NULL, NULL }
2456   };
2457
2458   const char* statement_data[] = {
2459     "(\"use strict\"); var eval;",
2460     "(\"use strong\"); var eval;",
2461     NULL
2462   };
2463
2464   static const ParserFlag always_flags[] = {kAllowStrongMode};
2465   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2466                     always_flags, arraysize(always_flags));
2467 }
2468
2469
2470 TEST(ErrorsNotAnIdentifierName) {
2471   const char* context_data[][2] = {
2472     { "", ""},
2473     { "\"use strict\";", ""},
2474     { NULL, NULL }
2475   };
2476
2477   const char* statement_data[] = {
2478     "var foo = {}; foo.{;",
2479     "var foo = {}; foo.};",
2480     "var foo = {}; foo.=;",
2481     "var foo = {}; foo.888;",
2482     "var foo = {}; foo.-;",
2483     "var foo = {}; foo.--;",
2484     NULL
2485   };
2486
2487   RunParserSyncTest(context_data, statement_data, kError);
2488 }
2489
2490
2491 TEST(NoErrorsIdentifierNames) {
2492   // Keywords etc. are valid as property names.
2493   const char* context_data[][2] = {
2494     { "", ""},
2495     { "\"use strict\";", ""},
2496     { NULL, NULL }
2497   };
2498
2499   const char* statement_data[] = {
2500     "var foo = {}; foo.if;",
2501     "var foo = {}; foo.yield;",
2502     "var foo = {}; foo.super;",
2503     "var foo = {}; foo.interface;",
2504     "var foo = {}; foo.eval;",
2505     "var foo = {}; foo.arguments;",
2506     NULL
2507   };
2508
2509   RunParserSyncTest(context_data, statement_data, kSuccess);
2510 }
2511
2512
2513 TEST(DontRegressPreParserDataSizes) {
2514   // These tests make sure that Parser doesn't start producing less "preparse
2515   // data" (data which the embedder can cache).
2516   v8::V8::Initialize();
2517   v8::Isolate* isolate = CcTest::isolate();
2518   v8::HandleScope handles(isolate);
2519
2520   CcTest::i_isolate()->stack_guard()->SetStackLimit(
2521       i::GetCurrentStackPosition() - 128 * 1024);
2522
2523   struct TestCase {
2524     const char* program;
2525     int functions;
2526   } test_cases[] = {
2527     // No functions.
2528     {"var x = 42;", 0},
2529     // Functions.
2530     {"function foo() {}", 1},
2531     {"function foo() {} function bar() {}", 2},
2532     // Getter / setter functions are recorded as functions if they're on the top
2533     // level.
2534     {"var x = {get foo(){} };", 1},
2535     // Functions insize lazy functions are not recorded.
2536     {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2537     {"function lazy() { var x = {get foo(){} } }", 1},
2538     {NULL, 0}
2539   };
2540
2541   for (int i = 0; test_cases[i].program; i++) {
2542     const char* program = test_cases[i].program;
2543     i::Factory* factory = CcTest::i_isolate()->factory();
2544     i::Handle<i::String> source =
2545         factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2546     i::Handle<i::Script> script = factory->NewScript(source);
2547     i::CompilationInfoWithZone info(script);
2548     i::ScriptData* sd = NULL;
2549     info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
2550     i::Parser::ParseStatic(&info, true);
2551     i::ParseData* pd = i::ParseData::FromCachedData(sd);
2552
2553     if (pd->FunctionCount() != test_cases[i].functions) {
2554       v8::base::OS::Print(
2555           "Expected preparse data for program:\n"
2556           "\t%s\n"
2557           "to contain %d functions, however, received %d functions.\n",
2558           program, test_cases[i].functions, pd->FunctionCount());
2559       CHECK(false);
2560     }
2561     delete sd;
2562     delete pd;
2563   }
2564 }
2565
2566
2567 TEST(FunctionDeclaresItselfStrict) {
2568   // Tests that we produce the right kinds of errors when a function declares
2569   // itself strict (we cannot produce there errors as soon as we see the
2570   // offending identifiers, because we don't know at that point whether the
2571   // function is strict or not).
2572   const char* context_data[][2] = {
2573     {"function eval() {", "}"},
2574     {"function arguments() {", "}"},
2575     {"function yield() {", "}"},
2576     {"function interface() {", "}"},
2577     {"function foo(eval) {", "}"},
2578     {"function foo(arguments) {", "}"},
2579     {"function foo(yield) {", "}"},
2580     {"function foo(interface) {", "}"},
2581     {"function foo(bar, eval) {", "}"},
2582     {"function foo(bar, arguments) {", "}"},
2583     {"function foo(bar, yield) {", "}"},
2584     {"function foo(bar, interface) {", "}"},
2585     {"function foo(bar, bar) {", "}"},
2586     { NULL, NULL }
2587   };
2588
2589   const char* strict_statement_data[] = {
2590     "\"use strict\";",
2591     "\"use strong\";",
2592     NULL
2593   };
2594
2595   const char* non_strict_statement_data[] = {
2596     ";",
2597     NULL
2598   };
2599
2600   static const ParserFlag always_flags[] = {kAllowStrongMode};
2601   RunParserSyncTest(context_data, strict_statement_data, kError, NULL, 0,
2602                     always_flags, arraysize(always_flags));
2603   RunParserSyncTest(context_data, non_strict_statement_data, kSuccess, NULL, 0,
2604                     always_flags, arraysize(always_flags));
2605 }
2606
2607
2608 TEST(ErrorsTryWithoutCatchOrFinally) {
2609   const char* context_data[][2] = {
2610     {"", ""},
2611     { NULL, NULL }
2612   };
2613
2614   const char* statement_data[] = {
2615     "try { }",
2616     "try { } foo();",
2617     "try { } catch (e) foo();",
2618     "try { } catch { }",
2619     "try { } finally foo();",
2620     NULL
2621   };
2622
2623   RunParserSyncTest(context_data, statement_data, kError);
2624 }
2625
2626
2627 TEST(NoErrorsTryCatchFinally) {
2628   const char* context_data[][2] = {
2629     {"", ""},
2630     { NULL, NULL }
2631   };
2632
2633   const char* statement_data[] = {
2634     "try { } catch (e) { }",
2635     "try { } catch (e) { } finally { }",
2636     "try { } finally { }",
2637     NULL
2638   };
2639
2640   RunParserSyncTest(context_data, statement_data, kSuccess);
2641 }
2642
2643
2644 TEST(ErrorsRegexpLiteral) {
2645   const char* context_data[][2] = {
2646     {"var r = ", ""},
2647     { NULL, NULL }
2648   };
2649
2650   const char* statement_data[] = {
2651     "/unterminated",
2652     NULL
2653   };
2654
2655   RunParserSyncTest(context_data, statement_data, kError);
2656 }
2657
2658
2659 TEST(NoErrorsRegexpLiteral) {
2660   const char* context_data[][2] = {
2661     {"var r = ", ""},
2662     { NULL, NULL }
2663   };
2664
2665   const char* statement_data[] = {
2666     "/foo/",
2667     "/foo/g",
2668     "/foo/whatever",  // This is an error but not detected by the parser.
2669     NULL
2670   };
2671
2672   RunParserSyncTest(context_data, statement_data, kSuccess);
2673 }
2674
2675
2676 TEST(Intrinsics) {
2677   const char* context_data[][2] = {
2678     {"", ""},
2679     { NULL, NULL }
2680   };
2681
2682   const char* statement_data[] = {
2683     "%someintrinsic(arg)",
2684     NULL
2685   };
2686
2687   // This test requires kAllowNatives to succeed.
2688   static const ParserFlag always_true_flags[] = {
2689     kAllowNatives
2690   };
2691
2692   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2693                     always_true_flags, 1);
2694 }
2695
2696
2697 TEST(NoErrorsNewExpression) {
2698   const char* context_data[][2] = {
2699     {"", ""},
2700     {"var f =", ""},
2701     { NULL, NULL }
2702   };
2703
2704   const char* statement_data[] = {
2705     "new foo",
2706     "new foo();",
2707     "new foo(1);",
2708     "new foo(1, 2);",
2709     // The first () will be processed as a part of the NewExpression and the
2710     // second () will be processed as part of LeftHandSideExpression.
2711     "new foo()();",
2712     // The first () will be processed as a part of the inner NewExpression and
2713     // the second () will be processed as a part of the outer NewExpression.
2714     "new new foo()();",
2715     "new foo.bar;",
2716     "new foo.bar();",
2717     "new foo.bar.baz;",
2718     "new foo.bar().baz;",
2719     "new foo[bar];",
2720     "new foo[bar]();",
2721     "new foo[bar][baz];",
2722     "new foo[bar]()[baz];",
2723     "new foo[bar].baz(baz)()[bar].baz;",
2724     "new \"foo\"",  // Runtime error
2725     "new 1",  // Runtime error
2726     // This even runs:
2727     "(new new Function(\"this.x = 1\")).x;",
2728     "new new Test_Two(String, 2).v(0123).length;",
2729     NULL
2730   };
2731
2732   RunParserSyncTest(context_data, statement_data, kSuccess);
2733 }
2734
2735
2736 TEST(ErrorsNewExpression) {
2737   const char* context_data[][2] = {
2738     {"", ""},
2739     {"var f =", ""},
2740     { NULL, NULL }
2741   };
2742
2743   const char* statement_data[] = {
2744     "new foo bar",
2745     "new ) foo",
2746     "new ++foo",
2747     "new foo ++",
2748     NULL
2749   };
2750
2751   RunParserSyncTest(context_data, statement_data, kError);
2752 }
2753
2754
2755 TEST(StrictObjectLiteralChecking) {
2756   const char* context_data[][2] = {
2757     {"\"use strict\"; var myobject = {", "};"},
2758     {"\"use strict\"; var myobject = {", ",};"},
2759     {"var myobject = {", "};"},
2760     {"var myobject = {", ",};"},
2761     { NULL, NULL }
2762   };
2763
2764   // These are only errors in strict mode.
2765   const char* statement_data[] = {
2766     "foo: 1, foo: 2",
2767     "\"foo\": 1, \"foo\": 2",
2768     "foo: 1, \"foo\": 2",
2769     "1: 1, 1: 2",
2770     "1: 1, \"1\": 2",
2771     "get: 1, get: 2",  // Not a getter for real, just a property called get.
2772     "set: 1, set: 2",  // Not a setter for real, just a property called set.
2773     NULL
2774   };
2775
2776   RunParserSyncTest(context_data, statement_data, kSuccess);
2777 }
2778
2779
2780 TEST(ErrorsObjectLiteralChecking) {
2781   const char* context_data[][2] = {
2782     {"\"use strict\"; var myobject = {", "};"},
2783     {"var myobject = {", "};"},
2784     { NULL, NULL }
2785   };
2786
2787   const char* statement_data[] = {
2788     ",",
2789     // Wrong number of parameters
2790     "get bar(x) {}",
2791     "get bar(x, y) {}",
2792     "set bar() {}",
2793     "set bar(x, y) {}",
2794     // Parsing FunctionLiteral for getter or setter fails
2795     "get foo( +",
2796     "get foo() \"error\"",
2797     NULL
2798   };
2799
2800   RunParserSyncTest(context_data, statement_data, kError);
2801 }
2802
2803
2804 TEST(NoErrorsObjectLiteralChecking) {
2805   const char* context_data[][2] = {
2806     {"var myobject = {", "};"},
2807     {"var myobject = {", ",};"},
2808     {"\"use strict\"; var myobject = {", "};"},
2809     {"\"use strict\"; var myobject = {", ",};"},
2810     { NULL, NULL }
2811   };
2812
2813   const char* statement_data[] = {
2814     "foo: 1, get foo() {}",
2815     "foo: 1, set foo(v) {}",
2816     "\"foo\": 1, get \"foo\"() {}",
2817     "\"foo\": 1, set \"foo\"(v) {}",
2818     "1: 1, get 1() {}",
2819     "1: 1, set 1(v) {}",
2820     "get foo() {}, get foo() {}",
2821     "set foo(_) {}, set foo(v) {}",
2822     "foo: 1, get \"foo\"() {}",
2823     "foo: 1, set \"foo\"(v) {}",
2824     "\"foo\": 1, get foo() {}",
2825     "\"foo\": 1, set foo(v) {}",
2826     "1: 1, get \"1\"() {}",
2827     "1: 1, set \"1\"(v) {}",
2828     "\"1\": 1, get 1() {}",
2829     "\"1\": 1, set 1(v) {}",
2830     "foo: 1, bar: 2",
2831     "\"foo\": 1, \"bar\": 2",
2832     "1: 1, 2: 2",
2833     // Syntax: IdentifierName ':' AssignmentExpression
2834     "foo: bar = 5 + baz",
2835     // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2836     "get foo() {}",
2837     "get \"foo\"() {}",
2838     "get 1() {}",
2839     // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2840     //     '{' FunctionBody '}'
2841     "set foo(v) {}",
2842     "set \"foo\"(v) {}",
2843     "set 1(v) {}",
2844     // Non-colliding getters and setters -> no errors
2845     "foo: 1, get bar() {}",
2846     "foo: 1, set bar(v) {}",
2847     "\"foo\": 1, get \"bar\"() {}",
2848     "\"foo\": 1, set \"bar\"(v) {}",
2849     "1: 1, get 2() {}",
2850     "1: 1, set 2(v) {}",
2851     "get: 1, get foo() {}",
2852     "set: 1, set foo(_) {}",
2853     // Keywords, future reserved and strict future reserved are also allowed as
2854     // property names.
2855     "if: 4",
2856     "interface: 5",
2857     "super: 6",
2858     "eval: 7",
2859     "arguments: 8",
2860     NULL
2861   };
2862
2863   RunParserSyncTest(context_data, statement_data, kSuccess);
2864 }
2865
2866
2867 TEST(TooManyArguments) {
2868   const char* context_data[][2] = {
2869     {"foo(", "0)"},
2870     { NULL, NULL }
2871   };
2872
2873   using v8::internal::Code;
2874   char statement[Code::kMaxArguments * 2 + 1];
2875   for (int i = 0; i < Code::kMaxArguments; ++i) {
2876     statement[2 * i] = '0';
2877     statement[2 * i + 1] = ',';
2878   }
2879   statement[Code::kMaxArguments * 2] = 0;
2880
2881   const char* statement_data[] = {
2882     statement,
2883     NULL
2884   };
2885
2886   // The test is quite slow, so run it with a reduced set of flags.
2887   static const ParserFlag empty_flags[] = {kAllowLazy};
2888   RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2889 }
2890
2891
2892 TEST(StrictDelete) {
2893   // "delete <Identifier>" is not allowed in strict mode.
2894   const char* strong_context_data[][2] = {
2895     {"\"use strong\"; ", ""},
2896     { NULL, NULL }
2897   };
2898
2899   const char* strict_context_data[][2] = {
2900     {"\"use strict\"; ", ""},
2901     { NULL, NULL }
2902   };
2903
2904   const char* sloppy_context_data[][2] = {
2905     {"", ""},
2906     { NULL, NULL }
2907   };
2908
2909   // These are errors in the strict mode.
2910   const char* sloppy_statement_data[] = {
2911     "delete foo;",
2912     "delete foo + 1;",
2913     "delete (foo);",
2914     "delete eval;",
2915     "delete interface;",
2916     NULL
2917   };
2918
2919   // These are always OK
2920   const char* good_statement_data[] = {
2921     "delete this;",
2922     "delete 1;",
2923     "delete 1 + 2;",
2924     "delete foo();",
2925     "delete foo.bar;",
2926     "delete foo[bar];",
2927     "delete foo--;",
2928     "delete --foo;",
2929     "delete new foo();",
2930     "delete new foo(bar);",
2931     NULL
2932   };
2933
2934   // These are always errors
2935   const char* bad_statement_data[] = {
2936     "delete if;",
2937     NULL
2938   };
2939
2940   static const ParserFlag always_flags[] = {kAllowStrongMode};
2941   RunParserSyncTest(strong_context_data, sloppy_statement_data, kError, NULL, 0,
2942                     always_flags, arraysize(always_flags));
2943   RunParserSyncTest(strict_context_data, sloppy_statement_data, kError, NULL, 0,
2944                     always_flags, arraysize(always_flags));
2945   RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess, NULL,
2946                     0, always_flags, arraysize(always_flags));
2947
2948   RunParserSyncTest(strong_context_data, good_statement_data, kError, NULL, 0,
2949                     always_flags, arraysize(always_flags));
2950   RunParserSyncTest(strict_context_data, good_statement_data, kSuccess, NULL, 0,
2951                     always_flags, arraysize(always_flags));
2952   RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess, NULL, 0,
2953                     always_flags, arraysize(always_flags));
2954
2955   RunParserSyncTest(strong_context_data, bad_statement_data, kError, NULL, 0,
2956                     always_flags, arraysize(always_flags));
2957   RunParserSyncTest(strict_context_data, bad_statement_data, kError, NULL, 0,
2958                     always_flags, arraysize(always_flags));
2959   RunParserSyncTest(sloppy_context_data, bad_statement_data, kError, NULL, 0,
2960                     always_flags, arraysize(always_flags));
2961 }
2962
2963
2964 TEST(InvalidLeftHandSide) {
2965   const char* assignment_context_data[][2] = {
2966     {"", " = 1;"},
2967     {"\"use strict\"; ", " = 1;"},
2968     { NULL, NULL }
2969   };
2970
2971   const char* prefix_context_data[][2] = {
2972     {"++", ";"},
2973     {"\"use strict\"; ++", ";"},
2974     {NULL, NULL},
2975   };
2976
2977   const char* postfix_context_data[][2] = {
2978     {"", "++;"},
2979     {"\"use strict\"; ", "++;"},
2980     { NULL, NULL }
2981   };
2982
2983   // Good left hand sides for assigment or prefix / postfix operations.
2984   const char* good_statement_data[] = {
2985     "foo",
2986     "foo.bar",
2987     "foo[bar]",
2988     "foo()[bar]",
2989     "foo().bar",
2990     "this.foo",
2991     "this[foo]",
2992     "new foo()[bar]",
2993     "new foo().bar",
2994     "foo()",
2995     "foo(bar)",
2996     "foo[bar]()",
2997     "foo.bar()",
2998     "this()",
2999     "this.foo()",
3000     "this[foo].bar()",
3001     "this.foo[foo].bar(this)(bar)[foo]()",
3002     NULL
3003   };
3004
3005   // Bad left hand sides for assigment or prefix / postfix operations.
3006   const char* bad_statement_data_common[] = {
3007     "2",
3008     "new foo",
3009     "new foo()",
3010     "null",
3011     "if",  // Unexpected token
3012     "{x: 1}",  // Unexpected token
3013     "this",
3014     "\"bar\"",
3015     "(foo + bar)",
3016     "new new foo()[bar]",  // means: new (new foo()[bar])
3017     "new new foo().bar",  // means: new (new foo()[bar])
3018     NULL
3019   };
3020
3021   // These are not okay for assignment, but okay for prefix / postix.
3022   const char* bad_statement_data_for_assignment[] = {
3023     "++foo",
3024     "foo++",
3025     "foo + bar",
3026     NULL
3027   };
3028
3029   RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3030   RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3031   RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3032                     kError);
3033
3034   RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3035   RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3036
3037   RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3038   RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3039 }
3040
3041
3042 TEST(FuncNameInferrerBasic) {
3043   // Tests that function names are inferred properly.
3044   i::FLAG_allow_natives_syntax = true;
3045   v8::Isolate* isolate = CcTest::isolate();
3046   v8::HandleScope scope(isolate);
3047   LocalContext env;
3048   CompileRun("var foo1 = function() {}; "
3049              "var foo2 = function foo3() {}; "
3050              "function not_ctor() { "
3051              "  var foo4 = function() {}; "
3052              "  return %FunctionGetInferredName(foo4); "
3053              "} "
3054              "function Ctor() { "
3055              "  var foo5 = function() {}; "
3056              "  return %FunctionGetInferredName(foo5); "
3057              "} "
3058              "var obj1 = { foo6: function() {} }; "
3059              "var obj2 = { 'foo7': function() {} }; "
3060              "var obj3 = {}; "
3061              "obj3[1] = function() {}; "
3062              "var obj4 = {}; "
3063              "obj4[1] = function foo8() {}; "
3064              "var obj5 = {}; "
3065              "obj5['foo9'] = function() {}; "
3066              "var obj6 = { obj7 : { foo10: function() {} } };");
3067   ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3068   // foo2 is not unnamed -> its name is not inferred.
3069   ExpectString("%FunctionGetInferredName(foo2)", "");
3070   ExpectString("not_ctor()", "foo4");
3071   ExpectString("Ctor()", "Ctor.foo5");
3072   ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3073   ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3074   ExpectString("%FunctionGetInferredName(obj3[1])",
3075                "obj3.(anonymous function)");
3076   ExpectString("%FunctionGetInferredName(obj4[1])", "");
3077   ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3078   ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3079 }
3080
3081
3082 TEST(FuncNameInferrerTwoByte) {
3083   // Tests function name inferring in cases where some parts of the inferred
3084   // function name are two-byte strings.
3085   i::FLAG_allow_natives_syntax = true;
3086   v8::Isolate* isolate = CcTest::isolate();
3087   v8::HandleScope scope(isolate);
3088   LocalContext env;
3089   uint16_t* two_byte_source = AsciiToTwoByteString(
3090       "var obj1 = { oXj2 : { foo1: function() {} } }; "
3091       "%FunctionGetInferredName(obj1.oXj2.foo1)");
3092   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3093   // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3094   two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3095   v8::Local<v8::String> source =
3096       v8::String::NewFromTwoByte(isolate, two_byte_source);
3097   v8::Local<v8::Value> result = CompileRun(source);
3098   CHECK(result->IsString());
3099   v8::Local<v8::String> expected_name =
3100       v8::String::NewFromTwoByte(isolate, two_byte_name);
3101   CHECK(result->Equals(expected_name));
3102   i::DeleteArray(two_byte_source);
3103   i::DeleteArray(two_byte_name);
3104 }
3105
3106
3107 TEST(FuncNameInferrerEscaped) {
3108   // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3109   // character as a unicode escape.
3110   i::FLAG_allow_natives_syntax = true;
3111   v8::Isolate* isolate = CcTest::isolate();
3112   v8::HandleScope scope(isolate);
3113   LocalContext env;
3114   uint16_t* two_byte_source = AsciiToTwoByteString(
3115       "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3116       "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3117   uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3118   // Fix to correspond to the non-ASCII name in two_byte_source.
3119   two_byte_name[6] = 0x010d;
3120   v8::Local<v8::String> source =
3121       v8::String::NewFromTwoByte(isolate, two_byte_source);
3122   v8::Local<v8::Value> result = CompileRun(source);
3123   CHECK(result->IsString());
3124   v8::Local<v8::String> expected_name =
3125       v8::String::NewFromTwoByte(isolate, two_byte_name);
3126   CHECK(result->Equals(expected_name));
3127   i::DeleteArray(two_byte_source);
3128   i::DeleteArray(two_byte_name);
3129 }
3130
3131
3132 TEST(RegressionLazyFunctionWithErrorWithArg) {
3133   // The bug occurred when a lazy function had an error which requires a
3134   // parameter (such as "unknown label" here). The error message was processed
3135   // before the AstValueFactory containing the error message string was
3136   // internalized.
3137   v8::Isolate* isolate = CcTest::isolate();
3138   v8::HandleScope scope(isolate);
3139   LocalContext env;
3140   i::FLAG_lazy = true;
3141   i::FLAG_min_preparse_length = 0;
3142   CompileRun("function this_is_lazy() {\n"
3143              "  break p;\n"
3144              "}\n"
3145              "this_is_lazy();\n");
3146 }
3147
3148
3149 TEST(SerializationOfMaybeAssignmentFlag) {
3150   i::Isolate* isolate = CcTest::i_isolate();
3151   i::Factory* factory = isolate->factory();
3152   i::HandleScope scope(isolate);
3153   LocalContext env;
3154
3155   const char* src =
3156       "function h() {"
3157       "  var result = [];"
3158       "  function f() {"
3159       "    result.push(2);"
3160       "  }"
3161       "  function assertResult(r) {"
3162       "    f();"
3163       "    result = [];"
3164       "  }"
3165       "  assertResult([2]);"
3166       "  assertResult([2]);"
3167       "  return f;"
3168       "};"
3169       "h();";
3170
3171   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3172   i::SNPrintF(program, "%s", src);
3173   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3174   source->PrintOn(stdout);
3175   printf("\n");
3176   i::Zone zone;
3177   v8::Local<v8::Value> v = CompileRun(src);
3178   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3179   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3180   i::Context* context = f->context();
3181   i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3182   avf.Internalize(isolate);
3183   const i::AstRawString* name = avf.GetOneByteString("result");
3184   i::Handle<i::String> str = name->string();
3185   CHECK(str->IsInternalizedString());
3186   i::Scope* script_scope =
3187       new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
3188   script_scope->Initialize();
3189   i::Scope* s =
3190       i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3191   DCHECK(s != script_scope);
3192   DCHECK(name != NULL);
3193
3194   // Get result from h's function context (that is f's context)
3195   i::Variable* var = s->Lookup(name);
3196
3197   CHECK(var != NULL);
3198   // Maybe assigned should survive deserialization
3199   CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3200   // TODO(sigurds) Figure out if is_used should survive context serialization.
3201 }
3202
3203
3204 TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3205   i::Isolate* isolate = CcTest::i_isolate();
3206   i::Factory* factory = isolate->factory();
3207   i::HandleScope scope(isolate);
3208   LocalContext env;
3209
3210
3211   const char* src =
3212       "function f(x) {"
3213       "    var a = arguments;"
3214       "    function g(i) {"
3215       "      ++a[0];"
3216       "    };"
3217       "    return g;"
3218       "  }"
3219       "f(0);";
3220
3221   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3222   i::SNPrintF(program, "%s", src);
3223   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3224   source->PrintOn(stdout);
3225   printf("\n");
3226   i::Zone zone;
3227   v8::Local<v8::Value> v = CompileRun(src);
3228   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3229   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3230   i::Context* context = f->context();
3231   i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3232   avf.Internalize(isolate);
3233
3234   i::Scope* script_scope =
3235       new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
3236   script_scope->Initialize();
3237   i::Scope* s =
3238       i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3239   DCHECK(s != script_scope);
3240   const i::AstRawString* name_x = avf.GetOneByteString("x");
3241
3242   // Get result from f's function context (that is g's outer context)
3243   i::Variable* var_x = s->Lookup(name_x);
3244   CHECK(var_x != NULL);
3245   CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3246 }
3247
3248
3249 TEST(ExportsMaybeAssigned) {
3250   i::FLAG_use_strict = true;
3251   i::FLAG_harmony_scoping = true;
3252   i::FLAG_harmony_modules = true;
3253
3254   i::Isolate* isolate = CcTest::i_isolate();
3255   i::Factory* factory = isolate->factory();
3256   i::HandleScope scope(isolate);
3257   LocalContext env;
3258
3259   const char* src =
3260       "module A {"
3261       "  export var x = 1;"
3262       "  export function f() { return x };"
3263       "  export const y = 2;"
3264       "  module B {}"
3265       "  export module C {}"
3266       "};"
3267       "A.f";
3268
3269   i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3270   i::SNPrintF(program, "%s", src);
3271   i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3272   source->PrintOn(stdout);
3273   printf("\n");
3274   i::Zone zone;
3275   v8::Local<v8::Value> v = CompileRun(src);
3276   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3277   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3278   i::Context* context = f->context();
3279   i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3280   avf.Internalize(isolate);
3281
3282   i::Scope* script_scope =
3283       new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
3284   script_scope->Initialize();
3285   i::Scope* s =
3286       i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3287   DCHECK(s != script_scope);
3288   const i::AstRawString* name_x = avf.GetOneByteString("x");
3289   const i::AstRawString* name_f = avf.GetOneByteString("f");
3290   const i::AstRawString* name_y = avf.GetOneByteString("y");
3291   const i::AstRawString* name_B = avf.GetOneByteString("B");
3292   const i::AstRawString* name_C = avf.GetOneByteString("C");
3293
3294   // Get result from h's function context (that is f's context)
3295   i::Variable* var_x = s->Lookup(name_x);
3296   CHECK(var_x != NULL);
3297   CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3298   i::Variable* var_f = s->Lookup(name_f);
3299   CHECK(var_f != NULL);
3300   CHECK(var_f->maybe_assigned() == i::kMaybeAssigned);
3301   i::Variable* var_y = s->Lookup(name_y);
3302   CHECK(var_y != NULL);
3303   CHECK(var_y->maybe_assigned() == i::kNotAssigned);
3304   i::Variable* var_B = s->Lookup(name_B);
3305   CHECK(var_B != NULL);
3306   CHECK(var_B->maybe_assigned() == i::kNotAssigned);
3307   i::Variable* var_C = s->Lookup(name_C);
3308   CHECK(var_C != NULL);
3309   CHECK(var_C->maybe_assigned() == i::kNotAssigned);
3310 }
3311
3312
3313 TEST(InnerAssignment) {
3314   i::Isolate* isolate = CcTest::i_isolate();
3315   i::Factory* factory = isolate->factory();
3316   i::HandleScope scope(isolate);
3317   LocalContext env;
3318
3319   const char* prefix = "function f() {";
3320   const char* midfix = " function g() {";
3321   const char* suffix = "}}";
3322   struct { const char* source; bool assigned; bool strict; } outers[] = {
3323     // Actual assignments.
3324     { "var x; var x = 5;", true, false },
3325     { "var x; { var x = 5; }", true, false },
3326     { "'use strict'; let x; x = 6;", true, true },
3327     { "var x = 5; function x() {}", true, false },
3328     // Actual non-assignments.
3329     { "var x;", false, false },
3330     { "var x = 5;", false, false },
3331     { "'use strict'; let x;", false, true },
3332     { "'use strict'; let x = 6;", false, true },
3333     { "'use strict'; var x = 0; { let x = 6; }", false, true },
3334     { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3335     { "'use strict'; let x = 0; { let x = 6; }", false, true },
3336     { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3337     { "var x; try {} catch (x) { x = 5; }", false, false },
3338     { "function x() {}", false, false },
3339     // Eval approximation.
3340     { "var x; eval('');", true, false },
3341     { "eval(''); var x;", true, false },
3342     { "'use strict'; let x; eval('');", true, true },
3343     { "'use strict'; eval(''); let x;", true, true },
3344     // Non-assignments not recognized, because the analysis is approximative.
3345     { "var x; var x;", true, false },
3346     { "var x = 5; var x;", true, false },
3347     { "var x; { var x; }", true, false },
3348     { "var x; function x() {}", true, false },
3349     { "function x() {}; var x;", true, false },
3350     { "var x; try {} catch (x) { var x = 5; }", true, false },
3351   };
3352   struct { const char* source; bool assigned; bool with; } inners[] = {
3353     // Actual assignments.
3354     { "x = 1;", true, false },
3355     { "x++;", true, false },
3356     { "++x;", true, false },
3357     { "x--;", true, false },
3358     { "--x;", true, false },
3359     { "{ x = 1; }", true, false },
3360     { "'use strict'; { let x; }; x = 0;", true, false },
3361     { "'use strict'; { const x = 1; }; x = 0;", true, false },
3362     { "'use strict'; { function x() {} }; x = 0;", true, false },
3363     { "with ({}) { x = 1; }", true, true },
3364     { "eval('');", true, false },
3365     { "'use strict'; { let y; eval('') }", true, false },
3366     { "function h() { x = 0; }", true, false },
3367     { "(function() { x = 0; })", true, false },
3368     { "(function() { x = 0; })", true, false },
3369     { "with ({}) (function() { x = 0; })", true, true },
3370     // Actual non-assignments.
3371     { "", false, false },
3372     { "x;", false, false },
3373     { "var x;", false, false },
3374     { "var x = 8;", false, false },
3375     { "var x; x = 8;", false, false },
3376     { "'use strict'; let x;", false, false },
3377     { "'use strict'; let x = 8;", false, false },
3378     { "'use strict'; let x; x = 8;", false, false },
3379     { "'use strict'; const x = 8;", false, false },
3380     { "function x() {}", false, false },
3381     { "function x() { x = 0; }", false, false },
3382     { "function h(x) { x = 0; }", false, false },
3383     { "'use strict'; { let x; x = 0; }", false, false },
3384     { "{ var x; }; x = 0;", false, false },
3385     { "with ({}) {}", false, true },
3386     { "var x; { with ({}) { x = 1; } }", false, true },
3387     { "try {} catch(x) { x = 0; }", false, false },
3388     { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3389     // Eval approximation.
3390     { "eval('');", true, false },
3391     { "function h() { eval(''); }", true, false },
3392     { "(function() { eval(''); })", true, false },
3393     // Shadowing not recognized because of eval approximation.
3394     { "var x; eval('');", true, false },
3395     { "'use strict'; let x; eval('');", true, false },
3396     { "try {} catch(x) { eval(''); }", true, false },
3397     { "function x() { eval(''); }", true, false },
3398     { "(function(x) { eval(''); })", true, false },
3399   };
3400
3401   // Used to trigger lazy compilation of function
3402   int comment_len = 2048;
3403   i::ScopedVector<char> comment(comment_len + 1);
3404   i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3405   int prefix_len = Utf8LengthHelper(prefix);
3406   int midfix_len = Utf8LengthHelper(midfix);
3407   int suffix_len = Utf8LengthHelper(suffix);
3408   for (unsigned i = 0; i < arraysize(outers); ++i) {
3409     const char* outer = outers[i].source;
3410     int outer_len = Utf8LengthHelper(outer);
3411     for (unsigned j = 0; j < arraysize(inners); ++j) {
3412       for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3413         for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3414           if (outers[i].strict && inners[j].with) continue;
3415           const char* inner = inners[j].source;
3416           int inner_len = Utf8LengthHelper(inner);
3417
3418           int outer_comment_len = outer_lazy ? comment_len : 0;
3419           int inner_comment_len = inner_lazy ? comment_len : 0;
3420           const char* outer_comment = outer_lazy ? comment.start() : "";
3421           const char* inner_comment = inner_lazy ? comment.start() : "";
3422           int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3423                     inner_comment_len + inner_len + suffix_len;
3424           i::ScopedVector<char> program(len + 1);
3425
3426           i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3427                       midfix, inner_comment, inner, suffix);
3428           i::Handle<i::String> source =
3429               factory->InternalizeUtf8String(program.start());
3430           source->PrintOn(stdout);
3431           printf("\n");
3432
3433           i::Handle<i::Script> script = factory->NewScript(source);
3434           i::CompilationInfoWithZone info(script);
3435           i::Parser parser(&info, isolate->stack_guard()->real_climit(),
3436                            isolate->heap()->HashSeed(),
3437                            isolate->unicode_cache());
3438           parser.set_allow_harmony_scoping(true);
3439           CHECK(parser.Parse(&info));
3440           CHECK(i::Compiler::Analyze(&info));
3441           CHECK(info.function() != NULL);
3442
3443           i::Scope* scope = info.function()->scope();
3444           CHECK_EQ(scope->inner_scopes()->length(), 1);
3445           i::Scope* inner_scope = scope->inner_scopes()->at(0);
3446           const i::AstRawString* var_name =
3447               info.ast_value_factory()->GetOneByteString("x");
3448           i::Variable* var = inner_scope->Lookup(var_name);
3449           bool expected = outers[i].assigned || inners[j].assigned;
3450           CHECK(var != NULL);
3451           CHECK(var->is_used() || !expected);
3452           CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3453         }
3454       }
3455     }
3456   }
3457 }
3458
3459 namespace {
3460
3461 int* global_use_counts = NULL;
3462
3463 void MockUseCounterCallback(v8::Isolate* isolate,
3464                             v8::Isolate::UseCounterFeature feature) {
3465   ++global_use_counts[feature];
3466 }
3467
3468 }
3469
3470
3471 TEST(UseAsmUseCount) {
3472   i::Isolate* isolate = CcTest::i_isolate();
3473   i::HandleScope scope(isolate);
3474   LocalContext env;
3475   int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3476   global_use_counts = use_counts;
3477   CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3478   CompileRun("\"use asm\";\n"
3479              "var foo = 1;\n"
3480              "\"use asm\";\n"  // Only the first one counts.
3481              "function bar() { \"use asm\"; var baz = 1; }");
3482   CHECK_EQ(2, use_counts[v8::Isolate::kUseAsm]);
3483 }
3484
3485
3486 TEST(ErrorsArrowFunctions) {
3487   // Tests that parser and preparser generate the same kind of errors
3488   // on invalid arrow function syntax.
3489   const char* context_data[][2] = {
3490     {"", ";"},
3491     {"v = ", ";"},
3492     {"bar ? (", ") : baz;"},
3493     {"bar ? baz : (", ");"},
3494     {"bar[", "];"},
3495     {"bar, ", ";"},
3496     {"", ", bar;"},
3497     {NULL, NULL}
3498   };
3499
3500   const char* statement_data[] = {
3501     "=> 0",
3502     "=>",
3503     "() =>",
3504     "=> {}",
3505     ") => {}",
3506     ", => {}",
3507     "(,) => {}",
3508     "return => {}",
3509     "() => {'value': 42}",
3510
3511     // Check that the early return introduced in ParsePrimaryExpression
3512     // does not accept stray closing parentheses.
3513     ")",
3514     ") => 0",
3515     "foo[()]",
3516     "()",
3517
3518     // Parameter lists with extra parens should be recognized as errors.
3519     "(()) => 0",
3520     "((x)) => 0",
3521     "((x, y)) => 0",
3522     "(x, (y)) => 0",
3523     "((x, y, z)) => 0",
3524     "(x, (y, z)) => 0",
3525     "((x, y), z) => 0",
3526
3527     // Parameter lists are always validated as strict, so those are errors.
3528     "eval => {}",
3529     "arguments => {}",
3530     "yield => {}",
3531     "interface => {}",
3532     "(eval) => {}",
3533     "(arguments) => {}",
3534     "(yield) => {}",
3535     "(interface) => {}",
3536     "(eval, bar) => {}",
3537     "(bar, eval) => {}",
3538     "(bar, arguments) => {}",
3539     "(bar, yield) => {}",
3540     "(bar, interface) => {}",
3541     // TODO(aperez): Detecting duplicates does not work in PreParser.
3542     // "(bar, bar) => {}",
3543
3544     // The parameter list is parsed as an expression, but only
3545     // a comma-separated list of identifier is valid.
3546     "32 => {}",
3547     "(32) => {}",
3548     "(a, 32) => {}",
3549     "if => {}",
3550     "(if) => {}",
3551     "(a, if) => {}",
3552     "a + b => {}",
3553     "(a + b) => {}",
3554     "(a + b, c) => {}",
3555     "(a, b - c) => {}",
3556     "\"a\" => {}",
3557     "(\"a\") => {}",
3558     "(\"a\", b) => {}",
3559     "(a, \"b\") => {}",
3560     "-a => {}",
3561     "(-a) => {}",
3562     "(-a, b) => {}",
3563     "(a, -b) => {}",
3564     "{} => {}",
3565     "({}) => {}",
3566     "(a, {}) => {}",
3567     "({}, a) => {}",
3568     "a++ => {}",
3569     "(a++) => {}",
3570     "(a++, b) => {}",
3571     "(a, b++) => {}",
3572     "[] => {}",
3573     "([]) => {}",
3574     "(a, []) => {}",
3575     "([], a) => {}",
3576     "(a = b) => {}",
3577     "(a = b, c) => {}",
3578     "(a, b = c) => {}",
3579     "(foo ? bar : baz) => {}",
3580     "(a, foo ? bar : baz) => {}",
3581     "(foo ? bar : baz, a) => {}",
3582     NULL
3583   };
3584
3585   // The test is quite slow, so run it with a reduced set of flags.
3586   static const ParserFlag flags[] = {kAllowLazy, kAllowHarmonyScoping};
3587   static const ParserFlag always_flags[] = { kAllowHarmonyArrowFunctions };
3588   RunParserSyncTest(context_data, statement_data, kError, flags,
3589                     arraysize(flags), always_flags, arraysize(always_flags));
3590 }
3591
3592
3593 TEST(NoErrorsArrowFunctions) {
3594   // Tests that parser and preparser accept valid arrow functions syntax.
3595   const char* context_data[][2] = {
3596     {"", ";"},
3597     {"bar ? (", ") : baz;"},
3598     {"bar ? baz : (", ");"},
3599     {"bar, ", ";"},
3600     {"", ", bar;"},
3601     {NULL, NULL}
3602   };
3603
3604   const char* statement_data[] = {
3605     "() => {}",
3606     "() => { return 42 }",
3607     "x => { return x; }",
3608     "(x) => { return x; }",
3609     "(x, y) => { return x + y; }",
3610     "(x, y, z) => { return x + y + z; }",
3611     "(x, y) => { x.a = y; }",
3612     "() => 42",
3613     "x => x",
3614     "x => x * x",
3615     "(x) => x",
3616     "(x) => x * x",
3617     "(x, y) => x + y",
3618     "(x, y, z) => x, y, z",
3619     "(x, y) => x.a = y",
3620     "() => ({'value': 42})",
3621     "x => y => x + y",
3622     "(x, y) => (u, v) => x*u + y*v",
3623     "(x, y) => z => z * (x + y)",
3624     "x => (y, z) => z * (x + y)",
3625
3626     // Those are comma-separated expressions, with arrow functions as items.
3627     // They stress the code for validating arrow function parameter lists.
3628     "a, b => 0",
3629     "a, b, (c, d) => 0",
3630     "(a, b, (c, d) => 0)",
3631     "(a, b) => 0, (c, d) => 1",
3632     "(a, b => {}, a => a + 1)",
3633     "((a, b) => {}, (a => a + 1))",
3634     "(a, (a, (b, c) => 0))",
3635
3636     // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3637     "foo ? bar : baz => {}",
3638     NULL
3639   };
3640
3641   static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions};
3642   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3643                     always_flags, arraysize(always_flags));
3644 }
3645
3646
3647 TEST(SuperNoErrors) {
3648   // Tests that parser and preparser accept 'super' keyword in right places.
3649   const char* context_data[][2] = {
3650     {"class C { m() { ", "; } }"},
3651     {"class C { m() { k = ", "; } }"},
3652     {"class C { m() { foo(", "); } }"},
3653     {"class C { m() { () => ", "; } }"},
3654     {NULL, NULL}
3655   };
3656
3657   const char* statement_data[] = {
3658     "super.x",
3659     "super[27]",
3660     "new super.x",
3661     "new super.x()",
3662     "new super[27]",
3663     "new super[27]()",
3664     "z.super",  // Ok, property lookup.
3665     NULL
3666   };
3667
3668   static const ParserFlag always_flags[] = {
3669     kAllowHarmonyArrowFunctions,
3670     kAllowHarmonyClasses,
3671     kAllowHarmonyObjectLiterals,
3672     kAllowHarmonySloppy
3673   };
3674   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3675                     always_flags, arraysize(always_flags));
3676 }
3677
3678
3679 TEST(SuperErrors) {
3680   const char* context_data[][2] = {
3681     {"class C { m() { ", "; } }"},
3682     {"class C { m() { k = ", "; } }"},
3683     {"class C { m() { foo(", "); } }"},
3684     {"class C { m() { () => ", "; } }"},
3685     {NULL, NULL}
3686   };
3687
3688   const char* expression_data[] = {
3689     "super",
3690     "super = x",
3691     "y = super",
3692     "f(super)",
3693     "new super",
3694     "new super()",
3695     "new super(12, 45)",
3696     "new new super",
3697     "new new super()",
3698     "new new super()()",
3699     NULL
3700   };
3701
3702   static const ParserFlag always_flags[] = {
3703     kAllowHarmonyClasses,
3704     kAllowHarmonyObjectLiterals,
3705     kAllowHarmonySloppy
3706   };
3707   RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
3708                     always_flags, arraysize(always_flags));
3709 }
3710
3711
3712 TEST(SuperCall) {
3713   const char* context_data[][2] = {{"", ""},
3714                                    {NULL, NULL}};
3715
3716   const char* success_data[] = {
3717     "class C extends B { constructor() { super(); } }",
3718     "class C extends B { constructor() { () => super(); } }",
3719     NULL
3720   };
3721
3722   static const ParserFlag always_flags[] = {
3723     kAllowHarmonyArrowFunctions,
3724     kAllowHarmonyClasses,
3725     kAllowHarmonyObjectLiterals,
3726     kAllowHarmonySloppy
3727   };
3728   RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
3729                     always_flags, arraysize(always_flags));
3730
3731   const char* error_data[] = {
3732     "class C { constructor() { super(); } }",
3733     "class C { method() { super(); } }",
3734     "class C { method() { () => super(); } }",
3735     "class C { *method() { super(); } }",
3736     "class C { get x() { super(); } }",
3737     "class C { set x(_) { super(); } }",
3738     "({ method() { super(); } })",
3739     "({ *method() { super(); } })",
3740     "({ get x() { super(); } })",
3741     "({ set x(_) { super(); } })",
3742     "({ f: function() { super(); } })",
3743     "(function() { super(); })",
3744     "var f = function() { super(); }",
3745     "({ f: function*() { super(); } })",
3746     "(function*() { super(); })",
3747     "var f = function*() { super(); }",
3748     NULL
3749   };
3750
3751   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
3752                     always_flags, arraysize(always_flags));
3753 }
3754
3755
3756 TEST(SuperNewNoErrors) {
3757   const char* context_data[][2] = {
3758     {"class C { constructor() { ", " } }"},
3759     {"class C { *method() { ", " } }"},
3760     {"class C { get x() { ", " } }"},
3761     {"class C { set x(_) { ", " } }"},
3762     {"({ method() { ", " } })"},
3763     {"({ *method() { ", " } })"},
3764     {"({ get x() { ", " } })"},
3765     {"({ set x(_) { ", " } })"},
3766     {NULL, NULL}
3767   };
3768
3769   const char* expression_data[] = {
3770     "new super.x;",
3771     "new super.x();",
3772     "() => new super.x;",
3773     "() => new super.x();",
3774     NULL
3775   };
3776
3777   static const ParserFlag always_flags[] = {
3778     kAllowHarmonyArrowFunctions,
3779     kAllowHarmonyClasses,
3780     kAllowHarmonyObjectLiterals,
3781     kAllowHarmonySloppy
3782   };
3783   RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
3784                     always_flags, arraysize(always_flags));
3785 }
3786
3787
3788 TEST(SuperNewErrors) {
3789   const char* context_data[][2] = {
3790     {"class C { method() { ", " } }"},
3791     {"class C { *method() { ", " } }"},
3792     {"class C { get x() { ", " } }"},
3793     {"class C { set x(_) { ", " } }"},
3794     {"({ method() { ", " } })"},
3795     {"({ *method() { ", " } })"},
3796     {"({ get x() { ", " } })"},
3797     {"({ set x(_) { ", " } })"},
3798     {"({ f: function() { ", " } })"},
3799     {"(function() { ", " })"},
3800     {"var f = function() { ", " }"},
3801     {"({ f: function*() { ", " } })"},
3802     {"(function*() { ", " })"},
3803     {"var f = function*() { ", " }"},
3804     {NULL, NULL}
3805   };
3806
3807   const char* statement_data[] = {
3808     "new super;",
3809     "new super();",
3810     "() => new super;",
3811     "() => new super();",
3812     NULL
3813   };
3814
3815   static const ParserFlag always_flags[] = {
3816     kAllowHarmonyArrowFunctions,
3817     kAllowHarmonyClasses,
3818     kAllowHarmonyObjectLiterals,
3819     kAllowHarmonySloppy
3820   };
3821   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
3822                     always_flags, arraysize(always_flags));
3823 }
3824
3825
3826 TEST(SuperErrorsNonMethods) {
3827   // super is only allowed in methods, accessors and constructors.
3828   const char* context_data[][2] = {
3829     {"", ";"},
3830     {"k = ", ";"},
3831     {"foo(", ");"},
3832     {"if (", ") {}"},
3833     {"if (true) {", "}"},
3834     {"if (false) {} else {", "}"},
3835     {"while (true) {", "}"},
3836     {"function f() {", "}"},
3837     {"class C extends (", ") {}"},
3838     {"class C { m() { function f() {", "} } }"},
3839     {"({ m() { function f() {", "} } })"},
3840     {NULL, NULL}
3841   };
3842
3843   const char* statement_data[] = {
3844     "super",
3845     "super = x",
3846     "y = super",
3847     "f(super)",
3848     "super.x",
3849     "super[27]",
3850     "super.x()",
3851     "super[27]()",
3852     "super()",
3853     "new super.x",
3854     "new super.x()",
3855     "new super[27]",
3856     "new super[27]()",
3857     NULL
3858   };
3859
3860   static const ParserFlag always_flags[] = {
3861     kAllowHarmonyClasses,
3862     kAllowHarmonyObjectLiterals,
3863     kAllowHarmonySloppy
3864   };
3865   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
3866                     always_flags, arraysize(always_flags));
3867 }
3868
3869
3870 TEST(NoErrorsMethodDefinition) {
3871   const char* context_data[][2] = {{"({", "});"},
3872                                    {"'use strict'; ({", "});"},
3873                                    {"({*", "});"},
3874                                    {"'use strict'; ({*", "});"},
3875                                    {NULL, NULL}};
3876
3877   const char* object_literal_body_data[] = {
3878     "m() {}",
3879     "m(x) { return x; }",
3880     "m(x, y) {}, n() {}",
3881     "set(x, y) {}",
3882     "get(x, y) {}",
3883     NULL
3884   };
3885
3886   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3887   RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0,
3888                     always_flags, arraysize(always_flags));
3889 }
3890
3891
3892 TEST(MethodDefinitionNames) {
3893   const char* context_data[][2] = {{"({", "(x, y) {}});"},
3894                                    {"'use strict'; ({", "(x, y) {}});"},
3895                                    {"({*", "(x, y) {}});"},
3896                                    {"'use strict'; ({*", "(x, y) {}});"},
3897                                    {NULL, NULL}};
3898
3899   const char* name_data[] = {
3900     "m",
3901     "'m'",
3902     "\"m\"",
3903     "\"m n\"",
3904     "true",
3905     "false",
3906     "null",
3907     "0",
3908     "1.2",
3909     "1e1",
3910     "1E1",
3911     "1e+1",
3912     "1e-1",
3913
3914     // Keywords
3915     "async",
3916     "await",
3917     "break",
3918     "case",
3919     "catch",
3920     "class",
3921     "const",
3922     "continue",
3923     "debugger",
3924     "default",
3925     "delete",
3926     "do",
3927     "else",
3928     "enum",
3929     "export",
3930     "extends",
3931     "finally",
3932     "for",
3933     "function",
3934     "if",
3935     "implements",
3936     "import",
3937     "in",
3938     "instanceof",
3939     "interface",
3940     "let",
3941     "new",
3942     "package",
3943     "private",
3944     "protected",
3945     "public",
3946     "return",
3947     "static",
3948     "super",
3949     "switch",
3950     "this",
3951     "throw",
3952     "try",
3953     "typeof",
3954     "var",
3955     "void",
3956     "while",
3957     "with",
3958     "yield",
3959     NULL
3960   };
3961
3962   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3963   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
3964                     always_flags, arraysize(always_flags));
3965 }
3966
3967
3968 TEST(MethodDefinitionStrictFormalParamereters) {
3969   const char* context_data[][2] = {{"({method(", "){}});"},
3970                                    {"'use strict'; ({method(", "){}});"},
3971                                    {"({*method(", "){}});"},
3972                                    {"'use strict'; ({*method(", "){}});"},
3973                                    {NULL, NULL}};
3974
3975   const char* params_data[] = {
3976     "x, x",
3977     "x, y, x",
3978     "var",
3979     "const",
3980     NULL
3981   };
3982
3983   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3984   RunParserSyncTest(context_data, params_data, kError, NULL, 0,
3985                     always_flags, arraysize(always_flags));
3986 }
3987
3988
3989 TEST(MethodDefinitionEvalArguments) {
3990   const char* strict_context_data[][2] =
3991       {{"'use strict'; ({method(", "){}});"},
3992        {"'use strict'; ({*method(", "){}});"},
3993        {NULL, NULL}};
3994   const char* sloppy_context_data[][2] =
3995       {{"({method(", "){}});"},
3996        {"({*method(", "){}});"},
3997        {NULL, NULL}};
3998
3999   const char* data[] = {
4000       "eval",
4001       "arguments",
4002       NULL};
4003
4004   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4005
4006   // Fail in strict mode
4007   RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
4008                     arraysize(always_flags));
4009
4010   // OK in sloppy mode
4011   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
4012                     arraysize(always_flags));
4013 }
4014
4015
4016 TEST(MethodDefinitionDuplicateEvalArguments) {
4017   const char* context_data[][2] =
4018       {{"'use strict'; ({method(", "){}});"},
4019        {"'use strict'; ({*method(", "){}});"},
4020        {"({method(", "){}});"},
4021        {"({*method(", "){}});"},
4022        {NULL, NULL}};
4023
4024   const char* data[] = {
4025       "eval, eval",
4026       "eval, a, eval",
4027       "arguments, arguments",
4028       "arguments, a, arguments",
4029       NULL};
4030
4031   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4032
4033   // In strict mode, the error is using "eval" or "arguments" as parameter names
4034   // In sloppy mode, the error is that eval / arguments are duplicated
4035   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4036                     arraysize(always_flags));
4037 }
4038
4039
4040 TEST(MethodDefinitionDuplicateProperty) {
4041   const char* context_data[][2] = {{"'use strict'; ({", "});"},
4042                                    {NULL, NULL}};
4043
4044   const char* params_data[] = {
4045     "x: 1, x() {}",
4046     "x() {}, x: 1",
4047     "x() {}, get x() {}",
4048     "x() {}, set x(_) {}",
4049     "x() {}, x() {}",
4050     "x() {}, y() {}, x() {}",
4051     "x() {}, \"x\"() {}",
4052     "x() {}, 'x'() {}",
4053     "0() {}, '0'() {}",
4054     "1.0() {}, 1: 1",
4055
4056     "x: 1, *x() {}",
4057     "*x() {}, x: 1",
4058     "*x() {}, get x() {}",
4059     "*x() {}, set x(_) {}",
4060     "*x() {}, *x() {}",
4061     "*x() {}, y() {}, *x() {}",
4062     "*x() {}, *\"x\"() {}",
4063     "*x() {}, *'x'() {}",
4064     "*0() {}, *'0'() {}",
4065     "*1.0() {}, 1: 1",
4066
4067     NULL
4068   };
4069
4070   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4071   RunParserSyncTest(context_data, params_data, kSuccess, NULL, 0,
4072                     always_flags, arraysize(always_flags));
4073 }
4074
4075
4076 TEST(ClassExpressionNoErrors) {
4077   const char* context_data[][2] = {{"(", ");"},
4078                                    {"var C = ", ";"},
4079                                    {"bar, ", ";"},
4080                                    {NULL, NULL}};
4081   const char* class_data[] = {
4082     "class {}",
4083     "class name {}",
4084     "class extends F {}",
4085     "class name extends F {}",
4086     "class extends (F, G) {}",
4087     "class name extends (F, G) {}",
4088     "class extends class {} {}",
4089     "class name extends class {} {}",
4090     "class extends class base {} {}",
4091     "class name extends class base {} {}",
4092     NULL};
4093
4094   static const ParserFlag always_flags[] = {
4095       kAllowHarmonyClasses, kAllowHarmonySloppy};
4096   RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
4097                     always_flags, arraysize(always_flags));
4098 }
4099
4100
4101 TEST(ClassDeclarationNoErrors) {
4102   const char* context_data[][2] = {{"'use strict'; ", ""},
4103                                    {"'use strict'; {", "}"},
4104                                    {"'use strict'; if (true) {", "}"},
4105                                    {NULL, NULL}};
4106   const char* statement_data[] = {
4107     "class name {}",
4108     "class name extends F {}",
4109     "class name extends (F, G) {}",
4110     "class name extends class {} {}",
4111     "class name extends class base {} {}",
4112     NULL};
4113
4114   static const ParserFlag always_flags[] = {
4115       kAllowHarmonyClasses, kAllowHarmonyScoping};
4116   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
4117                     always_flags, arraysize(always_flags));
4118 }
4119
4120
4121 TEST(ClassBodyNoErrors) {
4122   // Tests that parser and preparser accept valid class syntax.
4123   const char* context_data[][2] = {{"(class {", "});"},
4124                                    {"(class extends Base {", "});"},
4125                                    {"class C {", "}"},
4126                                    {"class C extends Base {", "}"},
4127                                    {NULL, NULL}};
4128   const char* class_body_data[] = {
4129     ";",
4130     ";;",
4131     "m() {}",
4132     "m() {};",
4133     "; m() {}",
4134     "m() {}; n(x) {}",
4135     "get x() {}",
4136     "set x(v) {}",
4137     "get() {}",
4138     "set() {}",
4139     "*g() {}",
4140     "*g() {};",
4141     "; *g() {}",
4142     "*g() {}; *h(x) {}",
4143     "static() {}",
4144     "static m() {}",
4145     "static get x() {}",
4146     "static set x(v) {}",
4147     "static get() {}",
4148     "static set() {}",
4149     "static static() {}",
4150     "static get static() {}",
4151     "static set static(v) {}",
4152     "*static() {}",
4153     "*get() {}",
4154     "*set() {}",
4155     "static *g() {}",
4156     NULL};
4157
4158   static const ParserFlag always_flags[] = {
4159     kAllowHarmonyClasses,
4160     kAllowHarmonyObjectLiterals,
4161     kAllowHarmonySloppy
4162   };
4163   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4164                     always_flags, arraysize(always_flags));
4165 }
4166
4167
4168 TEST(ClassPropertyNameNoErrors) {
4169   const char* context_data[][2] = {{"(class {", "() {}});"},
4170                                    {"(class { get ", "() {}});"},
4171                                    {"(class { set ", "(v) {}});"},
4172                                    {"(class { static ", "() {}});"},
4173                                    {"(class { static get ", "() {}});"},
4174                                    {"(class { static set ", "(v) {}});"},
4175                                    {"(class { *", "() {}});"},
4176                                    {"(class { static *", "() {}});"},
4177                                    {"class C {", "() {}}"},
4178                                    {"class C { get ", "() {}}"},
4179                                    {"class C { set ", "(v) {}}"},
4180                                    {"class C { static ", "() {}}"},
4181                                    {"class C { static get ", "() {}}"},
4182                                    {"class C { static set ", "(v) {}}"},
4183                                    {"class C { *", "() {}}"},
4184                                    {"class C { static *", "() {}}"},
4185                                    {NULL, NULL}};
4186   const char* name_data[] = {
4187     "42",
4188     "42.5",
4189     "42e2",
4190     "42e+2",
4191     "42e-2",
4192     "null",
4193     "false",
4194     "true",
4195     "'str'",
4196     "\"str\"",
4197     "static",
4198     "get",
4199     "set",
4200     "var",
4201     "const",
4202     "let",
4203     "this",
4204     "class",
4205     "function",
4206     "yield",
4207     "if",
4208     "else",
4209     "for",
4210     "while",
4211     "do",
4212     "try",
4213     "catch",
4214     "finally",
4215     NULL};
4216
4217   static const ParserFlag always_flags[] = {
4218     kAllowHarmonyClasses,
4219     kAllowHarmonyObjectLiterals,
4220     kAllowHarmonySloppy
4221   };
4222   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
4223                     always_flags, arraysize(always_flags));
4224 }
4225
4226
4227 TEST(ClassExpressionErrors) {
4228   const char* context_data[][2] = {{"(", ");"},
4229                                    {"var C = ", ";"},
4230                                    {"bar, ", ";"},
4231                                    {NULL, NULL}};
4232   const char* class_data[] = {
4233     "class",
4234     "class name",
4235     "class name extends",
4236     "class extends",
4237     "class {",
4238     "class { m }",
4239     "class { m; n }",
4240     "class { m: 1 }",
4241     "class { m(); n() }",
4242     "class { get m }",
4243     "class { get m() }",
4244     "class { get m() { }",
4245     "class { set m() {} }",  // Missing required parameter.
4246     "class { m() {}, n() {} }",  // No commas allowed.
4247     NULL};
4248
4249   static const ParserFlag always_flags[] = {
4250     kAllowHarmonyClasses,
4251     kAllowHarmonyObjectLiterals,
4252     kAllowHarmonySloppy
4253   };
4254   RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4255                     always_flags, arraysize(always_flags));
4256 }
4257
4258
4259 TEST(ClassDeclarationErrors) {
4260   const char* context_data[][2] = {{"", ""},
4261                                    {"{", "}"},
4262                                    {"if (true) {", "}"},
4263                                    {NULL, NULL}};
4264   const char* class_data[] = {
4265     "class",
4266     "class name",
4267     "class name extends",
4268     "class extends",
4269     "class name {",
4270     "class name { m }",
4271     "class name { m; n }",
4272     "class name { m: 1 }",
4273     "class name { m(); n() }",
4274     "class name { get x }",
4275     "class name { get x() }",
4276     "class name { set x() {) }",  // missing required param
4277     "class {}",  // Name is required for declaration
4278     "class extends base {}",
4279     "class name { *",
4280     "class name { * }",
4281     "class name { *; }",
4282     "class name { *get x() {} }",
4283     "class name { *set x(_) {} }",
4284     "class name { *static m() {} }",
4285     NULL};
4286
4287   static const ParserFlag always_flags[] = {
4288     kAllowHarmonyClasses,
4289     kAllowHarmonyNumericLiterals,
4290     kAllowHarmonySloppy
4291   };
4292   RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4293                     always_flags, arraysize(always_flags));
4294 }
4295
4296
4297 TEST(ClassNameErrors) {
4298   const char* context_data[][2] = {{"class ", "{}"},
4299                                    {"(class ", "{});"},
4300                                    {"'use strict'; class ", "{}"},
4301                                    {"'use strict'; (class ", "{});"},
4302                                    {NULL, NULL}};
4303   const char* class_name[] = {
4304     "arguments",
4305     "eval",
4306     "implements",
4307     "interface",
4308     "let",
4309     "package",
4310     "private",
4311     "protected",
4312     "public",
4313     "static",
4314     "var",
4315     "yield",
4316     NULL};
4317
4318   static const ParserFlag always_flags[] = {
4319     kAllowHarmonyClasses,
4320     kAllowHarmonyObjectLiterals,
4321     kAllowHarmonySloppy
4322   };
4323   RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4324                     always_flags, arraysize(always_flags));
4325 }
4326
4327
4328 TEST(ClassGetterParamNameErrors) {
4329   const char* context_data[][2] = {
4330     {"class C { get name(", ") {} }"},
4331     {"(class { get name(", ") {} });"},
4332     {"'use strict'; class C { get name(", ") {} }"},
4333     {"'use strict'; (class { get name(", ") {} })"},
4334     {NULL, NULL}
4335   };
4336
4337   const char* class_name[] = {
4338     "arguments",
4339     "eval",
4340     "implements",
4341     "interface",
4342     "let",
4343     "package",
4344     "private",
4345     "protected",
4346     "public",
4347     "static",
4348     "var",
4349     "yield",
4350     NULL};
4351
4352   static const ParserFlag always_flags[] = {
4353     kAllowHarmonyClasses,
4354     kAllowHarmonyObjectLiterals,
4355     kAllowHarmonySloppy
4356   };
4357   RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4358                     always_flags, arraysize(always_flags));
4359 }
4360
4361
4362 TEST(ClassStaticPrototypeErrors) {
4363   const char* context_data[][2] = {{"class C {", "}"},
4364                                    {"(class {", "});"},
4365                                    {NULL, NULL}};
4366
4367   const char* class_body_data[] = {
4368     "static prototype() {}",
4369     "static get prototype() {}",
4370     "static set prototype(_) {}",
4371     "static *prototype() {}",
4372     "static 'prototype'() {}",
4373     "static *'prototype'() {}",
4374     "static prot\\u006ftype() {}",
4375     "static 'prot\\u006ftype'() {}",
4376     "static get 'prot\\u006ftype'() {}",
4377     "static set 'prot\\u006ftype'(_) {}",
4378     "static *'prot\\u006ftype'() {}",
4379     NULL};
4380
4381   static const ParserFlag always_flags[] = {
4382     kAllowHarmonyClasses,
4383     kAllowHarmonyObjectLiterals,
4384     kAllowHarmonySloppy
4385   };
4386   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4387                     always_flags, arraysize(always_flags));
4388 }
4389
4390
4391 TEST(ClassSpecialConstructorErrors) {
4392   const char* context_data[][2] = {{"class C {", "}"},
4393                                    {"(class {", "});"},
4394                                    {NULL, NULL}};
4395
4396   const char* class_body_data[] = {
4397     "get constructor() {}",
4398     "get constructor(_) {}",
4399     "*constructor() {}",
4400     "get 'constructor'() {}",
4401     "*'constructor'() {}",
4402     "get c\\u006fnstructor() {}",
4403     "*c\\u006fnstructor() {}",
4404     "get 'c\\u006fnstructor'() {}",
4405     "get 'c\\u006fnstructor'(_) {}",
4406     "*'c\\u006fnstructor'() {}",
4407     NULL};
4408
4409   static const ParserFlag always_flags[] = {
4410     kAllowHarmonyClasses,
4411     kAllowHarmonyObjectLiterals,
4412     kAllowHarmonySloppy
4413   };
4414   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4415                     always_flags, arraysize(always_flags));
4416 }
4417
4418
4419 TEST(ClassConstructorNoErrors) {
4420   const char* context_data[][2] = {{"class C {", "}"},
4421                                    {"(class {", "});"},
4422                                    {NULL, NULL}};
4423
4424   const char* class_body_data[] = {
4425     "constructor() {}",
4426     "static constructor() {}",
4427     "static get constructor() {}",
4428     "static set constructor(_) {}",
4429     "static *constructor() {}",
4430     NULL};
4431
4432   static const ParserFlag always_flags[] = {
4433     kAllowHarmonyClasses,
4434     kAllowHarmonyObjectLiterals,
4435     kAllowHarmonySloppy
4436   };
4437   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4438                     always_flags, arraysize(always_flags));
4439 }
4440
4441
4442 TEST(ClassMultipleConstructorErrors) {
4443   const char* context_data[][2] = {{"class C {", "}"},
4444                                    {"(class {", "});"},
4445                                    {NULL, NULL}};
4446
4447   const char* class_body_data[] = {
4448     "constructor() {}; constructor() {}",
4449     NULL};
4450
4451   static const ParserFlag always_flags[] = {
4452     kAllowHarmonyClasses,
4453     kAllowHarmonyObjectLiterals,
4454     kAllowHarmonySloppy
4455   };
4456   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4457                     always_flags, arraysize(always_flags));
4458 }
4459
4460
4461 TEST(ClassMultiplePropertyNamesNoErrors) {
4462   const char* context_data[][2] = {{"class C {", "}"},
4463                                    {"(class {", "});"},
4464                                    {NULL, NULL}};
4465
4466   const char* class_body_data[] = {
4467     "constructor() {}; static constructor() {}",
4468     "m() {}; static m() {}",
4469     "m() {}; m() {}",
4470     "static m() {}; static m() {}",
4471     "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
4472     NULL};
4473
4474   static const ParserFlag always_flags[] = {
4475     kAllowHarmonyClasses,
4476     kAllowHarmonyObjectLiterals,
4477     kAllowHarmonySloppy
4478   };
4479   RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4480                     always_flags, arraysize(always_flags));
4481 }
4482
4483
4484 TEST(ClassesAreStrictErrors) {
4485   const char* context_data[][2] = {{"", ""},
4486                                    {"(", ");"},
4487                                    {NULL, NULL}};
4488
4489   const char* class_body_data[] = {
4490     "class C { method() { with ({}) {} } }",
4491     "class C extends function() { with ({}) {} } {}",
4492     "class C { *method() { with ({}) {} } }",
4493     NULL};
4494
4495   static const ParserFlag always_flags[] = {
4496     kAllowHarmonyClasses,
4497     kAllowHarmonyObjectLiterals,
4498     kAllowHarmonySloppy
4499   };
4500   RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4501                     always_flags, arraysize(always_flags));
4502 }
4503
4504
4505 TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4506   const char* context_data[][2] = {{"({", "});"},
4507                                    {"'use strict'; ({", "});"},
4508                                    {NULL, NULL}};
4509
4510   const char* name_data[] = {
4511     "break",
4512     "case",
4513     "catch",
4514     "class",
4515     "const",
4516     "continue",
4517     "debugger",
4518     "default",
4519     "delete",
4520     "do",
4521     "else",
4522     "enum",
4523     "export",
4524     "extends",
4525     "false",
4526     "finally",
4527     "for",
4528     "function",
4529     "if",
4530     "import",
4531     "in",
4532     "instanceof",
4533     "new",
4534     "null",
4535     "return",
4536     "super",
4537     "switch",
4538     "this",
4539     "throw",
4540     "true",
4541     "try",
4542     "typeof",
4543     "var",
4544     "void",
4545     "while",
4546     "with",
4547     NULL
4548   };
4549
4550   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4551   RunParserSyncTest(context_data, name_data, kError, NULL, 0,
4552                     always_flags, arraysize(always_flags));
4553 }
4554
4555
4556 TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4557   const char* context_data[][2] = {{"({", "});"},
4558                                    {NULL, NULL}};
4559
4560   const char* name_data[] = {
4561     "implements",
4562     "interface",
4563     "let",
4564     "package",
4565     "private",
4566     "protected",
4567     "public",
4568     "static",
4569     "yield",
4570     NULL
4571   };
4572
4573   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4574   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
4575                     always_flags, arraysize(always_flags));
4576
4577   const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4578                                           {NULL, NULL}};
4579   RunParserSyncTest(context_strict_data, name_data, kError, NULL, 0,
4580                     always_flags, arraysize(always_flags));
4581 }
4582
4583
4584 TEST(ObjectLiteralPropertyShorthandError) {
4585   const char* context_data[][2] = {{"({", "});"},
4586                                    {"'use strict'; ({", "});"},
4587                                    {NULL, NULL}};
4588
4589   const char* name_data[] = {
4590     "1",
4591     "1.2",
4592     "0",
4593     "0.1",
4594     "1.0",
4595     "1e1",
4596     "0x1",
4597     "\"s\"",
4598     "'s'",
4599     NULL
4600   };
4601
4602   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4603   RunParserSyncTest(context_data, name_data, kError, NULL, 0,
4604                     always_flags, arraysize(always_flags));
4605 }
4606
4607
4608 TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4609   const char* context_data[][2] = {{"", ""},
4610                                    {NULL, NULL}};
4611
4612   const char* name_data[] = {
4613     "function* g() { ({yield}); }",
4614     NULL
4615   };
4616
4617   static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
4618   RunParserSyncTest(context_data, name_data, kError, NULL, 0,
4619                     always_flags, arraysize(always_flags));
4620 }
4621
4622
4623 TEST(ConstParsingInForIn) {
4624   const char* context_data[][2] = {{"'use strict';", ""},
4625                                    {"function foo(){ 'use strict';", "}"},
4626                                    {NULL, NULL}};
4627
4628   const char* data[] = {
4629       "for(const x = 1; ; ) {}",
4630       "for(const x = 1, y = 2;;){}",
4631       "for(const x in [1,2,3]) {}",
4632       "for(const x of [1,2,3]) {}",
4633       NULL};
4634   static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
4635   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4636                     arraysize(always_flags));
4637 }
4638
4639
4640 TEST(ConstParsingInForInError) {
4641   const char* context_data[][2] = {{"'use strict';", ""},
4642                                    {"function foo(){ 'use strict';", "}"},
4643                                    {NULL, NULL}};
4644
4645   const char* data[] = {
4646       "for(const x,y = 1; ; ) {}",
4647       "for(const x = 4 in [1,2,3]) {}",
4648       "for(const x = 4, y in [1,2,3]) {}",
4649       "for(const x = 4 of [1,2,3]) {}",
4650       "for(const x = 4, y of [1,2,3]) {}",
4651       "for(const x = 1, y = 2 in []) {}",
4652       "for(const x,y in []) {}",
4653       "for(const x = 1, y = 2 of []) {}",
4654       "for(const x,y of []) {}",
4655       NULL};
4656   static const ParserFlag always_flags[] = {kAllowHarmonyScoping};
4657   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4658                     arraysize(always_flags));
4659 }
4660
4661
4662 TEST(InvalidUnicodeEscapes) {
4663   const char* context_data[][2] = {{"", ""},
4664                                    {"'use strict';", ""},
4665                                    {NULL, NULL}};
4666   const char* data[] = {
4667     "var foob\\u123r = 0;",
4668     "var \\u123roo = 0;",
4669     "\"foob\\u123rr\"",
4670     // No escapes allowed in regexp flags
4671     "/regex/\\u0069g",
4672     "/regex/\\u006g",
4673     // Braces gone wrong
4674     "var foob\\u{c481r = 0;",
4675     "var foob\\uc481}r = 0;",
4676     "var \\u{0052oo = 0;",
4677     "var \\u0052}oo = 0;",
4678     "\"foob\\u{c481r\"",
4679     "var foob\\u{}ar = 0;",
4680     // Too high value for the unicode escape
4681     "\"\\u{110000}\"",
4682     // Not an unicode escape
4683     "var foob\\v1234r = 0;",
4684     "var foob\\U1234r = 0;",
4685     "var foob\\v{1234}r = 0;",
4686     "var foob\\U{1234}r = 0;",
4687     NULL};
4688   static const ParserFlag always_flags[] = {kAllowHarmonyUnicode};
4689   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4690                     arraysize(always_flags));
4691 }
4692
4693
4694 TEST(UnicodeEscapes) {
4695   const char* context_data[][2] = {{"", ""},
4696                                    {"'use strict';", ""},
4697                                    {NULL, NULL}};
4698   const char* data[] = {
4699     // Identifier starting with escape
4700     "var \\u0052oo = 0;",
4701     "var \\u{0052}oo = 0;",
4702     "var \\u{52}oo = 0;",
4703     "var \\u{00000000052}oo = 0;",
4704     // Identifier with an escape but not starting with an escape
4705     "var foob\\uc481r = 0;",
4706     "var foob\\u{c481}r = 0;",
4707     // String with an escape
4708     "\"foob\\uc481r\"",
4709     "\"foob\\{uc481}r\"",
4710     // This character is a valid unicode character, representable as a surrogate
4711     // pair, not representable as 4 hex digits.
4712     "\"foo\\u{10e6d}\"",
4713     // Max value for the unicode escape
4714     "\"\\u{10ffff}\"",
4715     NULL};
4716   static const ParserFlag always_flags[] = {kAllowHarmonyUnicode};
4717   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4718                     arraysize(always_flags));
4719 }
4720
4721
4722 TEST(ScanTemplateLiterals) {
4723   const char* context_data[][2] = {{"'use strict';", ""},
4724                                    {"function foo(){ 'use strict';"
4725                                     "  var a, b, c; return ", "}"},
4726                                    {NULL, NULL}};
4727
4728   const char* data[] = {
4729       "``",
4730       "`no-subst-template`",
4731       "`template-head${a}`",
4732       "`${a}`",
4733       "`${a}template-tail`",
4734       "`template-head${a}template-tail`",
4735       "`${a}${b}${c}`",
4736       "`a${a}b${b}c${c}`",
4737       "`${a}a${b}b${c}c`",
4738       "`foo\n\nbar\r\nbaz`",
4739       "`foo\n\n${  bar  }\r\nbaz`",
4740       "`foo${a /* comment */}`",
4741       "`foo${a // comment\n}`",
4742       "`foo${a \n}`",
4743       "`foo${a \r\n}`",
4744       "`foo${a \r}`",
4745       "`foo${/* comment */ a}`",
4746       "`foo${// comment\na}`",
4747       "`foo${\n a}`",
4748       "`foo${\r\n a}`",
4749       "`foo${\r a}`",
4750       "`foo${'a' in a}`",
4751       NULL};
4752   static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
4753   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4754                     arraysize(always_flags));
4755 }
4756
4757
4758 TEST(ScanTaggedTemplateLiterals) {
4759   const char* context_data[][2] = {{"'use strict';", ""},
4760                                    {"function foo(){ 'use strict';"
4761                                     "  function tag() {}"
4762                                     "  var a, b, c; return ", "}"},
4763                                    {NULL, NULL}};
4764
4765   const char* data[] = {
4766       "tag ``",
4767       "tag `no-subst-template`",
4768       "tag`template-head${a}`",
4769       "tag `${a}`",
4770       "tag `${a}template-tail`",
4771       "tag   `template-head${a}template-tail`",
4772       "tag\n`${a}${b}${c}`",
4773       "tag\r\n`a${a}b${b}c${c}`",
4774       "tag    `${a}a${b}b${c}c`",
4775       "tag\t`foo\n\nbar\r\nbaz`",
4776       "tag\r`foo\n\n${  bar  }\r\nbaz`",
4777       "tag`foo${a /* comment */}`",
4778       "tag`foo${a // comment\n}`",
4779       "tag`foo${a \n}`",
4780       "tag`foo${a \r\n}`",
4781       "tag`foo${a \r}`",
4782       "tag`foo${/* comment */ a}`",
4783       "tag`foo${// comment\na}`",
4784       "tag`foo${\n a}`",
4785       "tag`foo${\r\n a}`",
4786       "tag`foo${\r a}`",
4787       "tag`foo${'a' in a}`",
4788       NULL};
4789   static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
4790   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4791                     arraysize(always_flags));
4792 }
4793
4794
4795 TEST(TemplateMaterializedLiterals) {
4796   const char* context_data[][2] = {
4797     {
4798       "'use strict';\n"
4799       "function tag() {}\n"
4800       "var a, b, c;\n"
4801       "(", ")"
4802     },
4803     {NULL, NULL}
4804   };
4805
4806   const char* data[] = {
4807     "tag``",
4808     "tag`a`",
4809     "tag`a${1}b`",
4810     "tag`a${1}b${2}c`",
4811     "``",
4812     "`a`",
4813     "`a${1}b`",
4814     "`a${1}b${2}c`",
4815     NULL
4816   };
4817
4818   static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
4819   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4820                     arraysize(always_flags));
4821 }
4822
4823
4824 TEST(ScanUnterminatedTemplateLiterals) {
4825   const char* context_data[][2] = {{"'use strict';", ""},
4826                                    {"function foo(){ 'use strict';"
4827                                     "  var a, b, c; return ", "}"},
4828                                    {NULL, NULL}};
4829
4830   const char* data[] = {
4831       "`no-subst-template",
4832       "`template-head${a}",
4833       "`${a}template-tail",
4834       "`template-head${a}template-tail",
4835       "`${a}${b}${c}",
4836       "`a${a}b${b}c${c}",
4837       "`${a}a${b}b${c}c",
4838       "`foo\n\nbar\r\nbaz",
4839       "`foo\n\n${  bar  }\r\nbaz",
4840       "`foo${a /* comment } */`",
4841       "`foo${a /* comment } `*/",
4842       "`foo${a // comment}`",
4843       "`foo${a \n`",
4844       "`foo${a \r\n`",
4845       "`foo${a \r`",
4846       "`foo${/* comment */ a`",
4847       "`foo${// commenta}`",
4848       "`foo${\n a`",
4849       "`foo${\r\n a`",
4850       "`foo${\r a`",
4851       "`foo${fn(}`",
4852       "`foo${1 if}`",
4853       NULL};
4854   static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
4855   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4856                     arraysize(always_flags));
4857 }
4858
4859
4860 TEST(TemplateLiteralsIllegalTokens) {
4861   const char* context_data[][2] = {{"'use strict';", ""},
4862                                    {"function foo(){ 'use strict';"
4863                                     "  var a, b, c; return ", "}"},
4864                                    {NULL, NULL}};
4865   const char* data[] = {
4866       "`hello\\x`",
4867       "`hello\\x${1}`",
4868       "`hello${1}\\x`",
4869       "`hello${1}\\x${2}`",
4870       "`hello\\x\n`",
4871       "`hello\\x\n${1}`",
4872       "`hello${1}\\x\n`",
4873       "`hello${1}\\x\n${2}`",
4874       NULL};
4875
4876   static const ParserFlag always_flags[] = {kAllowHarmonyTemplates};
4877   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4878                     arraysize(always_flags));
4879 }
4880
4881
4882 TEST(ParseRestParameters) {
4883   const char* context_data[][2] = {{"'use strict';(function(",
4884                                     "){ return args;})(1, [], /regexp/, 'str',"
4885                                     "function(){});"},
4886                                    {"(function(", "){ return args;})(1, [],"
4887                                     "/regexp/, 'str', function(){});"},
4888                                   {NULL, NULL}};
4889
4890   const char* data[] = {
4891     "...args",
4892     "a, ...args",
4893     "...   args",
4894     "a, ...   args",
4895     "...\targs",
4896     "a, ...\targs",
4897     "...\r\nargs",
4898     "a, ...\r\nargs",
4899     "...\rargs",
4900     "a, ...\rargs",
4901     "...\t\n\t\t\n  args",
4902     "a, ...  \n  \n  args",
4903     NULL};
4904   static const ParserFlag always_flags[] = {kAllowHarmonyRestParameters};
4905   RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
4906                     arraysize(always_flags));
4907 }
4908
4909
4910 TEST(ParseRestParametersErrors) {
4911   const char* context_data[][2] = {{"'use strict';(function(",
4912                                     "){ return args;}(1, [], /regexp/, 'str',"
4913                                     "function(){});"},
4914                                    {"(function(", "){ return args;}(1, [],"
4915                                     "/regexp/, 'str', function(){});"},
4916                                    {NULL, NULL}};
4917
4918   const char* data[] = {
4919       "...args, b",
4920       "a, ...args, b",
4921       "...args,   b",
4922       "a, ...args,   b",
4923       "...args,\tb",
4924       "a,...args\t,b",
4925       "...args\r\n, b",
4926       "a, ... args,\r\nb",
4927       "...args\r,b",
4928       "a, ... args,\rb",
4929       "...args\t\n\t\t\n,  b",
4930       "a, ... args,  \n  \n  b",
4931       "a, a, ...args",
4932       "a,\ta, ...args",
4933       "a,\ra, ...args",
4934       "a,\na, ...args",
4935       NULL};
4936   static const ParserFlag always_flags[] = {kAllowHarmonyRestParameters};
4937   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4938                     arraysize(always_flags));
4939 }
4940
4941
4942 TEST(RestParametersEvalArguments) {
4943   const char* strict_context_data[][2] =
4944       {{"'use strict';(function(",
4945         "){ return;})(1, [], /regexp/, 'str',function(){});"},
4946        {NULL, NULL}};
4947   const char* sloppy_context_data[][2] =
4948       {{"(function(",
4949         "){ return;})(1, [],/regexp/, 'str', function(){});"},
4950        {NULL, NULL}};
4951
4952   const char* data[] = {
4953       "...eval",
4954       "eval, ...args",
4955       "...arguments",
4956       "arguments, ...args",
4957       NULL};
4958
4959   static const ParserFlag always_flags[] = {kAllowHarmonyRestParameters};
4960
4961   // Fail in strict mode
4962   RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
4963                     arraysize(always_flags));
4964
4965   // OK in sloppy mode
4966   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
4967                     arraysize(always_flags));
4968 }
4969
4970
4971 TEST(RestParametersDuplicateEvalArguments) {
4972   const char* context_data[][2] =
4973       {{"'use strict';(function(",
4974         "){ return;})(1, [], /regexp/, 'str',function(){});"},
4975        {"(function(",
4976         "){ return;})(1, [],/regexp/, 'str', function(){});"},
4977        {NULL, NULL}};
4978
4979   const char* data[] = {
4980       "eval, ...eval",
4981       "eval, eval, ...args",
4982       "arguments, ...arguments",
4983       "arguments, arguments, ...args",
4984       NULL};
4985
4986   static const ParserFlag always_flags[] = {kAllowHarmonyRestParameters};
4987
4988   // In strict mode, the error is using "eval" or "arguments" as parameter names
4989   // In sloppy mode, the error is that eval / arguments are duplicated
4990   RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
4991                     arraysize(always_flags));
4992 }
4993
4994
4995 TEST(LexicalScopingSloppyMode) {
4996   const char* context_data[][2] = {
4997       {"", ""},
4998       {"function f() {", "}"},
4999       {"{", "}"},
5000       {NULL, NULL}};
5001   const char* bad_data[] = {
5002     "let x = 1;",
5003     "for(let x = 1;;){}",
5004     "for(let x of []){}",
5005     "for(let x in []){}",
5006     "class C {}",
5007     "class C extends D {}",
5008     "(class {})",
5009     "(class extends D {})",
5010     "(class C {})",
5011     "(class C extends D {})",
5012     NULL};
5013   static const ParserFlag always_true_flags[] = {
5014       kAllowHarmonyScoping, kAllowHarmonyClasses};
5015   static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
5016   RunParserSyncTest(context_data, bad_data, kError, NULL, 0,
5017                     always_true_flags, arraysize(always_true_flags),
5018                     always_false_flags, arraysize(always_false_flags));
5019
5020   const char* good_data[] = {
5021     "let = 1;",
5022     "for(let = 1;;){}",
5023     NULL};
5024   RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0,
5025                     always_true_flags, arraysize(always_true_flags),
5026                     always_false_flags, arraysize(always_false_flags));
5027 }
5028
5029
5030 TEST(ComputedPropertyName) {
5031   const char* context_data[][2] = {{"({[", "]: 1});"},
5032                                    {"({get [", "]() {}});"},
5033                                    {"({set [", "](_) {}});"},
5034                                    {"({[", "]() {}});"},
5035                                    {"({*[", "]() {}});"},
5036                                    {"(class {get [", "]() {}});"},
5037                                    {"(class {set [", "](_) {}});"},
5038                                    {"(class {[", "]() {}});"},
5039                                    {"(class {*[", "]() {}});"},
5040                                    {NULL, NULL}};
5041   const char* error_data[] = {
5042     "1, 2",
5043     "var name",
5044     NULL};
5045
5046   static const ParserFlag always_flags[] = {
5047     kAllowHarmonyClasses,
5048     kAllowHarmonyComputedPropertyNames,
5049     kAllowHarmonyObjectLiterals,
5050     kAllowHarmonySloppy,
5051   };
5052   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5053                     always_flags, arraysize(always_flags));
5054
5055   const char* name_data[] = {
5056     "1",
5057     "1 + 2",
5058     "'name'",
5059     "\"name\"",
5060     "[]",
5061     "{}",
5062     NULL};
5063
5064   RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
5065                     always_flags, arraysize(always_flags));
5066 }
5067
5068
5069 TEST(ComputedPropertyNameShorthandError) {
5070   const char* context_data[][2] = {{"({", "});"},
5071                                    {NULL, NULL}};
5072   const char* error_data[] = {
5073     "a: 1, [2]",
5074     "[1], a: 1",
5075     NULL};
5076
5077   static const ParserFlag always_flags[] = {
5078     kAllowHarmonyClasses,
5079     kAllowHarmonyComputedPropertyNames,
5080     kAllowHarmonyObjectLiterals,
5081     kAllowHarmonySloppy,
5082   };
5083   RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5084                     always_flags, arraysize(always_flags));
5085 }
5086
5087
5088 TEST(BasicImportExportParsing) {
5089   const char* kSources[] = {
5090       "export let x = 0;",
5091       "export var y = 0;",
5092       "export const z = 0;",
5093       "export function func() { };",
5094       "export class C { };",
5095       "export { };",
5096       "function f() {}; f(); export { f };",
5097       "var a, b, c; export { a, b as baz, c };",
5098       "var d, e; export { d as dreary, e, };",
5099       "export default function f() {}",
5100       "export default class C {}",
5101       "export default 42",
5102       "var x; export default x = 7",
5103       "export { Q } from 'somemodule.js';",
5104       "export * from 'somemodule.js';",
5105       "var foo; export { foo as for };",
5106       "export { arguments } from 'm.js';",
5107       "export { for } from 'm.js';",
5108       "export { yield } from 'm.js'",
5109       "export { static } from 'm.js'",
5110       "export { let } from 'm.js'",
5111
5112       "import 'somemodule.js';",
5113       "import { } from 'm.js';",
5114       "import { a } from 'm.js';",
5115       "import { a, b as d, c, } from 'm.js';",
5116       "import * as thing from 'm.js';",
5117       "import thing from 'm.js';",
5118       "import thing, * as rest from 'm.js';",
5119       "import thing, { a, b, c } from 'm.js';",
5120       "import { arguments as a } from 'm.js';",
5121       "import { for as f } from 'm.js';",
5122       "import { yield as y } from 'm.js';",
5123       "import { static as s } from 'm.js';",
5124       "import { let as l } from 'm.js';",
5125   };
5126
5127   i::Isolate* isolate = CcTest::i_isolate();
5128   i::Factory* factory = isolate->factory();
5129
5130   v8::HandleScope handles(CcTest::isolate());
5131   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
5132   v8::Context::Scope context_scope(context);
5133
5134   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5135                                         128 * 1024);
5136
5137   for (unsigned i = 0; i < arraysize(kSources); ++i) {
5138     int kProgramByteSize = i::StrLength(kSources[i]);
5139     i::ScopedVector<char> program(kProgramByteSize + 1);
5140     i::SNPrintF(program, "%s", kSources[i]);
5141     i::Handle<i::String> source =
5142         factory->NewStringFromUtf8(i::CStrVector(program.start()))
5143             .ToHandleChecked();
5144
5145     // Show that parsing as a module works
5146     {
5147       i::Handle<i::Script> script = factory->NewScript(source);
5148       i::CompilationInfoWithZone info(script);
5149       i::Parser parser(&info, isolate->stack_guard()->real_climit(),
5150                        isolate->heap()->HashSeed(), isolate->unicode_cache());
5151       parser.set_allow_harmony_classes(true);
5152       parser.set_allow_harmony_modules(true);
5153       parser.set_allow_harmony_scoping(true);
5154       info.MarkAsModule();
5155       if (!parser.Parse(&info)) {
5156         i::Handle<i::JSObject> exception_handle(
5157             i::JSObject::cast(isolate->pending_exception()));
5158         i::Handle<i::String> message_string =
5159             i::Handle<i::String>::cast(i::Object::GetProperty(
5160                   isolate, exception_handle, "message").ToHandleChecked());
5161
5162         v8::base::OS::Print(
5163             "Parser failed on:\n"
5164             "\t%s\n"
5165             "with error:\n"
5166             "\t%s\n"
5167             "However, we expected no error.",
5168             source->ToCString().get(), message_string->ToCString().get());
5169         CHECK(false);
5170       }
5171     }
5172
5173     // And that parsing a script does not.
5174     {
5175       i::Handle<i::Script> script = factory->NewScript(source);
5176       i::CompilationInfoWithZone info(script);
5177       i::Parser parser(&info, isolate->stack_guard()->real_climit(),
5178                        isolate->heap()->HashSeed(), isolate->unicode_cache());
5179       parser.set_allow_harmony_classes(true);
5180       parser.set_allow_harmony_modules(true);
5181       parser.set_allow_harmony_scoping(true);
5182       info.MarkAsGlobal();
5183       CHECK(!parser.Parse(&info));
5184     }
5185   }
5186 }
5187
5188
5189 TEST(ImportExportParsingErrors) {
5190   const char* kErrorSources[] = {
5191       "export {",
5192       "var a; export { a",
5193       "var a; export { a,",
5194       "var a; export { a, ;",
5195       "var a; export { a as };",
5196       "var a, b; export { a as , b};",
5197       "export }",
5198       "var foo, bar; export { foo bar };",
5199       "export { foo };",
5200       "export { , };",
5201       "export default;",
5202       "export default var x = 7;",
5203       "export default let x = 7;",
5204       "export default const x = 7;",
5205       "export *;",
5206       "export * from;",
5207       "export { Q } from;",
5208       "export default from 'module.js';",
5209       "export { for }",
5210       "export { for as foo }",
5211       "export { arguments }",
5212       "export { arguments as foo }",
5213       "var a; export { a, a };",
5214
5215       "import from;",
5216       "import from 'm.js';",
5217       "import { };",
5218       "import {;",
5219       "import };",
5220       "import { , };",
5221       "import { , } from 'm.js';",
5222       "import { a } from;",
5223       "import { a } 'm.js';",
5224       "import , from 'm.js';",
5225       "import a , from 'm.js';",
5226       "import a { b, c } from 'm.js';",
5227       "import arguments from 'm.js';",
5228       "import eval from 'm.js';",
5229       "import { arguments } from 'm.js';",
5230       "import { eval } from 'm.js';",
5231       "import { a as arguments } from 'm.js';",
5232       "import { for } from 'm.js';",
5233       "import { y as yield } from 'm.js'",
5234       "import { s as static } from 'm.js'",
5235       "import { l as let } from 'm.js'",
5236       "import { x }, def from 'm.js';",
5237       "import def, def2 from 'm.js';",
5238       "import * as x, def from 'm.js';",
5239       "import * as x, * as y from 'm.js';",
5240       "import {x}, {y} from 'm.js';",
5241       "import * as x, {y} from 'm.js';",
5242
5243       // TODO(ES6): These two forms should be supported
5244       "export default function() {};",
5245       "export default class {};"
5246   };
5247
5248   i::Isolate* isolate = CcTest::i_isolate();
5249   i::Factory* factory = isolate->factory();
5250
5251   v8::HandleScope handles(CcTest::isolate());
5252   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
5253   v8::Context::Scope context_scope(context);
5254
5255   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5256                                         128 * 1024);
5257
5258   for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5259     int kProgramByteSize = i::StrLength(kErrorSources[i]);
5260     i::ScopedVector<char> program(kProgramByteSize + 1);
5261     i::SNPrintF(program, "%s", kErrorSources[i]);
5262     i::Handle<i::String> source =
5263         factory->NewStringFromUtf8(i::CStrVector(program.start()))
5264             .ToHandleChecked();
5265
5266     i::Handle<i::Script> script = factory->NewScript(source);
5267     i::CompilationInfoWithZone info(script);
5268     i::Parser parser(&info, isolate->stack_guard()->real_climit(),
5269                      isolate->heap()->HashSeed(), isolate->unicode_cache());
5270     parser.set_allow_harmony_classes(true);
5271     parser.set_allow_harmony_modules(true);
5272     parser.set_allow_harmony_scoping(true);
5273     info.MarkAsModule();
5274     CHECK(!parser.Parse(&info));
5275   }
5276 }
5277
5278
5279 TEST(DuplicateProtoError) {
5280   const char* context_data[][2] = {
5281     {"({", "});"},
5282     {"'use strict'; ({", "});"},
5283     {NULL, NULL}
5284   };
5285   const char* error_data[] = {
5286     "__proto__: {}, __proto__: {}",
5287     "__proto__: {}, \"__proto__\": {}",
5288     "__proto__: {}, \"__\x70roto__\": {}",
5289     "__proto__: {}, a: 1, __proto__: {}",
5290     NULL
5291   };
5292
5293   RunParserSyncTest(context_data, error_data, kError);
5294 }
5295
5296
5297 TEST(DuplicateProtoNoError) {
5298   const char* context_data[][2] = {
5299     {"({", "});"},
5300     {"'use strict'; ({", "});"},
5301     {NULL, NULL}
5302   };
5303   const char* error_data[] = {
5304     "__proto__: {}, ['__proto__']: {}",
5305     "__proto__: {}, __proto__() {}",
5306     "__proto__: {}, get __proto__() {}",
5307     "__proto__: {}, set __proto__(v) {}",
5308     "__proto__: {}, __proto__",
5309     NULL
5310   };
5311
5312   static const ParserFlag always_flags[] = {
5313     kAllowHarmonyComputedPropertyNames,
5314     kAllowHarmonyObjectLiterals,
5315   };
5316   RunParserSyncTest(context_data, error_data, kSuccess, NULL, 0,
5317                     always_flags, arraysize(always_flags));
5318 }
5319
5320
5321 TEST(DeclarationsError) {
5322   const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5323                                    {"'use strict'; if (false) {} else", ""},
5324                                    {"'use strict'; while (false)", ""},
5325                                    {"'use strict'; for (;;)", ""},
5326                                    {"'use strict'; for (x in y)", ""},
5327                                    {"'use strict'; do ", " while (false)"},
5328                                    {"'use strong'; if (true)", ""},
5329                                    {"'use strong'; if (false) {} else", ""},
5330                                    {"'use strong'; while (false)", ""},
5331                                    {"'use strong'; for (;;)", ""},
5332                                    {"'use strong'; for (x in y)", ""},
5333                                    {"'use strong'; do ", " while (false)"},
5334                                    {NULL, NULL}};
5335
5336   const char* statement_data[] = {
5337     "let x = 1;",
5338     "const x = 1;",
5339     "class C {}",
5340     NULL};
5341
5342   static const ParserFlag always_flags[] = {
5343       kAllowHarmonyClasses, kAllowHarmonyScoping, kAllowStrongMode};
5344   RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
5345                     always_flags, arraysize(always_flags));
5346 }
5347
5348
5349 void TestLanguageMode(const char* source,
5350                       i::LanguageMode expected_language_mode) {
5351   i::Isolate* isolate = CcTest::i_isolate();
5352   i::Factory* factory = isolate->factory();
5353   v8::HandleScope handles(CcTest::isolate());
5354   v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
5355   v8::Context::Scope context_scope(context);
5356   isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5357                                         128 * 1024);
5358
5359   i::Handle<i::Script> script =
5360       factory->NewScript(factory->NewStringFromAsciiChecked(source));
5361   i::CompilationInfoWithZone info(script);
5362   i::Parser parser(&info, isolate->stack_guard()->real_climit(),
5363                    isolate->heap()->HashSeed(), isolate->unicode_cache());
5364   parser.set_allow_strong_mode(true);
5365   info.MarkAsGlobal();
5366   parser.Parse(&info);
5367   CHECK(info.function() != NULL);
5368   CHECK_EQ(expected_language_mode, info.function()->language_mode());
5369 }
5370
5371
5372 TEST(LanguageModeDirectives) {
5373   TestLanguageMode("\"use nothing\"", i::SLOPPY);
5374   TestLanguageMode("\"use strict\"", i::STRICT);
5375   TestLanguageMode("\"use strong\"", i::STRONG);
5376
5377   TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
5378   TestLanguageMode("var x = 1; \"use strong\"", i::SLOPPY);
5379
5380   // Test that multiple directives ("use strict" / "use strong") put the parser
5381   // into the correct mode.
5382   TestLanguageMode("\"use strict\"; \"use strong\";", i::STRONG);
5383   TestLanguageMode("\"use strong\"; \"use strict\";", i::STRONG);
5384
5385   TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
5386   TestLanguageMode("\"use some future directive\"; \"use strong\";", i::STRONG);
5387 }
5388
5389
5390 TEST(PropertyNameEvalArguments) {
5391   const char* context_data[][2] = {{"'use strict';", ""},
5392                                    {"'use strong';", ""},
5393                                    {NULL, NULL}};
5394
5395   const char* statement_data[] = {
5396       "({eval: 1})",
5397       "({arguments: 1})",
5398       "({eval() {}})",
5399       "({arguments() {}})",
5400       "({*eval() {}})",
5401       "({*arguments() {}})",
5402       "({get eval() {}})",
5403       "({get arguments() {}})",
5404       "({set eval(_) {}})",
5405       "({set arguments(_) {}})",
5406
5407       "class C {eval() {}}",
5408       "class C {arguments() {}}",
5409       "class C {*eval() {}}",
5410       "class C {*arguments() {}}",
5411       "class C {get eval() {}}",
5412       "class C {get arguments() {}}",
5413       "class C {set eval(_) {}}",
5414       "class C {set arguments(_) {}}",
5415
5416       "class C {static eval() {}}",
5417       "class C {static arguments() {}}",
5418       "class C {static *eval() {}}",
5419       "class C {static *arguments() {}}",
5420       "class C {static get eval() {}}",
5421       "class C {static get arguments() {}}",
5422       "class C {static set eval(_) {}}",
5423       "class C {static set arguments(_) {}}",
5424
5425       NULL};
5426
5427   static const ParserFlag always_flags[] = {
5428       kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
5429       kAllowStrongMode};
5430   RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
5431                     always_flags, arraysize(always_flags));
5432 }
5433
5434
5435 TEST(FunctionLiteralDuplicateParameters) {
5436   const char* strict_context_data[][2] =
5437       {{"'use strict';(function(", "){})();"},
5438        {"(function(", ") { 'use strict'; })();"},
5439        {"'use strict'; function fn(", ") {}; fn();"},
5440        {"function fn(", ") { 'use strict'; }; fn();"},
5441        {"'use strong';(function(", "){})();"},
5442        {"(function(", ") { 'use strong'; })();"},
5443        {"'use strong'; function fn(", ") {}; fn();"},
5444        {"function fn(", ") { 'use strong'; }; fn();"},
5445        {NULL, NULL}};
5446
5447   const char* sloppy_context_data[][2] =
5448       {{"(function(", "){})();"},
5449        {"(function(", ") {})();"},
5450        {"function fn(", ") {}; fn();"},
5451        {"function fn(", ") {}; fn();"},
5452        {NULL, NULL}};
5453
5454   const char* data[] = {
5455       "a, a",
5456       "a, a, a",
5457       "b, a, a",
5458       "a, b, c, c",
5459       "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
5460       NULL};
5461
5462   static const ParserFlag always_flags[] = { kAllowStrongMode };
5463   RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
5464                     arraysize(always_flags));
5465   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, NULL, 0);
5466 }
5467
5468
5469 TEST(VarForbiddenInStrongMode) {
5470   const char* strong_context_data[][2] =
5471       {{"'use strong'; ", ""},
5472        {"function f() {'use strong'; ", "}"},
5473        {"function f() {'use strong';  while (true) { ", "} }"},
5474        {NULL, NULL}};
5475
5476   const char* strict_context_data[][2] =
5477       {{"'use strict'; ", ""},
5478        {"function f() {'use strict'; ", "}"},
5479        {"function f() {'use strict'; while (true) { ", "} }"},
5480        {NULL, NULL}};
5481
5482   const char* sloppy_context_data[][2] =
5483       {{"", ""},
5484        {"function f() { ", "}"},
5485        {NULL, NULL}};
5486
5487   const char* var_declarations[] = {
5488     "var x = 0;",
5489     "for (var i = 0; i < 10; i++) { }",
5490     NULL};
5491
5492   const char* let_declarations[] = {
5493     "let x = 0;",
5494     "for (let i = 0; i < 10; i++) { }",
5495     NULL};
5496
5497   const char* const_declarations[] = {
5498     "const x = 0;",
5499     NULL};
5500
5501   static const ParserFlag always_flags[] = {kAllowStrongMode,
5502                                             kAllowHarmonyScoping};
5503   RunParserSyncTest(strong_context_data, var_declarations, kError, NULL, 0,
5504                     always_flags, arraysize(always_flags));
5505   RunParserSyncTest(strong_context_data, let_declarations, kSuccess, NULL, 0,
5506                     always_flags, arraysize(always_flags));
5507   RunParserSyncTest(strong_context_data, const_declarations, kSuccess, NULL, 0,
5508                     always_flags, arraysize(always_flags));
5509
5510   RunParserSyncTest(strict_context_data, var_declarations, kSuccess, NULL, 0,
5511                     always_flags, arraysize(always_flags));
5512   RunParserSyncTest(strict_context_data, let_declarations, kSuccess, NULL, 0,
5513                     always_flags, arraysize(always_flags));
5514
5515   RunParserSyncTest(sloppy_context_data, var_declarations, kSuccess, NULL, 0,
5516                     always_flags, arraysize(always_flags));
5517   // At the moment, let declarations are only available in strict mode.
5518   RunParserSyncTest(sloppy_context_data, let_declarations, kError, NULL, 0,
5519                     always_flags, arraysize(always_flags));
5520 }
5521
5522
5523 TEST(StrongEmptySubStatements) {
5524   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
5525   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
5526   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
5527
5528   const char* data[] = {
5529       "if (1);",
5530       "if (1) {} else;",
5531       "while (1);",
5532       "do; while (1);",
5533       "for (;;);",
5534       "for (x in []);",
5535       "for (x of []);",
5536       "for (const x = 0;;);",
5537       "for (const x in []);",
5538       "for (const x of []);",
5539       NULL};
5540
5541   static const ParserFlag always_flags[] = {
5542       kAllowStrongMode, kAllowHarmonyScoping
5543   };
5544   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
5545                     arraysize(always_flags));
5546   RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
5547                     arraysize(always_flags));
5548   RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
5549                     arraysize(always_flags));
5550 }
5551
5552
5553 TEST(StrongForIn) {
5554   const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
5555   const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
5556   const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
5557
5558   const char* data[] = {
5559       "for (x in []) {}",
5560       "for (const x in []) {}",
5561       NULL};
5562
5563   static const ParserFlag always_flags[] = {
5564       kAllowStrongMode, kAllowHarmonyScoping
5565   };
5566   RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
5567                     arraysize(always_flags));
5568   RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
5569                     arraysize(always_flags));
5570   RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
5571                     arraysize(always_flags));
5572 }