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