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