Skip to content

Commit 5679f96

Browse files
Emmanuel Garciaduanqz
Emmanuel Garcia
authored andcommitted
Reland Dart plugin registrant (flutter#25496)
1 parent 0854eba commit 5679f96

23 files changed

+302
-46
lines changed

BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ group("flutter") {
103103
"//flutter/flow:flow_unittests",
104104
"//flutter/fml:fml_unittests",
105105
"//flutter/lib/ui:ui_unittests",
106+
"//flutter/runtime:no_dart_plugin_registrant_unittests",
106107
"//flutter/runtime:runtime_unittests",
107108
"//flutter/shell/common:shell_unittests",
108109
"//flutter/shell/platform/embedder:embedder_proctable_unittests",

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,12 @@ FILE: ../../../flutter/runtime/dart_vm_lifecycle.h
609609
FILE: ../../../flutter/runtime/dart_vm_unittests.cc
610610
FILE: ../../../flutter/runtime/embedder_resources.cc
611611
FILE: ../../../flutter/runtime/embedder_resources.h
612+
FILE: ../../../flutter/runtime/fixtures/no_dart_plugin_registrant_test.dart
612613
FILE: ../../../flutter/runtime/fixtures/runtime_test.dart
613614
FILE: ../../../flutter/runtime/fixtures/split_lib_test.dart
614615
FILE: ../../../flutter/runtime/isolate_configuration.cc
615616
FILE: ../../../flutter/runtime/isolate_configuration.h
617+
FILE: ../../../flutter/runtime/no_dart_plugin_registrant_unittests.cc
616618
FILE: ../../../flutter/runtime/platform_data.cc
617619
FILE: ../../../flutter/runtime/platform_data.h
618620
FILE: ../../../flutter/runtime/ptrace_check.cc

lib/ui/painting/image_decoder_unittests.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,9 @@ TEST_F(ImageDecoderFixtureTest,
637637
});
638638
latch.Wait();
639639

640-
auto isolate =
641-
RunDartCodeInIsolate(vm_ref, settings, runners, "main", {},
642-
GetFixturesPath(), io_manager->GetWeakIOManager());
640+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, runners, "main", {},
641+
GetDefaultKernelFilePath(),
642+
io_manager->GetWeakIOManager());
643643

644644
// Latch the IO task runner.
645645
runners.GetIOTaskRunner()->PostTask([&]() { io_latch.Wait(); });

lib/ui/ui_benchmarks.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) {
3232
auto vm_ref = DartVMRef::Create(settings);
3333
auto isolate =
3434
testing::RunDartCodeInIsolate(vm_ref, settings, task_runners, "main", {},
35-
testing::GetFixturesPath(), {});
35+
testing::GetDefaultKernelFilePath(), {});
3636

3737
while (state.KeepRunning()) {
3838
state.PauseTiming();

runtime/BUILD.gn

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,24 @@ if (enable_unittests) {
136136
"//third_party/skia",
137137
]
138138
}
139+
140+
test_fixtures("no_plugin_registrant") {
141+
dart_main = "fixtures/no_dart_plugin_registrant_test.dart"
142+
use_target_as_artifact_prefix = true
143+
}
144+
145+
executable("no_dart_plugin_registrant_unittests") {
146+
testonly = true
147+
148+
sources = [ "no_dart_plugin_registrant_unittests.cc" ]
149+
150+
public_configs = [ "//flutter:export_dynamic_symbols" ]
151+
152+
public_deps = [
153+
":no_plugin_registrant",
154+
"//flutter/fml",
155+
"//flutter/testing",
156+
"//flutter/testing:fixture_test",
157+
]
158+
}
139159
}

runtime/dart_isolate.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,28 @@ bool DartIsolate::MarkIsolateRunnable() {
725725
return true;
726726
}
727727

728+
static void InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle) {
729+
TRACE_EVENT0("flutter", "InvokeDartPluginRegistrantIfAvailable");
730+
731+
// The Dart plugin registrant is a static method with signature `void
732+
// register()` within the class `_PluginRegistrant` generated by the Flutter
733+
// tool.
734+
//
735+
// This method binds a plugin implementation to their platform
736+
// interface based on the configuration of the app's pubpec.yaml, and the
737+
// plugin's pubspec.yaml.
738+
//
739+
// Since this method may or may not be defined, check if the class is defined
740+
// in the default library before calling the method.
741+
Dart_Handle plugin_registrant =
742+
::Dart_GetClass(library_handle, tonic::ToDart("_PluginRegistrant"));
743+
744+
if (Dart_IsError(plugin_registrant)) {
745+
return;
746+
}
747+
tonic::LogIfError(tonic::DartInvokeField(plugin_registrant, "register", {}));
748+
}
749+
728750
bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
729751
std::optional<std::string> entrypoint,
730752
const std::vector<std::string>& args) {
@@ -742,6 +764,9 @@ bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
742764
auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
743765
? tonic::ToDart(entrypoint.value().c_str())
744766
: tonic::ToDart("main");
767+
768+
InvokeDartPluginRegistrantIfAvailable(library_handle);
769+
745770
auto user_entrypoint_function =
746771
::Dart_GetField(library_handle, entrypoint_handle);
747772

runtime/dart_isolate_unittests.cc

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ TEST_F(DartIsolateTest, IsolateCanLoadAndRunDartCode) {
214214
GetCurrentTaskRunner() //
215215
);
216216
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
217-
{}, GetFixturesPath());
217+
{}, GetDefaultKernelFilePath());
218218
ASSERT_TRUE(isolate);
219219
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
220220
}
@@ -231,7 +231,7 @@ TEST_F(DartIsolateTest, IsolateCannotLoadAndRunUnknownDartEntrypoint) {
231231
);
232232
auto isolate =
233233
RunDartCodeInIsolate(vm_ref, settings, task_runners, "thisShouldNotExist",
234-
{}, GetFixturesPath());
234+
{}, GetDefaultKernelFilePath());
235235
ASSERT_FALSE(isolate);
236236
}
237237

@@ -246,7 +246,7 @@ TEST_F(DartIsolateTest, CanRunDartCodeCodeSynchronously) {
246246
GetCurrentTaskRunner() //
247247
);
248248
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
249-
{}, GetFixturesPath());
249+
{}, GetDefaultKernelFilePath());
250250

251251
ASSERT_TRUE(isolate);
252252
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
@@ -275,9 +275,9 @@ TEST_F(DartIsolateTest, CanRegisterNativeCallback) {
275275
thread, //
276276
thread //
277277
);
278-
auto isolate =
279-
RunDartCodeInIsolate(vm_ref, settings, task_runners,
280-
"canRegisterNativeCallback", {}, GetFixturesPath());
278+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
279+
"canRegisterNativeCallback", {},
280+
GetDefaultKernelFilePath());
281281
ASSERT_TRUE(isolate);
282282
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
283283
Wait();
@@ -307,7 +307,7 @@ TEST_F(DartIsolateTest, CanSaveCompilationTrace) {
307307
);
308308
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
309309
"testCanSaveCompilationTrace", {},
310-
GetFixturesPath());
310+
GetDefaultKernelFilePath());
311311
ASSERT_TRUE(isolate);
312312
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
313313

@@ -367,7 +367,7 @@ TEST_F(DartSecondaryIsolateTest, CanLaunchSecondaryIsolates) {
367367
);
368368
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
369369
"testCanLaunchSecondaryIsolate", {},
370-
GetFixturesPath());
370+
GetDefaultKernelFilePath());
371371
ASSERT_TRUE(isolate);
372372
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
373373
ChildShutdownWait(); // wait for child isolate to shutdown first
@@ -395,7 +395,7 @@ TEST_F(DartIsolateTest, CanRecieveArguments) {
395395
);
396396
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
397397
"testCanRecieveArguments", {"arg1"},
398-
GetFixturesPath());
398+
GetDefaultKernelFilePath());
399399
ASSERT_TRUE(isolate);
400400
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
401401

@@ -477,7 +477,7 @@ TEST_F(DartIsolateTest,
477477
);
478478
{
479479
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
480-
{}, GetFixturesPath());
480+
{}, GetDefaultKernelFilePath());
481481
ASSERT_TRUE(isolate);
482482
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
483483
}
@@ -505,7 +505,7 @@ TEST_F(DartIsolateTest,
505505
);
506506
{
507507
auto isolate = RunDartCodeInIsolate(vm_ref, instance_settings, task_runners,
508-
"main", {}, GetFixturesPath());
508+
"main", {}, GetDefaultKernelFilePath());
509509
ASSERT_TRUE(isolate);
510510
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
511511
}
@@ -596,9 +596,9 @@ TEST_F(DartIsolateTest, DISABLED_ValidLoadingUnitSucceeds) {
596596
thread, //
597597
thread //
598598
);
599-
auto isolate =
600-
RunDartCodeInIsolate(vm_ref, settings, task_runners,
601-
"canCallDeferredLibrary", {}, GetFixturesPath());
599+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
600+
"canCallDeferredLibrary", {},
601+
GetDefaultKernelFilePath());
602602
ASSERT_TRUE(isolate);
603603
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
604604
Wait();
@@ -613,5 +613,39 @@ TEST_F(DartIsolateTest, DISABLED_ValidLoadingUnitSucceeds) {
613613
Wait();
614614
}
615615

616+
TEST_F(DartIsolateTest, DartPluginRegistrantIsCalled) {
617+
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
618+
619+
std::vector<std::string> messages;
620+
fml::AutoResetWaitableEvent latch;
621+
622+
AddNativeCallback(
623+
"PassMessage",
624+
CREATE_NATIVE_ENTRY(([&latch, &messages](Dart_NativeArguments args) {
625+
auto message = tonic::DartConverter<std::string>::FromDart(
626+
Dart_GetNativeArgument(args, 0));
627+
messages.push_back(message);
628+
latch.Signal();
629+
})));
630+
631+
const auto settings = CreateSettingsForFixture();
632+
auto vm_ref = DartVMRef::Create(settings);
633+
auto thread = CreateNewThread();
634+
TaskRunners task_runners(GetCurrentTestName(), //
635+
thread, //
636+
thread, //
637+
thread, //
638+
thread //
639+
);
640+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
641+
"mainForPluginRegistrantTest", {},
642+
GetDefaultKernelFilePath());
643+
ASSERT_TRUE(isolate);
644+
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
645+
latch.Wait();
646+
ASSERT_EQ(messages.size(), 1u);
647+
ASSERT_EQ(messages[0], "_PluginRegistrant.register() was called");
648+
}
649+
616650
} // namespace testing
617651
} // namespace flutter
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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+
void passMessage(String message) native 'PassMessage';
6+
7+
void main() {
8+
passMessage('main() was called');
9+
}

runtime/fixtures/runtime_test.dart

Lines changed: 27 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,29 @@ 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+
@pragma('vm:entry-point')
122+
class _PluginRegistrant {
123+
124+
@pragma('vm:entry-point')
125+
static void register() {
126+
if (didCallRegistrantBeforeEntrypoint) {
127+
throw '_registerPlugins is being called twice';
128+
}
129+
didCallRegistrantBeforeEntrypoint = true;
130+
}
131+
132+
}
133+
134+
135+
@pragma('vm:entry-point')
136+
void mainForPluginRegistrantTest() { // ignore: unused_element
137+
if (didCallRegistrantBeforeEntrypoint) {
138+
passMessage('_PluginRegistrant.register() was called');
139+
} else {
140+
passMessage('_PluginRegistrant.register() was not called');
141+
}
142+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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 "flutter/runtime/dart_isolate.h"
6+
7+
#include "flutter/fml/paths.h"
8+
#include "flutter/runtime/dart_vm.h"
9+
#include "flutter/runtime/dart_vm_lifecycle.h"
10+
#include "flutter/testing/dart_isolate_runner.h"
11+
#include "flutter/testing/fixture_test.h"
12+
#include "flutter/testing/testing.h"
13+
14+
namespace flutter {
15+
namespace testing {
16+
17+
const std::string kernel_file_name = "no_plugin_registrant_kernel_blob.bin";
18+
const std::string elf_file_name = "no_plugin_registrant_app_elf_snapshot.so";
19+
20+
class DartIsolateTest : public FixtureTest {
21+
public:
22+
DartIsolateTest() : FixtureTest(kernel_file_name, elf_file_name, "") {}
23+
};
24+
25+
TEST_F(DartIsolateTest, DartPluginRegistrantIsNotPresent) {
26+
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
27+
28+
std::vector<std::string> messages;
29+
fml::AutoResetWaitableEvent latch;
30+
31+
AddNativeCallback(
32+
"PassMessage",
33+
CREATE_NATIVE_ENTRY(([&latch, &messages](Dart_NativeArguments args) {
34+
auto message = tonic::DartConverter<std::string>::FromDart(
35+
Dart_GetNativeArgument(args, 0));
36+
messages.push_back(message);
37+
latch.Signal();
38+
})));
39+
40+
auto settings = CreateSettingsForFixture();
41+
auto did_throw_exception = false;
42+
settings.unhandled_exception_callback = [&](const std::string& error,
43+
const std::string& stack_trace) {
44+
did_throw_exception = true;
45+
return true;
46+
};
47+
48+
auto vm_ref = DartVMRef::Create(settings);
49+
auto thread = CreateNewThread();
50+
TaskRunners task_runners(GetCurrentTestName(), //
51+
thread, //
52+
thread, //
53+
thread, //
54+
thread //
55+
);
56+
57+
auto kernel_path =
58+
fml::paths::JoinPaths({GetFixturesPath(), kernel_file_name});
59+
auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
60+
{}, kernel_path);
61+
62+
ASSERT_TRUE(isolate);
63+
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
64+
65+
latch.Wait();
66+
67+
ASSERT_EQ(messages.size(), 1u);
68+
ASSERT_EQ(messages[0], "main() was called");
69+
ASSERT_FALSE(did_throw_exception);
70+
}
71+
72+
} // namespace testing
73+
} // namespace flutter

runtime/type_conversions_unittests.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class TypeConversionsTest : public FixtureTest {
2828
thread, thread, thread);
2929
auto isolate =
3030
RunDartCodeInIsolate(vm_, settings_, single_threaded_task_runner,
31-
entrypoint, {}, GetFixturesPath());
31+
entrypoint, {}, GetDefaultKernelFilePath());
3232
if (!isolate || isolate->get()->GetPhase() != DartIsolate::Phase::Running) {
3333
return false;
3434
}

shell/common/shell_benchmarks.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ static void StartupAndShutdownShell(benchmark::State& state,
2929
settings.task_observer_remove = [](intptr_t) {};
3030

3131
if (DartVM::IsRunningPrecompiledCode()) {
32-
aot_symbols = testing::LoadELFSymbolFromFixturesIfNeccessary();
32+
aot_symbols = testing::LoadELFSymbolFromFixturesIfNeccessary(
33+
testing::kDefaultAOTAppELFFileName);
3334
FML_CHECK(
3435
testing::PrepareSettingsForAOTWithSymbols(settings, aot_symbols))
3536
<< "Could not set up settings with AOT symbols.";

0 commit comments

Comments
 (0)