@@ -26,84 +26,6 @@ namespace ts {
26
26
EmitNotifications = 1 << 1 ,
27
27
}
28
28
29
- export interface TransformationResult {
30
- /**
31
- * Gets the transformed source files.
32
- */
33
- transformed : SourceFile [ ] ;
34
-
35
- /**
36
- * Emits the substitute for a node, if one is available; otherwise, emits the node.
37
- *
38
- * @param emitContext The current emit context.
39
- * @param node The node to substitute.
40
- * @param emitCallback A callback used to emit the node or its substitute.
41
- */
42
- emitNodeWithSubstitution ( emitContext : EmitContext , node : Node , emitCallback : ( emitContext : EmitContext , node : Node ) => void ) : void ;
43
-
44
- /**
45
- * Emits a node with possible notification.
46
- *
47
- * @param emitContext The current emit context.
48
- * @param node The node to emit.
49
- * @param emitCallback A callback used to emit the node.
50
- */
51
- emitNodeWithNotification ( emitContext : EmitContext , node : Node , emitCallback : ( emitContext : EmitContext , node : Node ) => void ) : void ;
52
- }
53
-
54
- export interface TransformationContext extends LexicalEnvironment {
55
- getCompilerOptions ( ) : CompilerOptions ;
56
- getEmitResolver ( ) : EmitResolver ;
57
- getEmitHost ( ) : EmitHost ;
58
-
59
- /**
60
- * Hoists a function declaration to the containing scope.
61
- */
62
- hoistFunctionDeclaration ( node : FunctionDeclaration ) : void ;
63
-
64
- /**
65
- * Hoists a variable declaration to the containing scope.
66
- */
67
- hoistVariableDeclaration ( node : Identifier ) : void ;
68
-
69
- /**
70
- * Enables expression substitutions in the pretty printer for the provided SyntaxKind.
71
- */
72
- enableSubstitution ( kind : SyntaxKind ) : void ;
73
-
74
- /**
75
- * Determines whether expression substitutions are enabled for the provided node.
76
- */
77
- isSubstitutionEnabled ( node : Node ) : boolean ;
78
-
79
- /**
80
- * Hook used by transformers to substitute expressions just before they
81
- * are emitted by the pretty printer.
82
- */
83
- onSubstituteNode ?: ( emitContext : EmitContext , node : Node ) => Node ;
84
-
85
- /**
86
- * Enables before/after emit notifications in the pretty printer for the provided
87
- * SyntaxKind.
88
- */
89
- enableEmitNotification ( kind : SyntaxKind ) : void ;
90
-
91
- /**
92
- * Determines whether before/after emit notifications should be raised in the pretty
93
- * printer when it emits a node.
94
- */
95
- isEmitNotificationEnabled ( node : Node ) : boolean ;
96
-
97
- /**
98
- * Hook used to allow transformers to capture state before or after
99
- * the printer emits a node.
100
- */
101
- onEmitNode ?: ( emitContext : EmitContext , node : Node , emitCallback : ( emitContext : EmitContext , node : Node ) => void ) => void ;
102
- }
103
-
104
- /* @internal */
105
- export type Transformer = ( context : TransformationContext ) => ( node : SourceFile ) => SourceFile ;
106
-
107
29
export function getTransformers ( compilerOptions : CompilerOptions ) {
108
30
const jsx = compilerOptions . jsx ;
109
31
const languageVersion = getEmitScriptTarget ( compilerOptions ) ;
@@ -149,25 +71,33 @@ namespace ts {
149
71
* @param transforms An array of Transformers.
150
72
*/
151
73
export function transformFiles ( resolver : EmitResolver , host : EmitHost , sourceFiles : SourceFile [ ] , transformers : Transformer [ ] ) : TransformationResult {
152
- const lexicalEnvironmentVariableDeclarationsStack : VariableDeclaration [ ] [ ] = [ ] ;
153
- const lexicalEnvironmentFunctionDeclarationsStack : FunctionDeclaration [ ] [ ] = [ ] ;
154
74
const enabledSyntaxKindFeatures = new Array < SyntaxKindFeatureFlags > ( SyntaxKind . Count ) ;
155
75
76
+ let scopeModificationDisabled = false ;
77
+
78
+ let lexicalEnvironmentVariableDeclarations : VariableDeclaration [ ] ;
79
+ let lexicalEnvironmentFunctionDeclarations : FunctionDeclaration [ ] ;
80
+ let lexicalEnvironmentVariableDeclarationsStack : VariableDeclaration [ ] [ ] = [ ] ;
81
+ let lexicalEnvironmentFunctionDeclarationsStack : FunctionDeclaration [ ] [ ] = [ ] ;
156
82
let lexicalEnvironmentStackOffset = 0 ;
157
- let hoistedVariableDeclarations : VariableDeclaration [ ] ;
158
- let hoistedFunctionDeclarations : FunctionDeclaration [ ] ;
159
- let lexicalEnvironmentDisabled : boolean ;
83
+ let lexicalEnvironmentSuspended = false ;
84
+
85
+ let emitHelpers : EmitHelper [ ] ;
160
86
161
87
// The transformation context is provided to each transformer as part of transformer
162
88
// initialization.
163
89
const context : TransformationContext = {
164
90
getCompilerOptions : ( ) => host . getCompilerOptions ( ) ,
165
91
getEmitResolver : ( ) => resolver ,
166
92
getEmitHost : ( ) => host ,
167
- hoistVariableDeclaration,
168
- hoistFunctionDeclaration,
169
93
startLexicalEnvironment,
94
+ suspendLexicalEnvironment,
95
+ resumeLexicalEnvironment,
170
96
endLexicalEnvironment,
97
+ hoistVariableDeclaration,
98
+ hoistFunctionDeclaration,
99
+ requestEmitHelper,
100
+ readEmitHelpers,
171
101
onSubstituteNode : ( _emitContext , node ) => node ,
172
102
enableSubstitution,
173
103
isSubstitutionEnabled,
@@ -183,7 +113,7 @@ namespace ts {
183
113
const transformed = map ( sourceFiles , transformSourceFile ) ;
184
114
185
115
// Disable modification of the lexical environment.
186
- lexicalEnvironmentDisabled = true ;
116
+ scopeModificationDisabled = true ;
187
117
188
118
return {
189
119
transformed,
@@ -278,64 +208,80 @@ namespace ts {
278
208
* Records a hoisted variable declaration for the provided name within a lexical environment.
279
209
*/
280
210
function hoistVariableDeclaration ( name : Identifier ) : void {
281
- Debug . assert ( ! lexicalEnvironmentDisabled , "Cannot modify the lexical environment during the print phase." ) ;
211
+ Debug . assert ( ! scopeModificationDisabled , "Cannot modify the lexical environment during the print phase." ) ;
282
212
const decl = createVariableDeclaration ( name ) ;
283
- if ( ! hoistedVariableDeclarations ) {
284
- hoistedVariableDeclarations = [ decl ] ;
213
+ if ( ! lexicalEnvironmentVariableDeclarations ) {
214
+ lexicalEnvironmentVariableDeclarations = [ decl ] ;
285
215
}
286
216
else {
287
- hoistedVariableDeclarations . push ( decl ) ;
217
+ lexicalEnvironmentVariableDeclarations . push ( decl ) ;
288
218
}
289
219
}
290
220
291
221
/**
292
222
* Records a hoisted function declaration within a lexical environment.
293
223
*/
294
224
function hoistFunctionDeclaration ( func : FunctionDeclaration ) : void {
295
- Debug . assert ( ! lexicalEnvironmentDisabled , "Cannot modify the lexical environment during the print phase." ) ;
296
- if ( ! hoistedFunctionDeclarations ) {
297
- hoistedFunctionDeclarations = [ func ] ;
225
+ Debug . assert ( ! scopeModificationDisabled , "Cannot modify the lexical environment during the print phase." ) ;
226
+ if ( ! lexicalEnvironmentFunctionDeclarations ) {
227
+ lexicalEnvironmentFunctionDeclarations = [ func ] ;
298
228
}
299
229
else {
300
- hoistedFunctionDeclarations . push ( func ) ;
230
+ lexicalEnvironmentFunctionDeclarations . push ( func ) ;
301
231
}
302
232
}
303
233
234
+ /** Suspends the current lexical environment, usually after visiting a parameter list. */
235
+ function suspendLexicalEnvironment ( ) : void {
236
+ Debug . assert ( ! scopeModificationDisabled , "Cannot suspend a lexical environment during the print phase." ) ;
237
+ Debug . assert ( ! lexicalEnvironmentSuspended , "Lexical environment is already suspended." ) ;
238
+ lexicalEnvironmentSuspended = true ;
239
+ }
240
+
241
+ /** Resumes a suspended lexical environment, usually before visiting a function body. */
242
+ function resumeLexicalEnvironment ( ) : void {
243
+ Debug . assert ( ! scopeModificationDisabled , "Cannot resume a lexical environment during the print phase." ) ;
244
+ Debug . assert ( lexicalEnvironmentSuspended , "Lexical environment is not suspended suspended." ) ;
245
+ lexicalEnvironmentSuspended = false ;
246
+ }
247
+
304
248
/**
305
249
* Starts a new lexical environment. Any existing hoisted variable or function declarations
306
250
* are pushed onto a stack, and the related storage variables are reset.
307
251
*/
308
252
function startLexicalEnvironment ( ) : void {
309
- Debug . assert ( ! lexicalEnvironmentDisabled , "Cannot start a lexical environment during the print phase." ) ;
253
+ Debug . assert ( ! scopeModificationDisabled , "Cannot start a lexical environment during the print phase." ) ;
254
+ Debug . assert ( ! lexicalEnvironmentSuspended , "Lexical environment is suspended." ) ;
310
255
311
256
// Save the current lexical environment. Rather than resizing the array we adjust the
312
257
// stack size variable. This allows us to reuse existing array slots we've
313
258
// already allocated between transformations to avoid allocation and GC overhead during
314
259
// transformation.
315
- lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] = hoistedVariableDeclarations ;
316
- lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] = hoistedFunctionDeclarations ;
260
+ lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] = lexicalEnvironmentVariableDeclarations ;
261
+ lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] = lexicalEnvironmentFunctionDeclarations ;
317
262
lexicalEnvironmentStackOffset ++ ;
318
- hoistedVariableDeclarations = undefined ;
319
- hoistedFunctionDeclarations = undefined ;
263
+ lexicalEnvironmentVariableDeclarations = undefined ;
264
+ lexicalEnvironmentFunctionDeclarations = undefined ;
320
265
}
321
266
322
267
/**
323
268
* Ends a lexical environment. The previous set of hoisted declarations are restored and
324
269
* any hoisted declarations added in this environment are returned.
325
270
*/
326
271
function endLexicalEnvironment ( ) : Statement [ ] {
327
- Debug . assert ( ! lexicalEnvironmentDisabled , "Cannot end a lexical environment during the print phase." ) ;
272
+ Debug . assert ( ! scopeModificationDisabled , "Cannot end a lexical environment during the print phase." ) ;
273
+ Debug . assert ( ! lexicalEnvironmentSuspended , "Lexical environment is suspended." ) ;
328
274
329
275
let statements : Statement [ ] ;
330
- if ( hoistedVariableDeclarations || hoistedFunctionDeclarations ) {
331
- if ( hoistedFunctionDeclarations ) {
332
- statements = [ ...hoistedFunctionDeclarations ] ;
276
+ if ( lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations ) {
277
+ if ( lexicalEnvironmentFunctionDeclarations ) {
278
+ statements = [ ...lexicalEnvironmentFunctionDeclarations ] ;
333
279
}
334
280
335
- if ( hoistedVariableDeclarations ) {
281
+ if ( lexicalEnvironmentVariableDeclarations ) {
336
282
const statement = createVariableStatement (
337
283
/*modifiers*/ undefined ,
338
- createVariableDeclarationList ( hoistedVariableDeclarations )
284
+ createVariableDeclarationList ( lexicalEnvironmentVariableDeclarations )
339
285
) ;
340
286
341
287
if ( ! statements ) {
@@ -349,9 +295,27 @@ namespace ts {
349
295
350
296
// Restore the previous lexical environment.
351
297
lexicalEnvironmentStackOffset -- ;
352
- hoistedVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] ;
353
- hoistedFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] ;
298
+ lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] ;
299
+ lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] ;
300
+ if ( lexicalEnvironmentStackOffset === 0 ) {
301
+ lexicalEnvironmentVariableDeclarationsStack = [ ] ;
302
+ lexicalEnvironmentFunctionDeclarationsStack = [ ] ;
303
+ }
304
+
354
305
return statements ;
355
306
}
307
+
308
+ function requestEmitHelper ( helper : EmitHelper ) : void {
309
+ Debug . assert ( ! scopeModificationDisabled , "Cannot modify the lexical environment during the print phase." ) ;
310
+ Debug . assert ( ! helper . scoped , "Cannot request a scoped emit helper." ) ;
311
+ emitHelpers = append ( emitHelpers , helper ) ;
312
+ }
313
+
314
+ function readEmitHelpers ( ) : EmitHelper [ ] | undefined {
315
+ Debug . assert ( ! scopeModificationDisabled , "Cannot modify the lexical environment during the print phase." ) ;
316
+ const helpers = emitHelpers ;
317
+ emitHelpers = undefined ;
318
+ return helpers ;
319
+ }
356
320
}
357
321
}
0 commit comments