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