Merge.
authorRobert Sayre <sayrer@gmail.com>
Wed, 19 Aug 2009 15:30:21 -0400
changeset 31896 dc463a6bab6eb18f2e34a500624acf89c57998f3
parent 31894 bf06fc22595c240786dde4fa1addac5de35232c6 (current diff)
parent 31895 9dd844f6397244a87632f9008cb8264ffca3cbce (diff)
child 31897 2e528cc8602a697b5c6fd63bdfe477ef8a997b7c
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge.
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -4990,62 +4990,32 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp
 
 out:
     JS_ARENA_RELEASE(&cx->regexpPool, mark);
     return ok;
 }
 
 /************************************************************************/
 
-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)
 {
     jsint slot;
     JSRegExp *re;
 
     if (!JSVAL_IS_INT(id))
         return JS_TRUE;
     while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) {
         obj = OBJ_GET_PROTO(cx, obj);
         if (!obj)
             return JS_TRUE;
     }
     slot = JSVAL_TO_INT(id);
-    if (slot == REGEXP_LAST_INDEX) {
-        *vp = GetRegExpLastIndexValue(obj);
-        return JS_TRUE;
-    }
+    if (slot == REGEXP_LAST_INDEX)
+        return JS_GetReservedSlot(cx, obj, 0, vp);
 
     JS_LOCK_OBJ(cx, obj);
     re = (JSRegExp *) obj->getPrivate();
     if (re) {
         switch (slot) {
           case REGEXP_SOURCE:
             *vp = STRING_TO_JSVAL(re->source);
             break;
@@ -5082,17 +5052,18 @@ regexp_setProperty(JSContext *cx, JSObje
         if (!obj)
             return JS_TRUE;
     }
     slot = JSVAL_TO_INT(id);
     if (slot == REGEXP_LAST_INDEX) {
         if (!JS_ValueToNumber(cx, *vp, &lastIndex))
             return JS_FALSE;
         lastIndex = js_DoubleToInteger(lastIndex);
-        ok = SetRegExpLastIndex(cx, obj, lastIndex);
+        ok = JS_NewNumberValue(cx, lastIndex, vp) &&
+             JS_SetReservedSlot(cx, obj, 0, *vp);
     }
     return ok;
 }
 
 #define REGEXP_PROP_ATTRS     (JSPROP_PERMANENT | JSPROP_SHARED)
 #define RO_REGEXP_PROP_ATTRS  (REGEXP_PROP_ATTRS | JSPROP_READONLY)
 
 #define G regexp_getProperty
@@ -5352,17 +5323,18 @@ js_XDRRegExpObject(JSXDRState *xdr, JSOb
         if (!obj)
             return JS_FALSE;
         STOBJ_CLEAR_PARENT(obj);
         STOBJ_CLEAR_PROTO(obj);
         re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE);
         if (!re)
             return JS_FALSE;
         obj->setPrivate(re);
-        js_ClearRegExpLastIndex(0);
+        if (!js_SetLastIndex(xdr->cx, obj, 0))
+            return JS_FALSE;
         *objp = obj;
     }
     return JS_TRUE;
 }
 
 #else  /* !JS_HAS_XDR */
 
 #define js_XDRRegExpObject NULL
@@ -5374,18 +5346,17 @@ regexp_trace(JSTracer *trc, JSObject *ob
 {
     JSRegExp *re = (JSRegExp *) obj->getPrivate();
     if (re && re->source)
         JS_CALL_STRING_TRACER(trc, re->source, "source");
 }
 
 JSClass js_RegExpClass = {
     js_RegExp_str,
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_RESERVED_SLOTS(REGEXP_CLASS_FIXED_RESERVED_SLOTS) |
+    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
     JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
     JS_PropertyStub,    JS_PropertyStub,
     JS_PropertyStub,    JS_PropertyStub,
     JS_EnumerateStub,   JS_ResolveStub,
     JS_ConvertStub,     regexp_finalize,
     NULL,               NULL,
     regexp_call,        NULL,
     js_XDRRegExpObject, NULL,
@@ -5564,22 +5535,23 @@ regexp_compile_sub(JSContext *cx, JSObje
 
     re = js_NewRegExpOpt(cx, str, opt, JS_FALSE);
 created:
     if (!re)
         return JS_FALSE;
     JS_LOCK_OBJ(cx, obj);
     oldre = (JSRegExp *) obj->getPrivate();
     obj->setPrivate(re);
-    js_ClearRegExpLastIndex(obj);
+
+    JSBool ok = js_SetLastIndex(cx, obj, 0);
     JS_UNLOCK_OBJ(cx, obj);
     if (oldre)
         js_DestroyRegExp(cx, oldre);
     *rval = OBJECT_TO_JSVAL(obj);
-    return JS_TRUE;
+    return ok;
 }
 
 static JSBool
 regexp_compile(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj;
 
     obj = JS_THIS_OBJECT(cx, vp);
@@ -5604,20 +5576,24 @@ regexp_exec_sub(JSContext *cx, JSObject 
     if (!re) {
         JS_UNLOCK_OBJ(cx, obj);
         return JS_TRUE;
     }
 
     /* NB: we must reach out: after this paragraph, in order to drop re. */
     HOLD_REGEXP(cx, re);
     sticky = (re->flags & JSREG_STICKY) != 0;
-    lastIndex = (re->flags & (JSREG_GLOB | JSREG_STICKY))
-                ? GetRegExpLastIndex(obj)
-                : 0;
+    if (re->flags & (JSREG_GLOB | JSREG_STICKY)) {
+        ok = js_GetLastIndex(cx, obj, &lastIndex);
+    } else {
+        lastIndex = 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) {
         str = cx->regExpStatics.input;
         if (!str) {
             const char *bytes = js_GetStringBytes(cx, re->source);
 
             if (bytes) {
@@ -5637,27 +5613,24 @@ regexp_exec_sub(JSContext *cx, JSObject 
         if (!str) {
             ok = JS_FALSE;
             goto out;
         }
         argv[0] = STRING_TO_JSVAL(str);
     }
 
     if (lastIndex < 0 || str->length() < lastIndex) {
-        js_ClearRegExpLastIndex(obj);
+        ok = js_SetLastIndex(cx, obj, 0);
         *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))) {
-            if (*rval == JSVAL_NULL)
-                js_ClearRegExpLastIndex(obj);
-            else
-                ok = SetRegExpLastIndex(cx, obj, i);
+            ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i);
         }
     }
 
 out:
     DROP_REGEXP(cx, re);
     return ok;
 }
 
@@ -5763,31 +5736,49 @@ js_NewRegExpObject(JSContext *cx, JSToke
     if (!re)
         return NULL;
     obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
     if (!obj) {
         js_DestroyRegExp(cx, re);
         return NULL;
     }
     obj->setPrivate(re);
-    js_ClearRegExpLastIndex(obj);
+    if (!js_SetLastIndex(cx, obj, 0))
+        return NULL;
     return obj;
 }
 
 JSObject *
 js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
 {
     JSObject *clone;
     JSRegExp *re;
 
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
     clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
     if (!clone)
         return NULL;
     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);
+}
+
--- a/js/src/jsregexp.h
+++ b/js/src/jsregexp.h
@@ -180,21 +180,20 @@ js_NewRegExpObject(JSContext *cx, JSToke
                    jschar *chars, size_t length, uintN flags);
 
 extern JSBool
 js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp);
 
 extern JSObject *
 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
-js_ClearRegExpLastIndex(JSObject *obj)
-{
-    JS_ASSERT(obj->getClass() == &js_RegExpClass);
-    obj->fslots[JSSLOT_REGEXP_LAST_INDEX] = JSVAL_ZERO;
-}
+extern JSBool
+js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
 
 JS_END_EXTERN_C
 
 #endif /* jsregexp_h___ */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1338,31 +1338,36 @@ match_or_replace(JSContext *cx,
     if (GET_MODE(data->flags) == MODE_SEARCH) {
         ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
         if (ok) {
             *vp = (*vp == JSVAL_TRUE)
                   ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length)
                   : INT_TO_JSVAL(-1);
         }
     } else if (data->flags & GLOBAL_REGEXP) {
-        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)
+        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)
                     break;
-                index++;
+                ok = glob(cx, count, data);
+                if (!ok)
+                    break;
+                if (cx->regExpStatics.lastMatch.length == 0) {
+                    if (index == length)
+                        break;
+                    index++;
+                }
             }
         }
     } else {
         if (GET_MODE(data->flags) == MODE_REPLACE) {
             test = JS_TRUE;
         } else {
             /*
              * MODE_MATCH implies str_match is being called from a script or a