Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(905)

Side by Side Diff: src/objects.cc

Issue 1632603002: [api] Default native data property setter to replace the setter if the property is writable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/lookup.h ('k') | src/snapshot/serialize.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/lookup.h ('k') | src/snapshot/serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698