Flutter Engine
The Flutter Engine
dart_test_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 <fuchsia/test/cpp/fidl.h>
9#include <lib/async-loop/loop.h>
10#include <lib/async/cpp/task.h>
11#include <lib/async/default.h>
12#include <lib/fdio/directory.h>
13#include <lib/fdio/fd.h>
14#include <lib/fdio/namespace.h>
15#include <lib/fidl/cpp/string.h>
16#include <lib/fpromise/promise.h>
17#include <lib/sys/cpp/service_directory.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 "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
55constexpr zx::duration kTestTimeout = zx::sec(60);
56
57void AfterTask(async_loop_t*, void*) {
60 // Verify that the queue exists, as this method could have been called back as
61 // part of the exit routine, after the destruction of the microtask queue.
62 if (queue) {
63 queue->RunMicrotasks();
64 }
65}
66
67constexpr async_loop_config_t kLoopConfig = {
68 .default_accessors =
69 {
70 .getter = async_get_default_dispatcher,
71 .setter = async_set_default_dispatcher,
72 },
73 .make_default_for_current_thread = true,
74 .epilogue = &AfterTask,
75};
76
77// Find the last path of the component.
78// fuchsia-pkg://fuchsia.com/hello_dart#meta/hello_dart.cmx -> hello_dart.cmx
79std::string GetLabelFromUrl(const std::string& url) {
80 for (size_t i = url.length() - 1; i > 0; i--) {
81 if (url[i] == '/') {
82 return url.substr(i + 1, url.length() - 1);
83 }
84 }
85 return url;
86}
87
88// Find the name of the component.
89// fuchsia-pkg://fuchsia.com/hello_dart#meta/hello_dart.cm -> hello_dart
90std::string GetComponentNameFromUrl(const std::string& url) {
91 const std::string label = GetLabelFromUrl(url);
92 for (size_t i = 0; i < label.length(); ++i) {
93 if (label[i] == '.') {
94 return label.substr(0, i);
95 }
96 }
97 return label;
98}
99
100} // namespace
101
103 fuchsia::component::runner::ComponentStartInfo start_info,
104 std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
105 fidl::InterfaceRequest<fuchsia::component::runner::ComponentController>
106 controller,
107 DoneCallback done_callback)
108 : loop_(new async::Loop(&kLoopConfig)),
109 executor_(loop_->dispatcher()),
110 label_(GetLabelFromUrl(start_info.resolved_url())),
111 url_(std::move(start_info.resolved_url())),
112 runner_incoming_services_(runner_incoming_services),
113 start_info_(std::move(start_info)),
114 binding_(this),
115 done_callback_(std::move(done_callback)) {
116 // TODO(fxb/84537): This data path is configured based how we build Flutter
117 // applications in tree currently, but the way we build the Flutter
118 // application may change. We should avoid assuming the data path and let the
119 // CML file specify this data path instead.
120 test_component_name_ = GetComponentNameFromUrl(url_);
121 data_path_ = "pkg/data/" + test_component_name_;
122
123 if (controller.is_valid()) {
124 binding_.Bind(std::move(controller));
125 binding_.set_error_handler([this](zx_status_t status) { Kill(); });
126 } else {
127 FML_LOG(ERROR) << "Fuchsia component controller endpoint is not valid.";
128 }
129
130 zx_status_t idle_timer_status =
131 zx::timer::create(ZX_TIMER_SLACK_LATE, ZX_CLOCK_MONOTONIC, &idle_timer_);
132 if (idle_timer_status != ZX_OK) {
133 FML_LOG(INFO) << "Idle timer creation failed: "
134 << zx_status_get_string(idle_timer_status);
135 } else {
136 idle_wait_.set_object(idle_timer_.get());
137 idle_wait_.set_trigger(ZX_TIMER_SIGNALED);
138 idle_wait_.Begin(async_get_default_dispatcher());
139 }
140
141 // Close the runtime_dir channel if we don't intend to serve it. Otherwise any
142 // access to the runtime_dir will hang forever.
143 start_info_.clear_runtime_dir();
144}
145
147 if (namespace_) {
148 fdio_ns_destroy(namespace_);
149 namespace_ = nullptr;
150 }
151 close(stdout_fd_);
152 close(stderr_fd_);
153}
154
156 // Name the thread after the url of the component being launched.
157 zx::thread::self()->set_property(ZX_PROP_NAME, label_.c_str(), label_.size());
158 Dart_SetThreadName(label_.c_str());
159
160 if (!CreateAndBindNamespace()) {
161 return;
162 }
163
164 if (SetUpFromAppSnapshot()) {
165 FML_LOG(INFO) << url_ << " is running from an app snapshot";
166 } else if (SetUpFromKernel()) {
167 FML_LOG(INFO) << url_ << " is running from kernel";
168 } else {
169 FML_LOG(ERROR) << "Failed to set up component controller for " << url_;
170 return;
171 }
172
173 // Serve |fuchsia::test::Suite| on outgoing directory.
174 suite_context_ = sys::ComponentContext::Create();
175 suite_context_->outgoing()->AddPublicService(this->GetHandler());
176 suite_context_->outgoing()->Serve(
177 std::move(*start_info_.mutable_outgoing_dir()), loop_->dispatcher());
178
179 loop_->Run();
180}
181
182bool DartTestComponentController::CreateAndBindNamespace() {
183 if (!start_info_.has_ns()) {
184 FML_LOG(ERROR) << "Component start info does not have a namespace.";
185 return false;
186 }
187
188 const zx_status_t ns_create_status = fdio_ns_create(&namespace_);
189 if (ns_create_status != ZX_OK) {
190 FML_LOG(ERROR) << "Failed to create namespace: "
191 << zx_status_get_string(ns_create_status);
192 }
193
194 dart_utils::BindTemp(namespace_);
195
196 // Bind each directory in start_info's namespace to the controller's namespace
197 // instance.
198 for (auto& ns_entry : *start_info_.mutable_ns()) {
199 // TODO(akbiggs): Under what circumstances does a namespace entry not
200 // have a path or directory? Should we log an error for these?
201 if (!ns_entry.has_path() || !ns_entry.has_directory()) {
202 continue;
203 }
204
205 if (ns_entry.path() == kTmpPath) {
206 // /tmp is covered by a locally served virtual filesystem.
207 continue;
208 }
209
210 // We move ownership of the directory & path since RAII is used to keep
211 // the handle open.
212 fidl::InterfaceHandle<::fuchsia::io::Directory> dir =
213 std::move(*ns_entry.mutable_directory());
214 const std::string path = std::move(*ns_entry.mutable_path());
215
216 const zx_status_t ns_bind_status =
217 fdio_ns_bind(namespace_, path.c_str(), dir.TakeChannel().release());
218 if (ns_bind_status != ZX_OK) {
219 FML_LOG(ERROR) << "Failed to bind " << path << " to namespace: "
220 << zx_status_get_string(ns_bind_status);
221 return false;
222 }
223 }
224
225 return true;
226}
227
228bool DartTestComponentController::SetUpFromKernel() {
231 namespace_, data_path_ + "/app.dilplist", manifest)) {
232 return false;
233 }
234
236 nullptr, "/pkg/data/isolate_core_snapshot_data.bin",
237 isolate_snapshot_data_)) {
238 return false;
239 }
240
241 std::string str(reinterpret_cast<const char*>(manifest.address()),
242 manifest.size());
243 Dart_Handle library = Dart_Null();
244
245 for (size_t start = 0; start < manifest.size();) {
246 size_t end = str.find("\n", start);
247 if (end == std::string::npos) {
248 FML_LOG(ERROR) << "Malformed manifest";
249 return false;
250 }
251
252 std::string path = data_path_ + "/" + str.substr(start, end - start);
253 start = end + 1;
254
257 kernel)) {
258 FML_LOG(ERROR) << "Cannot load kernel from namespace: " << path;
259 return false;
260 }
261 kernel_peices_.emplace_back(std::move(kernel));
262 }
263
264 if (!CreateIsolate(isolate_snapshot_data_.address(),
265 /*isolate_snapshot_instructions=*/nullptr)) {
266 return false;
267 }
268
270
271 for (const auto& kernel : kernel_peices_) {
272 library = Dart_LoadLibraryFromKernel(kernel.address(), kernel.size());
273 if (Dart_IsError(library)) {
274 FML_LOG(ERROR) << "Cannot load library from kernel: "
275 << Dart_GetError(library);
277 return false;
278 }
279 }
280 Dart_SetRootLibrary(library);
281
283 if (Dart_IsError(result)) {
284 FML_LOG(ERROR) << "Failed to FinalizeLoading: " << Dart_GetError(result);
286 return false;
287 }
288
289 return true;
290}
291
292bool DartTestComponentController::SetUpFromAppSnapshot() {
293#if !defined(AOT_RUNTIME)
294 return false;
295#else
296 // Load the ELF snapshot as available, and fall back to a blobs snapshot
297 // otherwise.
298 const uint8_t *isolate_data, *isolate_instructions;
299 if (elf_snapshot_.Load(namespace_, data_path_ + "/app_aot_snapshot.so")) {
300 isolate_data = elf_snapshot_.IsolateData();
301 isolate_instructions = elf_snapshot_.IsolateInstrs();
302 if (isolate_data == nullptr || isolate_instructions == nullptr) {
303 return false;
304 }
305 } else {
307 namespace_, data_path_ + "/isolate_snapshot_data.bin",
308 isolate_snapshot_data_)) {
309 return false;
310 }
311 isolate_data = isolate_snapshot_data_.address();
312 isolate_instructions = nullptr;
313 }
314 return CreateIsolate(isolate_data, isolate_instructions);
315#endif // defined(AOT_RUNTIME)
316}
317
318bool DartTestComponentController::CreateIsolate(
319 const uint8_t* isolate_snapshot_data,
320 const uint8_t* isolate_snapshot_instructions) {
321 // Create the isolate from the snapshot.
322 char* error = nullptr;
323
324 // TODO(dart_runner): Pass if we start using tonic's loader.
325 intptr_t namespace_fd = -1;
326
327 // Freed in IsolateShutdownCallback.
328 auto state = new std::shared_ptr<tonic::DartState>(new tonic::DartState(
329 namespace_fd, [this](Dart_Handle result) { MessageEpilogue(result); }));
330
331 Dart_IsolateFlags isolate_flags;
332 Dart_IsolateFlagsInitialize(&isolate_flags);
333 isolate_flags.null_safety = true;
334
335 isolate_ = Dart_CreateIsolateGroup(
336 url_.c_str(), label_.c_str(), isolate_snapshot_data,
337 isolate_snapshot_instructions, &isolate_flags, state, state, &error);
338 if (!isolate_) {
339 FML_LOG(ERROR) << "Dart_CreateIsolateGroup failed: " << error;
340 return false;
341 }
342
343 state->get()->SetIsolate(isolate_);
344
346 [loop = loop_.get()](auto callback) {
347 async::PostTask(loop->dispatcher(), std::move(callback));
348 };
349 state->get()->message_handler().Initialize(dispatcher);
350
351 state->get()->SetReturnCodeCallback([this](uint32_t return_code) {
352 return_code_ = return_code;
353 auto ret_status = return_code == 0 ? fuchsia::test::Status::PASSED
355 fuchsia::test::Result result;
356 result.set_status(ret_status);
357 case_listener_->Finished(std::move(result));
358 });
359
360 return true;
361}
362
363// |fuchsia::test::CaseIterator|
364DartTestComponentController::CaseIterator::CaseIterator(
365 fidl::InterfaceRequest<fuchsia::test::CaseIterator> request,
366 async_dispatcher_t* dispatcher,
367 std::string test_component_name,
368 fit::function<void(CaseIterator*)> done_callback)
369 : binding_(this, std::move(request), dispatcher),
370 test_component_name_(test_component_name),
371 done_callback_(std::move(done_callback)) {}
372
373// |fuchsia::test::CaseIterator|
374void DartTestComponentController::CaseIterator::GetNext(
375 GetNextCallback callback) {
376 // Dart test suites run as multiple tests behind one
377 // test case. Flip flag once the one test case has been retrieved.
378 if (first_case_) {
379 fuchsia::test::Case test_case;
380 test_case.set_name(test_component_name_);
381 test_case.set_enabled(true);
382 std::vector<fuchsia::test::Case> cases;
383 cases.push_back(std::move(test_case));
384 callback(std::move(cases));
385 first_case_ = false;
386 } else {
387 // Return an pass an empty vector to the callback to indicate there
388 // are no more tests to be executed.
389 std::vector<fuchsia::test::Case> cases;
390 callback(std::move(cases));
391 done_callback_(this);
392 }
393}
394
395// |fuchsia::test::CaseIterator|
396std::unique_ptr<DartTestComponentController::CaseIterator>
397DartTestComponentController::RemoveCaseInterator(CaseIterator* case_iterator) {
398 auto it = case_iterators_.find(case_iterator);
399 std::unique_ptr<DartTestComponentController::CaseIterator> case_iterator_ptr;
400 if (it != case_iterators_.end()) {
401 case_iterator_ptr = std::move(it->second);
402 case_iterators_.erase(it);
403 }
404 return case_iterator_ptr;
405}
406
407// |fuchsia::test::Suite|
409 fidl::InterfaceRequest<fuchsia::test::CaseIterator> iterator) {
410 auto case_iterator = std::make_unique<CaseIterator>(
411 std::move(iterator), loop_->dispatcher(), test_component_name_,
412 [this](CaseIterator* case_iterator) {
413 RemoveCaseInterator(case_iterator);
414 });
415 case_iterators_.emplace(case_iterator.get(), std::move(case_iterator));
416}
417
418// |fuchsia::test::Suite|
420 std::vector<fuchsia::test::Invocation> tests,
421 fuchsia::test::RunOptions options,
422 fidl::InterfaceHandle<fuchsia::test::RunListener> listener) {
423 std::vector<std::string> args;
424 if (options.has_arguments()) {
425 args = std::move(*options.mutable_arguments());
426 }
427
428 auto listener_proxy = listener.Bind();
429
430 // We expect 1 test that will run all other tests in the test suite (i.e. a
431 // single main.dart that calls out to all of the dart tests). If the dart
432 // implementation in-tree changes, iterating over the invocations like so
433 // will be able to handle that.
434 for (auto it = tests.begin(); it != tests.end(); it++) {
435 auto invocation = std::move(*it);
436 std::string test_case_name;
437 if (invocation.has_name()) {
438 test_case_name = invocation.name();
439 }
440
441 // Create and out/err sockets and pass file descriptor for each to the
442 // dart process so that logging can be forwarded to the test_manager.
443 auto status = zx::socket::create(0, &out_, &out_client_);
444 if (status != ZX_OK) {
445 FML_LOG(FATAL) << "cannot create out socket: "
446 << zx_status_get_string(status);
447 }
448
449 status = fdio_fd_create(out_.release(), &stdout_fd_);
450 if (status != ZX_OK) {
451 FML_LOG(FATAL) << "failed to extract output fd: "
452 << zx_status_get_string(status);
453 }
454
455 status = zx::socket::create(0, &err_, &err_client_);
456 if (status != ZX_OK) {
457 FML_LOG(FATAL) << "cannot create error socket: "
458 << zx_status_get_string(status);
459 }
460
461 status = fdio_fd_create(err_.release(), &stderr_fd_);
462 if (status != ZX_OK) {
463 FML_LOG(FATAL) << "failed to extract error fd: "
464 << zx_status_get_string(status);
465 }
466
467 // Pass client end of out and err socket for test_manager to stream logs to
468 // current terminal, via |fuchsia::test::StdHandles|.
469 fuchsia::test::StdHandles std_handles;
470 std_handles.set_out(std::move(out_client_));
471 std_handles.set_err(std::move(err_client_));
472
473 listener_proxy->OnTestCaseStarted(std::move(invocation),
474 std::move(std_handles),
475 case_listener_.NewRequest());
476
477 // Run dart main and wait until exit code has been set before notifying of
478 // test completion.
479 auto dart_main_promise = fpromise::make_promise([&] { RunDartMain(); });
480 auto dart_state = tonic::DartState::Current();
481 executor_.schedule_task(std::move(dart_main_promise));
482 while (!dart_state->has_set_return_code()) {
483 loop_->Run(zx::deadline_after(kTestTimeout), true);
484 }
485
486 // Notify the test_manager that the test has completed.
487 listener_proxy->OnFinished();
488 }
489
490 if (binding_.is_bound()) {
491 // From the documentation for ComponentController, ZX_OK should be sent when
492 // the ComponentController receives a termination request. However, if the
493 // component exited with a non-zero return code, we indicate this by sending
494 // an INTERNAL epitaph instead.
495 //
496 // TODO(fxb/86666): Communicate return code from the ComponentController
497 // once v2 has support.
498 if (return_code_ == 0) {
499 binding_.Close(ZX_OK);
500 } else {
501 binding_.Close(zx_status_t(fuchsia::component::Error::INTERNAL));
502 }
503 }
504
505 // Stop and kill the test component.
506 Stop();
507}
508
509fpromise::promise<> DartTestComponentController::RunDartMain() {
510 FML_CHECK(namespace_ != nullptr);
512
514
515 fidl::InterfaceRequest<fuchsia::io::Directory> outgoing_dir =
516 std::move(*start_info_.mutable_outgoing_dir());
517 InitBuiltinLibrariesForIsolate(url_, namespace_, stdout_fd_, stderr_fd_,
518 outgoing_dir.TakeChannel(),
519 false /* service_isolate */);
520
523 char* error = Dart_IsolateMakeRunnable(isolate_);
524 if (error != nullptr) {
525 Dart_EnterIsolate(isolate_);
527 FML_LOG(ERROR) << "Unable to make isolate runnable: " << error;
528 free(error);
529 return fpromise::make_error_promise();
530 }
531 Dart_EnterIsolate(isolate_);
533
534 // TODO(fxb/88383): Support argument passing.
535 Dart_Handle corelib = Dart_LookupLibrary(ToDart("dart:core"));
536 Dart_Handle string_type =
537 Dart_GetNonNullableType(corelib, ToDart("String"), 0, NULL);
538 Dart_Handle dart_arguments =
540
541 if (Dart_IsError(dart_arguments)) {
542 FML_LOG(ERROR) << "Failed to allocate Dart arguments list: "
543 << Dart_GetError(dart_arguments);
545 return fpromise::make_error_promise();
546 }
547
548 Dart_Handle user_main = Dart_GetField(Dart_RootLibrary(), ToDart("main"));
549
550 if (Dart_IsError(user_main)) {
551 FML_LOG(ERROR) << "Failed to locate user_main in the root library: "
552 << Dart_GetError(user_main);
554 return fpromise::make_error_promise();
555 }
556
557 Dart_Handle fuchsia_lib = Dart_LookupLibrary(tonic::ToDart("dart:fuchsia"));
558
559 if (Dart_IsError(fuchsia_lib)) {
560 FML_LOG(ERROR) << "Failed to locate dart:fuchsia: "
561 << Dart_GetError(fuchsia_lib);
563 return fpromise::make_error_promise();
564 }
565
567 fuchsia_lib, "_runUserMainForDartRunner", {user_main, dart_arguments});
568
569 if (Dart_IsError(main_result)) {
570 auto dart_state = tonic::DartState::Current();
571 if (!dart_state->has_set_return_code()) {
572 // The program hasn't set a return code meaning this exit is unexpected.
573 FML_LOG(ERROR) << Dart_GetError(main_result);
574 return_code_ = tonic::GetErrorExitCode(main_result);
575
576 dart_utils::HandleIfException(runner_incoming_services_, url_,
577 main_result);
578 }
580 return fpromise::make_error_promise();
581 }
582
584 return fpromise::make_ok_promise();
585}
586
587void DartTestComponentController::Kill() {
588 done_callback_(this);
589 close(stdout_fd_);
590 close(stderr_fd_);
591 suite_bindings_.CloseAll();
592 if (Dart_CurrentIsolate()) {
595 if (queue) {
596 queue->Destroy();
597 }
598
599 loop_->Quit();
600
601 // TODO(rosswang): The docs warn of threading issues if doing this again,
602 // but without this, attempting to shut down the isolate finalizes app
603 // contexts that can't tell a shutdown is in progress and so fatal.
605
607 }
608}
609
610void DartTestComponentController::MessageEpilogue(Dart_Handle result) {
611 auto dart_state = tonic::DartState::Current();
612 // If the Dart program has set a return code, then it is intending to shut
613 // down by way of a fatal error, and so there is no need to override
614 // return_code_.
615 if (dart_state->has_set_return_code()) {
617 return;
618 }
619
620 dart_utils::HandleIfException(runner_incoming_services_, url_, result);
621
622 // Otherwise, see if there was any other error.
623 return_code_ = tonic::GetErrorExitCode(result);
624 if (return_code_ != 0) {
626 return;
627 }
628
629 idle_start_ = zx::clock::get_monotonic();
630 zx_status_t status =
631 idle_timer_.set(idle_start_ + kIdleWaitDuration, kIdleSlack);
632 if (status != ZX_OK) {
633 FML_LOG(INFO) << "Idle timer set failed: " << zx_status_get_string(status);
634 }
635}
636
637void DartTestComponentController::Stop() {
638 Kill();
639}
640
641void DartTestComponentController::OnIdleTimer(async_dispatcher_t* dispatcher,
642 async::WaitBase* wait,
643 zx_status_t status,
644 const zx_packet_signal* signal) {
645 if ((status != ZX_OK) || !(signal->observed & ZX_TIMER_SIGNALED) ||
647 // Timer closed or isolate shutdown.
648 return;
649 }
650
651 zx::time deadline = idle_start_ + kIdleWaitDuration;
652 zx::time now = zx::clock::get_monotonic();
653 if (now >= deadline) {
654 // No Dart message has been processed for kIdleWaitDuration: assume we'll
655 // stay idle for kIdleNotifyDuration.
656 Dart_NotifyIdle((now + kIdleNotifyDuration).get());
657 idle_start_ = zx::time(0);
658 idle_timer_.cancel(); // De-assert signal.
659 } else {
660 // Early wakeup or message pushed idle time forward: reschedule.
661 zx_status_t status = idle_timer_.set(deadline, kIdleSlack);
662 if (status != ZX_OK) {
663 FML_LOG(INFO) << "Idle timer set failed: "
664 << zx_status_get_string(status);
665 }
666 }
667 wait->Begin(dispatcher); // ignore errors
668}
669
670} // namespace dart_runner
static BlurTest tests[]
Definition: BlurTest.cpp:84
const char * options
static sk_sp< Effect > Create()
Definition: RefCntTest.cpp:117
void Run(std::vector< fuchsia::test::Invocation > tests, fuchsia::test::RunOptions options, fidl::InterfaceHandle< fuchsia::test::RunListener > listener) override
|Suite| protocol implementation.
fidl::InterfaceRequestHandler< fuchsia::test::Suite > GetHandler()
void GetTests(fidl::InterfaceRequest< fuchsia::test::CaseIterator > iterator) override
|Suite| protocol implementation.
DartTestComponentController(fuchsia::component::runner::ComponentStartInfo start_info, std::shared_ptr< sys::ServiceDirectory > runner_incoming_services, fidl::InterfaceRequest< fuchsia::component::runner::ComponentController > controller, DoneCallback done_callback)
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_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 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
#define FATAL(error)
AtkStateType state
glong glong end
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
Dart_NativeFunction function
Definition: fuchsia.cc:51
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
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
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
#define FAILED(hr)