flutter_flutter/engine/tonic/dart_wrappable.h
Adam Barth f562073fe2 Make it possible to inherit from any constructable host object
This CL makes it possible for authors to extend any host object (e.g., DOM
objects) and to use those objects in all the usual places they can be used in
the API.

R=esprehn@chromium.org

Review URL: https://codereview.chromium.org/936193005
2015-02-19 23:09:51 -08:00

147 lines
5.3 KiB
C++

// 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 "sky/engine/tonic/dart_converter.h"
#include "sky/engine/tonic/dart_error.h"
#include "sky/engine/tonic/dart_state.h"
#include "sky/engine/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_