OLD | NEW |
---|---|
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 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
754 } else { | 754 } else { |
755 exceptionState.throwTypeError("Invalid Array element type"); | 755 exceptionState.throwTypeError("Invalid Array element type"); |
756 return VectorType(); | 756 return VectorType(); |
757 } | 757 } |
758 } | 758 } |
759 return result; | 759 return result; |
760 } | 760 } |
761 | 761 |
762 // Converts a JavaScript value to an array as per the Web IDL specification: | 762 // Converts a JavaScript value to an array as per the Web IDL specification: |
763 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array | 763 // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array |
764 template <typename VectorType> | 764 template <typename VectorType, |
765 typename ValueType = typename VectorType::ValueType> | |
765 VectorType toImplArray(v8::Local<v8::Value> value, | 766 VectorType toImplArray(v8::Local<v8::Value> value, |
766 int argumentIndex, | 767 int argumentIndex, |
767 v8::Isolate* isolate, | 768 v8::Isolate* isolate, |
768 ExceptionState& exceptionState) { | 769 ExceptionState& exceptionState) { |
769 typedef typename VectorType::ValueType ValueType; | |
770 typedef NativeValueTraits<ValueType> TraitsType; | 770 typedef NativeValueTraits<ValueType> TraitsType; |
771 | 771 |
772 uint32_t length = 0; | 772 uint32_t length = 0; |
773 if (value->IsArray()) { | 773 if (value->IsArray()) { |
774 length = v8::Local<v8::Array>::Cast(value)->Length(); | 774 length = v8::Local<v8::Array>::Cast(value)->Length(); |
775 } else if (!toV8Sequence(value, length, isolate, exceptionState)) { | 775 } else if (!toV8Sequence(value, length, isolate, exceptionState)) { |
776 if (!exceptionState.hadException()) | 776 if (!exceptionState.hadException()) |
777 exceptionState.throwTypeError( | 777 exceptionState.throwTypeError( |
778 ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex)); | 778 ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex)); |
779 return VectorType(); | 779 return VectorType(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 if (!v8Call(lengthValue->Uint32Value(isolate->GetCurrentContext()), | 896 if (!v8Call(lengthValue->Uint32Value(isolate->GetCurrentContext()), |
897 sequenceLength, block)) { | 897 sequenceLength, block)) { |
898 exceptionState.rethrowV8Exception(block.Exception()); | 898 exceptionState.rethrowV8Exception(block.Exception()); |
899 return false; | 899 return false; |
900 } | 900 } |
901 | 901 |
902 length = sequenceLength; | 902 length = sequenceLength; |
903 return true; | 903 return true; |
904 } | 904 } |
905 | 905 |
906 WARN_UNUSED_RESULT CORE_EXPORT v8::MaybeLocal<v8::String> getStringValueInArray( | |
Yuki
2017/03/02 07:47:28
nit: I'm on the fence whether the name of |getStri
| |
907 v8::Local<v8::Context> context, | |
908 v8::Local<v8::Array> array, | |
909 uint32_t index); | |
910 | |
911 CORE_EXPORT bool isPropertyEnumerable(v8::Isolate* isolate, | |
912 v8::Local<v8::Value> descriptor, | |
913 ExceptionState& exceptionState); | |
914 | |
915 // Converts a JavaScript value |O| to an IDL record<K, V> value. | |
916 // In C++, a record is represented as a Vector<std::pair<k, v>> (or a | |
917 // HeapVector if v is a type that uses Oilpain). | |
918 // See https://heycam.github.io/webidl/#es-record. | |
919 template <typename KeyType, typename ValueType, typename VectorType> | |
920 VectorType toImplRecord(v8::Isolate* isolate, | |
921 v8::Local<v8::Value> originalValue, | |
922 ExceptionState& exceptionState) { | |
923 // "1. If Type(O) is not Object, throw a TypeError." | |
924 if (!originalValue->IsObject()) { | |
925 exceptionState.throwTypeError( | |
926 "Only objects can be converted to record<K,V> types"); | |
927 return VectorType(); | |
928 } | |
929 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(originalValue); | |
930 v8::TryCatch block(isolate); | |
931 | |
932 // "3. Let keys be ? O.[[OwnPropertyKeys]]()." | |
933 v8::Local<v8::Array> keys; | |
934 // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks | |
935 // web-platform-tests' headers-record.html and deviates from the spec | |
936 // algorithm. | |
937 // Symbols are being skipped due to | |
938 // https://github.com/heycam/webidl/issues/294. | |
939 if (!v8Object | |
940 ->GetOwnPropertyNames(isolate->GetCurrentContext(), | |
941 static_cast<v8::PropertyFilter>( | |
942 v8::PropertyFilter::ALL_PROPERTIES | | |
943 v8::PropertyFilter::SKIP_SYMBOLS)) | |
944 .ToLocal(&keys)) { | |
945 exceptionState.rethrowV8Exception(block.Exception()); | |
946 return VectorType(); | |
947 } | |
948 if (keys->Length() > VectorType::maxCapacity()) { | |
949 exceptionState.throwRangeError("Array length exceeds supported limit."); | |
950 return VectorType(); | |
951 } | |
952 | |
953 // "2. Let result be a new empty instance of record<K, V>." | |
954 VectorType result; | |
955 result.reserveInitialCapacity(keys->Length()); | |
956 | |
957 // The conversion algorithm needs a data structure with fast insertion at the | |
958 // end while at the same time requiring fast checks for previous insert of a | |
959 // given key. |seenKeys| is a key/position in |result| map that aids in the | |
960 // latter part. | |
961 HashMap<String, size_t> seenKeys; | |
962 | |
963 for (uint32_t i = 0; i < keys->Length(); ++i) { | |
964 // "4. Repeat, for each element key of keys in List order:" | |
965 v8::Local<v8::String> key; | |
966 if (!getStringValueInArray(isolate->GetCurrentContext(), keys, i) | |
967 .ToLocal(&key)) { | |
968 exceptionState.rethrowV8Exception(block.Exception()); | |
Yuki
2017/03/02 07:47:28
Not directly related to your CL, we may want an ut
| |
969 return VectorType(); | |
970 } | |
971 | |
972 // "4.1. Let desc be ? O.[[GetOwnProperty]](key)." | |
973 v8::Local<v8::Value> desc; | |
974 if (!v8Object->GetOwnPropertyDescriptor(isolate->GetCurrentContext(), key) | |
975 .ToLocal(&desc)) { | |
976 exceptionState.rethrowV8Exception(block.Exception()); | |
977 return VectorType(); | |
978 } | |
979 | |
980 // "4.2. If desc is not undefined and desc.[[Enumerable]] is true:" | |
981 if (!isPropertyEnumerable(isolate, desc, exceptionState)) { | |
982 if (exceptionState.hadException()) | |
983 return VectorType(); | |
984 continue; | |
985 } | |
986 | |
987 // "4.2.1. Let typedKey be key converted to an IDL value of type K." | |
988 String typedKey = | |
989 NativeValueTraits<KeyType>::nativeValue(isolate, key, exceptionState); | |
990 if (exceptionState.hadException()) | |
991 return VectorType(); | |
992 | |
993 // "4.2.2. Let value be ? Get(O, key)." | |
994 v8::Local<v8::Value> value; | |
995 if (!v8Object->Get(isolate->GetCurrentContext(), key).ToLocal(&value)) { | |
996 exceptionState.rethrowV8Exception(block.Exception()); | |
997 return VectorType(); | |
998 } | |
999 | |
1000 // "4.2.3. Let typedValue be value converted to an IDL value of type V." | |
1001 typename VectorType::ValueType::second_type typedValue = | |
1002 NativeValueTraits<ValueType>::nativeValue(isolate, value, | |
1003 exceptionState); | |
1004 if (exceptionState.hadException()) | |
1005 return VectorType(); | |
1006 | |
1007 if (seenKeys.contains(typedKey)) { | |
1008 // "4.2.4. If typedKey is already a key in result, set its value to | |
1009 // typedValue. | |
1010 // Note: This can happen when O is a proxy object." | |
1011 const size_t pos = seenKeys.at(typedKey); | |
1012 result[pos] = std::make_pair(typedKey, typedValue); | |
1013 } else { | |
1014 // "4.2.5. Otherwise, append to result a mapping (typedKey, typedValue)." | |
1015 const size_t pos = result.size(); // We can take this shortcut because | |
1016 // we are always appending. | |
1017 seenKeys.set(typedKey, pos); | |
1018 result.uncheckedAppend(std::make_pair(typedKey, typedValue)); | |
1019 } | |
1020 } | |
1021 // "5. Return result." | |
1022 return result; | |
1023 } | |
1024 | |
906 template <> | 1025 template <> |
907 struct NativeValueTraits<String> { | 1026 struct NativeValueTraits<String> { |
908 static inline String nativeValue(v8::Isolate* isolate, | 1027 static inline String nativeValue(v8::Isolate* isolate, |
909 v8::Local<v8::Value> value, | 1028 v8::Local<v8::Value> value, |
910 ExceptionState& exceptionState) { | 1029 ExceptionState& exceptionState) { |
911 V8StringResource<> stringValue(value); | 1030 V8StringResource<> stringValue(value); |
912 if (!stringValue.prepare(exceptionState)) | 1031 if (!stringValue.prepare(exceptionState)) |
913 return String(); | 1032 return String(); |
914 return stringValue; | 1033 return stringValue; |
915 } | 1034 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1160 // If the argument isn't an object, this will crash. | 1279 // If the argument isn't an object, this will crash. |
1161 CORE_EXPORT v8::Local<v8::Value> freezeV8Object(v8::Local<v8::Value>, | 1280 CORE_EXPORT v8::Local<v8::Value> freezeV8Object(v8::Local<v8::Value>, |
1162 v8::Isolate*); | 1281 v8::Isolate*); |
1163 | 1282 |
1164 CORE_EXPORT v8::Local<v8::Value> fromJSONString(v8::Isolate*, | 1283 CORE_EXPORT v8::Local<v8::Value> fromJSONString(v8::Isolate*, |
1165 const String& stringifiedJSON, | 1284 const String& stringifiedJSON, |
1166 ExceptionState&); | 1285 ExceptionState&); |
1167 } // namespace blink | 1286 } // namespace blink |
1168 | 1287 |
1169 #endif // V8Binding_h | 1288 #endif // V8Binding_h |
OLD | NEW |