Chromium Code Reviews| Index: frog/leg/ssa/codegen.dart |
| diff --git a/frog/leg/ssa/codegen.dart b/frog/leg/ssa/codegen.dart |
| index 6a02fc44aea093949b1baf9a6e32d95ebc35efe4..5920a6a3e83edb06face6a85e932d0922d2896c4 100644 |
| --- a/frog/leg/ssa/codegen.dart |
| +++ b/frog/leg/ssa/codegen.dart |
| @@ -489,6 +489,102 @@ class SsaCodeGenerator implements HVisitor { |
| buffer.add(')'); |
| } |
| + /** |
| + * Write the contents of the quoted string to a [StringBuffer] in |
| + * a form that is valid as JavaScript string literal content. |
| + * The string is assumed quoted by [quote] characters. |
| + */ |
| + static void writeEscapedString(QuotedString string, |
| + StringBuffer buffer, |
| + int quote, |
| + void cancel(String reason)) { |
| + bool raw = string.quoting.raw; |
| + Iterator<int> iter = string.iterator(); |
|
ahe
2012/01/26 19:24:28
Do you think performance would suffer if this was
Lasse Reichstein Nielsen
2012/01/27 11:39:04
Absoleffinglutely. But I'll rename it anyway, just
|
| + while (iter.hasNext()) { |
| + int code = iter.next(); |
| + if (code === quote) { |
| + // We need to add a backslash before quotes, both in normal |
| + // and in raw strings. |
| + buffer.add(@'\'); |
| + buffer.add(code === $SQ ? "'" : '"'); |
| + } else if (code === $LF) { |
| + // Newlines in strings only occour in multiline strings. |
|
ahe
2012/01/26 19:24:28
occour -> occur
Lasse Reichstein Nielsen
2012/01/27 11:39:04
Done.
|
| + // They need to be written using escapes in JS.. |
|
ahe
2012/01/26 19:24:28
Extra .
Lasse Reichstein Nielsen
2012/01/27 11:39:04
Done.
|
| + assert(string.quoting.multiline); |
| + buffer.add(@'\n'); |
| + } else if (code === $CR) { |
| + assert(string.quoting.multiline); |
| + buffer.add(@'\r'); |
| + } else if (code === $LS) { |
| + // This Unicode line terminator and $PS are invalid in JS string |
| + // literals. |
| + buffer.add(@'\u2028'); |
| + } else if (code === $PS) { |
| + buffer.add(@'\u2029'); |
| + } else if (code !== $BACKSLASH) { |
| + buffer.add(new String.fromCharCodes([code])); |
| + } else if (raw) { |
| + buffer.add(@'\\'); |
| + } else { |
|
ahe
2012/01/26 19:24:28
For documentation, how about adding:
assert(code
Lasse Reichstein Nielsen
2012/01/27 11:39:04
Done.
|
| + code = iter.next(); |
| + switch (code) { |
| + case $u: |
| + buffer.add(@'\u'); |
| + code = iter.next(); |
| + if (code == $OPEN_CURLY_BRACKET) { |
| + int value = 0; |
| + code = iter.next(); |
| + do { |
| + value = value * 16 + hexDigitValue(code); |
| + code = iter.next(); |
| + } while (code !== $CLOSE_CURLY_BRACKET); |
| + if (code > 0xffff) { |
| + cancel("Unhandled non-BMP character: " + |
| + "U+${code.toRadixString(16)}"); |
| + } |
| + for (int i = 12; i >= 0; i -= 4) { |
| + buffer.add(((value >> i) & 0xf).toRadixString(16)); |
| + } |
| + } else { |
| + buffer.add(new String.fromCharCodes([code])); |
| + // Remaining three hex digits will be copied verbatim. |
| + } |
| + break; |
| + case $x: |
| + buffer.add(@'\x'); |
| + // The two hex digits will be copied verbatim. |
| + break; |
| + // Character escapes that identical in meaning in JS. |
|
karlklose
2012/01/27 09:11:59
that *are* identical
Lasse Reichstein Nielsen
2012/01/27 11:39:04
Good catch.
ahe
2012/01/27 12:12:37
You forgot to change it :-)
|
| + case $b: buffer.add(@'\b'); break; |
| + case $f: buffer.add(@'\f'); break; |
| + case $n: buffer.add(@'\n'); break; |
| + case $r: buffer.add(@'\r'); break; |
| + case $t: buffer.add(@'\t'); break; |
| + case $v: buffer.add(@'\v'); break; |
| + // Identity escapes that must be escaped in JS strings. |
| + case $BACKSLASH: buffer.add(@'\\'); break; |
| + case $LF: buffer.add(@'\n'); break; |
| + case $CR: buffer.add(@'\r'); break; |
| + case $LS: buffer.add(@'\u2028'); break; |
| + case $PS: buffer.add(@'\u2029'); break; |
| + // Quotes may or may not need the escape. |
| + case $SQ: |
| + case $DQ: |
| + // Only escape quotes if they match the generated string quotes. |
| + if (code == quote) buffer.add(@'\'); |
| + buffer.add(code === $SQ ? "'" : '"'); |
| + break; |
| + default: |
| + // All other escaped characters are identity escapes, |
| + // and don't need a backslash in JS. |
| + buffer.add(new String.fromCharCodes([code])); |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + |
| + |
| visitLiteral(HLiteral node) { |
| if (node.isLiteralNull()) { |
| buffer.add("(void 0)"); |
| @@ -496,12 +592,13 @@ class SsaCodeGenerator implements HVisitor { |
| buffer.add('(${node.value})'); |
| } else if (node.isLiteralString()) { |
| QuotedString string = node.value; |
| - String quote = string.quoteChar; |
| + StringQuoting quoting = string.quoting; |
| + String quote = quoting.quoteChar; |
| buffer.add(quote); |
| - string.writeEscaped(buffer, string.quoteCharCode, |
| - (String reason) { |
| - compiler.cancel(reason, instruction: node); |
| - }); |
| + writeEscapedString(string, buffer, quoting.quote, |
| + (String reason) { |
| + compiler.cancel(reason, instruction:node); |
| + }); |
| buffer.add(quote); |
| } else { |
| buffer.add(node.value); |