- temporarily keeps the old sources under packages/tsc-wrapped until the build scripts are changed to use compiler-cli everywhere. - removes the compiler options `disableTransformerPipeline` that was introduced in a previous beta of Angular 5, i.e. the transformer based compiler is now always enabled. PR Close #18966
		
			
				
	
	
		
			273 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * @license
 | |
|  * Copyright Google Inc. 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 {ModuleMetadata} from '@angular/compiler-cli/src/metadata/index';
 | |
| import * as ts from 'typescript';
 | |
| 
 | |
| import {CompilerHost} from '../src/compiler_host';
 | |
| 
 | |
| import {Directory, Entry, MockAotContext, MockCompilerHost} from './mocks';
 | |
| 
 | |
| describe('CompilerHost', () => {
 | |
|   let context: MockAotContext;
 | |
|   let program: ts.Program;
 | |
|   let hostNestedGenDir: CompilerHost;
 | |
|   let hostSiblingGenDir: CompilerHost;
 | |
| 
 | |
|   beforeEach(() => {
 | |
|     context = new MockAotContext('/tmp/src', clone(FILES));
 | |
|     const host = new MockCompilerHost(context);
 | |
|     program = ts.createProgram(
 | |
|         ['main.ts'], {
 | |
|           module: ts.ModuleKind.CommonJS,
 | |
|         },
 | |
|         host);
 | |
|     // Force a typecheck
 | |
|     const errors = program.getSemanticDiagnostics();
 | |
|     if (errors && errors.length) {
 | |
|       throw new Error('Expected no errors');
 | |
|     }
 | |
|     hostNestedGenDir = new CompilerHost(
 | |
|         program, {
 | |
|           genDir: '/tmp/project/src/gen/',
 | |
|           basePath: '/tmp/project/src',
 | |
|           skipMetadataEmit: false,
 | |
|           strictMetadataEmit: false,
 | |
|           skipTemplateCodegen: false,
 | |
|           trace: false
 | |
|         },
 | |
|         context);
 | |
|     hostSiblingGenDir = new CompilerHost(
 | |
|         program, {
 | |
|           genDir: '/tmp/project/gen',
 | |
|           basePath: '/tmp/project/src/',
 | |
|           skipMetadataEmit: false,
 | |
|           strictMetadataEmit: false,
 | |
|           skipTemplateCodegen: false,
 | |
|           trace: false
 | |
|         },
 | |
|         context);
 | |
|   });
 | |
| 
 | |
|   describe('nestedGenDir', () => {
 | |
|     it('should import node_module from factory', () => {
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/node_modules/@angular/core.d.ts',
 | |
|                  '/tmp/project/src/gen/my.ngfactory.ts', ))
 | |
|           .toEqual('@angular/core');
 | |
|     });
 | |
| 
 | |
|     it('should import factory from factory', () => {
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./my.other.ngfactory');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.css.ngstyle.ts', '/tmp/project/src/a/my.ngfactory.ts'))
 | |
|           .toEqual('../my.other.css.ngstyle');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.shim.ngstyle.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./a/my.other.shim.ngstyle');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.sass.ngstyle.ts', '/tmp/project/src/a/my.ngfactory.ts'))
 | |
|           .toEqual('../my.other.sass.ngstyle');
 | |
|     });
 | |
| 
 | |
|     it('should import application from factory', () => {
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('../my.other');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
 | |
|           .toEqual('../../my.other');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('../a/my.other');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.css.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('../a/my.other.css');
 | |
|       expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('../a/my.other.css.shim');
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('siblingGenDir', () => {
 | |
|     it('should import node_module from factory', () => {
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/node_modules/@angular/core.d.ts',
 | |
|                  '/tmp/project/src/gen/my.ngfactory.ts'))
 | |
|           .toEqual('@angular/core');
 | |
|     });
 | |
| 
 | |
|     it('should import factory from factory', () => {
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./my.other.ngfactory');
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts'))
 | |
|           .toEqual('../my.other.css');
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./a/my.other.css.shim');
 | |
|     });
 | |
| 
 | |
|     it('should import application from factory', () => {
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./my.other');
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
 | |
|           .toEqual('../my.other');
 | |
|       expect(hostSiblingGenDir.fileNameToModuleName(
 | |
|                  '/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
 | |
|           .toEqual('./a/my.other');
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   it('should be able to produce an import from main @angular/core', () => {
 | |
|     expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                '/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/src/main.ts'))
 | |
|         .toEqual('@angular/core');
 | |
|   });
 | |
| 
 | |
|   it('should be able to produce an import to a shallow import', () => {
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('@angular/core', '/tmp/project/src/main.ts'))
 | |
|         .toEqual('@angular/core');
 | |
|     expect(hostNestedGenDir.fileNameToModuleName(
 | |
|                '@angular/upgrade/static', '/tmp/project/src/main.ts'))
 | |
|         .toEqual('@angular/upgrade/static');
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('myLibrary', '/tmp/project/src/main.ts'))
 | |
|         .toEqual('myLibrary');
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('lib23-43', '/tmp/project/src/main.ts'))
 | |
|         .toEqual('lib23-43');
 | |
|   });
 | |
| 
 | |
|   it('should be able to produce an import from main to a sub-directory', () => {
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('lib/utils.ts', 'main.ts')).toEqual('./lib/utils');
 | |
|   });
 | |
| 
 | |
|   it('should be able to produce an import from to a peer file', () => {
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('lib/collections.ts', 'lib/utils.ts'))
 | |
|         .toEqual('./collections');
 | |
|   });
 | |
| 
 | |
|   it('should be able to produce an import from to a sibling directory', () => {
 | |
|     expect(hostNestedGenDir.fileNameToModuleName('lib/utils.ts', 'lib2/utils2.ts'))
 | |
|         .toEqual('../lib/utils');
 | |
|   });
 | |
| 
 | |
|   it('should be able to read a metadata file', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('node_modules/@angular/core.d.ts')).toEqual([
 | |
|       {__symbolic: 'module', version: 3, metadata: {foo: {__symbolic: 'class'}}}
 | |
|     ]);
 | |
|   });
 | |
| 
 | |
|   it('should be able to read metadata from an otherwise unused .d.ts file ', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('node_modules/@angular/unused.d.ts')).toEqual([
 | |
|       dummyMetadata
 | |
|     ]);
 | |
|   });
 | |
| 
 | |
|   it('should be able to read empty metadata ', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('node_modules/@angular/empty.d.ts')).toEqual([]);
 | |
|   });
 | |
| 
 | |
|   it('should return undefined for missing modules', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('node_modules/@angular/missing.d.ts')).toBeUndefined();
 | |
|   });
 | |
| 
 | |
|   it('should add missing v3 metadata from v1 metadata and .d.ts files', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('metadata_versions/v1.d.ts')).toEqual([
 | |
|       {__symbolic: 'module', version: 1, metadata: {foo: {__symbolic: 'class'}}}, {
 | |
|         __symbolic: 'module',
 | |
|         version: 3,
 | |
|         metadata: {
 | |
|           foo: {__symbolic: 'class'},
 | |
|           Bar: {__symbolic: 'class', members: {ngOnInit: [{__symbolic: 'method'}]}},
 | |
|           BarChild: {__symbolic: 'class', extends: {__symbolic: 'reference', name: 'Bar'}},
 | |
|           ReExport: {__symbolic: 'reference', module: './lib/utils2', name: 'ReExport'},
 | |
|         },
 | |
|         exports: [{from: './lib/utils2', export: ['Export']}],
 | |
|       }
 | |
|     ]);
 | |
|   });
 | |
| 
 | |
|   it('should upgrade a missing metadata file into v3', () => {
 | |
|     expect(hostNestedGenDir.getMetadataFor('metadata_versions/v1_empty.d.ts')).toEqual([
 | |
|       {__symbolic: 'module', version: 3, metadata: {}, exports: [{from: './lib/utils'}]}
 | |
|     ]);
 | |
|   });
 | |
| });
 | |
| 
 | |
| const dummyModule = 'export let foo: any[];';
 | |
| const dummyMetadata: ModuleMetadata = {
 | |
|   __symbolic: 'module',
 | |
|   version: 3,
 | |
|   metadata:
 | |
|       {foo: {__symbolic: 'error', message: 'Variable not initialized', line: 0, character: 11}}
 | |
| };
 | |
| const FILES: Entry = {
 | |
|   'tmp': {
 | |
|     'src': {
 | |
|       'main.ts': `
 | |
|         import * as c from '@angular/core';
 | |
|         import * as r from '@angular/router';
 | |
|         import * as u from './lib/utils';
 | |
|         import * as cs from './lib/collections';
 | |
|         import * as u2 from './lib2/utils2';
 | |
|       `,
 | |
|       'lib': {
 | |
|         'utils.ts': dummyModule,
 | |
|         'collections.ts': dummyModule,
 | |
|       },
 | |
|       'lib2': {'utils2.ts': dummyModule},
 | |
|       'node_modules': {
 | |
|         '@angular': {
 | |
|           'core.d.ts': dummyModule,
 | |
|           'core.metadata.json':
 | |
|               `{"__symbolic":"module", "version": 3, "metadata": {"foo": {"__symbolic": "class"}}}`,
 | |
|           'router': {'index.d.ts': dummyModule, 'src': {'providers.d.ts': dummyModule}},
 | |
|           'unused.d.ts': dummyModule,
 | |
|           'empty.d.ts': 'export declare var a: string;',
 | |
|           'empty.metadata.json': '[]',
 | |
|         }
 | |
|       },
 | |
|       'metadata_versions': {
 | |
|         'v1.d.ts': `
 | |
|           import {ReExport} from './lib/utils2';
 | |
|           export {ReExport};
 | |
| 
 | |
|           export {Export} from './lib/utils2';
 | |
| 
 | |
|           export declare class Bar {
 | |
|             ngOnInit() {}
 | |
|           }
 | |
|           export declare class BarChild extends Bar {}
 | |
|         `,
 | |
|         'v1.metadata.json':
 | |
|             `{"__symbolic":"module", "version": 1, "metadata": {"foo": {"__symbolic": "class"}}}`,
 | |
|         'v1_empty.d.ts': `
 | |
|           export * from './lib/utils';
 | |
|         `
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| function clone(entry: Entry): Entry {
 | |
|   if (typeof entry === 'string') {
 | |
|     return entry;
 | |
|   } else {
 | |
|     const result: Directory = {};
 | |
|     for (const name in entry) {
 | |
|       result[name] = clone(entry[name]);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
| }
 |