mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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:
parent
243413f11b
commit
1d85de0fc8
@ -38,13 +38,15 @@ class BenchMaterial3Semantics extends WidgetBuildRecorder {
|
|||||||
if (showWidget) {
|
if (showWidget) {
|
||||||
final AggregatedTimings timings = FlutterTimeline.debugCollect();
|
final AggregatedTimings timings = FlutterTimeline.debugCollect();
|
||||||
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
|
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
|
||||||
final AggregatedTimedBlock getFragmentBlock = timings.getAggregated('Semantics.GetFragment');
|
final AggregatedTimedBlock updateChildren = timings.getAggregated('Semantics.updateChildren');
|
||||||
final AggregatedTimedBlock compileChildrenBlock = timings.getAggregated(
|
final AggregatedTimedBlock ensureGeometry = timings.getAggregated('Semantics.ensureGeometry');
|
||||||
'Semantics.compileChildren',
|
final AggregatedTimedBlock ensureSemanticsNode = timings.getAggregated(
|
||||||
|
'Semantics.ensureSemanticsNode',
|
||||||
);
|
);
|
||||||
profile!.addTimedBlock(semanticsBlock, reported: true);
|
profile!.addTimedBlock(semanticsBlock, reported: true);
|
||||||
profile!.addTimedBlock(getFragmentBlock, reported: true);
|
profile!.addTimedBlock(updateChildren, reported: true);
|
||||||
profile!.addTimedBlock(compileChildrenBlock, reported: true);
|
profile!.addTimedBlock(ensureGeometry, reported: true);
|
||||||
|
profile!.addTimedBlock(ensureSemanticsNode, reported: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.frameDidDraw();
|
super.frameDidDraw();
|
||||||
@ -90,13 +92,15 @@ class BenchMaterial3ScrollSemantics extends WidgetRecorder {
|
|||||||
void frameDidDraw() {
|
void frameDidDraw() {
|
||||||
final AggregatedTimings timings = FlutterTimeline.debugCollect();
|
final AggregatedTimings timings = FlutterTimeline.debugCollect();
|
||||||
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
|
final AggregatedTimedBlock semanticsBlock = timings.getAggregated('SEMANTICS');
|
||||||
final AggregatedTimedBlock getFragmentBlock = timings.getAggregated('Semantics.GetFragment');
|
final AggregatedTimedBlock updateChildren = timings.getAggregated('Semantics.updateChildren');
|
||||||
final AggregatedTimedBlock compileChildrenBlock = timings.getAggregated(
|
final AggregatedTimedBlock ensureGeometry = timings.getAggregated('Semantics.ensureGeometry');
|
||||||
'Semantics.compileChildren',
|
final AggregatedTimedBlock ensureSemanticsNode = timings.getAggregated(
|
||||||
|
'Semantics.ensureSemanticsNode',
|
||||||
);
|
);
|
||||||
profile!.addTimedBlock(semanticsBlock, reported: true);
|
profile!.addTimedBlock(semanticsBlock, reported: true);
|
||||||
profile!.addTimedBlock(getFragmentBlock, reported: true);
|
profile!.addTimedBlock(updateChildren, reported: true);
|
||||||
profile!.addTimedBlock(compileChildrenBlock, reported: true);
|
profile!.addTimedBlock(ensureGeometry, reported: true);
|
||||||
|
profile!.addTimedBlock(ensureSemanticsNode, reported: true);
|
||||||
|
|
||||||
super.frameDidDraw();
|
super.frameDidDraw();
|
||||||
FlutterTimeline.debugReset();
|
FlutterTimeline.debugReset();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2049,6 +2049,10 @@ class SemanticsNode with DiagnosticableTreeMixin {
|
|||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [elevation], the actual elevation of this [SemanticsNode].
|
/// * [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;
|
double? elevationAdjustment;
|
||||||
|
|
||||||
/// The index of this node within the parent's list of semantic children.
|
/// 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
|
/// An invisible node can be safely dropped from the semantic tree without
|
||||||
/// losing semantic information that is relevant for describing the content
|
/// losing semantic information that is relevant for describing the content
|
||||||
/// currently shown on screen.
|
/// currently shown on screen.
|
||||||
bool get isInvisible => !isMergedIntoParent && rect.isEmpty;
|
bool get isInvisible => !isMergedIntoParent && (rect.isEmpty || (transform?.isZero() ?? false));
|
||||||
|
|
||||||
// MERGING
|
// MERGING
|
||||||
|
|
||||||
@ -2077,8 +2081,15 @@ class SemanticsNode with DiagnosticableTreeMixin {
|
|||||||
///
|
///
|
||||||
/// This value indicates whether this node has any ancestors with
|
/// This value indicates whether this node has any ancestors with
|
||||||
/// [mergeAllDescendantsIntoThisNode] set to true.
|
/// [mergeAllDescendantsIntoThisNode] set to true.
|
||||||
bool get isMergedIntoParent => parent != null && _isMergedIntoParent;
|
bool get isMergedIntoParent => _isMergedIntoParent;
|
||||||
bool _isMergedIntoParent = false;
|
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.
|
/// Whether the user can interact with this node in assistive technologies.
|
||||||
///
|
///
|
||||||
@ -2322,12 +2333,11 @@ class SemanticsNode with DiagnosticableTreeMixin {
|
|||||||
assert(child.owner == owner);
|
assert(child.owner == owner);
|
||||||
final bool childShouldMergeToParent = isPartOfNodeMerging;
|
final bool childShouldMergeToParent = isPartOfNodeMerging;
|
||||||
|
|
||||||
if (childShouldMergeToParent == child._isMergedIntoParent) {
|
if (childShouldMergeToParent == child.isMergedIntoParent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
child._isMergedIntoParent = childShouldMergeToParent;
|
child.isMergedIntoParent = childShouldMergeToParent;
|
||||||
_markDirty();
|
|
||||||
|
|
||||||
if (child.mergeAllDescendantsIntoThisNode) {
|
if (child.mergeAllDescendantsIntoThisNode) {
|
||||||
// No need to update the descendants since `child` has the merge flag set.
|
// No need to update the descendants since `child` has the merge flag set.
|
||||||
@ -2355,6 +2365,11 @@ class SemanticsNode with DiagnosticableTreeMixin {
|
|||||||
child.attach(_owner!);
|
child.attach(_owner!);
|
||||||
}
|
}
|
||||||
_redepthChild(child);
|
_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);
|
_updateChildMergeFlagRecursively(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2612,6 +2627,10 @@ class SemanticsNode with DiagnosticableTreeMixin {
|
|||||||
/// * [thickness], which describes how much space in z-direction this
|
/// * [thickness], which describes how much space in z-direction this
|
||||||
/// [SemanticsNode] occupies starting at this [elevation].
|
/// [SemanticsNode] occupies starting at this [elevation].
|
||||||
/// * [elevationAdjustment], which has been used to calculate this value.
|
/// * [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 get elevation => _elevation;
|
||||||
double _elevation = _kEmptyConfig.elevation;
|
double _elevation = _kEmptyConfig.elevation;
|
||||||
|
|
||||||
@ -4890,6 +4909,10 @@ class SemanticsConfiguration {
|
|||||||
|
|
||||||
/// The elevation in z-direction at which the owning [RenderObject] is
|
/// The elevation in z-direction at which the owning [RenderObject] is
|
||||||
/// located relative to its parent.
|
/// 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 get elevation => _elevation;
|
||||||
double _elevation = 0.0;
|
double _elevation = 0.0;
|
||||||
set elevation(double value) {
|
set elevation(double value) {
|
||||||
@ -5442,7 +5465,7 @@ class SemanticsConfiguration {
|
|||||||
|
|
||||||
_thickness = math.max(_thickness, child._thickness + child._elevation);
|
_thickness = math.max(_thickness, child._thickness + child._elevation);
|
||||||
|
|
||||||
_hasBeenAnnotated = _hasBeenAnnotated || child._hasBeenAnnotated;
|
_hasBeenAnnotated = hasBeenAnnotated || child.hasBeenAnnotated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an exact copy of this configuration.
|
/// Returns an exact copy of this configuration.
|
||||||
@ -5451,7 +5474,7 @@ class SemanticsConfiguration {
|
|||||||
.._isSemanticBoundary = _isSemanticBoundary
|
.._isSemanticBoundary = _isSemanticBoundary
|
||||||
..explicitChildNodes = explicitChildNodes
|
..explicitChildNodes = explicitChildNodes
|
||||||
..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
|
..isBlockingSemanticsOfPreviouslyPaintedNodes = isBlockingSemanticsOfPreviouslyPaintedNodes
|
||||||
.._hasBeenAnnotated = _hasBeenAnnotated
|
.._hasBeenAnnotated = hasBeenAnnotated
|
||||||
.._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
|
.._isMergingSemanticsOfDescendants = _isMergingSemanticsOfDescendants
|
||||||
.._textDirection = _textDirection
|
.._textDirection = _textDirection
|
||||||
.._sortKey = _sortKey
|
.._sortKey = _sortKey
|
||||||
|
@ -2292,6 +2292,7 @@ class _OverlayPortalElement extends RenderObjectElement {
|
|||||||
assert(renderObject._deferredLayoutChild == child);
|
assert(renderObject._deferredLayoutChild == child);
|
||||||
slot._removeChild(child as _RenderDeferredLayoutBox);
|
slot._removeChild(child as _RenderDeferredLayoutBox);
|
||||||
renderObject._deferredLayoutChild = null;
|
renderObject._deferredLayoutChild = null;
|
||||||
|
renderObject.markNeedsSemanticsUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1923,7 +1923,6 @@ void main() {
|
|||||||
.simulatedAccessibilityTraversal(startNode: find.semantics.byLabel('prefix1'))
|
.simulatedAccessibilityTraversal(startNode: find.semantics.byLabel('prefix1'))
|
||||||
.map((SemanticsNode node) => node.label + node.value)
|
.map((SemanticsNode node) => node.label + node.value)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
expect(orders, <String>['prefix1', 'abc', 'suffix1', 'prefix2', 'def', 'suffix2']);
|
expect(orders, <String>['prefix1', 'abc', 'suffix1', 'prefix2', 'def', 'suffix2']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ void main() {
|
|||||||
onSemanticsUpdate: (ui.SemanticsUpdate update) {},
|
onSemanticsUpdate: (ui.SemanticsUpdate update) {},
|
||||||
);
|
);
|
||||||
owner.ensureSemantics();
|
owner.ensureSemantics();
|
||||||
renderObject.attach(owner);
|
owner.rootNode = renderObject;
|
||||||
renderObject.layout(
|
renderObject.layout(
|
||||||
const BoxConstraints.tightForFinite(),
|
const BoxConstraints.tightForFinite(),
|
||||||
); // semantics are only calculated if layout information is up to date.
|
); // semantics are only calculated if layout information is up to date.
|
||||||
@ -56,7 +56,7 @@ void main() {
|
|||||||
expect(onSemanticsUpdateCallCount, 0);
|
expect(onSemanticsUpdateCallCount, 0);
|
||||||
|
|
||||||
final TestRenderObject renderObject = TestRenderObject();
|
final TestRenderObject renderObject = TestRenderObject();
|
||||||
renderObject.attach(owner);
|
owner.rootNode = renderObject;
|
||||||
renderObject.layout(const BoxConstraints.tightForFinite());
|
renderObject.layout(const BoxConstraints.tightForFinite());
|
||||||
owner.flushSemantics();
|
owner.flushSemantics();
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ void main() {
|
|||||||
rect: TestSemantics.fullScreen,
|
rect: TestSemantics.fullScreen,
|
||||||
children: <TestSemantics>[
|
children: <TestSemantics>[
|
||||||
TestSemantics(
|
TestSemantics(
|
||||||
id: 4,
|
id: 2,
|
||||||
label: 'child1',
|
label: 'child1',
|
||||||
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
||||||
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],
|
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],
|
||||||
|
@ -139,7 +139,7 @@ void main() {
|
|||||||
rect: TestSemantics.fullScreen,
|
rect: TestSemantics.fullScreen,
|
||||||
children: <TestSemantics>[
|
children: <TestSemantics>[
|
||||||
TestSemantics(
|
TestSemantics(
|
||||||
id: 4,
|
id: 2,
|
||||||
label: 'child1',
|
label: 'child1',
|
||||||
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 10.0),
|
||||||
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],
|
flags: <SemanticsFlag>[SemanticsFlag.hasSelectedState, SemanticsFlag.isSelected],
|
||||||
|
@ -348,6 +348,7 @@ class RenderMarkSemanticsDirtySpy extends RenderProxyBox {
|
|||||||
Iterable<SemanticsNode> children,
|
Iterable<SemanticsNode> children,
|
||||||
) {
|
) {
|
||||||
hasRebuildSemantics = true;
|
hasRebuildSemantics = true;
|
||||||
|
super.assembleSemanticsNode(node, config, children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user