From 2463548fa7559053ec5488d32cd184a239502871 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 2 Apr 2020 11:03:11 +0100 Subject: [PATCH] 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 --- .../ngcc/src/packages/entry_point.ts | 20 ++++++++++++++----- .../ngcc/test/packages/entry_point_spec.ts | 16 +++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/compiler-cli/ngcc/src/packages/entry_point.ts b/packages/compiler-cli/ngcc/src/packages/entry_point.ts index cc74e8e82a..7a8097c79c 100644 --- a/packages/compiler-cli/ngcc/src/packages/entry_point.ts +++ b/packages/compiler-cli/ngcc/src/packages/entry_point.ts @@ -199,7 +199,7 @@ export function getEntryPointFormat( return undefined; } const pathToMain = join(entryPoint.path, mainFile); - return isUmdModule(fs, pathToMain) ? 'umd' : 'commonjs'; + return sniffModuleFormat(fs, pathToMain); case 'module': return 'esm5'; 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']); if (resolvedPath === null) { - return false; + return undefined; } + const sourceFile = ts.createSourceFile(sourceFilePath, fs.readFile(resolvedPath), ts.ScriptTarget.ES5); - return sourceFile.statements.length > 0 && - parseStatementForUmdModule(sourceFile.statements[0]) !== null; + if (sourceFile.statements.length === 0) { + return undefined; + } + if (ts.isExternalModule(sourceFile)) { + return 'esm5'; + } else if (parseStatementForUmdModule(sourceFile.statements[0]) !== null) { + return 'umd'; + } else { + return 'commonjs'; + } } function mergeConfigAndPackageJson( diff --git a/packages/compiler-cli/ngcc/test/packages/entry_point_spec.ts b/packages/compiler-cli/ngcc/test/packages/entry_point_spec.ts index 3ac8b1f32c..c5b8e143f0 100644 --- a/packages/compiler-cli/ngcc/test/packages/entry_point_spec.ts +++ b/packages/compiler-cli/ngcc/test/packages/entry_point_spec.ts @@ -425,6 +425,22 @@ runInEachFileSystem(() => { 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', () => { loadTestFiles([{ name: _(