Skip to content

Commit

Permalink
Allow promise resolution in Dust global helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
sethkinast committed Mar 26, 2015
1 parent 519526f commit ebb9985
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 32 deletions.
9 changes: 7 additions & 2 deletions lib/dust.js
Original file line number Diff line number Diff line change
Expand Up @@ -803,11 +803,16 @@
};

Chunk.prototype.helper = function(name, context, bodies, params) {
var chunk = this;
var chunk = this,
ret;
// handle invalid helpers, similar to invalid filters
if(dust.helpers[name]) {
try {
return dust.helpers[name](chunk, context, bodies, params);
ret = dust.helpers[name](chunk, context, bodies, params);
if (dust.isThenable(ret)) {
return this.await(ret, context, bodies);
}
return ret;
} catch(err) {
dust.log('Error in helper `' + name + '`: ' + err.message, ERROR);
return chunk.setError(err);
Expand Down
23 changes: 19 additions & 4 deletions test/jasmine-test/spec/coreTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -832,11 +832,26 @@ var coreTests = [
},
{
name: "thenable deep section, traverse outside",
source: "Eventually my {#magic.ally}{prince} {delicious}{/magic.ally} will come",
context: { "prince": "Prince", "magic": new FalsePromise(null, {"ally": {"delicious": new FalsePromise(null, "Lucky Charms")} }) },
source: "Eventually my {#magic.ally}{prince} {delicious} {charms}{/magic.ally} will come",
base: { charms: new FalsePromise(null, "Charms") },
context: { "prince": "Prince", "magic": new FalsePromise(null, {"ally": {"delicious": new FalsePromise(null, "Lucky")} }) },
expected: "Eventually my Prince Lucky Charms will come",
message: "should reserve an async section for a deep-reference thenable and not blow the stack"
},
{
name: "thenable resolved by global helper",
source: '{@promise resolve="helper"}I am a big {.}!{/promise}',
context: {},
expected: "I am a big helper!",
message: "Dust helpers that return thenables are resolved in context"
},
{
name: "thenable rejected by global helper",
source: '{@promise reject="error"}I am a big helper!{:error}I am a big {.}!{/promise}',
context: {},
expected: "I am a big error!",
message: "Dust helpers that return thenables are rejected in context"
},
{
name: "thenable error",
source: "{promise}",
Expand Down Expand Up @@ -1329,8 +1344,8 @@ var coreTests = [
'{>"{parentTemplate}"/} | additional parent output'].join("\n"),
context: { "loadTemplate": function(chunk, context, bodies, params)
{
var source = dust.testHelpers.tap(params.source, chunk, context),
name = dust.testHelpers.tap(params.name, chunk, context);
var source = context.resolve(params.source),
name = context.resolve(params.name);
dust.loadSource(dust.compile(source, name));
return chunk.write('');
},
Expand Down
38 changes: 12 additions & 26 deletions test/jasmine-test/spec/testHelpers.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
(function (root, factory) {
if (typeof exports === 'object') {
factory(require('../../../lib/dust'));
factory(require('../../../lib/dust'), require('ayepromise'));
} else {
factory(root.dust);
factory(root.dust, ayepromise);
}
}(this, function(dust) {
dust.testHelpers = {};
dust.testHelpers.tap = function(input, chunk, context) {
// return given input if there is no dust reference to resolve
var output = input;
// dust compiles a string/reference such as {foo} to function,
if (typeof input === 'function') {
// just a plain function (a.k.a anonymous functions) in the context, not a dust `body` function created by the dust compiler
if (input.isFunction === true) {
output = input();
} else {
output = '';
chunk.tap(function(data){
output += data;
return '';
}).render(input, context).untap();
if (output === '') {
output = false;
}
}
}
return output;
};

}(this, function(dust, ayepromise) {
dust.helpers = {};
dust.helpers.error = function(chunk, context, bodies, params) {
throw params.errorMessage;
};
dust.helpers.promise = function(chunk, context, bodies, params) {
var defer = ayepromise.defer();
if (params.reject) {
defer.reject(params.reject);
} else {
defer.resolve(params.resolve);
}
return defer.promise;
};
}));

0 comments on commit ebb9985

Please sign in to comment.