| 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 <iomanip> | 5 #include <iomanip> |
| 6 #include <sstream> | 6 #include <sstream> |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
| (...skipping 6353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6364 ReoptimizeIfPrototype(object); | 6364 ReoptimizeIfPrototype(object); |
| 6365 } | 6365 } |
| 6366 | 6366 |
| 6367 | 6367 |
| 6368 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, | 6368 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
| 6369 Handle<Name> name, | 6369 Handle<Name> name, |
| 6370 Handle<Object> getter, | 6370 Handle<Object> getter, |
| 6371 Handle<Object> setter, | 6371 Handle<Object> setter, |
| 6372 PropertyAttributes attributes) { | 6372 PropertyAttributes attributes) { |
| 6373 Isolate* isolate = object->GetIsolate(); | 6373 Isolate* isolate = object->GetIsolate(); |
| 6374 // Check access rights if needed. | |
| 6375 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { | |
| 6376 isolate->ReportFailedAccessCheck(object); | |
| 6377 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
| 6378 return isolate->factory()->undefined_value(); | |
| 6379 } | |
| 6380 | |
| 6381 if (object->IsJSGlobalProxy()) { | |
| 6382 PrototypeIterator iter(isolate, object); | |
| 6383 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | |
| 6384 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | |
| 6385 DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), | |
| 6386 name, getter, setter, attributes); | |
| 6387 return isolate->factory()->undefined_value(); | |
| 6388 } | |
| 6389 | 6374 |
| 6390 // Make sure that the top context does not change when doing callbacks or | 6375 // Make sure that the top context does not change when doing callbacks or |
| 6391 // interceptor calls. | 6376 // interceptor calls. |
| 6392 AssertNoContextChange ncc(isolate); | 6377 AssertNoContextChange ncc(isolate); |
| 6393 | 6378 |
| 6394 // Try to flatten before operating on the string. | 6379 // Try to flatten before operating on the string. |
| 6395 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 6380 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 6396 | 6381 |
| 6397 uint32_t index = 0; | 6382 uint32_t index = 0; |
| 6398 bool is_element = name->AsArrayIndex(&index); | 6383 LookupIterator::Configuration c = LookupIterator::HIDDEN_SKIP_INTERCEPTOR; |
| 6384 LookupIterator it = name->AsArrayIndex(&index) |
| 6385 ? LookupIterator(isolate, object, index, c) |
| 6386 : LookupIterator(object, name, c); |
| 6387 |
| 6388 if (it.state() == LookupIterator::ACCESS_CHECK) { |
| 6389 if (!it.HasAccess()) { |
| 6390 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); |
| 6391 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6392 return isolate->factory()->undefined_value(); |
| 6393 } |
| 6394 it.Next(); |
| 6395 } |
| 6399 | 6396 |
| 6400 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6397 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6401 bool is_observed = object->map()->is_observed() && | 6398 bool is_observed = object->map()->is_observed() && |
| 6402 !isolate->IsInternallyUsedPropertyName(name); | 6399 !isolate->IsInternallyUsedPropertyName(name); |
| 6403 bool preexists = false; | 6400 bool preexists = false; |
| 6404 if (is_observed) { | 6401 if (is_observed) { |
| 6405 if (is_element) { | 6402 CHECK(GetPropertyAttributes(&it).IsJust()); |
| 6406 Maybe<bool> maybe = HasOwnElement(object, index); | 6403 preexists = it.IsFound(); |
| 6407 // Workaround for a GCC 4.4.3 bug which leads to "‘preexists’ may be used | 6404 if (preexists && (it.state() == LookupIterator::DATA || |
| 6408 // uninitialized in this function". | 6405 it.GetAccessors()->IsAccessorInfo())) { |
| 6409 if (!maybe.IsJust()) { | 6406 old_value = GetProperty(&it).ToHandleChecked(); |
| 6410 DCHECK(false); | |
| 6411 return isolate->factory()->undefined_value(); | |
| 6412 } | |
| 6413 preexists = maybe.FromJust(); | |
| 6414 if (preexists && GetOwnElementAccessorPair(object, index).is_null()) { | |
| 6415 old_value = | |
| 6416 Object::GetElement(isolate, object, index).ToHandleChecked(); | |
| 6417 } | |
| 6418 } else { | |
| 6419 LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); | |
| 6420 CHECK(GetPropertyAttributes(&it).IsJust()); | |
| 6421 preexists = it.IsFound(); | |
| 6422 if (preexists && (it.state() == LookupIterator::DATA || | |
| 6423 it.GetAccessors()->IsAccessorInfo())) { | |
| 6424 old_value = GetProperty(&it).ToHandleChecked(); | |
| 6425 } | |
| 6426 } | 6407 } |
| 6427 } | 6408 } |
| 6428 | 6409 |
| 6429 if (is_element) { | 6410 if (it.IsElement()) { |
| 6430 DefineElementAccessor(object, index, getter, setter, attributes); | 6411 DefineElementAccessor(it.GetStoreTarget(), index, getter, setter, |
| 6412 attributes); |
| 6431 } else { | 6413 } else { |
| 6432 DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || | 6414 DCHECK(getter->IsSpecFunction() || getter->IsUndefined() || |
| 6433 getter->IsNull()); | 6415 getter->IsNull()); |
| 6434 DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || | 6416 DCHECK(setter->IsSpecFunction() || setter->IsUndefined() || |
| 6435 setter->IsNull()); | 6417 setter->IsNull()); |
| 6436 // At least one of the accessors needs to be a new value. | 6418 // At least one of the accessors needs to be a new value. |
| 6437 DCHECK(!getter->IsNull() || !setter->IsNull()); | 6419 DCHECK(!getter->IsNull() || !setter->IsNull()); |
| 6438 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | |
| 6439 if (it.state() == LookupIterator::ACCESS_CHECK) { | |
| 6440 // We already did an access check before. We do have access. | |
| 6441 it.Next(); | |
| 6442 } | |
| 6443 if (!getter->IsNull()) { | 6420 if (!getter->IsNull()) { |
| 6444 it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); | 6421 it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); |
| 6445 } | 6422 } |
| 6446 if (!setter->IsNull()) { | 6423 if (!setter->IsNull()) { |
| 6447 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); | 6424 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); |
| 6448 } | 6425 } |
| 6449 } | 6426 } |
| 6450 | 6427 |
| 6451 if (is_observed) { | 6428 if (is_observed) { |
| 6452 const char* type = preexists ? "reconfigure" : "add"; | 6429 const char* type = preexists ? "reconfigure" : "add"; |
| (...skipping 10223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16676 Handle<Object> new_value) { | 16653 Handle<Object> new_value) { |
| 16677 if (cell->value() != *new_value) { | 16654 if (cell->value() != *new_value) { |
| 16678 cell->set_value(*new_value); | 16655 cell->set_value(*new_value); |
| 16679 Isolate* isolate = cell->GetIsolate(); | 16656 Isolate* isolate = cell->GetIsolate(); |
| 16680 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16657 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16681 isolate, DependentCode::kPropertyCellChangedGroup); | 16658 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16682 } | 16659 } |
| 16683 } | 16660 } |
| 16684 } // namespace internal | 16661 } // namespace internal |
| 16685 } // namespace v8 | 16662 } // namespace v8 |
| OLD | NEW |