1/* @internal */ 2namespace ts { 3 function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile | Bundle> { 4 switch (moduleKind) { 5 case ModuleKind.ESNext: 6 case ModuleKind.ES2022: 7 case ModuleKind.ES2020: 8 case ModuleKind.ES2015: 9 return transformECMAScriptModule; 10 case ModuleKind.System: 11 return transformSystemModule; 12 case ModuleKind.Node16: 13 case ModuleKind.NodeNext: 14 return transformNodeModule; 15 default: 16 return transformModule; 17 } 18 } 19 20 const enum TransformationState { 21 Uninitialized, 22 Initialized, 23 Completed, 24 Disposed 25 } 26 27 const enum SyntaxKindFeatureFlags { 28 Substitution = 1 << 0, 29 EmitNotifications = 1 << 1, 30 } 31 32 export const noTransformers: EmitTransformers = { scriptTransformers: emptyArray, declarationTransformers: emptyArray }; 33 34 export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers { 35 return { 36 scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles), 37 declarationTransformers: getDeclarationTransformers(customTransformers), 38 }; 39 } 40 41 function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) { 42 if (emitOnlyDtsFiles) return emptyArray; 43 44 const languageVersion = getEmitScriptTarget(compilerOptions); 45 const moduleKind = getEmitModuleKind(compilerOptions); 46 const transformers: TransformerFactory<SourceFile | Bundle>[] = []; 47 48 addRange(transformers, customTransformers && map(customTransformers.before, wrapScriptTransformerFactory)); 49 50 transformers.push(transformTypeScript); 51 transformers.push(transformLegacyDecorators); 52 transformers.push(transformClassFields); 53 54 if (getJSXTransformEnabled(compilerOptions)) { 55 transformers.push(transformJsx); 56 } 57 58 if (languageVersion < ScriptTarget.ESNext) { 59 transformers.push(transformESNext); 60 } 61 62 if (languageVersion < ScriptTarget.ES2021) { 63 transformers.push(transformES2021); 64 } 65 66 if (languageVersion < ScriptTarget.ES2020) { 67 transformers.push(transformES2020); 68 } 69 70 if (languageVersion < ScriptTarget.ES2019) { 71 transformers.push(transformES2019); 72 } 73 74 if (languageVersion < ScriptTarget.ES2018) { 75 transformers.push(transformES2018); 76 } 77 78 if (languageVersion < ScriptTarget.ES2017) { 79 transformers.push(transformES2017); 80 } 81 82 if (languageVersion < ScriptTarget.ES2016) { 83 transformers.push(transformES2016); 84 } 85 86 if (languageVersion < ScriptTarget.ES2015) { 87 transformers.push(transformES2015); 88 transformers.push(transformGenerators); 89 } 90 91 transformers.push(getModuleTransformer(moduleKind)); 92 93 // The ES5 transformer is last so that it can substitute expressions like `exports.default` 94 // for ES3. 95 if (languageVersion < ScriptTarget.ES5) { 96 transformers.push(transformES5); 97 } 98 99 addRange(transformers, customTransformers && map(customTransformers.after, wrapScriptTransformerFactory)); 100 return transformers; 101 } 102 103 function getDeclarationTransformers(customTransformers?: CustomTransformers) { 104 const transformers: TransformerFactory<SourceFile | Bundle>[] = []; 105 transformers.push(transformDeclarations); 106 addRange(transformers, customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); 107 return transformers; 108 } 109 110 /** 111 * Wrap a custom script or declaration transformer object in a `Transformer` callback with fallback support for transforming bundles. 112 */ 113 function wrapCustomTransformer(transformer: CustomTransformer): Transformer<Bundle | SourceFile> { 114 return node => isBundle(node) ? transformer.transformBundle(node) : transformer.transformSourceFile(node); 115 } 116 117 /** 118 * Wrap a transformer factory that may return a custom script or declaration transformer object. 119 */ 120 function wrapCustomTransformerFactory<T extends SourceFile | Bundle>(transformer: TransformerFactory<T> | CustomTransformerFactory, handleDefault: (context: TransformationContext, tx: Transformer<T>) => Transformer<Bundle | SourceFile>): TransformerFactory<Bundle | SourceFile> { 121 return context => { 122 const customTransformer = transformer(context); 123 return typeof customTransformer === "function" 124 ? handleDefault(context, customTransformer) 125 : wrapCustomTransformer(customTransformer); 126 }; 127 } 128 129 function wrapScriptTransformerFactory(transformer: TransformerFactory<SourceFile> | CustomTransformerFactory): TransformerFactory<Bundle | SourceFile> { 130 return wrapCustomTransformerFactory(transformer, chainBundle); 131 } 132 133 function wrapDeclarationTransformerFactory(transformer: TransformerFactory<Bundle | SourceFile> | CustomTransformerFactory): TransformerFactory<Bundle | SourceFile> { 134 return wrapCustomTransformerFactory(transformer, (_, node) => node); 135 } 136 137 export function noEmitSubstitution(_hint: EmitHint, node: Node) { 138 return node; 139 } 140 141 export function noEmitNotification(hint: EmitHint, node: Node, callback: (hint: EmitHint, node: Node) => void) { 142 callback(hint, node); 143 } 144 145 /** 146 * Transforms an array of SourceFiles by passing them through each transformer. 147 * 148 * @param resolver The emit resolver provided by the checker. 149 * @param host The emit host object used to interact with the file system. 150 * @param options Compiler options to surface in the `TransformationContext`. 151 * @param nodes An array of nodes to transform. 152 * @param transforms An array of `TransformerFactory` callbacks. 153 * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. 154 */ 155 export function transformNodes<T extends Node>(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> { 156 const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count); 157 let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; 158 let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; 159 let lexicalEnvironmentStatements: Statement[]; 160 let lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; 161 let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = []; 162 let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; 163 let lexicalEnvironmentStatementsStack: Statement[][] = []; 164 let lexicalEnvironmentFlagsStack: LexicalEnvironmentFlags[] = []; 165 let lexicalEnvironmentStackOffset = 0; 166 let lexicalEnvironmentSuspended = false; 167 let blockScopedVariableDeclarationsStack: Identifier[][] = []; 168 let blockScopeStackOffset = 0; 169 let blockScopedVariableDeclarations: Identifier[]; 170 let emitHelpers: EmitHelper[] | undefined; 171 let onSubstituteNode: TransformationContext["onSubstituteNode"] = noEmitSubstitution; 172 let onEmitNode: TransformationContext["onEmitNode"] = noEmitNotification; 173 let state = TransformationState.Uninitialized; 174 const diagnostics: DiagnosticWithLocation[] = []; 175 176 // The transformation context is provided to each transformer as part of transformer 177 // initialization. 178 const context: TransformationContext = { 179 factory, 180 getCompilerOptions: () => options, 181 getEmitResolver: () => resolver!, // TODO: GH#18217 182 getEmitHost: () => host!, // TODO: GH#18217 183 getEmitHelperFactory: memoize(() => createEmitHelperFactory(context)), 184 startLexicalEnvironment, 185 suspendLexicalEnvironment, 186 resumeLexicalEnvironment, 187 endLexicalEnvironment, 188 setLexicalEnvironmentFlags, 189 getLexicalEnvironmentFlags, 190 hoistVariableDeclaration, 191 hoistFunctionDeclaration, 192 addInitializationStatement, 193 startBlockScope, 194 endBlockScope, 195 addBlockScopedVariable, 196 requestEmitHelper, 197 readEmitHelpers, 198 enableSubstitution, 199 enableEmitNotification, 200 isSubstitutionEnabled, 201 isEmitNotificationEnabled, 202 get onSubstituteNode() { return onSubstituteNode; }, 203 set onSubstituteNode(value) { 204 Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); 205 Debug.assert(value !== undefined, "Value must not be 'undefined'"); 206 onSubstituteNode = value; 207 }, 208 get onEmitNode() { return onEmitNode; }, 209 set onEmitNode(value) { 210 Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); 211 Debug.assert(value !== undefined, "Value must not be 'undefined'"); 212 onEmitNode = value; 213 }, 214 addDiagnostic(diag) { 215 diagnostics.push(diag); 216 } 217 }; 218 219 // Ensure the parse tree is clean before applying transformations 220 for (const node of nodes) { 221 disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node))); 222 } 223 224 performance.mark("beforeTransform"); 225 226 // Chain together and initialize each transformer. 227 const transformersWithContext = transformers.map(t => t(context)); 228 const transformation = (node: T): T => { 229 for (const transform of transformersWithContext) { 230 node = transform(node); 231 } 232 return node; 233 }; 234 235 // prevent modification of transformation hooks. 236 state = TransformationState.Initialized; 237 238 // Transform each node. 239 const transformed: T[] = []; 240 for (const node of nodes) { 241 tracing?.push(tracing.Phase.Emit, "transformNodes", node.kind === SyntaxKind.SourceFile ? { path: (node as any as SourceFile).path } : { kind: node.kind, pos: node.pos, end: node.end }); 242 transformed.push((allowDtsFiles ? transformation : transformRoot)(node)); 243 tracing?.pop(); 244 } 245 246 // prevent modification of the lexical environment. 247 state = TransformationState.Completed; 248 249 performance.mark("afterTransform"); 250 performance.measure("transformTime", "beforeTransform", "afterTransform"); 251 252 return { 253 transformed, 254 substituteNode, 255 emitNodeWithNotification, 256 isEmitNotificationEnabled, 257 dispose, 258 diagnostics 259 }; 260 261 function transformRoot(node: T) { 262 return node && (!isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; 263 } 264 265 /** 266 * Enables expression substitutions in the pretty printer for the provided SyntaxKind. 267 */ 268 function enableSubstitution(kind: SyntaxKind) { 269 Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); 270 enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution; 271 } 272 273 /** 274 * Determines whether expression substitutions are enabled for the provided node. 275 */ 276 function isSubstitutionEnabled(node: Node) { 277 return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.Substitution) !== 0 278 && (getEmitFlags(node) & EmitFlags.NoSubstitution) === 0; 279 } 280 281 /** 282 * Emits a node with possible substitution. 283 * 284 * @param hint A hint as to the intended usage of the node. 285 * @param node The node to emit. 286 * @param emitCallback The callback used to emit the node or its substitute. 287 */ 288 function substituteNode(hint: EmitHint, node: Node) { 289 Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed."); 290 return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node; 291 } 292 293 /** 294 * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. 295 */ 296 function enableEmitNotification(kind: SyntaxKind) { 297 Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); 298 enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications; 299 } 300 301 /** 302 * Determines whether before/after emit notifications should be raised in the pretty 303 * printer when it emits a node. 304 */ 305 function isEmitNotificationEnabled(node: Node) { 306 return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0 307 || (getEmitFlags(node) & EmitFlags.AdviseOnEmitNode) !== 0; 308 } 309 310 /** 311 * Emits a node with possible emit notification. 312 * 313 * @param hint A hint as to the intended usage of the node. 314 * @param node The node to emit. 315 * @param emitCallback The callback used to emit the node. 316 */ 317 function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { 318 Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed."); 319 if (node) { 320 // TODO: Remove check and unconditionally use onEmitNode when API is breakingly changed 321 // (see https://github.com/microsoft/TypeScript/pull/36248/files/5062623f39120171b98870c71344b3242eb03d23#r369766739) 322 if (isEmitNotificationEnabled(node)) { 323 onEmitNode(hint, node, emitCallback); 324 } 325 else { 326 emitCallback(hint, node); 327 } 328 } 329 } 330 331 /** 332 * Records a hoisted variable declaration for the provided name within a lexical environment. 333 */ 334 function hoistVariableDeclaration(name: Identifier): void { 335 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 336 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 337 const decl = setEmitFlags(factory.createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); 338 if (!lexicalEnvironmentVariableDeclarations) { 339 lexicalEnvironmentVariableDeclarations = [decl]; 340 } 341 else { 342 lexicalEnvironmentVariableDeclarations.push(decl); 343 } 344 if (lexicalEnvironmentFlags & LexicalEnvironmentFlags.InParameters) { 345 lexicalEnvironmentFlags |= LexicalEnvironmentFlags.VariablesHoistedInParameters; 346 } 347 } 348 349 /** 350 * Records a hoisted function declaration within a lexical environment. 351 */ 352 function hoistFunctionDeclaration(func: FunctionDeclaration): void { 353 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 354 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 355 setEmitFlags(func, EmitFlags.CustomPrologue); 356 if (!lexicalEnvironmentFunctionDeclarations) { 357 lexicalEnvironmentFunctionDeclarations = [func]; 358 } 359 else { 360 lexicalEnvironmentFunctionDeclarations.push(func); 361 } 362 } 363 364 /** 365 * Adds an initialization statement to the top of the lexical environment. 366 */ 367 function addInitializationStatement(node: Statement): void { 368 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 369 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 370 setEmitFlags(node, EmitFlags.CustomPrologue); 371 if (!lexicalEnvironmentStatements) { 372 lexicalEnvironmentStatements = [node]; 373 } 374 else { 375 lexicalEnvironmentStatements.push(node); 376 } 377 } 378 379 /** 380 * Starts a new lexical environment. Any existing hoisted variable or function declarations 381 * are pushed onto a stack, and the related storage variables are reset. 382 */ 383 function startLexicalEnvironment(): void { 384 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 385 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 386 Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); 387 388 // Save the current lexical environment. Rather than resizing the array we adjust the 389 // stack size variable. This allows us to reuse existing array slots we've 390 // already allocated between transformations to avoid allocation and GC overhead during 391 // transformation. 392 lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentVariableDeclarations; 393 lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFunctionDeclarations; 394 lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentStatements; 395 lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset] = lexicalEnvironmentFlags; 396 lexicalEnvironmentStackOffset++; 397 lexicalEnvironmentVariableDeclarations = undefined!; 398 lexicalEnvironmentFunctionDeclarations = undefined!; 399 lexicalEnvironmentStatements = undefined!; 400 lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; 401 } 402 403 /** Suspends the current lexical environment, usually after visiting a parameter list. */ 404 function suspendLexicalEnvironment(): void { 405 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 406 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 407 Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); 408 lexicalEnvironmentSuspended = true; 409 } 410 411 /** Resumes a suspended lexical environment, usually before visiting a function body. */ 412 function resumeLexicalEnvironment(): void { 413 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 414 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 415 Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); 416 lexicalEnvironmentSuspended = false; 417 } 418 419 /** 420 * Ends a lexical environment. The previous set of hoisted declarations are restored and 421 * any hoisted declarations added in this environment are returned. 422 */ 423 function endLexicalEnvironment(): Statement[] | undefined { 424 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); 425 Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); 426 Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); 427 428 let statements: Statement[] | undefined; 429 if (lexicalEnvironmentVariableDeclarations || 430 lexicalEnvironmentFunctionDeclarations || 431 lexicalEnvironmentStatements) { 432 if (lexicalEnvironmentFunctionDeclarations) { 433 statements = [...lexicalEnvironmentFunctionDeclarations]; 434 } 435 436 if (lexicalEnvironmentVariableDeclarations) { 437 const statement = factory.createVariableStatement( 438 /*modifiers*/ undefined, 439 factory.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations) 440 ); 441 442 setEmitFlags(statement, EmitFlags.CustomPrologue); 443 444 if (!statements) { 445 statements = [statement]; 446 } 447 else { 448 statements.push(statement); 449 } 450 } 451 452 if (lexicalEnvironmentStatements) { 453 if (!statements) { 454 statements = [...lexicalEnvironmentStatements]; 455 } 456 else { 457 statements = [...statements, ...lexicalEnvironmentStatements]; 458 } 459 } 460 } 461 462 // Restore the previous lexical environment. 463 lexicalEnvironmentStackOffset--; 464 lexicalEnvironmentVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset]; 465 lexicalEnvironmentFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset]; 466 lexicalEnvironmentStatements = lexicalEnvironmentStatementsStack[lexicalEnvironmentStackOffset]; 467 lexicalEnvironmentFlags = lexicalEnvironmentFlagsStack[lexicalEnvironmentStackOffset]; 468 if (lexicalEnvironmentStackOffset === 0) { 469 lexicalEnvironmentVariableDeclarationsStack = []; 470 lexicalEnvironmentFunctionDeclarationsStack = []; 471 lexicalEnvironmentStatementsStack = []; 472 lexicalEnvironmentFlagsStack = []; 473 } 474 return statements; 475 } 476 477 function setLexicalEnvironmentFlags(flags: LexicalEnvironmentFlags, value: boolean): void { 478 lexicalEnvironmentFlags = value ? 479 lexicalEnvironmentFlags | flags : 480 lexicalEnvironmentFlags & ~flags; 481 } 482 483 function getLexicalEnvironmentFlags(): LexicalEnvironmentFlags { 484 return lexicalEnvironmentFlags; 485 } 486 487 /** 488 * Starts a block scope. Any existing block hoisted variables are pushed onto the stack and the related storage variables are reset. 489 */ 490 function startBlockScope() { 491 Debug.assert(state > TransformationState.Uninitialized, "Cannot start a block scope during initialization."); 492 Debug.assert(state < TransformationState.Completed, "Cannot start a block scope after transformation has completed."); 493 blockScopedVariableDeclarationsStack[blockScopeStackOffset] = blockScopedVariableDeclarations; 494 blockScopeStackOffset++; 495 blockScopedVariableDeclarations = undefined!; 496 } 497 498 /** 499 * Ends a block scope. The previous set of block hoisted variables are restored. Any hoisted declarations are returned. 500 */ 501 function endBlockScope() { 502 Debug.assert(state > TransformationState.Uninitialized, "Cannot end a block scope during initialization."); 503 Debug.assert(state < TransformationState.Completed, "Cannot end a block scope after transformation has completed."); 504 const statements: Statement[] | undefined = some(blockScopedVariableDeclarations) ? 505 [ 506 factory.createVariableStatement( 507 /*modifiers*/ undefined, 508 factory.createVariableDeclarationList( 509 blockScopedVariableDeclarations.map(identifier => factory.createVariableDeclaration(identifier)), 510 NodeFlags.Let 511 ) 512 ) 513 ] : undefined; 514 blockScopeStackOffset--; 515 blockScopedVariableDeclarations = blockScopedVariableDeclarationsStack[blockScopeStackOffset]; 516 if (blockScopeStackOffset === 0) { 517 blockScopedVariableDeclarationsStack = []; 518 } 519 return statements; 520 } 521 522 function addBlockScopedVariable(name: Identifier): void { 523 Debug.assert(blockScopeStackOffset > 0, "Cannot add a block scoped variable outside of an iteration body."); 524 (blockScopedVariableDeclarations || (blockScopedVariableDeclarations = [])).push(name); 525 } 526 527 function requestEmitHelper(helper: EmitHelper): void { 528 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); 529 Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); 530 Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); 531 if (helper.dependencies) { 532 for (const h of helper.dependencies) { 533 requestEmitHelper(h); 534 } 535 } 536 emitHelpers = append(emitHelpers, helper); 537 } 538 539 function readEmitHelpers(): EmitHelper[] | undefined { 540 Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); 541 Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); 542 const helpers = emitHelpers; 543 emitHelpers = undefined; 544 return helpers; 545 } 546 547 function dispose() { 548 if (state < TransformationState.Disposed) { 549 // Clean up emit nodes on parse tree 550 for (const node of nodes) { 551 disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node))); 552 } 553 554 // Release references to external entries for GC purposes. 555 lexicalEnvironmentVariableDeclarations = undefined!; 556 lexicalEnvironmentVariableDeclarationsStack = undefined!; 557 lexicalEnvironmentFunctionDeclarations = undefined!; 558 lexicalEnvironmentFunctionDeclarationsStack = undefined!; 559 onSubstituteNode = undefined!; 560 onEmitNode = undefined!; 561 emitHelpers = undefined; 562 563 // Prevent further use of the transformation result. 564 state = TransformationState.Disposed; 565 } 566 } 567 } 568 569 export const nullTransformationContext: TransformationContext = { 570 factory: factory, // eslint-disable-line object-shorthand 571 getCompilerOptions: () => ({}), 572 getEmitResolver: notImplemented, 573 getEmitHost: notImplemented, 574 getEmitHelperFactory: notImplemented, 575 startLexicalEnvironment: noop, 576 resumeLexicalEnvironment: noop, 577 suspendLexicalEnvironment: noop, 578 endLexicalEnvironment: returnUndefined, 579 setLexicalEnvironmentFlags: noop, 580 getLexicalEnvironmentFlags: () => 0, 581 hoistVariableDeclaration: noop, 582 hoistFunctionDeclaration: noop, 583 addInitializationStatement: noop, 584 startBlockScope: noop, 585 endBlockScope: returnUndefined, 586 addBlockScopedVariable: noop, 587 requestEmitHelper: noop, 588 readEmitHelpers: notImplemented, 589 enableSubstitution: noop, 590 enableEmitNotification: noop, 591 isSubstitutionEnabled: notImplemented, 592 isEmitNotificationEnabled: notImplemented, 593 onSubstituteNode: noEmitSubstitution, 594 onEmitNode: noEmitNotification, 595 addDiagnostic: noop, 596 }; 597} 598