bug 509143 - js_CloneRegExp is missing a call to js_SetLastIndex. r=mrbkap

This commit is contained in:
Igor Bukanov 2009-08-22 19:59:55 +03:00
Родитель e5f7ef8a1d
Коммит 0fdc68aba3
3 изменённых файлов: 70 добавлений и 65 удалений

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

@ -4982,6 +4982,34 @@ out:
/************************************************************************/
static jsdouble
GetRegExpLastIndex(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &js_RegExpClass);
jsval v = obj->fslots[JSSLOT_REGEXP_LAST_INDEX];
if (JSVAL_IS_INT(v))
return JSVAL_TO_INT(v);
JS_ASSERT(JSVAL_IS_DOUBLE(v));
return *JSVAL_TO_DOUBLE(v);
}
static jsval
GetRegExpLastIndexValue(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &js_RegExpClass);
return obj->fslots[JSSLOT_REGEXP_LAST_INDEX];
}
static JSBool
SetRegExpLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex)
{
JS_ASSERT(obj->getClass() == &js_RegExpClass);
return JS_NewNumberValue(cx, lastIndex,
&obj->fslots[JSSLOT_REGEXP_LAST_INDEX]);
}
static JSBool
regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
@ -4996,8 +5024,10 @@ regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
}
slot = JSVAL_TO_INT(id);
if (slot == REGEXP_LAST_INDEX)
return JS_GetReservedSlot(cx, obj, 0, vp);
if (slot == REGEXP_LAST_INDEX) {
*vp = GetRegExpLastIndexValue(obj);
return JS_TRUE;
}
JS_LOCK_OBJ(cx, obj);
re = (JSRegExp *) obj->getPrivate();
@ -5044,8 +5074,7 @@ regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (!JS_ValueToNumber(cx, *vp, &lastIndex))
return JS_FALSE;
lastIndex = js_DoubleToInteger(lastIndex);
ok = JS_NewNumberValue(cx, lastIndex, vp) &&
JS_SetReservedSlot(cx, obj, 0, *vp);
ok = SetRegExpLastIndex(cx, obj, lastIndex);
}
return ok;
}
@ -5315,8 +5344,7 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
if (!re)
return JS_FALSE;
obj->setPrivate(re);
if (!js_SetLastIndex(xdr->cx, obj, 0))
return JS_FALSE;
js_ClearRegExpLastIndex(obj);
*objp = obj;
}
return JS_TRUE;
@ -5338,7 +5366,8 @@ regexp_trace(JSTracer *trc, JSObject *obj)
JSClass js_RegExpClass = {
js_RegExp_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(REGEXP_CLASS_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub,
@ -5527,13 +5556,12 @@ created:
JS_LOCK_OBJ(cx, obj);
oldre = (JSRegExp *) obj->getPrivate();
obj->setPrivate(re);
JSBool ok = js_SetLastIndex(cx, obj, 0);
js_ClearRegExpLastIndex(obj);
JS_UNLOCK_OBJ(cx, obj);
if (oldre)
js_DestroyRegExp(cx, oldre);
*rval = OBJECT_TO_JSVAL(obj);
return ok;
return JS_TRUE;
}
static JSBool
@ -5568,14 +5596,10 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
/* NB: we must reach out: after this paragraph, in order to drop re. */
HOLD_REGEXP(cx, re);
sticky = (re->flags & JSREG_STICKY) != 0;
if (re->flags & (JSREG_GLOB | JSREG_STICKY)) {
ok = js_GetLastIndex(cx, obj, &lastIndex);
} else {
lastIndex = 0;
}
lastIndex = (re->flags & (JSREG_GLOB | JSREG_STICKY))
? GetRegExpLastIndex(obj)
: 0;
JS_UNLOCK_OBJ(cx, obj);
if (!ok)
goto out;
/* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */
if (argc == 0) {
@ -5605,14 +5629,17 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
if (lastIndex < 0 || str->length() < lastIndex) {
ok = js_SetLastIndex(cx, obj, 0);
js_ClearRegExpLastIndex(obj);
*rval = JSVAL_NULL;
} else {
i = (size_t) lastIndex;
ok = js_ExecuteRegExp(cx, re, str, &i, test, rval);
if (ok &&
((re->flags & JSREG_GLOB) || (*rval != JSVAL_NULL && sticky))) {
ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i);
if (*rval == JSVAL_NULL)
js_ClearRegExpLastIndex(obj);
else
ok = SetRegExpLastIndex(cx, obj, i);
}
}
@ -5728,8 +5755,7 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
return NULL;
}
obj->setPrivate(re);
if (!js_SetLastIndex(cx, obj, 0))
return NULL;
js_ClearRegExpLastIndex(obj);
return obj;
}
@ -5746,26 +5772,9 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
re = (JSRegExp *) obj->getPrivate();
if (re) {
clone->setPrivate(re);
js_ClearRegExpLastIndex(clone);
HOLD_REGEXP(cx, re);
}
return clone;
}
JSBool
js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex)
{
jsval v;
return JS_GetReservedSlot(cx, obj, 0, &v) &&
JS_ValueToNumber(cx, v, lastIndex);
}
JSBool
js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex)
{
jsval v;
return JS_NewNumberValue(cx, lastIndex, &v) &&
JS_SetReservedSlot(cx, obj, 0, v);
}

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

@ -185,14 +185,15 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp);
extern JSObject *
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent);
/*
* Get and set the per-object (clone or clone-parent) lastIndex slot.
*/
extern JSBool
js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex);
const uint32 JSSLOT_REGEXP_LAST_INDEX = JSSLOT_PRIVATE + 1;
const uint32 REGEXP_CLASS_FIXED_RESERVED_SLOTS = 1;
extern JSBool
js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
static inline void
js_ClearRegExpLastIndex(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &js_RegExpClass);
obj->fslots[JSSLOT_REGEXP_LAST_INDEX] = JSVAL_ZERO;
}
JS_END_EXTERN_C

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

@ -1343,26 +1343,21 @@ match_or_replace(JSContext *cx,
: INT_TO_JSVAL(-1);
}
} else if (data->flags & GLOBAL_REGEXP) {
if (reobj) {
/* Set the lastIndex property's reserved slot to 0. */
ok = js_SetLastIndex(cx, reobj, 0);
} else {
ok = JS_TRUE;
}
if (ok) {
length = str->length();
for (count = 0; index <= length; count++) {
ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
if (!ok || *vp != JSVAL_TRUE)
if (reobj)
js_ClearRegExpLastIndex(reobj);
length = str->length();
ok = true;
for (count = 0; index <= length; count++) {
ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
if (!ok || *vp != JSVAL_TRUE)
break;
ok = glob(cx, count, data);
if (!ok)
break;
if (cx->regExpStatics.lastMatch.length == 0) {
if (index == length)
break;
ok = glob(cx, count, data);
if (!ok)
break;
if (cx->regExpStatics.lastMatch.length == 0) {
if (index == length)
break;
index++;
}
index++;
}
}
} else {