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
Dictionary()60 Dictionary::Dictionary()
61 : m_isolate(0)
62 {
63 }
64
Dictionary(const v8::Handle<v8::Value> & options,v8::Isolate * isolate)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
~Dictionary()72 Dictionary::~Dictionary()
73 {
74 }
75
operator =(const Dictionary & optionsObject)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
isObject() const83 bool Dictionary::isObject() const
84 {
85 return !isUndefinedOrNull() && m_options->IsObject();
86 }
87
isUndefinedOrNull() const88 bool Dictionary::isUndefinedOrNull() const
89 {
90 if (m_options.IsEmpty())
91 return true;
92 return WebCore::isUndefinedOrNull(m_options);
93 }
94
hasProperty(const String & key) const95 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
getKey(const String & key,v8::Local<v8::Value> & value) const111 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
get(const String & key,v8::Local<v8::Value> & value) const129 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
130 {
131 return getKey(key, value);
132 }
133
get(const String & key,bool & value) const134 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
convert(ConversionContext & context,const String & key,bool & value) const147 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
get(const String & key,int32_t & value) const154 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
get(const String & key,double & value,bool & hasValue) const167 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
get(const String & key,double & value) const183 bool Dictionary::get(const String& key, double& value) const
184 {
185 bool unused;
186 return get(key, value, unused);
187 }
188
convert(ConversionContext & context,const String & key,double & value) const189 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>
getStringType(const String & key,StringType & value) const202 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
get(const String & key,String & value) const213 bool Dictionary::get(const String& key, String& value) const
214 {
215 return getStringType(key, value);
216 }
217
get(const String & key,AtomicString & value) const218 bool Dictionary::get(const String& key, AtomicString& value) const
219 {
220 return getStringType(key, value);
221 }
222
convert(ConversionContext & context,const String & key,String & value) const223 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
get(const String & key,ScriptValue & value) const236 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
convert(ConversionContext & context,const String & key,ScriptValue & value) const246 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
get(const String & key,unsigned short & value) const254 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
get(const String & key,short & value) const267 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
get(const String & key,unsigned & value) const280 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
get(const String & key,unsigned long & value) const293 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
get(const String & key,unsigned long long & value) const306 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
get(const String & key,RefPtrWillBeMember<LocalDOMWindow> & value) const320 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
get(const String & key,RefPtrWillBeMember<Storage> & value) const332 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
get(const String & key,MessagePortArray & value) const342 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
convert(ConversionContext & context,const String & key,MessagePortArray & value) const357 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
get(const String & key,HashSet<AtomicString> & value) const368 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
convert(ConversionContext & context,const String & key,HashSet<AtomicString> & value) const390 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
getWithUndefinedOrNullCheck(const String & key,String & value) const409 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
get(const String & key,RefPtr<Uint8Array> & value) const420 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
get(const String & key,RefPtr<ArrayBufferView> & value) const430 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
get(const String & key,RefPtrWillBeMember<MIDIPort> & value) const440 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
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 = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value);
457 return true;
458 }
459
get(const String & key,RefPtrWillBeMember<TrackBase> & value) const460 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
get(const String & key,Member<SpeechRecognitionResult> & value) const480 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
get(const String & key,Member<SpeechRecognitionResultList> & value) const490 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
get(const String & key,Member<Gamepad> & value) const500 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
get(const String & key,RefPtr<MediaStream> & value) const510 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
get(const String & key,RefPtrWillBeMember<EventTarget> & value) const520 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
get(const String & key,Dictionary & value) const545 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
get(const String & key,RefPtr<HeaderMap> & value) const560 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
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(m_isolate, i));
600 TOSTRING_DEFAULT(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,RefPtrWillBeMember<DOMError> & value) const660 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
getOwnPropertiesAsStringHashMap(HashMap<String,String> & hashMap) const670 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
getOwnPropertyNames(Vector<String> & names) const697 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
resetPerPropertyContext()720 void Dictionary::ConversionContext::resetPerPropertyContext()
721 {
722 if (m_dirty) {
723 m_dirty = false;
724 m_isNullable = false;
725 m_propertyTypeName = "";
726 }
727 }
728
setConversionType(const String & typeName,bool isNullable)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
throwTypeError(const String & detail)739 void Dictionary::ConversionContext::throwTypeError(const String& detail)
740 {
741 exceptionState().throwTypeError(detail);
742 }
743
744 } // namespace WebCore
745