Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); | 838 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); |
| 839 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 839 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
| 840 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( | 840 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( |
| 841 elems, isolate->factory()->fixed_array_map()); | 841 elems, isolate->factory()->fixed_array_map()); |
| 842 object->set_elements(*writable_elems); | 842 object->set_elements(*writable_elems); |
| 843 isolate->counters()->cow_arrays_converted()->Increment(); | 843 isolate->counters()->cow_arrays_converted()->Increment(); |
| 844 return writable_elems; | 844 return writable_elems; |
| 845 } | 845 } |
| 846 | 846 |
| 847 | 847 |
| 848 // ES6 9.5.1 | 848 // ES6: Section 9.5.1 [[GetPrototypeOf]] ( ) |
| 849 // static | 849 // static |
| 850 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { | 850 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { |
| 851 Isolate* isolate = proxy->GetIsolate(); | 851 Isolate* isolate = proxy->GetIsolate(); |
| 852 Handle<Object> trap; | |
| 853 Handle<JSReceiver> handle; | |
| 854 Handle<Name> trap_name = isolate->factory()->getPrototypeOf_string(); | |
| 852 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. | 855 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. |
| 853 Handle<Object> raw_handler(proxy->handler(), isolate); | 856 Handle<Object> raw_handler(proxy->handler(), isolate); |
| 854 // 2. If handler is null, throw a TypeError exception. | 857 // 2. If handler is null, throw a TypeError exception. |
| 855 // 3. Assert: Type(handler) is Object. | 858 // 3. Assert: Type(handler) is Object. |
| 856 if (!raw_handler->IsSpecObject()) { | 859 if (!raw_handler->IsSpecObject()) { |
| 860 DCHECK(raw_handler->IsNull()); | |
| 861 DCHECK(proxy->target()->IsNull()); | |
| 857 // TODO(cbruni): Throw correct error message. | 862 // TODO(cbruni): Throw correct error message. |
| 858 THROW_NEW_ERROR( | 863 THROW_NEW_ERROR( |
| 859 isolate, NewTypeError(MessageTemplate::kProxyHandlerNonObject), Object); | 864 isolate, NewTypeError(MessageTemplate::kProxyHandlerNonObject), Object); |
| 860 } | 865 } |
| 861 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); | 866 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); |
| 862 // 4. Let target be the value of the [[ProxyTarget]] internal slot. | 867 // 4. Let target be the value of the [[ProxyTarget]] internal slot. |
| 863 // TODO(cbruni): Change target type to JSReceiver by default. | 868 // TODO(cbruni): Change target type to JSReceiver by default. |
| 864 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); | 869 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
| 865 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). | 870 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). |
| 866 Handle<Object> trap; | |
| 867 Handle<String> trap_name = isolate->factory()->getPrototypeOf_string(); | |
| 868 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name), | 871 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name), |
| 869 Object); | 872 Object); |
| 870 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). | 873 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). |
| 871 if (trap->IsUndefined()) { | 874 if (trap->IsUndefined()) { |
| 872 return Object::GetPrototype(isolate, target); | 875 return Object::GetPrototype(isolate, target); |
| 873 } | 876 } |
| 874 // 7. Let handlerProto be ? Call(trap, handler, «target»). | 877 // 7. Let handlerProto be ? Call(trap, handler, «target»). |
| 875 Handle<Object> argv[] = {target}; | 878 Handle<Object> argv[] = {target}; |
| 876 Handle<Object> handler_proto; | 879 Handle<Object> handler_proto; |
| 877 ASSIGN_RETURN_ON_EXCEPTION( | 880 ASSIGN_RETURN_ON_EXCEPTION( |
| 878 isolate, handler_proto, | 881 isolate, handler_proto, |
| 879 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); | 882 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); |
| 880 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. | 883 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. |
| 881 if (!(handler_proto->IsSpecObject() || handler_proto->IsNull())) { | 884 if (!(handler_proto->IsSpecObject() || handler_proto->IsNull())) { |
| 885 // TODO(cbruni): throw correct error message | |
| 882 THROW_NEW_ERROR(isolate, | 886 THROW_NEW_ERROR(isolate, |
| 883 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 887 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
| 884 handler, trap_name), | 888 handler, trap_name), |
| 885 Object); | 889 Object); |
| 886 } | 890 } |
| 887 // 9. Let extensibleTarget be ? IsExtensible(target). | 891 // 9. Let extensibleTarget be ? IsExtensible(target). |
| 888 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | 892 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); |
| 889 if (is_extensible.IsNothing()) return MaybeHandle<Object>(); | 893 if (is_extensible.IsNothing()) return MaybeHandle<Object>(); |
| 890 // 10. If extensibleTarget is true, return handlerProto. | 894 // 10. If extensibleTarget is true, return handlerProto. |
| 891 if (is_extensible.FromJust()) return handler_proto; | 895 if (is_extensible.FromJust()) return handler_proto; |
| 892 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | 896 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). |
| 893 Handle<Object> target_proto; | 897 Handle<Object> target_proto; |
| 894 ASSIGN_RETURN_ON_EXCEPTION(isolate, handler_proto, | 898 ASSIGN_RETURN_ON_EXCEPTION(isolate, handler_proto, |
| 895 Object::GetPrototype(isolate, target), Object); | 899 Object::GetPrototype(isolate, target), Object); |
| 896 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. | 900 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. |
| 897 if (!handler_proto->SameValue(*target_proto)) { | 901 if (!handler_proto->SameValue(*target_proto)) { |
| 898 THROW_NEW_ERROR(isolate, | 902 THROW_NEW_ERROR(isolate, |
| 899 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 903 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
| 900 handler, trap_name), | 904 handler, trap_name), |
| 901 Object); | 905 Object); |
| 902 } | 906 } |
| 903 // 13. Return handlerProto. | 907 // 13. Return handlerProto. |
| 904 return handler_proto; | 908 return handler_proto; |
| 905 } | 909 } |
| 906 | 910 |
| 907 | 911 |
| 912 // ES6: 9.5.2 [[SetPrototypeOf]] (V) | |
| 913 // static | |
| 914 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value, | |
| 915 bool from_javascript, | |
| 916 Object::ShouldThrow should_throw) { | |
| 917 Isolate* isolate = proxy->GetIsolate(); | |
| 918 Handle<JSReceiver> handle; | |
| 919 Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string(); | |
| 920 // 1. Assert: Either Type(V) is Object or Type(V) is Null. | |
| 921 DCHECK(value->IsSpecObject() || value->IsNull()); | |
| 922 // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O. | |
| 923 Handle<Object> raw_handler(proxy->handler(), isolate); | |
| 924 // 3. If handler is null, throw a TypeError exception. | |
| 925 // 4. Assert: Type(handler) is Object. | |
| 926 if (!raw_handler->IsSpecObject()) { | |
| 927 DCHECK(raw_handler->IsNull()); | |
| 928 DCHECK(proxy->target()->IsNull()); | |
| 929 isolate->Throw(*isolate->factory()->NewTypeError( | |
| 930 MessageTemplate::kProxyHandlerNonObject)); | |
| 931 return Nothing<bool>(); | |
| 932 } | |
| 933 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); | |
| 934 // 5. Let target be the value of the [[ProxyTarget]] internal slot. | |
| 935 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); | |
| 936 // 6. Let trap be ? GetMethod(handler, "getPrototypeOf"). | |
| 937 Handle<Object> trap; | |
| 938 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 939 isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>()); | |
| 940 // 7. If trap is undefined, then return target.[[SetPrototypeOf]](). | |
| 941 if (trap->IsUndefined()) { | |
| 942 return JSReceiver::SetPrototype(target, value, from_javascript, | |
| 943 should_throw); | |
| 944 } | |
| 945 // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)). | |
| 946 Handle<Object> argv[] = {target, value}; | |
| 947 Handle<Object> trap_result; | |
| 948 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 949 isolate, trap_result, | |
| 950 Execution::Call(isolate, trap, handler, arraysize(argv), argv), | |
| 951 Nothing<bool>()); | |
| 952 bool bool_trap_result = trap_result->BooleanValue(); | |
| 953 // 9. Let extensibleTarget be ? IsExtensible(target). | |
| 954 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | |
| 955 if (is_extensible.IsNothing()) return Nothing<bool>(); | |
| 956 // 10. If extensibleTarget is true, return booleanTrapResult. | |
| 957 if (is_extensible.FromJust()) return Just(bool_trap_result); | |
| 958 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | |
| 959 Handle<Object> target_proto; | |
| 960 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto, | |
| 961 Object::GetPrototype(isolate, target), | |
| 962 Nothing<bool>()); | |
| 963 // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false, | |
| 964 // throw a TypeError exception. | |
| 965 if (bool_trap_result && !value->SameValue(*target_proto)) { | |
| 966 isolate->Throw(*isolate->factory()->NewTypeError( | |
| 967 MessageTemplate::kObjectSetPrototypeNotExtensible)); | |
| 968 } | |
| 969 // 13. Return booleanTrapResult. | |
| 970 return Just(bool_trap_result); | |
| 971 } | |
| 972 | |
| 908 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy, | 973 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy, |
| 909 Handle<Object> receiver, | 974 Handle<Object> receiver, |
| 910 Handle<Name> name) { | 975 Handle<Name> name) { |
| 911 Isolate* isolate = proxy->GetIsolate(); | 976 Isolate* isolate = proxy->GetIsolate(); |
| 912 | 977 |
| 913 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 978 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 914 if (name->IsSymbol()) return isolate->factory()->undefined_value(); | 979 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
| 915 | 980 |
| 916 Handle<Object> args[] = { receiver, name }; | 981 Handle<Object> args[] = { receiver, name }; |
| 917 return CallTrap( | 982 return CallTrap( |
| (...skipping 13030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13948 TransitionArray::PutPrototypeTransition(map, prototype, new_map); | 14013 TransitionArray::PutPrototypeTransition(map, prototype, new_map); |
| 13949 Map::SetPrototype(new_map, prototype, mode); | 14014 Map::SetPrototype(new_map, prototype, mode); |
| 13950 } | 14015 } |
| 13951 return new_map; | 14016 return new_map; |
| 13952 } | 14017 } |
| 13953 | 14018 |
| 13954 | 14019 |
| 13955 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object, | 14020 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object, |
| 13956 Handle<Object> value, bool from_javascript, | 14021 Handle<Object> value, bool from_javascript, |
| 13957 ShouldThrow should_throw) { | 14022 ShouldThrow should_throw) { |
| 13958 if (!object->IsJSObject()) return Just(false); | 14023 if (!object->IsJSReceiver()) return Just(false); |
|
neis
2015/11/16 19:09:53
What's the motivation for this?
| |
| 13959 // TODO(neis): Deal with proxies. | 14024 if (object->IsJSProxy()) { |
| 14025 return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value, | |
| 14026 from_javascript, should_throw); | |
| 14027 } | |
| 13960 return JSObject::SetPrototype(Handle<JSObject>::cast(object), value, | 14028 return JSObject::SetPrototype(Handle<JSObject>::cast(object), value, |
| 13961 from_javascript, should_throw); | 14029 from_javascript, should_throw); |
| 13962 } | 14030 } |
| 13963 | 14031 |
| 13964 | 14032 |
| 13965 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, | 14033 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
| 13966 Handle<Object> value, bool from_javascript, | 14034 Handle<Object> value, bool from_javascript, |
| 13967 ShouldThrow should_throw) { | 14035 ShouldThrow should_throw) { |
| 13968 Isolate* isolate = object->GetIsolate(); | 14036 Isolate* isolate = object->GetIsolate(); |
| 13969 | 14037 |
| (...skipping 3965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 17935 if (cell->value() != *new_value) { | 18003 if (cell->value() != *new_value) { |
| 17936 cell->set_value(*new_value); | 18004 cell->set_value(*new_value); |
| 17937 Isolate* isolate = cell->GetIsolate(); | 18005 Isolate* isolate = cell->GetIsolate(); |
| 17938 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18006 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 17939 isolate, DependentCode::kPropertyCellChangedGroup); | 18007 isolate, DependentCode::kPropertyCellChangedGroup); |
| 17940 } | 18008 } |
| 17941 } | 18009 } |
| 17942 | 18010 |
| 17943 } // namespace internal | 18011 } // namespace internal |
| 17944 } // namespace v8 | 18012 } // namespace v8 |
| OLD | NEW |