Permalink
Browse files

Fixed compilation for macros

  • Loading branch information...
1 parent bc3ed24 commit 5e3a1dea4f906df4e7d4bd48de4e99d3cd97e7bb @mitsuhiko committed Dec 5, 2011
Showing with 60 additions and 28 deletions.
  1. +20 −13 templatetk/jscompiler.py
  2. +39 −14 templatetk/res/templatetk.runtime.js
  3. +1 −1 templatetk/runtime.py
View
33 templatetk/jscompiler.py
@@ -206,6 +206,19 @@ def write_context_as_object(self, fstate, reference_node):
self.writer.write('%s: %s' % (self.writer.dump_object(name), local_id))
self.writer.write('})')
+ def start_buffering(self, fstate):
+ self.writer.write_line('w = rts.startBuffering()')
+
+ def return_buffer_contents(self, fstate, write_to_var=False):
+ tmp = self.ident_manager.temporary()
+ self.writer.write_line('var %s = rts.endBuffering();' % tmp)
+ self.writer.write_line('w = %s[0];' % tmp)
+ if write_to_var:
+ self.writer.write_line('%s = %s[1];' % (tmp, tmp))
+ return tmp
+ else:
+ self.writer.write_line('return %s[1];' % tmp)
+
def visit_block(self, nodes, fstate):
self.writer.write_newline()
try:
@@ -343,10 +356,7 @@ def visit_If(self, node, fstate):
def visit_Output(self, node, fstate):
for child in node.nodes:
- if fstate.buffer:
- self.writer.write_line('%s.push(' % fstate.buffer)
- else:
- self.writer.write_line('w(')
+ self.writer.write_line('w(')
if isinstance(child, nodes.TemplateData):
self.writer.write_repr(child.data)
else:
@@ -360,7 +370,7 @@ def visit_Extends(self, node, fstate):
self.visit(node.template, fstate)
self.writer.write(', ')
self.write_context_as_object(fstate, node)
- self.writer.write(');')
+ self.writer.write(', w);')
if fstate.root:
raise StopFrameCompilation()
@@ -371,15 +381,14 @@ def visit_Block(self, node, fstate):
self.writer.write(');')
def visit_Function(self, node, fstate):
- buffer_name = self.ident_manager.temporary()
func_fstate = fstate.derive()
func_fstate.analyze_identfiers(node.args)
func_fstate.analyze_identfiers(node.body)
- func_fstate.buffer = buffer_name
- self.writer.write('rts.wrapFunction(')
+ argnames = [x.name for x in node.args]
+ self.writer.write('rt.wrapFunction(')
self.visit(node.name, fstate)
- self.writer.write(', %d, [' % len(node.args))
+ self.writer.write(', %s, [' % self.writer.dump_object(argnames))
for idx, arg in enumerate(node.defaults or ()):
if idx:
@@ -397,15 +406,13 @@ def visit_Function(self, node, fstate):
self.writer.write_newline()
self.writer.indent()
- self.writer.write('var %s = [];' % func_fstate.buffer)
buffer = self.writer.start_buffering()
+ self.start_buffering(func_fstate)
self.visit_block(node.body, func_fstate)
self.writer.end_buffering()
self.write_scope_code(func_fstate)
self.writer.write_from_buffer(buffer)
-
- self.writer.write_line('return rts.info.concatTemplateData(%s);' %
- func_fstate.buffer)
+ self.return_buffer_contents(func_fstate)
self.writer.outdent()
self.writer.write_line('})')
View
53 templatetk/res/templatetk.runtime.js
@@ -16,6 +16,12 @@
});
}
+ function makeWriteFunc(buffer) {
+ if (buffer.push.bind)
+ return buffer.push.bind(buffer);
+ return function(x) { buffer.push(x); };
+ }
+
function Config() {
this.filters = {};
};
@@ -66,9 +72,7 @@
render : function(context) {
context = new Context(context || {}, new Context(rtlib.getGlobals()));
var buffer = [];
- var rtstate = this.makeRuntimeState(context, function(chunk) {
- buffer.push(chunk);
- });
+ var rtstate = this.makeRuntimeState(context, makeWriteFunc(buffer));
this.run(rtstate);
return buffer.join("");
},
@@ -124,6 +128,7 @@
this.context = context;
this.config = config;
this.writeFunc = writeFunc;
+ this.buffers = [];
if (!info)
info = new rtlib.RuntimeInfo(this.config, templateName);
this.info = info;
@@ -157,10 +162,25 @@
return rv;
},
- extendTemplate : function(name, context) {
+ extendTemplate : function(name, context, writeFunc) {
var template = this.getTemplate(name);
var info = this.info.makeInfo(template, name, "extends");
- return this.config.evaluateTemplate(template, context, this.writeFunc, info);
+ return this.config.evaluateTemplate(template, context, writeFunc, info);
+ },
+
+ startBuffering : function() {
+ var buffer = [];
+ this.buffers.push([this.writeFunc, buffer]);
+ return this.writeFunc = makeWriteFunc(buffer);
+ },
+
+ endBuffering : function() {
+ var entry = this.buffers.pop();
+ this.writeFunc = entry[0];
+ var rv = entry[1].join('');
+ if (this.autoescape)
+ rv = rtlib.markSafe(rv);
+ return [this.writeFunc, rv];
}
};
@@ -198,13 +218,6 @@
return rtlib.finalize(value, this.autoescape);
},
- concatTemplateData : function(buffer) {
- var rv = buffer.join('');
- if (this.autoescape)
- rv = rtlib.markSafe(rv);
- return rv;
- },
-
registerBlock : function(name, executor) {
var m = this.blockExecutors;
(m[name] = (m[name] || [])).push(executor);
@@ -311,8 +324,20 @@
elseFunc();
},
- wrapFunction : function(name, argCount, defaults, func) {
- return func;
+ wrapFunction : function(name, argNames, defaults, func) {
+ var argCount = argNames.length;
+ return function() {
+ var args = [];
+ for (var i = 0, n = Math.min(arguments.length, argCount); i < n; i++)
+ args.push(arguments[i]);
+ var off = args.length;
+ if (off != argCount)
+ for (var i = 0, n = argCount - off; i < n; i++) {
+ var didx = defaults.length + (i - argCount + off);
+ args.push(rtlib.makeUndefined(defaults[didx], argNames[off + i]));
+ }
+ return func.apply(null, args);
+ };
}
};
View
2 templatetk/runtime.py
@@ -133,7 +133,7 @@ def __call__(self, *args, **kwargs):
pos_args = list(args[:self._arg_count])
off = len(args)
if off != self._arg_count:
- for idx, name in enumerate(self._arguments[:len(pos_args)]):
+ for idx, name in enumerate(self._arguments[len(pos_args):]):
try:
value = kwargs.pop(name)
except KeyError:

0 comments on commit 5e3a1de

Please sign in to comment.