PageRenderTime 76ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://gitlab.com/GeekSir/node
C++ | 3345 lines | 2703 code | 374 blank | 268 comment | 133 complexity | e7bdfa9d03c0307d0a54dd0759ae2d69 MD5 | raw file
Possible License(s): 0BSD, Apache-2.0, MPL-2.0-no-copyleft-exception, JSON, WTFPL, CC-BY-SA-3.0, Unlicense, ISC, BSD-3-Clause, 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 <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include "src/v8.h"
  31. #include "src/ast-value-factory.h"
  32. #include "src/compiler.h"
  33. #include "src/execution.h"
  34. #include "src/isolate.h"
  35. #include "src/objects.h"
  36. #include "src/parser.h"
  37. #include "src/preparser.h"
  38. #include "src/rewriter.h"
  39. #include "src/scanner-character-streams.h"
  40. #include "src/token.h"
  41. #include "src/utils.h"
  42. #include "test/cctest/cctest.h"
  43. TEST(ScanKeywords) {
  44. struct KeywordToken {
  45. const char* keyword;
  46. i::Token::Value token;
  47. };
  48. static const KeywordToken keywords[] = {
  49. #define KEYWORD(t, s, d) { s, i::Token::t },
  50. TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
  51. #undef KEYWORD
  52. { NULL, i::Token::IDENTIFIER }
  53. };
  54. KeywordToken key_token;
  55. i::UnicodeCache unicode_cache;
  56. i::byte buffer[32];
  57. for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
  58. const i::byte* keyword =
  59. reinterpret_cast<const i::byte*>(key_token.keyword);
  60. int length = i::StrLength(key_token.keyword);
  61. CHECK(static_cast<int>(sizeof(buffer)) >= length);
  62. {
  63. i::Utf8ToUtf16CharacterStream stream(keyword, length);
  64. i::Scanner scanner(&unicode_cache);
  65. // The scanner should parse Harmony keywords for this test.
  66. scanner.SetHarmonyScoping(true);
  67. scanner.SetHarmonyModules(true);
  68. scanner.Initialize(&stream);
  69. CHECK_EQ(key_token.token, scanner.Next());
  70. CHECK_EQ(i::Token::EOS, scanner.Next());
  71. }
  72. // Removing characters will make keyword matching fail.
  73. {
  74. i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
  75. i::Scanner scanner(&unicode_cache);
  76. scanner.Initialize(&stream);
  77. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  78. CHECK_EQ(i::Token::EOS, scanner.Next());
  79. }
  80. // Adding characters will make keyword matching fail.
  81. static const char chars_to_append[] = { 'z', '0', '_' };
  82. for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
  83. i::MemMove(buffer, keyword, length);
  84. buffer[length] = chars_to_append[j];
  85. i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
  86. i::Scanner scanner(&unicode_cache);
  87. scanner.Initialize(&stream);
  88. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  89. CHECK_EQ(i::Token::EOS, scanner.Next());
  90. }
  91. // Replacing characters will make keyword matching fail.
  92. {
  93. i::MemMove(buffer, keyword, length);
  94. buffer[length - 1] = '_';
  95. i::Utf8ToUtf16CharacterStream stream(buffer, length);
  96. i::Scanner scanner(&unicode_cache);
  97. scanner.Initialize(&stream);
  98. CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
  99. CHECK_EQ(i::Token::EOS, scanner.Next());
  100. }
  101. }
  102. }
  103. TEST(ScanHTMLEndComments) {
  104. v8::V8::Initialize();
  105. v8::Isolate* isolate = CcTest::isolate();
  106. v8::HandleScope handles(isolate);
  107. // Regression test. See:
  108. // http://code.google.com/p/chromium/issues/detail?id=53548
  109. // Tests that --> is correctly interpreted as comment-to-end-of-line if there
  110. // is only whitespace before it on the line (with comments considered as
  111. // whitespace, even a multiline-comment containing a newline).
  112. // This was not the case if it occurred before the first real token
  113. // in the input.
  114. const char* tests[] = {
  115. // Before first real token.
  116. "--> is eol-comment\nvar y = 37;\n",
  117. "\n --> is eol-comment\nvar y = 37;\n",
  118. "/* precomment */ --> is eol-comment\nvar y = 37;\n",
  119. "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
  120. // After first real token.
  121. "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
  122. "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
  123. NULL
  124. };
  125. const char* fail_tests[] = {
  126. "x --> is eol-comment\nvar y = 37;\n",
  127. "\"\\n\" --> is eol-comment\nvar y = 37;\n",
  128. "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
  129. "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
  130. "var x = 42; --> is eol-comment\nvar y = 37;\n",
  131. "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
  132. NULL
  133. };
  134. // Parser/Scanner needs a stack limit.
  135. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  136. 128 * 1024);
  137. uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
  138. for (int i = 0; tests[i]; i++) {
  139. const i::byte* source =
  140. reinterpret_cast<const i::byte*>(tests[i]);
  141. i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
  142. i::CompleteParserRecorder log;
  143. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  144. scanner.Initialize(&stream);
  145. i::PreParser preparser(&scanner, &log, stack_limit);
  146. preparser.set_allow_lazy(true);
  147. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  148. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  149. CHECK(!log.HasError());
  150. }
  151. for (int i = 0; fail_tests[i]; i++) {
  152. const i::byte* source =
  153. reinterpret_cast<const i::byte*>(fail_tests[i]);
  154. i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
  155. i::CompleteParserRecorder log;
  156. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  157. scanner.Initialize(&stream);
  158. i::PreParser preparser(&scanner, &log, stack_limit);
  159. preparser.set_allow_lazy(true);
  160. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  161. // Even in the case of a syntax error, kPreParseSuccess is returned.
  162. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  163. CHECK(log.HasError());
  164. }
  165. }
  166. class ScriptResource : public v8::String::ExternalAsciiStringResource {
  167. public:
  168. ScriptResource(const char* data, size_t length)
  169. : data_(data), length_(length) { }
  170. const char* data() const { return data_; }
  171. size_t length() const { return length_; }
  172. private:
  173. const char* data_;
  174. size_t length_;
  175. };
  176. TEST(UsingCachedData) {
  177. v8::Isolate* isolate = CcTest::isolate();
  178. v8::HandleScope handles(isolate);
  179. v8::Local<v8::Context> context = v8::Context::New(isolate);
  180. v8::Context::Scope context_scope(context);
  181. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  182. 128 * 1024);
  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. "var f = a => function (b) { return a + b; };"
  197. "var g = a => b => a + b;";
  198. int source_length = i::StrLength(source);
  199. // ScriptResource will be deleted when the corresponding String is GCd.
  200. v8::ScriptCompiler::Source script_source(v8::String::NewExternal(
  201. isolate, new ScriptResource(source, source_length)));
  202. i::FLAG_harmony_arrow_functions = true;
  203. i::FLAG_min_preparse_length = 0;
  204. v8::ScriptCompiler::Compile(isolate, &script_source,
  205. v8::ScriptCompiler::kProduceParserCache);
  206. CHECK(script_source.GetCachedData());
  207. // Compile the script again, using the cached data.
  208. bool lazy_flag = i::FLAG_lazy;
  209. i::FLAG_lazy = true;
  210. v8::ScriptCompiler::Compile(isolate, &script_source,
  211. v8::ScriptCompiler::kConsumeParserCache);
  212. i::FLAG_lazy = false;
  213. v8::ScriptCompiler::CompileUnbound(isolate, &script_source,
  214. v8::ScriptCompiler::kConsumeParserCache);
  215. i::FLAG_lazy = lazy_flag;
  216. }
  217. TEST(PreparseFunctionDataIsUsed) {
  218. // This tests that we actually do use the function data generated by the
  219. // preparser.
  220. // Make preparsing work for short scripts.
  221. i::FLAG_min_preparse_length = 0;
  222. i::FLAG_harmony_arrow_functions = true;
  223. v8::Isolate* isolate = CcTest::isolate();
  224. v8::HandleScope handles(isolate);
  225. v8::Local<v8::Context> context = v8::Context::New(isolate);
  226. v8::Context::Scope context_scope(context);
  227. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  228. 128 * 1024);
  229. const char* good_code[] = {
  230. "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
  231. "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
  232. };
  233. // Insert a syntax error inside the lazy function.
  234. const char* bad_code[] = {
  235. "function this_is_lazy() { if ( } function foo() { return 25; } foo();",
  236. "var this_is_lazy = () => { if ( }; var foo = () => 25; foo();",
  237. };
  238. for (unsigned i = 0; i < ARRAY_SIZE(good_code); i++) {
  239. v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
  240. v8::ScriptCompiler::Compile(isolate, &good_source,
  241. v8::ScriptCompiler::kProduceDataToCache);
  242. const v8::ScriptCompiler::CachedData* cached_data =
  243. good_source.GetCachedData();
  244. CHECK(cached_data->data != NULL);
  245. CHECK_GT(cached_data->length, 0);
  246. // Now compile the erroneous code with the good preparse data. If the
  247. // preparse data is used, the lazy function is skipped and it should
  248. // compile fine.
  249. v8::ScriptCompiler::Source bad_source(
  250. v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
  251. cached_data->data, cached_data->length));
  252. v8::Local<v8::Value> result =
  253. v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
  254. CHECK(result->IsInt32());
  255. CHECK_EQ(25, result->Int32Value());
  256. }
  257. }
  258. TEST(StandAlonePreParser) {
  259. v8::V8::Initialize();
  260. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  261. 128 * 1024);
  262. const char* programs[] = {
  263. "{label: 42}",
  264. "var x = 42;",
  265. "function foo(x, y) { return x + y; }",
  266. "%ArgleBargle(glop);",
  267. "var x = new new Function('this.x = 42');",
  268. "var f = (x, y) => x + y;",
  269. NULL
  270. };
  271. uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
  272. for (int i = 0; programs[i]; i++) {
  273. const char* program = programs[i];
  274. i::Utf8ToUtf16CharacterStream stream(
  275. reinterpret_cast<const i::byte*>(program),
  276. static_cast<unsigned>(strlen(program)));
  277. i::CompleteParserRecorder log;
  278. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  279. scanner.Initialize(&stream);
  280. i::PreParser preparser(&scanner, &log, stack_limit);
  281. preparser.set_allow_lazy(true);
  282. preparser.set_allow_natives_syntax(true);
  283. preparser.set_allow_arrow_functions(true);
  284. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  285. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  286. CHECK(!log.HasError());
  287. }
  288. }
  289. TEST(StandAlonePreParserNoNatives) {
  290. v8::V8::Initialize();
  291. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  292. 128 * 1024);
  293. const char* programs[] = {
  294. "%ArgleBargle(glop);",
  295. "var x = %_IsSmi(42);",
  296. NULL
  297. };
  298. uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
  299. for (int i = 0; programs[i]; i++) {
  300. const char* program = programs[i];
  301. i::Utf8ToUtf16CharacterStream stream(
  302. reinterpret_cast<const i::byte*>(program),
  303. static_cast<unsigned>(strlen(program)));
  304. i::CompleteParserRecorder log;
  305. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  306. scanner.Initialize(&stream);
  307. // Preparser defaults to disallowing natives syntax.
  308. i::PreParser preparser(&scanner, &log, stack_limit);
  309. preparser.set_allow_lazy(true);
  310. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  311. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  312. CHECK(log.HasError());
  313. }
  314. }
  315. TEST(PreparsingObjectLiterals) {
  316. // Regression test for a bug where the symbol stream produced by PreParser
  317. // didn't match what Parser wanted to consume.
  318. v8::Isolate* isolate = CcTest::isolate();
  319. v8::HandleScope handles(isolate);
  320. v8::Local<v8::Context> context = v8::Context::New(isolate);
  321. v8::Context::Scope context_scope(context);
  322. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  323. 128 * 1024);
  324. {
  325. const char* source = "var myo = {if: \"foo\"}; myo.if;";
  326. v8::Local<v8::Value> result = ParserCacheCompileRun(source);
  327. CHECK(result->IsString());
  328. v8::String::Utf8Value utf8(result);
  329. CHECK_EQ("foo", *utf8);
  330. }
  331. {
  332. const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
  333. v8::Local<v8::Value> result = ParserCacheCompileRun(source);
  334. CHECK(result->IsString());
  335. v8::String::Utf8Value utf8(result);
  336. CHECK_EQ("foo", *utf8);
  337. }
  338. {
  339. const char* source = "var myo = {1: \"foo\"}; myo[1];";
  340. v8::Local<v8::Value> result = ParserCacheCompileRun(source);
  341. CHECK(result->IsString());
  342. v8::String::Utf8Value utf8(result);
  343. CHECK_EQ("foo", *utf8);
  344. }
  345. }
  346. TEST(RegressChromium62639) {
  347. v8::V8::Initialize();
  348. i::Isolate* isolate = CcTest::i_isolate();
  349. isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
  350. const char* program = "var x = 'something';\n"
  351. "escape: function() {}";
  352. // Fails parsing expecting an identifier after "function".
  353. // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
  354. // and then used the invalid currently scanned literal. This always
  355. // failed in debug mode, and sometimes crashed in release mode.
  356. i::Utf8ToUtf16CharacterStream stream(
  357. reinterpret_cast<const i::byte*>(program),
  358. static_cast<unsigned>(strlen(program)));
  359. i::CompleteParserRecorder log;
  360. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  361. scanner.Initialize(&stream);
  362. i::PreParser preparser(&scanner, &log,
  363. CcTest::i_isolate()->stack_guard()->real_climit());
  364. preparser.set_allow_lazy(true);
  365. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  366. // Even in the case of a syntax error, kPreParseSuccess is returned.
  367. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  368. CHECK(log.HasError());
  369. }
  370. TEST(Regress928) {
  371. v8::V8::Initialize();
  372. i::Isolate* isolate = CcTest::i_isolate();
  373. i::Factory* factory = isolate->factory();
  374. // Preparsing didn't consider the catch clause of a try statement
  375. // as with-content, which made it assume that a function inside
  376. // the block could be lazily compiled, and an extra, unexpected,
  377. // entry was added to the data.
  378. isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
  379. const char* program =
  380. "try { } catch (e) { var foo = function () { /* first */ } }"
  381. "var bar = function () { /* second */ }";
  382. v8::HandleScope handles(CcTest::isolate());
  383. i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
  384. i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
  385. i::CompleteParserRecorder log;
  386. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  387. scanner.Initialize(&stream);
  388. i::PreParser preparser(&scanner, &log,
  389. CcTest::i_isolate()->stack_guard()->real_climit());
  390. preparser.set_allow_lazy(true);
  391. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  392. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  393. i::ScriptData* sd = log.GetScriptData();
  394. i::ParseData pd(sd);
  395. pd.Initialize();
  396. int first_function =
  397. static_cast<int>(strstr(program, "function") - program);
  398. int first_lbrace = first_function + i::StrLength("function () ");
  399. CHECK_EQ('{', program[first_lbrace]);
  400. i::FunctionEntry entry1 = pd.GetFunctionEntry(first_lbrace);
  401. CHECK(!entry1.is_valid());
  402. int second_function =
  403. static_cast<int>(strstr(program + first_lbrace, "function") - program);
  404. int second_lbrace =
  405. second_function + i::StrLength("function () ");
  406. CHECK_EQ('{', program[second_lbrace]);
  407. i::FunctionEntry entry2 = pd.GetFunctionEntry(second_lbrace);
  408. CHECK(entry2.is_valid());
  409. CHECK_EQ('}', program[entry2.end_pos() - 1]);
  410. delete sd;
  411. }
  412. TEST(PreParseOverflow) {
  413. v8::V8::Initialize();
  414. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  415. 128 * 1024);
  416. size_t kProgramSize = 1024 * 1024;
  417. i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
  418. memset(program.get(), '(', kProgramSize);
  419. program[kProgramSize] = '\0';
  420. uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
  421. i::Utf8ToUtf16CharacterStream stream(
  422. reinterpret_cast<const i::byte*>(program.get()),
  423. static_cast<unsigned>(kProgramSize));
  424. i::CompleteParserRecorder log;
  425. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  426. scanner.Initialize(&stream);
  427. i::PreParser preparser(&scanner, &log, stack_limit);
  428. preparser.set_allow_lazy(true);
  429. preparser.set_allow_arrow_functions(true);
  430. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  431. CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
  432. }
  433. class TestExternalResource: public v8::String::ExternalStringResource {
  434. public:
  435. explicit TestExternalResource(uint16_t* data, int length)
  436. : data_(data), length_(static_cast<size_t>(length)) { }
  437. ~TestExternalResource() { }
  438. const uint16_t* data() const {
  439. return data_;
  440. }
  441. size_t length() const {
  442. return length_;
  443. }
  444. private:
  445. uint16_t* data_;
  446. size_t length_;
  447. };
  448. #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
  449. void TestCharacterStream(const char* ascii_source,
  450. unsigned length,
  451. unsigned start = 0,
  452. unsigned end = 0) {
  453. if (end == 0) end = length;
  454. unsigned sub_length = end - start;
  455. i::Isolate* isolate = CcTest::i_isolate();
  456. i::Factory* factory = isolate->factory();
  457. i::HandleScope test_scope(isolate);
  458. i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
  459. for (unsigned i = 0; i < length; i++) {
  460. uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
  461. }
  462. i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
  463. i::Handle<i::String> ascii_string =
  464. factory->NewStringFromAscii(ascii_vector).ToHandleChecked();
  465. TestExternalResource resource(uc16_buffer.get(), length);
  466. i::Handle<i::String> uc16_string(
  467. factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
  468. i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
  469. i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
  470. i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end);
  471. i::Utf8ToUtf16CharacterStream utf8_stream(
  472. reinterpret_cast<const i::byte*>(ascii_source), end);
  473. utf8_stream.SeekForward(start);
  474. unsigned i = start;
  475. while (i < end) {
  476. // Read streams one char at a time
  477. CHECK_EQU(i, uc16_stream.pos());
  478. CHECK_EQU(i, string_stream.pos());
  479. CHECK_EQU(i, utf8_stream.pos());
  480. int32_t c0 = ascii_source[i];
  481. int32_t c1 = uc16_stream.Advance();
  482. int32_t c2 = string_stream.Advance();
  483. int32_t c3 = utf8_stream.Advance();
  484. i++;
  485. CHECK_EQ(c0, c1);
  486. CHECK_EQ(c0, c2);
  487. CHECK_EQ(c0, c3);
  488. CHECK_EQU(i, uc16_stream.pos());
  489. CHECK_EQU(i, string_stream.pos());
  490. CHECK_EQU(i, utf8_stream.pos());
  491. }
  492. while (i > start + sub_length / 4) {
  493. // Pushback, re-read, pushback again.
  494. int32_t c0 = ascii_source[i - 1];
  495. CHECK_EQU(i, uc16_stream.pos());
  496. CHECK_EQU(i, string_stream.pos());
  497. CHECK_EQU(i, utf8_stream.pos());
  498. uc16_stream.PushBack(c0);
  499. string_stream.PushBack(c0);
  500. utf8_stream.PushBack(c0);
  501. i--;
  502. CHECK_EQU(i, uc16_stream.pos());
  503. CHECK_EQU(i, string_stream.pos());
  504. CHECK_EQU(i, utf8_stream.pos());
  505. int32_t c1 = uc16_stream.Advance();
  506. int32_t c2 = string_stream.Advance();
  507. int32_t c3 = utf8_stream.Advance();
  508. i++;
  509. CHECK_EQU(i, uc16_stream.pos());
  510. CHECK_EQU(i, string_stream.pos());
  511. CHECK_EQU(i, utf8_stream.pos());
  512. CHECK_EQ(c0, c1);
  513. CHECK_EQ(c0, c2);
  514. CHECK_EQ(c0, c3);
  515. uc16_stream.PushBack(c0);
  516. string_stream.PushBack(c0);
  517. utf8_stream.PushBack(c0);
  518. i--;
  519. CHECK_EQU(i, uc16_stream.pos());
  520. CHECK_EQU(i, string_stream.pos());
  521. CHECK_EQU(i, utf8_stream.pos());
  522. }
  523. unsigned halfway = start + sub_length / 2;
  524. uc16_stream.SeekForward(halfway - i);
  525. string_stream.SeekForward(halfway - i);
  526. utf8_stream.SeekForward(halfway - i);
  527. i = halfway;
  528. CHECK_EQU(i, uc16_stream.pos());
  529. CHECK_EQU(i, string_stream.pos());
  530. CHECK_EQU(i, utf8_stream.pos());
  531. while (i < end) {
  532. // Read streams one char at a time
  533. CHECK_EQU(i, uc16_stream.pos());
  534. CHECK_EQU(i, string_stream.pos());
  535. CHECK_EQU(i, utf8_stream.pos());
  536. int32_t c0 = ascii_source[i];
  537. int32_t c1 = uc16_stream.Advance();
  538. int32_t c2 = string_stream.Advance();
  539. int32_t c3 = utf8_stream.Advance();
  540. i++;
  541. CHECK_EQ(c0, c1);
  542. CHECK_EQ(c0, c2);
  543. CHECK_EQ(c0, c3);
  544. CHECK_EQU(i, uc16_stream.pos());
  545. CHECK_EQU(i, string_stream.pos());
  546. CHECK_EQU(i, utf8_stream.pos());
  547. }
  548. int32_t c1 = uc16_stream.Advance();
  549. int32_t c2 = string_stream.Advance();
  550. int32_t c3 = utf8_stream.Advance();
  551. CHECK_LT(c1, 0);
  552. CHECK_LT(c2, 0);
  553. CHECK_LT(c3, 0);
  554. }
  555. TEST(CharacterStreams) {
  556. v8::Isolate* isolate = CcTest::isolate();
  557. v8::HandleScope handles(isolate);
  558. v8::Local<v8::Context> context = v8::Context::New(isolate);
  559. v8::Context::Scope context_scope(context);
  560. TestCharacterStream("abc\0\n\r\x7f", 7);
  561. static const unsigned kBigStringSize = 4096;
  562. char buffer[kBigStringSize + 1];
  563. for (unsigned i = 0; i < kBigStringSize; i++) {
  564. buffer[i] = static_cast<char>(i & 0x7f);
  565. }
  566. TestCharacterStream(buffer, kBigStringSize);
  567. TestCharacterStream(buffer, kBigStringSize, 576, 3298);
  568. TestCharacterStream("\0", 1);
  569. TestCharacterStream("", 0);
  570. }
  571. TEST(Utf8CharacterStream) {
  572. static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
  573. static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
  574. static const int kAllUtf8CharsSize =
  575. (unibrow::Utf8::kMaxOneByteChar + 1) +
  576. (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
  577. (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
  578. static const unsigned kAllUtf8CharsSizeU =
  579. static_cast<unsigned>(kAllUtf8CharsSize);
  580. char buffer[kAllUtf8CharsSizeU];
  581. unsigned cursor = 0;
  582. for (int i = 0; i <= kMaxUC16Char; i++) {
  583. cursor += unibrow::Utf8::Encode(buffer + cursor,
  584. i,
  585. unibrow::Utf16::kNoPreviousCharacter);
  586. }
  587. DCHECK(cursor == kAllUtf8CharsSizeU);
  588. i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
  589. kAllUtf8CharsSizeU);
  590. for (int i = 0; i <= kMaxUC16Char; i++) {
  591. CHECK_EQU(i, stream.pos());
  592. int32_t c = stream.Advance();
  593. CHECK_EQ(i, c);
  594. CHECK_EQU(i + 1, stream.pos());
  595. }
  596. for (int i = kMaxUC16Char; i >= 0; i--) {
  597. CHECK_EQU(i + 1, stream.pos());
  598. stream.PushBack(i);
  599. CHECK_EQU(i, stream.pos());
  600. }
  601. int i = 0;
  602. while (stream.pos() < kMaxUC16CharU) {
  603. CHECK_EQU(i, stream.pos());
  604. unsigned progress = stream.SeekForward(12);
  605. i += progress;
  606. int32_t c = stream.Advance();
  607. if (i <= kMaxUC16Char) {
  608. CHECK_EQ(i, c);
  609. } else {
  610. CHECK_EQ(-1, c);
  611. }
  612. i += 1;
  613. CHECK_EQU(i, stream.pos());
  614. }
  615. }
  616. #undef CHECK_EQU
  617. void TestStreamScanner(i::Utf16CharacterStream* stream,
  618. i::Token::Value* expected_tokens,
  619. int skip_pos = 0, // Zero means not skipping.
  620. int skip_to = 0) {
  621. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  622. scanner.Initialize(stream);
  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. TEST(StreamScanner) {
  635. v8::V8::Initialize();
  636. const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
  637. i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
  638. static_cast<unsigned>(strlen(str1)));
  639. i::Token::Value expectations1[] = {
  640. i::Token::LBRACE,
  641. i::Token::IDENTIFIER,
  642. i::Token::IDENTIFIER,
  643. i::Token::FOR,
  644. i::Token::COLON,
  645. i::Token::MUL,
  646. i::Token::DIV,
  647. i::Token::LT,
  648. i::Token::SUB,
  649. i::Token::IDENTIFIER,
  650. i::Token::EOS,
  651. i::Token::ILLEGAL
  652. };
  653. TestStreamScanner(&stream1, expectations1, 0, 0);
  654. const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
  655. i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
  656. static_cast<unsigned>(strlen(str2)));
  657. i::Token::Value expectations2[] = {
  658. i::Token::CASE,
  659. i::Token::DEFAULT,
  660. i::Token::CONST,
  661. i::Token::LBRACE,
  662. // Skipped part here
  663. i::Token::RBRACE,
  664. i::Token::DO,
  665. i::Token::EOS,
  666. i::Token::ILLEGAL
  667. };
  668. DCHECK_EQ('{', str2[19]);
  669. DCHECK_EQ('}', str2[37]);
  670. TestStreamScanner(&stream2, expectations2, 20, 37);
  671. const char* str3 = "{}}}}";
  672. i::Token::Value expectations3[] = {
  673. i::Token::LBRACE,
  674. i::Token::RBRACE,
  675. i::Token::RBRACE,
  676. i::Token::RBRACE,
  677. i::Token::RBRACE,
  678. i::Token::EOS,
  679. i::Token::ILLEGAL
  680. };
  681. // Skip zero-four RBRACEs.
  682. for (int i = 0; i <= 4; i++) {
  683. expectations3[6 - i] = i::Token::ILLEGAL;
  684. expectations3[5 - i] = i::Token::EOS;
  685. i::Utf8ToUtf16CharacterStream stream3(
  686. reinterpret_cast<const i::byte*>(str3),
  687. static_cast<unsigned>(strlen(str3)));
  688. TestStreamScanner(&stream3, expectations3, 1, 1 + i);
  689. }
  690. }
  691. void TestScanRegExp(const char* re_source, const char* expected) {
  692. i::Utf8ToUtf16CharacterStream stream(
  693. reinterpret_cast<const i::byte*>(re_source),
  694. static_cast<unsigned>(strlen(re_source)));
  695. i::HandleScope scope(CcTest::i_isolate());
  696. i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
  697. scanner.Initialize(&stream);
  698. i::Token::Value start = scanner.peek();
  699. CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
  700. CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
  701. scanner.Next(); // Current token is now the regexp literal.
  702. i::Zone zone(CcTest::i_isolate());
  703. i::AstValueFactory ast_value_factory(&zone,
  704. CcTest::i_isolate()->heap()->HashSeed());
  705. ast_value_factory.Internalize(CcTest::i_isolate());
  706. i::Handle<i::String> val =
  707. scanner.CurrentSymbol(&ast_value_factory)->string();
  708. i::DisallowHeapAllocation no_alloc;
  709. i::String::FlatContent content = val->GetFlatContent();
  710. CHECK(content.IsAscii());
  711. i::Vector<const uint8_t> actual = content.ToOneByteVector();
  712. for (int i = 0; i < actual.length(); i++) {
  713. CHECK_NE('\0', expected[i]);
  714. CHECK_EQ(expected[i], actual[i]);
  715. }
  716. }
  717. TEST(RegExpScanning) {
  718. v8::V8::Initialize();
  719. // RegExp token with added garbage at the end. The scanner should only
  720. // scan the RegExp until the terminating slash just before "flipperwald".
  721. TestScanRegExp("/b/flipperwald", "b");
  722. // Incomplete escape sequences doesn't hide the terminating slash.
  723. TestScanRegExp("/\\x/flipperwald", "\\x");
  724. TestScanRegExp("/\\u/flipperwald", "\\u");
  725. TestScanRegExp("/\\u1/flipperwald", "\\u1");
  726. TestScanRegExp("/\\u12/flipperwald", "\\u12");
  727. TestScanRegExp("/\\u123/flipperwald", "\\u123");
  728. TestScanRegExp("/\\c/flipperwald", "\\c");
  729. TestScanRegExp("/\\c//flipperwald", "\\c");
  730. // Slashes inside character classes are not terminating.
  731. TestScanRegExp("/[/]/flipperwald", "[/]");
  732. TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
  733. // Incomplete escape sequences inside a character class doesn't hide
  734. // the end of the character class.
  735. TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
  736. TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
  737. TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
  738. TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
  739. TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
  740. TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
  741. TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
  742. TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
  743. // Escaped ']'s wont end the character class.
  744. TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
  745. // Escaped slashes are not terminating.
  746. TestScanRegExp("/\\//flipperwald", "\\/");
  747. // Starting with '=' works too.
  748. TestScanRegExp("/=/", "=");
  749. TestScanRegExp("/=?/", "=?");
  750. }
  751. static int Utf8LengthHelper(const char* s) {
  752. int len = i::StrLength(s);
  753. int character_length = len;
  754. for (int i = 0; i < len; i++) {
  755. unsigned char c = s[i];
  756. int input_offset = 0;
  757. int output_adjust = 0;
  758. if (c > 0x7f) {
  759. if (c < 0xc0) continue;
  760. if (c >= 0xf0) {
  761. if (c >= 0xf8) {
  762. // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
  763. // byte.
  764. continue; // Handle first UTF-8 byte.
  765. }
  766. if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
  767. // This 4 byte sequence could have been coded as a 3 byte sequence.
  768. // Record a single kBadChar for the first byte and continue.
  769. continue;
  770. }
  771. input_offset = 3;
  772. // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
  773. character_length -= 2;
  774. } else if (c >= 0xe0) {
  775. if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
  776. // This 3 byte sequence could have been coded as a 2 byte sequence.
  777. // Record a single kBadChar for the first byte and continue.
  778. continue;
  779. }
  780. input_offset = 2;
  781. // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
  782. output_adjust = 2;
  783. } else {
  784. if ((c & 0x1e) == 0) {
  785. // This 2 byte sequence could have been coded as a 1 byte sequence.
  786. // Record a single kBadChar for the first byte and continue.
  787. continue;
  788. }
  789. input_offset = 1;
  790. // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
  791. output_adjust = 1;
  792. }
  793. bool bad = false;
  794. for (int j = 1; j <= input_offset; j++) {
  795. if ((s[i + j] & 0xc0) != 0x80) {
  796. // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
  797. // which is a single UTF-16 code unit.
  798. bad = true;
  799. break;
  800. }
  801. }
  802. if (!bad) {
  803. i += input_offset;
  804. character_length -= output_adjust;
  805. }
  806. }
  807. }
  808. return character_length;
  809. }
  810. TEST(ScopePositions) {
  811. v8::internal::FLAG_harmony_scoping = true;
  812. // Test the parser for correctly setting the start and end positions
  813. // of a scope. We check the scope positions of exactly one scope
  814. // nested in the global scope of a program. 'inner source' is the
  815. // source code that determines the part of the source belonging
  816. // to the nested scope. 'outer_prefix' and 'outer_suffix' are
  817. // parts of the source that belong to the global scope.
  818. struct SourceData {
  819. const char* outer_prefix;
  820. const char* inner_source;
  821. const char* outer_suffix;
  822. i::ScopeType scope_type;
  823. i::StrictMode strict_mode;
  824. };
  825. const SourceData source_data[] = {
  826. { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
  827. { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
  828. { " with ({}) ", "{\n"
  829. " block;\n"
  830. " }", "\n"
  831. " more;", i::WITH_SCOPE, i::SLOPPY },
  832. { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
  833. { " with ({}) ", "statement", "\n"
  834. " more;", i::WITH_SCOPE, i::SLOPPY },
  835. { " with ({})\n"
  836. " ", "statement;", "\n"
  837. " more;", i::WITH_SCOPE, i::SLOPPY },
  838. { " try {} catch ", "(e) { block; }", " more;",
  839. i::CATCH_SCOPE, i::SLOPPY },
  840. { " try {} catch ", "(e) { block; }", "; more;",
  841. i::CATCH_SCOPE, i::SLOPPY },
  842. { " try {} catch ", "(e) {\n"
  843. " block;\n"
  844. " }", "\n"
  845. " more;", i::CATCH_SCOPE, i::SLOPPY },
  846. { " try {} catch ", "(e) { block; }", " finally { block; } more;",
  847. i::CATCH_SCOPE, i::SLOPPY },
  848. { " start;\n"
  849. " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
  850. { " start;\n"
  851. " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
  852. { " start;\n"
  853. " ", "{\n"
  854. " let block;\n"
  855. " }", "\n"
  856. " more;", i::BLOCK_SCOPE, i::STRICT },
  857. { " start;\n"
  858. " function fun", "(a,b) { infunction; }", " more;",
  859. i::FUNCTION_SCOPE, i::SLOPPY },
  860. { " start;\n"
  861. " function fun", "(a,b) {\n"
  862. " infunction;\n"
  863. " }", "\n"
  864. " more;", i::FUNCTION_SCOPE, i::SLOPPY },
  865. // TODO(aperez): Change to use i::ARROW_SCOPE when implemented
  866. { " start;\n", "(a,b) => a + b", "; more;",
  867. i::FUNCTION_SCOPE, i::SLOPPY },
  868. { " start;\n", "(a,b) => { return a+b; }", "\nmore;",
  869. i::FUNCTION_SCOPE, i::SLOPPY },
  870. { " start;\n"
  871. " (function fun", "(a,b) { infunction; }", ")();",
  872. i::FUNCTION_SCOPE, i::SLOPPY },
  873. { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
  874. i::BLOCK_SCOPE, i::STRICT },
  875. { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
  876. i::BLOCK_SCOPE, i::STRICT },
  877. { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
  878. " block;\n"
  879. " }", "\n"
  880. " more;", i::BLOCK_SCOPE, i::STRICT },
  881. { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
  882. i::BLOCK_SCOPE, i::STRICT },
  883. { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
  884. " more;", i::BLOCK_SCOPE, i::STRICT },
  885. { " for ", "(let x = 1 ; x < 10; ++ x)\n"
  886. " statement;", "\n"
  887. " more;", i::BLOCK_SCOPE, i::STRICT },
  888. { " for ", "(let x in {}) { block; }", " more;",
  889. i::BLOCK_SCOPE, i::STRICT },
  890. { " for ", "(let x in {}) { block; }", "; more;",
  891. i::BLOCK_SCOPE, i::STRICT },
  892. { " for ", "(let x in {}) {\n"
  893. " block;\n"
  894. " }", "\n"
  895. " more;", i::BLOCK_SCOPE, i::STRICT },
  896. { " for ", "(let x in {}) statement;", " more;",
  897. i::BLOCK_SCOPE, i::STRICT },
  898. { " for ", "(let x in {}) statement", "\n"
  899. " more;", i::BLOCK_SCOPE, i::STRICT },
  900. { " for ", "(let x in {})\n"
  901. " statement;", "\n"
  902. " more;", i::BLOCK_SCOPE, i::STRICT },
  903. // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
  904. // the preparser off in terms of byte offsets.
  905. // 6 byte encoding.
  906. { " 'foo\355\240\201\355\260\211';\n"
  907. " (function fun", "(a,b) { infunction; }", ")();",
  908. i::FUNCTION_SCOPE, i::SLOPPY },
  909. // 4 byte encoding.
  910. { " 'foo\360\220\220\212';\n"
  911. " (function fun", "(a,b) { infunction; }", ")();",
  912. i::FUNCTION_SCOPE, i::SLOPPY },
  913. // 3 byte encoding of \u0fff.
  914. { " 'foo\340\277\277';\n"
  915. " (function fun", "(a,b) { infunction; }", ")();",
  916. i::FUNCTION_SCOPE, i::SLOPPY },
  917. // Broken 6 byte encoding with missing last byte.
  918. { " 'foo\355\240\201\355\211';\n"
  919. " (function fun", "(a,b) { infunction; }", ")();",
  920. i::FUNCTION_SCOPE, i::SLOPPY },
  921. // Broken 3 byte encoding of \u0fff with missing last byte.
  922. { " 'foo\340\277';\n"
  923. " (function fun", "(a,b) { infunction; }", ")();",
  924. i::FUNCTION_SCOPE, i::SLOPPY },
  925. // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
  926. { " 'foo\340';\n"
  927. " (function fun", "(a,b) { infunction; }", ")();",
  928. i::FUNCTION_SCOPE, i::SLOPPY },
  929. // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
  930. { " 'foo\340\203\277';\n"
  931. " (function fun", "(a,b) { infunction; }", ")();",
  932. i::FUNCTION_SCOPE, i::SLOPPY },
  933. // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
  934. { " 'foo\340\201\277';\n"
  935. " (function fun", "(a,b) { infunction; }", ")();",
  936. i::FUNCTION_SCOPE, i::SLOPPY },
  937. // Unpaired lead surrogate.
  938. { " 'foo\355\240\201';\n"
  939. " (function fun", "(a,b) { infunction; }", ")();",
  940. i::FUNCTION_SCOPE, i::SLOPPY },
  941. // Unpaired lead surrogate where following code point is a 3 byte sequence.
  942. { " 'foo\355\240\201\340\277\277';\n"
  943. " (function fun", "(a,b) { infunction; }", ")();",
  944. i::FUNCTION_SCOPE, i::SLOPPY },
  945. // Unpaired lead surrogate where following code point is a 4 byte encoding
  946. // of a trail surrogate.
  947. { " 'foo\355\240\201\360\215\260\211';\n"
  948. " (function fun", "(a,b) { infunction; }", ")();",
  949. i::FUNCTION_SCOPE, i::SLOPPY },
  950. // Unpaired trail surrogate.
  951. { " 'foo\355\260\211';\n"
  952. " (function fun", "(a,b) { infunction; }", ")();",
  953. i::FUNCTION_SCOPE, i::SLOPPY },
  954. // 2 byte encoding of \u00ff.
  955. { " 'foo\303\277';\n"
  956. " (function fun", "(a,b) { infunction; }", ")();",
  957. i::FUNCTION_SCOPE, i::SLOPPY },
  958. // Broken 2 byte encoding of \u00ff with missing last byte.
  959. { " 'foo\303';\n"
  960. " (function fun", "(a,b) { infunction; }", ")();",
  961. i::FUNCTION_SCOPE, i::SLOPPY },
  962. // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
  963. { " 'foo\301\277';\n"
  964. " (function fun", "(a,b) { infunction; }", ")();",
  965. i::FUNCTION_SCOPE, i::SLOPPY },
  966. // Illegal 5 byte encoding.
  967. { " 'foo\370\277\277\277\277';\n"
  968. " (function fun", "(a,b) { infunction; }", ")();",
  969. i::FUNCTION_SCOPE, i::SLOPPY },
  970. // Illegal 6 byte encoding.
  971. { " 'foo\374\277\277\277\277\277';\n"
  972. " (function fun", "(a,b) { infunction; }", ")();",
  973. i::FUNCTION_SCOPE, i::SLOPPY },
  974. // Illegal 0xfe byte
  975. { " 'foo\376\277\277\277\277\277\277';\n"
  976. " (function fun", "(a,b) { infunction; }", ")();",
  977. i::FUNCTION_SCOPE, i::SLOPPY },
  978. // Illegal 0xff byte
  979. { " 'foo\377\277\277\277\277\277\277\277';\n"
  980. " (function fun", "(a,b) { infunction; }", ")();",
  981. i::FUNCTION_SCOPE, i::SLOPPY },
  982. { " 'foo';\n"
  983. " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
  984. i::FUNCTION_SCOPE, i::SLOPPY },
  985. { " 'foo';\n"
  986. " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
  987. i::FUNCTION_SCOPE, i::SLOPPY },
  988. { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
  989. };
  990. i::Isolate* isolate = CcTest::i_isolate();
  991. i::Factory* factory = isolate->factory();
  992. v8::HandleScope handles(CcTest::isolate());
  993. v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
  994. v8::Context::Scope context_scope(context);
  995. isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition() - 128 * 1024);
  996. for (int i = 0; source_data[i].outer_prefix; i++) {
  997. int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
  998. int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
  999. int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
  1000. int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
  1001. int kInnerByteLen = i::StrLength(source_data[i].inner_source);
  1002. int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
  1003. int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
  1004. int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
  1005. i::ScopedVector<char> program(kProgramByteSize + 1);
  1006. i::SNPrintF(program, "%s%s%s",
  1007. source_data[i].outer_prefix,
  1008. source_data[i].inner_source,
  1009. source_data[i].outer_suffix);
  1010. // Parse program source.
  1011. i::Handle<i::String> source = factory->NewStringFromUtf8(
  1012. i::CStrVector(program.start())).ToHandleChecked();
  1013. CHECK_EQ(source->length(), kProgramSize);
  1014. i::Handle<i::Script> script = factory->NewScript(source);
  1015. i::CompilationInfoWithZone info(script);
  1016. i::Parser parser(&info);
  1017. parser.set_allow_lazy(true);
  1018. parser.set_allow_harmony_scoping(true);
  1019. parser.set_allow_arrow_functions(true);
  1020. info.MarkAsGlobal();
  1021. info.SetStrictMode(source_data[i].strict_mode);
  1022. parser.Parse();
  1023. CHECK(info.function() != NULL);
  1024. // Check scope types and positions.
  1025. i::Scope* scope = info.function()->scope();
  1026. CHECK(scope->is_global_scope());
  1027. CHECK_EQ(scope->start_position(), 0);
  1028. CHECK_EQ(scope->end_position(), kProgramSize);
  1029. CHECK_EQ(scope->inner_scopes()->length(), 1);
  1030. i::Scope* inner_scope = scope->inner_scopes()->at(0);
  1031. CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
  1032. CHECK_EQ(inner_scope->start_position(), kPrefixLen);
  1033. // The end position of a token is one position after the last
  1034. // character belonging to that token.
  1035. CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
  1036. }
  1037. }
  1038. const char* ReadString(unsigned* start) {
  1039. int length = start[0];
  1040. char* result = i::NewArray<char>(length + 1);
  1041. for (int i = 0; i < length; i++) {
  1042. result[i] = start[i + 1];
  1043. }
  1044. result[length] = '\0';
  1045. return result;
  1046. }
  1047. i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
  1048. i::Isolate* isolate = CcTest::i_isolate();
  1049. i::Factory* factory = isolate->factory();
  1050. const char* message =
  1051. ReadString(&data[i::PreparseDataConstants::kMessageTextPos]);
  1052. i::Handle<i::String> format = v8::Utils::OpenHandle(
  1053. *v8::String::NewFromUtf8(CcTest::isolate(), message));
  1054. int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
  1055. const char* arg = NULL;
  1056. i::Handle<i::JSArray> args_array;
  1057. if (arg_count == 1) {
  1058. // Position after text found by skipping past length field and
  1059. // length field content words.
  1060. int pos = i::PreparseDataConstants::kMessageTextPos + 1 +
  1061. data[i::PreparseDataConstants::kMessageTextPos];
  1062. arg = ReadString(&data[pos]);
  1063. args_array = factory->NewJSArray(1);
  1064. i::JSArray::SetElement(args_array, 0, v8::Utils::OpenHandle(*v8_str(arg)),
  1065. NONE, i::SLOPPY).Check();
  1066. } else {
  1067. CHECK_EQ(0, arg_count);
  1068. args_array = factory->NewJSArray(0);
  1069. }
  1070. i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
  1071. i::Handle<i::Object> format_fun = i::Object::GetProperty(
  1072. isolate, builtins, "FormatMessage").ToHandleChecked();
  1073. i::Handle<i::Object> arg_handles[] = { format, args_array };
  1074. i::Handle<i::Object> result = i::Execution::Call(
  1075. isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
  1076. CHECK(result->IsString());
  1077. i::DeleteArray(message);
  1078. i::DeleteArray(arg);
  1079. data.Dispose();
  1080. return i::Handle<i::String>::cast(result);
  1081. }
  1082. enum ParserFlag {
  1083. kAllowLazy,
  1084. kAllowNativesSyntax,
  1085. kAllowHarmonyScoping,
  1086. kAllowModules,
  1087. kAllowGenerators,
  1088. kAllowHarmonyNumericLiterals,
  1089. kAllowArrowFunctions
  1090. };
  1091. enum ParserSyncTestResult {
  1092. kSuccessOrError,
  1093. kSuccess,
  1094. kError
  1095. };
  1096. template <typename Traits>
  1097. void SetParserFlags(i::ParserBase<Traits>* parser,
  1098. i::EnumSet<ParserFlag> flags) {
  1099. parser->set_allow_lazy(flags.Contains(kAllowLazy));
  1100. parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
  1101. parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
  1102. parser->set_allow_modules(flags.Contains(kAllowModules));
  1103. parser->set_allow_generators(flags.Contains(kAllowGenerators));
  1104. parser->set_allow_harmony_numeric_literals(
  1105. flags.Contains(kAllowHarmonyNumericLiterals));
  1106. parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
  1107. }
  1108. void TestParserSyncWithFlags(i::Handle<i::String> source,
  1109. i::EnumSet<ParserFlag> flags,
  1110. ParserSyncTestResult result) {
  1111. i::Isolate* isolate = CcTest::i_isolate();
  1112. i::Factory* factory = isolate->factory();
  1113. uintptr_t stack_limit = isolate->stack_guard()->real_climit();
  1114. // Preparse the data.
  1115. i::CompleteParserRecorder log;
  1116. {
  1117. i::Scanner scanner(isolate->unicode_cache());
  1118. i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
  1119. i::PreParser preparser(&scanner, &log, stack_limit);
  1120. SetParserFlags(&preparser, flags);
  1121. scanner.Initialize(&stream);
  1122. i::PreParser::PreParseResult result = preparser.PreParseProgram();
  1123. CHECK_EQ(i::PreParser::kPreParseSuccess, result);
  1124. }
  1125. bool preparse_error = log.HasError();
  1126. // Parse the data
  1127. i::FunctionLiteral* function;
  1128. {
  1129. i::Handle<i::Script> script = factory->NewScript(source);
  1130. i::CompilationInfoWithZone info(script);
  1131. i::Parser parser(&info);
  1132. SetParserFlags(&parser, flags);
  1133. info.MarkAsGlobal();
  1134. parser.Parse();
  1135. function = info.function();
  1136. }
  1137. // Check that preparsing fails iff parsing fails.
  1138. if (function == NULL) {
  1139. // Extract exception from the parser.
  1140. CHECK(isolate->has_pending_exception());
  1141. i::Handle<i::JSObject> exception_handle(
  1142. i::JSObject::cast(isolate->pending_exception()));
  1143. i::Handle<i::String> message_string =
  1144. i::Handle<i::String>::cast(i::Object::GetProperty(
  1145. isolate, exception_handle, "message").ToHandleChecked());
  1146. if (result == kSuccess) {
  1147. v8::base::OS::Print(
  1148. "Parser failed on:\n"
  1149. "\t%s\n"
  1150. "with error:\n"
  1151. "\t%s\n"
  1152. "However, we expected no error.",
  1153. source->ToCString().get(), message_string->ToCString().get());
  1154. CHECK(false);
  1155. }
  1156. if (!preparse_error) {
  1157. v8::base::OS::Print(
  1158. "Parser failed on:\n"
  1159. "\t%s\n"
  1160. "with error:\n"
  1161. "\t%s\n"
  1162. "However, the preparser succeeded",
  1163. source->ToCString().get(), message_string->ToCString().get());
  1164. CHECK(false);
  1165. }
  1166. // Check that preparser and parser produce the same error.
  1167. i::Handle<i::String> preparser_message =
  1168. FormatMessage(log.ErrorMessageData());
  1169. if (!i::String::Equals(message_string, preparser_message)) {
  1170. v8::base::OS::Print(
  1171. "Expected parser and preparser to produce the same error on:\n"
  1172. "\t%s\n"
  1173. "However, found the following error messages\n"
  1174. "\tparser: %s\n"
  1175. "\tpreparser: %s\n",
  1176. source->ToCString().get(),
  1177. message_string->ToCString().get(),
  1178. preparser_message->ToCString().get());
  1179. CHECK(false);
  1180. }
  1181. } else if (preparse_error) {
  1182. v8::base::OS::Print(
  1183. "Preparser failed on:\n"
  1184. "\t%s\n"
  1185. "with error:\n"
  1186. "\t%s\n"
  1187. "However, the parser succeeded",
  1188. source->ToCString().get(),
  1189. FormatMessage(log.ErrorMessageData())->ToCString().get());
  1190. CHECK(false);
  1191. } else if (result == kError) {
  1192. v8::base::OS::Print(
  1193. "Expected error on:\n"
  1194. "\t%s\n"
  1195. "However, parser and preparser succeeded",
  1196. source->ToCString().get());
  1197. CHECK(false);
  1198. }
  1199. }
  1200. void TestParserSync(const char* source,
  1201. const ParserFlag* varying_flags,
  1202. size_t varying_flags_length,
  1203. ParserSyncTestResult result = kSuccessOrError,
  1204. const ParserFlag* always_true_flags = NULL,
  1205. size_t always_true_flags_length = 0) {
  1206. i::Handle<i::String> str =
  1207. CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
  1208. for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
  1209. i::EnumSet<ParserFlag> flags;
  1210. for (size_t flag_index = 0; flag_index < varying_flags_length;
  1211. ++flag_index) {
  1212. if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
  1213. }
  1214. for (size_t flag_index = 0; flag_index < always_true_flags_length;
  1215. ++flag_index) {
  1216. flags.Add(always_true_flags[flag_index]);
  1217. }
  1218. TestParserSyncWithFlags(str, flags, result);
  1219. }
  1220. }
  1221. TEST(ParserSync) {
  1222. const char* context_data[][2] = {
  1223. { "", "" },
  1224. { "{", "}" },
  1225. { "if (true) ", " else {}" },
  1226. { "if (true) {} else ", "" },
  1227. { "if (true) ", "" },
  1228. { "do ", " while (false)" },
  1229. { "while (false) ", "" },
  1230. { "for (;;) ", "" },
  1231. { "with ({})", "" },
  1232. { "switch (12) { case 12: ", "}" },
  1233. { "switch (12) { default: ", "}" },
  1234. { "switch (12) { ", "case 12: }" },
  1235. { "label2: ", "" },
  1236. { NULL, NULL }
  1237. };
  1238. const char* statement_data[] = {
  1239. "{}",
  1240. "var x",
  1241. "var x = 1",
  1242. "const x",
  1243. "const x = 1",
  1244. ";",
  1245. "12",
  1246. "if (false) {} else ;",
  1247. "if (false) {} else {}",
  1248. "if (false) {} else 12",
  1249. "if (false) ;"
  1250. "if (false) {}",
  1251. "if (false) 12",
  1252. "do {} while (false)",
  1253. "for (;;) ;",
  1254. "for (;;) {}",
  1255. "for (;;) 12",
  1256. "continue",
  1257. "continue label",
  1258. "continue\nlabel",
  1259. "break",
  1260. "break label",
  1261. "break\nlabel",
  1262. // TODO(marja): activate once parsing 'return' is merged into ParserBase.
  1263. // "return",
  1264. // "return 12",
  1265. // "return\n12",
  1266. "with ({}) ;",
  1267. "with ({}) {}",
  1268. "with ({}) 12",
  1269. "switch ({}) { default: }"
  1270. "label3: "
  1271. "throw",
  1272. "throw 12",
  1273. "throw\n12",
  1274. "try {} catch(e) {}",
  1275. "try {} finally {}",
  1276. "try {} catch(e) {} finally {}",
  1277. "debugger",
  1278. NULL
  1279. };
  1280. const char* termination_data[] = {
  1281. "",
  1282. ";",
  1283. "\n",
  1284. ";\n",
  1285. "\n;",
  1286. NULL
  1287. };
  1288. v8::HandleScope handles(CcTest::isolate());
  1289. v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
  1290. v8::Context::Scope context_scope(context);
  1291. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  1292. 128 * 1024);
  1293. static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping,
  1294. kAllowModules, kAllowGenerators,
  1295. kAllowArrowFunctions};
  1296. for (int i = 0; context_data[i][0] != NULL; ++i) {
  1297. for (int j = 0; statement_data[j] != NULL; ++j) {
  1298. for (int k = 0; termination_data[k] != NULL; ++k) {
  1299. int kPrefixLen = i::StrLength(context_data[i][0]);
  1300. int kStatementLen = i::StrLength(statement_data[j]);
  1301. int kTerminationLen = i::StrLength(termination_data[k]);
  1302. int kSuffixLen = i::StrLength(context_data[i][1]);
  1303. int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
  1304. + kSuffixLen + i::StrLength("label: for (;;) { }");
  1305. // Plug the source code pieces together.
  1306. i::ScopedVector<char> program(kProgramSize + 1);
  1307. int length = i::SNPrintF(program,
  1308. "label: for (;;) { %s%s%s%s }",
  1309. context_data[i][0],
  1310. statement_data[j],
  1311. termination_data[k],
  1312. context_data[i][1]);
  1313. CHECK(length == kProgramSize);
  1314. TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1));
  1315. }
  1316. }
  1317. }
  1318. // Neither Harmony numeric literals nor our natives syntax have any
  1319. // interaction with the flags above, so test these separately to reduce
  1320. // the combinatorial explosion.
  1321. static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals };
  1322. TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2));
  1323. TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2));
  1324. static const ParserFlag flags3[] = { kAllowNativesSyntax };
  1325. TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3));
  1326. }
  1327. TEST(StrictOctal) {
  1328. // Test that syntax error caused by octal literal is reported correctly as
  1329. // such (issue 2220).
  1330. v8::V8::Initialize();
  1331. v8::HandleScope scope(CcTest::isolate());
  1332. v8::Context::Scope context_scope(
  1333. v8::Context::New(CcTest::isolate()));
  1334. v8::TryCatch try_catch;
  1335. const char* script =
  1336. "\"use strict\"; \n"
  1337. "a = function() { \n"
  1338. " b = function() { \n"
  1339. " 01; \n"
  1340. " }; \n"
  1341. "}; \n";
  1342. v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
  1343. CHECK(try_catch.HasCaught());
  1344. v8::String::Utf8Value exception(try_catch.Exception());
  1345. CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
  1346. *exception);
  1347. }
  1348. void RunParserSyncTest(const char* context_data[][2],
  1349. const char* statement_data[],
  1350. ParserSyncTestResult result,
  1351. const ParserFlag* flags = NULL,
  1352. int flags_len = 0,
  1353. const ParserFlag* always_true_flags = NULL,
  1354. int always_true_flags_len = 0) {
  1355. v8::HandleScope handles(CcTest::isolate());
  1356. v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
  1357. v8::Context::Scope context_scope(context);
  1358. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  1359. 128 * 1024);
  1360. static const ParserFlag default_flags[] = {
  1361. kAllowLazy, kAllowHarmonyScoping, kAllowModules,
  1362. kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions};
  1363. ParserFlag* generated_flags = NULL;
  1364. if (flags == NULL) {
  1365. flags = default_flags;
  1366. flags_len = ARRAY_SIZE(default_flags);
  1367. if (always_true_flags != NULL) {
  1368. // Remove always_true_flags from default_flags.
  1369. CHECK(always_true_flags_len < flags_len);
  1370. generated_flags = new ParserFlag[flags_len - always_true_flags_len];
  1371. int flag_index = 0;
  1372. for (int i = 0; i < flags_len; ++i) {
  1373. bool use_flag = true;
  1374. for (int j = 0; j < always_true_flags_len; ++j) {
  1375. if (flags[i] == always_true_flags[j]) {
  1376. use_flag = false;
  1377. break;
  1378. }
  1379. }
  1380. if (use_flag) generated_flags[flag_index++] = flags[i];
  1381. }
  1382. CHECK(flag_index == flags_len - always_true_flags_len);
  1383. flags_len = flag_index;
  1384. flags = generated_flags;
  1385. }
  1386. }
  1387. for (int i = 0; context_data[i][0] != NULL; ++i) {
  1388. for (int j = 0; statement_data[j] != NULL; ++j) {
  1389. int kPrefixLen = i::StrLength(context_data[i][0]);
  1390. int kStatementLen = i::StrLength(statement_data[j]);
  1391. int kSuffixLen = i::StrLength(context_data[i][1]);
  1392. int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
  1393. // Plug the source code pieces together.
  1394. i::ScopedVector<char> program(kProgramSize + 1);
  1395. int length = i::SNPrintF(program,
  1396. "%s%s%s",
  1397. context_data[i][0],
  1398. statement_data[j],
  1399. context_data[i][1]);
  1400. CHECK(length == kProgramSize);
  1401. TestParserSync(program.start(),
  1402. flags,
  1403. flags_len,
  1404. result,
  1405. always_true_flags,
  1406. always_true_flags_len);
  1407. }
  1408. }
  1409. delete[] generated_flags;
  1410. }
  1411. TEST(ErrorsEvalAndArguments) {
  1412. // Tests that both preparsing and parsing produce the right kind of errors for
  1413. // using "eval" and "arguments" as identifiers. Without the strict mode, it's
  1414. // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
  1415. // isn't.
  1416. const char* context_data[][2] = {
  1417. { "\"use strict\";", "" },
  1418. { "var eval; function test_func() {\"use strict\"; ", "}"},
  1419. { NULL, NULL }
  1420. };
  1421. const char* statement_data[] = {
  1422. "var eval;",
  1423. "var arguments",
  1424. "var foo, eval;",
  1425. "var foo, arguments;",
  1426. "try { } catch (eval) { }",
  1427. "try { } catch (arguments) { }",
  1428. "function eval() { }",
  1429. "function arguments() { }",
  1430. "function foo(eval) { }",
  1431. "function foo(arguments) { }",
  1432. "function foo(bar, eval) { }",
  1433. "function foo(bar, arguments) { }",
  1434. "(eval) => { }",
  1435. "(arguments) => { }",
  1436. "(foo, eval) => { }",
  1437. "(foo, arguments) => { }",
  1438. "eval = 1;",
  1439. "arguments = 1;",
  1440. "var foo = eval = 1;",
  1441. "var foo = arguments = 1;",
  1442. "++eval;",
  1443. "++arguments;",
  1444. "eval++;",
  1445. "arguments++;",
  1446. NULL
  1447. };
  1448. RunParserSyncTest(context_data, statement_data, kError);
  1449. }
  1450. TEST(NoErrorsEvalAndArgumentsSloppy) {
  1451. // Tests that both preparsing and parsing accept "eval" and "arguments" as
  1452. // identifiers when needed.
  1453. const char* context_data[][2] = {
  1454. { "", "" },
  1455. { "function test_func() {", "}"},
  1456. { NULL, NULL }
  1457. };
  1458. const char* statement_data[] = {
  1459. "var eval;",
  1460. "var arguments",
  1461. "var foo, eval;",
  1462. "var foo, arguments;",
  1463. "try { } catch (eval) { }",
  1464. "try { } catch (arguments) { }",
  1465. "function eval() { }",
  1466. "function arguments() { }",
  1467. "function foo(eval) { }",
  1468. "function foo(arguments) { }",
  1469. "function foo(bar, eval) { }",
  1470. "function foo(bar, arguments) { }",
  1471. "eval = 1;",
  1472. "arguments = 1;",
  1473. "var foo = eval = 1;",
  1474. "var foo = arguments = 1;",
  1475. "++eval;",
  1476. "++arguments;",
  1477. "eval++;",
  1478. "arguments++;",
  1479. NULL
  1480. };
  1481. RunParserSyncTest(context_data, statement_data, kSuccess);
  1482. }
  1483. TEST(NoErrorsEvalAndArgumentsStrict) {
  1484. const char* context_data[][2] = {
  1485. { "\"use strict\";", "" },
  1486. { "function test_func() { \"use strict\";", "}" },
  1487. { "() => { \"use strict\"; ", "}" },
  1488. { NULL, NULL }
  1489. };
  1490. const char* statement_data[] = {
  1491. "eval;",
  1492. "arguments;",
  1493. "var foo = eval;",
  1494. "var foo = arguments;",
  1495. "var foo = { eval: 1 };",
  1496. "var foo = { arguments: 1 };",
  1497. "var foo = { }; foo.eval = {};",
  1498. "var foo = { }; foo.arguments = {};",
  1499. NULL
  1500. };
  1501. static const ParserFlag always_flags[] = {kAllowArrowFunctions};
  1502. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1503. always_flags, ARRAY_SIZE(always_flags));
  1504. }
  1505. TEST(ErrorsFutureStrictReservedWords) {
  1506. // Tests that both preparsing and parsing produce the right kind of errors for
  1507. // using future strict reserved words as identifiers. Without the strict mode,
  1508. // it's ok to use future strict reserved words as identifiers. With the strict
  1509. // mode, it isn't.
  1510. const char* context_data[][2] = {
  1511. { "\"use strict\";", "" },
  1512. { "function test_func() {\"use strict\"; ", "}"},
  1513. { "() => { \"use strict\"; ", "}" },
  1514. { NULL, NULL }
  1515. };
  1516. const char* statement_data[] = {
  1517. "var interface;",
  1518. "var foo, interface;",
  1519. "try { } catch (interface) { }",
  1520. "function interface() { }",
  1521. "function foo(interface) { }",
  1522. "function foo(bar, interface) { }",
  1523. "interface = 1;",
  1524. "var foo = interface = 1;",
  1525. "++interface;",
  1526. "interface++;",
  1527. "var yield = 13;",
  1528. NULL
  1529. };
  1530. static const ParserFlag always_flags[] = {kAllowArrowFunctions};
  1531. RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
  1532. ARRAY_SIZE(always_flags));
  1533. }
  1534. TEST(NoErrorsFutureStrictReservedWords) {
  1535. const char* context_data[][2] = {
  1536. { "", "" },
  1537. { "function test_func() {", "}"},
  1538. { "() => {", "}" },
  1539. { NULL, NULL }
  1540. };
  1541. const char* statement_data[] = {
  1542. "var interface;",
  1543. "var foo, interface;",
  1544. "try { } catch (interface) { }",
  1545. "function interface() { }",
  1546. "function foo(interface) { }",
  1547. "function foo(bar, interface) { }",
  1548. "interface = 1;",
  1549. "var foo = interface = 1;",
  1550. "++interface;",
  1551. "interface++;",
  1552. "var yield = 13;",
  1553. NULL
  1554. };
  1555. static const ParserFlag always_flags[] = {kAllowArrowFunctions};
  1556. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1557. always_flags, ARRAY_SIZE(always_flags));
  1558. }
  1559. TEST(ErrorsReservedWords) {
  1560. // Tests that both preparsing and parsing produce the right kind of errors for
  1561. // using future reserved words as identifiers. These tests don't depend on the
  1562. // strict mode.
  1563. const char* context_data[][2] = {
  1564. { "", "" },
  1565. { "\"use strict\";", "" },
  1566. { "var eval; function test_func() {", "}"},
  1567. { "var eval; function test_func() {\"use strict\"; ", "}"},
  1568. { "var eval; () => {", "}"},
  1569. { "var eval; () => {\"use strict\"; ", "}"},
  1570. { NULL, NULL }
  1571. };
  1572. const char* statement_data[] = {
  1573. "var super;",
  1574. "var foo, super;",
  1575. "try { } catch (super) { }",
  1576. "function super() { }",
  1577. "function foo(super) { }",
  1578. "function foo(bar, super) { }",
  1579. "(super) => { }",
  1580. "(bar, super) => { }",
  1581. "super = 1;",
  1582. "var foo = super = 1;",
  1583. "++super;",
  1584. "super++;",
  1585. "function foo super",
  1586. NULL
  1587. };
  1588. RunParserSyncTest(context_data, statement_data, kError);
  1589. }
  1590. TEST(NoErrorsLetSloppyAllModes) {
  1591. // In sloppy mode, it's okay to use "let" as identifier.
  1592. const char* context_data[][2] = {
  1593. { "", "" },
  1594. { "function f() {", "}" },
  1595. { "(function f() {", "})" },
  1596. { NULL, NULL }
  1597. };
  1598. const char* statement_data[] = {
  1599. "var let;",
  1600. "var foo, let;",
  1601. "try { } catch (let) { }",
  1602. "function let() { }",
  1603. "(function let() { })",
  1604. "function foo(let) { }",
  1605. "function foo(bar, let) { }",
  1606. "let = 1;",
  1607. "var foo = let = 1;",
  1608. "let * 2;",
  1609. "++let;",
  1610. "let++;",
  1611. "let: 34",
  1612. "function let(let) { let: let(let + let(0)); }",
  1613. "({ let: 1 })",
  1614. "({ get let() { 1 } })",
  1615. "let(100)",
  1616. NULL
  1617. };
  1618. RunParserSyncTest(context_data, statement_data, kSuccess);
  1619. }
  1620. TEST(NoErrorsYieldSloppyAllModes) {
  1621. // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
  1622. // generator (see other test).
  1623. const char* context_data[][2] = {
  1624. { "", "" },
  1625. { "function not_gen() {", "}" },
  1626. { "(function not_gen() {", "})" },
  1627. { NULL, NULL }
  1628. };
  1629. const char* statement_data[] = {
  1630. "var yield;",
  1631. "var foo, yield;",
  1632. "try { } catch (yield) { }",
  1633. "function yield() { }",
  1634. "(function yield() { })",
  1635. "function foo(yield) { }",
  1636. "function foo(bar, yield) { }",
  1637. "yield = 1;",
  1638. "var foo = yield = 1;",
  1639. "yield * 2;",
  1640. "++yield;",
  1641. "yield++;",
  1642. "yield: 34",
  1643. "function yield(yield) { yield: yield (yield + yield(0)); }",
  1644. "({ yield: 1 })",
  1645. "({ get yield() { 1 } })",
  1646. "yield(100)",
  1647. "yield[100]",
  1648. NULL
  1649. };
  1650. RunParserSyncTest(context_data, statement_data, kSuccess);
  1651. }
  1652. TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
  1653. // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
  1654. // generator (see next test).
  1655. const char* context_data[][2] = {
  1656. { "", "" },
  1657. { "function not_gen() {", "}" },
  1658. { "function * gen() { function not_gen() {", "} }" },
  1659. { "(function not_gen() {", "})" },
  1660. { "(function * gen() { (function not_gen() {", "}) })" },
  1661. { NULL, NULL }
  1662. };
  1663. const char* statement_data[] = {
  1664. "var yield;",
  1665. "var foo, yield;",
  1666. "try { } catch (yield) { }",
  1667. "function yield() { }",
  1668. "(function yield() { })",
  1669. "function foo(yield) { }",
  1670. "function foo(bar, yield) { }",
  1671. "function * yield() { }",
  1672. "(function * yield() { })",
  1673. "yield = 1;",
  1674. "var foo = yield = 1;",
  1675. "yield * 2;",
  1676. "++yield;",
  1677. "yield++;",
  1678. "yield: 34",
  1679. "function yield(yield) { yield: yield (yield + yield(0)); }",
  1680. "({ yield: 1 })",
  1681. "({ get yield() { 1 } })",
  1682. "yield(100)",
  1683. "yield[100]",
  1684. NULL
  1685. };
  1686. // This test requires kAllowGenerators to succeed.
  1687. static const ParserFlag always_true_flags[] = { kAllowGenerators };
  1688. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1689. always_true_flags, 1);
  1690. }
  1691. TEST(ErrorsYieldStrict) {
  1692. const char* context_data[][2] = {
  1693. { "\"use strict\";", "" },
  1694. { "\"use strict\"; function not_gen() {", "}" },
  1695. { "function test_func() {\"use strict\"; ", "}"},
  1696. { "\"use strict\"; function * gen() { function not_gen() {", "} }" },
  1697. { "\"use strict\"; (function not_gen() {", "})" },
  1698. { "\"use strict\"; (function * gen() { (function not_gen() {", "}) })" },
  1699. { "() => {\"use strict\"; ", "}" },
  1700. { NULL, NULL }
  1701. };
  1702. const char* statement_data[] = {
  1703. "var yield;",
  1704. "var foo, yield;",
  1705. "try { } catch (yield) { }",
  1706. "function yield() { }",
  1707. "(function yield() { })",
  1708. "function foo(yield) { }",
  1709. "function foo(bar, yield) { }",
  1710. "function * yield() { }",
  1711. "(function * yield() { })",
  1712. "yield = 1;",
  1713. "var foo = yield = 1;",
  1714. "++yield;",
  1715. "yield++;",
  1716. "yield: 34;",
  1717. NULL
  1718. };
  1719. RunParserSyncTest(context_data, statement_data, kError);
  1720. }
  1721. TEST(NoErrorsGenerator) {
  1722. const char* context_data[][2] = {
  1723. { "function * gen() {", "}" },
  1724. { "(function * gen() {", "})" },
  1725. { "(function * () {", "})" },
  1726. { NULL, NULL }
  1727. };
  1728. const char* statement_data[] = {
  1729. // A generator without a body is valid.
  1730. ""
  1731. // Valid yield expressions inside generators.
  1732. "yield 2;",
  1733. "yield * 2;",
  1734. "yield * \n 2;",
  1735. "yield yield 1;",
  1736. "yield * yield * 1;",
  1737. "yield 3 + (yield 4);",
  1738. "yield * 3 + (yield * 4);",
  1739. "(yield * 3) + (yield * 4);",
  1740. "yield 3; yield 4;",
  1741. "yield * 3; yield * 4;",
  1742. "(function (yield) { })",
  1743. "yield { yield: 12 }",
  1744. "yield /* comment */ { yield: 12 }",
  1745. "yield * \n { yield: 12 }",
  1746. "yield /* comment */ * \n { yield: 12 }",
  1747. // You can return in a generator.
  1748. "yield 1; return",
  1749. "yield * 1; return",
  1750. "yield 1; return 37",
  1751. "yield * 1; return 37",
  1752. "yield 1; return 37; yield 'dead';",
  1753. "yield * 1; return 37; yield * 'dead';",
  1754. // Yield is still a valid key in object literals.
  1755. "({ yield: 1 })",
  1756. "({ get yield() { } })",
  1757. // Yield without RHS.
  1758. "yield;",
  1759. "yield",
  1760. "yield\n",
  1761. "yield /* comment */"
  1762. "yield // comment\n"
  1763. "(yield)",
  1764. "[yield]",
  1765. "{yield}",
  1766. "yield, yield",
  1767. "yield; yield",
  1768. "(yield) ? yield : yield",
  1769. "(yield) \n ? yield : yield",
  1770. // If there is a newline before the next token, we don't look for RHS.
  1771. "yield\nfor (;;) {}",
  1772. NULL
  1773. };
  1774. // This test requires kAllowGenerators to succeed.
  1775. static const ParserFlag always_true_flags[] = {
  1776. kAllowGenerators
  1777. };
  1778. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1779. always_true_flags, 1);
  1780. }
  1781. TEST(ErrorsYieldGenerator) {
  1782. const char* context_data[][2] = {
  1783. { "function * gen() {", "}" },
  1784. { "\"use strict\"; function * gen() {", "}" },
  1785. { NULL, NULL }
  1786. };
  1787. const char* statement_data[] = {
  1788. // Invalid yield expressions inside generators.
  1789. "var yield;",
  1790. "var foo, yield;",
  1791. "try { } catch (yield) { }",
  1792. "function yield() { }",
  1793. // The name of the NFE is let-bound in the generator, which does not permit
  1794. // yield to be an identifier.
  1795. "(function yield() { })",
  1796. "(function * yield() { })",
  1797. // Yield isn't valid as a formal parameter for generators.
  1798. "function * foo(yield) { }",
  1799. "(function * foo(yield) { })",
  1800. "yield = 1;",
  1801. "var foo = yield = 1;",
  1802. "++yield;",
  1803. "yield++;",
  1804. "yield *",
  1805. "(yield *)",
  1806. // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
  1807. // is invalid.
  1808. "yield 3 + yield 4;",
  1809. "yield: 34",
  1810. "yield ? 1 : 2",
  1811. // Parses as yield (/ yield): invalid.
  1812. "yield / yield",
  1813. "+ yield",
  1814. "+ yield 3",
  1815. // Invalid (no newline allowed between yield and *).
  1816. "yield\n*3",
  1817. // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
  1818. // object literal, and yield is not a valid label).
  1819. "yield\n{yield: 42}",
  1820. "yield /* comment */\n {yield: 42}",
  1821. "yield //comment\n {yield: 42}",
  1822. NULL
  1823. };
  1824. RunParserSyncTest(context_data, statement_data, kError);
  1825. }
  1826. TEST(ErrorsNameOfStrictFunction) {
  1827. // Tests that illegal tokens as names of a strict function produce the correct
  1828. // errors.
  1829. const char* context_data[][2] = {
  1830. { "function ", ""},
  1831. { "\"use strict\"; function", ""},
  1832. { "function * ", ""},
  1833. { "\"use strict\"; function * ", ""},
  1834. { NULL, NULL }
  1835. };
  1836. const char* statement_data[] = {
  1837. "eval() {\"use strict\";}",
  1838. "arguments() {\"use strict\";}",
  1839. "interface() {\"use strict\";}",
  1840. "yield() {\"use strict\";}",
  1841. // Future reserved words are always illegal
  1842. "function super() { }",
  1843. "function super() {\"use strict\";}",
  1844. NULL
  1845. };
  1846. RunParserSyncTest(context_data, statement_data, kError);
  1847. }
  1848. TEST(NoErrorsNameOfStrictFunction) {
  1849. const char* context_data[][2] = {
  1850. { "function ", ""},
  1851. { NULL, NULL }
  1852. };
  1853. const char* statement_data[] = {
  1854. "eval() { }",
  1855. "arguments() { }",
  1856. "interface() { }",
  1857. "yield() { }",
  1858. NULL
  1859. };
  1860. RunParserSyncTest(context_data, statement_data, kSuccess);
  1861. }
  1862. TEST(NoErrorsNameOfStrictGenerator) {
  1863. const char* context_data[][2] = {
  1864. { "function * ", ""},
  1865. { NULL, NULL }
  1866. };
  1867. const char* statement_data[] = {
  1868. "eval() { }",
  1869. "arguments() { }",
  1870. "interface() { }",
  1871. "yield() { }",
  1872. NULL
  1873. };
  1874. // This test requires kAllowGenerators to succeed.
  1875. static const ParserFlag always_true_flags[] = {
  1876. kAllowGenerators
  1877. };
  1878. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1879. always_true_flags, 1);
  1880. }
  1881. TEST(ErrorsIllegalWordsAsLabelsSloppy) {
  1882. // Using future reserved words as labels is always an error.
  1883. const char* context_data[][2] = {
  1884. { "", ""},
  1885. { "function test_func() {", "}" },
  1886. { "() => {", "}" },
  1887. { NULL, NULL }
  1888. };
  1889. const char* statement_data[] = {
  1890. "super: while(true) { break super; }",
  1891. NULL
  1892. };
  1893. RunParserSyncTest(context_data, statement_data, kError);
  1894. }
  1895. TEST(ErrorsIllegalWordsAsLabelsStrict) {
  1896. // Tests that illegal tokens as labels produce the correct errors.
  1897. const char* context_data[][2] = {
  1898. { "\"use strict\";", "" },
  1899. { "function test_func() {\"use strict\"; ", "}"},
  1900. { "() => {\"use strict\"; ", "}" },
  1901. { NULL, NULL }
  1902. };
  1903. const char* statement_data[] = {
  1904. "super: while(true) { break super; }",
  1905. "interface: while(true) { break interface; }",
  1906. "yield: while(true) { break yield; }",
  1907. NULL
  1908. };
  1909. RunParserSyncTest(context_data, statement_data, kError);
  1910. }
  1911. TEST(NoErrorsIllegalWordsAsLabels) {
  1912. // Using eval and arguments as labels is legal even in strict mode.
  1913. const char* context_data[][2] = {
  1914. { "", ""},
  1915. { "function test_func() {", "}" },
  1916. { "() => {", "}" },
  1917. { "\"use strict\";", "" },
  1918. { "\"use strict\"; function test_func() {", "}" },
  1919. { "\"use strict\"; () => {", "}" },
  1920. { NULL, NULL }
  1921. };
  1922. const char* statement_data[] = {
  1923. "mylabel: while(true) { break mylabel; }",
  1924. "eval: while(true) { break eval; }",
  1925. "arguments: while(true) { break arguments; }",
  1926. NULL
  1927. };
  1928. static const ParserFlag always_flags[] = {kAllowArrowFunctions};
  1929. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  1930. always_flags, ARRAY_SIZE(always_flags));
  1931. }
  1932. TEST(ErrorsParenthesizedLabels) {
  1933. // Parenthesized identifiers shouldn't be recognized as labels.
  1934. const char* context_data[][2] = {
  1935. { "", ""},
  1936. { "function test_func() {", "}" },
  1937. { "() => {", "}" },
  1938. { NULL, NULL }
  1939. };
  1940. const char* statement_data[] = {
  1941. "(mylabel): while(true) { break mylabel; }",
  1942. NULL
  1943. };
  1944. RunParserSyncTest(context_data, statement_data, kError);
  1945. }
  1946. TEST(NoErrorsParenthesizedDirectivePrologue) {
  1947. // Parenthesized directive prologue shouldn't be recognized.
  1948. const char* context_data[][2] = {
  1949. { "", ""},
  1950. { NULL, NULL }
  1951. };
  1952. const char* statement_data[] = {
  1953. "(\"use strict\"); var eval;",
  1954. NULL
  1955. };
  1956. RunParserSyncTest(context_data, statement_data, kSuccess);
  1957. }
  1958. TEST(ErrorsNotAnIdentifierName) {
  1959. const char* context_data[][2] = {
  1960. { "", ""},
  1961. { "\"use strict\";", ""},
  1962. { NULL, NULL }
  1963. };
  1964. const char* statement_data[] = {
  1965. "var foo = {}; foo.{;",
  1966. "var foo = {}; foo.};",
  1967. "var foo = {}; foo.=;",
  1968. "var foo = {}; foo.888;",
  1969. "var foo = {}; foo.-;",
  1970. "var foo = {}; foo.--;",
  1971. NULL
  1972. };
  1973. RunParserSyncTest(context_data, statement_data, kError);
  1974. }
  1975. TEST(NoErrorsIdentifierNames) {
  1976. // Keywords etc. are valid as property names.
  1977. const char* context_data[][2] = {
  1978. { "", ""},
  1979. { "\"use strict\";", ""},
  1980. { NULL, NULL }
  1981. };
  1982. const char* statement_data[] = {
  1983. "var foo = {}; foo.if;",
  1984. "var foo = {}; foo.yield;",
  1985. "var foo = {}; foo.super;",
  1986. "var foo = {}; foo.interface;",
  1987. "var foo = {}; foo.eval;",
  1988. "var foo = {}; foo.arguments;",
  1989. NULL
  1990. };
  1991. RunParserSyncTest(context_data, statement_data, kSuccess);
  1992. }
  1993. TEST(DontRegressPreParserDataSizes) {
  1994. // These tests make sure that Parser doesn't start producing less "preparse
  1995. // data" (data which the embedder can cache).
  1996. v8::V8::Initialize();
  1997. v8::Isolate* isolate = CcTest::isolate();
  1998. v8::HandleScope handles(isolate);
  1999. CcTest::i_isolate()->stack_guard()->SetStackLimit(GetCurrentStackPosition() -
  2000. 128 * 1024);
  2001. struct TestCase {
  2002. const char* program;
  2003. int functions;
  2004. } test_cases[] = {
  2005. // No functions.
  2006. {"var x = 42;", 0},
  2007. // Functions.
  2008. {"function foo() {}", 1}, {"function foo() {} function bar() {}", 2},
  2009. // Getter / setter functions are recorded as functions if they're on the top
  2010. // level.
  2011. {"var x = {get foo(){} };", 1},
  2012. // Functions insize lazy functions are not recorded.
  2013. {"function lazy() { function a() {} function b() {} function c() {} }", 1},
  2014. {"function lazy() { var x = {get foo(){} } }", 1},
  2015. {NULL, 0}
  2016. };
  2017. for (int i = 0; test_cases[i].program; i++) {
  2018. const char* program = test_cases[i].program;
  2019. i::Factory* factory = CcTest::i_isolate()->factory();
  2020. i::Handle<i::String> source =
  2021. factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
  2022. i::Handle<i::Script> script = factory->NewScript(source);
  2023. i::CompilationInfoWithZone info(script);
  2024. i::ScriptData* sd = NULL;
  2025. info.SetCachedData(&sd, v8::ScriptCompiler::kProduceParserCache);
  2026. i::Parser::Parse(&info, true);
  2027. i::ParseData pd(sd);
  2028. if (pd.FunctionCount() != test_cases[i].functions) {
  2029. v8::base::OS::Print(
  2030. "Expected preparse data for program:\n"
  2031. "\t%s\n"
  2032. "to contain %d functions, however, received %d functions.\n",
  2033. program, test_cases[i].functions, pd.FunctionCount());
  2034. CHECK(false);
  2035. }
  2036. delete sd;
  2037. }
  2038. }
  2039. TEST(FunctionDeclaresItselfStrict) {
  2040. // Tests that we produce the right kinds of errors when a function declares
  2041. // itself strict (we cannot produce there errors as soon as we see the
  2042. // offending identifiers, because we don't know at that point whether the
  2043. // function is strict or not).
  2044. const char* context_data[][2] = {
  2045. {"function eval() {", "}"},
  2046. {"function arguments() {", "}"},
  2047. {"function yield() {", "}"},
  2048. {"function interface() {", "}"},
  2049. {"function foo(eval) {", "}"},
  2050. {"function foo(arguments) {", "}"},
  2051. {"function foo(yield) {", "}"},
  2052. {"function foo(interface) {", "}"},
  2053. {"function foo(bar, eval) {", "}"},
  2054. {"function foo(bar, arguments) {", "}"},
  2055. {"function foo(bar, yield) {", "}"},
  2056. {"function foo(bar, interface) {", "}"},
  2057. {"function foo(bar, bar) {", "}"},
  2058. { NULL, NULL }
  2059. };
  2060. const char* strict_statement_data[] = {
  2061. "\"use strict\";",
  2062. NULL
  2063. };
  2064. const char* non_strict_statement_data[] = {
  2065. ";",
  2066. NULL
  2067. };
  2068. RunParserSyncTest(context_data, strict_statement_data, kError);
  2069. RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
  2070. }
  2071. TEST(ErrorsTryWithoutCatchOrFinally) {
  2072. const char* context_data[][2] = {
  2073. {"", ""},
  2074. { NULL, NULL }
  2075. };
  2076. const char* statement_data[] = {
  2077. "try { }",
  2078. "try { } foo();",
  2079. "try { } catch (e) foo();",
  2080. "try { } catch { }",
  2081. "try { } finally foo();",
  2082. NULL
  2083. };
  2084. RunParserSyncTest(context_data, statement_data, kError);
  2085. }
  2086. TEST(NoErrorsTryCatchFinally) {
  2087. const char* context_data[][2] = {
  2088. {"", ""},
  2089. { NULL, NULL }
  2090. };
  2091. const char* statement_data[] = {
  2092. "try { } catch (e) { }",
  2093. "try { } catch (e) { } finally { }",
  2094. "try { } finally { }",
  2095. NULL
  2096. };
  2097. RunParserSyncTest(context_data, statement_data, kSuccess);
  2098. }
  2099. TEST(ErrorsRegexpLiteral) {
  2100. const char* context_data[][2] = {
  2101. {"var r = ", ""},
  2102. { NULL, NULL }
  2103. };
  2104. const char* statement_data[] = {
  2105. "/unterminated",
  2106. NULL
  2107. };
  2108. RunParserSyncTest(context_data, statement_data, kError);
  2109. }
  2110. TEST(NoErrorsRegexpLiteral) {
  2111. const char* context_data[][2] = {
  2112. {"var r = ", ""},
  2113. { NULL, NULL }
  2114. };
  2115. const char* statement_data[] = {
  2116. "/foo/",
  2117. "/foo/g",
  2118. "/foo/whatever", // This is an error but not detected by the parser.
  2119. NULL
  2120. };
  2121. RunParserSyncTest(context_data, statement_data, kSuccess);
  2122. }
  2123. TEST(Intrinsics) {
  2124. const char* context_data[][2] = {
  2125. {"", ""},
  2126. { NULL, NULL }
  2127. };
  2128. const char* statement_data[] = {
  2129. "%someintrinsic(arg)",
  2130. NULL
  2131. };
  2132. // This test requires kAllowNativesSyntax to succeed.
  2133. static const ParserFlag always_true_flags[] = {
  2134. kAllowNativesSyntax
  2135. };
  2136. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  2137. always_true_flags, 1);
  2138. }
  2139. TEST(NoErrorsNewExpression) {
  2140. const char* context_data[][2] = {
  2141. {"", ""},
  2142. {"var f =", ""},
  2143. { NULL, NULL }
  2144. };
  2145. const char* statement_data[] = {
  2146. "new foo",
  2147. "new foo();",
  2148. "new foo(1);",
  2149. "new foo(1, 2);",
  2150. // The first () will be processed as a part of the NewExpression and the
  2151. // second () will be processed as part of LeftHandSideExpression.
  2152. "new foo()();",
  2153. // The first () will be processed as a part of the inner NewExpression and
  2154. // the second () will be processed as a part of the outer NewExpression.
  2155. "new new foo()();",
  2156. "new foo.bar;",
  2157. "new foo.bar();",
  2158. "new foo.bar.baz;",
  2159. "new foo.bar().baz;",
  2160. "new foo[bar];",
  2161. "new foo[bar]();",
  2162. "new foo[bar][baz];",
  2163. "new foo[bar]()[baz];",
  2164. "new foo[bar].baz(baz)()[bar].baz;",
  2165. "new \"foo\"", // Runtime error
  2166. "new 1", // Runtime error
  2167. // This even runs:
  2168. "(new new Function(\"this.x = 1\")).x;",
  2169. "new new Test_Two(String, 2).v(0123).length;",
  2170. NULL
  2171. };
  2172. RunParserSyncTest(context_data, statement_data, kSuccess);
  2173. }
  2174. TEST(ErrorsNewExpression) {
  2175. const char* context_data[][2] = {
  2176. {"", ""},
  2177. {"var f =", ""},
  2178. { NULL, NULL }
  2179. };
  2180. const char* statement_data[] = {
  2181. "new foo bar",
  2182. "new ) foo",
  2183. "new ++foo",
  2184. "new foo ++",
  2185. NULL
  2186. };
  2187. RunParserSyncTest(context_data, statement_data, kError);
  2188. }
  2189. TEST(StrictObjectLiteralChecking) {
  2190. const char* strict_context_data[][2] = {
  2191. {"\"use strict\"; var myobject = {", "};"},
  2192. {"\"use strict\"; var myobject = {", ",};"},
  2193. { NULL, NULL }
  2194. };
  2195. const char* non_strict_context_data[][2] = {
  2196. {"var myobject = {", "};"},
  2197. {"var myobject = {", ",};"},
  2198. { NULL, NULL }
  2199. };
  2200. // These are only errors in strict mode.
  2201. const char* statement_data[] = {
  2202. "foo: 1, foo: 2",
  2203. "\"foo\": 1, \"foo\": 2",
  2204. "foo: 1, \"foo\": 2",
  2205. "1: 1, 1: 2",
  2206. "1: 1, \"1\": 2",
  2207. "get: 1, get: 2", // Not a getter for real, just a property called get.
  2208. "set: 1, set: 2", // Not a setter for real, just a property called set.
  2209. NULL
  2210. };
  2211. RunParserSyncTest(non_strict_context_data, statement_data, kSuccess);
  2212. RunParserSyncTest(strict_context_data, statement_data, kError);
  2213. }
  2214. TEST(ErrorsObjectLiteralChecking) {
  2215. const char* context_data[][2] = {
  2216. {"\"use strict\"; var myobject = {", "};"},
  2217. {"var myobject = {", "};"},
  2218. { NULL, NULL }
  2219. };
  2220. const char* statement_data[] = {
  2221. ",",
  2222. "foo: 1, get foo() {}",
  2223. "foo: 1, set foo(v) {}",
  2224. "\"foo\": 1, get \"foo\"() {}",
  2225. "\"foo\": 1, set \"foo\"(v) {}",
  2226. "1: 1, get 1() {}",
  2227. "1: 1, set 1() {}",
  2228. // It's counter-intuitive, but these collide too (even in classic
  2229. // mode). Note that we can have "foo" and foo as properties in classic mode,
  2230. // but we cannot have "foo" and get foo, or foo and get "foo".
  2231. "foo: 1, get \"foo\"() {}",
  2232. "foo: 1, set \"foo\"(v) {}",
  2233. "\"foo\": 1, get foo() {}",
  2234. "\"foo\": 1, set foo(v) {}",
  2235. "1: 1, get \"1\"() {}",
  2236. "1: 1, set \"1\"() {}",
  2237. "\"1\": 1, get 1() {}"
  2238. "\"1\": 1, set 1(v) {}"
  2239. // Wrong number of parameters
  2240. "get bar(x) {}",
  2241. "get bar(x, y) {}",
  2242. "set bar() {}",
  2243. "set bar(x, y) {}",
  2244. // Parsing FunctionLiteral for getter or setter fails
  2245. "get foo( +",
  2246. "get foo() \"error\"",
  2247. NULL
  2248. };
  2249. RunParserSyncTest(context_data, statement_data, kError);
  2250. }
  2251. TEST(NoErrorsObjectLiteralChecking) {
  2252. const char* context_data[][2] = {
  2253. {"var myobject = {", "};"},
  2254. {"var myobject = {", ",};"},
  2255. {"\"use strict\"; var myobject = {", "};"},
  2256. {"\"use strict\"; var myobject = {", ",};"},
  2257. { NULL, NULL }
  2258. };
  2259. const char* statement_data[] = {
  2260. "foo: 1, bar: 2",
  2261. "\"foo\": 1, \"bar\": 2",
  2262. "1: 1, 2: 2",
  2263. // Syntax: IdentifierName ':' AssignmentExpression
  2264. "foo: bar = 5 + baz",
  2265. // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
  2266. "get foo() {}",
  2267. "get \"foo\"() {}",
  2268. "get 1() {}",
  2269. // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
  2270. // '{' FunctionBody '}'
  2271. "set foo(v) {}",
  2272. "set \"foo\"(v) {}",
  2273. "set 1(v) {}",
  2274. // Non-colliding getters and setters -> no errors
  2275. "foo: 1, get bar() {}",
  2276. "foo: 1, set bar(v) {}",
  2277. "\"foo\": 1, get \"bar\"() {}",
  2278. "\"foo\": 1, set \"bar\"(v) {}",
  2279. "1: 1, get 2() {}",
  2280. "1: 1, set 2(v) {}",
  2281. // Keywords, future reserved and strict future reserved are also allowed as
  2282. // property names.
  2283. "if: 4",
  2284. "interface: 5",
  2285. "super: 6",
  2286. "eval: 7",
  2287. "arguments: 8",
  2288. NULL
  2289. };
  2290. RunParserSyncTest(context_data, statement_data, kSuccess);
  2291. }
  2292. TEST(TooManyArguments) {
  2293. const char* context_data[][2] = {
  2294. {"foo(", "0)"},
  2295. { NULL, NULL }
  2296. };
  2297. using v8::internal::Code;
  2298. char statement[Code::kMaxArguments * 2 + 1];
  2299. for (int i = 0; i < Code::kMaxArguments; ++i) {
  2300. statement[2 * i] = '0';
  2301. statement[2 * i + 1] = ',';
  2302. }
  2303. statement[Code::kMaxArguments * 2] = 0;
  2304. const char* statement_data[] = {
  2305. statement,
  2306. NULL
  2307. };
  2308. // The test is quite slow, so run it with a reduced set of flags.
  2309. static const ParserFlag empty_flags[] = {kAllowLazy};
  2310. RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
  2311. }
  2312. TEST(StrictDelete) {
  2313. // "delete <Identifier>" is not allowed in strict mode.
  2314. const char* strict_context_data[][2] = {
  2315. {"\"use strict\"; ", ""},
  2316. { NULL, NULL }
  2317. };
  2318. const char* sloppy_context_data[][2] = {
  2319. {"", ""},
  2320. { NULL, NULL }
  2321. };
  2322. // These are errors in the strict mode.
  2323. const char* sloppy_statement_data[] = {
  2324. "delete foo;",
  2325. "delete foo + 1;",
  2326. "delete (foo);",
  2327. "delete eval;",
  2328. "delete interface;",
  2329. NULL
  2330. };
  2331. // These are always OK
  2332. const char* good_statement_data[] = {
  2333. "delete this;",
  2334. "delete 1;",
  2335. "delete 1 + 2;",
  2336. "delete foo();",
  2337. "delete foo.bar;",
  2338. "delete foo[bar];",
  2339. "delete foo--;",
  2340. "delete --foo;",
  2341. "delete new foo();",
  2342. "delete new foo(bar);",
  2343. NULL
  2344. };
  2345. // These are always errors
  2346. const char* bad_statement_data[] = {
  2347. "delete if;",
  2348. NULL
  2349. };
  2350. RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
  2351. RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
  2352. RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
  2353. RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
  2354. RunParserSyncTest(strict_context_data, bad_statement_data, kError);
  2355. RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
  2356. }
  2357. TEST(InvalidLeftHandSide) {
  2358. const char* assignment_context_data[][2] = {
  2359. {"", " = 1;"},
  2360. {"\"use strict\"; ", " = 1;"},
  2361. { NULL, NULL }
  2362. };
  2363. const char* prefix_context_data[][2] = {
  2364. {"++", ";"},
  2365. {"\"use strict\"; ++", ";"},
  2366. {NULL, NULL},
  2367. };
  2368. const char* postfix_context_data[][2] = {
  2369. {"", "++;"},
  2370. {"\"use strict\"; ", "++;"},
  2371. { NULL, NULL }
  2372. };
  2373. // Good left hand sides for assigment or prefix / postfix operations.
  2374. const char* good_statement_data[] = {
  2375. "foo",
  2376. "foo.bar",
  2377. "foo[bar]",
  2378. "foo()[bar]",
  2379. "foo().bar",
  2380. "this.foo",
  2381. "this[foo]",
  2382. "new foo()[bar]",
  2383. "new foo().bar",
  2384. "foo()",
  2385. "foo(bar)",
  2386. "foo[bar]()",
  2387. "foo.bar()",
  2388. "this()",
  2389. "this.foo()",
  2390. "this[foo].bar()",
  2391. "this.foo[foo].bar(this)(bar)[foo]()",
  2392. NULL
  2393. };
  2394. // Bad left hand sides for assigment or prefix / postfix operations.
  2395. const char* bad_statement_data_common[] = {
  2396. "2",
  2397. "new foo",
  2398. "new foo()",
  2399. "null",
  2400. "if", // Unexpected token
  2401. "{x: 1}", // Unexpected token
  2402. "this",
  2403. "\"bar\"",
  2404. "(foo + bar)",
  2405. "new new foo()[bar]", // means: new (new foo()[bar])
  2406. "new new foo().bar", // means: new (new foo()[bar])
  2407. NULL
  2408. };
  2409. // These are not okay for assignment, but okay for prefix / postix.
  2410. const char* bad_statement_data_for_assignment[] = {
  2411. "++foo",
  2412. "foo++",
  2413. "foo + bar",
  2414. NULL
  2415. };
  2416. RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
  2417. RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
  2418. RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
  2419. kError);
  2420. RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
  2421. RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
  2422. RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
  2423. RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
  2424. }
  2425. TEST(FuncNameInferrerBasic) {
  2426. // Tests that function names are inferred properly.
  2427. i::FLAG_allow_natives_syntax = true;
  2428. v8::Isolate* isolate = CcTest::isolate();
  2429. v8::HandleScope scope(isolate);
  2430. LocalContext env;
  2431. CompileRun("var foo1 = function() {}; "
  2432. "var foo2 = function foo3() {}; "
  2433. "function not_ctor() { "
  2434. " var foo4 = function() {}; "
  2435. " return %FunctionGetInferredName(foo4); "
  2436. "} "
  2437. "function Ctor() { "
  2438. " var foo5 = function() {}; "
  2439. " return %FunctionGetInferredName(foo5); "
  2440. "} "
  2441. "var obj1 = { foo6: function() {} }; "
  2442. "var obj2 = { 'foo7': function() {} }; "
  2443. "var obj3 = {}; "
  2444. "obj3[1] = function() {}; "
  2445. "var obj4 = {}; "
  2446. "obj4[1] = function foo8() {}; "
  2447. "var obj5 = {}; "
  2448. "obj5['foo9'] = function() {}; "
  2449. "var obj6 = { obj7 : { foo10: function() {} } };");
  2450. ExpectString("%FunctionGetInferredName(foo1)", "foo1");
  2451. // foo2 is not unnamed -> its name is not inferred.
  2452. ExpectString("%FunctionGetInferredName(foo2)", "");
  2453. ExpectString("not_ctor()", "foo4");
  2454. ExpectString("Ctor()", "Ctor.foo5");
  2455. ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
  2456. ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
  2457. ExpectString("%FunctionGetInferredName(obj3[1])",
  2458. "obj3.(anonymous function)");
  2459. ExpectString("%FunctionGetInferredName(obj4[1])", "");
  2460. ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
  2461. ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
  2462. }
  2463. TEST(FuncNameInferrerTwoByte) {
  2464. // Tests function name inferring in cases where some parts of the inferred
  2465. // function name are two-byte strings.
  2466. i::FLAG_allow_natives_syntax = true;
  2467. v8::Isolate* isolate = CcTest::isolate();
  2468. v8::HandleScope scope(isolate);
  2469. LocalContext env;
  2470. uint16_t* two_byte_source = AsciiToTwoByteString(
  2471. "var obj1 = { oXj2 : { foo1: function() {} } }; "
  2472. "%FunctionGetInferredName(obj1.oXj2.foo1)");
  2473. uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
  2474. // Make it really non-ASCII (replace the Xs with a non-ASCII character).
  2475. two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
  2476. v8::Local<v8::String> source =
  2477. v8::String::NewFromTwoByte(isolate, two_byte_source);
  2478. v8::Local<v8::Value> result = CompileRun(source);
  2479. CHECK(result->IsString());
  2480. v8::Local<v8::String> expected_name =
  2481. v8::String::NewFromTwoByte(isolate, two_byte_name);
  2482. CHECK(result->Equals(expected_name));
  2483. i::DeleteArray(two_byte_source);
  2484. i::DeleteArray(two_byte_name);
  2485. }
  2486. TEST(FuncNameInferrerEscaped) {
  2487. // The same as FuncNameInferrerTwoByte, except that we express the two-byte
  2488. // character as a unicode escape.
  2489. i::FLAG_allow_natives_syntax = true;
  2490. v8::Isolate* isolate = CcTest::isolate();
  2491. v8::HandleScope scope(isolate);
  2492. LocalContext env;
  2493. uint16_t* two_byte_source = AsciiToTwoByteString(
  2494. "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
  2495. "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
  2496. uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
  2497. // Fix to correspond to the non-ASCII name in two_byte_source.
  2498. two_byte_name[6] = 0x010d;
  2499. v8::Local<v8::String> source =
  2500. v8::String::NewFromTwoByte(isolate, two_byte_source);
  2501. v8::Local<v8::Value> result = CompileRun(source);
  2502. CHECK(result->IsString());
  2503. v8::Local<v8::String> expected_name =
  2504. v8::String::NewFromTwoByte(isolate, two_byte_name);
  2505. CHECK(result->Equals(expected_name));
  2506. i::DeleteArray(two_byte_source);
  2507. i::DeleteArray(two_byte_name);
  2508. }
  2509. TEST(RegressionLazyFunctionWithErrorWithArg) {
  2510. // The bug occurred when a lazy function had an error which requires a
  2511. // parameter (such as "unknown label" here). The error message was processed
  2512. // before the AstValueFactory containing the error message string was
  2513. // internalized.
  2514. v8::Isolate* isolate = CcTest::isolate();
  2515. v8::HandleScope scope(isolate);
  2516. LocalContext env;
  2517. i::FLAG_lazy = true;
  2518. i::FLAG_min_preparse_length = 0;
  2519. CompileRun("function this_is_lazy() {\n"
  2520. " break p;\n"
  2521. "}\n"
  2522. "this_is_lazy();\n");
  2523. }
  2524. TEST(SerializationOfMaybeAssignmentFlag) {
  2525. i::Isolate* isolate = CcTest::i_isolate();
  2526. i::Factory* factory = isolate->factory();
  2527. i::HandleScope scope(isolate);
  2528. LocalContext env;
  2529. const char* src =
  2530. "function h() {"
  2531. " var result = [];"
  2532. " function f() {"
  2533. " result.push(2);"
  2534. " }"
  2535. " function assertResult(r) {"
  2536. " f();"
  2537. " result = [];"
  2538. " }"
  2539. " assertResult([2]);"
  2540. " assertResult([2]);"
  2541. " return f;"
  2542. "};"
  2543. "h();";
  2544. i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
  2545. i::SNPrintF(program, "%s", src);
  2546. i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
  2547. source->PrintOn(stdout);
  2548. printf("\n");
  2549. i::Zone zone(isolate);
  2550. v8::Local<v8::Value> v = CompileRun(src);
  2551. i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
  2552. i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
  2553. i::Context* context = f->context();
  2554. i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
  2555. avf.Internalize(isolate);
  2556. const i::AstRawString* name = avf.GetOneByteString("result");
  2557. i::Handle<i::String> str = name->string();
  2558. CHECK(str->IsInternalizedString());
  2559. i::Scope* global_scope =
  2560. new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
  2561. global_scope->Initialize();
  2562. i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
  2563. DCHECK(s != global_scope);
  2564. DCHECK(name != NULL);
  2565. // Get result from h's function context (that is f's context)
  2566. i::Variable* var = s->Lookup(name);
  2567. CHECK(var != NULL);
  2568. // Maybe assigned should survive deserialization
  2569. CHECK(var->maybe_assigned() == i::kMaybeAssigned);
  2570. // TODO(sigurds) Figure out if is_used should survive context serialization.
  2571. }
  2572. TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
  2573. i::Isolate* isolate = CcTest::i_isolate();
  2574. i::Factory* factory = isolate->factory();
  2575. i::HandleScope scope(isolate);
  2576. LocalContext env;
  2577. const char* src =
  2578. "function f(x) {"
  2579. " var a = arguments;"
  2580. " function g(i) {"
  2581. " ++a[0];"
  2582. " };"
  2583. " return g;"
  2584. " }"
  2585. "f(0);";
  2586. i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
  2587. i::SNPrintF(program, "%s", src);
  2588. i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
  2589. source->PrintOn(stdout);
  2590. printf("\n");
  2591. i::Zone zone(isolate);
  2592. v8::Local<v8::Value> v = CompileRun(src);
  2593. i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
  2594. i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
  2595. i::Context* context = f->context();
  2596. i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
  2597. avf.Internalize(isolate);
  2598. i::Scope* global_scope =
  2599. new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
  2600. global_scope->Initialize();
  2601. i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
  2602. DCHECK(s != global_scope);
  2603. const i::AstRawString* name_x = avf.GetOneByteString("x");
  2604. // Get result from f's function context (that is g's outer context)
  2605. i::Variable* var_x = s->Lookup(name_x);
  2606. CHECK(var_x != NULL);
  2607. CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
  2608. }
  2609. TEST(ExportsMaybeAssigned) {
  2610. i::FLAG_use_strict = true;
  2611. i::FLAG_harmony_scoping = true;
  2612. i::FLAG_harmony_modules = true;
  2613. i::Isolate* isolate = CcTest::i_isolate();
  2614. i::Factory* factory = isolate->factory();
  2615. i::HandleScope scope(isolate);
  2616. LocalContext env;
  2617. const char* src =
  2618. "module A {"
  2619. " export var x = 1;"
  2620. " export function f() { return x };"
  2621. " export const y = 2;"
  2622. " module B {}"
  2623. " export module C {}"
  2624. "};"
  2625. "A.f";
  2626. i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
  2627. i::SNPrintF(program, "%s", src);
  2628. i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
  2629. source->PrintOn(stdout);
  2630. printf("\n");
  2631. i::Zone zone(isolate);
  2632. v8::Local<v8::Value> v = CompileRun(src);
  2633. i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
  2634. i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
  2635. i::Context* context = f->context();
  2636. i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
  2637. avf.Internalize(isolate);
  2638. i::Scope* global_scope =
  2639. new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone);
  2640. global_scope->Initialize();
  2641. i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone);
  2642. DCHECK(s != global_scope);
  2643. const i::AstRawString* name_x = avf.GetOneByteString("x");
  2644. const i::AstRawString* name_f = avf.GetOneByteString("f");
  2645. const i::AstRawString* name_y = avf.GetOneByteString("y");
  2646. const i::AstRawString* name_B = avf.GetOneByteString("B");
  2647. const i::AstRawString* name_C = avf.GetOneByteString("C");
  2648. // Get result from h's function context (that is f's context)
  2649. i::Variable* var_x = s->Lookup(name_x);
  2650. CHECK(var_x != NULL);
  2651. CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
  2652. i::Variable* var_f = s->Lookup(name_f);
  2653. CHECK(var_f != NULL);
  2654. CHECK(var_f->maybe_assigned() == i::kMaybeAssigned);
  2655. i::Variable* var_y = s->Lookup(name_y);
  2656. CHECK(var_y != NULL);
  2657. CHECK(var_y->maybe_assigned() == i::kNotAssigned);
  2658. i::Variable* var_B = s->Lookup(name_B);
  2659. CHECK(var_B != NULL);
  2660. CHECK(var_B->maybe_assigned() == i::kNotAssigned);
  2661. i::Variable* var_C = s->Lookup(name_C);
  2662. CHECK(var_C != NULL);
  2663. CHECK(var_C->maybe_assigned() == i::kNotAssigned);
  2664. }
  2665. TEST(InnerAssignment) {
  2666. i::Isolate* isolate = CcTest::i_isolate();
  2667. i::Factory* factory = isolate->factory();
  2668. i::HandleScope scope(isolate);
  2669. LocalContext env;
  2670. const char* prefix = "function f() {";
  2671. const char* midfix = " function g() {";
  2672. const char* suffix = "}}";
  2673. struct { const char* source; bool assigned; bool strict; } outers[] = {
  2674. // Actual assignments.
  2675. { "var x; var x = 5;", true, false },
  2676. { "var x; { var x = 5; }", true, false },
  2677. { "'use strict'; let x; x = 6;", true, true },
  2678. { "var x = 5; function x() {}", true, false },
  2679. // Actual non-assignments.
  2680. { "var x;", false, false },
  2681. { "var x = 5;", false, false },
  2682. { "'use strict'; let x;", false, true },
  2683. { "'use strict'; let x = 6;", false, true },
  2684. { "'use strict'; var x = 0; { let x = 6; }", false, true },
  2685. { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
  2686. { "'use strict'; let x = 0; { let x = 6; }", false, true },
  2687. { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
  2688. { "var x; try {} catch (x) { x = 5; }", false, false },
  2689. { "function x() {}", false, false },
  2690. // Eval approximation.
  2691. { "var x; eval('');", true, false },
  2692. { "eval(''); var x;", true, false },
  2693. { "'use strict'; let x; eval('');", true, true },
  2694. { "'use strict'; eval(''); let x;", true, true },
  2695. // Non-assignments not recognized, because the analysis is approximative.
  2696. { "var x; var x;", true, false },
  2697. { "var x = 5; var x;", true, false },
  2698. { "var x; { var x; }", true, false },
  2699. { "var x; function x() {}", true, false },
  2700. { "function x() {}; var x;", true, false },
  2701. { "var x; try {} catch (x) { var x = 5; }", true, false },
  2702. };
  2703. struct { const char* source; bool assigned; bool with; } inners[] = {
  2704. // Actual assignments.
  2705. { "x = 1;", true, false },
  2706. { "x++;", true, false },
  2707. { "++x;", true, false },
  2708. { "x--;", true, false },
  2709. { "--x;", true, false },
  2710. { "{ x = 1; }", true, false },
  2711. { "'use strict'; { let x; }; x = 0;", true, false },
  2712. { "'use strict'; { const x = 1; }; x = 0;", true, false },
  2713. { "'use strict'; { function x() {} }; x = 0;", true, false },
  2714. { "with ({}) { x = 1; }", true, true },
  2715. { "eval('');", true, false },
  2716. { "'use strict'; { let y; eval('') }", true, false },
  2717. { "function h() { x = 0; }", true, false },
  2718. { "(function() { x = 0; })", true, false },
  2719. { "(function() { x = 0; })", true, false },
  2720. { "with ({}) (function() { x = 0; })", true, true },
  2721. // Actual non-assignments.
  2722. { "", false, false },
  2723. { "x;", false, false },
  2724. { "var x;", false, false },
  2725. { "var x = 8;", false, false },
  2726. { "var x; x = 8;", false, false },
  2727. { "'use strict'; let x;", false, false },
  2728. { "'use strict'; let x = 8;", false, false },
  2729. { "'use strict'; let x; x = 8;", false, false },
  2730. { "'use strict'; const x = 8;", false, false },
  2731. { "function x() {}", false, false },
  2732. { "function x() { x = 0; }", false, false },
  2733. { "function h(x) { x = 0; }", false, false },
  2734. { "'use strict'; { let x; x = 0; }", false, false },
  2735. { "{ var x; }; x = 0;", false, false },
  2736. { "with ({}) {}", false, true },
  2737. { "var x; { with ({}) { x = 1; } }", false, true },
  2738. { "try {} catch(x) { x = 0; }", false, false },
  2739. { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
  2740. // Eval approximation.
  2741. { "eval('');", true, false },
  2742. { "function h() { eval(''); }", true, false },
  2743. { "(function() { eval(''); })", true, false },
  2744. // Shadowing not recognized because of eval approximation.
  2745. { "var x; eval('');", true, false },
  2746. { "'use strict'; let x; eval('');", true, false },
  2747. { "try {} catch(x) { eval(''); }", true, false },
  2748. { "function x() { eval(''); }", true, false },
  2749. { "(function(x) { eval(''); })", true, false },
  2750. };
  2751. // Used to trigger lazy compilation of function
  2752. int comment_len = 2048;
  2753. i::ScopedVector<char> comment(comment_len + 1);
  2754. i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
  2755. int prefix_len = Utf8LengthHelper(prefix);
  2756. int midfix_len = Utf8LengthHelper(midfix);
  2757. int suffix_len = Utf8LengthHelper(suffix);
  2758. for (unsigned i = 0; i < ARRAY_SIZE(outers); ++i) {
  2759. const char* outer = outers[i].source;
  2760. int outer_len = Utf8LengthHelper(outer);
  2761. for (unsigned j = 0; j < ARRAY_SIZE(inners); ++j) {
  2762. for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
  2763. for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
  2764. if (outers[i].strict && inners[j].with) continue;
  2765. const char* inner = inners[j].source;
  2766. int inner_len = Utf8LengthHelper(inner);
  2767. int outer_comment_len = outer_lazy ? comment_len : 0;
  2768. int inner_comment_len = inner_lazy ? comment_len : 0;
  2769. const char* outer_comment = outer_lazy ? comment.start() : "";
  2770. const char* inner_comment = inner_lazy ? comment.start() : "";
  2771. int len = prefix_len + outer_comment_len + outer_len + midfix_len +
  2772. inner_comment_len + inner_len + suffix_len;
  2773. i::ScopedVector<char> program(len + 1);
  2774. i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
  2775. midfix, inner_comment, inner, suffix);
  2776. i::Handle<i::String> source =
  2777. factory->InternalizeUtf8String(program.start());
  2778. source->PrintOn(stdout);
  2779. printf("\n");
  2780. i::Handle<i::Script> script = factory->NewScript(source);
  2781. i::CompilationInfoWithZone info(script);
  2782. i::Parser parser(&info);
  2783. parser.set_allow_harmony_scoping(true);
  2784. CHECK(parser.Parse());
  2785. CHECK(i::Rewriter::Rewrite(&info));
  2786. CHECK(i::Scope::Analyze(&info));
  2787. CHECK(info.function() != NULL);
  2788. i::Scope* scope = info.function()->scope();
  2789. CHECK_EQ(scope->inner_scopes()->length(), 1);
  2790. i::Scope* inner_scope = scope->inner_scopes()->at(0);
  2791. const i::AstRawString* var_name =
  2792. info.ast_value_factory()->GetOneByteString("x");
  2793. i::Variable* var = inner_scope->Lookup(var_name);
  2794. bool expected = outers[i].assigned || inners[j].assigned;
  2795. CHECK(var != NULL);
  2796. CHECK(var->is_used() || !expected);
  2797. CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
  2798. }
  2799. }
  2800. }
  2801. }
  2802. }
  2803. namespace {
  2804. int* global_use_counts = NULL;
  2805. void MockUseCounterCallback(v8::Isolate* isolate,
  2806. v8::Isolate::UseCounterFeature feature) {
  2807. ++global_use_counts[feature];
  2808. }
  2809. }
  2810. TEST(UseAsmUseCount) {
  2811. i::Isolate* isolate = CcTest::i_isolate();
  2812. i::HandleScope scope(isolate);
  2813. LocalContext env;
  2814. int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
  2815. global_use_counts = use_counts;
  2816. CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
  2817. CompileRun("\"use asm\";\n"
  2818. "var foo = 1;\n"
  2819. "\"use asm\";\n" // Only the first one counts.
  2820. "function bar() { \"use asm\"; var baz = 1; }");
  2821. CHECK_EQ(2, use_counts[v8::Isolate::kUseAsm]);
  2822. }
  2823. TEST(ErrorsArrowFunctions) {
  2824. // Tests that parser and preparser generate the same kind of errors
  2825. // on invalid arrow function syntax.
  2826. const char* context_data[][2] = {
  2827. {"", ";"},
  2828. {"v = ", ";"},
  2829. {"bar ? (", ") : baz;"},
  2830. {"bar ? baz : (", ");"},
  2831. {"bar[", "];"},
  2832. {"bar, ", ";"},
  2833. {"", ", bar;"},
  2834. {NULL, NULL}
  2835. };
  2836. const char* statement_data[] = {
  2837. "=> 0",
  2838. "=>",
  2839. "() =>",
  2840. "=> {}",
  2841. ") => {}",
  2842. ", => {}",
  2843. "(,) => {}",
  2844. "return => {}",
  2845. "() => {'value': 42}",
  2846. // Check that the early return introduced in ParsePrimaryExpression
  2847. // does not accept stray closing parentheses.
  2848. ")",
  2849. ") => 0",
  2850. "foo[()]",
  2851. "()",
  2852. // Parameter lists with extra parens should be recognized as errors.
  2853. "(()) => 0",
  2854. "((x)) => 0",
  2855. "((x, y)) => 0",
  2856. "(x, (y)) => 0",
  2857. "((x, y, z)) => 0",
  2858. "(x, (y, z)) => 0",
  2859. "((x, y), z) => 0",
  2860. // Parameter lists are always validated as strict, so those are errors.
  2861. "eval => {}",
  2862. "arguments => {}",
  2863. "yield => {}",
  2864. "interface => {}",
  2865. "(eval) => {}",
  2866. "(arguments) => {}",
  2867. "(yield) => {}",
  2868. "(interface) => {}",
  2869. "(eval, bar) => {}",
  2870. "(bar, eval) => {}",
  2871. "(bar, arguments) => {}",
  2872. "(bar, yield) => {}",
  2873. "(bar, interface) => {}",
  2874. // TODO(aperez): Detecting duplicates does not work in PreParser.
  2875. // "(bar, bar) => {}",
  2876. // The parameter list is parsed as an expression, but only
  2877. // a comma-separated list of identifier is valid.
  2878. "32 => {}",
  2879. "(32) => {}",
  2880. "(a, 32) => {}",
  2881. "if => {}",
  2882. "(if) => {}",
  2883. "(a, if) => {}",
  2884. "a + b => {}",
  2885. "(a + b) => {}",
  2886. "(a + b, c) => {}",
  2887. "(a, b - c) => {}",
  2888. "\"a\" => {}",
  2889. "(\"a\") => {}",
  2890. "(\"a\", b) => {}",
  2891. "(a, \"b\") => {}",
  2892. "-a => {}",
  2893. "(-a) => {}",
  2894. "(-a, b) => {}",
  2895. "(a, -b) => {}",
  2896. "{} => {}",
  2897. "({}) => {}",
  2898. "(a, {}) => {}",
  2899. "({}, a) => {}",
  2900. "a++ => {}",
  2901. "(a++) => {}",
  2902. "(a++, b) => {}",
  2903. "(a, b++) => {}",
  2904. "[] => {}",
  2905. "([]) => {}",
  2906. "(a, []) => {}",
  2907. "([], a) => {}",
  2908. "(a = b) => {}",
  2909. "(a = b, c) => {}",
  2910. "(a, b = c) => {}",
  2911. "(foo ? bar : baz) => {}",
  2912. "(a, foo ? bar : baz) => {}",
  2913. "(foo ? bar : baz, a) => {}",
  2914. NULL
  2915. };
  2916. // The test is quite slow, so run it with a reduced set of flags.
  2917. static const ParserFlag flags[] = {
  2918. kAllowLazy, kAllowHarmonyScoping, kAllowGenerators
  2919. };
  2920. static const ParserFlag always_flags[] = { kAllowArrowFunctions };
  2921. RunParserSyncTest(context_data, statement_data, kError, flags,
  2922. ARRAY_SIZE(flags), always_flags, ARRAY_SIZE(always_flags));
  2923. }
  2924. TEST(NoErrorsArrowFunctions) {
  2925. // Tests that parser and preparser accept valid arrow functions syntax.
  2926. const char* context_data[][2] = {
  2927. {"", ";"},
  2928. {"bar ? (", ") : baz;"},
  2929. {"bar ? baz : (", ");"},
  2930. {"bar, ", ";"},
  2931. {"", ", bar;"},
  2932. {NULL, NULL}
  2933. };
  2934. const char* statement_data[] = {
  2935. "() => {}",
  2936. "() => { return 42 }",
  2937. "x => { return x; }",
  2938. "(x) => { return x; }",
  2939. "(x, y) => { return x + y; }",
  2940. "(x, y, z) => { return x + y + z; }",
  2941. "(x, y) => { x.a = y; }",
  2942. "() => 42",
  2943. "x => x",
  2944. "x => x * x",
  2945. "(x) => x",
  2946. "(x) => x * x",
  2947. "(x, y) => x + y",
  2948. "(x, y, z) => x, y, z",
  2949. "(x, y) => x.a = y",
  2950. "() => ({'value': 42})",
  2951. "x => y => x + y",
  2952. "(x, y) => (u, v) => x*u + y*v",
  2953. "(x, y) => z => z * (x + y)",
  2954. "x => (y, z) => z * (x + y)",
  2955. // Those are comma-separated expressions, with arrow functions as items.
  2956. // They stress the code for validating arrow function parameter lists.
  2957. "a, b => 0",
  2958. "a, b, (c, d) => 0",
  2959. "(a, b, (c, d) => 0)",
  2960. "(a, b) => 0, (c, d) => 1",
  2961. "(a, b => {}, a => a + 1)",
  2962. "((a, b) => {}, (a => a + 1))",
  2963. "(a, (a, (b, c) => 0))",
  2964. // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
  2965. "foo ? bar : baz => {}",
  2966. NULL
  2967. };
  2968. static const ParserFlag always_flags[] = {kAllowArrowFunctions};
  2969. RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
  2970. always_flags, ARRAY_SIZE(always_flags));
  2971. }