@@ -51,6 +51,8 @@ Compiler.prototype = {
|
||||
this.stringParams = options.stringParams;
|
||||
this.trackIds = options.trackIds;
|
||||
|
||||
options.blockParams = options.blockParams || [];
|
||||
|
||||
// These changes will propagate to the other compiler components
|
||||
var knownHelpers = options.knownHelpers;
|
||||
options.knownHelpers = {
|
||||
@@ -92,14 +94,17 @@ Compiler.prototype = {
|
||||
},
|
||||
|
||||
Program: function(program) {
|
||||
var body = program.body;
|
||||
this.options.blockParams.unshift(program.blockParams);
|
||||
|
||||
var body = program.body;
|
||||
for(var i=0, l=body.length; i<l; i++) {
|
||||
this.accept(body[i]);
|
||||
}
|
||||
|
||||
this.isSimple = l === 1;
|
||||
this.options.blockParams.shift();
|
||||
|
||||
this.isSimple = l === 1;
|
||||
this.blockParams = program.blockParams ? program.blockParams.length : 0;
|
||||
|
||||
return this;
|
||||
},
|
||||
@@ -231,15 +236,20 @@ Compiler.prototype = {
|
||||
this.addDepth(path.depth);
|
||||
this.opcode('getContext', path.depth);
|
||||
|
||||
var name = path.parts[0];
|
||||
if (!name) {
|
||||
var name = path.parts[0],
|
||||
scoped = AST.helpers.scopedId(path),
|
||||
blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
|
||||
|
||||
if (blockParamId) {
|
||||
this.opcode('lookupBlockParam', blockParamId, path.parts);
|
||||
} else if (!name) {
|
||||
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
|
||||
this.opcode('pushContext');
|
||||
} else if (path.data) {
|
||||
this.options.data = true;
|
||||
this.opcode('lookupData', path.depth, path.parts);
|
||||
} else {
|
||||
this.opcode('lookupOnContext', path.parts, path.falsy, AST.helpers.scopedId(path));
|
||||
this.opcode('lookupOnContext', path.parts, path.falsy, scoped);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -283,14 +293,18 @@ Compiler.prototype = {
|
||||
},
|
||||
|
||||
classifySexpr: function(sexpr) {
|
||||
var isSimple = AST.helpers.simpleId(sexpr.path);
|
||||
|
||||
var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
|
||||
|
||||
// a mustache is an eligible helper if:
|
||||
// * its id is simple (a single part, not `this` or `..`)
|
||||
var isHelper = AST.helpers.helperExpression(sexpr);
|
||||
var isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr);
|
||||
|
||||
// if a mustache is an eligible helper but not a definite
|
||||
// helper, it is ambiguous, and will be resolved in a later
|
||||
// pass or at runtime.
|
||||
var isEligible = isHelper || AST.helpers.simpleId(sexpr.path);
|
||||
var isEligible = !isBlockParam && (isHelper || isSimple);
|
||||
|
||||
var options = this.options;
|
||||
|
||||
@@ -345,14 +359,23 @@ Compiler.prototype = {
|
||||
}
|
||||
} else {
|
||||
if (this.trackIds) {
|
||||
value = val.original || value;
|
||||
if (value.replace) {
|
||||
value = value
|
||||
.replace(/^\.\//g, '')
|
||||
.replace(/^\.$/g, '');
|
||||
var blockParamIndex;
|
||||
if (val.parts && !AST.helpers.scopedId(val) && !val.depth) {
|
||||
blockParamIndex = this.blockParamIndex(val.parts[0]);
|
||||
}
|
||||
if (blockParamIndex) {
|
||||
var blockParamChild = val.parts.slice(1).join('.');
|
||||
this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
|
||||
} else {
|
||||
value = val.original || value;
|
||||
if (value.replace) {
|
||||
value = value
|
||||
.replace(/^\.\//g, '')
|
||||
.replace(/^\.$/g, '');
|
||||
}
|
||||
|
||||
this.opcode('pushId', val.type, value);
|
||||
this.opcode('pushId', val.type, value);
|
||||
}
|
||||
}
|
||||
this.accept(val);
|
||||
}
|
||||
@@ -372,6 +395,16 @@ Compiler.prototype = {
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
|
||||
blockParamIndex: function(name) {
|
||||
for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
|
||||
var blockParams = this.options.blockParams[depth],
|
||||
param = blockParams && blockParams.indexOf(name);
|
||||
if (blockParams && param >= 0) {
|
||||
return [depth, param];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -429,11 +462,11 @@ export function compile(input, options, env) {
|
||||
}
|
||||
return compiled._setup(options);
|
||||
};
|
||||
ret._child = function(i, data, depths) {
|
||||
ret._child = function(i, data, blockParams, depths) {
|
||||
if (!compiled) {
|
||||
compiled = compileInput();
|
||||
}
|
||||
return compiled._child(i, data, depths);
|
||||
return compiled._child(i, data, blockParams, depths);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user