refactor(compiler-cli): remove TS bug workaround (#42000)
The TS bug at https://github.com/Microsoft/TypeScript/issues/29300 was fixed in TS 3.3, so the workaround is no longer required. PR Close #42000
This commit is contained in:
		
							parent
							
								
									500db42a2e
								
							
						
					
					
						commit
						0cb68632c6
					
				| @ -23,7 +23,6 @@ import {ClassDeclaration, DeclarationNode, Decorator, ReflectionHost, reflectObj | ||||
| import {ComponentScopeReader, LocalModuleScopeRegistry, TypeCheckScopeRegistry} from '../../scope'; | ||||
| import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerFlags, HandlerPrecedence, ResolveResult} from '../../transform'; | ||||
| import {TemplateSourceMapping, TypeCheckContext} from '../../typecheck/api'; | ||||
| import {tsSourceMapBug29300Fixed} from '../../util/src/ts_source_map_bug_29300'; | ||||
| import {SubsetOfKeys} from '../../util/src/typescript'; | ||||
| 
 | ||||
| import {ResourceLoader} from './api'; | ||||
| @ -1231,7 +1230,7 @@ export class ComponentDecoratorHandler implements | ||||
|           templateUrl, | ||||
|           templateUrlExpression: templateUrlExpr, | ||||
|           resolvedTemplateUrl: resourceUrl, | ||||
|           potentialSourceMapUrl: sourceMapUrl(resourceUrl), | ||||
|           potentialSourceMapUrl: resourceUrl, | ||||
|         }; | ||||
|       } catch (e) { | ||||
|         throw this.makeResourceNotFoundError( | ||||
| @ -1342,17 +1341,6 @@ function getTemplateRange(templateExpr: ts.Expression) { | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| function sourceMapUrl(resourceUrl: string): string { | ||||
|   if (!tsSourceMapBug29300Fixed()) { | ||||
|     // By removing the template URL we are telling the translator not to try to
 | ||||
|     // map the external source file to the generated code, since the version
 | ||||
|     // of TS that is running does not support it.
 | ||||
|     return ''; | ||||
|   } else { | ||||
|     return resourceUrl; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** Determines if the result of an evaluation is a string array. */ | ||||
| function isStringArray(resolvedValue: ResolvedValue): resolvedValue is string[] { | ||||
|   return Array.isArray(resolvedValue) && resolvedValue.every(elem => typeof elem === 'string'); | ||||
|  | ||||
| @ -1,90 +0,0 @@ | ||||
| /** | ||||
|  * @license | ||||
|  * Copyright Google LLC All Rights Reserved. | ||||
|  * | ||||
|  * Use of this source code is governed by an MIT-style license that can be | ||||
|  * found in the LICENSE file at https://angular.io/license
 | ||||
|  */ | ||||
| import * as ts from 'typescript'; | ||||
| 
 | ||||
| let _tsSourceMapBug29300Fixed: boolean|undefined; | ||||
| 
 | ||||
| /** | ||||
|  * Test the current version of TypeScript to see if it has fixed the external SourceMap | ||||
|  * file bug: https://github.com/Microsoft/TypeScript/issues/29300.
 | ||||
|  * | ||||
|  * The bug is fixed in TS 3.3+ but this check avoid us having to rely upon the version number, | ||||
|  * and allows us to gracefully fail if the TS version still has the bug. | ||||
|  * | ||||
|  * We check for the bug by compiling a very small program `a;` and transforming it to `b;`, | ||||
|  * where we map the new `b` identifier to an external source file, which has different lines to | ||||
|  * the original source file.  If the bug is fixed then the output SourceMap should contain | ||||
|  * mappings that correspond ot the correct line/col pairs for this transformed node. | ||||
|  * | ||||
|  * @returns true if the bug is fixed. | ||||
|  */ | ||||
| export function tsSourceMapBug29300Fixed() { | ||||
|   if (_tsSourceMapBug29300Fixed === undefined) { | ||||
|     let writtenFiles: {[filename: string]: string} = {}; | ||||
|     const sourceFile = | ||||
|         ts.createSourceFile('test.ts', 'a;', ts.ScriptTarget.ES2015, true, ts.ScriptKind.TS); | ||||
|     const host = { | ||||
|       getSourceFile(): ts.SourceFile | | ||||
|           undefined { | ||||
|             return sourceFile; | ||||
|           }, | ||||
|       fileExists(): boolean { | ||||
|         return true; | ||||
|       }, | ||||
|       readFile(): string | | ||||
|           undefined { | ||||
|             return ''; | ||||
|           }, | ||||
|       writeFile(fileName: string, data: string) { | ||||
|         writtenFiles[fileName] = data; | ||||
|       }, | ||||
|       getDefaultLibFileName(): string { | ||||
|         return ''; | ||||
|       }, | ||||
|       getCurrentDirectory(): string { | ||||
|         return ''; | ||||
|       }, | ||||
|       getDirectories(): string[] { | ||||
|         return []; | ||||
|       }, | ||||
|       getCanonicalFileName(): string { | ||||
|         return ''; | ||||
|       }, | ||||
|       useCaseSensitiveFileNames(): boolean { | ||||
|         return true; | ||||
|       }, | ||||
|       getNewLine(): string { | ||||
|         return '\n'; | ||||
|       }, | ||||
|     }; | ||||
| 
 | ||||
|     const transform = (context: ts.TransformationContext) => { | ||||
|       return (node: ts.SourceFile) => ts.visitNode(node, visitor); | ||||
|       function visitor(node: ts.Node): ts.Node { | ||||
|         if (ts.isIdentifier(node) && node.text === 'a') { | ||||
|           const newNode = ts.createIdentifier('b'); | ||||
|           ts.setSourceMapRange(newNode, { | ||||
|             pos: 16, | ||||
|             end: 16, | ||||
|             source: ts.createSourceMapSource('test.html', 'abc\ndef\nghi\njkl\nmno\npqr') | ||||
|           }); | ||||
|           return newNode; | ||||
|         } | ||||
|         return ts.visitEachChild(node, visitor, context); | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     const program = ts.createProgram(['test.ts'], {sourceMap: true}, host); | ||||
|     program.emit(sourceFile, undefined, undefined, undefined, {after: [transform]}); | ||||
|     // The first two mappings in the source map should look like:
 | ||||
|     // [0,1,4,0] col 0 => source file 1, row 4, column 0)
 | ||||
|     // [1,0,0,0] col 1 => source file 1, row 4, column 0)
 | ||||
|     _tsSourceMapBug29300Fixed = /ACIA,CAAA/.test(writtenFiles['test.js.map']); | ||||
|   } | ||||
|   return _tsSourceMapBug29300Fixed; | ||||
| } | ||||
| @ -11,7 +11,6 @@ import {inspect} from 'util'; | ||||
| 
 | ||||
| import {runInEachFileSystem} from '../../src/ngtsc/file_system/testing'; | ||||
| import {loadStandardTestFiles} from '../../src/ngtsc/testing'; | ||||
| import {tsSourceMapBug29300Fixed} from '../../src/ngtsc/util/src/ts_source_map_bug_29300'; | ||||
| 
 | ||||
| import {NgtscTestEnvironment} from './env'; | ||||
| import {getMappedSegments, SegmentMapping} from './sourcemap_utils'; | ||||
| @ -603,91 +602,90 @@ runInEachFileSystem((os) => { | ||||
|          }); | ||||
|     }); | ||||
| 
 | ||||
|     if (tsSourceMapBug29300Fixed()) { | ||||
|       describe('External templates (where TS supports source-mapping)', () => { | ||||
|         it('should create external template source-mapping', () => { | ||||
|           const mappings = | ||||
|               compileAndMap('<div>this is a test</div><div>{{ 1 + 2 }}</div>', './dir/test.html'); | ||||
|     describe('External templates (where TS supports source-mapping)', () => { | ||||
|       it('should create external template source-mapping', () => { | ||||
|         const mappings = | ||||
|             compileAndMap('<div>this is a test</div><div>{{ 1 + 2 }}</div>', './dir/test.html'); | ||||
| 
 | ||||
|           // Creation mode
 | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementStart(0, "div")', | ||||
|             source: '<div>', | ||||
|             sourceUrl: '../dir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵtext(1, "this is a test")', | ||||
|             source: 'this is a test', | ||||
|             sourceUrl: '../dir/test.html' | ||||
|           }); | ||||
|           expectMapping( | ||||
|               mappings, | ||||
|               {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../dir/test.html'}); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementStart(2, "div")', | ||||
|             source: '<div>', | ||||
|             sourceUrl: '../dir/test.html' | ||||
|           }); | ||||
|           expectMapping( | ||||
|               mappings, | ||||
|               {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../dir/test.html'}); | ||||
|           expectMapping( | ||||
|               mappings, | ||||
|               {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../dir/test.html'}); | ||||
| 
 | ||||
|           // Update mode
 | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||
|             source: '{{ 1 + 2 }}', | ||||
|             sourceUrl: '../dir/test.html' | ||||
|           }); | ||||
|         // Creation mode
 | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementStart(0, "div")', | ||||
|           source: '<div>', | ||||
|           sourceUrl: '../dir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵtext(1, "this is a test")', | ||||
|           source: 'this is a test', | ||||
|           sourceUrl: '../dir/test.html' | ||||
|         }); | ||||
|         expectMapping( | ||||
|             mappings, | ||||
|             {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../dir/test.html'}); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementStart(2, "div")', | ||||
|           source: '<div>', | ||||
|           sourceUrl: '../dir/test.html' | ||||
|         }); | ||||
|         expectMapping( | ||||
|             mappings, | ||||
|             {generated: 'i0.ɵɵtext(3)', source: '{{ 1 + 2 }}', sourceUrl: '../dir/test.html'}); | ||||
|         expectMapping( | ||||
|             mappings, | ||||
|             {generated: 'i0.ɵɵelementEnd()', source: '</div>', sourceUrl: '../dir/test.html'}); | ||||
| 
 | ||||
|         it('should create correct mappings when templateUrl is in a different rootDir', () => { | ||||
|           const mappings = compileAndMap( | ||||
|               '<div>this is a test</div><div>{{ 1 + 2 }}</div>', 'extraRootDir/test.html'); | ||||
| 
 | ||||
|           // Creation mode
 | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementStart(0, "div")', | ||||
|             source: '<div>', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵtext(1, "this is a test")', | ||||
|             source: 'this is a test', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementEnd()', | ||||
|             source: '</div>', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementStart(2, "div")', | ||||
|             source: '<div>', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵtext(3)', | ||||
|             source: '{{ 1 + 2 }}', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵelementEnd()', | ||||
|             source: '</div>', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
| 
 | ||||
|           // Update mode
 | ||||
|           expectMapping(mappings, { | ||||
|             generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||
|             source: '{{ 1 + 2 }}', | ||||
|             sourceUrl: '../extraRootDir/test.html' | ||||
|           }); | ||||
|         // Update mode
 | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||
|           source: '{{ 1 + 2 }}', | ||||
|           sourceUrl: '../dir/test.html' | ||||
|         }); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|       it('should create correct mappings when templateUrl is in a different rootDir', () => { | ||||
|         const mappings = compileAndMap( | ||||
|             '<div>this is a test</div><div>{{ 1 + 2 }}</div>', 'extraRootDir/test.html'); | ||||
| 
 | ||||
|         // Creation mode
 | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementStart(0, "div")', | ||||
|           source: '<div>', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵtext(1, "this is a test")', | ||||
|           source: 'this is a test', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementEnd()', | ||||
|           source: '</div>', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementStart(2, "div")', | ||||
|           source: '<div>', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵtext(3)', | ||||
|           source: '{{ 1 + 2 }}', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵelementEnd()', | ||||
|           source: '</div>', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
| 
 | ||||
|         // Update mode
 | ||||
|         expectMapping(mappings, { | ||||
|           generated: 'i0.ɵɵtextInterpolate(1 + 2)', | ||||
|           source: '{{ 1 + 2 }}', | ||||
|           sourceUrl: '../extraRootDir/test.html' | ||||
|         }); | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
| 
 | ||||
|     function compileAndMap(template: string, templateUrl: string|null = null) { | ||||
|       const templateConfig = templateUrl ? `templateUrl: '${templateUrl}'` : | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user