Files
cypress/packages/errors/src/stackUtils.ts
Tim Griesser 92eac2f67e feat: Error standardization (#20323)
* refactor: reworking client-side error shape

* feat: add the CodeFrame to baseerror

* consolidate baseError handling, type fixes

* Fix UNIFY-1164 w/ test cleanup to avoid intercepting

* fix types, cleanup based on review / Brian

* fix: imports / types / tests

* cleanup tests, fix TSError location, add reinitializeCypress mutation

* fix: show correct stack trace file name (#20410)

* Improve comments for regexes / TSError capture

* feat: Add codeframe to error, address PR comments

* update snapshot

* change codeframe impl, per Brian's request

* Attempt to fix test flake

Co-authored-by: ElevateBart <ledouxb@gmail.com>
Co-authored-by: Alejandro Estrada <estrada9166@hotmail.com>
2022-03-02 18:03:52 -05:00

66 lines
1.8 KiB
TypeScript

import _ from 'lodash'
import type { ErrorLike } from './errorTypes'
const stackLineRegex = /^\s*(at )?.*@?\(?.*\:\d+\:\d+\)?$/
type MessageLines = [string[], string[]] & {messageEnded?: boolean}
// returns tuple of [message, stack]
export const splitStack = (stack: string) => {
const lines = stack.split('\n')
return _.reduce(lines, (memo, line) => {
if (memo.messageEnded || stackLineRegex.test(line)) {
memo.messageEnded = true
memo[1].push(line)
} else {
memo[0].push(line)
}
return memo
}, [[], []] as MessageLines)
}
export const unsplitStack = (messageLines: string | string[], stackLines: string[]) => {
return _.castArray(messageLines).concat(stackLines).join('\n')
}
export const getStackLines = (stack: string) => {
const [, stackLines] = splitStack(stack)
return stackLines
}
/**
* Captures & returns the absolute path, line, and column from a stack trace line
*/
export const parseStackLine = (line: string): null | { absolute: string, line: number, column: number } => {
const stackLineCapture = /^\s*(?:at )?.*@?\((.*?)\:(\d+)\:(\d+)\)?$/
const result = stackLineCapture.exec(line)
if (!result?.[1]) {
return null
}
return { absolute: result[1], line: Number(result[2]), column: Number(result[3]) }
}
/**
* Takes the stack and returns only the lines that contain stack-frame like entries,
* matching the `stackLineRegex` above
*/
export const stackWithoutMessage = (stack: string) => {
return getStackLines(stack).join('\n')
}
export const replacedStack = (err: ErrorLike, newStack: string) => {
// if err already lacks a stack or we've removed the stack
// for some reason, keep it stackless
if (!err.stack) return err.stack
const errString = err.toString()
const stackLines = getStackLines(newStack)
return unsplitStack(errString, stackLines)
}