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 | |
12 | namespace tonic { |
13 | |
14 | DartWrappable::~DartWrappable() { |
15 | TONIC_CHECK(!dart_wrapper_); |
16 | } |
17 | |
18 | // TODO(dnfield): Delete this. https://github.com/flutter/flutter/issues/50997 |
19 | Dart_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 | |
45 | void 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 | |
61 | void 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 | |
72 | void 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 | |
80 | size_t DartWrappable::GetAllocationSize() const { |
81 | return GetDartWrapperInfo().size_in_bytes; |
82 | } |
83 | |
84 | Dart_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 | |
90 | DartWrappable* 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 | |
99 | DartWrappable* 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 | |