Skip to content

Commit 0731b5f

Browse files
committed
[Fix] throws: avoid crashing on a nonconfigurable or nonextensible expected
1 parent 834453c commit 0731b5f

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

lib/test.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -542,10 +542,12 @@ Test.prototype['throws'] = function (fn, expected, msg, extra) {
542542
fn();
543543
} catch (err) {
544544
caught = { error: err };
545-
if (Object(err) === err && (!isEnumerable(err, 'message') || !has(err, 'message'))) {
546-
var message = err.message;
547-
delete err.message;
548-
err.message = message;
545+
if (Object(err) === err && 'message' in err && (!isEnumerable(err, 'message') || !has(err, 'message'))) {
546+
try {
547+
var message = err.message;
548+
delete err.message;
549+
err.message = message;
550+
} catch (e) { /**/ }
549551
}
550552
}
551553

test/throws.js

+40-3
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,19 @@ tap.test('failures', function (tt) {
176176
' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
177177
' [... stack stripped ...]',
178178
' ...',
179+
'# non-extensible throw match',
180+
'ok 15 error is non-extensible',
181+
'ok 16 non-extensible error matches',
182+
'ok 17 errorWithMessage is non-extensible',
183+
'ok 18 non-extensible error with message matches',
184+
'# frozen `message` property',
185+
'ok 19 error is non-writable',
186+
'ok 20 error is non-configurable',
187+
'ok 21 non-writable error matches',
179188
'',
180-
'1..14',
181-
'# tests 14',
182-
'# pass 4',
189+
'1..21',
190+
'# tests 21',
191+
'# pass 11',
183192
'# fail 10',
184193
''
185194
]);
@@ -221,4 +230,32 @@ tap.test('failures', function (tt) {
221230
t['throws'](function () { throw actual; }, TypeError, 'throws actual');
222231
t.end();
223232
});
233+
234+
test('non-extensible throw match', { skip: !Object.seal }, function (t) {
235+
var error = { foo: 1 };
236+
Object.seal(error);
237+
t.throws(function () { error.x = 1; }, TypeError, 'error is non-extensible');
238+
239+
t.throws(function () { throw error; }, error, 'non-extensible error matches');
240+
241+
var errorWithMessage = { message: 'abc' };
242+
Object.seal(errorWithMessage);
243+
t.throws(function () { errorWithMessage.x = 1; }, TypeError, 'errorWithMessage is non-extensible');
244+
245+
t.throws(function () { throw errorWithMessage; }, error, 'non-extensible error with message matches');
246+
247+
t.end();
248+
});
249+
250+
test('frozen `message` property', { skip: !Object.defineProperty }, function (t) {
251+
var error = { message: 'abc' };
252+
Object.defineProperty(error, 'message', { configurable: false, enumerable: false, writable: false });
253+
254+
t.throws(function () { error.message = 'def'; }, TypeError, 'error is non-writable');
255+
t.throws(function () { delete error.message; }, TypeError, 'error is non-configurable');
256+
257+
t.throws(function () { throw error; }, { message: 'abc' }, 'non-writable error matches');
258+
259+
t.end();
260+
});
224261
});

0 commit comments

Comments
 (0)