V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
prototype-inl.h
1 // Copyright 2018 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 #ifndef V8_PROTOTYPE_INL_H_
6 #define V8_PROTOTYPE_INL_H_
7 
8 #include "src/prototype.h"
9 
10 #include "src/handles-inl.h"
11 #include "src/objects/map-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 PrototypeIterator::PrototypeIterator(Isolate* isolate,
17  Handle<JSReceiver> receiver,
18  WhereToStart where_to_start,
19  WhereToEnd where_to_end)
20  : isolate_(isolate),
21  object_(nullptr),
22  handle_(receiver),
23  where_to_end_(where_to_end),
24  is_at_end_(false),
25  seen_proxies_(0) {
26  CHECK(!handle_.is_null());
27  if (where_to_start == kStartAtPrototype) Advance();
28 }
29 
30 PrototypeIterator::PrototypeIterator(Isolate* isolate, JSReceiver* receiver,
31  WhereToStart where_to_start,
32  WhereToEnd where_to_end)
33  : isolate_(isolate),
34  object_(receiver),
35  where_to_end_(where_to_end),
36  is_at_end_(false),
37  seen_proxies_(0) {
38  if (where_to_start == kStartAtPrototype) Advance();
39 }
40 
41 PrototypeIterator::PrototypeIterator(Isolate* isolate, Map receiver_map,
42  WhereToEnd where_to_end)
43  : isolate_(isolate),
44  object_(receiver_map->GetPrototypeChainRootMap(isolate_)->prototype()),
45  where_to_end_(where_to_end),
46  is_at_end_(object_->IsNull(isolate_)),
47  seen_proxies_(0) {
48  if (!is_at_end_ && where_to_end_ == END_AT_NON_HIDDEN) {
49  DCHECK(object_->IsJSReceiver());
50  Map map = JSReceiver::cast(object_)->map();
51  is_at_end_ = !map->has_hidden_prototype();
52  }
53 }
54 
55 PrototypeIterator::PrototypeIterator(Isolate* isolate, Handle<Map> receiver_map,
56  WhereToEnd where_to_end)
57  : isolate_(isolate),
58  object_(nullptr),
59  handle_(receiver_map->GetPrototypeChainRootMap(isolate_)->prototype(),
60  isolate_),
61  where_to_end_(where_to_end),
62  is_at_end_(handle_->IsNull(isolate_)),
63  seen_proxies_(0) {
64  if (!is_at_end_ && where_to_end_ == END_AT_NON_HIDDEN) {
65  DCHECK(handle_->IsJSReceiver());
66  Map map = JSReceiver::cast(*handle_)->map();
67  is_at_end_ = !map->has_hidden_prototype();
68  }
69 }
70 
71 bool PrototypeIterator::HasAccess() const {
72  // We can only perform access check in the handlified version of the
73  // PrototypeIterator.
74  DCHECK(!handle_.is_null());
75  if (handle_->IsAccessCheckNeeded()) {
76  return isolate_->MayAccess(handle(isolate_->context(), isolate_),
77  Handle<JSObject>::cast(handle_));
78  }
79  return true;
80 }
81 
82 void PrototypeIterator::Advance() {
83  if (handle_.is_null() && object_->IsJSProxy()) {
84  is_at_end_ = true;
85  object_ = ReadOnlyRoots(isolate_).null_value();
86  return;
87  } else if (!handle_.is_null() && handle_->IsJSProxy()) {
88  is_at_end_ = true;
89  handle_ = isolate_->factory()->null_value();
90  return;
91  }
92  AdvanceIgnoringProxies();
93 }
94 
95 void PrototypeIterator::AdvanceIgnoringProxies() {
96  Object* object = handle_.is_null() ? object_ : *handle_;
97  Map map = HeapObject::cast(object)->map();
98 
99  Object* prototype = map->prototype();
100  is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN ? !map->has_hidden_prototype()
101  : prototype->IsNull(isolate_);
102 
103  if (handle_.is_null()) {
104  object_ = prototype;
105  } else {
106  handle_ = handle(prototype, isolate_);
107  }
108 }
109 
110 V8_WARN_UNUSED_RESULT bool PrototypeIterator::AdvanceFollowingProxies() {
111  DCHECK(!(handle_.is_null() && object_->IsJSProxy()));
112  if (!HasAccess()) {
113  // Abort the lookup if we do not have access to the current object.
114  handle_ = isolate_->factory()->null_value();
115  is_at_end_ = true;
116  return true;
117  }
118  return AdvanceFollowingProxiesIgnoringAccessChecks();
119 }
120 
121 V8_WARN_UNUSED_RESULT bool
122 PrototypeIterator::AdvanceFollowingProxiesIgnoringAccessChecks() {
123  if (handle_.is_null() || !handle_->IsJSProxy()) {
124  AdvanceIgnoringProxies();
125  return true;
126  }
127 
128  // Due to possible __proto__ recursion limit the number of Proxies
129  // we visit to an arbitrarily chosen large number.
130  seen_proxies_++;
131  if (seen_proxies_ > JSProxy::kMaxIterationLimit) {
132  isolate_->StackOverflow();
133  return false;
134  }
135  MaybeHandle<Object> proto =
136  JSProxy::GetPrototype(Handle<JSProxy>::cast(handle_));
137  if (!proto.ToHandle(&handle_)) return false;
138  is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN || handle_->IsNull(isolate_);
139  return true;
140 }
141 
142 } // namespace internal
143 } // namespace v8
144 
145 #endif // V8_PROTOTYPE_INL_H_
Definition: libplatform.h:13