Started looking for the dart plugin registrant at runtime (flutter/engine#31418)
This commit is contained in:
@@ -145,6 +145,7 @@ group("flutter") {
|
||||
"//flutter/lib/spirv/test/supported_glsl_op_shaders:spirv_compile_supported_glsl_shaders",
|
||||
"//flutter/lib/spirv/test/supported_op_shaders:spirv_compile_supported_op_shaders",
|
||||
"//flutter/lib/ui:ui_unittests",
|
||||
"//flutter/runtime:dart_plugin_registrant_unittests",
|
||||
"//flutter/runtime:no_dart_plugin_registrant_unittests",
|
||||
"//flutter/runtime:runtime_unittests",
|
||||
"//flutter/shell/common:shell_unittests",
|
||||
|
||||
@@ -962,6 +962,7 @@ FILE: ../../../flutter/runtime/dart_isolate_group_data.cc
|
||||
FILE: ../../../flutter/runtime/dart_isolate_group_data.h
|
||||
FILE: ../../../flutter/runtime/dart_isolate_unittests.cc
|
||||
FILE: ../../../flutter/runtime/dart_lifecycle_unittests.cc
|
||||
FILE: ../../../flutter/runtime/dart_plugin_registrant_unittests.cc
|
||||
FILE: ../../../flutter/runtime/dart_service_isolate.cc
|
||||
FILE: ../../../flutter/runtime/dart_service_isolate.h
|
||||
FILE: ../../../flutter/runtime/dart_service_isolate_unittests.cc
|
||||
@@ -978,6 +979,7 @@ FILE: ../../../flutter/runtime/dart_vm_lifecycle.h
|
||||
FILE: ../../../flutter/runtime/dart_vm_unittests.cc
|
||||
FILE: ../../../flutter/runtime/embedder_resources.cc
|
||||
FILE: ../../../flutter/runtime/embedder_resources.h
|
||||
FILE: ../../../flutter/runtime/fixtures/dart_tool/flutter_build/dart_plugin_registrant.dart
|
||||
FILE: ../../../flutter/runtime/fixtures/no_dart_plugin_registrant_test.dart
|
||||
FILE: ../../../flutter/runtime/fixtures/runtime_test.dart
|
||||
FILE: ../../../flutter/runtime/fixtures/split_lib_test.dart
|
||||
|
||||
@@ -158,4 +158,24 @@ if (enable_unittests) {
|
||||
"//flutter/testing:fixture_test",
|
||||
]
|
||||
}
|
||||
|
||||
test_fixtures("plugin_registrant") {
|
||||
dart_main = "fixtures/dart_tool/flutter_build/dart_plugin_registrant.dart"
|
||||
use_target_as_artifact_prefix = true
|
||||
}
|
||||
|
||||
executable("dart_plugin_registrant_unittests") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "dart_plugin_registrant_unittests.cc" ]
|
||||
|
||||
public_configs = [ "//flutter:export_dynamic_symbols" ]
|
||||
|
||||
public_deps = [
|
||||
":plugin_registrant",
|
||||
"//flutter/fml",
|
||||
"//flutter/testing",
|
||||
"//flutter/testing:fixture_test",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,6 +709,34 @@ static void InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle) {
|
||||
tonic::LogIfError(tonic::DartInvokeField(plugin_registrant, "register", {}));
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool EndsWith(const std::string& str, const std::string& ending) {
|
||||
if (str.size() >= ending.size()) {
|
||||
return (0 ==
|
||||
str.compare(str.size() - ending.size(), ending.size(), ending));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Dart_Handle FindDartPluginRegistrantLibrary() {
|
||||
// TODO(): Instead of finding this, it could be passed down from the tool.
|
||||
Dart_Handle libraries = Dart_GetLoadedLibraries();
|
||||
intptr_t length = 0;
|
||||
Dart_ListLength(libraries, &length);
|
||||
for (intptr_t i = 0; i < length; ++i) {
|
||||
Dart_Handle library = Dart_ListGetAt(libraries, i);
|
||||
std::string library_name =
|
||||
tonic::DartConverter<std::string>::FromDart(Dart_ToString(library));
|
||||
if (EndsWith(library_name,
|
||||
"dart_tool/flutter_build/dart_plugin_registrant.dart'")) {
|
||||
return library;
|
||||
}
|
||||
}
|
||||
return Dart_Null();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
|
||||
std::optional<std::string> entrypoint,
|
||||
const std::vector<std::string>& args) {
|
||||
@@ -727,7 +755,12 @@ bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
|
||||
? tonic::ToDart(entrypoint.value().c_str())
|
||||
: tonic::ToDart("main");
|
||||
|
||||
InvokeDartPluginRegistrantIfAvailable(library_handle);
|
||||
auto dart_plugin_registrant_library = FindDartPluginRegistrantLibrary();
|
||||
if (!Dart_IsNull(dart_plugin_registrant_library)) {
|
||||
InvokeDartPluginRegistrantIfAvailable(dart_plugin_registrant_library);
|
||||
} else {
|
||||
InvokeDartPluginRegistrantIfAvailable(library_handle);
|
||||
}
|
||||
|
||||
auto user_entrypoint_function =
|
||||
::Dart_GetField(library_handle, entrypoint_handle);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/runtime/dart_isolate.h"
|
||||
|
||||
#include "flutter/fml/paths.h"
|
||||
#include "flutter/runtime/dart_vm.h"
|
||||
#include "flutter/runtime/dart_vm_lifecycle.h"
|
||||
#include "flutter/testing/dart_isolate_runner.h"
|
||||
#include "flutter/testing/fixture_test.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
|
||||
// CREATE_NATIVE_ENTRY is leaky by design
|
||||
// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
const std::string kernel_file_name = "plugin_registrant_kernel_blob.bin";
|
||||
const std::string elf_file_name = "plugin_registrant_app_elf_snapshot.so";
|
||||
|
||||
class DartIsolateTest : public FixtureTest {
|
||||
public:
|
||||
DartIsolateTest() : FixtureTest(kernel_file_name, elf_file_name, "") {}
|
||||
};
|
||||
|
||||
TEST_F(DartIsolateTest, DartPluginRegistrantIsNotPresent) {
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
|
||||
std::vector<std::string> messages;
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
|
||||
AddNativeCallback(
|
||||
"PassMessage",
|
||||
CREATE_NATIVE_ENTRY(([&latch, &messages](Dart_NativeArguments args) {
|
||||
auto message = tonic::DartConverter<std::string>::FromDart(
|
||||
Dart_GetNativeArgument(args, 0));
|
||||
messages.push_back(message);
|
||||
latch.Signal();
|
||||
})));
|
||||
|
||||
auto settings = CreateSettingsForFixture();
|
||||
auto did_throw_exception = false;
|
||||
settings.unhandled_exception_callback = [&](const std::string& error,
|
||||
const std::string& stack_trace) {
|
||||
did_throw_exception = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
auto vm_ref = DartVMRef::Create(settings);
|
||||
auto thread = CreateNewThread();
|
||||
TaskRunners task_runners(GetCurrentTestName(), //
|
||||
thread, //
|
||||
thread, //
|
||||
thread, //
|
||||
thread //
|
||||
);
|
||||
|
||||
auto kernel_path =
|
||||
fml::paths::JoinPaths({GetFixturesPath(), kernel_file_name});
|
||||
auto isolate =
|
||||
RunDartCodeInIsolate(vm_ref, settings, task_runners,
|
||||
"mainForPluginRegistrantTest", {}, kernel_path);
|
||||
|
||||
ASSERT_TRUE(isolate);
|
||||
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
|
||||
|
||||
latch.Wait();
|
||||
|
||||
ASSERT_EQ(messages.size(), 1u);
|
||||
ASSERT_EQ(messages[0], "_PluginRegistrant.register() was called");
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
// NOLINTEND(clang-analyzer-core.StackAddressEscape)
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
void passMessage(String message) native 'PassMessage';
|
||||
|
||||
bool didCallRegistrantBeforeEntrypoint = false;
|
||||
|
||||
// Test the Dart plugin registrant.
|
||||
@pragma('vm:entry-point')
|
||||
class _PluginRegistrant {
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
static void register() {
|
||||
if (didCallRegistrantBeforeEntrypoint) {
|
||||
throw '_registerPlugins is being called twice';
|
||||
}
|
||||
didCallRegistrantBeforeEntrypoint = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void mainForPluginRegistrantTest() {
|
||||
if (didCallRegistrantBeforeEntrypoint) {
|
||||
passMessage('_PluginRegistrant.register() was called');
|
||||
} else {
|
||||
passMessage('_PluginRegistrant.register() was not called');
|
||||
}
|
||||
}
|
||||
|
||||
void main() {}
|
||||
Reference in New Issue
Block a user