Index: third_party/WebKit/Source/bindings/core/v8/V8Binding.h |
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h |
index 1df7fae7726c68025efbae99fb7607a1ef7a794a..d35b1d21478a891836fb20bd70ec65b404805031 100644 |
--- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h |
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h |
@@ -761,12 +761,12 @@ HeapVector<Member<T>> toMemberNativeArray(v8::Local<v8::Value> value, |
// Converts a JavaScript value to an array as per the Web IDL specification: |
// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array |
-template <typename VectorType> |
+template <typename VectorType, |
+ typename ValueType = typename VectorType::ValueType> |
VectorType toImplArray(v8::Local<v8::Value> value, |
int argumentIndex, |
v8::Isolate* isolate, |
ExceptionState& exceptionState) { |
- typedef typename VectorType::ValueType ValueType; |
typedef NativeValueTraits<ValueType> TraitsType; |
uint32_t length = 0; |
@@ -903,6 +903,125 @@ inline bool toV8Sequence(v8::Local<v8::Value> value, |
return true; |
} |
+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
|
+ v8::Local<v8::Context> context, |
+ v8::Local<v8::Array> array, |
+ uint32_t index); |
+ |
+CORE_EXPORT bool isPropertyEnumerable(v8::Isolate* isolate, |
+ v8::Local<v8::Value> descriptor, |
+ ExceptionState& exceptionState); |
+ |
+// Converts a JavaScript value |O| to an IDL record<K, V> value. |
+// In C++, a record is represented as a Vector<std::pair<k, v>> (or a |
+// HeapVector if v is a type that uses Oilpain). |
+// See https://heycam.github.io/webidl/#es-record. |
+template <typename KeyType, typename ValueType, typename VectorType> |
+VectorType toImplRecord(v8::Isolate* isolate, |
+ v8::Local<v8::Value> originalValue, |
+ ExceptionState& exceptionState) { |
+ // "1. If Type(O) is not Object, throw a TypeError." |
+ if (!originalValue->IsObject()) { |
+ exceptionState.throwTypeError( |
+ "Only objects can be converted to record<K,V> types"); |
+ return VectorType(); |
+ } |
+ v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(originalValue); |
+ v8::TryCatch block(isolate); |
+ |
+ // "3. Let keys be ? O.[[OwnPropertyKeys]]()." |
+ v8::Local<v8::Array> keys; |
+ // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks |
+ // web-platform-tests' headers-record.html and deviates from the spec |
+ // algorithm. |
+ // Symbols are being skipped due to |
+ // https://github.com/heycam/webidl/issues/294. |
+ if (!v8Object |
+ ->GetOwnPropertyNames(isolate->GetCurrentContext(), |
+ static_cast<v8::PropertyFilter>( |
+ v8::PropertyFilter::ALL_PROPERTIES | |
+ v8::PropertyFilter::SKIP_SYMBOLS)) |
+ .ToLocal(&keys)) { |
+ exceptionState.rethrowV8Exception(block.Exception()); |
+ return VectorType(); |
+ } |
+ if (keys->Length() > VectorType::maxCapacity()) { |
+ exceptionState.throwRangeError("Array length exceeds supported limit."); |
+ return VectorType(); |
+ } |
+ |
+ // "2. Let result be a new empty instance of record<K, V>." |
+ VectorType result; |
+ result.reserveInitialCapacity(keys->Length()); |
+ |
+ // The conversion algorithm needs a data structure with fast insertion at the |
+ // end while at the same time requiring fast checks for previous insert of a |
+ // given key. |seenKeys| is a key/position in |result| map that aids in the |
+ // latter part. |
+ HashMap<String, size_t> seenKeys; |
+ |
+ for (uint32_t i = 0; i < keys->Length(); ++i) { |
+ // "4. Repeat, for each element key of keys in List order:" |
+ v8::Local<v8::String> key; |
+ if (!getStringValueInArray(isolate->GetCurrentContext(), keys, i) |
+ .ToLocal(&key)) { |
+ exceptionState.rethrowV8Exception(block.Exception()); |
Yuki
2017/03/02 07:47:28
Not directly related to your CL, we may want an ut
|
+ return VectorType(); |
+ } |
+ |
+ // "4.1. Let desc be ? O.[[GetOwnProperty]](key)." |
+ v8::Local<v8::Value> desc; |
+ if (!v8Object->GetOwnPropertyDescriptor(isolate->GetCurrentContext(), key) |
+ .ToLocal(&desc)) { |
+ exceptionState.rethrowV8Exception(block.Exception()); |
+ return VectorType(); |
+ } |
+ |
+ // "4.2. If desc is not undefined and desc.[[Enumerable]] is true:" |
+ if (!isPropertyEnumerable(isolate, desc, exceptionState)) { |
+ if (exceptionState.hadException()) |
+ return VectorType(); |
+ continue; |
+ } |
+ |
+ // "4.2.1. Let typedKey be key converted to an IDL value of type K." |
+ String typedKey = |
+ NativeValueTraits<KeyType>::nativeValue(isolate, key, exceptionState); |
+ if (exceptionState.hadException()) |
+ return VectorType(); |
+ |
+ // "4.2.2. Let value be ? Get(O, key)." |
+ v8::Local<v8::Value> value; |
+ if (!v8Object->Get(isolate->GetCurrentContext(), key).ToLocal(&value)) { |
+ exceptionState.rethrowV8Exception(block.Exception()); |
+ return VectorType(); |
+ } |
+ |
+ // "4.2.3. Let typedValue be value converted to an IDL value of type V." |
+ typename VectorType::ValueType::second_type typedValue = |
+ NativeValueTraits<ValueType>::nativeValue(isolate, value, |
+ exceptionState); |
+ if (exceptionState.hadException()) |
+ return VectorType(); |
+ |
+ if (seenKeys.contains(typedKey)) { |
+ // "4.2.4. If typedKey is already a key in result, set its value to |
+ // typedValue. |
+ // Note: This can happen when O is a proxy object." |
+ const size_t pos = seenKeys.at(typedKey); |
+ result[pos] = std::make_pair(typedKey, typedValue); |
+ } else { |
+ // "4.2.5. Otherwise, append to result a mapping (typedKey, typedValue)." |
+ const size_t pos = result.size(); // We can take this shortcut because |
+ // we are always appending. |
+ seenKeys.set(typedKey, pos); |
+ result.uncheckedAppend(std::make_pair(typedKey, typedValue)); |
+ } |
+ } |
+ // "5. Return result." |
+ return result; |
+} |
+ |
template <> |
struct NativeValueTraits<String> { |
static inline String nativeValue(v8::Isolate* isolate, |