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
Dictionary()61 Dictionary::Dictionary()
62 : m_isolate(0)
63 {
64 }
65
Dictionary(const v8::Handle<v8::Value> & options,v8::Isolate * isolate)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
~Dictionary()73 Dictionary::~Dictionary()
74 {
75 }
76
operator =(const Dictionary & optionsObject)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
isObject() const84 bool Dictionary::isObject() const
85 {
86 return !isUndefinedOrNull() && m_options->IsObject();
87 }
88
isUndefinedOrNull() const89 bool Dictionary::isUndefinedOrNull() const
90 {
91 if (m_options.IsEmpty())
92 return true;
93 return WebCore::isUndefinedOrNull(m_options);
94 }
95
hasProperty(const String & key) const96 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
getKey(const String & key,v8::Local<v8::Value> & value) const112 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
get(const String & key,v8::Local<v8::Value> & value) const130 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
131 {
132 return getKey(key, value);
133 }
134
get(const String & key,bool & value) const135 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
convert(ConversionContext & context,const String & key,bool & value) const148 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
get(const String & key,int32_t & value) const155 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
get(const String & key,double & value,bool & hasValue) const168 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
get(const String & key,double & value) const184 bool Dictionary::get(const String& key, double& value) const
185 {
186 bool unused;
187 return get(key, value, unused);
188 }
189
convert(ConversionContext & context,const String & key,double & value) const190 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
get(const String & key,String & value) const202 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
convert(ConversionContext & context,const String & key,String & value) const213 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
get(const String & key,ScriptValue & value) const226 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
convert(ConversionContext & context,const String & key,ScriptValue & value) const236 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
get(const String & key,unsigned short & value) const244 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
get(const String & key,short & value) const257 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
get(const String & key,unsigned & value) const270 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
get(const String & key,unsigned long & value) const283 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
get(const String & key,unsigned long long & value) const296 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
get(const String & key,RefPtr<DOMWindow> & value) const310 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
get(const String & key,RefPtr<Storage> & value) const328 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
get(const String & key,MessagePortArray & value) const340 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
convert(ConversionContext & context,const String & key,MessagePortArray & value) const351 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
get(const String & key,HashSet<AtomicString> & value) const362 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
convert(ConversionContext & context,const String & key,HashSet<AtomicString> & value) const384 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
getWithUndefinedOrNullCheck(const String & key,String & value) const403 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
get(const String & key,RefPtr<Uint8Array> & value) const414 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
get(const String & key,RefPtr<ArrayBufferView> & value) const426 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
get(const String & key,RefPtr<MIDIPort> & value) const438 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
get(const String & key,RefPtr<MediaKeyError> & value) const450 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
get(const String & key,RefPtr<TrackBase> & value) const462 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
get(const String & key,RefPtr<SpeechRecognitionError> & value) const482 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
get(const String & key,RefPtr<SpeechRecognitionResult> & value) const494 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
get(const String & key,RefPtr<SpeechRecognitionResultList> & value) const506 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
get(const String & key,RefPtr<MediaStream> & value) const518 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
get(const String & key,RefPtr<EventTarget> & value) const530 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
get(const String & key,Dictionary & value) const555 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
convert(ConversionContext & context,const String & key,Dictionary & value) const570 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
get(const String & key,Vector<String> & value) const588 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
convert(ConversionContext & context,const String & key,Vector<String> & value) const607 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
get(const String & key,ArrayValue & value) const626 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
convert(ConversionContext & context,const String & key,ArrayValue & value) const641 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
get(const String & key,RefPtr<DOMError> & value) const660 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
get(const String & key,OwnPtr<VoidCallback> & value) const677 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
getOwnPropertiesAsStringHashMap(HashMap<String,String> & hashMap) const690 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
getOwnPropertyNames(Vector<String> & names) const717 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
resetPerPropertyContext()740 void Dictionary::ConversionContext::resetPerPropertyContext()
741 {
742 if (m_dirty) {
743 m_dirty = false;
744 m_isNullable = false;
745 m_propertyTypeName = "";
746 }
747 }
748
setConversionType(const String & typeName,bool isNullable)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
throwTypeError(const String & detail)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