From 38d2c57016f18f809c48fc9d19357df77a34ee2b Mon Sep 17 00:00:00 2001 From: Luke Page Date: Wed, 24 Oct 2012 20:16:10 +0100 Subject: [PATCH] Make less.js ignore nodes in its own path so infinite recursion does not happen. Fixes #413 --- lib/less/tree/mixin.js | 23 ++++++++++++++++++----- lib/less/tree/ruleset.js | 1 + test/css/mixins.css | 3 +++ test/less/mixins.less | 6 ++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/less/tree/mixin.js b/lib/less/tree/mixin.js index 703c96f7..d758ae95 100644 --- a/lib/less/tree/mixin.js +++ b/lib/less/tree/mixin.js @@ -10,14 +10,25 @@ tree.mixin.Call = function (elements, args, index, filename, important) { }; tree.mixin.Call.prototype = { eval: function (env) { - var mixins, args, rules = [], match = false; + var mixins, args, rules = [], match = false, i, m, f, isRecursive; - for (var i = 0; i < env.frames.length; i++) { + for (i = 0; i < env.frames.length; i++) { if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { return { name: a.name, value: a.value.eval(env) }; }); - for (var m = 0; m < mixins.length; m++) { + for (m = 0; m < mixins.length; m++) { + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if (mixins[m] === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } if (mixins[m].match(args, env)) { try { Array.prototype.push.apply( @@ -140,7 +151,7 @@ tree.mixin.Definition.prototype = { return frame; }, eval: function (env, args, important) { - var _arguments = [], frame = this.evalParams(env, args, _arguments), context, rules, start; + var _arguments = [], frame = this.evalParams(env, args, _arguments), context, rules, start, ruleset; frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); @@ -149,9 +160,11 @@ tree.mixin.Definition.prototype = { return new(tree.Rule)(r.name, r.value, '!important', r.index); }) : this.rules.slice(0); - return new(tree.Ruleset)(null, rules).eval({ + ruleset = new(tree.Ruleset)(null, rules).eval({ frames: [this, frame].concat(this.frames, env.frames) }); + ruleset.originalRuleset = this; + return ruleset; }, match: function (args, env) { var argsLength = (args && args.length) || 0, len, frame; diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index 822f331e..5bef10f5 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -12,6 +12,7 @@ tree.Ruleset.prototype = { var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); var rules = []; + ruleset.originalRuleset = this; ruleset.root = this.root; ruleset.allowImports = this.allowImports; diff --git a/test/css/mixins.css b/test/css/mixins.css index c5d3b229..2a3bb0ec 100644 --- a/test/css/mixins.css +++ b/test/css/mixins.css @@ -106,3 +106,6 @@ h3 + * { background-image: "/a.png"; background-position: center center; } +.recursion { + color: black; +} diff --git a/test/less/mixins.less b/test/less/mixins.less index 7158c2ef..e03913e0 100644 --- a/test/less/mixins.less +++ b/test/less/mixins.less @@ -91,3 +91,9 @@ h3 { .margin_between(15px, 5px); } @s: "/"; .mixin_def( "@{s}a.png", center center); } +.recursion() { + color: black; +} +.recursion { + .recursion(); +}