Exemplo n.º 1
0
static JSBool
FindConstructor(JSContext *cx, JSClass *clasp, jsval *vp)
{
    JSAtom *atom;
    JSObject *obj, *tmp;
    JSBool ok;

    PR_ASSERT(JS_IS_LOCKED(cx));

    /* XXX pre-atomize in JS_InitClass! */
    atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
    if (!atom)
	return JS_FALSE;

    if (cx->fp && (tmp = cx->fp->scopeChain)) {
	/* Find the topmost object in the scope chain. */
	do {
	    obj = tmp;
	    tmp = OBJ_GET_PARENT(obj);
	} while (tmp);
    } else {
	obj = cx->globalObject;
	if (!obj) {
	    *vp = JSVAL_VOID;
	    return JS_TRUE;
	}
    }

    ok = (js_GetProperty(cx, obj, (jsval)atom, vp) != NULL);
    js_DropAtom(cx, atom);
    return JS_TRUE;
}
Exemplo n.º 2
0
void
js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
	     uintN argc, jsval *argv, jsval *rval)
{
    JSErrorReporter older;
    JSProperty *prop;
    jsval fval;

    older = JS_SetErrorReporter(cx, NULL);
    JS_LOCK_VOID(cx, prop = js_GetProperty(cx, obj, (jsval)atom, &fval));
    if (prop &&
	JSVAL_IS_OBJECT(fval) &&
	fval != JSVAL_NULL) {
	(void) js_Call(cx, obj, fval, argc, argv, rval);
    }
    JS_SetErrorReporter(cx, older);
}
Exemplo n.º 3
0
PyObject*
Context_rem_global(Context* self, PyObject* args, PyObject* kwargs)
{
    PyObject* pykey = NULL;
    PyObject* ret = NULL;
    jsval jsk;
    jsid kid;
    jsval jsv;

    JS_BeginRequest(self->cx);

    if(!PyArg_ParseTuple(args, "O", &pykey)) goto error;

    jsk = py2js(self, pykey);
    if(jsk == JSVAL_VOID) goto error;

    if(!JS_ValueToId(self->cx, jsk, &kid))
    {
        PyErr_SetString(JSError, "Failed to create key id.");
    }

    if(!js_GetProperty(self->cx, self->root, kid, &jsv))
    {
        PyErr_SetString(JSError, "Failed to get global property.");
        goto error;
    }
    
    ret = js2py(self, jsv);
    if(ret == NULL) goto error;
    
    if(!js_DeleteProperty(self->cx, self->root, kid, &jsv))
    {
        PyErr_SetString(JSError, "Failed to remove global property.");
        goto error;
    }

    JS_MaybeGC(self->cx);

    goto success;

error:
success:
    JS_EndRequest(self->cx);
    return ret;
}
Exemplo n.º 4
0
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
                   JSPropertyDesc *pd)
{
    JSPropertyOp getter;
    JSScope *scope;
    JSScopeProperty *aprop;
    jsval lastException;
    JSBool wasThrowing;

    pd->id = ID_TO_VALUE(sprop->id);

    wasThrowing = cx->throwing;
    if (wasThrowing) {
        lastException = cx->exception;
        if (JSVAL_IS_GCTHING(lastException) &&
            !js_AddRoot(cx, &lastException, "lastException")) {
                return JS_FALSE;
        }
        cx->throwing = JS_FALSE;
    }
    
    if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) {
        if (!cx->throwing) {
            pd->flags = JSPD_ERROR;
            pd->value = JSVAL_VOID;
        } else {
            pd->flags = JSPD_EXCEPTION;
            pd->value = cx->exception;
        }
    } else {
        pd->flags = 0;
    }
    
    cx->throwing = wasThrowing;
    if (wasThrowing) {
        cx->exception = lastException;
        if (JSVAL_IS_GCTHING(lastException))
            js_RemoveRoot(cx->runtime, &lastException);
    }
    
    getter = sprop->getter;
    pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
              | ((sprop->attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0)
              | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
#if JS_HAS_CALL_OBJECT
              | ((getter == js_GetCallVariable)    ? JSPD_VARIABLE  : 0)
#endif /* JS_HAS_CALL_OBJECT */
              | ((getter == js_GetArgument)        ? JSPD_ARGUMENT  : 0)
              | ((getter == js_GetLocalVariable)   ? JSPD_VARIABLE  : 0);
#if JS_HAS_CALL_OBJECT
    /* for Call Object 'real' getter isn't passed in to us */
    if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
        getter == js_CallClass.getProperty) {
        /*
         * Property of a heavyweight function's variable object having the
         * class-default getter.  It's either an argument if permanent, or a
         * nested function if impermanent.  Local variables have a special
         * getter (js_GetCallVariable, tested above) and setter, and not the
         * class default.
         */
        pd->flags |= (sprop->attrs & JSPROP_PERMANENT)
                     ? JSPD_ARGUMENT
                     : JSPD_VARIABLE;
    }
#endif /* JS_HAS_CALL_OBJECT */
    pd->spare = 0;
    pd->slot = (pd->flags & (JSPD_ARGUMENT | JSPD_VARIABLE))
               ? sprop->shortid
               : 0;
    pd->alias = JSVAL_VOID;
    scope = OBJ_SCOPE(obj);
    if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
        for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) {
            if (aprop != sprop && aprop->slot == sprop->slot) {
                pd->alias = ID_TO_VALUE(aprop->id);
                break;
            }
        }
    }
    return JS_TRUE;
}
Exemplo n.º 5
0
JSProperty *
js_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    JSRuntime *rt;
    JSScope *scope, *protoScope;
    JSProperty *prop, *protoProp;
    PRHashNumber hash;
    JSSymbol *sym, *protoSym;
    JSObject *proto, *assignobj;
    jsval pval, aval, rval;
    jsint slot;
    JSErrorReporter older;
    JSString *str;

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

#ifdef SCOPE_TABLE_NOTYET
    /* XXX hash recompute */
    /* XXX protoProp->getter, protoProp->setter, protoProp->flags */
    scope = js_MutateScope(cx, obj, id, getter, setter, flags, &prop);
#endif
    scope = js_GetMutableScope(cx, obj);
    if (!scope)
	return NULL;

    /* Handle old bug that treated empty string as zero index. */
    CHECK_FOR_FUNNY_INDEX(id);

    hash = js_HashValue(id);
    sym = scope->ops->lookup(cx, scope, id, hash);
    if (sym) {
	prop = sym_property(sym);
#if JS_HAS_OBJ_WATCHPOINT
	if (!prop) {
	    /*
	     * Deleted property place-holder, could have a watchpoint that
	     * holds the deleted-but-watched property.
	     */
	    prop = js_FindWatchPoint(rt, obj, js_IdToValue(id));
	}
#endif
    } else {
	prop = NULL;
    }

    if (!prop) {
	/* Find a prototype property with the same id. */
	proto = OBJ_GET_PROTO(obj);
	protoProp = NULL;
	while (proto) {
	    protoScope = (JSScope *)proto->map;
	    protoSym = protoScope->ops->lookup(cx, protoScope, id, hash);
	    if (protoSym) {
		protoProp = sym_property(protoSym);
		if (protoProp)
		    break;
	    }
	    proto = OBJ_GET_PROTO(proto);
	}

	/* Make a new property descriptor with the right heritage. */
	if (protoProp) {
	    prop = js_NewProperty(cx, scope, id,
				  protoProp->getter, protoProp->setter,
				  protoProp->flags | JSPROP_ENUMERATE);
	    prop->id = protoProp->id;
	} else {
	    prop = js_NewProperty(cx, scope, id,
				  scope->map.clasp->getProperty,
				  scope->map.clasp->setProperty,
				  JSPROP_ENUMERATE);
	}
	if (!prop)
	    return NULL;

	if (!obj->map->clasp->addProperty(cx, obj, prop->id, vp)) {
	    js_DestroyProperty(cx, prop);
	    return NULL;
	}

	/* Initialize new properties to undefined. */
	obj->slots[prop->slot] = JSVAL_VOID;

	if (sym) {
	    /* Null-valued symbol left behind from a delete operation. */
	    sym->entry.value = js_HoldProperty(cx, prop);
	}
    }

    if (!sym) {
	/* Need a new symbol as well as a new property. */
	sym = scope->ops->add(cx, scope, id, prop);
	if (!sym)
	    return NULL;
#if JS_BUG_AUTO_INDEX_PROPS
	{
	    jsval id2 = INT_TO_JSVAL(prop->slot - JSSLOT_START);
	    if (!scope->ops->add(cx, scope, id2, prop)) {
		scope->ops->remove(cx, scope, id);
		return NULL;
	    }
	    PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id2, prop);
	}
#endif
	PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, prop);
    }

    /* Get the current property value from its slot. */
    PR_ASSERT(prop->slot < obj->map->freeslot);
    slot = prop->slot;
    pval = obj->slots[slot];

    /* Evil overloaded operator assign() hack. */
    if (JSVAL_IS_OBJECT(pval)) {
	assignobj = JSVAL_TO_OBJECT(pval);
	if (assignobj) {
	    older = JS_SetErrorReporter(cx, NULL);
	    if (js_GetProperty(cx, assignobj, (jsval)rt->atomState.assignAtom,
			       &aval) &&
		JSVAL_IS_FUNCTION(aval) &&
		js_Call(cx, assignobj, aval, 1, vp, &rval)) {
		*vp = rval;
		JS_SetErrorReporter(cx, older);
		prop->flags |= JSPROP_ASSIGNHACK;
		return prop;
	    }
	    JS_SetErrorReporter(cx, older);
	}
    }

    /* Check for readonly *after* the assign() hack. */
    if (prop->flags & JSPROP_READONLY) {
	if (!JSVERSION_IS_ECMA(cx->version)) {
	    str = js_ValueToSource(cx, js_IdToValue(id));
	    if (str) {
		JS_ReportError(cx, "%s is read-only",
			       JS_GetStringBytes(str));
	    }
	}
	return NULL;
    }

    /* Let the setter modify vp before copying from it to obj->slots[slot]. */
    if (!prop->setter(cx, obj, prop->id, vp))
	return NULL;
    GC_POKE(cx, pval);
    obj->slots[slot] = *vp;

    /* Setting a property makes it enumerable. */
    prop->flags |= JSPROP_ENUMERATE;
    return prop;
}