1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "xpctest_private.h"
6 #include "xpctest_interfaces.h"
7 #include "mozilla/Casting.h"
11 #include "nsComponentManagerUtils.h"
14 using namespace mozilla
;
16 NS_IMPL_ISUPPORTS(nsXPCTestParams
, nsIXPCTestParams
)
18 #define GENERIC_METHOD_IMPL \
25 #define STRING_METHOD_IMPL \
32 #define SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP) \
34 _retval = std::move(b); \
36 for (uint32_t i = 0; i < b.Length(); ++i) TAKE_OWNERSHIP(b[i]); \
40 #define TAKE_OWNERSHIP_NOOP(val) \
42 #define TAKE_OWNERSHIP_INTERFACE(val) \
43 { static_cast<nsISupports*>(val)->AddRef(); }
44 #define TAKE_OWNERSHIP_STRING(val) \
46 nsDependentCString vprime(val); \
47 val = ToNewCString(vprime); \
49 #define TAKE_OWNERSHIP_WSTRING(val) \
51 nsDependentString vprime(val); \
52 val = ToNewUnicode(vprime); \
55 // Macro for our buffer-oriented types:
56 // 'type' is the type of element that the buffer contains.
57 // 'padding' is an offset added to length, allowing us to handle
58 // null-terminated strings.
59 // 'TAKE_OWNERSHIP' is one of the macros above.
60 #define BUFFER_METHOD_IMPL(type, padding, TAKE_OWNERSHIP) \
62 uint32_t elemSize = sizeof(type); \
64 /* Copy b into rv. */ \
65 *rvLength = *bLength; \
66 *rv = static_cast<type*>(moz_xmalloc(elemSize * (*bLength + padding))); \
67 memcpy(*rv, *b, elemSize*(*bLength + padding)); \
69 /* Copy a into b. */ \
72 *b = static_cast<type*>(moz_xmalloc(elemSize * (aLength + padding))); \
73 memcpy(*b, a, elemSize*(aLength + padding)); \
75 /* We need to take ownership of the data we got from a, \
76 since the caller owns it. */ \
77 for (unsigned i = 0; i < *bLength + padding; ++i) TAKE_OWNERSHIP((*b)[i]); \
82 NS_IMETHODIMP
nsXPCTestParams::TestBoolean(bool a
, bool* b
, bool* _retval
) {
86 NS_IMETHODIMP
nsXPCTestParams::TestOctet(uint8_t a
, uint8_t* b
,
91 NS_IMETHODIMP
nsXPCTestParams::TestShort(int16_t a
, int16_t* b
,
96 NS_IMETHODIMP
nsXPCTestParams::TestLong(int32_t a
, int32_t* b
,
101 NS_IMETHODIMP
nsXPCTestParams::TestLongLong(int64_t a
, int64_t* b
,
106 NS_IMETHODIMP
nsXPCTestParams::TestUnsignedShort(uint16_t a
, uint16_t* b
,
111 NS_IMETHODIMP
nsXPCTestParams::TestUnsignedLong(uint32_t a
, uint32_t* b
,
116 NS_IMETHODIMP
nsXPCTestParams::TestUnsignedLongLong(uint64_t a
, uint64_t* b
,
121 NS_IMETHODIMP
nsXPCTestParams::TestFloat(float a
, float* b
, float* _retval
) {
125 NS_IMETHODIMP
nsXPCTestParams::TestDouble(double a
, float* b
, double* _retval
) {
129 NS_IMETHODIMP
nsXPCTestParams::TestChar(char a
, char* b
, char* _retval
) {
133 NS_IMETHODIMP
nsXPCTestParams::TestString(const char* a
, char** b
,
135 nsDependentCString
aprime(a
);
136 nsDependentCString
bprime(*b
);
137 *_retval
= ToNewCString(bprime
);
138 *b
= ToNewCString(aprime
);
140 // XPCOM ownership rules dictate that overwritten inout params must be
141 // callee-freed. See https://developer.mozilla.org/en/XPIDL
142 free(const_cast<char*>(bprime
.get()));
147 NS_IMETHODIMP
nsXPCTestParams::TestWchar(char16_t a
, char16_t
* b
,
152 NS_IMETHODIMP
nsXPCTestParams::TestWstring(const char16_t
* a
, char16_t
** b
,
153 char16_t
** _retval
) {
154 nsDependentString
aprime(a
);
155 nsDependentString
bprime(*b
);
156 *_retval
= ToNewUnicode(bprime
);
157 *b
= ToNewUnicode(aprime
);
159 // XPCOM ownership rules dictate that overwritten inout params must be
160 // callee-freed. See https://developer.mozilla.org/en/XPIDL
161 free((void*)bprime
.get());
166 NS_IMETHODIMP
nsXPCTestParams::TestAString(const nsAString
& a
, nsAString
& b
,
167 nsAString
& _retval
) {
171 NS_IMETHODIMP
nsXPCTestParams::TestAUTF8String(const nsACString
& a
,
173 nsACString
& _retval
) {
177 NS_IMETHODIMP
nsXPCTestParams::TestACString(const nsACString
& a
, nsACString
& b
,
178 nsACString
& _retval
) {
182 NS_IMETHODIMP
nsXPCTestParams::TestJsval(JS::Handle
<JS::Value
> a
,
183 JS::MutableHandle
<JS::Value
> b
,
184 JS::MutableHandle
<JS::Value
> _retval
) {
190 NS_IMETHODIMP
nsXPCTestParams::TestShortArray(uint32_t aLength
, int16_t* a
,
191 uint32_t* bLength
, int16_t** b
,
194 BUFFER_METHOD_IMPL(int16_t, 0, TAKE_OWNERSHIP_NOOP
);
197 NS_IMETHODIMP
nsXPCTestParams::TestDoubleArray(uint32_t aLength
, double* a
,
198 uint32_t* bLength
, double** b
,
201 BUFFER_METHOD_IMPL(double, 0, TAKE_OWNERSHIP_NOOP
);
204 NS_IMETHODIMP
nsXPCTestParams::TestByteArrayOptionalLength(uint8_t* a
,
211 NS_IMETHODIMP
nsXPCTestParams::TestStringArray(uint32_t aLength
, const char** a
,
212 uint32_t* bLength
, char*** b
,
213 uint32_t* rvLength
, char*** rv
) {
214 BUFFER_METHOD_IMPL(char*, 0, TAKE_OWNERSHIP_STRING
);
217 NS_IMETHODIMP
nsXPCTestParams::TestWstringArray(
218 uint32_t aLength
, const char16_t
** a
, uint32_t* bLength
, char16_t
*** b
,
219 uint32_t* rvLength
, char16_t
*** rv
) {
220 BUFFER_METHOD_IMPL(char16_t
*, 0, TAKE_OWNERSHIP_WSTRING
);
223 NS_IMETHODIMP
nsXPCTestParams::TestInterfaceArray(
224 uint32_t aLength
, nsIXPCTestInterfaceA
** a
, uint32_t* bLength
,
225 nsIXPCTestInterfaceA
*** b
, uint32_t* rvLength
, nsIXPCTestInterfaceA
*** rv
) {
226 BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA
*, 0, TAKE_OWNERSHIP_INTERFACE
);
229 NS_IMETHODIMP
nsXPCTestParams::TestJsvalArray(uint32_t aLength
, JS::Value
* a
,
230 uint32_t* bLength
, JS::Value
** b
,
233 BUFFER_METHOD_IMPL(JS::Value
, 0, TAKE_OWNERSHIP_NOOP
);
236 NS_IMETHODIMP
nsXPCTestParams::TestSizedString(uint32_t aLength
, const char* a
,
237 uint32_t* bLength
, char** b
,
238 uint32_t* rvLength
, char** rv
) {
239 BUFFER_METHOD_IMPL(char, 1, TAKE_OWNERSHIP_NOOP
);
242 NS_IMETHODIMP
nsXPCTestParams::TestSizedWstring(uint32_t aLength
,
244 uint32_t* bLength
, char16_t
** b
,
247 BUFFER_METHOD_IMPL(char16_t
, 1, TAKE_OWNERSHIP_NOOP
);
250 NS_IMETHODIMP
nsXPCTestParams::TestInterfaceIs(const nsIID
* aIID
, void* a
,
251 nsIID
** bIID
, void** b
,
252 nsIID
** rvIID
, void** rv
) {
254 // Getting the buffers and ownership right here can be a little tricky.
257 // The interface pointers are heap-allocated, and b has been AddRef'd
258 // by XPConnect for the duration of the call. If we snatch it away from b
259 // and leave no trace, XPConnect won't Release it. Since we also need to
260 // return an already-AddRef'd pointer in rv, we don't need to do anything
264 // rvIID is out-only, so nobody allocated an IID buffer for us. Do that now,
265 // and store b's IID in the new buffer.
266 *rvIID
= static_cast<nsIID
*>(moz_xmalloc(sizeof(nsID
)));
269 // Copy the interface pointer from a to b. Since a is in-only, XPConnect will
270 // release it upon completion of the call. AddRef it for b.
272 static_cast<nsISupports
*>(*b
)->AddRef();
274 // We already had a buffer allocated for b's IID, so we can re-use it.
280 NS_IMETHODIMP
nsXPCTestParams::TestInterfaceIsArray(
281 uint32_t aLength
, const nsIID
* aIID
, void** a
, uint32_t* bLength
,
282 nsIID
** bIID
, void*** b
, uint32_t* rvLength
, nsIID
** rvIID
, void*** rv
) {
283 // Transfer the IIDs. See the comments in TestInterfaceIs (above) for an
284 // explanation of what we're doing.
285 *rvIID
= static_cast<nsIID
*>(moz_xmalloc(sizeof(nsID
)));
289 // The macro is agnostic to the actual interface types, so we can re-use code
292 // Do this second, since the macro returns.
293 BUFFER_METHOD_IMPL(void*, 0, TAKE_OWNERSHIP_INTERFACE
);
296 NS_IMETHODIMP
nsXPCTestParams::TestOutAString(nsAString
& o
) {
297 o
.AssignLiteral("out");
301 NS_IMETHODIMP
nsXPCTestParams::TestStringArrayOptionalSize(const char** a
,
305 for (uint32_t i
= 0; i
< length
; ++i
) {
313 nsXPCTestParams::TestShortSequence(const nsTArray
<short>& a
, nsTArray
<short>& b
,
314 nsTArray
<short>& _retval
) {
315 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
319 nsXPCTestParams::TestDoubleSequence(const nsTArray
<double>& a
,
321 nsTArray
<double>& _retval
) {
322 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
326 nsXPCTestParams::TestInterfaceSequence(
327 const nsTArray
<RefPtr
<nsIXPCTestInterfaceA
>>& a
,
328 nsTArray
<RefPtr
<nsIXPCTestInterfaceA
>>& b
,
329 nsTArray
<RefPtr
<nsIXPCTestInterfaceA
>>& _retval
) {
330 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
334 nsXPCTestParams::TestAStringSequence(const nsTArray
<nsString
>& a
,
335 nsTArray
<nsString
>& b
,
336 nsTArray
<nsString
>& _retval
) {
337 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
341 nsXPCTestParams::TestACStringSequence(const nsTArray
<nsCString
>& a
,
342 nsTArray
<nsCString
>& b
,
343 nsTArray
<nsCString
>& _retval
) {
344 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
348 nsXPCTestParams::TestJsvalSequence(const nsTArray
<JS::Value
>& a
,
349 nsTArray
<JS::Value
>& b
,
350 nsTArray
<JS::Value
>& _retval
) {
351 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_NOOP
);
355 nsXPCTestParams::TestSequenceSequence(const nsTArray
<nsTArray
<short>>& a
,
356 nsTArray
<nsTArray
<short>>& b
,
357 nsTArray
<nsTArray
<short>>& _retval
) {
358 _retval
= std::move(b
);
359 for (const auto& element
: a
) {
360 b
.AppendElement(element
.Clone());
366 nsXPCTestParams::TestInterfaceIsSequence(const nsIID
* aIID
,
367 const nsTArray
<void*>& a
, nsIID
** bIID
,
368 nsTArray
<void*>& b
, nsIID
** rvIID
,
369 nsTArray
<void*>& _retval
) {
370 // Shuffle around our nsIIDs
371 *rvIID
= (*bIID
)->Clone();
372 *bIID
= aIID
->Clone();
374 // Perform the generic sequence shuffle.
375 SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_INTERFACE
);
379 nsXPCTestParams::TestOptionalSequence(const nsTArray
<uint8_t>& aInArr
,
380 nsTArray
<uint8_t>& aReturnArr
) {
381 aReturnArr
= aInArr
.Clone();
386 nsXPCTestParams::TestOmittedOptionalOut(nsIXPCTestParams
* aJSObj
,
388 MOZ_ASSERT(!(*aOut
), "Unexpected value received");
389 // Call the js component, to check XPConnect won't crash when passing nullptr
390 // as the optional out parameter, and that the out object is built regardless.
392 // Invoke it directly passing nullptr.
393 rv
= aJSObj
->TestOmittedOptionalOut(nullptr, nullptr);
394 NS_ENSURE_SUCCESS(rv
, rv
);
395 // Also invoke it with a ref pointer.
396 nsCOMPtr
<nsIURI
> someURI
;
397 rv
= aJSObj
->TestOmittedOptionalOut(nullptr, getter_AddRefs(someURI
));
398 NS_ENSURE_SUCCESS(rv
, rv
);
400 rv
= someURI
->GetSpec(spec
);
401 if (!spec
.EqualsLiteral("http://example.com/")) {
402 return NS_ERROR_UNEXPECTED
;
404 someURI
.forget(aOut
);
409 nsXPCTestParams::GetTestNaN(double* aResult
) {
411 BitwiseCast
<double>((uint64_t(JSVAL_TAG_OBJECT
) << JSVAL_TAG_SHIFT
) + 1);