Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.

Commit 5f3558d

Browse files
committed
Merge pull request #618 from xzyfer/feat/hoist-feature-queries
Hoist selectors in feature queries
2 parents 068add9 + 40693d5 commit 5f3558d

File tree

6 files changed

+92
-8
lines changed

6 files changed

+92
-8
lines changed

ast.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,10 @@ namespace Sass {
345345
///////////////////
346346
class Feature_Block : public Has_Block {
347347
ADD_PROPERTY(Feature_Queries*, feature_queries);
348+
ADD_PROPERTY(Selector*, selector);
348349
public:
349350
Feature_Block(string path, Position position, Feature_Queries* fqs, Block* b)
350-
: Has_Block(path, position, b), feature_queries_(fqs)
351+
: Has_Block(path, position, b), feature_queries_(fqs), selector_(0)
351352
{ }
352353
bool is_hoistable() { return true; }
353354
ATTACH_OPERATIONS();

expand.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ namespace Sass {
9595
f->position(),
9696
static_cast<Feature_Queries*>(feature_queries),
9797
f->block()->perform(this)->block());
98+
ff->selector(selector_stack.back());
9899
return ff;
99100
}
100101

extend.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,10 @@ namespace Sass {
19391939

19401940
void Extend::operator()(Feature_Block* pFeatureBlock)
19411941
{
1942+
if (pFeatureBlock->selector()) {
1943+
extendObjectWithSelectorAndBlock(pFeatureBlock, ctx, subset_map);
1944+
}
1945+
19421946
pFeatureBlock->block()->perform(this);
19431947
}
19441948

output_nested.cpp

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,82 @@ namespace Sass {
124124
}
125125
}
126126

127+
void Output_Nested::operator()(Feature_Block* f)
128+
{
129+
Feature_Queries* q = f->feature_queries();
130+
Block* b = f->block();
131+
132+
// Filter out feature blocks that aren't printable (process its children though)
133+
if (!Util::isPrintable(f)) {
134+
for (size_t i = 0, L = b->length(); i < L; ++i) {
135+
Statement* stm = (*b)[i];
136+
if (dynamic_cast<Has_Block*>(stm)) {
137+
stm->perform(this);
138+
}
139+
}
140+
return;
141+
}
142+
143+
indent();
144+
ctx->source_map.add_mapping(f);
145+
append_to_buffer("@supports ");
146+
q->perform(this);
147+
append_to_buffer(" {\n");
148+
149+
Selector* e = f->selector();
150+
if (e && b->has_non_hoistable()) {
151+
// JMA - hoisted, output the non-hoistable in a nested block, followed by the hoistable
152+
++indentation;
153+
indent();
154+
e->perform(this);
155+
append_to_buffer(" {\n");
156+
157+
++indentation;
158+
for (size_t i = 0, L = b->length(); i < L; ++i) {
159+
Statement* stm = (*b)[i];
160+
if (!stm->is_hoistable()) {
161+
if (!stm->block()) indent();
162+
stm->perform(this);
163+
append_to_buffer("\n");
164+
}
165+
}
166+
--indentation;
167+
168+
buffer.erase(buffer.length()-1);
169+
if (ctx) ctx->source_map.remove_line();
170+
append_to_buffer(" }\n");
171+
--indentation;
172+
173+
++indentation;
174+
++indentation;
175+
for (size_t i = 0, L = b->length(); i < L; ++i) {
176+
Statement* stm = (*b)[i];
177+
if (stm->is_hoistable()) {
178+
stm->perform(this);
179+
}
180+
}
181+
--indentation;
182+
--indentation;
183+
}
184+
else {
185+
// JMA - not hoisted, just output in order
186+
++indentation;
187+
for (size_t i = 0, L = b->length(); i < L; ++i) {
188+
Statement* stm = (*b)[i];
189+
if (!stm->is_hoistable()) {
190+
if (!stm->block()) indent();
191+
}
192+
stm->perform(this);
193+
append_to_buffer("\n");
194+
}
195+
--indentation;
196+
}
197+
198+
buffer.erase(buffer.length()-1);
199+
if (ctx) ctx->source_map.remove_line();
200+
append_to_buffer(" }\n");
201+
}
202+
127203
void Output_Nested::operator()(Media_Block* m)
128204
{
129205
List* q = m->media_queries();
@@ -139,7 +215,7 @@ namespace Sass {
139215
}
140216
return;
141217
}
142-
218+
143219
indent();
144220
ctx->source_map.add_mapping(m);
145221
append_to_buffer("@media ");
@@ -153,7 +229,7 @@ namespace Sass {
153229
indent();
154230
e->perform(this);
155231
append_to_buffer(" {\n");
156-
232+
157233
++indentation;
158234
for (size_t i = 0, L = b->length(); i < L; ++i) {
159235
Statement* stm = (*b)[i];
@@ -164,12 +240,12 @@ namespace Sass {
164240
}
165241
}
166242
--indentation;
167-
243+
168244
buffer.erase(buffer.length()-1);
169245
if (ctx) ctx->source_map.remove_line();
170246
append_to_buffer(" }\n");
171247
--indentation;
172-
248+
173249
++indentation;
174250
++indentation;
175251
for (size_t i = 0, L = b->length(); i < L; ++i) {
@@ -194,7 +270,7 @@ namespace Sass {
194270
}
195271
--indentation;
196272
}
197-
273+
198274
buffer.erase(buffer.length()-1);
199275
if (ctx) ctx->source_map.remove_line();
200276
append_to_buffer(" }\n");

output_nested.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace Sass {
4343
virtual void operator()(Block*);
4444
virtual void operator()(Ruleset*);
4545
// virtual void operator()(Propset*);
46+
virtual void operator()(Feature_Block*);
4647
virtual void operator()(Media_Block*);
4748
virtual void operator()(At_Rule*);
4849
// virtual void operator()(Declaration*);

util.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,13 @@ namespace Sass {
5555

5656
Block* b = f->block();
5757

58-
bool hasSelectors = false;
58+
bool hasSelectors = f->selector() && static_cast<Selector_List*>(f->selector())->length() > 0;
59+
5960
bool hasDeclarations = false;
6061
bool hasPrintableChildBlocks = false;
6162
for (size_t i = 0, L = b->length(); i < L; ++i) {
6263
Statement* stm = (*b)[i];
63-
if (!stm->is_hoistable() && !hasSelectors) {
64+
if (!stm->is_hoistable() && f->selector() != NULL && !hasSelectors) {
6465
// If a statement isn't hoistable, the selectors apply to it. If there are no selectors (a selector list of length 0),
6566
// then those statements aren't considered printable. That means there was a placeholder that was removed. If the selector
6667
// is NULL, then that means there was never a wrapping selector and it is printable (think of a top level media block with

0 commit comments

Comments
 (0)