Description
Describe the problem
There are many cases where knowing what values a binding could potentially hold would allow us to generate more optimal code. For example, in a situation like this...
<script>
let name = $state('Rich');
</script>
<input bind:value={name} />
<p>Hello {name}!</p>
...we don't need the ?? ""
in the generated code, because we can determine that name
is always defined:
$.template_effect(() => $.set_text(text, `Hello ${$.get(name) ?? ""}!`));
The same goes for references to an index (and, if we were sophisticated enough, the item itself) inside an each block:
{#each 'abc' as l, i}
<p>{i}: {l}</p>
{/each}
-$.template_effect(() => $.set_text(text, `${i ?? ""}: ${l ?? ""}`));
+$.template_effect(() => $.set_text(text, `${i}: ${l ?? ""}`));
Post-#13264, it would also allow us to avoid creating effects in cases where we know an expression doesn't contain state. Right now, code like this...
<script>
let min = 0;
let max = 100;
let number = 50;
</script>
<p>{Math.max(min, Math.min(max, number))}</p>
...yields output like this...
var p = root();
p.textContent = Math.max(min, Math.min(max, number));
...but as of #13264 yields this unnecessary overhead:
var p = root();
var text = $.child(p);
$.template_effect(() => $.set_text(text, Math.max(min, Math.min(max, number))));
$.reset(p);
Describe the proposed solution
Track all the assignments (along with the scopes in which they occur) when first analysing bindings, so that we can later determine things like:
- is this binding always defined? (if so, don't need the
?? ""
) - could this binding hold a reference to a state proxy? (if not, and it's not a state binding, no need to create effects)
- do we know that such-and-such an expression is always truthy or always falsy?
- can this binding be hoisted somewhere?
There are limits to what we can know with such an analysis — often, the answer to 'what could this value be?' is :shrug:
. It's no substitute for knowing the entirety of your program (though we could one day augment it with knowledge of prop values and imports, for example), and nor is it a replacement for an type system (though unlike types, code can't lie about the range of possible values). But it's a relatively simple and cheap way to get a decent chunk of the benefits of a more comprehensive system.
Importance
nice to have