зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1026680 part 5 - Make escape work with Latin1 strings. r=njn
This commit is contained in:
Родитель
848442625f
Коммит
078d68703e
|
@ -8,3 +8,11 @@ assertEq(unescape(s), "a+ def\x00A0\u1200");
|
|||
// TwoByte
|
||||
s += "\u1200";
|
||||
assertEq(unescape(s), "a+ def\x00A0\u1200\u1200");
|
||||
|
||||
// Latin1
|
||||
s = toLatin1("abc \u00ff");
|
||||
assertEq(escape(s), "abc%20%FF");
|
||||
|
||||
// TwoByte
|
||||
s += "\u1200";
|
||||
assertEq(escape(s), "abc%20%FF%u1200");
|
||||
|
|
|
@ -113,18 +113,10 @@ str_encodeURI_Component(JSContext *cx, unsigned argc, Value *vp);
|
|||
|
||||
|
||||
/* ES5 B.2.1 */
|
||||
static bool
|
||||
str_escape(JSContext *cx, unsigned argc, Value *vp)
|
||||
template <typename CharT>
|
||||
static jschar *
|
||||
Escape(JSContext *cx, const CharT *chars, uint32_t length, uint32_t *newLengthOut)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSLinearString *str = ArgToRootedString(cx, args, 0);
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
uint32_t length = str->length();
|
||||
const jschar *chars = str->chars();
|
||||
|
||||
static const uint8_t shouldPassThrough[128] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
|
@ -137,14 +129,14 @@ str_escape(JSContext *cx, unsigned argc, Value *vp)
|
|||
};
|
||||
|
||||
/* Take a first pass and see how big the result string will need to be. */
|
||||
uint32_t newlength = length;
|
||||
uint32_t newLength = length;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
jschar ch = chars[i];
|
||||
if (ch < 128 && shouldPassThrough[ch])
|
||||
continue;
|
||||
|
||||
/* The character will be encoded as %XX or %uXXXX. */
|
||||
newlength += (ch < 256) ? 2 : 5;
|
||||
newLength += (ch < 256) ? 2 : 5;
|
||||
|
||||
/*
|
||||
* newlength is incremented by at most 5 on each iteration, so worst
|
||||
|
@ -154,9 +146,9 @@ str_escape(JSContext *cx, unsigned argc, Value *vp)
|
|||
"newlength must not overflow");
|
||||
}
|
||||
|
||||
ScopedJSFreePtr<jschar> newchars(cx->pod_malloc<jschar>(newlength + 1));
|
||||
if (!newchars)
|
||||
return false;
|
||||
jschar *newChars = cx->pod_malloc<jschar>(newLength + 1);
|
||||
if (!newChars)
|
||||
return nullptr;
|
||||
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
|
||||
|
@ -164,29 +156,56 @@ str_escape(JSContext *cx, unsigned argc, Value *vp)
|
|||
for (i = 0, ni = 0; i < length; i++) {
|
||||
jschar ch = chars[i];
|
||||
if (ch < 128 && shouldPassThrough[ch]) {
|
||||
newchars[ni++] = ch;
|
||||
newChars[ni++] = ch;
|
||||
} else if (ch < 256) {
|
||||
newchars[ni++] = '%';
|
||||
newchars[ni++] = digits[ch >> 4];
|
||||
newchars[ni++] = digits[ch & 0xF];
|
||||
newChars[ni++] = '%';
|
||||
newChars[ni++] = digits[ch >> 4];
|
||||
newChars[ni++] = digits[ch & 0xF];
|
||||
} else {
|
||||
newchars[ni++] = '%';
|
||||
newchars[ni++] = 'u';
|
||||
newchars[ni++] = digits[ch >> 12];
|
||||
newchars[ni++] = digits[(ch & 0xF00) >> 8];
|
||||
newchars[ni++] = digits[(ch & 0xF0) >> 4];
|
||||
newchars[ni++] = digits[ch & 0xF];
|
||||
newChars[ni++] = '%';
|
||||
newChars[ni++] = 'u';
|
||||
newChars[ni++] = digits[ch >> 12];
|
||||
newChars[ni++] = digits[(ch & 0xF00) >> 8];
|
||||
newChars[ni++] = digits[(ch & 0xF0) >> 4];
|
||||
newChars[ni++] = digits[ch & 0xF];
|
||||
}
|
||||
}
|
||||
JS_ASSERT(ni == newlength);
|
||||
newchars[newlength] = 0;
|
||||
JS_ASSERT(ni == newLength);
|
||||
newChars[newLength] = 0;
|
||||
|
||||
JSString *retstr = js_NewString<CanGC>(cx, newchars.get(), newlength);
|
||||
if (!retstr)
|
||||
*newLengthOut = newLength;
|
||||
return newChars;
|
||||
}
|
||||
|
||||
static bool
|
||||
str_escape(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
JSLinearString *str = ArgToRootedString(cx, args, 0);
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
newchars.forget();
|
||||
args.rval().setString(retstr);
|
||||
/* TODO: Once Latin1 strings are enabled, return a Latin1 string. */
|
||||
ScopedJSFreePtr<jschar> newChars;
|
||||
uint32_t newLength;
|
||||
if (str->hasLatin1Chars()) {
|
||||
AutoCheckCannotGC nogc;
|
||||
newChars = Escape(cx, str->latin1Chars(nogc), str->length(), &newLength);
|
||||
} else {
|
||||
AutoCheckCannotGC nogc;
|
||||
newChars = Escape(cx, str->twoByteChars(nogc), str->length(), &newLength);
|
||||
}
|
||||
|
||||
if (!newChars)
|
||||
return false;
|
||||
|
||||
JSString *res = js_NewString<CanGC>(cx, newChars.get(), newLength);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
newChars.forget();
|
||||
args.rval().setString(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче