Skip to content

Commit c1b483c

Browse files
committed
[Fix] throws: only reassign “message” when it is not already non-enumerable.
Fixes #320.
1 parent 918e217 commit c1b483c

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

lib/test.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ var inherits = require('inherits');
55
var EventEmitter = require('events').EventEmitter;
66
var has = require('has');
77
var trim = require('string.prototype.trim');
8+
var bind = require('function-bind');
9+
var isEnumerable = bind.call(Function.call, Object.prototype.propertyIsEnumerable);
810

911
module.exports = Test;
1012

@@ -444,9 +446,11 @@ Test.prototype['throws'] = function (fn, expected, msg, extra) {
444446
fn();
445447
} catch (err) {
446448
caught = { error : err };
447-
var message = err.message;
448-
delete err.message;
449-
err.message = message;
449+
if (!isEnumerable(err, 'message') || !has(err, 'message')) {
450+
var message = err.message;
451+
delete err.message;
452+
err.message = message;
453+
}
450454
}
451455

452456
var passed = caught;

test/throws.js

+21-4
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,14 @@ tap.test('failures', function (tt) {
9393
+ ' operator: throws\n'
9494
+ ' expected: undefined\n'
9595
+ ' actual: undefined\n'
96-
+ ' ...\n\n'
97-
+ '1..9\n'
98-
+ '# tests 9\n'
99-
+ '# pass 0\n'
96+
+ ' ...\n'
97+
+ '# custom error messages\n'
98+
+ 'ok 10 "message" is enumerable\n'
99+
+ "ok 11 { custom: 'error', message: 'message' }\n"
100+
+ 'ok 12 getter is still the same\n'
101+
+ '\n1..12\n'
102+
+ '# tests 12\n'
103+
+ '# pass 3\n'
100104
+ '# fail 9\n'
101105
);
102106
}));
@@ -117,4 +121,17 @@ tap.test('failures', function (tt) {
117121
t.plan(1);
118122
t.throws(function () {});
119123
});
124+
125+
test('custom error messages', function (t) {
126+
t.plan(3);
127+
var getter = function () { return 'message'; };
128+
var messageGetterError = Object.defineProperty(
129+
{ custom: 'error' },
130+
'message',
131+
{ configurable: true, enumerable: true, get: getter }
132+
);
133+
t.equal(Object.prototype.propertyIsEnumerable.call(messageGetterError, 'message'), true, '"message" is enumerable');
134+
t.throws(function () { throw messageGetterError; }, "{ custom: 'error', message: 'message' }");
135+
t.equal(Object.getOwnPropertyDescriptor(messageGetterError, 'message').get, getter, 'getter is still the same');
136+
});
120137
});

0 commit comments

Comments
 (0)