Bug 1021209 - Make QuoteString support Latin1 strings. r=bhackett
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 07 Jun 2014 14:59:50 +0200
changeset 206615 b68a8421c642590e7b5df2ec7502016a504f4721
parent 206614 0ea62f66f109388f7ba55ccdf7953ef95ac61629
child 206616 cd4218cd70f90a720505dfa4b88314598bc8c281
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1021209
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1021209 - Make QuoteString support Latin1 strings. r=bhackett
js/src/jit-test/tests/latin1/quote.js
js/src/jsopcode.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/quote.js
@@ -0,0 +1,7 @@
+var s = toLatin1('Abc1234"\'\t987\u00ff');
+assertEq(s.toSource(), '(new String("Abc1234\\"\'\\t987\\xFF"))');
+assertEq(s.quote(), '"Abc1234\\"\'\\t987\\xFF"');
+
+s = 'Abc1234"\'\t\u1200987\u00ff';
+assertEq(s.toSource(), '(new String("Abc1234\\"\'\\t\\u1200987\\xFF"))');
+assertEq(s.quote(), '"Abc1234\\"\'\\t\\u1200987\\xFF"');
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -790,17 +790,17 @@ js_DumpScriptDepth(JSContext *cx, JSScri
         return false;
     RootedScript script(cx, scriptArg);
     bool ok = js_DisassembleAtPC(cx, script, true, pc, true, &sprinter);
     fprintf(stdout, "%s", sprinter.string());
     return ok;
 }
 
 static char *
-QuoteString(Sprinter *sp, JSString *str, uint32_t quote);
+QuoteString(Sprinter *sp, JSString *str, jschar quote);
 
 static bool
 ToDisassemblySource(JSContext *cx, HandleValue v, JSAutoByteString *bytes)
 {
     if (v.isString()) {
         Sprinter sprinter(cx);
         if (!sprinter.init())
             return false;
@@ -1283,91 +1283,95 @@ const char js_EscapeMap[] = {
     '\t', 't',
     '\v', 'v',
     '"',  '"',
     '\'', '\'',
     '\\', '\\',
     '\0'
 };
 
-#define DONT_ESCAPE     0x10000
-
+template <typename CharT>
 static char *
-QuoteString(Sprinter *sp, JSString *str, uint32_t quote)
+QuoteString(Sprinter *sp, const CharT *s, size_t length, jschar quote)
 {
     /* Sample off first for later return value pointer computation. */
-    bool dontEscape = (quote & DONT_ESCAPE) != 0;
-    jschar qc = (jschar) quote;
     ptrdiff_t offset = sp->getOffset();
-    if (qc && Sprint(sp, "%c", (char)qc) < 0)
+
+    if (quote && Sprint(sp, "%c", char(quote)) < 0)
         return nullptr;
 
-    const jschar *s = str->getChars(sp->context);
-    if (!s)
-        return nullptr;
-    const jschar *z = s + str->length();
+    const CharT *end = s + length;
 
-    /* Loop control variables: z points at end of string sentinel. */
-    for (const jschar *t = s; t < z; s = ++t) {
+    /* Loop control variables: end points at end of string sentinel. */
+    for (const CharT *t = s; t < end; s = ++t) {
         /* Move t forward from s past un-quote-worthy characters. */
         jschar c = *t;
-        while (c < 127 && isprint(c) && c != qc && c != '\\' && c != '\t') {
+        while (c < 127 && isprint(c) && c != quote && c != '\\' && c != '\t') {
             c = *++t;
-            if (t == z)
+            if (t == end)
                 break;
         }
 
         {
             ptrdiff_t len = t - s;
             ptrdiff_t base = sp->getOffset();
-            char *bp = sp->reserve(len);
-            if (!bp)
+            if (!sp->reserve(len))
                 return nullptr;
 
             for (ptrdiff_t i = 0; i < len; ++i)
-                (*sp)[base + i] = (char) *s++;
+                (*sp)[base + i] = char(*s++);
             (*sp)[base + len] = 0;
         }
 
-        if (t == z)
+        if (t == end)
             break;
 
         /* Use js_EscapeMap, \u, or \x only if necessary. */
-        bool ok;
-        const char *e;
-        if (!(c >> 8) && c != 0 && (e = strchr(js_EscapeMap, (int)c)) != nullptr) {
-            ok = dontEscape
-                 ? Sprint(sp, "%c", (char)c) >= 0
-                 : Sprint(sp, "\\%c", e[1]) >= 0;
+        const char *escape;
+        if (!(c >> 8) && c != 0 && (escape = strchr(js_EscapeMap, int(c))) != nullptr) {
+            if (Sprint(sp, "\\%c", escape[1]) < 0)
+                return nullptr;
         } else {
             /*
              * Use \x only if the high byte is 0 and we're in a quoted string,
              * because ECMA-262 allows only \u, not \x, in Unicode identifiers
              * (see bug 621814).
              */
-            ok = Sprint(sp, (qc && !(c >> 8)) ? "\\x%02X" : "\\u%04X", c) >= 0;
+            if (Sprint(sp, (quote && !(c >> 8)) ? "\\x%02X" : "\\u%04X", c) < 0)
+                return nullptr;
         }
-        if (!ok)
-            return nullptr;
     }
 
     /* Sprint the closing quote and return the quoted string. */
-    if (qc && Sprint(sp, "%c", (char)qc) < 0)
+    if (quote && Sprint(sp, "%c", char(quote)) < 0)
         return nullptr;
 
     /*
      * If we haven't Sprint'd anything yet, Sprint an empty string so that
      * the return below gives a valid result.
      */
     if (offset == sp->getOffset() && Sprint(sp, "") < 0)
         return nullptr;
 
     return sp->stringAt(offset);
 }
 
+static char *
+QuoteString(Sprinter *sp, JSString *str, jschar quote)
+{
+    JSLinearString *linear = str->ensureLinear(sp->context);
+    if (!linear)
+        return nullptr;
+
+    AutoCheckCannotGC nogc;
+    return linear->hasLatin1Chars()
+           ? QuoteString(sp, linear->latin1Chars(nogc), linear->length(), quote)
+           : QuoteString(sp, linear->twoByteChars(nogc), linear->length(), quote);
+}
+
 JSString *
 js_QuoteString(ExclusiveContext *cx, JSString *str, jschar quote)
 {
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return nullptr;
     char *bytes = QuoteString(&sprinter, str, quote);
     if (!bytes)