Backed out changeset 759b21bbb64b (bug 610223) due to Windows build bustage, a=red

This commit is contained in:
Gavin Sharp 2010-11-15 23:15:02 -05:00
Родитель e7f1aced19
Коммит a9d2b1cd5a
6 изменённых файлов: 113 добавлений и 212 удалений

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

@ -1,8 +0,0 @@
var re = /(pattern)/g;
var input = "patternpatternpattern";
re.exec(input)
RegExp.input = "satturn";
assertEq(RegExp.$1, "pattern");
assertEq(RegExp.lastMatch, "pattern");
assertEq(RegExp.lastParen, "pattern");
assertEq(RegExp.rightContext, "patternpattern");

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

@ -1,8 +0,0 @@
var re = /abc(WHOO!)?def/y;
var input = 'abcdefabcdefabcdef';
var count = 0;
while ((match = re.exec(input)) !== null) {
print(count++);
assertEq(match[0], 'abcdef');
assertEq(match[1], undefined);
}

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

@ -393,7 +393,7 @@ regexp_resolve(JSContext *cx, JSObject *obj, jsid id, uint32 flags, JSObject **o
code; \
}
DEFINE_STATIC_GETTER(static_input_getter, return res->createPendingInput(cx, Valueify(vp)))
DEFINE_STATIC_GETTER(static_input_getter, return res->createInput(cx, Valueify(vp)))
DEFINE_STATIC_GETTER(static_multiline_getter, *vp = BOOLEAN_TO_JSVAL(res->multiline());
return true)
DEFINE_STATIC_GETTER(static_lastMatch_getter, return res->createLastMatch(cx, Valueify(vp)))
@ -423,7 +423,7 @@ DEFINE_STATIC_GETTER(static_paren9_getter, return res->createParen(cx, 8,
DEFINE_STATIC_SETTER(static_input_setter,
if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp))
return false;
res->setPendingInput(JSVAL_TO_STRING(*vp)))
res->setInput(JSVAL_TO_STRING(*vp)))
DEFINE_STATIC_SETTER(static_multiline_setter,
if (!JSVAL_IS_BOOLEAN(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp))
return false;
@ -783,7 +783,7 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool te
argv[0] = StringValue(str);
} else {
/* Need to grab input from statics. */
str = res->getPendingInput();
str = res->getInput();
if (!str) {
const char *sourceBytes = js_GetStringBytes(cx, re->getSource());
if (sourceBytes) {

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

@ -59,14 +59,11 @@ namespace js {
class RegExpStatics
{
typedef Vector<int, 20, SystemAllocPolicy> MatchPairs;
MatchPairs matchPairs;
/* The input that was used to produce matchPairs. */
JSString *matchPairsInput;
/* The input last set on the statics. */
JSString *pendingInput;
uintN flags;
RegExpStatics *bufferLink;
bool copied;
MatchPairs matchPairs;
JSString *input;
uintN flags;
RegExpStatics *bufferLink;
bool copied;
bool createDependent(JSContext *cx, size_t start, size_t end, Value *out) const;
@ -79,8 +76,7 @@ class RegExpStatics
dst.matchPairs.clear();
/* 'save' has already reserved space in matchPairs */
JS_ALWAYS_TRUE(dst.matchPairs.append(matchPairs));
dst.matchPairsInput = matchPairsInput;
dst.pendingInput = pendingInput;
dst.input = input;
dst.flags = flags;
}
@ -91,6 +87,25 @@ class RegExpStatics
}
}
/*
* Check whether the index at |checkValidIndex| is valid (>= 0).
* If so, construct a string for it and place it in |*out|.
* If not, place undefined in |*out|.
*/
bool makeMatch(JSContext *cx, size_t checkValidIndex, size_t pairNum, Value *out) const;
static const uintN allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_STICKY | JSREG_MULTILINE;
friend class RegExp;
public:
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
struct InitBuffer {};
explicit RegExpStatics(InitBuffer) : bufferLink(NULL), copied(false) {}
static RegExpStatics *extractFrom(JSObject *global);
/* Mutators. */
bool save(JSContext *cx, RegExpStatics *buffer) {
JS_ASSERT(!buffer->copied && !buffer->bufferLink);
buffer->bufferLink = bufferLink;
@ -108,76 +123,6 @@ class RegExpStatics
bufferLink = bufferLink->bufferLink;
}
void checkInvariants() {
#if DEBUG
if (pairCount() == 0) {
JS_ASSERT(!matchPairsInput);
return;
}
/* Pair count is non-zero, so there must be match pairs input. */
JS_ASSERT(matchPairsInput);
size_t mpiLen = matchPairsInput->length();
JS_ASSERT(pairIsPresent(0));
/* Present pairs must be valid. */
for (size_t i = 0; i < pairCount(); ++i) {
if (!pairIsPresent(i))
continue;
int start = get(i, 0);
int limit = get(i, 1);
JS_ASSERT(mpiLen >= size_t(limit) && limit >= start && start >= 0);
}
#endif
}
int get(size_t pairNum, bool which) const {
JS_ASSERT(pairNum < pairCount());
return matchPairs[2 * pairNum + which];
}
/*
* Check whether the index at |checkValidIndex| is valid (>= 0).
* If so, construct a string for it and place it in |*out|.
* If not, place undefined in |*out|.
*/
bool makeMatch(JSContext *cx, size_t checkValidIndex, size_t pairNum, Value *out) const;
static const uintN allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_STICKY | JSREG_MULTILINE;
struct InitBuffer {};
explicit RegExpStatics(InitBuffer) : bufferLink(NULL), copied(false) {}
friend class PreserveRegExpStatics;
public:
RegExpStatics() : bufferLink(NULL), copied(false) { clear(); }
static RegExpStatics *extractFrom(JSObject *global);
/* 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;
if (!matchPairs.resizeUninitialized(matchItemCount)) {
js_ReportOutOfMemory(cx);
return false;
}
for (size_t i = 0; i < matchItemCount; ++i)
matchPairs[i] = buf[i];
matchPairsInput = input;
return true;
}
void setMultiline(bool enabled) {
aboutToWrite();
if (enabled)
@ -188,61 +133,43 @@ class RegExpStatics
void clear() {
aboutToWrite();
input = 0;
flags = 0;
pendingInput = NULL;
matchPairsInput = NULL;
matchPairs.clear();
}
bool pairIsPresent(size_t pairNum) { return get(0, 0) != -1; }
void checkInvariants() {
if (pairCount() > 0) {
JS_ASSERT(input);
JS_ASSERT(get(0, 0) <= get(0, 1));
JS_ASSERT(get(0, 1) <= int(input->length()));
}
}
/* Corresponds to JSAPI functionality to set the pending RegExp input. */
void reset(JSString *newInput, bool newMultiline) {
aboutToWrite();
clear();
pendingInput = newInput;
input = newInput;
setMultiline(newMultiline);
checkInvariants();
}
void setPendingInput(JSString *newInput) {
void setInput(JSString *newInput) {
aboutToWrite();
pendingInput = newInput;
input = newInput;
}
/* Accessors. */
JSString *getPendingInput() const { return pendingInput; }
JSString *getInput() const { return input; }
uintN getFlags() const { return flags; }
bool multiline() const { return flags & JSREG_MULTILINE; }
size_t matchStart() const {
int start = get(0, 0);
JS_ASSERT(start >= 0);
return size_t(start);
}
size_t matchLimit() const {
int limit = get(0, 1);
JS_ASSERT(size_t(limit) >= matchStart() && limit >= 0);
return size_t(limit);
}
bool matched() const {
JS_ASSERT(pairCount() > 0);
return get(0, 1) - get(0, 0) > 0;
}
size_t getParenCount() const {
JS_ASSERT(pairCount() > 0);
return pairCount() - 1;
}
bool matched() const { JS_ASSERT(pairCount() > 0); return get(0, 1) - get(0, 0) > 0; }
size_t getParenCount() const { JS_ASSERT(pairCount() > 0); return pairCount() - 1; }
void mark(JSTracer *trc) const {
if (pendingInput)
JS_CALL_STRING_TRACER(trc, pendingInput, "res->pendingInput");
if (matchPairsInput)
JS_CALL_STRING_TRACER(trc, matchPairsInput, "res->matchPairsInput");
if (input)
JS_CALL_STRING_TRACER(trc, input, "res->input");
}
size_t getParenLength(size_t parenNum) const {
@ -251,9 +178,14 @@ class RegExpStatics
return get(parenNum + 1, 1) - get(parenNum + 1, 0);
}
int get(size_t pairNum, bool which) const {
JS_ASSERT(pairNum < pairCount());
return matchPairs[2 * pairNum + which];
}
/* Value creators. */
bool createPendingInput(JSContext *cx, Value *out) const;
bool createInput(JSContext *cx, Value *out) const;
bool createLastMatch(JSContext *cx, Value *out) const { return makeMatch(cx, 0, 0, out); }
bool createLastParen(JSContext *cx, Value *out) const;
bool createLeftContext(JSContext *cx, Value *out) const;
@ -272,26 +204,6 @@ class RegExpStatics
void getRightContext(JSSubString *out) const;
};
class PreserveRegExpStatics
{
RegExpStatics *const original;
RegExpStatics buffer;
public:
explicit PreserveRegExpStatics(RegExpStatics *original)
: original(original),
buffer(RegExpStatics::InitBuffer())
{}
bool init(JSContext *cx) {
return original->save(cx, &buffer);
}
~PreserveRegExpStatics() {
original->restore();
}
};
}
static inline bool

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

@ -93,8 +93,9 @@ class RegExp
void handlePCREError(JSContext *cx, int error);
void handleYarrError(JSContext *cx, int error);
static inline bool initArena(JSContext *cx);
static inline void checkMatchPairs(JSString *input, int *buf, size_t matchItemCount);
static JSObject *createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount);
static inline void checkMatchPairs(int *buf, size_t matchItemCount);
JSObject *createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount,
size_t inputOffset);
inline bool executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
size_t *lastIndex, bool test, Value *rval);
@ -217,29 +218,19 @@ RegExp::initArena(JSContext *cx)
}
inline void
RegExp::checkMatchPairs(JSString *input, int *buf, size_t matchItemCount)
RegExp::checkMatchPairs(int *buf, size_t matchItemCount)
{
#if DEBUG
size_t inputLength = input->length();
int largestStartSeen = 0;
for (size_t i = 0; i < matchItemCount; i += 2) {
int start = buf[i];
int limit = buf[i + 1];
JS_ASSERT(limit >= start); /* Limit index must be larger than the start index. */
if (start == -1)
continue;
JS_ASSERT(start >= 0);
JS_ASSERT(size_t(limit) <= inputLength);
/* Test the monotonically increasing nature of left parens. */
JS_ASSERT(start >= largestStartSeen);
largestStartSeen = start;
}
for (size_t i = 0; i < matchItemCount; i += 2)
JS_ASSERT(buf[i + 1] >= buf[i]); /* Limit index must be larger than the start index. */
#endif
}
inline JSObject *
RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount)
RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount,
size_t inputOffset)
{
#define MATCH_VALUE(__index) (buf[(__index)] + inputOffset)
/*
* Create the result array for a match. Array contents:
* 0: matched string
@ -251,13 +242,13 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
RegExpMatchBuilder builder(cx, array);
for (size_t i = 0; i < matchItemCount; i += 2) {
int start = buf[i];
int end = buf[i + 1];
int start = MATCH_VALUE(i);
int end = MATCH_VALUE(i + 1);
JSString *captured;
if (start >= 0) {
JS_ASSERT(start <= end);
JS_ASSERT(unsigned(end) <= input->length());
JS_ASSERT((unsigned) end <= input->length());
captured = js_NewDependentString(cx, input, start, end - start);
if (!(captured && builder.append(i / 2, captured)))
return NULL;
@ -270,11 +261,12 @@ RegExp::createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemC
}
}
if (!builder.appendIndex(buf[0]) ||
if (!builder.appendIndex(MATCH_VALUE(0)) ||
!builder.appendInput(input))
return NULL;
return array;
#undef MATCH_VALUE
}
inline bool
@ -305,11 +297,6 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
const jschar *chars = input->chars();
size_t len = input->length();
/*
* inputOffset emulates sticky mode by matching from this offset into the char buf and
* subtracting the delta off at the end.
*/
size_t inputOffset = 0;
if (sticky()) {
@ -331,29 +318,27 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
return true;
}
/*
* Adjust buf for the inputOffset. Use of sticky is rare and the matchItemCount is small, so
* just do another pass.
*/
if (JS_UNLIKELY(inputOffset)) {
checkMatchPairs(buf, matchItemCount);
if (res) {
res->aboutToWrite();
res->input = input;
if (!res->matchPairs.resizeUninitialized(matchItemCount)) {
js_ReportOutOfMemory(cx);
return false;
}
for (size_t i = 0; i < matchItemCount; ++i)
buf[i] = buf[i] < 0 ? -1 : buf[i] + inputOffset;
res->matchPairs[i] = buf[i] + inputOffset;
}
/* Make sure the populated contents of |buf| are sane values against |input|. */
checkMatchPairs(input, buf, matchItemCount);
if (res)
res->updateFromMatch(cx, input, buf, matchItemCount);
*lastIndex = buf[1];
*lastIndex = buf[1] + inputOffset;
if (test) {
*rval = BooleanValue(true);
return true;
}
JSObject *array = createResult(cx, input, buf, matchItemCount);
JSObject *array = createResult(cx, input, buf, matchItemCount, inputOffset);
if (!array)
return false;
@ -545,8 +530,8 @@ inline bool
RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *out) const
{
JS_ASSERT(start <= end);
JS_ASSERT(end <= matchPairsInput->length());
JSString *str = js_NewDependentString(cx, matchPairsInput, start, end - start);
JS_ASSERT(end <= input->length());
JSString *str = js_NewDependentString(cx, input, start, end - start);
if (!str)
return false;
*out = StringValue(str);
@ -554,9 +539,9 @@ RegExpStatics::createDependent(JSContext *cx, size_t start, size_t end, Value *o
}
inline bool
RegExpStatics::createPendingInput(JSContext *cx, Value *out) const
RegExpStatics::createInput(JSContext *cx, Value *out) const
{
out->setString(pendingInput ? pendingInput : cx->runtime->emptyString);
out->setString(input ? input : cx->runtime->emptyString);
return true;
}
@ -614,13 +599,13 @@ RegExpStatics::createRightContext(JSContext *cx, Value *out) const
*out = UndefinedValue();
return true;
}
return createDependent(cx, matchPairs[1], matchPairsInput->length(), out);
return createDependent(cx, matchPairs[1], input->length(), out);
}
inline void
RegExpStatics::getParen(size_t num, JSSubString *out) const
{
out->chars = matchPairsInput->chars() + get(num + 1, 0);
out->chars = input->chars() + get(num + 1, 0);
out->length = getParenLength(num);
}
@ -631,8 +616,8 @@ RegExpStatics::getLastMatch(JSSubString *out) const
*out = js_EmptySubString;
return;
}
JS_ASSERT(matchPairsInput);
out->chars = matchPairsInput->chars() + get(0, 0);
JS_ASSERT(input);
out->chars = input->chars() + get(0, 0);
JS_ASSERT(get(0, 1) >= get(0, 0));
out->length = get(0, 1) - get(0, 0);
}
@ -645,7 +630,7 @@ RegExpStatics::getLastParen(JSSubString *out) const
return;
}
size_t num = pairCount() - 1;
out->chars = matchPairsInput->chars() + get(num, 0);
out->chars = input->chars() + get(num, 0);
JS_ASSERT(get(num, 1) >= get(num, 0));
out->length = get(num, 1) - get(num, 0);
}
@ -657,7 +642,7 @@ RegExpStatics::getLeftContext(JSSubString *out) const
*out = js_EmptySubString;
return;
}
out->chars = matchPairsInput->chars();
out->chars = input->chars();
out->length = get(0, 0);
}
@ -668,9 +653,9 @@ RegExpStatics::getRightContext(JSSubString *out) const
*out = js_EmptySubString;
return;
}
out->chars = matchPairsInput->chars() + get(0, 1);
JS_ASSERT(get(0, 1) <= int(matchPairsInput->length()));
out->length = matchPairsInput->length() - get(0, 1);
out->chars = input->chars() + get(0, 1);
JS_ASSERT(get(0, 1) <= int(input->length()));
out->length = input->length() - get(0, 1);
}
}

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

@ -1955,7 +1955,7 @@ str_search(JSContext *cx, uintN argc, Value *vp)
return false;
if (vp->isTrue())
vp->setInt32(res->matchStart());
vp->setInt32(res->get(0, 0));
else
vp->setInt32(-1);
return true;
@ -2045,6 +2045,26 @@ InterpretDollar(JSContext *cx, RegExpStatics *res, jschar *dp, jschar *ep, Repla
return false;
}
class PreserveRegExpStatics
{
js::RegExpStatics *const original;
js::RegExpStatics buffer;
public:
explicit PreserveRegExpStatics(RegExpStatics *original)
: original(original),
buffer(RegExpStatics::InitBuffer())
{}
bool init(JSContext *cx) {
return original->save(cx, &buffer);
}
~PreserveRegExpStatics() {
original->restore();
}
};
static bool
FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t *sizep)
{
@ -2135,7 +2155,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
}
/* Push match index and input string. */
session[argi++].setInt32(res->matchStart());
session[argi++].setInt32(res->get(0, 0));
session[argi].setString(rdata.str);
if (!session.invoke(cx))
@ -2202,8 +2222,8 @@ ReplaceCallback(JSContext *cx, RegExpStatics *res, size_t count, void *p)
JSString *str = rdata.str;
size_t leftoff = rdata.leftIndex;
const jschar *left = str->chars() + leftoff;
size_t leftlen = res->matchStart() - leftoff;
rdata.leftIndex = res->matchLimit();
size_t leftlen = res->get(0, 0) - leftoff;
rdata.leftIndex = res->get(0, 1);
size_t replen = 0; /* silence 'unused' warning */
if (!FindReplaceLength(cx, res, rdata, &replen))