sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop, 0, ~JSPROP_SHARED, sprop->getter, setter);
sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, ~JSPROP_SHARED, sprop->getter, setter);
SetFunctionSlot(JSContext *cx, JSObject *obj, JSPropertyOp setter, jsid id,                jsval v){    uintN slot;    JSObject *origobj;    JSScope *scope;    JSScopeProperty *sprop;    JSString *str;    JSBool ok;    slot = (uintN) JSID_TO_INT(id);    if (OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {        /*         * Given a non-function object obj that has a function object in its         * prototype chain, where an argument or local variable property named         * by (setter, slot) is being set, override the shared property in the         * prototype with an unshared property in obj.  This situation arises         * in real-world JS due to .prototype setting and collisions among a         * function's "static property" names and arg or var names, believe it         * or not.         */        origobj = obj;        do {            obj = OBJ_GET_PROTO(cx, obj);            if (!obj)                return JS_TRUE;        } while (OBJ_GET_CLASS(cx, obj) != &js_FunctionClass);        JS_LOCK_OBJ(cx, obj);        scope = OBJ_SCOPE(obj);        for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {            if (sprop->setter == setter) {                JS_ASSERT(JSID_IS_ATOM(sprop->id) &&                          ATOM_IS_STRING(JSID_TO_ATOM(sprop->id)) &&                          (sprop->flags & SPROP_HAS_SHORTID));                if ((uintN) sprop->shortid == slot) {                    str = ATOM_TO_STRING(JSID_TO_ATOM(sprop->id));                    JS_UNLOCK_SCOPE(cx, scope);                    return JS_DefineUCProperty(cx, origobj,                                               JSSTRING_CHARS(str),                                               JSSTRING_LENGTH(str),                                               v, NULL, NULL,                                               JSPROP_ENUMERATE);                }            }        }        JS_UNLOCK_SCOPE(cx, scope);        return JS_TRUE;    }    /*     * Argument and local variable properties of function objects are shared     * by default (JSPROP_SHARED), therefore slot-less.  But if for function     * f(a) {}, f.a = 42 is evaluated, f.a should be 42 after the assignment,     * whether or not f is active.  So js_SetArgument and js_SetLocalVariable     * must be prepared to change an arg or var from shared to unshared status,     * allocating a slot in obj to hold v.     */    ok = JS_TRUE;    JS_LOCK_OBJ(cx, obj);    scope = OBJ_SCOPE(obj);    for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {        if (sprop->setter == setter && (uintN) sprop->shortid == slot) {            if (sprop->attrs & JSPROP_SHARED) {                sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop,                                                    0, ~JSPROP_SHARED,                                                    sprop->getter, setter);                if (!sprop) {                    ok = JS_FALSE;                } else {                    /* See js_SetProperty, near the bottom. */                    GC_POKE(cx, pval);                    LOCKED_OBJ_SET_SLOT(obj, sprop->slot, v);                }            }            break;        }    }    JS_UNLOCK_SCOPE(cx, scope);    return ok;}