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/core/v8/Dictionary.h"
28
29 #include "bindings/core/v8/ArrayValue.h"
30 #include "bindings/core/v8/ExceptionMessages.h"
31 #include "bindings/core/v8/ExceptionState.h"
32 #include "bindings/core/v8/V8Binding.h"
33 #include "bindings/core/v8/V8DOMError.h"
34 #include "bindings/core/v8/V8Element.h"
35 #include "bindings/core/v8/V8EventTarget.h"
36 #include "bindings/core/v8/V8MediaKeyError.h"
37 #include "bindings/core/v8/V8MessagePort.h"
38 #include "bindings/core/v8/V8Path2D.h"
39 #include "bindings/core/v8/V8Storage.h"
40 #include "bindings/core/v8/V8TextTrack.h"
41 #include "bindings/core/v8/V8VoidCallback.h"
42 #include "bindings/core/v8/V8Window.h"
43 #include "bindings/core/v8/custom/V8ArrayBufferViewCustom.h"
44 #include "bindings/core/v8/custom/V8Uint8ArrayCustom.h"
45 #include "bindings/modules/v8/V8Gamepad.h"
46 #include "bindings/modules/v8/V8Headers.h"
47 #include "bindings/modules/v8/V8IDBKeyRange.h"
48 #include "bindings/modules/v8/V8MIDIPort.h"
49 #include "bindings/modules/v8/V8MediaStream.h"
50 #include "bindings/modules/v8/V8SpeechRecognitionResult.h"
51 #include "bindings/modules/v8/V8SpeechRecognitionResultList.h"
52 #include "core/html/track/TrackBase.h"
53 #include "modules/gamepad/Gamepad.h"
54 #include "modules/indexeddb/IDBKeyRange.h"
55 #include "modules/mediastream/MediaStream.h"
56 #include "modules/speech/SpeechRecognitionResult.h"
57 #include "modules/speech/SpeechRecognitionResultList.h"
58 #include "wtf/MathExtras.h"
59
60 namespace blink {
61
Dictionary()62 Dictionary::Dictionary()
63 : m_isolate(0)
64 {
65 }
66
Dictionary(const v8::Handle<v8::Value> & options,v8::Isolate * isolate)67 Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate)
68 : m_options(options)
69 , m_isolate(isolate)
70 {
71 ASSERT(m_isolate);
72 }
73
~Dictionary()74 Dictionary::~Dictionary()
75 {
76 }
77
operator =(const Dictionary & optionsObject)78 Dictionary& Dictionary::operator=(const Dictionary& optionsObject)
79 {
80 m_options = optionsObject.m_options;
81 m_isolate = optionsObject.m_isolate;
82 return *this;
83 }
84
createEmpty(v8::Isolate * isolate)85 Dictionary Dictionary::createEmpty(v8::Isolate* isolate)
86 {
87 return Dictionary(v8::Object::New(isolate), isolate);
88 }
89
isObject() const90 bool Dictionary::isObject() const
91 {
92 return !isUndefinedOrNull() && m_options->IsObject();
93 }
94
isUndefinedOrNull() const95 bool Dictionary::isUndefinedOrNull() const
96 {
97 if (m_options.IsEmpty())
98 return true;
99 return blink::isUndefinedOrNull(m_options);
100 }
101
hasProperty(const String & key) const102 bool Dictionary::hasProperty(const String& key) const
103 {
104 if (isUndefinedOrNull())
105 return false;
106 v8::Local<v8::Object> options = m_options->ToObject();
107 ASSERT(!options.IsEmpty());
108
109 ASSERT(m_isolate);
110 ASSERT(m_isolate == v8::Isolate::GetCurrent());
111 v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
112 if (!options->Has(v8Key))
113 return false;
114
115 return true;
116 }
117
getKey(const String & key,v8::Local<v8::Value> & value) const118 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
119 {
120 if (isUndefinedOrNull())
121 return false;
122 v8::Local<v8::Object> options = m_options->ToObject();
123 ASSERT(!options.IsEmpty());
124
125 ASSERT(m_isolate);
126 ASSERT(m_isolate == v8::Isolate::GetCurrent());
127 v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
128 if (!options->Has(v8Key))
129 return false;
130 value = options->Get(v8Key);
131 if (value.IsEmpty())
132 return false;
133 return true;
134 }
135
get(const String & key,v8::Local<v8::Value> & value) const136 bool Dictionary::get(const String& key, v8::Local<v8::Value>& value) const
137 {
138 return getKey(key, value);
139 }
140
getWithUndefinedOrNullCheck(const String & key,String & value) const141 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
142 {
143 v8::Local<v8::Value> v8Value;
144 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
145 return false;
146
147 TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false);
148 value = stringValue;
149 return true;
150 }
151
getWithUndefinedOrNullCheck(const String & key,RefPtrWillBeMember<Element> & value) const152 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Element>& value) const
153 {
154 v8::Local<v8::Value> v8Value;
155 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
156 return false;
157
158 value = V8Element::toImplWithTypeCheck(m_isolate, v8Value);
159 return true;
160 }
161
getWithUndefinedOrNullCheck(const String & key,RefPtrWillBeMember<Path2D> & value) const162 bool Dictionary::getWithUndefinedOrNullCheck(const String& key, RefPtrWillBeMember<Path2D>& value) const
163 {
164 v8::Local<v8::Value> v8Value;
165 if (!getKey(key, v8Value) || blink::isUndefinedOrNull(v8Value))
166 return false;
167
168 value = V8Path2D::toImplWithTypeCheck(m_isolate, v8Value);
169 return true;
170 }
171
get(const String & key,Dictionary & value) const172 bool Dictionary::get(const String& key, Dictionary& value) const
173 {
174 v8::Local<v8::Value> v8Value;
175 if (!getKey(key, v8Value))
176 return false;
177
178 if (v8Value->IsObject()) {
179 ASSERT(m_isolate);
180 ASSERT(m_isolate == v8::Isolate::GetCurrent());
181 value = Dictionary(v8Value, m_isolate);
182 }
183
184 return true;
185 }
186
set(const String & key,const v8::Handle<v8::Value> & value)187 bool Dictionary::set(const String& key, const v8::Handle<v8::Value>& value)
188 {
189 if (isUndefinedOrNull())
190 return false;
191 v8::Local<v8::Object> options = m_options->ToObject();
192 ASSERT(!options.IsEmpty());
193
194 return options->Set(v8String(m_isolate, key), value);
195 }
196
set(const String & key,const String & value)197 bool Dictionary::set(const String& key, const String& value)
198 {
199 return set(key, v8String(m_isolate, value));
200 }
201
set(const String & key,unsigned value)202 bool Dictionary::set(const String& key, unsigned value)
203 {
204 return set(key, v8::Integer::NewFromUnsigned(m_isolate, value));
205 }
206
set(const String & key,const Dictionary & value)207 bool Dictionary::set(const String& key, const Dictionary& value)
208 {
209 return set(key, value.v8Value());
210 }
211
convert(ConversionContext & context,const String & key,Dictionary & value) const212 bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const
213 {
214 ConversionContextScope scope(context);
215
216 v8::Local<v8::Value> v8Value;
217 if (!getKey(key, v8Value))
218 return true;
219
220 if (v8Value->IsObject())
221 return get(key, value);
222
223 if (context.isNullable() && blink::isUndefinedOrNull(v8Value))
224 return true;
225
226 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type."));
227 return false;
228 }
229
getOwnPropertiesAsStringHashMap(HashMap<String,String> & hashMap) const230 bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMap) const
231 {
232 if (!isObject())
233 return false;
234
235 v8::Handle<v8::Object> options = m_options->ToObject();
236 if (options.IsEmpty())
237 return false;
238
239 v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
240 if (properties.IsEmpty())
241 return true;
242 for (uint32_t i = 0; i < properties->Length(); ++i) {
243 v8::Local<v8::String> key = properties->Get(i)->ToString();
244 if (!options->Has(key))
245 continue;
246
247 v8::Local<v8::Value> value = options->Get(key);
248 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
249 TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false);
250 if (!static_cast<const String&>(stringKey).isEmpty())
251 hashMap.set(stringKey, stringValue);
252 }
253
254 return true;
255 }
256
getOwnPropertyNames(Vector<String> & names) const257 bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
258 {
259 if (!isObject())
260 return false;
261
262 v8::Handle<v8::Object> options = m_options->ToObject();
263 if (options.IsEmpty())
264 return false;
265
266 v8::Local<v8::Array> properties = options->GetOwnPropertyNames();
267 if (properties.IsEmpty())
268 return true;
269 for (uint32_t i = 0; i < properties->Length(); ++i) {
270 v8::Local<v8::String> key = properties->Get(i)->ToString();
271 if (!options->Has(key))
272 continue;
273 TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false);
274 names.append(stringKey);
275 }
276
277 return true;
278 }
279
resetPerPropertyContext()280 void Dictionary::ConversionContext::resetPerPropertyContext()
281 {
282 if (m_dirty) {
283 m_dirty = false;
284 m_isNullable = false;
285 m_propertyTypeName = "";
286 }
287 }
288
setConversionType(const String & typeName,bool isNullable)289 Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable)
290 {
291 ASSERT(!m_dirty);
292 m_dirty = true;
293 m_isNullable = isNullable;
294 m_propertyTypeName = typeName;
295
296 return *this;
297 }
298
throwTypeError(const String & detail)299 void Dictionary::ConversionContext::throwTypeError(const String& detail)
300 {
301 exceptionState().throwTypeError(detail);
302 }
303
304 } // namespace blink
305