@@ -3892,17 +3892,41 @@ namespace ts {
3892
3892
*
3893
3893
* @param elements The array of Expression nodes.
3894
3894
* @param needsUniqueCopy A value indicating whether to ensure that the result is a fresh array.
3895
+ * This should be `true` when spreading into an `ArrayLiteral`, and `false` when spreading into an
3896
+ * argument list.
3895
3897
* @param multiLine A value indicating whether the result should be emitted on multiple lines.
3896
3898
*/
3897
3899
function transformAndSpreadElements ( elements : NodeArray < Expression > , needsUniqueCopy : boolean , multiLine : boolean , hasTrailingComma : boolean ) : Expression {
3900
+ // When there is no leading SpreadElement:
3901
+ //
3898
3902
// [source]
3899
3903
// [a, ...b, c]
3900
3904
//
3901
3905
// [output (downlevelIteration)]
3902
- // __spread( [a], b , [c])
3906
+ // __spreadArray(__spreadArray( [a], __read(b)) , [c])
3903
3907
//
3904
3908
// [output]
3905
- // __spreadArrays([a], b, [c])
3909
+ // __spreadArray(__spreadArray([a], b), [c])
3910
+ //
3911
+ // When there *is* a leading SpreadElement:
3912
+ //
3913
+ // [source]
3914
+ // [...a, b]
3915
+ //
3916
+ // [output (downlevelIteration)]
3917
+ // __spreadArray(__spreadArray([], __read(a)), [b])
3918
+ //
3919
+ // [output]
3920
+ // __spreadArray(__spreadArray([], a), [b])
3921
+ //
3922
+ // NOTE: We use `isPackedArrayLiteral` below rather than just `isArrayLiteral`
3923
+ // because ES2015 spread will replace _missing_ array elements with `undefined`,
3924
+ // so we cannot just use an array as is. For example:
3925
+ //
3926
+ // `[1, ...[2, , 3]]` becomes `[1, 2, undefined, 3]`
3927
+ //
3928
+ // However, for packed array literals (i.e., an array literal with no OmittedExpression
3929
+ // elements), we can use the array as-is.
3906
3930
3907
3931
// Map spans of spread expressions into their expressions and spans of other
3908
3932
// expressions into an array literal.
@@ -3913,43 +3937,33 @@ namespace ts {
3913
3937
)
3914
3938
) ;
3915
3939
3916
- if ( compilerOptions . downlevelIteration ) {
3917
- if ( segments . length === 1 ) {
3918
- const firstSegment = segments [ 0 ] ;
3919
- if ( isCallToHelper ( firstSegment , "___spread" as __String ) ) {
3920
- return segments [ 0 ] ;
3921
- }
3940
+ if ( segments . length === 1 ) {
3941
+ const firstSegment = segments [ 0 ] ;
3942
+ // If we don't need a unique copy, then we are spreading into an argument list for
3943
+ // a CallExpression or NewExpression. When using `--downlevelIteration`, we need
3944
+ // to coerce this into an array for use with `apply`, so we will use the code path
3945
+ // that follows instead.
3946
+ if ( ! needsUniqueCopy && ! compilerOptions . downlevelIteration
3947
+ || isPackedArrayLiteral ( firstSegment ) // see NOTE (above)
3948
+ || isCallToHelper ( firstSegment , "___spreadArray" as __String ) ) {
3949
+ return segments [ 0 ] ;
3922
3950
}
3923
-
3924
- return emitHelpers ( ) . createSpreadHelper ( segments ) ;
3925
3951
}
3926
- else {
3927
- if ( segments . length === 1 ) {
3928
- const firstSegment = segments [ 0 ] ;
3929
- if ( ! needsUniqueCopy
3930
- || isPackedArrayLiteral ( firstSegment )
3931
- || isCallToHelper ( firstSegment , "___spreadArrays" as __String ) ) {
3932
- return segments [ 0 ] ;
3933
- }
3934
- }
3935
3952
3936
- return emitHelpers ( ) . createSpreadArraysHelper ( segments ) ;
3953
+ const helpers = emitHelpers ( ) ;
3954
+ const startsWithSpread = isSpreadElement ( elements [ 0 ] ) ;
3955
+ let expression : Expression =
3956
+ startsWithSpread ? factory . createArrayLiteralExpression ( ) :
3957
+ segments [ 0 ] ;
3958
+ for ( let i = startsWithSpread ? 0 : 1 ; i < segments . length ; i ++ ) {
3959
+ expression = helpers . createSpreadArrayHelper (
3960
+ expression ,
3961
+ compilerOptions . downlevelIteration && ! isPackedArrayLiteral ( segments [ i ] ) ? // see NOTE (above)
3962
+ helpers . createReadHelper ( segments [ i ] , /*count*/ undefined ) :
3963
+ segments [ i ] ) ;
3937
3964
}
3938
- }
3939
3965
3940
- function isPackedElement ( node : Expression ) {
3941
- return ! isOmittedExpression ( node ) ;
3942
- }
3943
-
3944
- function isPackedArrayLiteral ( node : Expression ) {
3945
- return isArrayLiteralExpression ( node ) && every ( node . elements , isPackedElement ) ;
3946
- }
3947
-
3948
- function isCallToHelper ( firstSegment : Expression , helperName : __String ) {
3949
- return isCallExpression ( firstSegment )
3950
- && isIdentifier ( firstSegment . expression )
3951
- && ( getEmitFlags ( firstSegment . expression ) & EmitFlags . HelperName )
3952
- && firstSegment . expression . escapedText === helperName ;
3966
+ return expression ;
3953
3967
}
3954
3968
3955
3969
function partitionSpread ( node : Expression ) {
0 commit comments