Bug 1622887 - Properly support js components implementing an [optional] out nsISupports. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D67024

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Marco Bonardo 2020-03-18 17:54:03 +00:00
Родитель 8393d12b96
Коммит 9e08ff40bd
5 изменённых файлов: 58 добавлений и 3 удалений

Просмотреть файл

@ -558,6 +558,11 @@ void nsXPCWrappedJS::CleanupOutparams(const nsXPTMethodInfo* info,
MOZ_ASSERT(param.IsIndirect(), "Outparams are always indirect"); MOZ_ASSERT(param.IsIndirect(), "Outparams are always indirect");
// Don't try to clear optional out params that are not set.
if (param.IsOptional() && !nativeParams[i].val.p) {
continue;
}
// Call 'CleanupValue' on parameters which we know to be initialized: // Call 'CleanupValue' on parameters which we know to be initialized:
// 1. Complex parameters (initialized by caller) // 1. Complex parameters (initialized by caller)
// 2. 'inout' parameters (initialized by caller) // 2. 'inout' parameters (initialized by caller)
@ -890,8 +895,8 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
uint32_t array_count; uint32_t array_count;
RootedValue val(cx, NullValue()); RootedValue val(cx, NullValue());
// verify that null was not passed for 'out' param // Verify that null was not passed for a non-optional 'out' param.
if (param.IsOut() && !nativeParams[i].val.p) { if (param.IsOut() && !nativeParams[i].val.p && !param.IsOptional()) {
retval = NS_ERROR_INVALID_ARG; retval = NS_ERROR_INVALID_ARG;
goto pre_call_clean_up; goto pre_call_clean_up;
} }
@ -996,7 +1001,7 @@ pre_call_clean_up:
for (i = 0; i < paramCount; i++) { for (i = 0; i < paramCount; i++) {
const nsXPTParamInfo& param = info->GetParam(i); const nsXPTParamInfo& param = info->GetParam(i);
MOZ_ASSERT(!param.IsShared(), "[shared] implies [noscript]!"); MOZ_ASSERT(!param.IsShared(), "[shared] implies [noscript]!");
if (!param.IsOut()) { if (!param.IsOut() || !nativeParams[i].val.p) {
continue; continue;
} }

Просмотреть файл

@ -88,6 +88,17 @@ TestParams.prototype = {
arr.forEach((x) => rv += x); arr.forEach((x) => rv += x);
return rv; return rv;
}, },
testOmittedOptionalOut(o) {
if (typeof o != "object" || o.value !== undefined) {
throw new Components.Exception(
"unexpected value",
Cr.NS_ERROR_ILLEGAL_VALUE
);
}
o.value = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI("http://example.com/");
}
}; };
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestParams]); this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestParams]);

Просмотреть файл

@ -6,6 +6,10 @@
#include "xpctest_interfaces.h" #include "xpctest_interfaces.h"
#include "js/Value.h" #include "js/Value.h"
#include "nsCOMPtr.h"
#include "nsComponentManagerUtils.h"
#include "nsIURI.h"
NS_IMPL_ISUPPORTS(nsXPCTestParams, nsIXPCTestParams) NS_IMPL_ISUPPORTS(nsXPCTestParams, nsIXPCTestParams)
nsXPCTestParams::nsXPCTestParams() = default; nsXPCTestParams::nsXPCTestParams() = default;
@ -367,3 +371,28 @@ nsXPCTestParams::TestOptionalSequence(const nsTArray<uint8_t>& aInArr,
aReturnArr = aInArr; aReturnArr = aInArr;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsXPCTestParams::TestOmittedOptionalOut(nsIURI** aOut) {
MOZ_ASSERT(!(*aOut), "Unexpected value received");
// Call the js component, to check XPConnect won't crash when passing nullptr
// as the optional out parameter, and that the out object is built regardless.
nsresult rv;
nsCOMPtr<nsIXPCTestParams> jsComponent =
do_CreateInstance("@mozilla.org/js/xpc/test/js/Params;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Invoke it directly passing nullptr.
rv = jsComponent->TestOmittedOptionalOut(nullptr);
NS_ENSURE_SUCCESS(rv, rv);
// Also invoke it with a ref pointer.
nsCOMPtr<nsIURI> someURI;
rv = jsComponent->TestOmittedOptionalOut(getter_AddRefs(someURI));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString spec;
rv = someURI->GetSpec(spec);
if (!spec.EqualsLiteral("http://example.com/")) {
return NS_ERROR_UNEXPECTED;
}
someURI.forget(aOut);
return NS_OK;
}

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsISupports.idl" #include "nsISupports.idl"
interface nsIURI;
interface nsIXPCTestInterfaceA; interface nsIXPCTestInterfaceA;
interface nsIXPCTestInterfaceB; interface nsIXPCTestInterfaceB;
@ -108,4 +109,7 @@ interface nsIXPCTestParams : nsISupports {
// Test for optional array size_is. // Test for optional array size_is.
ACString testStringArrayOptionalSize([array, size_is(aLength)] in string a, [optional] in unsigned long aLength); ACString testStringArrayOptionalSize([array, size_is(aLength)] in string a, [optional] in unsigned long aLength);
// Test for omitted optional out parameter.
void testOmittedOptionalOut([optional] out nsIURI aOut);
}; };

Просмотреть файл

@ -16,6 +16,7 @@ function run_test() {
function test_component(contractid) { function test_component(contractid) {
// Instantiate the object. // Instantiate the object.
info("Testing " + contractid);
var o = Cc[contractid].createInstance(Ci["nsIXPCTestParams"]); var o = Cc[contractid].createInstance(Ci["nsIXPCTestParams"]);
// Possible comparator functions. // Possible comparator functions.
@ -228,4 +229,9 @@ function test_component(contractid) {
ret = o.testOptionalSequence([1, 2, 3]); ret = o.testOptionalSequence([1, 2, 3]);
Assert.ok(Array.isArray(ret)); Assert.ok(Array.isArray(ret));
Assert.equal(ret.length, 3); Assert.equal(ret.length, 3);
o.testOmittedOptionalOut();
ret = {};
o.testOmittedOptionalOut(ret);
Assert.equal(ret.value.spec, "http://example.com/")
} }