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

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

Issue 2810843002: bindings: Make the sequence conversion code more complaint with WebIDL. (Closed)
Patch Set: Created 3 years, 8 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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 } 276 }
277 }; 277 };
278 278
279 // Sequences 279 // Sequences
280 template <typename T> 280 template <typename T>
281 struct NativeValueTraits<IDLSequence<T>> 281 struct NativeValueTraits<IDLSequence<T>>
282 : public NativeValueTraitsBase<IDLSequence<T>> { 282 : public NativeValueTraitsBase<IDLSequence<T>> {
283 // Nondependent types need to be explicitly qualified to be accessible. 283 // Nondependent types need to be explicitly qualified to be accessible.
284 using typename NativeValueTraitsBase<IDLSequence<T>>::ImplType; 284 using typename NativeValueTraitsBase<IDLSequence<T>>::ImplType;
285 285
286 // https://heycam.github.io/webidl/#es-sequence
286 static ImplType NativeValue(v8::Isolate* isolate, 287 static ImplType NativeValue(v8::Isolate* isolate,
287 v8::Local<v8::Value> value, 288 v8::Local<v8::Value> value,
288 ExceptionState& exception_state) { 289 ExceptionState& exception_state) {
289 return NativeValue(isolate, value, exception_state, 0); 290 if (!value->IsObject()) {
291 exception_state.ThrowTypeError(
292 "The provided value cannot be converted to a sequence.");
293 return ImplType();
294 }
295
296 ImplType result;
297 // TODO(rakuco): Checking for IsArray() may not be enough. Other engines
298 // also prefer regular array iteration over a custom @@iterator when the
299 // latter is defined, but it is not clear if this is a valid optimization.
300 if (value->IsArray()) {
bashi 2017/04/11 00:34:00 We may want to ask v8 team this?
Yuki 2017/04/11 07:17:10 I think that this should be: if (value->Get(v8:
301 result.ReserveInitialCapacity(value.As<v8::Array>()->Length());
302 iteratorForEachFast(
303 isolate, value.As<v8::Object>(), exception_state,
304 [&isolate, &result, &exception_state](v8::Local<v8::Value> element) {
305 result.UncheckedAppend(NativeValueTraits<T>::NativeValue(
306 isolate, element, exception_state));
307 return !exception_state.HadException();
308 });
309 } else {
310 iteratorForEachSlow(
311 isolate, value.As<v8::Object>(), exception_state,
312 [&isolate, &result, &exception_state](v8::Local<v8::Value> element) {
313 result.emplace_back(NativeValueTraits<T>::NativeValue(
314 isolate, element, exception_state));
315 return !exception_state.HadException();
316 });
317 }
318
319 if (exception_state.HadException())
320 return ImplType();
321 return result;
290 } 322 }
291 323
292 static ImplType NativeValue(v8::Isolate* isolate, 324 private:
293 v8::Local<v8::Value> value, 325 // Fast case: we're interating over an Array that adheres to
294 ExceptionState& exception_state, 326 // %ArrayIteratorPrototype%'s protocol.
295 int index) { 327 template <typename CallbackFunction>
296 return ToImplArray<ImplType, T>(value, index, isolate, exception_state); 328 static void iteratorForEachFast(v8::Isolate* isolate,
329 v8::Local<v8::Object> v8Object,
330 ExceptionState& exception_state,
331 CallbackFunction&& callback) {
332 DCHECK(v8Object->IsArray());
333 v8::TryCatch block(isolate);
334 const uint32_t length = v8Object.As<v8::Array>()->Length();
335 for (uint32_t i = 0; i < length; ++i) {
336 v8::Local<v8::Value> element;
337 if (!V8Call(v8Object->Get(isolate->GetCurrentContext(), i), element,
Yuki 2017/04/11 07:17:10 nit: V8Call is deprecated. Please use V8's ToLoca
338 block)) {
339 exception_state.RethrowV8Exception(block.Exception());
340 return;
341 }
342 if (!callback(element))
bashi 2017/04/11 00:34:00 Help me understand: Why does the callback need to
343 return;
344 }
345 }
346
347 // Slow case: follow WebIDL's "Creating a sequence from an iterable" steps to
348 // iterate through each element.
349 // https://heycam.github.io/webidl/#create-sequence-from-iterable
350 template <typename CallbackFunction>
351 static void iteratorForEachSlow(v8::Isolate* isolate,
352 v8::Local<v8::Object> v8Object,
353 ExceptionState& exception_state,
354 CallbackFunction&& callback) {
355 v8::TryCatch block(isolate);
356
357 v8::Local<v8::Object> iterator =
358 GetEsIterator(isolate, v8Object, exception_state);
359 if (exception_state.HadException())
360 return;
361
362 v8::Local<v8::String> next_key = V8String(isolate, "next");
363 v8::Local<v8::String> value_key = V8String(isolate, "value");
364 v8::Local<v8::String> done_key = V8String(isolate, "done");
365 v8::Local<v8::Context> context = isolate->GetCurrentContext();
366 while (true) {
367 v8::Local<v8::Value> next;
368 if (!iterator->Get(context, next_key).ToLocal(&next)) {
369 exception_state.RethrowV8Exception(block.Exception());
370 return;
371 }
372 // TODO(bashi): Support callable objects.
bashi 2017/04/11 00:34:00 nit: My vague recollection is that yukishiino@ sai
Yuki 2017/04/11 07:17:10 Yes, a callable object is a function by definition
373 if (!next->IsObject() || !next.As<v8::Object>()->IsFunction()) {
374 exception_state.ThrowTypeError("Iterator.next should be callable.");
375 return;
376 }
377 v8::Local<v8::Value> nextResult;
Yuki 2017/04/11 07:17:10 nit: s/nextResult/next_result/ Last week end, Bli
378 if (!V8ScriptRunner::CallFunction(next.As<v8::Function>(),
379 ToExecutionContext(context), iterator,
380 0, nullptr, isolate)
381 .ToLocal(&nextResult)) {
382 exception_state.RethrowV8Exception(block.Exception());
383 return;
384 }
385 if (!nextResult->IsObject()) {
386 exception_state.ThrowTypeError(
387 "Iterator.next() did not return an object.");
388 return;
389 }
390 v8::Local<v8::Object> result_object = nextResult.As<v8::Object>();
391 v8::Local<v8::Value> element;
392 v8::Local<v8::Value> done;
393 if (!result_object->Get(context, value_key).ToLocal(&element) ||
394 !result_object->Get(context, done_key).ToLocal(&done)) {
395 exception_state.RethrowV8Exception(block.Exception());
396 return;
397 }
398 v8::Local<v8::Boolean> done_boolean;
399 if (!done->ToBoolean(context).ToLocal(&done_boolean)) {
Yuki 2017/04/11 07:17:10 nit: You can use done->BooleanValue(context).To(&d
400 exception_state.RethrowV8Exception(block.Exception());
401 return;
402 }
403 if (done_boolean->Value())
404 break;
405 if (!callback(element))
406 return;
407 }
297 } 408 }
298 }; 409 };
299 410
300 // Records 411 // Records
301 template <typename K, typename V> 412 template <typename K, typename V>
302 struct NativeValueTraits<IDLRecord<K, V>> 413 struct NativeValueTraits<IDLRecord<K, V>>
303 : public NativeValueTraitsBase<IDLRecord<K, V>> { 414 : public NativeValueTraitsBase<IDLRecord<K, V>> {
304 // Nondependent types need to be explicitly qualified to be accessible. 415 // Nondependent types need to be explicitly qualified to be accessible.
305 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType; 416 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType;
306 417
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 531 }
421 } 532 }
422 // "5. Return result." 533 // "5. Return result."
423 return result; 534 return result;
424 } 535 }
425 }; 536 };
426 537
427 } // namespace blink 538 } // namespace blink
428 539
429 #endif // NativeValueTraitsImpl_h 540 #endif // NativeValueTraitsImpl_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698