| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 1fee95b6b9a897615b25bcc36309a0a1206fdf6a..1137d6edbebb413ee51e5f4002864547680ee105 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -540,62 +540,43 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
|
| }
|
|
|
|
|
| -// Only deal with CALLBACKS and INTERCEPTOR
|
| +static bool FindAllCanReadHolder(LookupResult* result,
|
| + Handle<Name> name,
|
| + bool check_prototype) {
|
| + if (result->IsInterceptor()) {
|
| + result->holder()->LookupOwnRealNamedProperty(name, result);
|
| + }
|
| +
|
| + while (result->IsProperty()) {
|
| + if (result->type() == CALLBACKS) {
|
| + Object* callback_obj = result->GetCallbackObject();
|
| + if (callback_obj->IsAccessorInfo()) {
|
| + if (AccessorInfo::cast(callback_obj)->all_can_read()) return true;
|
| + } else if (callback_obj->IsAccessorPair()) {
|
| + if (AccessorPair::cast(callback_obj)->all_can_read()) return true;
|
| + }
|
| + }
|
| + if (!check_prototype) break;
|
| + result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
| Handle<JSObject> object,
|
| Handle<Object> receiver,
|
| LookupResult* result,
|
| Handle<Name> name,
|
| PropertyAttributes* attributes) {
|
| - Isolate* isolate = name->GetIsolate();
|
| - if (result->IsProperty()) {
|
| - switch (result->type()) {
|
| - case CALLBACKS: {
|
| - // Only allow API accessors.
|
| - Handle<Object> callback_obj(result->GetCallbackObject(), isolate);
|
| - if (callback_obj->IsAccessorInfo()) {
|
| - if (!AccessorInfo::cast(*callback_obj)->all_can_read()) break;
|
| - *attributes = result->GetAttributes();
|
| - // Fall through to GetPropertyWithCallback.
|
| - } else if (callback_obj->IsAccessorPair()) {
|
| - if (!AccessorPair::cast(*callback_obj)->all_can_read()) break;
|
| - // Fall through to GetPropertyWithCallback.
|
| - } else {
|
| - break;
|
| - }
|
| - Handle<JSObject> holder(result->holder(), isolate);
|
| - return GetPropertyWithCallback(receiver, name, holder, callback_obj);
|
| - }
|
| - case NORMAL:
|
| - case FIELD:
|
| - case CONSTANT: {
|
| - // Search ALL_CAN_READ accessors in prototype chain.
|
| - LookupResult r(isolate);
|
| - result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
|
| - if (r.IsProperty()) {
|
| - return GetPropertyWithFailedAccessCheck(
|
| - object, receiver, &r, name, attributes);
|
| - }
|
| - break;
|
| - }
|
| - case INTERCEPTOR: {
|
| - // If the object has an interceptor, try real named properties.
|
| - // No access check in GetPropertyAttributeWithInterceptor.
|
| - LookupResult r(isolate);
|
| - result->holder()->LookupRealNamedProperty(name, &r);
|
| - if (r.IsProperty()) {
|
| - return GetPropertyWithFailedAccessCheck(
|
| - object, receiver, &r, name, attributes);
|
| - }
|
| - break;
|
| - }
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| + if (FindAllCanReadHolder(result, name, true)) {
|
| + *attributes = result->GetAttributes();
|
| + Handle<JSObject> holder(result->holder());
|
| + Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
|
| + return GetPropertyWithCallback(receiver, name, holder, callbacks);
|
| }
|
| -
|
| - // No accessible property found.
|
| *attributes = ABSENT;
|
| + Isolate* isolate = result->isolate();
|
| isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
|
| RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->undefined_value();
|
| @@ -606,63 +587,61 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| Handle<JSObject> object,
|
| LookupResult* result,
|
| Handle<Name> name,
|
| - bool continue_search) {
|
| - if (result->IsProperty()) {
|
| - switch (result->type()) {
|
| - case CALLBACKS: {
|
| - // Only allow API accessors.
|
| - Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate());
|
| - if (obj->IsAccessorInfo()) {
|
| - Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj);
|
| - if (info->all_can_read()) {
|
| - return result->GetAttributes();
|
| - }
|
| - } else if (obj->IsAccessorPair()) {
|
| - Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj);
|
| - if (pair->all_can_read()) {
|
| - return result->GetAttributes();
|
| - }
|
| - }
|
| - break;
|
| - }
|
| + bool check_prototype) {
|
| + if (FindAllCanReadHolder(result, name, check_prototype)) {
|
| + return result->GetAttributes();
|
| + }
|
| + result->isolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
|
| + // TODO(yangguo): Issue 3269, check for scheduled exception missing?
|
| + return ABSENT;
|
| +}
|
|
|
| - case NORMAL:
|
| - case FIELD:
|
| - case CONSTANT: {
|
| - if (!continue_search) break;
|
| - // Search ALL_CAN_READ accessors in prototype chain.
|
| - LookupResult r(object->GetIsolate());
|
| - result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
|
| - if (r.IsProperty()) {
|
| - return GetPropertyAttributeWithFailedAccessCheck(
|
| - object, &r, name, continue_search);
|
| - }
|
| - break;
|
| - }
|
|
|
| - case INTERCEPTOR: {
|
| - // If the object has an interceptor, try real named properties.
|
| - // No access check in GetPropertyAttributeWithInterceptor.
|
| - LookupResult r(object->GetIsolate());
|
| - if (continue_search) {
|
| - result->holder()->LookupRealNamedProperty(name, &r);
|
| - } else {
|
| - result->holder()->LookupOwnRealNamedProperty(name, &r);
|
| - }
|
| - if (!r.IsFound()) break;
|
| - return GetPropertyAttributeWithFailedAccessCheck(
|
| - object, &r, name, continue_search);
|
| +static bool FindAllCanWriteHolder(LookupResult* result,
|
| + Handle<Name> name,
|
| + bool check_prototype) {
|
| + if (result->IsInterceptor()) {
|
| + result->holder()->LookupOwnRealNamedProperty(name, result);
|
| + }
|
| +
|
| + while (result->IsProperty()) {
|
| + if (result->type() == CALLBACKS) {
|
| + Object* callback_obj = result->GetCallbackObject();
|
| + if (callback_obj->IsAccessorInfo()) {
|
| + if (AccessorInfo::cast(callback_obj)->all_can_write()) return true;
|
| + } else if (callback_obj->IsAccessorPair()) {
|
| + if (AccessorPair::cast(callback_obj)->all_can_write()) return true;
|
| }
|
| -
|
| - case HANDLER:
|
| - case NONEXISTENT:
|
| - UNREACHABLE();
|
| }
|
| + if (!check_prototype) break;
|
| + result->holder()->LookupRealNamedPropertyInPrototypes(name, result);
|
| }
|
| + return false;
|
| +}
|
|
|
| - object->GetIsolate()->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
|
| - // TODO(yangguo): Issue 3269, check for scheduled exception missing?
|
| - return ABSENT;
|
| +
|
| +MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| + Handle<JSObject> object,
|
| + LookupResult* result,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + bool check_prototype,
|
| + StrictMode strict_mode) {
|
| + if (check_prototype && !result->IsProperty()) {
|
| + object->LookupRealNamedPropertyInPrototypes(name, result);
|
| + }
|
| +
|
| + if (FindAllCanWriteHolder(result, name, check_prototype)) {
|
| + Handle<JSObject> holder(result->holder());
|
| + Handle<Object> callbacks(result->GetCallbackObject(), result->isolate());
|
| + return SetPropertyWithCallback(
|
| + object, name, value, holder, callbacks, strict_mode);
|
| + }
|
| +
|
| + Isolate* isolate = object->GetIsolate();
|
| + isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
|
| + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| }
|
|
|
|
|
| @@ -834,11 +813,11 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
|
| if (!result->IsHandler()) {
|
| ASSERT(*object != object->GetPrototype(isolate));
|
| Handle<Object> last = result->IsProperty()
|
| - ? Handle<Object>(result->holder(), isolate)
|
| + ? handle(result->holder()->GetPrototype(), isolate)
|
| : Handle<Object>::cast(factory->null_value());
|
| for (Handle<Object> current = object;
|
| - true;
|
| - current = Handle<Object>(current->GetPrototype(isolate), isolate)) {
|
| + !current.is_identical_to(last);
|
| + current = Object::GetPrototype(isolate, current)) {
|
| if (current->IsAccessCheckNeeded()) {
|
| // Check if we're allowed to read from the current object. Note
|
| // that even though we may not actually end up loading the named
|
| @@ -850,10 +829,6 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
|
| checked, receiver, result, name, attributes);
|
| }
|
| }
|
| - // Stop traversing the chain once we reach the last object in the
|
| - // chain; either the holder of the result or null in case of an
|
| - // absent property.
|
| - if (current.is_identical_to(last)) break;
|
| }
|
| }
|
|
|
| @@ -3603,69 +3578,6 @@ void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
|
| }
|
|
|
|
|
| -// We only need to deal with CALLBACKS and INTERCEPTORS
|
| -MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| - Handle<JSObject> object,
|
| - LookupResult* result,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - bool check_prototype,
|
| - StrictMode strict_mode) {
|
| - if (check_prototype && !result->IsProperty()) {
|
| - object->LookupRealNamedPropertyInPrototypes(name, result);
|
| - }
|
| -
|
| - if (result->IsProperty()) {
|
| - if (!result->IsReadOnly()) {
|
| - switch (result->type()) {
|
| - case CALLBACKS: {
|
| - Object* obj = result->GetCallbackObject();
|
| - if (obj->IsAccessorInfo()) {
|
| - Handle<AccessorInfo> info(AccessorInfo::cast(obj));
|
| - if (info->all_can_write()) {
|
| - return SetPropertyWithCallback(object, name, value,
|
| - handle(result->holder()),
|
| - info, strict_mode);
|
| - }
|
| - } else if (obj->IsAccessorPair()) {
|
| - Handle<AccessorPair> pair(AccessorPair::cast(obj));
|
| - if (pair->all_can_read()) {
|
| - return SetPropertyWithCallback(object, name, value,
|
| - handle(result->holder()),
|
| - pair, strict_mode);
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - case INTERCEPTOR: {
|
| - // Try lookup real named properties. Note that only property can be
|
| - // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
|
| - LookupResult r(object->GetIsolate());
|
| - object->LookupRealNamedProperty(name, &r);
|
| - if (r.IsProperty()) {
|
| - return SetPropertyWithFailedAccessCheck(object,
|
| - &r,
|
| - name,
|
| - value,
|
| - check_prototype,
|
| - strict_mode);
|
| - }
|
| - break;
|
| - }
|
| - default: {
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - Isolate* isolate = object->GetIsolate();
|
| - isolate->ReportFailedAccessCheck(object, v8::ACCESS_SET);
|
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - return value;
|
| -}
|
| -
|
| -
|
| MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| LookupResult* result,
|
| Handle<Name> key,
|
| @@ -4505,14 +4417,14 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
|
| Handle<JSObject> object,
|
| Handle<JSObject> receiver,
|
| Handle<Name> name,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| // Check own property, ignore interceptor.
|
| Isolate* isolate = object->GetIsolate();
|
| LookupResult result(isolate);
|
| object->LookupOwnRealNamedProperty(name, &result);
|
| if (result.IsFound()) return result.GetAttributes();
|
|
|
| - if (continue_search) {
|
| + if (check_prototype) {
|
| // Continue searching via the prototype chain.
|
| Handle<Object> proto(object->GetPrototype(), isolate);
|
| if (!proto->IsNull()) {
|
| @@ -4528,7 +4440,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
|
| Handle<JSObject> object,
|
| Handle<JSObject> receiver,
|
| Handle<Name> name,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| // TODO(rossberg): Support symbols in the API.
|
| if (name->IsSymbol()) return ABSENT;
|
|
|
| @@ -4563,7 +4475,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
|
| if (!result.IsEmpty()) return DONT_ENUM;
|
| }
|
| return GetPropertyAttributePostInterceptor(
|
| - object, receiver, name, continue_search);
|
| + object, receiver, name, check_prototype);
|
| }
|
|
|
|
|
| @@ -4588,14 +4500,14 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
|
| Handle<JSReceiver> receiver,
|
| LookupResult* lookup,
|
| Handle<Name> name,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| Heap* heap = object->GetHeap();
|
| Handle<JSObject> obj = Handle<JSObject>::cast(object);
|
| if (!heap->isolate()->MayNamedAccess(obj, name, v8::ACCESS_HAS)) {
|
| return JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| - obj, lookup, name, continue_search);
|
| + obj, lookup, name, check_prototype);
|
| }
|
| }
|
| if (lookup->IsFound()) {
|
| @@ -4614,7 +4526,7 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
|
| handle(lookup->holder()),
|
| Handle<JSObject>::cast(receiver),
|
| name,
|
| - continue_search);
|
| + check_prototype);
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| }
|
| @@ -4641,7 +4553,7 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
|
| Handle<JSObject> object,
|
| Handle<JSReceiver> receiver,
|
| uint32_t index,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| Isolate* isolate = object->GetIsolate();
|
|
|
| // Check access rights if needed.
|
| @@ -4658,17 +4570,17 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver(
|
| if (proto->IsNull()) return ABSENT;
|
| ASSERT(proto->IsJSGlobalObject());
|
| return JSObject::GetElementAttributeWithReceiver(
|
| - Handle<JSObject>::cast(proto), receiver, index, continue_search);
|
| + Handle<JSObject>::cast(proto), receiver, index, check_prototype);
|
| }
|
|
|
| // Check for lookup interceptor except when bootstrapping.
|
| if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
|
| return JSObject::GetElementAttributeWithInterceptor(
|
| - object, receiver, index, continue_search);
|
| + object, receiver, index, check_prototype);
|
| }
|
|
|
| return GetElementAttributeWithoutInterceptor(
|
| - object, receiver, index, continue_search);
|
| + object, receiver, index, check_prototype);
|
| }
|
|
|
|
|
| @@ -4676,7 +4588,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
|
| Handle<JSObject> object,
|
| Handle<JSReceiver> receiver,
|
| uint32_t index,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| Isolate* isolate = object->GetIsolate();
|
| HandleScope scope(isolate);
|
|
|
| @@ -4706,7 +4618,7 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
|
| }
|
|
|
| return GetElementAttributeWithoutInterceptor(
|
| - object, receiver, index, continue_search);
|
| + object, receiver, index, check_prototype);
|
| }
|
|
|
|
|
| @@ -4714,7 +4626,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
|
| Handle<JSObject> object,
|
| Handle<JSReceiver> receiver,
|
| uint32_t index,
|
| - bool continue_search) {
|
| + bool check_prototype) {
|
| PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
|
| receiver, object, index);
|
| if (attr != ABSENT) return attr;
|
| @@ -4724,7 +4636,7 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
|
| return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
| }
|
|
|
| - if (!continue_search) return ABSENT;
|
| + if (!check_prototype) return ABSENT;
|
|
|
| Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
|
| if (proto->IsJSProxy()) {
|
|
|