Bug 1021209 - Make QuoteString support Latin1 strings. r=bhackett

This commit is contained in:
Jan de Mooij 2014-06-07 14:59:50 +02:00
parent 8b32cbeebf
commit 88da63623a
2 changed files with 40 additions and 29 deletions

View File

@ -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"');

View File

@ -795,7 +795,7 @@ js_DumpScriptDepth(JSContext *cx, JSScript *scriptArg, jsbytecode *pc)
}
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)
@ -1288,69 +1288,60 @@ const char js_EscapeMap[] = {
'\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 (!ok)
if (Sprint(sp, (quote && !(c >> 8)) ? "\\x%02X" : "\\u%04X", c) < 0)
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;
/*
@ -1363,6 +1354,19 @@ QuoteString(Sprinter *sp, JSString *str, uint32_t quote)
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)
{