static JSBool
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp)
{
  // Don't call XPC_XOW_RewrapIfNeeded for same origin properties. We only
  // need to wrap window, document and location.
  if (JSVAL_IS_PRIMITIVE(*vp)) {
    return JS_TRUE;
  }

  JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp);
  JSClass *clasp = STOBJ_GET_CLASS(wrappedObj);
  if (XPC_XOW_ClassNeedsXOW(clasp->name)) {
    return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp);
  }

  // Check if wrappedObj is an XOW. If so, verify that it's from the
  // right scope.
  if (clasp == &sXPC_XOW_JSClass.base &&
      STOBJ_GET_PARENT(wrappedObj) != STOBJ_GET_PARENT(outerObj)) {
    *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, wrappedObj));
    return XPC_XOW_WrapObject(cx, STOBJ_GET_PARENT(outerObj), vp);
  }

  return JS_TRUE;
}
예제 #2
0
파일: jsiter.cpp 프로젝트: ahadzi/celtx
/*
 * Shared code to close iterator's state either through an explicit call or
 * when GC detects that the iterator is no longer reachable.
 */
void
js_CloseNativeIterator(JSContext *cx, JSObject *iterobj)
{
    jsval state;
    JSObject *iterable;

    JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);

    /* Avoid double work if js_CloseNativeIterator was called on obj. */
    state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
    if (JSVAL_IS_NULL(state))
        return;

    /* Protect against failure to fully initialize obj. */
    iterable = STOBJ_GET_PARENT(iterobj);
    if (iterable) {
#if JS_HAS_XML_SUPPORT
        uintN flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
        if ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, iterable)) {
            ((JSXMLObjectOps *) iterable->map->ops)->
                enumerateValues(cx, iterable, JSENUMERATE_DESTROY, &state,
                                NULL, NULL);
        } else
#endif
            OBJ_ENUMERATE(cx, iterable, JSENUMERATE_DESTROY, &state, NULL);
    }
    STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL);
}
예제 #3
0
static inline JSObject *
GetUnsafeObject(JSObject *obj)
{
  obj = FindSafeObject(obj);

  if (!obj) {
    return nsnull;
  }

  return STOBJ_GET_PARENT(obj);
}
// Because of the drastically different ways that same- and cross-origin XOWs
// work, we have to call JS_ClearScope when a XOW changes from being same-
// origin to cross-origin. Normally, there are defined places in Gecko where
// this happens and they notify us. However, UniversalXPConnect causes the
// same transition without any notifications. We could try to detect when this
// happens, but doing so would require calling JS_ClearScope from random
// hooks, which is bad.
//
// The compromise is the UXPCObject. When resolving a property on a XOW as
// same-origin because of UniversalXPConnect, we actually resolve it on the
// UXPCObject (which is just a XOW for the same object). This causes the JS
// engine to do all of its work on another object, not polluting the main
// object. However, if the get results in calling a setter, the engine still
// uses the regular object as 'this', ensuring that the UXPCObject doesn't
// leak to script.
static JSObject *
GetUXPCObject(JSContext *cx, JSObject *obj)
{
  NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base, "wrong object");

  jsval v;
  if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &v)) {
    return nsnull;
  }

  if (HAS_FLAGS(v, FLAG_IS_UXPC_OBJECT)) {
    return obj;
  }

  if (!JS_GetReservedSlot(cx, obj, sUXPCObjectSlot, &v)) {
    return nsnull;
  }

  if (JSVAL_IS_OBJECT(v)) {
    return JSVAL_TO_OBJECT(v);
  }

  JSObject *uxpco =
    JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull,
                               STOBJ_GET_PARENT(obj));
  if (!uxpco) {
    return nsnull;
  }

  JSAutoTempValueRooter tvr(cx, uxpco);

  jsval wrappedObj, parentScope;
  if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &wrappedObj) ||
      !JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &parentScope)) {
    return nsnull;
  }

  if (!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sWrappedObjSlot, wrappedObj) ||
      !JS_SetReservedSlot(cx, uxpco, XPCWrapper::sFlagsSlot,
                          INT_TO_JSVAL(FLAG_IS_UXPC_OBJECT)) ||
      !JS_SetReservedSlot(cx, uxpco, XPC_XOW_ScopeSlot, parentScope)) {
    return nsnull;
  }

  if (!JS_SetReservedSlot(cx, obj, sUXPCObjectSlot, OBJECT_TO_JSVAL(uxpco))) {
    return nsnull;
  }

  return uxpco;
}
JSBool
XPC_XOW_RewrapIfNeeded(JSContext *cx, JSObject *outerObj, jsval *vp)
{
  // Don't need to wrap primitive values.
  if (JSVAL_IS_PRIMITIVE(*vp)) {
    return JS_TRUE;
  }

  JSObject *obj = JSVAL_TO_OBJECT(*vp);

  if (JS_ObjectIsFunction(cx, obj)) {
    return XPC_XOW_WrapFunction(cx, outerObj, obj, vp);
  }

  XPCWrappedNative *wn = nsnull;
  if (STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base &&
      STOBJ_GET_PARENT(outerObj) != STOBJ_GET_PARENT(obj)) {
    *vp = OBJECT_TO_JSVAL(GetWrappedObject(cx, obj));
  } else if (!(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj))) {
    return JS_TRUE;
  }

  return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp, wn);
}
예제 #6
0
JSBool
xpc_qsXPCOMObjectToJsval(XPCLazyCallContext &lccx, nsISupports *p,
                         nsWrapperCache *cache, const nsIID *iid,
                         XPCNativeInterface **iface, jsval *rval)
{
    // From the T_INTERFACE case in XPCConvert::NativeData2JS.
    // This is one of the slowest things quick stubs do.

    JSContext *cx = lccx.GetJSContext();
    if(!iface)
        return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_NATIVE);

    // XXX The OBJ_IS_NOT_GLOBAL here is not really right. In
    // fact, this code is depending on the fact that the
    // global object will not have been collected, and
    // therefore this NativeInterface2JSObject will not end up
    // creating a new XPCNativeScriptableShared.

    nsresult rv;
    if(!XPCConvert::NativeInterface2JSObject(lccx, rval, nsnull, p,
                                             iid, iface, cache,
                                             lccx.GetCurrentJSObject(), PR_TRUE,
                                             OBJ_IS_NOT_GLOBAL, &rv))
    {
        // I can't tell if NativeInterface2JSObject throws JS exceptions
        // or not.  This is a sloppy stab at the right semantics; the
        // method really ought to be fixed to behave consistently.
        if(!JS_IsExceptionPending(cx))
            xpc_qsThrow(cx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
        return JS_FALSE;
    }

#ifdef DEBUG
    JSObject* jsobj = JSVAL_TO_OBJECT(*rval);
    if(jsobj && !STOBJ_GET_PARENT(jsobj))
        NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL,
                     "Why did we recreate this wrapper?");
#endif

    return JS_TRUE;
}
예제 #7
0
파일: jsiter.cpp 프로젝트: ahadzi/celtx
static JSBool
CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval)
{
    JSObject *obj, *origobj;
    jsval state;
    JSBool foreach;
    jsid id;
    JSObject *obj2;
    JSBool cond;
    JSClass *clasp;
    JSExtendedClass *xclasp;
    JSProperty *prop;
    JSString *str;

    JS_ASSERT(flags & JSITER_ENUMERATE);
    JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);

    obj = STOBJ_GET_PARENT(iterobj);
    origobj = STOBJ_GET_PROTO(iterobj);
    state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
    if (JSVAL_IS_NULL(state))
        goto stop;

    foreach = (flags & JSITER_FOREACH) != 0;
#if JS_HAS_XML_SUPPORT
    /*
     * Treat an XML object specially only when it starts the prototype chain.
     * Otherwise we need to do the usual deleted and shadowed property checks.
     */
    if (obj == origobj && OBJECT_IS_XML(cx, obj)) {
        if (foreach) {
            JSXMLObjectOps *xmlops = (JSXMLObjectOps *) obj->map->ops;

            if (!xmlops->enumerateValues(cx, obj, JSENUMERATE_NEXT, &state,
                                         &id, rval)) {
                return JS_FALSE;
            }
        } else {
            if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
                return JS_FALSE;
        }
        STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
        if (JSVAL_IS_NULL(state))
            goto stop;
    } else
#endif
    {
      restart:
        if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
            return JS_FALSE;

        STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
        if (JSVAL_IS_NULL(state)) {
#if JS_HAS_XML_SUPPORT
            if (OBJECT_IS_XML(cx, obj)) {
                /*
                 * We just finished enumerating an XML obj that is present on
                 * the prototype chain of a non-XML origobj. Stop further
                 * prototype chain searches because XML objects don't
                 * enumerate prototypes.
                 */
                JS_ASSERT(origobj != obj);
                JS_ASSERT(!OBJECT_IS_XML(cx, origobj));
            } else
#endif
            {
                obj = OBJ_GET_PROTO(cx, obj);
                if (obj) {
                    STOBJ_SET_PARENT(iterobj, obj);
                    if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL))
                        return JS_FALSE;
                    STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
                    if (!JSVAL_IS_NULL(state))
                        goto restart;
                }
            }
            goto stop;
        }

        /* Skip properties not in obj when looking from origobj. */
        if (!OBJ_LOOKUP_PROPERTY(cx, origobj, id, &obj2, &prop))
            return JS_FALSE;
        if (!prop)
            goto restart;
        OBJ_DROP_PROPERTY(cx, obj2, prop);

        /*
         * If the id was found in a prototype object or an unrelated object
         * (specifically, not in an inner object for obj), skip it. This step
         * means that all OBJ_LOOKUP_PROPERTY implementations must return an
         * object further along on the prototype chain, or else possibly an
         * object returned by the JSExtendedClass.outerObject optional hook.
         */
        if (obj != obj2) {
            cond = JS_FALSE;
            clasp = OBJ_GET_CLASS(cx, obj2);
            if (clasp->flags & JSCLASS_IS_EXTENDED) {
                xclasp = (JSExtendedClass *) clasp;
                cond = xclasp->outerObject &&
                    xclasp->outerObject(cx, obj2) == obj;
            }
            if (!cond)
                goto restart;
        }

        if (foreach) {
            /* Get property querying the original object. */
            if (!OBJ_GET_PROPERTY(cx, origobj, id, rval))
                return JS_FALSE;
        }
    }

    if (foreach) {
        if (flags & JSITER_KEYVALUE) {
            if (!NewKeyValuePair(cx, id, *rval, rval))
                return JS_FALSE;
        }
    } else {
        /* Make rval a string for uniformity and compatibility. */
        str = js_ValueToString(cx, ID_TO_VALUE(id));
        if (!str)
            return JS_FALSE;
        *rval = STRING_TO_JSVAL(str);
    }
    return JS_TRUE;

  stop:
    JS_ASSERT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE) == JSVAL_NULL);
    *rval = JSVAL_HOLE;
    return JS_TRUE;
}