Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / v8 / Dictionary.cpp
index dc14888..bd039fd 100644 (file)
@@ -31,6 +31,7 @@
 #include "V8IDBKeyRange.h"
 #include "V8MIDIPort.h"
 #include "V8MediaKeyError.h"
+#include "V8MessagePort.h"
 #include "V8SpeechRecognitionError.h"
 #include "V8SpeechRecognitionResult.h"
 #include "V8SpeechRecognitionResultList.h"
@@ -38,6 +39,8 @@
 #include "V8VoidCallback.h"
 #include "V8Window.h"
 #include "bindings/v8/ArrayValue.h"
+#include "bindings/v8/ExceptionMessages.h"
+#include "bindings/v8/ExceptionState.h"
 #include "bindings/v8/V8Binding.h"
 #include "bindings/v8/V8Utilities.h"
 #include "bindings/v8/custom/V8ArrayBufferViewCustom.h"
@@ -61,7 +64,7 @@ Dictionary::Dictionary()
 {
 }
 
-Dictionary::Dictionary(const v8::Local<v8::Value>& options, v8::Isolate* isolate)
+Dictionary::Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate* isolate)
     : m_options(options)
     , m_isolate(isolate)
 {
@@ -91,6 +94,22 @@ bool Dictionary::isUndefinedOrNull() const
     return WebCore::isUndefinedOrNull(m_options);
 }
 
+bool Dictionary::hasProperty(const String& key) const
+{
+    if (isUndefinedOrNull())
+        return false;
+    v8::Local<v8::Object> options = m_options->ToObject();
+    ASSERT(!options.IsEmpty());
+
+    ASSERT(m_isolate);
+    ASSERT(m_isolate == v8::Isolate::GetCurrent());
+    v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
+    if (!options->Has(v8Key))
+        return false;
+
+    return true;
+}
+
 bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
 {
     if (isUndefinedOrNull())
@@ -100,7 +119,7 @@ bool Dictionary::getKey(const String& key, v8::Local<v8::Value>& value) const
 
     ASSERT(m_isolate);
     ASSERT(m_isolate == v8::Isolate::GetCurrent());
-    v8::Handle<v8::String> v8Key = v8String(key, m_isolate);
+    v8::Handle<v8::String> v8Key = v8String(m_isolate, key);
     if (!options->Has(v8Key))
         return false;
     value = options->Get(v8Key);
@@ -127,6 +146,13 @@ bool Dictionary::get(const String& key, bool& value) const
     return true;
 }
 
+bool Dictionary::convert(ConversionContext& context, const String& key, bool& value) const
+{
+    ConversionContextScope scope(context);
+    get(key, value);
+    return true;
+}
+
 bool Dictionary::get(const String& key, int32_t& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -149,7 +175,7 @@ bool Dictionary::get(const String& key, double& value, bool& hasValue) const
     }
 
     hasValue = true;
-    v8::Local<v8::Number> v8Number = v8Value->ToNumber();
+    V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
     if (v8Number.IsEmpty())
         return false;
     value = v8Number->Value();
@@ -162,7 +188,20 @@ bool Dictionary::get(const String& key, double& value) const
     return get(key, value, unused);
 }
 
-bool Dictionary::get(const String& key, String& value) const
+bool Dictionary::convert(ConversionContext& context, const String& key, double& value) const
+{
+    ConversionContextScope scope(context);
+
+    bool hasValue = false;
+    if (!get(key, value, hasValue) && hasValue) {
+        context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "is not of type 'double'."));
+        return false;
+    }
+    return true;
+}
+
+template<typename StringType>
+inline bool Dictionary::getStringType(const String& key, StringType& value) const
 {
     v8::Local<v8::Value> v8Value;
     if (!getKey(key, v8Value))
@@ -173,6 +212,29 @@ bool Dictionary::get(const String& key, String& value) const
     return true;
 }
 
+bool Dictionary::get(const String& key, String& value) const
+{
+    return getStringType(key, value);
+}
+
+bool Dictionary::get(const String& key, AtomicString& value) const
+{
+    return getStringType(key, value);
+}
+
+bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const
+{
+    ConversionContextScope scope(context);
+
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value))
+        return true;
+
+    V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false);
+    value = stringValue;
+    return true;
+}
+
 bool Dictionary::get(const String& key, ScriptValue& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -183,6 +245,14 @@ bool Dictionary::get(const String& key, ScriptValue& value) const
     return true;
 }
 
+bool Dictionary::convert(ConversionContext& context, const String& key, ScriptValue& value) const
+{
+    ConversionContextScope scope(context);
+
+    get(key, value);
+    return true;
+}
+
 bool Dictionary::get(const String& key, unsigned short& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -241,7 +311,7 @@ bool Dictionary::get(const String& key, unsigned long long& value) const
     if (!getKey(key, v8Value))
         return false;
 
-    v8::Local<v8::Number> v8Number = v8Value->ToNumber();
+    V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false);
     if (v8Number.IsEmpty())
         return false;
     double d = v8Number->Value();
@@ -257,24 +327,18 @@ bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const
 
     // We need to handle a DOMWindow specially, because a DOMWindow wrapper
     // exists on a prototype chain of v8Value.
-    value = 0;
-    if (v8Value->IsObject()) {
-        v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
-        v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::GetTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
-        if (!window.IsEmpty())
-            value = V8Window::toNative(window);
-    }
+    value = toDOMWindow(v8Value, m_isolate);
     return true;
 }
 
-bool Dictionary::get(const String& key, RefPtr<Storage>& value) const
+bool Dictionary::get(const String& key, RefPtrWillBeRawPtr<Storage>& value) const
 {
     v8::Local<v8::Value> v8Value;
     if (!getKey(key, v8Value))
         return false;
 
     value = 0;
-    if (V8Storage::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8Storage::hasInstance(v8Value, m_isolate))
         value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -287,7 +351,22 @@ bool Dictionary::get(const String& key, MessagePortArray& value) const
 
     ASSERT(m_isolate);
     ASSERT(m_isolate == v8::Isolate::GetCurrent());
-    return getMessagePortArray(v8Value, key, value, m_isolate);
+    if (WebCore::isUndefinedOrNull(v8Value))
+        return true;
+    bool success = false;
+    value = toRefPtrNativeArray<MessagePort, V8MessagePort>(v8Value, key, m_isolate, &success);
+    return success;
+}
+
+bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const
+{
+    ConversionContextScope scope(context);
+
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value))
+        return true;
+
+    return get(key, value);
 }
 
 bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
@@ -304,7 +383,7 @@ bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
     ASSERT(m_isolate == v8::Isolate::GetCurrent());
     v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
     for (size_t i = 0; i < v8Array->Length(); ++i) {
-        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i, m_isolate));
+        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(m_isolate, i));
         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false);
         value.add(stringValue);
     }
@@ -312,17 +391,31 @@ bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const
     return true;
 }
 
-bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
+bool Dictionary::convert(ConversionContext& context, const String& key, HashSet<AtomicString>& value) const
 {
+    ConversionContextScope scope(context);
+
     v8::Local<v8::Value> v8Value;
-    if (!getKey(key, v8Value) || v8Value->IsNull() || v8Value->IsUndefined())
-        return false;
+    if (!getKey(key, v8Value))
+        return true;
 
-    if (WebCore::isUndefinedOrNull(v8Value)) {
-        value = String();
+    if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
         return true;
+
+    if (!v8Value->IsArray()) {
+        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
+        return false;
     }
 
+    return get(key, value);
+}
+
+bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) const
+{
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value))
+        return false;
+
     V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false);
     value = stringValue;
     return true;
@@ -335,7 +428,7 @@ bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const
         return false;
 
     value = 0;
-    if (V8Uint8Array::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8Uint8Array::hasInstance(v8Value, m_isolate))
         value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -347,7 +440,7 @@ bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const
         return false;
 
     value = 0;
-    if (V8ArrayBufferView::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8ArrayBufferView::hasInstance(v8Value, m_isolate))
         value = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -359,7 +452,7 @@ bool Dictionary::get(const String& key, RefPtr<MIDIPort>& value) const
         return false;
 
     value = 0;
-    if (V8MIDIPort::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8MIDIPort::hasInstance(v8Value, m_isolate))
         value = V8MIDIPort::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -371,7 +464,7 @@ bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const
         return false;
 
     value = 0;
-    if (V8MediaKeyError::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8MediaKeyError::hasInstance(v8Value, m_isolate))
         value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -388,7 +481,7 @@ bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const
 
         // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once
         // we add them.
-        v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::GetTemplate(m_isolate, worldType(m_isolate)));
+        v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::domTemplate(m_isolate, worldType(m_isolate)));
         if (!track.IsEmpty())
             source = V8TextTrack::toNative(track);
     }
@@ -403,31 +496,31 @@ bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) c
         return false;
 
     value = 0;
-    if (V8SpeechRecognitionError::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8SpeechRecognitionError::hasInstance(v8Value, m_isolate))
         value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
 
-bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const
+bool Dictionary::get(const String& key, RefPtrWillBeRawPtr<SpeechRecognitionResult>& value) const
 {
     v8::Local<v8::Value> v8Value;
     if (!getKey(key, v8Value))
         return false;
 
     value = 0;
-    if (V8SpeechRecognitionResult::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8SpeechRecognitionResult::hasInstance(v8Value, m_isolate))
         value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
 
-bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const
+bool Dictionary::get(const String& key, RefPtrWillBeRawPtr<SpeechRecognitionResultList>& value) const
 {
     v8::Local<v8::Value> v8Value;
     if (!getKey(key, v8Value))
         return false;
 
     value = 0;
-    if (V8SpeechRecognitionResultList::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8SpeechRecognitionResultList::hasInstance(v8Value, m_isolate))
         value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -439,7 +532,7 @@ bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const
         return false;
 
     value = 0;
-    if (V8MediaStream::HasInstance(v8Value, m_isolate, worldType(m_isolate)))
+    if (V8MediaStream::hasInstance(v8Value, m_isolate))
         value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value));
     return true;
 }
@@ -455,7 +548,7 @@ bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const
     // exists on a prototype chain of v8Value.
     if (v8Value->IsObject()) {
         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
-        v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::GetTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
+        v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate)));
         if (!window.IsEmpty()) {
             value = toWrapperTypeInfo(window)->toEventTarget(window);
             return true;
@@ -484,6 +577,24 @@ bool Dictionary::get(const String& key, Dictionary& value) const
     return true;
 }
 
+bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const
+{
+    ConversionContextScope scope(context);
+
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value))
+        return true;
+
+    if (v8Value->IsObject())
+        return get(key, value);
+
+    if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
+        return true;
+
+    context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a Dictionary type."));
+    return false;
+}
+
 bool Dictionary::get(const String& key, Vector<String>& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -495,7 +606,7 @@ bool Dictionary::get(const String& key, Vector<String>& value) const
 
     v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
     for (size_t i = 0; i < v8Array->Length(); ++i) {
-        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(i, m_isolate));
+        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(m_isolate, i));
         V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false);
         value.append(stringValue);
     }
@@ -503,6 +614,25 @@ bool Dictionary::get(const String& key, Vector<String>& value) const
     return true;
 }
 
+bool Dictionary::convert(ConversionContext& context, const String& key, Vector<String>& value) const
+{
+    ConversionContextScope scope(context);
+
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value))
+        return true;
+
+    if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
+        return true;
+
+    if (!v8Value->IsArray()) {
+        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
+        return false;
+    }
+
+    return get(key, value);
+}
+
 bool Dictionary::get(const String& key, ArrayValue& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -518,6 +648,25 @@ bool Dictionary::get(const String& key, ArrayValue& value) const
     return true;
 }
 
+bool Dictionary::convert(ConversionContext& context, const String& key, ArrayValue& value) const
+{
+    ConversionContextScope scope(context);
+
+    v8::Local<v8::Value> v8Value;
+    if (!getKey(key, v8Value))
+        return true;
+
+    if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value))
+        return true;
+
+    if (!v8Value->IsArray()) {
+        context.throwTypeError(ExceptionMessages::notASequenceTypeProperty(key));
+        return false;
+    }
+
+    return get(key, value);
+}
+
 bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const
 {
     v8::Local<v8::Value> v8Value;
@@ -527,7 +676,7 @@ bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const
     DOMError* error = 0;
     if (v8Value->IsObject()) {
         v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value);
-        v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::GetTemplate(m_isolate, worldType(m_isolate)));
+        v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::domTemplate(m_isolate, worldType(m_isolate)));
         if (!domError.IsEmpty())
             error = V8DOMError::toNative(domError);
     }
@@ -535,7 +684,7 @@ bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const
     return true;
 }
 
-bool Dictionary::get(const String& key, RefPtr<VoidCallback>& value) const
+bool Dictionary::get(const String& key, OwnPtr<VoidCallback>& value) const
 {
     v8::Local<v8::Value> v8Value;
     if (!getKey(key, v8Value))
@@ -544,7 +693,7 @@ bool Dictionary::get(const String& key, RefPtr<VoidCallback>& value) const
     if (!v8Value->IsFunction())
         return false;
 
-    value = V8VoidCallback::create(v8Value, getExecutionContext());
+    value = V8VoidCallback::create(v8::Handle<v8::Function>::Cast(v8Value), currentExecutionContext(m_isolate));
     return true;
 }
 
@@ -598,4 +747,33 @@ bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
     return true;
 }
 
+void Dictionary::ConversionContext::resetPerPropertyContext()
+{
+    if (m_dirty) {
+        m_dirty = false;
+        m_isNullable = false;
+        m_propertyTypeName = "";
+    }
+}
+
+Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType(const String& typeName, bool isNullable)
+{
+    ASSERT(!m_dirty);
+    m_dirty = true;
+    m_isNullable = isNullable;
+    m_propertyTypeName = typeName;
+
+    return *this;
+}
+
+void Dictionary::ConversionContext::throwTypeError(const String& detail)
+{
+    if (forConstructor()) {
+        exceptionState().throwTypeError(detail);
+    } else {
+        ASSERT(!methodName().isEmpty());
+        exceptionState().throwTypeError(ExceptionMessages::failedToExecute(interfaceName(), methodName(), detail));
+    }
+}
+
 } // namespace WebCore