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. |
4 | |
5 | #ifndef V8_PROTOTYPE_H_ |
6 | #define V8_PROTOTYPE_H_ |
7 | |
8 | #include "src/isolate.h" |
9 | #include "src/objects.h" |
10 | |
11 | namespace v8 { |
12 | namespace internal { |
13 | |
14 | /** |
15 | * A class to uniformly access the prototype of any Object and walk its |
16 | * prototype chain. |
17 | * |
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. |
21 | * |
22 | * The PrototypeIterator can either run to the null_value(), the first |
23 | * non-hidden prototype, or a given object. |
24 | */ |
25 | |
26 | class PrototypeIterator { |
27 | public: |
28 | enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN }; |
29 | |
30 | inline PrototypeIterator(Isolate* isolate, Handle<JSReceiver> receiver, |
31 | WhereToStart where_to_start = kStartAtPrototype, |
32 | WhereToEnd where_to_end = END_AT_NULL); |
33 | |
34 | inline PrototypeIterator(Isolate* isolate, JSReceiver receiver, |
35 | WhereToStart where_to_start = kStartAtPrototype, |
36 | WhereToEnd where_to_end = END_AT_NULL); |
37 | |
38 | inline explicit PrototypeIterator(Isolate* isolate, Map receiver_map, |
39 | WhereToEnd where_to_end = END_AT_NULL); |
40 | |
41 | inline explicit PrototypeIterator(Isolate* isolate, Handle<Map> receiver_map, |
42 | WhereToEnd where_to_end = END_AT_NULL); |
43 | |
44 | ~PrototypeIterator() = default; |
45 | |
46 | inline bool HasAccess() const; |
47 | |
48 | template <typename T = HeapObject> |
49 | T GetCurrent() const { |
50 | DCHECK(handle_.is_null()); |
51 | return T::cast(object_); |
52 | } |
53 | |
54 | template <typename T = HeapObject> |
55 | static Handle<T> GetCurrent(const PrototypeIterator& iterator) { |
56 | DCHECK(!iterator.handle_.is_null()); |
57 | DCHECK_EQ(iterator.object_, Object()); |
58 | return Handle<T>::cast(iterator.handle_); |
59 | } |
60 | |
61 | inline void Advance(); |
62 | |
63 | inline void AdvanceIgnoringProxies(); |
64 | |
65 | // Returns false iff a call to JSProxy::GetPrototype throws. |
66 | V8_WARN_UNUSED_RESULT inline bool AdvanceFollowingProxies(); |
67 | |
68 | V8_WARN_UNUSED_RESULT inline bool |
69 | AdvanceFollowingProxiesIgnoringAccessChecks(); |
70 | |
71 | bool IsAtEnd() const { return is_at_end_; } |
72 | Isolate* isolate() const { return isolate_; } |
73 | |
74 | private: |
75 | Isolate* isolate_; |
76 | Object object_; |
77 | Handle<HeapObject> handle_; |
78 | WhereToEnd where_to_end_; |
79 | bool is_at_end_; |
80 | int seen_proxies_; |
81 | |
82 | DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); |
83 | }; |
84 | |
85 | |
86 | } // namespace internal |
87 | |
88 | } // namespace v8 |
89 | |
90 | #endif // V8_PROTOTYPE_H_ |
91 | |