Skip to content

Use grammar UUID to deduplicate text effects instead of ranges.#64209

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
megangardner:eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges
May 7, 2026
Merged

Use grammar UUID to deduplicate text effects instead of ranges.#64209
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
megangardner:eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges

Conversation

@megangardner
Copy link
Copy Markdown
Contributor

@megangardner megangardner commented May 4, 2026

6b1f3f6

Use grammar UUID to deduplicate text effects instead of ranges.
https://bugs.webkit.org/show_bug.cgi?id=314018
rdar://176211949

Reviewed by Aditya Keerthi.

The previous approach in 310132@main tracked applied grammar
text effect ranges to avoid reapplying animations. However,
the grammar checking API provides a UUID (NSGrammarUUID) for
each grammar issue that is stable across re-checks of the same
sentence. Using this UUID is simpler and more reliable than
comparing ranges.

If the UUID is not present, we fall back to always applying
the effect, since we have no way to deduplicate without an
identifier.

Test: editing/spelling/grammar-text-effect-not-reapplied.html

* LayoutTests/TestExpectations:
* LayoutTests/editing/spelling/grammar-text-effect-not-reapplied-expected.txt: Added.
* LayoutTests/editing/spelling/grammar-text-effect-not-reapplied.html: Added.
* Source/WebCore/dom/DocumentMarker.h:
(WebCore::DocumentMarker::description const):
* Source/WebCore/dom/DocumentMarkerController.cpp:
(WebCore::DocumentMarkerController::detach):
(WebCore::DocumentMarkerController::addMarker):
(WebCore::DocumentMarkerController::appliedGrammarTextEffectCount const):
* Source/WebCore/dom/DocumentMarkerController.h:
* Source/WebCore/editing/Editor.cpp:
(WebCore::Editor::advanceToNextMisspelling):
(WebCore::Editor::markAndReplaceFor):
* Source/WebCore/editing/TextCheckingHelper.cpp:
(WebCore::TextCheckingHelper::findUngrammaticalPhrases const):
* Source/WebCore/platform/text/TextChecking.h:
(WebCore::GrammarDetail::isolatedCopy):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::appliedGrammarTextEffectCount const):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Source/WebKit/UIProcess/ios/TextCheckerIOS.mm:
(WebKit::TextChecker::checkTextOfParagraph):
(WebKit::convertExtendedCheckingResults):
* Source/WebKit/UIProcess/mac/TextCheckerMac.mm:
(WebKit::TextChecker::checkTextOfParagraph):
(WebKit::convertExtendedCheckingResults):
* Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm:
(core):
* Tools/TestRunnerShared/cocoa/LayoutTestSpellChecker.mm:
(-[LayoutTestSpellChecker setResultsFromJSValue:inContext:]):

Canonical link: https://commits.webkit.org/312774@main

ee9be1a

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe 🛠 win ⏳ 🛠 ios-apple
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 🧪 win-tests ⏳ 🛠 mac-apple
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 🧪 api-mac ✅ 🧪 api-wpe ⏳ 🛠 vision-apple
🧪 ios-wk2-wpt 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🧪 vision-wk2 🧪 mac-intel-wk2
✅ 🛠 tv ✅ 🛠 mac-safer-cpp
✅ 🛠 tv-sim
✅ 🛠 watch
🛠 watch-sim

@megangardner megangardner self-assigned this May 4, 2026
@megangardner megangardner added the WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore). label May 4, 2026
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 4, 2026
@megangardner megangardner removed the merging-blocked Applied to prevent a change from being merged label May 4, 2026
@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from ec5014f to d1b5223 Compare May 4, 2026 22:28
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 4, 2026
@megangardner megangardner removed the merging-blocked Applied to prevent a change from being merged label May 5, 2026
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 5, 2026
@megangardner megangardner removed the merging-blocked Applied to prevent a change from being merged label May 5, 2026
@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from d1b5223 to 843e0ce Compare May 5, 2026 01:07
@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label May 5, 2026
@megangardner megangardner removed the merging-blocked Applied to prevent a change from being merged label May 6, 2026
@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from 843e0ce to 9595fe0 Compare May 6, 2026 07:15
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be in an #else.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can grammarUUID be part of DocumentMarker::Data? It's too specific to belong at the top level addMarker.

@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from 9595fe0 to 0c1024a Compare May 7, 2026 03:20
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
auto grammarUUID = grammarData ? grammarData->uuid : emptyString();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is only called when the Document is destroyed. Should we be removing UUIDs from this set somewhere else? For example, as words are deleted? Otherwise, the set grows forever.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did the same thing for ranges, this is not different. There's not a good way to figure out when the markers are removed, as we remove all grammar markers and re-apply them after every edit. We could set an arbitrary limit, but I don't know how else to realistically remove stale data from this list.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see... this is already much better then since we would have been leaking DOM nodes 😬

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should think more about it in a follow-up. At a minimum we should probably remove from the set when the grammar marker itself is removed from the list of document markers?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can't do that because we remove all the document markers and then re-add them. So if we remove the UUIDs from the list, we just end up in the same state as we were before this or the previous patch :-/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it possible for isGrammar to be true but for us not to have grammarData?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's technically possible to not have the UUID, but it's unlikely. I'm not sure what you are trying to figure out with your question?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could use std:get rather than std::get_if if DocumentMarkerType::Grammar will always have DocumentMarker::GrammarData. It's unrelated to whether there's a UUID or not, it's about whether that data object (which also contains the description) is always supplied/preserved when creating a grammar marker.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I searched the code for DocumentMarkerType::Grammar, and there are a couple places that don't use DocumentMarker::GrammarData. If that's expected, then fine to keep using std::get_if. But do consider whether those call sites should also be updated.

Copy link
Copy Markdown
Member

@pxlcoder pxlcoder left a comment

Choose a reason for hiding this comment

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

r+ but do consider: #64209 (comment)

@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from 0c1024a to b4cd177 Compare May 7, 2026 04:19
@megangardner megangardner force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from b4cd177 to ee9be1a Compare May 7, 2026 04:22
@megangardner megangardner added safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks merge-queue Applied to send a pull request to merge-queue and removed safe-merge-queue Applied to automatically send a pull-request to merge-queue after passing EWS checks labels May 7, 2026
https://bugs.webkit.org/show_bug.cgi?id=314018
rdar://176211949

Reviewed by Aditya Keerthi.

The previous approach in 310132@main tracked applied grammar
text effect ranges to avoid reapplying animations. However,
the grammar checking API provides a UUID (NSGrammarUUID) for
each grammar issue that is stable across re-checks of the same
sentence. Using this UUID is simpler and more reliable than
comparing ranges.

If the UUID is not present, we fall back to always applying
the effect, since we have no way to deduplicate without an
identifier.

Test: editing/spelling/grammar-text-effect-not-reapplied.html

* LayoutTests/TestExpectations:
* LayoutTests/editing/spelling/grammar-text-effect-not-reapplied-expected.txt: Added.
* LayoutTests/editing/spelling/grammar-text-effect-not-reapplied.html: Added.
* Source/WebCore/dom/DocumentMarker.h:
(WebCore::DocumentMarker::description const):
* Source/WebCore/dom/DocumentMarkerController.cpp:
(WebCore::DocumentMarkerController::detach):
(WebCore::DocumentMarkerController::addMarker):
(WebCore::DocumentMarkerController::appliedGrammarTextEffectCount const):
* Source/WebCore/dom/DocumentMarkerController.h:
* Source/WebCore/editing/Editor.cpp:
(WebCore::Editor::advanceToNextMisspelling):
(WebCore::Editor::markAndReplaceFor):
* Source/WebCore/editing/TextCheckingHelper.cpp:
(WebCore::TextCheckingHelper::findUngrammaticalPhrases const):
* Source/WebCore/platform/text/TextChecking.h:
(WebCore::GrammarDetail::isolatedCopy):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::appliedGrammarTextEffectCount const):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Source/WebKit/UIProcess/ios/TextCheckerIOS.mm:
(WebKit::TextChecker::checkTextOfParagraph):
(WebKit::convertExtendedCheckingResults):
* Source/WebKit/UIProcess/mac/TextCheckerMac.mm:
(WebKit::TextChecker::checkTextOfParagraph):
(WebKit::convertExtendedCheckingResults):
* Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm:
(core):
* Tools/TestRunnerShared/cocoa/LayoutTestSpellChecker.mm:
(-[LayoutTestSpellChecker setResultsFromJSValue:inContext:]):

Canonical link: https://commits.webkit.org/312774@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/Use-grammar-UUID-to-deduplicate-text-effects-instead-of-ranges branch from ee9be1a to 6b1f3f6 Compare May 7, 2026 07:07
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 312774@main (6b1f3f6): https://commits.webkit.org/312774@main

Reviewed commits have been landed. Closing PR #64209 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 6b1f3f6 into WebKit:main May 7, 2026
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WebKit Misc. For miscellaneous bugs in the WebKit framework (and not JavaScriptCore or WebCore).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants