It's a tricky corner case. I don't know how to describe it clearly.
But it is quite easy to reproduce and demonstrate itself.
Just open the writable store example (https://svelte.dev/examples#writable-stores),
and replace count_value = value (line 10) with
if(count_value = value)
console.log(count_value)
You will see that it is not reactive when the value is 0.
The $$invalidate call in the generated code is getting stuck inside the body of the if block, and so is only getting called when the value is truthy. I'm unsure whether it would be best to call it inside the if condition or after the whole if block.
I believe it couldn't go after the if block since a return or error after the assignment would bypass the invalidation.
What if $$invalidate returned the passed in value so that all assignments could be replaced as-is?
if (name = stuff) {}
if ($$invalidate('name', name = stuff)) {}
fn(name = value);
fn(name = value); $$invalidate('name', value);
fn($$invalidate('name', name = value));
const fn = (value) => name = value;
const fn = (value) => { const $$result = name = value; $$invalidate('name', name); return $$result; };
const fn = (value) => $$invalidate('name', name = value);
It looks like this was also fixed in 3.10.1 by #3533.
Most helpful comment
I believe it couldn't go after the
ifblock since areturnor error after the assignment would bypass the invalidation.What if
$$invalidatereturned the passed in value so that all assignments could be replaced as-is?