1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 32 #include "src/v8.h" 33 34 #include "src/ast/ast.h" 35 #include "src/ast/ast-numbering.h" 36 #include "src/ast/ast-value-factory.h" 37 #include "src/compiler.h" 38 #include "src/execution.h" 39 #include "src/isolate.h" 40 #include "src/objects.h" 41 #include "src/parsing/parser.h" 42 #include "src/parsing/preparser.h" 43 #include "src/parsing/rewriter.h" 44 #include "src/parsing/scanner-character-streams.h" 45 #include "src/parsing/token.h" 46 #include "src/utils.h" 47 48 #include "test/cctest/cctest.h" 49 50 TEST(ScanKeywords) { 51 struct KeywordToken { 52 const char* keyword; 53 i::Token::Value token; 54 }; 55 56 static const KeywordToken keywords[] = { 57 #define KEYWORD(t, s, d) { s, i::Token::t }, 58 TOKEN_LIST(IGNORE_TOKEN, KEYWORD) 59 #undef KEYWORD 60 { NULL, i::Token::IDENTIFIER } 61 }; 62 63 KeywordToken key_token; 64 i::UnicodeCache unicode_cache; 65 i::byte buffer[32]; 66 for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) { 67 const i::byte* keyword = 68 reinterpret_cast<const i::byte*>(key_token.keyword); 69 int length = i::StrLength(key_token.keyword); 70 CHECK(static_cast<int>(sizeof(buffer)) >= length); 71 { 72 i::Utf8ToUtf16CharacterStream stream(keyword, length); 73 i::Scanner scanner(&unicode_cache); 74 scanner.Initialize(&stream); 75 CHECK_EQ(key_token.token, scanner.Next()); 76 CHECK_EQ(i::Token::EOS, scanner.Next()); 77 } 78 // Removing characters will make keyword matching fail. 79 { 80 i::Utf8ToUtf16CharacterStream stream(keyword, length - 1); 81 i::Scanner scanner(&unicode_cache); 82 scanner.Initialize(&stream); 83 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); 84 CHECK_EQ(i::Token::EOS, scanner.Next()); 85 } 86 // Adding characters will make keyword matching fail. 87 static const char chars_to_append[] = { 'z', '0', '_' }; 88 for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) { 89 i::MemMove(buffer, keyword, length); 90 buffer[length] = chars_to_append[j]; 91 i::Utf8ToUtf16CharacterStream stream(buffer, length + 1); 92 i::Scanner scanner(&unicode_cache); 93 scanner.Initialize(&stream); 94 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); 95 CHECK_EQ(i::Token::EOS, scanner.Next()); 96 } 97 // Replacing characters will make keyword matching fail. 98 { 99 i::MemMove(buffer, keyword, length); 100 buffer[length - 1] = '_'; 101 i::Utf8ToUtf16CharacterStream stream(buffer, length); 102 i::Scanner scanner(&unicode_cache); 103 scanner.Initialize(&stream); 104 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); 105 CHECK_EQ(i::Token::EOS, scanner.Next()); 106 } 107 } 108 } 109 110 111 TEST(ScanHTMLEndComments) { 112 v8::V8::Initialize(); 113 v8::Isolate* isolate = CcTest::isolate(); 114 v8::HandleScope handles(isolate); 115 116 // Regression test. See: 117 // http://code.google.com/p/chromium/issues/detail?id=53548 118 // Tests that --> is correctly interpreted as comment-to-end-of-line if there 119 // is only whitespace before it on the line (with comments considered as 120 // whitespace, even a multiline-comment containing a newline). 121 // This was not the case if it occurred before the first real token 122 // in the input. 123 const char* tests[] = { 124 // Before first real token. 125 "--> is eol-comment\nvar y = 37;\n", 126 "\n --> is eol-comment\nvar y = 37;\n", 127 "/* precomment */ --> is eol-comment\nvar y = 37;\n", 128 "\n/* precomment */ --> is eol-comment\nvar y = 37;\n", 129 // After first real token. 130 "var x = 42;\n--> is eol-comment\nvar y = 37;\n", 131 "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n", 132 NULL 133 }; 134 135 const char* fail_tests[] = { 136 "x --> is eol-comment\nvar y = 37;\n", 137 "\"\\n\" --> is eol-comment\nvar y = 37;\n", 138 "x/* precomment */ --> is eol-comment\nvar y = 37;\n", 139 "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n", 140 "var x = 42; --> is eol-comment\nvar y = 37;\n", 141 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n", 142 NULL 143 }; 144 145 // Parser/Scanner needs a stack limit. 146 CcTest::i_isolate()->stack_guard()->SetStackLimit( 147 i::GetCurrentStackPosition() - 128 * 1024); 148 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 149 for (int i = 0; tests[i]; i++) { 150 const i::byte* source = 151 reinterpret_cast<const i::byte*>(tests[i]); 152 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i])); 153 i::CompleteParserRecorder log; 154 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 155 scanner.Initialize(&stream); 156 i::Zone zone(CcTest::i_isolate()->allocator()); 157 i::AstValueFactory ast_value_factory( 158 &zone, CcTest::i_isolate()->heap()->HashSeed()); 159 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 160 stack_limit); 161 preparser.set_allow_lazy(true); 162 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 163 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 164 CHECK(!log.HasError()); 165 } 166 167 for (int i = 0; fail_tests[i]; i++) { 168 const i::byte* source = 169 reinterpret_cast<const i::byte*>(fail_tests[i]); 170 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i])); 171 i::CompleteParserRecorder log; 172 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 173 scanner.Initialize(&stream); 174 i::Zone zone(CcTest::i_isolate()->allocator()); 175 i::AstValueFactory ast_value_factory( 176 &zone, CcTest::i_isolate()->heap()->HashSeed()); 177 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 178 stack_limit); 179 preparser.set_allow_lazy(true); 180 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 181 // Even in the case of a syntax error, kPreParseSuccess is returned. 182 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 183 CHECK(log.HasError()); 184 } 185 } 186 187 188 class ScriptResource : public v8::String::ExternalOneByteStringResource { 189 public: 190 ScriptResource(const char* data, size_t length) 191 : data_(data), length_(length) { } 192 193 const char* data() const { return data_; } 194 size_t length() const { return length_; } 195 196 private: 197 const char* data_; 198 size_t length_; 199 }; 200 201 202 TEST(UsingCachedData) { 203 // Producing cached parser data while parsing eagerly is not supported. 204 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return; 205 206 v8::Isolate* isolate = CcTest::isolate(); 207 v8::HandleScope handles(isolate); 208 v8::Local<v8::Context> context = v8::Context::New(isolate); 209 v8::Context::Scope context_scope(context); 210 CcTest::i_isolate()->stack_guard()->SetStackLimit( 211 i::GetCurrentStackPosition() - 128 * 1024); 212 213 // Source containing functions that might be lazily compiled and all types 214 // of symbols (string, propertyName, regexp). 215 const char* source = 216 "var x = 42;" 217 "function foo(a) { return function nolazy(b) { return a + b; } }" 218 "function bar(a) { if (a) return function lazy(b) { return b; } }" 219 "var z = {'string': 'string literal', bareword: 'propertyName', " 220 " 42: 'number literal', for: 'keyword as propertyName', " 221 " f\\u006fr: 'keyword propertyname with escape'};" 222 "var v = /RegExp Literal/;" 223 "var w = /RegExp Literal\\u0020With Escape/gi;" 224 "var y = { get getter() { return 42; }, " 225 " set setter(v) { this.value = v; }};" 226 "var f = a => function (b) { return a + b; };" 227 "var g = a => b => a + b;"; 228 int source_length = i::StrLength(source); 229 230 // ScriptResource will be deleted when the corresponding String is GCd. 231 v8::ScriptCompiler::Source script_source( 232 v8::String::NewExternalOneByte(isolate, 233 new ScriptResource(source, source_length)) 234 .ToLocalChecked()); 235 i::FLAG_min_preparse_length = 0; 236 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source, 237 v8::ScriptCompiler::kProduceParserCache) 238 .ToLocalChecked(); 239 CHECK(script_source.GetCachedData()); 240 241 // Compile the script again, using the cached data. 242 bool lazy_flag = i::FLAG_lazy; 243 i::FLAG_lazy = true; 244 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source, 245 v8::ScriptCompiler::kConsumeParserCache) 246 .ToLocalChecked(); 247 i::FLAG_lazy = false; 248 v8::ScriptCompiler::CompileUnboundScript( 249 isolate, &script_source, v8::ScriptCompiler::kConsumeParserCache) 250 .ToLocalChecked(); 251 i::FLAG_lazy = lazy_flag; 252 } 253 254 255 TEST(PreparseFunctionDataIsUsed) { 256 // Producing cached parser data while parsing eagerly is not supported. 257 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return; 258 259 // This tests that we actually do use the function data generated by the 260 // preparser. 261 262 // Make preparsing work for short scripts. 263 i::FLAG_min_preparse_length = 0; 264 265 v8::Isolate* isolate = CcTest::isolate(); 266 v8::HandleScope handles(isolate); 267 v8::Local<v8::Context> context = v8::Context::New(isolate); 268 v8::Context::Scope context_scope(context); 269 CcTest::i_isolate()->stack_guard()->SetStackLimit( 270 i::GetCurrentStackPosition() - 128 * 1024); 271 272 const char* good_code[] = { 273 "function this_is_lazy() { var a; } function foo() { return 25; } foo();", 274 "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();", 275 }; 276 277 // Insert a syntax error inside the lazy function. 278 const char* bad_code[] = { 279 "function this_is_lazy() { if ( } function foo() { return 25; } foo();", 280 "var this_is_lazy = () => { if ( }; var foo = () => 25; foo();", 281 }; 282 283 for (unsigned i = 0; i < arraysize(good_code); i++) { 284 v8::ScriptCompiler::Source good_source(v8_str(good_code[i])); 285 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &good_source, 286 v8::ScriptCompiler::kProduceParserCache) 287 .ToLocalChecked(); 288 289 const v8::ScriptCompiler::CachedData* cached_data = 290 good_source.GetCachedData(); 291 CHECK(cached_data->data != NULL); 292 CHECK_GT(cached_data->length, 0); 293 294 // Now compile the erroneous code with the good preparse data. If the 295 // preparse data is used, the lazy function is skipped and it should 296 // compile fine. 297 v8::ScriptCompiler::Source bad_source( 298 v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData( 299 cached_data->data, cached_data->length)); 300 v8::Local<v8::Value> result = 301 CompileRun(isolate->GetCurrentContext(), &bad_source, 302 v8::ScriptCompiler::kConsumeParserCache); 303 CHECK(result->IsInt32()); 304 CHECK_EQ(25, result->Int32Value(isolate->GetCurrentContext()).FromJust()); 305 } 306 } 307 308 309 TEST(StandAlonePreParser) { 310 v8::V8::Initialize(); 311 312 CcTest::i_isolate()->stack_guard()->SetStackLimit( 313 i::GetCurrentStackPosition() - 128 * 1024); 314 315 const char* programs[] = { 316 "{label: 42}", 317 "var x = 42;", 318 "function foo(x, y) { return x + y; }", 319 "%ArgleBargle(glop);", 320 "var x = new new Function('this.x = 42');", 321 "var f = (x, y) => x + y;", 322 NULL 323 }; 324 325 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 326 for (int i = 0; programs[i]; i++) { 327 const char* program = programs[i]; 328 i::Utf8ToUtf16CharacterStream stream( 329 reinterpret_cast<const i::byte*>(program), 330 static_cast<unsigned>(strlen(program))); 331 i::CompleteParserRecorder log; 332 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 333 scanner.Initialize(&stream); 334 335 i::Zone zone(CcTest::i_isolate()->allocator()); 336 i::AstValueFactory ast_value_factory( 337 &zone, CcTest::i_isolate()->heap()->HashSeed()); 338 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 339 stack_limit); 340 preparser.set_allow_lazy(true); 341 preparser.set_allow_natives(true); 342 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 343 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 344 CHECK(!log.HasError()); 345 } 346 } 347 348 349 TEST(StandAlonePreParserNoNatives) { 350 v8::V8::Initialize(); 351 352 CcTest::i_isolate()->stack_guard()->SetStackLimit( 353 i::GetCurrentStackPosition() - 128 * 1024); 354 355 const char* programs[] = { 356 "%ArgleBargle(glop);", 357 "var x = %_IsSmi(42);", 358 NULL 359 }; 360 361 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 362 for (int i = 0; programs[i]; i++) { 363 const char* program = programs[i]; 364 i::Utf8ToUtf16CharacterStream stream( 365 reinterpret_cast<const i::byte*>(program), 366 static_cast<unsigned>(strlen(program))); 367 i::CompleteParserRecorder log; 368 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 369 scanner.Initialize(&stream); 370 371 // Preparser defaults to disallowing natives syntax. 372 i::Zone zone(CcTest::i_isolate()->allocator()); 373 i::AstValueFactory ast_value_factory( 374 &zone, CcTest::i_isolate()->heap()->HashSeed()); 375 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 376 stack_limit); 377 preparser.set_allow_lazy(true); 378 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 379 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 380 CHECK(log.HasError()); 381 } 382 } 383 384 385 TEST(PreparsingObjectLiterals) { 386 // Regression test for a bug where the symbol stream produced by PreParser 387 // didn't match what Parser wanted to consume. 388 v8::Isolate* isolate = CcTest::isolate(); 389 v8::HandleScope handles(isolate); 390 v8::Local<v8::Context> context = v8::Context::New(isolate); 391 v8::Context::Scope context_scope(context); 392 CcTest::i_isolate()->stack_guard()->SetStackLimit( 393 i::GetCurrentStackPosition() - 128 * 1024); 394 395 { 396 const char* source = "var myo = {if: \"foo\"}; myo.if;"; 397 v8::Local<v8::Value> result = ParserCacheCompileRun(source); 398 CHECK(result->IsString()); 399 v8::String::Utf8Value utf8(result); 400 CHECK_EQ(0, strcmp("foo", *utf8)); 401 } 402 403 { 404 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];"; 405 v8::Local<v8::Value> result = ParserCacheCompileRun(source); 406 CHECK(result->IsString()); 407 v8::String::Utf8Value utf8(result); 408 CHECK_EQ(0, strcmp("foo", *utf8)); 409 } 410 411 { 412 const char* source = "var myo = {1: \"foo\"}; myo[1];"; 413 v8::Local<v8::Value> result = ParserCacheCompileRun(source); 414 CHECK(result->IsString()); 415 v8::String::Utf8Value utf8(result); 416 CHECK_EQ(0, strcmp("foo", *utf8)); 417 } 418 } 419 420 421 TEST(RegressChromium62639) { 422 v8::V8::Initialize(); 423 i::Isolate* isolate = CcTest::i_isolate(); 424 425 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 426 128 * 1024); 427 428 const char* program = "var x = 'something';\n" 429 "escape: function() {}"; 430 // Fails parsing expecting an identifier after "function". 431 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), 432 // and then used the invalid currently scanned literal. This always 433 // failed in debug mode, and sometimes crashed in release mode. 434 435 i::Utf8ToUtf16CharacterStream stream( 436 reinterpret_cast<const i::byte*>(program), 437 static_cast<unsigned>(strlen(program))); 438 i::CompleteParserRecorder log; 439 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 440 scanner.Initialize(&stream); 441 i::Zone zone(CcTest::i_isolate()->allocator()); 442 i::AstValueFactory ast_value_factory(&zone, 443 CcTest::i_isolate()->heap()->HashSeed()); 444 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 445 CcTest::i_isolate()->stack_guard()->real_climit()); 446 preparser.set_allow_lazy(true); 447 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 448 // Even in the case of a syntax error, kPreParseSuccess is returned. 449 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 450 CHECK(log.HasError()); 451 } 452 453 454 TEST(Regress928) { 455 v8::V8::Initialize(); 456 i::Isolate* isolate = CcTest::i_isolate(); 457 i::Factory* factory = isolate->factory(); 458 459 // Preparsing didn't consider the catch clause of a try statement 460 // as with-content, which made it assume that a function inside 461 // the block could be lazily compiled, and an extra, unexpected, 462 // entry was added to the data. 463 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 464 128 * 1024); 465 466 const char* program = 467 "try { } catch (e) { var foo = function () { /* first */ } }" 468 "var bar = function () { /* second */ }"; 469 470 v8::HandleScope handles(CcTest::isolate()); 471 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program); 472 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); 473 i::CompleteParserRecorder log; 474 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 475 scanner.Initialize(&stream); 476 i::Zone zone(CcTest::i_isolate()->allocator()); 477 i::AstValueFactory ast_value_factory(&zone, 478 CcTest::i_isolate()->heap()->HashSeed()); 479 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 480 CcTest::i_isolate()->stack_guard()->real_climit()); 481 preparser.set_allow_lazy(true); 482 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 483 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 484 i::ScriptData* sd = log.GetScriptData(); 485 i::ParseData* pd = i::ParseData::FromCachedData(sd); 486 pd->Initialize(); 487 488 int first_function = 489 static_cast<int>(strstr(program, "function") - program); 490 int first_lbrace = first_function + i::StrLength("function () "); 491 CHECK_EQ('{', program[first_lbrace]); 492 i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace); 493 CHECK(!entry1.is_valid()); 494 495 int second_function = 496 static_cast<int>(strstr(program + first_lbrace, "function") - program); 497 int second_lbrace = 498 second_function + i::StrLength("function () "); 499 CHECK_EQ('{', program[second_lbrace]); 500 i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace); 501 CHECK(entry2.is_valid()); 502 CHECK_EQ('}', program[entry2.end_pos() - 1]); 503 delete sd; 504 delete pd; 505 } 506 507 508 TEST(PreParseOverflow) { 509 v8::V8::Initialize(); 510 511 CcTest::i_isolate()->stack_guard()->SetStackLimit( 512 i::GetCurrentStackPosition() - 128 * 1024); 513 514 size_t kProgramSize = 1024 * 1024; 515 v8::base::SmartArrayPointer<char> program( 516 i::NewArray<char>(kProgramSize + 1)); 517 memset(program.get(), '(', kProgramSize); 518 program[kProgramSize] = '\0'; 519 520 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 521 522 i::Utf8ToUtf16CharacterStream stream( 523 reinterpret_cast<const i::byte*>(program.get()), 524 static_cast<unsigned>(kProgramSize)); 525 i::CompleteParserRecorder log; 526 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 527 scanner.Initialize(&stream); 528 529 i::Zone zone(CcTest::i_isolate()->allocator()); 530 i::AstValueFactory ast_value_factory(&zone, 531 CcTest::i_isolate()->heap()->HashSeed()); 532 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 533 stack_limit); 534 preparser.set_allow_lazy(true); 535 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 536 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result); 537 } 538 539 540 class TestExternalResource: public v8::String::ExternalStringResource { 541 public: 542 explicit TestExternalResource(uint16_t* data, int length) 543 : data_(data), length_(static_cast<size_t>(length)) { } 544 545 ~TestExternalResource() { } 546 547 const uint16_t* data() const { 548 return data_; 549 } 550 551 size_t length() const { 552 return length_; 553 } 554 private: 555 uint16_t* data_; 556 size_t length_; 557 }; 558 559 560 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2)) 561 562 void TestCharacterStream(const char* one_byte_source, unsigned length, 563 unsigned start = 0, unsigned end = 0) { 564 if (end == 0) end = length; 565 unsigned sub_length = end - start; 566 i::Isolate* isolate = CcTest::i_isolate(); 567 i::Factory* factory = isolate->factory(); 568 i::HandleScope test_scope(isolate); 569 v8::base::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]); 570 for (unsigned i = 0; i < length; i++) { 571 uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]); 572 } 573 i::Vector<const char> one_byte_vector(one_byte_source, 574 static_cast<int>(length)); 575 i::Handle<i::String> one_byte_string = 576 factory->NewStringFromAscii(one_byte_vector).ToHandleChecked(); 577 TestExternalResource resource(uc16_buffer.get(), length); 578 i::Handle<i::String> uc16_string( 579 factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked()); 580 581 i::ExternalTwoByteStringUtf16CharacterStream uc16_stream( 582 i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end); 583 i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start, 584 end); 585 i::Utf8ToUtf16CharacterStream utf8_stream( 586 reinterpret_cast<const i::byte*>(one_byte_source), end); 587 utf8_stream.SeekForward(start); 588 589 unsigned i = start; 590 while (i < end) { 591 // Read streams one char at a time 592 CHECK_EQU(i, uc16_stream.pos()); 593 CHECK_EQU(i, string_stream.pos()); 594 CHECK_EQU(i, utf8_stream.pos()); 595 int32_t c0 = one_byte_source[i]; 596 int32_t c1 = uc16_stream.Advance(); 597 int32_t c2 = string_stream.Advance(); 598 int32_t c3 = utf8_stream.Advance(); 599 i++; 600 CHECK_EQ(c0, c1); 601 CHECK_EQ(c0, c2); 602 CHECK_EQ(c0, c3); 603 CHECK_EQU(i, uc16_stream.pos()); 604 CHECK_EQU(i, string_stream.pos()); 605 CHECK_EQU(i, utf8_stream.pos()); 606 } 607 while (i > start + sub_length / 4) { 608 // Pushback, re-read, pushback again. 609 int32_t c0 = one_byte_source[i - 1]; 610 CHECK_EQU(i, uc16_stream.pos()); 611 CHECK_EQU(i, string_stream.pos()); 612 CHECK_EQU(i, utf8_stream.pos()); 613 uc16_stream.PushBack(c0); 614 string_stream.PushBack(c0); 615 utf8_stream.PushBack(c0); 616 i--; 617 CHECK_EQU(i, uc16_stream.pos()); 618 CHECK_EQU(i, string_stream.pos()); 619 CHECK_EQU(i, utf8_stream.pos()); 620 int32_t c1 = uc16_stream.Advance(); 621 int32_t c2 = string_stream.Advance(); 622 int32_t c3 = utf8_stream.Advance(); 623 i++; 624 CHECK_EQU(i, uc16_stream.pos()); 625 CHECK_EQU(i, string_stream.pos()); 626 CHECK_EQU(i, utf8_stream.pos()); 627 CHECK_EQ(c0, c1); 628 CHECK_EQ(c0, c2); 629 CHECK_EQ(c0, c3); 630 uc16_stream.PushBack(c0); 631 string_stream.PushBack(c0); 632 utf8_stream.PushBack(c0); 633 i--; 634 CHECK_EQU(i, uc16_stream.pos()); 635 CHECK_EQU(i, string_stream.pos()); 636 CHECK_EQU(i, utf8_stream.pos()); 637 } 638 unsigned halfway = start + sub_length / 2; 639 uc16_stream.SeekForward(halfway - i); 640 string_stream.SeekForward(halfway - i); 641 utf8_stream.SeekForward(halfway - i); 642 i = halfway; 643 CHECK_EQU(i, uc16_stream.pos()); 644 CHECK_EQU(i, string_stream.pos()); 645 CHECK_EQU(i, utf8_stream.pos()); 646 647 while (i < end) { 648 // Read streams one char at a time 649 CHECK_EQU(i, uc16_stream.pos()); 650 CHECK_EQU(i, string_stream.pos()); 651 CHECK_EQU(i, utf8_stream.pos()); 652 int32_t c0 = one_byte_source[i]; 653 int32_t c1 = uc16_stream.Advance(); 654 int32_t c2 = string_stream.Advance(); 655 int32_t c3 = utf8_stream.Advance(); 656 i++; 657 CHECK_EQ(c0, c1); 658 CHECK_EQ(c0, c2); 659 CHECK_EQ(c0, c3); 660 CHECK_EQU(i, uc16_stream.pos()); 661 CHECK_EQU(i, string_stream.pos()); 662 CHECK_EQU(i, utf8_stream.pos()); 663 } 664 665 int32_t c1 = uc16_stream.Advance(); 666 int32_t c2 = string_stream.Advance(); 667 int32_t c3 = utf8_stream.Advance(); 668 CHECK_LT(c1, 0); 669 CHECK_LT(c2, 0); 670 CHECK_LT(c3, 0); 671 } 672 673 674 TEST(CharacterStreams) { 675 v8::Isolate* isolate = CcTest::isolate(); 676 v8::HandleScope handles(isolate); 677 v8::Local<v8::Context> context = v8::Context::New(isolate); 678 v8::Context::Scope context_scope(context); 679 680 TestCharacterStream("abc\0\n\r\x7f", 7); 681 static const unsigned kBigStringSize = 4096; 682 char buffer[kBigStringSize + 1]; 683 for (unsigned i = 0; i < kBigStringSize; i++) { 684 buffer[i] = static_cast<char>(i & 0x7f); 685 } 686 TestCharacterStream(buffer, kBigStringSize); 687 688 TestCharacterStream(buffer, kBigStringSize, 576, 3298); 689 690 TestCharacterStream("\0", 1); 691 TestCharacterStream("", 0); 692 } 693 694 695 TEST(Utf8CharacterStream) { 696 static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar; 697 static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU); 698 699 static const int kAllUtf8CharsSize = 700 (unibrow::Utf8::kMaxOneByteChar + 1) + 701 (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 + 702 (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3; 703 static const unsigned kAllUtf8CharsSizeU = 704 static_cast<unsigned>(kAllUtf8CharsSize); 705 706 char buffer[kAllUtf8CharsSizeU]; 707 unsigned cursor = 0; 708 for (int i = 0; i <= kMaxUC16Char; i++) { 709 cursor += unibrow::Utf8::Encode(buffer + cursor, i, 710 unibrow::Utf16::kNoPreviousCharacter, true); 711 } 712 CHECK(cursor == kAllUtf8CharsSizeU); 713 714 i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer), 715 kAllUtf8CharsSizeU); 716 int32_t bad = unibrow::Utf8::kBadChar; 717 for (int i = 0; i <= kMaxUC16Char; i++) { 718 CHECK_EQU(i, stream.pos()); 719 int32_t c = stream.Advance(); 720 if (i >= 0xd800 && i <= 0xdfff) { 721 CHECK_EQ(bad, c); 722 } else { 723 CHECK_EQ(i, c); 724 } 725 CHECK_EQU(i + 1, stream.pos()); 726 } 727 for (int i = kMaxUC16Char; i >= 0; i--) { 728 CHECK_EQU(i + 1, stream.pos()); 729 stream.PushBack(i); 730 CHECK_EQU(i, stream.pos()); 731 } 732 int i = 0; 733 while (stream.pos() < kMaxUC16CharU) { 734 CHECK_EQU(i, stream.pos()); 735 int progress = static_cast<int>(stream.SeekForward(12)); 736 i += progress; 737 int32_t c = stream.Advance(); 738 if (i >= 0xd800 && i <= 0xdfff) { 739 CHECK_EQ(bad, c); 740 } else if (i <= kMaxUC16Char) { 741 CHECK_EQ(i, c); 742 } else { 743 CHECK_EQ(-1, c); 744 } 745 i += 1; 746 CHECK_EQU(i, stream.pos()); 747 } 748 } 749 750 #undef CHECK_EQU 751 752 void TestStreamScanner(i::Utf16CharacterStream* stream, 753 i::Token::Value* expected_tokens, 754 int skip_pos = 0, // Zero means not skipping. 755 int skip_to = 0) { 756 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 757 scanner.Initialize(stream); 758 759 int i = 0; 760 do { 761 i::Token::Value expected = expected_tokens[i]; 762 i::Token::Value actual = scanner.Next(); 763 CHECK_EQ(i::Token::String(expected), i::Token::String(actual)); 764 if (scanner.location().end_pos == skip_pos) { 765 scanner.SeekForward(skip_to); 766 } 767 i++; 768 } while (expected_tokens[i] != i::Token::ILLEGAL); 769 } 770 771 772 TEST(StreamScanner) { 773 v8::V8::Initialize(); 774 775 const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib"; 776 i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1), 777 static_cast<unsigned>(strlen(str1))); 778 i::Token::Value expectations1[] = { 779 i::Token::LBRACE, 780 i::Token::IDENTIFIER, 781 i::Token::IDENTIFIER, 782 i::Token::FOR, 783 i::Token::COLON, 784 i::Token::MUL, 785 i::Token::DIV, 786 i::Token::LT, 787 i::Token::SUB, 788 i::Token::IDENTIFIER, 789 i::Token::EOS, 790 i::Token::ILLEGAL 791 }; 792 TestStreamScanner(&stream1, expectations1, 0, 0); 793 794 const char* str2 = "case default const {THIS\nPART\nSKIPPED} do"; 795 i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2), 796 static_cast<unsigned>(strlen(str2))); 797 i::Token::Value expectations2[] = { 798 i::Token::CASE, 799 i::Token::DEFAULT, 800 i::Token::CONST, 801 i::Token::LBRACE, 802 // Skipped part here 803 i::Token::RBRACE, 804 i::Token::DO, 805 i::Token::EOS, 806 i::Token::ILLEGAL 807 }; 808 CHECK_EQ('{', str2[19]); 809 CHECK_EQ('}', str2[37]); 810 TestStreamScanner(&stream2, expectations2, 20, 37); 811 812 const char* str3 = "{}}}}"; 813 i::Token::Value expectations3[] = { 814 i::Token::LBRACE, 815 i::Token::RBRACE, 816 i::Token::RBRACE, 817 i::Token::RBRACE, 818 i::Token::RBRACE, 819 i::Token::EOS, 820 i::Token::ILLEGAL 821 }; 822 // Skip zero-four RBRACEs. 823 for (int i = 0; i <= 4; i++) { 824 expectations3[6 - i] = i::Token::ILLEGAL; 825 expectations3[5 - i] = i::Token::EOS; 826 i::Utf8ToUtf16CharacterStream stream3( 827 reinterpret_cast<const i::byte*>(str3), 828 static_cast<unsigned>(strlen(str3))); 829 TestStreamScanner(&stream3, expectations3, 1, 1 + i); 830 } 831 } 832 833 834 void TestScanRegExp(const char* re_source, const char* expected) { 835 i::Utf8ToUtf16CharacterStream stream( 836 reinterpret_cast<const i::byte*>(re_source), 837 static_cast<unsigned>(strlen(re_source))); 838 i::HandleScope scope(CcTest::i_isolate()); 839 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 840 scanner.Initialize(&stream); 841 842 i::Token::Value start = scanner.peek(); 843 CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV); 844 CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV)); 845 scanner.Next(); // Current token is now the regexp literal. 846 i::Zone zone(CcTest::i_isolate()->allocator()); 847 i::AstValueFactory ast_value_factory(&zone, 848 CcTest::i_isolate()->heap()->HashSeed()); 849 ast_value_factory.Internalize(CcTest::i_isolate()); 850 i::Handle<i::String> val = 851 scanner.CurrentSymbol(&ast_value_factory)->string(); 852 i::DisallowHeapAllocation no_alloc; 853 i::String::FlatContent content = val->GetFlatContent(); 854 CHECK(content.IsOneByte()); 855 i::Vector<const uint8_t> actual = content.ToOneByteVector(); 856 for (int i = 0; i < actual.length(); i++) { 857 CHECK_NE('\0', expected[i]); 858 CHECK_EQ(expected[i], actual[i]); 859 } 860 } 861 862 863 TEST(RegExpScanning) { 864 v8::V8::Initialize(); 865 866 // RegExp token with added garbage at the end. The scanner should only 867 // scan the RegExp until the terminating slash just before "flipperwald". 868 TestScanRegExp("/b/flipperwald", "b"); 869 // Incomplete escape sequences doesn't hide the terminating slash. 870 TestScanRegExp("/\\x/flipperwald", "\\x"); 871 TestScanRegExp("/\\u/flipperwald", "\\u"); 872 TestScanRegExp("/\\u1/flipperwald", "\\u1"); 873 TestScanRegExp("/\\u12/flipperwald", "\\u12"); 874 TestScanRegExp("/\\u123/flipperwald", "\\u123"); 875 TestScanRegExp("/\\c/flipperwald", "\\c"); 876 TestScanRegExp("/\\c//flipperwald", "\\c"); 877 // Slashes inside character classes are not terminating. 878 TestScanRegExp("/[/]/flipperwald", "[/]"); 879 TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]"); 880 // Incomplete escape sequences inside a character class doesn't hide 881 // the end of the character class. 882 TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]"); 883 TestScanRegExp("/[\\c]/flipperwald", "[\\c]"); 884 TestScanRegExp("/[\\x]/flipperwald", "[\\x]"); 885 TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]"); 886 TestScanRegExp("/[\\u]/flipperwald", "[\\u]"); 887 TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]"); 888 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]"); 889 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]"); 890 // Escaped ']'s wont end the character class. 891 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]"); 892 // Escaped slashes are not terminating. 893 TestScanRegExp("/\\//flipperwald", "\\/"); 894 // Starting with '=' works too. 895 TestScanRegExp("/=/", "="); 896 TestScanRegExp("/=?/", "=?"); 897 } 898 899 900 static int Utf8LengthHelper(const char* s) { 901 int len = i::StrLength(s); 902 int character_length = len; 903 for (int i = 0; i < len; i++) { 904 unsigned char c = s[i]; 905 int input_offset = 0; 906 int output_adjust = 0; 907 if (c > 0x7f) { 908 if (c < 0xc0) continue; 909 if (c >= 0xf0) { 910 if (c >= 0xf8) { 911 // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8 912 // byte. 913 continue; // Handle first UTF-8 byte. 914 } 915 if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) { 916 // This 4 byte sequence could have been coded as a 3 byte sequence. 917 // Record a single kBadChar for the first byte and continue. 918 continue; 919 } 920 input_offset = 3; 921 // 4 bytes of UTF-8 turn into 2 UTF-16 code units. 922 character_length -= 2; 923 } else if (c >= 0xe0) { 924 if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) { 925 // This 3 byte sequence could have been coded as a 2 byte sequence. 926 // Record a single kBadChar for the first byte and continue. 927 continue; 928 } 929 if (c == 0xed) { 930 unsigned char d = s[i + 1]; 931 if ((d < 0x80) || (d > 0x9f)) { 932 // This 3 byte sequence is part of a surrogate pair which is not 933 // supported by UTF-8. Record a single kBadChar for the first byte 934 // and continue. 935 continue; 936 } 937 } 938 input_offset = 2; 939 // 3 bytes of UTF-8 turn into 1 UTF-16 code unit. 940 output_adjust = 2; 941 } else { 942 if ((c & 0x1e) == 0) { 943 // This 2 byte sequence could have been coded as a 1 byte sequence. 944 // Record a single kBadChar for the first byte and continue. 945 continue; 946 } 947 input_offset = 1; 948 // 2 bytes of UTF-8 turn into 1 UTF-16 code unit. 949 output_adjust = 1; 950 } 951 bool bad = false; 952 for (int j = 1; j <= input_offset; j++) { 953 if ((s[i + j] & 0xc0) != 0x80) { 954 // Bad UTF-8 sequence turns the first in the sequence into kBadChar, 955 // which is a single UTF-16 code unit. 956 bad = true; 957 break; 958 } 959 } 960 if (!bad) { 961 i += input_offset; 962 character_length -= output_adjust; 963 } 964 } 965 } 966 return character_length; 967 } 968 969 970 TEST(ScopeUsesArgumentsSuperThis) { 971 static const struct { 972 const char* prefix; 973 const char* suffix; 974 } surroundings[] = { 975 { "function f() {", "}" }, 976 { "var f = () => {", "};" }, 977 { "class C { constructor() {", "} }" }, 978 }; 979 980 enum Expected { 981 NONE = 0, 982 ARGUMENTS = 1, 983 SUPER_PROPERTY = 1 << 1, 984 THIS = 1 << 2, 985 EVAL = 1 << 4 986 }; 987 988 // clang-format off 989 static const struct { 990 const char* body; 991 int expected; 992 } source_data[] = { 993 {"", NONE}, 994 {"return this", THIS}, 995 {"return arguments", ARGUMENTS}, 996 {"return super.x", SUPER_PROPERTY}, 997 {"return arguments[0]", ARGUMENTS}, 998 {"return this + arguments[0]", ARGUMENTS | THIS}, 999 {"return this + arguments[0] + super.x", 1000 ARGUMENTS | SUPER_PROPERTY | THIS}, 1001 {"return x => this + x", THIS}, 1002 {"return x => super.f() + x", SUPER_PROPERTY}, 1003 {"this.foo = 42;", THIS}, 1004 {"this.foo();", THIS}, 1005 {"if (foo()) { this.f() }", THIS}, 1006 {"if (foo()) { super.f() }", SUPER_PROPERTY}, 1007 {"if (arguments.length) { this.f() }", ARGUMENTS | THIS}, 1008 {"while (true) { this.f() }", THIS}, 1009 {"while (true) { super.f() }", SUPER_PROPERTY}, 1010 {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS}, 1011 // Multiple nesting levels must work as well. 1012 {"while (true) { while (true) { while (true) return this } }", THIS}, 1013 {"while (true) { while (true) { while (true) return super.f() } }", 1014 SUPER_PROPERTY}, 1015 {"if (1) { return () => { while (true) new this() } }", THIS}, 1016 {"return function (x) { return this + x }", NONE}, 1017 {"return { m(x) { return super.m() + x } }", NONE}, 1018 {"var x = function () { this.foo = 42 };", NONE}, 1019 {"var x = { m() { super.foo = 42 } };", NONE}, 1020 {"if (1) { return function () { while (true) new this() } }", NONE}, 1021 {"if (1) { return { m() { while (true) super.m() } } }", NONE}, 1022 {"return function (x) { return () => this }", NONE}, 1023 {"return { m(x) { return () => super.m() } }", NONE}, 1024 // Flags must be correctly set when using block scoping. 1025 {"\"use strict\"; while (true) { let x; this, arguments; }", 1026 THIS}, 1027 {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }", 1028 SUPER_PROPERTY | THIS}, 1029 {"\"use strict\"; if (foo()) { let x; this.f() }", THIS}, 1030 {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY}, 1031 {"\"use strict\"; if (1) {" 1032 " let x; return { m() { return this + super.m() + arguments } }" 1033 "}", 1034 NONE}, 1035 {"eval(42)", EVAL}, 1036 {"if (1) { eval(42) }", EVAL}, 1037 {"eval('super.x')", EVAL}, 1038 {"eval('this.x')", EVAL}, 1039 {"eval('arguments')", EVAL}, 1040 }; 1041 // clang-format on 1042 1043 i::Isolate* isolate = CcTest::i_isolate(); 1044 i::Factory* factory = isolate->factory(); 1045 1046 v8::HandleScope handles(CcTest::isolate()); 1047 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 1048 v8::Context::Scope context_scope(context); 1049 1050 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 1051 128 * 1024); 1052 1053 for (unsigned j = 0; j < arraysize(surroundings); ++j) { 1054 for (unsigned i = 0; i < arraysize(source_data); ++i) { 1055 // Super property is only allowed in constructor and method. 1056 if (((source_data[i].expected & SUPER_PROPERTY) || 1057 (source_data[i].expected == NONE)) && j != 2) { 1058 continue; 1059 } 1060 int kProgramByteSize = i::StrLength(surroundings[j].prefix) + 1061 i::StrLength(surroundings[j].suffix) + 1062 i::StrLength(source_data[i].body); 1063 i::ScopedVector<char> program(kProgramByteSize + 1); 1064 i::SNPrintF(program, "%s%s%s", surroundings[j].prefix, 1065 source_data[i].body, surroundings[j].suffix); 1066 i::Handle<i::String> source = 1067 factory->NewStringFromUtf8(i::CStrVector(program.start())) 1068 .ToHandleChecked(); 1069 i::Handle<i::Script> script = factory->NewScript(source); 1070 i::Zone zone(CcTest::i_isolate()->allocator()); 1071 i::ParseInfo info(&zone, script); 1072 i::Parser parser(&info); 1073 info.set_global(); 1074 CHECK(parser.Parse(&info)); 1075 CHECK(i::Rewriter::Rewrite(&info)); 1076 CHECK(i::Scope::Analyze(&info)); 1077 CHECK(info.literal() != NULL); 1078 1079 i::Scope* script_scope = info.literal()->scope(); 1080 CHECK(script_scope->is_script_scope()); 1081 CHECK_EQ(1, script_scope->inner_scopes()->length()); 1082 1083 i::Scope* scope = script_scope->inner_scopes()->at(0); 1084 // Adjust for constructor scope. 1085 if (j == 2) { 1086 CHECK_EQ(1, scope->inner_scopes()->length()); 1087 scope = scope->inner_scopes()->at(0); 1088 } 1089 CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0, 1090 scope->uses_arguments()); 1091 CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0, 1092 scope->uses_super_property()); 1093 if ((source_data[i].expected & THIS) != 0) { 1094 // Currently the is_used() flag is conservative; all variables in a 1095 // script scope are marked as used. 1096 CHECK( 1097 scope->Lookup(info.ast_value_factory()->this_string())->is_used()); 1098 } 1099 CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval()); 1100 } 1101 } 1102 } 1103 1104 1105 static void CheckParsesToNumber(const char* source, bool with_dot) { 1106 v8::V8::Initialize(); 1107 HandleAndZoneScope handles; 1108 1109 i::Isolate* isolate = CcTest::i_isolate(); 1110 i::Factory* factory = isolate->factory(); 1111 1112 std::string full_source = "function f() { return "; 1113 full_source += source; 1114 full_source += "; }"; 1115 1116 i::Handle<i::String> source_code = 1117 factory->NewStringFromUtf8(i::CStrVector(full_source.c_str())) 1118 .ToHandleChecked(); 1119 1120 i::Handle<i::Script> script = factory->NewScript(source_code); 1121 1122 i::ParseInfo info(handles.main_zone(), script); 1123 i::Parser parser(&info); 1124 info.set_global(); 1125 info.set_lazy(false); 1126 info.set_allow_lazy_parsing(false); 1127 info.set_toplevel(true); 1128 1129 CHECK(i::Compiler::ParseAndAnalyze(&info)); 1130 1131 CHECK(info.scope()->declarations()->length() == 1); 1132 i::FunctionLiteral* fun = 1133 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(); 1134 CHECK(fun->body()->length() == 1); 1135 CHECK(fun->body()->at(0)->IsReturnStatement()); 1136 i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement(); 1137 i::Literal* lit = ret->expression()->AsLiteral(); 1138 if (lit != NULL) { 1139 const i::AstValue* val = lit->raw_value(); 1140 CHECK(with_dot == val->ContainsDot()); 1141 } else if (with_dot) { 1142 i::BinaryOperation* bin = ret->expression()->AsBinaryOperation(); 1143 CHECK(bin != NULL); 1144 CHECK_EQ(i::Token::MUL, bin->op()); 1145 i::Literal* rlit = bin->right()->AsLiteral(); 1146 const i::AstValue* val = rlit->raw_value(); 1147 CHECK(with_dot == val->ContainsDot()); 1148 CHECK_EQ(1.0, val->AsNumber()); 1149 } 1150 } 1151 1152 1153 TEST(ParseNumbers) { 1154 CheckParsesToNumber("1.", true); 1155 CheckParsesToNumber("1.34", true); 1156 CheckParsesToNumber("134", false); 1157 CheckParsesToNumber("134e44", false); 1158 CheckParsesToNumber("134.e44", true); 1159 CheckParsesToNumber("134.44e44", true); 1160 CheckParsesToNumber(".44", true); 1161 1162 CheckParsesToNumber("-1.", true); 1163 CheckParsesToNumber("-1.0", true); 1164 CheckParsesToNumber("-1.34", true); 1165 CheckParsesToNumber("-134", false); 1166 CheckParsesToNumber("-134e44", false); 1167 CheckParsesToNumber("-134.e44", true); 1168 CheckParsesToNumber("-134.44e44", true); 1169 CheckParsesToNumber("-.44", true); 1170 1171 CheckParsesToNumber("+x", true); 1172 } 1173 1174 1175 TEST(ScopePositions) { 1176 // Test the parser for correctly setting the start and end positions 1177 // of a scope. We check the scope positions of exactly one scope 1178 // nested in the global scope of a program. 'inner source' is the 1179 // source code that determines the part of the source belonging 1180 // to the nested scope. 'outer_prefix' and 'outer_suffix' are 1181 // parts of the source that belong to the global scope. 1182 struct SourceData { 1183 const char* outer_prefix; 1184 const char* inner_source; 1185 const char* outer_suffix; 1186 i::ScopeType scope_type; 1187 i::LanguageMode language_mode; 1188 }; 1189 1190 const SourceData source_data[] = { 1191 { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY }, 1192 { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY }, 1193 { " with ({}) ", "{\n" 1194 " block;\n" 1195 " }", "\n" 1196 " more;", i::WITH_SCOPE, i::SLOPPY }, 1197 { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY }, 1198 { " with ({}) ", "statement", "\n" 1199 " more;", i::WITH_SCOPE, i::SLOPPY }, 1200 { " with ({})\n" 1201 " ", "statement;", "\n" 1202 " more;", i::WITH_SCOPE, i::SLOPPY }, 1203 { " try {} catch ", "(e) { block; }", " more;", 1204 i::CATCH_SCOPE, i::SLOPPY }, 1205 { " try {} catch ", "(e) { block; }", "; more;", 1206 i::CATCH_SCOPE, i::SLOPPY }, 1207 { " try {} catch ", "(e) {\n" 1208 " block;\n" 1209 " }", "\n" 1210 " more;", i::CATCH_SCOPE, i::SLOPPY }, 1211 { " try {} catch ", "(e) { block; }", " finally { block; } more;", 1212 i::CATCH_SCOPE, i::SLOPPY }, 1213 { " start;\n" 1214 " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT }, 1215 { " start;\n" 1216 " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT }, 1217 { " start;\n" 1218 " ", "{\n" 1219 " let block;\n" 1220 " }", "\n" 1221 " more;", i::BLOCK_SCOPE, i::STRICT }, 1222 { " start;\n" 1223 " function fun", "(a,b) { infunction; }", " more;", 1224 i::FUNCTION_SCOPE, i::SLOPPY }, 1225 { " start;\n" 1226 " function fun", "(a,b) {\n" 1227 " infunction;\n" 1228 " }", "\n" 1229 " more;", i::FUNCTION_SCOPE, i::SLOPPY }, 1230 { " start;\n", "(a,b) => a + b", "; more;", 1231 i::FUNCTION_SCOPE, i::SLOPPY }, 1232 { " start;\n", "(a,b) => { return a+b; }", "\nmore;", 1233 i::FUNCTION_SCOPE, i::SLOPPY }, 1234 { " start;\n" 1235 " (function fun", "(a,b) { infunction; }", ")();", 1236 i::FUNCTION_SCOPE, i::SLOPPY }, 1237 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", 1238 i::BLOCK_SCOPE, i::STRICT }, 1239 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;", 1240 i::BLOCK_SCOPE, i::STRICT }, 1241 { " for ", "(let x = 1 ; x < 10; ++ x) {\n" 1242 " block;\n" 1243 " }", "\n" 1244 " more;", i::BLOCK_SCOPE, i::STRICT }, 1245 { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;", 1246 i::BLOCK_SCOPE, i::STRICT }, 1247 { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n" 1248 " more;", i::BLOCK_SCOPE, i::STRICT }, 1249 { " for ", "(let x = 1 ; x < 10; ++ x)\n" 1250 " statement;", "\n" 1251 " more;", i::BLOCK_SCOPE, i::STRICT }, 1252 { " for ", "(let x in {}) { block; }", " more;", 1253 i::BLOCK_SCOPE, i::STRICT }, 1254 { " for ", "(let x in {}) { block; }", "; more;", 1255 i::BLOCK_SCOPE, i::STRICT }, 1256 { " for ", "(let x in {}) {\n" 1257 " block;\n" 1258 " }", "\n" 1259 " more;", i::BLOCK_SCOPE, i::STRICT }, 1260 { " for ", "(let x in {}) statement;", " more;", 1261 i::BLOCK_SCOPE, i::STRICT }, 1262 { " for ", "(let x in {}) statement", "\n" 1263 " more;", i::BLOCK_SCOPE, i::STRICT }, 1264 { " for ", "(let x in {})\n" 1265 " statement;", "\n" 1266 " more;", i::BLOCK_SCOPE, i::STRICT }, 1267 // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw 1268 // the preparser off in terms of byte offsets. 1269 // 6 byte encoding. 1270 { " 'foo\355\240\201\355\260\211';\n" 1271 " (function fun", "(a,b) { infunction; }", ")();", 1272 i::FUNCTION_SCOPE, i::SLOPPY }, 1273 // 4 byte encoding. 1274 { " 'foo\360\220\220\212';\n" 1275 " (function fun", "(a,b) { infunction; }", ")();", 1276 i::FUNCTION_SCOPE, i::SLOPPY }, 1277 // 3 byte encoding of \u0fff. 1278 { " 'foo\340\277\277';\n" 1279 " (function fun", "(a,b) { infunction; }", ")();", 1280 i::FUNCTION_SCOPE, i::SLOPPY }, 1281 // Broken 6 byte encoding with missing last byte. 1282 { " 'foo\355\240\201\355\211';\n" 1283 " (function fun", "(a,b) { infunction; }", ")();", 1284 i::FUNCTION_SCOPE, i::SLOPPY }, 1285 // Broken 3 byte encoding of \u0fff with missing last byte. 1286 { " 'foo\340\277';\n" 1287 " (function fun", "(a,b) { infunction; }", ")();", 1288 i::FUNCTION_SCOPE, i::SLOPPY }, 1289 // Broken 3 byte encoding of \u0fff with missing 2 last bytes. 1290 { " 'foo\340';\n" 1291 " (function fun", "(a,b) { infunction; }", ")();", 1292 i::FUNCTION_SCOPE, i::SLOPPY }, 1293 // Broken 3 byte encoding of \u00ff should be a 2 byte encoding. 1294 { " 'foo\340\203\277';\n" 1295 " (function fun", "(a,b) { infunction; }", ")();", 1296 i::FUNCTION_SCOPE, i::SLOPPY }, 1297 // Broken 3 byte encoding of \u007f should be a 2 byte encoding. 1298 { " 'foo\340\201\277';\n" 1299 " (function fun", "(a,b) { infunction; }", ")();", 1300 i::FUNCTION_SCOPE, i::SLOPPY }, 1301 // Unpaired lead surrogate. 1302 { " 'foo\355\240\201';\n" 1303 " (function fun", "(a,b) { infunction; }", ")();", 1304 i::FUNCTION_SCOPE, i::SLOPPY }, 1305 // Unpaired lead surrogate where following code point is a 3 byte sequence. 1306 { " 'foo\355\240\201\340\277\277';\n" 1307 " (function fun", "(a,b) { infunction; }", ")();", 1308 i::FUNCTION_SCOPE, i::SLOPPY }, 1309 // Unpaired lead surrogate where following code point is a 4 byte encoding 1310 // of a trail surrogate. 1311 { " 'foo\355\240\201\360\215\260\211';\n" 1312 " (function fun", "(a,b) { infunction; }", ")();", 1313 i::FUNCTION_SCOPE, i::SLOPPY }, 1314 // Unpaired trail surrogate. 1315 { " 'foo\355\260\211';\n" 1316 " (function fun", "(a,b) { infunction; }", ")();", 1317 i::FUNCTION_SCOPE, i::SLOPPY }, 1318 // 2 byte encoding of \u00ff. 1319 { " 'foo\303\277';\n" 1320 " (function fun", "(a,b) { infunction; }", ")();", 1321 i::FUNCTION_SCOPE, i::SLOPPY }, 1322 // Broken 2 byte encoding of \u00ff with missing last byte. 1323 { " 'foo\303';\n" 1324 " (function fun", "(a,b) { infunction; }", ")();", 1325 i::FUNCTION_SCOPE, i::SLOPPY }, 1326 // Broken 2 byte encoding of \u007f should be a 1 byte encoding. 1327 { " 'foo\301\277';\n" 1328 " (function fun", "(a,b) { infunction; }", ")();", 1329 i::FUNCTION_SCOPE, i::SLOPPY }, 1330 // Illegal 5 byte encoding. 1331 { " 'foo\370\277\277\277\277';\n" 1332 " (function fun", "(a,b) { infunction; }", ")();", 1333 i::FUNCTION_SCOPE, i::SLOPPY }, 1334 // Illegal 6 byte encoding. 1335 { " 'foo\374\277\277\277\277\277';\n" 1336 " (function fun", "(a,b) { infunction; }", ")();", 1337 i::FUNCTION_SCOPE, i::SLOPPY }, 1338 // Illegal 0xfe byte 1339 { " 'foo\376\277\277\277\277\277\277';\n" 1340 " (function fun", "(a,b) { infunction; }", ")();", 1341 i::FUNCTION_SCOPE, i::SLOPPY }, 1342 // Illegal 0xff byte 1343 { " 'foo\377\277\277\277\277\277\277\277';\n" 1344 " (function fun", "(a,b) { infunction; }", ")();", 1345 i::FUNCTION_SCOPE, i::SLOPPY }, 1346 { " 'foo';\n" 1347 " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();", 1348 i::FUNCTION_SCOPE, i::SLOPPY }, 1349 { " 'foo';\n" 1350 " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();", 1351 i::FUNCTION_SCOPE, i::SLOPPY }, 1352 { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY } 1353 }; 1354 1355 i::Isolate* isolate = CcTest::i_isolate(); 1356 i::Factory* factory = isolate->factory(); 1357 1358 v8::HandleScope handles(CcTest::isolate()); 1359 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 1360 v8::Context::Scope context_scope(context); 1361 1362 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 1363 128 * 1024); 1364 1365 for (int i = 0; source_data[i].outer_prefix; i++) { 1366 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix); 1367 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source); 1368 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix); 1369 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix); 1370 int kInnerByteLen = i::StrLength(source_data[i].inner_source); 1371 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix); 1372 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; 1373 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen; 1374 i::ScopedVector<char> program(kProgramByteSize + 1); 1375 i::SNPrintF(program, "%s%s%s", 1376 source_data[i].outer_prefix, 1377 source_data[i].inner_source, 1378 source_data[i].outer_suffix); 1379 1380 // Parse program source. 1381 i::Handle<i::String> source = factory->NewStringFromUtf8( 1382 i::CStrVector(program.start())).ToHandleChecked(); 1383 CHECK_EQ(source->length(), kProgramSize); 1384 i::Handle<i::Script> script = factory->NewScript(source); 1385 i::Zone zone(CcTest::i_isolate()->allocator()); 1386 i::ParseInfo info(&zone, script); 1387 i::Parser parser(&info); 1388 parser.set_allow_lazy(true); 1389 info.set_global(); 1390 info.set_language_mode(source_data[i].language_mode); 1391 parser.Parse(&info); 1392 CHECK(info.literal() != NULL); 1393 1394 // Check scope types and positions. 1395 i::Scope* scope = info.literal()->scope(); 1396 CHECK(scope->is_script_scope()); 1397 CHECK_EQ(scope->start_position(), 0); 1398 CHECK_EQ(scope->end_position(), kProgramSize); 1399 CHECK_EQ(scope->inner_scopes()->length(), 1); 1400 1401 i::Scope* inner_scope = scope->inner_scopes()->at(0); 1402 CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type); 1403 CHECK_EQ(inner_scope->start_position(), kPrefixLen); 1404 // The end position of a token is one position after the last 1405 // character belonging to that token. 1406 CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen); 1407 } 1408 } 1409 1410 1411 TEST(DiscardFunctionBody) { 1412 // Test that inner function bodies are discarded if possible. 1413 // See comments in ParseFunctionLiteral in parser.cc. 1414 const char* discard_sources[] = { 1415 "(function f() { function g() { var a; } })();", 1416 "(function f() { function g() { { function h() { } } } })();", 1417 /* TODO(conradw): In future it may be possible to apply this optimisation 1418 * to these productions. 1419 "(function f() { 0, function g() { var a; } })();", 1420 "(function f() { 0, { g() { var a; } } })();", 1421 "(function f() { 0, class c { g() { var a; } } })();", */ 1422 NULL}; 1423 1424 i::Isolate* isolate = CcTest::i_isolate(); 1425 i::Factory* factory = isolate->factory(); 1426 v8::HandleScope handles(CcTest::isolate()); 1427 i::FunctionLiteral* function; 1428 1429 for (int i = 0; discard_sources[i]; i++) { 1430 const char* source = discard_sources[i]; 1431 i::Handle<i::String> source_code = 1432 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked(); 1433 i::Handle<i::Script> script = factory->NewScript(source_code); 1434 i::Zone zone(CcTest::i_isolate()->allocator()); 1435 i::ParseInfo info(&zone, script); 1436 info.set_allow_lazy_parsing(); 1437 i::Parser parser(&info); 1438 parser.Parse(&info); 1439 function = info.literal(); 1440 CHECK_NOT_NULL(function); 1441 CHECK_NOT_NULL(function->body()); 1442 CHECK_EQ(1, function->body()->length()); 1443 i::FunctionLiteral* inner = 1444 function->body()->first()->AsExpressionStatement()->expression()-> 1445 AsCall()->expression()->AsFunctionLiteral(); 1446 i::Scope* inner_scope = inner->scope(); 1447 i::FunctionLiteral* fun = nullptr; 1448 if (inner_scope->declarations()->length() > 1) { 1449 fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun(); 1450 } else { 1451 // TODO(conradw): This path won't be hit until the other test cases can be 1452 // uncommented. 1453 UNREACHABLE(); 1454 CHECK_NOT_NULL(inner->body()); 1455 CHECK_GE(2, inner->body()->length()); 1456 i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()-> 1457 expression()->AsBinaryOperation()->right(); 1458 if (exp->IsFunctionLiteral()) { 1459 fun = exp->AsFunctionLiteral(); 1460 } else if (exp->IsObjectLiteral()) { 1461 fun = exp->AsObjectLiteral()->properties()->at(0)->value()-> 1462 AsFunctionLiteral(); 1463 } else { 1464 fun = exp->AsClassLiteral()->properties()->at(0)->value()-> 1465 AsFunctionLiteral(); 1466 } 1467 } 1468 CHECK_NULL(fun->body()); 1469 } 1470 } 1471 1472 1473 const char* ReadString(unsigned* start) { 1474 int length = start[0]; 1475 char* result = i::NewArray<char>(length + 1); 1476 for (int i = 0; i < length; i++) { 1477 result[i] = start[i + 1]; 1478 } 1479 result[length] = '\0'; 1480 return result; 1481 } 1482 1483 1484 i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) { 1485 i::Isolate* isolate = CcTest::i_isolate(); 1486 int message = data[i::PreparseDataConstants::kMessageTemplatePos]; 1487 int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos]; 1488 i::Handle<i::Object> arg_object; 1489 if (arg_count == 1) { 1490 // Position after text found by skipping past length field and 1491 // length field content words. 1492 const char* arg = 1493 ReadString(&data[i::PreparseDataConstants::kMessageArgPos]); 1494 arg_object = v8::Utils::OpenHandle(*v8_str(arg)); 1495 i::DeleteArray(arg); 1496 } else { 1497 CHECK_EQ(0, arg_count); 1498 arg_object = isolate->factory()->undefined_value(); 1499 } 1500 1501 data.Dispose(); 1502 return i::MessageTemplate::FormatMessage(isolate, message, arg_object); 1503 } 1504 1505 enum ParserFlag { 1506 kAllowLazy, 1507 kAllowNatives, 1508 kAllowHarmonyFunctionSent, 1509 kAllowHarmonyRestrictiveDeclarations, 1510 kAllowHarmonyExponentiationOperator, 1511 kAllowHarmonyForIn, 1512 kAllowHarmonyAsyncAwait, 1513 kAllowHarmonyRestrictiveGenerators, 1514 }; 1515 1516 enum ParserSyncTestResult { 1517 kSuccessOrError, 1518 kSuccess, 1519 kError 1520 }; 1521 1522 template <typename Traits> 1523 void SetParserFlags(i::ParserBase<Traits>* parser, 1524 i::EnumSet<ParserFlag> flags) { 1525 parser->set_allow_lazy(flags.Contains(kAllowLazy)); 1526 parser->set_allow_natives(flags.Contains(kAllowNatives)); 1527 parser->set_allow_harmony_function_sent( 1528 flags.Contains(kAllowHarmonyFunctionSent)); 1529 parser->set_allow_harmony_restrictive_declarations( 1530 flags.Contains(kAllowHarmonyRestrictiveDeclarations)); 1531 parser->set_allow_harmony_exponentiation_operator( 1532 flags.Contains(kAllowHarmonyExponentiationOperator)); 1533 parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn)); 1534 parser->set_allow_harmony_async_await( 1535 flags.Contains(kAllowHarmonyAsyncAwait)); 1536 parser->set_allow_harmony_restrictive_generators( 1537 flags.Contains(kAllowHarmonyRestrictiveGenerators)); 1538 } 1539 1540 1541 void TestParserSyncWithFlags(i::Handle<i::String> source, 1542 i::EnumSet<ParserFlag> flags, 1543 ParserSyncTestResult result, 1544 bool is_module = false, 1545 bool test_preparser = true) { 1546 i::Isolate* isolate = CcTest::i_isolate(); 1547 i::Factory* factory = isolate->factory(); 1548 1549 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); 1550 int preparser_materialized_literals = -1; 1551 int parser_materialized_literals = -2; 1552 1553 // Preparse the data. 1554 i::CompleteParserRecorder log; 1555 if (test_preparser) { 1556 i::Scanner scanner(isolate->unicode_cache()); 1557 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); 1558 i::Zone zone(CcTest::i_isolate()->allocator()); 1559 i::AstValueFactory ast_value_factory( 1560 &zone, CcTest::i_isolate()->heap()->HashSeed()); 1561 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log, 1562 stack_limit); 1563 SetParserFlags(&preparser, flags); 1564 scanner.Initialize(&stream); 1565 i::PreParser::PreParseResult result = 1566 preparser.PreParseProgram(&preparser_materialized_literals, is_module); 1567 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 1568 } 1569 bool preparse_error = log.HasError(); 1570 1571 // Parse the data 1572 i::FunctionLiteral* function; 1573 { 1574 i::Handle<i::Script> script = factory->NewScript(source); 1575 i::Zone zone(CcTest::i_isolate()->allocator()); 1576 i::ParseInfo info(&zone, script); 1577 i::Parser parser(&info); 1578 SetParserFlags(&parser, flags); 1579 if (is_module) { 1580 info.set_module(); 1581 } else { 1582 info.set_global(); 1583 } 1584 parser.Parse(&info); 1585 function = info.literal(); 1586 if (function) { 1587 parser_materialized_literals = function->materialized_literal_count(); 1588 } 1589 } 1590 1591 // Check that preparsing fails iff parsing fails. 1592 if (function == NULL) { 1593 // Extract exception from the parser. 1594 CHECK(isolate->has_pending_exception()); 1595 i::Handle<i::JSObject> exception_handle( 1596 i::JSObject::cast(isolate->pending_exception())); 1597 i::Handle<i::String> message_string = i::Handle<i::String>::cast( 1598 i::JSReceiver::GetProperty(isolate, exception_handle, "message") 1599 .ToHandleChecked()); 1600 1601 if (result == kSuccess) { 1602 v8::base::OS::Print( 1603 "Parser failed on:\n" 1604 "\t%s\n" 1605 "with error:\n" 1606 "\t%s\n" 1607 "However, we expected no error.", 1608 source->ToCString().get(), message_string->ToCString().get()); 1609 CHECK(false); 1610 } 1611 1612 if (test_preparser && !preparse_error) { 1613 v8::base::OS::Print( 1614 "Parser failed on:\n" 1615 "\t%s\n" 1616 "with error:\n" 1617 "\t%s\n" 1618 "However, the preparser succeeded", 1619 source->ToCString().get(), message_string->ToCString().get()); 1620 CHECK(false); 1621 } 1622 // Check that preparser and parser produce the same error. 1623 if (test_preparser) { 1624 i::Handle<i::String> preparser_message = 1625 FormatMessage(log.ErrorMessageData()); 1626 if (!i::String::Equals(message_string, preparser_message)) { 1627 v8::base::OS::Print( 1628 "Expected parser and preparser to produce the same error on:\n" 1629 "\t%s\n" 1630 "However, found the following error messages\n" 1631 "\tparser: %s\n" 1632 "\tpreparser: %s\n", 1633 source->ToCString().get(), message_string->ToCString().get(), 1634 preparser_message->ToCString().get()); 1635 CHECK(false); 1636 } 1637 } 1638 } else if (test_preparser && preparse_error) { 1639 v8::base::OS::Print( 1640 "Preparser failed on:\n" 1641 "\t%s\n" 1642 "with error:\n" 1643 "\t%s\n" 1644 "However, the parser succeeded", 1645 source->ToCString().get(), 1646 FormatMessage(log.ErrorMessageData())->ToCString().get()); 1647 CHECK(false); 1648 } else if (result == kError) { 1649 v8::base::OS::Print( 1650 "Expected error on:\n" 1651 "\t%s\n" 1652 "However, parser and preparser succeeded", 1653 source->ToCString().get()); 1654 CHECK(false); 1655 } else if (test_preparser && 1656 preparser_materialized_literals != parser_materialized_literals) { 1657 v8::base::OS::Print( 1658 "Preparser materialized literals (%d) differ from Parser materialized " 1659 "literals (%d) on:\n" 1660 "\t%s\n" 1661 "However, parser and preparser succeeded", 1662 preparser_materialized_literals, parser_materialized_literals, 1663 source->ToCString().get()); 1664 CHECK(false); 1665 } 1666 } 1667 1668 1669 void TestParserSync(const char* source, const ParserFlag* varying_flags, 1670 size_t varying_flags_length, 1671 ParserSyncTestResult result = kSuccessOrError, 1672 const ParserFlag* always_true_flags = NULL, 1673 size_t always_true_flags_length = 0, 1674 const ParserFlag* always_false_flags = NULL, 1675 size_t always_false_flags_length = 0, 1676 bool is_module = false, bool test_preparser = true) { 1677 i::Handle<i::String> str = 1678 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source); 1679 for (int bits = 0; bits < (1 << varying_flags_length); bits++) { 1680 i::EnumSet<ParserFlag> flags; 1681 for (size_t flag_index = 0; flag_index < varying_flags_length; 1682 ++flag_index) { 1683 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]); 1684 } 1685 for (size_t flag_index = 0; flag_index < always_true_flags_length; 1686 ++flag_index) { 1687 flags.Add(always_true_flags[flag_index]); 1688 } 1689 for (size_t flag_index = 0; flag_index < always_false_flags_length; 1690 ++flag_index) { 1691 flags.Remove(always_false_flags[flag_index]); 1692 } 1693 TestParserSyncWithFlags(str, flags, result, is_module, test_preparser); 1694 } 1695 } 1696 1697 1698 TEST(ParserSync) { 1699 const char* context_data[][2] = { 1700 { "", "" }, 1701 { "{", "}" }, 1702 { "if (true) ", " else {}" }, 1703 { "if (true) {} else ", "" }, 1704 { "if (true) ", "" }, 1705 { "do ", " while (false)" }, 1706 { "while (false) ", "" }, 1707 { "for (;;) ", "" }, 1708 { "with ({})", "" }, 1709 { "switch (12) { case 12: ", "}" }, 1710 { "switch (12) { default: ", "}" }, 1711 { "switch (12) { ", "case 12: }" }, 1712 { "label2: ", "" }, 1713 { NULL, NULL } 1714 }; 1715 1716 const char* statement_data[] = { 1717 "{}", 1718 "var x", 1719 "var x = 1", 1720 "const x", 1721 "const x = 1", 1722 ";", 1723 "12", 1724 "if (false) {} else ;", 1725 "if (false) {} else {}", 1726 "if (false) {} else 12", 1727 "if (false) ;", 1728 "if (false) {}", 1729 "if (false) 12", 1730 "do {} while (false)", 1731 "for (;;) ;", 1732 "for (;;) {}", 1733 "for (;;) 12", 1734 "continue", 1735 "continue label", 1736 "continue\nlabel", 1737 "break", 1738 "break label", 1739 "break\nlabel", 1740 // TODO(marja): activate once parsing 'return' is merged into ParserBase. 1741 // "return", 1742 // "return 12", 1743 // "return\n12", 1744 "with ({}) ;", 1745 "with ({}) {}", 1746 "with ({}) 12", 1747 "switch ({}) { default: }", 1748 "label3: ", 1749 "throw", 1750 "throw 12", 1751 "throw\n12", 1752 "try {} catch(e) {}", 1753 "try {} finally {}", 1754 "try {} catch(e) {} finally {}", 1755 "debugger", 1756 NULL 1757 }; 1758 1759 const char* termination_data[] = { 1760 "", 1761 ";", 1762 "\n", 1763 ";\n", 1764 "\n;", 1765 NULL 1766 }; 1767 1768 v8::HandleScope handles(CcTest::isolate()); 1769 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 1770 v8::Context::Scope context_scope(context); 1771 1772 CcTest::i_isolate()->stack_guard()->SetStackLimit( 1773 i::GetCurrentStackPosition() - 128 * 1024); 1774 1775 for (int i = 0; context_data[i][0] != NULL; ++i) { 1776 for (int j = 0; statement_data[j] != NULL; ++j) { 1777 for (int k = 0; termination_data[k] != NULL; ++k) { 1778 int kPrefixLen = i::StrLength(context_data[i][0]); 1779 int kStatementLen = i::StrLength(statement_data[j]); 1780 int kTerminationLen = i::StrLength(termination_data[k]); 1781 int kSuffixLen = i::StrLength(context_data[i][1]); 1782 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen 1783 + kSuffixLen + i::StrLength("label: for (;;) { }"); 1784 1785 // Plug the source code pieces together. 1786 i::ScopedVector<char> program(kProgramSize + 1); 1787 int length = i::SNPrintF(program, 1788 "label: for (;;) { %s%s%s%s }", 1789 context_data[i][0], 1790 statement_data[j], 1791 termination_data[k], 1792 context_data[i][1]); 1793 CHECK(length == kProgramSize); 1794 TestParserSync(program.start(), NULL, 0); 1795 } 1796 } 1797 } 1798 1799 // Neither Harmony numeric literals nor our natives syntax have any 1800 // interaction with the flags above, so test these separately to reduce 1801 // the combinatorial explosion. 1802 TestParserSync("0o1234", NULL, 0); 1803 TestParserSync("0b1011", NULL, 0); 1804 1805 static const ParserFlag flags3[] = { kAllowNatives }; 1806 TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3)); 1807 } 1808 1809 1810 TEST(StrictOctal) { 1811 // Test that syntax error caused by octal literal is reported correctly as 1812 // such (issue 2220). 1813 v8::V8::Initialize(); 1814 v8::HandleScope scope(CcTest::isolate()); 1815 v8::Context::Scope context_scope( 1816 v8::Context::New(CcTest::isolate())); 1817 v8::TryCatch try_catch(CcTest::isolate()); 1818 const char* script = 1819 "\"use strict\"; \n" 1820 "a = function() { \n" 1821 " b = function() { \n" 1822 " 01; \n" 1823 " }; \n" 1824 "}; \n"; 1825 v8_compile(v8_str(script)); 1826 CHECK(try_catch.HasCaught()); 1827 v8::String::Utf8Value exception(try_catch.Exception()); 1828 CHECK_EQ(0, 1829 strcmp("SyntaxError: Octal literals are not allowed in strict mode.", 1830 *exception)); 1831 } 1832 1833 1834 void RunParserSyncTest(const char* context_data[][2], 1835 const char* statement_data[], 1836 ParserSyncTestResult result, 1837 const ParserFlag* flags = NULL, int flags_len = 0, 1838 const ParserFlag* always_true_flags = NULL, 1839 int always_true_len = 0, 1840 const ParserFlag* always_false_flags = NULL, 1841 int always_false_len = 0, bool is_module = false, 1842 bool test_preparser = true) { 1843 v8::HandleScope handles(CcTest::isolate()); 1844 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 1845 v8::Context::Scope context_scope(context); 1846 1847 CcTest::i_isolate()->stack_guard()->SetStackLimit( 1848 i::GetCurrentStackPosition() - 128 * 1024); 1849 1850 // Experimental feature flags should not go here; pass the flags as 1851 // always_true_flags if the test needs them. 1852 static const ParserFlag default_flags[] = { 1853 kAllowLazy, 1854 kAllowNatives, 1855 }; 1856 ParserFlag* generated_flags = NULL; 1857 if (flags == NULL) { 1858 flags = default_flags; 1859 flags_len = arraysize(default_flags); 1860 if (always_true_flags != NULL || always_false_flags != NULL) { 1861 // Remove always_true/false_flags from default_flags (if present). 1862 CHECK((always_true_flags != NULL) == (always_true_len > 0)); 1863 CHECK((always_false_flags != NULL) == (always_false_len > 0)); 1864 generated_flags = new ParserFlag[flags_len + always_true_len]; 1865 int flag_index = 0; 1866 for (int i = 0; i < flags_len; ++i) { 1867 bool use_flag = true; 1868 for (int j = 0; use_flag && j < always_true_len; ++j) { 1869 if (flags[i] == always_true_flags[j]) use_flag = false; 1870 } 1871 for (int j = 0; use_flag && j < always_false_len; ++j) { 1872 if (flags[i] == always_false_flags[j]) use_flag = false; 1873 } 1874 if (use_flag) generated_flags[flag_index++] = flags[i]; 1875 } 1876 flags_len = flag_index; 1877 flags = generated_flags; 1878 } 1879 } 1880 for (int i = 0; context_data[i][0] != NULL; ++i) { 1881 for (int j = 0; statement_data[j] != NULL; ++j) { 1882 int kPrefixLen = i::StrLength(context_data[i][0]); 1883 int kStatementLen = i::StrLength(statement_data[j]); 1884 int kSuffixLen = i::StrLength(context_data[i][1]); 1885 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen; 1886 1887 // Plug the source code pieces together. 1888 i::ScopedVector<char> program(kProgramSize + 1); 1889 int length = i::SNPrintF(program, 1890 "%s%s%s", 1891 context_data[i][0], 1892 statement_data[j], 1893 context_data[i][1]); 1894 CHECK(length == kProgramSize); 1895 TestParserSync(program.start(), flags, flags_len, result, 1896 always_true_flags, always_true_len, always_false_flags, 1897 always_false_len, is_module, test_preparser); 1898 } 1899 } 1900 delete[] generated_flags; 1901 } 1902 1903 1904 void RunModuleParserSyncTest(const char* context_data[][2], 1905 const char* statement_data[], 1906 ParserSyncTestResult result, 1907 const ParserFlag* flags = NULL, int flags_len = 0, 1908 const ParserFlag* always_true_flags = NULL, 1909 int always_true_len = 0, 1910 const ParserFlag* always_false_flags = NULL, 1911 int always_false_len = 0, 1912 bool test_preparser = true) { 1913 RunParserSyncTest(context_data, statement_data, result, flags, flags_len, 1914 always_true_flags, always_true_len, always_false_flags, 1915 always_false_len, true, test_preparser); 1916 } 1917 1918 1919 TEST(ErrorsEvalAndArguments) { 1920 // Tests that both preparsing and parsing produce the right kind of errors for 1921 // using "eval" and "arguments" as identifiers. Without the strict mode, it's 1922 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it 1923 // isn't. 1924 const char* context_data[][2] = { 1925 {"\"use strict\";", ""}, 1926 {"var eval; function test_func() {\"use strict\"; ", "}"}, 1927 {NULL, NULL}}; 1928 1929 const char* statement_data[] = { 1930 "var eval;", 1931 "var arguments", 1932 "var foo, eval;", 1933 "var foo, arguments;", 1934 "try { } catch (eval) { }", 1935 "try { } catch (arguments) { }", 1936 "function eval() { }", 1937 "function arguments() { }", 1938 "function foo(eval) { }", 1939 "function foo(arguments) { }", 1940 "function foo(bar, eval) { }", 1941 "function foo(bar, arguments) { }", 1942 "(eval) => { }", 1943 "(arguments) => { }", 1944 "(foo, eval) => { }", 1945 "(foo, arguments) => { }", 1946 "eval = 1;", 1947 "arguments = 1;", 1948 "var foo = eval = 1;", 1949 "var foo = arguments = 1;", 1950 "++eval;", 1951 "++arguments;", 1952 "eval++;", 1953 "arguments++;", 1954 NULL 1955 }; 1956 1957 RunParserSyncTest(context_data, statement_data, kError); 1958 } 1959 1960 1961 TEST(NoErrorsEvalAndArgumentsSloppy) { 1962 // Tests that both preparsing and parsing accept "eval" and "arguments" as 1963 // identifiers when needed. 1964 const char* context_data[][2] = { 1965 { "", "" }, 1966 { "function test_func() {", "}"}, 1967 { NULL, NULL } 1968 }; 1969 1970 const char* statement_data[] = { 1971 "var eval;", 1972 "var arguments", 1973 "var foo, eval;", 1974 "var foo, arguments;", 1975 "try { } catch (eval) { }", 1976 "try { } catch (arguments) { }", 1977 "function eval() { }", 1978 "function arguments() { }", 1979 "function foo(eval) { }", 1980 "function foo(arguments) { }", 1981 "function foo(bar, eval) { }", 1982 "function foo(bar, arguments) { }", 1983 "eval = 1;", 1984 "arguments = 1;", 1985 "var foo = eval = 1;", 1986 "var foo = arguments = 1;", 1987 "++eval;", 1988 "++arguments;", 1989 "eval++;", 1990 "arguments++;", 1991 NULL 1992 }; 1993 1994 RunParserSyncTest(context_data, statement_data, kSuccess); 1995 } 1996 1997 1998 TEST(NoErrorsEvalAndArgumentsStrict) { 1999 const char* context_data[][2] = { 2000 { "\"use strict\";", "" }, 2001 { "function test_func() { \"use strict\";", "}" }, 2002 { "() => { \"use strict\"; ", "}" }, 2003 { NULL, NULL } 2004 }; 2005 2006 const char* statement_data[] = { 2007 "eval;", 2008 "arguments;", 2009 "var foo = eval;", 2010 "var foo = arguments;", 2011 "var foo = { eval: 1 };", 2012 "var foo = { arguments: 1 };", 2013 "var foo = { }; foo.eval = {};", 2014 "var foo = { }; foo.arguments = {};", 2015 NULL 2016 }; 2017 2018 RunParserSyncTest(context_data, statement_data, kSuccess); 2019 } 2020 2021 #define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \ 2022 V(implements) \ 2023 V(interface) \ 2024 V(package) \ 2025 V(private) \ 2026 V(protected) \ 2027 V(public) \ 2028 V(static) \ 2029 V(yield) 2030 2031 #define FUTURE_STRICT_RESERVED_WORDS(V) \ 2032 V(let) \ 2033 FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) 2034 2035 #define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \ 2036 V(implements) \ 2037 V(static) \ 2038 V(yield) 2039 2040 #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \ 2041 V(let) \ 2042 LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) 2043 2044 #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \ 2045 "var " #NAME ";", \ 2046 "var foo, " #NAME ";", \ 2047 "try { } catch (" #NAME ") { }", \ 2048 "function " #NAME "() { }", \ 2049 "(function " #NAME "() { })", \ 2050 "function foo(" #NAME ") { }", \ 2051 "function foo(bar, " #NAME ") { }", \ 2052 #NAME " = 1;", \ 2053 #NAME " += 1;", \ 2054 "var foo = " #NAME " = 1;", \ 2055 "++" #NAME ";", \ 2056 #NAME " ++;", 2057 2058 // clang-format off 2059 #define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \ 2060 "let " #NAME ";", \ 2061 "for (let " #NAME "; false; ) {}", \ 2062 "for (let " #NAME " in {}) {}", \ 2063 "for (let " #NAME " of []) {}", \ 2064 "const " #NAME " = null;", \ 2065 "for (const " #NAME " = null; false; ) {}", \ 2066 "for (const " #NAME " in {}) {}", \ 2067 "for (const " #NAME " of []) {}", 2068 // clang-format on 2069 2070 TEST(ErrorsFutureStrictReservedWords) { 2071 // Tests that both preparsing and parsing produce the right kind of errors for 2072 // using future strict reserved words as identifiers. Without the strict mode, 2073 // it's ok to use future strict reserved words as identifiers. With the strict 2074 // mode, it isn't. 2075 const char* strict_contexts[][2] = { 2076 {"function test_func() {\"use strict\"; ", "}"}, 2077 {"() => { \"use strict\"; ", "}"}, 2078 {NULL, NULL}}; 2079 2080 // clang-format off 2081 const char* statement_data[] { 2082 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS) 2083 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS) 2084 NULL 2085 }; 2086 // clang-format on 2087 2088 RunParserSyncTest(strict_contexts, statement_data, kError); 2089 2090 // From ES2015, 13.3.1.1 Static Semantics: Early Errors: 2091 // 2092 // > LexicalDeclaration : LetOrConst BindingList ; 2093 // > 2094 // > - It is a Syntax Error if the BoundNames of BindingList contains "let". 2095 const char* non_strict_contexts[][2] = {{"", ""}, 2096 {"function test_func() {", "}"}, 2097 {"() => {", "}"}, 2098 {NULL, NULL}}; 2099 const char* invalid_statements[] = {FUTURE_STRICT_RESERVED_LEX_BINDINGS("let") 2100 NULL}; 2101 2102 RunParserSyncTest(non_strict_contexts, invalid_statements, kError); 2103 } 2104 2105 #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS 2106 2107 2108 TEST(NoErrorsFutureStrictReservedWords) { 2109 const char* context_data[][2] = { 2110 { "", "" }, 2111 { "function test_func() {", "}"}, 2112 { "() => {", "}" }, 2113 { NULL, NULL } 2114 }; 2115 2116 // clang-format off 2117 const char* statement_data[] = { 2118 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS) 2119 FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS) 2120 NULL 2121 }; 2122 // clang-format on 2123 2124 RunParserSyncTest(context_data, statement_data, kSuccess); 2125 } 2126 2127 2128 TEST(ErrorsReservedWords) { 2129 // Tests that both preparsing and parsing produce the right kind of errors for 2130 // using future reserved words as identifiers. These tests don't depend on the 2131 // strict mode. 2132 const char* context_data[][2] = { 2133 { "", "" }, 2134 { "\"use strict\";", "" }, 2135 { "var eval; function test_func() {", "}"}, 2136 { "var eval; function test_func() {\"use strict\"; ", "}"}, 2137 { "var eval; () => {", "}"}, 2138 { "var eval; () => {\"use strict\"; ", "}"}, 2139 { NULL, NULL } 2140 }; 2141 2142 const char* statement_data[] = { 2143 "var super;", 2144 "var foo, super;", 2145 "try { } catch (super) { }", 2146 "function super() { }", 2147 "function foo(super) { }", 2148 "function foo(bar, super) { }", 2149 "(super) => { }", 2150 "(bar, super) => { }", 2151 "super = 1;", 2152 "var foo = super = 1;", 2153 "++super;", 2154 "super++;", 2155 "function foo super", 2156 NULL 2157 }; 2158 2159 RunParserSyncTest(context_data, statement_data, kError); 2160 } 2161 2162 2163 TEST(NoErrorsLetSloppyAllModes) { 2164 // In sloppy mode, it's okay to use "let" as identifier. 2165 const char* context_data[][2] = { 2166 { "", "" }, 2167 { "function f() {", "}" }, 2168 { "(function f() {", "})" }, 2169 { NULL, NULL } 2170 }; 2171 2172 const char* statement_data[] = { 2173 "var let;", 2174 "var foo, let;", 2175 "try { } catch (let) { }", 2176 "function let() { }", 2177 "(function let() { })", 2178 "function foo(let) { }", 2179 "function foo(bar, let) { }", 2180 "let = 1;", 2181 "var foo = let = 1;", 2182 "let * 2;", 2183 "++let;", 2184 "let++;", 2185 "let: 34", 2186 "function let(let) { let: let(let + let(0)); }", 2187 "({ let: 1 })", 2188 "({ get let() { 1 } })", 2189 "let(100)", 2190 NULL 2191 }; 2192 2193 RunParserSyncTest(context_data, statement_data, kSuccess); 2194 } 2195 2196 2197 TEST(NoErrorsYieldSloppyAllModes) { 2198 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a 2199 // generator (see other test). 2200 const char* context_data[][2] = { 2201 { "", "" }, 2202 { "function not_gen() {", "}" }, 2203 { "(function not_gen() {", "})" }, 2204 { NULL, NULL } 2205 }; 2206 2207 const char* statement_data[] = { 2208 "var yield;", 2209 "var foo, yield;", 2210 "try { } catch (yield) { }", 2211 "function yield() { }", 2212 "(function yield() { })", 2213 "function foo(yield) { }", 2214 "function foo(bar, yield) { }", 2215 "yield = 1;", 2216 "var foo = yield = 1;", 2217 "yield * 2;", 2218 "++yield;", 2219 "yield++;", 2220 "yield: 34", 2221 "function yield(yield) { yield: yield (yield + yield(0)); }", 2222 "({ yield: 1 })", 2223 "({ get yield() { 1 } })", 2224 "yield(100)", 2225 "yield[100]", 2226 NULL 2227 }; 2228 2229 RunParserSyncTest(context_data, statement_data, kSuccess); 2230 } 2231 2232 2233 TEST(NoErrorsYieldSloppyGeneratorsEnabled) { 2234 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a 2235 // generator (see next test). 2236 const char* context_data[][2] = { 2237 { "", "" }, 2238 { "function not_gen() {", "}" }, 2239 { "function * gen() { function not_gen() {", "} }" }, 2240 { "(function not_gen() {", "})" }, 2241 { "(function * gen() { (function not_gen() {", "}) })" }, 2242 { NULL, NULL } 2243 }; 2244 2245 const char* statement_data[] = { 2246 "var yield;", 2247 "var foo, yield;", 2248 "try { } catch (yield) { }", 2249 "function yield() { }", 2250 "(function yield() { })", 2251 "function foo(yield) { }", 2252 "function foo(bar, yield) { }", 2253 "function * yield() { }", 2254 "yield = 1;", 2255 "var foo = yield = 1;", 2256 "yield * 2;", 2257 "++yield;", 2258 "yield++;", 2259 "yield: 34", 2260 "function yield(yield) { yield: yield (yield + yield(0)); }", 2261 "({ yield: 1 })", 2262 "({ get yield() { 1 } })", 2263 "yield(100)", 2264 "yield[100]", 2265 NULL 2266 }; 2267 2268 RunParserSyncTest(context_data, statement_data, kSuccess); 2269 } 2270 2271 2272 TEST(ErrorsYieldStrict) { 2273 const char* context_data[][2] = { 2274 {"\"use strict\";", ""}, 2275 {"\"use strict\"; function not_gen() {", "}"}, 2276 {"function test_func() {\"use strict\"; ", "}"}, 2277 {"\"use strict\"; function * gen() { function not_gen() {", "} }"}, 2278 {"\"use strict\"; (function not_gen() {", "})"}, 2279 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"}, 2280 {"() => {\"use strict\"; ", "}"}, 2281 {NULL, NULL}}; 2282 2283 const char* statement_data[] = { 2284 "var yield;", 2285 "var foo, yield;", 2286 "try { } catch (yield) { }", 2287 "function yield() { }", 2288 "(function yield() { })", 2289 "function foo(yield) { }", 2290 "function foo(bar, yield) { }", 2291 "function * yield() { }", 2292 "(function * yield() { })", 2293 "yield = 1;", 2294 "var foo = yield = 1;", 2295 "++yield;", 2296 "yield++;", 2297 "yield: 34;", 2298 NULL 2299 }; 2300 2301 RunParserSyncTest(context_data, statement_data, kError); 2302 } 2303 2304 2305 TEST(ErrorsYieldSloppy) { 2306 const char* context_data[][2] = { 2307 { "", "" }, 2308 { "function not_gen() {", "}" }, 2309 { "(function not_gen() {", "})" }, 2310 { NULL, NULL } 2311 }; 2312 2313 const char* statement_data[] = { 2314 "(function * yield() { })", 2315 NULL 2316 }; 2317 2318 RunParserSyncTest(context_data, statement_data, kError); 2319 } 2320 2321 2322 TEST(NoErrorsGenerator) { 2323 // clang-format off 2324 const char* context_data[][2] = { 2325 { "function * gen() {", "}" }, 2326 { "(function * gen() {", "})" }, 2327 { "(function * () {", "})" }, 2328 { NULL, NULL } 2329 }; 2330 2331 const char* statement_data[] = { 2332 // A generator without a body is valid. 2333 "" 2334 // Valid yield expressions inside generators. 2335 "yield 2;", 2336 "yield * 2;", 2337 "yield * \n 2;", 2338 "yield yield 1;", 2339 "yield * yield * 1;", 2340 "yield 3 + (yield 4);", 2341 "yield * 3 + (yield * 4);", 2342 "(yield * 3) + (yield * 4);", 2343 "yield 3; yield 4;", 2344 "yield * 3; yield * 4;", 2345 "(function (yield) { })", 2346 "(function yield() { })", 2347 "yield { yield: 12 }", 2348 "yield /* comment */ { yield: 12 }", 2349 "yield * \n { yield: 12 }", 2350 "yield /* comment */ * \n { yield: 12 }", 2351 // You can return in a generator. 2352 "yield 1; return", 2353 "yield * 1; return", 2354 "yield 1; return 37", 2355 "yield * 1; return 37", 2356 "yield 1; return 37; yield 'dead';", 2357 "yield * 1; return 37; yield * 'dead';", 2358 // Yield is still a valid key in object literals. 2359 "({ yield: 1 })", 2360 "({ get yield() { } })", 2361 // And in assignment pattern computed properties 2362 "({ [yield]: x } = { })", 2363 // Yield without RHS. 2364 "yield;", 2365 "yield", 2366 "yield\n", 2367 "yield /* comment */" 2368 "yield // comment\n" 2369 "(yield)", 2370 "[yield]", 2371 "{yield}", 2372 "yield, yield", 2373 "yield; yield", 2374 "(yield) ? yield : yield", 2375 "(yield) \n ? yield : yield", 2376 // If there is a newline before the next token, we don't look for RHS. 2377 "yield\nfor (;;) {}", 2378 "x = class extends (yield) {}", 2379 "x = class extends f(yield) {}", 2380 "x = class extends (null, yield) { }", 2381 "x = class extends (a ? null : yield) { }", 2382 NULL 2383 }; 2384 // clang-format on 2385 2386 RunParserSyncTest(context_data, statement_data, kSuccess); 2387 } 2388 2389 2390 TEST(ErrorsYieldGenerator) { 2391 // clang-format off 2392 const char* context_data[][2] = { 2393 { "function * gen() {", "}" }, 2394 { "\"use strict\"; function * gen() {", "}" }, 2395 { NULL, NULL } 2396 }; 2397 2398 const char* statement_data[] = { 2399 // Invalid yield expressions inside generators. 2400 "var yield;", 2401 "var foo, yield;", 2402 "try { } catch (yield) { }", 2403 "function yield() { }", 2404 // The name of the NFE is bound in the generator, which does not permit 2405 // yield to be an identifier. 2406 "(function * yield() { })", 2407 // Yield isn't valid as a formal parameter for generators. 2408 "function * foo(yield) { }", 2409 "(function * foo(yield) { })", 2410 "yield = 1;", 2411 "var foo = yield = 1;", 2412 "++yield;", 2413 "yield++;", 2414 "yield *", 2415 "(yield *)", 2416 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which 2417 // is invalid. 2418 "yield 3 + yield 4;", 2419 "yield: 34", 2420 "yield ? 1 : 2", 2421 // Parses as yield (/ yield): invalid. 2422 "yield / yield", 2423 "+ yield", 2424 "+ yield 3", 2425 // Invalid (no newline allowed between yield and *). 2426 "yield\n*3", 2427 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an 2428 // object literal, and yield is not a valid label). 2429 "yield\n{yield: 42}", 2430 "yield /* comment */\n {yield: 42}", 2431 "yield //comment\n {yield: 42}", 2432 // Destructuring binding and assignment are both disallowed 2433 "var [yield] = [42];", 2434 "var {foo: yield} = {a: 42};", 2435 "[yield] = [42];", 2436 "({a: yield} = {a: 42});", 2437 // Also disallow full yield expressions on LHS 2438 "var [yield 24] = [42];", 2439 "var {foo: yield 24} = {a: 42};", 2440 "[yield 24] = [42];", 2441 "({a: yield 24} = {a: 42});", 2442 "for (yield 'x' in {});", 2443 "for (yield 'x' of {});", 2444 "for (yield 'x' in {} in {});", 2445 "for (yield 'x' in {} of {});", 2446 "class C extends yield { }", 2447 NULL 2448 }; 2449 // clang-format on 2450 2451 RunParserSyncTest(context_data, statement_data, kError); 2452 } 2453 2454 2455 TEST(ErrorsNameOfStrictFunction) { 2456 // Tests that illegal tokens as names of a strict function produce the correct 2457 // errors. 2458 const char* context_data[][2] = { 2459 { "function ", ""}, 2460 { "\"use strict\"; function", ""}, 2461 { "function * ", ""}, 2462 { "\"use strict\"; function * ", ""}, 2463 { NULL, NULL } 2464 }; 2465 2466 const char* statement_data[] = { 2467 "eval() {\"use strict\";}", 2468 "arguments() {\"use strict\";}", 2469 "interface() {\"use strict\";}", 2470 "yield() {\"use strict\";}", 2471 // Future reserved words are always illegal 2472 "super() { }", 2473 "super() {\"use strict\";}", 2474 NULL 2475 }; 2476 2477 RunParserSyncTest(context_data, statement_data, kError); 2478 } 2479 2480 2481 TEST(NoErrorsNameOfStrictFunction) { 2482 const char* context_data[][2] = { 2483 { "function ", ""}, 2484 { NULL, NULL } 2485 }; 2486 2487 const char* statement_data[] = { 2488 "eval() { }", 2489 "arguments() { }", 2490 "interface() { }", 2491 "yield() { }", 2492 NULL 2493 }; 2494 2495 RunParserSyncTest(context_data, statement_data, kSuccess); 2496 } 2497 2498 2499 TEST(NoErrorsNameOfStrictGenerator) { 2500 const char* context_data[][2] = { 2501 { "function * ", ""}, 2502 { NULL, NULL } 2503 }; 2504 2505 const char* statement_data[] = { 2506 "eval() { }", 2507 "arguments() { }", 2508 "interface() { }", 2509 "yield() { }", 2510 NULL 2511 }; 2512 2513 RunParserSyncTest(context_data, statement_data, kSuccess); 2514 } 2515 2516 2517 TEST(ErrorsIllegalWordsAsLabelsSloppy) { 2518 // Using future reserved words as labels is always an error. 2519 const char* context_data[][2] = { 2520 { "", ""}, 2521 { "function test_func() {", "}" }, 2522 { "() => {", "}" }, 2523 { NULL, NULL } 2524 }; 2525 2526 const char* statement_data[] = { 2527 "super: while(true) { break super; }", 2528 NULL 2529 }; 2530 2531 RunParserSyncTest(context_data, statement_data, kError); 2532 } 2533 2534 2535 TEST(ErrorsIllegalWordsAsLabelsStrict) { 2536 // Tests that illegal tokens as labels produce the correct errors. 2537 const char* context_data[][2] = { 2538 {"\"use strict\";", ""}, 2539 {"function test_func() {\"use strict\"; ", "}"}, 2540 {"() => {\"use strict\"; ", "}"}, 2541 {NULL, NULL}}; 2542 2543 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }", 2544 const char* statement_data[] = { 2545 "super: while(true) { break super; }", 2546 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) 2547 NULL 2548 }; 2549 #undef LABELLED_WHILE 2550 2551 RunParserSyncTest(context_data, statement_data, kError); 2552 } 2553 2554 2555 TEST(NoErrorsIllegalWordsAsLabels) { 2556 // Using eval and arguments as labels is legal even in strict mode. 2557 const char* context_data[][2] = { 2558 { "", ""}, 2559 { "function test_func() {", "}" }, 2560 { "() => {", "}" }, 2561 { "\"use strict\";", "" }, 2562 { "\"use strict\"; function test_func() {", "}" }, 2563 { "\"use strict\"; () => {", "}" }, 2564 { NULL, NULL } 2565 }; 2566 2567 const char* statement_data[] = { 2568 "mylabel: while(true) { break mylabel; }", 2569 "eval: while(true) { break eval; }", 2570 "arguments: while(true) { break arguments; }", 2571 NULL 2572 }; 2573 2574 RunParserSyncTest(context_data, statement_data, kSuccess); 2575 } 2576 2577 2578 TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) { 2579 const char* context_data[][2] = { 2580 { "", ""}, 2581 { "function test_func() {", "}" }, 2582 { "() => {", "}" }, 2583 { NULL, NULL } 2584 }; 2585 2586 #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }", 2587 const char* statement_data[] { 2588 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) 2589 NULL 2590 }; 2591 #undef LABELLED_WHILE 2592 2593 RunParserSyncTest(context_data, statement_data, kSuccess); 2594 } 2595 2596 2597 TEST(ErrorsParenthesizedLabels) { 2598 // Parenthesized identifiers shouldn't be recognized as labels. 2599 const char* context_data[][2] = { 2600 { "", ""}, 2601 { "function test_func() {", "}" }, 2602 { "() => {", "}" }, 2603 { NULL, NULL } 2604 }; 2605 2606 const char* statement_data[] = { 2607 "(mylabel): while(true) { break mylabel; }", 2608 NULL 2609 }; 2610 2611 RunParserSyncTest(context_data, statement_data, kError); 2612 } 2613 2614 2615 TEST(NoErrorsParenthesizedDirectivePrologue) { 2616 // Parenthesized directive prologue shouldn't be recognized. 2617 const char* context_data[][2] = { 2618 { "", ""}, 2619 { NULL, NULL } 2620 }; 2621 2622 const char* statement_data[] = { 2623 "(\"use strict\"); var eval;", 2624 NULL 2625 }; 2626 2627 RunParserSyncTest(context_data, statement_data, kSuccess); 2628 } 2629 2630 2631 TEST(ErrorsNotAnIdentifierName) { 2632 const char* context_data[][2] = { 2633 { "", ""}, 2634 { "\"use strict\";", ""}, 2635 { NULL, NULL } 2636 }; 2637 2638 const char* statement_data[] = { 2639 "var foo = {}; foo.{;", 2640 "var foo = {}; foo.};", 2641 "var foo = {}; foo.=;", 2642 "var foo = {}; foo.888;", 2643 "var foo = {}; foo.-;", 2644 "var foo = {}; foo.--;", 2645 NULL 2646 }; 2647 2648 RunParserSyncTest(context_data, statement_data, kError); 2649 } 2650 2651 2652 TEST(NoErrorsIdentifierNames) { 2653 // Keywords etc. are valid as property names. 2654 const char* context_data[][2] = { 2655 { "", ""}, 2656 { "\"use strict\";", ""}, 2657 { NULL, NULL } 2658 }; 2659 2660 const char* statement_data[] = { 2661 "var foo = {}; foo.if;", 2662 "var foo = {}; foo.yield;", 2663 "var foo = {}; foo.super;", 2664 "var foo = {}; foo.interface;", 2665 "var foo = {}; foo.eval;", 2666 "var foo = {}; foo.arguments;", 2667 NULL 2668 }; 2669 2670 RunParserSyncTest(context_data, statement_data, kSuccess); 2671 } 2672 2673 2674 TEST(DontRegressPreParserDataSizes) { 2675 // These tests make sure that Parser doesn't start producing less "preparse 2676 // data" (data which the embedder can cache). 2677 v8::V8::Initialize(); 2678 v8::Isolate* isolate = CcTest::isolate(); 2679 v8::HandleScope handles(isolate); 2680 2681 CcTest::i_isolate()->stack_guard()->SetStackLimit( 2682 i::GetCurrentStackPosition() - 128 * 1024); 2683 2684 struct TestCase { 2685 const char* program; 2686 int functions; 2687 } test_cases[] = { 2688 // No functions. 2689 {"var x = 42;", 0}, 2690 // Functions. 2691 {"function foo() {}", 1}, 2692 {"function foo() {} function bar() {}", 2}, 2693 // Getter / setter functions are recorded as functions if they're on the top 2694 // level. 2695 {"var x = {get foo(){} };", 1}, 2696 // Functions insize lazy functions are not recorded. 2697 {"function lazy() { function a() {} function b() {} function c() {} }", 1}, 2698 {"function lazy() { var x = {get foo(){} } }", 1}, 2699 {NULL, 0} 2700 }; 2701 2702 for (int i = 0; test_cases[i].program; i++) { 2703 const char* program = test_cases[i].program; 2704 i::Factory* factory = CcTest::i_isolate()->factory(); 2705 i::Handle<i::String> source = 2706 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked(); 2707 i::Handle<i::Script> script = factory->NewScript(source); 2708 i::Zone zone(CcTest::i_isolate()->allocator()); 2709 i::ParseInfo info(&zone, script); 2710 i::ScriptData* sd = NULL; 2711 info.set_cached_data(&sd); 2712 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache); 2713 info.set_allow_lazy_parsing(); 2714 i::Parser::ParseStatic(&info); 2715 i::ParseData* pd = i::ParseData::FromCachedData(sd); 2716 2717 if (pd->FunctionCount() != test_cases[i].functions) { 2718 v8::base::OS::Print( 2719 "Expected preparse data for program:\n" 2720 "\t%s\n" 2721 "to contain %d functions, however, received %d functions.\n", 2722 program, test_cases[i].functions, pd->FunctionCount()); 2723 CHECK(false); 2724 } 2725 delete sd; 2726 delete pd; 2727 } 2728 } 2729 2730 2731 TEST(FunctionDeclaresItselfStrict) { 2732 // Tests that we produce the right kinds of errors when a function declares 2733 // itself strict (we cannot produce there errors as soon as we see the 2734 // offending identifiers, because we don't know at that point whether the 2735 // function is strict or not). 2736 const char* context_data[][2] = { 2737 {"function eval() {", "}"}, 2738 {"function arguments() {", "}"}, 2739 {"function yield() {", "}"}, 2740 {"function interface() {", "}"}, 2741 {"function foo(eval) {", "}"}, 2742 {"function foo(arguments) {", "}"}, 2743 {"function foo(yield) {", "}"}, 2744 {"function foo(interface) {", "}"}, 2745 {"function foo(bar, eval) {", "}"}, 2746 {"function foo(bar, arguments) {", "}"}, 2747 {"function foo(bar, yield) {", "}"}, 2748 {"function foo(bar, interface) {", "}"}, 2749 {"function foo(bar, bar) {", "}"}, 2750 { NULL, NULL } 2751 }; 2752 2753 const char* strict_statement_data[] = { 2754 "\"use strict\";", 2755 NULL 2756 }; 2757 2758 const char* non_strict_statement_data[] = { 2759 ";", 2760 NULL 2761 }; 2762 2763 RunParserSyncTest(context_data, strict_statement_data, kError); 2764 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess); 2765 } 2766 2767 2768 TEST(ErrorsTryWithoutCatchOrFinally) { 2769 const char* context_data[][2] = { 2770 {"", ""}, 2771 { NULL, NULL } 2772 }; 2773 2774 const char* statement_data[] = { 2775 "try { }", 2776 "try { } foo();", 2777 "try { } catch (e) foo();", 2778 "try { } catch { }", 2779 "try { } finally foo();", 2780 NULL 2781 }; 2782 2783 RunParserSyncTest(context_data, statement_data, kError); 2784 } 2785 2786 2787 TEST(NoErrorsTryCatchFinally) { 2788 const char* context_data[][2] = { 2789 {"", ""}, 2790 { NULL, NULL } 2791 }; 2792 2793 const char* statement_data[] = { 2794 "try { } catch (e) { }", 2795 "try { } catch (e) { } finally { }", 2796 "try { } finally { }", 2797 NULL 2798 }; 2799 2800 RunParserSyncTest(context_data, statement_data, kSuccess); 2801 } 2802 2803 2804 TEST(ErrorsRegexpLiteral) { 2805 const char* context_data[][2] = { 2806 {"var r = ", ""}, 2807 { NULL, NULL } 2808 }; 2809 2810 const char* statement_data[] = { 2811 "/unterminated", 2812 NULL 2813 }; 2814 2815 RunParserSyncTest(context_data, statement_data, kError); 2816 } 2817 2818 2819 TEST(NoErrorsRegexpLiteral) { 2820 const char* context_data[][2] = { 2821 {"var r = ", ""}, 2822 { NULL, NULL } 2823 }; 2824 2825 const char* statement_data[] = { 2826 "/foo/", 2827 "/foo/g", 2828 NULL 2829 }; 2830 2831 RunParserSyncTest(context_data, statement_data, kSuccess); 2832 } 2833 2834 2835 TEST(NoErrorsNewExpression) { 2836 const char* context_data[][2] = { 2837 {"", ""}, 2838 {"var f =", ""}, 2839 { NULL, NULL } 2840 }; 2841 2842 const char* statement_data[] = { 2843 "new foo", 2844 "new foo();", 2845 "new foo(1);", 2846 "new foo(1, 2);", 2847 // The first () will be processed as a part of the NewExpression and the 2848 // second () will be processed as part of LeftHandSideExpression. 2849 "new foo()();", 2850 // The first () will be processed as a part of the inner NewExpression and 2851 // the second () will be processed as a part of the outer NewExpression. 2852 "new new foo()();", 2853 "new foo.bar;", 2854 "new foo.bar();", 2855 "new foo.bar.baz;", 2856 "new foo.bar().baz;", 2857 "new foo[bar];", 2858 "new foo[bar]();", 2859 "new foo[bar][baz];", 2860 "new foo[bar]()[baz];", 2861 "new foo[bar].baz(baz)()[bar].baz;", 2862 "new \"foo\"", // Runtime error 2863 "new 1", // Runtime error 2864 // This even runs: 2865 "(new new Function(\"this.x = 1\")).x;", 2866 "new new Test_Two(String, 2).v(0123).length;", 2867 NULL 2868 }; 2869 2870 RunParserSyncTest(context_data, statement_data, kSuccess); 2871 } 2872 2873 2874 TEST(ErrorsNewExpression) { 2875 const char* context_data[][2] = { 2876 {"", ""}, 2877 {"var f =", ""}, 2878 { NULL, NULL } 2879 }; 2880 2881 const char* statement_data[] = { 2882 "new foo bar", 2883 "new ) foo", 2884 "new ++foo", 2885 "new foo ++", 2886 NULL 2887 }; 2888 2889 RunParserSyncTest(context_data, statement_data, kError); 2890 } 2891 2892 2893 TEST(StrictObjectLiteralChecking) { 2894 const char* context_data[][2] = { 2895 {"\"use strict\"; var myobject = {", "};"}, 2896 {"\"use strict\"; var myobject = {", ",};"}, 2897 {"var myobject = {", "};"}, 2898 {"var myobject = {", ",};"}, 2899 { NULL, NULL } 2900 }; 2901 2902 // These are only errors in strict mode. 2903 const char* statement_data[] = { 2904 "foo: 1, foo: 2", 2905 "\"foo\": 1, \"foo\": 2", 2906 "foo: 1, \"foo\": 2", 2907 "1: 1, 1: 2", 2908 "1: 1, \"1\": 2", 2909 "get: 1, get: 2", // Not a getter for real, just a property called get. 2910 "set: 1, set: 2", // Not a setter for real, just a property called set. 2911 NULL 2912 }; 2913 2914 RunParserSyncTest(context_data, statement_data, kSuccess); 2915 } 2916 2917 2918 TEST(ErrorsObjectLiteralChecking) { 2919 const char* context_data[][2] = { 2920 {"\"use strict\"; var myobject = {", "};"}, 2921 {"var myobject = {", "};"}, 2922 { NULL, NULL } 2923 }; 2924 2925 const char* statement_data[] = { 2926 ",", 2927 // Wrong number of parameters 2928 "get bar(x) {}", 2929 "get bar(x, y) {}", 2930 "set bar() {}", 2931 "set bar(x, y) {}", 2932 // Parsing FunctionLiteral for getter or setter fails 2933 "get foo( +", 2934 "get foo() \"error\"", 2935 NULL 2936 }; 2937 2938 RunParserSyncTest(context_data, statement_data, kError); 2939 } 2940 2941 2942 TEST(NoErrorsObjectLiteralChecking) { 2943 const char* context_data[][2] = { 2944 {"var myobject = {", "};"}, 2945 {"var myobject = {", ",};"}, 2946 {"\"use strict\"; var myobject = {", "};"}, 2947 {"\"use strict\"; var myobject = {", ",};"}, 2948 { NULL, NULL } 2949 }; 2950 2951 const char* statement_data[] = { 2952 "foo: 1, get foo() {}", 2953 "foo: 1, set foo(v) {}", 2954 "\"foo\": 1, get \"foo\"() {}", 2955 "\"foo\": 1, set \"foo\"(v) {}", 2956 "1: 1, get 1() {}", 2957 "1: 1, set 1(v) {}", 2958 "get foo() {}, get foo() {}", 2959 "set foo(_) {}, set foo(v) {}", 2960 "foo: 1, get \"foo\"() {}", 2961 "foo: 1, set \"foo\"(v) {}", 2962 "\"foo\": 1, get foo() {}", 2963 "\"foo\": 1, set foo(v) {}", 2964 "1: 1, get \"1\"() {}", 2965 "1: 1, set \"1\"(v) {}", 2966 "\"1\": 1, get 1() {}", 2967 "\"1\": 1, set 1(v) {}", 2968 "foo: 1, bar: 2", 2969 "\"foo\": 1, \"bar\": 2", 2970 "1: 1, 2: 2", 2971 // Syntax: IdentifierName ':' AssignmentExpression 2972 "foo: bar = 5 + baz", 2973 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}' 2974 "get foo() {}", 2975 "get \"foo\"() {}", 2976 "get 1() {}", 2977 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')' 2978 // '{' FunctionBody '}' 2979 "set foo(v) {}", 2980 "set \"foo\"(v) {}", 2981 "set 1(v) {}", 2982 // Non-colliding getters and setters -> no errors 2983 "foo: 1, get bar() {}", 2984 "foo: 1, set bar(v) {}", 2985 "\"foo\": 1, get \"bar\"() {}", 2986 "\"foo\": 1, set \"bar\"(v) {}", 2987 "1: 1, get 2() {}", 2988 "1: 1, set 2(v) {}", 2989 "get: 1, get foo() {}", 2990 "set: 1, set foo(_) {}", 2991 // Keywords, future reserved and strict future reserved are also allowed as 2992 // property names. 2993 "if: 4", 2994 "interface: 5", 2995 "super: 6", 2996 "eval: 7", 2997 "arguments: 8", 2998 NULL 2999 }; 3000 3001 RunParserSyncTest(context_data, statement_data, kSuccess); 3002 } 3003 3004 3005 TEST(TooManyArguments) { 3006 const char* context_data[][2] = { 3007 {"foo(", "0)"}, 3008 { NULL, NULL } 3009 }; 3010 3011 using v8::internal::Code; 3012 char statement[Code::kMaxArguments * 2 + 1]; 3013 for (int i = 0; i < Code::kMaxArguments; ++i) { 3014 statement[2 * i] = '0'; 3015 statement[2 * i + 1] = ','; 3016 } 3017 statement[Code::kMaxArguments * 2] = 0; 3018 3019 const char* statement_data[] = { 3020 statement, 3021 NULL 3022 }; 3023 3024 // The test is quite slow, so run it with a reduced set of flags. 3025 static const ParserFlag empty_flags[] = {kAllowLazy}; 3026 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1); 3027 } 3028 3029 3030 TEST(StrictDelete) { 3031 // "delete <Identifier>" is not allowed in strict mode. 3032 const char* strict_context_data[][2] = { 3033 {"\"use strict\"; ", ""}, 3034 { NULL, NULL } 3035 }; 3036 3037 const char* sloppy_context_data[][2] = { 3038 {"", ""}, 3039 { NULL, NULL } 3040 }; 3041 3042 // These are errors in the strict mode. 3043 const char* sloppy_statement_data[] = { 3044 "delete foo;", 3045 "delete foo + 1;", 3046 "delete (foo);", 3047 "delete eval;", 3048 "delete interface;", 3049 NULL 3050 }; 3051 3052 // These are always OK 3053 const char* good_statement_data[] = { 3054 "delete this;", 3055 "delete 1;", 3056 "delete 1 + 2;", 3057 "delete foo();", 3058 "delete foo.bar;", 3059 "delete foo[bar];", 3060 "delete foo--;", 3061 "delete --foo;", 3062 "delete new foo();", 3063 "delete new foo(bar);", 3064 NULL 3065 }; 3066 3067 // These are always errors 3068 const char* bad_statement_data[] = { 3069 "delete if;", 3070 NULL 3071 }; 3072 3073 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError); 3074 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess); 3075 3076 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess); 3077 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess); 3078 3079 RunParserSyncTest(strict_context_data, bad_statement_data, kError); 3080 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError); 3081 } 3082 3083 3084 TEST(NoErrorsDeclsInCase) { 3085 const char* context_data[][2] = { 3086 {"'use strict'; switch(x) { case 1:", "}"}, 3087 {"function foo() {'use strict'; switch(x) { case 1:", "}}"}, 3088 {"'use strict'; switch(x) { case 1: case 2:", "}"}, 3089 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"}, 3090 {"'use strict'; switch(x) { default:", "}"}, 3091 {"function foo() {'use strict'; switch(x) { default:", "}}"}, 3092 {"'use strict'; switch(x) { case 1: default:", "}"}, 3093 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"}, 3094 { nullptr, nullptr } 3095 }; 3096 3097 const char* statement_data[] = { 3098 "function f() { }", 3099 "class C { }", 3100 "class C extends Q {}", 3101 "function f() { } class C {}", 3102 "function f() { }; class C {}", 3103 "class C {}; function f() {}", 3104 nullptr 3105 }; 3106 3107 RunParserSyncTest(context_data, statement_data, kSuccess); 3108 } 3109 3110 3111 TEST(InvalidLeftHandSide) { 3112 const char* assignment_context_data[][2] = { 3113 {"", " = 1;"}, 3114 {"\"use strict\"; ", " = 1;"}, 3115 { NULL, NULL } 3116 }; 3117 3118 const char* prefix_context_data[][2] = { 3119 {"++", ";"}, 3120 {"\"use strict\"; ++", ";"}, 3121 {NULL, NULL}, 3122 }; 3123 3124 const char* postfix_context_data[][2] = { 3125 {"", "++;"}, 3126 {"\"use strict\"; ", "++;"}, 3127 { NULL, NULL } 3128 }; 3129 3130 // Good left hand sides for assigment or prefix / postfix operations. 3131 const char* good_statement_data[] = { 3132 "foo", 3133 "foo.bar", 3134 "foo[bar]", 3135 "foo()[bar]", 3136 "foo().bar", 3137 "this.foo", 3138 "this[foo]", 3139 "new foo()[bar]", 3140 "new foo().bar", 3141 "foo()", 3142 "foo(bar)", 3143 "foo[bar]()", 3144 "foo.bar()", 3145 "this()", 3146 "this.foo()", 3147 "this[foo].bar()", 3148 "this.foo[foo].bar(this)(bar)[foo]()", 3149 NULL 3150 }; 3151 3152 // Bad left hand sides for assigment or prefix / postfix operations. 3153 const char* bad_statement_data_common[] = { 3154 "2", 3155 "new foo", 3156 "new foo()", 3157 "null", 3158 "if", // Unexpected token 3159 "{x: 1}", // Unexpected token 3160 "this", 3161 "\"bar\"", 3162 "(foo + bar)", 3163 "new new foo()[bar]", // means: new (new foo()[bar]) 3164 "new new foo().bar", // means: new (new foo()[bar]) 3165 NULL 3166 }; 3167 3168 // These are not okay for assignment, but okay for prefix / postix. 3169 const char* bad_statement_data_for_assignment[] = { 3170 "++foo", 3171 "foo++", 3172 "foo + bar", 3173 NULL 3174 }; 3175 3176 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess); 3177 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError); 3178 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment, 3179 kError); 3180 3181 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess); 3182 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError); 3183 3184 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); 3185 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); 3186 } 3187 3188 3189 TEST(FuncNameInferrerBasic) { 3190 // Tests that function names are inferred properly. 3191 i::FLAG_allow_natives_syntax = true; 3192 v8::Isolate* isolate = CcTest::isolate(); 3193 v8::HandleScope scope(isolate); 3194 LocalContext env; 3195 CompileRun("var foo1 = function() {}; " 3196 "var foo2 = function foo3() {}; " 3197 "function not_ctor() { " 3198 " var foo4 = function() {}; " 3199 " return %FunctionGetInferredName(foo4); " 3200 "} " 3201 "function Ctor() { " 3202 " var foo5 = function() {}; " 3203 " return %FunctionGetInferredName(foo5); " 3204 "} " 3205 "var obj1 = { foo6: function() {} }; " 3206 "var obj2 = { 'foo7': function() {} }; " 3207 "var obj3 = {}; " 3208 "obj3[1] = function() {}; " 3209 "var obj4 = {}; " 3210 "obj4[1] = function foo8() {}; " 3211 "var obj5 = {}; " 3212 "obj5['foo9'] = function() {}; " 3213 "var obj6 = { obj7 : { foo10: function() {} } };"); 3214 ExpectString("%FunctionGetInferredName(foo1)", "foo1"); 3215 // foo2 is not unnamed -> its name is not inferred. 3216 ExpectString("%FunctionGetInferredName(foo2)", ""); 3217 ExpectString("not_ctor()", "foo4"); 3218 ExpectString("Ctor()", "Ctor.foo5"); 3219 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6"); 3220 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7"); 3221 ExpectString("%FunctionGetInferredName(obj3[1])", 3222 "obj3.(anonymous function)"); 3223 ExpectString("%FunctionGetInferredName(obj4[1])", ""); 3224 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9"); 3225 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10"); 3226 } 3227 3228 3229 TEST(FuncNameInferrerTwoByte) { 3230 // Tests function name inferring in cases where some parts of the inferred 3231 // function name are two-byte strings. 3232 i::FLAG_allow_natives_syntax = true; 3233 v8::Isolate* isolate = CcTest::isolate(); 3234 v8::HandleScope scope(isolate); 3235 LocalContext env; 3236 uint16_t* two_byte_source = AsciiToTwoByteString( 3237 "var obj1 = { oXj2 : { foo1: function() {} } }; " 3238 "%FunctionGetInferredName(obj1.oXj2.foo1)"); 3239 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1"); 3240 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character). 3241 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d; 3242 v8::Local<v8::String> source = 3243 v8::String::NewFromTwoByte(isolate, two_byte_source, 3244 v8::NewStringType::kNormal) 3245 .ToLocalChecked(); 3246 v8::Local<v8::Value> result = CompileRun(source); 3247 CHECK(result->IsString()); 3248 v8::Local<v8::String> expected_name = 3249 v8::String::NewFromTwoByte(isolate, two_byte_name, 3250 v8::NewStringType::kNormal) 3251 .ToLocalChecked(); 3252 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust()); 3253 i::DeleteArray(two_byte_source); 3254 i::DeleteArray(two_byte_name); 3255 } 3256 3257 3258 TEST(FuncNameInferrerEscaped) { 3259 // The same as FuncNameInferrerTwoByte, except that we express the two-byte 3260 // character as a unicode escape. 3261 i::FLAG_allow_natives_syntax = true; 3262 v8::Isolate* isolate = CcTest::isolate(); 3263 v8::HandleScope scope(isolate); 3264 LocalContext env; 3265 uint16_t* two_byte_source = AsciiToTwoByteString( 3266 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; " 3267 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)"); 3268 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1"); 3269 // Fix to correspond to the non-ASCII name in two_byte_source. 3270 two_byte_name[6] = 0x010d; 3271 v8::Local<v8::String> source = 3272 v8::String::NewFromTwoByte(isolate, two_byte_source, 3273 v8::NewStringType::kNormal) 3274 .ToLocalChecked(); 3275 v8::Local<v8::Value> result = CompileRun(source); 3276 CHECK(result->IsString()); 3277 v8::Local<v8::String> expected_name = 3278 v8::String::NewFromTwoByte(isolate, two_byte_name, 3279 v8::NewStringType::kNormal) 3280 .ToLocalChecked(); 3281 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust()); 3282 i::DeleteArray(two_byte_source); 3283 i::DeleteArray(two_byte_name); 3284 } 3285 3286 3287 TEST(RegressionLazyFunctionWithErrorWithArg) { 3288 // Test only applies when lazy parsing. 3289 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return; 3290 3291 // The bug occurred when a lazy function had an error which requires a 3292 // parameter (such as "unknown label" here). The error message was processed 3293 // before the AstValueFactory containing the error message string was 3294 // internalized. 3295 v8::Isolate* isolate = CcTest::isolate(); 3296 v8::HandleScope scope(isolate); 3297 LocalContext env; 3298 i::FLAG_lazy = true; 3299 i::FLAG_min_preparse_length = 0; 3300 CompileRun("function this_is_lazy() {\n" 3301 " break p;\n" 3302 "}\n" 3303 "this_is_lazy();\n"); 3304 } 3305 3306 3307 TEST(SerializationOfMaybeAssignmentFlag) { 3308 i::Isolate* isolate = CcTest::i_isolate(); 3309 i::Factory* factory = isolate->factory(); 3310 i::HandleScope scope(isolate); 3311 LocalContext env; 3312 3313 const char* src = 3314 "function h() {" 3315 " var result = [];" 3316 " function f() {" 3317 " result.push(2);" 3318 " }" 3319 " function assertResult(r) {" 3320 " f();" 3321 " result = [];" 3322 " }" 3323 " assertResult([2]);" 3324 " assertResult([2]);" 3325 " return f;" 3326 "};" 3327 "h();"; 3328 3329 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1); 3330 i::SNPrintF(program, "%s", src); 3331 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); 3332 source->PrintOn(stdout); 3333 printf("\n"); 3334 i::Zone zone(CcTest::i_isolate()->allocator()); 3335 v8::Local<v8::Value> v = CompileRun(src); 3336 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); 3337 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); 3338 i::Context* context = f->context(); 3339 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); 3340 avf.Internalize(isolate); 3341 const i::AstRawString* name = avf.GetOneByteString("result"); 3342 i::Handle<i::String> str = name->string(); 3343 CHECK(str->IsInternalizedString()); 3344 i::Scope* script_scope = 3345 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf); 3346 script_scope->Initialize(); 3347 i::Scope* s = 3348 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope); 3349 CHECK(s != script_scope); 3350 CHECK(name != NULL); 3351 3352 // Get result from h's function context (that is f's context) 3353 i::Variable* var = s->Lookup(name); 3354 3355 CHECK(var != NULL); 3356 // Maybe assigned should survive deserialization 3357 CHECK(var->maybe_assigned() == i::kMaybeAssigned); 3358 // TODO(sigurds) Figure out if is_used should survive context serialization. 3359 } 3360 3361 3362 TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) { 3363 i::Isolate* isolate = CcTest::i_isolate(); 3364 i::Factory* factory = isolate->factory(); 3365 i::HandleScope scope(isolate); 3366 LocalContext env; 3367 3368 3369 const char* src = 3370 "function f(x) {" 3371 " var a = arguments;" 3372 " function g(i) {" 3373 " ++a[0];" 3374 " };" 3375 " return g;" 3376 " }" 3377 "f(0);"; 3378 3379 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1); 3380 i::SNPrintF(program, "%s", src); 3381 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); 3382 source->PrintOn(stdout); 3383 printf("\n"); 3384 i::Zone zone(CcTest::i_isolate()->allocator()); 3385 v8::Local<v8::Value> v = CompileRun(src); 3386 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); 3387 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); 3388 i::Context* context = f->context(); 3389 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); 3390 avf.Internalize(isolate); 3391 3392 i::Scope* script_scope = 3393 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf); 3394 script_scope->Initialize(); 3395 i::Scope* s = 3396 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope); 3397 CHECK(s != script_scope); 3398 const i::AstRawString* name_x = avf.GetOneByteString("x"); 3399 3400 // Get result from f's function context (that is g's outer context) 3401 i::Variable* var_x = s->Lookup(name_x); 3402 CHECK(var_x != NULL); 3403 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned); 3404 } 3405 3406 3407 TEST(InnerAssignment) { 3408 i::Isolate* isolate = CcTest::i_isolate(); 3409 i::Factory* factory = isolate->factory(); 3410 i::HandleScope scope(isolate); 3411 LocalContext env; 3412 3413 const char* prefix = "function f() {"; 3414 const char* midfix = " function g() {"; 3415 const char* suffix = "}}"; 3416 struct { const char* source; bool assigned; bool strict; } outers[] = { 3417 // Actual assignments. 3418 { "var x; var x = 5;", true, false }, 3419 { "var x; { var x = 5; }", true, false }, 3420 { "'use strict'; let x; x = 6;", true, true }, 3421 { "var x = 5; function x() {}", true, false }, 3422 // Actual non-assignments. 3423 { "var x;", false, false }, 3424 { "var x = 5;", false, false }, 3425 { "'use strict'; let x;", false, true }, 3426 { "'use strict'; let x = 6;", false, true }, 3427 { "'use strict'; var x = 0; { let x = 6; }", false, true }, 3428 { "'use strict'; var x = 0; { let x; x = 6; }", false, true }, 3429 { "'use strict'; let x = 0; { let x = 6; }", false, true }, 3430 { "'use strict'; let x = 0; { let x; x = 6; }", false, true }, 3431 { "var x; try {} catch (x) { x = 5; }", false, false }, 3432 { "function x() {}", false, false }, 3433 // Eval approximation. 3434 { "var x; eval('');", true, false }, 3435 { "eval(''); var x;", true, false }, 3436 { "'use strict'; let x; eval('');", true, true }, 3437 { "'use strict'; eval(''); let x;", true, true }, 3438 // Non-assignments not recognized, because the analysis is approximative. 3439 { "var x; var x;", true, false }, 3440 { "var x = 5; var x;", true, false }, 3441 { "var x; { var x; }", true, false }, 3442 { "var x; function x() {}", true, false }, 3443 { "function x() {}; var x;", true, false }, 3444 { "var x; try {} catch (x) { var x = 5; }", true, false }, 3445 }; 3446 struct { const char* source; bool assigned; bool with; } inners[] = { 3447 // Actual assignments. 3448 { "x = 1;", true, false }, 3449 { "x++;", true, false }, 3450 { "++x;", true, false }, 3451 { "x--;", true, false }, 3452 { "--x;", true, false }, 3453 { "{ x = 1; }", true, false }, 3454 { "'use strict'; { let x; }; x = 0;", true, false }, 3455 { "'use strict'; { const x = 1; }; x = 0;", true, false }, 3456 { "'use strict'; { function x() {} }; x = 0;", true, false }, 3457 { "with ({}) { x = 1; }", true, true }, 3458 { "eval('');", true, false }, 3459 { "'use strict'; { let y; eval('') }", true, false }, 3460 { "function h() { x = 0; }", true, false }, 3461 { "(function() { x = 0; })", true, false }, 3462 { "(function() { x = 0; })", true, false }, 3463 { "with ({}) (function() { x = 0; })", true, true }, 3464 // Actual non-assignments. 3465 { "", false, false }, 3466 { "x;", false, false }, 3467 { "var x;", false, false }, 3468 { "var x = 8;", false, false }, 3469 { "var x; x = 8;", false, false }, 3470 { "'use strict'; let x;", false, false }, 3471 { "'use strict'; let x = 8;", false, false }, 3472 { "'use strict'; let x; x = 8;", false, false }, 3473 { "'use strict'; const x = 8;", false, false }, 3474 { "function x() {}", false, false }, 3475 { "function x() { x = 0; }", false, false }, 3476 { "function h(x) { x = 0; }", false, false }, 3477 { "'use strict'; { let x; x = 0; }", false, false }, 3478 { "{ var x; }; x = 0;", false, false }, 3479 { "with ({}) {}", false, true }, 3480 { "var x; { with ({}) { x = 1; } }", false, true }, 3481 { "try {} catch(x) { x = 0; }", false, false }, 3482 { "try {} catch(x) { with ({}) { x = 1; } }", false, true }, 3483 // Eval approximation. 3484 { "eval('');", true, false }, 3485 { "function h() { eval(''); }", true, false }, 3486 { "(function() { eval(''); })", true, false }, 3487 // Shadowing not recognized because of eval approximation. 3488 { "var x; eval('');", true, false }, 3489 { "'use strict'; let x; eval('');", true, false }, 3490 { "try {} catch(x) { eval(''); }", true, false }, 3491 { "function x() { eval(''); }", true, false }, 3492 { "(function(x) { eval(''); })", true, false }, 3493 }; 3494 3495 // Used to trigger lazy compilation of function 3496 int comment_len = 2048; 3497 i::ScopedVector<char> comment(comment_len + 1); 3498 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0); 3499 int prefix_len = Utf8LengthHelper(prefix); 3500 int midfix_len = Utf8LengthHelper(midfix); 3501 int suffix_len = Utf8LengthHelper(suffix); 3502 for (unsigned i = 0; i < arraysize(outers); ++i) { 3503 const char* outer = outers[i].source; 3504 int outer_len = Utf8LengthHelper(outer); 3505 for (unsigned j = 0; j < arraysize(inners); ++j) { 3506 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) { 3507 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) { 3508 if (outers[i].strict && inners[j].with) continue; 3509 const char* inner = inners[j].source; 3510 int inner_len = Utf8LengthHelper(inner); 3511 3512 int outer_comment_len = outer_lazy ? comment_len : 0; 3513 int inner_comment_len = inner_lazy ? comment_len : 0; 3514 const char* outer_comment = outer_lazy ? comment.start() : ""; 3515 const char* inner_comment = inner_lazy ? comment.start() : ""; 3516 int len = prefix_len + outer_comment_len + outer_len + midfix_len + 3517 inner_comment_len + inner_len + suffix_len; 3518 i::ScopedVector<char> program(len + 1); 3519 3520 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer, 3521 midfix, inner_comment, inner, suffix); 3522 i::Handle<i::String> source = 3523 factory->InternalizeUtf8String(program.start()); 3524 source->PrintOn(stdout); 3525 printf("\n"); 3526 3527 i::Handle<i::Script> script = factory->NewScript(source); 3528 i::Zone zone(CcTest::i_isolate()->allocator()); 3529 i::ParseInfo info(&zone, script); 3530 i::Parser parser(&info); 3531 CHECK(parser.Parse(&info)); 3532 CHECK(i::Compiler::Analyze(&info)); 3533 CHECK(info.literal() != NULL); 3534 3535 i::Scope* scope = info.literal()->scope(); 3536 CHECK_EQ(scope->inner_scopes()->length(), 1); 3537 i::Scope* inner_scope = scope->inner_scopes()->at(0); 3538 const i::AstRawString* var_name = 3539 info.ast_value_factory()->GetOneByteString("x"); 3540 i::Variable* var = inner_scope->Lookup(var_name); 3541 bool expected = outers[i].assigned || inners[j].assigned; 3542 CHECK(var != NULL); 3543 CHECK(var->is_used() || !expected); 3544 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected); 3545 } 3546 } 3547 } 3548 } 3549 } 3550 3551 namespace { 3552 3553 int* global_use_counts = NULL; 3554 3555 void MockUseCounterCallback(v8::Isolate* isolate, 3556 v8::Isolate::UseCounterFeature feature) { 3557 ++global_use_counts[feature]; 3558 } 3559 3560 } 3561 3562 3563 TEST(UseAsmUseCount) { 3564 i::Isolate* isolate = CcTest::i_isolate(); 3565 i::HandleScope scope(isolate); 3566 LocalContext env; 3567 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; 3568 global_use_counts = use_counts; 3569 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); 3570 CompileRun("\"use asm\";\n" 3571 "var foo = 1;\n" 3572 "function bar() { \"use asm\"; var baz = 1; }"); 3573 CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]); 3574 } 3575 3576 3577 TEST(StrictModeUseCount) { 3578 i::Isolate* isolate = CcTest::i_isolate(); 3579 i::HandleScope scope(isolate); 3580 LocalContext env; 3581 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; 3582 global_use_counts = use_counts; 3583 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); 3584 CompileRun( 3585 "\"use strict\";\n" 3586 "function bar() { var baz = 1; }"); // strict mode inherits 3587 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]); 3588 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]); 3589 } 3590 3591 3592 TEST(SloppyModeUseCount) { 3593 i::Isolate* isolate = CcTest::i_isolate(); 3594 i::HandleScope scope(isolate); 3595 LocalContext env; 3596 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; 3597 global_use_counts = use_counts; 3598 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); 3599 CompileRun("function bar() { var baz = 1; }"); 3600 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]); 3601 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]); 3602 } 3603 3604 3605 TEST(BothModesUseCount) { 3606 i::Isolate* isolate = CcTest::i_isolate(); 3607 i::HandleScope scope(isolate); 3608 LocalContext env; 3609 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; 3610 global_use_counts = use_counts; 3611 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); 3612 CompileRun("function bar() { 'use strict'; var baz = 1; }"); 3613 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]); 3614 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]); 3615 } 3616 3617 3618 TEST(ErrorsArrowFormalParameters) { 3619 const char* context_data[][2] = { 3620 { "()", "=>{}" }, 3621 { "()", "=>{};" }, 3622 { "var x = ()", "=>{}" }, 3623 { "var x = ()", "=>{};" }, 3624 3625 { "a", "=>{}" }, 3626 { "a", "=>{};" }, 3627 { "var x = a", "=>{}" }, 3628 { "var x = a", "=>{};" }, 3629 3630 { "(a)", "=>{}" }, 3631 { "(a)", "=>{};" }, 3632 { "var x = (a)", "=>{}" }, 3633 { "var x = (a)", "=>{};" }, 3634 3635 { "(...a)", "=>{}" }, 3636 { "(...a)", "=>{};" }, 3637 { "var x = (...a)", "=>{}" }, 3638 { "var x = (...a)", "=>{};" }, 3639 3640 { "(a,b)", "=>{}" }, 3641 { "(a,b)", "=>{};" }, 3642 { "var x = (a,b)", "=>{}" }, 3643 { "var x = (a,b)", "=>{};" }, 3644 3645 { "(a,...b)", "=>{}" }, 3646 { "(a,...b)", "=>{};" }, 3647 { "var x = (a,...b)", "=>{}" }, 3648 { "var x = (a,...b)", "=>{};" }, 3649 3650 { nullptr, nullptr } 3651 }; 3652 const char* assignment_expression_suffix_data[] = { 3653 "?c:d=>{}", 3654 "=c=>{}", 3655 "()", 3656 "(c)", 3657 "[1]", 3658 "[c]", 3659 ".c", 3660 "-c", 3661 "+c", 3662 "c++", 3663 "`c`", 3664 "`${c}`", 3665 "`template-head${c}`", 3666 "`${c}template-tail`", 3667 "`template-head${c}template-tail`", 3668 "`${c}template-tail`", 3669 nullptr 3670 }; 3671 3672 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError); 3673 } 3674 3675 3676 TEST(ErrorsArrowFunctions) { 3677 // Tests that parser and preparser generate the same kind of errors 3678 // on invalid arrow function syntax. 3679 3680 // clang-format off 3681 const char* context_data[][2] = { 3682 {"", ";"}, 3683 {"v = ", ";"}, 3684 {"bar ? (", ") : baz;"}, 3685 {"bar ? baz : (", ");"}, 3686 {"bar[", "];"}, 3687 {"bar, ", ";"}, 3688 {"", ", bar;"}, 3689 {NULL, NULL} 3690 }; 3691 3692 const char* statement_data[] = { 3693 "=> 0", 3694 "=>", 3695 "() =>", 3696 "=> {}", 3697 ") => {}", 3698 ", => {}", 3699 "(,) => {}", 3700 "return => {}", 3701 "() => {'value': 42}", 3702 3703 // Check that the early return introduced in ParsePrimaryExpression 3704 // does not accept stray closing parentheses. 3705 ")", 3706 ") => 0", 3707 "foo[()]", 3708 "()", 3709 3710 // Parameter lists with extra parens should be recognized as errors. 3711 "(()) => 0", 3712 "((x)) => 0", 3713 "((x, y)) => 0", 3714 "(x, (y)) => 0", 3715 "((x, y, z)) => 0", 3716 "(x, (y, z)) => 0", 3717 "((x, y), z) => 0", 3718 3719 // Arrow function formal parameters are parsed as StrictFormalParameters, 3720 // which confusingly only implies that there are no duplicates. Words 3721 // reserved in strict mode, and eval or arguments, are indeed valid in 3722 // sloppy mode. 3723 "eval => { 'use strict'; 0 }", 3724 "arguments => { 'use strict'; 0 }", 3725 "yield => { 'use strict'; 0 }", 3726 "interface => { 'use strict'; 0 }", 3727 "(eval) => { 'use strict'; 0 }", 3728 "(arguments) => { 'use strict'; 0 }", 3729 "(yield) => { 'use strict'; 0 }", 3730 "(interface) => { 'use strict'; 0 }", 3731 "(eval, bar) => { 'use strict'; 0 }", 3732 "(bar, eval) => { 'use strict'; 0 }", 3733 "(bar, arguments) => { 'use strict'; 0 }", 3734 "(bar, yield) => { 'use strict'; 0 }", 3735 "(bar, interface) => { 'use strict'; 0 }", 3736 // TODO(aperez): Detecting duplicates does not work in PreParser. 3737 // "(bar, bar) => {}", 3738 3739 // The parameter list is parsed as an expression, but only 3740 // a comma-separated list of identifier is valid. 3741 "32 => {}", 3742 "(32) => {}", 3743 "(a, 32) => {}", 3744 "if => {}", 3745 "(if) => {}", 3746 "(a, if) => {}", 3747 "a + b => {}", 3748 "(a + b) => {}", 3749 "(a + b, c) => {}", 3750 "(a, b - c) => {}", 3751 "\"a\" => {}", 3752 "(\"a\") => {}", 3753 "(\"a\", b) => {}", 3754 "(a, \"b\") => {}", 3755 "-a => {}", 3756 "(-a) => {}", 3757 "(-a, b) => {}", 3758 "(a, -b) => {}", 3759 "{} => {}", 3760 "a++ => {}", 3761 "(a++) => {}", 3762 "(a++, b) => {}", 3763 "(a, b++) => {}", 3764 "[] => {}", 3765 "(foo ? bar : baz) => {}", 3766 "(a, foo ? bar : baz) => {}", 3767 "(foo ? bar : baz, a) => {}", 3768 "(a.b, c) => {}", 3769 "(c, a.b) => {}", 3770 "(a['b'], c) => {}", 3771 "(c, a['b']) => {}", 3772 3773 // crbug.com/582626 3774 "(...rest - a) => b", 3775 "(a, ...b - 10) => b", 3776 3777 NULL 3778 }; 3779 // clang-format on 3780 3781 // The test is quite slow, so run it with a reduced set of flags. 3782 static const ParserFlag flags[] = {kAllowLazy}; 3783 RunParserSyncTest(context_data, statement_data, kError, flags, 3784 arraysize(flags)); 3785 3786 // In a context where a concise arrow body is parsed with [~In] variant, 3787 // ensure that an error is reported in both full parser and preparser. 3788 const char* loop_context_data[][2] = {{"for (", "; 0;);"}, 3789 {nullptr, nullptr}}; 3790 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr}; 3791 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags, 3792 arraysize(flags)); 3793 } 3794 3795 3796 TEST(NoErrorsArrowFunctions) { 3797 // Tests that parser and preparser accept valid arrow functions syntax. 3798 // clang-format off 3799 const char* context_data[][2] = { 3800 {"", ";"}, 3801 {"bar ? (", ") : baz;"}, 3802 {"bar ? baz : (", ");"}, 3803 {"bar, ", ";"}, 3804 {"", ", bar;"}, 3805 {NULL, NULL} 3806 }; 3807 3808 const char* statement_data[] = { 3809 "() => {}", 3810 "() => { return 42 }", 3811 "x => { return x; }", 3812 "(x) => { return x; }", 3813 "(x, y) => { return x + y; }", 3814 "(x, y, z) => { return x + y + z; }", 3815 "(x, y) => { x.a = y; }", 3816 "() => 42", 3817 "x => x", 3818 "x => x * x", 3819 "(x) => x", 3820 "(x) => x * x", 3821 "(x, y) => x + y", 3822 "(x, y, z) => x, y, z", 3823 "(x, y) => x.a = y", 3824 "() => ({'value': 42})", 3825 "x => y => x + y", 3826 "(x, y) => (u, v) => x*u + y*v", 3827 "(x, y) => z => z * (x + y)", 3828 "x => (y, z) => z * (x + y)", 3829 3830 // Those are comma-separated expressions, with arrow functions as items. 3831 // They stress the code for validating arrow function parameter lists. 3832 "a, b => 0", 3833 "a, b, (c, d) => 0", 3834 "(a, b, (c, d) => 0)", 3835 "(a, b) => 0, (c, d) => 1", 3836 "(a, b => {}, a => a + 1)", 3837 "((a, b) => {}, (a => a + 1))", 3838 "(a, (a, (b, c) => 0))", 3839 3840 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {}) 3841 "foo ? bar : baz => {}", 3842 3843 // Arrows with non-simple parameters. 3844 "({}) => {}", 3845 "(a, {}) => {}", 3846 "({}, a) => {}", 3847 "([]) => {}", 3848 "(a, []) => {}", 3849 "([], a) => {}", 3850 "(a = b) => {}", 3851 "(a = b, c) => {}", 3852 "(a, b = c) => {}", 3853 "({a}) => {}", 3854 "(x = 9) => {}", 3855 "(x, y = 9) => {}", 3856 "(x = 9, y) => {}", 3857 "(x, y = 9, z) => {}", 3858 "(x, y = 9, z = 8) => {}", 3859 "(...a) => {}", 3860 "(x, ...a) => {}", 3861 "(x = 9, ...a) => {}", 3862 "(x, y = 9, ...a) => {}", 3863 "(x, y = 9, {b}, z = 8, ...a) => {}", 3864 "({a} = {}) => {}", 3865 "([x] = []) => {}", 3866 "({a = 42}) => {}", 3867 "([x = 0]) => {}", 3868 NULL 3869 }; 3870 // clang-format on 3871 3872 RunParserSyncTest(context_data, statement_data, kSuccess); 3873 3874 static const ParserFlag flags[] = {kAllowLazy}; 3875 // In a context where a concise arrow body is parsed with [~In] variant, 3876 // ensure that nested expressions can still use the 'in' operator, 3877 const char* loop_context_data[][2] = {{"for (", "; 0;);"}, 3878 {nullptr, nullptr}}; 3879 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr}; 3880 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags, 3881 arraysize(flags)); 3882 } 3883 3884 3885 TEST(ArrowFunctionsSloppyParameterNames) { 3886 const char* strict_context_data[][2] = { 3887 {"'use strict'; ", ";"}, 3888 {"'use strict'; bar ? (", ") : baz;"}, 3889 {"'use strict'; bar ? baz : (", ");"}, 3890 {"'use strict'; bar, ", ";"}, 3891 {"'use strict'; ", ", bar;"}, 3892 {NULL, NULL} 3893 }; 3894 3895 const char* sloppy_context_data[][2] = { 3896 {"", ";"}, 3897 {"bar ? (", ") : baz;"}, 3898 {"bar ? baz : (", ");"}, 3899 {"bar, ", ";"}, 3900 {"", ", bar;"}, 3901 {NULL, NULL} 3902 }; 3903 3904 const char* statement_data[] = { 3905 "eval => {}", 3906 "arguments => {}", 3907 "yield => {}", 3908 "interface => {}", 3909 "(eval) => {}", 3910 "(arguments) => {}", 3911 "(yield) => {}", 3912 "(interface) => {}", 3913 "(eval, bar) => {}", 3914 "(bar, eval) => {}", 3915 "(bar, arguments) => {}", 3916 "(bar, yield) => {}", 3917 "(bar, interface) => {}", 3918 "(interface, eval) => {}", 3919 "(interface, arguments) => {}", 3920 "(eval, interface) => {}", 3921 "(arguments, interface) => {}", 3922 NULL 3923 }; 3924 3925 RunParserSyncTest(strict_context_data, statement_data, kError); 3926 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess); 3927 } 3928 3929 3930 TEST(ArrowFunctionsYieldParameterNameInGenerator) { 3931 const char* sloppy_function_context_data[][2] = { 3932 {"(function f() { (", "); });"}, 3933 {NULL, NULL} 3934 }; 3935 3936 const char* strict_function_context_data[][2] = { 3937 {"(function f() {'use strict'; (", "); });"}, 3938 {NULL, NULL} 3939 }; 3940 3941 const char* generator_context_data[][2] = { 3942 {"(function *g() {'use strict'; (", "); });"}, 3943 {"(function *g() { (", "); });"}, 3944 {NULL, NULL} 3945 }; 3946 3947 const char* arrow_data[] = { 3948 "yield => {}", 3949 "(yield) => {}", 3950 "(a, yield) => {}", 3951 "(yield, a) => {}", 3952 "(yield, ...a) => {}", 3953 "(a, ...yield) => {}", 3954 "({yield}) => {}", 3955 "([yield]) => {}", 3956 NULL 3957 }; 3958 3959 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess); 3960 RunParserSyncTest(strict_function_context_data, arrow_data, kError); 3961 RunParserSyncTest(generator_context_data, arrow_data, kError); 3962 } 3963 3964 3965 TEST(SuperNoErrors) { 3966 // Tests that parser and preparser accept 'super' keyword in right places. 3967 const char* context_data[][2] = { 3968 {"class C { m() { ", "; } }"}, 3969 {"class C { m() { k = ", "; } }"}, 3970 {"class C { m() { foo(", "); } }"}, 3971 {"class C { m() { () => ", "; } }"}, 3972 {NULL, NULL} 3973 }; 3974 3975 const char* statement_data[] = { 3976 "super.x", 3977 "super[27]", 3978 "new super.x", 3979 "new super.x()", 3980 "new super[27]", 3981 "new super[27]()", 3982 "z.super", // Ok, property lookup. 3983 NULL 3984 }; 3985 3986 RunParserSyncTest(context_data, statement_data, kSuccess); 3987 } 3988 3989 3990 TEST(SuperErrors) { 3991 const char* context_data[][2] = { 3992 {"class C { m() { ", "; } }"}, 3993 {"class C { m() { k = ", "; } }"}, 3994 {"class C { m() { foo(", "); } }"}, 3995 {"class C { m() { () => ", "; } }"}, 3996 {NULL, NULL} 3997 }; 3998 3999 const char* expression_data[] = { 4000 "super", 4001 "super = x", 4002 "y = super", 4003 "f(super)", 4004 "new super", 4005 "new super()", 4006 "new super(12, 45)", 4007 "new new super", 4008 "new new super()", 4009 "new new super()()", 4010 NULL 4011 }; 4012 4013 RunParserSyncTest(context_data, expression_data, kError); 4014 } 4015 4016 4017 TEST(SuperCall) { 4018 const char* context_data[][2] = {{"", ""}, 4019 {NULL, NULL}}; 4020 4021 const char* success_data[] = { 4022 "class C extends B { constructor() { super(); } }", 4023 "class C extends B { constructor() { () => super(); } }", 4024 NULL 4025 }; 4026 4027 RunParserSyncTest(context_data, success_data, kSuccess); 4028 4029 const char* error_data[] = { 4030 "class C { constructor() { super(); } }", 4031 "class C { method() { super(); } }", 4032 "class C { method() { () => super(); } }", 4033 "class C { *method() { super(); } }", 4034 "class C { get x() { super(); } }", 4035 "class C { set x(_) { super(); } }", 4036 "({ method() { super(); } })", 4037 "({ *method() { super(); } })", 4038 "({ get x() { super(); } })", 4039 "({ set x(_) { super(); } })", 4040 "({ f: function() { super(); } })", 4041 "(function() { super(); })", 4042 "var f = function() { super(); }", 4043 "({ f: function*() { super(); } })", 4044 "(function*() { super(); })", 4045 "var f = function*() { super(); }", 4046 NULL 4047 }; 4048 4049 RunParserSyncTest(context_data, error_data, kError); 4050 } 4051 4052 4053 TEST(SuperNewNoErrors) { 4054 const char* context_data[][2] = { 4055 {"class C { constructor() { ", " } }"}, 4056 {"class C { *method() { ", " } }"}, 4057 {"class C { get x() { ", " } }"}, 4058 {"class C { set x(_) { ", " } }"}, 4059 {"({ method() { ", " } })"}, 4060 {"({ *method() { ", " } })"}, 4061 {"({ get x() { ", " } })"}, 4062 {"({ set x(_) { ", " } })"}, 4063 {NULL, NULL} 4064 }; 4065 4066 const char* expression_data[] = { 4067 "new super.x;", 4068 "new super.x();", 4069 "() => new super.x;", 4070 "() => new super.x();", 4071 NULL 4072 }; 4073 4074 RunParserSyncTest(context_data, expression_data, kSuccess); 4075 } 4076 4077 4078 TEST(SuperNewErrors) { 4079 const char* context_data[][2] = { 4080 {"class C { method() { ", " } }"}, 4081 {"class C { *method() { ", " } }"}, 4082 {"class C { get x() { ", " } }"}, 4083 {"class C { set x(_) { ", " } }"}, 4084 {"({ method() { ", " } })"}, 4085 {"({ *method() { ", " } })"}, 4086 {"({ get x() { ", " } })"}, 4087 {"({ set x(_) { ", " } })"}, 4088 {"({ f: function() { ", " } })"}, 4089 {"(function() { ", " })"}, 4090 {"var f = function() { ", " }"}, 4091 {"({ f: function*() { ", " } })"}, 4092 {"(function*() { ", " })"}, 4093 {"var f = function*() { ", " }"}, 4094 {NULL, NULL} 4095 }; 4096 4097 const char* statement_data[] = { 4098 "new super;", 4099 "new super();", 4100 "() => new super;", 4101 "() => new super();", 4102 NULL 4103 }; 4104 4105 RunParserSyncTest(context_data, statement_data, kError); 4106 } 4107 4108 4109 TEST(SuperErrorsNonMethods) { 4110 // super is only allowed in methods, accessors and constructors. 4111 const char* context_data[][2] = { 4112 {"", ";"}, 4113 {"k = ", ";"}, 4114 {"foo(", ");"}, 4115 {"if (", ") {}"}, 4116 {"if (true) {", "}"}, 4117 {"if (false) {} else {", "}"}, 4118 {"while (true) {", "}"}, 4119 {"function f() {", "}"}, 4120 {"class C extends (", ") {}"}, 4121 {"class C { m() { function f() {", "} } }"}, 4122 {"({ m() { function f() {", "} } })"}, 4123 {NULL, NULL} 4124 }; 4125 4126 const char* statement_data[] = { 4127 "super", 4128 "super = x", 4129 "y = super", 4130 "f(super)", 4131 "super.x", 4132 "super[27]", 4133 "super.x()", 4134 "super[27]()", 4135 "super()", 4136 "new super.x", 4137 "new super.x()", 4138 "new super[27]", 4139 "new super[27]()", 4140 NULL 4141 }; 4142 4143 RunParserSyncTest(context_data, statement_data, kError); 4144 } 4145 4146 4147 TEST(NoErrorsMethodDefinition) { 4148 const char* context_data[][2] = {{"({", "});"}, 4149 {"'use strict'; ({", "});"}, 4150 {"({*", "});"}, 4151 {"'use strict'; ({*", "});"}, 4152 {NULL, NULL}}; 4153 4154 const char* object_literal_body_data[] = { 4155 "m() {}", 4156 "m(x) { return x; }", 4157 "m(x, y) {}, n() {}", 4158 "set(x, y) {}", 4159 "get(x, y) {}", 4160 NULL 4161 }; 4162 4163 RunParserSyncTest(context_data, object_literal_body_data, kSuccess); 4164 } 4165 4166 4167 TEST(MethodDefinitionNames) { 4168 const char* context_data[][2] = {{"({", "(x, y) {}});"}, 4169 {"'use strict'; ({", "(x, y) {}});"}, 4170 {"({*", "(x, y) {}});"}, 4171 {"'use strict'; ({*", "(x, y) {}});"}, 4172 {NULL, NULL}}; 4173 4174 const char* name_data[] = { 4175 "m", 4176 "'m'", 4177 "\"m\"", 4178 "\"m n\"", 4179 "true", 4180 "false", 4181 "null", 4182 "0", 4183 "1.2", 4184 "1e1", 4185 "1E1", 4186 "1e+1", 4187 "1e-1", 4188 4189 // Keywords 4190 "async", 4191 "await", 4192 "break", 4193 "case", 4194 "catch", 4195 "class", 4196 "const", 4197 "continue", 4198 "debugger", 4199 "default", 4200 "delete", 4201 "do", 4202 "else", 4203 "enum", 4204 "export", 4205 "extends", 4206 "finally", 4207 "for", 4208 "function", 4209 "if", 4210 "implements", 4211 "import", 4212 "in", 4213 "instanceof", 4214 "interface", 4215 "let", 4216 "new", 4217 "package", 4218 "private", 4219 "protected", 4220 "public", 4221 "return", 4222 "static", 4223 "super", 4224 "switch", 4225 "this", 4226 "throw", 4227 "try", 4228 "typeof", 4229 "var", 4230 "void", 4231 "while", 4232 "with", 4233 "yield", 4234 NULL 4235 }; 4236 4237 RunParserSyncTest(context_data, name_data, kSuccess); 4238 } 4239 4240 4241 TEST(MethodDefinitionStrictFormalParamereters) { 4242 const char* context_data[][2] = {{"({method(", "){}});"}, 4243 {"'use strict'; ({method(", "){}});"}, 4244 {"({*method(", "){}});"}, 4245 {"'use strict'; ({*method(", "){}});"}, 4246 {NULL, NULL}}; 4247 4248 const char* params_data[] = { 4249 "x, x", 4250 "x, y, x", 4251 "var", 4252 "const", 4253 NULL 4254 }; 4255 4256 RunParserSyncTest(context_data, params_data, kError); 4257 } 4258 4259 4260 TEST(MethodDefinitionEvalArguments) { 4261 const char* strict_context_data[][2] = 4262 {{"'use strict'; ({method(", "){}});"}, 4263 {"'use strict'; ({*method(", "){}});"}, 4264 {NULL, NULL}}; 4265 const char* sloppy_context_data[][2] = 4266 {{"({method(", "){}});"}, 4267 {"({*method(", "){}});"}, 4268 {NULL, NULL}}; 4269 4270 const char* data[] = { 4271 "eval", 4272 "arguments", 4273 NULL}; 4274 4275 // Fail in strict mode 4276 RunParserSyncTest(strict_context_data, data, kError); 4277 4278 // OK in sloppy mode 4279 RunParserSyncTest(sloppy_context_data, data, kSuccess); 4280 } 4281 4282 4283 TEST(MethodDefinitionDuplicateEvalArguments) { 4284 const char* context_data[][2] = 4285 {{"'use strict'; ({method(", "){}});"}, 4286 {"'use strict'; ({*method(", "){}});"}, 4287 {"({method(", "){}});"}, 4288 {"({*method(", "){}});"}, 4289 {NULL, NULL}}; 4290 4291 const char* data[] = { 4292 "eval, eval", 4293 "eval, a, eval", 4294 "arguments, arguments", 4295 "arguments, a, arguments", 4296 NULL}; 4297 4298 // In strict mode, the error is using "eval" or "arguments" as parameter names 4299 // In sloppy mode, the error is that eval / arguments are duplicated 4300 RunParserSyncTest(context_data, data, kError); 4301 } 4302 4303 4304 TEST(MethodDefinitionDuplicateProperty) { 4305 const char* context_data[][2] = {{"'use strict'; ({", "});"}, 4306 {NULL, NULL}}; 4307 4308 const char* params_data[] = { 4309 "x: 1, x() {}", 4310 "x() {}, x: 1", 4311 "x() {}, get x() {}", 4312 "x() {}, set x(_) {}", 4313 "x() {}, x() {}", 4314 "x() {}, y() {}, x() {}", 4315 "x() {}, \"x\"() {}", 4316 "x() {}, 'x'() {}", 4317 "0() {}, '0'() {}", 4318 "1.0() {}, 1: 1", 4319 4320 "x: 1, *x() {}", 4321 "*x() {}, x: 1", 4322 "*x() {}, get x() {}", 4323 "*x() {}, set x(_) {}", 4324 "*x() {}, *x() {}", 4325 "*x() {}, y() {}, *x() {}", 4326 "*x() {}, *\"x\"() {}", 4327 "*x() {}, *'x'() {}", 4328 "*0() {}, *'0'() {}", 4329 "*1.0() {}, 1: 1", 4330 4331 NULL 4332 }; 4333 4334 RunParserSyncTest(context_data, params_data, kSuccess); 4335 } 4336 4337 4338 TEST(ClassExpressionNoErrors) { 4339 const char* context_data[][2] = {{"(", ");"}, 4340 {"var C = ", ";"}, 4341 {"bar, ", ";"}, 4342 {NULL, NULL}}; 4343 const char* class_data[] = { 4344 "class {}", 4345 "class name {}", 4346 "class extends F {}", 4347 "class name extends F {}", 4348 "class extends (F, G) {}", 4349 "class name extends (F, G) {}", 4350 "class extends class {} {}", 4351 "class name extends class {} {}", 4352 "class extends class base {} {}", 4353 "class name extends class base {} {}", 4354 NULL}; 4355 4356 RunParserSyncTest(context_data, class_data, kSuccess); 4357 } 4358 4359 4360 TEST(ClassDeclarationNoErrors) { 4361 const char* context_data[][2] = {{"'use strict'; ", ""}, 4362 {"'use strict'; {", "}"}, 4363 {"'use strict'; if (true) {", "}"}, 4364 {NULL, NULL}}; 4365 const char* statement_data[] = { 4366 "class name {}", 4367 "class name extends F {}", 4368 "class name extends (F, G) {}", 4369 "class name extends class {} {}", 4370 "class name extends class base {} {}", 4371 NULL}; 4372 4373 RunParserSyncTest(context_data, statement_data, kSuccess); 4374 } 4375 4376 4377 TEST(ClassBodyNoErrors) { 4378 // clang-format off 4379 // Tests that parser and preparser accept valid class syntax. 4380 const char* context_data[][2] = {{"(class {", "});"}, 4381 {"(class extends Base {", "});"}, 4382 {"class C {", "}"}, 4383 {"class C extends Base {", "}"}, 4384 {NULL, NULL}}; 4385 const char* class_body_data[] = { 4386 ";", 4387 ";;", 4388 "m() {}", 4389 "m() {};", 4390 "; m() {}", 4391 "m() {}; n(x) {}", 4392 "get x() {}", 4393 "set x(v) {}", 4394 "get() {}", 4395 "set() {}", 4396 "*g() {}", 4397 "*g() {};", 4398 "; *g() {}", 4399 "*g() {}; *h(x) {}", 4400 "static() {}", 4401 "get static() {}", 4402 "set static(v) {}", 4403 "static m() {}", 4404 "static get x() {}", 4405 "static set x(v) {}", 4406 "static get() {}", 4407 "static set() {}", 4408 "static static() {}", 4409 "static get static() {}", 4410 "static set static(v) {}", 4411 "*static() {}", 4412 "static *static() {}", 4413 "*get() {}", 4414 "*set() {}", 4415 "static *g() {}", 4416 4417 // Escaped 'static' should be allowed anywhere 4418 // static-as-PropertyName is. 4419 "st\\u0061tic() {}", 4420 "get st\\u0061tic() {}", 4421 "set st\\u0061tic(v) {}", 4422 "static st\\u0061tic() {}", 4423 "static get st\\u0061tic() {}", 4424 "static set st\\u0061tic(v) {}", 4425 "*st\\u0061tic() {}", 4426 "static *st\\u0061tic() {}", 4427 NULL}; 4428 // clang-format on 4429 4430 RunParserSyncTest(context_data, class_body_data, kSuccess); 4431 } 4432 4433 4434 TEST(ClassPropertyNameNoErrors) { 4435 const char* context_data[][2] = {{"(class {", "() {}});"}, 4436 {"(class { get ", "() {}});"}, 4437 {"(class { set ", "(v) {}});"}, 4438 {"(class { static ", "() {}});"}, 4439 {"(class { static get ", "() {}});"}, 4440 {"(class { static set ", "(v) {}});"}, 4441 {"(class { *", "() {}});"}, 4442 {"(class { static *", "() {}});"}, 4443 {"class C {", "() {}}"}, 4444 {"class C { get ", "() {}}"}, 4445 {"class C { set ", "(v) {}}"}, 4446 {"class C { static ", "() {}}"}, 4447 {"class C { static get ", "() {}}"}, 4448 {"class C { static set ", "(v) {}}"}, 4449 {"class C { *", "() {}}"}, 4450 {"class C { static *", "() {}}"}, 4451 {NULL, NULL}}; 4452 const char* name_data[] = { 4453 "42", 4454 "42.5", 4455 "42e2", 4456 "42e+2", 4457 "42e-2", 4458 "null", 4459 "false", 4460 "true", 4461 "'str'", 4462 "\"str\"", 4463 "static", 4464 "get", 4465 "set", 4466 "var", 4467 "const", 4468 "let", 4469 "this", 4470 "class", 4471 "function", 4472 "yield", 4473 "if", 4474 "else", 4475 "for", 4476 "while", 4477 "do", 4478 "try", 4479 "catch", 4480 "finally", 4481 NULL}; 4482 4483 RunParserSyncTest(context_data, name_data, kSuccess); 4484 } 4485 4486 4487 TEST(ClassExpressionErrors) { 4488 const char* context_data[][2] = {{"(", ");"}, 4489 {"var C = ", ";"}, 4490 {"bar, ", ";"}, 4491 {NULL, NULL}}; 4492 const char* class_data[] = { 4493 "class", 4494 "class name", 4495 "class name extends", 4496 "class extends", 4497 "class {", 4498 "class { m }", 4499 "class { m; n }", 4500 "class { m: 1 }", 4501 "class { m(); n() }", 4502 "class { get m }", 4503 "class { get m() }", 4504 "class { get m() { }", 4505 "class { set m() {} }", // Missing required parameter. 4506 "class { m() {}, n() {} }", // No commas allowed. 4507 NULL}; 4508 4509 RunParserSyncTest(context_data, class_data, kError); 4510 } 4511 4512 4513 TEST(ClassDeclarationErrors) { 4514 const char* context_data[][2] = {{"", ""}, 4515 {"{", "}"}, 4516 {"if (true) {", "}"}, 4517 {NULL, NULL}}; 4518 const char* class_data[] = { 4519 "class", 4520 "class name", 4521 "class name extends", 4522 "class extends", 4523 "class name {", 4524 "class name { m }", 4525 "class name { m; n }", 4526 "class name { m: 1 }", 4527 "class name { m(); n() }", 4528 "class name { get x }", 4529 "class name { get x() }", 4530 "class name { set x() {) }", // missing required param 4531 "class {}", // Name is required for declaration 4532 "class extends base {}", 4533 "class name { *", 4534 "class name { * }", 4535 "class name { *; }", 4536 "class name { *get x() {} }", 4537 "class name { *set x(_) {} }", 4538 "class name { *static m() {} }", 4539 NULL}; 4540 4541 RunParserSyncTest(context_data, class_data, kError); 4542 } 4543 4544 4545 TEST(ClassNameErrors) { 4546 const char* context_data[][2] = {{"class ", "{}"}, 4547 {"(class ", "{});"}, 4548 {"'use strict'; class ", "{}"}, 4549 {"'use strict'; (class ", "{});"}, 4550 {NULL, NULL}}; 4551 const char* class_name[] = { 4552 "arguments", 4553 "eval", 4554 "implements", 4555 "interface", 4556 "let", 4557 "package", 4558 "private", 4559 "protected", 4560 "public", 4561 "static", 4562 "var", 4563 "yield", 4564 NULL}; 4565 4566 RunParserSyncTest(context_data, class_name, kError); 4567 } 4568 4569 4570 TEST(ClassGetterParamNameErrors) { 4571 const char* context_data[][2] = { 4572 {"class C { get name(", ") {} }"}, 4573 {"(class { get name(", ") {} });"}, 4574 {"'use strict'; class C { get name(", ") {} }"}, 4575 {"'use strict'; (class { get name(", ") {} })"}, 4576 {NULL, NULL} 4577 }; 4578 4579 const char* class_name[] = { 4580 "arguments", 4581 "eval", 4582 "implements", 4583 "interface", 4584 "let", 4585 "package", 4586 "private", 4587 "protected", 4588 "public", 4589 "static", 4590 "var", 4591 "yield", 4592 NULL}; 4593 4594 RunParserSyncTest(context_data, class_name, kError); 4595 } 4596 4597 4598 TEST(ClassStaticPrototypeErrors) { 4599 const char* context_data[][2] = {{"class C {", "}"}, 4600 {"(class {", "});"}, 4601 {NULL, NULL}}; 4602 4603 const char* class_body_data[] = { 4604 "static prototype() {}", 4605 "static get prototype() {}", 4606 "static set prototype(_) {}", 4607 "static *prototype() {}", 4608 "static 'prototype'() {}", 4609 "static *'prototype'() {}", 4610 "static prot\\u006ftype() {}", 4611 "static 'prot\\u006ftype'() {}", 4612 "static get 'prot\\u006ftype'() {}", 4613 "static set 'prot\\u006ftype'(_) {}", 4614 "static *'prot\\u006ftype'() {}", 4615 NULL}; 4616 4617 RunParserSyncTest(context_data, class_body_data, kError); 4618 } 4619 4620 4621 TEST(ClassSpecialConstructorErrors) { 4622 const char* context_data[][2] = {{"class C {", "}"}, 4623 {"(class {", "});"}, 4624 {NULL, NULL}}; 4625 4626 const char* class_body_data[] = { 4627 "get constructor() {}", 4628 "get constructor(_) {}", 4629 "*constructor() {}", 4630 "get 'constructor'() {}", 4631 "*'constructor'() {}", 4632 "get c\\u006fnstructor() {}", 4633 "*c\\u006fnstructor() {}", 4634 "get 'c\\u006fnstructor'() {}", 4635 "get 'c\\u006fnstructor'(_) {}", 4636 "*'c\\u006fnstructor'() {}", 4637 NULL}; 4638 4639 RunParserSyncTest(context_data, class_body_data, kError); 4640 } 4641 4642 4643 TEST(ClassConstructorNoErrors) { 4644 const char* context_data[][2] = {{"class C {", "}"}, 4645 {"(class {", "});"}, 4646 {NULL, NULL}}; 4647 4648 const char* class_body_data[] = { 4649 "constructor() {}", 4650 "static constructor() {}", 4651 "static get constructor() {}", 4652 "static set constructor(_) {}", 4653 "static *constructor() {}", 4654 NULL}; 4655 4656 RunParserSyncTest(context_data, class_body_data, kSuccess); 4657 } 4658 4659 4660 TEST(ClassMultipleConstructorErrors) { 4661 const char* context_data[][2] = {{"class C {", "}"}, 4662 {"(class {", "});"}, 4663 {NULL, NULL}}; 4664 4665 const char* class_body_data[] = { 4666 "constructor() {}; constructor() {}", 4667 NULL}; 4668 4669 RunParserSyncTest(context_data, class_body_data, kError); 4670 } 4671 4672 4673 TEST(ClassMultiplePropertyNamesNoErrors) { 4674 const char* context_data[][2] = {{"class C {", "}"}, 4675 {"(class {", "});"}, 4676 {NULL, NULL}}; 4677 4678 const char* class_body_data[] = { 4679 "constructor() {}; static constructor() {}", 4680 "m() {}; static m() {}", 4681 "m() {}; m() {}", 4682 "static m() {}; static m() {}", 4683 "get m() {}; set m(_) {}; get m() {}; set m(_) {};", 4684 NULL}; 4685 4686 RunParserSyncTest(context_data, class_body_data, kSuccess); 4687 } 4688 4689 4690 TEST(ClassesAreStrictErrors) { 4691 const char* context_data[][2] = {{"", ""}, 4692 {"(", ");"}, 4693 {NULL, NULL}}; 4694 4695 const char* class_body_data[] = { 4696 "class C { method() { with ({}) {} } }", 4697 "class C extends function() { with ({}) {} } {}", 4698 "class C { *method() { with ({}) {} } }", 4699 NULL}; 4700 4701 RunParserSyncTest(context_data, class_body_data, kError); 4702 } 4703 4704 4705 TEST(ObjectLiteralPropertyShorthandKeywordsError) { 4706 const char* context_data[][2] = {{"({", "});"}, 4707 {"'use strict'; ({", "});"}, 4708 {NULL, NULL}}; 4709 4710 const char* name_data[] = { 4711 "break", 4712 "case", 4713 "catch", 4714 "class", 4715 "const", 4716 "continue", 4717 "debugger", 4718 "default", 4719 "delete", 4720 "do", 4721 "else", 4722 "enum", 4723 "export", 4724 "extends", 4725 "false", 4726 "finally", 4727 "for", 4728 "function", 4729 "if", 4730 "import", 4731 "in", 4732 "instanceof", 4733 "new", 4734 "null", 4735 "return", 4736 "super", 4737 "switch", 4738 "this", 4739 "throw", 4740 "true", 4741 "try", 4742 "typeof", 4743 "var", 4744 "void", 4745 "while", 4746 "with", 4747 NULL 4748 }; 4749 4750 RunParserSyncTest(context_data, name_data, kError); 4751 } 4752 4753 4754 TEST(ObjectLiteralPropertyShorthandStrictKeywords) { 4755 const char* context_data[][2] = {{"({", "});"}, 4756 {NULL, NULL}}; 4757 4758 const char* name_data[] = { 4759 "implements", 4760 "interface", 4761 "let", 4762 "package", 4763 "private", 4764 "protected", 4765 "public", 4766 "static", 4767 "yield", 4768 NULL 4769 }; 4770 4771 RunParserSyncTest(context_data, name_data, kSuccess); 4772 4773 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"}, 4774 {NULL, NULL}}; 4775 RunParserSyncTest(context_strict_data, name_data, kError); 4776 } 4777 4778 4779 TEST(ObjectLiteralPropertyShorthandError) { 4780 const char* context_data[][2] = {{"({", "});"}, 4781 {"'use strict'; ({", "});"}, 4782 {NULL, NULL}}; 4783 4784 const char* name_data[] = { 4785 "1", 4786 "1.2", 4787 "0", 4788 "0.1", 4789 "1.0", 4790 "1e1", 4791 "0x1", 4792 "\"s\"", 4793 "'s'", 4794 NULL 4795 }; 4796 4797 RunParserSyncTest(context_data, name_data, kError); 4798 } 4799 4800 4801 TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) { 4802 const char* context_data[][2] = {{"", ""}, 4803 {NULL, NULL}}; 4804 4805 const char* name_data[] = { 4806 "function* g() { ({yield}); }", 4807 NULL 4808 }; 4809 4810 RunParserSyncTest(context_data, name_data, kError); 4811 } 4812 4813 4814 TEST(ConstParsingInForIn) { 4815 const char* context_data[][2] = {{"'use strict';", ""}, 4816 {"function foo(){ 'use strict';", "}"}, 4817 {NULL, NULL}}; 4818 4819 const char* data[] = { 4820 "for(const x = 1; ; ) {}", 4821 "for(const x = 1, y = 2;;){}", 4822 "for(const x in [1,2,3]) {}", 4823 "for(const x of [1,2,3]) {}", 4824 NULL}; 4825 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0); 4826 } 4827 4828 4829 TEST(StatementParsingInForIn) { 4830 const char* context_data[][2] = {{"", ""}, 4831 {"'use strict';", ""}, 4832 {"function foo(){ 'use strict';", "}"}, 4833 {NULL, NULL}}; 4834 4835 const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}", 4836 "for(let x in {}, {}) {}", "for(const x in {}, {}) {}", 4837 NULL}; 4838 4839 RunParserSyncTest(context_data, data, kSuccess); 4840 } 4841 4842 4843 TEST(ConstParsingInForInError) { 4844 const char* context_data[][2] = {{"'use strict';", ""}, 4845 {"function foo(){ 'use strict';", "}"}, 4846 {NULL, NULL}}; 4847 4848 const char* data[] = { 4849 "for(const x,y = 1; ; ) {}", 4850 "for(const x = 4 in [1,2,3]) {}", 4851 "for(const x = 4, y in [1,2,3]) {}", 4852 "for(const x = 4 of [1,2,3]) {}", 4853 "for(const x = 4, y of [1,2,3]) {}", 4854 "for(const x = 1, y = 2 in []) {}", 4855 "for(const x,y in []) {}", 4856 "for(const x = 1, y = 2 of []) {}", 4857 "for(const x,y of []) {}", 4858 NULL}; 4859 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0); 4860 } 4861 4862 4863 TEST(InitializedDeclarationsInStrictForInError) { 4864 const char* context_data[][2] = {{"'use strict';", ""}, 4865 {"function foo(){ 'use strict';", "}"}, 4866 {NULL, NULL}}; 4867 4868 const char* data[] = { 4869 "for (var i = 1 in {}) {}", 4870 "for (var i = void 0 in [1, 2, 3]) {}", 4871 "for (let i = 1 in {}) {}", 4872 "for (let i = void 0 in [1, 2, 3]) {}", 4873 "for (const i = 1 in {}) {}", 4874 "for (const i = void 0 in [1, 2, 3]) {}", 4875 NULL}; 4876 RunParserSyncTest(context_data, data, kError); 4877 } 4878 4879 4880 TEST(InitializedDeclarationsInStrictForOfError) { 4881 const char* context_data[][2] = {{"'use strict';", ""}, 4882 {"function foo(){ 'use strict';", "}"}, 4883 {NULL, NULL}}; 4884 4885 const char* data[] = { 4886 "for (var i = 1 of {}) {}", 4887 "for (var i = void 0 of [1, 2, 3]) {}", 4888 "for (let i = 1 of {}) {}", 4889 "for (let i = void 0 of [1, 2, 3]) {}", 4890 "for (const i = 1 of {}) {}", 4891 "for (const i = void 0 of [1, 2, 3]) {}", 4892 NULL}; 4893 RunParserSyncTest(context_data, data, kError); 4894 } 4895 4896 4897 TEST(InitializedDeclarationsInSloppyForInError) { 4898 const char* context_data[][2] = {{"", ""}, 4899 {"function foo(){", "}"}, 4900 {NULL, NULL}}; 4901 4902 const char* data[] = { 4903 "for (var i = 1 in {}) {}", 4904 "for (var i = void 0 in [1, 2, 3]) {}", 4905 NULL}; 4906 // TODO(caitp): This should be an error in sloppy mode. 4907 RunParserSyncTest(context_data, data, kSuccess); 4908 } 4909 4910 4911 TEST(InitializedDeclarationsInSloppyForOfError) { 4912 const char* context_data[][2] = {{"", ""}, 4913 {"function foo(){", "}"}, 4914 {NULL, NULL}}; 4915 4916 const char* data[] = { 4917 "for (var i = 1 of {}) {}", 4918 "for (var i = void 0 of [1, 2, 3]) {}", 4919 NULL}; 4920 RunParserSyncTest(context_data, data, kError); 4921 } 4922 4923 4924 TEST(ForInMultipleDeclarationsError) { 4925 const char* context_data[][2] = {{"", ""}, 4926 {"function foo(){", "}"}, 4927 {"'use strict';", ""}, 4928 {"function foo(){ 'use strict';", "}"}, 4929 {NULL, NULL}}; 4930 4931 const char* data[] = { 4932 "for (var i, j in {}) {}", 4933 "for (var i, j in [1, 2, 3]) {}", 4934 "for (var i, j = 1 in {}) {}", 4935 "for (var i, j = void 0 in [1, 2, 3]) {}", 4936 4937 "for (let i, j in {}) {}", 4938 "for (let i, j in [1, 2, 3]) {}", 4939 "for (let i, j = 1 in {}) {}", 4940 "for (let i, j = void 0 in [1, 2, 3]) {}", 4941 4942 "for (const i, j in {}) {}", 4943 "for (const i, j in [1, 2, 3]) {}", 4944 "for (const i, j = 1 in {}) {}", 4945 "for (const i, j = void 0 in [1, 2, 3]) {}", 4946 NULL}; 4947 RunParserSyncTest(context_data, data, kError); 4948 } 4949 4950 4951 TEST(ForOfMultipleDeclarationsError) { 4952 const char* context_data[][2] = {{"", ""}, 4953 {"function foo(){", "}"}, 4954 {"'use strict';", ""}, 4955 {"function foo(){ 'use strict';", "}"}, 4956 {NULL, NULL}}; 4957 4958 const char* data[] = { 4959 "for (var i, j of {}) {}", 4960 "for (var i, j of [1, 2, 3]) {}", 4961 "for (var i, j = 1 of {}) {}", 4962 "for (var i, j = void 0 of [1, 2, 3]) {}", 4963 4964 "for (let i, j of {}) {}", 4965 "for (let i, j of [1, 2, 3]) {}", 4966 "for (let i, j = 1 of {}) {}", 4967 "for (let i, j = void 0 of [1, 2, 3]) {}", 4968 4969 "for (const i, j of {}) {}", 4970 "for (const i, j of [1, 2, 3]) {}", 4971 "for (const i, j = 1 of {}) {}", 4972 "for (const i, j = void 0 of [1, 2, 3]) {}", 4973 NULL}; 4974 RunParserSyncTest(context_data, data, kError); 4975 } 4976 4977 4978 TEST(ForInNoDeclarationsError) { 4979 const char* context_data[][2] = {{"", ""}, 4980 {"function foo(){", "}"}, 4981 {"'use strict';", ""}, 4982 {"function foo(){ 'use strict';", "}"}, 4983 {NULL, NULL}}; 4984 4985 const char* data[] = { 4986 "for (var in {}) {}", 4987 "for (const in {}) {}", 4988 NULL}; 4989 RunParserSyncTest(context_data, data, kError); 4990 } 4991 4992 4993 TEST(ForOfNoDeclarationsError) { 4994 const char* context_data[][2] = {{"", ""}, 4995 {"function foo(){", "}"}, 4996 {"'use strict';", ""}, 4997 {"function foo(){ 'use strict';", "}"}, 4998 {NULL, NULL}}; 4999 5000 const char* data[] = { 5001 "for (var of [1, 2, 3]) {}", 5002 "for (const of [1, 2, 3]) {}", 5003 NULL}; 5004 RunParserSyncTest(context_data, data, kError); 5005 } 5006 5007 5008 TEST(ForOfInOperator) { 5009 const char* context_data[][2] = {{"", ""}, 5010 {"'use strict';", ""}, 5011 {"function foo(){ 'use strict';", "}"}, 5012 {NULL, NULL}}; 5013 5014 const char* data[] = { 5015 "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}", 5016 "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL}; 5017 5018 RunParserSyncTest(context_data, data, kSuccess); 5019 } 5020 5021 5022 TEST(ForOfYieldIdentifier) { 5023 const char* context_data[][2] = {{"", ""}, {NULL, NULL}}; 5024 5025 const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}", 5026 "for(let x of yield) {}", "for(const x of yield) {}", 5027 NULL}; 5028 5029 RunParserSyncTest(context_data, data, kSuccess); 5030 } 5031 5032 5033 TEST(ForOfYieldExpression) { 5034 const char* context_data[][2] = {{"", ""}, 5035 {"'use strict';", ""}, 5036 {"function foo(){ 'use strict';", "}"}, 5037 {NULL, NULL}}; 5038 5039 const char* data[] = {"function* g() { for(x of yield) {} }", 5040 "function* g() { for(var x of yield) {} }", 5041 "function* g() { for(let x of yield) {} }", 5042 "function* g() { for(const x of yield) {} }", NULL}; 5043 5044 RunParserSyncTest(context_data, data, kSuccess); 5045 } 5046 5047 5048 TEST(ForOfExpressionError) { 5049 const char* context_data[][2] = {{"", ""}, 5050 {"'use strict';", ""}, 5051 {"function foo(){ 'use strict';", "}"}, 5052 {NULL, NULL}}; 5053 5054 const char* data[] = { 5055 "for(x of [], []) {}", "for(var x of [], []) {}", 5056 "for(let x of [], []) {}", "for(const x of [], []) {}", 5057 5058 // AssignmentExpression should be validated statically: 5059 "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}", 5060 "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL}; 5061 5062 RunParserSyncTest(context_data, data, kError); 5063 } 5064 5065 5066 TEST(InvalidUnicodeEscapes) { 5067 const char* context_data[][2] = {{"", ""}, 5068 {"'use strict';", ""}, 5069 {NULL, NULL}}; 5070 const char* data[] = { 5071 "var foob\\u123r = 0;", 5072 "var \\u123roo = 0;", 5073 "\"foob\\u123rr\"", 5074 // No escapes allowed in regexp flags 5075 "/regex/\\u0069g", 5076 "/regex/\\u006g", 5077 // Braces gone wrong 5078 "var foob\\u{c481r = 0;", 5079 "var foob\\uc481}r = 0;", 5080 "var \\u{0052oo = 0;", 5081 "var \\u0052}oo = 0;", 5082 "\"foob\\u{c481r\"", 5083 "var foob\\u{}ar = 0;", 5084 // Too high value for the unicode escape 5085 "\"\\u{110000}\"", 5086 // Not an unicode escape 5087 "var foob\\v1234r = 0;", 5088 "var foob\\U1234r = 0;", 5089 "var foob\\v{1234}r = 0;", 5090 "var foob\\U{1234}r = 0;", 5091 NULL}; 5092 RunParserSyncTest(context_data, data, kError); 5093 } 5094 5095 5096 TEST(UnicodeEscapes) { 5097 const char* context_data[][2] = {{"", ""}, 5098 {"'use strict';", ""}, 5099 {NULL, NULL}}; 5100 const char* data[] = { 5101 // Identifier starting with escape 5102 "var \\u0052oo = 0;", 5103 "var \\u{0052}oo = 0;", 5104 "var \\u{52}oo = 0;", 5105 "var \\u{00000000052}oo = 0;", 5106 // Identifier with an escape but not starting with an escape 5107 "var foob\\uc481r = 0;", 5108 "var foob\\u{c481}r = 0;", 5109 // String with an escape 5110 "\"foob\\uc481r\"", 5111 "\"foob\\{uc481}r\"", 5112 // This character is a valid unicode character, representable as a surrogate 5113 // pair, not representable as 4 hex digits. 5114 "\"foo\\u{10e6d}\"", 5115 // Max value for the unicode escape 5116 "\"\\u{10ffff}\"", 5117 NULL}; 5118 RunParserSyncTest(context_data, data, kSuccess); 5119 } 5120 5121 5122 TEST(ScanTemplateLiterals) { 5123 const char* context_data[][2] = {{"'use strict';", ""}, 5124 {"function foo(){ 'use strict';" 5125 " var a, b, c; return ", "}"}, 5126 {NULL, NULL}}; 5127 5128 const char* data[] = { 5129 "``", 5130 "`no-subst-template`", 5131 "`template-head${a}`", 5132 "`${a}`", 5133 "`${a}template-tail`", 5134 "`template-head${a}template-tail`", 5135 "`${a}${b}${c}`", 5136 "`a${a}b${b}c${c}`", 5137 "`${a}a${b}b${c}c`", 5138 "`foo\n\nbar\r\nbaz`", 5139 "`foo\n\n${ bar }\r\nbaz`", 5140 "`foo${a /* comment */}`", 5141 "`foo${a // comment\n}`", 5142 "`foo${a \n}`", 5143 "`foo${a \r\n}`", 5144 "`foo${a \r}`", 5145 "`foo${/* comment */ a}`", 5146 "`foo${// comment\na}`", 5147 "`foo${\n a}`", 5148 "`foo${\r\n a}`", 5149 "`foo${\r a}`", 5150 "`foo${'a' in a}`", 5151 NULL}; 5152 RunParserSyncTest(context_data, data, kSuccess); 5153 } 5154 5155 5156 TEST(ScanTaggedTemplateLiterals) { 5157 const char* context_data[][2] = {{"'use strict';", ""}, 5158 {"function foo(){ 'use strict';" 5159 " function tag() {}" 5160 " var a, b, c; return ", "}"}, 5161 {NULL, NULL}}; 5162 5163 const char* data[] = { 5164 "tag ``", 5165 "tag `no-subst-template`", 5166 "tag`template-head${a}`", 5167 "tag `${a}`", 5168 "tag `${a}template-tail`", 5169 "tag `template-head${a}template-tail`", 5170 "tag\n`${a}${b}${c}`", 5171 "tag\r\n`a${a}b${b}c${c}`", 5172 "tag `${a}a${b}b${c}c`", 5173 "tag\t`foo\n\nbar\r\nbaz`", 5174 "tag\r`foo\n\n${ bar }\r\nbaz`", 5175 "tag`foo${a /* comment */}`", 5176 "tag`foo${a // comment\n}`", 5177 "tag`foo${a \n}`", 5178 "tag`foo${a \r\n}`", 5179 "tag`foo${a \r}`", 5180 "tag`foo${/* comment */ a}`", 5181 "tag`foo${// comment\na}`", 5182 "tag`foo${\n a}`", 5183 "tag`foo${\r\n a}`", 5184 "tag`foo${\r a}`", 5185 "tag`foo${'a' in a}`", 5186 NULL}; 5187 RunParserSyncTest(context_data, data, kSuccess); 5188 } 5189 5190 5191 TEST(TemplateMaterializedLiterals) { 5192 const char* context_data[][2] = { 5193 { 5194 "'use strict';\n" 5195 "function tag() {}\n" 5196 "var a, b, c;\n" 5197 "(", ")" 5198 }, 5199 {NULL, NULL} 5200 }; 5201 5202 const char* data[] = { 5203 "tag``", 5204 "tag`a`", 5205 "tag`a${1}b`", 5206 "tag`a${1}b${2}c`", 5207 "``", 5208 "`a`", 5209 "`a${1}b`", 5210 "`a${1}b${2}c`", 5211 NULL 5212 }; 5213 5214 RunParserSyncTest(context_data, data, kSuccess); 5215 } 5216 5217 5218 TEST(ScanUnterminatedTemplateLiterals) { 5219 const char* context_data[][2] = {{"'use strict';", ""}, 5220 {"function foo(){ 'use strict';" 5221 " var a, b, c; return ", "}"}, 5222 {NULL, NULL}}; 5223 5224 const char* data[] = { 5225 "`no-subst-template", 5226 "`template-head${a}", 5227 "`${a}template-tail", 5228 "`template-head${a}template-tail", 5229 "`${a}${b}${c}", 5230 "`a${a}b${b}c${c}", 5231 "`${a}a${b}b${c}c", 5232 "`foo\n\nbar\r\nbaz", 5233 "`foo\n\n${ bar }\r\nbaz", 5234 "`foo${a /* comment } */`", 5235 "`foo${a /* comment } `*/", 5236 "`foo${a // comment}`", 5237 "`foo${a \n`", 5238 "`foo${a \r\n`", 5239 "`foo${a \r`", 5240 "`foo${/* comment */ a`", 5241 "`foo${// commenta}`", 5242 "`foo${\n a`", 5243 "`foo${\r\n a`", 5244 "`foo${\r a`", 5245 "`foo${fn(}`", 5246 "`foo${1 if}`", 5247 NULL}; 5248 RunParserSyncTest(context_data, data, kError); 5249 } 5250 5251 5252 TEST(TemplateLiteralsIllegalTokens) { 5253 const char* context_data[][2] = {{"'use strict';", ""}, 5254 {"function foo(){ 'use strict';" 5255 " var a, b, c; return ", "}"}, 5256 {NULL, NULL}}; 5257 const char* data[] = { 5258 "`hello\\x`", 5259 "`hello\\x${1}`", 5260 "`hello${1}\\x`", 5261 "`hello${1}\\x${2}`", 5262 "`hello\\x\n`", 5263 "`hello\\x\n${1}`", 5264 "`hello${1}\\x\n`", 5265 "`hello${1}\\x\n${2}`", 5266 NULL}; 5267 5268 RunParserSyncTest(context_data, data, kError); 5269 } 5270 5271 5272 TEST(ParseRestParameters) { 5273 const char* context_data[][2] = {{"'use strict';(function(", 5274 "){ return args;})(1, [], /regexp/, 'str'," 5275 "function(){});"}, 5276 {"(function(", "){ return args;})(1, []," 5277 "/regexp/, 'str', function(){});"}, 5278 {NULL, NULL}}; 5279 5280 const char* data[] = {"...args", 5281 "a, ...args", 5282 "... args", 5283 "a, ... args", 5284 "...\targs", 5285 "a, ...\targs", 5286 "...\r\nargs", 5287 "a, ...\r\nargs", 5288 "...\rargs", 5289 "a, ...\rargs", 5290 "...\t\n\t\t\n args", 5291 "a, ... \n \n args", 5292 "...{ length, 0: a, 1: b}", 5293 "...{}", 5294 "...[a, b]", 5295 "...[]", 5296 "...[...[a, b, ...c]]", 5297 NULL}; 5298 RunParserSyncTest(context_data, data, kSuccess); 5299 } 5300 5301 5302 TEST(ParseRestParametersErrors) { 5303 const char* context_data[][2] = {{"'use strict';(function(", 5304 "){ return args;}(1, [], /regexp/, 'str'," 5305 "function(){});"}, 5306 {"(function(", "){ return args;}(1, []," 5307 "/regexp/, 'str', function(){});"}, 5308 {NULL, NULL}}; 5309 5310 const char* data[] = { 5311 "...args, b", 5312 "a, ...args, b", 5313 "...args, b", 5314 "a, ...args, b", 5315 "...args,\tb", 5316 "a,...args\t,b", 5317 "...args\r\n, b", 5318 "a, ... args,\r\nb", 5319 "...args\r,b", 5320 "a, ... args,\rb", 5321 "...args\t\n\t\t\n, b", 5322 "a, ... args, \n \n b", 5323 "a, a, ...args", 5324 "a,\ta, ...args", 5325 "a,\ra, ...args", 5326 "a,\na, ...args", 5327 NULL}; 5328 RunParserSyncTest(context_data, data, kError); 5329 } 5330 5331 5332 TEST(RestParameterInSetterMethodError) { 5333 const char* context_data[][2] = { 5334 {"'use strict';({ set prop(", ") {} }).prop = 1;"}, 5335 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"}, 5336 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"}, 5337 {"({ set prop(", ") {} }).prop = 1;"}, 5338 {"(class { static set prop(", ") {} }).prop = 1;"}, 5339 {"(new (class { set prop(", ") {} })).prop = 1;"}, 5340 {nullptr, nullptr}}; 5341 const char* data[] = {"...a", "...arguments", "...eval", nullptr}; 5342 5343 RunParserSyncTest(context_data, data, kError); 5344 } 5345 5346 5347 TEST(RestParametersEvalArguments) { 5348 // clang-format off 5349 const char* strict_context_data[][2] = 5350 {{"'use strict';(function(", 5351 "){ return;})(1, [], /regexp/, 'str',function(){});"}, 5352 {NULL, NULL}}; 5353 const char* sloppy_context_data[][2] = 5354 {{"(function(", 5355 "){ return;})(1, [],/regexp/, 'str', function(){});"}, 5356 {NULL, NULL}}; 5357 5358 const char* data[] = { 5359 "...eval", 5360 "eval, ...args", 5361 "...arguments", 5362 // See https://bugs.chromium.org/p/v8/issues/detail?id=4577 5363 // "arguments, ...args", 5364 NULL}; 5365 // clang-format on 5366 5367 // Fail in strict mode 5368 RunParserSyncTest(strict_context_data, data, kError); 5369 5370 // OK in sloppy mode 5371 RunParserSyncTest(sloppy_context_data, data, kSuccess); 5372 } 5373 5374 5375 TEST(RestParametersDuplicateEvalArguments) { 5376 const char* context_data[][2] = 5377 {{"'use strict';(function(", 5378 "){ return;})(1, [], /regexp/, 'str',function(){});"}, 5379 {"(function(", 5380 "){ return;})(1, [],/regexp/, 'str', function(){});"}, 5381 {NULL, NULL}}; 5382 5383 const char* data[] = { 5384 "eval, ...eval", 5385 "eval, eval, ...args", 5386 "arguments, ...arguments", 5387 "arguments, arguments, ...args", 5388 NULL}; 5389 5390 // In strict mode, the error is using "eval" or "arguments" as parameter names 5391 // In sloppy mode, the error is that eval / arguments are duplicated 5392 RunParserSyncTest(context_data, data, kError); 5393 } 5394 5395 5396 TEST(SpreadCall) { 5397 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"}, 5398 {"function fn() {} fn(", ");"}, 5399 {NULL, NULL}}; 5400 5401 const char* data[] = { 5402 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4", 5403 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN", 5404 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'", 5405 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10", 5406 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9", 5407 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL}; 5408 5409 RunParserSyncTest(context_data, data, kSuccess); 5410 } 5411 5412 5413 TEST(SpreadCallErrors) { 5414 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"}, 5415 {"function fn() {} fn(", ");"}, 5416 {NULL, NULL}}; 5417 5418 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL}; 5419 5420 RunParserSyncTest(context_data, data, kError); 5421 } 5422 5423 5424 TEST(BadRestSpread) { 5425 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"}, 5426 {"function fn() { ", "} fn();"}, 5427 {NULL, NULL}}; 5428 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];", 5429 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];", 5430 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}", 5431 NULL}; 5432 RunParserSyncTest(context_data, data, kError); 5433 } 5434 5435 5436 TEST(LexicalScopingSloppyMode) { 5437 const char* context_data[][2] = { 5438 {"", ""}, 5439 {"function f() {", "}"}, 5440 {"{", "}"}, 5441 {NULL, NULL}}; 5442 5443 const char* good_data[] = { 5444 "let = 1;", 5445 "for(let = 1;;){}", 5446 NULL}; 5447 RunParserSyncTest(context_data, good_data, kSuccess); 5448 } 5449 5450 5451 TEST(ComputedPropertyName) { 5452 const char* context_data[][2] = {{"({[", "]: 1});"}, 5453 {"({get [", "]() {}});"}, 5454 {"({set [", "](_) {}});"}, 5455 {"({[", "]() {}});"}, 5456 {"({*[", "]() {}});"}, 5457 {"(class {get [", "]() {}});"}, 5458 {"(class {set [", "](_) {}});"}, 5459 {"(class {[", "]() {}});"}, 5460 {"(class {*[", "]() {}});"}, 5461 {NULL, NULL}}; 5462 const char* error_data[] = { 5463 "1, 2", 5464 "var name", 5465 NULL}; 5466 5467 RunParserSyncTest(context_data, error_data, kError); 5468 5469 const char* name_data[] = { 5470 "1", 5471 "1 + 2", 5472 "'name'", 5473 "\"name\"", 5474 "[]", 5475 "{}", 5476 NULL}; 5477 5478 RunParserSyncTest(context_data, name_data, kSuccess); 5479 } 5480 5481 5482 TEST(ComputedPropertyNameShorthandError) { 5483 const char* context_data[][2] = {{"({", "});"}, 5484 {NULL, NULL}}; 5485 const char* error_data[] = { 5486 "a: 1, [2]", 5487 "[1], a: 1", 5488 NULL}; 5489 5490 RunParserSyncTest(context_data, error_data, kError); 5491 } 5492 5493 5494 TEST(BasicImportExportParsing) { 5495 // clang-format off 5496 const char* kSources[] = { 5497 "export let x = 0;", 5498 "export var y = 0;", 5499 "export const z = 0;", 5500 "export function func() { };", 5501 "export class C { };", 5502 "export { };", 5503 "function f() {}; f(); export { f };", 5504 "var a, b, c; export { a, b as baz, c };", 5505 "var d, e; export { d as dreary, e, };", 5506 "export default function f() {}", 5507 "export default function() {}", 5508 "export default function*() {}", 5509 "export default class C {}", 5510 "export default class {}" 5511 "export default class extends C {}" 5512 "export default 42", 5513 "var x; export default x = 7", 5514 "export { Q } from 'somemodule.js';", 5515 "export * from 'somemodule.js';", 5516 "var foo; export { foo as for };", 5517 "export { arguments } from 'm.js';", 5518 "export { for } from 'm.js';", 5519 "export { yield } from 'm.js'", 5520 "export { static } from 'm.js'", 5521 "export { let } from 'm.js'", 5522 "var a; export { a as b, a as c };", 5523 "var a; export { a as await };", 5524 "var a; export { a as enum };", 5525 5526 "import 'somemodule.js';", 5527 "import { } from 'm.js';", 5528 "import { a } from 'm.js';", 5529 "import { a, b as d, c, } from 'm.js';", 5530 "import * as thing from 'm.js';", 5531 "import thing from 'm.js';", 5532 "import thing, * as rest from 'm.js';", 5533 "import thing, { a, b, c } from 'm.js';", 5534 "import { arguments as a } from 'm.js';", 5535 "import { for as f } from 'm.js';", 5536 "import { yield as y } from 'm.js';", 5537 "import { static as s } from 'm.js';", 5538 "import { let as l } from 'm.js';", 5539 }; 5540 // clang-format on 5541 5542 i::Isolate* isolate = CcTest::i_isolate(); 5543 i::Factory* factory = isolate->factory(); 5544 5545 v8::HandleScope handles(CcTest::isolate()); 5546 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 5547 v8::Context::Scope context_scope(context); 5548 5549 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 5550 128 * 1024); 5551 5552 for (unsigned i = 0; i < arraysize(kSources); ++i) { 5553 i::Handle<i::String> source = 5554 factory->NewStringFromAsciiChecked(kSources[i]); 5555 5556 // Show that parsing as a module works 5557 { 5558 i::Handle<i::Script> script = factory->NewScript(source); 5559 i::Zone zone(CcTest::i_isolate()->allocator()); 5560 i::ParseInfo info(&zone, script); 5561 i::Parser parser(&info); 5562 info.set_module(); 5563 if (!parser.Parse(&info)) { 5564 i::Handle<i::JSObject> exception_handle( 5565 i::JSObject::cast(isolate->pending_exception())); 5566 i::Handle<i::String> message_string = i::Handle<i::String>::cast( 5567 i::JSReceiver::GetProperty(isolate, exception_handle, "message") 5568 .ToHandleChecked()); 5569 5570 v8::base::OS::Print( 5571 "Parser failed on:\n" 5572 "\t%s\n" 5573 "with error:\n" 5574 "\t%s\n" 5575 "However, we expected no error.", 5576 source->ToCString().get(), message_string->ToCString().get()); 5577 CHECK(false); 5578 } 5579 } 5580 5581 // And that parsing a script does not. 5582 { 5583 i::Handle<i::Script> script = factory->NewScript(source); 5584 i::Zone zone(CcTest::i_isolate()->allocator()); 5585 i::ParseInfo info(&zone, script); 5586 i::Parser parser(&info); 5587 info.set_global(); 5588 CHECK(!parser.Parse(&info)); 5589 } 5590 } 5591 } 5592 5593 5594 TEST(ImportExportParsingErrors) { 5595 // clang-format off 5596 const char* kErrorSources[] = { 5597 "export {", 5598 "var a; export { a", 5599 "var a; export { a,", 5600 "var a; export { a, ;", 5601 "var a; export { a as };", 5602 "var a, b; export { a as , b};", 5603 "export }", 5604 "var foo, bar; export { foo bar };", 5605 "export { foo };", 5606 "export { , };", 5607 "export default;", 5608 "export default var x = 7;", 5609 "export default let x = 7;", 5610 "export default const x = 7;", 5611 "export *;", 5612 "export * from;", 5613 "export { Q } from;", 5614 "export default from 'module.js';", 5615 "export { for }", 5616 "export { for as foo }", 5617 "export { arguments }", 5618 "export { arguments as foo }", 5619 "var a; export { a, a };", 5620 "var a, b; export { a as b, b };", 5621 "var a, b; export { a as c, b as c };", 5622 "export default function f(){}; export default class C {};", 5623 "export default function f(){}; var a; export { a as default };", 5624 "export function() {}", 5625 "export function*() {}", 5626 "export class {}", 5627 "export class extends C {}", 5628 5629 "import from;", 5630 "import from 'm.js';", 5631 "import { };", 5632 "import {;", 5633 "import };", 5634 "import { , };", 5635 "import { , } from 'm.js';", 5636 "import { a } from;", 5637 "import { a } 'm.js';", 5638 "import , from 'm.js';", 5639 "import a , from 'm.js';", 5640 "import a { b, c } from 'm.js';", 5641 "import arguments from 'm.js';", 5642 "import eval from 'm.js';", 5643 "import { arguments } from 'm.js';", 5644 "import { eval } from 'm.js';", 5645 "import { a as arguments } from 'm.js';", 5646 "import { for } from 'm.js';", 5647 "import { y as yield } from 'm.js'", 5648 "import { s as static } from 'm.js'", 5649 "import { l as let } from 'm.js'", 5650 "import { a as await } from 'm.js';", 5651 "import { a as enum } from 'm.js';", 5652 "import { x }, def from 'm.js';", 5653 "import def, def2 from 'm.js';", 5654 "import * as x, def from 'm.js';", 5655 "import * as x, * as y from 'm.js';", 5656 "import {x}, {y} from 'm.js';", 5657 "import * as x, {y} from 'm.js';", 5658 }; 5659 // clang-format on 5660 5661 i::Isolate* isolate = CcTest::i_isolate(); 5662 i::Factory* factory = isolate->factory(); 5663 5664 v8::HandleScope handles(CcTest::isolate()); 5665 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 5666 v8::Context::Scope context_scope(context); 5667 5668 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 5669 128 * 1024); 5670 5671 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) { 5672 i::Handle<i::String> source = 5673 factory->NewStringFromAsciiChecked(kErrorSources[i]); 5674 5675 i::Handle<i::Script> script = factory->NewScript(source); 5676 i::Zone zone(CcTest::i_isolate()->allocator()); 5677 i::ParseInfo info(&zone, script); 5678 i::Parser parser(&info); 5679 info.set_module(); 5680 CHECK(!parser.Parse(&info)); 5681 } 5682 } 5683 5684 TEST(ModuleTopLevelFunctionDecl) { 5685 // clang-format off 5686 const char* kErrorSources[] = { 5687 "function f() {} function f() {}", 5688 "var f; function f() {}", 5689 "function f() {} var f;", 5690 "function* f() {} function* f() {}", 5691 "var f; function* f() {}", 5692 "function* f() {} var f;", 5693 "function f() {} function* f() {}", 5694 "function* f() {} function f() {}", 5695 }; 5696 // clang-format on 5697 5698 i::Isolate* isolate = CcTest::i_isolate(); 5699 i::Factory* factory = isolate->factory(); 5700 5701 v8::HandleScope handles(CcTest::isolate()); 5702 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 5703 v8::Context::Scope context_scope(context); 5704 5705 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 5706 128 * 1024); 5707 5708 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) { 5709 i::Handle<i::String> source = 5710 factory->NewStringFromAsciiChecked(kErrorSources[i]); 5711 5712 i::Handle<i::Script> script = factory->NewScript(source); 5713 i::Zone zone(CcTest::i_isolate()->allocator()); 5714 i::ParseInfo info(&zone, script); 5715 i::Parser parser(&info); 5716 info.set_module(); 5717 CHECK(!parser.Parse(&info)); 5718 } 5719 } 5720 5721 TEST(ModuleAwaitReserved) { 5722 // clang-format off 5723 const char* kErrorSources[] = { 5724 "await;", 5725 "await: ;", 5726 "var await;", 5727 "var [await] = [];", 5728 "var { await } = {};", 5729 "var { x: await } = {};", 5730 "{ var await; }", 5731 "let await;", 5732 "let [await] = [];", 5733 "let { await } = {};", 5734 "let { x: await } = {};", 5735 "{ let await; }", 5736 "const await = null;", 5737 "const [await] = [];", 5738 "const { await } = {};", 5739 "const { x: await } = {};", 5740 "{ const await = null; }", 5741 "function await() {}", 5742 "function f(await) {}", 5743 "function* await() {}", 5744 "function* g(await) {}", 5745 "(function await() {});", 5746 "(function (await) {});", 5747 "(function* await() {});", 5748 "(function* (await) {});", 5749 "(await) => {};", 5750 "await => {};", 5751 "class await {}", 5752 "class C { constructor(await) {} }", 5753 "class C { m(await) {} }", 5754 "class C { static m(await) {} }", 5755 "class C { *m(await) {} }", 5756 "class C { static *m(await) {} }", 5757 "(class await {})", 5758 "(class { constructor(await) {} });", 5759 "(class { m(await) {} });", 5760 "(class { static m(await) {} });", 5761 "(class { *m(await) {} });", 5762 "(class { static *m(await) {} });", 5763 "({ m(await) {} });", 5764 "({ *m(await) {} });", 5765 "({ set p(await) {} });", 5766 "try {} catch (await) {}", 5767 "try {} catch (await) {} finally {}", 5768 NULL 5769 }; 5770 // clang-format on 5771 const char* context_data[][2] = {{"", ""}, {NULL, NULL}}; 5772 5773 RunModuleParserSyncTest(context_data, kErrorSources, kError); 5774 } 5775 5776 TEST(ModuleAwaitReservedPreParse) { 5777 const char* context_data[][2] = {{"", ""}, {NULL, NULL}}; 5778 const char* error_data[] = {"function f() { var await = 0; }", NULL}; 5779 5780 RunModuleParserSyncTest(context_data, error_data, kError); 5781 } 5782 5783 TEST(ModuleAwaitPermitted) { 5784 // clang-format off 5785 const char* kValidSources[] = { 5786 "({}).await;", 5787 "({ await: null });", 5788 "({ await() {} });", 5789 "({ get await() {} });", 5790 "({ set await(x) {} });", 5791 "(class { await() {} });", 5792 "(class { static await() {} });", 5793 "(class { *await() {} });", 5794 "(class { static *await() {} });", 5795 NULL 5796 }; 5797 // clang-format on 5798 const char* context_data[][2] = {{"", ""}, {NULL, NULL}}; 5799 5800 RunModuleParserSyncTest(context_data, kValidSources, kSuccess); 5801 } 5802 5803 TEST(EnumReserved) { 5804 // clang-format off 5805 const char* kErrorSources[] = { 5806 "enum;", 5807 "enum: ;", 5808 "var enum;", 5809 "var [enum] = [];", 5810 "var { enum } = {};", 5811 "var { x: enum } = {};", 5812 "{ var enum; }", 5813 "let enum;", 5814 "let [enum] = [];", 5815 "let { enum } = {};", 5816 "let { x: enum } = {};", 5817 "{ let enum; }", 5818 "const enum = null;", 5819 "const [enum] = [];", 5820 "const { enum } = {};", 5821 "const { x: enum } = {};", 5822 "{ const enum = null; }", 5823 "function enum() {}", 5824 "function f(enum) {}", 5825 "function* enum() {}", 5826 "function* g(enum) {}", 5827 "(function enum() {});", 5828 "(function (enum) {});", 5829 "(function* enum() {});", 5830 "(function* (enum) {});", 5831 "(enum) => {};", 5832 "enum => {};", 5833 "class enum {}", 5834 "class C { constructor(enum) {} }", 5835 "class C { m(enum) {} }", 5836 "class C { static m(enum) {} }", 5837 "class C { *m(enum) {} }", 5838 "class C { static *m(enum) {} }", 5839 "(class enum {})", 5840 "(class { constructor(enum) {} });", 5841 "(class { m(enum) {} });", 5842 "(class { static m(enum) {} });", 5843 "(class { *m(enum) {} });", 5844 "(class { static *m(enum) {} });", 5845 "({ m(enum) {} });", 5846 "({ *m(enum) {} });", 5847 "({ set p(enum) {} });", 5848 "try {} catch (enum) {}", 5849 "try {} catch (enum) {} finally {}", 5850 NULL 5851 }; 5852 // clang-format on 5853 const char* context_data[][2] = {{"", ""}, {NULL, NULL}}; 5854 5855 RunModuleParserSyncTest(context_data, kErrorSources, kError); 5856 } 5857 5858 TEST(ModuleParsingInternals) { 5859 i::Isolate* isolate = CcTest::i_isolate(); 5860 i::Factory* factory = isolate->factory(); 5861 v8::HandleScope handles(CcTest::isolate()); 5862 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 5863 v8::Context::Scope context_scope(context); 5864 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 5865 128 * 1024); 5866 5867 static const char kSource[] = 5868 "let x = 5;" 5869 "export { x as y };" 5870 "import { q as z } from 'm.js';" 5871 "import n from 'n.js';" 5872 "export { a as b } from 'm.js';" 5873 "export * from 'p.js';" 5874 "import 'q.js'"; 5875 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource); 5876 i::Handle<i::Script> script = factory->NewScript(source); 5877 i::Zone zone(CcTest::i_isolate()->allocator()); 5878 i::ParseInfo info(&zone, script); 5879 i::Parser parser(&info); 5880 info.set_module(); 5881 CHECK(parser.Parse(&info)); 5882 CHECK(i::Compiler::Analyze(&info)); 5883 i::FunctionLiteral* func = info.literal(); 5884 i::Scope* module_scope = func->scope(); 5885 i::Scope* outer_scope = module_scope->outer_scope(); 5886 CHECK(outer_scope->is_script_scope()); 5887 CHECK_NULL(outer_scope->outer_scope()); 5888 CHECK(module_scope->is_module_scope()); 5889 i::ModuleDescriptor* descriptor = module_scope->module(); 5890 CHECK_NOT_NULL(descriptor); 5891 CHECK_EQ(1, descriptor->Length()); 5892 const i::AstRawString* export_name = 5893 info.ast_value_factory()->GetOneByteString("y"); 5894 const i::AstRawString* local_name = 5895 descriptor->LookupLocalExport(export_name, &zone); 5896 CHECK_NOT_NULL(local_name); 5897 CHECK(local_name->IsOneByteEqualTo("x")); 5898 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations(); 5899 CHECK_EQ(3, declarations->length()); 5900 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x")); 5901 i::ImportDeclaration* import_decl = 5902 declarations->at(1)->AsImportDeclaration(); 5903 CHECK(import_decl->import_name()->IsOneByteEqualTo("q")); 5904 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z")); 5905 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js")); 5906 import_decl = declarations->at(2)->AsImportDeclaration(); 5907 CHECK(import_decl->import_name()->IsOneByteEqualTo("default")); 5908 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n")); 5909 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js")); 5910 // TODO(adamk): Add test for indirect exports once they're fully implemented. 5911 // TODO(adamk): Add test for star exports once they're fully implemented. 5912 const i::ZoneList<const i::AstRawString*>& requested_modules = 5913 descriptor->requested_modules(); 5914 CHECK_EQ(4, requested_modules.length()); 5915 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js")); 5916 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js")); 5917 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js")); 5918 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js")); 5919 } 5920 5921 5922 TEST(DuplicateProtoError) { 5923 const char* context_data[][2] = { 5924 {"({", "});"}, 5925 {"'use strict'; ({", "});"}, 5926 {NULL, NULL} 5927 }; 5928 const char* error_data[] = { 5929 "__proto__: {}, __proto__: {}", 5930 "__proto__: {}, \"__proto__\": {}", 5931 "__proto__: {}, \"__\x70roto__\": {}", 5932 "__proto__: {}, a: 1, __proto__: {}", 5933 NULL 5934 }; 5935 5936 RunParserSyncTest(context_data, error_data, kError); 5937 } 5938 5939 5940 TEST(DuplicateProtoNoError) { 5941 const char* context_data[][2] = { 5942 {"({", "});"}, 5943 {"'use strict'; ({", "});"}, 5944 {NULL, NULL} 5945 }; 5946 const char* error_data[] = { 5947 "__proto__: {}, ['__proto__']: {}", 5948 "__proto__: {}, __proto__() {}", 5949 "__proto__: {}, get __proto__() {}", 5950 "__proto__: {}, set __proto__(v) {}", 5951 "__proto__: {}, __proto__", 5952 NULL 5953 }; 5954 5955 RunParserSyncTest(context_data, error_data, kSuccess); 5956 } 5957 5958 5959 TEST(DeclarationsError) { 5960 const char* context_data[][2] = {{"'use strict'; if (true)", ""}, 5961 {"'use strict'; if (false) {} else", ""}, 5962 {"'use strict'; while (false)", ""}, 5963 {"'use strict'; for (;;)", ""}, 5964 {"'use strict'; for (x in y)", ""}, 5965 {"'use strict'; do ", " while (false)"}, 5966 {NULL, NULL}}; 5967 5968 const char* statement_data[] = { 5969 "let x = 1;", 5970 "const x = 1;", 5971 "class C {}", 5972 NULL}; 5973 5974 RunParserSyncTest(context_data, statement_data, kError); 5975 } 5976 5977 5978 void TestLanguageMode(const char* source, 5979 i::LanguageMode expected_language_mode) { 5980 i::Isolate* isolate = CcTest::i_isolate(); 5981 i::Factory* factory = isolate->factory(); 5982 v8::HandleScope handles(CcTest::isolate()); 5983 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 5984 v8::Context::Scope context_scope(context); 5985 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() - 5986 128 * 1024); 5987 5988 i::Handle<i::Script> script = 5989 factory->NewScript(factory->NewStringFromAsciiChecked(source)); 5990 i::Zone zone(CcTest::i_isolate()->allocator()); 5991 i::ParseInfo info(&zone, script); 5992 i::Parser parser(&info); 5993 info.set_global(); 5994 parser.Parse(&info); 5995 CHECK(info.literal() != NULL); 5996 CHECK_EQ(expected_language_mode, info.literal()->language_mode()); 5997 } 5998 5999 6000 TEST(LanguageModeDirectives) { 6001 TestLanguageMode("\"use nothing\"", i::SLOPPY); 6002 TestLanguageMode("\"use strict\"", i::STRICT); 6003 6004 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY); 6005 6006 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT); 6007 } 6008 6009 6010 TEST(PropertyNameEvalArguments) { 6011 const char* context_data[][2] = {{"'use strict';", ""}, 6012 {NULL, NULL}}; 6013 6014 const char* statement_data[] = { 6015 "({eval: 1})", 6016 "({arguments: 1})", 6017 "({eval() {}})", 6018 "({arguments() {}})", 6019 "({*eval() {}})", 6020 "({*arguments() {}})", 6021 "({get eval() {}})", 6022 "({get arguments() {}})", 6023 "({set eval(_) {}})", 6024 "({set arguments(_) {}})", 6025 6026 "class C {eval() {}}", 6027 "class C {arguments() {}}", 6028 "class C {*eval() {}}", 6029 "class C {*arguments() {}}", 6030 "class C {get eval() {}}", 6031 "class C {get arguments() {}}", 6032 "class C {set eval(_) {}}", 6033 "class C {set arguments(_) {}}", 6034 6035 "class C {static eval() {}}", 6036 "class C {static arguments() {}}", 6037 "class C {static *eval() {}}", 6038 "class C {static *arguments() {}}", 6039 "class C {static get eval() {}}", 6040 "class C {static get arguments() {}}", 6041 "class C {static set eval(_) {}}", 6042 "class C {static set arguments(_) {}}", 6043 6044 NULL}; 6045 6046 RunParserSyncTest(context_data, statement_data, kSuccess); 6047 } 6048 6049 6050 TEST(FunctionLiteralDuplicateParameters) { 6051 const char* strict_context_data[][2] = 6052 {{"'use strict';(function(", "){})();"}, 6053 {"(function(", ") { 'use strict'; })();"}, 6054 {"'use strict'; function fn(", ") {}; fn();"}, 6055 {"function fn(", ") { 'use strict'; }; fn();"}, 6056 {NULL, NULL}}; 6057 6058 const char* sloppy_context_data[][2] = 6059 {{"(function(", "){})();"}, 6060 {"(function(", ") {})();"}, 6061 {"function fn(", ") {}; fn();"}, 6062 {"function fn(", ") {}; fn();"}, 6063 {NULL, NULL}}; 6064 6065 const char* data[] = { 6066 "a, a", 6067 "a, a, a", 6068 "b, a, a", 6069 "a, b, c, c", 6070 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w", 6071 NULL}; 6072 6073 RunParserSyncTest(strict_context_data, data, kError); 6074 RunParserSyncTest(sloppy_context_data, data, kSuccess); 6075 } 6076 6077 6078 TEST(ArrowFunctionASIErrors) { 6079 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""}, 6080 {NULL, NULL}}; 6081 6082 const char* data[] = { 6083 "(a\n=> a)(1)", 6084 "(a/*\n*/=> a)(1)", 6085 "((a)\n=> a)(1)", 6086 "((a)/*\n*/=> a)(1)", 6087 "((a, b)\n=> a + b)(1, 2)", 6088 "((a, b)/*\n*/=> a + b)(1, 2)", 6089 NULL}; 6090 RunParserSyncTest(context_data, data, kError); 6091 } 6092 6093 6094 TEST(DestructuringPositiveTests) { 6095 const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, 6096 {"var ", " = {};"}, 6097 {"'use strict'; const ", " = {};"}, 6098 {"function f(", ") {}"}, 6099 {"function f(argument1, ", ") {}"}, 6100 {"var f = (", ") => {};"}, 6101 {"var f = (argument1,", ") => {};"}, 6102 {"try {} catch(", ") {}"}, 6103 {NULL, NULL}}; 6104 6105 // clang-format off 6106 const char* data[] = { 6107 "a", 6108 "{ x : y }", 6109 "{ x : y = 1 }", 6110 "{ get, set }", 6111 "{ get = 1, set = 2 }", 6112 "[a]", 6113 "[a = 1]", 6114 "[a,b,c]", 6115 "[a, b = 42, c]", 6116 "{ x : x, y : y }", 6117 "{ x : x = 1, y : y }", 6118 "{ x : x, y : y = 42 }", 6119 "[]", 6120 "{}", 6121 "[{x:x, y:y}, [a,b,c]]", 6122 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]", 6123 "{x}", 6124 "{x, y}", 6125 "{x = 42, y = 15}", 6126 "[a,,b]", 6127 "{42 : x}", 6128 "{42 : x = 42}", 6129 "{42e-2 : x}", 6130 "{42e-2 : x = 42}", 6131 "{x : y, x : z}", 6132 "{'hi' : x}", 6133 "{'hi' : x = 42}", 6134 "{var: x}", 6135 "{var: x = 42}", 6136 "{[x] : z}", 6137 "{[1+1] : z}", 6138 "{[foo()] : z}", 6139 "{}", 6140 "[...rest]", 6141 "[a,b,...rest]", 6142 "[a,,...rest]", 6143 NULL}; 6144 // clang-format on 6145 RunParserSyncTest(context_data, data, kSuccess); 6146 } 6147 6148 6149 TEST(DestructuringNegativeTests) { 6150 { // All modes. 6151 const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, 6152 {"var ", " = {};"}, 6153 {"'use strict'; const ", " = {};"}, 6154 {"function f(", ") {}"}, 6155 {"function f(argument1, ", ") {}"}, 6156 {"var f = (", ") => {};"}, 6157 {"var f = ", " => {};"}, 6158 {"var f = (argument1,", ") => {};"}, 6159 {"try {} catch(", ") {}"}, 6160 {NULL, NULL}}; 6161 6162 // clang-format off 6163 const char* data[] = { 6164 "a++", 6165 "++a", 6166 "delete a", 6167 "void a", 6168 "typeof a", 6169 "--a", 6170 "+a", 6171 "-a", 6172 "~a", 6173 "!a", 6174 "{ x : y++ }", 6175 "[a++]", 6176 "(x => y)", 6177 "a[i]", "a()", 6178 "a.b", 6179 "new a", 6180 "a + a", 6181 "a - a", 6182 "a * a", 6183 "a / a", 6184 "a == a", 6185 "a != a", 6186 "a > a", 6187 "a < a", 6188 "a <<< a", 6189 "a >>> a", 6190 "function a() {}", 6191 "a`bcd`", 6192 "this", 6193 "null", 6194 "true", 6195 "false", 6196 "1", 6197 "'abc'", 6198 "/abc/", 6199 "`abc`", 6200 "class {}", 6201 "{+2 : x}", 6202 "{-2 : x}", 6203 "var", 6204 "[var]", 6205 "{x : {y : var}}", 6206 "{x : x = a+}", 6207 "{x : x = (a+)}", 6208 "{x : x += a}", 6209 "{m() {} = 0}", 6210 "{[1+1]}", 6211 "[...rest, x]", 6212 "[a,b,...rest, x]", 6213 "[a,,...rest, x]", 6214 "[...rest,]", 6215 "[a,b,...rest,]", 6216 "[a,,...rest,]", 6217 "[...rest,...rest1]", 6218 "[a,b,...rest,...rest1]", 6219 "[a,,..rest,...rest1]", 6220 "[x, y, ...z = 1]", 6221 "[...z = 1]", 6222 "[x, y, ...[z] = [1]]", 6223 "[...[z] = [1]]", 6224 "{ x : 3 }", 6225 "{ x : 'foo' }", 6226 "{ x : /foo/ }", 6227 "{ x : `foo` }", 6228 "{ get a() {} }", 6229 "{ set a() {} }", 6230 "{ method() {} }", 6231 "{ *method() {} }", 6232 NULL}; 6233 // clang-format on 6234 RunParserSyncTest(context_data, data, kError); 6235 } 6236 6237 { // All modes. 6238 const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, 6239 {"var ", " = {};"}, 6240 {"'use strict'; const ", " = {};"}, 6241 {"function f(", ") {}"}, 6242 {"function f(argument1, ", ") {}"}, 6243 {"var f = (", ") => {};"}, 6244 {"var f = (argument1,", ") => {};"}, 6245 {NULL, NULL}}; 6246 6247 // clang-format off 6248 const char* data[] = { 6249 "x => x", 6250 "() => x", 6251 NULL}; 6252 // clang-format on 6253 RunParserSyncTest(context_data, data, kError); 6254 } 6255 6256 { // Strict mode. 6257 const char* context_data[][2] = { 6258 {"'use strict'; let ", " = {};"}, 6259 {"'use strict'; const ", " = {};"}, 6260 {"'use strict'; function f(", ") {}"}, 6261 {"'use strict'; function f(argument1, ", ") {}"}, 6262 {NULL, NULL}}; 6263 6264 // clang-format off 6265 const char* data[] = { 6266 "[eval]", 6267 "{ a : arguments }", 6268 "[public]", 6269 "{ x : private }", 6270 NULL}; 6271 // clang-format on 6272 RunParserSyncTest(context_data, data, kError); 6273 } 6274 6275 { // 'yield' in generators. 6276 const char* context_data[][2] = { 6277 {"function*() { var ", " = {};"}, 6278 {"function*() { 'use strict'; let ", " = {};"}, 6279 {"function*() { 'use strict'; const ", " = {};"}, 6280 {NULL, NULL}}; 6281 6282 // clang-format off 6283 const char* data[] = { 6284 "yield", 6285 "[yield]", 6286 "{ x : yield }", 6287 NULL}; 6288 // clang-format on 6289 RunParserSyncTest(context_data, data, kError); 6290 } 6291 6292 { // Declaration-specific errors 6293 const char* context_data[][2] = {{"'use strict'; var ", ""}, 6294 {"'use strict'; let ", ""}, 6295 {"'use strict'; const ", ""}, 6296 {"'use strict'; for (var ", ";;) {}"}, 6297 {"'use strict'; for (let ", ";;) {}"}, 6298 {"'use strict'; for (const ", ";;) {}"}, 6299 {"var ", ""}, 6300 {"let ", ""}, 6301 {"const ", ""}, 6302 {"for (var ", ";;) {}"}, 6303 {"for (let ", ";;) {}"}, 6304 {"for (const ", ";;) {}"}, 6305 {NULL, NULL}}; 6306 6307 // clang-format off 6308 const char* data[] = { 6309 "{ a }", 6310 "[ a ]", 6311 NULL}; 6312 // clang-format on 6313 RunParserSyncTest(context_data, data, kError); 6314 } 6315 } 6316 6317 6318 TEST(DestructuringAssignmentPositiveTests) { 6319 const char* context_data[][2] = { 6320 {"'use strict'; let x, y, z; (", " = {});"}, 6321 {"var x, y, z; (", " = {});"}, 6322 {"'use strict'; let x, y, z; for (x in ", " = {});"}, 6323 {"'use strict'; let x, y, z; for (x of ", " = {});"}, 6324 {"var x, y, z; for (x in ", " = {});"}, 6325 {"var x, y, z; for (x of ", " = {});"}, 6326 {"var x, y, z; for (", " in {});"}, 6327 {"var x, y, z; for (", " of {});"}, 6328 {"'use strict'; var x, y, z; for (", " in {});"}, 6329 {"'use strict'; var x, y, z; for (", " of {});"}, 6330 {NULL, NULL}}; 6331 6332 const char* mixed_assignments_context_data[][2] = { 6333 {"'use strict'; let x, y, z; (", " = z = {});"}, 6334 {"var x, y, z; (", " = z = {});"}, 6335 {"'use strict'; let x, y, z; (x = ", " = z = {});"}, 6336 {"var x, y, z; (x = ", " = z = {});"}, 6337 {"'use strict'; let x, y, z; for (x in ", " = z = {});"}, 6338 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"}, 6339 {"'use strict'; let x, y, z; for (x of ", " = z = {});"}, 6340 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"}, 6341 {"var x, y, z; for (x in ", " = z = {});"}, 6342 {"var x, y, z; for (x in x = ", " = z = {});"}, 6343 {"var x, y, z; for (x of ", " = z = {});"}, 6344 {"var x, y, z; for (x of x = ", " = z = {});"}, 6345 {NULL, NULL}}; 6346 6347 // clang-format off 6348 const char* data[] = { 6349 "x", 6350 6351 "{ x : y }", 6352 "{ x : foo().y }", 6353 "{ x : foo()[y] }", 6354 "{ x : y.z }", 6355 "{ x : y[z] }", 6356 "{ x : { y } }", 6357 "{ x : { foo: y } }", 6358 "{ x : { foo: foo().y } }", 6359 "{ x : { foo: foo()[y] } }", 6360 "{ x : { foo: y.z } }", 6361 "{ x : { foo: y[z] } }", 6362 "{ x : [ y ] }", 6363 "{ x : [ foo().y ] }", 6364 "{ x : [ foo()[y] ] }", 6365 "{ x : [ y.z ] }", 6366 "{ x : [ y[z] ] }", 6367 6368 "{ x : y = 10 }", 6369 "{ x : foo().y = 10 }", 6370 "{ x : foo()[y] = 10 }", 6371 "{ x : y.z = 10 }", 6372 "{ x : y[z] = 10 }", 6373 "{ x : { y = 10 } = {} }", 6374 "{ x : { foo: y = 10 } = {} }", 6375 "{ x : { foo: foo().y = 10 } = {} }", 6376 "{ x : { foo: foo()[y] = 10 } = {} }", 6377 "{ x : { foo: y.z = 10 } = {} }", 6378 "{ x : { foo: y[z] = 10 } = {} }", 6379 "{ x : [ y = 10 ] = {} }", 6380 "{ x : [ foo().y = 10 ] = {} }", 6381 "{ x : [ foo()[y] = 10 ] = {} }", 6382 "{ x : [ y.z = 10 ] = {} }", 6383 "{ x : [ y[z] = 10 ] = {} }", 6384 6385 "[ x ]", 6386 "[ foo().x ]", 6387 "[ foo()[x] ]", 6388 "[ x.y ]", 6389 "[ x[y] ]", 6390 "[ { x } ]", 6391 "[ { x : y } ]", 6392 "[ { x : foo().y } ]", 6393 "[ { x : foo()[y] } ]", 6394 "[ { x : x.y } ]", 6395 "[ { x : x[y] } ]", 6396 "[ [ x ] ]", 6397 "[ [ foo().x ] ]", 6398 "[ [ foo()[x] ] ]", 6399 "[ [ x.y ] ]", 6400 "[ [ x[y] ] ]", 6401 6402 "[ x = 10 ]", 6403 "[ foo().x = 10 ]", 6404 "[ foo()[x] = 10 ]", 6405 "[ x.y = 10 ]", 6406 "[ x[y] = 10 ]", 6407 "[ { x = 10 } = {} ]", 6408 "[ { x : y = 10 } = {} ]", 6409 "[ { x : foo().y = 10 } = {} ]", 6410 "[ { x : foo()[y] = 10 } = {} ]", 6411 "[ { x : x.y = 10 } = {} ]", 6412 "[ { x : x[y] = 10 } = {} ]", 6413 "[ [ x = 10 ] = {} ]", 6414 "[ [ foo().x = 10 ] = {} ]", 6415 "[ [ foo()[x] = 10 ] = {} ]", 6416 "[ [ x.y = 10 ] = {} ]", 6417 "[ [ x[y] = 10 ] = {} ]", 6418 "{ x : y = 1 }", 6419 "{ x }", 6420 "{ x, y, z }", 6421 "{ x = 1, y: z, z: y }", 6422 "{x = 42, y = 15}", 6423 "[x]", 6424 "[x = 1]", 6425 "[x,y,z]", 6426 "[x, y = 42, z]", 6427 "{ x : x, y : y }", 6428 "{ x : x = 1, y : y }", 6429 "{ x : x, y : y = 42 }", 6430 "[]", 6431 "{}", 6432 "[{x:x, y:y}, [,x,z,]]", 6433 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]", 6434 "[x,,y]", 6435 "[(x),,(y)]", 6436 "[(x)]", 6437 "{42 : x}", 6438 "{42 : x = 42}", 6439 "{42e-2 : x}", 6440 "{42e-2 : x = 42}", 6441 "{'hi' : x}", 6442 "{'hi' : x = 42}", 6443 "{var: x}", 6444 "{var: x = 42}", 6445 "{var: (x) = 42}", 6446 "{[x] : z}", 6447 "{[1+1] : z}", 6448 "{[1+1] : (z)}", 6449 "{[foo()] : z}", 6450 "{[foo()] : (z)}", 6451 "{[foo()] : foo().bar}", 6452 "{[foo()] : foo()['bar']}", 6453 "{[foo()] : this.bar}", 6454 "{[foo()] : this['bar']}", 6455 "{[foo()] : 'foo'.bar}", 6456 "{[foo()] : 'foo'['bar']}", 6457 "[...x]", 6458 "[x,y,...z]", 6459 "[x,,...z]", 6460 "{ x: y }", 6461 "[x, y]", 6462 "[((x, y) => z).x]", 6463 "{x: ((y, z) => z).x}", 6464 "[((x, y) => z)['x']]", 6465 "{x: ((y, z) => z)['x']}", 6466 6467 "{x: { y = 10 } }", 6468 "[(({ x } = { x: 1 }) => x).a]", 6469 6470 // v8:4662 6471 "{ x: (y) }", 6472 "{ x: (y) = [] }", 6473 "{ x: (foo.bar) }", 6474 "{ x: (foo['bar']) }", 6475 "[ ...(a) ]", 6476 "[ ...(foo['bar']) ]", 6477 "[ ...(foo.bar) ]", 6478 "[ (y) ]", 6479 "[ (foo.bar) ]", 6480 "[ (foo['bar']) ]", 6481 6482 NULL}; 6483 // clang-format on 6484 RunParserSyncTest(context_data, data, kSuccess); 6485 6486 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess); 6487 6488 const char* empty_context_data[][2] = { 6489 {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; 6490 6491 // CoverInitializedName ambiguity handling in various contexts 6492 const char* ambiguity_data[] = { 6493 "var foo = { x = 10 } = {};", 6494 "var foo = { q } = { x = 10 } = {};", 6495 "var foo; foo = { x = 10 } = {};", 6496 "var foo; foo = { q } = { x = 10 } = {};", 6497 "var x; ({ x = 10 } = {});", 6498 "var q, x; ({ q } = { x = 10 } = {});", 6499 "var x; [{ x = 10 } = {}]", 6500 "var x; (true ? { x = true } = {} : { x = false } = {})", 6501 "var q, x; (q, { x = 10 } = {});", 6502 "var { x = 10 } = { x = 20 } = {};", 6503 "var { x = 10 } = (o = { x = 20 } = {});", 6504 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})", 6505 NULL, 6506 }; 6507 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess); 6508 } 6509 6510 6511 TEST(DestructuringAssignmentNegativeTests) { 6512 const char* context_data[][2] = { 6513 {"'use strict'; let x, y, z; (", " = {});"}, 6514 {"var x, y, z; (", " = {});"}, 6515 {"'use strict'; let x, y, z; for (x in ", " = {});"}, 6516 {"'use strict'; let x, y, z; for (x of ", " = {});"}, 6517 {"var x, y, z; for (x in ", " = {});"}, 6518 {"var x, y, z; for (x of ", " = {});"}, 6519 {NULL, NULL}}; 6520 6521 // clang-format off 6522 const char* data[] = { 6523 "{ x : ++y }", 6524 "{ x : y * 2 }", 6525 "{ ...x }", 6526 "{ get x() {} }", 6527 "{ set x() {} }", 6528 "{ x: y() }", 6529 "{ this }", 6530 "{ x: this }", 6531 "{ x: this = 1 }", 6532 "{ super }", 6533 "{ x: super }", 6534 "{ x: super = 1 }", 6535 "{ new.target }", 6536 "{ x: new.target }", 6537 "{ x: new.target = 1 }", 6538 "[x--]", 6539 "[--x = 1]", 6540 "[x()]", 6541 "[this]", 6542 "[this = 1]", 6543 "[new.target]", 6544 "[new.target = 1]", 6545 "[super]", 6546 "[super = 1]", 6547 "[function f() {}]", 6548 "[50]", 6549 "[(50)]", 6550 "[(function() {})]", 6551 "[(foo())]", 6552 "{ x: 50 }", 6553 "{ x: (50) }", 6554 "['str']", 6555 "{ x: 'str' }", 6556 "{ x: ('str') }", 6557 "{ x: (foo()) }", 6558 "{ x: (function() {}) }", 6559 "{ x: y } = 'str'", 6560 "[x, y] = 'str'", 6561 "[(x,y) => z]", 6562 "{x: (y) => z}", 6563 "[x, ...y, z]", 6564 "[...x,]", 6565 "[x, y, ...z = 1]", 6566 "[...z = 1]", 6567 "[x, y, ...[z] = [1]]", 6568 "[...[z] = [1]]", 6569 6570 // v8:4657 6571 "({ x: x4, x: (x+=1e4) })", 6572 "(({ x: x4, x: (x+=1e4) }))", 6573 "({ x: x4, x: (x+=1e4) } = {})", 6574 "(({ x: x4, x: (x+=1e4) } = {}))", 6575 "(({ x: x4, x: (x+=1e4) }) = {})", 6576 "({ x: y } = {})", 6577 "(({ x: y } = {}))", 6578 "(({ x: y }) = {})", 6579 "([a])", 6580 "(([a]))", 6581 "([a] = [])", 6582 "(([a] = []))", 6583 "(([a]) = [])", 6584 6585 // v8:4662 6586 "{ x: ([y]) }", 6587 "{ x: ([y] = []) }", 6588 "{ x: ({y}) }", 6589 "{ x: ({y} = {}) }", 6590 "{ x: (++y) }", 6591 "[ (...[a]) ]", 6592 "[ ...([a]) ]", 6593 "[ ...([a] = [])", 6594 "[ ...[ ( [ a ] ) ] ]", 6595 "[ ([a]) ]", 6596 "[ (...[a]) ]", 6597 "[ ([a] = []) ]", 6598 "[ (++y) ]", 6599 "[ ...(++y) ]", 6600 6601 "[ x += x ]", 6602 "{ foo: x += x }", 6603 6604 NULL}; 6605 // clang-format on 6606 RunParserSyncTest(context_data, data, kError); 6607 6608 const char* empty_context_data[][2] = { 6609 {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; 6610 6611 // CoverInitializedName ambiguity handling in various contexts 6612 const char* ambiguity_data[] = { 6613 "var foo = { x = 10 };", 6614 "var foo = { q } = { x = 10 };", 6615 "var foo; foo = { x = 10 };", 6616 "var foo; foo = { q } = { x = 10 };", 6617 "var x; ({ x = 10 });", 6618 "var q, x; ({ q } = { x = 10 });", 6619 "var x; [{ x = 10 }]", 6620 "var x; (true ? { x = true } : { x = false })", 6621 "var q, x; (q, { x = 10 });", 6622 "var { x = 10 } = { x = 20 };", 6623 "var { x = 10 } = (o = { x = 20 });", 6624 "var x; (({ x = 10 } = { x = 20 }) => x)({})", 6625 6626 // Not ambiguous, but uses same context data 6627 "switch([window %= []] = []) { default: }", 6628 6629 NULL, 6630 }; 6631 RunParserSyncTest(empty_context_data, ambiguity_data, kError); 6632 6633 // Strict mode errors 6634 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"}, 6635 {"'use strict'; for (", " of {}) {}"}, 6636 {"'use strict'; for (", " in {}) {}"}, 6637 {NULL, NULL}}; 6638 const char* strict_data[] = {"{ eval }", 6639 "{ arguments }", 6640 "{ foo: eval }", 6641 "{ foo: arguments }", 6642 "{ eval = 0 }", 6643 "{ arguments = 0 }", 6644 "{ foo: eval = 0 }", 6645 "{ foo: arguments = 0 }", 6646 "[ eval ]", 6647 "[ arguments ]", 6648 "[ eval = 0 ]", 6649 "[ arguments = 0 ]", 6650 6651 // v8:4662 6652 "{ x: (eval) }", 6653 "{ x: (arguments) }", 6654 "{ x: (eval = 0) }", 6655 "{ x: (arguments = 0) }", 6656 "{ x: (eval) = 0 }", 6657 "{ x: (arguments) = 0 }", 6658 "[ (eval) ]", 6659 "[ (arguments) ]", 6660 "[ (eval = 0) ]", 6661 "[ (arguments = 0) ]", 6662 "[ (eval) = 0 ]", 6663 "[ (arguments) = 0 ]", 6664 "[ ...(eval) ]", 6665 "[ ...(arguments) ]", 6666 "[ ...(eval = 0) ]", 6667 "[ ...(arguments = 0) ]", 6668 "[ ...(eval) = 0 ]", 6669 "[ ...(arguments) = 0 ]", 6670 6671 NULL}; 6672 RunParserSyncTest(strict_context_data, strict_data, kError); 6673 } 6674 6675 6676 TEST(DestructuringDisallowPatternsInForVarIn) { 6677 const char* context_data[][2] = { 6678 {"", ""}, {"function f() {", "}"}, {NULL, NULL}}; 6679 // clang-format off 6680 const char* error_data[] = { 6681 "for (let x = {} in null);", 6682 "for (let x = {} of null);", 6683 NULL}; 6684 // clang-format on 6685 RunParserSyncTest(context_data, error_data, kError); 6686 6687 // clang-format off 6688 const char* success_data[] = { 6689 "for (var x = {} in null);", 6690 NULL}; 6691 // clang-format on 6692 RunParserSyncTest(context_data, success_data, kSuccess); 6693 } 6694 6695 6696 TEST(DestructuringDuplicateParams) { 6697 const char* context_data[][2] = {{"'use strict';", ""}, 6698 {"function outer() { 'use strict';", "}"}, 6699 {nullptr, nullptr}}; 6700 6701 6702 // clang-format off 6703 const char* error_data[] = { 6704 "function f(x,x){}", 6705 "function f(x, {x : x}){}", 6706 "function f(x, {x}){}", 6707 "function f({x,x}) {}", 6708 "function f([x,x]) {}", 6709 "function f(x, [y,{z:x}]) {}", 6710 "function f([x,{y:x}]) {}", 6711 // non-simple parameter list causes duplicates to be errors in sloppy mode. 6712 "function f(x, x, {a}) {}", 6713 nullptr}; 6714 // clang-format on 6715 RunParserSyncTest(context_data, error_data, kError); 6716 } 6717 6718 6719 TEST(DestructuringDuplicateParamsSloppy) { 6720 const char* context_data[][2] = { 6721 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}}; 6722 6723 6724 // clang-format off 6725 const char* error_data[] = { 6726 // non-simple parameter list causes duplicates to be errors in sloppy mode. 6727 "function f(x, {x : x}){}", 6728 "function f(x, {x}){}", 6729 "function f({x,x}) {}", 6730 "function f(x, x, {a}) {}", 6731 nullptr}; 6732 // clang-format on 6733 RunParserSyncTest(context_data, error_data, kError); 6734 } 6735 6736 6737 TEST(DestructuringDisallowPatternsInSingleParamArrows) { 6738 const char* context_data[][2] = {{"'use strict';", ""}, 6739 {"function outer() { 'use strict';", "}"}, 6740 {"", ""}, 6741 {"function outer() { ", "}"}, 6742 {nullptr, nullptr}}; 6743 6744 // clang-format off 6745 const char* error_data[] = { 6746 "var f = {x} => {};", 6747 "var f = {x,y} => {};", 6748 nullptr}; 6749 // clang-format on 6750 RunParserSyncTest(context_data, error_data, kError); 6751 } 6752 6753 6754 TEST(DefaultParametersYieldInInitializers) { 6755 // clang-format off 6756 const char* sloppy_function_context_data[][2] = { 6757 {"(function f(", ") { });"}, 6758 {NULL, NULL} 6759 }; 6760 6761 const char* strict_function_context_data[][2] = { 6762 {"'use strict'; (function f(", ") { });"}, 6763 {NULL, NULL} 6764 }; 6765 6766 const char* sloppy_arrow_context_data[][2] = { 6767 {"((", ")=>{});"}, 6768 {NULL, NULL} 6769 }; 6770 6771 const char* strict_arrow_context_data[][2] = { 6772 {"'use strict'; ((", ")=>{});"}, 6773 {NULL, NULL} 6774 }; 6775 6776 const char* generator_context_data[][2] = { 6777 {"'use strict'; (function *g(", ") { });"}, 6778 {"(function *g(", ") { });"}, 6779 // Arrow function within generator has the same rules. 6780 {"'use strict'; (function *g() { (", ") => {} });"}, 6781 {"(function *g() { (", ") => {} });"}, 6782 // And similarly for arrow functions in the parameter list. 6783 {"'use strict'; (function *g(z = (", ") => {}) { });"}, 6784 {"(function *g(z = (", ") => {}) { });"}, 6785 {NULL, NULL} 6786 }; 6787 6788 const char* parameter_data[] = { 6789 "x=yield", 6790 "x, y=yield", 6791 "{x=yield}", 6792 "[x=yield]", 6793 6794 "x=(yield)", 6795 "x, y=(yield)", 6796 "{x=(yield)}", 6797 "[x=(yield)]", 6798 6799 "x=f(yield)", 6800 "x, y=f(yield)", 6801 "{x=f(yield)}", 6802 "[x=f(yield)]", 6803 6804 "{x}=yield", 6805 "[x]=yield", 6806 6807 "{x}=(yield)", 6808 "[x]=(yield)", 6809 6810 "{x}=f(yield)", 6811 "[x]=f(yield)", 6812 NULL 6813 }; 6814 6815 // Because classes are always in strict mode, these are always errors. 6816 const char* always_error_param_data[] = { 6817 "x = class extends (yield) { }", 6818 "x = class extends f(yield) { }", 6819 "x = class extends (null, yield) { }", 6820 "x = class extends (a ? null : yield) { }", 6821 "[x] = [class extends (a ? null : yield) { }]", 6822 "[x = class extends (a ? null : yield) { }]", 6823 "[x = class extends (a ? null : yield) { }] = [null]", 6824 "x = class { [yield]() { } }", 6825 "x = class { static [yield]() { } }", 6826 "x = class { [(yield, 1)]() { } }", 6827 "x = class { [y = (yield, 1)]() { } }", 6828 NULL 6829 }; 6830 // clang-format on 6831 6832 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess); 6833 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess); 6834 6835 RunParserSyncTest(strict_function_context_data, parameter_data, kError); 6836 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError); 6837 6838 RunParserSyncTest(generator_context_data, parameter_data, kError); 6839 RunParserSyncTest(generator_context_data, always_error_param_data, kError); 6840 } 6841 6842 TEST(SpreadArray) { 6843 const char* context_data[][2] = { 6844 {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; 6845 6846 // clang-format off 6847 const char* data[] = { 6848 "[...a]", 6849 "[a, ...b]", 6850 "[...a,]", 6851 "[...a, ,]", 6852 "[, ...a]", 6853 "[...a, ...b]", 6854 "[...a, , ...b]", 6855 "[...[...a]]", 6856 "[, ...a]", 6857 "[, , ...a]", 6858 NULL}; 6859 // clang-format on 6860 RunParserSyncTest(context_data, data, kSuccess); 6861 } 6862 6863 6864 TEST(SpreadArrayError) { 6865 const char* context_data[][2] = { 6866 {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; 6867 6868 // clang-format off 6869 const char* data[] = { 6870 "[...]", 6871 "[a, ...]", 6872 "[..., ]", 6873 "[..., ...]", 6874 "[ (...a)]", 6875 NULL}; 6876 // clang-format on 6877 RunParserSyncTest(context_data, data, kError); 6878 } 6879 6880 6881 TEST(NewTarget) { 6882 // clang-format off 6883 const char* good_context_data[][2] = { 6884 {"function f() {", "}"}, 6885 {"'use strict'; function f() {", "}"}, 6886 {"var f = function() {", "}"}, 6887 {"'use strict'; var f = function() {", "}"}, 6888 {"({m: function() {", "}})"}, 6889 {"'use strict'; ({m: function() {", "}})"}, 6890 {"({m() {", "}})"}, 6891 {"'use strict'; ({m() {", "}})"}, 6892 {"({get x() {", "}})"}, 6893 {"'use strict'; ({get x() {", "}})"}, 6894 {"({set x(_) {", "}})"}, 6895 {"'use strict'; ({set x(_) {", "}})"}, 6896 {"class C {m() {", "}}"}, 6897 {"class C {get x() {", "}}"}, 6898 {"class C {set x(_) {", "}}"}, 6899 {NULL} 6900 }; 6901 6902 const char* bad_context_data[][2] = { 6903 {"", ""}, 6904 {"'use strict';", ""}, 6905 {NULL} 6906 }; 6907 6908 const char* data[] = { 6909 "new.target", 6910 "{ new.target }", 6911 "() => { new.target }", 6912 "() => new.target", 6913 "if (1) { new.target }", 6914 "if (1) {} else { new.target }", 6915 "while (0) { new.target }", 6916 "do { new.target } while (0)", 6917 NULL 6918 }; 6919 6920 // clang-format on 6921 6922 RunParserSyncTest(good_context_data, data, kSuccess); 6923 RunParserSyncTest(bad_context_data, data, kError); 6924 } 6925 6926 6927 TEST(ConstSloppy) { 6928 // clang-format off 6929 const char* context_data[][2] = { 6930 {"", ""}, 6931 {"{", "}"}, 6932 {NULL, NULL} 6933 }; 6934 6935 const char* data[] = { 6936 "const x = 1", 6937 "for (const x = 1; x < 1; x++) {}", 6938 "for (const x in {}) {}", 6939 "for (const x of []) {}", 6940 NULL 6941 }; 6942 // clang-format on 6943 RunParserSyncTest(context_data, data, kSuccess); 6944 } 6945 6946 6947 TEST(LetSloppy) { 6948 // clang-format off 6949 const char* context_data[][2] = { 6950 {"", ""}, 6951 {"'use strict';", ""}, 6952 {"{", "}"}, 6953 {NULL, NULL} 6954 }; 6955 6956 const char* data[] = { 6957 "let x", 6958 "let x = 1", 6959 "for (let x = 1; x < 1; x++) {}", 6960 "for (let x in {}) {}", 6961 "for (let x of []) {}", 6962 NULL 6963 }; 6964 // clang-format on 6965 6966 RunParserSyncTest(context_data, data, kSuccess); 6967 } 6968 6969 6970 TEST(LanguageModeDirectivesNonSimpleParameterListErrors) { 6971 // TC39 deemed "use strict" directives to be an error when occurring in the 6972 // body of a function with non-simple parameter list, on 29/7/2015. 6973 // https://goo.gl/ueA7Ln 6974 const char* context_data[][2] = { 6975 {"function f(", ") { 'use strict'; }"}, 6976 {"function* g(", ") { 'use strict'; }"}, 6977 {"class c { foo(", ") { 'use strict' }"}, 6978 {"var a = (", ") => { 'use strict'; }"}, 6979 {"var o = { m(", ") { 'use strict'; }"}, 6980 {"var o = { *gm(", ") { 'use strict'; }"}, 6981 {"var c = { m(", ") { 'use strict'; }"}, 6982 {"var c = { *gm(", ") { 'use strict'; }"}, 6983 6984 {"'use strict'; function f(", ") { 'use strict'; }"}, 6985 {"'use strict'; function* g(", ") { 'use strict'; }"}, 6986 {"'use strict'; class c { foo(", ") { 'use strict' }"}, 6987 {"'use strict'; var a = (", ") => { 'use strict'; }"}, 6988 {"'use strict'; var o = { m(", ") { 'use strict'; }"}, 6989 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"}, 6990 {"'use strict'; var c = { m(", ") { 'use strict'; }"}, 6991 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"}, 6992 6993 {NULL, NULL}}; 6994 6995 const char* data[] = { 6996 // TODO(@caitp): support formal parameter initializers 6997 "{}", 6998 "[]", 6999 "[{}]", 7000 "{a}", 7001 "a, {b}", 7002 "a, b, {c, d, e}", 7003 "initializer = true", 7004 "a, b, c = 1", 7005 "...args", 7006 "a, b, ...rest", 7007 "[a, b, ...rest]", 7008 "{ bindingPattern = {} }", 7009 "{ initializedBindingPattern } = { initializedBindingPattern: true }", 7010 NULL}; 7011 7012 RunParserSyncTest(context_data, data, kError); 7013 } 7014 7015 7016 TEST(LetSloppyOnly) { 7017 // clang-format off 7018 const char* context_data[][2] = { 7019 {"", ""}, 7020 {"{", "}"}, 7021 {"(function() {", "})()"}, 7022 {NULL, NULL} 7023 }; 7024 7025 const char* data[] = { 7026 "let", 7027 "let = 1", 7028 "for (let = 1; let < 1; let++) {}", 7029 "for (let in {}) {}", 7030 "for (var let = 1; let < 1; let++) {}", 7031 "for (var let in {}) {}", 7032 "for (var [let] = 1; let < 1; let++) {}", 7033 "for (var [let] in {}) {}", 7034 "var let", 7035 "var [let] = []", 7036 NULL 7037 }; 7038 // clang-format on 7039 7040 RunParserSyncTest(context_data, data, kSuccess); 7041 7042 // Some things should be rejected even in sloppy mode 7043 // This addresses BUG(v8:4403). 7044 7045 // clang-format off 7046 const char* fail_data[] = { 7047 "let let = 1", 7048 "for (let let = 1; let < 1; let++) {}", 7049 "for (let let in {}) {}", 7050 "for (let let of []) {}", 7051 "const let = 1", 7052 "for (const let = 1; let < 1; let++) {}", 7053 "for (const let in {}) {}", 7054 "for (const let of []) {}", 7055 "let [let] = 1", 7056 "for (let [let] = 1; let < 1; let++) {}", 7057 "for (let [let] in {}) {}", 7058 "for (let [let] of []) {}", 7059 "const [let] = 1", 7060 "for (const [let] = 1; let < 1; let++) {}", 7061 "for (const [let] in {}) {}", 7062 "for (const [let] of []) {}", 7063 7064 // Sprinkle in the escaped version too. 7065 "let l\\u0065t = 1", 7066 "const l\\u0065t = 1", 7067 "let [l\\u0065t] = 1", 7068 "const [l\\u0065t] = 1", 7069 "for (let l\\u0065t in {}) {}", 7070 NULL 7071 }; 7072 // clang-format on 7073 7074 RunParserSyncTest(context_data, fail_data, kError); 7075 } 7076 7077 7078 TEST(EscapedKeywords) { 7079 // clang-format off 7080 const char* sloppy_context_data[][2] = { 7081 {"", ""}, 7082 {NULL, NULL} 7083 }; 7084 7085 const char* strict_context_data[][2] = { 7086 {"'use strict';", ""}, 7087 {NULL, NULL} 7088 }; 7089 7090 const char* fail_data[] = { 7091 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }", 7092 "cl\\u0061ss Foo {}", 7093 "var x = cl\\u0061ss {}", 7094 "\\u0063onst foo = 1;", 7095 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }", 7096 "d\\u0065bugger;", 7097 "d\\u0065lete this.a;", 7098 "\\u0063o { } while(0)", 7099 "if (d\\u006f { true }) {}", 7100 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }", 7101 "e\\u0078port var foo;", 7102 "try { } catch (e) {} f\\u0069nally { }", 7103 "f\\u006fr (var i = 0; i < 10; ++i);", 7104 "f\\u0075nction fn() {}", 7105 "var f = f\\u0075nction() {}", 7106 "\\u0069f (true) { }", 7107 "\\u0069mport blah from './foo.js';", 7108 "n\\u0065w function f() {}", 7109 "(function() { r\\u0065turn; })()", 7110 "class C extends function() {} { constructor() { sup\\u0065r() } }", 7111 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }", 7112 "sw\\u0069tch (this.a) {}", 7113 "var x = th\\u0069s;", 7114 "th\\u0069s.a = 1;", 7115 "thr\\u006fw 'boo';", 7116 "t\\u0072y { true } catch (e) {}", 7117 "var x = typ\\u0065of 'blah'", 7118 "v\\u0061r a = true", 7119 "var v\\u0061r = true", 7120 "(function() { return v\\u006fid 0; })()", 7121 "wh\\u0069le (true) { }", 7122 "w\\u0069th (this.scope) { }", 7123 "(function*() { y\\u0069eld 1; })()", 7124 "(function*() { var y\\u0069eld = 1; })()", 7125 7126 "var \\u0065num = 1;", 7127 "var { \\u0065num } = {}", 7128 "(\\u0065num = 1);", 7129 7130 // Null / Boolean literals 7131 "(x === n\\u0075ll);", 7132 "var x = n\\u0075ll;", 7133 "var n\\u0075ll = 1;", 7134 "var { n\\u0075ll } = { 1 };", 7135 "n\\u0075ll = 1;", 7136 "(x === tr\\u0075e);", 7137 "var x = tr\\u0075e;", 7138 "var tr\\u0075e = 1;", 7139 "var { tr\\u0075e } = {};", 7140 "tr\\u0075e = 1;", 7141 "(x === f\\u0061lse);", 7142 "var x = f\\u0061lse;", 7143 "var f\\u0061lse = 1;", 7144 "var { f\\u0061lse } = {};", 7145 "f\\u0061lse = 1;", 7146 7147 // TODO(caitp): consistent error messages for labeled statements and 7148 // expressions 7149 "switch (this.a) { c\\u0061se 6: break; }", 7150 "try { } c\\u0061tch (e) {}", 7151 "switch (this.a) { d\\u0065fault: break; }", 7152 "class C \\u0065xtends function B() {} {}", 7153 "for (var a i\\u006e this) {}", 7154 "if ('foo' \\u0069n this) {}", 7155 "if (this \\u0069nstanceof Array) {}", 7156 "(n\\u0065w function f() {})", 7157 "(typ\\u0065of 123)", 7158 "(v\\u006fid 0)", 7159 "do { ; } wh\\u0069le (true) { }", 7160 "(function*() { return (n++, y\\u0069eld 1); })()", 7161 "class C { st\\u0061tic bar() {} }", 7162 "class C { st\\u0061tic *bar() {} }", 7163 "class C { st\\u0061tic get bar() {} }", 7164 "class C { st\\u0061tic set bar() {} }", 7165 7166 // TODO(adamk): These should not be errors in sloppy mode. 7167 "(y\\u0069eld);", 7168 "var y\\u0069eld = 1;", 7169 "var { y\\u0069eld } = {};", 7170 NULL 7171 }; 7172 // clang-format on 7173 7174 RunParserSyncTest(sloppy_context_data, fail_data, kError); 7175 RunParserSyncTest(strict_context_data, fail_data, kError); 7176 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError); 7177 7178 // clang-format off 7179 const char* let_data[] = { 7180 "var l\\u0065t = 1;", 7181 "l\\u0065t = 1;", 7182 "(l\\u0065t === 1);", 7183 NULL 7184 }; 7185 // clang-format on 7186 7187 RunParserSyncTest(sloppy_context_data, let_data, kSuccess); 7188 RunParserSyncTest(strict_context_data, let_data, kError); 7189 7190 // Non-errors in sloppy mode 7191 const char* valid_data[] = {"(\\u0069mplements = 1);", 7192 "var impl\\u0065ments = 1;", 7193 "var { impl\\u0065ments } = {};", 7194 "(\\u0069nterface = 1);", 7195 "var int\\u0065rface = 1;", 7196 "var { int\\u0065rface } = {};", 7197 "(p\\u0061ckage = 1);", 7198 "var packa\\u0067e = 1;", 7199 "var { packa\\u0067e } = {};", 7200 "(p\\u0072ivate = 1);", 7201 "var p\\u0072ivate;", 7202 "var { p\\u0072ivate } = {};", 7203 "(prot\\u0065cted);", 7204 "var prot\\u0065cted = 1;", 7205 "var { prot\\u0065cted } = {};", 7206 "(publ\\u0069c);", 7207 "var publ\\u0069c = 1;", 7208 "var { publ\\u0069c } = {};", 7209 "(st\\u0061tic);", 7210 "var st\\u0061tic = 1;", 7211 "var { st\\u0061tic } = {};", 7212 NULL}; 7213 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess); 7214 RunParserSyncTest(strict_context_data, valid_data, kError); 7215 RunModuleParserSyncTest(strict_context_data, valid_data, kError); 7216 } 7217 7218 7219 TEST(MiscSyntaxErrors) { 7220 // clang-format off 7221 const char* context_data[][2] = { 7222 { "'use strict'", "" }, 7223 { "", "" }, 7224 { NULL, NULL } 7225 }; 7226 const char* error_data[] = { 7227 "for (();;) {}", 7228 7229 // crbug.com/582626 7230 "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf", 7231 NULL 7232 }; 7233 // clang-format on 7234 7235 RunParserSyncTest(context_data, error_data, kError); 7236 } 7237 7238 7239 TEST(EscapeSequenceErrors) { 7240 // clang-format off 7241 const char* context_data[][2] = { 7242 { "'", "'" }, 7243 { "\"", "\"" }, 7244 { "`", "`" }, 7245 { "`${'", "'}`" }, 7246 { "`${\"", "\"}`" }, 7247 { "`${`", "`}`" }, 7248 { "f(tag`", "`);" }, 7249 { NULL, NULL } 7250 }; 7251 const char* error_data[] = { 7252 "\\uABCG", 7253 "\\u{ZZ}", 7254 "\\u{FFZ}", 7255 "\\u{FFFFFFFFFF }", 7256 "\\u{110000}", 7257 "\\u{110000", 7258 "\\u{FFFD }", 7259 "\\xZF", 7260 NULL 7261 }; 7262 // clang-format on 7263 7264 RunParserSyncTest(context_data, error_data, kError); 7265 } 7266 7267 7268 TEST(FunctionSentErrors) { 7269 // clang-format off 7270 const char* context_data[][2] = { 7271 { "'use strict'", "" }, 7272 { "", "" }, 7273 { NULL, NULL } 7274 }; 7275 const char* error_data[] = { 7276 "var x = function.sent", 7277 "function* g() { yield function.s\\u0065nt; }", 7278 NULL 7279 }; 7280 // clang-format on 7281 7282 static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent}; 7283 RunParserSyncTest(context_data, error_data, kError, always_flags, 7284 arraysize(always_flags)); 7285 } 7286 7287 TEST(NewTargetErrors) { 7288 // clang-format off 7289 const char* context_data[][2] = { 7290 { "'use strict'", "" }, 7291 { "", "" }, 7292 { NULL, NULL } 7293 }; 7294 const char* error_data[] = { 7295 "var x = new.target", 7296 "function f() { return new.t\\u0061rget; }", 7297 NULL 7298 }; 7299 // clang-format on 7300 RunParserSyncTest(context_data, error_data, kError); 7301 } 7302 7303 TEST(FunctionDeclarationError) { 7304 // clang-format off 7305 const char* strict_context[][2] = { 7306 { "'use strict';", "" }, 7307 { "'use strict'; { ", "}" }, 7308 {"(function() { 'use strict';", "})()"}, 7309 {"(function() { 'use strict'; {", "} })()"}, 7310 { NULL, NULL } 7311 }; 7312 const char* sloppy_context[][2] = { 7313 { "", "" }, 7314 { "{", "}" }, 7315 {"(function() {", "})()"}, 7316 {"(function() { {", "} })()"}, 7317 { NULL, NULL } 7318 }; 7319 // Invalid in all contexts 7320 const char* error_data[] = { 7321 "try function foo() {} catch (e) {}", 7322 NULL 7323 }; 7324 // Valid in sloppy mode only, and only when the 7325 // --harmony-restrictive-declarations flag is off 7326 const char* unrestricted_data[] = { 7327 "do function foo() {} while (0);", 7328 "for (;false;) function foo() {}", 7329 "for (var i = 0; i < 1; i++) function f() { };", 7330 "for (var x in {a: 1}) function f() { };", 7331 "for (var x in {}) function f() { };", 7332 "for (var x in {}) function foo() {}", 7333 "for (x in {a: 1}) function f() { };", 7334 "for (x in {}) function f() { };", 7335 "var x; for (x in {}) function foo() {}", 7336 "with ({}) function f() { };", 7337 "do label: function foo() {} while (0);", 7338 "for (;false;) label: function foo() {}", 7339 "for (var i = 0; i < 1; i++) label: function f() { };", 7340 "for (var x in {a: 1}) label: function f() { };", 7341 "for (var x in {}) label: function f() { };", 7342 "for (var x in {}) label: function foo() {}", 7343 "for (x in {a: 1}) label: function f() { };", 7344 "for (x in {}) label: function f() { };", 7345 "var x; for (x in {}) label: function foo() {}", 7346 "with ({}) label: function f() { };", 7347 "if (true) label: function f() {}", 7348 "if (true) {} else label: function f() {}", 7349 "if (true) function* f() { }", 7350 "label: function* f() { }", 7351 // TODO(littledan, v8:4806): Ban duplicate generator declarations in 7352 // a block, maybe by tracking whether a Variable is a generator declaration 7353 // "{ function* f() {} function* f() {} }", 7354 // "{ function f() {} function* f() {} }", 7355 // "{ function* f() {} function f() {} }", 7356 NULL 7357 }; 7358 // Valid only in sloppy mode, with or without 7359 // --harmony-restrictive-declarations 7360 const char* sloppy_data[] = { 7361 "if (true) function foo() {}", 7362 "if (false) {} else function f() { };", 7363 "label: function f() { }", 7364 "label: if (true) function f() { }", 7365 "label: if (true) {} else function f() { }", 7366 NULL 7367 }; 7368 // clang-format on 7369 7370 static const ParserFlag restrictive_flags[] = { 7371 kAllowHarmonyRestrictiveDeclarations}; 7372 7373 // Nothing parses in strict mode without a SyntaxError 7374 RunParserSyncTest(strict_context, error_data, kError); 7375 RunParserSyncTest(strict_context, error_data, kError, NULL, 0, 7376 restrictive_flags, arraysize(restrictive_flags)); 7377 RunParserSyncTest(strict_context, unrestricted_data, kError); 7378 RunParserSyncTest(strict_context, unrestricted_data, kError, NULL, 0, 7379 restrictive_flags, arraysize(restrictive_flags)); 7380 RunParserSyncTest(strict_context, sloppy_data, kError); 7381 RunParserSyncTest(strict_context, sloppy_data, kError, NULL, 0, 7382 restrictive_flags, arraysize(restrictive_flags)); 7383 7384 // In sloppy mode, some things are successful, depending on the flag 7385 RunParserSyncTest(sloppy_context, error_data, kError); 7386 RunParserSyncTest(sloppy_context, error_data, kError, NULL, 0, 7387 restrictive_flags, arraysize(restrictive_flags)); 7388 RunParserSyncTest(sloppy_context, unrestricted_data, kSuccess); 7389 RunParserSyncTest(sloppy_context, unrestricted_data, kError, NULL, 0, 7390 restrictive_flags, arraysize(restrictive_flags)); 7391 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess); 7392 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess, restrictive_flags, 7393 arraysize(restrictive_flags)); 7394 } 7395 7396 TEST(ExponentiationOperator) { 7397 // clang-format off 7398 const char* context_data[][2] = { 7399 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" }, 7400 { "var O = { p: 1 }, x = 10; ; (", ")" }, 7401 { "var O = { p: 1 }, x = 10; foo(", ")" }, 7402 { NULL, NULL } 7403 }; 7404 const char* data[] = { 7405 "(delete O.p) ** 10", 7406 "(delete x) ** 10", 7407 "(~O.p) ** 10", 7408 "(~x) ** 10", 7409 "(!O.p) ** 10", 7410 "(!x) ** 10", 7411 "(+O.p) ** 10", 7412 "(+x) ** 10", 7413 "(-O.p) ** 10", 7414 "(-x) ** 10", 7415 "(typeof O.p) ** 10", 7416 "(typeof x) ** 10", 7417 "(void 0) ** 10", 7418 "(void O.p) ** 10", 7419 "(void x) ** 10", 7420 "++O.p ** 10", 7421 "++x ** 10", 7422 "--O.p ** 10", 7423 "--x ** 10", 7424 "O.p++ ** 10", 7425 "x++ ** 10", 7426 "O.p-- ** 10", 7427 "x-- ** 10", 7428 NULL 7429 }; 7430 // clang-format on 7431 7432 static const ParserFlag always_flags[] = { 7433 kAllowHarmonyExponentiationOperator}; 7434 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, 7435 arraysize(always_flags)); 7436 } 7437 7438 TEST(ExponentiationOperatorErrors) { 7439 // clang-format off 7440 const char* context_data[][2] = { 7441 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" }, 7442 { "var O = { p: 1 }, x = 10; ; (", ")" }, 7443 { "var O = { p: 1 }, x = 10; foo(", ")" }, 7444 { NULL, NULL } 7445 }; 7446 const char* error_data[] = { 7447 "delete O.p ** 10", 7448 "delete x ** 10", 7449 "~O.p ** 10", 7450 "~x ** 10", 7451 "!O.p ** 10", 7452 "!x ** 10", 7453 "+O.p ** 10", 7454 "+x ** 10", 7455 "-O.p ** 10", 7456 "-x ** 10", 7457 "typeof O.p ** 10", 7458 "typeof x ** 10", 7459 "void ** 10", 7460 "void O.p ** 10", 7461 "void x ** 10", 7462 "++delete O.p ** 10", 7463 "--delete O.p ** 10", 7464 "++~O.p ** 10", 7465 "++~x ** 10", 7466 "--!O.p ** 10", 7467 "--!x ** 10", 7468 "++-O.p ** 10", 7469 "++-x ** 10", 7470 "--+O.p ** 10", 7471 "--+x ** 10", 7472 "[ x ] **= [ 2 ]", 7473 "[ x **= 2 ] = [ 2 ]", 7474 "{ x } **= { x: 2 }", 7475 "{ x: x **= 2 ] = { x: 2 }", 7476 // TODO(caitp): a Call expression as LHS should be an early ReferenceError! 7477 // "Array() **= 10", 7478 NULL 7479 }; 7480 // clang-format on 7481 7482 static const ParserFlag always_flags[] = { 7483 kAllowHarmonyExponentiationOperator}; 7484 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, 7485 arraysize(always_flags)); 7486 } 7487 7488 TEST(AsyncAwait) { 7489 // clang-format off 7490 const char* context_data[][2] = { 7491 { "'use strict';", "" }, 7492 { "", "" }, 7493 { NULL, NULL } 7494 }; 7495 7496 const char* data[] = { 7497 "var asyncFn = async function() { await 1; };", 7498 "var asyncFn = async function withName() { await 1; };", 7499 "var asyncFn = async () => await 'test';", 7500 "var asyncFn = async x => await x + 'test';", 7501 "async function asyncFn() { await 1; }", 7502 "var O = { async method() { await 1; } }", 7503 "var O = { async ['meth' + 'od']() { await 1; } }", 7504 "var O = { async 'method'() { await 1; } }", 7505 "var O = { async 0() { await 1; } }", 7506 "async function await() {}", 7507 7508 "var asyncFn = async({ foo = 1 }) => foo;", 7509 "var asyncFn = async({ foo = 1 } = {}) => foo;", 7510 NULL 7511 }; 7512 // clang-format on 7513 7514 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; 7515 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, 7516 arraysize(always_flags)); 7517 7518 // clang-format off 7519 const char* async_body_context_data[][2] = { 7520 { "async function f() {", "}" }, 7521 { "var f = async function() {", "}" }, 7522 { "var f = async() => {", "}" }, 7523 { "var O = { async method() {", "} }" }, 7524 { "'use strict'; async function f() {", "}" }, 7525 { "'use strict'; var f = async function() {", "}" }, 7526 { "'use strict'; var f = async() => {", "}" }, 7527 { "'use strict'; var O = { async method() {", "} }" }, 7528 { NULL, NULL } 7529 }; 7530 7531 const char* body_context_data[][2] = { 7532 { "function f() {", "}" }, 7533 { "function* g() {", "}" }, 7534 { "var f = function() {", "}" }, 7535 { "var g = function*() {", "}" }, 7536 { "var O = { method() {", "} }" }, 7537 { "var O = { *method() {", "} }" }, 7538 { "var f = () => {", "}" }, 7539 { "'use strict'; function f() {", "}" }, 7540 { "'use strict'; function* g() {", "}" }, 7541 { "'use strict'; var f = function() {", "}" }, 7542 { "'use strict'; var g = function*() {", "}" }, 7543 { "'use strict'; var O = { method() {", "} }" }, 7544 { "'use strict'; var O = { *method() {", "} }" }, 7545 { "'use strict'; var f = () => {", "}" }, 7546 { NULL, NULL } 7547 }; 7548 7549 const char* body_data[] = { 7550 "var async = 1; return async;", 7551 "let async = 1; return async;", 7552 "const async = 1; return async;", 7553 "function async() {} return async();", 7554 "var async = async => async; return async();", 7555 "function foo() { var await = 1; return await; }", 7556 "function foo(await) { return await; }", 7557 "function* foo() { var await = 1; return await; }", 7558 "function* foo(await) { return await; }", 7559 "var f = (await) => await;", 7560 "var f = () => { var await = 1; return await; }", 7561 "var O = { method() { var await = 1; return await; } };", 7562 "var O = { method(await) { return await; } };", 7563 "var O = { *method() { var await = 1; return await; } };", 7564 "var O = { *method(await) { return await; } };", 7565 7566 "(function await() {})", 7567 NULL 7568 }; 7569 // clang-format on 7570 7571 RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0, 7572 always_flags, arraysize(always_flags)); 7573 RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0, 7574 always_flags, arraysize(always_flags)); 7575 } 7576 7577 TEST(AsyncAwaitErrors) { 7578 // clang-format off 7579 const char* context_data[][2] = { 7580 { "'use strict';", "" }, 7581 { "", "" }, 7582 { NULL, NULL } 7583 }; 7584 7585 const char* strict_context_data[][2] = { 7586 { "'use strict';", "" }, 7587 { NULL, NULL } 7588 }; 7589 7590 const char* error_data[] = { 7591 "var asyncFn = async function() { var await = 1; };", 7592 "var asyncFn = async function() { var { await } = 1; };", 7593 "var asyncFn = async function() { var [ await ] = 1; };", 7594 "var asyncFn = async function await() {};", 7595 "var asyncFn = async () => var await = 'test';", 7596 "var asyncFn = async await => await + 'test';", 7597 "var asyncFn = async function(await) {};", 7598 "var asyncFn = async function() { return async (await) => {}; }", 7599 "var asyncFn = async (await) => 'test';", 7600 "var asyncFn = async x => { var await = 1; }", 7601 "var asyncFn = async x => { var { await } = 1; }", 7602 "var asyncFn = async x => { var [ await ] = 1; }", 7603 "async function f(await) {}", 7604 "async function f() { var await = 1; }", 7605 "async function f() { var { await } = 1; }", 7606 "async function f() { var [ await ] = 1; }", 7607 7608 "var O = { async method(a, a) {} }", 7609 "var O = { async ['meth' + 'od'](a, a) {} }", 7610 "var O = { async 'method'(a, a) {} }", 7611 "var O = { async 0(a, a) {} }", 7612 7613 "async function f() { var O = { async [await](a, a) {} } }", 7614 7615 "var asyncFn = async function() { await; }", 7616 "async function f() { await; }", 7617 "var O = { async method() { await; } };", 7618 "var f = async() => await;", 7619 "var f = async() => { await; };", 7620 7621 "var asyncFn = async function*() {}", 7622 "async function* f() {}", 7623 "var O = { *async method() {} };", 7624 "var O = { async *method() {} };", 7625 "var O = { async method*() {} };", 7626 7627 "var asyncFn = async function(x = await 1) { return x; }", 7628 "async function f(x = await 1) { return x; }", 7629 "var f = async(x = await 1) => x;", 7630 "var O = { async method(x = await 1) { return x; } };", 7631 7632 "var f = async(x = await) => 1;", 7633 7634 "class C { async constructor() {} }", 7635 "class C {}; class C2 extends C { async constructor() {} }", 7636 "class C { static async prototype() {} }", 7637 "class C {}; class C2 extends C { static async prototype() {} }", 7638 7639 "var f = async() => ((async(x = await 1) => x)();", 7640 7641 "var asyncFn = async function() { function await() {} }", 7642 "var asyncFn = async() => { function await() {} }", 7643 "var O = { async method() { function await() {} } }", 7644 "async function foo() { function await() {} }", 7645 7646 // Henrique Ferreiro's bug (tm) 7647 "(async function foo() { } foo => 1)", 7648 "(async function foo() { } () => 1)", 7649 "(async function foo() { } => 1)", 7650 "(async function() { } foo => 1)", 7651 "(async function() { } () => 1)", 7652 "(async function() { } => 1)", 7653 "(async.foo => 1)", 7654 "(async.foo foo => 1)", 7655 "(async.foo () => 1)", 7656 "(async().foo => 1)", 7657 "(async().foo foo => 1)", 7658 "(async().foo () => 1)", 7659 "(async['foo'] => 1)", 7660 "(async['foo'] foo => 1)", 7661 "(async['foo'] () => 1)", 7662 "(async()['foo'] => 1)", 7663 "(async()['foo'] foo => 1)", 7664 "(async()['foo'] () => 1)", 7665 "(async`foo` => 1)", 7666 "(async`foo` foo => 1)", 7667 "(async`foo` () => 1)", 7668 "(async`foo`.bar => 1)", 7669 "(async`foo`.bar foo => 1)", 7670 "(async`foo`.bar () => 1)", 7671 7672 // v8:5148 assert that errors are still thrown for calls that may have been 7673 // async functions 7674 "async({ foo = 1 })", 7675 NULL 7676 }; 7677 7678 const char* strict_error_data[] = { 7679 "var O = { async method(eval) {} }", 7680 "var O = { async ['meth' + 'od'](eval) {} }", 7681 "var O = { async 'method'(eval) {} }", 7682 "var O = { async 0(eval) {} }", 7683 7684 "var O = { async method(arguments) {} }", 7685 "var O = { async ['meth' + 'od'](arguments) {} }", 7686 "var O = { async 'method'(arguments) {} }", 7687 "var O = { async 0(arguments) {} }", 7688 7689 "var O = { async method(dupe, dupe) {} }", 7690 7691 // TODO(caitp): preparser needs to report duplicate parameter errors, too. 7692 // "var f = async(dupe, dupe) => {}", 7693 7694 NULL 7695 }; 7696 7697 const char* formal_parameters_data[] = { 7698 "var f = async({ await }) => 1;", 7699 "var f = async({ await = 1 }) => 1;", 7700 "var f = async({ await } = {}) => 1;", 7701 "var f = async({ await = 1 } = {}) => 1;", 7702 "var f = async([await]) => 1;", 7703 "var f = async([await] = []) => 1;", 7704 "var f = async([await = 1]) => 1;", 7705 "var f = async([await = 1] = []) => 1;", 7706 "var f = async(...await) => 1;", 7707 "var f = async(await) => 1;", 7708 "var f = async(await = 1) => 1;", 7709 "var f = async(...[await]) => 1;", 7710 NULL 7711 }; 7712 // clang-format on 7713 7714 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; 7715 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, 7716 arraysize(always_flags)); 7717 RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0, 7718 always_flags, arraysize(always_flags)); 7719 7720 RunParserSyncTest(context_data, formal_parameters_data, kError, NULL, 0, 7721 always_flags, arraysize(always_flags)); 7722 } 7723 7724 TEST(AsyncAwaitModule) { 7725 // clang-format off 7726 const char* context_data[][2] = { 7727 { "", "" }, 7728 { NULL, NULL } 7729 }; 7730 7731 const char* data[] = { 7732 "export default async function() { await 1; }", 7733 "export default async function async() { await 1; }", 7734 "export async function async() { await 1; }", 7735 NULL 7736 }; 7737 // clang-format on 7738 7739 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; 7740 RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, 7741 arraysize(always_flags), NULL, 0, false); 7742 } 7743 7744 TEST(AsyncAwaitModuleErrors) { 7745 // clang-format off 7746 const char* context_data[][2] = { 7747 { "", "" }, 7748 { NULL, NULL } 7749 }; 7750 7751 const char* error_data[] = { 7752 "export default (async function await() {})", 7753 "export default async function await() {}", 7754 "export async function await() {}", 7755 "export async function() {}", 7756 "export async", 7757 NULL 7758 }; 7759 // clang-format on 7760 7761 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; 7762 RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0, 7763 always_flags, arraysize(always_flags), NULL, 0, 7764 false); 7765 } 7766 7767 TEST(RestrictiveForInErrors) { 7768 // clang-format off 7769 const char* context_data[][2] = { 7770 { "'use strict'", "" }, 7771 { "", "" }, 7772 { NULL, NULL } 7773 }; 7774 const char* error_data[] = { 7775 "for (var x = 0 in {});", 7776 "for (const x = 0 in {});", 7777 "for (let x = 0 in {});", 7778 NULL 7779 }; 7780 // clang-format on 7781 7782 static const ParserFlag always_flags[] = {kAllowHarmonyForIn}; 7783 RunParserSyncTest(context_data, error_data, kError, nullptr, 0, always_flags, 7784 arraysize(always_flags)); 7785 } 7786 7787 TEST(NoDuplicateGeneratorsInBlock) { 7788 const char* block_context_data[][2] = { 7789 {"'use strict'; {", "}"}, 7790 {"{", "}"}, 7791 {"(function() { {", "} })()"}, 7792 {"(function() {'use strict'; {", "} })()"}, 7793 {NULL, NULL}}; 7794 const char* top_level_context_data[][2] = { 7795 {"'use strict';", ""}, 7796 {"", ""}, 7797 {"(function() {", "})()"}, 7798 {"(function() {'use strict';", "})()"}, 7799 {NULL, NULL}}; 7800 const char* error_data[] = {"function* x() {} function* x() {}", 7801 "function x() {} function* x() {}", 7802 "function* x() {} function x() {}", NULL}; 7803 static const ParserFlag always_flags[] = {kAllowHarmonyRestrictiveGenerators}; 7804 // The preparser doesn't enforce the restriction, so turn it off. 7805 bool test_preparser = false; 7806 RunParserSyncTest(block_context_data, error_data, kError, NULL, 0, 7807 always_flags, arraysize(always_flags), NULL, 0, false, 7808 test_preparser); 7809 RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0, 7810 always_flags, arraysize(always_flags)); 7811 } 7812 7813 TEST(NoDuplicateAsyncFunctionInBlock) { 7814 const char* block_context_data[][2] = { 7815 {"'use strict'; {", "}"}, 7816 {"{", "}"}, 7817 {"(function() { {", "} })()"}, 7818 {"(function() {'use strict'; {", "} })()"}, 7819 {NULL, NULL}}; 7820 const char* top_level_context_data[][2] = { 7821 {"'use strict';", ""}, 7822 {"", ""}, 7823 {"(function() {", "})()"}, 7824 {"(function() {'use strict';", "})()"}, 7825 {NULL, NULL}}; 7826 const char* error_data[] = {"async function x() {} async function x() {}", 7827 "function x() {} async function x() {}", 7828 "async function x() {} function x() {}", 7829 "function* x() {} async function x() {}", 7830 "function* x() {} async function x() {}", 7831 "async function x() {} function* x() {}", 7832 "function* x() {} async function x() {}", 7833 NULL}; 7834 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; 7835 // The preparser doesn't enforce the restriction, so turn it off. 7836 bool test_preparser = false; 7837 RunParserSyncTest(block_context_data, error_data, kError, NULL, 0, 7838 always_flags, arraysize(always_flags), NULL, 0, false, 7839 test_preparser); 7840 RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0, 7841 always_flags, arraysize(always_flags)); 7842 } 7843