Dart Plugin Registrant - Reland e525aced27 (flutter/engine#32189)

This commit is contained in:
gaaclarke
2022-03-23 18:20:05 -07:00
committed by GitHub
parent dadc179b9a
commit 237c111725
8 changed files with 67 additions and 34 deletions

View File

@@ -187,6 +187,7 @@ if (enable_unittests) {
public_deps = [
":plugin_registrant",
"//flutter/fml",
"//flutter/runtime:dart_plugin_registrant",
"//flutter/testing",
"//flutter/testing:fixture_test",
]

View File

@@ -706,7 +706,12 @@ bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
? tonic::ToDart(entrypoint.value().c_str())
: tonic::ToDart("main");
InvokeDartPluginRegistrantIfAvailable(library_handle);
if (!FindAndInvokeDartPluginRegistrant()) {
// TODO(gaaclarke): Remove once the framework PR lands that uses `--source`
// to compile the Dart Plugin Registrant
// (https://github.com/flutter/flutter/pull/100572).
InvokeDartPluginRegistrantIfAvailable(library_handle);
}
auto user_entrypoint_function =
::Dart_GetField(library_handle, entrypoint_handle);

View File

@@ -6,40 +6,14 @@
#include <string>
#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/logging/dart_invoke.h"
namespace flutter {
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(99308): 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
const char* dart_plugin_registrant_library_override = nullptr;
bool InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle) {
TRACE_EVENT0("flutter", "InvokeDartPluginRegistrantIfAvailable");
@@ -65,12 +39,30 @@ bool InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle) {
}
bool FindAndInvokeDartPluginRegistrant() {
auto dart_plugin_registrant_library = FindDartPluginRegistrantLibrary();
if (!Dart_IsNull(dart_plugin_registrant_library)) {
return InvokeDartPluginRegistrantIfAvailable(
dart_plugin_registrant_library);
} else {
std::string library_name =
dart_plugin_registrant_library_override == nullptr
? "package:flutter/src/dart_plugin_registrant.dart"
: dart_plugin_registrant_library_override;
Dart_Handle library = Dart_LookupLibrary(tonic::ToDart(library_name));
if (Dart_IsError(library)) {
return false;
}
Dart_Handle registrant_file_uri =
Dart_GetField(library, tonic::ToDart("dartPluginRegistrantLibrary"));
if (Dart_IsError(registrant_file_uri)) {
// TODO(gaaclarke): Find a way to remove this branch so the field is
// required. I couldn't get it working with unit tests.
return InvokeDartPluginRegistrantIfAvailable(library);
}
std::string registrant_file_uri_string =
tonic::DartConverter<std::string>::FromDart(registrant_file_uri);
if (registrant_file_uri_string.empty()) {
FML_LOG(ERROR) << "Unexpected empty dartPluginRegistrantLibrary.";
return false;
}
Dart_Handle registrant_library = Dart_LookupLibrary(registrant_file_uri);
return InvokeDartPluginRegistrantIfAvailable(registrant_library);
}
} // namespace flutter

View File

@@ -9,6 +9,10 @@
namespace flutter {
/// The name of the library where the Dart Plugin Registrant will be looked for.
/// This is available for testing.
extern const char* dart_plugin_registrant_library_override;
/// Looks for the Dart Plugin Registrant in `library_handle` and invokes it if
/// it is found.
/// @return `true` when the registrant has been invoked.

View File

@@ -4,7 +4,9 @@
#include "flutter/runtime/dart_isolate.h"
#include <cstdlib>
#include "flutter/fml/paths.h"
#include "flutter/runtime/dart_plugin_registrant.h"
#include "flutter/runtime/dart_vm.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/testing/dart_isolate_runner.h"
@@ -23,6 +25,30 @@ 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, "") {}
void OverrideDartPluginRegistrant(const std::string& override_value) {
dart_plugin_registrant_library_ = override_value;
dart_plugin_registrant_library_override =
dart_plugin_registrant_library_.c_str();
}
void SetUp() override {
std::string source_path = GetSourcePath();
if (source_path[0] != '/') {
// On windows we need an extra '/' prefix.
source_path = "/" + source_path;
}
std::string registrant_uri = std::string("file://") + source_path +
"flutter/runtime/fixtures/dart_tool/"
"flutter_build/dart_plugin_registrant.dart";
OverrideDartPluginRegistrant(registrant_uri);
}
void TearDown() override {
dart_plugin_registrant_library_override = nullptr;
}
std::string dart_plugin_registrant_library_;
};
TEST_F(DartIsolateTest, DartPluginRegistrantIsPresent) {

View File

@@ -4,6 +4,7 @@
import 'dart:isolate';
import 'dart:ui';
import 'dart:io' show Platform;
void passMessage(String message) native 'PassMessage';

View File

@@ -27,11 +27,13 @@ template("fixtures_location") {
location_path = rebase_path(invoker.assets_dir)
testing_assets_path = rebase_path("$root_out_dir/gen/flutter/testing/assets")
source_path = rebase_path("//")
# Array of source lines. We use a list to ensure a trailing newline is
# emitted by write_file() to comply with -Wnewline-eof.
location_source = [
"namespace flutter { namespace testing { ",
"const char* GetSourcePath() {return \"$source_path\";} ",
"const char* GetFixturesPath() {return \"$location_path\";} ",
"const char* GetTestingAssetsPath() {return \"$testing_assets_path\";} ",
"}}",

View File

@@ -16,6 +16,8 @@
namespace flutter {
namespace testing {
const char* GetSourcePath();
//------------------------------------------------------------------------------
/// @brief Returns the directory containing the test fixture for the target
/// if this target has fixtures configured. If there are no