@@ -940,10 +940,6 @@ namespace ts {
940
940
return scanner . getStartPos ( ) ;
941
941
}
942
942
943
- function getNodeEnd ( ) : number {
944
- return scanner . getStartPos ( ) ;
945
- }
946
-
947
943
// Use this function to access the current token instead of reading the currentToken
948
944
// variable. Since function results aren't narrowed in control flow analysis, this ensures
949
945
// that the type checker doesn't make wrong assumptions about the type of the current
@@ -1135,13 +1131,14 @@ namespace ts {
1135
1131
new TokenConstructor ( kind , pos , pos ) ;
1136
1132
}
1137
1133
1138
- function createNodeArray < T extends Node > ( elements ?: T [ ] , pos ?: number ) : MutableNodeArray < T > {
1139
- const array = < MutableNodeArray < T > > ( elements || [ ] ) ;
1140
- if ( ! ( pos >= 0 ) ) {
1141
- pos = getNodePos ( ) ;
1142
- }
1134
+ function createNodeArray < T extends Node > ( elements : T [ ] , pos : number , end ?: number ) : NodeArray < T > {
1135
+ // Since the element list of a node array is typically created by starting with an empty array and
1136
+ // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for
1137
+ // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation.
1138
+ const length = elements . length ;
1139
+ const array = < MutableNodeArray < T > > ( length >= 1 && length <= 4 ? elements . slice ( ) : elements ) ;
1143
1140
array . pos = pos ;
1144
- array . end = pos ;
1141
+ array . end = end === undefined ? scanner . getStartPos ( ) : end ;
1145
1142
return array ;
1146
1143
}
1147
1144
@@ -1527,12 +1524,13 @@ namespace ts {
1527
1524
function parseList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T ) : NodeArray < T > {
1528
1525
const saveParsingContext = parsingContext ;
1529
1526
parsingContext |= 1 << kind ;
1530
- const result = createNodeArray < T > ( ) ;
1527
+ const list = [ ] ;
1528
+ const listPos = getNodePos ( ) ;
1531
1529
1532
1530
while ( ! isListTerminator ( kind ) ) {
1533
1531
if ( isListElement ( kind , /*inErrorRecovery*/ false ) ) {
1534
1532
const element = parseListElement ( kind , parseElement ) ;
1535
- result . push ( element ) ;
1533
+ list . push ( element ) ;
1536
1534
1537
1535
continue ;
1538
1536
}
@@ -1542,9 +1540,8 @@ namespace ts {
1542
1540
}
1543
1541
}
1544
1542
1545
- result . end = getNodeEnd ( ) ;
1546
1543
parsingContext = saveParsingContext ;
1547
- return result ;
1544
+ return createNodeArray ( list , listPos ) ;
1548
1545
}
1549
1546
1550
1547
function parseListElement < T extends Node > ( parsingContext : ParsingContext , parseElement : ( ) => T ) : T {
@@ -1874,13 +1871,14 @@ namespace ts {
1874
1871
function parseDelimitedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , considerSemicolonAsDelimiter ?: boolean ) : NodeArray < T > {
1875
1872
const saveParsingContext = parsingContext ;
1876
1873
parsingContext |= 1 << kind ;
1877
- const result = createNodeArray < T > ( ) ;
1874
+ const list = [ ] ;
1875
+ const listPos = getNodePos ( ) ;
1878
1876
1879
1877
let commaStart = - 1 ; // Meaning the previous token was not a comma
1880
1878
while ( true ) {
1881
1879
if ( isListElement ( kind , /*inErrorRecovery*/ false ) ) {
1882
1880
const startPos = scanner . getStartPos ( ) ;
1883
- result . push ( parseListElement ( kind , parseElement ) ) ;
1881
+ list . push ( parseListElement ( kind , parseElement ) ) ;
1884
1882
commaStart = scanner . getTokenPos ( ) ;
1885
1883
1886
1884
if ( parseOptional ( SyntaxKind . CommaToken ) ) {
@@ -1924,6 +1922,8 @@ namespace ts {
1924
1922
}
1925
1923
}
1926
1924
1925
+ parsingContext = saveParsingContext ;
1926
+ const result = createNodeArray ( list , listPos ) ;
1927
1927
// Recording the trailing comma is deliberately done after the previous
1928
1928
// loop, and not just if we see a list terminator. This is because the list
1929
1929
// may have ended incorrectly, but it is still important to know if there
@@ -1933,14 +1933,11 @@ namespace ts {
1933
1933
// Always preserve a trailing comma by marking it on the NodeArray
1934
1934
result . hasTrailingComma = true ;
1935
1935
}
1936
-
1937
- result . end = getNodeEnd ( ) ;
1938
- parsingContext = saveParsingContext ;
1939
1936
return result ;
1940
1937
}
1941
1938
1942
1939
function createMissingList < T extends Node > ( ) : NodeArray < T > {
1943
- return createNodeArray < T > ( ) ;
1940
+ return createNodeArray < T > ( [ ] , getNodePos ( ) ) ;
1944
1941
}
1945
1942
1946
1943
function parseBracketedList < T extends Node > ( kind : ParsingContext , parseElement : ( ) => T , open : SyntaxKind , close : SyntaxKind ) : NodeArray < T > {
@@ -2015,15 +2012,15 @@ namespace ts {
2015
2012
template . head = parseTemplateHead ( ) ;
2016
2013
Debug . assert ( template . head . kind === SyntaxKind . TemplateHead , "Template head has wrong token kind" ) ;
2017
2014
2018
- const templateSpans = createNodeArray < TemplateSpan > ( ) ;
2015
+ const list = [ ] ;
2016
+ const listPos = getNodePos ( ) ;
2019
2017
2020
2018
do {
2021
- templateSpans . push ( parseTemplateSpan ( ) ) ;
2019
+ list . push ( parseTemplateSpan ( ) ) ;
2022
2020
}
2023
- while ( lastOrUndefined ( templateSpans ) . literal . kind === SyntaxKind . TemplateMiddle ) ;
2021
+ while ( lastOrUndefined ( list ) . literal . kind === SyntaxKind . TemplateMiddle ) ;
2024
2022
2025
- templateSpans . end = getNodeEnd ( ) ;
2026
- template . templateSpans = templateSpans ;
2023
+ template . templateSpans = createNodeArray ( list , listPos ) ;
2027
2024
2028
2025
return finishNode ( template ) ;
2029
2026
}
@@ -2807,13 +2804,12 @@ namespace ts {
2807
2804
parseOptional ( operator ) ;
2808
2805
let type = parseConstituentType ( ) ;
2809
2806
if ( token ( ) === operator ) {
2810
- const types = createNodeArray < TypeNode > ( [ type ] , type . pos ) ;
2807
+ const types = [ type ] ;
2811
2808
while ( parseOptional ( operator ) ) {
2812
2809
types . push ( parseConstituentType ( ) ) ;
2813
2810
}
2814
- types . end = getNodeEnd ( ) ;
2815
2811
const node = < UnionOrIntersectionTypeNode > createNode ( kind , type . pos ) ;
2816
- node . types = types ;
2812
+ node . types = createNodeArray ( types , type . pos ) ;
2817
2813
type = finishNode ( node ) ;
2818
2814
}
2819
2815
return type ;
@@ -3179,8 +3175,7 @@ namespace ts {
3179
3175
parameter . name = identifier ;
3180
3176
finishNode ( parameter ) ;
3181
3177
3182
- node . parameters = createNodeArray < ParameterDeclaration > ( [ parameter ] , parameter . pos ) ;
3183
- node . parameters . end = parameter . end ;
3178
+ node . parameters = createNodeArray < ParameterDeclaration > ( [ parameter ] , parameter . pos , parameter . end ) ;
3184
3179
3185
3180
node . equalsGreaterThanToken = parseExpectedToken ( SyntaxKind . EqualsGreaterThanToken , /*reportAtCurrentPosition*/ false , Diagnostics . _0_expected , "=>" ) ;
3186
3181
node . body = parseArrowFunctionExpressionBody ( /*isAsync*/ ! ! asyncModifier ) ;
@@ -4030,7 +4025,8 @@ namespace ts {
4030
4025
}
4031
4026
4032
4027
function parseJsxChildren ( openingTagName : LeftHandSideExpression ) : NodeArray < JsxChild > {
4033
- const result = createNodeArray < JsxChild > ( ) ;
4028
+ const list = [ ] ;
4029
+ const listPos = getNodePos ( ) ;
4034
4030
const saveParsingContext = parsingContext ;
4035
4031
parsingContext |= 1 << ParsingContext . JsxChildren ;
4036
4032
@@ -4051,15 +4047,13 @@ namespace ts {
4051
4047
}
4052
4048
const child = parseJsxChild ( ) ;
4053
4049
if ( child ) {
4054
- result . push ( child ) ;
4050
+ list . push ( child ) ;
4055
4051
}
4056
4052
}
4057
4053
4058
- result . end = scanner . getTokenPos ( ) ;
4059
-
4060
4054
parsingContext = saveParsingContext ;
4061
4055
4062
- return result ;
4056
+ return createNodeArray ( list , listPos ) ;
4063
4057
}
4064
4058
4065
4059
function parseJsxAttributes ( ) : JsxAttributes {
@@ -5452,27 +5446,19 @@ namespace ts {
5452
5446
}
5453
5447
5454
5448
function parseDecorators ( ) : NodeArray < Decorator > {
5455
- let decorators : NodeArray < Decorator > & Decorator [ ] ;
5449
+ let list : Decorator [ ] ;
5450
+ const listPos = getNodePos ( ) ;
5456
5451
while ( true ) {
5457
5452
const decoratorStart = getNodePos ( ) ;
5458
5453
if ( ! parseOptional ( SyntaxKind . AtToken ) ) {
5459
5454
break ;
5460
5455
}
5461
-
5462
5456
const decorator = < Decorator > createNode ( SyntaxKind . Decorator , decoratorStart ) ;
5463
5457
decorator . expression = doInDecoratorContext ( parseLeftHandSideExpressionOrHigher ) ;
5464
5458
finishNode ( decorator ) ;
5465
- if ( ! decorators ) {
5466
- decorators = createNodeArray < Decorator > ( [ decorator ] , decoratorStart ) ;
5467
- }
5468
- else {
5469
- decorators . push ( decorator ) ;
5470
- }
5471
- }
5472
- if ( decorators ) {
5473
- decorators . end = getNodeEnd ( ) ;
5459
+ ( list || ( list = [ ] ) ) . push ( decorator ) ;
5474
5460
}
5475
- return decorators ;
5461
+ return list && createNodeArray ( list , listPos ) ;
5476
5462
}
5477
5463
5478
5464
/*
@@ -5483,7 +5469,8 @@ namespace ts {
5483
5469
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
5484
5470
*/
5485
5471
function parseModifiers ( permitInvalidConstAsModifier ?: boolean ) : NodeArray < Modifier > | undefined {
5486
- let modifiers : MutableNodeArray < Modifier > | undefined ;
5472
+ let list : Modifier [ ] ;
5473
+ const listPos = getNodePos ( ) ;
5487
5474
while ( true ) {
5488
5475
const modifierStart = scanner . getStartPos ( ) ;
5489
5476
const modifierKind = token ( ) ;
@@ -5502,17 +5489,9 @@ namespace ts {
5502
5489
}
5503
5490
5504
5491
const modifier = finishNode ( < Modifier > createNode ( modifierKind , modifierStart ) ) ;
5505
- if ( ! modifiers ) {
5506
- modifiers = createNodeArray < Modifier > ( [ modifier ] , modifierStart ) ;
5507
- }
5508
- else {
5509
- modifiers . push ( modifier ) ;
5510
- }
5511
- }
5512
- if ( modifiers ) {
5513
- modifiers . end = scanner . getStartPos ( ) ;
5492
+ ( list || ( list = [ ] ) ) . push ( modifier ) ;
5514
5493
}
5515
- return modifiers ;
5494
+ return list && createNodeArray ( list , listPos ) ;
5516
5495
}
5517
5496
5518
5497
function parseModifiersForArrowFunction ( ) : NodeArray < Modifier > {
@@ -5523,9 +5502,7 @@ namespace ts {
5523
5502
nextToken ( ) ;
5524
5503
const modifier = finishNode ( < Modifier > createNode ( modifierKind , modifierStart ) ) ;
5525
5504
modifiers = createNodeArray < Modifier > ( [ modifier ] , modifierStart ) ;
5526
- modifiers . end = scanner . getStartPos ( ) ;
5527
5505
}
5528
-
5529
5506
return modifiers ;
5530
5507
}
5531
5508
@@ -6227,7 +6204,9 @@ namespace ts {
6227
6204
Debug . assert ( start <= end ) ;
6228
6205
Debug . assert ( end <= content . length ) ;
6229
6206
6230
- let tags : MutableNodeArray < JSDocTag > ;
6207
+ let tags : JSDocTag [ ] ;
6208
+ let tagsPos : number ;
6209
+ let tagsEnd : number ;
6231
6210
const comments : string [ ] = [ ] ;
6232
6211
let result : JSDoc ;
6233
6212
@@ -6360,7 +6339,7 @@ namespace ts {
6360
6339
6361
6340
function createJSDocComment ( ) : JSDoc {
6362
6341
const result = < JSDoc > createNode ( SyntaxKind . JSDocComment , start ) ;
6363
- result . tags = tags ;
6342
+ result . tags = tags && createNodeArray ( tags , tagsPos , tagsEnd ) ;
6364
6343
result . comment = comments . length ? comments . join ( "" ) : undefined ;
6365
6344
return finishNode ( result , end ) ;
6366
6345
}
@@ -6500,12 +6479,13 @@ namespace ts {
6500
6479
tag . comment = comments . join ( "" ) ;
6501
6480
6502
6481
if ( ! tags ) {
6503
- tags = createNodeArray ( [ tag ] , tag . pos ) ;
6482
+ tags = [ tag ] ;
6483
+ tagsPos = tag . pos ;
6504
6484
}
6505
6485
else {
6506
6486
tags . push ( tag ) ;
6507
6487
}
6508
- tags . end = tag . end ;
6488
+ tagsEnd = tag . end ;
6509
6489
}
6510
6490
6511
6491
function tryParseTypeExpression ( ) : JSDocTypeExpression | undefined {
@@ -6805,7 +6785,8 @@ namespace ts {
6805
6785
}
6806
6786
6807
6787
// Type parameter list looks like '@template T,U,V'
6808
- const typeParameters = createNodeArray < TypeParameterDeclaration > ( ) ;
6788
+ const typeParameters = [ ] ;
6789
+ const typeParametersPos = getNodePos ( ) ;
6809
6790
6810
6791
while ( true ) {
6811
6792
const name = parseJSDocIdentifierName ( ) ;
@@ -6833,9 +6814,8 @@ namespace ts {
6833
6814
const result = < JSDocTemplateTag > createNode ( SyntaxKind . JSDocTemplateTag , atToken . pos ) ;
6834
6815
result . atToken = atToken ;
6835
6816
result . tagName = tagName ;
6836
- result . typeParameters = typeParameters ;
6817
+ result . typeParameters = createNodeArray ( typeParameters , typeParametersPos ) ;
6837
6818
finishNode ( result ) ;
6838
- typeParameters . end = result . end ;
6839
6819
return result ;
6840
6820
}
6841
6821
0 commit comments