From 5204f83ce2ff3785df154656d77ea688017b61d3 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 21 Sep 2023 11:17:16 -0400 Subject: [PATCH] [LiveComponent] Workaround for bad behavior with Chrome's translation feature --- .../Rendering/ExternalMutationTracker.d.ts | 1 + .../assets/dist/live_controller.js | 9 +++++++++ .../src/Rendering/ExternalMutationTracker.ts | 20 +++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/src/LiveComponent/assets/dist/Rendering/ExternalMutationTracker.d.ts b/src/LiveComponent/assets/dist/Rendering/ExternalMutationTracker.d.ts index 44b82db2ef1..0d76f2c22eb 100644 --- a/src/LiveComponent/assets/dist/Rendering/ExternalMutationTracker.d.ts +++ b/src/LiveComponent/assets/dist/Rendering/ExternalMutationTracker.d.ts @@ -22,4 +22,5 @@ export default class { private handleStyleAttributeMutation; private handleGenericAttributeMutation; private extractStyles; + private isElementAddedByTranslation; } diff --git a/src/LiveComponent/assets/dist/live_controller.js b/src/LiveComponent/assets/dist/live_controller.js index 85fe146a88a..ad8b2d40acf 100644 --- a/src/LiveComponent/assets/dist/live_controller.js +++ b/src/LiveComponent/assets/dist/live_controller.js @@ -1565,6 +1565,9 @@ class ExternalMutationTracker { if (!this.shouldTrackChangeCallback(element)) { continue; } + if (this.isElementAddedByTranslation(element)) { + continue; + } let isChangeInAddedElement = false; for (const addedElement of this.addedElements) { if (addedElement.contains(element)) { @@ -1603,6 +1606,9 @@ class ExternalMutationTracker { this.removedElements.splice(this.removedElements.indexOf(node), 1); return; } + if (this.isElementAddedByTranslation(node)) { + return; + } this.addedElements.push(node); }); mutation.removedNodes.forEach((node) => { @@ -1711,6 +1717,9 @@ class ExternalMutationTracker { }); return styleObject; } + isElementAddedByTranslation(element) { + return element.tagName === 'FONT' && element.getAttribute('style') === 'vertical-align: inherit;'; + } } class ChildComponentWrapper { diff --git a/src/LiveComponent/assets/src/Rendering/ExternalMutationTracker.ts b/src/LiveComponent/assets/src/Rendering/ExternalMutationTracker.ts index 332ed74d908..34c09ce8c7a 100644 --- a/src/LiveComponent/assets/src/Rendering/ExternalMutationTracker.ts +++ b/src/LiveComponent/assets/src/Rendering/ExternalMutationTracker.ts @@ -75,6 +75,10 @@ export default class { continue; } + if (this.isElementAddedByTranslation(element)) { + continue; + } + // ignore changes in elements that were externally-added let isChangeInAddedElement = false; for (const addedElement of this.addedElements) { @@ -133,6 +137,10 @@ export default class { return; } + if (this.isElementAddedByTranslation(node)) { + return; + } + this.addedElements.push(node); }); @@ -293,4 +301,16 @@ export default class { return styleObject; } + + /** + * Helps avoid tracking changes by Chrome's translation feature. + * + * When Chrome translates, it mutates the dom in a way that triggers MutationObserver. + * This includes adding new elements wrapped in a tag. This causes live + * components to incorrectly think that these new elements should persist through + * re-renders, causing duplicate text. + */ + private isElementAddedByTranslation(element: Element): boolean { + return element.tagName === 'FONT' && element.getAttribute('style') === 'vertical-align: inherit;' + } }