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
@@ -1,280 +1,275 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
2
- #include "ast.hpp"
3
- #include "context.hpp"
4
- #include "node.hpp"
5
- #include "eval.hpp"
6
- #include "extend.hpp"
7
- #include "emitter.hpp"
8
- #include "color_maps.hpp"
9
- #include "ast_fwd_decl.hpp"
10
- #include <set>
11
- #include <iomanip>
12
- #include <iostream>
13
- #include <algorithm>
14
- #include <functional>
15
- #include <cctype>
16
- #include <locale>
17
-
18
- #include "ast_selectors.hpp"
19
4
 
20
- // #define DEBUG_UNIFY
5
+ #include "ast.hpp"
21
6
 
22
7
  namespace Sass {
23
8
 
24
- Compound_Selector* Compound_Selector::unify_with(Compound_Selector* rhs)
9
+ // ##########################################################################
10
+ // Returns the contents of a [SelectorList] that matches only
11
+ // elements that are matched by both [complex1] and [complex2].
12
+ // If no such list can be produced, returns `null`.
13
+ // ##########################################################################
14
+ // ToDo: fine-tune API to avoid unnecessary wrapper allocations
15
+ // ##########################################################################
16
+ std::vector<std::vector<SelectorComponentObj>> unifyComplex(
17
+ const std::vector<std::vector<SelectorComponentObj>>& complexes)
25
18
  {
26
- #ifdef DEBUG_UNIFY
27
- const std::string debug_call = "unify(Compound[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
28
- std::cerr << debug_call << std::endl;
29
- #endif
30
19
 
20
+ SASS_ASSERT(!complexes.empty(), "Can't unify empty list");
21
+ if (complexes.size() == 1) return complexes;
22
+
23
+ CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, ParserState("[phony]"));
24
+ for (auto complex : complexes) {
25
+ SelectorComponentObj base = complex.back();
26
+ if (CompoundSelector * comp = base->getCompound()) {
27
+ if (unifiedBase->empty()) {
28
+ unifiedBase->concat(comp);
29
+ }
30
+ else {
31
+ for (SimpleSelectorObj simple : comp->elements()) {
32
+ unifiedBase = simple->unifyWith(unifiedBase);
33
+ if (unifiedBase.isNull()) return {};
34
+ }
35
+ }
36
+ }
37
+ else {
38
+ return {};
39
+ }
40
+ }
41
+
42
+ std::vector<std::vector<SelectorComponentObj>> complexesWithoutBases;
43
+ for (size_t i = 0; i < complexes.size(); i += 1) {
44
+ std::vector<SelectorComponentObj> sel = complexes[i];
45
+ sel.pop_back(); // remove last item (base) from the list
46
+ complexesWithoutBases.push_back(std::move(sel));
47
+ }
48
+
49
+ complexesWithoutBases.back().push_back(unifiedBase);
50
+
51
+ return weave(complexesWithoutBases);
52
+
53
+ }
54
+ // EO unifyComplex
55
+
56
+ // ##########################################################################
57
+ // Returns a [CompoundSelector] that matches only elements
58
+ // that are matched by both [compound1] and [compound2].
59
+ // If no such selector can be produced, returns `null`.
60
+ // ##########################################################################
61
+ CompoundSelector* CompoundSelector::unifyWith(CompoundSelector* rhs)
62
+ {
31
63
  if (empty()) return rhs;
32
- Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
33
- for (const Simple_Selector_Obj& sel : elements()) {
34
- unified = sel->unify_with(unified);
64
+ CompoundSelectorObj unified = SASS_MEMORY_COPY(rhs);
65
+ for (const SimpleSelectorObj& sel : elements()) {
66
+ unified = sel->unifyWith(unified);
35
67
  if (unified.isNull()) break;
36
68
  }
37
-
38
- #ifdef DEBUG_UNIFY
39
- std::cerr << "> " << debug_call << " = Compound[" << unified->to_string() << "]" << std::endl;
40
- #endif
41
69
  return unified.detach();
42
70
  }
43
-
44
- Compound_Selector* Simple_Selector::unify_with(Compound_Selector* rhs)
71
+ // EO CompoundSelector::unifyWith(CompoundSelector*)
72
+
73
+ // ##########################################################################
74
+ // Returns the compoments of a [CompoundSelector] that matches only elements
75
+ // matched by both this and [compound]. By default, this just returns a copy
76
+ // of [compound] with this selector added to the end, or returns the original
77
+ // array if this selector already exists in it. Returns `null` if unification
78
+ // is impossible—for example, if there are multiple ID selectors.
79
+ // ##########################################################################
80
+ // This is implemented in `selector/simple.dart` as `SimpleSelector::unify`
81
+ // ##########################################################################
82
+ CompoundSelector* SimpleSelector::unifyWith(CompoundSelector* rhs)
45
83
  {
46
- #ifdef DEBUG_UNIFY
47
- const std::string debug_call = "unify(Simple[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
48
- std::cerr << debug_call << std::endl;
49
- #endif
50
84
 
51
85
  if (rhs->length() == 1) {
52
- if (rhs->at(0)->is_universal()) {
53
- Compound_Selector* this_compound = SASS_MEMORY_NEW(Compound_Selector, pstate(), 1);
86
+ if (rhs->get(0)->is_universal()) {
87
+ CompoundSelector* this_compound = SASS_MEMORY_NEW(CompoundSelector, pstate());
54
88
  this_compound->append(SASS_MEMORY_COPY(this));
55
- Compound_Selector* unified = rhs->at(0)->unify_with(this_compound);
89
+ CompoundSelector* unified = rhs->get(0)->unifyWith(this_compound);
56
90
  if (unified == nullptr || unified != this_compound) delete this_compound;
57
-
58
- #ifdef DEBUG_UNIFY
59
- std::cerr << "> " << debug_call << " = " << "Compound[" << unified->to_string() << "]" << std::endl;
60
- #endif
61
91
  return unified;
62
92
  }
63
93
  }
64
- for (const Simple_Selector_Obj& sel : rhs->elements()) {
94
+ for (const SimpleSelectorObj& sel : rhs->elements()) {
65
95
  if (*this == *sel) {
66
- #ifdef DEBUG_UNIFY
67
- std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
68
- #endif
69
96
  return rhs;
70
97
  }
71
98
  }
72
- const int lhs_order = this->unification_order();
73
- size_t i = rhs->length();
74
- while (i > 0 && lhs_order < rhs->at(i - 1)->unification_order()) --i;
75
- rhs->insert(rhs->begin() + i, this);
76
- #ifdef DEBUG_UNIFY
77
- std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
78
- #endif
79
- return rhs;
80
- }
81
99
 
82
- Simple_Selector* Type_Selector::unify_with(Simple_Selector* rhs)
83
- {
84
- #ifdef DEBUG_UNIFY
85
- const std::string debug_call = "unify(Type[" + this->to_string() + "], Simple[" + rhs->to_string() + "])";
86
- std::cerr << debug_call << std::endl;
87
- #endif
100
+ CompoundSelectorObj result = SASS_MEMORY_NEW(CompoundSelector, rhs->pstate());
88
101
 
89
- bool rhs_ns = false;
90
- if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
91
- if (!is_universal_ns()) {
92
- #ifdef DEBUG_UNIFY
93
- std::cerr << "> " << debug_call << " = nullptr" << std::endl;
94
- #endif
95
- return nullptr;
96
- }
97
- rhs_ns = true;
98
- }
99
- bool rhs_name = false;
100
- if (!(name_ == rhs->name() || rhs->is_universal())) {
101
- if (!(is_universal())) {
102
- #ifdef DEBUG_UNIFY
103
- std::cerr << "> " << debug_call << " = nullptr" << std::endl;
104
- #endif
105
- return nullptr;
102
+ bool addedThis = false;
103
+ for (auto simple : rhs->elements()) {
104
+ // Make sure pseudo selectors always come last.
105
+ if (!addedThis && simple->getPseudoSelector()) {
106
+ result->append(this);
107
+ addedThis = true;
106
108
  }
107
- rhs_name = true;
109
+ result->append(simple);
108
110
  }
109
- if (rhs_ns) {
110
- ns(rhs->ns());
111
- has_ns(rhs->has_ns());
111
+
112
+ if (!addedThis) {
113
+ result->append(this);
112
114
  }
113
- if (rhs_name) name(rhs->name());
114
- #ifdef DEBUG_UNIFY
115
- std::cerr << "> " << debug_call << " = Simple[" << this->to_string() << "]" << std::endl;
116
- #endif
117
- return this;
115
+ return result.detach();
116
+
118
117
  }
118
+ // EO SimpleSelector::unifyWith(CompoundSelector*)
119
119
 
120
- Compound_Selector* Type_Selector::unify_with(Compound_Selector* rhs)
120
+ // ##########################################################################
121
+ // This is implemented in `selector/type.dart` as `PseudoSelector::unify`
122
+ // ##########################################################################
123
+ CompoundSelector* Type_Selector::unifyWith(CompoundSelector* rhs)
121
124
  {
122
- #ifdef DEBUG_UNIFY
123
- const std::string debug_call = "unify(Type[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
124
- std::cerr << debug_call << std::endl;
125
- #endif
126
-
127
125
  if (rhs->empty()) {
128
126
  rhs->append(this);
129
- #ifdef DEBUG_UNIFY
130
- std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
131
- #endif
132
127
  return rhs;
133
128
  }
134
- Type_Selector* rhs_0 = Cast<Type_Selector>(rhs->at(0));
135
- if (rhs_0 != nullptr) {
136
- Simple_Selector* unified = unify_with(rhs_0);
129
+ Type_Selector* type = Cast<Type_Selector>(rhs->at(0));
130
+ if (type != nullptr) {
131
+ SimpleSelector* unified = unifyWith(type);
137
132
  if (unified == nullptr) {
138
- #ifdef DEBUG_UNIFY
139
- std::cerr << "> " << debug_call << " = nullptr" << std::endl;
140
- #endif
141
133
  return nullptr;
142
134
  }
143
135
  rhs->elements()[0] = unified;
144
- } else if (!is_universal() || (has_ns_ && ns_ != "*")) {
136
+ }
137
+ else if (!is_universal() || (has_ns_ && ns_ != "*")) {
145
138
  rhs->insert(rhs->begin(), this);
146
139
  }
147
- #ifdef DEBUG_UNIFY
148
- std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
149
- #endif
150
140
  return rhs;
151
141
  }
152
142
 
153
- Compound_Selector* Class_Selector::unify_with(Compound_Selector* rhs)
154
- {
155
- rhs->has_line_break(has_line_break());
156
- return Simple_Selector::unify_with(rhs);
157
- }
158
-
159
- Compound_Selector* Id_Selector::unify_with(Compound_Selector* rhs)
143
+ // ##########################################################################
144
+ // This is implemented in `selector/id.dart` as `PseudoSelector::unify`
145
+ // ##########################################################################
146
+ CompoundSelector* Id_Selector::unifyWith(CompoundSelector* rhs)
160
147
  {
161
- for (const Simple_Selector_Obj& sel : rhs->elements()) {
162
- if (Id_Selector* id_sel = Cast<Id_Selector>(sel)) {
148
+ for (const SimpleSelector* sel : rhs->elements()) {
149
+ if (const Id_Selector* id_sel = Cast<Id_Selector>(sel)) {
163
150
  if (id_sel->name() != name()) return nullptr;
164
151
  }
165
152
  }
166
- rhs->has_line_break(has_line_break());
167
- return Simple_Selector::unify_with(rhs);
168
- }
169
-
170
- Compound_Selector* Pseudo_Selector::unify_with(Compound_Selector* rhs)
171
- {
172
- if (is_pseudo_element()) {
173
- for (const Simple_Selector_Obj& sel : rhs->elements()) {
174
- if (Pseudo_Selector* pseudo_sel = Cast<Pseudo_Selector>(sel)) {
175
- if (pseudo_sel->is_pseudo_element() && pseudo_sel->name() != name()) return nullptr;
176
- }
177
- }
178
- }
179
- return Simple_Selector::unify_with(rhs);
153
+ return SimpleSelector::unifyWith(rhs);
180
154
  }
181
155
 
182
- Selector_List* Complex_Selector::unify_with(Complex_Selector* rhs)
156
+ // ##########################################################################
157
+ // This is implemented in `selector/pseudo.dart` as `PseudoSelector::unify`
158
+ // ##########################################################################
159
+ CompoundSelector* Pseudo_Selector::unifyWith(CompoundSelector* compound)
183
160
  {
184
- #ifdef DEBUG_UNIFY
185
- const std::string debug_call = "unify(Complex[" + this->to_string() + "], Complex[" + rhs->to_string() + "])";
186
- std::cerr << debug_call << std::endl;
187
- #endif
188
-
189
- // get last tails (on the right side)
190
- Complex_Selector* l_last = this->mutable_last();
191
- Complex_Selector* r_last = rhs->mutable_last();
192
-
193
- // check valid pointers (assertion)
194
- SASS_ASSERT(l_last, "lhs is null");
195
- SASS_ASSERT(r_last, "rhs is null");
196
-
197
- // Not sure about this check, but closest way I could check
198
- // was to see if this is a ruby 'SimpleSequence' equivalent.
199
- // It seems to do the job correctly as some specs react to this
200
- if (l_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
201
- if (r_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
202
-
203
- // get the headers for the last tails
204
- Compound_Selector* l_last_head = l_last->head();
205
- Compound_Selector* r_last_head = r_last->head();
206
-
207
- // check valid head pointers (assertion)
208
- SASS_ASSERT(l_last_head, "lhs head is null");
209
- SASS_ASSERT(r_last_head, "rhs head is null");
210
-
211
- // get the unification of the last compound selectors
212
- Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
213
-
214
- // abort if we could not unify heads
215
- if (unified == nullptr) return nullptr;
216
-
217
- // move the head
218
- if (l_last_head->is_universal()) l_last->head({});
219
- r_last->head(unified);
220
161
 
221
- #ifdef DEBUG_UNIFY
222
- std::cerr << "> " << debug_call << " before weave: lhs=" << this->to_string() << " rhs=" << rhs->to_string() << std::endl;
223
- #endif
162
+ if (compound->length() == 1 && compound->first()->is_universal()) {
163
+ // std::cerr << "implement universal pseudo\n";
164
+ }
224
165
 
225
- // create nodes from both selectors
226
- Node lhsNode = complexSelectorToNode(this);
227
- Node rhsNode = complexSelectorToNode(rhs);
166
+ for (const SimpleSelectorObj& sel : compound->elements()) {
167
+ if (*this == *sel) {
168
+ return compound;
169
+ }
170
+ }
228
171
 
229
- // Complex_Selector_Obj fake = unified->to_complex();
230
- // Node unified_node = complexSelectorToNode(fake);
231
- // // add to permutate the list?
232
- // rhsNode.plus(unified_node);
172
+ CompoundSelectorObj result = SASS_MEMORY_NEW(CompoundSelector, compound->pstate());
173
+
174
+ bool addedThis = false;
175
+ for (auto simple : compound->elements()) {
176
+ // Make sure pseudo selectors always come last.
177
+ if (Pseudo_Selector_Obj pseudo = simple->getPseudoSelector()) {
178
+ if (pseudo->isElement()) {
179
+ // A given compound selector may only contain one pseudo element. If
180
+ // [compound] has a different one than [this], unification fails.
181
+ if (isElement()) {
182
+ return {};
183
+ }
184
+ // Otherwise, this is a pseudo selector and
185
+ // should come before pseduo elements.
186
+ result->append(this);
187
+ addedThis = true;
188
+ }
189
+ }
190
+ result->append(simple);
191
+ }
233
192
 
234
- // do some magic we inherit from node and extend
235
- Node node = subweave(lhsNode, rhsNode);
236
- Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate(), node.collection()->size());
237
- for (auto &item : *node.collection()) {
238
- result->append(nodeToComplexSelector(Node::naiveTrim(item)));
193
+ if (!addedThis) {
194
+ result->append(this);
239
195
  }
240
196
 
241
- #ifdef DEBUG_UNIFY
242
- std::cerr << "> " << debug_call << " = " << result->to_string() << std::endl;
243
- #endif
197
+ return result.detach();
244
198
 
245
- // only return if list has some entries
246
- return result->length() ? result.detach() : nullptr;
247
199
  }
200
+ // EO Pseudo_Selector::unifyWith(CompoundSelector*
201
+
202
+ // ##########################################################################
203
+ // This is implemented in `extend/functions.dart` as `unifyUniversalAndElement`
204
+ // Returns a [SimpleSelector] that matches only elements that are matched by
205
+ // both [selector1] and [selector2], which must both be either [UniversalSelector]s
206
+ // or [TypeSelector]s. If no such selector can be produced, returns `null`.
207
+ // Note: libsass handles universal selector directly within the type selector
208
+ // ##########################################################################
209
+ SimpleSelector* Type_Selector::unifyWith(const SimpleSelector* rhs)
210
+ {
211
+ bool rhs_ns = false;
212
+ if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
213
+ if (!is_universal_ns()) {
214
+ return nullptr;
215
+ }
216
+ rhs_ns = true;
217
+ }
218
+ bool rhs_name = false;
219
+ if (!(name_ == rhs->name() || rhs->is_universal())) {
220
+ if (!(is_universal())) {
221
+ return nullptr;
222
+ }
223
+ rhs_name = true;
224
+ }
225
+ if (rhs_ns) {
226
+ ns(rhs->ns());
227
+ has_ns(rhs->has_ns());
228
+ }
229
+ if (rhs_name) name(rhs->name());
230
+ return this;
231
+ }
232
+ // EO Type_Selector::unifyWith(const SimpleSelector*)
248
233
 
249
- Selector_List* Selector_List::unify_with(Selector_List* rhs) {
250
- #ifdef DEBUG_UNIFY
251
- const std::string debug_call = "unify(List[" + this->to_string() + "], List[" + rhs->to_string() + "])";
252
- std::cerr << debug_call << std::endl;
253
- #endif
234
+ // ##########################################################################
235
+ // Unify two complex selectors. Internally calls `unifyComplex`
236
+ // and then wraps the result in newly create ComplexSelectors.
237
+ // ##########################################################################
238
+ SelectorList* ComplexSelector::unifyWith(ComplexSelector* rhs)
239
+ {
240
+ SelectorListObj list = SASS_MEMORY_NEW(SelectorList, pstate());
241
+ std::vector<std::vector<SelectorComponentObj>> rv =
242
+ unifyComplex({ elements(), rhs->elements() });
243
+ for (std::vector<SelectorComponentObj> items : rv) {
244
+ ComplexSelectorObj sel = SASS_MEMORY_NEW(ComplexSelector, pstate());
245
+ sel->elements() = std::move(items);
246
+ list->append(sel);
247
+ }
248
+ return list.detach();
249
+ }
250
+ // EO ComplexSelector::unifyWith(ComplexSelector*)
254
251
 
255
- std::vector<Complex_Selector_Obj> result;
256
- // Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
257
- for (Complex_Selector_Obj& seq1 : elements()) {
258
- for (Complex_Selector_Obj& seq2 : rhs->elements()) {
259
- Complex_Selector_Obj seq1_copy = SASS_MEMORY_CLONE(seq1);
260
- Complex_Selector_Obj seq2_copy = SASS_MEMORY_CLONE(seq2);
261
- Selector_List_Obj unified = seq1_copy->unify_with(seq2_copy);
262
- if (unified) {
263
- result.reserve(result.size() + unified->length());
264
- std::copy(unified->begin(), unified->end(), std::back_inserter(result));
252
+ // ##########################################################################
253
+ // only called from the sass function `selector-unify`
254
+ // ##########################################################################
255
+ SelectorList* SelectorList::unifyWith(SelectorList* rhs)
256
+ {
257
+ SelectorList* slist = SASS_MEMORY_NEW(SelectorList, pstate());
258
+ // Unify all of children with RHS's children,
259
+ // storing the results in `unified_complex_selectors`
260
+ for (ComplexSelectorObj& seq1 : elements()) {
261
+ for (ComplexSelectorObj& seq2 : rhs->elements()) {
262
+ if (SelectorListObj unified = seq1->unifyWith(seq2)) {
263
+ std::move(unified->begin(), unified->end(),
264
+ std::inserter(slist->elements(), slist->end()));
265
265
  }
266
266
  }
267
267
  }
268
-
269
- // Creates the final Selector_List by combining all the complex selectors
270
- Selector_List* final_result = SASS_MEMORY_NEW(Selector_List, pstate(), result.size());
271
- for (Complex_Selector_Obj& sel : result) {
272
- final_result->append(sel);
273
- }
274
- #ifdef DEBUG_UNIFY
275
- std::cerr << "> " << debug_call << " = " << final_result->to_string() << std::endl;
276
- #endif
277
- return final_result;
268
+ return slist;
278
269
  }
270
+ // EO SelectorList::unifyWith(SelectorList*)
271
+
272
+ // ##########################################################################
273
+ // ##########################################################################
279
274
 
280
275
  }