Bug 903391: Evaluate both arguments in String.prototype.lastIndexOf. r=till

This commit is contained in:
André Bargull 2016-10-18 11:44:11 -07:00
Родитель 2c4a554595
Коммит 8e53c5e480
2 изменённых файлов: 54 добавлений и 20 удалений

Просмотреть файл

@ -1700,26 +1700,31 @@ LastIndexOfImpl(const TextChar* text, size_t textLen, const PatChar* pat, size_t
return -1;
}
// ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e
// 21.1.3.9 String.prototype.lastIndexOf ( searchString [ , position ] )
bool
js::str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedString textstr(cx, ToStringForStringFunction(cx, args.thisv()));
if (!textstr)
// Steps 1-2.
RootedString str(cx, ToStringForStringFunction(cx, args.thisv()));
if (!str)
return false;
RootedLinearString pat(cx, ArgToRootedString(cx, args, 0));
if (!pat)
// Step 3.
RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
if (!searchStr)
return false;
size_t textLen = textstr->length();
size_t patLen = pat->length();
int start = textLen - patLen; // Start searching here
if (start < 0) {
args.rval().setInt32(-1);
return true;
}
// Step 6.
size_t len = str->length();
// Step 8.
size_t searchLen = searchStr->length();
// Steps 4-5, 7.
int start = len - searchLen; // Start searching here
if (args.hasDefined(1)) {
if (args[1].isInt32()) {
int i = args[1].toInt32();
@ -1741,29 +1746,36 @@ js::str_lastIndexOf(JSContext* cx, unsigned argc, Value* vp)
}
}
if (patLen == 0) {
args.rval().setInt32(start);
if (searchLen > len) {
args.rval().setInt32(-1);
return true;
}
JSLinearString* text = textstr->ensureLinear(cx);
if (searchLen == 0) {
args.rval().setInt32(start);
return true;
}
MOZ_ASSERT(0 <= start && size_t(start) < len);
JSLinearString* text = str->ensureLinear(cx);
if (!text)
return false;
// Step 9.
int32_t res;
AutoCheckCannotGC nogc;
if (text->hasLatin1Chars()) {
const Latin1Char* textChars = text->latin1Chars(nogc);
if (pat->hasLatin1Chars())
res = LastIndexOfImpl(textChars, textLen, pat->latin1Chars(nogc), patLen, start);
if (searchStr->hasLatin1Chars())
res = LastIndexOfImpl(textChars, len, searchStr->latin1Chars(nogc), searchLen, start);
else
res = LastIndexOfImpl(textChars, textLen, pat->twoByteChars(nogc), patLen, start);
res = LastIndexOfImpl(textChars, len, searchStr->twoByteChars(nogc), searchLen, start);
} else {
const char16_t* textChars = text->twoByteChars(nogc);
if (pat->hasLatin1Chars())
res = LastIndexOfImpl(textChars, textLen, pat->latin1Chars(nogc), patLen, start);
if (searchStr->hasLatin1Chars())
res = LastIndexOfImpl(textChars, len, searchStr->latin1Chars(nogc), searchLen, start);
else
res = LastIndexOfImpl(textChars, textLen, pat->twoByteChars(nogc), patLen, start);
res = LastIndexOfImpl(textChars, len, searchStr->twoByteChars(nogc), searchLen, start);
}
args.rval().setInt32(res);

Просмотреть файл

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var str = "a";
var searchStr = "abc";
var position = new Object();
var valueOfCalled = false;
function positionValueOf() {
assertEq(valueOfCalled, false);
valueOfCalled = true;
return 0;
}
position.valueOf = positionValueOf;
var result = str.lastIndexOf(searchStr, position);
assertEq(result, -1);
assertEq(valueOfCalled, true);
if (typeof reportCompare == "function")
reportCompare(0, 0);