lib: allow skipping source maps in node_modules

Files in `node_modules` are not authored by the user directly and the
original sources are less relevant to the user.

Skipping source maps in `node_modules` improves the general
performance. Add `module.setSourceMapsSupport(enabled, options)` to
skip source maps in `node_modules` if it is needed. This moves
all source maps related API to `node:module` and this a step to
promote the source maps API to stable.

PR-URL: https://github.com/nodejs/node/pull/56639
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
Chengzhong Wu 2025-01-23 22:44:10 +00:00 committed by GitHub
parent 869d0cbca3
commit b11ee4cad3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 491 additions and 48 deletions

View File

@ -2,13 +2,19 @@
const common = require('../common.js');
const modPath = require.resolve('../fixtures/simple-error-stack.js');
const nodeModulePath = require.resolve('../fixtures/node_modules/error-stack/simple-error-stack.js');
const Module = require('node:module');
const bench = common.createBenchmark(main, {
method: ['without-sourcemap', 'sourcemap'],
method: [
'without-sourcemap',
'sourcemap',
'node-modules-without-sourcemap',
'node-module-sourcemap'],
n: [1e5],
});
function runN(n) {
function runN(n, modPath) {
delete require.cache[modPath];
const mod = require(modPath);
bench.start();
@ -22,11 +28,23 @@ function main({ n, method }) {
switch (method) {
case 'without-sourcemap':
process.setSourceMapsEnabled(false);
runN(n);
runN(n, modPath);
break;
case 'sourcemap':
process.setSourceMapsEnabled(true);
runN(n);
runN(n, modPath);
break;
case 'node-modules-without-sourcemap':
Module.setSourceMapsSupport(true, {
nodeModules: false,
});
runN(n, nodeModulePath);
break;
case 'node-modules-sourcemap':
Module.setSourceMapsSupport(true, {
nodeModules: true,
});
runN(n, nodeModulePath);
break;
default:
throw new Error(`Unexpected method "${method}"`);

View File

@ -0,0 +1,16 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.simpleErrorStack = simpleErrorStack;
// Compile with `tsc --inlineSourceMap benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts`.
var lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
function simpleErrorStack() {
[1].map(function () {
try {
lorem.BANG();
}
catch (e) {
return e.stack;
}
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLWVycm9yLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2ltcGxlLWVycm9yLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFpQlgsNENBQWdCO0FBZmxCLGlGQUFpRjtBQUVqRixJQUFNLEtBQUssR0FBRywrYkFBK2IsQ0FBQztBQUU5YyxTQUFTLGdCQUFnQjtJQUN2QixDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUNOLElBQUksQ0FBQztZQUNGLEtBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN4QixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDIn0=

View File

@ -0,0 +1,19 @@
'use strict';
// Compile with `tsc --inlineSourceMap benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts`.
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
function simpleErrorStack() {
[1].map(() => {
try {
(lorem as any).BANG();
} catch (e) {
return e.stack;
}
})
}
export {
simpleErrorStack,
};

View File

@ -1596,6 +1596,20 @@ import { findSourceMap, SourceMap } from 'node:module';
const { findSourceMap, SourceMap } = require('node:module');
```
### `module.getSourceMapsSupport()`
<!-- YAML
added: REPLACEME
-->
* Returns: {Object}
* `enabled` {boolean} If the source maps support is enabled
* `nodeModules` {boolean} If the support is enabled for files in `node_modules`.
* `generatedCode` {boolean} If the support is enabled for generated code from `eval` or `new Function`.
This method returns whether the [Source Map v3][Source Map] support for stack
traces is enabled.
<!-- Anchors to make sure old links find a target -->
<a id="module_module_findsourcemap_path_error"></a>
@ -1615,6 +1629,31 @@ added:
`path` is the resolved path for the file for which a corresponding source map
should be fetched.
### `module.setSourceMapsSupport(enabled[, options])`
<!-- YAML
added: REPLACEME
-->
* `enabled` {boolean} Enable the source map support.
* `options` {Object} Optional
* `nodeModules` {boolean} If enabling the support for files in
`node_modules`. **Default:** `false`.
* `generatedCode` {boolean} If enabling the support for generated code from
`eval` or `new Function`. **Default:** `false`.
This function enables or disables the [Source Map v3][Source Map] support for
stack traces.
It provides same features as launching Node.js process with commandline options
`--enable-source-maps`, with additional options to alter the support for files
in `node_modules` or generated codes.
Only source maps in JavaScript files that are loaded after source maps has been
enabled will be parsed and loaded. Preferably, use the commandline options
`--enable-source-maps` to avoid losing track of source maps of modules loaded
before this API call.
### Class: `module.SourceMap`
<!-- YAML
@ -1715,6 +1754,7 @@ returned object contains the following keys:
[Customization hooks]: #customization-hooks
[ES Modules]: esm.md
[Permission Model]: permissions.md#permission-model
[Source Map]: https://sourcemaps.info/spec.html
[Source map v3 format]: https://sourcemaps.info/spec.html#h.mofvlxcwqzej
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
[V8 code cache]: https://v8.dev/blog/code-caching-for-devs

View File

@ -4003,7 +4003,7 @@ added:
- v14.18.0
-->
> Stability: 1 - Experimental
> Stability: 1 - Experimental: Use [`module.setSourceMapsSupport()`][] instead.
* `val` {boolean}
@ -4016,6 +4016,9 @@ It provides same features as launching Node.js process with commandline options
Only source maps in JavaScript files that are loaded after source maps has been
enabled will be parsed and loaded.
This implies calling `module.setSourceMapsSupport()` with an option
`{ nodeModules: true, generatedCode: true }`.
## `process.setUncaughtExceptionCaptureCallback(fn)`
<!-- YAML
@ -4050,7 +4053,7 @@ added:
- v18.19.0
-->
> Stability: 1 - Experimental
> Stability: 1 - Experimental: Use [`module.getSourceMapsSupport()`][] instead.
* {boolean}
@ -4517,7 +4520,9 @@ cases:
[`console.error()`]: console.md#consoleerrordata-args
[`console.log()`]: console.md#consolelogdata-args
[`domain`]: domain.md
[`module.getSourceMapsSupport()`]: module.md#modulegetsourcemapssupport
[`module.isBuiltin(id)`]: module.md#moduleisbuiltinmodulename
[`module.setSourceMapsSupport()`]: module.md#modulesetsourcemapssupportenabled-options
[`net.Server`]: net.md#class-netserver
[`net.Socket`]: net.md#class-netsocket
[`os.constants.dlopen`]: os.md#dlopen-constants

View File

@ -368,8 +368,8 @@ internalBinding('process_methods').setEmitWarningSync(emitWarningSync);
{
const {
getSourceMapsEnabled,
setSourceMapsEnabled,
getSourceMapsSupport,
setSourceMapsSupport,
maybeCacheGeneratedSourceMap,
} = require('internal/source_map/source_map_cache');
const {
@ -381,10 +381,19 @@ internalBinding('process_methods').setEmitWarningSync(emitWarningSync);
enumerable: true,
configurable: true,
get() {
return getSourceMapsEnabled();
return getSourceMapsSupport().enabled;
},
});
process.setSourceMapsEnabled = setSourceMapsEnabled;
process.setSourceMapsEnabled = function setSourceMapsEnabled(val) {
setSourceMapsSupport(val, {
__proto__: null,
// TODO(legendecas): In order to smoothly improve the source map support,
// skip source maps in node_modules and generated code with
// `process.setSourceMapsEnabled(true)` in a semver major version.
nodeModules: val,
generatedCode: val,
});
};
// The C++ land calls back to maybeCacheGeneratedSourceMap()
// when code is generated by user with eval() or new Function()
// to cache the source maps from the evaluated code, if any.

View File

@ -30,7 +30,7 @@ const {
} = internalBinding('util');
const { decorateErrorStack, kEmptyObject } = require('internal/util');
const {
getSourceMapsEnabled,
getSourceMapsSupport,
} = require('internal/source_map/source_map_cache');
const assert = require('internal/assert');
const resolvedPromise = PromiseResolve();
@ -186,7 +186,7 @@ class ModuleJob extends ModuleJobBase {
// of missing named export. This is currently not possible because
// stack trace originates in module_job, not the file itself. A hidden
// symbol with filename could be set in node_errors.cc to facilitate this.
if (!getSourceMapsEnabled() &&
if (!getSourceMapsSupport().enabled &&
StringPrototypeIncludes(e.message,
' does not provide an export named')) {
const splitStack = StringPrototypeSplit(e.stack, '\n');

View File

@ -618,9 +618,17 @@ function initializeESMLoader(forceDefaultLoader) {
function initializeSourceMapsHandlers() {
const {
setSourceMapsEnabled,
setSourceMapsSupport,
} = require('internal/source_map/source_map_cache');
setSourceMapsEnabled(getOptionValue('--enable-source-maps'));
const enabled = getOptionValue('--enable-source-maps');
setSourceMapsSupport(enabled, {
__proto__: null,
// TODO(legendecas): In order to smoothly improve the source map support,
// skip source maps in node_modules and generated code with
// `--enable-source-maps` in a semver major version.
nodeModules: enabled,
generatedCode: enabled,
});
}
function initializeFrozenIntrinsics() {

View File

@ -3,6 +3,7 @@
const {
ArrayPrototypePush,
JSONParse,
ObjectFreeze,
RegExpPrototypeExec,
SafeMap,
StringPrototypeCodePointAt,
@ -15,7 +16,7 @@ let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => {
debug = fn;
});
const { validateBoolean } = require('internal/validators');
const { validateBoolean, validateObject } = require('internal/validators');
const {
setSourceMapsEnabled: setSourceMapsNative,
} = internalBinding('errors');
@ -23,7 +24,7 @@ const {
defaultPrepareStackTrace,
setInternalPrepareStackTrace,
} = require('internal/errors');
const { getLazy } = require('internal/util');
const { getLazy, isUnderNodeModules, kEmptyObject } = require('internal/util');
const getModuleSourceMapCache = getLazy(() => {
const { SourceMapCacheMap } = require('internal/source_map/source_map_cache_map');
@ -45,30 +46,48 @@ const { fileURLToPath, pathToFileURL, URL, URLParse } = require('internal/url');
let SourceMap;
// This is configured with --enable-source-maps during pre-execution.
let sourceMapsEnabled = false;
function getSourceMapsEnabled() {
return sourceMapsEnabled;
let sourceMapsSupport = ObjectFreeze({
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
function getSourceMapsSupport() {
// Return a read-only object.
return sourceMapsSupport;
}
/**
* Enables or disables source maps programmatically.
* @param {boolean} val
* @param {boolean} enabled
* @param {object} options
* @param {boolean} [options.nodeModules]
* @param {boolean} [options.generatedCode]
*/
function setSourceMapsEnabled(val) {
validateBoolean(val, 'val');
function setSourceMapsSupport(enabled, options = kEmptyObject) {
validateBoolean(enabled, 'enabled');
validateObject(options, 'options');
setSourceMapsNative(val);
if (val) {
const { nodeModules = false, generatedCode = false } = options;
validateBoolean(nodeModules, 'options.nodeModules');
validateBoolean(generatedCode, 'options.generatedCode');
setSourceMapsNative(enabled);
if (enabled) {
const {
prepareStackTraceWithSourceMaps,
} = require('internal/source_map/prepare_stack_trace');
setInternalPrepareStackTrace(prepareStackTraceWithSourceMaps);
} else if (sourceMapsEnabled !== undefined) {
// Reset prepare stack trace callback only when disabling source maps.
} else {
setInternalPrepareStackTrace(defaultPrepareStackTrace);
}
sourceMapsEnabled = val;
sourceMapsSupport = ObjectFreeze({
__proto__: null,
enabled,
nodeModules: nodeModules,
generatedCode: generatedCode,
});
}
/**
@ -130,14 +149,18 @@ function extractSourceMapURLMagicComment(content) {
* @param {string | undefined} sourceMapURL - the source map url
*/
function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSource, sourceURL, sourceMapURL) {
const sourceMapsEnabled = getSourceMapsEnabled();
if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return;
const support = getSourceMapsSupport();
if (!(process.env.NODE_V8_COVERAGE || support.enabled)) return;
const { normalizeReferrerURL } = require('internal/modules/helpers');
filename = normalizeReferrerURL(filename);
if (filename === undefined) {
// This is most likely an invalid filename in sourceURL of [eval]-wrapper.
return;
}
if (!support.nodeModules && isUnderNodeModules(filename)) {
// Skip file under node_modules if not enabled.
return;
}
if (sourceMapURL === undefined) {
sourceMapURL = extractSourceMapURLMagicComment(content);
@ -185,8 +208,8 @@ function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSourc
* @param {string} content - the eval'd source code
*/
function maybeCacheGeneratedSourceMap(content) {
const sourceMapsEnabled = getSourceMapsEnabled();
if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return;
const support = getSourceMapsSupport();
if (!(process.env.NODE_V8_COVERAGE || support.enabled || support.generated)) return;
const sourceURL = extractSourceURLMagicComment(content);
if (sourceURL === null) {
@ -352,6 +375,10 @@ function findSourceMap(sourceURL) {
return undefined;
}
if (!getSourceMapsSupport().nodeModules && isUnderNodeModules(sourceURL)) {
return undefined;
}
SourceMap ??= require('internal/source_map/source_map').SourceMap;
try {
if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) {
@ -377,8 +404,8 @@ function findSourceMap(sourceURL) {
module.exports = {
findSourceMap,
getSourceMapsEnabled,
setSourceMapsEnabled,
getSourceMapsSupport,
setSourceMapsSupport,
maybeCacheSourceMap,
maybeCacheGeneratedSourceMap,
sourceMapCacheToObject,

View File

@ -1,9 +1,15 @@
'use strict';
const { findSourceMap } = require('internal/source_map/source_map_cache');
const {
findSourceMap,
getSourceMapsSupport,
setSourceMapsSupport,
} = require('internal/source_map/source_map_cache');
const { Module } = require('internal/modules/cjs/loader');
const { register } = require('internal/modules/esm/loader');
const { SourceMap } = require('internal/source_map/source_map');
const {
SourceMap,
} = require('internal/source_map/source_map');
const {
constants,
enableCompileCache,
@ -15,9 +21,7 @@ const {
} = require('internal/modules/package_json_reader');
const { stripTypeScriptTypes } = require('internal/modules/typescript');
Module.findSourceMap = findSourceMap;
Module.register = register;
Module.SourceMap = SourceMap;
Module.constants = constants;
Module.enableCompileCache = enableCompileCache;
Module.findPackageJSON = findPackageJSON;
@ -25,4 +29,10 @@ Module.flushCompileCache = flushCompileCache;
Module.getCompileCacheDir = getCompileCacheDir;
Module.stripTypeScriptTypes = stripTypeScriptTypes;
// SourceMap APIs
Module.findSourceMap = findSourceMap;
Module.SourceMap = SourceMap;
Module.getSourceMapsSupport = getSourceMapsSupport;
Module.setSourceMapsSupport = setSourceMapsSupport;
module.exports = Module;

View File

@ -0,0 +1,3 @@
var functionA=function(){functionB()};function functionB(){functionC()}var functionC=function(){functionD()},functionD=function(){if(0<Math.random())throw Error("an error!");},thrower=functionA;try{functionA()}catch(a){throw a;};
//# sourceMappingURL=enclosing-call-site.js.map

View File

@ -0,0 +1,27 @@
const functionA = () => {
functionB()
}
function functionB() {
functionC()
}
const functionC = () => {
functionD()
}
const functionD = () => {
(function functionE () {
if (Math.random() > 0) {
throw new Error('an error!')
}
})()
}
const thrower = functionA
try {
thrower()
} catch (err) {
throw err
}

View File

@ -0,0 +1,8 @@
{
"version":3,
"file":"enclosing-call-site-min.js",
"lineCount":1,
"mappings":"AAAA,IAAMA,UAAYA,QAAA,EAAM,CACtBC,SAAA,EADsB,CAIxBA,SAASA,UAAS,EAAG,CACnBC,SAAA,EADmB,CAIrB,IAAMA,UAAYA,QAAA,EAAM,CACtBC,SAAA,EADsB,CAAxB,CAIMA,UAAYA,QAAA,EAAM,CAEpB,GAAoB,CAApB,CAAIC,IAAA,CAAKC,MAAL,EAAJ,CACE,KAAUC,MAAJ,CAAU,WAAV,CAAN,CAHkB,CAJxB,CAYMC,QAAUP,SAEhB,IAAI,CACFO,SAAA,EADE,CAEF,MAAOC,CAAP,CAAY,CACZ,KAAMA,EAAN,CADY;",
"sources":["enclosing-call-site.js"],
"names":["functionA","functionB","functionC","functionD","Math","random","Error","thrower","err"]
}

View File

@ -2,11 +2,23 @@
'use strict';
require('../../../common');
const assert = require('assert');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.strictEqual(process.sourceMapsEnabled, true);
process.setSourceMapsEnabled(false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: true,
generatedCode: true,
});
Module.setSourceMapsSupport(false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, false);
try {
@ -19,7 +31,13 @@ try {
// support enabled programmatically.
delete require.cache[require
.resolve('../enclosing-call-site-min.js')];
process.setSourceMapsEnabled(true);
Module.setSourceMapsSupport(true);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: false,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, true);
try {

View File

@ -0,0 +1,42 @@
// Flags: --enable-source-maps
'use strict';
require('../../../common');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.strictEqual(process.sourceMapsEnabled, true);
process.setSourceMapsEnabled(false);
assert.strictEqual(process.sourceMapsEnabled, false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
try {
require('../enclosing-call-site-min.js');
} catch (e) {
console.log(e);
}
// Delete the CJS module cache and loading the module again with source maps
// support enabled programmatically.
delete require.cache[require
.resolve('../enclosing-call-site-min.js')];
process.setSourceMapsEnabled(true);
assert.strictEqual(process.sourceMapsEnabled, true);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: true,
generatedCode: true,
});
try {
require('../enclosing-call-site-min.js');
} catch (e) {
console.log(e);
}

View File

@ -0,0 +1,12 @@
Error: an error!
at functionD (*enclosing-call-site-min.js:1:156)
at functionC (*enclosing-call-site-min.js:1:97)
at functionB (*enclosing-call-site-min.js:1:60)
at functionA (*enclosing-call-site-min.js:1:26)
at Object.<anonymous> (*enclosing-call-site-min.js:1:199)
Error: an error!
at functionD (*enclosing-call-site.js:16:17)
at functionC (*enclosing-call-site.js:10:3)
at functionB (*enclosing-call-site.js:6:3)
at functionA (*enclosing-call-site.js:2:3)
at Object.<anonymous> (*enclosing-call-site.js:24:3)

View File

@ -1,10 +1,22 @@
'use strict';
require('../../../common');
const assert = require('assert');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.strictEqual(process.sourceMapsEnabled, false);
process.setSourceMapsEnabled(true);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
Module.setSourceMapsSupport(true);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: false,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, true);
try {
@ -16,7 +28,13 @@ try {
delete require.cache[require
.resolve('../enclosing-call-site-min.js')];
process.setSourceMapsEnabled(false);
Module.setSourceMapsSupport(false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, false);
try {

View File

@ -0,0 +1,48 @@
'use strict';
require('../../../common');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
Module.setSourceMapsSupport(true, {
nodeModules: true,
});
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: true,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, true);
try {
require('../node_modules/error-stack/enclosing-call-site-min.js').simpleErrorStack();
} catch (e) {
console.log(e);
}
delete require.cache[require
.resolve('../node_modules/error-stack/enclosing-call-site-min.js')];
Module.setSourceMapsSupport(true, {
nodeModules: false,
});
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: false,
generatedCode: false,
});
assert.strictEqual(process.sourceMapsEnabled, true);
try {
require('../node_modules/error-stack/enclosing-call-site-min.js').simpleErrorStack();
} catch (e) {
console.log(e);
}

View File

@ -0,0 +1,12 @@
Error: an error!
at functionD (*node_modules*error-stack*enclosing-call-site.js:16:17)
at functionC (*node_modules*error-stack*enclosing-call-site.js:10:3)
at functionB (*node_modules*error-stack*enclosing-call-site.js:6:3)
at functionA (*node_modules*error-stack*enclosing-call-site.js:2:3)
at Object.<anonymous> (*node_modules*error-stack*enclosing-call-site.js:24:3)
Error: an error!
at functionD (*node_modules*error-stack*enclosing-call-site-min.js:1:156)
at functionC (*node_modules*error-stack*enclosing-call-site-min.js:1:97)
at functionB (*node_modules*error-stack*enclosing-call-site-min.js:1:60)
at functionA (*node_modules*error-stack*enclosing-call-site-min.js:1:26)
at Object.<anonymous> (*node_modules*error-stack*enclosing-call-site-min.js:1:199)

View File

@ -0,0 +1,39 @@
'use strict';
require('../../../common');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.strictEqual(process.sourceMapsEnabled, false);
process.setSourceMapsEnabled(true);
assert.strictEqual(process.sourceMapsEnabled, true);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: true,
nodeModules: true,
generatedCode: true,
});
try {
require('../enclosing-call-site-min.js');
} catch (e) {
console.log(e);
}
delete require.cache[require
.resolve('../enclosing-call-site-min.js')];
process.setSourceMapsEnabled(false);
assert.strictEqual(process.sourceMapsEnabled, false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
try {
require('../enclosing-call-site-min.js');
} catch (e) {
console.log(e);
}

View File

@ -0,0 +1,12 @@
Error: an error!
at functionD (*enclosing-call-site.js:16:17)
at functionC (*enclosing-call-site.js:10:3)
at functionB (*enclosing-call-site.js:6:3)
at functionA (*enclosing-call-site.js:2:3)
at Object.<anonymous> (*enclosing-call-site.js:24:3)
Error: an error!
at functionD (*enclosing-call-site-min.js:1:156)
at functionC (*enclosing-call-site-min.js:1:97)
at functionB (*enclosing-call-site-min.js:1:60)
at functionA (*enclosing-call-site-min.js:1:26)
at Object.<anonymous> (*enclosing-call-site-min.js:1:199)

View File

@ -2,7 +2,8 @@
'use strict';
require('../../../common');
const assert = require('assert');
const assert = require('node:assert');
const Module = require('node:module');
Error.stackTraceLimit = 5;
assert.strictEqual(typeof Error.prepareStackTrace, 'function');
@ -22,8 +23,13 @@ try {
// Source maps support is disabled programmatically even without deleting the
// CJS module cache.
process.setSourceMapsEnabled(false);
assert.strictEqual(process.sourceMapsEnabled, false);
Module.setSourceMapsSupport(false);
assert.deepStrictEqual(Module.getSourceMapsSupport(), {
__proto__: null,
enabled: false,
nodeModules: false,
generatedCode: false,
});
try {
require('../enclosing-call-site-min.js');

View File

@ -0,0 +1,43 @@
'use strict';
require('../common');
const assert = require('node:assert');
const Module = require('node:module');
// This test verifies that the `Module.setSourceMapsSupport` throws on invalid
// argument inputs.
{
const unexpectedValues = [
undefined,
null,
1,
{},
() => {},
];
for (const it of unexpectedValues) {
assert.throws(() => {
Module.setSourceMapsSupport(it);
}, /ERR_INVALID_ARG_TYPE/);
}
}
{
const unexpectedValues = [
null,
1,
{},
() => {},
];
for (const it of unexpectedValues) {
assert.throws(() => {
Module.setSourceMapsSupport(true, {
nodeModules: it,
});
}, /ERR_INVALID_ARG_TYPE/);
assert.throws(() => {
Module.setSourceMapsSupport(true, {
generatedCode: it,
});
}, /ERR_INVALID_ARG_TYPE/);
}
}

View File

@ -27,7 +27,10 @@ describe('sourcemaps output', { concurrency: !process.env.TEST_PARALLEL }, () =>
const tests = [
{ name: 'source-map/output/source_map_disabled_by_api.js' },
{ name: 'source-map/output/source_map_disabled_by_process_api.js' },
{ name: 'source-map/output/source_map_enabled_by_api.js' },
{ name: 'source-map/output/source_map_enabled_by_api_node_modules.js' },
{ name: 'source-map/output/source_map_enabled_by_process_api.js' },
{ name: 'source-map/output/source_map_enclosing_function.js' },
{ name: 'source-map/output/source_map_eval.js' },
{ name: 'source-map/output/source_map_no_source_file.js' },