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

Commit a4836a6

Browse files
author
Emmanuel Garcia
authored
Call Dart plugin registrant if available (#23813)
1 parent 993ab78 commit a4836a6

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

lib/ui/hooks.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,14 @@ typedef _ListStringArgFunction(List<String> args);
126126
@pragma('vm:entry-point')
127127
// ignore: unused_element
128128
void _runMainZoned(Function startMainIsolateFunction,
129+
Function? dartPluginRegistrant,
129130
Function userMainFunction,
130131
List<String> args) {
131132
startMainIsolateFunction(() {
132133
runZonedGuarded<void>(() {
134+
if (dartPluginRegistrant != null) {
135+
dartPluginRegistrant();
136+
}
133137
if (userMainFunction is _ListStringArgFunction) {
134138
(userMainFunction as dynamic)(args);
135139
} else {

runtime/dart_isolate.cc

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ bool DartIsolate::MarkIsolateRunnable() {
674674

675675
[[nodiscard]] static bool InvokeMainEntrypoint(
676676
Dart_Handle user_entrypoint_function,
677+
Dart_Handle plugin_registrant_function,
677678
Dart_Handle args) {
678679
if (tonic::LogIfError(user_entrypoint_function)) {
679680
FML_LOG(ERROR) << "Could not resolve main entrypoint function.";
@@ -691,7 +692,8 @@ bool DartIsolate::MarkIsolateRunnable() {
691692

692693
if (tonic::LogIfError(tonic::DartInvokeField(
693694
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
694-
{start_main_isolate_function, user_entrypoint_function, args}))) {
695+
{start_main_isolate_function, plugin_registrant_function,
696+
user_entrypoint_function, args}))) {
695697
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
696698
return false;
697699
}
@@ -716,12 +718,34 @@ bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
716718
auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
717719
? tonic::ToDart(entrypoint.value().c_str())
718720
: tonic::ToDart("main");
721+
auto entrypoint_args = tonic::ToDart(args);
719722
auto user_entrypoint_function =
720723
::Dart_GetField(library_handle, entrypoint_handle);
721724

722-
auto entrypoint_args = tonic::ToDart(args);
723-
724-
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
725+
// The Dart plugin registrant is a function named `_registerPlugins`
726+
// generated by the Flutter tool.
727+
//
728+
// This function binds a plugin implementation to their platform
729+
// interface based on the configuration of the app's pubpec.yaml, and the
730+
// plugin's pubspec.yaml.
731+
//
732+
// Since this function may or may not be defined. Check that it is a top
733+
// level function, and call it in hooks.dart before the main entrypoint
734+
// function.
735+
//
736+
// If it's not defined, then just call the main entrypoint function
737+
// as usual.
738+
//
739+
// This allows embeddings to change the name of the entrypoint function.
740+
auto plugin_registrant_function =
741+
::Dart_GetField(library_handle, tonic::ToDart("_registerPlugins"));
742+
743+
if (Dart_IsError(plugin_registrant_function)) {
744+
plugin_registrant_function = Dart_Null();
745+
}
746+
747+
if (!InvokeMainEntrypoint(user_entrypoint_function,
748+
plugin_registrant_function, entrypoint_args)) {
725749
return false;
726750
}
727751

runtime/dart_isolate_unittests.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,5 +597,39 @@ TEST_F(DartIsolateTest, DISABLED_ValidLoadingUnitSucceeds) {
597597
Wait();
598598
}
599599

600+
TEST_F(DartIsolateTest, DartPluginRegistrantIsCalled) {
601+
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
602+
603+
std::vector<std::string> messages;
604+
fml::AutoResetWaitableEvent latch;
605+
606+
AddNativeCallback(
607+
"PassMessage",
608+
CREATE_NATIVE_ENTRY(([&latch, &messages](Dart_NativeArguments args) {
609+
auto message = tonic::DartConverter<std::string>::FromDart(
610+
Dart_GetNativeArgument(args, 0));
611+
messages.push_back(message);
612+
latch.Signal();
613+
})));
614+
615+
const auto settings = CreateSettingsForFixture();
616+
auto vm_ref = DartVMRef::Create(settings);
617+
auto thread = CreateNewThread();
618+
TaskRunners task_runners(GetCurrentTestName(), //
619+
thread, //
620+
thread, //
621+
thread, //
622+
thread //
623+
);
624+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
625+
"mainForPluginRegistrantTest", {},
626+
GetFixturesPath());
627+
ASSERT_TRUE(isolate);
628+
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
629+
latch.Wait();
630+
ASSERT_EQ(messages.size(), 1u);
631+
ASSERT_EQ(messages[0], "_registerPlugins was called");
632+
}
633+
600634
} // namespace testing
601635
} // namespace flutter

runtime/fixtures/runtime_test.dart

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import 'dart:ui';
1010

1111
import 'split_lib_test.dart' deferred as splitlib;
1212

13-
void main() {
14-
}
13+
void main() {}
1514

1615
@pragma('vm:entry-point')
1716
void sayHi() {
@@ -115,3 +114,24 @@ void testCanConvertListOfInts(List<int> args){
115114
args[2] == 3 &&
116115
args[3] == 4);
117116
}
117+
118+
bool didCallRegistrantBeforeEntrypoint = false;
119+
120+
// Test the Dart plugin registrant.
121+
// _registerPlugins requires the entrypoint annotation, so the compiler doesn't tree shake it.
122+
@pragma('vm:entry-point')
123+
void _registerPlugins() { // ignore: unused_element
124+
if (didCallRegistrantBeforeEntrypoint) {
125+
throw '_registerPlugins is being called twice';
126+
}
127+
didCallRegistrantBeforeEntrypoint = true;
128+
}
129+
130+
@pragma('vm:entry-point')
131+
void mainForPluginRegistrantTest() { // ignore: unused_element
132+
if (didCallRegistrantBeforeEntrypoint) {
133+
passMessage('_registerPlugins was called');
134+
} else {
135+
passMessage('_registerPlugins was not called');
136+
}
137+
}

0 commit comments

Comments
 (0)