Merge "Copy all error properties in fromNativeValue."
diff --git a/src/proxy/websocket.js b/src/proxy/websocket.js
index 9deb710..b2d33f9 100644
--- a/src/proxy/websocket.js
+++ b/src/proxy/websocket.js
@@ -7,12 +7,13 @@
* @fileoverview WebSocket client implementation
*/
-var WebSocket = require('ws');
-var Deferred = require('./../lib/deferred');
-var vlog = require('./../lib/vlog');
-var Proxy = require('./index');
var isBrowser = require('is-browser');
+var WebSocket = require('ws');
+
var byteUtil = require('../vdl/byte-util');
+var Deferred = require('./../lib/deferred');
+var Proxy = require('./index');
+var vlog = require('./../lib/vlog');
var vom = require('../vom');
/**
@@ -75,13 +76,11 @@
// TODO(jasoncampbell): there can be more errors than just failed
// connection, additionally there can be more than one error emitted. We
// should take care to cover these cases.
- // TODO(nlacasse): Add tests that check for this error when bad wspr url is
- // provided.
- var error = new Error('Failed to connect to wspr at url ' + self.url +
- ': ' + e.message);
+ e.message = 'Failed to connect to wspr at url ' + self.url +
+ ': ' + e.message;
- vlog.logger.error(error);
- deferred.reject(error);
+ vlog.logger.error(e);
+ deferred.reject(e);
};
websocket.onmessage = function(frame) {
diff --git a/src/vdl/error-conversion.js b/src/vdl/error-conversion.js
index c788178..1f30af6 100644
--- a/src/vdl/error-conversion.js
+++ b/src/vdl/error-conversion.js
@@ -143,7 +143,18 @@
var errID = err.id || unknown.id;
var errRetryCode = err.retryCode || unknown.retryCode;
+ var errProps = {};
if (err instanceof Error) {
+ Object.getOwnPropertyNames(err).forEach(function(propName) {
+ if (propName === 'message') {
+ // Skip 'message' field since we set that ourselves to be enumerable.
+ return;
+ }
+ errProps[propName] = Object.getOwnPropertyDescriptor(err, propName);
+ // Set the property to non-enumerable.
+ errProps[propName].enumerable = false;
+ });
+
message = err.message;
paramList = ['app', 'call', message];
@@ -169,12 +180,17 @@
var EConstructor = errorMap[errID] || verror.UnknownError;
var e = new EConstructor(args);
- // Fill the remaining error parameters. By using new on an Error, we will have
- // a stack trace. Add the correct id, retryCode, message, etc.
+ // Add properties from original error.
+ Object.defineProperties(e, errProps);
+
+ // Add verror fields.
e.id = errID;
e.retryCode = errRetryCode;
e.resetArgs.apply(e, paramList);
+
+ // Add message and msg so that they will be enumerable.
e.message = message;
e.msg = message;
+
return e;
}
diff --git a/test/integration/test-client-bind-to.js b/test/integration/test-client-bind-to.js
index 53eb28c..bda032f 100644
--- a/test/integration/test-client-bind-to.js
+++ b/test/integration/test-client-bind-to.js
@@ -97,7 +97,9 @@
vanadium.init({ wspr: 'http://bad-address.tld' }, onruntime);
function onruntime(err, runtime) {
- assert.ok(err instanceof Error);
+ assert.ok(err instanceof Error, 'returns an error');
+ assert.ok(err.message.indexOf('Failed to connect') >= 0,
+ 'error is connection error');
assert.end();
}
});
@@ -114,7 +116,9 @@
assert.error('should not have succeeded');
assert.end();
}, function(err) {
- assert.ok(err instanceof Error);
+ assert.ok(err instanceof Error, 'returns an error');
+ assert.ok(err.message.indexOf('Failed to connect') >= 0,
+ 'error is connection error');
assert.end();
});
});
diff --git a/test/vdl/test-vdl-errors.js b/test/vdl/test-vdl-errors.js
index b242931..156520a 100644
--- a/test/vdl/test-vdl-errors.js
+++ b/test/vdl/test-vdl-errors.js
@@ -61,16 +61,73 @@
});
}
-var unknownError = (new verror.UnknownError(null));
test('var struct = ec.fromNativeValue(err)', function(assert) {
var err = new Error(message);
- var struct = ec.fromNativeValue(err, 'app', 'call');
- struct.paramList = deepUnwrapParamList(struct.paramList);
+
+ // Add properties that NodeJS errors commonly have.
+ Object.defineProperties(err, {
+ arguments: {
+ value: undefined,
+ writable: true,
+ enumerable: false,
+ configurable: true
+ },
+ type: {
+ value: undefined,
+ writable: true,
+ enumerable: false,
+ configurable: true
+ },
+ errno: {
+ value: 34,
+ writable: true,
+ enumerable: true,
+ configurable: true
+ },
+ code: {
+ value: 'ENOENT',
+ writable: true,
+ enumerable: true,
+ configurable: true
+ },
+ path: {
+ value: '',
+ writable: true,
+ enumerable: true,
+ configurable: true
+ }
+ });
+
+ var verr = ec.fromNativeValue(err, 'app', 'call');
+ verr.paramList = deepUnwrapParamList(verr.paramList);
+
+ // Check that verr has the correct enumerable properties.
var expectedError = new verror.UnknownError(null);
- expectedError.message = message;
- expectedError.msg = message;
- expectedError.paramList = ['app', 'call', message];
- assert.deepEqual(struct, expectedError);
+ expectedError.message = err.message;
+ expectedError.msg = err.message;
+ expectedError.paramList = ['app', 'call', err.message];
+ assert.deepEqual(verr, expectedError);
+
+ // Check that verr has the same properties (including non-enumerable
+ // properties) as the native error.
+ Object.getOwnPropertyNames(err).forEach(function(propName) {
+ assert.ok(verr.hasOwnProperty(propName), 'verror has expected property');
+ if (propName !== 'stack') {
+ // err.stack is a getter that returns different strings based on the
+ // error value, so we cannot check equality.
+ assert.equals(verr[propName], err[propName],
+ 'property matches original error');
+ }
+ });
+
+ // Check that 'code' and 'errno' properties are preserved from original
+ // error, and are not enumerable.
+ (['code', 'errno']).forEach(function(prop) {
+ assert.equal(verr[prop], err[prop], 'has the correct value for ' + prop );
+ assert.equal(Object.getOwnPropertyDescriptor(verr, 'code').enumerable,
+ false, 'property ' + prop + ' is not enumerable');
+ });
+
assert.end();
});
@@ -99,6 +156,7 @@
});
test('Error => Struct => Error', function(assert) {
+ var unknownError = new verror.UnknownError(null);
var message = 'testing JS error conversion';
var original = new Error(message);
var struct = ec.fromNativeValue(original);