Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |