| Index: sdk/lib/_internal/compiler/implementation/util/util.dart | 
| diff --git a/sdk/lib/_internal/compiler/implementation/util/util.dart b/sdk/lib/_internal/compiler/implementation/util/util.dart | 
| index 44fc305ef997ea0ce5304b27f1454f77785fd7ce..64194ea4d4c79f0db3550227497397912ccf5ab8 100644 | 
| --- a/sdk/lib/_internal/compiler/implementation/util/util.dart | 
| +++ b/sdk/lib/_internal/compiler/implementation/util/util.dart | 
| @@ -24,66 +24,52 @@ class SpannableAssertionFailure { | 
| String toString() => 'Compiler crashed: $message.'; | 
| } | 
|  | 
| -/// Writes the characters of [string] on [buffer].  The characters | 
| +/// Writes the characters of [iterator] on [buffer].  The characters | 
| /// are escaped as suitable for JavaScript and JSON.  [buffer] is | 
| /// anything which supports [:add:] and [:addCharCode:], for example, | 
| -/// [StringBuffer].  Note that JS supports \xnn and \unnnn whereas JSON only | 
| -/// supports the \unnnn notation.  Therefore we use the \unnnn notation. | 
| - | 
| -void writeJsonEscapedCharsOn(String string, buffer) { | 
| -  void addCodeUnitEscaped(CodeBuffer buffer, int code) { | 
| -    assert(code < 0x10000); | 
| -    buffer.add(r'\u'); | 
| -    if (code < 0x1000) { | 
| -      buffer.add('0'); | 
| -      if (code < 0x100) { | 
| -        buffer.add('0'); | 
| -        if (code < 0x10) { | 
| -          buffer.add('0'); | 
| -        } | 
| +/// [StringBuffer]. | 
| +void writeJsonEscapedCharsOn(Iterator<int> iterator, buffer, onError(code)) { | 
| +  while (iterator.hasNext) { | 
| +    int code = iterator.next(); | 
| +    if (identical(code, $SQ)) { | 
| +      buffer.add(r"\'"); | 
| +    } else if (identical(code, $LF)) { | 
| +      buffer.add(r'\n'); | 
| +    } else if (identical(code, $CR)) { | 
| +      buffer.add(r'\r'); | 
| +    } else if (identical(code, $LS)) { | 
| +      // This Unicode line terminator and $PS are invalid in JS string | 
| +      // literals. | 
| +      buffer.add(r'\u2028'); | 
| +    } else if (identical(code, $PS)) { | 
| +      buffer.add(r'\u2029'); | 
| +    } else if (identical(code, $BACKSLASH)) { | 
| +      buffer.add(r'\\'); | 
| +    } else { | 
| +      if (code > 0xffff) { | 
| +        if (onError != null) onError(code); | 
| +        throw 'Unhandled non-BMP character: ${code.toRadixString(16)}'; | 
| } | 
| -    } | 
| -    buffer.add(code.toRadixString(16)); | 
| -  } | 
| - | 
| -  void writeEscaped(String string, buffer) { | 
| -    for (int i = 0; i < string.length; i++) { | 
| -      int code = string.codeUnitAt(i); | 
| -      if (identical(code, $DQ)) { | 
| -        buffer.add(r'\"'); | 
| -      } else if (identical(code, $TAB)) { | 
| -        buffer.add(r'\t'); | 
| -      } else if (identical(code, $LF)) { | 
| -        buffer.add(r'\n'); | 
| -      } else if (identical(code, $CR)) { | 
| -        buffer.add(r'\r'); | 
| -      } else if (identical(code, $DEL)) { | 
| -        addCodeUnitEscaped(buffer, $DEL); | 
| -      } else if (identical(code, $LS)) { | 
| -        // This Unicode line terminator and $PS are invalid in JS string | 
| -        // literals. | 
| -        addCodeUnitEscaped(buffer, $LS);  // 0x2028. | 
| -      } else if (identical(code, $PS)) { | 
| -        addCodeUnitEscaped(buffer, $PS);  // 0x2029. | 
| -      } else if (identical(code, $BACKSLASH)) { | 
| -        buffer.add(r'\\'); | 
| -      } else { | 
| -        if (code < 0x20) { | 
| -          addCodeUnitEscaped(buffer, code); | 
| +      // TODO(lrn): Consider whether all codes above 0x7f really need to | 
| +      // be escaped. We build a Dart string here, so it should be a literal | 
| +      // stage that converts it to, e.g., UTF-8 for a JS interpreter. | 
| +      if (code < 0x20) { | 
| +        buffer.add(r'\x'); | 
| +        if (code < 0x10) buffer.add('0'); | 
| +        buffer.add(code.toRadixString(16)); | 
| +      } else if (code >= 0x80) { | 
| +        if (code < 0x100) { | 
| +          buffer.add(r'\x'); | 
| } else { | 
| -          buffer.addCharCode(code); | 
| +          buffer.add(r'\u'); | 
| +          if (code < 0x1000) { | 
| +            buffer.add('0'); | 
| +          } | 
| } | 
| +        buffer.add(code.toRadixString(16)); | 
| +      } else { | 
| +        buffer.addCharCode(code); | 
| } | 
| } | 
| } | 
| - | 
| -  for (int i = 0; i < string.length; i++) { | 
| -    int code = string.codeUnitAt(i); | 
| -    if (code < 0x20 || code == $DEL || code == $DQ || code == $LS || | 
| -        code == $PS || code == $BACKSLASH) { | 
| -      writeEscaped(string, buffer); | 
| -      return; | 
| -    } | 
| -  } | 
| -  buffer.add(string); | 
| } | 
|  |