Skip to content

Commit d3efea9

Browse files
authored
JSRuntime lifetime managed by WebFPage lifetime (#629)
Prior to WebF 0.16.0 "[Add Dedicated Threading support.](#512)", the JSRuntime lifecycle was managed by the DartIsolateContext lifecycle. ![ui_thread](https://github.com/user-attachments/assets/8e211366-eecd-4326-87e9-98ced7a34938) But in Dedicated threads, the JSRuntime life cycle must be managed by the WebFPage life cycle, and the `runtime_` redundancy created in DartIsolateContext. Therefore, JSRuntime lifetime managed by WebFPage lifetime in UI thread mode is more uniform ![page_lifetime](https://github.com/user-attachments/assets/d5ea64e6-feca-40b5-9504-68fb1e245633)
2 parents 0dad3df + 99ce435 commit d3efea9

File tree

7 files changed

+41
-30
lines changed

7 files changed

+41
-30
lines changed

bridge/core/dart_isolate_context.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ void DartIsolateContext::InitializeJSRuntime() {
8585
}
8686

8787
void DartIsolateContext::FinalizeJSRuntime() {
88-
if (running_dart_isolates > 0)
88+
if (running_dart_isolates > 0 ||
89+
runtime_ == nullptr) {
8990
return;
91+
}
9092

9193
// Prebuilt strings stored in JSRuntime. Only needs to dispose when runtime disposed.
9294
names_installer::Dispose();
@@ -107,10 +109,10 @@ DartIsolateContext::DartIsolateContext(const uint64_t* dart_methods, int32_t dar
107109
dart_method_ptr_(std::make_unique<DartMethodPointer>(this, dart_methods, dart_methods_length)) {
108110
is_valid_ = true;
109111
running_dart_isolates++;
110-
InitializeJSRuntime();
111112
}
112113

113114
JSRuntime* DartIsolateContext::runtime() {
115+
assert_m(runtime_ != nullptr, "nullptr is unsafe");
114116
return runtime_;
115117
}
116118

@@ -187,10 +189,19 @@ void* DartIsolateContext::AddNewPage(double thread_identity,
187189
return nullptr;
188190
}
189191

192+
std::unique_ptr<WebFPage> DartIsolateContext::InitializeNewPageSync(DartIsolateContext* dart_isolate_context,
193+
size_t sync_buffer_size,
194+
double page_context_id) {
195+
dart_isolate_context->profiler()->StartTrackInitialize();
196+
DartIsolateContext::InitializeJSRuntime();
197+
auto page = std::make_unique<WebFPage>(dart_isolate_context, false, sync_buffer_size, page_context_id, nullptr);
198+
dart_isolate_context->profiler()->FinishTrackInitialize();
199+
200+
return page;
201+
}
202+
190203
void* DartIsolateContext::AddNewPageSync(double thread_identity) {
191-
profiler()->StartTrackSteps("WebFPage::Initialize");
192-
auto page = std::make_unique<WebFPage>(this, false, 0, thread_identity, nullptr);
193-
profiler()->FinishTrackSteps();
204+
auto page = InitializeNewPageSync(this, 0, thread_identity);
194205

195206
void* p = page.get();
196207
pages_in_ui_thread_.emplace(std::move(page));
@@ -252,6 +263,10 @@ void DartIsolateContext::RemovePageSync(double thread_identity, WebFPage* page)
252263
break;
253264
}
254265
}
266+
267+
if (pages_in_ui_thread_.empty()) {
268+
FinalizeJSRuntime();
269+
}
255270
}
256271

257272
} // namespace webf

bridge/core/dart_isolate_context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class DartIsolateContext {
7474
private:
7575
static void InitializeJSRuntime();
7676
static void FinalizeJSRuntime();
77+
static std::unique_ptr<WebFPage> InitializeNewPageSync(DartIsolateContext* dart_isolate_context,
78+
size_t sync_buffer_size,
79+
double page_context_id);
7780
static void InitializeNewPageInJSThread(PageGroup* page_group,
7881
DartIsolateContext* dart_isolate_context,
7982
double page_context_id,

bridge/include/webf_bridge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,6 @@ WEBF_EXPORT_C void executeNativeCallback(DartWork* work_ptr);
147147
WEBF_EXPORT_C
148148
void init_dart_dynamic_linking(void* data);
149149
WEBF_EXPORT_C
150-
void register_dart_context_finalizer(Dart_Handle dart_handle, void* dart_isolate_context);
150+
void on_dart_context_finalized(void* dart_isolate_context);
151151

152152
#endif // WEBF_BRIDGE_EXPORT_H

bridge/webf_bridge.cc

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,11 @@ void* allocateNewPageSync(double thread_identity, void* ptr) {
6767
auto* dart_isolate_context = (webf::DartIsolateContext*)ptr;
6868
assert(dart_isolate_context != nullptr);
6969

70-
dart_isolate_context->profiler()->StartTrackInitialize();
71-
7270
void* result = static_cast<webf::DartIsolateContext*>(dart_isolate_context)->AddNewPageSync(thread_identity);
7371
#if ENABLE_LOG
7472
WEBF_LOG(INFO) << "[Dispatcher]: allocateNewPageSync Call END";
7573
#endif
7674

77-
dart_isolate_context->profiler()->FinishTrackInitialize();
78-
7975
return result;
8076
}
8177

@@ -289,7 +285,7 @@ void clearUICommandItems(void* page_) {
289285
}
290286

291287
// Callbacks when dart context object was finalized by Dart GC.
292-
static void finalize_dart_context(void* isolate_callback_data, void* peer) {
288+
static void finalize_dart_context(void* peer) {
293289
WEBF_LOG(VERBOSE) << "[Dispatcher]: BEGIN FINALIZE DART CONTEXT: ";
294290
auto* dart_isolate_context = (webf::DartIsolateContext*)peer;
295291
dart_isolate_context->Dispose([dart_isolate_context]() {
@@ -306,9 +302,8 @@ void init_dart_dynamic_linking(void* data) {
306302
}
307303
}
308304

309-
void register_dart_context_finalizer(Dart_Handle dart_handle, void* dart_isolate_context) {
310-
Dart_NewFinalizableHandle_DL(dart_handle, reinterpret_cast<void*>(dart_isolate_context),
311-
sizeof(webf::DartIsolateContext), finalize_dart_context);
305+
void on_dart_context_finalized(void* dart_isolate_context) {
306+
finalize_dart_context(dart_isolate_context);
312307
}
313308

314309
int8_t isJSThreadBlocked(void* dart_isolate_context_, double context_id) {

webf/lib/src/bridge/bridge.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,24 @@ import 'dart:async';
77
import 'dart:ffi';
88
import 'package:webf/launcher.dart';
99

10+
import 'dynamic_library.dart';
1011
import 'binding.dart';
1112
import 'from_native.dart';
1213
import 'to_native.dart';
1314
import 'multiple_thread.dart';
1415

15-
class DartContext {
16+
typedef NativeOnDartContextFinalized = Void Function(Pointer<Void> data);
17+
typedef DartOnDartContextFinalized = void Function(Pointer<Void> data);
18+
19+
final _initDartDynamicLinking = WebFDynamicLibrary.ref
20+
.lookup<NativeFunction<NativeOnDartContextFinalized>>('on_dart_context_finalized');
21+
22+
class DartContext implements Finalizable {
23+
static final _finalizer = NativeFinalizer(_initDartDynamicLinking);
24+
1625
DartContext() : pointer = initDartIsolateContext(makeDartMethodsData()) {
1726
initDartDynamicLinking();
18-
registerDartContextFinalizer(this);
27+
_finalizer.attach(this, pointer);
1928
}
2029
final Pointer<Void> pointer;
2130
}
@@ -28,11 +37,11 @@ bool isJSRunningInDedicatedThread(double contextId) {
2837

2938
/// Init bridge
3039
FutureOr<double> initBridge(WebFViewController view, WebFThread runningThread) async {
31-
dartContext ??= DartContext();
32-
3340
// Setup binding bridge.
3441
BindingBridge.setup();
3542

43+
dartContext ??= DartContext();
44+
3645
double newContextId = runningThread.identity();
3746
await allocateNewPage(runningThread is FlutterUIThread, newContextId, runningThread.syncBufferSize());
3847

webf/lib/src/bridge/to_native.dart

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -625,17 +625,6 @@ void initDartDynamicLinking() {
625625
_initDartDynamicLinking(NativeApi.initializeApiDLData);
626626
}
627627

628-
typedef NativeRegisterDartContextFinalizer = Void Function(Handle object, Pointer<Void> dart_context);
629-
typedef DartRegisterDartContextFinalizer = void Function(Object object, Pointer<Void> dart_context);
630-
631-
final DartRegisterDartContextFinalizer _registerDartContextFinalizer = WebFDynamicLibrary.ref
632-
.lookup<NativeFunction<NativeRegisterDartContextFinalizer>>('register_dart_context_finalizer')
633-
.asFunction();
634-
635-
void registerDartContextFinalizer(DartContext dartContext) {
636-
_registerDartContextFinalizer(dartContext, dartContext.pointer);
637-
}
638-
639628
typedef NativeRegisterPluginByteCode = Void Function(Pointer<Uint8> bytes, Int32 length, Pointer<Utf8> pluginName);
640629
typedef DartRegisterPluginByteCode = void Function(Pointer<Uint8> bytes, int length, Pointer<Utf8> pluginName);
641630

webf/lib/src/launcher/controller.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class WebFViewController implements WidgetsBindingObserver {
191191
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
192192
debugPaintSizeEnabled = true;
193193
}
194-
BindingBridge.setup();
194+
195195
_contextId = await initBridge(this, runningThread);
196196

197197
_setupObserver();

0 commit comments

Comments
 (0)