| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index ea3649198e1e77b8e1adbfdb4c10f2e000329816..cb47e5766d182758868db7e37ffa2604cb274349 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -116,17 +116,6 @@
|
| return result;
|
| }
|
|
|
| -// ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
|
| -// static
|
| -MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
|
| - Handle<Object> object) {
|
| - if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
|
| - if (*object == isolate->heap()->null_value() ||
|
| - *object == isolate->heap()->undefined_value()) {
|
| - return isolate->global_proxy();
|
| - }
|
| - return Object::ToObject(isolate, object);
|
| -}
|
|
|
| // static
|
| MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
|
| @@ -6146,9 +6135,7 @@
|
|
|
|
|
| // ES6 7.1.14
|
| -// static
|
| -MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
|
| - Handle<Object> value) {
|
| +MaybeHandle<Object> ToPropertyKey(Isolate* isolate, Handle<Object> value) {
|
| // 1. Let key be ToPrimitive(argument, hint String).
|
| MaybeHandle<Object> maybe_key =
|
| Object::ToPrimitive(value, ToPrimitiveHint::kString);
|
| @@ -8931,6 +8918,53 @@
|
|
|
| return object;
|
| }
|
| +
|
| +
|
| +MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
|
| + Handle<Name> name,
|
| + AccessorComponent component) {
|
| + Isolate* isolate = object->GetIsolate();
|
| +
|
| + // Make sure that the top context does not change when doing callbacks or
|
| + // interceptor calls.
|
| + AssertNoContextChange ncc(isolate);
|
| +
|
| + LookupIterator it = LookupIterator::PropertyOrElement(
|
| + isolate, object, name, LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
|
| +
|
| + for (; it.IsFound(); it.Next()) {
|
| + switch (it.state()) {
|
| + case LookupIterator::INTERCEPTOR:
|
| + case LookupIterator::NOT_FOUND:
|
| + case LookupIterator::TRANSITION:
|
| + UNREACHABLE();
|
| +
|
| + case LookupIterator::ACCESS_CHECK:
|
| + if (it.HasAccess()) continue;
|
| + isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
|
| + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return isolate->factory()->undefined_value();
|
| +
|
| + case LookupIterator::JSPROXY:
|
| + return isolate->factory()->undefined_value();
|
| +
|
| + case LookupIterator::INTEGER_INDEXED_EXOTIC:
|
| + return isolate->factory()->undefined_value();
|
| + case LookupIterator::DATA:
|
| + continue;
|
| + case LookupIterator::ACCESSOR: {
|
| + Handle<Object> maybe_pair = it.GetAccessors();
|
| + if (maybe_pair->IsAccessorPair()) {
|
| + return AccessorPair::GetComponent(
|
| + Handle<AccessorPair>::cast(maybe_pair), component);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return isolate->factory()->undefined_value();
|
| +}
|
| +
|
|
|
| Object* JSObject::SlowReverseLookup(Object* value) {
|
| if (HasFastProperties()) {
|
| @@ -15748,12 +15782,159 @@
|
| return is_api_object;
|
| }
|
|
|
| +int JSObject::NumberOfOwnElements(PropertyFilter filter) {
|
| + // Fast case for objects with no elements.
|
| + if (!IsJSValue() && HasFastElements()) {
|
| + uint32_t length =
|
| + IsJSArray()
|
| + ? static_cast<uint32_t>(
|
| + Smi::cast(JSArray::cast(this)->length())->value())
|
| + : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length());
|
| + if (length == 0) return 0;
|
| + }
|
| + // Compute the number of enumerable elements.
|
| + return GetOwnElementKeys(NULL, filter);
|
| +}
|
| +
|
| void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
|
| KeyAccumulator* keys,
|
| PropertyFilter filter) {
|
| if (filter & SKIP_STRINGS) return;
|
| ElementsAccessor* accessor = object->GetElementsAccessor();
|
| accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
|
| +}
|
| +
|
| +
|
| +int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
|
| + int counter = 0;
|
| +
|
| + // If this is a String wrapper, add the string indices first,
|
| + // as they're guaranteed to precede the elements in numerical order
|
| + // and ascending order is required by ECMA-262, 6th, 9.1.12.
|
| + if (IsJSValue()) {
|
| + Object* val = JSValue::cast(this)->value();
|
| + if (val->IsString()) {
|
| + String* str = String::cast(val);
|
| + if (storage) {
|
| + for (int i = 0; i < str->length(); i++) {
|
| + storage->set(counter + i, Smi::FromInt(i));
|
| + }
|
| + }
|
| + counter += str->length();
|
| + }
|
| + }
|
| +
|
| + switch (GetElementsKind()) {
|
| + case FAST_SMI_ELEMENTS:
|
| + case FAST_ELEMENTS:
|
| + case FAST_HOLEY_SMI_ELEMENTS:
|
| + case FAST_HOLEY_ELEMENTS:
|
| + case FAST_STRING_WRAPPER_ELEMENTS: {
|
| + int length = IsJSArray() ?
|
| + Smi::cast(JSArray::cast(this)->length())->value() :
|
| + FixedArray::cast(elements())->length();
|
| + for (int i = 0; i < length; i++) {
|
| + if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
|
| + if (storage != NULL) {
|
| + storage->set(counter, Smi::FromInt(i));
|
| + }
|
| + counter++;
|
| + }
|
| + }
|
| + DCHECK(!storage || storage->length() >= counter);
|
| + break;
|
| + }
|
| + case FAST_DOUBLE_ELEMENTS:
|
| + case FAST_HOLEY_DOUBLE_ELEMENTS: {
|
| + int length = IsJSArray() ?
|
| + Smi::cast(JSArray::cast(this)->length())->value() :
|
| + FixedArrayBase::cast(elements())->length();
|
| + for (int i = 0; i < length; i++) {
|
| + if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
|
| + if (storage != NULL) {
|
| + storage->set(counter, Smi::FromInt(i));
|
| + }
|
| + counter++;
|
| + }
|
| + }
|
| + DCHECK(!storage || storage->length() >= counter);
|
| + break;
|
| + }
|
| +
|
| +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| + case TYPE##_ELEMENTS: \
|
| +
|
| + TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| +#undef TYPED_ARRAY_CASE
|
| + {
|
| + int length = FixedArrayBase::cast(elements())->length();
|
| + while (counter < length) {
|
| + if (storage != NULL) {
|
| + storage->set(counter, Smi::FromInt(counter));
|
| + }
|
| + counter++;
|
| + }
|
| + DCHECK(!storage || storage->length() >= counter);
|
| + break;
|
| + }
|
| +
|
| + case DICTIONARY_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS: {
|
| + if (storage != NULL) {
|
| + element_dictionary()->CopyKeysTo(storage, counter, filter,
|
| + SeededNumberDictionary::SORTED);
|
| + }
|
| + counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
|
| + break;
|
| + }
|
| + case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
| + case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
|
| + FixedArray* parameter_map = FixedArray::cast(elements());
|
| + int mapped_length = parameter_map->length() - 2;
|
| + FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| + if (arguments->IsDictionary()) {
|
| + // Copy the keys from arguments first, because Dictionary::CopyKeysTo
|
| + // will insert in storage starting at index 0.
|
| + SeededNumberDictionary* dictionary =
|
| + SeededNumberDictionary::cast(arguments);
|
| + if (storage != NULL) {
|
| + dictionary->CopyKeysTo(storage, counter, filter,
|
| + SeededNumberDictionary::UNSORTED);
|
| + }
|
| + counter += dictionary->NumberOfElementsFilterAttributes(filter);
|
| + for (int i = 0; i < mapped_length; ++i) {
|
| + if (!parameter_map->get(i + 2)->IsTheHole()) {
|
| + if (storage != NULL) storage->set(counter, Smi::FromInt(i));
|
| + ++counter;
|
| + }
|
| + }
|
| + if (storage != NULL) storage->SortPairs(storage, counter);
|
| +
|
| + } else {
|
| + int backing_length = arguments->length();
|
| + int i = 0;
|
| + for (; i < mapped_length; ++i) {
|
| + if (!parameter_map->get(i + 2)->IsTheHole()) {
|
| + if (storage != NULL) storage->set(counter, Smi::FromInt(i));
|
| + ++counter;
|
| + } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
|
| + if (storage != NULL) storage->set(counter, Smi::FromInt(i));
|
| + ++counter;
|
| + }
|
| + }
|
| + for (; i < backing_length; ++i) {
|
| + if (storage != NULL) storage->set(counter, Smi::FromInt(i));
|
| + ++counter;
|
| + }
|
| + }
|
| + break;
|
| + }
|
| + case NO_ELEMENTS:
|
| + break;
|
| + }
|
| +
|
| + DCHECK(!storage || storage->length() == counter);
|
| + return counter;
|
| }
|
|
|
|
|
| @@ -17600,6 +17781,30 @@
|
| }
|
| }
|
|
|
| +
|
| +template <typename Derived, typename Shape, typename Key>
|
| +int Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
| + FixedArray* storage, int index, PropertyFilter filter,
|
| + typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) {
|
| + DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter));
|
| + int start_index = index;
|
| + int capacity = this->Capacity();
|
| + for (int i = 0; i < capacity; i++) {
|
| + Object* k = this->KeyAt(i);
|
| + if (!this->IsKey(k) || k->FilterKey(filter)) continue;
|
| + if (this->IsDeleted(i)) continue;
|
| + PropertyDetails details = this->DetailsAt(i);
|
| + PropertyAttributes attr = details.attributes();
|
| + if ((attr & filter) != 0) continue;
|
| + storage->set(index++, k);
|
| + }
|
| + if (sort_mode == Dictionary::SORTED) {
|
| + storage->SortPairs(storage, index);
|
| + }
|
| + DCHECK(storage->length() >= index);
|
| + return index - start_index;
|
| +}
|
| +
|
| template <typename Derived, typename Shape, typename Key>
|
| void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
| Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
|
|
|