| 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
|
| +// 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
|
|
|
|
|
|
|