зеркало из https://github.com/mozilla/pjs.git
Fix regexp match pair end-index == -1 assumption. (r=dmandelin, a=blocker b=605754)
--HG-- extra : rebase_source : a4a73855736671e4dae8264522ce26a3505ab800
This commit is contained in:
Родитель
b659ccd1b7
Коммит
de67205f5f
|
@ -0,0 +1,2 @@
|
|||
var result = "foobarbaz".replace(/foo(bar)?bar/, "$1");
|
||||
assertEq(result, "baz");
|
|
@ -124,7 +124,9 @@ class RegExpStatics
|
|||
JS_ASSERT(matchPairsInput);
|
||||
size_t mpiLen = matchPairsInput->length();
|
||||
|
||||
/* Both members of the first pair must be non-negative. */
|
||||
JS_ASSERT(pairIsPresent(0));
|
||||
JS_ASSERT(get(0, 1) >= 0);
|
||||
|
||||
/* Present pairs must be valid. */
|
||||
for (size_t i = 0; i < pairCount(); ++i) {
|
||||
|
@ -137,6 +139,19 @@ class RegExpStatics
|
|||
#endif
|
||||
}
|
||||
|
||||
bool pairIsPresent(size_t pairNum) const {
|
||||
return getCrash(pairNum, 0) >= 0;
|
||||
}
|
||||
|
||||
/* Precondition: paren is present. */
|
||||
size_t getParenLength(size_t parenNum) const {
|
||||
size_t pairNum = parenNum + 1;
|
||||
if (pairCountCrash() <= pairNum)
|
||||
return 0;
|
||||
JS_CRASH_UNLESS(pairIsPresent(pairNum));
|
||||
return getCrash(pairNum, 1) - getCrash(pairNum, 0);
|
||||
}
|
||||
|
||||
int get(size_t pairNum, bool which) const {
|
||||
JS_ASSERT(pairNum < pairCount());
|
||||
return matchPairs[2 * pairNum + which];
|
||||
|
@ -168,10 +183,6 @@ class RegExpStatics
|
|||
|
||||
/* Mutators. */
|
||||
|
||||
/*
|
||||
* The inputOffset parameter is added to the present (i.e. non-negative) match items to emulate
|
||||
* sticky mode.
|
||||
*/
|
||||
bool updateFromMatch(JSContext *cx, JSString *input, int *buf, size_t matchItemCount) {
|
||||
aboutToWrite();
|
||||
pendingInput = input;
|
||||
|
@ -204,8 +215,6 @@ class RegExpStatics
|
|||
matchPairs.clear();
|
||||
}
|
||||
|
||||
bool pairIsPresent(size_t pairNum) { return get(0, 0) != -1; }
|
||||
|
||||
/* Corresponds to JSAPI functionality to set the pending RegExp input. */
|
||||
void reset(JSString *newInput, bool newMultiline) {
|
||||
aboutToWrite();
|
||||
|
@ -238,12 +247,15 @@ class RegExpStatics
|
|||
return size_t(limit);
|
||||
}
|
||||
|
||||
/* Returns whether results for a non-empty match are present. */
|
||||
bool matched() const {
|
||||
JS_ASSERT(pairCount() > 0);
|
||||
JS_ASSERT_IF(get(0, 1) == -1, get(1, 1) == -1);
|
||||
return get(0, 1) - get(0, 0) > 0;
|
||||
}
|
||||
|
||||
size_t getParenCount() const {
|
||||
/* The first pair is the whole match. */
|
||||
JS_ASSERT(pairCount() > 0);
|
||||
return pairCount() - 1;
|
||||
}
|
||||
|
@ -255,12 +267,6 @@ class RegExpStatics
|
|||
JS_CALL_STRING_TRACER(trc, matchPairsInput, "res->matchPairsInput");
|
||||
}
|
||||
|
||||
size_t getParenLength(size_t parenNum) const {
|
||||
if (pairCountCrash() <= parenNum + 1)
|
||||
return 0;
|
||||
return getCrash(parenNum + 1, 1) - getCrash(parenNum + 1, 0);
|
||||
}
|
||||
|
||||
/* Value creators. */
|
||||
|
||||
bool createPendingInput(JSContext *cx, Value *out) const;
|
||||
|
@ -275,6 +281,7 @@ class RegExpStatics
|
|||
|
||||
/* Substring creators. */
|
||||
|
||||
/* @param num Zero-indexed paren number (i.e. $1 is 0). */
|
||||
void getParen(size_t num, JSSubString *out) const;
|
||||
void getLastMatch(JSSubString *out) const;
|
||||
void getLastParen(JSSubString *out) const;
|
||||
|
|
|
@ -265,7 +265,6 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
|
|||
} else {
|
||||
/* Missing parenthesized match. */
|
||||
JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
|
||||
JS_ASSERT(start == end && end == -1);
|
||||
if (!builder.append(INT_TO_JSID(i / 2), UndefinedValue()))
|
||||
return NULL;
|
||||
}
|
||||
|
@ -582,11 +581,11 @@ RegExpStatics::createLastParen(JSContext *cx, Value *out) const
|
|||
int start = get(num, 0);
|
||||
int end = get(num, 1);
|
||||
if (start == -1) {
|
||||
JS_ASSERT(end == -1);
|
||||
out->setString(cx->runtime->emptyString);
|
||||
return true;
|
||||
}
|
||||
JS_ASSERT(start >= 0 && end >= 0);
|
||||
JS_ASSERT(end >= start);
|
||||
return createDependent(cx, start, end, out);
|
||||
}
|
||||
|
||||
|
@ -621,7 +620,12 @@ RegExpStatics::createRightContext(JSContext *cx, Value *out) const
|
|||
inline void
|
||||
RegExpStatics::getParen(size_t num, JSSubString *out) const
|
||||
{
|
||||
out->chars = matchPairsInput->chars() + getCrash(num + 1, 0);
|
||||
size_t pairNum = num + 1;
|
||||
if (!pairIsPresent(pairNum)) {
|
||||
*out = js_EmptySubString;
|
||||
return;
|
||||
}
|
||||
out->chars = matchPairsInput->chars() + getCrash(pairNum, 0);
|
||||
out->length = getParenLength(num);
|
||||
}
|
||||
|
||||
|
@ -641,14 +645,12 @@ RegExpStatics::getLastMatch(JSSubString *out) const
|
|||
inline void
|
||||
RegExpStatics::getLastParen(JSSubString *out) const
|
||||
{
|
||||
if (!pairCountCrash()) {
|
||||
size_t parenCount = getParenCount();
|
||||
if (!parenCount) {
|
||||
*out = js_EmptySubString;
|
||||
return;
|
||||
}
|
||||
size_t num = pairCount() - 1;
|
||||
out->chars = matchPairsInput->chars() + getCrash(num, 0);
|
||||
JS_CRASH_UNLESS(getCrash(num, 1) >= get(num, 0));
|
||||
out->length = get(num, 1) - get(num, 0);
|
||||
getParen(parenCount - 1, out);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
Загрузка…
Ссылка в новой задаче