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 1175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 | 1186 |
1187 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, | 1187 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate, |
1188 Handle<AccessorInfo> info, | 1188 Handle<AccessorInfo> info, |
1189 Handle<Map> map) { | 1189 Handle<Map> map) { |
1190 if (!info->HasExpectedReceiverType()) return true; | 1190 if (!info->HasExpectedReceiverType()) return true; |
1191 if (!map->IsJSObjectMap()) return false; | 1191 if (!map->IsJSObjectMap()) return false; |
1192 return FunctionTemplateInfo::cast(info->expected_receiver_type()) | 1192 return FunctionTemplateInfo::cast(info->expected_receiver_type()) |
1193 ->IsTemplateFor(*map); | 1193 ->IsTemplateFor(*map); |
1194 } | 1194 } |
1195 | 1195 |
1196 | |
1197 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, | 1196 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it, |
1198 Handle<Object> value, | 1197 Handle<Object> value, |
1199 ShouldThrow should_throw) { | 1198 ShouldThrow should_throw) { |
1200 Isolate* isolate = it->isolate(); | 1199 Isolate* isolate = it->isolate(); |
1201 Handle<Object> structure = it->GetAccessors(); | 1200 Handle<Object> structure = it->GetAccessors(); |
1202 Handle<Object> receiver = it->GetReceiver(); | 1201 Handle<Object> receiver = it->GetReceiver(); |
1203 | 1202 |
1204 // 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 |
1205 // const declaration would conflict with the setter. | 1204 // const declaration would conflict with the setter. |
1206 DCHECK(!structure->IsForeign()); | 1205 DCHECK(!structure->IsForeign()); |
1207 | 1206 |
1208 // API style callbacks. | 1207 // API style callbacks. |
1209 if (structure->IsAccessorInfo()) { | 1208 if (structure->IsAccessorInfo()) { |
1210 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1209 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
1211 Handle<Name> name = it->GetName(); | 1210 Handle<Name> name = it->GetName(); |
1212 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); | 1211 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); |
1213 if (!info->IsCompatibleReceiver(*receiver)) { | 1212 if (!info->IsCompatibleReceiver(*receiver)) { |
1214 isolate->Throw(*isolate->factory()->NewTypeError( | 1213 isolate->Throw(*isolate->factory()->NewTypeError( |
1215 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); | 1214 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
1216 return Nothing<bool>(); | 1215 return Nothing<bool>(); |
1217 } | 1216 } |
1218 | 1217 |
1219 v8::AccessorNameSetterCallback call_fun = | 1218 v8::AccessorNameSetterCallback call_fun = |
1220 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); | 1219 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); |
| 1220 // TODO(verwaest): We should not get here anymore once all AccessorInfos are |
| 1221 // marked as special_data_property. They cannot both be writable and not |
| 1222 // have a setter. |
1221 if (call_fun == nullptr) return Just(true); | 1223 if (call_fun == nullptr) return Just(true); |
1222 // TODO(verwaest): Shouldn't this case be unreachable (at least in the long | |
1223 // run?) Should we have AccessorInfo with missing setter that are | |
1224 // "writable"? If they aren't writable, shouldn't we have bailed out already | |
1225 // earlier? | |
1226 | 1224 |
1227 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); | 1225 LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name)); |
1228 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, | 1226 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, |
1229 should_throw); | 1227 should_throw); |
1230 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)); |
1231 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); | 1229 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
1232 return Just(true); | 1230 return Just(true); |
1233 } | 1231 } |
1234 | 1232 |
1235 // Regular accessor. | 1233 // Regular accessor. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1344 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 1342 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
1345 return it->factory()->undefined_value(); | 1343 return it->factory()->undefined_value(); |
1346 } | 1344 } |
1347 | 1345 |
1348 | 1346 |
1349 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( | 1347 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( |
1350 LookupIterator* it) { | 1348 LookupIterator* it) { |
1351 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 1349 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
1352 while (AllCanRead(it)) { | 1350 while (AllCanRead(it)) { |
1353 if (it->state() == LookupIterator::ACCESSOR) { | 1351 if (it->state() == LookupIterator::ACCESSOR) { |
1354 return Just(it->property_details().attributes()); | 1352 return Just(it->property_attributes()); |
1355 } | 1353 } |
1356 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 1354 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
1357 auto result = GetPropertyAttributesWithInterceptor(it); | 1355 auto result = GetPropertyAttributesWithInterceptor(it); |
1358 if (it->isolate()->has_scheduled_exception()) break; | 1356 if (it->isolate()->has_scheduled_exception()) break; |
1359 if (result.IsJust() && result.FromJust() != ABSENT) return result; | 1357 if (result.IsJust() && result.FromJust() != ABSENT) return result; |
1360 } | 1358 } |
1361 it->isolate()->ReportFailedAccessCheck(checked); | 1359 it->isolate()->ReportFailedAccessCheck(checked); |
1362 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), | 1360 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), |
1363 Nothing<PropertyAttributes>()); | 1361 Nothing<PropertyAttributes>()); |
1364 return Just(ABSENT); | 1362 return Just(ABSENT); |
(...skipping 2845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4210 should_throw); | 4208 should_throw); |
4211 } | 4209 } |
4212 break; | 4210 break; |
4213 | 4211 |
4214 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 4212 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
4215 case LookupIterator::ACCESSOR: | 4213 case LookupIterator::ACCESSOR: |
4216 return RedefineIncompatibleProperty(isolate, it->GetName(), value, | 4214 return RedefineIncompatibleProperty(isolate, it->GetName(), value, |
4217 should_throw); | 4215 should_throw); |
4218 | 4216 |
4219 case LookupIterator::DATA: { | 4217 case LookupIterator::DATA: { |
4220 PropertyDetails details = own_lookup.property_details(); | 4218 if (own_lookup.IsReadOnly()) { |
4221 if (details.IsReadOnly()) { | |
4222 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); | 4219 return WriteToReadOnlyProperty(&own_lookup, value, should_throw); |
4223 } | 4220 } |
4224 return SetDataProperty(&own_lookup, value); | 4221 return SetDataProperty(&own_lookup, value); |
4225 } | 4222 } |
4226 | 4223 |
4227 case LookupIterator::INTERCEPTOR: | 4224 case LookupIterator::INTERCEPTOR: |
4228 case LookupIterator::JSPROXY: { | 4225 case LookupIterator::JSPROXY: { |
4229 PropertyDescriptor desc; | 4226 PropertyDescriptor desc; |
4230 Maybe<bool> owned = | 4227 Maybe<bool> owned = |
4231 JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc); | 4228 JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc); |
(...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5259 if (result.IsNothing() || result.FromJust()) return result; | 5256 if (result.IsNothing() || result.FromJust()) return result; |
5260 } | 5257 } |
5261 break; | 5258 break; |
5262 | 5259 |
5263 case LookupIterator::ACCESSOR: { | 5260 case LookupIterator::ACCESSOR: { |
5264 Handle<Object> accessors = it->GetAccessors(); | 5261 Handle<Object> accessors = it->GetAccessors(); |
5265 | 5262 |
5266 // Special handling for AccessorInfo, which behaves like a data | 5263 // Special handling for AccessorInfo, which behaves like a data |
5267 // property. | 5264 // property. |
5268 if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) { | 5265 if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) { |
5269 PropertyDetails details = it->property_details(); | 5266 PropertyAttributes current_attributes = it->property_attributes(); |
5270 // Ensure the context isn't changed after calling into accessors. | 5267 // Ensure the context isn't changed after calling into accessors. |
5271 AssertNoContextChange ncc(it->isolate()); | 5268 AssertNoContextChange ncc(it->isolate()); |
5272 | 5269 |
| 5270 // Update the attributes before calling the setter. The setter may |
| 5271 // later change the shape of the property. |
| 5272 if (current_attributes != attributes) { |
| 5273 it->TransitionToAccessorPair(accessors, attributes); |
| 5274 } |
| 5275 |
5273 Maybe<bool> result = | 5276 Maybe<bool> result = |
5274 JSObject::SetPropertyWithAccessor(it, value, should_throw); | 5277 JSObject::SetPropertyWithAccessor(it, value, should_throw); |
5275 if (result.IsNothing() || !result.FromJust()) return result; | |
5276 | 5278 |
5277 if (details.attributes() == attributes) return Just(true); | 5279 if (current_attributes == attributes || result.IsNothing()) { |
| 5280 return result; |
| 5281 } |
5278 | 5282 |
5279 // Reconfigure the accessor if attributes mismatch. | |
5280 it->TransitionToAccessorPair(accessors, attributes); | |
5281 } else { | 5283 } else { |
5282 it->ReconfigureDataProperty(value, attributes); | 5284 it->ReconfigureDataProperty(value, attributes); |
5283 } | 5285 } |
5284 | 5286 |
5285 if (is_observed) { | 5287 if (is_observed) { |
5286 RETURN_ON_EXCEPTION_VALUE( | 5288 RETURN_ON_EXCEPTION_VALUE( |
5287 it->isolate(), | 5289 it->isolate(), |
5288 EnqueueChangeRecord(object, "reconfigure", it->GetName(), | 5290 EnqueueChangeRecord(object, "reconfigure", it->GetName(), |
5289 it->factory()->the_hole_value()), | 5291 it->factory()->the_hole_value()), |
5290 Nothing<bool>()); | 5292 Nothing<bool>()); |
5291 } | 5293 } |
5292 | 5294 |
5293 return Just(true); | 5295 return Just(true); |
5294 } | 5296 } |
5295 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5297 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5296 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, | 5298 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, |
5297 should_throw); | 5299 should_throw); |
5298 | 5300 |
5299 case LookupIterator::DATA: { | 5301 case LookupIterator::DATA: { |
5300 PropertyDetails details = it->property_details(); | |
5301 Handle<Object> old_value = it->factory()->the_hole_value(); | 5302 Handle<Object> old_value = it->factory()->the_hole_value(); |
5302 // Regular property update if the attributes match. | 5303 // Regular property update if the attributes match. |
5303 if (details.attributes() == attributes) { | 5304 if (it->property_attributes() == attributes) { |
5304 return SetDataProperty(it, value); | 5305 return SetDataProperty(it, value); |
5305 } | 5306 } |
5306 | 5307 |
5307 // Special case: properties of typed arrays cannot be reconfigured to | 5308 // Special case: properties of typed arrays cannot be reconfigured to |
5308 // non-writable nor to non-enumerable. | 5309 // non-writable nor to non-enumerable. |
5309 if (it->IsElement() && object->HasFixedTypedArrayElements()) { | 5310 if (it->IsElement() && object->HasFixedTypedArrayElements()) { |
5310 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), | 5311 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), |
5311 value, should_throw); | 5312 value, should_throw); |
5312 } | 5313 } |
5313 | 5314 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5449 if (result.FromJust() != ABSENT) return result; | 5450 if (result.FromJust() != ABSENT) return result; |
5450 break; | 5451 break; |
5451 } | 5452 } |
5452 case LookupIterator::ACCESS_CHECK: | 5453 case LookupIterator::ACCESS_CHECK: |
5453 if (it->HasAccess()) break; | 5454 if (it->HasAccess()) break; |
5454 return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); | 5455 return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); |
5455 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5456 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5456 return Just(ABSENT); | 5457 return Just(ABSENT); |
5457 case LookupIterator::ACCESSOR: | 5458 case LookupIterator::ACCESSOR: |
5458 case LookupIterator::DATA: | 5459 case LookupIterator::DATA: |
5459 return Just(it->property_details().attributes()); | 5460 return Just(it->property_attributes()); |
5460 } | 5461 } |
5461 } | 5462 } |
5462 return Just(ABSENT); | 5463 return Just(ABSENT); |
5463 } | 5464 } |
5464 | 5465 |
5465 | 5466 |
5466 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { | 5467 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) { |
5467 Handle<FixedArray> array( | 5468 Handle<FixedArray> array( |
5468 isolate->factory()->NewFixedArray(kEntries, TENURED)); | 5469 isolate->factory()->NewFixedArray(kEntries, TENURED)); |
5469 return Handle<NormalizedMapCache>::cast(array); | 5470 return Handle<NormalizedMapCache>::cast(array); |
(...skipping 1722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7192 DCHECK(proxy->map()->is_dictionary_map()); | 7193 DCHECK(proxy->map()->is_dictionary_map()); |
7193 Handle<Object> value = | 7194 Handle<Object> value = |
7194 desc->has_value() | 7195 desc->has_value() |
7195 ? desc->value() | 7196 ? desc->value() |
7196 : Handle<Object>::cast(isolate->factory()->undefined_value()); | 7197 : Handle<Object>::cast(isolate->factory()->undefined_value()); |
7197 | 7198 |
7198 LookupIterator it(proxy, private_name); | 7199 LookupIterator it(proxy, private_name); |
7199 | 7200 |
7200 if (it.IsFound()) { | 7201 if (it.IsFound()) { |
7201 DCHECK_EQ(LookupIterator::DATA, it.state()); | 7202 DCHECK_EQ(LookupIterator::DATA, it.state()); |
7202 DCHECK_EQ(DONT_ENUM, it.property_details().attributes()); | 7203 DCHECK_EQ(DONT_ENUM, it.property_attributes()); |
7203 it.WriteDataValue(value); | 7204 it.WriteDataValue(value); |
7204 return Just(true); | 7205 return Just(true); |
7205 } | 7206 } |
7206 | 7207 |
7207 Handle<NameDictionary> dict(proxy->property_dictionary()); | 7208 Handle<NameDictionary> dict(proxy->property_dictionary()); |
7208 PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell); | 7209 PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell); |
7209 Handle<NameDictionary> result = | 7210 Handle<NameDictionary> result = |
7210 NameDictionary::Add(dict, private_name, value, details); | 7211 NameDictionary::Add(dict, private_name, value, details); |
7211 if (!dict.is_identical_to(result)) proxy->set_properties(*result); | 7212 if (!dict.is_identical_to(result)) proxy->set_properties(*result); |
7212 return Just(true); | 7213 return Just(true); |
(...skipping 12531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19744 if (cell->value() != *new_value) { | 19745 if (cell->value() != *new_value) { |
19745 cell->set_value(*new_value); | 19746 cell->set_value(*new_value); |
19746 Isolate* isolate = cell->GetIsolate(); | 19747 Isolate* isolate = cell->GetIsolate(); |
19747 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19748 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19748 isolate, DependentCode::kPropertyCellChangedGroup); | 19749 isolate, DependentCode::kPropertyCellChangedGroup); |
19749 } | 19750 } |
19750 } | 19751 } |
19751 | 19752 |
19752 } // namespace internal | 19753 } // namespace internal |
19753 } // namespace v8 | 19754 } // namespace v8 |
OLD | NEW |