Skip to content

Commit 0cd7a2c

Browse files
committed
[Fix] throws: avoid crashing on a nonconfigurable or nonextensible expected
1 parent 09906f3 commit 0cd7a2c

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

lib/test.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,12 @@ Test.prototype['throws'] = function (fn, expected, msg, extra) {
630630
fn();
631631
} catch (err) {
632632
caught = { error: err };
633-
if (Object(err) === err && (!isEnumerable(err, 'message') || !has(err, 'message'))) {
634-
var message = err.message;
635-
delete err.message;
636-
err.message = message;
633+
if (Object(err) === err && 'message' in err && (!isEnumerable(err, 'message') || !has(err, 'message'))) {
634+
try {
635+
var message = err.message;
636+
delete err.message;
637+
err.message = message;
638+
} catch (e) { /**/ }
637639
}
638640
}
639641

test/throws.js

+49-4
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,28 @@ tap.test('failures', function (tt) {
112112
' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
113113
' [... stack stripped ...]',
114114
' ...',
115+
'# non-extensible throw match',
116+
'ok 37 error is non-extensible',
117+
'ok 38 non-extensible error matches',
118+
'ok 39 errorWithMessage is non-extensible',
119+
'not ok 40 non-extensible error with message matches',
120+
' ---',
121+
' operator: throws',
122+
' expected: |-',
123+
' { foo: 1 }',
124+
' actual: |-',
125+
' { message: \'abc\' }',
126+
' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
127+
' ...',
128+
'# frozen `message` property',
129+
'ok 41 error is non-writable',
130+
'ok 42 error is non-configurable',
131+
'ok 43 non-writable error matches',
115132
'',
116-
'1..36',
117-
'# tests 36',
118-
'# pass 33',
119-
'# fail 3',
133+
'1..43',
134+
'# tests 43',
135+
'# pass 39',
136+
'# fail 4',
120137
''
121138
]);
122139
}));
@@ -304,4 +321,32 @@ tap.test('failures', function (tt) {
304321
// AssertionError [ERR_ASSERTION]
305322
t.end();
306323
});
324+
325+
test('non-extensible throw match', { skip: !Object.seal }, function (t) {
326+
var error = { foo: 1 };
327+
Object.seal(error);
328+
t.throws(function () { error.x = 1; }, TypeError, 'error is non-extensible');
329+
330+
t.throws(function () { throw error; }, error, 'non-extensible error matches');
331+
332+
var errorWithMessage = { message: 'abc' };
333+
Object.seal(errorWithMessage);
334+
t.throws(function () { errorWithMessage.x = 1; }, TypeError, 'errorWithMessage is non-extensible');
335+
336+
t.throws(function () { throw errorWithMessage; }, error, 'non-extensible error with message matches');
337+
338+
t.end();
339+
});
340+
341+
test('frozen `message` property', { skip: !Object.defineProperty }, function (t) {
342+
var error = { message: 'abc' };
343+
Object.defineProperty(error, 'message', { configurable: false, enumerable: false, writable: false });
344+
345+
t.throws(function () { error.message = 'def'; }, TypeError, 'error is non-writable');
346+
t.throws(function () { delete error.message; }, TypeError, 'error is non-configurable');
347+
348+
t.throws(function () { throw error; }, { message: 'abc' }, 'non-writable error matches');
349+
350+
t.end();
351+
});
307352
});

0 commit comments

Comments
 (0)