Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_.template syntax errors too hard to debug #666

Closed
ianb opened this issue Jul 11, 2012 · 20 comments
Closed

_.template syntax errors too hard to debug #666

ianb opened this issue Jul 11, 2012 · 20 comments

Comments

@ianb
Copy link

ianb commented Jul 11, 2012

If you have a syntax error in your generated template, you just get an exception from var render = new Function(settings.variable || 'obj', '_', source); – not very helpful, and you can't view the source of the template.

I'm not quite sure what to do, though try/catch around that might help. The exception itself will always be kind of bad. So maybe:

try {
  var render = ...
} catch (e) {
  e.generatedSource = e;
  throw e;
}

And that would have to be documented, I guess, otherwise you'd never notice that. And I'm not sure if all errors can have attributes added to them. But... something would be helpful.

@braddunbar
Copy link
Collaborator

Hi @ianb! You're right, syntax errors from new Function(...) are hard to debug since you don't get a line number. However, two things have been done recently to help with this (in the latest version of underscore).

  1. Source Lines - Template source lines are now separated instead of munged into one. At the very least, this makes it much easier to debug the error from the console.
  2. Precompilation - Since it's now possible to precompile templates via _.template(...).source, you can precompile your templates server-side and send them to the browser as plain javascript. This means you'll get line numbers with the syntax error. Even if you can't precompile them server-side you can still debug the syntax error with a quick node script to compile the template.

Hope these help!

@ianb
Copy link
Author

ianb commented Jul 11, 2012

Note that syntax errors are a little different than runtime errors. I should have given an example: _.template('<% if x %>')

There's no successful template object created because just constructing the Function object fails.

lodash tried to address this in this commit: lodash/lodash@10886be

@braddunbar
Copy link
Collaborator

Ah. Yes, of course, though the first point still stands. :)

lodash tried to address this in this commit: lodash/lodash@10886be

Why is it helpful to defer throwing the error? It seems to me this would lead to silent template compilation failures.

@ianb
Copy link
Author

ianb commented Jul 11, 2012

lodash's change is not the one I'd have thought of, though in the particular case I encountered it would have been helpful. In cases where you aren't aggressively precompiling templates I think lodash's approach is sensible – deferring the error for a couple lines of code doesn't make it harder to debug. Annotating or rewriting the exception object is more what I'd expect.

Also as it currently stands the first point would be helpful if I could get my hands on the syntactically invalid generated code, but right now I can't.

@jdalton
Copy link
Contributor

jdalton commented Jul 11, 2012

@braddunbar

Why is it helpful to defer throwing the error?

This way the template and its source are debuggable. Normally, for non-syntax error related failures compiled templates that error when passed a data object, either through _.template(string, data) or deferred via _.template(string), have sourceURLs associated with them so devs can simply look them up in their console to see the compiled source.

It seems to me this would lead to silent template compilation failures.

Because errors are deferred until execution rather than creation it allows it to be debugged in the same way you suggested.

@braddunbar
Copy link
Collaborator

This way the template and its source are debuggable.

You mean that you can still do console.log(_.template('...').source) when the template has a syntax error?

@jdalton
Copy link
Contributor

jdalton commented Jul 11, 2012

@braddunbar

You mean that you can still do console.log(_.template('...').source) when the template has a syntax error?

Yap.

@braddunbar
Copy link
Collaborator

I see how that's handy, but it poses a problem when precompiling templates. The code below would spit out code with a syntax error without warning, which I think is undesirable.

// Logs code with a syntax error.
console.log(_.template('<% syntax error %>').source);

@jdalton
Copy link
Contributor

jdalton commented Jul 11, 2012

I see how that's handy, but it poses a problem when precompiling templates. The code below would spit out code with a syntax error without warning, which I think is undesirable.

They would be debugging it because it threw an error in the first place. The warning bells will have already been sounded.

@braddunbar
Copy link
Collaborator

I meant precompiling server-side before delivering to the browser, where the template would not be executed.

@jdalton
Copy link
Contributor

jdalton commented Jul 11, 2012

I meant precompiling server-side before delivering to the browser, where the template would not be executed.

If they precompile and use the .source to inline it for delivery then it will error on client. Then they will go debugging the template they just inlined on the server-side and will be able to.

I make heavy use of compiled and inlined templates during the runtime and build process of Lo-Dash. If I or any other dev runs into issues or annoyances with the safeguard I'll simply tweak it. I'm going to stick it out for now.

@ianb
Copy link
Author

ianb commented Jul 11, 2012

This is roughly what I'd propose: https://github.com/ianb/underscore/tree/add-source-to-template-exceptions

Documentation here would be important (but I'm not clear where that is), as no one will notice this exception.source attribute on their own.

@braddunbar
Copy link
Collaborator

@jdalton Ok, thanks for the info!

@ianb What situation causes errors when assigning e.source = source?

@ianb
Copy link
Author

ianb commented Jul 11, 2012

The try/catch around e.source = source is defensive programming – there's nothing I hate more than an exception in my exception handler, and I'm not sure how writable all possible exceptions may be.

@jashkenas
Copy link
Owner

Instead of attaching the garbled source, I've gone ahead and added the original body of the template to the error.

jashkenas added a commit that referenced this issue Aug 31, 2012
@ianb
Copy link
Author

ianb commented Aug 31, 2012

But I already have the original body, it's the argument I passed in. It's the generated source I have no access to. This change doesn't add any new information.

@jashkenas
Copy link
Owner

Ah, then I misunderstand the original problem. I thought you were having trouble figuring out which template was causing the syntax error. How does the generated source help you debug a template syntaxerror exactly?

jashkenas added a commit that referenced this issue Aug 31, 2012
jashkenas added a commit that referenced this issue Aug 31, 2012
… you have a SyntaxError in a _.template"

This reverts commit 4e6b147.
@ianb
Copy link
Author

ianb commented Aug 31, 2012

In part it's just another thing to stare at to try to figure out what's syntactically wrong. But I can also drop the generated source into an editor and get syntax feedback there, and I can see what the line numbers map to. As it stands, when I've gotten syntax errors in my templates the only approach I've found to fixing them is to look really hard at the complete template and try to see what I got wrong.

@jashkenas
Copy link
Owner

Alright -- I'm not sure if we should document it, because it seems like a really pessimal debugging technique ... but I also don't see the harm, and I can imagine it being useful when dealing with somebody else's template on deadline ;)

@ianb
Copy link
Author

ianb commented Aug 31, 2012

I only opened the bug because it happened to me, so there is at least anecdotal evidence of this being useful ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants