diff options
author | Steve Block <steveblock@google.com> | 2011-02-16 13:27:44 +0000 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-02-16 15:22:50 +0000 |
commit | 103cc40e0c7630e0dada7fcec7f9de7c16ef8844 (patch) | |
tree | 0b379f3183f0523f6a3f61925e124b09b3be23c9 /src | |
parent | 81362e16c30e9e970af6b17592f627ad8cdee4d8 (diff) | |
download | android_external_v8-103cc40e0c7630e0dada7fcec7f9de7c16ef8844.tar.gz android_external_v8-103cc40e0c7630e0dada7fcec7f9de7c16ef8844.tar.bz2 android_external_v8-103cc40e0c7630e0dada7fcec7f9de7c16ef8844.zip |
Merge V8 at Chromium 9.0.597.106
This is V8 branches/2.5 at r6641.
Note that the bug fix that we'd cherry-picked to Android
(http://code.google.com/p/v8/source/detail?r=6579)
was pulled into the 2.5 branch in
http://code.google.com/p/v8/source/detail?r=6601 so is
subsumed by this revision.
Change-Id: I63fd80c82c821d94e71db82e66cea0fbf33a1140
Diffstat (limited to 'src')
-rw-r--r-- | src/objects.cc | 7 | ||||
-rw-r--r-- | src/runtime.cc | 160 | ||||
-rw-r--r-- | src/v8natives.js | 57 | ||||
-rw-r--r-- | src/version.cc | 2 |
4 files changed, 176 insertions, 50 deletions
diff --git a/src/objects.cc b/src/objects.cc index f5d19e28..dcfd926f 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -6265,6 +6265,13 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { return UNDEFINED_ELEMENT; } + if (IsJSGlobalProxy()) { + Object* proto = GetPrototype(); + if (proto->IsNull()) return UNDEFINED_ELEMENT; + ASSERT(proto->IsJSGlobalObject()); + return JSObject::cast(proto)->HasLocalElement(index); + } + // Check for lookup interceptor if (HasIndexedInterceptor()) { return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT diff --git a/src/runtime.cc b/src/runtime.cc index 7214cb98..2324e62d 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -635,6 +635,90 @@ static void GetOwnPropertyImplementation(JSObject* obj, } +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(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() && + !Top::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; + } + + Top::ReportFailedAccessCheck(current, access_type); + return false; +} + + +// TODO(1095): we should traverse hidden prototype hierachy as well. +static bool CheckElementAccess(JSObject* obj, + uint32_t index, + v8::AccessType access_type) { + if (obj->IsAccessCheckNeeded() && + !Top::MayIndexedAccess(obj, index, access_type)) { + return false; + } + + return true; +} + + // Enumerator used as indices into the array returned from GetOwnProperty enum PropertyDescriptorIndices { IS_ACCESSOR_INDEX, @@ -677,7 +761,7 @@ static MaybeObject* Runtime_GetOwnProperty(Arguments args) { // subsequent cases. Handle<JSValue> js_value = Handle<JSValue>::cast(obj); Handle<String> str(String::cast(js_value->value())); - Handle<String> substr = SubString(str, index, index+1, NOT_TENURED); + Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); elms->set(VALUE_INDEX, *substr); @@ -690,8 +774,7 @@ static MaybeObject* Runtime_GetOwnProperty(Arguments args) { case JSObject::INTERCEPTED_ELEMENT: case JSObject::FAST_ELEMENT: { elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); - Handle<Object> element = GetElement(Handle<Object>(obj), index); - elms->set(VALUE_INDEX, *element); + elms->set(VALUE_INDEX, *GetElement(obj, index)); elms->set(WRITABLE_INDEX, Heap::true_value()); elms->set(ENUMERABLE_INDEX, Heap::true_value()); elms->set(CONFIGURABLE_INDEX, Heap::true_value()); @@ -699,7 +782,14 @@ static MaybeObject* Runtime_GetOwnProperty(Arguments args) { } case JSObject::DICTIONARY_ELEMENT: { - NumberDictionary* dictionary = obj->element_dictionary(); + Handle<JSObject> holder = obj; + if (obj->IsJSGlobalProxy()) { + Object* proto = obj->GetPrototype(); + if (proto->IsNull()) return Heap::undefined_value(); + ASSERT(proto->IsJSGlobalObject()); + holder = Handle<JSObject>(JSObject::cast(proto)); + } + NumberDictionary* dictionary = holder->element_dictionary(); int entry = dictionary->FindEntry(index); ASSERT(entry != NumberDictionary::kNotFound); PropertyDetails details = dictionary->DetailsAt(entry); @@ -709,14 +799,18 @@ static MaybeObject* Runtime_GetOwnProperty(Arguments args) { FixedArray* callbacks = FixedArray::cast(dictionary->ValueAt(entry)); elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); - elms->set(GETTER_INDEX, callbacks->get(0)); - elms->set(SETTER_INDEX, callbacks->get(1)); + if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { + elms->set(GETTER_INDEX, callbacks->get(0)); + } + if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { + elms->set(SETTER_INDEX, callbacks->get(1)); + } break; } case NORMAL: // This is a data property. elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); - elms->set(VALUE_INDEX, dictionary->ValueAt(entry)); + elms->set(VALUE_INDEX, *GetElement(obj, index)); elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); break; default: @@ -736,35 +830,41 @@ static MaybeObject* Runtime_GetOwnProperty(Arguments args) { 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(*obj, *name, &result, v8::ACCESS_HAS)) { + return Heap::false_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(*obj, *name, &result, v8::ACCESS_GET)) { + elms->set(GETTER_INDEX, structure->get(0)); + } + if (CheckAccess(*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; } diff --git a/src/v8natives.js b/src/v8natives.js index 50a2774d..09b296d4 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -491,28 +491,29 @@ PropertyDescriptor.prototype.hasSetter = function() { } +// Converts an array returned from Runtime_GetOwnProperty to an actual +// property descriptor. For a description of the array layout please +// see the runtime.cc file. +function ConvertDescriptorArrayToDescriptor(desc_array) { + if (desc_array == false) { + throw 'Internal error: invalid desc_array'; + } -// ES5 section 8.12.1. -function GetOwnProperty(obj, p) { - var desc = new PropertyDescriptor(); - - // GetOwnProperty returns an array indexed by the constants - // defined in macros.py. - // If p is not a property on obj undefined is returned. - var props = %GetOwnProperty(ToObject(obj), ToString(p)); - - if (IS_UNDEFINED(props)) return void 0; + if (IS_UNDEFINED(desc_array)) { + return void 0; + } - // This is an accessor - if (props[IS_ACCESSOR_INDEX]) { - desc.setGet(props[GETTER_INDEX]); - desc.setSet(props[SETTER_INDEX]); + var desc = new PropertyDescriptor(); + // This is an accessor. + if (desc_array[IS_ACCESSOR_INDEX]) { + desc.setGet(desc_array[GETTER_INDEX]); + desc.setSet(desc_array[SETTER_INDEX]); } else { - desc.setValue(props[VALUE_INDEX]); - desc.setWritable(props[WRITABLE_INDEX]); + desc.setValue(desc_array[VALUE_INDEX]); + desc.setWritable(desc_array[WRITABLE_INDEX]); } - desc.setEnumerable(props[ENUMERABLE_INDEX]); - desc.setConfigurable(props[CONFIGURABLE_INDEX]); + desc.setEnumerable(desc_array[ENUMERABLE_INDEX]); + desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]); return desc; } @@ -535,9 +536,27 @@ function HasProperty(obj, p) { } +// ES5 section 8.12.1. +function GetOwnProperty(obj, p) { + // GetOwnProperty returns an array indexed by the constants + // defined in macros.py. + // If p is not a property on obj undefined is returned. + var props = %GetOwnProperty(ToObject(obj), ToString(p)); + + // A false value here means that access checks failed. + if (props == false) return void 0; + + return ConvertDescriptorArrayToDescriptor(props); +} + + // ES5 8.12.9. function DefineOwnProperty(obj, p, desc, should_throw) { - var current = GetOwnProperty(obj, p); + var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p)); + // A false value here means that access checks failed. + if (current_or_access == false) return void 0; + + var current = ConvertDescriptorArrayToDescriptor(current_or_access); var extensible = %IsExtensible(ToObject(obj)); // Error handling according to spec. diff --git a/src/version.cc b/src/version.cc index 24e95847..041facd3 100644 --- a/src/version.cc +++ b/src/version.cc @@ -35,7 +35,7 @@ #define MAJOR_VERSION 2 #define MINOR_VERSION 5 #define BUILD_NUMBER 9 -#define PATCH_LEVEL 11 +#define PATCH_LEVEL 15 #define CANDIDATE_VERSION false // Define SONAME to have the SCons build the put a specific SONAME into the |