Bug 188499

Summary: Setting a frame src after appending it to the DOM makes the frame's load event be fired twice
Product: WebKit Reporter: Timothée Pillard <tpillardpro>
Component: FramesAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: aestes, ahmad.saleem792, ap, beidson, cdumez, jannis.rautenstrauch, rniwa, saetia, webkit-bug-importer
Priority: P2 Keywords: BrowserCompat, InRadar
Version: Safari 11   
Hardware: Mac   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=243123
https://bugs.webkit.org/show_bug.cgi?id=245719
Attachments:
Description Flags
Test case none

Description Timothée Pillard 2018-08-12 23:53:24 PDT
Hello,

I am creating this bug in follow-up to https://twitter.com/tpillard/status/1028663435524009984

The following JavaScript code will log the "Loaded" message twice.


```
const root = document.body;
const frame = document.createElement('iframe');
const href = 'https://bugs.webkit.org';

frame.onload = (evt) => console.log('Loaded', evt);
root.appendChild(frame);
frame.src = href;
```

Inverting the last two lines (setting the frame's src before appending it to the DOM) fixes the problem.

Tested and fixed with the following UA string:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.1 Safari/605.1.15

I've originally had some customer complaints on this behavior, one includes the following UA string:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1 Safari/605.1.15

While debugging, I noticed similar issues have been reported by users on StackOverflow over the years:
https://stackoverflow.com/questions/10781880/dynamically-created-iframe-triggers-onload-event-twice
https://stackoverflow.com/questions/22722046/onload-bug-in-google-chrome-safari
https://stackoverflow.com/questions/25066052/window-onload-called-twice-inside-an-iframe

I could not reproduce this behavior on other browsers I had at my disposal.

Thank you for any response,

--
Tim
Comment 1 Timothée Pillard 2018-08-13 00:05:52 PDT
Quick note:

Setting the `load` event handler on the iframe after appending it to the DOM fixes the problem as well.
Comment 2 Ryosuke Niwa 2018-08-20 12:24:29 PDT
Created attachment 347527 [details]
Test case
Comment 3 Ryosuke Niwa 2018-08-20 12:28:02 PDT
On interesting, When an iframe is inserted into a document, it loads about:blank which in turn fires a load event. What makes WebKit and Blink's behavior different from the spec is that we synchronously fire a load event in this case.

See https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element

When an iframe element is inserted into a document that has a browsing context, the user agent must create a new browsing context, set the element's nested browsing context to the newly-created browsing context, and then process the iframe attributes for the "first time".

https://html.spec.whatwg.org/multipage/iframe-embed-object.html#process-the-iframe-attributes

Otherwise, if the element has no src attribute specified, and the user agent is processing the iframe's attributes for the "first time"
Queue a task to run the iframe load event steps.
The task source for this task is the DOM manipulation task source.
Comment 4 Ryosuke Niwa 2018-08-20 12:28:51 PDT
My guess is that making the event load fire async won't be a Web compatible change at this point but we can try.
Comment 5 Radar WebKit Bug Importer 2018-11-12 16:27:33 PST
<rdar://problem/46008888>
Comment 6 Ahmad Saleem 2022-09-12 14:48:23 PDT
I am able to reproduce this bug in Safari 16 / STP 153 on macOS 12.6 using attached test case and it shows two "Loaded Event" in Console compared to other browsers (Chrome Canary 107 and Firefox Nightly 106), which only shows one.

Just wanted to share updated testing results. Thanks!
Comment 7 jannis.rautenstrauch 2023-09-28 06:57:04 PDT
Chromium (v117) also fires two load events.
Testing v107 also shows two load events for me.
Firefox only fires one load event.