Skip to content

Commit d6b97cd

Browse files
committed
feat: using std::atomic value types for disposed checks of NativeBindingObject.
1 parent 7bd227b commit d6b97cd

File tree

7 files changed

+73
-16
lines changed

7 files changed

+73
-16
lines changed

bridge/core/binding_object.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void NativeBindingObject::HandleCallFromDartSide(const DartIsolateContext* dart_
7777
BindingObject::BindingObject(JSContext* ctx) : ScriptWrappable(ctx), binding_object_(new NativeBindingObject(this)) {}
7878
BindingObject::~BindingObject() {
7979
// Set below properties to nullptr to avoid dart callback to native.
80-
binding_object_->disposed_ = true;
80+
binding_object_->disposed_.store(true, std::memory_order_release);
8181
binding_object_->binding_target_ = nullptr;
8282
binding_object_->invoke_binding_methods_from_dart = nullptr;
8383
binding_object_->invoke_bindings_methods_from_native = nullptr;

bridge/core/binding_object.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ struct NativeBindingObject : public DartReadable {
5454
const NativeValue* argv,
5555
Dart_PersistentHandle dart_object,
5656
DartInvokeResultCallback result_callback);
57-
58-
bool disposed_{false};
57+
static bool IsDisposed(const NativeBindingObject* native_binding_object) {
58+
return native_binding_object->disposed_.load(std::memory_order_acquire);
59+
}
5960
BindingObject* binding_target_{nullptr};
6061
InvokeBindingMethodsFromDart invoke_binding_methods_from_dart{nullptr};
6162
InvokeBindingsMethodsFromNative invoke_bindings_methods_from_native{nullptr};
6263
void* extra{nullptr};
64+
std::atomic<bool> disposed_{false};
6365
};
6466

6567
enum BindingMethodCallOperations {

bridge/include/webf_bridge.h

+6
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ void collectNativeProfileData(void* ptr, const char** data, uint32_t* len);
123123
WEBF_EXPORT_C
124124
void clearNativeProfileData(void* ptr);
125125

126+
WEBF_EXPORT_C
127+
void* allocateNativeBindingObject();
128+
129+
WEBF_EXPORT_C
130+
bool isNativeBindingObjectDisposed(void* native_binding_object);
131+
126132
WEBF_EXPORT_C
127133
WebFInfo* getWebFInfo();
128134
WEBF_EXPORT_C

bridge/webf_bridge.cc

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
*/
44

55
#include "include/webf_bridge.h"
6+
#include <core/binding_object.h>
7+
68
#include "core/dart_isolate_context.h"
79
#include "core/html/parser/html_parser.h"
810
#include "core/page.h"
@@ -260,6 +262,14 @@ void clearNativeProfileData(void* ptr) {
260262
dart_isolate_context->profiler()->clear();
261263
}
262264

265+
void* allocateNativeBindingObject() {
266+
return new webf::NativeBindingObject(nullptr);
267+
}
268+
269+
bool isNativeBindingObjectDisposed(void* native_binding_object) {
270+
return webf::NativeBindingObject::IsDisposed(static_cast<webf::NativeBindingObject*>(native_binding_object));
271+
}
272+
263273
void dispatchUITask(void* page_, void* context, void* callback) {
264274
auto page = reinterpret_cast<webf::WebFPage*>(page_);
265275
reinterpret_cast<void (*)(void*)>(callback)(context);

webf/lib/src/bridge/binding.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ Future<void> _dispatchEventToNative(Event event, bool isCapture) async {
110110
if (contextId != null &&
111111
pointer != null &&
112112
pointer.ref.invokeBindingMethodFromDart != nullptr &&
113-
event.target?.pointer?.ref.disposed != true &&
114-
event.currentTarget?.pointer?.ref.disposed != true
113+
!isBindingObjectDisposed(event.target?.pointer) &&
114+
!isBindingObjectDisposed(event.currentTarget?.pointer)
115115
) {
116116
Completer completer = Completer();
117117

@@ -204,7 +204,7 @@ abstract class BindingBridge {
204204
view.setBindingObject(nativeBindingObject, object);
205205
}
206206

207-
if (!nativeBindingObject.ref.disposed) {
207+
if (!isBindingObjectDisposed(nativeBindingObject)) {
208208
nativeBindingObject.ref.invokeBindingMethodFromNative = _invokeBindingMethodFromNative;
209209
}
210210
}

webf/lib/src/bridge/native_types.dart

+47-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import 'dart:ffi';
77

88
import 'package:ffi/ffi.dart';
9+
import 'package:webf/bridge.dart';
910

1011
import 'native_value.dart';
1112

@@ -109,27 +110,64 @@ class NativeTouch extends Struct {
109110
external double azimuthAngle;
110111
}
111112

112-
typedef InvokeBindingsMethodsFromNative = Void Function(Double contextId, Int64 profileId, Pointer<NativeBindingObject> binding_object,
113-
Pointer<NativeValue> return_value, Pointer<NativeValue> method, Int32 argc, Pointer<NativeValue> argv);
113+
typedef InvokeBindingsMethodsFromNative = Void Function(
114+
Double contextId,
115+
Int64 profileId,
116+
Pointer<NativeBindingObject> binding_object,
117+
Pointer<NativeValue> return_value,
118+
Pointer<NativeValue> method,
119+
Int32 argc,
120+
Pointer<NativeValue> argv);
114121
typedef NativeInvokeResultCallback = Void Function(Handle object, Pointer<NativeValue> result);
115122

116-
typedef InvokeBindingMethodsFromDart = Void Function(Pointer<NativeBindingObject> binding_object, Int64 profileId, Pointer<NativeValue> method, Int32 argc, Pointer<NativeValue> argv, Handle bindingDartObject, Pointer<NativeFunction<NativeInvokeResultCallback>> result_callback);
117-
typedef DartInvokeBindingMethodsFromDart = void Function(Pointer<NativeBindingObject> binding_object, int profileId, Pointer<NativeValue> method, int argc, Pointer<NativeValue> argv, Object bindingDartObject, Pointer<NativeFunction<NativeInvokeResultCallback>> result_callback);
123+
typedef InvokeBindingMethodsFromDart = Void Function(
124+
Pointer<NativeBindingObject> binding_object,
125+
Int64 profileId,
126+
Pointer<NativeValue> method,
127+
Int32 argc,
128+
Pointer<NativeValue> argv,
129+
Handle bindingDartObject,
130+
Pointer<NativeFunction<NativeInvokeResultCallback>> result_callback);
131+
typedef DartInvokeBindingMethodsFromDart = void Function(
132+
Pointer<NativeBindingObject> binding_object,
133+
int profileId,
134+
Pointer<NativeValue> method,
135+
int argc,
136+
Pointer<NativeValue> argv,
137+
Object bindingDartObject,
138+
Pointer<NativeFunction<NativeInvokeResultCallback>> result_callback);
118139

119140
class NativeBindingObject extends Struct {
120-
@Bool()
121-
external bool disposed;
122141
external Pointer<Void> instance;
123142
external Pointer<NativeFunction<InvokeBindingMethodsFromDart>> invokeBindingMethodFromDart;
124143
// Shared method called by JS side.
125144
external Pointer<NativeFunction<InvokeBindingsMethodsFromNative>> invokeBindingMethodFromNative;
126145
external Pointer<Void> extra;
146+
@Bool()
147+
external bool _disposed;
127148
}
128149

150+
typedef NativeAllocateNativeBindingObject = Pointer<NativeBindingObject> Function();
151+
typedef DartAllocateNativeBindingObject = Pointer<NativeBindingObject> Function();
152+
153+
final DartAllocateNativeBindingObject _allocateNativeBindingObject = WebFDynamicLibrary.ref
154+
.lookup<NativeFunction<NativeAllocateNativeBindingObject>>('allocateNativeBindingObject')
155+
.asFunction();
156+
157+
typedef NativeIsNativeBindingObjectDisposed = Bool Function(Pointer<NativeBindingObject>);
158+
typedef DartIsNativeBindingObjectDisposed = bool Function(Pointer<NativeBindingObject>);
159+
160+
final DartIsNativeBindingObjectDisposed _isNativeBindingObjectDisposed = WebFDynamicLibrary.ref
161+
.lookup<NativeFunction<NativeIsNativeBindingObjectDisposed>>('isNativeBindingObjectDisposed')
162+
.asFunction();
163+
129164
Pointer<NativeBindingObject> allocateNewBindingObject() {
130-
Pointer<NativeBindingObject> pointer = malloc.allocate(sizeOf<NativeBindingObject>());
131-
pointer.ref.disposed = false;
132-
return pointer;
165+
return _allocateNativeBindingObject();
166+
}
167+
168+
bool isBindingObjectDisposed(Pointer<NativeBindingObject>? nativeBindingObject) {
169+
if (nativeBindingObject == null) return true;
170+
return _isNativeBindingObjectDisposed(nativeBindingObject);
133171
}
134172

135173
class NativePerformanceEntry extends Struct {

webf/lib/src/gesture/gesture_dispatcher.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'package:flutter/material.dart';
1111
import 'package:webf/dom.dart';
1212
import 'package:webf/gesture.dart';
1313
import 'package:webf/html.dart';
14+
import 'package:webf/bridge.dart';
1415

1516
class _DragEventInfo extends Drag {
1617
_DragEventInfo(this.gestureDispatcher);
@@ -432,7 +433,7 @@ class GestureDispatcher {
432433
// The touch target might be eliminated from the DOM tree and collected by JavaScript GC,
433434
// resulting in it becoming invisible and inaccessible, yet this change is not synchronized with Dart instantly.
434435
// Therefore, refrain from triggering events on these unavailable DOM targets.
435-
if (touch.target.pointer?.ref.disposed == true) {
436+
if (isBindingObjectDisposed(touch.target.pointer)) {
436437
continue;
437438
}
438439

0 commit comments

Comments
 (0)