js/xpconnect/src/XPCVariant.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:c34765c2c44a
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/. */
6
7 /* nsIVariant implementation for xpconnect. */
8
9 #include "xpcprivate.h"
10 #include "nsCxPusher.h"
11
12 #include "jsfriendapi.h"
13 #include "jsprf.h"
14 #include "jswrapper.h"
15
16 using namespace JS;
17 using namespace mozilla;
18
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)
27
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCVariant)
29 NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
30
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);
48
49 JSObject *unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
50 mReturnRawObject = !(unwrapped && IS_WN_REFLECTOR(unwrapped));
51 } else
52 mReturnRawObject = false;
53 }
54
55 XPCTraceableVariant::~XPCTraceableVariant()
56 {
57 jsval val = GetJSValPreserveColor();
58
59 MOZ_ASSERT(JSVAL_IS_GCTHING(val), "Must be traceable or unlinked");
60
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);
65
66 if (!JSVAL_IS_NULL(val))
67 RemoveFromRootSet();
68 }
69
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 }
76
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 }
83
84 NS_IMPL_CYCLE_COLLECTION_CLASS(XPCVariant)
85
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 }
92
93 nsVariant::Traverse(tmp->mData, cb);
94 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
95
96 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
97 JS::Value val = tmp->GetJSValPreserveColor();
98
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);
104
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
111
112 // static
113 already_AddRefed<XPCVariant>
114 XPCVariant::newVariant(JSContext* cx, jsval aJSVal)
115 {
116 nsRefPtr<XPCVariant> variant;
117
118 if (!aJSVal.isMarkable())
119 variant = new XPCVariant(cx, aJSVal);
120 else
121 variant = new XPCTraceableVariant(cx, aJSVal);
122
123 if (!variant->InitializeData(cx))
124 return nullptr;
125
126 return variant.forget();
127 }
128
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.
144
145 tTypeCount , // Just a count for table dimensioning.
146
147 tVar , // nsVariant - last ditch if no other common type found.
148 tErr // No valid state or type has this value.
149 };
150
151 // Table has tUnk as a state (column) but not as a type (row).
152 static const Type StateTable[tTypeCount][tTypeCount-1];
153
154 public:
155 static bool GetTypeForArray(JSContext* cx, HandleObject array,
156 uint32_t length,
157 nsXPTType* resultType, nsID* resultID);
158 };
159
160
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.
164
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 }};
177
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;
186
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;
192
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 }
216
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!");
221
222 state = StateTable[state][type];
223
224 MOZ_ASSERT(state != tErr, "bad state table!");
225 MOZ_ASSERT(state != tUnk, "bad state table!");
226
227 if (state == tVar)
228 break;
229 }
230
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 }
269
270 bool XPCVariant::InitializeData(JSContext* cx)
271 {
272 JS_CHECK_RECURSION(cx, return false);
273
274 RootedValue val(cx, GetJSVal());
275
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;
290
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?");
296
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;
303
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;
309
310 return true;
311 }
312
313 // leaving only JSObject...
314 MOZ_ASSERT(val.isObject(), "invalid type of jsval!");
315
316 RootedObject jsobj(cx, &val.toObject());
317
318 // Let's see if it is a xpcJSID.
319
320 const nsID* id = xpc_JSObjectToID(cx, jsobj);
321 if (id)
322 return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
323
324 // Let's see if it is a js array object.
325
326 uint32_t len;
327
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 }
334
335 nsXPTType type;
336 nsID id;
337
338 if (!XPCArrayHomogenizer::GetTypeForArray(cx, jsobj, len, &type, &id))
339 return false;
340
341 if (!XPCConvert::JSArray2Native(&mData.u.array.mArrayValue,
342 val, len, type, &id, nullptr))
343 return false;
344
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();
350
351 return true;
352 }
353
354 // XXX This could be smarter and pick some more interesting iface.
355
356 nsXPConnect* xpc = nsXPConnect::XPConnect();
357 nsCOMPtr<nsISupports> wrapper;
358 const nsIID& iid = NS_GET_IID(nsISupports);
359
360 return NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
361 iid, getter_AddRefs(wrapper))) &&
362 NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
363 }
364
365 NS_IMETHODIMP
366 XPCVariant::GetAsJSVal(MutableHandleValue result)
367 {
368 result.set(GetJSVal());
369 return NS_OK;
370 }
371
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;
381
382 AutoJSContext cx;
383 RootedValue realVal(cx);
384 nsresult rv = variant->GetAsJSVal(&realVal);
385
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 }
396
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");
402
403 if (!JS_WrapValue(cx, &realVal))
404 return false;
405 pJSVal.set(realVal);
406 return true;
407 }
408
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.
411
412 // We just fall through to the code below and let it do what it does.
413
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.
416
417 // We ASSUME that the variant implementation can do these conversions...
418
419 nsID iid;
420
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;
552
553 iid = *piid;
554 nsMemory::Free((char*)piid);
555
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;
567
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;
574
575 // must exit via VARIANT_DONE from here on...
576 du.mType = nsIDataType::VTYPE_ARRAY;
577 bool success = false;
578
579 nsXPTType conversionType;
580 uint16_t elementType = du.u.array.mArrayType;
581 const nsID* pid = nullptr;
582
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;
599
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;
605
606 case nsIDataType::VTYPE_INTERFACE:
607 pid = &NS_GET_IID(nsISupports);
608 conversionType = nsXPTType((uint8_t)elementType);
609 break;
610
611 case nsIDataType::VTYPE_INTERFACE_IS:
612 pid = &du.u.array.mArrayInterfaceID;
613 conversionType = nsXPTType((uint8_t)elementType);
614 break;
615
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 }
631
632 success =
633 XPCConvert::NativeArray2JS(pJSVal,
634 (const void**)&du.u.array.mArrayValue,
635 conversionType, pid,
636 du.u.array.mArrayCount, pErr);
637
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 }
661
662 /***************************************************************************/
663 /***************************************************************************/
664 // XXX These default implementations need to be improved to allow for
665 // some more interesting conversions.
666
667
668 /* readonly attribute uint16_t dataType; */
669 NS_IMETHODIMP XPCVariant::GetDataType(uint16_t *aDataType)
670 {
671 *aDataType = mData.mType;
672 return NS_OK;
673 }
674
675 /* uint8_t getAsInt8 (); */
676 NS_IMETHODIMP XPCVariant::GetAsInt8(uint8_t *_retval)
677 {
678 return nsVariant::ConvertToInt8(mData, _retval);
679 }
680
681 /* int16_t getAsInt16 (); */
682 NS_IMETHODIMP XPCVariant::GetAsInt16(int16_t *_retval)
683 {
684 return nsVariant::ConvertToInt16(mData, _retval);
685 }
686
687 /* int32_t getAsInt32 (); */
688 NS_IMETHODIMP XPCVariant::GetAsInt32(int32_t *_retval)
689 {
690 return nsVariant::ConvertToInt32(mData, _retval);
691 }
692
693 /* int64_t getAsInt64 (); */
694 NS_IMETHODIMP XPCVariant::GetAsInt64(int64_t *_retval)
695 {
696 return nsVariant::ConvertToInt64(mData, _retval);
697 }
698
699 /* uint8_t getAsUint8 (); */
700 NS_IMETHODIMP XPCVariant::GetAsUint8(uint8_t *_retval)
701 {
702 return nsVariant::ConvertToUint8(mData, _retval);
703 }
704
705 /* uint16_t getAsUint16 (); */
706 NS_IMETHODIMP XPCVariant::GetAsUint16(uint16_t *_retval)
707 {
708 return nsVariant::ConvertToUint16(mData, _retval);
709 }
710
711 /* uint32_t getAsUint32 (); */
712 NS_IMETHODIMP XPCVariant::GetAsUint32(uint32_t *_retval)
713 {
714 return nsVariant::ConvertToUint32(mData, _retval);
715 }
716
717 /* uint64_t getAsUint64 (); */
718 NS_IMETHODIMP XPCVariant::GetAsUint64(uint64_t *_retval)
719 {
720 return nsVariant::ConvertToUint64(mData, _retval);
721 }
722
723 /* float getAsFloat (); */
724 NS_IMETHODIMP XPCVariant::GetAsFloat(float *_retval)
725 {
726 return nsVariant::ConvertToFloat(mData, _retval);
727 }
728
729 /* double getAsDouble (); */
730 NS_IMETHODIMP XPCVariant::GetAsDouble(double *_retval)
731 {
732 return nsVariant::ConvertToDouble(mData, _retval);
733 }
734
735 /* bool getAsBool (); */
736 NS_IMETHODIMP XPCVariant::GetAsBool(bool *_retval)
737 {
738 return nsVariant::ConvertToBool(mData, _retval);
739 }
740
741 /* char getAsChar (); */
742 NS_IMETHODIMP XPCVariant::GetAsChar(char *_retval)
743 {
744 return nsVariant::ConvertToChar(mData, _retval);
745 }
746
747 /* wchar getAsWChar (); */
748 NS_IMETHODIMP XPCVariant::GetAsWChar(char16_t *_retval)
749 {
750 return nsVariant::ConvertToWChar(mData, _retval);
751 }
752
753 /* [notxpcom] nsresult getAsID (out nsID retval); */
754 NS_IMETHODIMP_(nsresult) XPCVariant::GetAsID(nsID *retval)
755 {
756 return nsVariant::ConvertToID(mData, retval);
757 }
758
759 /* AString getAsAString (); */
760 NS_IMETHODIMP XPCVariant::GetAsAString(nsAString & _retval)
761 {
762 return nsVariant::ConvertToAString(mData, _retval);
763 }
764
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 }
772
773 /* ACString getAsACString (); */
774 NS_IMETHODIMP XPCVariant::GetAsACString(nsACString & _retval)
775 {
776 return nsVariant::ConvertToACString(mData, _retval);
777 }
778
779 /* AUTF8String getAsAUTF8String (); */
780 NS_IMETHODIMP XPCVariant::GetAsAUTF8String(nsAUTF8String & _retval)
781 {
782 return nsVariant::ConvertToAUTF8String(mData, _retval);
783 }
784
785 /* string getAsString (); */
786 NS_IMETHODIMP XPCVariant::GetAsString(char **_retval)
787 {
788 return nsVariant::ConvertToString(mData, _retval);
789 }
790
791 /* wstring getAsWString (); */
792 NS_IMETHODIMP XPCVariant::GetAsWString(char16_t **_retval)
793 {
794 return nsVariant::ConvertToWString(mData, _retval);
795 }
796
797 /* nsISupports getAsISupports (); */
798 NS_IMETHODIMP XPCVariant::GetAsISupports(nsISupports **_retval)
799 {
800 return nsVariant::ConvertToISupports(mData, _retval);
801 }
802
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 }
808
809
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 }
815
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 }
821
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 }
827
828

mercurial