Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support virtual contexts #50

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
*
Expand All @@ -13,7 +27,7 @@
*/

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

/**
Expand All @@ -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;
}
Expand All @@ -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
Expand All @@ -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.
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -53,7 +53,8 @@
"rules": {
"complexity": "off",
"max-statements": "off",
"prefer-arrow-callback": "off"
"prefer-arrow-callback": "off",
"prefer-reflect": "off"
}
},
"devDependencies": {
Expand Down
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: [
],
};
Loading