Skip to content

Commit 5bd7260

Browse files
authored
Enable loading snapshots with sound null safety enabled. (flutter#21820)
Snapshots compiled with sound null-safety enabled require changes to the way in which isolates are launched. Specifically, the `Dart_IsolateFlags::null_safety` field needs to be known upfront. The value of this field can only be determined once the kernel snapshot is available. This poses a problem in the engine because the engine used to launch the isolate at shell initialization and only need the kernel mappings later at isolate launch (when transitioning the root isolate to the `DartIsolate::Phase::Running` phase). This patch delays launch of the isolate on the UI task runner till a kernel mapping is available. The side effects of this delay (callers no longer having access to the non-running isolate handle) have been addressed in this patch. The DartIsolate API has also been amended to hide the method that could return a non-running isolate to the caller. Instead, it has been replaced with a method that requires a valid isolate configuration that returns a running root isolate. The isolate will be launched by asking the isolate configuration for its null-safety characteristics. A side effect of enabling null-safety is that Dart APIs that work with legacy types will now terminate the process if used with an isolate that has sound null-safety enabled. These APIs may no longer be used in the engine. This primarily affects the Dart Convertors in Tonic that convert certain C++ objects into the Dart counterparts. All known Dart Converters have been updated to convert C++ objects to non-nullable Dart types inferred using type traits of the corresponding C++ object. The few spots in the engine that used the old Dart APIs directly have been manually updated. To ensure that no usage of the legacy APIs remain in the engine (as these would cause runtime process terminations), the legacy APIs were prefixed with the `DART_LEGACY_API` macro and the macro defined to `[[deprecated]]` in all engine translation units. While the engine now primarily works with non-nullable Dart types, callers can still use `Dart_TypeToNonNullableType` to acquire nullable types for use directly or with Tonic. One use case that is not addressed with the Tonic Dart Convertors is the creation of non-nullable lists of nullable types. This hasn’t come up so far in the engine. A minor related change is reworking tonic to define a single library target. This allows the various tonic subsystems to depend on one another. Primarily, this is used to make the Dart convertors use the logging utilities. This now allows errors to be more descriptive as the presence of error handles is caught (and logged) earlier. Fixes flutter#59879
1 parent 977537b commit 5bd7260

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1096
-740
lines changed

common/config.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ feature_defines_list = [
2828
"FLUTTER_RUNTIME_MODE_PROFILE=2",
2929
"FLUTTER_RUNTIME_MODE_RELEASE=3",
3030
"FLUTTER_RUNTIME_MODE_JIT_RELEASE=4",
31+
"DART_LEGACY_API=[[deprecated]]",
3132
]
3233

3334
if (flutter_runtime_mode == "debug") {

common/settings.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <chrono>
1111
#include <cstdint>
1212
#include <memory>
13+
#include <optional>
1314
#include <string>
1415
#include <vector>
1516

@@ -50,12 +51,11 @@ using UnhandledExceptionCallback =
5051
std::function<bool(const std::string& /* error */,
5152
const std::string& /* stack trace */)>;
5253

53-
// TODO(chinmaygarde): Deprecate all the "path" struct members in favor of the
54+
// TODO(26783): Deprecate all the "path" struct members in favor of the
5455
// callback that generates the mapping from these paths.
55-
// https://github.com/flutter/flutter/issues/26783
5656
using MappingCallback = std::function<std::unique_ptr<fml::Mapping>(void)>;
57-
using MappingsCallback =
58-
std::function<std::vector<std::unique_ptr<const fml::Mapping>>(void)>;
57+
using Mappings = std::vector<std::unique_ptr<const fml::Mapping>>;
58+
using MappingsCallback = std::function<Mappings(void)>;
5959

6060
using FrameRasterizedCallback = std::function<void(const FrameTiming&)>;
6161

fml/BUILD.gn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ source_set("fml") {
139139
"platform/darwin/string_range_sanitization.mm",
140140
]
141141

142-
libs += [ "Foundation.framework" ]
142+
frameworks = [ "Foundation.framework" ]
143143
}
144144

145145
if (is_android) {

fml/dart/dart_converter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ struct DartConverter<DartConverterMapping> {
2323
return Dart_Null();
2424
}
2525

26-
auto dart_list_handle = Dart_NewListOf(Dart_CoreType_Int, val->GetSize());
26+
auto dart_list_handle = Dart_NewListOfTypeFilled(
27+
ToDartTypeHandle<size_t>(), // type
28+
CreateZeroInitializedDartObject<size_t>(), // sentinel
29+
val->GetSize() // size
30+
);
2731

2832
if (Dart_IsError(dart_list_handle)) {
2933
FML_LOG(ERROR) << "Error while attempting to allocate a list: "

lib/io/dart_io.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4+
// FLUTTER_NOLINT
45

56
#include "flutter/lib/io/dart_io.h"
67

@@ -23,7 +24,7 @@ void DartIO::InitForIsolate(bool may_insecurely_connect_to_all_domains,
2324
FML_CHECK(!LogIfError(result));
2425

2526
Dart_Handle embedder_config_type =
26-
Dart_GetType(io_lib, ToDart("_EmbedderConfig"), 0, nullptr);
27+
Dart_GetNonNullableType(io_lib, ToDart("_EmbedderConfig"), 0, nullptr);
2728
FML_CHECK(!LogIfError(embedder_config_type));
2829

2930
Dart_Handle allow_insecure_connections_result = Dart_SetField(

lib/ui/dart_runtime_hooks.cc

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4+
// FLUTTER_NOLINT
45

56
#include "flutter/lib/ui/dart_runtime_hooks.h"
67

@@ -62,17 +63,19 @@ void DartRuntimeHooks::RegisterNatives(tonic::DartLibraryNatives* natives) {
6263

6364
static void PropagateIfError(Dart_Handle result) {
6465
if (Dart_IsError(result)) {
66+
FML_LOG(ERROR) << "Dart Error: " << ::Dart_GetError(result);
6567
Dart_PropagateError(result);
6668
}
6769
}
6870

69-
static Dart_Handle GetFunction(Dart_Handle builtin_library, const char* name) {
71+
static Dart_Handle InvokeFunction(Dart_Handle builtin_library,
72+
const char* name) {
7073
Dart_Handle getter_name = ToDart(name);
7174
return Dart_Invoke(builtin_library, getter_name, 0, nullptr);
7275
}
7376

7477
static void InitDartInternal(Dart_Handle builtin_library, bool is_ui_isolate) {
75-
Dart_Handle print = GetFunction(builtin_library, "_getPrintClosure");
78+
Dart_Handle print = InvokeFunction(builtin_library, "_getPrintClosure");
7679

7780
Dart_Handle internal_library = Dart_LookupLibrary(ToDart("dart:_internal"));
7881

@@ -112,7 +115,7 @@ static void InitDartAsync(Dart_Handle builtin_library, bool is_ui_isolate) {
112115
Dart_Handle schedule_microtask;
113116
if (is_ui_isolate) {
114117
schedule_microtask =
115-
GetFunction(builtin_library, "_getScheduleMicrotaskClosure");
118+
InvokeFunction(builtin_library, "_getScheduleMicrotaskClosure");
116119
} else {
117120
Dart_Handle isolate_lib = Dart_LookupLibrary(ToDart("dart:isolate"));
118121
Dart_Handle method_name =
@@ -130,21 +133,24 @@ static void InitDartIO(Dart_Handle builtin_library,
130133
const std::string& script_uri) {
131134
Dart_Handle io_lib = Dart_LookupLibrary(ToDart("dart:io"));
132135
Dart_Handle platform_type =
133-
Dart_GetType(io_lib, ToDart("_Platform"), 0, nullptr);
136+
Dart_GetNonNullableType(io_lib, ToDart("_Platform"), 0, nullptr);
134137
if (!script_uri.empty()) {
135138
Dart_Handle result = Dart_SetField(platform_type, ToDart("_nativeScript"),
136139
ToDart(script_uri));
137140
PropagateIfError(result);
138141
}
139-
Dart_Handle locale_closure =
140-
GetFunction(builtin_library, "_getLocaleClosure");
142+
// typedef _LocaleClosure = String Function();
143+
Dart_Handle /* _LocaleClosure? */ locale_closure =
144+
InvokeFunction(builtin_library, "_getLocaleClosure");
145+
PropagateIfError(locale_closure);
146+
// static String Function()? _localeClosure;
141147
Dart_Handle result =
142148
Dart_SetField(platform_type, ToDart("_localeClosure"), locale_closure);
143149
PropagateIfError(result);
144150

145151
// Register dart:io service extensions used for network profiling.
146152
Dart_Handle network_profiling_type =
147-
Dart_GetType(io_lib, ToDart("_NetworkProfiling"), 0, nullptr);
153+
Dart_GetNonNullableType(io_lib, ToDart("_NetworkProfiling"), 0, nullptr);
148154
PropagateIfError(network_profiling_type);
149155
result = Dart_Invoke(network_profiling_type,
150156
ToDart("_registerServiceExtension"), 0, nullptr);

lib/ui/hooks.dart

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ void _updateWindowMetrics(
5353
_invoke(window.onMetricsChanged, window._onMetricsChangedZone);
5454
}
5555

56-
typedef _LocaleClosure = String? Function();
57-
58-
String? _localeClosure() {
56+
String _localeClosure() {
5957
if (window.locale == null) {
60-
return null;
58+
return '';
6159
}
6260
return window.locale.toString();
6361
}
6462

63+
typedef _LocaleClosure = String Function();
64+
6565
@pragma('vm:entry-point')
6666
// ignore: unused_element
6767
_LocaleClosure? _getLocaleClosure() => _localeClosure;
@@ -210,9 +210,7 @@ void _drawFrame() {
210210
}
211211

212212
// ignore: always_declare_return_types, prefer_generic_function_type_aliases
213-
typedef _UnaryFunction(Null args);
214-
// ignore: always_declare_return_types, prefer_generic_function_type_aliases
215-
typedef _BinaryFunction(Null args, Null message);
213+
typedef _ListStringArgFunction(List<String> args);
216214

217215
@pragma('vm:entry-point')
218216
// ignore: unused_element
@@ -221,11 +219,7 @@ void _runMainZoned(Function startMainIsolateFunction,
221219
List<String> args) {
222220
startMainIsolateFunction((){
223221
runZonedGuarded<void>(() {
224-
if (userMainFunction is _BinaryFunction) {
225-
// This seems to be undocumented but supported by the command line VM.
226-
// Let's do the same in case old entry-points are ported to Flutter.
227-
(userMainFunction as dynamic)(args, '');
228-
} else if (userMainFunction is _UnaryFunction) {
222+
if (userMainFunction is _ListStringArgFunction) {
229223
(userMainFunction as dynamic)(args);
230224
} else {
231225
userMainFunction();

lib/ui/text/paragraph.cc

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2013 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
4+
// FLUTTER_NOLINT
45

56
#include "flutter/lib/ui/text/paragraph.h"
67

@@ -132,20 +133,19 @@ tonic::Float32List Paragraph::getRectsForPlaceholders() {
132133
}
133134

134135
Dart_Handle Paragraph::getPositionForOffset(double dx, double dy) {
135-
Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2);
136136
txt::Paragraph::PositionWithAffinity pos =
137137
m_paragraph->GetGlyphPositionAtCoordinate(dx, dy);
138-
Dart_ListSetAt(result, 0, ToDart(pos.position));
139-
Dart_ListSetAt(result, 1, ToDart(static_cast<int>(pos.affinity)));
140-
return result;
138+
std::vector<size_t> result = {
139+
pos.position, // size_t already
140+
static_cast<size_t>(pos.affinity) // affinity (enum)
141+
};
142+
return tonic::DartConverter<decltype(result)>::ToDart(result);
141143
}
142144

143145
Dart_Handle Paragraph::getWordBoundary(unsigned offset) {
144146
txt::Paragraph::Range<size_t> point = m_paragraph->GetWordBoundary(offset);
145-
Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2);
146-
Dart_ListSetAt(result, 0, ToDart(point.start));
147-
Dart_ListSetAt(result, 1, ToDart(point.end));
148-
return result;
147+
std::vector<size_t> result = {point.start, point.end};
148+
return tonic::DartConverter<decltype(result)>::ToDart(result);
149149
}
150150

151151
Dart_Handle Paragraph::getLineBoundary(unsigned offset) {
@@ -159,10 +159,8 @@ Dart_Handle Paragraph::getLineBoundary(unsigned offset) {
159159
break;
160160
}
161161
}
162-
Dart_Handle result = Dart_NewListOf(Dart_CoreType_Int, 2);
163-
Dart_ListSetAt(result, 0, ToDart(line_start));
164-
Dart_ListSetAt(result, 1, ToDart(line_end));
165-
return result;
162+
std::vector<int> result = {line_start, line_end};
163+
return tonic::DartConverter<decltype(result)>::ToDart(result);
166164
}
167165

168166
tonic::Float64List Paragraph::computeLineMetrics() {

lib/ui/window/platform_configuration.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,6 @@
1919
#include "flutter/lib/ui/window/window.h"
2020
#include "third_party/tonic/dart_persistent_value.h"
2121

22-
namespace tonic {
23-
class DartLibraryNatives;
24-
25-
// So tonic::ToDart<std::vector<int64_t>> returns List<int> instead of
26-
// List<dynamic>.
27-
template <>
28-
struct DartListFactory<int64_t> {
29-
static Dart_Handle NewList(intptr_t length) {
30-
return Dart_NewListOf(Dart_CoreType_Int, length);
31-
}
32-
};
33-
34-
} // namespace tonic
35-
3622
namespace flutter {
3723
class FontCollection;
3824
class PlatformMessage;

runtime/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ source_set("runtime") {
5353
"dart_vm_lifecycle.h",
5454
"embedder_resources.cc",
5555
"embedder_resources.h",
56+
"isolate_configuration.cc",
57+
"isolate_configuration.h",
5658
"platform_data.cc",
5759
"platform_data.h",
5860
"ptrace_check.h",
@@ -112,6 +114,7 @@ if (enable_unittests) {
112114
"dart_lifecycle_unittests.cc",
113115
"dart_service_isolate_unittests.cc",
114116
"dart_vm_unittests.cc",
117+
"type_conversions_unittests.cc",
115118
]
116119

117120
public_configs = [ "//flutter:export_dynamic_symbols" ]

0 commit comments

Comments
 (0)