Skip to content

Commit

Permalink
Fixed can.Construct-derived static properties being inaccessible in M…
Browse files Browse the repository at this point in the history
…ustache #450

Also fixed consistency issues in handling helper arguments
  • Loading branch information
andykant committed Apr 30, 2014
1 parent 0e96387 commit 36b82c7
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 4 deletions.
9 changes: 7 additions & 2 deletions compute/compute.js
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) {
// just do the dot operator
cur = prev[reads[i]];
}
type = typeof cur;
// If it's a compute, get the compute's value
// unless we are at the end of the
if (cur && cur.isComputed && (!options.isArgument && i < readLength - 1)) {
Expand All @@ -610,7 +611,10 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) {
}
cur = cur();
}
type = typeof cur;
// If it's an anonymous function, execute as requested
else if (i < reads.length - 1 && type === 'function' && options.executeAnonymousFunctions && !(can.Construct && cur.prototype instanceof can.Construct)) {
cur = cur();
}
// if there are properties left to read, and we don't have an object, early exit
if (i < reads.length - 1 && (cur === null || type !== 'function' && type !== 'object')) {
if (options.earlyExit) {
Expand All @@ -624,7 +628,8 @@ steal('can/util', 'can/util/bind', 'can/util/batch', function (can, bind) {
}
}
// handle an ending function
if (typeof cur === 'function') {
// unless it is a can.Construct-derived constructor
if (typeof cur === 'function' && !(can.Construct && cur.prototype instanceof can.Construct)) {
if (options.isArgument) {
if (!cur.isComputed && options.proxyMethods !== false) {
cur = can.proxy(cur, prev);
Expand Down
2 changes: 1 addition & 1 deletion view/mustache/mustache.js
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ steal('can/util',
// get values on hash
for (var prop in hash) {
if (isLookup(hash[prop])) {
hash[prop] = Mustache.get(hash[prop].get, scopeAndOptions);
hash[prop] = Mustache.get(hash[prop].get, scopeAndOptions, false, true);
}
}
} else if (arg && isLookup(arg)) {
Expand Down
53 changes: 53 additions & 0 deletions view/mustache/mustache_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3626,4 +3626,57 @@ steal("can/model", "can/view/mustache", "can/test", "can/view/mustache/spec/spec
data.attr("show", true);
equal(frag.childNodes[0].innerHTML, "Is showing", "Not showing the else");
});

test("can.Construct derived classes should be considered objects, not functions (#450)", 8, function() {
can.Mustache.registerHelper("cat", function(options) {
var clazz = options.hash ? options.hash.clazz : options;
// When using the anonymous function containing foostructor, it will need to be executed
return clazz.text || clazz().text;
});

var foostructor = can.Map({ text: "bar" }, {}),
obj = {
next_level: {
thing: foostructor,
text: "In the inner context"
}
},
div = document.createElement("div"),
description;
foostructor.self = foostructor;
window.other_text = "Window context";

for (var i = 0; i < 2; i++) {
if (i === 1) {
foostructor.self = function() { return foostructor; };
}

// // Fully dotted
div.appendChild(can.view.mustache("<div>{{next_level.thing.self.text}}</div>")(obj));

// // With attribute nested
div.appendChild(can.view.mustache("<div>{{#next_level.thing.self}}{{text}}{{/next_level.thing}}</div>")(obj));

// Passed as an argument to helper
div.appendChild(can.view.mustache("<div>{{cat next_level.thing.self}}</div>")(obj));

// Passed as a hash to helper
div.appendChild(can.view.mustache("<div>{{cat clazz=next_level.thing.self}}</div>")(obj));
}

var content = div.getElementsByTagName('div');

description = " (constructor by itself)";
equal(content[0].innerHTML, "bar", "fully dotted" + description);
equal(content[1].innerHTML.replace(/\<\/?span\>/g,''), "", "with attribute nested" + description);
equal(content[2].innerHTML, "bar", "passed as an argument to helper" + description);
equal(content[3].innerHTML, "bar", "passed as a hash to helper" + description);

description = " (constructor as function returning itself)";
equal(content[4].innerHTML, "bar", "fully dotted" + description);
equal(content[5].innerHTML.replace(/\<\/?span\>/g,''), "", "with attribute nested" + description);
equal(content[6].innerHTML, "bar", "passed as an argument to helper" + description);
equal(content[7].innerHTML, "bar", "passed as a hash to helper" + description);
});

});
4 changes: 3 additions & 1 deletion view/scope/scope.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ steal(
/* Clear and save readings so next attempt does not use these readings */
defaultComputeReadings = can.__clearReading();
}
}
},
// Execute anonymous functions found along the way
executeAnonymousFunctions: true
}, options));
// **Key was found**, return value and location data
if (data.value !== undefined) {
Expand Down

0 comments on commit 36b82c7

Please sign in to comment.