| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 using ::v8::ObjectTemplate; | 65 using ::v8::ObjectTemplate; |
| 66 using ::v8::Persistent; | 66 using ::v8::Persistent; |
| 67 using ::v8::Script; | 67 using ::v8::Script; |
| 68 using ::v8::StackTrace; | 68 using ::v8::StackTrace; |
| 69 using ::v8::String; | 69 using ::v8::String; |
| 70 using ::v8::TryCatch; | 70 using ::v8::TryCatch; |
| 71 using ::v8::Undefined; | 71 using ::v8::Undefined; |
| 72 using ::v8::V8; | 72 using ::v8::V8; |
| 73 using ::v8::Value; | 73 using ::v8::Value; |
| 74 | 74 |
| 75 namespace i = ::i; | |
| 76 | |
| 77 | 75 |
| 78 static void ExpectString(const char* code, const char* expected) { | 76 static void ExpectString(const char* code, const char* expected) { |
| 79 Local<Value> result = CompileRun(code); | 77 Local<Value> result = CompileRun(code); |
| 80 CHECK(result->IsString()); | 78 CHECK(result->IsString()); |
| 81 String::AsciiValue ascii(result); | 79 String::AsciiValue ascii(result); |
| 82 CHECK_EQ(expected, *ascii); | 80 CHECK_EQ(expected, *ascii); |
| 83 } | 81 } |
| 84 | 82 |
| 85 | 83 |
| 86 static void ExpectBoolean(const char* code, bool expected) { | 84 static void ExpectBoolean(const char* code, bool expected) { |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 Local<Script> script = Script::Compile(source); | 389 Local<Script> script = Script::Compile(source); |
| 392 Local<Value> value = script->Run(); | 390 Local<Value> value = script->Run(); |
| 393 CHECK(value->IsNumber()); | 391 CHECK(value->IsNumber()); |
| 394 CHECK_EQ(7, value->Int32Value()); | 392 CHECK_EQ(7, value->Int32Value()); |
| 395 CHECK(source->IsExternal()); | 393 CHECK(source->IsExternal()); |
| 396 CHECK_EQ(resource, | 394 CHECK_EQ(resource, |
| 397 static_cast<TestResource*>(source->GetExternalStringResource())); | 395 static_cast<TestResource*>(source->GetExternalStringResource())); |
| 398 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | 396 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 399 CHECK_EQ(0, dispose_count); | 397 CHECK_EQ(0, dispose_count); |
| 400 } | 398 } |
| 401 i::Isolate::Current()->compilation_cache()->Clear(); | 399 v8::internal::Isolate::Current()->compilation_cache()->Clear(); |
| 402 HEAP->CollectAllAvailableGarbage(); | 400 HEAP->CollectAllAvailableGarbage(); |
| 403 CHECK_EQ(1, dispose_count); | 401 CHECK_EQ(1, dispose_count); |
| 404 } | 402 } |
| 405 | 403 |
| 406 | 404 |
| 407 THREADED_TEST(ScriptUsingAsciiStringResource) { | 405 THREADED_TEST(ScriptUsingAsciiStringResource) { |
| 408 int dispose_count = 0; | 406 int dispose_count = 0; |
| 409 const char* c_source = "1 + 2 * 3"; | 407 const char* c_source = "1 + 2 * 3"; |
| 410 { | 408 { |
| 411 v8::HandleScope scope; | 409 v8::HandleScope scope; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 440 &dispose_count)); | 438 &dispose_count)); |
| 441 CHECK(success); | 439 CHECK(success); |
| 442 Local<Script> script = Script::Compile(source); | 440 Local<Script> script = Script::Compile(source); |
| 443 Local<Value> value = script->Run(); | 441 Local<Value> value = script->Run(); |
| 444 CHECK(value->IsNumber()); | 442 CHECK(value->IsNumber()); |
| 445 CHECK_EQ(7, value->Int32Value()); | 443 CHECK_EQ(7, value->Int32Value()); |
| 446 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | 444 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 447 CHECK_EQ(0, dispose_count); | 445 CHECK_EQ(0, dispose_count); |
| 448 } | 446 } |
| 449 i::Isolate::Current()->compilation_cache()->Clear(); | 447 i::Isolate::Current()->compilation_cache()->Clear(); |
| 450 HEAP->CollectAllAvailableGarbage(); | 448 HEAP->CollectAllGarbage(false); |
| 451 CHECK_EQ(1, dispose_count); | 449 CHECK_EQ(1, dispose_count); |
| 452 } | 450 } |
| 453 | 451 |
| 454 | 452 |
| 455 THREADED_TEST(ScriptMakingExternalAsciiString) { | 453 THREADED_TEST(ScriptMakingExternalAsciiString) { |
| 456 int dispose_count = 0; | 454 int dispose_count = 0; |
| 457 const char* c_source = "1 + 2 * 3"; | 455 const char* c_source = "1 + 2 * 3"; |
| 458 { | 456 { |
| 459 v8::HandleScope scope; | 457 v8::HandleScope scope; |
| 460 LocalContext env; | 458 LocalContext env; |
| 461 Local<String> source = v8_str(c_source); | 459 Local<String> source = v8_str(c_source); |
| 462 // Trigger GCs so that the newly allocated string moves to old gen. | 460 // Trigger GCs so that the newly allocated string moves to old gen. |
| 463 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now | 461 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 464 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now | 462 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 465 bool success = source->MakeExternal( | 463 bool success = source->MakeExternal( |
| 466 new TestAsciiResource(i::StrDup(c_source), &dispose_count)); | 464 new TestAsciiResource(i::StrDup(c_source), &dispose_count)); |
| 467 CHECK(success); | 465 CHECK(success); |
| 468 Local<Script> script = Script::Compile(source); | 466 Local<Script> script = Script::Compile(source); |
| 469 Local<Value> value = script->Run(); | 467 Local<Value> value = script->Run(); |
| 470 CHECK(value->IsNumber()); | 468 CHECK(value->IsNumber()); |
| 471 CHECK_EQ(7, value->Int32Value()); | 469 CHECK_EQ(7, value->Int32Value()); |
| 472 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | 470 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 473 CHECK_EQ(0, dispose_count); | 471 CHECK_EQ(0, dispose_count); |
| 474 } | 472 } |
| 475 i::Isolate::Current()->compilation_cache()->Clear(); | 473 i::Isolate::Current()->compilation_cache()->Clear(); |
| 476 HEAP->CollectAllAvailableGarbage(); | 474 HEAP->CollectAllGarbage(false); |
| 477 CHECK_EQ(1, dispose_count); | 475 CHECK_EQ(1, dispose_count); |
| 478 } | 476 } |
| 479 | 477 |
| 480 | 478 |
| 481 TEST(MakingExternalStringConditions) { | 479 TEST(MakingExternalStringConditions) { |
| 482 v8::HandleScope scope; | 480 v8::HandleScope scope; |
| 483 LocalContext env; | 481 LocalContext env; |
| 484 | 482 |
| 485 // Free some space in the new space so that we can check freshness. | 483 // Free some space in the new space so that we can check freshness. |
| 486 HEAP->CollectGarbage(i::NEW_SPACE); | 484 HEAP->CollectGarbage(i::NEW_SPACE); |
| (...skipping 3139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3626 "obj;")); | 3624 "obj;")); |
| 3627 Local<Value> result = create_unboxed_double_script->Run(); | 3625 Local<Value> result = create_unboxed_double_script->Run(); |
| 3628 CHECK(result->ToObject()->HasRealIndexedProperty(2000)); | 3626 CHECK(result->ToObject()->HasRealIndexedProperty(2000)); |
| 3629 Local<Script> key_count_check = Script::Compile(v8_str( | 3627 Local<Script> key_count_check = Script::Compile(v8_str( |
| 3630 "key_count;")); | 3628 "key_count;")); |
| 3631 result = key_count_check->Run(); | 3629 result = key_count_check->Run(); |
| 3632 CHECK_EQ(v8_num(40013), result); | 3630 CHECK_EQ(v8_num(40013), result); |
| 3633 } | 3631 } |
| 3634 | 3632 |
| 3635 | 3633 |
| 3634 Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator( |
| 3635 const AccessorInfo& info) { |
| 3636 // Force the list of returned keys to be stored in a Arguments object. |
| 3637 Local<Script> indexed_property_names_script = Script::Compile(v8_str( |
| 3638 "function f(w,x) {" |
| 3639 " return arguments;" |
| 3640 "}" |
| 3641 "keys = f(0, 1, 2, 3);" |
| 3642 "keys;")); |
| 3643 Local<Value> result = indexed_property_names_script->Run(); |
| 3644 return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result))); |
| 3645 } |
| 3646 |
| 3647 |
| 3648 static v8::Handle<Value> NonStrictIndexedPropertyGetter( |
| 3649 uint32_t index, |
| 3650 const AccessorInfo& info) { |
| 3651 ApiTestFuzzer::Fuzz(); |
| 3652 if (index < 4) { |
| 3653 return v8::Handle<Value>(v8_num(index)); |
| 3654 } |
| 3655 return v8::Handle<Value>(); |
| 3656 } |
| 3657 |
| 3658 |
| 3659 // Make sure that the the interceptor code in the runtime properly handles |
| 3660 // merging property name lists for non-string arguments arrays. |
| 3661 THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) { |
| 3662 v8::HandleScope scope; |
| 3663 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| 3664 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter, |
| 3665 0, |
| 3666 0, |
| 3667 0, |
| 3668 NonStrictArgsIndexedPropertyEnumerator); |
| 3669 LocalContext context; |
| 3670 context->Global()->Set(v8_str("obj"), templ->NewInstance()); |
| 3671 Local<Script> create_args_script = |
| 3672 Script::Compile(v8_str( |
| 3673 "var key_count = 0;" |
| 3674 "for (x in obj) {key_count++;} key_count;")); |
| 3675 Local<Value> result = create_args_script->Run(); |
| 3676 CHECK_EQ(v8_num(4), result); |
| 3677 } |
| 3678 |
| 3679 |
| 3636 static v8::Handle<Value> IdentityIndexedPropertyGetter( | 3680 static v8::Handle<Value> IdentityIndexedPropertyGetter( |
| 3637 uint32_t index, | 3681 uint32_t index, |
| 3638 const AccessorInfo& info) { | 3682 const AccessorInfo& info) { |
| 3639 return v8::Integer::NewFromUnsigned(index); | 3683 return v8::Integer::NewFromUnsigned(index); |
| 3640 } | 3684 } |
| 3641 | 3685 |
| 3642 | 3686 |
| 3643 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) { | 3687 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) { |
| 3644 v8::HandleScope scope; | 3688 v8::HandleScope scope; |
| 3645 Local<ObjectTemplate> templ = ObjectTemplate::New(); | 3689 Local<ObjectTemplate> templ = ObjectTemplate::New(); |
| (...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5259 | 5303 |
| 5260 memset(buf, 0x1, sizeof(buf)); | 5304 memset(buf, 0x1, sizeof(buf)); |
| 5261 memset(wbuf, 0x1, sizeof(wbuf)); | 5305 memset(wbuf, 0x1, sizeof(wbuf)); |
| 5262 len = str->WriteAscii(buf, 3, 1); | 5306 len = str->WriteAscii(buf, 3, 1); |
| 5263 CHECK_EQ(1, len); | 5307 CHECK_EQ(1, len); |
| 5264 len = str->Write(wbuf, 3, 1); | 5308 len = str->Write(wbuf, 3, 1); |
| 5265 CHECK_EQ(1, len); | 5309 CHECK_EQ(1, len); |
| 5266 CHECK_EQ(0, strncmp("d\1", buf, 2)); | 5310 CHECK_EQ(0, strncmp("d\1", buf, 2)); |
| 5267 uint16_t answer7[] = {'d', 0x101}; | 5311 uint16_t answer7[] = {'d', 0x101}; |
| 5268 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2)); | 5312 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2)); |
| 5313 |
| 5314 memset(wbuf, 0x1, sizeof(wbuf)); |
| 5315 wbuf[5] = 'X'; |
| 5316 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION); |
| 5317 CHECK_EQ(5, len); |
| 5318 CHECK_EQ('X', wbuf[5]); |
| 5319 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'}; |
| 5320 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'}; |
| 5321 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5)); |
| 5322 CHECK_NE(0, StrCmp16(answer8b, wbuf)); |
| 5323 wbuf[5] = '\0'; |
| 5324 CHECK_EQ(0, StrCmp16(answer8b, wbuf)); |
| 5325 |
| 5326 memset(buf, 0x1, sizeof(buf)); |
| 5327 buf[5] = 'X'; |
| 5328 len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION); |
| 5329 CHECK_EQ(5, len); |
| 5330 CHECK_EQ('X', buf[5]); |
| 5331 CHECK_EQ(0, strncmp("abcde", buf, 5)); |
| 5332 CHECK_NE(0, strcmp("abcde", buf)); |
| 5333 buf[5] = '\0'; |
| 5334 CHECK_EQ(0, strcmp("abcde", buf)); |
| 5335 |
| 5336 memset(utf8buf, 0x1, sizeof(utf8buf)); |
| 5337 utf8buf[8] = 'X'; |
| 5338 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen, |
| 5339 String::NO_NULL_TERMINATION); |
| 5340 CHECK_EQ(8, len); |
| 5341 CHECK_EQ('X', utf8buf[8]); |
| 5342 CHECK_EQ(5, charlen); |
| 5343 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8)); |
| 5344 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203")); |
| 5345 utf8buf[8] = '\0'; |
| 5346 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203")); |
| 5269 } | 5347 } |
| 5270 | 5348 |
| 5271 | 5349 |
| 5272 THREADED_TEST(ToArrayIndex) { | 5350 THREADED_TEST(ToArrayIndex) { |
| 5273 v8::HandleScope scope; | 5351 v8::HandleScope scope; |
| 5274 LocalContext context; | 5352 LocalContext context; |
| 5275 | 5353 |
| 5276 v8::Handle<String> str = v8_str("42"); | 5354 v8::Handle<String> str = v8_str("42"); |
| 5277 v8::Handle<v8::Uint32> index = str->ToArrayIndex(); | 5355 v8::Handle<v8::Uint32> index = str->ToArrayIndex(); |
| 5278 CHECK(!index.IsEmpty()); | 5356 CHECK(!index.IsEmpty()); |
| (...skipping 8382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13661 // See Chromium issue 47824. | 13739 // See Chromium issue 47824. |
| 13662 v8::HandleScope scope; | 13740 v8::HandleScope scope; |
| 13663 | 13741 |
| 13664 LocalContext context; | 13742 LocalContext context; |
| 13665 const char* init_code = | 13743 const char* init_code = |
| 13666 "var str1 = 'abelspendabel';" | 13744 "var str1 = 'abelspendabel';" |
| 13667 "var str2 = str1 + str1 + str1;" | 13745 "var str2 = str1 + str1 + str1;" |
| 13668 "str2;"; | 13746 "str2;"; |
| 13669 Local<Value> result = CompileRun(init_code); | 13747 Local<Value> result = CompileRun(init_code); |
| 13670 | 13748 |
| 13749 Local<Value> indexof = CompileRun("str2.indexOf('els')"); |
| 13750 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')"); |
| 13751 |
| 13671 CHECK(result->IsString()); | 13752 CHECK(result->IsString()); |
| 13672 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result)); | 13753 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result)); |
| 13673 int length = string->length(); | 13754 int length = string->length(); |
| 13674 CHECK(string->IsAsciiRepresentation()); | 13755 CHECK(string->IsAsciiRepresentation()); |
| 13675 | 13756 |
| 13676 FlattenString(string); | 13757 FlattenString(string); |
| 13677 i::Handle<i::String> flat_string = FlattenGetString(string); | 13758 i::Handle<i::String> flat_string = FlattenGetString(string); |
| 13678 | 13759 |
| 13679 CHECK(string->IsAsciiRepresentation()); | 13760 CHECK(string->IsAsciiRepresentation()); |
| 13680 CHECK(flat_string->IsAsciiRepresentation()); | 13761 CHECK(flat_string->IsAsciiRepresentation()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13726 | 13807 |
| 13727 reresult = CompileRun("/be./g.exec(str2);"); | 13808 reresult = CompileRun("/be./g.exec(str2);"); |
| 13728 CHECK(!reresult->IsNull()); | 13809 CHECK(!reresult->IsNull()); |
| 13729 | 13810 |
| 13730 ExpectString("str2.substring(2, 10);", "elspenda"); | 13811 ExpectString("str2.substring(2, 10);", "elspenda"); |
| 13731 | 13812 |
| 13732 ExpectString("str2.substring(2, 20);", "elspendabelabelspe"); | 13813 ExpectString("str2.substring(2, 20);", "elspendabelabelspe"); |
| 13733 | 13814 |
| 13734 ExpectString("str2.charAt(2);", "e"); | 13815 ExpectString("str2.charAt(2);", "e"); |
| 13735 | 13816 |
| 13817 ExpectObject("str2.indexOf('els');", indexof); |
| 13818 |
| 13819 ExpectObject("str2.lastIndexOf('dab');", lastindexof); |
| 13820 |
| 13736 reresult = CompileRun("str2.charCodeAt(2);"); | 13821 reresult = CompileRun("str2.charCodeAt(2);"); |
| 13737 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value()); | 13822 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value()); |
| 13738 } | 13823 } |
| 13739 | 13824 |
| 13740 | 13825 |
| 13741 // Failed access check callback that performs a GC on each invocation. | 13826 // Failed access check callback that performs a GC on each invocation. |
| 13742 void FailedAccessCheckCallbackGC(Local<v8::Object> target, | 13827 void FailedAccessCheckCallbackGC(Local<v8::Object> target, |
| 13743 v8::AccessType type, | 13828 v8::AccessType type, |
| 13744 Local<v8::Value> data) { | 13829 Local<v8::Value> data) { |
| 13745 HEAP->CollectAllGarbage(i::Heap::kForceCompactionMask); | 13830 HEAP->CollectAllGarbage(i::Heap::kForceCompactionMask); |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14604 CHECK(instance2->CreationContext() == context2); | 14689 CHECK(instance2->CreationContext() == context2); |
| 14605 CheckContextId(instance2, 2); | 14690 CheckContextId(instance2, 2); |
| 14606 } | 14691 } |
| 14607 | 14692 |
| 14608 context1.Dispose(); | 14693 context1.Dispose(); |
| 14609 context2.Dispose(); | 14694 context2.Dispose(); |
| 14610 context3.Dispose(); | 14695 context3.Dispose(); |
| 14611 } | 14696 } |
| 14612 | 14697 |
| 14613 | 14698 |
| 14699 THREADED_TEST(CreationContextOfJsFunction) { |
| 14700 HandleScope handle_scope; |
| 14701 Persistent<Context> context = Context::New(); |
| 14702 InstallContextId(context, 1); |
| 14703 |
| 14704 Local<Object> function; |
| 14705 { |
| 14706 Context::Scope scope(context); |
| 14707 function = CompileRun("function foo() {}; foo").As<Object>(); |
| 14708 } |
| 14709 |
| 14710 CHECK(function->CreationContext() == context); |
| 14711 CheckContextId(function, 1); |
| 14712 |
| 14713 context.Dispose(); |
| 14714 } |
| 14715 |
| 14716 |
| 14614 Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index, | 14717 Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index, |
| 14615 const AccessorInfo& info) { | 14718 const AccessorInfo& info) { |
| 14616 if (index == 42) return v8_str("yes"); | 14719 if (index == 42) return v8_str("yes"); |
| 14617 return Handle<v8::Integer>(); | 14720 return Handle<v8::Integer>(); |
| 14618 } | 14721 } |
| 14619 | 14722 |
| 14620 | 14723 |
| 14621 Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property, | 14724 Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property, |
| 14622 const AccessorInfo& info) { | 14725 const AccessorInfo& info) { |
| 14623 if (property->Equals(v8_str("foo"))) return v8_str("yes"); | 14726 if (property->Equals(v8_str("foo"))) return v8_str("yes"); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14846 } | 14949 } |
| 14847 | 14950 |
| 14848 i::Isolate::Current()->heap()->CollectAllGarbage(true); | 14951 i::Isolate::Current()->heap()->CollectAllGarbage(true); |
| 14849 { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache(); | 14952 { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache(); |
| 14850 if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) { | 14953 if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) { |
| 14851 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache); | 14954 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache); |
| 14852 CHECK_GT(elements, map_cache->NumberOfElements()); | 14955 CHECK_GT(elements, map_cache->NumberOfElements()); |
| 14853 } | 14956 } |
| 14854 } | 14957 } |
| 14855 } | 14958 } |
| 14959 |
| 14960 |
| 14961 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global, |
| 14962 Local<Value> name, |
| 14963 v8::AccessType type, |
| 14964 Local<Value> data) { |
| 14965 // Only block read access to __proto__. |
| 14966 if (type == v8::ACCESS_GET && |
| 14967 name->IsString() && |
| 14968 name->ToString()->Length() == 9 && |
| 14969 name->ToString()->Utf8Length() == 9) { |
| 14970 char buffer[10]; |
| 14971 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer)); |
| 14972 return strncmp(buffer, "__proto__", 9) != 0; |
| 14973 } |
| 14974 |
| 14975 return true; |
| 14976 } |
| 14977 |
| 14978 |
| 14979 THREADED_TEST(Regress93759) { |
| 14980 HandleScope scope; |
| 14981 |
| 14982 // Template for object with security check. |
| 14983 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(); |
| 14984 // We don't do indexing, so any callback can be used for that. |
| 14985 no_proto_template->SetAccessCheckCallbacks( |
| 14986 BlockProtoNamedSecurityTestCallback, |
| 14987 IndexedSecurityTestCallback); |
| 14988 |
| 14989 // Templates for objects with hidden prototypes and possibly security check. |
| 14990 Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New(); |
| 14991 hidden_proto_template->SetHiddenPrototype(true); |
| 14992 |
| 14993 Local<FunctionTemplate> protected_hidden_proto_template = |
| 14994 v8::FunctionTemplate::New(); |
| 14995 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks( |
| 14996 BlockProtoNamedSecurityTestCallback, |
| 14997 IndexedSecurityTestCallback); |
| 14998 protected_hidden_proto_template->SetHiddenPrototype(true); |
| 14999 |
| 15000 // Context for "foreign" objects used in test. |
| 15001 Persistent<Context> context = v8::Context::New(); |
| 15002 context->Enter(); |
| 15003 |
| 15004 // Plain object, no security check. |
| 15005 Local<Object> simple_object = Object::New(); |
| 15006 |
| 15007 // Object with explicit security check. |
| 15008 Local<Object> protected_object = |
| 15009 no_proto_template->NewInstance(); |
| 15010 |
| 15011 // JSGlobalProxy object, always have security check. |
| 15012 Local<Object> proxy_object = |
| 15013 context->Global(); |
| 15014 |
| 15015 // Global object, the prototype of proxy_object. No security checks. |
| 15016 Local<Object> global_object = |
| 15017 proxy_object->GetPrototype()->ToObject(); |
| 15018 |
| 15019 // Hidden prototype without security check. |
| 15020 Local<Object> hidden_prototype = |
| 15021 hidden_proto_template->GetFunction()->NewInstance(); |
| 15022 Local<Object> object_with_hidden = |
| 15023 Object::New(); |
| 15024 object_with_hidden->SetPrototype(hidden_prototype); |
| 15025 |
| 15026 // Hidden prototype with security check on the hidden prototype. |
| 15027 Local<Object> protected_hidden_prototype = |
| 15028 protected_hidden_proto_template->GetFunction()->NewInstance(); |
| 15029 Local<Object> object_with_protected_hidden = |
| 15030 Object::New(); |
| 15031 object_with_protected_hidden->SetPrototype(protected_hidden_prototype); |
| 15032 |
| 15033 context->Exit(); |
| 15034 |
| 15035 // Template for object for second context. Values to test are put on it as |
| 15036 // properties. |
| 15037 Local<ObjectTemplate> global_template = ObjectTemplate::New(); |
| 15038 global_template->Set(v8_str("simple"), simple_object); |
| 15039 global_template->Set(v8_str("protected"), protected_object); |
| 15040 global_template->Set(v8_str("global"), global_object); |
| 15041 global_template->Set(v8_str("proxy"), proxy_object); |
| 15042 global_template->Set(v8_str("hidden"), object_with_hidden); |
| 15043 global_template->Set(v8_str("phidden"), object_with_protected_hidden); |
| 15044 |
| 15045 LocalContext context2(NULL, global_template); |
| 15046 |
| 15047 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)"); |
| 15048 CHECK(result1->Equals(simple_object->GetPrototype())); |
| 15049 |
| 15050 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)"); |
| 15051 CHECK(result2->Equals(Undefined())); |
| 15052 |
| 15053 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)"); |
| 15054 CHECK(result3->Equals(global_object->GetPrototype())); |
| 15055 |
| 15056 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)"); |
| 15057 CHECK(result4->Equals(Undefined())); |
| 15058 |
| 15059 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)"); |
| 15060 CHECK(result5->Equals( |
| 15061 object_with_hidden->GetPrototype()->ToObject()->GetPrototype())); |
| 15062 |
| 15063 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)"); |
| 15064 CHECK(result6->Equals(Undefined())); |
| 15065 |
| 15066 context.Dispose(); |
| 15067 } |
| OLD | NEW |