Skip to content

Commit

Permalink
Plumb arguments from Settings to Dart main() (flutter#8710)
Browse files Browse the repository at this point in the history
  • Loading branch information
zanderso authored Apr 25, 2019
1 parent e44c5d9 commit 3a29e6a
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 26 deletions.
2 changes: 2 additions & 0 deletions common/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ struct Settings {

std::string temp_directory_path;
std::vector<std::string> dart_flags;
// Arguments passed as a List<String> to Dart's entrypoint function.
std::vector<std::string> dart_entrypoint_args;

// Isolate settings
bool start_paused = false;
Expand Down
4 changes: 3 additions & 1 deletion lib/stub_ui/lib/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ void _drawFrame() {
}

// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction, Function userMainFunction) {
void _runMainZoned(Function startMainIsolateFunction,
Function userMainFunction,
List<String> args) {
startMainIsolateFunction((){
runZoned<Future<void>>(() {
userMainFunction();
Expand Down
9 changes: 5 additions & 4 deletions lib/ui/hooks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,17 @@ typedef _BinaryFunction(Null args, Null message);

@pragma('vm:entry-point')
// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction, Function userMainFunction) {
void _runMainZoned(Function startMainIsolateFunction,
Function userMainFunction,
List<String> args) {
startMainIsolateFunction((){
runZoned<Future<void>>(() {
const List<String> empty_args = <String>[];
if (userMainFunction is _BinaryFunction) {
// This seems to be undocumented but supported by the command line VM.
// Let's do the same in case old entry-points are ported to Flutter.
(userMainFunction as dynamic)(empty_args, '');
(userMainFunction as dynamic)(args, '');
} else if (userMainFunction is _UnaryFunction) {
(userMainFunction as dynamic)(empty_args);
(userMainFunction as dynamic)(args);
} else {
userMainFunction();
}
Expand Down
18 changes: 13 additions & 5 deletions runtime/dart_isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ bool DartIsolate::MarkIsolateRunnable() {
}

FML_WARN_UNUSED_RESULT
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function,
Dart_Handle args) {
if (tonic::LogIfError(user_entrypoint_function)) {
FML_LOG(ERROR) << "Could not resolve main entrypoint function.";
return false;
Expand All @@ -463,7 +464,7 @@ static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {

if (tonic::LogIfError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
{start_main_isolate_function, user_entrypoint_function}))) {
{start_main_isolate_function, user_entrypoint_function, args}))) {
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
Expand All @@ -472,7 +473,9 @@ static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function) {
}

FML_WARN_UNUSED_RESULT
bool DartIsolate::Run(const std::string& entrypoint_name, fml::closure on_run) {
bool DartIsolate::Run(const std::string& entrypoint_name,
const std::vector<std::string>& args,
fml::closure on_run) {
TRACE_EVENT0("flutter", "DartIsolate::Run");
if (phase_ != Phase::Ready) {
return false;
Expand All @@ -483,7 +486,9 @@ bool DartIsolate::Run(const std::string& entrypoint_name, fml::closure on_run) {
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));

if (!InvokeMainEntrypoint(user_entrypoint_function)) {
auto entrypoint_args = tonic::ToDart(args);

if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}

Expand All @@ -499,6 +504,7 @@ bool DartIsolate::Run(const std::string& entrypoint_name, fml::closure on_run) {
FML_WARN_UNUSED_RESULT
bool DartIsolate::RunFromLibrary(const std::string& library_name,
const std::string& entrypoint_name,
const std::vector<std::string>& args,
fml::closure on_run) {
TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
if (phase_ != Phase::Ready) {
Expand All @@ -511,7 +517,9 @@ bool DartIsolate::RunFromLibrary(const std::string& library_name,
Dart_GetField(Dart_LookupLibrary(tonic::ToDart(library_name.c_str())),
tonic::ToDart(entrypoint_name.c_str()));

if (!InvokeMainEntrypoint(user_entrypoint_function)) {
auto entrypoint_args = tonic::ToDart(args);

if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
return false;
}

Expand Down
5 changes: 4 additions & 1 deletion runtime/dart_isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,14 @@ class DartIsolate : public UIDartState {
std::vector<std::unique_ptr<const fml::Mapping>> kernels);

FML_WARN_UNUSED_RESULT
bool Run(const std::string& entrypoint, fml::closure on_run = nullptr);
bool Run(const std::string& entrypoint,
const std::vector<std::string>& args,
fml::closure on_run = nullptr);

FML_WARN_UNUSED_RESULT
bool RunFromLibrary(const std::string& library_name,
const std::string& entrypoint,
const std::vector<std::string>& args,
fml::closure on_run = nullptr);

FML_WARN_UNUSED_RESULT
Expand Down
46 changes: 34 additions & 12 deletions runtime/dart_isolate_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref,
std::unique_ptr<AutoIsolateShutdown>& result,
const Settings& settings,
fml::RefPtr<fml::TaskRunner> task_runner,
std::string entrypoint) {
std::string entrypoint,
const std::vector<std::string>& args) {
FML_CHECK(task_runner->RunsTasksOnCurrentThread());

if (!vm_ref) {
Expand Down Expand Up @@ -248,7 +249,7 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref,
return;
}

if (!root_isolate->get()->Run(entrypoint,
if (!root_isolate->get()->Run(entrypoint, args,
settings.root_isolate_create_callback)) {
FML_LOG(ERROR) << "Could not run the method \"" << entrypoint
<< "\" in the isolate.";
Expand All @@ -265,12 +266,14 @@ static std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
DartVMRef& vm_ref,
const Settings& settings,
fml::RefPtr<fml::TaskRunner> task_runner,
std::string entrypoint) {
std::string entrypoint,
const std::vector<std::string>& args) {
std::unique_ptr<AutoIsolateShutdown> result;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runner, fml::MakeCopyable([&]() mutable {
RunDartCodeInIsolate(vm_ref, result, settings, task_runner, entrypoint);
RunDartCodeInIsolate(vm_ref, result, settings, task_runner, entrypoint,
args);
latch.Signal();
}));
latch.Wait();
Expand All @@ -281,8 +284,8 @@ TEST_F(DartIsolateTest, IsolateCanLoadAndRunDartCode) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate =
RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(), "main");
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
"main", {});
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
}
Expand All @@ -292,16 +295,16 @@ TEST_F(DartIsolateTest, IsolateCannotLoadAndRunUnknownDartEntrypoint) {
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
"thisShouldNotExist");
"thisShouldNotExist", {});
ASSERT_FALSE(isolate);
}

TEST_F(DartIsolateTest, CanRunDartCodeCodeSynchronously) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate =
RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(), "main");
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetCurrentTaskRunner(),
"main", {});

ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
Expand All @@ -325,7 +328,7 @@ TEST_F(DartIsolateTest, CanRegisterNativeCallback) {
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(),
"canRegisterNativeCallback");
"canRegisterNativeCallback", {});
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
latch.Wait();
Expand All @@ -348,7 +351,7 @@ TEST_F(DartIsolateTest, CanSaveCompilationTrace) {
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(),
"testCanSaveCompilationTrace");
"testCanSaveCompilationTrace", {});
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);

Expand All @@ -371,7 +374,26 @@ TEST_F(DartIsolateTest, CanLaunchSecondaryIsolates) {
const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(),
"testCanLaunchSecondaryIsolate");
"testCanLaunchSecondaryIsolate", {});
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);

latch.Wait();
}

TEST_F(DartIsolateTest, CanRecieveArguments) {
fml::AutoResetWaitableEvent latch;
AddNativeCallback("NotifyNative",
CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments args) {
ASSERT_TRUE(tonic::DartConverter<bool>::FromDart(
Dart_GetNativeArgument(args, 0)));
latch.Signal();
})));

const auto settings = CreateSettingsForFixture();
auto vm_ref = DartVMRef::Create(settings);
auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(),
"testCanRecieveArguments", {"arg1"});
ASSERT_TRUE(isolate);
ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);

Expand Down
2 changes: 1 addition & 1 deletion runtime/dart_lifecycle_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static std::shared_ptr<DartIsolate> CreateAndRunRootIsolate(
return nullptr;
}

if (!isolate->Run(entrypoint, settings.root_isolate_create_callback)) {
if (!isolate->Run(entrypoint, {}, settings.root_isolate_create_callback)) {
FML_LOG(ERROR) << "Could not run entrypoint: " << entrypoint << ".";
return nullptr;
}
Expand Down
5 changes: 5 additions & 0 deletions runtime/fixtures/runtime_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,8 @@ void testCanLaunchSecondaryIsolate() {
Isolate.spawn(secondaryIsolateMain, "Hello from root isolate.");
NotifyNative();
}

@pragma('vm:entry-point')
void testCanRecieveArguments(List<String> args) {
NotifyResult(args != null && args.length == 1 && args[0] == "arg1");
}
6 changes: 4 additions & 2 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,15 @@ Engine::RunStatus Engine::PrepareAndLaunchIsolate(
}

if (configuration.GetEntrypointLibrary().empty()) {
if (!isolate->Run(configuration.GetEntrypoint())) {
if (!isolate->Run(configuration.GetEntrypoint(),
settings_.dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
} else {
if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
configuration.GetEntrypoint())) {
configuration.GetEntrypoint(),
settings_.dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
Expand Down

0 comments on commit 3a29e6a

Please sign in to comment.