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

When exceptions occur in handler functions or helpers, call chunk.setError #267

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions lib/dust.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,11 @@ Chunk.prototype.map = function(callback) {

this.next = branch;
this.flushable = true;
callback(branch);
try {
callback(branch);
} catch(e) {
branch.setError(e);
}
return cursor;
};

Expand All @@ -365,7 +369,7 @@ Chunk.prototype.render = function(body, context) {
Chunk.prototype.reference = function(elem, context, auto, filters) {
if (typeof elem === "function") {
elem.isFunction = true;
// Changed the function calling to use apply with the current context to make sure
// Changed the function calling to use apply with the current context to make sure
// that "this" is wat we expect it to be inside the function
elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]);
if (elem instanceof Chunk) {
Expand All @@ -382,7 +386,11 @@ Chunk.prototype.reference = function(elem, context, auto, filters) {
Chunk.prototype.section = function(elem, context, bodies, params) {
// anonymous functions
if (typeof elem === "function") {
elem = elem.apply(context.current(), [this, context, bodies, params]);
try {
elem = elem.apply(context.current(), [this, context, bodies, params]);
} catch(e) {
return this.setError(e);
}
// functions that return chunks are assumed to have handled the body and/or have modified the chunk
// use that return value as the current chunk and go to the next method in the chain
if (elem instanceof Chunk) {
Expand All @@ -399,15 +407,15 @@ Chunk.prototype.section = function(elem, context, bodies, params) {

/*
Dust's default behavior is to enumerate over the array elem, passing each object in the array to the block.
When elem resolves to a value or object instead of an array, Dust sets the current context to the value
When elem resolves to a value or object instead of an array, Dust sets the current context to the value
and renders the block one time.
*/
//non empty array is truthy, empty array is falsy
if (dust.isArray(elem)) {
if (body) {
var len = elem.length, chunk = this;
if (len > 0) {
// any custom helper can blow up the stack
// any custom helper can blow up the stack
// and store a flattened context, guard defensively
if(context.stack.head) {
context.stack.head['$len'] = len;
Expand All @@ -423,15 +431,15 @@ Chunk.prototype.section = function(elem, context, bodies, params) {
context.stack.head['$len'] = undefined;
}
return chunk;
}
}
else if (skip) {
return skip(this, context);
}
}
}
// true is truthy but does not change context
else if (elem === true) {
if (body) {
if (body) {
return body(this, context);
}
}
Expand All @@ -445,7 +453,7 @@ Chunk.prototype.section = function(elem, context, bodies, params) {
// undefined are all falsy
} else if (skip) {
return skip(this, context);
}
}
return this;
};

Expand Down Expand Up @@ -515,7 +523,11 @@ Chunk.prototype.partial = function(elem, context, params) {
Chunk.prototype.helper = function(name, context, bodies, params) {
// handle invalid helpers, similar to invalid filters
if( dust.helpers[name]){
return dust.helpers[name](this, context, bodies, params);
try {
return dust.helpers[name](this, context, bodies, params);
} catch (e) {
return this.setError(e);
}
} else {
return this;
}
Expand Down
28 changes: 21 additions & 7 deletions test/jasmine-test/spec/coreTests.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var coreTests = [
{
{
name: "core tests",
tests: [
{
Expand Down Expand Up @@ -573,7 +573,7 @@ var coreTests = [
{
name: "using len in array reference Accessing",
source: "{#list3}{.[$len].idx}{/list3}",
context: { "list3": [
context: { "list3": [
[{"idx": "0"},
{"idx": "1"},
{"idx": "2"}],
Expand Down Expand Up @@ -704,7 +704,7 @@ var coreTests = [
}
]
},
{
{
name: "partial definitions",
tests: [
{
Expand Down Expand Up @@ -866,7 +866,7 @@ var coreTests = [
{
name: "inline partial/block tests",
tests: [
{
{
name: "blocks with dynamic keys",
source: ['{<title_A}',
'AAA',
Expand Down Expand Up @@ -1215,7 +1215,7 @@ var coreTests = [
name: "Dust syntax error. Error in Conditional",
source:["{?tags}",
"<ul>{~n}",
"{#tags}{~s}",
"{#tags}{~s}",
"<li>{#@$}</li>{~n}",
"{/tags}",
"</ul>",
Expand All @@ -1230,7 +1230,7 @@ var coreTests = [
name: "Dust syntax error. Error in Conditional's else",
source:["{?tags}",
"<ul>{~n}",
"{#tags}{~s}",
"{#tags}{~s}",
"<li>{.}</li>{~n}",
"{/tags}",
"</ul>",
Expand All @@ -1246,7 +1246,7 @@ var coreTests = [
name: "Dust syntax error. Error in Conditional without end tag",
source:["{?tags}",
"<ul>{~n}",
"{#tags}{~s}",
"{#tags}{~s}",
"<li>{.}</li>{~n}",
"{/tags}",
"</ul>",
Expand All @@ -1255,6 +1255,20 @@ var coreTests = [
context: {},
error: 'Expected end tag for tags but it was not found. At line : 8, column : 9',
message: "should test the errors message for Conditional without end tag."
},
{
name: "Helper syntax error. TypeError",
source:"{#hello/}",
context: {"hello":function() { var a; a.slice(1); }},
error: "Cannot call method 'slice' of undefined",
message: "should test helper syntax errors being handled gracefully"
},
{
name: "Helper syntax error. async TypeError",
source:"{#hello/}",
context: {"hello":function(chunk, context, bodies, params) { return chunk.map(function(chunk) { var a; a.slice(1); chunk.end(); })}},
error: "Cannot call method 'slice' of undefined",
message: "should test helper syntax errors inside an async block being handled gracefully"
}
]
},
Expand Down
13 changes: 7 additions & 6 deletions test/jasmine-test/spec/renderTestSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function render(test) {
try {
dust.loadSource(dust.compile(test.source, test.name, test.strip));
dust.render(test.name, test.context, function(err, output) {
expect(err).toBeNull();
if(err) throw err;
expect(test.expected).toEqual(output);
});
}
Expand All @@ -41,17 +41,18 @@ function stream(test) {
})
.on("error", function(err) {
output = err.message;
flag = true;
});
} catch(error) {
output = error.message;
flag= true;
flag = true;
}
});

waitsFor(function(){
return flag;
}, "the output", 500);

runs(function(){
if (test.error) {
expect(test.error || {} ).toEqual(output);
Expand Down Expand Up @@ -105,11 +106,11 @@ function pipe(test) {
flagTwo= true;
}
});

waitsFor(function(){
return flag && flagTwo;
}, "the output", 500);

runs(function(){
if (test.error) {
expect(test.error || {} ).toEqual(output);
Expand Down