Avoid eval when running in VM+Compiler mode

This commit is contained in:
kpdecker
2011-07-30 16:55:26 -05:00
parent f8edc59025
commit 993c793565
2 changed files with 39 additions and 22 deletions
+29 -21
View File
@@ -315,7 +315,7 @@ Handlebars.JavaScriptCompiler = function() {};
},
// END PUBLIC API
compile: function(environment, options) {
compile: function(environment, options, asObject) {
this.environment = environment;
this.options = options || {};
@@ -325,9 +325,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.stackVars = [];
this.registers = {list: []};
this.compileChildren(environment, options);
Handlebars.log(Handlebars.logger.DEBUG, environment.disassemble() + "\n\n");
this.compileChildren(environment, options, asObject);
var opcodes = environment.opcodes, opcode, name, declareName, declareVal;
@@ -345,7 +343,7 @@ Handlebars.JavaScriptCompiler = function() {};
}
}
return this.createFunctionContext();
return this.createFunctionContext(asObject);
},
nextOpcode: function(n) {
@@ -388,7 +386,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.source = out;
},
createFunctionContext: function() {
createFunctionContext: function(asObject) {
var locals = this.stackVars.concat(this.registers.list);
if(locals.length > 0) {
@@ -409,19 +407,28 @@ Handlebars.JavaScriptCompiler = function() {};
if(params.length === 4 && !this.environment.usePartial) { params.pop(); }
var functionSource = 'function(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}';
if (asObject) {
params.push(this.source.join("\n "));
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
return {
fn: Function.apply(this, params),
children: this.environment.children
};
} else {
var functionSource = 'function(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}';
var script = ['{\n fn: ', functionSource, ',\n children: [\n '],
children = this.environment.children;
for (var i = 0, len = children.length; i < len; i++) {
script.push(children[i]);
if (i < len-1) { script.push(',\n'); }
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
var script = ['{\n fn: ', functionSource, ',\n children: [\n '],
children = this.environment.children;
for (var i = 0, len = children.length; i < len; i++) {
script.push(children[i]);
if (i < len-1) { script.push(',\n'); }
}
script.push('\n ]\n}');
return script.join('');
}
script.push('\n ]\n}');
return script.join('');
},
appendContent: function(content) {
@@ -574,7 +581,7 @@ Handlebars.JavaScriptCompiler = function() {};
compiler: JavaScriptCompiler,
compileChildren: function(environment, options) {
compileChildren: function(environment, options, asObject) {
var children = environment.children, child, compiler;
var compiled = [];
@@ -582,7 +589,7 @@ Handlebars.JavaScriptCompiler = function() {};
child = children[i];
compiler = new this.compiler();
compiled[i] = compiler.compile(child, options);
compiled[i] = compiler.compile(child, options, asObject);
}
environment.rawChildren = children;
@@ -679,10 +686,11 @@ Handlebars.precompile = function(string, options) {
return new Handlebars.JavaScriptCompiler().compile(environment, options);
};
// TODO : Testing
// TODO : Do this without the eval requirement
Handlebars.compile = function(string, options) {
return Handlebars.template(eval('(' + Handlebars.precompile(string, options) + ')'));
var ast = Handlebars.parse(string);
var environment = new Handlebars.Compiler().compile(ast, options);
var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, true);
return Handlebars.template(templateSpec);
};
// END(BROWSER)
+10 -1
View File
@@ -246,7 +246,16 @@ test("helper with complex lookup and nested template", function() {
var helpers = {link: function (prefix, fn) {
return "<a href='" + prefix + "/" + this.url + "'>" + fn(this) + "</a>";
}};
shouldCompileTo(string, [hash, helpers], "<a href='/root/goodbye'>Goodbye</a>")
shouldCompileToWithPartials(string, [hash, helpers], false, "<a href='/root/goodbye'>Goodbye</a>");
});
test("helper with complex lookup and nested template in VM+Compiler", function() {
var string = "{{#goodbyes}}{{#link ../prefix}}{{text}}{{/link}}{{/goodbyes}}";
var hash = {prefix: '/root', goodbyes: [{text: "Goodbye", url: "goodbye"}]};
var helpers = {link: function (prefix, fn) {
return "<a href='" + prefix + "/" + this.url + "'>" + fn(this) + "</a>";
}};
shouldCompileToWithPartials(string, [hash, helpers], true, "<a href='/root/goodbye'>Goodbye</a>");
});
test("block with deep nested complex lookup", function() {