Skip to content

Commit dcab307

Browse files
committed
lib: add api to enable source-maps programmatically
Add `process.setSourceMapsEnabled` to enable source-maps programmatically.
1 parent e4eadb2 commit dcab307

File tree

8 files changed

+144
-16
lines changed

8 files changed

+144
-16
lines changed

doc/api/process.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,22 @@ This function is only available on POSIX platforms (i.e. not Windows or
23792379
Android).
23802380
This feature is not available in [`Worker`][] threads.
23812381

2382+
## `process.setSourceMapsEnabled(val)`
2383+
<!-- YAML
2384+
added: REPLACEME
2385+
-->
2386+
2387+
* `val` {boolean}
2388+
2389+
This function enables or disables the [Source Map v3][Source Map] support for
2390+
stack traces.
2391+
2392+
It provides same features as launching Node.js process with commandline options
2393+
`--enable-source-maps`.
2394+
2395+
Only source maps in JavaScript files that are loaded after source maps has been
2396+
enabled will be parsed and loaded.
2397+
23822398
## `process.setUncaughtExceptionCaptureCallback(fn)`
23832399
<!-- YAML
23842400
added: v9.3.0
@@ -2763,6 +2779,7 @@ cases:
27632779
[LTS]: https://github.com/nodejs/Release
27642780
[Readable]: stream.md#stream_readable_streams
27652781
[Signal Events]: #process_signal_events
2782+
[Source Map]: https://sourcemaps.info/spec.html
27662783
[Stream compatibility]: stream.md#stream_compatibility_with_older_node_js_versions
27672784
[TTY]: tty.md#tty_tty
27682785
[Writable]: stream.md#stream_writable_streams

lib/internal/bootstrap/pre_execution.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
6565
// (including preload modules).
6666
initializeClusterIPC();
6767

68+
initializeSourceMapsHandlers();
6869
initializeDeprecations();
6970
initializeWASI();
7071
initializeCJSLoader();
@@ -448,6 +449,11 @@ function initializeESMLoader() {
448449
}
449450
}
450451

452+
function initializeSourceMapsHandlers() {
453+
const { setSourceMapsEnabled } = require('internal/source_map/source_map_cache');
454+
process.setSourceMapsEnabled = setSourceMapsEnabled;
455+
}
456+
451457
function initializeFrozenIntrinsics() {
452458
if (getOptionValue('--frozen-intrinsics')) {
453459
process.emitWarning('The --frozen-intrinsics flag is experimental',

lib/internal/source_map/source_map_cache.js

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,33 @@ let SourceMap;
4141
let sourceMapsEnabled;
4242
function getSourceMapsEnabled() {
4343
if (sourceMapsEnabled === undefined) {
44-
sourceMapsEnabled = getOptionValue('--enable-source-maps');
45-
if (sourceMapsEnabled) {
46-
const {
47-
enableSourceMaps,
48-
setPrepareStackTraceCallback
49-
} = internalBinding('errors');
50-
const {
51-
prepareStackTrace
52-
} = require('internal/source_map/prepare_stack_trace');
53-
setPrepareStackTraceCallback(prepareStackTrace);
54-
enableSourceMaps();
55-
}
44+
setSourceMapsEnabled(getOptionValue('--enable-source-maps'));
5645
}
5746
return sourceMapsEnabled;
5847
}
5948

49+
function setSourceMapsEnabled(val) {
50+
const {
51+
setSourceMapsEnabled,
52+
setPrepareStackTraceCallback
53+
} = internalBinding('errors');
54+
setSourceMapsEnabled(val);
55+
if (val) {
56+
const {
57+
prepareStackTrace
58+
} = require('internal/source_map/prepare_stack_trace');
59+
setPrepareStackTraceCallback(prepareStackTrace);
60+
} else if (sourceMapsEnabled !== undefined) {
61+
// Set prepare stack trace callback only when disabling source maps.
62+
const {
63+
prepareStackTrace,
64+
} = require('internal/errors');
65+
setPrepareStackTraceCallback(prepareStackTrace);
66+
}
67+
68+
sourceMapsEnabled = val;
69+
}
70+
6071
function maybeCacheSourceMap(filename, content, cjsModuleInstance) {
6172
const sourceMapsEnabled = getSourceMapsEnabled();
6273
if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return;
@@ -239,6 +250,7 @@ function findSourceMap(sourceURL) {
239250
module.exports = {
240251
findSourceMap,
241252
getSourceMapsEnabled,
253+
setSourceMapsEnabled,
242254
maybeCacheSourceMap,
243255
rekeySourceMap,
244256
sourceMapCacheToObject,

src/node_errors.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -820,9 +820,11 @@ void SetPrepareStackTraceCallback(const FunctionCallbackInfo<Value>& args) {
820820
env->set_prepare_stack_trace_callback(args[0].As<Function>());
821821
}
822822

823-
static void EnableSourceMaps(const FunctionCallbackInfo<Value>& args) {
823+
static void SetSourceMapsEnabled(const FunctionCallbackInfo<Value>& args) {
824824
Environment* env = Environment::GetCurrent(args);
825-
env->set_source_maps_enabled(true);
825+
CHECK(args[0]->IsBoolean());
826+
env->set_source_maps_enabled(
827+
args[0].As<Boolean>()->BooleanValue(env->isolate()));
826828
}
827829

828830
static void SetEnhanceStackForFatalException(
@@ -858,7 +860,7 @@ static void TriggerUncaughtException(const FunctionCallbackInfo<Value>& args) {
858860

859861
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
860862
registry->Register(SetPrepareStackTraceCallback);
861-
registry->Register(EnableSourceMaps);
863+
registry->Register(SetSourceMapsEnabled);
862864
registry->Register(SetEnhanceStackForFatalException);
863865
registry->Register(NoSideEffectsToString);
864866
registry->Register(TriggerUncaughtException);
@@ -871,7 +873,7 @@ void Initialize(Local<Object> target,
871873
Environment* env = Environment::GetCurrent(context);
872874
env->SetMethod(
873875
target, "setPrepareStackTraceCallback", SetPrepareStackTraceCallback);
874-
env->SetMethod(target, "enableSourceMaps", EnableSourceMaps);
876+
env->SetMethod(target, "setSourceMapsEnabled", SetSourceMapsEnabled);
875877
env->SetMethod(target,
876878
"setEnhanceStackForFatalException",
877879
SetEnhanceStackForFatalException);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Flags: --enable-source-maps
2+
3+
'use strict';
4+
require('../common');
5+
6+
process.setSourceMapsEnabled(false);
7+
8+
try {
9+
require('../fixtures/source-map/enclosing-call-site-min.js');
10+
} catch (e) {
11+
console.log(e);
12+
}
13+
14+
delete require.cache[require.resolve('../fixtures/source-map/enclosing-call-site-min.js')];
15+
16+
// Re-enable.
17+
process.setSourceMapsEnabled(true);
18+
19+
require('../fixtures/source-map/enclosing-call-site-min.js');
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Error: an error!
2+
at functionD (*enclosing-call-site-min.js:1:156)
3+
at functionC (*enclosing-call-site-min.js:1:97)
4+
at functionB (*enclosing-call-site-min.js:1:60)
5+
at functionA (*enclosing-call-site-min.js:1:26)
6+
at Object.<anonymous> (*enclosing-call-site-min.js:1:199)
7+
at Module._compile (node:internal/modules/cjs/loader:*)
8+
at Object.Module._extensions..js (node:internal/modules/cjs/loader:*)
9+
at Module.load (node:internal/modules/cjs/loader:*)
10+
at Function.Module._load (node:internal/modules/cjs/loader:*)
11+
at Module.require (node:internal/modules/cjs/loader:*)
12+
*enclosing-call-site.js:16
13+
throw new Error('an error!')
14+
^
15+
16+
Error: an error!
17+
at functionD (*enclosing-call-site.js:16:17)
18+
at functionC (*enclosing-call-site.js:10:3)
19+
at functionB (*enclosing-call-site.js:6:3)
20+
at functionA (*enclosing-call-site.js:2:3)
21+
at Object.<anonymous> (*enclosing-call-site.js:24:3)
22+
at Module._compile (node:internal/modules/cjs/loader:*)
23+
at Object.Module._extensions..js (node:internal/modules/cjs/loader:*)
24+
at Module.load (node:internal/modules/cjs/loader:*)
25+
at Function.Module._load (node:internal/modules/cjs/loader:*)
26+
at Module.require (node:internal/modules/cjs/loader:*)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
require('../common');
3+
4+
process.setSourceMapsEnabled(true);
5+
6+
try {
7+
require('../fixtures/source-map/enclosing-call-site-min.js');
8+
} catch (e) {
9+
console.log(e);
10+
}
11+
12+
delete require.cache[require.resolve('../fixtures/source-map/enclosing-call-site-min.js')];
13+
14+
process.setSourceMapsEnabled(false);
15+
16+
require('../fixtures/source-map/enclosing-call-site-min.js');
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
*enclosing-call-site.js:16
2+
throw new Error('an error!')
3+
^
4+
5+
Error: an error!
6+
at functionD (*enclosing-call-site.js:16:17)
7+
at functionC (*enclosing-call-site.js:10:3)
8+
at functionB (*enclosing-call-site.js:6:3)
9+
at functionA (*enclosing-call-site.js:2:3)
10+
at Object.<anonymous> (*enclosing-call-site.js:24:3)
11+
at Module._compile (node:internal/modules/cjs/loader:*)
12+
at Object.Module._extensions..js (node:internal/modules/cjs/loader:*)
13+
at Module.load (node:internal/modules/cjs/loader:*)
14+
at Function.Module._load (node:internal/modules/cjs/loader:*)
15+
at Module.require (node:internal/modules/cjs/loader:*)
16+
*enclosing-call-site-min.js:1
17+
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;};
18+
^
19+
20+
Error: an error!
21+
at functionD (*enclosing-call-site-min.js:1:156)
22+
at functionC (*enclosing-call-site-min.js:1:97)
23+
at functionB (*enclosing-call-site-min.js:1:60)
24+
at functionA (*enclosing-call-site-min.js:1:26)
25+
at Object.<anonymous> (*enclosing-call-site-min.js:1:199)
26+
at Module._compile (node:internal/modules/cjs/loader:*)
27+
at Object.Module._extensions..js (node:internal/modules/cjs/loader:*)
28+
at Module.load (node:internal/modules/cjs/loader:*)
29+
at Function.Module._load (node:internal/modules/cjs/loader:*)
30+
at Module.require (node:internal/modules/cjs/loader:*)

0 commit comments

Comments
 (0)