diff options
Diffstat (limited to 'chromium/v8/src/prototype.h')
-rw-r--r-- | chromium/v8/src/prototype.h | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/chromium/v8/src/prototype.h b/chromium/v8/src/prototype.h index 07277498535..3253791f907 100644 --- a/chromium/v8/src/prototype.h +++ b/chromium/v8/src/prototype.h @@ -28,12 +28,15 @@ class PrototypeIterator { enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN }; + const int kProxyPrototypeLimit = 100 * 1000; + 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) { + isolate_(isolate), + seen_proxies_(0) { CHECK(!handle_.is_null()); if (where_to_start == START_AT_PROTOTYPE) { Advance(); @@ -44,7 +47,8 @@ class PrototypeIterator { WhereToStart where_to_start = START_AT_PROTOTYPE) : did_jump_to_prototype_chain_(false), object_(receiver), - isolate_(isolate) { + isolate_(isolate), + seen_proxies_(0) { if (where_to_start == START_AT_PROTOTYPE) { Advance(); } @@ -63,6 +67,17 @@ class PrototypeIterator { ~PrototypeIterator() {} + bool HasAccess() const { + // We can only perform access check in the handlified version of the + // PrototypeIterator. + DCHECK(!handle_.is_null()); + if (handle_->IsAccessCheckNeeded()) { + return isolate_->MayAccess(handle(isolate_->context()), + Handle<JSObject>::cast(handle_)); + } + return true; + } + template <typename T = Object> T* GetCurrent() const { DCHECK(handle_.is_null()); @@ -72,6 +87,7 @@ class PrototypeIterator { template <typename T = Object> static Handle<T> GetCurrent(const PrototypeIterator& iterator) { DCHECK(!iterator.handle_.is_null()); + DCHECK(iterator.object_ == NULL); return Handle<T>::cast(iterator.handle_); } @@ -106,6 +122,33 @@ class PrototypeIterator { } } + // Returns false iff a call to JSProxy::GetPrototype throws. + // TODO(neis): This should probably replace Advance(). + bool AdvanceFollowingProxies() { + DCHECK(!(handle_.is_null() && object_->IsJSProxy())); + if (!HasAccess()) { + // Abort the lookup if we do not have access to the current object. + handle_ = isolate_->factory()->null_value(); + return true; + } + if (handle_.is_null() || !handle_->IsJSProxy()) { + AdvanceIgnoringProxies(); + return true; + } + // Due to possible __proto__ recursion limit the number of Proxies + // we visit to an arbitrarily chosen large number. + seen_proxies_++; + if (seen_proxies_ > kProxyPrototypeLimit) { + isolate_->Throw( + *isolate_->factory()->NewRangeError(MessageTemplate::kStackOverflow)); + return false; + } + did_jump_to_prototype_chain_ = true; + MaybeHandle<Object> proto = + JSProxy::GetPrototype(Handle<JSProxy>::cast(handle_)); + return proto.ToHandle(&handle_); + } + bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const { if (handle_.is_null()) { return object_->IsNull() || @@ -135,6 +178,7 @@ class PrototypeIterator { Object* object_; Handle<Object> handle_; Isolate* isolate_; + int seen_proxies_; DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); }; |