perf: #3615226 Share one DOM parse across HTML-scanning Track plugins
Summary
HtmlLink, CkeditorImage, EntityEmbed, MediaEmbed, and LinkIt each parsed the same field text independently via Html::load(), multiplying DOM-parsing cost per entity revision by up to 5x and compounding a libxml memory leak that is only reclaimed by process termination. This mattered most during full entity_usage regeneration (the batch UI or drush entity-usage:recreate) on sites with a large number of revisions.
This MR adds a small, bounded cache to TextFieldEmbedBase so these plugins share one parsed DOMDocument per distinct field text instead of parsing it separately. Every plugin only reads the DOM via its own DOMXPath query and none of them mutate it, so sharing the parsed document is safe and produces identical tracking results.
Test plan
Verified locally: the cache correctly reuses the same DOMDocument across different plugin instances for identical field text, correctly reparses for different text, and stays bounded at 4 entries under sustained use.
AI-Generated: Yes (Used Claude (Anthropic) to identify the root cause of slow entity_usage regeneration, and to draft and locally test this patch. Findings and code were manually reviewed and verified before submission.)
Closes #3615226