watchCollection: Return correct oldCollection argument to listener

Fixes #2621.

At present, when watchCollection calls a registered listener, the oldCollection argument has the same value as
the newCollection argument. This does not accord with the API description: "The newCollection object is the newly modified data obtained from the obj expression and the oldCollection object is a copy of the former collection data.".

This fix caches the collection value correctly. It also includes some optimisations to avoid copy activity when the collection is unchanged.