flutter_flutter/runtime/dart_isolate.cc
Alexander Aprelev f5c7cb366a Roll dart to b298fc6d8f6a0e1aa841dbbdda26663d6012a79a. (#5155)
* Roll dart to b298fc6d8f6a0e1aa841dbbdda26663d6012a79a.

Changes since last roll:
```
b298fc6d8f Revert "[kernel] Change dill representation of doubles"
9a7e1f64a2 Revert "Revert "Fix incorrect handling of NSM forwarders and pull all logic into CFE.""
cbca4006f8 fix #30907, add library constants for all SDK libraries
61c226b4ea Only create Goma's analyzer on Linux.
24dd9b4176 Revert "Fix incorrect handling of NSM forwarders and pull all logic into CFE."
bed71b7776 Migrate and clean up the prefix negative tests.
1fcd896ed9 [VM] Avoid deadlock by allowing us to run kernel isolate from a script snapshot, fixes all dartk-sim* builders
0bc6e7217a Update expression compilation expectations.
9038b8f45f CFE support for compiling individual expressions in a context.
7d5025e814 Fix incorrect handling of NSM forwarders and pull all logic into CFE.
e2247e5e00 Put the '@' outside the revision variables.
9381424204 Fix presubmit on Windows. Dart executable is not called .bat
2a8c3515b2 Avoid strong+checked mode: strong mode supersedes checked mode
b7698dcbce Update status for Windows
8baa82413b [infra] Remove --no-preview-dart-2 flag from gardening tools
47e9039512 Don't encode strings up front; don't toString uris
4a0ac85cc3 Update co19 status
ce7329849d Fix build breakages - use platform independent path specification is test so that   it works on windows - skip test for precompiled and dartk builds as the test uses   spawnUri which is not supported in these modes
ee6351a147 [VM] Set up package config value when invoking the front end for compilation, this should fix issue 32950 "(Isolate.spawnUri() ignores packageConfig argument in Dart 2 mode.'
d1286a367e Strong mode update for swarm
fd27cc3435 Don't store bytes in the file cache.
73abd61304 Re-land "Clean up the use of deprecated API in the analyzer_plugin package".
607f4f5769 [vm] Get more helpful errors from Dart_SetVMFlags and Dart_MakeIsolateRunnable.
f044637c8b [infra] Upgrade checked in SDKs to 2.0.0-dev.52.0
dcf10816aa [infra] Add script that updates checked in SDKs
f8bea2a7e6 dart2js: Register inlined native methods for dump info
7fe8659613 dump-info: Use relative paths for library canonicalUri...
dcf4886500 [frontend-server] Add verbose option.
5087ffa481 [release] Move DDC sync-async flip to correct section in the release notes
fe7056ebaa [release] Update changelog for 2.0.0-dev.52.0
```

* Pick up another revert to fix https://github.com/flutter/flutter/issues/17214 and few more dart commits landed since:

```
4c9b712052 Revert "Don't encode strings up front; don't toString uris"
a1fbf62742 [build] Place 'extern "C"' before __attribute__, as required by gcc.
258c5172df [vm] Remove dart_mirrors_api.h.
384c55c29e Update dartdoc & dependencies to v0.19.0.
```

* fix licenses
2018-05-02 18:42:14 -07:00

751 lines
24 KiB
C++

// Copyright 2017 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/runtime/dart_isolate.h"
#include <cstdlib>
#include <tuple>
#include "flutter/fml/trace_event.h"
#include "flutter/lib/io/dart_io.h"
#include "flutter/lib/ui/dart_runtime_hooks.h"
#include "flutter/lib/ui/dart_ui.h"
#include "flutter/runtime/dart_service_isolate.h"
#include "flutter/runtime/dart_vm.h"
#include "lib/fxl/files/path.h"
#include "lib/tonic/converter/dart_converter.h"
#include "lib/tonic/dart_class_library.h"
#include "lib/tonic/dart_class_provider.h"
#include "lib/tonic/dart_message_handler.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/dart_sticky_error.h"
#include "lib/tonic/file_loader/file_loader.h"
#include "lib/tonic/scopes/dart_api_scope.h"
#include "lib/tonic/scopes/dart_isolate_scope.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
#ifdef ERROR
#undef ERROR
#endif
namespace blink {
fml::WeakPtr<DartIsolate> DartIsolate::CreateRootIsolate(
const DartVM* vm,
fxl::RefPtr<DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
std::unique_ptr<Window> window,
fml::WeakPtr<GrContext> resource_context,
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
Dart_IsolateFlags* flags) {
TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate");
Dart_Isolate vm_isolate = nullptr;
fml::WeakPtr<DartIsolate> embedder_isolate;
char* error = nullptr;
// 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).
auto root_embedder_data = std::make_unique<DartIsolate>(
vm, // VM
std::move(isolate_snapshot), // isolate snapshot
task_runners, // task runners
std::move(resource_context), // resource context
std::move(unref_queue), // skia unref queue
advisory_script_uri, // advisory URI
advisory_script_entrypoint, // advisory entrypoint
nullptr // child isolate preparer will be set when this isolate is
// prepared to run
);
std::tie(vm_isolate, embedder_isolate) = CreateDartVMAndEmbedderObjectPair(
advisory_script_uri.c_str(), // advisory script URI
advisory_script_entrypoint.c_str(), // advisory script entrypoint
nullptr, // package root
nullptr, // package config
flags, // flags
root_embedder_data.get(), // parent embedder data
true, // is root isolate
&error // error (out)
);
if (error != nullptr) {
free(error);
}
if (vm_isolate == nullptr) {
return {};
}
if (embedder_isolate) {
// Only root isolates can interact with windows.
embedder_isolate->SetWindow(std::move(window));
embedder_isolate->set_use_blink(vm->GetSettings().using_blink);
}
root_embedder_data.release();
return embedder_isolate;
}
DartIsolate::DartIsolate(const DartVM* vm,
fxl::RefPtr<DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
fml::WeakPtr<GrContext> resource_context,
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
ChildIsolatePreparer child_isolate_preparer)
: UIDartState(std::move(task_runners),
vm->GetSettings().task_observer_add,
vm->GetSettings().task_observer_remove,
std::move(resource_context),
std::move(unref_queue),
advisory_script_uri,
advisory_script_entrypoint,
vm->GetSettings().log_tag),
vm_(vm),
isolate_snapshot_(std::move(isolate_snapshot)),
child_isolate_preparer_(std::move(child_isolate_preparer)),
weak_factory_(std::make_unique<fml::WeakPtrFactory<DartIsolate>>(this)) {
FXL_DCHECK(isolate_snapshot_) << "Must contain a valid isolate snapshot.";
if (vm_ == nullptr) {
return;
}
phase_ = Phase::Uninitialized;
}
DartIsolate::~DartIsolate() = default;
DartIsolate::Phase DartIsolate::GetPhase() const {
return phase_;
}
const DartVM* DartIsolate::GetDartVM() const {
return vm_;
}
bool DartIsolate::Initialize(Dart_Isolate dart_isolate, bool is_root_isolate) {
TRACE_EVENT0("flutter", "DartIsolate::Initialize");
if (phase_ != Phase::Uninitialized) {
return false;
}
if (dart_isolate == nullptr) {
return false;
}
if (Dart_CurrentIsolate() != dart_isolate) {
return false;
}
if (Dart_IsolateData(dart_isolate) != this) {
return false;
}
// After this point, isolate scopes can be safely used.
SetIsolate(dart_isolate);
// We are entering a new scope (for the first time since initialization) and
// we want to restore the current scope to null when we exit out of this
// method. This balances the implicit Dart_EnterIsolate call made by
// Dart_CreateIsolate (which calls the Initialize).
Dart_ExitIsolate();
tonic::DartIsolateScope scope(isolate());
if (is_root_isolate) {
if (auto task_runner = GetTaskRunners().GetUITaskRunner()) {
// Isolates may not have any particular thread affinity. Only initialize
// the message handler if a task runner is explicitly specified.
message_handler().Initialize(task_runner);
}
}
if (tonic::LogIfError(
Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))) {
return false;
}
if (!UpdateThreadPoolNames()) {
return false;
}
phase_ = Phase::Initialized;
return true;
}
// Updating thread names here does not change the underlying OS thread names.
// Instead, this is just additional metadata for the Observatory to show the
// thread name of the isolate.
bool DartIsolate::UpdateThreadPoolNames() const {
// TODO(chinmaygarde): This implementation does not account for multiple
// shells sharing the same (or subset of) threads.
const auto& task_runners = GetTaskRunners();
if (auto task_runner = task_runners.GetGPUTaskRunner()) {
task_runner->PostTask(
[label = task_runners.GetLabel() + std::string{".gpu"}]() {
Dart_SetThreadName(label.c_str());
});
}
if (auto task_runner = task_runners.GetUITaskRunner()) {
task_runner->PostTask(
[label = task_runners.GetLabel() + std::string{".ui"}]() {
Dart_SetThreadName(label.c_str());
});
}
if (auto task_runner = task_runners.GetIOTaskRunner()) {
task_runner->PostTask(
[label = task_runners.GetLabel() + std::string{".io"}]() {
Dart_SetThreadName(label.c_str());
});
}
if (auto task_runner = task_runners.GetPlatformTaskRunner()) {
task_runner->PostTask(
[label = task_runners.GetLabel() + std::string{".platform"}]() {
Dart_SetThreadName(label.c_str());
});
}
return true;
}
bool DartIsolate::LoadLibraries(bool is_root_isolate) {
TRACE_EVENT0("flutter", "DartIsolate::LoadLibraries");
if (phase_ != Phase::Initialized) {
return false;
}
tonic::DartState::Scope scope(this);
DartIO::InitForIsolate();
DartUI::InitForIsolate();
const bool is_service_isolate = Dart_IsServiceIsolate(isolate());
DartRuntimeHooks::Install(is_root_isolate && !is_service_isolate,
GetAdvisoryScriptURI());
if (!is_service_isolate) {
class_library().add_provider(
"ui", std::make_unique<tonic::DartClassProvider>(this, "dart:ui"));
}
phase_ = Phase::LibrariesSetup;
return true;
}
bool DartIsolate::PrepareForRunningFromPrecompiledCode() {
TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromPrecompiledCode");
if (phase_ != Phase::LibrariesSetup) {
return false;
}
if (!DartVM::IsRunningPrecompiledCode()) {
return false;
}
tonic::DartState::Scope scope(this);
if (Dart_IsNull(Dart_RootLibrary())) {
return false;
}
if (!MarkIsolateRunnable()) {
return false;
}
child_isolate_preparer_ = [](DartIsolate* isolate) {
return isolate->PrepareForRunningFromPrecompiledCode();
};
phase_ = Phase::Ready;
return true;
}
static bool LoadScriptSnapshot(std::shared_ptr<const fml::Mapping> mapping) {
if (tonic::LogIfError(Dart_LoadScriptFromSnapshot(mapping->GetMapping(),
mapping->GetSize()))) {
return false;
}
return true;
}
static bool LoadKernelSnapshot(std::shared_ptr<const fml::Mapping> mapping) {
if (tonic::LogIfError(Dart_LoadScriptFromKernel(mapping->GetMapping(),
mapping->GetSize()))) {
return false;
}
return true;
}
static bool LoadSnapshot(std::shared_ptr<const fml::Mapping> mapping) {
if (Dart_IsKernel(mapping->GetMapping(), mapping->GetSize())) {
return LoadKernelSnapshot(std::move(mapping));
} else {
return LoadScriptSnapshot(std::move(mapping));
}
return false;
}
FXL_WARN_UNUSED_RESULT
bool DartIsolate::PrepareForRunningFromSnapshot(
std::shared_ptr<const fml::Mapping> mapping) {
TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSnapshot");
if (phase_ != Phase::LibrariesSetup) {
return false;
}
if (DartVM::IsRunningPrecompiledCode()) {
return false;
}
if (!mapping || mapping->GetSize() == 0) {
return false;
}
tonic::DartState::Scope scope(this);
if (!Dart_IsNull(Dart_RootLibrary())) {
return false;
}
if (!LoadSnapshot(mapping)) {
return false;
}
if (Dart_IsNull(Dart_RootLibrary())) {
return false;
}
if (!MarkIsolateRunnable()) {
return false;
}
child_isolate_preparer_ = [mapping](DartIsolate* isolate) {
return isolate->PrepareForRunningFromSnapshot(mapping);
};
phase_ = Phase::Ready;
return true;
}
bool DartIsolate::PrepareForRunningFromSource(
const std::string& main_source_file,
const std::string& packages) {
TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromSource");
if (phase_ != Phase::LibrariesSetup) {
return false;
}
if (DartVM::IsRunningPrecompiledCode()) {
return false;
}
if (main_source_file.empty()) {
return false;
}
tonic::DartState::Scope scope(this);
if (!Dart_IsNull(Dart_RootLibrary())) {
return false;
}
auto& loader = file_loader();
if (!packages.empty()) {
auto packages_absolute_path = files::AbsolutePath(packages);
FXL_DLOG(INFO) << "Loading from packages: " << packages_absolute_path;
if (!loader.LoadPackagesMap(packages_absolute_path)) {
return false;
}
}
auto main_source_absolute_path = files::AbsolutePath(main_source_file);
FXL_DLOG(INFO) << "Loading from source: " << main_source_absolute_path;
if (tonic::LogIfError(loader.LoadScript(main_source_absolute_path))) {
return false;
}
if (Dart_IsNull(Dart_RootLibrary())) {
return false;
}
if (!MarkIsolateRunnable()) {
return false;
}
child_isolate_preparer_ = [main_source_file, packages](DartIsolate* isolate) {
return isolate->PrepareForRunningFromSource(main_source_file, packages);
};
phase_ = Phase::Ready;
return true;
}
bool DartIsolate::MarkIsolateRunnable() {
TRACE_EVENT0("flutter", "DartIsolate::MarkIsolateRunnable");
if (phase_ != Phase::LibrariesSetup) {
return false;
}
// This function may only be called from an active isolate scope.
if (Dart_CurrentIsolate() != isolate()) {
return false;
}
// There must be no current isolate to mark an isolate as being runnable.
Dart_ExitIsolate();
char* error = Dart_IsolateMakeRunnable(isolate());
if (error) {
FXL_DLOG(ERROR) << error;
::free(error);
// Failed. Restore the isolate.
Dart_EnterIsolate(isolate());
return false;
}
// Success. Restore the isolate.
Dart_EnterIsolate(isolate());
return true;
}
FXL_WARN_UNUSED_RESULT
bool DartIsolate::Run(const std::string& entrypoint_name) {
TRACE_EVENT0("flutter", "DartIsolate::Run");
if (phase_ != Phase::Ready) {
return false;
}
tonic::DartState::Scope scope(this);
Dart_Handle entrypoint = Dart_GetClosure(
Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
if (tonic::LogIfError(entrypoint)) {
return false;
}
Dart_Handle isolate_lib = Dart_LookupLibrary(tonic::ToDart("dart:isolate"));
if (tonic::LogIfError(isolate_lib)) {
return false;
}
Dart_Handle isolate_args[] = {
entrypoint,
Dart_Null(),
};
if (tonic::LogIfError(Dart_Invoke(
isolate_lib, tonic::ToDart("_startMainIsolate"),
sizeof(isolate_args) / sizeof(isolate_args[0]), isolate_args))) {
return false;
}
phase_ = Phase::Running;
FXL_DLOG(INFO) << "New isolate is in the running state.";
return true;
}
bool DartIsolate::Shutdown() {
TRACE_EVENT0("flutter", "DartIsolate::Shutdown");
// This call may be re-entrant since Dart_ShutdownIsolate can invoke the
// cleanup callback which deletes the embedder side object of the dart isolate
// (a.k.a. this).
if (phase_ == Phase::Shutdown) {
return false;
}
phase_ = Phase::Shutdown;
Dart_Isolate vm_isolate = isolate();
// The isolate can be nullptr if this instance is the stub isolate data used
// during root isolate creation.
if (vm_isolate != nullptr) {
// We need to enter the isolate because Dart_ShutdownIsolate does not take
// the isolate to shutdown as a parameter.
FXL_DCHECK(Dart_CurrentIsolate() == nullptr);
Dart_EnterIsolate(vm_isolate);
Dart_ShutdownIsolate();
FXL_DCHECK(Dart_CurrentIsolate() == nullptr);
}
return true;
}
Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
const char* advisory_script_uri,
const char* advisory_script_entrypoint,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
char** error) {
auto vm = DartVM::ForProcessIfInitialized();
if (!vm) {
*error = strdup(
"Could not resolve the VM when attempting to create the service "
"isolate.");
return nullptr;
}
const auto& settings = vm->GetSettings();
if (!settings.enable_observatory) {
FXL_DLOG(INFO) << "Observatory is disabled.";
return nullptr;
}
blink::TaskRunners null_task_runners(
"io.flutter." DART_VM_SERVICE_ISOLATE_NAME, nullptr, nullptr, nullptr,
nullptr);
flags->load_vmservice_library = true;
fml::WeakPtr<DartIsolate> weak_service_isolate =
DartIsolate::CreateRootIsolate(
vm.get(), // vm
vm->GetIsolateSnapshot(), // isolate snapshot
null_task_runners, // task runners
nullptr, // window
{}, // resource context
{}, // unref queue
advisory_script_uri == nullptr ? ""
: advisory_script_uri, // script uri
advisory_script_entrypoint == nullptr
? ""
: advisory_script_entrypoint, // script entrypoint
flags // flags
);
if (!weak_service_isolate) {
*error = strdup("Could not create the service isolate.");
FXL_DLOG(ERROR) << *error;
return nullptr;
}
// The engine never holds a strong reference to the VM service isolate. Since
// we are about to lose our last weak reference to it, start the VM service
// while we have this reference.
DartIsolate* service_isolate = weak_service_isolate.get();
// The service isolate is created and destroyed on arbitrary Dart pool threads
// and can not support a weak pointer factory that must be bound to a specific
// thread.
service_isolate->ResetWeakPtrFactory();
const bool isolate_snapshot_is_dart_2 =
Dart_IsDart2Snapshot(vm->GetIsolateSnapshot()->GetData()->GetSnapshotPointer());
const bool is_preview_dart2 =
vm->GetPlatformKernel() != nullptr || isolate_snapshot_is_dart_2;
const bool running_from_sources =
!DartVM::IsRunningPrecompiledCode() && !is_preview_dart2;
tonic::DartState::Scope scope(service_isolate);
if (!DartServiceIsolate::Startup(
settings.ipv6 ? "::1" : "127.0.0.1", // server IP address
settings.observatory_port, // server observatory port
tonic::DartState::HandleLibraryTag, // embedder library tag handler
running_from_sources, // running from source code
false, // disable websocket origin check
error // error (out)
)) {
// Error is populated by call to startup.
FXL_DLOG(ERROR) << *error;
return nullptr;
}
vm->GetServiceProtocol().ToggleHooks(true);
return service_isolate->isolate();
}
// |Dart_IsolateCreateCallback|
Dart_Isolate DartIsolate::DartIsolateCreateCallback(
const char* advisory_script_uri,
const char* advisory_script_entrypoint,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
DartIsolate* parent_embedder_isolate,
char** error) {
if (parent_embedder_isolate == nullptr &&
strcmp(advisory_script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
// The VM attempts to start the VM service for us on |Dart_Initialize|. In
// such a case, the callback data will be null and the script URI will be
// DART_VM_SERVICE_ISOLATE_NAME. In such cases, we just create the service
// isolate like normal but dont hold a reference to it at all. We also start
// this isolate since we will never again reference it from the engine.
return DartCreateAndStartServiceIsolate(advisory_script_uri, //
advisory_script_entrypoint, //
package_root, //
package_config, //
flags, //
error //
);
}
return CreateDartVMAndEmbedderObjectPair(
advisory_script_uri, // URI
advisory_script_entrypoint, // entrypoint
package_root, // package root
package_config, // package config
flags, // isolate flags
parent_embedder_isolate, // embedder data
false, // is root isolate
error // error
)
.first;
}
std::pair<Dart_Isolate, fml::WeakPtr<DartIsolate>>
DartIsolate::CreateDartVMAndEmbedderObjectPair(
const char* advisory_script_uri,
const char* advisory_script_entrypoint,
const char* package_root,
const char* package_config,
Dart_IsolateFlags* flags,
DartIsolate* p_parent_embedder_isolate,
bool is_root_isolate,
char** error) {
TRACE_EVENT0("flutter", "DartIsolate::CreateDartVMAndEmbedderObjectPair");
std::unique_ptr<DartIsolate> embedder_isolate{p_parent_embedder_isolate};
if (embedder_isolate == nullptr || embedder_isolate->GetDartVM() == nullptr) {
*error =
strdup("Parent isolate did not have embedder specific callback data.");
FXL_DLOG(ERROR) << *error;
return {nullptr, {}};
}
const DartVM* vm = embedder_isolate->GetDartVM();
if (!is_root_isolate) {
auto raw_embedder_isolate = embedder_isolate.release();
blink::TaskRunners null_task_runners(advisory_script_uri, nullptr, nullptr,
nullptr, nullptr);
embedder_isolate = std::make_unique<DartIsolate>(
vm, // vm
raw_embedder_isolate->GetIsolateSnapshot(), // isolate_snapshot
null_task_runners, // task_runners
fml::WeakPtr<GrContext>{}, // resource_context
nullptr, // unref_queue
advisory_script_uri, // advisory_script_uri
advisory_script_entrypoint, // advisory_script_entrypoint
raw_embedder_isolate->child_isolate_preparer_ // child isolate preparer
);
}
// Create the Dart VM isolate and give it the embedder object as the baton.
Dart_Isolate isolate =
vm->GetPlatformKernel() != nullptr
? Dart_CreateIsolateFromKernel(advisory_script_uri, //
advisory_script_entrypoint, //
vm->GetPlatformKernel(), //
flags, //
embedder_isolate.get(), //
error //
)
: Dart_CreateIsolate(advisory_script_uri, //
advisory_script_entrypoint, //
embedder_isolate->GetIsolateSnapshot()
->GetData()
->GetSnapshotPointer(), //
embedder_isolate->GetIsolateSnapshot()
->GetInstructionsIfPresent(), //
nullptr, //
nullptr, //
flags, //
embedder_isolate.get(), //
error //
);
if (isolate == nullptr) {
FXL_DLOG(ERROR) << *error;
return {nullptr, {}};
}
if (!embedder_isolate->Initialize(isolate, is_root_isolate)) {
*error = strdup("Embedder could not initialize the Dart isolate.");
FXL_DLOG(ERROR) << *error;
return {nullptr, {}};
}
if (!embedder_isolate->LoadLibraries(is_root_isolate)) {
*error =
strdup("Embedder could not load libraries in the new Dart isolate.");
FXL_DLOG(ERROR) << *error;
return {nullptr, {}};
}
auto weak_embedder_isolate = embedder_isolate->GetWeakIsolatePtr();
// Root isolates will be setup by the engine and the service isolate (which is
// also a root isolate) by the utility routines in the VM. However, secondary
// isolates will be run by the VM if they are marked as runnable.
if (!is_root_isolate) {
FXL_DCHECK(embedder_isolate->child_isolate_preparer_);
if (!embedder_isolate->child_isolate_preparer_(embedder_isolate.get())) {
*error = strdup("Could not prepare the child isolate to run.");
FXL_DLOG(ERROR) << *error;
return {nullptr, {}};
}
embedder_isolate->ResetWeakPtrFactory();
}
// The ownership of the embedder object is controlled by the Dart VM. So the
// only reference returned to the caller is weak.
embedder_isolate.release();
return {isolate, weak_embedder_isolate};
}
// |Dart_IsolateShutdownCallback|
void DartIsolate::DartIsolateShutdownCallback(DartIsolate* embedder_isolate) {
if (!tonic::DartStickyError::IsSet()) {
return;
}
tonic::DartApiScope api_scope;
FXL_LOG(ERROR) << "Isolate " << tonic::StdStringFromDart(Dart_DebugName())
<< " exited with an error";
Dart_Handle sticky_error = Dart_GetStickyError();
FXL_CHECK(tonic::LogIfError(sticky_error));
}
// |Dart_IsolateCleanupCallback|
void DartIsolate::DartIsolateCleanupCallback(DartIsolate* embedder_isolate) {
delete embedder_isolate;
}
fxl::RefPtr<DartSnapshot> DartIsolate::GetIsolateSnapshot() const {
return isolate_snapshot_;
}
fml::WeakPtr<DartIsolate> DartIsolate::GetWeakIsolatePtr() const {
return weak_factory_ ? weak_factory_->GetWeakPtr()
: fml::WeakPtr<DartIsolate>();
}
void DartIsolate::ResetWeakPtrFactory() {
FXL_CHECK(weak_factory_);
weak_factory_.reset();
}
void DartIsolate::AddIsolateShutdownCallback(fxl::Closure closure) {
shutdown_callbacks_.emplace_back(
std::make_unique<AutoFireClosure>(std::move(closure)));
}
} // namespace blink