From 215cf2b6c4fc79c4ecbb8ba859a76d31065da241 Mon Sep 17 00:00:00 2001 From: Chase Latta <638538+chaselatta@users.noreply.github.com> Date: Fri, 21 Jan 2022 13:31:09 -0800 Subject: [PATCH] Add user main trampoline for dart_runner. (flutter/engine#30980) The dart_runner was invoking main directly which was working fine in JIT mode but when we switch to aot snapshots invoking main would fail. This was due to user's not marking their main as a vm entrypoint. Rather than having user's mark this entrypoint we add a trampoline through the dart:fuchsia package which is marked as an entrypoint and avoids the main functions being tree shaken. BUG: fxbug.dev/64153 --- .../fuchsia/dart-pkg/fuchsia/lib/fuchsia.dart | 21 +++++++++++ .../dart_runner/dart_component_controller.cc | 27 +++++++++++--- .../dart_component_controller_v2.cc | 35 +++++++++++-------- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/engine/src/flutter/shell/platform/fuchsia/dart-pkg/fuchsia/lib/fuchsia.dart b/engine/src/flutter/shell/platform/fuchsia/dart-pkg/fuchsia/lib/fuchsia.dart index e2619c5c39..ff0ade3a36 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart-pkg/fuchsia/lib/fuchsia.dart +++ b/engine/src/flutter/shell/platform/fuchsia/dart-pkg/fuchsia/lib/fuchsia.dart @@ -65,3 +65,24 @@ void exit(int returnCode) { _setReturnCode(returnCode); Isolate.current.kill(priority: Isolate.immediate); } + +// ignore: always_declare_return_types, prefer_generic_function_type_aliases +typedef _ListStringArgFunction(List args); + +// This function is used as the entry point for code in the dart runner and is +// not meant to be called directly outside of that context. The code will invoke +// the given main entry point and pass the args if the function takes args. This +// function is needed because without it the snapshot compiler will tree shake +// the function away unless the user marks it as being an entry point. +// +// The code does not catch any exceptions since this is handled in the dart +// runner calling code. +@pragma('vm:entry-point') +void _runUserMainForDartRunner(Function userMainFunction, + List args) { + if (userMainFunction is _ListStringArgFunction) { + (userMainFunction as dynamic)(args); + } else { + userMainFunction(); + } +} diff --git a/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller.cc b/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller.cc index 7af29d793a..2f29dc4ea2 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller.cc +++ b/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller.cc @@ -34,6 +34,7 @@ #include "third_party/tonic/dart_microtask_queue.h" #include "third_party/tonic/dart_state.h" #include "third_party/tonic/logging/dart_error.h" +#include "third_party/tonic/logging/dart_invoke.h" #include "builtin_libraries.h" #include "logging.h" @@ -414,12 +415,28 @@ bool DartComponentController::Main() { Dart_ListSetAt(dart_arguments, i, ToDart(arguments.at(i)))); } - Dart_Handle argv[] = { - dart_arguments, - }; + Dart_Handle user_main = Dart_GetField(Dart_RootLibrary(), ToDart("main")); + + if (Dart_IsError(user_main)) { + FX_LOGF(ERROR, LOG_TAG, + "Failed to locate user_main in the root library: %s", + Dart_GetError(user_main)); + Dart_ExitScope(); + return false; + } + + Dart_Handle fuchsia_lib = Dart_LookupLibrary(tonic::ToDart("dart:fuchsia")); + + if (Dart_IsError(fuchsia_lib)) { + FX_LOGF(ERROR, LOG_TAG, "Failed to locate dart:fuchsia: %s", + Dart_GetError(fuchsia_lib)); + Dart_ExitScope(); + return false; + } + + Dart_Handle main_result = tonic::DartInvokeField( + fuchsia_lib, "_runUserMainForDartRunner", {user_main, dart_arguments}); - Dart_Handle main_result = Dart_Invoke(Dart_RootLibrary(), ToDart("main"), - dart_utils::ArraySize(argv), argv); if (Dart_IsError(main_result)) { auto dart_state = tonic::DartState::Current(); if (!dart_state->has_set_return_code()) { diff --git a/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller_v2.cc b/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller_v2.cc index 23ea928817..e7d1065b5c 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller_v2.cc +++ b/engine/src/flutter/shell/platform/fuchsia/dart_runner/dart_component_controller_v2.cc @@ -35,6 +35,7 @@ #include "third_party/tonic/dart_microtask_queue.h" #include "third_party/tonic/dart_state.h" #include "third_party/tonic/logging/dart_error.h" +#include "third_party/tonic/logging/dart_invoke.h" #include "builtin_libraries.h" #include "logging.h" @@ -402,13 +403,6 @@ bool DartComponentControllerV2::RunDartMain() { Dart_EnterScope(); // TODO(fxb/88383): Support argument passing. - // Note: Even though we do not support argument passing via the cml files - // at this time, we still need to create an argument list and pass it off - // to the invocation of main below. If we do not do this dart will look for - // a function with the signature `void main()` but existing dart components - // that run in the dart runner are written with main functions that have the - // signature `void main(List args)`. In order to ensure that these - // components do not break we need to have this stub argument list. Dart_Handle corelib = Dart_LookupLibrary(ToDart("dart:core")); Dart_Handle string_type = Dart_GetNonNullableType(corelib, ToDart("String"), 0, NULL); @@ -422,14 +416,27 @@ bool DartComponentControllerV2::RunDartMain() { return false; } - Dart_Handle argv[] = { - dart_arguments, - }; + Dart_Handle user_main = Dart_GetField(Dart_RootLibrary(), ToDart("main")); - Dart_Handle main_result = - Dart_Invoke(Dart_RootLibrary() /* target */, ToDart("main") /* name */, - dart_utils::ArraySize(argv) /* number_of_arguments */, - argv /* arguments */); + if (Dart_IsError(user_main)) { + FX_LOGF(ERROR, LOG_TAG, + "Failed to locate user_main in the root library: %s", + Dart_GetError(user_main)); + Dart_ExitScope(); + return false; + } + + Dart_Handle fuchsia_lib = Dart_LookupLibrary(tonic::ToDart("dart:fuchsia")); + + if (Dart_IsError(fuchsia_lib)) { + FX_LOGF(ERROR, LOG_TAG, "Failed to locate dart:fuchsia: %s", + Dart_GetError(fuchsia_lib)); + Dart_ExitScope(); + return false; + } + + Dart_Handle main_result = tonic::DartInvokeField( + fuchsia_lib, "_runUserMainForDartRunner", {user_main, dart_arguments}); if (Dart_IsError(main_result)) { auto dart_state = tonic::DartState::Current();