Skip to content

Allow SliverCrossAxisGroup children to lay out with zero cross-axis extent instead of asserting - #191287

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
zemanux:sliver_cross_axis_group
Nov 11, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:masterfrom
zemanux:sliver_cross_axis_group

Conversation

@zemanux

@zemanux zemanux commented Aug 18, 2026

Copy link
Copy Markdown
Member

Fixes #191275

Pre-launch Checklist

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. labels Aug 18, 2026
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from 075157a to 7bff7ae Compare August 25, 2026 17:44
@zemanux
zemanux marked this pull request as ready for review August 25, 2026 17:45
@zemanux
zemanux requested a review from a team as a code owner August 25, 2026 17:45
@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Aug 25, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the allowHeadlessExecution property to the iOS Flutter engine and verifies its propagation from FlutterViewController via key-value coding. Additionally, it updates RenderSliverCrossAxisGroup to allow flexible children to be laid out with zero extent when constrained slivers consume the entire cross-axis extent, removing the previous assertion. Feedback suggests clamping the calculated cross-axis extent to a minimum of 0.0 to prevent negative values from triggering assertion failures in SliverConstraints when constrained children exceed the available extent, and recommends adding a test case to verify this behavior.

@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from 7bff7ae to 0caf96c Compare August 25, 2026 17:53
@github-actions github-actions Bot removed platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Aug 25, 2026
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch 3 times, most recently from 148b65d to b65cb3b Compare August 25, 2026 18:03
@justinmc justinmc added the CICD Run CI/CD label Sep 1, 2026
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from b65cb3b to 4e57cc1 Compare September 2, 2026 19:12
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Sep 2, 2026
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from 4e57cc1 to 1abc216 Compare September 18, 2026 16:06
@Renzo-Olivares
Renzo-Olivares removed the request for review from a team September 24, 2026 18:57
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from 1abc216 to 4820988 Compare October 7, 2026 16:52
@victorsanni
victorsanni self-requested a review October 14, 2026 22:17
@victorsanni victorsanni added the CICD Run CI/CD label Oct 14, 2026

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, approach looks good, left some comments.

if (flex != 0) {
childExtent = extentPerFlexValue * flex;
assert(_assertOutOfExtent(childExtent));
// Flexible children are allowed to be laid out with zero extent without asserting.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the public API docs also reflect this behavior change?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the comment explains the diff, not the code. Better is:

// The constrained children may have consumed all of the available cross
// axis extent, in which case flexible children are laid out with zero
// extent, like Expanded children in a Flex.
assert(extentPerFlexValue >= 0.0 && extentPerFlexValue.isFinite); // and a replacement assert to sanity check

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this PR, _assertOutOfExtent only fires for a constrained child when remainingExtent is exactly 0. A constrained child that is partially squished passes silently, so the hint "make sure the total … does not exceed the cross axis extent" is already inaccurate.

The condition is reachable in legitimate layouts. For example, a SliverCrossAxisGroup with a single SliverConstrainedCrossAxis throws in debug mode whenever its viewport animates/collapses to width 0. RenderFlex never aborts layout for overflow, it reports it during paint.

If we are removing the flex callsite, should we also consider removing the constrained callsite as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I removed the assertion for constrained children too, updated the docs, and added new tests in the latest commit.

testWidgets(
'Expanded slivers are laid out with zero extent when constrained slivers use it all up',
(WidgetTester tester) async {
final errors = <FlutterErrorDetails>[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FlutterError.onError override in the new test is unnecessary and hides failures.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

final FlutterExceptionHandler? oldHandler = FlutterError.onError;
FlutterError.onError = (FlutterErrorDetails error) => errors.add(error);
testWidgets(
'Expanded slivers are laid out with zero extent when constrained slivers use it all up',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: more terse title, like

Flexible slivers get zero extent when constrained slivers use all space

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 16, 2026
@zemanux zemanux added the CICD Run CI/CD label Oct 16, 2026
@zemanux
zemanux requested a review from victorsanni October 16, 2026 20:12

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title is now outdated?

@zemanux zemanux changed the title Fix lay out SliverCrossAxisGroup flexible children with zero extent i… Allow SliverCrossAxisGroup children to lay out with zero cross-axis extent instead of asserting Oct 21, 2026
@zemanux

zemanux commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

The PR title is now outdated?

I updated the title

@zemanux
zemanux requested a review from victorsanni October 21, 2026 15:33
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 21, 2026

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@victorsanni victorsanni added the CICD Run CI/CD label Oct 22, 2026
@victorsanni

Copy link
Copy Markdown
Contributor

There is a failing customer test, rerunning to deflake.

| 00:24 +661: /b/s/w/ir/x/t/flutter_customer_testing.flame.MSJKQV/tests/packages/flame/test/game/game_widget/game_widget_lifecycle_test.dart: Game Widget - Lifecycle all events are executed in the correct order
| ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
| The following TestFailure was thrown running a test:
| Expected: [
|             'onGameResize',
|             'onLoad',
|             'onMount',
|             'update',
|             'render',
|             'update',
|             'render',
|             'update',
|             'onRemove',
|             'onDispose'
|           ]
|   Actual: [
|             'onGameResize',
|             'onLoad',
|             'onMount',
|             'update',
|             'render',
|             'update',
|             'update',
|             'onRemove',
|             'onDispose'
|           ]
|    Which: at location [6] is 'update' instead of 'render'
|
| When the exception was thrown, this was the stack:
| #4      main.<anonymous closure>.<anonymous closure> (file:///b/s/w/ir/x/t/flutter_customer_testing.flame.MSJKQV/tests/packages/flame/test/game/game_widget/game_widget_lifecycle_test.dart:272:7)
| <asynchronous suspension>
| #5      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:192:15)
| <asynchronous suspension>
| #6      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:2062:5)
| <asynchronous suspension>
| <asynchronous suspension>
| (elided one frame from package:stack_trace)
|
| This was caught by the test expectation on the following line:
|   file:///b/s/w/ir/x/t/flutter_customer_testing.flame.MSJKQV/tests/packages/flame/test/game/game_widget/game_widget_lifecycle_test.dart line 272
| The test description was:
|   all events are executed in the correct order
| ════════════════════════════════════════════════════════════════════════════════════════════════════

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 29, 2026
@victorsanni victorsanni added the CICD Run CI/CD label Oct 29, 2026
@zemanux
zemanux force-pushed the sliver_cross_axis_group branch from bbc7b2d to a916934 Compare October 31, 2026 09:34
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 31, 2026
@zemanux zemanux added the CICD Run CI/CD label Oct 31, 2026
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 31, 2026
@zemanux zemanux self-assigned this Oct 31, 2026
@victorsanni victorsanni added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Nov 11, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Nov 11, 2026
Merged via the queue into flutter:master with commit 3b3db93 Nov 11, 2026
25 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 11, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Nov 12, 2026
flutter/flutter@b98afb5...9c427b5

2026-11-12 [email protected] Roll Skia from d67d0f22e3ec to 9aa2513a4ac9 (2 revisions) (flutter/flutter#196429)
2026-11-12 [email protected] [flutter_tools] Move CpuArch to flutter_tools_core and define HostPlatform by osName and cpuArch (flutter/flutter#195841)
2026-11-12 [email protected] Roll Skia from 23e7e63789b8 to d67d0f22e3ec (2 revisions) (flutter/flutter#196424)
2026-11-12 [email protected] Uber compactify (flutter/flutter#196392)
2026-11-12 [email protected] Roll Skia from 3d7e335da165 to 23e7e63789b8 (12 revisions) (flutter/flutter#196422)
2026-11-12 [email protected] Roll Dart SDK from 13af329ea4f2 to e5add7a25b32 (1 revision) (flutter/flutter#196413)
2026-11-12 [email protected] Don't terminate the shared EGL display when an engine is disposed (flutter/flutter#194520)
2026-11-11 [email protected] Adds manifest flag to turn on SDFs for Android. (flutter/flutter#196056)
2026-11-11 [email protected] Remove bringup from Linux_pixel_7pro integration_ui_keyboard_inset_jump (flutter/flutter#196334)
2026-11-11 [email protected] Uses system default locale for text rendering when preferred locale isn't supported (flutter/flutter#195997)
2026-11-11 [email protected] [android]: prewarms shaders when the context is created (flutter/flutter#196069)
2026-11-11 [email protected] iOS: Recomposite platform views only if their parameters change (flutter/flutter#196287)
2026-11-11 [email protected] [flutter_tools] Forward encoding in ErrorHandlingFile.readAsStringSync (flutter/flutter#196136)
2026-11-11 [email protected] Roll Skia from b89c24bbab8c to 3d7e335da165 (8 revisions) (flutter/flutter#196390)
2026-11-11 [email protected] Add Flutter Gardener instructions on how to disable a test (flutter/flutter#196312)
2026-11-11 [email protected] [Impeller] Enable malioc analysis for framebuffer_blend shaders (flutter/flutter#196343)
2026-11-11 [email protected] [flutter_tools] Migrate general.shard Android, asset, and build tests off globals (flutter/flutter#196125)
2026-11-11 [email protected] Roll Dart SDK from 8f15c4ca2d41 to 13af329ea4f2 (1 revision) (flutter/flutter#196386)
2026-11-11 [email protected] [Impeller] Do not clamp the local coverage limit to the root render target (flutter/flutter#195860)
2026-11-11 [email protected] [Impeller] Use separate uniform buffers on VMware SVGA3D (flutter/flutter#196022)
2026-11-11 [email protected] [flutter_tools] Introduce AndroidSdkProvider for lazy native_assets SDK lookup (flutter/flutter#196122)
2026-11-11 [email protected] Moves linux to ThinLTO. (flutter/flutter#196314)
2026-11-11 [email protected] [flutter_tools] Migrate bin/fuchsia_tester.dart off globals and runInContext (flutter/flutter#196074)
2026-11-11 [email protected] Changes the tolerances for frame_rate_main_test.dart. (flutter/flutter#196304)
2026-11-11 [email protected] Roll Packages from 08faf64 to 653628e (16 revisions) (flutter/flutter#196381)
2026-11-11 [email protected] Allow SliverCrossAxisGroup children to lay out with zero cross-axis extent instead of asserting (flutter/flutter#191287)
2026-11-11 [email protected] Roll Skia from cc4c54f752ba to b89c24bbab8c (4 revisions) (flutter/flutter#196375)
2026-11-11 [email protected] [Linux] Fix layer offset when compositing with glBlitFramebuffer (flutter/flutter#196189)
2026-11-11 [email protected] [flutter_tools] Inject CrashReportSender into SwiftPM migration (flutter/flutter#196315)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SliverCrossAxisGroup throws _assertOutOfExtent when available cross-axis extent is fully consumed by inflexible children (SliverConstrainedCrossAxis)

3 participants