fix(compiler_cli): allow to use builtin directives like NgIf, …

Related to #8448
Closes #8454
This commit is contained in:
Tobias Bosch
2016-05-03 17:31:40 -07:00
parent 0297398f5e
commit edec158dd8
14 changed files with 130 additions and 20 deletions

View File

@ -1,3 +1,3 @@
<div>{{ctxProp}}</div>
<form><input type="button" [(ngModel)]="ctxProp"/></form>
<my-comp></my-comp>
<my-comp *ngIf="ctxBool"></my-comp>

View File

@ -1,5 +1,5 @@
import {Component, Inject} from '@angular/core';
import {FORM_DIRECTIVES} from '@angular/common';
import {FORM_DIRECTIVES, NgIf} from '@angular/common';
import {MyComp} from './a/multiple_components';
@Component({
@ -7,9 +7,10 @@ import {MyComp} from './a/multiple_components';
templateUrl: './basic.html',
styles: ['.red { color: red }'],
styleUrls: ['./basic.css'],
directives: [MyComp, FORM_DIRECTIVES]
directives: [MyComp, FORM_DIRECTIVES, NgIf]
})
export class Basic {
ctxProp: string;
constructor() { this.ctxProp = 'initiaValue'; }
ctxBool: boolean;
constructor() { this.ctxProp = 'initialValue'; }
}

View File

@ -1,5 +1,9 @@
import * as fs from 'fs';
import * as path from 'path';
import {BasicNgFactory} from '../src/basic.ngfactory';
import {MyComp} from '../src/a/multiple_components';
import {ReflectiveInjector, DebugElement, getDebugNode} from '@angular/core';
import {browserPlatform, BROWSER_APP_STATIC_PROVIDERS} from '@angular/platform-browser';
describe("template codegen output", () => {
const outDir = path.join('dist', 'all', '@angular', 'compiler_cli', 'integrationtest', 'src');
@ -23,4 +27,17 @@ describe("template codegen output", () => {
expect(fs.existsSync(dtsOutput)).toBeTruthy();
expect(fs.readFileSync(dtsOutput, {encoding: 'utf-8'})).toContain('Basic');
});
it("should be able to create the basic component and trigger an ngIf", () => {
const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_STATIC_PROVIDERS,
browserPlatform().injector);
var comp = BasicNgFactory.create(appInjector);
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
expect(debugElement.children.length).toBe(2);
comp.instance.ctxBool = true;
comp.changeDetectorRef.detectChanges();
expect(debugElement.children.length).toBe(3);
expect(debugElement.children[2].injector.get(MyComp)).toBeTruthy();
});
});

View File

@ -25,6 +25,7 @@ import {Parse5DomAdapter} from '@angular/platform-server';
import {MetadataCollector} from 'ts-metadata-collector';
import {NodeReflectorHost} from './reflector_host';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
@ -164,6 +165,7 @@ export class CodeGenerator {
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
const reflectorHost = new NodeReflectorHost(program, compilerHost, options, ngOptions);
const staticReflector = new StaticReflector(reflectorHost);
StaticAndDynamicReflectionCapabilities.install(staticReflector);
const htmlParser = new HtmlParser();
const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser);
const parser = new Parser(new Lexer());

View File

@ -2,3 +2,6 @@ import {__core_private__ as r, __core_private_types__ as t} from '@angular/core'
export type ReflectorReader = t.ReflectorReader;
export var ReflectorReader: typeof t.ReflectorReader = r.ReflectorReader;
export type ReflectionCapabilities = t.ReflectionCapabilities;
export var ReflectionCapabilities: typeof t.ReflectionCapabilities = r.ReflectionCapabilities;

View File

@ -1,4 +1,4 @@
#!/usr/bin / env node
#!/usr/bin/env node
// Must be imported first, because angular2 decorators throws on load.
import 'reflect-metadata';

View File

@ -37,11 +37,15 @@ export class NodeReflectorHost implements StaticReflectorHost, ImportGenerator {
return resolved ? resolved.resolvedFileName : null;
};
private normalizeAssetUrl(url: string): string {
let assetUrl = AssetUrl.parse(url);
return assetUrl ? `${assetUrl.packageName}/${assetUrl.modulePath}` : null;
}
private resolveAssetUrl(url: string, containingFile: string): string {
let assetUrl = AssetUrl.parse(url);
let assetUrl = this.normalizeAssetUrl(url);
if (assetUrl) {
return this.resolve(`${assetUrl.packageName}/${assetUrl.modulePath}`, containingFile);
return this.resolve(assetUrl, containingFile);
}
return url;
}
@ -92,6 +96,10 @@ export class NodeReflectorHost implements StaticReflectorHost, ImportGenerator {
}
try {
let assetUrl = this.normalizeAssetUrl(module);
if (assetUrl) {
module = assetUrl;
}
const filePath = this.resolve(module, containingFile);
if (!filePath) {

View File

@ -0,0 +1,48 @@
import {reflector} from '@angular/core';
import {ReflectionCapabilities} from './core_private';
import {StaticReflector} from './static_reflector';
export class StaticAndDynamicReflectionCapabilities {
static install(staticDelegate: StaticReflector) {
reflector.updateCapabilities(new StaticAndDynamicReflectionCapabilities(staticDelegate));
}
private dynamicDelegate = new ReflectionCapabilities();
constructor(private staticDelegate: StaticReflector) {}
isReflectionEnabled(): boolean {
return true;
}
factory(type: any): Function {
return this.dynamicDelegate.factory(type);
}
interfaces(type: any): any[] {
return this.dynamicDelegate.interfaces(type);
}
parameters(type: any): any[][] {
return isStaticType(type) ? this.staticDelegate.parameters(type) : this.dynamicDelegate.parameters(type);
}
annotations(type: any): any[] {
return isStaticType(type) ? this.staticDelegate.annotations(type) : this.dynamicDelegate.annotations(type);
}
propMetadata(typeOrFunc: any): {[key: string]: any[]} {
return isStaticType(typeOrFunc) ? this.staticDelegate.propMetadata(typeOrFunc) : this.dynamicDelegate.propMetadata(typeOrFunc);
}
getter(name: string) {
return this.dynamicDelegate.getter(name);
}
setter(name: string) {
return this.dynamicDelegate.setter(name);
}
method(name: string) {
return this.dynamicDelegate.method(name);
}
importUri(type: any): string {
return this.staticDelegate.importUri(type);
}
}
function isStaticType(type: any): boolean {
return typeof type === 'object' && type.name && type.filePath;
}

View File

@ -75,7 +75,10 @@ export class StaticReflector implements ReflectorReader {
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
importUri(typeOrFunc: any): string { return (<StaticSymbol>typeOrFunc).filePath; }
importUri(typeOrFunc: StaticSymbol): string {
var staticSymbol = this.host.findDeclaration(typeOrFunc.filePath, typeOrFunc.name, '');
return staticSymbol ? staticSymbol.filePath : null;
}
public annotations(type: StaticSymbol): any[] {
let annotations = this.annotationCache.get(type);