Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 1239df9

Browse files
authored
Allow native bindings in secondary isolates. (#8658)
The callbacks can be wired in via the Settings object. Both runtime and shell unit-tests have been patched to test this.
1 parent b0cbce4 commit 1239df9

18 files changed

+268
-86
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ FILE: ../../../flutter/runtime/dart_vm_lifecycle.h
392392
FILE: ../../../flutter/runtime/dart_vm_unittests.cc
393393
FILE: ../../../flutter/runtime/embedder_resources.cc
394394
FILE: ../../../flutter/runtime/embedder_resources.h
395-
FILE: ../../../flutter/runtime/fixtures/simple_main.dart
395+
FILE: ../../../flutter/runtime/fixtures/runtime_test.dart
396396
FILE: ../../../flutter/runtime/runtime_controller.cc
397397
FILE: ../../../flutter/runtime/runtime_controller.h
398398
FILE: ../../../flutter/runtime/runtime_delegate.cc
@@ -409,7 +409,7 @@ FILE: ../../../flutter/shell/common/animator.cc
409409
FILE: ../../../flutter/shell/common/animator.h
410410
FILE: ../../../flutter/shell/common/engine.cc
411411
FILE: ../../../flutter/shell/common/engine.h
412-
FILE: ../../../flutter/shell/common/fixtures/main.dart
412+
FILE: ../../../flutter/shell/common/fixtures/shell_test.dart
413413
FILE: ../../../flutter/shell/common/isolate_configuration.cc
414414
FILE: ../../../flutter/shell/common/isolate_configuration.h
415415
FILE: ../../../flutter/shell/common/persistent_cache.cc

common/settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ struct Settings {
113113
// The main isolate is current when this callback is made. This is a good spot
114114
// to perform native Dart bindings for libraries not built in.
115115
fml::closure root_isolate_create_callback;
116+
fml::closure isolate_create_callback;
116117
// The isolate is not current and may have already been destroyed when this
117118
// call is made.
118119
fml::closure root_isolate_shutdown_callback;
120+
fml::closure isolate_shutdown_callback;
119121
// The callback made on the UI thread in an isolate scope when the engine
120122
// detects that the framework is idle. The VM also uses this time to perform
121123
// tasks suitable when idling. Due to this, embedders are still advised to be

runtime/BUILD.gn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ source_set("runtime") {
9696
}
9797

9898
test_fixtures("runtime_fixtures") {
99-
fixtures = [ "fixtures/simple_main.dart" ]
99+
fixtures = [ "fixtures/runtime_test.dart" ]
100100
}
101101

102102
source_set("runtime_unittests_common") {

runtime/dart_isolate.cc

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
3939
fml::WeakPtr<IOManager> io_manager,
4040
std::string advisory_script_uri,
4141
std::string advisory_script_entrypoint,
42-
Dart_IsolateFlags* flags) {
42+
Dart_IsolateFlags* flags,
43+
fml::closure isolate_create_callback,
44+
fml::closure isolate_shutdown_callback) {
4345
TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate");
4446
Dart_Isolate vm_isolate = nullptr;
4547
std::weak_ptr<DartIsolate> embedder_isolate;
@@ -49,6 +51,9 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
4951
// Since this is the root isolate, we fake a parent embedder data object. We
5052
// cannot use unique_ptr here because the destructor is private (since the
5153
// isolate lifecycle is entirely managed by the VM).
54+
//
55+
// The child isolate preparer is null but will be set when the isolate is
56+
// being prepared to run.
5257
auto root_embedder_data = std::make_unique<std::shared_ptr<DartIsolate>>(
5358
std::make_shared<DartIsolate>(
5459
settings, // settings
@@ -59,8 +64,9 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
5964
std::move(io_manager), // IO manager
6065
advisory_script_uri, // advisory URI
6166
advisory_script_entrypoint, // advisory entrypoint
62-
nullptr // child isolate preparer will be set when this isolate is
63-
// prepared to run
67+
nullptr, // child isolate preparer
68+
isolate_create_callback, // isolate create callback
69+
isolate_shutdown_callback // isolate shutdown callback
6470
));
6571

6672
std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair(
@@ -102,7 +108,9 @@ DartIsolate::DartIsolate(const Settings& settings,
102108
fml::WeakPtr<IOManager> io_manager,
103109
std::string advisory_script_uri,
104110
std::string advisory_script_entrypoint,
105-
ChildIsolatePreparer child_isolate_preparer)
111+
ChildIsolatePreparer child_isolate_preparer,
112+
fml::closure isolate_create_callback,
113+
fml::closure isolate_shutdown_callback)
106114
: UIDartState(std::move(task_runners),
107115
settings.task_observer_add,
108116
settings.task_observer_remove,
@@ -116,7 +124,9 @@ DartIsolate::DartIsolate(const Settings& settings,
116124
settings_(settings),
117125
isolate_snapshot_(std::move(isolate_snapshot)),
118126
shared_snapshot_(std::move(shared_snapshot)),
119-
child_isolate_preparer_(std::move(child_isolate_preparer)) {
127+
child_isolate_preparer_(std::move(child_isolate_preparer)),
128+
isolate_create_callback_(isolate_create_callback),
129+
isolate_shutdown_callback_(isolate_shutdown_callback) {
120130
FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot.";
121131
phase_ = Phase::Uninitialized;
122132
}
@@ -279,6 +289,11 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() {
279289
child_isolate_preparer_ = [](DartIsolate* isolate) {
280290
return isolate->PrepareForRunningFromPrecompiledCode();
281291
};
292+
293+
if (isolate_create_callback_) {
294+
isolate_create_callback_();
295+
}
296+
282297
phase_ = Phase::Ready;
283298
return true;
284299
}
@@ -365,7 +380,13 @@ bool DartIsolate::PrepareForRunningFromKernel(
365380
return true;
366381
};
367382
}
383+
384+
if (isolate_create_callback_) {
385+
isolate_create_callback_();
386+
}
387+
368388
phase_ = Phase::Ready;
389+
369390
return true;
370391
}
371392

@@ -563,7 +584,9 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
563584
{}, // IO Manager
564585
DART_VM_SERVICE_ISOLATE_NAME, // script uri
565586
DART_VM_SERVICE_ISOLATE_NAME, // script entrypoint
566-
flags // flags
587+
flags, // flags
588+
nullptr, // isolate create callback
589+
nullptr // isolate shutdown callback
567590
);
568591

569592
std::shared_ptr<DartIsolate> service_isolate = weak_service_isolate.lock();
@@ -662,6 +685,7 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
662685
TaskRunners null_task_runners(advisory_script_uri, nullptr, nullptr,
663686
nullptr, nullptr);
664687

688+
// Copy most fields from the parent to the child.
665689
embedder_isolate = std::make_unique<std::shared_ptr<DartIsolate>>(
666690
std::make_shared<DartIsolate>(
667691
(*raw_embedder_isolate)->GetSettings(), // settings
@@ -672,7 +696,12 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
672696
fml::WeakPtr<IOManager>{}, // io_manager
673697
advisory_script_uri, // advisory_script_uri
674698
advisory_script_entrypoint, // advisory_script_entrypoint
675-
(*raw_embedder_isolate)->child_isolate_preparer_));
699+
(*raw_embedder_isolate)->child_isolate_preparer_, // preparer
700+
(*raw_embedder_isolate)->isolate_create_callback_, // on create
701+
(*raw_embedder_isolate)->isolate_shutdown_callback_ // on shutdown
702+
)
703+
704+
);
676705
}
677706

678707
// Create the Dart VM isolate and give it the embedder object as the baton.
@@ -755,6 +784,9 @@ void DartIsolate::AddIsolateShutdownCallback(fml::closure closure) {
755784

756785
void DartIsolate::OnShutdownCallback() {
757786
shutdown_callbacks_.clear();
787+
if (isolate_shutdown_callback_) {
788+
isolate_shutdown_callback_();
789+
}
758790
}
759791

760792
DartIsolate::AutoFireClosure::AutoFireClosure(fml::closure closure)

runtime/dart_isolate.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class DartIsolate : public UIDartState {
5151
fml::WeakPtr<IOManager> io_manager,
5252
std::string advisory_script_uri,
5353
std::string advisory_script_entrypoint,
54-
Dart_IsolateFlags* flags = nullptr);
54+
Dart_IsolateFlags* flags,
55+
fml::closure isolate_create_callback,
56+
fml::closure isolate_shutdown_callback);
5557

5658
DartIsolate(const Settings& settings,
5759
fml::RefPtr<const DartSnapshot> isolate_snapshot,
@@ -61,7 +63,9 @@ class DartIsolate : public UIDartState {
6163
fml::WeakPtr<IOManager> io_manager,
6264
std::string advisory_script_uri,
6365
std::string advisory_script_entrypoint,
64-
ChildIsolatePreparer child_isolate_preparer);
66+
ChildIsolatePreparer child_isolate_preparer,
67+
fml::closure isolate_create_callback,
68+
fml::closure isolate_shutdown_callback);
6569

6670
~DartIsolate() override;
6771

@@ -128,9 +132,11 @@ class DartIsolate : public UIDartState {
128132
std::vector<std::unique_ptr<AutoFireClosure>> shutdown_callbacks_;
129133
ChildIsolatePreparer child_isolate_preparer_ = nullptr;
130134
fml::RefPtr<fml::TaskRunner> message_handling_task_runner_;
135+
const fml::closure isolate_create_callback_;
136+
const fml::closure isolate_shutdown_callback_;
131137

132-
FML_WARN_UNUSED_RESULT
133-
bool Initialize(Dart_Isolate isolate, bool is_root_isolate);
138+
FML_WARN_UNUSED_RESULT bool Initialize(Dart_Isolate isolate,
139+
bool is_root_isolate);
134140

135141
void SetMessageHandlingTaskRunner(fml::RefPtr<fml::TaskRunner> runner,
136142
bool is_root_isolate);

runtime/dart_isolate_unittests.cc

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "flutter/fml/make_copyable.h"
66
#include "flutter/fml/mapping.h"
77
#include "flutter/fml/paths.h"
8+
#include "flutter/fml/synchronization/count_down_latch.h"
89
#include "flutter/fml/synchronization/waitable_event.h"
910
#include "flutter/fml/thread.h"
1011
#include "flutter/runtime/dart_isolate.h"
@@ -35,15 +36,18 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) {
3536
GetCurrentTaskRunner() //
3637
);
3738
auto weak_isolate = DartIsolate::CreateRootIsolate(
38-
vm_data->GetSettings(), // settings
39-
vm_data->GetIsolateSnapshot(), // isolate snapshot
40-
vm_data->GetSharedSnapshot(), // shared snapshot
41-
std::move(task_runners), // task runners
42-
nullptr, // window
43-
{}, // snapshot delegate
44-
{}, // io manager
45-
"main.dart", // advisory uri
46-
"main" // advisory entrypoint
39+
vm_data->GetSettings(), // settings
40+
vm_data->GetIsolateSnapshot(), // isolate snapshot
41+
vm_data->GetSharedSnapshot(), // shared snapshot
42+
std::move(task_runners), // task runners
43+
nullptr, // window
44+
{}, // snapshot delegate
45+
{}, // io manager
46+
"main.dart", // advisory uri
47+
"main", // advisory entrypoint,
48+
nullptr, // flags
49+
settings.isolate_create_callback, // isolate create callback
50+
settings.isolate_shutdown_callback // isolate shutdown callback
4751
);
4852
auto root_isolate = weak_isolate.lock();
4953
ASSERT_TRUE(root_isolate);
@@ -65,15 +69,18 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
6569
GetCurrentTaskRunner() //
6670
);
6771
auto weak_isolate = DartIsolate::CreateRootIsolate(
68-
vm_data->GetSettings(), // settings
69-
vm_data->GetIsolateSnapshot(), // isolate snapshot
70-
vm_data->GetSharedSnapshot(), // shared snapshot
71-
std::move(task_runners), // task runners
72-
nullptr, // window
73-
{}, // snapshot delegate
74-
{}, // io manager
75-
"main.dart", // advisory uri
76-
"main" // advisory entrypoint
72+
vm_data->GetSettings(), // settings
73+
vm_data->GetIsolateSnapshot(), // isolate snapshot
74+
vm_data->GetSharedSnapshot(), // shared snapshot
75+
std::move(task_runners), // task runners
76+
nullptr, // window
77+
{}, // snapshot delegate
78+
{}, // io manager
79+
"main.dart", // advisory uri
80+
"main", // advisory entrypoint
81+
nullptr, // flags
82+
settings.isolate_create_callback, // isolate create callback
83+
settings.isolate_shutdown_callback // isolate shutdown callback
7784
);
7885
auto root_isolate = weak_isolate.lock();
7986
ASSERT_TRUE(root_isolate);
@@ -171,15 +178,18 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref,
171178
}
172179

173180
auto weak_isolate = DartIsolate::CreateRootIsolate(
174-
vm_data->GetSettings(), // settings
175-
vm_data->GetIsolateSnapshot(), // isolate snapshot
176-
vm_data->GetSharedSnapshot(), // shared snapshot
177-
std::move(task_runners), // task runners
178-
nullptr, // window
179-
{}, // snapshot delegate
180-
{}, // io manager
181-
"main.dart", // advisory uri
182-
"main" // advisory entrypoint
181+
vm_data->GetSettings(), // settings
182+
vm_data->GetIsolateSnapshot(), // isolate snapshot
183+
vm_data->GetSharedSnapshot(), // shared snapshot
184+
std::move(task_runners), // task runners
185+
nullptr, // window
186+
{}, // snapshot delegate
187+
{}, // io manager
188+
"main.dart", // advisory uri
189+
"main", // advisory entrypoint
190+
nullptr, // flags
191+
settings.isolate_create_callback, // isolate create callback
192+
settings.isolate_shutdown_callback // isolate shutdown callback
183193
);
184194

185195
auto root_isolate =
@@ -345,5 +355,28 @@ TEST_F(DartIsolateTest, CanSaveCompilationTrace) {
345355
latch.Wait();
346356
}
347357

358+
TEST_F(DartIsolateTest, CanLaunchSecondaryIsolates) {
359+
fml::CountDownLatch latch(3);
360+
AddNativeCallback("NotifyNative",
361+
CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments args) {
362+
latch.CountDown();
363+
})));
364+
AddNativeCallback(
365+
"PassMessage", CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments args) {
366+
auto message = tonic::DartConverter<std::string>::FromDart(
367+
Dart_GetNativeArgument(args, 0));
368+
ASSERT_EQ("Hello from code is secondary isolate.", message);
369+
latch.CountDown();
370+
})));
371+
const auto settings = CreateSettingsForFixture();
372+
auto vm_ref = DartVMRef::Create(settings);
373+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(),
374+
"testCanLaunchSecondaryIsolate");
375+
ASSERT_TRUE(isolate);
376+
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
377+
378+
latch.Wait();
379+
}
380+
348381
} // namespace testing
349382
} // namespace flutter

runtime/dart_lifecycle_unittests.cc

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,18 @@ static std::shared_ptr<DartIsolate> CreateAndRunRootIsolate(
5151
TaskRunners runners("io.flutter.test", task_runner, task_runner, task_runner,
5252
task_runner);
5353
auto isolate_weak = DartIsolate::CreateRootIsolate(
54-
vm.GetSettings(), // settings
55-
vm.GetIsolateSnapshot(), // isolate_snapshot
56-
vm.GetSharedSnapshot(), // shared_snapshot
57-
runners, // task_runners
58-
{}, // window
59-
{}, // snapshot_delegate
60-
{}, // io_manager
61-
"main.dart", // advisory_script_uri
62-
entrypoint.c_str(), // advisory_script_entrypoint
63-
nullptr // flags
54+
vm.GetSettings(), // settings
55+
vm.GetIsolateSnapshot(), // isolate_snapshot
56+
vm.GetSharedSnapshot(), // shared_snapshot
57+
runners, // task_runners
58+
{}, // window
59+
{}, // snapshot_delegate
60+
{}, // io_manager
61+
"main.dart", // advisory_script_uri
62+
entrypoint.c_str(), // advisory_script_entrypoint
63+
nullptr, // flags
64+
settings.isolate_create_callback, // isolate create callback
65+
settings.isolate_shutdown_callback // isolate shutdown callback
6466
);
6567

6668
auto isolate = isolate_weak.lock();

runtime/fixtures/simple_main.dart renamed to runtime/fixtures/runtime_test.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,16 @@ void testCanSaveCompilationTrace() {
4242
}
4343

4444
void NotifyResult(bool success) native "NotifyNative";
45+
void PassMessage(String message) native "PassMessage";
46+
47+
void secondaryIsolateMain(String message) {
48+
print("Secondary isolate got message: " + message);
49+
PassMessage("Hello from code is secondary isolate.");
50+
NotifyNative();
51+
}
52+
53+
@pragma('vm:entry-point')
54+
void testCanLaunchSecondaryIsolate() {
55+
Isolate.spawn(secondaryIsolateMain, "Hello from root isolate.");
56+
NotifyNative();
57+
}

0 commit comments

Comments
 (0)