Bug 1054755 - Part 3: Use IsRegExp in String.prototype.{contains,startsWith,endsWith}. r=till

This commit is contained in:
Tooru Fujisawa 2015-04-01 18:34:03 +09:00
parent 1b51c39b7e
commit 4b0c48c327
2 changed files with 72 additions and 26 deletions

View File

@ -1508,7 +1508,7 @@ RopeMatch(JSContext* cx, JSRope* text, JSLinearString* pat, int* match)
return true;
}
/* ES6 20121026 draft 15.5.4.24. */
/* ES6 draft rc3 21.1.3.7. */
static bool
str_contains(JSContext* cx, unsigned argc, Value* vp)
{
@ -1520,11 +1520,23 @@ str_contains(JSContext* cx, unsigned argc, Value* vp)
return false;
// Steps 4 and 5
bool isRegExp;
if (!IsRegExp(cx, args.get(0), &isRegExp))
return false;
// Step 6
if (isRegExp) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INVALID_ARG_TYPE,
"first", "", "Regular Expression");
return false;
}
// Steps 7 and 8
RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
if (!searchStr)
return false;
// Steps 6 and 7
// Steps 9 and 10
uint32_t pos = 0;
if (args.hasDefined(1)) {
if (args[1].isInt32()) {
@ -1538,13 +1550,13 @@ str_contains(JSContext* cx, unsigned argc, Value* vp)
}
}
// Step 8
// Step 11
uint32_t textLen = str->length();
// Step 9
// Step 12
uint32_t start = Min(Max(pos, 0U), textLen);
// Steps 10 and 11
// Steps 13 and 14
JSLinearString* text = str->ensureLinear(cx);
if (!text)
return false;
@ -1720,7 +1732,7 @@ HasSubstringAt(JSLinearString* text, JSLinearString* pat, size_t start)
return EqualChars(pat->latin1Chars(nogc), textChars, patLen);
}
/* ES6 20131108 draft 21.1.3.18. */
/* ES6 draft rc3 21.1.3.18. */
bool
js::str_startsWith(JSContext* cx, unsigned argc, Value* vp)
{
@ -1731,19 +1743,24 @@ js::str_startsWith(JSContext* cx, unsigned argc, Value* vp)
if (!str)
return false;
// Step 4
if (args.get(0).isObject() && IsObjectWithClass(args[0], ESClass_RegExp, cx)) {
// Steps 4 and 5
bool isRegExp;
if (!IsRegExp(cx, args.get(0), &isRegExp))
return false;
// Step 6
if (isRegExp) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INVALID_ARG_TYPE,
"first", "", "Regular Expression");
return false;
}
// Steps 5 and 6
// Steps 7 and 8
RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
if (!searchStr)
return false;
// Steps 7 and 8
// Steps 9 and 10
uint32_t pos = 0;
if (args.hasDefined(1)) {
if (args[1].isInt32()) {
@ -1757,22 +1774,22 @@ js::str_startsWith(JSContext* cx, unsigned argc, Value* vp)
}
}
// Step 9
// Step 11
uint32_t textLen = str->length();
// Step 10
// Step 12
uint32_t start = Min(Max(pos, 0U), textLen);
// Step 11
// Step 13
uint32_t searchLen = searchStr->length();
// Step 12
// Step 14
if (searchLen + start < searchLen || searchLen + start > textLen) {
args.rval().setBoolean(false);
return true;
}
// Steps 13 and 14
// Steps 15 and 16
JSLinearString* text = str->ensureLinear(cx);
if (!text)
return false;
@ -1781,7 +1798,7 @@ js::str_startsWith(JSContext* cx, unsigned argc, Value* vp)
return true;
}
/* ES6 20131108 draft 21.1.3.7. */
/* ES6 draft rc3 21.1.3.6. */
static bool
str_endsWith(JSContext* cx, unsigned argc, Value* vp)
{
@ -1792,22 +1809,27 @@ str_endsWith(JSContext* cx, unsigned argc, Value* vp)
if (!str)
return false;
// Step 4
if (args.get(0).isObject() && IsObjectWithClass(args[0], ESClass_RegExp, cx)) {
// Steps 4 and 5
bool isRegExp;
if (!IsRegExp(cx, args.get(0), &isRegExp))
return false;
// Step 6
if (isRegExp) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INVALID_ARG_TYPE,
"first", "", "Regular Expression");
return false;
}
// Steps 5 and 6
// Steps 7 and 8
RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
if (!searchStr)
return false;
// Step 7
// Step 9
uint32_t textLen = str->length();
// Steps 8 and 9
// Steps 10 and 11
uint32_t pos = textLen;
if (args.hasDefined(1)) {
if (args[1].isInt32()) {
@ -1821,22 +1843,22 @@ str_endsWith(JSContext* cx, unsigned argc, Value* vp)
}
}
// Step 10
// Step 12
uint32_t end = Min(Max(pos, 0U), textLen);
// Step 11
// Step 13
uint32_t searchLen = searchStr->length();
// Step 13 (reordered)
// Step 15 (reordered)
if (searchLen > end) {
args.rval().setBoolean(false);
return true;
}
// Step 12
// Step 14
uint32_t start = end - searchLen;
// Steps 14 and 15
// Steps 16 and 17
JSLinearString* text = str->ensureLinear(cx);
if (!text)
return false;

View File

@ -0,0 +1,24 @@
var BUGNUMBER = 1054755;
var summary = 'String.prototype.{startsWith,endsWith,contains} should call IsRegExp.';
print(BUGNUMBER + ": " + summary);
for (var method of ["startsWith", "endsWith", "contains"]) {
for (var re of [/foo/, new RegExp()]) {
assertThrowsInstanceOf(() => "foo"[method](re), TypeError);
re[Symbol.match] = false;
"foo"[method](re);
}
for (var v1 of [true, 1, "bar", [], {}, Symbol.iterator]) {
assertThrowsInstanceOf(() => "foo"[method]({ [Symbol.match]: v1 }), TypeError);
}
for (var v2 of [false, 0, undefined, ""]) {
"foo"[method]({ [Symbol.match]: v2 });
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);