refactor(ivy): ngcc - implement abstract FileSystem (#29643)
This commit introduces a new interface, which abstracts access to the underlying `FileSystem`. There is initially one concrete implementation, `NodeJsFileSystem`, which is simply wrapping the `fs` library of NodeJs. Going forward, we can provide a `MockFileSystem` for test, which should allow us to stop using `mock-fs` for most of the unit tests. We could also implement a `CachedFileSystem` that may improve the performance of ngcc. PR Close #29643
This commit is contained in:

committed by
Andrew Kushnir

parent
1fd2cc6340
commit
16d7dde2ad
@ -6,12 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import {readFileSync} from 'fs';
|
||||
import * as mockFs from 'mock-fs';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {NodeJSFileSystem} from '../../src/file_system/node_js_file_system';
|
||||
import {hasBeenProcessed, markAsProcessed} from '../../src/packages/build_marker';
|
||||
import {EntryPoint} from '../../src/packages/entry_point';
|
||||
|
||||
function createMockFileSystem() {
|
||||
mockFs({
|
||||
@ -106,21 +106,24 @@ describe('Marker files', () => {
|
||||
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||
|
||||
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||
const fs = new NodeJSFileSystem();
|
||||
|
||||
markAsProcessed(fs, pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||
pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||
expect(pkg.__processed_by_ivy_ngcc__.esm5).toBeUndefined();
|
||||
|
||||
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'esm5');
|
||||
markAsProcessed(fs, pkg, COMMON_PACKAGE_PATH, 'esm5');
|
||||
pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||
expect(pkg.__processed_by_ivy_ngcc__.esm5).toEqual('0.0.0-PLACEHOLDER');
|
||||
});
|
||||
|
||||
it('should update the packageJson object in-place', () => {
|
||||
const fs = new NodeJSFileSystem();
|
||||
let pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||
markAsProcessed(fs, pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||
});
|
||||
});
|
||||
|
@ -12,6 +12,7 @@ import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
||||
import {EsmDependencyHost} from '../../src/dependencies/esm_dependency_host';
|
||||
import {ModuleResolver} from '../../src/dependencies/module_resolver';
|
||||
import {NodeJSFileSystem} from '../../src/file_system/node_js_file_system';
|
||||
import {EntryPoint} from '../../src/packages/entry_point';
|
||||
import {EntryPointFinder} from '../../src/packages/entry_point_finder';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
@ -22,12 +23,13 @@ describe('findEntryPoints()', () => {
|
||||
let resolver: DependencyResolver;
|
||||
let finder: EntryPointFinder;
|
||||
beforeEach(() => {
|
||||
const fs = new NodeJSFileSystem();
|
||||
resolver =
|
||||
new DependencyResolver(new MockLogger(), new EsmDependencyHost(new ModuleResolver()));
|
||||
new DependencyResolver(new MockLogger(), new EsmDependencyHost(fs, new ModuleResolver(fs)));
|
||||
spyOn(resolver, 'sortEntryPointsByDependency').and.callFake((entryPoints: EntryPoint[]) => {
|
||||
return {entryPoints, ignoredEntryPoints: [], ignoredDependencies: []};
|
||||
});
|
||||
finder = new EntryPointFinder(new MockLogger(), resolver);
|
||||
finder = new EntryPointFinder(fs, new MockLogger(), resolver);
|
||||
});
|
||||
beforeEach(createMockFileSystem);
|
||||
afterEach(restoreRealFileSystem);
|
||||
|
@ -6,24 +6,27 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/path';
|
||||
import {readFileSync} from 'fs';
|
||||
import * as mockFs from 'mock-fs';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {NodeJSFileSystem} from '../../src/file_system/node_js_file_system';
|
||||
import {getEntryPointInfo} from '../../src/packages/entry_point';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
|
||||
const _ = AbsoluteFsPath.fromUnchecked;
|
||||
|
||||
describe('getEntryPointInfo()', () => {
|
||||
beforeEach(createMockFileSystem);
|
||||
afterEach(restoreRealFileSystem);
|
||||
|
||||
const _ = AbsoluteFsPath.from;
|
||||
const SOME_PACKAGE = _('/some_package');
|
||||
|
||||
it('should return an object containing absolute paths to the formats of the specified entry-point',
|
||||
() => {
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/valid_entry_point'));
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint = getEntryPointInfo(
|
||||
fs, new MockLogger(), SOME_PACKAGE, _('/some_package/valid_entry_point'));
|
||||
expect(entryPoint).toEqual({
|
||||
name: 'some-package/valid_entry_point',
|
||||
package: SOME_PACKAGE,
|
||||
@ -35,21 +38,24 @@ describe('getEntryPointInfo()', () => {
|
||||
});
|
||||
|
||||
it('should return null if there is no package.json at the entry-point path', () => {
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/missing_package_json'));
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint = getEntryPointInfo(
|
||||
fs, new MockLogger(), SOME_PACKAGE, _('/some_package/missing_package_json'));
|
||||
expect(entryPoint).toBe(null);
|
||||
});
|
||||
|
||||
it('should return null if there is no typings or types field in the package.json', () => {
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/missing_typings'));
|
||||
getEntryPointInfo(fs, new MockLogger(), SOME_PACKAGE, _('/some_package/missing_typings'));
|
||||
expect(entryPoint).toBe(null);
|
||||
});
|
||||
|
||||
it('should return an object with `compiledByAngular` set to false if there is no metadata.json file next to the typing file',
|
||||
() => {
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/missing_metadata'));
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint = getEntryPointInfo(
|
||||
fs, new MockLogger(), SOME_PACKAGE, _('/some_package/missing_metadata'));
|
||||
expect(entryPoint).toEqual({
|
||||
name: 'some-package/missing_metadata',
|
||||
package: SOME_PACKAGE,
|
||||
@ -61,8 +67,9 @@ describe('getEntryPointInfo()', () => {
|
||||
});
|
||||
|
||||
it('should work if the typings field is named `types', () => {
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint = getEntryPointInfo(
|
||||
new MockLogger(), SOME_PACKAGE, _('/some_package/types_rather_than_typings'));
|
||||
fs, new MockLogger(), SOME_PACKAGE, _('/some_package/types_rather_than_typings'));
|
||||
expect(entryPoint).toEqual({
|
||||
name: 'some-package/types_rather_than_typings',
|
||||
package: SOME_PACKAGE,
|
||||
@ -74,8 +81,9 @@ describe('getEntryPointInfo()', () => {
|
||||
});
|
||||
|
||||
it('should work with Angular Material style package.json', () => {
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/material_style'));
|
||||
getEntryPointInfo(fs, new MockLogger(), SOME_PACKAGE, _('/some_package/material_style'));
|
||||
expect(entryPoint).toEqual({
|
||||
name: 'some_package/material_style',
|
||||
package: SOME_PACKAGE,
|
||||
@ -87,8 +95,9 @@ describe('getEntryPointInfo()', () => {
|
||||
});
|
||||
|
||||
it('should return null if the package.json is not valid JSON', () => {
|
||||
const entryPoint =
|
||||
getEntryPointInfo(new MockLogger(), SOME_PACKAGE, _('/some_package/unexpected_symbols'));
|
||||
const fs = new NodeJSFileSystem();
|
||||
const entryPoint = getEntryPointInfo(
|
||||
fs, new MockLogger(), SOME_PACKAGE, _('/some_package/unexpected_symbols'));
|
||||
expect(entryPoint).toBe(null);
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user