anchor.diff:     */
     final ResultDescriptor descriptor;
   
  -  InvalidatedResult(this.entry, this.descriptor);
  +  /**
  +   * The value of the result which was invalidated.
  +   */
  +  final Object value;
  +
  +  InvalidatedResult(this.entry, this.descriptor, this.value);
   
     @override
     String toString() => '$descriptor of ${entry.target}';
  +}
  +
  +/**
  + * A Stream-like interface, which broadcasts events synchronously.
  + * If a second event is fired while delivering a first event, then the second
  + * event will be delivered first, and then delivering of the first will be
  + * continued.
  + */
  +class ReentrantSynchronousStream<T> {
  +  final List<Function> listeners = <Function>[];
  +
  +  /**
  +   * Send the given [event] to the stream.
  +   */
  +  void add(T event) {
  +    List<Function> listeners = this.listeners.toList();
  +    for (Function listener in listeners) {
  +      listener(event);
  +    }
  +  }
  +
  +  /**
  +   * Listen for the events in this stream.
  +   * Note that if the [listener] fires a new event, then the [listener] will be
  +   * invoked again before returning from the [add] invocation.
  +   */
  +  void listen(void listener(T event)) {
  +    listeners.add(listener);
  +  }
   }
   
   /**
  
positive.code:    * should not be used for any other purpose.
     */
    Map<AnalysisTarget, CacheEntry> get map => _targetMap;
  
    /**
     * Return the stream that is notified when a value is invalidated.
     */
    Stream<InvalidatedResult> get onResultInvalidated =>
        _onResultInvalidated.stream;
  
    /**
     * Notifies the partition that the client is going to stop using it.
  
negative.code:   /**
     * The [StreamController] reporting [InvalidatedResult]s.
     */
    final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
        new ReentrantSynchronousStream<InvalidatedResult>();
  
    /**
     * Initialize a newly created cache to have the given [partitions]. The
  