@@ -171,23 +171,116 @@ namespace ts {
171171 return result ;
172172 }
173173
174+ /**
175+ * Flattens an array containing a mix of array or non-array elements.
176+ *
177+ * @param array The array to flatten.
178+ */
179+ export function flatten < T > ( array : ( T | T [ ] ) [ ] ) : T [ ] {
180+ let result : T [ ] ;
181+ if ( array ) {
182+ result = [ ] ;
183+ for ( const v of array ) {
184+ if ( v ) {
185+ if ( isArray ( v ) ) {
186+ addRange ( result , v ) ;
187+ }
188+ else {
189+ result . push ( v ) ;
190+ }
191+ }
192+ }
193+ }
194+
195+ return result ;
196+ }
197+
174198 /**
175199 * Maps an array. If the mapped value is an array, it is spread into the result.
200+ *
201+ * @param array The array to map.
202+ * @param mapfn The callback used to map the result into one or more values.
176203 */
177- export function flatMap < T , U > ( array : T [ ] , f : ( x : T , i : number ) => U | U [ ] ) : U [ ] {
204+ export function flatMap < T , U > ( array : T [ ] , mapfn : ( x : T , i : number ) => U | U [ ] ) : U [ ] {
178205 let result : U [ ] ;
179206 if ( array ) {
180207 result = [ ] ;
181208 for ( let i = 0 ; i < array . length ; i ++ ) {
182- const v = array [ i ] ;
183- const ar = f ( v , i ) ;
184- if ( ar ) {
185- // We cast to <U> here to leverage the behavior of Array#concat
186- // which will append a single value here.
187- result = result . concat ( < U [ ] > ar ) ;
209+ const v = mapfn ( array [ i ] , i ) ;
210+ if ( v ) {
211+ if ( isArray ( v ) ) {
212+ addRange ( result , v ) ;
213+ }
214+ else {
215+ result . push ( v ) ;
216+ }
217+ }
218+ }
219+ }
220+ return result ;
221+ }
222+
223+ /**
224+ * Computes the first matching span of elements and returns a tuple of the first span
225+ * and the remaining elements.
226+ */
227+ export function span < T > ( array : T [ ] , f : ( x : T , i : number ) => boolean ) : [ T [ ] , T [ ] ] {
228+ if ( array ) {
229+ for ( let i = 0 ; i < array . length ; i ++ ) {
230+ if ( ! f ( array [ i ] , i ) ) {
231+ return [ array . slice ( 0 , i ) , array . slice ( i ) ] ;
232+ }
233+ }
234+ return [ array . slice ( 0 ) , [ ] ] ;
235+ }
236+
237+ return undefined ;
238+ }
239+
240+ /**
241+ * Maps contiguous spans of values with the same key.
242+ *
243+ * @param array The array to map.
244+ * @param keyfn A callback used to select the key for an element.
245+ * @param mapfn A callback used to map a contiguous chunk of values to a single value.
246+ */
247+ export function spanMap < T , K , U > ( array : T [ ] , keyfn : ( x : T , i : number ) => K , mapfn : ( chunk : T [ ] , key : K ) => U ) : U [ ] {
248+ let result : U [ ] ;
249+ if ( array ) {
250+ result = [ ] ;
251+ const len = array . length ;
252+ let previousKey : K ;
253+ let key : K ;
254+ let start = 0 ;
255+ let pos = 0 ;
256+ while ( start < len ) {
257+ while ( pos < len ) {
258+ const value = array [ pos ] ;
259+ key = keyfn ( value , pos ) ;
260+ if ( pos === 0 ) {
261+ previousKey = key ;
262+ }
263+ else if ( key !== previousKey ) {
264+ break ;
265+ }
266+
267+ pos ++ ;
188268 }
269+
270+ if ( start < pos ) {
271+ const v = mapfn ( array . slice ( start , pos ) , previousKey ) ;
272+ if ( v ) {
273+ result . push ( v ) ;
274+ }
275+
276+ start = pos ;
277+ }
278+
279+ previousKey = key ;
280+ pos ++ ;
189281 }
190282 }
283+
191284 return result ;
192285 }
193286
@@ -920,8 +1013,9 @@ namespace ts {
9201013 this . pos = pos ;
9211014 this . end = end ;
9221015 this . flags = NodeFlags . None ;
923- this . transformFlags = undefined ;
924- this . excludeTransformFlags = undefined ;
1016+ this . modifierFlagsCache = ModifierFlags . None ;
1017+ this . transformFlags = TransformFlags . None ;
1018+ this . excludeTransformFlags = TransformFlags . None ;
9251019 this . parent = undefined ;
9261020 this . original = undefined ;
9271021 }
@@ -942,7 +1036,12 @@ namespace ts {
9421036 }
9431037
9441038 export namespace Debug {
945- const currentAssertionLevel = AssertionLevel . None ;
1039+ declare var process : any ;
1040+ declare var require : any ;
1041+
1042+ const currentAssertionLevel = getDevelopmentMode ( ) === "development"
1043+ ? AssertionLevel . Normal
1044+ : AssertionLevel . None ;
9461045
9471046 export function shouldAssert ( level : AssertionLevel ) : boolean {
9481047 return currentAssertionLevel >= level ;
@@ -962,6 +1061,17 @@ namespace ts {
9621061 export function fail ( message ?: string ) : void {
9631062 Debug . assert ( /*expression*/ false , message ) ;
9641063 }
1064+
1065+ function getDevelopmentMode ( ) {
1066+ return typeof require !== "undefined"
1067+ && typeof process !== "undefined"
1068+ && ! process . browser
1069+ && process . nextTick
1070+ && process . env
1071+ && process . env . NODE_ENV
1072+ ? String ( process . env . NODE_ENV ) . toLowerCase ( )
1073+ : undefined ;
1074+ }
9651075 }
9661076
9671077 export function copyListRemovingItem < T > ( item : T , list : T [ ] ) {
0 commit comments