Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-error-overlay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"eslint-plugin-import": "2.7.0",
"eslint-plugin-jsx-a11y": "5.1.1",
"eslint-plugin-react": "7.1.0",
"flow-bin": "0.52.0",
"flow-bin": "^0.54.0",
"jest": "20.0.4",
"jest-fetch-mock": "1.2.1"
},
Expand Down
12 changes: 11 additions & 1 deletion packages/react-error-overlay/src/components/Collapsible.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import React, { Component } from 'react';
import { black } from '../styles';

import type { Element as ReactElement } from 'react';

const _collapsibleStyle = {
color: black,
cursor: 'pointer',
Expand All @@ -35,7 +37,15 @@ const collapsibleExpandedStyle = {
marginBottom: '0.6em',
};

class Collapsible extends Component {
type Props = {|
children: ReactElement<any>[],
|};

type State = {|
collapsed: boolean,
|};

class Collapsible extends Component<Props, State> {
state = {
collapsed: true,
};
Expand Down
15 changes: 13 additions & 2 deletions packages/react-error-overlay/src/components/ErrorOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import React, { Component } from 'react';
import { black } from '../styles';

import type { Node as ReactNode } from 'react';

const overlayStyle = {
position: 'relative',
display: 'inline-flex',
Expand All @@ -31,10 +33,19 @@ const overlayStyle = {
color: black,
};

class ErrorOverlay extends Component {
type Props = {|
children: ReactNode,
shortcutHandler?: (eventKey: string) => void,
|};

type State = {|
collapsed: boolean,
|};

class ErrorOverlay extends Component<Props, State> {
iframeWindow: window = null;

getIframeWindow = (element: HTMLDivElement) => {
getIframeWindow = (element: ?HTMLDivElement) => {
if (element) {
const document = element.ownerDocument;
this.iframeWindow = document.defaultView;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import Header from '../components/Header';
import CodeBlock from '../components/CodeBlock';
import generateAnsiHTML from '../utils/generateAnsiHTML';

class CompileErrorContainer extends PureComponent {
type Props = {|
error: string,
|};

class CompileErrorContainer extends PureComponent<Props, void> {
render() {
const { error } = this.props;
return (
Expand Down
3 changes: 2 additions & 1 deletion packages/react-error-overlay/src/containers/RuntimeError.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
import React from 'react';
import Header from '../components/Header';
import StackTrace from './StackTrace';

import type { StackFrame } from '../utils/stack-frame';

const wrapperStyle = {
display: 'flex',
flexDirection: 'column',
};

type ErrorRecord = {|
export type ErrorRecord = {|
error: Error,
unhandledRejection: boolean,
contextSize: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,19 @@ import NavigationBar from '../components/NavigationBar';
import RuntimeError from './RuntimeError';
import Footer from '../components/Footer';

class RuntimeErrorContainer extends PureComponent {
import type { ErrorRecord } from './RuntimeError';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please always add newline before import types?

import x from 'x';
import y from 'y';

import type { z } from 'z';

// code


type Props = {|
errorRecords: ErrorRecord[],
close: () => void,
launchEditorEndpoint: ?string,
|};

type State = {|
currentIndex: number,
|};

class RuntimeErrorContainer extends PureComponent<Props, State> {
state = {
currentIndex: 0,
};
Expand Down Expand Up @@ -54,13 +66,14 @@ class RuntimeErrorContainer extends PureComponent {
return (
<ErrorOverlay shortcutHandler={this.shortcutHandler}>
<CloseButton close={close} />
{totalErrors > 1 &&
{totalErrors > 1 && (
<NavigationBar
currentError={this.state.currentIndex + 1}
totalErrors={totalErrors}
previous={this.previous}
next={this.next}
/>}
/>
)}
<RuntimeError
errorRecord={errorRecords[this.state.currentIndex]}
launchEditorEndpoint={this.props.launchEditorEndpoint}
Expand Down
45 changes: 30 additions & 15 deletions packages/react-error-overlay/src/containers/StackFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import CodeBlock from './StackFrameCodeBlock';
import { getPrettyURL } from '../utils/getPrettyURL';
import { darkGray } from '../styles';

import type { StackFrame as StackFrameType } from '../utils/stack-frame';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here (and below).


const linkStyle = {
fontSize: '0.9em',
marginBottom: '0.9em',
Expand Down Expand Up @@ -43,7 +45,19 @@ const toggleStyle = {
lineHeight: '1.5',
};

class StackFrame extends Component {
type Props = {|
frame: StackFrameType,
launchEditorEndpoint: ?string,
contextSize: number,
critical: boolean,
showCode: boolean,
|};

type State = {|
compiled: boolean,
|};

class StackFrame extends Component<Props, State> {
state = {
compiled: false,
};
Expand All @@ -54,43 +68,45 @@ class StackFrame extends Component {
}));
};

canOpenInEditor() {
getEndpointUrl() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's explicitly type this as : string | null.

if (!this.props.launchEditorEndpoint) {
return;
return null;
}
const { _originalFileName: sourceFileName } = this.props.frame;
// Unknown file
if (!sourceFileName) {
return false;
return null;
}
// e.g. "/path-to-my-app/webpack/bootstrap eaddeb46b67d75e4dfc1"
const isInternalWebpackBootstrapCode =
sourceFileName.trim().indexOf(' ') !== -1;
if (isInternalWebpackBootstrapCode) {
return false;
return null;
}
// Code is in a real file
return true;
return this.props.launchEditorEndpoint;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add || null here so that it falls back to explicit null for bad values.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why making the distinction between null and undefined?

}

openInEditor = () => {
if (!this.canOpenInEditor()) {
const endpointUrl = this.getEndpointUrl();
if (endpointUrl == null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we can use strict === null check here.

return;
}

const {
_originalFileName: sourceFileName,
_originalLineNumber: sourceLineNumber,
} = this.props.frame;
// Keep this in sync with react-error-overlay/middleware.js
fetch(
`${this.props.launchEditorEndpoint}?fileName=` +
`${endpointUrl}?fileName=` +
window.encodeURIComponent(sourceFileName) +
'&lineNumber=' +
window.encodeURIComponent(sourceLineNumber || 1)
).then(() => {}, () => {});
};

onKeyDown = (e: SyntheticKeyboardEvent) => {
onKeyDown = (e: SyntheticKeyboardEvent<>) => {
if (e.key === 'Enter') {
this.openInEditor();
}
Expand Down Expand Up @@ -152,12 +168,10 @@ class StackFrame extends Component {
}
}

const canOpenInEditor = this.canOpenInEditor();
const canOpenInEditor = this.getEndpointUrl() != null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

return (
<div>
<div>
{functionName}
</div>
<div>{functionName}</div>
<div style={linkStyle}>
<a
style={canOpenInEditor ? anchorStyle : null}
Expand All @@ -168,7 +182,7 @@ class StackFrame extends Component {
{url}
</a>
</div>
{codeBlockProps &&
{codeBlockProps && (
<span>
<a
onClick={canOpenInEditor ? this.openInEditor : null}
Expand All @@ -179,7 +193,8 @@ class StackFrame extends Component {
<button style={toggleStyle} onClick={this.toggleCompiled}>
{'View ' + (compiled ? 'source' : 'compiled')}
</button>
</span>}
</span>
)}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ import codeFrame from 'babel-code-frame';
type StackFrameCodeBlockPropsType = {|
lines: ScriptLine[],
lineNum: number,
columnNum: number,
columnNum: ?number,
contextSize: number,
main: boolean,
|};

function StackFrameCodeBlock(props: StackFrameCodeBlockPropsType) {
// Exact type workaround for spread operator.
// See: https://github.com/facebook/flow/issues/2405
type Exact<T> = $Shape<T>;

function StackFrameCodeBlock(props: Exact<StackFrameCodeBlockPropsType>) {
const { lines, lineNum, columnNum, contextSize, main } = props;
const sourceCode = [];
let whiteSpace = Infinity;
Expand Down
17 changes: 11 additions & 6 deletions packages/react-error-overlay/src/containers/StackTrace.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@ import Collapsible from '../components/Collapsible';
import { isInternalFile } from '../utils/isInternalFile';
import { isBultinErrorName } from '../utils/isBultinErrorName';

import type { StackFrame as StackFrameType } from '../utils/stack-frame';

const traceStyle = {
fontSize: '1em',
flex: '0 1 auto',
minHeight: '0px',
overflow: 'auto',
};

class StackTrace extends Component {
type Props = {|
stackFrames: StackFrameType[],
errorName: string,
contextSize: number,
launchEditorEndpoint: ?string,
|};

class StackTrace extends Component<Props> {
renderFrames() {
const {
stackFrames,
Expand Down Expand Up @@ -84,11 +93,7 @@ class StackTrace extends Component {
}

render() {
return (
<div style={traceStyle}>
{this.renderFrames()}
</div>
);
return <div style={traceStyle}>{this.renderFrames()}</div>;
}
}

Expand Down
3 changes: 2 additions & 1 deletion packages/react-error-overlay/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

/* @flow */
import React from 'react';
import type { Element } from 'react';
import ReactDOM from 'react-dom';
import CompileErrorContainer from './containers/CompileErrorContainer';
import RuntimeErrorContainer from './containers/RuntimeErrorContainer';
Expand All @@ -27,7 +28,7 @@ type RuntimeReportingOptions = {|
let iframe: null | HTMLIFrameElement = null;
let isLoadingIframe: boolean = false;

let renderedElement: null | React.Element<any> = null;
let renderedElement: null | Element<any> = null;
let currentBuildError: null | string = null;
let currentRuntimeErrorRecords: Array<ErrorRecord> = [];
let currentRuntimeErrorOptions: null | RuntimeReportingOptions = null;
Expand Down
5 changes: 4 additions & 1 deletion packages/react-error-overlay/src/utils/getSourceMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ class SourceMap {
}
}

function extractSourceMapUrl(fileUri: string, fileContents: string) {
function extractSourceMapUrl(
fileUri: string,
fileContents: string
): Promise<string> {
const regex = /\/\/[#@] ?sourceMappingURL=([^\s'"]+)\s*$/gm;
let match = null;
for (;;) {
Expand Down