diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts index 9ee7694b71..db3cf7a662 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts @@ -73,10 +73,11 @@ export default class AttributeWrapper { const dependencies = this.node.get_dependencies(); const value = this.get_value(block); + const is_src = this.node.name === 'src'; // TODO retire this exception in favour of https://github.com/sveltejs/svelte/issues/3750 const is_select_value_attribute = name === 'value' && element.node.name === 'select'; - const should_cache = is_select_value_attribute; // TODO is this necessary? + const should_cache = is_src || this.node.should_cache() || is_select_value_attribute; // TODO is this necessary? const last = should_cache && block.get_unique_name( `${element.var.name}_${name.replace(/[^a-zA-Z_$]/g, '_')}_value` @@ -119,6 +120,11 @@ export default class AttributeWrapper { ${last} = ${value}; ${updater} `); + } else if (is_src) { + block.chunks.hydrate.push( + b`if (${element.var}.src !== ${init}) ${method}(${element.var}, "${name}", ${last});` + ); + updater = b`${method}(${element.var}, "${name}", ${should_cache ? last : value});`; } else if (property_name) { block.chunks.hydrate.push( b`${element.var}.${property_name} = ${init};` @@ -137,7 +143,9 @@ export default class AttributeWrapper { let condition = changed(dependencies); if (should_cache) { - condition = x`${condition} && (${last} !== (${last} = ${value}))`; + condition = is_src + ? x`${condition} && (${element.var}.src !== (${last} = ${value}))` + : x`${condition} && (${last} !== (${last} = ${value}))`; } if (block.has_outros) { diff --git a/test/js/samples/inline-style-unoptimized/expected.js b/test/js/samples/inline-style-unoptimized/expected.js index 93692daa32..11eaddbdf7 100644 --- a/test/js/samples/inline-style-unoptimized/expected.js +++ b/test/js/samples/inline-style-unoptimized/expected.js @@ -15,6 +15,7 @@ function create_fragment(ctx) { let div0; let t; let div1; + let div1_style_value; return { c() { @@ -22,7 +23,7 @@ function create_fragment(ctx) { t = space(); div1 = element("div"); attr(div0, "style", ctx.style); - attr(div1, "style", "" + (ctx.key + ": " + ctx.value)); + attr(div1, "style", div1_style_value = "" + (ctx.key + ": " + ctx.value)); }, m(target, anchor) { insert(target, div0, anchor); @@ -34,8 +35,8 @@ function create_fragment(ctx) { attr(div0, "style", ctx.style); } - if (changed.key || changed.value) { - attr(div1, "style", "" + (ctx.key + ": " + ctx.value)); + if ((changed.key || changed.value) && div1_style_value !== (div1_style_value = "" + (ctx.key + ": " + ctx.value))) { + attr(div1, "style", div1_style_value); } }, i: noop, diff --git a/test/js/samples/src-attribute-check/_config.js b/test/js/samples/src-attribute-check/_config.js new file mode 100644 index 0000000000..84c0d733ef --- /dev/null +++ b/test/js/samples/src-attribute-check/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + hydratable: true + } +}; \ No newline at end of file diff --git a/test/js/samples/src-attribute-check/expected.js b/test/js/samples/src-attribute-check/expected.js new file mode 100644 index 0000000000..3e6364fa4a --- /dev/null +++ b/test/js/samples/src-attribute-check/expected.js @@ -0,0 +1,90 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponent, + attr, + children, + claim_element, + claim_space, + detach, + element, + init, + insert, + noop, + safe_not_equal, + space +} from "svelte/internal"; + +function create_fragment(ctx) { + let img0; + let img0_src_value; + let t; + let img1; + let img1_src_value; + + return { + c() { + img0 = element("img"); + t = space(); + img1 = element("img"); + this.h(); + }, + l(nodes) { + img0 = claim_element(nodes, "IMG", { alt: true, src: true }); + var img0_nodes = children(img0); + img0_nodes.forEach(detach); + t = claim_space(nodes); + img1 = claim_element(nodes, "IMG", { alt: true, src: true }); + var img1_nodes = children(img1); + img1_nodes.forEach(detach); + this.h(); + }, + h() { + attr(img0, "alt", "potato"); + if (img0.src !== (img0_src_value = ctx.url)) attr(img0, "src", img0_src_value); + attr(img1, "alt", "potato"); + if (img1.src !== (img1_src_value = "" + (ctx.slug + ".jpg"))) attr(img1, "src", img1_src_value); + }, + m(target, anchor) { + insert(target, img0, anchor); + insert(target, t, anchor); + insert(target, img1, anchor); + }, + p(changed, ctx) { + if (changed.url && img0.src !== (img0_src_value = ctx.url)) { + attr(img0, "src", img0_src_value); + } + + if (changed.slug && img1.src !== (img1_src_value = "" + (ctx.slug + ".jpg"))) { + attr(img1, "src", img1_src_value); + } + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) detach(img0); + if (detaching) detach(t); + if (detaching) detach(img1); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let { url } = $$props; + let { slug } = $$props; + + $$self.$set = $$props => { + if ("url" in $$props) $$invalidate("url", url = $$props.url); + if ("slug" in $$props) $$invalidate("slug", slug = $$props.slug); + }; + + return { url, slug }; +} + +class Component extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, { url: 0, slug: 0 }); + } +} + +export default Component; \ No newline at end of file diff --git a/test/js/samples/src-attribute-check/input.svelte b/test/js/samples/src-attribute-check/input.svelte new file mode 100644 index 0000000000..9febd7e4ea --- /dev/null +++ b/test/js/samples/src-attribute-check/input.svelte @@ -0,0 +1,7 @@ + + +potato +potato \ No newline at end of file