From 3a29e6a7a7dde7fbedef1b87a3d3a1605aca387f Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Thu, 25 Apr 2019 07:57:54 -0700 Subject: [PATCH] Plumb arguments from Settings to Dart main() (#8710) --- common/settings.h | 2 ++ lib/stub_ui/lib/hooks.dart | 4 ++- lib/ui/hooks.dart | 9 +++--- runtime/dart_isolate.cc | 18 +++++++---- runtime/dart_isolate.h | 5 +++- runtime/dart_isolate_unittests.cc | 46 +++++++++++++++++++++-------- runtime/dart_lifecycle_unittests.cc | 2 +- runtime/fixtures/runtime_test.dart | 5 ++++ shell/common/engine.cc | 6 ++-- 9 files changed, 71 insertions(+), 26 deletions(-) diff --git a/common/settings.h b/common/settings.h index d71cd408dd3b7..58f940535291e 100644 --- a/common/settings.h +++ b/common/settings.h @@ -62,6 +62,8 @@ struct Settings { std::string temp_directory_path; std::vector dart_flags; + // Arguments passed as a List to Dart's entrypoint function. + std::vector dart_entrypoint_args; // Isolate settings bool start_paused = false; diff --git a/lib/stub_ui/lib/hooks.dart b/lib/stub_ui/lib/hooks.dart index 8770c3fac010a..960e92b4af015 100644 --- a/lib/stub_ui/lib/hooks.dart +++ b/lib/stub_ui/lib/hooks.dart @@ -140,7 +140,9 @@ void _drawFrame() { } // ignore: unused_element -void _runMainZoned(Function startMainIsolateFunction, Function userMainFunction) { +void _runMainZoned(Function startMainIsolateFunction, + Function userMainFunction, + List args) { startMainIsolateFunction((){ runZoned>(() { userMainFunction(); diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart index c7b18b6d34d60..dc3b427989505 100644 --- a/lib/ui/hooks.dart +++ b/lib/ui/hooks.dart @@ -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 args) { startMainIsolateFunction((){ runZoned>(() { - const List empty_args = []; 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(); } diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 5d751ec73a577..7aa191c7d701f 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -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; @@ -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; } @@ -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& args, + fml::closure on_run) { TRACE_EVENT0("flutter", "DartIsolate::Run"); if (phase_ != Phase::Ready) { return false; @@ -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; } @@ -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& args, fml::closure on_run) { TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary"); if (phase_ != Phase::Ready) { @@ -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; } diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index b86ba27a12e70..d99de870914c6 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -89,11 +89,14 @@ class DartIsolate : public UIDartState { std::vector> 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& args, + fml::closure on_run = nullptr); FML_WARN_UNUSED_RESULT bool RunFromLibrary(const std::string& library_name, const std::string& entrypoint, + const std::vector& args, fml::closure on_run = nullptr); FML_WARN_UNUSED_RESULT diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index a3e03b59b0604..e752582cc99aa 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -157,7 +157,8 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref, std::unique_ptr& result, const Settings& settings, fml::RefPtr task_runner, - std::string entrypoint) { + std::string entrypoint, + const std::vector& args) { FML_CHECK(task_runner->RunsTasksOnCurrentThread()); if (!vm_ref) { @@ -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."; @@ -265,12 +266,14 @@ static std::unique_ptr RunDartCodeInIsolate( DartVMRef& vm_ref, const Settings& settings, fml::RefPtr task_runner, - std::string entrypoint) { + std::string entrypoint, + const std::vector& args) { std::unique_ptr 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(); @@ -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); } @@ -292,7 +295,7 @@ 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); } @@ -300,8 +303,8 @@ 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); @@ -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(); @@ -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); @@ -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::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); diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc index 7ac4f6413d788..a6de7f792f1cd 100644 --- a/runtime/dart_lifecycle_unittests.cc +++ b/runtime/dart_lifecycle_unittests.cc @@ -92,7 +92,7 @@ static std::shared_ptr 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; } diff --git a/runtime/fixtures/runtime_test.dart b/runtime/fixtures/runtime_test.dart index 6f67e01b6b2ff..5cd09d2c6b531 100644 --- a/runtime/fixtures/runtime_test.dart +++ b/runtime/fixtures/runtime_test.dart @@ -55,3 +55,8 @@ void testCanLaunchSecondaryIsolate() { Isolate.spawn(secondaryIsolateMain, "Hello from root isolate."); NotifyNative(); } + +@pragma('vm:entry-point') +void testCanRecieveArguments(List args) { + NotifyResult(args != null && args.length == 1 && args[0] == "arg1"); +} diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 3d049f1c031b1..c1043c3877550 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -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; }