Chromium Code Reviews| 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 |