Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: src/objects.cc

Issue 2606833002: [ESnext] Implement Object spread (Closed)
Patch Set: fix build Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 1981 matching lines...) Expand 10 before | Expand all | Expand 10 after
1992 PrototypeIterator iter(isolate, object, kStartAtReceiver); 1992 PrototypeIterator iter(isolate, object, kStartAtReceiver);
1993 while (true) { 1993 while (true) {
1994 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); 1994 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
1995 if (iter.IsAtEnd()) return Just(false); 1995 if (iter.IsAtEnd()) return Just(false);
1996 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { 1996 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
1997 return Just(true); 1997 return Just(true);
1998 } 1998 }
1999 } 1999 }
2000 } 2000 }
2001 2001
2002 namespace {
2003
2004 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> target,
2005 Handle<Object> source, bool use_set) {
2006 // Non-empty strings are the only non-JSReceivers that need to be handled
2007 // explicitly by Object.assign.
2008 if (!source->IsJSReceiver()) {
2009 return Just(!source->IsString() || String::cast(*source)->length() == 0);
2010 }
2011
2012 // If the target is deprecated, the object will be updated on first store. If
2013 // the source for that store equals the target, this will invalidate the
2014 // cached representation of the source. Preventively upgrade the target.
2015 // Do this on each iteration since any property load could cause deprecation.
2016 if (target->map()->is_deprecated()) {
2017 JSObject::MigrateInstance(Handle<JSObject>::cast(target));
2018 }
2019
2020 Isolate* isolate = target->GetIsolate();
2021 Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
2022
2023 if (!map->IsJSObjectMap()) return Just(false);
2024 if (!map->OnlyHasSimpleProperties()) return Just(false);
2025
2026 Handle<JSObject> from = Handle<JSObject>::cast(source);
2027 if (from->elements() != isolate->heap()->empty_fixed_array()) {
2028 return Just(false);
2029 }
2030
2031 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
2032 int length = map->NumberOfOwnDescriptors();
2033
2034 bool stable = true;
2035
2036 for (int i = 0; i < length; i++) {
2037 Handle<Name> next_key(descriptors->GetKey(i), isolate);
2038 Handle<Object> prop_value;
2039 // Directly decode from the descriptor array if |from| did not change shape.
2040 if (stable) {
2041 PropertyDetails details = descriptors->GetDetails(i);
2042 if (!details.IsEnumerable()) continue;
2043 if (details.kind() == kData) {
2044 if (details.location() == kDescriptor) {
2045 prop_value = handle(descriptors->GetValue(i), isolate);
2046 } else {
2047 Representation representation = details.representation();
2048 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
2049 prop_value = JSObject::FastPropertyAt(from, representation, index);
2050 }
2051 } else {
2052 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2053 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
2054 Nothing<bool>());
2055 stable = from->map() == *map;
2056 }
2057 } else {
2058 // If the map did change, do a slower lookup. We are still guaranteed that
2059 // the object has a simple shape, and that the key is a name.
2060 LookupIterator it(from, next_key, from,
2061 LookupIterator::OWN_SKIP_INTERCEPTOR);
2062 if (!it.IsFound()) continue;
2063 DCHECK(it.state() == LookupIterator::DATA ||
2064 it.state() == LookupIterator::ACCESSOR);
2065 if (!it.IsEnumerable()) continue;
2066 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2067 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
2068 }
2069
2070 if (use_set) {
2071 LookupIterator it(target, next_key, target);
2072 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
2073 Maybe<bool> result = Object::SetProperty(
2074 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
2075 if (result.IsNothing()) return result;
2076 if (stable && call_to_js) stable = from->map() == *map;
2077 } else {
2078 // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
2079 bool success;
2080 LookupIterator it = LookupIterator::PropertyOrElement(
2081 isolate, target, next_key, &success, LookupIterator::OWN);
2082 if (!success) return Nothing<bool>();
2083 MAYBE_RETURN(JSReceiver::CreateDataProperty(&it, prop_value,
2084 Object::THROW_ON_ERROR),
2085 Nothing<bool>());
2086 }
2087 }
2088
2089 return Just(true);
2090 }
2091
2092 } // namespace
2093
2094 // static
2095 Maybe<bool> JSReceiver::SetOrCopyDataProperties(Isolate* isolate,
2096 Handle<JSReceiver> target,
2097 Handle<Object> source,
2098 bool use_set) {
Dan Ehrenberg 2016/12/29 17:31:03 I'm slightly worried that checking use_set paramet
gsathya 2017/01/05 22:18:36 Acknowledged.
2099 Maybe<bool> fast_assign = FastAssign(target, source, use_set);
2100 if (fast_assign.IsNothing()) return Nothing<bool>();
2101 if (fast_assign.FromJust()) return Just(true);
2102
2103 Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
2104 // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
2105 Handle<FixedArray> keys;
2106 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2107 isolate, keys,
2108 KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2109 GetKeysConversion::kKeepNumbers),
2110 Nothing<bool>());
2111
2112 // 4. Repeat for each element nextKey of keys in List order,
2113 for (int j = 0; j < keys->length(); ++j) {
adamk 2016/12/29 18:32:46 s/j/i/ now that this isn't a nested loop.
gsathya 2017/01/05 22:18:36 Done.
2114 Handle<Object> next_key(keys->get(j), isolate);
2115 // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
2116 PropertyDescriptor desc;
2117 Maybe<bool> found =
2118 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
2119 if (found.IsNothing()) return Nothing<bool>();
2120 // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
2121 if (found.FromJust() && desc.enumerable()) {
2122 // 4a ii 1. Let propValue be ? Get(from, nextKey).
2123 Handle<Object> prop_value;
2124 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2125 isolate, prop_value,
2126 Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
2127
2128 if (use_set) {
2129 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
2130 Handle<Object> status;
2131 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2132 isolate, status, Runtime::SetObjectProperty(
2133 isolate, target, next_key, prop_value, STRICT),
2134 Nothing<bool>());
2135 } else {
2136 // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
2137 bool success;
2138 LookupIterator it = LookupIterator::PropertyOrElement(
2139 isolate, target, next_key, &success, LookupIterator::OWN);
2140 if (!success) return Nothing<bool>();
adamk 2016/12/29 18:32:46 How could this fail?
gsathya 2017/01/05 22:18:36 Changed to CHECK.
2141 MAYBE_RETURN(JSReceiver::CreateDataProperty(&it, prop_value,
adamk 2016/12/29 18:32:46 Or this? I think it's quite likely you could use
gsathya 2017/01/05 22:18:36 Changed to CHECK.
2142 Object::THROW_ON_ERROR),
2143 Nothing<bool>());
2144 }
2145 }
2146 }
2147
2148 return Just(true);
2149 }
2150
2002 Map* Object::GetPrototypeChainRootMap(Isolate* isolate) { 2151 Map* Object::GetPrototypeChainRootMap(Isolate* isolate) {
2003 DisallowHeapAllocation no_alloc; 2152 DisallowHeapAllocation no_alloc;
2004 if (IsSmi()) { 2153 if (IsSmi()) {
2005 Context* native_context = isolate->context()->native_context(); 2154 Context* native_context = isolate->context()->native_context();
2006 return native_context->number_function()->initial_map(); 2155 return native_context->number_function()->initial_map();
2007 } 2156 }
2008 2157
2009 // The object is either a number, a string, a symbol, a boolean, a SIMD value, 2158 // The object is either a number, a string, a symbol, a boolean, a SIMD value,
2010 // a real JS object, or a Harmony proxy. 2159 // a real JS object, or a Harmony proxy.
2011 HeapObject* heap_object = HeapObject::cast(this); 2160 HeapObject* heap_object = HeapObject::cast(this);
(...skipping 18350 matching lines...) Expand 10 before | Expand all | Expand 10 after
20362 // depend on this. 20511 // depend on this.
20363 return DICTIONARY_ELEMENTS; 20512 return DICTIONARY_ELEMENTS;
20364 } 20513 }
20365 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20514 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20366 return kind; 20515 return kind;
20367 } 20516 }
20368 } 20517 }
20369 20518
20370 } // namespace internal 20519 } // namespace internal
20371 } // namespace v8 20520 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698