Unverified Commit 85b22ff5 authored by chunhtai's avatar chunhtai Committed by GitHub

Fix semantics node id overflow issue (#77287)

parent a01f3724
...@@ -1207,7 +1207,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1207,7 +1207,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
SemanticsNode({ SemanticsNode({
this.key, this.key,
VoidCallback? showOnScreen, VoidCallback? showOnScreen,
}) : id = _generateNewId(), }) : _id = _generateNewId(),
_showOnScreen = showOnScreen; _showOnScreen = showOnScreen;
/// Creates a semantic node to represent the root of the semantics tree. /// Creates a semantic node to represent the root of the semantics tree.
...@@ -1217,7 +1217,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1217,7 +1217,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
this.key, this.key,
VoidCallback? showOnScreen, VoidCallback? showOnScreen,
required SemanticsOwner owner, required SemanticsOwner owner,
}) : id = 0, }) : _id = 0,
_showOnScreen = showOnScreen { _showOnScreen = showOnScreen {
attach(owner); attach(owner);
} }
...@@ -1244,9 +1244,15 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1244,9 +1244,15 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
/// The unique identifier for this node. /// The unique identifier for this node.
/// ///
/// The root node has an id of zero. Other nodes are given a unique id when /// The root node has an id of zero. Other nodes are given a unique id
/// they are created. /// when they are attached to a [SemanticsOwner]. If they are detached, their
final int id; /// ids are invalid and should not be used.
///
/// In rare circumstances, id may change if this node is detached and
/// re-attached to the [SemanticsOwner]. This should only happen when the
/// application has generated too many semantics nodes.
int get id => _id;
int _id;
final VoidCallback? _showOnScreen; final VoidCallback? _showOnScreen;
...@@ -1541,7 +1547,11 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { ...@@ -1541,7 +1547,11 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
@override @override
void attach(SemanticsOwner owner) { void attach(SemanticsOwner owner) {
super.attach(owner); super.attach(owner);
assert(!owner._nodes.containsKey(id)); while (owner._nodes.containsKey(id)) {
// Ids may repeat if the Flutter has generated > 2^16 ids. We need to keep
// regenerating the id until we found an id that is not used.
_id = _generateNewId();
}
owner._nodes[id] = this; owner._nodes[id] = this;
owner._detachedNodes.remove(this); owner._detachedNodes.remove(this);
if (_dirty) { if (_dirty) {
......
...@@ -8,6 +8,8 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -8,6 +8,8 @@ import 'package:flutter_test/flutter_test.dart';
import '../rendering/rendering_tester.dart'; import '../rendering/rendering_tester.dart';
const int kMaxFrameworkAccessibilityIdentifier = (1<<16) - 1;
void main() { void main() {
setUp(() { setUp(() {
debugResetSemanticsIdCounter(); debugResetSemanticsIdCounter();
...@@ -567,6 +569,24 @@ void main() { ...@@ -567,6 +569,24 @@ void main() {
); );
}); });
test('Semantics id does not repeat', () {
final SemanticsOwner owner = SemanticsOwner();
const int expectId = 1400;
SemanticsNode? nodeToRemove;
for (int i = 0; i < kMaxFrameworkAccessibilityIdentifier; i++) {
final SemanticsNode node = SemanticsNode();
node.attach(owner);
if (node.id == expectId) {
nodeToRemove = node;
}
}
nodeToRemove!.detach();
final SemanticsNode newNode = SemanticsNode();
newNode.attach(owner);
// Id is reused.
expect(newNode.id, expectId);
});
test('Tags show up in debug properties', () { test('Tags show up in debug properties', () {
final SemanticsNode actionNode = SemanticsNode() final SemanticsNode actionNode = SemanticsNode()
..tags = <SemanticsTag>{RenderViewport.useTwoPaneSemantics}; ..tags = <SemanticsTag>{RenderViewport.useTwoPaneSemantics};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment