fix(compiler-cli): strictMetadataEmit should not break on non-compliant libraries (#23275)

rxjs 6.0.0 breaks strictMetadataEmit as they now publish a .d.ts file with a
structure like:

declare export class Subscription {
  static EMPTY: Subscription;
}

This generates metadata which contains an error, and fails the strictMetadataEmit
validation. There is nothing a library author can do in this situation except to
set strictMetadataEmit to false.

The spirit of strictMetadataEmit is to validate that the author's library doesn't
do anything that will break downstream users. This failure is a corner case which
causes more harm than good, so this commit disables validation for metadata
collected from .d.ts files.

Fixes #22210

PR Close #23275
This commit is contained in:
Alex Rickabaugh 2018-04-09 13:52:50 -07:00 committed by Igor Minar
parent 60e8392722
commit 58143555bc
2 changed files with 31 additions and 2 deletions

View File

@ -11,6 +11,7 @@ import * as ts from 'typescript';
import {MetadataCollector, MetadataValue, ModuleMetadata} from '../metadata/index'; import {MetadataCollector, MetadataValue, ModuleMetadata} from '../metadata/index';
import {MetadataProvider} from './compiler_host'; import {MetadataProvider} from './compiler_host';
import {TS} from './util';
export type ValueTransform = (value: MetadataValue, node: ts.Node) => MetadataValue; export type ValueTransform = (value: MetadataValue, node: ts.Node) => MetadataValue;
@ -26,7 +27,7 @@ export class MetadataCache implements MetadataProvider {
private metadataCache = new Map<string, ModuleMetadata|undefined>(); private metadataCache = new Map<string, ModuleMetadata|undefined>();
constructor( constructor(
private collector: MetadataCollector, private strict: boolean, private collector: MetadataCollector, private readonly strict: boolean,
private transformers: MetadataTransformer[]) { private transformers: MetadataTransformer[]) {
for (let transformer of transformers) { for (let transformer of transformers) {
if (transformer.connect) { if (transformer.connect) {
@ -59,7 +60,8 @@ export class MetadataCache implements MetadataProvider {
} }
} }
const result = this.collector.getMetadata(sourceFile, this.strict, substitute); const isTsFile = TS.test(sourceFile.fileName);
const result = this.collector.getMetadata(sourceFile, this.strict && isTsFile, substitute);
this.metadataCache.set(sourceFile.fileName, result); this.metadataCache.set(sourceFile.fileName, result);
return result; return result;
} }

View File

@ -2420,4 +2420,31 @@ describe('ngc transformer command-line', () => {
expect(moduleSource).toMatch(/inject\(i0\.INJECTOR/); expect(moduleSource).toMatch(/inject\(i0\.INJECTOR/);
}); });
}); });
it('libraries should not break strictMetadataEmit', () => {
// first only generate .d.ts / .js / .metadata.json files
writeConfig(`{
"extends": "./tsconfig-base.json",
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true
},
"compilerOptions": {
"outDir": "lib"
},
"files": ["main.ts", "test.d.ts"]
}`);
write('main.ts', `
import {Test} from './test';
export const bar = Test.bar;
`);
write('test.d.ts', `
declare export class Test {
static bar: string;
}
`);
let exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy);
expect(exitCode).toEqual(0);
});
}); });