js/xpconnect/src/XPCVariant.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* nsIVariant implementation for xpconnect. */
     9 #include "xpcprivate.h"
    10 #include "nsCxPusher.h"
    12 #include "jsfriendapi.h"
    13 #include "jsprf.h"
    14 #include "jswrapper.h"
    16 using namespace JS;
    17 using namespace mozilla;
    19 NS_IMPL_CLASSINFO(XPCVariant, nullptr, 0, XPCVARIANT_CID)
    20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCVariant)
    21   NS_INTERFACE_MAP_ENTRY(XPCVariant)
    22   NS_INTERFACE_MAP_ENTRY(nsIVariant)
    23   NS_INTERFACE_MAP_ENTRY(nsISupports)
    24   NS_IMPL_QUERY_CLASSINFO(XPCVariant)
    25 NS_INTERFACE_MAP_END
    26 NS_IMPL_CI_INTERFACE_GETTER(XPCVariant, XPCVariant, nsIVariant)
    28 NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant)
    29 NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
    31 XPCVariant::XPCVariant(JSContext* cx, jsval aJSVal)
    32     : mJSVal(aJSVal), mCCGeneration(0)
    33 {
    34     nsVariant::Initialize(&mData);
    35     if (!mJSVal.isPrimitive()) {
    36         // XXXbholley - The innerization here was from bug 638026. Blake says
    37         // the basic problem was that we were storing the C++ inner but the JS
    38         // outer, which meant that, after navigation, the JS inner could be
    39         // collected, which would cause us to try to recreate the JS inner at
    40         // some later point after teardown, which would crash. This is shouldn't
    41         // be a problem anymore because SetParentToWindow will do the right
    42         // thing, but I'm saving the cleanup here for another day. Blake thinks
    43         // that we should just not store the WN if we're creating a variant for
    44         // an outer window.
    45         JS::RootedObject obj(cx, &mJSVal.toObject());
    46         obj = JS_ObjectToInnerObject(cx, obj);
    47         mJSVal = JS::ObjectValue(*obj);
    49         JSObject *unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
    50         mReturnRawObject = !(unwrapped && IS_WN_REFLECTOR(unwrapped));
    51     } else
    52         mReturnRawObject = false;
    53 }
    55 XPCTraceableVariant::~XPCTraceableVariant()
    56 {
    57     jsval val = GetJSValPreserveColor();
    59     MOZ_ASSERT(JSVAL_IS_GCTHING(val), "Must be traceable or unlinked");
    61     // If val is JSVAL_STRING, we don't need to clean anything up; simply
    62     // removing the string from the root set is good.
    63     if (!JSVAL_IS_STRING(val))
    64         nsVariant::Cleanup(&mData);
    66     if (!JSVAL_IS_NULL(val))
    67         RemoveFromRootSet();
    68 }
    70 void XPCTraceableVariant::TraceJS(JSTracer* trc)
    71 {
    72     MOZ_ASSERT(mJSVal.isMarkable());
    73     trc->setTracingDetails(GetTraceName, this, 0);
    74     JS_CallHeapValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
    75 }
    77 // static
    78 void
    79 XPCTraceableVariant::GetTraceName(JSTracer* trc, char *buf, size_t bufsize)
    80 {
    81     JS_snprintf(buf, bufsize, "XPCVariant[0x%p].mJSVal", trc->debugPrintArg());
    82 }
    84 NS_IMPL_CYCLE_COLLECTION_CLASS(XPCVariant)
    86 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPCVariant)
    87     JS::Value val = tmp->GetJSValPreserveColor();
    88     if (val.isObjectOrNull()) {
    89         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mJSVal");
    90         cb.NoteJSChild(JSVAL_TO_OBJECT(val));
    91     }
    93     nsVariant::Traverse(tmp->mData, cb);
    94 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    96 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
    97     JS::Value val = tmp->GetJSValPreserveColor();
    99     // We're sharing val's buffer, clear the pointer to it so Cleanup() won't
   100     // try to delete it
   101     if (val.isString())
   102         tmp->mData.u.wstr.mWStringValue = nullptr;
   103     nsVariant::Cleanup(&tmp->mData);
   105     if (val.isMarkable()) {
   106         XPCTraceableVariant *v = static_cast<XPCTraceableVariant*>(tmp);
   107         v->RemoveFromRootSet();
   108     }
   109     tmp->mJSVal = JS::NullValue();
   110 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   112 // static
   113 already_AddRefed<XPCVariant>
   114 XPCVariant::newVariant(JSContext* cx, jsval aJSVal)
   115 {
   116     nsRefPtr<XPCVariant> variant;
   118     if (!aJSVal.isMarkable())
   119         variant = new XPCVariant(cx, aJSVal);
   120     else
   121         variant = new XPCTraceableVariant(cx, aJSVal);
   123     if (!variant->InitializeData(cx))
   124         return nullptr;
   126     return variant.forget();
   127 }
   129 // Helper class to give us a namespace for the table based code below.
   130 class XPCArrayHomogenizer
   131 {
   132 private:
   133     enum Type
   134     {
   135         tNull  = 0 ,  // null value
   136         tInt       ,  // Integer
   137         tDbl       ,  // Double
   138         tBool      ,  // Boolean
   139         tStr       ,  // String
   140         tID        ,  // ID
   141         tArr       ,  // Array
   142         tISup      ,  // nsISupports (really just a plain JSObject)
   143         tUnk       ,  // Unknown. Used only for initial state.
   145         tTypeCount ,  // Just a count for table dimensioning.
   147         tVar       ,  // nsVariant - last ditch if no other common type found.
   148         tErr          // No valid state or type has this value.
   149     };
   151     // Table has tUnk as a state (column) but not as a type (row).
   152     static const Type StateTable[tTypeCount][tTypeCount-1];
   154 public:
   155     static bool GetTypeForArray(JSContext* cx, HandleObject array,
   156                                 uint32_t length,
   157                                 nsXPTType* resultType, nsID* resultID);
   158 };
   161 // Current state is the column down the side.
   162 // Current type is the row along the top.
   163 // New state is in the box at the intersection.
   165 const XPCArrayHomogenizer::Type
   166 XPCArrayHomogenizer::StateTable[tTypeCount][tTypeCount-1] = {
   167 /*          tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tArr ,tISup */
   168 /* tNull */{tNull,tVar ,tVar ,tVar ,tStr ,tID  ,tVar ,tISup },
   169 /* tInt  */{tVar ,tInt ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
   170 /* tDbl  */{tVar ,tDbl ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
   171 /* tBool */{tVar ,tVar ,tVar ,tBool,tVar ,tVar ,tVar ,tVar  },
   172 /* tStr  */{tStr ,tVar ,tVar ,tVar ,tStr ,tVar ,tVar ,tVar  },
   173 /* tID   */{tID  ,tVar ,tVar ,tVar ,tVar ,tID  ,tVar ,tVar  },
   174 /* tArr  */{tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr  },
   175 /* tISup */{tISup,tVar ,tVar ,tVar ,tVar ,tVar ,tVar ,tISup },
   176 /* tUnk  */{tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tVar ,tISup }};
   178 // static
   179 bool
   180 XPCArrayHomogenizer::GetTypeForArray(JSContext* cx, HandleObject array,
   181                                      uint32_t length,
   182                                      nsXPTType* resultType, nsID* resultID)
   183 {
   184     Type state = tUnk;
   185     Type type;
   187     RootedValue val(cx);
   188     RootedObject jsobj(cx);
   189     for (uint32_t i = 0; i < length; i++) {
   190         if (!JS_GetElement(cx, array, i, &val))
   191             return false;
   193         if (val.isInt32()) {
   194             type = tInt;
   195         } else if (val.isDouble()) {
   196             type = tDbl;
   197         } else if (val.isBoolean()) {
   198             type = tBool;
   199         } else if (val.isUndefined()) {
   200             state = tVar;
   201             break;
   202         } else if (val.isNull()) {
   203             type = tNull;
   204         } else if (val.isString()) {
   205             type = tStr;
   206         } else {
   207             MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
   208             jsobj = &val.toObject();
   209             if (JS_IsArrayObject(cx, jsobj))
   210                 type = tArr;
   211             else if (xpc_JSObjectIsID(cx, jsobj))
   212                 type = tID;
   213             else
   214                 type = tISup;
   215         }
   217         MOZ_ASSERT(state != tErr, "bad state table!");
   218         MOZ_ASSERT(type  != tErr, "bad type!");
   219         MOZ_ASSERT(type  != tVar, "bad type!");
   220         MOZ_ASSERT(type  != tUnk, "bad type!");
   222         state = StateTable[state][type];
   224         MOZ_ASSERT(state != tErr, "bad state table!");
   225         MOZ_ASSERT(state != tUnk, "bad state table!");
   227         if (state == tVar)
   228             break;
   229     }
   231     switch (state) {
   232         case tInt :
   233             *resultType = nsXPTType((uint8_t)TD_INT32);
   234             break;
   235         case tDbl :
   236             *resultType = nsXPTType((uint8_t)TD_DOUBLE);
   237             break;
   238         case tBool:
   239             *resultType = nsXPTType((uint8_t)TD_BOOL);
   240             break;
   241         case tStr :
   242             *resultType = nsXPTType((uint8_t)TD_PWSTRING);
   243             break;
   244         case tID  :
   245             *resultType = nsXPTType((uint8_t)TD_PNSIID);
   246             break;
   247         case tISup:
   248             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
   249             *resultID = NS_GET_IID(nsISupports);
   250             break;
   251         case tNull:
   252             // FALL THROUGH
   253         case tVar :
   254             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
   255             *resultID = NS_GET_IID(nsIVariant);
   256             break;
   257         case tArr :
   258             // FALL THROUGH
   259         case tUnk :
   260             // FALL THROUGH
   261         case tErr :
   262             // FALL THROUGH
   263         default:
   264             NS_ERROR("bad state");
   265             return false;
   266     }
   267     return true;
   268 }
   270 bool XPCVariant::InitializeData(JSContext* cx)
   271 {
   272     JS_CHECK_RECURSION(cx, return false);
   274     RootedValue val(cx, GetJSVal());
   276     if (val.isInt32())
   277         return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, val.toInt32()));
   278     if (val.isDouble())
   279         return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData, val.toDouble()));
   280     if (val.isBoolean())
   281         return NS_SUCCEEDED(nsVariant::SetFromBool(&mData, val.toBoolean()));
   282     if (val.isUndefined())
   283         return NS_SUCCEEDED(nsVariant::SetToVoid(&mData));
   284     if (val.isNull())
   285         return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData));
   286     if (val.isString()) {
   287         JSString* str = val.toString();
   288         if (!str)
   289             return false;
   291         // Don't use nsVariant::SetFromWStringWithSize, because that will copy
   292         // the data.  Just handle this ourselves.  Note that it's ok to not
   293         // copy because we added mJSVal as a GC root.
   294         MOZ_ASSERT(mData.mType == nsIDataType::VTYPE_EMPTY,
   295                    "Why do we already have data?");
   297         // Despite the fact that the variant holds the length, there are
   298         // implicit assumptions that mWStringValue[mWStringLength] == 0
   299         size_t length;
   300         const jschar *chars = JS_GetStringCharsZAndLength(cx, str, &length);
   301         if (!chars)
   302             return false;
   304         mData.u.wstr.mWStringValue = const_cast<jschar *>(chars);
   305         // Use C-style cast, because reinterpret cast from size_t to
   306         // uint32_t is not valid on some platforms.
   307         mData.u.wstr.mWStringLength = (uint32_t)length;
   308         mData.mType = nsIDataType::VTYPE_WSTRING_SIZE_IS;
   310         return true;
   311     }
   313     // leaving only JSObject...
   314     MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
   316     RootedObject jsobj(cx, &val.toObject());
   318     // Let's see if it is a xpcJSID.
   320     const nsID* id = xpc_JSObjectToID(cx, jsobj);
   321     if (id)
   322         return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
   324     // Let's see if it is a js array object.
   326     uint32_t len;
   328     if (JS_IsArrayObject(cx, jsobj) && JS_GetArrayLength(cx, jsobj, &len)) {
   329         if (!len) {
   330             // Zero length array
   331             nsVariant::SetToEmptyArray(&mData);
   332             return true;
   333         }
   335         nsXPTType type;
   336         nsID id;
   338         if (!XPCArrayHomogenizer::GetTypeForArray(cx, jsobj, len, &type, &id))
   339             return false;
   341         if (!XPCConvert::JSArray2Native(&mData.u.array.mArrayValue,
   342                                         val, len, type, &id, nullptr))
   343             return false;
   345         mData.mType = nsIDataType::VTYPE_ARRAY;
   346         if (type.IsInterfacePointer())
   347             mData.u.array.mArrayInterfaceID = id;
   348         mData.u.array.mArrayCount = len;
   349         mData.u.array.mArrayType = type.TagPart();
   351         return true;
   352     }
   354     // XXX This could be smarter and pick some more interesting iface.
   356     nsXPConnect*  xpc = nsXPConnect::XPConnect();
   357     nsCOMPtr<nsISupports> wrapper;
   358     const nsIID& iid = NS_GET_IID(nsISupports);
   360     return NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
   361                                     iid, getter_AddRefs(wrapper))) &&
   362            NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
   363 }
   365 NS_IMETHODIMP
   366 XPCVariant::GetAsJSVal(MutableHandleValue result)
   367 {
   368   result.set(GetJSVal());
   369   return NS_OK;
   370 }
   372 // static
   373 bool
   374 XPCVariant::VariantDataToJS(nsIVariant* variant,
   375                             nsresult* pErr, MutableHandleValue pJSVal)
   376 {
   377     // Get the type early because we might need to spoof it below.
   378     uint16_t type;
   379     if (NS_FAILED(variant->GetDataType(&type)))
   380         return false;
   382     AutoJSContext cx;
   383     RootedValue realVal(cx);
   384     nsresult rv = variant->GetAsJSVal(&realVal);
   386     if (NS_SUCCEEDED(rv) &&
   387         (JSVAL_IS_PRIMITIVE(realVal) ||
   388          type == nsIDataType::VTYPE_ARRAY ||
   389          type == nsIDataType::VTYPE_EMPTY_ARRAY ||
   390          type == nsIDataType::VTYPE_ID)) {
   391         if (!JS_WrapValue(cx, &realVal))
   392             return false;
   393         pJSVal.set(realVal);
   394         return true;
   395     }
   397     nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
   398     if (xpcvariant && xpcvariant->mReturnRawObject) {
   399         MOZ_ASSERT(type == nsIDataType::VTYPE_INTERFACE ||
   400                    type == nsIDataType::VTYPE_INTERFACE_IS,
   401                    "Weird variant");
   403         if (!JS_WrapValue(cx, &realVal))
   404             return false;
   405         pJSVal.set(realVal);
   406         return true;
   407     }
   409     // else, it's an object and we really need to double wrap it if we've
   410     // already decided that its 'natural' type is as some sort of interface.
   412     // We just fall through to the code below and let it do what it does.
   414     // The nsIVariant is not a XPCVariant (or we act like it isn't).
   415     // So we extract the data and do the Right Thing.
   417     // We ASSUME that the variant implementation can do these conversions...
   419     nsID iid;
   421     switch (type) {
   422         case nsIDataType::VTYPE_INT8:
   423         case nsIDataType::VTYPE_INT16:
   424         case nsIDataType::VTYPE_INT32:
   425         case nsIDataType::VTYPE_INT64:
   426         case nsIDataType::VTYPE_UINT8:
   427         case nsIDataType::VTYPE_UINT16:
   428         case nsIDataType::VTYPE_UINT32:
   429         case nsIDataType::VTYPE_UINT64:
   430         case nsIDataType::VTYPE_FLOAT:
   431         case nsIDataType::VTYPE_DOUBLE:
   432         {
   433             double d;
   434             if (NS_FAILED(variant->GetAsDouble(&d)))
   435                 return false;
   436             pJSVal.setNumber(d);
   437             return true;
   438         }
   439         case nsIDataType::VTYPE_BOOL:
   440         {
   441             bool b;
   442             if (NS_FAILED(variant->GetAsBool(&b)))
   443                 return false;
   444             pJSVal.setBoolean(b);
   445             return true;
   446         }
   447         case nsIDataType::VTYPE_CHAR:
   448         {
   449             char c;
   450             if (NS_FAILED(variant->GetAsChar(&c)))
   451                 return false;
   452             return XPCConvert::NativeData2JS(pJSVal, (const void*)&c, TD_CHAR, &iid, pErr);
   453         }
   454         case nsIDataType::VTYPE_WCHAR:
   455         {
   456             char16_t wc;
   457             if (NS_FAILED(variant->GetAsWChar(&wc)))
   458                 return false;
   459             return XPCConvert::NativeData2JS(pJSVal, (const void*)&wc, TD_WCHAR, &iid, pErr);
   460         }
   461         case nsIDataType::VTYPE_ID:
   462         {
   463             if (NS_FAILED(variant->GetAsID(&iid)))
   464                 return false;
   465             nsID *v = &iid;
   466             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, TD_PNSIID, &iid, pErr);
   467         }
   468         case nsIDataType::VTYPE_ASTRING:
   469         {
   470             nsAutoString astring;
   471             if (NS_FAILED(variant->GetAsAString(astring)))
   472                 return false;
   473             nsAutoString *v = &astring;
   474             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v, TD_ASTRING, &iid, pErr);
   475         }
   476         case nsIDataType::VTYPE_DOMSTRING:
   477         {
   478             nsAutoString astring;
   479             if (NS_FAILED(variant->GetAsAString(astring)))
   480                 return false;
   481             nsAutoString *v = &astring;
   482             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
   483                                              TD_DOMSTRING, &iid, pErr);
   484         }
   485         case nsIDataType::VTYPE_CSTRING:
   486         {
   487             nsAutoCString cString;
   488             if (NS_FAILED(variant->GetAsACString(cString)))
   489                 return false;
   490             nsAutoCString *v = &cString;
   491             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
   492                                              TD_CSTRING, &iid, pErr);
   493         }
   494         case nsIDataType::VTYPE_UTF8STRING:
   495         {
   496             nsUTF8String utf8String;
   497             if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
   498                 return false;
   499             nsUTF8String *v = &utf8String;
   500             return XPCConvert::NativeData2JS(pJSVal, (const void*)&v,
   501                                              TD_UTF8STRING, &iid, pErr);
   502         }
   503         case nsIDataType::VTYPE_CHAR_STR:
   504         {
   505             char *pc;
   506             if (NS_FAILED(variant->GetAsString(&pc)))
   507                 return false;
   508             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pc,
   509                                                      TD_PSTRING, &iid, pErr);
   510             nsMemory::Free(pc);
   511             return success;
   512         }
   513         case nsIDataType::VTYPE_STRING_SIZE_IS:
   514         {
   515             char *pc;
   516             uint32_t size;
   517             if (NS_FAILED(variant->GetAsStringWithSize(&size, &pc)))
   518                 return false;
   519             bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pc,
   520                                                                TD_PSTRING_SIZE_IS, size, pErr);
   521             nsMemory::Free(pc);
   522             return success;
   523         }
   524         case nsIDataType::VTYPE_WCHAR_STR:
   525         {
   526             char16_t *pwc;
   527             if (NS_FAILED(variant->GetAsWString(&pwc)))
   528                 return false;
   529             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pwc,
   530                                                      TD_PSTRING, &iid, pErr);
   531             nsMemory::Free(pwc);
   532             return success;
   533         }
   534         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   535         {
   536             char16_t *pwc;
   537             uint32_t size;
   538             if (NS_FAILED(variant->GetAsWStringWithSize(&size, &pwc)))
   539                 return false;
   540             bool success = XPCConvert::NativeStringWithSize2JS(pJSVal, (const void*)&pwc,
   541                                                                TD_PWSTRING_SIZE_IS, size, pErr);
   542             nsMemory::Free(pwc);
   543             return success;
   544         }
   545         case nsIDataType::VTYPE_INTERFACE:
   546         case nsIDataType::VTYPE_INTERFACE_IS:
   547         {
   548             nsISupports *pi;
   549             nsID* piid;
   550             if (NS_FAILED(variant->GetAsInterface(&piid, (void **)&pi)))
   551                 return false;
   553             iid = *piid;
   554             nsMemory::Free((char*)piid);
   556             bool success = XPCConvert::NativeData2JS(pJSVal, (const void*)&pi,
   557                                                      TD_INTERFACE_IS_TYPE, &iid, pErr);
   558             if (pi)
   559                 pi->Release();
   560             return success;
   561         }
   562         case nsIDataType::VTYPE_ARRAY:
   563         {
   564             nsDiscriminatedUnion du;
   565             nsVariant::Initialize(&du);
   566             nsresult rv;
   568             rv = variant->GetAsArray(&du.u.array.mArrayType,
   569                                      &du.u.array.mArrayInterfaceID,
   570                                      &du.u.array.mArrayCount,
   571                                      &du.u.array.mArrayValue);
   572             if (NS_FAILED(rv))
   573                 return false;
   575             // must exit via VARIANT_DONE from here on...
   576             du.mType = nsIDataType::VTYPE_ARRAY;
   577             bool success = false;
   579             nsXPTType conversionType;
   580             uint16_t elementType = du.u.array.mArrayType;
   581             const nsID* pid = nullptr;
   583             switch (elementType) {
   584                 case nsIDataType::VTYPE_INT8:
   585                 case nsIDataType::VTYPE_INT16:
   586                 case nsIDataType::VTYPE_INT32:
   587                 case nsIDataType::VTYPE_INT64:
   588                 case nsIDataType::VTYPE_UINT8:
   589                 case nsIDataType::VTYPE_UINT16:
   590                 case nsIDataType::VTYPE_UINT32:
   591                 case nsIDataType::VTYPE_UINT64:
   592                 case nsIDataType::VTYPE_FLOAT:
   593                 case nsIDataType::VTYPE_DOUBLE:
   594                 case nsIDataType::VTYPE_BOOL:
   595                 case nsIDataType::VTYPE_CHAR:
   596                 case nsIDataType::VTYPE_WCHAR:
   597                     conversionType = nsXPTType((uint8_t)elementType);
   598                     break;
   600                 case nsIDataType::VTYPE_ID:
   601                 case nsIDataType::VTYPE_CHAR_STR:
   602                 case nsIDataType::VTYPE_WCHAR_STR:
   603                     conversionType = nsXPTType((uint8_t)elementType);
   604                     break;
   606                 case nsIDataType::VTYPE_INTERFACE:
   607                     pid = &NS_GET_IID(nsISupports);
   608                     conversionType = nsXPTType((uint8_t)elementType);
   609                     break;
   611                 case nsIDataType::VTYPE_INTERFACE_IS:
   612                     pid = &du.u.array.mArrayInterfaceID;
   613                     conversionType = nsXPTType((uint8_t)elementType);
   614                     break;
   616                 // The rest are illegal.
   617                 case nsIDataType::VTYPE_VOID:
   618                 case nsIDataType::VTYPE_ASTRING:
   619                 case nsIDataType::VTYPE_DOMSTRING:
   620                 case nsIDataType::VTYPE_CSTRING:
   621                 case nsIDataType::VTYPE_UTF8STRING:
   622                 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
   623                 case nsIDataType::VTYPE_STRING_SIZE_IS:
   624                 case nsIDataType::VTYPE_ARRAY:
   625                 case nsIDataType::VTYPE_EMPTY_ARRAY:
   626                 case nsIDataType::VTYPE_EMPTY:
   627                 default:
   628                     NS_ERROR("bad type in array!");
   629                     goto VARIANT_DONE;
   630             }
   632             success =
   633                 XPCConvert::NativeArray2JS(pJSVal,
   634                                            (const void**)&du.u.array.mArrayValue,
   635                                            conversionType, pid,
   636                                            du.u.array.mArrayCount, pErr);
   638 VARIANT_DONE:
   639             nsVariant::Cleanup(&du);
   640             return success;
   641         }
   642         case nsIDataType::VTYPE_EMPTY_ARRAY:
   643         {
   644             JSObject* array = JS_NewArrayObject(cx, 0);
   645             if (!array)
   646                 return false;
   647             pJSVal.setObject(*array);
   648             return true;
   649         }
   650         case nsIDataType::VTYPE_VOID:
   651             pJSVal.setUndefined();
   652             return true;
   653         case nsIDataType::VTYPE_EMPTY:
   654             pJSVal.setNull();
   655             return true;
   656         default:
   657             NS_ERROR("bad type in variant!");
   658             return false;
   659     }
   660 }
   662 /***************************************************************************/
   663 /***************************************************************************/
   664 // XXX These default implementations need to be improved to allow for
   665 // some more interesting conversions.
   668 /* readonly attribute uint16_t dataType; */
   669 NS_IMETHODIMP XPCVariant::GetDataType(uint16_t *aDataType)
   670 {
   671     *aDataType = mData.mType;
   672     return NS_OK;
   673 }
   675 /* uint8_t getAsInt8 (); */
   676 NS_IMETHODIMP XPCVariant::GetAsInt8(uint8_t *_retval)
   677 {
   678     return nsVariant::ConvertToInt8(mData, _retval);
   679 }
   681 /* int16_t getAsInt16 (); */
   682 NS_IMETHODIMP XPCVariant::GetAsInt16(int16_t *_retval)
   683 {
   684     return nsVariant::ConvertToInt16(mData, _retval);
   685 }
   687 /* int32_t getAsInt32 (); */
   688 NS_IMETHODIMP XPCVariant::GetAsInt32(int32_t *_retval)
   689 {
   690     return nsVariant::ConvertToInt32(mData, _retval);
   691 }
   693 /* int64_t getAsInt64 (); */
   694 NS_IMETHODIMP XPCVariant::GetAsInt64(int64_t *_retval)
   695 {
   696     return nsVariant::ConvertToInt64(mData, _retval);
   697 }
   699 /* uint8_t getAsUint8 (); */
   700 NS_IMETHODIMP XPCVariant::GetAsUint8(uint8_t *_retval)
   701 {
   702     return nsVariant::ConvertToUint8(mData, _retval);
   703 }
   705 /* uint16_t getAsUint16 (); */
   706 NS_IMETHODIMP XPCVariant::GetAsUint16(uint16_t *_retval)
   707 {
   708     return nsVariant::ConvertToUint16(mData, _retval);
   709 }
   711 /* uint32_t getAsUint32 (); */
   712 NS_IMETHODIMP XPCVariant::GetAsUint32(uint32_t *_retval)
   713 {
   714     return nsVariant::ConvertToUint32(mData, _retval);
   715 }
   717 /* uint64_t getAsUint64 (); */
   718 NS_IMETHODIMP XPCVariant::GetAsUint64(uint64_t *_retval)
   719 {
   720     return nsVariant::ConvertToUint64(mData, _retval);
   721 }
   723 /* float getAsFloat (); */
   724 NS_IMETHODIMP XPCVariant::GetAsFloat(float *_retval)
   725 {
   726     return nsVariant::ConvertToFloat(mData, _retval);
   727 }
   729 /* double getAsDouble (); */
   730 NS_IMETHODIMP XPCVariant::GetAsDouble(double *_retval)
   731 {
   732     return nsVariant::ConvertToDouble(mData, _retval);
   733 }
   735 /* bool getAsBool (); */
   736 NS_IMETHODIMP XPCVariant::GetAsBool(bool *_retval)
   737 {
   738     return nsVariant::ConvertToBool(mData, _retval);
   739 }
   741 /* char getAsChar (); */
   742 NS_IMETHODIMP XPCVariant::GetAsChar(char *_retval)
   743 {
   744     return nsVariant::ConvertToChar(mData, _retval);
   745 }
   747 /* wchar getAsWChar (); */
   748 NS_IMETHODIMP XPCVariant::GetAsWChar(char16_t *_retval)
   749 {
   750     return nsVariant::ConvertToWChar(mData, _retval);
   751 }
   753 /* [notxpcom] nsresult getAsID (out nsID retval); */
   754 NS_IMETHODIMP_(nsresult) XPCVariant::GetAsID(nsID *retval)
   755 {
   756     return nsVariant::ConvertToID(mData, retval);
   757 }
   759 /* AString getAsAString (); */
   760 NS_IMETHODIMP XPCVariant::GetAsAString(nsAString & _retval)
   761 {
   762     return nsVariant::ConvertToAString(mData, _retval);
   763 }
   765 /* DOMString getAsDOMString (); */
   766 NS_IMETHODIMP XPCVariant::GetAsDOMString(nsAString & _retval)
   767 {
   768     // A DOMString maps to an AString internally, so we can re-use
   769     // ConvertToAString here.
   770     return nsVariant::ConvertToAString(mData, _retval);
   771 }
   773 /* ACString getAsACString (); */
   774 NS_IMETHODIMP XPCVariant::GetAsACString(nsACString & _retval)
   775 {
   776     return nsVariant::ConvertToACString(mData, _retval);
   777 }
   779 /* AUTF8String getAsAUTF8String (); */
   780 NS_IMETHODIMP XPCVariant::GetAsAUTF8String(nsAUTF8String & _retval)
   781 {
   782     return nsVariant::ConvertToAUTF8String(mData, _retval);
   783 }
   785 /* string getAsString (); */
   786 NS_IMETHODIMP XPCVariant::GetAsString(char **_retval)
   787 {
   788     return nsVariant::ConvertToString(mData, _retval);
   789 }
   791 /* wstring getAsWString (); */
   792 NS_IMETHODIMP XPCVariant::GetAsWString(char16_t **_retval)
   793 {
   794     return nsVariant::ConvertToWString(mData, _retval);
   795 }
   797 /* nsISupports getAsISupports (); */
   798 NS_IMETHODIMP XPCVariant::GetAsISupports(nsISupports **_retval)
   799 {
   800     return nsVariant::ConvertToISupports(mData, _retval);
   801 }
   803 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
   804 NS_IMETHODIMP XPCVariant::GetAsInterface(nsIID * *iid, void * *iface)
   805 {
   806     return nsVariant::ConvertToInterface(mData, iid, iface);
   807 }
   810 /* [notxpcom] nsresult getAsArray (out uint16_t type, out nsIID iid, out uint32_t count, out voidPtr ptr); */
   811 NS_IMETHODIMP_(nsresult) XPCVariant::GetAsArray(uint16_t *type, nsIID *iid, uint32_t *count, void * *ptr)
   812 {
   813     return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
   814 }
   816 /* void getAsStringWithSize (out uint32_t size, [size_is (size), retval] out string str); */
   817 NS_IMETHODIMP XPCVariant::GetAsStringWithSize(uint32_t *size, char **str)
   818 {
   819     return nsVariant::ConvertToStringWithSize(mData, size, str);
   820 }
   822 /* void getAsWStringWithSize (out uint32_t size, [size_is (size), retval] out wstring str); */
   823 NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(uint32_t *size, char16_t **str)
   824 {
   825     return nsVariant::ConvertToWStringWithSize(mData, size, str);
   826 }

mercurial