fix(ngcc): sniff `main` property for ESM5 format (#36396)

Previously, `main` was only checked for `umd` or `commonjs`
formats. Now if there are `import` or `export` statements in the
source file it will be deemed to be in `esm5` format.

Fixes #35788

PR Close #36396
This commit is contained in:
Pete Bacon Darwin 2020-04-02 11:03:11 +01:00 committed by Kara Erickson
parent 1140bbc25c
commit 2463548fa7
2 changed files with 31 additions and 5 deletions

View File

@ -199,7 +199,7 @@ export function getEntryPointFormat(
return undefined; return undefined;
} }
const pathToMain = join(entryPoint.path, mainFile); const pathToMain = join(entryPoint.path, mainFile);
return isUmdModule(fs, pathToMain) ? 'umd' : 'commonjs'; return sniffModuleFormat(fs, pathToMain);
case 'module': case 'module':
return 'esm5'; return 'esm5';
default: default:
@ -226,15 +226,25 @@ function loadEntryPointPackage(
} }
} }
function isUmdModule(fs: FileSystem, sourceFilePath: AbsoluteFsPath): boolean { function sniffModuleFormat(fs: FileSystem, sourceFilePath: AbsoluteFsPath): EntryPointFormat|
undefined {
const resolvedPath = resolveFileWithPostfixes(fs, sourceFilePath, ['', '.js', '/index.js']); const resolvedPath = resolveFileWithPostfixes(fs, sourceFilePath, ['', '.js', '/index.js']);
if (resolvedPath === null) { if (resolvedPath === null) {
return false; return undefined;
} }
const sourceFile = const sourceFile =
ts.createSourceFile(sourceFilePath, fs.readFile(resolvedPath), ts.ScriptTarget.ES5); ts.createSourceFile(sourceFilePath, fs.readFile(resolvedPath), ts.ScriptTarget.ES5);
return sourceFile.statements.length > 0 && if (sourceFile.statements.length === 0) {
parseStatementForUmdModule(sourceFile.statements[0]) !== null; return undefined;
}
if (ts.isExternalModule(sourceFile)) {
return 'esm5';
} else if (parseStatementForUmdModule(sourceFile.statements[0]) !== null) {
return 'umd';
} else {
return 'commonjs';
}
} }
function mergeConfigAndPackageJson( function mergeConfigAndPackageJson(

View File

@ -425,6 +425,22 @@ runInEachFileSystem(() => {
expect(getEntryPointFormat(fs, entryPoint, 'module')).toBe('esm5'); expect(getEntryPointFormat(fs, entryPoint, 'module')).toBe('esm5');
}); });
it('should return `esm5` for `main` if the file contains import or export statements', () => {
const name = _(
'/project/node_modules/some_package/valid_entry_point/bundles/valid_entry_point/index.js');
loadTestFiles([{name, contents: `import * as core from '@angular/core;`}]);
expect(getEntryPointFormat(fs, entryPoint, 'main')).toBe('esm5');
loadTestFiles([{name, contents: `import {Component} from '@angular/core;`}]);
expect(getEntryPointFormat(fs, entryPoint, 'main')).toBe('esm5');
loadTestFiles([{name, contents: `export function foo() {}`}]);
expect(getEntryPointFormat(fs, entryPoint, 'main')).toBe('esm5');
loadTestFiles([{name, contents: `export * from 'abc';`}]);
expect(getEntryPointFormat(fs, entryPoint, 'main')).toBe('esm5');
});
it('should return `umd` for `main` if the file contains a UMD wrapper function', () => { it('should return `umd` for `main` if the file contains a UMD wrapper function', () => {
loadTestFiles([{ loadTestFiles([{
name: _( name: _(