anchor.diff:          charCodes.add(charCode);
         }
       }
  -    sb.write(needsEscape ? new String.fromCharCodes(charCodes) : s);
  -  }
  -
  -  void checkCycle(final object) {
  -    if (seen.contains(object)) {
  +    _sink.write(needsEscape ? new String.fromCharCodes(charCodes) : s);
  +  }
  +
  +  void checkCycle(object) {
  +    if (_seen.contains(object)) {
         throw new JsonCyclicError(object);
       }
  -    seen.add(object);
  -  }
  -
  -  void stringifyValue(final object) {
  +    _seen.add(object);
  +  }
  +
  +  void stringifyValue(object) {
       // Tries stringifying object directly. If it's not a simple value, List or
       // Map, call toJson() to get a custom representation and try serializing
       // that.
       if (!stringifyJsonValue(object)) {
         checkCycle(object);
         try {
  -        var customJson = toEncodable(object);
  +        var customJson = _toEncodable(object);
           if (!stringifyJsonValue(customJson)) {
             throw new JsonUnsupportedObjectError(object);
           }
  -        seen.remove(object);
  +        _seen.remove(object);
         } catch (e) {
           throw new JsonUnsupportedObjectError(object, cause: e);
         }
  
positive.code:    * Returns true if the value is one of these types, and false if not.
     * If a value is both a [List] and a [Map], it's serialized as a [List].
     */
    bool stringifyJsonValue(final object) {
      if (object is num) {
        if (!object.isFinite) return false;
        sink.write(numberToString(object));
        return true;
      } else if (identical(object, true)) {
        sink.write('true');
        return true;
      } else if (identical(object, false)) {
        sink.write('false');
         return true;
      } else if (object == null) {
        sink.write('null');
        return true;
      } else if (object is String) {
        sink.write('"');
        escape(sink, object);
        sink.write('"');
        return true;
      } else if (object is List) {
        checkCycle(object);
        List a = object;
        sink.write('[');
        if (a.length > 0) {
          stringifyValue(a[0]);
          for (int i = 1; i < a.length; i++) {
            sink.write(',');
            stringifyValue(a[i]);
          }
        }
        sink.write(']');
        seen.remove(object);
        return true;
      } else if (object is Map) {
        checkCycle(object);
        Map<String, Object> m = object;
        sink.write('{');
        bool first = true;
        m.forEach((String key, Object value) {
          if (!first) {
            sink.write(',"');
          } else {
            sink.write('"');
          }
          escape(sink, key);
          sink.write('":');
          stringifyValue(value);
          first = false;
        });
        sink.write('}');
        seen.remove(object);
        return true;
      } else {
        return false;
  
negative.code:   // ('0' + x) or ('a' + x - 10)
    static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x;
  
    void escape(String s) {
      final int length = s.length;
      bool needsEscape = false;
      final charCodes = new List<int>();
  