refactor(ivy): ngcc - mark target entry-point as processed even if ngcc was a noop (#29092)
If `targetEntryPointPath` is provided to `mainNgcc` then we will now mark all the `propertiesToConsider` for that entry-point if we determine that it does not contain code that was compiled by Angular (for instance it has no `...metadata.json` file). The commit also renames `__modified_by_ngcc__` to `__processed_by_ivy_ngcc__`, since there may be entry-points that are marked despite ngcc not actually compiling anything. PR Close #29092
This commit is contained in:
parent
083fb99033
commit
a827bc2e3a
|
@ -12,23 +12,23 @@ ivy-ngcc
|
||||||
# Did it add the appropriate build markers?
|
# Did it add the appropriate build markers?
|
||||||
|
|
||||||
# - esm2015
|
# - esm2015
|
||||||
grep '"__modified_by_ngcc__":[^}]*"esm2015":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"esm2015":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
|
|
||||||
# - fesm2015
|
# - fesm2015
|
||||||
grep '"__modified_by_ngcc__":[^}]*"fesm2015":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"fesm2015":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
grep '"__modified_by_ngcc__":[^}]*"es2015":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"es2015":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
|
|
||||||
# - esm5
|
# - esm5
|
||||||
grep '"__modified_by_ngcc__":[^}]*"esm5":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"esm5":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
|
|
||||||
# - fesm5
|
# - fesm5
|
||||||
grep '"__modified_by_ngcc__":[^}]*"module":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"module":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
grep '"__modified_by_ngcc__":[^}]*"fesm5":"' node_modules/@angular/common/package.json
|
grep '"__processed_by_ivy_ngcc__":[^}]*"fesm5":"' node_modules/@angular/common/package.json
|
||||||
if [[ $? != 0 ]]; then exit 1; fi
|
if [[ $? != 0 ]]; then exit 1; fi
|
||||||
|
|
||||||
# Did it replace the PRE_R3 markers correctly?
|
# Did it replace the PRE_R3 markers correctly?
|
||||||
|
|
|
@ -6,5 +6,12 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {hasBeenProcessed as _hasBeenProcessed} from './src/packages/build_marker';
|
||||||
|
import {EntryPointJsonProperty, EntryPointPackageJson} from './src/packages/entry_point';
|
||||||
|
|
||||||
export {NgccOptions, mainNgcc as process} from './src/main';
|
export {NgccOptions, mainNgcc as process} from './src/main';
|
||||||
export {hasBeenProcessed} from './src/packages/build_marker';
|
|
||||||
|
export function hasBeenProcessed(packageJson: object, format: string) {
|
||||||
|
// We are wrapping this function to hide the internal types.
|
||||||
|
return _hasBeenProcessed(packageJson as EntryPointPackageJson, format as EntryPointJsonProperty);
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {resolve} from 'canonical-path';
|
import {resolve} from 'canonical-path';
|
||||||
|
import {readFileSync} from 'fs';
|
||||||
|
|
||||||
import {AbsoluteFsPath, PathSegment} from '../../src/ngtsc/path';
|
import {AbsoluteFsPath} from '../../src/ngtsc/path';
|
||||||
|
|
||||||
import {checkMarker, writeMarker} from './packages/build_marker';
|
import {hasBeenProcessed, markAsProcessed} from './packages/build_marker';
|
||||||
import {DependencyHost} from './packages/dependency_host';
|
import {DependencyHost} from './packages/dependency_host';
|
||||||
import {DependencyResolver} from './packages/dependency_resolver';
|
import {DependencyResolver} from './packages/dependency_resolver';
|
||||||
import {EntryPointFormat, EntryPointJsonProperty, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
|
import {EntryPointFormat, EntryPointJsonProperty, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
|
||||||
|
@ -67,22 +68,41 @@ export function mainNgcc({basePath, targetEntryPointPath,
|
||||||
undefined;
|
undefined;
|
||||||
const {entryPoints} =
|
const {entryPoints} =
|
||||||
finder.findEntryPoints(AbsoluteFsPath.from(basePath), absoluteTargetEntryPointPath);
|
finder.findEntryPoints(AbsoluteFsPath.from(basePath), absoluteTargetEntryPointPath);
|
||||||
entryPoints.forEach(entryPoint => {
|
|
||||||
|
|
||||||
|
if (absoluteTargetEntryPointPath && entryPoints.every(entryPoint => {
|
||||||
|
return entryPoint.path !== absoluteTargetEntryPointPath;
|
||||||
|
})) {
|
||||||
|
// If we get here, then the requested entry-point did not contain anything compiled by
|
||||||
|
// the old Angular compiler. Therefore there is nothing for ngcc to do.
|
||||||
|
// So mark all formats in this entry-point as processed so that clients of ngcc can avoid
|
||||||
|
// triggering ngcc for this entry-point in the future.
|
||||||
|
const packageJsonPath =
|
||||||
|
AbsoluteFsPath.from(resolve(absoluteTargetEntryPointPath, 'package.json'));
|
||||||
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
||||||
|
propertiesToConsider.forEach(formatProperty => {
|
||||||
|
if (packageJson[formatProperty])
|
||||||
|
markAsProcessed(packageJson, packageJsonPath, formatProperty as EntryPointJsonProperty);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entryPoints.forEach(entryPoint => {
|
||||||
// Are we compiling the Angular core?
|
// Are we compiling the Angular core?
|
||||||
const isCore = entryPoint.name === '@angular/core';
|
const isCore = entryPoint.name === '@angular/core';
|
||||||
|
|
||||||
const compiledFormats = new Set<string>();
|
const compiledFormats = new Set<string>();
|
||||||
|
const entryPointPackageJson = entryPoint.packageJson;
|
||||||
|
const entryPointPackageJsonPath = AbsoluteFsPath.from(resolve(entryPoint.path, 'package.json'));
|
||||||
|
|
||||||
for (let i = 0; i < propertiesToConsider.length; i++) {
|
for (let i = 0; i < propertiesToConsider.length; i++) {
|
||||||
const property = propertiesToConsider[i] as EntryPointJsonProperty;
|
const property = propertiesToConsider[i] as EntryPointJsonProperty;
|
||||||
const formatPath = entryPoint.packageJson[property];
|
const formatPath = entryPointPackageJson[property];
|
||||||
const format = getEntryPointFormat(property);
|
const format = getEntryPointFormat(property);
|
||||||
|
|
||||||
// No format then this property is not supposed to be compiled.
|
// No format then this property is not supposed to be compiled.
|
||||||
if (!formatPath || !format || SUPPORTED_FORMATS.indexOf(format) === -1) continue;
|
if (!formatPath || !format || SUPPORTED_FORMATS.indexOf(format) === -1) continue;
|
||||||
|
|
||||||
if (checkMarker(entryPoint, property)) {
|
if (hasBeenProcessed(entryPointPackageJson, property)) {
|
||||||
compiledFormats.add(formatPath);
|
compiledFormats.add(formatPath);
|
||||||
console.warn(`Skipping ${entryPoint.name} : ${property} (already compiled).`);
|
console.warn(`Skipping ${entryPoint.name} : ${property} (already compiled).`);
|
||||||
continue;
|
continue;
|
||||||
|
@ -109,7 +129,7 @@ export function mainNgcc({basePath, targetEntryPointPath,
|
||||||
// Either this format was just compiled or its underlying format was compiled because of a
|
// Either this format was just compiled or its underlying format was compiled because of a
|
||||||
// previous property.
|
// previous property.
|
||||||
if (compiledFormats.has(formatPath)) {
|
if (compiledFormats.has(formatPath)) {
|
||||||
writeMarker(entryPoint, property);
|
markAsProcessed(entryPointPackageJson, entryPointPackageJsonPath, property);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {resolve} from 'canonical-path';
|
|
||||||
import {writeFileSync} from 'fs';
|
import {writeFileSync} from 'fs';
|
||||||
|
|
||||||
import {EntryPoint, EntryPointJsonProperty} from './entry_point';
|
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||||
|
|
||||||
|
import {EntryPointJsonProperty, EntryPointPackageJson} from './entry_point';
|
||||||
|
|
||||||
export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
|
export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
|
||||||
|
|
||||||
|
@ -25,36 +26,19 @@ export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
|
||||||
* @throws Error if the `packageJson` property is not an object.
|
* @throws Error if the `packageJson` property is not an object.
|
||||||
* @throws Error if the entry-point has already been processed with a different ngcc version.
|
* @throws Error if the entry-point has already been processed with a different ngcc version.
|
||||||
*/
|
*/
|
||||||
export function hasBeenProcessed(packageJson: any, format: string): boolean {
|
export function hasBeenProcessed(
|
||||||
if (typeof packageJson !== 'object') {
|
packageJson: EntryPointPackageJson, format: EntryPointJsonProperty): boolean {
|
||||||
throw new Error('`packageJson` parameter is invalid. It parameter must be an object.');
|
if (!packageJson.__processed_by_ivy_ngcc__) {
|
||||||
}
|
|
||||||
if (!packageJson.__modified_by_ngcc__) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Object.keys(packageJson.__modified_by_ngcc__)
|
if (Object.keys(packageJson.__processed_by_ivy_ngcc__)
|
||||||
.some(property => packageJson.__modified_by_ngcc__[property] !== NGCC_VERSION)) {
|
.some(property => packageJson.__processed_by_ivy_ngcc__ ![property] !== NGCC_VERSION)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
'The ngcc compiler has changed since the last ngcc build.\n' +
|
||||||
'Please completely remove `node_modules` and try again.');
|
'Please completely remove `node_modules` and try again.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return packageJson.__modified_by_ngcc__[format] === NGCC_VERSION;
|
return packageJson.__processed_by_ivy_ngcc__[format] === NGCC_VERSION;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether there is a marker for the given entry-point and format property, indicating that
|
|
||||||
* the given bundle has already been processed.
|
|
||||||
* @param entryPoint the entry-point to check for a marker.
|
|
||||||
* @param format the property in the package.json of the format for which we are checking for a
|
|
||||||
* marker.
|
|
||||||
* @returns true if the entry-point and format have already been processed with this ngcc version.
|
|
||||||
* @throws Error if the entry-point and format have already been processed with a different ngcc
|
|
||||||
* version.
|
|
||||||
*/
|
|
||||||
export function checkMarker(entryPoint: EntryPoint, format: EntryPointJsonProperty): boolean {
|
|
||||||
const pkg = entryPoint.packageJson;
|
|
||||||
return hasBeenProcessed(pkg, format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,9 +48,10 @@ export function checkMarker(entryPoint: EntryPoint, format: EntryPointJsonProper
|
||||||
* @param entryPoint the entry-point to write a marker.
|
* @param entryPoint the entry-point to write a marker.
|
||||||
* @param format the property in the package.json of the format for which we are writing the marker.
|
* @param format the property in the package.json of the format for which we are writing the marker.
|
||||||
*/
|
*/
|
||||||
export function writeMarker(entryPoint: EntryPoint, format: EntryPointJsonProperty) {
|
export function markAsProcessed(
|
||||||
const pkg = entryPoint.packageJson;
|
packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath,
|
||||||
if (!pkg.__modified_by_ngcc__) pkg.__modified_by_ngcc__ = {};
|
format: EntryPointJsonProperty) {
|
||||||
pkg.__modified_by_ngcc__[format] = NGCC_VERSION;
|
if (!packageJson.__processed_by_ivy_ngcc__) packageJson.__processed_by_ivy_ngcc__ = {};
|
||||||
writeFileSync(resolve(entryPoint.path, 'package.json'), JSON.stringify(pkg), 'utf8');
|
packageJson.__processed_by_ivy_ngcc__[format] = NGCC_VERSION;
|
||||||
|
writeFileSync(packageJsonPath, JSON.stringify(packageJson), 'utf8');
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ interface PackageJsonFormatProperties {
|
||||||
*/
|
*/
|
||||||
export interface EntryPointPackageJson extends PackageJsonFormatProperties {
|
export interface EntryPointPackageJson extends PackageJsonFormatProperties {
|
||||||
name: string;
|
name: string;
|
||||||
__modified_by_ngcc__?: {[key: string]: string};
|
__processed_by_ivy_ngcc__?: {[key: string]: string};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EntryPointJsonProperty = keyof(PackageJsonFormatProperties);
|
export type EntryPointJsonProperty = keyof(PackageJsonFormatProperties);
|
||||||
|
|
|
@ -13,6 +13,7 @@ const Module = require('module');
|
||||||
|
|
||||||
import {mainNgcc} from '../../src/main';
|
import {mainNgcc} from '../../src/main';
|
||||||
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '../../../test/runfile_helpers';
|
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '../../../test/runfile_helpers';
|
||||||
|
import {EntryPointPackageJson} from '../../src/packages/entry_point';
|
||||||
|
|
||||||
describe('ngcc main()', () => {
|
describe('ngcc main()', () => {
|
||||||
beforeEach(createMockFileSystem);
|
beforeEach(createMockFileSystem);
|
||||||
|
@ -32,7 +33,7 @@ describe('ngcc main()', () => {
|
||||||
it('should only compile the given package entry-point (and its dependencies).', () => {
|
it('should only compile the given package entry-point (and its dependencies).', () => {
|
||||||
mainNgcc({basePath: '/node_modules', targetEntryPointPath: '@angular/common/http'});
|
mainNgcc({basePath: '/node_modules', targetEntryPointPath: '@angular/common/http'});
|
||||||
|
|
||||||
expect(loadPackage('@angular/common/http').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common/http').__processed_by_ivy_ngcc__).toEqual({
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -41,7 +42,7 @@ describe('ngcc main()', () => {
|
||||||
fesm2015: '0.0.0-PLACEHOLDER',
|
fesm2015: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
// * `common` is a dependency of `common/http`, so is compiled.
|
// * `common` is a dependency of `common/http`, so is compiled.
|
||||||
expect(loadPackage('@angular/common').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common').__processed_by_ivy_ngcc__).toEqual({
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -50,7 +51,7 @@ describe('ngcc main()', () => {
|
||||||
fesm2015: '0.0.0-PLACEHOLDER',
|
fesm2015: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
// * `core` is a dependency of `common`, so is compiled.
|
// * `core` is a dependency of `common`, so is compiled.
|
||||||
expect(loadPackage('@angular/core').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -60,7 +61,20 @@ describe('ngcc main()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// * `common/testing` is not a dependency of `common/http` so is not compiled.
|
// * `common/testing` is not a dependency of `common/http` so is not compiled.
|
||||||
expect(loadPackage('@angular/common/testing').__modified_by_ngcc__).toBeUndefined();
|
expect(loadPackage('@angular/common/testing').__processed_by_ivy_ngcc__).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark a non-Angular package target as processed', () => {
|
||||||
|
mainNgcc({basePath: '/node_modules', targetEntryPointPath: 'test-package'});
|
||||||
|
|
||||||
|
// `test-package` has no Angular but is marked as processed.
|
||||||
|
expect(loadPackage('test-package').__processed_by_ivy_ngcc__).toEqual({
|
||||||
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
|
});
|
||||||
|
|
||||||
|
// * `core` is a dependency of `test-package`, but it is not processed, since test-package
|
||||||
|
// was not processed.
|
||||||
|
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -75,22 +89,22 @@ describe('ngcc main()', () => {
|
||||||
// * the `main` property is UMD, which is not yet supported.
|
// * the `main` property is UMD, which is not yet supported.
|
||||||
// * none of the ES2015 formats are compiled as they are not on the `propertiesToConsider`
|
// * none of the ES2015 formats are compiled as they are not on the `propertiesToConsider`
|
||||||
// list.
|
// list.
|
||||||
expect(loadPackage('@angular/core').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common').__processed_by_ivy_ngcc__).toEqual({
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common/testing').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common/testing').__processed_by_ivy_ngcc__).toEqual({
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common/http').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common/http').__processed_by_ivy_ngcc__).toEqual({
|
||||||
esm5: '0.0.0-PLACEHOLDER',
|
esm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -109,19 +123,19 @@ describe('ngcc main()', () => {
|
||||||
// * In the Angular packages fesm5 and module have the same underlying format,
|
// * In the Angular packages fesm5 and module have the same underlying format,
|
||||||
// so both are marked as compiled.
|
// so both are marked as compiled.
|
||||||
// * The `esm5` is not compiled because we stopped after the `fesm5` format.
|
// * The `esm5` is not compiled because we stopped after the `fesm5` format.
|
||||||
expect(loadPackage('@angular/core').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common').__processed_by_ivy_ngcc__).toEqual({
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common/testing').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common/testing').__processed_by_ivy_ngcc__).toEqual({
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/common/http').__modified_by_ngcc__).toEqual({
|
expect(loadPackage('@angular/common/http').__processed_by_ivy_ngcc__).toEqual({
|
||||||
fesm5: '0.0.0-PLACEHOLDER',
|
fesm5: '0.0.0-PLACEHOLDER',
|
||||||
module: '0.0.0-PLACEHOLDER',
|
module: '0.0.0-PLACEHOLDER',
|
||||||
});
|
});
|
||||||
|
@ -135,6 +149,13 @@ function createMockFileSystem() {
|
||||||
'/node_modules/@angular': loadAngularPackages(),
|
'/node_modules/@angular': loadAngularPackages(),
|
||||||
'/node_modules/rxjs': loadDirectory(resolveNpmTreeArtifact('rxjs', 'index.js')),
|
'/node_modules/rxjs': loadDirectory(resolveNpmTreeArtifact('rxjs', 'index.js')),
|
||||||
'/node_modules/tslib': loadDirectory(resolveNpmTreeArtifact('tslib', 'tslib.js')),
|
'/node_modules/tslib': loadDirectory(resolveNpmTreeArtifact('tslib', 'tslib.js')),
|
||||||
|
'/node_modules/test-package': {
|
||||||
|
'package.json': '{"name": "test-package", "es2015": "./index.js", "typings": "./index.d.ts"}',
|
||||||
|
'index.js':
|
||||||
|
'import {AppModule} from "@angular/common"; export class MyApp extends AppModule;',
|
||||||
|
'index.d.s':
|
||||||
|
'import {AppModule} from "@angular/common"; export declare class MyApp extends AppModule;',
|
||||||
|
}
|
||||||
});
|
});
|
||||||
spyOn(Module, '_resolveFilename').and.callFake(mockResolve);
|
spyOn(Module, '_resolveFilename').and.callFake(mockResolve);
|
||||||
}
|
}
|
||||||
|
@ -209,6 +230,6 @@ function mockResolve(request: string): string|null {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPackage(packageName: string): any {
|
function loadPackage(packageName: string): EntryPointPackageJson {
|
||||||
return JSON.parse(readFileSync(`/node_modules/${packageName}/package.json`, 'utf8'));
|
return JSON.parse(readFileSync(`/node_modules/${packageName}/package.json`, 'utf8'));
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ import {readFileSync, writeFileSync} from 'fs';
|
||||||
import * as mockFs from 'mock-fs';
|
import * as mockFs from 'mock-fs';
|
||||||
|
|
||||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||||
import {checkMarker, hasBeenProcessed, writeMarker} from '../../src/packages/build_marker';
|
import {hasBeenProcessed, markAsProcessed} from '../../src/packages/build_marker';
|
||||||
import {EntryPoint} from '../../src/packages/entry_point';
|
import {EntryPoint} from '../../src/packages/entry_point';
|
||||||
|
|
||||||
function createMockFileSystem() {
|
function createMockFileSystem() {
|
||||||
|
@ -94,104 +94,83 @@ function restoreRealFileSystem() {
|
||||||
mockFs.restore();
|
mockFs.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEntryPoint(path: string): EntryPoint {
|
|
||||||
const absolutePath = AbsoluteFsPath.from(path);
|
|
||||||
return {
|
|
||||||
name: 'some-package',
|
|
||||||
path: absolutePath,
|
|
||||||
package: absolutePath,
|
|
||||||
typings: AbsoluteFsPath.from('/typings'),
|
|
||||||
packageJson: JSON.parse(readFileSync(path + '/package.json', 'utf8'))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Marker files', () => {
|
describe('Marker files', () => {
|
||||||
beforeEach(createMockFileSystem);
|
beforeEach(createMockFileSystem);
|
||||||
afterEach(restoreRealFileSystem);
|
afterEach(restoreRealFileSystem);
|
||||||
|
|
||||||
describe('writeMarker', () => {
|
const COMMON_PACKAGE_PATH = AbsoluteFsPath.from('/node_modules/@angular/common/package.json');
|
||||||
|
|
||||||
|
describe('markAsProcessed', () => {
|
||||||
it('should write a property in the package.json containing the version placeholder', () => {
|
it('should write a property in the package.json containing the version placeholder', () => {
|
||||||
let pkg = JSON.parse(readFileSync('/node_modules/@angular/common/package.json', 'utf8'));
|
let pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||||
expect(pkg.__modified_by_ngcc__).toBeUndefined();
|
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||||
expect(pkg.__modified_by_ngcc__).toBeUndefined();
|
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||||
|
|
||||||
writeMarker(createEntryPoint('/node_modules/@angular/common'), 'fesm2015');
|
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||||
pkg = JSON.parse(readFileSync('/node_modules/@angular/common/package.json', 'utf8'));
|
pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||||
expect(pkg.__modified_by_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||||
expect(pkg.__modified_by_ngcc__.esm5).toBeUndefined();
|
expect(pkg.__processed_by_ivy_ngcc__.esm5).toBeUndefined();
|
||||||
|
|
||||||
writeMarker(createEntryPoint('/node_modules/@angular/common'), 'esm5');
|
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'esm5');
|
||||||
pkg = JSON.parse(readFileSync('/node_modules/@angular/common/package.json', 'utf8'));
|
pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||||
expect(pkg.__modified_by_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||||
expect(pkg.__modified_by_ngcc__.esm5).toEqual('0.0.0-PLACEHOLDER');
|
expect(pkg.__processed_by_ivy_ngcc__.esm5).toEqual('0.0.0-PLACEHOLDER');
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('checkMarker', () => {
|
it('should update the packageJson object in-place', () => {
|
||||||
it('should return false if the marker property does not exist', () => {
|
let pkg = JSON.parse(readFileSync(COMMON_PACKAGE_PATH, 'utf8'));
|
||||||
expect(checkMarker(createEntryPoint('/node_modules/@angular/common'), 'fesm2015'))
|
expect(pkg.__processed_by_ivy_ngcc__).toBeUndefined();
|
||||||
.toBe(false);
|
markAsProcessed(pkg, COMMON_PACKAGE_PATH, 'fesm2015');
|
||||||
});
|
expect(pkg.__processed_by_ivy_ngcc__.fesm2015).toEqual('0.0.0-PLACEHOLDER');
|
||||||
|
|
||||||
it('should return true if the marker property exists and contains the correct version', () => {
|
|
||||||
const pkg = JSON.parse(readFileSync('/node_modules/@angular/common/package.json', 'utf8'));
|
|
||||||
pkg.__modified_by_ngcc__ = {fesm2015: '0.0.0-PLACEHOLDER'};
|
|
||||||
writeFileSync('/node_modules/@angular/common/package.json', JSON.stringify(pkg), 'utf8');
|
|
||||||
expect(checkMarker(createEntryPoint('/node_modules/@angular/common'), 'fesm2015')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw if the marker property exists but contains the wrong version', () => {
|
|
||||||
const pkg = JSON.parse(readFileSync('/node_modules/@angular/common/package.json', 'utf8'));
|
|
||||||
pkg.__modified_by_ngcc__ = {fesm2015: 'WRONG_VERSION'};
|
|
||||||
writeFileSync('/node_modules/@angular/common/package.json', JSON.stringify(pkg), 'utf8');
|
|
||||||
expect(() => checkMarker(createEntryPoint('/node_modules/@angular/common'), 'fesm2015'))
|
|
||||||
.toThrowError(
|
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
|
||||||
'Please completely remove `node_modules` and try again.');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('hasBeenProcessed', () => {
|
describe('hasBeenProcessed', () => {
|
||||||
it('should return true if the marker exists for the given format property', () => {
|
it('should return true if the marker exists for the given format property', () => {
|
||||||
expect(
|
expect(hasBeenProcessed(
|
||||||
hasBeenProcessed({__modified_by_ngcc__: {'fesm2015': '0.0.0-PLACEHOLDER'}}, 'fesm2015'))
|
{name: 'test', __processed_by_ivy_ngcc__: {'fesm2015': '0.0.0-PLACEHOLDER'}},
|
||||||
|
'fesm2015'))
|
||||||
.toBe(true);
|
.toBe(true);
|
||||||
});
|
});
|
||||||
it('should return false if the marker does not exist for the given format property', () => {
|
it('should return false if the marker does not exist for the given format property', () => {
|
||||||
expect(hasBeenProcessed({__modified_by_ngcc__: {'fesm2015': '0.0.0-PLACEHOLDER'}}, 'module'))
|
expect(hasBeenProcessed(
|
||||||
|
{name: 'test', __processed_by_ivy_ngcc__: {'fesm2015': '0.0.0-PLACEHOLDER'}},
|
||||||
|
'module'))
|
||||||
.toBe(false);
|
.toBe(false);
|
||||||
});
|
});
|
||||||
it('should return false if the no markers exist',
|
it('should return false if no markers exist',
|
||||||
() => { expect(hasBeenProcessed({}, 'module')).toBe(false); });
|
() => { expect(hasBeenProcessed({name: 'test'}, 'module')).toBe(false); });
|
||||||
it('should throw an Error if the packageJson is not an object', () => {
|
it('should throw an Error if the format has been compiled with a different version.', () => {
|
||||||
expect(() => hasBeenProcessed(undefined, 'fesm2015'))
|
|
||||||
.toThrowError('`packageJson` parameter is invalid. It parameter must be an object.');
|
|
||||||
expect(
|
expect(
|
||||||
() => hasBeenProcessed(
|
() => hasBeenProcessed(
|
||||||
'{"__modified_by_ngcc__": {"fesm2015": "0.0.0-PLACEHOLDER"}}', 'fesm2015'))
|
{name: 'test', __processed_by_ivy_ngcc__: {'fesm2015': '8.0.0'}}, 'fesm2015'))
|
||||||
.toThrowError('`packageJson` parameter is invalid. It parameter must be an object.');
|
|
||||||
});
|
|
||||||
it('should throw an Error if the format has been compiled with a different version.', () => {
|
|
||||||
expect(() => hasBeenProcessed({__modified_by_ngcc__: {'fesm2015': '8.0.0'}}, 'fesm2015'))
|
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
'The ngcc compiler has changed since the last ngcc build.\n' +
|
||||||
'Please completely remove `node_modules` and try again.');
|
'Please completely remove `node_modules` and try again.');
|
||||||
});
|
});
|
||||||
it('should throw an Error if any format has been compiled with a different version.', () => {
|
it('should throw an Error if any format has been compiled with a different version.', () => {
|
||||||
expect(() => hasBeenProcessed({__modified_by_ngcc__: {'fesm2015': '8.0.0'}}, 'module'))
|
expect(
|
||||||
|
() => hasBeenProcessed(
|
||||||
|
{name: 'test', __processed_by_ivy_ngcc__: {'fesm2015': '8.0.0'}}, 'module'))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
'The ngcc compiler has changed since the last ngcc build.\n' +
|
||||||
'Please completely remove `node_modules` and try again.');
|
'Please completely remove `node_modules` and try again.');
|
||||||
expect(
|
expect(
|
||||||
() => hasBeenProcessed(
|
() => hasBeenProcessed(
|
||||||
{__modified_by_ngcc__: {'module': '0.0.0-PLACEHOLDER', 'fesm2015': '8.0.0'}},
|
{
|
||||||
|
name: 'test',
|
||||||
|
__processed_by_ivy_ngcc__: {'module': '0.0.0-PLACEHOLDER', 'fesm2015': '8.0.0'}
|
||||||
|
},
|
||||||
'module'))
|
'module'))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
'The ngcc compiler has changed since the last ngcc build.\n' +
|
||||||
'Please completely remove `node_modules` and try again.');
|
'Please completely remove `node_modules` and try again.');
|
||||||
expect(
|
expect(
|
||||||
() => hasBeenProcessed(
|
() => hasBeenProcessed(
|
||||||
{__modified_by_ngcc__: {'module': '0.0.0-PLACEHOLDER', 'fesm2015': '8.0.0'}},
|
{
|
||||||
|
name: 'test',
|
||||||
|
__processed_by_ivy_ngcc__: {'module': '0.0.0-PLACEHOLDER', 'fesm2015': '8.0.0'}
|
||||||
|
},
|
||||||
'fesm2015'))
|
'fesm2015'))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
'The ngcc compiler has changed since the last ngcc build.\n' +
|
'The ngcc compiler has changed since the last ngcc build.\n' +
|
||||||
|
|
Loading…
Reference in New Issue