@@ -1711,7 +1711,8 @@ namespace Sass {
17111711 static bool complexSelectorHasExtension (
17121712 Complex_Selector* pComplexSelector,
17131713 Context& ctx,
1714- ExtensionSubsetMap& subset_map) {
1714+ ExtensionSubsetMap& subset_map,
1715+ std::set<Compound_Selector>& seen) {
17151716
17161717 bool hasExtension = false ;
17171718
@@ -1721,16 +1722,18 @@ namespace Sass {
17211722 Compound_Selector* pHead = pIter->head ();
17221723
17231724 if (pHead) {
1724- for (Simple_Selector* pSimple : *pHead) {
1725- if (Wrapped_Selector* ws = dynamic_cast <Wrapped_Selector*>(pSimple)) {
1726- if (Selector_List* sl = dynamic_cast <Selector_List*>(ws->selector ())) {
1727- for (Complex_Selector* cs : sl->elements ()) {
1728- while (cs) {
1729- if (complexSelectorHasExtension (cs, ctx, subset_map)) {
1730- hasExtension = true ;
1731- break ;
1725+ if (seen.find (*pHead) == seen.end ()) {
1726+ for (Simple_Selector* pSimple : *pHead) {
1727+ if (Wrapped_Selector* ws = dynamic_cast <Wrapped_Selector*>(pSimple)) {
1728+ if (Selector_List* sl = dynamic_cast <Selector_List*>(ws->selector ())) {
1729+ for (Complex_Selector* cs : sl->elements ()) {
1730+ while (cs) {
1731+ if (complexSelectorHasExtension (cs, ctx, subset_map, seen)) {
1732+ hasExtension = true ;
1733+ break ;
1734+ }
1735+ cs = cs->tail ();
17321736 }
1733- cs = cs->tail ();
17341737 }
17351738 }
17361739 }
@@ -1907,6 +1910,14 @@ namespace Sass {
19071910 This is the equivalent of ruby's CommaSequence.do_extend.
19081911 */
19091912 Selector_List* Extend::extendSelectorList (Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool & extendedSomething) {
1913+ std::set<Compound_Selector> seen;
1914+ return extendSelectorList (pSelectorList, ctx, subset_map, isReplace, extendedSomething, seen);
1915+ }
1916+
1917+ /*
1918+ This is the equivalent of ruby's CommaSequence.do_extend.
1919+ */
1920+ Selector_List* Extend::extendSelectorList (Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool & extendedSomething, std::set<Compound_Selector>& seen) {
19101921
19111922 Selector_List* pNewSelectors = SASS_MEMORY_NEW (ctx.mem , Selector_List, pSelectorList->pstate (), pSelectorList->length ());
19121923
@@ -1920,19 +1931,18 @@ namespace Sass {
19201931 // run through the extend code (which does a data model transformation), check if there is anything to extend before doing
19211932 // the extend. We might be able to optimize extendComplexSelector, but this approach keeps us closer to ruby sass (which helps
19221933 // when debugging).
1923- if (!complexSelectorHasExtension (pSelector, ctx, subset_map)) {
1934+ if (!complexSelectorHasExtension (pSelector, ctx, subset_map, seen )) {
19241935 *pNewSelectors << pSelector;
19251936 continue ;
19261937 }
19271938
19281939 extendedSomething = true ;
19291940
1930- std::set<Compound_Selector> seen;
1931-
19321941 Node extendedSelectors = extendComplexSelector (pSelector, ctx, subset_map, seen, isReplace, true );
19331942 if (!pSelector->has_placeholder ()) {
19341943 if (!extendedSelectors.contains (complexSelectorToNode (pSelector, ctx), true /* simpleSelectorOrderDependent*/ )) {
19351944 *pNewSelectors << pSelector;
1945+ continue ;
19361946 }
19371947 }
19381948
@@ -1955,7 +1965,9 @@ namespace Sass {
19551965 // process tails
19561966 while (cur) {
19571967 // process header
1958- if (cur->head ()) {
1968+ if (cur->head () && seen.find (*cur->head ()) == seen.end ()) {
1969+ std::set<Compound_Selector> recseen (seen);
1970+ recseen.insert (*cur->head ());
19591971 // create a copy since we add multiple items if stuff get unwrapped
19601972 Compound_Selector* cpy_head = SASS_MEMORY_NEW (ctx.mem , Compound_Selector, cur->pstate ());
19611973 for (Simple_Selector* hs : *cur->head ()) {
@@ -1969,14 +1981,19 @@ namespace Sass {
19691981 // has wrapped selectors
19701982 else {
19711983 // extend the inner list of wrapped selector
1972- Selector_List* ext_sl = extendSelectorList (sl, ctx, subset_map);
1984+ Selector_List* ext_sl = extendSelectorList (sl, ctx, subset_map, recseen );
19731985 for (size_t i = 0 ; i < ext_sl->length (); i += 1 ) {
19741986 if (Complex_Selector* ext_cs = ext_sl->at (i)) {
19751987 // create clones for wrapped selector and the inner list
19761988 Wrapped_Selector* cpy_ws = SASS_MEMORY_NEW (ctx.mem , Wrapped_Selector, *ws);
19771989 Selector_List* cpy_ws_sl = SASS_MEMORY_NEW (ctx.mem , Selector_List, sl->pstate ());
19781990 // remove parent selectors from inner selector
1979- if (ext_cs->first ()) *cpy_ws_sl << ext_cs->first ();
1991+ if (ext_cs->first ()) {
1992+ if (ext_cs->first ()->has_wrapped_selector ()) {
1993+ continue ; // ignore this case for now
1994+ }
1995+ *cpy_ws_sl << ext_cs->first ();
1996+ }
19801997 // assign list to clone
19811998 cpy_ws->selector (cpy_ws_sl);
19821999 // append the clone
0 commit comments