window.onerror 默认不捕获 eval、function 构造函数或 innerhtml 插入的 script 执行异常,除非全局同步执行且无沙箱隔离;推荐用 try/catch 包裹执行、改用 createelement 同步注入 script 到无 sandbox iframe 并监听其 onerror、或用 addeventlistener('error') 补充上报。

为什么 window.onerror 无法捕获编辑器内动态执行的脚本异常
直接给结论:window.onerror 默认**不捕获**通过 eval、Function 构造函数、或 innerHTML 插入含 <script></script> 标签后执行的代码抛出的异常——除非这些脚本在全局作用域同步执行且未被沙箱隔离。
HTML 编辑器(如 CodeMirror、Monaco、或自研富文本编辑器)里用户写的 JS,通常走的是以下任一路径:
- 用
eval(code)或new Function(code)()执行,此时错误堆栈属于“间接 eval”,window.onerror不触发 - 把
<script>...</script>插入到临时iframe或document.body,但若该 script 是异步加载/延迟执行,或 iframe 启用了sandbox,window.onerror也收不到 - 使用
Web Workers运行用户脚本,那错误必须监听worker.onerror,和主窗口无关
如何让动态脚本异常可被捕获(3 种实操路径)
核心思路:不让异常“逃出”可控作用域。推荐按优先级采用以下方式:
-
改用 try/catch 包裹执行逻辑:对
eval或Function调用加壳,捕获后手动上报try { new Function(userCode)(); } catch (e) { reportError({ message: e.message, stack: e.stack, source: 'user-script-eval' }); } -
重写 script 插入逻辑,强制同步 + 全局上下文:避免用
innerHTML插入 script,改用document.createElement('script')并设script.textContent = userCode,再 append 到一个无 sandbox 的临时 iframe 的head;同时在该 iframe 的window上绑定自己的onerror -
用
window.addEventListener('error', ...)替代window.onerror:它能捕获更多事件源(包括某些 script 加载失败),但对eval错误依然无效,仅作为补充
上报时必须补全的关键上下文字段
只传 e.message 和 e.stack 基本没法定位问题。用户脚本运行环境与普通页面差异大,需显式标注:
-
editorMode:当前是 HTML / JS / JSX 模式?影响解析方式 -
scriptOrigin:值为'eval'、'function-constructor'、'inline-script'或'iframe-body',明确异常来源路径 -
editorVersion:编辑器自身版本,用于判断是否已知 bug -
userCodeHash:对原始代码做md5或sha1,方便去重和关联复现
漏掉 scriptOrigin 会导致你完全分不清是用户代码错了,还是编辑器注入逻辑崩了。
容易被忽略的兼容性坑:iframe 的 document.domain 与跨域限制
如果编辑器用了 iframe 隔离用户脚本,又想在父页面统一收集错误,要注意:
- 若 iframe 的
src为空字符串或about:blank,且父页面有设置document.domain,iframe 内脚本报错时,父页面的window.onerror可能收不到(尤其在旧版 Safari 和 IE) - 若 iframe 是
src="data:text/html,...",Chrome 120+ 开始默认禁止其执行脚本,需显式加allow-scripts权限 - 更稳妥的做法:在 iframe 内部直接初始化错误监听,并用
postMessage上报,父页面监听message事件接收,绕过 domain 限制
这个环节一旦配置错,上报看起来“全量丢失”,其实只是错误卡在 iframe 里没出来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











