anchor.diff:              try {
                 matchesTest = zone.runUnary(test, asyncError.error);
               } catch (e, s) {
  -              listenerValueOrError = identical(asyncError.error, e) ?
  -                  asyncError : new AsyncError(e, s);
  -              listenerHasValue = false;
  +              listenerValueOrError = identical(asyncError.error, e)
  +                  ? asyncError
  +                  : new AsyncError(e, s);
  +              listenerHasError = true;
                 return;
               }
             }
  
positive.code:             } else {
                listenerValueOrError = new AsyncError(e, s);
              }
              listenerHasValue = false;
              return;
            }
            if (completeResult is Future) {
              _Future result = listener.result;
              result._isChained = true;
              isPropagationAborted = true;
              completeResult.then((ignored) {
                _propagateToListeners(source, new _FutureListener.chain(result));
              }, onError: (error, [stackTrace]) {
                // When there is an error, we have to make the error the new
                // result of the current listener.
                if (completeResult is! _Future) {
                  // This should be a rare case.
                  completeResult = new _Future();
                  completeResult._setError(error, stackTrace);
                }
                _propagateToListeners(completeResult,
                                      new _FutureListener.chain(result));
              });
            }
          }
  
          if (!hasError) {
            if (listener.handlesValue) {
              listenerHasValue = handleValueCallback();
            }
          } else {
            handleError();
          }
          if (listener.handlesComplete) {
            handleWhenCompleteCallback();
          }
          // If we changed zone, oldZone will not be null.
          if (oldZone != null) Zone._leave(oldZone);
  
          if (isPropagationAborted) return;
          // If the listener's value is a future we need to chain it. Note that
          // this can only happen if there is a callback. Since 'is' checks
          // can be expensive, we're trying to avoid it.
          if (listenerHasValue &&
              !identical(sourceValue, listenerValueOrError) &&
              listenerValueOrError is Future) {
            Future chainSource = listenerValueOrError;
            // Shortcut if the chain-source is already completed. Just continue
            // the loop.
  
negative.code:     assert(source is _Future);
  
      // Mark the target as chained (and as such half-completed).
      target._setChained();
      _FutureListener listener = new _FutureListener.chain(target);
      if (source._isComplete) {
        _propagateToListeners(source, listener);
  