From 5e875382369a3017aa61ed47d43a4338fe23e066 Mon Sep 17 00:00:00 2001 From: 43081j <43081j@users.noreply.github.com> Date: Mon, 26 Feb 2024 19:02:16 +0000 Subject: [PATCH] fix: support some virtual contexts in `toThrow` This adds support for VM situations where we pass a `RegExp` from another process. Note that we don't have a full fix for this stuff until `check-error` also supports `Error` being from another origin. --- lib/chai/core/assertions.js | 6 +++--- lib/chai/utils/index.js | 4 ++++ test/assert.js | 3 +++ test/virtual-machines.js | 31 +++++++++++++++++++++++++++++++ web-test-runner.config.js | 5 ++++- 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 test/virtual-machines.js diff --git a/lib/chai/core/assertions.js b/lib/chai/core/assertions.js index 7d72b068..db7b2a94 100644 --- a/lib/chai/core/assertions.js +++ b/lib/chai/core/assertions.js @@ -2676,7 +2676,7 @@ function assertThrows (errorLike, errMsgMatcher, msg) { , negate = flag(this, 'negate') || false; new Assertion(obj, flagMsg, ssfi, true).is.a('function'); - if (errorLike instanceof RegExp || typeof errorLike === 'string') { + if (_.isRegExp(errorLike) || typeof errorLike === 'string') { errMsgMatcher = errorLike; errorLike = null; } @@ -2709,7 +2709,7 @@ function assertThrows (errorLike, errMsgMatcher, msg) { } this.assert( - caughtErr + caughtErr !== undefined , 'expected #{this} to throw ' + errorLikeString , 'expected #{this} to not throw an error but #{act} was thrown' , errorLike && errorLike.toString() @@ -2760,7 +2760,7 @@ function assertThrows (errorLike, errMsgMatcher, msg) { if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) { // Here we check compatible messages var placeholder = 'including'; - if (errMsgMatcher instanceof RegExp) { + if (_.isRegExp(errMsgMatcher)) { placeholder = 'matching' } diff --git a/lib/chai/utils/index.js b/lib/chai/utils/index.js index 0602997a..099c22ad 100644 --- a/lib/chai/utils/index.js +++ b/lib/chai/utils/index.js @@ -94,3 +94,7 @@ export {isNaN} from './isNaN.js'; // getOperator method export {getOperator} from './getOperator.js'; + +export function isRegExp(obj) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +} diff --git a/test/assert.js b/test/assert.js index c469dda1..d22998a7 100644 --- a/test/assert.js +++ b/test/assert.js @@ -1644,6 +1644,9 @@ describe('assert', function () { assert[throws](function() { throw new Error('bar'); }, Error, 'bar'); assert[throws](function() { throw new Error(''); }, Error, ''); assert[throws](function() { throw new Error('foo') }, ''); + assert[throws](function() { throw ''; }, ''); + assert[throws](function() { throw ''; }, /^$/); + assert[throws](function() { throw new Error(''); }, /^$/); var thrownErr = assert[throws](function() { throw new Error('foo'); }); assert(thrownErr instanceof Error, 'assert.' + throws + ' returns error'); diff --git a/test/virtual-machines.js b/test/virtual-machines.js new file mode 100644 index 00000000..92ac1978 --- /dev/null +++ b/test/virtual-machines.js @@ -0,0 +1,31 @@ +import vm from 'node:vm'; +import * as chai from '../index.js'; + +const {assert} = chai; +const vmContext = {assert}; +vm.createContext(vmContext); + +function runCodeInVm(code) { + vm.runInContext(code, vmContext); +} + +describe('node virtual machines', function () { + it('throws', function() { + const shouldNotThrow = [ + `assert.throws(function() { throw ''; }, /^$/);`, + `assert.throws(function() { throw new Error('bleepbloop'); });`, + `assert.throws(function() { throw new Error(''); });`, + // TODO (43081j): enable this test once check-error supports + // cross-vm `Error` objects + //`assert.throws(function() { throw new Error('swoosh'); }, /swoosh/);` + ]; + + for (const code of shouldNotThrow) { + assert.doesNotThrow( + () => { + runCodeInVm(code); + } + ); + } + }); +}); diff --git a/web-test-runner.config.js b/web-test-runner.config.js index 50d70191..b9b6cb25 100644 --- a/web-test-runner.config.js +++ b/web-test-runner.config.js @@ -5,7 +5,10 @@ const commonjs = fromRollup(rollupCommonjs); export default { nodeResolve: true, - files: ["test/*.js"], + files: [ + "test/*.js", + "!test/virtual-machines.js" + ], plugins: [ commonjs({ include: [