1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "tonic/dart_wrappable.h"
6
7#include "tonic/dart_class_library.h"
8#include "tonic/dart_state.h"
9#include "tonic/dart_wrapper_info.h"
10#include "tonic/logging/dart_error.h"
11
12namespace tonic {
13
14DartWrappable::~DartWrappable() {
15 TONIC_CHECK(!dart_wrapper_);
16}
17
18// TODO(dnfield): Delete this. https://github.com/flutter/flutter/issues/50997
19Dart_Handle DartWrappable::CreateDartWrapper(DartState* dart_state) {
20 TONIC_DCHECK(!dart_wrapper_);
21 const DartWrapperInfo& info = GetDartWrapperInfo();
22
23 Dart_PersistentHandle type = dart_state->class_library().GetClass(info);
24 TONIC_DCHECK(!LogIfError(type));
25
26 Dart_Handle wrapper =
27 Dart_New(type, dart_state->private_constructor_name(), 0, nullptr);
28
29 TONIC_DCHECK(!LogIfError(wrapper));
30
31 Dart_Handle res = Dart_SetNativeInstanceField(
32 wrapper, kPeerIndex, reinterpret_cast<intptr_t>(this));
33 TONIC_DCHECK(!LogIfError(res));
34 res = Dart_SetNativeInstanceField(wrapper, kWrapperInfoIndex,
35 reinterpret_cast<intptr_t>(&info));
36 TONIC_DCHECK(!LogIfError(res));
37
38 this->RetainDartWrappableReference(); // Balanced in FinalizeDartWrapper.
39 dart_wrapper_ = Dart_NewWeakPersistentHandle(
40 wrapper, this, GetAllocationSize(), &FinalizeDartWrapper);
41
42 return wrapper;
43}
44
45void DartWrappable::AssociateWithDartWrapper(Dart_Handle wrapper) {
46 TONIC_DCHECK(!dart_wrapper_);
47 TONIC_CHECK(!LogIfError(wrapper));
48
49 const DartWrapperInfo& info = GetDartWrapperInfo();
50
51 TONIC_CHECK(!LogIfError(Dart_SetNativeInstanceField(
52 wrapper, kPeerIndex, reinterpret_cast<intptr_t>(this))));
53 TONIC_CHECK(!LogIfError(Dart_SetNativeInstanceField(
54 wrapper, kWrapperInfoIndex, reinterpret_cast<intptr_t>(&info))));
55
56 this->RetainDartWrappableReference(); // Balanced in FinalizeDartWrapper.
57 dart_wrapper_ = Dart_NewWeakPersistentHandle(
58 wrapper, this, GetAllocationSize(), &FinalizeDartWrapper);
59}
60
61void DartWrappable::ClearDartWrapper() {
62 TONIC_DCHECK(dart_wrapper_);
63 Dart_Handle wrapper = Dart_HandleFromWeakPersistent(dart_wrapper_);
64 TONIC_CHECK(!LogIfError(Dart_SetNativeInstanceField(wrapper, kPeerIndex, 0)));
65 TONIC_CHECK(
66 !LogIfError(Dart_SetNativeInstanceField(wrapper, kWrapperInfoIndex, 0)));
67 Dart_DeleteWeakPersistentHandle(dart_wrapper_);
68 dart_wrapper_ = nullptr;
69 this->ReleaseDartWrappableReference();
70}
71
72void DartWrappable::FinalizeDartWrapper(void* isolate_callback_data,
73 Dart_WeakPersistentHandle wrapper,
74 void* peer) {
75 DartWrappable* wrappable = reinterpret_cast<DartWrappable*>(peer);
76 wrappable->dart_wrapper_ = nullptr;
77 wrappable->ReleaseDartWrappableReference(); // Balanced in CreateDartWrapper.
78}
79
80size_t DartWrappable::GetAllocationSize() const {
81 return GetDartWrapperInfo().size_in_bytes;
82}
83
84Dart_PersistentHandle DartWrappable::GetTypeForWrapper(
85 tonic::DartState* dart_state,
86 const tonic::DartWrapperInfo& wrapper_info) {
87 return dart_state->class_library().GetClass(wrapper_info);
88}
89
90DartWrappable* DartConverterWrappable::FromDart(Dart_Handle handle) {
91 intptr_t peer = 0;
92 Dart_Handle result =
93 Dart_GetNativeInstanceField(handle, DartWrappable::kPeerIndex, &peer);
94 if (Dart_IsError(result))
95 return nullptr;
96 return reinterpret_cast<DartWrappable*>(peer);
97}
98
99DartWrappable* DartConverterWrappable::FromArguments(Dart_NativeArguments args,
100 int index,
101 Dart_Handle& exception) {
102 intptr_t native_fields[DartWrappable::kNumberOfNativeFields];
103 Dart_Handle result = Dart_GetNativeFieldsOfArgument(
104 args, index, DartWrappable::kNumberOfNativeFields, native_fields);
105 if (Dart_IsError(result)) {
106 exception = Dart_NewStringFromCString(DartError::kInvalidArgument);
107 return nullptr;
108 }
109 if (!native_fields[DartWrappable::kPeerIndex])
110 return nullptr;
111 return reinterpret_cast<DartWrappable*>(
112 native_fields[DartWrappable::kPeerIndex]);
113}
114
115} // namespace tonic
116