blob: f3e225f3fe6afe40842463fca44b58a660b9594f [file] [log] [blame]
// 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<DartIsolate> isolate,
fml::RefPtr<fml::TaskRunner> runner)
: isolate_(std::move(isolate)), runner_(std::move(runner)) {}
AutoIsolateShutdown::~AutoIsolateShutdown() {
if (!isolate_->IsShuttingDown()) {
Shutdown();
}
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(runner_, [this, &latch]() {
// Delete isolate on thread.
isolate_.reset();
latch.Signal();
});
latch.Wait();
}
void AutoIsolateShutdown::Shutdown() {
if (!IsValid()) {
return;
}
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
runner_, [isolate = isolate_.get(), &latch]() {
if (!isolate->Shutdown()) {
FML_LOG(ERROR) << "Could not shutdown isolate.";
FML_CHECK(false);
}
latch.Signal();
});
latch.Wait();
}
[[nodiscard]] bool AutoIsolateShutdown::RunInIsolateScope(
std::function<bool(void)> 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 result;
}
std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolateOnUITaskRunner(
DartVMRef& vm_ref,
const Settings& p_settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& kernel_file_path,
fml::WeakPtr<IOManager> io_manager,
std::shared_ptr<VolatilePathTracker> 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;
if (!DartVM::IsRunningPrecompiledCode()) {
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<fml::FileMapping>(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);
UIDartState::Context context(std::move(task_runners));
context.io_manager = io_manager;
context.advisory_script_uri = "main.dart";
context.advisory_script_entrypoint = entrypoint.c_str();
auto isolate =
DartIsolate::CreateRunningRootIsolate(
settings, // settings
vm_data->GetIsolateSnapshot(), // isolate snapshot
nullptr, // platform configuration
DartIsolate::Flags{}, // flags
nullptr, // root isolate create callback
settings.isolate_create_callback, // isolate create callback
settings.isolate_shutdown_callback, // isolate shutdown callback
entrypoint, // entrypoint
std::nullopt, // library
args, // args
std::move(isolate_configuration), // isolate configuration
context // engine context
)
.lock();
if (!isolate) {
FML_LOG(ERROR) << "Could not create running isolate.";
return nullptr;
}
return std::make_unique<AutoIsolateShutdown>(isolate,
task_runners.GetUITaskRunner());
}
std::unique_ptr<AutoIsolateShutdown> RunDartCodeInIsolate(
DartVMRef& vm_ref,
const Settings& settings,
const TaskRunners& task_runners,
std::string entrypoint,
const std::vector<std::string>& args,
const std::string& kernel_file_path,
fml::WeakPtr<IOManager> io_manager,
std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
std::unique_ptr<AutoIsolateShutdown> result;
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetUITaskRunner(), fml::MakeCopyable([&]() mutable {
result = RunDartCodeInIsolateOnUITaskRunner(
vm_ref, settings, task_runners, entrypoint, args, kernel_file_path,
io_manager, std::move(volatile_path_tracker));
latch.Signal();
}));
latch.Wait();
return result;
}
} // namespace testing
} // namespace flutter