| 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 <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 7403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7414 } | 7414 } |
| 7415 | 7415 |
| 7416 | 7416 |
| 7417 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver, | 7417 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver, |
| 7418 IntegrityLevel level, | 7418 IntegrityLevel level, |
| 7419 ShouldThrow should_throw) { | 7419 ShouldThrow should_throw) { |
| 7420 DCHECK(level == SEALED || level == FROZEN); | 7420 DCHECK(level == SEALED || level == FROZEN); |
| 7421 | 7421 |
| 7422 if (receiver->IsJSObject()) { | 7422 if (receiver->IsJSObject()) { |
| 7423 Handle<JSObject> object = Handle<JSObject>::cast(receiver); | 7423 Handle<JSObject> object = Handle<JSObject>::cast(receiver); |
| 7424 |
| 7424 if (!object->HasSloppyArgumentsElements()) { // Fast path. | 7425 if (!object->HasSloppyArgumentsElements()) { // Fast path. |
| 7426 // prevent memory leaks by not adding unnecessary transitions |
| 7427 Maybe<bool> test = JSObject::TestIntegrityLevel(object, level); |
| 7428 MAYBE_RETURN(test, Nothing<bool>()); |
| 7429 if (test.FromJust()) return test; |
| 7430 |
| 7425 if (level == SEALED) { | 7431 if (level == SEALED) { |
| 7426 return JSObject::PreventExtensionsWithTransition<SEALED>(object, | 7432 return JSObject::PreventExtensionsWithTransition<SEALED>(object, |
| 7427 should_throw); | 7433 should_throw); |
| 7428 } else { | 7434 } else { |
| 7429 return JSObject::PreventExtensionsWithTransition<FROZEN>(object, | 7435 return JSObject::PreventExtensionsWithTransition<FROZEN>(object, |
| 7430 should_throw); | 7436 should_throw); |
| 7431 } | 7437 } |
| 7432 } | 7438 } |
| 7433 } | 7439 } |
| 7434 | 7440 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7470 ? no_conf | 7476 ? no_conf |
| 7471 : no_conf_no_write; | 7477 : no_conf_no_write; |
| 7472 MAYBE_RETURN( | 7478 MAYBE_RETURN( |
| 7473 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR), | 7479 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR), |
| 7474 Nothing<bool>()); | 7480 Nothing<bool>()); |
| 7475 } | 7481 } |
| 7476 } | 7482 } |
| 7477 return Just(true); | 7483 return Just(true); |
| 7478 } | 7484 } |
| 7479 | 7485 |
| 7486 namespace { |
| 7480 | 7487 |
| 7481 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object, | 7488 template <typename Dictionary> |
| 7482 IntegrityLevel level) { | 7489 bool TestDictionaryPropertiesIntegrityLevel(Dictionary dict, Isolate* isolate, |
| 7490 PropertyAttributes level) { |
| 7483 DCHECK(level == SEALED || level == FROZEN); | 7491 DCHECK(level == SEALED || level == FROZEN); |
| 7484 Isolate* isolate = object->GetIsolate(); | |
| 7485 | 7492 |
| 7486 Maybe<bool> extensible = JSReceiver::IsExtensible(object); | 7493 uint32_t capacity = dict->Capacity(); |
| 7494 for (uint32_t i = 0; i < capacity; i++) { |
| 7495 Object* key = dict->KeyAt(i); |
| 7496 if (!dict->IsKey(isolate, key) || key->FilterKey(ALL_PROPERTIES) || |
| 7497 dict->IsDeleted(i)) |
| 7498 continue; |
| 7499 PropertyDetails details = dict->DetailsAt(i); |
| 7500 if (details.IsConfigurable()) return false; |
| 7501 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) { |
| 7502 return false; |
| 7503 } |
| 7504 } |
| 7505 return true; |
| 7506 } |
| 7507 |
| 7508 bool TestFastPropertiesIntegrityLevel(Map* map, PropertyAttributes level) { |
| 7509 DCHECK(level == SEALED || level == FROZEN); |
| 7510 DCHECK_LT(LAST_CUSTOM_ELEMENTS_RECEIVER, map->instance_type()); |
| 7511 DCHECK(!map->is_dictionary_map()); |
| 7512 |
| 7513 DescriptorArray* descriptors = map->instance_descriptors(); |
| 7514 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 7515 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 7516 if (descriptors->GetKey(i)->IsPrivate()) continue; |
| 7517 PropertyDetails details = descriptors->GetDetails(i); |
| 7518 if (details.IsConfigurable()) return false; |
| 7519 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) { |
| 7520 return false; |
| 7521 } |
| 7522 } |
| 7523 return true; |
| 7524 } |
| 7525 |
| 7526 bool TestPropertiesIntegrityLevel(JSObject* object, PropertyAttributes level) { |
| 7527 DCHECK_LT(LAST_CUSTOM_ELEMENTS_RECEIVER, object->map()->instance_type()); |
| 7528 |
| 7529 if (object->HasFastProperties()) { |
| 7530 return TestFastPropertiesIntegrityLevel(object->map(), level); |
| 7531 } |
| 7532 |
| 7533 return TestDictionaryPropertiesIntegrityLevel(object->property_dictionary(), |
| 7534 object->GetIsolate(), level); |
| 7535 } |
| 7536 |
| 7537 bool TestElementsIntegrityLevel(JSObject* object, PropertyAttributes level) { |
| 7538 DCHECK(!object->HasSloppyArgumentsElements()); |
| 7539 |
| 7540 ElementsKind kind = object->GetElementsKind(); |
| 7541 |
| 7542 if (IsDictionaryElementsKind(kind)) { |
| 7543 return TestDictionaryPropertiesIntegrityLevel( |
| 7544 SeededNumberDictionary::cast(object->elements()), object->GetIsolate(), |
| 7545 level); |
| 7546 } |
| 7547 |
| 7548 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); |
| 7549 // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have |
| 7550 // PropertyAttributes so just test if empty |
| 7551 return accessor->NumberOfElements(object) == 0; |
| 7552 } |
| 7553 |
| 7554 bool FastTestIntegrityLevel(JSObject* object, PropertyAttributes level) { |
| 7555 DCHECK_LT(LAST_CUSTOM_ELEMENTS_RECEIVER, object->map()->instance_type()); |
| 7556 |
| 7557 return !object->map()->is_extensible() && |
| 7558 TestElementsIntegrityLevel(object, level) && |
| 7559 TestPropertiesIntegrityLevel(object, level); |
| 7560 } |
| 7561 |
| 7562 Maybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver, |
| 7563 PropertyAttributes level) { |
| 7564 DCHECK(level == SEALED || level == FROZEN); |
| 7565 |
| 7566 Maybe<bool> extensible = JSReceiver::IsExtensible(receiver); |
| 7487 MAYBE_RETURN(extensible, Nothing<bool>()); | 7567 MAYBE_RETURN(extensible, Nothing<bool>()); |
| 7488 if (extensible.FromJust()) return Just(false); | 7568 if (extensible.FromJust()) return Just(false); |
| 7489 | 7569 |
| 7570 Isolate* isolate = receiver->GetIsolate(); |
| 7571 |
| 7490 Handle<FixedArray> keys; | 7572 Handle<FixedArray> keys; |
| 7491 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7573 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 7492 isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>()); | 7574 isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>()); |
| 7493 | 7575 |
| 7494 for (int i = 0; i < keys->length(); ++i) { | 7576 for (int i = 0; i < keys->length(); ++i) { |
| 7495 Handle<Object> key(keys->get(i), isolate); | 7577 Handle<Object> key(keys->get(i), isolate); |
| 7496 PropertyDescriptor current_desc; | 7578 PropertyDescriptor current_desc; |
| 7497 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( | 7579 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( |
| 7498 isolate, object, key, ¤t_desc); | 7580 isolate, receiver, key, ¤t_desc); |
| 7499 MAYBE_RETURN(owned, Nothing<bool>()); | 7581 MAYBE_RETURN(owned, Nothing<bool>()); |
| 7500 if (owned.FromJust()) { | 7582 if (owned.FromJust()) { |
| 7501 if (current_desc.configurable()) return Just(false); | 7583 if (current_desc.configurable()) return Just(false); |
| 7502 if (level == FROZEN && | 7584 if (level == FROZEN && |
| 7503 PropertyDescriptor::IsDataDescriptor(¤t_desc) && | 7585 PropertyDescriptor::IsDataDescriptor(¤t_desc) && |
| 7504 current_desc.writable()) { | 7586 current_desc.writable()) { |
| 7505 return Just(false); | 7587 return Just(false); |
| 7506 } | 7588 } |
| 7507 } | 7589 } |
| 7508 } | 7590 } |
| 7509 return Just(true); | 7591 return Just(true); |
| 7510 } | 7592 } |
| 7511 | 7593 |
| 7594 } // namespace |
| 7595 |
| 7596 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver, |
| 7597 IntegrityLevel level) { |
| 7598 if (receiver->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER) { |
| 7599 return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver), |
| 7600 level); |
| 7601 } |
| 7602 return GenericTestIntegrityLevel(receiver, level); |
| 7603 } |
| 7604 |
| 7605 Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object, |
| 7606 IntegrityLevel level) { |
| 7607 if (object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && |
| 7608 !object->HasSloppyArgumentsElements()) { |
| 7609 return Just(FastTestIntegrityLevel(*object, level)); |
| 7610 } |
| 7611 return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(object), level); |
| 7612 } |
| 7512 | 7613 |
| 7513 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, | 7614 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, |
| 7514 ShouldThrow should_throw) { | 7615 ShouldThrow should_throw) { |
| 7515 if (object->IsJSProxy()) { | 7616 if (object->IsJSProxy()) { |
| 7516 return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object), | 7617 return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object), |
| 7517 should_throw); | 7618 should_throw); |
| 7518 } | 7619 } |
| 7519 DCHECK(object->IsJSObject()); | 7620 DCHECK(object->IsJSObject()); |
| 7520 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), | 7621 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), |
| 7521 should_throw); | 7622 should_throw); |
| (...skipping 12651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20173 // not | 20274 // not |
| 20174 // depend on this. | 20275 // depend on this. |
| 20175 return DICTIONARY_ELEMENTS; | 20276 return DICTIONARY_ELEMENTS; |
| 20176 } | 20277 } |
| 20177 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20278 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
| 20178 return kind; | 20279 return kind; |
| 20179 } | 20280 } |
| 20180 } | 20281 } |
| 20181 } // namespace internal | 20282 } // namespace internal |
| 20182 } // namespace v8 | 20283 } // namespace v8 |
| OLD | NEW |