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 |