OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 UNREACHABLE(); | 929 UNREACHABLE(); |
930 case LookupIterator::ACCESS_CHECK: | 930 case LookupIterator::ACCESS_CHECK: |
931 // Support calling this method without an active context, but refuse | 931 // Support calling this method without an active context, but refuse |
932 // access to access-checked objects in that case. | 932 // access to access-checked objects in that case. |
933 if (it->isolate()->context() != nullptr && it->HasAccess()) continue; | 933 if (it->isolate()->context() != nullptr && it->HasAccess()) continue; |
934 // Fall through. | 934 // Fall through. |
935 case LookupIterator::JSPROXY: | 935 case LookupIterator::JSPROXY: |
936 it->NotFound(); | 936 it->NotFound(); |
937 return it->isolate()->factory()->undefined_value(); | 937 return it->isolate()->factory()->undefined_value(); |
938 case LookupIterator::ACCESSOR: | 938 case LookupIterator::ACCESSOR: |
939 // TODO(verwaest): For now this doesn't call into | 939 // TODO(verwaest): For now this doesn't call into AccessorInfo, since |
940 // ExecutableAccessorInfo, since clients don't need it. Update once | 940 // clients don't need it. Update once relevant. |
941 // relevant. | |
942 it->NotFound(); | 941 it->NotFound(); |
943 return it->isolate()->factory()->undefined_value(); | 942 return it->isolate()->factory()->undefined_value(); |
944 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 943 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
945 return it->isolate()->factory()->undefined_value(); | 944 return it->isolate()->factory()->undefined_value(); |
946 case LookupIterator::DATA: | 945 case LookupIterator::DATA: |
947 return it->GetDataValue(); | 946 return it->GetDataValue(); |
948 } | 947 } |
949 } | 948 } |
950 return it->isolate()->factory()->undefined_value(); | 949 return it->isolate()->factory()->undefined_value(); |
951 } | 950 } |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 Handle<Object> receiver = it->GetReceiver(); | 1139 Handle<Object> receiver = it->GetReceiver(); |
1141 | 1140 |
1142 // We should never get here to initialize a const with the hole value since a | 1141 // We should never get here to initialize a const with the hole value since a |
1143 // const declaration would conflict with the getter. | 1142 // const declaration would conflict with the getter. |
1144 DCHECK(!structure->IsForeign()); | 1143 DCHECK(!structure->IsForeign()); |
1145 | 1144 |
1146 // API style callbacks. | 1145 // API style callbacks. |
1147 if (structure->IsAccessorInfo()) { | 1146 if (structure->IsAccessorInfo()) { |
1148 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1147 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
1149 Handle<Name> name = it->GetName(); | 1148 Handle<Name> name = it->GetName(); |
1150 Handle<ExecutableAccessorInfo> info = | 1149 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); |
1151 Handle<ExecutableAccessorInfo>::cast(structure); | |
1152 if (!info->IsCompatibleReceiver(*receiver)) { | 1150 if (!info->IsCompatibleReceiver(*receiver)) { |
1153 THROW_NEW_ERROR(isolate, | 1151 THROW_NEW_ERROR(isolate, |
1154 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | 1152 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, |
1155 name, receiver), | 1153 name, receiver), |
1156 Object); | 1154 Object); |
1157 } | 1155 } |
1158 | 1156 |
1159 v8::AccessorNameGetterCallback call_fun = | 1157 v8::AccessorNameGetterCallback call_fun = |
1160 v8::ToCData<v8::AccessorNameGetterCallback>(info->getter()); | 1158 v8::ToCData<v8::AccessorNameGetterCallback>(info->getter()); |
1161 if (call_fun == nullptr) return isolate->factory()->undefined_value(); | 1159 if (call_fun == nullptr) return isolate->factory()->undefined_value(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 ShouldThrow should_throw) { | 1198 ShouldThrow should_throw) { |
1201 Isolate* isolate = it->isolate(); | 1199 Isolate* isolate = it->isolate(); |
1202 Handle<Object> structure = it->GetAccessors(); | 1200 Handle<Object> structure = it->GetAccessors(); |
1203 Handle<Object> receiver = it->GetReceiver(); | 1201 Handle<Object> receiver = it->GetReceiver(); |
1204 | 1202 |
1205 // We should never get here to initialize a const with the hole value since a | 1203 // We should never get here to initialize a const with the hole value since a |
1206 // const declaration would conflict with the setter. | 1204 // const declaration would conflict with the setter. |
1207 DCHECK(!structure->IsForeign()); | 1205 DCHECK(!structure->IsForeign()); |
1208 | 1206 |
1209 // API style callbacks. | 1207 // API style callbacks. |
1210 if (structure->IsExecutableAccessorInfo()) { | 1208 if (structure->IsAccessorInfo()) { |
1211 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1209 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
1212 Handle<Name> name = it->GetName(); | 1210 Handle<Name> name = it->GetName(); |
1213 Handle<ExecutableAccessorInfo> info = | 1211 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); |
1214 Handle<ExecutableAccessorInfo>::cast(structure); | |
1215 if (!info->IsCompatibleReceiver(*receiver)) { | 1212 if (!info->IsCompatibleReceiver(*receiver)) { |
1216 isolate->Throw(*isolate->factory()->NewTypeError( | 1213 isolate->Throw(*isolate->factory()->NewTypeError( |
1217 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); | 1214 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
1218 return Nothing<bool>(); | 1215 return Nothing<bool>(); |
1219 } | 1216 } |
1220 | 1217 |
1221 v8::AccessorNameSetterCallback call_fun = | 1218 v8::AccessorNameSetterCallback call_fun = |
1222 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); | 1219 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); |
1223 if (call_fun == nullptr) return Just(true); | 1220 if (call_fun == nullptr) return Just(true); |
1224 // TODO(verwaest): Shouldn't this case be unreachable (at least in the | 1221 // TODO(verwaest): Shouldn't this case be unreachable (at least in the long |
1225 // long run?) Should we have ExecutableAccessorPairs with missing setter | 1222 // run?) Should we have AccessorInfo with missing setter that are |
1226 // that are "writable"? If they aren't writable, shouldn't we have bailed | 1223 // "writable"? If they aren't writable, shouldn't we have bailed out already |
1227 // out already earlier? | 1224 // earlier? |
1228 | 1225 |
1229 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); | 1226 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); |
1230 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); | 1227 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder); |
1231 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | 1228 args.Call(call_fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); |
1232 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); | 1229 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
1233 return Just(true); | 1230 return Just(true); |
1234 } | 1231 } |
1235 | 1232 |
1236 // Regular accessor. | 1233 // Regular accessor. |
1237 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 1234 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
(...skipping 3963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5201 DCHECK(object->map()->is_extensible() || | 5198 DCHECK(object->map()->is_extensible() || |
5202 it.isolate()->IsInternallyUsedPropertyName(name)); | 5199 it.isolate()->IsInternallyUsedPropertyName(name)); |
5203 #endif | 5200 #endif |
5204 CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR, | 5201 CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR, |
5205 CERTAINLY_NOT_STORE_FROM_KEYED) | 5202 CERTAINLY_NOT_STORE_FROM_KEYED) |
5206 .IsJust()); | 5203 .IsJust()); |
5207 } | 5204 } |
5208 | 5205 |
5209 | 5206 |
5210 // static | 5207 // static |
5211 void ExecutableAccessorInfo::ClearSetter(Handle<ExecutableAccessorInfo> info) { | 5208 void AccessorInfo::ClearSetter(Handle<AccessorInfo> info) { |
5212 Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr); | 5209 Handle<Object> object = v8::FromCData(info->GetIsolate(), nullptr); |
5213 info->set_setter(*object); | 5210 info->set_setter(*object); |
5214 } | 5211 } |
5215 | 5212 |
5216 | 5213 |
5217 // Reconfigures a property to a data property with attributes, even if it is not | 5214 // Reconfigures a property to a data property with attributes, even if it is not |
5218 // reconfigurable. | 5215 // reconfigurable. |
5219 // Requires a LookupIterator that does not look at the prototype chain beyond | 5216 // Requires a LookupIterator that does not look at the prototype chain beyond |
5220 // hidden prototypes. | 5217 // hidden prototypes. |
5221 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( | 5218 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( |
5222 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, | 5219 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, |
5223 ExecutableAccessorInfoHandling handling) { | 5220 AccessorInfoHandling handling) { |
5224 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes( | 5221 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes( |
5225 it, value, attributes, THROW_ON_ERROR, handling)); | 5222 it, value, attributes, THROW_ON_ERROR, handling)); |
5226 return value; | 5223 return value; |
5227 } | 5224 } |
5228 | 5225 |
5229 | 5226 |
5230 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( | 5227 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( |
5231 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, | 5228 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, |
5232 ShouldThrow should_throw, ExecutableAccessorInfoHandling handling) { | 5229 ShouldThrow should_throw, AccessorInfoHandling handling) { |
5233 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); | 5230 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); |
5234 bool is_observed = object->map()->is_observed() && | 5231 bool is_observed = object->map()->is_observed() && |
5235 (it->IsElement() || | 5232 (it->IsElement() || |
5236 !it->isolate()->IsInternallyUsedPropertyName(it->name())); | 5233 !it->isolate()->IsInternallyUsedPropertyName(it->name())); |
5237 | 5234 |
5238 for (; it->IsFound(); it->Next()) { | 5235 for (; it->IsFound(); it->Next()) { |
5239 switch (it->state()) { | 5236 switch (it->state()) { |
5240 case LookupIterator::JSPROXY: | 5237 case LookupIterator::JSPROXY: |
5241 case LookupIterator::NOT_FOUND: | 5238 case LookupIterator::NOT_FOUND: |
5242 case LookupIterator::TRANSITION: | 5239 case LookupIterator::TRANSITION: |
(...skipping 18 matching lines...) Expand all Loading... |
5261 case LookupIterator::INTERCEPTOR: | 5258 case LookupIterator::INTERCEPTOR: |
5262 if (handling == DONT_FORCE_FIELD) { | 5259 if (handling == DONT_FORCE_FIELD) { |
5263 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); | 5260 Maybe<bool> result = JSObject::SetPropertyWithInterceptor(it, value); |
5264 if (result.IsNothing() || result.FromJust()) return result; | 5261 if (result.IsNothing() || result.FromJust()) return result; |
5265 } | 5262 } |
5266 break; | 5263 break; |
5267 | 5264 |
5268 case LookupIterator::ACCESSOR: { | 5265 case LookupIterator::ACCESSOR: { |
5269 Handle<Object> accessors = it->GetAccessors(); | 5266 Handle<Object> accessors = it->GetAccessors(); |
5270 | 5267 |
5271 // Special handling for ExecutableAccessorInfo, which behaves like a | 5268 // Special handling for AccessorInfo, which behaves like a data |
5272 // data property. | 5269 // property. |
5273 if (accessors->IsExecutableAccessorInfo() && | 5270 if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) { |
5274 handling == DONT_FORCE_FIELD) { | |
5275 PropertyDetails details = it->property_details(); | 5271 PropertyDetails details = it->property_details(); |
5276 // Ensure the context isn't changed after calling into accessors. | 5272 // Ensure the context isn't changed after calling into accessors. |
5277 AssertNoContextChange ncc(it->isolate()); | 5273 AssertNoContextChange ncc(it->isolate()); |
5278 | 5274 |
5279 Maybe<bool> result = | 5275 Maybe<bool> result = |
5280 JSObject::SetPropertyWithAccessor(it, value, should_throw); | 5276 JSObject::SetPropertyWithAccessor(it, value, should_throw); |
5281 if (result.IsNothing() || !result.FromJust()) return result; | 5277 if (result.IsNothing() || !result.FromJust()) return result; |
5282 | 5278 |
5283 if (details.attributes() == attributes) return Just(true); | 5279 if (details.attributes() == attributes) return Just(true); |
5284 | 5280 |
5285 // Reconfigure the accessor if attributes mismatch. | 5281 // Reconfigure the accessor if attributes mismatch. |
5286 Handle<ExecutableAccessorInfo> new_data = Accessors::CloneAccessor( | 5282 Handle<AccessorInfo> new_data = Accessors::CloneAccessor( |
5287 it->isolate(), Handle<ExecutableAccessorInfo>::cast(accessors)); | 5283 it->isolate(), Handle<AccessorInfo>::cast(accessors)); |
5288 new_data->set_property_attributes(attributes); | 5284 new_data->set_property_attributes(attributes); |
5289 // By clearing the setter we don't have to introduce a lookup to | 5285 // By clearing the setter we don't have to introduce a lookup to |
5290 // the setter, simply make it unavailable to reflect the | 5286 // the setter, simply make it unavailable to reflect the |
5291 // attributes. | 5287 // attributes. |
5292 if (attributes & READ_ONLY) { | 5288 if (attributes & READ_ONLY) AccessorInfo::ClearSetter(new_data); |
5293 ExecutableAccessorInfo::ClearSetter(new_data); | |
5294 } | |
5295 | 5289 |
5296 it->TransitionToAccessorPair(new_data, attributes); | 5290 it->TransitionToAccessorPair(new_data, attributes); |
5297 } else { | 5291 } else { |
5298 it->ReconfigureDataProperty(value, attributes); | 5292 it->ReconfigureDataProperty(value, attributes); |
5299 } | 5293 } |
5300 | 5294 |
5301 if (is_observed) { | 5295 if (is_observed) { |
5302 RETURN_ON_EXCEPTION_VALUE( | 5296 RETURN_ON_EXCEPTION_VALUE( |
5303 it->isolate(), | 5297 it->isolate(), |
5304 EnqueueChangeRecord(object, "reconfigure", it->GetName(), | 5298 EnqueueChangeRecord(object, "reconfigure", it->GetName(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5346 } | 5340 } |
5347 } | 5341 } |
5348 | 5342 |
5349 return AddDataProperty(it, value, attributes, should_throw, | 5343 return AddDataProperty(it, value, attributes, should_throw, |
5350 CERTAINLY_NOT_STORE_FROM_KEYED); | 5344 CERTAINLY_NOT_STORE_FROM_KEYED); |
5351 } | 5345 } |
5352 | 5346 |
5353 | 5347 |
5354 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( | 5348 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( |
5355 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, | 5349 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, |
5356 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { | 5350 PropertyAttributes attributes, AccessorInfoHandling handling) { |
5357 DCHECK(!value->IsTheHole()); | 5351 DCHECK(!value->IsTheHole()); |
5358 LookupIterator it(object, name, LookupIterator::OWN); | 5352 LookupIterator it(object, name, LookupIterator::OWN); |
5359 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); | 5353 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); |
5360 } | 5354 } |
5361 | 5355 |
5362 | 5356 |
5363 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes( | 5357 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes( |
5364 Handle<JSObject> object, uint32_t index, Handle<Object> value, | 5358 Handle<JSObject> object, uint32_t index, Handle<Object> value, |
5365 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { | 5359 PropertyAttributes attributes, AccessorInfoHandling handling) { |
5366 Isolate* isolate = object->GetIsolate(); | 5360 Isolate* isolate = object->GetIsolate(); |
5367 LookupIterator it(isolate, object, index, LookupIterator::OWN); | 5361 LookupIterator it(isolate, object, index, LookupIterator::OWN); |
5368 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); | 5362 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); |
5369 } | 5363 } |
5370 | 5364 |
5371 | 5365 |
5372 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes( | 5366 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes( |
5373 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, | 5367 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, |
5374 PropertyAttributes attributes, ExecutableAccessorInfoHandling handling) { | 5368 PropertyAttributes attributes, AccessorInfoHandling handling) { |
5375 Isolate* isolate = object->GetIsolate(); | 5369 Isolate* isolate = object->GetIsolate(); |
5376 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name, | 5370 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name, |
5377 LookupIterator::OWN); | 5371 LookupIterator::OWN); |
5378 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); | 5372 return DefineOwnPropertyIgnoreAttributes(&it, value, attributes, handling); |
5379 } | 5373 } |
5380 | 5374 |
5381 | 5375 |
5382 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( | 5376 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor( |
5383 LookupIterator* it) { | 5377 LookupIterator* it) { |
5384 Isolate* isolate = it->isolate(); | 5378 Isolate* isolate = it->isolate(); |
(...skipping 14306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19691 if (cell->value() != *new_value) { | 19685 if (cell->value() != *new_value) { |
19692 cell->set_value(*new_value); | 19686 cell->set_value(*new_value); |
19693 Isolate* isolate = cell->GetIsolate(); | 19687 Isolate* isolate = cell->GetIsolate(); |
19694 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19688 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19695 isolate, DependentCode::kPropertyCellChangedGroup); | 19689 isolate, DependentCode::kPropertyCellChangedGroup); |
19696 } | 19690 } |
19697 } | 19691 } |
19698 | 19692 |
19699 } // namespace internal | 19693 } // namespace internal |
19700 } // namespace v8 | 19694 } // namespace v8 |
OLD | NEW |