| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library org_dartlang_compiler_util; | 5 library org_dartlang_compiler_util; |
| 6 | 6 |
| 7 import 'util_implementation.dart'; | 7 import 'util_implementation.dart'; |
| 8 import 'characters.dart'; | 8 import 'characters.dart'; |
| 9 | 9 |
| 10 part 'link.dart'; | 10 part 'link.dart'; |
| 11 | 11 |
| 12 /** | 12 /** |
| 13 * Tagging interface for classes from which source spans can be generated. | 13 * Tagging interface for classes from which source spans can be generated. |
| 14 */ | 14 */ |
| 15 // TODO(johnniwinther): Find a better name. | 15 // TODO(johnniwinther): Find a better name. |
| 16 // TODO(ahe): How about "Bolt"? | 16 // TODO(ahe): How about "Bolt"? |
| 17 abstract class Spannable {} | 17 abstract class Spannable {} |
| 18 | 18 |
| 19 class SpannableAssertionFailure { | 19 class SpannableAssertionFailure { |
| 20 final Spannable node; | 20 final Spannable node; |
| 21 final String message; | 21 final String message; |
| 22 SpannableAssertionFailure(this.node, this.message); | 22 SpannableAssertionFailure(this.node, this.message); |
| 23 | 23 |
| 24 String toString() => 'Compiler crashed: $message.'; | 24 String toString() => 'Compiler crashed: $message.'; |
| 25 } | 25 } |
| 26 | 26 |
| 27 /// Writes the characters of [string] on [buffer]. The characters | 27 /// Writes the characters of [iterator] on [buffer]. The characters |
| 28 /// are escaped as suitable for JavaScript and JSON. [buffer] is | 28 /// are escaped as suitable for JavaScript and JSON. [buffer] is |
| 29 /// anything which supports [:add:] and [:addCharCode:], for example, | 29 /// anything which supports [:add:] and [:addCharCode:], for example, |
| 30 /// [StringBuffer]. Note that JS supports \xnn and \unnnn whereas JSON only | 30 /// [StringBuffer]. |
| 31 /// supports the \unnnn notation. Therefore we use the \unnnn notation. | 31 void writeJsonEscapedCharsOn(Iterator<int> iterator, buffer, onError(code)) { |
| 32 | 32 while (iterator.hasNext) { |
| 33 void writeJsonEscapedCharsOn(String string, buffer) { | 33 int code = iterator.next(); |
| 34 void addCodeUnitEscaped(CodeBuffer buffer, int code) { | 34 if (identical(code, $SQ)) { |
| 35 assert(code < 0x10000); | 35 buffer.add(r"\'"); |
| 36 buffer.add(r'\u'); | 36 } else if (identical(code, $LF)) { |
| 37 if (code < 0x1000) { | 37 buffer.add(r'\n'); |
| 38 buffer.add('0'); | 38 } else if (identical(code, $CR)) { |
| 39 if (code < 0x100) { | 39 buffer.add(r'\r'); |
| 40 buffer.add('0'); | 40 } else if (identical(code, $LS)) { |
| 41 if (code < 0x10) { | 41 // This Unicode line terminator and $PS are invalid in JS string |
| 42 buffer.add('0'); | 42 // literals. |
| 43 buffer.add(r'\u2028'); |
| 44 } else if (identical(code, $PS)) { |
| 45 buffer.add(r'\u2029'); |
| 46 } else if (identical(code, $BACKSLASH)) { |
| 47 buffer.add(r'\\'); |
| 48 } else { |
| 49 if (code > 0xffff) { |
| 50 if (onError != null) onError(code); |
| 51 throw 'Unhandled non-BMP character: ${code.toRadixString(16)}'; |
| 52 } |
| 53 // TODO(lrn): Consider whether all codes above 0x7f really need to |
| 54 // be escaped. We build a Dart string here, so it should be a literal |
| 55 // stage that converts it to, e.g., UTF-8 for a JS interpreter. |
| 56 if (code < 0x20) { |
| 57 buffer.add(r'\x'); |
| 58 if (code < 0x10) buffer.add('0'); |
| 59 buffer.add(code.toRadixString(16)); |
| 60 } else if (code >= 0x80) { |
| 61 if (code < 0x100) { |
| 62 buffer.add(r'\x'); |
| 63 } else { |
| 64 buffer.add(r'\u'); |
| 65 if (code < 0x1000) { |
| 66 buffer.add('0'); |
| 67 } |
| 43 } | 68 } |
| 44 } | 69 buffer.add(code.toRadixString(16)); |
| 45 } | |
| 46 buffer.add(code.toRadixString(16)); | |
| 47 } | |
| 48 | |
| 49 void writeEscaped(String string, buffer) { | |
| 50 for (int i = 0; i < string.length; i++) { | |
| 51 int code = string.codeUnitAt(i); | |
| 52 if (identical(code, $DQ)) { | |
| 53 buffer.add(r'\"'); | |
| 54 } else if (identical(code, $TAB)) { | |
| 55 buffer.add(r'\t'); | |
| 56 } else if (identical(code, $LF)) { | |
| 57 buffer.add(r'\n'); | |
| 58 } else if (identical(code, $CR)) { | |
| 59 buffer.add(r'\r'); | |
| 60 } else if (identical(code, $DEL)) { | |
| 61 addCodeUnitEscaped(buffer, $DEL); | |
| 62 } else if (identical(code, $LS)) { | |
| 63 // This Unicode line terminator and $PS are invalid in JS string | |
| 64 // literals. | |
| 65 addCodeUnitEscaped(buffer, $LS); // 0x2028. | |
| 66 } else if (identical(code, $PS)) { | |
| 67 addCodeUnitEscaped(buffer, $PS); // 0x2029. | |
| 68 } else if (identical(code, $BACKSLASH)) { | |
| 69 buffer.add(r'\\'); | |
| 70 } else { | 70 } else { |
| 71 if (code < 0x20) { | 71 buffer.addCharCode(code); |
| 72 addCodeUnitEscaped(buffer, code); | |
| 73 } else { | |
| 74 buffer.addCharCode(code); | |
| 75 } | |
| 76 } | 72 } |
| 77 } | 73 } |
| 78 } | 74 } |
| 79 | |
| 80 for (int i = 0; i < string.length; i++) { | |
| 81 int code = string.codeUnitAt(i); | |
| 82 if (code < 0x20 || code == $DEL || code == $DQ || code == $LS || | |
| 83 code == $PS || code == $BACKSLASH) { | |
| 84 writeEscaped(string, buffer); | |
| 85 return; | |
| 86 } | |
| 87 } | |
| 88 buffer.add(string); | |
| 89 } | 75 } |
| OLD | NEW |