Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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,
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();
360 context.advisory_script_entrypoint =
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,
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_, GetAdvisoryScriptURI());
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 settings
1027 .disable_service_origin_check, // disable websocket origin check
1028 settings.disable_service_auth_codes, // disable VM service auth codes
1029 settings.enable_service_port_fallback, // enable fallback to port 0
1030 // when bind fails.
1031 error // error (out)
1032 )) {
1033 // Error is populated by call to startup.
1034 FML_DLOG(ERROR) << *error;
1035 return nullptr;
1036 }
1037
1038 if (auto callback = vm_data->GetSettings().service_isolate_create_callback) {
1039 callback();
1040 }
1041
1042 if (auto service_protocol = DartVMRef::GetServiceProtocol()) {
1043 service_protocol->ToggleHooks(true);
1044 } else {
1045 FML_DLOG(ERROR)
1046 << "Could not acquire the service protocol handlers. This might be "
1047 "because the VM has already begun teardown on another thread.";
1048 }
1049
1050 return service_isolate->isolate();
1051}
1052
1054 std::shared_ptr<DartIsolateGroupData>* isolate_group_data =
1055 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1056 Dart_IsolateGroupData(isolate()));
1057 return **isolate_group_data;
1058}
1059
1061 DartIsolate* non_const_this = const_cast<DartIsolate*>(this);
1062 return non_const_this->GetIsolateGroupData();
1063}
1064
1065// |Dart_IsolateGroupCreateCallback|
1066Dart_Isolate DartIsolate::DartIsolateGroupCreateCallback(
1067 const char* advisory_script_uri,
1068 const char* advisory_script_entrypoint,
1069 const char* package_root,
1070 const char* package_config,
1071 Dart_IsolateFlags* flags,
1072 std::shared_ptr<DartIsolate>* parent_isolate_data,
1073 char** error) {
1074 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCreateCallback");
1075 if (parent_isolate_data == nullptr &&
1076 strcmp(advisory_script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
1077 // The VM attempts to start the VM service for us on |Dart_Initialize|. In
1078 // such a case, the callback data will be null and the script URI will be
1079 // DART_VM_SERVICE_ISOLATE_NAME. In such cases, we just create the service
1080 // isolate like normal but dont hold a reference to it at all. We also start
1081 // this isolate since we will never again reference it from the engine.
1082 return DartCreateAndStartServiceIsolate(package_root, //
1083 package_config, //
1084 flags, //
1085 error //
1086 );
1087 }
1088
1089 if (!parent_isolate_data) {
1090 return nullptr;
1091 }
1092
1093 DartIsolateGroupData& parent_group_data =
1094 (*parent_isolate_data)->GetIsolateGroupData();
1095
1096 if (strncmp(advisory_script_uri, kFileUriPrefix.data(),
1097 kFileUriPrefix.size())) {
1098 std::string error_msg =
1099 std::string("Unsupported isolate URI: ") + advisory_script_uri;
1100 *error = fml::strdup(error_msg.c_str());
1101 return nullptr;
1102 }
1103
1104 auto isolate_group_data =
1105 std::make_unique<std::shared_ptr<DartIsolateGroupData>>(
1106 std::shared_ptr<DartIsolateGroupData>(new DartIsolateGroupData(
1107 parent_group_data.GetSettings(),
1108 parent_group_data.GetIsolateSnapshot(), advisory_script_uri,
1109 advisory_script_entrypoint,
1110 parent_group_data.GetChildIsolatePreparer(),
1111 parent_group_data.GetIsolateCreateCallback(),
1112 parent_group_data.GetIsolateShutdownCallback())));
1113
1114 TaskRunners null_task_runners(advisory_script_uri,
1115 /* platform= */ nullptr,
1116 /* raster= */ nullptr,
1117 /* ui= */ nullptr,
1118 /* io= */ nullptr);
1119
1120 UIDartState::Context context(null_task_runners);
1121 context.advisory_script_uri = advisory_script_uri;
1122 context.advisory_script_entrypoint = advisory_script_entrypoint;
1123 auto isolate_data = std::make_unique<std::shared_ptr<DartIsolate>>(
1124 std::shared_ptr<DartIsolate>(
1125 new DartIsolate((*isolate_group_data)->GetSettings(), // settings
1126 false, // is_root_isolate
1127 context))); // context
1128
1129 Dart_Isolate vm_isolate = CreateDartIsolateGroup(
1130 std::move(isolate_group_data), std::move(isolate_data), flags, error,
1131 [](std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1132 std::shared_ptr<DartIsolate>* isolate_data, Dart_IsolateFlags* flags,
1133 char** error) {
1134 return Dart_CreateIsolateGroup(
1135 (*isolate_group_data)->GetAdvisoryScriptURI().c_str(),
1136 (*isolate_group_data)->GetAdvisoryScriptEntrypoint().c_str(),
1137 (*isolate_group_data)->GetIsolateSnapshot()->GetDataMapping(),
1138 (*isolate_group_data)
1139 ->GetIsolateSnapshot()
1140 ->GetInstructionsMapping(),
1141 flags, isolate_group_data, isolate_data, error);
1142 });
1143
1144 if (*error) {
1145 FML_LOG(ERROR) << "CreateDartIsolateGroup failed: " << *error;
1146 }
1147
1148 return vm_isolate;
1149}
1150
1151// |Dart_IsolateInitializeCallback|
1152bool DartIsolate::DartIsolateInitializeCallback(void** child_callback_data,
1153 char** error) {
1154 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateInitializeCallback");
1155 Dart_Isolate isolate = Dart_CurrentIsolate();
1156 if (isolate == nullptr) {
1157 *error = fml::strdup("Isolate should be available in initialize callback.");
1158 FML_DLOG(ERROR) << *error;
1159 return false;
1160 }
1161
1162 auto* isolate_group_data =
1163 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1164 Dart_CurrentIsolateGroupData());
1165
1166 TaskRunners null_task_runners((*isolate_group_data)->GetAdvisoryScriptURI(),
1167 /* platform= */ nullptr,
1168 /* raster= */ nullptr,
1169 /* ui= */ nullptr,
1170 /* io= */ nullptr);
1171
1172 UIDartState::Context context(null_task_runners);
1173 context.advisory_script_uri = (*isolate_group_data)->GetAdvisoryScriptURI();
1174 context.advisory_script_entrypoint =
1175 (*isolate_group_data)->GetAdvisoryScriptEntrypoint();
1176 auto embedder_isolate = std::make_unique<std::shared_ptr<DartIsolate>>(
1177 std::shared_ptr<DartIsolate>(
1178 new DartIsolate((*isolate_group_data)->GetSettings(), // settings
1179 false, // is_root_isolate
1180 context))); // context
1181
1182 // root isolate should have been created via CreateRootIsolate
1183 if (!InitializeIsolate(*embedder_isolate, isolate, error)) {
1184 return false;
1185 }
1186
1187 // The ownership of the embedder object is controlled by the Dart VM. So the
1188 // only reference returned to the caller is weak.
1189 *child_callback_data = embedder_isolate.release();
1190
1191 return true;
1192}
1193
1194static void* NativeAssetsDlopenRelative(const char* path, char** error) {
1195 auto* isolate_group_data =
1196 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1197 Dart_CurrentIsolateGroupData());
1198 const std::string& script_uri = (*isolate_group_data)->GetAdvisoryScriptURI();
1199 return dart::bin::NativeAssets::DlopenRelative(path, script_uri.data(),
1200 error);
1201}
1202
1203static void* NativeAssetsDlopen(const char* asset_id, char** error) {
1204 auto* isolate_group_data =
1205 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1206 Dart_CurrentIsolateGroupData());
1207 auto native_assets_manager = (*isolate_group_data)->GetNativeAssetsManager();
1208 if (native_assets_manager == nullptr) {
1209 return nullptr;
1210 }
1211
1212 std::vector<std::string> asset_path =
1213 native_assets_manager->LookupNativeAsset(asset_id);
1214 if (asset_path.size() == 0) {
1215 // The asset id was not in the mapping.
1216 return nullptr;
1217 }
1218
1219 auto& path_type = asset_path[0];
1220 std::string path;
1221 static constexpr const char* kAbsolute = "absolute";
1222 static constexpr const char* kExecutable = "executable";
1223 static constexpr const char* kProcess = "process";
1224 static constexpr const char* kRelative = "relative";
1225 static constexpr const char* kSystem = "system";
1226 if (path_type == kAbsolute || path_type == kRelative ||
1227 path_type == kSystem) {
1228 path = asset_path[1];
1229 }
1230
1231 if (path_type == kAbsolute) {
1232 return dart::bin::NativeAssets::DlopenAbsolute(path.c_str(), error);
1233 } else if (path_type == kRelative) {
1234 return NativeAssetsDlopenRelative(path.c_str(), error);
1235 } else if (path_type == kSystem) {
1236 return dart::bin::NativeAssets::DlopenSystem(path.c_str(), error);
1237 } else if (path_type == kProcess) {
1238 return dart::bin::NativeAssets::DlopenProcess(error);
1239 } else if (path_type == kExecutable) {
1240 return dart::bin::NativeAssets::DlopenExecutable(error);
1241 }
1242
1243 return nullptr;
1244}
1245
1247 auto* isolate_group_data =
1248 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1249 Dart_CurrentIsolateGroupData());
1250 auto native_assets_manager = (*isolate_group_data)->GetNativeAssetsManager();
1251 FML_DCHECK(native_assets_manager != nullptr);
1252 auto available_assets = native_assets_manager->AvailableNativeAssets();
1253 auto* result = fml::strdup(available_assets.c_str());
1254 return result;
1255}
1256
1258 NativeAssetsApi native_assets;
1259 memset(&native_assets, 0, sizeof(native_assets));
1260 // TODO(dacoharkes): Remove after flutter_tools stops kernel embedding.
1261 native_assets.dlopen_absolute = &dart::bin::NativeAssets::DlopenAbsolute;
1262 native_assets.dlopen_relative = &NativeAssetsDlopenRelative;
1263 native_assets.dlopen_system = &dart::bin::NativeAssets::DlopenSystem;
1264 native_assets.dlopen_executable = &dart::bin::NativeAssets::DlopenExecutable;
1265 native_assets.dlopen_process = &dart::bin::NativeAssets::DlopenProcess;
1266 // TODO(dacoharkes): End todo.
1267 native_assets.dlsym = &dart::bin::NativeAssets::Dlsym;
1268 native_assets.dlopen = &NativeAssetsDlopen;
1269 native_assets.available_assets = &NativeAssetsAvailableAssets;
1270 Dart_InitializeNativeAssetsResolver(&native_assets);
1271};
1272
1273Dart_Isolate DartIsolate::CreateDartIsolateGroup(
1274 std::unique_ptr<std::shared_ptr<DartIsolateGroupData>> isolate_group_data,
1275 std::unique_ptr<std::shared_ptr<DartIsolate>> isolate_data,
1276 Dart_IsolateFlags* flags,
1277 char** error,
1278 const DartIsolate::IsolateMaker& make_isolate) {
1279 TRACE_EVENT0("flutter", "DartIsolate::CreateDartIsolateGroup");
1280
1281 // Create the Dart VM isolate and give it the embedder object as the baton.
1282 Dart_Isolate isolate =
1283 make_isolate(isolate_group_data.get(), isolate_data.get(), flags, error);
1284
1285 if (isolate == nullptr) {
1286 return nullptr;
1287 }
1288
1289 bool success = false;
1290 {
1291 // Ownership of the isolate data objects has been transferred to the Dart
1292 // VM.
1293 // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks)
1294 std::shared_ptr<DartIsolate> embedder_isolate(*isolate_data);
1295 isolate_group_data.release();
1296 isolate_data.release();
1297 // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
1298
1300
1301 success = InitializeIsolate(embedder_isolate, isolate, error);
1302 }
1303 if (!success) {
1304 Dart_ShutdownIsolate();
1305 return nullptr;
1306 }
1307
1308 // Balances the implicit [Dart_EnterIsolate] by [make_isolate] above.
1309 Dart_ExitIsolate();
1310 return isolate;
1311}
1312
1313bool DartIsolate::InitializeIsolate(
1314 const std::shared_ptr<DartIsolate>& embedder_isolate,
1315 Dart_Isolate isolate,
1316 char** error) {
1317 TRACE_EVENT0("flutter", "DartIsolate::InitializeIsolate");
1318 if (!embedder_isolate->Initialize(isolate)) {
1319 *error = fml::strdup("Embedder could not initialize the Dart isolate.");
1320 FML_DLOG(ERROR) << *error;
1321 return false;
1322 }
1323
1324 if (!embedder_isolate->LoadLibraries()) {
1325 *error = fml::strdup(
1326 "Embedder could not load libraries in the new Dart isolate.");
1327 FML_DLOG(ERROR) << *error;
1328 return false;
1329 }
1330
1331 // Root isolates will be set up by the engine and the service isolate
1332 // (which is also a root isolate) by the utility routines in the VM.
1333 // However, secondary isolates will be run by the VM if they are
1334 // marked as runnable.
1335 if (!embedder_isolate->IsRootIsolate()) {
1336 auto child_isolate_preparer =
1337 embedder_isolate->GetIsolateGroupData().GetChildIsolatePreparer();
1338 FML_DCHECK(child_isolate_preparer);
1339 if (!child_isolate_preparer(embedder_isolate.get())) {
1340 *error = fml::strdup("Could not prepare the child isolate to run.");
1341 FML_DLOG(ERROR) << *error;
1342 return false;
1343 }
1344 }
1345
1346 return true;
1347}
1348
1349// |Dart_IsolateShutdownCallback|
1350void DartIsolate::DartIsolateShutdownCallback(
1351 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1352 std::shared_ptr<DartIsolate>* isolate_data) {
1353 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateShutdownCallback");
1354
1355 // If the isolate initialization failed there will be nothing to do.
1356 // This can happen e.g. during a [DartIsolateInitializeCallback] invocation
1357 // that fails to initialize the VM-created isolate.
1358 if (isolate_data == nullptr) {
1359 return;
1360 }
1361
1362 isolate_data->get()->OnShutdownCallback();
1363}
1364
1365// |Dart_IsolateGroupCleanupCallback|
1366void DartIsolate::DartIsolateGroupCleanupCallback(
1367 std::shared_ptr<DartIsolateGroupData>* isolate_data) {
1368 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateGroupCleanupCallback");
1369 delete isolate_data;
1370}
1371
1372// |Dart_IsolateCleanupCallback|
1373void DartIsolate::DartIsolateCleanupCallback(
1374 std::shared_ptr<DartIsolateGroupData>* isolate_group_data,
1375 std::shared_ptr<DartIsolate>* isolate_data) {
1376 TRACE_EVENT0("flutter", "DartIsolate::DartIsolateCleanupCallback");
1377 delete isolate_data;
1378}
1379
1380std::weak_ptr<DartIsolate> DartIsolate::GetWeakIsolatePtr() {
1381 return std::static_pointer_cast<DartIsolate>(shared_from_this());
1382}
1383
1385 tonic::DartIsolateScope isolate_scope(isolate());
1386 Dart_SetCurrentThreadOwnsIsolate();
1387}
1388
1390 shutdown_callbacks_.emplace_back(std::make_unique<AutoFireClosure>(closure));
1391}
1392
1393void DartIsolate::OnShutdownCallback() {
1395 if (state != nullptr) {
1396 state->SetIsShuttingDown();
1397 }
1398
1399 {
1400 tonic::DartApiScope api_scope;
1401 Dart_Handle sticky_error = Dart_GetStickyError();
1402 if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) {
1403 FML_LOG(ERROR) << Dart_GetError(sticky_error);
1404 }
1405 }
1406
1407 if (is_platform_isolate_) {
1408 FML_DCHECK(platform_isolate_manager_ != nullptr);
1409 platform_isolate_manager_->RemovePlatformIsolate(isolate());
1410 }
1411
1412 shutdown_callbacks_.clear();
1413
1414 const fml::closure& isolate_shutdown_callback =
1416 if (isolate_shutdown_callback) {
1417 isolate_shutdown_callback();
1418 }
1419}
1420
1421Dart_Handle DartIsolate::OnDartLoadLibrary(intptr_t loading_unit_id) {
1424 loading_unit_id);
1425 return Dart_Null();
1426 }
1427 const std::string error_message =
1428 "Platform Configuration was null. Deferred library load request "
1429 "for loading unit id " +
1430 std::to_string(loading_unit_id) + " was not sent.";
1431 FML_LOG(ERROR) << error_message;
1432 return Dart_NewApiError(error_message.c_str());
1433}
1434
1436 const std::shared_ptr<const fml::Mapping>& mapping) {
1438 return Dart_Null();
1439 }
1440
1441 auto* isolate_group_data =
1442 static_cast<std::shared_ptr<DartIsolateGroupData>*>(
1443 Dart_CurrentIsolateGroupData());
1444 // Mapping must be retained until isolate shutdown.
1445 (*isolate_group_data)->AddKernelBuffer(mapping);
1446
1447 auto lib =
1448 Dart_LoadLibraryFromKernel(mapping->GetMapping(), mapping->GetSize());
1449 if (tonic::CheckAndHandleError(lib)) {
1450 return Dart_Null();
1451 }
1452 auto result = Dart_FinalizeLoading(false);
1453 if (Dart_IsError(result)) {
1454 return result;
1455 }
1456 return Dart_GetField(lib, Dart_NewStringFromCString("main"));
1457}
1458
1459DartIsolate::AutoFireClosure::AutoFireClosure(const fml::closure& closure)
1460 : closure_(closure) {}
1461
1462DartIsolate::AutoFireClosure::~AutoFireClosure() {
1463 if (closure_) {
1464 closure_();
1465 }
1466}
1467
1468} // namespace flutter
static void InitForIsolate(bool may_insecurely_connect_to_all_domains, const std::string &domain_network_policy, const std::string &script_uri)
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:351
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:177
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:119
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::shared_ptr< ContextGLES > context
std::function< void(const DartIsolate &)> root_isolate_create_callback
Definition settings.h:288
MergedPlatformUIThread merged_platform_ui_thread
Definition settings.h:382
TaskObserverAdd task_observer_add
Definition settings.h:284
UnhandledExceptionCallback unhandled_exception_callback
Definition settings.h:314
fml::closure root_isolate_shutdown_callback
Definition settings.h:294
The subset of state which is owned by the shell or engine and passed through the RuntimeController in...
#define TRACE_EVENT0(category_group, name)