// 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. #include "flutter/testing/dart_isolate_runner.h" #include "flutter/runtime/isolate_configuration.h" namespace flutter { namespace testing { AutoIsolateShutdown::AutoIsolateShutdown(std::shared_ptr isolate, fml::RefPtr runner) : isolate_(std::move(isolate)), runner_(std::move(runner)) {} AutoIsolateShutdown::~AutoIsolateShutdown() { if (!IsValid()) { return; } fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask( runner_, [isolate = std::move(isolate_), &latch]() { if (!isolate->Shutdown()) { FML_LOG(ERROR) << "Could not shutdown isolate."; FML_CHECK(false); } latch.Signal(); }); latch.Wait(); } [[nodiscard]] bool AutoIsolateShutdown::RunInIsolateScope( std::function closure) { if (!IsValid()) { return false; } bool result = false; fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask( runner_, [this, &result, &latch, closure]() { tonic::DartIsolateScope scope(isolate_->isolate()); tonic::DartApiScope api_scope; if (closure) { result = closure(); } latch.Signal(); }); latch.Wait(); return true; } 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, std::shared_ptr volatile_path_tracker) { FML_CHECK(task_runners.GetUITaskRunner()->RunsTasksOnCurrentThread()); if (!vm_ref) { return nullptr; } auto vm_data = vm_ref.GetVMData(); if (!vm_data) { return nullptr; } auto settings = p_settings; settings.dart_entrypoint_args = args; if (!DartVM::IsRunningPrecompiledCode()) { auto kernel_file_path = fml::paths::JoinPaths({fixtures_path, "kernel_blob.bin"}); if (!fml::IsFile(kernel_file_path)) { FML_LOG(ERROR) << "Could not locate kernel file."; return nullptr; } auto kernel_file = fml::OpenFile(kernel_file_path.c_str(), false, fml::FilePermission::kRead); if (!kernel_file.is_valid()) { FML_LOG(ERROR) << "Kernel file descriptor was invalid."; return nullptr; } auto kernel_mapping = std::make_unique(kernel_file); if (kernel_mapping->GetMapping() == nullptr) { FML_LOG(ERROR) << "Could not set up kernel mapping."; return nullptr; } settings.application_kernels = fml::MakeCopyable( [kernel_mapping = std::move(kernel_mapping)]() mutable -> Mappings { Mappings mappings; mappings.emplace_back(std::move(kernel_mapping)); return mappings; }); } 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 std::move(volatile_path_tracker) // volatile path tracker ) .lock(); if (!isolate) { FML_LOG(ERROR) << "Could not create running isolate."; return nullptr; } return std::make_unique(isolate, task_runners.GetUITaskRunner()); } std::unique_ptr RunDartCodeInIsolate( DartVMRef& vm_ref, const Settings& settings, const TaskRunners& task_runners, std::string entrypoint, const std::vector& args, const std::string& fixtures_path, fml::WeakPtr io_manager, std::shared_ptr volatile_path_tracker) { std::unique_ptr result; fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask( task_runners.GetUITaskRunner(), fml::MakeCopyable([&]() mutable { result = RunDartCodeInIsolateOnUITaskRunner( vm_ref, settings, task_runners, entrypoint, args, fixtures_path, io_manager, std::move(volatile_path_tracker)); latch.Signal(); })); latch.Wait(); return result; } } // namespace testing } // namespace flutter