Exemplo n.º 1
0
js_free_symbol(void *priv, PRHashEntry *he, uintN flag)
{
    JSContext *cx;
    JSSymbol *sym, **sp;
    JSProperty *prop;

    cx = priv;
    PR_ASSERT(JS_IS_LOCKED(cx));
    sym = (JSSymbol *)he;
    prop = sym->entry.value;
    if (prop) {
        sym->entry.value = NULL;
        prop = js_DropProperty(cx, prop);
        if (prop) {
            for (sp = &prop->symbols; *sp; sp = &(*sp)->next) {
                if (*sp == sym) {
                    *sp = sym->next;
                    if (!*sp)
                        break;
                }
            }
            sym->next = NULL;
        }
    }

    if (flag == HT_FREE_ENTRY) {
        if (!JSVAL_IS_INT(sym_id(sym)))
            JS_LOCK_VOID(cx, js_DropAtom(cx, sym_atom(sym)));
        JS_free(cx, he);
    }
}
Exemplo n.º 2
0
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
}