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 <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 4139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4150 } | 4150 } |
4151 | 4151 |
4152 *found = false; | 4152 *found = false; |
4153 return Nothing<bool>(); | 4153 return Nothing<bool>(); |
4154 } | 4154 } |
4155 | 4155 |
4156 | 4156 |
4157 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, | 4157 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value, |
4158 LanguageMode language_mode, | 4158 LanguageMode language_mode, |
4159 StoreFromKeyed store_mode) { | 4159 StoreFromKeyed store_mode) { |
4160 bool found = false; | |
4161 Maybe<bool> result = | |
4162 SetPropertyInternal(it, value, language_mode, store_mode, &found); | |
4163 if (found) return result; | |
4164 ShouldThrow should_throw = | 4160 ShouldThrow should_throw = |
4165 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4161 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4166 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) { | 4162 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) { |
4167 RETURN_FAILURE(it->isolate(), should_throw, | 4163 RETURN_FAILURE(it->isolate(), should_throw, |
4168 NewTypeError(MessageTemplate::kProxyPrivate)); | 4164 NewTypeError(MessageTemplate::kProxyPrivate)); |
4169 } | 4165 } |
| 4166 bool found = false; |
| 4167 Maybe<bool> result = |
| 4168 SetPropertyInternal(it, value, language_mode, store_mode, &found); |
| 4169 if (found) return result; |
4170 return AddDataProperty(it, value, NONE, should_throw, store_mode); | 4170 return AddDataProperty(it, value, NONE, should_throw, store_mode); |
4171 } | 4171 } |
4172 | 4172 |
4173 | 4173 |
4174 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value, | 4174 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value, |
4175 LanguageMode language_mode, | 4175 LanguageMode language_mode, |
4176 StoreFromKeyed store_mode) { | 4176 StoreFromKeyed store_mode) { |
4177 ShouldThrow should_throw = | 4177 ShouldThrow should_throw = |
4178 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; | 4178 is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR; |
4179 Isolate* isolate = it->isolate(); | 4179 Isolate* isolate = it->isolate(); |
| 4180 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) { |
| 4181 RETURN_FAILURE(isolate, should_throw, |
| 4182 NewTypeError(MessageTemplate::kProxyPrivate)); |
| 4183 } |
4180 | 4184 |
4181 bool found = false; | 4185 bool found = false; |
4182 Maybe<bool> result = | 4186 Maybe<bool> result = |
4183 SetPropertyInternal(it, value, language_mode, store_mode, &found); | 4187 SetPropertyInternal(it, value, language_mode, store_mode, &found); |
4184 if (found) return result; | 4188 if (found) return result; |
4185 if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) { | |
4186 RETURN_FAILURE(isolate, should_throw, | |
4187 NewTypeError(MessageTemplate::kProxyPrivate)); | |
4188 } | |
4189 | 4189 |
4190 // The property either doesn't exist on the holder or exists there as a data | 4190 // The property either doesn't exist on the holder or exists there as a data |
4191 // property. | 4191 // property. |
4192 | 4192 |
4193 if (!it->GetReceiver()->IsJSReceiver()) { | 4193 if (!it->GetReceiver()->IsJSReceiver()) { |
4194 return WriteToReadOnlyProperty(it, value, should_throw); | 4194 return WriteToReadOnlyProperty(it, value, should_throw); |
4195 } | 4195 } |
4196 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); | 4196 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver()); |
4197 | 4197 |
4198 LookupIterator::Configuration c = LookupIterator::OWN; | 4198 LookupIterator::Configuration c = LookupIterator::OWN; |
(...skipping 1989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6188 if (result.IsEmpty()) return Nothing<bool>(); | 6188 if (result.IsEmpty()) return Nothing<bool>(); |
6189 | 6189 |
6190 DCHECK(result->IsBoolean()); | 6190 DCHECK(result->IsBoolean()); |
6191 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 6191 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
6192 result_internal->VerifyApiCallResultType(); | 6192 result_internal->VerifyApiCallResultType(); |
6193 // Rebox CustomArguments::kReturnValueOffset before returning. | 6193 // Rebox CustomArguments::kReturnValueOffset before returning. |
6194 return Just(result_internal->BooleanValue()); | 6194 return Just(result_internal->BooleanValue()); |
6195 } | 6195 } |
6196 | 6196 |
6197 | 6197 |
6198 void JSObject::DeleteNormalizedProperty(Handle<JSObject> object, | 6198 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object, |
6199 Handle<Name> name, int entry) { | 6199 Handle<Name> name, int entry) { |
6200 DCHECK(!object->HasFastProperties()); | 6200 DCHECK(!object->HasFastProperties()); |
6201 Isolate* isolate = object->GetIsolate(); | 6201 Isolate* isolate = object->GetIsolate(); |
6202 | 6202 |
6203 if (object->IsJSGlobalObject()) { | 6203 if (object->IsJSGlobalObject()) { |
6204 // If we have a global object, invalidate the cell and swap in a new one. | 6204 // If we have a global object, invalidate the cell and swap in a new one. |
6205 Handle<GlobalDictionary> dictionary(object->global_dictionary()); | 6205 Handle<GlobalDictionary> dictionary( |
| 6206 JSObject::cast(*object)->global_dictionary()); |
6206 DCHECK_NE(GlobalDictionary::kNotFound, entry); | 6207 DCHECK_NE(GlobalDictionary::kNotFound, entry); |
6207 | 6208 |
6208 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); | 6209 auto cell = PropertyCell::InvalidateEntry(dictionary, entry); |
6209 cell->set_value(isolate->heap()->the_hole_value()); | 6210 cell->set_value(isolate->heap()->the_hole_value()); |
6210 // TODO(ishell): InvalidateForDelete | 6211 // TODO(ishell): InvalidateForDelete |
6211 cell->set_property_details( | 6212 cell->set_property_details( |
6212 cell->property_details().set_cell_type(PropertyCellType::kInvalidated)); | 6213 cell->property_details().set_cell_type(PropertyCellType::kInvalidated)); |
6213 } else { | 6214 } else { |
6214 Handle<NameDictionary> dictionary(object->property_dictionary()); | 6215 Handle<NameDictionary> dictionary(object->property_dictionary()); |
6215 DCHECK_NE(NameDictionary::kNotFound, entry); | 6216 DCHECK_NE(NameDictionary::kNotFound, entry); |
6216 | 6217 |
6217 NameDictionary::DeleteProperty(dictionary, entry); | 6218 NameDictionary::DeleteProperty(dictionary, entry); |
6218 Handle<NameDictionary> new_properties = | 6219 Handle<NameDictionary> new_properties = |
6219 NameDictionary::Shrink(dictionary, name); | 6220 NameDictionary::Shrink(dictionary, name); |
6220 object->set_properties(*new_properties); | 6221 object->set_properties(*new_properties); |
6221 } | 6222 } |
6222 } | 6223 } |
6223 | 6224 |
6224 | 6225 |
6225 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it, | 6226 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it, |
6226 LanguageMode language_mode) { | 6227 LanguageMode language_mode) { |
6227 Isolate* isolate = it->isolate(); | 6228 Isolate* isolate = it->isolate(); |
6228 | 6229 |
6229 if (it->state() == LookupIterator::JSPROXY) { | 6230 if (it->state() == LookupIterator::JSPROXY) { |
6230 return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(), | 6231 return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(), |
6231 it->GetName(), language_mode); | 6232 it->GetName(), language_mode); |
6232 } | 6233 } |
6233 | 6234 |
6234 if (it->GetReceiver()->IsJSProxy()) { | 6235 if (it->GetReceiver()->IsJSProxy()) { |
6235 DCHECK(it->state() == LookupIterator::NOT_FOUND); | 6236 if (it->state() != LookupIterator::NOT_FOUND) { |
6236 DCHECK(it->GetName()->IsPrivate()); | 6237 DCHECK_EQ(LookupIterator::DATA, it->state()); |
| 6238 DCHECK(it->GetName()->IsPrivate()); |
| 6239 it->Delete(); |
| 6240 } |
6237 return Just(true); | 6241 return Just(true); |
6238 } | 6242 } |
6239 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); | 6243 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); |
6240 | 6244 |
6241 bool is_observed = | 6245 bool is_observed = |
6242 receiver->map()->is_observed() && | 6246 receiver->map()->is_observed() && |
6243 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name())); | 6247 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name())); |
6244 | 6248 |
6245 Handle<Object> old_value = it->factory()->the_hole_value(); | 6249 Handle<Object> old_value = it->factory()->the_hole_value(); |
6246 | 6250 |
(...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7071 } | 7075 } |
7072 | 7076 |
7073 | 7077 |
7074 // ES6 9.5.6 | 7078 // ES6 9.5.6 |
7075 // static | 7079 // static |
7076 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, | 7080 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy, |
7077 Handle<Object> key, | 7081 Handle<Object> key, |
7078 PropertyDescriptor* desc, | 7082 PropertyDescriptor* desc, |
7079 ShouldThrow should_throw) { | 7083 ShouldThrow should_throw) { |
7080 STACK_CHECK(Nothing<bool>()); | 7084 STACK_CHECK(Nothing<bool>()); |
| 7085 if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) { |
| 7086 return AddPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc, |
| 7087 should_throw); |
| 7088 } |
7081 Handle<String> trap_name = isolate->factory()->defineProperty_string(); | 7089 Handle<String> trap_name = isolate->factory()->defineProperty_string(); |
7082 // 1. Assert: IsPropertyKey(P) is true. | 7090 // 1. Assert: IsPropertyKey(P) is true. |
7083 DCHECK(key->IsName() || key->IsNumber()); | 7091 DCHECK(key->IsName() || key->IsNumber()); |
7084 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | 7092 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. |
7085 Handle<Object> handler(proxy->handler(), isolate); | 7093 Handle<Object> handler(proxy->handler(), isolate); |
7086 // 3. If handler is null, throw a TypeError exception. | 7094 // 3. If handler is null, throw a TypeError exception. |
7087 // 4. Assert: Type(handler) is Object. | 7095 // 4. Assert: Type(handler) is Object. |
7088 if (proxy->IsRevoked()) { | 7096 if (proxy->IsRevoked()) { |
7089 isolate->Throw(*isolate->factory()->NewTypeError( | 7097 isolate->Throw(*isolate->factory()->NewTypeError( |
7090 MessageTemplate::kProxyRevoked, trap_name)); | 7098 MessageTemplate::kProxyRevoked, trap_name)); |
(...skipping 15 matching lines...) Expand all Loading... |
7106 } | 7114 } |
7107 // 8. Let descObj be FromPropertyDescriptor(Desc). | 7115 // 8. Let descObj be FromPropertyDescriptor(Desc). |
7108 Handle<Object> desc_obj = desc->ToObject(isolate); | 7116 Handle<Object> desc_obj = desc->ToObject(isolate); |
7109 // 9. Let booleanTrapResult be | 7117 // 9. Let booleanTrapResult be |
7110 // ToBoolean(? Call(trap, handler, «target, P, descObj»)). | 7118 // ToBoolean(? Call(trap, handler, «target, P, descObj»)). |
7111 Handle<Name> property_name = | 7119 Handle<Name> property_name = |
7112 key->IsName() | 7120 key->IsName() |
7113 ? Handle<Name>::cast(key) | 7121 ? Handle<Name>::cast(key) |
7114 : Handle<Name>::cast(isolate->factory()->NumberToString(key)); | 7122 : Handle<Name>::cast(isolate->factory()->NumberToString(key)); |
7115 // Do not leak private property names. | 7123 // Do not leak private property names. |
7116 if (property_name->IsPrivate()) { | 7124 DCHECK(!property_name->IsPrivate()); |
7117 RETURN_FAILURE(isolate, should_throw, | |
7118 NewTypeError(MessageTemplate::kProxyPrivate)); | |
7119 } | |
7120 Handle<Object> trap_result_obj; | 7125 Handle<Object> trap_result_obj; |
7121 Handle<Object> args[] = {target, property_name, desc_obj}; | 7126 Handle<Object> args[] = {target, property_name, desc_obj}; |
7122 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 7127 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
7123 isolate, trap_result_obj, | 7128 isolate, trap_result_obj, |
7124 Execution::Call(isolate, trap, handler, arraysize(args), args), | 7129 Execution::Call(isolate, trap, handler, arraysize(args), args), |
7125 Nothing<bool>()); | 7130 Nothing<bool>()); |
7126 // 10. If booleanTrapResult is false, return false. | 7131 // 10. If booleanTrapResult is false, return false. |
7127 if (!trap_result_obj->BooleanValue()) { | 7132 if (!trap_result_obj->BooleanValue()) { |
7128 RETURN_FAILURE(isolate, should_throw, | 7133 RETURN_FAILURE(isolate, should_throw, |
7129 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor, | 7134 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7177 MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name)); | 7182 MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name)); |
7178 return Nothing<bool>(); | 7183 return Nothing<bool>(); |
7179 } | 7184 } |
7180 } | 7185 } |
7181 // 17. Return true. | 7186 // 17. Return true. |
7182 return Just(true); | 7187 return Just(true); |
7183 } | 7188 } |
7184 | 7189 |
7185 | 7190 |
7186 // static | 7191 // static |
| 7192 Maybe<bool> JSProxy::AddPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy, |
| 7193 Handle<Symbol> private_name, |
| 7194 PropertyDescriptor* desc, |
| 7195 ShouldThrow should_throw) { |
| 7196 // Despite the generic name, this can only add private data properties. |
| 7197 if (!PropertyDescriptor::IsDataDescriptor(desc) || |
| 7198 desc->ToAttributes() != DONT_ENUM) { |
| 7199 RETURN_FAILURE(isolate, should_throw, |
| 7200 NewTypeError(MessageTemplate::kProxyPrivate)); |
| 7201 } |
| 7202 DCHECK(proxy->map()->is_dictionary_map()); |
| 7203 Handle<Object> value = |
| 7204 desc->has_value() |
| 7205 ? desc->value() |
| 7206 : Handle<Object>::cast(isolate->factory()->undefined_value()); |
| 7207 |
| 7208 LookupIterator it(proxy, private_name); |
| 7209 |
| 7210 if (it.IsFound()) { |
| 7211 DCHECK_EQ(LookupIterator::DATA, it.state()); |
| 7212 DCHECK_EQ(DONT_ENUM, it.property_details().attributes()); |
| 7213 it.WriteDataValue(value); |
| 7214 return Just(true); |
| 7215 } |
| 7216 |
| 7217 Handle<NameDictionary> dict(proxy->property_dictionary()); |
| 7218 PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell); |
| 7219 Handle<NameDictionary> result = |
| 7220 NameDictionary::Add(dict, private_name, value, details); |
| 7221 if (!dict.is_identical_to(result)) proxy->set_properties(*result); |
| 7222 return Just(true); |
| 7223 } |
| 7224 |
| 7225 |
| 7226 // static |
7187 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, | 7227 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, |
7188 Handle<JSReceiver> object, | 7228 Handle<JSReceiver> object, |
7189 Handle<Object> key, | 7229 Handle<Object> key, |
7190 PropertyDescriptor* desc) { | 7230 PropertyDescriptor* desc) { |
7191 bool success = false; | 7231 bool success = false; |
7192 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... | 7232 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
7193 LookupIterator it = LookupIterator::PropertyOrElement( | 7233 LookupIterator it = LookupIterator::PropertyOrElement( |
7194 isolate, object, key, &success, LookupIterator::HIDDEN); | 7234 isolate, object, key, &success, LookupIterator::HIDDEN); |
7195 DCHECK(success); // ...so creating a LookupIterator can't fail. | 7235 DCHECK(success); // ...so creating a LookupIterator can't fail. |
7196 return GetOwnPropertyDescriptor(&it, desc); | 7236 return GetOwnPropertyDescriptor(&it, desc); |
(...skipping 12493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19690 if (cell->value() != *new_value) { | 19730 if (cell->value() != *new_value) { |
19691 cell->set_value(*new_value); | 19731 cell->set_value(*new_value); |
19692 Isolate* isolate = cell->GetIsolate(); | 19732 Isolate* isolate = cell->GetIsolate(); |
19693 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19733 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19694 isolate, DependentCode::kPropertyCellChangedGroup); | 19734 isolate, DependentCode::kPropertyCellChangedGroup); |
19695 } | 19735 } |
19696 } | 19736 } |
19697 | 19737 |
19698 } // namespace internal | 19738 } // namespace internal |
19699 } // namespace v8 | 19739 } // namespace v8 |
OLD | NEW |