Skip to content

Commit

Permalink
Cherry-pick e9dd88d. rdar://problem/105158419
Browse files Browse the repository at this point in the history
    window.onload is repeatedly re-executed when changing URL fragment during onload
    https://bugs.webkit.org/show_bug.cgi?id=252931
    rdar://105158419

    Reviewed by Chris Dumez.

    When a cross-origin iframe changes its fragment identifier while its load event is being processed,
    we end up in a state where we will continually re-fire window.onload. We should fix this by only
    firing the load event on the frame's owner element. This still addresses the concern the original
    change fixed (259384@main), but without needing to always re-fire the window load event.

    * LayoutTests/http/tests/navigation/cross-origin-iframe-location-hash-reexecute-onload-expected.txt: Added.
    * LayoutTests/http/tests/navigation/cross-origin-iframe-location-hash-reexecute-onload.html: Added.
    * LayoutTests/http/tests/navigation/resources/change-location-hash-onload.html: Added.
    * Source/WebCore/loader/FrameLoader.cpp:
    (WebCore::FrameLoader::loadInSameDocument):

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

Canonical link: https://commits.webkit.org/259548.306@safari-7615-branch
  • Loading branch information
charliewolfe authored and MyahCobbs committed Feb 27, 2023
1 parent 55109fa commit bb40c5b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
@@ -0,0 +1,10 @@
This tests that the load event is only fired twice when the location hash is changed in an embedded iframe's window.load.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


PASS onload fired twice.
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,27 @@
<html>
<head>
<script src="/js-test-resources/js-test.js"></script>
</head>
<body>
<script>
description("This tests that the load event is only fired twice when the location hash is changed in an embedded iframe's window.load.");
jsTestIsAsync = true;

let onloadCount = 0;

window.addEventListener("message", () => {
if (onloadCount == 2)
testPassed("onload fired twice.");
else
testFailed("onload fired " + onloadCount + " time(s).");

finishJSTest();
});

function onloadFired() {
onloadCount++;
}
</script>
<iframe src="http://localhost:8000/navigation/resources/change-location-hash-onload.html" onload="onloadFired()"></iframe>
</body>
</html>
@@ -0,0 +1,8 @@
<html>
<script>
window.onload = () => {
window.location.hash = Math.random();
window.parent.postMessage("hashchange", "*");
}
</script>
</html>
4 changes: 2 additions & 2 deletions Source/WebCore/loader/FrameLoader.cpp
Expand Up @@ -1208,8 +1208,8 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr<SerializedScriptValue> stat
if (auto* parentFrame = dynamicDowncast<LocalFrame>(m_frame.tree().parent()); parentFrame
&& (m_frame.document()->processingLoadEvent() || m_frame.document()->loadEventFinished())
&& !m_frame.document()->securityOrigin().isSameOriginAs(parentFrame->document()->securityOrigin()))
m_frame.document()->dispatchWindowLoadEvent();
m_frame.ownerElement()->dispatchEvent(Event::create(eventNames().loadEvent, Event::CanBubble::No, Event::IsCancelable::No));

// FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
m_client->didFinishLoad();
}
Expand Down

0 comments on commit bb40c5b

Please sign in to comment.