             # nothing to do
             return
         v = []
+        oldest = undefined
         for x in patches
             if x? and (not @_times[x.time - 0] or (x.snapshot? and not @_snapshot_times[x.time - 0]))
                 v.push(x)
                 @_times[x.time - 0] = true
+                if not oldest? or oldest > x.time
+                    oldest = x.time
                 if x.snapshot?
                     @_snapshot_times[x.time - 0] = true
                     # WARNING: again, assuming patch times are unique here.
                     @_patches = (y for y in @_patches when y.time - 0 != x.time - 0)
-        if @_cache?
-            # if any patch introduced is as old as cached result (but
-            # newer than latest snapshot),
-            # then clear cache, since can't build on it
-            for x in v
-                if x.time - 0 <= @_cache.time - 0
-                    delete @_cache
-                    break
+        if oldest?
+            @_cache.invalidate(oldest)
+
         # this is O(n*log(n)) where n is the length of @_patches and patches;
         # better would be an insertion sort which would be O(m*log(n)) where m=patches.length...
         if v.length > 0

                        break
            # Apply each of the patches we need to get from
            # value (the last snapshot) to time.
            for i in [start...@_patches.length]
                x = @_patches[i]
                if time? and x.time > time
                    # Done -- no more patches need to be applied
                    break
                # Apply a patch to move us forward.
                #console.log("applying patch #{i}")
                value = apply_patch(x.patch, value)[0]
                if not time?
                    # We will save the results of applying
                    # all these patches in our local cache.
                    cache_time = x.time

        if cache_time
            # update the cache with our new known value
            @_cache = {time:cache_time, value:value, start:@_patches.length}

        #console.log("value: time=#{new Date() - start_time}")
        return value

    # integer index of user who made the edit at given point in time (or undefined)


    ###
    value: Return the value of the string at the given (optional)
    point in time.  If the optional time is given, only include patches up
    to (and including) the given time; otherwise, return current value.
    ###
    value: (time) =>
        #start_time = new Date()
