v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-forin.cc
Go to the documentation of this file.
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
6#include "src/heap/factory.h"
7#include "src/heap/heap-inl.h" // For ToBoolean. TODO(jkummerow): Drop.
8#include "src/objects/keys.h"
11
12namespace v8 {
13namespace internal {
14
15namespace {
16
17// Returns either a FixedArray or, if the given {receiver} has an enum cache
18// that contains all enumerable properties of the {receiver} and its prototypes
19// have none, the map of the {receiver}. This is used to speed up the check for
20// deletions during a for-in.
21MaybeDirectHandle<HeapObject> Enumerate(Isolate* isolate,
22 DirectHandle<JSReceiver> receiver) {
24 FastKeyAccumulator accumulator(isolate, receiver,
26 ENUMERABLE_STRINGS, true);
27 // Test if we have an enum cache for {receiver}.
28 if (!accumulator.is_receiver_simple_enum()) {
29 DirectHandle<FixedArray> keys;
31 isolate, keys,
32 accumulator.GetKeys(accumulator.may_have_elements()
35 // Test again, since cache may have been built by GetKeys() calls above.
36 if (!accumulator.is_receiver_simple_enum()) return keys;
37 }
38 DCHECK(!IsJSModuleNamespace(*receiver));
39 return direct_handle(receiver->map(), isolate);
40}
41
42// This is a slight modification of JSReceiver::HasProperty, dealing with
43// the oddities of JSProxy and JSModuleNamespace in for-in filter.
44MaybeDirectHandle<Object> HasEnumerableProperty(
45 Isolate* isolate, DirectHandle<JSReceiver> receiver,
46 DirectHandle<Object> key) {
47 bool success = false;
48 Maybe<PropertyAttributes> result = Just(ABSENT);
49 PropertyKey lookup_key(isolate, key, &success);
50 if (!success) return isolate->factory()->undefined_value();
51 LookupIterator it(isolate, receiver, lookup_key);
52 for (;; it.Next()) {
53 switch (it.state()) {
57 // For proxies we have to invoke the [[GetOwnProperty]] trap.
59 if (result.IsNothing()) return MaybeDirectHandle<Object>();
60 if (result.FromJust() == ABSENT) {
61 // Continue lookup on the proxy's prototype.
62 DirectHandle<JSProxy> proxy = it.GetHolder<JSProxy>();
63 DirectHandle<Object> prototype;
64 ASSIGN_RETURN_ON_EXCEPTION(isolate, prototype,
66 if (IsNull(*prototype, isolate)) {
67 return isolate->factory()->undefined_value();
68 }
69 // We already have a stack-check in JSProxy::GetPrototype.
70 return HasEnumerableProperty(isolate, Cast<JSReceiver>(prototype),
71 key);
72 } else if (result.FromJust() & DONT_ENUM) {
73 return isolate->factory()->undefined_value();
74 } else {
75 return it.GetName();
76 }
77 }
79 continue; // Continue to the prototype, if present.
82 if (result.IsNothing()) return MaybeDirectHandle<Object>();
83 if (result.FromJust() != ABSENT) return it.GetName();
84 continue;
85 }
87 if (it.HasAccess()) continue;
89 if (result.IsNothing()) return MaybeDirectHandle<Object>();
90 if (result.FromJust() != ABSENT) return it.GetName();
91 return isolate->factory()->undefined_value();
92 }
94 // TypedArray out-of-bounds access.
95 return isolate->factory()->undefined_value();
97 if (IsJSModuleNamespace(*it.GetHolder<Object>())) {
99 if (result.IsNothing()) return MaybeDirectHandle<Object>();
100 DCHECK_EQ(0, result.FromJust() & DONT_ENUM);
101 }
102 return it.GetName();
103 }
105 return it.GetName();
107 return isolate->factory()->undefined_value();
108 }
109 UNREACHABLE();
110 }
111}
112
113} // namespace
114
115
116RUNTIME_FUNCTION(Runtime_ForInEnumerate) {
117 HandleScope scope(isolate);
118 DCHECK_EQ(1, args.length());
120 RETURN_RESULT_OR_FAILURE(isolate, Enumerate(isolate, receiver));
121}
122
123
124RUNTIME_FUNCTION(Runtime_ForInHasProperty) {
125 HandleScope scope(isolate);
126 DCHECK_EQ(2, args.length());
131 isolate, result, HasEnumerableProperty(isolate, receiver, key));
132 return isolate->heap()->ToBoolean(!IsUndefined(*result, isolate));
133}
134
135} // namespace internal
136} // namespace v8
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(LookupIterator *it)
Definition module.cc:428
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithInterceptor(LookupIterator *it)
static void MakePrototypesFast(DirectHandle< Object > receiver, WhereToStart where_to_start, Isolate *isolate)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributesWithFailedAccessCheck(LookupIterator *it)
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetPropertyAttributes(LookupIterator *it)
Definition objects.cc:3096
static MaybeDirectHandle< JSPrototype > GetPrototype(DirectHandle< JSProxy > receiver)
Definition objects.cc:1456
#define RUNTIME_FUNCTION(Name)
Definition arguments.h:162
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:291
#define RETURN_RESULT_OR_FAILURE(isolate, call)
Definition isolate.h:264
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Object > receiver
ZoneVector< RpoNumber > & result
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485