sassc 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +18 -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 +4 -0
  9. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  10. data/ext/libsass/src/ast.cpp +158 -168
  11. data/ext/libsass/src/ast.hpp +389 -230
  12. data/ext/libsass/src/ast_def_macros.hpp +18 -10
  13. data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
  14. data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
  15. data/ext/libsass/src/ast_helpers.hpp +292 -0
  16. data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
  17. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  18. data/ext/libsass/src/ast_sel_unify.cpp +207 -212
  19. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  20. data/ext/libsass/src/ast_selectors.cpp +594 -1026
  21. data/ext/libsass/src/ast_selectors.hpp +339 -385
  22. data/ext/libsass/src/ast_supports.cpp +36 -52
  23. data/ext/libsass/src/ast_supports.hpp +29 -29
  24. data/ext/libsass/src/ast_values.cpp +271 -84
  25. data/ext/libsass/src/ast_values.hpp +116 -107
  26. data/ext/libsass/src/backtrace.cpp +9 -9
  27. data/ext/libsass/src/backtrace.hpp +5 -5
  28. data/ext/libsass/src/base64vlq.cpp +2 -2
  29. data/ext/libsass/src/base64vlq.hpp +1 -1
  30. data/ext/libsass/src/bind.cpp +18 -18
  31. data/ext/libsass/src/bind.hpp +1 -1
  32. data/ext/libsass/src/c2ast.cpp +3 -3
  33. data/ext/libsass/src/c2ast.hpp +1 -1
  34. data/ext/libsass/src/cencode.c +4 -6
  35. data/ext/libsass/src/check_nesting.cpp +40 -41
  36. data/ext/libsass/src/check_nesting.hpp +6 -2
  37. data/ext/libsass/src/color_maps.cpp +14 -13
  38. data/ext/libsass/src/color_maps.hpp +1 -9
  39. data/ext/libsass/src/constants.cpp +5 -0
  40. data/ext/libsass/src/constants.hpp +6 -0
  41. data/ext/libsass/src/context.cpp +92 -119
  42. data/ext/libsass/src/context.hpp +41 -53
  43. data/ext/libsass/src/cssize.cpp +66 -149
  44. data/ext/libsass/src/cssize.hpp +17 -23
  45. data/ext/libsass/src/dart_helpers.hpp +199 -0
  46. data/ext/libsass/src/debugger.hpp +451 -295
  47. data/ext/libsass/src/emitter.cpp +15 -16
  48. data/ext/libsass/src/emitter.hpp +10 -12
  49. data/ext/libsass/src/environment.cpp +27 -27
  50. data/ext/libsass/src/environment.hpp +29 -24
  51. data/ext/libsass/src/error_handling.cpp +62 -41
  52. data/ext/libsass/src/error_handling.hpp +61 -51
  53. data/ext/libsass/src/eval.cpp +167 -281
  54. data/ext/libsass/src/eval.hpp +27 -29
  55. data/ext/libsass/src/eval_selectors.cpp +75 -0
  56. data/ext/libsass/src/expand.cpp +275 -222
  57. data/ext/libsass/src/expand.hpp +36 -16
  58. data/ext/libsass/src/extender.cpp +1188 -0
  59. data/ext/libsass/src/extender.hpp +399 -0
  60. data/ext/libsass/src/extension.cpp +43 -0
  61. data/ext/libsass/src/extension.hpp +89 -0
  62. data/ext/libsass/src/file.cpp +81 -72
  63. data/ext/libsass/src/file.hpp +28 -37
  64. data/ext/libsass/src/fn_colors.cpp +20 -18
  65. data/ext/libsass/src/fn_lists.cpp +30 -29
  66. data/ext/libsass/src/fn_maps.cpp +3 -3
  67. data/ext/libsass/src/fn_miscs.cpp +34 -46
  68. data/ext/libsass/src/fn_numbers.cpp +20 -13
  69. data/ext/libsass/src/fn_selectors.cpp +98 -128
  70. data/ext/libsass/src/fn_strings.cpp +47 -33
  71. data/ext/libsass/src/fn_utils.cpp +31 -29
  72. data/ext/libsass/src/fn_utils.hpp +17 -11
  73. data/ext/libsass/src/inspect.cpp +186 -148
  74. data/ext/libsass/src/inspect.hpp +31 -29
  75. data/ext/libsass/src/lexer.cpp +20 -82
  76. data/ext/libsass/src/lexer.hpp +5 -16
  77. data/ext/libsass/src/listize.cpp +23 -37
  78. data/ext/libsass/src/listize.hpp +8 -9
  79. data/ext/libsass/src/mapping.hpp +1 -0
  80. data/ext/libsass/src/memory/allocator.cpp +48 -0
  81. data/ext/libsass/src/memory/allocator.hpp +138 -0
  82. data/ext/libsass/src/memory/config.hpp +20 -0
  83. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  84. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  85. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
  86. data/ext/libsass/src/memory.hpp +12 -0
  87. data/ext/libsass/src/operation.hpp +71 -61
  88. data/ext/libsass/src/operators.cpp +19 -18
  89. data/ext/libsass/src/operators.hpp +11 -11
  90. data/ext/libsass/src/ordered_map.hpp +112 -0
  91. data/ext/libsass/src/output.cpp +45 -64
  92. data/ext/libsass/src/output.hpp +6 -6
  93. data/ext/libsass/src/parser.cpp +512 -700
  94. data/ext/libsass/src/parser.hpp +89 -97
  95. data/ext/libsass/src/parser_selectors.cpp +189 -0
  96. data/ext/libsass/src/permutate.hpp +164 -0
  97. data/ext/libsass/src/plugins.cpp +7 -7
  98. data/ext/libsass/src/plugins.hpp +8 -8
  99. data/ext/libsass/src/position.cpp +7 -26
  100. data/ext/libsass/src/position.hpp +44 -21
  101. data/ext/libsass/src/prelexer.cpp +6 -6
  102. data/ext/libsass/src/remove_placeholders.cpp +55 -56
  103. data/ext/libsass/src/remove_placeholders.hpp +21 -18
  104. data/ext/libsass/src/sass.cpp +16 -15
  105. data/ext/libsass/src/sass.hpp +10 -5
  106. data/ext/libsass/src/sass2scss.cpp +4 -4
  107. data/ext/libsass/src/sass_context.cpp +91 -122
  108. data/ext/libsass/src/sass_context.hpp +2 -2
  109. data/ext/libsass/src/sass_functions.cpp +1 -1
  110. data/ext/libsass/src/sass_values.cpp +8 -11
  111. data/ext/libsass/src/settings.hpp +19 -0
  112. data/ext/libsass/src/source.cpp +69 -0
  113. data/ext/libsass/src/source.hpp +95 -0
  114. data/ext/libsass/src/source_data.hpp +32 -0
  115. data/ext/libsass/src/source_map.cpp +22 -18
  116. data/ext/libsass/src/source_map.hpp +12 -9
  117. data/ext/libsass/src/stylesheet.cpp +22 -0
  118. data/ext/libsass/src/stylesheet.hpp +57 -0
  119. data/ext/libsass/src/to_value.cpp +2 -2
  120. data/ext/libsass/src/to_value.hpp +1 -1
  121. data/ext/libsass/src/units.cpp +24 -22
  122. data/ext/libsass/src/units.hpp +8 -8
  123. data/ext/libsass/src/utf8_string.cpp +9 -10
  124. data/ext/libsass/src/utf8_string.hpp +7 -6
  125. data/ext/libsass/src/util.cpp +48 -50
  126. data/ext/libsass/src/util.hpp +20 -21
  127. data/ext/libsass/src/util_string.cpp +111 -61
  128. data/ext/libsass/src/util_string.hpp +62 -8
  129. data/ext/libsass/src/values.cpp +12 -12
  130. data/lib/sassc/engine.rb +5 -3
  131. data/lib/sassc/functions_handler.rb +8 -8
  132. data/lib/sassc/native.rb +4 -6
  133. data/lib/sassc/script.rb +4 -4
  134. data/lib/sassc/version.rb +1 -1
  135. data/test/functions_test.rb +18 -1
  136. data/test/native_test.rb +4 -4
  137. metadata +29 -15
  138. data/ext/libsass/src/extend.cpp +0 -2132
  139. data/ext/libsass/src/extend.hpp +0 -86
  140. data/ext/libsass/src/node.cpp +0 -322
  141. data/ext/libsass/src/node.hpp +0 -118
  142. data/ext/libsass/src/paths.hpp +0 -71
  143. data/ext/libsass/src/sass_util.cpp +0 -152
  144. data/ext/libsass/src/sass_util.hpp +0 -256
  145. data/ext/libsass/src/subset_map.cpp +0 -58
  146. data/ext/libsass/src/subset_map.hpp +0 -76
  147. data/lib/sassc/native/lib_c.rb +0 -21
@@ -13,13 +13,14 @@
13
13
  #include "context.hpp"
14
14
  #include "parser.hpp"
15
15
  #include "sass_functions.hpp"
16
+ #include "error_handling.hpp"
16
17
 
17
18
  namespace Sass {
18
19
 
19
20
  // simple endless recursion protection
20
21
  const size_t maxRecursion = 500;
21
22
 
22
- Expand::Expand(Context& ctx, Env* env, SelectorStack* stack)
23
+ Expand::Expand(Context& ctx, Env* env, SelectorStack* stack, SelectorStack* originals)
23
24
  : ctx(ctx),
24
25
  traces(ctx.traces),
25
26
  eval(Eval(*this)),
@@ -27,19 +28,32 @@ namespace Sass {
27
28
  in_keyframes(false),
28
29
  at_root_without_rule(false),
29
30
  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())
31
+ env_stack(),
32
+ block_stack(),
33
+ call_stack(),
34
+ selector_stack(),
35
+ originalStack(),
36
+ mediaStack()
35
37
  {
36
38
  env_stack.push_back(nullptr);
37
39
  env_stack.push_back(env);
38
40
  block_stack.push_back(nullptr);
39
41
  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);
42
+ if (stack == NULL) { pushToSelectorStack({}); }
43
+ else {
44
+ for (auto item : *stack) {
45
+ if (item.isNull()) pushToSelectorStack({});
46
+ else pushToSelectorStack(item);
47
+ }
48
+ }
49
+ if (originals == NULL) { pushToOriginalStack({}); }
50
+ else {
51
+ for (auto item : *stack) {
52
+ if (item.isNull()) pushToOriginalStack({});
53
+ else pushToOriginalStack(item);
54
+ }
55
+ }
56
+ mediaStack.push_back({});
43
57
  }
44
58
 
45
59
  Env* Expand::environment()
@@ -49,11 +63,80 @@ namespace Sass {
49
63
  return 0;
50
64
  }
51
65
 
52
- Selector_List_Obj Expand::selector()
66
+ void Expand::pushNullSelector()
67
+ {
68
+ pushToSelectorStack({});
69
+ pushToOriginalStack({});
70
+ }
71
+
72
+ void Expand::popNullSelector()
53
73
  {
54
- if (selector_stack.size() > 0)
55
- return selector_stack.back();
56
- return {};
74
+ popFromOriginalStack();
75
+ popFromSelectorStack();
76
+ }
77
+
78
+ SelectorStack Expand::getOriginalStack()
79
+ {
80
+ return originalStack;
81
+ }
82
+
83
+ SelectorStack Expand::getSelectorStack()
84
+ {
85
+ return selector_stack;
86
+ }
87
+
88
+ SelectorListObj& Expand::selector()
89
+ {
90
+ if (selector_stack.size() > 0) {
91
+ auto& sel = selector_stack.back();
92
+ if (sel.isNull()) return sel;
93
+ return sel;
94
+ }
95
+ // Avoid the need to return copies
96
+ // We always want an empty first item
97
+ selector_stack.push_back({});
98
+ return selector_stack.back();;
99
+ }
100
+
101
+ SelectorListObj& Expand::original()
102
+ {
103
+ if (originalStack.size() > 0) {
104
+ auto& sel = originalStack.back();
105
+ if (sel.isNull()) return sel;
106
+ return sel;
107
+ }
108
+ // Avoid the need to return copies
109
+ // We always want an empty first item
110
+ originalStack.push_back({});
111
+ return originalStack.back();
112
+ }
113
+
114
+ SelectorListObj Expand::popFromSelectorStack()
115
+ {
116
+ SelectorListObj last = selector_stack.back();
117
+ if (selector_stack.size() > 0)
118
+ selector_stack.pop_back();
119
+ if (last.isNull()) return {};
120
+ return last;
121
+ }
122
+
123
+ void Expand::pushToSelectorStack(SelectorListObj selector)
124
+ {
125
+ selector_stack.push_back(selector);
126
+ }
127
+
128
+ SelectorListObj Expand::popFromOriginalStack()
129
+ {
130
+ SelectorListObj last = originalStack.back();
131
+ if (originalStack.size() > 0)
132
+ originalStack.pop_back();
133
+ if (last.isNull()) return {};
134
+ return last;
135
+ }
136
+
137
+ void Expand::pushToOriginalStack(SelectorListObj selector)
138
+ {
139
+ originalStack.push_back(selector);
57
140
  }
58
141
 
59
142
  // blocks create new variable scopes
@@ -80,76 +163,62 @@ namespace Sass {
80
163
  return bb.detach();
81
164
  }
82
165
 
83
- Statement* Expand::operator()(Ruleset* r)
166
+ Statement* Expand::operator()(StyleRule* r)
84
167
  {
85
168
  LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
86
169
 
87
170
  if (in_keyframes) {
88
171
  Block* bb = operator()(r->block());
89
172
  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();
173
+ if (r->schema()) {
174
+ pushNullSelector();
175
+ k->name(eval(r->schema()));
176
+ popNullSelector();
177
+ }
178
+ else if (r->selector()) {
179
+ if (SelectorListObj s = r->selector()) {
180
+ pushNullSelector();
181
+ k->name(eval(s));
182
+ popNullSelector();
95
183
  }
96
184
  }
185
+
97
186
  return k.detach();
98
187
  }
99
188
 
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
- }
189
+ if (r->schema()) {
190
+ SelectorListObj sel = eval(r->schema());
191
+ r->selector(sel);
192
+ for (auto complex : sel->elements()) {
193
+ // ToDo: maybe we can get rid of chroots?
194
+ complex->chroots(complex->has_real_parent_ref());
135
195
  }
196
+
136
197
  }
137
198
 
199
+ // reset when leaving scope
200
+ LOCAL_FLAG(at_root_without_rule, false);
201
+
202
+ SelectorListObj evaled = eval(r->selector());
138
203
  // do not connect parent again
139
- sel->remove_parent_selectors();
140
- selector_stack.push_back(sel);
141
204
  Env env(environment());
142
205
  if (block_stack.back()->is_root()) {
143
206
  env_stack.push_back(&env);
144
207
  }
145
- sel->set_media_block(media_stack.back());
146
208
  Block_Obj blk;
209
+ pushToSelectorStack(evaled);
210
+ // The copy is needed for parent reference evaluation
211
+ // dart-sass stores it as `originalSelector` member
212
+ pushToOriginalStack(SASS_MEMORY_COPY(evaled));
213
+ ctx.extender.addSelector(evaled, mediaStack.back());
147
214
  if (r->block()) blk = operator()(r->block());
148
- Ruleset* rr = SASS_MEMORY_NEW(Ruleset,
215
+ popFromOriginalStack();
216
+ popFromSelectorStack();
217
+ StyleRule* rr = SASS_MEMORY_NEW(StyleRule,
149
218
  r->pstate(),
150
- sel,
219
+ evaled,
151
220
  blk);
152
- selector_stack.pop_back();
221
+
153
222
  if (block_stack.back()->is_root()) {
154
223
  env_stack.pop_back();
155
224
  }
@@ -160,47 +229,60 @@ namespace Sass {
160
229
  return rr;
161
230
  }
162
231
 
163
- Statement* Expand::operator()(Supports_Block* f)
232
+ Statement* Expand::operator()(SupportsRule* f)
164
233
  {
165
- Expression_Obj condition = f->condition()->perform(&eval);
166
- Supports_Block_Obj ff = SASS_MEMORY_NEW(Supports_Block,
234
+ ExpressionObj condition = f->condition()->perform(&eval);
235
+ SupportsRuleObj ff = SASS_MEMORY_NEW(SupportsRule,
167
236
  f->pstate(),
168
- Cast<Supports_Condition>(condition),
237
+ Cast<SupportsCondition>(condition),
169
238
  operator()(f->block()));
170
239
  return ff.detach();
171
240
  }
172
241
 
173
- Statement* Expand::operator()(Media_Block* m)
174
- {
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));
184
- char* str = sass_copy_c_string(str_mq.c_str());
185
- 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;
198
- }
199
-
200
- Statement* Expand::operator()(At_Root_Block* a)
242
+ sass::vector<CssMediaQuery_Obj> Expand::mergeMediaQueries(
243
+ const sass::vector<CssMediaQuery_Obj>& lhs,
244
+ const sass::vector<CssMediaQuery_Obj>& rhs)
245
+ {
246
+ sass::vector<CssMediaQuery_Obj> queries;
247
+ for (CssMediaQuery_Obj query1 : lhs) {
248
+ for (CssMediaQuery_Obj query2 : rhs) {
249
+ CssMediaQuery_Obj result = query1->merge(query2);
250
+ if (result && !result->empty()) {
251
+ queries.push_back(result);
252
+ }
253
+ }
254
+ }
255
+ return queries;
256
+ }
257
+
258
+ Statement* Expand::operator()(MediaRule* m)
259
+ {
260
+ ExpressionObj mq = eval(m->schema());
261
+ sass::string str_mq(mq->to_css(ctx.c_options));
262
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile,
263
+ str_mq.c_str(), m->pstate());
264
+ Parser parser(source, ctx, traces);
265
+ // Create a new CSS only representation of the media rule
266
+ CssMediaRuleObj css = SASS_MEMORY_NEW(CssMediaRule, m->pstate(), m->block());
267
+ sass::vector<CssMediaQuery_Obj> parsed = parser.parseCssMediaQueries();
268
+ if (mediaStack.size() && mediaStack.back()) {
269
+ auto& parent = mediaStack.back()->elements();
270
+ css->concat(mergeMediaQueries(parent, parsed));
271
+ }
272
+ else {
273
+ css->concat(parsed);
274
+ }
275
+ mediaStack.push_back(css);
276
+ css->block(operator()(m->block()));
277
+ mediaStack.pop_back();
278
+ return css.detach();
279
+
280
+ }
281
+
282
+ Statement* Expand::operator()(AtRootRule* a)
201
283
  {
202
284
  Block_Obj ab = a->block();
203
- Expression_Obj ae = a->expression();
285
+ ExpressionObj ae = a->expression();
204
286
 
205
287
  if (ae) ae = ae->perform(&eval);
206
288
  else ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate());
@@ -211,25 +293,25 @@ namespace Sass {
211
293
  ;
212
294
 
213
295
  Block_Obj bb = ab ? operator()(ab) : NULL;
214
- At_Root_Block_Obj aa = SASS_MEMORY_NEW(At_Root_Block,
296
+ AtRootRuleObj aa = SASS_MEMORY_NEW(AtRootRule,
215
297
  a->pstate(),
216
298
  bb,
217
299
  Cast<At_Root_Query>(ae));
218
300
  return aa.detach();
219
301
  }
220
302
 
221
- Statement* Expand::operator()(Directive* a)
303
+ Statement* Expand::operator()(AtRule* a)
222
304
  {
223
305
  LOCAL_FLAG(in_keyframes, a->is_keyframes());
224
306
  Block* ab = a->block();
225
- Selector_List* as = a->selector();
307
+ SelectorList* as = a->selector();
226
308
  Expression* av = a->value();
227
- selector_stack.push_back({});
309
+ pushNullSelector();
228
310
  if (av) av = av->perform(&eval);
229
311
  if (as) as = eval(as);
230
- selector_stack.pop_back();
312
+ popNullSelector();
231
313
  Block* bb = ab ? operator()(ab) : NULL;
232
- Directive* aa = SASS_MEMORY_NEW(Directive,
314
+ AtRule* aa = SASS_MEMORY_NEW(AtRule,
233
315
  a->pstate(),
234
316
  a->keyword(),
235
317
  as,
@@ -242,14 +324,14 @@ namespace Sass {
242
324
  {
243
325
  Block_Obj ab = d->block();
244
326
  String_Obj old_p = d->property();
245
- Expression_Obj prop = old_p->perform(&eval);
327
+ ExpressionObj prop = old_p->perform(&eval);
246
328
  String_Obj new_p = Cast<String>(prop);
247
329
  // we might get a color back
248
330
  if (!new_p) {
249
- std::string str(prop->to_string(ctx.c_options));
331
+ sass::string str(prop->to_string(ctx.c_options));
250
332
  new_p = SASS_MEMORY_NEW(String_Constant, old_p->pstate(), str);
251
333
  }
252
- Expression_Obj value = d->value();
334
+ ExpressionObj value = d->value();
253
335
  if (value) value = value->perform(&eval);
254
336
  Block_Obj bb = ab ? operator()(ab) : NULL;
255
337
  if (!bb) {
@@ -275,11 +357,17 @@ namespace Sass {
275
357
  Statement* Expand::operator()(Assignment* a)
276
358
  {
277
359
  Env* env = environment();
278
- const std::string& var(a->variable());
360
+ const sass::string& var(a->variable());
279
361
  if (a->is_global()) {
362
+ if (!env->has_global(var)) {
363
+ deprecated(
364
+ "!global assignments won't be able to declare new variables in future versions.",
365
+ "Consider adding `" + var + ": null` at the top level.",
366
+ true, a->pstate());
367
+ }
280
368
  if (a->is_default()) {
281
369
  if (env->has_global(var)) {
282
- Expression_Obj e = Cast<Expression>(env->get_global(var));
370
+ ExpressionObj e = Cast<Expression>(env->get_global(var));
283
371
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
284
372
  env->set_global(var, a->value()->perform(&eval));
285
373
  }
@@ -298,7 +386,7 @@ namespace Sass {
298
386
  while (cur && cur->is_lexical()) {
299
387
  if (cur->has_local(var)) {
300
388
  if (AST_Node_Obj node = cur->get_local(var)) {
301
- Expression_Obj e = Cast<Expression>(node);
389
+ ExpressionObj e = Cast<Expression>(node);
302
390
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
303
391
  cur->set_local(var, a->value()->perform(&eval));
304
392
  }
@@ -314,7 +402,7 @@ namespace Sass {
314
402
  }
315
403
  else if (env->has_global(var)) {
316
404
  if (AST_Node_Obj node = env->get_global(var)) {
317
- Expression_Obj e = Cast<Expression>(node);
405
+ ExpressionObj e = Cast<Expression>(node);
318
406
  if (!e || e->concrete_type() == Expression::NULL_VAL) {
319
407
  env->set_global(var, a->value()->perform(&eval));
320
408
  }
@@ -337,7 +425,7 @@ namespace Sass {
337
425
  {
338
426
  Import_Obj result = SASS_MEMORY_NEW(Import, imp->pstate());
339
427
  if (imp->import_queries() && imp->import_queries()->size()) {
340
- Expression_Obj ex = imp->import_queries()->perform(&eval);
428
+ ExpressionObj ex = imp->import_queries()->perform(&eval);
341
429
  result->import_queries(Cast<List>(ex));
342
430
  }
343
431
  for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) {
@@ -369,7 +457,7 @@ namespace Sass {
369
457
  block_stack.back()->append(trace);
370
458
  block_stack.push_back(trace_block);
371
459
 
372
- const std::string& abs_path(i->resource().abs_path);
460
+ const sass::string& abs_path(i->resource().abs_path);
373
461
  append_block(ctx.sheets.at(abs_path).root);
374
462
  sass_delete_import(ctx.import_stack.back());
375
463
  ctx.import_stack.pop_back();
@@ -378,21 +466,21 @@ namespace Sass {
378
466
  return 0;
379
467
  }
380
468
 
381
- Statement* Expand::operator()(Warning* w)
469
+ Statement* Expand::operator()(WarningRule* w)
382
470
  {
383
471
  // eval handles this too, because warnings may occur in functions
384
472
  w->perform(&eval);
385
473
  return 0;
386
474
  }
387
475
 
388
- Statement* Expand::operator()(Error* e)
476
+ Statement* Expand::operator()(ErrorRule* e)
389
477
  {
390
478
  // eval handles this too, because errors may occur in functions
391
479
  e->perform(&eval);
392
480
  return 0;
393
481
  }
394
482
 
395
- Statement* Expand::operator()(Debug* d)
483
+ Statement* Expand::operator()(DebugRule* d)
396
484
  {
397
485
  // eval handles this too, because warnings may occur in functions
398
486
  d->perform(&eval);
@@ -418,7 +506,7 @@ namespace Sass {
418
506
  Env env(environment(), true);
419
507
  env_stack.push_back(&env);
420
508
  call_stack.push_back(i);
421
- Expression_Obj rv = i->predicate()->perform(&eval);
509
+ ExpressionObj rv = i->predicate()->perform(&eval);
422
510
  if (*rv) {
423
511
  append_block(i->block());
424
512
  }
@@ -433,15 +521,15 @@ namespace Sass {
433
521
 
434
522
  // For does not create a new env scope
435
523
  // But iteration vars are reset afterwards
436
- Statement* Expand::operator()(For* f)
524
+ Statement* Expand::operator()(ForRule* f)
437
525
  {
438
- std::string variable(f->variable());
439
- Expression_Obj low = f->lower_bound()->perform(&eval);
526
+ sass::string variable(f->variable());
527
+ ExpressionObj low = f->lower_bound()->perform(&eval);
440
528
  if (low->concrete_type() != Expression::NUMBER) {
441
529
  traces.push_back(Backtrace(low->pstate()));
442
530
  throw Exception::TypeMismatch(traces, *low, "integer");
443
531
  }
444
- Expression_Obj high = f->upper_bound()->perform(&eval);
532
+ ExpressionObj high = f->upper_bound()->perform(&eval);
445
533
  if (high->concrete_type() != Expression::NUMBER) {
446
534
  traces.push_back(Backtrace(high->pstate()));
447
535
  throw Exception::TypeMismatch(traces, *high, "integer");
@@ -450,7 +538,7 @@ namespace Sass {
450
538
  Number_Obj sass_end = Cast<Number>(high);
451
539
  // check if units are valid for sequence
452
540
  if (sass_start->unit() != sass_end->unit()) {
453
- std::stringstream msg; msg << "Incompatible units: '"
541
+ sass::ostream msg; msg << "Incompatible units: '"
454
542
  << sass_start->unit() << "' and '"
455
543
  << sass_end->unit() << "'.";
456
544
  error(msg.str(), low->pstate(), traces);
@@ -488,18 +576,17 @@ namespace Sass {
488
576
 
489
577
  // Eval does not create a new env scope
490
578
  // But iteration vars are reset afterwards
491
- Statement* Expand::operator()(Each* e)
579
+ Statement* Expand::operator()(EachRule* e)
492
580
  {
493
- std::vector<std::string> variables(e->variables());
494
- Expression_Obj expr = e->list()->perform(&eval);
581
+ sass::vector<sass::string> variables(e->variables());
582
+ ExpressionObj expr = e->list()->perform(&eval);
495
583
  List_Obj list;
496
584
  Map_Obj map;
497
585
  if (expr->concrete_type() == Expression::MAP) {
498
586
  map = Cast<Map>(expr);
499
587
  }
500
- else if (Selector_List* ls = Cast<Selector_List>(expr)) {
501
- Listize listize;
502
- Expression_Obj rv = ls->perform(&listize);
588
+ else if (SelectorList * ls = Cast<SelectorList>(expr)) {
589
+ ExpressionObj rv = Listize::perform(ls);
503
590
  list = Cast<List>(rv);
504
591
  }
505
592
  else if (expr->concrete_type() != Expression::LIST) {
@@ -517,8 +604,8 @@ namespace Sass {
517
604
 
518
605
  if (map) {
519
606
  for (auto key : map->keys()) {
520
- Expression_Obj k = key->perform(&eval);
521
- Expression_Obj v = map->at(key)->perform(&eval);
607
+ ExpressionObj k = key->perform(&eval);
608
+ ExpressionObj v = map->at(key)->perform(&eval);
522
609
 
523
610
  if (variables.size() == 1) {
524
611
  List_Obj variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
@@ -534,11 +621,11 @@ namespace Sass {
534
621
  }
535
622
  else {
536
623
  // bool arglist = list->is_arglist();
537
- if (list->length() == 1 && Cast<Selector_List>(list)) {
624
+ if (list->length() == 1 && Cast<SelectorList>(list)) {
538
625
  list = Cast<List>(list);
539
626
  }
540
627
  for (size_t i = 0, L = list->length(); i < L; ++i) {
541
- Expression_Obj item = list->at(i);
628
+ ExpressionObj item = list->at(i);
542
629
  // unwrap value if the expression is an argument
543
630
  if (Argument_Obj arg = Cast<Argument>(item)) item = arg->value();
544
631
  // check if we got passed a list of args (investigate)
@@ -549,17 +636,16 @@ namespace Sass {
549
636
  env.set_local(variables[0], var);
550
637
  } else {
551
638
  for (size_t j = 0, K = variables.size(); j < K; ++j) {
552
- Expression_Obj res = j >= scalars->length()
639
+ env.set_local(variables[j], j >= scalars->length()
553
640
  ? SASS_MEMORY_NEW(Null, expr->pstate())
554
- : (*scalars)[j]->perform(&eval);
555
- env.set_local(variables[j], res);
641
+ : (*scalars)[j]->perform(&eval));
556
642
  }
557
643
  }
558
644
  } else {
559
645
  if (variables.size() > 0) {
560
646
  env.set_local(variables.at(0), item);
561
647
  for (size_t j = 1, K = variables.size(); j < K; ++j) {
562
- Expression_Obj res = SASS_MEMORY_NEW(Null, expr->pstate());
648
+ ExpressionObj res = SASS_MEMORY_NEW(Null, expr->pstate());
563
649
  env.set_local(variables[j], res);
564
650
  }
565
651
  }
@@ -572,14 +658,14 @@ namespace Sass {
572
658
  return 0;
573
659
  }
574
660
 
575
- Statement* Expand::operator()(While* w)
661
+ Statement* Expand::operator()(WhileRule* w)
576
662
  {
577
- Expression_Obj pred = w->predicate();
663
+ ExpressionObj pred = w->predicate();
578
664
  Block* body = w->block();
579
665
  Env env(environment(), true);
580
666
  env_stack.push_back(&env);
581
667
  call_stack.push_back(w);
582
- Expression_Obj cond = pred->perform(&eval);
668
+ ExpressionObj cond = pred->perform(&eval);
583
669
  while (!cond->is_false()) {
584
670
  append_block(body);
585
671
  cond = pred->perform(&eval);
@@ -595,87 +681,63 @@ namespace Sass {
595
681
  return 0;
596
682
  }
597
683
 
684
+ Statement* Expand::operator()(ExtendRule* e)
685
+ {
598
686
 
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
- }
687
+ // evaluate schema first
688
+ if (e->schema()) {
689
+ e->selector(eval(e->schema()));
690
+ e->isOptional(e->selector()->is_optional());
613
691
  }
692
+ // evaluate the selector
693
+ e->selector(eval(e->selector()));
614
694
 
695
+ if (e->selector()) {
615
696
 
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;
697
+ for (auto complex : e->selector()->elements()) {
698
+
699
+ if (complex->length() != 1) {
700
+ error("complex selectors may not be extended.", complex->pstate(), traces);
642
701
  }
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
702
 
648
- }
703
+ if (const CompoundSelector* compound = complex->first()->getCompound()) {
704
+
705
+ if (compound->length() != 1) {
706
+
707
+ sass::ostream sels; bool addComma = false;
708
+ sels << "Compound selectors may no longer be extended.\n";
709
+ sels << "Consider `@extend ";
710
+ for (auto sel : compound->elements()) {
711
+ if (addComma) sels << ", ";
712
+ sels << sel->to_sass();
713
+ addComma = true;
714
+ }
715
+ sels << "` instead.\n";
716
+ sels << "See http://bit.ly/ExtendCompound for details.";
717
+
718
+ warning(sels.str(), compound->pstate());
719
+
720
+ // Make this an error once deprecation is over
721
+ for (SimpleSelectorObj simple : compound->elements()) {
722
+ // Pass every selector we ever see to extender (to make them findable for extend)
723
+ ctx.extender.addExtension(selector(), simple, mediaStack.back(), e->isOptional());
724
+ }
725
+
726
+ }
727
+ else {
728
+ // Pass every selector we ever see to extender (to make them findable for extend)
729
+ ctx.extender.addExtension(selector(), compound->first(), mediaStack.back(), e->isOptional());
730
+ }
649
731
 
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
732
  }
668
- }
669
- for (Complex_Selector_Obj cs : sl->elements()) {
670
- if (!cs.isNull() && !cs->head().isNull()) {
671
- cs->head()->media_block(media_stack.back());
733
+ else {
734
+ error("complex selectors may not be extended.", complex->pstate(), traces);
672
735
  }
673
736
  }
674
- selector_stack.push_back({});
675
- expand_selector_list(sl, extender);
676
- selector_stack.pop_back();
677
737
  }
678
- return 0;
738
+
739
+ return nullptr;
740
+
679
741
  }
680
742
 
681
743
  Statement* Expand::operator()(Definition* d)
@@ -705,6 +767,7 @@ namespace Sass {
705
767
 
706
768
  Statement* Expand::operator()(Mixin_Call* c)
707
769
  {
770
+
708
771
  if (recursions > maxRecursion) {
709
772
  throw Exception::StackError(traces, *c);
710
773
  }
@@ -712,7 +775,7 @@ namespace Sass {
712
775
  recursions ++;
713
776
 
714
777
  Env* env = environment();
715
- std::string full_name(c->name() + "[m]");
778
+ sass::string full_name(c->name() + "[m]");
716
779
  if (!env->has(full_name)) {
717
780
  error("no mixin named " + c->name(), c->pstate(), traces);
718
781
  }
@@ -723,15 +786,15 @@ namespace Sass {
723
786
  if (c->block() && c->name() != "@content" && !body->has_content()) {
724
787
  error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), traces);
725
788
  }
726
- Expression_Obj rv = c->arguments()->perform(&eval);
789
+ ExpressionObj rv = c->arguments()->perform(&eval);
727
790
  Arguments_Obj args = Cast<Arguments>(rv);
728
- std::string msg(", in mixin `" + c->name() + "`");
791
+ sass::string msg(", in mixin `" + c->name() + "`");
729
792
  traces.push_back(Backtrace(c->pstate(), msg));
730
793
  ctx.callee_stack.push_back({
731
794
  c->name().c_str(),
732
- c->pstate().path,
733
- c->pstate().line + 1,
734
- c->pstate().column + 1,
795
+ c->pstate().getPath(),
796
+ c->pstate().getLine(),
797
+ c->pstate().getColumn(),
735
798
  SASS_CALLEE_MIXIN,
736
799
  { env }
737
800
  });
@@ -752,7 +815,7 @@ namespace Sass {
752
815
  new_env.local_frame()["@content[m]"] = thunk;
753
816
  }
754
817
 
755
- bind(std::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
818
+ bind(sass::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
756
819
 
757
820
  Block_Obj trace_block = SASS_MEMORY_NEW(Block, c->pstate());
758
821
  Trace_Obj trace = SASS_MEMORY_NEW(Trace, c->pstate(), c->name(), trace_block);
@@ -763,7 +826,7 @@ namespace Sass {
763
826
  }
764
827
  block_stack.push_back(trace_block);
765
828
  for (auto bb : body->elements()) {
766
- if (Ruleset* r = Cast<Ruleset>(bb)) {
829
+ if (StyleRule* r = Cast<StyleRule>(bb)) {
767
830
  r->is_root(trace_block->is_root());
768
831
  }
769
832
  Statement_Obj ith = bb->perform(this);
@@ -785,11 +848,6 @@ namespace Sass {
785
848
  Env* env = environment();
786
849
  // convert @content directives into mixin calls to the underlying thunk
787
850
  if (!env->has("@content[m]")) return 0;
788
-
789
- if (block_stack.back()->is_root()) {
790
- selector_stack.push_back({});
791
- }
792
-
793
851
  Arguments_Obj args = c->arguments();
794
852
  if (!args) args = SASS_MEMORY_NEW(Arguments, c->pstate());
795
853
 
@@ -799,11 +857,6 @@ namespace Sass {
799
857
  args);
800
858
 
801
859
  Trace_Obj trace = Cast<Trace>(call->perform(this));
802
-
803
- if (block_stack.back()->is_root()) {
804
- selector_stack.pop_back();
805
- }
806
-
807
860
  return trace.detach();
808
861
  }
809
862