From 613081e07557667bd2562ba23df69ad117112b48 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Fri, 7 Jun 2024 11:50:05 -0400 Subject: [PATCH 1/2] [web] Add 'semantics-identifier' attribute to semantics nodes --- .../lib/src/engine/semantics/semantics.dart | 32 +++++++++ .../test/engine/semantics/semantics_test.dart | 65 +++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/lib/web_ui/lib/src/engine/semantics/semantics.dart b/lib/web_ui/lib/src/engine/semantics/semantics.dart index 0fbd8596e9f00..5a45bbf9dfb3b 100644 --- a/lib/web_ui/lib/src/engine/semantics/semantics.dart +++ b/lib/web_ui/lib/src/engine/semantics/semantics.dart @@ -612,6 +612,18 @@ abstract class PrimaryRoleManager { for (final RoleManager secondaryRole in secondaryRoles) { secondaryRole.update(); } + + if (semanticsObject.isIdentifierDirty) { + _updateIdentifier(); + } + } + + void _updateIdentifier() { + if (semanticsObject.hasIdentifier) { + setAttribute('semantics-identifier', semanticsObject.identifier!); + } else { + removeAttribute('semantics-identifier'); + } } /// Whether this role manager was disposed of. @@ -1119,6 +1131,21 @@ class SemanticsObject { _dirtyFields |= _headingLevelIndex; } + /// See [ui.SemanticsUpdateBuilder.updateNode]. + String? get identifier => _identifier; + String? _identifier; + + bool get hasIdentifier => _identifier != null && _identifier!.isNotEmpty; + + static const int _identifierIndex = 1 << 25; + + /// Whether the [identifier] field has been updated but has not been + /// applied to the DOM yet. + bool get isIdentifierDirty => _isDirty(_identifierIndex); + void _markIdentifierDirty() { + _dirtyFields |= _identifierIndex; + } + /// A unique permanent identifier of the semantics node in the tree. final int id; @@ -1278,6 +1305,11 @@ class SemanticsObject { _markFlagsDirty(); } + if (_identifier != update.identifier) { + _identifier = update.identifier; + _markIdentifierDirty(); + } + if (_value != update.value) { _value = update.value; _markValueDirty(); diff --git a/lib/web_ui/test/engine/semantics/semantics_test.dart b/lib/web_ui/test/engine/semantics/semantics_test.dart index 117ebc55cb60a..2a4e86dd474f9 100644 --- a/lib/web_ui/test/engine/semantics/semantics_test.dart +++ b/lib/web_ui/test/engine/semantics/semantics_test.dart @@ -48,6 +48,9 @@ void runSemanticsTests() { group('longestIncreasingSubsequence', () { _testLongestIncreasingSubsequence(); }); + group(PrimaryRoleManager, () { + _testPrimaryRoleManager(); + }); group('Role managers', () { _testRoleManagerLifecycle(); }); @@ -107,6 +110,68 @@ void runSemanticsTests() { }); } +void _testPrimaryRoleManager() { + test('Sets id and semantics-identifier on the element', () { + semantics() + ..debugOverrideTimestampFunction(() => _testTime) + ..semanticsEnabled = true; + + final SemanticsTester tester = SemanticsTester(owner()); + tester.updateNode( + id: 0, + children: [ + tester.updateNode(id: 372), + tester.updateNode(id: 599), + ], + ); + tester.apply(); + + tester.expectSemantics(''' + + + + + +'''); + + tester.updateNode( + id: 0, + children: [ + tester.updateNode(id: 372, identifier: 'test-id-123'), + tester.updateNode(id: 599), + ], + ); + tester.apply(); + + tester.expectSemantics(''' + + + + + +'''); + + tester.updateNode( + id: 0, + children: [ + tester.updateNode(id: 372), + tester.updateNode(id: 599, identifier: 'test-id-211'), + tester.updateNode(id: 612, identifier: 'test-id-333'), + ], + ); + tester.apply(); + + tester.expectSemantics(''' + + + + + + +'''); + }); +} + void _testRoleManagerLifecycle() { test('Secondary role managers are added upon node initialization', () { semantics() From e535b208154bad6429b873f21efb8f0d5fe25aa5 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Thu, 20 Jun 2024 16:36:38 -0400 Subject: [PATCH 2/2] use the `flt-` prefix --- lib/web_ui/lib/src/engine/semantics/semantics.dart | 4 ++-- lib/web_ui/test/engine/semantics/semantics_test.dart | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/web_ui/lib/src/engine/semantics/semantics.dart b/lib/web_ui/lib/src/engine/semantics/semantics.dart index 5a45bbf9dfb3b..c48851d9836a2 100644 --- a/lib/web_ui/lib/src/engine/semantics/semantics.dart +++ b/lib/web_ui/lib/src/engine/semantics/semantics.dart @@ -620,9 +620,9 @@ abstract class PrimaryRoleManager { void _updateIdentifier() { if (semanticsObject.hasIdentifier) { - setAttribute('semantics-identifier', semanticsObject.identifier!); + setAttribute('flt-semantics-identifier', semanticsObject.identifier!); } else { - removeAttribute('semantics-identifier'); + removeAttribute('flt-semantics-identifier'); } } diff --git a/lib/web_ui/test/engine/semantics/semantics_test.dart b/lib/web_ui/test/engine/semantics/semantics_test.dart index 2a4e86dd474f9..39512a312909e 100644 --- a/lib/web_ui/test/engine/semantics/semantics_test.dart +++ b/lib/web_ui/test/engine/semantics/semantics_test.dart @@ -111,7 +111,7 @@ void runSemanticsTests() { } void _testPrimaryRoleManager() { - test('Sets id and semantics-identifier on the element', () { + test('Sets id and flt-semantics-identifier on the element', () { semantics() ..debugOverrideTimestampFunction(() => _testTime) ..semanticsEnabled = true; @@ -146,7 +146,7 @@ void _testPrimaryRoleManager() { tester.expectSemantics(''' - + '''); @@ -165,8 +165,8 @@ void _testPrimaryRoleManager() { - - + + '''); });