Skip to content

Commit fb1a57e

Browse files
committed
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.
1 parent 0e7ec5e commit fb1a57e

24 files changed

+450
-48
lines changed

benchmark/es/error-stack.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
const common = require('../common.js');
44
const modPath = require.resolve('../fixtures/simple-error-stack.js');
5+
const nodeModulePath = require.resolve('../fixtures/node_modules/error-stack/simple-error-stack.js');
56

67
const bench = common.createBenchmark(main, {
7-
method: ['without-sourcemap', 'sourcemap'],
8+
method: ['without-sourcemap', 'sourcemap', 'node-module-sourcemap', 'node-module'],
89
n: [1e5],
910
});
1011

11-
function runN(n) {
12+
function runN(n, modPath) {
1213
delete require.cache[modPath];
1314
const mod = require(modPath);
1415
bench.start();
@@ -22,11 +23,15 @@ function main({ n, method }) {
2223
switch (method) {
2324
case 'without-sourcemap':
2425
process.setSourceMapsEnabled(false);
25-
runN(n);
26+
runN(n, modPath);
2627
break;
2728
case 'sourcemap':
2829
process.setSourceMapsEnabled(true);
29-
runN(n);
30+
runN(n, modPath);
31+
break;
32+
case 'sourcemap-with-node-modules':
33+
process.setSourceMapsEnabled(true);
34+
runN(n, nodeModulePath);
3035
break;
3136
default:
3237
throw new Error(`Unexpected method "${method}"`);

benchmark/fixtures/node_modules/error-stack/simple-error-stack.js

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/fixtures/node_modules/error-stack/simple-error-stack.ts

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/api/module.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,43 @@ import { findSourceMap, SourceMap } from 'node:module';
15871587
const { findSourceMap, SourceMap } = require('node:module');
15881588
```
15891589
1590+
### `module.setSourceMapsSupport(enabled[, options])`
1591+
1592+
<!-- YAML
1593+
added: REPLACEME
1594+
-->
1595+
1596+
* `enabled` {boolean} Enable the source map support.
1597+
* `options` {Object} Optional
1598+
* `nodeModules` {boolean} If enabling the support for files in `node_modules`.
1599+
* `generatedCode` {boolean} If enabling the support for generated code from `eval` or `new Function`.
1600+
1601+
This function enables or disables the [Source Map v3][Source Map] support for
1602+
stack traces.
1603+
1604+
It provides same features as launching Node.js process with commandline options
1605+
`--enable-source-maps`, with additional options to alter the support for files
1606+
in `node_modules` or generated codes.
1607+
1608+
Only source maps in JavaScript files that are loaded after source maps has been
1609+
enabled will be parsed and loaded. Preferably, use the commandline options
1610+
`--enable-source-maps` to avoid losing track of source maps of modules loaded
1611+
before this API call.
1612+
1613+
### `module.getSourceMapsSupport()`
1614+
1615+
<!-- YAML
1616+
added: REPLACEME
1617+
-->
1618+
1619+
* Returns: {Object}
1620+
* `enabled` {boolean} If the source maps support is enabled
1621+
* `nodeModules` {boolean} If the support is enabled for files in `node_modules`.
1622+
* `generatedCode` {boolean} If the support is enabled for generated code from `eval` or `new Function`.
1623+
1624+
This method returns whether the [Source Map v3][Source Map] support for stack
1625+
traces is enabled.
1626+
15901627
<!-- Anchors to make sure old links find a target -->
15911628
15921629
<a id="module_module_findsourcemap_path_error"></a>
@@ -1705,6 +1742,7 @@ returned object contains the following keys:
17051742
[Conditional exports]: packages.md#conditional-exports
17061743
[Customization hooks]: #customization-hooks
17071744
[ES Modules]: esm.md
1745+
[Source Map]: https://sourcemaps.info/spec.html
17081746
[Source map v3 format]: https://sourcemaps.info/spec.html#h.mofvlxcwqzej
17091747
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
17101748
[V8 code cache]: https://v8.dev/blog/code-caching-for-devs

doc/api/process.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,9 +3995,13 @@ This feature is not available in [`Worker`][] threads.
39953995
added:
39963996
- v16.6.0
39973997
- v14.18.0
3998+
changes:
3999+
- version: REPLACEME
4000+
pr-url: https://github.com/nodejs/node/pull/56639
4001+
description: the `process.setSourceMapsEnabled` has been deprecated.
39984002
-->
39994003
4000-
> Stability: 1 - Experimental
4004+
> Stability: 0 - Deprecated: Use [`module.setSourceMapsSupport()`][] instead.
40014005
40024006
* `val` {boolean}
40034007
@@ -4042,9 +4046,13 @@ Using this function is mutually exclusive with using the deprecated
40424046
added:
40434047
- v20.7.0
40444048
- v18.19.0
4049+
changes:
4050+
- version: REPLACEME
4051+
pr-url: https://github.com/nodejs/node/pull/56639
4052+
description: the `process.sourceMapsEnabled` has been deprecated.
40454053
-->
40464054
4047-
> Stability: 1 - Experimental
4055+
> Stability: 0 - Deprecated: Use [`module.getSourceMapsSupport()`][] instead.
40484056
40494057
* {boolean}
40504058
@@ -4511,7 +4519,9 @@ cases:
45114519
[`console.error()`]: console.md#consoleerrordata-args
45124520
[`console.log()`]: console.md#consolelogdata-args
45134521
[`domain`]: domain.md
4522+
[`module.getSourceMapsSupport()`]: module.md#modulegetsourcemapssupport
45144523
[`module.isBuiltin(id)`]: module.md#moduleisbuiltinmodulename
4524+
[`module.setSourceMapsSupport()`]: module.md#modulesetsourcemapssupportenabled-options
45154525
[`net.Server`]: net.md#class-netserver
45164526
[`net.Socket`]: net.md#class-netsocket
45174527
[`os.constants.dlopen`]: os.md#dlopen-constants

lib/internal/bootstrap/node.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,8 @@ internalBinding('process_methods').setEmitWarningSync(emitWarningSync);
368368

369369
{
370370
const {
371-
getSourceMapsEnabled,
372-
setSourceMapsEnabled,
371+
getSourceMapsSupport,
372+
setSourceMapsSupport,
373373
maybeCacheGeneratedSourceMap,
374374
} = require('internal/source_map/source_map_cache');
375375
const {
@@ -381,10 +381,12 @@ internalBinding('process_methods').setEmitWarningSync(emitWarningSync);
381381
enumerable: true,
382382
configurable: true,
383383
get() {
384-
return getSourceMapsEnabled();
384+
return getSourceMapsSupport().enabled;
385385
},
386386
});
387-
process.setSourceMapsEnabled = setSourceMapsEnabled;
387+
process.setSourceMapsEnabled = function setSourceMapsEnabled(val) {
388+
setSourceMapsSupport(val);
389+
};
388390
// The C++ land calls back to maybeCacheGeneratedSourceMap()
389391
// when code is generated by user with eval() or new Function()
390392
// to cache the source maps from the evaluated code, if any.

lib/internal/modules/esm/module_job.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const {
3030
} = internalBinding('util');
3131
const { decorateErrorStack, kEmptyObject } = require('internal/util');
3232
const {
33-
getSourceMapsEnabled,
33+
getSourceMapsSupport,
3434
} = require('internal/source_map/source_map_cache');
3535
const assert = require('internal/assert');
3636
const resolvedPromise = PromiseResolve();
@@ -186,7 +186,7 @@ class ModuleJob extends ModuleJobBase {
186186
// of missing named export. This is currently not possible because
187187
// stack trace originates in module_job, not the file itself. A hidden
188188
// symbol with filename could be set in node_errors.cc to facilitate this.
189-
if (!getSourceMapsEnabled() &&
189+
if (!getSourceMapsSupport().enabled &&
190190
StringPrototypeIncludes(e.message,
191191
' does not provide an export named')) {
192192
const splitStack = StringPrototypeSplit(e.stack, '\n');

lib/internal/process/pre_execution.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,9 +618,9 @@ function initializeESMLoader(forceDefaultLoader) {
618618

619619
function initializeSourceMapsHandlers() {
620620
const {
621-
setSourceMapsEnabled,
621+
setSourceMapsSupport,
622622
} = require('internal/source_map/source_map_cache');
623-
setSourceMapsEnabled(getOptionValue('--enable-source-maps'));
623+
setSourceMapsSupport(getOptionValue('--enable-source-maps'));
624624
}
625625

626626
function initializeFrozenIntrinsics() {

lib/internal/source_map/source_map_cache.js

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
ArrayPrototypePush,
55
JSONParse,
6+
ObjectFreeze,
67
RegExpPrototypeExec,
78
SafeMap,
89
StringPrototypeCodePointAt,
@@ -15,15 +16,15 @@ let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => {
1516
debug = fn;
1617
});
1718

18-
const { validateBoolean } = require('internal/validators');
19+
const { validateBoolean, validateObject } = require('internal/validators');
1920
const {
2021
setSourceMapsEnabled: setSourceMapsNative,
2122
} = internalBinding('errors');
2223
const {
2324
defaultPrepareStackTrace,
2425
setInternalPrepareStackTrace,
2526
} = require('internal/errors');
26-
const { getLazy } = require('internal/util');
27+
const { getLazy, isUnderNodeModules, kEmptyObject } = require('internal/util');
2728

2829
const getModuleSourceMapCache = getLazy(() => {
2930
const { SourceMapCacheMap } = require('internal/source_map/source_map_cache_map');
@@ -45,30 +46,48 @@ const { fileURLToPath, pathToFileURL, URL, URLParse } = require('internal/url');
4546
let SourceMap;
4647

4748
// This is configured with --enable-source-maps during pre-execution.
48-
let sourceMapsEnabled = false;
49-
function getSourceMapsEnabled() {
50-
return sourceMapsEnabled;
49+
let sourceMapsSupport = ObjectFreeze({
50+
__proto__: null,
51+
enabled: false,
52+
nodeModules: false,
53+
generatedCode: false,
54+
});
55+
function getSourceMapsSupport() {
56+
// Return a read-only object.
57+
return sourceMapsSupport;
5158
}
5259

5360
/**
5461
* Enables or disables source maps programmatically.
55-
* @param {boolean} val
62+
* @param {boolean} enabled
63+
* @param {object} options
64+
* @param {boolean} [options.nodeModules]
65+
* @param {boolean} [options.generatedCode]
5666
*/
57-
function setSourceMapsEnabled(val) {
58-
validateBoolean(val, 'val');
67+
function setSourceMapsSupport(enabled, options = kEmptyObject) {
68+
validateBoolean(enabled, 'enabled');
69+
validateObject(options, 'options');
70+
71+
const { nodeModules = false, generatedCode = false } = options;
72+
validateBoolean(nodeModules, 'options.nodeModules');
73+
validateBoolean(generatedCode, 'options.generatedCode');
5974

60-
setSourceMapsNative(val);
61-
if (val) {
75+
setSourceMapsNative(enabled);
76+
if (enabled) {
6277
const {
6378
prepareStackTraceWithSourceMaps,
6479
} = require('internal/source_map/prepare_stack_trace');
6580
setInternalPrepareStackTrace(prepareStackTraceWithSourceMaps);
66-
} else if (sourceMapsEnabled !== undefined) {
67-
// Reset prepare stack trace callback only when disabling source maps.
81+
} else {
6882
setInternalPrepareStackTrace(defaultPrepareStackTrace);
6983
}
7084

71-
sourceMapsEnabled = val;
85+
sourceMapsSupport = ObjectFreeze({
86+
__proto__: null,
87+
enabled,
88+
nodeModules: nodeModules,
89+
generatedCode: generatedCode,
90+
});
7291
}
7392

7493
/**
@@ -130,14 +149,18 @@ function extractSourceMapURLMagicComment(content) {
130149
* @param {string | undefined} sourceMapURL - the source map url
131150
*/
132151
function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSource, sourceURL, sourceMapURL) {
133-
const sourceMapsEnabled = getSourceMapsEnabled();
134-
if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return;
152+
const support = getSourceMapsSupport();
153+
if (!(process.env.NODE_V8_COVERAGE || support.enabled)) return;
135154
const { normalizeReferrerURL } = require('internal/modules/helpers');
136155
filename = normalizeReferrerURL(filename);
137156
if (filename === undefined) {
138157
// This is most likely an invalid filename in sourceURL of [eval]-wrapper.
139158
return;
140159
}
160+
if (!support.nodeModules && isUnderNodeModules(filename)) {
161+
// Skip file under node_modules if not enabled.
162+
return;
163+
}
141164

142165
if (sourceMapURL === undefined) {
143166
sourceMapURL = extractSourceMapURLMagicComment(content);
@@ -185,8 +208,8 @@ function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSourc
185208
* @param {string} content - the eval'd source code
186209
*/
187210
function maybeCacheGeneratedSourceMap(content) {
188-
const sourceMapsEnabled = getSourceMapsEnabled();
189-
if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return;
211+
const support = getSourceMapsSupport();
212+
if (!(process.env.NODE_V8_COVERAGE || support.enabled || support.generated)) return;
190213

191214
const sourceURL = extractSourceURLMagicComment(content);
192215
if (sourceURL === null) {
@@ -352,6 +375,10 @@ function findSourceMap(sourceURL) {
352375
return undefined;
353376
}
354377

378+
if (!getSourceMapsSupport().nodeModules && isUnderNodeModules(sourceURL)) {
379+
return undefined;
380+
}
381+
355382
SourceMap ??= require('internal/source_map/source_map').SourceMap;
356383
try {
357384
if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) {
@@ -377,8 +404,8 @@ function findSourceMap(sourceURL) {
377404

378405
module.exports = {
379406
findSourceMap,
380-
getSourceMapsEnabled,
381-
setSourceMapsEnabled,
407+
getSourceMapsSupport,
408+
setSourceMapsSupport,
382409
maybeCacheSourceMap,
383410
maybeCacheGeneratedSourceMap,
384411
sourceMapCacheToObject,

lib/module.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
'use strict';
22

3-
const { findSourceMap } = require('internal/source_map/source_map_cache');
3+
const {
4+
findSourceMap,
5+
getSourceMapsSupport,
6+
setSourceMapsSupport,
7+
} = require('internal/source_map/source_map_cache');
48
const { Module } = require('internal/modules/cjs/loader');
59
const { register } = require('internal/modules/esm/loader');
6-
const { SourceMap } = require('internal/source_map/source_map');
10+
const {
11+
SourceMap,
12+
} = require('internal/source_map/source_map');
713
const {
814
constants,
915
enableCompileCache,
@@ -15,14 +21,18 @@ const {
1521
} = require('internal/modules/package_json_reader');
1622
const { stripTypeScriptTypes } = require('internal/modules/typescript');
1723

18-
Module.findSourceMap = findSourceMap;
1924
Module.register = register;
20-
Module.SourceMap = SourceMap;
2125
Module.constants = constants;
2226
Module.enableCompileCache = enableCompileCache;
2327
Module.findPackageJSON = findPackageJSON;
2428
Module.flushCompileCache = flushCompileCache;
2529
Module.getCompileCacheDir = getCompileCacheDir;
2630
Module.stripTypeScriptTypes = stripTypeScriptTypes;
2731

32+
// SourceMap APIs
33+
Module.findSourceMap = findSourceMap;
34+
Module.SourceMap = SourceMap;
35+
Module.getSourceMapsSupport = getSourceMapsSupport;
36+
Module.setSourceMapsSupport = setSourceMapsSupport;
37+
2838
module.exports = Module;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy