@cspotcode/source-map-support
Advanced tools
Comparing version 0.7.0 to 0.8.0
{ | ||
"name": "@cspotcode/source-map-support", | ||
"description": "Fixes stack traces for files with source maps", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"main": "./source-map-support.js", | ||
@@ -18,12 +18,16 @@ "types": "./source-map-support.d.ts", | ||
"/source-map-support.d.ts", | ||
"/source-map-support.js" | ||
"/source-map-support.js", | ||
"/browser-source-map-support.js" | ||
], | ||
"dependencies": { | ||
"@cspotcode/source-map-consumer": "0.8.0" | ||
"@jridgewell/trace-mapping": "0.3.9" | ||
}, | ||
"devDependencies": { | ||
"@types/lodash": "^4.14.182", | ||
"browserify": "^4.2.3", | ||
"coffeescript": "^1.12.7", | ||
"http-server": "^0.11.1", | ||
"lodash": "^4.17.21", | ||
"mocha": "^3.5.3", | ||
"semver": "^7.3.7", | ||
"source-map": "0.6.1", | ||
@@ -30,0 +34,0 @@ "webpack": "^1.15.0" |
@@ -9,3 +9,11 @@ // Type definitions for source-map-support 0.5 | ||
import { RawSourceMap } from '@cspotcode/source-map-consumer'; | ||
export interface RawSourceMap { | ||
version: 3; | ||
sources: string[]; | ||
names: string[]; | ||
sourceRoot?: string; | ||
sourcesContent?: string[]; | ||
mappings: string; | ||
file: string; | ||
} | ||
@@ -12,0 +20,0 @@ /** |
@@ -1,3 +0,4 @@ | ||
var SourceMapConsumer = require('@cspotcode/source-map-consumer').SourceMapConsumer; | ||
const { TraceMap, originalPositionFor, AnyMap } = require('@jridgewell/trace-mapping'); | ||
var path = require('path'); | ||
const { fileURLToPath, pathToFileURL } = require('url'); | ||
var util = require('util'); | ||
@@ -95,6 +96,7 @@ | ||
// Maps a file path to a string containing the file contents | ||
fileContentsCache: {}, | ||
fileContentsCache: Object.create(null), | ||
// Maps a file path to a source map for that file | ||
sourceMapCache: {}, | ||
/** @type {Record<string, {url: string, map: TraceMap}} */ | ||
sourceMapCache: Object.create(null), | ||
@@ -130,2 +132,61 @@ // Priority list of retrieve handlers | ||
function tryFileURLToPath(v) { | ||
if(isFileUrl(v)) { | ||
return fileURLToPath(v); | ||
} | ||
return v; | ||
} | ||
// TODO un-copy these from resolve-uri; see if they can be exported from that lib | ||
function isFileUrl(input) { | ||
return input.startsWith('file:'); | ||
} | ||
function isAbsoluteUrl(input) { | ||
return schemeRegex.test(input); | ||
} | ||
// Matches the scheme of a URL, eg "http://" | ||
const schemeRegex = /^[\w+.-]+:\/\//; | ||
function isSchemeRelativeUrl(input) { | ||
return input.startsWith('//'); | ||
} | ||
// #region Caches | ||
/** @param {string} pathOrFileUrl */ | ||
function getCacheKey(pathOrFileUrl) { | ||
if(pathOrFileUrl.startsWith('node:')) return pathOrFileUrl; | ||
if(isFileUrl(pathOrFileUrl)) { | ||
// Must normalize spaces to %20, stuff like that | ||
return new URL(pathOrFileUrl).toString(); | ||
} else { | ||
try { | ||
return pathToFileURL(pathOrFileUrl).toString(); | ||
} catch { | ||
return pathOrFileUrl; | ||
} | ||
} | ||
} | ||
function getFileContentsCache(key) { | ||
return sharedData.fileContentsCache[getCacheKey(key)]; | ||
} | ||
function hasFileContentsCacheFromKey(key) { | ||
return Object.prototype.hasOwnProperty.call(sharedData.fileContentsCache, key); | ||
} | ||
function getFileContentsCacheFromKey(key) { | ||
return sharedData.fileContentsCache[key]; | ||
} | ||
function setFileContentsCache(key, value) { | ||
return sharedData.fileContentsCache[getCacheKey(key)] = value; | ||
} | ||
function getSourceMapCache(key) { | ||
return sharedData.sourceMapCache[getCacheKey(key)]; | ||
} | ||
function setSourceMapCache(key, value) { | ||
return sharedData.sourceMapCache[getCacheKey(key)] = value; | ||
} | ||
function clearCaches() { | ||
sharedData.fileContentsCache = Object.create(null); | ||
sharedData.sourceMapCache = Object.create(null); | ||
} | ||
// #endregion Caches | ||
function handlerExec(list, internalList) { | ||
@@ -162,4 +223,5 @@ return function(arg) { | ||
} | ||
if (path in sharedData.fileContentsCache) { | ||
return sharedData.fileContentsCache[path]; | ||
const key = getCacheKey(path); | ||
if(hasFileContentsCacheFromKey(key)) { | ||
return getFileContentsCacheFromKey(key); | ||
} | ||
@@ -185,3 +247,3 @@ | ||
return sharedData.fileContentsCache[path] = contents; | ||
return setFileContentsCache(path, contents); | ||
}); | ||
@@ -192,15 +254,66 @@ | ||
function supportRelativeURL(file, url) { | ||
if (!file) return url; | ||
var dir = path.dirname(file); | ||
var match = /^\w+:\/\/[^\/]*/.exec(dir); | ||
var protocol = match ? match[0] : ''; | ||
var startPath = dir.slice(protocol.length); | ||
if (protocol && /^\/\w\:/.test(startPath)) { | ||
// handle file:///C:/ paths | ||
protocol += '/'; | ||
return protocol + path.resolve(dir.slice(protocol.length), url).replace(/\\/g, '/'); | ||
if(!file) return url; | ||
// given that this happens within error formatting codepath, probably best to | ||
// fallback instead of throwing if anything goes wrong | ||
try { | ||
// if should output a URL | ||
if(isAbsoluteUrl(file) || isSchemeRelativeUrl(file)) { | ||
if(isAbsoluteUrl(url) || isSchemeRelativeUrl(url)) { | ||
return new URL(url, file).toString(); | ||
} | ||
if(path.isAbsolute(url)) { | ||
return new URL(pathToFileURL(url), file).toString(); | ||
} | ||
// url is relative path or URL | ||
return new URL(url.replace(/\\/g, '/'), file).toString(); | ||
} | ||
// if should output a path (unless URL is something like https://) | ||
if(path.isAbsolute(file)) { | ||
if(isFileUrl(url)) { | ||
return fileURLToPath(url); | ||
} | ||
if(isSchemeRelativeUrl(url)) { | ||
return fileURLToPath(new URL(url, 'file://')); | ||
} | ||
if(isAbsoluteUrl(url)) { | ||
// url is a non-file URL | ||
// Go with the URL | ||
return url; | ||
} | ||
if(path.isAbsolute(url)) { | ||
// Normalize at all? decodeURI or normalize slashes? | ||
return path.normalize(url); | ||
} | ||
// url is relative path or URL | ||
return path.join(file, '..', decodeURI(url)); | ||
} | ||
// If we get here, file is relative. | ||
// Shouldn't happen since node identifies modules with absolute paths or URLs. | ||
// But we can take a stab at returning something meaningful anyway. | ||
if(isAbsoluteUrl(url) || isSchemeRelativeUrl(url)) { | ||
return url; | ||
} | ||
return path.join(file, '..', url); | ||
} catch(e) { | ||
return url; | ||
} | ||
return protocol + path.resolve(dir.slice(protocol.length), url); | ||
} | ||
// Return pathOrUrl in the same style as matchStyleOf: either a file URL or a native path | ||
function matchStyleOfPathOrUrl(matchStyleOf, pathOrUrl) { | ||
try { | ||
if(isAbsoluteUrl(matchStyleOf) || isSchemeRelativeUrl(matchStyleOf)) { | ||
if(isAbsoluteUrl(pathOrUrl) || isSchemeRelativeUrl(pathOrUrl)) return pathOrUrl; | ||
if(path.isAbsolute(pathOrUrl)) return pathToFileURL(pathOrUrl).toString(); | ||
} else if(path.isAbsolute(matchStyleOf)) { | ||
if(isAbsoluteUrl(pathOrUrl) || isSchemeRelativeUrl(pathOrUrl)) { | ||
return fileURLToPath(new URL(pathOrUrl, 'file://')); | ||
} | ||
} | ||
return pathOrUrl; | ||
} catch(e) { | ||
return pathOrUrl; | ||
} | ||
} | ||
function retrieveSourceMapURL(source) { | ||
@@ -227,3 +340,3 @@ var fileData; | ||
// Get the URL of the source map | ||
fileData = retrieveFile(source); | ||
fileData = retrieveFile(tryFileURLToPath(source)); | ||
var re = /(?:\/\/[@#][\s]*sourceMappingURL=([^\s'"]+)[\s]*$)|(?:\/\*[@#][\s]*sourceMappingURL=([^\s*'"]+)[\s]*(?:\*\/)[\s]*$)/mg; | ||
@@ -243,2 +356,3 @@ // Keep executing the search to find the *last* sourceMappingURL to avoid | ||
// constructor). | ||
/** @type {(source: string) => import('./source-map-support').UrlAndMap | null} */ | ||
var retrieveSourceMap = handlerExec(sharedData.retrieveMapHandlers, sharedData.internalRetrieveMapHandlers); | ||
@@ -259,3 +373,3 @@ sharedData.internalRetrieveMapHandlers.push(function(source) { | ||
sourceMappingURL = supportRelativeURL(source, sourceMappingURL); | ||
sourceMapData = retrieveFile(sourceMappingURL); | ||
sourceMapData = retrieveFile(tryFileURLToPath(sourceMappingURL)); | ||
} | ||
@@ -274,3 +388,3 @@ | ||
function mapSourcePosition(position) { | ||
var sourceMap = sharedData.sourceMapCache[position.source]; | ||
var sourceMap = getSourceMapCache(position.source); | ||
if (!sourceMap) { | ||
@@ -280,15 +394,19 @@ // Call the (overrideable) retrieveSourceMap function to get the source map. | ||
if (urlAndMap) { | ||
sourceMap = sharedData.sourceMapCache[position.source] = { | ||
sourceMap = setSourceMapCache(position.source, { | ||
url: urlAndMap.url, | ||
map: new SourceMapConsumer(urlAndMap.map) | ||
}; | ||
map: new AnyMap(urlAndMap.map, urlAndMap.url) | ||
}); | ||
// Overwrite trace-mapping's resolutions, because they do not handle | ||
// Windows paths the way we want. | ||
// TODO Remove now that windows path support was added to resolve-uri and thus trace-mapping? | ||
sourceMap.map.resolvedSources = sourceMap.map.sources.map(s => supportRelativeURL(sourceMap.url, s)); | ||
// Load all sources stored inline with the source map into the file cache | ||
// to pretend like they are already loaded. They may not exist on disk. | ||
if (sourceMap.map.sourcesContent) { | ||
sourceMap.map.sources.forEach(function(source, i) { | ||
sourceMap.map.resolvedSources.forEach(function(resolvedSource, i) { | ||
var contents = sourceMap.map.sourcesContent[i]; | ||
if (contents) { | ||
var url = supportRelativeURL(sourceMap.url, source); | ||
sharedData.fileContentsCache[url] = contents; | ||
setFileContentsCache(resolvedSource, contents); | ||
} | ||
@@ -298,6 +416,6 @@ }); | ||
} else { | ||
sourceMap = sharedData.sourceMapCache[position.source] = { | ||
sourceMap = setSourceMapCache(position.source, { | ||
url: null, | ||
map: null | ||
}; | ||
}); | ||
} | ||
@@ -307,4 +425,4 @@ } | ||
// Resolve the source URL relative to the URL of the source map | ||
if (sourceMap && sourceMap.map && typeof sourceMap.map.originalPositionFor === 'function') { | ||
var originalPosition = sourceMap.map.originalPositionFor(position); | ||
if (sourceMap && sourceMap.map) { | ||
var originalPosition = originalPositionFor(sourceMap.map, position); | ||
@@ -317,4 +435,7 @@ // Only return the original position if a matching line was found. If no | ||
if (originalPosition.source !== null) { | ||
originalPosition.source = supportRelativeURL( | ||
sourceMap.url, originalPosition.source); | ||
// originalPosition.source has *already* been resolved against sourceMap.url | ||
// so is *already* as absolute as possible. | ||
// However, we want to ensure we output in same format as input: URL or native path | ||
originalPosition.source = matchStyleOfPathOrUrl( | ||
position.source, originalPosition.source); | ||
return originalPosition; | ||
@@ -353,4 +474,8 @@ } | ||
// This is copied almost verbatim from the V8 source code at | ||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The | ||
// implementation of wrapCallSite() used to just forward to the actual source | ||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js | ||
// Update 2022-04-29: | ||
// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/builtins/builtins-callsite.cc#L175-L179 | ||
// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/objects/call-site-info.cc#L795-L804 | ||
// https://github.com/v8/v8/blob/98f6f100c5ab8e390e51422747c4ef644d5ac6f2/src/objects/call-site-info.cc#L717-L750 | ||
// The implementation of wrapCallSite() used to just forward to the actual source | ||
// code of CallSite.prototype.toString but unfortunately a new release of V8 | ||
@@ -461,2 +586,8 @@ // did something to the prototype chain and broke the shim. The only fix I | ||
if (source) { | ||
// v8 does not expose its internal isWasm, etc methods, so we do this instead. | ||
if(source.startsWith('wasm://')) { | ||
state.curPosition = null; | ||
return frame; | ||
} | ||
var line = frame.getLineNumber(); | ||
@@ -533,4 +664,3 @@ var column = frame.getColumnNumber() - 1; | ||
if (sharedData.emptyCacheBetweenOperations) { | ||
sharedData.fileContentsCache = {}; | ||
sharedData.sourceMapCache = {}; | ||
clearCaches(); | ||
} | ||
@@ -574,8 +704,10 @@ | ||
// Support the inline sourceContents inside the source map | ||
var contents = sharedData.fileContentsCache[source]; | ||
var contents = getFileContentsCache(source); | ||
const sourceAsPath = tryFileURLToPath(source); | ||
// Support files on disk | ||
if (!contents && fs && fs.existsSync(source)) { | ||
if (!contents && fs && fs.existsSync(sourceAsPath)) { | ||
try { | ||
contents = fs.readFileSync(source, 'utf8'); | ||
contents = fs.readFileSync(sourceAsPath, 'utf8'); | ||
} catch (er) { | ||
@@ -730,4 +862,4 @@ contents = ''; | ||
Module.prototype._compile = function(content, filename) { | ||
sharedData.fileContentsCache[filename] = content; | ||
sharedData.sourceMapCache[filename] = undefined; | ||
setFileContentsCache(filename, content); | ||
setSourceMapCache(filename, undefined); | ||
return $compile.call(this, content, filename); | ||
@@ -734,0 +866,0 @@ }; |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
102072
10
1158
9
2
4
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/sourcemap-codec@1.4.15(transitive)
+ Added@jridgewell/trace-mapping@0.3.9(transitive)
- Removed@cspotcode/source-map-consumer@0.8.0
- Removed@cspotcode/source-map-consumer@0.8.0(transitive)