Chromium Code Reviews| Index: src/runtime.cc |
| =================================================================== |
| --- src/runtime.cc (revision 7030) |
| +++ src/runtime.cc (working copy) |
| @@ -675,6 +675,78 @@ |
| } |
| +static bool CheckAccessException(LookupResult* result, |
| + v8::AccessType access_type) { |
| + if (result->type() == CALLBACKS) { |
| + Object* callback = result->GetCallbackObject(); |
| + if (callback->IsAccessorInfo()) { |
| + AccessorInfo* info = AccessorInfo::cast(callback); |
| + bool can_access = |
| + (access_type == v8::ACCESS_HAS && |
| + (info->all_can_read() || info->all_can_write())) || |
| + (access_type == v8::ACCESS_GET && info->all_can_read()) || |
| + (access_type == v8::ACCESS_SET && info->all_can_write()); |
| + return can_access; |
| + } |
| + } |
| + |
| + return false; |
| +} |
| + |
| + |
| +static bool CheckAccess(Isolate* isolate, |
| + JSObject* obj, |
| + String* name, |
| + LookupResult* result, |
| + v8::AccessType access_type) { |
| + ASSERT(result->IsProperty()); |
| + |
| + JSObject* holder = result->holder(); |
| + JSObject* current = obj; |
| + while (true) { |
| + if (current->IsAccessCheckNeeded() && |
| + !isolate->MayNamedAccess(current, name, access_type)) { |
| + // Access check callback denied the access, but some properties |
| + // can have a special permissions which override callbacks descision |
| + // (currently see v8::AccessControl). |
| + break; |
| + } |
| + |
| + if (current == holder) { |
| + return true; |
| + } |
| + |
| + current = JSObject::cast(current->GetPrototype()); |
| + } |
| + |
| + // API callbacks can have per callback access exceptions. |
| + switch (result->type()) { |
| + case CALLBACKS: { |
| + if (CheckAccessException(result, access_type)) { |
| + return true; |
| + } |
| + break; |
| + } |
| + case INTERCEPTOR: { |
| + // If the object has an interceptor, try real named properties. |
| + // Overwrite the result to fetch the correct property later. |
| + holder->LookupRealNamedProperty(name, result); |
| + if (result->IsProperty()) { |
| + if (CheckAccessException(result, access_type)) { |
| + return true; |
| + } |
| + } |
| + break; |
| + } |
| + default: |
| + break; |
| + } |
| + |
| + isolate->ReportFailedAccessCheck(current, access_type); |
| + return false; |
| +} |
| + |
| + |
| // Enumerator used as indices into the array returned from GetOwnProperty |
| enum PropertyDescriptorIndices { |
| IS_ACCESSOR_INDEX, |
| @@ -778,35 +850,41 @@ |
| if (!result.IsProperty()) { |
| return heap->undefined_value(); |
| } |
| - if (result.type() == CALLBACKS) { |
| - Object* structure = result.GetCallbackObject(); |
| - if (structure->IsProxy() || structure->IsAccessorInfo()) { |
| - // Property that is internally implemented as a callback or |
| - // an API defined callback. |
| - Object* value; |
| - { MaybeObject* maybe_value = obj->GetPropertyWithCallback( |
| - *obj, structure, *name, result.holder()); |
| - if (!maybe_value->ToObject(&value)) return maybe_value; |
| - } |
| - elms->set(IS_ACCESSOR_INDEX, heap->false_value()); |
| - elms->set(VALUE_INDEX, value); |
| - elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly())); |
| - } else if (structure->IsFixedArray()) { |
| - // __defineGetter__/__defineSetter__ callback. |
| - elms->set(IS_ACCESSOR_INDEX, heap->true_value()); |
| - elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); |
| - elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); |
| - } else { |
| - return heap->undefined_value(); |
| + |
| + if (!CheckAccess(isolate, *obj, *name, &result, v8::ACCESS_HAS)) { |
| + return heap->undefined_value(); |
| + } |
| + |
| + elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum())); |
| + elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); |
| + |
| + bool is_js_accessor = (result.type() == CALLBACKS) && |
| + (result.GetCallbackObject()->IsFixedArray()); |
| + |
| + if (is_js_accessor) { |
| + // __defineGetter__/__defineSetter__ callback. |
| + elms->set(IS_ACCESSOR_INDEX, heap->true_value()); |
| + |
| + FixedArray* structure = FixedArray::cast(result.GetCallbackObject()); |
| + if (CheckAccess(isolate, *obj, *name, &result, v8::ACCESS_GET)) { |
| + elms->set(GETTER_INDEX, structure->get(0)); |
| } |
| + if (CheckAccess(isolate, *obj, *name, &result, v8::ACCESS_SET)) { |
| + elms->set(SETTER_INDEX, structure->get(1)); |
| + } |
| } else { |
| elms->set(IS_ACCESSOR_INDEX, heap->false_value()); |
| - elms->set(VALUE_INDEX, result.GetLazyValue()); |
| elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly())); |
| + |
| + PropertyAttributes attrs; |
| + Object* value; |
| + // GetProperty will check access and report any violations. |
| + { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs); |
| + if (!maybe_value->ToObject(&value)) return maybe_value; |
| + } |
| + elms->set(VALUE_INDEX, value); |
| } |
| - elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum())); |
| - elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); |
| return *desc; |
| } |
| @@ -11233,6 +11311,53 @@ |
| return *value; |
| } |
| + |
| +static MaybeObject* Runtime_NewMessageObject(RUNTIME_CALLING_CONVENTION) { |
| + RUNTIME_GET_ISOLATE; |
| + HandleScope scope; |
|
Vitaly Repeshko
2011/03/02 16:41:09
It's not performance critical, but just for consis
|
| + CONVERT_ARG_CHECKED(String, type, 0); |
| + CONVERT_ARG_CHECKED(JSArray, arguments, 1); |
| + Factory* factory = isolate->factory(); |
| + Handle<Object> undefined = factory->undefined_value(); |
| + return *factory->NewJSMessageObject(type, |
| + arguments, |
| + 0, |
| + 0, |
| + undefined, |
| + undefined, |
| + undefined); |
| +} |
| + |
| + |
| +static MaybeObject* Runtime_MessageGetType(RUNTIME_CALLING_CONVENTION) { |
| + RUNTIME_GET_ISOLATE; |
| + CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| + return message->type(); |
| +} |
| + |
| + |
| +static MaybeObject* Runtime_MessageGetArguments(RUNTIME_CALLING_CONVENTION) { |
| + RUNTIME_GET_ISOLATE; |
| + CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| + return message->arguments(); |
| +} |
| + |
| + |
| +static MaybeObject* Runtime_MessageGetStartPosition( |
| + RUNTIME_CALLING_CONVENTION) { |
| + RUNTIME_GET_ISOLATE; |
| + CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| + return Smi::FromInt(message->start_position()); |
| +} |
| + |
| + |
| +static MaybeObject* Runtime_MessageGetScript(RUNTIME_CALLING_CONVENTION) { |
| + RUNTIME_GET_ISOLATE; |
| + CONVERT_CHECKED(JSMessageObject, message, args[0]); |
| + return message->script(); |
| +} |
| + |
| + |
| #ifdef DEBUG |
| // ListNatives is ONLY used by the fuzz-natives.js in debug mode |
| // Exclude the code in release mode. |