From 72c87f272262da0276ee016f914e708cf1fdee5e Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 5 Jan 2016 23:36:09 -0800 Subject: [PATCH] Add direct wrappers to tonic Instead of using a C++ object as a peer to the Dart wrapper, these wrapper hold arbitrary data in the internal field of the Dart wrapper. --- sky/engine/tonic/BUILD.gn | 2 + sky/engine/tonic/dart_converter.h | 49 ++++++++++++- sky/engine/tonic/dart_direct_wrappable.cc | 53 ++++++++++++++ sky/engine/tonic/dart_direct_wrappable.h | 84 +++++++++++++++++++++++ 4 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 sky/engine/tonic/dart_direct_wrappable.cc create mode 100644 sky/engine/tonic/dart_direct_wrappable.h diff --git a/sky/engine/tonic/BUILD.gn b/sky/engine/tonic/BUILD.gn index e6db431205f..ed2b5cc445e 100644 --- a/sky/engine/tonic/BUILD.gn +++ b/sky/engine/tonic/BUILD.gn @@ -15,6 +15,8 @@ source_set("tonic") { "dart_converter.h", "dart_dependency_catcher.cc", "dart_dependency_catcher.h", + "dart_direct_wrappable.cc", + "dart_direct_wrappable.h", "dart_error.cc", "dart_error.h", "dart_exception_factory.cc", diff --git a/sky/engine/tonic/dart_converter.h b/sky/engine/tonic/dart_converter.h index 4361b1eac36..d3494a1bfc3 100644 --- a/sky/engine/tonic/dart_converter.h +++ b/sky/engine/tonic/dart_converter.h @@ -267,6 +267,29 @@ struct DartConverter { } }; +template <> +struct DartConverter { + static Dart_Handle ToDart(const char* val) { + return Dart_NewStringFromCString(val); + } + + static void SetReturnValue(Dart_NativeArguments args, const char* val) { + Dart_SetReturnValue(args, ToDart(val)); + } + + static const char* FromDart(Dart_Handle handle) { + const char* result = nullptr; + Dart_StringToCString(handle, &result); + return result; + } + + static const char* FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + return FromDart(Dart_GetNativeArgument(args, index)); + } +}; + //////////////////////////////////////////////////////////////////////////////// // Collections @@ -342,11 +365,35 @@ struct DartConverter { static PassRefPtr FromArguments(Dart_NativeArguments args, int index, Dart_Handle& exception) { - // TODO(abarth): What should we do with auto_scope? return FromDart(Dart_GetNativeArgument(args, index)); } }; + +//////////////////////////////////////////////////////////////////////////////// +// Dart_Handle + +template <> +struct DartConverter { + static Dart_Handle ToDart(DartState* state, Dart_Handle val) { + return val; + } + + static void SetReturnValue(Dart_NativeArguments args, Dart_Handle val) { + Dart_SetReturnValue(args, val); + } + + static Dart_Handle FromDart(Dart_Handle handle) { + return handle; + } + + static Dart_Handle FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + return Dart_GetNativeArgument(args, index); + } +}; + //////////////////////////////////////////////////////////////////////////////// // Convience wrappers for commonly used conversions diff --git a/sky/engine/tonic/dart_direct_wrappable.cc b/sky/engine/tonic/dart_direct_wrappable.cc new file mode 100644 index 00000000000..2e70c4154a5 --- /dev/null +++ b/sky/engine/tonic/dart_direct_wrappable.cc @@ -0,0 +1,53 @@ +// 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. + +#include "sky/engine/tonic/dart_direct_wrappable.h" + +#include "sky/engine/tonic/dart_class_library.h" +#include "sky/engine/tonic/dart_error.h" +#include "sky/engine/tonic/dart_state.h" +#include "sky/engine/tonic/dart_wrappable.h" +#include "sky/engine/tonic/dart_wrapper_info.h" + +namespace blink { + +Dart_Handle DartDirectWrappable::Wrap( + DartState* dart_state, + void* val, + const DartWrapperInfo& info) { + Dart_PersistentHandle type = dart_state->class_library().GetClass(info); + DCHECK(!LogIfError(type)); + + intptr_t native_fields[DartWrappable::kNumberOfNativeFields]; + native_fields[DartWrappable::kPeerIndex] = reinterpret_cast(val); + native_fields[DartWrappable::kWrapperInfoIndex] = reinterpret_cast(&info); + Dart_Handle wrapper = + Dart_AllocateWithNativeFields(type, DartWrappable::kNumberOfNativeFields, native_fields); + DCHECK(!LogIfError(wrapper)); + return wrapper; +} + +void* DartDirectWrappable::FromDart(Dart_Handle handle) { + intptr_t peer = 0; + Dart_Handle result = + Dart_GetNativeInstanceField(handle, DartWrappable::kPeerIndex, &peer); + if (Dart_IsError(result)) + return nullptr; + return reinterpret_cast(peer); +} + +void* DartDirectWrappable::FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + intptr_t native_fields[DartWrappable::kNumberOfNativeFields]; + Dart_Handle result = Dart_GetNativeFieldsOfArgument( + args, index, DartWrappable::kNumberOfNativeFields, native_fields); + if (Dart_IsError(result)) { + exception = Dart_NewStringFromCString(DartError::kInvalidArgument); + return nullptr; + } + return reinterpret_cast(native_fields[DartWrappable::kPeerIndex]); +} + +} // namespace blink diff --git a/sky/engine/tonic/dart_direct_wrappable.h b/sky/engine/tonic/dart_direct_wrappable.h new file mode 100644 index 00000000000..5c2c9c79941 --- /dev/null +++ b/sky/engine/tonic/dart_direct_wrappable.h @@ -0,0 +1,84 @@ +// Copyright 2016 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_DIRECT_WRAPPABLE_H_ +#define SKY_ENGINE_TONIC_DART_DIRECT_WRAPPABLE_H_ + +#include "dart/runtime/include/dart_api.h" +#include "sky/engine/tonic/dart_converter.h" + +namespace blink { +class DartState; +struct DartWrapperInfo; + +template +struct DartDirectWrappable; + +template<> +struct DartDirectWrappable { + static Dart_Handle Wrap(DartState* dart_state, void* val, + const DartWrapperInfo& info); + static void* FromDart(Dart_Handle handle); + static void* FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception); +}; + +template +struct DartDirectWrappable { + static Dart_Handle Wrap(DartState* dart_state, T val, + const DartWrapperInfo& info) { + return DartDirectWrappable::Wrap(dart_state, static_cast(val), + info); + } + + static T FromDart(Dart_Handle handle) { + return static_cast(DartDirectWrappable::FromDart(handle)); + } + + static T FromArguments(Dart_NativeArguments args, int index, + Dart_Handle& exception) { + return static_cast(DartDirectWrappable::FromArguments( + args, index, exception)); + } +}; + +template +struct DartConverterDirectWrappable { + static Dart_Handle ToDart(T val) { + if (!val) + return Dart_Null(); + return DartDirectWrappable::Wrap( + DartState::Current(), val, GetWrapperInfo()); + } + + static void SetReturnValue(Dart_NativeArguments args, T val) { + Dart_SetReturnValue(args, ToDart(val)); + } + + static T FromDart(Dart_Handle handle) { + return DartDirectWrappable::FromDart(handle); + } + + static T FromArguments(Dart_NativeArguments args, + int index, + Dart_Handle& exception) { + return DartDirectWrappable::FromArguments(args, index, exception); + } +}; + +#define IMPLEMENT_DIRECT_WRAPPABLE(DartName, ImplType) \ +static const DartWrapperInfo kDartWrapperInfo_##DartName = { \ + #DartName, 0, 0, 0, \ +}; \ +static const DartWrapperInfo& GetWrapperTypeInfo##DartName() { \ + return kDartWrapperInfo_##DartName; \ +} \ +template <> \ +struct DartConverter : public DartConverterDirectWrappable< \ + ImplType, GetWrapperTypeInfo##DartName> {}; + +} // namespace blink + +#endif // SKY_ENGINE_TONIC_DART_DIRECT_WRAPPABLE_H_