diff --git a/packages/compiler-cli/ngcc/src/writing/file_writer.ts b/packages/compiler-cli/ngcc/src/writing/file_writer.ts index 025d321cdc..9b2e27faf4 100644 --- a/packages/compiler-cli/ngcc/src/writing/file_writer.ts +++ b/packages/compiler-cli/ngcc/src/writing/file_writer.ts @@ -6,7 +6,8 @@ * 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 {EntryPointJsonProperty} from '../packages/entry_point'; +import {AbsoluteFsPath} from '../../../src/ngtsc/file_system'; +import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point'; import {EntryPointBundle} from '../packages/entry_point_bundle'; import {FileToWrite} from '../rendering/utils'; @@ -17,4 +18,18 @@ export interface FileWriter { writeBundle( bundle: EntryPointBundle, transformedFiles: FileToWrite[], formatProperties: EntryPointJsonProperty[]): void; + + /** + * Revert the changes to an entry-point processed for the specified format-properties by the same + * `FileWriter` implementation. + * + * @param entryPoint The entry-point to revert. + * @param transformedFilePaths The original paths of the transformed files. (The transformed files + * may be written at the same or a different location, depending on the `FileWriter` + * implementation.) + * @param formatProperties The format-properties pointing to the entry-point. + */ + revertBundle( + entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], + formatProperties: EntryPointJsonProperty[]): void; } diff --git a/packages/compiler-cli/ngcc/src/writing/in_place_file_writer.ts b/packages/compiler-cli/ngcc/src/writing/in_place_file_writer.ts index 52c6022053..22263d456b 100644 --- a/packages/compiler-cli/ngcc/src/writing/in_place_file_writer.ts +++ b/packages/compiler-cli/ngcc/src/writing/in_place_file_writer.ts @@ -5,9 +5,9 @@ * 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 {absoluteFrom, dirname, FileSystem} from '../../../src/ngtsc/file_system'; +import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem} from '../../../src/ngtsc/file_system'; import {Logger} from '../logging/logger'; -import {EntryPointJsonProperty} from '../packages/entry_point'; +import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point'; import {EntryPointBundle} from '../packages/entry_point_bundle'; import {FileToWrite} from '../rendering/utils'; @@ -29,6 +29,14 @@ export class InPlaceFileWriter implements FileWriter { transformedFiles.forEach(file => this.writeFileAndBackup(file)); } + revertBundle( + _entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], + _formatProperties: EntryPointJsonProperty[]): void { + for (const filePath of transformedFilePaths) { + this.revertFileAndBackup(filePath); + } + } + protected writeFileAndBackup(file: FileToWrite): void { this.fs.ensureDir(dirname(file.path)); const backPath = absoluteFrom(`${file.path}${NGCC_BACKUP_EXTENSION}`); @@ -51,4 +59,15 @@ export class InPlaceFileWriter implements FileWriter { this.fs.writeFile(file.path, file.contents); } } + + protected revertFileAndBackup(filePath: AbsoluteFsPath): void { + if (this.fs.exists(filePath)) { + this.fs.removeFile(filePath); + + const backPath = absoluteFrom(`${filePath}${NGCC_BACKUP_EXTENSION}`); + if (this.fs.exists(backPath)) { + this.fs.moveFile(backPath, filePath); + } + } + } } diff --git a/packages/compiler-cli/ngcc/src/writing/new_entry_point_file_writer.ts b/packages/compiler-cli/ngcc/src/writing/new_entry_point_file_writer.ts index 40c8fa2c73..d6cfd344ea 100644 --- a/packages/compiler-cli/ngcc/src/writing/new_entry_point_file_writer.ts +++ b/packages/compiler-cli/ngcc/src/writing/new_entry_point_file_writer.ts @@ -45,6 +45,27 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter { this.updatePackageJson(entryPoint, formatProperties, ngccFolder); } + revertBundle( + entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], + formatProperties: EntryPointJsonProperty[]): void { + // IMPLEMENTATION NOTE: + // + // The changes made by `copyBundle()` are not reverted here. The non-transformed copied files + // are identical to the original ones and they will be overwritten when re-processing the + // entry-point anyway. + // + // This way, we avoid the overhead of having to inform the master process about all source files + // being copied in `copyBundle()`. + + // Revert the transformed files. + for (const filePath of transformedFilePaths) { + this.revertFile(filePath, entryPoint.package); + } + + // Revert any changes to `package.json`. + this.revertPackageJson(entryPoint, formatProperties); + } + protected copyBundle( bundle: EntryPointBundle, packagePath: AbsoluteFsPath, ngccFolder: AbsoluteFsPath) { bundle.src.program.getSourceFiles().forEach(sourceFile => { @@ -71,6 +92,17 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter { } } + protected revertFile(filePath: AbsoluteFsPath, packagePath: AbsoluteFsPath): void { + if (isDtsPath(filePath.replace(/\.map$/, ''))) { + // This is either `.d.ts` or `.d.ts.map` file + super.revertFileAndBackup(filePath); + } else if (this.fs.exists(filePath)) { + const relativePath = relative(packagePath, filePath); + const newFilePath = join(packagePath, NGCC_DIRECTORY, relativePath); + this.fs.removeFile(newFilePath); + } + } + protected updatePackageJson( entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[], ngccFolder: AbsoluteFsPath) { @@ -105,4 +137,25 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter { update.writeChanges(packageJsonPath, packageJson); } + + protected revertPackageJson(entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[]) { + if (formatProperties.length === 0) { + // No format properties need reverting. + return; + } + + const packageJson = entryPoint.packageJson; + const packageJsonPath = join(entryPoint.path, 'package.json'); + + // Revert all properties in `package.json` (both in memory and on disk). + // Since `updatePackageJson()` only adds properties, it is safe to just remove them (if they + // exist). + const update = this.pkgJsonUpdater.createUpdate(); + + for (const formatProperty of formatProperties) { + update.addChange([`${formatProperty}${NGCC_PROPERTY_EXTENSION}`], undefined); + } + + update.writeChanges(packageJsonPath, packageJson); + } } diff --git a/packages/compiler-cli/ngcc/test/writing/in_place_file_writer_spec.ts b/packages/compiler-cli/ngcc/test/writing/in_place_file_writer_spec.ts index 0b3d249bd3..22feed4ec1 100644 --- a/packages/compiler-cli/ngcc/test/writing/in_place_file_writer_spec.ts +++ b/packages/compiler-cli/ngcc/test/writing/in_place_file_writer_spec.ts @@ -8,8 +8,9 @@ import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; import {loadTestFiles} from '../../../test/helpers'; +import {EntryPoint} from '../../src/packages/entry_point'; import {EntryPointBundle} from '../../src/packages/entry_point_bundle'; -import {InPlaceFileWriter} from '../../src/writing/in_place_file_writer'; +import {InPlaceFileWriter, NGCC_BACKUP_EXTENSION} from '../../src/writing/in_place_file_writer'; import {MockLogger} from '../helpers/mock_logger'; runInEachFileSystem(() => { @@ -29,77 +30,144 @@ runInEachFileSystem(() => { ]); }); - it('should write all the FileInfo to the disk', () => { - const fs = getFileSystem(); - const logger = new MockLogger(); - const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); - fileWriter.writeBundle({} as EntryPointBundle, [ - {path: _('/package/path/top-level.js'), contents: 'MODIFIED TOP LEVEL'}, - {path: _('/package/path/folder-1/file-1.js'), contents: 'MODIFIED FILE 1'}, - {path: _('/package/path/folder-2/file-4.js'), contents: 'MODIFIED FILE 4'}, - {path: _('/package/path/folder-3/file-5.js'), contents: 'NEW FILE 5'}, - ]); - expect(fs.readFile(_('/package/path/top-level.js'))).toEqual('MODIFIED TOP LEVEL'); - expect(fs.readFile(_('/package/path/folder-1/file-1.js'))).toEqual('MODIFIED FILE 1'); - expect(fs.readFile(_('/package/path/folder-1/file-2.js'))).toEqual('ORIGINAL FILE 2'); - expect(fs.readFile(_('/package/path/folder-2/file-3.js'))).toEqual('ORIGINAL FILE 3'); - expect(fs.readFile(_('/package/path/folder-2/file-4.js'))).toEqual('MODIFIED FILE 4'); - expect(fs.readFile(_('/package/path/folder-3/file-5.js'))).toEqual('NEW FILE 5'); + describe('writeBundle()', () => { + it('should write all the FileInfo to the disk', () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + fileWriter.writeBundle({} as EntryPointBundle, [ + {path: _('/package/path/top-level.js'), contents: 'MODIFIED TOP LEVEL'}, + {path: _('/package/path/folder-1/file-1.js'), contents: 'MODIFIED FILE 1'}, + {path: _('/package/path/folder-2/file-4.js'), contents: 'MODIFIED FILE 4'}, + {path: _('/package/path/folder-3/file-5.js'), contents: 'NEW FILE 5'}, + ]); + expect(fs.readFile(_('/package/path/top-level.js'))).toEqual('MODIFIED TOP LEVEL'); + expect(fs.readFile(_('/package/path/folder-1/file-1.js'))).toEqual('MODIFIED FILE 1'); + expect(fs.readFile(_('/package/path/folder-1/file-2.js'))).toEqual('ORIGINAL FILE 2'); + expect(fs.readFile(_('/package/path/folder-2/file-3.js'))).toEqual('ORIGINAL FILE 3'); + expect(fs.readFile(_('/package/path/folder-2/file-4.js'))).toEqual('MODIFIED FILE 4'); + expect(fs.readFile(_('/package/path/folder-3/file-5.js'))).toEqual('NEW FILE 5'); + }); + + it('should create backups of all files that previously existed', () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + fileWriter.writeBundle({} as EntryPointBundle, [ + {path: _('/package/path/top-level.js'), contents: 'MODIFIED TOP LEVEL'}, + {path: _('/package/path/folder-1/file-1.js'), contents: 'MODIFIED FILE 1'}, + {path: _('/package/path/folder-2/file-4.js'), contents: 'MODIFIED FILE 4'}, + {path: _('/package/path/folder-3/file-5.js'), contents: 'NEW FILE 5'}, + ]); + expect(fs.readFile(_('/package/path/top-level.js.__ivy_ngcc_bak'))) + .toEqual('ORIGINAL TOP LEVEL'); + expect(fs.readFile(_('/package/path/folder-1/file-1.js.__ivy_ngcc_bak'))) + .toEqual('ORIGINAL FILE 1'); + expect(fs.exists(_('/package/path/folder-1/file-2.js.__ivy_ngcc_bak'))).toBe(false); + expect(fs.exists(_('/package/path/folder-2/file-3.js.__ivy_ngcc_bak'))).toBe(false); + expect(fs.readFile(_('/package/path/folder-2/file-4.js.__ivy_ngcc_bak'))) + .toEqual('ORIGINAL FILE 4'); + expect(fs.exists(_('/package/path/folder-3/file-5.js.__ivy_ngcc_bak'))).toBe(false); + }); + + it('should throw an error if the backup file already exists and errorOnFailedEntryPoint is true', + () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + const absoluteBackupPath = _('/package/path/already-backed-up.js'); + expect( + () => fileWriter.writeBundle( + {} as EntryPointBundle, + [{path: absoluteBackupPath, contents: 'MODIFIED BACKED UP'}])) + .toThrowError(`Tried to overwrite ${ + absoluteBackupPath}.__ivy_ngcc_bak with an ngcc back up file, which is disallowed.`); + }); + + it('should log an error, and skip writing the file, if the backup file already exists and errorOnFailedEntryPoint is false', + () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = + new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ false); + const absoluteBackupPath = _('/package/path/already-backed-up.js'); + fileWriter.writeBundle( + {} as EntryPointBundle, + [{path: absoluteBackupPath, contents: 'MODIFIED BACKED UP'}]); + // Should not have written the new file nor overwritten the backup file. + expect(fs.readFile(absoluteBackupPath)).toEqual('ORIGINAL ALREADY BACKED UP'); + expect(fs.readFile(_(absoluteBackupPath + '.__ivy_ngcc_bak'))).toEqual('BACKED UP'); + expect(logger.logs.error).toEqual([[ + `Tried to write ${ + absoluteBackupPath}.__ivy_ngcc_bak with an ngcc back up file but it already exists so not writing, nor backing up, ${ + absoluteBackupPath}.\n` + + `This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` + + `You should check other entry-points in this package and set up a config to ignore any that you are not using.` + ]]); + }); }); - it('should create backups of all files that previously existed', () => { - const fs = getFileSystem(); - const logger = new MockLogger(); - const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); - fileWriter.writeBundle({} as EntryPointBundle, [ - {path: _('/package/path/top-level.js'), contents: 'MODIFIED TOP LEVEL'}, - {path: _('/package/path/folder-1/file-1.js'), contents: 'MODIFIED FILE 1'}, - {path: _('/package/path/folder-2/file-4.js'), contents: 'MODIFIED FILE 4'}, - {path: _('/package/path/folder-3/file-5.js'), contents: 'NEW FILE 5'}, - ]); - expect(fs.readFile(_('/package/path/top-level.js.__ivy_ngcc_bak'))) - .toEqual('ORIGINAL TOP LEVEL'); - expect(fs.readFile(_('/package/path/folder-1/file-1.js.__ivy_ngcc_bak'))) - .toEqual('ORIGINAL FILE 1'); - expect(fs.exists(_('/package/path/folder-1/file-2.js.__ivy_ngcc_bak'))).toBe(false); - expect(fs.exists(_('/package/path/folder-2/file-3.js.__ivy_ngcc_bak'))).toBe(false); - expect(fs.readFile(_('/package/path/folder-2/file-4.js.__ivy_ngcc_bak'))) - .toEqual('ORIGINAL FILE 4'); - expect(fs.exists(_('/package/path/folder-3/file-5.js.__ivy_ngcc_bak'))).toBe(false); + describe('revertBundle()', () => { + it('should revert the written files (and their backups)', () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + + const filePath1 = _('/package/path/folder-1/file-1.js'); + const filePath2 = _('/package/path/folder-1/file-2.js'); + const fileBackupPath1 = _(`/package/path/folder-1/file-1.js${NGCC_BACKUP_EXTENSION}`); + const fileBackupPath2 = _(`/package/path/folder-1/file-2.js${NGCC_BACKUP_EXTENSION}`); + + fileWriter.writeBundle({} as EntryPointBundle, [ + {path: filePath1, contents: 'MODIFIED FILE 1'}, + {path: filePath2, contents: 'MODIFIED FILE 2'}, + ]); + expect(fs.readFile(filePath1)).toBe('MODIFIED FILE 1'); + expect(fs.readFile(filePath2)).toBe('MODIFIED FILE 2'); + expect(fs.readFile(fileBackupPath1)).toBe('ORIGINAL FILE 1'); + expect(fs.readFile(fileBackupPath2)).toBe('ORIGINAL FILE 2'); + + fileWriter.revertBundle({} as EntryPoint, [filePath1, filePath2], []); + expect(fs.readFile(filePath1)).toBe('ORIGINAL FILE 1'); + expect(fs.readFile(filePath2)).toBe('ORIGINAL FILE 2'); + expect(fs.exists(fileBackupPath1)).toBeFalse(); + expect(fs.exists(fileBackupPath2)).toBeFalse(); + }); + + it('should just remove the written files if there is no backup', () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + + const filePath = _('/package/path/folder-1/file-1.js'); + const fileBackupPath = _(`/package/path/folder-1/file-1.js${NGCC_BACKUP_EXTENSION}`); + + fileWriter.writeBundle({} as EntryPointBundle, [ + {path: filePath, contents: 'MODIFIED FILE 1'}, + ]); + fs.removeFile(fileBackupPath); + expect(fs.readFile(filePath)).toBe('MODIFIED FILE 1'); + expect(fs.exists(fileBackupPath)).toBeFalse(); + + fileWriter.revertBundle({} as EntryPoint, [filePath], []); + expect(fs.exists(filePath)).toBeFalse(); + expect(fs.exists(fileBackupPath)).toBeFalse(); + }); + + it('should do nothing if the file does not exist', () => { + const fs = getFileSystem(); + const logger = new MockLogger(); + const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); + + const filePath = _('/package/path/non-existent.js'); + const fileBackupPath = _(`/package/path/non-existent.js${NGCC_BACKUP_EXTENSION}`); + + fs.writeFile(fileBackupPath, 'BACKUP WITHOUT FILE'); + fileWriter.revertBundle({} as EntryPoint, [filePath], []); + + expect(fs.exists(filePath)).toBeFalse(); + expect(fs.readFile(fileBackupPath)).toBe('BACKUP WITHOUT FILE'); + }); }); - - it('should throw an error if the backup file already exists and errorOnFailedEntryPoint is true', - () => { - const fs = getFileSystem(); - const logger = new MockLogger(); - const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ true); - const absoluteBackupPath = _('/package/path/already-backed-up.js'); - expect( - () => fileWriter.writeBundle( - {} as EntryPointBundle, - [{path: absoluteBackupPath, contents: 'MODIFIED BACKED UP'}])) - .toThrowError(`Tried to overwrite ${ - absoluteBackupPath}.__ivy_ngcc_bak with an ngcc back up file, which is disallowed.`); - }); - - it('should log an error, and skip writing the file, if the backup file already exists and errorOnFailedEntryPoint is false', - () => { - const fs = getFileSystem(); - const logger = new MockLogger(); - const fileWriter = new InPlaceFileWriter(fs, logger, /* errorOnFailedEntryPoint */ false); - const absoluteBackupPath = _('/package/path/already-backed-up.js'); - fileWriter.writeBundle( - {} as EntryPointBundle, [{path: absoluteBackupPath, contents: 'MODIFIED BACKED UP'}]); - // Should not have written the new file nor overwritten the backup file. - expect(fs.readFile(absoluteBackupPath)).toEqual('ORIGINAL ALREADY BACKED UP'); - expect(fs.readFile(_(absoluteBackupPath + '.__ivy_ngcc_bak'))).toEqual('BACKED UP'); - expect(logger.logs.error).toEqual([[ - `Tried to write ${ - absoluteBackupPath}.__ivy_ngcc_bak with an ngcc back up file but it already exists so not writing, nor backing up, ${ - absoluteBackupPath}.\n` + - `This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` + - `You should check other entry-points in this package and set up a config to ignore any that you are not using.` - ]]); - }); }); }); diff --git a/packages/compiler-cli/ngcc/test/writing/new_entry_point_file_writer_spec.ts b/packages/compiler-cli/ngcc/test/writing/new_entry_point_file_writer_spec.ts index 5f361cbb4e..640c3e1209 100644 --- a/packages/compiler-cli/ngcc/test/writing/new_entry_point_file_writer_spec.ts +++ b/packages/compiler-cli/ngcc/test/writing/new_entry_point_file_writer_spec.ts @@ -5,7 +5,7 @@ * 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 {absoluteFrom, FileSystem, getFileSystem} from '../../../src/ngtsc/file_system'; +import {absoluteFrom, FileSystem, getFileSystem, join} from '../../../src/ngtsc/file_system'; import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; import {loadTestFiles} from '../../../test/helpers'; import {NgccConfiguration} from '../../src/packages/configuration'; @@ -32,7 +32,6 @@ runInEachFileSystem(() => { fs = getFileSystem(); logger = new MockLogger(); loadTestFiles([ - { name: _('/node_modules/test/package.json'), contents: ` @@ -494,6 +493,142 @@ runInEachFileSystem(() => { expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/typings/index.d.ts'))).toBe(false); }); }); + + describe('revertFile()', () => { + beforeEach(() => { + fileWriter = new NewEntryPointFileWriter( + fs, logger, /* errorOnFailedEntryPoint */ true, new DirectPackageJsonUpdater(fs)); + const config = new NgccConfiguration(fs, _('/')); + const result = getEntryPointInfo( + fs, config, logger, _('/node_modules/test'), _('/node_modules/test'))!; + if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) { + return fail(`Expected an entry point but got ${result}`); + } + entryPoint = result; + esm5bundle = makeTestBundle(fs, entryPoint, 'module', 'esm5'); + }); + + it('should remove non-typings files', () => { + fileWriter.writeBundle( + esm5bundle, + [ + { + path: _('/node_modules/test/esm5.js'), + contents: 'export function FooTop() {} // MODIFIED', + }, + { + path: _('/node_modules/test/esm5.js.map'), + contents: 'MODIFIED MAPPING DATA', + }, + // Normally there will be no backup file. Write one here to ensure it is not removed. + { + path: _('/node_modules/test/esm5.js.__ivy_ngcc_bak'), + contents: 'NOT AN ACTUAL BACKUP', + }, + ], + ['module']); + + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js'))).toBeTrue(); + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js.map'))).toBeTrue(); + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js.__ivy_ngcc_bak'))).toBeTrue(); + + fileWriter.revertBundle( + esm5bundle.entryPoint, + [_('/node_modules/test/esm5.js'), _('/node_modules/test/esm5.js.map')], []); + + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js'))).toBeFalse(); + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js.map'))).toBeFalse(); + expect(fs.exists(_('/node_modules/test/__ivy_ngcc__/esm5.js.__ivy_ngcc_bak'))).toBeTrue(); + }); + + it('should revert written typings files (and their backups)', () => { + fileWriter.writeBundle( + esm5bundle, + [ + { + path: _('/node_modules/test/index.d.ts'), + contents: 'export declare class FooTop {} // MODIFIED' + }, + { + path: _('/node_modules/test/index.d.ts.map'), + contents: 'MODIFIED MAPPING DATA', + }, + ], + ['module']); + + expect(fs.readFile(_('/node_modules/test/index.d.ts'))) + .toBe('export declare class FooTop {} // MODIFIED'); + expect(fs.readFile(_('/node_modules/test/index.d.ts.__ivy_ngcc_bak'))) + .toBe('export declare class FooTop {}'); + expect(fs.readFile(_('/node_modules/test/index.d.ts.map'))).toBe('MODIFIED MAPPING DATA'); + expect(fs.readFile(_('/node_modules/test/index.d.ts.map.__ivy_ngcc_bak'))) + .toBe('ORIGINAL MAPPING DATA'); + + fileWriter.revertBundle( + esm5bundle.entryPoint, + [_('/node_modules/test/index.d.ts'), _('/node_modules/test/index.d.ts.map')], []); + + expect(fs.readFile(_('/node_modules/test/index.d.ts'))) + .toBe('export declare class FooTop {}'); + expect(fs.exists(_('/node_modules/test/index.d.ts.__ivy_ngcc_bak'))).toBeFalse(); + expect(fs.readFile(_('/node_modules/test/index.d.ts.map'))).toBe('ORIGINAL MAPPING DATA'); + expect(fs.exists(_('/node_modules/test/index.d.ts.map.__ivy_ngcc_bak'))).toBeFalse(); + }); + + it('should revert changes to `package.json`', () => { + const entryPoint = esm5bundle.entryPoint; + const packageJsonPath = join(entryPoint.package, 'package.json'); + + fileWriter.writeBundle( + esm5bundle, + [ + { + path: _('/node_modules/test/index.d.ts'), + contents: 'export declare class FooTop {} // MODIFIED' + }, + { + path: _('/node_modules/test/index.d.ts.map'), + contents: 'MODIFIED MAPPING DATA', + }, + ], + ['fesm5', 'module']); + const packageJsonFromFile1 = JSON.parse(fs.readFile(packageJsonPath)); + + expect(entryPoint.packageJson).toEqual(jasmine.objectContaining({ + fesm5_ivy_ngcc: '__ivy_ngcc__/esm5.js', + fesm5: './esm5.js', + module_ivy_ngcc: '__ivy_ngcc__/esm5.js', + module: './esm5.js', + })); + + expect(packageJsonFromFile1).toEqual(jasmine.objectContaining({ + fesm5_ivy_ngcc: '__ivy_ngcc__/esm5.js', + fesm5: './esm5.js', + module_ivy_ngcc: '__ivy_ngcc__/esm5.js', + module: './esm5.js', + })); + + fileWriter.revertBundle( + esm5bundle.entryPoint, + [_('/node_modules/test/index.d.ts'), _('/node_modules/test/index.d.ts.map')], + ['fesm5', 'module']); + const packageJsonFromFile2 = JSON.parse(fs.readFile(packageJsonPath)); + + expect(entryPoint.packageJson).toEqual(jasmine.objectContaining({ + fesm5: './esm5.js', + module: './esm5.js', + })); + expect(entryPoint.packageJson.fesm5_ivy_ngcc).toBeUndefined(); + expect(entryPoint.packageJson.module_ivy_ngcc).toBeUndefined(); + + expect(packageJsonFromFile2).toEqual(jasmine.objectContaining({ + fesm5: './esm5.js', + module: './esm5.js', + })); + expect(packageJsonFromFile2.fesm5_ivy_ngcc).toBeUndefined(); + expect(packageJsonFromFile2.module_ivy_ngcc).toBeUndefined(); + }); + }); }); function makeTestBundle(