Beispiel #1
0
JSBool
js_GetClassPrototype(JSContext *cx, JSClass *clasp, JSObject **protop)
{
    JSBool ok;
    JSObject *ctor;
    jsval pval;
    JSProperty *prop;

    *protop = NULL;
    JS_LOCK(cx);
    ok = FindConstructor(cx, clasp, &pval);
    if (!ok || !JSVAL_IS_FUNCTION(pval))
	goto out;
    ctor = JSVAL_TO_OBJECT(pval);
    if (!js_LookupProperty(cx, ctor,
			   (jsval)cx->runtime->atomState.classPrototypeAtom,
			   NULL, &prop)) {
	ok = JS_FALSE;
	goto out;
    }
    if (prop) {
	pval = prop->object->slots[prop->slot];
	if (JSVAL_IS_OBJECT(pval))
	    *protop = JSVAL_TO_OBJECT(pval);
    }
out:
    JS_UNLOCK(cx);
    return ok;
}
Beispiel #2
0
static JSBool
exn_enumerate(JSContext *cx, JSObject *obj)
{
    JSAtomState *atomState;
    uintN i;
    JSAtom *atom;
    JSObject *pobj;
    JSProperty *prop;

    JS_STATIC_ASSERT(sizeof(JSAtomState) <= (size_t)(uint16)-1);
    static const uint16 offsets[] = {
        (uint16)offsetof(JSAtomState, messageAtom),
        (uint16)offsetof(JSAtomState, fileNameAtom),
        (uint16)offsetof(JSAtomState, lineNumberAtom),
        (uint16)offsetof(JSAtomState, stackAtom),
    };

    atomState = &cx->runtime->atomState;
    for (i = 0; i != JS_ARRAY_LENGTH(offsets); ++i) {
        atom = *(JSAtom **)((uint8 *)atomState + offsets[i]);
        if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))
            return JS_FALSE;
        if (prop)
            OBJ_DROP_PROPERTY(cx, pobj, prop);
    }
    return JS_TRUE;
}
Beispiel #3
0
JSProperty *
js_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    JSProperty *prop;
    JSObject *obj2;
    jsint slot;

    PR_ASSERT(JS_IS_LOCKED(cx));

    if (!js_LookupProperty(cx, obj, id, &obj, &prop))
	return NULL;
    if (!prop) {
	prop = js_DefineProperty(cx, obj, id,
#if JS_BUG_NULL_INDEX_PROPS
				 (JSVAL_IS_INT(id) && JSVAL_TO_INT(id) >= 0)
				 ? JSVAL_NULL
				 : JSVAL_VOID,
#else
				 JSVAL_VOID,
#endif
				 NULL, NULL, 0);
	if (!prop)
	    return NULL;
    }
    obj2 = prop->object;
    slot = prop->slot;
    *vp = obj2->slots[slot];
    if (!prop->getter(cx, obj, prop->id, vp))
	return NULL;
    obj2->slots[slot] = *vp;
    return prop;
}
Beispiel #4
0
JSBool
js_FindProperty(JSContext *cx, jsval id, JSObject **objp, JSProperty **propp)
{
    JSRuntime *rt;
    JSObject *obj, *parent, *lastobj;
    JSProperty *prop;

    rt = cx->runtime;
    PR_ASSERT(JS_IS_RUNTIME_LOCKED(rt));

    for (obj = cx->fp->scopeChain; obj; obj = parent) {
	/* Try the property cache and return immediately on cache hit. */
	PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, prop);
	if (PROP_FOUND(prop)) {
	    *objp = obj;
	    *propp = prop;
	    return JS_TRUE;
	}

	/*
	 * Set parent here, after cache hit to minimize cycles in that case,
	 * but before js_LookupProperty, which might change obj.
	 */
	parent = OBJ_GET_PARENT(obj);

	/* If cache miss (not cached-as-not-found), take the slow path. */
	if (!prop) {
	    if (!js_LookupProperty(cx, obj, id, &obj, &prop))
		return JS_FALSE;
	    if (prop) {
		PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, prop);
		*objp = obj;
		*propp = prop;
		return JS_TRUE;
	    }

	    /* No such property -- cache obj[id] as not-found. */
	    PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id,
				PROP_NOT_FOUND);
	}
	lastobj = obj;
    }
    *objp = lastobj;
    *propp = NULL;
    return JS_TRUE;
}
Beispiel #5
0
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
}
Beispiel #6
0
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
                 JSWatchPointHandler handler, void *closure)
{
    JSAtom *atom;
    jsid propid;
    JSObject *pobj;
    JSScopeProperty *sprop;
    JSRuntime *rt;
    JSWatchPoint *wp;
    JSPropertyOp watcher;

    if (!OBJ_IS_NATIVE(obj)) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
                             OBJ_GET_CLASS(cx, obj)->name);
        return JS_FALSE;
    }

    if (JSVAL_IS_INT(id)) {
        propid = (jsid)id;
        atom = NULL;
    } else {
        atom = js_ValueToStringAtom(cx, id);
        if (!atom)
            return JS_FALSE;
        propid = (jsid)atom;
    }

    if (!js_LookupProperty(cx, obj, propid, &pobj, (JSProperty **)&sprop))
        return JS_FALSE;
    rt = cx->runtime;
    if (!sprop) {
        /* Check for a deleted symbol watchpoint, which holds its property. */
        sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
        if (!sprop) {
            /* Make a new property in obj so we can watch for the first set. */
            if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID,
                                   NULL, NULL, JSPROP_ENUMERATE,
                                   (JSProperty **)&sprop)) {
                sprop = NULL;
            }
        }
    } else if (pobj != obj) {
        /* Clone the prototype property so we can watch the right object. */
        jsval value;
        JSPropertyOp getter, setter;
        uintN attrs;

        if (OBJ_IS_NATIVE(pobj)) {
            value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))
                    ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
                    : JSVAL_VOID;
            getter = sprop->getter;
            setter = sprop->setter;
            attrs = sprop->attrs;
        } else {
            if (!OBJ_GET_PROPERTY(cx, pobj, id, &value)) {
                OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
                return JS_FALSE;
            }
            getter = setter = JS_PropertyStub;
            attrs = JSPROP_ENUMERATE;
        }
        OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);

        if (!js_DefineProperty(cx, obj, propid, value, getter, setter, attrs,
                               (JSProperty **)&sprop)) {
            sprop = NULL;
        }
    }
    if (!sprop)
        return JS_FALSE;

    wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
    if (!wp) {
        watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter);
        if (!watcher)
            return JS_FALSE;

        wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp);
        if (!wp)
            return JS_FALSE;
        wp->handler = NULL;
        wp->closure = NULL;
        if (!js_AddRoot(cx, &wp->closure, "wp->closure")) {
            JS_free(cx, wp);
            return JS_FALSE;
        }
        JS_APPEND_LINK(&wp->links, &rt->watchPointList);
        wp->object = obj;
        wp->sprop = sprop;
        JS_ASSERT(sprop->setter != js_watch_set);
        wp->setter = sprop->setter;
        wp->nrefs = 1;
        sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs,
                                             sprop->getter, watcher);
        if (!sprop)
            return DropWatchPoint(cx, wp);
    }
    wp->handler = handler;
    wp->closure = closure;
    OBJ_DROP_PROPERTY(cx, obj, (JSProperty *)sprop);
    return JS_TRUE;
}
Beispiel #7
0
static JSBool
obj_watch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSFunction *fun;
    jsval userid, symid, propid, value;
    JSAtom *atom;
    JSRuntime *rt;
    JSBool ok;
    JSProperty *prop;
    JSPropertyOp getter, setter;
    JSClass *clasp;

    fun = JS_ValueToFunction(cx, argv[1]);
    if (!fun)
	return JS_FALSE;
    argv[1] = OBJECT_TO_JSVAL(fun->object);

    /*
     * Lock the world while we look in obj.  Be sure to return via goto out
     * on error, so we unlock.
     */
    rt = cx->runtime;
    JS_LOCK_RUNTIME(rt);

    /* Compute the unique int/atom symbol id needed by js_LookupProperty. */
    userid = argv[0];
    if (JSVAL_IS_INT(userid)) {
	symid = userid;
	atom = NULL;
    } else {
	atom = js_ValueToStringAtom(cx, userid);
	if (!atom) {
	    ok = JS_FALSE;
	    goto out;
	}
	symid = (jsval)atom;
    }

    ok = js_LookupProperty(cx, obj, symid, &obj, &prop);
    if (atom)
	js_DropAtom(cx, atom);
    if (!ok)
	goto out;

    /* Set propid from the property, in case it has a tinyid. */
    if (prop) {
	propid = prop->id;
	getter = prop->getter;
	setter = prop->setter;
	value = prop->object->slots[prop->slot];
    } else {
	propid = userid;
	clasp = obj->map->clasp;
	getter = clasp->getProperty;
	setter = clasp->setProperty;
	value = JSVAL_VOID;
    }

    /*
     * Security policy is implemented in getters and setters, so we have to
     * call get and set here to let the JS API client check for a watchpoint
     * that crosses a trust boundary.
     * XXX assumes get and set are idempotent, should use a clasp->watch hook
     */
    ok = getter(cx, obj, propid, &value) && setter(cx, obj, propid, &value);
    if (!ok)
	goto out;

    /* Finally, call into jsdbgapi.c to set the watchpoint on userid. */
    ok = JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, fun->object);

out:
    JS_UNLOCK_RUNTIME(rt);
    return ok;
}