• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(ScanKeywords)45 TEST(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 
TEST(ScanHTMLEndComments)109 TEST(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 
181 class ScriptResource : public v8::String::ExternalAsciiStringResource {
182  public:
ScriptResource(const char * data,size_t length)183   ScriptResource(const char* data, size_t length)
184       : data_(data), length_(length) { }
185 
data() const186   const char* data() const { return data_; }
length() const187   size_t length() const { return length_; }
188 
189  private:
190   const char* data_;
191   size_t length_;
192 };
193 
194 
TEST(UsingCachedData)195 TEST(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 
TEST(PreparseFunctionDataIsUsed)237 TEST(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 
TEST(StandAlonePreParser)280 TEST(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 
TEST(StandAlonePreParserNoNatives)317 TEST(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 
TEST(PreparsingObjectLiterals)352 TEST(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 
TEST(RegressChromium62639)389 TEST(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 
TEST(Regress928)421 TEST(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 
TEST(PreParseOverflow)471 TEST(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 
499 class TestExternalResource: public v8::String::ExternalStringResource {
500  public:
TestExternalResource(uint16_t * data,int length)501   explicit TestExternalResource(uint16_t* data, int length)
502       : data_(data), length_(static_cast<size_t>(length)) { }
503 
~TestExternalResource()504   ~TestExternalResource() { }
505 
data() const506   const uint16_t* data() const {
507     return data_;
508   }
509 
length() const510   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 
TestCharacterStream(const char * ascii_source,unsigned length,unsigned start=0,unsigned end=0)521 void 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 
TEST(CharacterStreams)633 TEST(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 
TEST(Utf8CharacterStream)654 TEST(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 
TestStreamScanner(i::Utf16CharacterStream * stream,i::Token::Value * expected_tokens,int skip_pos=0,int skip_to=0)705 void 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 
TEST(StreamScanner)725 TEST(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 
TestScanRegExp(const char * re_source,const char * expected)787 void 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 
TEST(RegExpScanning)812 TEST(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 
Utf8LengthHelper(const char * s)849 static 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 
TEST(ScopePositions)910 TEST(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 
FormatMessage(i::ScriptData * data)1144 i::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 
1171 enum ParserFlag {
1172   kAllowLazy,
1173   kAllowNativesSyntax,
1174   kAllowHarmonyScoping,
1175   kAllowModules,
1176   kAllowGenerators,
1177   kAllowForOf,
1178   kAllowHarmonyNumericLiterals
1179 };
1180 
1181 
1182 enum ParserSyncTestResult {
1183   kSuccessOrError,
1184   kSuccess,
1185   kError
1186 };
1187 
1188 template <typename Traits>
SetParserFlags(i::ParserBase<Traits> * parser,i::EnumSet<ParserFlag> flags)1189 void 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 
TestParserSyncWithFlags(i::Handle<i::String> source,i::EnumSet<ParserFlag> flags,ParserSyncTestResult result)1202 void 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 
TestParserSync(const char * source,const ParserFlag * flag_list,size_t flag_list_length,ParserSyncTestResult result=kSuccessOrError)1300 void 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 
TEST(ParserSync)1316 TEST(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 
TEST(StrictOctal)1434 TEST(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 
RunParserSyncTest(const char * context_data[][2],const char * statement_data[],ParserSyncTestResult result,const ParserFlag * flags=NULL,int flags_len=0)1457 void 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 
TEST(ErrorsEvalAndArguments)1502 TEST(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 
TEST(NoErrorsEvalAndArgumentsSloppy)1541 TEST(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 
TEST(NoErrorsEvalAndArgumentsStrict)1578 TEST(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 
TEST(ErrorsFutureStrictReservedWords)1601 TEST(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 
TEST(NoErrorsFutureStrictReservedWords)1630 TEST(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 
TEST(ErrorsReservedWords)1655 TEST(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 
TEST(NoErrorsYieldSloppy)1686 TEST(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 
TEST(ErrorsYieldSloppyGenerator)1713 TEST(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 
TEST(ErrorsYieldStrict)1741 TEST(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 
TEST(ErrorsYield)1767 TEST(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 
TEST(ErrorsNameOfStrictFunction)1786 TEST(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 
TEST(NoErrorsNameOfStrictFunction)1810 TEST(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 
TEST(ErrorsIllegalWordsAsLabelsSloppy)1829 TEST(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 
TEST(ErrorsIllegalWordsAsLabelsStrict)1846 TEST(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 
TEST(NoErrorsIllegalWordsAsLabels)1865 TEST(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 
TEST(ErrorsParenthesizedLabels)1886 TEST(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 
TEST(NoErrorsParenthesizedDirectivePrologue)1903 TEST(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 
TEST(ErrorsNotAnIdentifierName)1919 TEST(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 
TEST(NoErrorsIdentifierNames)1940 TEST(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 
TEST(DontRegressPreParserDataSizes)1962 TEST(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 
TEST(FunctionDeclaresItselfStrict)2017 TEST(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 
TEST(ErrorsTryWithoutCatchOrFinally)2054 TEST(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 
TEST(NoErrorsTryCatchFinally)2073 TEST(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 
TEST(ErrorsRegexpLiteral)2090 TEST(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 
TEST(NoErrorsRegexpLiteral)2105 TEST(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 
TEST(Intrinsics)2122 TEST(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 
TEST(NoErrorsNewExpression)2139 TEST(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 
TEST(ErrorsNewExpression)2178 TEST(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 
TEST(StrictObjectLiteralChecking)2197 TEST(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 
TEST(ErrorsObjectLiteralChecking)2224 TEST(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 
TEST(NoErrorsObjectLiteralChecking)2264 TEST(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 
TEST(TooManyArguments)2307 TEST(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 
TEST(StrictDelete)2332 TEST(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 
TEST(InvalidLeftHandSide)2386 TEST(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 
TEST(FuncNameInferrerBasic)2464 TEST(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 
TEST(FuncNameInferrerTwoByte)2504 TEST(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 
TEST(FuncNameInferrerEscaped)2529 TEST(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