if ((~sprop->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
if (SPROP_IS_SHARED_PERMANENT(sprop))
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval){#if JS_HAS_PROP_DELETE    JSObject *proto;    JSProperty *prop;    JSScopeProperty *sprop;    JSString *str;    JSScope *scope;    JSBool ok;    *rval = JSVERSION_IS_ECMA(cx->version) ? JSVAL_TRUE : JSVAL_VOID;    /*     * Handle old bug that took empty string as zero index.  Also convert     * string indices to integers if appropriate.     */    CHECK_FOR_FUNNY_INDEX(id);    if (!js_LookupProperty(cx, obj, id, &proto, &prop))        return JS_FALSE;    if (!prop || proto != obj) {        /*         * If the property was found in a native prototype, check whether it's         * shared and permanent.  Such a property stands for direct properties         * in all delegating objects, matching ECMA semantics without bloating         * each delegating object.         */        if (prop) {            if (OBJ_IS_NATIVE(proto)) {                sprop = (JSScopeProperty *)prop;                if ((~sprop->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)                    *rval = JSVAL_FALSE;            }            OBJ_DROP_PROPERTY(cx, proto, prop);            if (*rval == JSVAL_FALSE)                return JS_TRUE;        }        /*         * If no property, or the property comes unshared or impermanent from         * a prototype, call the class's delProperty hook, passing rval as the         * result parameter.         */        return OBJ_GET_CLASS(cx, obj)->delProperty(cx, obj, ID_TO_VALUE(id),                                                   rval);    }    sprop = (JSScopeProperty *)prop;    if (sprop->attrs & JSPROP_PERMANENT) {        OBJ_DROP_PROPERTY(cx, obj, prop);        if (JSVERSION_IS_ECMA(cx->version)) {            *rval = JSVAL_FALSE;            return JS_TRUE;        }        str = js_DecompileValueGenerator(cx, JSDVG_IGNORE_STACK,                                         ID_TO_VALUE(id), NULL);        if (str) {            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,                                 JSMSG_PERMANENT, JS_GetStringBytes(str));        }        return JS_FALSE;    }    /* XXXbe called with obj locked */    if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop),                                                rval)) {        OBJ_DROP_PROPERTY(cx, obj, prop);        return JS_FALSE;    }    scope = OBJ_SCOPE(obj);    if (SPROP_HAS_VALID_SLOT(sprop, scope))        GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));    PROPERTY_CACHE_FILL(&cx->runtime->propertyCache, obj, id, NULL);    ok = js_RemoveScopeProperty(cx, scope, id);    OBJ_DROP_PROPERTY(cx, obj, prop);    return ok;#else  /* !JS_HAS_PROP_DELETE */    jsval null = JSVAL_NULL;    *rval = JSVAL_VOID;    return js_SetProperty(cx, obj, id, &null);#endif /* !JS_HAS_PROP_DELETE */}