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

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/V8Binding.h

Issue 2810843002: bindings: Make the sequence conversion code more complaint with WebIDL. (Closed)
Patch Set: Adjust even more tests Created 3 years, 8 months 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Ericsson AB. All rights reserved. 3 * Copyright (C) 2012 Ericsson AB. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 NodeFilter* ToNodeFilter(v8::Local<v8::Value>, 666 NodeFilter* ToNodeFilter(v8::Local<v8::Value>,
667 v8::Local<v8::Object>, 667 v8::Local<v8::Object>,
668 ScriptState*); 668 ScriptState*);
669 XPathNSResolver* ToXPathNSResolver(ScriptState*, v8::Local<v8::Value>); 669 XPathNSResolver* ToXPathNSResolver(ScriptState*, v8::Local<v8::Value>);
670 670
671 bool ToV8Sequence(v8::Local<v8::Value>, 671 bool ToV8Sequence(v8::Local<v8::Value>,
672 uint32_t& length, 672 uint32_t& length,
673 v8::Isolate*, 673 v8::Isolate*,
674 ExceptionState&); 674 ExceptionState&);
675 675
676 template <typename T>
677 HeapVector<Member<T>> ToMemberNativeArray(v8::Local<v8::Value> value,
678 int argument_index,
679 v8::Isolate* isolate,
680 ExceptionState& exception_state) {
681 v8::Local<v8::Value> v8_value(v8::Local<v8::Value>::New(isolate, value));
682 uint32_t length = 0;
683 if (value->IsArray()) {
684 length = v8::Local<v8::Array>::Cast(v8_value)->Length();
685 } else if (!ToV8Sequence(value, length, isolate, exception_state)) {
686 if (!exception_state.HadException())
687 exception_state.ThrowTypeError(
688 ExceptionMessages::NotAnArrayTypeArgumentOrValue(argument_index));
689 return HeapVector<Member<T>>();
690 }
691
692 using VectorType = HeapVector<Member<T>>;
693 if (length > VectorType::MaxCapacity()) {
694 exception_state.ThrowRangeError("Array length exceeds supported limit.");
695 return VectorType();
696 }
697
698 VectorType result;
699 result.ReserveInitialCapacity(length);
700 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8_value);
701 v8::TryCatch block(isolate);
702 for (uint32_t i = 0; i < length; ++i) {
703 v8::Local<v8::Value> element;
704 if (!V8Call(object->Get(isolate->GetCurrentContext(), i), element, block)) {
705 exception_state.RethrowV8Exception(block.Exception());
706 return VectorType();
707 }
708 if (V8TypeOf<T>::Type::hasInstance(element, isolate)) {
709 v8::Local<v8::Object> element_object =
710 v8::Local<v8::Object>::Cast(element);
711 result.UncheckedAppend(V8TypeOf<T>::Type::toImpl(element_object));
712 } else {
713 exception_state.ThrowTypeError("Invalid Array element type");
714 return VectorType();
715 }
716 }
717 return result;
718 }
719
720 template <typename T>
721 HeapVector<Member<T>> ToMemberNativeArray(v8::Local<v8::Value> value,
722 const String& property_name,
723 v8::Isolate* isolate,
724 ExceptionState& exception_state) {
725 v8::Local<v8::Value> v8_value(v8::Local<v8::Value>::New(isolate, value));
726 uint32_t length = 0;
727 if (value->IsArray()) {
728 length = v8::Local<v8::Array>::Cast(v8_value)->Length();
729 } else if (!ToV8Sequence(value, length, isolate, exception_state)) {
730 if (!exception_state.HadException())
731 exception_state.ThrowTypeError(
732 ExceptionMessages::NotASequenceTypeProperty(property_name));
733 return HeapVector<Member<T>>();
734 }
735
736 using VectorType = HeapVector<Member<T>>;
737 if (length > VectorType::MaxCapacity()) {
738 exception_state.ThrowRangeError("Array length exceeds supported limit.");
739 return VectorType();
740 }
741
742 VectorType result;
743 result.ReserveInitialCapacity(length);
744 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8_value);
745 v8::TryCatch block(isolate);
746 for (uint32_t i = 0; i < length; ++i) {
747 v8::Local<v8::Value> element;
748 if (!V8Call(object->Get(isolate->GetCurrentContext(), i), element, block)) {
749 exception_state.RethrowV8Exception(block.Exception());
750 return VectorType();
751 }
752 if (V8TypeOf<T>::Type::hasInstance(element, isolate)) {
753 v8::Local<v8::Object> element_object =
754 v8::Local<v8::Object>::Cast(element);
755 result.UncheckedAppend(V8TypeOf<T>::Type::toImpl(element_object));
756 } else {
757 exception_state.ThrowTypeError("Invalid Array element type");
758 return VectorType();
759 }
760 }
761 return result;
762 }
763
764 // Converts a JavaScript value to an array as per the Web IDL specification:
765 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array
766 template <typename VectorType,
767 typename ValueType = typename VectorType::ValueType>
768 VectorType ToImplArray(v8::Local<v8::Value> value,
769 int argument_index,
770 v8::Isolate* isolate,
771 ExceptionState& exception_state) {
772 typedef NativeValueTraits<ValueType> TraitsType;
773
774 uint32_t length = 0;
775 if (value->IsArray()) {
776 length = v8::Local<v8::Array>::Cast(value)->Length();
777 } else if (!ToV8Sequence(value, length, isolate, exception_state)) {
778 if (!exception_state.HadException())
779 exception_state.ThrowTypeError(
780 ExceptionMessages::NotAnArrayTypeArgumentOrValue(argument_index));
781 return VectorType();
782 }
783
784 if (length > VectorType::MaxCapacity()) {
785 exception_state.ThrowRangeError("Array length exceeds supported limit.");
786 return VectorType();
787 }
788
789 VectorType result;
790 result.ReserveInitialCapacity(length);
791 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
792 v8::TryCatch block(isolate);
793 for (uint32_t i = 0; i < length; ++i) {
794 v8::Local<v8::Value> element;
795 if (!V8Call(object->Get(isolate->GetCurrentContext(), i), element, block)) {
796 exception_state.RethrowV8Exception(block.Exception());
797 return VectorType();
798 }
799 result.UncheckedAppend(
800 TraitsType::NativeValue(isolate, element, exception_state));
801 if (exception_state.HadException())
802 return VectorType();
803 }
804 return result;
805 }
806
807 template <typename VectorType>
808 VectorType ToImplArray(const Vector<ScriptValue>& value,
809 v8::Isolate* isolate,
810 ExceptionState& exception_state) {
811 using ValueType = typename VectorType::ValueType;
812 using TraitsType = NativeValueTraits<ValueType>;
813
814 if (value.size() > VectorType::MaxCapacity()) {
815 exception_state.ThrowRangeError("Array length exceeds supported limit.");
816 return VectorType();
817 }
818
819 VectorType result;
820 result.ReserveInitialCapacity(value.size());
821 for (unsigned i = 0; i < value.size(); ++i) {
822 result.UncheckedAppend(
823 TraitsType::NativeValue(isolate, value[i].V8Value(), exception_state));
824 if (exception_state.HadException())
825 return VectorType();
826 }
827 return result;
828 }
829
830 template <typename VectorType> 676 template <typename VectorType>
831 VectorType ToImplArguments(const v8::FunctionCallbackInfo<v8::Value>& info, 677 VectorType ToImplArguments(const v8::FunctionCallbackInfo<v8::Value>& info,
832 int start_index, 678 int start_index,
833 ExceptionState& exception_state) { 679 ExceptionState& exception_state) {
834 using ValueType = typename VectorType::ValueType; 680 using ValueType = typename VectorType::ValueType;
835 using TraitsType = NativeValueTraits<ValueType>; 681 using TraitsType = NativeValueTraits<ValueType>;
836 682
837 int length = info.Length(); 683 int length = info.Length();
838 VectorType result; 684 VectorType result;
839 if (start_index < length) { 685 if (start_index < length) {
(...skipping 10 matching lines...) Expand all
850 } 696 }
851 } 697 }
852 return result; 698 return result;
853 } 699 }
854 700
855 // Gets an iterator from an Object. 701 // Gets an iterator from an Object.
856 CORE_EXPORT v8::Local<v8::Object> GetEsIterator(v8::Isolate*, 702 CORE_EXPORT v8::Local<v8::Object> GetEsIterator(v8::Isolate*,
857 v8::Local<v8::Object>, 703 v8::Local<v8::Object>,
858 ExceptionState&); 704 ExceptionState&);
859 705
860 // Validates that the passed object is a sequence type per WebIDL spec 706 // Validates that the passed object is a sequence type per the WebIDL spec: it
861 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence 707 // has a callable @iterator.
862 inline bool ToV8Sequence(v8::Local<v8::Value> value, 708 // https://heycam.github.io/webidl/#es-sequence
863 uint32_t& length, 709 CORE_EXPORT bool IsV8Sequence(v8::Isolate*,
864 v8::Isolate* isolate, 710 v8::Local<v8::Value>,
865 ExceptionState& exception_state) { 711 ExceptionState&);
866 // Attempt converting to a sequence if the value is not already an array but
867 // is any kind of object except for a native Date object or a native RegExp
868 // object.
869 ASSERT(!value->IsArray());
870 // FIXME: Do we really need to special case Date and RegExp object?
871 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806
872 if (!value->IsObject() || value->IsDate() || value->IsRegExp()) {
873 // The caller is responsible for reporting a TypeError.
874 return false;
875 }
876
877 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
878 v8::Local<v8::String> length_symbol = V8AtomicString(isolate, "length");
879
880 // FIXME: The specification states that the length property should be used as
881 // fallback, if value is not a platform object that supports indexed
882 // properties. If it supports indexed properties, length should actually be
883 // one greater than value's maximum indexed property index.
884 v8::TryCatch block(isolate);
885 v8::Local<v8::Value> length_value;
886 if (!V8Call(object->Get(isolate->GetCurrentContext(), length_symbol),
887 length_value, block)) {
888 exception_state.RethrowV8Exception(block.Exception());
889 return false;
890 }
891
892 if (length_value->IsUndefined() || length_value->IsNull()) {
893 // The caller is responsible for reporting a TypeError.
894 return false;
895 }
896
897 uint32_t sequence_length;
898 if (!V8Call(length_value->Uint32Value(isolate->GetCurrentContext()),
899 sequence_length, block)) {
900 exception_state.RethrowV8Exception(block.Exception());
901 return false;
902 }
903
904 length = sequence_length;
905 return true;
906 }
907 712
908 // TODO(rakuco): remove the specializations below (and consequently the 713 // TODO(rakuco): remove the specializations below (and consequently the
909 // non-IDLBase version of NativeValueTraitsBase) once we manage to convert all 714 // non-IDLBase version of NativeValueTraitsBase) once we manage to convert all
910 // uses of NativeValueTraits to types that derive from IDLBase or for generated 715 // uses of NativeValueTraits to types that derive from IDLBase or for generated
911 // IDL interfaces/dictionaries/unions. 716 // IDL interfaces/dictionaries/unions.
912 template <> 717 template <>
913 struct NativeValueTraits<String> { 718 struct NativeValueTraits<String> {
914 static inline String NativeValue(v8::Isolate* isolate, 719 static inline String NativeValue(v8::Isolate* isolate,
915 v8::Local<v8::Value> value, 720 v8::Local<v8::Value> value,
916 ExceptionState& exception_state) { 721 ExceptionState& exception_state) {
917 V8StringResource<> string_value(value); 722 V8StringResource<> string_value(value);
918 if (!string_value.Prepare(exception_state)) 723 if (!string_value.Prepare(exception_state))
919 return String(); 724 return String();
920 return string_value; 725 return string_value;
921 } 726 }
922 }; 727 };
923 728
924 template <> 729 template <>
925 struct NativeValueTraits<AtomicString> { 730 struct NativeValueTraits<v8::Local<v8::Value>>
926 static inline AtomicString NativeValue(v8::Isolate* isolate, 731 : public NativeValueTraitsBase<v8::Local<v8::Value>> {
927 v8::Local<v8::Value> value,
928 ExceptionState& exception_state) {
929 V8StringResource<> string_value(value);
930 if (!string_value.Prepare(exception_state))
931 return AtomicString();
932 return string_value;
933 }
934 };
935
936 template <>
937 struct NativeValueTraits<int> {
938 static inline int NativeValue(v8::Isolate* isolate,
939 v8::Local<v8::Value> value,
940 ExceptionState& exception_state) {
941 return ToInt32(isolate, value, kNormalConversion, exception_state);
942 }
943 };
944
945 template <>
946 struct NativeValueTraits<unsigned> {
947 static inline unsigned NativeValue(v8::Isolate* isolate,
948 v8::Local<v8::Value> value,
949 ExceptionState& exception_state) {
950 return ToUInt32(isolate, value, kNormalConversion, exception_state);
951 }
952 };
953
954 template <>
955 struct NativeValueTraits<float> {
956 static inline float NativeValue(v8::Isolate* isolate,
957 v8::Local<v8::Value> value,
958 ExceptionState& exception_state) {
959 return ToFloat(isolate, value, exception_state);
960 }
961 };
962
963 template <>
964 struct NativeValueTraits<double> {
965 static inline double NativeValue(v8::Isolate* isolate,
966 v8::Local<v8::Value> value,
967 ExceptionState& exception_state) {
968 return ToDouble(isolate, value, exception_state);
969 }
970 };
971
972 template <>
973 struct NativeValueTraits<v8::Local<v8::Value>> {
974 static inline v8::Local<v8::Value> NativeValue( 732 static inline v8::Local<v8::Value> NativeValue(
975 v8::Isolate* isolate, 733 v8::Isolate* isolate,
976 v8::Local<v8::Value> value, 734 v8::Local<v8::Value> value,
977 ExceptionState& exception_state) { 735 ExceptionState& exception_state) {
978 return value; 736 return value;
979 } 737 }
980 }; 738 };
981 739
982 template <>
983 struct NativeValueTraits<ScriptValue> {
984 static inline ScriptValue NativeValue(v8::Isolate* isolate,
985 v8::Local<v8::Value> value,
986 ExceptionState& exception_state) {
987 return ScriptValue(ScriptState::Current(isolate), value);
988 }
989 };
990
991 template <typename T>
992 struct NativeValueTraits<Vector<T>> {
993 static inline Vector<T> NativeValue(v8::Isolate* isolate,
994 v8::Local<v8::Value> value,
995 ExceptionState& exception_state) {
996 return ToImplArray<Vector<T>>(value, 0, isolate, exception_state);
997 }
998 };
999
1000 CORE_EXPORT v8::Isolate* ToIsolate(ExecutionContext*); 740 CORE_EXPORT v8::Isolate* ToIsolate(ExecutionContext*);
1001 CORE_EXPORT v8::Isolate* ToIsolate(LocalFrame*); 741 CORE_EXPORT v8::Isolate* ToIsolate(LocalFrame*);
1002 742
1003 CORE_EXPORT DOMWindow* ToDOMWindow(v8::Isolate*, v8::Local<v8::Value>); 743 CORE_EXPORT DOMWindow* ToDOMWindow(v8::Isolate*, v8::Local<v8::Value>);
1004 LocalDOMWindow* ToLocalDOMWindow(v8::Local<v8::Context>); 744 LocalDOMWindow* ToLocalDOMWindow(v8::Local<v8::Context>);
1005 LocalDOMWindow* EnteredDOMWindow(v8::Isolate*); 745 LocalDOMWindow* EnteredDOMWindow(v8::Isolate*);
1006 CORE_EXPORT LocalDOMWindow* CurrentDOMWindow(v8::Isolate*); 746 CORE_EXPORT LocalDOMWindow* CurrentDOMWindow(v8::Isolate*);
1007 CORE_EXPORT ExecutionContext* ToExecutionContext(v8::Local<v8::Context>); 747 CORE_EXPORT ExecutionContext* ToExecutionContext(v8::Local<v8::Context>);
1008 CORE_EXPORT void RegisterToExecutionContextForModules(ExecutionContext* ( 748 CORE_EXPORT void RegisterToExecutionContextForModules(ExecutionContext* (
1009 *to_execution_context_for_modules)(v8::Local<v8::Context>)); 749 *to_execution_context_for_modules)(v8::Local<v8::Context>));
(...skipping 24 matching lines...) Expand all
1034 CORE_EXPORT LocalFrame* ToLocalFrameIfNotDetached(v8::Local<v8::Context>); 774 CORE_EXPORT LocalFrame* ToLocalFrameIfNotDetached(v8::Local<v8::Context>);
1035 775
1036 // If 'storage' is non-null, it must be large enough to copy all bytes in the 776 // If 'storage' is non-null, it must be large enough to copy all bytes in the
1037 // array buffer view into it. Use allocateFlexibleArrayBufferStorage(v8Value) 777 // array buffer view into it. Use allocateFlexibleArrayBufferStorage(v8Value)
1038 // to allocate it using alloca() in the callers stack frame. 778 // to allocate it using alloca() in the callers stack frame.
1039 CORE_EXPORT void ToFlexibleArrayBufferView(v8::Isolate*, 779 CORE_EXPORT void ToFlexibleArrayBufferView(v8::Isolate*,
1040 v8::Local<v8::Value>, 780 v8::Local<v8::Value>,
1041 FlexibleArrayBufferView&, 781 FlexibleArrayBufferView&,
1042 void* storage = nullptr); 782 void* storage = nullptr);
1043 783
1044 // Converts a V8 value to an array (an IDL sequence) as per the WebIDL
1045 // specification: http://heycam.github.io/webidl/#es-sequence
1046 template <typename VectorType>
1047 VectorType ToImplSequence(v8::Isolate* isolate,
1048 v8::Local<v8::Value> value,
1049 ExceptionState& exception_state) {
1050 using ValueType = typename VectorType::ValueType;
1051
1052 if (!value->IsObject() || value->IsRegExp()) {
1053 exception_state.ThrowTypeError(
1054 "The provided value cannot be converted to a sequence.");
1055 return VectorType();
1056 }
1057
1058 v8::TryCatch block(isolate);
1059 v8::Local<v8::Object> iterator =
1060 GetEsIterator(isolate, value.As<v8::Object>(), exception_state);
1061 if (exception_state.HadException())
1062 return VectorType();
1063
1064 v8::Local<v8::String> next_key = V8String(isolate, "next");
1065 v8::Local<v8::String> value_key = V8String(isolate, "value");
1066 v8::Local<v8::String> done_key = V8String(isolate, "done");
1067 v8::Local<v8::Context> context = isolate->GetCurrentContext();
1068 VectorType result;
1069 while (true) {
1070 v8::Local<v8::Value> next;
1071 if (!iterator->Get(context, next_key).ToLocal(&next)) {
1072 exception_state.RethrowV8Exception(block.Exception());
1073 return VectorType();
1074 }
1075 // TODO(bashi): Support callable objects.
1076 if (!next->IsObject() || !next.As<v8::Object>()->IsFunction()) {
1077 exception_state.ThrowTypeError("Iterator.next should be callable.");
1078 return VectorType();
1079 }
1080 v8::Local<v8::Value> next_result;
1081 if (!V8ScriptRunner::CallFunction(next.As<v8::Function>(),
1082 ToExecutionContext(context), iterator, 0,
1083 nullptr, isolate)
1084 .ToLocal(&next_result)) {
1085 exception_state.RethrowV8Exception(block.Exception());
1086 return VectorType();
1087 }
1088 if (!next_result->IsObject()) {
1089 exception_state.ThrowTypeError(
1090 "Iterator.next() did not return an object.");
1091 return VectorType();
1092 }
1093 v8::Local<v8::Object> result_object = next_result.As<v8::Object>();
1094 v8::Local<v8::Value> element;
1095 v8::Local<v8::Value> done;
1096 if (!result_object->Get(context, value_key).ToLocal(&element) ||
1097 !result_object->Get(context, done_key).ToLocal(&done)) {
1098 exception_state.RethrowV8Exception(block.Exception());
1099 return VectorType();
1100 }
1101 v8::Local<v8::Boolean> done_boolean;
1102 if (!done->ToBoolean(context).ToLocal(&done_boolean)) {
1103 exception_state.RethrowV8Exception(block.Exception());
1104 return VectorType();
1105 }
1106 if (done_boolean->Value())
1107 break;
1108 result.push_back(NativeValueTraits<ValueType>::NativeValue(
1109 isolate, element, exception_state));
1110 }
1111 return result;
1112 }
1113
1114 // If the current context causes out of memory, JavaScript setting 784 // If the current context causes out of memory, JavaScript setting
1115 // is disabled and it returns true. 785 // is disabled and it returns true.
1116 bool HandleOutOfMemory(); 786 bool HandleOutOfMemory();
1117 787
1118 inline bool IsUndefinedOrNull(v8::Local<v8::Value> value) { 788 inline bool IsUndefinedOrNull(v8::Local<v8::Value> value) {
1119 return value.IsEmpty() || value->IsNull() || value->IsUndefined(); 789 return value.IsEmpty() || value->IsNull() || value->IsUndefined();
1120 } 790 }
1121 v8::Local<v8::Function> GetBoundFunction(v8::Local<v8::Function>); 791 v8::Local<v8::Function> GetBoundFunction(v8::Local<v8::Function>);
1122 792
1123 // FIXME: This will be soon embedded in the generated code. 793 // FIXME: This will be soon embedded in the generated code.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 exception_state.ThrowTypeError( 862 exception_state.ThrowTypeError(
1193 "The provided ArrayBufferView value must not be shared."); 863 "The provided ArrayBufferView value must not be shared.");
1194 return NotSharedType(); 864 return NotSharedType();
1195 } 865 }
1196 return NotSharedType(dom_typed_array); 866 return NotSharedType(dom_typed_array);
1197 } 867 }
1198 868
1199 } // namespace blink 869 } // namespace blink
1200 870
1201 #endif // V8Binding_h 871 #endif // V8Binding_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698