window.onerror无法捕获编辑器预览中动态执行的js异常,因eval/new function/iframe注入属于间接执行,受浏览器规范限制;必须用try/catch包裹执行、监听unhandledrejection、或通过同源iframe手动注入script并绑定onerror。

window.onerror 无法捕获 HTML 编辑器实时预览中动态执行的脚本异常,必须绕过“全局监听”幻想,直接控制执行上下文。
为什么 window.onerror 对编辑器预览脚本完全失效
HTML 编辑器(如 Monaco、CodeMirror 或自研富文本)里用户写的 JS,通常不是通过 <script src="..."></script> 加载的静态脚本,而是:
– 被 eval() 或 new Function() 执行;
– 或插入到 iframe 的 innerHTML 中再触发;
– 或在沙箱 iframe 里运行。
这些方式产生的错误属于“间接执行”,浏览器明确不触发 window.onerror。你看到控制台报错,但监听函数根本不会被调用——这不是配置问题,是规范限制。
必须用 try/catch 包裹 eval 或 Function 执行
这是最简单、最可靠、兼容性最好的第一道防线。不要指望“全局兜底”,得在执行那一刻就捕获。
- 所有用户代码执行入口必须加壳,例如:
try { const fn = new Function(userCode); fn(); } catch (e) { reportError({ message: e.message, stack: e.stack, source: 'preview-eval', lineno: 1, // 注意:Function 构造函数里无法获取真实行号,需额外解析 }); } - 避免直接
eval(userCode):它在严格模式下会抛出 SyntaxError 且更难定位;new Function()至少能统一作用域 - 如果用户代码含异步逻辑(
setTimeout、Promise),需额外补监听:window.addEventListener('unhandledrejection', ...)和window.addEventListener('error', ..., true)(仅对 iframe 内有效)
改用 createElement + 无 sandbox iframe 同步注入 script
若你坚持走 DOM 注入路径(比如想复现真实 script 标签行为),就不能用 innerHTML,而要手动构造并同步执行:
- 创建一个无
sandbox属性的临时 iframe:const iframe = document.createElement('iframe'); iframe.src = 'about:blank'; document.body.appendChild(iframe); - 往它的
head插入 script 元素:const script = iframe.contentDocument.createElement('script'); script.textContent = userCode; iframe.contentDocument.head.appendChild(script); - 在该 iframe 的
window上绑定自己的onerror:iframe.contentWindow.onerror = function(msg, url, line, col, error) { reportError({ message: msg, stack: error?.stack, source: 'preview-iframe' }); }; - 注意:iframe 必须同源(
src="about:blank"满足),否则contentWindow访问受限;启用sandbox会禁用onerror
别把 HTML 解析错误和 JS 错误混为一谈
用户在编辑器里写错 HTML(比如 <div><p>hello</p></div>
window.onerror、try/catch、DOMParser 全部无感。这类问题只能靠开发期工具拦截(如 html-validate CLI)或运行时检查极端 case(如 doc.body.children.length === 0)。
真正需要你动手捕获的,只有 JS 执行层错误——而它们从来不在“HTML 全局监听”覆盖范围内。漏掉这点,监控就从根上失焦。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











