@the-real-blackh The following two commits in the main sodium repository:
73cbcf99919ad54c006e425a0c0e731dfbc8593c
c1b2aa000aa84a0288e1e29dacca5fc9889c4530
The problem was that when Lift
or Apply
was used to create the inner cell of a Cell<Cell<T>>
, the initial inner cell wasn't listened to correctly if it was created in a separate transaction than the switched cell was listened on unless the Cell<Cell<T>>
had Sample
called on it before SwitchC
was called on it. Thus, this only affects FRP logic constructed without a surrounding transaction.
The reason for this bug is that SwitchC
uses SampleLazy
. Without a listener being attached to the resulting Cell<T>
from SwitchC
, SampleLazy
will not calculate the value for the initial inner cell to switch into being active until the "last" phase of the transaction. However, when the inner cell being created lazily uses Apply
(which Lift
also does), the Value
stream of the cell containing the function to apply is used. Value
uses a "snapshot stream" to ensure that it gets its value appropriately after the cell has finished all updates using Transaction.Prioritized
. But since the transaction has finished running all prioritized actions and is now in the "last" phase, the initial function is never set, and all further firings of the cell values involved in the Apply
will fail. Thus, no values will pass through the switched cell until a new (second) cell is switched in.
My solution to this problem was originally to simply run the prioritized action right away in Transaction.Prioritized
if the transaction has already finished running prioritized actions. In the second commit, I changed this to just add the action to the end of the lastQueue
. I'm not sure if that makes it "more right" or not, but it felt like it should be done that way.
Please let me know your thoughts and if this would have any unforeseen effects. I ran all tests and they passed and I verified that this new test (in CellTests
at the end of the file named TestLiftCellsInSwitchC
) is the only place where this situation arises that Transaction.Prioritized
is called after prioritized actions have been run, so I am fairly confident this is the right solution to this problem. Thanks!