import React, {Component, PropTypes} from 'react' import ReactDOM from 'react-dom' import style from './style.js' import ErrorStackParser from 'error-stack-parser' import assign from 'object-assign' import {isFilenameAbsolute, makeUrl, makeLinkText} from './lib' export class RedBoxError extends Component { static propTypes = { error: PropTypes.instanceOf(Error).isRequired, filename: PropTypes.string, editorScheme: PropTypes.string, useLines: PropTypes.bool, useColumns: PropTypes.bool, style: PropTypes.object, className: PropTypes.string, } static displayName = 'RedBoxError' static defaultProps = { useLines: true, useColumns: true } renderFrames (frames) { const {filename, editorScheme, useLines, useColumns} = this.props const {frame, file, linkToFile} = assign({}, style, this.props.style) return frames.map((f, index) => { let text let url if (index === 0 && filename && !isFilenameAbsolute(f.fileName)) { url = makeUrl(filename, editorScheme) text = makeLinkText(filename) } else { let lines = useLines ? f.lineNumber : null let columns = useColumns ? f.columnNumber : null url = makeUrl(f.fileName, editorScheme, lines, columns) text = makeLinkText(f.fileName, lines, columns) } return (
{f.functionName}
{text}
) }) } render () { const {error, className} = this.props const {redbox, message, stack, frame} = assign({}, style, this.props.style) let frames let parseError try { frames = ErrorStackParser.parse(error) } catch (e) { parseError = new Error('Failed to parse stack trace. Stack trace information unavailable.') } if (parseError) { frames = (
{parseError.message}
) } else { frames = this.renderFrames(frames) } return (
{error.name}: {error.message}
{frames}
) } } // "Portal" component for actual RedBoxError component to // render to (directly under body). Prevents bugs as in #27. export default class RedBox extends Component { static propTypes = { error: PropTypes.instanceOf(Error).isRequired } static displayName = 'RedBox' componentDidMount () { this.el = document.createElement('div') document.body.appendChild(this.el) this.renderRedBoxError() } componentDidUpdate () { this.renderRedBoxError() } componentWillUnmount () { ReactDOM.unmountComponentAtNode(this.el) document.body.removeChild(this.el) this.el = null } renderRedBoxError () { ReactDOM.render(, this.el) } render () { return null } }