LCOV - code coverage report
Current view: directory - js/xpconnect/src - XPCVariant.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 366 231 63.1 %
Date: 2012-06-02 Functions: 45 22 48.9 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   John Bandhauer <jband@netscape.com> (original author)
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : /* nsIVariant implementation for xpconnect. */
      42                 : 
      43                 : #include "xpcprivate.h"
      44                 : #include "XPCWrapper.h"
      45                 : 
      46                 : #include "jsfriendapi.h"
      47                 : 
      48            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(XPCVariant)
      49                 : 
      50                 : NS_IMPL_CLASSINFO(XPCVariant, NULL, 0, XPCVARIANT_CID)
      51           13896 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCVariant)
      52            3431 :   NS_INTERFACE_MAP_ENTRY(XPCVariant)
      53            3061 :   NS_INTERFACE_MAP_ENTRY(nsIVariant)
      54               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      55               0 :   NS_IMPL_QUERY_CLASSINFO(XPCVariant)
      56               0 : NS_INTERFACE_MAP_END
      57               0 : NS_IMPL_CI_INTERFACE_GETTER2(XPCVariant, XPCVariant, nsIVariant)
      58                 : 
      59           13636 : NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant)
      60           13636 : NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
      61                 : 
      62            6515 : XPCVariant::XPCVariant(XPCCallContext& ccx, jsval aJSVal)
      63            6515 :     : mJSVal(aJSVal), mCCGeneration(0)
      64                 : {
      65            6515 :     nsVariant::Initialize(&mData);
      66            6515 :     if (!JSVAL_IS_PRIMITIVE(mJSVal)) {
      67             887 :         JSObject *obj = JS_ObjectToInnerObject(ccx, JSVAL_TO_OBJECT(mJSVal));
      68                 : 
      69             887 :         mJSVal = OBJECT_TO_JSVAL(obj);
      70                 : 
      71                 :         // If the incoming object is an XPCWrappedNative, then it could be a
      72                 :         // double-wrapped object, and we should return the double-wrapped
      73                 :         // object back out to script.
      74                 : 
      75                 :         JSObject* proto;
      76                 :         XPCWrappedNative* wn =
      77                 :             XPCWrappedNative::GetWrappedNativeOfJSObject(ccx,
      78                 :                                                          JSVAL_TO_OBJECT(mJSVal),
      79                 :                                                          nsnull,
      80             887 :                                                          &proto);
      81             887 :         mReturnRawObject = !wn && !proto;
      82                 :     } else
      83            5628 :         mReturnRawObject = false;
      84            6515 : }
      85                 : 
      86           10389 : XPCTraceableVariant::~XPCTraceableVariant()
      87                 : {
      88            3463 :     jsval val = GetJSValPreserveColor();
      89                 : 
      90            3463 :     NS_ASSERTION(JSVAL_IS_GCTHING(val), "Must be traceable or unlinked");
      91                 : 
      92                 :     // If val is JSVAL_STRING, we don't need to clean anything up; simply
      93                 :     // removing the string from the root set is good.
      94            3463 :     if (!JSVAL_IS_STRING(val))
      95             887 :         nsVariant::Cleanup(&mData);
      96                 : 
      97            3463 :     if (!JSVAL_IS_NULL(val))
      98            3463 :         RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
      99           13852 : }
     100                 : 
     101             551 : void XPCTraceableVariant::TraceJS(JSTracer* trc)
     102                 : {
     103             551 :     jsval val = GetJSValPreserveColor();
     104                 : 
     105             551 :     NS_ASSERTION(JSVAL_IS_TRACEABLE(val), "Must be traceable");
     106             551 :     JS_SET_TRACING_DETAILS(trc, PrintTraceName, this, 0);
     107             551 :     JS_CallTracer(trc, JSVAL_TO_TRACEABLE(val), JSVAL_TRACE_KIND(val));
     108             551 : }
     109                 : 
     110                 : #ifdef DEBUG
     111                 : // static
     112                 : void
     113               0 : XPCTraceableVariant::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize)
     114                 : {
     115               0 :     JS_snprintf(buf, bufsize, "XPCVariant[0x%p].mJSVal", trc->debugPrintArg);
     116               0 : }
     117                 : #endif
     118                 : 
     119               2 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPCVariant)
     120               2 :     jsval val = tmp->GetJSValPreserveColor();
     121               2 :     if (JSVAL_IS_OBJECT(val)) {
     122               2 :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mJSVal");
     123                 :         cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
     124               2 :                            JSVAL_TO_OBJECT(val));
     125                 :     }
     126                 : 
     127               2 :     nsVariant::Traverse(tmp->mData, cb);
     128               2 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     129                 : 
     130               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
     131               0 :     jsval val = tmp->GetJSValPreserveColor();
     132                 : 
     133                 :     // We're sharing val's buffer, clear the pointer to it so Cleanup() won't
     134                 :     // try to delete it
     135               0 :     if (JSVAL_IS_STRING(val))
     136               0 :         tmp->mData.u.wstr.mWStringValue = nsnull;
     137               0 :     nsVariant::Cleanup(&tmp->mData);
     138                 : 
     139               0 :     if (JSVAL_IS_TRACEABLE(val)) {
     140               0 :         XPCTraceableVariant *v = static_cast<XPCTraceableVariant*>(tmp);
     141               0 :         v->RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
     142                 :     }
     143               0 :     tmp->mJSVal = JSVAL_NULL;
     144               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     145                 : 
     146                 : // static
     147            6515 : XPCVariant* XPCVariant::newVariant(XPCCallContext& ccx, jsval aJSVal)
     148                 : {
     149                 :     XPCVariant* variant;
     150                 : 
     151            6515 :     if (!JSVAL_IS_TRACEABLE(aJSVal))
     152            3052 :         variant = new XPCVariant(ccx, aJSVal);
     153                 :     else
     154            3463 :         variant = new XPCTraceableVariant(ccx, aJSVal);
     155                 : 
     156            6515 :     if (!variant)
     157               0 :         return nsnull;
     158            6515 :     NS_ADDREF(variant);
     159                 : 
     160            6515 :     if (!variant->InitializeData(ccx))
     161               0 :         NS_RELEASE(variant);     // Also sets variant to nsnull.
     162                 : 
     163            6515 :     return variant;
     164                 : }
     165                 : 
     166                 : // Helper class to give us a namespace for the table based code below.
     167                 : class XPCArrayHomogenizer
     168                 : {
     169                 : private:
     170                 :     enum Type
     171                 :     {
     172                 :         tNull  = 0 ,  // null value
     173                 :         tInt       ,  // Integer
     174                 :         tDbl       ,  // Double
     175                 :         tBool      ,  // Boolean
     176                 :         tStr       ,  // String
     177                 :         tID        ,  // ID
     178                 :         tArr       ,  // Array
     179                 :         tISup      ,  // nsISupports (really just a plain JSObject)
     180                 :         tUnk       ,  // Unknown. Used only for initial state.
     181                 : 
     182                 :         tTypeCount ,  // Just a count for table dimensioning.
     183                 : 
     184                 :         tVar       ,  // nsVariant - last ditch if no other common type found.
     185                 :         tErr          // No valid state or type has this value.
     186                 :     };
     187                 : 
     188                 :     // Table has tUnk as a state (column) but not as a type (row).
     189                 :     static const Type StateTable[tTypeCount][tTypeCount-1];
     190                 : 
     191                 : public:
     192                 :     static JSBool GetTypeForArray(XPCCallContext& ccx, JSObject* array,
     193                 :                                   uint32_t length,
     194                 :                                   nsXPTType* resultType, nsID* resultID);
     195                 : };
     196                 : 
     197                 : 
     198                 : // Current state is the column down the side.
     199                 : // Current type is the row along the top.
     200                 : // New state is in the box at the intersection.
     201                 : 
     202                 : const XPCArrayHomogenizer::Type
     203                 : XPCArrayHomogenizer::StateTable[tTypeCount][tTypeCount-1] = {
     204                 : /*          tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tArr ,tISup */
     205                 : /* tNull */{tNull,tVar ,tVar ,tVar ,tStr ,tID  ,tVar ,tISup },
     206                 : /* tInt  */{tVar ,tInt ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
     207                 : /* tDbl  */{tVar ,tDbl ,tDbl ,tVar ,tVar ,tVar ,tVar ,tVar  },
     208                 : /* tBool */{tVar ,tVar ,tVar ,tBool,tVar ,tVar ,tVar ,tVar  },
     209                 : /* tStr  */{tStr ,tVar ,tVar ,tVar ,tStr ,tVar ,tVar ,tVar  },
     210                 : /* tID   */{tID  ,tVar ,tVar ,tVar ,tVar ,tID  ,tVar ,tVar  },
     211                 : /* tArr  */{tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr ,tErr  },
     212                 : /* tISup */{tISup,tVar ,tVar ,tVar ,tVar ,tVar ,tVar ,tISup },
     213                 : /* tUnk  */{tNull,tInt ,tDbl ,tBool,tStr ,tID  ,tVar ,tISup }};
     214                 : 
     215                 : // static
     216                 : JSBool
     217             436 : XPCArrayHomogenizer::GetTypeForArray(XPCCallContext& ccx, JSObject* array,
     218                 :                                      uint32_t length,
     219                 :                                      nsXPTType* resultType, nsID* resultID)
     220                 : {
     221             436 :     Type state = tUnk;
     222                 :     Type type;
     223                 : 
     224            1930 :     for (uint32_t i = 0; i < length; i++) {
     225                 :         jsval val;
     226            1505 :         if (!JS_GetElement(ccx, array, i, &val))
     227               0 :             return false;
     228                 : 
     229            1505 :         if (JSVAL_IS_INT(val))
     230               6 :             type = tInt;
     231            1499 :         else if (JSVAL_IS_DOUBLE(val))
     232               5 :             type = tDbl;
     233            1494 :         else if (JSVAL_IS_BOOLEAN(val))
     234               0 :             type = tBool;
     235            1494 :         else if (JSVAL_IS_VOID(val)) {
     236               4 :             state = tVar;
     237               4 :             break;
     238            1490 :         } else if (JSVAL_IS_NULL(val))
     239               2 :             type = tNull;
     240            1488 :         else if (JSVAL_IS_STRING(val))
     241            1389 :             type = tStr;
     242                 :         else {
     243              99 :             NS_ASSERTION(JSVAL_IS_OBJECT(val), "invalid type of jsval!");
     244              99 :             JSObject* jsobj = JSVAL_TO_OBJECT(val);
     245              99 :             if (JS_IsArrayObject(ccx, jsobj))
     246               0 :                 type = tArr;
     247              99 :             else if (xpc_JSObjectIsID(ccx, jsobj))
     248               0 :                 type = tID;
     249                 :             else
     250              99 :                 type = tISup;
     251                 :         }
     252                 : 
     253            1501 :         NS_ASSERTION(state != tErr, "bad state table!");
     254            1501 :         NS_ASSERTION(type  != tErr, "bad type!");
     255            1501 :         NS_ASSERTION(type  != tVar, "bad type!");
     256            1501 :         NS_ASSERTION(type  != tUnk, "bad type!");
     257                 : 
     258            1501 :         state = StateTable[state][type];
     259                 : 
     260            1501 :         NS_ASSERTION(state != tErr, "bad state table!");
     261            1501 :         NS_ASSERTION(state != tUnk, "bad state table!");
     262                 : 
     263            1501 :         if (state == tVar)
     264               7 :             break;
     265                 :     }
     266                 : 
     267             436 :     switch (state) {
     268                 :         case tInt :
     269               1 :             *resultType = nsXPTType((uint8_t)TD_INT32);
     270               1 :             break;
     271                 :         case tDbl :
     272               1 :             *resultType = nsXPTType((uint8_t)TD_DOUBLE);
     273               1 :             break;
     274                 :         case tBool:
     275               0 :             *resultType = nsXPTType((uint8_t)TD_BOOL);
     276               0 :             break;
     277                 :         case tStr :
     278             404 :             *resultType = nsXPTType((uint8_t)TD_PWSTRING);
     279             404 :             break;
     280                 :         case tID  :
     281               0 :             *resultType = nsXPTType((uint8_t)TD_PNSIID);
     282               0 :             break;
     283                 :         case tISup:
     284              18 :             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
     285              18 :             *resultID = NS_GET_IID(nsISupports);
     286              18 :             break;
     287                 :         case tNull:
     288                 :             // FALL THROUGH
     289                 :         case tVar :
     290              12 :             *resultType = nsXPTType((uint8_t)TD_INTERFACE_IS_TYPE);
     291              12 :             *resultID = NS_GET_IID(nsIVariant);
     292              12 :             break;
     293                 :         case tArr :
     294                 :             // FALL THROUGH
     295                 :         case tUnk :
     296                 :             // FALL THROUGH
     297                 :         case tErr :
     298                 :             // FALL THROUGH
     299                 :         default:
     300               0 :             NS_ERROR("bad state");
     301               0 :             return false;
     302                 :     }
     303             436 :     return true;
     304                 : }
     305                 : 
     306            6515 : JSBool XPCVariant::InitializeData(XPCCallContext& ccx)
     307                 : {
     308            6515 :     JS_CHECK_RECURSION(ccx.GetJSContext(), return false);
     309                 : 
     310            6515 :     jsval val = GetJSVal();
     311                 : 
     312            6515 :     if (JSVAL_IS_INT(val))
     313            1212 :         return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, JSVAL_TO_INT(val)));
     314            5303 :     if (JSVAL_IS_DOUBLE(val))
     315             566 :         return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData,
     316                 :                                                      JSVAL_TO_DOUBLE(val)));
     317            4737 :     if (JSVAL_IS_BOOLEAN(val))
     318             388 :         return NS_SUCCEEDED(nsVariant::SetFromBool(&mData,
     319                 :                                                    JSVAL_TO_BOOLEAN(val)));
     320            4349 :     if (JSVAL_IS_VOID(val))
     321              50 :         return NS_SUCCEEDED(nsVariant::SetToVoid(&mData));
     322            4299 :     if (JSVAL_IS_NULL(val))
     323             836 :         return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData));
     324            3463 :     if (JSVAL_IS_STRING(val)) {
     325                 :         // Make our string immutable.  This will also ensure null-termination,
     326                 :         // which nsVariant assumes for its PRUnichar* stuff.
     327            2576 :         JSString* str = JSVAL_TO_STRING(val);
     328            2576 :         if (!JS_MakeStringImmutable(ccx, str))
     329               0 :             return false;
     330                 : 
     331                 :         // Don't use nsVariant::SetFromWStringWithSize, because that will copy
     332                 :         // the data.  Just handle this ourselves.  Note that it's ok to not
     333                 :         // copy because we added mJSVal as a GC root.
     334            2576 :         NS_ASSERTION(mData.mType == nsIDataType::VTYPE_EMPTY,
     335                 :                      "Why do we already have data?");
     336                 : 
     337                 :         // Despite the fact that the variant holds the length, there are
     338                 :         // implicit assumptions that mWStringValue[mWStringLength] == 0
     339                 :         size_t length;
     340            2576 :         const jschar *chars = JS_GetStringCharsZAndLength(ccx, str, &length);
     341            2576 :         if (!chars)
     342               0 :             return false;
     343                 : 
     344            2576 :         mData.u.wstr.mWStringValue = const_cast<jschar *>(chars);
     345                 :         // Use C-style cast, because reinterpret cast from size_t to
     346                 :         // PRUint32 is not valid on some platforms.
     347            2576 :         mData.u.wstr.mWStringLength = (PRUint32)length;
     348            2576 :         mData.mType = nsIDataType::VTYPE_WSTRING_SIZE_IS;
     349                 : 
     350            2576 :         return true;
     351                 :     }
     352                 : 
     353                 :     // leaving only JSObject...
     354             887 :     NS_ASSERTION(JSVAL_IS_OBJECT(val), "invalid type of jsval!");
     355                 : 
     356             887 :     JSObject* jsobj = JSVAL_TO_OBJECT(val);
     357                 : 
     358                 :     // Let's see if it is a xpcJSID.
     359                 : 
     360             887 :     const nsID* id = xpc_JSObjectToID(ccx, jsobj);
     361             887 :     if (id)
     362               0 :         return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
     363                 : 
     364                 :     // Let's see if it is a js array object.
     365                 : 
     366                 :     uint32_t len;
     367                 : 
     368             887 :     if (JS_IsArrayObject(ccx, jsobj) && JS_GetArrayLength(ccx, jsobj, &len)) {
     369             508 :         if (!len) {
     370                 :             // Zero length array
     371              72 :             nsVariant::SetToEmptyArray(&mData);
     372              72 :             return true;
     373                 :         }
     374                 : 
     375             436 :         nsXPTType type;
     376                 :         nsID id;
     377                 : 
     378             436 :         if (!XPCArrayHomogenizer::GetTypeForArray(ccx, jsobj, len, &type, &id))
     379               0 :             return false;
     380                 : 
     381             436 :         if (!XPCConvert::JSArray2Native(ccx, &mData.u.array.mArrayValue,
     382             436 :                                         val, len, type, &id, nsnull))
     383               0 :             return false;
     384                 : 
     385             436 :         mData.mType = nsIDataType::VTYPE_ARRAY;
     386             436 :         if (type.IsInterfacePointer())
     387              30 :             mData.u.array.mArrayInterfaceID = id;
     388             436 :         mData.u.array.mArrayCount = len;
     389             436 :         mData.u.array.mArrayType = type.TagPart();
     390                 : 
     391             436 :         return true;
     392                 :     }
     393                 : 
     394                 :     // XXX This could be smarter and pick some more interesting iface.
     395                 : 
     396                 :     nsXPConnect*  xpc;
     397             758 :     nsCOMPtr<nsISupports> wrapper;
     398             379 :     const nsIID& iid = NS_GET_IID(nsISupports);
     399                 : 
     400                 :     return nsnull != (xpc = nsXPConnect::GetXPConnect()) &&
     401            1137 :            NS_SUCCEEDED(xpc->WrapJS(ccx, jsobj,
     402                 :                                     iid, getter_AddRefs(wrapper))) &&
     403            1137 :            NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
     404                 : }
     405                 : 
     406                 : NS_IMETHODIMP
     407            1487 : XPCVariant::GetAsJSVal(jsval* result)
     408                 : {
     409            1487 :   NS_PRECONDITION(result, "null result arg.");
     410            1487 :   *result = GetJSVal();
     411            1487 :   return NS_OK;
     412                 : }
     413                 : 
     414                 : // static
     415                 : JSBool
     416          126658 : XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
     417                 :                             nsIVariant* variant,
     418                 :                             nsresult* pErr, jsval* pJSVal)
     419                 : {
     420                 :     // Get the type early because we might need to spoof it below.
     421                 :     PRUint16 type;
     422          126658 :     if (NS_FAILED(variant->GetDataType(&type)))
     423               0 :         return false;
     424                 : 
     425                 :     jsval realVal;
     426          126658 :     nsresult rv = variant->GetAsJSVal(&realVal);
     427                 : 
     428          128145 :     if (NS_SUCCEEDED(rv) &&
     429            1487 :         (JSVAL_IS_PRIMITIVE(realVal) ||
     430                 :          type == nsIDataType::VTYPE_ARRAY ||
     431                 :          type == nsIDataType::VTYPE_EMPTY_ARRAY ||
     432                 :          type == nsIDataType::VTYPE_ID)) {
     433            1117 :         JSContext *cx = lccx.GetJSContext();
     434            1117 :         if (!JS_WrapValue(cx, &realVal))
     435               0 :             return false;
     436            1117 :         *pJSVal = realVal;
     437            1117 :         return true;
     438                 :     }
     439                 : 
     440          251082 :     nsCOMPtr<XPCVariant> xpcvariant = do_QueryInterface(variant);
     441          125541 :     if (xpcvariant && xpcvariant->mReturnRawObject) {
     442             122 :         NS_ASSERTION(type == nsIDataType::VTYPE_INTERFACE ||
     443                 :                      type == nsIDataType::VTYPE_INTERFACE_IS,
     444                 :                      "Weird variant");
     445                 : 
     446             122 :         JSContext *cx = lccx.GetJSContext();
     447             122 :         if (!JS_WrapValue(cx, &realVal))
     448               0 :             return false;
     449             122 :         *pJSVal = realVal;
     450             122 :         return true;
     451                 :     }
     452                 : 
     453                 :     // else, it's an object and we really need to double wrap it if we've
     454                 :     // already decided that its 'natural' type is as some sort of interface.
     455                 : 
     456                 :     // We just fall through to the code below and let it do what it does.
     457                 : 
     458                 :     // The nsIVariant is not a XPCVariant (or we act like it isn't).
     459                 :     // So we extract the data and do the Right Thing.
     460                 : 
     461                 :     // We ASSUME that the variant implementation can do these conversions...
     462                 : 
     463          125419 :     nsXPTCVariant xpctvar;
     464                 :     nsID iid;
     465          250838 :     nsAutoString astring;
     466          250838 :     nsCAutoString cString;
     467          250838 :     nsUTF8String utf8String;
     468                 :     PRUint32 size;
     469          125419 :     xpctvar.flags = 0;
     470                 :     JSBool success;
     471                 : 
     472          125419 :     JSContext* cx = lccx.GetJSContext();
     473          125419 :     NS_ABORT_IF_FALSE(js::IsObjectInContextCompartment(lccx.GetScopeForNewJSObjects(), cx),
     474                 :                       "bad scope for new JSObjects");
     475                 : 
     476          125419 :     switch (type) {
     477                 :         case nsIDataType::VTYPE_INT8:
     478                 :         case nsIDataType::VTYPE_INT16:
     479                 :         case nsIDataType::VTYPE_INT32:
     480                 :         case nsIDataType::VTYPE_INT64:
     481                 :         case nsIDataType::VTYPE_UINT8:
     482                 :         case nsIDataType::VTYPE_UINT16:
     483                 :         case nsIDataType::VTYPE_UINT32:
     484                 :         case nsIDataType::VTYPE_UINT64:
     485                 :         case nsIDataType::VTYPE_FLOAT:
     486                 :         case nsIDataType::VTYPE_DOUBLE:
     487                 :         {
     488                 :             // Easy. Handle inline.
     489           47037 :             if (NS_FAILED(variant->GetAsDouble(&xpctvar.val.d)))
     490               0 :                 return false;
     491           47037 :             return JS_NewNumberValue(cx, xpctvar.val.d, pJSVal);
     492                 :         }
     493                 :         case nsIDataType::VTYPE_BOOL:
     494                 :         {
     495                 :             // Easy. Handle inline.
     496              44 :             if (NS_FAILED(variant->GetAsBool(&xpctvar.val.b)))
     497               0 :                 return false;
     498              44 :             *pJSVal = BOOLEAN_TO_JSVAL(xpctvar.val.b);
     499              44 :             return true;
     500                 :         }
     501                 :         case nsIDataType::VTYPE_CHAR:
     502               0 :             if (NS_FAILED(variant->GetAsChar(&xpctvar.val.c)))
     503               0 :                 return false;
     504               0 :             xpctvar.type = (uint8_t)TD_CHAR;
     505               0 :             break;
     506                 :         case nsIDataType::VTYPE_WCHAR:
     507               0 :             if (NS_FAILED(variant->GetAsWChar(&xpctvar.val.wc)))
     508               0 :                 return false;
     509               0 :             xpctvar.type = (uint8_t)TD_WCHAR;
     510               0 :             break;
     511                 :         case nsIDataType::VTYPE_ID:
     512               0 :             if (NS_FAILED(variant->GetAsID(&iid)))
     513               0 :                 return false;
     514               0 :             xpctvar.type = (uint8_t)TD_PNSIID;
     515               0 :             xpctvar.val.p = &iid;
     516               0 :             break;
     517                 :         case nsIDataType::VTYPE_ASTRING:
     518           33406 :             if (NS_FAILED(variant->GetAsAString(astring)))
     519               0 :                 return false;
     520           33406 :             xpctvar.type = (uint8_t)TD_ASTRING;
     521           33406 :             xpctvar.val.p = &astring;
     522           33406 :             break;
     523                 :         case nsIDataType::VTYPE_DOMSTRING:
     524               0 :             if (NS_FAILED(variant->GetAsAString(astring)))
     525               0 :                 return false;
     526               0 :             xpctvar.type = (uint8_t)TD_DOMSTRING;
     527               0 :             xpctvar.val.p = &astring;
     528               0 :             break;
     529                 :         case nsIDataType::VTYPE_CSTRING:
     530             135 :             if (NS_FAILED(variant->GetAsACString(cString)))
     531               0 :                 return false;
     532             135 :             xpctvar.type = (uint8_t)TD_CSTRING;
     533             135 :             xpctvar.val.p = &cString;
     534             135 :             break;
     535                 :         case nsIDataType::VTYPE_UTF8STRING:
     536             244 :             if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
     537               0 :                 return false;
     538             244 :             xpctvar.type = (uint8_t)TD_UTF8STRING;
     539             244 :             xpctvar.val.p = &utf8String;
     540             244 :             break;
     541                 :         case nsIDataType::VTYPE_CHAR_STR:
     542               0 :             if (NS_FAILED(variant->GetAsString((char**)&xpctvar.val.p)))
     543               0 :                 return false;
     544               0 :             xpctvar.type = (uint8_t)TD_PSTRING;
     545               0 :             xpctvar.SetValNeedsCleanup();
     546               0 :             break;
     547                 :         case nsIDataType::VTYPE_STRING_SIZE_IS:
     548               0 :             if (NS_FAILED(variant->GetAsStringWithSize(&size,
     549                 :                                                        (char**)&xpctvar.val.p)))
     550               0 :                 return false;
     551               0 :             xpctvar.type = (uint8_t)TD_PSTRING_SIZE_IS;
     552               0 :             xpctvar.SetValNeedsCleanup();
     553               0 :             break;
     554                 :         case nsIDataType::VTYPE_WCHAR_STR:
     555               0 :             if (NS_FAILED(variant->GetAsWString((PRUnichar**)&xpctvar.val.p)))
     556               0 :                 return false;
     557               0 :             xpctvar.type = (uint8_t)TD_PWSTRING;
     558               0 :             xpctvar.SetValNeedsCleanup();
     559               0 :             break;
     560                 :         case nsIDataType::VTYPE_WSTRING_SIZE_IS:
     561               0 :             if (NS_FAILED(variant->GetAsWStringWithSize(&size,
     562                 :                                                         (PRUnichar**)&xpctvar.val.p)))
     563               0 :                 return false;
     564               0 :             xpctvar.type = (uint8_t)TD_PWSTRING_SIZE_IS;
     565               0 :             xpctvar.SetValNeedsCleanup();
     566               0 :             break;
     567                 :         case nsIDataType::VTYPE_INTERFACE:
     568                 :         case nsIDataType::VTYPE_INTERFACE_IS:
     569                 :         {
     570                 :             nsID* piid;
     571            2844 :             if (NS_FAILED(variant->GetAsInterface(&piid, &xpctvar.val.p)))
     572               0 :                 return false;
     573                 : 
     574            2844 :             iid = *piid;
     575            2844 :             nsMemory::Free((char*)piid);
     576                 : 
     577            2844 :             xpctvar.type = (uint8_t)TD_INTERFACE_IS_TYPE;
     578            2844 :             if (xpctvar.val.p)
     579            2844 :                 xpctvar.SetValNeedsCleanup();
     580            2844 :             break;
     581                 :         }
     582                 :         case nsIDataType::VTYPE_ARRAY:
     583                 :         {
     584                 :             nsDiscriminatedUnion du;
     585            1268 :             nsVariant::Initialize(&du);
     586                 :             nsresult rv;
     587                 : 
     588                 :             rv = variant->GetAsArray(&du.u.array.mArrayType,
     589                 :                                      &du.u.array.mArrayInterfaceID,
     590                 :                                      &du.u.array.mArrayCount,
     591            1268 :                                      &du.u.array.mArrayValue);
     592            1268 :             if (NS_FAILED(rv))
     593               0 :                 return false;
     594                 : 
     595                 :             // must exit via VARIANT_DONE from here on...
     596            1268 :             du.mType = nsIDataType::VTYPE_ARRAY;
     597            1268 :             success = false;
     598                 : 
     599            1268 :             nsXPTType conversionType;
     600            1268 :             PRUint16 elementType = du.u.array.mArrayType;
     601            1268 :             const nsID* pid = nsnull;
     602                 : 
     603            1268 :             switch (elementType) {
     604                 :                 case nsIDataType::VTYPE_INT8:
     605                 :                 case nsIDataType::VTYPE_INT16:
     606                 :                 case nsIDataType::VTYPE_INT32:
     607                 :                 case nsIDataType::VTYPE_INT64:
     608                 :                 case nsIDataType::VTYPE_UINT8:
     609                 :                 case nsIDataType::VTYPE_UINT16:
     610                 :                 case nsIDataType::VTYPE_UINT32:
     611                 :                 case nsIDataType::VTYPE_UINT64:
     612                 :                 case nsIDataType::VTYPE_FLOAT:
     613                 :                 case nsIDataType::VTYPE_DOUBLE:
     614                 :                 case nsIDataType::VTYPE_BOOL:
     615                 :                 case nsIDataType::VTYPE_CHAR:
     616                 :                 case nsIDataType::VTYPE_WCHAR:
     617               4 :                     conversionType = nsXPTType((uint8_t)elementType);
     618               4 :                     break;
     619                 : 
     620                 :                 case nsIDataType::VTYPE_ID:
     621                 :                 case nsIDataType::VTYPE_CHAR_STR:
     622                 :                 case nsIDataType::VTYPE_WCHAR_STR:
     623            1264 :                     conversionType = nsXPTType((uint8_t)elementType);
     624            1264 :                     break;
     625                 : 
     626                 :                 case nsIDataType::VTYPE_INTERFACE:
     627               0 :                     pid = &NS_GET_IID(nsISupports);
     628               0 :                     conversionType = nsXPTType((uint8_t)elementType);
     629               0 :                     break;
     630                 : 
     631                 :                 case nsIDataType::VTYPE_INTERFACE_IS:
     632               0 :                     pid = &du.u.array.mArrayInterfaceID;
     633               0 :                     conversionType = nsXPTType((uint8_t)elementType);
     634               0 :                     break;
     635                 : 
     636                 :                 // The rest are illegal.
     637                 :                 case nsIDataType::VTYPE_VOID:
     638                 :                 case nsIDataType::VTYPE_ASTRING:
     639                 :                 case nsIDataType::VTYPE_DOMSTRING:
     640                 :                 case nsIDataType::VTYPE_CSTRING:
     641                 :                 case nsIDataType::VTYPE_UTF8STRING:
     642                 :                 case nsIDataType::VTYPE_WSTRING_SIZE_IS:
     643                 :                 case nsIDataType::VTYPE_STRING_SIZE_IS:
     644                 :                 case nsIDataType::VTYPE_ARRAY:
     645                 :                 case nsIDataType::VTYPE_EMPTY_ARRAY:
     646                 :                 case nsIDataType::VTYPE_EMPTY:
     647                 :                 default:
     648               0 :                     NS_ERROR("bad type in array!");
     649               0 :                     goto VARIANT_DONE;
     650                 :             }
     651                 : 
     652                 :             success =
     653                 :                 XPCConvert::NativeArray2JS(lccx, pJSVal,
     654                 :                                            (const void**)&du.u.array.mArrayValue,
     655                 :                                            conversionType, pid,
     656            1268 :                                            du.u.array.mArrayCount, pErr);
     657                 : 
     658                 : VARIANT_DONE:
     659            1268 :             nsVariant::Cleanup(&du);
     660            1268 :             return success;
     661                 :         }
     662                 :         case nsIDataType::VTYPE_EMPTY_ARRAY:
     663                 :         {
     664            7213 :             JSObject* array = JS_NewArrayObject(cx, 0, nsnull);
     665            7213 :             if (!array)
     666               0 :                 return false;
     667            7213 :             *pJSVal = OBJECT_TO_JSVAL(array);
     668            7213 :             return true;
     669                 :         }
     670                 :         case nsIDataType::VTYPE_VOID:
     671               0 :             *pJSVal = JSVAL_VOID;
     672               0 :             return true;
     673                 :         case nsIDataType::VTYPE_EMPTY:
     674           33228 :             *pJSVal = JSVAL_NULL;
     675           33228 :             return true;
     676                 :         default:
     677               0 :             NS_ERROR("bad type in variant!");
     678               0 :             return false;
     679                 :     }
     680                 : 
     681                 :     // If we are here then we need to convert the data in the xpctvar.
     682                 : 
     683           73258 :     if (xpctvar.type.TagPart() == TD_PSTRING_SIZE_IS ||
     684           36629 :         xpctvar.type.TagPart() == TD_PWSTRING_SIZE_IS) {
     685                 :         success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal,
     686                 :                                                       (const void*)&xpctvar.val,
     687                 :                                                       xpctvar.type,
     688               0 :                                                       size, pErr);
     689                 :     } else {
     690                 :         success = XPCConvert::NativeData2JS(lccx, pJSVal,
     691                 :                                             (const void*)&xpctvar.val,
     692                 :                                             xpctvar.type,
     693           36629 :                                             &iid, pErr);
     694                 :     }
     695                 : 
     696                 :     // We may have done something in the above code that requires cleanup.
     697           36629 :     if (xpctvar.DoesValNeedCleanup()) {
     698            2844 :         if (type == nsIDataType::VTYPE_INTERFACE ||
     699                 :             type == nsIDataType::VTYPE_INTERFACE_IS)
     700            2844 :             ((nsISupports*)xpctvar.val.p)->Release();
     701                 :         else
     702               0 :             nsMemory::Free((char*)xpctvar.val.p);
     703                 :     }
     704                 : 
     705           36629 :     return success;
     706                 : }
     707                 : 
     708                 : /***************************************************************************/
     709                 : /***************************************************************************/
     710                 : // XXX These default implementations need to be improved to allow for
     711                 : // some more interesting conversions.
     712                 : 
     713                 : 
     714                 : /* readonly attribute PRUint16 dataType; */
     715            5903 : NS_IMETHODIMP XPCVariant::GetDataType(PRUint16 *aDataType)
     716                 : {
     717            5903 :     *aDataType = mData.mType;
     718            5903 :     return NS_OK;
     719                 : }
     720                 : 
     721                 : /* PRUint8 getAsInt8 (); */
     722               0 : NS_IMETHODIMP XPCVariant::GetAsInt8(PRUint8 *_retval)
     723                 : {
     724               0 :     return nsVariant::ConvertToInt8(mData, _retval);
     725                 : }
     726                 : 
     727                 : /* PRInt16 getAsInt16 (); */
     728               0 : NS_IMETHODIMP XPCVariant::GetAsInt16(PRInt16 *_retval)
     729                 : {
     730               0 :     return nsVariant::ConvertToInt16(mData, _retval);
     731                 : }
     732                 : 
     733                 : /* PRInt32 getAsInt32 (); */
     734             850 : NS_IMETHODIMP XPCVariant::GetAsInt32(PRInt32 *_retval)
     735                 : {
     736             850 :     return nsVariant::ConvertToInt32(mData, _retval);
     737                 : }
     738                 : 
     739                 : /* PRInt64 getAsInt64 (); */
     740               0 : NS_IMETHODIMP XPCVariant::GetAsInt64(PRInt64 *_retval)
     741                 : {
     742               0 :     return nsVariant::ConvertToInt64(mData, _retval);
     743                 : }
     744                 : 
     745                 : /* PRUint8 getAsUint8 (); */
     746               0 : NS_IMETHODIMP XPCVariant::GetAsUint8(PRUint8 *_retval)
     747                 : {
     748               0 :     return nsVariant::ConvertToUint8(mData, _retval);
     749                 : }
     750                 : 
     751                 : /* PRUint16 getAsUint16 (); */
     752               0 : NS_IMETHODIMP XPCVariant::GetAsUint16(PRUint16 *_retval)
     753                 : {
     754               0 :     return nsVariant::ConvertToUint16(mData, _retval);
     755                 : }
     756                 : 
     757                 : /* PRUint32 getAsUint32 (); */
     758               0 : NS_IMETHODIMP XPCVariant::GetAsUint32(PRUint32 *_retval)
     759                 : {
     760               0 :     return nsVariant::ConvertToUint32(mData, _retval);
     761                 : }
     762                 : 
     763                 : /* PRUint64 getAsUint64 (); */
     764               0 : NS_IMETHODIMP XPCVariant::GetAsUint64(PRUint64 *_retval)
     765                 : {
     766               0 :     return nsVariant::ConvertToUint64(mData, _retval);
     767                 : }
     768                 : 
     769                 : /* float getAsFloat (); */
     770               0 : NS_IMETHODIMP XPCVariant::GetAsFloat(float *_retval)
     771                 : {
     772               0 :     return nsVariant::ConvertToFloat(mData, _retval);
     773                 : }
     774                 : 
     775                 : /* double getAsDouble (); */
     776             551 : NS_IMETHODIMP XPCVariant::GetAsDouble(double *_retval)
     777                 : {
     778             551 :     return nsVariant::ConvertToDouble(mData, _retval);
     779                 : }
     780                 : 
     781                 : /* bool getAsBool (); */
     782             382 : NS_IMETHODIMP XPCVariant::GetAsBool(bool *_retval)
     783                 : {
     784             382 :     return nsVariant::ConvertToBool(mData, _retval);
     785                 : }
     786                 : 
     787                 : /* char getAsChar (); */
     788               0 : NS_IMETHODIMP XPCVariant::GetAsChar(char *_retval)
     789                 : {
     790               0 :     return nsVariant::ConvertToChar(mData, _retval);
     791                 : }
     792                 : 
     793                 : /* wchar getAsWChar (); */
     794               0 : NS_IMETHODIMP XPCVariant::GetAsWChar(PRUnichar *_retval)
     795                 : {
     796               0 :     return nsVariant::ConvertToWChar(mData, _retval);
     797                 : }
     798                 : 
     799                 : /* [notxpcom] nsresult getAsID (out nsID retval); */
     800               0 : NS_IMETHODIMP_(nsresult) XPCVariant::GetAsID(nsID *retval)
     801                 : {
     802               0 :     return nsVariant::ConvertToID(mData, retval);
     803                 : }
     804                 : 
     805                 : /* AString getAsAString (); */
     806            2169 : NS_IMETHODIMP XPCVariant::GetAsAString(nsAString & _retval)
     807                 : {
     808            2169 :     return nsVariant::ConvertToAString(mData, _retval);
     809                 : }
     810                 : 
     811                 : /* DOMString getAsDOMString (); */
     812               0 : NS_IMETHODIMP XPCVariant::GetAsDOMString(nsAString & _retval)
     813                 : {
     814                 :     // A DOMString maps to an AString internally, so we can re-use
     815                 :     // ConvertToAString here.
     816               0 :     return nsVariant::ConvertToAString(mData, _retval);
     817                 : }
     818                 : 
     819                 : /* ACString getAsACString (); */
     820               0 : NS_IMETHODIMP XPCVariant::GetAsACString(nsACString & _retval)
     821                 : {
     822               0 :     return nsVariant::ConvertToACString(mData, _retval);
     823                 : }
     824                 : 
     825                 : /* AUTF8String getAsAUTF8String (); */
     826               0 : NS_IMETHODIMP XPCVariant::GetAsAUTF8String(nsAUTF8String & _retval)
     827                 : {
     828               0 :     return nsVariant::ConvertToAUTF8String(mData, _retval);
     829                 : }
     830                 : 
     831                 : /* string getAsString (); */
     832               0 : NS_IMETHODIMP XPCVariant::GetAsString(char **_retval)
     833                 : {
     834               0 :     return nsVariant::ConvertToString(mData, _retval);
     835                 : }
     836                 : 
     837                 : /* wstring getAsWString (); */
     838               0 : NS_IMETHODIMP XPCVariant::GetAsWString(PRUnichar **_retval)
     839                 : {
     840               0 :     return nsVariant::ConvertToWString(mData, _retval);
     841                 : }
     842                 : 
     843                 : /* nsISupports getAsISupports (); */
     844               0 : NS_IMETHODIMP XPCVariant::GetAsISupports(nsISupports **_retval)
     845                 : {
     846               0 :     return nsVariant::ConvertToISupports(mData, _retval);
     847                 : }
     848                 : 
     849                 : /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
     850             252 : NS_IMETHODIMP XPCVariant::GetAsInterface(nsIID * *iid, void * *iface)
     851                 : {
     852             252 :     return nsVariant::ConvertToInterface(mData, iid, iface);
     853                 : }
     854                 : 
     855                 : 
     856                 : /* [notxpcom] nsresult getAsArray (out PRUint16 type, out nsIID iid, out PRUint32 count, out voidPtr ptr); */
     857             189 : NS_IMETHODIMP_(nsresult) XPCVariant::GetAsArray(PRUint16 *type, nsIID *iid, PRUint32 *count, void * *ptr)
     858                 : {
     859             189 :     return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
     860                 : }
     861                 : 
     862                 : /* void getAsStringWithSize (out PRUint32 size, [size_is (size), retval] out string str); */
     863               0 : NS_IMETHODIMP XPCVariant::GetAsStringWithSize(PRUint32 *size, char **str)
     864                 : {
     865               0 :     return nsVariant::ConvertToStringWithSize(mData, size, str);
     866                 : }
     867                 : 
     868                 : /* void getAsWStringWithSize (out PRUint32 size, [size_is (size), retval] out wstring str); */
     869               0 : NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(PRUint32 *size, PRUnichar **str)
     870                 : {
     871               0 :     return nsVariant::ConvertToWStringWithSize(mData, size, str);
     872            4392 : }
     873                 : 
     874                 : 

Generated by: LCOV version 1.7