Skip to content

Commit

Permalink
fix: use importNode to clone templates for Firefox
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloricciuti committed Feb 11, 2025
1 parent a3e49b6 commit ca74fcd
Show file tree
Hide file tree
Showing 9 changed files with 14 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-meals-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: use `importNode` to clone templates for Firefox
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ export function Attribute(node, context) {
if (node.name === 'value' && parent.name === 'option') {
mark_subtree_dynamic(context.path);
}

// special case <img loading="lazy" />
if (node.name === 'loading' && parent.name === 'img') {
mark_subtree_dynamic(context.path);
}
}

if (is_event_attribute(node)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,6 @@ export function RegularElement(node, context) {
build_class_directives(class_directives, node_id, context, is_attributes_reactive);
build_style_directives(style_directives, node_id, context, is_attributes_reactive);

// Apply the src and loading attributes for <img> elements after the element is appended to the document
if (node.name === 'img' && (has_spread || lookup.has('loading'))) {
context.state.after_update.push(b.stmt(b.call('$.handle_lazy_img', node_id)));
}

if (
is_load_error_element(node.name) &&
(has_spread || has_use || lookup.has('onload') || lookup.has('onerror'))
Expand Down
25 changes: 0 additions & 25 deletions packages/svelte/src/internal/client/dom/elements/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -523,28 +523,3 @@ function srcset_url_equal(element, srcset) {
)
);
}

/**
* @param {HTMLImageElement} element
* @returns {void}
*/
export function handle_lazy_img(element) {
// If we're using an image that has a lazy loading attribute, we need to apply
// the loading and src after the img element has been appended to the document.
// Otherwise the lazy behaviour will not work due to our cloneNode heuristic for
// templates.
if (!hydrating && element.loading === 'lazy') {
var src = element.src;
// @ts-expect-error
element[LOADING_ATTR_SYMBOL] = null;
element.loading = 'eager';
element.removeAttribute('src');
requestAnimationFrame(() => {
// @ts-expect-error
if (element[LOADING_ATTR_SYMBOL] !== 'eager') {
element.loading = 'lazy';
}
element.src = src;
});
}
}
4 changes: 4 additions & 0 deletions packages/svelte/src/internal/client/dom/operations.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export var $window;
/** @type {Document} */
export var $document;

/** @type {boolean} */
export var is_firefox;

/** @type {() => Node | null} */
var first_child_getter;
/** @type {() => Node | null} */
Expand All @@ -27,6 +30,7 @@ export function init_operations() {

$window = window;
$document = document;
is_firefox = /Firefox/.test(navigator.userAgent);

var element_prototype = Element.prototype;
var node_prototype = Node.prototype;
Expand Down
4 changes: 2 additions & 2 deletions packages/svelte/src/internal/client/dom/template.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @import { Effect, TemplateNode } from '#client' */
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from './hydration.js';
import { create_text, get_first_child } from './operations.js';
import { create_text, get_first_child, is_firefox } from './operations.js';
import { create_fragment_from_html } from './reconciler.js';
import { active_effect } from '../runtime.js';
import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../constants.js';
Expand Down Expand Up @@ -48,7 +48,7 @@ export function template(content, flags) {
}

var clone = /** @type {TemplateNode} */ (
use_import_node ? document.importNode(node, true) : node.cloneNode(true)
use_import_node || is_firefox ? document.importNode(node, true) : node.cloneNode(true)
);

if (is_fragment) {
Expand Down
1 change: 0 additions & 1 deletion packages/svelte/src/internal/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export {
set_attributes,
set_custom_element_data,
set_xlink_attribute,
handle_lazy_img,
set_value,
set_checked,
set_selected,
Expand Down
3 changes: 2 additions & 1 deletion packages/svelte/src/internal/client/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
set_component_context,
set_dev_current_component_function
} from './context.js';
import { is_firefox } from './dom/operations.js';

const FLUSH_MICROTASK = 0;
const FLUSH_SYNC = 1;
Expand Down Expand Up @@ -333,7 +334,7 @@ export function handle_error(error, effect, previous_effect, component_context)
current_context = current_context.p;
}

const indent = /Firefox/.test(navigator.userAgent) ? ' ' : '\t';
const indent = is_firefox ? ' ' : '\t';
define_property(error, 'message', {
value: error.message + `\n${component_stack.map((name) => `\n${indent}in ${name}`).join('')}\n`
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,8 @@ export default function Skip_static_subtree($$anchor, $$props) {
$.reset(select);

var img = $.sibling(select, 2);
var div_2 = $.sibling(img, 2);
var img_1 = $.child(div_2);

$.reset(div_2);
$.next(2);
$.template_effect(() => $.set_text(text, $$props.title));
$.handle_lazy_img(img);
$.handle_lazy_img(img_1);
$.append($$anchor, fragment);
}

0 comments on commit ca74fcd

Please sign in to comment.