So far, here's what I observed: The `for (u in ve(t, l), s = l)` below iterates over the properties from the above, and the property value flows into `b(e, u, c, i)`: https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function Bo(e, n, t) { var r = n.pendingProps; switch (Gl(n), n.tag) { ... case 5: tu(n); var l = Za(Ga.current); if (t = n.type, null !== e && null != n.stateNode) Po(e, n, t, r), e.ref !== n.ref && (n.flags |= 512, n.flags |= 2097152); else { ... if (e = Za(Ya.current), oa(n)) { ... } else { ... e: { ... for (u in ve(t, l), s = l) if (s.hasOwnProperty(u)) { var c = s[u]; 'style' === u ? he(e, c) : 'dangerouslySetInnerHTML' === u ? null != (c = c ? c.__html : void 0) && ce(e, c) : 'children' === u ? 'string' == typeof c ? ('textarea' !== t || '' !== c) && fe(e, c) : 'number' == typeof c && fe(e, '' + c) : 'suppressContentEditableWarning' !== u && 'suppressHydrationWarning' !== u && 'autoFocus' !== u && (o.hasOwnProperty(u) ? null != c && 'onScroll' === u && Mr('scroll', e) : null != c && b(e, u, c, i)) } ``` `b(e, u, c, i)` performs `setAttribute` on the `img` element. At this point, the `img` element doesn't have parent node. https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function b(e, n, t, r) { ... }(n) && (null === t ? e.removeAttribute(n) : e.setAttribute(n, '' + t)) : l.mustUseProperty ? e[l.propertyName] = null === t ? 3 !== l.type && '' : t : (n = l.attributeName, r = l.attributeNamespace, null === t ? e.removeAttribute(n) : (t = 3 === (l = l.type) || 4 === l && !0 === t ? '' : '' + t, r ? e.setAttributeNS(r, n, t) : e.setAttribute(n, t)))) ``` After all attributes are populates (including both `src` and `srcset`), the element is *somehow* connected to the document, and then it causes the `error` event. Then, after that, yet another `setAttribute` call happens t times in the following https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function di(e, n) { var t = e.alternate, r = e.flags; switch (e.tag) { ... case 5: ... if (4 & r && null != (l = e.stateNode)) { ... if (e.updateQueue = null, null !== s) try { 'input' === i && 'radio' === u.type && null != u.name && G(l, u), ye(i, o); var c = ye(i, u); for (o = 0; o < s.length; o += 2) { var f = s[o], d = s[o + 1]; 'style' === f ? he(l, d) : 'dangerouslySetInnerHTML' === f ? ce(l, d) : 'children' === f ? fe(l, d) : b(l, f, d, c) ``` and then `load` event is dispatched on the `img` element twice. There's no difference in the element attributes between: * after `for (u in ve(t, l), s = l)` loop, and * after `for (o = 0; o < s.length; o += 2)` loop So at least the difference between `error` vs `load` doesn't seem to be caused by the attributes themselves. Then, one thing I notice is that, the behavior for the following case differs between Firefox vs Chromium/Safari * `img` element is not attached to the tree * `img` element has `src` attribute with empty string * `img` element has `srcset` attribute with valid sources * `img` element has `loading` attribute with `lazy` value testcase: `data:text/html,<script>const img = document.createElement("img"); img.onload = () => { console.log("load"); }; img.onerror = ( ) => { console.log("error"); }; img.setAttribute("src", ""); img.setAttribute("srcset", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12NgYPgPAAEDAQDZqt2zAAAAAElFTkSuQmCC 100w, data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12NgYPgPAAEDAQDZqt2zAAAAAElFTkSuQmCC 200w"); img.setAttribute("loading", "lazy");</script>` Firefox shows `error`, but Chromium/Safari show `load`. So, the possibility is that, there's some delay between setting attributes and attaching to the tree, and `error` event happens only on Firefox, and it applies the `visibility: hidden`, and then the image loads properly once the `img` is attached to the tree.
Bug 1905646 Comment 1 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
So far, here's what I observed: The `for (u in ve(t, l), s = l)` below iterates over the properties from the above, and the property value flows into `b(e, u, c, i)`: https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function Bo(e, n, t) { var r = n.pendingProps; switch (Gl(n), n.tag) { ... case 5: tu(n); var l = Za(Ga.current); if (t = n.type, null !== e && null != n.stateNode) Po(e, n, t, r), e.ref !== n.ref && (n.flags |= 512, n.flags |= 2097152); else { ... if (e = Za(Ya.current), oa(n)) { ... } else { ... e: { ... for (u in ve(t, l), s = l) if (s.hasOwnProperty(u)) { var c = s[u]; 'style' === u ? he(e, c) : 'dangerouslySetInnerHTML' === u ? null != (c = c ? c.__html : void 0) && ce(e, c) : 'children' === u ? 'string' == typeof c ? ('textarea' !== t || '' !== c) && fe(e, c) : 'number' == typeof c && fe(e, '' + c) : 'suppressContentEditableWarning' !== u && 'suppressHydrationWarning' !== u && 'autoFocus' !== u && (o.hasOwnProperty(u) ? null != c && 'onScroll' === u && Mr('scroll', e) : null != c && b(e, u, c, i)) } ``` `b(e, u, c, i)` performs `setAttribute` on the `img` element. At this point, the `img` element doesn't have parent node. https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function b(e, n, t, r) { ... }(n) && (null === t ? e.removeAttribute(n) : e.setAttribute(n, '' + t)) : l.mustUseProperty ? e[l.propertyName] = null === t ? 3 !== l.type && '' : t : (n = l.attributeName, r = l.attributeNamespace, null === t ? e.removeAttribute(n) : (t = 3 === (l = l.type) || 4 === l && !0 === t ? '' : '' + t, r ? e.setAttributeNS(r, n, t) : e.setAttribute(n, t)))) ``` After all attributes are populates (including both `src` and `srcset`), the element is *somehow* connected to the document, and then (or maybe before get connected?) it causes the `error` event. Then, after that, yet another `setAttribute` call happens t times in the following (at this point, `img` has parent node) https://www.ubereats.com/_static/client-vendor-react-57d02f50089116f6.js ```js function di(e, n) { var t = e.alternate, r = e.flags; switch (e.tag) { ... case 5: ... if (4 & r && null != (l = e.stateNode)) { ... if (e.updateQueue = null, null !== s) try { 'input' === i && 'radio' === u.type && null != u.name && G(l, u), ye(i, o); var c = ye(i, u); for (o = 0; o < s.length; o += 2) { var f = s[o], d = s[o + 1]; 'style' === f ? he(l, d) : 'dangerouslySetInnerHTML' === f ? ce(l, d) : 'children' === f ? fe(l, d) : b(l, f, d, c) ``` and then `load` event is dispatched on the `img` element twice. There's no difference in the element attributes between: * after `for (u in ve(t, l), s = l)` loop, and * after `for (o = 0; o < s.length; o += 2)` loop So at least the difference between `error` vs `load` doesn't seem to be caused by the attributes themselves. Then, one thing I notice is that, the behavior for the following case differs between Firefox vs Chromium/Safari * `img` element is not attached to the tree * `img` element has `src` attribute with empty string * `img` element has `srcset` attribute with valid sources * `img` element has `loading` attribute with `lazy` value testcase: `data:text/html,<script>const img = document.createElement("img"); img.onload = () => { console.log("load"); }; img.onerror = ( ) => { console.log("error"); }; img.setAttribute("src", ""); img.setAttribute("srcset", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12NgYPgPAAEDAQDZqt2zAAAAAElFTkSuQmCC 100w, data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12NgYPgPAAEDAQDZqt2zAAAAAElFTkSuQmCC 200w"); img.setAttribute("loading", "lazy");</script>` Firefox shows `error`, but Chromium/Safari show `load`. So, the possibility is that, there's some delay between setting attributes and attaching to the tree, and `error` event happens only on Firefox, and it applies the `visibility: hidden`, and then the image loads properly once the `img` is attached to the tree.