1 // Copyright 2014 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.
5 #ifndef V8_PROTOTYPE_H_
6 #define V8_PROTOTYPE_H_
8 #include "src/isolate.h"
9 #include "src/objects.h"
15 * A class to uniformly access the prototype of any Object and walk its
18 * The PrototypeIterator can either start at the prototype (default), or
19 * include the receiver itself. If a PrototypeIterator is constructed for a
20 * Map, it will always start at the prototype.
22 * The PrototypeIterator can either run to the null_value(), the first
23 * non-hidden prototype, or a given object.
25 class PrototypeIterator {
27 enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE };
29 enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN };
31 PrototypeIterator(Isolate* isolate, Handle<Object> receiver,
32 WhereToStart where_to_start = START_AT_PROTOTYPE)
33 : did_jump_to_prototype_chain_(false),
37 CHECK(!handle_.is_null());
38 if (where_to_start == START_AT_PROTOTYPE) {
42 PrototypeIterator(Isolate* isolate, Object* receiver,
43 WhereToStart where_to_start = START_AT_PROTOTYPE)
44 : did_jump_to_prototype_chain_(false),
47 if (where_to_start == START_AT_PROTOTYPE) {
51 explicit PrototypeIterator(Map* receiver_map)
52 : did_jump_to_prototype_chain_(true),
53 object_(receiver_map->prototype()),
54 isolate_(receiver_map->GetIsolate()) {}
55 explicit PrototypeIterator(Handle<Map> receiver_map)
56 : did_jump_to_prototype_chain_(true),
58 handle_(handle(receiver_map->prototype(), receiver_map->GetIsolate())),
59 isolate_(receiver_map->GetIsolate()) {}
60 ~PrototypeIterator() {}
62 Object* GetCurrent() const {
63 DCHECK(handle_.is_null());
66 static Handle<Object> GetCurrent(const PrototypeIterator& iterator) {
67 DCHECK(!iterator.handle_.is_null());
68 return iterator.handle_;
71 if (handle_.is_null() && object_->IsJSProxy()) {
72 did_jump_to_prototype_chain_ = true;
73 object_ = isolate_->heap()->null_value();
75 } else if (!handle_.is_null() && handle_->IsJSProxy()) {
76 did_jump_to_prototype_chain_ = true;
77 handle_ = handle(isolate_->heap()->null_value(), isolate_);
80 AdvanceIgnoringProxies();
82 void AdvanceIgnoringProxies() {
83 if (!did_jump_to_prototype_chain_) {
84 did_jump_to_prototype_chain_ = true;
85 if (handle_.is_null()) {
86 object_ = object_->GetRootMap(isolate_)->prototype();
88 handle_ = handle(handle_->GetRootMap(isolate_)->prototype(), isolate_);
91 if (handle_.is_null()) {
92 object_ = HeapObject::cast(object_)->map()->prototype();
95 handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_);
99 bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const {
100 if (handle_.is_null()) {
101 return object_->IsNull() ||
102 (did_jump_to_prototype_chain_ &&
103 where_to_end == END_AT_NON_HIDDEN &&
104 !HeapObject::cast(object_)->map()->is_hidden_prototype());
106 return handle_->IsNull() ||
107 (did_jump_to_prototype_chain_ &&
108 where_to_end == END_AT_NON_HIDDEN &&
109 !Handle<HeapObject>::cast(handle_)->map()->is_hidden_prototype());
112 bool IsAtEnd(Object* final_object) {
113 DCHECK(handle_.is_null());
114 return object_->IsNull() || object_ == final_object;
116 bool IsAtEnd(Handle<Object> final_object) {
117 DCHECK(!handle_.is_null());
118 return handle_->IsNull() || *handle_ == *final_object;
122 bool did_jump_to_prototype_chain_;
124 Handle<Object> handle_;
127 DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
131 } // namespace internal
135 #endif // V8_PROTOTYPE_H_