Bug 1025875 part 10 - Make array.join work with Latin1 strings. r=luke

--HG--
extra : rebase_source : e811a9ad5b5c8e46ad65554e55272fab95fef2cc
This commit is contained in:
Jan de Mooij 2014-06-17 16:54:13 +02:00
parent 531dbe80df
commit 372fb7e9d7
4 changed files with 50 additions and 29 deletions

View File

@ -0,0 +1,14 @@
var arrLatin1 = [toLatin1("abc1"), toLatin1("abc\u00A0")];
assertEq(arrLatin1.join(toLatin1("sep\u00ff")), "abc1sep\xFFabc\xA0");
var arrTwoByte = [toLatin1("abc2"), "def\u1200"];
assertEq(arrTwoByte.join(toLatin1("sep\u00fe")), "abc2sep\xFEdef\u1200");
assertEq(arrLatin1.join(toLatin1("-")), "abc1-abc\xA0");
assertEq(arrTwoByte.join(toLatin1("7")), "abc27def\u1200");
assertEq(arrLatin1.join("\u1200"), "abc1\u1200abc\xA0");
assertEq(arrTwoByte.join("\u1200"), "abc2\u1200def\u1200");
assertEq(arrLatin1.join("---\u1200"), "abc1---\u1200abc\xA0");
assertEq(arrTwoByte.join("---\u1200"), "abc2---\u1200def\u1200");

View File

@ -943,23 +943,22 @@ struct EmptySeparatorOp
bool operator()(JSContext *, StringBuffer &sb) { return true; }
};
template <typename CharT>
struct CharSeparatorOp
{
jschar sep;
explicit CharSeparatorOp(jschar sep) : sep(sep) {};
const CharT sep;
explicit CharSeparatorOp(CharT sep) : sep(sep) {};
bool operator()(JSContext *, StringBuffer &sb) { return sb.append(sep); }
};
struct StringSeparatorOp
{
const jschar *sepchars;
size_t seplen;
HandleLinearString sep;
StringSeparatorOp(const jschar *sepchars, size_t seplen)
: sepchars(sepchars), seplen(seplen) {};
explicit StringSeparatorOp(HandleLinearString sep) : sep(sep) {}
bool operator()(JSContext *cx, StringBuffer &sb) {
return sb.append(sepchars, seplen);
return sb.append(sep);
}
};
@ -1064,22 +1063,16 @@ ArrayJoin(JSContext *cx, CallArgs &args)
return false;
// Steps 4 and 5
RootedString sepstr(cx, nullptr);
const jschar *sepchars;
size_t seplen;
RootedLinearString sepstr(cx);
if (!Locale && args.hasDefined(0)) {
sepstr = ToString<CanGC>(cx, args[0]);
JSString *s = ToString<CanGC>(cx, args[0]);
if (!s)
return false;
sepstr = s->ensureLinear(cx);
if (!sepstr)
return false;
sepchars = sepstr->getChars(cx);
if (!sepchars)
return false;
seplen = sepstr->length();
} else {
HandlePropertyName comma = cx->names().comma;
sepstr = comma;
sepchars = comma->chars();
seplen = comma->length();
sepstr = cx->names().comma;
}
JS::Anchor<JSString*> anchor(sepstr);
@ -1100,9 +1093,12 @@ ArrayJoin(JSContext *cx, CallArgs &args)
}
StringBuffer sb(cx);
if (sepstr->hasTwoByteChars() && !sb.ensureTwoByteChars())
return false;
// The separator will be added |length - 1| times, reserve space for that
// so that we don't have to unnecessarily grow the buffer.
size_t seplen = sepstr->length();
if (length > 0 && !sb.reserve(seplen * (length - 1)))
return false;
@ -1112,11 +1108,18 @@ ArrayJoin(JSContext *cx, CallArgs &args)
if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
return false;
} else if (seplen == 1) {
CharSeparatorOp op(sepchars[0]);
if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
return false;
jschar c = sepstr->latin1OrTwoByteChar(0);
if (c <= JSString::MAX_LATIN1_CHAR) {
CharSeparatorOp<Latin1Char> op(c);
if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
return false;
} else {
CharSeparatorOp<jschar> op(c);
if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
return false;
}
} else {
StringSeparatorOp op(sepchars, seplen);
StringSeparatorOp op(sepstr);
if (!ArrayJoinKernel<Locale>(cx, op, obj, length, sb))
return false;
}

View File

@ -258,6 +258,8 @@ class JSString : public js::gc::BarrieredCell<JSString>
static const uint32_t MAX_LENGTH = JS_BIT(28) - 1;
static const JS::Latin1Char MAX_LATIN1_CHAR = 0xff;
/*
* Helper function to validate that a string of a given length is
* representable by a JSString. An allocation overflow is reported if false

View File

@ -67,8 +67,6 @@ class StringBuffer
return cb.ref<TwoByteCharBuffer>();
}
static const Latin1Char MaxLatin1Char = 0xff;
bool inflateChars();
public:
@ -107,7 +105,7 @@ class StringBuffer
inline bool append(const jschar c) {
if (isLatin1()) {
if (c <= MaxLatin1Char)
if (c <= JSString::MAX_LATIN1_CHAR)
return latin1Chars().append(Latin1Char(c));
if (!inflateChars())
return false;
@ -224,7 +222,7 @@ StringBuffer::append(const jschar *begin, const jschar *end)
while (true) {
if (begin >= end)
return true;
if (*begin > MaxLatin1Char)
if (*begin > JSString::MAX_LATIN1_CHAR)
break;
if (!latin1Chars().append(*begin))
return false;
@ -246,7 +244,9 @@ StringBuffer::append(JSLinearString *str)
if (!inflateChars())
return false;
}
return twoByteChars().append(str->twoByteChars(nogc), str->length());
return str->hasLatin1Chars()
? twoByteChars().append(str->latin1Chars(nogc), str->length())
: twoByteChars().append(str->twoByteChars(nogc), str->length());
}
inline bool
@ -261,7 +261,9 @@ StringBuffer::appendSubstring(JSLinearString *base, size_t off, size_t len)
if (!inflateChars())
return false;
}
return twoByteChars().append(base->twoByteChars(nogc) + off, len);
return base->hasLatin1Chars()
? twoByteChars().append(base->latin1Chars(nogc) + off, len)
: twoByteChars().append(base->twoByteChars(nogc) + off, len);
}
inline bool