-
Notifications
You must be signed in to change notification settings - Fork 1
Description
In migrating one of our applications to Can 4, I've encountered what appears to be a pretty low-level problem in SetterObservable: specifically, when you call its setter, it never actually updates its value property. I assume this is because it's expected that the observation handler will be used to retrieve the value, but when can-bind calls the setter in updateValue (args.observable will be a SetterObservable in the case where value that's changing is bound to a converter), it then immediately calls the getter on the same observable.
This would be fine, except that because bound is true, the getter (implemented in get-set.js) skips using the observation function and returns this.value directly, which returns whatever the parent value was at the time the binding was set up.
This has a few negative side effects when using two-way binding through a converter:
- A confusing semaphore warning is written out to the console because the
updateValuefunction referenced above will cycle multiple times trying to get the parent and child values to agree (even though they already do; it's simply looking at an old snapshot of the parent value to do the comparison), which involves overwriting the child value with the original value of the parent, which will basically always be wrong - The issue that led to me debugging this problem was that my child value was being set first to the expected value, then to whatever the parent value was when the UI was created, then back to the correct value, which was causing unexpected behavior in my application.
I've created a jsbin that reproduces my binding scenario and demonstrates the warning: https://jsbin.com/kevolovonu/4/edit?html,js,console,output
I was unable to get it to reproduce the multiple sets, but I think the warning is probably sufficient to demonstrate that there's a problem here. The solution I found was to add this.value = to the beginning of SetterObservable.prototype.set.