This commit is contained in:
Robert Sayre 2009-08-19 15:30:21 -04:00
commit 0da1878591
3 changed files with 65 additions and 70 deletions

View File

@ -4995,34 +4995,6 @@ 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 static JSBool
regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{ {
@ -5037,10 +5009,8 @@ regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
slot = JSVAL_TO_INT(id); slot = JSVAL_TO_INT(id);
if (slot == REGEXP_LAST_INDEX) { if (slot == REGEXP_LAST_INDEX)
*vp = GetRegExpLastIndexValue(obj); return JS_GetReservedSlot(cx, obj, 0, vp);
return JS_TRUE;
}
JS_LOCK_OBJ(cx, obj); JS_LOCK_OBJ(cx, obj);
re = (JSRegExp *) obj->getPrivate(); re = (JSRegExp *) obj->getPrivate();
@ -5087,7 +5057,8 @@ regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (!JS_ValueToNumber(cx, *vp, &lastIndex)) if (!JS_ValueToNumber(cx, *vp, &lastIndex))
return JS_FALSE; return JS_FALSE;
lastIndex = js_DoubleToInteger(lastIndex); lastIndex = js_DoubleToInteger(lastIndex);
ok = SetRegExpLastIndex(cx, obj, lastIndex); ok = JS_NewNumberValue(cx, lastIndex, vp) &&
JS_SetReservedSlot(cx, obj, 0, *vp);
} }
return ok; return ok;
} }
@ -5357,7 +5328,8 @@ js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
if (!re) if (!re)
return JS_FALSE; return JS_FALSE;
obj->setPrivate(re); obj->setPrivate(re);
js_ClearRegExpLastIndex(0); if (!js_SetLastIndex(xdr->cx, obj, 0))
return JS_FALSE;
*objp = obj; *objp = obj;
} }
return JS_TRUE; return JS_TRUE;
@ -5379,8 +5351,7 @@ regexp_trace(JSTracer *trc, JSObject *obj)
JSClass js_RegExpClass = { JSClass js_RegExpClass = {
js_RegExp_str, js_RegExp_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
JSCLASS_HAS_RESERVED_SLOTS(REGEXP_CLASS_FIXED_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp), JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
@ -5569,12 +5540,13 @@ created:
JS_LOCK_OBJ(cx, obj); JS_LOCK_OBJ(cx, obj);
oldre = (JSRegExp *) obj->getPrivate(); oldre = (JSRegExp *) obj->getPrivate();
obj->setPrivate(re); obj->setPrivate(re);
js_ClearRegExpLastIndex(obj);
JSBool ok = js_SetLastIndex(cx, obj, 0);
JS_UNLOCK_OBJ(cx, obj); JS_UNLOCK_OBJ(cx, obj);
if (oldre) if (oldre)
js_DestroyRegExp(cx, oldre); js_DestroyRegExp(cx, oldre);
*rval = OBJECT_TO_JSVAL(obj); *rval = OBJECT_TO_JSVAL(obj);
return JS_TRUE; return ok;
} }
static JSBool static JSBool
@ -5609,10 +5581,14 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
/* NB: we must reach out: after this paragraph, in order to drop re. */ /* NB: we must reach out: after this paragraph, in order to drop re. */
HOLD_REGEXP(cx, re); HOLD_REGEXP(cx, re);
sticky = (re->flags & JSREG_STICKY) != 0; sticky = (re->flags & JSREG_STICKY) != 0;
lastIndex = (re->flags & (JSREG_GLOB | JSREG_STICKY)) if (re->flags & (JSREG_GLOB | JSREG_STICKY)) {
? GetRegExpLastIndex(obj) ok = js_GetLastIndex(cx, obj, &lastIndex);
: 0; } else {
lastIndex = 0;
}
JS_UNLOCK_OBJ(cx, obj); JS_UNLOCK_OBJ(cx, obj);
if (!ok)
goto out;
/* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */ /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */
if (argc == 0) { if (argc == 0) {
@ -5642,17 +5618,14 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
} }
if (lastIndex < 0 || str->length() < lastIndex) { if (lastIndex < 0 || str->length() < lastIndex) {
js_ClearRegExpLastIndex(obj); ok = js_SetLastIndex(cx, obj, 0);
*rval = JSVAL_NULL; *rval = JSVAL_NULL;
} else { } else {
i = (size_t) lastIndex; i = (size_t) lastIndex;
ok = js_ExecuteRegExp(cx, re, str, &i, test, rval); ok = js_ExecuteRegExp(cx, re, str, &i, test, rval);
if (ok && if (ok &&
((re->flags & JSREG_GLOB) || (*rval != JSVAL_NULL && sticky))) { ((re->flags & JSREG_GLOB) || (*rval != JSVAL_NULL && sticky))) {
if (*rval == JSVAL_NULL) ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i);
js_ClearRegExpLastIndex(obj);
else
ok = SetRegExpLastIndex(cx, obj, i);
} }
} }
@ -5768,7 +5741,8 @@ js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
return NULL; return NULL;
} }
obj->setPrivate(re); obj->setPrivate(re);
js_ClearRegExpLastIndex(obj); if (!js_SetLastIndex(cx, obj, 0))
return NULL;
return obj; return obj;
} }
@ -5785,9 +5759,26 @@ js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
re = (JSRegExp *) obj->getPrivate(); re = (JSRegExp *) obj->getPrivate();
if (re) { if (re) {
clone->setPrivate(re); clone->setPrivate(re);
js_ClearRegExpLastIndex(clone);
HOLD_REGEXP(cx, re); HOLD_REGEXP(cx, re);
} }
return clone; 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);
}

View File

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

View File

@ -1343,10 +1343,14 @@ match_or_replace(JSContext *cx,
: INT_TO_JSVAL(-1); : INT_TO_JSVAL(-1);
} }
} else if (data->flags & GLOBAL_REGEXP) { } else if (data->flags & GLOBAL_REGEXP) {
if (reobj) if (reobj) {
js_ClearRegExpLastIndex(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(); length = str->length();
ok = true;
for (count = 0; index <= length; count++) { for (count = 0; index <= length; count++) {
ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp); ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
if (!ok || *vp != JSVAL_TRUE) if (!ok || *vp != JSVAL_TRUE)
@ -1360,6 +1364,7 @@ match_or_replace(JSContext *cx,
index++; index++;
} }
} }
}
} else { } else {
if (GET_MODE(data->flags) == MODE_REPLACE) { if (GET_MODE(data->flags) == MODE_REPLACE) {
test = JS_TRUE; test = JS_TRUE;