diff --git a/modules/@angular/compiler/src/compile_metadata.ts b/modules/@angular/compiler/src/compile_metadata.ts
index 782bf0d7a4..af1246d8de 100644
--- a/modules/@angular/compiler/src/compile_metadata.ts
+++ b/modules/@angular/compiler/src/compile_metadata.ts
@@ -1,4 +1,4 @@
-import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
+import {ChangeDetectionStrategy, ViewEncapsulation, reflector} from '@angular/core';
import {
CHANGE_DETECTION_STRATEGY_VALUES,
VIEW_ENCAPSULATION_VALUES,
@@ -259,10 +259,13 @@ export class CompileFactoryMetadata implements CompileIdentifierMetadata,
}
}
+var UNDEFINED = new Object();
+
export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
value: any;
identifier: CompileIdentifierMetadata;
identifierIsInstance: boolean;
+ private _assetCacheKey = UNDEFINED;
constructor({value, identifier, identifierIsInstance}: {
value?: any,
@@ -299,14 +302,23 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
}
get assetCacheKey(): any {
- if (isPresent(this.identifier)) {
- return isPresent(this.identifier.moduleUrl) &&
- isPresent(getUrlScheme(this.identifier.moduleUrl)) ?
- `${this.identifier.name}|${this.identifier.moduleUrl}|${this.identifierIsInstance}` :
- null;
- } else {
- return this.value;
+ if (this._assetCacheKey === UNDEFINED) {
+ if (isPresent(this.identifier)) {
+ if (isPresent(this.identifier.moduleUrl) &&
+ isPresent(getUrlScheme(this.identifier.moduleUrl))) {
+ var uri = reflector.importUri({
+ 'filePath': this.identifier.moduleUrl,
+ 'name': this.identifier.name
+ });
+ this._assetCacheKey = `${this.identifier.name}|${uri}|${this.identifierIsInstance}`;
+ } else {
+ this._assetCacheKey = null;
+ }
+ } else {
+ this._assetCacheKey = this.value;
+ }
}
+ return this._assetCacheKey;
}
equalsTo(token2: CompileTokenMetadata): boolean {
diff --git a/modules/@angular/compiler_cli/integrationtest/src/basic.html b/modules/@angular/compiler_cli/integrationtest/src/basic.html
index a2e5268700..8a535b9117 100644
--- a/modules/@angular/compiler_cli/integrationtest/src/basic.html
+++ b/modules/@angular/compiler_cli/integrationtest/src/basic.html
@@ -1,3 +1,3 @@
{{ctxProp}}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/modules/@angular/compiler_cli/integrationtest/src/basic.ts b/modules/@angular/compiler_cli/integrationtest/src/basic.ts
index 551e1b1ee2..56e6430eaf 100644
--- a/modules/@angular/compiler_cli/integrationtest/src/basic.ts
+++ b/modules/@angular/compiler_cli/integrationtest/src/basic.ts
@@ -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'; }
}
diff --git a/modules/@angular/compiler_cli/integrationtest/test/basic_spec.ts b/modules/@angular/compiler_cli/integrationtest/test/basic_spec.ts
index f3bb094b7a..750e064db6 100644
--- a/modules/@angular/compiler_cli/integrationtest/test/basic_spec.ts
+++ b/modules/@angular/compiler_cli/integrationtest/test/basic_spec.ts
@@ -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 = 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();
+ });
});
\ No newline at end of file
diff --git a/modules/@angular/compiler_cli/src/codegen.ts b/modules/@angular/compiler_cli/src/codegen.ts
index f1f9066e6c..be4f8152e2 100644
--- a/modules/@angular/compiler_cli/src/codegen.ts
+++ b/modules/@angular/compiler_cli/src/codegen.ts
@@ -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());
diff --git a/modules/@angular/compiler_cli/src/core_private.ts b/modules/@angular/compiler_cli/src/core_private.ts
index 5197e05a10..c2a9ec2f38 100644
--- a/modules/@angular/compiler_cli/src/core_private.ts
+++ b/modules/@angular/compiler_cli/src/core_private.ts
@@ -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;
diff --git a/modules/@angular/compiler_cli/src/main.ts b/modules/@angular/compiler_cli/src/main.ts
index 0ae6f5f8d9..cc33e93363 100644
--- a/modules/@angular/compiler_cli/src/main.ts
+++ b/modules/@angular/compiler_cli/src/main.ts
@@ -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';
diff --git a/modules/@angular/compiler_cli/src/reflector_host.ts b/modules/@angular/compiler_cli/src/reflector_host.ts
index c4bd6e19db..bceb9a3d2c 100644
--- a/modules/@angular/compiler_cli/src/reflector_host.ts
+++ b/modules/@angular/compiler_cli/src/reflector_host.ts
@@ -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) {
diff --git a/modules/@angular/compiler_cli/src/static_reflection_capabilities.ts b/modules/@angular/compiler_cli/src/static_reflection_capabilities.ts
new file mode 100644
index 0000000000..91ca210a37
--- /dev/null
+++ b/modules/@angular/compiler_cli/src/static_reflection_capabilities.ts
@@ -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;
+}
\ No newline at end of file
diff --git a/modules/@angular/compiler_cli/src/static_reflector.ts b/modules/@angular/compiler_cli/src/static_reflector.ts
index d2ad0c975e..2b3c4a5f2d 100644
--- a/modules/@angular/compiler_cli/src/static_reflector.ts
+++ b/modules/@angular/compiler_cli/src/static_reflector.ts
@@ -75,7 +75,10 @@ export class StaticReflector implements ReflectorReader {
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
- importUri(typeOrFunc: any): string { return (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);
diff --git a/modules/@angular/core/src/reflection/platform_reflection_capabilities.ts b/modules/@angular/core/src/reflection/platform_reflection_capabilities.ts
index ad4c13f27e..c28ec060cc 100644
--- a/modules/@angular/core/src/reflection/platform_reflection_capabilities.ts
+++ b/modules/@angular/core/src/reflection/platform_reflection_capabilities.ts
@@ -11,5 +11,5 @@ export interface PlatformReflectionCapabilities {
getter(name: string): GetterFn;
setter(name: string): SetterFn;
method(name: string): MethodFn;
- importUri(type: Type): string;
+ importUri(type: any): string;
}
diff --git a/modules/@angular/core/src/reflection/reflection_capabilities.dart b/modules/@angular/core/src/reflection/reflection_capabilities.dart
index 3cd4b4a030..7082065057 100644
--- a/modules/@angular/core/src/reflection/reflection_capabilities.dart
+++ b/modules/@angular/core/src/reflection/reflection_capabilities.dart
@@ -342,7 +342,12 @@ class ReflectionCapabilities implements PlatformReflectionCapabilities {
return classMirror.metadata;
}
- String importUri(Type type) {
+ String importUri(dynamic type) {
+ // StaticSymbol
+ if (type is Map && type['filePath'] != null) {
+ return type['filePath'];
+ }
+ // Runtime type
return '${(reflectClass(type).owner as LibraryMirror).uri}';
}
}
diff --git a/modules/@angular/core/src/reflection/reflection_capabilities.ts b/modules/@angular/core/src/reflection/reflection_capabilities.ts
index 07796ac688..525c7ec332 100644
--- a/modules/@angular/core/src/reflection/reflection_capabilities.ts
+++ b/modules/@angular/core/src/reflection/reflection_capabilities.ts
@@ -214,7 +214,14 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}
// There is not a concept of import uri in Js, but this is useful in developing Dart applications.
- importUri(type: Type): string { return `./${stringify(type)}`; }
+ importUri(type: any): string {
+ // StaticSymbol
+ if (typeof type === 'object' && type['filePath']) {
+ return type['filePath'];
+ }
+ // Runtime type
+ return `./${stringify(type)}`;
+ }
}
function convertTsickleDecoratorIntoMetadata(decoratorInvocations: any[]): any[] {
diff --git a/modules/@angular/core/src/reflection/reflector.ts b/modules/@angular/core/src/reflection/reflector.ts
index 191db83e6c..56d1984be0 100644
--- a/modules/@angular/core/src/reflection/reflector.ts
+++ b/modules/@angular/core/src/reflection/reflector.ts
@@ -45,6 +45,10 @@ export class Reflector extends ReflectorReader {
this.reflectionCapabilities = reflectionCapabilities;
}
+ updateCapabilities(caps: PlatformReflectionCapabilities) {
+ this.reflectionCapabilities = caps;
+ }
+
isReflectionEnabled(): boolean { return this.reflectionCapabilities.isReflectionEnabled(); }
/**
@@ -160,7 +164,7 @@ export class Reflector extends ReflectorReader {
/** @internal */
_containsReflectionInfo(typeOrFunc: any) { return this._injectableInfo.has(typeOrFunc); }
- importUri(type: Type): string { return this.reflectionCapabilities.importUri(type); }
+ importUri(type: any): string { return this.reflectionCapabilities.importUri(type); }
}
function _mergeMaps(target: Map, config: {[key: string]: Function}): void {