From fb1a57eca24ce3831198fcb8c6411a2803a9250e Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Wed, 4 Dec 2024 14:30:32 +0000 Subject: [PATCH] lib: skip source maps in node_modules Skipping source maps in `node_modules` by default improves the general performance. Add `module.setSourceMapsSupport(enabled, options)` to enable source maps in `node_modules` if it is needed. Files in `node_modules` are not authored by the user directly and the original sources are less relevant to the user. --- benchmark/es/error-stack.js | 13 ++-- .../error-stack/simple-error-stack.js | 16 +++++ .../error-stack/simple-error-stack.ts | 19 ++++++ doc/api/module.md | 38 +++++++++++ doc/api/process.md | 14 +++- lib/internal/bootstrap/node.js | 10 +-- lib/internal/modules/esm/module_job.js | 4 +- lib/internal/process/pre_execution.js | 4 +- lib/internal/source_map/source_map_cache.js | 65 +++++++++++++------ lib/module.js | 18 +++-- .../error-stack/enclosing-call-site-min.js | 3 + .../error-stack/enclosing-call-site.js | 27 ++++++++ .../error-stack/enclosing-call-site.js.map | 8 +++ .../output/source_map_disabled_by_api.js | 26 ++++++-- .../source_map_disabled_by_process_api.js | 42 ++++++++++++ ...ource_map_disabled_by_process_api.snapshot | 12 ++++ .../output/source_map_enabled_by_api.js | 26 ++++++-- .../source_map_enabled_by_api_node_modules.js | 48 ++++++++++++++ ...e_map_enabled_by_api_node_modules.snapshot | 12 ++++ .../source_map_enabled_by_process_api.js | 39 +++++++++++ ...source_map_enabled_by_process_api.snapshot | 12 ++++ .../output/source_map_prepare_stack_trace.js | 12 +++- .../test-module-setsourcemapssupport.js | 27 ++++++++ test/parallel/test-node-output-sourcemaps.mjs | 3 + 24 files changed, 450 insertions(+), 48 deletions(-) create mode 100644 benchmark/fixtures/node_modules/error-stack/simple-error-stack.js create mode 100644 benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts create mode 100644 test/fixtures/source-map/node_modules/error-stack/enclosing-call-site-min.js create mode 100644 test/fixtures/source-map/node_modules/error-stack/enclosing-call-site.js create mode 100644 test/fixtures/source-map/node_modules/error-stack/enclosing-call-site.js.map create mode 100644 test/fixtures/source-map/output/source_map_disabled_by_process_api.js create mode 100644 test/fixtures/source-map/output/source_map_disabled_by_process_api.snapshot create mode 100644 test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.js create mode 100644 test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.snapshot create mode 100644 test/fixtures/source-map/output/source_map_enabled_by_process_api.js create mode 100644 test/fixtures/source-map/output/source_map_enabled_by_process_api.snapshot create mode 100644 test/parallel/test-module-setsourcemapssupport.js diff --git a/benchmark/es/error-stack.js b/benchmark/es/error-stack.js index 907f308ea41558..9b574f11416ea8 100644 --- a/benchmark/es/error-stack.js +++ b/benchmark/es/error-stack.js @@ -2,13 +2,14 @@ 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 bench = common.createBenchmark(main, { - method: ['without-sourcemap', 'sourcemap'], + method: ['without-sourcemap', 'sourcemap', 'node-module-sourcemap', 'node-module'], n: [1e5], }); -function runN(n) { +function runN(n, modPath) { delete require.cache[modPath]; const mod = require(modPath); bench.start(); @@ -22,11 +23,15 @@ 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 'sourcemap-with-node-modules': + process.setSourceMapsEnabled(true); + runN(n, nodeModulePath); break; default: throw new Error(`Unexpected method "${method}"`); diff --git a/benchmark/fixtures/node_modules/error-stack/simple-error-stack.js b/benchmark/fixtures/node_modules/error-stack/simple-error-stack.js new file mode 100644 index 00000000000000..33c3ad7f324d40 --- /dev/null +++ b/benchmark/fixtures/node_modules/error-stack/simple-error-stack.js @@ -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= diff --git a/benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts b/benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts new file mode 100644 index 00000000000000..58d3d7eedd2f1b --- /dev/null +++ b/benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts @@ -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, +}; diff --git a/doc/api/module.md b/doc/api/module.md index 6f399fb07a44ee..2cc6c786ab1c34 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -1587,6 +1587,43 @@ import { findSourceMap, SourceMap } from 'node:module'; const { findSourceMap, SourceMap } = require('node:module'); ``` +### `module.setSourceMapsSupport(enabled[, options])` + + + +* `enabled` {boolean} Enable the source map support. +* `options` {Object} Optional + * `nodeModules` {boolean} If enabling the support for files in `node_modules`. + * `generatedCode` {boolean} If enabling the support for generated code from `eval` or `new Function`. + +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. + +### `module.getSourceMapsSupport()` + + + +* 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. + @@ -1705,6 +1742,7 @@ returned object contains the following keys: [Conditional exports]: packages.md#conditional-exports [Customization hooks]: #customization-hooks [ES Modules]: esm.md +[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 diff --git a/doc/api/process.md b/doc/api/process.md index 95b35897f9d568..b42b7d0f0f7c72 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -3995,9 +3995,13 @@ This feature is not available in [`Worker`][] threads. added: - v16.6.0 - v14.18.0 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/56639 + description: the `process.setSourceMapsEnabled` has been deprecated. --> -> Stability: 1 - Experimental +> Stability: 0 - Deprecated: Use [`module.setSourceMapsSupport()`][] instead. * `val` {boolean} @@ -4042,9 +4046,13 @@ Using this function is mutually exclusive with using the deprecated added: - v20.7.0 - v18.19.0 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/56639 + description: the `process.sourceMapsEnabled` has been deprecated. --> -> Stability: 1 - Experimental +> Stability: 0 - Deprecated: Use [`module.getSourceMapsSupport()`][] instead. * {boolean} @@ -4511,7 +4519,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 diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index de2f0e00e14092..4011ce2ad972e1 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -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,12 @@ 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); + }; // 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. diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 8039e2f57a500f..846a336d27547e 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -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'); diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index 3ea9a934726462..50096af241a2bc 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -618,9 +618,9 @@ function initializeESMLoader(forceDefaultLoader) { function initializeSourceMapsHandlers() { const { - setSourceMapsEnabled, + setSourceMapsSupport, } = require('internal/source_map/source_map_cache'); - setSourceMapsEnabled(getOptionValue('--enable-source-maps')); + setSourceMapsSupport(getOptionValue('--enable-source-maps')); } function initializeFrozenIntrinsics() { diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index aaca27136e66a0..bdef338e3dd086 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -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'); + + const { nodeModules = false, generatedCode = false } = options; + validateBoolean(nodeModules, 'options.nodeModules'); + validateBoolean(generatedCode, 'options.generatedCode'); - setSourceMapsNative(val); - if (val) { + 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, diff --git a/lib/module.js b/lib/module.js index a0317d06e0edb0..1217172afb3ccb 100644 --- a/lib/module.js +++ b/lib/module.js @@ -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; diff --git a/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site-min.js b/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site-min.js new file mode 100644 index 00000000000000..45b7ed2b219b86 --- /dev/null +++ b/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site-min.js @@ -0,0 +1,3 @@ +var functionA=function(){functionB()};function functionB(){functionC()}var functionC=function(){functionD()},functionD=function(){if(0 { + 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 +} diff --git a/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site.js.map b/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site.js.map new file mode 100644 index 00000000000000..d0c785f26091cc --- /dev/null +++ b/test/fixtures/source-map/node_modules/error-stack/enclosing-call-site.js.map @@ -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"] +} diff --git a/test/fixtures/source-map/output/source_map_disabled_by_api.js b/test/fixtures/source-map/output/source_map_disabled_by_api.js index 8f455f26b6c9c4..88d92a20df87d6 100644 --- a/test/fixtures/source-map/output/source_map_disabled_by_api.js +++ b/test/fixtures/source-map/output/source_map_disabled_by_api.js @@ -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: false, + generatedCode: false, +}); +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 { diff --git a/test/fixtures/source-map/output/source_map_disabled_by_process_api.js b/test/fixtures/source-map/output/source_map_disabled_by_process_api.js new file mode 100644 index 00000000000000..defe3b4246feae --- /dev/null +++ b/test/fixtures/source-map/output/source_map_disabled_by_process_api.js @@ -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: false, + generatedCode: false, +}); + +try { + require('../enclosing-call-site-min.js'); +} catch (e) { + console.log(e); +} diff --git a/test/fixtures/source-map/output/source_map_disabled_by_process_api.snapshot b/test/fixtures/source-map/output/source_map_disabled_by_process_api.snapshot new file mode 100644 index 00000000000000..655cd6695e1116 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_disabled_by_process_api.snapshot @@ -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. (*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. (*enclosing-call-site.js:24:3) diff --git a/test/fixtures/source-map/output/source_map_enabled_by_api.js b/test/fixtures/source-map/output/source_map_enabled_by_api.js index 1dd4f9530c68db..e09e05b59339f4 100644 --- a/test/fixtures/source-map/output/source_map_enabled_by_api.js +++ b/test/fixtures/source-map/output/source_map_enabled_by_api.js @@ -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 { diff --git a/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.js b/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.js new file mode 100644 index 00000000000000..5de2f3b0d7eb85 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.js @@ -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); +} \ No newline at end of file diff --git a/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.snapshot b/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.snapshot new file mode 100644 index 00000000000000..f46c21dbe42057 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enabled_by_api_node_modules.snapshot @@ -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. (*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. (*node_modules*error-stack*enclosing-call-site-min.js:1:199) diff --git a/test/fixtures/source-map/output/source_map_enabled_by_process_api.js b/test/fixtures/source-map/output/source_map_enabled_by_process_api.js new file mode 100644 index 00000000000000..f8285790bae488 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enabled_by_process_api.js @@ -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: false, + generatedCode: false, +}); + +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); +} diff --git a/test/fixtures/source-map/output/source_map_enabled_by_process_api.snapshot b/test/fixtures/source-map/output/source_map_enabled_by_process_api.snapshot new file mode 100644 index 00000000000000..082b3f310ed4f9 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enabled_by_process_api.snapshot @@ -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. (*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. (*enclosing-call-site-min.js:1:199) diff --git a/test/fixtures/source-map/output/source_map_prepare_stack_trace.js b/test/fixtures/source-map/output/source_map_prepare_stack_trace.js index 1b04e0a3ac221b..894aea60a96f18 100644 --- a/test/fixtures/source-map/output/source_map_prepare_stack_trace.js +++ b/test/fixtures/source-map/output/source_map_prepare_stack_trace.js @@ -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'); diff --git a/test/parallel/test-module-setsourcemapssupport.js b/test/parallel/test-module-setsourcemapssupport.js new file mode 100644 index 00000000000000..4decf58aaf9006 --- /dev/null +++ b/test/parallel/test-module-setsourcemapssupport.js @@ -0,0 +1,27 @@ +'use strict'; +require('../common'); +const assert = require('node:assert'); +const Module = require('node:module'); + +const unexpectedValues = [ + undefined, + null, + 1, + {}, + () => {}, +]; +for (const it of unexpectedValues) { + assert.throws(() => { + Module.setSourceMapsSupport(it); + }, /ERR_INVALID_ARG_TYPE/); + assert.throws(() => { + Module.setSourceMapsSupport(true, { + nodeModules: it, + }); + }, /ERR_INVALID_ARG_TYPE/); + assert.throws(() => { + Module.setSourceMapsSupport(true, { + generatedCode: it, + }); + }, /ERR_INVALID_ARG_TYPE/); +} diff --git a/test/parallel/test-node-output-sourcemaps.mjs b/test/parallel/test-node-output-sourcemaps.mjs index e9104db220867f..29cc5eb711f176 100644 --- a/test/parallel/test-node-output-sourcemaps.mjs +++ b/test/parallel/test-node-output-sourcemaps.mjs @@ -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' },