| Index: Source/bindings/core/dart/DartDOMWrapper.h
|
| diff --git a/Source/bindings/core/dart/DartDOMWrapper.h b/Source/bindings/core/dart/DartDOMWrapper.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a29b6049d65e52a568efe8af1a64b2c76dbd71d3
|
| --- /dev/null
|
| +++ b/Source/bindings/core/dart/DartDOMWrapper.h
|
| @@ -0,0 +1,411 @@
|
| +// 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 "bindings/core/v8/Dictionary.h"
|
| +#include "bindings/core/dart/DartDOMData.h"
|
| +#include "bindings/core/dart/DartUtilities.h"
|
| +#include "bindings/core/v8/SerializedScriptValue.h"
|
| +#include "bindings/dart/DartWebkitClassIds.h"
|
| +#include "core/dom/ExceptionCode.h"
|
| +
|
| +#include "wtf/PassRefPtr.h"
|
| +#include "wtf/RefPtr.h"
|
| +#include "wtf/text/AtomicString.h"
|
| +#include "wtf/text/WTFString.h"
|
| +#include <dart_api.h>
|
| +
|
| +namespace blink {
|
| +
|
| +template<typename HTMLElement>
|
| +class DartCustomElementWrapper;
|
| +class HTMLElement;
|
| +
|
| +template<class BindingsClass>
|
| +struct DartDOMWrapperTraits;
|
| +
|
| +class DartDOMWrapper {
|
| +public:
|
| + enum NativeFieldIndices {
|
| + NativeImplementationIndex = 0,
|
| + NativeTypeIndex = 1,
|
| + NativeFieldCount
|
| + };
|
| +
|
| + template <class BindingsClass>
|
| + static Dart_WeakPersistentHandle lookupWrapper(DartDOMData* domData, typename BindingsClass::NativeType* domObject)
|
| + {
|
| + typedef DartDOMWrapperTraits<BindingsClass> Traits;
|
| + ASSERT(domObject);
|
| + ASSERT(domData);
|
| + return Traits::MapTraits::domMap(domData)->get(domObject);
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static Dart_Handle createWrapper(DartDOMData* domData, typename BindingsClass::NativeType* domObject)
|
| + {
|
| + return createWrapper<BindingsClass>(
|
| + domData,
|
| + domObject,
|
| + BindingsClass::dartClassId);
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static Dart_Handle createWrapper(
|
| + DartDOMData* domData, typename BindingsClass::NativeType* domObject,
|
| + intptr_t cid)
|
| + {
|
| + ASSERT(domData);
|
| + ASSERT(domObject);
|
| + Dart_PersistentHandle type = dartClass(domData, cid);
|
| + ASSERT(!Dart_IsError(type));
|
| + intptr_t nativeFields[NativeFieldCount];
|
| + nativeFields[NativeImplementationIndex] = reinterpret_cast<intptr_t>(domObject);
|
| + nativeFields[NativeTypeIndex] = cid;
|
| + Dart_Handle wrapper = Dart_AllocateWithNativeFields(type, NativeFieldCount, nativeFields);
|
| + if (Dart_IsError(wrapper)) {
|
| + return wrapper;
|
| + }
|
| + associateWrapper<BindingsClass>(domData, domObject, wrapper);
|
| + return wrapper;
|
| + }
|
| +
|
| + template<class BindingsClass>
|
| + static Dart_Handle vectorToDart(const Vector< RefPtr<typename BindingsClass::NativeType> >& vector)
|
| + {
|
| + return DartUtilities::vectorToDart<RefPtr<typename BindingsClass::NativeType>, PassRefPtr<typename BindingsClass::NativeType>, BindingsClass::toDart>(vector);
|
| + }
|
| +
|
| + template<class BindingsClass>
|
| + static Dart_Handle vectorToDart(const HeapVector< Member<typename BindingsClass::NativeType> >& vector)
|
| + {
|
| + return DartUtilities::vectorToDart<typename BindingsClass::NativeType, BindingsClass::toDart>(vector);
|
| + }
|
| +
|
| + static Dart_Handle vectorToDart(const Vector<float>& vector)
|
| + {
|
| + // If this is hot, consider using a Float32List instead.
|
| + return DartUtilities::vectorToDart<float, double, DartUtilities::doubleToDart>(vector);
|
| + }
|
| +
|
| + static Dart_Handle vectorToDart(const Vector<double>& vector)
|
| + {
|
| + // If this is hot, consider using a Float32List instead.
|
| + return DartUtilities::vectorToDart<double, double, DartUtilities::doubleToDart>(vector);
|
| + }
|
| +
|
| + static Dart_Handle vectorToDart(const Vector<unsigned>& vector)
|
| + {
|
| + // If this is hot, consider using a typed array instead.
|
| + return DartUtilities::vectorToDart<unsigned, unsigned, DartUtilities::unsignedToDart>(vector);
|
| + }
|
| +
|
| + static Dart_Handle vectorToDart(const Vector<String>& vector)
|
| + {
|
| + return DartUtilities::vectorToDart<String, const String&, DartUtilities::stringToDart>(vector);
|
| + }
|
| +
|
| + template<class T>
|
| + static Dart_Handle vectorToDartNullable(Nullable<T> vector)
|
| + {
|
| + if (vector.isNull())
|
| + return Dart_Null();
|
| + return vectorToDart(vector.get());
|
| + }
|
| +
|
| + template<class BindingsClass>
|
| + static Dart_Handle vectorToDartNullable(Nullable< Vector< RefPtr<typename BindingsClass::NativeType> > > vector)
|
| + {
|
| + if (vector.isNull())
|
| + return Dart_Null();
|
| + return vectorToDart<BindingsClass>(vector.get());
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static typename BindingsClass::NativeType* unwrapDartWrapper(
|
| + DartDOMData* domData, Dart_Handle wrapper, Dart_Handle& exception)
|
| + {
|
| + ASSERT(!exception);
|
| +
|
| + if (Dart_IsNull(wrapper))
|
| + return 0;
|
| +
|
| + if (subtypeOf(wrapper, BindingsClass::dartClassId)) {
|
| + void* nativePointer = readNativePointer(wrapper, NativeImplementationIndex);
|
| + return static_cast<typename BindingsClass::NativeType*>(nativePointer);
|
| + }
|
| + const char* className = DartWebkitClassInfo[BindingsClass::dartClassId].jsName;
|
| + String message = String("Invalid class: expected instance of ") +
|
| + className;
|
| + exception = DartUtilities::stringToDartString(message);
|
| + return 0;
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static typename BindingsClass::NativeType* unwrapDartWrapper(
|
| + Dart_NativeArguments args, int index, Dart_Handle& exception)
|
| + {
|
| + ASSERT(!exception);
|
| + intptr_t fieldValues[NativeFieldCount];
|
| + Dart_Handle result = Dart_GetNativeFieldsOfArgument(args, index, NativeFieldCount, fieldValues);
|
| + if (!Dart_IsError(result)) {
|
| + void* wrapper = reinterpret_cast<void*>(fieldValues[NativeImplementationIndex]);
|
| + if (!wrapper) {
|
| + return 0;
|
| + }
|
| + intptr_t cid = fieldValues[NativeTypeIndex];
|
| + if (subtypeOf(cid, BindingsClass::dartClassId)) {
|
| + // FIXME(vsm): This is not safe if BindingsClass::NativeType is
|
| + // not the primary parent.
|
| + return static_cast<typename BindingsClass::NativeType*>(wrapper);
|
| + }
|
| + }
|
| + const char* className = DartWebkitClassInfo[BindingsClass::dartClassId].jsName;
|
| + String message = String("Invalid class: expected instance of ") + className;
|
| + exception = DartUtilities::stringToDartString(message);
|
| + return 0;
|
| + }
|
| +
|
| + static bool subtypeOf(Dart_Handle wrapper, intptr_t basecid)
|
| + {
|
| + intptr_t cid = reinterpret_cast<intptr_t>(readNativePointer(wrapper, NativeTypeIndex));
|
| + return subtypeOf(cid, basecid);
|
| + }
|
| +
|
| + static bool subtypeOf(intptr_t cid, intptr_t basecid)
|
| + {
|
| + while (cid != -1) {
|
| + if (cid == basecid) {
|
| + return true;
|
| + }
|
| + ASSERT(cid < NumWebkitClassIds);
|
| + cid = DartWebkitClassInfo[cid].base_class_id;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static bool instanceOf(DartDOMData* domData, Dart_Handle wrapper)
|
| + {
|
| + Dart_PersistentHandle type = dartClass(domData, BindingsClass::dartClassId);
|
| +
|
| + bool isInstanceOf = false;
|
| + Dart_Handle ALLOW_UNUSED result = Dart_ObjectIsType(wrapper, type, &isInstanceOf);
|
| + ASSERT(!Dart_IsError(result));
|
| + return isInstanceOf;
|
| + }
|
| +
|
| + template <class WebKitClass>
|
| + static WebKitClass* receiver(Dart_NativeArguments args)
|
| + {
|
| + // Type of receiver is ensured by Dart VM runtime, so bypass additional checks.
|
| + intptr_t value = 0;
|
| + ASSERT(!NativeImplementationIndex);
|
| + Dart_Handle ALLOW_UNUSED result = Dart_GetNativeReceiver(args, &value);
|
| + ASSERT(!Dart_IsError(result));
|
| + WebKitClass* const recv = reinterpret_cast<WebKitClass*>(value);
|
| + if (recv == 0) {
|
| + Dart_ThrowException(DartUtilities::stringToDartString(String("Not a valid object")));
|
| + }
|
| + return recv;
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static void returnToDart(Dart_NativeArguments args, typename BindingsClass::NativeType* domObject)
|
| + {
|
| + if (domObject) {
|
| + DartDOMData* domData = static_cast<DartDOMData*>(Dart_GetNativeIsolateData(args));
|
| + Dart_WeakPersistentHandle result = lookupWrapper<BindingsClass>(domData, domObject);
|
| + if (result)
|
| + Dart_SetWeakHandleReturnValue(args, result);
|
| + else
|
| + Dart_SetReturnValue(args, createWrapper<BindingsClass>(domData, domObject, BindingsClass::dartClassId));
|
| + }
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static void returnToDart(Dart_NativeArguments args, PassRefPtr<typename BindingsClass::NativeType> domObject)
|
| + {
|
| + returnToDart<BindingsClass>(args, domObject.get());
|
| + }
|
| +
|
| + static int wrapperNativeFieldCount() { return NativeFieldCount; }
|
| +
|
| +private:
|
| + static Dart_PersistentHandle dartClass(DartDOMData*, intptr_t classIndex);
|
| +
|
| + static void writeNativePointer(Dart_Handle wrapper, void* pointer, intptr_t cid)
|
| + {
|
| + Dart_Handle ALLOW_UNUSED result = Dart_SetNativeInstanceField(
|
| + wrapper, NativeImplementationIndex, reinterpret_cast<intptr_t>(pointer));
|
| + ASSERT(!Dart_IsError(result));
|
| + result = Dart_SetNativeInstanceField(wrapper, NativeTypeIndex, cid);
|
| + ASSERT(!Dart_IsError(result));
|
| + }
|
| +
|
| + static void* readNativePointer(Dart_Handle wrapper, int index)
|
| + {
|
| + intptr_t value;
|
| + Dart_Handle result = Dart_GetNativeInstanceField(wrapper, index, &value);
|
| + // FIXME: the fact that we return 0 on error rather than asserting is
|
| + // somewhat of a hack. We currently make this method return 0 because
|
| + // we reuse this method to verify that objects are actually native
|
| + // Node objects rather than objects that implement the Node interface.
|
| + if (Dart_IsError(result))
|
| + return 0;
|
| + return reinterpret_cast<void*>(value);
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static void wrapperWeakCallback(void* isolateCallbackData, Dart_WeakPersistentHandle wrapper, void* blinkHandle)
|
| + {
|
| + typedef DartDOMWrapperTraits<BindingsClass> Traits;
|
| + DartDOMData* domData = reinterpret_cast<DartDOMData*>(isolateCallbackData);
|
| + typename BindingsClass::NativeType* domObject = Traits::GCTraits::read(blinkHandle);
|
| +
|
| + Dart_WeakPersistentHandle currentWrapper = 0;
|
| + currentWrapper = Traits::MapTraits::domMap(domData)->get(domObject);
|
| +
|
| + // This could be an old wrapper which has been replaced with a custom element.
|
| + if (currentWrapper != wrapper) {
|
| +#ifdef DEBUG
|
| + DartApiScope scope;
|
| + ASSERT(!Dart_IdentityEquals(Dart_HandleFromWeakPersistent(currentWrapper), Dart_HandleFromWeakPersistent(wrapper)));
|
| +#endif
|
| + return;
|
| + }
|
| +
|
| + if (currentWrapper) {
|
| + Traits::MapTraits::domMap(domData)->remove(domObject);
|
| + }
|
| + Traits::GCTraits::deref(blinkHandle);
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static void associateWrapper(
|
| + DartDOMData* domData, typename BindingsClass::NativeType* domObject, Dart_Handle newInstance)
|
| + {
|
| + typedef DartDOMWrapperTraits<BindingsClass> Traits;
|
| + void* blinkHandle = Traits::GCTraits::ref(domObject);
|
| + // This is only used to inform the Dart garbage collector on how much external memory
|
| + // is kept alive.
|
| + intptr_t externalAllocationSize = sizeof(*domObject);
|
| +
|
| + Dart_WeakPersistentHandle wrapper = Dart_NewPrologueWeakPersistentHandle(
|
| + newInstance, blinkHandle, externalAllocationSize, &wrapperWeakCallback<BindingsClass>);
|
| + Traits::MapTraits::domMap(domData)->set(domObject, wrapper);
|
| + }
|
| +
|
| + template <class BindingsClass>
|
| + static void disassociateWrapper(
|
| + DartDOMData* domData, typename BindingsClass::NativeType* domObject, Dart_Handle oldInstance)
|
| + {
|
| + typedef DartDOMWrapperTraits<BindingsClass> Traits;
|
| +
|
| +#ifdef DEBUG
|
| + Dart_WeakPersistentHandle wrapper = Traits::MapTraits::domMap(domData)->get(domObject);
|
| + ASSERT(Dart_IdentityEquals(Dart_HandleFromWeakPersistent(wrapper), oldInstance));
|
| +#endif
|
| + Traits::MapTraits::domMap(domData)->remove(domObject);
|
| + }
|
| +
|
| + friend class DartCustomElementConstructorBuilder;
|
| + friend class DartCustomElementWrapper<HTMLElement>;
|
| + friend class DartUtilities;
|
| +};
|
| +
|
| +struct DartDOMWrapperMapTraits {
|
| + static DartDOMObjectMap* domMap(DartDOMData* domData) { return domData->objectMap(); }
|
| +};
|
| +
|
| +template<class BindingsClass, bool isGarbageCollected>
|
| +struct DartDOMWrapperGarbageCollectedTraits { };
|
| +
|
| +template<class BindingsClass>
|
| +struct DartDOMWrapperGarbageCollectedTraits<BindingsClass, false> {
|
| + static void* ref(typename BindingsClass::NativeType* domObject)
|
| + {
|
| + domObject->ref();
|
| + return domObject;
|
| + }
|
| +
|
| + static void deref(void* blinkHandle)
|
| + {
|
| + typename BindingsClass::NativeType* domObject = read(blinkHandle);
|
| + domObject->deref();
|
| + }
|
| +
|
| + static typename BindingsClass::NativeType* read(void* blinkHandle)
|
| + {
|
| + return static_cast<typename BindingsClass::NativeType*>(blinkHandle);
|
| + }
|
| +};
|
| +
|
| +template<class BindingsClass>
|
| +struct DartDOMWrapperGarbageCollectedTraits<BindingsClass, true> {
|
| + static void* ref(typename BindingsClass::NativeType* domObject)
|
| + {
|
| + return new Persistent<typename BindingsClass::NativeType>(domObject);
|
| + }
|
| +
|
| + static void deref(void* blinkHandle)
|
| + {
|
| + Persistent<typename BindingsClass::NativeType>* handle = static_cast<Persistent<typename BindingsClass::NativeType>*>(blinkHandle);
|
| + delete handle;
|
| + }
|
| +
|
| + static typename BindingsClass::NativeType* read(void* blinkHandle)
|
| + {
|
| + Persistent<typename BindingsClass::NativeType>* handle = static_cast<Persistent<typename BindingsClass::NativeType>*>(blinkHandle);
|
| + return handle->get();
|
| + }
|
| +};
|
| +
|
| +template<class BindingsClass>
|
| +struct DartDOMWrapperTraits {
|
| + typedef DartDOMWrapperMapTraits MapTraits;
|
| + typedef DartDOMWrapperGarbageCollectedTraits<BindingsClass, BindingsClass::isGarbageCollected> GCTraits;
|
| +};
|
| +
|
| +struct DartMessagePort;
|
| +
|
| +template<>
|
| +struct DartDOMWrapperTraits<DartMessagePort> {
|
| + struct MessagePortMapTraits {
|
| + static DartMessagePortMap* domMap(DartDOMData* domData) { return domData->messagePortMap(); }
|
| + };
|
| + typedef MessagePortMapTraits MapTraits;
|
| + typedef DartDOMWrapperGarbageCollectedTraits<DartMessagePort, false> GCTraits;
|
| +};
|
| +
|
| +}
|
| +
|
| +#endif // DartDOMWrapper_h
|
|
|