Skip to content

Commit

Permalink
[base] Add less intrusive error handler (#1367)
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Jun 13, 2019
1 parent 93e6db6 commit c59c62a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 8 deletions.
72 changes: 72 additions & 0 deletions packages/@sanity/base/src/components/ErrorHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react'
import Snackbar from 'part:@sanity/components/snackbar/default'

const SANITY_ERROR_HANDLER = Symbol.for('SANITY_ERROR_HANDLER')

export default class ErrorHandler extends React.PureComponent {
state = {error: null}

constructor(props) {
super(props)

this.handleGlobalError = this.handleGlobalError.bind(this)
this.handleGlobalError.identity = SANITY_ERROR_HANDLER
}

componentDidMount() {
// Only store the original error handler if it wasn't a copy of _this_ error handler
if (window.onerror && window.onerror.identity !== SANITY_ERROR_HANDLER) {
this.originalErrorHandler = window.onerror
}

window.onerror = this.handleGlobalError
}

componentWillUnmount() {
window.onerror = this.originalErrorHandler || window.onerror
}

handleGlobalError = (msg, url, lineNo, columnNo, err) => {
// Certain events (ResizeObserver max loop threshold, for instance)
// only gives a _message_. We choose to ignore these events since
// they are usually not _fatal_
if (!err) {
return
}

// Certain errors should be ignored
if (
[
/unexpected token <$/i // Trying to load HTML as JS
].some(item => item.test(err.message))
) {
return
}

// eslint-disable-next-line no-console
console.error(err)
this.setState({error: err})
}

handleClose = () => {
this.setState({error: null})
}

render() {
const {error} = this.state
if (!error) {
return null
}

const message = __DEV__ ? `An error occured: ${error.message}` : 'An error occured'

return (
<Snackbar kind="error" action={{title: 'Close'}} onAction={this.handleClose} timeout={2500}>
<div>
<strong>{message}</strong>
</div>
<div>Check browser javascript console for details</div>
</Snackbar>
)
}
}
2 changes: 2 additions & 0 deletions packages/@sanity/base/src/components/SanityRoot.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from 'react'
import RootComponent from 'part:@sanity/base/root'
import VersionChecker from './VersionChecker'
import ErrorHandler from './ErrorHandler'
import styles from './styles/SanityRoot.css'

function SanityRoot() {
return (
<div className={styles.root}>
<ErrorHandler />
<RootComponent />
<VersionChecker />
</div>
Expand Down
9 changes: 1 addition & 8 deletions packages/@sanity/base/src/util/uncaughtErrorHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ function errHandler(msg, url, lineNo, columnNo, err) {
return
}
// Certain errors should be ignored
if ([
/unexpected token <$/i // Trying to load HTML as JS
].some(item => item.test(err.message))) {
return
}
var container = document.getElementById('sanity')
var wrapper = document.createElement('div')
wrapper.style.position = 'absolute'
Expand Down Expand Up @@ -69,4 +62,4 @@ export default () => `window.onerror = ${errHandler.toString()}`
*/

export default () =>
'/* Global error handler */ window.onerror = function(e,t,n,o,r){if(r&&![/unexpected token <$/i].some(e=>e.test(r.message))){var a=document.getElementById("sanity"),l=document.createElement("div");l.style.position="absolute",l.style.top="50%",l.style.left="50%",l.style.transform="translate(-50%, -50%)";var s=document.createElement("h1");s.innerText="Uncaught error";var d=document.createElement("pre"),i=document.createElement("code");d.style.fontSize="0.8em",d.style.opacity="0.7",d.style.overflow="auto",d.style.whiteSpace="pre-wrap",d.style.maxHeight="70vh";var c=r.stack&&r.stack.replace(r.message,"").replace(/^error: *\\n?/i,""),m=(r.stack?r.message:r.toString())+(r.stack?"\\n\\nStack:\\n\\n"+c:"")+"\\n\\n(Your browsers Developer Tools may contain more info)";i.textContent=m;var p=document.createElement("button");for(p.style.padding="0.8em 1em",p.style.marginTop="1em",p.style.border="none",p.style.backgroundColor="#303030",p.style.color="#fff",p.style.borderRadius="4px",p.onclick=function(){window.location.reload()},p.textContent="Reload",d.appendChild(i),l.appendChild(s),l.appendChild(d),l.appendChild(p);a.firstChild;)a.removeChild(a.firstChild);a.appendChild(l)}}'
'/* Global error handler */ window.onerror = function(e,t,n,o,r){if(r){var a=document.getElementById("sanity"),l=document.createElement("div");l.style.position="absolute",l.style.top="50%",l.style.left="50%",l.style.transform="translate(-50%, -50%)";var s=document.createElement("h1");s.innerText="Uncaught error";var d=document.createElement("pre"),i=document.createElement("code");d.style.fontSize="0.8em",d.style.opacity="0.7",d.style.overflow="auto",d.style.whiteSpace="pre-wrap",d.style.maxHeight="70vh";var c=r.stack&&r.stack.replace(r.message,"").replace(/^error: *\\n?/i,""),m=(r.stack?r.message:r.toString())+(r.stack?"\\n\\nStack:\\n\\n"+c:"")+"\\n\\n(Your browsers Developer Tools may contain more info)";i.textContent=m;var p=document.createElement("button");for(p.style.padding="0.8em 1em",p.style.marginTop="1em",p.style.border="none",p.style.backgroundColor="#303030",p.style.color="#fff",p.style.borderRadius="4px",p.onclick=function(){window.location.reload()},p.textContent="Reload",d.appendChild(i),l.appendChild(s),l.appendChild(d),l.appendChild(p);a.firstChild;)a.removeChild(a.firstChild);a.appendChild(l)}}'

0 comments on commit c59c62a

Please sign in to comment.