Bug 1551124. Add support for optional Array arguments in xpconnect. r=nika
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 13 May 2019 19:51:57 +0000
changeset 535539 e2bf0e06cb7564341039fe37a03a0dbe70b0a543
parent 535538 b0c2b45643a2be2ea68e114630cad0c546f23e8b
child 535540 aca591c75b072b5737b372a4aa226a5aba502b1d
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1551124
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1551124. Add support for optional Array arguments in xpconnect. r=nika The semantics are that you get an empty array if the argument is not supplied, and if [optional_argc] is used it's set accordingly so you can tell whether you were passed explicit [] or not passed anything. Differential Revision: https://phabricator.services.mozilla.com/D30850
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/tests/components/js/xpctest_params.js
js/xpconnect/tests/components/native/xpctest_params.cpp
js/xpconnect/tests/idl/xpctest_params.idl
js/xpconnect/tests/unit/test_params.js
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -1515,16 +1515,22 @@ bool CallMethodHelper::ConvertIndependen
   // the default value if IsOptional is true.
   if (i >= mArgc) {
     MOZ_ASSERT(paramInfo.IsOptional(), "missing non-optional argument!");
     if (type.Tag() == nsXPTType::T_NSID) {
       // Use a default value of the null ID for optional NSID objects.
       dp->ext.nsid.Clear();
       return true;
     }
+
+    if (type.Tag() == nsXPTType::T_ARRAY) {
+      // Use a default value of empty array for optional Array objects.
+      dp->ext.array.Clear();
+      return true;
+    }
   }
 
   // We're definitely some variety of 'in' now, so there's something to
   // convert. The source value for conversion depends on whether we're
   // dealing with an 'in' or an 'inout' parameter. 'inout' was handled above,
   // so all that's left is 'in'.
   if (!paramInfo.IsOut()) {
     // Handle the 'in' case.
--- a/js/xpconnect/tests/components/js/xpctest_params.js
+++ b/js/xpconnect/tests/components/js/xpctest_params.js
@@ -65,28 +65,29 @@ TestParams.prototype = {
   testJsval: f,
   testShortSequence: f,
   testDoubleSequence: f,
   testAStringSequence: f,
   testACStringSequence: f,
   testInterfaceSequence: f,
   testJsvalSequence: f,
   testInterfaceIsSequence: f_is,
+  testOptionalSequence: function (arr) { return arr; },
   testShortArray: f_is,
   testDoubleArray: f_is,
   testStringArray: f_is,
   testWstringArray: f_is,
   testInterfaceArray: f_is,
   testJsvalArray: f_is,
   testSizedString: f_is,
   testSizedWstring: f_is,
   testInterfaceIs: f_is,
   testInterfaceIsArray: f_size_and_iid,
   testOutAString: function(o) { o.value = "out"; },
   testStringArrayOptionalSize: function(arr, size) {
     if (arr.length != size) { throw "bad size passed to test method"; }
     var rv = "";
     arr.forEach((x) => rv += x);
     return rv;
-  }
+  },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestParams]);
--- a/js/xpconnect/tests/components/native/xpctest_params.cpp
+++ b/js/xpconnect/tests/components/native/xpctest_params.cpp
@@ -355,8 +355,15 @@ nsXPCTestParams::TestInterfaceIsSequence
                                          nsTArray<void*>& _retval) {
   // Shuffle around our nsIIDs
   *rvIID = (*bIID)->Clone();
   *bIID = aIID->Clone();
 
   // Perform the generic sequence shuffle.
   SEQUENCE_METHOD_IMPL(TAKE_OWNERSHIP_INTERFACE);
 }
+
+NS_IMETHODIMP
+nsXPCTestParams::TestOptionalSequence(const nsTArray<uint8_t>& aInArr,
+                                      nsTArray<uint8_t>& aReturnArr) {
+  aReturnArr = aInArr;
+  return NS_OK;
+}
--- a/js/xpconnect/tests/idl/xpctest_params.idl
+++ b/js/xpconnect/tests/idl/xpctest_params.idl
@@ -46,16 +46,19 @@ interface nsIXPCTestParams : nsISupports
   Array<ACString>       testACStringSequence(in Array<ACString> a, inout Array<ACString> b);
   Array<jsval>          testJsvalSequence(in Array<jsval> a, inout Array<jsval> b);
   Array<Array<short> >  testSequenceSequence(in Array<Array<short> > a, inout Array<Array<short> > b);
 
   void                  testInterfaceIsSequence(in nsIIDPtr aIID, [iid_is(aIID)] in Array<nsQIResult> a,
                                                 inout nsIIDPtr bIID, [iid_is(bIID)] inout Array<nsQIResult> b,
                                                 out nsIIDPtr rvIID, [retval, iid_is(rvIID)] out Array<nsQIResult> rv);
 
+  // Returns whatever was passed in.
+  Array<uint8_t>        testOptionalSequence([optional] in Array<uint8_t> arr);
+
   //
   // Dependent parameters use the same types as above, but are handled much differently.
   //
 
   // Test arrays.
   void                  testShortArray(in unsigned long aLength, [array, size_is(aLength)] in short a,
                                        inout unsigned long bLength, [array, size_is(bLength)] inout short b,
                                        out unsigned long rvLength, [retval, array, size_is(rvLength)] out short rv);
--- a/js/xpconnect/tests/unit/test_params.js
+++ b/js/xpconnect/tests/unit/test_params.js
@@ -211,9 +211,21 @@ function test_component(contractid) {
                                   [makeA(), makeA(), makeA(), makeA(), makeA(), makeA()], arrayComparator(interfaceComparator));
 
   doTest("testJsvalSequence", [{ cheese: 'whiz', apple: 8 }, [1, 5, '3'], /regex/],
                               ['apple', 2.2e10, 3.3e30, { only: "wheedle", except: {} }], arrayComparator(standardComparator));
 
   doIsTest("testInterfaceIsSequence", [makeA(), makeA(), makeA(), makeA(), makeA()], Ci['nsIXPCTestInterfaceA'],
                                       [makeB(), makeB(), makeB()], Ci['nsIXPCTestInterfaceB'],
                                       arrayComparator(interfaceComparator), dotEqualsComparator);
+
+  var ret = o.testOptionalSequence();
+  Assert.ok(Array.isArray(ret));
+  Assert.equal(ret.length, 0);
+
+  ret = o.testOptionalSequence([]);
+  Assert.ok(Array.isArray(ret));
+  Assert.equal(ret.length, 0);
+
+  ret = o.testOptionalSequence([1, 2, 3]);
+  Assert.ok(Array.isArray(ret));
+  Assert.equal(ret.length, 3);
 }