fix(ivy): ngcc - do not copy declaration files into bundle clone (#30020)

Previously, all of a program's files would be copied into the __ivy_ngcc__
folder where ngcc then writes its modifications into. The set of source files
in a program however is much larger than the source files contained within
the entry-point of interest, so many more files were copied than necessary.
Even worse, it may occur that an unrelated file in the program would collide
with an already existing source file, resulting in incorrectly overwriting
a file with unrelated content. This behavior has actually been observed
with @angular/animations and @angular/platform-browser/animations, where
the former package would overwrite declaration files of the latter package.

This commit fixes the issue by only copying relevant source files when cloning
a bundle's content into __ivy_ngcc__.

Fixes #29960

PR Close #30020
This commit is contained in:
JoostK 2019-04-22 00:57:55 +02:00 committed by Ben Lesh
parent 5a07aa484d
commit 8cba4e1f6b
2 changed files with 24 additions and 7 deletions

View File

@ -43,10 +43,12 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter {
protected copyBundle(
bundle: EntryPointBundle, entryPointPath: AbsoluteFsPath, newDir: AbsoluteFsPath) {
bundle.src.program.getSourceFiles().forEach(sourceFile => {
const relativePath = relative(entryPointPath, sourceFile.fileName);
const newFilePath = join(newDir, relativePath);
mkdir('-p', dirname(newFilePath));
cp(sourceFile.fileName, newFilePath);
if (!sourceFile.isDeclarationFile) {
const relativePath = relative(entryPointPath, sourceFile.fileName);
const newFilePath = join(newDir, relativePath);
mkdir('-p', dirname(newFilePath));
cp(sourceFile.fileName, newFilePath);
}
});
}

View File

@ -52,7 +52,7 @@ function createMockFileSystem() {
'lib': {
'esm5.js': 'export function FooB() {}',
'es2015': {
'index.js': 'import {FooB} from "./foo";',
'index.js': 'import {FooB} from "./foo"; import * from "other";',
'foo.js': 'export class FooB {}',
},
},
@ -61,6 +61,11 @@ function createMockFileSystem() {
'index.metadata.json': '...',
}
},
'/node_modules/other': {
'package.json': '{"module": "./esm5.js", "typings": "./index.d.ts"}',
'index.d.ts': 'export declare class OtherClass {}',
'esm5.js': 'export class OtherClass {}',
},
});
}
@ -250,9 +255,19 @@ describe('NewEntryPointFileWriter', () => {
expect(readFileSync('/node_modules/test/lib/es2015/foo.js', 'utf8'))
.toEqual('export class FooB {}');
expect(readFileSync('/node_modules/test/__ivy_ngcc__/lib/es2015/index.js', 'utf8'))
.toEqual('import {FooB} from "./foo";');
.toEqual('import {FooB} from "./foo"; import * from "other";');
expect(readFileSync('/node_modules/test/lib/es2015/index.js', 'utf8'))
.toEqual('import {FooB} from "./foo";');
.toEqual('import {FooB} from "./foo"; import * from "other";');
});
it('should not copy declaration files outside of the entry-point', () => {
fileWriter.writeBundle(entryPoint, esm2015bundle, [
{
path: '/node_modules/test/lib/es2015/foo.js',
contents: 'export class FooB {} // MODIFIED'
},
]);
expect(existsSync('/node_modules/test/other/index.d.ts')).toEqual(false);
});
it('should update the package.json properties', () => {