Index: tonic/dart_wrappable.h |
diff --git a/tonic/dart_wrappable.h b/tonic/dart_wrappable.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..13feb999cf4771cb0d5e6971e8254bd1e09d290e |
--- /dev/null |
+++ b/tonic/dart_wrappable.h |
@@ -0,0 +1,146 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ |
+#define SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ |
+ |
+#include "base/logging.h" |
+#include "base/template_util.h" |
+#include "dart/runtime/include/dart_api.h" |
+#include "tonic/dart_converter.h" |
+#include "tonic/dart_error.h" |
+#include "tonic/dart_state.h" |
+#include "tonic/dart_wrapper_info.h" |
+ |
+namespace blink { |
+class DartGCVisitor; |
+struct DartWrapperInfo; |
+ |
+// DartWrappable is a base class that you can inherit from in order to be |
+// exposed to Dart code as an interface. |
+class DartWrappable { |
+ public: |
+ enum DartNativeFields { |
+ kPeerIndex, // Must be first to work with Dart_GetNativeReceiver. |
+ kWrapperInfoIndex, |
+ kNumberOfNativeFields, |
+ }; |
+ |
+ DartWrappable() : dart_wrapper_(nullptr) {} |
+ |
+ // Subclasses that wish to expose a new interface must override this function |
+ // and provide information about their wrapper. There is no need to call your |
+ // base class's implementation of this function. |
+ virtual const DartWrapperInfo& GetDartWrapperInfo() const = 0; |
+ |
+ // Subclasses that wish to integrate with the Dart garbage collector should |
+ // override this function. Please call your base class's AcceptDartGCVisitor |
+ // at the end of your override. |
+ virtual void AcceptDartGCVisitor(DartGCVisitor& visitor) const; |
+ |
+ Dart_Handle CreateDartWrapper(DartState* dart_state); |
+ void AssociateWithDartWrapper(Dart_NativeArguments args); |
+ Dart_WeakPersistentHandle dart_wrapper() const { return dart_wrapper_; } |
+ |
+ protected: |
+ virtual ~DartWrappable(); |
+ |
+ private: |
+ static void FinalizeDartWrapper(void* isolate_callback_data, |
+ Dart_WeakPersistentHandle wrapper, |
+ void* peer); |
+ |
+ Dart_WeakPersistentHandle dart_wrapper_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DartWrappable); |
+}; |
+ |
+#define DEFINE_WRAPPERTYPEINFO() \ |
+ public: \ |
+ const DartWrapperInfo& GetDartWrapperInfo() const override { \ |
+ return dart_wrapper_info_; \ |
+ } \ |
+ private: \ |
+ static const DartWrapperInfo& dart_wrapper_info_ |
+ |
+struct DartConverterWrappable { |
+ static DartWrappable* FromDart(Dart_Handle handle); |
+ static DartWrappable* FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception); |
+ static DartWrappable* FromArgumentsWithNullCheck(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception); |
+}; |
+ |
+template<typename T> |
+struct DartConverter< |
+ T*, |
+ typename base::enable_if< |
+ base::is_convertible<T*, DartWrappable*>::value>::type> { |
+ static Dart_Handle ToDart(DartWrappable* val) { |
+ if (!val) |
+ return Dart_Null(); |
+ if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) |
+ return Dart_HandleFromWeakPersistent(wrapper); |
+ return val->CreateDartWrapper(DartState::Current()); |
+ } |
+ |
+ static void SetReturnValue(Dart_NativeArguments args, |
+ DartWrappable* val, |
+ bool auto_scope = true) { |
+ if (!val) |
+ Dart_SetReturnValue(args, Dart_Null()); |
+ else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) |
+ Dart_SetWeakHandleReturnValue(args, wrapper); |
+ else |
+ Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current())); |
+ } |
+ |
+ static T* FromDart(Dart_Handle handle) { |
+ // TODO(abarth): We're missing a type check. |
+ return static_cast<T*>(DartConverterWrappable::FromDart(handle)); |
+ } |
+ |
+ static T* FromArguments(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): We're missing a type check. |
+ return static_cast<T*>(DartConverterWrappable::FromArguments( |
+ args, index, exception)); |
+ } |
+ |
+ static T* FromArgumentsWithNullCheck(Dart_NativeArguments args, |
+ int index, |
+ Dart_Handle& exception, |
+ bool auto_scope = true) { |
+ // TODO(abarth): We're missing a type check. |
+ return static_cast<T*>(DartConverterWrappable::FromArgumentsWithNullCheck( |
+ args, index, exception)); |
+ } |
+}; |
+ |
+template<typename T> |
+struct DartConverter<RefPtr<T>> { |
+ static Dart_Handle ToDart(RefPtr<T> val) { |
+ return DartConverter<T*>::ToDart(val.get()); |
+ } |
+ |
+ static RefPtr<T> FromDart(Dart_Handle handle) { |
+ return DartConverter<T*>::FromDart(handle); |
+ } |
+}; |
+ |
+template<typename T> |
+inline T* GetReceiver(Dart_NativeArguments args) { |
+ intptr_t receiver; |
+ Dart_Handle result = Dart_GetNativeReceiver(args, &receiver); |
+ DCHECK(!Dart_IsError(result)); |
+ return static_cast<T*>(reinterpret_cast<DartWrappable*>(receiver)); |
+} |
+ |
+} // namespace blink |
+ |
+#endif // SKY_ENGINE_TONIC_DART_WRAPPABLE_H_ |