| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 | 230 |
| 231 // Syntax error. | 231 // Syntax error. |
| 232 v8::ScriptData* error_preparse = v8::ScriptData::PreCompile( | 232 v8::ScriptData* error_preparse = v8::ScriptData::PreCompile( |
| 233 v8::String::NewFromUtf8(isolate, | 233 v8::String::NewFromUtf8(isolate, |
| 234 error_source, | 234 error_source, |
| 235 v8::String::kNormalString, | 235 v8::String::kNormalString, |
| 236 error_source_length)); | 236 error_source_length)); |
| 237 CHECK(error_preparse->HasError()); | 237 CHECK(error_preparse->HasError()); |
| 238 i::ScriptDataImpl *pre_impl = | 238 i::ScriptDataImpl *pre_impl = |
| 239 reinterpret_cast<i::ScriptDataImpl*>(error_preparse); | 239 reinterpret_cast<i::ScriptDataImpl*>(error_preparse); |
| 240 i::ScannerBase::Location error_location = | 240 i::Scanner::Location error_location = |
| 241 pre_impl->MessageLocation(); | 241 pre_impl->MessageLocation(); |
| 242 // Error is at "z" in source, location 10..11. | 242 // Error is at "z" in source, location 10..11. |
| 243 CHECK_EQ(10, error_location.beg_pos); | 243 CHECK_EQ(10, error_location.beg_pos); |
| 244 CHECK_EQ(11, error_location.end_pos); | 244 CHECK_EQ(11, error_location.end_pos); |
| 245 // Should not crash. | 245 // Should not crash. |
| 246 const char* message = pre_impl->BuildMessage(); | 246 const char* message = pre_impl->BuildMessage(); |
| 247 pre_impl->BuildArgs(); | 247 i::Vector<const char*> args = pre_impl->BuildArgs(); |
| 248 CHECK_GT(strlen(message), 0); | 248 CHECK_GT(strlen(message), 0); |
| 249 args.Dispose(); |
| 250 i::DeleteArray(message); |
| 251 delete error_preparse; |
| 249 } | 252 } |
| 250 | 253 |
| 251 | 254 |
| 252 TEST(StandAlonePreParser) { | 255 TEST(StandAlonePreParser) { |
| 253 v8::V8::Initialize(); | 256 v8::V8::Initialize(); |
| 254 | 257 |
| 255 int marker; | 258 int marker; |
| 256 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 259 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 257 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 260 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 258 | 261 |
| 259 const char* programs[] = { | 262 const char* programs[] = { |
| 260 "{label: 42}", | 263 "{label: 42}", |
| 261 "var x = 42;", | 264 "var x = 42;", |
| 262 "function foo(x, y) { return x + y; }", | 265 "function foo(x, y) { return x + y; }", |
| 263 "%ArgleBargle(glop);", | 266 "%ArgleBargle(glop);", |
| 264 "var x = new new Function('this.x = 42');", | 267 "var x = new new Function('this.x = 42');", |
| 265 NULL | 268 NULL |
| 266 }; | 269 }; |
| 267 | 270 |
| 268 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); | 271 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); |
| 269 for (int i = 0; programs[i]; i++) { | 272 for (int i = 0; programs[i]; i++) { |
| 270 i::HandleScope handle_scope(CcTest::i_isolate()); | 273 const char* program = programs[i]; |
| 271 i::Handle<i::String> source = | 274 i::Utf8ToUtf16CharacterStream stream( |
| 272 CcTest::i_isolate()->factory()->NewStringFromAscii( | 275 reinterpret_cast<const i::byte*>(program), |
| 273 i::Vector<const char>(programs[i], strlen(programs[i]))); | 276 static_cast<unsigned>(strlen(program))); |
| 274 i::CompleteParserRecorder log; | 277 i::CompleteParserRecorder log; |
| 275 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); | 278 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
| 276 scanner.Init(); | 279 scanner.Initialize(&stream); |
| 277 | 280 |
| 278 i::PreParser preparser(&scanner, &log, stack_limit); | 281 i::PreParser preparser(&scanner, &log, stack_limit); |
| 279 preparser.set_allow_lazy(true); | 282 preparser.set_allow_lazy(true); |
| 280 preparser.set_allow_natives_syntax(true); | 283 preparser.set_allow_natives_syntax(true); |
| 281 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 284 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 282 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 285 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 283 i::ScriptDataImpl data(log.ExtractData()); | 286 i::ScriptDataImpl data(log.ExtractData()); |
| 284 CHECK(!data.has_error()); | 287 CHECK(!data.has_error()); |
| 285 } | 288 } |
| 286 } | 289 } |
| 287 | 290 |
| 288 | 291 |
| 289 TEST(StandAlonePreParserNoNatives) { | 292 TEST(StandAlonePreParserNoNatives) { |
| 290 v8::V8::Initialize(); | 293 v8::V8::Initialize(); |
| 291 | 294 |
| 292 int marker; | 295 int marker; |
| 293 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 296 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 294 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 297 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 295 | 298 |
| 296 const char* programs[] = { | 299 const char* programs[] = { |
| 297 "%ArgleBargle(glop);", | 300 "%ArgleBargle(glop);", |
| 298 "var x = %_IsSmi(42);", | 301 "var x = %_IsSmi(42);", |
| 299 NULL | 302 NULL |
| 300 }; | 303 }; |
| 301 | 304 |
| 302 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); | 305 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); |
| 303 for (int i = 0; programs[i]; i++) { | 306 for (int i = 0; programs[i]; i++) { |
| 304 i::HandleScope handle_scope(CcTest::i_isolate()); | 307 const char* program = programs[i]; |
| 305 i::Handle<i::String> source = | 308 i::Utf8ToUtf16CharacterStream stream( |
| 306 CcTest::i_isolate()->factory()->NewStringFromAscii( | 309 reinterpret_cast<const i::byte*>(program), |
| 307 i::Vector<const char>(programs[i], strlen(programs[i]))); | 310 static_cast<unsigned>(strlen(program))); |
| 308 i::CompleteParserRecorder log; | 311 i::CompleteParserRecorder log; |
| 309 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); | 312 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
| 310 scanner.Init(); | 313 scanner.Initialize(&stream); |
| 314 |
| 311 // Preparser defaults to disallowing natives syntax. | 315 // Preparser defaults to disallowing natives syntax. |
| 312 i::PreParser preparser(&scanner, &log, stack_limit); | 316 i::PreParser preparser(&scanner, &log, stack_limit); |
| 313 preparser.set_allow_lazy(true); | 317 preparser.set_allow_lazy(true); |
| 314 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 318 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 315 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 319 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 316 i::ScriptDataImpl data(log.ExtractData()); | 320 i::ScriptDataImpl data(log.ExtractData()); |
| 317 // Data contains syntax error. | 321 // Data contains syntax error. |
| 318 CHECK(data.has_error()); | 322 CHECK(data.has_error()); |
| 319 } | 323 } |
| 320 } | 324 } |
| 321 | 325 |
| 322 | 326 |
| 327 TEST(PreparsingObjectLiterals) { |
| 328 // Regression test for a bug where the symbol stream produced by PreParser |
| 329 // didn't match what Parser wanted to consume. |
| 330 v8::Isolate* isolate = CcTest::isolate(); |
| 331 v8::HandleScope handles(isolate); |
| 332 v8::Local<v8::Context> context = v8::Context::New(isolate); |
| 333 v8::Context::Scope context_scope(context); |
| 334 int marker; |
| 335 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 336 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 337 |
| 338 { |
| 339 const char* source = "var myo = {if: \"foo\"}; myo.if;"; |
| 340 v8::Local<v8::Value> result = PreCompileCompileRun(source); |
| 341 CHECK(result->IsString()); |
| 342 v8::String::Utf8Value utf8(result); |
| 343 CHECK_EQ("foo", *utf8); |
| 344 } |
| 345 |
| 346 { |
| 347 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];"; |
| 348 v8::Local<v8::Value> result = PreCompileCompileRun(source); |
| 349 CHECK(result->IsString()); |
| 350 v8::String::Utf8Value utf8(result); |
| 351 CHECK_EQ("foo", *utf8); |
| 352 } |
| 353 |
| 354 { |
| 355 const char* source = "var myo = {1: \"foo\"}; myo[1];"; |
| 356 v8::Local<v8::Value> result = PreCompileCompileRun(source); |
| 357 CHECK(result->IsString()); |
| 358 v8::String::Utf8Value utf8(result); |
| 359 CHECK_EQ("foo", *utf8); |
| 360 } |
| 361 } |
| 362 |
| 363 namespace v8 { |
| 364 namespace internal { |
| 365 |
| 366 void FakeWritingSymbolIdInPreParseData(i::CompleteParserRecorder* log, |
| 367 int number) { |
| 368 log->WriteNumber(number); |
| 369 if (log->symbol_id_ < number + 1) { |
| 370 log->symbol_id_ = number + 1; |
| 371 } |
| 372 } |
| 373 |
| 374 } |
| 375 } |
| 376 |
| 377 |
| 378 TEST(StoringNumbersInPreParseData) { |
| 379 // Symbol IDs are split into chunks of 7 bits for storing. This is a |
| 380 // regression test for a bug where a symbol id was incorrectly stored if some |
| 381 // of the chunks in the middle were all zeros. |
| 382 i::CompleteParserRecorder log; |
| 383 for (int i = 0; i < 18; ++i) { |
| 384 FakeWritingSymbolIdInPreParseData(&log, 1 << i); |
| 385 } |
| 386 for (int i = 1; i < 18; ++i) { |
| 387 FakeWritingSymbolIdInPreParseData(&log, (1 << i) + 1); |
| 388 } |
| 389 for (int i = 6; i < 18; ++i) { |
| 390 FakeWritingSymbolIdInPreParseData(&log, (3 << i) + (5 << (i - 6))); |
| 391 } |
| 392 i::Vector<unsigned> store = log.ExtractData(); |
| 393 i::ScriptDataImpl script_data(store); |
| 394 script_data.Initialize(); |
| 395 // Check that we get the same symbols back. |
| 396 for (int i = 0; i < 18; ++i) { |
| 397 CHECK_EQ(1 << i, script_data.GetSymbolIdentifier()); |
| 398 } |
| 399 for (int i = 1; i < 18; ++i) { |
| 400 CHECK_EQ((1 << i) + 1, script_data.GetSymbolIdentifier()); |
| 401 } |
| 402 for (int i = 6; i < 18; ++i) { |
| 403 CHECK_EQ((3 << i) + (5 << (i - 6)), script_data.GetSymbolIdentifier()); |
| 404 } |
| 405 } |
| 406 |
| 407 |
| 323 TEST(RegressChromium62639) { | 408 TEST(RegressChromium62639) { |
| 324 v8::V8::Initialize(); | 409 v8::V8::Initialize(); |
| 325 i::Isolate* isolate = CcTest::i_isolate(); | 410 i::Isolate* isolate = CcTest::i_isolate(); |
| 326 | 411 |
| 327 int marker; | 412 int marker; |
| 328 isolate->stack_guard()->SetStackLimit( | 413 isolate->stack_guard()->SetStackLimit( |
| 329 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 414 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 330 | 415 |
| 331 const char* program = "var x = 'something';\n" | 416 const char* program = "var x = 'something';\n" |
| 332 "escape: function() {}"; | 417 "escape: function() {}"; |
| 333 // Fails parsing expecting an identifier after "function". | 418 // Fails parsing expecting an identifier after "function". |
| 334 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), | 419 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), |
| 335 // and then used the invalid currently scanned literal. This always | 420 // and then used the invalid currently scanned literal. This always |
| 336 // failed in debug mode, and sometimes crashed in release mode. | 421 // failed in debug mode, and sometimes crashed in release mode. |
| 337 | 422 |
| 338 v8::HandleScope handles(CcTest::isolate()); | 423 i::Utf8ToUtf16CharacterStream stream( |
| 339 i::Handle<i::String> source = isolate->factory()->NewStringFromAscii( | 424 reinterpret_cast<const i::byte*>(program), |
| 340 i::Vector<const char>(reinterpret_cast<const char*>(program), | 425 static_cast<unsigned>(strlen(program))); |
| 341 strlen(program))); | 426 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); |
| 342 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, source); | |
| 343 CHECK(data->HasError()); | 427 CHECK(data->HasError()); |
| 344 delete data; | 428 delete data; |
| 345 } | 429 } |
| 346 | 430 |
| 347 | 431 |
| 348 TEST(Regress928) { | 432 TEST(Regress928) { |
| 349 v8::V8::Initialize(); | 433 v8::V8::Initialize(); |
| 350 i::Isolate* isolate = CcTest::i_isolate(); | 434 i::Isolate* isolate = CcTest::i_isolate(); |
| 351 i::Factory* factory = isolate->factory(); | 435 i::Factory* factory = isolate->factory(); |
| 352 | 436 |
| 353 // Preparsing didn't consider the catch clause of a try statement | 437 // Preparsing didn't consider the catch clause of a try statement |
| 354 // as with-content, which made it assume that a function inside | 438 // as with-content, which made it assume that a function inside |
| 355 // the block could be lazily compiled, and an extra, unexpected, | 439 // the block could be lazily compiled, and an extra, unexpected, |
| 356 // entry was added to the data. | 440 // entry was added to the data. |
| 357 int marker; | 441 int marker; |
| 358 isolate->stack_guard()->SetStackLimit( | 442 isolate->stack_guard()->SetStackLimit( |
| 359 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 443 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 360 | 444 |
| 361 const char* program = | 445 const char* program = |
| 362 "try { } catch (e) { var foo = function () { /* first */ } }" | 446 "try { } catch (e) { var foo = function () { /* first */ } }" |
| 363 "var bar = function () { /* second */ }"; | 447 "var bar = function () { /* second */ }"; |
| 364 | 448 |
| 365 v8::HandleScope handles(CcTest::isolate()); | 449 v8::HandleScope handles(CcTest::isolate()); |
| 366 i::Handle<i::String> source( | 450 i::Handle<i::String> source( |
| 367 factory->NewStringFromAscii(i::CStrVector(program))); | 451 factory->NewStringFromAscii(i::CStrVector(program))); |
| 368 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, source); | 452 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
| 453 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); |
| 369 CHECK(!data->HasError()); | 454 CHECK(!data->HasError()); |
| 370 | 455 |
| 371 data->Initialize(); | 456 data->Initialize(); |
| 372 | 457 |
| 373 int first_function = | 458 int first_function = |
| 374 static_cast<int>(strstr(program, "function") - program); | 459 static_cast<int>(strstr(program, "function") - program); |
| 375 int first_lbrace = first_function + i::StrLength("function () "); | 460 int first_lbrace = first_function + i::StrLength("function () "); |
| 376 CHECK_EQ('{', program[first_lbrace]); | 461 CHECK_EQ('{', program[first_lbrace]); |
| 377 i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace); | 462 i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace); |
| 378 CHECK(!entry1.is_valid()); | 463 CHECK(!entry1.is_valid()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 396 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 481 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 397 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 482 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 398 | 483 |
| 399 size_t kProgramSize = 1024 * 1024; | 484 size_t kProgramSize = 1024 * 1024; |
| 400 i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1)); | 485 i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1)); |
| 401 memset(program.get(), '(', kProgramSize); | 486 memset(program.get(), '(', kProgramSize); |
| 402 program[kProgramSize] = '\0'; | 487 program[kProgramSize] = '\0'; |
| 403 | 488 |
| 404 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); | 489 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); |
| 405 | 490 |
| 406 i::HandleScope handle_scope(CcTest::i_isolate()); | 491 i::Utf8ToUtf16CharacterStream stream( |
| 407 i::Handle<i::String> source = | 492 reinterpret_cast<const i::byte*>(program.get()), |
| 408 CcTest::i_isolate()->factory()->NewStringFromAscii( | 493 static_cast<unsigned>(kProgramSize)); |
| 409 i::Vector<const char>(program.get(), kProgramSize)); | |
| 410 i::CompleteParserRecorder log; | 494 i::CompleteParserRecorder log; |
| 411 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); | 495 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
| 412 scanner.Init(); | 496 scanner.Initialize(&stream); |
| 413 | 497 |
| 414 i::PreParser preparser(&scanner, &log, stack_limit); | 498 i::PreParser preparser(&scanner, &log, stack_limit); |
| 415 preparser.set_allow_lazy(true); | 499 preparser.set_allow_lazy(true); |
| 416 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 500 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 417 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result); | 501 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result); |
| 418 } | 502 } |
| 419 | 503 |
| 420 | 504 |
| 421 class TestExternalResource: public v8::String::ExternalStringResource { | 505 class TestExternalResource: public v8::String::ExternalStringResource { |
| 422 public: | 506 public: |
| 423 explicit TestExternalResource(uint16_t* data, int length) | 507 explicit TestExternalResource(uint16_t* data, int length) |
| 424 : data_(data), length_(static_cast<size_t>(length)) { } | 508 : data_(data), length_(static_cast<size_t>(length)) { } |
| 425 | 509 |
| 426 ~TestExternalResource() { } | 510 ~TestExternalResource() { } |
| 427 | 511 |
| 428 const uint16_t* data() const { | 512 const uint16_t* data() const { |
| 429 return data_; | 513 return data_; |
| 430 } | 514 } |
| 431 | 515 |
| 432 size_t length() const { | 516 size_t length() const { |
| 433 return length_; | 517 return length_; |
| 434 } | 518 } |
| 435 private: | 519 private: |
| 436 uint16_t* data_; | 520 uint16_t* data_; |
| 437 size_t length_; | 521 size_t length_; |
| 438 }; | 522 }; |
| 439 | 523 |
| 440 | 524 |
| 525 #ifndef V8_USE_GENERATED_LEXER |
| 526 |
| 527 |
| 441 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2)) | 528 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2)) |
| 442 | 529 |
| 530 |
| 443 void TestCharacterStream(const char* ascii_source, | 531 void TestCharacterStream(const char* ascii_source, |
| 444 unsigned length, | 532 unsigned length, |
| 445 unsigned start = 0, | 533 unsigned start = 0, |
| 446 unsigned end = 0) { | 534 unsigned end = 0) { |
| 447 if (end == 0) end = length; | 535 if (end == 0) end = length; |
| 448 unsigned sub_length = end - start; | 536 unsigned sub_length = end - start; |
| 449 i::Isolate* isolate = CcTest::i_isolate(); | 537 i::Isolate* isolate = CcTest::i_isolate(); |
| 450 i::Factory* factory = isolate->factory(); | 538 i::Factory* factory = isolate->factory(); |
| 451 i::HandleScope test_scope(isolate); | 539 i::HandleScope test_scope(isolate); |
| 452 i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]); | 540 i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 } else { | 705 } else { |
| 618 CHECK_EQ(-1, c); | 706 CHECK_EQ(-1, c); |
| 619 } | 707 } |
| 620 i += 1; | 708 i += 1; |
| 621 CHECK_EQU(i, stream.pos()); | 709 CHECK_EQU(i, stream.pos()); |
| 622 } | 710 } |
| 623 } | 711 } |
| 624 | 712 |
| 625 #undef CHECK_EQU | 713 #undef CHECK_EQU |
| 626 | 714 |
| 715 |
| 716 #endif |
| 717 |
| 718 |
| 627 void TestStreamScanner(i::Utf16CharacterStream* stream, | 719 void TestStreamScanner(i::Utf16CharacterStream* stream, |
| 628 i::Token::Value* expected_tokens, | 720 i::Token::Value* expected_tokens, |
| 629 int skip_pos = 0, // Zero means not skipping. | 721 int skip_pos = 0, // Zero means not skipping. |
| 630 int skip_to = 0) { | 722 int skip_to = 0) { |
| 631 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); | 723 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
| 632 scanner.Initialize(stream); | 724 scanner.Initialize(stream); |
| 633 | 725 |
| 634 int i = 0; | 726 int i = 0; |
| 635 do { | 727 do { |
| 636 i::Token::Value expected = expected_tokens[i]; | 728 i::Token::Value expected = expected_tokens[i]; |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 | 1104 |
| 1013 for (int i = 0; source_data[i].outer_prefix; i++) { | 1105 for (int i = 0; source_data[i].outer_prefix; i++) { |
| 1014 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix); | 1106 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix); |
| 1015 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source); | 1107 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source); |
| 1016 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix); | 1108 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix); |
| 1017 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix); | 1109 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix); |
| 1018 int kInnerByteLen = i::StrLength(source_data[i].inner_source); | 1110 int kInnerByteLen = i::StrLength(source_data[i].inner_source); |
| 1019 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix); | 1111 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix); |
| 1020 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; | 1112 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; |
| 1021 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen; | 1113 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen; |
| 1022 i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1); | 1114 i::ScopedVector<char> program(kProgramByteSize + 1); |
| 1023 i::OS::SNPrintF(program, "%s%s%s", | 1115 i::OS::SNPrintF(program, "%s%s%s", |
| 1024 source_data[i].outer_prefix, | 1116 source_data[i].outer_prefix, |
| 1025 source_data[i].inner_source, | 1117 source_data[i].inner_source, |
| 1026 source_data[i].outer_suffix); | 1118 source_data[i].outer_suffix); |
| 1027 | 1119 |
| 1028 // Parse program source. | 1120 // Parse program source. |
| 1029 i::Handle<i::String> source( | 1121 i::Handle<i::String> source( |
| 1030 factory->NewStringFromUtf8(i::CStrVector(program.start()))); | 1122 factory->NewStringFromUtf8(i::CStrVector(program.start()))); |
| 1031 CHECK_EQ(source->length(), kProgramSize); | 1123 CHECK_EQ(source->length(), kProgramSize); |
| 1032 i::Handle<i::Script> script = factory->NewScript(source); | 1124 i::Handle<i::Script> script = factory->NewScript(source); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 kAllowLazy, | 1184 kAllowLazy, |
| 1093 kAllowNativesSyntax, | 1185 kAllowNativesSyntax, |
| 1094 kAllowHarmonyScoping, | 1186 kAllowHarmonyScoping, |
| 1095 kAllowModules, | 1187 kAllowModules, |
| 1096 kAllowGenerators, | 1188 kAllowGenerators, |
| 1097 kAllowForOf, | 1189 kAllowForOf, |
| 1098 kAllowHarmonyNumericLiterals | 1190 kAllowHarmonyNumericLiterals |
| 1099 }; | 1191 }; |
| 1100 | 1192 |
| 1101 | 1193 |
| 1102 void SetParserFlags(i::ParserBase* parser, i::EnumSet<ParserFlag> flags) { | 1194 enum ParserSyncTestResult { |
| 1195 kSuccessOrError, |
| 1196 kSuccess, |
| 1197 kError |
| 1198 }; |
| 1199 |
| 1200 template <typename Traits> |
| 1201 void SetParserFlags(i::ParserBase<Traits>* parser, |
| 1202 i::EnumSet<ParserFlag> flags) { |
| 1103 parser->set_allow_lazy(flags.Contains(kAllowLazy)); | 1203 parser->set_allow_lazy(flags.Contains(kAllowLazy)); |
| 1104 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax)); | 1204 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax)); |
| 1105 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping)); | 1205 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping)); |
| 1106 parser->set_allow_modules(flags.Contains(kAllowModules)); | 1206 parser->set_allow_modules(flags.Contains(kAllowModules)); |
| 1107 parser->set_allow_generators(flags.Contains(kAllowGenerators)); | 1207 parser->set_allow_generators(flags.Contains(kAllowGenerators)); |
| 1108 parser->set_allow_for_of(flags.Contains(kAllowForOf)); | 1208 parser->set_allow_for_of(flags.Contains(kAllowForOf)); |
| 1109 parser->set_allow_harmony_numeric_literals( | 1209 parser->set_allow_harmony_numeric_literals( |
| 1110 flags.Contains(kAllowHarmonyNumericLiterals)); | 1210 flags.Contains(kAllowHarmonyNumericLiterals)); |
| 1111 } | 1211 } |
| 1112 | 1212 |
| 1113 | 1213 |
| 1114 void TestParserSyncWithFlags(i::Handle<i::String> source, | 1214 void TestParserSyncWithFlags(i::Handle<i::String> source, |
| 1115 i::EnumSet<ParserFlag> flags) { | 1215 i::EnumSet<ParserFlag> flags, |
| 1216 ParserSyncTestResult result) { |
| 1116 i::Isolate* isolate = CcTest::i_isolate(); | 1217 i::Isolate* isolate = CcTest::i_isolate(); |
| 1117 i::Factory* factory = isolate->factory(); | 1218 i::Factory* factory = isolate->factory(); |
| 1118 | 1219 |
| 1119 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); | 1220 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); |
| 1120 | 1221 |
| 1121 // Preparse the data. | 1222 // Preparse the data. |
| 1122 i::CompleteParserRecorder log; | 1223 i::CompleteParserRecorder log; |
| 1123 { | 1224 { |
| 1124 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); | 1225 i::Scanner scanner(isolate->unicode_cache()); |
| 1226 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
| 1125 i::PreParser preparser(&scanner, &log, stack_limit); | 1227 i::PreParser preparser(&scanner, &log, stack_limit); |
| 1126 SetParserFlags(&preparser, flags); | 1228 SetParserFlags(&preparser, flags); |
| 1127 scanner.Init(); | 1229 scanner.Initialize(&stream); |
| 1128 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | 1230 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 1129 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | 1231 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 1130 } | 1232 } |
| 1131 i::ScriptDataImpl data(log.ExtractData()); | 1233 i::ScriptDataImpl data(log.ExtractData()); |
| 1132 | 1234 |
| 1133 // Parse the data | 1235 // Parse the data |
| 1134 i::FunctionLiteral* function; | 1236 i::FunctionLiteral* function; |
| 1135 { | 1237 { |
| 1136 i::Handle<i::Script> script = factory->NewScript(source); | 1238 i::Handle<i::Script> script = factory->NewScript(source); |
| 1137 i::CompilationInfoWithZone info(script); | 1239 i::CompilationInfoWithZone info(script); |
| 1138 i::Parser parser(&info); | 1240 i::Parser parser(&info); |
| 1139 SetParserFlags(&parser, flags); | 1241 SetParserFlags(&parser, flags); |
| 1140 info.MarkAsGlobal(); | 1242 info.MarkAsGlobal(); |
| 1141 parser.Parse(); | 1243 parser.Parse(); |
| 1142 function = info.function(); | 1244 function = info.function(); |
| 1143 } | 1245 } |
| 1144 | 1246 |
| 1145 // Check that preparsing fails iff parsing fails. | 1247 // Check that preparsing fails iff parsing fails. |
| 1146 if (function == NULL) { | 1248 if (function == NULL) { |
| 1147 // Extract exception from the parser. | 1249 // Extract exception from the parser. |
| 1148 CHECK(isolate->has_pending_exception()); | 1250 CHECK(isolate->has_pending_exception()); |
| 1149 i::MaybeObject* maybe_object = isolate->pending_exception(); | 1251 i::MaybeObject* maybe_object = isolate->pending_exception(); |
| 1150 i::JSObject* exception = NULL; | 1252 i::JSObject* exception = NULL; |
| 1151 CHECK(maybe_object->To(&exception)); | 1253 CHECK(maybe_object->To(&exception)); |
| 1152 i::Handle<i::JSObject> exception_handle(exception); | 1254 i::Handle<i::JSObject> exception_handle(exception); |
| 1153 i::Handle<i::String> message_string = | 1255 i::Handle<i::String> message_string = |
| 1154 i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message")); | 1256 i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message")); |
| 1257 |
| 1258 if (result == kSuccess) { |
| 1259 i::OS::Print( |
| 1260 "Parser failed on:\n" |
| 1261 "\t%s\n" |
| 1262 "with error:\n" |
| 1263 "\t%s\n" |
| 1264 "However, we expected no error.", |
| 1265 source->ToCString().get(), message_string->ToCString().get()); |
| 1266 CHECK(false); |
| 1267 } |
| 1155 | 1268 |
| 1156 if (!data.has_error()) { | 1269 if (!data.has_error()) { |
| 1157 i::OS::Print( | 1270 i::OS::Print( |
| 1158 "Parser failed on:\n" | 1271 "Parser failed on:\n" |
| 1159 "\t%s\n" | 1272 "\t%s\n" |
| 1160 "with error:\n" | 1273 "with error:\n" |
| 1161 "\t%s\n" | 1274 "\t%s\n" |
| 1162 "However, the preparser succeeded", | 1275 "However, the preparser succeeded", |
| 1163 source->ToCString().get(), message_string->ToCString().get()); | 1276 source->ToCString().get(), message_string->ToCString().get()); |
| 1164 CHECK(false); | 1277 CHECK(false); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1179 } | 1292 } |
| 1180 } else if (data.has_error()) { | 1293 } else if (data.has_error()) { |
| 1181 i::OS::Print( | 1294 i::OS::Print( |
| 1182 "Preparser failed on:\n" | 1295 "Preparser failed on:\n" |
| 1183 "\t%s\n" | 1296 "\t%s\n" |
| 1184 "with error:\n" | 1297 "with error:\n" |
| 1185 "\t%s\n" | 1298 "\t%s\n" |
| 1186 "However, the parser succeeded", | 1299 "However, the parser succeeded", |
| 1187 source->ToCString().get(), FormatMessage(&data)->ToCString().get()); | 1300 source->ToCString().get(), FormatMessage(&data)->ToCString().get()); |
| 1188 CHECK(false); | 1301 CHECK(false); |
| 1302 } else if (result == kError) { |
| 1303 i::OS::Print( |
| 1304 "Expected error on:\n" |
| 1305 "\t%s\n" |
| 1306 "However, parser and preparser succeeded", |
| 1307 source->ToCString().get()); |
| 1308 CHECK(false); |
| 1189 } | 1309 } |
| 1190 } | 1310 } |
| 1191 | 1311 |
| 1192 | 1312 |
| 1193 void TestParserSync(const char* source, | 1313 void TestParserSync(const char* source, |
| 1194 const ParserFlag* flag_list, | 1314 const ParserFlag* flag_list, |
| 1195 size_t flag_list_length) { | 1315 size_t flag_list_length, |
| 1316 ParserSyncTestResult result = kSuccessOrError) { |
| 1196 i::Handle<i::String> str = | 1317 i::Handle<i::String> str = |
| 1197 CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source)); | 1318 CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source)); |
| 1198 for (int bits = 0; bits < (1 << flag_list_length); bits++) { | 1319 for (int bits = 0; bits < (1 << flag_list_length); bits++) { |
| 1199 i::EnumSet<ParserFlag> flags; | 1320 i::EnumSet<ParserFlag> flags; |
| 1200 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) { | 1321 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) { |
| 1201 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]); | 1322 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]); |
| 1202 } | 1323 } |
| 1203 TestParserSyncWithFlags(str, flags); | 1324 TestParserSyncWithFlags(str, flags, result); |
| 1204 } | 1325 } |
| 1205 } | 1326 } |
| 1206 | 1327 |
| 1207 | 1328 |
| 1208 TEST(ParserSync) { | 1329 TEST(ParserSync) { |
| 1209 const char* context_data[][2] = { | 1330 const char* context_data[][2] = { |
| 1210 { "", "" }, | 1331 { "", "" }, |
| 1211 { "{", "}" }, | 1332 { "{", "}" }, |
| 1212 { "if (true) ", " else {}" }, | 1333 { "if (true) ", " else {}" }, |
| 1213 { "if (true) {} else ", "" }, | 1334 { "if (true) {} else ", "" }, |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 " b = function() { \n" | 1458 " b = function() { \n" |
| 1338 " 01; \n" | 1459 " 01; \n" |
| 1339 " }; \n" | 1460 " }; \n" |
| 1340 "}; \n"; | 1461 "}; \n"; |
| 1341 v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script)); | 1462 v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script)); |
| 1342 CHECK(try_catch.HasCaught()); | 1463 CHECK(try_catch.HasCaught()); |
| 1343 v8::String::Utf8Value exception(try_catch.Exception()); | 1464 v8::String::Utf8Value exception(try_catch.Exception()); |
| 1344 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", | 1465 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", |
| 1345 *exception); | 1466 *exception); |
| 1346 } | 1467 } |
| 1468 |
| 1469 |
| 1470 void RunParserSyncTest(const char* context_data[][2], |
| 1471 const char* statement_data[], |
| 1472 ParserSyncTestResult result) { |
| 1473 v8::HandleScope handles(CcTest::isolate()); |
| 1474 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate()); |
| 1475 v8::Context::Scope context_scope(context); |
| 1476 |
| 1477 int marker; |
| 1478 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 1479 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 1480 |
| 1481 static const ParserFlag flags[] = { |
| 1482 kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators, |
| 1483 kAllowForOf, kAllowNativesSyntax |
| 1484 }; |
| 1485 for (int i = 0; context_data[i][0] != NULL; ++i) { |
| 1486 for (int j = 0; statement_data[j] != NULL; ++j) { |
| 1487 int kPrefixLen = i::StrLength(context_data[i][0]); |
| 1488 int kStatementLen = i::StrLength(statement_data[j]); |
| 1489 int kSuffixLen = i::StrLength(context_data[i][1]); |
| 1490 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen; |
| 1491 |
| 1492 // Plug the source code pieces together. |
| 1493 i::ScopedVector<char> program(kProgramSize + 1); |
| 1494 int length = i::OS::SNPrintF(program, |
| 1495 "%s%s%s", |
| 1496 context_data[i][0], |
| 1497 statement_data[j], |
| 1498 context_data[i][1]); |
| 1499 CHECK(length == kProgramSize); |
| 1500 TestParserSync(program.start(), |
| 1501 flags, |
| 1502 ARRAY_SIZE(flags), |
| 1503 result); |
| 1504 } |
| 1505 } |
| 1506 } |
| 1507 |
| 1508 |
| 1509 TEST(ErrorsEvalAndArguments) { |
| 1510 // Tests that both preparsing and parsing produce the right kind of errors for |
| 1511 // using "eval" and "arguments" as identifiers. Without the strict mode, it's |
| 1512 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it |
| 1513 // isn't. |
| 1514 const char* context_data[][2] = { |
| 1515 { "\"use strict\";", "" }, |
| 1516 { "var eval; function test_func() {\"use strict\"; ", "}"}, |
| 1517 { NULL, NULL } |
| 1518 }; |
| 1519 |
| 1520 const char* statement_data[] = { |
| 1521 "var eval;", |
| 1522 "var arguments", |
| 1523 "var foo, eval;", |
| 1524 "var foo, arguments;", |
| 1525 "try { } catch (eval) { }", |
| 1526 "try { } catch (arguments) { }", |
| 1527 "function eval() { }", |
| 1528 "function arguments() { }", |
| 1529 "function foo(eval) { }", |
| 1530 "function foo(arguments) { }", |
| 1531 "function foo(bar, eval) { }", |
| 1532 "function foo(bar, arguments) { }", |
| 1533 "eval = 1;", |
| 1534 "arguments = 1;", |
| 1535 "var foo = eval = 1;", |
| 1536 "var foo = arguments = 1;", |
| 1537 "++eval;", |
| 1538 "++arguments;", |
| 1539 "eval++;", |
| 1540 "arguments++;", |
| 1541 NULL |
| 1542 }; |
| 1543 |
| 1544 RunParserSyncTest(context_data, statement_data, kError); |
| 1545 } |
| 1546 |
| 1547 |
| 1548 TEST(NoErrorsEvalAndArgumentsClassic) { |
| 1549 // Tests that both preparsing and parsing accept "eval" and "arguments" as |
| 1550 // identifiers when needed. |
| 1551 const char* context_data[][2] = { |
| 1552 { "", "" }, |
| 1553 { "function test_func() {", "}"}, |
| 1554 { NULL, NULL } |
| 1555 }; |
| 1556 |
| 1557 const char* statement_data[] = { |
| 1558 "var eval;", |
| 1559 "var arguments", |
| 1560 "var foo, eval;", |
| 1561 "var foo, arguments;", |
| 1562 "try { } catch (eval) { }", |
| 1563 "try { } catch (arguments) { }", |
| 1564 "function eval() { }", |
| 1565 "function arguments() { }", |
| 1566 "function foo(eval) { }", |
| 1567 "function foo(arguments) { }", |
| 1568 "function foo(bar, eval) { }", |
| 1569 "function foo(bar, arguments) { }", |
| 1570 "eval = 1;", |
| 1571 "arguments = 1;", |
| 1572 "var foo = eval = 1;", |
| 1573 "var foo = arguments = 1;", |
| 1574 "++eval;", |
| 1575 "++arguments;", |
| 1576 "eval++;", |
| 1577 "arguments++;", |
| 1578 NULL |
| 1579 }; |
| 1580 |
| 1581 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1582 } |
| 1583 |
| 1584 |
| 1585 TEST(NoErrorsEvalAndArgumentsStrict) { |
| 1586 const char* context_data[][2] = { |
| 1587 { "\"use strict\";", "" }, |
| 1588 { "function test_func() { \"use strict\";", "}" }, |
| 1589 { NULL, NULL } |
| 1590 }; |
| 1591 |
| 1592 const char* statement_data[] = { |
| 1593 "eval;", |
| 1594 "arguments;", |
| 1595 "var foo = eval;", |
| 1596 "var foo = arguments;", |
| 1597 "var foo = { eval: 1 };", |
| 1598 "var foo = { arguments: 1 };", |
| 1599 "var foo = { }; foo.eval = {};", |
| 1600 "var foo = { }; foo.arguments = {};", |
| 1601 NULL |
| 1602 }; |
| 1603 |
| 1604 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1605 } |
| 1606 |
| 1607 |
| 1608 TEST(ErrorsFutureStrictReservedWords) { |
| 1609 // Tests that both preparsing and parsing produce the right kind of errors for |
| 1610 // using future strict reserved words as identifiers. Without the strict mode, |
| 1611 // it's ok to use future strict reserved words as identifiers. With the strict |
| 1612 // mode, it isn't. |
| 1613 const char* context_data[][2] = { |
| 1614 { "\"use strict\";", "" }, |
| 1615 { "function test_func() {\"use strict\"; ", "}"}, |
| 1616 { NULL, NULL } |
| 1617 }; |
| 1618 |
| 1619 const char* statement_data[] = { |
| 1620 "var interface;", |
| 1621 "var foo, interface;", |
| 1622 "try { } catch (interface) { }", |
| 1623 "function interface() { }", |
| 1624 "function foo(interface) { }", |
| 1625 "function foo(bar, interface) { }", |
| 1626 "interface = 1;", |
| 1627 "var foo = interface = 1;", |
| 1628 "++interface;", |
| 1629 "interface++;", |
| 1630 NULL |
| 1631 }; |
| 1632 |
| 1633 RunParserSyncTest(context_data, statement_data, kError); |
| 1634 } |
| 1635 |
| 1636 |
| 1637 TEST(NoErrorsFutureStrictReservedWords) { |
| 1638 const char* context_data[][2] = { |
| 1639 { "", "" }, |
| 1640 { "function test_func() {", "}"}, |
| 1641 { NULL, NULL } |
| 1642 }; |
| 1643 |
| 1644 const char* statement_data[] = { |
| 1645 "var interface;", |
| 1646 "var foo, interface;", |
| 1647 "try { } catch (interface) { }", |
| 1648 "function interface() { }", |
| 1649 "function foo(interface) { }", |
| 1650 "function foo(bar, interface) { }", |
| 1651 "interface = 1;", |
| 1652 "var foo = interface = 1;", |
| 1653 "++interface;", |
| 1654 "interface++;", |
| 1655 NULL |
| 1656 }; |
| 1657 |
| 1658 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1659 } |
| 1660 |
| 1661 |
| 1662 TEST(ErrorsReservedWords) { |
| 1663 // Tests that both preparsing and parsing produce the right kind of errors for |
| 1664 // using future reserved words as identifiers. These tests don't depend on the |
| 1665 // strict mode. |
| 1666 const char* context_data[][2] = { |
| 1667 { "", "" }, |
| 1668 { "\"use strict\";", "" }, |
| 1669 { "var eval; function test_func() {", "}"}, |
| 1670 { "var eval; function test_func() {\"use strict\"; ", "}"}, |
| 1671 { NULL, NULL } |
| 1672 }; |
| 1673 |
| 1674 const char* statement_data[] = { |
| 1675 "var super;", |
| 1676 "var foo, super;", |
| 1677 "try { } catch (super) { }", |
| 1678 "function super() { }", |
| 1679 "function foo(super) { }", |
| 1680 "function foo(bar, super) { }", |
| 1681 "super = 1;", |
| 1682 "var foo = super = 1;", |
| 1683 "++super;", |
| 1684 "super++;", |
| 1685 "function foo super", |
| 1686 NULL |
| 1687 }; |
| 1688 |
| 1689 RunParserSyncTest(context_data, statement_data, kError); |
| 1690 } |
| 1691 |
| 1692 |
| 1693 TEST(NoErrorsYieldClassic) { |
| 1694 // In classic mode, it's okay to use "yield" as identifier, *except* inside a |
| 1695 // generator (see next test). |
| 1696 const char* context_data[][2] = { |
| 1697 { "", "" }, |
| 1698 { "function is_not_gen() {", "}" }, |
| 1699 { NULL, NULL } |
| 1700 }; |
| 1701 |
| 1702 const char* statement_data[] = { |
| 1703 "var yield;", |
| 1704 "var foo, yield;", |
| 1705 "try { } catch (yield) { }", |
| 1706 "function yield() { }", |
| 1707 "function foo(yield) { }", |
| 1708 "function foo(bar, yield) { }", |
| 1709 "yield = 1;", |
| 1710 "var foo = yield = 1;", |
| 1711 "++yield;", |
| 1712 "yield++;", |
| 1713 NULL |
| 1714 }; |
| 1715 |
| 1716 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1717 } |
| 1718 |
| 1719 |
| 1720 TEST(ErrorsYieldClassicGenerator) { |
| 1721 const char* context_data[][2] = { |
| 1722 { "function * is_gen() {", "}" }, |
| 1723 { NULL, NULL } |
| 1724 }; |
| 1725 |
| 1726 const char* statement_data[] = { |
| 1727 "var yield;", |
| 1728 "var foo, yield;", |
| 1729 "try { } catch (yield) { }", |
| 1730 "function yield() { }", |
| 1731 // BUG: These should not be allowed, but they are (if kAllowGenerators is |
| 1732 // set) |
| 1733 // "function foo(yield) { }", |
| 1734 // "function foo(bar, yield) { }", |
| 1735 "yield = 1;", |
| 1736 "var foo = yield = 1;", |
| 1737 "++yield;", |
| 1738 "yield++;", |
| 1739 NULL |
| 1740 }; |
| 1741 |
| 1742 // If generators are not allowed, the error will be produced at the '*' token, |
| 1743 // so this test works both with and without the kAllowGenerators flag. |
| 1744 RunParserSyncTest(context_data, statement_data, kError); |
| 1745 } |
| 1746 |
| 1747 |
| 1748 TEST(ErrorsYieldStrict) { |
| 1749 const char* context_data[][2] = { |
| 1750 { "\"use strict\";", "" }, |
| 1751 { "\"use strict\"; function is_not_gen() {", "}" }, |
| 1752 { "function test_func() {\"use strict\"; ", "}"}, |
| 1753 { NULL, NULL } |
| 1754 }; |
| 1755 |
| 1756 const char* statement_data[] = { |
| 1757 "var yield;", |
| 1758 "var foo, yield;", |
| 1759 "try { } catch (yield) { }", |
| 1760 "function yield() { }", |
| 1761 "function foo(yield) { }", |
| 1762 "function foo(bar, yield) { }", |
| 1763 "yield = 1;", |
| 1764 "var foo = yield = 1;", |
| 1765 "++yield;", |
| 1766 "yield++;", |
| 1767 NULL |
| 1768 }; |
| 1769 |
| 1770 RunParserSyncTest(context_data, statement_data, kError); |
| 1771 } |
| 1772 |
| 1773 |
| 1774 TEST(ErrorsYield) { |
| 1775 const char* context_data[][2] = { |
| 1776 { "function * is_gen() {", "}" }, |
| 1777 { NULL, NULL } |
| 1778 }; |
| 1779 |
| 1780 const char* statement_data[] = { |
| 1781 "yield 2;", // this is legal inside generator |
| 1782 "yield * 2;", // this is legal inside generator |
| 1783 NULL |
| 1784 }; |
| 1785 |
| 1786 // Here we cannot assert that there is no error, since there will be without |
| 1787 // the kAllowGenerators flag. However, we test that Parser and PreParser |
| 1788 // produce the same errors. |
| 1789 RunParserSyncTest(context_data, statement_data, kSuccessOrError); |
| 1790 } |
| 1791 |
| 1792 |
| 1793 TEST(ErrorsNameOfStrictFunction) { |
| 1794 // Tests that illegal tokens as names of a strict function produce the correct |
| 1795 // errors. |
| 1796 const char* context_data[][2] = { |
| 1797 { "", ""}, |
| 1798 { "\"use strict\";", ""}, |
| 1799 { NULL, NULL } |
| 1800 }; |
| 1801 |
| 1802 const char* statement_data[] = { |
| 1803 "function eval() {\"use strict\";}", |
| 1804 "function arguments() {\"use strict\";}", |
| 1805 "function interface() {\"use strict\";}", |
| 1806 "function yield() {\"use strict\";}", |
| 1807 // Future reserved words are always illegal |
| 1808 "function super() { }", |
| 1809 "function super() {\"use strict\";}", |
| 1810 NULL |
| 1811 }; |
| 1812 |
| 1813 RunParserSyncTest(context_data, statement_data, kError); |
| 1814 } |
| 1815 |
| 1816 |
| 1817 TEST(NoErrorsNameOfStrictFunction) { |
| 1818 const char* context_data[][2] = { |
| 1819 { "", ""}, |
| 1820 { NULL, NULL } |
| 1821 }; |
| 1822 |
| 1823 const char* statement_data[] = { |
| 1824 "function eval() { }", |
| 1825 "function arguments() { }", |
| 1826 "function interface() { }", |
| 1827 "function yield() { }", |
| 1828 NULL |
| 1829 }; |
| 1830 |
| 1831 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1832 } |
| 1833 |
| 1834 |
| 1835 |
| 1836 TEST(ErrorsIllegalWordsAsLabelsClassic) { |
| 1837 // Using future reserved words as labels is always an error. |
| 1838 const char* context_data[][2] = { |
| 1839 { "", ""}, |
| 1840 { "function test_func() {", "}" }, |
| 1841 { NULL, NULL } |
| 1842 }; |
| 1843 |
| 1844 const char* statement_data[] = { |
| 1845 "super: while(true) { break super; }", |
| 1846 NULL |
| 1847 }; |
| 1848 |
| 1849 RunParserSyncTest(context_data, statement_data, kError); |
| 1850 } |
| 1851 |
| 1852 |
| 1853 TEST(ErrorsIllegalWordsAsLabelsStrict) { |
| 1854 // Tests that illegal tokens as labels produce the correct errors. |
| 1855 const char* context_data[][2] = { |
| 1856 { "\"use strict\";", "" }, |
| 1857 { "function test_func() {\"use strict\"; ", "}"}, |
| 1858 { NULL, NULL } |
| 1859 }; |
| 1860 |
| 1861 const char* statement_data[] = { |
| 1862 "super: while(true) { break super; }", |
| 1863 "interface: while(true) { break interface; }", |
| 1864 "yield: while(true) { break yield; }", |
| 1865 NULL |
| 1866 }; |
| 1867 |
| 1868 RunParserSyncTest(context_data, statement_data, kError); |
| 1869 } |
| 1870 |
| 1871 |
| 1872 TEST(NoErrorsIllegalWordsAsLabels) { |
| 1873 // Using eval and arguments as labels is legal even in strict mode. |
| 1874 const char* context_data[][2] = { |
| 1875 { "", ""}, |
| 1876 { "function test_func() {", "}" }, |
| 1877 { "\"use strict\";", "" }, |
| 1878 { "\"use strict\"; function test_func() {", "}" }, |
| 1879 { NULL, NULL } |
| 1880 }; |
| 1881 |
| 1882 const char* statement_data[] = { |
| 1883 "mylabel: while(true) { break mylabel; }", |
| 1884 "eval: while(true) { break eval; }", |
| 1885 "arguments: while(true) { break arguments; }", |
| 1886 NULL |
| 1887 }; |
| 1888 |
| 1889 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1890 } |
| 1891 |
| 1892 |
| 1893 TEST(ErrorsParenthesizedLabels) { |
| 1894 // Parenthesized identifiers shouldn't be recognized as labels. |
| 1895 const char* context_data[][2] = { |
| 1896 { "", ""}, |
| 1897 { "function test_func() {", "}" }, |
| 1898 { NULL, NULL } |
| 1899 }; |
| 1900 |
| 1901 const char* statement_data[] = { |
| 1902 "(mylabel): while(true) { break mylabel; }", |
| 1903 NULL |
| 1904 }; |
| 1905 |
| 1906 RunParserSyncTest(context_data, statement_data, kError); |
| 1907 } |
| 1908 |
| 1909 |
| 1910 TEST(NoErrorsParenthesizedDirectivePrologue) { |
| 1911 // Parenthesized directive prologue shouldn't be recognized. |
| 1912 const char* context_data[][2] = { |
| 1913 { "", ""}, |
| 1914 { NULL, NULL } |
| 1915 }; |
| 1916 |
| 1917 const char* statement_data[] = { |
| 1918 "(\"use strict\"); var eval;", |
| 1919 NULL |
| 1920 }; |
| 1921 |
| 1922 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1923 } |
| 1924 |
| 1925 |
| 1926 TEST(ErrorsNotAnIdentifierName) { |
| 1927 const char* context_data[][2] = { |
| 1928 { "", ""}, |
| 1929 { "\"use strict\";", ""}, |
| 1930 { NULL, NULL } |
| 1931 }; |
| 1932 |
| 1933 const char* statement_data[] = { |
| 1934 "var foo = {}; foo.{;", |
| 1935 "var foo = {}; foo.};", |
| 1936 "var foo = {}; foo.=;", |
| 1937 "var foo = {}; foo.888;", |
| 1938 "var foo = {}; foo.-;", |
| 1939 "var foo = {}; foo.--;", |
| 1940 NULL |
| 1941 }; |
| 1942 |
| 1943 RunParserSyncTest(context_data, statement_data, kError); |
| 1944 } |
| 1945 |
| 1946 |
| 1947 TEST(NoErrorsIdentifierNames) { |
| 1948 // Keywords etc. are valid as property names. |
| 1949 const char* context_data[][2] = { |
| 1950 { "", ""}, |
| 1951 { "\"use strict\";", ""}, |
| 1952 { NULL, NULL } |
| 1953 }; |
| 1954 |
| 1955 const char* statement_data[] = { |
| 1956 "var foo = {}; foo.if;", |
| 1957 "var foo = {}; foo.yield;", |
| 1958 "var foo = {}; foo.super;", |
| 1959 "var foo = {}; foo.interface;", |
| 1960 "var foo = {}; foo.eval;", |
| 1961 "var foo = {}; foo.arguments;", |
| 1962 NULL |
| 1963 }; |
| 1964 |
| 1965 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 1966 } |
| 1967 |
| 1968 |
| 1969 TEST(DontRegressPreParserDataSizes) { |
| 1970 // These tests make sure that PreParser doesn't start producing less data. |
| 1971 |
| 1972 v8::V8::Initialize(); |
| 1973 |
| 1974 int marker; |
| 1975 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
| 1976 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
| 1977 |
| 1978 struct TestCase { |
| 1979 const char* program; |
| 1980 int symbols; |
| 1981 int functions; |
| 1982 } test_cases[] = { |
| 1983 // Labels, variables and functions are recorded as symbols. |
| 1984 {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0}, |
| 1985 {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0}, |
| 1986 {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2}, |
| 1987 // Labels, variables and functions insize lazy functions are not recorded. |
| 1988 {"function lazy() { var a, b, c; }", 1, 1}, |
| 1989 {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1}, |
| 1990 {"function lazy() { function a() {} function b() {} function c() {} }", 1, |
| 1991 1}, |
| 1992 {NULL, 0, 0} |
| 1993 }; |
| 1994 // Each function adds 5 elements to the preparse function data. |
| 1995 const int kDataPerFunction = 5; |
| 1996 |
| 1997 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); |
| 1998 for (int i = 0; test_cases[i].program; i++) { |
| 1999 const char* program = test_cases[i].program; |
| 2000 i::Utf8ToUtf16CharacterStream stream( |
| 2001 reinterpret_cast<const i::byte*>(program), |
| 2002 static_cast<unsigned>(strlen(program))); |
| 2003 i::CompleteParserRecorder log; |
| 2004 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
| 2005 scanner.Initialize(&stream); |
| 2006 |
| 2007 i::PreParser preparser(&scanner, &log, stack_limit); |
| 2008 preparser.set_allow_lazy(true); |
| 2009 preparser.set_allow_natives_syntax(true); |
| 2010 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 2011 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 2012 if (log.symbol_ids() != test_cases[i].symbols) { |
| 2013 i::OS::Print( |
| 2014 "Expected preparse data for program:\n" |
| 2015 "\t%s\n" |
| 2016 "to contain %d symbols, however, received %d symbols.\n", |
| 2017 program, test_cases[i].symbols, log.symbol_ids()); |
| 2018 CHECK(false); |
| 2019 } |
| 2020 if (log.function_position() != test_cases[i].functions * kDataPerFunction) { |
| 2021 i::OS::Print( |
| 2022 "Expected preparse data for program:\n" |
| 2023 "\t%s\n" |
| 2024 "to contain %d functions, however, received %d functions.\n", |
| 2025 program, test_cases[i].functions, |
| 2026 log.function_position() / kDataPerFunction); |
| 2027 CHECK(false); |
| 2028 } |
| 2029 i::ScriptDataImpl data(log.ExtractData()); |
| 2030 CHECK(!data.has_error()); |
| 2031 } |
| 2032 } |
| 2033 |
| 2034 |
| 2035 TEST(FunctionDeclaresItselfStrict) { |
| 2036 // Tests that we produce the right kinds of errors when a function declares |
| 2037 // itself strict (we cannot produce there errors as soon as we see the |
| 2038 // offending identifiers, because we don't know at that point whether the |
| 2039 // function is strict or not). |
| 2040 const char* context_data[][2] = { |
| 2041 {"function eval() {", "}"}, |
| 2042 {"function arguments() {", "}"}, |
| 2043 {"function yield() {", "}"}, |
| 2044 {"function interface() {", "}"}, |
| 2045 {"function foo(eval) {", "}"}, |
| 2046 {"function foo(arguments) {", "}"}, |
| 2047 {"function foo(yield) {", "}"}, |
| 2048 {"function foo(interface) {", "}"}, |
| 2049 {"function foo(bar, eval) {", "}"}, |
| 2050 {"function foo(bar, arguments) {", "}"}, |
| 2051 {"function foo(bar, yield) {", "}"}, |
| 2052 {"function foo(bar, interface) {", "}"}, |
| 2053 {"function foo(bar, bar) {", "}"}, |
| 2054 { NULL, NULL } |
| 2055 }; |
| 2056 |
| 2057 const char* strict_statement_data[] = { |
| 2058 "\"use strict\";", |
| 2059 NULL |
| 2060 }; |
| 2061 |
| 2062 const char* non_strict_statement_data[] = { |
| 2063 ";", |
| 2064 NULL |
| 2065 }; |
| 2066 |
| 2067 RunParserSyncTest(context_data, strict_statement_data, kError); |
| 2068 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess); |
| 2069 } |
| 2070 |
| 2071 |
| 2072 TEST(ErrorsTryWithoutCatchOrFinally) { |
| 2073 const char* context_data[][2] = { |
| 2074 {"", ""}, |
| 2075 { NULL, NULL } |
| 2076 }; |
| 2077 |
| 2078 const char* statement_data[] = { |
| 2079 "try { }", |
| 2080 "try { } foo();", |
| 2081 "try { } catch (e) foo();", |
| 2082 "try { } catch { }", |
| 2083 "try { } finally foo();", |
| 2084 NULL |
| 2085 }; |
| 2086 |
| 2087 RunParserSyncTest(context_data, statement_data, kError); |
| 2088 } |
| 2089 |
| 2090 |
| 2091 TEST(NoErrorsTryCatchFinally) { |
| 2092 const char* context_data[][2] = { |
| 2093 {"", ""}, |
| 2094 { NULL, NULL } |
| 2095 }; |
| 2096 |
| 2097 const char* statement_data[] = { |
| 2098 "try { } catch (e) { }", |
| 2099 "try { } catch (e) { } finally { }", |
| 2100 "try { } finally { }", |
| 2101 NULL |
| 2102 }; |
| 2103 |
| 2104 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 2105 } |
| 2106 |
| 2107 |
| 2108 TEST(ErrorsRegexpLiteral) { |
| 2109 const char* context_data[][2] = { |
| 2110 {"var r = ", ""}, |
| 2111 { NULL, NULL } |
| 2112 }; |
| 2113 |
| 2114 const char* statement_data[] = { |
| 2115 "/unterminated", |
| 2116 NULL |
| 2117 }; |
| 2118 |
| 2119 RunParserSyncTest(context_data, statement_data, kError); |
| 2120 } |
| 2121 |
| 2122 |
| 2123 TEST(NoErrorsRegexpLiteral) { |
| 2124 const char* context_data[][2] = { |
| 2125 {"var r = ", ""}, |
| 2126 { NULL, NULL } |
| 2127 }; |
| 2128 |
| 2129 const char* statement_data[] = { |
| 2130 "/foo/", |
| 2131 "/foo/g", |
| 2132 "/foo/whatever", // This is an error but not detected by the parser. |
| 2133 NULL |
| 2134 }; |
| 2135 |
| 2136 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 2137 } |
| 2138 |
| 2139 |
| 2140 TEST(Intrinsics) { |
| 2141 const char* context_data[][2] = { |
| 2142 {"", ""}, |
| 2143 { NULL, NULL } |
| 2144 }; |
| 2145 |
| 2146 const char* statement_data[] = { |
| 2147 "%someintrinsic(arg)", |
| 2148 NULL |
| 2149 }; |
| 2150 |
| 2151 // Parsing will fail or succeed depending on whether we allow natives syntax |
| 2152 // or not. |
| 2153 RunParserSyncTest(context_data, statement_data, kSuccessOrError); |
| 2154 } |
| 2155 |
| 2156 |
| 2157 TEST(NoErrorsNewExpression) { |
| 2158 const char* context_data[][2] = { |
| 2159 {"", ""}, |
| 2160 {"var f =", ""}, |
| 2161 { NULL, NULL } |
| 2162 }; |
| 2163 |
| 2164 const char* statement_data[] = { |
| 2165 "new foo", |
| 2166 "new foo();", |
| 2167 "new foo(1);", |
| 2168 "new foo(1, 2);", |
| 2169 // The first () will be processed as a part of the NewExpression and the |
| 2170 // second () will be processed as part of LeftHandSideExpression. |
| 2171 "new foo()();", |
| 2172 // The first () will be processed as a part of the inner NewExpression and |
| 2173 // the second () will be processed as a part of the outer NewExpression. |
| 2174 "new new foo()();", |
| 2175 "new foo.bar;", |
| 2176 "new foo.bar();", |
| 2177 "new foo.bar.baz;", |
| 2178 "new foo.bar().baz;", |
| 2179 "new foo[bar];", |
| 2180 "new foo[bar]();", |
| 2181 "new foo[bar][baz];", |
| 2182 "new foo[bar]()[baz];", |
| 2183 "new foo[bar].baz(baz)()[bar].baz;", |
| 2184 "new \"foo\"", // Runtime error |
| 2185 "new 1", // Runtime error |
| 2186 "new foo++", |
| 2187 // This even runs: |
| 2188 "(new new Function(\"this.x = 1\")).x;", |
| 2189 "new new Test_Two(String, 2).v(0123).length;", |
| 2190 NULL |
| 2191 }; |
| 2192 |
| 2193 RunParserSyncTest(context_data, statement_data, kSuccess); |
| 2194 } |
| 2195 |
| 2196 |
| 2197 TEST(ErrorsNewExpression) { |
| 2198 const char* context_data[][2] = { |
| 2199 {"", ""}, |
| 2200 {"var f =", ""}, |
| 2201 { NULL, NULL } |
| 2202 }; |
| 2203 |
| 2204 const char* statement_data[] = { |
| 2205 "new foo bar", |
| 2206 "new ) foo", |
| 2207 "new ++foo", |
| 2208 NULL |
| 2209 }; |
| 2210 |
| 2211 RunParserSyncTest(context_data, statement_data, kError); |
| 2212 } |
| OLD | NEW |