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 |