Exemplo n.º 1
0
JSBool
WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
  // Slim wrappers don't expect to be wrapped, so morph them to fat wrappers
  // if we're about to wrap one.
  JSObject *innerObj = JSVAL_TO_OBJECT(v);
  if (IS_SLIM_WRAPPER(innerObj) && !MorphSlimWrapper(cx, innerObj)) {
    return ThrowException(NS_ERROR_FAILURE, cx);
  }

  JSObject *wrapperObj =
    JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SOWClass), NULL, parent);
  if (!wrapperObj) {
    return JS_FALSE;
  }

  *vp = OBJECT_TO_JSVAL(wrapperObj);
  js::AutoObjectRooter tvr(cx, wrapperObj);

  if (!JS_SetReservedSlot(cx, wrapperObj, sWrappedObjSlot, v) ||
      !JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, JSVAL_ZERO)) {
    return JS_FALSE;
  }

  return JS_TRUE;
}
Exemplo n.º 2
0
JSBool
js_json_stringify(JSContext *cx, uintN argc, jsval *vp)
{
    jsval *argv = vp + 2;
    JSObject *replacer = NULL;
    jsval space = JSVAL_NULL;
    JSAutoTempValueRooter tvr(cx, replacer);
    JSAutoTempValueRooter tvr2(cx, 1, &space);

    // Must throw an Error if there isn't a first arg
    if (!JS_ConvertArguments(cx, argc, argv, "v / o v", vp, &replacer, &space))
        return JS_FALSE;

    JSCharBuffer cb(cx);

    if (!js_Stringify(cx, vp, replacer, space, cb))
        return JS_FALSE;

    // XXX This can never happen to nsJSON.cpp, but the JSON object
    // needs to support returning undefined. So this is a little awkward
    // for the API, because we want to support streaming writers.
    if (!cb.empty()) {
        JSString *str = js_NewStringFromCharBuffer(cx, cb);
        if (!str)
            return JS_FALSE;
        *vp = STRING_TO_JSVAL(str);
    } else {
        *vp = JSVAL_VOID;
    }

    return JS_TRUE;
}
Exemplo n.º 3
0
static JSObject *
XPC_COW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
  JSObject *wrappedObj = GetWrappedObject(cx, obj);
  if (!wrappedObj) {
    ThrowException(NS_ERROR_INVALID_ARG, cx);
    return nsnull;
  }

  XPCCallContext ccx(JS_CALLER, cx);
  if (!ccx.IsValid()) {
    ThrowException(NS_ERROR_FAILURE, cx);
    return nsnull;
  }

  JSObject *wrapperIter = JS_NewObject(cx, &sXPC_COW_JSClass.base, nsnull,
                                       JS_GetGlobalForObject(cx, obj));
  if (!wrapperIter) {
    return nsnull;
  }

  JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));

  // Initialize our COW.
  jsval v = OBJECT_TO_JSVAL(wrappedObj);
  if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
      !JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
                          JSVAL_ZERO)) {
    return nsnull;
  }

  return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, wrappedObj,
                                       keysonly);
}
Exemplo n.º 4
0
static JSObject *
GeneratePropertyOp(JSContext *cx, JSObject *obj, jsval idval, uintN argc,
                   const char *name, JSPropertyOp pop)
{
    // The JS engine provides two reserved slots on function objects for
    // XPConnect to use. Use them to stick the necessary info here.
    JSFunction *fun =
        JS_NewFunction(cx, reinterpret_cast<JSNative>(PropertyOpForwarder),
                       argc, JSFUN_FAST_NATIVE, obj, name);
    if(!fun)
        return JS_FALSE;

    JSObject *funobj = JS_GetFunctionObject(fun);

    JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(funobj));

    // Unfortunately, we cannot guarantee that JSPropertyOp is aligned. Use a
    // second object to work around this.
    JSObject *ptrobj = JS_NewObject(cx, &PointerHolderClass, nsnull, funobj);
    if(!ptrobj)
        return JS_FALSE;
    JSPropertyOp *popp = new JSPropertyOp;
    if(!popp)
        return JS_FALSE;
    *popp = pop;
    JS_SetPrivate(cx, ptrobj, popp);

    JS_SetReservedSlot(cx, funobj, 0, OBJECT_TO_JSVAL(ptrobj));
    JS_SetReservedSlot(cx, funobj, 1, idval);
    return funobj;
}
Exemplo n.º 5
0
JSBool
XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp)
{
  JSObject *wrapperObj =
    JS_NewObjectWithGivenProto(cx, &sXPC_COW_JSClass.base, NULL, parent);
  if (!wrapperObj) {
    return JS_FALSE;
  }

  *vp = OBJECT_TO_JSVAL(wrapperObj);

  jsval exposedProps = JSVAL_VOID;
  JSAutoTempValueRooter tvr(cx, 1, &exposedProps);

  if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) {
    return JS_FALSE;
  }

  if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
      !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
                          JSVAL_ZERO) ||
      !JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) {
    return JS_FALSE;
  }

  return JS_TRUE;
}
// 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;
}
Exemplo n.º 7
0
static JSObject *
XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    ThrowException(NS_ERROR_INVALID_ARG, cx);

    return nsnull;
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return nsnull;
  }

  JSObject *tmp = XPCWrapper::UnwrapGeneric(cx, &sXPC_XOW_JSClass, unsafeObj);
  if (tmp) {
    unsafeObj = tmp;

    // Repeat the CanCallerAccess check because the XOW is parented to our
    // scope's global object which makes the above CanCallerAccess call lie.
    if (!CanCallerAccess(cx, unsafeObj)) {
      // CanCallerAccess() already threw for us.
      return nsnull;
    }
  }

  // Create our dummy SJOW.
  JSObject *wrapperIter =
    ::JS_NewObjectWithGivenProto(cx, &sXPC_SJOW_JSClass.base, nsnull,
                                 unsafeObj);
  if (!wrapperIter) {
    return nsnull;
  }

  if (!::JS_SetReservedSlot(cx, wrapperIter, XPC_SJOW_SLOT_IS_RESOLVING,
                            JSVAL_ZERO)) {
    return nsnull;
  }

  JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));

  // Initialize the wrapper.
  return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, unsafeObj,
                                       keysonly);
}
static JSObject *
XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
  JSObject *wrappedObj = GetWrappedObject(cx, obj);
  if (!wrappedObj) {
    ThrowException(NS_ERROR_INVALID_ARG, cx);
    return nsnull;
  }

  XPCCallContext ccx(JS_CALLER, cx);
  if (!ccx.IsValid()) {
    ThrowException(NS_ERROR_FAILURE, cx);
    return nsnull;
  }

  nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
  if (NS_FAILED(rv)) {
    if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
      // Can't create iterators for foreign objects.
      ThrowException(rv, cx);
      return nsnull;
    }

    ThrowException(NS_ERROR_FAILURE, cx);
    return nsnull;
  }

  JSObject *wrapperIter = JS_NewObject(cx, &sXPC_XOW_JSClass.base, nsnull,
                                       JS_GetGlobalForObject(cx, obj));
  if (!wrapperIter) {
    return nsnull;
  }

  JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));

  // Initialize our XOW.
  jsval v = OBJECT_TO_JSVAL(wrappedObj);
  if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot, v) ||
      !JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
                          JSVAL_ZERO) ||
      !JS_SetReservedSlot(cx, wrapperIter, XPC_XOW_ScopeSlot,
                          PRIVATE_TO_JSVAL(nsnull))) {
    return nsnull;
  }

  return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, wrappedObj,
                                       keysonly);
}
Exemplo n.º 9
0
nsresult
mozilla::dom::bluetooth::StringArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
                                              const nsTArray<nsString>& aSourceArray,
                                              JSObject** aResultArray)
{
  NS_ASSERTION(aCx, "Null context!");
  NS_ASSERTION(aGlobal, "Null global!");

  JSAutoRequest ar(aCx);
  JSAutoEnterCompartment ac;
  if (!ac.enter(aCx, aGlobal)) {
    NS_WARNING("Failed to enter compartment!");
    return NS_ERROR_FAILURE;
  }

  JSObject* arrayObj;

  if (aSourceArray.IsEmpty()) {
    arrayObj = JS_NewArrayObject(aCx, 0, nullptr);
  } else {
    uint32_t valLength = aSourceArray.Length();
    mozilla::ScopedDeleteArray<jsval> valArray(new jsval[valLength]);
    JS::AutoArrayRooter tvr(aCx, valLength, valArray);
    for (PRUint32 index = 0; index < valLength; index++) {
      JSString* s = JS_NewUCStringCopyN(aCx, aSourceArray[index].BeginReading(),
                                        aSourceArray[index].Length());
      if(!s) {
        NS_WARNING("Memory allocation error!");
        return NS_ERROR_OUT_OF_MEMORY;
      }
      valArray[index] = STRING_TO_JSVAL(s);
    }
    arrayObj = JS_NewArrayObject(aCx, valLength, valArray);
  }

  if (!arrayObj) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // XXX This is not what Jonas wants. He wants it to be live.
  // Followup at bug 717414
  if (!JS_FreezeObject(aCx, arrayObj)) {
    return NS_ERROR_FAILURE;
  }

  *aResultArray = arrayObj;
  return NS_OK;
}
Exemplo n.º 10
0
static JSBool
JA(JSContext *cx, jsval *vp, StringifyContext *scx)
{
    JSObject *obj = JSVAL_TO_OBJECT(*vp);

    if (!scx->cb.append('['))
        return JS_FALSE;

    jsuint length;
    if (!js_GetLengthProperty(cx, obj, &length))
        return JS_FALSE;

    jsval outputValue = JSVAL_NULL;
    JSAutoTempValueRooter tvr(cx, 1, &outputValue);

    jsid id;
    jsuint i;
    for (i = 0; i < length; i++) {
        id = INT_TO_JSID(i);

        if (!obj->getProperty(cx, id, &outputValue))
            return JS_FALSE;

        if (!Str(cx, id, obj, scx, &outputValue))
            return JS_FALSE;

        if (outputValue == JSVAL_VOID) {
            if (!js_AppendLiteral(scx->cb, "null"))
                return JS_FALSE;
        }

        if (i < length - 1) {
            if (!scx->cb.append(','))
                return JS_FALSE;
            if (!WriteIndent(cx, scx, scx->depth))
                return JS_FALSE;
        }
    }

    if (length != 0 && !WriteIndent(cx, scx, scx->depth - 1))
        return JS_FALSE;

    return scx->cb.append(']');
}
Exemplo n.º 11
0
static JSBool
ReifyPropertyOps(JSContext *cx, JSObject *obj, jsval idval, jsid interned_id,
                 const char *name, JSPropertyOp getter, JSPropertyOp setter,
                 JSObject **getterobjp, JSObject **setterobjp)
{
    // Generate both getter and setter and stash them in the prototype.
    jsval roots[2] = { JSVAL_NULL, JSVAL_NULL };
    JSAutoTempValueRooter tvr(cx, 2, roots);

    uintN attrs = JSPROP_SHARED;
    JSObject *getterobj;
    if(getter)
    {
        getterobj = GeneratePropertyOp(cx, obj, idval, 0, name, getter);
        if(!getterobj)
            return JS_FALSE;
        roots[0] = OBJECT_TO_JSVAL(getterobj);
        attrs |= JSPROP_GETTER;
    }
    else
        getterobj = nsnull;

    JSObject *setterobj;
    if (setter)
    {
        setterobj = GeneratePropertyOp(cx, obj, idval, 1, name, setter);
        if(!setterobj)
            return JS_FALSE;
        roots[1] = OBJECT_TO_JSVAL(setterobj);
        attrs |= JSPROP_SETTER;
    }
    else
        setterobj = nsnull;

    if(getterobjp)
        *getterobjp = getterobj;
    if(setterobjp)
        *setterobjp = setterobj;
    return JS_DefinePropertyById(cx, obj, interned_id, JSVAL_VOID,
                                 JS_DATA_TO_FUNC_PTR(JSPropertyOp, getterobj),
                                 JS_DATA_TO_FUNC_PTR(JSPropertyOp, setterobj),
                                 attrs);
}
Exemplo n.º 12
0
static JSBool
PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
{
    JSAutoTempValueRooter tvr(cx, 1, &value);
  
    JSBool ok;
    if (OBJ_IS_ARRAY(cx, parent)) {
        jsuint len;
        ok = JS_GetArrayLength(cx, parent, &len);
        if (ok)
            ok = JS_SetElement(cx, parent, len, &value);
    } else {
        ok = JS_DefineUCProperty(cx, parent, JS_GetStringChars(jp->objectKey),
                                 JS_GetStringLength(jp->objectKey), value,
                                 NULL, NULL, JSPROP_ENUMERATE);
    }
 
    return ok;
}
Exemplo n.º 13
0
static JSBool
PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
{
    jsuint len;
    if (!js_GetLengthProperty(cx, jp->objectStack, &len))
        return JS_FALSE;
    if (len >= JSON_MAX_DEPTH)
        return JS_FALSE; // decoding error

    jsval v = OBJECT_TO_JSVAL(obj);
    JSAutoTempValueRooter tvr(cx, v);

    // Check if this is the root object
    if (len == 0) {
        *jp->rootVal = v;
        // This property must be enumerable to keep the array dense
        if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(0), *jp->rootVal,
                                 NULL, NULL, JSPROP_ENUMERATE, NULL)) {
            return JS_FALSE;
        }
        return JS_TRUE;
    }

    jsval p;
    if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len - 1), &p))
        return JS_FALSE;

    JS_ASSERT(JSVAL_IS_OBJECT(p));
    JSObject *parent = JSVAL_TO_OBJECT(p);
    if (!PushValue(cx, jp, parent, OBJECT_TO_JSVAL(obj)))
        return JS_FALSE;

    // This property must be enumerable to keep the array dense
    if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len), v,
                             NULL, NULL, JSPROP_ENUMERATE, NULL)) {
        return JS_FALSE;
    }

    return JS_TRUE;
}
Exemplo n.º 14
0
JSBool
js_json_parse(JSContext *cx, uintN argc, jsval *vp)
{
    JSString *s = NULL;
    jsval *argv = vp + 2;
    jsval reviver = JSVAL_NULL;
    JSAutoTempValueRooter tvr(cx, 1, &reviver);

    if (!JS_ConvertArguments(cx, argc, argv, "S / v", &s, &reviver))
        return JS_FALSE;

    JSONParser *jp = js_BeginJSONParse(cx, vp);
    JSBool ok = jp != NULL;
    if (ok) {
        const jschar *chars;
        size_t length;
        s->getCharsAndLength(chars, length);
        ok = js_ConsumeJSONText(cx, jp, chars, length);
        ok &= js_FinishJSONParse(cx, jp, reviver);
    }

    return ok;
}
Exemplo n.º 15
0
static JSBool
PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
{
    JSAutoTempValueRooter tvr(cx, 1, &value);
 
    JSBool ok;
    if (OBJ_IS_ARRAY(cx, parent)) {
        jsuint len;
        ok = js_GetLengthProperty(cx, parent, &len);
        if (ok) {
            ok = OBJ_DEFINE_PROPERTY(cx, parent, INT_TO_JSID(len), value,
                                     NULL, NULL, JSPROP_ENUMERATE, NULL);
        }
    } else {
        ok = JS_DefineUCProperty(cx, parent, jp->objectKey->base,
                                 STRING_BUFFER_OFFSET(jp->objectKey), value,
                                 NULL, NULL, JSPROP_ENUMERATE);
        js_FinishStringBuffer(jp->objectKey);
        js_InitStringBuffer(jp->objectKey);
    }

    return ok;
}
Exemplo n.º 16
0
static JSBool
js_json_stringify(JSContext *cx, JSObject* pThis, uintN argc, jsval *vp, jsval* rval)
{
    JSObject *obj;
    jsval *argv = vp;
    
    // Must throw an Error if there isn't a first arg
    if (!JS_ConvertArguments(cx, argc, argv, "o", &obj))
        return JS_FALSE;
 
    // Only use objects and arrays as the root for now
    jsval v = OBJECT_TO_JSVAL(obj);
    JSBool ok = js_TryJSON(cx, &v);
    JSType type;
    if (!(ok && !JSVAL_IS_PRIMITIVE(v) &&
          (type = JS_TypeOfValue(cx, v)) != JSTYPE_FUNCTION &&
          type != JSTYPE_XML)) {
        JS_ReportError(cx, "Invalid argument.");
        return JS_FALSE;
    }
    
    JSString *s = JS_NewStringCopyN(cx, "", 0);
    if (!s)
        ok = JS_FALSE;
 
    if (ok) {
        jsval sv = STRING_TO_JSVAL(s);
        StringifyClosure sc;
        sc.cx = cx;
        sc.s = &sv;
	JSAutoTempValueRooter tvr(cx, 1, sc.s); 
        ok = js_Stringify(cx, &v, NULL, &WriteCallback, &sc, 0);
        *rval = *sc.s;
    }
 
    return ok;
}
Exemplo n.º 17
0
static void
TestArgFormatter(JSContext* jscontext, JSObject* glob, nsIXPConnect* xpc)
{
    JSBool ok = JS_TRUE;

    const char*                  a_in = "some string";
    nsCOMPtr<nsITestXPCFoo>      b_in = new nsTestXPCFoo();
    nsCOMPtr<nsIWritableVariant> c_in = do_CreateInstance("@mozilla.org/variant;1"); 
    static NS_NAMED_LITERAL_STRING(d_in, "foo bar");
    const char*                  e_in = "another meaningless chunck of text";
    

    JSBool                  a_match;
    nsCOMPtr<nsISupports>   b_out;
    nsCOMPtr<nsIVariant>    c_out;
    nsAutoString            d_out;
    JSBool                  e_match;

    nsCOMPtr<nsITestXPCFoo> specified;
    PRInt32                 val;

    printf("ArgumentFormatter test: ");

    if(!b_in || !c_in || NS_FAILED(c_in->SetAsInt32(5)))
    {
        printf(" failed to construct test objects -- FAILED!\n");
        return;
    }

    do {
        JSAutoRequest ar(jscontext);

        // Prepare an array of arguments for JS_ConvertArguments
        jsval argv[5];
        js::AutoArrayRooter tvr(jscontext, JS_ARRAY_LENGTH(argv), argv);

        if (!PushArguments(jscontext, 5, argv,
                           "s %ip %iv %is s",
                           a_in,
                           &NS_GET_IID(nsITestXPCFoo2), b_in.get(),
                           c_in.get(),
                           static_cast<const nsAString*>(&d_in),
                           e_in))
        {
            printf(" could not convert from native to JS -- FAILED!\n");
            return;
        }

        JSString *a_out, *e_out;
        ok = JS_ConvertArguments(jscontext, 5, argv, "S %ip %iv %is S",
                                &a_out, 
                                static_cast<nsISupports**>(getter_AddRefs(b_out)), 
                                static_cast<nsIVariant**>(getter_AddRefs(c_out)),
                                static_cast<nsAString*>(&d_out), 
                                 &e_out);
        TAF_CHECK(ok, " could not convert from JS to native -- FAILED!\n");
        TAF_CHECK(b_out, " JS to native for %%ip returned NULL -- FAILED!\n");
    
        specified = do_QueryInterface(b_out);
        TAF_CHECK(specified, " could not QI value JS to native returned -- FAILED!\n");
        ok = specified.get() == b_in.get();
        TAF_CHECK(ok, " JS to native returned wrong value -- FAILED!\n");
        TAF_CHECK(c_out, " JS to native for %%iv returned NULL -- FAILED!\n");
        TAF_CHECK(NS_SUCCEEDED(c_out->GetAsInt32(&val)) && val == 5, " JS to native for %%iv holds wrong value -- FAILED!\n");
        TAF_CHECK(d_in.Equals(d_out), " JS to native for %%is returned the wrong value -- FAILED!\n");
        TAF_CHECK(JS_StringEqualsAscii(jscontext, a_out, a_in, &a_match), " oom -- FAILED!\n");
        TAF_CHECK(JS_StringEqualsAscii(jscontext, e_out, e_in, &e_match), " oom -- FAILED!\n");
    } while (0);
    if (!ok)
        return;

    if(a_match && e_match)
        printf("passed\n");
    else
        printf(" conversion OK, but surrounding was mangled -- FAILED!\n");
}
Exemplo n.º 18
0
JSBool
js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
             JSONWriteCallback callback, void *data, uint32 depth)
{
    if (depth > JSON_MAX_DEPTH)
        return JS_FALSE; /* encoding error */
 
    JSBool ok = JS_TRUE;
    JSObject *obj = JSVAL_TO_OBJECT(*vp);
    JSBool isArray = JS_IsArrayObject(cx, obj);
    jschar output = jschar(isArray ? '[' : '{');
    if (!callback(&output, 1, data))
        return JS_FALSE;
    
    JSObject *iterObj = NULL;
    jsint i = 0;
    jsuint length = 0;
 
    if (isArray) {
        if (!JS_GetArrayLength(cx, obj, &length))
            return JS_FALSE;
    } else {
        if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp))
            return JS_FALSE;
        iterObj = JSVAL_TO_OBJECT(*vp);
    }
 
    jsval outputValue = JSVAL_VOID;
    JSAutoTempValueRooter tvr(cx, 1, &outputValue);
 
    jsval key;
    JSBool memberWritten = JS_FALSE;
    do {
        outputValue = JSVAL_VOID;
 
        if (isArray) {
            if ((jsuint)i >= length)
                break;
            ok = JS_GetElement(cx, obj, i++, &outputValue);
        } else {
            ok = js_CallIteratorNext(cx, iterObj, &key);
            if (!ok)
                break;
            if (key == JSVAL_HOLE)
                break;
 
            JSString *ks;
            if (JSVAL_IS_STRING(key)) {
                ks = JSVAL_TO_STRING(key);
            } else {
                ks = JS_ValueToString(cx, key);
                if (!ks) {
                    ok = JS_FALSE;
                    break;
                }
            }
 
            ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks),
                                  JS_GetStringLength(ks), &outputValue);
        }
 
        if (!ok)
            break;
 
        // if this is an array, holes are transmitted as null
        if (isArray && outputValue == JSVAL_VOID) {
            outputValue = JSVAL_NULL;
        } else if (JSVAL_IS_OBJECT(outputValue)) {
            ok = js_TryJSON(cx, &outputValue);
            if (!ok)
                break;
        }
 
        // elide undefined values
        if (outputValue == JSVAL_VOID)
            continue;
 
        // output a comma unless this is the first member to write
        if (memberWritten) {
            output = jschar(',');
            ok = callback(&output, 1, data);
        if (!ok)
                break;
        }
        memberWritten = JS_TRUE;
 
        JSType type = JS_TypeOfValue(cx, outputValue);
 
        // Can't encode these types, so drop them
        if (type == JSTYPE_FUNCTION || type == JSTYPE_XML)
            break;
 
        // Be careful below, this string is weakly rooted.
        JSString *s;
 
        // If this isn't an array, we need to output a key
        if (!isArray) {
            s = JS_ValueToString(cx, key);
            if (!s) {
                ok = JS_FALSE;
                break;
            }
 
            ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
            if (!ok)
                break;
 
            output = jschar(':');
            ok = callback(&output, 1, data);
            if (!ok)
                break;
        }
 
        if (!JSVAL_IS_PRIMITIVE(outputValue)) {
            // recurse
          ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1);
        } else {
            JSString *outputString;
            s = JS_ValueToString(cx, outputValue);
            if (!s) {
                ok = JS_FALSE;
                break;
            }
 
            if (type == JSTYPE_STRING) {
                ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
                if (!ok)
                    break;
                
                continue;
            }
 
            if (type == JSTYPE_NUMBER) {
                if (JSVAL_IS_DOUBLE(outputValue)) {
                    jsdouble d = *JSVAL_TO_DOUBLE(outputValue);
                    if (!JSDOUBLE_IS_FINITE(d))
                        outputString = JS_NewStringCopyN(cx, "null", 4);
                    else
                        outputString = s;
                } else {
                    outputString = s;
                }
            } else if (type == JSTYPE_BOOLEAN) {
                outputString = s;
            } else if (JSVAL_IS_NULL(outputValue)) {
                outputString = JS_NewStringCopyN(cx, "null", 4);
            } else {
                ok = JS_FALSE; // encoding error
                break;
            }
 
            ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data);
        }
    } while (ok);
 
    if (iterObj) {
        // Always close the iterator, but make sure not to stomp on OK
        js_CloseIteratorState(cx, iterObj);
        // encoding error or propagate? FIXME: Bug 408838.
    }
 
    if (!ok) {
        JS_ReportError(cx, "Error during JSON encoding.");
        return JS_FALSE;
    }
 
    output = jschar(isArray ? ']' : '}');
    ok = callback(&output, 1, data);
 
    return ok;
}
Exemplo n.º 19
0
static JSBool
JO(JSContext *cx, jsval *vp, StringifyContext *scx)
{
    JSObject *obj = JSVAL_TO_OBJECT(*vp);

    if (!scx->cb.append('{'))
        return JS_FALSE;

    jsval vec[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
    JSAutoTempValueRooter tvr(cx, 3, vec);
    jsval& key = vec[0];
    jsval& outputValue = vec[1];

    JSObject *iterObj = NULL;
    jsval *keySource = vp;
    bool usingWhitelist = false;

    // if the replacer is an array, we use the keys from it
    if (scx->replacer && JS_IsArrayObject(cx, scx->replacer)) {
        usingWhitelist = true;
        vec[2] = OBJECT_TO_JSVAL(scx->replacer);
        keySource = &vec[2];
    }

    if (!js_ValueToIterator(cx, JSITER_ENUMERATE, keySource))
        return JS_FALSE;
    iterObj = JSVAL_TO_OBJECT(*keySource);

    JSBool memberWritten = JS_FALSE;

    bool ok = false;
    while (true) {
        outputValue = JSVAL_VOID;
        if (!js_CallIteratorNext(cx, iterObj, &key))
            goto error_break;
        if (key == JSVAL_HOLE)
            break;

        jsuint index = 0;
        if (usingWhitelist) {
            // skip non-index properties
            if (!js_IdIsIndex(key, &index))
                continue;

            jsval newKey;
            if (!scx->replacer->getProperty(cx, key, &newKey))
                goto error_break;
            key = newKey;
        }

        JSString *ks;
        if (JSVAL_IS_STRING(key)) {
            ks = JSVAL_TO_STRING(key);
        } else {
            ks = js_ValueToString(cx, key);
            if (!ks)
                goto error_break;
        }
        JSAutoTempValueRooter keyStringRoot(cx, ks);

        // Don't include prototype properties, since this operation is
        // supposed to be implemented as if by ES3.1 Object.keys()
        jsid id;
        jsval v = JS_FALSE;
        if (!js_ValueToStringId(cx, STRING_TO_JSVAL(ks), &id) ||
            !js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v)) {
            goto error_break;
        }

        if (v != JSVAL_TRUE)
            continue;

        if (!JS_GetPropertyById(cx, obj, id, &outputValue))
            goto error_break;

        if (JSVAL_IS_OBJECT(outputValue) && !js_TryJSON(cx, &outputValue))
            goto error_break;

        // call this here, so we don't write out keys if the replacer function
        // wants to elide the value.
        if (!CallReplacerFunction(cx, id, obj, scx, &outputValue))
            goto error_break;

        JSType type = JS_TypeOfValue(cx, outputValue);

        // elide undefined values and functions and XML
        if (outputValue == JSVAL_VOID || type == JSTYPE_FUNCTION || type == JSTYPE_XML)
            continue;

        // output a comma unless this is the first member to write
        if (memberWritten && !scx->cb.append(','))
            goto error_break;
        memberWritten = JS_TRUE;

        if (!WriteIndent(cx, scx, scx->depth))
            goto error_break;

        // Be careful below, this string is weakly rooted
        JSString *s = js_ValueToString(cx, key);
        if (!s)
            goto error_break;

        const jschar *chars;
        size_t length;
        s->getCharsAndLength(chars, length);
        if (!write_string(cx, scx->cb, chars, length) ||
            !scx->cb.append(':') ||
            !Str(cx, id, obj, scx, &outputValue, false)) {
            goto error_break;
        }
    }
    ok = true;

  error_break:
    if (iterObj) {
        // Always close the iterator, but make sure not to stomp on OK
        JS_ASSERT(OBJECT_TO_JSVAL(iterObj) == *keySource);
        ok &= js_CloseIterator(cx, *keySource);
    }

    if (!ok)
        return JS_FALSE;

    if (memberWritten && !WriteIndent(cx, scx, scx->depth - 1))
        return JS_FALSE;

    return scx->cb.append('}');
}
static JSBool
CVE_2012_0478_firefox4_0_1_nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
{
    XPC_QS_ASSERT_CONTEXT_OK(cx);
    JSObject *obj = JS_THIS_OBJECT(cx, vp);
    if (!obj)
        return JS_FALSE;

    nsresult rv;

    nsIDOMWebGLRenderingContext *self;
    xpc_qsSelfRef selfref;
    js::AutoValueRooter tvr(cx);
    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
        return JS_FALSE;

    if (argc < 6 || argc == 7 || argc == 8)
        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);

    jsval *argv = JS_ARGV(cx, vp);

    // arguments common to all cases
    GET_UINT32_ARG(argv0, 0);
    GET_INT32_ARG(argv1, 1);

    if (argc > 5 &&
        !JSVAL_IS_PRIMITIVE(argv[5]))
    {
        // implement the variants taking a DOMElement as argv[5]
        GET_UINT32_ARG(argv2, 2);
        GET_UINT32_ARG(argv3, 3);
        GET_UINT32_ARG(argv4, 4);

        nsIDOMElement *elt;
        xpc_qsSelfRef eltRef;
        rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[5], &elt, &eltRef.ptr, &argv[5]);
        if (NS_FAILED(rv)) return JS_FALSE;

        rv = self->TexImage2D_dom(argv0, argv1, argv2, argv3, argv4, elt);

        if (NS_FAILED(rv)) {
            // failed to interprete argv[5] as a DOMElement, now try to interprete it as ImageData
            JSObject *argv5 = JSVAL_TO_OBJECT(argv[5]);

            jsval js_width, js_height, js_data;
            JS_GetProperty(cx, argv5, "width", &js_width);
            JS_GetProperty(cx, argv5, "height", &js_height);
            JS_GetProperty(cx, argv5, "data", &js_data);
            if (js_width  == JSVAL_VOID ||
                js_height == JSVAL_VOID ||
                js_data   == JSVAL_VOID)
            {
                xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5);
                return JS_FALSE;
            }
            int32 int_width, int_height;
            JSObject *obj_data = JSVAL_TO_OBJECT(js_data);
            if (!JS_ValueToECMAInt32(cx, js_width, &int_width) ||
                !JS_ValueToECMAInt32(cx, js_height, &int_height))
            {
                return JS_FALSE;
            }
            if (!js_IsTypedArray(obj_data))
            {
                xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5);
                return JS_FALSE;
            }
            rv = self->TexImage2D_imageData(argv0, argv1, argv2,
                                            int_width, int_height, 0,
                                            argv3, argv4, js::TypedArray::fromJSObject(obj_data));
        }
    } else if (argc > 8 &&
               JSVAL_IS_OBJECT(argv[8])) // here, we allow null !
    {
        // implement the variants taking a buffer/array as argv[8]
        GET_UINT32_ARG(argv2, 2);
        GET_INT32_ARG(argv3, 3);
        GET_INT32_ARG(argv4, 4);
        GET_INT32_ARG(argv5, 5);
        GET_UINT32_ARG(argv6, 6);
        GET_UINT32_ARG(argv7, 7);

        JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]);

        // then try to grab either a js::ArrayBuffer, js::TypedArray, or null
        if (argv8 == nsnull) {
            rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3,
                                      argv4, argv5, argv6, argv7,
                                      nsnull);
        } else if (js_IsArrayBuffer(argv8)) {
            rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3,
                                      argv4, argv5, argv6, argv7,
                                      js::ArrayBuffer::fromJSObject(argv8));
        } else if (js_IsTypedArray(argv8)) {
            rv = self->TexImage2D_array(argv0, argv1, argv2, argv3,
                                        argv4, argv5, argv6, argv7,
                                        js::TypedArray::fromJSObject(argv8));
        } else {
            xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
            return JS_FALSE;
        }
    } else {
        xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
        return JS_FALSE;
    }

    if (NS_FAILED(rv))
        return xpc_qsThrowMethodFailed(cx, rv, vp);

    *vp = JSVAL_VOID;
    return JS_TRUE;
}
Exemplo n.º 21
0
JSObject *
js_InitExceptionClasses(JSContext *cx, JSObject *obj)
{
    jsval roots[3];
    JSObject *obj_proto, *error_proto;
    jsval empty;

    /*
     * If lazy class initialization occurs for any Error subclass, then all
     * classes are initialized, starting with Error.  To avoid reentry and
     * redundant initialization, we must not pass a null proto parameter to
     * js_NewObject below, when called for the Error superclass.  We need to
     * ensure that Object.prototype is the proto of Error.prototype.
     *
     * See the equivalent code to ensure that parent_proto is non-null when
     * JS_InitClass calls js_NewObject, in jsapi.c.
     */
    if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
                              &obj_proto)) {
        return NULL;
    }

    memset(roots, 0, sizeof(roots));
    JSAutoTempValueRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);

#ifdef __GNUC__
    error_proto = NULL;   /* quell GCC overwarning */
#endif

    /* Initialize the prototypes first. */
    for (intN i = JSEXN_ERR; i != JSEXN_LIMIT; i++) {
        JSObject *proto;
        JSProtoKey protoKey;
        JSAtom *atom;
        JSFunction *fun;

        /* Make the prototype for the current constructor name. */
        proto = js_NewObject(cx, &js_ErrorClass,
                             (i != JSEXN_ERR) ? error_proto : obj_proto,
                             obj);
        if (!proto)
            return NULL;
        if (i == JSEXN_ERR) {
            error_proto = proto;
            roots[0] = OBJECT_TO_JSVAL(proto);
        } else {
            // We cannot share the root for error_proto and other prototypes
            // as error_proto must be rooted until the function returns.
            roots[1] = OBJECT_TO_JSVAL(proto);
        }

        /* So exn_finalize knows whether to destroy private data. */
        proto->setPrivate(NULL);

        /* Make a constructor function for the current name. */
        protoKey = GetExceptionProtoKey(i);
        atom = cx->runtime->atomState.classAtoms[protoKey];
        fun = js_DefineFunction(cx, obj, atom, Exception, 3, 0);
        if (!fun)
            return NULL;
        roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun));

        /* Make this constructor make objects of class Exception. */
        FUN_CLASP(fun) = &js_ErrorClass;

        /* Make the prototype and constructor links. */
        if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
                                  JSPROP_READONLY | JSPROP_PERMANENT)) {
            return NULL;
        }

        /* Add the name property to the prototype. */
        if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_KEY(atom),
                               NULL, NULL, JSPROP_ENUMERATE)) {
            return NULL;
        }

        /* Finally, stash the constructor for later uses. */
        if (!js_SetClassObject(cx, obj, protoKey, FUN_OBJECT(fun)))
            return NULL;
    }

    /*
     * Set default values and add methods. We do it only for Error.prototype
     * as the rest of exceptions delegate to it.
     */
    empty = STRING_TO_JSVAL(cx->runtime->emptyString);
    if (!JS_DefineProperty(cx, error_proto, js_message_str, empty,
                           NULL, NULL, JSPROP_ENUMERATE) ||
        !JS_DefineProperty(cx, error_proto, js_fileName_str, empty,
                           NULL, NULL, JSPROP_ENUMERATE) ||
        !JS_DefineProperty(cx, error_proto, js_lineNumber_str, JSVAL_ZERO,
                           NULL, NULL, JSPROP_ENUMERATE) ||
        !JS_DefineFunctions(cx, error_proto, exception_methods)) {
        return NULL;
    }

    return error_proto;
}