summaryrefslogtreecommitdiff
path: root/node_modules/stacktracey/stacktracey.js
diff options
context:
space:
mode:
authorakiyamn2023-09-24 23:22:21 +1000
committerakiyamn2023-09-24 23:22:21 +1000
commit4e87195739f2a5d9a05451b48773c8afdc680765 (patch)
tree9cba501844a4a11dcbdffc4050ed8189561c55ed /node_modules/stacktracey/stacktracey.js
downloadprice-tracker-worker-4e87195739f2a5d9a05451b48773c8afdc680765.tar.gz
price-tracker-worker-4e87195739f2a5d9a05451b48773c8afdc680765.zip
Initial commit (by create-cloudflare CLI)
Diffstat (limited to 'node_modules/stacktracey/stacktracey.js')
-rw-r--r--node_modules/stacktracey/stacktracey.js339
1 files changed, 339 insertions, 0 deletions
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 <anonymous> 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 || '<anonymous>') + ' → ' + (entry.callee || '<anonymous>')
+ memo.calleeShort = (memo.calleeShort || '<anonymous>') + ' → ' + (entry.calleeShort || '<anonymous>')
+ 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
+