@@ -26,84 +26,6 @@ namespace ts {
2626 EmitNotifications = 1 << 1 ,
2727 }
2828
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-
10729 export function getTransformers ( compilerOptions : CompilerOptions ) {
10830 const jsx = compilerOptions . jsx ;
10931 const languageVersion = getEmitScriptTarget ( compilerOptions ) ;
@@ -149,25 +71,33 @@ namespace ts {
14971 * @param transforms An array of Transformers.
15072 */
15173 export function transformFiles ( resolver : EmitResolver , host : EmitHost , sourceFiles : SourceFile [ ] , transformers : Transformer [ ] ) : TransformationResult {
152- const lexicalEnvironmentVariableDeclarationsStack : VariableDeclaration [ ] [ ] = [ ] ;
153- const lexicalEnvironmentFunctionDeclarationsStack : FunctionDeclaration [ ] [ ] = [ ] ;
15474 const enabledSyntaxKindFeatures = new Array < SyntaxKindFeatureFlags > ( SyntaxKind . Count ) ;
15575
76+ let scopeModificationDisabled = false ;
77+
78+ let lexicalEnvironmentVariableDeclarations : VariableDeclaration [ ] ;
79+ let lexicalEnvironmentFunctionDeclarations : FunctionDeclaration [ ] ;
80+ let lexicalEnvironmentVariableDeclarationsStack : VariableDeclaration [ ] [ ] = [ ] ;
81+ let lexicalEnvironmentFunctionDeclarationsStack : FunctionDeclaration [ ] [ ] = [ ] ;
15682 let lexicalEnvironmentStackOffset = 0 ;
157- let hoistedVariableDeclarations : VariableDeclaration [ ] ;
158- let hoistedFunctionDeclarations : FunctionDeclaration [ ] ;
159- let lexicalEnvironmentDisabled : boolean ;
83+ let lexicalEnvironmentSuspended = false ;
84+
85+ let emitHelpers : EmitHelper [ ] ;
16086
16187 // The transformation context is provided to each transformer as part of transformer
16288 // initialization.
16389 const context : TransformationContext = {
16490 getCompilerOptions : ( ) => host . getCompilerOptions ( ) ,
16591 getEmitResolver : ( ) => resolver ,
16692 getEmitHost : ( ) => host ,
167- hoistVariableDeclaration,
168- hoistFunctionDeclaration,
16993 startLexicalEnvironment,
94+ suspendLexicalEnvironment,
95+ resumeLexicalEnvironment,
17096 endLexicalEnvironment,
97+ hoistVariableDeclaration,
98+ hoistFunctionDeclaration,
99+ requestEmitHelper,
100+ readEmitHelpers,
171101 onSubstituteNode : ( _emitContext , node ) => node ,
172102 enableSubstitution,
173103 isSubstitutionEnabled,
@@ -183,7 +113,7 @@ namespace ts {
183113 const transformed = map ( sourceFiles , transformSourceFile ) ;
184114
185115 // Disable modification of the lexical environment.
186- lexicalEnvironmentDisabled = true ;
116+ scopeModificationDisabled = true ;
187117
188118 return {
189119 transformed,
@@ -278,64 +208,80 @@ namespace ts {
278208 * Records a hoisted variable declaration for the provided name within a lexical environment.
279209 */
280210 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." ) ;
282212 const decl = createVariableDeclaration ( name ) ;
283- if ( ! hoistedVariableDeclarations ) {
284- hoistedVariableDeclarations = [ decl ] ;
213+ if ( ! lexicalEnvironmentVariableDeclarations ) {
214+ lexicalEnvironmentVariableDeclarations = [ decl ] ;
285215 }
286216 else {
287- hoistedVariableDeclarations . push ( decl ) ;
217+ lexicalEnvironmentVariableDeclarations . push ( decl ) ;
288218 }
289219 }
290220
291221 /**
292222 * Records a hoisted function declaration within a lexical environment.
293223 */
294224 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 ] ;
298228 }
299229 else {
300- hoistedFunctionDeclarations . push ( func ) ;
230+ lexicalEnvironmentFunctionDeclarations . push ( func ) ;
301231 }
302232 }
303233
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+
304248 /**
305249 * Starts a new lexical environment. Any existing hoisted variable or function declarations
306250 * are pushed onto a stack, and the related storage variables are reset.
307251 */
308252 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." ) ;
310255
311256 // Save the current lexical environment. Rather than resizing the array we adjust the
312257 // stack size variable. This allows us to reuse existing array slots we've
313258 // already allocated between transformations to avoid allocation and GC overhead during
314259 // transformation.
315- lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] = hoistedVariableDeclarations ;
316- lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] = hoistedFunctionDeclarations ;
260+ lexicalEnvironmentVariableDeclarationsStack [ lexicalEnvironmentStackOffset ] = lexicalEnvironmentVariableDeclarations ;
261+ lexicalEnvironmentFunctionDeclarationsStack [ lexicalEnvironmentStackOffset ] = lexicalEnvironmentFunctionDeclarations ;
317262 lexicalEnvironmentStackOffset ++ ;
318- hoistedVariableDeclarations = undefined ;
319- hoistedFunctionDeclarations = undefined ;
263+ lexicalEnvironmentVariableDeclarations = undefined ;
264+ lexicalEnvironmentFunctionDeclarations = undefined ;
320265 }
321266
322267 /**
323268 * Ends a lexical environment. The previous set of hoisted declarations are restored and
324269 * any hoisted declarations added in this environment are returned.
325270 */
326271 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." ) ;
328274
329275 let statements : Statement [ ] ;
330- if ( hoistedVariableDeclarations || hoistedFunctionDeclarations ) {
331- if ( hoistedFunctionDeclarations ) {
332- statements = [ ...hoistedFunctionDeclarations ] ;
276+ if ( lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations ) {
277+ if ( lexicalEnvironmentFunctionDeclarations ) {
278+ statements = [ ...lexicalEnvironmentFunctionDeclarations ] ;
333279 }
334280
335- if ( hoistedVariableDeclarations ) {
281+ if ( lexicalEnvironmentVariableDeclarations ) {
336282 const statement = createVariableStatement (
337283 /*modifiers*/ undefined ,
338- createVariableDeclarationList ( hoistedVariableDeclarations )
284+ createVariableDeclarationList ( lexicalEnvironmentVariableDeclarations )
339285 ) ;
340286
341287 if ( ! statements ) {
@@ -349,9 +295,27 @@ namespace ts {
349295
350296 // Restore the previous lexical environment.
351297 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+
354305 return statements ;
355306 }
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+ }
356320 }
357321}
0 commit comments