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
@@ -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
+ sass::vector<sass::vector<SelectorComponentObj>> unifyComplex(
17
+ const sass::vector<sass::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, SourceSpan("[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
+ sass::vector<sass::vector<SelectorComponentObj>> complexesWithoutBases;
43
+ for (size_t i = 0; i < complexes.size(); i += 1) {
44
+ sass::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* TypeSelector::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
+ TypeSelector* type = Cast<TypeSelector>(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* IDSelector::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 IDSelector* id_sel = Cast<IDSelector>(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* PseudoSelector::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 (PseudoSelectorObj 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 PseudoSelector::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* TypeSelector::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 TypeSelector::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
+ sass::vector<sass::vector<SelectorComponentObj>> rv =
242
+ unifyComplex({ elements(), rhs->elements() });
243
+ for (sass::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
  }