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
This commit is contained in:
Chase Latta
2022-01-21 13:31:09 -08:00
committed by GitHub
parent 5465438e48
commit 215cf2b6c4
3 changed files with 64 additions and 19 deletions

View File

@@ -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<String> 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<String> args) {
if (userMainFunction is _ListStringArgFunction) {
(userMainFunction as dynamic)(args);
} else {
userMainFunction();
}
}

View File

@@ -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()) {

View File

@@ -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<String> 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();