diff --git a/lib/modules/coverage.js b/lib/modules/coverage.js index 6aa81f17..6fe2e1ef 100755 --- a/lib/modules/coverage.js +++ b/lib/modules/coverage.js @@ -9,10 +9,10 @@ const Path = require('path'); const ESLint = require('eslint'); const ESLintParser = require('@babel/eslint-parser'); -const SourceMap = require('source-map'); const SourceMapSupport = require('source-map-support'); const Eslintrc = require('../linter/.eslintrc'); +const SourceMap = require('../source-map'); const Transform = require('./transform'); const internals = { diff --git a/lib/reporters/html.js b/lib/reporters/html.js index e0a1295f..be76a083 100755 --- a/lib/reporters/html.js +++ b/lib/reporters/html.js @@ -5,9 +5,9 @@ const Path = require('path'); const Handlebars = require('handlebars'); const Hoek = require('@hapi/hoek'); -const SourceMap = require('source-map'); const SourceMapSupport = require('source-map-support'); +const SourceMap = require('../source-map'); const internals = {}; diff --git a/lib/source-map.js b/lib/source-map.js new file mode 100644 index 00000000..ba4ca8fe --- /dev/null +++ b/lib/source-map.js @@ -0,0 +1,12 @@ +'use strict'; + +const Utils = require('./utils'); + +// An unfortunate quirk of source-maps is that it detects +// whether it's a node or browser environment based on the +// presence of fetch(), which is now a global in node v18. +const stash = Utils.stashProperty(globalThis, 'fetch'); + +module.exports = require('source-map'); + +Utils.restoreProperty(globalThis, 'fetch', stash); diff --git a/lib/utils.js b/lib/utils.js index b5064b83..fe01da2e 100755 --- a/lib/utils.js +++ b/lib/utils.js @@ -15,3 +15,18 @@ exports.position = function (err) { column: parseInt(match[2], 10) }; }; + +exports.stashProperty = (obj, property) => { + + const descriptor = Object.getOwnPropertyDescriptor(obj, property); + delete obj[property]; + + return descriptor; +}; + +exports.restoreProperty = (obj, property, descriptor) => { + + if (descriptor) { + Object.defineProperty(obj, property, descriptor); + } +}; diff --git a/test/utils.js b/test/utils.js index 579a1997..edfb65d5 100755 --- a/test/utils.js +++ b/test/utils.js @@ -22,4 +22,64 @@ describe('Utils', () => { expect(Utils.position({ stack: '' })).to.equal({}); }); }); + + describe('stashProperty() and restoreProperty()', () => { + + it('stashes and restores an existing property', () => { + + const obj = { x: 1 }; + + expect(obj).to.contain('x'); + + const stash = Utils.stashProperty(obj, 'x'); + + expect(obj).to.not.contain('x'); + + Utils.restoreProperty(obj, 'x', stash); + + expect(obj).to.contain('x'); + expect(obj.x).to.equal(1); + }); + + it('stashes and restores a non-existing property', () => { + + const obj = { x: 1 }; + + expect(obj).to.not.contain('y'); + + const stash = Utils.stashProperty(obj, 'y'); + + expect(obj).to.not.contain('y'); + + Utils.restoreProperty(obj, 'y', stash); + + expect(obj).to.not.contain('y'); + }); + + it('preserves descriptor', () => { + + const obj = {}; + Object.defineProperty(obj, 'x', { + value: 1, + enumerable: false, + configurable: true + }); + + expect(obj).to.contain('x'); + + const stash = Utils.stashProperty(obj, 'x'); + + expect(obj).to.not.contain('x'); + + Utils.restoreProperty(obj, 'x', stash); + + expect(obj).to.contain('x'); + + expect(Object.getOwnPropertyDescriptor(obj, 'x')).to.contain({ + value: 1, + enumerable: false, + configurable: true + }); + }); + }); });