sassc4 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 (216) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.md +97 -0
  6. data/CODE_OF_CONDUCT.md +10 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +80 -0
  10. data/Rakefile +51 -0
  11. data/ext/depend +4 -0
  12. data/ext/extconf.rb +92 -0
  13. data/ext/libsass/VERSION +1 -0
  14. data/ext/libsass/contrib/plugin.cpp +60 -0
  15. data/ext/libsass/include/sass/base.h +97 -0
  16. data/ext/libsass/include/sass/context.h +174 -0
  17. data/ext/libsass/include/sass/functions.h +139 -0
  18. data/ext/libsass/include/sass/values.h +145 -0
  19. data/ext/libsass/include/sass/version.h +12 -0
  20. data/ext/libsass/include/sass.h +15 -0
  21. data/ext/libsass/include/sass2scss.h +120 -0
  22. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  23. data/ext/libsass/src/ast.cpp +953 -0
  24. data/ext/libsass/src/ast.hpp +1064 -0
  25. data/ext/libsass/src/ast2c.cpp +80 -0
  26. data/ext/libsass/src/ast2c.hpp +39 -0
  27. data/ext/libsass/src/ast_def_macros.hpp +140 -0
  28. data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
  29. data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
  30. data/ext/libsass/src/ast_helpers.hpp +316 -0
  31. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  32. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  33. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  34. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  35. data/ext/libsass/src/ast_selectors.cpp +1070 -0
  36. data/ext/libsass/src/ast_selectors.hpp +523 -0
  37. data/ext/libsass/src/ast_supports.cpp +114 -0
  38. data/ext/libsass/src/ast_supports.hpp +121 -0
  39. data/ext/libsass/src/ast_values.cpp +1154 -0
  40. data/ext/libsass/src/ast_values.hpp +498 -0
  41. data/ext/libsass/src/b64/cencode.h +32 -0
  42. data/ext/libsass/src/b64/encode.h +79 -0
  43. data/ext/libsass/src/backtrace.cpp +50 -0
  44. data/ext/libsass/src/backtrace.hpp +29 -0
  45. data/ext/libsass/src/base64vlq.cpp +47 -0
  46. data/ext/libsass/src/base64vlq.hpp +30 -0
  47. data/ext/libsass/src/bind.cpp +312 -0
  48. data/ext/libsass/src/bind.hpp +15 -0
  49. data/ext/libsass/src/c2ast.cpp +64 -0
  50. data/ext/libsass/src/c2ast.hpp +14 -0
  51. data/ext/libsass/src/c99func.c +54 -0
  52. data/ext/libsass/src/cencode.c +106 -0
  53. data/ext/libsass/src/check_nesting.cpp +393 -0
  54. data/ext/libsass/src/check_nesting.hpp +70 -0
  55. data/ext/libsass/src/color_maps.cpp +652 -0
  56. data/ext/libsass/src/color_maps.hpp +323 -0
  57. data/ext/libsass/src/color_spaces.cpp +241 -0
  58. data/ext/libsass/src/color_spaces.hpp +227 -0
  59. data/ext/libsass/src/constants.cpp +199 -0
  60. data/ext/libsass/src/constants.hpp +200 -0
  61. data/ext/libsass/src/context.cpp +870 -0
  62. data/ext/libsass/src/context.hpp +140 -0
  63. data/ext/libsass/src/cssize.cpp +521 -0
  64. data/ext/libsass/src/cssize.hpp +71 -0
  65. data/ext/libsass/src/dart_helpers.hpp +199 -0
  66. data/ext/libsass/src/debug.hpp +43 -0
  67. data/ext/libsass/src/debugger.hpp +964 -0
  68. data/ext/libsass/src/emitter.cpp +297 -0
  69. data/ext/libsass/src/emitter.hpp +101 -0
  70. data/ext/libsass/src/environment.cpp +260 -0
  71. data/ext/libsass/src/environment.hpp +124 -0
  72. data/ext/libsass/src/error_handling.cpp +239 -0
  73. data/ext/libsass/src/error_handling.hpp +248 -0
  74. data/ext/libsass/src/eval.cpp +1543 -0
  75. data/ext/libsass/src/eval.hpp +110 -0
  76. data/ext/libsass/src/eval_selectors.cpp +75 -0
  77. data/ext/libsass/src/expand.cpp +875 -0
  78. data/ext/libsass/src/expand.hpp +98 -0
  79. data/ext/libsass/src/extender.cpp +1226 -0
  80. data/ext/libsass/src/extender.hpp +399 -0
  81. data/ext/libsass/src/extension.cpp +43 -0
  82. data/ext/libsass/src/extension.hpp +89 -0
  83. data/ext/libsass/src/file.cpp +531 -0
  84. data/ext/libsass/src/file.hpp +124 -0
  85. data/ext/libsass/src/fn_colors.cpp +836 -0
  86. data/ext/libsass/src/fn_colors.hpp +99 -0
  87. data/ext/libsass/src/fn_lists.cpp +285 -0
  88. data/ext/libsass/src/fn_lists.hpp +34 -0
  89. data/ext/libsass/src/fn_maps.cpp +94 -0
  90. data/ext/libsass/src/fn_maps.hpp +30 -0
  91. data/ext/libsass/src/fn_miscs.cpp +248 -0
  92. data/ext/libsass/src/fn_miscs.hpp +40 -0
  93. data/ext/libsass/src/fn_numbers.cpp +246 -0
  94. data/ext/libsass/src/fn_numbers.hpp +45 -0
  95. data/ext/libsass/src/fn_selectors.cpp +205 -0
  96. data/ext/libsass/src/fn_selectors.hpp +35 -0
  97. data/ext/libsass/src/fn_strings.cpp +268 -0
  98. data/ext/libsass/src/fn_strings.hpp +34 -0
  99. data/ext/libsass/src/fn_utils.cpp +159 -0
  100. data/ext/libsass/src/fn_utils.hpp +62 -0
  101. data/ext/libsass/src/inspect.cpp +1126 -0
  102. data/ext/libsass/src/inspect.hpp +101 -0
  103. data/ext/libsass/src/json.cpp +1436 -0
  104. data/ext/libsass/src/json.hpp +117 -0
  105. data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
  106. data/ext/libsass/src/lexer.cpp +122 -0
  107. data/ext/libsass/src/lexer.hpp +304 -0
  108. data/ext/libsass/src/listize.cpp +70 -0
  109. data/ext/libsass/src/listize.hpp +37 -0
  110. data/ext/libsass/src/mapping.hpp +19 -0
  111. data/ext/libsass/src/memory/allocator.cpp +48 -0
  112. data/ext/libsass/src/memory/allocator.hpp +138 -0
  113. data/ext/libsass/src/memory/config.hpp +20 -0
  114. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  115. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  116. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  117. data/ext/libsass/src/memory.hpp +12 -0
  118. data/ext/libsass/src/operation.hpp +223 -0
  119. data/ext/libsass/src/operators.cpp +267 -0
  120. data/ext/libsass/src/operators.hpp +30 -0
  121. data/ext/libsass/src/ordered_map.hpp +112 -0
  122. data/ext/libsass/src/output.cpp +320 -0
  123. data/ext/libsass/src/output.hpp +47 -0
  124. data/ext/libsass/src/parser.cpp +3059 -0
  125. data/ext/libsass/src/parser.hpp +395 -0
  126. data/ext/libsass/src/parser_selectors.cpp +189 -0
  127. data/ext/libsass/src/permutate.hpp +164 -0
  128. data/ext/libsass/src/plugins.cpp +188 -0
  129. data/ext/libsass/src/plugins.hpp +57 -0
  130. data/ext/libsass/src/position.cpp +163 -0
  131. data/ext/libsass/src/position.hpp +147 -0
  132. data/ext/libsass/src/prelexer.cpp +1780 -0
  133. data/ext/libsass/src/prelexer.hpp +484 -0
  134. data/ext/libsass/src/remove_placeholders.cpp +86 -0
  135. data/ext/libsass/src/remove_placeholders.hpp +37 -0
  136. data/ext/libsass/src/sass.cpp +156 -0
  137. data/ext/libsass/src/sass.hpp +147 -0
  138. data/ext/libsass/src/sass2scss.cpp +895 -0
  139. data/ext/libsass/src/sass_context.cpp +742 -0
  140. data/ext/libsass/src/sass_context.hpp +129 -0
  141. data/ext/libsass/src/sass_functions.cpp +210 -0
  142. data/ext/libsass/src/sass_functions.hpp +50 -0
  143. data/ext/libsass/src/sass_values.cpp +362 -0
  144. data/ext/libsass/src/sass_values.hpp +82 -0
  145. data/ext/libsass/src/settings.hpp +19 -0
  146. data/ext/libsass/src/source.cpp +69 -0
  147. data/ext/libsass/src/source.hpp +95 -0
  148. data/ext/libsass/src/source_data.hpp +32 -0
  149. data/ext/libsass/src/source_map.cpp +202 -0
  150. data/ext/libsass/src/source_map.hpp +65 -0
  151. data/ext/libsass/src/stylesheet.cpp +22 -0
  152. data/ext/libsass/src/stylesheet.hpp +57 -0
  153. data/ext/libsass/src/to_value.cpp +114 -0
  154. data/ext/libsass/src/to_value.hpp +46 -0
  155. data/ext/libsass/src/units.cpp +507 -0
  156. data/ext/libsass/src/units.hpp +110 -0
  157. data/ext/libsass/src/utf8/checked.h +336 -0
  158. data/ext/libsass/src/utf8/core.h +332 -0
  159. data/ext/libsass/src/utf8/unchecked.h +235 -0
  160. data/ext/libsass/src/utf8.h +34 -0
  161. data/ext/libsass/src/utf8_string.cpp +104 -0
  162. data/ext/libsass/src/utf8_string.hpp +38 -0
  163. data/ext/libsass/src/util.cpp +723 -0
  164. data/ext/libsass/src/util.hpp +105 -0
  165. data/ext/libsass/src/util_string.cpp +125 -0
  166. data/ext/libsass/src/util_string.hpp +73 -0
  167. data/ext/libsass/src/values.cpp +140 -0
  168. data/ext/libsass/src/values.hpp +12 -0
  169. data/lib/sassc/dependency.rb +17 -0
  170. data/lib/sassc/engine.rb +141 -0
  171. data/lib/sassc/error.rb +37 -0
  172. data/lib/sassc/functions_handler.rb +73 -0
  173. data/lib/sassc/import_handler.rb +50 -0
  174. data/lib/sassc/importer.rb +31 -0
  175. data/lib/sassc/native/native_context_api.rb +147 -0
  176. data/lib/sassc/native/native_functions_api.rb +159 -0
  177. data/lib/sassc/native/sass2scss_api.rb +10 -0
  178. data/lib/sassc/native/sass_input_style.rb +13 -0
  179. data/lib/sassc/native/sass_output_style.rb +12 -0
  180. data/lib/sassc/native/sass_value.rb +97 -0
  181. data/lib/sassc/native/string_list.rb +10 -0
  182. data/lib/sassc/native.rb +64 -0
  183. data/lib/sassc/sass_2_scss.rb +9 -0
  184. data/lib/sassc/script/functions.rb +8 -0
  185. data/lib/sassc/script/value/bool.rb +32 -0
  186. data/lib/sassc/script/value/color.rb +95 -0
  187. data/lib/sassc/script/value/list.rb +136 -0
  188. data/lib/sassc/script/value/map.rb +69 -0
  189. data/lib/sassc/script/value/number.rb +389 -0
  190. data/lib/sassc/script/value/string.rb +96 -0
  191. data/lib/sassc/script/value.rb +137 -0
  192. data/lib/sassc/script/value_conversion/base.rb +13 -0
  193. data/lib/sassc/script/value_conversion/bool.rb +13 -0
  194. data/lib/sassc/script/value_conversion/color.rb +18 -0
  195. data/lib/sassc/script/value_conversion/list.rb +25 -0
  196. data/lib/sassc/script/value_conversion/map.rb +21 -0
  197. data/lib/sassc/script/value_conversion/number.rb +13 -0
  198. data/lib/sassc/script/value_conversion/string.rb +17 -0
  199. data/lib/sassc/script/value_conversion.rb +69 -0
  200. data/lib/sassc/script.rb +17 -0
  201. data/lib/sassc/util/normalized_map.rb +117 -0
  202. data/lib/sassc/util.rb +231 -0
  203. data/lib/sassc/version.rb +5 -0
  204. data/lib/sassc.rb +57 -0
  205. data/sassc.gemspec +69 -0
  206. data/test/css_color_level4_test.rb +168 -0
  207. data/test/custom_importer_test.rb +127 -0
  208. data/test/engine_test.rb +314 -0
  209. data/test/error_test.rb +29 -0
  210. data/test/fixtures/paths.scss +10 -0
  211. data/test/functions_test.rb +340 -0
  212. data/test/native_test.rb +213 -0
  213. data/test/output_style_test.rb +107 -0
  214. data/test/sass_2_scss_test.rb +14 -0
  215. data/test/test_helper.rb +45 -0
  216. metadata +396 -0
@@ -0,0 +1,875 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include <iostream>
6
+ #include <typeinfo>
7
+
8
+ #include "ast.hpp"
9
+ #include "expand.hpp"
10
+ #include "bind.hpp"
11
+ #include "eval.hpp"
12
+ #include "backtrace.hpp"
13
+ #include "context.hpp"
14
+ #include "parser.hpp"
15
+ #include "sass_functions.hpp"
16
+ #include "error_handling.hpp"
17
+
18
+ namespace Sass {
19
+
20
+ // simple endless recursion protection
21
+ const size_t maxRecursion = 500;
22
+
23
+ Expand::Expand(Context& ctx, Env* env, SelectorStack* stack, SelectorStack* originals)
24
+ : ctx(ctx),
25
+ traces(ctx.traces),
26
+ eval(Eval(*this)),
27
+ recursions(0),
28
+ in_keyframes(false),
29
+ at_root_without_rule(false),
30
+ old_at_root_without_rule(false),
31
+ env_stack(),
32
+ block_stack(),
33
+ call_stack(),
34
+ selector_stack(),
35
+ originalStack(),
36
+ mediaStack()
37
+ {
38
+ env_stack.push_back(nullptr);
39
+ env_stack.push_back(env);
40
+ block_stack.push_back(nullptr);
41
+ call_stack.push_back({});
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({});
57
+ }
58
+
59
+ Env* Expand::environment()
60
+ {
61
+ if (env_stack.size() > 0)
62
+ return env_stack.back();
63
+ return 0;
64
+ }
65
+
66
+ void Expand::pushNullSelector()
67
+ {
68
+ pushToSelectorStack({});
69
+ pushToOriginalStack({});
70
+ }
71
+
72
+ void Expand::popNullSelector()
73
+ {
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);
140
+ }
141
+
142
+ // blocks create new variable scopes
143
+ Block* Expand::operator()(Block* b)
144
+ {
145
+ // create new local environment
146
+ // set the current env as parent
147
+ Env env(environment());
148
+ // copy the block object (add items later)
149
+ Block_Obj bb = SASS_MEMORY_NEW(Block,
150
+ b->pstate(),
151
+ b->length(),
152
+ b->is_root());
153
+ // setup block and env stack
154
+ this->block_stack.push_back(bb);
155
+ this->env_stack.push_back(&env);
156
+ // operate on block
157
+ // this may throw up!
158
+ this->append_block(b);
159
+ // revert block and env stack
160
+ this->block_stack.pop_back();
161
+ this->env_stack.pop_back();
162
+ // return copy
163
+ return bb.detach();
164
+ }
165
+
166
+ Statement* Expand::operator()(StyleRule* r)
167
+ {
168
+ LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
169
+
170
+ if (in_keyframes) {
171
+ Block* bb = operator()(r->block());
172
+ Keyframe_Rule_Obj k = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), bb);
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();
183
+ }
184
+ }
185
+
186
+ return k.detach();
187
+ }
188
+
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());
195
+ }
196
+
197
+ }
198
+
199
+ // reset when leaving scope
200
+ LOCAL_FLAG(at_root_without_rule, false);
201
+
202
+ SelectorListObj evaled = eval(r->selector());
203
+ // do not connect parent again
204
+ Env env(environment());
205
+ if (block_stack.back()->is_root()) {
206
+ env_stack.push_back(&env);
207
+ }
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());
214
+ if (r->block()) blk = operator()(r->block());
215
+ popFromOriginalStack();
216
+ popFromSelectorStack();
217
+ StyleRule* rr = SASS_MEMORY_NEW(StyleRule,
218
+ r->pstate(),
219
+ evaled,
220
+ blk);
221
+
222
+ if (block_stack.back()->is_root()) {
223
+ env_stack.pop_back();
224
+ }
225
+
226
+ rr->is_root(r->is_root());
227
+ rr->tabs(r->tabs());
228
+
229
+ return rr;
230
+ }
231
+
232
+ Statement* Expand::operator()(SupportsRule* f)
233
+ {
234
+ ExpressionObj condition = f->condition()->perform(&eval);
235
+ SupportsRuleObj ff = SASS_MEMORY_NEW(SupportsRule,
236
+ f->pstate(),
237
+ Cast<SupportsCondition>(condition),
238
+ operator()(f->block()));
239
+ return ff.detach();
240
+ }
241
+
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)
283
+ {
284
+ Block_Obj ab = a->block();
285
+ ExpressionObj ae = a->expression();
286
+
287
+ if (ae) ae = ae->perform(&eval);
288
+ else ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate());
289
+
290
+ LOCAL_FLAG(at_root_without_rule, Cast<At_Root_Query>(ae)->exclude("rule"));
291
+ LOCAL_FLAG(in_keyframes, false);
292
+
293
+ ;
294
+
295
+ Block_Obj bb = ab ? operator()(ab) : NULL;
296
+ AtRootRuleObj aa = SASS_MEMORY_NEW(AtRootRule,
297
+ a->pstate(),
298
+ bb,
299
+ Cast<At_Root_Query>(ae));
300
+ return aa.detach();
301
+ }
302
+
303
+ Statement* Expand::operator()(AtRule* a)
304
+ {
305
+ LOCAL_FLAG(in_keyframes, a->is_keyframes());
306
+ Block* ab = a->block();
307
+ SelectorList* as = a->selector();
308
+ Expression* av = a->value();
309
+ pushNullSelector();
310
+ if (av) av = av->perform(&eval);
311
+ if (as) as = eval(as);
312
+ popNullSelector();
313
+ Block* bb = ab ? operator()(ab) : NULL;
314
+ AtRule* aa = SASS_MEMORY_NEW(AtRule,
315
+ a->pstate(),
316
+ a->keyword(),
317
+ as,
318
+ bb,
319
+ av);
320
+ return aa;
321
+ }
322
+
323
+ Statement* Expand::operator()(Declaration* d)
324
+ {
325
+ Block_Obj ab = d->block();
326
+ String_Obj old_p = d->property();
327
+ ExpressionObj prop = old_p->perform(&eval);
328
+ String_Obj new_p = Cast<String>(prop);
329
+ // we might get a color back
330
+ if (!new_p) {
331
+ sass::string str(prop->to_string(ctx.c_options));
332
+ new_p = SASS_MEMORY_NEW(String_Constant, old_p->pstate(), str);
333
+ }
334
+ ExpressionObj value = d->value();
335
+ if (value) value = value->perform(&eval);
336
+ Block_Obj bb = ab ? operator()(ab) : NULL;
337
+ if (!bb) {
338
+ if (!value || (value->is_invisible() && !d->is_important())) {
339
+ if (d->is_custom_property()) {
340
+ error("Custom property values may not be empty.", d->value()->pstate(), traces);
341
+ } else {
342
+ return nullptr;
343
+ }
344
+ }
345
+ }
346
+ Declaration* decl = SASS_MEMORY_NEW(Declaration,
347
+ d->pstate(),
348
+ new_p,
349
+ value,
350
+ d->is_important(),
351
+ d->is_custom_property(),
352
+ bb);
353
+ decl->tabs(d->tabs());
354
+ return decl;
355
+ }
356
+
357
+ Statement* Expand::operator()(Assignment* a)
358
+ {
359
+ Env* env = environment();
360
+ const sass::string& var(a->variable());
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
+ }
368
+ if (a->is_default()) {
369
+ if (env->has_global(var)) {
370
+ ExpressionObj e = Cast<Expression>(env->get_global(var));
371
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
372
+ env->set_global(var, a->value()->perform(&eval));
373
+ }
374
+ }
375
+ else {
376
+ env->set_global(var, a->value()->perform(&eval));
377
+ }
378
+ }
379
+ else {
380
+ env->set_global(var, a->value()->perform(&eval));
381
+ }
382
+ }
383
+ else if (a->is_default()) {
384
+ if (env->has_lexical(var)) {
385
+ auto cur = env;
386
+ while (cur && cur->is_lexical()) {
387
+ if (cur->has_local(var)) {
388
+ if (AST_Node_Obj node = cur->get_local(var)) {
389
+ ExpressionObj e = Cast<Expression>(node);
390
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
391
+ cur->set_local(var, a->value()->perform(&eval));
392
+ }
393
+ }
394
+ else {
395
+ throw std::runtime_error("Env not in sync");
396
+ }
397
+ return 0;
398
+ }
399
+ cur = cur->parent();
400
+ }
401
+ throw std::runtime_error("Env not in sync");
402
+ }
403
+ else if (env->has_global(var)) {
404
+ if (AST_Node_Obj node = env->get_global(var)) {
405
+ ExpressionObj e = Cast<Expression>(node);
406
+ if (!e || e->concrete_type() == Expression::NULL_VAL) {
407
+ env->set_global(var, a->value()->perform(&eval));
408
+ }
409
+ }
410
+ }
411
+ else if (env->is_lexical()) {
412
+ env->set_local(var, a->value()->perform(&eval));
413
+ }
414
+ else {
415
+ env->set_local(var, a->value()->perform(&eval));
416
+ }
417
+ }
418
+ else {
419
+ env->set_lexical(var, a->value()->perform(&eval));
420
+ }
421
+ return 0;
422
+ }
423
+
424
+ Statement* Expand::operator()(Import* imp)
425
+ {
426
+ Import_Obj result = SASS_MEMORY_NEW(Import, imp->pstate());
427
+ if (imp->import_queries() && imp->import_queries()->size()) {
428
+ ExpressionObj ex = imp->import_queries()->perform(&eval);
429
+ result->import_queries(Cast<List>(ex));
430
+ }
431
+ for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) {
432
+ result->urls().push_back(imp->urls()[i]->perform(&eval));
433
+ }
434
+ // all resources have been dropped for Input_Stubs
435
+ // for ( size_t i = 0, S = imp->incs().size(); i < S; ++i) {}
436
+ return result.detach();
437
+ }
438
+
439
+ Statement* Expand::operator()(Import_Stub* i)
440
+ {
441
+ traces.push_back(Backtrace(i->pstate()));
442
+ // get parent node from call stack
443
+ AST_Node_Obj parent = call_stack.back();
444
+ if (Cast<Block>(parent) == NULL) {
445
+ error("Import directives may not be used within control directives or mixins.", i->pstate(), traces);
446
+ }
447
+ // we don't seem to need that actually afterall
448
+ Sass_Import_Entry import = sass_make_import(
449
+ i->imp_path().c_str(),
450
+ i->abs_path().c_str(),
451
+ 0, 0
452
+ );
453
+ ctx.import_stack.push_back(import);
454
+
455
+ Block_Obj trace_block = SASS_MEMORY_NEW(Block, i->pstate());
456
+ Trace_Obj trace = SASS_MEMORY_NEW(Trace, i->pstate(), i->imp_path(), trace_block, 'i');
457
+ block_stack.back()->append(trace);
458
+ block_stack.push_back(trace_block);
459
+
460
+ const sass::string& abs_path(i->resource().abs_path);
461
+ append_block(ctx.sheets.at(abs_path).root);
462
+ sass_delete_import(ctx.import_stack.back());
463
+ ctx.import_stack.pop_back();
464
+ block_stack.pop_back();
465
+ traces.pop_back();
466
+ return 0;
467
+ }
468
+
469
+ Statement* Expand::operator()(WarningRule* w)
470
+ {
471
+ // eval handles this too, because warnings may occur in functions
472
+ w->perform(&eval);
473
+ return 0;
474
+ }
475
+
476
+ Statement* Expand::operator()(ErrorRule* e)
477
+ {
478
+ // eval handles this too, because errors may occur in functions
479
+ e->perform(&eval);
480
+ return 0;
481
+ }
482
+
483
+ Statement* Expand::operator()(DebugRule* d)
484
+ {
485
+ // eval handles this too, because warnings may occur in functions
486
+ d->perform(&eval);
487
+ return 0;
488
+ }
489
+
490
+ Statement* Expand::operator()(Comment* c)
491
+ {
492
+ if (ctx.output_style() == COMPRESSED) {
493
+ // comments should not be evaluated in compact
494
+ // https://github.com/sass/libsass/issues/2359
495
+ if (!c->is_important()) return NULL;
496
+ }
497
+ eval.is_in_comment = true;
498
+ Comment* rv = SASS_MEMORY_NEW(Comment, c->pstate(), Cast<String>(c->text()->perform(&eval)), c->is_important());
499
+ eval.is_in_comment = false;
500
+ // TODO: eval the text, once we're parsing/storing it as a String_Schema
501
+ return rv;
502
+ }
503
+
504
+ Statement* Expand::operator()(If* i)
505
+ {
506
+ Env env(environment(), true);
507
+ env_stack.push_back(&env);
508
+ call_stack.push_back(i);
509
+ ExpressionObj rv = i->predicate()->perform(&eval);
510
+ if (*rv) {
511
+ append_block(i->block());
512
+ }
513
+ else {
514
+ Block* alt = i->alternative();
515
+ if (alt) append_block(alt);
516
+ }
517
+ call_stack.pop_back();
518
+ env_stack.pop_back();
519
+ return 0;
520
+ }
521
+
522
+ // For does not create a new env scope
523
+ // But iteration vars are reset afterwards
524
+ Statement* Expand::operator()(ForRule* f)
525
+ {
526
+ sass::string variable(f->variable());
527
+ ExpressionObj low = f->lower_bound()->perform(&eval);
528
+ if (low->concrete_type() != Expression::NUMBER) {
529
+ traces.push_back(Backtrace(low->pstate()));
530
+ throw Exception::TypeMismatch(traces, *low, "integer");
531
+ }
532
+ ExpressionObj high = f->upper_bound()->perform(&eval);
533
+ if (high->concrete_type() != Expression::NUMBER) {
534
+ traces.push_back(Backtrace(high->pstate()));
535
+ throw Exception::TypeMismatch(traces, *high, "integer");
536
+ }
537
+ Number_Obj sass_start = Cast<Number>(low);
538
+ Number_Obj sass_end = Cast<Number>(high);
539
+ // check if units are valid for sequence
540
+ if (sass_start->unit() != sass_end->unit()) {
541
+ sass::ostream msg; msg << "Incompatible units: '"
542
+ << sass_start->unit() << "' and '"
543
+ << sass_end->unit() << "'.";
544
+ error(msg.str(), low->pstate(), traces);
545
+ }
546
+ double start = sass_start->value();
547
+ double end = sass_end->value();
548
+ // only create iterator once in this environment
549
+ Env env(environment(), true);
550
+ env_stack.push_back(&env);
551
+ call_stack.push_back(f);
552
+ Block* body = f->block();
553
+ if (start < end) {
554
+ if (f->is_inclusive()) ++end;
555
+ for (double i = start;
556
+ i < end;
557
+ ++i) {
558
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
559
+ env.set_local(variable, it);
560
+ append_block(body);
561
+ }
562
+ } else {
563
+ if (f->is_inclusive()) --end;
564
+ for (double i = start;
565
+ i > end;
566
+ --i) {
567
+ Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
568
+ env.set_local(variable, it);
569
+ append_block(body);
570
+ }
571
+ }
572
+ call_stack.pop_back();
573
+ env_stack.pop_back();
574
+ return 0;
575
+ }
576
+
577
+ // Eval does not create a new env scope
578
+ // But iteration vars are reset afterwards
579
+ Statement* Expand::operator()(EachRule* e)
580
+ {
581
+ sass::vector<sass::string> variables(e->variables());
582
+ ExpressionObj expr = e->list()->perform(&eval);
583
+ List_Obj list;
584
+ Map_Obj map;
585
+ if (expr->concrete_type() == Expression::MAP) {
586
+ map = Cast<Map>(expr);
587
+ }
588
+ else if (SelectorList * ls = Cast<SelectorList>(expr)) {
589
+ ExpressionObj rv = Listize::perform(ls);
590
+ list = Cast<List>(rv);
591
+ }
592
+ else if (expr->concrete_type() != Expression::LIST) {
593
+ list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
594
+ list->append(expr);
595
+ }
596
+ else {
597
+ list = Cast<List>(expr);
598
+ }
599
+ // remember variables and then reset them
600
+ Env env(environment(), true);
601
+ env_stack.push_back(&env);
602
+ call_stack.push_back(e);
603
+ Block* body = e->block();
604
+
605
+ if (map) {
606
+ for (auto key : map->keys()) {
607
+ ExpressionObj k = key->perform(&eval);
608
+ ExpressionObj v = map->at(key)->perform(&eval);
609
+
610
+ if (variables.size() == 1) {
611
+ List_Obj variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
612
+ variable->append(k);
613
+ variable->append(v);
614
+ env.set_local(variables[0], variable);
615
+ } else {
616
+ env.set_local(variables[0], k);
617
+ env.set_local(variables[1], v);
618
+ }
619
+ append_block(body);
620
+ }
621
+ }
622
+ else {
623
+ // bool arglist = list->is_arglist();
624
+ if (list->length() == 1 && Cast<SelectorList>(list)) {
625
+ list = Cast<List>(list);
626
+ }
627
+ for (size_t i = 0, L = list->length(); i < L; ++i) {
628
+ ExpressionObj item = list->at(i);
629
+ // unwrap value if the expression is an argument
630
+ if (Argument_Obj arg = Cast<Argument>(item)) item = arg->value();
631
+ // check if we got passed a list of args (investigate)
632
+ if (List_Obj scalars = Cast<List>(item)) {
633
+ if (variables.size() == 1) {
634
+ List_Obj var = scalars;
635
+ // if (arglist) var = (*scalars)[0];
636
+ env.set_local(variables[0], var);
637
+ } else {
638
+ for (size_t j = 0, K = variables.size(); j < K; ++j) {
639
+ env.set_local(variables[j], j >= scalars->length()
640
+ ? SASS_MEMORY_NEW(Null, expr->pstate())
641
+ : (*scalars)[j]->perform(&eval));
642
+ }
643
+ }
644
+ } else {
645
+ if (variables.size() > 0) {
646
+ env.set_local(variables.at(0), item);
647
+ for (size_t j = 1, K = variables.size(); j < K; ++j) {
648
+ ExpressionObj res = SASS_MEMORY_NEW(Null, expr->pstate());
649
+ env.set_local(variables[j], res);
650
+ }
651
+ }
652
+ }
653
+ append_block(body);
654
+ }
655
+ }
656
+ call_stack.pop_back();
657
+ env_stack.pop_back();
658
+ return 0;
659
+ }
660
+
661
+ Statement* Expand::operator()(WhileRule* w)
662
+ {
663
+ ExpressionObj pred = w->predicate();
664
+ Block* body = w->block();
665
+ Env env(environment(), true);
666
+ env_stack.push_back(&env);
667
+ call_stack.push_back(w);
668
+ ExpressionObj cond = pred->perform(&eval);
669
+ while (!cond->is_false()) {
670
+ append_block(body);
671
+ cond = pred->perform(&eval);
672
+ }
673
+ call_stack.pop_back();
674
+ env_stack.pop_back();
675
+ return 0;
676
+ }
677
+
678
+ Statement* Expand::operator()(Return* r)
679
+ {
680
+ error("@return may only be used within a function", r->pstate(), traces);
681
+ return 0;
682
+ }
683
+
684
+ Statement* Expand::operator()(ExtendRule* e)
685
+ {
686
+
687
+ // evaluate schema first
688
+ if (e->schema()) {
689
+ e->selector(eval(e->schema()));
690
+ e->isOptional(e->selector()->is_optional());
691
+ }
692
+ // evaluate the selector
693
+ e->selector(eval(e->selector()));
694
+
695
+ if (e->selector()) {
696
+
697
+ for (auto complex : e->selector()->elements()) {
698
+
699
+ if (complex->length() != 1) {
700
+ error("complex selectors may not be extended.", complex->pstate(), traces);
701
+ }
702
+
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
+ }
731
+
732
+ }
733
+ else {
734
+ error("complex selectors may not be extended.", complex->pstate(), traces);
735
+ }
736
+ }
737
+ }
738
+
739
+ return nullptr;
740
+
741
+ }
742
+
743
+ Statement* Expand::operator()(Definition* d)
744
+ {
745
+ Env* env = environment();
746
+ Definition_Obj dd = SASS_MEMORY_COPY(d);
747
+ env->local_frame()[d->name() +
748
+ (d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd;
749
+
750
+ if (d->type() == Definition::FUNCTION && (
751
+ Prelexer::calc_fn_call(d->name().c_str()) ||
752
+ d->name() == "element" ||
753
+ d->name() == "expression" ||
754
+ d->name() == "url"
755
+ )) {
756
+ deprecated(
757
+ "Naming a function \"" + d->name() + "\" is disallowed and will be an error in future versions of Sass.",
758
+ "This name conflicts with an existing CSS function with special parse rules.",
759
+ false, d->pstate()
760
+ );
761
+ }
762
+
763
+ // set the static link so we can have lexical scoping
764
+ dd->environment(env);
765
+ return 0;
766
+ }
767
+
768
+ Statement* Expand::operator()(Mixin_Call* c)
769
+ {
770
+
771
+ if (recursions > maxRecursion) {
772
+ throw Exception::StackError(traces, *c);
773
+ }
774
+
775
+ recursions ++;
776
+
777
+ Env* env = environment();
778
+ sass::string full_name(c->name() + "[m]");
779
+ if (!env->has(full_name)) {
780
+ error("no mixin named " + c->name(), c->pstate(), traces);
781
+ }
782
+ Definition_Obj def = Cast<Definition>((*env)[full_name]);
783
+ Block_Obj body = def->block();
784
+ Parameters_Obj params = def->parameters();
785
+
786
+ if (c->block() && c->name() != "@content" && !body->has_content()) {
787
+ error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), traces);
788
+ }
789
+ ExpressionObj rv = c->arguments()->perform(&eval);
790
+ Arguments_Obj args = Cast<Arguments>(rv);
791
+ sass::string msg(", in mixin `" + c->name() + "`");
792
+ traces.push_back(Backtrace(c->pstate(), msg));
793
+ ctx.callee_stack.push_back({
794
+ c->name().c_str(),
795
+ c->pstate().getPath(),
796
+ c->pstate().getLine(),
797
+ c->pstate().getColumn(),
798
+ SASS_CALLEE_MIXIN,
799
+ { env }
800
+ });
801
+
802
+ Env new_env(def->environment());
803
+ env_stack.push_back(&new_env);
804
+ if (c->block()) {
805
+ Parameters_Obj params = c->block_parameters();
806
+ if (!params) params = SASS_MEMORY_NEW(Parameters, c->pstate());
807
+ // represent mixin content blocks as thunks/closures
808
+ Definition_Obj thunk = SASS_MEMORY_NEW(Definition,
809
+ c->pstate(),
810
+ "@content",
811
+ params,
812
+ c->block(),
813
+ Definition::MIXIN);
814
+ thunk->environment(env);
815
+ new_env.local_frame()["@content[m]"] = thunk;
816
+ }
817
+
818
+ bind(sass::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
819
+
820
+ Block_Obj trace_block = SASS_MEMORY_NEW(Block, c->pstate());
821
+ Trace_Obj trace = SASS_MEMORY_NEW(Trace, c->pstate(), c->name(), trace_block);
822
+
823
+ env->set_global("is_in_mixin", bool_true);
824
+ if (Block* pr = block_stack.back()) {
825
+ trace_block->is_root(pr->is_root());
826
+ }
827
+ block_stack.push_back(trace_block);
828
+ for (auto bb : body->elements()) {
829
+ if (StyleRule* r = Cast<StyleRule>(bb)) {
830
+ r->is_root(trace_block->is_root());
831
+ }
832
+ Statement_Obj ith = bb->perform(this);
833
+ if (ith) trace->block()->append(ith);
834
+ }
835
+ block_stack.pop_back();
836
+ env->del_global("is_in_mixin");
837
+
838
+ ctx.callee_stack.pop_back();
839
+ env_stack.pop_back();
840
+ traces.pop_back();
841
+
842
+ recursions --;
843
+ return trace.detach();
844
+ }
845
+
846
+ Statement* Expand::operator()(Content* c)
847
+ {
848
+ Env* env = environment();
849
+ // convert @content directives into mixin calls to the underlying thunk
850
+ if (!env->has("@content[m]")) return 0;
851
+ Arguments_Obj args = c->arguments();
852
+ if (!args) args = SASS_MEMORY_NEW(Arguments, c->pstate());
853
+
854
+ Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call,
855
+ c->pstate(),
856
+ "@content",
857
+ args);
858
+
859
+ Trace_Obj trace = Cast<Trace>(call->perform(this));
860
+ return trace.detach();
861
+ }
862
+
863
+ // process and add to last block on stack
864
+ inline void Expand::append_block(Block* b)
865
+ {
866
+ if (b->is_root()) call_stack.push_back(b);
867
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
868
+ Statement* stm = b->at(i);
869
+ Statement_Obj ith = stm->perform(this);
870
+ if (ith) block_stack.back()->append(ith);
871
+ }
872
+ if (b->is_root()) call_stack.pop_back();
873
+ }
874
+
875
+ }