diff --git a/.ci.yaml b/.ci.yaml index b1ec149fbc8cc..94e761779332a 100755 --- a/.ci.yaml +++ b/.ci.yaml @@ -63,10 +63,10 @@ platform_properties: ] dependencies: >- [] - os: Mac-10.15 + os: Mac-12 device_type: none mac_model: Macmini8,1 - xcode: 12c33 + xcode: 13a233 mac_android: properties: caches: >- @@ -85,7 +85,7 @@ platform_properties: {"dependency": "chrome_and_driver", "version": "version:84"}, {"dependency": "open_jdk"} ] - os: Mac-12.0 + os: Mac-12 device_os: N mac_ios: properties: @@ -106,7 +106,7 @@ platform_properties: {"dependency": "gems"}, {"dependency": "ios_signing"} ] - os: Mac-12.0 + os: Mac-12 device_os: iOS-15.1 xcode: 13a233 windows: @@ -1613,6 +1613,7 @@ targets: scheduler: luci - name: Linux_android complex_layout__start_up + bringup: true # Flaky https://github.com/flutter/flutter/issues/98999 recipe: devicelab/devicelab_drone presubmit: false timeout: 60 @@ -2139,7 +2140,6 @@ targets: - name: Linux_android android_picture_cache_complexity_scoring_perf__timeline_summary recipe: devicelab/devicelab_drone - bringup: true presubmit: false timeout: 60 properties: @@ -2243,7 +2243,6 @@ targets: scheduler: luci - name: Linux_android tiles_scroll_perf__timeline_summary - bringup: true # Flaky https://github.com/flutter/flutter/issues/98423 recipe: devicelab/devicelab_drone presubmit: false timeout: 60 @@ -2273,6 +2272,7 @@ targets: scheduler: luci - name: Linux android views + bringup: true # Flaky https://github.com/flutter/flutter/issues/99001 recipe: flutter/android_views properties: dependencies: >- @@ -2378,6 +2378,17 @@ targets: benchmark: "true" scheduler: luci + - name: Linux_android android_choreographer_do_frame_test + bringup: true + recipe: devicelab/devicelab_drone + presubmit: false + timeout: 60 + properties: + tags: > + ["devicelab","android","linux"] + task_name: android_choreographer_do_frame_test + scheduler: luci + - name: Mac build_aar_module_test recipe: devicelab/devicelab_drone timeout: 60 @@ -2774,7 +2785,6 @@ targets: - name: Mac module_test_ios recipe: devicelab/devicelab_drone - bringup: true # Flaky https://github.com/flutter/flutter/issues/89175 timeout: 60 properties: caches: >- @@ -2841,8 +2851,6 @@ targets: tags: > ["devicelab","hostonly"] task_name: plugin_lint_mac - os: Mac-12 # Override OS and Xcode for https://github.com/flutter/flutter/issues/97303 - xcode: 13a233 scheduler: luci runIf: - dev/** @@ -3076,6 +3084,8 @@ targets: subshard: web tags: > ["framework","hostonly","shard"] + os: Mac-10.15 # Override OS and Xcode for https://github.com/flutter/flutter/issues/98278 + xcode: 12c33 scheduler: luci runIf: - dev/** @@ -3260,7 +3270,6 @@ targets: scheduler: luci - name: Mac_ios cubic_bezier_perf_ios_sksl_warmup__timeline_summary - bringup: true # Flaky https://github.com/flutter/flutter/issues/95867 recipe: devicelab/devicelab_drone presubmit: false timeout: 60 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 9282635cd501c..ba89d5841822e 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -49,6 +49,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@d39d5d5c9707b926d517b1b292905ef4c03aa777 + uses: github/codeql-action/upload-sarif@75f07e7ab2ee63cba88752d8c696324e4df67466 with: sarif_file: results.sarif diff --git a/TESTOWNERS b/TESTOWNERS index 5944196682f53..28bf447a581d1 100644 --- a/TESTOWNERS +++ b/TESTOWNERS @@ -71,6 +71,7 @@ /dev/devicelab/bin/tasks/opacity_peephole_fade_transition_text_perf__e2e_summary.dart @flar @flutter/engine /dev/devicelab/bin/tasks/opacity_peephole_col_of_alpha_savelayer_rows_perf__e2e_summary.dart @flar @flutter/engine /dev/devicelab/bin/tasks/opacity_peephole_grid_of_alpha_savelayers_perf__e2e_summary.dart @flar @flutter/engine +/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart @blasten @flutter/engine ## Windows Android DeviceLab tests /dev/devicelab/bin/tasks/basic_material_app_win__compile.dart @zanderso @flutter/tool diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 9a37c96dd2b67..a7daec419fe27 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -1012ac4b5af7909a89a1fd03b0379c2304b9e4ab +1a919ed9086883c140dc8f9f230f149ee41dffcb diff --git a/bin/internal/flutter_plugins.version b/bin/internal/flutter_plugins.version index 81b7d715accfc..b4c314b33681a 100644 --- a/bin/internal/flutter_plugins.version +++ b/bin/internal/flutter_plugins.version @@ -1 +1 @@ -6d88e3a2a1848ed93670890bc79532426b1344a2 +f96d633e7a54470208e43c9363b208293a41b623 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index 0b7e9b414704d..af9fcbfb414c0 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -IXGdq-EQPYiKZJBGxB5S8kuZ8o4zEIVGOCI96SmEv4wC +-WG2dxBr62rFjjho47I0QzT0jV-CXgLloebwdsJI_6AC diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index 98af6525bf43a..f8d59f5a39be9 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -9KwyMwVIpyzWHsZ8J6ftyrWN_tOEbJDj2hBvG985b54C +dROOoKmsjzFPqazFnn9v59fmjoQWmnPGLv6xJn9X04UC diff --git a/dev/automated_tests/flutter_test/flutter_gold_expectation.txt b/dev/automated_tests/flutter_test/flutter_gold_expectation.txt index b3e2cce386ed3..7de9b5a2a55e8 100644 --- a/dev/automated_tests/flutter_test/flutter_gold_expectation.txt +++ b/dev/automated_tests/flutter_test/flutter_gold_expectation.txt @@ -1,7 +1,7 @@ [0-9]+:[0-9]+ [+]0: Local passes non-existent baseline for new test, null expectation * - *No expectations provided by Skia Gold for test: library.flutter.new_golden_test.1. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org. + *No expectations provided by Skia Gold for test: library.flutter.new_golden_test.1.png. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org. *Validate image output found at flutter/test/library/ [0-9]+:[0-9]+ [+]1: Local passes non-existent baseline for new test, empty expectation * - *No expectations provided by Skia Gold for test: library.flutter.new_golden_test.2. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org. + *No expectations provided by Skia Gold for test: library.flutter.new_golden_test.2.png. This may be a new test. If this is an unexpected result, check https://flutter-gold.skia.org. *Validate image output found at flutter/test/library/ [0-9]+:[0-9]+ [+]2: All tests passed! * diff --git a/dev/automated_tests/flutter_test/flutter_gold_test.dart b/dev/automated_tests/flutter_test/flutter_gold_test.dart index 36831b6623ca9..fbd701b4737c9 100644 --- a/dev/automated_tests/flutter_test/flutter_gold_test.dart +++ b/dev/automated_tests/flutter_test/flutter_gold_test.dart @@ -38,7 +38,7 @@ void main() { expect( await comparator.compare( Uint8List.fromList(_kFailPngBytes), - Uri.parse('flutter.new_golden_test.1'), + Uri.parse('flutter.new_golden_test.1.png'), ), isTrue, ); @@ -48,7 +48,7 @@ void main() { expect( await comparator.compare( Uint8List.fromList(_kFailPngBytes), - Uri.parse('flutter.new_golden_test.2'), + Uri.parse('flutter.new_golden_test.2.png'), ), isTrue, ); diff --git a/dev/automated_tests/pubspec.yaml b/dev/automated_tests/pubspec.yaml index 00e90bec2a3c9..286f5931af958 100644 --- a/dev/automated_tests/pubspec.yaml +++ b/dev/automated_tests/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -73,4 +73,4 @@ flutter: assets: - icon/ -# PUBSPEC CHECKSUM: af58 +# PUBSPEC CHECKSUM: 5b59 diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml index e05d6be7ed0c2..41ac081661b52 100644 --- a/dev/benchmarks/complex_layout/pubspec.yaml +++ b/dev/benchmarks/complex_layout/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -85,4 +85,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: f090 +# PUBSPEC CHECKSUM: bc91 diff --git a/dev/benchmarks/macrobenchmarks/pubspec.yaml b/dev/benchmarks/macrobenchmarks/pubspec.yaml index f60ce2765e3aa..f111227c838a8 100644 --- a/dev/benchmarks/macrobenchmarks/pubspec.yaml +++ b/dev/benchmarks/macrobenchmarks/pubspec.yaml @@ -52,7 +52,7 @@ dependencies: url_launcher_web: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" url_launcher_windows: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -221,4 +221,4 @@ flutter: fonts: - asset: packages/flutter_gallery_assets/fonts/GalleryIcons.ttf -# PUBSPEC CHECKSUM: 5574 +# PUBSPEC CHECKSUM: 2175 diff --git a/dev/benchmarks/microbenchmarks/pubspec.yaml b/dev/benchmarks/microbenchmarks/pubspec.yaml index 682fb01bc19c1..025fabdc0ef3c 100644 --- a/dev/benchmarks/microbenchmarks/pubspec.yaml +++ b/dev/benchmarks/microbenchmarks/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -71,4 +71,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: f40a +# PUBSPEC CHECKSUM: a00b diff --git a/dev/benchmarks/multiple_flutters/module/pubspec.yaml b/dev/benchmarks/multiple_flutters/module/pubspec.yaml index 9f17251e35af6..0f68f6e94e455 100644 --- a/dev/benchmarks/multiple_flutters/module/pubspec.yaml +++ b/dev/benchmarks/multiple_flutters/module/pubspec.yaml @@ -26,8 +26,8 @@ dependencies: meta: 1.7.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider: 2.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_android: 2.0.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_ios: 2.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_android: 2.0.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_ios: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_linux: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_macos: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_platform_interface: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -40,7 +40,7 @@ dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - win32: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + win32: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" xdg_directories: 0.2.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" flutter: @@ -51,4 +51,4 @@ flutter: androidPackage: com.example.multiple_flutters_module iosBundleIdentifier: com.example.multipleFluttersModule -# PUBSPEC CHECKSUM: a7c4 +# PUBSPEC CHECKSUM: dbc7 diff --git a/dev/benchmarks/platform_channels_benchmarks/pubspec.yaml b/dev/benchmarks/platform_channels_benchmarks/pubspec.yaml index 8a0ca7597d20e..604c711e9f824 100644 --- a/dev/benchmarks/platform_channels_benchmarks/pubspec.yaml +++ b/dev/benchmarks/platform_channels_benchmarks/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -74,4 +74,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: b4f7 +# PUBSPEC CHECKSUM: 60f8 diff --git a/dev/benchmarks/platform_views_layout/pubspec.yaml b/dev/benchmarks/platform_views_layout/pubspec.yaml index 2e92b6cc37f34..568bf667b5db8 100644 --- a/dev/benchmarks/platform_views_layout/pubspec.yaml +++ b/dev/benchmarks/platform_views_layout/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -83,4 +83,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: f090 +# PUBSPEC CHECKSUM: bc91 diff --git a/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml b/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml index 5e6634687962f..339c34cafb64a 100644 --- a/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml +++ b/dev/benchmarks/platform_views_layout_hybrid_composition/pubspec.yaml @@ -29,7 +29,7 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -83,4 +83,4 @@ flutter: - packages/flutter_gallery_assets/people/square/ali.png - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png -# PUBSPEC CHECKSUM: f090 +# PUBSPEC CHECKSUM: bc91 diff --git a/dev/benchmarks/test_apps/stocks/pubspec.yaml b/dev/benchmarks/test_apps/stocks/pubspec.yaml index 030627f212efa..b0b62f1693f51 100644 --- a/dev/benchmarks/test_apps/stocks/pubspec.yaml +++ b/dev/benchmarks/test_apps/stocks/pubspec.yaml @@ -68,7 +68,7 @@ dev_dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -78,4 +78,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: a4ae +# PUBSPEC CHECKSUM: 70af diff --git a/dev/bots/allowlist.dart b/dev/bots/allowlist.dart index e174a5bda334b..2622c7f037134 100644 --- a/dev/bots/allowlist.dart +++ b/dev/bots/allowlist.dart @@ -17,19 +17,13 @@ /// unless the additions are cleared as described above. const Set kCorePackageAllowList = { // Please keep this list in alphabetical order. - '_fe_analyzer_shared', - 'analyzer', 'archive', - 'args', 'async', 'boolean_selector', 'characters', 'charcode', - 'cli_util', 'clock', 'collection', - 'convert', - 'coverage', 'crypto', 'fake_async', 'file', @@ -37,45 +31,25 @@ const Set kCorePackageAllowList = { 'flutter_driver', 'flutter_localizations', 'flutter_test', - 'frontend_server_client', - 'glob', - 'http_multi_server', - 'http_parser', + 'fuchsia_remote_debug_protocol', 'integration_test', 'intl', - 'io', - 'js', - 'logging', 'matcher', 'material_color_utilities', 'meta', - 'mime', - 'node_preamble', - 'package_config', 'path', - 'pool', - 'pub_semver', - 'shelf', - 'shelf_packages_handler', - 'shelf_static', - 'shelf_web_socket', - 'source_map_stack_trace', - 'source_maps', + 'platform', + 'process', + 'sky_engine', 'source_span', 'stack_trace', 'stream_channel', 'string_scanner', 'sync_http', 'term_glyph', - 'test', 'test_api', - 'test_core', 'typed_data', 'vector_math', 'vm_service', - 'watcher', - 'web_socket_channel', 'webdriver', - 'webkit_inspection_protocol', - 'yaml', }; diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index 60366fd2d6b85..833437820767e 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -1565,24 +1565,50 @@ Future _evalCommand(String executable, List arguments, { } Future _checkConsumerDependencies() async { - final ProcessResult result = await Process.run(flutter, [ - 'update-packages', - '--transitive-closure', - '--consumer-only', - ]); - if (result.exitCode != 0) { - print(result.stdout as Object); - print(result.stderr as Object); - exit(result.exitCode); - } + const List kCorePackages = [ + 'flutter', + 'flutter_test', + 'flutter_driver', + 'flutter_localizations', + 'integration_test', + 'fuchsia_remote_debug_protocol', + ]; final Set dependencies = {}; - for (final String line in result.stdout.toString().split('\n')) { - if (!line.contains('->')) { - continue; + + // Parse the output of pub deps --json to determine all of the + // current packages used by the core set of flutter packages. + for (final String package in kCorePackages) { + final ProcessResult result = await Process.run(flutter, [ + 'pub', + 'deps', + '--json', + '--directory=${path.join(flutterRoot, 'packages', package)}' + ]); + if (result.exitCode != 0) { + print(result.stdout as Object); + print(result.stderr as Object); + exit(result.exitCode); + } + final Map rawJson = json.decode(result.stdout as String) as Map; + final Map> dependencyTree = >{ + for (final Map package in (rawJson['packages']! as List).cast>()) + package['name']! as String : package, + }; + final List> workset = >[]; + workset.add(dependencyTree[package]!); + + while (workset.isNotEmpty) { + final Map currentPackage = workset.removeLast(); + if (currentPackage['kind'] == 'dev') { + continue; + } + dependencies.add(currentPackage['name']! as String); + + final List currentDependencies = (currentPackage['dependencies']! as List).cast(); + for (final String dependency in currentDependencies) { + workset.add(dependencyTree[dependency]!); + } } - final List parts = line.split('->'); - final String name = parts[0].trim(); - dependencies.add(name); } final Set removed = kCorePackageAllowList.difference(dependencies); diff --git a/dev/bots/docs.sh b/dev/bots/docs.sh index 2d154430ec2b7..4463b9f0cde1f 100755 --- a/dev/bots/docs.sh +++ b/dev/bots/docs.sh @@ -28,11 +28,6 @@ function generate_docs() { # >>> If you update this version, also update it in dev/bots/analyze_sample_code.dart <<< "$DART" pub global activate snippets 0.2.5 - # Run the snippets tool once to force building of the package executable, - # since "dart pub global run" has issues with startup concurrency. - # TODO(gspencergoog): Remove once pub issue is fixed, https://github.com/dart-lang/pub/issues/3165 - "$DART" pub global run snippets --help - # This script generates a unified doc set, and creates # a custom index.html, placing everything into dev/docs/doc. (cd "$FLUTTER_ROOT/dev/tools" && "$FLUTTER" pub get) diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml index 493ad58b51a3c..2debe343009d5 100644 --- a/dev/bots/pubspec.yaml +++ b/dev/bots/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -71,4 +71,4 @@ dependencies: dev_dependencies: test_api: 0.4.9 -# PUBSPEC CHECKSUM: 8aae +# PUBSPEC CHECKSUM: 36af diff --git a/dev/bots/test/analyze_sample_code_test.dart b/dev/bots/test/analyze_sample_code_test.dart index 4f7b32a33ac38..ac435ab14b89d 100644 --- a/dev/bots/test/analyze_sample_code_test.dart +++ b/dev/bots/test/analyze_sample_code_test.dart @@ -22,9 +22,9 @@ void main() { final List stdoutLines = process.stdout.toString().split('\n'); final List stderrLines = process.stderr.toString().split('\n'); expect(process.exitCode, isNot(equals(0))); - expect(stderrLines, containsAll([ + expect(stderrLines, containsAll([ 'In sample starting at dev/bots/test/analyze-sample-code-test-input/known_broken_documentation.dart:125: child: Text(title),', - ">>> error: The final variable 'title' can't be read because it is potentially unassigned at this point (read_potentially_unassigned_final)", + matches(RegExp(r">>> error: The final variable 'title' can't be read because (it is|it's) potentially unassigned at this point \(read_potentially_unassigned_final\)")), 'dev/bots/test/analyze-sample-code-test-input/known_broken_documentation.dart:30:9: new Opacity(', '>>> info: Unnecessary new keyword (unnecessary_new)', 'dev/bots/test/analyze-sample-code-test-input/known_broken_documentation.dart:62:9: new Opacity(', diff --git a/dev/conductor/core/lib/src/start.dart b/dev/conductor/core/lib/src/start.dart index fa4131ac282b5..4187ea0223acf 100644 --- a/dev/conductor/core/lib/src/start.dart +++ b/dev/conductor/core/lib/src/start.dart @@ -377,9 +377,12 @@ class StartContext extends Context { candidateBranch, exact: false, )); - // [force] means we know this would fail but need to publish anyway - if (!force) { + + try { lastVersion.ensureValid(candidateBranch, incrementLetter); + } on ConductorException catch (e) { + // Let the user know, but resume execution + stdio.printError(e.message); } Version nextVersion = calculateNextVersion(lastVersion); diff --git a/dev/conductor/core/pubspec.yaml b/dev/conductor/core/pubspec.yaml index cc64858a1347e..43d76ece0afc0 100644 --- a/dev/conductor/core/pubspec.yaml +++ b/dev/conductor/core/pubspec.yaml @@ -62,9 +62,9 @@ dev_dependencies: stack_trace: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" stream_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: a1b8 +# PUBSPEC CHECKSUM: 4db9 diff --git a/dev/conductor/core/test/start_test.dart b/dev/conductor/core/test/start_test.dart index fcef75378d2a5..ba937a5a62670 100644 --- a/dev/conductor/core/test/start_test.dart +++ b/dev/conductor/core/test/start_test.dart @@ -509,6 +509,211 @@ void main() { expect(branchPointTag != nextVersion, true); }); + test('logs to STDERR but does not fail on an unexpected candidate branch', () async { + stdio.stdin.add('y'); // accept prompt from ensureBranchPointTagged() + const String revision2 = 'def789'; + const String revision3 = '123abc'; + const String previousDartRevision = '171876a4e6cf56ee6da1f97d203926bd7afda7ef'; + const String nextDartRevision = 'f6c91128be6b77aef8351e1e3a9d07c85bc2e46e'; + // note that this significantly behind the candidate branch name + const String previousVersion = '0.9.0-1.0.pre'; + // This is a git tag applied to the branch point, not an actual release + const String branchPointTag = '1.2.0-3.0.pre'; + // This is what this release will be + const String nextVersion = '1.2.0-3.1.pre'; + const String incrementLevel = 'm'; + + final Directory engine = fileSystem + .directory(checkoutsParentDirectory) + .childDirectory('flutter_conductor_checkouts') + .childDirectory('engine'); + + final File depsFile = engine.childFile('DEPS'); + + final List engineCommands = [ + FakeCommand( + command: [ + 'git', + 'clone', + '--origin', + 'upstream', + '--', + EngineRepository.defaultUpstream, + engine.path, + ], + onRun: () { + // Create the DEPS file which the tool will update + engine.createSync(recursive: true); + depsFile.writeAsStringSync(generateMockDeps(previousDartRevision)); + }), + const FakeCommand( + command: ['git', 'remote', 'add', 'mirror', engineMirror], + ), + const FakeCommand( + command: ['git', 'fetch', 'mirror'], + ), + const FakeCommand( + command: ['git', 'checkout', 'upstream/$candidateBranch'], + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + stdout: revision2, + ), + const FakeCommand( + command: [ + 'git', + 'checkout', + '-b', + 'cherrypicks-$candidateBranch', + ], + ), + const FakeCommand( + command: ['git', 'status', '--porcelain'], + stdout: 'MM path/to/DEPS', + ), + const FakeCommand( + command: ['git', 'add', '--all'], + ), + const FakeCommand( + command: ['git', 'commit', "--message='Update Dart SDK to $nextDartRevision'"], + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + stdout: revision2, + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + stdout: revision2, + ), + ]; + + final List frameworkCommands = [ + FakeCommand( + command: [ + 'git', + 'clone', + '--origin', + 'upstream', + '--', + FrameworkRepository.defaultUpstream, + fileSystem.path.join( + checkoutsParentDirectory, + 'flutter_conductor_checkouts', + 'framework', + ), + ], + ), + const FakeCommand( + command: ['git', 'remote', 'add', 'mirror', frameworkMirror], + ), + const FakeCommand( + command: ['git', 'fetch', 'mirror'], + ), + const FakeCommand( + command: ['git', 'checkout', 'upstream/$candidateBranch'], + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + stdout: revision3, + ), + const FakeCommand( + command: [ + 'git', + 'checkout', + '-b', + 'cherrypicks-$candidateBranch', + ], + ), + const FakeCommand( + command: [ + 'git', + 'describe', + '--match', + '*.*.*', + '--tags', + 'refs/remotes/upstream/$candidateBranch', + ], + stdout: '$previousVersion-42-gabc123', + ), + const FakeCommand( + command: ['git', 'merge-base', candidateBranch, 'master'], + stdout: branchPointRevision, + ), + // check if commit is tagged + const FakeCommand( + command: ['git', 'describe', '--exact-match', '--tags', branchPointRevision], + // non-zero exit means commit is not tagged + exitCode: 128, + ), + const FakeCommand( + command: ['git', 'tag', branchPointTag, branchPointRevision], + ), + const FakeCommand( + command: ['git', 'push', FrameworkRepository.defaultUpstream, branchPointTag], + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + stdout: revision3, + ), + ]; + + final CommandRunner runner = createRunner( + commands: [ + ...engineCommands, + ...frameworkCommands, + ], + ); + + final String stateFilePath = fileSystem.path.join( + platform.environment['HOME']!, + kStateFileName, + ); + + await runner.run([ + 'start', + '--$kFrameworkMirrorOption', + frameworkMirror, + '--$kEngineMirrorOption', + engineMirror, + '--$kCandidateOption', + candidateBranch, + '--$kReleaseOption', + releaseChannel, + '--$kStateOption', + stateFilePath, + '--$kDartRevisionOption', + nextDartRevision, + '--$kIncrementOption', + incrementLevel, + ]); + + final File stateFile = fileSystem.file(stateFilePath); + + final pb.ConductorState state = pb.ConductorState(); + state.mergeFromProto3Json( + jsonDecode(stateFile.readAsStringSync()), + ); + + expect(processManager.hasRemainingExpectations, false); + expect(state.isInitialized(), true); + expect(state.releaseChannel, releaseChannel); + expect(state.releaseVersion, nextVersion); + expect(state.engine.candidateBranch, candidateBranch); + expect(state.engine.startingGitHead, revision2); + expect(state.engine.dartRevision, nextDartRevision); + expect(state.engine.upstream.url, 'git@github.com:flutter/engine.git'); + expect(state.framework.candidateBranch, candidateBranch); + expect(state.framework.startingGitHead, revision3); + expect(state.framework.upstream.url, 'git@github.com:flutter/flutter.git'); + expect(state.currentPhase, ReleasePhase.APPLY_ENGINE_CHERRYPICKS); + expect(state.conductorVersion, conductorVersion); + expect(state.incrementLevel, incrementLevel); + expect(stdio.stdout, contains('Applying the tag $branchPointTag at the branch point $branchPointRevision')); + expect(stdio.stdout, contains('The actual release will be version $nextVersion')); + expect(branchPointTag != nextVersion, true); + expect(stdio.error, contains('Parsed version $previousVersion.42 has a different x value than candidate branch $candidateBranch')); + }); + test('can convert from dev style version to stable version', () async { const String revision2 = 'def789'; const String revision3 = '123abc'; diff --git a/dev/customer_testing/pubspec.yaml b/dev/customer_testing/pubspec.yaml index 310879cb97dea..b70d47f3e01c4 100644 --- a/dev/customer_testing/pubspec.yaml +++ b/dev/customer_testing/pubspec.yaml @@ -51,10 +51,10 @@ dev_dependencies: test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: e5dd +# PUBSPEC CHECKSUM: 91de diff --git a/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart b/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart new file mode 100644 index 0000000000000..644af31b3d535 --- /dev/null +++ b/dev/devicelab/bin/tasks/android_choreographer_do_frame_test.dart @@ -0,0 +1,10 @@ +// Copyright 2014 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 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/tasks/android_choreographer_do_frame_test.dart'; + +Future main() async { + await task(androidChoreographerDoFrameTest()); +} diff --git a/dev/devicelab/lib/tasks/android_choreographer_do_frame_test.dart b/dev/devicelab/lib/tasks/android_choreographer_do_frame_test.dart new file mode 100644 index 0000000000000..8226c0a920519 --- /dev/null +++ b/dev/devicelab/lib/tasks/android_choreographer_do_frame_test.dart @@ -0,0 +1,193 @@ +// Copyright 2014 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:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as path; + +import '../framework/framework.dart'; +import '../framework/task_result.dart'; +import '../framework/utils.dart'; + +const List kSentinelStr = [ + '==== sentinel #1 ====', + '==== sentinel #2 ====', + '==== sentinel #3 ====', +]; + +// Regression test for https://github.com/flutter/flutter/issues/98973 +// This test ensures that Choreographer#doFrame finishes during application startup. +// This test fails if the application hangs during this period. +// https://ui.perfetto.dev/#!/?s=da6628c3a92456ae8fa3f345d0186e781da77e90fc8a64d073e9fee11d1e65 +TaskFunction androidChoreographerDoFrameTest({ + String? deviceIdOverride, + Map? environment, +}) { + final Directory tempDir = Directory.systemTemp + .createTempSync('flutter_devicelab_android_surface_recreation.'); + return () async { + try { + section('Create app'); + await inDirectory(tempDir, () async { + await flutter( + 'create', + options: [ + '--platforms', + 'android', + 'app', + ], + environment: environment, + ); + }); + + final File mainDart = File(path.join( + tempDir.absolute.path, + 'app', + 'lib', + 'main.dart', + )); + if (!mainDart.existsSync()) { + return TaskResult.failure('${mainDart.path} does not exist'); + } + + section('Patch lib/main.dart'); + await mainDart.writeAsString(''' +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + + print('${kSentinelStr[0]}'); + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); + + print('${kSentinelStr[1]}'); + // If the Android UI thread is blocked, then this Future won't resolve. + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); + + print('${kSentinelStr[2]}'); + runApp( + Container( + decoration: BoxDecoration( + color: const Color(0xff7c94b6), + ), + ), + ); +} +''', flush: true); + + Future runTestFor(String mode) async { + int nextCompleterIdx = 0; + final Map> sentinelCompleters = >{}; + for (final String sentinel in kSentinelStr) { + sentinelCompleters[sentinel] = Completer(); + } + + section('Flutter run (mode: $mode)'); + await inDirectory(path.join(tempDir.path, 'app'), () async { + final Process run = await startProcess( + path.join(flutterDirectory.path, 'bin', 'flutter'), + flutterCommandArgs('run', ['--$mode', '--verbose']), + ); + + int currSentinelIdx = 0; + final StreamSubscription stdout = run.stdout + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + + if (currSentinelIdx < sentinelCompleters.keys.length && + line.contains(sentinelCompleters.keys.elementAt(currSentinelIdx))) { + sentinelCompleters.values.elementAt(currSentinelIdx).complete(); + currSentinelIdx++; + print('stdout(MATCHED): $line'); + } else { + print('stdout: $line'); + } + + }); + + final StreamSubscription stderr = run.stderr + .transform(utf8.decoder) + .transform(const LineSplitter()) + .listen((String line) { + print('stderr: $line'); + }); + + final Completer exitCompleter = Completer(); + + unawaited(run.exitCode.then((int exitCode) { + exitCompleter.complete(); + })); + + section('Wait for sentinels (mode: $mode)'); + for (final Completer completer in sentinelCompleters.values) { + if (nextCompleterIdx == 0) { + // Don't time out because we don't know how long it would take to get the first log. + await Future.any( + >[ + completer.future, + exitCompleter.future, + ], + ); + } else { + try { + // Time out since this should not take 1s after the first log was received. + await Future.any( + >[ + completer.future.timeout(const Duration(seconds: 1)), + exitCompleter.future, + ], + ); + } on TimeoutException { + break; + } + } + if (exitCompleter.isCompleted) { + // The process exited. + break; + } + nextCompleterIdx++; + } + + section('Quit app (mode: $mode)'); + run.stdin.write('q'); + await exitCompleter.future; + + section('Stop listening to stdout and stderr (mode: $mode)'); + await stdout.cancel(); + await stderr.cancel(); + run.kill(); + }); + + if (nextCompleterIdx == sentinelCompleters.values.length) { + return TaskResult.success(null); + } + final String nextSentinel = sentinelCompleters.keys.elementAt(nextCompleterIdx); + return TaskResult.failure('Expected sentinel `$nextSentinel` in mode $mode'); + } + + final TaskResult debugResult = await runTestFor('debug'); + if (debugResult.failed) { + return debugResult; + } + + final TaskResult profileResult = await runTestFor('profile'); + if (profileResult.failed) { + return profileResult; + } + + final TaskResult releaseResult = await runTestFor('release'); + if (releaseResult.failed) { + return releaseResult; + } + + return TaskResult.success(null); + } finally { + rmTree(tempDir); + } + }; +} diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml index d6e8e3889d408..81390c08464dc 100644 --- a/dev/devicelab/pubspec.yaml +++ b/dev/devicelab/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: shelf: 1.1.4 shelf_static: 1.1.0 stack_trace: 1.10.0 - vm_service: 8.1.0 + vm_service: 8.2.0 webkit_inspection_protocol: 1.0.0 _discoveryapis_commons: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -71,4 +71,4 @@ dev_dependencies: watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 8aae +# PUBSPEC CHECKSUM: 36af diff --git a/dev/integration_tests/android_semantics_testing/pubspec.yaml b/dev/integration_tests/android_semantics_testing/pubspec.yaml index 3e0bee7032a95..def039ad80274 100644 --- a/dev/integration_tests/android_semantics_testing/pubspec.yaml +++ b/dev/integration_tests/android_semantics_testing/pubspec.yaml @@ -60,7 +60,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -70,4 +70,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/dev/integration_tests/android_views/pubspec.yaml b/dev/integration_tests/android_views/pubspec.yaml index b1eab208176ae..bf9ebb32f8a8a 100644 --- a/dev/integration_tests/android_views/pubspec.yaml +++ b/dev/integration_tests/android_views/pubspec.yaml @@ -28,8 +28,8 @@ dependencies: material_color_utilities: 0.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.7.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_android: 2.0.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_ios: 2.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_android: 2.0.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_ios: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_linux: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_macos: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_platform_interface: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -41,9 +41,9 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - win32: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + win32: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" xdg_directories: 0.2.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -94,4 +94,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: e421 +# PUBSPEC CHECKSUM: 2925 diff --git a/dev/integration_tests/channels/pubspec.yaml b/dev/integration_tests/channels/pubspec.yaml index 067b6a91c026b..5de2e736164f1 100644 --- a/dev/integration_tests/channels/pubspec.yaml +++ b/dev/integration_tests/channels/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -67,4 +67,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: a73c +# PUBSPEC CHECKSUM: 733d diff --git a/dev/integration_tests/deferred_components_test/pubspec.yaml b/dev/integration_tests/deferred_components_test/pubspec.yaml index 99de6481dbf58..c478ba1ecfc18 100644 --- a/dev/integration_tests/deferred_components_test/pubspec.yaml +++ b/dev/integration_tests/deferred_components_test/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -82,4 +82,4 @@ flutter: assets: - customassets/flutter_logo.png -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/dev/integration_tests/external_ui/pubspec.yaml b/dev/integration_tests/external_ui/pubspec.yaml index 8640cf2a357a2..6b9dc3275046d 100644 --- a/dev/integration_tests/external_ui/pubspec.yaml +++ b/dev/integration_tests/external_ui/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -67,4 +67,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: a73c +# PUBSPEC CHECKSUM: 733d diff --git a/dev/integration_tests/flavors/pubspec.yaml b/dev/integration_tests/flavors/pubspec.yaml index 9b27a881209b6..b2411c0c8516e 100644 --- a/dev/integration_tests/flavors/pubspec.yaml +++ b/dev/integration_tests/flavors/pubspec.yaml @@ -59,7 +59,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -76,4 +76,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/dev/integration_tests/flutter_gallery/pubspec.yaml b/dev/integration_tests/flutter_gallery/pubspec.yaml index 20284d926fdc3..0b243d142061b 100644 --- a/dev/integration_tests/flutter_gallery/pubspec.yaml +++ b/dev/integration_tests/flutter_gallery/pubspec.yaml @@ -100,7 +100,7 @@ dev_dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -278,4 +278,4 @@ flutter: - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Regular.ttf - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Light.ttf -# PUBSPEC CHECKSUM: 8cc1 +# PUBSPEC CHECKSUM: 58c2 diff --git a/dev/integration_tests/gradle_deprecated_settings/pubspec.yaml b/dev/integration_tests/gradle_deprecated_settings/pubspec.yaml index 28f7cf75782db..af7f811203922 100644 --- a/dev/integration_tests/gradle_deprecated_settings/pubspec.yaml +++ b/dev/integration_tests/gradle_deprecated_settings/pubspec.yaml @@ -7,10 +7,10 @@ environment: dependencies: flutter: sdk: flutter - camera: 0.9.4+12 + camera: 0.9.4+14 camera_platform_interface: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - camera_web: 0.2.1+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + camera_web: 0.2.1+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" characters: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" collection: 1.15.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" cross_file: 0.3.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -20,7 +20,6 @@ dependencies: material_color_utilities: 0.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.7.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - pedantic: 1.11.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" plugin_platform_interface: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" quiver: 3.0.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" stack_trace: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -31,4 +30,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 9f20 +# PUBSPEC CHECKSUM: 3c5c diff --git a/dev/integration_tests/hybrid_android_views/pubspec.yaml b/dev/integration_tests/hybrid_android_views/pubspec.yaml index d4729cc221c02..d93876aa68d9e 100644 --- a/dev/integration_tests/hybrid_android_views/pubspec.yaml +++ b/dev/integration_tests/hybrid_android_views/pubspec.yaml @@ -28,8 +28,8 @@ dependencies: material_color_utilities: 0.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.7.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path: 1.8.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_android: 2.0.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - path_provider_ios: 2.0.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_android: 2.0.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path_provider_ios: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_linux: 2.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_macos: 2.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" path_provider_platform_interface: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -41,9 +41,9 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - win32: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + win32: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" xdg_directories: 0.2.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -94,4 +94,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: e421 +# PUBSPEC CHECKSUM: 2925 diff --git a/dev/integration_tests/ios_platform_view_tests/pubspec.yaml b/dev/integration_tests/ios_platform_view_tests/pubspec.yaml index e9b3facfb9d27..79fda032ad032 100644 --- a/dev/integration_tests/ios_platform_view_tests/pubspec.yaml +++ b/dev/integration_tests/ios_platform_view_tests/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: sync_http: 0.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -79,4 +79,4 @@ flutter: # the material Icons class. uses-material-design: true -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/dev/integration_tests/platform_interaction/pubspec.yaml b/dev/integration_tests/platform_interaction/pubspec.yaml index e9992e8873507..843a0caba862b 100644 --- a/dev/integration_tests/platform_interaction/pubspec.yaml +++ b/dev/integration_tests/platform_interaction/pubspec.yaml @@ -57,7 +57,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -67,4 +67,4 @@ dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: a73c +# PUBSPEC CHECKSUM: 733d diff --git a/dev/integration_tests/release_smoke_test/pubspec.yaml b/dev/integration_tests/release_smoke_test/pubspec.yaml index f431d719da849..a957e789a4ce1 100644 --- a/dev/integration_tests/release_smoke_test/pubspec.yaml +++ b/dev/integration_tests/release_smoke_test/pubspec.yaml @@ -33,6 +33,6 @@ dev_dependencies: string_scanner: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 7509 +# PUBSPEC CHECKSUM: 7a0a diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml index 8c4c1c66fe011..6a13a5297b7d1 100644 --- a/dev/integration_tests/ui/pubspec.yaml +++ b/dev/integration_tests/ui/pubspec.yaml @@ -8,7 +8,7 @@ environment: # It can probably be removed, see the comment in that file. dependencies: - image: 3.1.1 + image: 3.1.3 flutter: sdk: flutter flutter_driver: @@ -63,7 +63,7 @@ dependencies: test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -82,4 +82,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 7df0 +# PUBSPEC CHECKSUM: 89f3 diff --git a/dev/integration_tests/web_e2e_tests/pubspec.yaml b/dev/integration_tests/web_e2e_tests/pubspec.yaml index c898774401449..dcca07dbfbf84 100644 --- a/dev/integration_tests/web_e2e_tests/pubspec.yaml +++ b/dev/integration_tests/web_e2e_tests/pubspec.yaml @@ -46,7 +46,7 @@ dependencies: test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" vector_math: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" dev_dependencies: @@ -86,4 +86,4 @@ dev_dependencies: webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: b6d8 +# PUBSPEC CHECKSUM: 82d9 diff --git a/dev/manual_tests/lib/drag_and_drop.dart b/dev/manual_tests/lib/drag_and_drop.dart index 944a7464495d0..85101e845fb39 100644 --- a/dev/manual_tests/lib/drag_and_drop.dart +++ b/dev/manual_tests/lib/drag_and_drop.dart @@ -16,9 +16,9 @@ class ExampleDragTarget extends StatefulWidget { class ExampleDragTargetState extends State { Color _color = Colors.grey; - void _handleAccept(Color data) { + void _handleAccept(Color? data) { setState(() { - _color = data; + _color = data!; }); } @@ -215,7 +215,7 @@ class MovableBall extends StatelessWidget { ); } else { return DragTarget( - onAccept: (bool data) { callback(position); }, + onAccept: (bool? data) { callback(position); }, builder: (BuildContext context, List accepted, List rejected) { return dashedBall; }, diff --git a/dev/snippets/config/skeletons/sample.html b/dev/snippets/config/skeletons/sample.html index 92dd25aa832bd..e4b672fa694d0 100644 --- a/dev/snippets/config/skeletons/sample.html +++ b/dev/snippets/config/skeletons/sample.html @@ -8,35 +8,18 @@ link -
- - - -
-
+
{{description}} -
- -
{{code}}
-
-
-
diff --git a/dev/tools/dartdoc.dart b/dev/tools/dartdoc.dart index 26ab9cfb1c652..6a0b128e16bd9 100644 --- a/dev/tools/dartdoc.dart +++ b/dev/tools/dartdoc.dart @@ -173,7 +173,6 @@ Future main(List arguments) async { 'analyzer', 'args', 'barback', - 'cli_util', 'csslib', 'flutter_goldens', 'flutter_goldens_client', @@ -382,6 +381,25 @@ void cleanOutSnippets() { } } +void _sanityCheckExample(File file, RegExp regExp) { + if (file.existsSync()) { + final List contents = file.readAsLinesSync(); + bool found = false; + for (final String line in contents) { + if (regExp.matchAsPrefix(line) != null) { + found = true; + break; + } + } + if (!found) { + throw Exception("Missing example code in ${file.path}. Either it didn't get published, publishing has changed, or the example no longer exists."); + } + } else { + throw Exception("Missing example code sanity test file ${file.path}. Either it didn't get published, or you might have to update the test to look at a different file."); + } +} + +/// Runs a sanity check by running a test. void sanityCheckDocs() { final List canaries = [ '$kPublishRoot/assets/overrides.css', @@ -398,6 +416,22 @@ void sanityCheckDocs() { if (!File(canary).existsSync()) throw Exception('Missing "$canary", which probably means the documentation failed to build correctly.'); } + // Make sure at least one example of each kind includes source code. + + // Check a "sample" example, any one will do. + final File sampleExample = File('$kPublishRoot/api/widgets/showGeneralDialog.html'); + final RegExp sampleRegExp = RegExp(r'\s*
\s*\s*import 'package:flutter/material.dart';');
+  _sanityCheckExample(sampleExample, sampleRegExp);
+
+  // Check a "snippet" example, any one will do.
+  final File snippetExample = File('$kPublishRoot/api/widgets/ModalRoute/barrierColor.html');
+  final RegExp snippetRegExp = RegExp(r'\s*
.*Color get barrierColor => Theme\.of\(navigator\.context\)\.backgroundColor;.*
'); + _sanityCheckExample(snippetExample, snippetRegExp); + + // Check a "dartpad" example, any one will do. + final File dartpadExample = File('$kPublishRoot/api/widgets/PhysicalShape-class.html'); + final RegExp dartpadRegExp = RegExp(r'\s*'); + _sanityCheckExample(dartpadExample, dartpadRegExp); } /// Creates a custom index.html because we try to maintain old diff --git a/dev/tools/gen_defaults/pubspec.yaml b/dev/tools/gen_defaults/pubspec.yaml index 33ffd6b7f1e22..0b109abe15acd 100644 --- a/dev/tools/gen_defaults/pubspec.yaml +++ b/dev/tools/gen_defaults/pubspec.yaml @@ -51,10 +51,10 @@ dev_dependencies: test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" typed_data: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: e5dd +# PUBSPEC CHECKSUM: 91de diff --git a/dev/tools/gen_keycodes/pubspec.yaml b/dev/tools/gen_keycodes/pubspec.yaml index ffcce2a8aa913..66920aa120ccb 100644 --- a/dev/tools/gen_keycodes/pubspec.yaml +++ b/dev/tools/gen_keycodes/pubspec.yaml @@ -53,10 +53,10 @@ dev_dependencies: stack_trace: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" stream_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: bad2 +# PUBSPEC CHECKSUM: 66d3 diff --git a/dev/tools/pubspec.yaml b/dev/tools/pubspec.yaml index 80fc055e42774..a0db37c37d9b3 100644 --- a/dev/tools/pubspec.yaml +++ b/dev/tools/pubspec.yaml @@ -57,10 +57,10 @@ dev_dependencies: stack_trace: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" stream_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 7118 +# PUBSPEC CHECKSUM: 1d19 diff --git a/dev/tracing_tests/pubspec.yaml b/dev/tracing_tests/pubspec.yaml index ef29e903d13ab..f923cba1ba3ba 100644 --- a/dev/tracing_tests/pubspec.yaml +++ b/dev/tracing_tests/pubspec.yaml @@ -8,7 +8,7 @@ dependencies: flutter: sdk: flutter - vm_service: 8.1.0 + vm_service: 8.2.0 characters: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" collection: 1.15.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -35,4 +35,4 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 7509 +# PUBSPEC CHECKSUM: 7a0a diff --git a/examples/api/README.md b/examples/api/README.md index 2c1a878295c79..07574a2b3068d 100644 --- a/examples/api/README.md +++ b/examples/api/README.md @@ -6,7 +6,7 @@ documentation in the framework. The examples can be run individually by just specifying the path to the example on the command line (or in the run configuration of an IDE). -For example (no pun intended!), to run, the first example from the `Curve2D` +For example (no pun intended!), to run the first example from the `Curve2D` class in Chrome, you would run it like so from the [api](.) directory: ``` diff --git a/examples/api/lib/foundation/change_notifier/change_notifier.0.dart b/examples/api/lib/foundation/change_notifier/change_notifier.0.dart new file mode 100644 index 0000000000000..28011318331a7 --- /dev/null +++ b/examples/api/lib/foundation/change_notifier/change_notifier.0.dart @@ -0,0 +1,65 @@ +// Copyright 2014 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. + +// Flutter code sample for ChangeNotifier with an AnimatedBuilder + +import 'package:flutter/material.dart'; + +class CounterBody extends StatelessWidget { + const CounterBody({Key? key, required this.counterValueNotifier}) : super(key: key); + + final ValueNotifier counterValueNotifier; + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Current counter value:'), + // Thanks to the [AnimatedBuilder], only the widget displaying the + // current count is rebuilt when `counterValueNotifier` notifies its + // listeners. The [Text] widget above and [CounterBody] itself aren't + // rebuilt. + AnimatedBuilder( + // [AnimatedBuilder] accepts any [Listenable] subtype. + animation: counterValueNotifier, + builder: (BuildContext context, Widget? child) { + return Text('${counterValueNotifier.value}'); + }, + ), + ], + ), + ); + } +} + +class MyApp extends StatefulWidget { + const MyApp({Key? key}) : super(key: key); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + final ValueNotifier _counter = ValueNotifier(0); + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar(title: const Text('AnimatedBuilder example')), + body: CounterBody(counterValueNotifier: _counter), + floatingActionButton: FloatingActionButton( + onPressed: () => _counter.value++, + child: const Icon(Icons.add), + ), + ), + ); + } +} + +void main() { + runApp(const MyApp()); +} diff --git a/examples/api/lib/widgets/drag_target/draggable.0.dart b/examples/api/lib/widgets/drag_target/draggable.0.dart index d09bfbe2237f6..1562528b8ed81 100644 --- a/examples/api/lib/widgets/drag_target/draggable.0.dart +++ b/examples/api/lib/widgets/drag_target/draggable.0.dart @@ -81,9 +81,9 @@ class _MyStatefulWidgetState extends State { ), ); }, - onAccept: (int data) { + onAccept: (int? data) { setState(() { - acceptedData += data; + acceptedData += data!; }); }, ), diff --git a/examples/api/pubspec.yaml b/examples/api/pubspec.yaml index 56e9db2c497c0..5c9a2ecdd6bfe 100644 --- a/examples/api/pubspec.yaml +++ b/examples/api/pubspec.yaml @@ -71,7 +71,7 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -81,4 +81,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 939c +# PUBSPEC CHECKSUM: 5f9d diff --git a/examples/api/test/foundation/change_notifier/change_notifier.0_test.dart b/examples/api/test/foundation/change_notifier/change_notifier.0_test.dart new file mode 100644 index 0000000000000..c7fc76c6cbbcf --- /dev/null +++ b/examples/api/test/foundation/change_notifier/change_notifier.0_test.dart @@ -0,0 +1,33 @@ +// Copyright 2014 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 'package:flutter/material.dart'; +import 'package:flutter_api_samples/foundation/change_notifier/change_notifier.0.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Smoke test for MyApp', (WidgetTester tester) async { + await tester.pumpWidget(const MyApp()); + + expect(find.byType(Scaffold), findsOneWidget); + expect(find.byType(CounterBody), findsOneWidget); + expect(find.byType(FloatingActionButton), findsOneWidget); + expect(find.text('Current counter value:'), findsOneWidget); + }); + + testWidgets('Counter update', (WidgetTester tester) async { + await tester.pumpWidget(const MyApp()); + + // Initial state of the counter + expect(find.text('0'), findsOneWidget); + + // Tapping the increase button + await tester.tap(find.byType(FloatingActionButton)); + await tester.pumpAndSettle(); + + // Counter should be at 1 + expect(find.text('1'), findsOneWidget); + expect(find.text('0'), findsNothing); + }); +} diff --git a/examples/hello_world/pubspec.yaml b/examples/hello_world/pubspec.yaml index 74feee1fa47d6..81193f0e1a169 100644 --- a/examples/hello_world/pubspec.yaml +++ b/examples/hello_world/pubspec.yaml @@ -63,11 +63,11 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/examples/platform_channel/pubspec.yaml b/examples/platform_channel/pubspec.yaml index 1146abc3dd826..80410ca6f395a 100644 --- a/examples/platform_channel/pubspec.yaml +++ b/examples/platform_channel/pubspec.yaml @@ -63,7 +63,7 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -73,4 +73,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/examples/platform_channel_swift/pubspec.yaml b/examples/platform_channel_swift/pubspec.yaml index 53c076d8d725c..6c2a3a18240b8 100644 --- a/examples/platform_channel_swift/pubspec.yaml +++ b/examples/platform_channel_swift/pubspec.yaml @@ -63,7 +63,7 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -73,4 +73,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 26f5 +# PUBSPEC CHECKSUM: f1f6 diff --git a/packages/flutter/lib/src/cupertino/text_theme.dart b/packages/flutter/lib/src/cupertino/text_theme.dart index d632f49c95539..51ed4dd3a9117 100644 --- a/packages/flutter/lib/src/cupertino/text_theme.dart +++ b/packages/flutter/lib/src/cupertino/text_theme.dart @@ -45,6 +45,7 @@ const TextStyle _kDefaultTabLabelTextStyle = TextStyle( inherit: false, fontFamily: '.SF Pro Text', fontSize: 10.0, + fontWeight: FontWeight.w500, letterSpacing: -0.24, color: CupertinoColors.inactiveGray, ); diff --git a/packages/flutter/lib/src/foundation/change_notifier.dart b/packages/flutter/lib/src/foundation/change_notifier.dart index d3b521f7d3f79..a9e20eda14f69 100644 --- a/packages/flutter/lib/src/foundation/change_notifier.dart +++ b/packages/flutter/lib/src/foundation/change_notifier.dart @@ -98,6 +98,8 @@ abstract class ValueListenable extends Listenable { /// It is O(1) for adding listeners and O(N) for removing listeners and dispatching /// notifications (where N is the number of listeners). /// +/// {@macro flutter.flutter.animatedbuilder_changenotifier.rebuild} +/// /// See also: /// /// * [ValueNotifier], which is a [ChangeNotifier] that wraps a single value. diff --git a/packages/flutter/lib/src/material/reorderable_list.dart b/packages/flutter/lib/src/material/reorderable_list.dart index 06f3ed0d4c22d..39fa4c9642047 100644 --- a/packages/flutter/lib/src/material/reorderable_list.dart +++ b/packages/flutter/lib/src/material/reorderable_list.dart @@ -72,6 +72,7 @@ class ReorderableListView extends StatefulWidget { this.buildDefaultDragHandles = true, this.padding, this.header, + this.footer, this.scrollDirection = Axis.vertical, this.reverse = false, this.scrollController, @@ -141,6 +142,7 @@ class ReorderableListView extends StatefulWidget { this.buildDefaultDragHandles = true, this.padding, this.header, + this.footer, this.scrollDirection = Axis.vertical, this.reverse = false, this.scrollController, @@ -214,6 +216,11 @@ class ReorderableListView extends StatefulWidget { /// If null, no header will appear before the list. final Widget? header; + /// A non-reorderable footer item to show after the items of the list. + /// + /// If null, no footer will appear after the list. + final Widget? footer; + /// {@macro flutter.widgets.scroll_view.scrollDirection} final Axis scrollDirection; @@ -426,39 +433,41 @@ class _ReorderableListViewState extends State { assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasOverlay(context)); - // If there is a header we can't just apply the padding to the list, - // so we break it up into padding for the header and padding for the list. + // If there is a header or footer we can't just apply the padding to the list, + // so we break it up into padding for the header, footer and padding for the list. final EdgeInsets padding = widget.padding ?? EdgeInsets.zero; late final EdgeInsets headerPadding; + late final EdgeInsets footerPadding; late final EdgeInsets listPadding; - if (widget.header == null) { + if (widget.header == null && widget.footer == null) { headerPadding = EdgeInsets.zero; + footerPadding = EdgeInsets.zero; listPadding = padding; - } else { + } else if (widget.header != null || widget.footer != null) { switch (widget.scrollDirection) { case Axis.horizontal: if (widget.reverse) { - // Header on the right headerPadding = EdgeInsets.fromLTRB(0, padding.top, padding.right, padding.bottom); - listPadding = EdgeInsets.fromLTRB(padding.left, padding.top, 0, padding.bottom); + listPadding = EdgeInsets.fromLTRB(widget.footer != null ? 0 : padding.left, padding.top, widget.header != null ? 0 : padding.right, padding.bottom); + footerPadding = EdgeInsets.fromLTRB(padding.left, padding.top, 0, padding.bottom); } else { - // Header on the left headerPadding = EdgeInsets.fromLTRB(padding.left, padding.top, 0, padding.bottom); - listPadding = EdgeInsets.fromLTRB(0, padding.top, padding.right, padding.bottom); + listPadding = EdgeInsets.fromLTRB(widget.header != null ? 0 : padding.left, padding.top, widget.footer != null ? 0 : padding.right, padding.bottom); + footerPadding = EdgeInsets.fromLTRB(0, padding.top, padding.right, padding.bottom); } break; case Axis.vertical: if (widget.reverse) { - // Header on the bottom headerPadding = EdgeInsets.fromLTRB(padding.left, 0, padding.right, padding.bottom); - listPadding = EdgeInsets.fromLTRB(padding.left, padding.top, padding.right, 0); + listPadding = EdgeInsets.fromLTRB(padding.left, widget.footer != null ? 0 : padding.top, padding.right, widget.header != null ? 0 : padding.bottom); + footerPadding = EdgeInsets.fromLTRB(padding.left, padding.top, padding.right, 0); } else { - // Header on the top headerPadding = EdgeInsets.fromLTRB(padding.left, padding.top, padding.right, 0); - listPadding = EdgeInsets.fromLTRB(padding.left, 0, padding.right, padding.bottom); + listPadding = EdgeInsets.fromLTRB(padding.left, widget.header != null ? 0 : padding.top, padding.right, widget.footer != null ? 0 : padding.bottom); + footerPadding = EdgeInsets.fromLTRB(padding.left, 0, padding.right, padding.bottom); } - break; + break; } } @@ -494,6 +503,11 @@ class _ReorderableListViewState extends State { proxyDecorator: widget.proxyDecorator ?? _proxyDecorator, ), ), + if (widget.footer != null) + SliverPadding( + padding: footerPadding, + sliver: SliverToBoxAdapter(child: widget.footer), + ), ], ); } diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart index cb997fecdb8f0..aeaff37358169 100644 --- a/packages/flutter/lib/src/material/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -204,6 +204,7 @@ class SnackBar extends StatefulWidget { this.animation, this.onVisible, this.dismissDirection = DismissDirection.down, + this.clipBehavior = Clip.hardEdge, }) : assert(elevation == null || elevation >= 0.0), assert(content != null), assert( @@ -211,6 +212,7 @@ class SnackBar extends StatefulWidget { 'Width and margin can not be used together', ), assert(duration != null), + assert(clipBehavior != null), super(key: key); /// The primary content of the snack bar. @@ -336,6 +338,11 @@ class SnackBar extends StatefulWidget { /// Cannot be null, defaults to [DismissDirection.down]. final DismissDirection dismissDirection; + /// {@macro flutter.material.Material.clipBehavior} + /// + /// Defaults to [Clip.hardEdge], and must not be null. + final Clip clipBehavior; + // API for ScaffoldMessengerState.showSnackBar(): /// Creates an animation controller useful for driving a snack bar's entrance and exit animation. @@ -367,6 +374,7 @@ class SnackBar extends StatefulWidget { animation: newAnimation, onVisible: onVisible, dismissDirection: dismissDirection, + clipBehavior: clipBehavior, ); } @@ -612,7 +620,10 @@ class _SnackBarState extends State { return Hero( tag: '', - child: snackBarTransition, + child: ClipRect( + clipBehavior: widget.clipBehavior, + child: snackBarTransition, + ), ); } } diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 3714622d2242c..1d298003573e7 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -1420,7 +1420,9 @@ class _TabBarViewState extends State { if (widget.controller != oldWidget.controller) { _updateTabController(); _currentIndex = _controller!.index; + _warpUnderwayCount += 1; _pageController.jumpToPage(_currentIndex!); + _warpUnderwayCount -= 1; } if (widget.children != oldWidget.children && _warpUnderwayCount == 0) _updateChildren(); diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index 94fc68844215b..ccafd50a0d330 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -522,12 +522,16 @@ class _TooltipState extends State with SingleTickerProviderStateMixin { static final Set<_TooltipState> _mouseIn = <_TooltipState>{}; void _handleMouseEnter() { - _showTooltip(); + if (mounted) { + _showTooltip(); + } } void _handleMouseExit({bool immediately = false}) { - // If the tip is currently covered, we can just remove it without waiting. - _dismissTooltip(immediately: _isConcealed || immediately); + if (mounted) { + // If the tip is currently covered, we can just remove it without waiting. + _dismissTooltip(immediately: _isConcealed || immediately); + } } void _createNewEntry() { diff --git a/packages/flutter/lib/src/painting/placeholder_span.dart b/packages/flutter/lib/src/painting/placeholder_span.dart index 1f0c0cbbbf3fe..536b52e950b74 100644 --- a/packages/flutter/lib/src/painting/placeholder_span.dart +++ b/packages/flutter/lib/src/painting/placeholder_span.dart @@ -42,7 +42,7 @@ abstract class PlaceholderSpan extends InlineSpan { }) : super(style: style); /// The unicode character to represent a placeholder. - static const String placeholderCodeUnit = '\uFFFC'; + static const int placeholderCodeUnit = 0xFFFC; /// How the placeholder aligns vertically with the text. /// @@ -60,7 +60,7 @@ abstract class PlaceholderSpan extends InlineSpan { @override void computeToPlainText(StringBuffer buffer, {bool includeSemanticsLabels = true, bool includePlaceholders = true}) { if (includePlaceholders) { - buffer.write(placeholderCodeUnit); + buffer.writeCharCode(placeholderCodeUnit); } } diff --git a/packages/flutter/lib/src/services/hardware_keyboard.dart b/packages/flutter/lib/src/services/hardware_keyboard.dart index 81c68bc59a540..d554f3767f2ce 100644 --- a/packages/flutter/lib/src/services/hardware_keyboard.dart +++ b/packages/flutter/lib/src/services/hardware_keyboard.dart @@ -887,6 +887,7 @@ class KeyEventManager { final PhysicalKeyboardKey physicalKey = rawEvent.physicalKey; final LogicalKeyboardKey logicalKey = rawEvent.logicalKey; final Set physicalKeysPressed = _hardwareKeyboard.physicalKeysPressed; + final List eventAfterwards = []; final KeyEvent? mainEvent; final LogicalKeyboardKey? recordedLogicalMain = _hardwareKeyboard.lookUpLayout(physicalKey); final Duration timeStamp = ServicesBinding.instance.currentSystemFrameTimeStamp; @@ -923,12 +924,24 @@ class KeyEventManager { } } for (final PhysicalKeyboardKey key in physicalKeysPressed.difference(_rawKeyboard.physicalKeysPressed)) { - _keyEventsSinceLastMessage.add(KeyUpEvent( - physicalKey: key, - logicalKey: _hardwareKeyboard.lookUpLayout(key)!, - timeStamp: timeStamp, - synthesized: true, - )); + if (key == physicalKey) { + // Somehow, a down event is dispatched but the key is absent from + // keysPressed. Synthesize a up event for the key, but this event must + // be added after the main key down event. + eventAfterwards.add(KeyUpEvent( + physicalKey: key, + logicalKey: logicalKey, + timeStamp: timeStamp, + synthesized: true, + )); + } else { + _keyEventsSinceLastMessage.add(KeyUpEvent( + physicalKey: key, + logicalKey: _hardwareKeyboard.lookUpLayout(key)!, + timeStamp: timeStamp, + synthesized: true, + )); + } } for (final PhysicalKeyboardKey key in _rawKeyboard.physicalKeysPressed.difference(physicalKeysPressed)) { _keyEventsSinceLastMessage.add(KeyDownEvent( @@ -938,8 +951,10 @@ class KeyEventManager { synthesized: true, )); } - if (mainEvent != null) + if (mainEvent != null) { _keyEventsSinceLastMessage.add(mainEvent); + } + _keyEventsSinceLastMessage.addAll(eventAfterwards); } /// Reset the inferred platform transit mode and related states. diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index e47b3a54f0229..d1644f03a318d 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -3359,6 +3359,8 @@ class IntrinsicHeight extends SingleChildRenderObjectWidget { /// the top of the child to the baseline of the child, then the child /// is top-aligned instead. /// +/// {@youtube 560 315 https://www.youtube.com/watch?v=8ZaFk0yvNlI} +/// /// See also: /// /// * [Align], a widget that aligns its child within itself and optionally diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 380d0330dca63..c6bb4cc1ff2e1 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -20,7 +20,7 @@ typedef DragTargetWillAccept = bool Function(T? data); /// Signature for causing a [DragTarget] to accept the given data. /// /// Used by [DragTarget.onAccept]. -typedef DragTargetAccept = void Function(T data); +typedef DragTargetAccept = void Function(T? data); /// Signature for determining information about the acceptance by a [DragTarget]. /// @@ -638,7 +638,7 @@ class DragTargetDetails { DragTargetDetails({required this.data, required this.offset}) : assert(offset != null); /// The data that was dropped onto this [DragTarget]. - final T data; + final T? data; /// The global position when the specific pointer event occurred on /// the draggable. @@ -767,14 +767,14 @@ class _DragTargetState extends State> { setState(() { _candidateAvatars.remove(avatar); }); - widget.onAccept?.call(avatar.data! as T); - widget.onAcceptWithDetails?.call(DragTargetDetails(data: avatar.data! as T, offset: avatar._lastOffset!)); + widget.onAccept?.call(avatar.data as T?); + widget.onAcceptWithDetails?.call(DragTargetDetails(data: avatar.data as T?, offset: avatar._lastOffset!)); } void didMove(_DragAvatar avatar) { if (!mounted) return; - widget.onMove?.call(DragTargetDetails(data: avatar.data! as T, offset: avatar._lastOffset!)); + widget.onMove?.call(DragTargetDetails(data: avatar.data as T?, offset: avatar._lastOffset!)); } @override diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 99ae704991c66..ed5f53351f2f2 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -1689,7 +1689,10 @@ class EditableTextState extends State with AutomaticKeepAliveClien Clipboard.setData(ClipboardData(text: selection.textInside(text))); _replaceText(ReplaceTextIntent(textEditingValue, '', selection, cause)); if (cause == SelectionChangedCause.toolbar) { - bringIntoView(textEditingValue.selection.extent); + // Schedule a call to bringIntoView() after renderEditable updates. + SchedulerBinding.instance.addPostFrameCallback((_) { + bringIntoView(textEditingValue.selection.extent); + }); hideToolbar(); } _clipboardStatus?.update(); @@ -1713,9 +1716,22 @@ class EditableTextState extends State with AutomaticKeepAliveClien return; } - _replaceText(ReplaceTextIntent(textEditingValue, data.text!, selection, cause)); + // After the paste, the cursor should be collapsed and located after the + // pasted content. + final int lastSelectionIndex = math.max(selection.baseOffset, selection.extentOffset); + final TextEditingValue collapsedTextEditingValue = textEditingValue.copyWith( + selection: TextSelection.collapsed(offset: lastSelectionIndex), + ); + + userUpdateTextEditingValue( + collapsedTextEditingValue.replaced(selection, data.text!), + cause, + ); if (cause == SelectionChangedCause.toolbar) { - bringIntoView(textEditingValue.selection.extent); + // Schedule a call to bringIntoView() after renderEditable updates. + SchedulerBinding.instance.addPostFrameCallback((_) { + bringIntoView(textEditingValue.selection.extent); + }); hideToolbar(); } } @@ -3095,10 +3111,20 @@ class EditableTextState extends State with AutomaticKeepAliveClien } void _replaceText(ReplaceTextIntent intent) { - userUpdateTextEditingValue( - intent.currentTextEditingValue.replaced(intent.replacementRange, intent.replacementText), - intent.cause, + final TextEditingValue oldValue = _value; + final TextEditingValue newValue = intent.currentTextEditingValue.replaced( + intent.replacementRange, + intent.replacementText, ); + userUpdateTextEditingValue(newValue, intent.cause); + + // If there's no change in text and selection (e.g. when selecting and + // pasting identical text), the widget won't be rebuilt on value update. + // Handle this by calling _didChangeTextEditingValue() so caret and scroll + // updates can happen. + if (newValue == oldValue) { + _didChangeTextEditingValue(); + } } late final Action _replaceTextAction = CallbackAction(onInvoke: _replaceText); diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 67beb0ad38d31..1483b814cfe54 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -8,6 +8,7 @@ import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; +import 'media_query.dart'; export 'package:flutter/gestures.dart' show DragDownDetails, @@ -170,6 +171,8 @@ class GestureDetector extends StatelessWidget { /// because a combination of a horizontal and vertical drag is a pan. Simply /// use the pan callbacks instead. /// + /// {@youtube 560 315 https://www.youtube.com/watch?v=WhVXkCFPmK4} + /// /// By default, gesture detectors contribute semantic information to the tree /// that is used by assistive technology. GestureDetector({ @@ -955,6 +958,7 @@ class GestureDetector extends StatelessWidget { @override Widget build(BuildContext context) { final Map gestures = {}; + final DeviceGestureSettings? gestureSettings = MediaQuery.maybeOf(context)?.gestureSettings; if (onTapDown != null || onTapUp != null || @@ -982,7 +986,8 @@ class GestureDetector extends StatelessWidget { ..onSecondaryTapCancel = onSecondaryTapCancel ..onTertiaryTapDown = onTertiaryTapDown ..onTertiaryTapUp = onTertiaryTapUp - ..onTertiaryTapCancel = onTertiaryTapCancel; + ..onTertiaryTapCancel = onTertiaryTapCancel + ..gestureSettings = gestureSettings; }, ); } @@ -994,7 +999,8 @@ class GestureDetector extends StatelessWidget { instance ..onDoubleTapDown = onDoubleTapDown ..onDoubleTap = onDoubleTap - ..onDoubleTapCancel = onDoubleTapCancel; + ..onDoubleTapCancel = onDoubleTapCancel + ..gestureSettings = gestureSettings; }, ); } @@ -1044,7 +1050,8 @@ class GestureDetector extends StatelessWidget { ..onTertiaryLongPressStart = onTertiaryLongPressStart ..onTertiaryLongPressMoveUpdate = onTertiaryLongPressMoveUpdate ..onTertiaryLongPressUp = onTertiaryLongPressUp - ..onTertiaryLongPressEnd = onTertiaryLongPressEnd; + ..onTertiaryLongPressEnd = onTertiaryLongPressEnd + ..gestureSettings = gestureSettings; }, ); } @@ -1063,7 +1070,8 @@ class GestureDetector extends StatelessWidget { ..onUpdate = onVerticalDragUpdate ..onEnd = onVerticalDragEnd ..onCancel = onVerticalDragCancel - ..dragStartBehavior = dragStartBehavior; + ..dragStartBehavior = dragStartBehavior + ..gestureSettings = gestureSettings; }, ); } @@ -1082,7 +1090,8 @@ class GestureDetector extends StatelessWidget { ..onUpdate = onHorizontalDragUpdate ..onEnd = onHorizontalDragEnd ..onCancel = onHorizontalDragCancel - ..dragStartBehavior = dragStartBehavior; + ..dragStartBehavior = dragStartBehavior + ..gestureSettings = gestureSettings; }, ); } @@ -1101,7 +1110,8 @@ class GestureDetector extends StatelessWidget { ..onUpdate = onPanUpdate ..onEnd = onPanEnd ..onCancel = onPanCancel - ..dragStartBehavior = dragStartBehavior; + ..dragStartBehavior = dragStartBehavior + ..gestureSettings = gestureSettings; }, ); } @@ -1114,7 +1124,8 @@ class GestureDetector extends StatelessWidget { ..onStart = onScaleStart ..onUpdate = onScaleUpdate ..onEnd = onScaleEnd - ..dragStartBehavior = dragStartBehavior; + ..dragStartBehavior = dragStartBehavior + ..gestureSettings = gestureSettings; }, ); } @@ -1130,7 +1141,8 @@ class GestureDetector extends StatelessWidget { ..onStart = onForcePressStart ..onPeak = onForcePressPeak ..onUpdate = onForcePressUpdate - ..onEnd = onForcePressEnd; + ..onEnd = onForcePressEnd + ..gestureSettings = gestureSettings; }, ); } diff --git a/packages/flutter/lib/src/widgets/scrollbar.dart b/packages/flutter/lib/src/widgets/scrollbar.dart index 7d08188c26b8a..d7ff4e44b2833 100644 --- a/packages/flutter/lib/src/widgets/scrollbar.dart +++ b/packages/flutter/lib/src/widgets/scrollbar.dart @@ -86,6 +86,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { double mainAxisMargin = 0.0, double crossAxisMargin = 0.0, Radius? radius, + Radius? trackRadius, OutlinedBorder? shape, double minLength = _kMinThumbExtent, double? minOverscrollLength, @@ -117,6 +118,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { _minLength = minLength, _trackColor = trackColor, _trackBorderColor = trackBorderColor, + _trackRadius = trackRadius, _scrollbarOrientation = scrollbarOrientation, _minOverscrollLength = minOverscrollLength ?? minLength, _ignorePointer = ignorePointer { @@ -159,6 +161,19 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { notifyListeners(); } + /// [Radius] of corners of the Scrollbar's track. + /// + /// Scrollbar's track will be rectangular if [trackRadius] is null. + Radius? get trackRadius => _trackRadius; + Radius? _trackRadius; + set trackRadius(Radius? value) { + if (trackRadius == value) + return; + + _trackRadius = value; + notifyListeners(); + } + /// [TextDirection] of the [BuildContext] which dictates the side of the /// screen the scrollbar appears in (the trailing side). Must be set prior to /// calling paint. @@ -496,7 +511,11 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { // Paint if the opacity dictates visibility if (fadeoutOpacityAnimation.value != 0.0) { // Track - canvas.drawRect(_trackRect!, _paintTrack()); + if (trackRadius == null) { + canvas.drawRect(_trackRect!, _paintTrack()); + } else { + canvas.drawRRect(RRect.fromRectAndRadius(_trackRect!, trackRadius!), _paintTrack()); + } // Track Border canvas.drawLine(borderStart, borderEnd, _paintTrack(isBorder: true)); if (radius != null) { @@ -741,6 +760,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter { || mainAxisMargin != oldDelegate.mainAxisMargin || crossAxisMargin != oldDelegate.crossAxisMargin || radius != oldDelegate.radius + || trackRadius != oldDelegate.trackRadius || shape != oldDelegate.shape || padding != oldDelegate.padding || minLength != oldDelegate.minLength @@ -880,6 +900,7 @@ class RawScrollbar extends StatefulWidget { this.minThumbLength = _kMinThumbExtent, this.minOverscrollLength, this.trackVisibility, + this.trackRadius, this.trackColor, this.trackBorderColor, this.fadeDuration = _kScrollbarFadeDuration, @@ -1224,6 +1245,12 @@ class RawScrollbar extends StatefulWidget { /// [MaterialState]s by using [ScrollbarThemeData.trackVisibility]. final bool? trackVisibility; + /// The [Radius] of the scrollbar track's rounded rectangle corners. + /// + /// Scrollbar's track will be rectangular if [trackRadius] is null, which is + /// the default behavior. + final Radius? trackRadius; + /// The color of the scrollbar track. /// /// The scrollbar track will only be visible when [trackVisibility] and @@ -1380,6 +1407,7 @@ class RawScrollbarState extends State with TickerProv fadeoutOpacityAnimation: _fadeoutOpacityAnimation, thickness: widget.thickness ?? _kScrollbarThickness, radius: widget.radius, + trackRadius: widget.trackRadius, scrollbarOrientation: widget.scrollbarOrientation, mainAxisMargin: widget.mainAxisMargin, shape: widget.shape, @@ -1513,6 +1541,7 @@ class RawScrollbarState extends State with TickerProv void updateScrollbarPainter() { scrollbarPainter ..color = widget.thumbColor ?? const Color(0x66BCBCBC) + ..trackRadius = widget.trackRadius ..trackColor = _showTrack ? const Color(0x08000000) : const Color(0x00000000) ..trackBorderColor = _showTrack ? const Color(0x1a000000) : const Color(0x00000000) ..textDirection = Directionality.of(context) diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart index 75742a191c1d4..eba5269118d73 100644 --- a/packages/flutter/lib/src/widgets/transitions.dart +++ b/packages/flutter/lib/src/widgets/transitions.dart @@ -979,7 +979,7 @@ class DefaultTextStyleTransition extends AnimatedWidget { /// rebuilding it on every animation tick. /// /// If you pass the pre-built subtree as the [child] parameter, the -/// AnimatedBuilder will pass it back to your builder function so that you +/// [AnimatedBuilder] will pass it back to your builder function so that you /// can incorporate it into your build. /// /// Using this pre-built child is entirely optional, but can improve @@ -993,6 +993,25 @@ class DefaultTextStyleTransition extends AnimatedWidget { /// ** See code in examples/api/lib/widgets/transitions/animated_builder.0.dart ** /// {@end-tool} /// +/// {@template flutter.flutter.animatedbuilder_changenotifier.rebuild} +/// ## Improve rebuilds performance using AnimatedBuilder +/// +/// Despite the name, [AnimatedBuilder] is not limited to [Animation]s. Any subtype +/// of [Listenable] (such as [ChangeNotifier] and [ValueNotifier]) can be used with +/// an [AnimatedBuilder] to rebuild only certain parts of a widget when the +/// [Listenable] notifies its listeners. This technique is a performance improvement +/// that allows rebuilding only specific widgets leaving others untouched. +/// +/// {@tool dartpad} +/// The following example implements a simple counter that utilizes an +/// [AnimatedBuilder] to limit rebuilds to only the [Text] widget. The current count +/// is stored in a [ValueNotifier], which rebuilds the [AnimatedBuilder]'s contents +/// when its value is changed. +/// +/// ** See code in examples/api/lib/foundation/change_notifier/change_notifier.0.dart ** +/// {@end-tool} +/// {@endtemplate} +/// /// See also: /// /// * [TweenAnimationBuilder], which animates a property to a target value diff --git a/packages/flutter/lib/src/widgets/widget_span.dart b/packages/flutter/lib/src/widgets/widget_span.dart index 686bf7779c814..b4c035682d5e2 100644 --- a/packages/flutter/lib/src/widgets/widget_span.dart +++ b/packages/flutter/lib/src/widgets/widget_span.dart @@ -140,7 +140,7 @@ class WidgetSpan extends PlaceholderSpan { @override int? codeUnitAtVisitor(int index, Accumulator offset) { offset.increment(1); - return PlaceholderSpan.placeholderCodeUnit.codeUnitAt(0); + return PlaceholderSpan.placeholderCodeUnit; } @override diff --git a/packages/flutter/test/cupertino/text_theme_test.dart b/packages/flutter/test/cupertino/text_theme_test.dart new file mode 100644 index 0000000000000..42dbd520cd13c --- /dev/null +++ b/packages/flutter/test/cupertino/text_theme_test.dart @@ -0,0 +1,62 @@ +// Copyright 2014 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 'package:flutter/cupertino.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('CupertinoTextTheme matches Apple Design resources', () { + // Check the default cupertino text theme against the style values + // Values derived from https://developer.apple.com/design/resources/. + + const CupertinoTextThemeData theme = CupertinoTextThemeData(); + const FontWeight normal = FontWeight.normal; + const FontWeight regular = FontWeight.w400; + const FontWeight medium = FontWeight.w500; + const FontWeight semiBold = FontWeight.w600; + const FontWeight bold = FontWeight.w700; + + // TextStyle 17 -0.41 + expect(theme.textStyle.fontSize, 17); + expect(theme.textStyle.fontFamily, '.SF Pro Text'); + expect(theme.textStyle.letterSpacing, -0.41); + expect(theme.textStyle.fontWeight, null); + + // ActionTextStyle 17 -0.41 + expect(theme.actionTextStyle.fontSize, 17); + expect(theme.actionTextStyle.fontFamily, '.SF Pro Text'); + expect(theme.actionTextStyle.letterSpacing, -0.41); + expect(theme.actionTextStyle.fontWeight, null); + + // TextStyle 17 -0.41 + expect(theme.tabLabelTextStyle.fontSize, 10); + expect(theme.tabLabelTextStyle.fontFamily, '.SF Pro Text'); + expect(theme.tabLabelTextStyle.letterSpacing, -0.24); + expect(theme.tabLabelTextStyle.fontWeight, medium); + + // NavTitle SemiBold 17 -0.41 + expect(theme.navTitleTextStyle.fontSize, 17); + expect(theme.navTitleTextStyle.fontFamily, '.SF Pro Text'); + expect(theme.navTitleTextStyle.letterSpacing, -0.41); + expect(theme.navTitleTextStyle.fontWeight, semiBold); + + // NavLargeTitle Bold 34 0.41 + expect(theme.navLargeTitleTextStyle.fontSize, 34); + expect(theme.navLargeTitleTextStyle.fontFamily, '.SF Pro Display'); + expect(theme.navLargeTitleTextStyle.letterSpacing, 0.41); + expect(theme.navLargeTitleTextStyle.fontWeight, bold); + + // Picker Regular 21 -0.6 + expect(theme.pickerTextStyle.fontSize, 21); + expect(theme.pickerTextStyle.fontFamily, '.SF Pro Display'); + expect(theme.pickerTextStyle.letterSpacing, -0.6); + expect(theme.pickerTextStyle.fontWeight, regular); + + // DateTimePicker Normal 21 + expect(theme.dateTimePickerTextStyle.fontSize, 21); + expect(theme.dateTimePickerTextStyle.fontFamily, '.SF Pro Display'); + expect(theme.dateTimePickerTextStyle.letterSpacing, null); + expect(theme.dateTimePickerTextStyle.fontWeight, normal); + }); +} diff --git a/packages/flutter/test/gestures/gesture_config_regression_test.dart b/packages/flutter/test/gestures/gesture_config_regression_test.dart new file mode 100644 index 0000000000000..c21ade7824e41 --- /dev/null +++ b/packages/flutter/test/gestures/gesture_config_regression_test.dart @@ -0,0 +1,83 @@ +// Copyright 2014 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:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class TestResult { + bool dragStarted = false; + bool dragUpdate = false; +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.testResult}) : super(key: key); + + final TestResult testResult; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold( + body: CustomScrollView( + slivers: [ + SliverFixedExtentList( + itemExtent: 50.0, + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return Container( + alignment: Alignment.center, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onVerticalDragDown: (DragDownDetails details) { + widget.testResult.dragStarted = true; + }, + onVerticalDragUpdate: (DragUpdateDetails details){ + widget.testResult.dragUpdate = true; + }, + onVerticalDragEnd: (_) {}, + child: Text('List Item $index', key: ValueKey(index), + ), + ), + ); + }, + ), + ), + ], + ), + ); + } +} + +void main() { + testWidgets('Scroll Views get the same ScrollConfiguration as GestureDetectors', (WidgetTester tester) async { + tester.binding.window.viewConfigurationTestValue = const ui.ViewConfiguration( + gestureSettings: ui.GestureSettings(physicalTouchSlop: 4), + ); + final TestResult result = TestResult(); + + await tester.pumpWidget(MaterialApp( + title: 'Scroll Bug', + home: MyHomePage(testResult: result), + )); + + // By dragging the scroll view more than the configured touch slop above but less than + // the framework default value, we demonstrate that this causes gesture detectors + // that do not receive the same gesture settings to fire at different times than would + // be expected. + final Offset start = tester.getCenter(find.byKey(const ValueKey(1))); + await tester.timedDragFrom(start, const Offset(0, 5), const Duration(milliseconds: 50)); + await tester.pumpAndSettle(); + + expect(result.dragStarted, true); + expect(result.dragUpdate, true); + }); +} diff --git a/packages/flutter/test/material/reorderable_list_test.dart b/packages/flutter/test/material/reorderable_list_test.dart index 08fb57692b8f2..2e8e8a6da1b33 100644 --- a/packages/flutter/test/material/reorderable_list_test.dart +++ b/packages/flutter/test/material/reorderable_list_test.dart @@ -36,6 +36,7 @@ void main() { Widget build({ Widget? header, + Widget? footer, Axis scrollDirection = Axis.vertical, bool reverse = false, EdgeInsets padding = EdgeInsets.zero, @@ -51,6 +52,7 @@ void main() { width: itemHeight * 10, child: ReorderableListView( header: header, + footer: footer, scrollDirection: scrollDirection, onReorder: onReorder, reverse: reverse, @@ -157,6 +159,20 @@ void main() { expect(listItems, orderedEquals(['Item 2', 'Item 3', 'Item 4', 'Item 1'])); }); + testWidgets('properly reorders with a footer', (WidgetTester tester) async { + await tester.pumpWidget(build(footer: const Text('Footer Text'))); + expect(find.text('Footer Text'), findsOneWidget); + expect(listItems, orderedEquals(originalListItems)); + await longPressDrag( + tester, + tester.getCenter(find.text('Item 1')), + tester.getCenter(find.text('Item 4')) + const Offset(0.0, itemHeight * 2), + ); + await tester.pumpAndSettle(); + expect(find.text('Footer Text'), findsOneWidget); + expect(listItems, orderedEquals(['Item 2', 'Item 3', 'Item 4', 'Item 1'])); + }); + testWidgets('properly determines the vertical drop area extents', (WidgetTester tester) async { final Widget reorderableListView = ReorderableListView( onReorder: (int oldIndex, int newIndex) { }, @@ -764,6 +780,29 @@ void main() { expect(listItems, orderedEquals(['Item 2', 'Item 4', 'Item 3', 'Item 1'])); }); + testWidgets('properly reorders with a footer', (WidgetTester tester) async { + await tester.pumpWidget(build(footer: const Text('Footer Text'), scrollDirection: Axis.horizontal)); + expect(find.text('Footer Text'), findsOneWidget); + expect(listItems, orderedEquals(originalListItems)); + await longPressDrag( + tester, + tester.getCenter(find.text('Item 1')), + tester.getCenter(find.text('Item 4')) + const Offset(itemHeight * 2, 0.0), + ); + await tester.pumpAndSettle(); + expect(find.text('Footer Text'), findsOneWidget); + expect(listItems, orderedEquals(['Item 2', 'Item 3', 'Item 4', 'Item 1'])); + await tester.pumpWidget(build(footer: const Text('Footer Text'), scrollDirection: Axis.horizontal)); + await longPressDrag( + tester, + tester.getCenter(find.text('Item 4')), + tester.getCenter(find.text('Item 3')), + ); + await tester.pumpAndSettle(); + expect(find.text('Footer Text'), findsOneWidget); + expect(listItems, orderedEquals(['Item 2', 'Item 4', 'Item 3', 'Item 1'])); + }); + testWidgets('properly determines the horizontal drop area extents', (WidgetTester tester) async { final Widget reorderableListView = ReorderableListView( scrollDirection: Axis.horizontal, @@ -1242,7 +1281,7 @@ void main() { }); group('Padding', () { - testWidgets('Padding with no header', (WidgetTester tester) async { + testWidgets('Padding with no header & footer', (WidgetTester tester) async { const EdgeInsets padding = EdgeInsets.fromLTRB(10, 20, 30, 40); // Vertical @@ -1256,35 +1295,62 @@ void main() { expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(154, 20, 202, 560)); }); - testWidgets('Padding with header', (WidgetTester tester) async { + testWidgets('Padding with header or footer', (WidgetTester tester) async { const EdgeInsets padding = EdgeInsets.fromLTRB(10, 20, 30, 40); const Key headerKey = Key('Header'); + const Key footerKey = Key('Footer'); const Widget verticalHeader = SizedBox(key: headerKey, height: 10); const Widget horizontalHeader = SizedBox(key: headerKey, width: 10); + const Widget verticalFooter = SizedBox(key: footerKey, height: 10); + const Widget horizontalFooter = SizedBox(key: footerKey, width: 10); - // Vertical + // Vertical Header await tester.pumpWidget(build(padding: padding, header: verticalHeader)); expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 20, 770, 30)); expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 30, 770, 78)); expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 174, 770, 222)); - // Vertical, reversed + // Vertical Footer + await tester.pumpWidget(build(padding: padding, footer: verticalFooter)); + expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(10, 212, 770, 222)); + expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 770, 68)); + expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 164, 770, 212)); + + // Vertical Header, reversed await tester.pumpWidget(build(padding: padding, header: verticalHeader, reverse: true)); expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 550, 770, 560)); expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 502, 770, 550)); expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 358, 770, 406)); - // Horizontal + // Vertical Footer, reversed + await tester.pumpWidget(build(padding: padding, footer: verticalFooter, reverse: true)); + expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(10, 358, 770, 368)); + expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 512, 770, 560)); + expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(10, 368, 770, 416)); + + // Horizontal Header await tester.pumpWidget(build(padding: padding, header: horizontalHeader, scrollDirection: Axis.horizontal)); expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(10, 20, 20, 560)); expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(20, 20, 68, 560)); expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(164, 20, 212, 560)); - // Horizontal, reversed + // // Horizontal Footer + await tester.pumpWidget(build(padding: padding, footer: horizontalFooter, scrollDirection: Axis.horizontal)); + expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(202, 20, 212, 560)); + expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(10, 20, 58, 560)); + expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(154, 20, 202, 560)); + + // Horizontal Header, reversed await tester.pumpWidget(build(padding: padding, header: horizontalHeader, scrollDirection: Axis.horizontal, reverse: true)); expect(tester.getRect(find.byKey(headerKey)), const Rect.fromLTRB(760, 20, 770, 560)); expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(712, 20, 760, 560)); expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(568, 20, 616, 560)); + + // // Horizontal Footer, reversed + await tester.pumpWidget(build(padding: padding, footer: horizontalFooter, scrollDirection: Axis.horizontal, reverse: true)); + expect(tester.getRect(find.byKey(footerKey)), const Rect.fromLTRB(568, 20, 578, 560)); + expect(tester.getRect(find.byKey(const Key('Item 1'))), const Rect.fromLTRB(722, 20, 770, 560)); + expect(tester.getRect(find.byKey(const Key('Item 4'))), const Rect.fromLTRB(578, 20, 626, 560)); }); }); diff --git a/packages/flutter/test/material/snack_bar_test.dart b/packages/flutter/test/material/snack_bar_test.dart index a4477ecec91a5..2eef94246c8e7 100644 --- a/packages/flutter/test/material/snack_bar_test.dart +++ b/packages/flutter/test/material/snack_bar_test.dart @@ -6,6 +6,8 @@ // machines. @Tags(['reduced-test-set']) +import 'dart:ui'; + import 'package:flutter/foundation.dart' show FlutterExceptionHandler; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -2558,6 +2560,38 @@ void main() { 'was set by default.', ); }); + + testWidgets('Snackbar by default clips BackdropFilter', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/98205 + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: const Scaffold(), + floatingActionButton: FloatingActionButton(onPressed: () {}), + ), + )); + + final ScaffoldMessengerState scaffoldMessengerState = tester.state( + find.byType(ScaffoldMessenger), + ); + scaffoldMessengerState.showSnackBar(SnackBar( + backgroundColor: Colors.transparent, + content: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 20.0, + sigmaY: 20.0, + ), + child: const Text('I am a snack bar.'), + ), + duration: const Duration(seconds: 2), + action: SnackBarAction(label: 'ACTION', onPressed: () {}), + behavior: SnackBarBehavior.fixed, + )); + await tester.pumpAndSettle(); + await tester.tap(find.text('I am a snack bar.')); + await tester.pump(); // start animation + await tester.pump(const Duration(milliseconds: 750)); + await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.backdropFilter.png')); + }); } /// Start test for "SnackBar dismiss test". diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index 984fc18f3b8f2..f8ff769949943 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -4253,7 +4253,7 @@ void main() { testWidgets('Change the TabController should make both TabBar and TabBarView return to the initial index.', (WidgetTester tester) async { // This is a regression test for https://github.com/flutter/flutter/issues/93237 - Widget buildFrame(TabController controller, bool showLast) { + Widget buildFrame(TabController controller, {required bool showLast}) { return boilerplate( child: Column( children: [ @@ -4295,23 +4295,22 @@ void main() { length: 3, ); - await tester.pumpWidget(buildFrame(controller1, true)); + await tester.pumpWidget(buildFrame(controller1, showLast: true)); final PageView pageView = tester.widget(find.byType(PageView)); final PageController pageController = pageView.controller; - await tester.tap(find.text('three')); await tester.pumpAndSettle(); expect(controller1.index, 2); expect(pageController.page, 2); // Change TabController from 3 items to 2. - await tester.pumpWidget(buildFrame(controller2, false)); + await tester.pumpWidget(buildFrame(controller2, showLast: false)); await tester.pumpAndSettle(); expect(controller2.index, 0); expect(pageController.page, 0); // Change TabController from 2 items to 3. - await tester.pumpWidget(buildFrame(controller3, true)); + await tester.pumpWidget(buildFrame(controller3, showLast: true)); await tester.pumpAndSettle(); expect(controller3.index, 0); expect(pageController.page, 0); @@ -4323,6 +4322,71 @@ void main() { expect(pageController.page, 2); }); + testWidgets('Do not crash when the new TabController.index is longer than the old length.', (WidgetTester tester) async { + // This is a regression test for https://github.com/flutter/flutter/issues/97441 + + Widget buildFrame(TabController controller, {required bool showLast}) { + return boilerplate( + child: Column( + children: [ + TabBar( + controller: controller, + tabs: [ + const Tab(text: 'one'), + const Tab(text: 'two'), + if (showLast) const Tab(text: 'three'), + ], + ), + Flexible( + child: TabBarView( + controller: controller, + children: [ + const Text('PAGE1'), + const Text('PAGE2'), + if (showLast) const Text('PAGE3'), + ], + ), + ), + ], + ), + ); + } + + final TabController controller1 = TabController( + vsync: const TestVSync(), + length: 3, + ); + + final TabController controller2 = TabController( + vsync: const TestVSync(), + length: 2, + ); + + await tester.pumpWidget(buildFrame(controller1, showLast: true)); + PageView pageView = tester.widget(find.byType(PageView)); + PageController pageController = pageView.controller; + await tester.tap(find.text('three')); + await tester.pumpAndSettle(); + expect(controller1.index, 2); + expect(pageController.page, 2); + + // Change TabController from controller1 to controller2. + await tester.pumpWidget(buildFrame(controller2, showLast: false)); + await tester.pumpAndSettle(); + pageView = tester.widget(find.byType(PageView)); + pageController = pageView.controller; + expect(controller2.index, 0); + expect(pageController.page, 0); + + // Change TabController back to 'controller1' whose index is 2. + await tester.pumpWidget(buildFrame(controller1, showLast: true)); + await tester.pumpAndSettle(); + pageView = tester.widget(find.byType(PageView)); + pageController = pageView.controller; + expect(controller1.index, 2); + expect(pageController.page, 2); + }); + testWidgets('TabBar InkWell splashFactory and overlayColor', (WidgetTester tester) async { const InteractiveInkFeatureFactory splashFactory = NoSplash.splashFactory; final MaterialStateProperty overlayColor = MaterialStateProperty.resolveWith( diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart index 8226eebe9db72..151ae0d49e6f9 100644 --- a/packages/flutter/test/material/tooltip_test.dart +++ b/packages/flutter/test/material/tooltip_test.dart @@ -863,6 +863,62 @@ void main() { await gesture.up(); }); + testWidgets('Dispatch the mouse events before tip overlay detached', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/96890 + const Duration waitDuration = Duration.zero; + TestGesture? gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + addTearDown(() async { + if (gesture != null) + return gesture.removePointer(); + }); + await gesture.addPointer(); + await gesture.moveTo(const Offset(1.0, 1.0)); + await tester.pump(); + await gesture.moveTo(Offset.zero); + + await tester.pumpWidget( + const MaterialApp( + home: Center( + child: Tooltip( + message: tooltipText, + waitDuration: waitDuration, + child: SizedBox( + width: 100.0, + height: 100.0, + ), + ), + ), + ), + ); + + // Trigger the tip overlay. + final Finder tooltip = find.byType(Tooltip); + await gesture.moveTo(tester.getCenter(tooltip)); + await tester.pump(); + // Wait for it to appear. + await tester.pump(waitDuration); + + // Remove the `Tooltip` widget. + await tester.pumpWidget( + const MaterialApp( + home: Center( + child: SizedBox.shrink(), + ), + ), + ); + + // The tooltip overlay still on the tree and it will removed in the next frame. + + // Dispatch the mouse in and out events before the overlay detached. + await gesture.moveTo(tester.getCenter(find.text(tooltipText))); + await gesture.moveTo(Offset.zero); + await tester.pumpAndSettle(); + + // Go without crashes. + await gesture.removePointer(); + gesture = null; + }); + testWidgets('Tooltip shows/hides when hovered', (WidgetTester tester) async { const Duration waitDuration = Duration.zero; TestGesture? gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); diff --git a/packages/flutter/test/services/hardware_keyboard_test.dart b/packages/flutter/test/services/hardware_keyboard_test.dart index 159f9a62f1989..a6080f8a23288 100644 --- a/packages/flutter/test/services/hardware_keyboard_test.dart +++ b/packages/flutter/test/services/hardware_keyboard_test.dart @@ -195,6 +195,56 @@ void main() { logs.clear(); }, variant: KeySimulatorTransitModeVariant.all()); + // Regression test for https://github.com/flutter/flutter/issues/99196 . + // + // In rawKeyData mode, if a key down event is dispatched but immediately + // synthesized to be released, the old logic would trigger a Null check + // _CastError on _hardwareKeyboard.lookUpLayout(key). The original scenario + // that this is triggered on Android is unknown. Here we make up a scenario + // where a ShiftLeft key down is dispatched but the modifier bit is not set. + testWidgets('Correctly convert down events that are synthesized released', (WidgetTester tester) async { + final FocusNode focusNode = FocusNode(); + final List events = []; + + await tester.pumpWidget( + KeyboardListener( + autofocus: true, + focusNode: focusNode, + child: Container(), + onKeyEvent: (KeyEvent event) { + events.add(event); + }, + ), + ); + + // Dispatch an arbitrary event to bypass the pressedKeys check. + await simulateKeyDownEvent(LogicalKeyboardKey.keyA, platform: 'web'); + + // Dispatch an + final Map data2 = KeyEventSimulator.getKeyData( + LogicalKeyboardKey.shiftLeft, + platform: 'web', + )..['metaState'] = 0; + await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + SystemChannels.keyEvent.name, + SystemChannels.keyEvent.codec.encodeMessage(data2), + (ByteData? data) {}, + ); + + expect(events, hasLength(3)); + expect(events[1], isA()); + expect(events[1].logicalKey, LogicalKeyboardKey.shiftLeft); + expect(events[1].synthesized, false); + expect(events[2], isA()); + expect(events[2].logicalKey, LogicalKeyboardKey.shiftLeft); + expect(events[2].synthesized, true); + expect(ServicesBinding.instance.keyboard.physicalKeysPressed, equals({ + PhysicalKeyboardKey.keyA, + })); + }, variant: const KeySimulatorTransitModeVariant({ + KeyDataTransitMode.rawKeyData, + })); + testWidgets('Instantly dispatch synthesized key events when the queue is empty', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); final List logs = []; diff --git a/packages/flutter/test/widgets/draggable_test.dart b/packages/flutter/test/widgets/draggable_test.dart index e58ee03713a7f..2b5bc52ad1090 100644 --- a/packages/flutter/test/widgets/draggable_test.dart +++ b/packages/flutter/test/widgets/draggable_test.dart @@ -39,7 +39,9 @@ void main() { return const SizedBox(height: 100.0, child: Text('Target')); }, onMove: (_) => moveCount++, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -91,9 +93,60 @@ void main() { expect(moveCount, 1); }); + testWidgets('Draggable can be accepted when the data is null', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/84816 + final Map receivedData = {}; + + await tester.pumpWidget(MaterialApp( + home: Column( + children: [ + const Draggable( + feedback: Text('Dragging'), + child: Text('Source'), + ), + DragTarget( + builder: (BuildContext context, List data, List rejects) { + return const SizedBox(height: 100.0, child: Text('Target 1')); + }, + onWillAccept: (int? data) { + receivedData['onWillAccept'] = data; + return true; + }, + onAccept: (int? data) { + receivedData['onAccept'] = data; + }, + onAcceptWithDetails: (DragTargetDetails details) { + receivedData['onAcceptWithDetails'] = details.data; + }, + onMove: (DragTargetDetails details) { + receivedData['onMove'] = details.data; + }, + ), + ], + ), + )); + + final Offset firstLocation = tester.getCenter(find.text('Source')); + final TestGesture gesture = await tester.startGesture(firstLocation, pointer: 7); + await tester.pump(); + + final Offset secondLocation = tester.getCenter(find.text('Target 1')); + await gesture.moveTo(secondLocation); + await tester.pump(); + + await gesture.up(); + await tester.pump(); + + expect(receivedData.length, 4); + expect(receivedData['onWillAccept'], null); + expect(receivedData['onMove'], null); + expect(receivedData['onAccept'], null); + expect(receivedData['onAcceptWithDetails'], null); + }); + // Regression test for https://github.com/flutter/flutter/issues/76825 testWidgets('Drag and drop - onLeave callback fires correctly with generic parameter', (WidgetTester tester) async { - final Map leftBehind = { + final Map leftBehind = { 'Target 1': 0, 'Target 2': 0, }; @@ -168,7 +221,7 @@ void main() { }); testWidgets('Drag and drop - onLeave callback fires correctly', (WidgetTester tester) async { - final Map leftBehind = { + final Map leftBehind = { 'Target 1': 0, 'Target 2': 0, }; @@ -244,7 +297,7 @@ void main() { // Regression test for https://github.com/flutter/flutter/issues/76825 testWidgets('Drag and drop - onMove callback fires correctly with generic parameter', (WidgetTester tester) async { - final Map targetMoveCount = { + final Map targetMoveCount = { 'Target 1': 0, 'Target 2': 0, }; @@ -263,7 +316,7 @@ void main() { }, onMove: (DragTargetDetails details) { targetMoveCount['Target 1'] = - targetMoveCount['Target 1']! + details.data; + targetMoveCount['Target 1']! + details.data!; }, ), DragTarget( @@ -272,7 +325,7 @@ void main() { }, onMove: (DragTargetDetails details) { targetMoveCount['Target 2'] = - targetMoveCount['Target 2']! + details.data; + targetMoveCount['Target 2']! + details.data!; }, ), ], @@ -317,7 +370,7 @@ void main() { }); testWidgets('Drag and drop - onMove callback fires correctly', (WidgetTester tester) async { - final Map targetMoveCount = { + final Map targetMoveCount = { 'Target 1': 0, 'Target 2': 0, }; @@ -1167,7 +1220,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1243,7 +1298,9 @@ void main() { ); }, onWillAccept: (int? data) => false, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1316,7 +1373,9 @@ void main() { return const SizedBox(height: 100.0, child: Text('Target')); }, onWillAccept: (int? data) => false, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ]), @@ -1366,7 +1425,9 @@ void main() { return const SizedBox(height: 100.0, child: Text('Target')); }, onWillAccept: (int? data) => false, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1580,7 +1641,9 @@ void main() { ); }, onWillAccept: (int? data) => false, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1648,7 +1711,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1789,7 +1854,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -1867,7 +1934,9 @@ void main() { ), ); }, - onAccept: acceptedInts.add, + onAccept: (int? data) { + acceptedInts.add(data!); + }, onAcceptWithDetails: acceptedIntsDetails.add, ), DragTarget( @@ -1879,7 +1948,9 @@ void main() { ), ); }, - onAccept: acceptedDoubles.add, + onAccept: (double? data) { + acceptedDoubles.add(data!); + }, onAcceptWithDetails: acceptedDoublesDetails.add, ), ], @@ -1995,7 +2066,9 @@ void main() { child: Text('Target1'), ), ); - }, onAccept: acceptedDragTargetDatas.add, + }, onAccept: (DragTargetData? data) { + acceptedDragTargetDatas.add(data!); + }, onAcceptWithDetails: acceptedDragTargetDataDetails.add, ), DragTarget( @@ -2007,7 +2080,9 @@ void main() { ), ); }, - onAccept: acceptedExtendedDragTargetDatas.add, + onAccept: (ExtendedDragTargetData? data) { + acceptedExtendedDragTargetDatas.add(data!); + }, onAcceptWithDetails: acceptedExtendedDragTargetDataDetails.add, ), ], @@ -2057,7 +2132,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -2316,7 +2393,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -2346,7 +2425,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -2426,7 +2507,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -2511,7 +2594,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], @@ -2765,7 +2850,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (Object? data) { + accepted.add(data!); + }, ), ], ), @@ -2801,7 +2888,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, ), ], ), @@ -2837,7 +2926,9 @@ void main() { builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onWillAccept: (int? data) { if (data == null) isReceiveNullDataForCheck = true; @@ -3180,7 +3271,9 @@ Future _testChildAnchorFeedbackPosition({ required WidgetTester tester, do builder: (BuildContext context, List data, List rejects) { return const SizedBox(height: 100.0, child: Text('Target')); }, - onAccept: accepted.add, + onAccept: (int? data) { + accepted.add(data!); + }, onAcceptWithDetails: acceptedDetails.add, ), ], diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 5c7f821b38d61..497b1d4f2cbe0 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -49,6 +49,8 @@ enum HandlePositionInViewport { leftEdge, rightEdge, within, } +typedef _VoidFutureCallback = Future Function(); + void main() { final MockClipboard mockClipboard = MockClipboard(); TestWidgetsFlutterBinding.ensureInitialized() @@ -10948,12 +10950,12 @@ void main() { // Paste await resetSelectionAndScrollOffset(); - textSelectionDelegate.pasteText(SelectionChangedCause.keyboard); + await textSelectionDelegate.pasteText(SelectionChangedCause.keyboard); await tester.pump(); expect(scrollController.offset, maxScrollExtent); await resetSelectionAndScrollOffset(); - textSelectionDelegate.pasteText(SelectionChangedCause.toolbar); + await textSelectionDelegate.pasteText(SelectionChangedCause.toolbar); await tester.pump(); expect(scrollController.offset.roundToDouble(), 0.0); @@ -10980,6 +10982,50 @@ void main() { expect(scrollController.offset.roundToDouble(), 0.0); }); + testWidgets('Should not scroll on paste if caret already visible', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/96658. + final ScrollController scrollController = ScrollController(); + final TextEditingController controller = TextEditingController( + text: 'Lorem ipsum please paste here: \n${".\n" * 50}', + ); + final FocusNode focusNode = FocusNode(); + + await tester.pumpWidget( + MaterialApp( + home: Center( + child: SizedBox( + height: 600.0, + width: 600.0, + child: EditableText( + controller: controller, + scrollController: scrollController, + focusNode: focusNode, + maxLines: null, + style: const TextStyle(fontSize: 36.0), + backgroundCursorColor: Colors.grey, + cursorColor: cursorColor, + ), + ), + ), + ) + ); + + await Clipboard.setData(const ClipboardData(text: 'Fairly long text to be pasted')); + focusNode.requestFocus(); + + final EditableTextState state = + tester.state(find.byType(EditableText)); + + expect(scrollController.offset, 0.0); + + controller.selection = const TextSelection.collapsed(offset: 31); + await state.pasteText(SelectionChangedCause.toolbar); + await tester.pumpAndSettle(); + + // No scroll should happen as the caret is in the viewport all the time. + expect(scrollController.offset, 0.0); + }); + testWidgets('Autofill enabled by default', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(); await tester.pumpWidget( @@ -11475,6 +11521,140 @@ void main() { }, variant: TargetPlatformVariant.all(), skip: kIsWeb); // [intended] }); + testWidgets('pasting with the keyboard collapses the selection and places it after the pasted content', (WidgetTester tester) async { + Future testPasteSelection(WidgetTester tester, _VoidFutureCallback paste) async { + final TextEditingController controller = TextEditingController(); + await tester.pumpWidget( + MaterialApp( + home: EditableText( + backgroundCursorColor: Colors.grey, + controller: controller, + focusNode: focusNode, + style: textStyle, + cursorColor: cursorColor, + selectionControls: materialTextSelectionControls, + ), + ), + ); + + await tester.pump(); + expect(controller.text, ''); + + await tester.enterText(find.byType(EditableText), '12345'); + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection.collapsed(offset: 5), + )); + + await sendKeys( + tester, + [ + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.arrowLeft, + LogicalKeyboardKey.arrowLeft, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection(baseOffset: 5, extentOffset: 0), + )); + + await sendKeys( + tester, + [ + LogicalKeyboardKey.keyC, + ], + shortcutModifier: true, + targetPlatform: defaultTargetPlatform, + ); + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection(baseOffset: 5, extentOffset: 0), + )); + + // Pasting content of equal length, reversed selection. + await paste(); + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection.collapsed(offset: 5), + )); + + // Pasting content of longer length, forward selection. + await sendKeys( + tester, + [ + LogicalKeyboardKey.arrowLeft, + ], + targetPlatform: defaultTargetPlatform, + ); + await sendKeys( + tester, + [ + LogicalKeyboardKey.arrowRight, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection(baseOffset: 4, extentOffset: 5), + )); + await paste(); + expect(controller.value, const TextEditingValue( + text: '123412345', + selection: TextSelection.collapsed(offset: 9), + )); + + // Pasting content of shorter length, forward selection. + await sendKeys( + tester, + [ + LogicalKeyboardKey.keyA, + ], + shortcutModifier: true, + targetPlatform: defaultTargetPlatform, + ); + expect(controller.value, const TextEditingValue( + text: '123412345', + selection: TextSelection(baseOffset: 0, extentOffset: 9), + )); + await paste(); + // Pump to allow postFrameCallbacks to finish before dispose. + await tester.pump(); + expect(controller.value, const TextEditingValue( + text: '12345', + selection: TextSelection.collapsed(offset: 5), + )); + } + + // Test pasting with the keyboard. + await testPasteSelection(tester, () { + return sendKeys( + tester, + [ + LogicalKeyboardKey.keyV, + ], + shortcutModifier: true, + targetPlatform: defaultTargetPlatform, + ); + }); + + // Test pasting with the toolbar. + await testPasteSelection(tester, () async { + final EditableTextState state = + tester.state(find.byType(EditableText)); + expect(state.showToolbar(), true); + await tester.pumpAndSettle(); + expect(find.text('Paste'), findsOneWidget); + return tester.tap(find.text('Paste')); + }); + }, skip: kIsWeb); // [intended] + // Regression test for https://github.com/flutter/flutter/issues/98322. testWidgets('EditableText consumes ActivateIntent and ButtonActivateIntent', (WidgetTester tester) async { bool receivedIntent = false; diff --git a/packages/flutter/test/widgets/scrollbar_test.dart b/packages/flutter/test/widgets/scrollbar_test.dart index d23a0521a7d51..09d1740fa0544 100644 --- a/packages/flutter/test/widgets/scrollbar_test.dart +++ b/packages/flutter/test/widgets/scrollbar_test.dart @@ -25,6 +25,7 @@ ScrollbarPainter _buildPainter({ double mainAxisMargin = 0.0, double crossAxisMargin = 0.0, Radius? radius, + Radius? trackRadius, double minLength = _kMinThumbExtent, double? minOverscrollLength, ScrollbarOrientation? scrollbarOrientation, @@ -38,6 +39,7 @@ ScrollbarPainter _buildPainter({ mainAxisMargin: mainAxisMargin, crossAxisMargin: crossAxisMargin, radius: radius, + trackRadius: trackRadius, minLength: minLength, minOverscrollLength: minOverscrollLength ?? minLength, fadeoutOpacityAnimation: kAlwaysCompleteAnimation, @@ -47,12 +49,18 @@ ScrollbarPainter _buildPainter({ class _DrawRectOnceCanvas extends Fake implements Canvas { List rects = []; + List rrects = []; @override void drawRect(Rect rect, Paint paint) { rects.add(rect); } + @override + void drawRRect(ui.RRect rrect, ui.Paint paint) { + rrects.add(rrect); + } + @override void drawLine(Offset p1, Offset p2, Paint paint) {} } @@ -62,9 +70,11 @@ void main() { ScrollbarPainter painter; Rect captureRect() => testCanvas.rects.removeLast(); + RRect captureRRect() => testCanvas.rrects.removeLast(); tearDown(() { testCanvas.rects.clear(); + testCanvas.rrects.clear(); }); final ScrollMetrics defaultMetrics = FixedScrollMetrics( @@ -629,6 +639,37 @@ void main() { }, ); + test('trackRadius and radius is respected', () { + const double minLen = 3.5; + const Size size = Size(600, 10); + final ScrollMetrics metrics = defaultMetrics.copyWith( + maxScrollExtent: 100000, + viewportDimension: size.height, + ); + + painter = _buildPainter( + trackRadius: const Radius.circular(2.0), + radius: const Radius.circular(3.0), + minLength: minLen, + minOverscrollLength: minLen, + scrollMetrics: metrics, + ); + + painter.paint(testCanvas, size); + + final RRect thumbRRect = captureRRect(); // thumb + expect(thumbRRect.blRadius, const Radius.circular(3.0)); + expect(thumbRRect.brRadius, const Radius.circular(3.0)); + expect(thumbRRect.tlRadius, const Radius.circular(3.0)); + expect(thumbRRect.trRadius, const Radius.circular(3.0)); + + final RRect trackRRect = captureRRect(); // track + expect(trackRRect.blRadius, const Radius.circular(2.0)); + expect(trackRRect.brRadius, const Radius.circular(2.0)); + expect(trackRRect.tlRadius, const Radius.circular(2.0)); + expect(trackRRect.trRadius, const Radius.circular(2.0)); + }); + testWidgets('ScrollbarPainter asserts if no TextDirection has been provided', (WidgetTester tester) async { final ScrollbarPainter painter = ScrollbarPainter( color: _kScrollbarColor, @@ -691,7 +732,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 240.0, 800.0, 600.0), color: const Color(0x66BCBCBC), - ), + ), ); // Tap on the track area above the thumb. @@ -706,7 +747,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 360.0), color: const Color(0x66BCBCBC), - ), + ), ); }); @@ -736,7 +777,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0), color: const Color(0x66BCBCBC), - ), + ), ); await tester.pump(const Duration(seconds: 3)); @@ -749,7 +790,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0), color: const Color(0x66BCBCBC), - ), + ), ); await gesture.up(); @@ -764,7 +805,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0), color: const Color(0x4fbcbcbc), - ), + ), ); }); @@ -794,7 +835,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0), color: const Color(0x66BCBCBC), - ), + ), ); final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse); @@ -811,7 +852,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 3.0, 800.0, 93.0), color: const Color(0x66BCBCBC), - ), + ), ); }); @@ -940,7 +981,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 0.0, 800.0, 90.0), color: const Color(0x66BCBCBC), - ), + ), ); // Drag the thumb down to scroll down. @@ -962,7 +1003,7 @@ void main() { ..rect( rect: const Rect.fromLTRB(794.0, 10.0, 800.0, 100.0), color: const Color(0x66BCBCBC), - ), + ), ); }); @@ -2206,6 +2247,7 @@ void main() { double mainAxisMargin = 0.0, double crossAxisMargin = 0.0, Radius? radius, + Radius? trackRadius, OutlinedBorder? shape, double minLength = _kMinThumbExtent, double? minOverscrollLength, @@ -2222,6 +2264,7 @@ void main() { mainAxisMargin: mainAxisMargin, crossAxisMargin: crossAxisMargin, radius: radius, + trackRadius: trackRadius, shape: shape, minLength: minLength, minOverscrollLength: minOverscrollLength, @@ -2240,6 +2283,7 @@ void main() { expect(painter.shouldRepaint(createPainter(mainAxisMargin: 1.0)), true); expect(painter.shouldRepaint(createPainter(crossAxisMargin: 1.0)), true); expect(painter.shouldRepaint(createPainter(radius: const Radius.circular(1.0))), true); + expect(painter.shouldRepaint(createPainter(trackRadius: const Radius.circular(1.0))), true); expect(painter.shouldRepaint(createPainter(shape: const CircleBorder(side: BorderSide(width: 2.0)))), true); expect(painter.shouldRepaint(createPainter(minLength: _kMinThumbExtent + 1.0)), true); expect(painter.shouldRepaint(createPainter(minOverscrollLength: 1.0)), true); @@ -2289,6 +2333,45 @@ void main() { ); }); + testWidgets('trackRadius and radius properties of RawScrollbar can draw RoundedRectangularRect', (WidgetTester tester) async { + final ScrollController scrollController = ScrollController(); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: PrimaryScrollController( + controller: scrollController, + child: RawScrollbar( + thumbVisibility: true, + trackVisibility: true, + trackRadius: const Radius.circular(1.0), + radius: const Radius.circular(2.0), + controller: scrollController, + child: const SingleChildScrollView( + child: SizedBox(width: 4000.0, height: 4000.0), + ), + ), + ), + ), + ), + ); + await tester.pumpAndSettle(); + expect(scrollController.offset, 0.0); + expect( + find.byType(RawScrollbar), + paints + ..rrect( + rrect: RRect.fromLTRBR(794.0, 0.0, 800.0, 600.0, const Radius.circular(1.0)), + color: const Color(0x08000000), + ) + ..rrect( + rrect: RRect.fromLTRBR(794.0, 0.0, 800.0, 90.0, const Radius.circular(2.0)), + color: const Color(0x66bcbcbc), + ) + ); + }); + testWidgets('Scrollbar asserts that a visible track has a visible thumb', (WidgetTester tester) async { final ScrollController scrollController = ScrollController(); Widget _buildApp() { diff --git a/packages/flutter_driver/pubspec.yaml b/packages/flutter_driver/pubspec.yaml index 2f573fa77e03c..418b678d78718 100644 --- a/packages/flutter_driver/pubspec.yaml +++ b/packages/flutter_driver/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: sdk: flutter path: 1.8.1 meta: 1.7.0 - vm_service: 8.1.0 + vm_service: 8.2.0 webdriver: 3.0.0 archive: 3.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -74,4 +74,4 @@ dev_dependencies: webkit_inspection_protocol: 1.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" yaml: 3.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" -# PUBSPEC CHECKSUM: 08fc +# PUBSPEC CHECKSUM: d3fd diff --git a/packages/flutter_goldens/lib/flutter_goldens.dart b/packages/flutter_goldens/lib/flutter_goldens.dart index 664141487514e..e0b5bdfcc2255 100644 --- a/packages/flutter_goldens/lib/flutter_goldens.dart +++ b/packages/flutter_goldens/lib/flutter_goldens.dart @@ -167,6 +167,12 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator { /// Prepends the golden URL with the library name that encloses the current /// test. Uri _addPrefix(Uri golden) { + // Ensure the Uri ends in .png as the SkiaClient expects + assert( + golden.toString().split('.').last == 'png', + 'Golden files in the Flutter framework must end with the file extension ' + '.png.' + ); final String prefix = basedir.pathSegments[basedir.pathSegments.length - 2]; return Uri.parse('$prefix.$golden'); } diff --git a/packages/flutter_goldens/test/flutter_goldens_test.dart b/packages/flutter_goldens/test/flutter_goldens_test.dart index c5d22cc5f72d3..494f582cfe01f 100644 --- a/packages/flutter_goldens/test/flutter_goldens_test.dart +++ b/packages/flutter_goldens/test/flutter_goldens_test.dart @@ -481,6 +481,26 @@ void main() { ); }); + test('asserts .png format', () async { + await expectLater( + () async { + return comparator.compare( + Uint8List.fromList(_kTestPngBytes), + Uri.parse('flutter.golden_test.1'), + ); + }, + throwsA( + isA().having((AssertionError error) => error.toString(), + 'description', + contains( + 'Golden files in the Flutter framework must end with the file ' + 'extension .png.' + ), + ), + ), + ); + }); + test('calls init during compare', () { expect(fakeSkiaClient.initCalls, 0); comparator.compare( @@ -579,6 +599,26 @@ void main() { ); }); + test('asserts .png format', () async { + await expectLater( + () async { + return comparator.compare( + Uint8List.fromList(_kTestPngBytes), + Uri.parse('flutter.golden_test.1'), + ); + }, + throwsA( + isA().having((AssertionError error) => error.toString(), + 'description', + contains( + 'Golden files in the Flutter framework must end with the file ' + 'extension .png.' + ), + ), + ), + ); + }); + test('calls init during compare', () { expect(fakeSkiaClient.tryInitCalls, 0); comparator.compare( @@ -745,6 +785,26 @@ void main() { fakeSkiaClient.cleanTestNameValues['library.flutter.golden_test.1.png'] = 'flutter.golden_test.1'; }); + test('asserts .png format', () async { + await expectLater( + () async { + return comparator.compare( + Uint8List.fromList(_kTestPngBytes), + Uri.parse('flutter.golden_test.1'), + ); + }, + throwsA( + isA().having((AssertionError error) => error.toString(), + 'description', + contains( + 'Golden files in the Flutter framework must end with the file ' + 'extension .png.' + ), + ), + ), + ); + }); + test('passes when bytes match', () async { expect( await comparator.compare( diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart index 796084f171d66..377641b6e216f 100644 --- a/packages/flutter_tools/lib/src/commands/packages.dart +++ b/packages/flutter_tools/lib/src/commands/packages.dart @@ -27,7 +27,7 @@ class PackagesCommand extends FlutterCommand { addSubcommand(PackagesTestCommand()); addSubcommand(PackagesForwardCommand('publish', 'Publish the current package to pub.dartlang.org', requiresPubspec: true)); addSubcommand(PackagesForwardCommand('downgrade', 'Downgrade packages in a Flutter project', requiresPubspec: true)); - addSubcommand(PackagesForwardCommand('deps', 'Print package dependencies', requiresPubspec: true)); + addSubcommand(PackagesForwardCommand('deps', 'Print package dependencies')); // path to package can be specified with --directory argument addSubcommand(PackagesForwardCommand('run', 'Run an executable from a package', requiresPubspec: true)); addSubcommand(PackagesForwardCommand('cache', 'Work with the Pub system cache')); addSubcommand(PackagesForwardCommand('version', 'Print Pub version')); diff --git a/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart b/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart index e48cac1af3f2d..e4dea3a1f92e1 100644 --- a/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart +++ b/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart @@ -85,30 +85,55 @@ class FlutterDebugAdapter extends DartDebugAdapter attachImpl() async { @@ -214,7 +239,7 @@ class FlutterDebugAdapter extends DartDebugAdapter toolArgs = [ 'run', '--machine', - if (debug) '--start-paused', + if (enableDebugger) '--start-paused', ]; await _startProcess( @@ -258,7 +283,7 @@ class FlutterDebugAdapter extends DartDebugAdapter params) { // When running in noDebug mode, Flutter may still provide us a VM Service // URI, but we will not connect it because we don't want to do any debugging. - if (!debug) { + if (!enableDebugger) { return; } @@ -494,7 +519,7 @@ class FlutterDebugAdapter extends DartDebugAdapter{ 'appId': _appId, 'fullRestart': fullRestart, - 'pause': debug, + 'pause': enableDebugger, 'reason': reason, 'debounce': true, }); diff --git a/packages/flutter_tools/lib/src/ios/ios_deploy.dart b/packages/flutter_tools/lib/src/ios/ios_deploy.dart index 7e6e79fe7f86d..553d8b388b707 100644 --- a/packages/flutter_tools/lib/src/ios/ios_deploy.dart +++ b/packages/flutter_tools/lib/src/ios/ios_deploy.dart @@ -395,11 +395,11 @@ class IOSDeployDebugger { _monitorIOSDeployFailure(line, _logger); _logger.printTrace(line); }); - unawaited(_iosDeployProcess!.exitCode.then((int status) { + unawaited(_iosDeployProcess!.exitCode.then((int status) async { _logger.printTrace('ios-deploy exited with code $exitCode'); _debuggerState = _IOSDeployDebuggerState.detached; - unawaited(stdoutSubscription.cancel()); - unawaited(stderrSubscription.cancel()); + await stdoutSubscription.cancel(); + await stderrSubscription.cancel(); }).whenComplete(() async { if (_debuggerOutput.hasListener) { // Tell listeners the process died. diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart index 8e7a08f62cedb..7c3689e9bcebe 100644 --- a/packages/flutter_tools/lib/src/macos/cocoapods.dart +++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart @@ -69,7 +69,7 @@ enum CocoaPodsStatus { } const Version cocoaPodsMinimumVersion = Version.withText(1, 9, 0, '1.9.0'); -const Version cocoaPodsRecommendedVersion = Version.withText(1, 10, 0, '1.10.0'); +const Version cocoaPodsRecommendedVersion = Version.withText(1, 11, 0, '1.11.0'); /// Cocoapods is a dependency management solution for iOS and macOS applications. /// diff --git a/packages/flutter_tools/lib/src/tracing.dart b/packages/flutter_tools/lib/src/tracing.dart index 8b35765058273..c896a2b901194 100644 --- a/packages/flutter_tools/lib/src/tracing.dart +++ b/packages/flutter_tools/lib/src/tracing.dart @@ -51,7 +51,10 @@ class Tracing { // It is safe to ignore this error because we expect an error to be // thrown if we're already subscribed. } + final StringBuffer bufferedEvents = StringBuffer(); + void Function(String) handleBufferedEvent = bufferedEvents.writeln; vmService.service.onExtensionEvent.listen((vm_service.Event event) { + handleBufferedEvent('${event.extensionKind}: ${event.extensionData}'); if (event.extensionKind == 'Flutter.FirstFrame') { whenFirstFrameRendered.complete(); } @@ -69,7 +72,19 @@ class Tracing { } } if (!done) { + final Timer timer = Timer(const Duration(seconds: 10), () { + _logger.printStatus('First frame is taking longer than expected...'); + _logger.printTrace('Views:'); + for (final FlutterView view in views) { + _logger.printTrace('id: ${view.id} isolate: ${view.uiIsolate?.id}'); + } + _logger.printTrace('Received VM events:'); + _logger.printTrace(bufferedEvents.toString()); + // Swap to just printing new events instead of buffering. + handleBufferedEvent = _logger.printTrace; + }); await whenFirstFrameRendered.future; + timer.cancel(); } // The exception is rethrown, so don't catch only Exceptions. } catch (exception) { // ignore: avoid_catches_without_on_clauses diff --git a/packages/flutter_tools/lib/src/windows/build_windows.dart b/packages/flutter_tools/lib/src/windows/build_windows.dart index 6422d39d726b7..859b97ceb611d 100644 --- a/packages/flutter_tools/lib/src/windows/build_windows.dart +++ b/packages/flutter_tools/lib/src/windows/build_windows.dart @@ -74,6 +74,9 @@ Future buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, { buildDir: buildDirectory, sourceDir: windowsProject.cmakeFile.parent, ); + if (visualStudio.displayVersion == '17.1.0') { + _fixBrokenCmakeGeneration(buildDirectory); + } await _runBuild(cmakePath, buildDirectory, buildModeName); } finally { status.cancel(); @@ -335,3 +338,55 @@ void _writeGeneratedFlutterConfig( } writeGeneratedCmakeConfig(Cache.flutterRoot!, windowsProject, environment); } + +// Works around the Visual Studio 17.1.0 CMake bug described in +// https://github.com/flutter/flutter/issues/97086 +// +// Rather than attempt to remove all the duplicate entries within the +// element, which would require a more complicated parser, this +// just fixes the incorrect duplicates to have the correct `$` value, +// making the duplication harmless. +// +// TODO(stuartmorgan): Remove this workaround either once 17.1.0 is +// sufficiently old that we no longer need to support it, or when +// dropping VS 2022 support. +void _fixBrokenCmakeGeneration(Directory buildDirectory) { + final File assembleProject = buildDirectory + .childDirectory('flutter') + .childFile('flutter_assemble.vcxproj'); + if (assembleProject.existsSync()) { + // E.g.: + final RegExp commandRegex = RegExp( + r' TestFeatureFlags(isWindowsEnabled: true), }); + testUsingContext('Windows build works around CMake generation bug', () async { + final FakeVisualStudio fakeVisualStudio = FakeVisualStudio(displayVersion: '17.1.0'); + final BuildWindowsCommand command = BuildWindowsCommand() + ..visualStudioOverride = fakeVisualStudio; + setUpMockProjectFilesForBuild(); + + processManager = FakeProcessManager.list([ + cmakeGenerationCommand(), + buildCommand('Release'), + ]); + fileSystem.file(fileSystem.path.join('lib', 'other.dart')) + .createSync(recursive: true); + fileSystem.file(fileSystem.path.join('foo', 'bar.sksl.json')) + .createSync(recursive: true); + + // Relevant portions of an incorrectly generated project, with some + // irrelevant details removed for length. + const String fakeBadProjectContent = r''' + + + + + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Debug +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Debug +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Debug +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Profile +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Profile +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Profile +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Release +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Release +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + Generating some files + setlocal +"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64 Release +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd + + + +'''; + final File assembleProject = fileSystem.currentDirectory + .childDirectory('build') + .childDirectory('windows') + .childDirectory('flutter') + .childFile('flutter_assemble.vcxproj'); + assembleProject.createSync(recursive: true); + assembleProject.writeAsStringSync(fakeBadProjectContent); + + await createTestCommandRunner(command).run( + const ['windows', '--no-pub'] + ); + + final List projectLines = assembleProject.readAsLinesSync(); + + const String commandBase = r'"C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" ' + r'-E env FOO=bar C:/src/flutter/packages/flutter_tools/bin/tool_backend.bat windows-x64'; + // The duplicate commands will still be present, but with the order matching + // the condition order (cycling through the configurations), rather than + // three copies of Debug, then three copies of Profile, then three copies + // of Release. + expect(projectLines, containsAllInOrder([ + '$commandBase Debug\r', + '$commandBase Profile\r', + '$commandBase Release\r', + '$commandBase Debug\r', + '$commandBase Profile\r', + '$commandBase Release\r', + '$commandBase Debug\r', + '$commandBase Profile\r', + '$commandBase Release\r', + ])); + }, overrides: { + FileSystem: () => fileSystem, + ProcessManager: () => processManager, + Platform: () => windowsPlatform, + FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true), + }); + testUsingContext('Windows build invokes build and writes generated files', () async { final FakeVisualStudio fakeVisualStudio = FakeVisualStudio(); final BuildWindowsCommand command = BuildWindowsCommand() @@ -604,6 +740,7 @@ class FakeVisualStudio extends Fake implements VisualStudio { FakeVisualStudio({ this.cmakePath = _cmakePath, this.cmakeGenerator = 'Visual Studio 16 2019', + this.displayVersion = '17.0.0' }); @override @@ -611,4 +748,7 @@ class FakeVisualStudio extends Fake implements VisualStudio { @override final String cmakeGenerator; + + @override + final String displayVersion; } diff --git a/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart b/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart new file mode 100644 index 0000000000000..4d1146a42fc9c --- /dev/null +++ b/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart @@ -0,0 +1,158 @@ +// Copyright 2014 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:async'; + +import 'package:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart'; +import 'package:flutter_tools/src/globals.dart' as globals; +import 'package:test/test.dart'; + +import 'mocks.dart'; + +void main() { + group('flutter adapter', () { + final String expectedFlutterExecutable = globals.platform.isWindows + ? r'C:\fake\flutter\bin\flutter.bat' + : '/fake/flutter/bin/flutter'; + + setUpAll(() { + Cache.flutterRoot = globals.platform.isWindows + ? r'C:\fake\flutter' + : '/fake/flutter'; + }); + + group('--start-paused', () { + test('is passed for debug mode', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final Completer responseCompleter = Completer(); + + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.processArgs, contains('--start-paused')); + }); + + test('is not passed for noDebug mode', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final Completer responseCompleter = Completer(); + + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + noDebug: true, + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.processArgs, isNot(contains('--start-paused'))); + }); + + test('is not passed if toolArgs contains --profile', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final Completer responseCompleter = Completer(); + + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + toolArgs: ['--profile'], + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.processArgs, isNot(contains('--start-paused'))); + }); + + test('is not passed if toolArgs contains --release', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final Completer responseCompleter = Completer(); + + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + toolArgs: ['--release'], + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.processArgs, isNot(contains('--start-paused'))); + }); + }); + + test('includes toolArgs', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final Completer responseCompleter = Completer(); + + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + toolArgs: ['tool_arg'], + noDebug: true, + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.executable, equals(expectedFlutterExecutable)); + expect(adapter.processArgs, contains('tool_arg')); + }); + + group('includes customTool', () { + test('with no args replaced', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + customTool: '/custom/flutter', + noDebug: true, + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + final Completer responseCompleter = Completer(); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.executable, equals('/custom/flutter')); + // args should be in-tact + expect(adapter.processArgs, contains('--machine')); + }); + + test('with all args replaced', () async { + final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); + final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( + cwd: '/project', + program: 'foo.dart', + customTool: '/custom/flutter', + customToolReplacesArgs: 9999, // replaces all built-in args + noDebug: true, + toolArgs: ['tool_args'], // should still be in args + ); + + await adapter.configurationDoneRequest(MockRequest(), null, () {}); + final Completer responseCompleter = Completer(); + await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); + await responseCompleter.future; + + expect(adapter.executable, equals('/custom/flutter')); + // normal built-in args are replaced by customToolReplacesArgs, but + // user-provided toolArgs are not. + expect(adapter.processArgs, isNot(contains('--machine'))); + expect(adapter.processArgs, contains('tool_args')); + }); + }); + }); +} diff --git a/packages/flutter_tools/test/src/dap/flutter_test_adapter_test.dart b/packages/flutter_tools/test/general.shard/dap/flutter_test_adapter_test.dart similarity index 90% rename from packages/flutter_tools/test/src/dap/flutter_test_adapter_test.dart rename to packages/flutter_tools/test/general.shard/dap/flutter_test_adapter_test.dart index 3d980444238f6..79064e81ca10e 100644 --- a/packages/flutter_tools/test/src/dap/flutter_test_adapter_test.dart +++ b/packages/flutter_tools/test/general.shard/dap/flutter_test_adapter_test.dart @@ -13,9 +13,15 @@ import 'mocks.dart'; void main() { group('flutter test adapter', () { + final String expectedFlutterExecutable = globals.platform.isWindows + ? r'C:\fake\flutter\bin\flutter.bat' + : '/fake/flutter/bin/flutter'; + setUpAll(() { - Cache.flutterRoot = '/fake/flutter'; - }); + Cache.flutterRoot = globals.platform.isWindows + ? r'C:\fake\flutter' + : '/fake/flutter'; + }); test('includes toolArgs', () async { final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter( @@ -35,7 +41,7 @@ void main() { await adapter.launchRequest(request, args, responseCompleter.complete); await responseCompleter.future; - expect(adapter.executable, equals('/fake/flutter/bin/flutter')); + expect(adapter.executable, equals(expectedFlutterExecutable)); expect(adapter.processArgs, contains('tool_arg')); }); diff --git a/packages/flutter_tools/test/src/dap/mocks.dart b/packages/flutter_tools/test/general.shard/dap/mocks.dart similarity index 92% rename from packages/flutter_tools/test/src/dap/mocks.dart rename to packages/flutter_tools/test/general.shard/dap/mocks.dart index 066e6b31c2d79..b544213e5045a 100644 --- a/packages/flutter_tools/test/src/dap/mocks.dart +++ b/packages/flutter_tools/test/general.shard/dap/mocks.dart @@ -52,6 +52,14 @@ class MockFlutterDebugAdapter extends FlutterDebugAdapter { // launchRequest will complete. appStartedCompleter.complete(); } + + @override + Future get debuggerInitialized { + // If we were mocking debug mode, then simulate the debugger initializing. + return enableDebugger + ? Future.value() + : throw StateError('Invalid attempt to wait for debuggerInitialized when not debugging'); + } } /// A [FlutterTestDebugAdapter] that captures what process/args will be launched. diff --git a/packages/flutter_tools/test/general.shard/ios/ios_deploy_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_deploy_test.dart index e9c9c2c61b5f3..3da7d21b95e6c 100644 --- a/packages/flutter_tools/test/general.shard/ios/ios_deploy_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/ios_deploy_test.dart @@ -75,8 +75,9 @@ void main () { interfaceType: IOSDeviceConnectionInterface.network, ); + expect(iosDeployDebugger.logLines, emits('Did finish launching.')); expect(await iosDeployDebugger.launchAndAttach(), isTrue); - expect(await iosDeployDebugger.logLines.toList(), ['Did finish launching.']); + await iosDeployDebugger.logLines.drain(); expect(processManager, hasNoRemainingExpectations); expect(appDeltaDirectory, exists); }); @@ -92,7 +93,6 @@ void main () { testWithoutContext('debugger attached and stopped', () async { final StreamController> stdin = StreamController>(); - final Stream stdinStream = stdin.stream.transform(const Utf8Decoder()); final FakeProcessManager processManager = FakeProcessManager.list([ FakeCommand( command: const ['ios-deploy'], @@ -108,24 +108,47 @@ void main () { final Stream logLines = iosDeployDebugger.logLines ..listen(receivedLogLines.add); - expect(await iosDeployDebugger.launchAndAttach(), isTrue); - await logLines.toList(); - expect(receivedLogLines, [ + expect(iosDeployDebugger.logLines, emitsInOrder([ 'success', // ignore first "success" from lldb, but log subsequent ones from real logging. 'Log on attach1', 'Log on attach2', '', '', 'Log after process stop' - ]); - expect(logger.traceText, contains('PROCESS_STOPPED')); - expect(logger.traceText, contains('thread backtrace all')); - expect(logger.traceText, contains('* thread #1')); - expect(await stdinStream.take(3).toList(), [ + ])); + expect(stdin.stream.transform(const Utf8Decoder()), emitsInOrder([ 'thread backtrace all', '\n', 'process detach', + ])); + expect(await iosDeployDebugger.launchAndAttach(), isTrue); + await logLines.drain(); + + expect(logger.traceText, contains('PROCESS_STOPPED')); + expect(logger.traceText, contains('thread backtrace all')); + expect(logger.traceText, contains('* thread #1')); + }); + + testWithoutContext('handle processing logging after process exit', () async { + final StreamController> stdin = StreamController>(); + // Make sure we don't hit a race where logging processed after the process exits + // causes listeners to receive logging on the closed logLines stream. + final FakeProcessManager processManager = FakeProcessManager.list([ + FakeCommand( + command: const ['ios-deploy'], + stdout: 'stdout: "(lldb) run\r\nsuccess\r\n', + stdin: IOSink(stdin.sink), + outputFollowsExit: true, + ), ]); + final IOSDeployDebugger iosDeployDebugger = IOSDeployDebugger.test( + processManager: processManager, + logger: logger, + ); + + expect(iosDeployDebugger.logLines, emitsDone); + expect(await iosDeployDebugger.launchAndAttach(), isFalse); + await iosDeployDebugger.logLines.drain(); }); testWithoutContext('app exit', () async { @@ -139,21 +162,17 @@ void main () { processManager: processManager, logger: logger, ); - final List receivedLogLines = []; - final Stream logLines = iosDeployDebugger.logLines - ..listen(receivedLogLines.add); - - expect(await iosDeployDebugger.launchAndAttach(), isTrue); - await logLines.toList(); - expect(receivedLogLines, [ + expect(iosDeployDebugger.logLines, emitsInOrder([ 'Log on attach', 'Log after process exit', - ]); + ])); + + expect(await iosDeployDebugger.launchAndAttach(), isTrue); + await iosDeployDebugger.logLines.drain(); }); testWithoutContext('app crash', () async { final StreamController> stdin = StreamController>(); - final Stream stdinStream = stdin.stream.transform(const Utf8Decoder()); final FakeProcessManager processManager = FakeProcessManager.list([ FakeCommand( command: const ['ios-deploy'], @@ -166,24 +185,24 @@ void main () { processManager: processManager, logger: logger, ); - final List receivedLogLines = []; - final Stream logLines = iosDeployDebugger.logLines - ..listen(receivedLogLines.add); - expect(await iosDeployDebugger.launchAndAttach(), isTrue); - await logLines.toList(); - expect(receivedLogLines, [ + expect(iosDeployDebugger.logLines, emitsInOrder([ 'Log on attach', '* thread #1, stop reason = Assertion failed:', - ]); - expect(logger.traceText, contains('Process 6156 stopped')); - expect(logger.traceText, contains('thread backtrace all')); - expect(logger.traceText, contains('* thread #1')); - expect(await stdinStream.take(3).toList(), [ + ])); + + expect(stdin.stream.transform(const Utf8Decoder()), emitsInOrder([ 'thread backtrace all', '\n', 'process detach', - ]); + ])); + + expect(await iosDeployDebugger.launchAndAttach(), isTrue); + await iosDeployDebugger.logLines.drain(); + + expect(logger.traceText, contains('Process 6156 stopped')); + expect(logger.traceText, contains('thread backtrace all')); + expect(logger.traceText, contains('* thread #1')); }); testWithoutContext('attach failed', () async { @@ -198,15 +217,12 @@ void main () { processManager: processManager, logger: logger, ); - final List receivedLogLines = []; - final Stream logLines = iosDeployDebugger.logLines - ..listen(receivedLogLines.add); - - expect(await iosDeployDebugger.launchAndAttach(), isFalse); - await logLines.toList(); // Debugger lines are double spaced, separated by an extra \r\n. Skip the extra lines. // Still include empty lines other than the extra added newlines. - expect(receivedLogLines, isEmpty); + expect(iosDeployDebugger.logLines, emitsDone); + + expect(await iosDeployDebugger.launchAndAttach(), isFalse); + await iosDeployDebugger.logLines.drain(); }); testWithoutContext('no provisioning profile 1, stdout', () async { @@ -273,7 +289,6 @@ void main () { testWithoutContext('detach', () async { final StreamController> stdin = StreamController>(); - final Stream stdinStream = stdin.stream.transform(const Utf8Decoder()); final FakeProcessManager processManager = FakeProcessManager.list([ FakeCommand( command: const [ @@ -286,9 +301,9 @@ void main () { final IOSDeployDebugger iosDeployDebugger = IOSDeployDebugger.test( processManager: processManager, ); + expect(stdin.stream.transform(const Utf8Decoder()), emits('process detach')); await iosDeployDebugger.launchAndAttach(); iosDeployDebugger.detach(); - expect(await stdinStream.first, 'process detach'); }); testWithoutContext('stop with backtrace', () async { diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart index a27a1cc7a24a6..b49ea1fabccd9 100644 --- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart @@ -165,13 +165,13 @@ void main() { testWithoutContext('detects at recommended version', () async { pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('1.11.0'); expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended); }); testWithoutContext('detects above recommended version', () async { pretendPodIsInstalled(); - pretendPodVersionIs('1.10.1'); + pretendPodVersionIs('1.11.1'); expect(await cocoaPodsUnderTest.evaluateCocoaPodsInstallation, CocoaPodsStatus.recommended); }); }); @@ -410,7 +410,7 @@ void main() { testUsingContext('prints warning if macOS Podfile parses .flutter-plugins', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); fakeProcessManager.addCommands(const [ FakeCommand( command: ['pod', 'install', '--verbose'], @@ -449,7 +449,7 @@ void main() { testUsingContext('throws, if specs repo is outdated.', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile')) ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -499,7 +499,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('ffi $errorName failure on ARM macOS prompts gem install', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile')) ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -542,7 +542,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('ffi failure on x86 macOS does not prompt gem install', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); fileSystem.file(fileSystem.path.join('project', 'ios', 'Podfile')) ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -586,7 +586,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('run pod install, if Podfile.lock is missing', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -613,7 +613,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('runs iOS pod install, if Manifest.lock is missing', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -642,7 +642,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('runs macOS pod install, if Manifest.lock is missing', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.macos.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -671,7 +671,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('runs pod install, if Manifest.lock different from Podspec.lock', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -703,7 +703,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('runs pod install, if flutter framework changed', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -735,7 +735,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('runs pod install, if Podfile.lock is older than Podfile', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); @@ -789,7 +789,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by testUsingContext('a failed pod install deletes Pods/Manifest.lock', () async { final FlutterProject projectUnderTest = setupProjectUnderTest(); pretendPodIsInstalled(); - pretendPodVersionIs('1.10.0'); + pretendPodVersionIs('100.0.0'); projectUnderTest.ios.podfile ..createSync() ..writeAsStringSync('Existing Podfile'); diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_validator_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_validator_test.dart index 1f4262c9a1610..67d8f2d0c2a7f 100644 --- a/packages/flutter_tools/test/general.shard/macos/cocoapods_validator_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_validator_test.dart @@ -40,7 +40,7 @@ void main() { final ValidationMessage message = result.messages.first; expect(message.type, ValidationMessageType.hint); expect(message.message, contains('CocoaPods $currentVersion out of date')); - expect(message.message, contains('(1.10.0 is recommended)')); + expect(message.message, contains('(1.11.0 is recommended)')); }); }); } diff --git a/packages/flutter_tools/test/general.shard/tracing_test.dart b/packages/flutter_tools/test/general.shard/tracing_test.dart index 3d654c4a41972..fb885f8d42a98 100644 --- a/packages/flutter_tools/test/general.shard/tracing_test.dart +++ b/packages/flutter_tools/test/general.shard/tracing_test.dart @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + +import 'package:fake_async/fake_async.dart'; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; import 'package:flutter_tools/src/base/file_system.dart'; @@ -181,6 +184,58 @@ void main() { ), throwsToolExit(message: 'Engine start event is missing in the timeline')); }); + testWithoutContext('prints when first frame is taking a long time', () async { + final BufferLogger logger = BufferLogger.test(); + final FileSystem fileSystem = MemoryFileSystem.test(); + final Completer completer = Completer(); + await FakeAsync().run((FakeAsync time) { + final Map extensionData = { + 'test': 'data', + 'renderedErrorText': 'error text', + }; + final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: [ + const FakeVmServiceRequest( + method: 'streamListen', + args: { + 'streamId': vm_service.EventKind.kExtension, + } + ), + const FakeVmServiceRequest( + method: kListViewsMethod, + jsonResponse: { + 'views': [ + { + 'id': '1', + // No isolate, no views. + 'isolate': null, + } + ], + }, + ), + FakeVmServiceStreamResponse( + streamId: 'Extension', + event: vm_service.Event( + timestamp: 0, + extensionKind: 'Flutter.Error', + extensionData: vm_service.ExtensionData.parse(extensionData), + kind: vm_service.EventStreams.kExtension, + ), + ), + ]); + unawaited(downloadStartupTrace(fakeVmServiceHost.vmService, + output: fileSystem.currentDirectory, + logger: logger, + )); + time.elapse(const Duration(seconds: 11)); + time.flushMicrotasks(); + completer.complete(); + return completer.future; + }); + expect(logger.statusText, contains('First frame is taking longer than expected')); + expect(logger.traceText, contains('id: 1 isolate: null')); + expect(logger.traceText, contains('Flutter.Error: [ExtensionData {test: data, renderedErrorText: error text}]')); + }); + testWithoutContext('throws tool exit if first frame events are missing', () async { final BufferLogger logger = BufferLogger.test(); final FileSystem fileSystem = MemoryFileSystem.test(); diff --git a/packages/flutter_tools/test/src/dap/flutter_adapter_test.dart b/packages/flutter_tools/test/src/dap/flutter_adapter_test.dart deleted file mode 100644 index 042de41e115fb..0000000000000 --- a/packages/flutter_tools/test/src/dap/flutter_adapter_test.dart +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 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:async'; - -import 'package:flutter_tools/src/cache.dart'; -import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart'; -import 'package:flutter_tools/src/globals.dart' as globals; -import 'package:test/test.dart'; - -import 'mocks.dart'; - -void main() { - group('flutter adapter', () { - setUpAll(() { - Cache.flutterRoot = '/fake/flutter'; - }); - - test('includes toolArgs', () async { - final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); - final Completer responseCompleter = Completer(); - - final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( - cwd: '/project', - program: 'foo.dart', - toolArgs: ['tool_arg'], - noDebug: true, - ); - - await adapter.configurationDoneRequest(MockRequest(), null, () {}); - await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); - await responseCompleter.future; - - expect(adapter.executable, equals('/fake/flutter/bin/flutter')); - expect(adapter.processArgs, contains('tool_arg')); - }); - - group('includes customTool', () { - test('with no args replaced', () async { - final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); - final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( - cwd: '/project', - program: 'foo.dart', - customTool: '/custom/flutter', - noDebug: true, - ); - - await adapter.configurationDoneRequest(MockRequest(), null, () {}); - final Completer responseCompleter = Completer(); - await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); - await responseCompleter.future; - - expect(adapter.executable, equals('/custom/flutter')); - // args should be in-tact - expect(adapter.processArgs, contains('--machine')); - }); - - test('with all args replaced', () async { - final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform); - final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments( - cwd: '/project', - program: 'foo.dart', - customTool: '/custom/flutter', - customToolReplacesArgs: 9999, // replaces all built-in args - noDebug: true, - toolArgs: ['tool_args'], // should still be in args - ); - - await adapter.configurationDoneRequest(MockRequest(), null, () {}); - final Completer responseCompleter = Completer(); - await adapter.launchRequest(MockRequest(), args, responseCompleter.complete); - await responseCompleter.future; - - expect(adapter.executable, equals('/custom/flutter')); - // normal built-in args are replaced by customToolReplacesArgs, but - // user-provided toolArgs are not. - expect(adapter.processArgs, isNot(contains('--machine'))); - expect(adapter.processArgs, contains('tool_args')); - }); - }); - }); -} diff --git a/packages/flutter_tools/test/web.shard/vm_service_web_test.dart b/packages/flutter_tools/test/web.shard/vm_service_web_test.dart index e606580536ec5..a0f5bd7a01ddf 100644 --- a/packages/flutter_tools/test/web.shard/vm_service_web_test.dart +++ b/packages/flutter_tools/test/web.shard/vm_service_web_test.dart @@ -62,7 +62,7 @@ void main() { validateFlutterVersion(client1), validateFlutterVersion(client2)] ); - }); + }, skip: true); // https://github.com/flutter/flutter/issues/99003 }); group('Clients of flutter run on web with DDS disabled', () { diff --git a/packages/fuchsia_remote_debug_protocol/pubspec.yaml b/packages/fuchsia_remote_debug_protocol/pubspec.yaml index 21c9eaf6a0e89..a752356de05fb 100644 --- a/packages/fuchsia_remote_debug_protocol/pubspec.yaml +++ b/packages/fuchsia_remote_debug_protocol/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: process: 4.2.4 - vm_service: 8.1.0 + vm_service: 8.2.0 file: 6.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" meta: 1.7.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -65,4 +65,4 @@ dartdoc: # Exclude this package from the hosted API docs. nodoc: true -# PUBSPEC CHECKSUM: 44e4 +# PUBSPEC CHECKSUM: efe5 diff --git a/packages/integration_test/example/pubspec.yaml b/packages/integration_test/example/pubspec.yaml index b4b72e1dca77a..8c54cdb3ed5b7 100644 --- a/packages/integration_test/example/pubspec.yaml +++ b/packages/integration_test/example/pubspec.yaml @@ -76,7 +76,7 @@ dev_dependencies: term_glyph: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_api: 0.4.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" test_core: 0.4.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" - vm_service: 8.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 8.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" watcher: 1.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" web_socket_channel: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" webdriver: 3.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -86,4 +86,4 @@ dev_dependencies: flutter: uses-material-design: true -# PUBSPEC CHECKSUM: 7e63 +# PUBSPEC CHECKSUM: 4a64 diff --git a/packages/integration_test/pubspec.yaml b/packages/integration_test/pubspec.yaml index 7e1465e74f74d..b7863477fda25 100644 --- a/packages/integration_test/pubspec.yaml +++ b/packages/integration_test/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: flutter_test: sdk: flutter path: 1.8.1 - vm_service: 8.1.0 + vm_service: 8.2.0 archive: 3.1.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" async: 2.8.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" @@ -48,4 +48,4 @@ flutter: ios: pluginClass: IntegrationTestPlugin -# PUBSPEC CHECKSUM: d38e +# PUBSPEC CHECKSUM: f88f