anchor.diff:      }).bind(connection.onClose);
     }
   
  -  Stream<WipEvent> eventStream(String method, WipEventTransformer transformer) {
  +  Stream<T> eventStream<T>(String method, WipEventTransformer<T> transformer) {
       return _eventStreams.putIfAbsent(
         method,
         () => new StreamTransformer.fromHandlers(
  -            handleData: (WipEvent event, EventSink<WipEvent> sink) {
  +            handleData: (WipEvent event, EventSink<T> sink) {
                 if (event.method == method) {
                   sink.add(transformer(event));
                 }
  
positive.code:   Future<List<ChromeTab>> getTabs() async {
      var response = await getUrl('/json');
      var respBody = await utf8.decodeStream(response);
      List<Map<String, String>> data = jsonDecode(respBody);
      return data.map((m) => new ChromeTab(m)).toList();
    }
  
    Future<ChromeTab> getTab(bool accept(ChromeTab tab),
  
negative.code:   String toString() => 'WipResponse $id: $result';
  }
  
  typedef T WipEventTransformer<T>(WipEvent event);
  
  /// @optional
  const String optional = 'optional';
  