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 "flutter/lib/ui/dart_runtime_hooks.h"
6
7#include <cstdio>
8#include <cstdlib>
9#include <cstring>
10#include <iostream>
11#include <sstream>
12
13#include "flutter/common/settings.h"
14#include "flutter/fml/build_config.h"
15#include "flutter/fml/logging.h"
16#include "flutter/lib/ui/plugins/callback_cache.h"
17#include "flutter/lib/ui/ui_dart_state.h"
18#include "flutter/runtime/dart_plugin_registrant.h"
19#include "third_party/dart/runtime/include/bin/dart_io_api.h"
20#include "third_party/dart/runtime/include/dart_api.h"
21#include "third_party/dart/runtime/include/dart_tools_api.h"
22#include "third_party/tonic/converter/dart_converter.h"
23#include "third_party/tonic/dart_library_natives.h"
24#include "third_party/tonic/dart_microtask_queue.h"
25#include "third_party/tonic/dart_state.h"
26#include "third_party/tonic/logging/dart_error.h"
27#include "third_party/tonic/logging/dart_invoke.h"
28#include "third_party/tonic/scopes/dart_api_scope.h"
29#include "third_party/tonic/scopes/dart_isolate_scope.h"
30
31using tonic::DartConverter;
32using tonic::ToDart;
33
34namespace flutter {
35
36static void PropagateIfError(Dart_Handle result) {
37 if (Dart_IsError(handle: result)) {
38 FML_LOG(ERROR) << "Dart Error: " << ::Dart_GetError(handle: result);
39 Dart_PropagateError(handle: result);
40 }
41}
42
43static Dart_Handle InvokeFunction(Dart_Handle builtin_library,
44 const char* name) {
45 Dart_Handle getter_name = ToDart(val: name);
46 return Dart_Invoke(target: builtin_library, name: getter_name, number_of_arguments: 0, arguments: nullptr);
47}
48
49static void InitDartInternal(Dart_Handle builtin_library, bool is_ui_isolate) {
50 Dart_Handle print = InvokeFunction(builtin_library, name: "_getPrintClosure");
51
52 Dart_Handle internal_library = Dart_LookupLibrary(url: ToDart(val: "dart:_internal"));
53
54 Dart_Handle result =
55 Dart_SetField(container: internal_library, name: ToDart(val: "_printClosure"), value: print);
56 PropagateIfError(result);
57
58 if (is_ui_isolate) {
59 // Call |_setupHooks| to configure |VMLibraryHooks|.
60 Dart_Handle method_name = Dart_NewStringFromCString(str: "_setupHooks");
61 result = Dart_Invoke(target: builtin_library, name: method_name, number_of_arguments: 0, NULL);
62 PropagateIfError(result);
63 }
64
65 Dart_Handle setup_hooks = Dart_NewStringFromCString(str: "_setupHooks");
66
67 Dart_Handle io_lib = Dart_LookupLibrary(url: ToDart(val: "dart:io"));
68 result = Dart_Invoke(target: io_lib, name: setup_hooks, number_of_arguments: 0, NULL);
69 PropagateIfError(result);
70
71 Dart_Handle isolate_lib = Dart_LookupLibrary(url: ToDart(val: "dart:isolate"));
72 result = Dart_Invoke(target: isolate_lib, name: setup_hooks, number_of_arguments: 0, NULL);
73 PropagateIfError(result);
74}
75
76static void InitDartCore(Dart_Handle builtin, const std::string& script_uri) {
77 Dart_Handle io_lib = Dart_LookupLibrary(url: ToDart(val: "dart:io"));
78 Dart_Handle get_base_url =
79 Dart_Invoke(target: io_lib, name: ToDart(val: "_getUriBaseClosure"), number_of_arguments: 0, NULL);
80 Dart_Handle core_library = Dart_LookupLibrary(url: ToDart(val: "dart:core"));
81 Dart_Handle result =
82 Dart_SetField(container: core_library, name: ToDart(val: "_uriBaseClosure"), value: get_base_url);
83 PropagateIfError(result);
84}
85
86static void InitDartAsync(Dart_Handle builtin_library, bool is_ui_isolate) {
87 Dart_Handle schedule_microtask;
88 if (is_ui_isolate) {
89 schedule_microtask =
90 InvokeFunction(builtin_library, name: "_getScheduleMicrotaskClosure");
91 } else {
92 Dart_Handle isolate_lib = Dart_LookupLibrary(url: ToDart(val: "dart:isolate"));
93 Dart_Handle method_name =
94 Dart_NewStringFromCString(str: "_getIsolateScheduleImmediateClosure");
95 schedule_microtask = Dart_Invoke(target: isolate_lib, name: method_name, number_of_arguments: 0, NULL);
96 }
97 Dart_Handle async_library = Dart_LookupLibrary(url: ToDart(val: "dart:async"));
98 Dart_Handle set_schedule_microtask = ToDart(val: "_setScheduleImmediateClosure");
99 Dart_Handle result = Dart_Invoke(target: async_library, name: set_schedule_microtask, number_of_arguments: 1,
100 arguments: &schedule_microtask);
101 PropagateIfError(result);
102}
103
104static void InitDartIO(Dart_Handle builtin_library,
105 const std::string& script_uri) {
106 Dart_Handle io_lib = Dart_LookupLibrary(url: ToDart(val: "dart:io"));
107 Dart_Handle platform_type =
108 Dart_GetNonNullableType(library: io_lib, class_name: ToDart(val: "_Platform"), number_of_type_arguments: 0, type_arguments: nullptr);
109 if (!script_uri.empty()) {
110 Dart_Handle result = Dart_SetField(container: platform_type, name: ToDart(val: "_nativeScript"),
111 value: ToDart(object: script_uri));
112 PropagateIfError(result);
113 }
114 // typedef _LocaleClosure = String Function();
115 Dart_Handle /* _LocaleClosure? */ locale_closure =
116 InvokeFunction(builtin_library, name: "_getLocaleClosure");
117 PropagateIfError(result: locale_closure);
118 // static String Function()? _localeClosure;
119 Dart_Handle result =
120 Dart_SetField(container: platform_type, name: ToDart(val: "_localeClosure"), value: locale_closure);
121 PropagateIfError(result);
122
123#if !FLUTTER_RELEASE
124 // Register dart:io service extensions used for network profiling.
125 Dart_Handle network_profiling_type =
126 Dart_GetNonNullableType(library: io_lib, class_name: ToDart(val: "_NetworkProfiling"), number_of_type_arguments: 0, type_arguments: nullptr);
127 PropagateIfError(result: network_profiling_type);
128 result = Dart_Invoke(target: network_profiling_type,
129 name: ToDart(val: "_registerServiceExtension"), number_of_arguments: 0, arguments: nullptr);
130 PropagateIfError(result);
131#endif // !FLUTTER_RELEASE
132}
133
134void DartRuntimeHooks::Install(bool is_ui_isolate,
135 const std::string& script_uri) {
136 Dart_Handle builtin = Dart_LookupLibrary(url: ToDart(val: "dart:ui"));
137 InitDartInternal(builtin_library: builtin, is_ui_isolate);
138 InitDartCore(builtin, script_uri);
139 InitDartAsync(builtin_library: builtin, is_ui_isolate);
140 InitDartIO(builtin_library: builtin, script_uri);
141}
142
143void DartRuntimeHooks::Logger_PrintDebugString(const std::string& message) {
144#ifndef NDEBUG
145 DartRuntimeHooks::Logger_PrintString(message);
146#endif
147}
148
149void DartRuntimeHooks::Logger_PrintString(const std::string& message) {
150 const auto& tag = UIDartState::Current()->logger_prefix();
151 UIDartState::Current()->LogMessage(tag, message);
152
153 if (dart::bin::ShouldCaptureStdout()) {
154 std::stringstream stream;
155 if (!tag.empty()) {
156 stream << tag << ": ";
157 }
158 stream << message;
159 std::string log = stream.str();
160
161 // For now we report print output on the Stdout stream.
162 uint8_t newline[] = {'\n'};
163 Dart_ServiceSendDataEvent(stream_id: "Stdout", event_kind: "WriteEvent",
164 bytes: reinterpret_cast<const uint8_t*>(log.c_str()),
165 bytes_length: log.size());
166 Dart_ServiceSendDataEvent(stream_id: "Stdout", event_kind: "WriteEvent", bytes: newline, bytes_length: sizeof(newline));
167 }
168}
169
170void DartRuntimeHooks::ScheduleMicrotask(Dart_Handle closure) {
171 UIDartState::Current()->ScheduleMicrotask(handle: closure);
172}
173
174static std::string GetFunctionLibraryUrl(Dart_Handle closure) {
175 if (Dart_IsClosure(object: closure)) {
176 closure = Dart_ClosureFunction(closure);
177 PropagateIfError(result: closure);
178 }
179
180 if (!Dart_IsFunction(handle: closure)) {
181 return "";
182 }
183
184 Dart_Handle url = Dart_Null();
185 Dart_Handle owner = Dart_FunctionOwner(function: closure);
186 if (Dart_IsInstance(object: owner)) {
187 owner = Dart_ClassLibrary(cls_type: owner);
188 }
189 if (Dart_IsLibrary(object: owner)) {
190 url = Dart_LibraryUrl(library: owner);
191 PropagateIfError(result: url);
192 }
193 return DartConverter<std::string>::FromDart(handle: url);
194}
195
196static std::string GetFunctionClassName(Dart_Handle closure) {
197 Dart_Handle result;
198
199 if (Dart_IsClosure(object: closure)) {
200 closure = Dart_ClosureFunction(closure);
201 PropagateIfError(result: closure);
202 }
203
204 if (!Dart_IsFunction(handle: closure)) {
205 return "";
206 }
207
208 bool is_static = false;
209 result = Dart_FunctionIsStatic(function: closure, is_static: &is_static);
210 PropagateIfError(result);
211 if (!is_static) {
212 return "";
213 }
214
215 result = Dart_FunctionOwner(function: closure);
216 PropagateIfError(result);
217
218 if (Dart_IsLibrary(object: result) || !Dart_IsInstance(object: result)) {
219 return "";
220 }
221 return DartConverter<std::string>::FromDart(handle: Dart_ClassName(cls_type: result));
222}
223
224static std::string GetFunctionName(Dart_Handle func) {
225 if (Dart_IsClosure(object: func)) {
226 func = Dart_ClosureFunction(closure: func);
227 PropagateIfError(result: func);
228 }
229
230 if (!Dart_IsFunction(handle: func)) {
231 return "";
232 }
233
234 bool is_static = false;
235 Dart_Handle result = Dart_FunctionIsStatic(function: func, is_static: &is_static);
236 PropagateIfError(result);
237 if (!is_static) {
238 return "";
239 }
240
241 result = Dart_FunctionName(function: func);
242 PropagateIfError(result);
243
244 return DartConverter<std::string>::FromDart(handle: result);
245}
246
247Dart_Handle DartRuntimeHooks::GetCallbackHandle(Dart_Handle func) {
248 std::string name = GetFunctionName(func);
249 std::string class_name = GetFunctionClassName(closure: func);
250 std::string library_path = GetFunctionLibraryUrl(closure: func);
251
252 // `name` is empty if `func` can't be used as a callback. This is the case
253 // when `func` is not a function object or is not a static function. Anonymous
254 // closures (e.g. `(int a, int b) => a + b;`) also cannot be used as
255 // callbacks, so `func` must be a tear-off of a named static function.
256 if (!Dart_IsTearOff(object: func) || name.empty()) {
257 return Dart_Null();
258 }
259 return DartConverter<int64_t>::ToDart(
260 val: DartCallbackCache::GetCallbackHandle(name, class_name, library_path));
261}
262
263Dart_Handle DartRuntimeHooks::GetCallbackFromHandle(int64_t handle) {
264 Dart_Handle result = DartCallbackCache::GetCallback(handle);
265 PropagateIfError(result);
266 return result;
267}
268
269void DartPluginRegistrant_EnsureInitialized() {
270 tonic::DartApiScope api_scope;
271 FindAndInvokeDartPluginRegistrant();
272}
273
274} // namespace flutter
275

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com

source code of flutter_engine/flutter/lib/ui/dart_runtime_hooks.cc