Index: src/prototype.h |
diff --git a/src/prototype.h b/src/prototype.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aebdcbc067ef1ed7d65432597826029e63650532 |
--- /dev/null |
+++ b/src/prototype.h |
@@ -0,0 +1,130 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_PROTOTYPE_H_ |
+#define V8_PROTOTYPE_H_ |
+ |
+#include "src/isolate.h" |
+#include "src/objects.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+/** |
+ * A class to uniformly access the prototype of any Object and walk its |
+ * prototype chain. |
+ * |
+ * The PrototypeIterator can either start at the prototype (default), or |
+ * include the receiver itself. If a PrototypeIterator is constructed for a |
+ * Map, it will always start at the prototype. |
+ * |
+ * The PrototypeIterator can either run to the null_value(), the first |
+ * non-hidden prototype, or a given object. |
+ */ |
+class PrototypeIterator { |
+ public: |
+ enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE }; |
+ |
+ enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN }; |
+ |
+ PrototypeIterator(Isolate* isolate, Handle<Object> receiver, |
+ WhereToStart where_to_start = START_AT_PROTOTYPE) |
+ : did_jump_to_prototype_chain_(false), |
+ object_(NULL), |
+ handle_(receiver), |
+ isolate_(isolate) { |
+ CHECK(!handle_.is_null()); |
+ if (where_to_start == START_AT_PROTOTYPE) { |
+ Advance(); |
+ } |
+ } |
+ PrototypeIterator(Isolate* isolate, Object* receiver, |
+ WhereToStart where_to_start = START_AT_PROTOTYPE) |
+ : did_jump_to_prototype_chain_(false), |
+ object_(receiver), |
+ isolate_(isolate) { |
+ if (where_to_start == START_AT_PROTOTYPE) { |
+ Advance(); |
+ } |
+ } |
+ explicit PrototypeIterator(Map* receiver_map) |
+ : did_jump_to_prototype_chain_(true), |
+ object_(receiver_map->prototype()), |
+ isolate_(receiver_map->GetIsolate()) {} |
+ ~PrototypeIterator() {} |
+ |
+ Object* GetCurrent() const { |
+ ASSERT(handle_.is_null()); |
+ return object_; |
+ } |
+ static Handle<Object> GetCurrent(const PrototypeIterator& iterator) { |
+ ASSERT(!iterator.handle_.is_null()); |
+ return iterator.handle_; |
+ } |
+ void Advance() { |
+ if (handle_.is_null() && object_->IsJSProxy()) { |
+ did_jump_to_prototype_chain_ = true; |
+ object_ = isolate_->heap()->null_value(); |
+ return; |
+ } else if (!handle_.is_null() && handle_->IsJSProxy()) { |
+ did_jump_to_prototype_chain_ = true; |
+ handle_ = handle(isolate_->heap()->null_value(), isolate_); |
+ return; |
+ } |
+ AdvanceIgnoringProxies(); |
+ } |
+ void AdvanceIgnoringProxies() { |
+ if (!did_jump_to_prototype_chain_) { |
+ did_jump_to_prototype_chain_ = true; |
+ if (handle_.is_null()) { |
+ object_ = object_->GetRootMap(isolate_)->prototype(); |
+ } else { |
+ handle_ = handle(handle_->GetRootMap(isolate_)->prototype(), isolate_); |
+ } |
+ } else { |
+ if (handle_.is_null()) { |
+ object_ = HeapObject::cast(object_)->map()->prototype(); |
+ } else { |
+ handle_ = |
+ handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_); |
+ } |
+ } |
+ } |
+ bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const { |
+ if (handle_.is_null()) { |
+ return object_->IsNull() || |
+ (did_jump_to_prototype_chain_ && |
+ where_to_end == END_AT_NON_HIDDEN && |
+ !HeapObject::cast(object_)->map()->is_hidden_prototype()); |
+ } else { |
+ return handle_->IsNull() || |
+ (did_jump_to_prototype_chain_ && |
+ where_to_end == END_AT_NON_HIDDEN && |
+ !Handle<HeapObject>::cast(handle_)->map()->is_hidden_prototype()); |
+ } |
+ } |
+ bool IsAtEnd(Object* final_object) { |
+ ASSERT(handle_.is_null()); |
+ return object_->IsNull() || object_ == final_object; |
+ } |
+ bool IsAtEnd(Handle<Object> final_object) { |
+ ASSERT(!handle_.is_null()); |
+ return handle_->IsNull() || *handle_ == *final_object; |
+ } |
+ |
+ private: |
+ bool did_jump_to_prototype_chain_; |
+ Object* object_; |
+ Handle<Object> handle_; |
+ Isolate* isolate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); |
+}; |
+ |
+ |
+} // namespace internal |
+ |
+} // namespace v8 |
+ |
+#endif // V8_PROTOTYPE_H_ |