Socket
Socket
Sign inDemoInstall

@cspotcode/source-map-support

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cspotcode/source-map-support - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0

register-hook-require.d.ts

8

package.json
{
"name": "@cspotcode/source-map-support",
"description": "Fixes stack traces for files with source maps",
"version": "0.6.1",
"version": "0.7.0",
"main": "./source-map-support.js",

@@ -15,2 +15,4 @@ "types": "./source-map-support.d.ts",

"/register.js",
"/register-hook-require.d.ts",
"/register-hook-require.js",
"/source-map-support.d.ts",

@@ -40,3 +42,7 @@ "/source-map-support.js"

"node": ">=12"
},
"volta": {
"node": "16.11.0",
"npm": "7.24.2"
}
}

@@ -33,2 +33,4 @@ # Source Map Support

node -r @cspotcode/source-map-support/register compiled.js
# Or to enable hookRequire
node -r @cspotcode/source-map-support/register-hook-require compiled.js
```

@@ -35,0 +37,0 @@

4

register.d.ts
// tslint:disable:no-useless-files
// For following usage:
// import 'source-map-support/register'
// import '@cspotcode/source-map-support/register'
// Instead of:
// import sourceMapSupport from 'source-map-support'
// import sourceMapSupport from '@cspotcode/source-map-support'
// sourceMapSupport.install()

@@ -34,2 +34,13 @@ // Type definitions for source-map-support 0.5

retrieveSourceMap?(source: string): UrlAndMap | null;
/**
* Set false to disable redirection of require / import `source-map-support` to `@cspotcode/source-map-support`
*/
redirectConflictingLibrary?: boolean;
/**
* Callback will be called every time we redirect due to `redirectConflictingLibrary`
* This allows consumers to log helpful warnings if they choose.
* @param parent NodeJS.Module which made the require() or require.resolve() call
* @param options options object internally passed to node's `_resolveFilename` hook
*/
onConflictingLibraryRedirect?: (request: string, parent: any, isMain: boolean, options: any, redirectedRequest: string) => void;
}

@@ -54,1 +65,6 @@

export function install(options?: Options): void;
/**
* Uninstall SourceMap support.
*/
export function uninstall(): void;

@@ -26,25 +26,93 @@ var SourceMapConsumer = require('@cspotcode/source-map-consumer').SourceMapConsumer;

// Only install once if called multiple times
var errorFormatterInstalled = false;
var uncaughtShimInstalled = false;
/**
* @typedef {{
* enabled: boolean;
* originalValue: any;
* installedValue: any;
* }} HookState
* Used for installing and uninstalling hooks
*/
// If true, the caches are reset before a stack trace formatting operation
var emptyCacheBetweenOperations = false;
// Increment this if the format of sharedData changes in a breaking way.
var sharedDataVersion = 1;
/**
* @template T
* @param {T} defaults
* @returns {T}
*/
function initializeSharedData(defaults) {
var sharedDataKey = 'source-map-support/sharedData';
if (typeof Symbol !== 'undefined') {
sharedDataKey = Symbol.for(sharedDataKey);
}
var sharedData = this[sharedDataKey];
if (!sharedData) {
sharedData = { version: sharedDataVersion };
if (Object.defineProperty) {
Object.defineProperty(this, sharedDataKey, { value: sharedData });
} else {
this[sharedDataKey] = sharedData;
}
}
if (sharedDataVersion !== sharedData.version) {
throw new Error("Multiple incompatible instances of source-map-support were loaded");
}
for (var key in defaults) {
if (!(key in sharedData)) {
sharedData[key] = defaults[key];
}
}
return sharedData;
}
// If multiple instances of source-map-support are loaded into the same
// context, they shouldn't overwrite each other. By storing handlers, caches,
// and other state on a shared object, different instances of
// source-map-support can work together in a limited way. This does require
// that future versions of source-map-support continue to support the fields on
// this object. If this internal contract ever needs to be broken, increment
// sharedDataVersion. (This version number is not the same as any of the
// package's version numbers, which should reflect the *external* API of
// source-map-support.)
var sharedData = initializeSharedData({
// Only install once if called multiple times
// Remember how the environment looked before installation so we can restore if able
/** @type {HookState} */
errorPrepareStackTraceHook: undefined,
/** @type {HookState} */
processEmitHook: undefined,
/** @type {HookState} */
moduleResolveFilenameHook: undefined,
/** @type {Array<(request: string, parent: any, isMain: boolean, options: any, redirectedRequest: string) => void>} */
onConflictingLibraryRedirectArr: [],
// If true, the caches are reset before a stack trace formatting operation
emptyCacheBetweenOperations: false,
// Maps a file path to a string containing the file contents
fileContentsCache: {},
// Maps a file path to a source map for that file
sourceMapCache: {},
// Priority list of retrieve handlers
retrieveFileHandlers: [],
retrieveMapHandlers: [],
// Priority list of internally-implemented handlers.
// When resetting state, we must keep these.
internalRetrieveFileHandlers: [],
internalRetrieveMapHandlers: [],
});
// Supports {browser, node, auto}
var environment = "auto";
// Maps a file path to a string containing the file contents
var fileContentsCache = {};
// Maps a file path to a source map for that file
var sourceMapCache = {};
// Regex for detecting source maps
var reSourceMap = /^data:application\/json[^,]+base64,/;
// Priority list of retrieve handlers
var retrieveFileHandlers = [];
var retrieveMapHandlers = [];
function isInBrowser() {

@@ -62,3 +130,3 @@ if (environment === "browser")

function handlerExec(list) {
function handlerExec(list, internalList) {
return function(arg) {

@@ -71,2 +139,8 @@ for (var i = 0; i < list.length; i++) {

}
for (var i = 0; i < internalList.length; i++) {
var ret = internalList[i](arg);
if (ret) {
return ret;
}
}
return null;

@@ -76,5 +150,5 @@ };

var retrieveFile = handlerExec(retrieveFileHandlers);
var retrieveFile = handlerExec(sharedData.retrieveFileHandlers, sharedData.internalRetrieveFileHandlers);
retrieveFileHandlers.push(function(path) {
sharedData.internalRetrieveFileHandlers.push(function(path) {
// Trim the path to make sure there is no extra whitespace.

@@ -90,4 +164,4 @@ path = path.trim();

}
if (path in fileContentsCache) {
return fileContentsCache[path];
if (path in sharedData.fileContentsCache) {
return sharedData.fileContentsCache[path];
}

@@ -113,3 +187,3 @@

return fileContentsCache[path] = contents;
return sharedData.fileContentsCache[path] = contents;
});

@@ -169,4 +243,4 @@

// constructor).
var retrieveSourceMap = handlerExec(retrieveMapHandlers);
retrieveMapHandlers.push(function(source) {
var retrieveSourceMap = handlerExec(sharedData.retrieveMapHandlers, sharedData.internalRetrieveMapHandlers);
sharedData.internalRetrieveMapHandlers.push(function(source) {
var sourceMappingURL = retrieveSourceMapURL(source);

@@ -199,3 +273,3 @@ if (!sourceMappingURL) return null;

function mapSourcePosition(position) {
var sourceMap = sourceMapCache[position.source];
var sourceMap = sharedData.sourceMapCache[position.source];
if (!sourceMap) {

@@ -205,3 +279,3 @@ // Call the (overrideable) retrieveSourceMap function to get the source map.

if (urlAndMap) {
sourceMap = sourceMapCache[position.source] = {
sourceMap = sharedData.sourceMapCache[position.source] = {
url: urlAndMap.url,

@@ -218,3 +292,3 @@ map: new SourceMapConsumer(urlAndMap.map)

var url = supportRelativeURL(sourceMap.url, source);
fileContentsCache[url] = contents;
sharedData.fileContentsCache[url] = contents;
}

@@ -224,3 +298,3 @@ });

} else {
sourceMap = sourceMapCache[position.source] = {
sourceMap = sharedData.sourceMapCache[position.source] = {
url: null,

@@ -445,34 +519,41 @@ map: null

// This function is part of the V8 stack trace API, for more info see:
// https://v8.dev/docs/stack-trace-api
function prepareStackTrace(error, stack) {
if (emptyCacheBetweenOperations) {
fileContentsCache = {};
sourceMapCache = {};
}
/** @param {HookState} hookState */
function createPrepareStackTrace(hookState) {
return prepareStackTrace;
// node gives its own errors special treatment. Mimic that behavior
// https://github.com/nodejs/node/blob/3cbaabc4622df1b4009b9d026a1a970bdbae6e89/lib/internal/errors.js#L118-L128
// https://github.com/nodejs/node/pull/39182
var errorString;
if (kIsNodeError) {
if(kIsNodeError in error) {
errorString = `${error.name} [${error.code}]: ${error.message}`;
// This function is part of the V8 stack trace API, for more info see:
// https://v8.dev/docs/stack-trace-api
function prepareStackTrace(error, stack) {
if(!hookState.enabled) return hookState.originalValue.apply(this, arguments);
if (sharedData.emptyCacheBetweenOperations) {
sharedData.fileContentsCache = {};
sharedData.sourceMapCache = {};
}
// node gives its own errors special treatment. Mimic that behavior
// https://github.com/nodejs/node/blob/3cbaabc4622df1b4009b9d026a1a970bdbae6e89/lib/internal/errors.js#L118-L128
// https://github.com/nodejs/node/pull/39182
var errorString;
if (kIsNodeError) {
if(kIsNodeError in error) {
errorString = `${error.name} [${error.code}]: ${error.message}`;
} else {
errorString = ErrorPrototypeToString(error);
}
} else {
errorString = ErrorPrototypeToString(error);
var name = error.name || 'Error';
var message = error.message || '';
errorString = name + ": " + message;
}
} else {
var name = error.name || 'Error';
var message = error.message || '';
errorString = name + ": " + message;
}
var state = { nextPosition: null, curPosition: null };
var processedStack = [];
for (var i = stack.length - 1; i >= 0; i--) {
processedStack.push('\n at ' + wrapCallSite(stack[i], state));
state.nextPosition = state.curPosition;
var state = { nextPosition: null, curPosition: null };
var processedStack = [];
for (var i = stack.length - 1; i >= 0; i--) {
processedStack.push('\n at ' + wrapCallSite(stack[i], state));
state.nextPosition = state.curPosition;
}
state.curPosition = state.nextPosition = null;
return errorString + processedStack.reverse().join('');
}
state.curPosition = state.nextPosition = null;
return errorString + processedStack.reverse().join('');
}

@@ -489,3 +570,3 @@

// Support the inline sourceContents inside the source map
var contents = fileContentsCache[source];
var contents = sharedData.fileContentsCache[source];

@@ -535,16 +616,23 @@ // Support files on disk

function shimEmitUncaughtException () {
var origEmit = process.emit;
const originalValue = process.emit;
var hook = sharedData.processEmitHook = {
enabled: true,
originalValue,
installedValue: undefined
};
var isTerminatingDueToFatalException = false;
var fatalException;
process.emit = function (type) {
const hadListeners = origEmit.apply(this, arguments);
if (type === 'uncaughtException' && !hadListeners) {
isTerminatingDueToFatalException = true;
fatalException = arguments[1];
process.exit(1);
process.emit = sharedData.processEmitHook.installedValue = function (type) {
const hadListeners = originalValue.apply(this, arguments);
if(hook.enabled) {
if (type === 'uncaughtException' && !hadListeners) {
isTerminatingDueToFatalException = true;
fatalException = arguments[1];
process.exit(1);
}
if (type === 'exit' && isTerminatingDueToFatalException) {
printFatalErrorUponExit(fatalException);
}
}
if (type === 'exit' && isTerminatingDueToFatalException) {
printFatalErrorUponExit(fatalException);
}
return hadListeners;

@@ -554,4 +642,4 @@ };

var originalRetrieveFileHandlers = retrieveFileHandlers.slice(0);
var originalRetrieveMapHandlers = retrieveMapHandlers.slice(0);
var originalRetrieveFileHandlers = sharedData.retrieveFileHandlers.slice(0);
var originalRetrieveMapHandlers = sharedData.retrieveMapHandlers.slice(0);

@@ -573,2 +661,43 @@ exports.wrapCallSite = wrapCallSite;

// Use dynamicRequire to avoid including in browser bundles
var Module = dynamicRequire(module, 'module');
// Redirect subsequent imports of "source-map-support"
// to this package
const {redirectConflictingLibrary = true, onConflictingLibraryRedirect} = options;
if(redirectConflictingLibrary) {
if (!sharedData.moduleResolveFilenameHook) {
const originalValue = Module._resolveFilename;
const moduleResolveFilenameHook = sharedData.moduleResolveFilenameHook = {
enabled: true,
originalValue,
installedValue: undefined,
}
Module._resolveFilename = sharedData.moduleResolveFilenameHook.installedValue = function (request, parent, isMain, options) {
if (moduleResolveFilenameHook.enabled) {
// Match all source-map-support entrypoints: source-map-support, source-map-support/register
let requestRedirect;
if (request === 'source-map-support') {
requestRedirect = './';
} else if (request === 'source-map-support/register') {
requestRedirect = './register';
}
if (requestRedirect !== undefined) {
const newRequest = require.resolve(requestRedirect);
for (const cb of sharedData.onConflictingLibraryRedirectArr) {
cb(request, parent, isMain, options, newRequest);
}
request = newRequest;
}
}
return originalValue.call(this, request, parent, isMain, options);
}
}
if (onConflictingLibraryRedirect) {
sharedData.onConflictingLibraryRedirectArr.push(onConflictingLibraryRedirect);
}
}
// Allow sources to be found by methods other than reading the files

@@ -578,6 +707,6 @@ // directly from disk.

if (options.overrideRetrieveFile) {
retrieveFileHandlers.length = 0;
sharedData.retrieveFileHandlers.length = 0;
}
retrieveFileHandlers.unshift(options.retrieveFile);
sharedData.retrieveFileHandlers.unshift(options.retrieveFile);
}

@@ -589,6 +718,6 @@

if (options.overrideRetrieveSourceMap) {
retrieveMapHandlers.length = 0;
sharedData.retrieveMapHandlers.length = 0;
}
retrieveMapHandlers.unshift(options.retrieveSourceMap);
sharedData.retrieveMapHandlers.unshift(options.retrieveSourceMap);
}

@@ -598,4 +727,2 @@

if (options.hookRequire && !isInBrowser()) {
// Use dynamicRequire to avoid including in browser bundles
var Module = dynamicRequire(module, 'module');
var $compile = Module.prototype._compile;

@@ -605,4 +732,4 @@

Module.prototype._compile = function(content, filename) {
fileContentsCache[filename] = content;
sourceMapCache[filename] = undefined;
sharedData.fileContentsCache[filename] = content;
sharedData.sourceMapCache[filename] = undefined;
return $compile.call(this, content, filename);

@@ -616,14 +743,20 @@ };

// Configure options
if (!emptyCacheBetweenOperations) {
emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ?
if (!sharedData.emptyCacheBetweenOperations) {
sharedData.emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ?
options.emptyCacheBetweenOperations : false;
}
// Install the error reformatter
if (!errorFormatterInstalled) {
errorFormatterInstalled = true;
Error.prepareStackTrace = prepareStackTrace;
if (!sharedData.errorPrepareStackTraceHook) {
const originalValue = Error.prepareStackTrace;
sharedData.errorPrepareStackTraceHook = {
enabled: true,
originalValue,
installedValue: undefined
};
Error.prepareStackTrace = sharedData.errorPrepareStackTraceHook.installedValue = createPrepareStackTrace(sharedData.errorPrepareStackTraceHook);
}
if (!uncaughtShimInstalled) {
if (!sharedData.processEmitHook) {
var installHandler = 'handleUncaughtExceptions' in options ?

@@ -651,3 +784,2 @@ options.handleUncaughtExceptions : true;

if (installHandler && hasGlobalProcessEventEmitter()) {
uncaughtShimInstalled = true;
shimEmitUncaughtException();

@@ -658,11 +790,40 @@ }

exports.uninstall = function() {
if(sharedData.processEmitHook) {
// Disable behavior
sharedData.processEmitHook.enabled = false;
// If possible, remove our hook function. May not be possible if subsequent third-party hooks have wrapped around us.
if(process.emit === sharedData.processEmitHook.installedValue) {
process.emit = sharedData.processEmitHook.originalValue;
}
sharedData.processEmitHook = undefined;
}
if(sharedData.errorPrepareStackTraceHook) {
// Disable behavior
sharedData.errorPrepareStackTraceHook.enabled = false;
// If possible or necessary, remove our hook function.
// In vanilla environments, prepareStackTrace is `undefined`.
// We cannot delegate to `undefined` the way we can to a function w/`.apply()`; our only option is to remove the function.
// If we are the *first* hook installed, and another was installed on top of us, we have no choice but to remove both.
if(Error.prepareStackTrace === sharedData.errorPrepareStackTraceHook.installedValue || typeof sharedData.errorPrepareStackTraceHook.originalValue !== 'function') {
Error.prepareStackTrace = sharedData.errorPrepareStackTraceHook.originalValue;
}
sharedData.errorPrepareStackTraceHook = undefined;
}
if (sharedData.moduleResolveFilenameHook) {
// Disable behavior
sharedData.moduleResolveFilenameHook.enabled = false;
// If possible, remove our hook function. May not be possible if subsequent third-party hooks have wrapped around us.
var Module = dynamicRequire(module, 'module');
if(Module._resolveFilename === sharedData.moduleResolveFilenameHook.installedValue) {
Module._resolveFilename = sharedData.moduleResolveFilenameHook.originalValue;
}
sharedData.moduleResolveFilenameHook = undefined;
}
sharedData.onConflictingLibraryRedirectArr.length = 0;
}
exports.resetRetrieveHandlers = function() {
retrieveFileHandlers.length = 0;
retrieveMapHandlers.length = 0;
retrieveFileHandlers = originalRetrieveFileHandlers.slice(0);
retrieveMapHandlers = originalRetrieveMapHandlers.slice(0);
retrieveSourceMap = handlerExec(retrieveMapHandlers);
retrieveFile = handlerExec(retrieveFileHandlers);
sharedData.retrieveFileHandlers.length = 0;
sharedData.retrieveMapHandlers.length = 0;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc