• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "builtin_libraries.h"
6 
7 #include <lib/fdio/namespace.h>
8 #include <lib/zx/channel.h>
9 
10 #include "dart-pkg/fuchsia/sdk_ext/fuchsia.h"
11 #include "flutter/fml/logging.h"
12 #include "runtime/dart/utils/inlines.h"
13 #include "third_party/dart/runtime/bin/io_natives.h"
14 #include "third_party/dart/runtime/include/dart_api.h"
15 #include "third_party/tonic/converter/dart_converter.h"
16 #include "third_party/tonic/dart_microtask_queue.h"
17 #include "third_party/tonic/logging/dart_error.h"
18 
19 #include "logging.h"
20 
21 using tonic::ToDart;
22 
23 namespace dart_runner {
24 namespace {
25 
26 #define REGISTER_FUNCTION(name, count) {#name, name, count},
27 #define DECLARE_FUNCTION(name, count) \
28   extern void name(Dart_NativeArguments args);
29 
30 #define BUILTIN_NATIVE_LIST(V) \
31   V(Logger_PrintString, 1)     \
32   V(ScheduleMicrotask, 1)
33 
34 BUILTIN_NATIVE_LIST(DECLARE_FUNCTION);
35 
36 const struct NativeEntry {
37   const char* name;
38   Dart_NativeFunction function;
39   int argument_count;
40 } kBuiltinEntries[] = {BUILTIN_NATIVE_LIST(REGISTER_FUNCTION)};
41 
BuiltinNativeLookup(Dart_Handle name,int argument_count,bool * auto_setup_scope)42 Dart_NativeFunction BuiltinNativeLookup(Dart_Handle name,
43                                         int argument_count,
44                                         bool* auto_setup_scope) {
45   const char* function_name = nullptr;
46   Dart_Handle result = Dart_StringToCString(name, &function_name);
47   if (Dart_IsError(result)) {
48     Dart_PropagateError(result);
49   }
50   FML_DCHECK(function_name != nullptr);
51   FML_DCHECK(auto_setup_scope != nullptr);
52   *auto_setup_scope = true;
53   size_t num_entries = dart_utils::ArraySize(kBuiltinEntries);
54   for (size_t i = 0; i < num_entries; i++) {
55     const NativeEntry& entry = kBuiltinEntries[i];
56     if (!strcmp(function_name, entry.name) &&
57         (entry.argument_count == argument_count)) {
58       return entry.function;
59     }
60   }
61   return nullptr;
62 }
63 
BuiltinNativeSymbol(Dart_NativeFunction native_function)64 const uint8_t* BuiltinNativeSymbol(Dart_NativeFunction native_function) {
65   size_t num_entries = dart_utils::ArraySize(kBuiltinEntries);
66   for (size_t i = 0; i < num_entries; i++) {
67     const NativeEntry& entry = kBuiltinEntries[i];
68     if (entry.function == native_function)
69       return reinterpret_cast<const uint8_t*>(entry.name);
70   }
71   return nullptr;
72 }
73 
Logger_PrintString(Dart_NativeArguments args)74 void Logger_PrintString(Dart_NativeArguments args) {
75   intptr_t length = 0;
76   uint8_t* chars = nullptr;
77   Dart_Handle str = Dart_GetNativeArgument(args, 0);
78   Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
79   if (Dart_IsError(result)) {
80     Dart_PropagateError(result);
81   } else {
82     fwrite(chars, 1, length, stdout);
83     fputc('\n', stdout);
84     fflush(stdout);
85   }
86 }
87 
ScheduleMicrotask(Dart_NativeArguments args)88 void ScheduleMicrotask(Dart_NativeArguments args) {
89   Dart_Handle closure = Dart_GetNativeArgument(args, 0);
90   if (tonic::LogIfError(closure) || !Dart_IsClosure(closure))
91     return;
92   tonic::DartMicrotaskQueue::GetForCurrentThread()->ScheduleMicrotask(closure);
93 }
94 
95 }  // namespace
96 
InitBuiltinLibrariesForIsolate(const std::string & script_uri,fdio_ns_t * namespc,int stdoutfd,int stderrfd,fidl::InterfaceHandle<fuchsia::sys::Environment> environment,zx::channel directory_request,bool service_isolate)97 void InitBuiltinLibrariesForIsolate(
98     const std::string& script_uri,
99     fdio_ns_t* namespc,
100     int stdoutfd,
101     int stderrfd,
102     fidl::InterfaceHandle<fuchsia::sys::Environment> environment,
103     zx::channel directory_request,
104     bool service_isolate) {
105   // dart:fuchsia --------------------------------------------------------------
106   if (!service_isolate) {
107     fuchsia::dart::Initialize(std::move(environment),
108                               std::move(directory_request));
109   }
110 
111   // dart:fuchsia.builtin ------------------------------------------------------
112 
113   Dart_Handle builtin_lib = Dart_LookupLibrary(ToDart("dart:fuchsia.builtin"));
114   FML_CHECK(!tonic::LogIfError(builtin_lib));
115   Dart_Handle result = Dart_SetNativeResolver(builtin_lib, BuiltinNativeLookup,
116                                               BuiltinNativeSymbol);
117   FML_CHECK(!tonic::LogIfError(result));
118 
119   // dart:io -------------------------------------------------------------------
120 
121   Dart_Handle io_lib = Dart_LookupLibrary(ToDart("dart:io"));
122   FML_CHECK(!tonic::LogIfError(io_lib));
123   result = Dart_SetNativeResolver(io_lib, dart::bin::IONativeLookup,
124                                   dart::bin::IONativeSymbol);
125   FML_CHECK(!tonic::LogIfError(result));
126 
127   // dart:zircon ---------------------------------------------------------------
128 
129   Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon"));
130   FML_CHECK(!tonic::LogIfError(zircon_lib));
131   // NativeResolver already set by fuchsia::dart::Initialize().
132 
133   // Core libraries ------------------------------------------------------------
134 
135   Dart_Handle async_lib = Dart_LookupLibrary(ToDart("dart:async"));
136   FML_CHECK(!tonic::LogIfError(async_lib));
137 
138   Dart_Handle core_lib = Dart_LookupLibrary(ToDart("dart:core"));
139   FML_CHECK(!tonic::LogIfError(core_lib));
140 
141   Dart_Handle internal_lib = Dart_LookupLibrary(ToDart("dart:_internal"));
142   FML_CHECK(!tonic::LogIfError(internal_lib));
143 
144   Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate"));
145   FML_CHECK(!tonic::LogIfError(isolate_lib));
146 
147 #if !defined(AOT_RUNTIME)
148   // AOT: These steps already happened at compile time in gen_snapshot.
149 
150   // We need to ensure that all the scripts loaded so far are finalized
151   // as we are about to invoke some Dart code below to setup closures.
152   result = Dart_FinalizeLoading(false);
153   FML_CHECK(!tonic::LogIfError(result));
154 #endif
155 
156   // Setup the internal library's 'internalPrint' function.
157   Dart_Handle print =
158       Dart_Invoke(builtin_lib, ToDart("_getPrintClosure"), 0, nullptr);
159   FML_CHECK(!tonic::LogIfError(print));
160 
161   result = Dart_SetField(internal_lib, ToDart("_printClosure"), print);
162   FML_CHECK(!tonic::LogIfError(result));
163 
164   // Set up the 'scheduleImmediate' closure.
165   Dart_Handle schedule_immediate_closure;
166   if (service_isolate) {
167     // Running on dart::ThreadPool.
168     schedule_immediate_closure = Dart_Invoke(
169         isolate_lib, ToDart("_getIsolateScheduleImmediateClosure"), 0, nullptr);
170   } else {
171     // Running on async::Loop.
172     schedule_immediate_closure = Dart_Invoke(
173         builtin_lib, ToDart("_getScheduleMicrotaskClosure"), 0, nullptr);
174   }
175   FML_CHECK(!tonic::LogIfError(schedule_immediate_closure));
176 
177   Dart_Handle schedule_args[1];
178   schedule_args[0] = schedule_immediate_closure;
179   result = Dart_Invoke(async_lib, ToDart("_setScheduleImmediateClosure"), 1,
180                        schedule_args);
181   FML_CHECK(!tonic::LogIfError(result));
182 
183   // Set up the namespace in dart:io.
184   Dart_Handle namespace_type =
185       Dart_GetType(io_lib, ToDart("_Namespace"), 0, nullptr);
186   FML_CHECK(!tonic::LogIfError(namespace_type));
187 
188   Dart_Handle namespace_args[1];
189   namespace_args[0] = ToDart(reinterpret_cast<intptr_t>(namespc));
190   result =
191       Dart_Invoke(namespace_type, ToDart("_setupNamespace"), 1, namespace_args);
192   FML_CHECK(!tonic::LogIfError(result));
193 
194   // Set up the namespace in dart:zircon.
195   namespace_type = Dart_GetType(zircon_lib, ToDart("_Namespace"), 0, nullptr);
196   FML_CHECK(!tonic::LogIfError(namespace_type));
197 
198   result = Dart_SetField(namespace_type, ToDart("_namespace"),
199                          ToDart(reinterpret_cast<intptr_t>(namespc)));
200   FML_CHECK(!tonic::LogIfError(result));
201 
202   // Set up stdout and stderr.
203   Dart_Handle stdio_args[3];
204   stdio_args[0] = Dart_NewInteger(0);
205   stdio_args[1] = Dart_NewInteger(stdoutfd);
206   stdio_args[2] = Dart_NewInteger(stderrfd);
207   result = Dart_Invoke(io_lib, ToDart("_setStdioFDs"), 3, stdio_args);
208   FML_CHECK(!tonic::LogIfError(result));
209 
210   // Disable some dart:io operations.
211   Dart_Handle embedder_config_type =
212       Dart_GetType(io_lib, ToDart("_EmbedderConfig"), 0, nullptr);
213   FML_CHECK(!tonic::LogIfError(embedder_config_type));
214 
215   result =
216       Dart_SetField(embedder_config_type, ToDart("_mayExit"), Dart_False());
217   FML_CHECK(!tonic::LogIfError(result));
218 
219   // Set the script location.
220   result = Dart_SetField(builtin_lib, ToDart("_rawScript"), ToDart(script_uri));
221   FML_CHECK(!tonic::LogIfError(result));
222 
223   // Setup the uriBase with the base uri of the fidl app.
224   Dart_Handle uri_base =
225       Dart_Invoke(io_lib, ToDart("_getUriBaseClosure"), 0, nullptr);
226   FML_CHECK(!tonic::LogIfError(uri_base));
227 
228   result = Dart_SetField(core_lib, ToDart("_uriBaseClosure"), uri_base);
229   FML_CHECK(!tonic::LogIfError(result));
230 
231   Dart_Handle setup_hooks = ToDart("_setupHooks");
232   result = Dart_Invoke(builtin_lib, setup_hooks, 0, nullptr);
233   FML_CHECK(!tonic::LogIfError(result));
234   result = Dart_Invoke(io_lib, setup_hooks, 0, nullptr);
235   FML_CHECK(!tonic::LogIfError(result));
236   result = Dart_Invoke(isolate_lib, setup_hooks, 0, nullptr);
237   FML_CHECK(!tonic::LogIfError(result));
238 }
239 
240 }  // namespace dart_runner
241