From feef70e70fadca9a06eb71591117b2c31f7d89ab Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 12 Sep 2017 00:20:50 +0800 Subject: [PATCH] Updated react-error-overlay to latest Flow (0.54.0) (#3065) * Updated react-error-overlay to latest Flow (0.54.0) * Revert "Updated react-error-overlay to latest Flow (0.54.0)" This reverts commit 6deaffbdb0b2e7c72a7f4053a299f28db174383b. * Fixed unit tests. * Updated code as per code review. * Fixed code as per code review. * Updated the code as per review. --- packages/react-error-overlay/package.json | 2 +- .../src/components/Collapsible.js | 12 ++++++- .../src/components/ErrorOverlay.js | 15 ++++++-- .../src/containers/CompileErrorContainer.js | 6 +++- .../src/containers/RuntimeError.js | 3 +- .../src/containers/RuntimeErrorContainer.js | 14 +++++++- .../src/containers/StackFrame.js | 36 +++++++++++++------ .../src/containers/StackFrameCodeBlock.js | 8 +++-- .../src/containers/StackTrace.js | 11 +++++- packages/react-error-overlay/src/index.js | 3 +- .../src/utils/getSourceMap.js | 5 ++- 11 files changed, 93 insertions(+), 22 deletions(-) diff --git a/packages/react-error-overlay/package.json b/packages/react-error-overlay/package.json index 289f72126bf..11ee8589447 100644 --- a/packages/react-error-overlay/package.json +++ b/packages/react-error-overlay/package.json @@ -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", "rimraf": "^2.6.1" diff --git a/packages/react-error-overlay/src/components/Collapsible.js b/packages/react-error-overlay/src/components/Collapsible.js index 92f1de4295c..0954288130a 100644 --- a/packages/react-error-overlay/src/components/Collapsible.js +++ b/packages/react-error-overlay/src/components/Collapsible.js @@ -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', @@ -35,7 +37,15 @@ const collapsibleExpandedStyle = { marginBottom: '0.6em', }; -class Collapsible extends Component { +type Props = {| + children: ReactElement[], +|}; + +type State = {| + collapsed: boolean, +|}; + +class Collapsible extends Component { state = { collapsed: true, }; diff --git a/packages/react-error-overlay/src/components/ErrorOverlay.js b/packages/react-error-overlay/src/components/ErrorOverlay.js index 446105dad2e..2f706f2424b 100644 --- a/packages/react-error-overlay/src/components/ErrorOverlay.js +++ b/packages/react-error-overlay/src/components/ErrorOverlay.js @@ -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', @@ -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 { iframeWindow: window = null; - getIframeWindow = (element: HTMLDivElement) => { + getIframeWindow = (element: ?HTMLDivElement) => { if (element) { const document = element.ownerDocument; this.iframeWindow = document.defaultView; diff --git a/packages/react-error-overlay/src/containers/CompileErrorContainer.js b/packages/react-error-overlay/src/containers/CompileErrorContainer.js index a3e89fe591d..9eb8c029b32 100644 --- a/packages/react-error-overlay/src/containers/CompileErrorContainer.js +++ b/packages/react-error-overlay/src/containers/CompileErrorContainer.js @@ -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 { render() { const { error } = this.props; return ( diff --git a/packages/react-error-overlay/src/containers/RuntimeError.js b/packages/react-error-overlay/src/containers/RuntimeError.js index c64824137d2..b21360d5e30 100644 --- a/packages/react-error-overlay/src/containers/RuntimeError.js +++ b/packages/react-error-overlay/src/containers/RuntimeError.js @@ -11,6 +11,7 @@ import React from 'react'; import Header from '../components/Header'; import StackTrace from './StackTrace'; + import type { StackFrame } from '../utils/stack-frame'; const wrapperStyle = { @@ -18,7 +19,7 @@ const wrapperStyle = { flexDirection: 'column', }; -type ErrorRecord = {| +export type ErrorRecord = {| error: Error, unhandledRejection: boolean, contextSize: number, diff --git a/packages/react-error-overlay/src/containers/RuntimeErrorContainer.js b/packages/react-error-overlay/src/containers/RuntimeErrorContainer.js index 1e09724df9a..dafd2af27ad 100644 --- a/packages/react-error-overlay/src/containers/RuntimeErrorContainer.js +++ b/packages/react-error-overlay/src/containers/RuntimeErrorContainer.js @@ -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'; + +type Props = {| + errorRecords: ErrorRecord[], + close: () => void, + launchEditorEndpoint: ?string, +|}; + +type State = {| + currentIndex: number, +|}; + +class RuntimeErrorContainer extends PureComponent { state = { currentIndex: 0, }; diff --git a/packages/react-error-overlay/src/containers/StackFrame.js b/packages/react-error-overlay/src/containers/StackFrame.js index 1dfcbb4376a..9916623564a 100644 --- a/packages/react-error-overlay/src/containers/StackFrame.js +++ b/packages/react-error-overlay/src/containers/StackFrame.js @@ -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'; + const linkStyle = { fontSize: '0.9em', marginBottom: '0.9em', @@ -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 { state = { compiled: false, }; @@ -54,43 +68,45 @@ class StackFrame extends Component { })); }; - canOpenInEditor() { + getEndpointUrl(): 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 || null; } openInEditor = () => { - if (!this.canOpenInEditor()) { + const endpointUrl = this.getEndpointUrl(); + if (endpointUrl === null) { 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(); } @@ -152,7 +168,7 @@ class StackFrame extends Component { } } - const canOpenInEditor = this.canOpenInEditor(); + const canOpenInEditor = this.getEndpointUrl() !== null; return (
{functionName}
diff --git a/packages/react-error-overlay/src/containers/StackFrameCodeBlock.js b/packages/react-error-overlay/src/containers/StackFrameCodeBlock.js index 2ed685cff49..58a2c0d537c 100644 --- a/packages/react-error-overlay/src/containers/StackFrameCodeBlock.js +++ b/packages/react-error-overlay/src/containers/StackFrameCodeBlock.js @@ -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 = $Shape; + +function StackFrameCodeBlock(props: Exact) { const { lines, lineNum, columnNum, contextSize, main } = props; const sourceCode = []; let whiteSpace = Infinity; diff --git a/packages/react-error-overlay/src/containers/StackTrace.js b/packages/react-error-overlay/src/containers/StackTrace.js index 8d81cc9429e..8d4a487dc7b 100644 --- a/packages/react-error-overlay/src/containers/StackTrace.js +++ b/packages/react-error-overlay/src/containers/StackTrace.js @@ -14,6 +14,8 @@ 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', @@ -21,7 +23,14 @@ const traceStyle = { overflow: 'auto', }; -class StackTrace extends Component { +type Props = {| + stackFrames: StackFrameType[], + errorName: string, + contextSize: number, + launchEditorEndpoint: ?string, +|}; + +class StackTrace extends Component { renderFrames() { const { stackFrames, diff --git a/packages/react-error-overlay/src/index.js b/packages/react-error-overlay/src/index.js index 168baa7ef64..d44976713a6 100644 --- a/packages/react-error-overlay/src/index.js +++ b/packages/react-error-overlay/src/index.js @@ -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'; @@ -27,7 +28,7 @@ type RuntimeReportingOptions = {| let iframe: null | HTMLIFrameElement = null; let isLoadingIframe: boolean = false; -let renderedElement: null | React.Element = null; +let renderedElement: null | Element = null; let currentBuildError: null | string = null; let currentRuntimeErrorRecords: Array = []; let currentRuntimeErrorOptions: null | RuntimeReportingOptions = null; diff --git a/packages/react-error-overlay/src/utils/getSourceMap.js b/packages/react-error-overlay/src/utils/getSourceMap.js index 1d8405519bd..5c9e3aa9eb7 100644 --- a/packages/react-error-overlay/src/utils/getSourceMap.js +++ b/packages/react-error-overlay/src/utils/getSourceMap.js @@ -77,7 +77,10 @@ class SourceMap { } } -function extractSourceMapUrl(fileUri: string, fileContents: string) { +function extractSourceMapUrl( + fileUri: string, + fileContents: string +): Promise { const regex = /\/\/[#@] ?sourceMappingURL=([^\s'"]+)\s*$/gm; let match = null; for (;;) {