Skip to content
Browse files

Merge pull request #736 from brianmhunt/master

Prioritize resolution of .then
  • Loading branch information...
2 parents 487da8d + 6f6c49f commit dc1e1dcd33a8dc26fecdf1d269e750b8a3482295 @prashn64 prashn64 committed on GitHub Jun 10, 2016
Showing with 39 additions and 6 deletions.
  1. +15 −6 lib/dust.js
  2. +24 −0 test/templates/all.js
View
21 lib/dust.js
@@ -248,17 +248,26 @@
};
/**
- * Decide somewhat-naively if something is a Thenable.
+ * Decide somewhat-naively if something is a Thenable. Matches Promises A+ Spec, section 1.2 “thenable” is an object or function that defines a then method."
* @param elem {*} object to inspect
* @return {Boolean} is `elem` a Thenable?
*/
dust.isThenable = function(elem) {
- return elem &&
- typeof elem === 'object' &&
+ return elem && /* Beware: `typeof null` is `object` */
+ (typeof elem === 'object' || typeof elem === 'function') &&
typeof elem.then === 'function';
};
/**
+ * Decide if an element is a function but not Thenable; it is prefereable to resolve a thenable function by its `.then` method.
+ * @param elem {*} target of inspection
+ * @return {Boolean} is `elem` a function without a `.then` property?
+ */
+ dust.isNonThenableFunction = function(elem) {
+ return typeof elem === 'function' && !dust.isThenable(elem);
+ };
+
+ /**
* Decide very naively if something is a Stream.
* @param elem {*} object to inspect
* @return {Boolean} is `elem` a Stream?
@@ -430,7 +439,7 @@
}
}
- if (typeof ctx === 'function') {
+ if (dust.isNonThenableFunction(ctx)) {
fn = function() {
try {
return ctx.apply(ctxThis, arguments);
@@ -747,7 +756,7 @@
};
Chunk.prototype.reference = function(elem, context, auto, filters) {
- if (typeof elem === 'function') {
+ if (dust.isNonThenableFunction(elem)) {
elem = elem.apply(context.current(), [this, context, null, {auto: auto, filters: filters}]);
if (elem instanceof Chunk) {
return elem;
@@ -772,7 +781,7 @@
chunk = this,
i, len, head;
- if (typeof elem === 'function' && !dust.isTemplateFn(elem)) {
+ if (dust.isNonThenableFunction(elem) && !dust.isTemplateFn(elem)) {
try {
elem = elem.apply(context.current(), [this, context, bodies, params]);
} catch(err) {
View
24 test/templates/all.js
@@ -25,6 +25,16 @@ function FalsePromise(err, data) {
}
/**
+ * A naive function factory that adds a thenable that resolves to the given value.
+ * @param resolvesTo {*} The value passed to the `resolve` then argument
+*/
+function createThenableFunction(resolvesTo) {
+ var fn = function () {};
+ fn.then = function (res) { res(resolvesTo) };
+ return fn;
+}
+
+/**
* A naive Stream constructor that streams the provided array asynchronously
* @param arr {Array<Object|Error>|String} items to be streamed
* @return {Stream}
@@ -914,6 +924,20 @@ return [
expected: "Eventually magic!",
message: "should reserve an async section for a thenable returned from a function"
},
+ {
+ name: "thenable section from thenable function",
+ source: "{#thenable}Eventually poof!{/thenable}",
+ context: { "thenable": createThenableFunction("poof!") },
+ expected: "Eventually poof!",
+ message: "should reserve an async section for a thenable function"
+ },
+ {
+ name: "thenable reference from thenable function",
+ source: "A {thenable} thing",
+ context: { "thenable": createThenableFunction("real") },
+ expected: "A real thing",
+ message: "should reserve an async reference for a thenable function"
+ },
{
name: "thenable deep section",
source: "Eventually my {#magic.ally}{delicious}{/magic.ally} will come",

0 comments on commit dc1e1dc

Please sign in to comment.
Something went wrong with that request. Please try again.