Merge branch 'master' into tordev
This commit is contained in:
commit
048c27fa7e
|
@ -6,7 +6,7 @@ import copy from 'clipboard-copy'
|
||||||
import { LoggerContext } from './logger'
|
import { LoggerContext } from './logger'
|
||||||
import Button from 'react-bootstrap/Button'
|
import Button from 'react-bootstrap/Button'
|
||||||
import { useToast } from './toast'
|
import { useToast } from './toast'
|
||||||
|
import { decodeMinifiedStackTrace } from '@/lib/stacktrace'
|
||||||
class ErrorBoundary extends Component {
|
class ErrorBoundary extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -27,7 +27,7 @@ class ErrorBoundary extends Component {
|
||||||
getErrorDetails () {
|
getErrorDetails () {
|
||||||
let details = this.state.error.stack
|
let details = this.state.error.stack
|
||||||
if (this.state.errorInfo?.componentStack) {
|
if (this.state.errorInfo?.componentStack) {
|
||||||
details += `\n\nComponent stack:${this.state.errorInfo.componentStack}`
|
details += `\n\nComponent stack:\n ${this.state.errorInfo.componentStack}`
|
||||||
}
|
}
|
||||||
return details
|
return details
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,8 @@ const CopyErrorButton = ({ errorDetails }) => {
|
||||||
const toaster = useToast()
|
const toaster = useToast()
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
try {
|
try {
|
||||||
await copy(errorDetails)
|
const decodedDetails = await decodeMinifiedStackTrace(errorDetails)
|
||||||
|
await copy(decodedDetails)
|
||||||
toaster?.success?.('copied')
|
toaster?.success?.('copied')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { SourceMapConsumer } from 'source-map'
|
||||||
|
|
||||||
|
// FUN@FILE:LINE:COLUMN
|
||||||
|
const STACK_TRACE_LINE_REGEX = /^([A-Za-z0-9]*)@(.*):([0-9]+):([0-9]+)/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a minified stack trace using source maps
|
||||||
|
* @param {string} stack - the minified stack trace
|
||||||
|
* @param {Object<string, SourceMapConsumer>} [sourceMaps] - an object used to cache source maps
|
||||||
|
* @returns {Promise<string>} Decoded stack trace
|
||||||
|
*/
|
||||||
|
export async function decodeMinifiedStackTrace (stack, sourceMaps = {}) {
|
||||||
|
let decodedStack = ''
|
||||||
|
let decoded = false
|
||||||
|
for (const line of stack.split('\n')) {
|
||||||
|
try {
|
||||||
|
const stackLine = line.trim()
|
||||||
|
const stackLineParts = stackLine?.match(STACK_TRACE_LINE_REGEX)
|
||||||
|
if (stackLineParts) {
|
||||||
|
const [stackFile, stackLine, stackColumn] = stackLineParts.slice(2)
|
||||||
|
if (!stackFile || !stackLine || !stackColumn) throw new Error('Unsupported stack line')
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
!stackFile.startsWith(process.env.NEXT_PUBLIC_ASSET_PREFIX) &&
|
||||||
|
!stackFile.startsWith(process.env.NEXT_PUBLIC_URL)
|
||||||
|
) ||
|
||||||
|
!stackFile.endsWith('.js')
|
||||||
|
) throw new Error('Unsupported file url ' + stackFile)
|
||||||
|
const sourceMapUrl = stackFile + '.map'
|
||||||
|
if (!sourceMaps[sourceMapUrl]) {
|
||||||
|
sourceMaps[sourceMapUrl] = await new SourceMapConsumer(await fetch(sourceMapUrl).then(res => res.text()))
|
||||||
|
}
|
||||||
|
const sourceMapper = sourceMaps[sourceMapUrl]
|
||||||
|
const map = sourceMapper.originalPositionFor({
|
||||||
|
line: parseInt(stackLine),
|
||||||
|
column: parseInt(stackColumn)
|
||||||
|
})
|
||||||
|
const { source, name, line, column } = map
|
||||||
|
if (!source || line === undefined) throw new Error('Unsupported stack line')
|
||||||
|
decodedStack += `${name || ''}@${source}:${line}:${column}\n`
|
||||||
|
decoded = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Cannot decode stack line', e)
|
||||||
|
}
|
||||||
|
decodedStack += `${line}\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoded) {
|
||||||
|
decodedStack = `Decoded stacktrace:\n${decodedStack}\n\nOriginal stack trace:\n${stack}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return decodedStack
|
||||||
|
}
|
|
@ -86,6 +86,7 @@
|
||||||
"remove-markdown": "^0.5.5",
|
"remove-markdown": "^0.5.5",
|
||||||
"sass": "^1.79.5",
|
"sass": "^1.79.5",
|
||||||
"serviceworker-storage": "^0.1.0",
|
"serviceworker-storage": "^0.1.0",
|
||||||
|
"source-map": "^0.8.0-beta.0",
|
||||||
"textarea-caret": "^3.1.0",
|
"textarea-caret": "^3.1.0",
|
||||||
"tldts": "^6.1.51",
|
"tldts": "^6.1.51",
|
||||||
"tsx": "^4.19.1",
|
"tsx": "^4.19.1",
|
||||||
|
@ -18307,6 +18308,7 @@
|
||||||
"version": "0.8.0-beta.0",
|
"version": "0.8.0-beta.0",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
|
||||||
"integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
|
"integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"whatwg-url": "^7.0.0"
|
"whatwg-url": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
@ -18343,6 +18345,7 @@
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
|
||||||
"integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
|
"integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
@ -18350,12 +18353,14 @@
|
||||||
"node_modules/source-map/node_modules/webidl-conversions": {
|
"node_modules/source-map/node_modules/webidl-conversions": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
||||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
|
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/source-map/node_modules/whatwg-url": {
|
"node_modules/source-map/node_modules/whatwg-url": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
||||||
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
|
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash.sortby": "^4.7.0",
|
"lodash.sortby": "^4.7.0",
|
||||||
"tr46": "^1.0.1",
|
"tr46": "^1.0.1",
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
"remove-markdown": "^0.5.5",
|
"remove-markdown": "^0.5.5",
|
||||||
"sass": "^1.79.5",
|
"sass": "^1.79.5",
|
||||||
"serviceworker-storage": "^0.1.0",
|
"serviceworker-storage": "^0.1.0",
|
||||||
|
"source-map": "^0.8.0-beta.0",
|
||||||
"textarea-caret": "^3.1.0",
|
"textarea-caret": "^3.1.0",
|
||||||
"tldts": "^6.1.51",
|
"tldts": "^6.1.51",
|
||||||
"tsx": "^4.19.1",
|
"tsx": "^4.19.1",
|
||||||
|
|
Loading…
Reference in New Issue