@@ -152,39 +152,41 @@ export default {
152152 * Populates `cyclic` with cyclic segments.
153153 */
154154
155- function countPathsFromStart ( segment ) {
155+ function countPathsFromStart ( segment , pathHistory ) {
156156 const { cache} = countPathsFromStart ;
157157 let paths = cache . get ( segment . id ) ;
158-
159- // If `paths` is null then we've found a cycle! Add it to `cyclic` and
160- // any other segments which are a part of this cycle.
161- if ( paths === null ) {
162- if ( cyclic . has ( segment . id ) ) {
163- return 0 ;
164- } else {
165- cyclic . add ( segment . id ) ;
166- for ( const prevSegment of segment . prevSegments ) {
167- countPathsFromStart ( prevSegment ) ;
168- }
169- return 0 ;
158+ const pathList = new Set ( pathHistory ) ;
159+
160+ // If `pathList` includes the current segment then we've found a cycle!
161+ // We need to fill `cyclic` with all segments inside cycle
162+ if ( pathList . has ( segment . id ) ) {
163+ const pathArray = [ ...pathList ] ;
164+ const cyclicSegments = pathArray . slice (
165+ pathArray . indexOf ( segment . id ) + 1 ,
166+ ) ;
167+ for ( const cyclicSegment of cyclicSegments ) {
168+ cyclic . add ( cyclicSegment ) ;
170169 }
170+
171+ return 0 ;
171172 }
172173
174+ // add the current segment to pathList
175+ pathList . add ( segment . id ) ;
176+
173177 // We have a cached `paths`. Return it.
174178 if ( paths !== undefined ) {
175179 return paths ;
176180 }
177181
178- // Compute `paths` and cache it. Guarding against cycles.
179- cache . set ( segment . id , null ) ;
180182 if ( codePath . thrownSegments . includes ( segment ) ) {
181183 paths = 0 ;
182184 } else if ( segment . prevSegments . length === 0 ) {
183185 paths = 1 ;
184186 } else {
185187 paths = 0 ;
186188 for ( const prevSegment of segment . prevSegments ) {
187- paths += countPathsFromStart ( prevSegment ) ;
189+ paths += countPathsFromStart ( prevSegment , pathList ) ;
188190 }
189191 }
190192
@@ -221,43 +223,45 @@ export default {
221223 * Populates `cyclic` with cyclic segments.
222224 */
223225
224- function countPathsToEnd ( segment ) {
226+ function countPathsToEnd ( segment , pathHistory ) {
225227 const { cache} = countPathsToEnd ;
226228 let paths = cache . get ( segment . id ) ;
227-
228- // If `paths` is null then we've found a cycle! Add it to `cyclic` and
229- // any other segments which are a part of this cycle.
230- if ( paths === null ) {
231- if ( cyclic . has ( segment . id ) ) {
232- return 0 ;
233- } else {
234- cyclic . add ( segment . id ) ;
235- for ( const nextSegment of segment . nextSegments ) {
236- countPathsToEnd ( nextSegment ) ;
237- }
238- return 0 ;
229+ let pathList = new Set ( pathHistory ) ;
230+
231+ // If `pathList` includes the current segment then we've found a cycle!
232+ // We need to fill `cyclic` with all segments inside cycle
233+ if ( pathList . has ( segment . id ) ) {
234+ const pathArray = Array . from ( pathList ) ;
235+ const cyclicSegments = pathArray . slice (
236+ pathArray . indexOf ( segment . id ) + 1 ,
237+ ) ;
238+ for ( const cyclicSegment of cyclicSegments ) {
239+ cyclic . add ( cyclicSegment ) ;
239240 }
241+
242+ return 0 ;
240243 }
241244
245+ // add the current segment to pathList
246+ pathList . add ( segment . id ) ;
247+
242248 // We have a cached `paths`. Return it.
243249 if ( paths !== undefined ) {
244250 return paths ;
245251 }
246252
247- // Compute `paths` and cache it. Guarding against cycles.
248- cache . set ( segment . id , null ) ;
249253 if ( codePath . thrownSegments . includes ( segment ) ) {
250254 paths = 0 ;
251255 } else if ( segment . nextSegments . length === 0 ) {
252256 paths = 1 ;
253257 } else {
254258 paths = 0 ;
255259 for ( const nextSegment of segment . nextSegments ) {
256- paths += countPathsToEnd ( nextSegment ) ;
260+ paths += countPathsToEnd ( nextSegment , pathList ) ;
257261 }
258262 }
259- cache . set ( segment . id , paths ) ;
260263
264+ cache . set ( segment . id , paths ) ;
261265 return paths ;
262266 }
263267
0 commit comments