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 <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32#include "src/v8.h"
33
34#include "src/compiler.h"
35#include "src/execution.h"
36#include "src/isolate.h"
37#include "src/objects.h"
38#include "src/parser.h"
39#include "src/preparser.h"
40#include "src/scanner-character-streams.h"
41#include "src/token.h"
42#include "src/utils.h"
43#include "test/cctest/cctest.h"
44
45TEST(ScanKeywords) {
46  struct KeywordToken {
47    const char* keyword;
48    i::Token::Value token;
49  };
50
51  static const KeywordToken keywords[] = {
52#define KEYWORD(t, s, d) { s, i::Token::t },
53      TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
54#undef KEYWORD
55      { NULL, i::Token::IDENTIFIER }
56  };
57
58  KeywordToken key_token;
59  i::UnicodeCache unicode_cache;
60  i::byte buffer[32];
61  for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
62    const i::byte* keyword =
63        reinterpret_cast<const i::byte*>(key_token.keyword);
64    int length = i::StrLength(key_token.keyword);
65    CHECK(static_cast<int>(sizeof(buffer)) >= length);
66    {
67      i::Utf8ToUtf16CharacterStream stream(keyword, length);
68      i::Scanner scanner(&unicode_cache);
69      // The scanner should parse Harmony keywords for this test.
70      scanner.SetHarmonyScoping(true);
71      scanner.SetHarmonyModules(true);
72      scanner.Initialize(&stream);
73      CHECK_EQ(key_token.token, scanner.Next());
74      CHECK_EQ(i::Token::EOS, scanner.Next());
75    }
76    // Removing characters will make keyword matching fail.
77    {
78      i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
79      i::Scanner scanner(&unicode_cache);
80      scanner.Initialize(&stream);
81      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
82      CHECK_EQ(i::Token::EOS, scanner.Next());
83    }
84    // Adding characters will make keyword matching fail.
85    static const char chars_to_append[] = { 'z', '0', '_' };
86    for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
87      i::MemMove(buffer, keyword, length);
88      buffer[length] = chars_to_append[j];
89      i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
90      i::Scanner scanner(&unicode_cache);
91      scanner.Initialize(&stream);
92      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
93      CHECK_EQ(i::Token::EOS, scanner.Next());
94    }
95    // Replacing characters will make keyword matching fail.
96    {
97      i::MemMove(buffer, keyword, length);
98      buffer[length - 1] = '_';
99      i::Utf8ToUtf16CharacterStream stream(buffer, length);
100      i::Scanner scanner(&unicode_cache);
101      scanner.Initialize(&stream);
102      CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
103      CHECK_EQ(i::Token::EOS, scanner.Next());
104    }
105  }
106}
107
108
109TEST(ScanHTMLEndComments) {
110  v8::V8::Initialize();
111  v8::Isolate* isolate = CcTest::isolate();
112  v8::HandleScope handles(isolate);
113
114  // Regression test. See:
115  //    http://code.google.com/p/chromium/issues/detail?id=53548
116  // Tests that --> is correctly interpreted as comment-to-end-of-line if there
117  // is only whitespace before it on the line (with comments considered as
118  // whitespace, even a multiline-comment containing a newline).
119  // This was not the case if it occurred before the first real token
120  // in the input.
121  const char* tests[] = {
122      // Before first real token.
123      "--> is eol-comment\nvar y = 37;\n",
124      "\n --> is eol-comment\nvar y = 37;\n",
125      "/* precomment */ --> is eol-comment\nvar y = 37;\n",
126      "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
127      // After first real token.
128      "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
129      "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
130      NULL
131  };
132
133  const char* fail_tests[] = {
134      "x --> is eol-comment\nvar y = 37;\n",
135      "\"\\n\" --> is eol-comment\nvar y = 37;\n",
136      "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
137      "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
138      "var x = 42; --> is eol-comment\nvar y = 37;\n",
139      "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
140      NULL
141  };
142
143  // Parser/Scanner needs a stack limit.
144  int marker;
145  CcTest::i_isolate()->stack_guard()->SetStackLimit(
146      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
147  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
148  for (int i = 0; tests[i]; i++) {
149    const i::byte* source =
150        reinterpret_cast<const i::byte*>(tests[i]);
151    i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
152    i::CompleteParserRecorder log;
153    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
154    scanner.Initialize(&stream);
155    i::PreParser preparser(&scanner, &log, stack_limit);
156    preparser.set_allow_lazy(true);
157    i::PreParser::PreParseResult result = preparser.PreParseProgram();
158    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
159    i::ScriptData data(log.ExtractData());
160    CHECK(!data.has_error());
161  }
162
163  for (int i = 0; fail_tests[i]; i++) {
164    const i::byte* source =
165        reinterpret_cast<const i::byte*>(fail_tests[i]);
166    i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
167    i::CompleteParserRecorder log;
168    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
169    scanner.Initialize(&stream);
170    i::PreParser preparser(&scanner, &log, stack_limit);
171    preparser.set_allow_lazy(true);
172    i::PreParser::PreParseResult result = preparser.PreParseProgram();
173    // Even in the case of a syntax error, kPreParseSuccess is returned.
174    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
175    i::ScriptData data(log.ExtractData());
176    CHECK(data.has_error());
177  }
178}
179
180
181class ScriptResource : public v8::String::ExternalAsciiStringResource {
182 public:
183  ScriptResource(const char* data, size_t length)
184      : data_(data), length_(length) { }
185
186  const char* data() const { return data_; }
187  size_t length() const { return length_; }
188
189 private:
190  const char* data_;
191  size_t length_;
192};
193
194
195TEST(UsingCachedData) {
196  v8::Isolate* isolate = CcTest::isolate();
197  v8::HandleScope handles(isolate);
198  v8::Local<v8::Context> context = v8::Context::New(isolate);
199  v8::Context::Scope context_scope(context);
200  int marker;
201  CcTest::i_isolate()->stack_guard()->SetStackLimit(
202      reinterpret_cast<uintptr_t>(&marker) - 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  int source_length = i::StrLength(source);
218
219  // ScriptResource will be deleted when the corresponding String is GCd.
220  v8::ScriptCompiler::Source script_source(v8::String::NewExternal(
221      isolate, new ScriptResource(source, source_length)));
222  i::FLAG_min_preparse_length = 0;
223  v8::ScriptCompiler::Compile(isolate, &script_source,
224                              v8::ScriptCompiler::kProduceDataToCache);
225  CHECK(script_source.GetCachedData());
226
227  // Compile the script again, using the cached data.
228  bool lazy_flag = i::FLAG_lazy;
229  i::FLAG_lazy = true;
230  v8::ScriptCompiler::Compile(isolate, &script_source);
231  i::FLAG_lazy = false;
232  v8::ScriptCompiler::CompileUnbound(isolate, &script_source);
233  i::FLAG_lazy = lazy_flag;
234}
235
236
237TEST(PreparseFunctionDataIsUsed) {
238  // This tests that we actually do use the function data generated by the
239  // preparser.
240
241  // Make preparsing work for short scripts.
242  i::FLAG_min_preparse_length = 0;
243
244  v8::Isolate* isolate = CcTest::isolate();
245  v8::HandleScope handles(isolate);
246  v8::Local<v8::Context> context = v8::Context::New(isolate);
247  v8::Context::Scope context_scope(context);
248  int marker;
249  CcTest::i_isolate()->stack_guard()->SetStackLimit(
250      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
251
252  const char* good_code =
253      "function this_is_lazy() { var a; } function foo() { return 25; } foo();";
254
255  // Insert a syntax error inside the lazy function.
256  const char* bad_code =
257      "function this_is_lazy() { if (   } function foo() { return 25; } foo();";
258
259  v8::ScriptCompiler::Source good_source(v8_str(good_code));
260  v8::ScriptCompiler::Compile(isolate, &good_source,
261                              v8::ScriptCompiler::kProduceDataToCache);
262
263  const v8::ScriptCompiler::CachedData* cached_data =
264      good_source.GetCachedData();
265  CHECK(cached_data->data != NULL);
266  CHECK_GT(cached_data->length, 0);
267
268  // Now compile the erroneous code with the good preparse data. If the preparse
269  // data is used, the lazy function is skipped and it should compile fine.
270  v8::ScriptCompiler::Source bad_source(
271      v8_str(bad_code), new v8::ScriptCompiler::CachedData(
272                            cached_data->data, cached_data->length));
273  v8::Local<v8::Value> result =
274      v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
275  CHECK(result->IsInt32());
276  CHECK_EQ(25, result->Int32Value());
277}
278
279
280TEST(StandAlonePreParser) {
281  v8::V8::Initialize();
282
283  int marker;
284  CcTest::i_isolate()->stack_guard()->SetStackLimit(
285      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
286
287  const char* programs[] = {
288      "{label: 42}",
289      "var x = 42;",
290      "function foo(x, y) { return x + y; }",
291      "%ArgleBargle(glop);",
292      "var x = new new Function('this.x = 42');",
293      NULL
294  };
295
296  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
297  for (int i = 0; programs[i]; i++) {
298    const char* program = programs[i];
299    i::Utf8ToUtf16CharacterStream stream(
300        reinterpret_cast<const i::byte*>(program),
301        static_cast<unsigned>(strlen(program)));
302    i::CompleteParserRecorder log;
303    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
304    scanner.Initialize(&stream);
305
306    i::PreParser preparser(&scanner, &log, stack_limit);
307    preparser.set_allow_lazy(true);
308    preparser.set_allow_natives_syntax(true);
309    i::PreParser::PreParseResult result = preparser.PreParseProgram();
310    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
311    i::ScriptData data(log.ExtractData());
312    CHECK(!data.has_error());
313  }
314}
315
316
317TEST(StandAlonePreParserNoNatives) {
318  v8::V8::Initialize();
319
320  int marker;
321  CcTest::i_isolate()->stack_guard()->SetStackLimit(
322      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
323
324  const char* programs[] = {
325      "%ArgleBargle(glop);",
326      "var x = %_IsSmi(42);",
327      NULL
328  };
329
330  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
331  for (int i = 0; programs[i]; i++) {
332    const char* program = programs[i];
333    i::Utf8ToUtf16CharacterStream stream(
334        reinterpret_cast<const i::byte*>(program),
335        static_cast<unsigned>(strlen(program)));
336    i::CompleteParserRecorder log;
337    i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
338    scanner.Initialize(&stream);
339
340    // Preparser defaults to disallowing natives syntax.
341    i::PreParser preparser(&scanner, &log, stack_limit);
342    preparser.set_allow_lazy(true);
343    i::PreParser::PreParseResult result = preparser.PreParseProgram();
344    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
345    i::ScriptData data(log.ExtractData());
346    // Data contains syntax error.
347    CHECK(data.has_error());
348  }
349}
350
351
352TEST(PreparsingObjectLiterals) {
353  // Regression test for a bug where the symbol stream produced by PreParser
354  // didn't match what Parser wanted to consume.
355  v8::Isolate* isolate = CcTest::isolate();
356  v8::HandleScope handles(isolate);
357  v8::Local<v8::Context> context = v8::Context::New(isolate);
358  v8::Context::Scope context_scope(context);
359  int marker;
360  CcTest::i_isolate()->stack_guard()->SetStackLimit(
361      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
362
363  {
364    const char* source = "var myo = {if: \"foo\"}; myo.if;";
365    v8::Local<v8::Value> result = PreCompileCompileRun(source);
366    CHECK(result->IsString());
367    v8::String::Utf8Value utf8(result);
368    CHECK_EQ("foo", *utf8);
369  }
370
371  {
372    const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
373    v8::Local<v8::Value> result = PreCompileCompileRun(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 = {1: \"foo\"}; myo[1];";
381    v8::Local<v8::Value> result = PreCompileCompileRun(source);
382    CHECK(result->IsString());
383    v8::String::Utf8Value utf8(result);
384    CHECK_EQ("foo", *utf8);
385  }
386}
387
388
389TEST(RegressChromium62639) {
390  v8::V8::Initialize();
391  i::Isolate* isolate = CcTest::i_isolate();
392
393  int marker;
394  isolate->stack_guard()->SetStackLimit(
395      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
396
397  const char* program = "var x = 'something';\n"
398                        "escape: function() {}";
399  // Fails parsing expecting an identifier after "function".
400  // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
401  // and then used the invalid currently scanned literal. This always
402  // failed in debug mode, and sometimes crashed in release mode.
403
404  i::Utf8ToUtf16CharacterStream stream(
405      reinterpret_cast<const i::byte*>(program),
406      static_cast<unsigned>(strlen(program)));
407  i::CompleteParserRecorder log;
408  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
409  scanner.Initialize(&stream);
410  i::PreParser preparser(&scanner, &log,
411                         CcTest::i_isolate()->stack_guard()->real_climit());
412  preparser.set_allow_lazy(true);
413  i::PreParser::PreParseResult result = preparser.PreParseProgram();
414  // Even in the case of a syntax error, kPreParseSuccess is returned.
415  CHECK_EQ(i::PreParser::kPreParseSuccess, result);
416  i::ScriptData data(log.ExtractData());
417  CHECK(data.has_error());
418}
419
420
421TEST(Regress928) {
422  v8::V8::Initialize();
423  i::Isolate* isolate = CcTest::i_isolate();
424  i::Factory* factory = isolate->factory();
425
426  // Preparsing didn't consider the catch clause of a try statement
427  // as with-content, which made it assume that a function inside
428  // the block could be lazily compiled, and an extra, unexpected,
429  // entry was added to the data.
430  int marker;
431  isolate->stack_guard()->SetStackLimit(
432      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
433
434  const char* program =
435      "try { } catch (e) { var foo = function () { /* first */ } }"
436      "var bar = function () { /* second */ }";
437
438  v8::HandleScope handles(CcTest::isolate());
439  i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
440  i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
441  i::CompleteParserRecorder log;
442  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
443  scanner.Initialize(&stream);
444  i::PreParser preparser(&scanner, &log,
445                         CcTest::i_isolate()->stack_guard()->real_climit());
446  preparser.set_allow_lazy(true);
447  i::PreParser::PreParseResult result = preparser.PreParseProgram();
448  CHECK_EQ(i::PreParser::kPreParseSuccess, result);
449  i::ScriptData data(log.ExtractData());
450  CHECK(!data.has_error());
451  data.Initialize();
452
453  int first_function =
454      static_cast<int>(strstr(program, "function") - program);
455  int first_lbrace = first_function + i::StrLength("function () ");
456  CHECK_EQ('{', program[first_lbrace]);
457  i::FunctionEntry entry1 = data.GetFunctionEntry(first_lbrace);
458  CHECK(!entry1.is_valid());
459
460  int second_function =
461      static_cast<int>(strstr(program + first_lbrace, "function") - program);
462  int second_lbrace =
463      second_function + i::StrLength("function () ");
464  CHECK_EQ('{', program[second_lbrace]);
465  i::FunctionEntry entry2 = data.GetFunctionEntry(second_lbrace);
466  CHECK(entry2.is_valid());
467  CHECK_EQ('}', program[entry2.end_pos() - 1]);
468}
469
470
471TEST(PreParseOverflow) {
472  v8::V8::Initialize();
473
474  int marker;
475  CcTest::i_isolate()->stack_guard()->SetStackLimit(
476      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
477
478  size_t kProgramSize = 1024 * 1024;
479  i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
480  memset(program.get(), '(', kProgramSize);
481  program[kProgramSize] = '\0';
482
483  uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
484
485  i::Utf8ToUtf16CharacterStream stream(
486      reinterpret_cast<const i::byte*>(program.get()),
487      static_cast<unsigned>(kProgramSize));
488  i::CompleteParserRecorder log;
489  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
490  scanner.Initialize(&stream);
491
492  i::PreParser preparser(&scanner, &log, stack_limit);
493  preparser.set_allow_lazy(true);
494  i::PreParser::PreParseResult result = preparser.PreParseProgram();
495  CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
496}
497
498
499class TestExternalResource: public v8::String::ExternalStringResource {
500 public:
501  explicit TestExternalResource(uint16_t* data, int length)
502      : data_(data), length_(static_cast<size_t>(length)) { }
503
504  ~TestExternalResource() { }
505
506  const uint16_t* data() const {
507    return data_;
508  }
509
510  size_t length() const {
511    return length_;
512  }
513 private:
514  uint16_t* data_;
515  size_t length_;
516};
517
518
519#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
520
521void TestCharacterStream(const char* ascii_source,
522                         unsigned length,
523                         unsigned start = 0,
524                         unsigned end = 0) {
525  if (end == 0) end = length;
526  unsigned sub_length = end - start;
527  i::Isolate* isolate = CcTest::i_isolate();
528  i::Factory* factory = isolate->factory();
529  i::HandleScope test_scope(isolate);
530  i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
531  for (unsigned i = 0; i < length; i++) {
532    uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
533  }
534  i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
535  i::Handle<i::String> ascii_string =
536      factory->NewStringFromAscii(ascii_vector).ToHandleChecked();
537  TestExternalResource resource(uc16_buffer.get(), length);
538  i::Handle<i::String> uc16_string(
539      factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
540
541  i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
542      i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
543  i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end);
544  i::Utf8ToUtf16CharacterStream utf8_stream(
545      reinterpret_cast<const i::byte*>(ascii_source), end);
546  utf8_stream.SeekForward(start);
547
548  unsigned i = start;
549  while (i < end) {
550    // Read streams one char at a time
551    CHECK_EQU(i, uc16_stream.pos());
552    CHECK_EQU(i, string_stream.pos());
553    CHECK_EQU(i, utf8_stream.pos());
554    int32_t c0 = ascii_source[i];
555    int32_t c1 = uc16_stream.Advance();
556    int32_t c2 = string_stream.Advance();
557    int32_t c3 = utf8_stream.Advance();
558    i++;
559    CHECK_EQ(c0, c1);
560    CHECK_EQ(c0, c2);
561    CHECK_EQ(c0, c3);
562    CHECK_EQU(i, uc16_stream.pos());
563    CHECK_EQU(i, string_stream.pos());
564    CHECK_EQU(i, utf8_stream.pos());
565  }
566  while (i > start + sub_length / 4) {
567    // Pushback, re-read, pushback again.
568    int32_t c0 = ascii_source[i - 1];
569    CHECK_EQU(i, uc16_stream.pos());
570    CHECK_EQU(i, string_stream.pos());
571    CHECK_EQU(i, utf8_stream.pos());
572    uc16_stream.PushBack(c0);
573    string_stream.PushBack(c0);
574    utf8_stream.PushBack(c0);
575    i--;
576    CHECK_EQU(i, uc16_stream.pos());
577    CHECK_EQU(i, string_stream.pos());
578    CHECK_EQU(i, utf8_stream.pos());
579    int32_t c1 = uc16_stream.Advance();
580    int32_t c2 = string_stream.Advance();
581    int32_t c3 = utf8_stream.Advance();
582    i++;
583    CHECK_EQU(i, uc16_stream.pos());
584    CHECK_EQU(i, string_stream.pos());
585    CHECK_EQU(i, utf8_stream.pos());
586    CHECK_EQ(c0, c1);
587    CHECK_EQ(c0, c2);
588    CHECK_EQ(c0, c3);
589    uc16_stream.PushBack(c0);
590    string_stream.PushBack(c0);
591    utf8_stream.PushBack(c0);
592    i--;
593    CHECK_EQU(i, uc16_stream.pos());
594    CHECK_EQU(i, string_stream.pos());
595    CHECK_EQU(i, utf8_stream.pos());
596  }
597  unsigned halfway = start + sub_length / 2;
598  uc16_stream.SeekForward(halfway - i);
599  string_stream.SeekForward(halfway - i);
600  utf8_stream.SeekForward(halfway - i);
601  i = halfway;
602  CHECK_EQU(i, uc16_stream.pos());
603  CHECK_EQU(i, string_stream.pos());
604  CHECK_EQU(i, utf8_stream.pos());
605
606  while (i < end) {
607    // Read streams one char at a time
608    CHECK_EQU(i, uc16_stream.pos());
609    CHECK_EQU(i, string_stream.pos());
610    CHECK_EQU(i, utf8_stream.pos());
611    int32_t c0 = ascii_source[i];
612    int32_t c1 = uc16_stream.Advance();
613    int32_t c2 = string_stream.Advance();
614    int32_t c3 = utf8_stream.Advance();
615    i++;
616    CHECK_EQ(c0, c1);
617    CHECK_EQ(c0, c2);
618    CHECK_EQ(c0, c3);
619    CHECK_EQU(i, uc16_stream.pos());
620    CHECK_EQU(i, string_stream.pos());
621    CHECK_EQU(i, utf8_stream.pos());
622  }
623
624  int32_t c1 = uc16_stream.Advance();
625  int32_t c2 = string_stream.Advance();
626  int32_t c3 = utf8_stream.Advance();
627  CHECK_LT(c1, 0);
628  CHECK_LT(c2, 0);
629  CHECK_LT(c3, 0);
630}
631
632
633TEST(CharacterStreams) {
634  v8::Isolate* isolate = CcTest::isolate();
635  v8::HandleScope handles(isolate);
636  v8::Local<v8::Context> context = v8::Context::New(isolate);
637  v8::Context::Scope context_scope(context);
638
639  TestCharacterStream("abc\0\n\r\x7f", 7);
640  static const unsigned kBigStringSize = 4096;
641  char buffer[kBigStringSize + 1];
642  for (unsigned i = 0; i < kBigStringSize; i++) {
643    buffer[i] = static_cast<char>(i & 0x7f);
644  }
645  TestCharacterStream(buffer, kBigStringSize);
646
647  TestCharacterStream(buffer, kBigStringSize, 576, 3298);
648
649  TestCharacterStream("\0", 1);
650  TestCharacterStream("", 0);
651}
652
653
654TEST(Utf8CharacterStream) {
655  static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
656  static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
657
658  static const int kAllUtf8CharsSize =
659      (unibrow::Utf8::kMaxOneByteChar + 1) +
660      (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
661      (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
662  static const unsigned kAllUtf8CharsSizeU =
663      static_cast<unsigned>(kAllUtf8CharsSize);
664
665  char buffer[kAllUtf8CharsSizeU];
666  unsigned cursor = 0;
667  for (int i = 0; i <= kMaxUC16Char; i++) {
668    cursor += unibrow::Utf8::Encode(buffer + cursor,
669                                    i,
670                                    unibrow::Utf16::kNoPreviousCharacter);
671  }
672  ASSERT(cursor == kAllUtf8CharsSizeU);
673
674  i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
675                                       kAllUtf8CharsSizeU);
676  for (int i = 0; i <= kMaxUC16Char; i++) {
677    CHECK_EQU(i, stream.pos());
678    int32_t c = stream.Advance();
679    CHECK_EQ(i, c);
680    CHECK_EQU(i + 1, stream.pos());
681  }
682  for (int i = kMaxUC16Char; i >= 0; i--) {
683    CHECK_EQU(i + 1, stream.pos());
684    stream.PushBack(i);
685    CHECK_EQU(i, stream.pos());
686  }
687  int i = 0;
688  while (stream.pos() < kMaxUC16CharU) {
689    CHECK_EQU(i, stream.pos());
690    unsigned progress = stream.SeekForward(12);
691    i += progress;
692    int32_t c = stream.Advance();
693    if (i <= kMaxUC16Char) {
694      CHECK_EQ(i, c);
695    } else {
696      CHECK_EQ(-1, c);
697    }
698    i += 1;
699    CHECK_EQU(i, stream.pos());
700  }
701}
702
703#undef CHECK_EQU
704
705void TestStreamScanner(i::Utf16CharacterStream* stream,
706                       i::Token::Value* expected_tokens,
707                       int skip_pos = 0,  // Zero means not skipping.
708                       int skip_to = 0) {
709  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
710  scanner.Initialize(stream);
711
712  int i = 0;
713  do {
714    i::Token::Value expected = expected_tokens[i];
715    i::Token::Value actual = scanner.Next();
716    CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
717    if (scanner.location().end_pos == skip_pos) {
718      scanner.SeekForward(skip_to);
719    }
720    i++;
721  } while (expected_tokens[i] != i::Token::ILLEGAL);
722}
723
724
725TEST(StreamScanner) {
726  v8::V8::Initialize();
727
728  const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
729  i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
730                                        static_cast<unsigned>(strlen(str1)));
731  i::Token::Value expectations1[] = {
732      i::Token::LBRACE,
733      i::Token::IDENTIFIER,
734      i::Token::IDENTIFIER,
735      i::Token::FOR,
736      i::Token::COLON,
737      i::Token::MUL,
738      i::Token::DIV,
739      i::Token::LT,
740      i::Token::SUB,
741      i::Token::IDENTIFIER,
742      i::Token::EOS,
743      i::Token::ILLEGAL
744  };
745  TestStreamScanner(&stream1, expectations1, 0, 0);
746
747  const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
748  i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
749                                        static_cast<unsigned>(strlen(str2)));
750  i::Token::Value expectations2[] = {
751      i::Token::CASE,
752      i::Token::DEFAULT,
753      i::Token::CONST,
754      i::Token::LBRACE,
755      // Skipped part here
756      i::Token::RBRACE,
757      i::Token::DO,
758      i::Token::EOS,
759      i::Token::ILLEGAL
760  };
761  ASSERT_EQ('{', str2[19]);
762  ASSERT_EQ('}', str2[37]);
763  TestStreamScanner(&stream2, expectations2, 20, 37);
764
765  const char* str3 = "{}}}}";
766  i::Token::Value expectations3[] = {
767      i::Token::LBRACE,
768      i::Token::RBRACE,
769      i::Token::RBRACE,
770      i::Token::RBRACE,
771      i::Token::RBRACE,
772      i::Token::EOS,
773      i::Token::ILLEGAL
774  };
775  // Skip zero-four RBRACEs.
776  for (int i = 0; i <= 4; i++) {
777     expectations3[6 - i] = i::Token::ILLEGAL;
778     expectations3[5 - i] = i::Token::EOS;
779     i::Utf8ToUtf16CharacterStream stream3(
780         reinterpret_cast<const i::byte*>(str3),
781         static_cast<unsigned>(strlen(str3)));
782     TestStreamScanner(&stream3, expectations3, 1, 1 + i);
783  }
784}
785
786
787void TestScanRegExp(const char* re_source, const char* expected) {
788  i::Utf8ToUtf16CharacterStream stream(
789       reinterpret_cast<const i::byte*>(re_source),
790       static_cast<unsigned>(strlen(re_source)));
791  i::HandleScope scope(CcTest::i_isolate());
792  i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
793  scanner.Initialize(&stream);
794
795  i::Token::Value start = scanner.peek();
796  CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
797  CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
798  scanner.Next();  // Current token is now the regexp literal.
799  i::Handle<i::String> val =
800      scanner.AllocateInternalizedString(CcTest::i_isolate());
801  i::DisallowHeapAllocation no_alloc;
802  i::String::FlatContent content = val->GetFlatContent();
803  CHECK(content.IsAscii());
804  i::Vector<const uint8_t> actual = content.ToOneByteVector();
805  for (int i = 0; i < actual.length(); i++) {
806    CHECK_NE('\0', expected[i]);
807    CHECK_EQ(expected[i], actual[i]);
808  }
809}
810
811
812TEST(RegExpScanning) {
813  v8::V8::Initialize();
814
815  // RegExp token with added garbage at the end. The scanner should only
816  // scan the RegExp until the terminating slash just before "flipperwald".
817  TestScanRegExp("/b/flipperwald", "b");
818  // Incomplete escape sequences doesn't hide the terminating slash.
819  TestScanRegExp("/\\x/flipperwald", "\\x");
820  TestScanRegExp("/\\u/flipperwald", "\\u");
821  TestScanRegExp("/\\u1/flipperwald", "\\u1");
822  TestScanRegExp("/\\u12/flipperwald", "\\u12");
823  TestScanRegExp("/\\u123/flipperwald", "\\u123");
824  TestScanRegExp("/\\c/flipperwald", "\\c");
825  TestScanRegExp("/\\c//flipperwald", "\\c");
826  // Slashes inside character classes are not terminating.
827  TestScanRegExp("/[/]/flipperwald", "[/]");
828  TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
829  // Incomplete escape sequences inside a character class doesn't hide
830  // the end of the character class.
831  TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
832  TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
833  TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
834  TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
835  TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
836  TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
837  TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
838  TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
839  // Escaped ']'s wont end the character class.
840  TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
841  // Escaped slashes are not terminating.
842  TestScanRegExp("/\\//flipperwald", "\\/");
843  // Starting with '=' works too.
844  TestScanRegExp("/=/", "=");
845  TestScanRegExp("/=?/", "=?");
846}
847
848
849static int Utf8LengthHelper(const char* s) {
850  int len = i::StrLength(s);
851  int character_length = len;
852  for (int i = 0; i < len; i++) {
853    unsigned char c = s[i];
854    int input_offset = 0;
855    int output_adjust = 0;
856    if (c > 0x7f) {
857      if (c < 0xc0) continue;
858      if (c >= 0xf0) {
859        if (c >= 0xf8) {
860          // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
861          // byte.
862          continue;  // Handle first UTF-8 byte.
863        }
864        if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
865          // This 4 byte sequence could have been coded as a 3 byte sequence.
866          // Record a single kBadChar for the first byte and continue.
867          continue;
868        }
869        input_offset = 3;
870        // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
871        character_length -= 2;
872      } else if (c >= 0xe0) {
873        if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
874          // This 3 byte sequence could have been coded as a 2 byte sequence.
875          // Record a single kBadChar for the first byte and continue.
876          continue;
877        }
878        input_offset = 2;
879        // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
880        output_adjust = 2;
881      } else {
882        if ((c & 0x1e) == 0) {
883          // This 2 byte sequence could have been coded as a 1 byte sequence.
884          // Record a single kBadChar for the first byte and continue.
885          continue;
886        }
887        input_offset = 1;
888        // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
889        output_adjust = 1;
890      }
891      bool bad = false;
892      for (int j = 1; j <= input_offset; j++) {
893        if ((s[i + j] & 0xc0) != 0x80) {
894          // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
895          // which is a single UTF-16 code unit.
896          bad = true;
897          break;
898        }
899      }
900      if (!bad) {
901        i += input_offset;
902        character_length -= output_adjust;
903      }
904    }
905  }
906  return character_length;
907}
908
909
910TEST(ScopePositions) {
911  v8::internal::FLAG_harmony_scoping = true;
912
913  // Test the parser for correctly setting the start and end positions
914  // of a scope. We check the scope positions of exactly one scope
915  // nested in the global scope of a program. 'inner source' is the
916  // source code that determines the part of the source belonging
917  // to the nested scope. 'outer_prefix' and 'outer_suffix' are
918  // parts of the source that belong to the global scope.
919  struct SourceData {
920    const char* outer_prefix;
921    const char* inner_source;
922    const char* outer_suffix;
923    i::ScopeType scope_type;
924    i::StrictMode strict_mode;
925  };
926
927  const SourceData source_data[] = {
928    { "  with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
929    { "  with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
930    { "  with ({}) ", "{\n"
931      "    block;\n"
932      "  }", "\n"
933      "  more;", i::WITH_SCOPE, i::SLOPPY },
934    { "  with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
935    { "  with ({}) ", "statement", "\n"
936      "  more;", i::WITH_SCOPE, i::SLOPPY },
937    { "  with ({})\n"
938      "    ", "statement;", "\n"
939      "  more;", i::WITH_SCOPE, i::SLOPPY },
940    { "  try {} catch ", "(e) { block; }", " more;",
941      i::CATCH_SCOPE, i::SLOPPY },
942    { "  try {} catch ", "(e) { block; }", "; more;",
943      i::CATCH_SCOPE, i::SLOPPY },
944    { "  try {} catch ", "(e) {\n"
945      "    block;\n"
946      "  }", "\n"
947      "  more;", i::CATCH_SCOPE, i::SLOPPY },
948    { "  try {} catch ", "(e) { block; }", " finally { block; } more;",
949      i::CATCH_SCOPE, i::SLOPPY },
950    { "  start;\n"
951      "  ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
952    { "  start;\n"
953      "  ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
954    { "  start;\n"
955      "  ", "{\n"
956      "    let block;\n"
957      "  }", "\n"
958      "  more;", i::BLOCK_SCOPE, i::STRICT },
959    { "  start;\n"
960      "  function fun", "(a,b) { infunction; }", " more;",
961      i::FUNCTION_SCOPE, i::SLOPPY },
962    { "  start;\n"
963      "  function fun", "(a,b) {\n"
964      "    infunction;\n"
965      "  }", "\n"
966      "  more;", i::FUNCTION_SCOPE, i::SLOPPY },
967    { "  (function fun", "(a,b) { infunction; }", ")();",
968      i::FUNCTION_SCOPE, i::SLOPPY },
969    { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
970      i::BLOCK_SCOPE, i::STRICT },
971    { "  for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
972      i::BLOCK_SCOPE, i::STRICT },
973    { "  for ", "(let x = 1 ; x < 10; ++ x) {\n"
974      "    block;\n"
975      "  }", "\n"
976      "  more;", i::BLOCK_SCOPE, i::STRICT },
977    { "  for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
978      i::BLOCK_SCOPE, i::STRICT },
979    { "  for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
980      "  more;", i::BLOCK_SCOPE, i::STRICT },
981    { "  for ", "(let x = 1 ; x < 10; ++ x)\n"
982      "    statement;", "\n"
983      "  more;", i::BLOCK_SCOPE, i::STRICT },
984    { "  for ", "(let x in {}) { block; }", " more;",
985      i::BLOCK_SCOPE, i::STRICT },
986    { "  for ", "(let x in {}) { block; }", "; more;",
987      i::BLOCK_SCOPE, i::STRICT },
988    { "  for ", "(let x in {}) {\n"
989      "    block;\n"
990      "  }", "\n"
991      "  more;", i::BLOCK_SCOPE, i::STRICT },
992    { "  for ", "(let x in {}) statement;", " more;",
993      i::BLOCK_SCOPE, i::STRICT },
994    { "  for ", "(let x in {}) statement", "\n"
995      "  more;", i::BLOCK_SCOPE, i::STRICT },
996    { "  for ", "(let x in {})\n"
997      "    statement;", "\n"
998      "  more;", i::BLOCK_SCOPE, i::STRICT },
999    // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1000    // the preparser off in terms of byte offsets.
1001    // 6 byte encoding.
1002    { "  'foo\355\240\201\355\260\211';\n"
1003      "  (function fun", "(a,b) { infunction; }", ")();",
1004      i::FUNCTION_SCOPE, i::SLOPPY },
1005    // 4 byte encoding.
1006    { "  'foo\360\220\220\212';\n"
1007      "  (function fun", "(a,b) { infunction; }", ")();",
1008      i::FUNCTION_SCOPE, i::SLOPPY },
1009    // 3 byte encoding of \u0fff.
1010    { "  'foo\340\277\277';\n"
1011      "  (function fun", "(a,b) { infunction; }", ")();",
1012      i::FUNCTION_SCOPE, i::SLOPPY },
1013    // Broken 6 byte encoding with missing last byte.
1014    { "  'foo\355\240\201\355\211';\n"
1015      "  (function fun", "(a,b) { infunction; }", ")();",
1016      i::FUNCTION_SCOPE, i::SLOPPY },
1017    // Broken 3 byte encoding of \u0fff with missing last byte.
1018    { "  'foo\340\277';\n"
1019      "  (function fun", "(a,b) { infunction; }", ")();",
1020      i::FUNCTION_SCOPE, i::SLOPPY },
1021    // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1022    { "  'foo\340';\n"
1023      "  (function fun", "(a,b) { infunction; }", ")();",
1024      i::FUNCTION_SCOPE, i::SLOPPY },
1025    // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1026    { "  'foo\340\203\277';\n"
1027      "  (function fun", "(a,b) { infunction; }", ")();",
1028      i::FUNCTION_SCOPE, i::SLOPPY },
1029    // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1030    { "  'foo\340\201\277';\n"
1031      "  (function fun", "(a,b) { infunction; }", ")();",
1032      i::FUNCTION_SCOPE, i::SLOPPY },
1033    // Unpaired lead surrogate.
1034    { "  'foo\355\240\201';\n"
1035      "  (function fun", "(a,b) { infunction; }", ")();",
1036      i::FUNCTION_SCOPE, i::SLOPPY },
1037    // Unpaired lead surrogate where following code point is a 3 byte sequence.
1038    { "  'foo\355\240\201\340\277\277';\n"
1039      "  (function fun", "(a,b) { infunction; }", ")();",
1040      i::FUNCTION_SCOPE, i::SLOPPY },
1041    // Unpaired lead surrogate where following code point is a 4 byte encoding
1042    // of a trail surrogate.
1043    { "  'foo\355\240\201\360\215\260\211';\n"
1044      "  (function fun", "(a,b) { infunction; }", ")();",
1045      i::FUNCTION_SCOPE, i::SLOPPY },
1046    // Unpaired trail surrogate.
1047    { "  'foo\355\260\211';\n"
1048      "  (function fun", "(a,b) { infunction; }", ")();",
1049      i::FUNCTION_SCOPE, i::SLOPPY },
1050    // 2 byte encoding of \u00ff.
1051    { "  'foo\303\277';\n"
1052      "  (function fun", "(a,b) { infunction; }", ")();",
1053      i::FUNCTION_SCOPE, i::SLOPPY },
1054    // Broken 2 byte encoding of \u00ff with missing last byte.
1055    { "  'foo\303';\n"
1056      "  (function fun", "(a,b) { infunction; }", ")();",
1057      i::FUNCTION_SCOPE, i::SLOPPY },
1058    // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1059    { "  'foo\301\277';\n"
1060      "  (function fun", "(a,b) { infunction; }", ")();",
1061      i::FUNCTION_SCOPE, i::SLOPPY },
1062    // Illegal 5 byte encoding.
1063    { "  'foo\370\277\277\277\277';\n"
1064      "  (function fun", "(a,b) { infunction; }", ")();",
1065      i::FUNCTION_SCOPE, i::SLOPPY },
1066    // Illegal 6 byte encoding.
1067    { "  'foo\374\277\277\277\277\277';\n"
1068      "  (function fun", "(a,b) { infunction; }", ")();",
1069      i::FUNCTION_SCOPE, i::SLOPPY },
1070    // Illegal 0xfe byte
1071    { "  'foo\376\277\277\277\277\277\277';\n"
1072      "  (function fun", "(a,b) { infunction; }", ")();",
1073      i::FUNCTION_SCOPE, i::SLOPPY },
1074    // Illegal 0xff byte
1075    { "  'foo\377\277\277\277\277\277\277\277';\n"
1076      "  (function fun", "(a,b) { infunction; }", ")();",
1077      i::FUNCTION_SCOPE, i::SLOPPY },
1078    { "  'foo';\n"
1079      "  (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
1080      i::FUNCTION_SCOPE, i::SLOPPY },
1081    { "  'foo';\n"
1082      "  (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
1083      i::FUNCTION_SCOPE, i::SLOPPY },
1084    { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
1085  };
1086
1087  i::Isolate* isolate = CcTest::i_isolate();
1088  i::Factory* factory = isolate->factory();
1089
1090  v8::HandleScope handles(CcTest::isolate());
1091  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1092  v8::Context::Scope context_scope(context);
1093
1094  int marker;
1095  isolate->stack_guard()->SetStackLimit(
1096      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1097
1098  for (int i = 0; source_data[i].outer_prefix; i++) {
1099    int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1100    int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1101    int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1102    int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1103    int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1104    int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1105    int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1106    int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1107    i::ScopedVector<char> program(kProgramByteSize + 1);
1108    i::SNPrintF(program, "%s%s%s",
1109                         source_data[i].outer_prefix,
1110                         source_data[i].inner_source,
1111                         source_data[i].outer_suffix);
1112
1113    // Parse program source.
1114    i::Handle<i::String> source = factory->NewStringFromUtf8(
1115        i::CStrVector(program.start())).ToHandleChecked();
1116    CHECK_EQ(source->length(), kProgramSize);
1117    i::Handle<i::Script> script = factory->NewScript(source);
1118    i::CompilationInfoWithZone info(script);
1119    i::Parser parser(&info);
1120    parser.set_allow_lazy(true);
1121    parser.set_allow_harmony_scoping(true);
1122    info.MarkAsGlobal();
1123    info.SetStrictMode(source_data[i].strict_mode);
1124    parser.Parse();
1125    CHECK(info.function() != NULL);
1126
1127    // Check scope types and positions.
1128    i::Scope* scope = info.function()->scope();
1129    CHECK(scope->is_global_scope());
1130    CHECK_EQ(scope->start_position(), 0);
1131    CHECK_EQ(scope->end_position(), kProgramSize);
1132    CHECK_EQ(scope->inner_scopes()->length(), 1);
1133
1134    i::Scope* inner_scope = scope->inner_scopes()->at(0);
1135    CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1136    CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1137    // The end position of a token is one position after the last
1138    // character belonging to that token.
1139    CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1140  }
1141}
1142
1143
1144i::Handle<i::String> FormatMessage(i::ScriptData* data) {
1145  i::Isolate* isolate = CcTest::i_isolate();
1146  i::Factory* factory = isolate->factory();
1147  const char* message = data->BuildMessage();
1148  i::Handle<i::String> format = v8::Utils::OpenHandle(
1149      *v8::String::NewFromUtf8(CcTest::isolate(), message));
1150  const char* arg = data->BuildArg();
1151  i::Handle<i::JSArray> args_array = factory->NewJSArray(arg == NULL ? 0 : 1);
1152  if (arg != NULL) {
1153    i::JSArray::SetElement(
1154        args_array, 0, v8::Utils::OpenHandle(*v8::String::NewFromUtf8(
1155                                                  CcTest::isolate(), arg)),
1156        NONE, i::SLOPPY).Check();
1157  }
1158  i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
1159  i::Handle<i::Object> format_fun = i::Object::GetProperty(
1160      isolate, builtins, "FormatMessage").ToHandleChecked();
1161  i::Handle<i::Object> arg_handles[] = { format, args_array };
1162  i::Handle<i::Object> result = i::Execution::Call(
1163      isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
1164  CHECK(result->IsString());
1165  i::DeleteArray(message);
1166  i::DeleteArray(arg);
1167  return i::Handle<i::String>::cast(result);
1168}
1169
1170
1171enum ParserFlag {
1172  kAllowLazy,
1173  kAllowNativesSyntax,
1174  kAllowHarmonyScoping,
1175  kAllowModules,
1176  kAllowGenerators,
1177  kAllowForOf,
1178  kAllowHarmonyNumericLiterals
1179};
1180
1181
1182enum ParserSyncTestResult {
1183  kSuccessOrError,
1184  kSuccess,
1185  kError
1186};
1187
1188template <typename Traits>
1189void SetParserFlags(i::ParserBase<Traits>* parser,
1190                    i::EnumSet<ParserFlag> flags) {
1191  parser->set_allow_lazy(flags.Contains(kAllowLazy));
1192  parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
1193  parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
1194  parser->set_allow_modules(flags.Contains(kAllowModules));
1195  parser->set_allow_generators(flags.Contains(kAllowGenerators));
1196  parser->set_allow_for_of(flags.Contains(kAllowForOf));
1197  parser->set_allow_harmony_numeric_literals(
1198      flags.Contains(kAllowHarmonyNumericLiterals));
1199}
1200
1201
1202void TestParserSyncWithFlags(i::Handle<i::String> source,
1203                             i::EnumSet<ParserFlag> flags,
1204                             ParserSyncTestResult result) {
1205  i::Isolate* isolate = CcTest::i_isolate();
1206  i::Factory* factory = isolate->factory();
1207
1208  uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1209
1210  // Preparse the data.
1211  i::CompleteParserRecorder log;
1212  {
1213    i::Scanner scanner(isolate->unicode_cache());
1214    i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1215    i::PreParser preparser(&scanner, &log, stack_limit);
1216    SetParserFlags(&preparser, flags);
1217    scanner.Initialize(&stream);
1218    i::PreParser::PreParseResult result = preparser.PreParseProgram();
1219    CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1220  }
1221  i::ScriptData data(log.ExtractData());
1222
1223  // Parse the data
1224  i::FunctionLiteral* function;
1225  {
1226    i::Handle<i::Script> script = factory->NewScript(source);
1227    i::CompilationInfoWithZone info(script);
1228    i::Parser parser(&info);
1229    SetParserFlags(&parser, flags);
1230    info.MarkAsGlobal();
1231    parser.Parse();
1232    function = info.function();
1233  }
1234
1235  // Check that preparsing fails iff parsing fails.
1236  if (function == NULL) {
1237    // Extract exception from the parser.
1238    CHECK(isolate->has_pending_exception());
1239    i::Handle<i::JSObject> exception_handle(
1240        i::JSObject::cast(isolate->pending_exception()));
1241    i::Handle<i::String> message_string =
1242        i::Handle<i::String>::cast(i::Object::GetProperty(
1243            isolate, exception_handle, "message").ToHandleChecked());
1244
1245    if (result == kSuccess) {
1246      i::OS::Print(
1247          "Parser failed on:\n"
1248          "\t%s\n"
1249          "with error:\n"
1250          "\t%s\n"
1251          "However, we expected no error.",
1252          source->ToCString().get(), message_string->ToCString().get());
1253      CHECK(false);
1254    }
1255
1256    if (!data.has_error()) {
1257      i::OS::Print(
1258          "Parser failed on:\n"
1259          "\t%s\n"
1260          "with error:\n"
1261          "\t%s\n"
1262          "However, the preparser succeeded",
1263          source->ToCString().get(), message_string->ToCString().get());
1264      CHECK(false);
1265    }
1266    // Check that preparser and parser produce the same error.
1267    i::Handle<i::String> preparser_message = FormatMessage(&data);
1268    if (!i::String::Equals(message_string, preparser_message)) {
1269      i::OS::Print(
1270          "Expected parser and preparser to produce the same error on:\n"
1271          "\t%s\n"
1272          "However, found the following error messages\n"
1273          "\tparser:    %s\n"
1274          "\tpreparser: %s\n",
1275          source->ToCString().get(),
1276          message_string->ToCString().get(),
1277          preparser_message->ToCString().get());
1278      CHECK(false);
1279    }
1280  } else if (data.has_error()) {
1281    i::OS::Print(
1282        "Preparser failed on:\n"
1283        "\t%s\n"
1284        "with error:\n"
1285        "\t%s\n"
1286        "However, the parser succeeded",
1287        source->ToCString().get(), FormatMessage(&data)->ToCString().get());
1288    CHECK(false);
1289  } else if (result == kError) {
1290    i::OS::Print(
1291        "Expected error on:\n"
1292        "\t%s\n"
1293        "However, parser and preparser succeeded",
1294        source->ToCString().get());
1295    CHECK(false);
1296  }
1297}
1298
1299
1300void TestParserSync(const char* source,
1301                    const ParserFlag* flag_list,
1302                    size_t flag_list_length,
1303                    ParserSyncTestResult result = kSuccessOrError) {
1304  i::Handle<i::String> str =
1305      CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1306  for (int bits = 0; bits < (1 << flag_list_length); bits++) {
1307    i::EnumSet<ParserFlag> flags;
1308    for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) {
1309      if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]);
1310    }
1311    TestParserSyncWithFlags(str, flags, result);
1312  }
1313}
1314
1315
1316TEST(ParserSync) {
1317  const char* context_data[][2] = {
1318    { "", "" },
1319    { "{", "}" },
1320    { "if (true) ", " else {}" },
1321    { "if (true) {} else ", "" },
1322    { "if (true) ", "" },
1323    { "do ", " while (false)" },
1324    { "while (false) ", "" },
1325    { "for (;;) ", "" },
1326    { "with ({})", "" },
1327    { "switch (12) { case 12: ", "}" },
1328    { "switch (12) { default: ", "}" },
1329    { "switch (12) { ", "case 12: }" },
1330    { "label2: ", "" },
1331    { NULL, NULL }
1332  };
1333
1334  const char* statement_data[] = {
1335    "{}",
1336    "var x",
1337    "var x = 1",
1338    "const x",
1339    "const x = 1",
1340    ";",
1341    "12",
1342    "if (false) {} else ;",
1343    "if (false) {} else {}",
1344    "if (false) {} else 12",
1345    "if (false) ;"
1346    "if (false) {}",
1347    "if (false) 12",
1348    "do {} while (false)",
1349    "for (;;) ;",
1350    "for (;;) {}",
1351    "for (;;) 12",
1352    "continue",
1353    "continue label",
1354    "continue\nlabel",
1355    "break",
1356    "break label",
1357    "break\nlabel",
1358    // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1359    // "return",
1360    // "return  12",
1361    // "return\n12",
1362    "with ({}) ;",
1363    "with ({}) {}",
1364    "with ({}) 12",
1365    "switch ({}) { default: }"
1366    "label3: "
1367    "throw",
1368    "throw  12",
1369    "throw\n12",
1370    "try {} catch(e) {}",
1371    "try {} finally {}",
1372    "try {} catch(e) {} finally {}",
1373    "debugger",
1374    NULL
1375  };
1376
1377  const char* termination_data[] = {
1378    "",
1379    ";",
1380    "\n",
1381    ";\n",
1382    "\n;",
1383    NULL
1384  };
1385
1386  v8::HandleScope handles(CcTest::isolate());
1387  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1388  v8::Context::Scope context_scope(context);
1389
1390  int marker;
1391  CcTest::i_isolate()->stack_guard()->SetStackLimit(
1392      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1393
1394  static const ParserFlag flags1[] = {
1395    kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
1396    kAllowForOf
1397  };
1398  for (int i = 0; context_data[i][0] != NULL; ++i) {
1399    for (int j = 0; statement_data[j] != NULL; ++j) {
1400      for (int k = 0; termination_data[k] != NULL; ++k) {
1401        int kPrefixLen = i::StrLength(context_data[i][0]);
1402        int kStatementLen = i::StrLength(statement_data[j]);
1403        int kTerminationLen = i::StrLength(termination_data[k]);
1404        int kSuffixLen = i::StrLength(context_data[i][1]);
1405        int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1406            + kSuffixLen + i::StrLength("label: for (;;) {  }");
1407
1408        // Plug the source code pieces together.
1409        i::ScopedVector<char> program(kProgramSize + 1);
1410        int length = i::SNPrintF(program,
1411            "label: for (;;) { %s%s%s%s }",
1412            context_data[i][0],
1413            statement_data[j],
1414            termination_data[k],
1415            context_data[i][1]);
1416        CHECK(length == kProgramSize);
1417        TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1));
1418      }
1419    }
1420  }
1421
1422  // Neither Harmony numeric literals nor our natives syntax have any
1423  // interaction with the flags above, so test these separately to reduce
1424  // the combinatorial explosion.
1425  static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals };
1426  TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2));
1427  TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2));
1428
1429  static const ParserFlag flags3[] = { kAllowNativesSyntax };
1430  TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3));
1431}
1432
1433
1434TEST(StrictOctal) {
1435  // Test that syntax error caused by octal literal is reported correctly as
1436  // such (issue 2220).
1437  v8::V8::Initialize();
1438  v8::HandleScope scope(CcTest::isolate());
1439  v8::Context::Scope context_scope(
1440      v8::Context::New(CcTest::isolate()));
1441  v8::TryCatch try_catch;
1442  const char* script =
1443      "\"use strict\";       \n"
1444      "a = function() {      \n"
1445      "  b = function() {    \n"
1446      "    01;               \n"
1447      "  };                  \n"
1448      "};                    \n";
1449  v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
1450  CHECK(try_catch.HasCaught());
1451  v8::String::Utf8Value exception(try_catch.Exception());
1452  CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
1453           *exception);
1454}
1455
1456
1457void RunParserSyncTest(const char* context_data[][2],
1458                       const char* statement_data[],
1459                       ParserSyncTestResult result,
1460                       const ParserFlag* flags = NULL,
1461                       int flags_len = 0) {
1462  v8::HandleScope handles(CcTest::isolate());
1463  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1464  v8::Context::Scope context_scope(context);
1465
1466  int marker;
1467  CcTest::i_isolate()->stack_guard()->SetStackLimit(
1468      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1469
1470  static const ParserFlag default_flags[] = {
1471    kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
1472    kAllowForOf, kAllowNativesSyntax
1473  };
1474  if (!flags) {
1475    flags = default_flags;
1476    flags_len = ARRAY_SIZE(default_flags);
1477  }
1478  for (int i = 0; context_data[i][0] != NULL; ++i) {
1479    for (int j = 0; statement_data[j] != NULL; ++j) {
1480      int kPrefixLen = i::StrLength(context_data[i][0]);
1481      int kStatementLen = i::StrLength(statement_data[j]);
1482      int kSuffixLen = i::StrLength(context_data[i][1]);
1483      int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1484
1485      // Plug the source code pieces together.
1486      i::ScopedVector<char> program(kProgramSize + 1);
1487      int length = i::SNPrintF(program,
1488                               "%s%s%s",
1489                               context_data[i][0],
1490                               statement_data[j],
1491                               context_data[i][1]);
1492      CHECK(length == kProgramSize);
1493      TestParserSync(program.start(),
1494                     flags,
1495                     flags_len,
1496                     result);
1497    }
1498  }
1499}
1500
1501
1502TEST(ErrorsEvalAndArguments) {
1503  // Tests that both preparsing and parsing produce the right kind of errors for
1504  // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1505  // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1506  // isn't.
1507  const char* context_data[][2] = {
1508    { "\"use strict\";", "" },
1509    { "var eval; function test_func() {\"use strict\"; ", "}"},
1510    { NULL, NULL }
1511  };
1512
1513  const char* statement_data[] = {
1514    "var eval;",
1515    "var arguments",
1516    "var foo, eval;",
1517    "var foo, arguments;",
1518    "try { } catch (eval) { }",
1519    "try { } catch (arguments) { }",
1520    "function eval() { }",
1521    "function arguments() { }",
1522    "function foo(eval) { }",
1523    "function foo(arguments) { }",
1524    "function foo(bar, eval) { }",
1525    "function foo(bar, arguments) { }",
1526    "eval = 1;",
1527    "arguments = 1;",
1528    "var foo = eval = 1;",
1529    "var foo = arguments = 1;",
1530    "++eval;",
1531    "++arguments;",
1532    "eval++;",
1533    "arguments++;",
1534    NULL
1535  };
1536
1537  RunParserSyncTest(context_data, statement_data, kError);
1538}
1539
1540
1541TEST(NoErrorsEvalAndArgumentsSloppy) {
1542  // Tests that both preparsing and parsing accept "eval" and "arguments" as
1543  // identifiers when needed.
1544  const char* context_data[][2] = {
1545    { "", "" },
1546    { "function test_func() {", "}"},
1547    { NULL, NULL }
1548  };
1549
1550  const char* statement_data[] = {
1551    "var eval;",
1552    "var arguments",
1553    "var foo, eval;",
1554    "var foo, arguments;",
1555    "try { } catch (eval) { }",
1556    "try { } catch (arguments) { }",
1557    "function eval() { }",
1558    "function arguments() { }",
1559    "function foo(eval) { }",
1560    "function foo(arguments) { }",
1561    "function foo(bar, eval) { }",
1562    "function foo(bar, arguments) { }",
1563    "eval = 1;",
1564    "arguments = 1;",
1565    "var foo = eval = 1;",
1566    "var foo = arguments = 1;",
1567    "++eval;",
1568    "++arguments;",
1569    "eval++;",
1570    "arguments++;",
1571    NULL
1572  };
1573
1574  RunParserSyncTest(context_data, statement_data, kSuccess);
1575}
1576
1577
1578TEST(NoErrorsEvalAndArgumentsStrict) {
1579  const char* context_data[][2] = {
1580    { "\"use strict\";", "" },
1581    { "function test_func() { \"use strict\";", "}" },
1582    { NULL, NULL }
1583  };
1584
1585  const char* statement_data[] = {
1586    "eval;",
1587    "arguments;",
1588    "var foo = eval;",
1589    "var foo = arguments;",
1590    "var foo = { eval: 1 };",
1591    "var foo = { arguments: 1 };",
1592    "var foo = { }; foo.eval = {};",
1593    "var foo = { }; foo.arguments = {};",
1594    NULL
1595  };
1596
1597  RunParserSyncTest(context_data, statement_data, kSuccess);
1598}
1599
1600
1601TEST(ErrorsFutureStrictReservedWords) {
1602  // Tests that both preparsing and parsing produce the right kind of errors for
1603  // using future strict reserved words as identifiers. Without the strict mode,
1604  // it's ok to use future strict reserved words as identifiers. With the strict
1605  // mode, it isn't.
1606  const char* context_data[][2] = {
1607    { "\"use strict\";", "" },
1608    { "function test_func() {\"use strict\"; ", "}"},
1609    { NULL, NULL }
1610  };
1611
1612  const char* statement_data[] = {
1613    "var interface;",
1614    "var foo, interface;",
1615    "try { } catch (interface) { }",
1616    "function interface() { }",
1617    "function foo(interface) { }",
1618    "function foo(bar, interface) { }",
1619    "interface = 1;",
1620    "var foo = interface = 1;",
1621    "++interface;",
1622    "interface++;",
1623    NULL
1624  };
1625
1626  RunParserSyncTest(context_data, statement_data, kError);
1627}
1628
1629
1630TEST(NoErrorsFutureStrictReservedWords) {
1631  const char* context_data[][2] = {
1632    { "", "" },
1633    { "function test_func() {", "}"},
1634    { NULL, NULL }
1635  };
1636
1637  const char* statement_data[] = {
1638    "var interface;",
1639    "var foo, interface;",
1640    "try { } catch (interface) { }",
1641    "function interface() { }",
1642    "function foo(interface) { }",
1643    "function foo(bar, interface) { }",
1644    "interface = 1;",
1645    "var foo = interface = 1;",
1646    "++interface;",
1647    "interface++;",
1648    NULL
1649  };
1650
1651  RunParserSyncTest(context_data, statement_data, kSuccess);
1652}
1653
1654
1655TEST(ErrorsReservedWords) {
1656  // Tests that both preparsing and parsing produce the right kind of errors for
1657  // using future reserved words as identifiers. These tests don't depend on the
1658  // strict mode.
1659  const char* context_data[][2] = {
1660    { "", "" },
1661    { "\"use strict\";", "" },
1662    { "var eval; function test_func() {", "}"},
1663    { "var eval; function test_func() {\"use strict\"; ", "}"},
1664    { NULL, NULL }
1665  };
1666
1667  const char* statement_data[] = {
1668    "var super;",
1669    "var foo, super;",
1670    "try { } catch (super) { }",
1671    "function super() { }",
1672    "function foo(super) { }",
1673    "function foo(bar, super) { }",
1674    "super = 1;",
1675    "var foo = super = 1;",
1676    "++super;",
1677    "super++;",
1678    "function foo super",
1679    NULL
1680  };
1681
1682  RunParserSyncTest(context_data, statement_data, kError);
1683}
1684
1685
1686TEST(NoErrorsYieldSloppy) {
1687  // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
1688  // generator (see next test).
1689  const char* context_data[][2] = {
1690    { "", "" },
1691    { "function is_not_gen() {", "}" },
1692    { NULL, NULL }
1693  };
1694
1695  const char* statement_data[] = {
1696    "var yield;",
1697    "var foo, yield;",
1698    "try { } catch (yield) { }",
1699    "function yield() { }",
1700    "function foo(yield) { }",
1701    "function foo(bar, yield) { }",
1702    "yield = 1;",
1703    "var foo = yield = 1;",
1704    "++yield;",
1705    "yield++;",
1706    NULL
1707  };
1708
1709  RunParserSyncTest(context_data, statement_data, kSuccess);
1710}
1711
1712
1713TEST(ErrorsYieldSloppyGenerator) {
1714  const char* context_data[][2] = {
1715    { "function * is_gen() {", "}" },
1716    { NULL, NULL }
1717  };
1718
1719  const char* statement_data[] = {
1720    "var yield;",
1721    "var foo, yield;",
1722    "try { } catch (yield) { }",
1723    "function yield() { }",
1724    // BUG: These should not be allowed, but they are (if kAllowGenerators is
1725    // set)
1726    // "function foo(yield) { }",
1727    // "function foo(bar, yield) { }",
1728    "yield = 1;",
1729    "var foo = yield = 1;",
1730    "++yield;",
1731    "yield++;",
1732    NULL
1733  };
1734
1735  // If generators are not allowed, the error will be produced at the '*' token,
1736  // so this test works both with and without the kAllowGenerators flag.
1737  RunParserSyncTest(context_data, statement_data, kError);
1738}
1739
1740
1741TEST(ErrorsYieldStrict) {
1742  const char* context_data[][2] = {
1743    { "\"use strict\";", "" },
1744    { "\"use strict\"; function is_not_gen() {", "}" },
1745    { "function test_func() {\"use strict\"; ", "}"},
1746    { NULL, NULL }
1747  };
1748
1749  const char* statement_data[] = {
1750    "var yield;",
1751    "var foo, yield;",
1752    "try { } catch (yield) { }",
1753    "function yield() { }",
1754    "function foo(yield) { }",
1755    "function foo(bar, yield) { }",
1756    "yield = 1;",
1757    "var foo = yield = 1;",
1758    "++yield;",
1759    "yield++;",
1760    NULL
1761  };
1762
1763  RunParserSyncTest(context_data, statement_data, kError);
1764}
1765
1766
1767TEST(ErrorsYield) {
1768  const char* context_data[][2] = {
1769    { "function * is_gen() {", "}" },
1770    { NULL, NULL }
1771  };
1772
1773  const char* statement_data[] = {
1774    "yield 2;",  // this is legal inside generator
1775    "yield * 2;",  // this is legal inside generator
1776    NULL
1777  };
1778
1779  // Here we cannot assert that there is no error, since there will be without
1780  // the kAllowGenerators flag. However, we test that Parser and PreParser
1781  // produce the same errors.
1782  RunParserSyncTest(context_data, statement_data, kSuccessOrError);
1783}
1784
1785
1786TEST(ErrorsNameOfStrictFunction) {
1787  // Tests that illegal tokens as names of a strict function produce the correct
1788  // errors.
1789  const char* context_data[][2] = {
1790    { "", ""},
1791    { "\"use strict\";", ""},
1792    { NULL, NULL }
1793  };
1794
1795  const char* statement_data[] = {
1796    "function eval() {\"use strict\";}",
1797    "function arguments() {\"use strict\";}",
1798    "function interface() {\"use strict\";}",
1799    "function yield() {\"use strict\";}",
1800    // Future reserved words are always illegal
1801    "function super() { }",
1802    "function super() {\"use strict\";}",
1803    NULL
1804  };
1805
1806  RunParserSyncTest(context_data, statement_data, kError);
1807}
1808
1809
1810TEST(NoErrorsNameOfStrictFunction) {
1811  const char* context_data[][2] = {
1812    { "", ""},
1813    { NULL, NULL }
1814  };
1815
1816  const char* statement_data[] = {
1817    "function eval() { }",
1818    "function arguments() { }",
1819    "function interface() { }",
1820    "function yield() { }",
1821    NULL
1822  };
1823
1824  RunParserSyncTest(context_data, statement_data, kSuccess);
1825}
1826
1827
1828
1829TEST(ErrorsIllegalWordsAsLabelsSloppy) {
1830  // Using future reserved words as labels is always an error.
1831  const char* context_data[][2] = {
1832    { "", ""},
1833    { "function test_func() {", "}" },
1834    { NULL, NULL }
1835  };
1836
1837  const char* statement_data[] = {
1838    "super: while(true) { break super; }",
1839    NULL
1840  };
1841
1842  RunParserSyncTest(context_data, statement_data, kError);
1843}
1844
1845
1846TEST(ErrorsIllegalWordsAsLabelsStrict) {
1847  // Tests that illegal tokens as labels produce the correct errors.
1848  const char* context_data[][2] = {
1849    { "\"use strict\";", "" },
1850    { "function test_func() {\"use strict\"; ", "}"},
1851    { NULL, NULL }
1852  };
1853
1854  const char* statement_data[] = {
1855    "super: while(true) { break super; }",
1856    "interface: while(true) { break interface; }",
1857    "yield: while(true) { break yield; }",
1858    NULL
1859  };
1860
1861  RunParserSyncTest(context_data, statement_data, kError);
1862}
1863
1864
1865TEST(NoErrorsIllegalWordsAsLabels) {
1866  // Using eval and arguments as labels is legal even in strict mode.
1867  const char* context_data[][2] = {
1868    { "", ""},
1869    { "function test_func() {", "}" },
1870    { "\"use strict\";", "" },
1871    { "\"use strict\"; function test_func() {", "}" },
1872    { NULL, NULL }
1873  };
1874
1875  const char* statement_data[] = {
1876    "mylabel: while(true) { break mylabel; }",
1877    "eval: while(true) { break eval; }",
1878    "arguments: while(true) { break arguments; }",
1879    NULL
1880  };
1881
1882  RunParserSyncTest(context_data, statement_data, kSuccess);
1883}
1884
1885
1886TEST(ErrorsParenthesizedLabels) {
1887  // Parenthesized identifiers shouldn't be recognized as labels.
1888  const char* context_data[][2] = {
1889    { "", ""},
1890    { "function test_func() {", "}" },
1891    { NULL, NULL }
1892  };
1893
1894  const char* statement_data[] = {
1895    "(mylabel): while(true) { break mylabel; }",
1896    NULL
1897  };
1898
1899  RunParserSyncTest(context_data, statement_data, kError);
1900}
1901
1902
1903TEST(NoErrorsParenthesizedDirectivePrologue) {
1904  // Parenthesized directive prologue shouldn't be recognized.
1905  const char* context_data[][2] = {
1906    { "", ""},
1907    { NULL, NULL }
1908  };
1909
1910  const char* statement_data[] = {
1911    "(\"use strict\"); var eval;",
1912    NULL
1913  };
1914
1915  RunParserSyncTest(context_data, statement_data, kSuccess);
1916}
1917
1918
1919TEST(ErrorsNotAnIdentifierName) {
1920  const char* context_data[][2] = {
1921    { "", ""},
1922    { "\"use strict\";", ""},
1923    { NULL, NULL }
1924  };
1925
1926  const char* statement_data[] = {
1927    "var foo = {}; foo.{;",
1928    "var foo = {}; foo.};",
1929    "var foo = {}; foo.=;",
1930    "var foo = {}; foo.888;",
1931    "var foo = {}; foo.-;",
1932    "var foo = {}; foo.--;",
1933    NULL
1934  };
1935
1936  RunParserSyncTest(context_data, statement_data, kError);
1937}
1938
1939
1940TEST(NoErrorsIdentifierNames) {
1941  // Keywords etc. are valid as property names.
1942  const char* context_data[][2] = {
1943    { "", ""},
1944    { "\"use strict\";", ""},
1945    { NULL, NULL }
1946  };
1947
1948  const char* statement_data[] = {
1949    "var foo = {}; foo.if;",
1950    "var foo = {}; foo.yield;",
1951    "var foo = {}; foo.super;",
1952    "var foo = {}; foo.interface;",
1953    "var foo = {}; foo.eval;",
1954    "var foo = {}; foo.arguments;",
1955    NULL
1956  };
1957
1958  RunParserSyncTest(context_data, statement_data, kSuccess);
1959}
1960
1961
1962TEST(DontRegressPreParserDataSizes) {
1963  // These tests make sure that Parser doesn't start producing less "preparse
1964  // data" (data which the embedder can cache).
1965  v8::V8::Initialize();
1966  v8::Isolate* isolate = CcTest::isolate();
1967  v8::HandleScope handles(isolate);
1968
1969  int marker;
1970  CcTest::i_isolate()->stack_guard()->SetStackLimit(
1971      reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1972
1973  struct TestCase {
1974    const char* program;
1975    int functions;
1976  } test_cases[] = {
1977    // No functions.
1978    {"var x = 42;", 0},
1979    // Functions.
1980    {"function foo() {}", 1}, {"function foo() {} function bar() {}", 2},
1981    // Getter / setter functions are recorded as functions if they're on the top
1982    // level.
1983    {"var x = {get foo(){} };", 1},
1984    // Functions insize lazy functions are not recorded.
1985    {"function lazy() { function a() {} function b() {} function c() {} }", 1},
1986    {"function lazy() { var x = {get foo(){} } }", 1},
1987    {NULL, 0}
1988  };
1989
1990  for (int i = 0; test_cases[i].program; i++) {
1991    const char* program = test_cases[i].program;
1992    i::Factory* factory = CcTest::i_isolate()->factory();
1993    i::Handle<i::String> source =
1994        factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
1995    i::Handle<i::Script> script = factory->NewScript(source);
1996    i::CompilationInfoWithZone info(script);
1997    i::ScriptData* data = NULL;
1998    info.SetCachedData(&data, i::PRODUCE_CACHED_DATA);
1999    i::Parser::Parse(&info, true);
2000    CHECK(data);
2001    CHECK(!data->HasError());
2002
2003    if (data->function_count() != test_cases[i].functions) {
2004      i::OS::Print(
2005          "Expected preparse data for program:\n"
2006          "\t%s\n"
2007          "to contain %d functions, however, received %d functions.\n",
2008          program, test_cases[i].functions,
2009          data->function_count());
2010      CHECK(false);
2011    }
2012    delete data;
2013  }
2014}
2015
2016
2017TEST(FunctionDeclaresItselfStrict) {
2018  // Tests that we produce the right kinds of errors when a function declares
2019  // itself strict (we cannot produce there errors as soon as we see the
2020  // offending identifiers, because we don't know at that point whether the
2021  // function is strict or not).
2022  const char* context_data[][2] = {
2023    {"function eval() {", "}"},
2024    {"function arguments() {", "}"},
2025    {"function yield() {", "}"},
2026    {"function interface() {", "}"},
2027    {"function foo(eval) {", "}"},
2028    {"function foo(arguments) {", "}"},
2029    {"function foo(yield) {", "}"},
2030    {"function foo(interface) {", "}"},
2031    {"function foo(bar, eval) {", "}"},
2032    {"function foo(bar, arguments) {", "}"},
2033    {"function foo(bar, yield) {", "}"},
2034    {"function foo(bar, interface) {", "}"},
2035    {"function foo(bar, bar) {", "}"},
2036    { NULL, NULL }
2037  };
2038
2039  const char* strict_statement_data[] = {
2040    "\"use strict\";",
2041    NULL
2042  };
2043
2044  const char* non_strict_statement_data[] = {
2045    ";",
2046    NULL
2047  };
2048
2049  RunParserSyncTest(context_data, strict_statement_data, kError);
2050  RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2051}
2052
2053
2054TEST(ErrorsTryWithoutCatchOrFinally) {
2055  const char* context_data[][2] = {
2056    {"", ""},
2057    { NULL, NULL }
2058  };
2059
2060  const char* statement_data[] = {
2061    "try { }",
2062    "try { } foo();",
2063    "try { } catch (e) foo();",
2064    "try { } catch { }",
2065    "try { } finally foo();",
2066    NULL
2067  };
2068
2069  RunParserSyncTest(context_data, statement_data, kError);
2070}
2071
2072
2073TEST(NoErrorsTryCatchFinally) {
2074  const char* context_data[][2] = {
2075    {"", ""},
2076    { NULL, NULL }
2077  };
2078
2079  const char* statement_data[] = {
2080    "try { } catch (e) { }",
2081    "try { } catch (e) { } finally { }",
2082    "try { } finally { }",
2083    NULL
2084  };
2085
2086  RunParserSyncTest(context_data, statement_data, kSuccess);
2087}
2088
2089
2090TEST(ErrorsRegexpLiteral) {
2091  const char* context_data[][2] = {
2092    {"var r = ", ""},
2093    { NULL, NULL }
2094  };
2095
2096  const char* statement_data[] = {
2097    "/unterminated",
2098    NULL
2099  };
2100
2101  RunParserSyncTest(context_data, statement_data, kError);
2102}
2103
2104
2105TEST(NoErrorsRegexpLiteral) {
2106  const char* context_data[][2] = {
2107    {"var r = ", ""},
2108    { NULL, NULL }
2109  };
2110
2111  const char* statement_data[] = {
2112    "/foo/",
2113    "/foo/g",
2114    "/foo/whatever",  // This is an error but not detected by the parser.
2115    NULL
2116  };
2117
2118  RunParserSyncTest(context_data, statement_data, kSuccess);
2119}
2120
2121
2122TEST(Intrinsics) {
2123  const char* context_data[][2] = {
2124    {"", ""},
2125    { NULL, NULL }
2126  };
2127
2128  const char* statement_data[] = {
2129    "%someintrinsic(arg)",
2130    NULL
2131  };
2132
2133  // Parsing will fail or succeed depending on whether we allow natives syntax
2134  // or not.
2135  RunParserSyncTest(context_data, statement_data, kSuccessOrError);
2136}
2137
2138
2139TEST(NoErrorsNewExpression) {
2140  const char* context_data[][2] = {
2141    {"", ""},
2142    {"var f =", ""},
2143    { NULL, NULL }
2144  };
2145
2146  const char* statement_data[] = {
2147    "new foo",
2148    "new foo();",
2149    "new foo(1);",
2150    "new foo(1, 2);",
2151    // The first () will be processed as a part of the NewExpression and the
2152    // second () will be processed as part of LeftHandSideExpression.
2153    "new foo()();",
2154    // The first () will be processed as a part of the inner NewExpression and
2155    // the second () will be processed as a part of the outer NewExpression.
2156    "new new foo()();",
2157    "new foo.bar;",
2158    "new foo.bar();",
2159    "new foo.bar.baz;",
2160    "new foo.bar().baz;",
2161    "new foo[bar];",
2162    "new foo[bar]();",
2163    "new foo[bar][baz];",
2164    "new foo[bar]()[baz];",
2165    "new foo[bar].baz(baz)()[bar].baz;",
2166    "new \"foo\"",  // Runtime error
2167    "new 1",  // Runtime error
2168    // This even runs:
2169    "(new new Function(\"this.x = 1\")).x;",
2170    "new new Test_Two(String, 2).v(0123).length;",
2171    NULL
2172  };
2173
2174  RunParserSyncTest(context_data, statement_data, kSuccess);
2175}
2176
2177
2178TEST(ErrorsNewExpression) {
2179  const char* context_data[][2] = {
2180    {"", ""},
2181    {"var f =", ""},
2182    { NULL, NULL }
2183  };
2184
2185  const char* statement_data[] = {
2186    "new foo bar",
2187    "new ) foo",
2188    "new ++foo",
2189    "new foo ++",
2190    NULL
2191  };
2192
2193  RunParserSyncTest(context_data, statement_data, kError);
2194}
2195
2196
2197TEST(StrictObjectLiteralChecking) {
2198  const char* strict_context_data[][2] = {
2199    {"\"use strict\"; var myobject = {", "};"},
2200    { NULL, NULL }
2201  };
2202  const char* non_strict_context_data[][2] = {
2203    {"var myobject = {", "};"},
2204    { NULL, NULL }
2205  };
2206
2207  // These are only errors in strict mode.
2208  const char* statement_data[] = {
2209    "foo: 1, foo: 2",
2210    "\"foo\": 1, \"foo\": 2",
2211    "foo: 1, \"foo\": 2",
2212    "1: 1, 1: 2",
2213    "1: 1, \"1\": 2",
2214    "get: 1, get: 2",  // Not a getter for real, just a property called get.
2215    "set: 1, set: 2",  // Not a setter for real, just a property called set.
2216    NULL
2217  };
2218
2219  RunParserSyncTest(non_strict_context_data, statement_data, kSuccess);
2220  RunParserSyncTest(strict_context_data, statement_data, kError);
2221}
2222
2223
2224TEST(ErrorsObjectLiteralChecking) {
2225  const char* context_data[][2] = {
2226    {"\"use strict\"; var myobject = {", "};"},
2227    {"var myobject = {", "};"},
2228    { NULL, NULL }
2229  };
2230
2231  const char* statement_data[] = {
2232    "foo: 1, get foo() {}",
2233    "foo: 1, set foo(v) {}",
2234    "\"foo\": 1, get \"foo\"() {}",
2235    "\"foo\": 1, set \"foo\"(v) {}",
2236    "1: 1, get 1() {}",
2237    "1: 1, set 1() {}",
2238    // It's counter-intuitive, but these collide too (even in classic
2239    // mode). Note that we can have "foo" and foo as properties in classic mode,
2240    // but we cannot have "foo" and get foo, or foo and get "foo".
2241    "foo: 1, get \"foo\"() {}",
2242    "foo: 1, set \"foo\"(v) {}",
2243    "\"foo\": 1, get foo() {}",
2244    "\"foo\": 1, set foo(v) {}",
2245    "1: 1, get \"1\"() {}",
2246    "1: 1, set \"1\"() {}",
2247    "\"1\": 1, get 1() {}"
2248    "\"1\": 1, set 1(v) {}"
2249    // Wrong number of parameters
2250    "get bar(x) {}",
2251    "get bar(x, y) {}",
2252    "set bar() {}",
2253    "set bar(x, y) {}",
2254    // Parsing FunctionLiteral for getter or setter fails
2255    "get foo( +",
2256    "get foo() \"error\"",
2257    NULL
2258  };
2259
2260  RunParserSyncTest(context_data, statement_data, kError);
2261}
2262
2263
2264TEST(NoErrorsObjectLiteralChecking) {
2265  const char* context_data[][2] = {
2266    {"var myobject = {", "};"},
2267    {"\"use strict\"; var myobject = {", "};"},
2268    { NULL, NULL }
2269  };
2270
2271  const char* statement_data[] = {
2272    "foo: 1, bar: 2",
2273    "\"foo\": 1, \"bar\": 2",
2274    "1: 1, 2: 2",
2275    // Syntax: IdentifierName ':' AssignmentExpression
2276    "foo: bar = 5 + baz",
2277    // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2278    "get foo() {}",
2279    "get \"foo\"() {}",
2280    "get 1() {}",
2281    // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2282    //     '{' FunctionBody '}'
2283    "set foo(v) {}",
2284    "set \"foo\"(v) {}",
2285    "set 1(v) {}",
2286    // Non-colliding getters and setters -> no errors
2287    "foo: 1, get bar() {}",
2288    "foo: 1, set bar(v) {}",
2289    "\"foo\": 1, get \"bar\"() {}",
2290    "\"foo\": 1, set \"bar\"(v) {}",
2291    "1: 1, get 2() {}",
2292    "1: 1, set 2(v) {}",
2293    // Keywords, future reserved and strict future reserved are also allowed as
2294    // property names.
2295    "if: 4",
2296    "interface: 5",
2297    "super: 6",
2298    "eval: 7",
2299    "arguments: 8",
2300    NULL
2301  };
2302
2303  RunParserSyncTest(context_data, statement_data, kSuccess);
2304}
2305
2306
2307TEST(TooManyArguments) {
2308  const char* context_data[][2] = {
2309    {"foo(", "0)"},
2310    { NULL, NULL }
2311  };
2312
2313  using v8::internal::Code;
2314  char statement[Code::kMaxArguments * 2 + 1];
2315  for (int i = 0; i < Code::kMaxArguments; ++i) {
2316    statement[2 * i] = '0';
2317    statement[2 * i + 1] = ',';
2318  }
2319  statement[Code::kMaxArguments * 2] = 0;
2320
2321  const char* statement_data[] = {
2322    statement,
2323    NULL
2324  };
2325
2326  // The test is quite slow, so run it with a reduced set of flags.
2327  static const ParserFlag empty_flags[] = {kAllowLazy};
2328  RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2329}
2330
2331
2332TEST(StrictDelete) {
2333  // "delete <Identifier>" is not allowed in strict mode.
2334  const char* strict_context_data[][2] = {
2335    {"\"use strict\"; ", ""},
2336    { NULL, NULL }
2337  };
2338
2339  const char* sloppy_context_data[][2] = {
2340    {"", ""},
2341    { NULL, NULL }
2342  };
2343
2344  // These are errors in the strict mode.
2345  const char* sloppy_statement_data[] = {
2346    "delete foo;",
2347    "delete foo + 1;",
2348    "delete (foo);",
2349    "delete eval;",
2350    "delete interface;",
2351    NULL
2352  };
2353
2354  // These are always OK
2355  const char* good_statement_data[] = {
2356    "delete this;",
2357    "delete 1;",
2358    "delete 1 + 2;",
2359    "delete foo();",
2360    "delete foo.bar;",
2361    "delete foo[bar];",
2362    "delete foo--;",
2363    "delete --foo;",
2364    "delete new foo();",
2365    "delete new foo(bar);",
2366    NULL
2367  };
2368
2369  // These are always errors
2370  const char* bad_statement_data[] = {
2371    "delete if;",
2372    NULL
2373  };
2374
2375  RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
2376  RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
2377
2378  RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
2379  RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
2380
2381  RunParserSyncTest(strict_context_data, bad_statement_data, kError);
2382  RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
2383}
2384
2385
2386TEST(InvalidLeftHandSide) {
2387  const char* assignment_context_data[][2] = {
2388    {"", " = 1;"},
2389    {"\"use strict\"; ", " = 1;"},
2390    { NULL, NULL }
2391  };
2392
2393  const char* prefix_context_data[][2] = {
2394    {"++", ";"},
2395    {"\"use strict\"; ++", ";"},
2396    {NULL, NULL},
2397  };
2398
2399  const char* postfix_context_data[][2] = {
2400    {"", "++;"},
2401    {"\"use strict\"; ", "++;"},
2402    { NULL, NULL }
2403  };
2404
2405  // Good left hand sides for assigment or prefix / postfix operations.
2406  const char* good_statement_data[] = {
2407    "foo",
2408    "foo.bar",
2409    "foo[bar]",
2410    "foo()[bar]",
2411    "foo().bar",
2412    "this.foo",
2413    "this[foo]",
2414    "new foo()[bar]",
2415    "new foo().bar",
2416    "foo()",
2417    "foo(bar)",
2418    "foo[bar]()",
2419    "foo.bar()",
2420    "this()",
2421    "this.foo()",
2422    "this[foo].bar()",
2423    "this.foo[foo].bar(this)(bar)[foo]()",
2424    NULL
2425  };
2426
2427  // Bad left hand sides for assigment or prefix / postfix operations.
2428  const char* bad_statement_data_common[] = {
2429    "2",
2430    "new foo",
2431    "new foo()",
2432    "null",
2433    "if",  // Unexpected token
2434    "{x: 1}",  // Unexpected token
2435    "this",
2436    "\"bar\"",
2437    "(foo + bar)",
2438    "new new foo()[bar]",  // means: new (new foo()[bar])
2439    "new new foo().bar",  // means: new (new foo()[bar])
2440    NULL
2441  };
2442
2443  // These are not okay for assignment, but okay for prefix / postix.
2444  const char* bad_statement_data_for_assignment[] = {
2445    "++foo",
2446    "foo++",
2447    "foo + bar",
2448    NULL
2449  };
2450
2451  RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
2452  RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
2453  RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
2454                    kError);
2455
2456  RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
2457  RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
2458
2459  RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
2460  RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
2461}
2462
2463
2464TEST(FuncNameInferrerBasic) {
2465  // Tests that function names are inferred properly.
2466  i::FLAG_allow_natives_syntax = true;
2467  v8::Isolate* isolate = CcTest::isolate();
2468  v8::HandleScope scope(isolate);
2469  LocalContext env;
2470  CompileRun("var foo1 = function() {}; "
2471             "var foo2 = function foo3() {}; "
2472             "function not_ctor() { "
2473             "  var foo4 = function() {}; "
2474             "  return %FunctionGetInferredName(foo4); "
2475             "} "
2476             "function Ctor() { "
2477             "  var foo5 = function() {}; "
2478             "  return %FunctionGetInferredName(foo5); "
2479             "} "
2480             "var obj1 = { foo6: function() {} }; "
2481             "var obj2 = { 'foo7': function() {} }; "
2482             "var obj3 = {}; "
2483             "obj3[1] = function() {}; "
2484             "var obj4 = {}; "
2485             "obj4[1] = function foo8() {}; "
2486             "var obj5 = {}; "
2487             "obj5['foo9'] = function() {}; "
2488             "var obj6 = { obj7 : { foo10: function() {} } };");
2489  ExpectString("%FunctionGetInferredName(foo1)", "foo1");
2490  // foo2 is not unnamed -> its name is not inferred.
2491  ExpectString("%FunctionGetInferredName(foo2)", "");
2492  ExpectString("not_ctor()", "foo4");
2493  ExpectString("Ctor()", "Ctor.foo5");
2494  ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
2495  ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
2496  ExpectString("%FunctionGetInferredName(obj3[1])",
2497               "obj3.(anonymous function)");
2498  ExpectString("%FunctionGetInferredName(obj4[1])", "");
2499  ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
2500  ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
2501}
2502
2503
2504TEST(FuncNameInferrerTwoByte) {
2505  // Tests function name inferring in cases where some parts of the inferred
2506  // function name are two-byte strings.
2507  i::FLAG_allow_natives_syntax = true;
2508  v8::Isolate* isolate = CcTest::isolate();
2509  v8::HandleScope scope(isolate);
2510  LocalContext env;
2511  uint16_t* two_byte_source = AsciiToTwoByteString(
2512      "var obj1 = { oXj2 : { foo1: function() {} } }; "
2513      "%FunctionGetInferredName(obj1.oXj2.foo1)");
2514  uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2515  // Make it really non-ASCII (replace the Xs with a non-ASCII character).
2516  two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
2517  v8::Local<v8::String> source =
2518      v8::String::NewFromTwoByte(isolate, two_byte_source);
2519  v8::Local<v8::Value> result = CompileRun(source);
2520  CHECK(result->IsString());
2521  v8::Local<v8::String> expected_name =
2522      v8::String::NewFromTwoByte(isolate, two_byte_name);
2523  CHECK(result->Equals(expected_name));
2524  i::DeleteArray(two_byte_source);
2525  i::DeleteArray(two_byte_name);
2526}
2527
2528
2529TEST(FuncNameInferrerEscaped) {
2530  // The same as FuncNameInferrerTwoByte, except that we express the two-byte
2531  // character as a unicode escape.
2532  i::FLAG_allow_natives_syntax = true;
2533  v8::Isolate* isolate = CcTest::isolate();
2534  v8::HandleScope scope(isolate);
2535  LocalContext env;
2536  uint16_t* two_byte_source = AsciiToTwoByteString(
2537      "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
2538      "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
2539  uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2540  // Fix to correspond to the non-ASCII name in two_byte_source.
2541  two_byte_name[6] = 0x010d;
2542  v8::Local<v8::String> source =
2543      v8::String::NewFromTwoByte(isolate, two_byte_source);
2544  v8::Local<v8::Value> result = CompileRun(source);
2545  CHECK(result->IsString());
2546  v8::Local<v8::String> expected_name =
2547      v8::String::NewFromTwoByte(isolate, two_byte_name);
2548  CHECK(result->Equals(expected_name));
2549  i::DeleteArray(two_byte_source);
2550  i::DeleteArray(two_byte_name);
2551}
2552