Originally, combineLatest made an array or a dictionary to hold the latest values from each inner stream. It would modify that object if an inner stream changed, then dispatch the result.
Though this minimizes allocations, it also makes the resulting stream more difficult to reason about. Consider this example (taken from Tossable):
const locationOnDown$ = location$._debounce(whenDragIsActive$); const draggedLocation$ = draggable.value$.addedBy(locationOnDown$); // … spring.value$.subscribe(location$);
This looks like it takes the location when the drag started and adds it to the latest emission from draggable. Indeed, when Tossable used a NumericSpring, this is what it did. Because numbers are primitives, each emission from NumericSpring is distinct.
However, Point2DSpring uses combineLatest, which means that older emissions and current emissions all recycle the same object: if location$ is set by a Point2DSpring, locationOnDown$ can change even though whenDragIsActive$ hasn't dispatched. This is non-obvious and difficult to debug.
Therefore, I'm altering the behavior of combineLatest to always dispatch a new object. If this ever introduces a performance problem, we can revert this change (and introduce a _clone operator to replace it). However, I doubt that is worth either the technical complexity or the mental overhead.