LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value);
if (SPROP_HAS_VALID_SLOT(sprop)) LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value);
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,		  JSPropertyOp getter, JSPropertyOp setter, uintN attrs,		  JSProperty **propp){    JSClass *clasp;    JSScope *scope;    JSScopeProperty *sprop;    /*     * Handle old bug that took empty string as zero index.  Also convert     * string indices to integers if appropriate.     */    CHECK_FOR_FUNNY_INDEX(id);    /* Lock if object locking is required by this implementation. */    JS_LOCK_OBJ(cx, obj);#if JS_HAS_GETTER_SETTER    /*     * If defining a getter or setter, we must check for its counterpart and     * update the attributes and property ops.  A getter or setter is really     * only half of a property.     */    if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {        JSObject *pobj;        if (!js_LookupProperty(cx, obj, id, &pobj, (JSProperty **)&sprop))            goto bad;        if (sprop &&            pobj == obj &&            (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {            sprop->attrs |= attrs;            if (attrs & JSPROP_GETTER)                SPROP_GETTER(sprop, pobj) = getter;            else                SPROP_SETTER(sprop, pobj) = setter;            if (propp)                *propp = (JSProperty *) sprop;#ifdef JS_THREADSAFE            else {                /* Release sprop and the lock acquired by js_LookupProperty. */                js_DropProperty(cx, obj, (JSProperty *)sprop);            }#endif            /* Release our lock on obj, in which js_LookupProperty's nested. */            JS_UNLOCK_OBJ(cx, obj);            return JS_TRUE;        }        if (sprop) {            /* NB: call OBJ_DROP_PROPERTY, as pobj might not be native. */            OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);        }    }#endif /* JS_HAS_GETTER_SETTER */    /* Use the object's class getter and setter by default. */    clasp = LOCKED_OBJ_GET_CLASS(obj);    if (!getter)	getter = clasp->getProperty;    if (!setter)	setter = clasp->setProperty;    /* Find a sharable scope, or get a new one for obj. */    scope = js_MutateScope(cx, obj, id, getter, setter, attrs, &sprop);    if (!scope)	goto bad;    /* Add the property only if MutateScope didn't find a shared scope. */    if (!sprop) {	sprop = js_NewScopeProperty(cx, scope, id, getter, setter, attrs);	if (!sprop)	    goto bad;	/* XXXbe called with lock held */	if (!clasp->addProperty(cx, obj, sprop->id, &value) ||	    !scope->ops->add(cx, scope, id, sprop)) {	    js_DestroyScopeProperty(cx, scope, sprop);	    goto bad;	}	PROPERTY_CACHE_FILL(cx, &cx->runtime->propertyCache, obj, id,			    (JSProperty *)sprop);    }    LOCKED_OBJ_SET_SLOT(obj, sprop->slot, value);    if (propp) {#ifdef JS_THREADSAFE	js_HoldScopeProperty(cx, scope, sprop);#endif	*propp = (JSProperty *) sprop;    } else {	JS_UNLOCK_OBJ(cx, obj);    }    return JS_TRUE;bad:    JS_UNLOCK_OBJ(cx, obj);    return JS_FALSE;}