@@ -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
}
@@ -2802,13 +2799,12 @@ namespace ts {
2802
2799
parseOptional ( operator ) ;
2803
2800
let type = parseConstituentType ( ) ;
2804
2801
if ( token ( ) === operator ) {
2805
- const types = createNodeArray < TypeNode > ( [ type ] , type . pos ) ;
2802
+ const types = [ type ] ;
2806
2803
while ( parseOptional ( operator ) ) {
2807
2804
types . push ( parseConstituentType ( ) ) ;
2808
2805
}
2809
- types . end = getNodeEnd ( ) ;
2810
2806
const node = < UnionOrIntersectionTypeNode > createNode ( kind , type . pos ) ;
2811
- node . types = types ;
2807
+ node . types = createNodeArray ( types , type . pos ) ;
2812
2808
type = finishNode ( node ) ;
2813
2809
}
2814
2810
return type ;
@@ -3174,8 +3170,7 @@ namespace ts {
3174
3170
parameter . name = identifier ;
3175
3171
finishNode ( parameter ) ;
3176
3172
3177
- node . parameters = createNodeArray < ParameterDeclaration > ( [ parameter ] , parameter . pos ) ;
3178
- node . parameters . end = parameter . end ;
3173
+ node . parameters = createNodeArray < ParameterDeclaration > ( [ parameter ] , parameter . pos , parameter . end ) ;
3179
3174
3180
3175
node . equalsGreaterThanToken = parseExpectedToken ( SyntaxKind . EqualsGreaterThanToken , /*reportAtCurrentPosition*/ false , Diagnostics . _0_expected , "=>" ) ;
3181
3176
node . body = parseArrowFunctionExpressionBody ( /*isAsync*/ ! ! asyncModifier ) ;
@@ -4025,7 +4020,8 @@ namespace ts {
4025
4020
}
4026
4021
4027
4022
function parseJsxChildren ( openingTagName : LeftHandSideExpression ) : NodeArray < JsxChild > {
4028
- const result = createNodeArray < JsxChild > ( ) ;
4023
+ const list = [ ] ;
4024
+ const listPos = getNodePos ( ) ;
4029
4025
const saveParsingContext = parsingContext ;
4030
4026
parsingContext |= 1 << ParsingContext . JsxChildren ;
4031
4027
@@ -4046,15 +4042,13 @@ namespace ts {
4046
4042
}
4047
4043
const child = parseJsxChild ( ) ;
4048
4044
if ( child ) {
4049
- result . push ( child ) ;
4045
+ list . push ( child ) ;
4050
4046
}
4051
4047
}
4052
4048
4053
- result . end = scanner . getTokenPos ( ) ;
4054
-
4055
4049
parsingContext = saveParsingContext ;
4056
4050
4057
- return result ;
4051
+ return createNodeArray ( list , listPos ) ;
4058
4052
}
4059
4053
4060
4054
function parseJsxAttributes ( ) : JsxAttributes {
@@ -5447,27 +5441,19 @@ namespace ts {
5447
5441
}
5448
5442
5449
5443
function parseDecorators ( ) : NodeArray < Decorator > {
5450
- let decorators : NodeArray < Decorator > & Decorator [ ] ;
5444
+ let list : Decorator [ ] ;
5445
+ const listPos = getNodePos ( ) ;
5451
5446
while ( true ) {
5452
5447
const decoratorStart = getNodePos ( ) ;
5453
5448
if ( ! parseOptional ( SyntaxKind . AtToken ) ) {
5454
5449
break ;
5455
5450
}
5456
-
5457
5451
const decorator = < Decorator > createNode ( SyntaxKind . Decorator , decoratorStart ) ;
5458
5452
decorator . expression = doInDecoratorContext ( parseLeftHandSideExpressionOrHigher ) ;
5459
5453
finishNode ( decorator ) ;
5460
- if ( ! decorators ) {
5461
- decorators = createNodeArray < Decorator > ( [ decorator ] , decoratorStart ) ;
5462
- }
5463
- else {
5464
- decorators . push ( decorator ) ;
5465
- }
5466
- }
5467
- if ( decorators ) {
5468
- decorators . end = getNodeEnd ( ) ;
5454
+ ( list || ( list = [ ] ) ) . push ( decorator ) ;
5469
5455
}
5470
- return decorators ;
5456
+ return list && createNodeArray ( list , listPos ) ;
5471
5457
}
5472
5458
5473
5459
/*
@@ -5478,7 +5464,8 @@ namespace ts {
5478
5464
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
5479
5465
*/
5480
5466
function parseModifiers ( permitInvalidConstAsModifier ?: boolean ) : NodeArray < Modifier > | undefined {
5481
- let modifiers : MutableNodeArray < Modifier > | undefined ;
5467
+ let list : Modifier [ ] ;
5468
+ const listPos = getNodePos ( ) ;
5482
5469
while ( true ) {
5483
5470
const modifierStart = scanner . getStartPos ( ) ;
5484
5471
const modifierKind = token ( ) ;
@@ -5497,17 +5484,9 @@ namespace ts {
5497
5484
}
5498
5485
5499
5486
const modifier = finishNode ( < Modifier > createNode ( modifierKind , modifierStart ) ) ;
5500
- if ( ! modifiers ) {
5501
- modifiers = createNodeArray < Modifier > ( [ modifier ] , modifierStart ) ;
5502
- }
5503
- else {
5504
- modifiers . push ( modifier ) ;
5505
- }
5506
- }
5507
- if ( modifiers ) {
5508
- modifiers . end = scanner . getStartPos ( ) ;
5487
+ ( list || ( list = [ ] ) ) . push ( modifier ) ;
5509
5488
}
5510
- return modifiers ;
5489
+ return list && createNodeArray ( list , listPos ) ;
5511
5490
}
5512
5491
5513
5492
function parseModifiersForArrowFunction ( ) : NodeArray < Modifier > {
@@ -5518,9 +5497,7 @@ namespace ts {
5518
5497
nextToken ( ) ;
5519
5498
const modifier = finishNode ( < Modifier > createNode ( modifierKind , modifierStart ) ) ;
5520
5499
modifiers = createNodeArray < Modifier > ( [ modifier ] , modifierStart ) ;
5521
- modifiers . end = scanner . getStartPos ( ) ;
5522
5500
}
5523
-
5524
5501
return modifiers ;
5525
5502
}
5526
5503
@@ -6222,7 +6199,9 @@ namespace ts {
6222
6199
Debug . assert ( start <= end ) ;
6223
6200
Debug . assert ( end <= content . length ) ;
6224
6201
6225
- let tags : MutableNodeArray < JSDocTag > ;
6202
+ let tags : JSDocTag [ ] ;
6203
+ let tagsPos : number ;
6204
+ let tagsEnd : number ;
6226
6205
const comments : string [ ] = [ ] ;
6227
6206
let result : JSDoc ;
6228
6207
@@ -6355,7 +6334,7 @@ namespace ts {
6355
6334
6356
6335
function createJSDocComment ( ) : JSDoc {
6357
6336
const result = < JSDoc > createNode ( SyntaxKind . JSDocComment , start ) ;
6358
- result . tags = tags ;
6337
+ result . tags = tags && createNodeArray ( tags , tagsPos , tagsEnd ) ;
6359
6338
result . comment = comments . length ? comments . join ( "" ) : undefined ;
6360
6339
return finishNode ( result , end ) ;
6361
6340
}
@@ -6495,12 +6474,13 @@ namespace ts {
6495
6474
tag . comment = comments . join ( "" ) ;
6496
6475
6497
6476
if ( ! tags ) {
6498
- tags = createNodeArray ( [ tag ] , tag . pos ) ;
6477
+ tags = [ tag ] ;
6478
+ tagsPos = tag . pos ;
6499
6479
}
6500
6480
else {
6501
6481
tags . push ( tag ) ;
6502
6482
}
6503
- tags . end = tag . end ;
6483
+ tagsEnd = tag . end ;
6504
6484
}
6505
6485
6506
6486
function tryParseTypeExpression ( ) : JSDocTypeExpression | undefined {
@@ -6800,7 +6780,8 @@ namespace ts {
6800
6780
}
6801
6781
6802
6782
// Type parameter list looks like '@template T,U,V'
6803
- const typeParameters = createNodeArray < TypeParameterDeclaration > ( ) ;
6783
+ const typeParameters = [ ] ;
6784
+ const typeParametersPos = getNodePos ( ) ;
6804
6785
6805
6786
while ( true ) {
6806
6787
const name = parseJSDocIdentifierName ( ) ;
@@ -6828,9 +6809,8 @@ namespace ts {
6828
6809
const result = < JSDocTemplateTag > createNode ( SyntaxKind . JSDocTemplateTag , atToken . pos ) ;
6829
6810
result . atToken = atToken ;
6830
6811
result . tagName = tagName ;
6831
- result . typeParameters = typeParameters ;
6812
+ result . typeParameters = createNodeArray ( typeParameters , typeParametersPos ) ;
6832
6813
finishNode ( result ) ;
6833
- typeParameters . end = result . end ;
6834
6814
return result ;
6835
6815
}
6836
6816
0 commit comments