Patch removeNode / insertBefore to fix React crash with Google translate
Hopefully all the info for this is in the comment. Fixes https://github.com/vector-im/riot-web/issues/13557
This commit is contained in:
parent
d44808e0e6
commit
a35d566551
1 changed files with 44 additions and 0 deletions
|
@ -78,6 +78,48 @@ function checkBrowserFeatures() {
|
||||||
return featureComplete;
|
return featureComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monkey patch some browser methods to work around a fundamental
|
||||||
|
* incompatability between React and any browser extension or anything
|
||||||
|
* else that manipulates the DOM.
|
||||||
|
*
|
||||||
|
* React issue: https://github.com/facebook/react/issues/11538
|
||||||
|
* Chromium issue: https://bugs.chromium.org/p/chromium/issues/detail?id=872770
|
||||||
|
*
|
||||||
|
* The workaround here is inspired by the one in a comment on the Readt bug
|
||||||
|
* (https://github.com/facebook/react/issues/11538#issuecomment-417504600)
|
||||||
|
* except that we catch the exception rather than sanity checking every call,
|
||||||
|
* and we remove the child from whatever its parent actually is rather than
|
||||||
|
* doing nothing (the workaround in the comment leaves the element in the DOM,
|
||||||
|
* which in the case of https://github.com/vector-im/riot-web/issues/13557
|
||||||
|
* makes it fail by adding another submit button to the page every time you
|
||||||
|
* try to log in, which is also a fairly terrible failure mode).
|
||||||
|
*/
|
||||||
|
function monkeyPatchForReact() {
|
||||||
|
const originalRemoveChild = Node.prototype.removeChild;
|
||||||
|
Node.prototype.removeChild = function(...args) {
|
||||||
|
try {
|
||||||
|
return originalRemoveChild.apply(this, args);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Caught exception from removeChild", e);
|
||||||
|
return originalRemoveChild.apply(args[0].parentNode, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalInsertBefore = Node.prototype.insertBefore;
|
||||||
|
Node.prototype.insertBefore = function(...args) {
|
||||||
|
try {
|
||||||
|
return originalInsertBefore.apply(this, args);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Caught exception from insertBefore", e);
|
||||||
|
// We could use appendChild instead, then the node would
|
||||||
|
// be in the DOM but not necessarily in the right place?
|
||||||
|
// For now, do nothing.
|
||||||
|
return args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const supportedBrowser = checkBrowserFeatures();
|
const supportedBrowser = checkBrowserFeatures();
|
||||||
|
|
||||||
// React depends on Map & Set which we check for using modernizr's es6collections
|
// React depends on Map & Set which we check for using modernizr's es6collections
|
||||||
|
@ -190,6 +232,8 @@ async function start() {
|
||||||
await loadThemePromise;
|
await loadThemePromise;
|
||||||
await loadLanguagePromise;
|
await loadLanguagePromise;
|
||||||
|
|
||||||
|
monkeyPatchForReact();
|
||||||
|
|
||||||
// Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to
|
// Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to
|
||||||
// run on the components.
|
// run on the components.
|
||||||
await loadApp(fragparts.params);
|
await loadApp(fragparts.params);
|
||||||
|
|
Loading…
Add table
Reference in a new issue