/ cloudformation-templates / node_modules / aws-cdk / node_modules / source-map-support / source-map-support.js
source-map-support.js
1 var SourceMapConsumer = require('source-map').SourceMapConsumer; 2 var path = require('path'); 3 4 var fs; 5 try { 6 fs = require('fs'); 7 if (!fs.existsSync || !fs.readFileSync) { 8 // fs doesn't have all methods we need 9 fs = null; 10 } 11 } catch (err) { 12 /* nop */ 13 } 14 15 var bufferFrom = require('buffer-from'); 16 17 /** 18 * Requires a module which is protected against bundler minification. 19 * 20 * @param {NodeModule} mod 21 * @param {string} request 22 */ 23 function dynamicRequire(mod, request) { 24 return mod.require(request); 25 } 26 27 // Only install once if called multiple times 28 var errorFormatterInstalled = false; 29 var uncaughtShimInstalled = false; 30 31 // If true, the caches are reset before a stack trace formatting operation 32 var emptyCacheBetweenOperations = false; 33 34 // Supports {browser, node, auto} 35 var environment = "auto"; 36 37 // Maps a file path to a string containing the file contents 38 var fileContentsCache = {}; 39 40 // Maps a file path to a source map for that file 41 var sourceMapCache = {}; 42 43 // Regex for detecting source maps 44 var reSourceMap = /^data:application\/json[^,]+base64,/; 45 46 // Priority list of retrieve handlers 47 var retrieveFileHandlers = []; 48 var retrieveMapHandlers = []; 49 50 function isInBrowser() { 51 if (environment === "browser") 52 return true; 53 if (environment === "node") 54 return false; 55 return ((typeof window !== 'undefined') && (typeof XMLHttpRequest === 'function') && !(window.require && window.module && window.process && window.process.type === "renderer")); 56 } 57 58 function hasGlobalProcessEventEmitter() { 59 return ((typeof process === 'object') && (process !== null) && (typeof process.on === 'function')); 60 } 61 62 function handlerExec(list) { 63 return function(arg) { 64 for (var i = 0; i < list.length; i++) { 65 var ret = list[i](arg); 66 if (ret) { 67 return ret; 68 } 69 } 70 return null; 71 }; 72 } 73 74 var retrieveFile = handlerExec(retrieveFileHandlers); 75 76 retrieveFileHandlers.push(function(path) { 77 // Trim the path to make sure there is no extra whitespace. 78 path = path.trim(); 79 if (/^file:/.test(path)) { 80 // existsSync/readFileSync can't handle file protocol, but once stripped, it works 81 path = path.replace(/file:\/\/\/(\w:)?/, function(protocol, drive) { 82 return drive ? 83 '' : // file:///C:/dir/file -> C:/dir/file 84 '/'; // file:///root-dir/file -> /root-dir/file 85 }); 86 } 87 if (path in fileContentsCache) { 88 return fileContentsCache[path]; 89 } 90 91 var contents = ''; 92 try { 93 if (!fs) { 94 // Use SJAX if we are in the browser 95 var xhr = new XMLHttpRequest(); 96 xhr.open('GET', path, /** async */ false); 97 xhr.send(null); 98 if (xhr.readyState === 4 && xhr.status === 200) { 99 contents = xhr.responseText; 100 } 101 } else if (fs.existsSync(path)) { 102 // Otherwise, use the filesystem 103 contents = fs.readFileSync(path, 'utf8'); 104 } 105 } catch (er) { 106 /* ignore any errors */ 107 } 108 109 return fileContentsCache[path] = contents; 110 }); 111 112 // Support URLs relative to a directory, but be careful about a protocol prefix 113 // in case we are in the browser (i.e. directories may start with "http://" or "file:///") 114 function supportRelativeURL(file, url) { 115 if (!file) return url; 116 var dir = path.dirname(file); 117 var match = /^\w+:\/\/[^\/]*/.exec(dir); 118 var protocol = match ? match[0] : ''; 119 var startPath = dir.slice(protocol.length); 120 if (protocol && /^\/\w\:/.test(startPath)) { 121 // handle file:///C:/ paths 122 protocol += '/'; 123 return protocol + path.resolve(dir.slice(protocol.length), url).replace(/\\/g, '/'); 124 } 125 return protocol + path.resolve(dir.slice(protocol.length), url); 126 } 127 128 function retrieveSourceMapURL(source) { 129 var fileData; 130 131 if (isInBrowser()) { 132 try { 133 var xhr = new XMLHttpRequest(); 134 xhr.open('GET', source, false); 135 xhr.send(null); 136 fileData = xhr.readyState === 4 ? xhr.responseText : null; 137 138 // Support providing a sourceMappingURL via the SourceMap header 139 var sourceMapHeader = xhr.getResponseHeader("SourceMap") || 140 xhr.getResponseHeader("X-SourceMap"); 141 if (sourceMapHeader) { 142 return sourceMapHeader; 143 } 144 } catch (e) { 145 } 146 } 147 148 // Get the URL of the source map 149 fileData = retrieveFile(source); 150 var re = /(?:\/\/[@#][\s]*sourceMappingURL=([^\s'"]+)[\s]*$)|(?:\/\*[@#][\s]*sourceMappingURL=([^\s*'"]+)[\s]*(?:\*\/)[\s]*$)/mg; 151 // Keep executing the search to find the *last* sourceMappingURL to avoid 152 // picking up sourceMappingURLs from comments, strings, etc. 153 var lastMatch, match; 154 while (match = re.exec(fileData)) lastMatch = match; 155 if (!lastMatch) return null; 156 return lastMatch[1]; 157 }; 158 159 // Can be overridden by the retrieveSourceMap option to install. Takes a 160 // generated source filename; returns a {map, optional url} object, or null if 161 // there is no source map. The map field may be either a string or the parsed 162 // JSON object (ie, it must be a valid argument to the SourceMapConsumer 163 // constructor). 164 var retrieveSourceMap = handlerExec(retrieveMapHandlers); 165 retrieveMapHandlers.push(function(source) { 166 var sourceMappingURL = retrieveSourceMapURL(source); 167 if (!sourceMappingURL) return null; 168 169 // Read the contents of the source map 170 var sourceMapData; 171 if (reSourceMap.test(sourceMappingURL)) { 172 // Support source map URL as a data url 173 var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1); 174 sourceMapData = bufferFrom(rawData, "base64").toString(); 175 sourceMappingURL = source; 176 } else { 177 // Support source map URLs relative to the source URL 178 sourceMappingURL = supportRelativeURL(source, sourceMappingURL); 179 sourceMapData = retrieveFile(sourceMappingURL); 180 } 181 182 if (!sourceMapData) { 183 return null; 184 } 185 186 return { 187 url: sourceMappingURL, 188 map: sourceMapData 189 }; 190 }); 191 192 function mapSourcePosition(position) { 193 var sourceMap = sourceMapCache[position.source]; 194 if (!sourceMap) { 195 // Call the (overrideable) retrieveSourceMap function to get the source map. 196 var urlAndMap = retrieveSourceMap(position.source); 197 if (urlAndMap) { 198 sourceMap = sourceMapCache[position.source] = { 199 url: urlAndMap.url, 200 map: new SourceMapConsumer(urlAndMap.map) 201 }; 202 203 // Load all sources stored inline with the source map into the file cache 204 // to pretend like they are already loaded. They may not exist on disk. 205 if (sourceMap.map.sourcesContent) { 206 sourceMap.map.sources.forEach(function(source, i) { 207 var contents = sourceMap.map.sourcesContent[i]; 208 if (contents) { 209 var url = supportRelativeURL(sourceMap.url, source); 210 fileContentsCache[url] = contents; 211 } 212 }); 213 } 214 } else { 215 sourceMap = sourceMapCache[position.source] = { 216 url: null, 217 map: null 218 }; 219 } 220 } 221 222 // Resolve the source URL relative to the URL of the source map 223 if (sourceMap && sourceMap.map && typeof sourceMap.map.originalPositionFor === 'function') { 224 var originalPosition = sourceMap.map.originalPositionFor(position); 225 226 // Only return the original position if a matching line was found. If no 227 // matching line is found then we return position instead, which will cause 228 // the stack trace to print the path and line for the compiled file. It is 229 // better to give a precise location in the compiled file than a vague 230 // location in the original file. 231 if (originalPosition.source !== null) { 232 originalPosition.source = supportRelativeURL( 233 sourceMap.url, originalPosition.source); 234 return originalPosition; 235 } 236 } 237 238 return position; 239 } 240 241 // Parses code generated by FormatEvalOrigin(), a function inside V8: 242 // https://code.google.com/p/v8/source/browse/trunk/src/messages.js 243 function mapEvalOrigin(origin) { 244 // Most eval() calls are in this format 245 var match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin); 246 if (match) { 247 var position = mapSourcePosition({ 248 source: match[2], 249 line: +match[3], 250 column: match[4] - 1 251 }); 252 return 'eval at ' + match[1] + ' (' + position.source + ':' + 253 position.line + ':' + (position.column + 1) + ')'; 254 } 255 256 // Parse nested eval() calls using recursion 257 match = /^eval at ([^(]+) \((.+)\)$/.exec(origin); 258 if (match) { 259 return 'eval at ' + match[1] + ' (' + mapEvalOrigin(match[2]) + ')'; 260 } 261 262 // Make sure we still return useful information if we didn't find anything 263 return origin; 264 } 265 266 // This is copied almost verbatim from the V8 source code at 267 // https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The 268 // implementation of wrapCallSite() used to just forward to the actual source 269 // code of CallSite.prototype.toString but unfortunately a new release of V8 270 // did something to the prototype chain and broke the shim. The only fix I 271 // could find was copy/paste. 272 function CallSiteToString() { 273 var fileName; 274 var fileLocation = ""; 275 if (this.isNative()) { 276 fileLocation = "native"; 277 } else { 278 fileName = this.getScriptNameOrSourceURL(); 279 if (!fileName && this.isEval()) { 280 fileLocation = this.getEvalOrigin(); 281 fileLocation += ", "; // Expecting source position to follow. 282 } 283 284 if (fileName) { 285 fileLocation += fileName; 286 } else { 287 // Source code does not originate from a file and is not native, but we 288 // can still get the source position inside the source string, e.g. in 289 // an eval string. 290 fileLocation += "<anonymous>"; 291 } 292 var lineNumber = this.getLineNumber(); 293 if (lineNumber != null) { 294 fileLocation += ":" + lineNumber; 295 var columnNumber = this.getColumnNumber(); 296 if (columnNumber) { 297 fileLocation += ":" + columnNumber; 298 } 299 } 300 } 301 302 var line = ""; 303 var functionName = this.getFunctionName(); 304 var addSuffix = true; 305 var isConstructor = this.isConstructor(); 306 var isMethodCall = !(this.isToplevel() || isConstructor); 307 if (isMethodCall) { 308 var typeName = this.getTypeName(); 309 // Fixes shim to be backward compatable with Node v0 to v4 310 if (typeName === "[object Object]") { 311 typeName = "null"; 312 } 313 var methodName = this.getMethodName(); 314 if (functionName) { 315 if (typeName && functionName.indexOf(typeName) != 0) { 316 line += typeName + "."; 317 } 318 line += functionName; 319 if (methodName && functionName.indexOf("." + methodName) != functionName.length - methodName.length - 1) { 320 line += " [as " + methodName + "]"; 321 } 322 } else { 323 line += typeName + "." + (methodName || "<anonymous>"); 324 } 325 } else if (isConstructor) { 326 line += "new " + (functionName || "<anonymous>"); 327 } else if (functionName) { 328 line += functionName; 329 } else { 330 line += fileLocation; 331 addSuffix = false; 332 } 333 if (addSuffix) { 334 line += " (" + fileLocation + ")"; 335 } 336 return line; 337 } 338 339 function cloneCallSite(frame) { 340 var object = {}; 341 Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach(function(name) { 342 object[name] = /^(?:is|get)/.test(name) ? function() { return frame[name].call(frame); } : frame[name]; 343 }); 344 object.toString = CallSiteToString; 345 return object; 346 } 347 348 function wrapCallSite(frame, state) { 349 // provides interface backward compatibility 350 if (state === undefined) { 351 state = { nextPosition: null, curPosition: null } 352 } 353 if(frame.isNative()) { 354 state.curPosition = null; 355 return frame; 356 } 357 358 // Most call sites will return the source file from getFileName(), but code 359 // passed to eval() ending in "//# sourceURL=..." will return the source file 360 // from getScriptNameOrSourceURL() instead 361 var source = frame.getFileName() || frame.getScriptNameOrSourceURL(); 362 if (source) { 363 var line = frame.getLineNumber(); 364 var column = frame.getColumnNumber() - 1; 365 366 // Fix position in Node where some (internal) code is prepended. 367 // See https://github.com/evanw/node-source-map-support/issues/36 368 // Header removed in node at ^10.16 || >=11.11.0 369 // v11 is not an LTS candidate, we can just test the one version with it. 370 // Test node versions for: 10.16-19, 10.20+, 12-19, 20-99, 100+, or 11.11 371 var noHeader = /^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/; 372 var headerLength = noHeader.test(process.version) ? 0 : 62; 373 if (line === 1 && column > headerLength && !isInBrowser() && !frame.isEval()) { 374 column -= headerLength; 375 } 376 377 var position = mapSourcePosition({ 378 source: source, 379 line: line, 380 column: column 381 }); 382 state.curPosition = position; 383 frame = cloneCallSite(frame); 384 var originalFunctionName = frame.getFunctionName; 385 frame.getFunctionName = function() { 386 if (state.nextPosition == null) { 387 return originalFunctionName(); 388 } 389 return state.nextPosition.name || originalFunctionName(); 390 }; 391 frame.getFileName = function() { return position.source; }; 392 frame.getLineNumber = function() { return position.line; }; 393 frame.getColumnNumber = function() { return position.column + 1; }; 394 frame.getScriptNameOrSourceURL = function() { return position.source; }; 395 return frame; 396 } 397 398 // Code called using eval() needs special handling 399 var origin = frame.isEval() && frame.getEvalOrigin(); 400 if (origin) { 401 origin = mapEvalOrigin(origin); 402 frame = cloneCallSite(frame); 403 frame.getEvalOrigin = function() { return origin; }; 404 return frame; 405 } 406 407 // If we get here then we were unable to change the source position 408 return frame; 409 } 410 411 // This function is part of the V8 stack trace API, for more info see: 412 // https://v8.dev/docs/stack-trace-api 413 function prepareStackTrace(error, stack) { 414 if (emptyCacheBetweenOperations) { 415 fileContentsCache = {}; 416 sourceMapCache = {}; 417 } 418 419 var name = error.name || 'Error'; 420 var message = error.message || ''; 421 var errorString = name + ": " + message; 422 423 var state = { nextPosition: null, curPosition: null }; 424 var processedStack = []; 425 for (var i = stack.length - 1; i >= 0; i--) { 426 processedStack.push('\n at ' + wrapCallSite(stack[i], state)); 427 state.nextPosition = state.curPosition; 428 } 429 state.curPosition = state.nextPosition = null; 430 return errorString + processedStack.reverse().join(''); 431 } 432 433 // Generate position and snippet of original source with pointer 434 function getErrorSource(error) { 435 var match = /\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(error.stack); 436 if (match) { 437 var source = match[1]; 438 var line = +match[2]; 439 var column = +match[3]; 440 441 // Support the inline sourceContents inside the source map 442 var contents = fileContentsCache[source]; 443 444 // Support files on disk 445 if (!contents && fs && fs.existsSync(source)) { 446 try { 447 contents = fs.readFileSync(source, 'utf8'); 448 } catch (er) { 449 contents = ''; 450 } 451 } 452 453 // Format the line from the original source code like node does 454 if (contents) { 455 var code = contents.split(/(?:\r\n|\r|\n)/)[line - 1]; 456 if (code) { 457 return source + ':' + line + '\n' + code + '\n' + 458 new Array(column).join(' ') + '^'; 459 } 460 } 461 } 462 return null; 463 } 464 465 function printErrorAndExit (error) { 466 var source = getErrorSource(error); 467 468 // Ensure error is printed synchronously and not truncated 469 if (process.stderr._handle && process.stderr._handle.setBlocking) { 470 process.stderr._handle.setBlocking(true); 471 } 472 473 if (source) { 474 console.error(); 475 console.error(source); 476 } 477 478 console.error(error.stack); 479 process.exit(1); 480 } 481 482 function shimEmitUncaughtException () { 483 var origEmit = process.emit; 484 485 process.emit = function (type) { 486 if (type === 'uncaughtException') { 487 var hasStack = (arguments[1] && arguments[1].stack); 488 var hasListeners = (this.listeners(type).length > 0); 489 490 if (hasStack && !hasListeners) { 491 return printErrorAndExit(arguments[1]); 492 } 493 } 494 495 return origEmit.apply(this, arguments); 496 }; 497 } 498 499 var originalRetrieveFileHandlers = retrieveFileHandlers.slice(0); 500 var originalRetrieveMapHandlers = retrieveMapHandlers.slice(0); 501 502 exports.wrapCallSite = wrapCallSite; 503 exports.getErrorSource = getErrorSource; 504 exports.mapSourcePosition = mapSourcePosition; 505 exports.retrieveSourceMap = retrieveSourceMap; 506 507 exports.install = function(options) { 508 options = options || {}; 509 510 if (options.environment) { 511 environment = options.environment; 512 if (["node", "browser", "auto"].indexOf(environment) === -1) { 513 throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}") 514 } 515 } 516 517 // Allow sources to be found by methods other than reading the files 518 // directly from disk. 519 if (options.retrieveFile) { 520 if (options.overrideRetrieveFile) { 521 retrieveFileHandlers.length = 0; 522 } 523 524 retrieveFileHandlers.unshift(options.retrieveFile); 525 } 526 527 // Allow source maps to be found by methods other than reading the files 528 // directly from disk. 529 if (options.retrieveSourceMap) { 530 if (options.overrideRetrieveSourceMap) { 531 retrieveMapHandlers.length = 0; 532 } 533 534 retrieveMapHandlers.unshift(options.retrieveSourceMap); 535 } 536 537 // Support runtime transpilers that include inline source maps 538 if (options.hookRequire && !isInBrowser()) { 539 // Use dynamicRequire to avoid including in browser bundles 540 var Module = dynamicRequire(module, 'module'); 541 var $compile = Module.prototype._compile; 542 543 if (!$compile.__sourceMapSupport) { 544 Module.prototype._compile = function(content, filename) { 545 fileContentsCache[filename] = content; 546 sourceMapCache[filename] = undefined; 547 return $compile.call(this, content, filename); 548 }; 549 550 Module.prototype._compile.__sourceMapSupport = true; 551 } 552 } 553 554 // Configure options 555 if (!emptyCacheBetweenOperations) { 556 emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ? 557 options.emptyCacheBetweenOperations : false; 558 } 559 560 // Install the error reformatter 561 if (!errorFormatterInstalled) { 562 errorFormatterInstalled = true; 563 Error.prepareStackTrace = prepareStackTrace; 564 } 565 566 if (!uncaughtShimInstalled) { 567 var installHandler = 'handleUncaughtExceptions' in options ? 568 options.handleUncaughtExceptions : true; 569 570 // Do not override 'uncaughtException' with our own handler in Node.js 571 // Worker threads. Workers pass the error to the main thread as an event, 572 // rather than printing something to stderr and exiting. 573 try { 574 // We need to use `dynamicRequire` because `require` on it's own will be optimized by WebPack/Browserify. 575 var worker_threads = dynamicRequire(module, 'worker_threads'); 576 if (worker_threads.isMainThread === false) { 577 installHandler = false; 578 } 579 } catch(e) {} 580 581 // Provide the option to not install the uncaught exception handler. This is 582 // to support other uncaught exception handlers (in test frameworks, for 583 // example). If this handler is not installed and there are no other uncaught 584 // exception handlers, uncaught exceptions will be caught by node's built-in 585 // exception handler and the process will still be terminated. However, the 586 // generated JavaScript code will be shown above the stack trace instead of 587 // the original source code. 588 if (installHandler && hasGlobalProcessEventEmitter()) { 589 uncaughtShimInstalled = true; 590 shimEmitUncaughtException(); 591 } 592 } 593 }; 594 595 exports.resetRetrieveHandlers = function() { 596 retrieveFileHandlers.length = 0; 597 retrieveMapHandlers.length = 0; 598 599 retrieveFileHandlers = originalRetrieveFileHandlers.slice(0); 600 retrieveMapHandlers = originalRetrieveMapHandlers.slice(0); 601 602 retrieveSourceMap = handlerExec(retrieveMapHandlers); 603 retrieveFile = handlerExec(retrieveFileHandlers); 604 }