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 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 |