sassc 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Rakefile +1 -3
  5. data/ext/extconf.rb +13 -5
  6. data/ext/libsass/VERSION +1 -1
  7. data/ext/libsass/include/sass/base.h +2 -1
  8. data/ext/libsass/include/sass/context.h +1 -0
  9. data/ext/libsass/src/ast.cpp +49 -59
  10. data/ext/libsass/src/ast.hpp +263 -102
  11. data/ext/libsass/src/ast_def_macros.hpp +8 -0
  12. data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
  13. data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
  14. data/ext/libsass/src/ast_helpers.hpp +292 -0
  15. data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
  16. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  17. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  18. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  19. data/ext/libsass/src/ast_selectors.cpp +559 -1001
  20. data/ext/libsass/src/ast_selectors.hpp +311 -367
  21. data/ext/libsass/src/ast_supports.cpp +1 -17
  22. data/ext/libsass/src/ast_values.cpp +216 -29
  23. data/ext/libsass/src/ast_values.hpp +42 -33
  24. data/ext/libsass/src/bind.cpp +1 -1
  25. data/ext/libsass/src/cencode.c +4 -6
  26. data/ext/libsass/src/check_nesting.cpp +5 -6
  27. data/ext/libsass/src/check_nesting.hpp +4 -0
  28. data/ext/libsass/src/color_maps.cpp +11 -10
  29. data/ext/libsass/src/color_maps.hpp +0 -8
  30. data/ext/libsass/src/constants.cpp +5 -0
  31. data/ext/libsass/src/constants.hpp +6 -0
  32. data/ext/libsass/src/context.cpp +30 -60
  33. data/ext/libsass/src/context.hpp +8 -20
  34. data/ext/libsass/src/cssize.cpp +36 -120
  35. data/ext/libsass/src/cssize.hpp +4 -10
  36. data/ext/libsass/src/dart_helpers.hpp +199 -0
  37. data/ext/libsass/src/debugger.hpp +364 -207
  38. data/ext/libsass/src/emitter.cpp +3 -4
  39. data/ext/libsass/src/emitter.hpp +0 -2
  40. data/ext/libsass/src/environment.hpp +5 -0
  41. data/ext/libsass/src/error_handling.cpp +21 -0
  42. data/ext/libsass/src/error_handling.hpp +25 -3
  43. data/ext/libsass/src/eval.cpp +33 -153
  44. data/ext/libsass/src/eval.hpp +11 -13
  45. data/ext/libsass/src/eval_selectors.cpp +75 -0
  46. data/ext/libsass/src/expand.cpp +214 -167
  47. data/ext/libsass/src/expand.hpp +26 -6
  48. data/ext/libsass/src/extender.cpp +1186 -0
  49. data/ext/libsass/src/extender.hpp +399 -0
  50. data/ext/libsass/src/extension.cpp +43 -0
  51. data/ext/libsass/src/extension.hpp +89 -0
  52. data/ext/libsass/src/file.cpp +15 -14
  53. data/ext/libsass/src/file.hpp +5 -12
  54. data/ext/libsass/src/fn_colors.cpp +12 -10
  55. data/ext/libsass/src/fn_lists.cpp +12 -11
  56. data/ext/libsass/src/fn_miscs.cpp +22 -34
  57. data/ext/libsass/src/fn_numbers.cpp +13 -6
  58. data/ext/libsass/src/fn_selectors.cpp +94 -124
  59. data/ext/libsass/src/fn_strings.cpp +16 -14
  60. data/ext/libsass/src/fn_utils.cpp +5 -6
  61. data/ext/libsass/src/fn_utils.hpp +9 -3
  62. data/ext/libsass/src/inspect.cpp +154 -117
  63. data/ext/libsass/src/inspect.hpp +10 -8
  64. data/ext/libsass/src/lexer.cpp +17 -81
  65. data/ext/libsass/src/lexer.hpp +5 -16
  66. data/ext/libsass/src/listize.cpp +22 -36
  67. data/ext/libsass/src/listize.hpp +8 -9
  68. data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
  69. data/ext/libsass/src/operation.hpp +27 -17
  70. data/ext/libsass/src/operators.cpp +1 -0
  71. data/ext/libsass/src/ordered_map.hpp +112 -0
  72. data/ext/libsass/src/output.cpp +30 -49
  73. data/ext/libsass/src/output.hpp +1 -1
  74. data/ext/libsass/src/parser.cpp +211 -381
  75. data/ext/libsass/src/parser.hpp +17 -15
  76. data/ext/libsass/src/parser_selectors.cpp +189 -0
  77. data/ext/libsass/src/permutate.hpp +140 -0
  78. data/ext/libsass/src/position.hpp +1 -1
  79. data/ext/libsass/src/prelexer.cpp +6 -6
  80. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  81. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  82. data/ext/libsass/src/sass.hpp +1 -0
  83. data/ext/libsass/src/sass2scss.cpp +4 -4
  84. data/ext/libsass/src/sass_context.cpp +42 -91
  85. data/ext/libsass/src/sass_context.hpp +2 -2
  86. data/ext/libsass/src/sass_functions.cpp +1 -1
  87. data/ext/libsass/src/sass_values.cpp +0 -1
  88. data/ext/libsass/src/stylesheet.cpp +22 -0
  89. data/ext/libsass/src/stylesheet.hpp +57 -0
  90. data/ext/libsass/src/to_value.cpp +2 -2
  91. data/ext/libsass/src/to_value.hpp +1 -1
  92. data/ext/libsass/src/units.cpp +5 -3
  93. data/ext/libsass/src/util.cpp +10 -12
  94. data/ext/libsass/src/util.hpp +2 -3
  95. data/ext/libsass/src/util_string.cpp +111 -61
  96. data/ext/libsass/src/util_string.hpp +61 -8
  97. data/lib/sassc/engine.rb +5 -3
  98. data/lib/sassc/functions_handler.rb +8 -8
  99. data/lib/sassc/native.rb +1 -1
  100. data/lib/sassc/script.rb +4 -4
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/functions_test.rb +18 -1
  103. data/test/native_test.rb +1 -1
  104. metadata +17 -12
  105. data/ext/libsass/src/extend.cpp +0 -2132
  106. data/ext/libsass/src/extend.hpp +0 -86
  107. data/ext/libsass/src/node.cpp +0 -322
  108. data/ext/libsass/src/node.hpp +0 -118
  109. data/ext/libsass/src/paths.hpp +0 -71
  110. data/ext/libsass/src/sass_util.cpp +0 -152
  111. data/ext/libsass/src/sass_util.hpp +0 -256
  112. data/ext/libsass/src/subset_map.cpp +0 -58
  113. data/ext/libsass/src/subset_map.hpp +0 -76
@@ -0,0 +1,75 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+ #include "expand.hpp"
5
+ #include "eval.hpp"
6
+ #include "ast.hpp"
7
+
8
+
9
+ namespace Sass {
10
+
11
+ SelectorList* Eval::operator()(SelectorList* s)
12
+ {
13
+ std::vector<SelectorListObj> rv;
14
+ SelectorListObj sl = SASS_MEMORY_NEW(SelectorList, s->pstate());
15
+ for (size_t i = 0, iL = s->length(); i < iL; ++i) {
16
+ rv.push_back(operator()(s->get(i)));
17
+ }
18
+
19
+ // we should actually permutate parent first
20
+ // but here we have permutated the selector first
21
+ size_t round = 0;
22
+ while (round != std::string::npos) {
23
+ bool abort = true;
24
+ for (size_t i = 0, iL = rv.size(); i < iL; ++i) {
25
+ if (rv[i]->length() > round) {
26
+ sl->append((*rv[i])[round]);
27
+ abort = false;
28
+ }
29
+ }
30
+ if (abort) {
31
+ round = std::string::npos;
32
+ }
33
+ else {
34
+ ++round;
35
+ }
36
+
37
+ }
38
+ return sl.detach();
39
+ }
40
+
41
+ SelectorComponent* Eval::operator()(SelectorComponent* s)
42
+ {
43
+ return {};
44
+ }
45
+
46
+ SelectorList* Eval::operator()(ComplexSelector* s)
47
+ {
48
+ bool implicit_parent = !exp.old_at_root_without_rule;
49
+ if (is_in_selector_schema) exp.pushNullSelector();
50
+ SelectorListObj other = s->resolve_parent_refs(
51
+ exp.getOriginalStack(), traces, implicit_parent);
52
+ if (is_in_selector_schema) exp.popNullSelector();
53
+
54
+ for (size_t i = 0; i < other->length(); i++) {
55
+ ComplexSelectorObj sel = other->at(i);
56
+ for (size_t n = 0; n < sel->length(); n++) {
57
+ if (CompoundSelectorObj comp = Cast<CompoundSelector>(sel->at(n))) {
58
+ sel->at(n) = operator()(comp);
59
+ }
60
+ }
61
+ }
62
+
63
+ return other.detach();
64
+ }
65
+
66
+ CompoundSelector* Eval::operator()(CompoundSelector* s)
67
+ {
68
+ for (size_t i = 0; i < s->length(); i++) {
69
+ SimpleSelector* ss = s->at(i);
70
+ // skip parents here (called via resolve_parent_refs)
71
+ s->at(i) = Cast<SimpleSelector>(ss->perform(this));
72
+ }
73
+ return s;
74
+ }
75
+ }
@@ -19,7 +19,7 @@ namespace Sass {
19
19
  // simple endless recursion protection
20
20
  const size_t maxRecursion = 500;
21
21
 
22
- Expand::Expand(Context& ctx, Env* env, SelectorStack* stack)
22
+ Expand::Expand(Context& ctx, Env* env, SelectorStack* stack, SelectorStack* originals)
23
23
  : ctx(ctx),
24
24
  traces(ctx.traces),
25
25
  eval(Eval(*this)),
@@ -27,19 +27,32 @@ namespace Sass {
27
27
  in_keyframes(false),
28
28
  at_root_without_rule(false),
29
29
  old_at_root_without_rule(false),
30
- env_stack(EnvStack()),
31
- block_stack(BlockStack()),
32
- call_stack(CallStack()),
33
- selector_stack(SelectorStack()),
34
- media_stack(MediaStack())
30
+ env_stack(),
31
+ block_stack(),
32
+ call_stack(),
33
+ selector_stack(),
34
+ originalStack(),
35
+ mediaStack()
35
36
  {
36
37
  env_stack.push_back(nullptr);
37
38
  env_stack.push_back(env);
38
39
  block_stack.push_back(nullptr);
39
40
  call_stack.push_back({});
40
- if (stack == NULL) { selector_stack.push_back({}); }
41
- else { selector_stack.insert(selector_stack.end(), stack->begin(), stack->end()); }
42
- media_stack.push_back(nullptr);
41
+ if (stack == NULL) { pushToSelectorStack({}); }
42
+ else {
43
+ for (auto item : *stack) {
44
+ if (item.isNull()) pushToSelectorStack({});
45
+ else pushToSelectorStack(item);
46
+ }
47
+ }
48
+ if (originals == NULL) { pushToOriginalStack({}); }
49
+ else {
50
+ for (auto item : *stack) {
51
+ if (item.isNull()) pushToOriginalStack({});
52
+ else pushToOriginalStack(item);
53
+ }
54
+ }
55
+ mediaStack.push_back({});
43
56
  }
44
57
 
45
58
  Env* Expand::environment()
@@ -49,11 +62,80 @@ namespace Sass {
49
62
  return 0;
50
63
  }
51
64
 
52
- Selector_List_Obj Expand::selector()
65
+ void Expand::pushNullSelector()
66
+ {
67
+ pushToSelectorStack({});
68
+ pushToOriginalStack({});
69
+ }
70
+
71
+ void Expand::popNullSelector()
72
+ {
73
+ popFromOriginalStack();
74
+ popFromSelectorStack();
75
+ }
76
+
77
+ SelectorStack Expand::getOriginalStack()
78
+ {
79
+ return originalStack;
80
+ }
81
+
82
+ SelectorStack Expand::getSelectorStack()
53
83
  {
54
- if (selector_stack.size() > 0)
55
- return selector_stack.back();
56
- return {};
84
+ return selector_stack;
85
+ }
86
+
87
+ SelectorListObj& Expand::selector()
88
+ {
89
+ if (selector_stack.size() > 0) {
90
+ auto& sel = selector_stack.back();
91
+ if (sel.isNull()) return sel;
92
+ return sel;
93
+ }
94
+ // Avoid the need to return copies
95
+ // We always want an empty first item
96
+ selector_stack.push_back({});
97
+ return selector_stack.back();;
98
+ }
99
+
100
+ SelectorListObj& Expand::original()
101
+ {
102
+ if (originalStack.size() > 0) {
103
+ auto& sel = originalStack.back();
104
+ if (sel.isNull()) return sel;
105
+ return sel;
106
+ }
107
+ // Avoid the need to return copies
108
+ // We always want an empty first item
109
+ originalStack.push_back({});
110
+ return originalStack.back();
111
+ }
112
+
113
+ SelectorListObj Expand::popFromSelectorStack()
114
+ {
115
+ SelectorListObj last = selector_stack.back();
116
+ if (selector_stack.size() > 0)
117
+ selector_stack.pop_back();
118
+ if (last.isNull()) return {};
119
+ return last;
120
+ }
121
+
122
+ void Expand::pushToSelectorStack(SelectorListObj selector)
123
+ {
124
+ selector_stack.push_back(selector);
125
+ }
126
+
127
+ SelectorListObj Expand::popFromOriginalStack()
128
+ {
129
+ SelectorListObj last = originalStack.back();
130
+ if (originalStack.size() > 0)
131
+ originalStack.pop_back();
132
+ if (last.isNull()) return {};
133
+ return last;
134
+ }
135
+
136
+ void Expand::pushToOriginalStack(SelectorListObj selector)
137
+ {
138
+ originalStack.push_back(selector);
57
139
  }
58
140
 
59
141
  // blocks create new variable scopes
@@ -87,69 +169,55 @@ namespace Sass {
87
169
  if (in_keyframes) {
88
170
  Block* bb = operator()(r->block());
89
171
  Keyframe_Rule_Obj k = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), bb);
90
- if (r->selector()) {
91
- if (Selector_List* s = r->selector()) {
92
- selector_stack.push_back({});
93
- k->name(s->eval(eval));
94
- selector_stack.pop_back();
172
+ if (r->schema()) {
173
+ pushNullSelector();
174
+ k->name(eval(r->schema()));
175
+ popNullSelector();
176
+ }
177
+ else if (r->selector()) {
178
+ if (SelectorListObj s = r->selector()) {
179
+ pushNullSelector();
180
+ k->name(eval(s));
181
+ popNullSelector();
95
182
  }
96
183
  }
184
+
97
185
  return k.detach();
98
186
  }
99
187
 
100
- // reset when leaving scope
101
- LOCAL_FLAG(at_root_without_rule, false);
102
-
103
- // `&` is allowed in `@at-root`!
104
- bool has_parent_selector = false;
105
- for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
106
- Selector_List_Obj ll = selector_stack.at(i);
107
- has_parent_selector = ll != nullptr && ll->length() > 0;
108
- }
109
-
110
- Selector_List_Obj sel = r->selector();
111
- if (sel) sel = sel->eval(eval);
112
-
113
- // check for parent selectors in base level rules
114
- if (r->is_root() || (block_stack.back() && block_stack.back()->is_root())) {
115
- if (Selector_List* selector_list = Cast<Selector_List>(r->selector())) {
116
- for (Complex_Selector_Obj complex_selector : selector_list->elements()) {
117
- Complex_Selector* tail = complex_selector;
118
- while (tail) {
119
- if (tail->head()) for (Simple_Selector_Obj header : tail->head()->elements()) {
120
- Parent_Selector* ptr = Cast<Parent_Selector>(header);
121
- if (ptr == NULL || (!ptr->real() || has_parent_selector)) continue;
122
- std::string sel_str(complex_selector->to_string(ctx.c_options));
123
- error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), traces);
124
- }
125
- tail = tail->tail();
126
- }
127
- }
128
- }
129
- }
130
- else {
131
- if (sel->length() == 0 || sel->has_parent_ref()) {
132
- if (sel->has_real_parent_ref() && !has_parent_selector) {
133
- error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), traces);
134
- }
188
+ if (r->schema()) {
189
+ SelectorListObj sel = eval(r->schema());
190
+ r->selector(sel);
191
+ bool chroot = sel->has_real_parent_ref();
192
+ for (auto complex : sel->elements()) {
193
+ complex->chroots(chroot);
135
194
  }
195
+
136
196
  }
137
197
 
198
+ // reset when leaving scope
199
+ LOCAL_FLAG(at_root_without_rule, false);
200
+
201
+ SelectorListObj evaled = eval(r->selector());
138
202
  // do not connect parent again
139
- sel->remove_parent_selectors();
140
- selector_stack.push_back(sel);
141
203
  Env env(environment());
142
204
  if (block_stack.back()->is_root()) {
143
205
  env_stack.push_back(&env);
144
206
  }
145
- sel->set_media_block(media_stack.back());
146
207
  Block_Obj blk;
208
+ pushToSelectorStack(evaled);
209
+ // The copy is needed for parent reference evaluation
210
+ // dart-sass stores it as `originalSelector` member
211
+ pushToOriginalStack(SASS_MEMORY_COPY(evaled));
212
+ ctx.extender.addSelector(evaled, mediaStack.back());
147
213
  if (r->block()) blk = operator()(r->block());
214
+ popFromOriginalStack();
215
+ popFromSelectorStack();
148
216
  Ruleset* rr = SASS_MEMORY_NEW(Ruleset,
149
217
  r->pstate(),
150
- sel,
218
+ evaled,
151
219
  blk);
152
- selector_stack.pop_back();
220
+
153
221
  if (block_stack.back()->is_root()) {
154
222
  env_stack.pop_back();
155
223
  }
@@ -170,31 +238,44 @@ namespace Sass {
170
238
  return ff.detach();
171
239
  }
172
240
 
173
- Statement* Expand::operator()(Media_Block* m)
241
+ std::vector<CssMediaQuery_Obj> Expand::mergeMediaQueries(
242
+ const std::vector<CssMediaQuery_Obj>& lhs,
243
+ const std::vector<CssMediaQuery_Obj>& rhs)
174
244
  {
175
- Media_Block_Obj cpy = SASS_MEMORY_COPY(m);
176
- // Media_Blocks are prone to have circular references
177
- // Copy could leak memory if it does not get picked up
178
- // Looks like we are able to reset block reference for copy
179
- // Good as it will ensure a low memory overhead for this fix
180
- // So this is a cheap solution with a minimal price
181
- ctx.ast_gc.push_back(cpy); cpy->block({});
182
- Expression_Obj mq = eval(m->media_queries());
183
- std::string str_mq(mq->to_string(ctx.c_options));
245
+ std::vector<CssMediaQuery_Obj> queries;
246
+ for (CssMediaQuery_Obj query1 : lhs) {
247
+ for (CssMediaQuery_Obj query2 : rhs) {
248
+ CssMediaQuery_Obj result = query1->merge(query2);
249
+ if (result && !result->empty()) {
250
+ queries.push_back(result);
251
+ }
252
+ }
253
+ }
254
+ return queries;
255
+ }
256
+
257
+ Statement* Expand::operator()(MediaRule* m)
258
+ {
259
+ Expression_Obj mq = eval(m->schema());
260
+ std::string str_mq(mq->to_css(ctx.c_options));
184
261
  char* str = sass_copy_c_string(str_mq.c_str());
185
262
  ctx.strings.push_back(str);
186
- Parser p(Parser::from_c_str(str, ctx, traces, mq->pstate()));
187
- mq = p.parse_media_queries(); // re-assign now
188
- cpy->media_queries(mq);
189
- media_stack.push_back(cpy);
190
- Block_Obj blk = operator()(m->block());
191
- Media_Block* mm = SASS_MEMORY_NEW(Media_Block,
192
- m->pstate(),
193
- mq,
194
- blk);
195
- media_stack.pop_back();
196
- mm->tabs(m->tabs());
197
- return mm;
263
+ Parser parser(Parser::from_c_str(str, ctx, traces, mq->pstate()));
264
+ // Create a new CSS only representation of the media rule
265
+ CssMediaRuleObj css = SASS_MEMORY_NEW(CssMediaRule, m->pstate(), m->block());
266
+ std::vector<CssMediaQuery_Obj> parsed = parser.parseCssMediaQueries();
267
+ if (mediaStack.size() && mediaStack.back()) {
268
+ auto& parent = mediaStack.back()->elements();
269
+ css->concat(mergeMediaQueries(parent, parsed));
270
+ }
271
+ else {
272
+ css->concat(parsed);
273
+ }
274
+ mediaStack.push_back(css);
275
+ css->block(operator()(m->block()));
276
+ mediaStack.pop_back();
277
+ return css.detach();
278
+
198
279
  }
199
280
 
200
281
  Statement* Expand::operator()(At_Root_Block* a)
@@ -222,12 +303,12 @@ namespace Sass {
222
303
  {
223
304
  LOCAL_FLAG(in_keyframes, a->is_keyframes());
224
305
  Block* ab = a->block();
225
- Selector_List* as = a->selector();
306
+ SelectorList* as = a->selector();
226
307
  Expression* av = a->value();
227
- selector_stack.push_back({});
308
+ pushNullSelector();
228
309
  if (av) av = av->perform(&eval);
229
310
  if (as) as = eval(as);
230
- selector_stack.pop_back();
311
+ popNullSelector();
231
312
  Block* bb = ab ? operator()(ab) : NULL;
232
313
  Directive* aa = SASS_MEMORY_NEW(Directive,
233
314
  a->pstate(),
@@ -497,9 +578,8 @@ namespace Sass {
497
578
  if (expr->concrete_type() == Expression::MAP) {
498
579
  map = Cast<Map>(expr);
499
580
  }
500
- else if (Selector_List* ls = Cast<Selector_List>(expr)) {
501
- Listize listize;
502
- Expression_Obj rv = ls->perform(&listize);
581
+ else if (SelectorList * ls = Cast<SelectorList>(expr)) {
582
+ Expression_Obj rv = Listize::perform(ls);
503
583
  list = Cast<List>(rv);
504
584
  }
505
585
  else if (expr->concrete_type() != Expression::LIST) {
@@ -534,7 +614,7 @@ namespace Sass {
534
614
  }
535
615
  else {
536
616
  // bool arglist = list->is_arglist();
537
- if (list->length() == 1 && Cast<Selector_List>(list)) {
617
+ if (list->length() == 1 && Cast<SelectorList>(list)) {
538
618
  list = Cast<List>(list);
539
619
  }
540
620
  for (size_t i = 0, L = list->length(); i < L; ++i) {
@@ -595,87 +675,63 @@ namespace Sass {
595
675
  return 0;
596
676
  }
597
677
 
678
+ Statement* Expand::operator()(ExtendRule* e)
679
+ {
598
680
 
599
- void Expand::expand_selector_list(Selector_Obj s, Selector_List_Obj extender) {
600
-
601
- if (Selector_List_Obj sl = Cast<Selector_List>(s)) {
602
- for (Complex_Selector_Obj complex_selector : sl->elements()) {
603
- Complex_Selector_Obj tail = complex_selector;
604
- while (tail) {
605
- if (tail->head()) for (Simple_Selector_Obj header : tail->head()->elements()) {
606
- if (Cast<Parent_Selector>(header) == NULL) continue; // skip all others
607
- std::string sel_str(complex_selector->to_string(ctx.c_options));
608
- error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), traces);
609
- }
610
- tail = tail->tail();
611
- }
612
- }
681
+ // evaluate schema first
682
+ if (e->schema()) {
683
+ e->selector(eval(e->schema()));
684
+ e->isOptional(e->selector()->is_optional());
613
685
  }
686
+ // evaluate the selector
687
+ e->selector(eval(e->selector()));
614
688
 
689
+ if (e->selector()) {
615
690
 
616
- Selector_List_Obj contextualized = Cast<Selector_List>(s->perform(&eval));
617
- if (contextualized == nullptr) return;
618
- for (auto complex_sel : contextualized->elements()) {
619
- Complex_Selector_Obj c = complex_sel;
620
- if (!c->head() || c->tail()) {
621
- std::string sel_str(contextualized->to_string(ctx.c_options));
622
- error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), traces);
623
- }
624
- Compound_Selector_Obj target = c->head();
625
- if (contextualized->is_optional()) target->is_optional(true);
626
- for (size_t i = 0, L = extender->length(); i < L; ++i) {
627
- Complex_Selector_Obj sel = (*extender)[i];
628
- if (!(sel->head() && sel->head()->length() > 0 &&
629
- Cast<Parent_Selector>((*sel->head())[0])))
630
- {
631
- Compound_Selector_Obj hh = SASS_MEMORY_NEW(Compound_Selector, (*extender)[i]->pstate());
632
- hh->media_block((*extender)[i]->media_block());
633
- Complex_Selector_Obj ssel = SASS_MEMORY_NEW(Complex_Selector, (*extender)[i]->pstate());
634
- ssel->media_block((*extender)[i]->media_block());
635
- if (sel->has_line_feed()) ssel->has_line_feed(true);
636
- Parent_Selector_Obj ps = SASS_MEMORY_NEW(Parent_Selector, (*extender)[i]->pstate());
637
- ps->media_block((*extender)[i]->media_block());
638
- hh->append(ps);
639
- ssel->tail(sel);
640
- ssel->head(hh);
641
- sel = ssel;
691
+ for (auto complex : e->selector()->elements()) {
692
+
693
+ if (complex->length() != 1) {
694
+ error("complex selectors may not be extended.", complex->pstate(), traces);
642
695
  }
643
- // if (c->has_line_feed()) sel->has_line_feed(true);
644
- ctx.subset_map.put(target, std::make_pair(sel, target));
645
- }
646
- }
647
696
 
648
- }
697
+ if (const CompoundSelector* compound = complex->first()->getCompound()) {
698
+
699
+ if (compound->length() != 1) {
700
+
701
+ std::stringstream sels; bool addComma = false;
702
+ sels << "Compound selectors may no longer be extended.\n";
703
+ sels << "Consider `@extend ";
704
+ for (auto sel : compound->elements()) {
705
+ if (addComma) sels << ", ";
706
+ sels << sel->to_sass();
707
+ addComma = true;
708
+ }
709
+ sels << "` instead.\n";
710
+ sels << "See http://bit.ly/ExtendCompound for details.";
711
+
712
+ warning(sels.str(), compound->pstate());
713
+
714
+ // Make this an error once deprecation is over
715
+ for (SimpleSelectorObj simple : compound->elements()) {
716
+ // Pass every selector we ever see to extender (to make them findable for extend)
717
+ ctx.extender.addExtension(selector(), simple, mediaStack.back(), e->isOptional());
718
+ }
719
+
720
+ }
721
+ else {
722
+ // Pass every selector we ever see to extender (to make them findable for extend)
723
+ ctx.extender.addExtension(selector(), compound->first(), mediaStack.back(), e->isOptional());
724
+ }
649
725
 
650
- Statement* Expand::operator()(Extension* e)
651
- {
652
- if (Selector_List_Obj extender = selector()) {
653
- Selector_List* sl = e->selector();
654
- // abort on invalid selector
655
- if (sl == NULL) return NULL;
656
- if (Selector_Schema* schema = sl->schema()) {
657
- if (schema->has_real_parent_ref()) {
658
- // put root block on stack again (ignore parents)
659
- // selector schema must not connect in eval!
660
- block_stack.push_back(block_stack.at(1));
661
- sl = eval(sl->schema());
662
- block_stack.pop_back();
663
- } else {
664
- selector_stack.push_back({});
665
- sl = eval(sl->schema());
666
- selector_stack.pop_back();
667
726
  }
668
- }
669
- for (Complex_Selector_Obj cs : sl->elements()) {
670
- if (!cs.isNull() && !cs->head().isNull()) {
671
- cs->head()->media_block(media_stack.back());
727
+ else {
728
+ error("complex selectors may not be extended.", complex->pstate(), traces);
672
729
  }
673
730
  }
674
- selector_stack.push_back({});
675
- expand_selector_list(sl, extender);
676
- selector_stack.pop_back();
677
731
  }
678
- return 0;
732
+
733
+ return nullptr;
734
+
679
735
  }
680
736
 
681
737
  Statement* Expand::operator()(Definition* d)
@@ -705,6 +761,7 @@ namespace Sass {
705
761
 
706
762
  Statement* Expand::operator()(Mixin_Call* c)
707
763
  {
764
+
708
765
  if (recursions > maxRecursion) {
709
766
  throw Exception::StackError(traces, *c);
710
767
  }
@@ -785,11 +842,6 @@ namespace Sass {
785
842
  Env* env = environment();
786
843
  // convert @content directives into mixin calls to the underlying thunk
787
844
  if (!env->has("@content[m]")) return 0;
788
-
789
- if (block_stack.back()->is_root()) {
790
- selector_stack.push_back({});
791
- }
792
-
793
845
  Arguments_Obj args = c->arguments();
794
846
  if (!args) args = SASS_MEMORY_NEW(Arguments, c->pstate());
795
847
 
@@ -799,11 +851,6 @@ namespace Sass {
799
851
  args);
800
852
 
801
853
  Trace_Obj trace = Cast<Trace>(call->perform(this));
802
-
803
- if (block_stack.back()->is_root()) {
804
- selector_stack.pop_back();
805
- }
806
-
807
854
  return trace.detach();
808
855
  }
809
856