From 4e87195739f2a5d9a05451b48773c8afdc680765 Mon Sep 17 00:00:00 2001 From: akiyamn Date: Sun, 24 Sep 2023 23:22:21 +1000 Subject: Initial commit (by create-cloudflare CLI) --- node_modules/stacktracey/stacktracey.js | 339 ++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 node_modules/stacktracey/stacktracey.js (limited to 'node_modules/stacktracey/stacktracey.js') diff --git a/node_modules/stacktracey/stacktracey.js b/node_modules/stacktracey/stacktracey.js new file mode 100644 index 0000000..b86b6db --- /dev/null +++ b/node_modules/stacktracey/stacktracey.js @@ -0,0 +1,339 @@ +"use strict"; + +/* ------------------------------------------------------------------------ */ + +const O = Object, + isBrowser = (typeof window !== 'undefined') && (window.window === window) && window.navigator, + nodeRequire = isBrowser ? null : module.require, // to prevent bundlers from expanding the require call + lastOf = x => x[x.length - 1], + getSource = require ('get-source'), + partition = require ('./impl/partition'), + asTable = require ('as-table'), + nixSlashes = x => x.replace (/\\/g, '/'), + pathRoot = isBrowser ? window.location.href : (nixSlashes (process.cwd ()) + '/') + +/* ------------------------------------------------------------------------ */ + +class StackTracey { + + constructor (input, offset) { + + const originalInput = input + , isParseableSyntaxError = input && (input instanceof SyntaxError && !isBrowser) + + /* new StackTracey () */ + + if (!input) { + input = new Error () + offset = (offset === undefined) ? 1 : offset + } + + /* new StackTracey (Error) */ + + if (input instanceof Error) { + input = input.stack || '' + } + + /* new StackTracey (string) */ + + if (typeof input === 'string') { + input = this.rawParse (input).slice (offset).map (x => this.extractEntryMetadata (x)) + } + + /* new StackTracey (array) */ + + if (Array.isArray (input)) { + + if (isParseableSyntaxError) { + + const rawLines = nodeRequire ('util').inspect (originalInput).split ('\n') + , fileLine = rawLines[0].split (':') + , line = fileLine.pop () + , file = fileLine.join (':') + + if (file) { + input.unshift ({ + file: nixSlashes (file), + line: line, + column: (rawLines[2] || '').indexOf ('^') + 1, + sourceLine: rawLines[1], + callee: '(syntax error)', + syntaxError: true + }) + } + } + + this.items = input + + } else { + this.items = [] + } + } + + extractEntryMetadata (e) { + + const decomposedPath = this.decomposePath (e.file || '') + const fileRelative = decomposedPath[0] + const externalDomain = decomposedPath[1] + + return O.assign (e, { + + calleeShort: e.calleeShort || lastOf ((e.callee || '').split ('.')), + fileRelative: fileRelative, + fileShort: this.shortenPath (fileRelative), + fileName: lastOf ((e.file || '').split ('/')), + thirdParty: this.isThirdParty (fileRelative, externalDomain) && !e.index, + externalDomain: externalDomain + }) + } + + shortenPath (relativePath) { + return relativePath.replace (/^node_modules\//, '') + .replace (/^webpack\/bootstrap\//, '') + .replace (/^__parcel_source_root\//, '') + } + + decomposePath (fullPath) { + let result = fullPath + + if (isBrowser) result = result.replace (pathRoot, '') + + const externalDomainMatch = result.match (/^(http|https)\:\/\/?([^\/]+)\/(.*)/) + const externalDomain = externalDomainMatch ? externalDomainMatch[2] : undefined + result = externalDomainMatch ? externalDomainMatch[3] : result + + if (!isBrowser) result = nodeRequire ('path').relative (pathRoot, result) + + return [ + nixSlashes(result).replace (/^.*\:\/\/?\/?/, ''), // cut webpack:/// and webpack:/ things + externalDomain + ] + } + + isThirdParty (relativePath, externalDomain) { + return externalDomain || + (relativePath[0] === '~') || // webpack-specific heuristic + (relativePath[0] === '/') || // external source + (relativePath.indexOf ('node_modules') === 0) || + (relativePath.indexOf ('webpack/bootstrap') === 0) + } + + rawParse (str) { + + const lines = (str || '').split ('\n') + + const entries = lines.map (line => { + + line = line.trim () + + let callee, fileLineColumn = [], native, planA, planB + + if ((planA = line.match (/at (.+) \(eval at .+ \((.+)\), .+\)/)) || // eval calls + (planA = line.match (/at (.+) \((.+)\)/)) || + ((line.slice (0, 3) !== 'at ') && (planA = line.match (/(.*)@(.*)/)))) { + + callee = planA[1] + native = (planA[2] === 'native') + fileLineColumn = (planA[2].match (/(.*):(\d+):(\d+)/) || + planA[2].match (/(.*):(\d+)/) || []).slice (1) + + } else if ((planB = line.match (/^(at\s+)*(.+):(\d+):(\d+)/) )) { + fileLineColumn = (planB).slice (2) + + } else { + return undefined + } + + /* Detect things like Array.reduce + TODO: detect more built-in types */ + + if (callee && !fileLineColumn[0]) { + const type = callee.split ('.')[0] + if (type === 'Array') { + native = true + } + } + + return { + beforeParse: line, + callee: callee || '', + index: isBrowser && (fileLineColumn[0] === window.location.href), + native: native || false, + file: nixSlashes (fileLineColumn[0] || ''), + line: parseInt (fileLineColumn[1] || '', 10) || undefined, + column: parseInt (fileLineColumn[2] || '', 10) || undefined + } + }) + + return entries.filter (x => (x !== undefined)) + } + + withSourceAt (i) { + return this.items[i] && this.withSource (this.items[i]) + } + + withSourceAsyncAt (i) { + return this.items[i] && this.withSourceAsync (this.items[i]) + } + + withSource (loc) { + + if (this.shouldSkipResolving (loc)) { + return loc + + } else { + + let resolved = getSource (loc.file || '').resolve (loc) + + if (!resolved.sourceFile) { + return loc + } + + return this.withSourceResolved (loc, resolved) + } + } + + withSourceAsync (loc) { + + if (this.shouldSkipResolving (loc)) { + return Promise.resolve (loc) + + } else { + return getSource.async (loc.file || '') + .then (x => x.resolve (loc)) + .then (resolved => this.withSourceResolved (loc, resolved)) + .catch (e => this.withSourceResolved (loc, { error: e, sourceLine: '' })) + } + } + + shouldSkipResolving (loc) { + return loc.sourceFile || loc.error || (loc.file && loc.file.indexOf ('<') >= 0) // skip things like and stuff that was already fetched + } + + withSourceResolved (loc, resolved) { + + if (resolved.sourceFile && !resolved.sourceFile.error) { + resolved.file = nixSlashes (resolved.sourceFile.path) + resolved = this.extractEntryMetadata (resolved) + } + + if (resolved.sourceLine.includes ('// @hide')) { + resolved.sourceLine = resolved.sourceLine.replace ('// @hide', '') + resolved.hide = true + } + + if (resolved.sourceLine.includes ('__webpack_require__') || // webpack-specific heuristics + resolved.sourceLine.includes ('/******/ ({')) { + resolved.thirdParty = true + } + + return O.assign ({ sourceLine: '' }, loc, resolved) + } + + withSources () { + return this.map (x => this.withSource (x)) + } + + withSourcesAsync () { + return Promise.all (this.items.map (x => this.withSourceAsync (x))) + .then (items => new StackTracey (items)) + } + + mergeRepeatedLines () { + return new StackTracey ( + partition (this.items, e => e.file + e.line).map ( + group => { + return group.items.slice (1).reduce ((memo, entry) => { + memo.callee = (memo.callee || '') + ' → ' + (entry.callee || '') + memo.calleeShort = (memo.calleeShort || '') + ' → ' + (entry.calleeShort || '') + return memo + }, O.assign ({}, group.items[0])) + } + ) + ) + } + + clean () { + const s = this.withSources ().mergeRepeatedLines () + return s.filter (s.isClean.bind (s)) + } + + cleanAsync () { + return this.withSourcesAsync ().then (s => { + s = s.mergeRepeatedLines () + return s.filter (s.isClean.bind (s)) + }) + } + + isClean (entry, index) { + return (index === 0) || !(entry.thirdParty || entry.hide || entry.native) + } + + at (i) { + return O.assign ({ + + beforeParse: '', + callee: '', + index: false, + native: false, + file: '', + line: 0, + column: 0 + + }, this.items[i]) + } + + asTable (opts) { + + const maxColumnWidths = (opts && opts.maxColumnWidths) || this.maxColumnWidths () + + const trimEnd = (s, n) => s && ((s.length > n) ? (s.slice (0, n-1) + '…') : s) + const trimStart = (s, n) => s && ((s.length > n) ? ('…' + s.slice (-(n-1))) : s) + + const trimmed = this.map ( + e => [ + ('at ' + trimEnd (e.calleeShort, maxColumnWidths.callee)), + trimStart ((e.fileShort && (e.fileShort + ':' + e.line)) || '', maxColumnWidths.file), + trimEnd (((e.sourceLine || '').trim () || ''), maxColumnWidths.sourceLine) + ] + ) + + return asTable (trimmed.items) + } + + maxColumnWidths () { + return { + callee: 30, + file: 60, + sourceLine: 80 + } + } + + static resetCache () { + + getSource.resetCache () + getSource.async.resetCache () + } + + static locationsEqual (a, b) { + + return (a.file === b.file) && + (a.line === b.line) && + (a.column === b.column) + } +} + +/* Array methods + ------------------------------------------------------------------------ */ + +;['map', 'filter', 'slice', 'concat'].forEach (method => { + + StackTracey.prototype[method] = function (/*...args */) { // no support for ...args in Node v4 :( + return new StackTracey (this.items[method].apply (this.items, arguments)) + } +}) + +/* ------------------------------------------------------------------------ */ + +module.exports = StackTracey + -- cgit v1.2.3