Introduce caching mechanism during compile semantics tree monorepo and formatted version (#161195)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->
old pr: https://github.com/flutter/flutter/pull/150394

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
chunhtai 2025-02-05 19:08:23 -08:00 committed by GitHub
parent 243413f11b
commit 1d85de0fc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1421 additions and 974 deletions

View File

@ -38,13 +38,15 @@ class BenchMaterial3Semantics extends WidgetBuildRecorder {
if (showWidget) {
final AggregatedTimings timings = FlutterTimeline.debugCollect();
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
final AggregatedTimedBlock getFragmentBlock = timings.getAggregated('Semantics.GetFragment');
final AggregatedTimedBlock compileChildrenBlock = timings.getAggregated(
'Semantics.compileChildren',
final AggregatedTimedBlock updateChildren = timings.getAggregated('Semantics.updateChildren');
final AggregatedTimedBlock ensureGeometry = timings.getAggregated('Semantics.ensureGeometry');
final AggregatedTimedBlock ensureSemanticsNode = timings.getAggregated(
'Semantics.ensureSemanticsNode',
);
profile!.addTimedBlock(semanticsBlock, reported: true);
profile!.addTimedBlock(getFragmentBlock, reported: true);
profile!.addTimedBlock(compileChildrenBlock, reported: true);
profile!.addTimedBlock(updateChildren, reported: true);
profile!.addTimedBlock(ensureGeometry, reported: true);
profile!.addTimedBlock(ensureSemanticsNode, reported: true);
}
super.frameDidDraw();
@ -90,13 +92,15 @@ class BenchMaterial3ScrollSemantics extends WidgetRecorder {
void frameDidDraw() {
final AggregatedTimings timings = FlutterTimeline.debugCollect();
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
final AggregatedTimedBlock getFragmentBlock = timings.getAggregated('Semantics.GetFragment');
final AggregatedTimedBlock compileChildrenBlock = timings.getAggregated(
'Semantics.compileChildren',
final AggregatedTimedBlock updateChildren = timings.getAggregated('Semantics.updateChildren');
final AggregatedTimedBlock ensureGeometry = timings.getAggregated('Semantics.ensureGeometry');
final AggregatedTimedBlock ensureSemanticsNode = timings.getAggregated(
'Semantics.ensureSemanticsNode',
);
profile!.addTimedBlock(semanticsBlock, reported: true);
profile!.addTimedBlock(getFragmentBlock, reported: true);
profile!.addTimedBlock(compileChildrenBlock, reported: true);
profile!.addTimedBlock(updateChildren, reported: true);
profile!.addTimedBlock(ensureGeometry, reported: true);
profile!.addTimedBlock(ensureSemanticsNode, reported: true);
super.frameDidDraw();
FlutterTimeline.debugReset();

File diff suppressed because it is too large Load Diff

View File

@ -2049,6 +2049,10 @@ class SemanticsNode with DiagnosticableTreeMixin {
/// See also:
///
/// * [elevation], the actual elevation of this [SemanticsNode].
@Deprecated(
'This was a cache for internal calculations and is no longer needed. '
'This feature was deprecated after v3.29.0-0.0.pre.',
)
double? elevationAdjustment;
/// The index of this node within the parent's list of semantic children.
@ -2069,7 +2073,7 @@ class SemanticsNode with DiagnosticableTreeMixin {
/// An invisible node can be safely dropped from the semantic tree without
/// losing semantic information that is relevant for describing the content
/// currently shown on screen.
bool get isInvisible => !isMergedIntoParent && rect.isEmpty;
bool get isInvisible => !isMergedIntoParent && (rect.isEmpty || (transform?.isZero() ?? false));
// MERGING
@ -2077,8 +2081,15 @@ class SemanticsNode with DiagnosticableTreeMixin {
///
/// This value indicates whether this node has any ancestors with
/// [mergeAllDescendantsIntoThisNode] set to true.
bool get isMergedIntoParent => parent != null && _isMergedIntoParent;
bool get isMergedIntoParent => _isMergedIntoParent;
bool _isMergedIntoParent = false;
set isMergedIntoParent(bool value) {
if (_isMergedIntoParent == value) {
return;
}
_isMergedIntoParent = value;
parent?._markDirty();
}
/// Whether the user can interact with this node in assistive technologies.
///
@ -2322,12 +2333,11 @@ class SemanticsNode with DiagnosticableTreeMixin {
assert(child.owner == owner);
final bool childShouldMergeToParent = isPartOfNodeMerging;
if (childShouldMergeToParent == child._isMergedIntoParent) {
if (childShouldMergeToParent == child.isMergedIntoParent) {
return;
}
child._isMergedIntoParent = childShouldMergeToParent;
_markDirty();
child.isMergedIntoParent = childShouldMergeToParent;
if (child.mergeAllDescendantsIntoThisNode) {
// No need to update the descendants since `child` has the merge flag set.
@ -2355,6 +2365,11 @@ class SemanticsNode with DiagnosticableTreeMixin {
child.attach(_owner!);
}
_redepthChild(child);
// In most cases, child should have up to date `isMergedIntoParent` since
// it was set during _RenderObjectSemantics.buildSemantics. However, it is
// still possible that this child was an extra node introduced in
// RenderObject.assembleSemanticsNode. We have to make sure their
// `isMergedIntoParent` is updated correctly.
_updateChildMergeFlagRecursively(child);
}
@ -2612,6 +2627,10 @@ class SemanticsNode with DiagnosticableTreeMixin {
/// * [thickness], which describes how much space in z-direction this
/// [SemanticsNode] occupies starting at this [elevation].
/// * [elevationAdjustment], which has been used to calculate this value.
@Deprecated(
'This was a feature added for 3D rendering, but the feature was deprecated. '
'This feature was deprecated after v3.29.0-0.0.pre.',
)
double get elevation => _elevation;
double _elevation = _kEmptyConfig.elevation;
@ -4890,6 +4909,10 @@ class SemanticsConfiguration {
/// The elevation in z-direction at which the owning [RenderObject] is
/// located relative to its parent.
@Deprecated(
'This was a feature added for 3D rendering, but the feature was deprecated. '
'This feature was deprecated after v3.29.0-0.0.pre.',
)
double get elevation => _elevation;
double _elevation = 0.0;
set elevation(double value) {
@ -5442,7 +5465,7 @@ class SemanticsConfiguration {
_thickness = math.max(_thickness, child._thickness + child._elevation);
_hasBeenAnnotated = _hasBeenAnnotated || child._hasBeenAnnotated;
_hasBeenAnnotated = hasBeenAnnotated || child.hasBeenAnnotated;
}
/// Returns an exact copy of this configuration.
@ -5451,7 +5474,7 @@ class SemanticsConfiguration {
.._isSemanticBoundary = _isSemanticBoundary
..explicitChildNodes = explicitChildNodes
..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
.._hasBeenAnnotated = _hasBeenAnnotated
.._hasBeenAnnotated = hasBeenAnnotated
.._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
.._textDirection = _textDirection
.._sortKey = _sortKey

View File

@ -2292,6 +2292,7 @@ class _OverlayPortalElement extends RenderObjectElement {
assert(renderObject._deferredLayoutChild == child);
slot._removeChild(child as _RenderDeferredLayoutBox);
renderObject._deferredLayoutChild = null;
renderObject.markNeedsSemanticsUpdate();
}
@override

View File

@ -1923,7 +1923,6 @@ void main() {
.simulatedAccessibilityTraversal(startNode: find.semantics.byLabel('prefix1'))
.map((SemanticsNode node) => node.label + node.value)
.toList();
expect(orders, <String>['prefix1', 'abc', 'suffix1', 'prefix2', 'def', 'suffix2']);
});

View File

@ -33,7 +33,7 @@ void main() {
onSemanticsUpdate: (ui.SemanticsUpdate update) {},
);
owner.ensureSemantics();
renderObject.attach(owner);
owner.rootNode = renderObject;
renderObject.layout(
const BoxConstraints.tightForFinite(),
); // semantics are only calculated if layout information is up to date.
@ -56,7 +56,7 @@ void main() {
expect(onSemanticsUpdateCallCount, 0);
final TestRenderObject renderObject = TestRenderObject();
renderObject.attach(owner);
owner.rootNode = renderObject;
renderObject.layout(const BoxConstraints.tightForFinite());
owner.flushSemantics();

View File

@ -202,7 +202,7 @@ void main() {
rect: TestSemantics.fullScreen,
children: <TestSemantics>[
TestSemantics(
id: 4,
id: 2,
label: 'child1',
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],

View File

@ -139,7 +139,7 @@ void main() {
rect: TestSemantics.fullScreen,
children: <TestSemantics>[
TestSemantics(
id: 4,
id: 2,
label: 'child1',
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],

View File

@ -348,6 +348,7 @@ class RenderMarkSemanticsDirtySpy extends RenderProxyBox {
Iterable<SemanticsNode> children,
) {
hasRebuildSemantics = true;
super.assembleSemanticsNode(node, config, children);
}
}

View File

@ -0,0 +1,48 @@
// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('finder does not return dirty semantics nodes', (WidgetTester tester) async {
final UniqueKey key1 = UniqueKey();
final UniqueKey key2 = UniqueKey();
const String label = 'label';
// not merged
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Semantics(
key: key1,
label: label,
container: true,
child: Semantics(
key: key2,
label: label,
container: true,
child: const SizedBox(width: 100, height: 100),
),
),
),
);
expect(find.bySemanticsLabel(label), findsExactly(2));
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
// key2 widget should merge up to key1, its dirty cached semantics node
// should not show up in the finder.
child: Semantics(
key: key1,
container: true,
child: Semantics(key: key2, label: label, child: const SizedBox(width: 100, height: 100)),
),
),
);
expect(find.bySemanticsLabel(label), findsOneWidget);
});
}