Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: chaijs/check-error
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.0.0
Choose a base ref
...
head repository: chaijs/check-error
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.1.0
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on May 8, 2024

  1. feat: support virtual contexts (#50)

    This adds support for virtual contexts by testing `RegExp` and `Error`
    via `toString` instead of an `instanceof` check.
    43081j authored May 8, 2024
    Copy the full SHA
    d3622a0 View commit details
Showing with 101 additions and 7 deletions.
  1. +19 −5 index.js
  2. +3 −2 package.json
  3. +70 −0 test/virtual-machines.js
  4. +9 −0 web-test-runner.config.js
24 changes: 19 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
function isErrorInstance(obj) {
// eslint-disable-next-line prefer-reflect
return obj instanceof Error || Object.prototype.toString.call(obj) === '[object Error]';
}

function isErrorClass(obj) {
return obj === Error || (typeof obj === 'function' && obj.name === 'Error');
}

function isRegExp(obj) {
// eslint-disable-next-line prefer-reflect
return Object.prototype.toString.call(obj) === '[object RegExp]';
}

/**
* ### .compatibleInstance(thrown, errorLike)
*
@@ -13,7 +27,7 @@
*/

function compatibleInstance(thrown, errorLike) {
return errorLike instanceof Error && thrown === errorLike;
return isErrorInstance(errorLike) && thrown === errorLike;
}

/**
@@ -33,10 +47,10 @@ function compatibleInstance(thrown, errorLike) {
*/

function compatibleConstructor(thrown, errorLike) {
if (errorLike instanceof Error) {
if (isErrorInstance(errorLike)) {
// If `errorLike` is an instance of any error we compare their constructors
return thrown.constructor === errorLike.constructor || thrown instanceof errorLike.constructor;
} else if (errorLike.prototype instanceof Error || errorLike === Error) {
} else if (isErrorClass(Object.getPrototypeOf(errorLike)) || isErrorClass(errorLike)) {
// If `errorLike` is a constructor that inherits from Error, we compare `thrown` to `errorLike` directly
return thrown.constructor === errorLike || thrown instanceof errorLike;
}
@@ -60,7 +74,7 @@ function compatibleConstructor(thrown, errorLike) {

function compatibleMessage(thrown, errMatcher) {
const comparisonString = typeof thrown === 'string' ? thrown : thrown.message;
if (errMatcher instanceof RegExp) {
if (isRegExp(errMatcher)) {
return errMatcher.test(comparisonString);
} else if (typeof errMatcher === 'string') {
return comparisonString.indexOf(errMatcher) !== -1; // eslint-disable-line no-magic-numbers
@@ -82,7 +96,7 @@ function compatibleMessage(thrown, errMatcher) {

function getConstructorName(errorLike) {
let constructorName = errorLike;
if (errorLike instanceof Error) {
if (isErrorInstance(errorLike)) {
constructorName = errorLike.constructor.name;
} else if (typeof errorLike === 'function') {
// If `err` is not an instance of Error it is an error constructor itself or another function.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
"pretest": "npm run lint && npm run build",
"test": "npm run test:node && npm run test:browser",
"test:browser": "web-test-runner --node-resolve test/",
"test:browser": "web-test-runner",
"test:node": "mocha"
},
"config": {
@@ -53,7 +53,8 @@
"rules": {
"complexity": "off",
"max-statements": "off",
"prefer-arrow-callback": "off"
"prefer-arrow-callback": "off",
"prefer-reflect": "off"
}
},
"devDependencies": {
70 changes: 70 additions & 0 deletions test/virtual-machines.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { createContext, runInContext } from 'node:vm';
import { assert } from 'simple-assert';
import * as checkError from '../index.js';

const vmContext = { checkError };
createContext(vmContext);

function runCodeInVm(code) {
return runInContext(`{${ code }}`, vmContext);
}

describe('node virtual machines', function () {
it('compatibleMessage', function () {
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
checkError.compatibleMessage(errorInstance, /instance$/) === true;
`) === true);
});

it('constructorName', function () {
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
checkError.getConstructorName(errorInstance);
`) === 'Error');
assert(runCodeInVm(`
const derivedInstance = new TypeError('I inherit from Error');
checkError.getConstructorName(derivedInstance);
`) === 'TypeError');
});

it('compatibleInstance', function () {
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const sameInstance = errorInstance;
checkError.compatibleInstance(errorInstance, sameInstance);
`) === true);
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const otherInstance = new Error('I am another');
checkError.compatibleInstance(errorInstance, otherInstance);
`) === false);
});

it('compatibleConstructor', function () {
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const sameInstance = errorInstance;
checkError.compatibleConstructor(errorInstance, sameInstance);
`) === true);
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const otherInstance = new Error('I an another instance');
checkError.compatibleConstructor(errorInstance, otherInstance);
`) === true);
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const derivedInstance = new TypeError('I inherit from Error');
checkError.compatibleConstructor(derivedInstance, errorInstance);
`) === true);
assert(runCodeInVm(`
const errorInstance = new Error('I am an instance');
const derivedInstance = new TypeError('I inherit from Error');
checkError.compatibleConstructor(errorInstance, derivedInstance);
`) === false);
assert(runCodeInVm(`
const errorInstance = new TypeError('I am an instance');
checkError.compatibleConstructor(errorInstance, TypeError);
`) === true);
});
});
9 changes: 9 additions & 0 deletions web-test-runner.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default {
nodeResolve: true,
files: [
'test/*.js',
'!test/virtual-machines.js',
],
plugins: [
],
};