Chromium Code Reviews| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "accessors.h" | 7 #include "accessors.h" |
| 8 #include "allocation-site-scopes.h" | 8 #include "allocation-site-scopes.h" |
| 9 #include "api.h" | 9 #include "api.h" |
| 10 #include "arguments.h" | 10 #include "arguments.h" |
| (...skipping 4300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4311 return result; | 4311 return result; |
| 4312 } | 4312 } |
| 4313 | 4313 |
| 4314 | 4314 |
| 4315 // Set a real local property, even if it is READ_ONLY. If the property is not | 4315 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 4316 // present, add it with attributes NONE. This code is an exact clone of | 4316 // present, add it with attributes NONE. This code is an exact clone of |
| 4317 // SetProperty, with the check for IsReadOnly and the check for a | 4317 // SetProperty, with the check for IsReadOnly and the check for a |
| 4318 // callback setter removed. The two lines looking up the LookupResult | 4318 // callback setter removed. The two lines looking up the LookupResult |
| 4319 // result are also added. If one of the functions is changed, the other | 4319 // result are also added. If one of the functions is changed, the other |
| 4320 // should be. | 4320 // should be. |
| 4321 // Note that this method cannot be used to set the prototype of a function | |
| 4322 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | |
| 4323 // doesn't handle function prototypes correctly. | |
| 4324 MaybeHandle<Object> JSObject::SetLocalPropertyIgnoreAttributes( | 4321 MaybeHandle<Object> JSObject::SetLocalPropertyIgnoreAttributes( |
| 4325 Handle<JSObject> object, | 4322 Handle<JSObject> object, |
| 4326 Handle<Name> name, | 4323 Handle<Name> name, |
| 4327 Handle<Object> value, | 4324 Handle<Object> value, |
| 4328 PropertyAttributes attributes, | 4325 PropertyAttributes attributes, |
| 4329 ValueType value_type, | 4326 ValueType value_type, |
| 4330 StoreMode mode, | 4327 StoreMode mode, |
| 4331 ExtensibilityCheck extensibility_check, | 4328 ExtensibilityCheck extensibility_check, |
| 4332 StoreFromKeyed store_from_keyed) { | 4329 StoreFromKeyed store_from_keyed, |
| 4330 ExecutableAccessorInfoHandling handling) { | |
| 4333 Isolate* isolate = object->GetIsolate(); | 4331 Isolate* isolate = object->GetIsolate(); |
| 4334 | 4332 |
| 4335 // Make sure that the top context does not change when doing callbacks or | 4333 // Make sure that the top context does not change when doing callbacks or |
| 4336 // interceptor calls. | 4334 // interceptor calls. |
| 4337 AssertNoContextChange ncc(isolate); | 4335 AssertNoContextChange ncc(isolate); |
| 4338 | 4336 |
| 4339 LookupResult lookup(isolate); | 4337 LookupResult lookup(isolate); |
| 4340 object->LocalLookup(name, &lookup, true); | 4338 object->LocalLookup(name, &lookup, true); |
| 4341 if (!lookup.IsFound()) { | 4339 if (!lookup.IsFound()) { |
| 4342 object->map()->LookupTransition(*object, *name, &lookup); | 4340 object->map()->LookupTransition(*object, *name, &lookup); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4377 PropertyAttributes old_attributes = ABSENT; | 4375 PropertyAttributes old_attributes = ABSENT; |
| 4378 bool is_observed = object->map()->is_observed() && | 4376 bool is_observed = object->map()->is_observed() && |
| 4379 *name != isolate->heap()->hidden_string(); | 4377 *name != isolate->heap()->hidden_string(); |
| 4380 if (is_observed && lookup.IsProperty()) { | 4378 if (is_observed && lookup.IsProperty()) { |
| 4381 if (lookup.IsDataProperty()) { | 4379 if (lookup.IsDataProperty()) { |
| 4382 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked(); | 4380 old_value = Object::GetPropertyOrElement(object, name).ToHandleChecked(); |
| 4383 } | 4381 } |
| 4384 old_attributes = lookup.GetAttributes(); | 4382 old_attributes = lookup.GetAttributes(); |
| 4385 } | 4383 } |
| 4386 | 4384 |
| 4385 bool dont_enqueue_records = false; | |
| 4386 | |
| 4387 // Check of IsReadOnly removed from here in clone. | 4387 // Check of IsReadOnly removed from here in clone. |
| 4388 if (lookup.IsTransition()) { | 4388 if (lookup.IsTransition()) { |
| 4389 Handle<Object> result; | 4389 Handle<Object> result; |
| 4390 ASSIGN_RETURN_ON_EXCEPTION( | 4390 ASSIGN_RETURN_ON_EXCEPTION( |
| 4391 isolate, result, | 4391 isolate, result, |
| 4392 SetPropertyUsingTransition( | 4392 SetPropertyUsingTransition( |
| 4393 handle(lookup.holder()), &lookup, name, value, attributes), | 4393 handle(lookup.holder()), &lookup, name, value, attributes), |
| 4394 Object); | 4394 Object); |
| 4395 } else { | 4395 } else { |
| 4396 switch (lookup.type()) { | 4396 switch (lookup.type()) { |
| 4397 case NORMAL: | 4397 case NORMAL: |
| 4398 ReplaceSlowProperty(object, name, value, attributes); | 4398 ReplaceSlowProperty(object, name, value, attributes); |
| 4399 break; | 4399 break; |
| 4400 case FIELD: | 4400 case FIELD: |
| 4401 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); | 4401 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4402 break; | 4402 break; |
| 4403 case CONSTANT: | 4403 case CONSTANT: |
| 4404 // Only replace the constant if necessary. | 4404 // Only replace the constant if necessary. |
| 4405 if (lookup.GetAttributes() != attributes || | 4405 if (lookup.GetAttributes() != attributes || |
| 4406 *value != lookup.GetConstant()) { | 4406 *value != lookup.GetConstant()) { |
| 4407 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); | 4407 SetPropertyToFieldWithAttributes(&lookup, name, value, attributes); |
| 4408 } | 4408 } |
| 4409 break; | 4409 break; |
| 4410 case CALLBACKS: | 4410 case CALLBACKS: |
| 4411 ConvertAndSetLocalProperty(&lookup, name, value, attributes); | 4411 { |
| 4412 Handle<Object> callback(lookup.GetCallbackObject(), isolate); | |
| 4413 if (callback->IsExecutableAccessorInfo() && | |
| 4414 handling == DONT_FORCE_FIELD) { | |
| 4415 Handle<Object> result; | |
| 4416 ASSIGN_RETURN_ON_EXCEPTION( | |
| 4417 isolate, result, | |
| 4418 JSObject::SetPropertyWithCallback(object, | |
| 4419 callback, | |
| 4420 name, | |
| 4421 value, | |
| 4422 handle(lookup.holder()), | |
| 4423 STRICT), | |
| 4424 Object); | |
| 4425 | |
| 4426 if (attributes != lookup.GetAttributes()) { | |
| 4427 Handle<ExecutableAccessorInfo> new_data = | |
| 4428 Accessors::CloneAccessor( | |
| 4429 isolate, Handle<ExecutableAccessorInfo>::cast(callback)); | |
| 4430 new_data->set_property_attributes(attributes); | |
| 4431 if (attributes & READ_ONLY) { | |
| 4432 // This way we don't have to introduce a lookup to the setter, | |
| 4433 // simply make it unavailable to reflect the attributes. | |
| 4434 new_data->clear_setter(); | |
| 4435 } | |
| 4436 | |
| 4437 SetPropertyCallback(object, name, new_data, attributes); | |
| 4438 } else if (is_observed) { | |
|
ulan
2014/05/23 10:14:48
Shouldn't we check is_observed independent of (att
mvstanton
2014/05/27 13:31:24
Good catch. And I renamed the variable from dont_e
| |
| 4439 // If we are setting the prototype of a function and are observed, | |
| 4440 // don't send change records because the prototype handles that | |
| 4441 // itself. | |
| 4442 dont_enqueue_records = object->IsJSFunction() && | |
| 4443 String::Equals(isolate->factory()->prototype_string(), | |
| 4444 Handle<String>::cast(name)) && | |
| 4445 Handle<JSFunction>::cast(object)->should_have_prototype(); | |
| 4446 } | |
| 4447 } else { | |
| 4448 ConvertAndSetLocalProperty(&lookup, name, value, attributes); | |
| 4449 } | |
| 4412 break; | 4450 break; |
| 4451 } | |
| 4413 case NONEXISTENT: | 4452 case NONEXISTENT: |
| 4414 case HANDLER: | 4453 case HANDLER: |
| 4415 case INTERCEPTOR: | 4454 case INTERCEPTOR: |
| 4416 UNREACHABLE(); | 4455 UNREACHABLE(); |
| 4417 } | 4456 } |
| 4418 } | 4457 } |
| 4419 | 4458 |
| 4420 if (is_observed) { | 4459 if (is_observed && !dont_enqueue_records) { |
| 4421 if (lookup.IsTransition()) { | 4460 if (lookup.IsTransition()) { |
| 4422 EnqueueChangeRecord(object, "add", name, old_value); | 4461 EnqueueChangeRecord(object, "add", name, old_value); |
| 4423 } else if (old_value->IsTheHole()) { | 4462 } else if (old_value->IsTheHole()) { |
| 4424 EnqueueChangeRecord(object, "reconfigure", name, old_value); | 4463 EnqueueChangeRecord(object, "reconfigure", name, old_value); |
| 4425 } else { | 4464 } else { |
| 4426 LookupResult new_lookup(isolate); | 4465 LookupResult new_lookup(isolate); |
| 4427 object->LocalLookup(name, &new_lookup, true); | 4466 object->LocalLookup(name, &new_lookup, true); |
| 4428 bool value_changed = false; | 4467 bool value_changed = false; |
| 4429 if (new_lookup.IsDataProperty()) { | 4468 if (new_lookup.IsDataProperty()) { |
| 4430 Handle<Object> new_value = | 4469 Handle<Object> new_value = |
| (...skipping 12845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17276 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17315 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 17277 static const char* error_messages_[] = { | 17316 static const char* error_messages_[] = { |
| 17278 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17317 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 17279 }; | 17318 }; |
| 17280 #undef ERROR_MESSAGES_TEXTS | 17319 #undef ERROR_MESSAGES_TEXTS |
| 17281 return error_messages_[reason]; | 17320 return error_messages_[reason]; |
| 17282 } | 17321 } |
| 17283 | 17322 |
| 17284 | 17323 |
| 17285 } } // namespace v8::internal | 17324 } } // namespace v8::internal |
| OLD | NEW |