/** * The following code is modified based on * https://github.com/webpack/webpack-dev-server * * MIT Licensed * Author Tobias Koppers @sokra * Copyright (c) JS Foundation and other contributors * https://github.com/webpack/webpack-dev-server/blob/main/LICENSE */ var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; // 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 './utils/ansiHTML'; 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; }; var replaceUsingRegExp = function (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.slice(replaceLastIndex, replaceMatch.index); } var replaceInput = replaceMatch[0]; replaceResult += macroReplacer(replaceInput); replaceLastIndex = replaceMatch.index + replaceInput.length; } while ((replaceMatch = macroRegExp.exec(macroText))); if (replaceLastIndex !== macroText.length) { replaceResult += macroText.slice(replaceLastIndex); } } else { replaceResult = macroText; } return replaceResult; }; var references = { '<': '<', '>': '>', '"': '"', "'": ''', '&': '&', }; 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; }); } /** * 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. */ function createMachine(_a, _b) { var states = _a.states, context = _a.context, initial = _a.initial; var actions = _b.actions; var currentState = initial; var currentContext = context; return { send: function (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 = __assign(__assign({}, currentContext), nextContextValue); } }); } } }, }; } var createOverlayMachine = function (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 () { return { messages: [], level: 'error', messageSource: 'build', }; }, appendMessages: function (context, event) { return { messages: context.messages.concat(event.messages), level: event.level || context.level, messageSource: event.type === 'RUNTIME_ERROR' ? 'runtime' : 'build', }; }, setMessages: function (context, event) { return { messages: event.messages, level: event.level || context.level, messageSource: event.type === 'RUNTIME_ERROR' ? 'runtime' : 'build', }; }, hideOverlay: hideOverlay, showOverlay: showOverlay, }, }); }; var parseErrorToStacks = function (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); }); } }; var listenToRuntimeError = function (callback) { window.addEventListener('error', callback); return function cleanup() { window.removeEventListener('error', callback); }; }; var listenToUnhandledRejection = function (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: '0px', left: '0px', right: '0px', bottom: '0px', width: '100vw', height: '100vh', border: 'none', 'z-index': 9999999999, }; var containerStyle = { position: 'fixed', boxSizing: 'border-box', left: '0px', top: '0px', right: '0px', bottom: '0px', 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: '0px', top: '0px', 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); var formatProblem = function (type, item) { var header = type === 'warning' ? 'WARNING' : 'ERROR'; var body = ''; if (typeof item === 'string') { body += item; } else { var file = item.file || ''; 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 (typeof item !== 'string' && Array.isArray(item.stack)) { item.stack.forEach(function (stack) { if (typeof stack === 'string') { body += "\r\n".concat(stack); } }); } return { header: header, body: body }; }; var createOverlay = function (options) { var iframeContainerElement; var containerElement; var headerElement; var onLoadQueue = []; var overlayTrustedTypesPolicy; function applyStyle(element, style) { Object.keys(style).forEach(function (prop) { element.style[prop] = style[prop]; }); } 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 (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 = (iframeContainerElement === null || iframeContainerElement === void 0 ? void 0 : iframeContainerElement.contentDocument).createElement('div'); containerElement = (iframeContainerElement === null || iframeContainerElement === void 0 ? void 0 : 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); (iframeContainerElement === null || iframeContainerElement === void 0 ? void 0 : iframeContainerElement.contentDocument).body.appendChild(contentElement); onLoadQueue.forEach(function (onLoad) { onLoad(contentElement); }); onLoadQueue = []; iframeContainerElement.onload = null; }; document.body.appendChild(iframeContainerElement); } 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). 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, __assign(__assign({}, msgStyle), { padding: '1rem 1rem 1.5rem 1rem' })); var typeElement = document.createElement('div'); var _a = formatProblem(type, message), header = _a.header, body = _a.body; typeElement.innerText = header; applyStyle(typeElement, msgTypeStyle); if (typeof message !== 'string' && 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); containerElement === null || containerElement === void 0 ? void 0 : containerElement.appendChild(entryElement); }); }, trustedTypesPolicyName); } var handleEscapeKey; var hideOverlayWithEscCleanup = function () { window.removeEventListener('keydown', handleEscapeKey); hide(); }; var overlayService = createOverlayMachine({ showOverlay: function (_a) { var _b = _a.level, level = _b === void 0 ? 'error' : _b, messages = _a.messages, messageSource = _a.messageSource; return show(level, messages, options.trustedTypesPolicyName, messageSource); }, hideOverlay: hideOverlayWithEscCleanup, }); /** * ESC key press to dismiss the overlay. */ handleEscapeKey = function (event) { if (event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27) { overlayService.send({ type: 'DISMISS' }); } }; window.addEventListener('keydown', handleEscapeKey); if (options.catchRuntimeError) { var handleError_1 = function (error, fallbackMessage) { var errorObject = error instanceof Error ? error : // @ts-expect-error error options new Error(error || fallbackMessage, { cause: error }); 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_1(error, message); }); listenToUnhandledRejection(function (promiseRejectionEvent) { var reason = promiseRejectionEvent.reason; handleError_1(reason, 'Unknown promise rejection reason'); }); } return overlayService; }; export { createOverlay, formatProblem };