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

Side by Side Diff: src/builtins/builtins-object.cc

Issue 2606833002: [ESnext] Implement Object spread (Closed)
Patch Set: fix test 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
« no previous file with comments | « src/bootstrapper.cc ('k') | src/compiler/ast-graph-builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stub-assembler.h" 8 #include "src/code-stub-assembler.h"
9 #include "src/property-descriptor.h" 9 #include "src/property-descriptor.h"
10 10
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 assembler.Return(assembler.BooleanConstant(true)); 59 assembler.Return(assembler.BooleanConstant(true));
60 60
61 assembler.Bind(&return_false); 61 assembler.Bind(&return_false);
62 assembler.Return(assembler.BooleanConstant(false)); 62 assembler.Return(assembler.BooleanConstant(false));
63 63
64 assembler.Bind(&call_runtime); 64 assembler.Bind(&call_runtime);
65 assembler.Return(assembler.CallRuntime(Runtime::kObjectHasOwnProperty, 65 assembler.Return(assembler.CallRuntime(Runtime::kObjectHasOwnProperty,
66 context, object, key)); 66 context, object, key));
67 } 67 }
68 68
69 namespace {
70
71 MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
72 Handle<Object> next_source) {
73 // Non-empty strings are the only non-JSReceivers that need to be handled
74 // explicitly by Object.assign.
75 if (!next_source->IsJSReceiver()) {
76 return Just(!next_source->IsString() ||
77 String::cast(*next_source)->length() == 0);
78 }
79
80 // If the target is deprecated, the object will be updated on first store. If
81 // the source for that store equals the target, this will invalidate the
82 // cached representation of the source. Preventively upgrade the target.
83 // Do this on each iteration since any property load could cause deprecation.
84 if (to->map()->is_deprecated()) {
85 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
86 }
87
88 Isolate* isolate = to->GetIsolate();
89 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
90
91 if (!map->IsJSObjectMap()) return Just(false);
92 if (!map->OnlyHasSimpleProperties()) return Just(false);
93
94 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
95 if (from->elements() != isolate->heap()->empty_fixed_array()) {
96 return Just(false);
97 }
98
99 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
100 int length = map->NumberOfOwnDescriptors();
101
102 bool stable = true;
103
104 for (int i = 0; i < length; i++) {
105 Handle<Name> next_key(descriptors->GetKey(i), isolate);
106 Handle<Object> prop_value;
107 // Directly decode from the descriptor array if |from| did not change shape.
108 if (stable) {
109 PropertyDetails details = descriptors->GetDetails(i);
110 if (!details.IsEnumerable()) continue;
111 if (details.kind() == kData) {
112 if (details.location() == kDescriptor) {
113 prop_value = handle(descriptors->GetValue(i), isolate);
114 } else {
115 Representation representation = details.representation();
116 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
117 prop_value = JSObject::FastPropertyAt(from, representation, index);
118 }
119 } else {
120 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
121 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
122 Nothing<bool>());
123 stable = from->map() == *map;
124 }
125 } else {
126 // If the map did change, do a slower lookup. We are still guaranteed that
127 // the object has a simple shape, and that the key is a name.
128 LookupIterator it(from, next_key, from,
129 LookupIterator::OWN_SKIP_INTERCEPTOR);
130 if (!it.IsFound()) continue;
131 DCHECK(it.state() == LookupIterator::DATA ||
132 it.state() == LookupIterator::ACCESSOR);
133 if (!it.IsEnumerable()) continue;
134 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
135 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
136 }
137 LookupIterator it(to, next_key, to);
138 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
139 Maybe<bool> result = Object::SetProperty(
140 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
141 if (result.IsNothing()) return result;
142 if (stable && call_to_js) stable = from->map() == *map;
143 }
144
145 return Just(true);
146 }
147
148 } // namespace
149
150 // ES6 19.1.2.1 Object.assign 69 // ES6 19.1.2.1 Object.assign
151 BUILTIN(ObjectAssign) { 70 BUILTIN(ObjectAssign) {
152 HandleScope scope(isolate); 71 HandleScope scope(isolate);
153 Handle<Object> target = args.atOrUndefined(isolate, 1); 72 Handle<Object> target = args.atOrUndefined(isolate, 1);
154 73
155 // 1. Let to be ? ToObject(target). 74 // 1. Let to be ? ToObject(target).
156 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target, 75 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
157 Object::ToObject(isolate, target)); 76 Object::ToObject(isolate, target));
158 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target); 77 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
159 // 2. If only one argument was passed, return to. 78 // 2. If only one argument was passed, return to.
160 if (args.length() == 2) return *to; 79 if (args.length() == 2) return *to;
161 // 3. Let sources be the List of argument values starting with the 80 // 3. Let sources be the List of argument values starting with the
162 // second argument. 81 // second argument.
163 // 4. For each element nextSource of sources, in ascending index order, 82 // 4. For each element nextSource of sources, in ascending index order,
164 for (int i = 2; i < args.length(); ++i) { 83 for (int i = 2; i < args.length(); ++i) {
165 Handle<Object> next_source = args.at(i); 84 Handle<Object> next_source = args.at(i);
166 Maybe<bool> fast_assign = FastAssign(to, next_source); 85 MAYBE_RETURN(
167 if (fast_assign.IsNothing()) return isolate->heap()->exception(); 86 JSReceiver::SetOrCopyDataProperties(isolate, to, next_source, true),
168 if (fast_assign.FromJust()) continue; 87 isolate->heap()->exception());
169 // 4a. If nextSource is undefined or null, let keys be an empty List.
170 // 4b. Else,
171 // 4b i. Let from be ToObject(nextSource).
172 // Only non-empty strings and JSReceivers have enumerable properties.
173 Handle<JSReceiver> from =
174 Object::ToObject(isolate, next_source).ToHandleChecked();
175 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
176 Handle<FixedArray> keys;
177 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
178 isolate, keys, KeyAccumulator::GetKeys(
179 from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
180 GetKeysConversion::kKeepNumbers));
181 // 4c. Repeat for each element nextKey of keys in List order,
182 for (int j = 0; j < keys->length(); ++j) {
183 Handle<Object> next_key(keys->get(j), isolate);
184 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
185 PropertyDescriptor desc;
186 Maybe<bool> found =
187 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
188 if (found.IsNothing()) return isolate->heap()->exception();
189 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
190 if (found.FromJust() && desc.enumerable()) {
191 // 4c ii 1. Let propValue be ? Get(from, nextKey).
192 Handle<Object> prop_value;
193 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
194 isolate, prop_value,
195 Runtime::GetObjectProperty(isolate, from, next_key));
196 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
197 Handle<Object> status;
198 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
199 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
200 prop_value, STRICT));
201 }
202 }
203 } 88 }
204 // 5. Return to. 89 // 5. Return to.
205 return *to; 90 return *to;
206 } 91 }
207 92
208 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V ) 93 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
209 BUILTIN(ObjectPrototypePropertyIsEnumerable) { 94 BUILTIN(ObjectPrototypePropertyIsEnumerable) {
210 HandleScope scope(isolate); 95 HandleScope scope(isolate);
211 Handle<JSReceiver> object; 96 Handle<JSReceiver> object;
212 Handle<Name> name; 97 Handle<Name> name;
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 CodeStubAssembler assembler(state); 985 CodeStubAssembler assembler(state);
1101 986
1102 Node* object = assembler.Parameter(Descriptor::kObject); 987 Node* object = assembler.Parameter(Descriptor::kObject);
1103 Node* context = assembler.Parameter(Descriptor::kContext); 988 Node* context = assembler.Parameter(Descriptor::kContext);
1104 989
1105 assembler.Return(assembler.GetSuperConstructor(object, context)); 990 assembler.Return(assembler.GetSuperConstructor(object, context));
1106 } 991 }
1107 992
1108 } // namespace internal 993 } // namespace internal
1109 } // namespace v8 994 } // namespace v8
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/compiler/ast-graph-builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698