v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-parsing.cc
Go to the documentation of this file.
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"
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 },
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) {
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;
146  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
147 
148  for (int i = 0; tests[i]; i++) {
150  isolate, tests[i], v8::String::kNormalString, i::StrLength(tests[i]));
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],
161  i::StrLength(fail_tests[i]));
163  CHECK(data == NULL || data->HasError());
164  delete data;
165  }
166 }
167 
168 
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;
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 
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),
219  reinterpret_cast<const uint8_t*>(preparse->Data()),
220  preparse->Length()));
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),
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,
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;
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,
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;
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,
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) {
358 
359  int marker;
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];
376  reinterpret_cast<const i::byte*>(program),
377  static_cast<unsigned>(strlen(program)));
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();
387  i::ScriptDataImpl data(log.ExtractData());
388  CHECK(!data.has_error());
389  }
390 }
391 
392 
393 TEST(StandAlonePreParserNoNatives) {
395 
396  int marker;
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];
410  reinterpret_cast<const i::byte*>(program),
411  static_cast<unsigned>(strlen(program)));
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();
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;
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 
469  int number) {
470  log->WriteNumber(number);
471  if (log->symbol_id_ < number + 1) {
472  log->symbol_id_ = number + 1;
473  }
474  }
476  return log->symbol_store_.size();
477  }
479  return log->symbol_id_;
480  }
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.
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) {
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 
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) {
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) {
592 
593  int marker;
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 
605  reinterpret_cast<const i::byte*>(program.get()),
606  static_cast<unsigned>(kProgramSize));
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();
615 }
616 
617 
619  public:
621  : data_(data), length_(static_cast<size_t>(length)) { }
622 
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 
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 =
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,
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 
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) {
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,
858  i::Token::LT,
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[] = {
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;
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) {
908  reinterpret_cast<const i::byte*>(re_source),
909  static_cast<unsigned>(strlen(re_source)));
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.
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) {
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;",
1061  { " try {} catch ", "(e) { block; }", "; more;",
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;",
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;",
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; }", ")();",
1088  { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
1090  { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
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;",
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;",
1105  { " for ", "(let x in {}) { block; }", "; more;",
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;",
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; }", ")();",
1124  // 4 byte encoding.
1125  { " 'foo\360\220\220\212';\n"
1126  " (function fun", "(a,b) { infunction; }", ")();",
1128  // 3 byte encoding of \u0fff.
1129  { " 'foo\340\277\277';\n"
1130  " (function fun", "(a,b) { infunction; }", ")();",
1132  // Broken 6 byte encoding with missing last byte.
1133  { " 'foo\355\240\201\355\211';\n"
1134  " (function fun", "(a,b) { infunction; }", ")();",
1136  // Broken 3 byte encoding of \u0fff with missing last byte.
1137  { " 'foo\340\277';\n"
1138  " (function fun", "(a,b) { infunction; }", ")();",
1140  // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1141  { " 'foo\340';\n"
1142  " (function fun", "(a,b) { infunction; }", ")();",
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; }", ")();",
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; }", ")();",
1152  // Unpaired lead surrogate.
1153  { " 'foo\355\240\201';\n"
1154  " (function fun", "(a,b) { infunction; }", ")();",
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; }", ")();",
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; }", ")();",
1165  // Unpaired trail surrogate.
1166  { " 'foo\355\260\211';\n"
1167  " (function fun", "(a,b) { infunction; }", ")();",
1169  // 2 byte encoding of \u00ff.
1170  { " 'foo\303\277';\n"
1171  " (function fun", "(a,b) { infunction; }", ")();",
1173  // Broken 2 byte encoding of \u00ff with missing last byte.
1174  { " 'foo\303';\n"
1175  " (function fun", "(a,b) { infunction; }", ")();",
1177  // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1178  { " 'foo\301\277';\n"
1179  " (function fun", "(a,b) { infunction; }", ")();",
1181  // Illegal 5 byte encoding.
1182  { " 'foo\370\277\277\277\277';\n"
1183  " (function fun", "(a,b) { infunction; }", ")();",
1185  // Illegal 6 byte encoding.
1186  { " 'foo\374\277\277\277\277\277';\n"
1187  " (function fun", "(a,b) { infunction; }", ")();",
1189  // Illegal 0xfe byte
1190  { " 'foo\376\277\277\277\277\277\277';\n"
1191  " (function fun", "(a,b) { infunction; }", ")();",
1193  // Illegal 0xff byte
1194  { " 'foo\377\277\277\277\277\277\277\277';\n"
1195  " (function fun", "(a,b) { infunction; }", ")();",
1197  { " 'foo';\n"
1198  " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
1200  { " 'foo';\n"
1201  " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
1204  };
1205 
1206  i::Isolate* isolate = CcTest::i_isolate();
1207  i::Factory* factory = isolate->factory();
1208 
1209  v8::HandleScope handles(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);
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 
1264  i::Isolate* isolate = CcTest::i_isolate();
1265  i::Factory* factory = isolate->factory();
1266  const char* message = data->BuildMessage();
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++) {
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;
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 
1303 };
1304 
1305 
1310 };
1311 
1312 template <typename Traits>
1315  parser->set_allow_lazy(flags.Contains(kAllowLazy));
1318  parser->set_allow_modules(flags.Contains(kAllowModules));
1320  parser->set_allow_for_of(flags.Contains(kAllowForOf));
1323 }
1324 
1325 
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.
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();
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);
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,
1429  i::Handle<i::String> str =
1431  for (int bits = 0; bits < (1 << flag_list_length); bits++) {
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());
1512  v8::Context::Scope context_scope(context);
1513 
1514  int marker;
1516  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1517 
1518  static const ParserFlag flags1[] = {
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.
1564  v8::Context::Scope context_scope(
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";
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());
1589  v8::Context::Scope context_scope(context);
1590 
1591  int marker;
1593  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1594 
1595  static const ParserFlag default_flags[] = {
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 
2091  int marker;
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 
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;
2128  reinterpret_cast<const i::byte*>(program),
2129  static_cast<unsigned>(strlen(program)));
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();
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 }
static Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12410
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
const char * data() const
#define CHECK_EQ(expected, value)
Definition: checks.h:252
PreParseResult PreParseProgram()
Definition: preparser.h:1021
static void FakeWritingSymbolIdInPreParseData(CompleteParserRecorder *log, int number)
TestExternalResource(uint16_t *data, int length)
Vector< const char * > BuildArgs()
Definition: parser.cc:320
MaybeObject * pending_exception()
Definition: isolate.h:570
Local< Value > Exception() const
Definition: api.cc:1923
static int symbol_position(CompleteParserRecorder *log)
Handle< Script > NewScript(Handle< String > source)
Definition: factory.cc:699
#define CHECK_GT(a, b)
Definition: checks.h:260
bool HasCaught() const
Definition: api.cc:1901
static const unsigned kMaxTwoByteChar
Definition: unicode.h:165
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
Handle< String > NewStringFromAscii(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.h:141
void SetHarmonyScoping(bool scoping)
Definition: scanner.h:448
void set_allow_modules(bool allow)
Definition: preparser.h:128
#define IGNORE_TOKEN(name, string, precedence)
Definition: token.h:49
#define F(size, func)
static int symbol_ids(CompleteParserRecorder *log)
void set_allow_harmony_numeric_literals(bool allow)
Definition: preparser.h:132
int int32_t
Definition: unicode.cc:47
void TestParserSync(const char *source, const ParserFlag *flag_list, size_t flag_list_length, ParserSyncTestResult result=kSuccessOrError)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 log
Definition: flags.cc:806
uintptr_t real_climit()
Definition: execution.h:241
#define CHECK_LT(a, b)
Definition: checks.h:262
TEST(ScanKeywords)
Definition: test-parsing.cc:45
#define ASSERT(condition)
Definition: checks.h:329
unsigned short uint16_t
Definition: unicode.cc:46
V8_INLINE const CachedData * GetCachedData() const
Definition: v8.h:6123
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 log
void set_allow_natives_syntax(bool allow)
Definition: preparser.h:125
void set_allow_harmony_scoping(bool allow)
Definition: preparser.h:129
#define CHECK(condition)
Definition: checks.h:75
void SetHarmonyModules(bool modules)
Definition: scanner.h:454
#define TOKEN_LIST(T, K)
Definition: token.h:51
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
Factory * factory()
Definition: isolate.h:995
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
void TestStreamScanner(i::Utf16CharacterStream *stream, i::Token::Value *expected_tokens, int skip_pos=0, int skip_to=0)
size_t length() const
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
i::Handle< i::String > FormatMessage(i::ScriptDataImpl *data)
#define KEYWORD(t, s, d)
static Local< UnboundScript > CompileUnbound(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions)
Definition: api.cc:1723
StackGuard * stack_guard()
Definition: isolate.h:874
uint8_t byte
Definition: globals.h:185
Handle< String > NewStringFromUtf8(Vector< const char > str, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:273
UnicodeCache * unicode_cache()
Definition: isolate.h:908
virtual const char * Data()=0
ParserFlag
T * start() const
Definition: utils.h:426
virtual bool HasError()=0
#define CHECK_EQU(v1, v2)
static const char * String(Value tok)
Definition: token.h:294
ZoneList< Scope * > * inner_scopes()
Definition: scopes.h:347
FunctionLiteral * function() const
Definition: compiler.h:77
void SeekForward(int pos)
Definition: scanner.cc:601
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
void set_allow_lazy(bool allow)
Definition: preparser.h:124
static void MemMove(void *dest, const void *src, size_t size)
Definition: platform.h:402
int length() const
Definition: utils.h:420
static i::Isolate * i_isolate()
Definition: cctest.h:102
bool has_pending_exception()
Definition: isolate.h:587
Handle< JSBuiltinsObject > js_builtins_object()
Definition: isolate.h:680
ParserSyncTestResult
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
Definition: unicode-inl.h:114
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
static int function_position(CompleteParserRecorder *log)
void Initialize(Utf16CharacterStream *source)
Definition: scanner.cc:55
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
static ScriptDataImpl * PreParse(Isolate *isolate, Utf16CharacterStream *source)
Definition: parser.cc:4624
int StrLength(const char *string)
Definition: utils.h:253
static void Print(const char *format,...)
const char * BuildMessage()
Definition: parser.cc:314
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:5188
static int SNPrintF(Vector< char > str, const char *format,...)
void TestParserSyncWithFlags(i::Handle< i::String > source, i::EnumSet< ParserFlag > flags, ParserSyncTestResult result)
#define CASE(name)
Location location() const
Definition: scanner.h:375
Handle< String > NewExternalStringFromTwoByte(const ExternalTwoByteString::Resource *resource)
Definition: factory.cc:563
enable upcoming ES6 features enable harmony block scoping enable harmony symbols(a.k.a.private names)") DEFINE_bool(harmony_proxies
void set_allow_for_of(bool allow)
Definition: preparser.h:127
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:153
bool Contains(E element) const
Definition: utils.h:1055
void TestCharacterStream(const char *ascii_source, unsigned length, unsigned start=0, unsigned end=0)
void set_allow_generators(bool allow)
Definition: preparser.h:126
void SetStrictMode(StrictMode strict_mode)
Definition: compiler.h:117
uint16_t uc16
Definition: globals.h:309
Scanner::Location MessageLocation()
Definition: parser.cc:307
size_t length() const
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
static Local< String > NewExternal(Isolate *isolate, ExternalStringResource *resource)
Definition: api.cc:5493
virtual int Length()=0
const uint8_t * data
Definition: v8.h:1117
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
static const unsigned kMaxThreeByteChar
Definition: unicode.h:166
void TestScanRegExp(const char *re_source, const char *expected)
static const unsigned kMaxOneByteChar
Definition: unicode.h:164
const uint16_t * data() const
Token::Value peek() const
Definition: scanner.h:380
ScriptResource(const char *data, size_t length)
static Local< Script > Compile(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions)
Definition: api.cc:1816
Token::Value Next()
Definition: scanner.cc:231
void SetParserFlags(i::ParserBase< Traits > *parser, i::EnumSet< ParserFlag > flags)
static bool Parse(CompilationInfo *info, bool allow_lazy=false)
Definition: parser.h:611
static ScriptData * PreCompile(Handle< String > source)
Definition: api.cc:1573
void DeleteArray(T *array)
Definition: allocation.h:91
void SetStackLimit(uintptr_t limit)
Definition: execution.cc:400
unsigned SeekForward(unsigned code_unit_count)
Definition: scanner.h:96
void Add(E element)
Definition: utils.h:1059
bool ScanRegExpPattern(bool seen_equal)
Definition: scanner.cc:1022
Handle< String > AllocateInternalizedString(Isolate *isolate)
Definition: scanner.cc:1131
#define ARRAY_SIZE(a)
Definition: globals.h:333
Definition: v8.h:124
virtual bool HasError()
Definition: parser.cc:4574
static bool Initialize()
Definition: api.cc:4967
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1437
static const int kNoPreviousCharacter
Definition: unicode.h:120
void RunParserSyncTest(const char *context_data[][2], const char *statement_data[], ParserSyncTestResult result, const ParserFlag *flags=NULL, int flags_len=0)
static v8::Isolate * isolate()
Definition: cctest.h:96
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417