Skip to content

Commit

Permalink
fix: fix the dll test case
Browse files Browse the repository at this point in the history
  • Loading branch information
harrytothemoon authored Aug 16, 2022
1 parent f921ef1 commit 9b2a083
Show file tree
Hide file tree
Showing 12 changed files with 346 additions and 166 deletions.
13 changes: 7 additions & 6 deletions packages/error-overlay/package.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
{
"name": "@shuvi/error-overlay",
"version": "1.0.0-rc.4",
"main": "lib/index.js",
"main": "umd/index.js",
"files": [
"lib",
"esm",
"umd"
],
"scripts": {
"dev": "run-p watch:*",
"dev": "pnpm run iframe-dev && run-p watch:*",
"iframe-dev": "cross-env NODE_ENV=development rollup -c rollup.config.iframe.js -w",
"watch:cjs": "tsc -p tsconfig.build.json -m commonjs --outDir lib -w",
"watch:esm": "tsc -p tsconfig.build.json -m esnext --outDir esm -w",
"watch:umd": "cross-env NODE_ENV=development rollup -c rollup.config.js -w",
"prebuild": "rimraf lib",
"build": "run-p build:*",
"build": "pnpm run iframe-prod && run-p build:*",
"iframe-prod": "cross-env NODE_ENV=production rollup -c rollup.config.iframe.js",
"build:cjs": "tsc -p tsconfig.build.json -m commonjs --outDir lib",
"build:ems": "tsc -p tsconfig.build.json -m esnext --outDir esm",
"build:umd": "cross-env NODE_ENV=production rollup -c rollup.config.js"
},
"engines": {
Expand All @@ -37,13 +36,15 @@
"tslib": "2.4.0"
},
"devDependencies": {
"@rollup/plugin-alias": "3.1.9",
"@rollup/plugin-commonjs": "22.0.2",
"@rollup/plugin-node-resolve": "13.3.0",
"@rollup/plugin-replace": "4.0.0",
"@types/babel__code-frame": "7.0.3",
"@types/react": "18.0.9",
"@types/react-dom": "18.0.6",
"rollup": "2.77.2",
"rollup-plugin-string": "3.0.0",
"rollup-plugin-typescript2": "0.32.1"
}
}
31 changes: 31 additions & 0 deletions packages/error-overlay/rollup.config.iframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from 'path';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import ts from 'rollup-plugin-typescript2';

const extensions = ['.js', '.ts', '.tsx', 'jsx'];

export default {
input: path.join(__dirname, 'src/iframeScript.tsx'),

plugins: [
replace({
preventAssignment: true,
values: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}
}),
commonjs(),
resolve({ extensions }),

ts({
tsconfig: path.join('./tsconfig.build.json'),
extensions
})
],
output: {
name: 'iframe-bundle',
file: path.join(__dirname, './lib/iframe-bundle.js')
}
};
14 changes: 13 additions & 1 deletion packages/error-overlay/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@ import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import replace from '@rollup/plugin-replace';
import ts from 'rollup-plugin-typescript2';
import alias from '@rollup/plugin-alias';
import { string } from 'rollup-plugin-string';

const extensions = ['.js', '.ts', '.tsx', 'jsx'];

export default {
input: path.join(__dirname, 'src/index.ts'),

plugins: [
alias({
entries: [
{
find: 'iframeScript',
replacement: path.resolve(__dirname, './lib/iframe-bundle.js')
}
]
}),
string({
include: path.resolve(__dirname, './lib/iframe-bundle.js')
}),
replace({
preventAssignment: true,
values: {
Expand All @@ -18,7 +31,6 @@ export default {
}),
commonjs(),
resolve({ extensions }),

ts({
tsconfig: path.join('./tsconfig.build.json'),
extensions
Expand Down
202 changes: 202 additions & 0 deletions packages/error-overlay/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import iframeScript from 'iframeScript';
import { parse } from 'stacktrace-parser';

import * as errorTypeHandler from './view/errorTypeHandler';
import {
TYPE_UNHANDLED_ERROR,
TYPE_UNHANDLED_REJECTION,
TYPE_BUILD_ERROR,
TYPE_BUILD_OK,
TYPE_REFRESH,
STACK_TRACE_LIMIT
} from './constants';

let isRegistered = false;
let stackTraceLimit: number | undefined = undefined;

let iframe: null | HTMLIFrameElement = null;
let isLoadingIframe: boolean = false;
let isIframeReady: boolean = false;
let errorType: errorTypeHandler.ErrorTypeEvent;

declare global {
interface Window {
__SHUVI_ERROR_OVERLAY_GLOBAL_HOOK__: string | {};
}
}

const iframeStyle = {
position: 'fixed',
top: '0',
left: '0',
width: '100%',
height: '100%',
border: 'none',
'z-index': 2147483647
};

function onUnhandledError(ev: ErrorEvent) {
const error = ev?.error;
if (!error || !(error instanceof Error) || typeof error.stack !== 'string') {
// A non-error was thrown, we don't have anything to show.
return;
}

errorType = {
type: TYPE_UNHANDLED_ERROR,
reason: error,
frames: parse(error.stack)
};
update();
}

function onUnhandledRejection(ev: PromiseRejectionEvent) {
const reason = ev?.reason;
if (
!reason ||
!(reason instanceof Error) ||
typeof reason.stack !== 'string'
) {
// A non-error was thrown, we don't have anything to show.
return;
}

errorType = {
type: TYPE_UNHANDLED_REJECTION,
reason: reason,
frames: parse(reason.stack)
};
update();
}

function startReportingRuntimeErrors({ onError }: { onError: () => void }) {
if (isRegistered) {
return;
}
isRegistered = true;

try {
const limit = Error.stackTraceLimit;
Error.stackTraceLimit = STACK_TRACE_LIMIT;
stackTraceLimit = limit;
} catch {}

window.addEventListener('error', ev => {
onError();
onUnhandledError(ev);
});
window.addEventListener('unhandledrejection', ev => {
onError();
onUnhandledRejection(ev);
});
}

function stopReportingRuntimeErrors() {
if (!isRegistered) {
return;
}
isRegistered = false;

if (stackTraceLimit !== undefined) {
try {
Error.stackTraceLimit = stackTraceLimit;
} catch {}
stackTraceLimit = undefined;
}

window.removeEventListener('error', onUnhandledError);
window.removeEventListener('unhandledrejection', onUnhandledRejection);
}

function onBuildOk() {
errorType = { type: TYPE_BUILD_OK };
update();
}

function onBuildError(message: string) {
errorType = { type: TYPE_BUILD_ERROR, message };
update();
}

function onRefresh() {
errorType = { type: TYPE_REFRESH };
}

function applyStyles(element: HTMLElement, styles: Object) {
element.setAttribute('style', '');
for (const key in styles) {
if (!Object.prototype.hasOwnProperty.call(styles, key)) {
continue;
}
//@ts-ignore
element.style[key] = styles[key];
}
}

function update() {
// Loading iframe can be either sync or async depending on the browser.
if (isLoadingIframe) {
// Iframe is loading.
// First render will happen soon--don't need to do anything.
return;
}
if (isIframeReady) {
// Iframe is ready.
// Just update it.
updateIframeContent();
return;
}
// We need to schedule the first render.
isLoadingIframe = true;
const loadingIframe = window.document.createElement('iframe');
applyStyles(loadingIframe, iframeStyle);
loadingIframe.onload = function () {
const iframeDocument = loadingIframe.contentDocument;
if (iframeDocument != null && iframeDocument.body != null) {
iframe = loadingIframe;
const script =
loadingIframe.contentWindow!.document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = iframeScript;
iframeDocument.body.appendChild(script);
}
};
const appDocument = window.document;
appDocument.body.appendChild(loadingIframe);
}

function updateIframeContent() {
if (!iframe) {
throw new Error('Iframe has not been created yet.');
}

//@ts-ignore
const isRendered = iframe.contentWindow!.updateContent(errorType);

if (!isRendered) {
window.document.body.removeChild(iframe);
iframe = null;
isIframeReady = false;
}
}

window.__SHUVI_ERROR_OVERLAY_GLOBAL_HOOK__ =
window.__SHUVI_ERROR_OVERLAY_GLOBAL_HOOK__ || {};

//@ts-ignore
window.__SHUVI_ERROR_OVERLAY_GLOBAL_HOOK__.iframeReady =
function iframeReady() {
isIframeReady = true;
isLoadingIframe = false;
updateIframeContent();
};

export { getErrorByType } from './view/helpers/getErrorByType';
export { getServerError } from './view/helpers/nodeStackFrames';
export {
onBuildError,
onBuildOk,
onRefresh,
startReportingRuntimeErrors,
stopReportingRuntimeErrors
};
Loading

0 comments on commit 9b2a083

Please sign in to comment.