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

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: Adjust even more tests 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()) {
301 ConvertSequenceFast(isolate, value.As<v8::Array>(), exception_state,
302 result);
303 } else {
304 ConvertSequenceSlow(isolate, value.As<v8::Object>(), exception_state,
305 result);
306 }
307
308 if (exception_state.HadException())
309 return ImplType();
310 return result;
290 } 311 }
291 312
292 static ImplType NativeValue(v8::Isolate* isolate, 313 private:
293 v8::Local<v8::Value> value, 314 // Fast case: we're interating over an Array that adheres to
294 ExceptionState& exception_state, 315 // %ArrayIteratorPrototype%'s protocol.
295 int index) { 316 static void ConvertSequenceFast(v8::Isolate* isolate,
296 return ToImplArray<ImplType, T>(value, index, isolate, exception_state); 317 v8::Local<v8::Array> v8_array,
318 ExceptionState& exception_state,
319 ImplType& result) {
320 const uint32_t length = v8_array->Length();
321 if (length > ImplType::MaxCapacity()) {
322 exception_state.ThrowRangeError("Array length exceeds supported limit.");
323 return;
324 }
325 result.ReserveInitialCapacity(length);
326 v8::TryCatch block(isolate);
327 for (uint32_t i = 0; i < length; ++i) {
328 v8::Local<v8::Value> element;
329 if (!v8_array->Get(isolate->GetCurrentContext(), i).ToLocal(&element)) {
330 exception_state.RethrowV8Exception(block.Exception());
331 return;
332 }
333 result.UncheckedAppend(
334 NativeValueTraits<T>::NativeValue(isolate, element, exception_state));
335 if (exception_state.HadException())
336 return;
337 }
338 }
339
340 // Slow case: follow WebIDL's "Creating a sequence from an iterable" steps to
341 // iterate through each element.
342 // https://heycam.github.io/webidl/#create-sequence-from-iterable
343 static void ConvertSequenceSlow(v8::Isolate* isolate,
344 v8::Local<v8::Object> v8_object,
345 ExceptionState& exception_state,
346 ImplType& result) {
347 v8::TryCatch block(isolate);
348
349 v8::Local<v8::Object> iterator =
350 GetEsIterator(isolate, v8_object, exception_state);
351 if (exception_state.HadException())
352 return;
353
354 v8::Local<v8::String> next_key = V8String(isolate, "next");
355 v8::Local<v8::String> value_key = V8String(isolate, "value");
356 v8::Local<v8::String> done_key = V8String(isolate, "done");
357 v8::Local<v8::Context> context = isolate->GetCurrentContext();
358 while (true) {
359 v8::Local<v8::Value> next;
360 if (!iterator->Get(context, next_key).ToLocal(&next)) {
361 exception_state.RethrowV8Exception(block.Exception());
362 return;
363 }
364 if (!next->IsFunction()) {
365 exception_state.ThrowTypeError("Iterator.next should be callable.");
366 return;
367 }
368 v8::Local<v8::Value> next_result;
369 if (!V8ScriptRunner::CallFunction(next.As<v8::Function>(),
370 ToExecutionContext(context), iterator,
371 0, nullptr, isolate)
372 .ToLocal(&next_result)) {
373 exception_state.RethrowV8Exception(block.Exception());
374 return;
375 }
376 if (!next_result->IsObject()) {
377 exception_state.ThrowTypeError(
378 "Iterator.next() did not return an object.");
379 return;
380 }
381 v8::Local<v8::Object> result_object = next_result.As<v8::Object>();
382 v8::Local<v8::Value> element;
383 v8::Local<v8::Value> done;
384 if (!result_object->Get(context, value_key).ToLocal(&element) ||
385 !result_object->Get(context, done_key).ToLocal(&done)) {
386 exception_state.RethrowV8Exception(block.Exception());
387 return;
388 }
389 bool done_boolean;
390 if (!done->BooleanValue(context).To(&done_boolean)) {
391 exception_state.RethrowV8Exception(block.Exception());
392 return;
393 }
394 if (done_boolean)
395 break;
396 result.emplace_back(
397 NativeValueTraits<T>::NativeValue(isolate, element, exception_state));
398 if (exception_state.HadException())
399 return;
400 }
297 } 401 }
298 }; 402 };
299 403
300 // Records 404 // Records
301 template <typename K, typename V> 405 template <typename K, typename V>
302 struct NativeValueTraits<IDLRecord<K, V>> 406 struct NativeValueTraits<IDLRecord<K, V>>
303 : public NativeValueTraitsBase<IDLRecord<K, V>> { 407 : public NativeValueTraitsBase<IDLRecord<K, V>> {
304 // Nondependent types need to be explicitly qualified to be accessible. 408 // Nondependent types need to be explicitly qualified to be accessible.
305 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType; 409 using typename NativeValueTraitsBase<IDLRecord<K, V>>::ImplType;
306 410
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 524 }
421 } 525 }
422 // "5. Return result." 526 // "5. Return result."
423 return result; 527 return result;
424 } 528 }
425 }; 529 };
426 530
427 } // namespace blink 531 } // namespace blink
428 532
429 #endif // NativeValueTraitsImpl_h 533 #endif // NativeValueTraitsImpl_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698