summaryrefslogtreecommitdiff
path: root/chromium/v8/src/prototype.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/prototype.h')
-rw-r--r--chromium/v8/src/prototype.h48
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);
};