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 MaybeHandle<Object> Object::SetElementWithReceiver( |
| 806 Isolate* isolate, Handle<Object> object, Handle<Object> receiver, |
| 807 uint32_t index, Handle<Object> value, StrictMode strict_mode) { |
| 808 // Iterate up the prototype chain until an element is found or the null |
| 809 // prototype is encountered. |
| 810 bool done = false; |
| 811 for (PrototypeIterator iter(isolate, object, |
| 812 object->IsJSProxy() || object->IsJSObject() |
| 813 ? PrototypeIterator::START_AT_RECEIVER |
| 814 : PrototypeIterator::START_AT_PROTOTYPE); |
| 815 !iter.IsAtEnd() && !done; iter.Advance()) { |
| 816 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| 817 // TODO(dslomov): implement. |
| 818 isolate->ThrowIllegalOperation(); |
| 819 return MaybeHandle<Object>(); |
| 820 } |
| 821 |
| 822 Handle<JSObject> js_object = |
| 823 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 824 |
| 825 // Check access rights if needed. |
| 826 if (js_object->IsAccessCheckNeeded()) { |
| 827 if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_SET)) { |
| 828 isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_SET); |
| 829 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 830 return isolate->factory()->undefined_value(); |
| 831 } |
| 832 } |
| 833 |
| 834 if (js_object->HasIndexedInterceptor()) { |
| 835 Maybe<PropertyAttributes> from_interceptor = |
| 836 JSObject::GetElementAttributeFromInterceptor(js_object, receiver, |
| 837 index); |
| 838 if (!from_interceptor.has_value) return MaybeHandle<Object>(); |
| 839 if ((from_interceptor.value & READ_ONLY) != 0) { |
| 840 return WriteToReadOnlyElement(isolate, receiver, index, value, |
| 841 strict_mode); |
| 842 } |
| 843 done = from_interceptor.value != ABSENT; |
| 844 } |
| 845 |
| 846 if (!done && |
| 847 js_object->elements() != isolate->heap()->empty_fixed_array()) { |
| 848 ElementsAccessor* accessor = js_object->GetElementsAccessor(); |
| 849 PropertyAttributes attrs = |
| 850 accessor->GetAttributes(receiver, js_object, index); |
| 851 if ((attrs & READ_ONLY) != 0) { |
| 852 return WriteToReadOnlyElement(isolate, receiver, index, value, |
| 853 strict_mode); |
| 854 } |
| 855 Handle<AccessorPair> accessor_pair; |
| 856 if (accessor->GetAccessorPair(receiver, js_object, index) |
| 857 .ToHandle(&accessor_pair)) { |
| 858 return JSObject::SetElementWithCallback(receiver, accessor_pair, index, |
| 859 value, js_object, strict_mode); |
| 860 } else { |
| 861 done = attrs != ABSENT; |
| 862 } |
| 863 } |
| 864 } |
| 865 |
| 866 if (!receiver->IsJSObject()) { |
| 867 return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode); |
| 868 } |
| 869 Handle<JSObject> target = Handle<JSObject>::cast(receiver); |
| 870 ElementsAccessor* accessor = target->GetElementsAccessor(); |
| 871 PropertyAttributes attrs = accessor->GetAttributes(receiver, target, index); |
| 872 if ((attrs & READ_ONLY) != 0) { |
| 873 return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode); |
| 874 } |
| 875 PropertyAttributes new_attrs = attrs != ABSENT ? attrs : NONE; |
| 876 return JSObject::SetElement(target, index, value, new_attrs, strict_mode, |
| 877 false); |
| 878 } |
| 879 |
| 880 |
805 Map* Object::GetRootMap(Isolate* isolate) { | 881 Map* Object::GetRootMap(Isolate* isolate) { |
806 DisallowHeapAllocation no_alloc; | 882 DisallowHeapAllocation no_alloc; |
807 if (IsSmi()) { | 883 if (IsSmi()) { |
808 Context* context = isolate->context()->native_context(); | 884 Context* context = isolate->context()->native_context(); |
809 return context->number_function()->initial_map(); | 885 return context->number_function()->initial_map(); |
810 } | 886 } |
811 | 887 |
812 HeapObject* heap_object = HeapObject::cast(this); | 888 HeapObject* heap_object = HeapObject::cast(this); |
813 | 889 |
814 // The object is either a number, a string, a boolean, | 890 // The object is either a number, a string, a boolean, |
(...skipping 2110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2925 if (strict_mode != STRICT) return value; | 3001 if (strict_mode != STRICT) return value; |
2926 | 3002 |
2927 Handle<Object> args[] = {it->name(), it->GetReceiver()}; | 3003 Handle<Object> args[] = {it->name(), it->GetReceiver()}; |
2928 THROW_NEW_ERROR(it->isolate(), | 3004 THROW_NEW_ERROR(it->isolate(), |
2929 NewTypeError("strict_read_only_property", | 3005 NewTypeError("strict_read_only_property", |
2930 HandleVector(args, arraysize(args))), | 3006 HandleVector(args, arraysize(args))), |
2931 Object); | 3007 Object); |
2932 } | 3008 } |
2933 | 3009 |
2934 | 3010 |
| 3011 MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate, |
| 3012 Handle<Object> receiver, |
| 3013 uint32_t index, |
| 3014 Handle<Object> value, |
| 3015 StrictMode strict_mode) { |
| 3016 if (strict_mode != STRICT) return value; |
| 3017 |
| 3018 Handle<Object> args[] = {isolate->factory()->NewNumberFromUint(index), |
| 3019 receiver}; |
| 3020 THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property", |
| 3021 HandleVector(args, arraysize(args))), |
| 3022 Object); |
| 3023 } |
| 3024 |
| 3025 |
2935 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, | 3026 MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, |
2936 Handle<Object> value) { | 3027 Handle<Object> value) { |
2937 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot | 3028 // Proxies are handled on the WithHandler path. Other non-JSObjects cannot |
2938 // have own properties. | 3029 // have own properties. |
2939 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 3030 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
2940 | 3031 |
2941 // Store on the holder which may be hidden behind the receiver. | 3032 // Store on the holder which may be hidden behind the receiver. |
2942 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); | 3033 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); |
2943 | 3034 |
2944 // Old value for the observation change record. | 3035 // Old value for the observation change record. |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4072 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( | 4163 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( |
4073 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, | 4164 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4074 bool check_prototype) { | 4165 bool check_prototype) { |
4075 Isolate* isolate = object->GetIsolate(); | 4166 Isolate* isolate = object->GetIsolate(); |
4076 HandleScope scope(isolate); | 4167 HandleScope scope(isolate); |
4077 | 4168 |
4078 // Make sure that the top context does not change when doing | 4169 // Make sure that the top context does not change when doing |
4079 // callbacks or interceptor calls. | 4170 // callbacks or interceptor calls. |
4080 AssertNoContextChange ncc(isolate); | 4171 AssertNoContextChange ncc(isolate); |
4081 | 4172 |
| 4173 Maybe<PropertyAttributes> from_interceptor = |
| 4174 GetElementAttributeFromInterceptor(object, receiver, index); |
| 4175 if (!from_interceptor.has_value) return Maybe<PropertyAttributes>(); |
| 4176 if (from_interceptor.value != ABSENT) return maybe(from_interceptor.value); |
| 4177 |
| 4178 return GetElementAttributeWithoutInterceptor(object, receiver, index, |
| 4179 check_prototype); |
| 4180 } |
| 4181 |
| 4182 |
| 4183 Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor( |
| 4184 Handle<JSObject> object, Handle<Object> receiver, uint32_t index) { |
| 4185 Isolate* isolate = object->GetIsolate(); |
| 4186 AssertNoContextChange ncc(isolate); |
| 4187 |
4082 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | 4188 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
4083 PropertyCallbackArguments args( | 4189 PropertyCallbackArguments args( |
4084 isolate, interceptor->data(), *receiver, *object); | 4190 isolate, interceptor->data(), *receiver, *object); |
4085 if (!interceptor->query()->IsUndefined()) { | 4191 if (!interceptor->query()->IsUndefined()) { |
4086 v8::IndexedPropertyQueryCallback query = | 4192 v8::IndexedPropertyQueryCallback query = |
4087 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); | 4193 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
4088 LOG(isolate, | 4194 LOG(isolate, |
4089 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); | 4195 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); |
4090 v8::Handle<v8::Integer> result = args.Call(query, index); | 4196 v8::Handle<v8::Integer> result = args.Call(query, index); |
4091 if (!result.IsEmpty()) | 4197 if (!result.IsEmpty()) |
4092 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); | 4198 return maybe(static_cast<PropertyAttributes>(result->Int32Value())); |
4093 } else if (!interceptor->getter()->IsUndefined()) { | 4199 } else if (!interceptor->getter()->IsUndefined()) { |
4094 v8::IndexedPropertyGetterCallback getter = | 4200 v8::IndexedPropertyGetterCallback getter = |
4095 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | 4201 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
4096 LOG(isolate, | 4202 LOG(isolate, |
4097 ApiIndexedPropertyAccess( | 4203 ApiIndexedPropertyAccess( |
4098 "interceptor-indexed-get-has", *object, index)); | 4204 "interceptor-indexed-get-has", *object, index)); |
4099 v8::Handle<v8::Value> result = args.Call(getter, index); | 4205 v8::Handle<v8::Value> result = args.Call(getter, index); |
4100 if (!result.IsEmpty()) return maybe(NONE); | 4206 if (!result.IsEmpty()) return maybe(NONE); |
4101 } | 4207 } |
4102 | 4208 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>()); |
4103 return GetElementAttributeWithoutInterceptor( | 4209 return maybe(ABSENT); |
4104 object, receiver, index, check_prototype); | |
4105 } | 4210 } |
4106 | 4211 |
4107 | 4212 |
4108 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor( | 4213 Maybe<PropertyAttributes> JSObject::GetElementAttributeWithoutInterceptor( |
4109 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, | 4214 Handle<JSObject> object, Handle<JSReceiver> receiver, uint32_t index, |
4110 bool check_prototype) { | 4215 bool check_prototype) { |
4111 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( | 4216 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( |
4112 receiver, object, index); | 4217 receiver, object, index); |
4113 if (attr != ABSENT) return maybe(attr); | 4218 if (attr != ABSENT) return maybe(attr); |
4114 | 4219 |
(...skipping 7749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11864 if (structure->IsDeclaredAccessorInfo()) { | 11969 if (structure->IsDeclaredAccessorInfo()) { |
11865 return GetDeclaredAccessorProperty( | 11970 return GetDeclaredAccessorProperty( |
11866 receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate); | 11971 receiver, Handle<DeclaredAccessorInfo>::cast(structure), isolate); |
11867 } | 11972 } |
11868 | 11973 |
11869 UNREACHABLE(); | 11974 UNREACHABLE(); |
11870 return MaybeHandle<Object>(); | 11975 return MaybeHandle<Object>(); |
11871 } | 11976 } |
11872 | 11977 |
11873 | 11978 |
11874 MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, | 11979 MaybeHandle<Object> JSObject::SetElementWithCallback( |
11875 Handle<Object> structure, | 11980 Handle<Object> object, Handle<Object> structure, uint32_t index, |
11876 uint32_t index, | 11981 Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode) { |
11877 Handle<Object> value, | 11982 Isolate* isolate = holder->GetIsolate(); |
11878 Handle<JSObject> holder, | |
11879 StrictMode strict_mode) { | |
11880 Isolate* isolate = object->GetIsolate(); | |
11881 | 11983 |
11882 // We should never get here to initialize a const with the hole | 11984 // We should never get here to initialize a const with the hole |
11883 // value since a const declaration would conflict with the setter. | 11985 // value since a const declaration would conflict with the setter. |
11884 DCHECK(!value->IsTheHole()); | 11986 DCHECK(!value->IsTheHole()); |
11885 DCHECK(!structure->IsForeign()); | 11987 DCHECK(!structure->IsForeign()); |
11886 if (structure->IsExecutableAccessorInfo()) { | 11988 if (structure->IsExecutableAccessorInfo()) { |
11887 // api style callbacks | 11989 // api style callbacks |
11888 Handle<ExecutableAccessorInfo> data = | 11990 Handle<ExecutableAccessorInfo> data = |
11889 Handle<ExecutableAccessorInfo>::cast(structure); | 11991 Handle<ExecutableAccessorInfo>::cast(structure); |
11890 Object* call_obj = data->setter(); | 11992 Object* call_obj = data->setter(); |
11891 v8::AccessorNameSetterCallback call_fun = | 11993 v8::AccessorNameSetterCallback call_fun = |
11892 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj); | 11994 v8::ToCData<v8::AccessorNameSetterCallback>(call_obj); |
11893 if (call_fun == NULL) return value; | 11995 if (call_fun == NULL) return value; |
11894 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11996 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
11895 Handle<String> key(isolate->factory()->NumberToString(number)); | 11997 Handle<String> key(isolate->factory()->NumberToString(number)); |
11896 LOG(isolate, ApiNamedPropertyAccess("store", *object, *key)); | 11998 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key)); |
11897 PropertyCallbackArguments | 11999 PropertyCallbackArguments |
11898 args(isolate, data->data(), *object, *holder); | 12000 args(isolate, data->data(), *object, *holder); |
11899 args.Call(call_fun, | 12001 args.Call(call_fun, |
11900 v8::Utils::ToLocal(key), | 12002 v8::Utils::ToLocal(key), |
11901 v8::Utils::ToLocal(value)); | 12003 v8::Utils::ToLocal(value)); |
11902 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12004 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
11903 return value; | 12005 return value; |
11904 } | 12006 } |
11905 | 12007 |
11906 if (structure->IsAccessorPair()) { | 12008 if (structure->IsAccessorPair()) { |
(...skipping 4506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16413 Handle<DependentCode> codes = | 16515 Handle<DependentCode> codes = |
16414 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), | 16516 DependentCode::Insert(handle(cell->dependent_code(), info->isolate()), |
16415 DependentCode::kPropertyCellChangedGroup, | 16517 DependentCode::kPropertyCellChangedGroup, |
16416 info->object_wrapper()); | 16518 info->object_wrapper()); |
16417 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 16519 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
16418 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 16520 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
16419 cell, info->zone()); | 16521 cell, info->zone()); |
16420 } | 16522 } |
16421 | 16523 |
16422 } } // namespace v8::internal | 16524 } } // namespace v8::internal |
OLD | NEW |