зеркало из 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);
|
JS_ASSERT(matchPairsInput);
|
||||||
size_t mpiLen = matchPairsInput->length();
|
size_t mpiLen = matchPairsInput->length();
|
||||||
|
|
||||||
|
/* Both members of the first pair must be non-negative. */
|
||||||
JS_ASSERT(pairIsPresent(0));
|
JS_ASSERT(pairIsPresent(0));
|
||||||
|
JS_ASSERT(get(0, 1) >= 0);
|
||||||
|
|
||||||
/* Present pairs must be valid. */
|
/* Present pairs must be valid. */
|
||||||
for (size_t i = 0; i < pairCount(); ++i) {
|
for (size_t i = 0; i < pairCount(); ++i) {
|
||||||
|
@ -137,6 +139,19 @@ class RegExpStatics
|
||||||
#endif
|
#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 {
|
int get(size_t pairNum, bool which) const {
|
||||||
JS_ASSERT(pairNum < pairCount());
|
JS_ASSERT(pairNum < pairCount());
|
||||||
return matchPairs[2 * pairNum + which];
|
return matchPairs[2 * pairNum + which];
|
||||||
|
@ -168,10 +183,6 @@ class RegExpStatics
|
||||||
|
|
||||||
/* Mutators. */
|
/* 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) {
|
bool updateFromMatch(JSContext *cx, JSString *input, int *buf, size_t matchItemCount) {
|
||||||
aboutToWrite();
|
aboutToWrite();
|
||||||
pendingInput = input;
|
pendingInput = input;
|
||||||
|
@ -204,8 +215,6 @@ class RegExpStatics
|
||||||
matchPairs.clear();
|
matchPairs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pairIsPresent(size_t pairNum) { return get(0, 0) != -1; }
|
|
||||||
|
|
||||||
/* Corresponds to JSAPI functionality to set the pending RegExp input. */
|
/* Corresponds to JSAPI functionality to set the pending RegExp input. */
|
||||||
void reset(JSString *newInput, bool newMultiline) {
|
void reset(JSString *newInput, bool newMultiline) {
|
||||||
aboutToWrite();
|
aboutToWrite();
|
||||||
|
@ -238,12 +247,15 @@ class RegExpStatics
|
||||||
return size_t(limit);
|
return size_t(limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns whether results for a non-empty match are present. */
|
||||||
bool matched() const {
|
bool matched() const {
|
||||||
JS_ASSERT(pairCount() > 0);
|
JS_ASSERT(pairCount() > 0);
|
||||||
|
JS_ASSERT_IF(get(0, 1) == -1, get(1, 1) == -1);
|
||||||
return get(0, 1) - get(0, 0) > 0;
|
return get(0, 1) - get(0, 0) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getParenCount() const {
|
size_t getParenCount() const {
|
||||||
|
/* The first pair is the whole match. */
|
||||||
JS_ASSERT(pairCount() > 0);
|
JS_ASSERT(pairCount() > 0);
|
||||||
return pairCount() - 1;
|
return pairCount() - 1;
|
||||||
}
|
}
|
||||||
|
@ -255,12 +267,6 @@ class RegExpStatics
|
||||||
JS_CALL_STRING_TRACER(trc, matchPairsInput, "res->matchPairsInput");
|
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. */
|
/* Value creators. */
|
||||||
|
|
||||||
bool createPendingInput(JSContext *cx, Value *out) const;
|
bool createPendingInput(JSContext *cx, Value *out) const;
|
||||||
|
@ -275,6 +281,7 @@ class RegExpStatics
|
||||||
|
|
||||||
/* Substring creators. */
|
/* Substring creators. */
|
||||||
|
|
||||||
|
/* @param num Zero-indexed paren number (i.e. $1 is 0). */
|
||||||
void getParen(size_t num, JSSubString *out) const;
|
void getParen(size_t num, JSSubString *out) const;
|
||||||
void getLastMatch(JSSubString *out) const;
|
void getLastMatch(JSSubString *out) const;
|
||||||
void getLastParen(JSSubString *out) const;
|
void getLastParen(JSSubString *out) const;
|
||||||
|
|
|
@ -265,7 +265,6 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
|
||||||
} else {
|
} else {
|
||||||
/* Missing parenthesized match. */
|
/* Missing parenthesized match. */
|
||||||
JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
|
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()))
|
if (!builder.append(INT_TO_JSID(i / 2), UndefinedValue()))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -582,11 +581,11 @@ RegExpStatics::createLastParen(JSContext *cx, Value *out) const
|
||||||
int start = get(num, 0);
|
int start = get(num, 0);
|
||||||
int end = get(num, 1);
|
int end = get(num, 1);
|
||||||
if (start == -1) {
|
if (start == -1) {
|
||||||
JS_ASSERT(end == -1);
|
|
||||||
out->setString(cx->runtime->emptyString);
|
out->setString(cx->runtime->emptyString);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
JS_ASSERT(start >= 0 && end >= 0);
|
JS_ASSERT(start >= 0 && end >= 0);
|
||||||
|
JS_ASSERT(end >= start);
|
||||||
return createDependent(cx, start, end, out);
|
return createDependent(cx, start, end, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,7 +620,12 @@ RegExpStatics::createRightContext(JSContext *cx, Value *out) const
|
||||||
inline void
|
inline void
|
||||||
RegExpStatics::getParen(size_t num, JSSubString *out) const
|
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);
|
out->length = getParenLength(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,14 +645,12 @@ RegExpStatics::getLastMatch(JSSubString *out) const
|
||||||
inline void
|
inline void
|
||||||
RegExpStatics::getLastParen(JSSubString *out) const
|
RegExpStatics::getLastParen(JSSubString *out) const
|
||||||
{
|
{
|
||||||
if (!pairCountCrash()) {
|
size_t parenCount = getParenCount();
|
||||||
|
if (!parenCount) {
|
||||||
*out = js_EmptySubString;
|
*out = js_EmptySubString;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t num = pairCount() - 1;
|
getParen(parenCount - 1, out);
|
||||||
out->chars = matchPairsInput->chars() + getCrash(num, 0);
|
|
||||||
JS_CRASH_UNLESS(getCrash(num, 1) >= get(num, 0));
|
|
||||||
out->length = get(num, 1) - get(num, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
|
Загрузка…
Ссылка в новой задаче