615 lines
20 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.

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
// The error overlay is inspired (and mostly copied) from Create React App (https://github.com/facebookincubator/create-react-app)
// They, in turn, got inspired by webpack-hot-middleware (https://github.com/glenjamin/webpack-hot-middleware).
import ansiHTML from "ansi-html-community";
/**
* @type {(input: string, position: number) => string}
*/
var getCodePoint = String.prototype.codePointAt ? function (input, position) {
return input.codePointAt(position);
} : function (input, position) {
return (input.charCodeAt(position) - 0xd800) * 0x400 + input.charCodeAt(position + 1) - 0xdc00 + 0x10000;
};
/**
* @param {string} macroText
* @param {RegExp} macroRegExp
* @param {(input: string) => string} macroReplacer
* @returns {string}
*/
var replaceUsingRegExp = function replaceUsingRegExp(macroText, macroRegExp, macroReplacer) {
macroRegExp.lastIndex = 0;
var replaceMatch = macroRegExp.exec(macroText);
var replaceResult;
if (replaceMatch) {
replaceResult = "";
var replaceLastIndex = 0;
do {
if (replaceLastIndex !== replaceMatch.index) {
replaceResult += macroText.substring(replaceLastIndex, replaceMatch.index);
}
var replaceInput = replaceMatch[0];
replaceResult += macroReplacer(replaceInput);
replaceLastIndex = replaceMatch.index + replaceInput.length;
// eslint-disable-next-line no-cond-assign
} while (replaceMatch = macroRegExp.exec(macroText));
if (replaceLastIndex !== macroText.length) {
replaceResult += macroText.substring(replaceLastIndex);
}
} else {
replaceResult = macroText;
}
return replaceResult;
};
var references = {
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&apos;",
"&": "&amp;"
};
/**
* @param {string} text text
* @returns {string}
*/
function encode(text) {
if (!text) {
return "";
}
return replaceUsingRegExp(text, /[<>'"&]/g, function (input) {
var result = references[input];
if (!result) {
var code = input.length > 1 ? getCodePoint(input, 0) : input.charCodeAt(0);
result = "&#".concat(code, ";");
}
return result;
});
}
/**
* @typedef {Object} StateDefinitions
* @property {{[event: string]: { target: string; actions?: Array<string> }}} [on]
*/
/**
* @typedef {Object} Options
* @property {{[state: string]: StateDefinitions}} states
* @property {object} context;
* @property {string} initial
*/
/**
* @typedef {Object} Implementation
* @property {{[actionName: string]: (ctx: object, event: any) => object}} actions
*/
/**
* A simplified `createMachine` from `@xstate/fsm` with the following differences:
*
* - the returned machine is technically a "service". No `interpret(machine).start()` is needed.
* - the state definition only support `on` and target must be declared with { target: 'nextState', actions: [] } explicitly.
* - event passed to `send` must be an object with `type` property.
* - actions implementation will be [assign action](https://xstate.js.org/docs/guides/context.html#assign-action) if you return any value.
* Do not return anything if you just want to invoke side effect.
*
* The goal of this custom function is to avoid installing the entire `'xstate/fsm'` package, while enabling modeling using
* state machine. You can copy the first parameter into the editor at https://stately.ai/viz to visualize the state machine.
*
* @param {Options} options
* @param {Implementation} implementation
*/
function createMachine(_ref, _ref2) {
var states = _ref.states,
context = _ref.context,
initial = _ref.initial;
var actions = _ref2.actions;
var currentState = initial;
var currentContext = context;
return {
send: function send(event) {
var currentStateOn = states[currentState].on;
var transitionConfig = currentStateOn && currentStateOn[event.type];
if (transitionConfig) {
currentState = transitionConfig.target;
if (transitionConfig.actions) {
transitionConfig.actions.forEach(function (actName) {
var actionImpl = actions[actName];
var nextContextValue = actionImpl && actionImpl(currentContext, event);
if (nextContextValue) {
currentContext = _objectSpread(_objectSpread({}, currentContext), nextContextValue);
}
});
}
}
}
};
}
/**
* @typedef {Object} ShowOverlayData
* @property {'warning' | 'error'} level
* @property {Array<string | { moduleIdentifier?: string, moduleName?: string, loc?: string, message?: string }>} messages
* @property {'build' | 'runtime'} messageSource
*/
/**
* @typedef {Object} CreateOverlayMachineOptions
* @property {(data: ShowOverlayData) => void} showOverlay
* @property {() => void} hideOverlay
*/
/**
* @param {CreateOverlayMachineOptions} options
*/
var createOverlayMachine = function createOverlayMachine(options) {
var hideOverlay = options.hideOverlay,
showOverlay = options.showOverlay;
return createMachine({
initial: "hidden",
context: {
level: "error",
messages: [],
messageSource: "build"
},
states: {
hidden: {
on: {
BUILD_ERROR: {
target: "displayBuildError",
actions: ["setMessages", "showOverlay"]
},
RUNTIME_ERROR: {
target: "displayRuntimeError",
actions: ["setMessages", "showOverlay"]
}
}
},
displayBuildError: {
on: {
DISMISS: {
target: "hidden",
actions: ["dismissMessages", "hideOverlay"]
},
BUILD_ERROR: {
target: "displayBuildError",
actions: ["appendMessages", "showOverlay"]
}
}
},
displayRuntimeError: {
on: {
DISMISS: {
target: "hidden",
actions: ["dismissMessages", "hideOverlay"]
},
RUNTIME_ERROR: {
target: "displayRuntimeError",
actions: ["appendMessages", "showOverlay"]
},
BUILD_ERROR: {
target: "displayBuildError",
actions: ["setMessages", "showOverlay"]
}
}
}
}
}, {
actions: {
dismissMessages: function dismissMessages() {
return {
messages: [],
level: "error",
messageSource: "build"
};
},
appendMessages: function appendMessages(context, event) {
return {
messages: context.messages.concat(event.messages),
level: event.level || context.level,
messageSource: event.type === "RUNTIME_ERROR" ? "runtime" : "build"
};
},
setMessages: function setMessages(context, event) {
return {
messages: event.messages,
level: event.level || context.level,
messageSource: event.type === "RUNTIME_ERROR" ? "runtime" : "build"
};
},
hideOverlay: hideOverlay,
showOverlay: showOverlay
}
});
};
/**
*
* @param {Error} error
*/
var parseErrorToStacks = function parseErrorToStacks(error) {
if (!error || !(error instanceof Error)) {
throw new Error("parseErrorToStacks expects Error object");
}
if (typeof error.stack === "string") {
return error.stack.split("\n").filter(function (stack) {
return stack !== "Error: ".concat(error.message);
});
}
};
/**
* @callback ErrorCallback
* @param {ErrorEvent} error
* @returns {void}
*/
/**
* @param {ErrorCallback} callback
*/
var listenToRuntimeError = function listenToRuntimeError(callback) {
window.addEventListener("error", callback);
return function cleanup() {
window.removeEventListener("error", callback);
};
};
/**
* @callback UnhandledRejectionCallback
* @param {PromiseRejectionEvent} rejectionEvent
* @returns {void}
*/
/**
* @param {UnhandledRejectionCallback} callback
*/
var listenToUnhandledRejection = function listenToUnhandledRejection(callback) {
window.addEventListener("unhandledrejection", callback);
return function cleanup() {
window.removeEventListener("unhandledrejection", callback);
};
};
// Styles are inspired by `react-error-overlay`
var msgStyles = {
error: {
backgroundColor: "rgba(206, 17, 38, 0.1)",
color: "#fccfcf"
},
warning: {
backgroundColor: "rgba(251, 245, 180, 0.1)",
color: "#fbf5b4"
}
};
var iframeStyle = {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
width: "100vw",
height: "100vh",
border: "none",
"z-index": 9999999999
};
var containerStyle = {
position: "fixed",
boxSizing: "border-box",
left: 0,
top: 0,
right: 0,
bottom: 0,
width: "100vw",
height: "100vh",
fontSize: "large",
padding: "2rem 2rem 4rem 2rem",
lineHeight: "1.2",
whiteSpace: "pre-wrap",
overflow: "auto",
backgroundColor: "rgba(0, 0, 0, 0.9)",
color: "white"
};
var headerStyle = {
color: "#e83b46",
fontSize: "2em",
whiteSpace: "pre-wrap",
fontFamily: "sans-serif",
margin: "0 2rem 2rem 0",
flex: "0 0 auto",
maxHeight: "50%",
overflow: "auto"
};
var dismissButtonStyle = {
color: "#ffffff",
lineHeight: "1rem",
fontSize: "1.5rem",
padding: "1rem",
cursor: "pointer",
position: "absolute",
right: 0,
top: 0,
backgroundColor: "transparent",
border: "none"
};
var msgTypeStyle = {
color: "#e83b46",
fontSize: "1.2em",
marginBottom: "1rem",
fontFamily: "sans-serif"
};
var msgTextStyle = {
lineHeight: "1.5",
fontSize: "1rem",
fontFamily: "Menlo, Consolas, monospace"
};
// ANSI HTML
var colors = {
reset: ["transparent", "transparent"],
black: "181818",
red: "E36049",
green: "B3CB74",
yellow: "FFD080",
blue: "7CAFC2",
magenta: "7FACCA",
cyan: "C3C2EF",
lightgrey: "EBE7E3",
darkgrey: "6D7891"
};
ansiHTML.setColors(colors);
/**
* @param {string} type
* @param {string | { file?: string, moduleName?: string, loc?: string, message?: string; stack?: string[] }} item
* @returns {{ header: string, body: string }}
*/
var formatProblem = function formatProblem(type, item) {
var header = type === "warning" ? "WARNING" : "ERROR";
var body = "";
if (typeof item === "string") {
body += item;
} else {
var file = item.file || "";
// eslint-disable-next-line no-nested-ternary
var moduleName = item.moduleName ? item.moduleName.indexOf("!") !== -1 ? "".concat(item.moduleName.replace(/^(\s|\S)*!/, ""), " (").concat(item.moduleName, ")") : "".concat(item.moduleName) : "";
var loc = item.loc;
header += "".concat(moduleName || file ? " in ".concat(moduleName ? "".concat(moduleName).concat(file ? " (".concat(file, ")") : "") : file).concat(loc ? " ".concat(loc) : "") : "");
body += item.message || "";
}
if (Array.isArray(item.stack)) {
item.stack.forEach(function (stack) {
if (typeof stack === "string") {
body += "\r\n".concat(stack);
}
});
}
return {
header: header,
body: body
};
};
/**
* @typedef {Object} CreateOverlayOptions
* @property {string | null} trustedTypesPolicyName
* @property {boolean | (error: Error) => void} [catchRuntimeError]
*/
/**
*
* @param {CreateOverlayOptions} options
*/
var createOverlay = function createOverlay(options) {
/** @type {HTMLIFrameElement | null | undefined} */
var iframeContainerElement;
/** @type {HTMLDivElement | null | undefined} */
var containerElement;
/** @type {HTMLDivElement | null | undefined} */
var headerElement;
/** @type {Array<(element: HTMLDivElement) => void>} */
var onLoadQueue = [];
/** @type {TrustedTypePolicy | undefined} */
var overlayTrustedTypesPolicy;
/**
*
* @param {HTMLElement} element
* @param {CSSStyleDeclaration} style
*/
function applyStyle(element, style) {
Object.keys(style).forEach(function (prop) {
element.style[prop] = style[prop];
});
}
/**
* @param {string | null} trustedTypesPolicyName
*/
function createContainer(trustedTypesPolicyName) {
// Enable Trusted Types if they are available in the current browser.
if (window.trustedTypes) {
overlayTrustedTypesPolicy = window.trustedTypes.createPolicy(trustedTypesPolicyName || "webpack-dev-server#overlay", {
createHTML: function createHTML(value) {
return value;
}
});
}
iframeContainerElement = document.createElement("iframe");
iframeContainerElement.id = "webpack-dev-server-client-overlay";
iframeContainerElement.src = "about:blank";
applyStyle(iframeContainerElement, iframeStyle);
iframeContainerElement.onload = function () {
var contentElement = /** @type {Document} */
(/** @type {HTMLIFrameElement} */
iframeContainerElement.contentDocument).createElement("div");
containerElement = /** @type {Document} */
(/** @type {HTMLIFrameElement} */
iframeContainerElement.contentDocument).createElement("div");
contentElement.id = "webpack-dev-server-client-overlay-div";
applyStyle(contentElement, containerStyle);
headerElement = document.createElement("div");
headerElement.innerText = "Compiled with problems:";
applyStyle(headerElement, headerStyle);
var closeButtonElement = document.createElement("button");
applyStyle(closeButtonElement, dismissButtonStyle);
closeButtonElement.innerText = "×";
closeButtonElement.ariaLabel = "Dismiss";
closeButtonElement.addEventListener("click", function () {
// eslint-disable-next-line no-use-before-define
overlayService.send({
type: "DISMISS"
});
});
contentElement.appendChild(headerElement);
contentElement.appendChild(closeButtonElement);
contentElement.appendChild(containerElement);
/** @type {Document} */
(/** @type {HTMLIFrameElement} */
iframeContainerElement.contentDocument).body.appendChild(contentElement);
onLoadQueue.forEach(function (onLoad) {
onLoad(/** @type {HTMLDivElement} */contentElement);
});
onLoadQueue = [];
/** @type {HTMLIFrameElement} */
iframeContainerElement.onload = null;
};
document.body.appendChild(iframeContainerElement);
}
/**
* @param {(element: HTMLDivElement) => void} callback
* @param {string | null} trustedTypesPolicyName
*/
function ensureOverlayExists(callback, trustedTypesPolicyName) {
if (containerElement) {
containerElement.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML("") : "";
// Everything is ready, call the callback right away.
callback(containerElement);
return;
}
onLoadQueue.push(callback);
if (iframeContainerElement) {
return;
}
createContainer(trustedTypesPolicyName);
}
// Successful compilation.
function hide() {
if (!iframeContainerElement) {
return;
}
// Clean up and reset internal state.
document.body.removeChild(iframeContainerElement);
iframeContainerElement = null;
containerElement = null;
}
// Compilation with errors (e.g. syntax error or missing modules).
/**
* @param {string} type
* @param {Array<string | { moduleIdentifier?: string, moduleName?: string, loc?: string, message?: string }>} messages
* @param {string | null} trustedTypesPolicyName
* @param {'build' | 'runtime'} messageSource
*/
function show(type, messages, trustedTypesPolicyName, messageSource) {
ensureOverlayExists(function () {
headerElement.innerText = messageSource === "runtime" ? "Uncaught runtime errors:" : "Compiled with problems:";
messages.forEach(function (message) {
var entryElement = document.createElement("div");
var msgStyle = type === "warning" ? msgStyles.warning : msgStyles.error;
applyStyle(entryElement, _objectSpread(_objectSpread({}, msgStyle), {}, {
padding: "1rem 1rem 1.5rem 1rem"
}));
var typeElement = document.createElement("div");
var _formatProblem = formatProblem(type, message),
header = _formatProblem.header,
body = _formatProblem.body;
typeElement.innerText = header;
applyStyle(typeElement, msgTypeStyle);
if (message.moduleIdentifier) {
applyStyle(typeElement, {
cursor: "pointer"
});
// element.dataset not supported in IE
typeElement.setAttribute("data-can-open", true);
typeElement.addEventListener("click", function () {
fetch("/webpack-dev-server/open-editor?fileName=".concat(message.moduleIdentifier));
});
}
// Make it look similar to our terminal.
var text = ansiHTML(encode(body));
var messageTextNode = document.createElement("div");
applyStyle(messageTextNode, msgTextStyle);
messageTextNode.innerHTML = overlayTrustedTypesPolicy ? overlayTrustedTypesPolicy.createHTML(text) : text;
entryElement.appendChild(typeElement);
entryElement.appendChild(messageTextNode);
/** @type {HTMLDivElement} */
containerElement.appendChild(entryElement);
});
}, trustedTypesPolicyName);
}
var overlayService = createOverlayMachine({
showOverlay: function showOverlay(_ref3) {
var _ref3$level = _ref3.level,
level = _ref3$level === void 0 ? "error" : _ref3$level,
messages = _ref3.messages,
messageSource = _ref3.messageSource;
return show(level, messages, options.trustedTypesPolicyName, messageSource);
},
hideOverlay: hide
});
if (options.catchRuntimeError) {
/**
* @param {Error | undefined} error
* @param {string} fallbackMessage
*/
var handleError = function handleError(error, fallbackMessage) {
var errorObject = error instanceof Error ? error : new Error(error || fallbackMessage);
var shouldDisplay = typeof options.catchRuntimeError === "function" ? options.catchRuntimeError(errorObject) : true;
if (shouldDisplay) {
overlayService.send({
type: "RUNTIME_ERROR",
messages: [{
message: errorObject.message,
stack: parseErrorToStacks(errorObject)
}]
});
}
};
listenToRuntimeError(function (errorEvent) {
// error property may be empty in older browser like IE
var error = errorEvent.error,
message = errorEvent.message;
if (!error && !message) {
return;
}
// if error stack indicates a React error boundary caught the error, do not show overlay.
if (error && error.stack && error.stack.includes("invokeGuardedCallbackDev")) {
return;
}
handleError(error, message);
});
listenToUnhandledRejection(function (promiseRejectionEvent) {
var reason = promiseRejectionEvent.reason;
handleError(reason, "Unknown promise rejection reason");
});
}
return overlayService;
};
export { formatProblem, createOverlay };