Skip to content

Commit d4c5823

Browse files
committed
Create a DBus.Error error class
Create a DBus.Error class that contains both the error's name and message. throw new DBus.Error('dbus.test.TestService.Error', 'Human-readable error message') Return this type of error to the client when a DBus service returns an error on a function call, so that the caller has access both to the name and the message.
1 parent f755fa9 commit d4c5823

13 files changed

+114
-23
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,28 @@ made (via `addMethod`, `addProperty`, and `addSignal`), `update` must be called
358358
to ensure that other DBus clients can see the changes that were made.
359359

360360

361+
### DBus.Error
362+
363+
A DBus-specific error
364+
365+
#### `new DBus.Error(name, message)`
366+
367+
* name `<string>` - A valid DBus Error name, according to the [specification][spec]
368+
* message `<string>` - A human readable message
369+
370+
Create a new error. The name must be a valid error name.
371+
372+
```
373+
throw new DBus.Error('com.example.Library.Error.BookExistsError', 'The book already exists');
374+
```
375+
376+
#### `dbusError.dbusName`
377+
378+
The DBus Error name of the error. When a DBus.Error is created, its message is
379+
set to the human-readable error message. The `dbusName` property is set to the
380+
name (according to the DBus Spec).
381+
382+
361383
## License
362384

363385
(The MIT License)
@@ -383,3 +405,4 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
383405
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
384406
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
385407

408+
[spec]: https://dbus.freedesktop.org/doc/dbus-specification.html

examples/service.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ iface1.addMethod('Dummy', {}, function(callback) {
1717
});
1818

1919
iface1.addMethod('MakeError', { out: DBus.Define(String) }, function(callback) {
20-
var error = new Error('Some error');
21-
error.dbusName = 'nodejs.dbus.ExampleService.ErrorTest';
22-
callback(error);
20+
callback(new DBus.Error('nodejs.dbus.ExampleService.ErrorTest', 'Some error'));
2321
});
2422

2523
iface1.addMethod('Hello', { out: DBus.Define(String) }, function(callback) {

lib/dbus.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var _dbus = require('../build/Release/dbus.node');
55
var Utils = require('./utils');
66
var Bus = require('./bus');
77
var Service = require('./service');
8+
var Error = require('./error');
89

910
var serviceMap = {};
1011

@@ -36,6 +37,7 @@ var DBus = module.exports = function(opts) {
3637

3738
DBus.Define = Utils.Define;
3839
DBus.Signature = Utils.Signature;
40+
DBus.Error = Error;
3941

4042
DBus.prototype.getBus = function(busName) {
4143
var self = this;
@@ -128,9 +130,14 @@ DBus.prototype._sendErrorMessageReply = function(message, name, msg) {
128130
_dbus.sendErrorMessageReply(message, name, msg);
129131
};
130132

131-
DBus.prototype.callMethod = function() {
133+
function createError(name, message) {
134+
return new DBus.Error(name, message);
135+
}
132136

133-
_dbus.callMethod.apply(this, Array.prototype.slice.call(arguments));
137+
DBus.prototype.callMethod = function() {
138+
var args = Array.prototype.slice.call(arguments);
139+
args.push(createError);
140+
_dbus.callMethod.apply(this, args);
134141
};
135142

136143
DBus.prototype.setMaxMessageSize = function(bus, size) {

lib/error.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
var util = require('util');
2+
3+
function DBusError(name, message) {
4+
Error.call(this, message);
5+
this.message = message;
6+
this.dbusName = name;
7+
8+
if (Error.captureStackTrace) {
9+
Error.captureStackTrace(this, 'DBusError');
10+
}
11+
else {
12+
Object.defineProperty(this, 'stack', { value: (new Error()).stack });
13+
}
14+
}
15+
16+
util.inherits(DBusError, Error);
17+
18+
DBusError.prototype.toString = function() {
19+
return 'DBusError: ' + this.message;
20+
}
21+
22+
module.exports = DBusError;

lib/interface.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,6 @@ Interface.prototype.init = function(callback) {
7575
});
7676
};
7777
})(methodName, self.object['method'][methodName]['in'].join('') || '');
78-
self[methodName].timeout = -1;
79-
self[methodName].finish = null;
80-
self[methodName].error = null;
81-
8278
}
8379

8480
// Initializing signal handler

src/dbus.cc

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,38 @@ namespace NodeDBus {
3737

3838
Local<Value> err = Nan::Null();
3939
if (dbus_error_is_set(&error)) {
40-
err = Nan::Error(error.message);
40+
if (error.message != NULL) {
41+
Local<Value> createErrorParameters[] = {
42+
Nan::New(error.name).ToLocalChecked(),
43+
Nan::New(error.message).ToLocalChecked()
44+
};
45+
err = data->createError->Call(2, createErrorParameters);
46+
}
47+
else {
48+
Local<Value> createErrorParameters[] = {
49+
Nan::New(error.name).ToLocalChecked(),
50+
Nan::Undefined()
51+
};
52+
err = data->createError->Call(2, createErrorParameters);
53+
}
4154
dbus_error_free(&error);
4255
} else if (dbus_message_get_type(reply_message) == DBUS_MESSAGE_TYPE_ERROR) {
43-
err = Nan::Error(dbus_message_get_error_name(reply_message));
56+
dbus_set_error_from_message(&error, reply_message);
57+
if (error.message != NULL) {
58+
Local<Value> createErrorParameters[] = {
59+
Nan::New(error.name).ToLocalChecked(),
60+
Nan::New(error.message).ToLocalChecked()
61+
};
62+
err = data->createError->Call(2, createErrorParameters);
63+
}
64+
else {
65+
Local<Value> createErrorParameters[] = {
66+
Nan::New(error.name).ToLocalChecked(),
67+
Nan::Undefined()
68+
};
69+
err = data->createError->Call(2, createErrorParameters);
70+
}
71+
dbus_error_free(&error);
4472
}
4573

4674
// Decode message for arguments
@@ -129,6 +157,9 @@ namespace NodeDBus {
129157
if (!info[8]->IsFunction())
130158
return Nan::ThrowError("Require callback function");
131159

160+
if (!info[9]->IsFunction())
161+
return Nan::ThrowError("Require createError function");
162+
132163
int timeout = -1;
133164
if (info[6]->IsInt32())
134165
timeout = info[6]->Int32Value();
@@ -219,6 +250,7 @@ namespace NodeDBus {
219250
DBusAsyncData *data = new DBusAsyncData;
220251
data->pending = pending;
221252
data->callback = new Nan::Callback(info[8].As<Function>());
253+
data->createError = new Nan::Callback(info[9].As<Function>());
222254
if (!dbus_pending_call_set_notify(pending, method_callback, data, method_free)) {
223255
if (message != NULL)
224256
dbus_message_unref(message);

src/dbus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ namespace NodeDBus {
2020
// Nan::Persistent<Function> callback;
2121
Nan::Callback *callback;
2222
DBusPendingCall *pending;
23+
Nan::Callback *createError;
2324

2425
~DBusAsyncData() {
26+
delete createError;
2527
delete callback;
2628
}
2729
} DBusAsyncData;

test/client-call-error.test.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var withService = require('./with-service');
22
var tap = require('tap');
33
var DBus = require('../');
44

5-
tap.plan(6);
5+
tap.plan(10);
66
withService('service.js', function(err, done) {
77
if (err) throw err;
88

@@ -13,14 +13,16 @@ withService('service.js', function(err, done) {
1313
iface.ThrowsError({ timeout: 1000 }, function(err, result) {
1414
tap.notSame(err, null);
1515
tap.same(result, null);
16-
// tap.match(err.message, /from service/);
17-
tap.match(err.message, 'org.freedesktop.DBus.Error.Failed');
16+
tap.match(err.message, /from.*service/);
17+
tap.match(err.dbusName, 'org.freedesktop.DBus.Error.Failed');
18+
tap.type(err, DBus.Error);
1819

1920
iface.ThrowsCustomError({ timeout: 1000 }, function(err, result) {
2021
tap.notSame(err, null);
2122
tap.same(result, null);
22-
// tap.match(err.message, /from service/);
23-
tap.match(err.message, 'test.dbus.TestService.Error');
23+
tap.match(err.message, /from.*service/);
24+
tap.match(err.dbusName, 'test.dbus.TestService.Error');
25+
tap.type(err, DBus.Error);
2426
done();
2527
bus.disconnect();
2628
});

test/client-property-error.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var withService = require('./with-service');
22
var tap = require('tap');
33
var DBus = require('../');
44

5-
tap.plan(3);
5+
tap.plan(4);
66
withService('service.js', function(err, done) {
77
if (err) throw err;
88

@@ -13,8 +13,8 @@ withService('service.js', function(err, done) {
1313
iface.getProperty('ErrorProperty', function(err, value) {
1414
tap.notSame(err, null);
1515
tap.same(value, null);
16-
//tap.match(err.message, /from service/);
17-
tap.match(err.message, 'org.freedesktop.DBus.Error.Failed');
16+
tap.match(err.message, /from.*service/);
17+
tap.type(err, DBus.Error);
1818
done();
1919
bus.disconnect();
2020
});

test/client-property.test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ withService('service.js', function(err, done) {
2121
tap.equal(value, 'http://stem.mandice.org');
2222

2323
iface.getProperties(function(err, props) {
24-
console.log(props);
2524
tap.equal(props.Author, 'Douglas Adams');
2625
tap.equal(props.URL, 'http://stem.mandice.org');
2726
done();

0 commit comments

Comments
 (0)