Flutter Engine
The Flutter Engine
dart_component_controller.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 <fcntl.h>
8#include <lib/async-loop/loop.h>
9#include <lib/async/cpp/task.h>
10#include <lib/async/default.h>
11#include <lib/fdio/directory.h>
12#include <lib/fdio/fd.h>
13#include <lib/fdio/namespace.h>
14#include <lib/fidl/cpp/string.h>
15#include <lib/sys/cpp/service_directory.h>
16#include <lib/vfs/cpp/composed_service_dir.h>
17#include <lib/vfs/cpp/remote_dir.h>
18#include <lib/zx/clock.h>
19#include <lib/zx/thread.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
23#include <zircon/status.h>
24
25#include <regex>
26#include <utility>
27
28#include "dart_api.h"
29#include "flutter/fml/logging.h"
33#include "third_party/dart/runtime/include/dart_tools_api.h"
40
41#include "builtin_libraries.h"
42
43using tonic::ToDart;
44
45namespace dart_runner {
46
47namespace {
48
49constexpr char kTmpPath[] = "/tmp";
50
51constexpr zx::duration kIdleWaitDuration = zx::sec(2);
52constexpr zx::duration kIdleNotifyDuration = zx::msec(500);
53constexpr zx::duration kIdleSlack = zx::sec(1);
54
55void AfterTask(async_loop_t*, void*) {
58 // Verify that the queue exists, as this method could have been called back as
59 // part of the exit routine, after the destruction of the microtask queue.
60 if (queue) {
61 queue->RunMicrotasks();
62 }
63}
64
65constexpr async_loop_config_t kLoopConfig = {
66 .default_accessors =
67 {
68 .getter = async_get_default_dispatcher,
69 .setter = async_set_default_dispatcher,
70 },
71 .make_default_for_current_thread = true,
72 .epilogue = &AfterTask,
73};
74
75// Find the last path of the component.
76// fuchsia-pkg://fuchsia.com/hello_dart#meta/hello_dart.cmx -> hello_dart.cmx
77std::string GetLabelFromUrl(const std::string& url) {
78 for (size_t i = url.length() - 1; i > 0; i--) {
79 if (url[i] == '/') {
80 return url.substr(i + 1, url.length() - 1);
81 }
82 }
83 return url;
84}
85
86// Find the name of the component.
87// fuchsia-pkg://fuchsia.com/hello_dart#meta/hello_dart.cm -> hello_dart
88std::string GetComponentNameFromUrl(const std::string& url) {
89 const std::string label = GetLabelFromUrl(url);
90 for (size_t i = 0; i < label.length(); ++i) {
91 if (label[i] == '.') {
92 return label.substr(0, i);
93 }
94 }
95 return label;
96}
97
98} // namespace
99
101 fuchsia::component::runner::ComponentStartInfo start_info,
102 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
103 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
104 controller)
105 : loop_(new async::Loop(&kLoopConfig)),
106 label_(GetLabelFromUrl(start_info.resolved_url())),
107 url_(start_info.resolved_url()),
108 runner_incoming_services_(std::move(runner_incoming_services)),
109 dart_outgoing_dir_(new vfs::PseudoDir()),
110 start_info_(std::move(start_info)),
111 binding_(this, std::move(controller)) {
112 binding_.set_error_handler([this](zx_status_t status) { Kill(); });
113
114 // TODO(fxb/84537): This data path is configured based how we build Flutter
115 // applications in tree currently, but the way we build the Flutter
116 // application may change. We should avoid assuming the data path and let the
117 // CML file specify this data path instead.
118 const std::string component_name = GetComponentNameFromUrl(url_);
119 data_path_ = "pkg/data/" + component_name;
120
121 zx_status_t idle_timer_status =
122 zx::timer::create(ZX_TIMER_SLACK_LATE, ZX_CLOCK_MONOTONIC, &idle_timer_);
123 if (idle_timer_status != ZX_OK) {
124 FML_LOG(INFO) << "Idle timer creation failed: "
125 << zx_status_get_string(idle_timer_status);
126 } else {
127 idle_wait_.set_object(idle_timer_.get());
128 idle_wait_.set_trigger(ZX_TIMER_SIGNALED);
129 idle_wait_.Begin(async_get_default_dispatcher());
130 }
131
132 // Close the runtime_dir channel if we don't intend to serve it. Otherwise any
133 // access to the runtime_dir will hang forever.
134 start_info_.clear_runtime_dir();
135}
136
138 if (namespace_) {
139 fdio_ns_destroy(namespace_);
140 namespace_ = nullptr;
141 }
142 close(stdout_fd_);
143 close(stderr_fd_);
144}
145
147 // Name the thread after the url of the component being launched.
148 zx::thread::self()->set_property(ZX_PROP_NAME, label_.c_str(), label_.size());
149 Dart_SetThreadName(label_.c_str());
150
151 if (!CreateAndBindNamespace()) {
152 return false;
153 }
154
155 if (SetUpFromAppSnapshot()) {
156 FML_LOG(INFO) << url_ << " is running from an app snapshot";
157 } else if (SetUpFromKernel()) {
158 FML_LOG(INFO) << url_ << " is running from kernel";
159 } else {
160 FML_LOG(ERROR) << "Failed to set up component controller for " << url_;
161 return false;
162 }
163
164 return true;
165}
166
167bool DartComponentController::CreateAndBindNamespace() {
168 if (!start_info_.has_ns()) {
169 FML_LOG(ERROR) << "Component start info does not have a namespace.";
170 return false;
171 }
172
173 const zx_status_t ns_create_status = fdio_ns_create(&namespace_);
174 if (ns_create_status != ZX_OK) {
175 FML_LOG(ERROR) << "Failed to create namespace: "
176 << zx_status_get_string(ns_create_status);
177 }
178
179 dart_utils::BindTemp(namespace_);
180
181 // Bind each directory in start_info's namespace to the controller's namespace
182 // instance.
183 for (auto& ns_entry : *start_info_.mutable_ns()) {
184 // TODO(akbiggs): Under what circumstances does a namespace entry not have a
185 // path or directory? Should we log an error for these?
186 if (!ns_entry.has_path() || !ns_entry.has_directory()) {
187 continue;
188 }
189
190 if (ns_entry.path() == kTmpPath) {
191 // /tmp is covered by a locally served virtual filesystem.
192 continue;
193 }
194
195 // We move ownership of the directory & path since RAII is used to keep
196 // the handle open.
197 fidl::InterfaceHandle<::fuchsia::io::Directory> dir =
198 std::move(*ns_entry.mutable_directory());
199 const std::string path = std::move(*ns_entry.mutable_path());
200
201 const zx_status_t ns_bind_status =
202 fdio_ns_bind(namespace_, path.c_str(), dir.TakeChannel().release());
203 if (ns_bind_status != ZX_OK) {
204 FML_LOG(ERROR) << "Failed to bind " << path << " to namespace: "
205 << zx_status_get_string(ns_bind_status);
206 return false;
207 }
208 }
209
210 dart_outgoing_dir_request_ = dart_outgoing_dir_ptr_.NewRequest();
211
212 fuchsia::io::DirectoryHandle dart_public_dir;
213 // TODO(anmittal): when fixing enumeration using new c++ vfs, make sure that
214 // flutter_public_dir is only accessed once we receive OnOpen Event.
215 // That will prevent FL-175 for public directory
216 fdio_service_connect_at(dart_outgoing_dir_ptr_.channel().get(), "svc",
217 dart_public_dir.NewRequest().TakeChannel().release());
218
219#pragma clang diagnostic push
220#pragma clang diagnostic ignored "-Wdeprecated-declarations"
221
222 auto composed_service_dir = std::make_unique<vfs::ComposedServiceDir>();
223 composed_service_dir->set_fallback(std::move(dart_public_dir));
224
225#pragma clang diagnostic pop
226
227 // Clone and check if client is servicing the directory.
228 dart_outgoing_dir_ptr_->Clone(
229 fuchsia::io::OpenFlags::DESCRIBE |
230 fuchsia::io::OpenFlags::CLONE_SAME_RIGHTS,
231 dart_outgoing_dir_ptr_to_check_on_open_.NewRequest());
232
233 // Collect our standard set of directories.
234 std::vector<std::string> other_dirs = {"debug", "ctrl"};
235
236 dart_outgoing_dir_ptr_to_check_on_open_.events().OnOpen =
237 [this, other_dirs](zx_status_t status, auto unused) {
238 dart_outgoing_dir_ptr_to_check_on_open_.Unbind();
239 if (status != ZX_OK) {
240 FML_LOG(ERROR) << "could not bind out directory for dart component("
241 << label_ << "): " << zx_status_get_string(status);
242 return;
243 }
244
245 // add other directories as RemoteDirs.
246 for (auto& dir_str : other_dirs) {
247 fuchsia::io::DirectoryHandle dir;
248 auto request = dir.NewRequest().TakeChannel();
249 auto status = fdio_open_at(
250 dart_outgoing_dir_ptr_.channel().get(), dir_str.c_str(),
251 static_cast<uint32_t>(fuchsia::io::OpenFlags::DIRECTORY |
252 fuchsia::io::OpenFlags::RIGHT_READABLE),
253 request.release());
254 if (status == ZX_OK) {
255 dart_outgoing_dir_->AddEntry(
256 dir_str.c_str(),
257 std::make_unique<vfs::RemoteDir>(dir.TakeChannel()));
258 } else {
259 FML_LOG(ERROR) << "could not add out directory entry(" << dir_str
260 << ") for flutter component(" << label_
261 << "): " << zx_status_get_string(status);
262 }
263 }
264 };
265 dart_outgoing_dir_ptr_to_check_on_open_.set_error_handler(
266 [this](zx_status_t status) {
267 dart_outgoing_dir_ptr_to_check_on_open_.Unbind();
268 });
269
270 // Expose the "Echo" service here on behalf of the running dart program, so
271 // that integration tests can make use of it.
272 //
273 // The flutter/engine repository doesn't support connecting to FIDL from Dart,
274 // so for the tests sake we connect to the FIDL from C++ here and proxy the
275 // Echo to dart using native hooks.
276 composed_service_dir->AddService(
277 dart::test::Echo::Name_,
278 std::make_unique<vfs::Service>([this](zx::channel channel,
279 async_dispatcher_t* dispatcher) {
280 echo_binding_.AddBinding(
281 this, fidl::InterfaceRequest<dart::test::Echo>(std::move(channel)));
282 }));
283 dart_outgoing_dir_->AddEntry("svc", std::move(composed_service_dir));
284
285 if (start_info_.has_outgoing_dir()) {
286 dart_outgoing_dir_->Serve(
287 fuchsia::io::OpenFlags::RIGHT_READABLE |
288 fuchsia::io::OpenFlags::RIGHT_WRITABLE |
289 fuchsia::io::OpenFlags::DIRECTORY,
290 start_info_.mutable_outgoing_dir()->TakeChannel());
291 }
292
293 return true;
294}
295
296bool DartComponentController::SetUpFromKernel() {
299 namespace_, data_path_ + "/app.dilplist", manifest)) {
300 return false;
301 }
302
304 nullptr, "/pkg/data/isolate_core_snapshot_data.bin",
305 isolate_snapshot_data_)) {
306 return false;
307 }
308
309 std::string str(reinterpret_cast<const char*>(manifest.address()),
310 manifest.size());
311 Dart_Handle library = Dart_Null();
312
313 for (size_t start = 0; start < manifest.size();) {
314 size_t end = str.find("\n", start);
315 if (end == std::string::npos) {
316 FML_LOG(ERROR) << "Malformed manifest";
318 return false;
319 }
320
321 std::string path = data_path_ + "/" + str.substr(start, end - start);
322 start = end + 1;
323
326 kernel)) {
327 FML_LOG(ERROR) << "Cannot load kernel from namespace: " << path;
329 return false;
330 }
331 kernel_peices_.emplace_back(std::move(kernel));
332 }
333
334 if (!CreateIsolate(isolate_snapshot_data_.address(),
335 /*isolate_snapshot_instructions=*/nullptr)) {
336 return false;
337 }
338
340
341 for (const auto& kernel : kernel_peices_) {
342 library = Dart_LoadLibraryFromKernel(kernel.address(), kernel.size());
343 if (Dart_IsError(library)) {
344 FML_LOG(ERROR) << "Cannot load library from kernel: "
345 << Dart_GetError(library);
347 return false;
348 }
349 }
350
351 Dart_SetRootLibrary(library);
352
354 if (Dart_IsError(result)) {
355 FML_LOG(ERROR) << "Failed to FinalizeLoading: " << Dart_GetError(result);
357 return false;
358 }
359
360 return true;
361}
362
363bool DartComponentController::SetUpFromAppSnapshot() {
364#if !defined(AOT_RUNTIME)
365 return false;
366#else
367 // Load the ELF snapshot as available, and fall back to a blobs snapshot
368 // otherwise.
369 const uint8_t *isolate_data, *isolate_instructions;
370 if (elf_snapshot_.Load(namespace_, data_path_ + "/app_aot_snapshot.so")) {
371 isolate_data = elf_snapshot_.IsolateData();
372 isolate_instructions = elf_snapshot_.IsolateInstrs();
373 if (isolate_data == nullptr || isolate_instructions == nullptr) {
374 return false;
375 }
376 } else {
378 namespace_, data_path_ + "/isolate_snapshot_data.bin",
379 isolate_snapshot_data_)) {
380 return false;
381 }
382 isolate_data = isolate_snapshot_data_.address();
383 isolate_instructions = nullptr;
384 }
385 return CreateIsolate(isolate_data, isolate_instructions);
386#endif // defined(AOT_RUNTIME)
387}
388
389bool DartComponentController::CreateIsolate(
390 const uint8_t* isolate_snapshot_data,
391 const uint8_t* isolate_snapshot_instructions) {
392 // Create the isolate from the snapshot.
393 char* error = nullptr;
394
395 // TODO(dart_runner): Pass if we start using tonic's loader.
396 intptr_t namespace_fd = -1;
397
398 // Freed in IsolateShutdownCallback.
399 auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState(
400 namespace_fd, [this](Dart_Handle result) { MessageEpilogue(result); }));
401
402 Dart_IsolateFlags isolate_flags;
403 Dart_IsolateFlagsInitialize(&isolate_flags);
404 isolate_flags.null_safety = true;
405
406 isolate_ = Dart_CreateIsolateGroup(
407 url_.c_str(), label_.c_str(), isolate_snapshot_data,
408 isolate_snapshot_instructions, &isolate_flags, state, state, &error);
409 if (!isolate_) {
410 FML_LOG(ERROR) << "Dart_CreateIsolateGroup failed: " << error;
411 return false;
412 }
413
414 state->get()->SetIsolate(isolate_);
415
417 [loop = loop_.get()](auto callback) {
418 async::PostTask(loop->dispatcher(), std::move(callback));
419 };
420 state->get()->message_handler().Initialize(dispatcher);
421
422 state->get()->SetReturnCodeCallback(
423 [this](uint32_t return_code) { return_code_ = return_code; });
424
425 return true;
426}
427
429 async::PostTask(loop_->dispatcher(), [loop = loop_.get(), app = this] {
430 if (!app->RunDartMain()) {
431 loop->Quit();
432 }
433 });
434 loop_->Run();
435
436 if (binding_.is_bound()) {
437 // From the documentation for ComponentController, ZX_OK should be sent when
438 // the ComponentController receives a termination request. However, if the
439 // component exited with a non-zero return code, we indicate this by sending
440 // an INTERNAL epitaph instead.
441 //
442 // TODO(fxb/86666): Communicate return code from the ComponentController
443 // once v2 has support.
444 if (return_code_ == 0) {
445 binding_.Close(ZX_OK);
446 } else {
447 FML_LOG(ERROR) << "Component exited with non-zero return code: "
448 << return_code_;
449 binding_.Close(zx_status_t(fuchsia::component::Error::INTERNAL));
450 }
451 }
452}
453
454bool DartComponentController::RunDartMain() {
455 FML_CHECK(namespace_ != nullptr);
457
459
460 // TODO(fxb/88384): Create a file descriptor for each component that is
461 // launched and listen for anything that is written to the component. When
462 // something is written to the component, forward that message along to the
463 // Fuchsia logger and decorate it with the tag that it came from the
464 // component.
465 stdout_fd_ = fileno(stdout);
466 stderr_fd_ = fileno(stderr);
467
468 InitBuiltinLibrariesForIsolate(url_, namespace_, stdout_fd_, stderr_fd_,
469 dart_outgoing_dir_request_.TakeChannel(),
470 false /* service_isolate */);
471
474 char* error = Dart_IsolateMakeRunnable(isolate_);
475 if (error != nullptr) {
476 Dart_EnterIsolate(isolate_);
478 FML_LOG(ERROR) << "Unable to make isolate runnable: " << error;
479 free(error);
480 return false;
481 }
482 Dart_EnterIsolate(isolate_);
484
485 // TODO(fxb/88383): Support argument passing.
486 Dart_Handle corelib = Dart_LookupLibrary(ToDart("dart:core"));
487 Dart_Handle string_type =
488 Dart_GetNonNullableType(corelib, ToDart("String"), 0, NULL);
489 Dart_Handle dart_arguments =
491
492 if (Dart_IsError(dart_arguments)) {
493 FML_LOG(ERROR) << "Failed to allocate Dart arguments list: "
494 << Dart_GetError(dart_arguments);
496 return false;
497 }
498
499 Dart_Handle user_main = Dart_GetField(Dart_RootLibrary(), ToDart("main"));
500
501 if (Dart_IsError(user_main)) {
502 FML_LOG(ERROR) << "Failed to locate user_main in the root library: "
503 << Dart_GetError(user_main);
505 return false;
506 }
507
508 Dart_Handle fuchsia_lib = Dart_LookupLibrary(tonic::ToDart("dart:fuchsia"));
509
510 if (Dart_IsError(fuchsia_lib)) {
511 FML_LOG(ERROR) << "Failed to locate dart:fuchsia: "
512 << Dart_GetError(fuchsia_lib);
514 return false;
515 }
516
518 fuchsia_lib, "_runUserMainForDartRunner", {user_main, dart_arguments});
519
520 if (Dart_IsError(main_result)) {
521 auto dart_state = tonic::DartState::Current();
522 if (!dart_state->has_set_return_code()) {
523 // The program hasn't set a return code meaning this exit is unexpected.
524 FML_LOG(ERROR) << Dart_GetError(main_result);
525 return_code_ = tonic::GetErrorExitCode(main_result);
526
527 dart_utils::HandleIfException(runner_incoming_services_, url_,
528 main_result);
529 }
531 return false;
532 }
533
535 return true;
536}
537
538void DartComponentController::EchoString(fidl::StringPtr value,
539 EchoStringCallback callback) {
541
542 Dart_Handle builtin_lib = Dart_LookupLibrary(ToDart("dart:fuchsia.builtin"));
544
545 Dart_Handle receive_echo_string = ToDart("_receiveEchoString");
546 Dart_Handle string_to_echo =
547 value.has_value() ? tonic::ToDart(*value) : Dart_Null();
549 Dart_Invoke(builtin_lib, receive_echo_string, 1, &string_to_echo);
551
552 fidl::StringPtr echo_string;
553 if (!Dart_IsNull(result)) {
554 echo_string = tonic::StdStringFromDart(result);
555 }
556 callback(std::move(echo_string));
557
559}
560
562 if (Dart_CurrentIsolate()) {
565 if (queue) {
566 queue->Destroy();
567 }
568
569 loop_->Quit();
570
571 // TODO(rosswang): The docs warn of threading issues if doing this again,
572 // but without this, attempting to shut down the isolate finalizes app
573 // contexts that can't tell a shutdown is in progress and so fatal.
575
577 }
578}
579
580void DartComponentController::Stop() {
581 Kill();
582}
583
584void DartComponentController::MessageEpilogue(Dart_Handle result) {
585 auto dart_state = tonic::DartState::Current();
586 // If the Dart program has set a return code, then it is intending to shut
587 // down by way of a fatal error, and so there is no need to override
588 // return_code_.
589 if (dart_state->has_set_return_code()) {
591 return;
592 }
593
594 dart_utils::HandleIfException(runner_incoming_services_, url_, result);
595
596 // Otherwise, see if there was any other error.
597 return_code_ = tonic::GetErrorExitCode(result);
598 if (return_code_ != 0) {
600 return;
601 }
602
603 idle_start_ = zx::clock::get_monotonic();
604 zx_status_t status =
605 idle_timer_.set(idle_start_ + kIdleWaitDuration, kIdleSlack);
606 if (status != ZX_OK) {
607 FML_LOG(INFO) << "Idle timer set failed: " << zx_status_get_string(status);
608 }
609}
610
611void DartComponentController::OnIdleTimer(async_dispatcher_t* dispatcher,
612 async::WaitBase* wait,
613 zx_status_t status,
614 const zx_packet_signal* signal) {
615 if ((status != ZX_OK) || !(signal->observed & ZX_TIMER_SIGNALED) ||
617 // Timer closed or isolate shutdown.
618 return;
619 }
620
621 zx::time deadline = idle_start_ + kIdleWaitDuration;
622 zx::time now = zx::clock::get_monotonic();
623 if (now >= deadline) {
624 // No Dart message has been processed for kIdleWaitDuration: assume we'll
625 // stay idle for kIdleNotifyDuration.
626 Dart_NotifyIdle((now + kIdleNotifyDuration).get());
627 idle_start_ = zx::time(0);
628 idle_timer_.cancel(); // De-assert signal.
629 } else {
630 // Early wakeup or message pushed idle time forward: reschedule.
631 zx_status_t status = idle_timer_.set(deadline, kIdleSlack);
632 if (status != ZX_OK) {
633 FML_LOG(INFO) << "Idle timer set failed: "
634 << zx_status_get_string(status);
635 }
636 }
637 wait->Begin(dispatcher); // ignore errors
638}
639
640} // namespace dart_runner
static bool unused
DartComponentController(fuchsia::component::runner::ComponentStartInfo start_info, std::shared_ptr< sys::ServiceDirectory > runner_incoming_services, fidl::InterfaceRequest< fuchsia::component::runner::ComponentController > controller)
bool Load(fdio_ns_t *namespc, const std::string &path)
const uint8_t * IsolateData() const
const uint8_t * IsolateInstrs() const
static bool LoadFromNamespace(fdio_ns_t *namespc, const std::string &path, MappedResource &resource, bool executable=false)
const uint8_t * address() const
std::function< void(std::function< void(void)>)> TaskDispatcher
static DartMicrotaskQueue * GetForCurrentThread()
static DartState * Current()
Definition: dart_state.cc:56
DART_EXPORT Dart_Isolate Dart_CreateIsolateGroup(const char *script_uri, const char *name, const uint8_t *isolate_snapshot_data, const uint8_t *isolate_snapshot_instructions, Dart_IsolateFlags *flags, void *isolate_group_data, void *isolate_data, char **error)
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags *flags)
DART_EXPORT Dart_Handle Dart_GetNonNullableType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
DART_EXPORT DART_WARN_UNUSED_RESULT char * Dart_IsolateMakeRunnable(Dart_Isolate isolate)
DART_EXPORT void Dart_EnterScope(void)
DART_EXPORT void Dart_ExitScope(void)
DART_EXPORT void Dart_ShutdownIsolate(void)
DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type, Dart_Handle fill_object, intptr_t length)
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_EmptyString(void)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t *kernel_buffer, intptr_t kernel_buffer_size)
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeLoading(bool complete_futures)
DART_EXPORT void Dart_NotifyIdle(int64_t deadline)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)
DART_EXPORT Dart_Handle Dart_Null(void)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT void Dart_ExitIsolate(void)
DART_EXPORT void Dart_SetMessageNotifyCallback(Dart_MessageNotifyCallback message_notify_callback)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_RootLibrary(void)
DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library)
DART_EXPORT void Dart_SetThreadName(const char *name)
VkQueue queue
Definition: main.cc:55
double duration
Definition: examples.cpp:30
AtkStateType state
glong glong end
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
const uint8_t * isolate_snapshot_data
Definition: gen_snapshot.cc:69
const uint8_t * isolate_snapshot_instructions
Definition: gen_snapshot.cc:70
void InitBuiltinLibrariesForIsolate(const std::string &script_uri, fdio_ns_t *namespc, int stdoutfd, int stderrfd, zx::channel directory_request, bool service_isolate)
void HandleIfException(std::shared_ptr<::sys::ServiceDirectory > services, const std::string &component_url, Dart_Handle result)
void BindTemp(fdio_ns_t *ns)
Definition: tempfs.cc:23
static void Kill(Thread *thread, JSONStream *js)
Definition: service.cc:4400
std::string EchoString(std::string arg)
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: switches.h:57
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 vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
const myers::Point & get(const myers::Segment &)
Definition: ref_ptr.h:256
Dart_Handle ToDart(const T &object)
int GetErrorExitCode(Dart_Handle handle)
Definition: dart_error.cc:68
bool CheckAndHandleError(Dart_Handle handle)
Definition: dart_error.cc:33
std::string StdStringFromDart(Dart_Handle handle)
Dart_Handle DartInvokeField(Dart_Handle target, const char *name, std::initializer_list< Dart_Handle > args)
Definition: dart_invoke.cc:12
static double time(int loops, Benchmark *bench, Target *target)
Definition: nanobench.cpp:394
fidl::Binding< fuchsia::ui::composition::ChildViewWatcher > binding_
int_closure create
#define ERROR(message)
Definition: elf_loader.cc:260