Home General

showcase: debugging JavaScript code

Currently, it's quite painful to use JavaScript in LINQPad as there's no feedback on what's wrong with the code.
I've created a nuget package to address the issue:

https://github.com/vlad2048/LINQPadPlus
https://nuget.org/packages/LINQPadPlus/

Here's how a compilation error would look like:

There's more info on the readme. Also there's a linqpad-sample that goes through the different cases.
The async case is not quite done though, I can go into more detail if someone's interested.

Would this be a reasonable addition to LINQPad itself ?

Comments

  • This is amazing!

    I will link to this from the samples. Also, in LINQPad 9, I'll implement exception-handling for the inbuilt JavaScript execution methods - at least for compile-time errors and synchronous runtime errors. This is definitely a pain-point.

  • Cool, I thought you'd find this useful.
    Glad it's on your roadmap.

    Here's the rest of my thoughts in no particular order:

    • overall, this logic takes a while to get right (more insight comes from more usage)
    • I forbid returning an empty object from JS.Return to catch a non invoked function expression. This decision is debatable, but I found the error so easy to make
    • good xml doc strings can go a long way to improve usability of JS.Run / JS.Return
    • I think for the async case I would need to parse the javascript AST (there's some mature c# libs to do that) and wrap the async function bodies in try/catch + send a message. But there's lot of value to be had even without handling it.
    • improvement: highlight the JS error (line/column) in the exception ToDump
    • improvement (maybe?): remove the added boilerplate in the exception ToDump

    Also, may I have my first github star please?
    Comming from you would mean a lot, thanks.

  • edited June 4

    Done!

    You're right - getting the correct logic is tricky, and I have to be extremely careful not to do anything that could change functionality for existing users.

    So, for LINQPad 9, I've kept it simple and aimed for minimal disruption. This means it won't be a complete replacement for what you've done. I've improved the entry points, so instead of calling Util.InvokeScript with true and "eval", you now call Util.JS.Eval(string javaScript), or Util.JS.Run if there's no return value. (This won't conflict with your JS.* methods because it's a nested class in Util.) The old InvokeScript method is hidden, but will remain in place indefinitely for backward compatibility (there are similar changes on LINQPad's HtmlElement class). This change had to happen because in LINQPad 9, there's been a terminology change. "Queries" are now "Scripts", so a method called Util.InvokeScript to invoke JavaScript is confusing, to say the least. (Also, having to pass "eval" as a parameter has always felt yucky - it was a hangover from the original Trident implementation.) Also, Uti.JS.Eval now returns a string rather than an object - again, returning an object was a hangover from Trident.

    Exception-handling uses a try/catch, with the code inside an eval, so it can catch both syntax and runtime errors. However, I'm not planning to take a dependency on the V8 engine at this stage, so the line/column info is shown only for runtime errors. Async errors are handled via window.onerror, which posts back to the WPF side. Again, there's limited stack info, but it's much better what we have now.

    There will be an early LINQPad 9 beta in the next month or two. It's a major revision, with most of the UI rewritten in WPF.

  • Very nice, I like the API cleanup, try/catch inside eval and global error handler (I didn't think about these last 2).

    I'd say check window.onerror vs window.unhandledrejection, it seems the later one is the correct one to use for async errors.

  • I'd say check window.onerror vs window.unhandledrejection, it seems the later one is the correct one to use for async errors.

    Thanks - I'll add that one in, too.

Sign In or Register to comment.