Files
create-react-app/packages/react-dev-utils/crashOverlay.js
Valerii Sorokobatko fe7b5c212b update to modern code style (#1738)
* mv create-react-app/index.js -> create-react-app/creteReactApp.js

* update to modern code style

* var -> cosnt

* set trailing-coma to es5 for prettier
2017-03-07 19:46:10 +00:00

936 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var codeFrame = require('babel-code-frame');
var ansiHTML = require('./ansiHTML');
var StackTraceResolve = require('stack-frame-resolver').default;
var CONTEXT_SIZE = 3;
var black = '#293238';
var darkGray = '#878e91';
var lightGray = '#fafafa';
var red = '#ce1126';
var lightRed = '#fccfcf';
var yellow = '#fbf5b4';
function getHead() {
return document.head || document.getElementsByTagName('head')[0];
}
var injectedCss = [];
// From: http://stackoverflow.com/a/524721/127629
function injectCss(css) {
var head = getHead();
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
head.appendChild(style);
injectedCss.push(style);
}
var css = [
'.cra-container {',
' padding-right: 15px;',
' padding-left: 15px;',
' margin-right: auto;',
' margin-left: auto;',
'}',
'',
'@media (min-width: 768px) {',
' .cra-container {',
' width: calc(750px - 6em);',
' }',
'}',
'',
'@media (min-width: 992px) {',
' .cra-container {',
' width: calc(970px - 6em);',
' }',
'}',
'',
'@media (min-width: 1200px) {',
' .cra-container {',
' width: calc(1170px - 6em);',
' }',
'}',
].join('\n');
var overlayStyle = {
position: 'fixed',
'box-sizing': 'border-box',
top: '1em',
left: '1em',
bottom: '1em',
right: '1em',
width: 'calc(100% - 2em)',
height: 'calc(100% - 2em)',
'border-radius': '3px',
'background-color': lightGray,
padding: '4rem',
'z-index': 1337,
'font-family': 'Consolas, Menlo, monospace',
color: black,
'white-space': 'pre-wrap',
overflow: 'auto',
'overflow-x': 'hidden',
'word-break': 'break-all',
'box-shadow': '0 0 6px 0 rgba(0, 0, 0, 0.5)',
'line-height': 1.5,
};
var hintsStyle = {
'font-size': '0.8em',
'margin-top': '-3em',
'margin-bottom': '3em',
'text-align': 'right',
color: darkGray,
};
var hintStyle = {
padding: '0.5em 1em',
cursor: 'pointer',
};
var closeButtonStyle = {
'font-size': '26px',
color: black,
padding: '0.5em 1em',
cursor: 'pointer',
position: 'absolute',
right: 0,
top: 0,
};
var additionalStyle = {
'margin-bottom': '1.5em',
'margin-top': '-4em',
};
var headerStyle = {
'font-size': '1.7em',
'font-weight': 'bold',
color: red,
};
var functionNameStyle = {
'margin-top': '1em',
'font-size': '1.2em',
};
var linkStyle = {
'font-size': '0.9em',
};
var anchorStyle = {
'text-decoration': 'none',
color: darkGray,
};
var traceStyle = {
'font-size': '1em',
};
var depStyle = {
'font-size': '1.2em',
};
var primaryErrorStyle = {
'background-color': lightRed,
};
var secondaryErrorStyle = {
'background-color': yellow,
};
var omittedFramesStyle = {
color: black,
'font-size': '0.9em',
margin: '1.5em 0',
cursor: 'pointer',
};
var preStyle = {
display: 'block',
padding: '0.5em',
'margin-top': '1.5em',
'margin-bottom': '0px',
'overflow-x': 'auto',
'font-size': '1.1em',
'white-space': 'pre',
};
var toggleStyle = {
'margin-bottom': '1.5em',
color: darkGray,
cursor: 'pointer',
};
var codeStyle = {
'font-family': 'Consolas, Menlo, monospace',
};
var hiddenStyle = {
display: 'none',
};
var groupStyle = {
'margin-left': '1em',
};
var _groupElemStyle = {
'background-color': 'inherit',
'border-color': '#ddd',
'border-width': '1px',
'border-radius': '4px',
'border-style': 'solid',
padding: '3px 6px',
cursor: 'pointer',
};
var groupElemLeft = Object.assign({}, _groupElemStyle, {
'border-top-right-radius': '0px',
'border-bottom-right-radius': '0px',
'margin-right': '0px',
});
var groupElemRight = Object.assign({}, _groupElemStyle, {
'border-top-left-radius': '0px',
'border-bottom-left-radius': '0px',
'margin-left': '-1px',
});
var footerStyle = {
'text-align': 'center',
color: darkGray,
};
function applyStyles(element, styles) {
element.setAttribute('style', '');
// Firefox can't handle const due to non-compliant implementation
// Revisit Jan 2016
// https://developer.mozilla.org/en-US/Firefox/Releases/51#JavaScript
// https://bugzilla.mozilla.org/show_bug.cgi?id=1101653
for (var key in styles) {
if (!styles.hasOwnProperty(key)) continue;
var val = styles[key];
if (typeof val === 'function') val = val();
element.style[key] = val.toString();
}
}
var overlayReference = null;
var additionalReference = null;
var capturedErrors = [];
var viewIndex = -1;
var frameSettings = [];
function consumeEvent(e) {
e.preventDefault();
e.target.blur();
}
function accessify(node) {
node.setAttribute('tabindex', 0);
node.addEventListener('keydown', function(e) {
var key = e.key, which = e.which, keyCode = e.keyCode;
if (key === 'Enter' || which === 13 || keyCode === 13) {
e.preventDefault();
e.target.click();
}
});
}
function renderAdditional() {
if (additionalReference.lastChild) {
additionalReference.removeChild(additionalReference.lastChild);
}
var text = ' ';
if (capturedErrors.length <= 1) {
additionalReference.appendChild(document.createTextNode(text));
return;
}
text = 'Errors ' + (viewIndex + 1) + ' of ' + capturedErrors.length;
var span = document.createElement('span');
span.appendChild(document.createTextNode(text));
var group = document.createElement('span');
applyStyles(group, groupStyle);
var left = document.createElement('button');
applyStyles(left, groupElemLeft);
left.addEventListener('click', function(e) {
consumeEvent(e);
switchError(-1);
});
left.appendChild(document.createTextNode('←'));
accessify(left);
var right = document.createElement('button');
applyStyles(right, groupElemRight);
right.addEventListener('click', function(e) {
consumeEvent(e);
switchError(1);
});
right.appendChild(document.createTextNode('→'));
accessify(right);
group.appendChild(left);
group.appendChild(right);
span.appendChild(group);
additionalReference.appendChild(span);
}
function removeNextBr(parent, component) {
while (component != null && component.tagName.toLowerCase() !== 'br') {
component = component.nextSibling;
}
if (component != null) {
parent.removeChild(component);
}
}
function absolutifyCode(component) {
var ccn = component.childNodes;
for (var index = 0; index < ccn.length; ++index) {
var c = ccn[index];
if (c.tagName.toLowerCase() !== 'span') continue;
var text = c.innerText.replace(/\s/g, '');
if (text !== '|^') continue;
c.style.position = 'absolute';
removeNextBr(component, c);
}
}
function sourceCodePre(sourceLines, lineNum, columnNum) {
var main = arguments.length > 3 && arguments[3] !== undefined
? arguments[3]
: false;
var sourceCode = [];
var whiteSpace = Infinity;
sourceLines.forEach(function(_ref2) {
var text = _ref2.text;
var m = text.match(/^\s*/);
if (text === '') return;
if (m && m[0]) {
whiteSpace = Math.min(whiteSpace, m[0].length);
} else {
whiteSpace = 0;
}
});
sourceLines.forEach(function(_ref3) {
var text = _ref3.text, line = _ref3.line;
if (isFinite(whiteSpace)) text = text.substring(whiteSpace);
sourceCode[line - 1] = text;
});
sourceCode = sourceCode.join('\n');
var ansiHighlight = codeFrame(
sourceCode,
lineNum,
columnNum - (isFinite(whiteSpace) ? whiteSpace : 0),
{
forceColor: true,
linesAbove: CONTEXT_SIZE,
linesBelow: CONTEXT_SIZE,
}
);
var htmlHighlight = ansiHTML(ansiHighlight);
var code = document.createElement('code');
code.innerHTML = htmlHighlight;
absolutifyCode(code);
applyStyles(code, codeStyle);
var ccn = code.childNodes;
for (var index = 0; index < ccn.length; ++index) {
var node = ccn[index];
var breakOut = false;
var ccn2 = node.childNodes;
for (var index2 = 0; index2 < ccn2.length; ++index2) {
var lineNode = ccn2[index2];
if (lineNode.innerText.indexOf(' ' + lineNum + ' |') === -1) continue;
applyStyles(node, main ? primaryErrorStyle : secondaryErrorStyle);
breakOut = true;
}
if (breakOut) break;
}
var pre = document.createElement('pre');
applyStyles(pre, preStyle);
pre.appendChild(code);
return pre;
}
function createHint(hint) {
var span = document.createElement('span');
span.appendChild(document.createTextNode(hint));
applyStyles(span, hintStyle);
return span;
}
function hintsDiv() {
var hints = document.createElement('div');
applyStyles(hints, hintsStyle);
var close = createHint('×');
close.addEventListener('click', function() {
unmount();
});
applyStyles(close, closeButtonStyle);
hints.appendChild(close);
return hints;
}
function frameDiv(functionName, url, internalUrl) {
var frame = document.createElement('div');
var frameFunctionName = document.createElement('div');
var cleanedFunctionName = void 0;
if (!functionName || functionName === 'Object.<anonymous>') {
cleanedFunctionName = '(anonymous function)';
} else {
cleanedFunctionName = functionName;
}
var cleanedUrl = url.replace('webpack://', '.');
if (internalUrl) {
applyStyles(
frameFunctionName,
Object.assign({}, functionNameStyle, depStyle)
);
} else {
applyStyles(frameFunctionName, functionNameStyle);
}
frameFunctionName.appendChild(document.createTextNode(cleanedFunctionName));
frame.appendChild(frameFunctionName);
var frameLink = document.createElement('div');
applyStyles(frameLink, linkStyle);
var frameAnchor = document.createElement('a');
applyStyles(frameAnchor, anchorStyle);
//frameAnchor.href = url
frameAnchor.appendChild(document.createTextNode(cleanedUrl));
frameLink.appendChild(frameAnchor);
frame.appendChild(frameLink);
return frame;
}
function getGroupToggle(omitsCount, omitBundle) {
var omittedFrames = document.createElement('div');
accessify(omittedFrames);
var text1 = document.createTextNode(
'\u25B6 ' + omitsCount + ' stack frames were collapsed.'
);
omittedFrames.appendChild(text1);
omittedFrames.addEventListener('click', function() {
var hide = text1.textContent.match(/▲/);
var list = document.getElementsByName('bundle-' + omitBundle);
for (var index = 0; index < list.length; ++index) {
var n = list[index];
if (hide) {
n.style.display = 'none';
} else {
n.style.display = '';
}
}
if (hide) {
text1.textContent = text1.textContent.replace(/▲/, '▶');
text1.textContent = text1.textContent.replace(/expanded/, 'collapsed');
} else {
text1.textContent = text1.textContent.replace(/▶/, '▲');
text1.textContent = text1.textContent.replace(/collapsed/, 'expanded');
}
});
applyStyles(omittedFrames, omittedFramesStyle);
return omittedFrames;
}
function insertBeforeBundle(parent, omitsCount, omitBundle, actionElement) {
var children = document.getElementsByName('bundle-' + omitBundle);
if (children.length < 1) return;
var first = children[0];
while (first.parentNode !== parent) {
first = first.parentNode;
}
var div = document.createElement('div');
accessify(div);
div.setAttribute('name', 'bundle-' + omitBundle);
var text = document.createTextNode(
'\u25BC ' + omitsCount + ' stack frames were expanded.'
);
div.appendChild(text);
div.addEventListener('click', function() {
return actionElement.click();
});
applyStyles(div, omittedFramesStyle);
div.style.display = 'none';
parent.insertBefore(div, first);
}
function traceFrame(
frameSetting,
frame,
critical,
omits,
omitBundle,
parentContainer,
lastElement
) {
var compiled = frameSetting.compiled;
var functionName = frame.functionName,
fileName = frame.fileName,
lineNumber = frame.lineNumber,
columnNumber = frame.columnNumber,
scriptLines = frame.scriptLines,
sourceFileName = frame.sourceFileName,
sourceLineNumber = frame.sourceLineNumber,
sourceColumnNumber = frame.sourceColumnNumber,
sourceLines = frame.sourceLines;
var url = void 0;
if (!compiled && sourceFileName) {
url = sourceFileName + ':' + sourceLineNumber;
if (sourceColumnNumber) url += ':' + sourceColumnNumber;
} else {
url = fileName + ':' + lineNumber;
if (columnNumber) url += ':' + columnNumber;
}
var needsHidden = false;
var internalUrl = isInternalFile(url, sourceFileName);
if (internalUrl) {
++omits.value;
needsHidden = true;
}
var collapseElement = null;
if (!internalUrl || lastElement) {
if (omits.value > 0) {
var omittedFrames = getGroupToggle(omits.value, omitBundle);
setTimeout(
(function() {
insertBeforeBundle.apply(undefined, arguments);
}).bind(
undefined,
parentContainer,
omits.value,
omitBundle,
omittedFrames
),
1
);
if (lastElement && internalUrl) {
collapseElement = omittedFrames;
} else {
parentContainer.appendChild(omittedFrames);
}
++omits.bundle;
}
omits.value = 0;
}
var elem = frameDiv(functionName, url, internalUrl);
if (needsHidden) {
applyStyles(elem, hiddenStyle);
elem.setAttribute('name', 'bundle-' + omitBundle);
}
var hasSource = false;
if (!internalUrl) {
if (compiled && scriptLines.length !== 0) {
elem.appendChild(
sourceCodePre(scriptLines, lineNumber, columnNumber, critical)
);
hasSource = true;
} else if (!compiled && sourceLines.length !== 0) {
elem.appendChild(
sourceCodePre(
sourceLines,
sourceLineNumber,
sourceColumnNumber,
critical
)
);
hasSource = true;
}
}
return { elem: elem, hasSource: hasSource, collapseElement: collapseElement };
}
function lazyFrame(parent, factory, lIndex) {
var fac = factory();
if (fac == null) return;
var hasSource = fac.hasSource,
elem = fac.elem,
collapseElement = fac.collapseElement;
var elemWrapper = document.createElement('div');
elemWrapper.appendChild(elem);
if (hasSource) {
(function() {
var compiledDiv = document.createElement('div');
accessify(compiledDiv);
applyStyles(compiledDiv, toggleStyle);
var o = frameSettings[lIndex];
var compiledText = document.createTextNode(
'View ' + (o && o.compiled ? 'source' : 'compiled')
);
compiledDiv.addEventListener('click', function() {
if (o) o.compiled = !o.compiled;
var next = lazyFrame(parent, factory, lIndex);
if (next != null) {
parent.insertBefore(next, elemWrapper);
parent.removeChild(elemWrapper);
}
});
compiledDiv.appendChild(compiledText);
elemWrapper.appendChild(compiledDiv);
})();
}
if (collapseElement != null) {
elemWrapper.appendChild(collapseElement);
}
return elemWrapper;
}
function traceDiv(resolvedFrames) {
var trace = document.createElement('div');
applyStyles(trace, traceStyle);
var index = 0;
var critical = true;
var omits = { value: 0, bundle: 1 };
resolvedFrames.forEach(function(frame) {
var lIndex = index++;
var elem = lazyFrame(
trace,
traceFrame.bind(
undefined,
frameSettings[lIndex],
frame,
critical,
omits,
omits.bundle,
trace,
index === resolvedFrames.length
),
lIndex
);
if (elem == null) return;
critical = false;
trace.appendChild(elem);
});
//TODO: fix this
omits.value = 0;
return trace;
}
function footer() {
var div = document.createElement('div');
applyStyles(div, footerStyle);
div.appendChild(
document.createTextNode(
'This screen is visible only in development. It will not appear when the app crashes in production.'
)
);
div.appendChild(document.createElement('br'));
div.appendChild(
document.createTextNode(
'Open your browsers developer console to further inspect this error.'
)
);
return div;
}
function render(error, name, message, resolvedFrames) {
dispose();
frameSettings = resolvedFrames.map(function() {
return { compiled: false };
});
injectCss(css);
// Create overlay
var overlay = document.createElement('div');
applyStyles(overlay, overlayStyle);
overlay.appendChild(hintsDiv());
// Create container
var container = document.createElement('div');
container.className = 'cra-container';
overlay.appendChild(container);
// Create additional
additionalReference = document.createElement('div');
applyStyles(additionalReference, additionalStyle);
container.appendChild(additionalReference);
renderAdditional();
// Create header
var header = document.createElement('div');
applyStyles(header, headerStyle);
if (message.match(/^\w*:/)) {
header.appendChild(document.createTextNode(message));
} else {
header.appendChild(document.createTextNode(name + ': ' + message));
}
container.appendChild(header);
// Create trace
container.appendChild(traceDiv(resolvedFrames));
// Show message
container.appendChild(footer());
// Mount
document.body.appendChild((overlayReference = overlay));
}
function dispose() {
if (overlayReference === null) return;
document.body.removeChild(overlayReference);
overlayReference = null;
var head = getHead();
injectedCss.forEach(function(node) {
head.removeChild(node);
});
injectedCss = [];
}
function unmount() {
dispose();
capturedErrors = [];
viewIndex = -1;
}
function isInternalFile(url, sourceFileName) {
return url.indexOf('/~/') !== -1 ||
url.trim().indexOf(' ') !== -1 ||
!sourceFileName;
}
function renderError(index) {
viewIndex = index;
var _capturedErrors$index = capturedErrors[index],
error = _capturedErrors$index.error,
unhandledRejection = _capturedErrors$index.unhandledRejection,
resolvedFrames = _capturedErrors$index.resolvedFrames;
if (unhandledRejection) {
render(
error,
'Unhandled Rejection (' + error.name + ')',
error.message,
resolvedFrames
);
} else {
render(error, error.name, error.message, resolvedFrames);
}
}
function crash(error) {
var unhandledRejection = arguments.length > 1 && arguments[1] !== undefined
? arguments[1]
: false;
var sourceOverrides = arguments.length > 2 && arguments[2] !== undefined
? arguments[2]
: [];
if (module.hot) module.hot.decline();
StackTraceResolve(error, CONTEXT_SIZE)
.then(function(resolvedFrames) {
resolvedFrames = resolvedFrames.filter(function(_ref) {
var functionName = _ref.functionName;
return functionName.indexOf('__cra_proxy_console__') === -1;
});
var overrideCount = sourceOverrides.length,
frameCount = resolvedFrames.length;
var frameIndex = 0;
for (
var overrideIndex = 0;
overrideIndex < overrideCount;
++overrideIndex
) {
var tag = sourceOverrides[overrideIndex];
var shouldContinue = false;
for (; frameIndex < frameCount; ++frameIndex) {
var sourceFileName = resolvedFrames[frameIndex].sourceFileName;
if (sourceFileName == null) continue;
if (sourceFileName.indexOf('/' + tag.file) !== -1) {
var prevLineNumber = resolvedFrames[frameIndex].sourceLineNumber;
if (Math.abs(prevLineNumber - tag.lineNum) < CONTEXT_SIZE) {
resolvedFrames[frameIndex].sourceLineNumber = tag.lineNum;
}
shouldContinue = true;
break;
}
}
if (shouldContinue) continue;
break;
}
capturedErrors.push({
error: error,
unhandledRejection: unhandledRejection,
resolvedFrames: resolvedFrames,
});
if (overlayReference !== null)
renderAdditional();
else {
renderError((viewIndex = 0));
}
})
.catch(function(e) {
// This is another fail case (unlikely to happen)
// e.g. render(...) throws an error with provided arguments
console.log('Red box renderer error:', e);
unmount();
render(
null,
'Error',
'There is an error with red box. *Please* report this (see console).',
[]
);
});
}
function switchError(offset) {
try {
var nextView = viewIndex + offset;
if (nextView < 0 || nextView >= capturedErrors.length) return;
renderError(nextView);
} catch (e) {
console.log('Red box renderer error:', e);
unmount();
render(
null,
'Error',
'There is an error with red box. *Please* report this (see console).',
[]
);
}
}
window.onerror = function(messageOrEvent, source, lineno, colno, error) {
if (
error == null ||
!(error instanceof Error) ||
messageOrEvent.indexOf('Script error') !== -1
) {
crash(new Error(error || messageOrEvent)); // TODO: more helpful message
} else {
crash(error);
}
};
var promiseHandler = function promiseHandler(event) {
if (event != null && event.reason != null) {
var reason = event.reason;
if (reason == null || !(reason instanceof Error)) {
crash(new Error(reason), true);
} else {
crash(reason, true);
}
} else {
crash(new Error('Unknown event'), true);
}
};
window.addEventListener('unhandledrejection', promiseHandler);
var escapeHandler = function escapeHandler(event) {
var key = event.key, keyCode = event.keyCode, which = event.which;
if (key === 'Escape' || keyCode === 27 || which === 27) unmount();
else if (key === 'ArrowLeft' || keyCode === 37 || which === 37)
switchError(-1);
else if (key === 'ArrowRight' || keyCode === 39 || which === 39)
switchError(1);
};
window.addEventListener('keydown', escapeHandler);
try {
Error.stackTraceLimit = 50;
} catch (e) {
// Browser may not support this, we don't care.
}
// eslint-disable-next-line
var proxyConsole = function proxyConsole(type) {
var orig = console[type];
console[type] = function __cra_proxy_console__() {
var warning = [].slice.call(arguments).join(' ');
var nIndex = warning.indexOf('\n');
var message = warning;
if (nIndex !== -1) message = message.substring(0, nIndex);
var stack = warning
.substring(nIndex + 1)
.split('\n')
.filter(function(line) {
return line.indexOf('(at ') !== -1;
})
.map(function(line) {
var prefix = '(at ';
var suffix = ')';
line = line.substring(line.indexOf(prefix) + prefix.length);
line = line.substring(0, line.indexOf(suffix));
var parts = line.split(/[:]/g);
if (parts.length !== 2) return null;
var file = parts[0];
var lineNum = Number(parts[1]);
if (isNaN(lineNum)) return null;
return { file: file, lineNum: lineNum };
})
.filter(function(obj) {
return obj !== null;
});
var error = void 0;
try {
throw new Error(message);
} catch (e) {
error = e;
}
setTimeout(function() {
return crash(error, false, stack);
});
return orig.apply(this, arguments);
};
};
// proxyConsole('error');
if (module.hot) {
module.hot.dispose(function() {
unmount();
window.removeEventListener('unhandledrejection', promiseHandler);
window.removeEventListener('keydown', escapeHandler);
});
}