Skip to content

Commit f0d7649

Browse files
authored
Merge pull request #2264 from mgreter/bugfix/issue-2060
Fix error case for parent compound selectors check
2 parents 312240c + bec39a1 commit f0d7649

File tree

5 files changed

+25
-13
lines changed

5 files changed

+25
-13
lines changed

src/ast.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,25 +1199,25 @@ namespace Sass {
11991199

12001200
}
12011201

1202-
Selector_List_Ptr Selector_List::resolve_parent_refs(Context& ctx, Selector_List_Ptr ps, bool implicit_parent)
1202+
Selector_List_Ptr Selector_List::resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent)
12031203
{
1204-
if (!this->has_parent_ref()/* && !implicit_parent*/) return this;
1204+
if (!this->has_parent_ref()) return this;
12051205
Selector_List_Ptr ss = SASS_MEMORY_NEW(Selector_List, pstate());
1206+
Selector_List_Ptr ps = &pstack.back();
12061207
for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) {
1207-
Selector_List_Obj list = SASS_MEMORY_NEW(Selector_List, pstate());
1208-
list->append(ps->at(pi));
12091208
for (size_t si = 0, sL = this->length(); si < sL; ++si) {
1210-
Selector_List_Obj rv = at(si)->resolve_parent_refs(ctx, &list, implicit_parent);
1209+
Selector_List_Obj rv = at(si)->resolve_parent_refs(ctx, pstack, implicit_parent);
12111210
ss->concat(&rv);
12121211
}
12131212
}
12141213
return ss;
12151214
}
12161215

1217-
Selector_List_Ptr Complex_Selector::resolve_parent_refs(Context& ctx, Selector_List_Ptr parents, bool implicit_parent)
1216+
Selector_List_Ptr Complex_Selector::resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent)
12181217
{
12191218
Complex_Selector_Obj tail = this->tail();
12201219
Compound_Selector_Obj head = this->head();
1220+
Selector_List_Ptr parents = &pstack.back();
12211221

12221222
if (!this->has_real_parent_ref() && !implicit_parent) {
12231223
Selector_List_Ptr retval = SASS_MEMORY_NEW(Selector_List, pstate());
@@ -1226,7 +1226,7 @@ namespace Sass {
12261226
}
12271227

12281228
// first resolve_parent_refs the tail (which may return an expanded list)
1229-
Selector_List_Obj tails = tail ? tail->resolve_parent_refs(ctx, parents, implicit_parent) : 0;
1229+
Selector_List_Obj tails = tail ? tail->resolve_parent_refs(ctx, pstack, implicit_parent) : 0;
12301230

12311231
if (head && head->length() > 0) {
12321232

@@ -1235,6 +1235,16 @@ namespace Sass {
12351235
// mix parent complex selector into the compound list
12361236
if (SASS_MEMORY_CAST(Parent_Selector, (*head)[0])) {
12371237
retval = SASS_MEMORY_NEW(Selector_List, pstate());
1238+
1239+
// it turns out that real parent references reach
1240+
// across @at-root rules, which comes unexpected
1241+
if (parents == NULL && head->has_real_parent_ref()) {
1242+
int i = pstack.size() - 1;
1243+
while (!parents && i > -1) {
1244+
parents = &pstack.at(i--);
1245+
}
1246+
}
1247+
12381248
if (parents && parents->length()) {
12391249
if (tails && tails->length() > 0) {
12401250
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
@@ -1329,7 +1339,7 @@ namespace Sass {
13291339
for (Simple_Selector_Obj ss : head->elements()) {
13301340
if (Wrapped_Selector_Ptr ws = SASS_MEMORY_CAST(Wrapped_Selector, ss)) {
13311341
if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, ws->selector())) {
1332-
if (parents) ws->selector(sl->resolve_parent_refs(ctx, parents, implicit_parent));
1342+
if (parents) ws->selector(sl->resolve_parent_refs(ctx, pstack, implicit_parent));
13331343
}
13341344
}
13351345
}

src/ast.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,7 +2909,7 @@ namespace Sass {
29092909
Complex_Selector_Obj innermost() { return last(); };
29102910

29112911
size_t length() const;
2912-
Selector_List_Ptr resolve_parent_refs(Context& ctx, Selector_List_Ptr parents, bool implicit_parent = true);
2912+
Selector_List_Ptr resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
29132913
virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
29142914
virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
29152915
virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");
@@ -3030,7 +3030,7 @@ namespace Sass {
30303030
virtual bool has_parent_ref();
30313031
virtual bool has_real_parent_ref();
30323032
void remove_parent_selectors();
3033-
Selector_List_Ptr resolve_parent_refs(Context& ctx, Selector_List_Ptr parents, bool implicit_parent = true);
3033+
Selector_List_Ptr resolve_parent_refs(Context& ctx, std::vector<Selector_List_Obj>& pstack, bool implicit_parent = true);
30343034
virtual bool is_superselector_of(Compound_Selector_Obj sub, std::string wrapping = "");
30353035
virtual bool is_superselector_of(Complex_Selector_Obj sub, std::string wrapping = "");
30363036
virtual bool is_superselector_of(Selector_List_Obj sub, std::string wrapping = "");

src/eval.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,7 @@ namespace Sass {
16771677
Selector_List_Ptr Eval::operator()(Complex_Selector_Ptr s)
16781678
{
16791679
bool implicit_parent = !exp.old_at_root_without_rule;
1680-
return s->resolve_parent_refs(ctx, &selector(), implicit_parent);
1680+
return s->resolve_parent_refs(ctx, exp.selector_stack, implicit_parent);
16811681
}
16821682

16831683
// XXX: this is never hit via spec tests

src/expand.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ namespace Sass {
136136
Selector_List_Obj ll = selector_stack.at(i);
137137
has_parent_selector = ll != 0 && ll->length() > 0;
138138
}
139-
if (!has_parent_selector) {
139+
if (sel->has_real_parent_ref() && !has_parent_selector) {
140140
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), backtrace());
141141
}
142142
}

src/functions.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1804,7 +1804,9 @@ namespace Sass {
18041804
for(;itr != parsedSelectors.end(); ++itr) {
18051805
Selector_List_Obj child = *itr;
18061806
std::vector<Complex_Selector_Obj> exploded;
1807-
Selector_List_Obj rv = child->resolve_parent_refs(ctx, &result);
1807+
selector_stack.push_back(&result);
1808+
Selector_List_Obj rv = child->resolve_parent_refs(ctx, selector_stack);
1809+
selector_stack.pop_back();
18081810
for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
18091811
exploded.push_back((*rv)[m]);
18101812
}

0 commit comments

Comments
 (0)