OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
795 js_object->GetElementsAccessor()->Get(receiver, js_object, index), | 795 js_object->GetElementsAccessor()->Get(receiver, js_object, index), |
796 Object); | 796 Object); |
797 if (!result->IsTheHole()) return result; | 797 if (!result->IsTheHole()) return result; |
798 } | 798 } |
799 } | 799 } |
800 | 800 |
801 return isolate->factory()->undefined_value(); | 801 return isolate->factory()->undefined_value(); |
802 } | 802 } |
803 | 803 |
804 | 804 |
805 static MaybeHandle<Object> GetElementStructure(Isolate* isolate, | |
806 Handle<JSObject> object, | |
807 uint32_t index) { | |
Toon Verwaest
2014/10/14 08:31:54
Replace by JSObject::GetOwnElementAccessorPair
Dmitry Lomov (no reviews)
2014/10/14 09:08:37
Is that enough? SetElementWithCallback handles mor
| |
808 if (!object->HasDictionaryElements() && | |
809 !object->HasDictionaryArgumentsElements()) | |
810 return MaybeHandle<Object>(); | |
811 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | |
812 bool is_arguments = | |
813 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); | |
814 Handle<SeededNumberDictionary> dictionary( | |
815 is_arguments ? SeededNumberDictionary::cast(elements->get(1)) | |
816 : SeededNumberDictionary::cast(*elements)); | |
817 int entry = dictionary->FindEntry(index); | |
818 if (entry != SeededNumberDictionary::kNotFound) { | |
819 Handle<Object> element(dictionary->ValueAt(entry), isolate); | |
820 PropertyDetails details = dictionary->DetailsAt(entry); | |
821 if (details.type() == CALLBACKS) return element; | |
822 } | |
823 return MaybeHandle<Object>(); | |
824 } | |
825 | |
826 | |
827 MaybeHandle<Object> Object::SetElementWithReceiver( | |
828 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, | |
829 uint32_t index, Handle<Object> value, StrictMode strict_mode) { | |
830 // Iterate up the prototype chain until an element is found or the null | |
831 // prototype is encountered. | |
832 bool done = false; | |
833 for (PrototypeIterator iter(isolate, object, | |
834 object->IsJSProxy() || object->IsJSObject() | |
835 ? PrototypeIterator::START_AT_RECEIVER | |
836 : PrototypeIterator::START_AT_PROTOTYPE); | |
837 !iter.IsAtEnd() && !done; iter.Advance()) { | |
838 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | |
839 // TODO(dslomov): implement. | |
840 isolate->ThrowIllegalOperation(); | |
841 return MaybeHandle<Object>(); | |
842 } | |
843 | |
844 Handle<JSObject> js_object = | |
845 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
846 | |
847 // Check access rights if needed. | |
848 if (js_object->IsAccessCheckNeeded()) { | |
849 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_SET)) { | |
850 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_SET); | |
851 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
852 return isolate->factory()->undefined_value(); | |
853 } | |
854 } | |
855 | |
856 if (js_object->HasIndexedInterceptor()) { | |
857 Maybe<PropertyAttributes> from_interceptor = | |
858 JSObject::GetElementAttributeFromInterceptor(js_object, receiver, | |
859 index); | |
860 if (from_interceptor.has_value) { | |
Toon Verwaest
2014/10/14 08:31:54
The contract is normally that if !has_value, an ex
Dmitry Lomov (no reviews)
2014/10/14 09:08:37
I see. Wow, all those things could use some docume
Dmitry Lomov (no reviews)
2014/10/14 09:28:26
Done.
| |
861 if ((from_interceptor.value & READ_ONLY) != 0) { | |
862 return WriteToReadOnlyElement(isolate, receiver, index, value, | |
863 strict_mode); | |
864 } | |
865 // Treat indexed interceptor as presence of data property. | |
866 done = true; | |
867 } | |
868 } else if (js_object->elements() != isolate->heap()->empty_fixed_array()) { | |
869 ElementsAccessor* accessor = js_object->GetElementsAccessor(); | |
870 PropertyAttributes attrs = | |
871 accessor->GetAttributes(receiver, js_object, index); | |
872 if ((attrs & READ_ONLY) != 0) { | |
873 return WriteToReadOnlyElement(isolate, receiver, index, value, | |
874 strict_mode); | |
875 } | |
876 Handle<Object> element_structure; | |
877 if (GetElementStructure(isolate, js_object, index) | |
878 .ToHandle(&element_structure)) { | |
879 return JSObject::SetElementWithCallback( | |
880 receiver, element_structure, index, value, js_object, strict_mode); | |
881 } else { | |
882 done = attrs != ABSENT; | |
883 } | |
884 } | |
885 } | |
886 | |
887 if (!receiver->IsJSObject()) { | |
888 return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode); | |
889 } | |
890 Handle<JSObject> target = Handle<JSObject>::cast(receiver); | |
891 ElementsAccessor* accessor = target->GetElementsAccessor(); | |
892 PropertyAttributes attrs = accessor->GetAttributes(receiver, target, index); | |
893 if ((attrs & READ_ONLY) != 0) { | |
894 return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode); | |
895 } | |
896 PropertyAttributes new_attrs = attrs != ABSENT ? attrs : NONE; | |
897 return JSObject::SetElement(target, index, value, new_attrs, strict_mode, | |
898 false); | |
899 } | |
900 | |
901 | |
805 Map* Object::GetRootMap(Isolate* isolate) { | 902 Map* Object::GetRootMap(Isolate* isolate) { |
806 DisallowHeapAllocation no_alloc; | 903 DisallowHeapAllocation no_alloc; |
807 if (IsSmi()) { | 904 if (IsSmi()) { |
808 Context* context = isolate->context()->native_context(); | 905 Context* context = isolate->context()->native_context(); |
809 return context->number_function()->initial_map(); | 906 return context->number_function()->initial_map(); |
810 } | 907 } |
811 | 908 |
812 HeapObject* heap_object = HeapObject::cast(this); | 909 HeapObject* heap_object = HeapObject::cast(this); |
813 | 910 |
814 // The object is either a number, a string, a boolean, | 911 // The object is either a number, a string, a boolean, |
(...skipping 2108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2923 if (strict_mode != STRICT) return value; | 3020 if (strict_mode != STRICT) return value; |
2924 | 3021 |
2925 Handle<Object> args[] = {it->name(), it->GetReceiver()}; | 3022 Handle<Object> args[] = {it->name(), it->GetReceiver()}; |
2926 THROW_NEW_ERROR(it->isolate(), | 3023 THROW_NEW_ERROR(it->isolate(), |
2927 NewTypeError("strict_read_only_property", | 3024 NewTypeError("strict_read_only_property", |
2928 HandleVector(args, arraysize(args))), | 3025 HandleVector(args, arraysize(args))), |
2929 Object); | 3026 Object); |
2930 } | 3027 } |
2931 | 3028 |
2932 | 3029 |
3030 MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate, | |
3031 Handle<Object> receiver, | |
3032 uint32_t index, | |
3033 Handle<Object> value, | |
3034 StrictMode strict_mode) { | |
3035 if (strict_mode != STRICT) return value; | |
3036 | |
3037 Handle<Object> args[] = {isolate->factory()->NewNumberFromUint(index), | |
3038 receiver}; | |
3039 THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property", | |
3040 HandleVector(args, arraysize(args))), | |
3041 Object); | |
3042 } | |
3043 | |
3044 | |
2933 Handle<Object> Object::SetDataProperty(LookupIterator* it, | 3045 Handle<Object> Object::SetDataProperty(LookupIterator* it, |
2934 Handle<Object> value) { | 3046 Handle<Object> value) { |
2935 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3047 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
2936 // have own properties. | 3048 // have own properties. |
2937 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3049 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
2938 | 3050 |
2939 // Store on the holder which may be hidden behind the receiver. | 3051 // Store on the holder which may be hidden behind the receiver. |
2940 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); | 3052 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); |
2941 | 3053 |
2942 // Old value for the observation change record. | 3054 // Old value for the observation change record. |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4050 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( | 4162 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( |
4051 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, | 4163 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4052 bool check_prototype) { | 4164 bool check_prototype) { |
4053 Isolate* isolate = object->GetIsolate(); | 4165 Isolate* isolate = object->GetIsolate(); |
4054 HandleScope scope(isolate); | 4166 HandleScope scope(isolate); |
4055 | 4167 |
4056 // Make sure that the top context does not change when doing | 4168 // Make sure that the top context does not change when doing |
4057 // callbacks or interceptor calls. | 4169 // callbacks or interceptor calls. |
4058 AssertNoContextChange ncc(isolate); | 4170 AssertNoContextChange ncc(isolate); |
4059 | 4171 |
4172 Maybe<PropertyAttributes> from_interceptor = | |
4173 GetElementAttributeFromInterceptor(object, receiver, index); | |
4174 | |
4175 if (from_interceptor.has_value) return from_interceptor; | |
4176 | |
4177 return GetElementAttributeWithoutInterceptor(object, receiver, index, | |
4178 check_prototype); | |
4179 } | |
4180 | |
4181 | |
4182 Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor( | |
4183 Handle<JSObject> object, Handle<Object> receiver, uint32_t index) { | |
4184 Isolate* isolate = object->GetIsolate(); | |
4185 AssertNoContextChange ncc(isolate); | |
4186 | |
4060 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | 4187 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
4061 PropertyCallbackArguments args( | 4188 PropertyCallbackArguments args( |
4062 isolate, interceptor->data(), *receiver, *object); | 4189 isolate, interceptor->data(), *receiver, *object); |
4063 if (!interceptor->query()->IsUndefined()) { | 4190 if (!interceptor->query()->IsUndefined()) { |
4064 v8::IndexedPropertyQueryCallback query = | 4191 v8::IndexedPropertyQueryCallback query = |
4065 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); | 4192 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
4066 LOG(isolate, | 4193 LOG(isolate, |
4067 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); | 4194 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); |
4068 v8::Handle<v8::Integer> result = args.Call(query, index); | 4195 v8::Handle<v8::Integer> result = args.Call(query, index); |
4069 if (!result.IsEmpty()) | 4196 if (!result.IsEmpty()) |
4070 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); | 4197 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); |
4071 } else if (!interceptor->getter()->IsUndefined()) { | 4198 } else if (!interceptor->getter()->IsUndefined()) { |
4072 v8::IndexedPropertyGetterCallback getter = | 4199 v8::IndexedPropertyGetterCallback getter = |
4073 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | 4200 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
4074 LOG(isolate, | 4201 LOG(isolate, |
4075 ApiIndexedPropertyAccess( | 4202 ApiIndexedPropertyAccess( |
4076 "interceptor-indexed-get-has", *object, index)); | 4203 "interceptor-indexed-get-has", *object, index)); |
4077 v8::Handle<v8::Value> result = args.Call(getter, index); | 4204 v8::Handle<v8::Value> result = args.Call(getter, index); |
4078 if (!result.IsEmpty()) return maybe(NONE); | 4205 if (!result.IsEmpty()) return maybe(NONE); |
4079 } | 4206 } |
4080 | 4207 |
4081 return GetElementAttributeWithoutInterceptor( | 4208 return Maybe<PropertyAttributes>(); |
4082 object, receiver, index, check_prototype); | |
4083 } | 4209 } |
4084 | 4210 |
4085 | 4211 |
4086 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor( | 4212 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor( |
4087 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, | 4213 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4088 bool check_prototype) { | 4214 bool check_prototype) { |
4089 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( | 4215 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( |
4090 receiver, object, index); | 4216 receiver, object, index); |
4091 if (attr != ABSENT) return maybe(attr); | 4217 if (attr != ABSENT) return maybe(attr); |
4092 | 4218 |
(...skipping 7771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11864 if (structure->IsDeclaredAccessorInfo()) { | 11990 if (structure->IsDeclaredAccessorInfo()) { |
11865 return GetDeclaredAccessorProperty( | 11991 return GetDeclaredAccessorProperty( |
11866 receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate); | 11992 receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate); |
11867 } | 11993 } |
11868 | 11994 |
11869 UNREACHABLE(); | 11995 UNREACHABLE(); |
11870 return MaybeHandle<Object>(); | 11996 return MaybeHandle<Object>(); |
11871 } | 11997 } |
11872 | 11998 |
11873 | 11999 |
11874 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, | 12000 MaybeHandle<Object> JSObject::SetElementWithCallback( |
11875 Handle<Object> structure, | 12001 Handle<Object> object, Handle<Object> structure, uint32_t index, |
11876 uint32_t index, | 12002 Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode) { |
11877 Handle<Object> value, | 12003 Isolate* isolate = holder->GetIsolate(); |
11878 Handle<JSObject> holder, | |
11879 StrictMode strict_mode) { | |
11880 Isolate* isolate = object->GetIsolate(); | |
11881 | 12004 |
11882 // We should never get here to initialize a const with the hole | 12005 // We should never get here to initialize a const with the hole |
11883 // value since a const declaration would conflict with the setter. | 12006 // value since a const declaration would conflict with the setter. |
11884 DCHECK(!value->IsTheHole()); | 12007 DCHECK(!value->IsTheHole()); |
11885 DCHECK(!structure->IsForeign()); | 12008 DCHECK(!structure->IsForeign()); |
11886 if (structure->IsExecutableAccessorInfo()) { | 12009 if (structure->IsExecutableAccessorInfo()) { |
11887 // api style callbacks | 12010 // api style callbacks |
11888 Handle<ExecutableAccessorInfo> data = | 12011 Handle<ExecutableAccessorInfo> data = |
11889 Handle<ExecutableAccessorInfo>::cast(structure); | 12012 Handle<ExecutableAccessorInfo>::cast(structure); |
11890 Object* call_obj = data->setter(); | 12013 Object* call_obj = data->setter(); |
11891 v8::AccessorNameSetterCallback call_fun = | 12014 v8::AccessorNameSetterCallback call_fun = |
11892 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj); | 12015 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj); |
11893 if (call_fun == NULL) return value; | 12016 if (call_fun == NULL) return value; |
11894 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12017 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
11895 Handle<String> key(isolate->factory()->NumberToString(number)); | 12018 Handle<String> key(isolate->factory()->NumberToString(number)); |
11896 LOG(isolate, ApiNamedPropertyAccess("store", *object, *key)); | 12019 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key)); |
11897 PropertyCallbackArguments | 12020 PropertyCallbackArguments |
11898 args(isolate, data->data(), *object, *holder); | 12021 args(isolate, data->data(), *object, *holder); |
11899 args.Call(call_fun, | 12022 args.Call(call_fun, |
11900 v8::Utils::ToLocal(key), | 12023 v8::Utils::ToLocal(key), |
11901 v8::Utils::ToLocal(value)); | 12024 v8::Utils::ToLocal(value)); |
11902 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12025 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
11903 return value; | 12026 return value; |
11904 } | 12027 } |
11905 | 12028 |
11906 if (structure->IsAccessorPair()) { | 12029 if (structure->IsAccessorPair()) { |
(...skipping 4481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16388 Handle<DependentCode> codes = | 16511 Handle<DependentCode> codes = |
16389 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 16512 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
16390 DependentCode::kPropertyCellChangedGroup, | 16513 DependentCode::kPropertyCellChangedGroup, |
16391 info->object_wrapper()); | 16514 info->object_wrapper()); |
16392 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 16515 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
16393 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16516 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
16394 cell, info->zone()); | 16517 cell, info->zone()); |
16395 } | 16518 } |
16396 | 16519 |
16397 } } // namespace v8::internal | 16520 } } // namespace v8::internal |
OLD | NEW |