Skip to content

Commit 822a5f6

Browse files
committed
Update compile-time error overlay to use react-error-overlay components
* Refactor react-error-overlay components to container and presentational components. * Make the compile-time error overlay a part of react-error-overlay package. * Use react-error-overlay as dependency in react-dev-utils to show compile-time errors.
1 parent 1e43349 commit 822a5f6

21 files changed

+444
-394
lines changed

packages/react-dev-utils/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"inquirer": "3.1.1",
4848
"is-root": "1.0.0",
4949
"opn": "5.1.0",
50+
"react-error-overlay": "^1.0.9",
5051
"recursive-readdir": "2.2.1",
5152
"shell-quote": "1.6.1",
5253
"sockjs-client": "1.1.4",

packages/react-dev-utils/webpackHotDevClient.js

Lines changed: 10 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -22,143 +22,10 @@ var SockJS = require('sockjs-client');
2222
var stripAnsi = require('strip-ansi');
2323
var url = require('url');
2424
var formatWebpackMessages = require('./formatWebpackMessages');
25-
var Entities = require('html-entities').AllHtmlEntities;
26-
var ansiHTML = require('./ansiHTML');
27-
var entities = new Entities();
28-
29-
function createOverlayIframe(onIframeLoad) {
30-
var iframe = document.createElement('iframe');
31-
iframe.id = 'react-dev-utils-webpack-hot-dev-client-overlay';
32-
iframe.src = 'about:blank';
33-
iframe.style.position = 'fixed';
34-
iframe.style.left = 0;
35-
iframe.style.top = 0;
36-
iframe.style.right = 0;
37-
iframe.style.bottom = 0;
38-
iframe.style.width = '100vw';
39-
iframe.style.height = '100vh';
40-
iframe.style.border = 'none';
41-
iframe.style.zIndex = 2147483647;
42-
iframe.onload = onIframeLoad;
43-
return iframe;
44-
}
45-
46-
function addOverlayDivTo(iframe) {
47-
// TODO: unify these styles with react-error-overlay
48-
iframe.contentDocument.body.style.margin = 0;
49-
iframe.contentDocument.body.style.maxWidth = '100vw';
50-
51-
var outerDiv = iframe.contentDocument.createElement('div');
52-
outerDiv.id = 'react-dev-utils-webpack-hot-dev-client-overlay-div';
53-
outerDiv.style.width = '100%';
54-
outerDiv.style.height = '100%';
55-
outerDiv.style.boxSizing = 'border-box';
56-
outerDiv.style.textAlign = 'center';
57-
outerDiv.style.backgroundColor = 'rgb(255, 255, 255)';
58-
59-
var div = iframe.contentDocument.createElement('div');
60-
div.style.position = 'relative';
61-
div.style.display = 'inline-flex';
62-
div.style.flexDirection = 'column';
63-
div.style.height = '100%';
64-
div.style.width = '1024px';
65-
div.style.maxWidth = '100%';
66-
div.style.overflowX = 'hidden';
67-
div.style.overflowY = 'auto';
68-
div.style.padding = '0.5rem';
69-
div.style.boxSizing = 'border-box';
70-
div.style.textAlign = 'left';
71-
div.style.fontFamily = 'Consolas, Menlo, monospace';
72-
div.style.fontSize = '11px';
73-
div.style.whiteSpace = 'pre-wrap';
74-
div.style.wordBreak = 'break-word';
75-
div.style.lineHeight = '1.5';
76-
div.style.color = 'rgb(41, 50, 56)';
77-
78-
outerDiv.appendChild(div);
79-
iframe.contentDocument.body.appendChild(outerDiv);
80-
return div;
81-
}
82-
83-
function overlayHeaderStyle() {
84-
return (
85-
'font-size: 2em;' +
86-
'font-family: sans-serif;' +
87-
'color: rgb(206, 17, 38);' +
88-
'white-space: pre-wrap;' +
89-
'margin: 0 2rem 0.75rem 0px;' +
90-
'flex: 0 0 auto;' +
91-
'max-height: 35%;' +
92-
'overflow: auto;'
93-
);
94-
}
95-
96-
var overlayIframe = null;
97-
var overlayDiv = null;
98-
var lastOnOverlayDivReady = null;
99-
100-
function ensureOverlayDivExists(onOverlayDivReady) {
101-
if (overlayDiv) {
102-
// Everything is ready, call the callback right away.
103-
onOverlayDivReady(overlayDiv);
104-
return;
105-
}
106-
107-
// Creating an iframe may be asynchronous so we'll schedule the callback.
108-
// In case of multiple calls, last callback wins.
109-
lastOnOverlayDivReady = onOverlayDivReady;
110-
111-
if (overlayIframe) {
112-
// We're already creating it.
113-
return;
114-
}
25+
var showCompileErrorOverlay = require('react-error-overlay')
26+
.showCompileErrorOverlay;
11527

116-
// Create iframe and, when it is ready, a div inside it.
117-
overlayIframe = createOverlayIframe(function onIframeLoad() {
118-
overlayDiv = addOverlayDivTo(overlayIframe);
119-
// Now we can talk!
120-
lastOnOverlayDivReady(overlayDiv);
121-
});
122-
123-
// Zalgo alert: onIframeLoad() will be called either synchronously
124-
// or asynchronously depending on the browser.
125-
// We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
126-
document.body.appendChild(overlayIframe);
127-
}
128-
129-
function showErrorOverlay(message) {
130-
ensureOverlayDivExists(function onOverlayDivReady(overlayDiv) {
131-
// TODO: unify this with our runtime overlay
132-
overlayDiv.innerHTML =
133-
'<div style="' +
134-
overlayHeaderStyle() +
135-
'">Failed to compile</div>' +
136-
'<pre style="' +
137-
'display: block; padding: 0.5em; margin-top: 0; ' +
138-
'margin-bottom: 0.5em; overflow-x: auto; white-space: pre-wrap; ' +
139-
'border-radius: 0.25rem; background-color: rgba(206, 17, 38, 0.05)">' +
140-
'<code style="font-family: Consolas, Menlo, monospace;">' +
141-
ansiHTML(entities.encode(message)) +
142-
'</code></pre>' +
143-
'<div style="' +
144-
'font-family: sans-serif; color: rgb(135, 142, 145); margin-top: 0.5rem; ' +
145-
'flex: 0 0 auto">' +
146-
'This error occurred during the build time and cannot be dismissed.</div>';
147-
});
148-
}
149-
150-
function destroyErrorOverlay() {
151-
if (!overlayDiv) {
152-
// It is not there in the first place.
153-
return;
154-
}
155-
156-
// Clean up and reset internal state.
157-
document.body.removeChild(overlayIframe);
158-
overlayDiv = null;
159-
overlayIframe = null;
160-
lastOnOverlayDivReady = null;
161-
}
28+
var destroyOverlay = null;
16229

16330
// Connect to WebpackDevServer via a socket.
16431
var connection = new SockJS(
@@ -209,7 +76,9 @@ function handleSuccess() {
20976
tryApplyUpdates(function onHotUpdateSuccess() {
21077
// Only destroy it when we're sure it's a hot update.
21178
// Otherwise it would flicker right before the reload.
212-
destroyErrorOverlay();
79+
if (destroyOverlay) {
80+
destroyOverlay();
81+
}
21382
});
21483
}
21584
}
@@ -251,7 +120,9 @@ function handleWarnings(warnings) {
251120
printWarnings();
252121
// Only destroy it when we're sure it's a hot update.
253122
// Otherwise it would flicker right before the reload.
254-
destroyErrorOverlay();
123+
if (destroyOverlay) {
124+
destroyOverlay();
125+
}
255126
});
256127
} else {
257128
// Print initial warnings immediately.
@@ -273,7 +144,7 @@ function handleErrors(errors) {
273144
});
274145

275146
// Only show the first error.
276-
showErrorOverlay(formatted.errors[0]);
147+
destroyOverlay = showCompileErrorOverlay(formatted.errors[0]);
277148

278149
// Also log them to the console.
279150
if (typeof console !== 'undefined' && typeof console.error === 'function') {

packages/react-error-overlay/.flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[ignore]
2+
.*/node_modules/eslint-plugin-jsx-a11y/.*
23

34
[include]
45
src/**/*.js

packages/react-error-overlay/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"anser": "1.2.5",
3535
"babel-code-frame": "6.22.0",
3636
"babel-runtime": "6.23.0",
37+
"html-entities": "^1.2.1",
3738
"react": "^15.5.4",
3839
"react-dev-utils": "^3.0.2",
3940
"react-dom": "^15.5.4",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
/* @flow */
11+
import React from 'react';
12+
import ReactDOM from 'react-dom';
13+
import CompileErrorContainer from './containers/CompileErrorContainer';
14+
import { mountOverlayIframe } from './utils/dom/mountOverlayIframe';
15+
16+
let container: HTMLDivElement | null = null;
17+
let iframeReference: HTMLIFrameElement | null = null;
18+
19+
function mount(callback) {
20+
iframeReference = mountOverlayIframe(containerDiv => {
21+
container = containerDiv;
22+
callback();
23+
});
24+
}
25+
26+
function unmount() {
27+
if (iframeReference === null) {
28+
return;
29+
}
30+
ReactDOM.unmountComponentAtNode(container);
31+
window.document.body.removeChild(iframeReference);
32+
iframeReference = null;
33+
container = null;
34+
}
35+
36+
function render(error: string) {
37+
ReactDOM.render(<CompileErrorContainer error={error} />, container);
38+
}
39+
40+
function showCompileErrorOverlay(error: string) {
41+
if (container == null) {
42+
mount(() => render(error));
43+
} else {
44+
render(error);
45+
}
46+
return unmount;
47+
}
48+
49+
export { showCompileErrorOverlay };

packages/react-error-overlay/src/components/CodeBlock.js

Lines changed: 4 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,7 @@
99

1010
/* @flow */
1111
import React from 'react';
12-
import { applyStyles } from '../utils/dom/css';
13-
import { absolutifyCaret } from '../utils/dom/absolutifyCaret';
14-
import type { ScriptLine } from '../utils/stack-frame';
15-
import {
16-
primaryErrorStyle,
17-
secondaryErrorStyle,
18-
redTransparent,
19-
yellowTransparent,
20-
} from '../styles';
21-
22-
import generateAnsiHtml from 'react-dev-utils/ansiHTML';
23-
24-
import codeFrame from 'babel-code-frame';
12+
import { redTransparent, yellowTransparent } from '../styles';
2513

2614
const _preStyle = {
2715
display: 'block',
@@ -48,76 +36,14 @@ const codeStyle = {
4836
};
4937

5038
type CodeBlockPropsType = {
51-
lines: ScriptLine[],
52-
lineNum: number,
53-
columnNum: number,
54-
contextSize: number,
5539
main: boolean,
40+
codeHTML: string,
5641
};
5742

5843
function CodeBlock(props: CodeBlockPropsType) {
59-
const { lines, lineNum, columnNum, contextSize, main } = props;
60-
const sourceCode = [];
61-
let whiteSpace = Infinity;
62-
lines.forEach(function(e) {
63-
const { content: text } = e;
64-
const m = text.match(/^\s*/);
65-
if (text === '') {
66-
return;
67-
}
68-
if (m && m[0]) {
69-
whiteSpace = Math.min(whiteSpace, m[0].length);
70-
} else {
71-
whiteSpace = 0;
72-
}
73-
});
74-
lines.forEach(function(e) {
75-
let { content: text } = e;
76-
const { lineNumber: line } = e;
77-
78-
if (isFinite(whiteSpace)) {
79-
text = text.substring(whiteSpace);
80-
}
81-
sourceCode[line - 1] = text;
82-
});
83-
const ansiHighlight = codeFrame(
84-
sourceCode.join('\n'),
85-
lineNum,
86-
columnNum == null ? 0 : columnNum - (isFinite(whiteSpace) ? whiteSpace : 0),
87-
{
88-
forceColor: true,
89-
linesAbove: contextSize,
90-
linesBelow: contextSize,
91-
}
92-
);
93-
const htmlHighlight = generateAnsiHtml(ansiHighlight);
94-
const code = document.createElement('code');
95-
code.innerHTML = htmlHighlight;
96-
absolutifyCaret(code);
97-
98-
const ccn = code.childNodes;
99-
// eslint-disable-next-line
100-
oLoop: for (let index = 0; index < ccn.length; ++index) {
101-
const node = ccn[index];
102-
const ccn2 = node.childNodes;
103-
for (let index2 = 0; index2 < ccn2.length; ++index2) {
104-
const lineNode = ccn2[index2];
105-
const text = lineNode.innerText;
106-
if (text == null) {
107-
continue;
108-
}
109-
if (text.indexOf(' ' + lineNum + ' |') === -1) {
110-
continue;
111-
}
112-
// $FlowFixMe
113-
applyStyles(node, main ? primaryErrorStyle : secondaryErrorStyle);
114-
// eslint-disable-next-line
115-
break oLoop;
116-
}
117-
}
44+
const preStyle = props.main ? primaryPreStyle : secondaryPreStyle;
45+
const codeBlock = { __html: props.codeHTML };
11846

119-
const preStyle = main ? primaryPreStyle : secondaryPreStyle;
120-
const codeBlock = { __html: code.innerHTML };
12147
return (
12248
<pre style={preStyle}>
12349
<code style={codeStyle} dangerouslySetInnerHTML={codeBlock} />

packages/react-error-overlay/src/components/Collapsible.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,9 @@ class Collapsible extends Component {
5757
collapsed ? collapsibleCollapsedStyle : collapsibleExpandedStyle
5858
}
5959
>
60-
{
61-
(collapsed ? '▶' : '▼') +
62-
` ${count} stack frames were ` +
63-
(collapsed ? 'collapsed.' : 'expanded.')
64-
}
60+
{(collapsed ? '▶' : '▼') +
61+
` ${count} stack frames were ` +
62+
(collapsed ? 'collapsed.' : 'expanded.')}
6563
</button>
6664
<div style={{ display: collapsed ? 'none' : 'block' }}>
6765
{this.props.children}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy