Pass undefined fields to helpers in strict mode
This allows for `{{helper foo}}` to still operate under strict mode when `foo` is not defined on the context. This allows helpers to perform whatever existence checks they please so patterns like `{{#if foo}}{{foo}}{{/if}}` can be used to protect against missing values.
Fixes #1063
This commit is contained in:
@@ -217,13 +217,16 @@ Compiler.prototype = {
|
||||
this.opcode('pushProgram', program);
|
||||
this.opcode('pushProgram', inverse);
|
||||
|
||||
path.strict = true;
|
||||
this.accept(path);
|
||||
|
||||
this.opcode('invokeAmbiguous', name, isBlock);
|
||||
},
|
||||
|
||||
simpleSexpr: function(sexpr) {
|
||||
this.accept(sexpr.path);
|
||||
let path = sexpr.path;
|
||||
path.strict = true;
|
||||
this.accept(path);
|
||||
this.opcode('resolvePossibleLambda');
|
||||
},
|
||||
|
||||
@@ -237,6 +240,7 @@ Compiler.prototype = {
|
||||
} else if (this.options.knownHelpersOnly) {
|
||||
throw new Exception('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr);
|
||||
} else {
|
||||
path.strict = true;
|
||||
path.falsy = true;
|
||||
|
||||
this.accept(path);
|
||||
@@ -259,9 +263,9 @@ Compiler.prototype = {
|
||||
this.opcode('pushContext');
|
||||
} else if (path.data) {
|
||||
this.options.data = true;
|
||||
this.opcode('lookupData', path.depth, path.parts);
|
||||
this.opcode('lookupData', path.depth, path.parts, path.strict);
|
||||
} else {
|
||||
this.opcode('lookupOnContext', path.parts, path.falsy, scoped);
|
||||
this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ JavaScriptCompiler.prototype = {
|
||||
//
|
||||
// Looks up the value of `name` on the current context and pushes
|
||||
// it onto the stack.
|
||||
lookupOnContext: function(parts, falsy, scoped) {
|
||||
lookupOnContext: function(parts, falsy, strict, scoped) {
|
||||
let i = 0;
|
||||
|
||||
if (!scoped && this.options.compat && !this.lastContext) {
|
||||
@@ -401,7 +401,7 @@ JavaScriptCompiler.prototype = {
|
||||
this.pushContext();
|
||||
}
|
||||
|
||||
this.resolvePath('context', parts, i, falsy);
|
||||
this.resolvePath('context', parts, i, falsy, strict);
|
||||
},
|
||||
|
||||
// [lookupBlockParam]
|
||||
@@ -424,19 +424,19 @@ JavaScriptCompiler.prototype = {
|
||||
// On stack, after: data, ...
|
||||
//
|
||||
// Push the data lookup operator
|
||||
lookupData: function(depth, parts) {
|
||||
lookupData: function(depth, parts, strict) {
|
||||
if (!depth) {
|
||||
this.pushStackLiteral('data');
|
||||
} else {
|
||||
this.pushStackLiteral('this.data(data, ' + depth + ')');
|
||||
}
|
||||
|
||||
this.resolvePath('data', parts, 0, true);
|
||||
this.resolvePath('data', parts, 0, true, strict);
|
||||
},
|
||||
|
||||
resolvePath: function(type, parts, i, falsy) {
|
||||
resolvePath: function(type, parts, i, falsy, strict) {
|
||||
if (this.options.strict || this.options.assumeObjects) {
|
||||
this.push(strictLookup(this.options.strict, this, parts, type));
|
||||
this.push(strictLookup(this.options.strict && strict, this, parts, type));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,23 @@ describe('strict', function() {
|
||||
template({hello: {}});
|
||||
}, Exception, /"bar" not defined in/);
|
||||
});
|
||||
|
||||
it('should allow undefined parameters when passed to helpers', function() {
|
||||
var template = CompilerContext.compile('{{#unless foo}}success{{/unless}}', {strict: true});
|
||||
equals(template({}), 'success');
|
||||
});
|
||||
|
||||
it('should allow undefined hash when passed to helpers', function() {
|
||||
var template = CompilerContext.compile('{{helper value=@foo}}', {strict: true});
|
||||
var helpers = {
|
||||
helper: function(options) {
|
||||
equals('value' in options.hash, true);
|
||||
equals(options.hash.value, undefined);
|
||||
return 'success';
|
||||
}
|
||||
};
|
||||
equals(template({}, {helpers: helpers}), 'success');
|
||||
});
|
||||
});
|
||||
|
||||
describe('assume objects', function() {
|
||||
|
||||
Reference in New Issue
Block a user