javascriptgoogle-chromegoogle-chrome-devtoolseval

JavaScript Eval: in case of error display a correct script reference link in console


If I eval a script with intentionally made mistakes I get an error log in console with a script reference link at the right side. For instance, here is the script:

my_script = 'const a = 2;\nconst b = a 2;';

eval(my_script)

Here is the console screenshot after execution:

console after execution

At the right corner you see this lovely script reference link that I adore and appreciate very much. The main reason for this appreciation is that by clicking on it I can view the script that caused error and even look at the exact place where the error occurred:

debugger after execution

But if I want to have some additional logic to happen upon error and therefore I add try/catch statement with this logic, I lose script reference and my lovely script reference link doesn't lead to my initial script anymore. Instead it leads to eval code itself. Here is the new script:

my_script = 'const a = 2;\nconst b = a 2;';

try {
    eval(my_script)    
} catch (e) {
    // first we do some additional logic like error type checking and etc
    // then we just log error so a user could view the erroneous script, the exact position of error and maybe make amends   
    console.error(e)
}

Here is what I see after executing it: console after second execution

As you can see, the trace consists only of 2 records - the initial code and the eval code, but the first one is not clickable. And here is what I see after clicking the only available script reference link: debugger after second execution, lost initial script reference

The debugger now shows me the eval code itself, not the initial script that is being evaluated

   

How to preserve script reference when evaluating an arbitrary script inside try/catch statement? Is there a way to catch eval error and still be able to view the actual script in chrome debugger?


Solution

  • In chromium based browsers, the argument of eval is put in a new file by the developer tools (through VM I guess). Same happens with JSON.parse, and other similar functions. This new file is called VM, from "virtual machine" followed by some digits.

    When you catch the error coming from eval, you override the default reportError that the browser has, as @kaiido is pointing. If you inspect the error, specially if you inspect the stack, you can see that, originally, you don't have reference to the VM file. This is because, as the docs of reportError says, you are preventing the error to be thrown, again, by other handlers:

    This ensures that an exception in one callback will not prevent others from being handled, while at the same time ensuring that stack trace information is still readily available for debugging at the top level.

    This is why, if you throw the error again in the catch of the promise (as @damzaky says), the error is shown as you wanted, handled by the default dev tools handler for errors. But apparently this is not happening with try...catch blocks, but this is something I haven't figured out.