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 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 // TODO(dcarney): this should just be read from the symbol registry so as not | 617 // TODO(dcarney): this should just be read from the symbol registry so as not |
618 // to be context dependent. | 618 // to be context dependent. |
619 auto key = isolate->factory()->promise_status_symbol(); | 619 auto key = isolate->factory()->promise_status_symbol(); |
620 // Shouldn't be possible to throw here. | 620 // Shouldn't be possible to throw here. |
621 return JSObject::HasRealNamedProperty(js_object, key).FromJust(); | 621 return JSObject::HasRealNamedProperty(js_object, key).FromJust(); |
622 } | 622 } |
623 | 623 |
624 | 624 |
625 // static | 625 // static |
626 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver, | 626 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver, |
627 Handle<Name> name) { | 627 Handle<Name> name, |
628 ShouldThrow should_throw) { | |
628 Handle<Object> func; | 629 Handle<Object> func; |
629 Isolate* isolate = receiver->GetIsolate(); | 630 Isolate* isolate = receiver->GetIsolate(); |
630 ASSIGN_RETURN_ON_EXCEPTION(isolate, func, | 631 // TODO(cbruni,neis): Propagage should_throw here. |
Toon Verwaest
2015/11/13 17:28:21
Propagate
| |
631 JSReceiver::GetProperty(receiver, name), Object); | 632 if (!JSReceiver::GetProperty(receiver, name).ToHandle(&func)) { |
633 return MaybeHandle<Object>(); | |
634 } | |
632 if (func->IsNull() || func->IsUndefined()) { | 635 if (func->IsNull() || func->IsUndefined()) { |
633 return isolate->factory()->undefined_value(); | 636 return isolate->factory()->undefined_value(); |
634 } | 637 } |
635 if (!func->IsCallable()) { | 638 if (!func->IsCallable()) { |
636 // TODO(bmeurer): Better error message here? | 639 // TODO(bmeurer): Better error message here? |
Toon Verwaest
2015/11/13 17:28:21
The spec says you actually have to throw a TypeErr
| |
637 THROW_NEW_ERROR(isolate, | 640 if (should_throw == Object::THROW_ON_ERROR) { |
638 NewTypeError(MessageTemplate::kCalledNonCallable, func), | 641 THROW_NEW_ERROR(isolate, |
639 Object); | 642 NewTypeError(MessageTemplate::kCalledNonCallable, func), |
643 Object); | |
644 } else { | |
645 return MaybeHandle<Object>(); | |
646 } | |
640 } | 647 } |
641 return func; | 648 return func; |
642 } | 649 } |
643 | 650 |
644 | 651 |
645 // static | 652 // static |
646 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) { | 653 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) { |
647 for (; it->IsFound(); it->Next()) { | 654 for (; it->IsFound(); it->Next()) { |
648 switch (it->state()) { | 655 switch (it->state()) { |
649 case LookupIterator::NOT_FOUND: | 656 case LookupIterator::NOT_FOUND: |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); | 845 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); |
839 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 846 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
840 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( | 847 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( |
841 elems, isolate->factory()->fixed_array_map()); | 848 elems, isolate->factory()->fixed_array_map()); |
842 object->set_elements(*writable_elems); | 849 object->set_elements(*writable_elems); |
843 isolate->counters()->cow_arrays_converted()->Increment(); | 850 isolate->counters()->cow_arrays_converted()->Increment(); |
844 return writable_elems; | 851 return writable_elems; |
845 } | 852 } |
846 | 853 |
847 | 854 |
848 // ES6 9.5.1 | 855 // ES6: Section 9.5.1 [[GetPrototypeOf]] ( ) |
849 // static | 856 // static |
850 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { | 857 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) { |
851 Isolate* isolate = proxy->GetIsolate(); | 858 Isolate* isolate = proxy->GetIsolate(); |
859 Handle<Object> trap; | |
860 Handle<JSReceiver> handle; | |
861 Handle<Name> trap_name = isolate->factory()->getPrototypeOf_string(); | |
852 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. | 862 // 1. Let handler be the value of the [[ProxyHandler]] internal slot. |
853 Handle<Object> raw_handler(proxy->handler(), isolate); | 863 Handle<Object> raw_handler(proxy->handler(), isolate); |
854 // 2. If handler is null, throw a TypeError exception. | 864 // 2. If handler is null, throw a TypeError exception. |
855 // 3. Assert: Type(handler) is Object. | 865 // 3. Assert: Type(handler) is Object. |
856 if (!raw_handler->IsSpecObject()) { | 866 if (!raw_handler->IsSpecObject()) { |
867 DCHECK(raw_handler->IsNull()); | |
868 DCHECK(proxy->target()->IsNull()); | |
857 // TODO(cbruni): Throw correct error message. | 869 // TODO(cbruni): Throw correct error message. |
858 THROW_NEW_ERROR( | 870 THROW_NEW_ERROR( |
859 isolate, NewTypeError(MessageTemplate::kProxyHandlerNonObject), Object); | 871 isolate, NewTypeError(MessageTemplate::kProxyHandlerNonObject), Object); |
860 } | 872 } |
861 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); | 873 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); |
862 // 4. Let target be the value of the [[ProxyTarget]] internal slot. | 874 // 4. Let target be the value of the [[ProxyTarget]] internal slot. |
863 // TODO(cbruni): Change target type to JSReceiver by default. | 875 // TODO(cbruni): Change target type to JSReceiver by default. |
864 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); | 876 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); |
865 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). | 877 // 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), | 878 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name), |
869 Object); | 879 Object); |
870 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). | 880 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). |
871 if (trap->IsUndefined()) { | 881 if (trap->IsUndefined()) { |
872 return Object::GetPrototype(isolate, target); | 882 return Object::GetPrototype(isolate, target); |
873 } | 883 } |
874 // 7. Let handlerProto be ? Call(trap, handler, «target»). | 884 // 7. Let handlerProto be ? Call(trap, handler, «target»). |
875 Handle<Object> argv[] = {target}; | 885 Handle<Object> argv[] = {target}; |
876 Handle<Object> handler_proto; | 886 Handle<Object> handler_proto; |
877 ASSIGN_RETURN_ON_EXCEPTION( | 887 ASSIGN_RETURN_ON_EXCEPTION( |
878 isolate, handler_proto, | 888 isolate, handler_proto, |
879 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); | 889 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); |
880 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. | 890 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. |
881 if (!(handler_proto->IsSpecObject() || handler_proto->IsNull())) { | 891 if (!(handler_proto->IsSpecObject() || handler_proto->IsNull())) { |
892 // TODO(cbruni): throw correct error message | |
882 THROW_NEW_ERROR(isolate, | 893 THROW_NEW_ERROR(isolate, |
883 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 894 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
884 handler, trap_name), | 895 handler, trap_name), |
885 Object); | 896 Object); |
886 } | 897 } |
887 // 9. Let extensibleTarget be ? IsExtensible(target). | 898 // 9. Let extensibleTarget be ? IsExtensible(target). |
888 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | 899 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); |
889 if (is_extensible.IsNothing()) return MaybeHandle<Object>(); | 900 if (is_extensible.IsNothing()) return MaybeHandle<Object>(); |
890 // 10. If extensibleTarget is true, return handlerProto. | 901 // 10. If extensibleTarget is true, return handlerProto. |
891 if (is_extensible.FromJust()) return handler_proto; | 902 if (is_extensible.FromJust()) return handler_proto; |
892 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | 903 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). |
893 Handle<Object> target_proto; | 904 Handle<Object> target_proto; |
894 ASSIGN_RETURN_ON_EXCEPTION(isolate, handler_proto, | 905 ASSIGN_RETURN_ON_EXCEPTION(isolate, handler_proto, |
895 Object::GetPrototype(isolate, target), Object); | 906 Object::GetPrototype(isolate, target), Object); |
896 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. | 907 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. |
897 if (!handler_proto->SameValue(*target_proto)) { | 908 if (!handler_proto->SameValue(*target_proto)) { |
898 THROW_NEW_ERROR(isolate, | 909 THROW_NEW_ERROR(isolate, |
899 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, | 910 NewTypeError(MessageTemplate::kProxyHandlerTrapMissing, |
900 handler, trap_name), | 911 handler, trap_name), |
901 Object); | 912 Object); |
902 } | 913 } |
903 // 13. Return handlerProto. | 914 // 13. Return handlerProto. |
904 return handler_proto; | 915 return handler_proto; |
905 } | 916 } |
906 | 917 |
907 | 918 |
919 // ES6: 9.5.2 [[SetPrototypeOf]] (V) | |
920 // static | |
921 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value, | |
922 bool from_javascript, | |
923 Object::ShouldThrow should_throw) { | |
924 Isolate* isolate = proxy->GetIsolate(); | |
925 Handle<Object> trap; | |
926 Handle<JSReceiver> handle; | |
927 Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string(); | |
928 // 1. Assert: Either Type(V) is Object or Type(V) is Null. | |
929 if (!(value->IsSpecObject() || value->IsNull())) { | |
930 RETURN_FAILURE(isolate, should_throw, | |
931 NewTypeError(MessageTemplate::kProtoObjectOrNull, value)); | |
932 } | |
933 Handle<Object> raw_handler(proxy->handler(), isolate); | |
934 // 2. If handler is null, throw a TypeError exception. | |
935 // 3. Assert: Type(handler) is Object. | |
936 if (!raw_handler->IsSpecObject()) { | |
937 DCHECK(raw_handler->IsNull()); | |
938 DCHECK(proxy->target()->IsNull()); | |
939 // TODO(cbruni): use proper error message here. | |
940 RETURN_FAILURE(isolate, should_throw, | |
941 NewTypeError(MessageTemplate::kProxyHandlerNonObject)); | |
942 } | |
943 Handle<JSReceiver> handler = Handle<JSReceiver>::cast(raw_handler); | |
944 // 4. Let target be the value of the [[ProxyTarget]] internal slot. | |
945 Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate); | |
946 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). | |
947 if (!Object::GetMethod(handler, trap_name, should_throw).ToHandle(&trap)) { | |
948 if (should_throw == Object::DONT_THROW) { | |
949 return Just(false); | |
950 } else { | |
951 return Nothing<bool>(); | |
952 } | |
953 } | |
954 // 7. If trap is undefined, then return target.[[SetPrototypeOf]](). | |
955 if (trap->IsUndefined()) { | |
956 return JSReceiver::SetPrototype(target, value, from_javascript, | |
957 should_throw); | |
958 } | |
959 // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, «target, V»)). | |
960 Handle<Object> argv[] = {target, value}; | |
961 Handle<Object> trap_result; | |
962 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
963 isolate, trap_result, | |
964 Execution::Call(isolate, trap, handler, arraysize(argv), argv), | |
965 Nothing<bool>()); | |
966 Maybe<bool> result = Just(trap_result->BooleanValue()); | |
967 // 9. Let extensibleTarget be ? IsExtensible(target). | |
968 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | |
969 if (is_extensible.IsNothing()) return Nothing<bool>(); | |
970 // 10. If extensibleTarget is true, return booleanTrapResult. | |
971 if (is_extensible.FromJust()) return result; | |
972 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | |
973 Handle<Object> target_proto; | |
974 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto, | |
975 Object::GetPrototype(isolate, target), | |
976 Nothing<bool>()); | |
977 // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false, | |
978 if (result.FromJust() && !value->SameValue(*target_proto)) { | |
979 RETURN_FAILURE( | |
980 isolate, should_throw, | |
981 NewTypeError(MessageTemplate::kObjectSetPrototypeNotExtensible)); | |
982 } | |
983 // 13. Return booleanTrapResult. | |
984 return result; | |
985 } | |
986 | |
908 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy, | 987 MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy, |
909 Handle<Object> receiver, | 988 Handle<Object> receiver, |
910 Handle<Name> name) { | 989 Handle<Name> name) { |
911 Isolate* isolate = proxy->GetIsolate(); | 990 Isolate* isolate = proxy->GetIsolate(); |
912 | 991 |
913 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 992 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
914 if (name->IsSymbol()) return isolate->factory()->undefined_value(); | 993 if (name->IsSymbol()) return isolate->factory()->undefined_value(); |
915 | 994 |
916 Handle<Object> args[] = { receiver, name }; | 995 Handle<Object> args[] = { receiver, name }; |
917 return CallTrap( | 996 return CallTrap( |
(...skipping 13030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13948 TransitionArray::PutPrototypeTransition(map, prototype, new_map); | 14027 TransitionArray::PutPrototypeTransition(map, prototype, new_map); |
13949 Map::SetPrototype(new_map, prototype, mode); | 14028 Map::SetPrototype(new_map, prototype, mode); |
13950 } | 14029 } |
13951 return new_map; | 14030 return new_map; |
13952 } | 14031 } |
13953 | 14032 |
13954 | 14033 |
13955 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object, | 14034 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object, |
13956 Handle<Object> value, bool from_javascript, | 14035 Handle<Object> value, bool from_javascript, |
13957 ShouldThrow should_throw) { | 14036 ShouldThrow should_throw) { |
13958 if (!object->IsJSObject()) return Just(false); | 14037 if (!object->IsJSReceiver()) return Just(false); |
13959 // TODO(neis): Deal with proxies. | 14038 if (object->IsJSProxy()) { |
14039 return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value, | |
14040 from_javascript, should_throw); | |
14041 } | |
13960 return JSObject::SetPrototype(Handle<JSObject>::cast(object), value, | 14042 return JSObject::SetPrototype(Handle<JSObject>::cast(object), value, |
13961 from_javascript, should_throw); | 14043 from_javascript, should_throw); |
13962 } | 14044 } |
13963 | 14045 |
13964 | 14046 |
13965 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, | 14047 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
13966 Handle<Object> value, bool from_javascript, | 14048 Handle<Object> value, bool from_javascript, |
13967 ShouldThrow should_throw) { | 14049 ShouldThrow should_throw) { |
13968 Isolate* isolate = object->GetIsolate(); | 14050 Isolate* isolate = object->GetIsolate(); |
13969 | 14051 |
(...skipping 3965 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
17935 if (cell->value() != *new_value) { | 18017 if (cell->value() != *new_value) { |
17936 cell->set_value(*new_value); | 18018 cell->set_value(*new_value); |
17937 Isolate* isolate = cell->GetIsolate(); | 18019 Isolate* isolate = cell->GetIsolate(); |
17938 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18020 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17939 isolate, DependentCode::kPropertyCellChangedGroup); | 18021 isolate, DependentCode::kPropertyCellChangedGroup); |
17940 } | 18022 } |
17941 } | 18023 } |
17942 | 18024 |
17943 } // namespace internal | 18025 } // namespace internal |
17944 } // namespace v8 | 18026 } // namespace v8 |
OLD | NEW |