| OLD | NEW |
| 1 // Copyright 2007-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2009 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 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 387 } |
| 388 | 388 |
| 389 | 389 |
| 390 THREADED_TEST(ScriptMakingExternalString) { | 390 THREADED_TEST(ScriptMakingExternalString) { |
| 391 TestResource::dispose_count = 0; | 391 TestResource::dispose_count = 0; |
| 392 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3"); | 392 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3"); |
| 393 { | 393 { |
| 394 v8::HandleScope scope; | 394 v8::HandleScope scope; |
| 395 LocalContext env; | 395 LocalContext env; |
| 396 Local<String> source = String::New(two_byte_source); | 396 Local<String> source = String::New(two_byte_source); |
| 397 // Trigger GCs so that the newly allocated string moves to old gen. |
| 398 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now |
| 399 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now |
| 397 bool success = source->MakeExternal(new TestResource(two_byte_source)); | 400 bool success = source->MakeExternal(new TestResource(two_byte_source)); |
| 398 CHECK(success); | 401 CHECK(success); |
| 399 Local<Script> script = Script::Compile(source); | 402 Local<Script> script = Script::Compile(source); |
| 400 Local<Value> value = script->Run(); | 403 Local<Value> value = script->Run(); |
| 401 CHECK(value->IsNumber()); | 404 CHECK(value->IsNumber()); |
| 402 CHECK_EQ(7, value->Int32Value()); | 405 CHECK_EQ(7, value->Int32Value()); |
| 403 v8::internal::Heap::CollectAllGarbage(false); | 406 v8::internal::Heap::CollectAllGarbage(false); |
| 404 CHECK_EQ(0, TestResource::dispose_count); | 407 CHECK_EQ(0, TestResource::dispose_count); |
| 405 } | 408 } |
| 406 v8::internal::CompilationCache::Clear(); | 409 v8::internal::CompilationCache::Clear(); |
| 407 v8::internal::Heap::CollectAllGarbage(false); | 410 v8::internal::Heap::CollectAllGarbage(false); |
| 408 CHECK_EQ(1, TestResource::dispose_count); | 411 CHECK_EQ(1, TestResource::dispose_count); |
| 409 } | 412 } |
| 410 | 413 |
| 411 | 414 |
| 412 THREADED_TEST(ScriptMakingExternalAsciiString) { | 415 THREADED_TEST(ScriptMakingExternalAsciiString) { |
| 413 TestAsciiResource::dispose_count = 0; | 416 TestAsciiResource::dispose_count = 0; |
| 414 const char* c_source = "1 + 2 * 3"; | 417 const char* c_source = "1 + 2 * 3"; |
| 415 { | 418 { |
| 416 v8::HandleScope scope; | 419 v8::HandleScope scope; |
| 417 LocalContext env; | 420 LocalContext env; |
| 418 Local<String> source = v8_str(c_source); | 421 Local<String> source = v8_str(c_source); |
| 422 // Trigger GCs so that the newly allocated string moves to old gen. |
| 423 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now |
| 424 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now |
| 419 bool success = source->MakeExternal( | 425 bool success = source->MakeExternal( |
| 420 new TestAsciiResource(i::StrDup(c_source))); | 426 new TestAsciiResource(i::StrDup(c_source))); |
| 421 CHECK(success); | 427 CHECK(success); |
| 422 Local<Script> script = Script::Compile(source); | 428 Local<Script> script = Script::Compile(source); |
| 423 Local<Value> value = script->Run(); | 429 Local<Value> value = script->Run(); |
| 424 CHECK(value->IsNumber()); | 430 CHECK(value->IsNumber()); |
| 425 CHECK_EQ(7, value->Int32Value()); | 431 CHECK_EQ(7, value->Int32Value()); |
| 426 v8::internal::Heap::CollectAllGarbage(false); | 432 v8::internal::Heap::CollectAllGarbage(false); |
| 427 CHECK_EQ(0, TestAsciiResource::dispose_count); | 433 CHECK_EQ(0, TestAsciiResource::dispose_count); |
| 428 } | 434 } |
| 429 v8::internal::CompilationCache::Clear(); | 435 v8::internal::CompilationCache::Clear(); |
| 430 v8::internal::Heap::CollectAllGarbage(false); | 436 v8::internal::Heap::CollectAllGarbage(false); |
| 431 CHECK_EQ(1, TestAsciiResource::dispose_count); | 437 CHECK_EQ(1, TestAsciiResource::dispose_count); |
| 432 } | 438 } |
| 433 | 439 |
| 434 | 440 |
| 441 TEST(MakingExternalStringConditions) { |
| 442 v8::HandleScope scope; |
| 443 LocalContext env; |
| 444 |
| 445 // Free some space in the new space so that we can check freshness. |
| 446 i::Heap::CollectGarbage(0, i::NEW_SPACE); |
| 447 i::Heap::CollectGarbage(0, i::NEW_SPACE); |
| 448 |
| 449 Local<String> small_string = String::New(AsciiToTwoByteString("small")); |
| 450 // We should refuse to externalize newly created small string. |
| 451 CHECK(!small_string->CanMakeExternal()); |
| 452 // Trigger GCs so that the newly allocated string moves to old gen. |
| 453 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now |
| 454 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now |
| 455 // Old space strings should be accepted. |
| 456 CHECK(small_string->CanMakeExternal()); |
| 457 |
| 458 small_string = String::New(AsciiToTwoByteString("small 2")); |
| 459 // We should refuse externalizing newly created small string. |
| 460 CHECK(!small_string->CanMakeExternal()); |
| 461 for (int i = 0; i < 100; i++) { |
| 462 String::Value value(small_string); |
| 463 } |
| 464 // Frequently used strings should be accepted. |
| 465 CHECK(small_string->CanMakeExternal()); |
| 466 |
| 467 const int buf_size = 10 * 1024; |
| 468 char* buf = i::NewArray<char>(buf_size); |
| 469 memset(buf, 'a', buf_size); |
| 470 buf[buf_size - 1] = '\0'; |
| 471 Local<String> large_string = String::New(AsciiToTwoByteString(buf)); |
| 472 i::DeleteArray(buf); |
| 473 // Large strings should be immediately accepted. |
| 474 CHECK(large_string->CanMakeExternal()); |
| 475 } |
| 476 |
| 477 |
| 478 TEST(MakingExternalAsciiStringConditions) { |
| 479 v8::HandleScope scope; |
| 480 LocalContext env; |
| 481 |
| 482 // Free some space in the new space so that we can check freshness. |
| 483 i::Heap::CollectGarbage(0, i::NEW_SPACE); |
| 484 i::Heap::CollectGarbage(0, i::NEW_SPACE); |
| 485 |
| 486 Local<String> small_string = String::New("small"); |
| 487 // We should refuse to externalize newly created small string. |
| 488 CHECK(!small_string->CanMakeExternal()); |
| 489 // Trigger GCs so that the newly allocated string moves to old gen. |
| 490 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now |
| 491 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now |
| 492 // Old space strings should be accepted. |
| 493 CHECK(small_string->CanMakeExternal()); |
| 494 |
| 495 small_string = String::New("small 2"); |
| 496 // We should refuse externalizing newly created small string. |
| 497 CHECK(!small_string->CanMakeExternal()); |
| 498 for (int i = 0; i < 100; i++) { |
| 499 String::Value value(small_string); |
| 500 } |
| 501 // Frequently used strings should be accepted. |
| 502 CHECK(small_string->CanMakeExternal()); |
| 503 |
| 504 const int buf_size = 10 * 1024; |
| 505 char* buf = i::NewArray<char>(buf_size); |
| 506 memset(buf, 'a', buf_size); |
| 507 buf[buf_size - 1] = '\0'; |
| 508 Local<String> large_string = String::New(buf); |
| 509 i::DeleteArray(buf); |
| 510 // Large strings should be immediately accepted. |
| 511 CHECK(large_string->CanMakeExternal()); |
| 512 } |
| 513 |
| 514 |
| 435 THREADED_TEST(UsingExternalString) { | 515 THREADED_TEST(UsingExternalString) { |
| 436 { | 516 { |
| 437 v8::HandleScope scope; | 517 v8::HandleScope scope; |
| 438 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); | 518 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); |
| 439 Local<String> string = | 519 Local<String> string = |
| 440 String::NewExternal(new TestResource(two_byte_string)); | 520 String::NewExternal(new TestResource(two_byte_string)); |
| 441 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); | 521 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); |
| 442 // Trigger GCs so that the newly allocated string moves to old gen. | 522 // Trigger GCs so that the newly allocated string moves to old gen. |
| 443 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now | 523 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in survivor space now |
| 444 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now | 524 i::Heap::CollectGarbage(0, i::NEW_SPACE); // in old gen now |
| (...skipping 1996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2441 LocalContext context; | 2521 LocalContext context; |
| 2442 context->Global()->Set(v8_str("obj"), templ->NewInstance()); | 2522 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
| 2443 Local<Script> script = Script::Compile(v8_str("obj.x")); | 2523 Local<Script> script = Script::Compile(v8_str("obj.x")); |
| 2444 for (int i = 0; i < 10; i++) { | 2524 for (int i = 0; i < 10; i++) { |
| 2445 Local<Value> result = script->Run(); | 2525 Local<Value> result = script->Run(); |
| 2446 CHECK_EQ(result, v8_str("x")); | 2526 CHECK_EQ(result, v8_str("x")); |
| 2447 } | 2527 } |
| 2448 } | 2528 } |
| 2449 | 2529 |
| 2450 | 2530 |
| 2531 static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property, |
| 2532 const AccessorInfo& info) { |
| 2533 // Set x on the prototype object and do not handle the get request. |
| 2534 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype(); |
| 2535 v8::Handle<v8::Object>::Cast(proto)->Set(v8_str("x"), v8::Integer::New(23)); |
| 2536 return v8::Handle<Value>(); |
| 2537 } |
| 2538 |
| 2539 |
| 2540 // This is a regression test for http://crbug.com/20104. Map |
| 2541 // transitions should not interfere with post interceptor lookup. |
| 2542 THREADED_TEST(NamedInterceptorMapTransitionRead) { |
| 2543 v8::HandleScope scope; |
| 2544 Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New(); |
| 2545 Local<v8::ObjectTemplate> instance_template |
| 2546 = function_template->InstanceTemplate(); |
| 2547 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter); |
| 2548 LocalContext context; |
| 2549 context->Global()->Set(v8_str("F"), function_template->GetFunction()); |
| 2550 // Create an instance of F and introduce a map transition for x. |
| 2551 CompileRun("var o = new F(); o.x = 23;"); |
| 2552 // Create an instance of F and invoke the getter. The result should be 23. |
| 2553 Local<Value> result = CompileRun("o = new F(); o.x"); |
| 2554 CHECK_EQ(result->Int32Value(), 23); |
| 2555 } |
| 2556 |
| 2557 |
| 2451 static v8::Handle<Value> IndexedPropertyGetter(uint32_t index, | 2558 static v8::Handle<Value> IndexedPropertyGetter(uint32_t index, |
| 2452 const AccessorInfo& info) { | 2559 const AccessorInfo& info) { |
| 2453 ApiTestFuzzer::Fuzz(); | 2560 ApiTestFuzzer::Fuzz(); |
| 2454 if (index == 37) { | 2561 if (index == 37) { |
| 2455 return v8::Handle<Value>(v8_num(625)); | 2562 return v8::Handle<Value>(v8_num(625)); |
| 2456 } | 2563 } |
| 2457 return v8::Handle<Value>(); | 2564 return v8::Handle<Value>(); |
| 2458 } | 2565 } |
| 2459 | 2566 |
| 2460 | 2567 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2522 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;" | 2629 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2523 " }" | 2630 " }" |
| 2524 " 'PASSED'" | 2631 " 'PASSED'" |
| 2525 "} catch(e) {" | 2632 "} catch(e) {" |
| 2526 " e" | 2633 " e" |
| 2527 "}"; | 2634 "}"; |
| 2528 ExpectString(code, "PASSED"); | 2635 ExpectString(code, "PASSED"); |
| 2529 } | 2636 } |
| 2530 | 2637 |
| 2531 | 2638 |
| 2639 THREADED_TEST(IndexedInterceptorWithAccessorCheck) { |
| 2640 v8::HandleScope scope; |
| 2641 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2642 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2643 |
| 2644 LocalContext context; |
| 2645 Local<v8::Object> obj = templ->NewInstance(); |
| 2646 obj->TurnOnAccessCheck(); |
| 2647 context->Global()->Set(v8_str("obj"), obj); |
| 2648 |
| 2649 const char* code = |
| 2650 "try {" |
| 2651 " for (var i = 0; i < 100; i++) {" |
| 2652 " var v = obj[0];" |
| 2653 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2654 " }" |
| 2655 " 'PASSED'" |
| 2656 "} catch(e) {" |
| 2657 " e" |
| 2658 "}"; |
| 2659 ExpectString(code, "PASSED"); |
| 2660 } |
| 2661 |
| 2662 |
| 2663 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) { |
| 2664 i::FLAG_allow_natives_syntax = true; |
| 2665 v8::HandleScope scope; |
| 2666 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2667 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2668 |
| 2669 LocalContext context; |
| 2670 Local<v8::Object> obj = templ->NewInstance(); |
| 2671 context->Global()->Set(v8_str("obj"), obj); |
| 2672 |
| 2673 const char* code = |
| 2674 "try {" |
| 2675 " for (var i = 0; i < 100; i++) {" |
| 2676 " var expected = i;" |
| 2677 " if (i == 5) {" |
| 2678 " %EnableAccessChecks(obj);" |
| 2679 " expected = undefined;" |
| 2680 " }" |
| 2681 " var v = obj[i];" |
| 2682 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2683 " if (i == 5) %DisableAccessChecks(obj);" |
| 2684 " }" |
| 2685 " 'PASSED'" |
| 2686 "} catch(e) {" |
| 2687 " e" |
| 2688 "}"; |
| 2689 ExpectString(code, "PASSED"); |
| 2690 } |
| 2691 |
| 2692 |
| 2693 THREADED_TEST(IndexedInterceptorWithDifferentIndices) { |
| 2694 v8::HandleScope scope; |
| 2695 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2696 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2697 |
| 2698 LocalContext context; |
| 2699 Local<v8::Object> obj = templ->NewInstance(); |
| 2700 context->Global()->Set(v8_str("obj"), obj); |
| 2701 |
| 2702 const char* code = |
| 2703 "try {" |
| 2704 " for (var i = 0; i < 100; i++) {" |
| 2705 " var v = obj[i];" |
| 2706 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2707 " }" |
| 2708 " 'PASSED'" |
| 2709 "} catch(e) {" |
| 2710 " e" |
| 2711 "}"; |
| 2712 ExpectString(code, "PASSED"); |
| 2713 } |
| 2714 |
| 2715 |
| 2716 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) { |
| 2717 v8::HandleScope scope; |
| 2718 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2719 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2720 |
| 2721 LocalContext context; |
| 2722 Local<v8::Object> obj = templ->NewInstance(); |
| 2723 context->Global()->Set(v8_str("obj"), obj); |
| 2724 |
| 2725 const char* code = |
| 2726 "try {" |
| 2727 " for (var i = 0; i < 100; i++) {" |
| 2728 " var expected = i;" |
| 2729 " if (i == 50) {" |
| 2730 " i = 'foobar';" |
| 2731 " expected = undefined;" |
| 2732 " }" |
| 2733 " var v = obj[i];" |
| 2734 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2735 " }" |
| 2736 " 'PASSED'" |
| 2737 "} catch(e) {" |
| 2738 " e" |
| 2739 "}"; |
| 2740 ExpectString(code, "PASSED"); |
| 2741 } |
| 2742 |
| 2743 |
| 2744 THREADED_TEST(IndexedInterceptorGoingMegamorphic) { |
| 2745 v8::HandleScope scope; |
| 2746 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2747 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2748 |
| 2749 LocalContext context; |
| 2750 Local<v8::Object> obj = templ->NewInstance(); |
| 2751 context->Global()->Set(v8_str("obj"), obj); |
| 2752 |
| 2753 const char* code = |
| 2754 "var original = obj;" |
| 2755 "try {" |
| 2756 " for (var i = 0; i < 100; i++) {" |
| 2757 " var expected = i;" |
| 2758 " if (i == 50) {" |
| 2759 " obj = {50: 'foobar'};" |
| 2760 " expected = 'foobar';" |
| 2761 " }" |
| 2762 " var v = obj[i];" |
| 2763 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2764 " if (i == 50) obj = original;" |
| 2765 " }" |
| 2766 " 'PASSED'" |
| 2767 "} catch(e) {" |
| 2768 " e" |
| 2769 "}"; |
| 2770 ExpectString(code, "PASSED"); |
| 2771 } |
| 2772 |
| 2773 |
| 2774 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) { |
| 2775 v8::HandleScope scope; |
| 2776 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2777 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2778 |
| 2779 LocalContext context; |
| 2780 Local<v8::Object> obj = templ->NewInstance(); |
| 2781 context->Global()->Set(v8_str("obj"), obj); |
| 2782 |
| 2783 const char* code = |
| 2784 "var original = obj;" |
| 2785 "try {" |
| 2786 " for (var i = 0; i < 100; i++) {" |
| 2787 " var expected = i;" |
| 2788 " if (i == 5) {" |
| 2789 " obj = 239;" |
| 2790 " expected = undefined;" |
| 2791 " }" |
| 2792 " var v = obj[i];" |
| 2793 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2794 " if (i == 5) obj = original;" |
| 2795 " }" |
| 2796 " 'PASSED'" |
| 2797 "} catch(e) {" |
| 2798 " e" |
| 2799 "}"; |
| 2800 ExpectString(code, "PASSED"); |
| 2801 } |
| 2802 |
| 2803 |
| 2804 THREADED_TEST(IndexedInterceptorOnProto) { |
| 2805 v8::HandleScope scope; |
| 2806 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2807 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter); |
| 2808 |
| 2809 LocalContext context; |
| 2810 Local<v8::Object> obj = templ->NewInstance(); |
| 2811 context->Global()->Set(v8_str("obj"), obj); |
| 2812 |
| 2813 const char* code = |
| 2814 "var o = {__proto__: obj};" |
| 2815 "try {" |
| 2816 " for (var i = 0; i < 100; i++) {" |
| 2817 " var v = o[i];" |
| 2818 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;" |
| 2819 " }" |
| 2820 " 'PASSED'" |
| 2821 "} catch(e) {" |
| 2822 " e" |
| 2823 "}"; |
| 2824 ExpectString(code, "PASSED"); |
| 2825 } |
| 2826 |
| 2827 |
| 2532 THREADED_TEST(MultiContexts) { | 2828 THREADED_TEST(MultiContexts) { |
| 2533 v8::HandleScope scope; | 2829 v8::HandleScope scope; |
| 2534 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(); | 2830 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(); |
| 2535 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler)); | 2831 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler)); |
| 2536 | 2832 |
| 2537 Local<String> password = v8_str("Password"); | 2833 Local<String> password = v8_str("Password"); |
| 2538 | 2834 |
| 2539 // Create an environment | 2835 // Create an environment |
| 2540 LocalContext context0(0, templ); | 2836 LocalContext context0(0, templ); |
| 2541 context0->SetSecurityToken(password); | 2837 context0->SetSecurityToken(password); |
| (...skipping 2295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4837 | 5133 |
| 4838 // Getting the prototype of o0 should get the first visible one | 5134 // Getting the prototype of o0 should get the first visible one |
| 4839 // which is o3. Therefore, z should not be defined on the prototype | 5135 // which is o3. Therefore, z should not be defined on the prototype |
| 4840 // object. | 5136 // object. |
| 4841 Local<Value> proto = o0->Get(v8_str("__proto__")); | 5137 Local<Value> proto = o0->Get(v8_str("__proto__")); |
| 4842 CHECK(proto->IsObject()); | 5138 CHECK(proto->IsObject()); |
| 4843 CHECK(Local<v8::Object>::Cast(proto)->Get(v8_str("z"))->IsUndefined()); | 5139 CHECK(Local<v8::Object>::Cast(proto)->Get(v8_str("z"))->IsUndefined()); |
| 4844 } | 5140 } |
| 4845 | 5141 |
| 4846 | 5142 |
| 5143 THREADED_TEST(SetPrototype) { |
| 5144 v8::HandleScope handle_scope; |
| 5145 LocalContext context; |
| 5146 |
| 5147 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(); |
| 5148 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0)); |
| 5149 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(); |
| 5150 t1->SetHiddenPrototype(true); |
| 5151 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1)); |
| 5152 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(); |
| 5153 t2->SetHiddenPrototype(true); |
| 5154 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2)); |
| 5155 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(); |
| 5156 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3)); |
| 5157 |
| 5158 Local<v8::Object> o0 = t0->GetFunction()->NewInstance(); |
| 5159 Local<v8::Object> o1 = t1->GetFunction()->NewInstance(); |
| 5160 Local<v8::Object> o2 = t2->GetFunction()->NewInstance(); |
| 5161 Local<v8::Object> o3 = t3->GetFunction()->NewInstance(); |
| 5162 |
| 5163 // Setting the prototype on an object does not skip hidden prototypes. |
| 5164 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value()); |
| 5165 CHECK(o0->SetPrototype(o1)); |
| 5166 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value()); |
| 5167 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value()); |
| 5168 CHECK(o1->SetPrototype(o2)); |
| 5169 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value()); |
| 5170 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value()); |
| 5171 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value()); |
| 5172 CHECK(o2->SetPrototype(o3)); |
| 5173 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value()); |
| 5174 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value()); |
| 5175 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value()); |
| 5176 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value()); |
| 5177 |
| 5178 // Getting the prototype of o0 should get the first visible one |
| 5179 // which is o3. Therefore, z should not be defined on the prototype |
| 5180 // object. |
| 5181 Local<Value> proto = o0->Get(v8_str("__proto__")); |
| 5182 CHECK(proto->IsObject()); |
| 5183 CHECK_EQ(v8::Handle<v8::Object>::Cast(proto), o3); |
| 5184 |
| 5185 // However, Object::GetPrototype ignores hidden prototype. |
| 5186 Local<Value> proto0 = o0->GetPrototype(); |
| 5187 CHECK(proto0->IsObject()); |
| 5188 CHECK_EQ(v8::Handle<v8::Object>::Cast(proto0), o1); |
| 5189 |
| 5190 Local<Value> proto1 = o1->GetPrototype(); |
| 5191 CHECK(proto1->IsObject()); |
| 5192 CHECK_EQ(v8::Handle<v8::Object>::Cast(proto1), o2); |
| 5193 |
| 5194 Local<Value> proto2 = o2->GetPrototype(); |
| 5195 CHECK(proto2->IsObject()); |
| 5196 CHECK_EQ(v8::Handle<v8::Object>::Cast(proto2), o3); |
| 5197 } |
| 5198 |
| 5199 |
| 5200 THREADED_TEST(SetPrototypeThrows) { |
| 5201 v8::HandleScope handle_scope; |
| 5202 LocalContext context; |
| 5203 |
| 5204 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); |
| 5205 |
| 5206 Local<v8::Object> o0 = t->GetFunction()->NewInstance(); |
| 5207 Local<v8::Object> o1 = t->GetFunction()->NewInstance(); |
| 5208 |
| 5209 CHECK(o0->SetPrototype(o1)); |
| 5210 // If setting the prototype leads to the cycle, SetPrototype should |
| 5211 // return false and keep VM in sane state. |
| 5212 v8::TryCatch try_catch; |
| 5213 CHECK(!o1->SetPrototype(o0)); |
| 5214 CHECK(!try_catch.HasCaught()); |
| 5215 ASSERT(!i::Top::has_pending_exception()); |
| 5216 |
| 5217 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value()); |
| 5218 } |
| 5219 |
| 5220 |
| 4847 THREADED_TEST(GetterSetterExceptions) { | 5221 THREADED_TEST(GetterSetterExceptions) { |
| 4848 v8::HandleScope handle_scope; | 5222 v8::HandleScope handle_scope; |
| 4849 LocalContext context; | 5223 LocalContext context; |
| 4850 CompileRun( | 5224 CompileRun( |
| 4851 "function Foo() { };" | 5225 "function Foo() { };" |
| 4852 "function Throw() { throw 5; };" | 5226 "function Throw() { throw 5; };" |
| 4853 "var x = { };" | 5227 "var x = { };" |
| 4854 "x.__defineSetter__('set', Throw);" | 5228 "x.__defineSetter__('set', Throw);" |
| 4855 "x.__defineGetter__('get', Throw);"); | 5229 "x.__defineGetter__('get', Throw);"); |
| 4856 Local<v8::Object> x = | 5230 Local<v8::Object> x = |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5071 | 5445 |
| 5072 // Trigger lazy loading in other context. | 5446 // Trigger lazy loading in other context. |
| 5073 Local<Script> script = | 5447 Local<Script> script = |
| 5074 Script::Compile(v8_str("other.eval('new Date(42)')")); | 5448 Script::Compile(v8_str("other.eval('new Date(42)')")); |
| 5075 Local<Value> value = script->Run(); | 5449 Local<Value> value = script->Run(); |
| 5076 CHECK_EQ(42.0, value->NumberValue()); | 5450 CHECK_EQ(42.0, value->NumberValue()); |
| 5077 } | 5451 } |
| 5078 | 5452 |
| 5079 | 5453 |
| 5080 static v8::Handle<Value> call_as_function(const v8::Arguments& args) { | 5454 static v8::Handle<Value> call_as_function(const v8::Arguments& args) { |
| 5081 //ApiTestFuzzer::Fuzz(); | 5455 ApiTestFuzzer::Fuzz(); |
| 5082 if (args.IsConstructCall()) { | 5456 if (args.IsConstructCall()) { |
| 5083 if (args[0]->IsInt32()) { | 5457 if (args[0]->IsInt32()) { |
| 5084 return v8_num(-args[0]->Int32Value()); | 5458 return v8_num(-args[0]->Int32Value()); |
| 5085 } | 5459 } |
| 5086 } | 5460 } |
| 5087 | 5461 |
| 5088 return args[0]; | 5462 return args[0]; |
| 5089 } | 5463 } |
| 5090 | 5464 |
| 5091 | 5465 |
| (...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5884 " for (var i = 0; i < 10; i++) {" | 6258 " for (var i = 0; i < 10; i++) {" |
| 5885 " result += o.parseFloat('239');" | 6259 " result += o.parseFloat('239');" |
| 5886 " }" | 6260 " }" |
| 5887 " result" | 6261 " result" |
| 5888 "} catch(e) {" | 6262 "} catch(e) {" |
| 5889 " e" | 6263 " e" |
| 5890 "};"); | 6264 "};"); |
| 5891 CHECK_EQ(239 * 10, value->Int32Value()); | 6265 CHECK_EQ(239 * 10, value->Int32Value()); |
| 5892 } | 6266 } |
| 5893 | 6267 |
| 6268 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, |
| 6269 const AccessorInfo& info) { |
| 6270 ApiTestFuzzer::Fuzz(); |
| 6271 int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); |
| 6272 ++(*call_count); |
| 6273 if ((*call_count) % 20 == 0) { |
| 6274 v8::internal::Heap::CollectAllGarbage(true); |
| 6275 } |
| 6276 return v8::Handle<Value>(); |
| 6277 } |
| 6278 |
| 6279 static v8::Handle<Value> FastApiCallback_TrivialSignature( |
| 6280 const v8::Arguments& args) { |
| 6281 ApiTestFuzzer::Fuzz(); |
| 6282 CHECK_EQ(args.This(), args.Holder()); |
| 6283 CHECK(args.Data()->Equals(v8_str("method_data"))); |
| 6284 return v8::Integer::New(args[0]->Int32Value() + 1); |
| 6285 } |
| 6286 |
| 6287 static v8::Handle<Value> FastApiCallback_SimpleSignature( |
| 6288 const v8::Arguments& args) { |
| 6289 ApiTestFuzzer::Fuzz(); |
| 6290 CHECK_EQ(args.This()->GetPrototype(), args.Holder()); |
| 6291 CHECK(args.Data()->Equals(v8_str("method_data"))); |
| 6292 // Note, we're using HasRealNamedProperty instead of Has to avoid |
| 6293 // invoking the interceptor again. |
| 6294 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo"))); |
| 6295 return v8::Integer::New(args[0]->Int32Value() + 1); |
| 6296 } |
| 6297 |
| 6298 // Helper to maximize the odds of object moving. |
| 6299 static void GenerateSomeGarbage() { |
| 6300 CompileRun( |
| 6301 "var garbage;" |
| 6302 "for (var i = 0; i < 1000; i++) {" |
| 6303 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];" |
| 6304 "}" |
| 6305 "garbage = undefined;"); |
| 6306 } |
| 6307 |
| 6308 THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) { |
| 6309 int interceptor_call_count = 0; |
| 6310 v8::HandleScope scope; |
| 6311 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6312 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6313 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature, |
| 6314 v8_str("method_data"), |
| 6315 v8::Handle<v8::Signature>()); |
| 6316 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6317 proto_templ->Set(v8_str("method"), method_templ); |
| 6318 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6319 templ->SetNamedPropertyHandler(InterceptorCallICFastApi, |
| 6320 NULL, NULL, NULL, NULL, |
| 6321 v8::External::Wrap(&interceptor_call_count)); |
| 6322 LocalContext context; |
| 6323 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6324 GenerateSomeGarbage(); |
| 6325 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6326 v8::Handle<Value> value = CompileRun( |
| 6327 "var result = 0;" |
| 6328 "for (var i = 0; i < 100; i++) {" |
| 6329 " result = o.method(41);" |
| 6330 "}"); |
| 6331 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6332 CHECK_EQ(100, interceptor_call_count); |
| 6333 } |
| 6334 |
| 6335 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) { |
| 6336 int interceptor_call_count = 0; |
| 6337 v8::HandleScope scope; |
| 6338 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6339 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6340 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6341 v8_str("method_data"), |
| 6342 v8::Signature::New(fun_templ)); |
| 6343 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6344 proto_templ->Set(v8_str("method"), method_templ); |
| 6345 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6346 templ->SetNamedPropertyHandler(InterceptorCallICFastApi, |
| 6347 NULL, NULL, NULL, NULL, |
| 6348 v8::External::Wrap(&interceptor_call_count)); |
| 6349 LocalContext context; |
| 6350 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6351 GenerateSomeGarbage(); |
| 6352 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6353 v8::Handle<Value> value = CompileRun( |
| 6354 "o.foo = 17;" |
| 6355 "var receiver = {};" |
| 6356 "receiver.__proto__ = o;" |
| 6357 "var result = 0;" |
| 6358 "for (var i = 0; i < 100; i++) {" |
| 6359 " result = receiver.method(41);" |
| 6360 "}"); |
| 6361 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6362 CHECK_EQ(100, interceptor_call_count); |
| 6363 } |
| 6364 |
| 6365 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) { |
| 6366 int interceptor_call_count = 0; |
| 6367 v8::HandleScope scope; |
| 6368 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6369 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6370 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6371 v8_str("method_data"), |
| 6372 v8::Signature::New(fun_templ)); |
| 6373 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6374 proto_templ->Set(v8_str("method"), method_templ); |
| 6375 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6376 templ->SetNamedPropertyHandler(InterceptorCallICFastApi, |
| 6377 NULL, NULL, NULL, NULL, |
| 6378 v8::External::Wrap(&interceptor_call_count)); |
| 6379 LocalContext context; |
| 6380 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6381 GenerateSomeGarbage(); |
| 6382 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6383 v8::Handle<Value> value = CompileRun( |
| 6384 "o.foo = 17;" |
| 6385 "var receiver = {};" |
| 6386 "receiver.__proto__ = o;" |
| 6387 "var result = 0;" |
| 6388 "var saved_result = 0;" |
| 6389 "for (var i = 0; i < 100; i++) {" |
| 6390 " result = receiver.method(41);" |
| 6391 " if (i == 50) {" |
| 6392 " saved_result = result;" |
| 6393 " receiver = {method: function(x) { return x - 1 }};" |
| 6394 " }" |
| 6395 "}"); |
| 6396 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6397 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
| 6398 CHECK_GE(interceptor_call_count, 50); |
| 6399 } |
| 6400 |
| 6401 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) { |
| 6402 int interceptor_call_count = 0; |
| 6403 v8::HandleScope scope; |
| 6404 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6405 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6406 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6407 v8_str("method_data"), |
| 6408 v8::Signature::New(fun_templ)); |
| 6409 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6410 proto_templ->Set(v8_str("method"), method_templ); |
| 6411 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6412 templ->SetNamedPropertyHandler(InterceptorCallICFastApi, |
| 6413 NULL, NULL, NULL, NULL, |
| 6414 v8::External::Wrap(&interceptor_call_count)); |
| 6415 LocalContext context; |
| 6416 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6417 GenerateSomeGarbage(); |
| 6418 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6419 v8::Handle<Value> value = CompileRun( |
| 6420 "o.foo = 17;" |
| 6421 "var receiver = {};" |
| 6422 "receiver.__proto__ = o;" |
| 6423 "var result = 0;" |
| 6424 "var saved_result = 0;" |
| 6425 "for (var i = 0; i < 100; i++) {" |
| 6426 " result = receiver.method(41);" |
| 6427 " if (i == 50) {" |
| 6428 " saved_result = result;" |
| 6429 " o.method = function(x) { return x - 1 };" |
| 6430 " }" |
| 6431 "}"); |
| 6432 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6433 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
| 6434 CHECK_GE(interceptor_call_count, 50); |
| 6435 } |
| 6436 |
| 6437 THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { |
| 6438 int interceptor_call_count = 0; |
| 6439 v8::HandleScope scope; |
| 6440 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6441 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6442 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6443 v8_str("method_data"), |
| 6444 v8::Signature::New(fun_templ)); |
| 6445 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6446 proto_templ->Set(v8_str("method"), method_templ); |
| 6447 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6448 templ->SetNamedPropertyHandler(InterceptorCallICFastApi, |
| 6449 NULL, NULL, NULL, NULL, |
| 6450 v8::External::Wrap(&interceptor_call_count)); |
| 6451 LocalContext context; |
| 6452 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6453 GenerateSomeGarbage(); |
| 6454 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6455 v8::TryCatch try_catch; |
| 6456 v8::Handle<Value> value = CompileRun( |
| 6457 "o.foo = 17;" |
| 6458 "var receiver = {};" |
| 6459 "receiver.__proto__ = o;" |
| 6460 "var result = 0;" |
| 6461 "var saved_result = 0;" |
| 6462 "for (var i = 0; i < 100; i++) {" |
| 6463 " result = receiver.method(41);" |
| 6464 " if (i == 50) {" |
| 6465 " saved_result = result;" |
| 6466 " receiver = {method: receiver.method};" |
| 6467 " }" |
| 6468 "}"); |
| 6469 CHECK(try_catch.HasCaught()); |
| 6470 CHECK_EQ(v8_str("TypeError: Illegal invocation"), |
| 6471 try_catch.Exception()->ToString()); |
| 6472 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
| 6473 CHECK_GE(interceptor_call_count, 50); |
| 6474 } |
| 6475 |
| 6476 THREADED_TEST(CallICFastApi_TrivialSignature) { |
| 6477 v8::HandleScope scope; |
| 6478 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6479 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6480 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature, |
| 6481 v8_str("method_data"), |
| 6482 v8::Handle<v8::Signature>()); |
| 6483 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6484 proto_templ->Set(v8_str("method"), method_templ); |
| 6485 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6486 LocalContext context; |
| 6487 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6488 GenerateSomeGarbage(); |
| 6489 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6490 v8::Handle<Value> value = CompileRun( |
| 6491 "var result = 0;" |
| 6492 "for (var i = 0; i < 100; i++) {" |
| 6493 " result = o.method(41);" |
| 6494 "}"); |
| 6495 |
| 6496 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6497 } |
| 6498 |
| 6499 THREADED_TEST(CallICFastApi_SimpleSignature) { |
| 6500 v8::HandleScope scope; |
| 6501 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6502 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6503 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6504 v8_str("method_data"), |
| 6505 v8::Signature::New(fun_templ)); |
| 6506 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6507 proto_templ->Set(v8_str("method"), method_templ); |
| 6508 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6509 LocalContext context; |
| 6510 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6511 GenerateSomeGarbage(); |
| 6512 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6513 v8::Handle<Value> value = CompileRun( |
| 6514 "o.foo = 17;" |
| 6515 "var receiver = {};" |
| 6516 "receiver.__proto__ = o;" |
| 6517 "var result = 0;" |
| 6518 "for (var i = 0; i < 100; i++) {" |
| 6519 " result = receiver.method(41);" |
| 6520 "}"); |
| 6521 |
| 6522 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6523 } |
| 6524 |
| 6525 THREADED_TEST(CallICFastApi_SimpleSignature_Miss) { |
| 6526 v8::HandleScope scope; |
| 6527 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 6528 v8::Handle<v8::FunctionTemplate> method_templ = |
| 6529 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature, |
| 6530 v8_str("method_data"), |
| 6531 v8::Signature::New(fun_templ)); |
| 6532 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); |
| 6533 proto_templ->Set(v8_str("method"), method_templ); |
| 6534 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); |
| 6535 LocalContext context; |
| 6536 v8::Handle<v8::Function> fun = fun_templ->GetFunction(); |
| 6537 GenerateSomeGarbage(); |
| 6538 context->Global()->Set(v8_str("o"), fun->NewInstance()); |
| 6539 v8::Handle<Value> value = CompileRun( |
| 6540 "o.foo = 17;" |
| 6541 "var receiver = {};" |
| 6542 "receiver.__proto__ = o;" |
| 6543 "var result = 0;" |
| 6544 "var saved_result = 0;" |
| 6545 "for (var i = 0; i < 100; i++) {" |
| 6546 " result = receiver.method(41);" |
| 6547 " if (i == 50) {" |
| 6548 " saved_result = result;" |
| 6549 " receiver = {method: function(x) { return x - 1 }};" |
| 6550 " }" |
| 6551 "}"); |
| 6552 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); |
| 6553 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); |
| 6554 } |
| 6555 |
| 5894 | 6556 |
| 5895 static int interceptor_call_count = 0; | 6557 static int interceptor_call_count = 0; |
| 5896 | 6558 |
| 5897 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name, | 6559 static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name, |
| 5898 const AccessorInfo& info) { | 6560 const AccessorInfo& info) { |
| 5899 ApiTestFuzzer::Fuzz(); | 6561 ApiTestFuzzer::Fuzz(); |
| 5900 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) { | 6562 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) { |
| 5901 return call_ic_function2; | 6563 return call_ic_function2; |
| 5902 } | 6564 } |
| 5903 return v8::Handle<Value>(); | 6565 return v8::Handle<Value>(); |
| (...skipping 3016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8920 CompileRun(source_exception); | 9582 CompileRun(source_exception); |
| 8921 other_context->Exit(); | 9583 other_context->Exit(); |
| 8922 v8::internal::Heap::CollectAllGarbage(false); | 9584 v8::internal::Heap::CollectAllGarbage(false); |
| 8923 if (GetGlobalObjectsCount() == 1) break; | 9585 if (GetGlobalObjectsCount() == 1) break; |
| 8924 } | 9586 } |
| 8925 CHECK_GE(2, gc_count); | 9587 CHECK_GE(2, gc_count); |
| 8926 CHECK_EQ(1, GetGlobalObjectsCount()); | 9588 CHECK_EQ(1, GetGlobalObjectsCount()); |
| 8927 | 9589 |
| 8928 other_context.Dispose(); | 9590 other_context.Dispose(); |
| 8929 } | 9591 } |
| 9592 |
| 9593 |
| 9594 THREADED_TEST(ScriptOrigin) { |
| 9595 v8::HandleScope scope; |
| 9596 LocalContext env; |
| 9597 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test")); |
| 9598 v8::Handle<v8::String> script = v8::String::New( |
| 9599 "function f() {}\n\nfunction g() {}"); |
| 9600 v8::Script::Compile(script, &origin)->Run(); |
| 9601 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( |
| 9602 env->Global()->Get(v8::String::New("f"))); |
| 9603 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast( |
| 9604 env->Global()->Get(v8::String::New("g"))); |
| 9605 |
| 9606 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin(); |
| 9607 CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName())); |
| 9608 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value()); |
| 9609 |
| 9610 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin(); |
| 9611 CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName())); |
| 9612 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value()); |
| 9613 } |
| 9614 |
| 9615 |
| 9616 THREADED_TEST(ScriptLineNumber) { |
| 9617 v8::HandleScope scope; |
| 9618 LocalContext env; |
| 9619 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test")); |
| 9620 v8::Handle<v8::String> script = v8::String::New( |
| 9621 "function f() {}\n\nfunction g() {}"); |
| 9622 v8::Script::Compile(script, &origin)->Run(); |
| 9623 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( |
| 9624 env->Global()->Get(v8::String::New("f"))); |
| 9625 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast( |
| 9626 env->Global()->Get(v8::String::New("g"))); |
| 9627 CHECK_EQ(0, f->GetScriptLineNumber()); |
| 9628 CHECK_EQ(2, g->GetScriptLineNumber()); |
| 9629 } |
| 9630 |
| 9631 |
| 9632 static v8::Handle<Value> GetterWhichReturns42(Local<String> name, |
| 9633 const AccessorInfo& info) { |
| 9634 return v8_num(42); |
| 9635 } |
| 9636 |
| 9637 |
| 9638 static void SetterWhichSetsYOnThisTo23(Local<String> name, |
| 9639 Local<Value> value, |
| 9640 const AccessorInfo& info) { |
| 9641 info.This()->Set(v8_str("y"), v8_num(23)); |
| 9642 } |
| 9643 |
| 9644 |
| 9645 THREADED_TEST(SetterOnConstructorPrototype) { |
| 9646 v8::HandleScope scope; |
| 9647 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 9648 templ->SetAccessor(v8_str("x"), |
| 9649 GetterWhichReturns42, |
| 9650 SetterWhichSetsYOnThisTo23); |
| 9651 LocalContext context; |
| 9652 context->Global()->Set(v8_str("P"), templ->NewInstance()); |
| 9653 CompileRun("function C1() {" |
| 9654 " this.x = 23;" |
| 9655 "};" |
| 9656 "C1.prototype = P;" |
| 9657 "function C2() {" |
| 9658 " this.x = 23" |
| 9659 "};" |
| 9660 "C2.prototype = { };" |
| 9661 "C2.prototype.__proto__ = P;"); |
| 9662 |
| 9663 v8::Local<v8::Script> script; |
| 9664 script = v8::Script::Compile(v8_str("new C1();")); |
| 9665 for (int i = 0; i < 10; i++) { |
| 9666 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run()); |
| 9667 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value()); |
| 9668 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value()); |
| 9669 } |
| 9670 |
| 9671 script = v8::Script::Compile(v8_str("new C2();")); |
| 9672 for (int i = 0; i < 10; i++) { |
| 9673 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run()); |
| 9674 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value()); |
| 9675 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value()); |
| 9676 } |
| 9677 } |
| 9678 |
| 9679 |
| 9680 static v8::Handle<Value> NamedPropertyGetterWhichReturns42( |
| 9681 Local<String> name, const AccessorInfo& info) { |
| 9682 return v8_num(42); |
| 9683 } |
| 9684 |
| 9685 |
| 9686 static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23( |
| 9687 Local<String> name, Local<Value> value, const AccessorInfo& info) { |
| 9688 if (name->Equals(v8_str("x"))) { |
| 9689 info.This()->Set(v8_str("y"), v8_num(23)); |
| 9690 } |
| 9691 return v8::Handle<Value>(); |
| 9692 } |
| 9693 |
| 9694 |
| 9695 THREADED_TEST(InterceptorOnConstructorPrototype) { |
| 9696 v8::HandleScope scope; |
| 9697 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 9698 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42, |
| 9699 NamedPropertySetterWhichSetsYOnThisTo23); |
| 9700 LocalContext context; |
| 9701 context->Global()->Set(v8_str("P"), templ->NewInstance()); |
| 9702 CompileRun("function C1() {" |
| 9703 " this.x = 23;" |
| 9704 "};" |
| 9705 "C1.prototype = P;" |
| 9706 "function C2() {" |
| 9707 " this.x = 23" |
| 9708 "};" |
| 9709 "C2.prototype = { };" |
| 9710 "C2.prototype.__proto__ = P;"); |
| 9711 |
| 9712 v8::Local<v8::Script> script; |
| 9713 script = v8::Script::Compile(v8_str("new C1();")); |
| 9714 for (int i = 0; i < 10; i++) { |
| 9715 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run()); |
| 9716 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value()); |
| 9717 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value()); |
| 9718 } |
| 9719 |
| 9720 script = v8::Script::Compile(v8_str("new C2();")); |
| 9721 for (int i = 0; i < 10; i++) { |
| 9722 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run()); |
| 9723 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value()); |
| 9724 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value()); |
| 9725 } |
| 9726 } |
| OLD | NEW |