Skip to content
This repository has been archived by the owner on Apr 11, 2018. It is now read-only.

Commit

Permalink
Use local-context first for var lookups
Browse files Browse the repository at this point in the history
Ensures that browser-globals are not used before using the local context.
Ensured resetting values in for-loops.

Fixes gh-347
Possibly related to gh-344
  • Loading branch information
paularmstrong committed Nov 2, 2013
1 parent 9395e31 commit 32f3994
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 14 deletions.
6 changes: 3 additions & 3 deletions lib/parser.js
Expand Up @@ -204,8 +204,8 @@ TokenParser.prototype = {

case _t.FUNCTION:
case _t.FUNCTIONEMPTY:
self.out.push('((typeof ' + match + ' !== "undefined") ? ' + match +
' : ((typeof _ctx.' + match + ' !== "undefined") ? _ctx.' + match +
self.out.push('((typeof _ctx.' + match + ' !== "undefined") ? _ctx.' + match +
' : ((typeof ' + match + ' !== "undefined") ? ' + match +
' : _fn))(');
self.escape = false;
if (token.type === _t.FUNCTIONEMPTY) {
Expand Down Expand Up @@ -403,7 +403,7 @@ TokenParser.prototype = {
return '(' + checkDot(ctx) + ' ? ' + ctx + match.join('.') + ' : "")';
}

return '(' + checkDot('') + ' ? ' + buildDot('') + ' : ' + buildDot('_ctx.') + ')';
return '(' + checkDot('_ctx.') + ' ? ' + buildDot('_ctx.') + ' : ' + buildDot('') + ')';
}
};

Expand Down
20 changes: 15 additions & 5 deletions lib/tags/for.js
@@ -1,3 +1,7 @@
var ctx = '_ctx.',
ctxloop = ctx + 'loop',
ctxloopcache = ctx + '___loopcache';

/**
* Loop over objects and arrays.
*
Expand Down Expand Up @@ -55,14 +59,20 @@ exports.compile = function (compiler, args, content, parents, options, blockName
'(function () {\n',
' var __l = ' + last + ';\n',
' if (!__l) { return; }\n',
' var loop = { first: false, index: 1, index0: 0, revindex: __l.length, revindex0: __l.length - 1, length: __l.length, last: false };\n',
' ' + ctxloopcache + ' = { loop: ' + ctxloop + ', ' + val + ': ' + ctx + val + ', ' + key + ': ' + ctx + key + ' };\n',
' ' + ctxloop + ' = { first: false, index: 1, index0: 0, revindex: __l.length, revindex0: __l.length - 1, length: __l.length, last: false };\n',
' _utils.each(__l, function (' + val + ', ' + key + ') {\n',
' loop.key = ' + key + ';\n',
' loop.first = (loop.index0 === 0);\n',
' loop.last = (loop.revindex0 === 0);\n',
' ' + ctx + val + ' = ' + val + ';\n',
' ' + ctx + key + ' = ' + key + ';\n',
' ' + ctxloop + '.key = ' + key + ';\n',
' ' + ctxloop + '.first = (' + ctxloop + '.index0 === 0);\n',
' ' + ctxloop + '.last = (' + ctxloop + '.revindex0 === 0);\n',
' ' + compiler(content, parents, options, blockName),
' loop.index += 1; loop.index0 += 1; loop.revindex -= 1; loop.revindex0 -= 1;\n',
' ' + ctxloop + '.index += 1; ' + ctxloop + '.index0 += 1; ' + ctxloop + '.revindex -= 1; ' + ctxloop + '.revindex0 -= 1;\n',
' });\n',
' ' + ctxloop + ' = ' + ctxloopcache + '.loop;\n',
' ' + ctx + val + ' = ' + ctxloopcache + '.' + val + ';\n',
' ' + ctx + key + ' = ' + ctxloopcache + '.' + key + ';\n',
'})();\n'
].join('');
};
Expand Down
7 changes: 3 additions & 4 deletions lib/tags/import.js
Expand Up @@ -22,12 +22,12 @@ var utils = require('../utils');
*/
exports.compile = function (compiler, args) {
var ctx = args.pop(),
out = 'var ' + ctx + ' = {};\n' +
'(function (exports) {\n' +
out = '_ctx.' + ctx + ' = {};\n' +
'(function (_ctx) {\n' +
' var _output = "";\n';

out += args.join('');
out += '}(' + ctx + '));\n';
out += '}(_ctx.' + ctx + '));\n';

return out;
};
Expand All @@ -52,7 +52,6 @@ exports.parse = function (str, line, parser, types, stack, opts) {
}
macroName = token.args[0];
out += token.compile(compiler, token.args, token.content, [], compileOpts) + '\n';
out += 'exports.' + macroName + ' = ' + macroName + ';\n';
self.out.push(out);
});
return;
Expand Down
4 changes: 2 additions & 2 deletions lib/tags/macro.js
Expand Up @@ -19,12 +19,12 @@
exports.compile = function (compiler, args, content, parents, options, blockName) {
var fnName = args.shift();

return 'function ' + fnName + '(' + args.join('') + ') {\n' +
return '_ctx.' + fnName + ' = function (' + args.join('') + ') {\n' +
' var _output = "";\n' +
compiler(content, parents, options, blockName) + '\n' +
' return _output;\n' +
'};\n' +
fnName + '.safe = true;\n';
'_ctx.' + fnName + '.safe = true;\n';
};

exports.parse = function (str, line, parser, types) {
Expand Down
5 changes: 5 additions & 0 deletions tests/tags/for.test.js
Expand Up @@ -34,6 +34,11 @@ describe('Tag: for', function () {
});
});

it('resets loop and vars', function () {
expect(swig.render('{% for a, b in c %}{% endfor %}{{ a }}{{ b }}{{ loop }}', { locals: { loop: 'z', a: 'x', b: 'y', c: { d: 'e', f: 'g' }}}))
.to.equal('xyz');
});

it('throws on numbers as any argument', function () {
expect(function () {
swig.render('{% for a in 32 %}{% endfor %}');
Expand Down

0 comments on commit 32f3994

Please sign in to comment.