Diff
Modified: branches/safari-609-branch/LayoutTests/ChangeLog (255014 => 255015)
--- branches/safari-609-branch/LayoutTests/ChangeLog 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/LayoutTests/ChangeLog 2020-01-23 21:43:50 UTC (rev 255015)
@@ -1,5 +1,70 @@
2020-01-23 Russell Epstein <[email protected]>
+ Cherry-pick r254652. rdar://problem/58811422
+
+ Regression(r253213) Load hang and high CPU usage when trying to load myuhc.com
+ https://bugs.webkit.org/show_bug.cgi?id=206315
+ <rdar://problem/58139842>
+
+ Reviewed by Geoffrey Garen.
+
+ Source/WebCore:
+
+ Starting in r253213, we now throw when trying to do a sync XHR during unload. Unfortunately, this is confusing the script
+ on myuhc.com and it ends up retrying the sync XHR in a tight loop. To address the issue, I am putting in a safety net which
+ ignores calls to XMLHttpRequest.send() instead of throwing, once we've reached 5 sync XHR failures during unload.
+
+ Throwing is useful because this gives a change for Web authors to fall back to using Beacon API or Fetch KeepAlive if the
+ sync XHR fails. There is already code out there doing just that. You could imagine content doing more than one sync XHR
+ during unload, each one with a good beacon API fallback. For this reason, I put in a limit of 5 sync failures before
+ we stop throwing. Having a limit is important to break bad loops when the content simply retries the same sync XHR load
+ when the sync XHR send() call throws.
+
+ Tests: fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html
+ fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::didRejectSyncXHRDuringPageDismissal):
+ (WebCore::Document::shouldIgnoreSyncXHRs const):
+ * dom/Document.h:
+ * loader/DocumentThreadableLoader.cpp:
+ (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::prepareToSend):
+
+ LayoutTests:
+
+ Add layout test coverage.
+
+ * fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@254652 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2020-01-15 Chris Dumez <[email protected]>
+
+ Regression(r253213) Load hang and high CPU usage when trying to load myuhc.com
+ https://bugs.webkit.org/show_bug.cgi?id=206315
+ <rdar://problem/58139842>
+
+ Reviewed by Geoffrey Garen.
+
+ Add layout test coverage.
+
+ * fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html: Added.
+
+2020-01-23 Russell Epstein <[email protected]>
+
Cherry-pick r254541. rdar://problem/58605951
Supported mime types for encoding should be supported mime types for loading
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,22 @@
+<script>
+let xhrExceptionCount = 0;
+
+function doSyncXHR(i)
+{
+ try {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "xmlhttprequest-responsetype-json.json?" + i, false);
+ xhr.send(null);
+ } catch(e) {
+ xhrExceptionCount++;
+ return false;
+ }
+ return true;
+}
+
+_onunload_ = () => {
+ for (let i = 0; i < 5; i++)
+ doSyncXHR(i);
+ top.frameDidUnload(xhrExceptionCount);
+}
+</script>
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,18 @@
+<script>
+function doSyncXHR()
+{
+ try {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "xmlhttprequest-responsetype-json.json", false);
+ xhr.send(null);
+ } catch(e) {
+ return false;
+ }
+ return true;
+}
+
+_onunload_ = () => {
+ while (!doSyncXHR()) { };
+ top.frameDidUnload();
+}
+</script>
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,16 @@
+frame "<!--frame1-->" - has 1 onunload handler(s)
+CONSOLE MESSAGE: line 9: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json?0.
+CONSOLE MESSAGE: line 9: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json?1.
+CONSOLE MESSAGE: line 9: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json?2.
+CONSOLE MESSAGE: line 9: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json?3.
+CONSOLE MESSAGE: line 9: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json?4.
+Makes sure that we throw when doing sync XHRs during unload.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS xhrExceptionCount is 5
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<iframe id="testFrame" src=""
+<script>
+description("Makes sure that we throw when doing sync XHRs during unload.");
+jsTestIsAsync = true;
+
+frameDidUnload = (_xhrExceptionCount) => {
+ xhrExceptionCount = _xhrExceptionCount;
+ shouldBe("xhrExceptionCount", "5");
+ finishJSTest();
+}
+
+_onload_ = () => {
+ testFrame.remove();
+}
+</script>
+</html>
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,18 @@
+frame "<!--frame1-->" - has 1 onunload handler(s)
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: XMLHttpRequest cannot load xmlhttprequest-responsetype-json.json.
+CONSOLE MESSAGE: line 7: Ignoring XMLHttpRequest.send() call for 'xmlhttprequest-responsetype-json.json' because the maximum number of synchronous failures was reached.
+Makes sure that retrying failed sync XHRs in a loop during unload does not cause a hang.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS No hang while unloading the iframe
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html (0 => 255015)
--- branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html (rev 0)
+++ branches/safari-609-branch/LayoutTests/fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html 2020-01-23 21:43:50 UTC (rev 255015)
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<iframe id="testFrame" src=""
+<script>
+description("Makes sure that retrying failed sync XHRs in a loop during unload does not cause a hang.");
+jsTestIsAsync = true;
+
+frameDidUnload = () => {
+ testPassed("No hang while unloading the iframe");
+ finishJSTest();
+}
+
+_onload_ = () => {
+ testFrame.remove();
+}
+</script>
+</html>
Modified: branches/safari-609-branch/Source/WebCore/ChangeLog (255014 => 255015)
--- branches/safari-609-branch/Source/WebCore/ChangeLog 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/Source/WebCore/ChangeLog 2020-01-23 21:43:50 UTC (rev 255015)
@@ -1,5 +1,83 @@
2020-01-23 Russell Epstein <[email protected]>
+ Cherry-pick r254652. rdar://problem/58811422
+
+ Regression(r253213) Load hang and high CPU usage when trying to load myuhc.com
+ https://bugs.webkit.org/show_bug.cgi?id=206315
+ <rdar://problem/58139842>
+
+ Reviewed by Geoffrey Garen.
+
+ Source/WebCore:
+
+ Starting in r253213, we now throw when trying to do a sync XHR during unload. Unfortunately, this is confusing the script
+ on myuhc.com and it ends up retrying the sync XHR in a tight loop. To address the issue, I am putting in a safety net which
+ ignores calls to XMLHttpRequest.send() instead of throwing, once we've reached 5 sync XHR failures during unload.
+
+ Throwing is useful because this gives a change for Web authors to fall back to using Beacon API or Fetch KeepAlive if the
+ sync XHR fails. There is already code out there doing just that. You could imagine content doing more than one sync XHR
+ during unload, each one with a good beacon API fallback. For this reason, I put in a limit of 5 sync failures before
+ we stop throwing. Having a limit is important to break bad loops when the content simply retries the same sync XHR load
+ when the sync XHR send() call throws.
+
+ Tests: fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html
+ fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::didRejectSyncXHRDuringPageDismissal):
+ (WebCore::Document::shouldIgnoreSyncXHRs const):
+ * dom/Document.h:
+ * loader/DocumentThreadableLoader.cpp:
+ (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::prepareToSend):
+
+ LayoutTests:
+
+ Add layout test coverage.
+
+ * fast/xmlhttprequest/resources/xmlhttprequest-multiple-sync-xhr-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/resources/xmlhttprequest-sync-xhr-failure-loop-during-unload-iframe.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload-expected.txt: Added.
+ * fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@254652 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2020-01-15 Chris Dumez <[email protected]>
+
+ Regression(r253213) Load hang and high CPU usage when trying to load myuhc.com
+ https://bugs.webkit.org/show_bug.cgi?id=206315
+ <rdar://problem/58139842>
+
+ Reviewed by Geoffrey Garen.
+
+ Starting in r253213, we now throw when trying to do a sync XHR during unload. Unfortunately, this is confusing the script
+ on myuhc.com and it ends up retrying the sync XHR in a tight loop. To address the issue, I am putting in a safety net which
+ ignores calls to XMLHttpRequest.send() instead of throwing, once we've reached 5 sync XHR failures during unload.
+
+ Throwing is useful because this gives a change for Web authors to fall back to using Beacon API or Fetch KeepAlive if the
+ sync XHR fails. There is already code out there doing just that. You could imagine content doing more than one sync XHR
+ during unload, each one with a good beacon API fallback. For this reason, I put in a limit of 5 sync failures before
+ we stop throwing. Having a limit is important to break bad loops when the content simply retries the same sync XHR load
+ when the sync XHR send() call throws.
+
+ Tests: fast/xmlhttprequest/xmlhttprequest-multiple-sync-xhr-during-unload.html
+ fast/xmlhttprequest/xmlhttprequest-sync-xhr-failure-loop-during-unload.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::didRejectSyncXHRDuringPageDismissal):
+ (WebCore::Document::shouldIgnoreSyncXHRs const):
+ * dom/Document.h:
+ * loader/DocumentThreadableLoader.cpp:
+ (WebCore::DocumentThreadableLoader::DocumentThreadableLoader):
+ * xml/XMLHttpRequest.cpp:
+ (WebCore::XMLHttpRequest::prepareToSend):
+
+2020-01-23 Russell Epstein <[email protected]>
+
Cherry-pick r254541. rdar://problem/58605951
Supported mime types for encoding should be supported mime types for loading
Modified: branches/safari-609-branch/Source/WebCore/dom/Document.cpp (255014 => 255015)
--- branches/safari-609-branch/Source/WebCore/dom/Document.cpp 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/Source/WebCore/dom/Document.cpp 2020-01-23 21:43:50 UTC (rev 255015)
@@ -8352,6 +8352,24 @@
top.setHasEvaluatedUserAgentScripts();
}
+void Document::didRejectSyncXHRDuringPageDismissal()
+{
+ ++m_numberOfRejectedSyncXHRs;
+ if (m_numberOfRejectedSyncXHRs > 1)
+ return;
+
+ postTask([this, weakThis = makeWeakPtr(*this)](auto&) mutable {
+ if (weakThis)
+ m_numberOfRejectedSyncXHRs = 0;
+ });
+}
+
+bool Document::shouldIgnoreSyncXHRs() const
+{
+ const unsigned maxRejectedSyncXHRsPerEventLoopIteration = 5;
+ return m_numberOfRejectedSyncXHRs > maxRejectedSyncXHRsPerEventLoopIteration;
+}
+
#if ENABLE(APPLE_PAY)
bool Document::isApplePayActive() const
Modified: branches/safari-609-branch/Source/WebCore/dom/Document.h (255014 => 255015)
--- branches/safari-609-branch/Source/WebCore/dom/Document.h 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/Source/WebCore/dom/Document.h 2020-01-23 21:43:50 UTC (rev 255015)
@@ -762,6 +762,9 @@
void setFocusNavigationStartingNode(Node*);
Element* focusNavigationStartingNode(FocusDirection) const;
+ void didRejectSyncXHRDuringPageDismissal();
+ bool shouldIgnoreSyncXHRs() const;
+
enum class NodeRemoval { Node, ChildrenOfNode };
void adjustFocusedNodeOnNodeRemoval(Node&, NodeRemoval = NodeRemoval::Node);
void adjustFocusNavigationNodeOnNodeRemoval(Node&, NodeRemoval = NodeRemoval::Node);
@@ -2055,7 +2058,7 @@
RefPtr<Worklet> m_paintWorklet;
HashMap<String, Ref<PaintWorkletGlobalScope>> m_paintWorkletGlobalScopes;
#endif
-
+ unsigned m_numberOfRejectedSyncXHRs { 0 };
bool m_hasEvaluatedUserAgentScripts { false };
bool m_isRunningUserScripts { false };
bool m_mayBeDetachedFromFrame { true };
Modified: branches/safari-609-branch/Source/WebCore/loader/DocumentThreadableLoader.cpp (255014 => 255015)
--- branches/safari-609-branch/Source/WebCore/loader/DocumentThreadableLoader.cpp 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/Source/WebCore/loader/DocumentThreadableLoader.cpp 2020-01-23 21:43:50 UTC (rev 255015)
@@ -133,6 +133,7 @@
ASSERT(m_async || m_referrer.isEmpty());
if (document.settings().disallowSyncXHRDuringPageDismissalEnabled() && !m_async && (!document.page() || !document.page()->areSynchronousLoadsAllowed())) {
+ document.didRejectSyncXHRDuringPageDismissal();
logErrorAndFail(ResourceError(errorDomainWebKitInternal, 0, request.url(), "Synchronous loads are not allowed at this time"));
return;
}
Modified: branches/safari-609-branch/Source/WebCore/xml/XMLHttpRequest.cpp (255014 => 255015)
--- branches/safari-609-branch/Source/WebCore/xml/XMLHttpRequest.cpp 2020-01-23 21:43:45 UTC (rev 255014)
+++ branches/safari-609-branch/Source/WebCore/xml/XMLHttpRequest.cpp 2020-01-23 21:43:50 UTC (rev 255015)
@@ -413,6 +413,11 @@
auto& context = *scriptExecutionContext();
+ if (is<Document>(context) && downcast<Document>(context).shouldIgnoreSyncXHRs()) {
+ logConsoleError(scriptExecutionContext(), makeString("Ignoring XMLHttpRequest.send() call for '", m_url.string(), "' because the maximum number of synchronous failures was reached."));
+ return ExceptionOr<void> { };
+ }
+
if (readyState() != OPENED || m_sendFlag)
return ExceptionOr<void> { Exception { InvalidStateError } };
ASSERT(!m_loader);