v8  3.11.10(node0.8.26)
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 "parser.h"
39 #include "preparser.h"
41 #include "token.h"
42 #include "utils.h"
43 
44 TEST(ScanKeywords) {
45  struct KeywordToken {
46  const char* keyword;
47  i::Token::Value token;
48  };
49 
50  static const KeywordToken keywords[] = {
51 #define KEYWORD(t, s, d) { s, i::Token::t },
53 #undef KEYWORD
54  { NULL, i::Token::IDENTIFIER }
55  };
56 
57  KeywordToken key_token;
58  i::UnicodeCache unicode_cache;
59  i::byte buffer[32];
60  for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
61  const i::byte* keyword =
62  reinterpret_cast<const i::byte*>(key_token.keyword);
63  int length = i::StrLength(key_token.keyword);
64  CHECK(static_cast<int>(sizeof(buffer)) >= length);
65  {
66  i::Utf8ToUtf16CharacterStream stream(keyword, length);
67  i::Scanner scanner(&unicode_cache);
68  // The scanner should parse Harmony keywords for this test.
69  scanner.SetHarmonyScoping(true);
70  scanner.SetHarmonyModules(true);
71  scanner.Initialize(&stream);
72  CHECK_EQ(key_token.token, scanner.Next());
73  CHECK_EQ(i::Token::EOS, scanner.Next());
74  }
75  // Removing characters will make keyword matching fail.
76  {
77  i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
78  i::Scanner scanner(&unicode_cache);
79  scanner.Initialize(&stream);
80  CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
81  CHECK_EQ(i::Token::EOS, scanner.Next());
82  }
83  // Adding characters will make keyword matching fail.
84  static const char chars_to_append[] = { 'z', '0', '_' };
85  for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
86  memmove(buffer, keyword, length);
87  buffer[length] = chars_to_append[j];
88  i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
89  i::Scanner scanner(&unicode_cache);
90  scanner.Initialize(&stream);
91  CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
92  CHECK_EQ(i::Token::EOS, scanner.Next());
93  }
94  // Replacing characters will make keyword matching fail.
95  {
96  memmove(buffer, keyword, length);
97  buffer[length - 1] = '_';
98  i::Utf8ToUtf16CharacterStream stream(buffer, length);
99  i::Scanner scanner(&unicode_cache);
100  scanner.Initialize(&stream);
101  CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
102  CHECK_EQ(i::Token::EOS, scanner.Next());
103  }
104  }
105 }
106 
107 
108 TEST(ScanHTMLEndComments) {
110 
111  // Regression test. See:
112  // http://code.google.com/p/chromium/issues/detail?id=53548
113  // Tests that --> is correctly interpreted as comment-to-end-of-line if there
114  // is only whitespace before it on the line (with comments considered as
115  // whitespace, even a multiline-comment containing a newline).
116  // This was not the case if it occurred before the first real token
117  // in the input.
118  const char* tests[] = {
119  // Before first real token.
120  "--> is eol-comment\nvar y = 37;\n",
121  "\n --> is eol-comment\nvar y = 37;\n",
122  "/* precomment */ --> is eol-comment\nvar y = 37;\n",
123  "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
124  // After first real token.
125  "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
126  "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
127  NULL
128  };
129 
130  const char* fail_tests[] = {
131  "x --> is eol-comment\nvar y = 37;\n",
132  "\"\\n\" --> is eol-comment\nvar y = 37;\n",
133  "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
134  "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
135  "var x = 42; --> is eol-comment\nvar y = 37;\n",
136  "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
137  NULL
138  };
139 
140  // Parser/Scanner needs a stack limit.
141  int marker;
142  i::Isolate::Current()->stack_guard()->SetStackLimit(
143  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
144 
145  for (int i = 0; tests[i]; i++) {
146  v8::ScriptData* data =
147  v8::ScriptData::PreCompile(tests[i], i::StrLength(tests[i]));
148  CHECK(data != NULL && !data->HasError());
149  delete data;
150  }
151 
152  for (int i = 0; fail_tests[i]; i++) {
153  v8::ScriptData* data =
154  v8::ScriptData::PreCompile(fail_tests[i], i::StrLength(fail_tests[i]));
155  CHECK(data == NULL || data->HasError());
156  delete data;
157  }
158 }
159 
160 
162  public:
163  ScriptResource(const char* data, size_t length)
164  : data_(data), length_(length) { }
165 
166  const char* data() const { return data_; }
167  size_t length() const { return length_; }
168 
169  private:
170  const char* data_;
171  size_t length_;
172 };
173 
174 
175 TEST(Preparsing) {
176  v8::HandleScope handles;
178  v8::Context::Scope context_scope(context);
179  int marker;
180  i::Isolate::Current()->stack_guard()->SetStackLimit(
181  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
182 
183  // Source containing functions that might be lazily compiled and all types
184  // of symbols (string, propertyName, regexp).
185  const char* source =
186  "var x = 42;"
187  "function foo(a) { return function nolazy(b) { return a + b; } }"
188  "function bar(a) { if (a) return function lazy(b) { return b; } }"
189  "var z = {'string': 'string literal', bareword: 'propertyName', "
190  " 42: 'number literal', for: 'keyword as propertyName', "
191  " f\\u006fr: 'keyword propertyname with escape'};"
192  "var v = /RegExp Literal/;"
193  "var w = /RegExp Literal\\u0020With Escape/gin;"
194  "var y = { get getter() { return 42; }, "
195  " set setter(v) { this.value = v; }};";
196  int source_length = i::StrLength(source);
197  const char* error_source = "var x = y z;";
198  int error_source_length = i::StrLength(error_source);
199 
200  v8::ScriptData* preparse =
201  v8::ScriptData::PreCompile(source, source_length);
202  CHECK(!preparse->HasError());
203  bool lazy_flag = i::FLAG_lazy;
204  {
205  i::FLAG_lazy = true;
206  ScriptResource* resource = new ScriptResource(source, source_length);
207  v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
208  v8::Script::Compile(script_source, NULL, preparse);
209  }
210 
211  {
212  i::FLAG_lazy = false;
213 
214  ScriptResource* resource = new ScriptResource(source, source_length);
215  v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
216  v8::Script::New(script_source, NULL, preparse, v8::Local<v8::String>());
217  }
218  delete preparse;
219  i::FLAG_lazy = lazy_flag;
220 
221  // Syntax error.
222  v8::ScriptData* error_preparse =
223  v8::ScriptData::PreCompile(error_source, error_source_length);
224  CHECK(error_preparse->HasError());
225  i::ScriptDataImpl *pre_impl =
226  reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
227  i::Scanner::Location error_location =
228  pre_impl->MessageLocation();
229  // Error is at "z" in source, location 10..11.
230  CHECK_EQ(10, error_location.beg_pos);
231  CHECK_EQ(11, error_location.end_pos);
232  // Should not crash.
233  const char* message = pre_impl->BuildMessage();
234  pre_impl->BuildArgs();
235  CHECK_GT(strlen(message), 0);
236 }
237 
238 
239 TEST(StandAlonePreParser) {
241 
242  int marker;
243  i::Isolate::Current()->stack_guard()->SetStackLimit(
244  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
245 
246  const char* programs[] = {
247  "{label: 42}",
248  "var x = 42;",
249  "function foo(x, y) { return x + y; }",
250  "%ArgleBargle(glop);",
251  "var x = new new Function('this.x = 42');",
252  NULL
253  };
254 
255  uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
256  for (int i = 0; programs[i]; i++) {
257  const char* program = programs[i];
259  reinterpret_cast<const i::byte*>(program),
260  static_cast<unsigned>(strlen(program)));
262  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
263  scanner.Initialize(&stream);
264 
268  &log,
269  flags,
270  stack_limit);
272  i::ScriptDataImpl data(log.ExtractData());
273  CHECK(!data.has_error());
274  }
275 }
276 
277 
278 TEST(StandAlonePreParserNoNatives) {
280 
281  int marker;
282  i::Isolate::Current()->stack_guard()->SetStackLimit(
283  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
284 
285  const char* programs[] = {
286  "%ArgleBargle(glop);",
287  "var x = %_IsSmi(42);",
288  NULL
289  };
290 
291  uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
292  for (int i = 0; programs[i]; i++) {
293  const char* program = programs[i];
295  reinterpret_cast<const i::byte*>(program),
296  static_cast<unsigned>(strlen(program)));
298  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
299  scanner.Initialize(&stream);
300 
301  // Flags don't allow natives syntax.
304  &log,
306  stack_limit);
308  i::ScriptDataImpl data(log.ExtractData());
309  // Data contains syntax error.
310  CHECK(data.has_error());
311  }
312 }
313 
314 
315 TEST(RegressChromium62639) {
317 
318  int marker;
319  i::Isolate::Current()->stack_guard()->SetStackLimit(
320  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
321 
322  const char* program = "var x = 'something';\n"
323  "escape: function() {}";
324  // Fails parsing expecting an identifier after "function".
325  // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
326  // and then used the invalid currently scanned literal. This always
327  // failed in debug mode, and sometimes crashed in release mode.
328 
330  reinterpret_cast<const i::byte*>(program),
331  static_cast<unsigned>(strlen(program)));
332  i::ScriptDataImpl* data =
333  i::ParserApi::PreParse(&stream, NULL, false);
334  CHECK(data->HasError());
335  delete data;
336 }
337 
338 
339 TEST(Regress928) {
341 
342  // Preparsing didn't consider the catch clause of a try statement
343  // as with-content, which made it assume that a function inside
344  // the block could be lazily compiled, and an extra, unexpected,
345  // entry was added to the data.
346  int marker;
347  i::Isolate::Current()->stack_guard()->SetStackLimit(
348  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
349 
350  const char* program =
351  "try { } catch (e) { var foo = function () { /* first */ } }"
352  "var bar = function () { /* second */ }";
353 
354  v8::HandleScope handles;
355  i::Handle<i::String> source(
356  FACTORY->NewStringFromAscii(i::CStrVector(program)));
357  i::ScriptDataImpl* data = i::ParserApi::PartialPreParse(source, NULL, false);
358  CHECK(!data->HasError());
359 
360  data->Initialize();
361 
362  int first_function =
363  static_cast<int>(strstr(program, "function") - program);
364  int first_lbrace = first_function + i::StrLength("function () ");
365  CHECK_EQ('{', program[first_lbrace]);
366  i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace);
367  CHECK(!entry1.is_valid());
368 
369  int second_function =
370  static_cast<int>(strstr(program + first_lbrace, "function") - program);
371  int second_lbrace =
372  second_function + i::StrLength("function () ");
373  CHECK_EQ('{', program[second_lbrace]);
374  i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace);
375  CHECK(entry2.is_valid());
376  CHECK_EQ('}', program[entry2.end_pos() - 1]);
377  delete data;
378 }
379 
380 
381 TEST(PreParseOverflow) {
383 
384  int marker;
385  i::Isolate::Current()->stack_guard()->SetStackLimit(
386  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
387 
388  size_t kProgramSize = 1024 * 1024;
390  reinterpret_cast<char*>(malloc(kProgramSize + 1)));
391  memset(*program, '(', kProgramSize);
392  program[kProgramSize] = '\0';
393 
394  uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
395 
397  reinterpret_cast<const i::byte*>(*program),
398  static_cast<unsigned>(kProgramSize));
400  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
401  scanner.Initialize(&stream);
402 
403 
406  &log,
407  true,
408  stack_limit);
410 }
411 
412 
414  public:
416  : data_(data), length_(static_cast<size_t>(length)) { }
417 
419 
420  const uint16_t* data() const {
421  return data_;
422  }
423 
424  size_t length() const {
425  return length_;
426  }
427  private:
428  uint16_t* data_;
429  size_t length_;
430 };
431 
432 
433 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
434 
435 void TestCharacterStream(const char* ascii_source,
436  unsigned length,
437  unsigned start = 0,
438  unsigned end = 0) {
439  if (end == 0) end = length;
440  unsigned sub_length = end - start;
441  i::HandleScope test_scope;
442  i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
443  for (unsigned i = 0; i < length; i++) {
444  uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
445  }
446  i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
447  i::Handle<i::String> ascii_string(
448  FACTORY->NewStringFromAscii(ascii_vector));
449  TestExternalResource resource(*uc16_buffer, length);
450  i::Handle<i::String> uc16_string(
451  FACTORY->NewExternalStringFromTwoByte(&resource));
452 
454  i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
455  i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end);
456  i::Utf8ToUtf16CharacterStream utf8_stream(
457  reinterpret_cast<const i::byte*>(ascii_source), end);
458  utf8_stream.SeekForward(start);
459 
460  unsigned i = start;
461  while (i < end) {
462  // Read streams one char at a time
463  CHECK_EQU(i, uc16_stream.pos());
464  CHECK_EQU(i, string_stream.pos());
465  CHECK_EQU(i, utf8_stream.pos());
466  int32_t c0 = ascii_source[i];
467  int32_t c1 = uc16_stream.Advance();
468  int32_t c2 = string_stream.Advance();
469  int32_t c3 = utf8_stream.Advance();
470  i++;
471  CHECK_EQ(c0, c1);
472  CHECK_EQ(c0, c2);
473  CHECK_EQ(c0, c3);
474  CHECK_EQU(i, uc16_stream.pos());
475  CHECK_EQU(i, string_stream.pos());
476  CHECK_EQU(i, utf8_stream.pos());
477  }
478  while (i > start + sub_length / 4) {
479  // Pushback, re-read, pushback again.
480  int32_t c0 = ascii_source[i - 1];
481  CHECK_EQU(i, uc16_stream.pos());
482  CHECK_EQU(i, string_stream.pos());
483  CHECK_EQU(i, utf8_stream.pos());
484  uc16_stream.PushBack(c0);
485  string_stream.PushBack(c0);
486  utf8_stream.PushBack(c0);
487  i--;
488  CHECK_EQU(i, uc16_stream.pos());
489  CHECK_EQU(i, string_stream.pos());
490  CHECK_EQU(i, utf8_stream.pos());
491  int32_t c1 = uc16_stream.Advance();
492  int32_t c2 = string_stream.Advance();
493  int32_t c3 = utf8_stream.Advance();
494  i++;
495  CHECK_EQU(i, uc16_stream.pos());
496  CHECK_EQU(i, string_stream.pos());
497  CHECK_EQU(i, utf8_stream.pos());
498  CHECK_EQ(c0, c1);
499  CHECK_EQ(c0, c2);
500  CHECK_EQ(c0, c3);
501  uc16_stream.PushBack(c0);
502  string_stream.PushBack(c0);
503  utf8_stream.PushBack(c0);
504  i--;
505  CHECK_EQU(i, uc16_stream.pos());
506  CHECK_EQU(i, string_stream.pos());
507  CHECK_EQU(i, utf8_stream.pos());
508  }
509  unsigned halfway = start + sub_length / 2;
510  uc16_stream.SeekForward(halfway - i);
511  string_stream.SeekForward(halfway - i);
512  utf8_stream.SeekForward(halfway - i);
513  i = halfway;
514  CHECK_EQU(i, uc16_stream.pos());
515  CHECK_EQU(i, string_stream.pos());
516  CHECK_EQU(i, utf8_stream.pos());
517 
518  while (i < end) {
519  // Read streams one char at a time
520  CHECK_EQU(i, uc16_stream.pos());
521  CHECK_EQU(i, string_stream.pos());
522  CHECK_EQU(i, utf8_stream.pos());
523  int32_t c0 = ascii_source[i];
524  int32_t c1 = uc16_stream.Advance();
525  int32_t c2 = string_stream.Advance();
526  int32_t c3 = utf8_stream.Advance();
527  i++;
528  CHECK_EQ(c0, c1);
529  CHECK_EQ(c0, c2);
530  CHECK_EQ(c0, c3);
531  CHECK_EQU(i, uc16_stream.pos());
532  CHECK_EQU(i, string_stream.pos());
533  CHECK_EQU(i, utf8_stream.pos());
534  }
535 
536  int32_t c1 = uc16_stream.Advance();
537  int32_t c2 = string_stream.Advance();
538  int32_t c3 = utf8_stream.Advance();
539  CHECK_LT(c1, 0);
540  CHECK_LT(c2, 0);
541  CHECK_LT(c3, 0);
542 }
543 
544 
545 TEST(CharacterStreams) {
546  v8::HandleScope handles;
548  v8::Context::Scope context_scope(context);
549 
550  TestCharacterStream("abc\0\n\r\x7f", 7);
551  static const unsigned kBigStringSize = 4096;
552  char buffer[kBigStringSize + 1];
553  for (unsigned i = 0; i < kBigStringSize; i++) {
554  buffer[i] = static_cast<char>(i & 0x7f);
555  }
556  TestCharacterStream(buffer, kBigStringSize);
557 
558  TestCharacterStream(buffer, kBigStringSize, 576, 3298);
559 
560  TestCharacterStream("\0", 1);
561  TestCharacterStream("", 0);
562 }
563 
564 
565 TEST(Utf8CharacterStream) {
566  static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
567  static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
568 
569  static const int kAllUtf8CharsSize =
573  static const unsigned kAllUtf8CharsSizeU =
574  static_cast<unsigned>(kAllUtf8CharsSize);
575 
576  char buffer[kAllUtf8CharsSizeU];
577  unsigned cursor = 0;
578  for (int i = 0; i <= kMaxUC16Char; i++) {
579  cursor += unibrow::Utf8::Encode(buffer + cursor,
580  i,
582  }
583  ASSERT(cursor == kAllUtf8CharsSizeU);
584 
585  i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
586  kAllUtf8CharsSizeU);
587  for (int i = 0; i <= kMaxUC16Char; i++) {
588  CHECK_EQU(i, stream.pos());
589  int32_t c = stream.Advance();
590  CHECK_EQ(i, c);
591  CHECK_EQU(i + 1, stream.pos());
592  }
593  for (int i = kMaxUC16Char; i >= 0; i--) {
594  CHECK_EQU(i + 1, stream.pos());
595  stream.PushBack(i);
596  CHECK_EQU(i, stream.pos());
597  }
598  int i = 0;
599  while (stream.pos() < kMaxUC16CharU) {
600  CHECK_EQU(i, stream.pos());
601  unsigned progress = stream.SeekForward(12);
602  i += progress;
603  int32_t c = stream.Advance();
604  if (i <= kMaxUC16Char) {
605  CHECK_EQ(i, c);
606  } else {
607  CHECK_EQ(-1, c);
608  }
609  i += 1;
610  CHECK_EQU(i, stream.pos());
611  }
612 }
613 
614 #undef CHECK_EQU
615 
617  i::Token::Value* expected_tokens,
618  int skip_pos = 0, // Zero means not skipping.
619  int skip_to = 0) {
620  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
621  scanner.Initialize(stream);
622 
623  int i = 0;
624  do {
625  i::Token::Value expected = expected_tokens[i];
626  i::Token::Value actual = scanner.Next();
627  CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
628  if (scanner.location().end_pos == skip_pos) {
629  scanner.SeekForward(skip_to);
630  }
631  i++;
632  } while (expected_tokens[i] != i::Token::ILLEGAL);
633 }
634 
635 TEST(StreamScanner) {
637 
638  const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
639  i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
640  static_cast<unsigned>(strlen(str1)));
641  i::Token::Value expectations1[] = {
642  i::Token::LBRACE,
643  i::Token::IDENTIFIER,
644  i::Token::IDENTIFIER,
645  i::Token::FOR,
646  i::Token::COLON,
649  i::Token::LT,
651  i::Token::IDENTIFIER,
652  i::Token::EOS,
653  i::Token::ILLEGAL
654  };
655  TestStreamScanner(&stream1, expectations1, 0, 0);
656 
657  const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
658  i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
659  static_cast<unsigned>(strlen(str2)));
660  i::Token::Value expectations2[] = {
661  i::Token::CASE,
664  i::Token::LBRACE,
665  // Skipped part here
666  i::Token::RBRACE,
667  i::Token::DO,
668  i::Token::EOS,
669  i::Token::ILLEGAL
670  };
671  ASSERT_EQ('{', str2[19]);
672  ASSERT_EQ('}', str2[37]);
673  TestStreamScanner(&stream2, expectations2, 20, 37);
674 
675  const char* str3 = "{}}}}";
676  i::Token::Value expectations3[] = {
677  i::Token::LBRACE,
678  i::Token::RBRACE,
679  i::Token::RBRACE,
680  i::Token::RBRACE,
681  i::Token::RBRACE,
682  i::Token::EOS,
683  i::Token::ILLEGAL
684  };
685  // Skip zero-four RBRACEs.
686  for (int i = 0; i <= 4; i++) {
687  expectations3[6 - i] = i::Token::ILLEGAL;
688  expectations3[5 - i] = i::Token::EOS;
690  reinterpret_cast<const i::byte*>(str3),
691  static_cast<unsigned>(strlen(str3)));
692  TestStreamScanner(&stream3, expectations3, 1, 1 + i);
693  }
694 }
695 
696 
697 void TestScanRegExp(const char* re_source, const char* expected) {
699  reinterpret_cast<const i::byte*>(re_source),
700  static_cast<unsigned>(strlen(re_source)));
701  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
702  scanner.Initialize(&stream);
703 
704  i::Token::Value start = scanner.peek();
705  CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
706  CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
707  scanner.Next(); // Current token is now the regexp literal.
708  CHECK(scanner.is_literal_ascii());
709  i::Vector<const char> actual = scanner.literal_ascii_string();
710  for (int i = 0; i < actual.length(); i++) {
711  CHECK_NE('\0', expected[i]);
712  CHECK_EQ(expected[i], actual[i]);
713  }
714 }
715 
716 
717 TEST(RegExpScanning) {
719 
720  // RegExp token with added garbage at the end. The scanner should only
721  // scan the RegExp until the terminating slash just before "flipperwald".
722  TestScanRegExp("/b/flipperwald", "b");
723  // Incomplete escape sequences doesn't hide the terminating slash.
724  TestScanRegExp("/\\x/flipperwald", "\\x");
725  TestScanRegExp("/\\u/flipperwald", "\\u");
726  TestScanRegExp("/\\u1/flipperwald", "\\u1");
727  TestScanRegExp("/\\u12/flipperwald", "\\u12");
728  TestScanRegExp("/\\u123/flipperwald", "\\u123");
729  TestScanRegExp("/\\c/flipperwald", "\\c");
730  TestScanRegExp("/\\c//flipperwald", "\\c");
731  // Slashes inside character classes are not terminating.
732  TestScanRegExp("/[/]/flipperwald", "[/]");
733  TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
734  // Incomplete escape sequences inside a character class doesn't hide
735  // the end of the character class.
736  TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
737  TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
738  TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
739  TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
740  TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
741  TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
742  TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
743  TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
744  // Escaped ']'s wont end the character class.
745  TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
746  // Escaped slashes are not terminating.
747  TestScanRegExp("/\\//flipperwald", "\\/");
748  // Starting with '=' works too.
749  TestScanRegExp("/=/", "=");
750  TestScanRegExp("/=?/", "=?");
751 }
752 
753 
754 static int Utf8LengthHelper(const char* s) {
755  int len = i::StrLength(s);
756  int character_length = len;
757  for (int i = 0; i < len; i++) {
758  unsigned char c = s[i];
759  int input_offset = 0;
760  int output_adjust = 0;
761  if (c > 0x7f) {
762  if (c < 0xc0) continue;
763  if (c >= 0xf0) {
764  if (c >= 0xf8) {
765  // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
766  // byte.
767  continue; // Handle first UTF-8 byte.
768  }
769  if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
770  // This 4 byte sequence could have been coded as a 3 byte sequence.
771  // Record a single kBadChar for the first byte and continue.
772  continue;
773  }
774  input_offset = 3;
775  // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
776  character_length -= 2;
777  } else if (c >= 0xe0) {
778  if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
779  // This 3 byte sequence could have been coded as a 2 byte sequence.
780  // Record a single kBadChar for the first byte and continue.
781  continue;
782  }
783  input_offset = 2;
784  // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
785  output_adjust = 2;
786  } else {
787  if ((c & 0x1e) == 0) {
788  // This 2 byte sequence could have been coded as a 1 byte sequence.
789  // Record a single kBadChar for the first byte and continue.
790  continue;
791  }
792  input_offset = 1;
793  // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
794  output_adjust = 1;
795  }
796  bool bad = false;
797  for (int j = 1; j <= input_offset; j++) {
798  if ((s[i + j] & 0xc0) != 0x80) {
799  // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
800  // which is a single UTF-16 code unit.
801  bad = true;
802  break;
803  }
804  }
805  if (!bad) {
806  i += input_offset;
807  character_length -= output_adjust;
808  }
809  }
810  }
811  return character_length;
812 }
813 
814 
815 TEST(ScopePositions) {
816  // Test the parser for correctly setting the start and end positions
817  // of a scope. We check the scope positions of exactly one scope
818  // nested in the global scope of a program. 'inner source' is the
819  // source code that determines the part of the source belonging
820  // to the nested scope. 'outer_prefix' and 'outer_suffix' are
821  // parts of the source that belong to the global scope.
822  struct SourceData {
823  const char* outer_prefix;
824  const char* inner_source;
825  const char* outer_suffix;
826  i::ScopeType scope_type;
827  i::LanguageMode language_mode;
828  };
829 
830  const SourceData source_data[] = {
831  { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
832  { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::CLASSIC_MODE },
833  { " with ({}) ", "{\n"
834  " block;\n"
835  " }", "\n"
836  " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
837  { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
838  { " with ({}) ", "statement", "\n"
839  " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
840  { " with ({})\n"
841  " ", "statement;", "\n"
842  " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
843  { " try {} catch ", "(e) { block; }", " more;",
845  { " try {} catch ", "(e) { block; }", "; more;",
847  { " try {} catch ", "(e) {\n"
848  " block;\n"
849  " }", "\n"
850  " more;", i::CATCH_SCOPE, i::CLASSIC_MODE },
851  { " try {} catch ", "(e) { block; }", " finally { block; } more;",
853  { " start;\n"
854  " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
855  { " start;\n"
856  " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
857  { " start;\n"
858  " ", "{\n"
859  " let block;\n"
860  " }", "\n"
861  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
862  { " start;\n"
863  " function fun", "(a,b) { infunction; }", " more;",
865  { " start;\n"
866  " function fun", "(a,b) {\n"
867  " infunction;\n"
868  " }", "\n"
869  " more;", i::FUNCTION_SCOPE, i::CLASSIC_MODE },
870  { " (function fun", "(a,b) { infunction; }", ")();",
872  { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
874  { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
876  { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
877  " block;\n"
878  " }", "\n"
879  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
880  { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
882  { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
883  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
884  { " for ", "(let x = 1 ; x < 10; ++ x)\n"
885  " statement;", "\n"
886  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
887  { " for ", "(let x in {}) { block; }", " more;",
889  { " for ", "(let x in {}) { block; }", "; more;",
891  { " for ", "(let x in {}) {\n"
892  " block;\n"
893  " }", "\n"
894  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
895  { " for ", "(let x in {}) statement;", " more;",
897  { " for ", "(let x in {}) statement", "\n"
898  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
899  { " for ", "(let x in {})\n"
900  " statement;", "\n"
901  " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
902  // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
903  // the preparser off in terms of byte offsets.
904  // 6 byte encoding.
905  { " 'foo\355\240\201\355\260\211';\n"
906  " (function fun", "(a,b) { infunction; }", ")();",
908  // 4 byte encoding.
909  { " 'foo\360\220\220\212';\n"
910  " (function fun", "(a,b) { infunction; }", ")();",
912  // 3 byte encoding of \u0fff.
913  { " 'foo\340\277\277';\n"
914  " (function fun", "(a,b) { infunction; }", ")();",
916  // Broken 6 byte encoding with missing last byte.
917  { " 'foo\355\240\201\355\211';\n"
918  " (function fun", "(a,b) { infunction; }", ")();",
920  // Broken 3 byte encoding of \u0fff with missing last byte.
921  { " 'foo\340\277';\n"
922  " (function fun", "(a,b) { infunction; }", ")();",
924  // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
925  { " 'foo\340';\n"
926  " (function fun", "(a,b) { infunction; }", ")();",
928  // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
929  { " 'foo\340\203\277';\n"
930  " (function fun", "(a,b) { infunction; }", ")();",
932  // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
933  { " 'foo\340\201\277';\n"
934  " (function fun", "(a,b) { infunction; }", ")();",
936  // Unpaired lead surrogate.
937  { " 'foo\355\240\201';\n"
938  " (function fun", "(a,b) { infunction; }", ")();",
940  // Unpaired lead surrogate where following code point is a 3 byte sequence.
941  { " 'foo\355\240\201\340\277\277';\n"
942  " (function fun", "(a,b) { infunction; }", ")();",
944  // Unpaired lead surrogate where following code point is a 4 byte encoding
945  // of a trail surrogate.
946  { " 'foo\355\240\201\360\215\260\211';\n"
947  " (function fun", "(a,b) { infunction; }", ")();",
949  // Unpaired trail surrogate.
950  { " 'foo\355\260\211';\n"
951  " (function fun", "(a,b) { infunction; }", ")();",
953  // 2 byte encoding of \u00ff.
954  { " 'foo\303\277';\n"
955  " (function fun", "(a,b) { infunction; }", ")();",
957  // Broken 2 byte encoding of \u00ff with missing last byte.
958  { " 'foo\303';\n"
959  " (function fun", "(a,b) { infunction; }", ")();",
961  // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
962  { " 'foo\301\277';\n"
963  " (function fun", "(a,b) { infunction; }", ")();",
965  // Illegal 5 byte encoding.
966  { " 'foo\370\277\277\277\277';\n"
967  " (function fun", "(a,b) { infunction; }", ")();",
969  // Illegal 6 byte encoding.
970  { " 'foo\374\277\277\277\277\277';\n"
971  " (function fun", "(a,b) { infunction; }", ")();",
973  // Illegal 0xfe byte
974  { " 'foo\376\277\277\277\277\277\277';\n"
975  " (function fun", "(a,b) { infunction; }", ")();",
977  // Illegal 0xff byte
978  { " 'foo\377\277\277\277\277\277\277\277';\n"
979  " (function fun", "(a,b) { infunction; }", ")();",
981  { " 'foo';\n"
982  " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
984  { " 'foo';\n"
985  " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
988  };
989 
990  v8::HandleScope handles;
992  v8::Context::Scope context_scope(context);
993 
994  int marker;
995  i::Isolate::Current()->stack_guard()->SetStackLimit(
996  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
997  i::FLAG_harmony_scoping = true;
998 
999  for (int i = 0; source_data[i].outer_prefix; i++) {
1000  int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1001  int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1002  int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1003  int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1004  int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1005  int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1006  int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1007  int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1008  i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1);
1009  i::OS::SNPrintF(program, "%s%s%s",
1010  source_data[i].outer_prefix,
1011  source_data[i].inner_source,
1012  source_data[i].outer_suffix);
1013 
1014  // Parse program source.
1015  i::Handle<i::String> source(
1016  FACTORY->NewStringFromUtf8(i::CStrVector(program.start())));
1017  CHECK_EQ(source->length(), kProgramSize);
1018  i::Handle<i::Script> script = FACTORY->NewScript(source);
1019  i::Parser parser(script, i::kAllowLazy | i::EXTENDED_MODE, NULL, NULL,
1020  i::Isolate::Current()->zone());
1021  i::CompilationInfo info(script);
1022  info.MarkAsGlobal();
1023  info.SetLanguageMode(source_data[i].language_mode);
1024  i::FunctionLiteral* function = parser.ParseProgram(&info);
1025  CHECK(function != NULL);
1026 
1027  // Check scope types and positions.
1028  i::Scope* scope = function->scope();
1029  CHECK(scope->is_global_scope());
1030  CHECK_EQ(scope->start_position(), 0);
1031  CHECK_EQ(scope->end_position(), kProgramSize);
1032  CHECK_EQ(scope->inner_scopes()->length(), 1);
1033 
1034  i::Scope* inner_scope = scope->inner_scopes()->at(0);
1035  CHECK_EQ(inner_scope->type(), source_data[i].scope_type);
1036  CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1037  // The end position of a token is one position after the last
1038  // character belonging to that token.
1039  CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1040  }
1041 }
1042 
1043 
1045  uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
1046  bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE);
1047 
1048  // Preparse the data.
1050  i::Scanner scanner(i::Isolate::Current()->unicode_cache());
1051  i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1052  scanner.SetHarmonyScoping(harmony_scoping);
1053  scanner.Initialize(&stream);
1056  &scanner, &log, flags, stack_limit);
1058  i::ScriptDataImpl data(log.ExtractData());
1059 
1060  // Parse the data
1061  i::Handle<i::Script> script = FACTORY->NewScript(source);
1062  bool save_harmony_scoping = i::FLAG_harmony_scoping;
1063  i::FLAG_harmony_scoping = harmony_scoping;
1064  i::Parser parser(script, flags, NULL, NULL, i::Isolate::Current()->zone());
1065  i::CompilationInfo info(script);
1066  info.MarkAsGlobal();
1067  i::FunctionLiteral* function = parser.ParseProgram(&info);
1068  i::FLAG_harmony_scoping = save_harmony_scoping;
1069 
1070  i::String* type_string = NULL;
1071  if (function == NULL) {
1072  // Extract exception from the parser.
1073  i::Handle<i::String> type_symbol = FACTORY->LookupAsciiSymbol("type");
1074  CHECK(i::Isolate::Current()->has_pending_exception());
1075  i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception();
1076  i::JSObject* exception = NULL;
1077  CHECK(maybe_object->To(&exception));
1078 
1079  // Get the type string.
1080  maybe_object = exception->GetProperty(*type_symbol);
1081  CHECK(maybe_object->To(&type_string));
1082  }
1083 
1084  // Check that preparsing fails iff parsing fails.
1085  if (data.has_error() && function != NULL) {
1086  i::OS::Print(
1087  "Preparser failed on:\n"
1088  "\t%s\n"
1089  "with error:\n"
1090  "\t%s\n"
1091  "However, the parser succeeded",
1092  *source->ToCString(), data.BuildMessage());
1093  CHECK(false);
1094  } else if (!data.has_error() && function == NULL) {
1095  i::OS::Print(
1096  "Parser failed on:\n"
1097  "\t%s\n"
1098  "with error:\n"
1099  "\t%s\n"
1100  "However, the preparser succeeded",
1101  *source->ToCString(), *type_string->ToCString());
1102  CHECK(false);
1103  }
1104 
1105  // Check that preparser and parser produce the same error.
1106  if (function == NULL) {
1107  if (!type_string->IsEqualTo(i::CStrVector(data.BuildMessage()))) {
1108  i::OS::Print(
1109  "Expected parser and preparser to produce the same error on:\n"
1110  "\t%s\n"
1111  "However, found the following error messages\n"
1112  "\tparser: %s\n"
1113  "\tpreparser: %s\n",
1114  *source->ToCString(), *type_string->ToCString(), data.BuildMessage());
1115  CHECK(false);
1116  }
1117  }
1118 }
1119 
1120 
1122  static const int kFlagsCount = 6;
1123  const int flags[kFlagsCount] = {
1130  };
1131 
1132  for (int k = 0; k < kFlagsCount; ++k) {
1133  TestParserSync(source, flags[k]);
1134  }
1135 }
1136 
1137 
1138 TEST(ParserSync) {
1139  const char* context_data[][2] = {
1140  { "", "" },
1141  { "{", "}" },
1142  { "if (true) ", " else {}" },
1143  { "if (true) {} else ", "" },
1144  { "if (true) ", "" },
1145  { "do ", " while (false)" },
1146  { "while (false) ", "" },
1147  { "for (;;) ", "" },
1148  { "with ({})", "" },
1149  { "switch (12) { case 12: ", "}" },
1150  { "switch (12) { default: ", "}" },
1151  { "label2: ", "" },
1152  { NULL, NULL }
1153  };
1154 
1155  const char* statement_data[] = {
1156  "{}",
1157  "var x",
1158  "var x = 1",
1159  "const x",
1160  "const x = 1",
1161  ";",
1162  "12",
1163  "if (false) {} else ;",
1164  "if (false) {} else {}",
1165  "if (false) {} else 12",
1166  "if (false) ;"
1167  "if (false) {}",
1168  "if (false) 12",
1169  "do {} while (false)",
1170  "for (;;) ;",
1171  "for (;;) {}",
1172  "for (;;) 12",
1173  "continue",
1174  "continue label",
1175  "continue\nlabel",
1176  "break",
1177  "break label",
1178  "break\nlabel",
1179  "return",
1180  "return 12",
1181  "return\n12",
1182  "with ({}) ;",
1183  "with ({}) {}",
1184  "with ({}) 12",
1185  "switch ({}) { default: }"
1186  "label3: "
1187  "throw",
1188  "throw 12",
1189  "throw\n12",
1190  "try {} catch(e) {}",
1191  "try {} finally {}",
1192  "try {} catch(e) {} finally {}",
1193  "debugger",
1194  NULL
1195  };
1196 
1197  const char* termination_data[] = {
1198  "",
1199  ";",
1200  "\n",
1201  ";\n",
1202  "\n;",
1203  NULL
1204  };
1205 
1206  v8::HandleScope handles;
1208  v8::Context::Scope context_scope(context);
1209 
1210  int marker;
1211  i::Isolate::Current()->stack_guard()->SetStackLimit(
1212  reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1213 
1214  for (int i = 0; context_data[i][0] != NULL; ++i) {
1215  for (int j = 0; statement_data[j] != NULL; ++j) {
1216  for (int k = 0; termination_data[k] != NULL; ++k) {
1217  int kPrefixLen = i::StrLength(context_data[i][0]);
1218  int kStatementLen = i::StrLength(statement_data[j]);
1219  int kTerminationLen = i::StrLength(termination_data[k]);
1220  int kSuffixLen = i::StrLength(context_data[i][1]);
1221  int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1222  + kSuffixLen + i::StrLength("label: for (;;) { }");
1223 
1224  // Plug the source code pieces together.
1225  i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1);
1226  int length = i::OS::SNPrintF(program,
1227  "label: for (;;) { %s%s%s%s }",
1228  context_data[i][0],
1229  statement_data[j],
1230  termination_data[k],
1231  context_data[i][1]);
1232  CHECK(length == kProgramSize);
1233  i::Handle<i::String> source =
1234  FACTORY->NewStringFromAscii(i::CStrVector(program.start()));
1235  TestParserSyncWithFlags(source);
1236  }
1237  }
1238  }
1239 }
bool is_global_scope() const
Definition: scopes.h:278
static ScriptDataImpl * PartialPreParse(Handle< String > source, v8::Extension *extension, int flags)
Definition: parser.cc:5969
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1560
static ScriptDataImpl * PreParse(Utf16CharacterStream *source, v8::Extension *extension, int flags)
Definition: parser.cc:5992
const char * data() const
#define CHECK_EQ(expected, value)
Definition: checks.h:219
TestExternalResource(uint16_t *data, int length)
#define CHECK_GT(a, b)
Definition: checks.h:227
static const unsigned kMaxTwoByteChar
Definition: unicode.h:165
void SetHarmonyScoping(bool scoping)
Definition: scanner.h:410
#define IGNORE_TOKEN(name, string, precedence)
Definition: token.h:49
Flag flags[]
Definition: flags.cc:1467
int int32_t
Definition: unicode.cc:47
FunctionLiteral * ParseProgram(CompilationInfo *info)
Definition: parser.cc:567
#define CHECK_LT(a, b)
Definition: checks.h:229
TEST(ScanKeywords)
Definition: test-parsing.cc:44
#define ASSERT(condition)
Definition: checks.h:270
unsigned short uint16_t
Definition: unicode.cc:46
#define CHECK(condition)
Definition: checks.h:56
void SetHarmonyModules(bool modules)
Definition: scanner.h:416
#define TOKEN_LIST(T, K)
Definition: token.h:51
void TestStreamScanner(i::Utf16CharacterStream *stream, i::Token::Value *expected_tokens, int skip_pos=0, int skip_to=0)
size_t length() const
void TestParserSyncWithFlags(i::Handle< i::String > source)
#define KEYWORD(t, s, d)
uint8_t byte
Definition: globals.h:171
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:6161
static Local< Script > New(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *pre_data=NULL, Handle< String > script_data=Handle< String >())
Definition: api.cc:1499
int start_position() const
Definition: scopes.h:262
static ScriptData * PreCompile(const char *input, int length)
Definition: api.cc:1455
T * start() const
Definition: utils.h:389
virtual bool HasError()=0
#define CHECK_EQU(v1, v2)
int Utf8LengthHelper(String *input, int from, int to, bool followed_by_surrogate, int max_recursion, bool *failure, bool *starts_with_surrogate)
Definition: handles.cc:825
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static const char * String(Value tok)
Definition: token.h:275
ZoneList< Scope * > * inner_scopes()
Definition: scopes.h:344
void SeekForward(int pos)
Definition: scanner.cc:593
bool is_literal_ascii()
Definition: scanner.h:345
int end_position() const
Definition: scopes.h:266
static Vector< T > New(int length)
Definition: utils.h:369
#define CHECK_NE(unexpected, value)
Definition: checks.h:223
void Initialize(Utf16CharacterStream *source)
Definition: scanner.cc:48
Vector< const char > CStrVector(const char *data)
Definition: utils.h:525
static unsigned Encode(char *out, uchar c, int previous)
Definition: unicode-inl.h:81
int StrLength(const char *string)
Definition: utils.h:234
static void Print(const char *format,...)
virtual Vector< unsigned > ExtractData()
static int SNPrintF(Vector< char > str, const char *format,...)
Location location() const
Definition: scanner.h:330
void TestCharacterStream(const char *ascii_source, unsigned length, unsigned start=0, unsigned end=0)
uint16_t uc16
Definition: globals.h:273
Scanner::Location MessageLocation()
Definition: parser.cc:371
size_t length() const
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:851
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
static PreParseResult PreParseProgram(i::Scanner *scanner, i::ParserRecorder *log, int flags, uintptr_t stack_limit)
Definition: preparser.h:140
Vector< const char > literal_ascii_string()
Definition: scanner.h:337
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:367
ScriptResource(const char *data, size_t length)
#define FACTORY
Definition: isolate.h:1409
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4308
Token::Value Next()
Definition: scanner.cc:224
bool IsEqualTo(Vector< const char > str)
Definition: objects.cc:7091
void TestParserSync(i::Handle< i::String > source, int flags)
static V8EXPORT Local< String > NewExternal(ExternalStringResource *resource)
Definition: api.cc:4747
unsigned SeekForward(unsigned code_unit_count)
Definition: scanner.h:110
bool ScanRegExpPattern(bool seen_equal)
Definition: scanner.cc:993
#define ARRAY_SIZE(a)
Definition: globals.h:295
Definition: v8.h:105
virtual bool HasError()
Definition: parser.cc:5891
static bool Initialize()
Definition: api.cc:4204
static const int kNoPreviousCharacter
Definition: unicode.h:132