sidorares / dbus-native

D-bus protocol client and server for node.js written in native javascript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

unexpected callback argument with dbus error

pabigot opened this issue · comments

With 0.2.3 invoking service.getInterface(a, b, (err, value) => {...}) in a case where the service doesn't exist returns a message like this:

{
serial: 3,
destination: ':1.398',
errorName: 'org.freedesktop.DBus.Error.ServiceUnknown',
replySerial: 2,
signature: 's',
sender: 'org.freedesktop.DBus',
type: 3,
flags: 1,
body: [ 'The name net.connman was not provided by any .service files' ]
}

This results in the callback being passed an err argument that is the value of msg.body, i.e. an array with a string member.

Is this the intended behavior? I would expect (want) an Error instance, preferably with the msg errorName property preserved, as with:

diff --git a/lib/bus.js b/lib/bus.js
index c2d6b47..b54722d 100644
--- a/lib/bus.js
+++ b/lib/bus.js
@@ -112,7 +112,9 @@ module.exports = function bus(conn, opts) {
                  args = [null].concat(args); // first argument - no errors, null
                  handler.apply(props, args); // body as array of arguments
               } else {
-                 handler.call(props, args);  // body as first argument
+                 var err = new Error(args[0]);
+                 err.errorName = msg.errorName;
+                 handler.call(props, err);  // error as first argument
               }
            }
        } else if (msg.type == constants.messageType.signal) {

Or, to handle #178:

var err = new Error(args[0] || msg.errorName);
err.errorName = msg.errorName;
handler.call(props, err);  // error as first argument

FWIW, I see no way to fix this without breaking API. If a method invocation fails, the msg.type will be constants.messageType.error rather than ...methodReturn. Since dbus-native has chosen to only follow the error-as-first-argument callback convention when the type is methodReturn the error can't be conveyed without a patch like the following:

diff --git a/lib/bus.js b/lib/bus.js
index b42d229..db838b3 100644
--- a/lib/bus.js
+++ b/lib/bus.js
@@ -106,8 +106,12 @@ module.exports = function bus(conn, opts) {
         if (msg.type === constants.messageType.methodReturn) {
           args = [null].concat(args); // first argument - no errors, null
           handler.apply(props, args); // body as array of arguments
+        } else if (msg.type === constants.messageType.error) {
+          var error = new Error(msg.errorName || 'unspecified D-Bus error');
+          error.body = msg.body;
+          handler.call(props, error); // error as first argument
         } else {
-          handler.call(props, args); // body as first argument
+          handler.call(props, null, args); // body as second argument
         }
       }
     } else if (msg.type === constants.messageType.signal) {

Hey @pabigot happy to go with this change ( probably with major version bump )

@sidorares do you want a PR for this or do you have it covered? What's your timeframe for a release; I'd like to rework my applications to the new API and test so any similar callback problems can be identified and fixed too, but if it's months out I have other things to do now.