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; |
| 1911 Handle<Object> value; |
| 1912 MaybeHandle<AccessorPair> maybe_accessors; |
| 1913 // TODO(verwaest): Unify once indexed properties can be handled by the |
| 1914 // LookupIterator. |
| 1915 if (name->AsArrayIndex(&index)) { |
| 1916 // Get attributes. |
| 1917 attrs = JSReceiver::GetOwnElementAttribute(obj, index); |
| 1918 if (attrs == ABSENT) { |
| 1919 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 1920 return factory->undefined_value(); |
| 1921 } |
1991 | 1922 |
1992 PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name); | 1923 // Get AccessorPair if present. |
1993 if (attrs == ABSENT) { | 1924 maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index); |
1994 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1925 |
1995 return factory->undefined_value(); | 1926 // Get value if not an AccessorPair. |
| 1927 if (maybe_accessors.is_null()) { |
| 1928 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, |
| 1929 Runtime::GetElementOrCharAt(isolate, obj, index), Object); |
| 1930 } |
| 1931 } else { |
| 1932 // Get attributes. |
| 1933 LookupIterator it(obj, name, LookupIterator::CHECK_OWN); |
| 1934 attrs = JSObject::GetPropertyAttributes(&it); |
| 1935 if (attrs == ABSENT) { |
| 1936 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 1937 return factory->undefined_value(); |
| 1938 } |
| 1939 |
| 1940 // Get AccessorPair if present. |
| 1941 if (it.state() == LookupIterator::PROPERTY && |
| 1942 it.property_kind() == LookupIterator::ACCESSOR && |
| 1943 it.GetAccessors()->IsAccessorPair()) { |
| 1944 maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors()); |
| 1945 } |
| 1946 |
| 1947 // Get value if not an AccessorPair. |
| 1948 if (maybe_accessors.is_null()) { |
| 1949 ASSIGN_RETURN_ON_EXCEPTION( |
| 1950 isolate, value, Object::GetProperty(&it), Object); |
| 1951 } |
1996 } | 1952 } |
1997 ASSERT(!isolate->has_scheduled_exception()); | 1953 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); | 1954 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); |
2002 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | 1955 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
2003 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | 1956 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
2004 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors)); | 1957 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null())); |
2005 | 1958 |
2006 if (!has_accessors) { | 1959 Handle<AccessorPair> accessors; |
2007 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); | 1960 if (maybe_accessors.ToHandle(&accessors)) { |
2008 // Runtime::GetObjectProperty does access check. | |
2009 Handle<Object> value; | |
2010 ASSIGN_RETURN_ON_EXCEPTION( | |
2011 isolate, value, Runtime::GetObjectProperty(isolate, obj, name), | |
2012 Object); | |
2013 elms->set(VALUE_INDEX, *value); | |
2014 } else { | |
2015 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | 1961 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); |
2016 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | 1962 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); |
2017 elms->set(GETTER_INDEX, *getter); | 1963 elms->set(GETTER_INDEX, *getter); |
2018 elms->set(SETTER_INDEX, *setter); | 1964 elms->set(SETTER_INDEX, *setter); |
| 1965 } else { |
| 1966 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); |
| 1967 elms->set(VALUE_INDEX, *value); |
2019 } | 1968 } |
2020 | 1969 |
2021 return factory->NewJSArrayWithElements(elms); | 1970 return factory->NewJSArrayWithElements(elms); |
2022 } | 1971 } |
2023 | 1972 |
2024 | 1973 |
2025 // Returns an array with the property description: | 1974 // Returns an array with the property description: |
2026 // if args[1] is not a property on args[0] | 1975 // if args[1] is not a property on args[0] |
2027 // returns undefined | 1976 // returns undefined |
2028 // if args[1] is a data property on args[0] | 1977 // if args[1] is a data property on args[0] |
(...skipping 13132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15161 } | 15110 } |
15162 return NULL; | 15111 return NULL; |
15163 } | 15112 } |
15164 | 15113 |
15165 | 15114 |
15166 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15115 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15167 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15116 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15168 } | 15117 } |
15169 | 15118 |
15170 } } // namespace v8::internal | 15119 } } // namespace v8::internal |
OLD | NEW |