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

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

Issue 2732093003: bindings: Add support for the record<K,V> WebIDL type. (Closed)
Patch Set: s/isolate->GetCurrentContext()/context/ Created 3 years, 9 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 // Copyright (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2017 The Chromium 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 #ifndef NativeValueTraitsImpl_h 5 #ifndef NativeValueTraitsImpl_h
6 #define NativeValueTraitsImpl_h 6 #define NativeValueTraitsImpl_h
7 7
8 #include "bindings/core/v8/IDLTypes.h" 8 #include "bindings/core/v8/IDLTypes.h"
9 #include "bindings/core/v8/NativeValueTraits.h" 9 #include "bindings/core/v8/NativeValueTraits.h"
10 #include "bindings/core/v8/V8Binding.h" 10 #include "bindings/core/v8/V8Binding.h"
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 } 298 }
299 299
300 static inline ImplType nativeValue(v8::Isolate* isolate, 300 static inline ImplType nativeValue(v8::Isolate* isolate,
301 v8::Local<v8::Value> value, 301 v8::Local<v8::Value> value,
302 ExceptionState& exceptionState, 302 ExceptionState& exceptionState,
303 int index) { 303 int index) {
304 return toImplArray<ImplType, T>(value, index, isolate, exceptionState); 304 return toImplArray<ImplType, T>(value, index, isolate, exceptionState);
305 } 305 }
306 }; 306 };
307 307
308 // Records
309 template <typename K, typename V>
310 struct NativeValueTraits<IDLRecord<K, V>>
311 : public NativeValueTraitsBase<IDLRecord<K, V>> {
312 // Nondependent types need to be explicitly qualified to be accessible.
313 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType;
314
315 // Converts a JavaScript value |O| to an IDL record<K, V> value. In C++, a
316 // record is represented as a Vector<std::pair<k, v>> (or a HeapVector if
317 // necessary). See https://heycam.github.io/webidl/#es-record.
318 static ImplType nativeValue(v8::Isolate* isolate,
319 v8::Local<v8::Value> v8Value,
320 ExceptionState& exceptionState) {
321 v8::Local<v8::Context> context = isolate->GetCurrentContext();
322
323 // "1. If Type(O) is not Object, throw a TypeError."
324 if (!v8Value->IsObject()) {
325 exceptionState.throwTypeError(
326 "Only objects can be converted to record<K,V> types");
327 return ImplType();
328 }
329 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(v8Value);
330 v8::TryCatch block(isolate);
331
332 // "3. Let keys be ? O.[[OwnPropertyKeys]]()."
333 v8::Local<v8::Array> keys;
334 // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks
335 // web-platform-tests' headers-record.html and deviates from the spec
336 // algorithm.
337 // Symbols are being skipped due to
338 // https://github.com/heycam/webidl/issues/294.
339 if (!v8Object
340 ->GetOwnPropertyNames(context,
341 static_cast<v8::PropertyFilter>(
342 v8::PropertyFilter::ALL_PROPERTIES |
343 v8::PropertyFilter::SKIP_SYMBOLS))
344 .ToLocal(&keys)) {
345 exceptionState.rethrowV8Exception(block.Exception());
346 return ImplType();
347 }
348 if (keys->Length() > ImplType::maxCapacity()) {
349 exceptionState.throwRangeError("Array length exceeds supported limit.");
350 return ImplType();
351 }
352
353 // "2. Let result be a new empty instance of record<K, V>."
354 ImplType result;
355 result.reserveInitialCapacity(keys->Length());
356
357 // The conversion algorithm needs a data structure with fast insertion at
358 // the end while at the same time requiring fast checks for previous insert
359 // of a given key. |seenKeys| is a key/position in |result| map that aids in
360 // the latter part.
361 HashMap<String, size_t> seenKeys;
362
363 for (uint32_t i = 0; i < keys->Length(); ++i) {
364 // "4. Repeat, for each element key of keys in List order:"
365 v8::Local<v8::Value> key;
366 if (!keys->Get(context, i).ToLocal(&key)) {
367 exceptionState.rethrowV8Exception(block.Exception());
368 return ImplType();
369 }
370
371 // "4.1. Let desc be ? O.[[GetOwnProperty]](key)."
372 v8::Local<v8::Value> desc;
373 if (!v8Object
374 ->GetOwnPropertyDescriptor(
375 context, key->ToString(context).ToLocalChecked())
376 .ToLocal(&desc)) {
377 exceptionState.rethrowV8Exception(block.Exception());
378 return ImplType();
379 }
380
381 // "4.2. If desc is not undefined and desc.[[Enumerable]] is true:"
382 // We can call ToLocalChecked() and ToChecked() here because
383 // GetOwnPropertyDescriptor is responsible for catching any exceptions
384 // and failures, and if we got to this point of the code we have a proper
385 // object that was not created by a user.
386 DCHECK(desc->IsObject());
387 v8::Local<v8::Value> enumerable =
388 v8::Local<v8::Object>::Cast(desc)
389 ->Get(context, v8String(isolate, "enumerable"))
390 .ToLocalChecked();
391 if (!enumerable->BooleanValue(context).ToChecked())
392 continue;
393
394 // "4.2.1. Let typedKey be key converted to an IDL value of type K."
395 String typedKey =
396 NativeValueTraits<K>::nativeValue(isolate, key, exceptionState);
397 if (exceptionState.hadException())
398 return ImplType();
399
400 // "4.2.2. Let value be ? Get(O, key)."
401 v8::Local<v8::Value> value;
402 if (!v8Object->Get(context, key).ToLocal(&value)) {
403 exceptionState.rethrowV8Exception(block.Exception());
404 return ImplType();
405 }
406
407 // "4.2.3. Let typedValue be value converted to an IDL value of type V."
408 typename ImplType::ValueType::second_type typedValue =
409 NativeValueTraits<V>::nativeValue(isolate, value, exceptionState);
410 if (exceptionState.hadException())
411 return ImplType();
412
413 if (seenKeys.contains(typedKey)) {
414 // "4.2.4. If typedKey is already a key in result, set its value to
415 // typedValue.
416 // Note: This can happen when O is a proxy object."
417 const size_t pos = seenKeys.at(typedKey);
418 result[pos] = std::make_pair(typedKey, typedValue);
419 } else {
420 // "4.2.5. Otherwise, append to result a mapping (typedKey,
421 // typedValue)."
422 // Note we can take this shortcut because we are always appending.
423 const size_t pos = result.size();
424 seenKeys.set(typedKey, pos);
425 result.uncheckedAppend(std::make_pair(typedKey, typedValue));
426 }
427 }
428 // "5. Return result."
429 return result;
430 }
431 };
432
308 } // namespace blink 433 } // namespace blink
309 434
310 #endif // NativeValueTraitsImpl_h 435 #endif // NativeValueTraitsImpl_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698