| 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 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 accumulator->Add("=====================\n\n"); | 686 accumulator->Add("=====================\n\n"); |
| 687 } | 687 } |
| 688 | 688 |
| 689 | 689 |
| 690 void Isolate::SetFailedAccessCheckCallback( | 690 void Isolate::SetFailedAccessCheckCallback( |
| 691 v8::FailedAccessCheckCallback callback) { | 691 v8::FailedAccessCheckCallback callback) { |
| 692 thread_local_top()->failed_access_check_callback_ = callback; | 692 thread_local_top()->failed_access_check_callback_ = callback; |
| 693 } | 693 } |
| 694 | 694 |
| 695 | 695 |
| 696 void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { | 696 static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate, |
| 697 Handle<JSObject> receiver) { |
| 698 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); |
| 699 if (!constructor->shared()->IsApiFunction()) return NULL; |
| 700 |
| 701 Object* data_obj = |
| 702 constructor->shared()->get_api_func_data()->access_check_info(); |
| 703 if (data_obj == isolate->heap()->undefined_value()) return NULL; |
| 704 |
| 705 return AccessCheckInfo::cast(data_obj); |
| 706 } |
| 707 |
| 708 |
| 709 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver, |
| 710 v8::AccessType type) { |
| 697 if (!thread_local_top()->failed_access_check_callback_) return; | 711 if (!thread_local_top()->failed_access_check_callback_) return; |
| 698 | 712 |
| 699 ASSERT(receiver->IsAccessCheckNeeded()); | 713 ASSERT(receiver->IsAccessCheckNeeded()); |
| 700 ASSERT(context()); | 714 ASSERT(context()); |
| 701 | 715 |
| 702 // Get the data object from access check info. | 716 // Get the data object from access check info. |
| 703 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 717 HandleScope scope(this); |
| 704 if (!constructor->shared()->IsApiFunction()) return; | 718 Handle<Object> data; |
| 705 Object* data_obj = | 719 { DisallowHeapAllocation no_gc; |
| 706 constructor->shared()->get_api_func_data()->access_check_info(); | 720 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 707 if (data_obj == heap_.undefined_value()) return; | 721 if (!access_check_info) return; |
| 722 data = handle(access_check_info->data(), this); |
| 723 } |
| 708 | 724 |
| 709 HandleScope scope(this); | 725 // Leaving JavaScript. |
| 710 Handle<JSObject> receiver_handle(receiver); | 726 VMState<EXTERNAL> state(this); |
| 711 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this); | 727 thread_local_top()->failed_access_check_callback_( |
| 712 { VMState<EXTERNAL> state(this); | 728 v8::Utils::ToLocal(receiver), |
| 713 thread_local_top()->failed_access_check_callback_( | |
| 714 v8::Utils::ToLocal(receiver_handle), | |
| 715 type, | 729 type, |
| 716 v8::Utils::ToLocal(data)); | 730 v8::Utils::ToLocal(data)); |
| 717 } | |
| 718 } | 731 } |
| 719 | 732 |
| 720 | 733 |
| 721 enum MayAccessDecision { | 734 enum MayAccessDecision { |
| 722 YES, NO, UNKNOWN | 735 YES, NO, UNKNOWN |
| 723 }; | 736 }; |
| 724 | 737 |
| 725 | 738 |
| 726 static MayAccessDecision MayAccessPreCheck(Isolate* isolate, | 739 static MayAccessDecision MayAccessPreCheck(Isolate* isolate, |
| 727 JSObject* receiver, | 740 Handle<JSObject> receiver, |
| 728 v8::AccessType type) { | 741 v8::AccessType type) { |
| 742 DisallowHeapAllocation no_gc; |
| 729 // During bootstrapping, callback functions are not enabled yet. | 743 // During bootstrapping, callback functions are not enabled yet. |
| 730 if (isolate->bootstrapper()->IsActive()) return YES; | 744 if (isolate->bootstrapper()->IsActive()) return YES; |
| 731 | 745 |
| 732 if (receiver->IsJSGlobalProxy()) { | 746 if (receiver->IsJSGlobalProxy()) { |
| 733 Object* receiver_context = JSGlobalProxy::cast(receiver)->native_context(); | 747 Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context(); |
| 734 if (!receiver_context->IsContext()) return NO; | 748 if (!receiver_context->IsContext()) return NO; |
| 735 | 749 |
| 736 // Get the native context of current top context. | 750 // Get the native context of current top context. |
| 737 // avoid using Isolate::native_context() because it uses Handle. | 751 // avoid using Isolate::native_context() because it uses Handle. |
| 738 Context* native_context = | 752 Context* native_context = |
| 739 isolate->context()->global_object()->native_context(); | 753 isolate->context()->global_object()->native_context(); |
| 740 if (receiver_context == native_context) return YES; | 754 if (receiver_context == native_context) return YES; |
| 741 | 755 |
| 742 if (Context::cast(receiver_context)->security_token() == | 756 if (Context::cast(receiver_context)->security_token() == |
| 743 native_context->security_token()) | 757 native_context->security_token()) |
| 744 return YES; | 758 return YES; |
| 745 } | 759 } |
| 746 | 760 |
| 747 return UNKNOWN; | 761 return UNKNOWN; |
| 748 } | 762 } |
| 749 | 763 |
| 750 | 764 |
| 751 bool Isolate::MayNamedAccess(JSObject* receiver, Object* key, | 765 bool Isolate::MayNamedAccess(Handle<JSObject> receiver, |
| 766 Handle<Object> key, |
| 752 v8::AccessType type) { | 767 v8::AccessType type) { |
| 753 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | 768 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); |
| 754 | 769 |
| 755 // The callers of this method are not expecting a GC. | |
| 756 DisallowHeapAllocation no_gc; | |
| 757 | |
| 758 // Skip checks for hidden properties access. Note, we do not | 770 // Skip checks for hidden properties access. Note, we do not |
| 759 // require existence of a context in this case. | 771 // require existence of a context in this case. |
| 760 if (key == heap_.hidden_string()) return true; | 772 if (key.is_identical_to(factory()->hidden_string())) return true; |
| 761 | 773 |
| 762 // Check for compatibility between the security tokens in the | 774 // Check for compatibility between the security tokens in the |
| 763 // current lexical context and the accessed object. | 775 // current lexical context and the accessed object. |
| 764 ASSERT(context()); | 776 ASSERT(context()); |
| 765 | 777 |
| 766 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | 778 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); |
| 767 if (decision != UNKNOWN) return decision == YES; | 779 if (decision != UNKNOWN) return decision == YES; |
| 768 | 780 |
| 769 // Get named access check callback | 781 HandleScope scope(this); |
| 770 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 782 Handle<Object> data; |
| 771 if (!constructor->shared()->IsApiFunction()) return false; | 783 v8::NamedSecurityCallback callback; |
| 784 { DisallowHeapAllocation no_gc; |
| 785 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 786 if (!access_check_info) return false; |
| 787 Object* fun_obj = access_check_info->named_callback(); |
| 788 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); |
| 789 if (!callback) return false; |
| 790 data = handle(access_check_info->data(), this); |
| 791 } |
| 772 | 792 |
| 773 Object* data_obj = | 793 LOG(this, ApiNamedSecurityCheck(*key)); |
| 774 constructor->shared()->get_api_func_data()->access_check_info(); | |
| 775 if (data_obj == heap_.undefined_value()) return false; | |
| 776 | 794 |
| 777 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback(); | 795 // Leaving JavaScript. |
| 778 v8::NamedSecurityCallback callback = | 796 VMState<EXTERNAL> state(this); |
| 779 v8::ToCData<v8::NamedSecurityCallback>(fun_obj); | 797 return callback(v8::Utils::ToLocal(receiver), |
| 780 | 798 v8::Utils::ToLocal(key), |
| 781 if (!callback) return false; | 799 type, |
| 782 | 800 v8::Utils::ToLocal(data)); |
| 783 HandleScope scope(this); | |
| 784 Handle<JSObject> receiver_handle(receiver, this); | |
| 785 Handle<Object> key_handle(key, this); | |
| 786 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this); | |
| 787 LOG(this, ApiNamedSecurityCheck(key)); | |
| 788 bool result = false; | |
| 789 { | |
| 790 // Leaving JavaScript. | |
| 791 VMState<EXTERNAL> state(this); | |
| 792 result = callback(v8::Utils::ToLocal(receiver_handle), | |
| 793 v8::Utils::ToLocal(key_handle), | |
| 794 type, | |
| 795 v8::Utils::ToLocal(data)); | |
| 796 } | |
| 797 return result; | |
| 798 } | 801 } |
| 799 | 802 |
| 800 | 803 |
| 801 bool Isolate::MayIndexedAccess(JSObject* receiver, | 804 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver, |
| 802 uint32_t index, | 805 uint32_t index, |
| 803 v8::AccessType type) { | 806 v8::AccessType type) { |
| 804 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | 807 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); |
| 805 // Check for compatibility between the security tokens in the | 808 // Check for compatibility between the security tokens in the |
| 806 // current lexical context and the accessed object. | 809 // current lexical context and the accessed object. |
| 807 ASSERT(context()); | 810 ASSERT(context()); |
| 808 | 811 |
| 809 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | 812 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); |
| 810 if (decision != UNKNOWN) return decision == YES; | 813 if (decision != UNKNOWN) return decision == YES; |
| 811 | 814 |
| 812 // Get indexed access check callback | 815 HandleScope scope(this); |
| 813 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 816 Handle<Object> data; |
| 814 if (!constructor->shared()->IsApiFunction()) return false; | 817 v8::IndexedSecurityCallback callback; |
| 818 { DisallowHeapAllocation no_gc; |
| 819 // Get named access check callback |
| 820 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 821 if (!access_check_info) return false; |
| 822 Object* fun_obj = access_check_info->indexed_callback(); |
| 823 callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); |
| 824 if (!callback) return false; |
| 825 data = handle(access_check_info->data(), this); |
| 826 } |
| 815 | 827 |
| 816 Object* data_obj = | 828 LOG(this, ApiIndexedSecurityCheck(index)); |
| 817 constructor->shared()->get_api_func_data()->access_check_info(); | |
| 818 if (data_obj == heap_.undefined_value()) return false; | |
| 819 | 829 |
| 820 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback(); | 830 // Leaving JavaScript. |
| 821 v8::IndexedSecurityCallback callback = | 831 VMState<EXTERNAL> state(this); |
| 822 v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); | 832 return callback( |
| 823 | 833 v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data)); |
| 824 if (!callback) return false; | |
| 825 | |
| 826 HandleScope scope(this); | |
| 827 Handle<JSObject> receiver_handle(receiver, this); | |
| 828 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this); | |
| 829 LOG(this, ApiIndexedSecurityCheck(index)); | |
| 830 bool result = false; | |
| 831 { | |
| 832 // Leaving JavaScript. | |
| 833 VMState<EXTERNAL> state(this); | |
| 834 result = callback(v8::Utils::ToLocal(receiver_handle), | |
| 835 index, | |
| 836 type, | |
| 837 v8::Utils::ToLocal(data)); | |
| 838 } | |
| 839 return result; | |
| 840 } | 834 } |
| 841 | 835 |
| 842 | 836 |
| 843 const char* const Isolate::kStackOverflowMessage = | 837 const char* const Isolate::kStackOverflowMessage = |
| 844 "Uncaught RangeError: Maximum call stack size exceeded"; | 838 "Uncaught RangeError: Maximum call stack size exceeded"; |
| 845 | 839 |
| 846 | 840 |
| 847 Failure* Isolate::StackOverflow() { | 841 Failure* Isolate::StackOverflow() { |
| 848 HandleScope scope(this); | 842 HandleScope scope(this); |
| 849 // At this point we cannot create an Error object using its javascript | 843 // At this point we cannot create an Error object using its javascript |
| (...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2287 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map); | 2281 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map); |
| 2288 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8); | 2282 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8); |
| 2289 JSObject::SetProperty(registry, name, obj, NONE, STRICT).Assert(); | 2283 JSObject::SetProperty(registry, name, obj, NONE, STRICT).Assert(); |
| 2290 } | 2284 } |
| 2291 } | 2285 } |
| 2292 return Handle<JSObject>::cast(factory()->symbol_registry()); | 2286 return Handle<JSObject>::cast(factory()->symbol_registry()); |
| 2293 } | 2287 } |
| 2294 | 2288 |
| 2295 | 2289 |
| 2296 } } // namespace v8::internal | 2290 } } // namespace v8::internal |
| OLD | NEW |