Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2c527d6

Browse files
christopherfujinodcharkesHarry Terkelseniskakaushikxster
authored
[flutter_releases] Flutter 1.26.0-17.2.pre Beta Engine Cherrypicks (#24142)
* add ffi_allocation_patch.dart to libraries.yaml 2 (#23954) * Use `runes` to get code units in CanvasKit. (#24024) * [windows] Honor only valid resize requests (#23990) * Load FlutterLoader when creating FlutterEngineGroup (#23980) * [canvaskit] remove the DOM node of unrendered platform view (#24001) * update dart to 2.12.0-259.8.beta * [web] Fix svg based stroke rendering. (#23969) * [canvaskit] fix text background, foreground, color; add text style tests (#23800) * [canvaskit] fix text background, foreground, familyFallback; add style tests * add leak test * update goldens_lock.yaml * remove solo * Warn when popping out of empty text style stack * [web] Fix alignment issue in rich paragraphs (#23965) * [web] Implement CanvasParagraph.getLineBoundary (#24037) * [web] Fix text alignment when transform + tight constraints + DOM rendering (#24036) * update licenses_third_party golden Co-authored-by: Daco Harkes <[email protected]> Co-authored-by: Harry Terkelsen <[email protected]> Co-authored-by: Kaushik Iska <[email protected]> Co-authored-by: xster <[email protected]> Co-authored-by: Yegor <[email protected]> Co-authored-by: Ferhat <[email protected]> Co-authored-by: Mouad Debbar <[email protected]>
1 parent 5d3477e commit 2c527d6

File tree

26 files changed

+1407
-245
lines changed

26 files changed

+1407
-245
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ vars = {
3535
# Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
3636
# You can use //tools/dart/create_updated_flutter_deps.py to produce
3737
# updated revision list of existing dependencies.
38-
'dart_revision': '2607b01bec99f324e45b00fde76591f244f65a4e',
38+
'dart_revision': 'e5dd92c3ca766810e0e5a02d8725b1cebc19f564',
3939

4040
# WARNING: DO NOT EDIT MANUALLY
4141
# The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py

ci/licenses_golden/licenses_third_party

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Signature: 8d4521c3fe82b7be926a7af5f8b15557
1+
Signature: 65f332e775d31fee5a51ee0a303354c3
22

33
UNUSED LICENSES:
44

@@ -9750,9 +9750,11 @@ FILE: ../../../third_party/dart/samples_2/ffi/sqlite/lib/src/ffi/arena.dart
97509750
FILE: ../../../third_party/dart/samples_2/ffi/sqlite/lib/src/ffi/dylib_utils.dart
97519751
FILE: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/rti.dart
97529752
FILE: ../../../third_party/dart/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
9753+
FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart
97539754
FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
97549755
FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
97559756
FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart
9757+
FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart
97569758
FILE: ../../../third_party/dart/sdk/lib/ffi/annotations.dart
97579759
FILE: ../../../third_party/dart/sdk/lib/ffi/dynamic_library.dart
97589760
FILE: ../../../third_party/dart/sdk/lib/ffi/ffi.dart

lib/snapshot/libraries.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@
8282
"ffi": {
8383
"uri": "../../../third_party/dart/sdk/lib/ffi/ffi.dart",
8484
"patches": [
85+
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart",
86+
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart",
8587
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
8688
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart",
87-
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
89+
"../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart"
8890
]
8991
},
9092
"wasm": {

lib/snapshot/libraries.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,11 @@ flutter:
8787
ffi:
8888
uri: "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
8989
patches:
90+
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
91+
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_allocation_patch.dart"
9092
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
9193
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
92-
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_patch.dart"
94+
- "../../../third_party/dart/sdk/lib/_internal/vm/lib/ffi_struct_patch.dart"
9395

9496
wasm:
9597
uri: "../../../third_party/dart/sdk/lib/wasm/wasm.dart"

lib/web_ui/dev/goldens_lock.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
repository: https://github.com/flutter/goldens.git
2-
revision: b85f9093e6bc6d4e7cbb7f97491667c143c4a360
2+
revision: 99caeb1bcb8b7a856a78bd8d55816cc97db56112

lib/web_ui/dev/test_runner.dart

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ class TestCommand extends Command<bool> with ArgUtils {
8888
'.dart_tool/goldens. Use this option to bulk-update all screenshots, '
8989
'for example, when a new browser version affects pixels.',
9090
)
91+
..addFlag(
92+
'fetch-goldens-repo',
93+
defaultsTo: true,
94+
negatable: true,
95+
help:
96+
'Whether to fetch the goldens repo. Set this to false to iterate '
97+
'on golden tests without fearing that the fetcher will overwrite '
98+
'your local changes.',
99+
)
91100
..addOption(
92101
'browser',
93102
defaultsTo: 'chrome',
@@ -165,39 +174,41 @@ class TestCommand extends Command<bool> with ArgUtils {
165174
final FilePath dir = FilePath.fromWebUi('');
166175
print('');
167176
print('Initial test run is done!');
168-
print('Watching ${dir.relativeToCwd}/lib and ${dir.relativeToCwd}/test to re-run tests');
177+
print(
178+
'Watching ${dir.relativeToCwd}/lib and ${dir.relativeToCwd}/test to re-run tests');
169179
print('');
170180
PipelineWatcher(
171-
dir: dir.absolute,
172-
pipeline: testPipeline,
173-
ignore: (event) {
174-
// Ignore font files that are copied whenever tests run.
175-
if (event.path.endsWith('.ttf')) {
176-
return true;
177-
}
181+
dir: dir.absolute,
182+
pipeline: testPipeline,
183+
ignore: (event) {
184+
// Ignore font files that are copied whenever tests run.
185+
if (event.path.endsWith('.ttf')) {
186+
return true;
187+
}
178188

179-
// Ignore auto-generated JS files.
180-
// The reason we are using `.contains()` instead of `.endsWith()` is
181-
// because the auto-generated files could end with any of the
182-
// following:
183-
//
184-
// - browser_test.dart.js
185-
// - browser_test.dart.js.map
186-
// - browser_test.dart.js.deps
187-
if (event.path.contains('browser_test.dart.js')) {
188-
return true;
189-
}
189+
// Ignore auto-generated JS files.
190+
// The reason we are using `.contains()` instead of `.endsWith()` is
191+
// because the auto-generated files could end with any of the
192+
// following:
193+
//
194+
// - browser_test.dart.js
195+
// - browser_test.dart.js.map
196+
// - browser_test.dart.js.deps
197+
if (event.path.contains('browser_test.dart.js')) {
198+
return true;
199+
}
190200

191-
// React to changes in lib/ and test/ folders.
192-
final String relativePath = path.relative(event.path, from: dir.absolute);
193-
if (relativePath.startsWith('lib/') || relativePath.startsWith('test/')) {
194-
return false;
195-
}
201+
// React to changes in lib/ and test/ folders.
202+
final String relativePath =
203+
path.relative(event.path, from: dir.absolute);
204+
if (relativePath.startsWith('lib/') ||
205+
relativePath.startsWith('test/')) {
206+
return false;
207+
}
196208

197-
// Ignore anything else.
198-
return true;
199-
}
200-
).start();
209+
// Ignore anything else.
210+
return true;
211+
}).start();
201212
// Return a never-ending future.
202213
return Completer<bool>().future;
203214
} else {
@@ -217,15 +228,17 @@ class TestCommand extends Command<bool> with ArgUtils {
217228
bool unitTestResult = await runUnitTests();
218229
bool integrationTestResult = await runIntegrationTests();
219230
if (integrationTestResult != unitTestResult) {
220-
print('Tests run. Integration tests passed: $integrationTestResult '
231+
print(
232+
'Tests run. Integration tests passed: $integrationTestResult '
221233
'unit tests passed: $unitTestResult');
222234
}
223235
return integrationTestResult && unitTestResult;
224236
} else {
225237
return await runUnitTests();
226238
}
227239
}
228-
throw UnimplementedError('Unknown test type requested: $testTypesRequested');
240+
throw UnimplementedError(
241+
'Unknown test type requested: $testTypesRequested');
229242
} on TestFailureException {
230243
return true;
231244
}
@@ -272,9 +285,9 @@ class TestCommand extends Command<bool> with ArgUtils {
272285
environment.webUiTestResultsDirectory.createSync(recursive: true);
273286

274287
// If screenshot tests are available, fetch the screenshot goldens.
275-
if (isScreenshotTestsAvailable) {
288+
if (isScreenshotTestsAvailable && doFetchGoldensRepo) {
276289
if (isVerboseLoggingEnabled) {
277-
print('INFO: Screenshot tests available');
290+
print('INFO: Fetching goldens repo');
278291
}
279292
final GoldensRepoFetcher goldensRepoFetcher = GoldensRepoFetcher(
280293
environment.webUiGoldensRepositoryDirectory,
@@ -483,6 +496,9 @@ class TestCommand extends Command<bool> with ArgUtils {
483496
/// ".dart_tool/goldens".
484497
bool get doUpdateScreenshotGoldens => boolArg('update-screenshot-goldens');
485498

499+
/// Whether to fetch the goldens repo prior to running tests.
500+
bool get doFetchGoldensRepo => boolArg('fetch-goldens-repo');
501+
486502
/// Runs all tests specified in [targets].
487503
///
488504
/// Unlike [_runAllTestsForCurrentPlatform], this does not filter targets
@@ -774,6 +790,7 @@ const List<String> _kTestFonts = <String>[
774790
'ahem.ttf',
775791
'Roboto-Regular.ttf',
776792
'NotoNaskhArabic-Regular.ttf',
793+
'NotoColorEmoji.ttf',
777794
];
778795

779796
void _copyTestFontsIntoWebUi() {

lib/web_ui/lib/src/engine/assets.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,16 @@ class AssetManagerException implements Exception {
8888
class WebOnlyMockAssetManager implements AssetManager {
8989
String defaultAssetsDir = '';
9090
String defaultAssetManifest = '{}';
91-
String defaultFontManifest = '[]';
91+
String defaultFontManifest = '''[
92+
{
93+
"family":"$_robotoFontFamily",
94+
"fonts":[{"asset":"$_robotoTestFontUrl"}]
95+
},
96+
{
97+
"family":"$_ahemFontFamily",
98+
"fonts":[{"asset":"$_ahemFontUrl"}]
99+
}
100+
]''';
92101

93102
@override
94103
String get assetsDir => defaultAssetsDir;

lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,17 @@ class HtmlViewEmbedder {
359359
final Set<int> unusedViews = Set<int>.from(_activeCompositionOrder);
360360
_activeCompositionOrder.clear();
361361

362+
List<int>? debugInvalidViewIds;
362363
for (int i = 0; i < _compositionOrder.length; i++) {
363364
int viewId = _compositionOrder[i];
364365

365-
assert(
366-
_views.containsKey(viewId),
367-
'Cannot render platform view $viewId. '
368-
'It has not been created, or it has been deleted.',
369-
);
366+
if (assertionsEnabled) {
367+
if (!_views.containsKey(viewId)) {
368+
debugInvalidViewIds ??= <int>[];
369+
debugInvalidViewIds.add(viewId);
370+
continue;
371+
}
372+
}
370373

371374
unusedViews.remove(viewId);
372375
html.Element platformViewRoot = _rootViews[viewId]!;
@@ -381,6 +384,16 @@ class HtmlViewEmbedder {
381384

382385
for (final int unusedViewId in unusedViews) {
383386
_releaseOverlay(unusedViewId);
387+
_rootViews[unusedViewId]?.remove();
388+
}
389+
390+
if (assertionsEnabled) {
391+
if (debugInvalidViewIds != null && debugInvalidViewIds.isNotEmpty) {
392+
throw AssertionError(
393+
'Cannot render platform views: ${debugInvalidViewIds.join(', ')}. '
394+
'These views have not been created, or they have been deleted.',
395+
);
396+
}
384397
}
385398
}
386399

@@ -476,6 +489,7 @@ class OverlayCache {
476489
for (final Surface overlay in _cache) {
477490
overlay.dispose();
478491
}
492+
_cache.clear();
479493
}
480494
}
481495

lib/web_ui/lib/src/engine/canvaskit/font_fallbacks.dart

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,19 @@ Future<void> _registerSymbolsAndEmoji() async {
211211
String? symbolsFontUrl = extractUrlFromCss(symbolsCss);
212212
String? emojiFontUrl = extractUrlFromCss(emojiCss);
213213

214-
if (symbolsFontUrl == null || emojiFontUrl == null) {
215-
html.window.console
216-
.warn('Error parsing CSS for Noto Emoji and Symbols font.');
214+
if (symbolsFontUrl != null) {
215+
notoDownloadQueue.add(_ResolvedNotoSubset(
216+
symbolsFontUrl, 'Noto Sans Symbols', const <CodeunitRange>[]));
217+
} else {
218+
html.window.console.warn('Error parsing CSS for Noto Symbols font.');
217219
}
218220

219-
notoDownloadQueue.add(_ResolvedNotoSubset(
220-
symbolsFontUrl!, 'Noto Sans Symbols', const <CodeunitRange>[]));
221-
notoDownloadQueue.add(_ResolvedNotoSubset(
222-
emojiFontUrl!, 'Noto Color Emoji Compat', const <CodeunitRange>[]));
221+
if (emojiFontUrl != null) {
222+
notoDownloadQueue.add(_ResolvedNotoSubset(
223+
emojiFontUrl, 'Noto Color Emoji Compat', const <CodeunitRange>[]));
224+
} else {
225+
html.window.console.warn('Error parsing CSS for Noto Emoji font.');
226+
}
223227
}
224228

225229
/// Finds the minimum set of fonts which covers all of the [codeunits].
@@ -388,6 +392,9 @@ class _ResolvedNotoSubset {
388392
final List<CodeunitRange> ranges;
389393

390394
_ResolvedNotoSubset(this.url, this.family, this.ranges);
395+
396+
@override
397+
String toString() => '_ResolvedNotoSubset($family, $url)';
391398
}
392399

393400
_NotoFont _notoSansSC = _NotoFont('Noto Sans SC', <CodeunitRange>[
@@ -660,21 +667,64 @@ class FallbackFontDownloadQueue {
660667
}
661668

662669
class NotoDownloader {
670+
int _debugActiveDownloadCount = 0;
671+
672+
/// Returns a future that resolves when there are no pending downloads.
673+
///
674+
/// Useful in tests to make sure that fonts are loaded before working with
675+
/// text.
676+
Future<void> debugWhenIdle() async {
677+
if (assertionsEnabled) {
678+
// Some downloads begin asynchronously in a microtask or in a Timer.run.
679+
// Let those run before waiting for downloads to finish.
680+
await Future<void>.delayed(Duration.zero);
681+
while (_debugActiveDownloadCount > 0) {
682+
await Future<void>.delayed(const Duration(milliseconds: 100));
683+
// If we started with a non-zero count and hit zero while waiting, wait a
684+
// little more to make sure another download doesn't get chained after
685+
// the last one (e.g. font file download after font CSS download).
686+
if (_debugActiveDownloadCount == 0) {
687+
await Future<void>.delayed(const Duration(milliseconds: 100));
688+
}
689+
}
690+
} else {
691+
throw UnimplementedError();
692+
}
693+
}
694+
663695
/// Downloads the [url] and returns it as a [ByteBuffer].
664696
///
665697
/// Override this for testing.
666698
Future<ByteBuffer> downloadAsBytes(String url) {
667-
return html.window.fetch(url).then((dynamic fetchResult) => fetchResult
699+
if (assertionsEnabled) {
700+
_debugActiveDownloadCount += 1;
701+
}
702+
final Future<ByteBuffer> result = html.window.fetch(url).then((dynamic fetchResult) => fetchResult
668703
.arrayBuffer()
669704
.then<ByteBuffer>((dynamic x) => x as ByteBuffer));
705+
if (assertionsEnabled) {
706+
result.whenComplete(() {
707+
_debugActiveDownloadCount -= 1;
708+
});
709+
}
710+
return result;
670711
}
671712

672713
/// Downloads the [url] and returns is as a [String].
673714
///
674715
/// Override this for testing.
675716
Future<String> downloadAsString(String url) {
676-
return html.window.fetch(url).then((dynamic response) =>
717+
if (assertionsEnabled) {
718+
_debugActiveDownloadCount += 1;
719+
}
720+
final Future<String> result = html.window.fetch(url).then((dynamic response) =>
677721
response.text().then<String>((dynamic x) => x as String));
722+
if (assertionsEnabled) {
723+
result.whenComplete(() {
724+
_debugActiveDownloadCount -= 1;
725+
});
726+
}
727+
return result;
678728
}
679729
}
680730

0 commit comments

Comments
 (0)