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 "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 5943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5954 | 5954 |
5955 return context->extension_object()->ReferencesObject(obj); | 5955 return context->extension_object()->ReferencesObject(obj); |
5956 } | 5956 } |
5957 } | 5957 } |
5958 | 5958 |
5959 // No references to object. | 5959 // No references to object. |
5960 return false; | 5960 return false; |
5961 } | 5961 } |
5962 | 5962 |
5963 | 5963 |
5964 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { | 5964 Maybe<bool> JSObject::PreventExtensionsInternal(Handle<JSObject> object) { |
5965 if (!object->map()->is_extensible()) return object; | 5965 Isolate* isolate = object->GetIsolate(); |
| 5966 |
| 5967 if (!object->map()->is_extensible()) return Just(true); |
5966 | 5968 |
5967 if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) { | 5969 if (!object->HasSloppyArgumentsElements() && !object->map()->is_observed()) { |
5968 return PreventExtensionsWithTransition<NONE>(object); | 5970 return PreventExtensionsWithTransition<NONE>(object); |
5969 } | 5971 } |
5970 | 5972 |
5971 Isolate* isolate = object->GetIsolate(); | |
5972 | |
5973 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { | 5973 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
5974 isolate->ReportFailedAccessCheck(object); | 5974 isolate->ReportFailedAccessCheck(object); |
5975 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5975 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
5976 return isolate->factory()->false_value(); | 5976 UNREACHABLE(); |
| 5977 return Just(false); |
5977 } | 5978 } |
5978 | 5979 |
5979 if (object->IsJSGlobalProxy()) { | 5980 if (object->IsJSGlobalProxy()) { |
5980 PrototypeIterator iter(isolate, object); | 5981 PrototypeIterator iter(isolate, object); |
5981 if (iter.IsAtEnd()) return object; | 5982 if (iter.IsAtEnd()) return Just(true); |
5982 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5983 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5983 return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter)); | 5984 return PreventExtensionsInternal( |
| 5985 PrototypeIterator::GetCurrent<JSObject>(iter)); |
5984 } | 5986 } |
5985 | 5987 |
5986 // It's not possible to seal objects with external array elements | 5988 // It's not possible to seal objects with external array elements |
5987 if (object->HasFixedTypedArrayElements()) { | 5989 if (object->HasFixedTypedArrayElements()) { |
5988 THROW_NEW_ERROR( | 5990 isolate->Throw(*isolate->factory()->NewTypeError( |
5989 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), | 5991 MessageTemplate::kCannotPreventExtExternalArray)); |
5990 Object); | 5992 return Nothing<bool>(); |
5991 } | 5993 } |
5992 | 5994 |
5993 // If there are fast elements we normalize. | 5995 // If there are fast elements we normalize. |
5994 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 5996 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
5995 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); | 5997 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); |
5996 | 5998 |
5997 // Make sure that we never go back to fast case. | 5999 // Make sure that we never go back to fast case. |
5998 object->RequireSlowElements(*dictionary); | 6000 object->RequireSlowElements(*dictionary); |
5999 | 6001 |
6000 // Do a map transition, other objects with this map may still | 6002 // Do a map transition, other objects with this map may still |
6001 // be extensible. | 6003 // be extensible. |
6002 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 6004 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
6003 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); | 6005 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); |
6004 | 6006 |
6005 new_map->set_is_extensible(false); | 6007 new_map->set_is_extensible(false); |
6006 JSObject::MigrateToMap(object, new_map); | 6008 JSObject::MigrateToMap(object, new_map); |
6007 DCHECK(!object->map()->is_extensible()); | 6009 DCHECK(!object->map()->is_extensible()); |
6008 | 6010 |
6009 if (object->map()->is_observed()) { | 6011 if (object->map()->is_observed()) { |
6010 RETURN_ON_EXCEPTION( | 6012 RETURN_ON_EXCEPTION_VALUE( |
6011 isolate, | 6013 isolate, |
6012 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 6014 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
6013 isolate->factory()->the_hole_value()), | 6015 isolate->factory()->the_hole_value()), |
6014 Object); | 6016 Nothing<bool>()); |
6015 } | 6017 } |
6016 return object; | 6018 return Just(true); |
6017 } | 6019 } |
6018 | 6020 |
6019 | 6021 |
| 6022 static MaybeHandle<Object> ReturnObjectOrThrowTypeError( |
| 6023 Handle<JSObject> object, Maybe<bool> maybe, MessageTemplate::Template msg) { |
| 6024 if (!maybe.IsJust()) return MaybeHandle<Object>(); |
| 6025 if (maybe.FromJust()) return object; |
| 6026 Isolate* isolate = object->GetIsolate(); |
| 6027 THROW_NEW_ERROR(isolate, NewTypeError(msg), Object); |
| 6028 } |
| 6029 |
| 6030 |
| 6031 MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
| 6032 return ReturnObjectOrThrowTypeError(object, PreventExtensionsInternal(object), |
| 6033 MessageTemplate::kCannotPreventExt); |
| 6034 } |
| 6035 |
| 6036 |
6020 bool JSObject::IsExtensible(Handle<JSObject> object) { | 6037 bool JSObject::IsExtensible(Handle<JSObject> object) { |
6021 Isolate* isolate = object->GetIsolate(); | 6038 Isolate* isolate = object->GetIsolate(); |
6022 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { | 6039 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
6023 return true; | 6040 return true; |
6024 } | 6041 } |
6025 if (object->IsJSGlobalProxy()) { | 6042 if (object->IsJSGlobalProxy()) { |
6026 PrototypeIterator iter(isolate, *object); | 6043 PrototypeIterator iter(isolate, *object); |
6027 if (iter.IsAtEnd()) return false; | 6044 if (iter.IsAtEnd()) return false; |
6028 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | 6045 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
6029 return iter.GetCurrent<JSObject>()->map()->is_extensible(); | 6046 return iter.GetCurrent<JSObject>()->map()->is_extensible(); |
(...skipping 20 matching lines...) Expand all Loading... |
6050 } | 6067 } |
6051 details = details.CopyAddAttributes( | 6068 details = details.CopyAddAttributes( |
6052 static_cast<PropertyAttributes>(attrs)); | 6069 static_cast<PropertyAttributes>(attrs)); |
6053 dictionary->DetailsAtPut(i, details); | 6070 dictionary->DetailsAtPut(i, details); |
6054 } | 6071 } |
6055 } | 6072 } |
6056 } | 6073 } |
6057 | 6074 |
6058 | 6075 |
6059 template <PropertyAttributes attrs> | 6076 template <PropertyAttributes attrs> |
6060 MaybeHandle<Object> JSObject::PreventExtensionsWithTransition( | 6077 Maybe<bool> JSObject::PreventExtensionsWithTransition(Handle<JSObject> object) { |
6061 Handle<JSObject> object) { | |
6062 STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN); | 6078 STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN); |
6063 | 6079 |
6064 // Sealing/freezing sloppy arguments should be handled elsewhere. | 6080 // Sealing/freezing sloppy arguments should be handled elsewhere. |
6065 DCHECK(!object->HasSloppyArgumentsElements()); | 6081 DCHECK(!object->HasSloppyArgumentsElements()); |
6066 DCHECK(!object->map()->is_observed()); | 6082 DCHECK(!object->map()->is_observed()); |
6067 | 6083 |
6068 Isolate* isolate = object->GetIsolate(); | 6084 Isolate* isolate = object->GetIsolate(); |
6069 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { | 6085 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
6070 isolate->ReportFailedAccessCheck(object); | 6086 isolate->ReportFailedAccessCheck(object); |
6071 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6087 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
6072 return isolate->factory()->false_value(); | 6088 UNREACHABLE(); |
6073 } | 6089 } |
6074 | 6090 |
6075 if (object->IsJSGlobalProxy()) { | 6091 if (object->IsJSGlobalProxy()) { |
6076 PrototypeIterator iter(isolate, object); | 6092 PrototypeIterator iter(isolate, object); |
6077 if (iter.IsAtEnd()) return object; | 6093 if (iter.IsAtEnd()) return Just(true); |
6078 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6094 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
6079 return PreventExtensionsWithTransition<attrs>( | 6095 return PreventExtensionsWithTransition<attrs>( |
6080 PrototypeIterator::GetCurrent<JSObject>(iter)); | 6096 PrototypeIterator::GetCurrent<JSObject>(iter)); |
6081 } | 6097 } |
6082 | 6098 |
6083 // It's not possible to seal or freeze objects with external array elements | 6099 // It's not possible to seal or freeze objects with external array elements |
6084 if (object->HasFixedTypedArrayElements()) { | 6100 if (object->HasFixedTypedArrayElements()) { |
6085 THROW_NEW_ERROR( | 6101 isolate->Throw(*isolate->factory()->NewTypeError( |
6086 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), | 6102 MessageTemplate::kCannotPreventExtExternalArray)); |
6087 Object); | 6103 return Nothing<bool>(); |
6088 } | 6104 } |
6089 | 6105 |
6090 Handle<SeededNumberDictionary> new_element_dictionary; | 6106 Handle<SeededNumberDictionary> new_element_dictionary; |
6091 if (!object->HasDictionaryElements()) { | 6107 if (!object->HasDictionaryElements()) { |
6092 int length = | 6108 int length = |
6093 object->IsJSArray() | 6109 object->IsJSArray() |
6094 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() | 6110 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
6095 : object->elements()->length(); | 6111 : object->elements()->length(); |
6096 new_element_dictionary = | 6112 new_element_dictionary = |
6097 length == 0 ? isolate->factory()->empty_slow_element_dictionary() | 6113 length == 0 ? isolate->factory()->empty_slow_element_dictionary() |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6152 | 6168 |
6153 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { | 6169 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
6154 SeededNumberDictionary* dictionary = object->element_dictionary(); | 6170 SeededNumberDictionary* dictionary = object->element_dictionary(); |
6155 // Make sure we never go back to the fast case | 6171 // Make sure we never go back to the fast case |
6156 object->RequireSlowElements(dictionary); | 6172 object->RequireSlowElements(dictionary); |
6157 if (attrs != NONE) { | 6173 if (attrs != NONE) { |
6158 ApplyAttributesToDictionary(dictionary, attrs); | 6174 ApplyAttributesToDictionary(dictionary, attrs); |
6159 } | 6175 } |
6160 } | 6176 } |
6161 | 6177 |
6162 return object; | 6178 return Just(true); |
6163 } | 6179 } |
6164 | 6180 |
6165 | 6181 |
6166 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { | 6182 MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
6167 return PreventExtensionsWithTransition<FROZEN>(object); | 6183 return ReturnObjectOrThrowTypeError( |
| 6184 object, PreventExtensionsWithTransition<FROZEN>(object), |
| 6185 MessageTemplate::kCannotPreventExt); |
6168 } | 6186 } |
6169 | 6187 |
6170 | 6188 |
6171 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) { | 6189 MaybeHandle<Object> JSObject::Seal(Handle<JSObject> object) { |
6172 return PreventExtensionsWithTransition<SEALED>(object); | 6190 return ReturnObjectOrThrowTypeError( |
| 6191 object, PreventExtensionsWithTransition<SEALED>(object), |
| 6192 MessageTemplate::kCannotPreventExt); |
6173 } | 6193 } |
6174 | 6194 |
6175 | 6195 |
6176 void JSObject::SetObserved(Handle<JSObject> object) { | 6196 void JSObject::SetObserved(Handle<JSObject> object) { |
6177 DCHECK(!object->IsJSGlobalProxy()); | 6197 DCHECK(!object->IsJSGlobalProxy()); |
6178 DCHECK(!object->IsJSGlobalObject()); | 6198 DCHECK(!object->IsJSGlobalObject()); |
6179 Isolate* isolate = object->GetIsolate(); | 6199 Isolate* isolate = object->GetIsolate(); |
6180 Handle<Map> new_map; | 6200 Handle<Map> new_map; |
6181 Handle<Map> old_map(object->map(), isolate); | 6201 Handle<Map> old_map(object->map(), isolate); |
6182 DCHECK(!old_map->is_observed()); | 6202 DCHECK(!old_map->is_observed()); |
(...skipping 10685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16868 if (cell->value() != *new_value) { | 16888 if (cell->value() != *new_value) { |
16869 cell->set_value(*new_value); | 16889 cell->set_value(*new_value); |
16870 Isolate* isolate = cell->GetIsolate(); | 16890 Isolate* isolate = cell->GetIsolate(); |
16871 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16891 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16872 isolate, DependentCode::kPropertyCellChangedGroup); | 16892 isolate, DependentCode::kPropertyCellChangedGroup); |
16873 } | 16893 } |
16874 } | 16894 } |
16875 | 16895 |
16876 } // namespace internal | 16896 } // namespace internal |
16877 } // namespace v8 | 16897 } // namespace v8 |
OLD | NEW |