为什么 `window.addEventListener("error", ...)` 有时会给出“脚本错误”。没有其他细节吗?

问题描述 投票:0回答:1

(我最初以为这只是一个 Chrome 错误,但我在 Firefox 中测试过,它有类似的奇怪行为,甚至在

event.message
中使用完全相同的“脚本错误。”字符串,所以我想知道这是否是一个与规范相关的问题。)

我对下面代码的直觉当然是每个测试(我故意在构造函数中输入无效值)应该在

ErrorEvent
处理程序中产生相同的
window.addEventListener("error", ...)
(只是具有不同的行号和内容),但正如该代码块的注释中所述,它们会产生不同的行为。

<script>
  window.addEventListener("error", function(e) {
    console.error("window error handler:", e);
  })
</script>

<!-- Note: This is just an immutable snapshot of https://codemirror.net/codemirror.js and note that the txt extension doesn't affect this issue - it occurs with js extension too. The txt was just because github doesn't allow uploading js files. -->
<script src="https://github.com/user-attachments/files/17729754/codemirror6-november-13-2024.txt"></script>

<script>
  let { EditorView } = CM["@codemirror/view"];
</script>

<script>
  new EditorView(null); // Example 1: just "Script error."
</script>

<script type="module">
  new EditorView(null); // Example 2: just "Script error."
</script>

<script type="module">
  await new Promise(r => setTimeout(r, 10));
  new EditorView(null); // Example 3: just "Script error."
</script>

<script>
  (async function() {
    new EditorView(null); // Example 4: no window error event at all??
  })();
</script>

<script type="module">
  let { EditorView } = await import("https://esm.sh/@codemirror/[email protected]");
  new EditorView(null); // Example 5: ✅ produces error event with the actual error attached 
</script>


<!-- note: this uses a data url, but i tested using an actual server to server this file and it's the same result -->
<script src="data:text/plain,window.foo=function(a){a.b.c}"></script>
<script>
  foo(1); // Example 6: ✅ produces error event with the actual error attached 
  // caveat: in firefox, specifically, this data URL version gives "Script error.", but substituting it with a server url version results in the same behavior as chrome.
  // chrome gives the 'correct' behavior for both cases.
</script>

备注:

  • 我最初认为这与模块脚本有关,但最后一个示例表明这不是原因。
  • 我想也许
    Example 4
    与需要
    window.addEventListener("unhandledrejection", ...)
    处理程序有关,但我尝试了,但它没有收到任何事件。
  • ErrorEvent
    还包括文件名属性,它给出了导致它的脚本(但不包括行号、堆栈等)

额外背景:

我正在构建一个开发人员工具,它可以挂钩页面上的错误事件,以帮助开发人员了解错误的原因/来源。我不控制页面上的代码,因此我需要能够获取错误详细信息,而无需重新编写代码。

因此,不幸的是,“您可以避免以 XYZ 形式编写代码/导入”,这对我来说不是一个解决方案。

javascript html
1个回答
0
投票

请注意,您必须在任何其他脚本运行之前附加事件侦听器,推迟其他脚本,以便它们在初始化程序之后运行(而不是并行)。

另请注意,错误事件具有作为原始错误的错误对象(如果可用,则具有适当的堆栈)。

请注意,在下面的示例中没有“脚本错误”,并且每个“错误对象”都有一个堆栈。

<script>
  const errorEventHandler = errorEvent =>
  {
    errorEvent.preventDefault();
    
    const error = errorEvent?.error;
    
    console.log
    (
      'Error Event:',
      {
        Message: errorEvent?.message,
        Cause: errorEvent?.cause,
        File: errorEvent?.fileName,
        Line: errorEvent?.lineNumber,
        Stack: errorEvent?.stack,
      }
    );
    console.log
    (
      'Error Object:',
      {
        Message: error?.message,
        Cause: error?.cause,
        File: error?.fileName,
        Line: error?.lineNumber,
        Stack: error?.stack,
      }
    );
    console.log();
  };
  
  console.clear();
  window.addEventListener("error", errorEventHandler);
</script>

<!-- Note: This is just an immutable snapshot of https://codemirror.net/codemirror.js and note that the txt extension doesn't affect this issue - it occurs with js extension too. The txt was just because github doesn't allow uploading js files. -->
<script src="https://github.com/user-attachments/files/17729754/codemirror6-november-13-2024.txt" defer></script>

<script defer>
  let { EditorView } = CM["@codemirror/view"];
</script>

<script defer>
  new EditorView(null); // Example 1: just "Script error."
</script>

<script type="module" defer>
  new EditorView(null); // Example 2: just "Script error."
</script>

<script type="module" defer>
  await new Promise(r => setTimeout(r, 10));
  new EditorView(null); // Example 3: just "Script error."
</script>

<script defer>
  (async function() {
    new EditorView(null); // Example 4: no window error event at all??
  })();
</script>

<script type="module" defer>
  let { EditorView } = await import("https://esm.sh/@codemirror/[email protected]");
  new EditorView(null); // Example 5: ✅ produces error event with the actual error attached 
</script>


<!-- note: this uses a data url, but i tested using an actual server to server this file and it's the same result -->
<script src="data:text/plain,window.foo=function(a){a.b.c}" defer></script>
<script defer>
  foo(1); // Example 6: ✅ produces error event with the actual error attached 
  // caveat: in firefox, specifically, this data URL version gives "Script error.", but substituting it with a server url version results in the same behavior as chrome.
  // chrome gives the 'correct' behavior for both cases.
</script>

© www.soinside.com 2019 - 2024. All rights reserved.