зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1024518 part 2 - Make RegExp flags parser handle latin1 strings and add tests. r=bhackett
This commit is contained in:
Родитель
8a12913383
Коммит
ec6e1dc9bb
|
@ -0,0 +1,15 @@
|
|||
// Latin1
|
||||
var re = new RegExp(toLatin1("foo[bB]a\\r"), toLatin1("im"));
|
||||
assertEq(isLatin1(re.source), true);
|
||||
assertEq(re.source, "foo[bB]a\\r");
|
||||
assertEq(re.multiline, true);
|
||||
assertEq(re.ignoreCase, true);
|
||||
assertEq(re.sticky, false);
|
||||
|
||||
// TwoByte
|
||||
re = new RegExp("foo[bB]a\\r\u1200", "im");
|
||||
assertEq(isLatin1(re.source), false);
|
||||
assertEq(re.source, "foo[bB]a\\r\u1200");
|
||||
assertEq(re.multiline, true);
|
||||
assertEq(re.ignoreCase, true);
|
||||
assertEq(re.sticky, false);
|
|
@ -1062,40 +1062,76 @@ js::CloneRegExpObject(JSContext *cx, JSObject *obj_)
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool
|
||||
HandleRegExpFlag(RegExpFlag flag, RegExpFlag *flags)
|
||||
{
|
||||
if (*flags & flag)
|
||||
return false;
|
||||
*flags = RegExpFlag(*flags | flag);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static size_t
|
||||
ParseRegExpFlags(const CharT *chars, size_t length, RegExpFlag *flagsOut, jschar *lastParsedOut)
|
||||
{
|
||||
*flagsOut = RegExpFlag(0);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
*lastParsedOut = chars[i];
|
||||
switch (chars[i]) {
|
||||
case 'i':
|
||||
if (!HandleRegExpFlag(IgnoreCaseFlag, flagsOut))
|
||||
return false;
|
||||
break;
|
||||
case 'g':
|
||||
if (!HandleRegExpFlag(GlobalFlag, flagsOut))
|
||||
return false;
|
||||
break;
|
||||
case 'm':
|
||||
if (!HandleRegExpFlag(MultilineFlag, flagsOut))
|
||||
return false;
|
||||
break;
|
||||
case 'y':
|
||||
if (!HandleRegExpFlag(StickyFlag, flagsOut))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
|
||||
{
|
||||
size_t n = flagStr->length();
|
||||
const jschar *s = flagStr->getChars(cx);
|
||||
if (!s)
|
||||
JSLinearString *linear = flagStr->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return false;
|
||||
|
||||
*flagsOut = RegExpFlag(0);
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
#define HANDLE_FLAG(name_) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (*flagsOut & (name_)) \
|
||||
goto bad_flag; \
|
||||
*flagsOut = RegExpFlag(*flagsOut | (name_)); \
|
||||
JS_END_MACRO
|
||||
switch (s[i]) {
|
||||
case 'i': HANDLE_FLAG(IgnoreCaseFlag); break;
|
||||
case 'g': HANDLE_FLAG(GlobalFlag); break;
|
||||
case 'm': HANDLE_FLAG(MultilineFlag); break;
|
||||
case 'y': HANDLE_FLAG(StickyFlag); break;
|
||||
default:
|
||||
bad_flag:
|
||||
{
|
||||
size_t len = linear->length();
|
||||
|
||||
bool ok;
|
||||
jschar lastParsed;
|
||||
if (linear->hasLatin1Chars()) {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
ok = ::ParseRegExpFlags(linear->latin1Chars(nogc), len, flagsOut, &lastParsed);
|
||||
} else {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
ok = ::ParseRegExpFlags(linear->twoByteChars(nogc), len, flagsOut, &lastParsed);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
char charBuf[2];
|
||||
charBuf[0] = char(s[i]);
|
||||
charBuf[0] = char(lastParsed);
|
||||
charBuf[1] = '\0';
|
||||
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
|
||||
JSMSG_BAD_REGEXP_FLAG, charBuf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#undef HANDLE_FLAG
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче