diff --git a/src/compile/nodes/shared/Expression.ts b/src/compile/nodes/shared/Expression.ts index 0a0c4c6cb6..c7a3d5de91 100644 --- a/src/compile/nodes/shared/Expression.ts +++ b/src/compile/nodes/shared/Expression.ts @@ -10,6 +10,7 @@ import Wrapper from '../../render-dom/wrappers/shared/Wrapper'; import sanitize from '../../../utils/sanitize'; import TemplateScope from './TemplateScope'; import getObject from '../../../utils/getObject'; +import { nodes_match } from '../../../utils/nodes_match'; const binaryOperators: Record = { '**': 15, @@ -253,11 +254,21 @@ export default class Expression { ? [getObject(node.left).name] : extractNames(node.left); - names.forEach(name => { - if (!scope.declarations.has(name)) { - pending_assignments.add(name); - } - }); + if (node.operator === '=' && nodes_match(node.left, node.right)) { + const dirty = names.filter(name => { + return !scope.declarations.has(name); + }); + + if (dirty.length) component.has_reactive_assignments = true; + + code.overwrite(node.start, node.end, dirty.map(n => `$$make_dirty('${n}')`).join('; ')); + } else { + names.forEach(name => { + if (!scope.declarations.has(name)) { + pending_assignments.add(name); + } + }); + } } else if (node.type === 'UpdateExpression') { const { name } = getObject(node.argument); diff --git a/test/js/samples/instrumentation-template-x-equals-x/expected.js b/test/js/samples/instrumentation-template-x-equals-x/expected.js new file mode 100644 index 0000000000..15a1994cf5 --- /dev/null +++ b/test/js/samples/instrumentation-template-x-equals-x/expected.js @@ -0,0 +1,67 @@ +/* generated by Svelte vX.Y.Z */ +import { SvelteComponent as SvelteComponent_1, addListener, append, createElement, createText, detachNode, init, insert, run, safe_not_equal, setData } from "svelte/internal.js"; + +function create_fragment(component, ctx) { + var button, text1, p, text2, text3_value = ctx.things.length, text3, current, dispose; + + return { + c() { + button = createElement("button"); + button.textContent = "foo"; + text1 = createText("\n\n"); + p = createElement("p"); + text2 = createText("number of things: "); + text3 = createText(text3_value); + dispose = addListener(button, "click", ctx.click_handler); + }, + + m(target, anchor) { + insert(target, button, anchor); + insert(target, text1, anchor); + insert(target, p, anchor); + append(p, text2); + append(p, text3); + current = true; + }, + + p(changed, ctx) { + if ((changed.things) && text3_value !== (text3_value = ctx.things.length)) { + setData(text3, text3_value); + } + }, + + i(target, anchor) { + if (current) return; + this.m(target, anchor); + }, + + o: run, + + d(detach) { + if (detach) { + detachNode(button); + detachNode(text1); + detachNode(p); + } + + dispose(); + } + }; +} + +function define($$self, $$props, $$make_dirty) { + let things = []; + + function click_handler() { things.push(1); $$make_dirty('things') } + + $$self.$$.get = () => ({ things, click_handler }); +} + +class SvelteComponent extends SvelteComponent_1 { + constructor(options) { + super(); + init(this, options, define, create_fragment, safe_not_equal); + } +} + +export default SvelteComponent; \ No newline at end of file diff --git a/test/js/samples/instrumentation-template-x-equals-x/input.html b/test/js/samples/instrumentation-template-x-equals-x/input.html new file mode 100644 index 0000000000..bfd4a480dd --- /dev/null +++ b/test/js/samples/instrumentation-template-x-equals-x/input.html @@ -0,0 +1,7 @@ + + + + +

number of things: {things.length}

\ No newline at end of file