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 "V8DOMError.h" 30 #include "V8EventTarget.h" 31 #include "V8IDBKeyRange.h" 32 #include "V8MIDIPort.h" 33 #include "V8MediaKeyError.h" 34 #include "V8SpeechRecognitionError.h" 35 #include "V8SpeechRecognitionResult.h" 36 #include "V8SpeechRecognitionResultList.h" 37 #include "V8Storage.h" 38 #include "V8VoidCallback.h" 39 #include "V8Window.h" 40 #include "bindings/v8/ArrayValue.h" 41 #include "bindings/v8/ExceptionMessages.h" 42 #include "bindings/v8/ExceptionState.h" 43 #include "bindings/v8/V8Binding.h" 44 #include "bindings/v8/V8Utilities.h" 45 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" 46 #include "bindings/v8/custom/V8Uint8ArrayCustom.h" 47 #include "modules/indexeddb/IDBKeyRange.h" 48 #include "modules/speech/SpeechRecognitionError.h" 49 #include "modules/speech/SpeechRecognitionResult.h" 50 #include "modules/speech/SpeechRecognitionResultList.h" 51 #include "wtf/MathExtras.h" 52 53 #include "V8TextTrack.h" 54 #include "core/html/track/TrackBase.h" 55 56 #include "V8MediaStream.h" 57 #include "modules/mediastream/MediaStream.h" 58 59 namespace WebCore { 60 61 Dictionary::Dictionary() 62 : m_isolate(0) 63 { 64 } 65 66 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate) 67 : m_options(options) 68 , m_isolate(isolate) 69 { 70 ASSERT(m_isolate); 71 } 72 73 Dictionary::~Dictionary() 74 { 75 } 76 77 Dictionary& Dictionary::operator=(const Dictionary& optionsObject) 78 { 79 m_options = optionsObject.m_options; 80 m_isolate = optionsObject.m_isolate; 81 return *this; 82 } 83 84 bool Dictionary::isObject() const 85 { 86 return !isUndefinedOrNull() && m_options->IsObject(); 87 } 88 89 bool Dictionary::isUndefinedOrNull() const 90 { 91 if (m_options.IsEmpty()) 92 return true; 93 return WebCore::isUndefinedOrNull(m_options); 94 } 95 96 bool Dictionary::hasProperty(const String& key) const 97 { 98 if (isUndefinedOrNull()) 99 return false; 100 v8::Local<v8::Object> options = m_options->ToObject(); 101 ASSERT(!options.IsEmpty()); 102 103 ASSERT(m_isolate); 104 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 105 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 106 if (!options->Has(v8Key)) 107 return false; 108 109 return true; 110 } 111 112 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const 113 { 114 if (isUndefinedOrNull()) 115 return false; 116 v8::Local<v8::Object> options = m_options->ToObject(); 117 ASSERT(!options.IsEmpty()); 118 119 ASSERT(m_isolate); 120 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 121 v8::Handle<v8::String> v8Key = v8String(m_isolate, key); 122 if (!options->Has(v8Key)) 123 return false; 124 value = options->Get(v8Key); 125 if (value.IsEmpty()) 126 return false; 127 return true; 128 } 129 130 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const 131 { 132 return getKey(key, value); 133 } 134 135 bool Dictionary::get(const String& key, bool& value) const 136 { 137 v8::Local<v8::Value> v8Value; 138 if (!getKey(key, v8Value)) 139 return false; 140 141 v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean(); 142 if (v8Bool.IsEmpty()) 143 return false; 144 value = v8Bool->Value(); 145 return true; 146 } 147 148 bool Dictionary::convert(ConversionContext& context, const String& key, bool& value) const 149 { 150 ConversionContextScope scope(context); 151 get(key, value); 152 return true; 153 } 154 155 bool Dictionary::get(const String& key, int32_t& value) const 156 { 157 v8::Local<v8::Value> v8Value; 158 if (!getKey(key, v8Value)) 159 return false; 160 161 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 162 if (v8Int32.IsEmpty()) 163 return false; 164 value = v8Int32->Value(); 165 return true; 166 } 167 168 bool Dictionary::get(const String& key, double& value, bool& hasValue) const 169 { 170 v8::Local<v8::Value> v8Value; 171 if (!getKey(key, v8Value)) { 172 hasValue = false; 173 return false; 174 } 175 176 hasValue = true; 177 V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); 178 if (v8Number.IsEmpty()) 179 return false; 180 value = v8Number->Value(); 181 return true; 182 } 183 184 bool Dictionary::get(const String& key, double& value) const 185 { 186 bool unused; 187 return get(key, value, unused); 188 } 189 190 bool Dictionary::convert(ConversionContext& context, const String& key, double& value) const 191 { 192 ConversionContextScope scope(context); 193 194 bool hasValue = false; 195 if (!get(key, value, hasValue) && hasValue) { 196 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'.")); 197 return false; 198 } 199 return true; 200 } 201 202 bool Dictionary::get(const String& key, String& value) const 203 { 204 v8::Local<v8::Value> v8Value; 205 if (!getKey(key, v8Value)) 206 return false; 207 208 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); 209 value = stringValue; 210 return true; 211 } 212 213 bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const 214 { 215 ConversionContextScope scope(context); 216 217 v8::Local<v8::Value> v8Value; 218 if (!getKey(key, v8Value)) 219 return true; 220 221 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); 222 value = stringValue; 223 return true; 224 } 225 226 bool Dictionary::get(const String& key, ScriptValue& value) const 227 { 228 v8::Local<v8::Value> v8Value; 229 if (!getKey(key, v8Value)) 230 return false; 231 232 value = ScriptValue(v8Value, m_isolate); 233 return true; 234 } 235 236 bool Dictionary::convert(ConversionContext& context, const String& key, ScriptValue& value) const 237 { 238 ConversionContextScope scope(context); 239 240 get(key, value); 241 return true; 242 } 243 244 bool Dictionary::get(const String& key, unsigned short& value) const 245 { 246 v8::Local<v8::Value> v8Value; 247 if (!getKey(key, v8Value)) 248 return false; 249 250 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 251 if (v8Int32.IsEmpty()) 252 return false; 253 value = static_cast<unsigned short>(v8Int32->Value()); 254 return true; 255 } 256 257 bool Dictionary::get(const String& key, short& value) const 258 { 259 v8::Local<v8::Value> v8Value; 260 if (!getKey(key, v8Value)) 261 return false; 262 263 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 264 if (v8Int32.IsEmpty()) 265 return false; 266 value = static_cast<short>(v8Int32->Value()); 267 return true; 268 } 269 270 bool Dictionary::get(const String& key, unsigned& value) const 271 { 272 v8::Local<v8::Value> v8Value; 273 if (!getKey(key, v8Value)) 274 return false; 275 276 v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32(); 277 if (v8Int32.IsEmpty()) 278 return false; 279 value = static_cast<unsigned>(v8Int32->Value()); 280 return true; 281 } 282 283 bool Dictionary::get(const String& key, unsigned long& value) const 284 { 285 v8::Local<v8::Value> v8Value; 286 if (!getKey(key, v8Value)) 287 return false; 288 289 v8::Local<v8::Integer> v8Integer = v8Value->ToInteger(); 290 if (v8Integer.IsEmpty()) 291 return false; 292 value = static_cast<unsigned long>(v8Integer->Value()); 293 return true; 294 } 295 296 bool Dictionary::get(const String& key, unsigned long long& value) const 297 { 298 v8::Local<v8::Value> v8Value; 299 if (!getKey(key, v8Value)) 300 return false; 301 302 V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); 303 if (v8Number.IsEmpty()) 304 return false; 305 double d = v8Number->Value(); 306 doubleToInteger(d, value); 307 return true; 308 } 309 310 bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const 311 { 312 v8::Local<v8::Value> v8Value; 313 if (!getKey(key, v8Value)) 314 return false; 315 316 // We need to handle a DOMWindow specially, because a DOMWindow wrapper 317 // exists on a prototype chain of v8Value. 318 value = 0; 319 if (v8Value->IsObject()) { 320 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 321 v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); 322 if (!window.IsEmpty()) 323 value = V8Window::toNative(window); 324 } 325 return true; 326 } 327 328 bool Dictionary::get(const String& key, RefPtr<Storage>& value) const 329 { 330 v8::Local<v8::Value> v8Value; 331 if (!getKey(key, v8Value)) 332 return false; 333 334 value = 0; 335 if (V8Storage::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 336 value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 337 return true; 338 } 339 340 bool Dictionary::get(const String& key, MessagePortArray& value) const 341 { 342 v8::Local<v8::Value> v8Value; 343 if (!getKey(key, v8Value)) 344 return false; 345 346 ASSERT(m_isolate); 347 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 348 return getMessagePortArray(v8Value, key, value, m_isolate); 349 } 350 351 bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const 352 { 353 ConversionContextScope scope(context); 354 355 v8::Local<v8::Value> v8Value; 356 if (!getKey(key, v8Value)) 357 return true; 358 359 return get(key, value); 360 } 361 362 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const 363 { 364 v8::Local<v8::Value> v8Value; 365 if (!getKey(key, v8Value)) 366 return false; 367 368 // FIXME: Support array-like objects 369 if (!v8Value->IsArray()) 370 return false; 371 372 ASSERT(m_isolate); 373 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 374 v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); 375 for (size_t i = 0; i < v8Array->Length(); ++i) { 376 v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i, m_isolate)); 377 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false); 378 value.add(stringValue); 379 } 380 381 return true; 382 } 383 384 bool Dictionary::convert(ConversionContext& context, const String& key, HashSet<AtomicString>& value) const 385 { 386 ConversionContextScope scope(context); 387 388 v8::Local<v8::Value> v8Value; 389 if (!getKey(key, v8Value)) 390 return true; 391 392 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 393 return true; 394 395 if (!v8Value->IsArray()) { 396 context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key)); 397 return false; 398 } 399 400 return get(key, value); 401 } 402 403 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const 404 { 405 v8::Local<v8::Value> v8Value; 406 if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value)) 407 return false; 408 409 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); 410 value = stringValue; 411 return true; 412 } 413 414 bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const 415 { 416 v8::Local<v8::Value> v8Value; 417 if (!getKey(key, v8Value)) 418 return false; 419 420 value = 0; 421 if (V8Uint8Array::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 422 value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 423 return true; 424 } 425 426 bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const 427 { 428 v8::Local<v8::Value> v8Value; 429 if (!getKey(key, v8Value)) 430 return false; 431 432 value = 0; 433 if (V8ArrayBufferView::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 434 value = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 435 return true; 436 } 437 438 bool Dictionary::get(const String& key, RefPtr<MIDIPort>& value) const 439 { 440 v8::Local<v8::Value> v8Value; 441 if (!getKey(key, v8Value)) 442 return false; 443 444 value = 0; 445 if (V8MIDIPort::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 446 value = V8MIDIPort::toNative(v8::Handle<v8::Object>::Cast(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 = 0; 457 if (V8MediaKeyError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 458 value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 459 return true; 460 } 461 462 bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const 463 { 464 v8::Local<v8::Value> v8Value; 465 if (!getKey(key, v8Value)) 466 return false; 467 468 TrackBase* source = 0; 469 if (v8Value->IsObject()) { 470 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 471 472 // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once 473 // we add them. 474 v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::domTemplate(m_isolate, worldType(m_isolate))); 475 if (!track.IsEmpty()) 476 source = V8TextTrack::toNative(track); 477 } 478 value = source; 479 return true; 480 } 481 482 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) const 483 { 484 v8::Local<v8::Value> v8Value; 485 if (!getKey(key, v8Value)) 486 return false; 487 488 value = 0; 489 if (V8SpeechRecognitionError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 490 value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 491 return true; 492 } 493 494 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const 495 { 496 v8::Local<v8::Value> v8Value; 497 if (!getKey(key, v8Value)) 498 return false; 499 500 value = 0; 501 if (V8SpeechRecognitionResult::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 502 value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 503 return true; 504 } 505 506 bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const 507 { 508 v8::Local<v8::Value> v8Value; 509 if (!getKey(key, v8Value)) 510 return false; 511 512 value = 0; 513 if (V8SpeechRecognitionResultList::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 514 value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 515 return true; 516 } 517 518 bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const 519 { 520 v8::Local<v8::Value> v8Value; 521 if (!getKey(key, v8Value)) 522 return false; 523 524 value = 0; 525 if (V8MediaStream::hasInstance(v8Value, m_isolate, worldType(m_isolate))) 526 value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value)); 527 return true; 528 } 529 530 bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const 531 { 532 v8::Local<v8::Value> v8Value; 533 if (!getKey(key, v8Value)) 534 return false; 535 536 value = 0; 537 // We need to handle a DOMWindow specially, because a DOMWindow wrapper 538 // exists on a prototype chain of v8Value. 539 if (v8Value->IsObject()) { 540 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 541 v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); 542 if (!window.IsEmpty()) { 543 value = toWrapperTypeInfo(window)->toEventTarget(window); 544 return true; 545 } 546 } 547 548 if (V8DOMWrapper::isDOMWrapper(v8Value)) { 549 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 550 value = toWrapperTypeInfo(wrapper)->toEventTarget(wrapper); 551 } 552 return true; 553 } 554 555 bool Dictionary::get(const String& key, Dictionary& value) const 556 { 557 v8::Local<v8::Value> v8Value; 558 if (!getKey(key, v8Value)) 559 return false; 560 561 if (v8Value->IsObject()) { 562 ASSERT(m_isolate); 563 ASSERT(m_isolate == v8::Isolate::GetCurrent()); 564 value = Dictionary(v8Value, m_isolate); 565 } 566 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(i, m_isolate)); 600 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(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, RefPtr<DOMError>& value) const 661 { 662 v8::Local<v8::Value> v8Value; 663 if (!getKey(key, v8Value)) 664 return false; 665 666 DOMError* error = 0; 667 if (v8Value->IsObject()) { 668 v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); 669 v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::domTemplate(m_isolate, worldType(m_isolate))); 670 if (!domError.IsEmpty()) 671 error = V8DOMError::toNative(domError); 672 } 673 value = error; 674 return true; 675 } 676 677 bool Dictionary::get(const String& key, OwnPtr<VoidCallback>& value) const 678 { 679 v8::Local<v8::Value> v8Value; 680 if (!getKey(key, v8Value)) 681 return false; 682 683 if (!v8Value->IsFunction()) 684 return false; 685 686 value = V8VoidCallback::create(v8::Handle<v8::Function>::Cast(v8Value), getExecutionContext()); 687 return true; 688 } 689 690 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const 691 { 692 if (!isObject()) 693 return false; 694 695 v8::Handle<v8::Object> options = m_options->ToObject(); 696 if (options.IsEmpty()) 697 return false; 698 699 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 700 if (properties.IsEmpty()) 701 return true; 702 for (uint32_t i = 0; i < properties->Length(); ++i) { 703 v8::Local<v8::String> key = properties->Get(i)->ToString(); 704 if (!options->Has(key)) 705 continue; 706 707 v8::Local<v8::Value> value = options->Get(key); 708 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); 709 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, false); 710 if (!static_cast<const String&>(stringKey).isEmpty()) 711 hashMap.set(stringKey, stringValue); 712 } 713 714 return true; 715 } 716 717 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const 718 { 719 if (!isObject()) 720 return false; 721 722 v8::Handle<v8::Object> options = m_options->ToObject(); 723 if (options.IsEmpty()) 724 return false; 725 726 v8::Local<v8::Array> properties = options->GetOwnPropertyNames(); 727 if (properties.IsEmpty()) 728 return true; 729 for (uint32_t i = 0; i < properties->Length(); ++i) { 730 v8::Local<v8::String> key = properties->Get(i)->ToString(); 731 if (!options->Has(key)) 732 continue; 733 V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); 734 names.append(stringKey); 735 } 736 737 return true; 738 } 739 740 void Dictionary::ConversionContext::resetPerPropertyContext() 741 { 742 if (m_dirty) { 743 m_dirty = false; 744 m_isNullable = false; 745 m_propertyTypeName = ""; 746 } 747 } 748 749 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable) 750 { 751 ASSERT(!m_dirty); 752 m_dirty = true; 753 m_isNullable = isNullable; 754 m_propertyTypeName = typeName; 755 756 return *this; 757 } 758 759 void Dictionary::ConversionContext::throwTypeError(const String& detail) 760 { 761 if (forConstructor()) { 762 exceptionState().throwTypeError(detail); 763 } else { 764 ASSERT(!methodName().isEmpty()); 765 exceptionState().throwTypeError(ExceptionMessages::failedToExecute(interfaceName(), methodName(), detail)); 766 } 767 } 768 769 } // namespace WebCore 770