From e6334f166dc133360102a4c8a44de1e41b244379 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Fri, 17 Mar 2023 15:14:49 -0400 Subject: [PATCH 01/15] [web] Remove image codecs from Canvaskit Chromium (#40309) [web] Remove image codecs from Canvaskit Chromium --- .../lib/src/engine/browser_detection.dart | 4 +- .../src/engine/canvaskit/canvaskit_api.dart | 1 + .../lib/src/engine/safe_browser_api.dart | 22 ++++++--- lib/web_ui/test/browser_detect_test.dart | 49 +++++++++++++++++++ third_party/canvaskit/BUILD.gn | 13 +++++ tools/gn | 5 +- 6 files changed, 84 insertions(+), 10 deletions(-) diff --git a/lib/web_ui/lib/src/engine/browser_detection.dart b/lib/web_ui/lib/src/engine/browser_detection.dart index 4073b82b0c0f2..431a81f304808 100644 --- a/lib/web_ui/lib/src/engine/browser_detection.dart +++ b/lib/web_ui/lib/src/engine/browser_detection.dart @@ -5,6 +5,7 @@ import 'package:meta/meta.dart'; import 'dom.dart'; +import 'safe_browser_api.dart'; // iOS 15 launched WebGL 2.0, but there's something broken about it, which // leads to apps failing to load. For now, we're forcing WebGL 1 on iOS. @@ -268,4 +269,5 @@ int _detectWebGLVersion() { } /// Whether the current browser supports the Chromium variant of CanvasKit. -final bool browserSupportsCanvaskitChromium = domIntl.v8BreakIterator != null; +bool get browserSupportsCanvaskitChromium => + browserSupportsImageDecoder && domIntl.v8BreakIterator != null; diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index dbd01511304d6..00c8662ed6422 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -29,6 +29,7 @@ import 'renderer.dart'; late CanvasKit canvasKit; // TODO(mdebbar): Turn this on when CanvasKit Chromium is ready. +// Set it to `browserSupportsCanvasKitChromium`. // https://github.com/flutter/flutter/issues/122329 const bool _enableCanvasKitChromiumInAutoMode = false; diff --git a/lib/web_ui/lib/src/engine/safe_browser_api.dart b/lib/web_ui/lib/src/engine/safe_browser_api.dart index 38c7f52c3db94..c908bf514575b 100644 --- a/lib/web_ui/lib/src/engine/safe_browser_api.dart +++ b/lib/web_ui/lib/src/engine/safe_browser_api.dart @@ -217,17 +217,27 @@ const bool _browserImageDecodingEnabled = bool.fromEnvironment( ); /// Whether the current browser supports `ImageDecoder`. -bool browserSupportsImageDecoder = - _browserImageDecodingEnabled && - _imageDecoderConstructor != null && - browserEngine == BrowserEngine.blink; +bool browserSupportsImageDecoder = _defaultBrowserSupportsImageDecoder; /// Sets the value of [browserSupportsImageDecoder] to its default value. void debugResetBrowserSupportsImageDecoder() { - browserSupportsImageDecoder = - _imageDecoderConstructor != null; + browserSupportsImageDecoder = _defaultBrowserSupportsImageDecoder; } +bool get _defaultBrowserSupportsImageDecoder => + _browserImageDecodingEnabled && + _imageDecoderConstructor != null && + _isBrowserImageDecoderStable; + +// TODO(yjbanov): https://github.com/flutter/flutter/issues/122761 +// Frequently, when a browser launches an API that other browsers already +// support, there are subtle incompatibilities that may cause apps to crash if, +// we blindly adopt the new implementation. This variable prevents us from +// picking up potentially incompatible implementations of ImagdeDecoder API. +// Instead, when a new browser engine launches the API, we'll evaluate it and +// enable it explicitly. +bool get _isBrowserImageDecoderStable => browserEngine == BrowserEngine.blink; + /// The signature of the function passed to the constructor of JavaScript `Promise`. typedef JsPromiseCallback = void Function(void Function(Object? value) resolve, void Function(Object? error) reject); diff --git a/lib/web_ui/test/browser_detect_test.dart b/lib/web_ui/test/browser_detect_test.dart index ae291d0cc5bf7..ff3af2fe233dc 100644 --- a/lib/web_ui/test/browser_detect_test.dart +++ b/lib/web_ui/test/browser_detect_test.dart @@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:js/js.dart'; + import 'package:test/bootstrap/browser.dart'; import 'package:test/test.dart'; import 'package:ui/src/engine/browser_detection.dart'; +import 'package:ui/src/engine/safe_browser_api.dart'; void main() { internalBootstrapBrowserTest(() => testMain); @@ -152,4 +155,50 @@ void testMain() { ); }); }); + + group('browserSupportsCanvasKitChromium', () { + late dynamic oldV8BreakIterator = v8BreakIterator; + setUp(() { + oldV8BreakIterator = v8BreakIterator; + }); + tearDown(() { + v8BreakIterator = oldV8BreakIterator; + debugResetBrowserSupportsImageDecoder(); + }); + + test('Detect browsers that support CanvasKit Chromium', () { + v8BreakIterator = Object(); // Any non-null value. + browserSupportsImageDecoder = true; + + expect(browserSupportsCanvaskitChromium, isTrue); + }); + + test('Detect browsers that do not support image codecs', () { + v8BreakIterator = Object(); // Any non-null value. + browserSupportsImageDecoder = false; + + expect(browserSupportsCanvaskitChromium, isFalse); + }); + + test('Detect browsers that do not support v8BreakIterator', () { + v8BreakIterator = null; + browserSupportsImageDecoder = true; + + expect(browserSupportsCanvaskitChromium, isFalse); + }); + + test('Detect browsers that support neither', () { + v8BreakIterator = null; + browserSupportsImageDecoder = false; + + expect(browserSupportsCanvaskitChromium, isFalse); + }); + }); } + + +@JS('window.Intl.v8BreakIterator') +external dynamic get v8BreakIterator; + +@JS('window.Intl.v8BreakIterator') +external set v8BreakIterator(dynamic x); diff --git a/third_party/canvaskit/BUILD.gn b/third_party/canvaskit/BUILD.gn index 188bfdff04692..fe7032bfd5b77 100644 --- a/third_party/canvaskit/BUILD.gn +++ b/third_party/canvaskit/BUILD.gn @@ -7,8 +7,14 @@ import("//build/toolchain/wasm.gni") # This toolchain is only to be used by the canvaskit target below. wasm_toolchain("canvaskit") { extra_toolchain_args = { + # Include ICU data. skia_use_icu = true skia_use_client_icu = false + + # Include image codecs. + skia_use_libjpeg_turbo_decode = true + skia_use_libpng_decode = true + skia_use_libwebp_decode = true } } @@ -20,9 +26,16 @@ group("canvaskit_group") { # This toolchain is only to be used by canvaskit_chromium_group below. wasm_toolchain("canvaskit_chromium") { extra_toolchain_args = { + # In Chromium browsers, we can use the browser's APIs to get the necessary + # ICU data. skia_use_icu = false skia_use_client_icu = true skia_icu_bidi_third_party_dir = "//flutter/third_party/canvaskit/icu_bidi" + + # In Chromium browsers, we can use the browser's built-in codecs. + skia_use_libjpeg_turbo_decode = false + skia_use_libpng_decode = false + skia_use_libwebp_decode = false } } diff --git a/tools/gn b/tools/gn index 0dccbe5177250..eba9f4984fd72 100755 --- a/tools/gn +++ b/tools/gn @@ -617,11 +617,10 @@ def to_gn_wasm_args(args, gn_args): gn_args['skia_use_vulkan'] = False gn_args['skia_use_webgpu'] = False gn_args['skia_use_libheif'] = False - gn_args['skia_use_libjpeg_turbo_decode'] = True gn_args['skia_use_libjpeg_turbo_encode'] = False - gn_args['skia_use_libpng_decode'] = True + # TODO(yjbanov): https://github.com/flutter/flutter/issues/122759 + # Remove this and implement it through Canvas2d. gn_args['skia_use_libpng_encode'] = True - gn_args['skia_use_libwebp_decode'] = True gn_args['skia_use_libwebp_encode'] = False gn_args['skia_use_lua'] = False gn_args['skia_use_wuffs'] = True From 56727d62c7070df97fb91c433a9a6d70c1044b95 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 17 Mar 2023 12:14:52 -0700 Subject: [PATCH 02/15] Revert "[Impeller] mark decoded images as optimized for GPU access (#40356)" (#40387) Revert "[Impeller] mark decoded images as optimized for GPU access" --- .../renderer/backend/gles/blit_pass_gles.cc | 5 ----- .../renderer/backend/gles/blit_pass_gles.h | 4 ---- .../renderer/backend/metal/blit_command_mtl.h | 9 --------- .../backend/metal/blit_command_mtl.mm | 19 ------------------- .../renderer/backend/metal/blit_pass_mtl.h | 4 ---- .../renderer/backend/metal/blit_pass_mtl.mm | 11 ----------- .../renderer/backend/vulkan/blit_pass_vk.cc | 6 ------ .../renderer/backend/vulkan/blit_pass_vk.h | 3 --- impeller/renderer/blit_pass.cc | 5 ----- impeller/renderer/blit_pass.h | 16 ---------------- impeller/renderer/testing/mocks.h | 3 --- lib/ui/painting/image_decoder_impeller.cc | 1 - 12 files changed, 86 deletions(-) diff --git a/impeller/renderer/backend/gles/blit_pass_gles.cc b/impeller/renderer/backend/gles/blit_pass_gles.cc index 4819670db49fb..8685d86aa4a29 100644 --- a/impeller/renderer/backend/gles/blit_pass_gles.cc +++ b/impeller/renderer/backend/gles/blit_pass_gles.cc @@ -130,11 +130,6 @@ bool BlitPassGLES::OnCopyTextureToBufferCommand( return true; } -bool BlitPassGLES::OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) { - return true; -} - // |BlitPass| bool BlitPassGLES::OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) { diff --git a/impeller/renderer/backend/gles/blit_pass_gles.h b/impeller/renderer/backend/gles/blit_pass_gles.h index 146aedf953a1b..deaf1a41835f4 100644 --- a/impeller/renderer/backend/gles/blit_pass_gles.h +++ b/impeller/renderer/backend/gles/blit_pass_gles.h @@ -50,10 +50,6 @@ class BlitPassGLES final : public BlitPass { size_t destination_offset, std::string label) override; - // |BlitPass| - bool OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) override; - // |BlitPass| bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; diff --git a/impeller/renderer/backend/metal/blit_command_mtl.h b/impeller/renderer/backend/metal/blit_command_mtl.h index b1411ce8c8063..ffdd450f16c9b 100644 --- a/impeller/renderer/backend/metal/blit_command_mtl.h +++ b/impeller/renderer/backend/metal/blit_command_mtl.h @@ -50,13 +50,4 @@ struct BlitGenerateMipmapCommandMTL : public BlitGenerateMipmapCommand, [[nodiscard]] bool Encode(id encoder) const override; }; -struct BlitOptimizeGPUAccessCommandMTL : public BlitGenerateMipmapCommand, - public BlitEncodeMTL { - ~BlitOptimizeGPUAccessCommandMTL() override; - - std::string GetLabel() const override; - - [[nodiscard]] bool Encode(id encoder) const override; -}; - } // namespace impeller diff --git a/impeller/renderer/backend/metal/blit_command_mtl.mm b/impeller/renderer/backend/metal/blit_command_mtl.mm index 2981faef692c8..7f589b4f54175 100644 --- a/impeller/renderer/backend/metal/blit_command_mtl.mm +++ b/impeller/renderer/backend/metal/blit_command_mtl.mm @@ -112,23 +112,4 @@ return true; }; -BlitOptimizeGPUAccessCommandMTL::~BlitOptimizeGPUAccessCommandMTL() = default; - -std::string BlitOptimizeGPUAccessCommandMTL::GetLabel() const { - return label; -} - -bool BlitOptimizeGPUAccessCommandMTL::Encode( - id encoder) const { - if (@available(macOS 10.14, iOS 12, tvOS 12, *)) { - auto texture_mtl = TextureMTL::Cast(*texture).GetMTLTexture(); - if (!texture_mtl) { - return false; - } - - [encoder optimizeContentsForGPUAccess:texture_mtl]; - } - return true; -} - } // namespace impeller diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.h b/impeller/renderer/backend/metal/blit_pass_mtl.h index 836273819da28..108d320d98bf0 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.h +++ b/impeller/renderer/backend/metal/blit_pass_mtl.h @@ -57,10 +57,6 @@ class BlitPassMTL final : public BlitPass { bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; - // |BlitPass| - bool OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) override; - FML_DISALLOW_COPY_AND_ASSIGN(BlitPassMTL); }; diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.mm b/impeller/renderer/backend/metal/blit_pass_mtl.mm index 9b084eb5f043b..74df114143655 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.mm +++ b/impeller/renderer/backend/metal/blit_pass_mtl.mm @@ -134,15 +134,4 @@ return true; } -// |BlitPass| -bool BlitPassMTL::OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) { - auto command = std::make_unique(); - command->label = label; - command->texture = std::move(texture); - - commands_.emplace_back(std::move(command)); - return true; -} - } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.cc b/impeller/renderer/backend/vulkan/blit_pass_vk.cc index e649a73d51b20..f563681af3455 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.cc @@ -87,12 +87,6 @@ bool BlitPassVK::OnCopyTextureToBufferCommand( return true; } -// |BlitPass| -bool BlitPassVK::OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) { - return true; -} - // |BlitPass| bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) { diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.h b/impeller/renderer/backend/vulkan/blit_pass_vk.h index 72f8b40ea01e2..62e52c15477bc 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.h +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.h @@ -51,9 +51,6 @@ class BlitPassVK final : public BlitPass { std::string label) override; // |BlitPass| - bool OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) override; - // |BlitPass| bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; diff --git a/impeller/renderer/blit_pass.cc b/impeller/renderer/blit_pass.cc index 14760889e14aa..dd53e125645b5 100644 --- a/impeller/renderer/blit_pass.cc +++ b/impeller/renderer/blit_pass.cc @@ -116,11 +116,6 @@ bool BlitPass::AddCopy(std::shared_ptr source, std::move(label)); } -bool BlitPass::OptimizeForGPUAccess(std::shared_ptr texture, - std::string label) { - return OnOptimizeForGPUAccess(std::move(texture), std::move(label)); -} - bool BlitPass::GenerateMipmap(std::shared_ptr texture, std::string label) { if (!texture) { diff --git a/impeller/renderer/blit_pass.h b/impeller/renderer/blit_pass.h index 5341c20f62de5..7ac7b820e5972 100644 --- a/impeller/renderer/blit_pass.h +++ b/impeller/renderer/blit_pass.h @@ -95,19 +95,6 @@ class BlitPass { /// bool GenerateMipmap(std::shared_ptr texture, std::string label = ""); - //---------------------------------------------------------------------------- - /// @brief Optimize the provided texture for GPU access. - /// This will no-op on platforms where this functionality is - /// unsupported. - /// - /// @param[in] texture The texture to generate mipmaps for. - /// @param[in] label The optional debug label to give the command. - /// - /// @return If the command was valid for subsequent commitment. - /// - bool OptimizeForGPUAccess(std::shared_ptr texture, - std::string label = ""); - //---------------------------------------------------------------------------- /// @brief Encode the recorded commands to the underlying command buffer. /// @@ -140,9 +127,6 @@ class BlitPass { size_t destination_offset, std::string label) = 0; - virtual bool OnOptimizeForGPUAccess(std::shared_ptr texture, - std::string label) = 0; - virtual bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) = 0; diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 29f4faa01e37b..1f387ee58e05a 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -62,9 +62,6 @@ class MockBlitPass : public BlitPass { size_t destination_offset, std::string label)); - MOCK_METHOD2(OnOptimizeForGPUAccess, - bool(std::shared_ptr texture, std::string label)); - MOCK_METHOD2(OnGenerateMipmapCommand, bool(std::shared_ptr texture, std::string label)); }; diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index 3c6ba866e0da7..a6a130b3932c0 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -286,7 +286,6 @@ sk_sp ImageDecoderImpeller::UploadTexture( } blit_pass->SetLabel("Mipmap Blit Pass"); blit_pass->GenerateMipmap(texture); - blit_pass->OptimizeForGPUAccess(texture); blit_pass->EncodeCommands(context->GetResourceAllocator()); if (!command_buffer->SubmitCommands()) { From 2cd19e3d12efffee83736b71908796b7005a1c4e Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Fri, 17 Mar 2023 12:15:47 -0700 Subject: [PATCH 03/15] Wrap the iOS platform message handler in an autorelease pool block (#40373) Wrap the iOS platform message handler in an autorelease pool block --- .../ios/platform_message_handler_ios.mm | 84 ++++++++++--------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/shell/platform/darwin/ios/platform_message_handler_ios.mm b/shell/platform/darwin/ios/platform_message_handler_ios.mm index df6582882f751..8a1b2ebe0d66b 100644 --- a/shell/platform/darwin/ios/platform_message_handler_ios.mm +++ b/shell/platform/darwin/ios/platform_message_handler_ios.mm @@ -46,50 +46,52 @@ - (void)dispatch:(dispatch_block_t)block { void PlatformMessageHandlerIos::HandlePlatformMessage(std::unique_ptr message) { // This can be called from any isolate's thread. - fml::RefPtr completer = message->response(); - HandlerInfo handler_info; - { - // TODO(gaaclarke): This mutex is a bottleneck for multiple isolates sending - // messages at the same time. This could be potentially changed to a - // read-write lock. - std::lock_guard lock(message_handlers_mutex_); - auto it = message_handlers_.find(message->channel()); - if (it != message_handlers_.end()) { - handler_info = it->second; + @autoreleasepool { + fml::RefPtr completer = message->response(); + HandlerInfo handler_info; + { + // TODO(gaaclarke): This mutex is a bottleneck for multiple isolates sending + // messages at the same time. This could be potentially changed to a + // read-write lock. + std::lock_guard lock(message_handlers_mutex_); + auto it = message_handlers_.find(message->channel()); + if (it != message_handlers_.end()) { + handler_info = it->second; + } } - } - if (handler_info.handler) { - FlutterBinaryMessageHandler handler = handler_info.handler; - NSData* data = nil; - if (message->hasData()) { - data = ConvertMappingToNSData(message->releaseData()); - } - - uint64_t platform_message_id = platform_message_counter++; - TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id, - "channel", message->channel().c_str()); - dispatch_block_t run_handler = ^{ - handler(data, ^(NSData* reply) { - TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id); - // Called from any thread. - if (completer) { - if (reply) { - completer->Complete(ConvertNSDataToMappingPtr(reply)); - } else { - completer->CompleteEmpty(); + if (handler_info.handler) { + FlutterBinaryMessageHandler handler = handler_info.handler; + NSData* data = nil; + if (message->hasData()) { + data = ConvertMappingToNSData(message->releaseData()); + } + + uint64_t platform_message_id = platform_message_counter++; + TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id, + "channel", message->channel().c_str()); + dispatch_block_t run_handler = ^{ + handler(data, ^(NSData* reply) { + TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id); + // Called from any thread. + if (completer) { + if (reply) { + completer->Complete(ConvertNSDataToMappingPtr(reply)); + } else { + completer->CompleteEmpty(); + } } - } - }); - }; - - if (handler_info.task_queue.get()) { - [handler_info.task_queue.get() dispatch:run_handler]; + }); + }; + + if (handler_info.task_queue.get()) { + [handler_info.task_queue.get() dispatch:run_handler]; + } else { + dispatch_async(dispatch_get_main_queue(), run_handler); + } } else { - dispatch_async(dispatch_get_main_queue(), run_handler); - } - } else { - if (completer) { - completer->CompleteEmpty(); + if (completer) { + completer->CompleteEmpty(); + } } } } From bab7853adad86b70605139d385ebd46dcfe2e45f Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Fri, 17 Mar 2023 12:15:50 -0700 Subject: [PATCH 04/15] Update analyzer for api_conform_test (#40386) Update analyzer for api_conform_test --- web_sdk/pubspec.yaml | 2 +- web_sdk/test/api_conform_test.dart | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/web_sdk/pubspec.yaml b/web_sdk/pubspec.yaml index 448654dfad4ed..0a6691711c262 100644 --- a/web_sdk/pubspec.yaml +++ b/web_sdk/pubspec.yaml @@ -9,6 +9,6 @@ dependencies: path: 1.8.2 dev_dependencies: - analyzer: 5.7.1 + analyzer: 5.8.0 test: 1.22.1 pub_semver: 2.1.3 diff --git a/web_sdk/test/api_conform_test.dart b/web_sdk/test/api_conform_test.dart index 21d14dce0524c..b3368b0215983 100644 --- a/web_sdk/test/api_conform_test.dart +++ b/web_sdk/test/api_conform_test.dart @@ -10,7 +10,6 @@ import 'package:analyzer/dart/analysis/features.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/utilities.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:pub_semver/pub_semver.dart'; // Ignore members defined on Object. const Set _kObjectMembers = { @@ -20,10 +19,7 @@ const Set _kObjectMembers = { }; CompilationUnit _parseAndCheckDart(String path) { - final FeatureSet analyzerFeatures = FeatureSet.fromEnableFlags2( - flags: ['class-modifiers', 'sealed-class', 'records', 'patterns'], - sdkLanguageVersion: Version.parse('3.0.0-0'), - ); + final FeatureSet analyzerFeatures = FeatureSet.latestLanguageVersion(); if (!analyzerFeatures.isEnabled(Feature.non_nullable)) { throw Exception('non-nullable feature is disabled.'); } From 87b2e82d1392becf32a68eee938985b7687da483 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Fri, 17 Mar 2023 15:15:52 -0400 Subject: [PATCH 05/15] Roll Fuchsia Mac SDK from z32cF6YFs6CvZbY3g... to 4ZrEK2uzGdp_Gz3DU... (#40385) Roll Fuchsia Mac SDK from z32cF6YFs6CvZbY3g... to 4ZrEK2uzGdp_Gz3DU... --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index b039775344165..36968e1d9f71a 100644 --- a/DEPS +++ b/DEPS @@ -832,7 +832,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/mac-amd64', - 'version': 'z32cF6YFs6CvZbY3gLSIyhUnc4vPYMt_zhI7ONd6AGQC' + 'version': '4ZrEK2uzGdp_Gz3DUhs5i6102CjKK_pVXgYqh5mccRoC' } ], 'condition': 'host_os == "mac" and not download_fuchsia_sdk', From fc57995fe137d883016a6c115bf45710883cd77c Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Fri, 17 Mar 2023 13:05:43 -0700 Subject: [PATCH 06/15] Ignore some MTLCompiler failures in impeller unit tests (#40391) --- testing/run_tests.py | 84 +++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/testing/run_tests.py b/testing/run_tests.py index 9961cd1e53fe9..23be9205b1d45 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -52,10 +52,17 @@ def is_asan(build_dir): def run_cmd( - cmd, forbidden_output=None, expect_failure=False, env=None, **kwargs + cmd, + forbidden_output=None, + expect_failure=False, + env=None, + allowed_failure_output=None, + **kwargs ): if forbidden_output is None: forbidden_output = [] + if allowed_failure_output is None: + allowed_failure_output = [] command_string = ' '.join(cmd) @@ -63,8 +70,9 @@ def run_cmd( print('Running command "%s"' % command_string) start_time = time.time() - stdout_pipe = sys.stdout if not forbidden_output else subprocess.PIPE - stderr_pipe = sys.stderr if not forbidden_output else subprocess.PIPE + collect_output = forbidden_output or allowed_failure_output + stdout_pipe = sys.stdout if not collect_output else subprocess.PIPE + stderr_pipe = sys.stderr if not collect_output else subprocess.PIPE process = subprocess.Popen( cmd, stdout=stdout_pipe, @@ -92,10 +100,17 @@ def run_cmd( print_divider('!') - raise Exception( - 'Command "%s" exited with code %d.' % - (command_string, process.returncode) - ) + allowed_failure = False + for allowed_string in allowed_failure_output: + if (stdout and allowed_string in stdout) or (stderr and + allowed_string in stderr): + allowed_failure = True + + if not allowed_failure: + raise Exception( + 'Command "%s" exited with code %d.' % + (command_string, process.returncode) + ) if stdout or stderr: print(stdout) @@ -192,6 +207,7 @@ def run_engine_executable( # pylint: disable=too-many-arguments flags=None, cwd=BUILDROOT_DIR, forbidden_output=None, + allowed_failure_output=None, expect_failure=False, coverage=False, extra_env=None, @@ -205,6 +221,8 @@ def run_engine_executable( # pylint: disable=too-many-arguments flags = [] if forbidden_output is None: forbidden_output = [] + if allowed_failure_output is None: + allowed_failure_output = [] if extra_env is None: extra_env = {} @@ -249,7 +267,8 @@ def run_engine_executable( # pylint: disable=too-many-arguments cwd=cwd, forbidden_output=forbidden_output, expect_failure=expect_failure, - env=env + env=env, + allowed_failure_output=allowed_failure_output ) except: # The LUCI environment may provide a variable containing a directory path @@ -287,6 +306,7 @@ def __init__( # pylint: disable=too-many-arguments flags=None, cwd=BUILDROOT_DIR, forbidden_output=None, + allowed_failure_output=None, expect_failure=False, coverage=False, extra_env=None, @@ -297,6 +317,7 @@ def __init__( # pylint: disable=too-many-arguments self.flags = flags self.cwd = cwd self.forbidden_output = forbidden_output + self.allowed_failure_output = allowed_failure_output self.expect_failure = expect_failure self.coverage = coverage self.extra_env = extra_env @@ -309,6 +330,7 @@ def __call__(self, *args): flags=self.flags, cwd=self.cwd, forbidden_output=self.forbidden_output, + allowed_failure_output=self.allowed_failure_output, expect_failure=self.expect_failure, coverage=self.coverage, extra_env=self.extra_env, @@ -442,28 +464,32 @@ def make_test(name, flags=None, extra_env=None): shuffle_flags, coverage=coverage ) - # TODO(117122): Re-enable impeller_unittests after shader compiler errors - # are addressed. # Impeller tests are only supported on macOS for now. - # run_engine_executable( - # build_dir, - # 'impeller_unittests', - # executable_filter, - # shuffle_flags, - # coverage=coverage, - # extra_env={ - # # pylint: disable=line-too-long - # # See https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early?language=objc - # 'MTL_SHADER_VALIDATION': - # '1', # Enables all shader validation tests. - # 'MTL_SHADER_VALIDATION_GLOBAL_MEMORY': - # '1', # Validates accesses to device and constant memory. - # 'MTL_SHADER_VALIDATION_THREADGROUP_MEMORY': - # '1', # Validates accesses to threadgroup memory. - # 'MTL_SHADER_VALIDATION_TEXTURE_USAGE': - # '1', # Validates that texture references are not nil. - # } - # ) + run_engine_executable( + build_dir, + 'impeller_unittests', + executable_filter, + shuffle_flags, + coverage=coverage, + extra_env={ + # pylint: disable=line-too-long + # See https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early?language=objc + 'MTL_SHADER_VALIDATION': + '1', # Enables all shader validation tests. + 'MTL_SHADER_VALIDATION_GLOBAL_MEMORY': + '1', # Validates accesses to device and constant memory. + 'MTL_SHADER_VALIDATION_THREADGROUP_MEMORY': + '1', # Validates accesses to threadgroup memory. + 'MTL_SHADER_VALIDATION_TEXTURE_USAGE': + '1', # Validates that texture references are not nil. + }, + # TODO(117122): Remove this allowlist. + # https://github.com/flutter/flutter/issues/114872 + allowed_failure_output=[ + '[MTLCompiler createVertexStageAndLinkPipelineWithFragment:', + '[MTLCompiler pipelineStateWithVariant:', + ] + ) def parse_impeller_vulkan_filter(): From 2398c522219b9ba02b3b869159b10bd8bc75308b Mon Sep 17 00:00:00 2001 From: Chris Bracken Date: Fri, 17 Mar 2023 13:38:55 -0700 Subject: [PATCH 07/15] Add doc comment to Pipeline (#40388) Add doc comment to Pipeline --- fml/synchronization/semaphore.h | 2 +- shell/common/pipeline.h | 41 +++++++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/fml/synchronization/semaphore.h b/fml/synchronization/semaphore.h index b88be468ee27c..38d1488d64870 100644 --- a/fml/synchronization/semaphore.h +++ b/fml/synchronization/semaphore.h @@ -67,7 +67,7 @@ class Semaphore { /// Which makes doing the validity check before this call doubly /// important. /// - /// @return If the count could be decrement. + /// @return If the count could be decremented. /// [[nodiscard]] bool TryWait(); diff --git a/shell/common/pipeline.h b/shell/common/pipeline.h index e8b17768cba2f..1de4498e7f08c 100644 --- a/shell/common/pipeline.h +++ b/shell/common/pipeline.h @@ -35,7 +35,29 @@ enum class PipelineConsumeResult { size_t GetNextPipelineTraceID(); /// A thread-safe queue of resources for a single consumer and a single -/// producer. +/// producer, with a maximum queue depth. +/// +/// Pipelines support two key operations: produce and consume. +/// +/// The consumer calls |Consume| to wait for a resource to be produced and +/// consume it when ready. +/// +/// The producer calls |Produce| to generate a `ProducerContinuation` which +/// provides a means to enqueue a resource in the pipeline, if the pipeline is +/// below its maximum depth. When the resource has been prepared, the producer +/// calls `Complete` on the continuation, which enqueues the resource and +/// signals the waiting consumer. +/// +/// Pipelines generate the following tracing information: +/// * PipelineItem: async flow tracking time taken from the time a producer +/// calls |Produce| to the time a consumer consumes calls |Consume|. +/// * PipelineProduce: async flow tracking time taken from the time a producer +/// calls |Produce| to the time they complete the `ProducerContinuation` with +/// a resource. +/// * Pipeline Depth: counter of inflight resource producers. +/// +/// The primary use of this class is as the frame pipeline used in Flutter's +/// animator/rasterizer. template class Pipeline { public: @@ -70,6 +92,7 @@ class Pipeline { } } + /// Completes the continuation with the specified resource. [[nodiscard]] PipelineProduceResult Complete(ResourcePtr resource) { PipelineProduceResult result; if (continuation_) { @@ -108,6 +131,11 @@ class Pipeline { bool IsValid() const { return empty_.IsValid() && available_.IsValid(); } + /// Creates a `ProducerContinuation` that a producer can use to add a + /// resource to the queue. + /// + /// If the queue is already at its maximum depth, the `ProducerContinuation` + /// is returned with success = false. ProducerContinuation Produce() { if (!empty_.TryWait()) { return {}; @@ -124,10 +152,11 @@ class Pipeline { GetNextPipelineTraceID()}; // trace id } - // Create a `ProducerContinuation` that will only push the task if the queue - // is empty. - // Prefer using |Produce|. ProducerContinuation returned by this method - // doesn't guarantee that the frame will be rendered. + /// Creates a `ProducerContinuation` that will only push the task if the + /// queue is empty. + /// + /// Prefer using |Produce|. ProducerContinuation returned by this method + /// doesn't guarantee that the frame will be rendered. ProducerContinuation ProduceIfEmpty() { if (!empty_.TryWait()) { return {}; @@ -186,6 +215,8 @@ class Pipeline { std::mutex queue_mutex_; std::deque> queue_; + /// Commits a produced resource to the queue and signals the consumer that a + /// resource is available. PipelineProduceResult ProducerCommit(ResourcePtr resource, size_t trace_id) { bool is_first_item = false; { From f585d4bc588a467a81e907b3064473607a51f54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Sharma?= <737941+loic-sharma@users.noreply.github.com> Date: Fri, 17 Mar 2023 13:53:39 -0700 Subject: [PATCH 08/15] [macOS] Remove a single accessibility root assumption (#40316) [macOS] Remove a single accessibility root assumption --- shell/platform/common/accessibility_bridge.h | 7 -- .../Source/AccessibilityBridgeMac.mm | 4 +- .../Source/AccessibilityBridgeMacTest.mm | 83 ++++++++++++++++++- 3 files changed, 81 insertions(+), 13 deletions(-) diff --git a/shell/platform/common/accessibility_bridge.h b/shell/platform/common/accessibility_bridge.h index b654dad66f8bb..bc9567624f4b1 100644 --- a/shell/platform/common/accessibility_bridge.h +++ b/shell/platform/common/accessibility_bridge.h @@ -48,13 +48,6 @@ class AccessibilityBridge AccessibilityBridge(); virtual ~AccessibilityBridge(); - //----------------------------------------------------------------------------- - /// @brief The ID of the root node in the accessibility tree. In Flutter, - /// this is always 0. - // TODO(loicsharma): Remove this as it is incorrect in a multi-view world. - // See: https://github.com/flutter/flutter/issues/119391 - static constexpr int32_t kRootNodeId = 0; - //------------------------------------------------------------------------------ /// @brief Adds a semantics node update to the pending semantics update. /// Calling this method alone will NOT update the semantics tree. diff --git a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.mm b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.mm index d124bcfe34826..be715db20c99f 100644 --- a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.mm +++ b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.mm @@ -187,9 +187,7 @@ if (ax_node.data().HasState(ax::mojom::State::kEditable)) { events.push_back({ .name = NSAccessibilityValueChangedNotification, - .target = GetFlutterPlatformNodeDelegateFromID(AccessibilityBridge::kRootNodeId) - .lock() - ->GetNativeViewAccessible(), + .target = RootDelegate()->GetNativeViewAccessible(), .user_info = nil, }); } diff --git a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm index c13335dd63033..fdb11ece0a6c8 100644 --- a/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm +++ b/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMacTest.mm @@ -58,7 +58,7 @@ @implementation AccessibilityBridgeTestViewController } } // namespace -TEST(AccessibilityBridgeMacTest, sendsAccessibilityCreateNotificationToWindowOfFlutterView) { +TEST(AccessibilityBridgeMacTest, SendsAccessibilityCreateNotificationToWindowOfFlutterView) { FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; [viewController loadView]; @@ -112,7 +112,84 @@ @implementation AccessibilityBridgeTestViewController [engine shutDownEngine]; } -TEST(AccessibilityBridgeMacTest, doesNotSendAccessibilityCreateNotificationWhenHeadless) { +// Flutter used to assume that the accessibility root had ID 0. +// In a multi-view world, each view has its own accessibility root +// with a globally unique node ID. +// +// node1 +// | +// node2 +TEST(AccessibilityBridgeMacTest, NonZeroRootNodeId) { + FlutterViewController* viewController = CreateTestViewController(); + FlutterEngine* engine = viewController.engine; + [viewController loadView]; + + NSWindow* expectedTarget = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600) + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + expectedTarget.contentView = viewController.view; + // Setting up bridge so that the AccessibilityBridgeMacDelegateSpy + // can query semantics information from. + engine.semanticsEnabled = YES; + auto bridge = std::static_pointer_cast( + viewController.accessibilityBridge.lock()); + + FlutterSemanticsNode node1; + std::vector node1_children{2}; + node1.id = 1; + node1.flags = static_cast(0); + node1.actions = static_cast(0); + node1.text_selection_base = -1; + node1.text_selection_extent = -1; + node1.label = "node1"; + node1.hint = ""; + node1.value = ""; + node1.increased_value = ""; + node1.decreased_value = ""; + node1.tooltip = ""; + node1.child_count = node1_children.size(); + node1.children_in_traversal_order = node1_children.data(); + node1.children_in_hit_test_order = node1_children.data(); + node1.custom_accessibility_actions_count = 0; + + FlutterSemanticsNode node2; + node2.id = 2; + node2.flags = static_cast(0); + node2.actions = static_cast(0); + node2.text_selection_base = -1; + node2.text_selection_extent = -1; + node2.label = "node2"; + node2.hint = ""; + node2.value = ""; + node2.increased_value = ""; + node2.decreased_value = ""; + node2.tooltip = ""; + node2.child_count = 0; + node2.custom_accessibility_actions_count = 0; + + bridge->AddFlutterSemanticsNodeUpdate(node1); + bridge->AddFlutterSemanticsNodeUpdate(node2); + bridge->CommitUpdates(); + + // Look up the root node delegate. + auto root_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock(); + ASSERT_TRUE(root_delegate); + ASSERT_EQ(root_delegate->GetChildCount(), 1); + + // Look up the child node delegate. + auto child_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock(); + ASSERT_TRUE(child_delegate); + ASSERT_EQ(child_delegate->GetChildCount(), 0); + + // Ensure a node with ID 0 does not exist. + auto invalid_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock(); + ASSERT_FALSE(invalid_delegate); + + [engine shutDownEngine]; +} + +TEST(AccessibilityBridgeMacTest, DoesNotSendAccessibilityCreateNotificationWhenHeadless) { FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; [viewController loadView]; @@ -158,7 +235,7 @@ @implementation AccessibilityBridgeTestViewController [engine shutDownEngine]; } -TEST(AccessibilityBridgeMacTest, doesNotSendAccessibilityCreateNotificationWhenNoWindow) { +TEST(AccessibilityBridgeMacTest, DoesNotSendAccessibilityCreateNotificationWhenNoWindow) { FlutterViewController* viewController = CreateTestViewController(); FlutterEngine* engine = viewController.engine; [viewController loadView]; From 940cf3c9809d4c1db7d80322935eb52cc6e3b48c Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Fri, 17 Mar 2023 13:58:46 -0700 Subject: [PATCH 09/15] remove temporary flag and make FlutterTest the default font for real (#40352) Remove temporary flag and make FlutterTest the default font for real --- runtime/test_font_data.cc | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/runtime/test_font_data.cc b/runtime/test_font_data.cc index 462b1440258aa..3dbe58f2548bd 100644 --- a/runtime/test_font_data.cc +++ b/runtime/test_font_data.cc @@ -1621,19 +1621,10 @@ namespace flutter { std::vector> GetTestFontData() { std::vector> typefaces; #if EMBED_TEST_FONT_DATA - const bool defaultsToAhem = - std::getenv("FLUTTER_ROOT") && !std::getenv("USE_FLUTTER_TEST_FONT"); - if (defaultsToAhem) { - typefaces.push_back(SkTypeface::MakeFromStream( - SkMemoryStream::MakeDirect(kAhemFont, kAhemFontLength))); - typefaces.push_back(SkTypeface::MakeFromStream( - SkMemoryStream::MakeDirect(kFlutterTestFont, kFlutterTestFontLength))); - } else { - typefaces.push_back(SkTypeface::MakeFromStream( - SkMemoryStream::MakeDirect(kFlutterTestFont, kFlutterTestFontLength))); - typefaces.push_back(SkTypeface::MakeFromStream( - SkMemoryStream::MakeDirect(kAhemFont, kAhemFontLength))); - } + typefaces.push_back(SkTypeface::MakeFromStream( + SkMemoryStream::MakeDirect(kFlutterTestFont, kFlutterTestFontLength))); + typefaces.push_back(SkTypeface::MakeFromStream( + SkMemoryStream::MakeDirect(kAhemFont, kAhemFontLength))); typefaces.push_back(SkTypeface::MakeFromStream( SkMemoryStream::MakeDirect(kCoughFont, kCoughFontLength))); #endif // EMBED_TEST_FONT_DATA @@ -1643,13 +1634,7 @@ std::vector> GetTestFontData() { std::vector GetTestFontFamilyNames() { std::vector names; #if EMBED_TEST_FONT_DATA - const bool defaultsToAhem = - std::getenv("FLUTTER_ROOT") && !std::getenv("USE_FLUTTER_TEST_FONT"); - if (defaultsToAhem) { - names = {"Ahem", "FlutterTest", "Cough"}; - } else { - names = {"FlutterTest", "Ahem", "Cough"}; - } + names = {"FlutterTest", "Ahem", "Cough"}; #endif // EMBED_TEST_FONT_DATA return names; } From a1bf9fd2adb58d335206efc921050fb9b391c307 Mon Sep 17 00:00:00 2001 From: Jim Graham Date: Fri, 17 Mar 2023 14:13:04 -0700 Subject: [PATCH 10/15] drawTextBlob should not be compatible with opacity inheritance (#40396) drawTextBlob should not be compatible with opacity inheritance --- display_list/display_list_builder.cc | 7 ++++++- display_list/display_list_unittests.cc | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index 160f35e005eb8..30ca37dbe454d 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -1124,7 +1124,12 @@ void DisplayListBuilder::drawTextBlob(const sk_sp blob, SkScalar y) { Push(0, 1, blob, x, y); AccumulateOpBounds(blob->bounds().makeOffset(x, y), kDrawTextBlobFlags); - CheckLayerOpacityCompatibility(); + // There is no way to query if the glyphs of a text blob overlap and + // there are no current guarantees from either Skia or Impeller that + // they will protect overlapping glyphs from the effects of overdraw + // so we must make the conservative assessment that this DL layer is + // not compatible with group opacity inheritance. + UpdateLayerOpacityCompatibility(false); } void DisplayListBuilder::DrawTextBlob(const sk_sp& blob, SkScalar x, diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 9b942bb442ead..b2ac33ed5e8e5 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -645,7 +645,7 @@ TEST(DisplayList, SingleOpsMightSupportGroupOpacityWithOrWithoutBlendMode) { static auto display_list = builder.Build(); RUN_TESTS2(builder.drawDisplayList(display_list);, false); } - RUN_TESTS(builder.drawTextBlob(TestBlob1, 0, 0);); + RUN_TESTS2(builder.drawTextBlob(TestBlob1, 0, 0);, false); RUN_TESTS2(builder.drawShadow(kTestPath1, SK_ColorBLACK, 1.0, false, 1.0); , false); From 55bf0d85edf43b4efda2d1f9c209f08a7bf64863 Mon Sep 17 00:00:00 2001 From: Michael Goderbauer Date: Fri, 17 Mar 2023 14:21:04 -0700 Subject: [PATCH 11/15] Use bundled analyzer everywhere (#40398) Use analyzer from dart source everywhere --- web_sdk/pubspec.yaml | 46 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/web_sdk/pubspec.yaml b/web_sdk/pubspec.yaml index 0a6691711c262..01325c453a050 100644 --- a/web_sdk/pubspec.yaml +++ b/web_sdk/pubspec.yaml @@ -6,9 +6,49 @@ environment: dependencies: args: 2.3.1 - path: 1.8.2 + path: any # see dependency_overrides dev_dependencies: - analyzer: 5.8.0 + # Using the bundled analyzer (see dependency_overrides) to always be + # up-to-date instead of a version from pub, which may not have the latest + # language features enabled. + analyzer: any test: 1.22.1 - pub_semver: 2.1.3 + +dependency_overrides: # Must include all transitive dependencies from the "any" packages above. + _fe_analyzer_shared: + path: ../../third_party/dart/pkg/_fe_analyzer_shared + analyzer: + path: ../../third_party/dart/pkg/analyzer + async: + path: ../../third_party/dart/third_party/pkg/async + collection: + path: ../../third_party/dart/third_party/pkg/collection + convert: + path: ../../third_party/dart/third_party/pkg/convert + crypto: + path: ../../third_party/dart/third_party/pkg/crypto + file: + path: ../../third_party/pkg/file/packages/file + glob: + path: ../../third_party/dart/third_party/pkg/glob + meta: + path: ../../third_party/dart/pkg/meta + package_config: + path: ../../third_party/dart/third_party/pkg/package_config + path: + path: ../../third_party/dart/third_party/pkg/path + pub_semver: + path: ../../third_party/dart/third_party/pkg/pub_semver + source_span: + path: ../../third_party/dart/third_party/pkg/source_span + string_scanner: + path: ../../third_party/dart/third_party/pkg/string_scanner + term_glyph: + path: ../../third_party/dart/third_party/pkg/term_glyph + typed_data: + path: ../../third_party/dart/third_party/pkg/typed_data + watcher: + path: ../../third_party/dart/third_party/pkg/watcher + yaml: + path: ../../third_party/dart/third_party/pkg/yaml From 8e580414a5f5e8fd0694c90afe59af60e1ddc294 Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Fri, 17 Mar 2023 17:21:06 -0400 Subject: [PATCH 12/15] Roll Skia from 9bfb45d3e065 to 49b902e5fb91 (11 revisions) (#40397) Roll Skia from 9bfb45d3e065 to 49b902e5fb91 (11 revisions) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 36968e1d9f71a..91162b2d187d1 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '9bfb45d3e065ff624c7a8e1043c01feff4caa8c5', + 'skia_revision': '49b902e5fb9188919ac3f9b00efafe2e49391c7a', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index c3bd371509c8f..c44b7db930794 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: 1583b09be00c4b0f5900e3f5551e6ae5 +Signature: da0cf65b2e5f09a564a7ceb9564418a9 ==================================================================================================== LIBRARY: etc1 @@ -8883,6 +8883,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LIBRARY: skia ORIGIN: ../../../third_party/skia/gm/coordclampshader.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/gm/imagefiltersunpremul.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/include/ports/SkFontMgr_data.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkGainmapInfo.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkGainmapShader.h + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/include/private/SkJpegGainmapEncoder.h + ../../../third_party/skia/LICENSE @@ -8904,6 +8905,7 @@ ORIGIN: ../../../third_party/skia/src/shaders/SkGainmapShader.cpp + ../../../thi TYPE: LicenseType.bsd FILE: ../../../third_party/skia/gm/coordclampshader.cpp FILE: ../../../third_party/skia/gm/imagefiltersunpremul.cpp +FILE: ../../../third_party/skia/include/ports/SkFontMgr_data.h FILE: ../../../third_party/skia/include/private/SkGainmapInfo.h FILE: ../../../third_party/skia/include/private/SkGainmapShader.h FILE: ../../../third_party/skia/include/private/SkJpegGainmapEncoder.h From 77c53d25eeeb2016bacb2f7535a7e7ee0acec508 Mon Sep 17 00:00:00 2001 From: Harry Terkelsen Date: Fri, 17 Mar 2023 14:36:11 -0700 Subject: [PATCH 13/15] Default the CanvasKit base URL to local artifacts. (#40293) --- lib/web_ui/README.md | 28 --- lib/web_ui/dev/canvaskit_lock.yaml | 4 - lib/web_ui/dev/canvaskit_roller.dart | 169 ------------------- lib/web_ui/lib/src/engine/configuration.dart | 7 +- 4 files changed, 1 insertion(+), 207 deletions(-) delete mode 100644 lib/web_ui/dev/canvaskit_lock.yaml delete mode 100644 lib/web_ui/dev/canvaskit_roller.dart diff --git a/lib/web_ui/README.md b/lib/web_ui/README.md index f1e11e92f9a01..5c19ffdaade14 100644 --- a/lib/web_ui/README.md +++ b/lib/web_ui/README.md @@ -197,34 +197,6 @@ Resources: 2. LUCI web [recipe][5] 3. More general reading on CIPD packages [link][6] -### Rolling CanvasKit - -CanvasKit is versioned separately from Skia and rolled manually. Flutter -consumes a pre-built CanvasKit provided by the Skia team, currently hosted on -unpkg.com. When a new version of CanvasKit is available (check -https://www.npmjs.com/package/canvaskit-wasm or consult the Skia team -directly), follow these steps to roll to the new version: - -- Make sure you have `depot_tools` installed (if you are regularly hacking on - the engine code, you probably do). -- If not already authenticated with CIPD, run `cipd auth-login` and follow - instructions (this step requires sufficient privileges; file a github - infra ticket queue issue: https://github.com/flutter/flutter/wiki/Infra-Ticket-Queue - to get access) -- Edit `dev/canvaskit_lock.yaml` and update the value of `canvaskit_version` - to the new version. -- Run `dart dev/canvaskit_roller.dart` and make sure it completes successfully. - The script uploads the new version of CanvasKit to the - `flutter/web/canvaskit_bundle` CIPD package, and writes the CIPD package - instance ID to the DEPS file. -- Rerun `gclient sync` and do a clean build to test that the new version is - picked up. -- Send a pull request containing the above file changes. If the new version - contains breaking changes, the PR must also contain corresponding fixes. - -If you have questions, contact the Flutter Web team on Flutter Discord on the -#hackers-web-🌍 channel. - ### Rolling Noto Font Data In order to generate new data for the Noto fallback fonts, you will need diff --git a/lib/web_ui/dev/canvaskit_lock.yaml b/lib/web_ui/dev/canvaskit_lock.yaml deleted file mode 100644 index ab4826af1a057..0000000000000 --- a/lib/web_ui/dev/canvaskit_lock.yaml +++ /dev/null @@ -1,4 +0,0 @@ -# Specifies the version of CanvasKit to use for Flutter Web apps. -# -# See `lib/web_ui/README.md` for how to update this file. -canvaskit_version: "0.38.0" diff --git a/lib/web_ui/dev/canvaskit_roller.dart b/lib/web_ui/dev/canvaskit_roller.dart deleted file mode 100644 index 44b4de43f9d61..0000000000000 --- a/lib/web_ui/dev/canvaskit_roller.dart +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert' show json; -import 'dart:io'; - -import 'package:path/path.dart' as pathlib; -import 'package:yaml/yaml.dart'; - -import 'environment.dart'; -import 'utils.dart'; - -/// Rolls CanvasKit to the version specified in `dev/canvaskit_lock.yaml`. -/// -/// Detailed instructions for how to use this script can be found in -/// `lib/web_ui/README.md`. -Future main(List args) async { - final String canvaskitVersion = _readCanvaskitVersion(); - print('Rolling CanvasKit to version $canvaskitVersion'); - - final Directory canvaskitDirectory = await Directory.systemTemp.createTemp('canvaskit-roll-$canvaskitVersion-'); - print('Will use ${canvaskitDirectory.path} as staging directory.'); - - final String baseUrl = 'https://unpkg.com/canvaskit-wasm@$canvaskitVersion/bin/'; - print('Downloading CanvasKit from $baseUrl'); - final HttpClient client = HttpClient(); - for (final String assetPath in _canvaskitAssets) { - final String assetUrl = '$baseUrl/$assetPath'; - final File assetFile = File(pathlib.joinAll([ - canvaskitDirectory.path, - 'canvaskit', - ...assetPath.split('/'), // so it's compatible with Windows - ])); - await assetFile.parent.create(recursive: true); - final HttpClientRequest request = await client.getUrl(Uri.parse(assetUrl)); - final HttpClientResponse response = await request.close(); - final IOSink fileSink = assetFile.openWrite(); - await response.pipe(fileSink); - } - client.close(); - - final File cipdConfigFile = File(pathlib.join( - canvaskitDirectory.path, - 'cipd.yaml', - )); - await cipdConfigFile.writeAsString(''' -package: flutter/web/canvaskit_bundle -description: A build of CanvasKit bundled with Flutter Web apps -preserve_writable: true -data: - - dir: canvaskit -'''); - - print('Uploading to CIPD'); - await runProcess('cipd', [ - 'create', - '--tag=version:$canvaskitVersion', - '--pkg-def=cipd.yaml', - '--json-output=result.json', - ], workingDirectory: canvaskitDirectory.path); - - final Map cipdResult = json.decode(File(pathlib.join( - canvaskitDirectory.path, - 'result.json', - )).readAsStringSync()) as Map; - final String cipdInstanceId = (cipdResult['result'] as Map)['instance_id'] as String; - - print('CIPD instance information:'); - final String cipdInfo = await evalProcess('cipd', [ - 'describe', - 'flutter/web/canvaskit_bundle', - '--version=$cipdInstanceId', - ], workingDirectory: canvaskitDirectory.path); - print(cipdInfo.trim().split('\n').map((String line) => ' • $line').join('\n')); - - print('Updating DEPS file'); - await _updateDepsFile(cipdInstanceId); - await _updateCanvaskitInitializationCode(canvaskitVersion); - - print('\nATTENTION: the roll process is not complete yet.'); - print('Last step: for the roll to take effect submit an engine pull request from local git changes.'); -} - -const List _canvaskitAssets = [ - 'canvaskit.js', - 'canvaskit.wasm', - 'profiling/canvaskit.js', - 'profiling/canvaskit.wasm', -]; - -String _readCanvaskitVersion() { - final YamlMap canvaskitLock = loadYaml(File(pathlib.join( - environment.webUiDevDir.path, - 'canvaskit_lock.yaml', - )).readAsStringSync()) as YamlMap; - return canvaskitLock['canvaskit_version'] as String; -} - -Future _updateDepsFile(String cipdInstanceId) async { - final File depsFile = File(pathlib.join( - environment.flutterDirectory.path, - 'DEPS', - )); - - final String originalDepsCode = await depsFile.readAsString(); - final List rewrittenDepsCode = []; - const String kCanvasKitDependencyKeyInDeps = "'canvaskit_cipd_instance': '"; - bool canvaskitDependencyFound = false; - for (final String line in originalDepsCode.split('\n')) { - if (line.trim().startsWith(kCanvasKitDependencyKeyInDeps)) { - canvaskitDependencyFound = true; - rewrittenDepsCode.add( - " 'canvaskit_cipd_instance': '$cipdInstanceId',", - ); - } else { - rewrittenDepsCode.add(line); - } - } - - if (!canvaskitDependencyFound) { - stderr.writeln( - 'Failed to update the DEPS file.\n' - 'Could not to locate CanvasKit dependency in the DEPS file. Make sure the ' - 'DEPS file contains a line like this:\n' - '\n' - " 'canvaskit_cipd_instance': 'SOME_VALUE'," - ); - exit(1); - } - - await depsFile.writeAsString(rewrittenDepsCode.join('\n')); -} - -Future _updateCanvaskitInitializationCode(String canvaskitVersion) async { - const String kCanvasKitVersionKey = 'const String _canvaskitVersion'; - const String kPathToConfigurationCode = 'lib/src/engine/configuration.dart'; - final File initializationFile = File(pathlib.join( - environment.webUiRootDir.path, - kPathToConfigurationCode, - )); - final String originalInitializationCode = await initializationFile.readAsString(); - - final List rewrittenCode = []; - bool canvaskitVersionFound = false; - for (final String line in originalInitializationCode.split('\n')) { - if (line.trim().startsWith(kCanvasKitVersionKey)) { - canvaskitVersionFound = true; - rewrittenCode.add( - "const String _canvaskitVersion = '$canvaskitVersion';", - ); - } else { - rewrittenCode.add(line); - } - } - - if (!canvaskitVersionFound) { - stderr.writeln( - 'Failed to update CanvasKit version in $kPathToConfigurationCode.\n' - 'Could not to locate the constant that defines the version. Make sure the ' - '$kPathToConfigurationCode file contains a line like this:\n' - '\n' - "const String _canvaskitVersion = 'VERSION';" - ); - exit(1); - } - - await initializationFile.writeAsString(rewrittenCode.join('\n')); -} diff --git a/lib/web_ui/lib/src/engine/configuration.dart b/lib/web_ui/lib/src/engine/configuration.dart index e153286f711f8..720c3be61ad98 100644 --- a/lib/web_ui/lib/src/engine/configuration.dart +++ b/lib/web_ui/lib/src/engine/configuration.dart @@ -49,11 +49,6 @@ import 'package:meta/meta.dart'; import 'canvaskit/renderer.dart'; import 'dom.dart'; -/// The version of CanvasKit used by the web engine by default. -// DO NOT EDIT THE NEXT LINE OF CODE MANUALLY -// See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. -const String _canvaskitVersion = '0.38.0'; - /// The Web Engine configuration for the current application. FlutterConfiguration get configuration => _configuration ??= FlutterConfiguration.legacy(_jsConfiguration); @@ -182,7 +177,7 @@ class FlutterConfiguration { String get canvasKitBaseUrl => _configuration?.canvasKitBaseUrl ?? _defaultCanvasKitBaseUrl; static const String _defaultCanvasKitBaseUrl = String.fromEnvironment( 'FLUTTER_WEB_CANVASKIT_URL', - defaultValue: 'https://unpkg.com/canvaskit-wasm@$_canvaskitVersion/bin/', + defaultValue: 'canvaskit/', ); /// The variant of CanvasKit to download. From 625ea5395042ad64df28ef188376100e3c243ade Mon Sep 17 00:00:00 2001 From: skia-flutter-autoroll Date: Fri, 17 Mar 2023 19:20:23 -0400 Subject: [PATCH 14/15] Roll Skia from 49b902e5fb91 to aa983f5486f0 (7 revisions) (#40404) Roll Skia from 49b902e5fb91 to aa983f5486f0 (7 revisions) --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 91162b2d187d1..da5210a6f9dbf 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '49b902e5fb9188919ac3f9b00efafe2e49391c7a', + 'skia_revision': 'aa983f5486f04343a44780eb4080554e9bf35510', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index c44b7db930794..8afb69f652401 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: da0cf65b2e5f09a564a7ceb9564418a9 +Signature: a42391bf2409b2ce4be4fdf0c9fdc587 ==================================================================================================== LIBRARY: etc1 @@ -8981,6 +8981,7 @@ ORIGIN: ../../../third_party/skia/src/core/SkMipmapBuilder.cpp + ../../../third_ ORIGIN: ../../../third_party/skia/src/core/SkPixmapDraw.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkRSXform.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkReadPixelsRec.cpp + ../../../third_party/skia/LICENSE +ORIGIN: ../../../third_party/skia/src/core/SkScan_SAAPath.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/core/SkWritePixelsRec.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/encode/SkEncoder.cpp + ../../../third_party/skia/LICENSE ORIGIN: ../../../third_party/skia/src/gpu/dawn/DawnUtilsPriv.h + ../../../third_party/skia/LICENSE @@ -9031,6 +9032,7 @@ FILE: ../../../third_party/skia/src/core/SkMipmapBuilder.cpp FILE: ../../../third_party/skia/src/core/SkPixmapDraw.cpp FILE: ../../../third_party/skia/src/core/SkRSXform.cpp FILE: ../../../third_party/skia/src/core/SkReadPixelsRec.cpp +FILE: ../../../third_party/skia/src/core/SkScan_SAAPath.cpp FILE: ../../../third_party/skia/src/core/SkWritePixelsRec.cpp FILE: ../../../third_party/skia/src/encode/SkEncoder.cpp FILE: ../../../third_party/skia/src/gpu/dawn/DawnUtilsPriv.h From 867679facd716d9350f7637ff76e434ae9e912ff Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Fri, 17 Mar 2023 18:09:06 -0700 Subject: [PATCH 15/15] [Impeller] Add playground flag to render for a specific amount of time. (#40377) [Impeller] Add playground flag to render for a specific amount of time. --- impeller/playground/BUILD.gn | 2 ++ impeller/playground/playground.cc | 8 ++++++++ impeller/playground/playground.h | 5 ++++- impeller/playground/playground_test.cc | 17 ++++++++++++++++- impeller/playground/playground_test.h | 7 +++++++ impeller/playground/switches.cc | 18 ++++++++++++++++++ impeller/playground/switches.h | 24 ++++++++++++++++++++++++ testing/BUILD.gn | 2 ++ testing/run_all_unittests.cc | 10 +++++++--- testing/test_args.cc | 21 +++++++++++++++++++++ testing/test_args.h | 17 +++++++++++++++++ 11 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 impeller/playground/switches.cc create mode 100644 impeller/playground/switches.h create mode 100644 testing/test_args.cc create mode 100644 testing/test_args.h diff --git a/impeller/playground/BUILD.gn b/impeller/playground/BUILD.gn index 623b0d2557b9e..e574e8044594a 100644 --- a/impeller/playground/BUILD.gn +++ b/impeller/playground/BUILD.gn @@ -11,6 +11,8 @@ impeller_component("playground") { "playground.h", "playground_impl.cc", "playground_impl.h", + "switches.cc", + "switches.h", "widgets.cc", "widgets.h", ] diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 85042638b8044..5080e8842e190 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -300,6 +300,10 @@ bool Playground::OpenPlaygroundHere( VALIDATION_LOG << "Could not render into the surface."; return false; } + + if (!ShouldKeepRendering()) { + break; + } } ::glfwHideWindow(window); @@ -450,4 +454,8 @@ void Playground::SetWindowSize(ISize size) { window_size_ = size; } +bool Playground::ShouldKeepRendering() const { + return true; +} + } // namespace impeller diff --git a/impeller/playground/playground.h b/impeller/playground/playground.h index ac44f19450a6d..f44e36c20b100 100644 --- a/impeller/playground/playground.h +++ b/impeller/playground/playground.h @@ -4,12 +4,12 @@ #pragma once +#include #include #include "flutter/fml/closure.h" #include "flutter/fml/macros.h" #include "flutter/fml/time/time_delta.h" - #include "impeller/geometry/point.h" #include "impeller/image/compressed_image.h" #include "impeller/image/decompressed_image.h" @@ -91,6 +91,9 @@ class Playground { virtual std::string GetWindowTitle() const = 0; + protected: + virtual bool ShouldKeepRendering() const; + private: #if IMPELLER_ENABLE_PLAYGROUND static const bool is_enabled_ = true; diff --git a/impeller/playground/playground_test.cc b/impeller/playground/playground_test.cc index 9db2c3a2eeb21..16f86d282121f 100644 --- a/impeller/playground/playground_test.cc +++ b/impeller/playground/playground_test.cc @@ -4,11 +4,13 @@ #include "flutter/fml/time/time_point.h" +#include "impeller/base/timing.h" #include "impeller/playground/playground_test.h" namespace impeller { -PlaygroundTest::PlaygroundTest() = default; +PlaygroundTest::PlaygroundTest() + : switches_(flutter::testing::GetArgsForProcess()) {} PlaygroundTest::~PlaygroundTest() = default; @@ -61,4 +63,17 @@ std::string PlaygroundTest::GetWindowTitle() const { return FormatWindowTitle(flutter::testing::GetCurrentTestName()); } +// |Playground| +bool PlaygroundTest::ShouldKeepRendering() const { + if (!switches_.timeout.has_value()) { + return true; + } + + if (SecondsF{GetSecondsElapsed()} > switches_.timeout.value()) { + return false; + } + + return true; +} + } // namespace impeller diff --git a/impeller/playground/playground_test.h b/impeller/playground/playground_test.h index 2d01cae7632a0..720623ecda33e 100644 --- a/impeller/playground/playground_test.h +++ b/impeller/playground/playground_test.h @@ -7,9 +7,11 @@ #include #include "flutter/fml/macros.h" +#include "flutter/testing/test_args.h" #include "flutter/testing/testing.h" #include "impeller/geometry/scalar.h" #include "impeller/playground/playground.h" +#include "impeller/playground/switches.h" namespace impeller { @@ -35,6 +37,11 @@ class PlaygroundTest : public Playground, std::string GetWindowTitle() const override; private: + const PlaygroundSwitches switches_; + + // |Playground| + bool ShouldKeepRendering() const; + FML_DISALLOW_COPY_AND_ASSIGN(PlaygroundTest); }; diff --git a/impeller/playground/switches.cc b/impeller/playground/switches.cc new file mode 100644 index 0000000000000..3991e5f9831d5 --- /dev/null +++ b/impeller/playground/switches.cc @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/playground/switches.h" + +#include + +namespace impeller { + +PlaygroundSwitches::PlaygroundSwitches(const fml::CommandLine& args) { + std::string timeout_str; + if (args.GetOptionValue("playground_timeout_ms", &timeout_str)) { + timeout = std::chrono::milliseconds(atoi(timeout_str.c_str())); + } +} + +} // namespace impeller diff --git a/impeller/playground/switches.h b/impeller/playground/switches.h new file mode 100644 index 0000000000000..905123b3cc986 --- /dev/null +++ b/impeller/playground/switches.h @@ -0,0 +1,24 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include +#include + +#include "flutter/fml/command_line.h" +#include "flutter/fml/macros.h" + +namespace impeller { + +struct PlaygroundSwitches { + // If specified, the playgrounds will render for at least the duration + // specified in the timeout. If the timeout is zero, exactly one frame will be + // rendered in the playground. + std::optional timeout; + + explicit PlaygroundSwitches(const fml::CommandLine& args); +}; + +} // namespace impeller diff --git a/testing/BUILD.gn b/testing/BUILD.gn index 6ba34ebcc3d97..e20b644948bdd 100644 --- a/testing/BUILD.gn +++ b/testing/BUILD.gn @@ -45,6 +45,8 @@ source_set("testing") { "debugger_detection.cc", "debugger_detection.h", "run_all_unittests.cc", + "test_args.cc", + "test_args.h", "test_timeout_listener.cc", "test_timeout_listener.h", ] diff --git a/testing/run_all_unittests.cc b/testing/run_all_unittests.cc index ae5105fc21e72..8d08a3a59ebdb 100644 --- a/testing/run_all_unittests.cc +++ b/testing/run_all_unittests.cc @@ -10,6 +10,7 @@ #include "flutter/fml/build_config.h" #include "flutter/fml/command_line.h" #include "flutter/testing/debugger_detection.h" +#include "flutter/testing/test_args.h" #include "flutter/testing/test_timeout_listener.h" #include "gtest/gtest.h" @@ -17,8 +18,8 @@ #include #endif // FML_OS_IOS -std::optional GetTestTimeoutFromArgs(int argc, char** argv) { - const auto command_line = fml::CommandLineFromPlatformOrArgcArgv(argc, argv); +std::optional GetTestTimeout() { + const auto& command_line = flutter::testing::GetArgsForProcess(); std::string timeout_seconds; if (!command_line.GetOptionValue("timeout", &timeout_seconds)) { @@ -37,6 +38,9 @@ std::optional GetTestTimeoutFromArgs(int argc, char** argv) { int main(int argc, char** argv) { fml::InstallCrashHandler(); + + flutter::testing::SetArgsForProcess(argc, argv); + #ifdef FML_OS_IOS asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE); @@ -47,7 +51,7 @@ int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); // Check if the user has specified a timeout. - const auto timeout = GetTestTimeoutFromArgs(argc, argv); + const auto timeout = GetTestTimeout(); if (!timeout.has_value()) { FML_LOG(INFO) << "Timeouts disabled via a command line flag."; return RUN_ALL_TESTS(); diff --git a/testing/test_args.cc b/testing/test_args.cc new file mode 100644 index 0000000000000..ace858cd64e7f --- /dev/null +++ b/testing/test_args.cc @@ -0,0 +1,21 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/testing/test_args.h" + +namespace flutter { +namespace testing { + +static fml::CommandLine gProcessArgs; + +const fml::CommandLine& GetArgsForProcess() { + return gProcessArgs; +} + +void SetArgsForProcess(int argc, char** argv) { + gProcessArgs = fml::CommandLineFromArgcArgv(argc, argv); +} + +} // namespace testing +} // namespace flutter diff --git a/testing/test_args.h b/testing/test_args.h new file mode 100644 index 0000000000000..0ee5d2a79837a --- /dev/null +++ b/testing/test_args.h @@ -0,0 +1,17 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include "flutter/fml/command_line.h" + +namespace flutter { +namespace testing { + +const fml::CommandLine& GetArgsForProcess(); + +void SetArgsForProcess(int argc, char** argv); + +} // namespace testing +} // namespace flutter