feat(compiler-cli): lower metadata useValue and data literal fields (#18905)

With this commit the compiler will "lower" expressions into exported
variables for values the compiler does not need to know statically
in order to be able to generate a factory. For example:

```
  providers: [{provider: 'token', useValue: calculated()}]
```

produced an error as the expression `calculated()` is not supported
by the compiler because `calculated` is not a
[known function](https://angular.io/guide/metadata#annotationsdecorators)

With this commit this is rewritten, during emit of the .js file, into
something like:

```
export var ɵ0 = calculated();

  ...

  provdiers: [{provider: 'token', useValue: ɵ0}]
```

The compiler then will now generate a reference to the exported `ɵ0`
instead of failing to evaluate `calculated()`.

PR Close #18905
This commit is contained in:
Chuck Jazdzewski
2017-08-23 10:22:17 -07:00
committed by Jason Aden
parent 2f2d5f35bd
commit c685cc2f0a
8 changed files with 324 additions and 28 deletions

View File

@ -12,6 +12,8 @@ import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
export interface MetadataProvider { getMetadata(source: ts.SourceFile): ModuleMetadata|undefined; }
let nodeModulesPath: string;
let angularSourcePath: string;
let rootPath: string;
@ -327,12 +329,13 @@ const DTS = /\.d\.ts$/;
const GENERATED_FILES = /\.ngfactory\.ts$|\.ngstyle\.ts$/;
export class MockAotCompilerHost implements AotCompilerHost {
private metadataCollector = new MetadataCollector();
private metadataVisible: boolean = true;
private dtsAreSource: boolean = true;
private resolveModuleNameHost: ts.ModuleResolutionHost;
constructor(private tsHost: MockCompilerHost) {
constructor(
private tsHost: MockCompilerHost,
private metadataProvider: MetadataProvider = new MetadataCollector()) {
this.resolveModuleNameHost = Object.create(tsHost);
this.resolveModuleNameHost.fileExists = (fileName) => {
fileName = stripNgResourceSuffix(fileName);
@ -359,7 +362,7 @@ export class MockAotCompilerHost implements AotCompilerHost {
}
} else {
const sf = this.tsHost.getSourceFile(modulePath, ts.ScriptTarget.Latest);
const metadata = this.metadataCollector.getMetadata(sf);
const metadata = this.metadataProvider.getMetadata(sf);
return metadata ? [metadata] : [];
}
return undefined;