fix(ivy): ngtsc fails building flat module out on windows (#27993)
`ngtsc` currently fails building a flat module out file on Windows because it generates an invalid flat module TypeScript source file. e.g: ```ts 5 export * from './C:\Users\Paul\Desktop\test\src\export'; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` This is because `path.posix.relative` does not properly with non-posix paths, and only expects posix paths in order to work. PR Close #27993
This commit is contained in:
parent
d336bff200
commit
070fca1591
@ -12,6 +12,7 @@ import * as path from 'path';
|
|||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ShimGenerator} from '../../shims';
|
import {ShimGenerator} from '../../shims';
|
||||||
|
import {relativePathBetween} from '../../util/src/path';
|
||||||
|
|
||||||
export class FlatIndexGenerator implements ShimGenerator {
|
export class FlatIndexGenerator implements ShimGenerator {
|
||||||
readonly flatIndexPath: string;
|
readonly flatIndexPath: string;
|
||||||
@ -27,10 +28,7 @@ export class FlatIndexGenerator implements ShimGenerator {
|
|||||||
recognize(fileName: string): boolean { return fileName === this.flatIndexPath; }
|
recognize(fileName: string): boolean { return fileName === this.flatIndexPath; }
|
||||||
|
|
||||||
generate(): ts.SourceFile {
|
generate(): ts.SourceFile {
|
||||||
const relativeEntryPoint = './' +
|
const relativeEntryPoint = relativePathBetween(this.flatIndexPath, this.entryPoint);
|
||||||
path.posix.relative(path.posix.dirname(this.flatIndexPath), this.entryPoint)
|
|
||||||
.replace(/\.tsx?$/, '');
|
|
||||||
|
|
||||||
const contents = `/**
|
const contents = `/**
|
||||||
* Generated bundle index. Do not edit.
|
* Generated bundle index. Do not edit.
|
||||||
*/
|
*/
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {normalizeSeparators} from '../../util/src/path';
|
||||||
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
||||||
|
|
||||||
export function findFlatIndexEntryPoint(rootFiles: ReadonlyArray<string>): string|null {
|
export function findFlatIndexEntryPoint(rootFiles: ReadonlyArray<string>): string|null {
|
||||||
@ -13,22 +14,24 @@ export function findFlatIndexEntryPoint(rootFiles: ReadonlyArray<string>): strin
|
|||||||
// 1) if it's the only file!!!!!!
|
// 1) if it's the only file!!!!!!
|
||||||
// 2) (deprecated) if it's named 'index.ts' and has the shortest path of all such files.
|
// 2) (deprecated) if it's named 'index.ts' and has the shortest path of all such files.
|
||||||
const tsFiles = rootFiles.filter(file => isNonDeclarationTsPath(file));
|
const tsFiles = rootFiles.filter(file => isNonDeclarationTsPath(file));
|
||||||
|
let resolvedEntryPoint: string|null = null;
|
||||||
|
|
||||||
if (tsFiles.length === 1) {
|
if (tsFiles.length === 1) {
|
||||||
// There's only one file - this is the flat module index.
|
// There's only one file - this is the flat module index.
|
||||||
return tsFiles[0];
|
resolvedEntryPoint = tsFiles[0];
|
||||||
} else {
|
} else {
|
||||||
// In the event there's more than one TS file, one of them can still be selected as the
|
// In the event there's more than one TS file, one of them can still be selected as the
|
||||||
// flat module index if it's named 'index.ts'. If there's more than one 'index.ts', the one
|
// flat module index if it's named 'index.ts'. If there's more than one 'index.ts', the one
|
||||||
// with the shortest path wins.
|
// with the shortest path wins.
|
||||||
//
|
//
|
||||||
// This behavior is DEPRECATED and only exists to support existing usages.
|
// This behavior is DEPRECATED and only exists to support existing usages.
|
||||||
let indexFile: string|null = null;
|
|
||||||
for (const tsFile of tsFiles) {
|
for (const tsFile of tsFiles) {
|
||||||
if (tsFile.endsWith('/index.ts') &&
|
if (tsFile.endsWith('/index.ts') &&
|
||||||
(indexFile === null || tsFile.length <= indexFile.length)) {
|
(resolvedEntryPoint === null || tsFile.length <= resolvedEntryPoint.length)) {
|
||||||
indexFile = tsFile;
|
resolvedEntryPoint = tsFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return indexFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return resolvedEntryPoint ? normalizeSeparators(resolvedEntryPoint) : null;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* @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 {findFlatIndexEntryPoint} from '../src/logic';
|
||||||
|
|
||||||
|
describe('entry_point logic', () => {
|
||||||
|
|
||||||
|
describe('findFlatIndexEntryPoint', () => {
|
||||||
|
|
||||||
|
it('should use the only source file if only a single one is specified',
|
||||||
|
() => { expect(findFlatIndexEntryPoint(['/src/index.ts'])).toBe('/src/index.ts'); });
|
||||||
|
|
||||||
|
it('should use the shortest source file ending with "index.ts" for multiple files', () => {
|
||||||
|
expect(findFlatIndexEntryPoint([
|
||||||
|
'/src/deep/index.ts', '/src/index.ts', '/index.ts'
|
||||||
|
])).toBe('/index.ts');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should normalize the path separators for the found entry point',
|
||||||
|
() => { expect(findFlatIndexEntryPoint(['\\src\\index.ts'])).toBe('/src/index.ts'); });
|
||||||
|
});
|
||||||
|
});
|
@ -24,6 +24,7 @@ import {FactoryGenerator, FactoryInfo, GeneratedShimsHostWrapper, ShimGenerator,
|
|||||||
import {ivySwitchTransform} from './switch';
|
import {ivySwitchTransform} from './switch';
|
||||||
import {IvyCompilation, ivyTransformFactory} from './transform';
|
import {IvyCompilation, ivyTransformFactory} from './transform';
|
||||||
import {TypeCheckContext, TypeCheckProgramHost} from './typecheck';
|
import {TypeCheckContext, TypeCheckProgramHost} from './typecheck';
|
||||||
|
import {normalizeSeparators} from './util/src/path';
|
||||||
import {isDtsPath} from './util/src/typescript';
|
import {isDtsPath} from './util/src/typescript';
|
||||||
|
|
||||||
export class NgtscProgram implements api.Program {
|
export class NgtscProgram implements api.Program {
|
||||||
@ -107,8 +108,9 @@ export class NgtscProgram implements api.Program {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const flatModuleId = options.flatModuleId || null;
|
const flatModuleId = options.flatModuleId || null;
|
||||||
|
const flatModuleOutFile = normalizeSeparators(options.flatModuleOutFile);
|
||||||
this.flatIndexGenerator =
|
this.flatIndexGenerator =
|
||||||
new FlatIndexGenerator(entryPoint, options.flatModuleOutFile, flatModuleId);
|
new FlatIndexGenerator(entryPoint, flatModuleOutFile, flatModuleId);
|
||||||
generators.push(this.flatIndexGenerator);
|
generators.push(this.flatIndexGenerator);
|
||||||
rootFiles.push(this.flatIndexGenerator.flatIndexPath);
|
rootFiles.push(this.flatIndexGenerator.flatIndexPath);
|
||||||
}
|
}
|
||||||
|
@ -1610,6 +1610,17 @@ describe('ngtsc behavioral tests', () => {
|
|||||||
expect(dtsContents).toContain('/// <amd-module name="@mymodule" />');
|
expect(dtsContents).toContain('/// <amd-module name="@mymodule" />');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate a proper flat module index file when nested', () => {
|
||||||
|
env.tsconfig({
|
||||||
|
'flatModuleOutFile': './public-api/index.js',
|
||||||
|
});
|
||||||
|
|
||||||
|
env.write('test.ts', `export const SOME_EXPORT = 'some-export'`);
|
||||||
|
env.driveMain();
|
||||||
|
|
||||||
|
expect(env.getContents('./public-api/index.js')).toContain(`export * from '../test';`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should report an error when a flat module index is requested but no entrypoint can be determined',
|
it('should report an error when a flat module index is requested but no entrypoint can be determined',
|
||||||
() => {
|
() => {
|
||||||
env.tsconfig({'flatModuleOutFile': 'flat.js'});
|
env.tsconfig({'flatModuleOutFile': 'flat.js'});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user