Added guards checking to namespaces. Issue #1418.

This commit is contained in:
jurcovicovam
2014-09-05 09:01:56 +02:00
parent 9c7854708b
commit c330c3a4a8
4 changed files with 115 additions and 30 deletions

View File

@@ -19,16 +19,45 @@ tree.mixin.Call.prototype = {
}
},
eval: function (env) {
var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset;
var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
defaultResult, defFalseEitherCase=-1, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
function calcDefGroup(mixin, mixinPath) {
var p, namespace;
for (f = 0; f < 2; f++) {
conditionResult[f] = true;
defaultFunc.value(f);
for(p = 0; p < mixinPath.length && conditionResult[f]; p++) {
namespace = mixinPath[p];
if (namespace.matchCondition) {
conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, env);
}
}
if (mixin.matchCondition) {
conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, env);
}
}
if (conditionResult[0] || conditionResult[1]) {
if (conditionResult[0] != conditionResult[1]) {
return conditionResult[1] ?
defTrue : defFalse;
}
return defNone;
}
return defFalseEitherCase;
}
args = this.arguments && this.arguments.map(function (a) {
return { name: a.name, value: a.value.eval(env) };
});
noArgumentsFilter = function(rule) {return rule.matchArgs(null, env);};
for (i = 0; i < env.frames.length; i++) {
if ((mixins = env.frames[i].find(this.selector)).length > 0) {
if ((mixins = env.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
isOneFound = true;
// To make `default()` function independent of definition order we have two "subpasses" here.
@@ -37,7 +66,8 @@ tree.mixin.Call.prototype = {
// we make a final decision.
for (m = 0; m < mixins.length; m++) {
mixin = mixins[m];
mixin = mixins[m].rule;
mixinPath = mixins[m].path;
isRecursive = false;
for(f = 0; f < env.frames.length; f++) {
if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
@@ -48,28 +78,14 @@ tree.mixin.Call.prototype = {
if (isRecursive) {
continue;
}
if (mixin.matchArgs(args, env)) {
candidate = {mixin: mixin, group: defNone};
if (mixin.matchCondition) {
for (f = 0; f < 2; f++) {
defaultFunc.value(f);
conditionResult[f] = mixin.matchCondition(args, env);
}
if (conditionResult[0] || conditionResult[1]) {
if (conditionResult[0] != conditionResult[1]) {
candidate.group = conditionResult[1] ?
defTrue : defFalse;
}
candidates.push(candidate);
}
if (mixin.matchArgs(args, env)) {
candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
if (candidate.group!==defFalseEitherCase) {
candidates.push(candidate);
}
else {
candidates.push(candidate);
}
match = true;
}
}
@@ -133,6 +149,7 @@ tree.mixin.Call.prototype = {
message: this.selector.toCSS().trim() + " is undefined",
index: this.index, filename: this.currentFileInfo.filename };
}
},
format: function (args) {
return this.selector.toCSS().trim() + '(' +

View File

@@ -238,9 +238,9 @@ tree.Ruleset.prototype = {
var rules = this.rules;
if (rules) { rules.unshift(rule); } else { this.rules = [ rule ]; }
},
find: function (selector, self) {
find: function (selector, self, filter) {
self = self || this;
var rules = [], match,
var rules = [], match, foundMixins,
key = selector.toCSS();
if (key in this._lookups) { return this._lookups[key]; }
@@ -251,10 +251,15 @@ tree.Ruleset.prototype = {
match = selector.match(rule.selectors[j]);
if (match) {
if (selector.elements.length > match) {
Array.prototype.push.apply(rules, rule.find(
new(tree.Selector)(selector.elements.slice(match)), self));
if (!filter || filter(rule)) {
foundMixins = rule.find(new(tree.Selector)(selector.elements.slice(match)), self, filter);
for (var i = 0; i < foundMixins.length; ++i) {
foundMixins[i].path.push(rule);
}
Array.prototype.push.apply(rules, foundMixins);
}
} else {
rules.push(rule);
rules.push({ rule: rule, path: []});
}
break;
}

View File

@@ -91,3 +91,11 @@
.mixin-generated-class {
a: 1;
}
#guarded-caller {
guarded: namespace;
silent: namespace;
guarded: with default;
}
#guarded-deeper {
should: match 1;
}

View File

@@ -171,3 +171,58 @@
}
#ns > .mixin-for-root-usage(1);
@namespaceGuard: 1;
#guarded when (@namespaceGuard>0) {
#deeper {
.mixin() {
guarded: namespace;
}
}
}
#guarded() when (@namespaceGuard>0) {
#deeper {
.mixin() {
silent: namespace;
}
}
}
#guarded(@variable) when (@namespaceGuard>0) {
#deeper {
.mixin() {
should: not match because namespace argument;
}
}
}
#guarded(@variable: default) when (@namespaceGuard>0) {
#deeper {
.mixin() {
guarded: with default;
}
}
}
#guarded when (@namespaceGuard<0) {
#deeper {
.mixin() {
should: not match because namespace guard;
}
}
}
#guarded-caller {
#guarded > #deeper > .mixin();
}
#top {
#deeper when (@namespaceGuard<0) {
.mixin(@a) {
should: not match because namespace guard;
}
}
#deeper() when (@namespaceGuard>0) {
.mixin(@a) {
should: match @a;
}
}
}
#guarded-deeper {
#top > #deeper > .mixin(1);
}