Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: src/objects.cc

Issue 1439693002: [runtime] Support Proxy setPrototypeOf trap (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@2015-11-09_new_Proxy_1417063011
Patch Set: more tests Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-object.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698