| Index: src/builtins/builtins-object.cc
|
| diff --git a/src/builtins/builtins-object.cc b/src/builtins/builtins-object.cc
|
| index 1de47667b73255638f3b2ebb72f35d4d99cd7ab4..8efee178c0e6536459fafdb7c9b68e6e4549f20f 100644
|
| --- a/src/builtins/builtins-object.cc
|
| +++ b/src/builtins/builtins-object.cc
|
| @@ -66,87 +66,6 @@ void Builtins::Generate_ObjectHasOwnProperty(
|
| context, object, key));
|
| }
|
|
|
| -namespace {
|
| -
|
| -MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
|
| - Handle<Object> next_source) {
|
| - // Non-empty strings are the only non-JSReceivers that need to be handled
|
| - // explicitly by Object.assign.
|
| - if (!next_source->IsJSReceiver()) {
|
| - return Just(!next_source->IsString() ||
|
| - String::cast(*next_source)->length() == 0);
|
| - }
|
| -
|
| - // If the target is deprecated, the object will be updated on first store. If
|
| - // the source for that store equals the target, this will invalidate the
|
| - // cached representation of the source. Preventively upgrade the target.
|
| - // Do this on each iteration since any property load could cause deprecation.
|
| - if (to->map()->is_deprecated()) {
|
| - JSObject::MigrateInstance(Handle<JSObject>::cast(to));
|
| - }
|
| -
|
| - Isolate* isolate = to->GetIsolate();
|
| - Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
|
| -
|
| - if (!map->IsJSObjectMap()) return Just(false);
|
| - if (!map->OnlyHasSimpleProperties()) return Just(false);
|
| -
|
| - Handle<JSObject> from = Handle<JSObject>::cast(next_source);
|
| - if (from->elements() != isolate->heap()->empty_fixed_array()) {
|
| - return Just(false);
|
| - }
|
| -
|
| - Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
|
| - int length = map->NumberOfOwnDescriptors();
|
| -
|
| - bool stable = true;
|
| -
|
| - for (int i = 0; i < length; i++) {
|
| - Handle<Name> next_key(descriptors->GetKey(i), isolate);
|
| - Handle<Object> prop_value;
|
| - // Directly decode from the descriptor array if |from| did not change shape.
|
| - if (stable) {
|
| - PropertyDetails details = descriptors->GetDetails(i);
|
| - if (!details.IsEnumerable()) continue;
|
| - if (details.kind() == kData) {
|
| - if (details.location() == kDescriptor) {
|
| - prop_value = handle(descriptors->GetValue(i), isolate);
|
| - } else {
|
| - Representation representation = details.representation();
|
| - FieldIndex index = FieldIndex::ForDescriptor(*map, i);
|
| - prop_value = JSObject::FastPropertyAt(from, representation, index);
|
| - }
|
| - } else {
|
| - ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
| - isolate, prop_value, JSReceiver::GetProperty(from, next_key),
|
| - Nothing<bool>());
|
| - stable = from->map() == *map;
|
| - }
|
| - } else {
|
| - // If the map did change, do a slower lookup. We are still guaranteed that
|
| - // the object has a simple shape, and that the key is a name.
|
| - LookupIterator it(from, next_key, from,
|
| - LookupIterator::OWN_SKIP_INTERCEPTOR);
|
| - if (!it.IsFound()) continue;
|
| - DCHECK(it.state() == LookupIterator::DATA ||
|
| - it.state() == LookupIterator::ACCESSOR);
|
| - if (!it.IsEnumerable()) continue;
|
| - ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
| - isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
|
| - }
|
| - LookupIterator it(to, next_key, to);
|
| - bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
|
| - Maybe<bool> result = Object::SetProperty(
|
| - &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
|
| - if (result.IsNothing()) return result;
|
| - if (stable && call_to_js) stable = from->map() == *map;
|
| - }
|
| -
|
| - return Just(true);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| // ES6 19.1.2.1 Object.assign
|
| BUILTIN(ObjectAssign) {
|
| HandleScope scope(isolate);
|
| @@ -163,43 +82,9 @@ BUILTIN(ObjectAssign) {
|
| // 4. For each element nextSource of sources, in ascending index order,
|
| for (int i = 2; i < args.length(); ++i) {
|
| Handle<Object> next_source = args.at(i);
|
| - Maybe<bool> fast_assign = FastAssign(to, next_source);
|
| - if (fast_assign.IsNothing()) return isolate->heap()->exception();
|
| - if (fast_assign.FromJust()) continue;
|
| - // 4a. If nextSource is undefined or null, let keys be an empty List.
|
| - // 4b. Else,
|
| - // 4b i. Let from be ToObject(nextSource).
|
| - // Only non-empty strings and JSReceivers have enumerable properties.
|
| - Handle<JSReceiver> from =
|
| - Object::ToObject(isolate, next_source).ToHandleChecked();
|
| - // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
|
| - Handle<FixedArray> keys;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, keys, KeyAccumulator::GetKeys(
|
| - from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
|
| - GetKeysConversion::kKeepNumbers));
|
| - // 4c. Repeat for each element nextKey of keys in List order,
|
| - for (int j = 0; j < keys->length(); ++j) {
|
| - Handle<Object> next_key(keys->get(j), isolate);
|
| - // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
|
| - PropertyDescriptor desc;
|
| - Maybe<bool> found =
|
| - JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
|
| - if (found.IsNothing()) return isolate->heap()->exception();
|
| - // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
|
| - if (found.FromJust() && desc.enumerable()) {
|
| - // 4c ii 1. Let propValue be ? Get(from, nextKey).
|
| - Handle<Object> prop_value;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, prop_value,
|
| - Runtime::GetObjectProperty(isolate, from, next_key));
|
| - // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
|
| - Handle<Object> status;
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| - isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
|
| - prop_value, STRICT));
|
| - }
|
| - }
|
| + MAYBE_RETURN(
|
| + JSReceiver::SetOrCopyDataProperties(isolate, to, next_source, true),
|
| + isolate->heap()->exception());
|
| }
|
| // 5. Return to.
|
| return *to;
|
|
|