@@ -65,9 +65,7 @@ function child(query, node, index, parent, state) {
65
65
return
66
66
}
67
67
68
- walkIterator ( query , node , state )
69
- . each ( )
70
- . done ( )
68
+ indexedSearch ( query , node , state )
71
69
}
72
70
73
71
function nextSibling ( query , node , index , parent , state ) {
@@ -76,11 +74,7 @@ function nextSibling(query, node, index, parent, state) {
76
74
return
77
75
}
78
76
79
- walkIterator ( query , parent , state )
80
- . prefillTypeIndex ( 0 , ++ index )
81
- . each ( index , ++ index )
82
- . prefillTypeIndex ( index )
83
- . done ( )
77
+ indexedSearch ( query , parent , state , index + 1 , true )
84
78
}
85
79
86
80
function subsequentSibling ( query , node , index , parent , state ) {
@@ -89,132 +83,116 @@ function subsequentSibling(query, node, index, parent, state) {
89
83
return
90
84
}
91
85
92
- walkIterator ( query , parent , state )
93
- . prefillTypeIndex ( 0 , ++ index )
94
- . each ( index )
95
- . done ( )
86
+ indexedSearch ( query , parent , state , index + 1 )
96
87
}
97
88
98
89
// Handles `typeIndex` and `typeCount` properties for every walker.
99
- function walkIterator ( query , parent , state ) {
100
- var nodes = parent . children
101
- var typeIndex = state . index ? createTypeIndex ( ) : null
90
+ function indexedSearch ( query , parent , state , from , firstElementOnly ) {
91
+ var needsIndex = state . index
92
+ var children = parent . children
93
+ var length = children . length
102
94
var delayed = [ ]
103
-
104
- return {
105
- prefillTypeIndex : rangeDefaults ( prefillTypeIndex ) ,
106
- each : rangeDefaults ( each ) ,
107
- done : done
95
+ var index = 0
96
+ var types = { }
97
+ var elements = 0
98
+ var handle = needsIndex ? delay : add
99
+ var child
100
+
101
+ // Start looking at `from`
102
+ if ( from === undefined ) {
103
+ from = 0
108
104
}
109
105
110
- function done ( ) {
111
- var length = delayed . length
112
- var index = - 1
106
+ // Exit if there are no further nodes.
107
+ if ( from >= length ) {
108
+ return
109
+ }
113
110
114
- while ( ++ index < length ) {
115
- delayed [ index ] ( )
111
+ // If we need to index for types, do so for all elements before `from`.
112
+ if ( needsIndex ) {
113
+ while ( index < from ) {
114
+ child = children [ index ]
116
115
117
- if ( state . one && state . found ) {
118
- break
116
+ if ( child . type === 'element' ) {
117
+ count ( child . tagName )
119
118
}
120
- }
121
119
122
- return this
123
- }
124
-
125
- function prefillTypeIndex ( start , end ) {
126
- if ( typeIndex ) {
127
- while ( start < end ) {
128
- typeIndex ( nodes [ start ] )
129
- start ++
130
- }
120
+ index ++
131
121
}
132
-
133
- return this
134
122
}
135
123
136
- function each ( start , end ) {
137
- var child = nodes [ start ]
138
- var index
139
- var elementIndex
140
-
141
- if ( start >= end ) {
142
- return this
143
- }
124
+ index = from
144
125
145
- if ( typeIndex ) {
146
- elementIndex = typeIndex . elements
147
- index = typeIndex ( child )
148
- delayed . push ( delay )
149
- } else {
150
- pushNode ( )
151
- }
126
+ while ( index < length ) {
127
+ child = children [ index ]
152
128
153
- // Stop if we’re looking for one node and it’s already found .
154
- if ( state . one && state . found ) {
155
- return this
156
- }
129
+ // Only check elements .
130
+ // Check either all elements, or only check the first sibling
131
+ if ( child . type === 'element' ) {
132
+ handle ( child , index )
157
133
158
- return each . call ( this , start + 1 , end )
134
+ // Stop if we’re looking for one node and it’s already found.
135
+ if ( state . one && state . found ) {
136
+ return
137
+ }
159
138
160
- function delay ( ) {
161
- state . typeIndex = index
162
- state . elementIndex = elementIndex
163
- state . typeCount = typeIndex . count ( child )
164
- state . elementCount = typeIndex . elements
165
- pushNode ( )
139
+ if ( firstElementOnly ) {
140
+ break
141
+ }
166
142
}
167
143
168
- function pushNode ( ) {
169
- var exit = enter ( state , child )
170
- state . iterator ( query , child , start , parent , state )
171
- exit ( )
172
- }
144
+ index ++
173
145
}
174
146
175
- function rangeDefaults ( iterator ) {
176
- return rangeDefault
147
+ if ( needsIndex ) {
148
+ index = - 1
149
+ length = delayed . length
177
150
178
- function rangeDefault ( start , end ) {
179
- if ( start === null || start === undefined || start < 0 ) {
180
- start = 0
181
- }
151
+ while ( ++ index < length ) {
152
+ delayed [ index ] ( )
182
153
183
- if ( end === null || end === undefined || end > nodes . length ) {
184
- end = nodes . length
154
+ // Stop if we’re looking for one node and it’s already found.
155
+ if ( state . one && state . found ) {
156
+ // To do: maybe return?
157
+ return
185
158
}
186
-
187
- return iterator . call ( this , start , end )
188
159
}
189
160
}
190
- }
191
-
192
- function createTypeIndex ( ) {
193
- var counts = { }
194
161
195
- index . count = count
196
- index . elements = 0
162
+ function delay ( node , childIndex ) {
163
+ var name = node . tagName
164
+ var elementsBefore = elements
165
+ var elementsByTypeBefore = own . call ( types , name ) ? types [ name ] : 0
197
166
198
- return index
167
+ count ( name )
199
168
200
- function index ( node ) {
201
- var type = node . tagName
169
+ delayed . push ( fn )
202
170
203
- if ( ! type ) {
204
- return 0
205
- }
171
+ function fn ( ) {
172
+ // Before counting further elements:
173
+ state . elementIndex = elementsBefore
174
+ state . typeIndex = elementsByTypeBefore
206
175
207
- index . elements ++
176
+ // After counting all elements.
177
+ state . elementCount = elements
178
+ state . typeCount = types [ name ]
208
179
209
- if ( ! own . call ( counts , type ) ) {
210
- counts [ type ] = 0
180
+ add ( node , childIndex )
211
181
}
182
+ }
212
183
213
- // Note: ++ needs is intended to be postfixed!
214
- return counts [ type ] ++
184
+ function add ( node , childIndex ) {
185
+ var exit = enter ( state , node )
186
+ state . iterator ( query , node , childIndex , parent , state )
187
+ exit ( )
215
188
}
216
189
217
- function count ( node ) {
218
- return own . call ( counts , node . tagName ) ? counts [ node . tagName ] : 0
190
+ function count ( name ) {
191
+ if ( ! own . call ( types , name ) ) {
192
+ types [ name ] = 0
193
+ }
194
+
195
+ elements ++
196
+ types [ name ] ++
219
197
}
220
198
}
0 commit comments