Skip to content

Commit

Permalink
errors: support prepareSourceMap with source-maps
Browse files Browse the repository at this point in the history
Adds support for Error.prepareStackTrace override, when
--enable-source-maps is set.

PR-URL: #31143
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
bcoe committed Jan 2, 2020
1 parent 7babffb commit 9cdda60
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 12 deletions.
32 changes: 21 additions & 11 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const { kMaxLength } = internalBinding('buffer');
const MainContextError = Error;
const ErrorToString = Error.prototype.toString;
const overrideStackTrace = new WeakMap();
const kNoOverride = Symbol('kNoOverride');
const prepareStackTrace = (globalThis, error, trace) => {
// API for node internals to override error stack formatting
// without interfering with userland code.
Expand All @@ -52,6 +53,23 @@ const prepareStackTrace = (globalThis, error, trace) => {
return f(error, trace);
}

const globalOverride =
maybeOverridePrepareStackTrace(globalThis, error, trace);
if (globalOverride !== kNoOverride) return globalOverride;

// Normal error formatting:
//
// Error: Message
// at function (file)
// at file
const errorString = ErrorToString.call(error);
if (trace.length === 0) {
return errorString;
}
return `${errorString}\n at ${trace.join('\n at ')}`;
};

const maybeOverridePrepareStackTrace = (globalThis, error, trace) => {
// Polyfill of V8's Error.prepareStackTrace API.
// https://crbug.com/v8/7848
// `globalThis` is the global that contains the constructor which
Expand All @@ -66,19 +84,9 @@ const prepareStackTrace = (globalThis, error, trace) => {
return MainContextError.prepareStackTrace(error, trace);
}

// Normal error formatting:
//
// Error: Message
// at function (file)
// at file
const errorString = ErrorToString.call(error);
if (trace.length === 0) {
return errorString;
}
return `${errorString}\n at ${trace.join('\n at ')}`;
return kNoOverride;
};


let excludedStackFn;

// Lazily loaded
Expand Down Expand Up @@ -691,7 +699,9 @@ module.exports = {
SystemError,
// This is exported only to facilitate testing.
E,
kNoOverride,
prepareStackTrace,
maybeOverridePrepareStackTrace,
overrideStackTrace,
kEnhanceStackBeforeInspector,
fatalExceptionStackEnhancers
Expand Down
10 changes: 9 additions & 1 deletion lib/internal/source_map/prepare_stack_trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

const debug = require('internal/util/debuglog').debuglog('source_map');
const { findSourceMap } = require('internal/source_map/source_map_cache');
const { overrideStackTrace } = require('internal/errors');
const {
kNoOverride,
overrideStackTrace,
maybeOverridePrepareStackTrace
} = require('internal/errors');

// Create a prettified stacktrace, inserting context from source maps
// if possible.
Expand All @@ -17,6 +21,10 @@ const prepareStackTrace = (globalThis, error, trace) => {
return f(error, trace);
}

const globalOverride =
maybeOverridePrepareStackTrace(globalThis, error, trace);
if (globalOverride !== kNoOverride) return globalOverride;

const { SourceMap } = require('internal/source_map/source_map');
const errorString = ErrorToString.call(error);

Expand Down
19 changes: 19 additions & 0 deletions test/parallel/test-error-prepare-stack-trace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Flags: --enable-source-maps
'use strict';

require('../common');
const assert = require('assert');

// Error.prepareStackTrace() can be overridden with source maps enabled.
{
let prepareCalled = false;
Error.prepareStackTrace = (_error, trace) => {
prepareCalled = true;
};
try {
throw new Error('foo');
} catch (err) {
err.stack;
}
assert(prepareCalled);
}

0 comments on commit 9cdda60

Please sign in to comment.