OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 1869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1880 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); | 1880 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); |
1881 while (true) { | 1881 while (true) { |
1882 Handle<Object> prototype = Object::GetPrototype(isolate, V); | 1882 Handle<Object> prototype = Object::GetPrototype(isolate, V); |
1883 if (prototype->IsNull()) return isolate->heap()->false_value(); | 1883 if (prototype->IsNull()) return isolate->heap()->false_value(); |
1884 if (*O == *prototype) return isolate->heap()->true_value(); | 1884 if (*O == *prototype) return isolate->heap()->true_value(); |
1885 V = prototype; | 1885 V = prototype; |
1886 } | 1886 } |
1887 } | 1887 } |
1888 | 1888 |
1889 | 1889 |
1890 static bool CheckAccessException(Object* callback, | |
1891 v8::AccessType access_type) { | |
1892 DisallowHeapAllocation no_gc; | |
1893 ASSERT(!callback->IsForeign()); | |
1894 if (callback->IsAccessorInfo()) { | |
1895 AccessorInfo* info = AccessorInfo::cast(callback); | |
1896 return | |
1897 (access_type == v8::ACCESS_HAS && | |
1898 (info->all_can_read() || info->all_can_write())) || | |
1899 (access_type == v8::ACCESS_GET && info->all_can_read()) || | |
1900 (access_type == v8::ACCESS_SET && info->all_can_write()); | |
1901 } | |
1902 return false; | |
1903 } | |
1904 | |
1905 | |
1906 template<class Key> | |
1907 static bool CheckGenericAccess( | |
1908 Handle<JSObject> receiver, | |
1909 Handle<Object> end, | |
1910 Key key, | |
1911 v8::AccessType access_type, | |
1912 bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) { | |
1913 Isolate* isolate = receiver->GetIsolate(); | |
1914 for (Handle<Object> current = receiver; | |
1915 !current.is_identical_to(end); | |
1916 current = Object::GetPrototype(isolate, current)) { | |
1917 if (current->IsAccessCheckNeeded() && | |
1918 !(isolate->*mayAccess)( | |
1919 Handle<JSObject>::cast(current), key, access_type)) { | |
1920 return false; | |
1921 } | |
1922 } | |
1923 return true; | |
1924 } | |
1925 | |
1926 | |
1927 static void CheckPropertyAccess(Handle<JSObject> obj, | |
1928 Handle<Name> name, | |
1929 v8::AccessType access_type) { | |
1930 Isolate* isolate = obj->GetIsolate(); | |
1931 uint32_t index; | |
1932 if (name->AsArrayIndex(&index)) { | |
1933 Handle<Object> next(obj->GetPrototype(), isolate); | |
1934 // TODO(1095): we should traverse hidden prototype hierachy as well. | |
1935 if (!CheckGenericAccess( | |
1936 obj, next, index, access_type, &Isolate::MayIndexedAccess)) { | |
1937 obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); | |
1938 } | |
1939 return; | |
1940 } | |
1941 | |
1942 LookupResult lookup(isolate); | |
1943 obj->LookupOwn(name, &lookup, true); | |
1944 | |
1945 Handle<Object> next = lookup.IsProperty() | |
1946 ? handle(lookup.holder()->GetPrototype(), isolate) | |
1947 : Handle<Object>::cast(isolate->factory()->null_value()); | |
1948 if (CheckGenericAccess<Handle<Object> >( | |
1949 obj, next, name, access_type, &Isolate::MayNamedAccess)) { | |
1950 return; | |
1951 } | |
1952 | |
1953 // Access check callback denied the access, but some properties | |
1954 // can have a special permissions which override callbacks decision | |
1955 // (see v8::AccessControl). | |
1956 // API callbacks can have per callback access exceptions. | |
1957 if (lookup.IsFound() && lookup.type() == INTERCEPTOR) { | |
1958 lookup.holder()->LookupOwnRealNamedProperty(name, &lookup); | |
1959 } | |
1960 | |
1961 if (lookup.IsPropertyCallbacks() && | |
1962 CheckAccessException(lookup.GetCallbackObject(), access_type)) { | |
1963 return; | |
1964 } | |
1965 | |
1966 isolate->ReportFailedAccessCheck(obj, access_type); | |
1967 } | |
1968 | |
1969 | |
1970 // Enumerator used as indices into the array returned from GetOwnProperty | 1890 // Enumerator used as indices into the array returned from GetOwnProperty |
1971 enum PropertyDescriptorIndices { | 1891 enum PropertyDescriptorIndices { |
1972 IS_ACCESSOR_INDEX, | 1892 IS_ACCESSOR_INDEX, |
1973 VALUE_INDEX, | 1893 VALUE_INDEX, |
1974 GETTER_INDEX, | 1894 GETTER_INDEX, |
1975 SETTER_INDEX, | 1895 SETTER_INDEX, |
1976 WRITABLE_INDEX, | 1896 WRITABLE_INDEX, |
1977 ENUMERABLE_INDEX, | 1897 ENUMERABLE_INDEX, |
1978 CONFIGURABLE_INDEX, | 1898 CONFIGURABLE_INDEX, |
1979 DESCRIPTOR_SIZE | 1899 DESCRIPTOR_SIZE |
1980 }; | 1900 }; |
1981 | 1901 |
1982 | 1902 |
1983 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, | 1903 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate, |
1984 Handle<JSObject> obj, | 1904 Handle<JSObject> obj, |
1985 Handle<Name> name) { | 1905 Handle<Name> name) { |
1986 Heap* heap = isolate->heap(); | 1906 Heap* heap = isolate->heap(); |
1987 Factory* factory = isolate->factory(); | 1907 Factory* factory = isolate->factory(); |
1988 | 1908 |
1989 CheckPropertyAccess(obj, name, v8::ACCESS_HAS); | 1909 PropertyAttributes attrs; |
1990 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1910 uint32_t index = 0; |
1991 | 1911 MaybeHandle<AccessorPair> maybe_accessors; |
1992 PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name); | 1912 // TODO(verwaest): Unify once indexed properties can be handled by the |
1993 if (attrs == ABSENT) { | 1913 // LookupIterator. |
1994 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1914 if (name->AsArrayIndex(&index)) { |
1995 return factory->undefined_value(); | 1915 attrs = JSReceiver::GetOwnElementAttribute(obj, index); |
1916 if (attrs == ABSENT) { | |
1917 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
1918 return factory->undefined_value(); | |
1919 } | |
1920 maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index); | |
1921 } else { | |
1922 LookupIterator it(obj, name, LookupIterator::CHECK_OWN); | |
1923 attrs = JSObject::GetPropertyAttributes(&it); | |
1924 if (attrs == ABSENT) { | |
1925 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | |
1926 return factory->undefined_value(); | |
1927 } | |
1928 if (it.state() == LookupIterator::PROPERTY && | |
1929 it.property_kind() == LookupIterator::ACCESSOR) { | |
1930 Handle<Object> accessors = it.GetAccessors(); | |
1931 if (accessors->IsAccessorPair()) { | |
1932 maybe_accessors = Handle<AccessorPair>::cast(accessors); | |
1933 } | |
1934 } | |
1996 } | 1935 } |
1997 ASSERT(!isolate->has_scheduled_exception()); | 1936 ASSERT(!isolate->has_scheduled_exception()); |
1998 Handle<AccessorPair> accessors; | |
1999 bool has_accessors = | |
2000 JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors); | |
2001 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); | 1937 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); |
2002 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | 1938 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
2003 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | 1939 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
2004 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors)); | 1940 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null())); |
2005 | 1941 |
2006 if (!has_accessors) { | 1942 Handle<AccessorPair> accessors; |
1943 if (maybe_accessors.ToHandle(&accessors)) { | |
1944 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | |
1945 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | |
1946 elms->set(GETTER_INDEX, *getter); | |
1947 elms->set(SETTER_INDEX, *setter); | |
1948 } else { | |
2007 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); | 1949 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
2008 // Runtime::GetObjectProperty does access check. | 1950 // Runtime::GetObjectProperty does access check. |
2009 Handle<Object> value; | 1951 Handle<Object> value; |
2010 ASSIGN_RETURN_ON_EXCEPTION( | 1952 ASSIGN_RETURN_ON_EXCEPTION( |
Toon Verwaest
2014/06/16 17:26:14
I'd avoid rewalking by using the LookupIterator, b
| |
2011 isolate, value, Runtime::GetObjectProperty(isolate, obj, name), | 1953 isolate, value, Runtime::GetObjectProperty(isolate, obj, name), |
2012 Object); | 1954 Object); |
2013 elms->set(VALUE_INDEX, *value); | 1955 elms->set(VALUE_INDEX, *value); |
2014 } else { | |
2015 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | |
2016 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | |
2017 elms->set(GETTER_INDEX, *getter); | |
2018 elms->set(SETTER_INDEX, *setter); | |
2019 } | 1956 } |
2020 | 1957 |
2021 return factory->NewJSArrayWithElements(elms); | 1958 return factory->NewJSArrayWithElements(elms); |
2022 } | 1959 } |
2023 | 1960 |
2024 | 1961 |
2025 // Returns an array with the property description: | 1962 // Returns an array with the property description: |
2026 // if args[1] is not a property on args[0] | 1963 // if args[1] is not a property on args[0] |
2027 // returns undefined | 1964 // returns undefined |
2028 // if args[1] is a data property on args[0] | 1965 // if args[1] is a data property on args[0] |
(...skipping 13132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15161 } | 15098 } |
15162 return NULL; | 15099 return NULL; |
15163 } | 15100 } |
15164 | 15101 |
15165 | 15102 |
15166 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15103 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15167 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15104 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15168 } | 15105 } |
15169 | 15106 |
15170 } } // namespace v8::internal | 15107 } } // namespace v8::internal |
OLD | NEW |