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-value-factory.h"
35#include "src/compiler.h"
36#include "src/execution.h"
37#include "src/isolate.h"
38#include "src/objects.h"
39#include "src/parser.h"
40#include "src/preparser.h"
41#include "src/rewriter.h"
42#include "src/scanner-character-streams.h"
43#include "src/token.h"
44#include "src/utils.h"
45
46#include "test/cctest/cctest.h"
47
48TEST(ScanKeywords) {
49  struct KeywordToken {
50    const char* keyword;
51    i::Token::Value token;
52  };
53
54  static const KeywordToken keywords[] = {
55#define KEYWORD(t, s, d) { s, i::Token::t },
56      TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
57#undef KEYWORD
58      { NULL, i::Token::IDENTIFIER }
59  };
60
61  KeywordToken key_token;
62  i::UnicodeCache unicode_cache;
63  i::byte buffer[32];
64  for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
65    const i::byte* keyword =
66        reinterpret_cast<const i::byte*>(key_token.keyword);
67    int length = i::StrLength(key_token.keyword);
68    CHECK(static_cast<int>(sizeof(buffer)) >= length);
69    {
70      i::Utf8ToUtf16CharacterStream stream(keyword, length);
71      i::Scanner scanner(&unicode_cache);
72      // The scanner should parse Harmony keywords for this test.
73      scanner.SetHarmonyScoping(true);
74      scanner.SetHarmonyModules(true);
75      scanner.SetHarmonyClasses(true);
76      scanner.Initialize(&stream);
77      CHECK_EQ(key_token.token, scanner.Next());
78      CHECK_EQ(i::Token::EOS, scanner.Next());
79    }
80    // Removing characters will make keyword matching fail.
81    {
82      i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
83      i::Scanner scanner(&unicode_cache);
84      scanner.Initialize(&stream);
85      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
86      CHECK_EQ(i::Token::EOS, scanner.Next());
87    }
88    // Adding characters will make keyword matching fail.
89    static const char chars_to_append[] = { 'z', '0', '_' };
90    for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
91      i::MemMove(buffer, keyword, length);
92      buffer[length] = chars_to_append[j];
93      i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
94      i::Scanner scanner(&unicode_cache);
95      scanner.Initialize(&stream);
96      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
97      CHECK_EQ(i::Token::EOS, scanner.Next());
98    }
99    // Replacing characters will make keyword matching fail.
100    {
101      i::MemMove(buffer, keyword, length);
102      buffer[length - 1] = '_';
103      i::Utf8ToUtf16CharacterStream stream(buffer, length);
104      i::Scanner scanner(&unicode_cache);
105      scanner.Initialize(&stream);
106      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
107      CHECK_EQ(i::Token::EOS, scanner.Next());
108    }
109  }
110}
111
112
113TEST(ScanHTMLEndComments) {
114  v8::V8::Initialize();
115  v8::Isolate* isolate = CcTest::isolate();
116  v8::HandleScope handles(isolate);
117
118  // Regression test. See:
119  //    http://code.google.com/p/chromium/issues/detail?id=53548
120  // Tests that --> is correctly interpreted as comment-to-end-of-line if there
121  // is only whitespace before it on the line (with comments considered as
122  // whitespace, even a multiline-comment containing a newline).
123  // This was not the case if it occurred before the first real token
124  // in the input.
125  const char* tests[] = {
126      // Before first real token.
127      "--> is eol-comment\nvar y = 37;\n",
128      "\n --> is eol-comment\nvar y = 37;\n",
129      "/* precomment */ --> is eol-comment\nvar y = 37;\n",
130      "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
131      // After first real token.
132      "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
133      "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
134      NULL
135  };
136
137  const char* fail_tests[] = {
138      "x --> is eol-comment\nvar y = 37;\n",
139      "\"\\n\" --> is eol-comment\nvar y = 37;\n",
140      "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
141      "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
142      "var x = 42; --> is eol-comment\nvar y = 37;\n",
143      "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
144      NULL
145  };
146
147  // Parser/Scanner needs a stack limit.
148  CcTest::i_isolate()->stack_guard()->SetStackLimit(
149      i::GetCurrentStackPosition() - 128 * 1024);
150  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
151  for (int i = 0; tests[i]; i++) {
152    const i::byte* source =
153        reinterpret_cast<const i::byte*>(tests[i]);
154    i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
155    i::CompleteParserRecorder log;
156    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
157    scanner.Initialize(&stream);
158    i::PreParser preparser(&scanner, &log, stack_limit);
159    preparser.set_allow_lazy(true);
160    i::PreParser::PreParseResult result = preparser.PreParseProgram();
161    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
162    CHECK(!log.HasError());
163  }
164
165  for (int i = 0; fail_tests[i]; i++) {
166    const i::byte* source =
167        reinterpret_cast<const i::byte*>(fail_tests[i]);
168    i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
169    i::CompleteParserRecorder log;
170    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
171    scanner.Initialize(&stream);
172    i::PreParser preparser(&scanner, &log, stack_limit);
173    preparser.set_allow_lazy(true);
174    i::PreParser::PreParseResult result = preparser.PreParseProgram();
175    // Even in the case of a syntax error, kPreParseSuccess is returned.
176    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
177    CHECK(log.HasError());
178  }
179}
180
181
182class ScriptResource : public v8::String::ExternalOneByteStringResource {
183 public:
184  ScriptResource(const char* data, size_t length)
185      : data_(data), length_(length) { }
186
187  const char* data() const { return data_; }
188  size_t length() const { return length_; }
189
190 private:
191  const char* data_;
192  size_t length_;
193};
194
195
196TEST(UsingCachedData) {
197  v8::Isolate* isolate = CcTest::isolate();
198  v8::HandleScope handles(isolate);
199  v8::Local<v8::Context> context = v8::Context::New(isolate);
200  v8::Context::Scope context_scope(context);
201  CcTest::i_isolate()->stack_guard()->SetStackLimit(
202      i::GetCurrentStackPosition() - 128 * 1024);
203
204  // Source containing functions that might be lazily compiled  and all types
205  // of symbols (string, propertyName, regexp).
206  const char* source =
207      "var x = 42;"
208      "function foo(a) { return function nolazy(b) { return a + b; } }"
209      "function bar(a) { if (a) return function lazy(b) { return b; } }"
210      "var z = {'string': 'string literal', bareword: 'propertyName', "
211      "         42: 'number literal', for: 'keyword as propertyName', "
212      "         f\\u006fr: 'keyword propertyname with escape'};"
213      "var v = /RegExp Literal/;"
214      "var w = /RegExp Literal\\u0020With Escape/gin;"
215      "var y = { get getter() { return 42; }, "
216      "          set setter(v) { this.value = v; }};"
217      "var f = a => function (b) { return a + b; };"
218      "var g = a => b => a + b;";
219  int source_length = i::StrLength(source);
220
221  // ScriptResource will be deleted when the corresponding String is GCd.
222  v8::ScriptCompiler::Source script_source(v8::String::NewExternal(
223      isolate, new ScriptResource(source, source_length)));
224  i::FLAG_harmony_arrow_functions = true;
225  i::FLAG_min_preparse_length = 0;
226  v8::ScriptCompiler::Compile(isolate, &script_source,
227                              v8::ScriptCompiler::kProduceParserCache);
228  CHECK(script_source.GetCachedData());
229
230  // Compile the script again, using the cached data.
231  bool lazy_flag = i::FLAG_lazy;
232  i::FLAG_lazy = true;
233  v8::ScriptCompiler::Compile(isolate, &script_source,
234                              v8::ScriptCompiler::kConsumeParserCache);
235  i::FLAG_lazy = false;
236  v8::ScriptCompiler::CompileUnbound(isolate, &script_source,
237                                     v8::ScriptCompiler::kConsumeParserCache);
238  i::FLAG_lazy = lazy_flag;
239}
240
241
242TEST(PreparseFunctionDataIsUsed) {
243  // This tests that we actually do use the function data generated by the
244  // preparser.
245
246  // Make preparsing work for short scripts.
247  i::FLAG_min_preparse_length = 0;
248  i::FLAG_harmony_arrow_functions = true;
249
250  v8::Isolate* isolate = CcTest::isolate();
251  v8::HandleScope handles(isolate);
252  v8::Local<v8::Context> context = v8::Context::New(isolate);
253  v8::Context::Scope context_scope(context);
254  CcTest::i_isolate()->stack_guard()->SetStackLimit(
255      i::GetCurrentStackPosition() - 128 * 1024);
256
257  const char* good_code[] = {
258      "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
259      "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
260  };
261
262  // Insert a syntax error inside the lazy function.
263  const char* bad_code[] = {
264      "function this_is_lazy() { if (   } function foo() { return 25; } foo();",
265      "var this_is_lazy = () => { if (   }; var foo = () => 25; foo();",
266  };
267
268  for (unsigned i = 0; i < arraysize(good_code); i++) {
269    v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
270    v8::ScriptCompiler::Compile(isolate, &good_source,
271                                v8::ScriptCompiler::kProduceDataToCache);
272
273    const v8::ScriptCompiler::CachedData* cached_data =
274        good_source.GetCachedData();
275    CHECK(cached_data->data != NULL);
276    CHECK_GT(cached_data->length, 0);
277
278    // Now compile the erroneous code with the good preparse data. If the
279    // preparse data is used, the lazy function is skipped and it should
280    // compile fine.
281    v8::ScriptCompiler::Source bad_source(
282        v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
283                                 cached_data->data, cached_data->length));
284    v8::Local<v8::Value> result =
285        v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
286    CHECK(result->IsInt32());
287    CHECK_EQ(25, result->Int32Value());
288  }
289}
290
291
292TEST(StandAlonePreParser) {
293  v8::V8::Initialize();
294
295  CcTest::i_isolate()->stack_guard()->SetStackLimit(
296      i::GetCurrentStackPosition() - 128 * 1024);
297
298  const char* programs[] = {
299      "{label: 42}",
300      "var x = 42;",
301      "function foo(x, y) { return x + y; }",
302      "%ArgleBargle(glop);",
303      "var x = new new Function('this.x = 42');",
304      "var f = (x, y) => x + y;",
305      NULL
306  };
307
308  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
309  for (int i = 0; programs[i]; i++) {
310    const char* program = programs[i];
311    i::Utf8ToUtf16CharacterStream stream(
312        reinterpret_cast<const i::byte*>(program),
313        static_cast<unsigned>(strlen(program)));
314    i::CompleteParserRecorder log;
315    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
316    scanner.Initialize(&stream);
317
318    i::PreParser preparser(&scanner, &log, stack_limit);
319    preparser.set_allow_lazy(true);
320    preparser.set_allow_natives_syntax(true);
321    preparser.set_allow_arrow_functions(true);
322    i::PreParser::PreParseResult result = preparser.PreParseProgram();
323    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
324    CHECK(!log.HasError());
325  }
326}
327
328
329TEST(StandAlonePreParserNoNatives) {
330  v8::V8::Initialize();
331
332  CcTest::i_isolate()->stack_guard()->SetStackLimit(
333      i::GetCurrentStackPosition() - 128 * 1024);
334
335  const char* programs[] = {
336      "%ArgleBargle(glop);",
337      "var x = %_IsSmi(42);",
338      NULL
339  };
340
341  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
342  for (int i = 0; programs[i]; i++) {
343    const char* program = programs[i];
344    i::Utf8ToUtf16CharacterStream stream(
345        reinterpret_cast<const i::byte*>(program),
346        static_cast<unsigned>(strlen(program)));
347    i::CompleteParserRecorder log;
348    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
349    scanner.Initialize(&stream);
350
351    // Preparser defaults to disallowing natives syntax.
352    i::PreParser preparser(&scanner, &log, stack_limit);
353    preparser.set_allow_lazy(true);
354    i::PreParser::PreParseResult result = preparser.PreParseProgram();
355    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
356    CHECK(log.HasError());
357  }
358}
359
360
361TEST(PreparsingObjectLiterals) {
362  // Regression test for a bug where the symbol stream produced by PreParser
363  // didn't match what Parser wanted to consume.
364  v8::Isolate* isolate = CcTest::isolate();
365  v8::HandleScope handles(isolate);
366  v8::Local<v8::Context> context = v8::Context::New(isolate);
367  v8::Context::Scope context_scope(context);
368  CcTest::i_isolate()->stack_guard()->SetStackLimit(
369      i::GetCurrentStackPosition() - 128 * 1024);
370
371  {
372    const char* source = "var myo = {if: \"foo\"}; myo.if;";
373    v8::Local<v8::Value> result = ParserCacheCompileRun(source);
374    CHECK(result->IsString());
375    v8::String::Utf8Value utf8(result);
376    CHECK_EQ("foo", *utf8);
377  }
378
379  {
380    const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
381    v8::Local<v8::Value> result = ParserCacheCompileRun(source);
382    CHECK(result->IsString());
383    v8::String::Utf8Value utf8(result);
384    CHECK_EQ("foo", *utf8);
385  }
386
387  {
388    const char* source = "var myo = {1: \"foo\"}; myo[1];";
389    v8::Local<v8::Value> result = ParserCacheCompileRun(source);
390    CHECK(result->IsString());
391    v8::String::Utf8Value utf8(result);
392    CHECK_EQ("foo", *utf8);
393  }
394}
395
396
397TEST(RegressChromium62639) {
398  v8::V8::Initialize();
399  i::Isolate* isolate = CcTest::i_isolate();
400
401  isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
402                                        128 * 1024);
403
404  const char* program = "var x = 'something';\n"
405                        "escape: function() {}";
406  // Fails parsing expecting an identifier after "function".
407  // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
408  // and then used the invalid currently scanned literal. This always
409  // failed in debug mode, and sometimes crashed in release mode.
410
411  i::Utf8ToUtf16CharacterStream stream(
412      reinterpret_cast<const i::byte*>(program),
413      static_cast<unsigned>(strlen(program)));
414  i::CompleteParserRecorder log;
415  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
416  scanner.Initialize(&stream);
417  i::PreParser preparser(&scanner, &log,
418                         CcTest::i_isolate()->stack_guard()->real_climit());
419  preparser.set_allow_lazy(true);
420  i::PreParser::PreParseResult result = preparser.PreParseProgram();
421  // Even in the case of a syntax error, kPreParseSuccess is returned.
422  CHECK_EQ(i::PreParser::kPreParseSuccess, result);
423  CHECK(log.HasError());
424}
425
426
427TEST(Regress928) {
428  v8::V8::Initialize();
429  i::Isolate* isolate = CcTest::i_isolate();
430  i::Factory* factory = isolate->factory();
431
432  // Preparsing didn't consider the catch clause of a try statement
433  // as with-content, which made it assume that a function inside
434  // the block could be lazily compiled, and an extra, unexpected,
435  // entry was added to the data.
436  isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
437                                        128 * 1024);
438
439  const char* program =
440      "try { } catch (e) { var foo = function () { /* first */ } }"
441      "var bar = function () { /* second */ }";
442
443  v8::HandleScope handles(CcTest::isolate());
444  i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
445  i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
446  i::CompleteParserRecorder log;
447  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
448  scanner.Initialize(&stream);
449  i::PreParser preparser(&scanner, &log,
450                         CcTest::i_isolate()->stack_guard()->real_climit());
451  preparser.set_allow_lazy(true);
452  i::PreParser::PreParseResult result = preparser.PreParseProgram();
453  CHECK_EQ(i::PreParser::kPreParseSuccess, result);
454  i::ScriptData* sd = log.GetScriptData();
455  i::ParseData pd(sd);
456  pd.Initialize();
457
458  int first_function =
459      static_cast<int>(strstr(program, "function") - program);
460  int first_lbrace = first_function + i::StrLength("function () ");
461  CHECK_EQ('{', program[first_lbrace]);
462  i::FunctionEntry entry1 = pd.GetFunctionEntry(first_lbrace);
463  CHECK(!entry1.is_valid());
464
465  int second_function =
466      static_cast<int>(strstr(program + first_lbrace, "function") - program);
467  int second_lbrace =
468      second_function + i::StrLength("function () ");
469  CHECK_EQ('{', program[second_lbrace]);
470  i::FunctionEntry entry2 = pd.GetFunctionEntry(second_lbrace);
471  CHECK(entry2.is_valid());
472  CHECK_EQ('}', program[entry2.end_pos() - 1]);
473  delete sd;
474}
475
476
477TEST(PreParseOverflow) {
478  v8::V8::Initialize();
479
480  CcTest::i_isolate()->stack_guard()->SetStackLimit(
481      i::GetCurrentStackPosition() - 128 * 1024);
482
483  size_t kProgramSize = 1024 * 1024;
484  i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
485  memset(program.get(), '(', kProgramSize);
486  program[kProgramSize] = '\0';
487
488  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
489
490  i::Utf8ToUtf16CharacterStream stream(
491      reinterpret_cast<const i::byte*>(program.get()),
492      static_cast<unsigned>(kProgramSize));
493  i::CompleteParserRecorder log;
494  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
495  scanner.Initialize(&stream);
496
497  i::PreParser preparser(&scanner, &log, stack_limit);
498  preparser.set_allow_lazy(true);
499  preparser.set_allow_arrow_functions(true);
500  i::PreParser::PreParseResult result = preparser.PreParseProgram();
501  CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
502}
503
504
505class TestExternalResource: public v8::String::ExternalStringResource {
506 public:
507  explicit TestExternalResource(uint16_t* data, int length)
508      : data_(data), length_(static_cast<size_t>(length)) { }
509
510  ~TestExternalResource() { }
511
512  const uint16_t* data() const {
513    return data_;
514  }
515
516  size_t length() const {
517    return length_;
518  }
519 private:
520  uint16_t* data_;
521  size_t length_;
522};
523
524
525#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
526
527void TestCharacterStream(const char* one_byte_source, unsigned length,
528                         unsigned start = 0, unsigned end = 0) {
529  if (end == 0) end = length;
530  unsigned sub_length = end - start;
531  i::Isolate* isolate = CcTest::i_isolate();
532  i::Factory* factory = isolate->factory();
533  i::HandleScope test_scope(isolate);
534  i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
535  for (unsigned i = 0; i < length; i++) {
536    uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
537  }
538  i::Vector<const char> one_byte_vector(one_byte_source,
539                                        static_cast<int>(length));
540  i::Handle<i::String> one_byte_string =
541      factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
542  TestExternalResource resource(uc16_buffer.get(), length);
543  i::Handle<i::String> uc16_string(
544      factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
545
546  i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
547      i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
548  i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
549                                                     end);
550  i::Utf8ToUtf16CharacterStream utf8_stream(
551      reinterpret_cast<const i::byte*>(one_byte_source), end);
552  utf8_stream.SeekForward(start);
553
554  unsigned i = start;
555  while (i < end) {
556    // Read streams one char at a time
557    CHECK_EQU(i, uc16_stream.pos());
558    CHECK_EQU(i, string_stream.pos());
559    CHECK_EQU(i, utf8_stream.pos());
560    int32_t c0 = one_byte_source[i];
561    int32_t c1 = uc16_stream.Advance();
562    int32_t c2 = string_stream.Advance();
563    int32_t c3 = utf8_stream.Advance();
564    i++;
565    CHECK_EQ(c0, c1);
566    CHECK_EQ(c0, c2);
567    CHECK_EQ(c0, c3);
568    CHECK_EQU(i, uc16_stream.pos());
569    CHECK_EQU(i, string_stream.pos());
570    CHECK_EQU(i, utf8_stream.pos());
571  }
572  while (i > start + sub_length / 4) {
573    // Pushback, re-read, pushback again.
574    int32_t c0 = one_byte_source[i - 1];
575    CHECK_EQU(i, uc16_stream.pos());
576    CHECK_EQU(i, string_stream.pos());
577    CHECK_EQU(i, utf8_stream.pos());
578    uc16_stream.PushBack(c0);
579    string_stream.PushBack(c0);
580    utf8_stream.PushBack(c0);
581    i--;
582    CHECK_EQU(i, uc16_stream.pos());
583    CHECK_EQU(i, string_stream.pos());
584    CHECK_EQU(i, utf8_stream.pos());
585    int32_t c1 = uc16_stream.Advance();
586    int32_t c2 = string_stream.Advance();
587    int32_t c3 = utf8_stream.Advance();
588    i++;
589    CHECK_EQU(i, uc16_stream.pos());
590    CHECK_EQU(i, string_stream.pos());
591    CHECK_EQU(i, utf8_stream.pos());
592    CHECK_EQ(c0, c1);
593    CHECK_EQ(c0, c2);
594    CHECK_EQ(c0, c3);
595    uc16_stream.PushBack(c0);
596    string_stream.PushBack(c0);
597    utf8_stream.PushBack(c0);
598    i--;
599    CHECK_EQU(i, uc16_stream.pos());
600    CHECK_EQU(i, string_stream.pos());
601    CHECK_EQU(i, utf8_stream.pos());
602  }
603  unsigned halfway = start + sub_length / 2;
604  uc16_stream.SeekForward(halfway - i);
605  string_stream.SeekForward(halfway - i);
606  utf8_stream.SeekForward(halfway - i);
607  i = halfway;
608  CHECK_EQU(i, uc16_stream.pos());
609  CHECK_EQU(i, string_stream.pos());
610  CHECK_EQU(i, utf8_stream.pos());
611
612  while (i < end) {
613    // Read streams one char at a time
614    CHECK_EQU(i, uc16_stream.pos());
615    CHECK_EQU(i, string_stream.pos());
616    CHECK_EQU(i, utf8_stream.pos());
617    int32_t c0 = one_byte_source[i];
618    int32_t c1 = uc16_stream.Advance();
619    int32_t c2 = string_stream.Advance();
620    int32_t c3 = utf8_stream.Advance();
621    i++;
622    CHECK_EQ(c0, c1);
623    CHECK_EQ(c0, c2);
624    CHECK_EQ(c0, c3);
625    CHECK_EQU(i, uc16_stream.pos());
626    CHECK_EQU(i, string_stream.pos());
627    CHECK_EQU(i, utf8_stream.pos());
628  }
629
630  int32_t c1 = uc16_stream.Advance();
631  int32_t c2 = string_stream.Advance();
632  int32_t c3 = utf8_stream.Advance();
633  CHECK_LT(c1, 0);
634  CHECK_LT(c2, 0);
635  CHECK_LT(c3, 0);
636}
637
638
639TEST(CharacterStreams) {
640  v8::Isolate* isolate = CcTest::isolate();
641  v8::HandleScope handles(isolate);
642  v8::Local<v8::Context> context = v8::Context::New(isolate);
643  v8::Context::Scope context_scope(context);
644
645  TestCharacterStream("abc\0\n\r\x7f", 7);
646  static const unsigned kBigStringSize = 4096;
647  char buffer[kBigStringSize + 1];
648  for (unsigned i = 0; i < kBigStringSize; i++) {
649    buffer[i] = static_cast<char>(i & 0x7f);
650  }
651  TestCharacterStream(buffer, kBigStringSize);
652
653  TestCharacterStream(buffer, kBigStringSize, 576, 3298);
654
655  TestCharacterStream("\0", 1);
656  TestCharacterStream("", 0);
657}
658
659
660TEST(Utf8CharacterStream) {
661  static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
662  static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
663
664  static const int kAllUtf8CharsSize =
665      (unibrow::Utf8::kMaxOneByteChar + 1) +
666      (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
667      (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
668  static const unsigned kAllUtf8CharsSizeU =
669      static_cast<unsigned>(kAllUtf8CharsSize);
670
671  char buffer[kAllUtf8CharsSizeU];
672  unsigned cursor = 0;
673  for (int i = 0; i <= kMaxUC16Char; i++) {
674    cursor += unibrow::Utf8::Encode(buffer + cursor,
675                                    i,
676                                    unibrow::Utf16::kNoPreviousCharacter);
677  }
678  DCHECK(cursor == kAllUtf8CharsSizeU);
679
680  i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
681                                       kAllUtf8CharsSizeU);
682  for (int i = 0; i <= kMaxUC16Char; i++) {
683    CHECK_EQU(i, stream.pos());
684    int32_t c = stream.Advance();
685    CHECK_EQ(i, c);
686    CHECK_EQU(i + 1, stream.pos());
687  }
688  for (int i = kMaxUC16Char; i >= 0; i--) {
689    CHECK_EQU(i + 1, stream.pos());
690    stream.PushBack(i);
691    CHECK_EQU(i, stream.pos());
692  }
693  int i = 0;
694  while (stream.pos() < kMaxUC16CharU) {
695    CHECK_EQU(i, stream.pos());
696    unsigned progress = stream.SeekForward(12);
697    i += progress;
698    int32_t c = stream.Advance();
699    if (i <= kMaxUC16Char) {
700      CHECK_EQ(i, c);
701    } else {
702      CHECK_EQ(-1, c);
703    }
704    i += 1;
705    CHECK_EQU(i, stream.pos());
706  }
707}
708
709#undef CHECK_EQU
710
711void TestStreamScanner(i::Utf16CharacterStream* stream,
712                       i::Token::Value* expected_tokens,
713                       int skip_pos = 0,  // Zero means not skipping.
714                       int skip_to = 0) {
715  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
716  scanner.Initialize(stream);
717
718  int i = 0;
719  do {
720    i::Token::Value expected = expected_tokens[i];
721    i::Token::Value actual = scanner.Next();
722    CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
723    if (scanner.location().end_pos == skip_pos) {
724      scanner.SeekForward(skip_to);
725    }
726    i++;
727  } while (expected_tokens[i] != i::Token::ILLEGAL);
728}
729
730
731TEST(StreamScanner) {
732  v8::V8::Initialize();
733
734  const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
735  i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
736                                        static_cast<unsigned>(strlen(str1)));
737  i::Token::Value expectations1[] = {
738      i::Token::LBRACE,
739      i::Token::IDENTIFIER,
740      i::Token::IDENTIFIER,
741      i::Token::FOR,
742      i::Token::COLON,
743      i::Token::MUL,
744      i::Token::DIV,
745      i::Token::LT,
746      i::Token::SUB,
747      i::Token::IDENTIFIER,
748      i::Token::EOS,
749      i::Token::ILLEGAL
750  };
751  TestStreamScanner(&stream1, expectations1, 0, 0);
752
753  const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
754  i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
755                                        static_cast<unsigned>(strlen(str2)));
756  i::Token::Value expectations2[] = {
757      i::Token::CASE,
758      i::Token::DEFAULT,
759      i::Token::CONST,
760      i::Token::LBRACE,
761      // Skipped part here
762      i::Token::RBRACE,
763      i::Token::DO,
764      i::Token::EOS,
765      i::Token::ILLEGAL
766  };
767  DCHECK_EQ('{', str2[19]);
768  DCHECK_EQ('}', str2[37]);
769  TestStreamScanner(&stream2, expectations2, 20, 37);
770
771  const char* str3 = "{}}}}";
772  i::Token::Value expectations3[] = {
773      i::Token::LBRACE,
774      i::Token::RBRACE,
775      i::Token::RBRACE,
776      i::Token::RBRACE,
777      i::Token::RBRACE,
778      i::Token::EOS,
779      i::Token::ILLEGAL
780  };
781  // Skip zero-four RBRACEs.
782  for (int i = 0; i <= 4; i++) {
783     expectations3[6 - i] = i::Token::ILLEGAL;
784     expectations3[5 - i] = i::Token::EOS;
785     i::Utf8ToUtf16CharacterStream stream3(
786         reinterpret_cast<const i::byte*>(str3),
787         static_cast<unsigned>(strlen(str3)));
788     TestStreamScanner(&stream3, expectations3, 1, 1 + i);
789  }
790}
791
792
793void TestScanRegExp(const char* re_source, const char* expected) {
794  i::Utf8ToUtf16CharacterStream stream(
795       reinterpret_cast<const i::byte*>(re_source),
796       static_cast<unsigned>(strlen(re_source)));
797  i::HandleScope scope(CcTest::i_isolate());
798  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
799  scanner.Initialize(&stream);
800
801  i::Token::Value start = scanner.peek();
802  CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
803  CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
804  scanner.Next();  // Current token is now the regexp literal.
805  i::Zone zone(CcTest::i_isolate());
806  i::AstValueFactory ast_value_factory(&zone,
807                                       CcTest::i_isolate()->heap()->HashSeed());
808  ast_value_factory.Internalize(CcTest::i_isolate());
809  i::Handle<i::String> val =
810      scanner.CurrentSymbol(&ast_value_factory)->string();
811  i::DisallowHeapAllocation no_alloc;
812  i::String::FlatContent content = val->GetFlatContent();
813  CHECK(content.IsOneByte());
814  i::Vector<const uint8_t> actual = content.ToOneByteVector();
815  for (int i = 0; i < actual.length(); i++) {
816    CHECK_NE('\0', expected[i]);
817    CHECK_EQ(expected[i], actual[i]);
818  }
819}
820
821
822TEST(RegExpScanning) {
823  v8::V8::Initialize();
824
825  // RegExp token with added garbage at the end. The scanner should only
826  // scan the RegExp until the terminating slash just before "flipperwald".
827  TestScanRegExp("/b/flipperwald", "b");
828  // Incomplete escape sequences doesn't hide the terminating slash.
829  TestScanRegExp("/\\x/flipperwald", "\\x");
830  TestScanRegExp("/\\u/flipperwald", "\\u");
831  TestScanRegExp("/\\u1/flipperwald", "\\u1");
832  TestScanRegExp("/\\u12/flipperwald", "\\u12");
833  TestScanRegExp("/\\u123/flipperwald", "\\u123");
834  TestScanRegExp("/\\c/flipperwald", "\\c");
835  TestScanRegExp("/\\c//flipperwald", "\\c");
836  // Slashes inside character classes are not terminating.
837  TestScanRegExp("/[/]/flipperwald", "[/]");
838  TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
839  // Incomplete escape sequences inside a character class doesn't hide
840  // the end of the character class.
841  TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
842  TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
843  TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
844  TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
845  TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
846  TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
847  TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
848  TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
849  // Escaped ']'s wont end the character class.
850  TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
851  // Escaped slashes are not terminating.
852  TestScanRegExp("/\\//flipperwald", "\\/");
853  // Starting with '=' works too.
854  TestScanRegExp("/=/", "=");
855  TestScanRegExp("/=?/", "=?");
856}
857
858
859static int Utf8LengthHelper(const char* s) {
860  int len = i::StrLength(s);
861  int character_length = len;
862  for (int i = 0; i < len; i++) {
863    unsigned char c = s[i];
864    int input_offset = 0;
865    int output_adjust = 0;
866    if (c > 0x7f) {
867      if (c < 0xc0) continue;
868      if (c >= 0xf0) {
869        if (c >= 0xf8) {
870          // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
871          // byte.
872          continue;  // Handle first UTF-8 byte.
873        }
874        if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
875          // This 4 byte sequence could have been coded as a 3 byte sequence.
876          // Record a single kBadChar for the first byte and continue.
877          continue;
878        }
879        input_offset = 3;
880        // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
881        character_length -= 2;
882      } else if (c >= 0xe0) {
883        if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
884          // This 3 byte sequence could have been coded as a 2 byte sequence.
885          // Record a single kBadChar for the first byte and continue.
886          continue;
887        }
888        input_offset = 2;
889        // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
890        output_adjust = 2;
891      } else {
892        if ((c & 0x1e) == 0) {
893          // This 2 byte sequence could have been coded as a 1 byte sequence.
894          // Record a single kBadChar for the first byte and continue.
895          continue;
896        }
897        input_offset = 1;
898        // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
899        output_adjust = 1;
900      }
901      bool bad = false;
902      for (int j = 1; j <= input_offset; j++) {
903        if ((s[i + j] & 0xc0) != 0x80) {
904          // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
905          // which is a single UTF-16 code unit.
906          bad = true;
907          break;
908        }
909      }
910      if (!bad) {
911        i += input_offset;
912        character_length -= output_adjust;
913      }
914    }
915  }
916  return character_length;
917}
918
919
920TEST(ScopePositions) {
921  v8::internal::FLAG_harmony_scoping = true;
922
923  // Test the parser for correctly setting the start and end positions
924  // of a scope. We check the scope positions of exactly one scope
925  // nested in the global scope of a program. 'inner source' is the
926  // source code that determines the part of the source belonging
927  // to the nested scope. 'outer_prefix' and 'outer_suffix' are
928  // parts of the source that belong to the global scope.
929  struct SourceData {
930    const char* outer_prefix;
931    const char* inner_source;
932    const char* outer_suffix;
933    i::ScopeType scope_type;
934    i::StrictMode strict_mode;
935  };
936
937  const SourceData source_data[] = {
938    { "  with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
939    { "  with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
940    { "  with ({}) ", "{\n"
941      "    block;\n"
942      "  }", "\n"
943      "  more;", i::WITH_SCOPE, i::SLOPPY },
944    { "  with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
945    { "  with ({}) ", "statement", "\n"
946      "  more;", i::WITH_SCOPE, i::SLOPPY },
947    { "  with ({})\n"
948      "    ", "statement;", "\n"
949      "  more;", i::WITH_SCOPE, i::SLOPPY },
950    { "  try {} catch ", "(e) { block; }", " more;",
951      i::CATCH_SCOPE, i::SLOPPY },
952    { "  try {} catch ", "(e) { block; }", "; more;",
953      i::CATCH_SCOPE, i::SLOPPY },
954    { "  try {} catch ", "(e) {\n"
955      "    block;\n"
956      "  }", "\n"
957      "  more;", i::CATCH_SCOPE, i::SLOPPY },
958    { "  try {} catch ", "(e) { block; }", " finally { block; } more;",
959      i::CATCH_SCOPE, i::SLOPPY },
960    { "  start;\n"
961      "  ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
962    { "  start;\n"
963      "  ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
964    { "  start;\n"
965      "  ", "{\n"
966      "    let block;\n"
967      "  }", "\n"
968      "  more;", i::BLOCK_SCOPE, i::STRICT },
969    { "  start;\n"
970      "  function fun", "(a,b) { infunction; }", " more;",
971      i::FUNCTION_SCOPE, i::SLOPPY },
972    { "  start;\n"
973      "  function fun", "(a,b) {\n"
974      "    infunction;\n"
975      "  }", "\n"
976      "  more;", i::FUNCTION_SCOPE, i::SLOPPY },
977    // TODO(aperez): Change to use i::ARROW_SCOPE when implemented
978    { "  start;\n", "(a,b) => a + b", "; more;",
979      i::FUNCTION_SCOPE, i::SLOPPY },
980    { "  start;\n", "(a,b) => { return a+b; }", "\nmore;",
981      i::FUNCTION_SCOPE, i::SLOPPY },
982    { "  start;\n"
983      "  (function fun", "(a,b) { infunction; }", ")();",
984      i::FUNCTION_SCOPE, i::SLOPPY },
985    { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
986      i::BLOCK_SCOPE, i::STRICT },
987    { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
988      i::BLOCK_SCOPE, i::STRICT },
989    { "  for ", "(let x = 1 ; x < 10; ++ x) {\n"
990      "    block;\n"
991      "  }", "\n"
992      "  more;", i::BLOCK_SCOPE, i::STRICT },
993    { "  for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
994      i::BLOCK_SCOPE, i::STRICT },
995    { "  for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
996      "  more;", i::BLOCK_SCOPE, i::STRICT },
997    { "  for ", "(let x = 1 ; x < 10; ++ x)\n"
998      "    statement;", "\n"
999      "  more;", i::BLOCK_SCOPE, i::STRICT },
1000    { "  for ", "(let x in {}) { block; }", " more;",
1001      i::BLOCK_SCOPE, i::STRICT },
1002    { "  for ", "(let x in {}) { block; }", "; more;",
1003      i::BLOCK_SCOPE, i::STRICT },
1004    { "  for ", "(let x in {}) {\n"
1005      "    block;\n"
1006      "  }", "\n"
1007      "  more;", i::BLOCK_SCOPE, i::STRICT },
1008    { "  for ", "(let x in {}) statement;", " more;",
1009      i::BLOCK_SCOPE, i::STRICT },
1010    { "  for ", "(let x in {}) statement", "\n"
1011      "  more;", i::BLOCK_SCOPE, i::STRICT },
1012    { "  for ", "(let x in {})\n"
1013      "    statement;", "\n"
1014      "  more;", i::BLOCK_SCOPE, i::STRICT },
1015    // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1016    // the preparser off in terms of byte offsets.
1017    // 6 byte encoding.
1018    { "  'foo\355\240\201\355\260\211';\n"
1019      "  (function fun", "(a,b) { infunction; }", ")();",
1020      i::FUNCTION_SCOPE, i::SLOPPY },
1021    // 4 byte encoding.
1022    { "  'foo\360\220\220\212';\n"
1023      "  (function fun", "(a,b) { infunction; }", ")();",
1024      i::FUNCTION_SCOPE, i::SLOPPY },
1025    // 3 byte encoding of \u0fff.
1026    { "  'foo\340\277\277';\n"
1027      "  (function fun", "(a,b) { infunction; }", ")();",
1028      i::FUNCTION_SCOPE, i::SLOPPY },
1029    // Broken 6 byte encoding with missing last byte.
1030    { "  'foo\355\240\201\355\211';\n"
1031      "  (function fun", "(a,b) { infunction; }", ")();",
1032      i::FUNCTION_SCOPE, i::SLOPPY },
1033    // Broken 3 byte encoding of \u0fff with missing last byte.
1034    { "  'foo\340\277';\n"
1035      "  (function fun", "(a,b) { infunction; }", ")();",
1036      i::FUNCTION_SCOPE, i::SLOPPY },
1037    // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1038    { "  'foo\340';\n"
1039      "  (function fun", "(a,b) { infunction; }", ")();",
1040      i::FUNCTION_SCOPE, i::SLOPPY },
1041    // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1042    { "  'foo\340\203\277';\n"
1043      "  (function fun", "(a,b) { infunction; }", ")();",
1044      i::FUNCTION_SCOPE, i::SLOPPY },
1045    // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1046    { "  'foo\340\201\277';\n"
1047      "  (function fun", "(a,b) { infunction; }", ")();",
1048      i::FUNCTION_SCOPE, i::SLOPPY },
1049    // Unpaired lead surrogate.
1050    { "  'foo\355\240\201';\n"
1051      "  (function fun", "(a,b) { infunction; }", ")();",
1052      i::FUNCTION_SCOPE, i::SLOPPY },
1053    // Unpaired lead surrogate where following code point is a 3 byte sequence.
1054    { "  'foo\355\240\201\340\277\277';\n"
1055      "  (function fun", "(a,b) { infunction; }", ")();",
1056      i::FUNCTION_SCOPE, i::SLOPPY },
1057    // Unpaired lead surrogate where following code point is a 4 byte encoding
1058    // of a trail surrogate.
1059    { "  'foo\355\240\201\360\215\260\211';\n"
1060      "  (function fun", "(a,b) { infunction; }", ")();",
1061      i::FUNCTION_SCOPE, i::SLOPPY },
1062    // Unpaired trail surrogate.
1063    { "  'foo\355\260\211';\n"
1064      "  (function fun", "(a,b) { infunction; }", ")();",
1065      i::FUNCTION_SCOPE, i::SLOPPY },
1066    // 2 byte encoding of \u00ff.
1067    { "  'foo\303\277';\n"
1068      "  (function fun", "(a,b) { infunction; }", ")();",
1069      i::FUNCTION_SCOPE, i::SLOPPY },
1070    // Broken 2 byte encoding of \u00ff with missing last byte.
1071    { "  'foo\303';\n"
1072      "  (function fun", "(a,b) { infunction; }", ")();",
1073      i::FUNCTION_SCOPE, i::SLOPPY },
1074    // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1075    { "  'foo\301\277';\n"
1076      "  (function fun", "(a,b) { infunction; }", ")();",
1077      i::FUNCTION_SCOPE, i::SLOPPY },
1078    // Illegal 5 byte encoding.
1079    { "  'foo\370\277\277\277\277';\n"
1080      "  (function fun", "(a,b) { infunction; }", ")();",
1081      i::FUNCTION_SCOPE, i::SLOPPY },
1082    // Illegal 6 byte encoding.
1083    { "  'foo\374\277\277\277\277\277';\n"
1084      "  (function fun", "(a,b) { infunction; }", ")();",
1085      i::FUNCTION_SCOPE, i::SLOPPY },
1086    // Illegal 0xfe byte
1087    { "  'foo\376\277\277\277\277\277\277';\n"
1088      "  (function fun", "(a,b) { infunction; }", ")();",
1089      i::FUNCTION_SCOPE, i::SLOPPY },
1090    // Illegal 0xff byte
1091    { "  'foo\377\277\277\277\277\277\277\277';\n"
1092      "  (function fun", "(a,b) { infunction; }", ")();",
1093      i::FUNCTION_SCOPE, i::SLOPPY },
1094    { "  'foo';\n"
1095      "  (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
1096      i::FUNCTION_SCOPE, i::SLOPPY },
1097    { "  'foo';\n"
1098      "  (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
1099      i::FUNCTION_SCOPE, i::SLOPPY },
1100    { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
1101  };
1102
1103  i::Isolate* isolate = CcTest::i_isolate();
1104  i::Factory* factory = isolate->factory();
1105
1106  v8::HandleScope handles(CcTest::isolate());
1107  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1108  v8::Context::Scope context_scope(context);
1109
1110  isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1111                                        128 * 1024);
1112
1113  for (int i = 0; source_data[i].outer_prefix; i++) {
1114    int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1115    int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1116    int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1117    int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1118    int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1119    int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1120    int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1121    int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1122    i::ScopedVector<char> program(kProgramByteSize + 1);
1123    i::SNPrintF(program, "%s%s%s",
1124                         source_data[i].outer_prefix,
1125                         source_data[i].inner_source,
1126                         source_data[i].outer_suffix);
1127
1128    // Parse program source.
1129    i::Handle<i::String> source = factory->NewStringFromUtf8(
1130        i::CStrVector(program.start())).ToHandleChecked();
1131    CHECK_EQ(source->length(), kProgramSize);
1132    i::Handle<i::Script> script = factory->NewScript(source);
1133    i::CompilationInfoWithZone info(script);
1134    i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(),
1135                                       isolate->heap()->HashSeed(),
1136                                       isolate->unicode_cache()};
1137    i::Parser parser(&info, &parse_info);
1138    parser.set_allow_lazy(true);
1139    parser.set_allow_harmony_scoping(true);
1140    parser.set_allow_arrow_functions(true);
1141    info.MarkAsGlobal();
1142    info.SetStrictMode(source_data[i].strict_mode);
1143    parser.Parse();
1144    CHECK(info.function() != NULL);
1145
1146    // Check scope types and positions.
1147    i::Scope* scope = info.function()->scope();
1148    CHECK(scope->is_global_scope());
1149    CHECK_EQ(scope->start_position(), 0);
1150    CHECK_EQ(scope->end_position(), kProgramSize);
1151    CHECK_EQ(scope->inner_scopes()->length(), 1);
1152
1153    i::Scope* inner_scope = scope->inner_scopes()->at(0);
1154    CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1155    CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1156    // The end position of a token is one position after the last
1157    // character belonging to that token.
1158    CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1159  }
1160}
1161
1162
1163const char* ReadString(unsigned* start) {
1164  int length = start[0];
1165  char* result = i::NewArray<char>(length + 1);
1166  for (int i = 0; i < length; i++) {
1167    result[i] = start[i + 1];
1168  }
1169  result[length] = '\0';
1170  return result;
1171}
1172
1173
1174i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
1175  i::Isolate* isolate = CcTest::i_isolate();
1176  i::Factory* factory = isolate->factory();
1177  const char* message =
1178      ReadString(&data[i::PreparseDataConstants::kMessageTextPos]);
1179  i::Handle<i::String> format = v8::Utils::OpenHandle(
1180      *v8::String::NewFromUtf8(CcTest::isolate(), message));
1181  int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
1182  const char* arg = NULL;
1183  i::Handle<i::JSArray> args_array;
1184  if (arg_count == 1) {
1185    // Position after text found by skipping past length field and
1186    // length field content words.
1187    int pos = i::PreparseDataConstants::kMessageTextPos + 1 +
1188              data[i::PreparseDataConstants::kMessageTextPos];
1189    arg = ReadString(&data[pos]);
1190    args_array = factory->NewJSArray(1);
1191    i::JSArray::SetElement(args_array, 0, v8::Utils::OpenHandle(*v8_str(arg)),
1192                           NONE, i::SLOPPY).Check();
1193  } else {
1194    CHECK_EQ(0, arg_count);
1195    args_array = factory->NewJSArray(0);
1196  }
1197
1198  i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
1199  i::Handle<i::Object> format_fun = i::Object::GetProperty(
1200      isolate, builtins, "FormatMessage").ToHandleChecked();
1201  i::Handle<i::Object> arg_handles[] = { format, args_array };
1202  i::Handle<i::Object> result = i::Execution::Call(
1203      isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
1204  CHECK(result->IsString());
1205  i::DeleteArray(message);
1206  i::DeleteArray(arg);
1207  data.Dispose();
1208  return i::Handle<i::String>::cast(result);
1209}
1210
1211
1212enum ParserFlag {
1213  kAllowLazy,
1214  kAllowNativesSyntax,
1215  kAllowHarmonyScoping,
1216  kAllowModules,
1217  kAllowHarmonyNumericLiterals,
1218  kAllowArrowFunctions,
1219  kAllowClasses,
1220  kAllowHarmonyObjectLiterals
1221};
1222
1223
1224enum ParserSyncTestResult {
1225  kSuccessOrError,
1226  kSuccess,
1227  kError
1228};
1229
1230template <typename Traits>
1231void SetParserFlags(i::ParserBase<Traits>* parser,
1232                    i::EnumSet<ParserFlag> flags) {
1233  parser->set_allow_lazy(flags.Contains(kAllowLazy));
1234  parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
1235  parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
1236  parser->set_allow_modules(flags.Contains(kAllowModules));
1237  parser->set_allow_harmony_numeric_literals(
1238      flags.Contains(kAllowHarmonyNumericLiterals));
1239  parser->set_allow_harmony_object_literals(
1240      flags.Contains(kAllowHarmonyObjectLiterals));
1241  parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
1242  parser->set_allow_classes(flags.Contains(kAllowClasses));
1243}
1244
1245
1246void TestParserSyncWithFlags(i::Handle<i::String> source,
1247                             i::EnumSet<ParserFlag> flags,
1248                             ParserSyncTestResult result) {
1249  i::Isolate* isolate = CcTest::i_isolate();
1250  i::Factory* factory = isolate->factory();
1251
1252  uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1253
1254  // Preparse the data.
1255  i::CompleteParserRecorder log;
1256  {
1257    i::Scanner scanner(isolate->unicode_cache());
1258    i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1259    i::PreParser preparser(&scanner, &log, stack_limit);
1260    SetParserFlags(&preparser, flags);
1261    scanner.Initialize(&stream);
1262    i::PreParser::PreParseResult result = preparser.PreParseProgram();
1263    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1264  }
1265
1266  bool preparse_error = log.HasError();
1267
1268  // Parse the data
1269  i::FunctionLiteral* function;
1270  {
1271    i::Handle<i::Script> script = factory->NewScript(source);
1272    i::CompilationInfoWithZone info(script);
1273    i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(),
1274                                       isolate->heap()->HashSeed(),
1275                                       isolate->unicode_cache()};
1276    i::Parser parser(&info, &parse_info);
1277    SetParserFlags(&parser, flags);
1278    info.MarkAsGlobal();
1279    parser.Parse();
1280    function = info.function();
1281  }
1282
1283  // Check that preparsing fails iff parsing fails.
1284  if (function == NULL) {
1285    // Extract exception from the parser.
1286    CHECK(isolate->has_pending_exception());
1287    i::Handle<i::JSObject> exception_handle(
1288        i::JSObject::cast(isolate->pending_exception()));
1289    i::Handle<i::String> message_string =
1290        i::Handle<i::String>::cast(i::Object::GetProperty(
1291            isolate, exception_handle, "message").ToHandleChecked());
1292
1293    if (result == kSuccess) {
1294      v8::base::OS::Print(
1295          "Parser failed on:\n"
1296          "\t%s\n"
1297          "with error:\n"
1298          "\t%s\n"
1299          "However, we expected no error.",
1300          source->ToCString().get(), message_string->ToCString().get());
1301      CHECK(false);
1302    }
1303
1304    if (!preparse_error) {
1305      v8::base::OS::Print(
1306          "Parser failed on:\n"
1307          "\t%s\n"
1308          "with error:\n"
1309          "\t%s\n"
1310          "However, the preparser succeeded",
1311          source->ToCString().get(), message_string->ToCString().get());
1312      CHECK(false);
1313    }
1314    // Check that preparser and parser produce the same error.
1315    i::Handle<i::String> preparser_message =
1316        FormatMessage(log.ErrorMessageData());
1317    if (!i::String::Equals(message_string, preparser_message)) {
1318      v8::base::OS::Print(
1319          "Expected parser and preparser to produce the same error on:\n"
1320          "\t%s\n"
1321          "However, found the following error messages\n"
1322          "\tparser:    %s\n"
1323          "\tpreparser: %s\n",
1324          source->ToCString().get(),
1325          message_string->ToCString().get(),
1326          preparser_message->ToCString().get());
1327      CHECK(false);
1328    }
1329  } else if (preparse_error) {
1330    v8::base::OS::Print(
1331        "Preparser failed on:\n"
1332        "\t%s\n"
1333        "with error:\n"
1334        "\t%s\n"
1335        "However, the parser succeeded",
1336        source->ToCString().get(),
1337        FormatMessage(log.ErrorMessageData())->ToCString().get());
1338    CHECK(false);
1339  } else if (result == kError) {
1340    v8::base::OS::Print(
1341        "Expected error on:\n"
1342        "\t%s\n"
1343        "However, parser and preparser succeeded",
1344        source->ToCString().get());
1345    CHECK(false);
1346  }
1347}
1348
1349
1350void TestParserSync(const char* source,
1351                    const ParserFlag* varying_flags,
1352                    size_t varying_flags_length,
1353                    ParserSyncTestResult result = kSuccessOrError,
1354                    const ParserFlag* always_true_flags = NULL,
1355                    size_t always_true_flags_length = 0) {
1356  i::Handle<i::String> str =
1357      CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1358  for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1359    i::EnumSet<ParserFlag> flags;
1360    for (size_t flag_index = 0; flag_index < varying_flags_length;
1361         ++flag_index) {
1362      if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1363    }
1364    for (size_t flag_index = 0; flag_index < always_true_flags_length;
1365         ++flag_index) {
1366      flags.Add(always_true_flags[flag_index]);
1367    }
1368    TestParserSyncWithFlags(str, flags, result);
1369  }
1370}
1371
1372
1373TEST(ParserSync) {
1374  const char* context_data[][2] = {
1375    { "", "" },
1376    { "{", "}" },
1377    { "if (true) ", " else {}" },
1378    { "if (true) {} else ", "" },
1379    { "if (true) ", "" },
1380    { "do ", " while (false)" },
1381    { "while (false) ", "" },
1382    { "for (;;) ", "" },
1383    { "with ({})", "" },
1384    { "switch (12) { case 12: ", "}" },
1385    { "switch (12) { default: ", "}" },
1386    { "switch (12) { ", "case 12: }" },
1387    { "label2: ", "" },
1388    { NULL, NULL }
1389  };
1390
1391  const char* statement_data[] = {
1392    "{}",
1393    "var x",
1394    "var x = 1",
1395    "const x",
1396    "const x = 1",
1397    ";",
1398    "12",
1399    "if (false) {} else ;",
1400    "if (false) {} else {}",
1401    "if (false) {} else 12",
1402    "if (false) ;"
1403    "if (false) {}",
1404    "if (false) 12",
1405    "do {} while (false)",
1406    "for (;;) ;",
1407    "for (;;) {}",
1408    "for (;;) 12",
1409    "continue",
1410    "continue label",
1411    "continue\nlabel",
1412    "break",
1413    "break label",
1414    "break\nlabel",
1415    // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1416    // "return",
1417    // "return  12",
1418    // "return\n12",
1419    "with ({}) ;",
1420    "with ({}) {}",
1421    "with ({}) 12",
1422    "switch ({}) { default: }"
1423    "label3: "
1424    "throw",
1425    "throw  12",
1426    "throw\n12",
1427    "try {} catch(e) {}",
1428    "try {} finally {}",
1429    "try {} catch(e) {} finally {}",
1430    "debugger",
1431    NULL
1432  };
1433
1434  const char* termination_data[] = {
1435    "",
1436    ";",
1437    "\n",
1438    ";\n",
1439    "\n;",
1440    NULL
1441  };
1442
1443  v8::HandleScope handles(CcTest::isolate());
1444  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1445  v8::Context::Scope context_scope(context);
1446
1447  CcTest::i_isolate()->stack_guard()->SetStackLimit(
1448      i::GetCurrentStackPosition() - 128 * 1024);
1449
1450  static const ParserFlag flags1[] = {
1451    kAllowArrowFunctions,
1452    kAllowClasses,
1453    kAllowHarmonyNumericLiterals,
1454    kAllowHarmonyObjectLiterals,
1455    kAllowHarmonyScoping,
1456    kAllowLazy,
1457    kAllowModules,
1458  };
1459
1460  for (int i = 0; context_data[i][0] != NULL; ++i) {
1461    for (int j = 0; statement_data[j] != NULL; ++j) {
1462      for (int k = 0; termination_data[k] != NULL; ++k) {
1463        int kPrefixLen = i::StrLength(context_data[i][0]);
1464        int kStatementLen = i::StrLength(statement_data[j]);
1465        int kTerminationLen = i::StrLength(termination_data[k]);
1466        int kSuffixLen = i::StrLength(context_data[i][1]);
1467        int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1468            + kSuffixLen + i::StrLength("label: for (;;) {  }");
1469
1470        // Plug the source code pieces together.
1471        i::ScopedVector<char> program(kProgramSize + 1);
1472        int length = i::SNPrintF(program,
1473            "label: for (;;) { %s%s%s%s }",
1474            context_data[i][0],
1475            statement_data[j],
1476            termination_data[k],
1477            context_data[i][1]);
1478        CHECK(length == kProgramSize);
1479        TestParserSync(program.start(), flags1, arraysize(flags1));
1480      }
1481    }
1482  }
1483
1484  // Neither Harmony numeric literals nor our natives syntax have any
1485  // interaction with the flags above, so test these separately to reduce
1486  // the combinatorial explosion.
1487  static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals };
1488  TestParserSync("0o1234", flags2, arraysize(flags2));
1489  TestParserSync("0b1011", flags2, arraysize(flags2));
1490
1491  static const ParserFlag flags3[] = { kAllowNativesSyntax };
1492  TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1493}
1494
1495
1496TEST(StrictOctal) {
1497  // Test that syntax error caused by octal literal is reported correctly as
1498  // such (issue 2220).
1499  v8::V8::Initialize();
1500  v8::HandleScope scope(CcTest::isolate());
1501  v8::Context::Scope context_scope(
1502      v8::Context::New(CcTest::isolate()));
1503  v8::TryCatch try_catch;
1504  const char* script =
1505      "\"use strict\";       \n"
1506      "a = function() {      \n"
1507      "  b = function() {    \n"
1508      "    01;               \n"
1509      "  };                  \n"
1510      "};                    \n";
1511  v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
1512  CHECK(try_catch.HasCaught());
1513  v8::String::Utf8Value exception(try_catch.Exception());
1514  CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
1515           *exception);
1516}
1517
1518
1519void RunParserSyncTest(const char* context_data[][2],
1520                       const char* statement_data[],
1521                       ParserSyncTestResult result,
1522                       const ParserFlag* flags = NULL,
1523                       int flags_len = 0,
1524                       const ParserFlag* always_true_flags = NULL,
1525                       int always_true_flags_len = 0) {
1526  v8::HandleScope handles(CcTest::isolate());
1527  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1528  v8::Context::Scope context_scope(context);
1529
1530  CcTest::i_isolate()->stack_guard()->SetStackLimit(
1531      i::GetCurrentStackPosition() - 128 * 1024);
1532
1533  static const ParserFlag default_flags[] = {
1534    kAllowArrowFunctions,
1535    kAllowClasses,
1536    kAllowHarmonyNumericLiterals,
1537    kAllowHarmonyObjectLiterals,
1538    kAllowHarmonyScoping,
1539    kAllowLazy,
1540    kAllowModules,
1541    kAllowNativesSyntax,
1542  };
1543  ParserFlag* generated_flags = NULL;
1544  if (flags == NULL) {
1545    flags = default_flags;
1546    flags_len = arraysize(default_flags);
1547    if (always_true_flags != NULL) {
1548      // Remove always_true_flags from default_flags.
1549      CHECK(always_true_flags_len < flags_len);
1550      generated_flags = new ParserFlag[flags_len - always_true_flags_len];
1551      int flag_index = 0;
1552      for (int i = 0; i < flags_len; ++i) {
1553        bool use_flag = true;
1554        for (int j = 0; j < always_true_flags_len; ++j) {
1555          if (flags[i] == always_true_flags[j]) {
1556            use_flag = false;
1557            break;
1558          }
1559        }
1560        if (use_flag) generated_flags[flag_index++] = flags[i];
1561      }
1562      CHECK(flag_index == flags_len - always_true_flags_len);
1563      flags_len = flag_index;
1564      flags = generated_flags;
1565    }
1566  }
1567  for (int i = 0; context_data[i][0] != NULL; ++i) {
1568    for (int j = 0; statement_data[j] != NULL; ++j) {
1569      int kPrefixLen = i::StrLength(context_data[i][0]);
1570      int kStatementLen = i::StrLength(statement_data[j]);
1571      int kSuffixLen = i::StrLength(context_data[i][1]);
1572      int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1573
1574      // Plug the source code pieces together.
1575      i::ScopedVector<char> program(kProgramSize + 1);
1576      int length = i::SNPrintF(program,
1577                               "%s%s%s",
1578                               context_data[i][0],
1579                               statement_data[j],
1580                               context_data[i][1]);
1581      CHECK(length == kProgramSize);
1582      TestParserSync(program.start(),
1583                     flags,
1584                     flags_len,
1585                     result,
1586                     always_true_flags,
1587                     always_true_flags_len);
1588    }
1589  }
1590  delete[] generated_flags;
1591}
1592
1593
1594TEST(ErrorsEvalAndArguments) {
1595  // Tests that both preparsing and parsing produce the right kind of errors for
1596  // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1597  // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1598  // isn't.
1599  const char* context_data[][2] = {
1600    { "\"use strict\";", "" },
1601    { "var eval; function test_func() {\"use strict\"; ", "}"},
1602    { NULL, NULL }
1603  };
1604
1605  const char* statement_data[] = {
1606    "var eval;",
1607    "var arguments",
1608    "var foo, eval;",
1609    "var foo, arguments;",
1610    "try { } catch (eval) { }",
1611    "try { } catch (arguments) { }",
1612    "function eval() { }",
1613    "function arguments() { }",
1614    "function foo(eval) { }",
1615    "function foo(arguments) { }",
1616    "function foo(bar, eval) { }",
1617    "function foo(bar, arguments) { }",
1618    "(eval) => { }",
1619    "(arguments) => { }",
1620    "(foo, eval) => { }",
1621    "(foo, arguments) => { }",
1622    "eval = 1;",
1623    "arguments = 1;",
1624    "var foo = eval = 1;",
1625    "var foo = arguments = 1;",
1626    "++eval;",
1627    "++arguments;",
1628    "eval++;",
1629    "arguments++;",
1630    NULL
1631  };
1632
1633  RunParserSyncTest(context_data, statement_data, kError);
1634}
1635
1636
1637TEST(NoErrorsEvalAndArgumentsSloppy) {
1638  // Tests that both preparsing and parsing accept "eval" and "arguments" as
1639  // identifiers when needed.
1640  const char* context_data[][2] = {
1641    { "", "" },
1642    { "function test_func() {", "}"},
1643    { NULL, NULL }
1644  };
1645
1646  const char* statement_data[] = {
1647    "var eval;",
1648    "var arguments",
1649    "var foo, eval;",
1650    "var foo, arguments;",
1651    "try { } catch (eval) { }",
1652    "try { } catch (arguments) { }",
1653    "function eval() { }",
1654    "function arguments() { }",
1655    "function foo(eval) { }",
1656    "function foo(arguments) { }",
1657    "function foo(bar, eval) { }",
1658    "function foo(bar, arguments) { }",
1659    "eval = 1;",
1660    "arguments = 1;",
1661    "var foo = eval = 1;",
1662    "var foo = arguments = 1;",
1663    "++eval;",
1664    "++arguments;",
1665    "eval++;",
1666    "arguments++;",
1667    NULL
1668  };
1669
1670  RunParserSyncTest(context_data, statement_data, kSuccess);
1671}
1672
1673
1674TEST(NoErrorsEvalAndArgumentsStrict) {
1675  const char* context_data[][2] = {
1676    { "\"use strict\";", "" },
1677    { "function test_func() { \"use strict\";", "}" },
1678    { "() => { \"use strict\"; ", "}" },
1679    { NULL, NULL }
1680  };
1681
1682  const char* statement_data[] = {
1683    "eval;",
1684    "arguments;",
1685    "var foo = eval;",
1686    "var foo = arguments;",
1687    "var foo = { eval: 1 };",
1688    "var foo = { arguments: 1 };",
1689    "var foo = { }; foo.eval = {};",
1690    "var foo = { }; foo.arguments = {};",
1691    NULL
1692  };
1693
1694  static const ParserFlag always_flags[] = {kAllowArrowFunctions};
1695  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
1696                    always_flags, arraysize(always_flags));
1697}
1698
1699
1700TEST(ErrorsFutureStrictReservedWords) {
1701  // Tests that both preparsing and parsing produce the right kind of errors for
1702  // using future strict reserved words as identifiers. Without the strict mode,
1703  // it's ok to use future strict reserved words as identifiers. With the strict
1704  // mode, it isn't.
1705  const char* context_data[][2] = {
1706    { "\"use strict\";", "" },
1707    { "function test_func() {\"use strict\"; ", "}"},
1708    { "() => { \"use strict\"; ", "}" },
1709    { NULL, NULL }
1710  };
1711
1712  const char* statement_data[] = {
1713    "var interface;",
1714    "var foo, interface;",
1715    "try { } catch (interface) { }",
1716    "function interface() { }",
1717    "function foo(interface) { }",
1718    "function foo(bar, interface) { }",
1719    "interface = 1;",
1720    "var foo = interface = 1;",
1721    "++interface;",
1722    "interface++;",
1723    "var yield = 13;",
1724    NULL
1725  };
1726
1727  static const ParserFlag always_flags[] = {kAllowArrowFunctions};
1728  RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1729                    arraysize(always_flags));
1730}
1731
1732
1733TEST(NoErrorsFutureStrictReservedWords) {
1734  const char* context_data[][2] = {
1735    { "", "" },
1736    { "function test_func() {", "}"},
1737    { "() => {", "}" },
1738    { NULL, NULL }
1739  };
1740
1741  const char* statement_data[] = {
1742    "var interface;",
1743    "var foo, interface;",
1744    "try { } catch (interface) { }",
1745    "function interface() { }",
1746    "function foo(interface) { }",
1747    "function foo(bar, interface) { }",
1748    "interface = 1;",
1749    "var foo = interface = 1;",
1750    "++interface;",
1751    "interface++;",
1752    "var yield = 13;",
1753    NULL
1754  };
1755
1756  static const ParserFlag always_flags[] = {kAllowArrowFunctions};
1757  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
1758                    always_flags, arraysize(always_flags));
1759}
1760
1761
1762TEST(ErrorsReservedWords) {
1763  // Tests that both preparsing and parsing produce the right kind of errors for
1764  // using future reserved words as identifiers. These tests don't depend on the
1765  // strict mode.
1766  const char* context_data[][2] = {
1767    { "", "" },
1768    { "\"use strict\";", "" },
1769    { "var eval; function test_func() {", "}"},
1770    { "var eval; function test_func() {\"use strict\"; ", "}"},
1771    { "var eval; () => {", "}"},
1772    { "var eval; () => {\"use strict\"; ", "}"},
1773    { NULL, NULL }
1774  };
1775
1776  const char* statement_data[] = {
1777    "var super;",
1778    "var foo, super;",
1779    "try { } catch (super) { }",
1780    "function super() { }",
1781    "function foo(super) { }",
1782    "function foo(bar, super) { }",
1783    "(super) => { }",
1784    "(bar, super) => { }",
1785    "super = 1;",
1786    "var foo = super = 1;",
1787    "++super;",
1788    "super++;",
1789    "function foo super",
1790    NULL
1791  };
1792
1793  RunParserSyncTest(context_data, statement_data, kError);
1794}
1795
1796
1797TEST(NoErrorsLetSloppyAllModes) {
1798  // In sloppy mode, it's okay to use "let" as identifier.
1799  const char* context_data[][2] = {
1800    { "", "" },
1801    { "function f() {", "}" },
1802    { "(function f() {", "})" },
1803    { NULL, NULL }
1804  };
1805
1806  const char* statement_data[] = {
1807    "var let;",
1808    "var foo, let;",
1809    "try { } catch (let) { }",
1810    "function let() { }",
1811    "(function let() { })",
1812    "function foo(let) { }",
1813    "function foo(bar, let) { }",
1814    "let = 1;",
1815    "var foo = let = 1;",
1816    "let * 2;",
1817    "++let;",
1818    "let++;",
1819    "let: 34",
1820    "function let(let) { let: let(let + let(0)); }",
1821    "({ let: 1 })",
1822    "({ get let() { 1 } })",
1823    "let(100)",
1824    NULL
1825  };
1826
1827  RunParserSyncTest(context_data, statement_data, kSuccess);
1828}
1829
1830
1831TEST(NoErrorsYieldSloppyAllModes) {
1832  // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
1833  // generator (see other test).
1834  const char* context_data[][2] = {
1835    { "", "" },
1836    { "function not_gen() {", "}" },
1837    { "(function not_gen() {", "})" },
1838    { NULL, NULL }
1839  };
1840
1841  const char* statement_data[] = {
1842    "var yield;",
1843    "var foo, yield;",
1844    "try { } catch (yield) { }",
1845    "function yield() { }",
1846    "(function yield() { })",
1847    "function foo(yield) { }",
1848    "function foo(bar, yield) { }",
1849    "yield = 1;",
1850    "var foo = yield = 1;",
1851    "yield * 2;",
1852    "++yield;",
1853    "yield++;",
1854    "yield: 34",
1855    "function yield(yield) { yield: yield (yield + yield(0)); }",
1856    "({ yield: 1 })",
1857    "({ get yield() { 1 } })",
1858    "yield(100)",
1859    "yield[100]",
1860    NULL
1861  };
1862
1863  RunParserSyncTest(context_data, statement_data, kSuccess);
1864}
1865
1866
1867TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
1868  // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
1869  // generator (see next test).
1870  const char* context_data[][2] = {
1871    { "", "" },
1872    { "function not_gen() {", "}" },
1873    { "function * gen() { function not_gen() {", "} }" },
1874    { "(function not_gen() {", "})" },
1875    { "(function * gen() { (function not_gen() {", "}) })" },
1876    { NULL, NULL }
1877  };
1878
1879  const char* statement_data[] = {
1880    "var yield;",
1881    "var foo, yield;",
1882    "try { } catch (yield) { }",
1883    "function yield() { }",
1884    "(function yield() { })",
1885    "function foo(yield) { }",
1886    "function foo(bar, yield) { }",
1887    "function * yield() { }",
1888    "(function * yield() { })",
1889    "yield = 1;",
1890    "var foo = yield = 1;",
1891    "yield * 2;",
1892    "++yield;",
1893    "yield++;",
1894    "yield: 34",
1895    "function yield(yield) { yield: yield (yield + yield(0)); }",
1896    "({ yield: 1 })",
1897    "({ get yield() { 1 } })",
1898    "yield(100)",
1899    "yield[100]",
1900    NULL
1901  };
1902
1903  RunParserSyncTest(context_data, statement_data, kSuccess);
1904}
1905
1906
1907TEST(ErrorsYieldStrict) {
1908  const char* context_data[][2] = {
1909    { "\"use strict\";", "" },
1910    { "\"use strict\"; function not_gen() {", "}" },
1911    { "function test_func() {\"use strict\"; ", "}"},
1912    { "\"use strict\"; function * gen() { function not_gen() {", "} }" },
1913    { "\"use strict\"; (function not_gen() {", "})" },
1914    { "\"use strict\"; (function * gen() { (function not_gen() {", "}) })" },
1915    { "() => {\"use strict\"; ", "}" },
1916    { NULL, NULL }
1917  };
1918
1919  const char* statement_data[] = {
1920    "var yield;",
1921    "var foo, yield;",
1922    "try { } catch (yield) { }",
1923    "function yield() { }",
1924    "(function yield() { })",
1925    "function foo(yield) { }",
1926    "function foo(bar, yield) { }",
1927    "function * yield() { }",
1928    "(function * yield() { })",
1929    "yield = 1;",
1930    "var foo = yield = 1;",
1931    "++yield;",
1932    "yield++;",
1933    "yield: 34;",
1934    NULL
1935  };
1936
1937  RunParserSyncTest(context_data, statement_data, kError);
1938}
1939
1940
1941TEST(NoErrorsGenerator) {
1942  const char* context_data[][2] = {
1943    { "function * gen() {", "}" },
1944    { "(function * gen() {", "})" },
1945    { "(function * () {", "})" },
1946    { NULL, NULL }
1947  };
1948
1949  const char* statement_data[] = {
1950    // A generator without a body is valid.
1951    ""
1952    // Valid yield expressions inside generators.
1953    "yield 2;",
1954    "yield * 2;",
1955    "yield * \n 2;",
1956    "yield yield 1;",
1957    "yield * yield * 1;",
1958    "yield 3 + (yield 4);",
1959    "yield * 3 + (yield * 4);",
1960    "(yield * 3) + (yield * 4);",
1961    "yield 3; yield 4;",
1962    "yield * 3; yield * 4;",
1963    "(function (yield) { })",
1964    "yield { yield: 12 }",
1965    "yield /* comment */ { yield: 12 }",
1966    "yield * \n { yield: 12 }",
1967    "yield /* comment */ * \n { yield: 12 }",
1968    // You can return in a generator.
1969    "yield 1; return",
1970    "yield * 1; return",
1971    "yield 1; return 37",
1972    "yield * 1; return 37",
1973    "yield 1; return 37; yield 'dead';",
1974    "yield * 1; return 37; yield * 'dead';",
1975    // Yield is still a valid key in object literals.
1976    "({ yield: 1 })",
1977    "({ get yield() { } })",
1978    // Yield without RHS.
1979    "yield;",
1980    "yield",
1981    "yield\n",
1982    "yield /* comment */"
1983    "yield // comment\n"
1984    "(yield)",
1985    "[yield]",
1986    "{yield}",
1987    "yield, yield",
1988    "yield; yield",
1989    "(yield) ? yield : yield",
1990    "(yield) \n ? yield : yield",
1991    // If there is a newline before the next token, we don't look for RHS.
1992    "yield\nfor (;;) {}",
1993    NULL
1994  };
1995
1996  RunParserSyncTest(context_data, statement_data, kSuccess);
1997}
1998
1999
2000TEST(ErrorsYieldGenerator) {
2001  const char* context_data[][2] = {
2002    { "function * gen() {", "}" },
2003    { "\"use strict\"; function * gen() {", "}" },
2004    { NULL, NULL }
2005  };
2006
2007  const char* statement_data[] = {
2008    // Invalid yield expressions inside generators.
2009    "var yield;",
2010    "var foo, yield;",
2011    "try { } catch (yield) { }",
2012    "function yield() { }",
2013    // The name of the NFE is let-bound in the generator, which does not permit
2014    // yield to be an identifier.
2015    "(function yield() { })",
2016    "(function * yield() { })",
2017    // Yield isn't valid as a formal parameter for generators.
2018    "function * foo(yield) { }",
2019    "(function * foo(yield) { })",
2020    "yield = 1;",
2021    "var foo = yield = 1;",
2022    "++yield;",
2023    "yield++;",
2024    "yield *",
2025    "(yield *)",
2026    // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2027    // is invalid.
2028    "yield 3 + yield 4;",
2029    "yield: 34",
2030    "yield ? 1 : 2",
2031    // Parses as yield (/ yield): invalid.
2032    "yield / yield",
2033    "+ yield",
2034    "+ yield 3",
2035    // Invalid (no newline allowed between yield and *).
2036    "yield\n*3",
2037    // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2038    // object literal, and yield is not a valid label).
2039    "yield\n{yield: 42}",
2040    "yield /* comment */\n {yield: 42}",
2041    "yield //comment\n {yield: 42}",
2042    NULL
2043  };
2044
2045  RunParserSyncTest(context_data, statement_data, kError);
2046}
2047
2048
2049TEST(ErrorsNameOfStrictFunction) {
2050  // Tests that illegal tokens as names of a strict function produce the correct
2051  // errors.
2052  const char* context_data[][2] = {
2053    { "function ", ""},
2054    { "\"use strict\"; function", ""},
2055    { "function * ", ""},
2056    { "\"use strict\"; function * ", ""},
2057    { NULL, NULL }
2058  };
2059
2060  const char* statement_data[] = {
2061    "eval() {\"use strict\";}",
2062    "arguments() {\"use strict\";}",
2063    "interface() {\"use strict\";}",
2064    "yield() {\"use strict\";}",
2065    // Future reserved words are always illegal
2066    "function super() { }",
2067    "function super() {\"use strict\";}",
2068    NULL
2069  };
2070
2071  RunParserSyncTest(context_data, statement_data, kError);
2072}
2073
2074
2075TEST(NoErrorsNameOfStrictFunction) {
2076  const char* context_data[][2] = {
2077    { "function ", ""},
2078    { NULL, NULL }
2079  };
2080
2081  const char* statement_data[] = {
2082    "eval() { }",
2083    "arguments() { }",
2084    "interface() { }",
2085    "yield() { }",
2086    NULL
2087  };
2088
2089  RunParserSyncTest(context_data, statement_data, kSuccess);
2090}
2091
2092
2093TEST(NoErrorsNameOfStrictGenerator) {
2094  const char* context_data[][2] = {
2095    { "function * ", ""},
2096    { NULL, NULL }
2097  };
2098
2099  const char* statement_data[] = {
2100    "eval() { }",
2101    "arguments() { }",
2102    "interface() { }",
2103    "yield() { }",
2104    NULL
2105  };
2106
2107  RunParserSyncTest(context_data, statement_data, kSuccess);
2108}
2109
2110
2111TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2112  // Using future reserved words as labels is always an error.
2113  const char* context_data[][2] = {
2114    { "", ""},
2115    { "function test_func() {", "}" },
2116    { "() => {", "}" },
2117    { NULL, NULL }
2118  };
2119
2120  const char* statement_data[] = {
2121    "super: while(true) { break super; }",
2122    NULL
2123  };
2124
2125  RunParserSyncTest(context_data, statement_data, kError);
2126}
2127
2128
2129TEST(ErrorsIllegalWordsAsLabelsStrict) {
2130  // Tests that illegal tokens as labels produce the correct errors.
2131  const char* context_data[][2] = {
2132    { "\"use strict\";", "" },
2133    { "function test_func() {\"use strict\"; ", "}"},
2134    { "() => {\"use strict\"; ", "}" },
2135    { NULL, NULL }
2136  };
2137
2138  const char* statement_data[] = {
2139    "super: while(true) { break super; }",
2140    "interface: while(true) { break interface; }",
2141    "yield: while(true) { break yield; }",
2142    NULL
2143  };
2144
2145  RunParserSyncTest(context_data, statement_data, kError);
2146}
2147
2148
2149TEST(NoErrorsIllegalWordsAsLabels) {
2150  // Using eval and arguments as labels is legal even in strict mode.
2151  const char* context_data[][2] = {
2152    { "", ""},
2153    { "function test_func() {", "}" },
2154    { "() => {", "}" },
2155    { "\"use strict\";", "" },
2156    { "\"use strict\"; function test_func() {", "}" },
2157    { "\"use strict\"; () => {", "}" },
2158    { NULL, NULL }
2159  };
2160
2161  const char* statement_data[] = {
2162    "mylabel: while(true) { break mylabel; }",
2163    "eval: while(true) { break eval; }",
2164    "arguments: while(true) { break arguments; }",
2165    NULL
2166  };
2167
2168  static const ParserFlag always_flags[] = {kAllowArrowFunctions};
2169  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2170                    always_flags, arraysize(always_flags));
2171}
2172
2173
2174TEST(ErrorsParenthesizedLabels) {
2175  // Parenthesized identifiers shouldn't be recognized as labels.
2176  const char* context_data[][2] = {
2177    { "", ""},
2178    { "function test_func() {", "}" },
2179    { "() => {", "}" },
2180    { NULL, NULL }
2181  };
2182
2183  const char* statement_data[] = {
2184    "(mylabel): while(true) { break mylabel; }",
2185    NULL
2186  };
2187
2188  RunParserSyncTest(context_data, statement_data, kError);
2189}
2190
2191
2192TEST(NoErrorsParenthesizedDirectivePrologue) {
2193  // Parenthesized directive prologue shouldn't be recognized.
2194  const char* context_data[][2] = {
2195    { "", ""},
2196    { NULL, NULL }
2197  };
2198
2199  const char* statement_data[] = {
2200    "(\"use strict\"); var eval;",
2201    NULL
2202  };
2203
2204  RunParserSyncTest(context_data, statement_data, kSuccess);
2205}
2206
2207
2208TEST(ErrorsNotAnIdentifierName) {
2209  const char* context_data[][2] = {
2210    { "", ""},
2211    { "\"use strict\";", ""},
2212    { NULL, NULL }
2213  };
2214
2215  const char* statement_data[] = {
2216    "var foo = {}; foo.{;",
2217    "var foo = {}; foo.};",
2218    "var foo = {}; foo.=;",
2219    "var foo = {}; foo.888;",
2220    "var foo = {}; foo.-;",
2221    "var foo = {}; foo.--;",
2222    NULL
2223  };
2224
2225  RunParserSyncTest(context_data, statement_data, kError);
2226}
2227
2228
2229TEST(NoErrorsIdentifierNames) {
2230  // Keywords etc. are valid as property names.
2231  const char* context_data[][2] = {
2232    { "", ""},
2233    { "\"use strict\";", ""},
2234    { NULL, NULL }
2235  };
2236
2237  const char* statement_data[] = {
2238    "var foo = {}; foo.if;",
2239    "var foo = {}; foo.yield;",
2240    "var foo = {}; foo.super;",
2241    "var foo = {}; foo.interface;",
2242    "var foo = {}; foo.eval;",
2243    "var foo = {}; foo.arguments;",
2244    NULL
2245  };
2246
2247  RunParserSyncTest(context_data, statement_data, kSuccess);
2248}
2249
2250
2251TEST(DontRegressPreParserDataSizes) {
2252  // These tests make sure that Parser doesn't start producing less "preparse
2253  // data" (data which the embedder can cache).
2254  v8::V8::Initialize();
2255  v8::Isolate* isolate = CcTest::isolate();
2256  v8::HandleScope handles(isolate);
2257
2258  CcTest::i_isolate()->stack_guard()->SetStackLimit(
2259      i::GetCurrentStackPosition() - 128 * 1024);
2260
2261  struct TestCase {
2262    const char* program;
2263    int functions;
2264  } test_cases[] = {
2265    // No functions.
2266    {"var x = 42;", 0},
2267    // Functions.
2268    {"function foo() {}", 1}, {"function foo() {} function bar() {}", 2},
2269    // Getter / setter functions are recorded as functions if they're on the top
2270    // level.
2271    {"var x = {get foo(){} };", 1},
2272    // Functions insize lazy functions are not recorded.
2273    {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2274    {"function lazy() { var x = {get foo(){} } }", 1},
2275    {NULL, 0}
2276  };
2277
2278  for (int i = 0; test_cases[i].program; i++) {
2279    const char* program = test_cases[i].program;
2280    i::Factory* factory = CcTest::i_isolate()->factory();
2281    i::Handle<i::String> source =
2282        factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2283    i::Handle<i::Script> script = factory->NewScript(source);
2284    i::CompilationInfoWithZone info(script);
2285    i::ScriptData* sd = NULL;
2286    info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
2287    i::Parser::Parse(&info, true);
2288    i::ParseData pd(sd);
2289
2290    if (pd.FunctionCount() != test_cases[i].functions) {
2291      v8::base::OS::Print(
2292          "Expected preparse data for program:\n"
2293          "\t%s\n"
2294          "to contain %d functions, however, received %d functions.\n",
2295          program, test_cases[i].functions, pd.FunctionCount());
2296      CHECK(false);
2297    }
2298    delete sd;
2299  }
2300}
2301
2302
2303TEST(FunctionDeclaresItselfStrict) {
2304  // Tests that we produce the right kinds of errors when a function declares
2305  // itself strict (we cannot produce there errors as soon as we see the
2306  // offending identifiers, because we don't know at that point whether the
2307  // function is strict or not).
2308  const char* context_data[][2] = {
2309    {"function eval() {", "}"},
2310    {"function arguments() {", "}"},
2311    {"function yield() {", "}"},
2312    {"function interface() {", "}"},
2313    {"function foo(eval) {", "}"},
2314    {"function foo(arguments) {", "}"},
2315    {"function foo(yield) {", "}"},
2316    {"function foo(interface) {", "}"},
2317    {"function foo(bar, eval) {", "}"},
2318    {"function foo(bar, arguments) {", "}"},
2319    {"function foo(bar, yield) {", "}"},
2320    {"function foo(bar, interface) {", "}"},
2321    {"function foo(bar, bar) {", "}"},
2322    { NULL, NULL }
2323  };
2324
2325  const char* strict_statement_data[] = {
2326    "\"use strict\";",
2327    NULL
2328  };
2329
2330  const char* non_strict_statement_data[] = {
2331    ";",
2332    NULL
2333  };
2334
2335  RunParserSyncTest(context_data, strict_statement_data, kError);
2336  RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2337}
2338
2339
2340TEST(ErrorsTryWithoutCatchOrFinally) {
2341  const char* context_data[][2] = {
2342    {"", ""},
2343    { NULL, NULL }
2344  };
2345
2346  const char* statement_data[] = {
2347    "try { }",
2348    "try { } foo();",
2349    "try { } catch (e) foo();",
2350    "try { } catch { }",
2351    "try { } finally foo();",
2352    NULL
2353  };
2354
2355  RunParserSyncTest(context_data, statement_data, kError);
2356}
2357
2358
2359TEST(NoErrorsTryCatchFinally) {
2360  const char* context_data[][2] = {
2361    {"", ""},
2362    { NULL, NULL }
2363  };
2364
2365  const char* statement_data[] = {
2366    "try { } catch (e) { }",
2367    "try { } catch (e) { } finally { }",
2368    "try { } finally { }",
2369    NULL
2370  };
2371
2372  RunParserSyncTest(context_data, statement_data, kSuccess);
2373}
2374
2375
2376TEST(ErrorsRegexpLiteral) {
2377  const char* context_data[][2] = {
2378    {"var r = ", ""},
2379    { NULL, NULL }
2380  };
2381
2382  const char* statement_data[] = {
2383    "/unterminated",
2384    NULL
2385  };
2386
2387  RunParserSyncTest(context_data, statement_data, kError);
2388}
2389
2390
2391TEST(NoErrorsRegexpLiteral) {
2392  const char* context_data[][2] = {
2393    {"var r = ", ""},
2394    { NULL, NULL }
2395  };
2396
2397  const char* statement_data[] = {
2398    "/foo/",
2399    "/foo/g",
2400    "/foo/whatever",  // This is an error but not detected by the parser.
2401    NULL
2402  };
2403
2404  RunParserSyncTest(context_data, statement_data, kSuccess);
2405}
2406
2407
2408TEST(Intrinsics) {
2409  const char* context_data[][2] = {
2410    {"", ""},
2411    { NULL, NULL }
2412  };
2413
2414  const char* statement_data[] = {
2415    "%someintrinsic(arg)",
2416    NULL
2417  };
2418
2419  // This test requires kAllowNativesSyntax to succeed.
2420  static const ParserFlag always_true_flags[] = {
2421    kAllowNativesSyntax
2422  };
2423
2424  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2425                    always_true_flags, 1);
2426}
2427
2428
2429TEST(NoErrorsNewExpression) {
2430  const char* context_data[][2] = {
2431    {"", ""},
2432    {"var f =", ""},
2433    { NULL, NULL }
2434  };
2435
2436  const char* statement_data[] = {
2437    "new foo",
2438    "new foo();",
2439    "new foo(1);",
2440    "new foo(1, 2);",
2441    // The first () will be processed as a part of the NewExpression and the
2442    // second () will be processed as part of LeftHandSideExpression.
2443    "new foo()();",
2444    // The first () will be processed as a part of the inner NewExpression and
2445    // the second () will be processed as a part of the outer NewExpression.
2446    "new new foo()();",
2447    "new foo.bar;",
2448    "new foo.bar();",
2449    "new foo.bar.baz;",
2450    "new foo.bar().baz;",
2451    "new foo[bar];",
2452    "new foo[bar]();",
2453    "new foo[bar][baz];",
2454    "new foo[bar]()[baz];",
2455    "new foo[bar].baz(baz)()[bar].baz;",
2456    "new \"foo\"",  // Runtime error
2457    "new 1",  // Runtime error
2458    // This even runs:
2459    "(new new Function(\"this.x = 1\")).x;",
2460    "new new Test_Two(String, 2).v(0123).length;",
2461    NULL
2462  };
2463
2464  RunParserSyncTest(context_data, statement_data, kSuccess);
2465}
2466
2467
2468TEST(ErrorsNewExpression) {
2469  const char* context_data[][2] = {
2470    {"", ""},
2471    {"var f =", ""},
2472    { NULL, NULL }
2473  };
2474
2475  const char* statement_data[] = {
2476    "new foo bar",
2477    "new ) foo",
2478    "new ++foo",
2479    "new foo ++",
2480    NULL
2481  };
2482
2483  RunParserSyncTest(context_data, statement_data, kError);
2484}
2485
2486
2487TEST(StrictObjectLiteralChecking) {
2488  const char* strict_context_data[][2] = {
2489    {"\"use strict\"; var myobject = {", "};"},
2490    {"\"use strict\"; var myobject = {", ",};"},
2491    { NULL, NULL }
2492  };
2493  const char* non_strict_context_data[][2] = {
2494    {"var myobject = {", "};"},
2495    {"var myobject = {", ",};"},
2496    { NULL, NULL }
2497  };
2498
2499  // These are only errors in strict mode.
2500  const char* statement_data[] = {
2501    "foo: 1, foo: 2",
2502    "\"foo\": 1, \"foo\": 2",
2503    "foo: 1, \"foo\": 2",
2504    "1: 1, 1: 2",
2505    "1: 1, \"1\": 2",
2506    "get: 1, get: 2",  // Not a getter for real, just a property called get.
2507    "set: 1, set: 2",  // Not a setter for real, just a property called set.
2508    NULL
2509  };
2510
2511  RunParserSyncTest(non_strict_context_data, statement_data, kSuccess);
2512  RunParserSyncTest(strict_context_data, statement_data, kError);
2513}
2514
2515
2516TEST(ErrorsObjectLiteralChecking) {
2517  const char* context_data[][2] = {
2518    {"\"use strict\"; var myobject = {", "};"},
2519    {"var myobject = {", "};"},
2520    { NULL, NULL }
2521  };
2522
2523  const char* statement_data[] = {
2524      ",",
2525      "foo: 1, get foo() {}",
2526      "foo: 1, set foo(v) {}",
2527      "\"foo\": 1, get \"foo\"() {}",
2528      "\"foo\": 1, set \"foo\"(v) {}",
2529      "1: 1, get 1() {}",
2530      "1: 1, set 1() {}",
2531      "get foo() {}, get foo() {}",
2532      "set foo(_) {}, set foo(_) {}",
2533      // It's counter-intuitive, but these collide too (even in classic
2534      // mode). Note that we can have "foo" and foo as properties in classic
2535      // mode,
2536      // but we cannot have "foo" and get foo, or foo and get "foo".
2537      "foo: 1, get \"foo\"() {}",
2538      "foo: 1, set \"foo\"(v) {}",
2539      "\"foo\": 1, get foo() {}",
2540      "\"foo\": 1, set foo(v) {}",
2541      "1: 1, get \"1\"() {}",
2542      "1: 1, set \"1\"() {}",
2543      "\"1\": 1, get 1() {}"
2544      "\"1\": 1, set 1(v) {}"
2545      // Wrong number of parameters
2546      "get bar(x) {}",
2547      "get bar(x, y) {}",
2548      "set bar() {}",
2549      "set bar(x, y) {}",
2550      // Parsing FunctionLiteral for getter or setter fails
2551      "get foo( +",
2552      "get foo() \"error\"",
2553      NULL};
2554
2555  RunParserSyncTest(context_data, statement_data, kError);
2556}
2557
2558
2559TEST(NoErrorsObjectLiteralChecking) {
2560  const char* context_data[][2] = {
2561    {"var myobject = {", "};"},
2562    {"var myobject = {", ",};"},
2563    {"\"use strict\"; var myobject = {", "};"},
2564    {"\"use strict\"; var myobject = {", ",};"},
2565    { NULL, NULL }
2566  };
2567
2568  const char* statement_data[] = {
2569    "foo: 1, bar: 2",
2570    "\"foo\": 1, \"bar\": 2",
2571    "1: 1, 2: 2",
2572    // Syntax: IdentifierName ':' AssignmentExpression
2573    "foo: bar = 5 + baz",
2574    // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2575    "get foo() {}",
2576    "get \"foo\"() {}",
2577    "get 1() {}",
2578    // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2579    //     '{' FunctionBody '}'
2580    "set foo(v) {}",
2581    "set \"foo\"(v) {}",
2582    "set 1(v) {}",
2583    // Non-colliding getters and setters -> no errors
2584    "foo: 1, get bar() {}",
2585    "foo: 1, set bar(v) {}",
2586    "\"foo\": 1, get \"bar\"() {}",
2587    "\"foo\": 1, set \"bar\"(v) {}",
2588    "1: 1, get 2() {}",
2589    "1: 1, set 2(v) {}",
2590    "get: 1, get foo() {}",
2591    "set: 1, set foo(_) {}",
2592    // Keywords, future reserved and strict future reserved are also allowed as
2593    // property names.
2594    "if: 4",
2595    "interface: 5",
2596    "super: 6",
2597    "eval: 7",
2598    "arguments: 8",
2599    NULL
2600  };
2601
2602  RunParserSyncTest(context_data, statement_data, kSuccess);
2603}
2604
2605
2606TEST(TooManyArguments) {
2607  const char* context_data[][2] = {
2608    {"foo(", "0)"},
2609    { NULL, NULL }
2610  };
2611
2612  using v8::internal::Code;
2613  char statement[Code::kMaxArguments * 2 + 1];
2614  for (int i = 0; i < Code::kMaxArguments; ++i) {
2615    statement[2 * i] = '0';
2616    statement[2 * i + 1] = ',';
2617  }
2618  statement[Code::kMaxArguments * 2] = 0;
2619
2620  const char* statement_data[] = {
2621    statement,
2622    NULL
2623  };
2624
2625  // The test is quite slow, so run it with a reduced set of flags.
2626  static const ParserFlag empty_flags[] = {kAllowLazy};
2627  RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2628}
2629
2630
2631TEST(StrictDelete) {
2632  // "delete <Identifier>" is not allowed in strict mode.
2633  const char* strict_context_data[][2] = {
2634    {"\"use strict\"; ", ""},
2635    { NULL, NULL }
2636  };
2637
2638  const char* sloppy_context_data[][2] = {
2639    {"", ""},
2640    { NULL, NULL }
2641  };
2642
2643  // These are errors in the strict mode.
2644  const char* sloppy_statement_data[] = {
2645    "delete foo;",
2646    "delete foo + 1;",
2647    "delete (foo);",
2648    "delete eval;",
2649    "delete interface;",
2650    NULL
2651  };
2652
2653  // These are always OK
2654  const char* good_statement_data[] = {
2655    "delete this;",
2656    "delete 1;",
2657    "delete 1 + 2;",
2658    "delete foo();",
2659    "delete foo.bar;",
2660    "delete foo[bar];",
2661    "delete foo--;",
2662    "delete --foo;",
2663    "delete new foo();",
2664    "delete new foo(bar);",
2665    NULL
2666  };
2667
2668  // These are always errors
2669  const char* bad_statement_data[] = {
2670    "delete if;",
2671    NULL
2672  };
2673
2674  RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
2675  RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
2676
2677  RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
2678  RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
2679
2680  RunParserSyncTest(strict_context_data, bad_statement_data, kError);
2681  RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
2682}
2683
2684
2685TEST(InvalidLeftHandSide) {
2686  const char* assignment_context_data[][2] = {
2687    {"", " = 1;"},
2688    {"\"use strict\"; ", " = 1;"},
2689    { NULL, NULL }
2690  };
2691
2692  const char* prefix_context_data[][2] = {
2693    {"++", ";"},
2694    {"\"use strict\"; ++", ";"},
2695    {NULL, NULL},
2696  };
2697
2698  const char* postfix_context_data[][2] = {
2699    {"", "++;"},
2700    {"\"use strict\"; ", "++;"},
2701    { NULL, NULL }
2702  };
2703
2704  // Good left hand sides for assigment or prefix / postfix operations.
2705  const char* good_statement_data[] = {
2706    "foo",
2707    "foo.bar",
2708    "foo[bar]",
2709    "foo()[bar]",
2710    "foo().bar",
2711    "this.foo",
2712    "this[foo]",
2713    "new foo()[bar]",
2714    "new foo().bar",
2715    "foo()",
2716    "foo(bar)",
2717    "foo[bar]()",
2718    "foo.bar()",
2719    "this()",
2720    "this.foo()",
2721    "this[foo].bar()",
2722    "this.foo[foo].bar(this)(bar)[foo]()",
2723    NULL
2724  };
2725
2726  // Bad left hand sides for assigment or prefix / postfix operations.
2727  const char* bad_statement_data_common[] = {
2728    "2",
2729    "new foo",
2730    "new foo()",
2731    "null",
2732    "if",  // Unexpected token
2733    "{x: 1}",  // Unexpected token
2734    "this",
2735    "\"bar\"",
2736    "(foo + bar)",
2737    "new new foo()[bar]",  // means: new (new foo()[bar])
2738    "new new foo().bar",  // means: new (new foo()[bar])
2739    NULL
2740  };
2741
2742  // These are not okay for assignment, but okay for prefix / postix.
2743  const char* bad_statement_data_for_assignment[] = {
2744    "++foo",
2745    "foo++",
2746    "foo + bar",
2747    NULL
2748  };
2749
2750  RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
2751  RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
2752  RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
2753                    kError);
2754
2755  RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
2756  RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
2757
2758  RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
2759  RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
2760}
2761
2762
2763TEST(FuncNameInferrerBasic) {
2764  // Tests that function names are inferred properly.
2765  i::FLAG_allow_natives_syntax = true;
2766  v8::Isolate* isolate = CcTest::isolate();
2767  v8::HandleScope scope(isolate);
2768  LocalContext env;
2769  CompileRun("var foo1 = function() {}; "
2770             "var foo2 = function foo3() {}; "
2771             "function not_ctor() { "
2772             "  var foo4 = function() {}; "
2773             "  return %FunctionGetInferredName(foo4); "
2774             "} "
2775             "function Ctor() { "
2776             "  var foo5 = function() {}; "
2777             "  return %FunctionGetInferredName(foo5); "
2778             "} "
2779             "var obj1 = { foo6: function() {} }; "
2780             "var obj2 = { 'foo7': function() {} }; "
2781             "var obj3 = {}; "
2782             "obj3[1] = function() {}; "
2783             "var obj4 = {}; "
2784             "obj4[1] = function foo8() {}; "
2785             "var obj5 = {}; "
2786             "obj5['foo9'] = function() {}; "
2787             "var obj6 = { obj7 : { foo10: function() {} } };");
2788  ExpectString("%FunctionGetInferredName(foo1)", "foo1");
2789  // foo2 is not unnamed -> its name is not inferred.
2790  ExpectString("%FunctionGetInferredName(foo2)", "");
2791  ExpectString("not_ctor()", "foo4");
2792  ExpectString("Ctor()", "Ctor.foo5");
2793  ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
2794  ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
2795  ExpectString("%FunctionGetInferredName(obj3[1])",
2796               "obj3.(anonymous function)");
2797  ExpectString("%FunctionGetInferredName(obj4[1])", "");
2798  ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
2799  ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
2800}
2801
2802
2803TEST(FuncNameInferrerTwoByte) {
2804  // Tests function name inferring in cases where some parts of the inferred
2805  // function name are two-byte strings.
2806  i::FLAG_allow_natives_syntax = true;
2807  v8::Isolate* isolate = CcTest::isolate();
2808  v8::HandleScope scope(isolate);
2809  LocalContext env;
2810  uint16_t* two_byte_source = AsciiToTwoByteString(
2811      "var obj1 = { oXj2 : { foo1: function() {} } }; "
2812      "%FunctionGetInferredName(obj1.oXj2.foo1)");
2813  uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2814  // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
2815  two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
2816  v8::Local<v8::String> source =
2817      v8::String::NewFromTwoByte(isolate, two_byte_source);
2818  v8::Local<v8::Value> result = CompileRun(source);
2819  CHECK(result->IsString());
2820  v8::Local<v8::String> expected_name =
2821      v8::String::NewFromTwoByte(isolate, two_byte_name);
2822  CHECK(result->Equals(expected_name));
2823  i::DeleteArray(two_byte_source);
2824  i::DeleteArray(two_byte_name);
2825}
2826
2827
2828TEST(FuncNameInferrerEscaped) {
2829  // The same as FuncNameInferrerTwoByte, except that we express the two-byte
2830  // character as a unicode escape.
2831  i::FLAG_allow_natives_syntax = true;
2832  v8::Isolate* isolate = CcTest::isolate();
2833  v8::HandleScope scope(isolate);
2834  LocalContext env;
2835  uint16_t* two_byte_source = AsciiToTwoByteString(
2836      "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
2837      "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
2838  uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2839  // Fix to correspond to the non-ASCII name in two_byte_source.
2840  two_byte_name[6] = 0x010d;
2841  v8::Local<v8::String> source =
2842      v8::String::NewFromTwoByte(isolate, two_byte_source);
2843  v8::Local<v8::Value> result = CompileRun(source);
2844  CHECK(result->IsString());
2845  v8::Local<v8::String> expected_name =
2846      v8::String::NewFromTwoByte(isolate, two_byte_name);
2847  CHECK(result->Equals(expected_name));
2848  i::DeleteArray(two_byte_source);
2849  i::DeleteArray(two_byte_name);
2850}
2851
2852
2853TEST(RegressionLazyFunctionWithErrorWithArg) {
2854  // The bug occurred when a lazy function had an error which requires a
2855  // parameter (such as "unknown label" here). The error message was processed
2856  // before the AstValueFactory containing the error message string was
2857  // internalized.
2858  v8::Isolate* isolate = CcTest::isolate();
2859  v8::HandleScope scope(isolate);
2860  LocalContext env;
2861  i::FLAG_lazy = true;
2862  i::FLAG_min_preparse_length = 0;
2863  CompileRun("function this_is_lazy() {\n"
2864             "  break p;\n"
2865             "}\n"
2866             "this_is_lazy();\n");
2867}
2868
2869
2870TEST(SerializationOfMaybeAssignmentFlag) {
2871  i::Isolate* isolate = CcTest::i_isolate();
2872  i::Factory* factory = isolate->factory();
2873  i::HandleScope scope(isolate);
2874  LocalContext env;
2875
2876  const char* src =
2877      "function h() {"
2878      "  var result = [];"
2879      "  function f() {"
2880      "    result.push(2);"
2881      "  }"
2882      "  function assertResult(r) {"
2883      "    f();"
2884      "    result = [];"
2885      "  }"
2886      "  assertResult([2]);"
2887      "  assertResult([2]);"
2888      "  return f;"
2889      "};"
2890      "h();";
2891
2892  i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
2893  i::SNPrintF(program, "%s", src);
2894  i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
2895  source->PrintOn(stdout);
2896  printf("\n");
2897  i::Zone zone(isolate);
2898  v8::Local<v8::Value> v = CompileRun(src);
2899  i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
2900  i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
2901  i::Context* context = f->context();
2902  i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
2903  avf.Internalize(isolate);
2904  const i::AstRawString* name = avf.GetOneByteString("result");
2905  i::Handle<i::String> str = name->string();
2906  CHECK(str->IsInternalizedString());
2907  i::Scope* global_scope =
2908      new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
2909  global_scope->Initialize();
2910  i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
2911  DCHECK(s != global_scope);
2912  DCHECK(name != NULL);
2913
2914  // Get result from h's function context (that is f's context)
2915  i::Variable* var = s->Lookup(name);
2916
2917  CHECK(var != NULL);
2918  // Maybe assigned should survive deserialization
2919  CHECK(var->maybe_assigned() == i::kMaybeAssigned);
2920  // TODO(sigurds) Figure out if is_used should survive context serialization.
2921}
2922
2923
2924TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
2925  i::Isolate* isolate = CcTest::i_isolate();
2926  i::Factory* factory = isolate->factory();
2927  i::HandleScope scope(isolate);
2928  LocalContext env;
2929
2930
2931  const char* src =
2932      "function f(x) {"
2933      "    var a = arguments;"
2934      "    function g(i) {"
2935      "      ++a[0];"
2936      "    };"
2937      "    return g;"
2938      "  }"
2939      "f(0);";
2940
2941  i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
2942  i::SNPrintF(program, "%s", src);
2943  i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
2944  source->PrintOn(stdout);
2945  printf("\n");
2946  i::Zone zone(isolate);
2947  v8::Local<v8::Value> v = CompileRun(src);
2948  i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
2949  i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
2950  i::Context* context = f->context();
2951  i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
2952  avf.Internalize(isolate);
2953
2954  i::Scope* global_scope =
2955      new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
2956  global_scope->Initialize();
2957  i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
2958  DCHECK(s != global_scope);
2959  const i::AstRawString* name_x = avf.GetOneByteString("x");
2960
2961  // Get result from f's function context (that is g's outer context)
2962  i::Variable* var_x = s->Lookup(name_x);
2963  CHECK(var_x != NULL);
2964  CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
2965}
2966
2967
2968TEST(ExportsMaybeAssigned) {
2969  i::FLAG_use_strict = true;
2970  i::FLAG_harmony_scoping = true;
2971  i::FLAG_harmony_modules = true;
2972
2973  i::Isolate* isolate = CcTest::i_isolate();
2974  i::Factory* factory = isolate->factory();
2975  i::HandleScope scope(isolate);
2976  LocalContext env;
2977
2978  const char* src =
2979      "module A {"
2980      "  export var x = 1;"
2981      "  export function f() { return x };"
2982      "  export const y = 2;"
2983      "  module B {}"
2984      "  export module C {}"
2985      "};"
2986      "A.f";
2987
2988  i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
2989  i::SNPrintF(program, "%s", src);
2990  i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
2991  source->PrintOn(stdout);
2992  printf("\n");
2993  i::Zone zone(isolate);
2994  v8::Local<v8::Value> v = CompileRun(src);
2995  i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
2996  i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
2997  i::Context* context = f->context();
2998  i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
2999  avf.Internalize(isolate);
3000
3001  i::Scope* global_scope =
3002      new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
3003  global_scope->Initialize();
3004  i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
3005  DCHECK(s != global_scope);
3006  const i::AstRawString* name_x = avf.GetOneByteString("x");
3007  const i::AstRawString* name_f = avf.GetOneByteString("f");
3008  const i::AstRawString* name_y = avf.GetOneByteString("y");
3009  const i::AstRawString* name_B = avf.GetOneByteString("B");
3010  const i::AstRawString* name_C = avf.GetOneByteString("C");
3011
3012  // Get result from h's function context (that is f's context)
3013  i::Variable* var_x = s->Lookup(name_x);
3014  CHECK(var_x != NULL);
3015  CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3016  i::Variable* var_f = s->Lookup(name_f);
3017  CHECK(var_f != NULL);
3018  CHECK(var_f->maybe_assigned() == i::kMaybeAssigned);
3019  i::Variable* var_y = s->Lookup(name_y);
3020  CHECK(var_y != NULL);
3021  CHECK(var_y->maybe_assigned() == i::kNotAssigned);
3022  i::Variable* var_B = s->Lookup(name_B);
3023  CHECK(var_B != NULL);
3024  CHECK(var_B->maybe_assigned() == i::kNotAssigned);
3025  i::Variable* var_C = s->Lookup(name_C);
3026  CHECK(var_C != NULL);
3027  CHECK(var_C->maybe_assigned() == i::kNotAssigned);
3028}
3029
3030
3031TEST(InnerAssignment) {
3032  i::Isolate* isolate = CcTest::i_isolate();
3033  i::Factory* factory = isolate->factory();
3034  i::HandleScope scope(isolate);
3035  LocalContext env;
3036
3037  const char* prefix = "function f() {";
3038  const char* midfix = " function g() {";
3039  const char* suffix = "}}";
3040  struct { const char* source; bool assigned; bool strict; } outers[] = {
3041    // Actual assignments.
3042    { "var x; var x = 5;", true, false },
3043    { "var x; { var x = 5; }", true, false },
3044    { "'use strict'; let x; x = 6;", true, true },
3045    { "var x = 5; function x() {}", true, false },
3046    // Actual non-assignments.
3047    { "var x;", false, false },
3048    { "var x = 5;", false, false },
3049    { "'use strict'; let x;", false, true },
3050    { "'use strict'; let x = 6;", false, true },
3051    { "'use strict'; var x = 0; { let x = 6; }", false, true },
3052    { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3053    { "'use strict'; let x = 0; { let x = 6; }", false, true },
3054    { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3055    { "var x; try {} catch (x) { x = 5; }", false, false },
3056    { "function x() {}", false, false },
3057    // Eval approximation.
3058    { "var x; eval('');", true, false },
3059    { "eval(''); var x;", true, false },
3060    { "'use strict'; let x; eval('');", true, true },
3061    { "'use strict'; eval(''); let x;", true, true },
3062    // Non-assignments not recognized, because the analysis is approximative.
3063    { "var x; var x;", true, false },
3064    { "var x = 5; var x;", true, false },
3065    { "var x; { var x; }", true, false },
3066    { "var x; function x() {}", true, false },
3067    { "function x() {}; var x;", true, false },
3068    { "var x; try {} catch (x) { var x = 5; }", true, false },
3069  };
3070  struct { const char* source; bool assigned; bool with; } inners[] = {
3071    // Actual assignments.
3072    { "x = 1;", true, false },
3073    { "x++;", true, false },
3074    { "++x;", true, false },
3075    { "x--;", true, false },
3076    { "--x;", true, false },
3077    { "{ x = 1; }", true, false },
3078    { "'use strict'; { let x; }; x = 0;", true, false },
3079    { "'use strict'; { const x = 1; }; x = 0;", true, false },
3080    { "'use strict'; { function x() {} }; x = 0;", true, false },
3081    { "with ({}) { x = 1; }", true, true },
3082    { "eval('');", true, false },
3083    { "'use strict'; { let y; eval('') }", true, false },
3084    { "function h() { x = 0; }", true, false },
3085    { "(function() { x = 0; })", true, false },
3086    { "(function() { x = 0; })", true, false },
3087    { "with ({}) (function() { x = 0; })", true, true },
3088    // Actual non-assignments.
3089    { "", false, false },
3090    { "x;", false, false },
3091    { "var x;", false, false },
3092    { "var x = 8;", false, false },
3093    { "var x; x = 8;", false, false },
3094    { "'use strict'; let x;", false, false },
3095    { "'use strict'; let x = 8;", false, false },
3096    { "'use strict'; let x; x = 8;", false, false },
3097    { "'use strict'; const x = 8;", false, false },
3098    { "function x() {}", false, false },
3099    { "function x() { x = 0; }", false, false },
3100    { "function h(x) { x = 0; }", false, false },
3101    { "'use strict'; { let x; x = 0; }", false, false },
3102    { "{ var x; }; x = 0;", false, false },
3103    { "with ({}) {}", false, true },
3104    { "var x; { with ({}) { x = 1; } }", false, true },
3105    { "try {} catch(x) { x = 0; }", false, false },
3106    { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3107    // Eval approximation.
3108    { "eval('');", true, false },
3109    { "function h() { eval(''); }", true, false },
3110    { "(function() { eval(''); })", true, false },
3111    // Shadowing not recognized because of eval approximation.
3112    { "var x; eval('');", true, false },
3113    { "'use strict'; let x; eval('');", true, false },
3114    { "try {} catch(x) { eval(''); }", true, false },
3115    { "function x() { eval(''); }", true, false },
3116    { "(function(x) { eval(''); })", true, false },
3117  };
3118
3119  // Used to trigger lazy compilation of function
3120  int comment_len = 2048;
3121  i::ScopedVector<char> comment(comment_len + 1);
3122  i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3123  int prefix_len = Utf8LengthHelper(prefix);
3124  int midfix_len = Utf8LengthHelper(midfix);
3125  int suffix_len = Utf8LengthHelper(suffix);
3126  for (unsigned i = 0; i < arraysize(outers); ++i) {
3127    const char* outer = outers[i].source;
3128    int outer_len = Utf8LengthHelper(outer);
3129    for (unsigned j = 0; j < arraysize(inners); ++j) {
3130      for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3131        for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3132          if (outers[i].strict && inners[j].with) continue;
3133          const char* inner = inners[j].source;
3134          int inner_len = Utf8LengthHelper(inner);
3135
3136          int outer_comment_len = outer_lazy ? comment_len : 0;
3137          int inner_comment_len = inner_lazy ? comment_len : 0;
3138          const char* outer_comment = outer_lazy ? comment.start() : "";
3139          const char* inner_comment = inner_lazy ? comment.start() : "";
3140          int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3141                    inner_comment_len + inner_len + suffix_len;
3142          i::ScopedVector<char> program(len + 1);
3143
3144          i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3145                      midfix, inner_comment, inner, suffix);
3146          i::Handle<i::String> source =
3147              factory->InternalizeUtf8String(program.start());
3148          source->PrintOn(stdout);
3149          printf("\n");
3150
3151          i::Handle<i::Script> script = factory->NewScript(source);
3152          i::CompilationInfoWithZone info(script);
3153          i::Parser::ParseInfo parse_info = {
3154              isolate->stack_guard()->real_climit(),
3155              isolate->heap()->HashSeed(), isolate->unicode_cache()};
3156          i::Parser parser(&info, &parse_info);
3157          parser.set_allow_harmony_scoping(true);
3158          CHECK(parser.Parse());
3159          CHECK(i::Rewriter::Rewrite(&info));
3160          CHECK(i::Scope::Analyze(&info));
3161          CHECK(info.function() != NULL);
3162
3163          i::Scope* scope = info.function()->scope();
3164          CHECK_EQ(scope->inner_scopes()->length(), 1);
3165          i::Scope* inner_scope = scope->inner_scopes()->at(0);
3166          const i::AstRawString* var_name =
3167              info.ast_value_factory()->GetOneByteString("x");
3168          i::Variable* var = inner_scope->Lookup(var_name);
3169          bool expected = outers[i].assigned || inners[j].assigned;
3170          CHECK(var != NULL);
3171          CHECK(var->is_used() || !expected);
3172          CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3173        }
3174      }
3175    }
3176  }
3177}
3178
3179namespace {
3180
3181int* global_use_counts = NULL;
3182
3183void MockUseCounterCallback(v8::Isolate* isolate,
3184                            v8::Isolate::UseCounterFeature feature) {
3185  ++global_use_counts[feature];
3186}
3187
3188}
3189
3190
3191TEST(UseAsmUseCount) {
3192  i::Isolate* isolate = CcTest::i_isolate();
3193  i::HandleScope scope(isolate);
3194  LocalContext env;
3195  int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3196  global_use_counts = use_counts;
3197  CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3198  CompileRun("\"use asm\";\n"
3199             "var foo = 1;\n"
3200             "\"use asm\";\n"  // Only the first one counts.
3201             "function bar() { \"use asm\"; var baz = 1; }");
3202  CHECK_EQ(2, use_counts[v8::Isolate::kUseAsm]);
3203}
3204
3205
3206TEST(ErrorsArrowFunctions) {
3207  // Tests that parser and preparser generate the same kind of errors
3208  // on invalid arrow function syntax.
3209  const char* context_data[][2] = {
3210    {"", ";"},
3211    {"v = ", ";"},
3212    {"bar ? (", ") : baz;"},
3213    {"bar ? baz : (", ");"},
3214    {"bar[", "];"},
3215    {"bar, ", ";"},
3216    {"", ", bar;"},
3217    {NULL, NULL}
3218  };
3219
3220  const char* statement_data[] = {
3221    "=> 0",
3222    "=>",
3223    "() =>",
3224    "=> {}",
3225    ") => {}",
3226    ", => {}",
3227    "(,) => {}",
3228    "return => {}",
3229    "() => {'value': 42}",
3230
3231    // Check that the early return introduced in ParsePrimaryExpression
3232    // does not accept stray closing parentheses.
3233    ")",
3234    ") => 0",
3235    "foo[()]",
3236    "()",
3237
3238    // Parameter lists with extra parens should be recognized as errors.
3239    "(()) => 0",
3240    "((x)) => 0",
3241    "((x, y)) => 0",
3242    "(x, (y)) => 0",
3243    "((x, y, z)) => 0",
3244    "(x, (y, z)) => 0",
3245    "((x, y), z) => 0",
3246
3247    // Parameter lists are always validated as strict, so those are errors.
3248    "eval => {}",
3249    "arguments => {}",
3250    "yield => {}",
3251    "interface => {}",
3252    "(eval) => {}",
3253    "(arguments) => {}",
3254    "(yield) => {}",
3255    "(interface) => {}",
3256    "(eval, bar) => {}",
3257    "(bar, eval) => {}",
3258    "(bar, arguments) => {}",
3259    "(bar, yield) => {}",
3260    "(bar, interface) => {}",
3261    // TODO(aperez): Detecting duplicates does not work in PreParser.
3262    // "(bar, bar) => {}",
3263
3264    // The parameter list is parsed as an expression, but only
3265    // a comma-separated list of identifier is valid.
3266    "32 => {}",
3267    "(32) => {}",
3268    "(a, 32) => {}",
3269    "if => {}",
3270    "(if) => {}",
3271    "(a, if) => {}",
3272    "a + b => {}",
3273    "(a + b) => {}",
3274    "(a + b, c) => {}",
3275    "(a, b - c) => {}",
3276    "\"a\" => {}",
3277    "(\"a\") => {}",
3278    "(\"a\", b) => {}",
3279    "(a, \"b\") => {}",
3280    "-a => {}",
3281    "(-a) => {}",
3282    "(-a, b) => {}",
3283    "(a, -b) => {}",
3284    "{} => {}",
3285    "({}) => {}",
3286    "(a, {}) => {}",
3287    "({}, a) => {}",
3288    "a++ => {}",
3289    "(a++) => {}",
3290    "(a++, b) => {}",
3291    "(a, b++) => {}",
3292    "[] => {}",
3293    "([]) => {}",
3294    "(a, []) => {}",
3295    "([], a) => {}",
3296    "(a = b) => {}",
3297    "(a = b, c) => {}",
3298    "(a, b = c) => {}",
3299    "(foo ? bar : baz) => {}",
3300    "(a, foo ? bar : baz) => {}",
3301    "(foo ? bar : baz, a) => {}",
3302    NULL
3303  };
3304
3305  // The test is quite slow, so run it with a reduced set of flags.
3306  static const ParserFlag flags[] = {kAllowLazy, kAllowHarmonyScoping};
3307  static const ParserFlag always_flags[] = { kAllowArrowFunctions };
3308  RunParserSyncTest(context_data, statement_data, kError, flags,
3309                    arraysize(flags), always_flags, arraysize(always_flags));
3310}
3311
3312
3313TEST(NoErrorsArrowFunctions) {
3314  // Tests that parser and preparser accept valid arrow functions syntax.
3315  const char* context_data[][2] = {
3316    {"", ";"},
3317    {"bar ? (", ") : baz;"},
3318    {"bar ? baz : (", ");"},
3319    {"bar, ", ";"},
3320    {"", ", bar;"},
3321    {NULL, NULL}
3322  };
3323
3324  const char* statement_data[] = {
3325    "() => {}",
3326    "() => { return 42 }",
3327    "x => { return x; }",
3328    "(x) => { return x; }",
3329    "(x, y) => { return x + y; }",
3330    "(x, y, z) => { return x + y + z; }",
3331    "(x, y) => { x.a = y; }",
3332    "() => 42",
3333    "x => x",
3334    "x => x * x",
3335    "(x) => x",
3336    "(x) => x * x",
3337    "(x, y) => x + y",
3338    "(x, y, z) => x, y, z",
3339    "(x, y) => x.a = y",
3340    "() => ({'value': 42})",
3341    "x => y => x + y",
3342    "(x, y) => (u, v) => x*u + y*v",
3343    "(x, y) => z => z * (x + y)",
3344    "x => (y, z) => z * (x + y)",
3345
3346    // Those are comma-separated expressions, with arrow functions as items.
3347    // They stress the code for validating arrow function parameter lists.
3348    "a, b => 0",
3349    "a, b, (c, d) => 0",
3350    "(a, b, (c, d) => 0)",
3351    "(a, b) => 0, (c, d) => 1",
3352    "(a, b => {}, a => a + 1)",
3353    "((a, b) => {}, (a => a + 1))",
3354    "(a, (a, (b, c) => 0))",
3355
3356    // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3357    "foo ? bar : baz => {}",
3358    NULL
3359  };
3360
3361  static const ParserFlag always_flags[] = {kAllowArrowFunctions};
3362  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3363                    always_flags, arraysize(always_flags));
3364}
3365
3366
3367TEST(NoErrorsSuper) {
3368  // Tests that parser and preparser accept 'super' keyword in right places.
3369  const char* context_data[][2] = {{"", ";"},
3370                                   {"k = ", ";"},
3371                                   {"foo(", ");"},
3372                                   {NULL, NULL}};
3373
3374  const char* statement_data[] = {
3375    "super.x",
3376    "super[27]",
3377    "new super",
3378    "new super()",
3379    "new super(12, 45)",
3380    "new new super",
3381    "new new super()",
3382    "new new super()()",
3383    "z.super",  // Ok, property lookup.
3384    NULL};
3385
3386  static const ParserFlag always_flags[] = {kAllowClasses};
3387  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3388                    always_flags, arraysize(always_flags));
3389}
3390
3391
3392TEST(ErrorsSuper) {
3393  // Tests that parser and preparser generate same errors for 'super'.
3394  const char* context_data[][2] = {{"", ";"},
3395                                   {"k = ", ";"},
3396                                   {"foo(", ");"},
3397                                   {NULL, NULL}};
3398
3399  const char* statement_data[] = {
3400    "super = x",
3401    "y = super",
3402    "f(super)",
3403    NULL};
3404
3405  static const ParserFlag always_flags[] = {kAllowClasses};
3406  RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
3407                    always_flags, arraysize(always_flags));
3408}
3409
3410
3411TEST(NoErrorsMethodDefinition) {
3412  const char* context_data[][2] = {{"({", "});"},
3413                                   {"'use strict'; ({", "});"},
3414                                   {"({*", "});"},
3415                                   {"'use strict'; ({*", "});"},
3416                                   {NULL, NULL}};
3417
3418  const char* object_literal_body_data[] = {
3419    "m() {}",
3420    "m(x) { return x; }",
3421    "m(x, y) {}, n() {}",
3422    "set(x, y) {}",
3423    "get(x, y) {}",
3424    NULL
3425  };
3426
3427  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3428  RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0,
3429                    always_flags, arraysize(always_flags));
3430}
3431
3432
3433TEST(MethodDefinitionNames) {
3434  const char* context_data[][2] = {{"({", "(x, y) {}});"},
3435                                   {"'use strict'; ({", "(x, y) {}});"},
3436                                   {"({*", "(x, y) {}});"},
3437                                   {"'use strict'; ({*", "(x, y) {}});"},
3438                                   {NULL, NULL}};
3439
3440  const char* name_data[] = {
3441    "m",
3442    "'m'",
3443    "\"m\"",
3444    "\"m n\"",
3445    "true",
3446    "false",
3447    "null",
3448    "0",
3449    "1.2",
3450    "1e1",
3451    "1E1",
3452    "1e+1",
3453    "1e-1",
3454
3455    // Keywords
3456    "async",
3457    "await",
3458    "break",
3459    "case",
3460    "catch",
3461    "class",
3462    "const",
3463    "continue",
3464    "debugger",
3465    "default",
3466    "delete",
3467    "do",
3468    "else",
3469    "enum",
3470    "export",
3471    "extends",
3472    "finally",
3473    "for",
3474    "function",
3475    "if",
3476    "implements",
3477    "import",
3478    "in",
3479    "instanceof",
3480    "interface",
3481    "let",
3482    "new",
3483    "package",
3484    "private",
3485    "protected",
3486    "public",
3487    "return",
3488    "static",
3489    "super",
3490    "switch",
3491    "this",
3492    "throw",
3493    "try",
3494    "typeof",
3495    "var",
3496    "void",
3497    "while",
3498    "with",
3499    "yield",
3500    NULL
3501  };
3502
3503  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3504  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
3505                    always_flags, arraysize(always_flags));
3506}
3507
3508
3509TEST(MethodDefinitionStrictFormalParamereters) {
3510  const char* context_data[][2] = {{"({method(", "){}});"},
3511                                   {"'use strict'; ({method(", "){}});"},
3512                                   {"({*method(", "){}});"},
3513                                   {"'use strict'; ({*method(", "){}});"},
3514                                   {NULL, NULL}};
3515
3516  const char* params_data[] = {
3517    "x, x",
3518    "x, y, x",
3519    "eval",
3520    "arguments",
3521    "var",
3522    "const",
3523    NULL
3524  };
3525
3526  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3527  RunParserSyncTest(context_data, params_data, kError, NULL, 0,
3528                    always_flags, arraysize(always_flags));
3529}
3530
3531
3532TEST(MethodDefinitionDuplicateProperty) {
3533  // Duplicate properties are allowed in ES6 but we haven't removed that check
3534  // yet.
3535  const char* context_data[][2] = {{"'use strict'; ({", "});"},
3536                                   {NULL, NULL}};
3537
3538  const char* params_data[] = {
3539    "x: 1, x() {}",
3540    "x() {}, x: 1",
3541    "x() {}, get x() {}",
3542    "x() {}, set x(_) {}",
3543    "x() {}, x() {}",
3544    "x() {}, y() {}, x() {}",
3545    "x() {}, \"x\"() {}",
3546    "x() {}, 'x'() {}",
3547    "0() {}, '0'() {}",
3548    "1.0() {}, 1: 1",
3549
3550    "x: 1, *x() {}",
3551    "*x() {}, x: 1",
3552    "*x() {}, get x() {}",
3553    "*x() {}, set x(_) {}",
3554    "*x() {}, *x() {}",
3555    "*x() {}, y() {}, *x() {}",
3556    "*x() {}, *\"x\"() {}",
3557    "*x() {}, *'x'() {}",
3558    "*0() {}, *'0'() {}",
3559    "*1.0() {}, 1: 1",
3560
3561    NULL
3562  };
3563
3564  static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
3565  RunParserSyncTest(context_data, params_data, kError, NULL, 0,
3566                    always_flags, arraysize(always_flags));
3567}
3568
3569
3570TEST(ClassExpressionNoErrors) {
3571  const char* context_data[][2] = {{"(", ");"},
3572                                   {"var C = ", ";"},
3573                                   {"bar, ", ";"},
3574                                   {NULL, NULL}};
3575  const char* class_data[] = {
3576    "class {}",
3577    "class name {}",
3578    "class extends F {}",
3579    "class name extends F {}",
3580    "class extends (F, G) {}",
3581    "class name extends (F, G) {}",
3582    "class extends class {} {}",
3583    "class name extends class {} {}",
3584    "class extends class base {} {}",
3585    "class name extends class base {} {}",
3586    NULL};
3587
3588  static const ParserFlag always_flags[] = {kAllowClasses};
3589  RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
3590                    always_flags, arraysize(always_flags));
3591}
3592
3593
3594TEST(ClassDeclarationNoErrors) {
3595  const char* context_data[][2] = {{"", ""},
3596                                   {"{", "}"},
3597                                   {"if (true) {", "}"},
3598                                   {NULL, NULL}};
3599  const char* statement_data[] = {
3600    "class name {}",
3601    "class name extends F {}",
3602    "class name extends (F, G) {}",
3603    "class name extends class {} {}",
3604    "class name extends class base {} {}",
3605    NULL};
3606
3607  static const ParserFlag always_flags[] = {kAllowClasses};
3608  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3609                    always_flags, arraysize(always_flags));
3610}
3611
3612
3613TEST(ClassBodyNoErrors) {
3614  // Tests that parser and preparser accept valid class syntax.
3615  const char* context_data[][2] = {{"(class {", "});"},
3616                                   {"(class extends Base {", "});"},
3617                                   {"class C {", "}"},
3618                                   {"class C extends Base {", "}"},
3619                                   {NULL, NULL}};
3620  const char* class_body_data[] = {
3621    ";",
3622    ";;",
3623    "m() {}",
3624    "m() {};",
3625    "; m() {}",
3626    "m() {}; n(x) {}",
3627    "get x() {}",
3628    "set x(v) {}",
3629    "get() {}",
3630    "set() {}",
3631    "*g() {}",
3632    "*g() {};",
3633    "; *g() {}",
3634    "*g() {}; *h(x) {}",
3635    "static() {}",
3636    "static m() {}",
3637    "static get x() {}",
3638    "static set x(v) {}",
3639    "static get() {}",
3640    "static set() {}",
3641    "static static() {}",
3642    "static get static() {}",
3643    "static set static(v) {}",
3644    "*static() {}",
3645    "*get() {}",
3646    "*set() {}",
3647    "static *g() {}",
3648    NULL};
3649
3650  static const ParserFlag always_flags[] = {
3651    kAllowClasses,
3652    kAllowHarmonyObjectLiterals
3653  };
3654  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
3655                    always_flags, arraysize(always_flags));
3656}
3657
3658
3659TEST(ClassPropertyNameNoErrors) {
3660  const char* context_data[][2] = {{"(class {", "() {}});"},
3661                                   {"(class { get ", "() {}});"},
3662                                   {"(class { set ", "(v) {}});"},
3663                                   {"(class { static ", "() {}});"},
3664                                   {"(class { static get ", "() {}});"},
3665                                   {"(class { static set ", "(v) {}});"},
3666                                   {"(class { *", "() {}});"},
3667                                   {"(class { static *", "() {}});"},
3668                                   {"class C {", "() {}}"},
3669                                   {"class C { get ", "() {}}"},
3670                                   {"class C { set ", "(v) {}}"},
3671                                   {"class C { static ", "() {}}"},
3672                                   {"class C { static get ", "() {}}"},
3673                                   {"class C { static set ", "(v) {}}"},
3674                                   {"class C { *", "() {}}"},
3675                                   {"class C { static *", "() {}}"},
3676                                   {NULL, NULL}};
3677  const char* name_data[] = {
3678    "42",
3679    "42.5",
3680    "42e2",
3681    "42e+2",
3682    "42e-2",
3683    "null",
3684    "false",
3685    "true",
3686    "'str'",
3687    "\"str\"",
3688    "static",
3689    "get",
3690    "set",
3691    "var",
3692    "const",
3693    "let",
3694    "this",
3695    "class",
3696    "function",
3697    "yield",
3698    "if",
3699    "else",
3700    "for",
3701    "while",
3702    "do",
3703    "try",
3704    "catch",
3705    "finally",
3706    NULL};
3707
3708  static const ParserFlag always_flags[] = {
3709    kAllowClasses,
3710    kAllowHarmonyObjectLiterals
3711  };
3712  RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
3713                    always_flags, arraysize(always_flags));
3714}
3715
3716
3717TEST(ClassExpressionErrors) {
3718  const char* context_data[][2] = {{"(", ");"},
3719                                   {"var C = ", ";"},
3720                                   {"bar, ", ";"},
3721                                   {NULL, NULL}};
3722  const char* class_data[] = {
3723    "class",
3724    "class name",
3725    "class name extends",
3726    "class extends",
3727    "class {",
3728    "class { m }",
3729    "class { m; n }",
3730    "class { m: 1 }",
3731    "class { m(); n() }",
3732    "class { get m }",
3733    "class { get m() }",
3734    "class { get m() { }",
3735    "class { set m() {} }",  // Missing required parameter.
3736    "class { m() {}, n() {} }",  // No commas allowed.
3737    NULL};
3738
3739  static const ParserFlag always_flags[] = {
3740    kAllowClasses,
3741    kAllowHarmonyObjectLiterals
3742  };
3743  RunParserSyncTest(context_data, class_data, kError, NULL, 0,
3744                    always_flags, arraysize(always_flags));
3745}
3746
3747
3748TEST(ClassDeclarationErrors) {
3749  const char* context_data[][2] = {{"", ""},
3750                                   {"{", "}"},
3751                                   {"if (true) {", "}"},
3752                                   {NULL, NULL}};
3753  const char* class_data[] = {
3754    "class",
3755    "class name",
3756    "class name extends",
3757    "class extends",
3758    "class name {",
3759    "class name { m }",
3760    "class name { m; n }",
3761    "class name { m: 1 }",
3762    "class name { m(); n() }",
3763    "class name { get x }",
3764    "class name { get x() }",
3765    "class name { set x() {) }",  // missing required param
3766    "class {}",  // Name is required for declaration
3767    "class extends base {}",
3768    "class name { *",
3769    "class name { * }",
3770    "class name { *; }",
3771    "class name { *get x() {} }",
3772    "class name { *set x(_) {} }",
3773    "class name { *static m() {} }",
3774    NULL};
3775
3776  static const ParserFlag always_flags[] = {
3777    kAllowClasses,
3778    kAllowHarmonyNumericLiterals
3779  };
3780  RunParserSyncTest(context_data, class_data, kError, NULL, 0,
3781                    always_flags, arraysize(always_flags));
3782}
3783
3784
3785TEST(ClassNameErrors) {
3786  const char* context_data[][2] = {{"class ", "{}"},
3787                                   {"(class ", "{});"},
3788                                   {"'use strict'; class ", "{}"},
3789                                   {"'use strict'; (class ", "{});"},
3790                                   {NULL, NULL}};
3791  const char* class_name[] = {
3792    "arguments",
3793    "eval",
3794    "implements",
3795    "interface",
3796    "let",
3797    "package",
3798    "private",
3799    "protected",
3800    "public",
3801    "static",
3802    "var",
3803    "yield",
3804    NULL};
3805
3806  static const ParserFlag always_flags[] = {
3807    kAllowClasses,
3808    kAllowHarmonyObjectLiterals
3809  };
3810  RunParserSyncTest(context_data, class_name, kError, NULL, 0,
3811                    always_flags, arraysize(always_flags));
3812}
3813
3814
3815TEST(ClassGetterParamNameErrors) {
3816  const char* context_data[][2] = {
3817    {"class C { get name(", ") {} }"},
3818    {"(class { get name(", ") {} });"},
3819    {"'use strict'; class C { get name(", ") {} }"},
3820    {"'use strict'; (class { get name(", ") {} })"},
3821    {NULL, NULL}
3822  };
3823
3824  const char* class_name[] = {
3825    "arguments",
3826    "eval",
3827    "implements",
3828    "interface",
3829    "let",
3830    "package",
3831    "private",
3832    "protected",
3833    "public",
3834    "static",
3835    "var",
3836    "yield",
3837    NULL};
3838
3839  static const ParserFlag always_flags[] = {
3840    kAllowClasses,
3841    kAllowHarmonyObjectLiterals
3842  };
3843  RunParserSyncTest(context_data, class_name, kError, NULL, 0,
3844                    always_flags, arraysize(always_flags));
3845}
3846
3847
3848TEST(ClassStaticPrototypeErrors) {
3849  const char* context_data[][2] = {{"class C {", "}"},
3850                                   {"(class {", "});"},
3851                                   {NULL, NULL}};
3852
3853  const char* class_body_data[] = {
3854    "static prototype() {}",
3855    "static get prototype() {}",
3856    "static set prototype(_) {}",
3857    "static *prototype() {}",
3858    NULL};
3859
3860  static const ParserFlag always_flags[] = {
3861    kAllowClasses,
3862    kAllowHarmonyObjectLiterals
3863  };
3864  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
3865                    always_flags, arraysize(always_flags));
3866}
3867
3868
3869TEST(ClassSpecialConstructorErrors) {
3870  const char* context_data[][2] = {{"class C {", "}"},
3871                                   {"(class {", "});"},
3872                                   {NULL, NULL}};
3873
3874  const char* class_body_data[] = {
3875    "get constructor() {}",
3876    "get constructor(_) {}",
3877    "*constructor() {}",
3878    NULL};
3879
3880  static const ParserFlag always_flags[] = {
3881    kAllowClasses,
3882    kAllowHarmonyObjectLiterals
3883  };
3884  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
3885                    always_flags, arraysize(always_flags));
3886}
3887
3888
3889TEST(ClassConstructorNoErrors) {
3890  const char* context_data[][2] = {{"class C {", "}"},
3891                                   {"(class {", "});"},
3892                                   {NULL, NULL}};
3893
3894  const char* class_body_data[] = {
3895    "constructor() {}",
3896    "static constructor() {}",
3897    "static get constructor() {}",
3898    "static set constructor(_) {}",
3899    "static *constructor() {}",
3900    NULL};
3901
3902  static const ParserFlag always_flags[] = {
3903    kAllowClasses,
3904    kAllowHarmonyObjectLiterals
3905  };
3906  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
3907                    always_flags, arraysize(always_flags));
3908}
3909
3910
3911TEST(ClassMultipleConstructorErrors) {
3912  // We currently do not allow any duplicate properties in class bodies. This
3913  // test ensures that when we change that we still throw on duplicate
3914  // constructors.
3915  const char* context_data[][2] = {{"class C {", "}"},
3916                                   {"(class {", "});"},
3917                                   {NULL, NULL}};
3918
3919  const char* class_body_data[] = {
3920    "constructor() {}; constructor() {}",
3921    NULL};
3922
3923  static const ParserFlag always_flags[] = {
3924    kAllowClasses,
3925    kAllowHarmonyObjectLiterals
3926  };
3927  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
3928                    always_flags, arraysize(always_flags));
3929}
3930
3931
3932// TODO(arv): We should allow duplicate property names.
3933// https://code.google.com/p/v8/issues/detail?id=3570
3934DISABLED_TEST(ClassMultiplePropertyNamesNoErrors) {
3935  const char* context_data[][2] = {{"class C {", "}"},
3936                                   {"(class {", "});"},
3937                                   {NULL, NULL}};
3938
3939  const char* class_body_data[] = {
3940    "constructor() {}; static constructor() {}",
3941    "m() {}; static m() {}",
3942    "m() {}; m() {}",
3943    NULL};
3944
3945  static const ParserFlag always_flags[] = {
3946    kAllowClasses,
3947    kAllowHarmonyObjectLiterals
3948  };
3949  RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
3950                    always_flags, arraysize(always_flags));
3951}
3952
3953
3954TEST(ClassesAreStrictErrors) {
3955  const char* context_data[][2] = {{"", ""},
3956                                   {"(", ");"},
3957                                   {NULL, NULL}};
3958
3959  const char* class_body_data[] = {
3960    "class C { method() { with ({}) {} } }",
3961    "class C extends function() { with ({}) {} } {}",
3962    "class C { *method() { with ({}) {} } }",
3963    NULL};
3964
3965  static const ParserFlag always_flags[] = {
3966    kAllowClasses,
3967    kAllowHarmonyObjectLiterals
3968  };
3969  RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
3970                    always_flags, arraysize(always_flags));
3971}
3972