The annoying fact is that only the global error handler will get the detailed script parsing errors when you use eval() or new Function(). If the error is caught by any exception handler, then there is no way to recover the detailed information, even if the handler re-throws it. So, you have to somehow arrange to execute your eval outside the scope of any of your exception handlers.
On Firefox, I had to diddle config settings so it would execute scripts in a local HTML file. Firefox also disagreed slightly on the column number, but that's likely just the vagaries of parser lookahead. Other than that, the outputs were essentially identical. I use the more general "new Function" rather than directly calling eval().
I tested this script with the latest (05/26/2023) versions of Firefox/Chrome/Edge:
<html>
<head>
</head>
<body>BODY</body>
<script>
function errorHandler(e){
const {lineno,colno} = event;
let line = script1.split('\n')[lineno-3];
console.log(line);
let marker = "-".repeat(colno-1)+"^";
console.log(marker);
console.log(event.message);
return true; // allow execution to continue
}
window.addEventListener('error', errorHandler, true);
let script1 = "let x = 5;\nx=.x;\n";
let script2 = "let y = 5;\ny=.y;\n";
let func;
func = new Function(script1);
try {
func = new Function(script2);
}catch(e){
console.log(e);
}
</script>
The outputs looked like this:
As you can see, the global error handler gets an event with a rich enough set of properties that it can display detailed information (including the text of the relevant line, if it has access to the script text). The exception handler only gets the less helpful pre-canned message.
What about copying the script to a 'script' node and temporarily inserting it into the document head? You don't get the control you get by using 'new Function'. For example, I want to treat my loadable scripts much like node modules. By using 'Function', I can both pass in information to the script (such as a 'require' function it can call to give controlled access to other information) and get information back (the last expression of the script is the return value of executing the newly created function).
Of course, you can hack around these limitations with global variables and it's fairly impossible to truly sandbox an eval()'ed script, but with such infinite scopes in JavaScript, I prefer to control the scope enough that the eval()'ed script is extremely unlikely to accidentally tread on anything else.
Edit 05/27/23:
Forgot to actually test the insert-script-node trick. On all three browsers, it does not provide detailed error info. So, AFAICT, the only way to get detailed error info from a dynamic script is to use eval() or new Function, and make sure the error gets to the global error handler without being caught with an exception handler.
eval
and the syntax error in evaled string are on the 2nd line. – Cytolysin