Determine the specific dynamically-added inline script element that caused an Uncaught Error (via `window.addEventListener(‘error’, …)`)

I’m building a dev tool that captures uncaught errors with window.addEventListener('error', ...) and provides more information about the error. I’d like to be able determine if the error came from a dynamically added inline script, and if so, show the line of code that caused the error (and perhaps a few surrounding lines).

I can get event.error.stack which looks like this in Chrome (but varies by browser):

TypeError: foo is not iterable
    at fn (<anonymous>:3:16)

The <anonymous> bit is what Chrome uses for a dynamically-added inline script, but of course there can be multiple dynamically-added inline scripts on the page.

I’m wondering if there is any reliable way to determine the script which caused an uncaught error. I’d hoped that ErrorEvent.srcElement or something like that would point to the script element that caused the error, but there’s no property available for what I want to achieve as far as I can see. (And I guess one problem is that the script element may have since been removed from the page.)

To be clear, I don’t actually need a reference to the element itself – I just need a reference to the full script text.

Example Code:

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

<script>
  let scriptEl = document.createElement("script");
  scriptEl.textContent = `function fn() { 
  let foo = {};
  for(let a of foo) {
    console.log(a);
  }
}`;
  document.head.append(scriptEl);

  setTimeout(() => {
    fn();
  }, 10)
</script>

Extra Context:

  • Since this is a dev tool, I don’t control the actual code within the inserted script. I just “inject” this uncaught error event handler.
  • That said, I can actually make small edits to the contents of script tags that are added to the page. But the edits would have to be very “light-weight”, since they wouldn’t be allowed to change the ‘userland’ code in any significant way.
  • I can also add code before the userland code – e.g. to overwrite .append and .appendChild prototypes so I can monitor scripts that are added to the page.
  • Note that it’s easy to catch SyntaxErrors, since they occur immediately after the script is inserted. But runtime errors can occur at any time.

Attempted Solution:

  • One hacky/unreliable approach might be to parse the line number from the stack, and then search the dynamically added inline scripts for variable names that were mentioned in the error message at the relevant line number. If there is only one script tag with that variable name at that line, then that might isolate the relevant script. But there are obviously a lot of ways that could go wrong, especially since we’re parsing error stacks, which IIUC don’t have any TC39 spec backing them.

(Note: I don’t think this question has a satisfying solution/answer, but I figure there’s a chance I missed something, and it also may become possible in the future, so it may be useful to have a question to track the possibility of this.)