Bug 190031 - Creating an image via JavaScript will download both src and srcset
Summary: Creating an image via JavaScript will download both src and srcset
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Images (show other bugs)
Version: Safari 11
Hardware: All All
: P2 Normal
Assignee: Nobody
URL:
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2018-09-27 01:37 PDT by Gareth
Modified: 2024-06-09 03:08 PDT (History)
14 users (show)

See Also:


Attachments
[Testcase] Safari img element src and srcset double loading bug (3.58 KB, text/html)
2022-04-07 12:59 PDT, affix.grower_0y
no flags Details
Network tab while loading the sample website over a slow connection (1.01 MB, image/png)
2023-05-08 07:40 PDT, Otto G
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Gareth 2018-09-27 01:37:23 PDT
See the following JavaScript example to create an image:

> var image = document.createElement( 'img' );
> image.setAttribute( 'src', 'https://via.placeholder.com/300x100/0e7f00' );
> image.setAttribute( 'srcset', 'https://via.placeholder.com/400x100/0e7f00 400w' );
> document.body.appendChild( image );
In WebKit, both the src and srcset image will be downloaded.

However, upon setting srcset first, before src, then only the srcset version will be downloaded:

> var image = document.createElement( 'img' );
> image.setAttribute( 'srcset', 'https://via.placeholder.com/400x100/0e7f00 400w' );
> image.setAttribute( 'src', 'https://via.placeholder.com/300x100/0e7f00' );
> document.body.appendChild( image );
Expected behaviour:

Only download one correct source, no matter of setAttribute order.

Tested on Safari 10.1 and 12.0 (iPhone and macOS)

Possibly related: https://bugs.webkit.org/show_bug.cgi?id=177068
Comment 1 Radar WebKit Bug Importer 2018-09-28 16:21:57 PDT
<rdar://problem/44878381>
Comment 2 Daniel O'Connor 2019-05-30 18:13:35 PDT
May be a duplicate of: 
https://bugs.webkit.org/show_bug.cgi?id=177068
Comment 3 affix.grower_0y 2022-04-07 12:59:44 PDT
Created attachment 456958 [details]
[Testcase] Safari img element src and srcset double loading bug
Comment 4 Igor Danchenko 2023-02-23 11:27:46 PST
This bug is still present in Safari 16.3 and can cause significant bandwidth waste for React-based websites.

Here is an isolated test case using React app - https://2ed5dq.csb.app

Test case source code - https://codesandbox.io/s/webkit-190031-2ed5dq?file=/src/App.js
Comment 5 Otto G 2023-05-08 06:56:13 PDT
Hi,

This bug is still present in Safari 16.4 and Safari Technology Preview Release 169.

I would like to stress that in frameworks such as React and Vue.js, there is by definition no way of controlling the order in which elements and attributes are added to the DOM tree.

This makes it all the more important that browsers are indifferent to that aspect of the HTML.

Now, it might possibly be that on a slow network, Safari cancels the first request before it has been completed. This would make the issue less serious, although it is still not optimal. I will try to find a good way of testing this.
Comment 6 Otto G 2023-05-08 07:40:32 PDT
Created attachment 466278 [details]
Network tab while loading the sample website over a slow connection

I downloaded and installed the "Network Link Conditioner" control panel (see https://stackoverflow.com/a/73962679/2416627 for instructions), and I can report that unfortunately, Safari patiently downloads both the src image and the appropriate srcset image, even if it takes a few minutes before all images are loaded and the smaller image finishes loading a minute or more before the larger image.

This actually, completely unnecessarily, leads to horrible performance over a simulated 3G connection for some web pages. (On a real-life website with several responsive images on client-side React pages.)

The sample by Igor Danchenko exhibits the same behavior over a simulated slow connection. I attach a screen dump of the network tab with custom Network Link Conditioner settings of 5 mbps down / 2 mbps up, 50 ms delay, when loading the sample website with a cleared cache.
Comment 7 Ahmad Saleem 2024-02-22 04:47:06 PST
Going by comment - it might be some code here: 

https://searchfox.org/wubkat/rev/65d5c80e4e183ab1f41152388e975fdd33cbe259/Source/WebCore/loader/ImageLoader.cpp#197

// Do not load any image if the 'src' attribute is missing or if it is
// an empty string.

Could be completely wrong.. but just trying to understand code. Although only reference to 'srcset' is this:


        if (imageElement) {
            options.referrerPolicy = imageElement->referrerPolicy();
            options.fetchPriorityHint = imageElement->fetchPriorityHint();
            if (imageElement->usesSrcsetOrPicture())
                options.initiator = Initiator::Imageset;
        }

__

might be to add 'else' condition? Just taking notes etc.
Comment 8 Maciass 2024-06-09 03:06:52 PDT
// example 1, srcset first
const newImage = new Image();
newImage.srcset = 'https://domain.com/image.jpg?w=200 200w';
newImage.src = 'https://domain.com/image.jpg';
document.body.appendChild(newImage);
Comment 9 Maciass 2024-06-09 03:07:11 PDT
// example 2, src first
const newImage = new Image();
newImage.src = 'https://domain.com/image.jpg';
newImage.srcset = 'https://domain.com/image.jpg?w=200 200w';
document.body.appendChild(newImage);
Comment 10 Maciass 2024-06-09 03:08:52 PDT
(In reply to Gareth from comment #0)
> See the following JavaScript example to create an image:
> 
> > var image = document.createElement( 'img' );
> > image.setAttribute( 'src', 'https://via.placeholder.com/300x100/0e7f00' );
> > image.setAttribute( 'srcset', 'https://via.placeholder.com/400x100/0e7f00 400w' );
> > document.body.appendChild( image );
> In WebKit, both the src and srcset image will be downloaded.
> 
> However, upon setting srcset first, before src, then only the srcset version
> will be downloaded:
> 
> > var image = document.createElement( 'img' );
> > image.setAttribute( 'srcset', 'https://via.placeholder.com/400x100/0e7f00 400w' );
> > image.setAttribute( 'src', 'https://via.placeholder.com/300x100/0e7f00' );
> > document.body.appendChild( image );
> Expected behaviour:
> 
> Only download one correct source, no matter of setAttribute order.
> 
> Tested on Safari 10.1 and 12.0 (iPhone and macOS)
> 
> Possibly related: https://bugs.webkit.org/show_bug.cgi?id=177068