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

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: It turns out static was indeed necessary 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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 } 300 }
301 301
302 CORE_EXPORT static inline ImplType nativeValue(v8::Isolate* isolate, 302 CORE_EXPORT static inline ImplType nativeValue(v8::Isolate* isolate,
303 v8::Local<v8::Value> value, 303 v8::Local<v8::Value> value,
304 ExceptionState& exceptionState, 304 ExceptionState& exceptionState,
305 int index) { 305 int index) {
306 return toImplArray<ImplType, T>(value, index, isolate, exceptionState); 306 return toImplArray<ImplType, T>(value, index, isolate, exceptionState);
307 } 307 }
308 }; 308 };
309 309
310 // Records
311 template <typename K, typename V>
312 struct NativeValueTraits<IDLRecord<K, V>>
313 : public NativeValueTraitsBase<IDLRecord<K, V>> {
314 private:
Yuki 2017/03/08 13:37:52 Sort the sections public: first and private: last
Raphael Kubo da Costa (rakuco) 2017/03/08 18:13:19 Done.
315 static inline bool isPropertyEnumerable(v8::Isolate* isolate,
Yuki 2017/03/08 13:37:52 It's |inline| by default if member functions are d
Raphael Kubo da Costa (rakuco) 2017/03/08 18:13:19 Done.
316 v8::Local<v8::Value> descriptor,
317 ExceptionState& exceptionState) {
318 if (descriptor->IsUndefined())
Yuki 2017/03/08 13:37:52 We don't need this because we're checking IsObject
Raphael Kubo da Costa (rakuco) 2017/03/08 18:13:18 Done.
319 return false;
320 if (!descriptor->IsObject())
321 return false;
322 v8::Local<v8::Value> enumerable;
323 if (!v8::Local<v8::Object>::Cast(descriptor)
324 ->Get(isolate->GetCurrentContext(),
325 v8String(isolate, "enumerable"))
326 .ToLocal(&enumerable))
327 return false;
328 return toBoolean(isolate, enumerable, exceptionState);
329 }
330
331 public:
332 // Nondependent types need to be explicitly qualified to be accessible.
333 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType;
334
335 // Converts a JavaScript value |O| to an IDL record<K, V> value. In C++, a
336 // record is represented as a Vector<std::pair<k, v>> (or a HeapVector if
337 // necessary). See https://heycam.github.io/webidl/#es-record.
338 CORE_EXPORT static inline ImplType nativeValue(
339 v8::Isolate* isolate,
340 v8::Local<v8::Value> originalValue,
Yuki 2017/03/08 13:37:52 Can we name this |value| simply? Since this is a
Raphael Kubo da Costa (rakuco) 2017/03/08 18:13:19 We can, but I thought the preference was to leave
Yuki 2017/03/09 08:32:55 I didn't notice your intention, and later use of |
341 ExceptionState& exceptionState) {
342 v8::Local<v8::Context> context = isolate->GetCurrentContext();
343
344 // "1. If Type(O) is not Object, throw a TypeError."
345 if (!originalValue->IsObject()) {
346 exceptionState.throwTypeError(
347 "Only objects can be converted to record<K,V> types");
348 return ImplType();
349 }
350 v8::Local<v8::Object> v8Object = v8::Local<v8::Object>::Cast(originalValue);
351 v8::TryCatch block(isolate);
352
353 // "3. Let keys be ? O.[[OwnPropertyKeys]]()."
354 v8::Local<v8::Array> keys;
355 // While we could pass v8::ONLY_ENUMERABLE below, doing so breaks
356 // web-platform-tests' headers-record.html and deviates from the spec
357 // algorithm.
358 // Symbols are being skipped due to
359 // https://github.com/heycam/webidl/issues/294.
360 if (!v8Object
361 ->GetOwnPropertyNames(context,
362 static_cast<v8::PropertyFilter>(
363 v8::PropertyFilter::ALL_PROPERTIES |
364 v8::PropertyFilter::SKIP_SYMBOLS))
365 .ToLocal(&keys)) {
366 exceptionState.rethrowV8Exception(block.Exception());
367 return ImplType();
368 }
369 if (keys->Length() > ImplType::maxCapacity()) {
370 exceptionState.throwRangeError("Array length exceeds supported limit.");
371 return ImplType();
372 }
373
374 // "2. Let result be a new empty instance of record<K, V>."
375 ImplType result;
376 result.reserveInitialCapacity(keys->Length());
377
378 // The conversion algorithm needs a data structure with fast insertion at
379 // the end while at the same time requiring fast checks for previous insert
380 // of a given key. |seenKeys| is a key/position in |result| map that aids in
381 // the latter part.
382 HashMap<String, size_t> seenKeys;
383
384 for (uint32_t i = 0; i < keys->Length(); ++i) {
385 // "4. Repeat, for each element key of keys in List order:"
386 v8::Local<v8::Value> key;
387 if (!keys->Get(context, i).ToLocal(&key)) {
388 exceptionState.rethrowV8Exception(block.Exception());
389 return ImplType();
390 }
391
392 // "4.1. Let desc be ? O.[[GetOwnProperty]](key)."
393 v8::Local<v8::Value> desc;
394 if (!v8Object
395 ->GetOwnPropertyDescriptor(
396 context, key->ToString(context).ToLocalChecked())
397 .ToLocal(&desc)) {
398 exceptionState.rethrowV8Exception(block.Exception());
399 return ImplType();
400 }
401
402 // "4.2. If desc is not undefined and desc.[[Enumerable]] is true:"
403 if (!isPropertyEnumerable(isolate, desc, exceptionState)) {
404 if (exceptionState.hadException())
405 return ImplType();
406 continue;
407 }
408
409 // "4.2.1. Let typedKey be key converted to an IDL value of type K."
410 String typedKey =
411 NativeValueTraits<K>::nativeValue(isolate, key, exceptionState);
412 if (exceptionState.hadException())
413 return ImplType();
414
415 // "4.2.2. Let value be ? Get(O, key)."
416 v8::Local<v8::Value> value;
417 if (!v8Object->Get(context, key).ToLocal(&value)) {
418 exceptionState.rethrowV8Exception(block.Exception());
419 return ImplType();
420 }
421
422 // "4.2.3. Let typedValue be value converted to an IDL value of type V."
423 typename ImplType::ValueType::second_type typedValue =
424 NativeValueTraits<V>::nativeValue(isolate, value, exceptionState);
425 if (exceptionState.hadException())
426 return ImplType();
427
428 if (seenKeys.contains(typedKey)) {
429 // "4.2.4. If typedKey is already a key in result, set its value to
430 // typedValue.
431 // Note: This can happen when O is a proxy object."
432 const size_t pos = seenKeys.at(typedKey);
433 result[pos] = std::make_pair(typedKey, typedValue);
434 } else {
435 // "4.2.5. Otherwise, append to result a mapping (typedKey,
436 // typedValue)."
437 const size_t pos = result.size(); // We can take this shortcut because
438 // we are always appending.
439 seenKeys.set(typedKey, pos);
440 result.uncheckedAppend(std::make_pair(typedKey, typedValue));
441 }
442 }
443 // "5. Return result."
444 return result;
445 }
446 };
447
310 } // namespace blink 448 } // namespace blink
311 449
312 #endif // NativeValueTraitsImpl_h 450 #endif // NativeValueTraitsImpl_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698