OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <memory> | 9 #include <memory> |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 1985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1996 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); | 1996 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); |
1997 if (iter.IsAtEnd()) return Just(false); | 1997 if (iter.IsAtEnd()) return Just(false); |
1998 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { | 1998 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { |
1999 return Just(true); | 1999 return Just(true); |
2000 } | 2000 } |
2001 } | 2001 } |
2002 } | 2002 } |
2003 | 2003 |
2004 namespace { | 2004 namespace { |
2005 | 2005 |
2006 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> target, | 2006 bool HasExcludedProperty(const ScopedVector<Handle<Name>>* excluded_properties, |
2007 Handle<Object> source, bool use_set) { | 2007 Handle<Object> search_element) { |
| 2008 // TODO(gsathya): Change this to be a hashtable. |
| 2009 for (int i = 0; i < excluded_properties->length(); i++) { |
| 2010 if (search_element->SameValue(*excluded_properties->at(i))) { |
| 2011 return true; |
| 2012 } |
| 2013 } |
| 2014 |
| 2015 return false; |
| 2016 } |
| 2017 |
| 2018 MUST_USE_RESULT Maybe<bool> FastAssign( |
| 2019 Handle<JSReceiver> target, Handle<Object> source, |
| 2020 const ScopedVector<Handle<Name>>* excluded_properties, bool use_set) { |
2008 // Non-empty strings are the only non-JSReceivers that need to be handled | 2021 // Non-empty strings are the only non-JSReceivers that need to be handled |
2009 // explicitly by Object.assign. | 2022 // explicitly by Object.assign. |
2010 if (!source->IsJSReceiver()) { | 2023 if (!source->IsJSReceiver()) { |
2011 return Just(!source->IsString() || String::cast(*source)->length() == 0); | 2024 return Just(!source->IsString() || String::cast(*source)->length() == 0); |
2012 } | 2025 } |
2013 | 2026 |
2014 // If the target is deprecated, the object will be updated on first store. If | 2027 // If the target is deprecated, the object will be updated on first store. If |
2015 // the source for that store equals the target, this will invalidate the | 2028 // the source for that store equals the target, this will invalidate the |
2016 // cached representation of the source. Preventively upgrade the target. | 2029 // cached representation of the source. Preventively upgrade the target. |
2017 // Do this on each iteration since any property load could cause deprecation. | 2030 // Do this on each iteration since any property load could cause deprecation. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 } | 2083 } |
2071 | 2084 |
2072 if (use_set) { | 2085 if (use_set) { |
2073 LookupIterator it(target, next_key, target); | 2086 LookupIterator it(target, next_key, target); |
2074 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA; | 2087 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA; |
2075 Maybe<bool> result = Object::SetProperty( | 2088 Maybe<bool> result = Object::SetProperty( |
2076 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED); | 2089 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED); |
2077 if (result.IsNothing()) return result; | 2090 if (result.IsNothing()) return result; |
2078 if (stable && call_to_js) stable = from->map() == *map; | 2091 if (stable && call_to_js) stable = from->map() == *map; |
2079 } else { | 2092 } else { |
| 2093 if (excluded_properties != nullptr && |
| 2094 HasExcludedProperty(excluded_properties, next_key)) { |
| 2095 continue; |
| 2096 } |
| 2097 |
2080 // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue). | 2098 // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue). |
2081 bool success; | 2099 bool success; |
2082 LookupIterator it = LookupIterator::PropertyOrElement( | 2100 LookupIterator it = LookupIterator::PropertyOrElement( |
2083 isolate, target, next_key, &success, LookupIterator::OWN); | 2101 isolate, target, next_key, &success, LookupIterator::OWN); |
2084 CHECK(success); | 2102 CHECK(success); |
2085 CHECK( | 2103 CHECK( |
2086 JSObject::CreateDataProperty(&it, prop_value, Object::THROW_ON_ERROR) | 2104 JSObject::CreateDataProperty(&it, prop_value, Object::THROW_ON_ERROR) |
2087 .FromJust()); | 2105 .FromJust()); |
2088 } | 2106 } |
2089 } | 2107 } |
2090 | 2108 |
2091 return Just(true); | 2109 return Just(true); |
2092 } | 2110 } |
2093 | |
2094 } // namespace | 2111 } // namespace |
2095 | 2112 |
2096 // static | 2113 // static |
2097 Maybe<bool> JSReceiver::SetOrCopyDataProperties(Isolate* isolate, | 2114 Maybe<bool> JSReceiver::SetOrCopyDataProperties( |
2098 Handle<JSReceiver> target, | 2115 Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source, |
2099 Handle<Object> source, | 2116 const ScopedVector<Handle<Name>>* excluded_properties, bool use_set) { |
2100 bool use_set) { | 2117 Maybe<bool> fast_assign = |
2101 Maybe<bool> fast_assign = FastAssign(target, source, use_set); | 2118 FastAssign(target, source, excluded_properties, use_set); |
2102 if (fast_assign.IsNothing()) return Nothing<bool>(); | 2119 if (fast_assign.IsNothing()) return Nothing<bool>(); |
2103 if (fast_assign.FromJust()) return Just(true); | 2120 if (fast_assign.FromJust()) return Just(true); |
2104 | 2121 |
2105 Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked(); | 2122 Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked(); |
2106 // 3b. Let keys be ? from.[[OwnPropertyKeys]](). | 2123 // 3b. Let keys be ? from.[[OwnPropertyKeys]](). |
2107 Handle<FixedArray> keys; | 2124 Handle<FixedArray> keys; |
2108 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 2125 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
2109 isolate, keys, | 2126 isolate, keys, |
2110 KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES, | 2127 KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES, |
2111 GetKeysConversion::kKeepNumbers), | 2128 GetKeysConversion::kConvertToString), |
2112 Nothing<bool>()); | 2129 Nothing<bool>()); |
2113 | 2130 |
2114 // 4. Repeat for each element nextKey of keys in List order, | 2131 // 4. Repeat for each element nextKey of keys in List order, |
2115 for (int j = 0; j < keys->length(); ++j) { | 2132 for (int j = 0; j < keys->length(); ++j) { |
2116 Handle<Object> next_key(keys->get(j), isolate); | 2133 Handle<Object> next_key(keys->get(j), isolate); |
2117 // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey). | 2134 // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey). |
2118 PropertyDescriptor desc; | 2135 PropertyDescriptor desc; |
2119 Maybe<bool> found = | 2136 Maybe<bool> found = |
2120 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc); | 2137 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc); |
2121 if (found.IsNothing()) return Nothing<bool>(); | 2138 if (found.IsNothing()) return Nothing<bool>(); |
2122 // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then | 2139 // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then |
2123 if (found.FromJust() && desc.enumerable()) { | 2140 if (found.FromJust() && desc.enumerable()) { |
2124 // 4a ii 1. Let propValue be ? Get(from, nextKey). | 2141 // 4a ii 1. Let propValue be ? Get(from, nextKey). |
2125 Handle<Object> prop_value; | 2142 Handle<Object> prop_value; |
2126 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 2143 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
2127 isolate, prop_value, | 2144 isolate, prop_value, |
2128 Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>()); | 2145 Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>()); |
2129 | 2146 |
2130 if (use_set) { | 2147 if (use_set) { |
2131 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true). | 2148 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true). |
2132 Handle<Object> status; | 2149 Handle<Object> status; |
2133 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 2150 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
2134 isolate, status, Runtime::SetObjectProperty( | 2151 isolate, status, Runtime::SetObjectProperty( |
2135 isolate, target, next_key, prop_value, STRICT), | 2152 isolate, target, next_key, prop_value, STRICT), |
2136 Nothing<bool>()); | 2153 Nothing<bool>()); |
2137 } else { | 2154 } else { |
| 2155 if (excluded_properties != nullptr && |
| 2156 HasExcludedProperty(excluded_properties, next_key)) { |
| 2157 continue; |
| 2158 } |
| 2159 |
2138 // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue). | 2160 // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue). |
2139 bool success; | 2161 bool success; |
2140 LookupIterator it = LookupIterator::PropertyOrElement( | 2162 LookupIterator it = LookupIterator::PropertyOrElement( |
2141 isolate, target, next_key, &success, LookupIterator::OWN); | 2163 isolate, target, next_key, &success, LookupIterator::OWN); |
2142 CHECK(success); | 2164 CHECK(success); |
2143 CHECK(JSObject::CreateDataProperty(&it, prop_value, | 2165 CHECK(JSObject::CreateDataProperty(&it, prop_value, |
2144 Object::THROW_ON_ERROR) | 2166 Object::THROW_ON_ERROR) |
2145 .FromJust()); | 2167 .FromJust()); |
2146 } | 2168 } |
2147 } | 2169 } |
(...skipping 17749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19897 // depend on this. | 19919 // depend on this. |
19898 return DICTIONARY_ELEMENTS; | 19920 return DICTIONARY_ELEMENTS; |
19899 } | 19921 } |
19900 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 19922 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
19901 return kind; | 19923 return kind; |
19902 } | 19924 } |
19903 } | 19925 } |
19904 | 19926 |
19905 } // namespace internal | 19927 } // namespace internal |
19906 } // namespace v8 | 19928 } // namespace v8 |
OLD | NEW |