fix: keep short-circuited bindings subscribed so they can update again#7649
Open
AKnassa wants to merge 1 commit into
Open
fix: keep short-circuited bindings subscribed so they can update again#7649AKnassa wants to merge 1 commit into
AKnassa wants to merge 1 commit into
Conversation
A binding whose expression short-circuits before reading any observable (for example `x => x.plainValue && x.observable`) collected no dependencies and could therefore never be re-evaluated, leaving it permanently dead. Volatile bindings that end an evaluation with no dependencies now subscribe to the source itself, via the existing no-property path on PropertyChangeNotifier, so a later change still wakes them. Guarded so non-object sources (repeat binds primitives) cannot reach the WeakMap. Fixes microsoft#7035
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Fixes a bug where a piece of your UI could quietly stop responding to data — forever — just because of the order you wrote two conditions in.
Why
Consider a condition like "show this if the feature is on and we have a value":
Both read the same, but only the first one keeps working. JavaScript stops evaluating an
&&as soon as it finds something falsy, so in the second version the observable value is never actually read. FAST tracks what a binding reads, so nothing gets tracked, the binding ends up watching nothing at all, and once that happens it can never wake up again.It is worse than a binding that never works: a binding can start out healthy and go permanently dead the first time the guard is false. There is no error and no warning. Reversing two words in a condition should not silently break your app.
What changed
repeatbinds each item, and items can be plain strings or numbers, so the fallback is guarded to only apply where it is safe.when's handling of a value that arrives while unbound is now covered too.Scope
This rescues the "read nothing at all" case, which is the one that dies permanently. A binding that reads some of its dependencies (
x => x.tracked && x.getter && x.other) still tracks only what it read on the last pass — that is existing, intended behavior and is unchanged.How to see it
Run the
fast-elementtest suite. The new tests inobservation/observable.pw.spec.tsandtemplating/when.pw.spec.tsassert that both orderings of&&produce identical update counts. They fail onmainand pass here.Performance was measured, since this touches the code every binding in every FAST app runs through. Benchmarks (
basic,when,repeat, in both client-render and hydration) were run interleaved againstmainacross multiple rounds: all differences fell inside the harness's own round-to-round noise. The added cost on the common path is a single field read and comparison, which short-circuits before any new work.Fixes #7035