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 19 matching lines...) Expand all Loading... |
30 #include "src/hydrogen.h" | 30 #include "src/hydrogen.h" |
31 #include "src/ic/ic.h" | 31 #include "src/ic/ic.h" |
32 #include "src/interpreter/bytecodes.h" | 32 #include "src/interpreter/bytecodes.h" |
33 #include "src/isolate-inl.h" | 33 #include "src/isolate-inl.h" |
34 #include "src/log.h" | 34 #include "src/log.h" |
35 #include "src/lookup.h" | 35 #include "src/lookup.h" |
36 #include "src/macro-assembler.h" | 36 #include "src/macro-assembler.h" |
37 #include "src/messages.h" | 37 #include "src/messages.h" |
38 #include "src/objects-inl.h" | 38 #include "src/objects-inl.h" |
39 #include "src/profiler/cpu-profiler.h" | 39 #include "src/profiler/cpu-profiler.h" |
| 40 #include "src/property-descriptor.h" |
40 #include "src/prototype.h" | 41 #include "src/prototype.h" |
41 #include "src/safepoint-table.h" | 42 #include "src/safepoint-table.h" |
42 #include "src/string-builder.h" | 43 #include "src/string-builder.h" |
43 #include "src/string-search.h" | 44 #include "src/string-search.h" |
44 #include "src/string-stream.h" | 45 #include "src/string-stream.h" |
45 #include "src/utils.h" | 46 #include "src/utils.h" |
46 | 47 |
47 #ifdef ENABLE_DISASSEMBLER | 48 #ifdef ENABLE_DISASSEMBLER |
48 #include "src/disasm.h" | 49 #include "src/disasm.h" |
49 #include "src/disassembler.h" | 50 #include "src/disassembler.h" |
(...skipping 5769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5819 | 5820 |
5820 | 5821 |
5821 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement( | 5822 MaybeHandle<Object> JSReceiver::DeletePropertyOrElement( |
5822 Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) { | 5823 Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode) { |
5823 LookupIterator it = LookupIterator::PropertyOrElement( | 5824 LookupIterator it = LookupIterator::PropertyOrElement( |
5824 name->GetIsolate(), object, name, LookupIterator::HIDDEN); | 5825 name->GetIsolate(), object, name, LookupIterator::HIDDEN); |
5825 return JSObject::DeleteProperty(&it, language_mode); | 5826 return JSObject::DeleteProperty(&it, language_mode); |
5826 } | 5827 } |
5827 | 5828 |
5828 | 5829 |
| 5830 // ES6 7.1.14 |
| 5831 MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) { |
| 5832 // 1. Let key be ToPrimitive(argument, hint String). |
| 5833 MaybeHandle<Object> maybe_key = |
| 5834 Object::ToPrimitive(value, ToPrimitiveHint::kString); |
| 5835 // 2. ReturnIfAbrupt(key). |
| 5836 Handle<Object> key; |
| 5837 if (!maybe_key.ToHandle(&key)) return key; |
| 5838 // 3. If Type(key) is Symbol, then return key. |
| 5839 if (key->IsSymbol()) return key; |
| 5840 // 4. Return ToString(key). |
| 5841 // Extending spec'ed behavior, we'd be happy to return an element index. |
| 5842 if (key->IsSmi()) return key; |
| 5843 if (key->IsHeapNumber()) { |
| 5844 uint32_t uint_value; |
| 5845 if (value->ToArrayLength(&uint_value) && |
| 5846 uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 5847 return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate); |
| 5848 } |
| 5849 } |
| 5850 return Object::ToString(isolate, key); |
| 5851 } |
| 5852 |
| 5853 |
| 5854 // ES6 19.1.2.4 |
| 5855 // static |
| 5856 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object, |
| 5857 Handle<Object> key, |
| 5858 Handle<Object> attributes) { |
| 5859 // 1. If Type(O) is not Object, throw a TypeError exception. |
| 5860 // TODO(jkummerow): Implement Proxy support, change to "IsSpecObject". |
| 5861 if (!object->IsJSObject()) { |
| 5862 Handle<String> fun_name = |
| 5863 isolate->factory()->InternalizeUtf8String("Object.defineProperty"); |
| 5864 THROW_NEW_ERROR_RETURN_FAILURE( |
| 5865 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name)); |
| 5866 } |
| 5867 // 2. Let key be ToPropertyKey(P). |
| 5868 // 3. ReturnIfAbrupt(key). |
| 5869 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key)); |
| 5870 // 4. Let desc be ToPropertyDescriptor(Attributes). |
| 5871 // 5. ReturnIfAbrupt(desc). |
| 5872 PropertyDescriptor desc; |
| 5873 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) { |
| 5874 return isolate->heap()->exception(); |
| 5875 } |
| 5876 // 6. Let success be DefinePropertyOrThrow(O,key, desc). |
| 5877 bool success = DefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, |
| 5878 &desc, THROW_ON_ERROR); |
| 5879 // 7. ReturnIfAbrupt(success). |
| 5880 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| 5881 CHECK(success == true); |
| 5882 // 8. Return O. |
| 5883 return *object; |
| 5884 } |
| 5885 |
| 5886 |
| 5887 // ES6 19.1.2.3.1 |
| 5888 // static |
| 5889 Object* JSReceiver::DefineProperties(Isolate* isolate, Handle<Object> object, |
| 5890 Handle<Object> properties) { |
| 5891 // 1. If Type(O) is not Object, throw a TypeError exception. |
| 5892 // TODO(jkummerow): Implement Proxy support, change to "IsSpecObject". |
| 5893 if (!object->IsJSObject()) { |
| 5894 Handle<String> fun_name = |
| 5895 isolate->factory()->InternalizeUtf8String("Object.defineProperties"); |
| 5896 THROW_NEW_ERROR_RETURN_FAILURE( |
| 5897 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name)); |
| 5898 } |
| 5899 // 2. Let props be ToObject(Properties). |
| 5900 // 3. ReturnIfAbrupt(props). |
| 5901 Handle<JSReceiver> props; |
| 5902 if (!Object::ToObject(isolate, properties).ToHandle(&props)) { |
| 5903 THROW_NEW_ERROR_RETURN_FAILURE( |
| 5904 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); |
| 5905 } |
| 5906 // 4. Let keys be props.[[OwnPropertyKeys]](). |
| 5907 // 5. ReturnIfAbrupt(keys). |
| 5908 Handle<FixedArray> keys; |
| 5909 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 5910 isolate, keys, |
| 5911 JSReceiver::GetKeys(props, JSReceiver::OWN_ONLY, INCLUDE_SYMBOLS)); |
| 5912 // 6. Let descriptors be an empty List. |
| 5913 int capacity = keys->length(); |
| 5914 std::vector<PropertyDescriptor> descriptors(capacity); |
| 5915 // 7. Repeat for each element nextKey of keys in List order, |
| 5916 for (int i = 0; i < keys->length(); ++i) { |
| 5917 Handle<Object> next_key(keys->get(i), isolate); |
| 5918 // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey). |
| 5919 // 7b. ReturnIfAbrupt(propDesc). |
| 5920 bool success = false; |
| 5921 LookupIterator it = LookupIterator::PropertyOrElement( |
| 5922 isolate, props, next_key, &success, LookupIterator::HIDDEN); |
| 5923 DCHECK(success); |
| 5924 // TODO(jkummerow): Support JSProxies. Make sure we call the correct |
| 5925 // getOwnPropertyDescriptor trap, and convert the result object to a |
| 5926 // PropertyDescriptor. |
| 5927 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it); |
| 5928 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 5929 PropertyAttributes attrs = maybe.FromJust(); |
| 5930 // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true: |
| 5931 if (attrs == ABSENT) continue; |
| 5932 // GetKeys() only returns enumerable keys. |
| 5933 DCHECK((attrs & DONT_ENUM) == 0); |
| 5934 // 7c i. Let descObj be Get(props, nextKey). |
| 5935 // 7c ii. ReturnIfAbrupt(descObj). |
| 5936 Handle<Object> desc_obj; |
| 5937 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, desc_obj, |
| 5938 JSObject::GetProperty(&it)); |
| 5939 // 7c iii. Let desc be ToPropertyDescriptor(descObj). |
| 5940 success = PropertyDescriptor::ToPropertyDescriptor(isolate, desc_obj, |
| 5941 &descriptors[i]); |
| 5942 // 7c iv. ReturnIfAbrupt(desc). |
| 5943 if (!success) return isolate->heap()->exception(); |
| 5944 // 7c v. Append the pair (a two element List) consisting of nextKey and |
| 5945 // desc to the end of descriptors. |
| 5946 descriptors[i].set_name(next_key); |
| 5947 } |
| 5948 // 8. For each pair from descriptors in list order, |
| 5949 for (size_t i = 0; i < descriptors.size(); ++i) { |
| 5950 PropertyDescriptor* desc = &descriptors[i]; |
| 5951 // 8a. Let P be the first element of pair. |
| 5952 // 8b. Let desc be the second element of pair. |
| 5953 // 8c. Let status be DefinePropertyOrThrow(O, P, desc). |
| 5954 bool status = DefineOwnProperty(isolate, Handle<JSObject>::cast(object), |
| 5955 desc->name(), desc, THROW_ON_ERROR); |
| 5956 // 8d. ReturnIfAbrupt(status). |
| 5957 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| 5958 CHECK(status == true); |
| 5959 } |
| 5960 // 9. Return o. |
| 5961 return *object; |
| 5962 } |
| 5963 |
| 5964 |
| 5965 // static |
| 5966 bool JSReceiver::DefineOwnProperty(Isolate* isolate, Handle<JSObject> object, |
| 5967 Handle<Object> key, PropertyDescriptor* desc, |
| 5968 ShouldThrow should_throw) { |
| 5969 if (object->IsJSArray()) { |
| 5970 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), |
| 5971 key, desc, should_throw); |
| 5972 } |
| 5973 // TODO(jkummerow): Support Modules (ES6 9.4.6.6) |
| 5974 // TODO(jkummerow): Support Proxies (ES6 9.5.6) |
| 5975 |
| 5976 // OrdinaryDefineOwnProperty, by virtue of calling |
| 5977 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) |
| 5978 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: |
| 5979 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. |
| 5980 return OrdinaryDefineOwnProperty(isolate, object, key, desc, should_throw); |
| 5981 } |
| 5982 |
| 5983 |
| 5984 // static |
| 5985 bool JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, |
| 5986 Handle<JSObject> object, |
| 5987 Handle<Object> key, |
| 5988 PropertyDescriptor* desc, |
| 5989 ShouldThrow should_throw) { |
| 5990 bool success = false; |
| 5991 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
| 5992 LookupIterator it = LookupIterator::PropertyOrElement( |
| 5993 isolate, object, key, &success, LookupIterator::HIDDEN); |
| 5994 DCHECK(success); // ...so creating a LookupIterator can't fail. |
| 5995 return OrdinaryDefineOwnProperty(&it, desc, should_throw); |
| 5996 } |
| 5997 |
| 5998 |
| 5999 // ES6 9.1.6.1 |
| 6000 // static |
| 6001 bool JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it, |
| 6002 PropertyDescriptor* desc, |
| 6003 ShouldThrow should_throw) { |
| 6004 Isolate* isolate = it->isolate(); |
| 6005 // == OrdinaryDefineOwnProperty (O, P, Desc) == |
| 6006 // 1. Let current be O.[[GetOwnProperty]](P). |
| 6007 // 2. ReturnIfAbrupt(current). |
| 6008 PropertyDescriptor current; |
| 6009 if (!GetOwnPropertyDescriptor(it, ¤t) && |
| 6010 isolate->has_pending_exception()) { |
| 6011 return false; |
| 6012 } |
| 6013 // 3. Let extensible be the value of the [[Extensible]] internal slot of O. |
| 6014 Handle<JSObject> o = Handle<JSObject>::cast(it->GetReceiver()); |
| 6015 bool extensible = JSObject::IsExtensible(o); |
| 6016 |
| 6017 bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc); |
| 6018 bool desc_is_accessor_descriptor = |
| 6019 PropertyDescriptor::IsAccessorDescriptor(desc); |
| 6020 bool desc_is_generic_descriptor = |
| 6021 PropertyDescriptor::IsGenericDescriptor(desc); |
| 6022 |
| 6023 // == ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current) == |
| 6024 // 2. If current is undefined, then |
| 6025 if (current.is_empty()) { |
| 6026 // 2a. If extensible is false, return false. |
| 6027 if (!extensible) { |
| 6028 if (should_throw == THROW_ON_ERROR) { |
| 6029 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6030 MessageTemplate::kDefineDisallowed, it->GetName())); |
| 6031 } |
| 6032 return false; |
| 6033 } |
| 6034 // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then: |
| 6035 // (This is equivalent to !IsAccessorDescriptor(desc).) |
| 6036 DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) == |
| 6037 !desc_is_accessor_descriptor); |
| 6038 if (!desc_is_accessor_descriptor) { |
| 6039 // 2c i. If O is not undefined, create an own data property named P of |
| 6040 // object O whose [[Value]], [[Writable]], [[Enumerable]] and |
| 6041 // [[Configurable]] attribute values are described by Desc. If the value |
| 6042 // of an attribute field of Desc is absent, the attribute of the newly |
| 6043 // created property is set to its default value. |
| 6044 if (!o->IsUndefined()) { |
| 6045 if (!desc->has_writable()) desc->set_writable(false); |
| 6046 if (!desc->has_enumerable()) desc->set_enumerable(false); |
| 6047 if (!desc->has_configurable()) desc->set_configurable(false); |
| 6048 Handle<Object> value( |
| 6049 desc->has_value() |
| 6050 ? desc->value() |
| 6051 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
| 6052 MaybeHandle<Object> result = |
| 6053 JSObject::DefineOwnPropertyIgnoreAttributes(it, value, |
| 6054 desc->ToAttributes()); |
| 6055 if (result.is_null()) return false; |
| 6056 } |
| 6057 } else { |
| 6058 // 2d. Else Desc must be an accessor Property Descriptor, |
| 6059 DCHECK(desc_is_accessor_descriptor); |
| 6060 // 2d i. If O is not undefined, create an own accessor property named P |
| 6061 // of object O whose [[Get]], [[Set]], [[Enumerable]] and |
| 6062 // [[Configurable]] attribute values are described by Desc. If the value |
| 6063 // of an attribute field of Desc is absent, the attribute of the newly |
| 6064 // created property is set to its default value. |
| 6065 if (!o->IsUndefined()) { |
| 6066 if (!desc->has_enumerable()) desc->set_enumerable(false); |
| 6067 if (!desc->has_configurable()) desc->set_configurable(false); |
| 6068 Handle<Object> getter( |
| 6069 desc->has_get() |
| 6070 ? desc->get() |
| 6071 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
| 6072 Handle<Object> setter( |
| 6073 desc->has_set() |
| 6074 ? desc->set() |
| 6075 : Handle<Object>::cast(isolate->factory()->undefined_value())); |
| 6076 MaybeHandle<Object> result = |
| 6077 JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes()); |
| 6078 if (result.is_null()) return false; |
| 6079 } |
| 6080 } |
| 6081 // 2e. Return true. |
| 6082 return true; |
| 6083 } |
| 6084 // 3. Return true, if every field in Desc is absent. |
| 6085 // 4. Return true, if every field in Desc also occurs in current and the |
| 6086 // value of every field in Desc is the same value as the corresponding field |
| 6087 // in current when compared using the SameValue algorithm. |
| 6088 if ((!desc->has_enumerable() || desc->enumerable() == current.enumerable()) && |
| 6089 (!desc->has_configurable() || |
| 6090 desc->configurable() == current.configurable()) && |
| 6091 (!desc->has_value() || |
| 6092 (current.has_value() && current.value()->SameValue(*desc->value()))) && |
| 6093 (!desc->has_writable() || |
| 6094 (current.has_writable() && current.writable() == desc->writable())) && |
| 6095 (!desc->has_get() || |
| 6096 (current.has_get() && current.get()->SameValue(*desc->get()))) && |
| 6097 (!desc->has_set() || |
| 6098 (current.has_set() && current.set()->SameValue(*desc->set())))) { |
| 6099 return true; |
| 6100 } |
| 6101 // 5. If the [[Configurable]] field of current is false, then |
| 6102 if (!current.configurable()) { |
| 6103 // 5a. Return false, if the [[Configurable]] field of Desc is true. |
| 6104 if (desc->has_configurable() && desc->configurable()) { |
| 6105 if (should_throw == THROW_ON_ERROR) { |
| 6106 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6107 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6108 } |
| 6109 return false; |
| 6110 } |
| 6111 // 5b. Return false, if the [[Enumerable]] field of Desc is present and the |
| 6112 // [[Enumerable]] fields of current and Desc are the Boolean negation of |
| 6113 // each other. |
| 6114 if (desc->has_enumerable() && desc->enumerable() != current.enumerable()) { |
| 6115 if (should_throw == THROW_ON_ERROR) { |
| 6116 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6117 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6118 } |
| 6119 return false; |
| 6120 } |
| 6121 } |
| 6122 |
| 6123 bool current_is_data_descriptor = |
| 6124 PropertyDescriptor::IsDataDescriptor(¤t); |
| 6125 // 6. If IsGenericDescriptor(Desc) is true, no further validation is required. |
| 6126 if (desc_is_generic_descriptor) { |
| 6127 // Nothing to see here. |
| 6128 |
| 6129 // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have |
| 6130 // different results, then: |
| 6131 } else if (current_is_data_descriptor != desc_is_data_descriptor) { |
| 6132 // 7a. Return false, if the [[Configurable]] field of current is false. |
| 6133 if (!current.configurable()) { |
| 6134 if (should_throw == THROW_ON_ERROR) { |
| 6135 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6136 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6137 } |
| 6138 return false; |
| 6139 } |
| 6140 // 7b. If IsDataDescriptor(current) is true, then: |
| 6141 if (current_is_data_descriptor) { |
| 6142 // 7b i. If O is not undefined, convert the property named P of object O |
| 6143 // from a data property to an accessor property. Preserve the existing |
| 6144 // values of the converted property's [[Configurable]] and [[Enumerable]] |
| 6145 // attributes and set the rest of the property's attributes to their |
| 6146 // default values. |
| 6147 // --> Folded into step 10. |
| 6148 } else { |
| 6149 // 7c i. If O is not undefined, convert the property named P of object O |
| 6150 // from an accessor property to a data property. Preserve the existing |
| 6151 // values of the converted property’s [[Configurable]] and [[Enumerable]] |
| 6152 // attributes and set the rest of the property’s attributes to their |
| 6153 // default values. |
| 6154 // --> Folded into step 10. |
| 6155 } |
| 6156 |
| 6157 // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both |
| 6158 // true, then: |
| 6159 } else if (current_is_data_descriptor && desc_is_data_descriptor) { |
| 6160 // 8a. If the [[Configurable]] field of current is false, then: |
| 6161 if (!current.configurable()) { |
| 6162 // [Strong mode] Disallow changing writable -> readonly for |
| 6163 // non-configurable properties. |
| 6164 if (current.writable() && desc->has_writable() && !desc->writable() && |
| 6165 o->map()->is_strong()) { |
| 6166 if (should_throw == THROW_ON_ERROR) { |
| 6167 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6168 MessageTemplate::kStrongRedefineDisallowed, o, it->GetName())); |
| 6169 } |
| 6170 return false; |
| 6171 } |
| 6172 // 8a i. Return false, if the [[Writable]] field of current is false and |
| 6173 // the [[Writable]] field of Desc is true. |
| 6174 if (!current.writable() && desc->has_writable() && desc->writable()) { |
| 6175 if (should_throw == THROW_ON_ERROR) { |
| 6176 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6177 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6178 } |
| 6179 return false; |
| 6180 } |
| 6181 // 8a ii. If the [[Writable]] field of current is false, then: |
| 6182 if (!current.writable()) { |
| 6183 // 8a ii 1. Return false, if the [[Value]] field of Desc is present and |
| 6184 // SameValue(Desc.[[Value]], current.[[Value]]) is false. |
| 6185 if (desc->has_value() && !desc->value()->SameValue(*current.value())) { |
| 6186 if (should_throw == THROW_ON_ERROR) { |
| 6187 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6188 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6189 } |
| 6190 return false; |
| 6191 } |
| 6192 } |
| 6193 } |
| 6194 } else { |
| 6195 // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) |
| 6196 // are both true, |
| 6197 DCHECK(PropertyDescriptor::IsAccessorDescriptor(¤t) && |
| 6198 desc_is_accessor_descriptor); |
| 6199 // 9a. If the [[Configurable]] field of current is false, then: |
| 6200 if (!current.configurable()) { |
| 6201 // 9a i. Return false, if the [[Set]] field of Desc is present and |
| 6202 // SameValue(Desc.[[Set]], current.[[Set]]) is false. |
| 6203 if (desc->has_set() && !desc->set()->SameValue(*current.set())) { |
| 6204 if (should_throw == THROW_ON_ERROR) { |
| 6205 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6206 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6207 } |
| 6208 return false; |
| 6209 } |
| 6210 // 9a ii. Return false, if the [[Get]] field of Desc is present and |
| 6211 // SameValue(Desc.[[Get]], current.[[Get]]) is false. |
| 6212 if (desc->has_get() && !desc->get()->SameValue(*current.get())) { |
| 6213 if (should_throw == THROW_ON_ERROR) { |
| 6214 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6215 MessageTemplate::kRedefineDisallowed, it->GetName())); |
| 6216 } |
| 6217 return false; |
| 6218 } |
| 6219 } |
| 6220 } |
| 6221 |
| 6222 // 10. If O is not undefined, then: |
| 6223 if (!o->IsUndefined()) { |
| 6224 // 10a. For each field of Desc that is present, set the corresponding |
| 6225 // attribute of the property named P of object O to the value of the field. |
| 6226 PropertyAttributes attrs = NONE; |
| 6227 |
| 6228 if (desc->has_enumerable()) { |
| 6229 attrs = static_cast<PropertyAttributes>( |
| 6230 attrs | (desc->enumerable() ? NONE : DONT_ENUM)); |
| 6231 } else { |
| 6232 attrs = static_cast<PropertyAttributes>( |
| 6233 attrs | (current.enumerable() ? NONE : DONT_ENUM)); |
| 6234 } |
| 6235 if (desc->has_configurable()) { |
| 6236 attrs = static_cast<PropertyAttributes>( |
| 6237 attrs | (desc->configurable() ? NONE : DONT_DELETE)); |
| 6238 } else { |
| 6239 attrs = static_cast<PropertyAttributes>( |
| 6240 attrs | (current.configurable() ? NONE : DONT_DELETE)); |
| 6241 } |
| 6242 if (desc_is_data_descriptor || |
| 6243 (desc_is_generic_descriptor && current_is_data_descriptor)) { |
| 6244 if (desc->has_writable()) { |
| 6245 attrs = static_cast<PropertyAttributes>( |
| 6246 attrs | (desc->writable() ? NONE : READ_ONLY)); |
| 6247 } else { |
| 6248 attrs = static_cast<PropertyAttributes>( |
| 6249 attrs | (current.writable() ? NONE : READ_ONLY)); |
| 6250 } |
| 6251 Handle<Object> value( |
| 6252 desc->has_value() ? desc->value() |
| 6253 : current.has_value() |
| 6254 ? current.value() |
| 6255 : Handle<Object>::cast( |
| 6256 isolate->factory()->undefined_value())); |
| 6257 MaybeHandle<Object> result = JSObject::DefineOwnPropertyIgnoreAttributes( |
| 6258 it, value, attrs, JSObject::DONT_FORCE_FIELD); |
| 6259 if (result.is_null()) return false; |
| 6260 } else { |
| 6261 DCHECK(desc_is_accessor_descriptor || |
| 6262 (desc_is_generic_descriptor && |
| 6263 PropertyDescriptor::IsAccessorDescriptor(¤t))); |
| 6264 Handle<Object> getter( |
| 6265 desc->has_get() |
| 6266 ? desc->get() |
| 6267 : current.has_get() ? current.get() |
| 6268 : Handle<Object>::cast( |
| 6269 isolate->factory()->undefined_value())); |
| 6270 Handle<Object> setter( |
| 6271 desc->has_set() |
| 6272 ? desc->set() |
| 6273 : current.has_set() ? current.set() |
| 6274 : Handle<Object>::cast( |
| 6275 isolate->factory()->undefined_value())); |
| 6276 MaybeHandle<Object> result = |
| 6277 JSObject::DefineAccessor(it, getter, setter, attrs); |
| 6278 if (result.is_null()) return false; |
| 6279 } |
| 6280 } |
| 6281 |
| 6282 // 11. Return true. |
| 6283 return true; |
| 6284 } |
| 6285 |
| 6286 |
| 6287 // TODO(jkummerow): Consider unification with FastAsArrayLength() in |
| 6288 // accessors.cc. |
| 6289 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) { |
| 6290 DCHECK(value->IsNumber() || value->IsName()); |
| 6291 if (value->ToArrayLength(length)) return true; |
| 6292 if (value->IsString()) return String::cast(*value)->AsArrayIndex(length); |
| 6293 return false; |
| 6294 } |
| 6295 |
| 6296 |
| 6297 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) { |
| 6298 return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32; |
| 6299 } |
| 6300 |
| 6301 |
| 6302 // ES6 9.4.2.1 |
| 6303 // static |
| 6304 bool JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o, |
| 6305 Handle<Object> name, PropertyDescriptor* desc, |
| 6306 ShouldThrow should_throw) { |
| 6307 // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.) |
| 6308 // 2. If P is "length", then: |
| 6309 // TODO(jkummerow): Check if we need slow string comparison. |
| 6310 if (*name == isolate->heap()->length_string()) { |
| 6311 // 2a. Return ArraySetLength(A, Desc). |
| 6312 return ArraySetLength(isolate, o, desc, should_throw); |
| 6313 } |
| 6314 // 3. Else if P is an array index, then: |
| 6315 uint32_t index = 0; |
| 6316 if (PropertyKeyToArrayIndex(name, &index)) { |
| 6317 // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). |
| 6318 PropertyDescriptor old_len_desc; |
| 6319 bool success = GetOwnPropertyDescriptor( |
| 6320 isolate, o, isolate->factory()->length_string(), &old_len_desc); |
| 6321 // 3b. (Assert) |
| 6322 DCHECK(success); |
| 6323 USE(success); |
| 6324 // 3c. Let oldLen be oldLenDesc.[[Value]]. |
| 6325 uint32_t old_len = 0; |
| 6326 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); |
| 6327 // 3d. Let index be ToUint32(P). |
| 6328 // (Already done above.) |
| 6329 // 3e. (Assert) |
| 6330 // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false, |
| 6331 // return false. |
| 6332 if (index >= old_len && old_len_desc.has_writable() && |
| 6333 !old_len_desc.writable()) { |
| 6334 if (should_throw == THROW_ON_ERROR) { |
| 6335 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6336 MessageTemplate::kDefineDisallowed, name)); |
| 6337 } |
| 6338 return false; |
| 6339 } |
| 6340 // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc). |
| 6341 bool succeeded = |
| 6342 OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); |
| 6343 // 3h. (Assert) |
| 6344 // 3i. If succeeded is false, return false. |
| 6345 if (!succeeded) return false; |
| 6346 // 3j. If index >= oldLen, then: |
| 6347 if (index >= old_len) { |
| 6348 // 3j i. Set oldLenDesc.[[Value]] to index + 1. |
| 6349 old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1)); |
| 6350 // 3j ii. Let succeeded be |
| 6351 // OrdinaryDefineOwnProperty(A, "length", oldLenDesc). |
| 6352 OrdinaryDefineOwnProperty(isolate, o, isolate->factory()->length_string(), |
| 6353 &old_len_desc, should_throw); |
| 6354 // 3j iii. (Assert) |
| 6355 } |
| 6356 // 3k. Return true. |
| 6357 return true; |
| 6358 } |
| 6359 |
| 6360 // 4. Return OrdinaryDefineOwnProperty(A, P, Desc). |
| 6361 return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw); |
| 6362 } |
| 6363 |
| 6364 |
| 6365 // TODO(jkummerow): Consider unification with ArrayLengthSetter in accessors.cc. |
| 6366 bool AnythingToArrayLength(Isolate* isolate, Handle<Object> length_obj, |
| 6367 uint32_t* output) { |
| 6368 // Fast path: check numbers and strings that can be converted directly |
| 6369 // and unobservably. |
| 6370 if (length_obj->ToUint32(output)) return true; |
| 6371 if (length_obj->IsString() && |
| 6372 Handle<String>::cast(length_obj)->AsArrayIndex(output)) { |
| 6373 return true; |
| 6374 } |
| 6375 // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength". |
| 6376 // 3. Let newLen be ToUint32(Desc.[[Value]]). |
| 6377 Handle<Object> uint32_v; |
| 6378 if (!Object::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) { |
| 6379 // 4. ReturnIfAbrupt(newLen). |
| 6380 return false; |
| 6381 } |
| 6382 // 5. Let numberLen be ToNumber(Desc.[[Value]]). |
| 6383 Handle<Object> number_v; |
| 6384 if (!Object::ToNumber(length_obj).ToHandle(&number_v)) { |
| 6385 // 6. ReturnIfAbrupt(newLen). |
| 6386 return false; |
| 6387 } |
| 6388 // 7. If newLen != numberLen, throw a RangeError exception. |
| 6389 if (uint32_v->Number() != number_v->Number()) { |
| 6390 Handle<Object> exception = |
| 6391 isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength); |
| 6392 isolate->Throw(*exception); |
| 6393 return false; |
| 6394 } |
| 6395 return uint32_v->ToArrayLength(output); |
| 6396 } |
| 6397 |
| 6398 |
| 6399 // ES6 9.4.2.4 |
| 6400 // static |
| 6401 bool JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a, |
| 6402 PropertyDescriptor* desc, |
| 6403 ShouldThrow should_throw) { |
| 6404 // 1. If the [[Value]] field of Desc is absent, then |
| 6405 if (!desc->has_value()) { |
| 6406 // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc). |
| 6407 return OrdinaryDefineOwnProperty( |
| 6408 isolate, a, isolate->factory()->length_string(), desc, should_throw); |
| 6409 } |
| 6410 // 2. Let newLenDesc be a copy of Desc. |
| 6411 // (Actual copying is not necessary.) |
| 6412 PropertyDescriptor* new_len_desc = desc; |
| 6413 // 3. - 7. Convert Desc.[[Value]] to newLen. |
| 6414 uint32_t new_len = 0; |
| 6415 if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) { |
| 6416 if (should_throw == THROW_ON_ERROR && !isolate->has_pending_exception()) { |
| 6417 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6418 MessageTemplate::kCannotConvertToPrimitive)); |
| 6419 } |
| 6420 return false; |
| 6421 } |
| 6422 // 8. Set newLenDesc.[[Value]] to newLen. |
| 6423 // (Done below, if needed.) |
| 6424 // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). |
| 6425 PropertyDescriptor old_len_desc; |
| 6426 bool success = GetOwnPropertyDescriptor( |
| 6427 isolate, a, isolate->factory()->length_string(), &old_len_desc); |
| 6428 // 10. (Assert) |
| 6429 DCHECK(success); |
| 6430 USE(success); |
| 6431 // 11. Let oldLen be oldLenDesc.[[Value]]. |
| 6432 uint32_t old_len = 0; |
| 6433 CHECK(old_len_desc.value()->ToArrayLength(&old_len)); |
| 6434 // 12. If newLen >= oldLen, then |
| 6435 if (new_len >= old_len) { |
| 6436 // 8. Set newLenDesc.[[Value]] to newLen. |
| 6437 // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc). |
| 6438 new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len)); |
| 6439 return OrdinaryDefineOwnProperty(isolate, a, |
| 6440 isolate->factory()->length_string(), |
| 6441 new_len_desc, should_throw); |
| 6442 } |
| 6443 // 13. If oldLenDesc.[[Writable]] is false, return false. |
| 6444 if (!old_len_desc.writable()) { |
| 6445 if (should_throw == THROW_ON_ERROR) |
| 6446 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6447 MessageTemplate::kRedefineDisallowed, |
| 6448 isolate->factory()->length_string())); |
| 6449 return false; |
| 6450 } |
| 6451 // 14. If newLenDesc.[[Writable]] is absent or has the value true, |
| 6452 // let newWritable be true. |
| 6453 bool new_writable = false; |
| 6454 if (!new_len_desc->has_writable() || new_len_desc->writable()) { |
| 6455 new_writable = true; |
| 6456 } else { |
| 6457 // 15. Else, |
| 6458 // 15a. Need to defer setting the [[Writable]] attribute to false in case |
| 6459 // any elements cannot be deleted. |
| 6460 // 15b. Let newWritable be false. (It's initialized as "false" anyway.) |
| 6461 // 15c. Set newLenDesc.[[Writable]] to true. |
| 6462 // (Not needed.) |
| 6463 } |
| 6464 // Most of steps 16 through 19 is implemented by JSArray::SetLength. |
| 6465 if (JSArray::ObservableSetLength(a, new_len).is_null()) { |
| 6466 DCHECK(isolate->has_pending_exception()); |
| 6467 return false; |
| 6468 } |
| 6469 // Steps 19d-ii, 20. |
| 6470 if (!new_writable) { |
| 6471 PropertyDescriptor readonly; |
| 6472 readonly.set_writable(false); |
| 6473 OrdinaryDefineOwnProperty(isolate, a, isolate->factory()->length_string(), |
| 6474 &readonly, should_throw); |
| 6475 } |
| 6476 uint32_t actual_new_len = 0; |
| 6477 CHECK(a->length()->ToArrayLength(&actual_new_len)); |
| 6478 // Steps 19d-v, 21. Return false if there were non-deletable elements. |
| 6479 success = actual_new_len == new_len; |
| 6480 if (!success && should_throw == THROW_ON_ERROR) { |
| 6481 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6482 MessageTemplate::kStrictDeleteProperty, |
| 6483 isolate->factory()->NewNumberFromUint(actual_new_len - 1))); |
| 6484 } |
| 6485 return success; |
| 6486 } |
| 6487 |
| 6488 |
| 6489 // static |
| 6490 bool JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate, |
| 6491 Handle<JSObject> object, |
| 6492 Handle<Object> key, |
| 6493 PropertyDescriptor* desc) { |
| 6494 bool success = false; |
| 6495 DCHECK(key->IsName() || key->IsNumber()); // |key| is a PropertyKey... |
| 6496 LookupIterator it = LookupIterator::PropertyOrElement( |
| 6497 isolate, object, key, &success, LookupIterator::HIDDEN); |
| 6498 DCHECK(success); // ...so creating a LookupIterator can't fail. |
| 6499 return GetOwnPropertyDescriptor(&it, desc); |
| 6500 } |
| 6501 |
| 6502 |
| 6503 // TODO(jkummerow): Any chance to unify this with |
| 6504 // "MaybeHandle<Object> GetOwnProperty()" in runtime-object.cc? |
| 6505 |
| 6506 // TODO(jkummerow/verwaest): Proxy support: call getOwnPropertyDescriptor trap |
| 6507 // and convert the result (if it's an object) with ToPropertyDescriptor. |
| 6508 |
| 6509 // ES6 9.1.5.1 |
| 6510 // Returns true on success; false if there was an exception or no property. |
| 6511 // static |
| 6512 bool JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it, |
| 6513 PropertyDescriptor* desc) { |
| 6514 Isolate* isolate = it->isolate(); |
| 6515 // 1. (Assert) |
| 6516 // 2. If O does not have an own property with key P, return undefined. |
| 6517 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it); |
| 6518 |
| 6519 if (!maybe.IsJust()) return false; |
| 6520 PropertyAttributes attrs = maybe.FromJust(); |
| 6521 if (attrs == ABSENT) return false; |
| 6522 DCHECK(!isolate->has_pending_exception()); |
| 6523 |
| 6524 // 3. Let D be a newly created Property Descriptor with no fields. |
| 6525 DCHECK(desc->is_empty()); |
| 6526 // 4. Let X be O's own property whose key is P. |
| 6527 // 5. If X is a data property, then |
| 6528 bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR && |
| 6529 it->GetAccessors()->IsAccessorPair(); |
| 6530 if (!is_accessor_pair) { |
| 6531 // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute. |
| 6532 Handle<Object> value = JSObject::GetProperty(it).ToHandleChecked(); |
| 6533 desc->set_value(value); |
| 6534 // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute |
| 6535 desc->set_writable((attrs & READ_ONLY) == 0); |
| 6536 } else { |
| 6537 // 6. Else X is an accessor property, so |
| 6538 Handle<AccessorPair> accessors = |
| 6539 Handle<AccessorPair>::cast(it->GetAccessors()); |
| 6540 // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute. |
| 6541 desc->set_get(handle(accessors->GetComponent(ACCESSOR_GETTER), isolate)); |
| 6542 // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute. |
| 6543 desc->set_set(handle(accessors->GetComponent(ACCESSOR_SETTER), isolate)); |
| 6544 } |
| 6545 |
| 6546 // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute. |
| 6547 desc->set_enumerable((attrs & DONT_ENUM) == 0); |
| 6548 // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute. |
| 6549 desc->set_configurable((attrs & DONT_DELETE) == 0); |
| 6550 // 9. Return D. |
| 6551 return true; |
| 6552 } |
| 6553 |
| 6554 |
5829 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 6555 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
5830 ElementsKind kind, | 6556 ElementsKind kind, |
5831 Object* object) { | 6557 Object* object) { |
5832 DCHECK(IsFastObjectElementsKind(kind) || | 6558 DCHECK(IsFastObjectElementsKind(kind) || |
5833 kind == DICTIONARY_ELEMENTS); | 6559 kind == DICTIONARY_ELEMENTS); |
5834 if (IsFastObjectElementsKind(kind)) { | 6560 if (IsFastObjectElementsKind(kind)) { |
5835 int length = IsJSArray() | 6561 int length = IsJSArray() |
5836 ? Smi::cast(JSArray::cast(this)->length())->value() | 6562 ? Smi::cast(JSArray::cast(this)->length())->value() |
5837 : elements->length(); | 6563 : elements->length(); |
5838 for (int i = 0; i < length; ++i) { | 6564 for (int i = 0; i < length; ++i) { |
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6976 | 7702 |
6977 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, | 7703 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object, |
6978 Handle<Name> name, | 7704 Handle<Name> name, |
6979 Handle<Object> getter, | 7705 Handle<Object> getter, |
6980 Handle<Object> setter, | 7706 Handle<Object> setter, |
6981 PropertyAttributes attributes) { | 7707 PropertyAttributes attributes) { |
6982 Isolate* isolate = object->GetIsolate(); | 7708 Isolate* isolate = object->GetIsolate(); |
6983 | 7709 |
6984 LookupIterator it = LookupIterator::PropertyOrElement( | 7710 LookupIterator it = LookupIterator::PropertyOrElement( |
6985 isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); | 7711 isolate, object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR); |
| 7712 return DefineAccessor(&it, getter, setter, attributes); |
| 7713 } |
6986 | 7714 |
6987 if (it.state() == LookupIterator::ACCESS_CHECK) { | 7715 |
6988 if (!it.HasAccess()) { | 7716 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it, |
6989 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>()); | 7717 Handle<Object> getter, |
| 7718 Handle<Object> setter, |
| 7719 PropertyAttributes attributes) { |
| 7720 Isolate* isolate = it->isolate(); |
| 7721 |
| 7722 if (it->state() == LookupIterator::ACCESS_CHECK) { |
| 7723 if (!it->HasAccess()) { |
| 7724 isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>()); |
6990 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 7725 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
6991 return isolate->factory()->undefined_value(); | 7726 return isolate->factory()->undefined_value(); |
6992 } | 7727 } |
6993 it.Next(); | 7728 it->Next(); |
6994 } | 7729 } |
6995 | 7730 |
| 7731 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); |
6996 // Ignore accessors on typed arrays. | 7732 // Ignore accessors on typed arrays. |
6997 if (it.IsElement() && object->HasFixedTypedArrayElements()) { | 7733 if (it->IsElement() && object->HasFixedTypedArrayElements()) { |
6998 return it.factory()->undefined_value(); | 7734 return it->factory()->undefined_value(); |
6999 } | 7735 } |
7000 | 7736 |
7001 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 7737 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
7002 bool is_observed = object->map()->is_observed() && | 7738 bool is_observed = object->map()->is_observed() && |
7003 !isolate->IsInternallyUsedPropertyName(name); | 7739 !isolate->IsInternallyUsedPropertyName(it->GetName()); |
7004 bool preexists = false; | 7740 bool preexists = false; |
7005 if (is_observed) { | 7741 if (is_observed) { |
7006 CHECK(GetPropertyAttributes(&it).IsJust()); | 7742 CHECK(GetPropertyAttributes(it).IsJust()); |
7007 preexists = it.IsFound(); | 7743 preexists = it->IsFound(); |
7008 if (preexists && (it.state() == LookupIterator::DATA || | 7744 if (preexists && (it->state() == LookupIterator::DATA || |
7009 it.GetAccessors()->IsAccessorInfo())) { | 7745 it->GetAccessors()->IsAccessorInfo())) { |
7010 old_value = GetProperty(&it).ToHandleChecked(); | 7746 old_value = GetProperty(it).ToHandleChecked(); |
7011 } | 7747 } |
7012 } | 7748 } |
7013 | 7749 |
7014 DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull()); | 7750 DCHECK(getter->IsCallable() || getter->IsUndefined() || getter->IsNull()); |
7015 DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull()); | 7751 DCHECK(setter->IsCallable() || setter->IsUndefined() || setter->IsNull()); |
7016 // At least one of the accessors needs to be a new value. | 7752 // At least one of the accessors needs to be a new value. |
7017 DCHECK(!getter->IsNull() || !setter->IsNull()); | 7753 DCHECK(!getter->IsNull() || !setter->IsNull()); |
7018 if (!getter->IsNull()) { | 7754 if (!getter->IsNull()) { |
7019 it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); | 7755 it->TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes); |
7020 } | 7756 } |
7021 if (!setter->IsNull()) { | 7757 if (!setter->IsNull()) { |
7022 it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); | 7758 it->TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes); |
7023 } | 7759 } |
7024 | 7760 |
7025 if (is_observed) { | 7761 if (is_observed) { |
7026 // Make sure the top context isn't changed. | 7762 // Make sure the top context isn't changed. |
7027 AssertNoContextChange ncc(isolate); | 7763 AssertNoContextChange ncc(isolate); |
7028 const char* type = preexists ? "reconfigure" : "add"; | 7764 const char* type = preexists ? "reconfigure" : "add"; |
7029 RETURN_ON_EXCEPTION( | 7765 RETURN_ON_EXCEPTION( |
7030 isolate, EnqueueChangeRecord(object, type, name, old_value), Object); | 7766 isolate, EnqueueChangeRecord(object, type, it->GetName(), old_value), |
| 7767 Object); |
7031 } | 7768 } |
7032 | 7769 |
7033 return isolate->factory()->undefined_value(); | 7770 return isolate->factory()->undefined_value(); |
7034 } | 7771 } |
7035 | 7772 |
7036 | 7773 |
7037 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, | 7774 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, |
7038 Handle<AccessorInfo> info) { | 7775 Handle<AccessorInfo> info) { |
7039 Isolate* isolate = object->GetIsolate(); | 7776 Isolate* isolate = object->GetIsolate(); |
7040 Handle<Name> name(Name::cast(info->name()), isolate); | 7777 Handle<Name> name(Name::cast(info->name()), isolate); |
(...skipping 9827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16868 if (cell->value() != *new_value) { | 17605 if (cell->value() != *new_value) { |
16869 cell->set_value(*new_value); | 17606 cell->set_value(*new_value); |
16870 Isolate* isolate = cell->GetIsolate(); | 17607 Isolate* isolate = cell->GetIsolate(); |
16871 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17608 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16872 isolate, DependentCode::kPropertyCellChangedGroup); | 17609 isolate, DependentCode::kPropertyCellChangedGroup); |
16873 } | 17610 } |
16874 } | 17611 } |
16875 | 17612 |
16876 } // namespace internal | 17613 } // namespace internal |
16877 } // namespace v8 | 17614 } // namespace v8 |
OLD | NEW |