1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "bindings/v8/Dictionary.h" 28 29 #include "bindings/core/v8/V8DOMError.h" 30 #include "bindings/core/v8/V8EventTarget.h" 31 #include "bindings/core/v8/V8MediaKeyError.h" 32 #include "bindings/core/v8/V8MessagePort.h" 33 #include "bindings/core/v8/V8Storage.h" 34 #include "bindings/core/v8/V8TextTrack.h" 35 #include "bindings/core/v8/V8VoidCallback.h" 36 #include "bindings/core/v8/V8Window.h" 37 #include "bindings/modules/v8/V8Gamepad.h" 38 #include "bindings/modules/v8/V8HeaderMap.h" 39 #include "bindings/modules/v8/V8IDBKeyRange.h" 40 #include "bindings/modules/v8/V8MIDIPort.h" 41 #include "bindings/modules/v8/V8MediaStream.h" 42 #include "bindings/modules/v8/V8SpeechRecognitionResult.h" 43 #include "bindings/modules/v8/V8SpeechRecognitionResultList.h" 44 #include "bindings/v8/ArrayValue.h" 45 #include "bindings/v8/ExceptionMessages.h" 46 #include "bindings/v8/ExceptionState.h" 47 #include "bindings/v8/V8Binding.h" 48 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" 49 #include "bindings/v8/custom/V8Uint8ArrayCustom.h" 50 #include "core/html/track/TrackBase.h" 51 #include "modules/gamepad/Gamepad.h" 52 #include "modules/indexeddb/IDBKeyRange.h" 53 #include "modules/mediastream/MediaStream.h" 54 #include "modules/speech/SpeechRecognitionResult.h" 55 #include "modules/speech/SpeechRecognitionResultList.h" 56 #include "wtf/MathExtras.h" 57 58 namespace WebCore { 59 60 Dictionary::Dictionary() 61 : m_isolate(0) 62 { 63 } 64 65 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate) 66 : m_options(options) 67 , m_isolate(isolate) 68 { 69 ASSERT(m_isolate); 70 } 71 72 Dictionary::~Dictionary() 73 { 74 } 75 76 Dictionary& Dictionary::operator=(const Dictionary& optionsObject) 77 { 78 m_options = optionsObject.m_options; 79 m_isolate = optionsObject.m_isolate; 80 return *this; 81 } 82 83 bool Dictionary::isObject() const 84 { 85 return !isUndefinedOrNull() && m_options->IsObject(); 86 } 87 88 bool Dictionary::isUndefinedOrNull() const 89 { 90 if (m_options.IsEmpty()) 91 return true; 92 return WebCore::isUndefinedOrNull(m_options); 93 } 94 95 bool Dictionary::hasProperty(const String& key) const 96 { 97 if (isUndefinedOrNull()) 98 return false; 99 v8::Local<v8::Object> options = m_options->ToObject(); 100 ASSERT(!options.IsEmpty()); 101 102 ASSERT(m_isolate); 103 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 104 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 105 if (!options->Has(v8Key)) 106 return false; 107 108 return true; 109 } 110 111 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const 112 { 113 if (isUndefinedOrNull()) 114 return false; 115 v8::Local<v8::Object> options = m_options->ToObject(); 116 ASSERT(!options.IsEmpty()); 117 118 ASSERT(m_isolate); 119 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 120 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 121 if (!options->Has(v8Key)) 122 return false; 123 value = options->Get(v8Key); 124 if (value.IsEmpty()) 125 return false; 126 return true; 127 } 128 129 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const 130 { 131 return getKey(key, value); 132 } 133 134 bool Dictionary::get(const String& key, bool& value) const 135 { 136 v8::Local<v8::Value> v8Value; 137 if (!getKey(key, v8Value)) 138 return false; 139 140 v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean(); 141 if (v8Bool.IsEmpty()) 142 return false; 143 value = v8Bool->Value(); 144 return true; 145 } 146 147 bool Dictionary::convert(ConversionContext& context, const String& key, bool& value) const 148 { 149 ConversionContextScope scope(context); 150 get(key, value); 151 return true; 152 } 153 154 bool Dictionary::get(const String& key, int32_t& value) const 155 { 156 v8::Local<v8::Value> v8Value; 157 if (!getKey(key, v8Value)) 158 return false; 159 160 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 161 if (v8Int32.IsEmpty()) 162 return false; 163 value = v8Int32->Value(); 164 return true; 165 } 166 167 bool Dictionary::get(const String& key, double& value, bool& hasValue) const 168 { 169 v8::Local<v8::Value> v8Value; 170 if (!getKey(key, v8Value)) { 171 hasValue = false; 172 return false; 173 } 174 175 hasValue = true; 176 TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); 177 if (v8Number.IsEmpty()) 178 return false; 179 value = v8Number->Value(); 180 return true; 181 } 182 183 bool Dictionary::get(const String& key, double& value) const 184 { 185 bool unused; 186 return get(key, value, unused); 187 } 188 189 bool Dictionary::convert(ConversionContext& context, const String& key, double& value) const 190 { 191 ConversionContextScope scope(context); 192 193 bool hasValue = false; 194 if (!get(key, value, hasValue) && hasValue) { 195 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'.")); 196 return false; 197 } 198 return true; 199 } 200 201 template<typename StringType> 202 inline bool Dictionary::getStringType(const String& key, StringType& value) const 203 { 204 v8::Local<v8::Value> v8Value; 205 if (!getKey(key, v8Value)) 206 return false; 207 208 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); 209 value = stringValue; 210 return true; 211 } 212 213 bool Dictionary::get(const String& key, String& value) const 214 { 215 return getStringType(key, value); 216 } 217 218 bool Dictionary::get(const String& key, AtomicString& value) const 219 { 220 return getStringType(key, value); 221 } 222 223 bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const 224 { 225 ConversionContextScope scope(context); 226 227 v8::Local<v8::Value> v8Value; 228 if (!getKey(key, v8Value)) 229 return true; 230 231 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); 232 value = stringValue; 233 return true; 234 } 235 236 bool Dictionary::get(const String& key, ScriptValue& value) const 237 { 238 v8::Local<v8::Value> v8Value; 239 if (!getKey(key, v8Value)) 240 return false; 241 242 value = ScriptValue(ScriptState::current(m_isolate), v8Value); 243 return true; 244 } 245 246 bool Dictionary::convert(ConversionContext& context, const String& key, ScriptValue& value) const 247 { 248 ConversionContextScope scope(context); 249 250 get(key, value); 251 return true; 252 } 253 254 bool Dictionary::get(const String& key, unsigned short& value) const 255 { 256 v8::Local<v8::Value> v8Value; 257 if (!getKey(key, v8Value)) 258 return false; 259 260 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 261 if (v8Int32.IsEmpty()) 262 return false; 263 value = static_cast<unsigned short>(v8Int32->Value()); 264 return true; 265 } 266 267 bool Dictionary::get(const String& key, short& value) const 268 { 269 v8::Local<v8::Value> v8Value; 270 if (!getKey(key, v8Value)) 271 return false; 272 273 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 274 if (v8Int32.IsEmpty()) 275 return false; 276 value = static_cast<short>(v8Int32->Value()); 277 return true; 278 } 279 280 bool Dictionary::get(const String& key, unsigned& value) const 281 { 282 v8::Local<v8::Value> v8Value; 283 if (!getKey(key, v8Value)) 284 return false; 285 286 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 287 if (v8Int32.IsEmpty()) 288 return false; 289 value = static_cast<unsigned>(v8Int32->Value()); 290 return true; 291 } 292 293 bool Dictionary::get(const String& key, unsigned long& value) const 294 { 295 v8::Local<v8::Value> v8Value; 296 if (!getKey(key, v8Value)) 297 return false; 298 299 v8::Local<v8::Integer> v8Integer = v8Value->ToInteger(); 300 if (v8Integer.IsEmpty()) 301 return false; 302 value = static_cast<unsigned long>(v8Integer->Value()); 303 return true; 304 } 305 306 bool Dictionary::get(const String& key, unsigned long long& value) const 307 { 308 v8::Local<v8::Value> v8Value; 309 if (!getKey(key, v8Value)) 310 return false; 311 312 TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); 313 if (v8Number.IsEmpty()) 314 return false; 315 double d = v8Number->Value(); 316 doubleToInteger(d, value); 317 return true; 318 } 319 320 bool Dictionary::get(const String& key, RefPtrWillBeMember<LocalDOMWindow>& value) const 321 { 322 v8::Local<v8::Value> v8Value; 323 if (!getKey(key, v8Value)) 324 return false; 325 326 // We need to handle a DOMWindow specially, because a DOMWindow wrapper 327 // exists on a prototype chain of v8Value. 328 value = toDOMWindow(v8Value, m_isolate); 329 return true; 330 } 331 332 bool Dictionary::get(const String& key, RefPtrWillBeMember<Storage>& value) const 333 { 334 v8::Local<v8::Value> v8Value; 335 if (!getKey(key, v8Value)) 336 return false; 337 338 value = V8Storage::toNativeWithTypeCheck(m_isolate, v8Value); 339 return true; 340 } 341 342 bool Dictionary::get(const String& key, MessagePortArray& value) const 343 { 344 v8::Local<v8::Value> v8Value; 345 if (!getKey(key, v8Value)) 346 return false; 347 348 ASSERT(m_isolate); 349 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 350 if (WebCore::isUndefinedOrNull(v8Value)) 351 return true; 352 bool success = false; 353 value = toRefPtrNativeArray<MessagePort, V8MessagePort>(v8Value, key, m_isolate, &success); 354 return success; 355 } 356 357 bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const 358 { 359 ConversionContextScope scope(context); 360 361 v8::Local<v8::Value> v8Value; 362 if (!getKey(key, v8Value)) 363 return true; 364 365 return get(key, value); 366 } 367 368 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const 369 { 370 v8::Local<v8::Value> v8Value; 371 if (!getKey(key, v8Value)) 372 return false; 373 374 // FIXME: Support array-like objects 375 if (!v8Value->IsArray()) 376 return false; 377 378 ASSERT(m_isolate); 379 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 380 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); 381 for (size_t i = 0; i < v8Array->Length(); ++i) { 382 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(m_isolate, i)); 383 TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); 384 value.add(stringValue); 385 } 386 387 return true; 388 } 389 390 bool Dictionary::convert(ConversionContext& context, const String& key, HashSet<AtomicString>& value) const 391 { 392 ConversionContextScope scope(context); 393 394 v8::Local<v8::Value> v8Value; 395 if (!getKey(key, v8Value)) 396 return true; 397 398 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 399 return true; 400 401 if (!v8Value->IsArray()) { 402 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key)); 403 return false; 404 } 405 406 return get(key, value); 407 } 408 409 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const 410 { 411 v8::Local<v8::Value> v8Value; 412 if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value)) 413 return false; 414 415 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); 416 value = stringValue; 417 return true; 418 } 419 420 bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const 421 { 422 v8::Local<v8::Value> v8Value; 423 if (!getKey(key, v8Value)) 424 return false; 425 426 value = V8Uint8Array::toNativeWithTypeCheck(m_isolate, v8Value); 427 return true; 428 } 429 430 bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const 431 { 432 v8::Local<v8::Value> v8Value; 433 if (!getKey(key, v8Value)) 434 return false; 435 436 value = V8ArrayBufferView::toNativeWithTypeCheck(m_isolate, v8Value); 437 return true; 438 } 439 440 bool Dictionary::get(const String& key, RefPtrWillBeMember<MIDIPort>& value) const 441 { 442 v8::Local<v8::Value> v8Value; 443 if (!getKey(key, v8Value)) 444 return false; 445 446 value = V8MIDIPort::toNativeWithTypeCheck(m_isolate, v8Value); 447 return true; 448 } 449 450 bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const 451 { 452 v8::Local<v8::Value> v8Value; 453 if (!getKey(key, v8Value)) 454 return false; 455 456 value = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value); 457 return true; 458 } 459 460 bool Dictionary::get(const String& key, RefPtrWillBeMember<TrackBase>& value) const 461 { 462 v8::Local<v8::Value> v8Value; 463 if (!getKey(key, v8Value)) 464 return false; 465 466 TrackBase* source = 0; 467 if (v8Value->IsObject()) { 468 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 469 470 // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once 471 // we add them. 472 v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, m_isolate); 473 if (!track.IsEmpty()) 474 source = V8TextTrack::toNative(track); 475 } 476 value = source; 477 return true; 478 } 479 480 bool Dictionary::get(const String& key, Member<SpeechRecognitionResult>& value) const 481 { 482 v8::Local<v8::Value> v8Value; 483 if (!getKey(key, v8Value)) 484 return false; 485 486 value = V8SpeechRecognitionResult::toNativeWithTypeCheck(m_isolate, v8Value); 487 return true; 488 } 489 490 bool Dictionary::get(const String& key, Member<SpeechRecognitionResultList>& value) const 491 { 492 v8::Local<v8::Value> v8Value; 493 if (!getKey(key, v8Value)) 494 return false; 495 496 value = V8SpeechRecognitionResultList::toNativeWithTypeCheck(m_isolate, v8Value); 497 return true; 498 } 499 500 bool Dictionary::get(const String& key, Member<Gamepad>& value) const 501 { 502 v8::Local<v8::Value> v8Value; 503 if (!getKey(key, v8Value)) 504 return false; 505 506 value = V8Gamepad::toNativeWithTypeCheck(m_isolate, v8Value); 507 return true; 508 } 509 510 bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const 511 { 512 v8::Local<v8::Value> v8Value; 513 if (!getKey(key, v8Value)) 514 return false; 515 516 value = V8MediaStream::toNativeWithTypeCheck(m_isolate, v8Value); 517 return true; 518 } 519 520 bool Dictionary::get(const String& key, RefPtrWillBeMember<EventTarget>& value) const 521 { 522 v8::Local<v8::Value> v8Value; 523 if (!getKey(key, v8Value)) 524 return false; 525 526 value = nullptr; 527 // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper 528 // exists on a prototype chain of v8Value. 529 if (v8Value->IsObject()) { 530 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 531 v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, m_isolate); 532 if (!window.IsEmpty()) { 533 value = toWrapperTypeInfo(window)->toEventTarget(window); 534 return true; 535 } 536 } 537 538 if (V8DOMWrapper::isDOMWrapper(v8Value)) { 539 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 540 value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper); 541 } 542 return true; 543 } 544 545 bool Dictionary::get(const String& key, Dictionary& value) const 546 { 547 v8::Local<v8::Value> v8Value; 548 if (!getKey(key, v8Value)) 549 return false; 550 551 if (v8Value->IsObject()) { 552 ASSERT(m_isolate); 553 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 554 value = Dictionary(v8Value, m_isolate); 555 } 556 557 return true; 558 } 559 560 bool Dictionary::get(const String& key, RefPtr<HeaderMap>& value) const 561 { 562 v8::Local<v8::Value> v8Value; 563 if (!getKey(key, v8Value)) 564 return false; 565 566 value = V8HeaderMap::toNativeWithTypeCheck(m_isolate, v8Value); 567 return true; 568 } 569 570 bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const 571 { 572 ConversionContextScope scope(context); 573 574 v8::Local<v8::Value> v8Value; 575 if (!getKey(key, v8Value)) 576 return true; 577 578 if (v8Value->IsObject()) 579 return get(key, value); 580 581 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 582 return true; 583 584 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type.")); 585 return false; 586 } 587 588 bool Dictionary::get(const String& key, Vector<String>& value) const 589 { 590 v8::Local<v8::Value> v8Value; 591 if (!getKey(key, v8Value)) 592 return false; 593 594 if (!v8Value->IsArray()) 595 return false; 596 597 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); 598 for (size_t i = 0; i < v8Array->Length(); ++i) { 599 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(m_isolate, i)); 600 TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); 601 value.append(stringValue); 602 } 603 604 return true; 605 } 606 607 bool Dictionary::convert(ConversionContext& context, const String& key, Vector<String>& value) const 608 { 609 ConversionContextScope scope(context); 610 611 v8::Local<v8::Value> v8Value; 612 if (!getKey(key, v8Value)) 613 return true; 614 615 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 616 return true; 617 618 if (!v8Value->IsArray()) { 619 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key)); 620 return false; 621 } 622 623 return get(key, value); 624 } 625 626 bool Dictionary::get(const String& key, ArrayValue& value) const 627 { 628 v8::Local<v8::Value> v8Value; 629 if (!getKey(key, v8Value)) 630 return false; 631 632 if (!v8Value->IsArray()) 633 return false; 634 635 ASSERT(m_isolate); 636 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 637 value = ArrayValue(v8::Local<v8::Array>::Cast(v8Value), m_isolate); 638 return true; 639 } 640 641 bool Dictionary::convert(ConversionContext& context, const String& key, ArrayValue& value) const 642 { 643 ConversionContextScope scope(context); 644 645 v8::Local<v8::Value> v8Value; 646 if (!getKey(key, v8Value)) 647 return true; 648 649 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 650 return true; 651 652 if (!v8Value->IsArray()) { 653 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key)); 654 return false; 655 } 656 657 return get(key, value); 658 } 659 660 bool Dictionary::get(const String& key, RefPtrWillBeMember<DOMError>& value) const 661 { 662 v8::Local<v8::Value> v8Value; 663 if (!getKey(key, v8Value)) 664 return false; 665 666 value = V8DOMError::toNativeWithTypeCheck(m_isolate, v8Value); 667 return true; 668 } 669 670 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const 671 { 672 if (!isObject()) 673 return false; 674 675 v8::Handle<v8::Object> options = m_options->ToObject(); 676 if (options.IsEmpty()) 677 return false; 678 679 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 680 if (properties.IsEmpty()) 681 return true; 682 for (uint32_t i = 0; i < properties->Length(); ++i) { 683 v8::Local<v8::String> key = properties->Get(i)->ToString(); 684 if (!options->Has(key)) 685 continue; 686 687 v8::Local<v8::Value> value = options->Get(key); 688 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); 689 TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); 690 if (!static_cast<const String&>(stringKey).isEmpty()) 691 hashMap.set(stringKey, stringValue); 692 } 693 694 return true; 695 } 696 697 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const 698 { 699 if (!isObject()) 700 return false; 701 702 v8::Handle<v8::Object> options = m_options->ToObject(); 703 if (options.IsEmpty()) 704 return false; 705 706 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 707 if (properties.IsEmpty()) 708 return true; 709 for (uint32_t i = 0; i < properties->Length(); ++i) { 710 v8::Local<v8::String> key = properties->Get(i)->ToString(); 711 if (!options->Has(key)) 712 continue; 713 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); 714 names.append(stringKey); 715 } 716 717 return true; 718 } 719 720 void Dictionary::ConversionContext::resetPerPropertyContext() 721 { 722 if (m_dirty) { 723 m_dirty = false; 724 m_isNullable = false; 725 m_propertyTypeName = ""; 726 } 727 } 728 729 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable) 730 { 731 ASSERT(!m_dirty); 732 m_dirty = true; 733 m_isNullable = isNullable; 734 m_propertyTypeName = typeName; 735 736 return *this; 737 } 738 739 void Dictionary::ConversionContext::throwTypeError(const String& detail) 740 { 741 exceptionState().throwTypeError(detail); 742 } 743 744 } // namespace WebCore 745