JSBool js_DeleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval) { #if JS_HAS_PROP_DELETE JSProperty *prop; PR_ASSERT(JS_IS_LOCKED(cx)); if (!js_LookupProperty(cx, obj, id, NULL, &prop)) return JS_FALSE; if (!prop) return JS_TRUE; return js_DeleteProperty2(cx, obj, prop, id, rval); #else jsval null = JSVAL_NULL; *rval = JSVAL_VOID; return (js_SetProperty(cx, obj, id, &null) != NULL); #endif }
PyObject* Context_add_global(Context* self, PyObject* args, PyObject* kwargs) { PyObject* pykey = NULL; PyObject* pyval = NULL; jsval jsk; jsid kid; jsval jsv; JS_BeginRequest(self->cx); if(!PyArg_ParseTuple(args, "OO", &pykey, &pyval)) goto error; jsk = py2js(self, pykey); if(jsk == JSVAL_VOID) goto error; if(!JS_ValueToId(self->cx, jsk, &kid)) { PyErr_SetString(PyExc_AttributeError, "Failed to create key id."); goto error; } jsv = py2js(self, pyval); if(jsv == JSVAL_VOID) goto error; if(!js_SetProperty(self->cx, self->root, kid, &jsv)) { PyErr_SetString(PyExc_AttributeError, "Failed to set global property."); goto error; } goto success; error: success: JS_EndRequest(self->cx); Py_RETURN_NONE; }
JSBool js_DeleteProperty2(JSContext *cx, JSObject *obj, JSProperty *prop, jsval id, jsval *rval) { #if JS_HAS_PROP_DELETE JSRuntime *rt; JSString *str; JSScope *scope; JSObject *proto; PRHashNumber hash; JSSymbol *sym; rt = cx->runtime; PR_ASSERT(JS_IS_RUNTIME_LOCKED(rt)); *rval = JSVERSION_IS_ECMA(cx->version) ? JSVAL_TRUE : JSVAL_VOID; if (prop->flags & JSPROP_PERMANENT) { if (JSVERSION_IS_ECMA(cx->version)) { *rval = JSVAL_FALSE; return JS_TRUE; } str = js_ValueToSource(cx, js_IdToValue(id)); if (str) JS_ReportError(cx, "%s is permanent", JS_GetStringBytes(str)); return JS_FALSE; } if (!obj->map->clasp->delProperty(cx, obj, prop->id, &prop->object->slots[prop->slot])) { return JS_FALSE; } /* Handle old bug that treated empty string as zero index. */ CHECK_FOR_FUNNY_INDEX(id); GC_POKE(cx, prop->object->slots[prop->slot]); scope = (JSScope *)obj->map; proto = scope->object; if (proto == obj) { /* The object has its own scope, so remove id if it was found here. */ if (prop->object == obj) { /* Purge cache only if prop is not about to be destroyed. */ if (prop->nrefs != 1) { PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, PROP_NOT_FOUND); } #if JS_HAS_OBJ_WATCHPOINT if (prop->setter == js_watch_set) { /* * Keep the symbol around with null value in case of re-set. * The watchpoint will hold the "deleted" property until it * is removed by obj_unwatch or a native JS_ClearWatchPoint. * See js_SetProperty for the re-set logic. */ for (sym = prop->symbols; sym; sym = sym->next) { if (sym_id(sym) == id) { sym->entry.value = NULL; prop = js_DropProperty(cx, prop); PR_ASSERT(prop); return JS_TRUE; } } } #endif scope->ops->remove(cx, scope, id); } proto = OBJ_GET_PROTO(obj); if (!proto) return JS_TRUE; } /* Search shared prototype scopes for an inherited property to hide. */ hash = js_HashValue(id); do { scope = (JSScope *)proto->map; sym = scope->ops->lookup(cx, scope, id, hash); if (sym) { /* Add a null-valued symbol to hide the prototype property. */ scope = js_GetMutableScope(cx, obj); if (!scope) return JS_FALSE; if (!scope->ops->add(cx, scope, id, NULL)) return JS_FALSE; PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, PROP_NOT_FOUND); return JS_TRUE; } proto = OBJ_GET_PROTO(proto); } while (proto); return JS_TRUE; #else jsval null = JSVAL_NULL; return (js_SetProperty(cx, obj, id, &null) != NULL); #endif }