Flutter Engine
 
Loading...
Searching...
No Matches
dart_isolate.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cstdlib>
8#include <utility>
9
10#include "flutter/fml/logging.h"
24#include "fml/task_source.h"
25#include "fml/time/time_point.h"
26#include "third_party/dart/runtime/include/bin/native_assets_api.h"
27#include "third_party/dart/runtime/include/dart_api.h"
28#include "third_party/dart/runtime/include/dart_tools_api.h"
37
38namespace flutter {
39
40namespace {
41
42constexpr std::string_view kFileUriPrefix = "file://";
43
44class DartErrorString {
45 public:
46 DartErrorString() {}
47 ~DartErrorString() {
48 if (str_) {
49 ::free(str_);
50 }
51 }
52 char** error() { return &str_; }
53 const char* str() const { return str_; }
54 explicit operator bool() const { return str_ != nullptr; }
55
56 private:
57 FML_DISALLOW_COPY_AND_ASSIGN(DartErrorString);
58 char* str_ = nullptr;
59};
60
61} // anonymous namespace
62
63DartIsolate::Flags::Flags() : Flags(nullptr) {}
64
65DartIsolate::Flags::Flags(const Dart_IsolateFlags* flags) {
66 if (flags) {
67 flags_ = *flags;
68 } else {
69 ::Dart_IsolateFlagsInitialize(&flags_);
70 }
71}
72
73DartIsolate::Flags::~Flags() = default;
74
75void DartIsolate::Flags::SetNullSafetyEnabled(bool enabled) {
76 flags_.null_safety = enabled;
77}
78
79void DartIsolate::Flags::SetIsDontNeedSafe(bool value) {
80 flags_.snapshot_is_dontneed_safe = value;
81}
82
83Dart_IsolateFlags DartIsolate::Flags::Get() const {
84 return flags_;
85}
86
87std::weak_ptr<DartIsolate> DartIsolate::CreateRunningRootIsolate(
88 const Settings& settings,
89 const fml::RefPtr<const DartSnapshot>& isolate_snapshot,
90 std::unique_ptr<PlatformConfiguration> platform_configuration,
91 Flags isolate_flags,
92 const fml::closure& root_isolate_create_callback,
93 const fml::closure& isolate_create_callback,
94 const fml::closure& isolate_shutdown_callback,
95 std::optional<std::string> dart_entrypoint,
96 std::optional<std::string> dart_entrypoint_library,
97 const std::vector<std::string>& dart_entrypoint_args,
98 std::unique_ptr<IsolateConfiguration> isolate_configuration,
99 const UIDartState::Context& context,
100 const DartIsolate* spawning_isolate,
101 std::shared_ptr<NativeAssetsManager> native_assets_manager) {
102 if (!isolate_snapshot) {
103 FML_LOG(ERROR) << "Invalid isolate snapshot.";
104 return {};
105 }
106
107 if (!isolate_configuration) {
108 FML_LOG(ERROR) << "Invalid isolate configuration.";
109 return {};
110 }
111
112 isolate_flags.SetNullSafetyEnabled(
113 isolate_configuration->IsNullSafetyEnabled(*isolate_snapshot));
114 isolate_flags.SetIsDontNeedSafe(isolate_snapshot->IsDontNeedSafe());
115
116 auto isolate = CreateRootIsolate(settings, //
117 isolate_snapshot, //
118 std::move(platform_configuration), //
119 isolate_flags, //
120 isolate_create_callback, //
121 isolate_shutdown_callback, //
122 context, //
123 spawning_isolate, //
124 std::move(native_assets_manager) //
125 )
126 .lock();
127
128 if (!isolate) {
129 FML_LOG(ERROR) << "Could not create root isolate.";
130 return {};
131 }
132
133 fml::ScopedCleanupClosure shutdown_on_error([isolate]() {
134 if (!isolate->Shutdown()) {
135 FML_DLOG(ERROR) << "Could not shutdown transient isolate.";
136 }
137 });
138
139 if (isolate->GetPhase() != DartIsolate::Phase::LibrariesSetup) {
140 FML_LOG(ERROR) << "Root isolate was created in an incorrect phase: "
141 << static_cast<int>(isolate->GetPhase());
142 return {};
143 }
144
145 if (!isolate_configuration->PrepareIsolate(*isolate.get())) {
146 FML_LOG(ERROR) << "Could not prepare isolate.";
147 return {};
148 }
149
150 if (isolate->GetPhase() != DartIsolate::Phase::Ready) {
151 FML_LOG(ERROR) << "Root isolate not in the ready phase for Dart entrypoint "
152 "invocation.";
153 return {};
154 }
155
156 {
157 tonic::DartState::Scope scope(isolate.get());
158 if (settings.merged_platform_ui_thread !=
160 Dart_SetCurrentThreadOwnsIsolate();
161 }
162
163 if (settings.root_isolate_create_callback) {
164 // Isolate callbacks always occur in isolate scope and before user code
165 // has had a chance to run.
166 settings.root_isolate_create_callback(*isolate.get());
167 }
168 }
169
170 if (root_isolate_create_callback) {
171 root_isolate_create_callback();
172 }
173
174 if (!isolate->RunFromLibrary(std::move(dart_entrypoint_library), //
175 std::move(dart_entrypoint), //
176 dart_entrypoint_args)) {
177 FML_LOG(ERROR) << "Could not run the run main Dart entrypoint.";
178 return {};
179 }
180
181 if (settings.root_isolate_shutdown_callback) {
182 isolate->AddIsolateShutdownCallback(
184 }
185
186 shutdown_on_error.Release();
187
188 return isolate;
189}
190
191void DartIsolate::SpawnIsolateShutdownCallback(
192 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
193 std::shared_ptr<DartIsolate>* isolate_data) {
194 DartIsolate::DartIsolateShutdownCallback(isolate_group_data, isolate_data);
195}
196
197std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
198 const Settings& settings,
199 fml::RefPtr<const DartSnapshot> isolate_snapshot,
200 std::unique_ptr<PlatformConfiguration> platform_configuration,
201 const Flags& flags,
202 const fml::closure& isolate_create_callback,
203 const fml::closure& isolate_shutdown_callback,
204 const UIDartState::Context& context,
205 const DartIsolate* spawning_isolate,
206 std::shared_ptr<NativeAssetsManager> native_assets_manager) {
207 TRACE_EVENT0("flutter", "DartIsolate::CreateRootIsolate");
208
209 // Only needed if this is the main isolate for the group.
210 std::unique_ptr<std::shared_ptr<DartIsolateGroupData>> isolate_group_data;
211
212 auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
213 std::shared_ptr<DartIsolate>(new DartIsolate(
214 /*settings=*/settings,
215 /*is_root_isolate=*/true,
216 /*context=*/context,
217 /*is_spawning_in_group=*/!!spawning_isolate)));
218
219 DartErrorString error;
220 Dart_Isolate vm_isolate = nullptr;
221 auto isolate_flags = flags.Get();
222
223 IsolateMaker isolate_maker;
224 if (spawning_isolate) {
225 isolate_maker =
226 [spawning_isolate](
227 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
228 std::shared_ptr<DartIsolate>* isolate_data,
229 Dart_IsolateFlags* flags, char** error) {
230 return Dart_CreateIsolateInGroup(
231 /*group_member=*/spawning_isolate->isolate(),
232 /*name=*/
233 spawning_isolate->GetIsolateGroupData()
234 .GetAdvisoryScriptEntrypoint()
235 .c_str(),
236 /*shutdown_callback=*/
237 reinterpret_cast<Dart_IsolateShutdownCallback>(
238 DartIsolate::SpawnIsolateShutdownCallback),
239 /*cleanup_callback=*/
240 reinterpret_cast<Dart_IsolateCleanupCallback>(
241 DartIsolateCleanupCallback),
242 /*child_isolate_data=*/isolate_data,
243 /*error=*/error);
244 };
245 } else {
246 // The child isolate preparer is null but will be set when the isolate is
247 // being prepared to run.
248 isolate_group_data =
249 std::make_unique<std::shared_ptr<DartIsolateGroupData>>(
250 std::shared_ptr<DartIsolateGroupData>(new DartIsolateGroupData(
251 settings, // settings
252 std::move(isolate_snapshot), // isolate snapshot
253 context.advisory_script_uri, // advisory URI
254 context.advisory_script_entrypoint, // advisory entrypoint
255 nullptr, // child isolate preparer
256 isolate_create_callback, // isolate create callback
257 isolate_shutdown_callback, // isolate shutdown callback
258 std::move(native_assets_manager) //
259 )));
260 isolate_maker = [](std::shared_ptr<DartIsolateGroupData>*
261 isolate_group_data,
262 std::shared_ptr<DartIsolate>* isolate_data,
263 Dart_IsolateFlags* flags, char** error) {
264 return Dart_CreateIsolateGroup(
265 (*isolate_group_data)->GetAdvisoryScriptURI().c_str(),
266 (*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(),
267 (*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(),
268 (*isolate_group_data)->GetIsolateSnapshot()->GetInstructionsMapping(),
269 flags, isolate_group_data, isolate_data, error);
270 };
271 }
272
273 vm_isolate = CreateDartIsolateGroup(std::move(isolate_group_data),
274 std::move(isolate_data), &isolate_flags,
275 error.error(), isolate_maker);
276
277 if (error) {
278 FML_LOG(ERROR) << "CreateRootIsolate failed: " << error.str();
279 }
280
281 if (vm_isolate == nullptr) {
282 return {};
283 }
284
285 std::shared_ptr<DartIsolate>* root_isolate_data =
286 static_cast<std::shared_ptr<DartIsolate>*>(Dart_IsolateData(vm_isolate));
287
288 (*root_isolate_data)
289 ->SetPlatformConfiguration(std::move(platform_configuration));
290
291 return (*root_isolate_data)->GetWeakIsolatePtr();
292}
293
294Dart_Isolate DartIsolate::CreatePlatformIsolate(Dart_Handle entry_point,
295 char** error) {
296 *error = nullptr;
298 FML_DCHECK(platform_config != nullptr);
299 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
300 platform_config->client()->GetPlatformIsolateManager();
301 std::weak_ptr<PlatformIsolateManager> weak_platform_isolate_manager =
302 platform_isolate_manager;
303 if (platform_isolate_manager->HasShutdownMaybeFalseNegative()) {
304 // Don't set the error string. We want to silently ignore this error,
305 // because the engine is shutting down.
306 FML_LOG(INFO) << "CreatePlatformIsolate called after shutdown";
307 return nullptr;
308 }
309
310 Dart_Isolate parent_isolate = isolate();
311 Dart_ExitIsolate(); // Exit parent_isolate.
312
313 const TaskRunners& task_runners = GetTaskRunners();
314 fml::RefPtr<fml::TaskRunner> platform_task_runner =
315 task_runners.GetPlatformTaskRunner();
316 FML_DCHECK(platform_task_runner);
317
318 auto isolate_group_data = std::shared_ptr<DartIsolateGroupData>(
319 *static_cast<std::shared_ptr<DartIsolateGroupData>*>(
320 Dart_IsolateGroupData(parent_isolate)));
321
322 Settings settings(isolate_group_data->GetSettings());
323
324 // PlatformIsolate.spawn should behave like Isolate.spawn when unhandled
325 // exceptions happen (log the exception, but don't terminate the app). But the
326 // default unhandled_exception_callback may terminate the app, because it is
327 // only called for the root isolate (child isolates are managed by the VM and
328 // have a different error code path). So override it to simply log the error.
329 settings.unhandled_exception_callback = [](const std::string& error,
330 const std::string& stack_trace) {
331 FML_LOG(ERROR) << "Unhandled exception:\n" << error << "\n" << stack_trace;
332 return true;
333 };
334
335 // The platform isolate task observer must be added on the platform thread. So
336 // schedule the add function on the platform task runner.
337 TaskObserverAdd old_task_observer_add = settings.task_observer_add;
338 settings.task_observer_add = [old_task_observer_add, platform_task_runner,
339 weak_platform_isolate_manager](
340 intptr_t key, const fml::closure& callback) {
341 platform_task_runner->PostTask([old_task_observer_add,
342 weak_platform_isolate_manager, key,
343 callback]() {
344 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
345 weak_platform_isolate_manager.lock();
346 if (platform_isolate_manager == nullptr ||
347 platform_isolate_manager->HasShutdown()) {
348 // Shutdown happened in between this task being posted, and it running.
349 // platform_isolate has already been shut down. Do nothing.
350 FML_LOG(INFO) << "Shutdown before platform isolate task observer added";
351 return;
352 }
353 old_task_observer_add(key, callback);
354 });
355 return platform_task_runner->GetTaskQueueId();
356 };
357
358 UIDartState::Context context(task_runners);
359 context.advisory_script_uri = isolate_group_data->GetAdvisoryScriptURI();
361 isolate_group_data->GetAdvisoryScriptEntrypoint();
362 auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
363 std::shared_ptr<DartIsolate>(
364 new DartIsolate(settings, context, platform_isolate_manager)));
365
366 IsolateMaker isolate_maker =
367 [parent_isolate](
368 std::shared_ptr<DartIsolateGroupData>* unused_isolate_group_data,
369 std::shared_ptr<DartIsolate>* isolate_data, Dart_IsolateFlags* flags,
370 char** error) {
371 return Dart_CreateIsolateInGroup(
372 /*group_member=*/parent_isolate,
373 /*name=*/"PlatformIsolate",
374 /*shutdown_callback=*/
375 reinterpret_cast<Dart_IsolateShutdownCallback>(
376 DartIsolate::SpawnIsolateShutdownCallback),
377 /*cleanup_callback=*/
378 reinterpret_cast<Dart_IsolateCleanupCallback>(
379 DartIsolateCleanupCallback),
380 /*child_isolate_data=*/isolate_data,
381 /*error=*/error);
382 };
383 Dart_Isolate platform_isolate = CreateDartIsolateGroup(
384 nullptr, std::move(isolate_data), nullptr, error, isolate_maker);
385
386 Dart_EnterIsolate(parent_isolate);
387
388 if (*error) {
389 return nullptr;
390 }
391
392 if (!platform_isolate_manager->RegisterPlatformIsolate(platform_isolate)) {
393 // The PlatformIsolateManager was shutdown while we were creating the
394 // isolate. This means that we're shutting down the engine. We need to
395 // shutdown the platform isolate.
396 FML_LOG(INFO) << "Shutdown during platform isolate creation";
397 tonic::DartIsolateScope isolate_scope(platform_isolate);
398 Dart_ShutdownIsolate();
399 return nullptr;
400 }
401
402 tonic::DartApiScope api_scope;
403 Dart_PersistentHandle entry_point_handle =
404 Dart_NewPersistentHandle(entry_point);
405
406 platform_task_runner->PostTask([entry_point_handle, platform_isolate,
407 weak_platform_isolate_manager]() {
408 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager =
409 weak_platform_isolate_manager.lock();
410 if (platform_isolate_manager == nullptr ||
411 platform_isolate_manager->HasShutdown()) {
412 // Shutdown happened in between this task being posted, and it running.
413 // platform_isolate has already been shut down. Do nothing.
414 FML_LOG(INFO) << "Shutdown before platform isolate entry point";
415 return;
416 }
417
418 tonic::DartIsolateScope isolate_scope(platform_isolate);
419 tonic::DartApiScope api_scope;
420 Dart_Handle entry_point = Dart_HandleFromPersistent(entry_point_handle);
421 Dart_DeletePersistentHandle(entry_point_handle);
422
423 // Disable Isolate.exit().
424 Dart_Handle isolate_lib = Dart_LookupLibrary(tonic::ToDart("dart:isolate"));
426 Dart_Handle isolate_type = Dart_GetNonNullableType(
427 isolate_lib, tonic::ToDart("Isolate"), 0, nullptr);
429 Dart_Handle result =
430 Dart_SetField(isolate_type, tonic::ToDart("_mayExit"), Dart_False());
432
433 tonic::DartInvokeVoid(entry_point);
434 });
435
436 return platform_isolate;
437}
438
439DartIsolate::DartIsolate(const Settings& settings,
440 bool is_root_isolate,
441 const UIDartState::Context& context,
442 bool is_spawning_in_group)
443 : UIDartState(settings.task_observer_add,
444 settings.task_observer_remove,
445 settings.log_tag,
447 settings.log_message_callback,
449 is_root_isolate,
450 context),
451 may_insecurely_connect_to_all_domains_(
452 settings.may_insecurely_connect_to_all_domains),
453 is_platform_isolate_(false),
454 is_spawning_in_group_(is_spawning_in_group),
455 domain_network_policy_(settings.domain_network_policy) {
456 phase_ = Phase::Uninitialized;
457}
458
459DartIsolate::DartIsolate(
460 const Settings& settings,
461 const UIDartState::Context& context,
462 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager)
463 : UIDartState(settings.task_observer_add,
464 settings.task_observer_remove,
465 settings.log_tag,
466 settings.unhandled_exception_callback,
467 settings.log_message_callback,
468 DartVMRef::GetIsolateNameServer(),
469 false, // is_root_isolate
470 context),
471 may_insecurely_connect_to_all_domains_(
472 settings.may_insecurely_connect_to_all_domains),
473 is_platform_isolate_(true),
474 is_spawning_in_group_(false),
475 domain_network_policy_(settings.domain_network_policy),
476 platform_isolate_manager_(std::move(platform_isolate_manager)) {
477 phase_ = Phase::Uninitialized;
478}
479
482 FML_DCHECK(GetMessageHandlingTaskRunner()->RunsTasksOnCurrentThread());
483 }
484}
485
487 return phase_;
488}
489
491 const char* service_id_buf = Dart_IsolateServiceId(isolate());
492 std::string service_id(service_id_buf);
493 free(const_cast<char*>(service_id_buf));
494 return service_id;
495}
496
497bool DartIsolate::Initialize(Dart_Isolate dart_isolate) {
498 TRACE_EVENT0("flutter", "DartIsolate::Initialize");
499 if (phase_ != Phase::Uninitialized) {
500 return false;
501 }
502
503 FML_DCHECK(dart_isolate != nullptr);
504 FML_DCHECK(dart_isolate == Dart_CurrentIsolate());
505
506 // After this point, isolate scopes can be safely used.
507 SetIsolate(dart_isolate);
508
509 // For the root isolate set the "AppStartUp" as soon as the root isolate
510 // has been initialized. This is to ensure that all the timeline events
511 // that have the set user-tag will be listed user AppStartUp.
512 if (IsRootIsolate()) {
513 tonic::DartApiScope api_scope;
514 Dart_SetCurrentUserTag(Dart_NewUserTag("AppStartUp"));
515 }
516
517 if (is_platform_isolate_) {
518 SetMessageHandlingTaskRunner(GetTaskRunners().GetPlatformTaskRunner(),
519 true);
520 } else {
521 // When running with custom UI task runner post directly to runner (there is
522 // no task queue).
523 bool post_directly_to_runner =
526 SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner(),
527 post_directly_to_runner);
528 }
529
531 Dart_SetLibraryTagHandler(tonic::DartState::HandleLibraryTag))) {
532 return false;
533 }
534
536 Dart_SetDeferredLoadHandler(OnDartLoadLibrary))) {
537 return false;
538 }
539
540 if (!UpdateThreadPoolNames()) {
541 return false;
542 }
543
544 phase_ = Phase::Initialized;
545 return true;
546}
547
549 return message_handling_task_runner_;
550}
551
553 intptr_t loading_unit_id,
554 std::unique_ptr<const fml::Mapping> snapshot_data,
555 std::unique_ptr<const fml::Mapping> snapshot_instructions) {
556 tonic::DartState::Scope scope(this);
557
558 fml::RefPtr<DartSnapshot> dart_snapshot =
560 std::move(snapshot_data), std::move(snapshot_instructions));
561
562 Dart_Handle result = Dart_DeferredLoadComplete(
563 loading_unit_id, dart_snapshot->GetDataMapping(),
564 dart_snapshot->GetInstructionsMapping());
565 if (tonic::CheckAndHandleError(result)) {
566 LoadLoadingUnitError(loading_unit_id, Dart_GetError(result),
567 /*transient*/ true);
568 return false;
569 }
570 loading_unit_snapshots_.insert(dart_snapshot);
571 return true;
572}
573
574void DartIsolate::LoadLoadingUnitError(intptr_t loading_unit_id,
575 const std::string& error_message,
576 bool transient) {
577 tonic::DartState::Scope scope(this);
578 Dart_Handle result = Dart_DeferredLoadCompleteError(
579 loading_unit_id, error_message.c_str(), transient);
581}
582
583void DartIsolate::SetMessageHandlingTaskRunner(
584 const fml::RefPtr<fml::TaskRunner>& runner,
585 bool post_directly_to_runner) {
586 if (!runner) {
587 return;
588 }
589
590 message_handling_task_runner_ = runner;
591
593
594#ifdef OS_FUCHSIA
595 post_directly_to_runner = true;
596#endif
597
598 if (post_directly_to_runner) {
599 dispatcher = [runner](std::function<void()> task) {
600 runner->PostTask([task = std::move(task)]() {
601 TRACE_EVENT0("flutter", "DartIsolate::HandleMessage");
602 task();
603 });
604 };
605 } else {
606 dispatcher = [runner](std::function<void()> task) {
607 auto task_queues = fml::MessageLoopTaskQueues::GetInstance();
608 task_queues->RegisterTask(
609 runner->GetTaskQueueId(),
610 [task = std::move(task)]() {
611 TRACE_EVENT0("flutter", "DartIsolate::HandleMessage");
612 task();
613 },
615 };
616 }
617
618 message_handler().Initialize(dispatcher);
619}
620
621// Updating thread names here does not change the underlying OS thread names.
622// Instead, this is just additional metadata for the Dart VM Service to show the
623// thread name of the isolate.
624bool DartIsolate::UpdateThreadPoolNames() const {
625 // TODO(chinmaygarde): This implementation does not account for multiple
626 // shells sharing the same (or subset of) threads.
627 const auto& task_runners = GetTaskRunners();
628
629 if (auto task_runner = task_runners.GetRasterTaskRunner()) {
630 task_runner->PostTask(
631 [label = task_runners.GetLabel() + std::string{".raster"}]() {
632 Dart_SetThreadName(label.c_str());
633 });
634 }
635
636 if (auto task_runner = task_runners.GetUITaskRunner()) {
637 task_runner->PostTask(
638 [label = task_runners.GetLabel() + std::string{".ui"}]() {
639 Dart_SetThreadName(label.c_str());
640 });
641 }
642
643 if (auto task_runner = task_runners.GetIOTaskRunner()) {
644 task_runner->PostTask(
645 [label = task_runners.GetLabel() + std::string{".io"}]() {
646 Dart_SetThreadName(label.c_str());
647 });
648 }
649
650 if (auto task_runner = task_runners.GetPlatformTaskRunner()) {
651 bool is_merged_platform_ui_thread =
652 task_runner == task_runners.GetUITaskRunner();
653 std::string label;
654 if (is_merged_platform_ui_thread) {
655 label = task_runners.GetLabel() + std::string{".ui"};
656 } else {
657 label = task_runners.GetLabel() + std::string{".platform"};
658 }
659 task_runner->PostTask(
660 [label = std::move(label)]() { Dart_SetThreadName(label.c_str()); });
661 }
662
663 return true;
664}
665
666bool DartIsolate::LoadLibraries() {
667 TRACE_EVENT0("flutter", "DartIsolate::LoadLibraries");
668 if (phase_ != Phase::Initialized) {
669 return false;
670 }
671
672 tonic::DartState::Scope scope(this);
673
674 DartIO::InitForIsolate(may_insecurely_connect_to_all_domains_,
675 domain_network_policy_);
676
677 const auto& settings = GetIsolateGroupData().GetSettings();
678
679 DartUI::InitForIsolate(settings);
680
681 const bool is_service_isolate = Dart_IsServiceIsolate(isolate());
682
683 DartRuntimeHooks::Install(IsRootIsolate() && !is_service_isolate,
684 settings.profile_microtasks,
686
687 if (!is_service_isolate) {
689 "ui", std::make_unique<tonic::DartClassProvider>(this, "dart:ui"));
690 }
691
692 phase_ = Phase::LibrariesSetup;
693 return true;
694}
695
697 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromPrecompiledCode");
698 if (phase_ != Phase::LibrariesSetup) {
699 return false;
700 }
701
702 tonic::DartState::Scope scope(this);
703
704 if (Dart_IsNull(Dart_RootLibrary())) {
705 return false;
706 }
707
708 if (!MarkIsolateRunnable()) {
709 return false;
710 }
711
712 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
714 return isolate->PrepareForRunningFromPrecompiledCode();
715 });
716 }
717
718 const fml::closure& isolate_create_callback =
720 if (isolate_create_callback) {
721 isolate_create_callback();
722 }
723
724 phase_ = Phase::Ready;
725 return true;
726}
727
728bool DartIsolate::LoadKernel(const std::shared_ptr<const fml::Mapping>& mapping,
729 bool last_piece) {
730 if (!Dart_IsKernel(mapping->GetMapping(), mapping->GetSize())) {
731 return false;
732 }
733
734 // Mapping must be retained until isolate group shutdown.
736
737 Dart_Handle library =
738 Dart_LoadLibraryFromKernel(mapping->GetMapping(), mapping->GetSize());
739 if (tonic::CheckAndHandleError(library)) {
740 return false;
741 }
742
743 if (!last_piece) {
744 // More to come.
745 return true;
746 }
747
748 Dart_SetRootLibrary(library);
749 if (tonic::CheckAndHandleError(Dart_FinalizeLoading(false))) {
750 return false;
751 }
752 return true;
753}
754
756 const std::shared_ptr<const fml::Mapping>& mapping,
757 bool child_isolate,
758 bool last_piece) {
759 TRACE_EVENT0("flutter", "DartIsolate::PrepareForRunningFromKernel");
760 if (phase_ != Phase::LibrariesSetup) {
761 return false;
762 }
763
765 return false;
766 }
767
768 tonic::DartState::Scope scope(this);
769
770 if (!child_isolate && !is_spawning_in_group_) {
771 if (!mapping || mapping->GetSize() == 0) {
772 return false;
773 }
774
775 // Use root library provided by kernel in favor of one provided by snapshot.
776 Dart_SetRootLibrary(Dart_Null());
777
778 if (!LoadKernel(mapping, last_piece)) {
779 return false;
780 }
781 }
782
783 if (!last_piece) {
784 // More to come.
785 return true;
786 }
787
788 if (Dart_IsNull(Dart_RootLibrary())) {
789 return false;
790 }
791
792 if (!MarkIsolateRunnable()) {
793 return false;
794 }
795
796 // Child isolate shares root isolate embedder_isolate (lines 691 and 693
797 // below). Re-initializing child_isolate_preparer_ lambda while it is being
798 // executed leads to crashes.
799 if (GetIsolateGroupData().GetChildIsolatePreparer() == nullptr) {
801 [buffers =
802 GetIsolateGroupData().GetKernelBuffers()](DartIsolate* isolate) {
803 for (uint64_t i = 0; i < buffers.size(); i++) {
804 bool last_piece = i + 1 == buffers.size();
805 const std::shared_ptr<const fml::Mapping>& buffer = buffers.at(i);
806 if (!isolate->PrepareForRunningFromKernel(buffer,
807 /*child_isolate=*/true,
808 last_piece)) {
809 return false;
810 }
811 }
812 return true;
813 });
814 }
815
816 const fml::closure& isolate_create_callback =
818 if (isolate_create_callback) {
819 isolate_create_callback();
820 }
821
822 phase_ = Phase::Ready;
823
824 return true;
825}
826
828 std::vector<std::shared_ptr<const fml::Mapping>> kernels) {
829 const auto count = kernels.size();
830 if (count == 0) {
831 return false;
832 }
833
834 for (size_t i = 0; i < count; ++i) {
835 bool last = (i == (count - 1));
836 if (!PrepareForRunningFromKernel(kernels[i], /*child_isolate=*/false,
837 last)) {
838 return false;
839 }
840 }
841
842 return true;
843}
844
846 std::vector<std::unique_ptr<const fml::Mapping>> kernels) {
847 std::vector<std::shared_ptr<const fml::Mapping>> shared_kernels;
848 shared_kernels.reserve(kernels.size());
849 for (auto& kernel : kernels) {
850 shared_kernels.emplace_back(std::move(kernel));
851 }
852 return PrepareForRunningFromKernels(shared_kernels);
853}
854
855bool DartIsolate::MarkIsolateRunnable() {
856 TRACE_EVENT0("flutter", "DartIsolate::MarkIsolateRunnable");
857 if (phase_ != Phase::LibrariesSetup) {
858 return false;
859 }
860
861 // This function may only be called from an active isolate scope.
862 if (Dart_CurrentIsolate() != isolate()) {
863 return false;
864 }
865
866 // There must be no current isolate to mark an isolate as being runnable.
867 Dart_ExitIsolate();
868
869 char* error = Dart_IsolateMakeRunnable(isolate());
870 if (error) {
871 FML_DLOG(ERROR) << error;
872 ::free(error);
873 // Failed. Restore the isolate.
874 Dart_EnterIsolate(isolate());
875 return false;
876 }
877 // Success. Restore the isolate.
878 Dart_EnterIsolate(isolate());
879 return true;
880}
881
882[[nodiscard]] static bool InvokeMainEntrypoint(
883 Dart_Handle user_entrypoint_function,
884 Dart_Handle args) {
885 if (tonic::CheckAndHandleError(user_entrypoint_function)) {
886 FML_LOG(ERROR) << "Could not resolve main entrypoint function.";
887 return false;
888 }
889
890 Dart_Handle start_main_isolate_function =
891 tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
892 "_getStartMainIsolateFunction", {});
893
894 if (tonic::CheckAndHandleError(start_main_isolate_function)) {
895 FML_LOG(ERROR) << "Could not resolve main entrypoint trampoline.";
896 return false;
897 }
898
900 Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMain",
901 {start_main_isolate_function, user_entrypoint_function, args}))) {
902 FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
903 return false;
904 }
905
906 return true;
907}
908
909bool DartIsolate::RunFromLibrary(std::optional<std::string> library_name,
910 std::optional<std::string> entrypoint,
911 const std::vector<std::string>& args) {
912 TRACE_EVENT0("flutter", "DartIsolate::RunFromLibrary");
913 if (phase_ != Phase::Ready) {
914 return false;
915 }
916
917 tonic::DartState::Scope scope(this);
918
919 auto library_handle =
920 library_name.has_value() && !library_name.value().empty()
921 ? ::Dart_LookupLibrary(tonic::ToDart(library_name.value().c_str()))
922 : ::Dart_RootLibrary();
923 auto entrypoint_handle = entrypoint.has_value() && !entrypoint.value().empty()
924 ? tonic::ToDart(entrypoint.value().c_str())
925 : tonic::ToDart("main");
926
928 // TODO(gaaclarke): Remove once the framework PR lands that uses `--source`
929 // to compile the Dart Plugin Registrant
930 // (https://github.com/flutter/flutter/pull/100572).
932 }
933
934 auto user_entrypoint_function =
935 ::Dart_GetField(library_handle, entrypoint_handle);
936
937 auto entrypoint_args = tonic::ToDart(args);
938
939 if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {
940 return false;
941 }
942
943 phase_ = Phase::Running;
944
945 return true;
946}
947
949 TRACE_EVENT0("flutter", "DartIsolate::Shutdown");
950 // This call may be re-entrant since Dart_ShutdownIsolate can invoke the
951 // cleanup callback which deletes the embedder side object of the dart isolate
952 // (a.k.a. this).
953 if (phase_ == Phase::Shutdown) {
954 return false;
955 }
956 phase_ = Phase::Shutdown;
957 Dart_Isolate vm_isolate = isolate();
958 // The isolate can be nullptr if this instance is the stub isolate data used
959 // during root isolate creation.
960 if (vm_isolate != nullptr) {
961 // We need to enter the isolate because Dart_ShutdownIsolate does not take
962 // the isolate to shutdown as a parameter.
963 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
964 Dart_EnterIsolate(vm_isolate);
965 Dart_ShutdownIsolate();
966 FML_DCHECK(Dart_CurrentIsolate() == nullptr);
967 }
968 return true;
969}
970
971Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
972 const char* package_root,
973 const char* package_config,
974 Dart_IsolateFlags* flags,
975 char** error) {
976 auto vm_data = DartVMRef::GetVMData();
977
978 if (!vm_data) {
980 "Could not access VM data to initialize isolates. This may be because "
981 "the VM has initialized shutdown on another thread already.");
982 return nullptr;
983 }
984
985 const auto& settings = vm_data->GetSettings();
986
987 if (!settings.enable_vm_service) {
988 return nullptr;
989 }
990
991 flags->load_vmservice_library = true;
992
993#if (FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DEBUG)
994 // TODO(68663): The service isolate in debug mode is always launched without
995 // sound null safety. Fix after the isolate snapshot data is created with the
996 // right flags.
997 flags->null_safety = vm_data->GetServiceIsolateSnapshotNullSafety();
998#endif
999
1000 UIDartState::Context context(
1001 TaskRunners("io.flutter." DART_VM_SERVICE_ISOLATE_NAME, nullptr, nullptr,
1002 nullptr, nullptr));
1003 context.advisory_script_uri = DART_VM_SERVICE_ISOLATE_NAME;
1004 context.advisory_script_entrypoint = DART_VM_SERVICE_ISOLATE_NAME;
1005 std::weak_ptr<DartIsolate> weak_service_isolate =
1006 DartIsolate::CreateRootIsolate(vm_data->GetSettings(), //
1007 vm_data->GetServiceIsolateSnapshot(), //
1008 nullptr, //
1009 DartIsolate::Flags{flags}, //
1010 nullptr, //
1011 nullptr, //
1012 context); //
1013
1014 std::shared_ptr<DartIsolate> service_isolate = weak_service_isolate.lock();
1015 if (!service_isolate) {
1016 *error = fml::strdup("Could not create the service isolate.");
1017 FML_DLOG(ERROR) << *error;
1018 return nullptr;
1019 }
1020
1021 tonic::DartState::Scope scope(service_isolate);
1023 settings.vm_service_host, // server IP address
1024 settings.vm_service_port, // server VM service port
1025 tonic::DartState::HandleLibraryTag, // embedder library tag handler
1026 false, // disable websocket origin check
1027 settings.disable_service_auth_codes, // disable VM service auth codes
1028 settings.enable_service_port_fallback, // enable fallback to port 0
1029 // when bind fails.
1030 error // error (out)
1031 )) {
1032 // Error is populated by call to startup.
1033 FML_DLOG(ERROR) << *error;
1034 return nullptr;
1035 }
1036
1037 if (auto callback = vm_data->GetSettings().service_isolate_create_callback) {
1038 callback();
1039 }
1040
1041 if (auto service_protocol = DartVMRef::GetServiceProtocol()) {
1042 service_protocol->ToggleHooks(true);
1043 } else {
1044 FML_DLOG(ERROR)
1045 << "Could not acquire the service protocol handlers. This might be "
1046 "because the VM has already begun teardown on another thread.";
1047 }
1048
1049 return service_isolate->isolate();
1050}
1051
1053 std::shared_ptr<DartIsolateGroupData>* isolate_group_data =
1054 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1055 Dart_IsolateGroupData(isolate()));
1056 return **isolate_group_data;
1057}
1058
1060 DartIsolate* non_const_this = const_cast<DartIsolate*>(this);
1061 return non_const_this->GetIsolateGroupData();
1062}
1063
1064// |Dart_IsolateGroupCreateCallback|
1065Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback(
1066 const char* advisory_script_uri,
1067 const char* advisory_script_entrypoint,
1068 const char* package_root,
1069 const char* package_config,
1070 Dart_IsolateFlags* flags,
1071 std::shared_ptr<DartIsolate>* parent_isolate_data,
1072 char** error) {
1073 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCreateCallback");
1074 if (parent_isolate_data == nullptr &&
1075 strcmp(advisory_script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
1076 // The VM attempts to start the VM service for us on |Dart_Initialize|. In
1077 // such a case, the callback data will be null and the script URI will be
1078 // DART_VM_SERVICE_ISOLATE_NAME. In such cases, we just create the service
1079 // isolate like normal but dont hold a reference to it at all. We also start
1080 // this isolate since we will never again reference it from the engine.
1081 return DartCreateAndStartServiceIsolate(package_root, //
1082 package_config, //
1083 flags, //
1084 error //
1085 );
1086 }
1087
1088 if (!parent_isolate_data) {
1089 return nullptr;
1090 }
1091
1092 DartIsolateGroupData& parent_group_data =
1093 (*parent_isolate_data)->GetIsolateGroupData();
1094
1095 if (strncmp(advisory_script_uri, kFileUriPrefix.data(),
1096 kFileUriPrefix.size())) {
1097 std::string error_msg =
1098 std::string("Unsupported isolate URI: ") + advisory_script_uri;
1099 *error = fml::strdup(error_msg.c_str());
1100 return nullptr;
1101 }
1102
1103 auto isolate_group_data =
1104 std::make_unique<std::shared_ptr<DartIsolateGroupData>>(
1105 std::shared_ptr<DartIsolateGroupData>(new DartIsolateGroupData(
1106 parent_group_data.GetSettings(),
1107 parent_group_data.GetIsolateSnapshot(), advisory_script_uri,
1108 advisory_script_entrypoint,
1109 parent_group_data.GetChildIsolatePreparer(),
1110 parent_group_data.GetIsolateCreateCallback(),
1111 parent_group_data.GetIsolateShutdownCallback())));
1112
1113 TaskRunners null_task_runners(advisory_script_uri,
1114 /* platform= */ nullptr,
1115 /* raster= */ nullptr,
1116 /* ui= */ nullptr,
1117 /* io= */ nullptr);
1118
1119 UIDartState::Context context(null_task_runners);
1120 context.advisory_script_uri = advisory_script_uri;
1121 context.advisory_script_entrypoint = advisory_script_entrypoint;
1122 auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
1123 std::shared_ptr<DartIsolate>(
1124 new DartIsolate((*isolate_group_data)->GetSettings(), // settings
1125 false, // is_root_isolate
1126 context))); // context
1127
1128 Dart_Isolate vm_isolate = CreateDartIsolateGroup(
1129 std::move(isolate_group_data), std::move(isolate_data), flags, error,
1130 [](std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1131 std::shared_ptr<DartIsolate>* isolate_data, Dart_IsolateFlags* flags,
1132 char** error) {
1133 return Dart_CreateIsolateGroup(
1134 (*isolate_group_data)->GetAdvisoryScriptURI().c_str(),
1135 (*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(),
1136 (*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(),
1137 (*isolate_group_data)
1138 ->GetIsolateSnapshot()
1139 ->GetInstructionsMapping(),
1140 flags, isolate_group_data, isolate_data, error);
1141 });
1142
1143 if (*error) {
1144 FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << *error;
1145 }
1146
1147 return vm_isolate;
1148}
1149
1150// |Dart_IsolateInitializeCallback|
1151bool DartIsolate::DartIsolateInitializeCallback(void** child_callback_data,
1152 char** error) {
1153 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateInitializeCallback");
1154 Dart_Isolate isolate = Dart_CurrentIsolate();
1155 if (isolate == nullptr) {
1156 *error = fml::strdup("Isolate should be available in initialize callback.");
1157 FML_DLOG(ERROR) << *error;
1158 return false;
1159 }
1160
1161 auto* isolate_group_data =
1162 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1163 Dart_CurrentIsolateGroupData());
1164
1165 TaskRunners null_task_runners((*isolate_group_data)->GetAdvisoryScriptURI(),
1166 /* platform= */ nullptr,
1167 /* raster= */ nullptr,
1168 /* ui= */ nullptr,
1169 /* io= */ nullptr);
1170
1171 UIDartState::Context context(null_task_runners);
1172 context.advisory_script_uri = (*isolate_group_data)->GetAdvisoryScriptURI();
1173 context.advisory_script_entrypoint =
1174 (*isolate_group_data)->GetAdvisoryScriptEntrypoint();
1175 auto embedder_isolate = std::make_unique<std::shared_ptr<DartIsolate>>(
1176 std::shared_ptr<DartIsolate>(
1177 new DartIsolate((*isolate_group_data)->GetSettings(), // settings
1178 false, // is_root_isolate
1179 context))); // context
1180
1181 // root isolate should have been created via CreateRootIsolate
1182 if (!InitializeIsolate(*embedder_isolate, isolate, error)) {
1183 return false;
1184 }
1185
1186 // The ownership of the embedder object is controlled by the Dart VM. So the
1187 // only reference returned to the caller is weak.
1188 *child_callback_data = embedder_isolate.release();
1189
1190 return true;
1191}
1192
1193static void* NativeAssetsDlopenRelative(const char* path, char** error) {
1194 auto* isolate_group_data =
1195 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1196 Dart_CurrentIsolateGroupData());
1197 const std::string& script_uri = (*isolate_group_data)->GetAdvisoryScriptURI();
1198 return dart::bin::NativeAssets::DlopenRelative(path, script_uri.data(),
1199 error);
1200}
1201
1202static void* NativeAssetsDlopen(const char* asset_id, char** error) {
1203 auto* isolate_group_data =
1204 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1205 Dart_CurrentIsolateGroupData());
1206 auto native_assets_manager = (*isolate_group_data)->GetNativeAssetsManager();
1207 if (native_assets_manager == nullptr) {
1208 return nullptr;
1209 }
1210
1211 std::vector<std::string> asset_path =
1212 native_assets_manager->LookupNativeAsset(asset_id);
1213 if (asset_path.size() == 0) {
1214 // The asset id was not in the mapping.
1215 return nullptr;
1216 }
1217
1218 auto& path_type = asset_path[0];
1219 std::string path;
1220 static constexpr const char* kAbsolute = "absolute";
1221 static constexpr const char* kExecutable = "executable";
1222 static constexpr const char* kProcess = "process";
1223 static constexpr const char* kRelative = "relative";
1224 static constexpr const char* kSystem = "system";
1225 if (path_type == kAbsolute || path_type == kRelative ||
1226 path_type == kSystem) {
1227 path = asset_path[1];
1228 }
1229
1230 if (path_type == kAbsolute) {
1231 return dart::bin::NativeAssets::DlopenAbsolute(path.c_str(), error);
1232 } else if (path_type == kRelative) {
1233 return NativeAssetsDlopenRelative(path.c_str(), error);
1234 } else if (path_type == kSystem) {
1235 return dart::bin::NativeAssets::DlopenSystem(path.c_str(), error);
1236 } else if (path_type == kProcess) {
1237 return dart::bin::NativeAssets::DlopenProcess(error);
1238 } else if (path_type == kExecutable) {
1239 return dart::bin::NativeAssets::DlopenExecutable(error);
1240 }
1241
1242 return nullptr;
1243}
1244
1246 auto* isolate_group_data =
1247 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1248 Dart_CurrentIsolateGroupData());
1249 auto native_assets_manager = (*isolate_group_data)->GetNativeAssetsManager();
1250 FML_DCHECK(native_assets_manager != nullptr);
1251 auto available_assets = native_assets_manager->AvailableNativeAssets();
1252 auto* result = fml::strdup(available_assets.c_str());
1253 return result;
1254}
1255
1257 NativeAssetsApi native_assets;
1258 memset(&native_assets, 0, sizeof(native_assets));
1259 // TODO(dacoharkes): Remove after flutter_tools stops kernel embedding.
1260 native_assets.dlopen_absolute = &dart::bin::NativeAssets::DlopenAbsolute;
1261 native_assets.dlopen_relative = &NativeAssetsDlopenRelative;
1262 native_assets.dlopen_system = &dart::bin::NativeAssets::DlopenSystem;
1263 native_assets.dlopen_executable = &dart::bin::NativeAssets::DlopenExecutable;
1264 native_assets.dlopen_process = &dart::bin::NativeAssets::DlopenProcess;
1265 // TODO(dacoharkes): End todo.
1266 native_assets.dlsym = &dart::bin::NativeAssets::Dlsym;
1267 native_assets.dlopen = &NativeAssetsDlopen;
1268 native_assets.available_assets = &NativeAssetsAvailableAssets;
1269 Dart_InitializeNativeAssetsResolver(&native_assets);
1270};
1271
1272Dart_Isolate DartIsolate::CreateDartIsolateGroup(
1273 std::unique_ptr<std::shared_ptr<DartIsolateGroupData>> isolate_group_data,
1274 std::unique_ptr<std::shared_ptr<DartIsolate>> isolate_data,
1275 Dart_IsolateFlags* flags,
1276 char** error,
1277 const DartIsolate::IsolateMaker& make_isolate) {
1278 TRACE_EVENT0("flutter", "DartIsolate::CreateDartIsolateGroup");
1279
1280 // Create the Dart VM isolate and give it the embedder object as the baton.
1281 Dart_Isolate isolate =
1282 make_isolate(isolate_group_data.get(), isolate_data.get(), flags, error);
1283
1284 if (isolate == nullptr) {
1285 return nullptr;
1286 }
1287
1288 bool success = false;
1289 {
1290 // Ownership of the isolate data objects has been transferred to the Dart
1291 // VM.
1292 // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks)
1293 std::shared_ptr<DartIsolate> embedder_isolate(*isolate_data);
1294 isolate_group_data.release();
1295 isolate_data.release();
1296 // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
1297
1299
1300 success = InitializeIsolate(embedder_isolate, isolate, error);
1301 }
1302 if (!success) {
1303 Dart_ShutdownIsolate();
1304 return nullptr;
1305 }
1306
1307 // Balances the implicit [Dart_EnterIsolate] by [make_isolate] above.
1308 Dart_ExitIsolate();
1309 return isolate;
1310}
1311
1312bool DartIsolate::InitializeIsolate(
1313 const std::shared_ptr<DartIsolate>& embedder_isolate,
1314 Dart_Isolate isolate,
1315 char** error) {
1316 TRACE_EVENT0("flutter", "DartIsolate::InitializeIsolate");
1317 if (!embedder_isolate->Initialize(isolate)) {
1318 *error = fml::strdup("Embedder could not initialize the Dart isolate.");
1319 FML_DLOG(ERROR) << *error;
1320 return false;
1321 }
1322
1323 if (!embedder_isolate->LoadLibraries()) {
1324 *error = fml::strdup(
1325 "Embedder could not load libraries in the new Dart isolate.");
1326 FML_DLOG(ERROR) << *error;
1327 return false;
1328 }
1329
1330 // Root isolates will be set up by the engine and the service isolate
1331 // (which is also a root isolate) by the utility routines in the VM.
1332 // However, secondary isolates will be run by the VM if they are
1333 // marked as runnable.
1334 if (!embedder_isolate->IsRootIsolate()) {
1335 auto child_isolate_preparer =
1336 embedder_isolate->GetIsolateGroupData().GetChildIsolatePreparer();
1337 FML_DCHECK(child_isolate_preparer);
1338 if (!child_isolate_preparer(embedder_isolate.get())) {
1339 *error = fml::strdup("Could not prepare the child isolate to run.");
1340 FML_DLOG(ERROR) << *error;
1341 return false;
1342 }
1343 }
1344
1345 return true;
1346}
1347
1348// |Dart_IsolateShutdownCallback|
1349void DartIsolate::DartIsolateShutdownCallback(
1350 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1351 std::shared_ptr<DartIsolate>* isolate_data) {
1352 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateShutdownCallback");
1353
1354 // If the isolate initialization failed there will be nothing to do.
1355 // This can happen e.g. during a [DartIsolateInitializeCallback] invocation
1356 // that fails to initialize the VM-created isolate.
1357 if (isolate_data == nullptr) {
1358 return;
1359 }
1360
1361 isolate_data->get()->OnShutdownCallback();
1362}
1363
1364// |Dart_IsolateGroupCleanupCallback|
1365void DartIsolate::DartIsolateGroupCleanupCallback(
1366 std::shared_ptr<DartIsolateGroupData>* isolate_data) {
1367 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCleanupCallback");
1368 delete isolate_data;
1369}
1370
1371// |Dart_IsolateCleanupCallback|
1372void DartIsolate::DartIsolateCleanupCallback(
1373 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1374 std::shared_ptr<DartIsolate>* isolate_data) {
1375 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateCleanupCallback");
1376 delete isolate_data;
1377}
1378
1379std::weak_ptr<DartIsolate> DartIsolate::GetWeakIsolatePtr() {
1380 return std::static_pointer_cast<DartIsolate>(shared_from_this());
1381}
1382
1384 tonic::DartIsolateScope isolate_scope(isolate());
1385 Dart_SetCurrentThreadOwnsIsolate();
1386}
1387
1389 shutdown_callbacks_.emplace_back(std::make_unique<AutoFireClosure>(closure));
1390}
1391
1392void DartIsolate::OnShutdownCallback() {
1394 if (state != nullptr) {
1395 state->SetIsShuttingDown();
1396 }
1397
1398 {
1399 tonic::DartApiScope api_scope;
1400 Dart_Handle sticky_error = Dart_GetStickyError();
1401 if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
1402 FML_LOG(ERROR) << Dart_GetError(sticky_error);
1403 }
1404 }
1405
1406 if (is_platform_isolate_) {
1407 FML_DCHECK(platform_isolate_manager_ != nullptr);
1408 platform_isolate_manager_->RemovePlatformIsolate(isolate());
1409 }
1410
1411 shutdown_callbacks_.clear();
1412
1413 const fml::closure& isolate_shutdown_callback =
1415 if (isolate_shutdown_callback) {
1416 isolate_shutdown_callback();
1417 }
1418}
1419
1420Dart_Handle DartIsolate::OnDartLoadLibrary(intptr_t loading_unit_id) {
1423 loading_unit_id);
1424 return Dart_Null();
1425 }
1426 const std::string error_message =
1427 "Platform Configuration was null. Deferred library load request "
1428 "for loading unit id " +
1429 std::to_string(loading_unit_id) + " was not sent.";
1430 FML_LOG(ERROR) << error_message;
1431 return Dart_NewApiError(error_message.c_str());
1432}
1433
1435 const std::shared_ptr<const fml::Mapping>& mapping) {
1437 return Dart_Null();
1438 }
1439
1440 auto* isolate_group_data =
1441 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1442 Dart_CurrentIsolateGroupData());
1443 // Mapping must be retained until isolate shutdown.
1444 (*isolate_group_data)->AddKernelBuffer(mapping);
1445
1446 auto lib =
1447 Dart_LoadLibraryFromKernel(mapping->GetMapping(), mapping->GetSize());
1448 if (tonic::CheckAndHandleError(lib)) {
1449 return Dart_Null();
1450 }
1451 auto result = Dart_FinalizeLoading(false);
1452 if (Dart_IsError(result)) {
1453 return result;
1454 }
1455 return Dart_GetField(lib, Dart_NewStringFromCString("main"));
1456}
1457
1458DartIsolate::AutoFireClosure::AutoFireClosure(const fml::closure& closure)
1459 : closure_(closure) {}
1460
1461DartIsolate::AutoFireClosure::~AutoFireClosure() {
1462 if (closure_) {
1463 closure_();
1464 }
1465}
1466
1467} // namespace flutter
static void InitForIsolate(bool may_insecurely_connect_to_all_domains, const std::string &domain_network_policy)
Definition dart_io.cc:18
void SetNullSafetyEnabled(bool enabled)
void SetIsDontNeedSafe(bool value)
const fml::closure & GetIsolateShutdownCallback() const
void SetChildIsolatePreparer(const ChildIsolatePreparer &value)
const fml::closure & GetIsolateCreateCallback() const
void AddKernelBuffer(const std::shared_ptr< const fml::Mapping > &buffer)
Adds a kernel buffer mapping to the kernels loaded for this isolate group.
Represents an instance of a live isolate. An isolate is a separate Dart execution context....
bool PrepareForRunningFromKernel(const std::shared_ptr< const fml::Mapping > &kernel, bool child_isolate, bool last_piece)
Prepare the isolate for running for a a list of kernel files.
std::string GetServiceId()
Returns the ID for an isolate which is used to query the service protocol.
void LoadLoadingUnitError(intptr_t loading_unit_id, const std::string &error_message, bool transient)
std::weak_ptr< DartIsolate > GetWeakIsolatePtr()
A weak pointer to the Dart isolate instance. This instance may only be used on the task runner that c...
Dart_Isolate CreatePlatformIsolate(Dart_Handle entry_point, char **error) override
Creates a new isolate in the same group as this isolate, which runs on the platform thread....
bool PrepareForRunningFromKernels(std::vector< std::shared_ptr< const fml::Mapping > > kernels)
Prepare the isolate for running for a a list of kernel files.
static Dart_Handle LoadLibraryFromKernel(const std::shared_ptr< const fml::Mapping > &mapping)
bool RunFromLibrary(std::optional< std::string > library_name, std::optional< std::string > entrypoint, const std::vector< std::string > &args)
Transition the root isolate to the Phase::Running phase and invoke the main entrypoint (the "main" me...
DartIsolateGroupData & GetIsolateGroupData()
void AddIsolateShutdownCallback(const fml::closure &closure)
Registers a callback that will be invoked in isolate scope just before the isolate transitions to the...
fml::RefPtr< fml::TaskRunner > GetMessageHandlingTaskRunner() const
The task runner on which the Dart code for the root isolate is running. For the root isolate,...
bool Shutdown()
Transition the isolate to the Phase::Shutdown phase. The only thing left to do is to collect the isol...
Phase GetPhase() const
The current phase of the isolate. The engine represents all dart isolates as being in one of the know...
static std::weak_ptr< DartIsolate > CreateRunningRootIsolate(const Settings &settings, const fml::RefPtr< const DartSnapshot > &isolate_snapshot, std::unique_ptr< PlatformConfiguration > platform_configuration, Flags flags, const fml::closure &root_isolate_create_callback, const fml::closure &isolate_create_callback, const fml::closure &isolate_shutdown_callback, std::optional< std::string > dart_entrypoint, std::optional< std::string > dart_entrypoint_library, const std::vector< std::string > &dart_entrypoint_args, std::unique_ptr< IsolateConfiguration > isolate_configuration, const UIDartState::Context &context, const DartIsolate *spawning_isolate=nullptr, std::shared_ptr< NativeAssetsManager > native_assets_manager=nullptr)
Creates an instance of a root isolate and returns a weak pointer to the same. The isolate instance ma...
bool PrepareForRunningFromPrecompiledCode()
Prepare the isolate for running for a precompiled code bundle. The Dart VM must be configured for run...
bool LoadLoadingUnit(intptr_t loading_unit_id, std::unique_ptr< const fml::Mapping > snapshot_data, std::unique_ptr< const fml::Mapping > snapshot_instructions)
Phase
The engine represents all dart isolates as being in one of the known phases. By invoking various meth...
static void Install(bool is_ui_isolate, bool enable_microtask_profiling, const std::string &script_uri)
static bool Startup(const std::string &server_ip, intptr_t server_port, Dart_LibraryTagHandler embedder_tag_handler, bool disable_origin_check, bool disable_service_auth_codes, bool enable_service_port_fallback, char **error)
Start the service isolate. This call may only be made in the Dart VM initiated isolate creation callb...
static fml::RefPtr< DartSnapshot > IsolateSnapshotFromMappings(const std::shared_ptr< const fml::Mapping > &snapshot_data, const std::shared_ptr< const fml::Mapping > &snapshot_instructions)
Create an isolate snapshot from existing fml::Mappings.
static void InitForIsolate(const Settings &settings)
Definition dart_ui.cc:350
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition dart_vm.cc:176
static std::shared_ptr< ServiceProtocol > GetServiceProtocol()
static std::shared_ptr< const DartVMData > GetVMData()
virtual std::shared_ptr< PlatformIsolateManager > GetPlatformIsolateManager()=0
virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id)=0
Invoked when the Dart VM requests that a deferred library be loaded. Notifies the engine that the def...
A class for holding and distributing platform-level information to and from the Dart code in Flutter'...
PlatformConfigurationClient * client() const
Access to the platform configuration client (which typically is implemented by the RuntimeController)...
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
PlatformConfiguration * platform_configuration() const
UnhandledExceptionCallback unhandled_exception_callback() const
bool IsRootIsolate() const
const TaskRunners & GetTaskRunners() const
std::shared_ptr< IsolateNameServer > GetIsolateNameServer() const
const std::string & GetAdvisoryScriptURI() const
static UIDartState * Current()
static MessageLoopTaskQueues * GetInstance()
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition closure.h:32
bool is_valid() const
virtual TaskQueueId GetTaskQueueId()
static TimePoint Now()
Definition time_point.cc:49
void add_provider(const std::string &library_name, std::unique_ptr< DartClassProvider > provider)
std::function< void(std::function< void(void)>)> TaskDispatcher
void Initialize(TaskDispatcher dispatcher)
Dart_Isolate isolate()
Definition dart_state.h:51
void SetIsolate(Dart_Isolate isolate)
Definition dart_state.cc:35
DartMessageHandler & message_handler()
Definition dart_state.h:61
void SetIsShuttingDown()
Definition dart_state.h:73
static DartState * Current()
Definition dart_state.cc:56
DartClassLibrary & class_library()
Definition dart_state.h:60
static Dart_Handle HandleLibraryTag(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition dart_state.cc:79
int32_t value
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
FlutterDesktopBinaryReply callback
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
static void * NativeAssetsDlopenRelative(const char *path, char **error)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
static void InitDartFFIForIsolateGroup()
static void * NativeAssetsDlopen(const char *asset_id, char **error)
static char * NativeAssetsAvailableAssets()
constexpr char kFileUriPrefix[]
Definition dart_vm.cc:118
bool InvokeDartPluginRegistrantIfAvailable(Dart_Handle library_handle)
std::function< fml::TaskQueueId(intptr_t, fml::closure)> TaskObserverAdd
Definition settings.h:75
bool FindAndInvokeDartPluginRegistrant()
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function, Dart_Handle args)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
char * strdup(const char *str1)
std::function< void()> closure
Definition closure.h:14
Definition ref_ptr.h:261
Dart_Handle ToDart(const T &object)
Dart_Handle DartInvokeVoid(Dart_Handle closure)
bool CheckAndHandleError(Dart_Handle handle)
Definition dart_error.cc:33
Dart_Handle DartInvokeField(Dart_Handle target, const char *name, std::initializer_list< Dart_Handle > args)
std::function< void(const DartIsolate &)> root_isolate_create_callback
Definition settings.h:285
MergedPlatformUIThread merged_platform_ui_thread
Definition settings.h:379
TaskObserverAdd task_observer_add
Definition settings.h:281
UnhandledExceptionCallback unhandled_exception_callback
Definition settings.h:311
fml::closure root_isolate_shutdown_callback
Definition settings.h:291
The subset of state which is owned by the shell or engine and passed through the RuntimeController in...
#define TRACE_EVENT0(category_group, name)