diff --git a/common/config.gni b/common/config.gni index f7b122a3f480e..3173a5e15b069 100644 --- a/common/config.gni +++ b/common/config.gni @@ -28,6 +28,7 @@ feature_defines_list = [ "FLUTTER_RUNTIME_MODE_PROFILE=2", "FLUTTER_RUNTIME_MODE_RELEASE=3", "FLUTTER_RUNTIME_MODE_JIT_RELEASE=4", + "DART_LEGACY_API=[[deprecated]]", ] if (flutter_runtime_mode == "debug") { diff --git a/common/settings.h b/common/settings.h index d85506b946e25..17408322eedb3 100644 --- a/common/settings.h +++ b/common/settings.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -50,12 +51,11 @@ using UnhandledExceptionCallback = std::function; -// TODO(chinmaygarde): Deprecate all the "path" struct members in favor of the +// TODO(26783): Deprecate all the "path" struct members in favor of the // callback that generates the mapping from these paths. -// https://github.com/flutter/flutter/issues/26783 using MappingCallback = std::function(void)>; -using MappingsCallback = - std::function>(void)>; +using Mappings = std::vector>; +using MappingsCallback = std::function; using FrameRasterizedCallback = std::function; diff --git a/fml/BUILD.gn b/fml/BUILD.gn index 358fbee5483ff..198d61c52c610 100644 --- a/fml/BUILD.gn +++ b/fml/BUILD.gn @@ -139,7 +139,7 @@ source_set("fml") { "platform/darwin/string_range_sanitization.mm", ] - libs += [ "Foundation.framework" ] + frameworks = [ "Foundation.framework" ] } if (is_android) { diff --git a/fml/dart/dart_converter.h b/fml/dart/dart_converter.h index 159ec44e25c31..ccdd2422abed6 100644 --- a/fml/dart/dart_converter.h +++ b/fml/dart/dart_converter.h @@ -23,7 +23,11 @@ struct DartConverter { return Dart_Null(); } - auto dart_list_handle = Dart_NewListOf(Dart_CoreType_Int, val->GetSize()); + auto dart_list_handle = Dart_NewListOfTypeFilled( + ToDartTypeHandle(), // type + CreateZeroInitializedDartObject(), // sentinel + val->GetSize() // size + ); if (Dart_IsError(dart_list_handle)) { FML_LOG(ERROR) << "Error while attempting to allocate a list: " diff --git a/lib/io/dart_io.cc b/lib/io/dart_io.cc index 21b5952b15233..cb255fbedd6e8 100644 --- a/lib/io/dart_io.cc +++ b/lib/io/dart_io.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/lib/io/dart_io.h" @@ -23,7 +24,7 @@ void DartIO::InitForIsolate(bool may_insecurely_connect_to_all_domains, FML_CHECK(!LogIfError(result)); Dart_Handle embedder_config_type = - Dart_GetType(io_lib, ToDart("_EmbedderConfig"), 0, nullptr); + Dart_GetNonNullableType(io_lib, ToDart("_EmbedderConfig"), 0, nullptr); FML_CHECK(!LogIfError(embedder_config_type)); Dart_Handle allow_insecure_connections_result = Dart_SetField( diff --git a/lib/ui/dart_runtime_hooks.cc b/lib/ui/dart_runtime_hooks.cc index 3512f9b446cb8..6cfa20a5333d3 100644 --- a/lib/ui/dart_runtime_hooks.cc +++ b/lib/ui/dart_runtime_hooks.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/lib/ui/dart_runtime_hooks.h" @@ -62,17 +63,19 @@ void DartRuntimeHooks::RegisterNatives(tonic::DartLibraryNatives* natives) { static void PropagateIfError(Dart_Handle result) { if (Dart_IsError(result)) { + FML_LOG(ERROR) << "Dart Error: " << ::Dart_GetError(result); Dart_PropagateError(result); } } -static Dart_Handle GetFunction(Dart_Handle builtin_library, const char* name) { +static Dart_Handle InvokeFunction(Dart_Handle builtin_library, + const char* name) { Dart_Handle getter_name = ToDart(name); return Dart_Invoke(builtin_library, getter_name, 0, nullptr); } static void InitDartInternal(Dart_Handle builtin_library, bool is_ui_isolate) { - Dart_Handle print = GetFunction(builtin_library, "_getPrintClosure"); + Dart_Handle print = InvokeFunction(builtin_library, "_getPrintClosure"); Dart_Handle internal_library = Dart_LookupLibrary(ToDart("dart:_internal")); @@ -112,7 +115,7 @@ static void InitDartAsync(Dart_Handle builtin_library, bool is_ui_isolate) { Dart_Handle schedule_microtask; if (is_ui_isolate) { schedule_microtask = - GetFunction(builtin_library, "_getScheduleMicrotaskClosure"); + InvokeFunction(builtin_library, "_getScheduleMicrotaskClosure"); } else { Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate")); Dart_Handle method_name = @@ -130,21 +133,24 @@ static void InitDartIO(Dart_Handle builtin_library, const std::string& script_uri) { Dart_Handle io_lib = Dart_LookupLibrary(ToDart("dart:io")); Dart_Handle platform_type = - Dart_GetType(io_lib, ToDart("_Platform"), 0, nullptr); + Dart_GetNonNullableType(io_lib, ToDart("_Platform"), 0, nullptr); if (!script_uri.empty()) { Dart_Handle result = Dart_SetField(platform_type, ToDart("_nativeScript"), ToDart(script_uri)); PropagateIfError(result); } - Dart_Handle locale_closure = - GetFunction(builtin_library, "_getLocaleClosure"); + // typedef _LocaleClosure = String Function(); + Dart_Handle /* _LocaleClosure? */ locale_closure = + InvokeFunction(builtin_library, "_getLocaleClosure"); + PropagateIfError(locale_closure); + // static String Function()? _localeClosure; Dart_Handle result = Dart_SetField(platform_type, ToDart("_localeClosure"), locale_closure); PropagateIfError(result); // Register dart:io service extensions used for network profiling. Dart_Handle network_profiling_type = - Dart_GetType(io_lib, ToDart("_NetworkProfiling"), 0, nullptr); + Dart_GetNonNullableType(io_lib, ToDart("_NetworkProfiling"), 0, nullptr); PropagateIfError(network_profiling_type); result = Dart_Invoke(network_profiling_type, ToDart("_registerServiceExtension"), 0, nullptr); diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart index a911d79f63a8d..f3e4d1ee5ec81 100644 --- a/lib/ui/hooks.dart +++ b/lib/ui/hooks.dart @@ -53,15 +53,15 @@ void _updateWindowMetrics( _invoke(window.onMetricsChanged, window._onMetricsChangedZone); } -typedef _LocaleClosure = String? Function(); - -String? _localeClosure() { +String _localeClosure() { if (window.locale == null) { - return null; + return ''; } return window.locale.toString(); } +typedef _LocaleClosure = String Function(); + @pragma('vm:entry-point') // ignore: unused_element _LocaleClosure? _getLocaleClosure() => _localeClosure; @@ -210,9 +210,7 @@ void _drawFrame() { } // ignore: always_declare_return_types, prefer_generic_function_type_aliases -typedef _UnaryFunction(Null args); -// ignore: always_declare_return_types, prefer_generic_function_type_aliases -typedef _BinaryFunction(Null args, Null message); +typedef _ListStringArgFunction(List args); @pragma('vm:entry-point') // ignore: unused_element @@ -221,11 +219,7 @@ void _runMainZoned(Function startMainIsolateFunction, List args) { startMainIsolateFunction((){ runZonedGuarded(() { - 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)(args, ''); - } else if (userMainFunction is _UnaryFunction) { + if (userMainFunction is _ListStringArgFunction) { (userMainFunction as dynamic)(args); } else { userMainFunction(); diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 31897c82d9b3b..f8beda3e94899 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/lib/ui/text/paragraph.h" @@ -132,20 +133,19 @@ tonic::Float32List Paragraph::getRectsForPlaceholders() { } Dart_Handle Paragraph::getPositionForOffset(double dx, double dy) { - Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2); txt::Paragraph::PositionWithAffinity pos = m_paragraph->GetGlyphPositionAtCoordinate(dx, dy); - Dart_ListSetAt(result, 0, ToDart(pos.position)); - Dart_ListSetAt(result, 1, ToDart(static_cast(pos.affinity))); - return result; + std::vector result = { + pos.position, // size_t already + static_cast(pos.affinity) // affinity (enum) + }; + return tonic::DartConverter::ToDart(result); } Dart_Handle Paragraph::getWordBoundary(unsigned offset) { txt::Paragraph::Range point = m_paragraph->GetWordBoundary(offset); - Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2); - Dart_ListSetAt(result, 0, ToDart(point.start)); - Dart_ListSetAt(result, 1, ToDart(point.end)); - return result; + std::vector result = {point.start, point.end}; + return tonic::DartConverter::ToDart(result); } Dart_Handle Paragraph::getLineBoundary(unsigned offset) { @@ -159,10 +159,8 @@ Dart_Handle Paragraph::getLineBoundary(unsigned offset) { break; } } - Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2); - Dart_ListSetAt(result, 0, ToDart(line_start)); - Dart_ListSetAt(result, 1, ToDart(line_end)); - return result; + std::vector result = {line_start, line_end}; + return tonic::DartConverter::ToDart(result); } tonic::Float64List Paragraph::computeLineMetrics() { diff --git a/lib/ui/window/platform_configuration.h b/lib/ui/window/platform_configuration.h index 4652c7c5dcdbb..01089dac9c202 100644 --- a/lib/ui/window/platform_configuration.h +++ b/lib/ui/window/platform_configuration.h @@ -19,20 +19,6 @@ #include "flutter/lib/ui/window/window.h" #include "third_party/tonic/dart_persistent_value.h" -namespace tonic { -class DartLibraryNatives; - -// So tonic::ToDart> returns List instead of -// List. -template <> -struct DartListFactory { - static Dart_Handle NewList(intptr_t length) { - return Dart_NewListOf(Dart_CoreType_Int, length); - } -}; - -} // namespace tonic - namespace flutter { class FontCollection; class PlatformMessage; diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index d584693fdcfe7..9788794f7da83 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -53,6 +53,8 @@ source_set("runtime") { "dart_vm_lifecycle.h", "embedder_resources.cc", "embedder_resources.h", + "isolate_configuration.cc", + "isolate_configuration.h", "platform_data.cc", "platform_data.h", "ptrace_check.h", @@ -112,6 +114,7 @@ if (enable_unittests) { "dart_lifecycle_unittests.cc", "dart_service_isolate_unittests.cc", "dart_vm_unittests.cc", + "type_conversions_unittests.cc", ] public_configs = [ "//flutter:export_dynamic_symbols" ] diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 919a9a532c17a..80583aab1fd6b 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/runtime/dart_isolate.h" @@ -17,6 +18,7 @@ #include "flutter/runtime/dart_service_isolate.h" #include "flutter/runtime/dart_vm.h" #include "flutter/runtime/dart_vm_lifecycle.h" +#include "flutter/runtime/isolate_configuration.h" #include "third_party/dart/runtime/include/dart_api.h" #include "third_party/dart/runtime/include/dart_tools_api.h" #include "third_party/tonic/converter/dart_converter.h" @@ -52,6 +54,126 @@ class DartErrorString { } // anonymous namespace +DartIsolate::Flags::Flags() : Flags(nullptr) {} + +DartIsolate::Flags::Flags(const Dart_IsolateFlags* flags) { + if (flags) { + flags_ = *flags; + } else { + ::Dart_IsolateFlagsInitialize(&flags_); + } +} + +DartIsolate::Flags::~Flags() = default; + +void DartIsolate::Flags::SetNullSafetyEnabled(bool enabled) { + flags_.null_safety = enabled; +} + +Dart_IsolateFlags DartIsolate::Flags::Get() const { + return flags_; +} + +std::weak_ptr DartIsolate::CreateRunningRootIsolate( + const Settings& settings, + fml::RefPtr isolate_snapshot, + TaskRunners task_runners, + std::unique_ptr platform_configuration, + fml::WeakPtr snapshot_delegate, + fml::WeakPtr hint_freed_delegate, + fml::WeakPtr io_manager, + fml::RefPtr skia_unref_queue, + fml::WeakPtr image_decoder, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + Flags isolate_flags, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback, + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configration) { + if (!isolate_snapshot) { + FML_LOG(ERROR) << "Invalid isolate snapshot."; + return {}; + } + + if (!isolate_configration) { + FML_LOG(ERROR) << "Invalid isolate configuration."; + return {}; + } + + isolate_flags.SetNullSafetyEnabled( + isolate_configration->IsNullSafetyEnabled(*isolate_snapshot)); + + auto isolate = CreateRootIsolate(settings, // + isolate_snapshot, // + task_runners, // + std::move(platform_configuration), // + snapshot_delegate, // + hint_freed_delegate, // + io_manager, // + skia_unref_queue, // + image_decoder, // + advisory_script_uri, // + advisory_script_entrypoint, // + isolate_flags, // + isolate_create_callback, // + isolate_shutdown_callback // + ) + .lock(); + + if (!isolate) { + FML_LOG(ERROR) << "Could not create root isolate."; + return {}; + } + + fml::ScopedCleanupClosure shutdown_on_error([isolate]() { + if (!isolate->Shutdown()) { + FML_DLOG(ERROR) << "Could not shutdown transient isolate."; + } + }); + + if (isolate->GetPhase() != DartIsolate::Phase::LibrariesSetup) { + FML_LOG(ERROR) << "Root isolate was created in an incorrect phase."; + return {}; + } + + if (!isolate_configration->PrepareIsolate(*isolate.get())) { + FML_LOG(ERROR) << "Could not prepare isolate."; + return {}; + } + + if (isolate->GetPhase() != DartIsolate::Phase::Ready) { + FML_LOG(ERROR) << "Root isolate not in the ready phase for Dart entrypoint " + "invocation."; + return {}; + } + + if (!isolate->RunFromLibrary(dart_entrypoint_library, // + dart_entrypoint, // + settings.dart_entrypoint_args, // + settings.root_isolate_create_callback // + )) { + FML_LOG(ERROR) << "Could not run the run main Dart entrypoint."; + return {}; + } + + if (settings.root_isolate_create_callback) { + // Isolate callbacks always occur in isolate scope. + tonic::DartState::Scope scope(isolate.get()); + settings.root_isolate_create_callback(); + } + + if (settings.root_isolate_shutdown_callback) { + isolate->AddIsolateShutdownCallback( + settings.root_isolate_shutdown_callback); + } + + shutdown_on_error.Release(); + + return isolate; +} + std::weak_ptr DartIsolate::CreateRootIsolate( const Settings& settings, fml::RefPtr isolate_snapshot, @@ -64,7 +186,7 @@ std::weak_ptr DartIsolate::CreateRootIsolate( fml::WeakPtr image_decoder, std::string advisory_script_uri, std::string advisory_script_entrypoint, - Dart_IsolateFlags* flags, + Flags flags, const fml::closure& isolate_create_callback, const fml::closure& isolate_shutdown_callback) { TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate"); @@ -98,9 +220,10 @@ std::weak_ptr DartIsolate::CreateRootIsolate( ))); DartErrorString error; - Dart_Isolate vm_isolate = - CreateDartIsolateGroup(std::move(isolate_group_data), - std::move(isolate_data), flags, error.error()); + auto isolate_flags = flags.Get(); + Dart_Isolate vm_isolate = CreateDartIsolateGroup( + std::move(isolate_group_data), std::move(isolate_data), &isolate_flags, + error.error()); if (error) { FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << error.str(); @@ -493,40 +616,10 @@ bool DartIsolate::MarkIsolateRunnable() { return true; } -/// @note Procedure doesn't copy all closures. -[[nodiscard]] bool DartIsolate::Run(const std::string& entrypoint_name, - const std::vector& args, - const fml::closure& on_run) { - TRACE_EVENT0("flutter", "DartIsolate::Run"); - if (phase_ != Phase::Ready) { - return false; - } - - tonic::DartState::Scope scope(this); - - auto user_entrypoint_function = - Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str())); - - auto entrypoint_args = tonic::ToDart(args); - - if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) { - return false; - } - - phase_ = Phase::Running; - - if (on_run) { - on_run(); - } - return true; -} - -/// @note Procedure doesn't copy all closures. -[[nodiscard]] bool DartIsolate::RunFromLibrary( - const std::string& library_name, - const std::string& entrypoint_name, - const std::vector& args, - const fml::closure& on_run) { +bool DartIsolate::RunFromLibrary(std::optional library_name, + std::optional entrypoint, + const std::vector& args, + const fml::closure& on_run) { TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary"); if (phase_ != Phase::Ready) { return false; @@ -534,9 +627,15 @@ bool DartIsolate::MarkIsolateRunnable() { tonic::DartState::Scope scope(this); + auto library_handle = + library_name.has_value() && !library_name.value().empty() + ? ::Dart_LookupLibrary(tonic::ToDart(library_name.value().c_str())) + : ::Dart_RootLibrary(); + auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty() + ? tonic::ToDart(entrypoint.value().c_str()) + : tonic::ToDart("main"); auto user_entrypoint_function = - Dart_GetField(Dart_LookupLibrary(tonic::ToDart(library_name.c_str())), - tonic::ToDart(entrypoint_name.c_str())); + ::Dart_GetField(library_handle, entrypoint_handle); auto entrypoint_args = tonic::ToDart(args); @@ -613,7 +712,7 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( {}, // Image Decoder DART_VM_SERVICE_ISOLATE_NAME, // script uri DART_VM_SERVICE_ISOLATE_NAME, // script entrypoint - flags, // flags + DartIsolate::Flags{flags}, // flags nullptr, // isolate create callback nullptr // isolate shutdown callback ); diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index d1f741518ec21..b7ef2be67e3fb 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -6,6 +6,7 @@ #define FLUTTER_RUNTIME_DART_ISOLATE_H_ #include +#include #include #include @@ -26,6 +27,7 @@ namespace flutter { class DartVM; class DartIsolateGroupData; +class IsolateConfiguration; //------------------------------------------------------------------------------ /// @brief Represents an instance of a live isolate. An isolate is a @@ -59,6 +61,22 @@ class DartIsolateGroupData; /// class DartIsolate : public UIDartState { public: + class Flags { + public: + Flags(); + + explicit Flags(const Dart_IsolateFlags* flags); + + ~Flags(); + + void SetNullSafetyEnabled(bool enabled); + + Dart_IsolateFlags Get() const; + + private: + Dart_IsolateFlags flags_; + }; + //---------------------------------------------------------------------------- /// @brief The engine represents all dart isolates as being in one of the /// known phases. By invoking various methods on the Dart isolate, @@ -174,14 +192,19 @@ class DartIsolate : public UIDartState { /// the root isolate. The isolate is /// already in the running state at /// this point and an isolate scope is - /// current. + /// current. This callback is made for + /// all isolate launches (including + /// the children of the root isolate). /// @param[in] isolate_shutdown_callback The isolate shutdown callback. /// This will be called before the /// isolate is about to transition /// into the Shutdown phase. The /// isolate is still running at this /// point and an isolate scope is - /// current. + /// current. This callback is made + /// for all isolate shutdowns + /// (including the children of the + /// root isolate). /// /// @return A weak pointer to the root Dart isolate. The caller must /// ensure that the isolate is not referenced for long periods of @@ -189,7 +212,7 @@ class DartIsolate : public UIDartState { /// terminates itself. The caller may also only use the isolate on /// the thread on which the isolate was created. /// - static std::weak_ptr CreateRootIsolate( + static std::weak_ptr CreateRunningRootIsolate( const Settings& settings, fml::RefPtr isolate_snapshot, TaskRunners task_runners, @@ -201,9 +224,12 @@ class DartIsolate : public UIDartState { fml::WeakPtr image_decoder, std::string advisory_script_uri, std::string advisory_script_entrypoint, - Dart_IsolateFlags* flags, + Flags flags, const fml::closure& isolate_create_callback, - const fml::closure& isolate_shutdown_callback); + const fml::closure& isolate_shutdown_callback, + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configration); // |UIDartState| ~DartIsolate() override; @@ -306,26 +332,6 @@ class DartIsolate : public UIDartState { [[nodiscard]] bool PrepareForRunningFromKernels( std::vector> kernels); - //---------------------------------------------------------------------------- - /// @brief Transition the root isolate to the `Phase::Running` phase and - /// invoke the main entrypoint (the "main" method) in the root - /// library. The isolate must already be in the `Phase::Ready` - /// phase. - /// - /// @param[in] entrypoint The entrypoint in the root library. - /// @param[in] args A list of string arguments to the entrypoint. - /// @param[in] on_run A callback to run in isolate scope after the main - /// entrypoint has been invoked. There is no isolate - /// scope current on the thread once this method - /// returns. - /// - /// @return If the isolate successfully transitioned to the running phase - /// and the main entrypoint was invoked. - /// - [[nodiscard]] bool Run(const std::string& entrypoint, - const std::vector& args, - const fml::closure& on_run = nullptr); - //---------------------------------------------------------------------------- /// @brief Transition the root isolate to the `Phase::Running` phase and /// invoke the main entrypoint (the "main" method) in the @@ -344,11 +350,12 @@ class DartIsolate : public UIDartState { /// @return If the isolate successfully transitioned to the running phase /// and the main entrypoint was invoked. /// - [[nodiscard]] bool RunFromLibrary(const std::string& library_name, - const std::string& entrypoint, + [[nodiscard]] bool RunFromLibrary(std::optional library_name, + std::optional entrypoint, const std::vector& args, const fml::closure& on_run = nullptr); + public: //---------------------------------------------------------------------------- /// @brief Transition the isolate to the `Phase::Shutdown` phase. The /// only thing left to do is to collect the isolate. @@ -384,6 +391,7 @@ class DartIsolate : public UIDartState { fml::RefPtr GetMessageHandlingTaskRunner() const; private: + friend class IsolateConfiguration; class AutoFireClosure { public: AutoFireClosure(const fml::closure& closure); @@ -403,6 +411,22 @@ class DartIsolate : public UIDartState { const bool may_insecurely_connect_to_all_domains_; std::string domain_network_policy_; + static std::weak_ptr CreateRootIsolate( + const Settings& settings, + fml::RefPtr isolate_snapshot, + TaskRunners task_runners, + std::unique_ptr platform_configuration, + fml::WeakPtr snapshot_delegate, + fml::WeakPtr hint_freed_delegate, + fml::WeakPtr io_manager, + fml::RefPtr skia_unref_queue, + fml::WeakPtr image_decoder, + std::string advisory_script_uri, + std::string advisory_script_entrypoint, + Flags flags, + const fml::closure& isolate_create_callback, + const fml::closure& isolate_shutdown_callback); + DartIsolate(const Settings& settings, TaskRunners task_runners, fml::WeakPtr snapshot_delegate, @@ -413,6 +437,7 @@ class DartIsolate : public UIDartState { std::string advisory_script_uri, std::string advisory_script_entrypoint, bool is_root_isolate); + [[nodiscard]] bool Initialize(Dart_Isolate isolate); void SetMessageHandlingTaskRunner(fml::RefPtr runner); diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index 8a1bcb2cf2469..ddbc402e563ef 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/runtime/dart_isolate.h" @@ -10,6 +11,7 @@ #include "flutter/fml/thread.h" #include "flutter/runtime/dart_vm.h" #include "flutter/runtime/dart_vm_lifecycle.h" +#include "flutter/runtime/isolate_configuration.h" #include "flutter/testing/dart_isolate_runner.h" #include "flutter/testing/fixture_test.h" #include "flutter/testing/testing.h" @@ -46,25 +48,32 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) { GetCurrentTaskRunner(), // GetCurrentTaskRunner() // ); - auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // hint freed delegate - {}, // io manager - {}, // unref queue - {}, // image decoder - "main.dart", // advisory uri - "main", // advisory entrypoint, - nullptr, // flags - settings.isolate_create_callback, // isolate create callback - settings.isolate_shutdown_callback // isolate shutdown callback + + auto isolate_configuration = + IsolateConfiguration::InferFromSettings(settings); + + auto weak_isolate = DartIsolate::CreateRunningRootIsolate( + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // hint freed delegate + {}, // io manager + {}, // unref queue + {}, // image decoder + "main.dart", // advisory uri + "main", // advisory entrypoint, + DartIsolate::Flags{}, // flags + settings.isolate_create_callback, // isolate create callback + settings.isolate_shutdown_callback, // isolate shutdown callback + "main", // dart entrypoint + std::nullopt, // dart entrypoint library + std::move(isolate_configuration) // isolate configuration ); auto root_isolate = weak_isolate.lock(); ASSERT_TRUE(root_isolate); - ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::LibrariesSetup); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running); ASSERT_TRUE(root_isolate->Shutdown()); } @@ -81,25 +90,30 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) { GetCurrentTaskRunner(), // GetCurrentTaskRunner() // ); - auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // hint freed delegate - {}, // io manager - {}, // unref queue - {}, // image decoder - "main.dart", // advisory uri - "main", // advisory entrypoint - nullptr, // flags - settings.isolate_create_callback, // isolate create callback - settings.isolate_shutdown_callback // isolate shutdown callback + auto isolate_configuration = + IsolateConfiguration::InferFromSettings(settings); + auto weak_isolate = DartIsolate::CreateRunningRootIsolate( + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // hint freed delegate + {}, // io manager + {}, // unref queue + {}, // image decoder + "main.dart", // advisory uri + "main", // advisory entrypoint + DartIsolate::Flags{}, // flags + settings.isolate_create_callback, // isolate create callback + settings.isolate_shutdown_callback, // isolate shutdown callback + "main", // dart entrypoint + std::nullopt, // dart entrypoint library + std::move(isolate_configuration) // isolate configuration ); auto root_isolate = weak_isolate.lock(); ASSERT_TRUE(root_isolate); - ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::LibrariesSetup); + ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running); size_t destruction_callback_count = 0; root_isolate->AddIsolateShutdownCallback([&destruction_callback_count]() { ASSERT_NE(Dart_CurrentIsolate(), nullptr); diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc index 3c45c702a80fe..e6fd7b1093351 100644 --- a/runtime/dart_lifecycle_unittests.cc +++ b/runtime/dart_lifecycle_unittests.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/common/task_runners.h" #include "flutter/fml/paths.h" @@ -8,6 +9,7 @@ #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/runtime/dart_vm.h" #include "flutter/runtime/dart_vm_lifecycle.h" +#include "flutter/runtime/isolate_configuration.h" #include "flutter/testing/fixture_test.h" namespace flutter { @@ -50,57 +52,34 @@ static std::shared_ptr CreateAndRunRootIsolate( FML_CHECK(entrypoint.size() > 0); TaskRunners runners("io.flutter.test", task_runner, task_runner, task_runner, task_runner); - auto isolate_weak = DartIsolate::CreateRootIsolate( - vm.GetSettings(), // settings - vm.GetIsolateSnapshot(), // isolate_snapshot - runners, // task_runners - {}, // window - {}, // snapshot_delegate - {}, // hint_freed_delegate - {}, // io_manager - {}, // unref_queue - {}, // image_decoder - "main.dart", // advisory_script_uri - entrypoint.c_str(), // advisory_script_entrypoint - nullptr, // flags - settings.isolate_create_callback, // isolate create callback - settings.isolate_shutdown_callback // isolate shutdown callback - ); - - auto isolate = isolate_weak.lock(); - if (!isolate) { - FML_LOG(ERROR) << "Could not create valid isolate."; - return nullptr; - } - - if (DartVM::IsRunningPrecompiledCode()) { - if (!isolate->PrepareForRunningFromPrecompiledCode()) { - FML_LOG(ERROR) - << "Could not prepare to run the isolate from precompiled code."; - return nullptr; - } - - } else { - if (!isolate->PrepareForRunningFromKernels( - settings.application_kernels())) { - FML_LOG(ERROR) << "Could not prepare isolate from application kernels."; - return nullptr; - } - } + auto isolate_configuration = + IsolateConfiguration::InferFromSettings(settings); + + auto isolate = + DartIsolate::CreateRunningRootIsolate( + vm.GetSettings(), // settings + vm.GetIsolateSnapshot(), // isolate_snapshot + runners, // task_runners + {}, // window + {}, // snapshot_delegate + {}, // hint_freed_delegate + {}, // io_manager + {}, // unref_queue + {}, // image_decoder + "main.dart", // advisory_script_uri + entrypoint.c_str(), // advisory_script_entrypoint + DartIsolate::Flags{}, // flags + settings.isolate_create_callback, // isolate create callback + settings.isolate_shutdown_callback, // isolate shutdown callback, + entrypoint, // dart entrypoint + std::nullopt, // dart entrypoint library + std::move(isolate_configuration) // isolate configuration + ) + .lock(); - if (isolate->GetPhase() != DartIsolate::Phase::Ready) { - FML_LOG(ERROR) << "Isolate was not ready."; - return nullptr; - } - - if (!isolate->Run(entrypoint, {}, settings.root_isolate_create_callback)) { - FML_LOG(ERROR) << "Could not run entrypoint: " << entrypoint << "."; - return nullptr; - } - - if (isolate->GetPhase() != DartIsolate::Phase::Running) { - FML_LOG(ERROR) << "Isolate was not Running."; + if (!isolate) { + FML_LOG(ERROR) << "Could not launch the root isolate."; return nullptr; } diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc index 050592d04a967..dd2d45c4d40f4 100644 --- a/runtime/dart_snapshot.cc +++ b/runtime/dart_snapshot.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/runtime/dart_snapshot.h" @@ -11,6 +12,7 @@ #include "flutter/fml/trace_event.h" #include "flutter/lib/snapshot/snapshot.h" #include "flutter/runtime/dart_vm.h" +#include "third_party/dart/runtime/include/dart_api.h" namespace flutter { @@ -202,4 +204,16 @@ const uint8_t* DartSnapshot::GetInstructionsMapping() const { return instructions_ ? instructions_->GetMapping() : nullptr; } +bool DartSnapshot::IsNullSafetyEnabled(const fml::Mapping* kernel) const { + return ::Dart_DetectNullSafety( + nullptr, // script_uri (unsupported by Flutter) + nullptr, // package_config (package resolution of parent used) + nullptr, // original_working_directory (no package config) + GetDataMapping(), // snapshot_data + GetInstructionsMapping(), // snapshot_instructions + kernel ? kernel->GetMapping() : nullptr, // kernel_buffer + kernel ? kernel->GetSize() : 0u // kernel_buffer_size + ); +} + } // namespace flutter diff --git a/runtime/dart_snapshot.h b/runtime/dart_snapshot.h index 97038aac4aee9..15ca157c7a273 100644 --- a/runtime/dart_snapshot.h +++ b/runtime/dart_snapshot.h @@ -139,6 +139,9 @@ class DartSnapshot : public fml::RefCountedThreadSafe { /// const uint8_t* GetInstructionsMapping() const; + bool IsNullSafetyEnabled( + const fml::Mapping* application_kernel_mapping) const; + private: std::shared_ptr data_; std::shared_ptr instructions_; diff --git a/runtime/fixtures/runtime_test.dart b/runtime/fixtures/runtime_test.dart index 821e01e8fa433..616e026a5ccce 100644 --- a/runtime/fixtures/runtime_test.dart +++ b/runtime/fixtures/runtime_test.dart @@ -32,13 +32,7 @@ void testIsolateShutdown() { } @pragma('vm:entry-point') void testCanSaveCompilationTrace() { - List trace; - try { - trace = saveCompilationTrace(); - } catch (exception) { - print('Could not save compilation trace: ' + exception); - } - notifyResult(trace != null && trace.isNotEmpty); + notifyResult(saveCompilationTrace().isNotEmpty); } void notifyResult(bool success) native 'NotifyNative'; @@ -58,5 +52,44 @@ void testCanLaunchSecondaryIsolate() { @pragma('vm:entry-point') void testCanRecieveArguments(List args) { - notifyResult(args != null && args.length == 1 && args[0] == 'arg1'); + notifyResult(args.length == 1 && args[0] == 'arg1'); +} + +@pragma('vm:entry-point') +void trampoline() { + notifyNative(); +} + +void notifySuccess(bool success) native 'NotifySuccess'; + +@pragma('vm:entry-point') +void testCanConvertEmptyList(List args){ + notifySuccess(args.length == 0); +} + +@pragma('vm:entry-point') +void testCanConvertListOfStrings(List args){ + notifySuccess(args.length == 4 && + args[0] == 'tinker' && + args[1] == 'tailor' && + args[2] == 'soldier' && + args[3] == 'sailor'); +} + +@pragma('vm:entry-point') +void testCanConvertListOfDoubles(List args){ + notifySuccess(args.length == 4 && + args[0] == 1.0 && + args[1] == 2.0 && + args[2] == 3.0 && + args[3] == 4.0); +} + +@pragma('vm:entry-point') +void testCanConvertListOfInts(List args){ + notifySuccess(args.length == 4 && + args[0] == 1 && + args[1] == 2 && + args[2] == 3 && + args[3] == 4); } diff --git a/shell/common/isolate_configuration.cc b/runtime/isolate_configuration.cc similarity index 70% rename from shell/common/isolate_configuration.cc rename to runtime/isolate_configuration.cc index 4d37c03464ff2..a7f4aa19da5c9 100644 --- a/shell/common/isolate_configuration.cc +++ b/runtime/isolate_configuration.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/common/isolate_configuration.h" +#include "flutter/runtime/isolate_configuration.h" #include "flutter/fml/make_copyable.h" #include "flutter/runtime/dart_vm.h" @@ -32,6 +32,11 @@ class AppSnapshotIsolateConfiguration final : public IsolateConfiguration { return isolate.PrepareForRunningFromPrecompiledCode(); } + // |IsolateConfiguration| + bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override { + return snapshot.IsNullSafetyEnabled(nullptr); + } + private: FML_DISALLOW_COPY_AND_ASSIGN(AppSnapshotIsolateConfiguration); }; @@ -49,6 +54,11 @@ class KernelIsolateConfiguration : public IsolateConfiguration { return isolate.PrepareForRunningFromKernel(std::move(kernel_)); } + // |IsolateConfiguration| + bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override { + return snapshot.IsNullSafetyEnabled(kernel_.get()); + } + private: std::unique_ptr kernel_; @@ -60,7 +70,12 @@ class KernelListIsolateConfiguration final : public IsolateConfiguration { KernelListIsolateConfiguration( std::vector>> kernel_pieces) - : kernel_pieces_(std::move(kernel_pieces)) {} + : kernel_piece_futures_(std::move(kernel_pieces)) { + if (kernel_piece_futures_.empty()) { + FML_LOG(ERROR) << "Attempted to create kernel list configuration without " + "any kernel blobs."; + } + } // |IsolateConfiguration| bool DoPrepareIsolate(DartIsolate& isolate) override { @@ -68,11 +83,22 @@ class KernelListIsolateConfiguration final : public IsolateConfiguration { return false; } - for (size_t i = 0; i < kernel_pieces_.size(); i++) { - bool last_piece = i + 1 == kernel_pieces_.size(); + ResolveKernelPiecesIfNecessary(); - if (!isolate.PrepareForRunningFromKernel(kernel_pieces_[i].get(), - last_piece)) { + if (resolved_kernel_pieces_.empty()) { + FML_DLOG(ERROR) << "No kernel pieces provided to prepare this isolate."; + return false; + } + + for (size_t i = 0; i < resolved_kernel_pieces_.size(); i++) { + if (!resolved_kernel_pieces_[i]) { + FML_DLOG(ERROR) << "This kernel list isolate configuration was already " + "used to prepare an isolate."; + return false; + } + const bool last_piece = i + 1 == resolved_kernel_pieces_.size(); + if (!isolate.PrepareForRunningFromKernel( + std::move(resolved_kernel_pieces_[i]), last_piece)) { return false; } } @@ -80,8 +106,36 @@ class KernelListIsolateConfiguration final : public IsolateConfiguration { return true; } + // |IsolateConfiguration| + bool IsNullSafetyEnabled(const DartSnapshot& snapshot) override { + ResolveKernelPiecesIfNecessary(); + const auto kernel = resolved_kernel_pieces_.empty() + ? nullptr + : resolved_kernel_pieces_.front().get(); + return snapshot.IsNullSafetyEnabled(kernel); + } + + // This must be call as late as possible before accessing any of the kernel + // pieces. This will delay blocking on the futures for as long as possible. So + // far, only Fuchsia depends on this optimization and only on the non-AOT + // configs. + void ResolveKernelPiecesIfNecessary() { + if (resolved_kernel_pieces_.size() == kernel_piece_futures_.size()) { + return; + } + + resolved_kernel_pieces_.clear(); + for (auto& piece : kernel_piece_futures_) { + // The get() call will xfer the unique pointer out and leave an empty + // future in the original vector. + resolved_kernel_pieces_.emplace_back(piece.get()); + } + } + private: - std::vector>> kernel_pieces_; + std::vector>> + kernel_piece_futures_; + std::vector> resolved_kernel_pieces_; FML_DISALLOW_COPY_AND_ASSIGN(KernelListIsolateConfiguration); }; @@ -150,10 +204,6 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( return CreateForAppSnapshot(); } - if (!asset_manager) { - return nullptr; - } - if (settings.application_kernels) { return CreateForKernelList(settings.application_kernels()); } @@ -165,7 +215,13 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( return nullptr; } - // Running from kernel snapshot. + if (!asset_manager) { + FML_DLOG(ERROR) << "No asset manager specified when attempting to create " + "isolate configuration."; + return nullptr; + } + + // Running from kernel snapshot. Requires asset manager. { std::unique_ptr kernel = asset_manager->GetAsMapping(settings.application_kernel_asset); @@ -174,7 +230,14 @@ std::unique_ptr IsolateConfiguration::InferFromSettings( } } - // Running from kernel divided into several pieces (for sharing). + // Running from kernel divided into several pieces (for sharing). Requires + // asset manager and io worker. + + if (!io_worker) { + FML_DLOG(ERROR) << "No IO worker specified to load kernel pieces."; + return nullptr; + } + { std::unique_ptr kernel_list = asset_manager->GetAsMapping(settings.application_kernel_list_asset); @@ -206,6 +269,10 @@ std::unique_ptr IsolateConfiguration::CreateForKernelList( std::vector> kernel_pieces) { std::vector>> pieces; for (auto& piece : kernel_pieces) { + if (!piece) { + FML_DLOG(ERROR) << "Invalid kernel piece."; + continue; + } std::promise> promise; pieces.push_back(promise.get_future()); promise.set_value(std::move(piece)); diff --git a/shell/common/isolate_configuration.h b/runtime/isolate_configuration.h similarity index 90% rename from shell/common/isolate_configuration.h rename to runtime/isolate_configuration.h index c5f286103a0d6..1fc3efef51323 100644 --- a/shell/common/isolate_configuration.h +++ b/runtime/isolate_configuration.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_COMMON_ISOLATE_CONFIGURATION_H_ -#define FLUTTER_SHELL_COMMON_ISOLATE_CONFIGURATION_H_ +#ifndef FLUTTER_SHELL_RUNTIME_ISOLATE_CONFIGURATION_H_ +#define FLUTTER_SHELL_RUNTIME_ISOLATE_CONFIGURATION_H_ #include #include @@ -50,7 +50,10 @@ class IsolateConfiguration { /// for which this run configuration is used is collected. /// /// @param[in] settings The settings - /// @param[in] asset_manager The asset manager + /// @param[in] asset_manager The optional asset manager. This is used when + /// using the legacy settings fields that specify + /// the asset by name instead of a mappings + /// callback. /// @param[in] io_worker An optional IO worker. Specify `nullptr` is a /// worker should not be used or one is not /// available. @@ -58,10 +61,10 @@ class IsolateConfiguration { /// @return An isolate configuration if one can be inferred from the /// settings. If not, returns `nullptr`. /// - static std::unique_ptr InferFromSettings( + [[nodiscard]] static std::unique_ptr InferFromSettings( const Settings& settings, - std::shared_ptr asset_manager, - fml::RefPtr io_worker); + std::shared_ptr asset_manager = nullptr, + fml::RefPtr io_worker = nullptr); //---------------------------------------------------------------------------- /// @brief Creates an AOT isolate configuration using snapshot symbols @@ -152,7 +155,9 @@ class IsolateConfiguration { /// returns true, the engine will not move the isolate to the /// `DartIsolate::Phase::Ready` phase for subsequent run. /// - bool PrepareIsolate(DartIsolate& isolate); + [[nodiscard]] bool PrepareIsolate(DartIsolate& isolate); + + virtual bool IsNullSafetyEnabled(const DartSnapshot& snapshot) = 0; protected: virtual bool DoPrepareIsolate(DartIsolate& isolate) = 0; @@ -163,4 +168,4 @@ class IsolateConfiguration { } // namespace flutter -#endif // FLUTTER_SHELL_COMMON_ISOLATE_CONFIGURATION_H_ +#endif // FLUTTER_SHELL_RUNTIME_ISOLATE_CONFIGURATION_H_ diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 7697d70e37c0f..b2a8f7a14389f 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/runtime/runtime_controller.h" @@ -11,6 +12,7 @@ #include "flutter/lib/ui/window/platform_configuration.h" #include "flutter/lib/ui/window/viewport_metrics.h" #include "flutter/lib/ui/window/window.h" +#include "flutter/runtime/isolate_configuration.h" #include "flutter/runtime/runtime_delegate.h" #include "third_party/tonic/dart_message_handler.h" @@ -18,10 +20,7 @@ namespace flutter { RuntimeController::RuntimeController(RuntimeDelegate& client, TaskRunners p_task_runners) - : client_(client), - vm_(nullptr), - task_runners_(p_task_runners), - weak_factory_(this) {} + : client_(client), vm_(nullptr), task_runners_(p_task_runners) {} RuntimeController::RuntimeController( RuntimeDelegate& p_client, @@ -55,82 +54,7 @@ RuntimeController::RuntimeController( platform_data_(std::move(p_platform_data)), isolate_create_callback_(p_isolate_create_callback), isolate_shutdown_callback_(p_isolate_shutdown_callback), - persistent_isolate_data_(std::move(p_persistent_isolate_data)), - weak_factory_(this) { - // Create the root isolate as soon as the runtime controller is initialized, - // but not using a synchronous way to avoid blocking the platform thread a - // long time as it is waiting while creating `Shell` on that platform thread. - // It will be run at a later point when the engine provides a run - // configuration and then runs the isolate. - create_and_config_root_isolate_ = - std::async(std::launch::deferred, [self = weak_factory_.GetWeakPtr()]() { - if (!self) { - return; - } - - auto strong_root_isolate = - DartIsolate::CreateRootIsolate( - self->vm_->GetVMData()->GetSettings(), // - self->isolate_snapshot_, // - self->task_runners_, // - std::make_unique(self.get()), // - self->snapshot_delegate_, // - self->hint_freed_delegate_, // - self->io_manager_, // - self->unref_queue_, // - self->image_decoder_, // - self->advisory_script_uri_, // - self->advisory_script_entrypoint_, // - nullptr, // - self->isolate_create_callback_, // - self->isolate_shutdown_callback_ // - ) - .lock(); - - FML_CHECK(strong_root_isolate) << "Could not create root isolate."; - - // The root isolate ivar is weak. - self->root_isolate_ = strong_root_isolate; - - strong_root_isolate->SetReturnCodeCallback([self](uint32_t code) { - if (!self) { - return; - } - - self->root_isolate_return_code_ = {true, code}; - }); - - if (auto* platform_configuration = - self->GetPlatformConfigurationIfAvailable()) { - tonic::DartState::Scope scope(strong_root_isolate); - platform_configuration->DidCreateIsolate(); - if (!self->FlushRuntimeStateToIsolate()) { - FML_DLOG(ERROR) << "Could not setup initial isolate state."; - } - } else { - FML_DCHECK(false) - << "RuntimeController created without window binding."; - } - - FML_DCHECK(Dart_CurrentIsolate() == nullptr); - - self->client_.OnRootIsolateCreated(); - return; - }); - - // We're still trying to create the root isolate as soon as possible here on - // the UI thread although it's deferred a little bit by - // std::async(std::launch::deferred, ...). So the callers of `GetRootIsolate` - // should get a quick return after this UI thread task. - task_runners_.GetUITaskRunner()->PostTask( - [self = weak_factory_.GetWeakPtr()]() { - if (!self) { - return; - } - - self->GetRootIsolate(); - }); -} + persistent_isolate_data_(std::move(p_persistent_isolate_data)) {} RuntimeController::~RuntimeController() { FML_DCHECK(Dart_CurrentIsolate() == nullptr); @@ -418,20 +342,82 @@ tonic::DartErrorHandleType RuntimeController::GetLastError() { return root_isolate ? root_isolate->GetLastError() : tonic::kNoError; } +bool RuntimeController::LaunchRootIsolate( + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configuration) { + if (root_isolate_.lock()) { + FML_LOG(ERROR) << "Root isolate was already running."; + return false; + } + + auto strong_root_isolate = + DartIsolate::CreateRunningRootIsolate( + vm_->GetVMData()->GetSettings(), // + isolate_snapshot_, // + task_runners_, // + std::make_unique(this), // + snapshot_delegate_, // + hint_freed_delegate_, // + io_manager_, // + unref_queue_, // + image_decoder_, // + advisory_script_uri_, // + advisory_script_entrypoint_, // + DartIsolate::Flags{}, // + isolate_create_callback_, // + isolate_shutdown_callback_, // + dart_entrypoint, // + dart_entrypoint_library, // + std::move(isolate_configuration) // + ) + .lock(); + + if (!strong_root_isolate) { + FML_LOG(ERROR) << "Could not create root isolate."; + return false; + } + + // The root isolate ivar is weak. + root_isolate_ = strong_root_isolate; + + // Capture by `this` here is safe because the callback is made by the dart + // state itself. The isolate (and its Dart state) is owned by this object and + // it will be collected before this object. + strong_root_isolate->SetReturnCodeCallback( + [this](uint32_t code) { root_isolate_return_code_ = code; }); + + if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { + tonic::DartState::Scope scope(strong_root_isolate); + platform_configuration->DidCreateIsolate(); + if (!FlushRuntimeStateToIsolate()) { + FML_DLOG(ERROR) << "Could not setup initial isolate state."; + } + } else { + FML_DCHECK(false) << "RuntimeController created without window binding."; + } + + FML_DCHECK(Dart_CurrentIsolate() == nullptr); + return true; +} + +std::optional RuntimeController::GetRootIsolateServiceID() const { + if (auto isolate = root_isolate_.lock()) { + return isolate->GetServiceId(); + } + return std::nullopt; +} + std::weak_ptr RuntimeController::GetRootIsolate() { std::shared_ptr root_isolate = root_isolate_.lock(); if (root_isolate) { return root_isolate_; } - // Root isolate is not yet created, get it and do some configuration. - FML_DCHECK(create_and_config_root_isolate_.valid()); - create_and_config_root_isolate_.get(); - return root_isolate_; } -std::pair RuntimeController::GetRootIsolateReturnCode() { +std::optional RuntimeController::GetRootIsolateReturnCode() { return root_isolate_return_code_; } diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index b3f1a41d3716f..9b5ef99da617c 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -96,7 +96,7 @@ class RuntimeController : public PlatformConfigurationClient { /// code in isolate scope when the VM /// is about to be notified that the /// engine is going to be idle. - /// @param[in] platform_data The window data (if exists). + /// @param[in] platform_data The window data (if exists). /// @param[in] isolate_create_callback The isolate create callback. This /// allows callers to run native code /// in isolate scope on the UI task @@ -133,10 +133,39 @@ class RuntimeController : public PlatformConfigurationClient { ~RuntimeController() override; //---------------------------------------------------------------------------- - /// @brief Clone the the runtime controller. This re-creates the root - /// isolate with the same snapshots and copies all window data to - /// the new instance. This is usually only used in the debug - /// runtime mode to support the cold-restart scenario. + /// @brief Launches the isolate using the window data associated with + /// this runtime controller. Before this call, the Dart isolate + /// has not been initialized. On successful return, the caller can + /// assume that the isolate is in the + /// `DartIsolate::Phase::Running` phase. + /// + /// This call will fail if a root isolate is already running. To + /// re-create an isolate with the window data associated with this + /// runtime controller, `Clone` this runtime controller and + /// Launch an isolate in that runtime controller instead. + /// + /// @param[in] dart_entrypoint The dart entrypoint. If + /// `std::nullopt` or empty, `main` will + /// be attempted. + /// @param[in] dart_entrypoint_library The dart entrypoint library. If + /// `std::nullopt` or empty, the core + /// library will be attempted. + /// @param[in] isolate_configuration The isolate configuration + /// + /// @return If the isolate could be launched and guided to the + /// `DartIsolate::Phase::Running` phase. + /// + [[nodiscard]] bool LaunchRootIsolate( + std::optional dart_entrypoint, + std::optional dart_entrypoint_library, + std::unique_ptr isolate_configuration); + + //---------------------------------------------------------------------------- + /// @brief Clone the the runtime controller. Launching an isolate with a + /// cloned runtime controller will use the same snapshots and + /// copies all window data to the new instance. This is usually + /// only used in the debug runtime mode to support the + /// cold-restart scenario. /// /// @return A clone of the existing runtime controller. /// @@ -428,29 +457,20 @@ class RuntimeController : public PlatformConfigurationClient { tonic::DartErrorHandleType GetLastError(); //---------------------------------------------------------------------------- - /// @brief Get a weak pointer to the root Dart isolate. This isolate may - /// only be locked on the UI task runner. Callers use this - /// accessor to transition to the root isolate to the running - /// phase. Note that it might take times if the isolate is not yet - /// created, which should be done in a subsequence task after - /// constructing `RuntimeController`, or it should get a quick - /// return otherwise. + /// @brief Get the service ID of the root isolate if the root isolate is + /// running. /// - /// @return The root isolate reference. + /// @return The root isolate service id. /// - std::weak_ptr GetRootIsolate(); + std::optional GetRootIsolateServiceID() const; //---------------------------------------------------------------------------- /// @brief Get the return code specified by the root isolate (if one is /// present). /// - /// @bug Change this method to return `std::optional` - /// instead. - /// - /// @return The root isolate return code. The first argument in the pair - /// indicates if one is specified by the root isolate. + /// @return The root isolate return code if the isolate has specified one. /// - std::pair GetRootIsolateReturnCode(); + std::optional GetRootIsolateReturnCode(); protected: /// Constructor for Mocks. @@ -489,11 +509,10 @@ class RuntimeController : public PlatformConfigurationClient { // `RuntimeController`, be careful to use it directly while it might have not // been created yet. Call `GetRootIsolate()` instead which guarantees that. std::weak_ptr root_isolate_; - std::pair root_isolate_return_code_ = {false, 0}; + std::optional root_isolate_return_code_; const fml::closure isolate_create_callback_; const fml::closure isolate_shutdown_callback_; std::shared_ptr persistent_isolate_data_; - fml::WeakPtrFactory weak_factory_; PlatformConfiguration* GetPlatformConfigurationIfAvailable(); @@ -531,6 +550,16 @@ class RuntimeController : public PlatformConfigurationClient { std::unique_ptr> ComputePlatformResolvedLocale( const std::vector& supported_locale_data) override; + //---------------------------------------------------------------------------- + /// @brief Get a weak pointer to the root Dart isolate. This isolate may + /// only be locked on the UI task runner. Callers use this + /// accessor to transition to the root isolate to the running + /// phase. + /// + /// @return The root isolate reference. + /// + std::weak_ptr GetRootIsolate(); + FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); }; diff --git a/runtime/type_conversions_unittests.cc b/runtime/type_conversions_unittests.cc new file mode 100644 index 0000000000000..fe02962a3aa56 --- /dev/null +++ b/runtime/type_conversions_unittests.cc @@ -0,0 +1,175 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// FLUTTER_NOLINT + +#include "flutter/runtime/dart_vm_lifecycle.h" +#include "flutter/testing/dart_isolate_runner.h" +#include "flutter/testing/fixture_test.h" +#include "flutter/testing/testing.h" +#include "flutter/third_party/tonic/converter/dart_converter.h" + +namespace flutter { +namespace testing { + +class TypeConversionsTest : public FixtureTest { + public: + TypeConversionsTest() + : settings_(CreateSettingsForFixture()), + vm_(DartVMRef::Create(settings_)) {} + + ~TypeConversionsTest() = default; + + [[nodiscard]] bool RunWithEntrypoint(const std::string& entrypoint) { + if (running_isolate_) { + return false; + } + auto thread = CreateNewThread(); + TaskRunners single_threaded_task_runner(GetCurrentTestName(), thread, + thread, thread, thread); + auto isolate = + RunDartCodeInIsolate(vm_, settings_, single_threaded_task_runner, + entrypoint, {}, GetFixturesPath()); + if (!isolate || isolate->get()->GetPhase() != DartIsolate::Phase::Running) { + return false; + } + + running_isolate_ = std::move(isolate); + return true; + } + + private: + Settings settings_; + DartVMRef vm_; + std::unique_ptr running_isolate_; + FML_DISALLOW_COPY_AND_ASSIGN(TypeConversionsTest); +}; + +TEST_F(TypeConversionsTest, TestFixture) { + ASSERT_TRUE(RunWithEntrypoint("main")); +} + +TEST_F(TypeConversionsTest, CanConvertEmptyList) { + fml::AutoResetWaitableEvent event; + AddNativeCallback( + "NotifySuccess", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + auto bool_handle = Dart_GetNativeArgument(args, 0); + ASSERT_FALSE(tonic::LogIfError(bool_handle)); + ASSERT_TRUE(tonic::DartConverter::FromDart(bool_handle)); + event.Signal(); + })); + AddNativeCallback( + "NotifyNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments) { + std::vector items; + auto items_handle = tonic::ToDart(items); + ASSERT_FALSE(tonic::LogIfError(items_handle)); + tonic::DartInvokeField(::Dart_RootLibrary(), "testCanConvertEmptyList", + {items_handle}); + })); + ASSERT_TRUE(RunWithEntrypoint("trampoline")); + event.Wait(); +} + +TEST_F(TypeConversionsTest, CanConvertListOfStrings) { + fml::AutoResetWaitableEvent event; + AddNativeCallback( + "NotifySuccess", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + auto bool_handle = Dart_GetNativeArgument(args, 0); + ASSERT_FALSE(tonic::LogIfError(bool_handle)); + ASSERT_TRUE(tonic::DartConverter::FromDart(bool_handle)); + event.Signal(); + })); + AddNativeCallback( + "NotifyNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments) { + std::vector items; + items.push_back("tinker"); + items.push_back("tailor"); + items.push_back("soldier"); + items.push_back("sailor"); + auto items_handle = tonic::ToDart(items); + ASSERT_FALSE(tonic::LogIfError(items_handle)); + tonic::DartInvokeField(::Dart_RootLibrary(), + "testCanConvertListOfStrings", {items_handle}); + })); + ASSERT_TRUE(RunWithEntrypoint("trampoline")); + event.Wait(); +} + +TEST_F(TypeConversionsTest, CanConvertListOfDoubles) { + fml::AutoResetWaitableEvent event; + AddNativeCallback( + "NotifySuccess", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + auto bool_handle = Dart_GetNativeArgument(args, 0); + ASSERT_FALSE(tonic::LogIfError(bool_handle)); + ASSERT_TRUE(tonic::DartConverter::FromDart(bool_handle)); + event.Signal(); + })); + AddNativeCallback( + "NotifyNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments) { + std::vector items; + items.push_back(1.0); + items.push_back(2.0); + items.push_back(3.0); + items.push_back(4.0); + auto items_handle = tonic::ToDart(items); + ASSERT_FALSE(tonic::LogIfError(items_handle)); + tonic::DartInvokeField(::Dart_RootLibrary(), + "testCanConvertListOfDoubles", {items_handle}); + })); + ASSERT_TRUE(RunWithEntrypoint("trampoline")); + event.Wait(); +} + +TEST_F(TypeConversionsTest, CanConvertListOfInts) { + fml::AutoResetWaitableEvent event; + AddNativeCallback( + "NotifySuccess", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + auto bool_handle = Dart_GetNativeArgument(args, 0); + ASSERT_FALSE(tonic::LogIfError(bool_handle)); + ASSERT_TRUE(tonic::DartConverter::FromDart(bool_handle)); + event.Signal(); + })); + AddNativeCallback( + "NotifyNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments) { + std::vector items; + items.push_back(1); + items.push_back(2); + items.push_back(3); + items.push_back(4); + auto items_handle = tonic::ToDart(items); + ASSERT_FALSE(tonic::LogIfError(items_handle)); + tonic::DartInvokeField(::Dart_RootLibrary(), "testCanConvertListOfInts", + {items_handle}); + })); + ASSERT_TRUE(RunWithEntrypoint("trampoline")); + event.Wait(); +} + +TEST_F(TypeConversionsTest, CanConvertListOfFloatsToListOfDartDoubles) { + fml::AutoResetWaitableEvent event; + AddNativeCallback( + "NotifySuccess", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + auto bool_handle = Dart_GetNativeArgument(args, 0); + ASSERT_FALSE(tonic::LogIfError(bool_handle)); + ASSERT_TRUE(tonic::DartConverter::FromDart(bool_handle)); + event.Signal(); + })); + AddNativeCallback( + "NotifyNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments) { + std::vector items; + items.push_back(1.0f); + items.push_back(2.0f); + items.push_back(3.0f); + items.push_back(4.0f); + auto items_handle = tonic::ToDart(items); + ASSERT_FALSE(tonic::LogIfError(items_handle)); + // This will fail on type mismatch. + tonic::DartInvokeField(::Dart_RootLibrary(), + "testCanConvertListOfDoubles", {items_handle}); + })); + ASSERT_TRUE(RunWithEntrypoint("trampoline")); + event.Wait(); +} + +} // namespace testing +} // namespace flutter diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index eff5742eebee8..c988e88c2a1a6 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -69,8 +69,6 @@ source_set("common") { "display_manager.h", "engine.cc", "engine.h", - "isolate_configuration.cc", - "isolate_configuration.h", "persistent_cache.cc", "persistent_cache.h", "pipeline.cc", diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 310ebc4ce925b..31901318a8243 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/shell/common/engine.h" @@ -153,90 +154,32 @@ Engine::RunStatus Engine::Run(RunConfiguration configuration) { last_entry_point_ = configuration.GetEntrypoint(); last_entry_point_library_ = configuration.GetEntrypointLibrary(); - auto isolate_launch_status = - PrepareAndLaunchIsolate(std::move(configuration)); - if (isolate_launch_status == Engine::RunStatus::Failure) { - FML_LOG(ERROR) << "Engine not prepare and launch isolate."; - return isolate_launch_status; - } else if (isolate_launch_status == - Engine::RunStatus::FailureAlreadyRunning) { - return isolate_launch_status; - } - - std::shared_ptr isolate = - runtime_controller_->GetRootIsolate().lock(); - - bool isolate_running = - isolate && isolate->GetPhase() == DartIsolate::Phase::Running; - - if (isolate_running) { - tonic::DartState::Scope scope(isolate.get()); - - if (settings_.root_isolate_create_callback) { - settings_.root_isolate_create_callback(); - } - - if (settings_.root_isolate_shutdown_callback) { - isolate->AddIsolateShutdownCallback( - settings_.root_isolate_shutdown_callback); - } - - std::string service_id = isolate->GetServiceId(); - fml::RefPtr service_id_message = - fml::MakeRefCounted( - kIsolateChannel, - std::vector(service_id.begin(), service_id.end()), - nullptr); - HandlePlatformMessage(service_id_message); - } - - return isolate_running ? Engine::RunStatus::Success - : Engine::RunStatus::Failure; -} - -Engine::RunStatus Engine::PrepareAndLaunchIsolate( - RunConfiguration configuration) { - TRACE_EVENT0("flutter", "Engine::PrepareAndLaunchIsolate"); - UpdateAssetManager(configuration.GetAssetManager()); - auto isolate_configuration = configuration.TakeIsolateConfiguration(); - - std::shared_ptr isolate = - runtime_controller_->GetRootIsolate().lock(); - - if (!isolate) { - return RunStatus::Failure; - } - - // This can happen on iOS after a plugin shows a native window and returns to - // the Flutter ViewController. - if (isolate->GetPhase() == DartIsolate::Phase::Running) { - FML_DLOG(WARNING) << "Isolate was already running!"; + if (runtime_controller_->IsRootIsolateRunning()) { return RunStatus::FailureAlreadyRunning; } - if (!isolate_configuration->PrepareIsolate(*isolate)) { - FML_LOG(ERROR) << "Could not prepare to run the isolate."; + if (!runtime_controller_->LaunchRootIsolate( + configuration.GetEntrypoint(), // + configuration.GetEntrypointLibrary(), // + configuration.TakeIsolateConfiguration()) // + ) { return RunStatus::Failure; } - if (configuration.GetEntrypointLibrary().empty()) { - 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(), - settings_.dart_entrypoint_args)) { - FML_LOG(ERROR) << "Could not run the isolate."; - return RunStatus::Failure; - } + auto service_id = runtime_controller_->GetRootIsolateServiceID(); + if (service_id.has_value()) { + fml::RefPtr service_id_message = + fml::MakeRefCounted( + kIsolateChannel, + std::vector(service_id.value().begin(), + service_id.value().end()), + nullptr); + HandlePlatformMessage(service_id_message); } - return RunStatus::Success; + return Engine::RunStatus::Success; } void Engine::BeginFrame(fml::TimePoint frame_time) { @@ -261,7 +204,7 @@ void Engine::NotifyIdle(int64_t deadline) { hint_freed_bytes_since_last_idle_ = 0; } -std::pair Engine::GetUIIsolateReturnCode() { +std::optional Engine::GetUIIsolateReturnCode() { return runtime_controller_->GetRootIsolateReturnCode(); } diff --git a/shell/common/engine.h b/shell/common/engine.h index c0e53c3d742a4..3319e9c9e28c5 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -608,14 +608,9 @@ class Engine final : public RuntimeDelegate, /// /// @see `UIIsolateHasLivePorts` /// - // TODO(chinmaygarde): Use std::optional instead of the pair now that it is - // available. + /// @return The return code (if specified) by the isolate. /// - /// @return A pair containing a boolean value indicating if the isolate - /// set a "return value" and that value if present. When the first - /// item of the pair is false, second item is meaningless. - /// - std::pair GetUIIsolateReturnCode(); + std::optional GetUIIsolateReturnCode(); //---------------------------------------------------------------------------- /// @brief Indicates to the Flutter application that it has obtained a @@ -837,8 +832,6 @@ class Engine final : public RuntimeDelegate, bool GetAssetAsBuffer(const std::string& name, std::vector* data); - RunStatus PrepareAndLaunchIsolate(RunConfiguration configuration); - friend class testing::ShellTest; FML_DISALLOW_COPY_AND_ASSIGN(Engine); diff --git a/shell/common/fixtures/shell_test.dart b/shell/common/fixtures/shell_test.dart index 492ddb8960d03..15d9386df12e7 100644 --- a/shell/common/fixtures/shell_test.dart +++ b/shell/common/fixtures/shell_test.dart @@ -87,7 +87,7 @@ void testCanLaunchSecondaryIsolate() { @pragma('vm:entry-point') void testSkiaResourceCacheSendsResponse() { - final PlatformMessageResponseCallback callback = (ByteData data) { + final PlatformMessageResponseCallback callback = (ByteData? data) { if (data == null) { throw 'Response must not be null.'; } @@ -130,7 +130,7 @@ void canCreateImageFromDecompressedData() { @pragma('vm:entry-point') void canAccessIsolateLaunchData() { - notifyMessage(utf8.decode(window.getPersistentIsolateData().buffer.asUint8List())); + notifyMessage(utf8.decode(window.getPersistentIsolateData()!.buffer.asUint8List())); } void notifyMessage(String string) native 'NotifyMessage'; @@ -174,7 +174,7 @@ void canAccessResourceFromAssetDir() async { window.sendPlatformMessage( 'flutter/assets', Uint8List.fromList(utf8.encode('kernel_blob.bin')).buffer.asByteData(), - (ByteData byteData) { + (ByteData? byteData) { notifyCanAccessResource(byteData != null); }, ); diff --git a/shell/common/run_configuration.h b/shell/common/run_configuration.h index 45dfed1c2d232..cb5a5b531d248 100644 --- a/shell/common/run_configuration.h +++ b/shell/common/run_configuration.h @@ -14,7 +14,7 @@ #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "flutter/fml/unique_fd.h" -#include "flutter/shell/common/isolate_configuration.h" +#include "flutter/runtime/isolate_configuration.h" namespace flutter { diff --git a/shell/platform/embedder/fixtures/main.dart b/shell/platform/embedder/fixtures/main.dart index 5dae4e494745c..1df95c1c8727c 100644 --- a/shell/platform/embedder/fixtures/main.dart +++ b/shell/platform/embedder/fixtures/main.dart @@ -79,12 +79,12 @@ class SemanticsActionData { const SemanticsActionData(this.id, this.action, this.args); final int id; final SemanticsAction action; - final ByteData args; + final ByteData? args; } Future get semanticsAction { final Completer actionReceived = Completer(); - window.onSemanticsAction = (int id, SemanticsAction action, ByteData args) { + window.onSemanticsAction = (int id, SemanticsAction action, ByteData? args) { actionReceived.complete(SemanticsActionData(id, action, args)); }; return actionReceived.future; @@ -115,12 +115,52 @@ void a11y_main() async { // ignore: non_constant_identifier_names transform: kTestTransform, childrenInTraversalOrder: Int32List.fromList([84, 96]), childrenInHitTestOrder: Int32List.fromList([96, 84]), + actions: 0, + flags: 0, + maxValueLength: 0, + currentValueLength: 0, + textSelectionBase: 0, + textSelectionExtent: 0, + platformViewId: 0, + scrollChildren: 0, + scrollIndex: 0, + scrollPosition: 0.0, + scrollExtentMax: 0.0, + scrollExtentMin: 0.0, + elevation: 0.0, + thickness: 0.0, + hint: "", + value: "", + increasedValue: "", + decreasedValue: "", + additionalActions: Int32List(0), ) ..updateNode( id: 84, label: 'B: leaf', rect: Rect.fromLTRB(40.0, 40.0, 80.0, 80.0), transform: kTestTransform, + actions: 0, + flags: 0, + maxValueLength: 0, + currentValueLength: 0, + textSelectionBase: 0, + textSelectionExtent: 0, + platformViewId: 0, + scrollChildren: 0, + scrollIndex: 0, + scrollPosition: 0.0, + scrollExtentMax: 0.0, + scrollExtentMin: 0.0, + elevation: 0.0, + thickness: 0.0, + hint: "", + value: "", + increasedValue: "", + decreasedValue: "", + additionalActions: Int32List(0), + childrenInHitTestOrder: Int32List(0), + childrenInTraversalOrder: Int32List(0), ) ..updateNode( id: 96, @@ -129,6 +169,25 @@ void a11y_main() async { // ignore: non_constant_identifier_names transform: kTestTransform, childrenInTraversalOrder: Int32List.fromList([128]), childrenInHitTestOrder: Int32List.fromList([128]), + actions: 0, + flags: 0, + maxValueLength: 0, + currentValueLength: 0, + textSelectionBase: 0, + textSelectionExtent: 0, + platformViewId: 0, + scrollChildren: 0, + scrollIndex: 0, + scrollPosition: 0.0, + scrollExtentMax: 0.0, + scrollExtentMin: 0.0, + elevation: 0.0, + thickness: 0.0, + hint: "", + value: "", + increasedValue: "", + decreasedValue: "", + additionalActions: Int32List(0), ) ..updateNode( id: 128, @@ -137,6 +196,25 @@ void a11y_main() async { // ignore: non_constant_identifier_names transform: kTestTransform, additionalActions: Int32List.fromList([21]), platformViewId: 0x3f3, + actions: 0, + flags: 0, + maxValueLength: 0, + currentValueLength: 0, + textSelectionBase: 0, + textSelectionExtent: 0, + scrollChildren: 0, + scrollIndex: 0, + scrollPosition: 0.0, + scrollExtentMax: 0.0, + scrollExtentMin: 0.0, + elevation: 0.0, + thickness: 0.0, + hint: "", + value: "", + increasedValue: "", + decreasedValue: "", + childrenInHitTestOrder: Int32List(0), + childrenInTraversalOrder: Int32List(0), ) ..updateCustomAction( id: 21, @@ -148,7 +226,7 @@ void a11y_main() async { // ignore: non_constant_identifier_names // Await semantics action from embedder. final SemanticsActionData data = await semanticsAction; - final List actionArgs = [data.args.getInt8(0), data.args.getInt8(1)]; + final List actionArgs = [data.args!.getInt8(0), data.args!.getInt8(1)]; notifySemanticsAction(data.id, data.action.index, actionArgs); // Await semantics disabled from embedder. @@ -159,20 +237,20 @@ void a11y_main() async { // ignore: non_constant_identifier_names @pragma('vm:entry-point') void platform_messages_response() { - window.onPlatformMessage = (String name, ByteData data, PlatformMessageResponseCallback callback) { - callback(data); + window.onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) { + callback!(data); }; signalNativeTest(); } @pragma('vm:entry-point') void platform_messages_no_response() { - window.onPlatformMessage = (String name, ByteData data, PlatformMessageResponseCallback callback) { - var list = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + window.onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) { + var list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); signalNativeMessage(utf8.decode(list)); // This does nothing because no one is listening on the other side. But complete the loop anyway // to make sure all null checking on response handles in the engine is in place. - callback(data); + callback!(data); }; signalNativeTest(); } @@ -180,10 +258,10 @@ void platform_messages_no_response() { @pragma('vm:entry-point') void null_platform_messages() { window.onPlatformMessage = - (String name, ByteData data, PlatformMessageResponseCallback callback) { + (String name, ByteData? data, PlatformMessageResponseCallback? callback) { // This checks if the platform_message null data is converted to Flutter null. signalNativeMessage((null == data).toString()); - callback(data); + callback!(data); }; signalNativeTest(); } @@ -507,7 +585,7 @@ void can_display_platform_view_with_pixel_ratio() { @pragma('vm:entry-point') void can_receive_locale_updates() { window.onLocaleChanged = (){ - signalNativeCount(window.locales.length); + signalNativeCount(window.locales!.length); }; signalNativeTest(); } diff --git a/shell/platform/fuchsia/flutter/component.cc b/shell/platform/fuchsia/flutter/component.cc index d60dff5c8d111..04cd15bfc6cb0 100644 --- a/shell/platform/fuchsia/flutter/component.cc +++ b/shell/platform/fuchsia/flutter/component.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "component.h" @@ -606,8 +607,8 @@ void Application::OnEngineTerminate(const Engine* shell_holder) { // terminate when the last shell goes away. The error code return to the // application controller will be the last isolate that had an error. auto return_code = shell_holder->GetEngineReturnCode(); - if (return_code.first) { - last_return_code_ = return_code; + if (return_code.has_value()) { + last_return_code_ = {true, return_code.value()}; } shell_holders_.erase(found); diff --git a/shell/platform/fuchsia/flutter/engine.cc b/shell/platform/fuchsia/flutter/engine.cc index c0f52142c934a..0ef28c3566965 100644 --- a/shell/platform/fuchsia/flutter/engine.cc +++ b/shell/platform/fuchsia/flutter/engine.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "engine.h" @@ -406,11 +407,11 @@ Engine::~Engine() { } } -std::pair Engine::GetEngineReturnCode() const { - std::pair code(false, 0); +std::optional Engine::GetEngineReturnCode() const { if (!shell_) { - return code; + return std::nullopt; } + std::optional code; fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask( shell_->GetTaskRunners().GetUITaskRunner(), diff --git a/shell/platform/fuchsia/flutter/engine.h b/shell/platform/fuchsia/flutter/engine.h index 29868c731c45b..a1335c59c78e5 100644 --- a/shell/platform/fuchsia/flutter/engine.h +++ b/shell/platform/fuchsia/flutter/engine.h @@ -5,6 +5,8 @@ #ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_ENGINE_H_ #define FLUTTER_SHELL_PLATFORM_FUCHSIA_ENGINE_H_ +#include + #include #include #include @@ -56,7 +58,7 @@ class Engine final { // Returns the Dart return code for the root isolate if one is present. This // call is thread safe and synchronous. This call must be made infrequently. - std::pair GetEngineReturnCode() const; + std::optional GetEngineReturnCode() const; #if !defined(DART_PRODUCT) void WriteProfileToTrace() const; diff --git a/testing/dart_isolate_runner.cc b/testing/dart_isolate_runner.cc index 1515f2e5afb15..8ba08719bc77e 100644 --- a/testing/dart_isolate_runner.cc +++ b/testing/dart_isolate_runner.cc @@ -1,9 +1,12 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/testing/dart_isolate_runner.h" +#include "flutter/runtime/isolate_configuration.h" + namespace flutter { namespace testing { AutoIsolateShutdown::AutoIsolateShutdown(std::shared_ptr isolate, @@ -47,55 +50,29 @@ AutoIsolateShutdown::~AutoIsolateShutdown() { return true; } -void RunDartCodeInIsolate(DartVMRef& vm_ref, - std::unique_ptr& result, - const Settings& settings, - const TaskRunners& task_runners, - std::string entrypoint, - const std::vector& args, - const std::string& fixtures_path, - fml::WeakPtr io_manager) { +std::unique_ptr RunDartCodeInIsolateOnUITaskRunner( + DartVMRef& vm_ref, + const Settings& p_settings, + const TaskRunners& task_runners, + std::string entrypoint, + const std::vector& args, + const std::string& fixtures_path, + fml::WeakPtr io_manager) { FML_CHECK(task_runners.GetUITaskRunner()->RunsTasksOnCurrentThread()); if (!vm_ref) { - return; + return nullptr; } auto vm_data = vm_ref.GetVMData(); if (!vm_data) { - return; + return nullptr; } - auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // hint freed delegate - io_manager, // io manager - {}, // unref queue - {}, // image decoder - "main.dart", // advisory uri - "main", // advisory entrypoint - nullptr, // flags - settings.isolate_create_callback, // isolate create callback - settings.isolate_shutdown_callback // isolate shutdown callback - ); - - auto root_isolate = std::make_unique( - weak_isolate.lock(), task_runners.GetUITaskRunner()); - - if (!root_isolate->IsValid()) { - FML_LOG(ERROR) << "Could not create isolate."; - return; - } + auto settings = p_settings; - if (root_isolate->get()->GetPhase() != DartIsolate::Phase::LibrariesSetup) { - FML_LOG(ERROR) << "Created isolate is in unexpected phase."; - return; - } + settings.dart_entrypoint_args = args; if (!DartVM::IsRunningPrecompiledCode()) { auto kernel_file_path = @@ -103,7 +80,7 @@ void RunDartCodeInIsolate(DartVMRef& vm_ref, if (!fml::IsFile(kernel_file_path)) { FML_LOG(ERROR) << "Could not locate kernel file."; - return; + return nullptr; } auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false, @@ -111,46 +88,56 @@ void RunDartCodeInIsolate(DartVMRef& vm_ref, if (!kernel_file.is_valid()) { FML_LOG(ERROR) << "Kernel file descriptor was invalid."; - return; + return nullptr; } auto kernel_mapping = std::make_unique(kernel_file); if (kernel_mapping->GetMapping() == nullptr) { FML_LOG(ERROR) << "Could not setup kernel mapping."; - return; - } - - if (!root_isolate->get()->PrepareForRunningFromKernel( - std::move(kernel_mapping))) { - FML_LOG(ERROR) - << "Could not prepare to run the isolate from the kernel file."; - return; + return nullptr; } - } else { - if (!root_isolate->get()->PrepareForRunningFromPrecompiledCode()) { - FML_LOG(ERROR) - << "Could not prepare to run the isolate from precompiled code."; - return; - } - } - if (root_isolate->get()->GetPhase() != DartIsolate::Phase::Ready) { - FML_LOG(ERROR) << "Isolate is in unexpected phase."; - return; + settings.application_kernels = fml::MakeCopyable( + [kernel_mapping = std::move(kernel_mapping)]() mutable -> Mappings { + Mappings mappings; + mappings.emplace_back(std::move(kernel_mapping)); + return mappings; + }); } - if (!root_isolate->get()->Run(entrypoint, args, - settings.root_isolate_create_callback)) { - FML_LOG(ERROR) << "Could not run the method \"" << entrypoint - << "\" in the isolate."; - return; + auto isolate_configuration = + IsolateConfiguration::InferFromSettings(settings); + + auto isolate = + DartIsolate::CreateRunningRootIsolate( + settings, // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // hint freed delegate + io_manager, // io manager + {}, // unref queue + {}, // image decoder + "main.dart", // advisory uri + entrypoint.c_str(), // advisory entrypoint + DartIsolate::Flags{}, // flags + settings.isolate_create_callback, // isolate create callback + settings.isolate_shutdown_callback, // isolate shutdown callback + entrypoint, // entrypoint + std::nullopt, // library + std::move(isolate_configuration) // isolate configuration + ) + .lock(); + + if (!isolate) { + FML_LOG(ERROR) << "Could not create running isolate."; + return nullptr; } - root_isolate->get()->AddIsolateShutdownCallback( - settings.root_isolate_shutdown_callback); - - result = std::move(root_isolate); + return std::make_unique(isolate, + task_runners.GetUITaskRunner()); } std::unique_ptr RunDartCodeInIsolate( @@ -165,8 +152,9 @@ std::unique_ptr RunDartCodeInIsolate( fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask( task_runners.GetUITaskRunner(), fml::MakeCopyable([&]() mutable { - RunDartCodeInIsolate(vm_ref, result, settings, task_runners, entrypoint, - args, fixtures_path, io_manager); + result = RunDartCodeInIsolateOnUITaskRunner( + vm_ref, settings, task_runners, entrypoint, args, fixtures_path, + io_manager); latch.Signal(); })); latch.Wait(); diff --git a/testing/fixture_test.cc b/testing/fixture_test.cc index 06cb2227fdfeb..d001a8b35ab16 100644 --- a/testing/fixture_test.cc +++ b/testing/fixture_test.cc @@ -1,6 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// FLUTTER_NOLINT #include "flutter/testing/fixture_test.h" @@ -40,10 +41,16 @@ void FixtureTest::SetSnapshotsAndAssets(Settings& settings) { if (DartVM::IsRunningPrecompiledCode()) { FML_CHECK(PrepareSettingsForAOTWithSymbols(settings, aot_symbols_)); } else { - settings.application_kernels = [this]() { + settings.application_kernels = [this]() -> Mappings { std::vector> kernel_mappings; - kernel_mappings.emplace_back( - fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin")); + auto kernel_mapping = + fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin"); + if (!kernel_mapping || !kernel_mapping->IsValid()) { + FML_LOG(ERROR) << "Could not find kernel blob for test fixture not " + "running in precompiled mode."; + return kernel_mappings; + } + kernel_mappings.emplace_back(std::move(kernel_mapping)); return kernel_mappings; }; } diff --git a/testing/testing.gni b/testing/testing.gni index 488310a05032a..2e0bf8bf78963 100644 --- a/testing/testing.gni +++ b/testing/testing.gni @@ -80,6 +80,7 @@ template("dart_snapshot_kernel") { rebase_path("$root_out_dir/flutter_patched_sdk"), "--target", "flutter", + "--enable-experiment=non-nullable", "--output-dill", rebase_path(invoker.dart_kernel, root_out_dir), "--depfile", diff --git a/third_party/tonic/BUILD.gn b/third_party/tonic/BUILD.gn index eb0136d54bd59..f5bedda8dab0d 100644 --- a/third_party/tonic/BUILD.gn +++ b/third_party/tonic/BUILD.gn @@ -11,6 +11,12 @@ config("config") { source_set("tonic") { sources = [ + "common/build_config.h", + "common/log.cc", + "common/log.h", + "common/macros.h", + "converter/dart_converter.cc", + "converter/dart_converter.h", "dart_args.h", "dart_binding_macros.h", "dart_class_library.cc", @@ -32,17 +38,53 @@ source_set("tonic") { "dart_wrappable.cc", "dart_wrappable.h", "dart_wrapper_info.h", - ] + "file_loader/file_loader.cc", + "file_loader/file_loader.h", + "logging/dart_error.cc", + "logging/dart_error.h", + "logging/dart_invoke.cc", + "logging/dart_invoke.h", + "scopes/dart_api_scope.h", + "scopes/dart_isolate_scope.cc", + "scopes/dart_isolate_scope.h", + "typed_data/dart_byte_data.cc", + "typed_data/dart_byte_data.h", - public_deps = [ - "common", - "converter", - "file_loader", - "logging", - "scopes", - "typed_data", - "//third_party/dart/runtime:dart_api", + # Deprecated. + "filesystem/filesystem/eintr_wrapper.h", + "filesystem/filesystem/file.cc", + "filesystem/filesystem/file.h", + "filesystem/filesystem/path.h", + "filesystem/filesystem/portable_unistd.h", + "parsers/packages_map.cc", + "parsers/packages_map.h", + "typed_data/float32_list.h", + "typed_data/float64_list.h", + "typed_data/int32_list.h", + "typed_data/typed_list.cc", + "typed_data/typed_list.h", + "typed_data/uint16_list.h", + "typed_data/uint8_list.h", ] + if (is_win) { + sources += [ + "file_loader/file_loader_win.cc", + "filesystem/filesystem/path_win.cc", + ] + } else if (is_fuchsia) { + sources += [ + "file_loader/file_loader_fuchsia.cc", + "filesystem/filesystem/path_posix.cc", + ] + } else { + sources += [ + "file_loader/file_loader_posix.cc", + "filesystem/filesystem/path_posix.cc", + ] + } + + public_deps = [ "//third_party/dart/runtime:dart_api" ] + public_configs = [ ":config" ] } diff --git a/third_party/tonic/common/BUILD.gn b/third_party/tonic/common/BUILD.gn deleted file mode 100644 index 2af823348c554..0000000000000 --- a/third_party/tonic/common/BUILD.gn +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("common") { - visibility = [ "../*" ] - - public_configs = [ "../:config" ] - - sources = [ - "build_config.h", - "log.cc", - "log.h", - "macros.h", - ] -} diff --git a/third_party/tonic/converter/BUILD.gn b/third_party/tonic/converter/BUILD.gn deleted file mode 100644 index 1cde8c17e5ff4..0000000000000 --- a/third_party/tonic/converter/BUILD.gn +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("converter") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - sources = [ - "dart_converter.cc", - "dart_converter.h", - ] - - deps = [ "../common" ] - - public_deps = [ "//third_party/dart/runtime:dart_api" ] -} diff --git a/third_party/tonic/converter/dart_converter.h b/third_party/tonic/converter/dart_converter.h index 6693615a2d98d..2ba75a9c96aa9 100644 --- a/third_party/tonic/converter/dart_converter.h +++ b/third_party/tonic/converter/dart_converter.h @@ -6,10 +6,12 @@ #define LIB_CONVERTER_TONIC_DART_CONVERTER_H_ #include +#include #include #include "third_party/dart/runtime/include/dart_api.h" #include "tonic/common/macros.h" +#include "tonic/logging/dart_error.h" namespace tonic { @@ -279,15 +281,80 @@ struct DartConverter { //////////////////////////////////////////////////////////////////////////////// // Collections +inline Dart_Handle LookupNonNullableType(const std::string& library_name, + const std::string& type_name) { + auto library = + Dart_LookupLibrary(DartConverter::ToDart(library_name)); + if (LogIfError(library)) { + return library; + } + auto type_string = DartConverter::ToDart(type_name); + if (LogIfError(type_string)) { + return type_string; + } + auto type = Dart_GetNonNullableType(library, type_string, 0, nullptr); + if (LogIfError(type)) { + return type; + } + return type; +} + +template ::value, int> = 0> +Dart_Handle ToDartTypeHandle() { + return LookupNonNullableType("dart:core", "String"); +} + +template ::value, int> = 0> +Dart_Handle ToDartTypeHandle() { + return LookupNonNullableType("dart:core", "int"); +} + +template ::value, int> = 0> +Dart_Handle ToDartTypeHandle() { + return LookupNonNullableType("dart:core", "double"); +} + +template +Dart_Handle CreateZeroInitializedDartObject( + Dart_Handle type_handle_or_null = ::Dart_Null()) { + if constexpr (std::is_same::value) { + return ::Dart_EmptyString(); + } else if constexpr (std::is_integral::value) { + return ::Dart_NewIntegerFromUint64(0u); + } else if constexpr (std::is_floating_point::value) { + return ::Dart_NewDouble(0.0); + } else { + auto object = ::Dart_New(type_handle_or_null, ::Dart_Null(), 0, nullptr); + LogIfError(object); + return object; + } + return ::Dart_Null(); +} + template struct DartListFactory { - static Dart_Handle NewList(intptr_t length) { return Dart_NewList(length); } -}; - -template <> -struct DartListFactory { - static Dart_Handle NewList(intptr_t length) { - return Dart_NewListOf(Dart_CoreType_String, length); + static Dart_Handle NewList(Dart_Handle type_handle, intptr_t length) { + bool is_nullable = false; + auto is_nullable_handle = ::Dart_IsNullableType(type_handle, &is_nullable); + if (LogIfError(is_nullable_handle)) { + return is_nullable_handle; + } + if (is_nullable) { + auto list = ::Dart_NewListOfType(type_handle, length); + LogIfError(list); + return list; + } else { + auto sentinel = CreateZeroInitializedDartObject(type_handle); + if (LogIfError(sentinel)) { + return sentinel; + } + auto list = ::Dart_NewListOfTypeFilled(type_handle, sentinel, length); + LogIfError(list); + return list; + } + return ::Dart_Null(); } }; @@ -297,7 +364,8 @@ struct DartConverter> { using ConverterType = typename DartConverterTypes::ConverterType; static Dart_Handle ToDart(const std::vector& val) { - Dart_Handle list = DartListFactory::NewList(val.size()); + Dart_Handle list = DartListFactory::NewList( + ToDartTypeHandle(), val.size()); if (Dart_IsError(list)) return list; for (size_t i = 0; i < val.size(); i++) { diff --git a/third_party/tonic/dart_class_provider.cc b/third_party/tonic/dart_class_provider.cc index 2d9ca00642fbd..590b0b959a224 100644 --- a/third_party/tonic/dart_class_provider.cc +++ b/third_party/tonic/dart_class_provider.cc @@ -20,7 +20,7 @@ DartClassProvider::~DartClassProvider() {} Dart_Handle DartClassProvider::GetClassByName(const char* class_name) { Dart_Handle name_handle = ToDart(class_name); Dart_Handle class_handle = - Dart_GetType(library_.value(), name_handle, 0, nullptr); + Dart_GetNonNullableType(library_.value(), name_handle, 0, nullptr); TONIC_DCHECK(!Dart_IsError(class_handle)); return class_handle; } diff --git a/third_party/tonic/file_loader/BUILD.gn b/third_party/tonic/file_loader/BUILD.gn deleted file mode 100644 index e350a447c438f..0000000000000 --- a/third_party/tonic/file_loader/BUILD.gn +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("file_loader") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - sources = [ - "file_loader.cc", - "file_loader.h", - ] - - if (is_win) { - sources += [ "file_loader_win.cc" ] - } else if (is_fuchsia) { - sources += [ "file_loader_fuchsia.cc" ] - } else { - sources += [ "file_loader_posix.cc" ] - } - - deps = [ - "../common", - "../converter", - "../filesystem", - "../parsers", - "//third_party/dart/runtime:dart_api", - ] -} diff --git a/third_party/tonic/file_loader/file_loader.cc b/third_party/tonic/file_loader/file_loader.cc index 32019b2de42cd..4a9e1791794ac 100644 --- a/third_party/tonic/file_loader/file_loader.cc +++ b/third_party/tonic/file_loader/file_loader.cc @@ -8,11 +8,11 @@ #include #include -#include "filesystem/file.h" -#include "filesystem/path.h" -#include "filesystem/portable_unistd.h" #include "tonic/common/macros.h" #include "tonic/converter/dart_converter.h" +#include "tonic/filesystem/filesystem/file.h" +#include "tonic/filesystem/filesystem/path.h" +#include "tonic/filesystem/filesystem/portable_unistd.h" #include "tonic/parsers/packages_map.h" namespace tonic { diff --git a/third_party/tonic/file_loader/file_loader_fuchsia.cc b/third_party/tonic/file_loader/file_loader_fuchsia.cc index 794a298b49124..359f88df39930 100644 --- a/third_party/tonic/file_loader/file_loader_fuchsia.cc +++ b/third_party/tonic/file_loader/file_loader_fuchsia.cc @@ -13,10 +13,10 @@ #include #include -#include "filesystem/file.h" -#include "filesystem/path.h" #include "tonic/common/macros.h" #include "tonic/converter/dart_converter.h" +#include "tonic/filesystem/filesystem/file.h" +#include "tonic/filesystem/filesystem/path.h" #include "tonic/parsers/packages_map.h" namespace tonic { diff --git a/third_party/tonic/file_loader/file_loader_posix.cc b/third_party/tonic/file_loader/file_loader_posix.cc index 13f3bd3caebd3..f5167f6e7f5ca 100644 --- a/third_party/tonic/file_loader/file_loader_posix.cc +++ b/third_party/tonic/file_loader/file_loader_posix.cc @@ -8,10 +8,10 @@ #include #include -#include "filesystem/file.h" -#include "filesystem/path.h" #include "tonic/common/macros.h" #include "tonic/converter/dart_converter.h" +#include "tonic/filesystem/filesystem/file.h" +#include "tonic/filesystem/filesystem/path.h" #include "tonic/parsers/packages_map.h" namespace tonic { diff --git a/third_party/tonic/file_loader/file_loader_win.cc b/third_party/tonic/file_loader/file_loader_win.cc index e79e86f1a0439..f312a0ac1dce5 100644 --- a/third_party/tonic/file_loader/file_loader_win.cc +++ b/third_party/tonic/file_loader/file_loader_win.cc @@ -8,9 +8,9 @@ #include #include -#include "filesystem/file.h" -#include "filesystem/path.h" #include "tonic/common/macros.h" +#include "tonic/filesystem/filesystem/file.h" +#include "tonic/filesystem/filesystem/path.h" #include "tonic/parsers/packages_map.h" namespace tonic { diff --git a/third_party/tonic/filesystem/filesystem/BUILD.gn b/third_party/tonic/filesystem/filesystem/BUILD.gn deleted file mode 100644 index 197a35e907ab4..0000000000000 --- a/third_party/tonic/filesystem/filesystem/BUILD.gn +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -config("filesystem_config") { - visibility = [ ":*" ] - - # We want callers to refer to headers in this folders using the "files" - # prefix. - include_dirs = [ ".." ] -} - -source_set("filesystem") { - visibility = [ "../*" ] - - configs += [ "../../:config" ] - - sources = [ - "eintr_wrapper.h", - "file.cc", - "file.h", - "path.h", - "portable_unistd.h", - ] - - if (is_win) { - sources += [ "path_win.cc" ] - } else { - sources += [ "path_posix.cc" ] - } - - deps = [ "../../common" ] - - public_configs = [ ":filesystem_config" ] -} diff --git a/third_party/tonic/filesystem/filesystem/file.cc b/third_party/tonic/filesystem/filesystem/file.cc index 0bc6eed02b0e8..c8436c89054a3 100644 --- a/third_party/tonic/filesystem/filesystem/file.cc +++ b/third_party/tonic/filesystem/filesystem/file.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "filesystem/file.h" +#include "tonic/filesystem/filesystem/file.h" #include #include @@ -23,8 +23,8 @@ typedef SSIZE_T ssize_t; #endif -#include "filesystem/eintr_wrapper.h" -#include "filesystem/portable_unistd.h" +#include "tonic/filesystem/filesystem/eintr_wrapper.h" +#include "tonic/filesystem/filesystem/portable_unistd.h" namespace filesystem { namespace { diff --git a/third_party/tonic/filesystem/filesystem/file.h b/third_party/tonic/filesystem/filesystem/file.h index ee206850df50c..fc6e3bc166ed7 100644 --- a/third_party/tonic/filesystem/filesystem/file.h +++ b/third_party/tonic/filesystem/filesystem/file.h @@ -8,8 +8,8 @@ #include #include -#include "filesystem/eintr_wrapper.h" -#include "filesystem/portable_unistd.h" +#include "tonic/filesystem/filesystem/eintr_wrapper.h" +#include "tonic/filesystem/filesystem/portable_unistd.h" namespace filesystem { diff --git a/third_party/tonic/filesystem/filesystem/path_posix.cc b/third_party/tonic/filesystem/filesystem/path_posix.cc index ac4b6ac69b3f6..bdce0852bf87c 100644 --- a/third_party/tonic/filesystem/filesystem/path_posix.cc +++ b/third_party/tonic/filesystem/filesystem/path_posix.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "filesystem/path.h" +#include "tonic/filesystem/filesystem/path.h" #include #include @@ -17,8 +17,8 @@ #include #include -#include "filesystem/portable_unistd.h" #include "tonic/common/build_config.h" +#include "tonic/filesystem/filesystem/portable_unistd.h" namespace filesystem { namespace { diff --git a/third_party/tonic/filesystem/filesystem/path_win.cc b/third_party/tonic/filesystem/filesystem/path_win.cc index 04a5e681025d6..9b74f07a3d0bc 100644 --- a/third_party/tonic/filesystem/filesystem/path_win.cc +++ b/third_party/tonic/filesystem/filesystem/path_win.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "filesystem/path.h" +#include "tonic/filesystem/filesystem/path.h" #include diff --git a/third_party/tonic/logging/BUILD.gn b/third_party/tonic/logging/BUILD.gn deleted file mode 100644 index cee90880f6070..0000000000000 --- a/third_party/tonic/logging/BUILD.gn +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("logging") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - sources = [ - "dart_error.cc", - "dart_error.h", - "dart_invoke.cc", - "dart_invoke.h", - ] - - deps = [ - "../common", - "../converter", - ] - - public_deps = [ "//third_party/dart/runtime:dart_api" ] -} diff --git a/third_party/tonic/parsers/BUILD.gn b/third_party/tonic/parsers/BUILD.gn deleted file mode 100644 index b03ae32a1363b..0000000000000 --- a/third_party/tonic/parsers/BUILD.gn +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("parsers") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - deps = [ "../common" ] - - sources = [ - "packages_map.cc", - "packages_map.h", - ] -} diff --git a/third_party/tonic/scopes/BUILD.gn b/third_party/tonic/scopes/BUILD.gn deleted file mode 100644 index af2a3a9fc6f5c..0000000000000 --- a/third_party/tonic/scopes/BUILD.gn +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("scopes") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - sources = [ - "dart_api_scope.h", - "dart_isolate_scope.cc", - "dart_isolate_scope.h", - ] - - deps = [ "../common" ] - - public_deps = [ "//third_party/dart/runtime:dart_api" ] -} diff --git a/third_party/tonic/typed_data/BUILD.gn b/third_party/tonic/typed_data/BUILD.gn deleted file mode 100644 index cdc58d43afa62..0000000000000 --- a/third_party/tonic/typed_data/BUILD.gn +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("typed_data") { - visibility = [ "../*" ] - - configs += [ "../:config" ] - - sources = [ - "dart_byte_data.cc", - "dart_byte_data.h", - "typed_list.cc", - "typed_list.h", - - # Deprecated. - "float32_list.h", - "float64_list.h", - "int32_list.h", - "uint16_list.h", - "uint8_list.h", - ] - - deps = [ "../common" ] - - public_deps = [ - "../converter", - "../logging", - "//third_party/dart/runtime:dart_api", - ] -} diff --git a/tools/font-subset/BUILD.gn b/tools/font-subset/BUILD.gn index 54c5f75e3a101..42341c09f7614 100644 --- a/tools/font-subset/BUILD.gn +++ b/tools/font-subset/BUILD.gn @@ -12,7 +12,7 @@ executable("font-subset") { libs = [] if (is_mac) { - libs += [ + frameworks = [ "Foundation.framework", "CoreGraphics.framework", "CoreText.framework",