11/**
2- * @fileoverview A class of the code path segment .
2+ * @fileoverview The CodePathSegment class .
33 * @author Toru Nagashima
44 */
55
@@ -30,10 +30,22 @@ function isReachable(segment) {
3030
3131/**
3232 * A code path segment.
33+ *
34+ * Each segment is arranged in a series of linked lists (implemented by arrays)
35+ * that keep track of the previous and next segments in a code path. In this way,
36+ * you can navigate between all segments in any code path so long as you have a
37+ * reference to any segment in that code path.
38+ *
39+ * When first created, the segment is in a detached state, meaning that it knows the
40+ * segments that came before it but those segments don't know that this new segment
41+ * follows it. Only when `CodePathSegment#markUsed()` is called on a segment does it
42+ * officially become part of the code path by updating the previous segments to know
43+ * that this new segment follows.
3344 */
3445class CodePathSegment {
3546
3647 /**
48+ * Creates a new instance.
3749 * @param {string } id An identifier.
3850 * @param {CodePathSegment[] } allPrevSegments An array of the previous segments.
3951 * This array includes unreachable segments.
@@ -49,27 +61,25 @@ class CodePathSegment {
4961 this . id = id ;
5062
5163 /**
52- * An array of the next segments.
64+ * An array of the next reachable segments.
5365 * @type {CodePathSegment[] }
5466 */
5567 this . nextSegments = [ ] ;
5668
5769 /**
58- * An array of the previous segments.
70+ * An array of the previous reachable segments.
5971 * @type {CodePathSegment[] }
6072 */
6173 this . prevSegments = allPrevSegments . filter ( isReachable ) ;
6274
6375 /**
64- * An array of the next segments.
65- * This array includes unreachable segments.
76+ * An array of all next segments including reachable and unreachable.
6677 * @type {CodePathSegment[] }
6778 */
6879 this . allNextSegments = [ ] ;
6980
7081 /**
71- * An array of the previous segments.
72- * This array includes unreachable segments.
82+ * An array of all previous segments including reachable and unreachable.
7383 * @type {CodePathSegment[] }
7484 */
7585 this . allPrevSegments = allPrevSegments ;
@@ -83,7 +93,11 @@ class CodePathSegment {
8393 // Internal data.
8494 Object . defineProperty ( this , "internal" , {
8595 value : {
96+
97+ // determines if the segment has been attached to the code path
8698 used : false ,
99+
100+ // array of previous segments coming from the end of a loop
87101 loopedPrevSegments : [ ]
88102 }
89103 } ) ;
@@ -113,9 +127,10 @@ class CodePathSegment {
113127 }
114128
115129 /**
116- * Creates a segment that follows given segments.
130+ * Creates a new segment and appends it after the given segments.
117131 * @param {string } id An identifier.
118- * @param {CodePathSegment[] } allPrevSegments An array of the previous segments.
132+ * @param {CodePathSegment[] } allPrevSegments An array of the previous segments
133+ * to append to.
119134 * @returns {CodePathSegment } The created segment.
120135 */
121136 static newNext ( id , allPrevSegments ) {
@@ -127,7 +142,7 @@ class CodePathSegment {
127142 }
128143
129144 /**
130- * Creates an unreachable segment that follows given segments.
145+ * Creates an unreachable segment and appends it after the given segments.
131146 * @param {string } id An identifier.
132147 * @param {CodePathSegment[] } allPrevSegments An array of the previous segments.
133148 * @returns {CodePathSegment } The created segment.
@@ -137,7 +152,7 @@ class CodePathSegment {
137152
138153 /*
139154 * In `if (a) return a; foo();` case, the unreachable segment preceded by
140- * the return statement is not used but must not be remove .
155+ * the return statement is not used but must not be removed .
141156 */
142157 CodePathSegment . markUsed ( segment ) ;
143158
@@ -157,7 +172,7 @@ class CodePathSegment {
157172 }
158173
159174 /**
160- * Makes a given segment being used.
175+ * Marks a given segment as used.
161176 *
162177 * And this function registers the segment into the previous segments as a next.
163178 * @param {CodePathSegment } segment A segment to mark.
@@ -172,13 +187,27 @@ class CodePathSegment {
172187 let i ;
173188
174189 if ( segment . reachable ) {
190+
191+ /*
192+ * If the segment is reachable, then it's officially part of the
193+ * code path. This loops through all previous segments to update
194+ * their list of next segments. Because the segment is reachable,
195+ * it's added to both `nextSegments` and `allNextSegments`.
196+ */
175197 for ( i = 0 ; i < segment . allPrevSegments . length ; ++ i ) {
176198 const prevSegment = segment . allPrevSegments [ i ] ;
177199
178200 prevSegment . allNextSegments . push ( segment ) ;
179201 prevSegment . nextSegments . push ( segment ) ;
180202 }
181203 } else {
204+
205+ /*
206+ * If the segment is not reachable, then it's not officially part of the
207+ * code path. This loops through all previous segments to update
208+ * their list of next segments. Because the segment is not reachable,
209+ * it's added only to `allNextSegments`.
210+ */
182211 for ( i = 0 ; i < segment . allPrevSegments . length ; ++ i ) {
183212 segment . allPrevSegments [ i ] . allNextSegments . push ( segment ) ;
184213 }
@@ -196,19 +225,20 @@ class CodePathSegment {
196225 }
197226
198227 /**
199- * Replaces unused segments with the previous segments of each unused segment.
200- * @param {CodePathSegment[] } segments An array of segments to replace.
201- * @returns {CodePathSegment[] } The replaced array.
228+ * Creates a new array based on an array of segments. If any segment in the
229+ * array is unused, then it is replaced by all of its previous segments.
230+ * All used segments are returned as-is without replacement.
231+ * @param {CodePathSegment[] } segments The array of segments to flatten.
232+ * @returns {CodePathSegment[] } The flattened array.
202233 */
203234 static flattenUnusedSegments ( segments ) {
204- const done = Object . create ( null ) ;
205- const retv = [ ] ;
235+ const done = new Set ( ) ;
206236
207237 for ( let i = 0 ; i < segments . length ; ++ i ) {
208238 const segment = segments [ i ] ;
209239
210240 // Ignores duplicated.
211- if ( done [ segment . id ] ) {
241+ if ( done . has ( segment ) ) {
212242 continue ;
213243 }
214244
@@ -217,18 +247,16 @@ class CodePathSegment {
217247 for ( let j = 0 ; j < segment . allPrevSegments . length ; ++ j ) {
218248 const prevSegment = segment . allPrevSegments [ j ] ;
219249
220- if ( ! done [ prevSegment . id ] ) {
221- done [ prevSegment . id ] = true ;
222- retv . push ( prevSegment ) ;
250+ if ( ! done . has ( prevSegment ) ) {
251+ done . add ( prevSegment ) ;
223252 }
224253 }
225254 } else {
226- done [ segment . id ] = true ;
227- retv . push ( segment ) ;
255+ done . add ( segment ) ;
228256 }
229257 }
230258
231- return retv ;
259+ return [ ... done ] ;
232260 }
233261}
234262
0 commit comments