PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/deps/v8/test/cctest/test-parsing.cc

http://github.com/joyent/node
C++ | 1330 lines | 1074 code | 132 blank | 124 comment | 76 complexity | 9b5eb223450d64e2030bbcc194d98646 MD5 | raw file
Possible License(s): 0BSD, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, ISC, Apache-2.0, MIT, AGPL-3.0
  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. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include "v8.h"
  31. #include "cctest.h"
  32. #include "compiler.h"
  33. #include "execution.h"
  34. #include "isolate.h"
  35. #include "parser.h"
  36. #include "preparser.h"
  37. #include "scanner-character-streams.h"
  38. #include "token.h"
  39. #include "utils.h"
  40. TEST(ScanKeywords) {
  41. struct KeywordToken {
  42. const char* keyword;
  43. i::Token::Value token;
  44. };
  45. static const KeywordToken keywords[] = {
  46. #define KEYWORD(t, s, d) { s, i::Token::t },
  47. TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
  48. #undef KEYWORD
  49. { NULL, i::Token::IDENTIFIER }
  50. };
  51. KeywordToken key_token;
  52. i::UnicodeCache unicode_cache;
  53. i::byte buffer[32];
  54. for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
  55. const i::byte* keyword =
  56. reinterpret_cast<const i::byte*>(key_token.keyword);
  57. int length = i::StrLength(key_token.keyword);
  58. CHECK(static_cast<int>(sizeof(buffer)) >= length);
  59. {
  60. i::Utf8ToUtf16CharacterStream stream(keyword, length);
  61. i::Scanner scanner(&unicode_cache);
  62. // The scanner should parse Harmony keywords for this test.
  63. scanner.SetHarmonyScoping(true);
  64. scanner.SetHarmonyModules(true);
  65. scanner.Initialize(&stream);
  66. CHECK_EQ(key_token.token, scanner.Next());
  67. CHECK_EQ(i::Token::EOS, scanner.Next());
  68. }
  69. // Removing characters will make keyword matching fail.
  70. {
  71. i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
  72. i::Scanner scanner(&unicode_cache);
  73. scanner.Initialize(&stream);
  74. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  75. CHECK_EQ(i::Token::EOS, scanner.Next());
  76. }
  77. // Adding characters will make keyword matching fail.
  78. static const char chars_to_append[] = { 'z', '0', '_' };
  79. for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
  80. i::OS::MemMove(buffer, keyword, length);
  81. buffer[length] = chars_to_append[j];
  82. i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
  83. i::Scanner scanner(&unicode_cache);
  84. scanner.Initialize(&stream);
  85. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  86. CHECK_EQ(i::Token::EOS, scanner.Next());
  87. }
  88. // Replacing characters will make keyword matching fail.
  89. {
  90. i::OS::MemMove(buffer, keyword, length);
  91. buffer[length - 1] = '_';
  92. i::Utf8ToUtf16CharacterStream stream(buffer, length);
  93. i::Scanner scanner(&unicode_cache);
  94. scanner.Initialize(&stream);
  95. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  96. CHECK_EQ(i::Token::EOS, scanner.Next());
  97. }
  98. }
  99. }
  100. TEST(ScanHTMLEndComments) {
  101. v8::V8::Initialize();
  102. // Regression test. See:
  103. // http://code.google.com/p/chromium/issues/detail?id=53548
  104. // Tests that --> is correctly interpreted as comment-to-end-of-line if there
  105. // is only whitespace before it on the line (with comments considered as
  106. // whitespace, even a multiline-comment containing a newline).
  107. // This was not the case if it occurred before the first real token
  108. // in the input.
  109. const char* tests[] = {
  110. // Before first real token.
  111. "--> is eol-comment\nvar y = 37;\n",
  112. "\n --> is eol-comment\nvar y = 37;\n",
  113. "/* precomment */ --> is eol-comment\nvar y = 37;\n",
  114. "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
  115. // After first real token.
  116. "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
  117. "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
  118. NULL
  119. };
  120. const char* fail_tests[] = {
  121. "x --> is eol-comment\nvar y = 37;\n",
  122. "\"\\n\" --> is eol-comment\nvar y = 37;\n",
  123. "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
  124. "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
  125. "var x = 42; --> is eol-comment\nvar y = 37;\n",
  126. "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
  127. NULL
  128. };
  129. // Parser/Scanner needs a stack limit.
  130. int marker;
  131. i::Isolate::Current()->stack_guard()->SetStackLimit(
  132. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  133. for (int i = 0; tests[i]; i++) {
  134. v8::ScriptData* data =
  135. v8::ScriptData::PreCompile(tests[i], i::StrLength(tests[i]));
  136. CHECK(data != NULL && !data->HasError());
  137. delete data;
  138. }
  139. for (int i = 0; fail_tests[i]; i++) {
  140. v8::ScriptData* data =
  141. v8::ScriptData::PreCompile(fail_tests[i], i::StrLength(fail_tests[i]));
  142. CHECK(data == NULL || data->HasError());
  143. delete data;
  144. }
  145. }
  146. class ScriptResource : public v8::String::ExternalAsciiStringResource {
  147. public:
  148. ScriptResource(const char* data, size_t length)
  149. : data_(data), length_(length) { }
  150. const char* data() const { return data_; }
  151. size_t length() const { return length_; }
  152. private:
  153. const char* data_;
  154. size_t length_;
  155. };
  156. TEST(Preparsing) {
  157. v8::Isolate* isolate = v8::Isolate::GetCurrent();
  158. v8::HandleScope handles(isolate);
  159. v8::Local<v8::Context> context = v8::Context::New(isolate);
  160. v8::Context::Scope context_scope(context);
  161. int marker;
  162. i::Isolate::Current()->stack_guard()->SetStackLimit(
  163. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  164. // Source containing functions that might be lazily compiled and all types
  165. // of symbols (string, propertyName, regexp).
  166. const char* source =
  167. "var x = 42;"
  168. "function foo(a) { return function nolazy(b) { return a + b; } }"
  169. "function bar(a) { if (a) return function lazy(b) { return b; } }"
  170. "var z = {'string': 'string literal', bareword: 'propertyName', "
  171. " 42: 'number literal', for: 'keyword as propertyName', "
  172. " f\\u006fr: 'keyword propertyname with escape'};"
  173. "var v = /RegExp Literal/;"
  174. "var w = /RegExp Literal\\u0020With Escape/gin;"
  175. "var y = { get getter() { return 42; }, "
  176. " set setter(v) { this.value = v; }};";
  177. int source_length = i::StrLength(source);
  178. const char* error_source = "var x = y z;";
  179. int error_source_length = i::StrLength(error_source);
  180. v8::ScriptData* preparse =
  181. v8::ScriptData::PreCompile(source, source_length);
  182. CHECK(!preparse->HasError());
  183. bool lazy_flag = i::FLAG_lazy;
  184. {
  185. i::FLAG_lazy = true;
  186. ScriptResource* resource = new ScriptResource(source, source_length);
  187. v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
  188. v8::Script::Compile(script_source, NULL, preparse);
  189. }
  190. {
  191. i::FLAG_lazy = false;
  192. ScriptResource* resource = new ScriptResource(source, source_length);
  193. v8::Local<v8::String> script_source = v8::String::NewExternal(resource);
  194. v8::Script::New(script_source, NULL, preparse, v8::Local<v8::String>());
  195. }
  196. delete preparse;
  197. i::FLAG_lazy = lazy_flag;
  198. // Syntax error.
  199. v8::ScriptData* error_preparse =
  200. v8::ScriptData::PreCompile(error_source, error_source_length);
  201. CHECK(error_preparse->HasError());
  202. i::ScriptDataImpl *pre_impl =
  203. reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
  204. i::Scanner::Location error_location =
  205. pre_impl->MessageLocation();
  206. // Error is at "z" in source, location 10..11.
  207. CHECK_EQ(10, error_location.beg_pos);
  208. CHECK_EQ(11, error_location.end_pos);
  209. // Should not crash.
  210. const char* message = pre_impl->BuildMessage();
  211. pre_impl->BuildArgs();
  212. CHECK_GT(strlen(message), 0);
  213. }
  214. TEST(StandAlonePreParser) {
  215. v8::V8::Initialize();
  216. int marker;
  217. i::Isolate::Current()->stack_guard()->SetStackLimit(
  218. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  219. const char* programs[] = {
  220. "{label: 42}",
  221. "var x = 42;",
  222. "function foo(x, y) { return x + y; }",
  223. "%ArgleBargle(glop);",
  224. "var x = new new Function('this.x = 42');",
  225. NULL
  226. };
  227. uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
  228. for (int i = 0; programs[i]; i++) {
  229. const char* program = programs[i];
  230. i::Utf8ToUtf16CharacterStream stream(
  231. reinterpret_cast<const i::byte*>(program),
  232. static_cast<unsigned>(strlen(program)));
  233. i::CompleteParserRecorder log;
  234. i::Scanner scanner(i::Isolate::Current()->unicode_cache());
  235. scanner.Initialize(&stream);
  236. v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
  237. preparser.set_allow_lazy(true);
  238. preparser.set_allow_natives_syntax(true);
  239. v8::preparser::PreParser::PreParseResult result =
  240. preparser.PreParseProgram();
  241. CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
  242. i::ScriptDataImpl data(log.ExtractData());
  243. CHECK(!data.has_error());
  244. }
  245. }
  246. TEST(StandAlonePreParserNoNatives) {
  247. v8::V8::Initialize();
  248. int marker;
  249. i::Isolate::Current()->stack_guard()->SetStackLimit(
  250. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  251. const char* programs[] = {
  252. "%ArgleBargle(glop);",
  253. "var x = %_IsSmi(42);",
  254. NULL
  255. };
  256. uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
  257. for (int i = 0; programs[i]; i++) {
  258. const char* program = programs[i];
  259. i::Utf8ToUtf16CharacterStream stream(
  260. reinterpret_cast<const i::byte*>(program),
  261. static_cast<unsigned>(strlen(program)));
  262. i::CompleteParserRecorder log;
  263. i::Scanner scanner(i::Isolate::Current()->unicode_cache());
  264. scanner.Initialize(&stream);
  265. // Preparser defaults to disallowing natives syntax.
  266. v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
  267. preparser.set_allow_lazy(true);
  268. v8::preparser::PreParser::PreParseResult result =
  269. preparser.PreParseProgram();
  270. CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
  271. i::ScriptDataImpl data(log.ExtractData());
  272. // Data contains syntax error.
  273. CHECK(data.has_error());
  274. }
  275. }
  276. TEST(RegressChromium62639) {
  277. v8::V8::Initialize();
  278. int marker;
  279. i::Isolate::Current()->stack_guard()->SetStackLimit(
  280. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  281. const char* program = "var x = 'something';\n"
  282. "escape: function() {}";
  283. // Fails parsing expecting an identifier after "function".
  284. // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
  285. // and then used the invalid currently scanned literal. This always
  286. // failed in debug mode, and sometimes crashed in release mode.
  287. i::Utf8ToUtf16CharacterStream stream(
  288. reinterpret_cast<const i::byte*>(program),
  289. static_cast<unsigned>(strlen(program)));
  290. i::ScriptDataImpl* data = i::PreParserApi::PreParse(&stream);
  291. CHECK(data->HasError());
  292. delete data;
  293. }
  294. TEST(Regress928) {
  295. v8::V8::Initialize();
  296. i::Isolate* isolate = i::Isolate::Current();
  297. i::Factory* factory = isolate->factory();
  298. // Preparsing didn't consider the catch clause of a try statement
  299. // as with-content, which made it assume that a function inside
  300. // the block could be lazily compiled, and an extra, unexpected,
  301. // entry was added to the data.
  302. int marker;
  303. isolate->stack_guard()->SetStackLimit(
  304. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  305. const char* program =
  306. "try { } catch (e) { var foo = function () { /* first */ } }"
  307. "var bar = function () { /* second */ }";
  308. v8::HandleScope handles(v8::Isolate::GetCurrent());
  309. i::Handle<i::String> source(
  310. factory->NewStringFromAscii(i::CStrVector(program)));
  311. i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
  312. i::ScriptDataImpl* data = i::PreParserApi::PreParse(&stream);
  313. CHECK(!data->HasError());
  314. data->Initialize();
  315. int first_function =
  316. static_cast<int>(strstr(program, "function") - program);
  317. int first_lbrace = first_function + i::StrLength("function () ");
  318. CHECK_EQ('{', program[first_lbrace]);
  319. i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace);
  320. CHECK(!entry1.is_valid());
  321. int second_function =
  322. static_cast<int>(strstr(program + first_lbrace, "function") - program);
  323. int second_lbrace =
  324. second_function + i::StrLength("function () ");
  325. CHECK_EQ('{', program[second_lbrace]);
  326. i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace);
  327. CHECK(entry2.is_valid());
  328. CHECK_EQ('}', program[entry2.end_pos() - 1]);
  329. delete data;
  330. }
  331. TEST(PreParseOverflow) {
  332. v8::V8::Initialize();
  333. int marker;
  334. i::Isolate::Current()->stack_guard()->SetStackLimit(
  335. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  336. size_t kProgramSize = 1024 * 1024;
  337. i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
  338. memset(*program, '(', kProgramSize);
  339. program[kProgramSize] = '\0';
  340. uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
  341. i::Utf8ToUtf16CharacterStream stream(
  342. reinterpret_cast<const i::byte*>(*program),
  343. static_cast<unsigned>(kProgramSize));
  344. i::CompleteParserRecorder log;
  345. i::Scanner scanner(i::Isolate::Current()->unicode_cache());
  346. scanner.Initialize(&stream);
  347. v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
  348. preparser.set_allow_lazy(true);
  349. v8::preparser::PreParser::PreParseResult result =
  350. preparser.PreParseProgram();
  351. CHECK_EQ(v8::preparser::PreParser::kPreParseStackOverflow, result);
  352. }
  353. class TestExternalResource: public v8::String::ExternalStringResource {
  354. public:
  355. explicit TestExternalResource(uint16_t* data, int length)
  356. : data_(data), length_(static_cast<size_t>(length)) { }
  357. ~TestExternalResource() { }
  358. const uint16_t* data() const {
  359. return data_;
  360. }
  361. size_t length() const {
  362. return length_;
  363. }
  364. private:
  365. uint16_t* data_;
  366. size_t length_;
  367. };
  368. #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
  369. void TestCharacterStream(const char* ascii_source,
  370. unsigned length,
  371. unsigned start = 0,
  372. unsigned end = 0) {
  373. if (end == 0) end = length;
  374. unsigned sub_length = end - start;
  375. i::Isolate* isolate = i::Isolate::Current();
  376. i::Factory* factory = isolate->factory();
  377. i::HandleScope test_scope(isolate);
  378. i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
  379. for (unsigned i = 0; i < length; i++) {
  380. uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
  381. }
  382. i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
  383. i::Handle<i::String> ascii_string(
  384. factory->NewStringFromAscii(ascii_vector));
  385. TestExternalResource resource(*uc16_buffer, length);
  386. i::Handle<i::String> uc16_string(
  387. factory->NewExternalStringFromTwoByte(&resource));
  388. i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
  389. i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
  390. i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end);
  391. i::Utf8ToUtf16CharacterStream utf8_stream(
  392. reinterpret_cast<const i::byte*>(ascii_source), end);
  393. utf8_stream.SeekForward(start);
  394. unsigned i = start;
  395. while (i < end) {
  396. // Read streams one char at a time
  397. CHECK_EQU(i, uc16_stream.pos());
  398. CHECK_EQU(i, string_stream.pos());
  399. CHECK_EQU(i, utf8_stream.pos());
  400. int32_t c0 = ascii_source[i];
  401. int32_t c1 = uc16_stream.Advance();
  402. int32_t c2 = string_stream.Advance();
  403. int32_t c3 = utf8_stream.Advance();
  404. i++;
  405. CHECK_EQ(c0, c1);
  406. CHECK_EQ(c0, c2);
  407. CHECK_EQ(c0, c3);
  408. CHECK_EQU(i, uc16_stream.pos());
  409. CHECK_EQU(i, string_stream.pos());
  410. CHECK_EQU(i, utf8_stream.pos());
  411. }
  412. while (i > start + sub_length / 4) {
  413. // Pushback, re-read, pushback again.
  414. int32_t c0 = ascii_source[i - 1];
  415. CHECK_EQU(i, uc16_stream.pos());
  416. CHECK_EQU(i, string_stream.pos());
  417. CHECK_EQU(i, utf8_stream.pos());
  418. uc16_stream.PushBack(c0);
  419. string_stream.PushBack(c0);
  420. utf8_stream.PushBack(c0);
  421. i--;
  422. CHECK_EQU(i, uc16_stream.pos());
  423. CHECK_EQU(i, string_stream.pos());
  424. CHECK_EQU(i, utf8_stream.pos());
  425. int32_t c1 = uc16_stream.Advance();
  426. int32_t c2 = string_stream.Advance();
  427. int32_t c3 = utf8_stream.Advance();
  428. i++;
  429. CHECK_EQU(i, uc16_stream.pos());
  430. CHECK_EQU(i, string_stream.pos());
  431. CHECK_EQU(i, utf8_stream.pos());
  432. CHECK_EQ(c0, c1);
  433. CHECK_EQ(c0, c2);
  434. CHECK_EQ(c0, c3);
  435. uc16_stream.PushBack(c0);
  436. string_stream.PushBack(c0);
  437. utf8_stream.PushBack(c0);
  438. i--;
  439. CHECK_EQU(i, uc16_stream.pos());
  440. CHECK_EQU(i, string_stream.pos());
  441. CHECK_EQU(i, utf8_stream.pos());
  442. }
  443. unsigned halfway = start + sub_length / 2;
  444. uc16_stream.SeekForward(halfway - i);
  445. string_stream.SeekForward(halfway - i);
  446. utf8_stream.SeekForward(halfway - i);
  447. i = halfway;
  448. CHECK_EQU(i, uc16_stream.pos());
  449. CHECK_EQU(i, string_stream.pos());
  450. CHECK_EQU(i, utf8_stream.pos());
  451. while (i < end) {
  452. // Read streams one char at a time
  453. CHECK_EQU(i, uc16_stream.pos());
  454. CHECK_EQU(i, string_stream.pos());
  455. CHECK_EQU(i, utf8_stream.pos());
  456. int32_t c0 = ascii_source[i];
  457. int32_t c1 = uc16_stream.Advance();
  458. int32_t c2 = string_stream.Advance();
  459. int32_t c3 = utf8_stream.Advance();
  460. i++;
  461. CHECK_EQ(c0, c1);
  462. CHECK_EQ(c0, c2);
  463. CHECK_EQ(c0, c3);
  464. CHECK_EQU(i, uc16_stream.pos());
  465. CHECK_EQU(i, string_stream.pos());
  466. CHECK_EQU(i, utf8_stream.pos());
  467. }
  468. int32_t c1 = uc16_stream.Advance();
  469. int32_t c2 = string_stream.Advance();
  470. int32_t c3 = utf8_stream.Advance();
  471. CHECK_LT(c1, 0);
  472. CHECK_LT(c2, 0);
  473. CHECK_LT(c3, 0);
  474. }
  475. TEST(CharacterStreams) {
  476. v8::Isolate* isolate = v8::Isolate::GetCurrent();
  477. v8::HandleScope handles(isolate);
  478. v8::Local<v8::Context> context = v8::Context::New(isolate);
  479. v8::Context::Scope context_scope(context);
  480. TestCharacterStream("abc\0\n\r\x7f", 7);
  481. static const unsigned kBigStringSize = 4096;
  482. char buffer[kBigStringSize + 1];
  483. for (unsigned i = 0; i < kBigStringSize; i++) {
  484. buffer[i] = static_cast<char>(i & 0x7f);
  485. }
  486. TestCharacterStream(buffer, kBigStringSize);
  487. TestCharacterStream(buffer, kBigStringSize, 576, 3298);
  488. TestCharacterStream("\0", 1);
  489. TestCharacterStream("", 0);
  490. }
  491. TEST(Utf8CharacterStream) {
  492. static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
  493. static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
  494. static const int kAllUtf8CharsSize =
  495. (unibrow::Utf8::kMaxOneByteChar + 1) +
  496. (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
  497. (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
  498. static const unsigned kAllUtf8CharsSizeU =
  499. static_cast<unsigned>(kAllUtf8CharsSize);
  500. char buffer[kAllUtf8CharsSizeU];
  501. unsigned cursor = 0;
  502. for (int i = 0; i <= kMaxUC16Char; i++) {
  503. cursor += unibrow::Utf8::Encode(buffer + cursor,
  504. i,
  505. unibrow::Utf16::kNoPreviousCharacter);
  506. }
  507. ASSERT(cursor == kAllUtf8CharsSizeU);
  508. i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
  509. kAllUtf8CharsSizeU);
  510. for (int i = 0; i <= kMaxUC16Char; i++) {
  511. CHECK_EQU(i, stream.pos());
  512. int32_t c = stream.Advance();
  513. CHECK_EQ(i, c);
  514. CHECK_EQU(i + 1, stream.pos());
  515. }
  516. for (int i = kMaxUC16Char; i >= 0; i--) {
  517. CHECK_EQU(i + 1, stream.pos());
  518. stream.PushBack(i);
  519. CHECK_EQU(i, stream.pos());
  520. }
  521. int i = 0;
  522. while (stream.pos() < kMaxUC16CharU) {
  523. CHECK_EQU(i, stream.pos());
  524. unsigned progress = stream.SeekForward(12);
  525. i += progress;
  526. int32_t c = stream.Advance();
  527. if (i <= kMaxUC16Char) {
  528. CHECK_EQ(i, c);
  529. } else {
  530. CHECK_EQ(-1, c);
  531. }
  532. i += 1;
  533. CHECK_EQU(i, stream.pos());
  534. }
  535. }
  536. #undef CHECK_EQU
  537. void TestStreamScanner(i::Utf16CharacterStream* stream,
  538. i::Token::Value* expected_tokens,
  539. int skip_pos = 0, // Zero means not skipping.
  540. int skip_to = 0) {
  541. i::Scanner scanner(i::Isolate::Current()->unicode_cache());
  542. scanner.Initialize(stream);
  543. int i = 0;
  544. do {
  545. i::Token::Value expected = expected_tokens[i];
  546. i::Token::Value actual = scanner.Next();
  547. CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
  548. if (scanner.location().end_pos == skip_pos) {
  549. scanner.SeekForward(skip_to);
  550. }
  551. i++;
  552. } while (expected_tokens[i] != i::Token::ILLEGAL);
  553. }
  554. TEST(StreamScanner) {
  555. v8::V8::Initialize();
  556. const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
  557. i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
  558. static_cast<unsigned>(strlen(str1)));
  559. i::Token::Value expectations1[] = {
  560. i::Token::LBRACE,
  561. i::Token::IDENTIFIER,
  562. i::Token::IDENTIFIER,
  563. i::Token::FOR,
  564. i::Token::COLON,
  565. i::Token::MUL,
  566. i::Token::DIV,
  567. i::Token::LT,
  568. i::Token::SUB,
  569. i::Token::IDENTIFIER,
  570. i::Token::EOS,
  571. i::Token::ILLEGAL
  572. };
  573. TestStreamScanner(&stream1, expectations1, 0, 0);
  574. const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
  575. i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
  576. static_cast<unsigned>(strlen(str2)));
  577. i::Token::Value expectations2[] = {
  578. i::Token::CASE,
  579. i::Token::DEFAULT,
  580. i::Token::CONST,
  581. i::Token::LBRACE,
  582. // Skipped part here
  583. i::Token::RBRACE,
  584. i::Token::DO,
  585. i::Token::EOS,
  586. i::Token::ILLEGAL
  587. };
  588. ASSERT_EQ('{', str2[19]);
  589. ASSERT_EQ('}', str2[37]);
  590. TestStreamScanner(&stream2, expectations2, 20, 37);
  591. const char* str3 = "{}}}}";
  592. i::Token::Value expectations3[] = {
  593. i::Token::LBRACE,
  594. i::Token::RBRACE,
  595. i::Token::RBRACE,
  596. i::Token::RBRACE,
  597. i::Token::RBRACE,
  598. i::Token::EOS,
  599. i::Token::ILLEGAL
  600. };
  601. // Skip zero-four RBRACEs.
  602. for (int i = 0; i <= 4; i++) {
  603. expectations3[6 - i] = i::Token::ILLEGAL;
  604. expectations3[5 - i] = i::Token::EOS;
  605. i::Utf8ToUtf16CharacterStream stream3(
  606. reinterpret_cast<const i::byte*>(str3),
  607. static_cast<unsigned>(strlen(str3)));
  608. TestStreamScanner(&stream3, expectations3, 1, 1 + i);
  609. }
  610. }
  611. void TestScanRegExp(const char* re_source, const char* expected) {
  612. i::Utf8ToUtf16CharacterStream stream(
  613. reinterpret_cast<const i::byte*>(re_source),
  614. static_cast<unsigned>(strlen(re_source)));
  615. i::Scanner scanner(i::Isolate::Current()->unicode_cache());
  616. scanner.Initialize(&stream);
  617. i::Token::Value start = scanner.peek();
  618. CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
  619. CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
  620. scanner.Next(); // Current token is now the regexp literal.
  621. CHECK(scanner.is_literal_ascii());
  622. i::Vector<const char> actual = scanner.literal_ascii_string();
  623. for (int i = 0; i < actual.length(); i++) {
  624. CHECK_NE('\0', expected[i]);
  625. CHECK_EQ(expected[i], actual[i]);
  626. }
  627. }
  628. TEST(RegExpScanning) {
  629. v8::V8::Initialize();
  630. // RegExp token with added garbage at the end. The scanner should only
  631. // scan the RegExp until the terminating slash just before "flipperwald".
  632. TestScanRegExp("/b/flipperwald", "b");
  633. // Incomplete escape sequences doesn't hide the terminating slash.
  634. TestScanRegExp("/\\x/flipperwald", "\\x");
  635. TestScanRegExp("/\\u/flipperwald", "\\u");
  636. TestScanRegExp("/\\u1/flipperwald", "\\u1");
  637. TestScanRegExp("/\\u12/flipperwald", "\\u12");
  638. TestScanRegExp("/\\u123/flipperwald", "\\u123");
  639. TestScanRegExp("/\\c/flipperwald", "\\c");
  640. TestScanRegExp("/\\c//flipperwald", "\\c");
  641. // Slashes inside character classes are not terminating.
  642. TestScanRegExp("/[/]/flipperwald", "[/]");
  643. TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
  644. // Incomplete escape sequences inside a character class doesn't hide
  645. // the end of the character class.
  646. TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
  647. TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
  648. TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
  649. TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
  650. TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
  651. TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
  652. TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
  653. TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
  654. // Escaped ']'s wont end the character class.
  655. TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
  656. // Escaped slashes are not terminating.
  657. TestScanRegExp("/\\//flipperwald", "\\/");
  658. // Starting with '=' works too.
  659. TestScanRegExp("/=/", "=");
  660. TestScanRegExp("/=?/", "=?");
  661. }
  662. static int Utf8LengthHelper(const char* s) {
  663. int len = i::StrLength(s);
  664. int character_length = len;
  665. for (int i = 0; i < len; i++) {
  666. unsigned char c = s[i];
  667. int input_offset = 0;
  668. int output_adjust = 0;
  669. if (c > 0x7f) {
  670. if (c < 0xc0) continue;
  671. if (c >= 0xf0) {
  672. if (c >= 0xf8) {
  673. // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
  674. // byte.
  675. continue; // Handle first UTF-8 byte.
  676. }
  677. if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
  678. // This 4 byte sequence could have been coded as a 3 byte sequence.
  679. // Record a single kBadChar for the first byte and continue.
  680. continue;
  681. }
  682. input_offset = 3;
  683. // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
  684. character_length -= 2;
  685. } else if (c >= 0xe0) {
  686. if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
  687. // This 3 byte sequence could have been coded as a 2 byte sequence.
  688. // Record a single kBadChar for the first byte and continue.
  689. continue;
  690. }
  691. input_offset = 2;
  692. // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
  693. output_adjust = 2;
  694. } else {
  695. if ((c & 0x1e) == 0) {
  696. // This 2 byte sequence could have been coded as a 1 byte sequence.
  697. // Record a single kBadChar for the first byte and continue.
  698. continue;
  699. }
  700. input_offset = 1;
  701. // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
  702. output_adjust = 1;
  703. }
  704. bool bad = false;
  705. for (int j = 1; j <= input_offset; j++) {
  706. if ((s[i + j] & 0xc0) != 0x80) {
  707. // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
  708. // which is a single UTF-16 code unit.
  709. bad = true;
  710. break;
  711. }
  712. }
  713. if (!bad) {
  714. i += input_offset;
  715. character_length -= output_adjust;
  716. }
  717. }
  718. }
  719. return character_length;
  720. }
  721. TEST(ScopePositions) {
  722. // Test the parser for correctly setting the start and end positions
  723. // of a scope. We check the scope positions of exactly one scope
  724. // nested in the global scope of a program. 'inner source' is the
  725. // source code that determines the part of the source belonging
  726. // to the nested scope. 'outer_prefix' and 'outer_suffix' are
  727. // parts of the source that belong to the global scope.
  728. struct SourceData {
  729. const char* outer_prefix;
  730. const char* inner_source;
  731. const char* outer_suffix;
  732. i::ScopeType scope_type;
  733. i::LanguageMode language_mode;
  734. };
  735. const SourceData source_data[] = {
  736. { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  737. { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  738. { " with ({}) ", "{\n"
  739. " block;\n"
  740. " }", "\n"
  741. " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  742. { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  743. { " with ({}) ", "statement", "\n"
  744. " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  745. { " with ({})\n"
  746. " ", "statement;", "\n"
  747. " more;", i::WITH_SCOPE, i::CLASSIC_MODE },
  748. { " try {} catch ", "(e) { block; }", " more;",
  749. i::CATCH_SCOPE, i::CLASSIC_MODE },
  750. { " try {} catch ", "(e) { block; }", "; more;",
  751. i::CATCH_SCOPE, i::CLASSIC_MODE },
  752. { " try {} catch ", "(e) {\n"
  753. " block;\n"
  754. " }", "\n"
  755. " more;", i::CATCH_SCOPE, i::CLASSIC_MODE },
  756. { " try {} catch ", "(e) { block; }", " finally { block; } more;",
  757. i::CATCH_SCOPE, i::CLASSIC_MODE },
  758. { " start;\n"
  759. " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  760. { " start;\n"
  761. " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  762. { " start;\n"
  763. " ", "{\n"
  764. " let block;\n"
  765. " }", "\n"
  766. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  767. { " start;\n"
  768. " function fun", "(a,b) { infunction; }", " more;",
  769. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  770. { " start;\n"
  771. " function fun", "(a,b) {\n"
  772. " infunction;\n"
  773. " }", "\n"
  774. " more;", i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  775. { " (function fun", "(a,b) { infunction; }", ")();",
  776. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  777. { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
  778. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  779. { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
  780. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  781. { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
  782. " block;\n"
  783. " }", "\n"
  784. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  785. { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
  786. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  787. { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
  788. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  789. { " for ", "(let x = 1 ; x < 10; ++ x)\n"
  790. " statement;", "\n"
  791. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  792. { " for ", "(let x in {}) { block; }", " more;",
  793. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  794. { " for ", "(let x in {}) { block; }", "; more;",
  795. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  796. { " for ", "(let x in {}) {\n"
  797. " block;\n"
  798. " }", "\n"
  799. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  800. { " for ", "(let x in {}) statement;", " more;",
  801. i::BLOCK_SCOPE, i::EXTENDED_MODE },
  802. { " for ", "(let x in {}) statement", "\n"
  803. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  804. { " for ", "(let x in {})\n"
  805. " statement;", "\n"
  806. " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE },
  807. // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
  808. // the preparser off in terms of byte offsets.
  809. // 6 byte encoding.
  810. { " 'foo\355\240\201\355\260\211';\n"
  811. " (function fun", "(a,b) { infunction; }", ")();",
  812. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  813. // 4 byte encoding.
  814. { " 'foo\360\220\220\212';\n"
  815. " (function fun", "(a,b) { infunction; }", ")();",
  816. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  817. // 3 byte encoding of \u0fff.
  818. { " 'foo\340\277\277';\n"
  819. " (function fun", "(a,b) { infunction; }", ")();",
  820. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  821. // Broken 6 byte encoding with missing last byte.
  822. { " 'foo\355\240\201\355\211';\n"
  823. " (function fun", "(a,b) { infunction; }", ")();",
  824. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  825. // Broken 3 byte encoding of \u0fff with missing last byte.
  826. { " 'foo\340\277';\n"
  827. " (function fun", "(a,b) { infunction; }", ")();",
  828. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  829. // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
  830. { " 'foo\340';\n"
  831. " (function fun", "(a,b) { infunction; }", ")();",
  832. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  833. // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
  834. { " 'foo\340\203\277';\n"
  835. " (function fun", "(a,b) { infunction; }", ")();",
  836. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  837. // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
  838. { " 'foo\340\201\277';\n"
  839. " (function fun", "(a,b) { infunction; }", ")();",
  840. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  841. // Unpaired lead surrogate.
  842. { " 'foo\355\240\201';\n"
  843. " (function fun", "(a,b) { infunction; }", ")();",
  844. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  845. // Unpaired lead surrogate where following code point is a 3 byte sequence.
  846. { " 'foo\355\240\201\340\277\277';\n"
  847. " (function fun", "(a,b) { infunction; }", ")();",
  848. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  849. // Unpaired lead surrogate where following code point is a 4 byte encoding
  850. // of a trail surrogate.
  851. { " 'foo\355\240\201\360\215\260\211';\n"
  852. " (function fun", "(a,b) { infunction; }", ")();",
  853. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  854. // Unpaired trail surrogate.
  855. { " 'foo\355\260\211';\n"
  856. " (function fun", "(a,b) { infunction; }", ")();",
  857. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  858. // 2 byte encoding of \u00ff.
  859. { " 'foo\303\277';\n"
  860. " (function fun", "(a,b) { infunction; }", ")();",
  861. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  862. // Broken 2 byte encoding of \u00ff with missing last byte.
  863. { " 'foo\303';\n"
  864. " (function fun", "(a,b) { infunction; }", ")();",
  865. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  866. // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
  867. { " 'foo\301\277';\n"
  868. " (function fun", "(a,b) { infunction; }", ")();",
  869. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  870. // Illegal 5 byte encoding.
  871. { " 'foo\370\277\277\277\277';\n"
  872. " (function fun", "(a,b) { infunction; }", ")();",
  873. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  874. // Illegal 6 byte encoding.
  875. { " 'foo\374\277\277\277\277\277';\n"
  876. " (function fun", "(a,b) { infunction; }", ")();",
  877. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  878. // Illegal 0xfe byte
  879. { " 'foo\376\277\277\277\277\277\277';\n"
  880. " (function fun", "(a,b) { infunction; }", ")();",
  881. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  882. // Illegal 0xff byte
  883. { " 'foo\377\277\277\277\277\277\277\277';\n"
  884. " (function fun", "(a,b) { infunction; }", ")();",
  885. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  886. { " 'foo';\n"
  887. " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
  888. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  889. { " 'foo';\n"
  890. " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
  891. i::FUNCTION_SCOPE, i::CLASSIC_MODE },
  892. { NULL, NULL, NULL, i::EVAL_SCOPE, i::CLASSIC_MODE }
  893. };
  894. i::Isolate* isolate = i::Isolate::Current();
  895. i::Factory* factory = isolate->factory();
  896. v8::HandleScope handles(v8::Isolate::GetCurrent());
  897. v8::Handle<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent());
  898. v8::Context::Scope context_scope(context);
  899. int marker;
  900. isolate->stack_guard()->SetStackLimit(
  901. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  902. for (int i = 0; source_data[i].outer_prefix; i++) {
  903. int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
  904. int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
  905. int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
  906. int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
  907. int kInnerByteLen = i::StrLength(source_data[i].inner_source);
  908. int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
  909. int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
  910. int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
  911. i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1);
  912. i::OS::SNPrintF(program, "%s%s%s",
  913. source_data[i].outer_prefix,
  914. source_data[i].inner_source,
  915. source_data[i].outer_suffix);
  916. // Parse program source.
  917. i::Handle<i::String> source(
  918. factory->NewStringFromUtf8(i::CStrVector(program.start())));
  919. CHECK_EQ(source->length(), kProgramSize);
  920. i::Handle<i::Script> script = factory->NewScript(source);
  921. i::CompilationInfoWithZone info(script);
  922. i::Parser parser(&info);
  923. parser.set_allow_lazy(true);
  924. parser.set_allow_harmony_scoping(true);
  925. info.MarkAsGlobal();
  926. info.SetLanguageMode(source_data[i].language_mode);
  927. i::FunctionLiteral* function = parser.ParseProgram();
  928. CHECK(function != NULL);
  929. // Check scope types and positions.
  930. i::Scope* scope = function->scope();
  931. CHECK(scope->is_global_scope());
  932. CHECK_EQ(scope->start_position(), 0);
  933. CHECK_EQ(scope->end_position(), kProgramSize);
  934. CHECK_EQ(scope->inner_scopes()->length(), 1);
  935. i::Scope* inner_scope = scope->inner_scopes()->at(0);
  936. CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
  937. CHECK_EQ(inner_scope->start_position(), kPrefixLen);
  938. // The end position of a token is one position after the last
  939. // character belonging to that token.
  940. CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
  941. }
  942. }
  943. i::Handle<i::String> FormatMessage(i::ScriptDataImpl* data) {
  944. i::Isolate* isolate = i::Isolate::Current();
  945. i::Factory* factory = isolate->factory();
  946. const char* message = data->BuildMessage();
  947. i::Handle<i::String> format = v8::Utils::OpenHandle(
  948. *v8::String::New(message));
  949. i::Vector<const char*> args = data->BuildArgs();
  950. i::Handle<i::JSArray> args_array = factory->NewJSArray(args.length());
  951. for (int i = 0; i < args.length(); i++) {
  952. i::JSArray::SetElement(args_array,
  953. i,
  954. v8::Utils::OpenHandle(*v8::String::New(args[i])),
  955. NONE,
  956. i::kNonStrictMode);
  957. }
  958. i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
  959. i::Handle<i::Object> format_fun =
  960. i::GetProperty(builtins, "FormatMessage");
  961. i::Handle<i::Object> arg_handles[] = { format, args_array };
  962. bool has_exception = false;
  963. i::Handle<i::Object> result =
  964. i::Execution::Call(format_fun, builtins, 2, arg_handles, &has_exception);
  965. CHECK(!has_exception);
  966. CHECK(result->IsString());
  967. for (int i = 0; i < args.length(); i++) {
  968. i::DeleteArray(args[i]);
  969. }
  970. i::DeleteArray(args.start());
  971. i::DeleteArray(message);
  972. return i::Handle<i::String>::cast(result);
  973. }
  974. enum ParserFlag {
  975. kAllowLazy,
  976. kAllowNativesSyntax,
  977. kAllowHarmonyScoping,
  978. kAllowModules,
  979. kAllowGenerators,
  980. kAllowForOf,
  981. kAllowHarmonyNumericLiterals,
  982. kParserFlagCount
  983. };
  984. static bool checkParserFlag(unsigned flags, ParserFlag flag) {
  985. return flags & (1 << flag);
  986. }
  987. #define SET_PARSER_FLAGS(parser, flags) \
  988. parser.set_allow_lazy(checkParserFlag(flags, kAllowLazy)); \
  989. parser.set_allow_natives_syntax(checkParserFlag(flags, \
  990. kAllowNativesSyntax)); \
  991. parser.set_allow_harmony_scoping(checkParserFlag(flags, \
  992. kAllowHarmonyScoping)); \
  993. parser.set_allow_modules(checkParserFlag(flags, kAllowModules)); \
  994. parser.set_allow_generators(checkParserFlag(flags, kAllowGenerators)); \
  995. parser.set_allow_for_of(checkParserFlag(flags, kAllowForOf)); \
  996. parser.set_allow_harmony_numeric_literals( \
  997. checkParserFlag(flags, kAllowHarmonyNumericLiterals));
  998. void TestParserSyncWithFlags(i::Handle<i::String> source, unsigned flags) {
  999. i::Isolate* isolate = i::Isolate::Current();
  1000. i::Factory* factory = isolate->factory();
  1001. uintptr_t stack_limit = isolate->stack_guard()->real_climit();
  1002. // Preparse the data.
  1003. i::CompleteParserRecorder log;
  1004. {
  1005. i::Scanner scanner(isolate->unicode_cache());
  1006. i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
  1007. v8::preparser::PreParser preparser(&scanner, &log, stack_limit);
  1008. SET_PARSER_FLAGS(preparser, flags);
  1009. scanner.Initialize(&stream);
  1010. v8::preparser::PreParser::PreParseResult result =
  1011. preparser.PreParseProgram();
  1012. CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
  1013. }
  1014. i::ScriptDataImpl data(log.ExtractData());
  1015. // Parse the data
  1016. i::FunctionLiteral* function;
  1017. {
  1018. i::Handle<i::Script> script = factory->NewScript(source);
  1019. i::CompilationInfoWithZone info(script);
  1020. i::Parser parser(&info);
  1021. SET_PARSER_FLAGS(parser, flags);
  1022. info.MarkAsGlobal();
  1023. function = parser.ParseProgram();
  1024. }
  1025. // Check that preparsing fails iff parsing fails.
  1026. if (function == NULL) {
  1027. // Extract exception from the parser.
  1028. CHECK(isolate->has_pending_exception());
  1029. i::MaybeObject* maybe_object = isolate->pending_exception();
  1030. i::JSObject* exception = NULL;
  1031. CHECK(maybe_object->To(&exception));
  1032. i::Handle<i::JSObject> exception_handle(exception);
  1033. i::Handle<i::String> message_string =
  1034. i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message"));
  1035. if (!data.has_error()) {
  1036. i::OS::Print(
  1037. "Parser failed on:\n"
  1038. "\t%s\n"
  1039. "with error:\n"
  1040. "\t%s\n"
  1041. "However, the preparser succeeded",
  1042. *source->ToCString(), *message_string->ToCString());
  1043. CHECK(false);
  1044. }
  1045. // Check that preparser and parser produce the same error.
  1046. i::Handle<i::String> preparser_message = FormatMessage(&data);
  1047. if (!message_string->Equals(*preparser_message)) {
  1048. i::OS::Print(
  1049. "Expected parser and preparser to produce the same error on:\n"
  1050. "\t%s\n"
  1051. "However, found the following error messages\n"
  1052. "\tparser: %s\n"
  1053. "\tpreparser: %s\n",
  1054. *source->ToCString(),
  1055. *message_string->ToCString(),
  1056. *preparser_message->ToCString());
  1057. CHECK(false);
  1058. }
  1059. } else if (data.has_error()) {
  1060. i::OS::Print(
  1061. "Preparser failed on:\n"
  1062. "\t%s\n"
  1063. "with error:\n"
  1064. "\t%s\n"
  1065. "However, the parser succeeded",
  1066. *source->ToCString(), *FormatMessage(&data)->ToCString());
  1067. CHECK(false);
  1068. }
  1069. }
  1070. void TestParserSync(i::Handle<i::String> source) {
  1071. for (unsigned flags = 0; flags < (1 << kParserFlagCount); ++flags) {
  1072. TestParserSyncWithFlags(source, flags);
  1073. }
  1074. }
  1075. TEST(ParserSync) {
  1076. const char* context_data[][2] = {
  1077. { "", "" },
  1078. { "{", "}" },
  1079. { "if (true) ", " else {}" },
  1080. { "if (true) {} else ", "" },
  1081. { "if (true) ", "" },
  1082. { "do ", " while (false)" },
  1083. { "while (false) ", "" },
  1084. { "for (;;) ", "" },
  1085. { "with ({})", "" },
  1086. { "switch (12) { case 12: ", "}" },
  1087. { "switch (12) { default: ", "}" },
  1088. { "switch (12) { ", "case 12: }" },
  1089. { "label2: ", "" },
  1090. { NULL, NULL }
  1091. };
  1092. const char* statement_data[] = {
  1093. "{}",
  1094. "var x",
  1095. "var x = 1",
  1096. "const x",
  1097. "const x = 1",
  1098. ";",
  1099. "12",
  1100. "if (false) {} else ;",
  1101. "if (false) {} else {}",
  1102. "if (false) {} else 12",
  1103. "if (false) ;"
  1104. "if (false) {}",
  1105. "if (false) 12",
  1106. "do {} while (false)",
  1107. "for (;;) ;",
  1108. "for (;;) {}",
  1109. "for (;;) 12",
  1110. "continue",
  1111. "continue label",
  1112. "continue\nlabel",
  1113. "break",
  1114. "break label",
  1115. "break\nlabel",
  1116. "return",
  1117. "return 12",
  1118. "return\n12",
  1119. "with ({}) ;",
  1120. "with ({}) {}",
  1121. "with ({}) 12",
  1122. "switch ({}) { default: }"
  1123. "label3: "
  1124. "throw",
  1125. "throw 12",
  1126. "throw\n12",
  1127. "try {} catch(e) {}",
  1128. "try {} finally {}",
  1129. "try {} catch(e) {} finally {}",
  1130. "debugger",
  1131. NULL
  1132. };
  1133. const char* termination_data[] = {
  1134. "",
  1135. ";",
  1136. "\n",
  1137. ";\n",
  1138. "\n;",
  1139. NULL
  1140. };
  1141. // TODO(mstarzinger): Disabled in GC stress mode for now, we should find the
  1142. // correct timeout for this and re-enable this test again.
  1143. if (i::FLAG_stress_compaction) return;
  1144. i::Isolate* isolate = i::Isolate::Current();
  1145. i::Factory* factory = isolate->factory();
  1146. v8::HandleScope handles(v8::Isolate::GetCurrent());
  1147. v8::Handle<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent());
  1148. v8::Context::Scope context_scope(context);
  1149. int marker;
  1150. isolate->stack_guard()->SetStackLimit(
  1151. reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
  1152. for (int i = 0; context_data[i][0] != NULL; ++i) {
  1153. for (int j = 0; statement_data[j] != NULL; ++j) {
  1154. for (int k = 0; termination_data[k] != NULL; ++k) {
  1155. int kPrefixLen = i::StrLength(context_data[i][0]);
  1156. int kStatementLen = i::StrLength(statement_data[j]);
  1157. int kTerminationLen = i::StrLength(termination_data[k]);
  1158. int kSuffixLen = i::StrLength(context_data[i][1]);
  1159. int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
  1160. + kSuffixLen + i::StrLength("label: for (;;) { }");
  1161. // Plug the source code pieces together.
  1162. i::ScopedVector<char> program(kProgramSize + 1);
  1163. int length = i::OS::SNPrintF(program,
  1164. "label: for (;;) { %s%s%s%s }",
  1165. context_data[i][0],
  1166. statement_data[j],
  1167. termination_data[k],
  1168. context_data[i][1]);
  1169. CHECK(length == kProgramSize);
  1170. i::Handle<i::String> source =
  1171. factory->NewStringFromAscii(i::CStrVector(program.start()));
  1172. TestParserSync(source);
  1173. }
  1174. }
  1175. }
  1176. }
  1177. TEST(PreparserStrictOctal) {
  1178. // Test that syntax error caused by octal literal is reported correctly as
  1179. // such (issue 2220).
  1180. v8::internal::FLAG_min_preparse_length = 1; // Force preparsing.
  1181. v8::V8::Initialize();
  1182. v8::HandleScope scope(v8::Isolate::GetCurrent());
  1183. v8::Context::Scope context_scope(
  1184. v8::Context::New(v8::Isolate::GetCurrent()));
  1185. v8::TryCatch try_catch;
  1186. const char* script =
  1187. "\"use strict\"; \n"
  1188. "a = function() { \n"
  1189. " b = function() { \n"
  1190. " 01; \n"
  1191. " }; \n"
  1192. "}; \n";
  1193. v8::Script::Compile(v8::String::New(script));
  1194. CHECK(try_catch.HasCaught());
  1195. v8::String::Utf8Value exception(try_catch.Exception());
  1196. CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
  1197. *exception);
  1198. }