Permalink
Browse files

begin implementing cleaner errors discussed in #16

  • Loading branch information...
devoidfury committed Nov 16, 2012
1 parent 3c6f0a5 commit ea5557a8953cd0d189e233689fb4fb29139e0861
Showing with 66 additions and 19 deletions.
  1. +2 −1 .gitignore
  2. +32 −9 src/environment.js
  3. +21 −0 src/lib.js
  4. +9 −7 src/parser.js
  5. +2 −2 tests/util.js
View
@@ -1,2 +1,3 @@
node_modules
-.#*
+.#*
+.idea
View
@@ -8,7 +8,13 @@ var runtime = require('./runtime');
var Frame = runtime.Frame;
var Environment = Object.extend({
- init: function(loaders, tags) {
+ init: function(loaders, tags, development) {
+ // The development flag determines the trace that'll be shown on errors.
+ // If set to true, returns the full trace from the error point,
+ // otherwise will return trace starting from Template.render
+ // (the full trace from within nunjucks may confuse developers using
+ // the library)
+ this.development = development;
if(!loaders) {
// The filesystem loader is only available client-side
if(builtin_loaders.FileSystemLoader) {
@@ -234,15 +240,32 @@ var Template = Object.extend({
},
render: function(ctx, frame) {
- if(!this.compiled) {
- this._compile();
- }
+ try {
+ if(!this.compiled) {
+ this._compile();
+ }
- var context = new Context(ctx || {}, this.blocks);
- return this.rootRenderFunc(this.env,
- context,
- frame || new Frame(),
- runtime);
+ var context = new Context(ctx || {}, this.blocks);
+
+ return this.rootRenderFunc(this.env,
+ context,
+ frame || new Frame(),
+ runtime);
+ } catch (e) {
+ if (e.Update) {
+ e.Update("(" + (this.path || "unknown path") + ")");
+ } else {
+ e.name = "Template Render Error - " + e.name;
+ e.message = "(" + (this.path || "unknown path") + ")\n " + (e.message || "");
+ }
+ if (!this.env.development) {
+ var old = e;
+ e = new Error(old.message);
+ e.name = old.name;
+ }
+
+ throw e;
+ }
},
isUpToDate: function() {
View
@@ -3,6 +3,27 @@ var ObjProto = Object.prototype;
var exports = module.exports = {};
+exports.TemplateError = function(message, lineno, colno) {
+
+ Error.captureStackTrace(this);
+
+ this.name = "Template render error";
+ this.message = message;
+ this.lineno = lineno;
+ this.colno = colno;
+
+ this.Update = function(path) {
+ var message = (path || " ");
+
+ if (this.lineno && this.colno)
+ message += ' [Line ' + this.lineno + ', Column ' + this.colno + ']\n ';
+
+ this.message = message + (this.message || '');
+ };
+};
+exports.TemplateError.prototype = Error.prototype;
+
+
exports.isFunction = function(obj) {
return ObjProto.toString.call(obj) == '[object Function]';
};
View
@@ -49,17 +49,15 @@ var Parser = Object.extend({
},
fail: function (msg, lineno, colno) {
- if((!lineno || !colno) && this.peekToken()) {
+ if((lineno === undefined || colno === undefined) && this.peekToken()) {
var tok = this.peekToken();
lineno = tok.lineno;
colno = tok.colno;
}
+ if (lineno !== undefined) lineno += 1;
+ if (colno !== undefined) colno += 1;
- if(lineno && colno) {
- msg = '[Line ' + (lineno + 1) + ', Column ' + (colno + 1) + '] ' + msg;
- }
-
- throw new Error(msg);
+ throw new lib.TemplateError(msg, lineno, colno);
},
skip: function(type) {
@@ -296,7 +294,11 @@ var Parser = Object.extend({
if(!(node.template instanceof nodes.Literal &&
lib.isString(node.template.value)) &&
!(node.template instanceof nodes.Symbol)) {
- this.fail('parseExtends: string or value expected');
+ this.fail(
+ 'parseExtends: string or value expected',
+ node.template.lineno,
+ node.template.colno
+ );
}
this.advanceAfterBlockEnd(tag.value);
View
@@ -3,12 +3,12 @@ var env = require('../src/environment');
var loaders = require('../src/node-loaders');
function render(str, ctx) {
- var e = new env.Environment(new loaders.FileSystemLoader('tests/templates'));
+ var e = new env.Environment(new loaders.FileSystemLoader('tests/templates'), null, true);
ctx = ctx || {};
var t = new env.Template(str, e);
return t.render(ctx);
}
module.exports = {
render: render
-};
+};

0 comments on commit ea5557a

Please sign in to comment.