Skip to content

Commit ab8c3fa

Browse files
committed
Pre-generate names ahead of time
1 parent ffc931c commit ab8c3fa

File tree

36 files changed

+3901
-3797
lines changed

36 files changed

+3901
-3797
lines changed

src/compiler/emitter.ts

Lines changed: 120 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,8 @@ namespace ts {
13781378
}
13791379

13801380
function emitObjectLiteralExpression(node: ObjectLiteralExpression) {
1381+
forEach(node.properties, generateMemberNames);
1382+
13811383
const indentedFlag = getEmitFlags(node) & EmitFlags.Indented;
13821384
if (indentedFlag) {
13831385
increaseIndent();
@@ -1481,6 +1483,7 @@ namespace ts {
14811483
}
14821484

14831485
function emitFunctionExpression(node: FunctionExpression) {
1486+
generateNameIfNeeded(node.name);
14841487
emitFunctionDeclarationOrExpression(node);
14851488
}
14861489

@@ -1606,6 +1609,7 @@ namespace ts {
16061609
}
16071610

16081611
function emitClassExpression(node: ClassExpression) {
1612+
generateNameIfNeeded(node.name);
16091613
emitClassDeclarationOrExpression(node);
16101614
}
16111615

@@ -1911,6 +1915,9 @@ namespace ts {
19111915
}
19121916

19131917
pushNameGenerationScope(node);
1918+
forEach(node.parameters, generateNames);
1919+
generateNames(node.body);
1920+
19141921
emitSignatureHead(node);
19151922
if (onEmitNode) {
19161923
onEmitNode(EmitHint.Unspecified, body, emitBlockCallback);
@@ -2025,6 +2032,8 @@ namespace ts {
20252032
}
20262033

20272034
function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) {
2035+
forEach(node.members, generateMemberNames);
2036+
20282037
emitDecorators(node, node.decorators);
20292038
emitModifiers(node, node.modifiers);
20302039
writeKeyword("class");
@@ -2113,6 +2122,7 @@ namespace ts {
21132122

21142123
function emitModuleBlock(node: ModuleBlock) {
21152124
pushNameGenerationScope(node);
2125+
forEach(node.statements, generateNames);
21162126
emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node));
21172127
popNameGenerationScope(node);
21182128
}
@@ -2516,6 +2526,7 @@ namespace ts {
25162526
function emitSourceFileWorker(node: SourceFile) {
25172527
const statements = node.statements;
25182528
pushNameGenerationScope(node);
2529+
forEach(node.statements, generateNames);
25192530
emitHelpers(node);
25202531
const index = findIndex(statements, statement => !isPrologueDirective(statement));
25212532
emitTripleSlashDirectivesIfNeeded(node);
@@ -3222,24 +3233,122 @@ namespace ts {
32223233
reservedNames.set(name, true);
32233234
}
32243235

3236+
function generateNames(node: Node | undefined) {
3237+
if (!node) return;
3238+
switch (node.kind) {
3239+
case SyntaxKind.Block:
3240+
forEach((<Block>node).statements, generateNames);
3241+
break;
3242+
case SyntaxKind.LabeledStatement:
3243+
case SyntaxKind.WithStatement:
3244+
case SyntaxKind.DoStatement:
3245+
case SyntaxKind.WhileStatement:
3246+
generateNames((<LabeledStatement | WithStatement | DoStatement | WhileStatement>node).statement);
3247+
break;
3248+
case SyntaxKind.IfStatement:
3249+
generateNames((<IfStatement>node).thenStatement);
3250+
generateNames((<IfStatement>node).elseStatement);
3251+
break;
3252+
case SyntaxKind.ForStatement:
3253+
case SyntaxKind.ForOfStatement:
3254+
case SyntaxKind.ForInStatement:
3255+
generateNames((<ForStatement | ForInOrOfStatement>node).initializer);
3256+
generateNames((<ForStatement | ForInOrOfStatement>node).statement);
3257+
break;
3258+
case SyntaxKind.SwitchStatement:
3259+
generateNames((<SwitchStatement>node).caseBlock);
3260+
break;
3261+
case SyntaxKind.CaseBlock:
3262+
forEach((<CaseBlock>node).clauses, generateNames);
3263+
break;
3264+
case SyntaxKind.CaseClause:
3265+
case SyntaxKind.DefaultClause:
3266+
forEach((<CaseOrDefaultClause>node).statements, generateNames);
3267+
break;
3268+
case SyntaxKind.TryStatement:
3269+
generateNames((<TryStatement>node).tryBlock);
3270+
generateNames((<TryStatement>node).catchClause);
3271+
generateNames((<TryStatement>node).finallyBlock);
3272+
break;
3273+
case SyntaxKind.CatchClause:
3274+
generateNames((<CatchClause>node).variableDeclaration);
3275+
generateNames((<CatchClause>node).block);
3276+
break;
3277+
case SyntaxKind.VariableStatement:
3278+
generateNames((<VariableStatement>node).declarationList);
3279+
break;
3280+
case SyntaxKind.VariableDeclarationList:
3281+
forEach((<VariableDeclarationList>node).declarations, generateNames);
3282+
break;
3283+
case SyntaxKind.VariableDeclaration:
3284+
case SyntaxKind.Parameter:
3285+
case SyntaxKind.BindingElement:
3286+
case SyntaxKind.ClassDeclaration:
3287+
generateNameIfNeeded((<NamedDeclaration>node).name);
3288+
break;
3289+
case SyntaxKind.FunctionDeclaration:
3290+
generateNameIfNeeded((<FunctionDeclaration>node).name);
3291+
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
3292+
forEach((<FunctionDeclaration>node).parameters, generateNames);
3293+
generateNames((<FunctionDeclaration>node).body);
3294+
}
3295+
break;
3296+
case SyntaxKind.ObjectBindingPattern:
3297+
case SyntaxKind.ArrayBindingPattern:
3298+
forEach((<BindingPattern>node).elements, generateNames);
3299+
break;
3300+
case SyntaxKind.ImportDeclaration:
3301+
generateNames((<ImportDeclaration>node).importClause);
3302+
break;
3303+
case SyntaxKind.ImportClause:
3304+
generateNameIfNeeded((<ImportClause>node).name);
3305+
generateNames((<ImportClause>node).namedBindings);
3306+
break;
3307+
case SyntaxKind.NamespaceImport:
3308+
generateNameIfNeeded((<NamespaceImport>node).name);
3309+
break;
3310+
case SyntaxKind.NamedImports:
3311+
forEach((<NamedImports>node).elements, generateNames);
3312+
break;
3313+
case SyntaxKind.ImportSpecifier:
3314+
generateNameIfNeeded((<ImportSpecifier>node).propertyName || (<ImportSpecifier>node).name);
3315+
break;
3316+
}
3317+
}
3318+
3319+
function generateMemberNames(node: Node | undefined) {
3320+
if (!node) return;
3321+
switch (node.kind) {
3322+
case SyntaxKind.PropertyAssignment:
3323+
case SyntaxKind.ShorthandPropertyAssignment:
3324+
case SyntaxKind.PropertyDeclaration:
3325+
case SyntaxKind.MethodDeclaration:
3326+
case SyntaxKind.GetAccessor:
3327+
case SyntaxKind.SetAccessor:
3328+
generateNameIfNeeded((<NamedDeclaration>node).name);
3329+
break;
3330+
}
3331+
}
3332+
3333+
function generateNameIfNeeded(name: DeclarationName | undefined) {
3334+
if (name) {
3335+
if (isGeneratedIdentifier(name)) {
3336+
generateName(name);
3337+
}
3338+
else if (isBindingPattern(name)) {
3339+
generateNames(name);
3340+
}
3341+
}
3342+
}
3343+
32253344
/**
32263345
* Generate the text for a generated identifier.
32273346
*/
32283347
function generateName(name: GeneratedIdentifier) {
32293348
if ((name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) {
32303349
// Node names generate unique names based on their original node
32313350
// and are cached based on that node's id.
3232-
if (name.autoGenerateFlags & GeneratedIdentifierFlags.SkipNameGenerationScope) {
3233-
const savedTempFlags = tempFlags;
3234-
popNameGenerationScope(/*node*/ undefined);
3235-
const result = generateNameCached(getNodeForGeneratedName(name));
3236-
pushNameGenerationScope(/*node*/ undefined);
3237-
tempFlags = savedTempFlags;
3238-
return result;
3239-
}
3240-
else {
3241-
return generateNameCached(getNodeForGeneratedName(name));
3242-
}
3351+
return generateNameCached(getNodeForGeneratedName(name));
32433352
}
32443353
else {
32453354
// Auto, Loop, and Unique names are cached based on their unique

src/compiler/factory.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,11 @@ namespace ts {
188188
}
189189

190190
/** Create a unique name generated for a node. */
191-
export function getGeneratedNameForNode(node: Node): Identifier;
192-
/* @internal */ export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier; // tslint:disable-line unified-signatures
193-
export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier {
191+
export function getGeneratedNameForNode(node: Node): Identifier {
194192
const name = createIdentifier("");
195193
name.autoGenerateFlags = GeneratedIdentifierFlags.Node;
196194
name.autoGenerateId = nextAutoGenerateId;
197195
name.original = node;
198-
if (shouldSkipNameGenerationScope) {
199-
name.autoGenerateFlags |= GeneratedIdentifierFlags.SkipNameGenerationScope;
200-
}
201196
nextAutoGenerateId++;
202197
return name;
203198
}

src/compiler/transformers/ts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ namespace ts {
12481248
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
12491249
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
12501250
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
1251-
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name, !hasModifier(property, ModifierFlags.Static)))
1251+
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
12521252
: property.name;
12531253
const initializer = visitNode(property.initializer, visitor, isExpression);
12541254
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);

src/compiler/types.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,9 @@ namespace ts {
710710
KindMask = 7, // Mask to extract the kind of identifier from its flags.
711711

712712
// Flags
713-
SkipNameGenerationScope = 1 << 3, // Should skip a name generation scope when generating the name for this identifier
714-
ReservedInNestedScopes = 1 << 4, // Reserve the generated name in nested scopes
715-
Optimistic = 1 << 5, // First instance won't use '_#' if there's no conflict
716-
FileLevel = 1 << 6, // Use only the file identifiers list and not generated names to search for conflicts
713+
ReservedInNestedScopes = 1 << 3, // Reserve the generated name in nested scopes
714+
Optimistic = 1 << 4, // First instance won't use '_#' if there's no conflict
715+
FileLevel = 1 << 5, // Use only the file identifiers list and not generated names to search for conflicts
717716
}
718717

719718
export interface Identifier extends PrimaryExpression, Declaration {

tests/baselines/reference/bindingPatternOmittedExpressionNesting.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ export let [,,[,[],,[],]] = undefined as any;
44
//// [bindingPatternOmittedExpressionNesting.js]
55
"use strict";
66
exports.__esModule = true;
7-
exports._a = (_b = undefined, _c = _b[2], _d = _c[1], _e = _c[3]);
8-
var _b, _c, _d, _e;
7+
exports._e = (_a = undefined, _b = _a[2], _c = _b[1], _d = _b[3]);
8+
var _a, _b, _c, _d;
99

1010

1111
//// [bindingPatternOmittedExpressionNesting.d.ts]

tests/baselines/reference/blockScopedBindingsReassignedInLoop3.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ var _loop_1 = function (x, y) {
9898
return out_x_1 = x, out_y_1 = y, "break";
9999
}
100100
else {
101-
var _loop_2 = function (a_1) {
101+
var _loop_5 = function (a_1) {
102102
var f = function () { return a_1; };
103103
if (a_1) {
104104
a_1 = x;
@@ -111,9 +111,9 @@ var _loop_1 = function (x, y) {
111111
};
112112
var out_a_1;
113113
for (var a_1 = 1; a_1 < 5; --a_1) {
114-
var state_1 = _loop_2(a_1);
114+
var state_4 = _loop_5(a_1);
115115
a_1 = out_a_1;
116-
if (state_1 === "break")
116+
if (state_4 === "break")
117117
break;
118118
}
119119
y = 5;
@@ -123,19 +123,19 @@ var _loop_1 = function (x, y) {
123123
};
124124
var out_x_1, out_y_1;
125125
for (var x = 1, y = 2; x < y; ++x, --y) {
126-
var state_2 = _loop_1(x, y);
126+
var state_1 = _loop_1(x, y);
127127
x = out_x_1;
128128
y = out_y_1;
129-
if (state_2 === "break")
129+
if (state_1 === "break")
130130
break;
131131
}
132-
var _loop_3 = function (x, y) {
132+
var _loop_2 = function (x, y) {
133133
var a = function () { return x++ + y++; };
134134
if (x == 1) {
135135
return out_x_2 = x, out_y_2 = y, "continue";
136136
}
137137
else {
138-
var _loop_4 = function (a_2) {
138+
var _loop_6 = function (a_2) {
139139
var f = function () { return a_2; };
140140
if (a_2) {
141141
a_2 = x;
@@ -148,7 +148,7 @@ var _loop_3 = function (x, y) {
148148
};
149149
var out_a_2;
150150
for (var a_2 = 1; a_2 < 5; --a_2) {
151-
_loop_4(a_2);
151+
_loop_6(a_2);
152152
a_2 = out_a_2;
153153
}
154154
y = 5;
@@ -158,17 +158,17 @@ var _loop_3 = function (x, y) {
158158
};
159159
var out_x_2, out_y_2;
160160
for (var x = 1, y = 2; x < y; ++x, --y) {
161-
_loop_3(x, y);
161+
_loop_2(x, y);
162162
x = out_x_2;
163163
y = out_y_2;
164164
}
165-
var _loop_5 = function (x, y) {
165+
var _loop_3 = function (x, y) {
166166
var a = function () { return x++ + y++; };
167167
if (x == 1) {
168168
return out_x_3 = x, out_y_3 = y, "break-loop2";
169169
}
170170
else {
171-
var _loop_6 = function (a_3) {
171+
var _loop_7 = function (a_3) {
172172
var f = function () { return a_3; };
173173
if (a_3) {
174174
a_3 = x;
@@ -182,11 +182,11 @@ var _loop_5 = function (x, y) {
182182
};
183183
var out_a_3;
184184
loop1: for (var a_3 = 1; a_3 < 5; --a_3) {
185-
var state_3 = _loop_6(a_3);
185+
var state_5 = _loop_7(a_3);
186186
a_3 = out_a_3;
187-
switch (state_3) {
187+
switch (state_5) {
188188
case "break-loop1": break loop1;
189-
case "break-loop2": return state_3;
189+
case "break-loop2": return state_5;
190190
}
191191
}
192192
y = 5;
@@ -196,14 +196,14 @@ var _loop_5 = function (x, y) {
196196
};
197197
var out_x_3, out_y_3;
198198
loop2: for (var x = 1, y = 2; x < y; ++x, --y) {
199-
var state_4 = _loop_5(x, y);
199+
var state_2 = _loop_3(x, y);
200200
x = out_x_3;
201201
y = out_y_3;
202-
switch (state_4) {
202+
switch (state_2) {
203203
case "break-loop2": break loop2;
204204
}
205205
}
206-
var _loop_7 = function (x, y) {
206+
var _loop_4 = function (x, y) {
207207
var a = function () { return x++ + y++; };
208208
if (x == 1) {
209209
return out_x_4 = x, out_y_4 = y, "continue-loop2";
@@ -223,11 +223,11 @@ var _loop_7 = function (x, y) {
223223
};
224224
var out_a_4;
225225
loop1: for (var a_4 = 1; a_4 < 5; --a_4) {
226-
var state_5 = _loop_8(a_4);
226+
var state_6 = _loop_8(a_4);
227227
a_4 = out_a_4;
228-
switch (state_5) {
228+
switch (state_6) {
229229
case "continue-loop1": continue loop1;
230-
case "continue-loop2": return state_5;
230+
case "continue-loop2": return state_6;
231231
}
232232
}
233233
y = 5;
@@ -237,10 +237,10 @@ var _loop_7 = function (x, y) {
237237
};
238238
var out_x_4, out_y_4;
239239
loop2: for (var x = 1, y = 2; x < y; ++x, --y) {
240-
var state_6 = _loop_7(x, y);
240+
var state_3 = _loop_4(x, y);
241241
x = out_x_4;
242242
y = out_y_4;
243-
switch (state_6) {
243+
switch (state_3) {
244244
case "continue-loop2": continue loop2;
245245
}
246246
}

0 commit comments

Comments
 (0)