LCOV - code coverage report
Current view: top level - src/runtime - runtime-forin.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 40 46 87.0 %
Date: 2019-04-17 Functions: 5 7 71.4 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/runtime/runtime-utils.h"
       6             : 
       7             : #include "src/arguments-inl.h"
       8             : #include "src/counters.h"
       9             : #include "src/elements.h"
      10             : #include "src/heap/factory.h"
      11             : #include "src/heap/heap-inl.h"  // For ToBoolean. TODO(jkummerow): Drop.
      12             : #include "src/isolate-inl.h"
      13             : #include "src/keys.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/module.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : 
      20             : namespace {
      21             : 
      22             : // Returns either a FixedArray or, if the given {receiver} has an enum cache
      23             : // that contains all enumerable properties of the {receiver} and its prototypes
      24             : // have none, the map of the {receiver}. This is used to speed up the check for
      25             : // deletions during a for-in.
      26       54443 : MaybeHandle<HeapObject> Enumerate(Isolate* isolate,
      27             :                                   Handle<JSReceiver> receiver) {
      28       54443 :   JSObject::MakePrototypesFast(receiver, kStartAtReceiver, isolate);
      29             :   FastKeyAccumulator accumulator(isolate, receiver,
      30             :                                  KeyCollectionMode::kIncludePrototypes,
      31             :                                  ENUMERABLE_STRINGS, true);
      32             :   // Test if we have an enum cache for {receiver}.
      33       54443 :   if (!accumulator.is_receiver_simple_enum()) {
      34             :     Handle<FixedArray> keys;
      35      103188 :     ASSIGN_RETURN_ON_EXCEPTION(
      36             :         isolate, keys, accumulator.GetKeys(GetKeysConversion::kConvertToString),
      37             :         HeapObject);
      38             :     // Test again, since cache may have been built by GetKeys() calls above.
      39       51468 :     if (!accumulator.is_receiver_simple_enum()) return keys;
      40             :   }
      41             :   DCHECK(!receiver->IsJSModuleNamespace());
      42        7755 :   return handle(receiver->map(), isolate);
      43             : }
      44             : 
      45             : // This is a slight modifcation of JSReceiver::HasProperty, dealing with
      46             : // the oddities of JSProxy and JSModuleNamespace in for-in filter.
      47      246045 : MaybeHandle<Object> HasEnumerableProperty(Isolate* isolate,
      48             :                                           Handle<JSReceiver> receiver,
      49             :                                           Handle<Object> key) {
      50      246045 :   bool success = false;
      51             :   Maybe<PropertyAttributes> result = Just(ABSENT);
      52             :   LookupIterator it =
      53      246045 :       LookupIterator::PropertyOrElement(isolate, receiver, key, &success);
      54      246045 :   if (!success) return isolate->factory()->undefined_value();
      55      733853 :   for (; it.IsFound(); it.Next()) {
      56      489931 :     switch (it.state()) {
      57             :       case LookupIterator::NOT_FOUND:
      58             :       case LookupIterator::TRANSITION:
      59           0 :         UNREACHABLE();
      60             :       case LookupIterator::JSPROXY: {
      61             :         // For proxies we have to invoke the [[GetOwnProperty]] trap.
      62        1197 :         result = JSProxy::GetPropertyAttributes(&it);
      63        1197 :         if (result.IsNothing()) return MaybeHandle<Object>();
      64        1170 :         if (result.FromJust() == ABSENT) {
      65             :           // Continue lookup on the proxy's prototype.
      66          81 :           Handle<JSProxy> proxy = it.GetHolder<JSProxy>();
      67             :           Handle<Object> prototype;
      68         162 :           ASSIGN_RETURN_ON_EXCEPTION(isolate, prototype,
      69             :                                      JSProxy::GetPrototype(proxy), Object);
      70          81 :           if (prototype->IsNull(isolate)) {
      71           9 :             return isolate->factory()->undefined_value();
      72             :           }
      73             :           // We already have a stack-check in JSProxy::GetPrototype.
      74             :           return HasEnumerableProperty(
      75          72 :               isolate, Handle<JSReceiver>::cast(prototype), key);
      76        1089 :         } else if (result.FromJust() & DONT_ENUM) {
      77         189 :           return isolate->factory()->undefined_value();
      78             :         } else {
      79         900 :           return it.GetName();
      80             :         }
      81             :       }
      82             :       case LookupIterator::INTERCEPTOR: {
      83      240249 :         result = JSObject::GetPropertyAttributesWithInterceptor(&it);
      84      240249 :         if (result.IsNothing()) return MaybeHandle<Object>();
      85      240249 :         if (result.FromJust() != ABSENT) return it.GetName();
      86             :         continue;
      87             :       }
      88             :       case LookupIterator::ACCESS_CHECK: {
      89        3870 :         if (it.HasAccess()) continue;
      90           0 :         result = JSObject::GetPropertyAttributesWithFailedAccessCheck(&it);
      91           0 :         if (result.IsNothing()) return MaybeHandle<Object>();
      92           0 :         if (result.FromJust() != ABSENT) return it.GetName();
      93           0 :         return isolate->factory()->undefined_value();
      94             :       }
      95             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
      96             :         // TypedArray out-of-bounds access.
      97           0 :         return isolate->factory()->undefined_value();
      98             :       case LookupIterator::ACCESSOR: {
      99          63 :         if (it.GetHolder<Object>()->IsJSModuleNamespace()) {
     100          45 :           result = JSModuleNamespace::GetPropertyAttributes(&it);
     101          45 :           if (result.IsNothing()) return MaybeHandle<Object>();
     102             :           DCHECK_EQ(0, result.FromJust() & DONT_ENUM);
     103             :         }
     104          63 :         return it.GetName();
     105             :       }
     106             :       case LookupIterator::DATA:
     107      244552 :         return it.GetName();
     108             :     }
     109             :   }
     110          18 :   return isolate->factory()->undefined_value();
     111             : }
     112             : 
     113             : }  // namespace
     114             : 
     115             : 
     116      108886 : RUNTIME_FUNCTION(Runtime_ForInEnumerate) {
     117             :   HandleScope scope(isolate);
     118             :   DCHECK_EQ(1, args.length());
     119       54443 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
     120      108886 :   RETURN_RESULT_OR_FAILURE(isolate, Enumerate(isolate, receiver));
     121             : }
     122             : 
     123             : 
     124      491946 : RUNTIME_FUNCTION(Runtime_ForInHasProperty) {
     125             :   HandleScope scope(isolate);
     126             :   DCHECK_EQ(2, args.length());
     127      245973 :   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
     128             :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
     129             :   Handle<Object> result;
     130      491946 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
     131             :       isolate, result, HasEnumerableProperty(isolate, receiver, key));
     132             :   return isolate->heap()->ToBoolean(!result->IsUndefined(isolate));
     133             : }
     134             : 
     135             : }  // namespace internal
     136      121996 : }  // namespace v8

Generated by: LCOV version 1.10