diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index a323d42e1aee1f3be08d116e7f7eda41fc8a41e3..047d6c80645a698bf94042a306c910d4e0676b84 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -392,7 +392,7 @@ FILE: ../../../flutter/runtime/dart_vm_lifecycle.h FILE: ../../../flutter/runtime/dart_vm_unittests.cc FILE: ../../../flutter/runtime/embedder_resources.cc FILE: ../../../flutter/runtime/embedder_resources.h -FILE: ../../../flutter/runtime/fixtures/simple_main.dart +FILE: ../../../flutter/runtime/fixtures/runtime_test.dart FILE: ../../../flutter/runtime/runtime_controller.cc FILE: ../../../flutter/runtime/runtime_controller.h FILE: ../../../flutter/runtime/runtime_delegate.cc @@ -409,7 +409,7 @@ FILE: ../../../flutter/shell/common/animator.cc FILE: ../../../flutter/shell/common/animator.h FILE: ../../../flutter/shell/common/engine.cc FILE: ../../../flutter/shell/common/engine.h -FILE: ../../../flutter/shell/common/fixtures/main.dart +FILE: ../../../flutter/shell/common/fixtures/shell_test.dart FILE: ../../../flutter/shell/common/isolate_configuration.cc FILE: ../../../flutter/shell/common/isolate_configuration.h FILE: ../../../flutter/shell/common/persistent_cache.cc diff --git a/common/settings.h b/common/settings.h index c7ee514fbdb7f2a83b2e4387e2c6d66677814d94..68b7529033df9420762dfc7c4bc7cd8e3a82c095 100644 --- a/common/settings.h +++ b/common/settings.h @@ -113,9 +113,11 @@ struct Settings { // The main isolate is current when this callback is made. This is a good spot // to perform native Dart bindings for libraries not built in. fml::closure root_isolate_create_callback; + fml::closure isolate_create_callback; // The isolate is not current and may have already been destroyed when this // call is made. fml::closure root_isolate_shutdown_callback; + fml::closure isolate_shutdown_callback; // The callback made on the UI thread in an isolate scope when the engine // detects that the framework is idle. The VM also uses this time to perform // tasks suitable when idling. Due to this, embedders are still advised to be diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index bcfd7e399d532c6b8436754750413c2e359a8d7f..96de6356e23e82a59f824707912c1c75ec851851 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -96,7 +96,7 @@ source_set("runtime") { } test_fixtures("runtime_fixtures") { - fixtures = [ "fixtures/simple_main.dart" ] + fixtures = [ "fixtures/runtime_test.dart" ] } source_set("runtime_unittests_common") { diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc index 8de6bca542c1279fb7b4e62e65fef7a177753dae..5d751ec73a57787d6ea6255db21ef7315a51e7e6 100644 --- a/runtime/dart_isolate.cc +++ b/runtime/dart_isolate.cc @@ -39,7 +39,9 @@ std::weak_ptr DartIsolate::CreateRootIsolate( fml::WeakPtr io_manager, std::string advisory_script_uri, std::string advisory_script_entrypoint, - Dart_IsolateFlags* flags) { + Dart_IsolateFlags* flags, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback) { TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate"); Dart_Isolate vm_isolate = nullptr; std::weak_ptr embedder_isolate; @@ -49,6 +51,9 @@ std::weak_ptr DartIsolate::CreateRootIsolate( // Since this is the root isolate, we fake a parent embedder data object. We // cannot use unique_ptr here because the destructor is private (since the // isolate lifecycle is entirely managed by the VM). + // + // The child isolate preparer is null but will be set when the isolate is + // being prepared to run. auto root_embedder_data = std::make_unique>( std::make_shared( settings, // settings @@ -59,8 +64,9 @@ std::weak_ptr DartIsolate::CreateRootIsolate( std::move(io_manager), // IO manager advisory_script_uri, // advisory URI advisory_script_entrypoint, // advisory entrypoint - nullptr // child isolate preparer will be set when this isolate is - // prepared to run + nullptr, // child isolate preparer + isolate_create_callback, // isolate create callback + isolate_shutdown_callback // isolate shutdown callback )); std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair( @@ -102,7 +108,9 @@ DartIsolate::DartIsolate(const Settings& settings, fml::WeakPtr io_manager, std::string advisory_script_uri, std::string advisory_script_entrypoint, - ChildIsolatePreparer child_isolate_preparer) + ChildIsolatePreparer child_isolate_preparer, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback) : UIDartState(std::move(task_runners), settings.task_observer_add, settings.task_observer_remove, @@ -116,7 +124,9 @@ DartIsolate::DartIsolate(const Settings& settings, settings_(settings), isolate_snapshot_(std::move(isolate_snapshot)), shared_snapshot_(std::move(shared_snapshot)), - child_isolate_preparer_(std::move(child_isolate_preparer)) { + child_isolate_preparer_(std::move(child_isolate_preparer)), + isolate_create_callback_(isolate_create_callback), + isolate_shutdown_callback_(isolate_shutdown_callback) { FML_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot."; phase_ = Phase::Uninitialized; } @@ -279,6 +289,11 @@ bool DartIsolate::PrepareForRunningFromPrecompiledCode() { child_isolate_preparer_ = [](DartIsolate* isolate) { return isolate->PrepareForRunningFromPrecompiledCode(); }; + + if (isolate_create_callback_) { + isolate_create_callback_(); + } + phase_ = Phase::Ready; return true; } @@ -365,7 +380,13 @@ bool DartIsolate::PrepareForRunningFromKernel( return true; }; } + + if (isolate_create_callback_) { + isolate_create_callback_(); + } + phase_ = Phase::Ready; + return true; } @@ -563,7 +584,9 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate( {}, // IO Manager DART_VM_SERVICE_ISOLATE_NAME, // script uri DART_VM_SERVICE_ISOLATE_NAME, // script entrypoint - flags // flags + flags, // flags + nullptr, // isolate create callback + nullptr // isolate shutdown callback ); std::shared_ptr service_isolate = weak_service_isolate.lock(); @@ -662,6 +685,7 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair( TaskRunners null_task_runners(advisory_script_uri, nullptr, nullptr, nullptr, nullptr); + // Copy most fields from the parent to the child. embedder_isolate = std::make_unique>( std::make_shared( (*raw_embedder_isolate)->GetSettings(), // settings @@ -672,7 +696,12 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair( fml::WeakPtr{}, // io_manager advisory_script_uri, // advisory_script_uri advisory_script_entrypoint, // advisory_script_entrypoint - (*raw_embedder_isolate)->child_isolate_preparer_)); + (*raw_embedder_isolate)->child_isolate_preparer_, // preparer + (*raw_embedder_isolate)->isolate_create_callback_, // on create + (*raw_embedder_isolate)->isolate_shutdown_callback_ // on shutdown + ) + + ); } // Create the Dart VM isolate and give it the embedder object as the baton. @@ -755,6 +784,9 @@ void DartIsolate::AddIsolateShutdownCallback(fml::closure closure) { void DartIsolate::OnShutdownCallback() { shutdown_callbacks_.clear(); + if (isolate_shutdown_callback_) { + isolate_shutdown_callback_(); + } } DartIsolate::AutoFireClosure::AutoFireClosure(fml::closure closure) diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h index d2c09517e167628388f51ba499319acd0c370ea4..b86ba27a12e70b66f66498ee0cf475b0ce6852f0 100644 --- a/runtime/dart_isolate.h +++ b/runtime/dart_isolate.h @@ -51,7 +51,9 @@ class DartIsolate : public UIDartState { fml::WeakPtr io_manager, std::string advisory_script_uri, std::string advisory_script_entrypoint, - Dart_IsolateFlags* flags = nullptr); + Dart_IsolateFlags* flags, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback); DartIsolate(const Settings& settings, fml::RefPtr isolate_snapshot, @@ -61,7 +63,9 @@ class DartIsolate : public UIDartState { fml::WeakPtr io_manager, std::string advisory_script_uri, std::string advisory_script_entrypoint, - ChildIsolatePreparer child_isolate_preparer); + ChildIsolatePreparer child_isolate_preparer, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback); ~DartIsolate() override; @@ -128,9 +132,11 @@ class DartIsolate : public UIDartState { std::vector> shutdown_callbacks_; ChildIsolatePreparer child_isolate_preparer_ = nullptr; fml::RefPtr message_handling_task_runner_; + const fml::closure isolate_create_callback_; + const fml::closure isolate_shutdown_callback_; - FML_WARN_UNUSED_RESULT - bool Initialize(Dart_Isolate isolate, bool is_root_isolate); + FML_WARN_UNUSED_RESULT bool Initialize(Dart_Isolate isolate, + bool is_root_isolate); void SetMessageHandlingTaskRunner(fml::RefPtr runner, bool is_root_isolate); diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc index eb12946e93511b9015224a3dd25b68722b1d261b..98644a1fc7c08def7b67fd47055a59969dffcfa4 100644 --- a/runtime/dart_isolate_unittests.cc +++ b/runtime/dart_isolate_unittests.cc @@ -5,6 +5,7 @@ #include "flutter/fml/make_copyable.h" #include "flutter/fml/mapping.h" #include "flutter/fml/paths.h" +#include "flutter/fml/synchronization/count_down_latch.h" #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/thread.h" #include "flutter/runtime/dart_isolate.h" @@ -35,15 +36,18 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) { GetCurrentTaskRunner() // ); auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - vm_data->GetSharedSnapshot(), // shared snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // io manager - "main.dart", // advisory uri - "main" // advisory entrypoint + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + vm_data->GetSharedSnapshot(), // shared snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // io manager + "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 = weak_isolate.lock(); ASSERT_TRUE(root_isolate); @@ -65,15 +69,18 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) { GetCurrentTaskRunner() // ); auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - vm_data->GetSharedSnapshot(), // shared snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // io manager - "main.dart", // advisory uri - "main" // advisory entrypoint + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + vm_data->GetSharedSnapshot(), // shared snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // io manager + "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 = weak_isolate.lock(); ASSERT_TRUE(root_isolate); @@ -171,15 +178,18 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref, } auto weak_isolate = DartIsolate::CreateRootIsolate( - vm_data->GetSettings(), // settings - vm_data->GetIsolateSnapshot(), // isolate snapshot - vm_data->GetSharedSnapshot(), // shared snapshot - std::move(task_runners), // task runners - nullptr, // window - {}, // snapshot delegate - {}, // io manager - "main.dart", // advisory uri - "main" // advisory entrypoint + vm_data->GetSettings(), // settings + vm_data->GetIsolateSnapshot(), // isolate snapshot + vm_data->GetSharedSnapshot(), // shared snapshot + std::move(task_runners), // task runners + nullptr, // window + {}, // snapshot delegate + {}, // io manager + "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 = @@ -345,5 +355,28 @@ TEST_F(DartIsolateTest, CanSaveCompilationTrace) { latch.Wait(); } +TEST_F(DartIsolateTest, CanLaunchSecondaryIsolates) { + fml::CountDownLatch latch(3); + AddNativeCallback("NotifyNative", + CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments args) { + latch.CountDown(); + }))); + AddNativeCallback( + "PassMessage", CREATE_NATIVE_ENTRY(([&latch](Dart_NativeArguments args) { + auto message = tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 0)); + ASSERT_EQ("Hello from code is secondary isolate.", message); + latch.CountDown(); + }))); + const auto settings = CreateSettingsForFixture(); + auto vm_ref = DartVMRef::Create(settings); + auto isolate = RunDartCodeInIsolate(vm_ref, settings, GetThreadTaskRunner(), + "testCanLaunchSecondaryIsolate"); + ASSERT_TRUE(isolate); + ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running); + + latch.Wait(); +} + } // namespace testing } // namespace flutter diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc index f50de290890925b951affec12bcc8bcf54da4650..7ac4f6413d7884a7b5cef2afd988c5340793be21 100644 --- a/runtime/dart_lifecycle_unittests.cc +++ b/runtime/dart_lifecycle_unittests.cc @@ -51,16 +51,18 @@ static std::shared_ptr CreateAndRunRootIsolate( 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 - vm.GetSharedSnapshot(), // shared_snapshot - runners, // task_runners - {}, // window - {}, // snapshot_delegate - {}, // io_manager - "main.dart", // advisory_script_uri - entrypoint.c_str(), // advisory_script_entrypoint - nullptr // flags + vm.GetSettings(), // settings + vm.GetIsolateSnapshot(), // isolate_snapshot + vm.GetSharedSnapshot(), // shared_snapshot + runners, // task_runners + {}, // window + {}, // snapshot_delegate + {}, // io_manager + "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(); diff --git a/runtime/fixtures/simple_main.dart b/runtime/fixtures/runtime_test.dart similarity index 72% rename from runtime/fixtures/simple_main.dart rename to runtime/fixtures/runtime_test.dart index f9ba92d98f7fde7bf6b501fa3b99a37125e08cc7..6f67e01b6b2ffb4daea55b503e542672a39bf1dc 100644 --- a/runtime/fixtures/simple_main.dart +++ b/runtime/fixtures/runtime_test.dart @@ -42,3 +42,16 @@ void testCanSaveCompilationTrace() { } void NotifyResult(bool success) native "NotifyNative"; +void PassMessage(String message) native "PassMessage"; + +void secondaryIsolateMain(String message) { + print("Secondary isolate got message: " + message); + PassMessage("Hello from code is secondary isolate."); + NotifyNative(); +} + +@pragma('vm:entry-point') +void testCanLaunchSecondaryIsolate() { + Isolate.spawn(secondaryIsolateMain, "Hello from root isolate."); + NotifyNative(); +} diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index 341cbe7ee078d79a65ab7b4d5e871e0705006c7b..45267ecc3e8206667e31ed5939c4eef2e030b603 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -24,7 +24,9 @@ RuntimeController::RuntimeController( fml::WeakPtr p_io_manager, std::string p_advisory_script_uri, std::string p_advisory_script_entrypoint, - std::function p_idle_notification_callback) + std::function p_idle_notification_callback, + fml::closure p_isolate_create_callback, + fml::closure p_isolate_shutdown_callback) : RuntimeController(p_client, p_vm, std::move(p_isolate_snapshot), @@ -35,7 +37,9 @@ RuntimeController::RuntimeController( std::move(p_advisory_script_uri), std::move(p_advisory_script_entrypoint), p_idle_notification_callback, - WindowData{/* default window data */}) {} + WindowData{/* default window data */}, + p_isolate_create_callback, + p_isolate_shutdown_callback) {} RuntimeController::RuntimeController( RuntimeDelegate& p_client, @@ -48,7 +52,9 @@ RuntimeController::RuntimeController( std::string p_advisory_script_uri, std::string p_advisory_script_entrypoint, std::function idle_notification_callback, - WindowData p_window_data) + WindowData p_window_data, + fml::closure p_isolate_create_callback, + fml::closure p_isolate_shutdown_callback) : client_(p_client), vm_(p_vm), isolate_snapshot_(std::move(p_isolate_snapshot)), @@ -60,22 +66,38 @@ RuntimeController::RuntimeController( advisory_script_entrypoint_(p_advisory_script_entrypoint), idle_notification_callback_(idle_notification_callback), window_data_(std::move(p_window_data)), - root_isolate_( - DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(), - isolate_snapshot_, - shared_snapshot_, - task_runners_, - std::make_unique(this), - snapshot_delegate_, - io_manager_, - p_advisory_script_uri, - p_advisory_script_entrypoint)) { - std::shared_ptr root_isolate = root_isolate_.lock(); - root_isolate->SetReturnCodeCallback([this](uint32_t code) { + isolate_create_callback_(p_isolate_create_callback), + isolate_shutdown_callback_(p_isolate_shutdown_callback) { + // Create the root isolate as soon as the runtime controller is initialized. + // It will be run at a later point when the engine provides a run + // configuration and then runs the isolate. + auto strong_root_isolate = + DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(), // + isolate_snapshot_, // + shared_snapshot_, // + task_runners_, // + std::make_unique(this), // + snapshot_delegate_, // + io_manager_, // + p_advisory_script_uri, // + p_advisory_script_entrypoint, // + nullptr, // + isolate_create_callback_, // + isolate_shutdown_callback_ // + ) + .lock(); + + FML_CHECK(strong_root_isolate) << "Could not create root isolate."; + + // The root isolate ivar is weak. + root_isolate_ = strong_root_isolate; + + strong_root_isolate->SetReturnCodeCallback([this](uint32_t code) { root_isolate_return_code_ = {true, code}; }); + if (auto* window = GetWindowIfAvailable()) { - tonic::DartState::Scope scope(root_isolate); + tonic::DartState::Scope scope(strong_root_isolate); window->DidCreateIsolate(); if (!FlushRuntimeStateToIsolate()) { FML_DLOG(ERROR) << "Could not setup intial isolate state."; @@ -83,6 +105,7 @@ RuntimeController::RuntimeController( } else { FML_DCHECK(false) << "RuntimeController created without window binding."; } + FML_DCHECK(Dart_CurrentIsolate() == nullptr); } @@ -119,7 +142,9 @@ std::unique_ptr RuntimeController::Clone() const { advisory_script_uri_, // advisory_script_entrypoint_, // idle_notification_callback_, // - window_data_ // + window_data_, // + isolate_create_callback_, // + isolate_shutdown_callback_ // )); } diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index fbc92aeb60f2205b7b4a6aa0b8e2b394506ecb7d..8522b35d2ff76fb02a719910d79d5c92bfdbb406 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -37,7 +37,9 @@ class RuntimeController final : public WindowClient { fml::WeakPtr io_manager, std::string advisory_script_uri, std::string advisory_script_entrypoint, - std::function idle_notification_callback); + std::function idle_notification_callback, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback); ~RuntimeController() override; @@ -132,6 +134,8 @@ class RuntimeController final : public WindowClient { WindowData window_data_; std::weak_ptr root_isolate_; std::pair root_isolate_return_code_ = {false, 0}; + const fml::closure isolate_create_callback_; + const fml::closure isolate_shutdown_callback_; RuntimeController(RuntimeDelegate& client, DartVM* vm, @@ -143,7 +147,9 @@ class RuntimeController final : public WindowClient { std::string advisory_script_uri, std::string advisory_script_entrypoint, std::function idle_notification_callback, - WindowData data); + WindowData data, + fml::closure isolate_create_callback, + fml::closure isolate_shutdown_callback); Window* GetWindowIfAvailable(); diff --git a/runtime/runtime_test.cc b/runtime/runtime_test.cc index 97d42bc431418381a94560862e8e86e0393af86c..264e619ffdde398d20df8f34a6fbcd6ffb081cf6 100644 --- a/runtime/runtime_test.cc +++ b/runtime/runtime_test.cc @@ -60,7 +60,7 @@ Settings RuntimeTest::CreateSettingsForFixture() { settings.leak_vm = false; settings.task_observer_add = [](intptr_t, fml::closure) {}; settings.task_observer_remove = [](intptr_t) {}; - settings.root_isolate_create_callback = [this]() { + settings.isolate_create_callback = [this]() { native_resolver_->SetNativeResolverForIsolate(); }; SetSnapshotsAndAssets(settings); diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index 48d949e227e1e12949596f55093babdf537b64ad..b5103cca08c82cb924677e37d4e743b214126c10 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -148,7 +148,7 @@ shell_gpu_configuration("shell_unittests_gpu_configuration") { } test_fixtures("shell_unittests_fixtures") { - fixtures = [ "fixtures/main.dart" ] + fixtures = [ "fixtures/shell_test.dart" ] } shell_host_executable("shell_unittests") { diff --git a/shell/common/engine.cc b/shell/common/engine.cc index a427df24dae85718a7e3af997cc7c174c0933786..3d049f1c031b1fbdd539552a93e92f74561ffc6b 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -62,7 +62,9 @@ Engine::Engine(Delegate& delegate, std::move(io_manager), // io manager settings_.advisory_script_uri, // advisory script uri settings_.advisory_script_entrypoint, // advisory script entrypoint - settings_.idle_notification_callback // idle notification callback + settings_.idle_notification_callback, // idle notification callback + settings_.isolate_create_callback, // isolate create callback + settings_.isolate_shutdown_callback // isolate shutdown callback ); } diff --git a/shell/common/fixtures/main.dart b/shell/common/fixtures/main.dart deleted file mode 100644 index c896712d2da7e6aeecc2e61ea49a8e4d2c57b810..0000000000000000000000000000000000000000 --- a/shell/common/fixtures/main.dart +++ /dev/null @@ -1,8 +0,0 @@ -main() {} - -@pragma('vm:entry-point') -fixturesAreFunctionalMain() { - SayHiFromFixturesAreFunctionalMain(); -} - -void SayHiFromFixturesAreFunctionalMain() native "SayHiFromFixturesAreFunctionalMain"; \ No newline at end of file diff --git a/shell/common/fixtures/shell_test.dart b/shell/common/fixtures/shell_test.dart new file mode 100644 index 0000000000000000000000000000000000000000..705ac12b95b044d7a78fd6390bb53de3f09ebdd9 --- /dev/null +++ b/shell/common/fixtures/shell_test.dart @@ -0,0 +1,27 @@ +// 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. + +import 'dart:isolate'; + +main() {} + +@pragma('vm:entry-point') +fixturesAreFunctionalMain() { + SayHiFromFixturesAreFunctionalMain(); +} + +void SayHiFromFixturesAreFunctionalMain() native "SayHiFromFixturesAreFunctionalMain"; + +void NotifyNative() native "NotifyNative"; + +void secondaryIsolateMain(String message) { + print("Secondary isolate got message: " + message); + NotifyNative(); +} + +@pragma('vm:entry-point') +void testCanLaunchSecondaryIsolate() { + Isolate.spawn(secondaryIsolateMain, "Hello from root isolate."); + NotifyNative(); +} diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index bf70163ad3dd86310f84401737462cf0cdf67569..a6c958f7bbfa81a53f707c79516b768709e933db 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -67,7 +67,7 @@ Settings ShellTest::CreateSettingsForFixture() { settings.task_observer_remove = [](intptr_t key) { fml::MessageLoop::GetCurrent().RemoveTaskObserver(key); }; - settings.root_isolate_create_callback = [this]() { + settings.isolate_create_callback = [this]() { native_resolver_->SetNativeResolverForIsolate(); }; SetSnapshotsAndAssets(settings); diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 9def5530306f3215ac742dda60e5be2c655eb0f0..b18cdf2cd1dff4f71d5907e759c542b4e7084a28 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -10,6 +10,7 @@ #include "flutter/fml/make_copyable.h" #include "flutter/fml/message_loop.h" +#include "flutter/fml/synchronization/count_down_latch.h" #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/common/rasterizer.h" @@ -267,5 +268,43 @@ TEST_F(ShellTest, FixturesAreFunctional) { ASSERT_FALSE(DartVMRef::IsInstanceRunning()); } +TEST_F(ShellTest, SecondaryIsolateBindingsAreSetupViaShellSettings) { + ASSERT_FALSE(DartVMRef::IsInstanceRunning()); + const auto settings = CreateSettingsForFixture(); + auto shell = Shell::Create( + GetTaskRunnersForFixture(), settings, + [](Shell& shell) { + return std::make_unique(shell, + shell.GetTaskRunners()); + }, + [](Shell& shell) { + return std::make_unique(shell.GetTaskRunners()); + }); + ASSERT_TRUE(ValidateShell(shell.get())); + + auto configuration = RunConfiguration::InferFromSettings(settings); + ASSERT_TRUE(configuration.IsValid()); + configuration.SetEntrypoint("testCanLaunchSecondaryIsolate"); + + fml::CountDownLatch latch(2); + AddNativeCallback("NotifyNative", CREATE_NATIVE_ENTRY([&latch](auto args) { + latch.CountDown(); + })); + + fml::TaskRunner::RunNowOrPostTask( + shell->GetTaskRunners().GetUITaskRunner(), + fml::MakeCopyable([config = std::move(configuration), + engine = shell->GetEngine()]() mutable { + ASSERT_TRUE(engine); + ASSERT_EQ(engine->Run(std::move(config)), Engine::RunStatus::Success); + })); + + latch.Wait(); + + ASSERT_TRUE(DartVMRef::IsInstanceRunning()); + shell.reset(); + ASSERT_FALSE(DartVMRef::IsInstanceRunning()); +} + } // namespace testing } // namespace flutter diff --git a/testing/test_dart_native_resolver.cc b/testing/test_dart_native_resolver.cc index 62fb2a4944d9670ec6a6c1906c6ebc531e146d6e..a6d3684ad566bb89733a78da111da00317ebda04 100644 --- a/testing/test_dart_native_resolver.cc +++ b/testing/test_dart_native_resolver.cc @@ -7,7 +7,9 @@ #include #include +#include "flutter/fml/logging.h" #include "flutter/fml/synchronization/thread_annotations.h" +#include "third_party/tonic/logging/dart_error.h" #include "tonic/converter/dart_converter.h" namespace testing { @@ -44,6 +46,7 @@ Dart_NativeFunction TestDartNativeResolver::DartNativeEntryResolverCallback( std::lock_guard lock(gIsolateResolversMutex); auto found = gIsolateResolvers.find(Dart_CurrentIsolate()); if (found == gIsolateResolvers.end()) { + FML_LOG(ERROR) << "Could not resolve native method for :" << name; return nullptr; } @@ -53,6 +56,7 @@ Dart_NativeFunction TestDartNativeResolver::DartNativeEntryResolverCallback( gIsolateResolvers.erase(found); } + FML_LOG(ERROR) << "Could not resolve native method for :" << name; return nullptr; } @@ -62,13 +66,12 @@ static const uint8_t* DartNativeEntrySymbolCallback( } void TestDartNativeResolver::SetNativeResolverForIsolate() { + FML_CHECK(!Dart_IsError(Dart_RootLibrary())); auto result = Dart_SetNativeResolver(Dart_RootLibrary(), DartNativeEntryResolverCallback, DartNativeEntrySymbolCallback); - - if (Dart_IsError(result)) { - return; - } + FML_CHECK(!tonic::LogIfError(result)) + << "Could not set native resolver in test."; std::lock_guard lock(gIsolateResolversMutex); gIsolateResolvers[Dart_CurrentIsolate()] = shared_from_this();