Index: Source/WebCore/bindings/dart/DartDOMWrapper.h |
diff --git a/Source/WebCore/bindings/dart/DartDOMWrapper.h b/Source/WebCore/bindings/dart/DartDOMWrapper.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..45cde007cc49999a2a40d9455cf0d3b11dcc3253 |
--- /dev/null |
+++ b/Source/WebCore/bindings/dart/DartDOMWrapper.h |
@@ -0,0 +1,622 @@ |
+// Copyright 2011, Google Inc. |
+// All rights reserved. |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following disclaimer |
+// in the documentation and/or other materials provided with the |
+// distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived from |
+// this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+#ifndef DartDOMWrapper_h |
+#define DartDOMWrapper_h |
+ |
+#include "DartScriptValueDeserializer.h" |
+#include "DartUtilities.h" |
+#include "EventListener.h" |
+#include "EventTarget.h" |
+#include "ExceptionCode.h" |
+#include "MediaQueryListListener.h" |
+#include "OptionsObject.h" |
+#include "Range.h" |
+#include "ScriptValue.h" |
+#include "SerializedScriptValue.h" |
+#if ENABLE(SVG) |
+#include "SVGPropertyTearOff.h" |
+#endif |
+#include "VoidCallback.h" |
+#include "npruntime_impl.h" |
+ |
+#include <bindings/npruntime.h> |
+#include <dart_api.h> |
+#include <wtf/PassRefPtr.h> |
+#include <wtf/RefPtr.h> |
+#include <wtf/text/AtomicString.h> |
+#include <wtf/text/WTFString.h> |
+ |
+namespace WebCore { |
+ |
+#if ENABLE(FILE_SYSTEM) |
+class Entry; |
+class EntrySync; |
+#endif |
+ |
+#if ENABLE(INDEXED_DATABASE) |
+class IDBAny; |
+class IDBKey; |
+#endif |
+ |
+#if ENABLE(SVG) |
+class SVGPathSeg; |
+#endif |
+ |
+enum ConversionFlag { |
+ ConvertNone = 0, |
+ ConvertDefaultToNull = 1 |
+}; |
+ |
+// The only purpose of this template declaration is to prohibit implicit |
+// conversions of toDartValue parameter. |
+template <typename Type> |
+Dart_Handle toDartValue(Type value); |
+ |
+template <typename Type> |
+Dart_Handle toDartValue(Type value, ConversionFlag); |
+ |
+template <typename Type> |
+inline Dart_Handle toDartValue(PassRefPtr<Type> value) |
+{ |
+ return toDartValue(value.get()); |
+} |
+ |
+inline Dart_Handle toDartValue(const AtomicString& value, ConversionFlag flag = ConvertNone) |
+{ |
+ if ((flag & ConvertDefaultToNull) && value.isNull()) |
+ return 0; |
+ return DartUtilities::stringToDartString(value); |
+} |
+ |
+inline Dart_Handle toDartValue(const String& value, ConversionFlag flag = ConvertNone) |
+{ |
+ if ((flag & ConvertDefaultToNull) && value.isNull()) |
+ return 0; |
+ return DartUtilities::stringToDartString(value); |
+} |
+ |
+inline Dart_Handle toDartValue(bool value) |
+{ |
+ return Dart_NewBoolean(value); |
+} |
+ |
+inline Dart_Handle toDartValue(unsigned long long value) |
+{ |
+ // FIXME: WebIDL unsigned long long is guaranteed to fit into 64-bit unsigned, |
+ // so we need a dart API for constructing an integer from uint64_t. |
+ ASSERT(value <= 0x7fffffffffffffffLL); |
+ return Dart_NewInteger(static_cast<int64_t>(value)); |
+} |
+ |
+inline Dart_Handle toDartValue(int64_t value) |
+{ |
+ return Dart_NewInteger(value); |
+} |
+ |
+inline Dart_Handle toDartValue(intptr_t value) |
+{ |
+ return Dart_NewInteger(value); |
+} |
+ |
+inline Dart_Handle toDartValue(float value) |
+{ |
+ return Dart_NewDouble(value); |
+} |
+ |
+inline Dart_Handle toDartValue(double value) |
+{ |
+ return Dart_NewDouble(value); |
+} |
+ |
+inline Dart_Handle toDartValue(const KURL& value, ConversionFlag flag = ConvertNone) |
+{ |
+ return toDartValue(value.string(), flag); |
+} |
+ |
+inline Dart_Handle toDartValue(const ScriptValue& value) |
+{ |
+ // FIXME: dart specific implementation of ScriptValue and |
+ // proper conversion. |
+ DART_UNIMPLEMENTED(); |
+ return 0; |
+} |
+ |
+inline Dart_Handle toDartValue(SerializedScriptValue* value) |
+{ |
+ // FIXME: better error handling. |
+ DartScriptValueDeserializer deserializer; |
+ if (!value->deserialize(&deserializer)) |
+ return 0; |
+ return deserializer.result(); |
+} |
+ |
+Dart_Handle toDartValue(NPObject* object); |
+ |
+class ContainerNode; |
+Dart_Handle toDartValue(ContainerNode*); |
+ |
+class CSSMutableStyleDeclaration; |
+Dart_Handle toDartValue(CSSMutableStyleDeclaration*); |
+ |
+class HTMLFormControlElement; |
+Dart_Handle toDartValue(HTMLFormControlElement*); |
+ |
+class DartDOMWrapper { |
+public: |
+ template <class WebkitClass> |
+ static Dart_Handle newWrapper(const char* className, WebkitClass* domObject) |
+ { |
+ Dart_Handle wrapper = instantiateWrapper(className); |
+ installNativePointers(domObject, wrapper); |
+ return wrapper; |
+ } |
+ |
+ template <class BindingsClass> |
+ static Dart_Handle toDart(typename BindingsClass::NativeType* instance) |
+ { |
+ return toDart(instance, BindingsClass::dartImplementationClassName); |
+ } |
+ |
+ template <class WebkitClass> |
+ static Dart_Handle toDart(WebkitClass* instance, const char* className) |
+ { |
+ if (!instance) |
+ return 0; |
+ |
+ // FIXME: custom toDartValue implementations should check the cache first. |
+ // FIXME: separate maps for nodes, dom objects and active dom objects. |
+ DartDOMMap* domMap = DartUtilities::domMapForCurrentIsolate(); |
+ Dart_Handle wrapper = domMap->get(instance); |
+ if (wrapper) |
+ return wrapper; |
+ |
+ wrapper = instantiateWrapper(className); |
+ bindDOMObjectToDartWrapper(instance, wrapper); |
+ return wrapper; |
+ } |
+ |
+ template <class WebkitClass> |
+ static void bindDOMObjectToDartWrapper(WebkitClass* domObject, Dart_Handle wrapper) |
+ { |
+ ASSERT(domObject); |
+ domObject->ref(); |
+ installNativePointers(domObject, wrapper); |
+ |
+ // FIXME: make persistent handle weak and deref domObject in weak callback. |
+ Dart_Handle persistentWrapperHandle = Dart_NewPersistentHandle(wrapper); |
+ |
+ DartDOMMap* domMap = DartUtilities::domMapForCurrentIsolate(); |
+ ASSERT(!domMap->contains(domObject)); |
+ domMap->set(domObject, persistentWrapperHandle); |
+ } |
+ |
+ template <class BindingsClass> |
+ static typename BindingsClass::NativeType* unwrapDartWrapper(Dart_Handle wrapper, Dart_Handle& exception) |
+ { |
+ // FIXME: support cross-domain wrappers. |
+ if (!instanceOf(BindingsClass::dartImplementationClassName, wrapper, exception)) |
+ return 0; |
+ ASSERT(!exception); |
+ void* nativePointer = readNativePointer(wrapper, kNativeImplementationIndex); |
+ return reinterpret_cast<typename BindingsClass::NativeType*>(nativePointer); |
+ } |
+ |
+ static void derefDOMObject(Dart_Handle wrapper, void* domObject); |
+ |
+ template <class WebkitClass> |
+ static WebkitClass* receiver(Dart_NativeArguments args) |
+ { |
+ // Type of receiver is ensured by Dart VM runtime, so bypass additional checks. |
+ void* nativePointer = readNativePointer(Dart_GetNativeArgument(args, 0), kNativeImplementationIndex); |
+ WebkitClass* const recv = static_cast<WebkitClass*>(nativePointer); |
+ ASSERT(recv); // Never should return 0. |
+ return recv; |
+ } |
+ |
+ template <typename Type> |
+ static void returnValue(Dart_NativeArguments args, const Type& value) |
+ { |
+ Dart_Handle result = toDartValue(value); |
+ if (result) |
+ Dart_SetReturnValue(args, result); |
+ } |
+ |
+ static int wrapperNativeFieldCount() { return kNativeFieldCount; } |
+ |
+ template <typename Type> |
+ static void returnValue(Dart_NativeArguments args, const Type& value, ConversionFlag flag) |
+ { |
+ Dart_Handle result = toDartValue(value, flag); |
+ if (result) |
+ Dart_SetReturnValue(args, result); |
+ } |
+ |
+ static Dart_Handle exceptionCodeToDartException(ExceptionCode); |
+ |
+private: |
+ enum NativeFieldIndices { |
+ kNativeImplementationIndex = 0, |
+ kDerefObjectFunctionIndex, |
+ kNativeFieldCount |
+ }; |
+ |
+ static Dart_Handle instantiateWrapper(const char* className); |
+ static bool instanceOf(const char* dartImplementationClassName, Dart_Handle wrapper, Dart_Handle& exception); |
+ |
+ static void writeNativePointer(Dart_Handle wrapper, int index, void* pointer) |
+ { |
+ DartApiScope scope; |
+ Dart_Handle result = Dart_SetNativeInstanceField(wrapper, index, reinterpret_cast<intptr_t>(pointer)); |
+ UNUSED_PARAM(result); |
+ ASSERT(!Dart_IsError(result)); |
+ } |
+ |
+ static void* readNativePointer(Dart_Handle wrapper, int index) |
+ { |
+ // FIXME: Try to remove this scope from the hot path. |
+ DartApiScope scope; |
+ intptr_t value; |
+ Dart_Handle result = Dart_GetNativeInstanceField(wrapper, index, &value); |
+ ASSERT(!Dart_IsError(result)); |
+ UNUSED_PARAM(result); |
+ return reinterpret_cast<void*>(value); |
+ } |
+ |
+ template <class WebkitClass> |
+ static void installNativePointers(WebkitClass* domObject, Dart_Handle wrapper) |
+ { |
+ ASSERT(domObject); |
+ DerefObjectFunction derefObjectFunction = &DartDOMWrapper::derefObject<WebkitClass>; |
+ writeNativePointer(wrapper, kNativeImplementationIndex, domObject); |
+ writeNativePointer(wrapper, kDerefObjectFunctionIndex, reinterpret_cast<void*>(derefObjectFunction)); |
+ } |
+ |
+ typedef void (*DerefObjectFunction)(void*); |
+ |
+ template<typename T> |
+ static void derefObject(void* pointer) |
+ { |
+ static_cast<T*>(pointer)->deref(); |
+ } |
+}; |
+ |
+template<> |
+inline void DartDOMWrapper::derefObject<NPObject>(void*) |
+{ |
+ // FIXME: proper deref. |
+} |
+ |
+// ParameterAdapter. |
+ |
+template <typename Value> |
+class ParameterAdapterBase { |
+public: |
+ bool conversionSuccessful() const { return !m_exception; } |
+ |
+ Dart_Handle exception() const |
+ { |
+ ASSERT(!conversionSuccessful()); |
+ return m_exception; |
+ } |
+ |
+protected: |
+ |
+ ParameterAdapterBase() |
+ : m_value() |
+ , m_exception(0) { } |
+ |
+ void setException(Dart_Handle exception) |
+ { |
+ ASSERT(exception); |
+ m_exception = exception; |
+ ASSERT(!conversionSuccessful()); |
+ } |
+ |
+ const Value& value() const |
+ { |
+ ASSERT(conversionSuccessful()); |
+ return m_value; |
+ } |
+ |
+ void setValue(Value value) |
+ { |
+ m_value = value; |
+ } |
+ |
+protected: |
+ Value m_value; |
+ |
+private: |
+ Dart_Handle m_exception; |
+}; |
+ |
+ |
+template <class NativeValue, class DartBindingsClass = void> |
+class ParameterAdapter : public ParameterAdapterBase<NativeValue*> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ this->setValue(DartBindingsClass::toNative(handle, exception).get()); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ |
+ operator PassRefPtr<NativeValue>() const { return this->value(); } |
+ operator NativeValue*() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter< RefPtr<EventListener> > : public ParameterAdapterBase< RefPtr<EventListener> > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ // FIXME: abstract away this common pattern of exception management in conversion. |
+ Dart_Handle exception = 0; |
+ this->setValue(DartUtilities::toEventListener(handle, exception)); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ operator EventListener*() const { return this->value().get(); } |
+ operator PassRefPtr<EventListener>() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter< RefPtr<EventTarget> > : public ParameterAdapterBase< RefPtr<EventTarget> > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ // FIXME: abstract away this common pattern of exception management in conversion. |
+ Dart_Handle exception = 0; |
+ this->setValue(DartUtilities::toEventTarget(handle, exception)); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ operator EventTarget*() const { return this->value().get(); } |
+ operator PassRefPtr<EventTarget>() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter< RefPtr<MediaQueryListListener> > : public ParameterAdapterBase<MediaQueryListListener*> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ setException(Dart_NewString("Not supported yet")); |
+ } |
+ operator MediaQueryListListener*() const { return this->value(); } |
+ operator PassRefPtr<MediaQueryListListener>() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter< RefPtr<SerializedScriptValue> > : public ParameterAdapterBase< RefPtr<SerializedScriptValue> > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ // FIXME: abstract away this common pattern of exception management in conversion. |
+ Dart_Handle exception = 0; |
+ this->setValue(DartUtilities::toSerializedScriptValue(handle, exception)); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ operator SerializedScriptValue*() const { return this->value().get(); } |
+ operator PassRefPtr<SerializedScriptValue>() const { return this->value(); } |
+ PassRefPtr<SerializedScriptValue> release() { return m_value->release(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter< RefPtr<VoidCallback> > : public ParameterAdapterBase<VoidCallback*> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ setException(Dart_NewString("Not supported yet")); |
+ } |
+ operator VoidCallback*() const { return this->value(); } |
+ operator PassRefPtr<VoidCallback>() const { return this->value(); } |
+}; |
+ |
+#if ENABLE(SVG) |
+template <class NativeValue, class DartBindingsClass> |
+class ParameterAdapter< RefPtr<SVGPropertyTearOff<NativeValue> >, DartBindingsClass> : public ParameterAdapterBase< RefPtr<SVGPropertyTearOff<NativeValue> > > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ this->setValue(DartBindingsClass::toNative(handle, exception).get()); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ operator const NativeValue&() const { return this->value()->propertyReference(); } |
+ operator NativeValue&() { return this->value()->propertyReference(); } |
+ operator PassRefPtr<SVGPropertyTearOff<NativeValue> >() const { return this->value(); } |
+ operator SVGPropertyTearOff<NativeValue>*() const { return this->value().get(); } |
+}; |
+#endif // ENABLE(SVG) |
+ |
+template <class NativeValue, class DartBindingsClass> |
+class ParameterAdapter< RefPtr<NativeValue>, DartBindingsClass > : public ParameterAdapterBase< RefPtr<NativeValue> > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ this->setValue(DartBindingsClass::toNative(handle, exception)); |
+ if (exception) |
+ this->setException(exception); |
+ } |
+ |
+ operator PassRefPtr<NativeValue>() const { return this->value(); } |
+ operator RefPtr<NativeValue>() const { return this->value(); } |
+ operator NativeValue*() const { return this->value().get(); } |
+}; |
+ |
+class DoubleParameterAdapter : public ParameterAdapterBase<double> { |
+protected: |
+ explicit DoubleParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ setValue(DartUtilities::toDouble(handle, exception)); |
+ if (exception) |
+ setException(exception); |
+ } |
+}; |
+ |
+template <> |
+class ParameterAdapter<double> : public DoubleParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : DoubleParameterAdapter(handle) { } |
+ operator double() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<float> : public DoubleParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : DoubleParameterAdapter(handle) { } |
+ operator float() const { return this->value(); } |
+}; |
+ |
+class IntParameterAdapter : public ParameterAdapterBase<int64_t> { |
+protected: |
+ explicit IntParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ setValue(DartUtilities::toInteger(handle, exception)); |
+ if (exception) |
+ setException(exception); |
+ } |
+}; |
+ |
+template <> |
+class ParameterAdapter<int> : public IntParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : IntParameterAdapter(handle) |
+ { |
+ if (conversionSuccessful() && (value() < INT_MIN || value() > INT_MAX)) |
+ setException(Dart_NewString("value out of range")); |
+ } |
+ operator int() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<long long> : public IntParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : IntParameterAdapter(handle) { } |
+ // FIXME: proper processing of longer integer values. |
+ operator long long() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<unsigned int> : public IntParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : IntParameterAdapter(handle) |
+ { |
+ if (conversionSuccessful() && (value() < 0 || value() > UINT_MAX)) |
+ setException(Dart_NewString("value out of range")); |
+ } |
+ operator unsigned int() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<unsigned long long> : public IntParameterAdapter { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ : IntParameterAdapter(handle) |
+ { |
+ if (conversionSuccessful() && value() < 0) |
+ setException(Dart_NewString("value out of range")); |
+ } |
+ // FIXME: proper processing of longer integer values. |
+ operator unsigned long long() const { return this->value(); } |
+}; |
+ |
+// FIXME: [performance] need better treatment of String vs. AtomicString, cf. v8 implementation. |
+template <> |
+class ParameterAdapter<String> : public ParameterAdapterBase< RefPtr<StringImpl> > { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle, DartUtilities::ConversionFlag flag = DartUtilities::ConvertNone) |
+ { |
+ Dart_Handle exception = 0; |
+ setValue(DartUtilities::toStringImpl(handle, flag, exception)); |
+ if (exception) |
+ setException(exception); |
+ } |
+ operator String() const { return String(this->value()); } |
+ operator AtomicString() const { return AtomicString(this->value()); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<bool> : public ParameterAdapterBase<bool> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ Dart_Handle exception = 0; |
+ setValue(DartUtilities::toBool(handle, exception)); |
+ if (exception) |
+ setException(exception); |
+ } |
+ operator bool() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<ScriptValue> : public ParameterAdapterBase<ScriptValue> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ setException(Dart_NewString("Not supported yet")); |
+ } |
+ operator ScriptValue() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<OptionsObject> : public ParameterAdapterBase<OptionsObject> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ setException(Dart_NewString("Not supported yet")); |
+ } |
+ operator OptionsObject() const { return this->value(); } |
+}; |
+ |
+template <> |
+class ParameterAdapter<Range::CompareHow> : public ParameterAdapterBase<Range::CompareHow> { |
+public: |
+ explicit ParameterAdapter(Dart_Handle handle) |
+ { |
+ setException(Dart_NewString("Not supported yet")); |
+ } |
+ operator Range::CompareHow() const { return this->value(); } |
+}; |
+ |
+} |
+ |
+#endif // DartDOMWrapper_h |