Chromium Code Reviews| Index: src/runtime/runtime-forin.cc |
| diff --git a/src/runtime/runtime-forin.cc b/src/runtime/runtime-forin.cc |
| index 6374cb97e5a8a92ad37b0b671059363274ac3c1e..4b558d124f5db765d3c51d9b7a20ee934019224f 100644 |
| --- a/src/runtime/runtime-forin.cc |
| +++ b/src/runtime/runtime-forin.cc |
| @@ -24,6 +24,7 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) { |
| Isolate* const isolate = receiver->GetIsolate(); |
| FastKeyAccumulator accumulator(isolate, receiver, INCLUDE_PROTOS, |
| ENUMERABLE_STRINGS); |
| + accumulator.set_filter_proxy_keys(false); |
| // Test if we have an enum cache for {receiver}. |
| if (!accumulator.is_receiver_simple_enum()) { |
| Handle<FixedArray> keys; |
| @@ -35,28 +36,70 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) { |
| return handle(receiver->map(), isolate); |
| } |
| - |
| -MaybeHandle<Object> Filter(Handle<JSReceiver> receiver, Handle<Object> key) { |
| - Isolate* const isolate = receiver->GetIsolate(); |
| - Handle<Name> name; |
| - ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key), |
| - Object); |
| - // Directly check for elements if the key is a smi and avoid a conversion |
| - // roundtrip (Number -> Name -> Number). |
| - if (key->IsNumber() && receiver->map()->OnlyHasSimpleProperties()) { |
| - Handle<JSObject> object = Handle<JSObject>::cast(receiver); |
| - ElementsAccessor* accessor = object->GetElementsAccessor(); |
| - DCHECK_LT(key->Number(), kMaxUInt32); |
| - if (accessor->HasElement(object, key->Number(), ONLY_ENUMERABLE)) { |
| - return name; |
| +// This is a slight modifcation of JSReceiver::HasProperty, dealing with |
|
Jakob Kummerow
2016/03/18 14:12:00
nit: missng 'i' ;-)
Camillo Bruni
2016/03/18 17:46:34
shorter is better, no ;)
|
| +// the oddities of JSProxy in for-in filter. |
| +MaybeHandle<Object> HasEnumerableProperty(Isolate* isolate, |
| + Handle<JSReceiver> receiver, |
| + Handle<Object> key) { |
| + bool success = false; |
| + Maybe<PropertyAttributes> result = Just(ABSENT); |
| + LookupIterator it = |
| + LookupIterator::PropertyOrElement(isolate, receiver, key, &success); |
| + if (!success) return isolate->factory()->undefined_value(); |
| + for (; it.IsFound(); it.Next()) { |
| + switch (it.state()) { |
| + case LookupIterator::NOT_FOUND: |
| + case LookupIterator::TRANSITION: |
| + UNREACHABLE(); |
| + case LookupIterator::JSPROXY: { |
| + // For proxies we have to invoke the [[GetOwnProperty]] trap. |
| + result = JSProxy::GetPropertyAttributes(&it); |
| + if (result.IsNothing()) return MaybeHandle<Object>(); |
| + if (result.FromJust() == ABSENT) { |
| + // Continue lookup on the proxy's prototype. |
| + Handle<JSProxy> proxy = it.GetHolder<JSProxy>(); |
| + Handle<Object> prototype; |
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, prototype, |
| + JSProxy::GetPrototype(proxy), Object); |
| + if (prototype->IsNull()) break; |
| + // We already have a stack-check in JSProxy::GetPrototype. |
| + return HasEnumerableProperty( |
| + isolate, Handle<JSReceiver>::cast(prototype), key); |
| + } else if (result.FromJust() & DONT_ENUM) { |
| + return isolate->factory()->undefined_value(); |
| + } else { |
| + return it.GetName(); |
| + } |
| + } |
| + case LookupIterator::INTERCEPTOR: { |
| + result = JSObject::GetPropertyAttributesWithInterceptor(&it); |
| + if (result.IsNothing()) return MaybeHandle<Object>(); |
| + if (result.FromJust() != ABSENT) return it.GetName(); |
| + continue; |
| + } |
| + case LookupIterator::ACCESS_CHECK: { |
| + if (it.HasAccess()) continue; |
| + result = JSObject::GetPropertyAttributesWithFailedAccessCheck(&it); |
| + if (result.IsNothing()) return MaybeHandle<Object>(); |
| + if (result.FromJust() != ABSENT) return it.GetName(); |
| + return isolate->factory()->undefined_value(); |
| + } |
| + case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| + // TypedArray out-of-bounds access. |
| + return isolate->factory()->undefined_value(); |
| + case LookupIterator::ACCESSOR: |
| + case LookupIterator::DATA: |
| + return it.GetName(); |
| } |
| } |
| - Maybe<bool> result = JSReceiver::HasProperty(receiver, name); |
| - MAYBE_RETURN_NULL(result); |
| - if (result.FromJust()) return name; |
| return isolate->factory()->undefined_value(); |
| } |
| +MaybeHandle<Object> Filter(Handle<JSReceiver> receiver, Handle<Object> key) { |
| + Isolate* const isolate = receiver->GetIsolate(); |
| + return HasEnumerableProperty(isolate, receiver, key); |
| +} |
| + |
| } // namespace |