Skip to content

Commit

Permalink
Maximum call stack size exceeded when include many templates (#787)
Browse files Browse the repository at this point in the history
* add test for max callstack size exceed error

* fix callstack size exceed error

* fix tests add old node versions support

This reverts commit 56e085b.

* fix tests for node v6

* sort dependencies alphabetically
  • Loading branch information
hydiak authored and carljm committed Aug 3, 2016
1 parent 509a7ac commit e233636
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 5 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "3.0.0-dev.3",
"author": "James Long <longster@gmail.com>",
"dependencies": {
"a-sync-waterfall": "^1.0.0",
"asap": "^2.0.3",
"chokidar": "^1.6.0",
"yargs": "^3.32.0"
Expand Down
22 changes: 18 additions & 4 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -1029,14 +1029,28 @@ var Compiler = Object.extend({
var id = this.tmpid();
var id2 = this.tmpid();

this.emitLine('var tasks = [];');
this.emitLine('tasks.push(');
this.emitLine('function(callback) {');
this.emit('env.getTemplate(');
this._compileExpression(node.template, frame);
this.emitLine(', false, '+this._templateName()+', ' + node.ignoreMissing + ', ' + this.makeCallback(id));
this.addScopeLevel();
this.emitLine('callback(null,' + id + ');});');
this.emitLine('});');

this.emitLine(id + '.render(' +
'context.getVariables(), frame, ' + this.makeCallback(id2));
this.emitLine(this.buffer + ' += ' + id2);
this.emitLine('tasks.push(');
this.emitLine('function(template, callback){');
this.emitLine('template.render(' +
'context.getVariables(), frame, ' + this.makeCallback(id2));
this.emitLine('callback(null,' + id2 + ');});');
this.emitLine('});');

this.emitLine('tasks.push(');
this.emitLine('function(result, callback){');
this.emitLine(this.buffer + ' += result;');
this.emitLine('callback(null);');
this.emitLine('});');
this.emitLine('env.waterfall(tasks, function(){');
this.addScopeLevel();
},

Expand Down
5 changes: 4 additions & 1 deletion src/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var builtin_filters = require('./filters');
var builtin_loaders = require('./loaders');
var runtime = require('./runtime');
var globals = require('./globals');
var waterfall = require('a-sync-waterfall');
var Frame = runtime.Frame;
var Template;

Expand Down Expand Up @@ -324,7 +325,9 @@ var Environment = Obj.extend({

var tmpl = new Template(src, this, opts.path);
return tmpl.render(ctx, cb);
}
},

waterfall: waterfall
});

var Context = Obj.extend({
Expand Down
6 changes: 6 additions & 0 deletions tests/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,12 @@
finish(done);
});

it('should include 130 templates without call stack size exceed', function(done) {
equal('{% include "includeMany.njk" %}',
new Array(131).join('FooInclude \n'));
finish(done);
});

it('should include templates with context', function(done) {
equal('hello world {% include "include.njk" %}',
{ name: 'james' },
Expand Down
130 changes: 130 additions & 0 deletions tests/templates/includeMany.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}
{% include "include.njk" %}

0 comments on commit e233636

Please sign in to comment.