fix(core): Remove static dependency from @angular/core to @angular/compiler (#26734)

PR Close #26734
This commit is contained in:
Misko Hevery
2018-10-24 16:02:25 -07:00
committed by Matias Niemelä
parent 5d740785a9
commit d042c4afe0
46 changed files with 923 additions and 551 deletions

View File

@ -0,0 +1,22 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {global} from '../../util';
import {CompilerFacade, ExportedCompilerFacade} from './compiler_facade_interface';
export * from './compiler_facade_interface';
export function getCompilerFacade(): CompilerFacade {
const globalNg: ExportedCompilerFacade = global.ng;
if (!globalNg || !globalNg.ɵcompilerFacade) {
throw new Error(
`Angular JIT compilation failed: '@angular/compiler' not loaded!\n` +
` - JIT compilation is discouraged for production use-cases! Consider AOT mode instead.\n` +
` - Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?\n` +
` - Alternatively provide the compiler with 'import "@angular/compiler";' before bootstrapping.`);
}
return globalNg.ɵcompilerFacade;
}

View File

@ -0,0 +1,145 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A set of interfaces which are shared between `@angular/core` and `@angular/compiler` to allow
* for late binding of `@angular/compiler` for JIT purposes.
*
* This file has two copies. Please ensure that they are in sync:
* - packages/compiler/src/compiler_facade_interface.ts (master)
* - packages/core/src/render3/jit/compiler_facade_interface.ts (copy)
*
* Please ensure that the two files are in sync using this command:
* ```
* cp packages/compiler/src/compiler_facade_interface.ts \
* packages/core/src/render3/jit/compiler_facade_interface.ts
* ```
*/
export interface ExportedCompilerFacade { ɵcompilerFacade: CompilerFacade; }
export interface CompilerFacade {
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3PipeMetadataFacade):
any;
compileInjectable(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectableMetadataFacade): any;
compileInjector(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3InjectorMetadataFacade): any;
compileNgModule(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3NgModuleMetadataFacade): any;
compileDirective(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3DirectiveMetadataFacade): any;
compileComponent(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
R3ResolvedDependencyType: typeof R3ResolvedDependencyType;
}
export interface CoreEnvironment { [name: string]: Function; }
export type StringMap = {
[key: string]: string;
};
export type StringMapWithRename = {
[key: string]: string | [string, string];
};
export type Provider = any;
export enum R3ResolvedDependencyType {
Token = 0,
Attribute = 1,
}
export interface R3DependencyMetadataFacade {
token: any;
resolved: R3ResolvedDependencyType;
host: boolean;
optional: boolean;
self: boolean;
skipSelf: boolean;
}
export interface R3PipeMetadataFacade {
name: string;
type: any;
pipeName: string;
deps: R3DependencyMetadataFacade[]|null;
pure: boolean;
}
export interface R3InjectableMetadataFacade {
name: string;
type: any;
ctorDeps: R3DependencyMetadataFacade[]|null;
providedIn: any;
useClass?: any;
useFactory?: any;
useExisting?: any;
useValue?: any;
userDeps?: R3DependencyMetadataFacade[];
}
export interface R3NgModuleMetadataFacade {
type: any;
bootstrap: Function[];
declarations: Function[];
imports: Function[];
exports: Function[];
emitInline: boolean;
}
export interface R3InjectorMetadataFacade {
name: string;
type: any;
deps: R3DependencyMetadataFacade[]|null;
providers: any;
imports: any;
}
export interface R3DirectiveMetadataFacade {
name: string;
type: any;
typeArgumentCount: number;
typeSourceSpan: null;
deps: R3DependencyMetadataFacade[]|null;
selector: string|null;
queries: R3QueryMetadataFacade[];
host: {[key: string]: string};
propMetadata: {[key: string]: any[]};
lifecycle: {usesOnChanges: boolean;};
inputs: string[];
outputs: string[];
usesInheritance: boolean;
exportAs: string|null;
providers: Provider[]|null;
}
export interface R3ComponentMetadataFacade extends R3DirectiveMetadataFacade {
template: string;
preserveWhitespaces: boolean;
animations: any[]|undefined;
viewQueries: R3QueryMetadataFacade[];
pipes: Map<string, any>;
directives: Map<string, any>;
styles: string[];
encapsulation: ViewEncapsulation;
viewProviders: Provider[]|null;
}
export type ViewEncapsulation = number;
export interface R3QueryMetadataFacade {
propertyName: string;
first: boolean;
predicate: any|string[];
descendants: boolean;
read: any|null;
}

View File

@ -6,23 +6,22 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ConstantPool, Expression, R3DirectiveMetadata, R3QueryMetadata, WrappedNodeExpr, compileComponentFromMetadata as compileR3Component, compileDirectiveFromMetadata as compileR3Directive, jitExpression, makeBindingParser, parseHostBindings, parseTemplate} from '@angular/compiler';
import {Query} from '../../metadata/di';
import {Component, Directive, HostBinding, HostListener, Input, Output} from '../../metadata/directives';
import {Component, Directive} from '../../metadata/directives';
import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from '../../metadata/resource_loading';
import {ViewEncapsulation} from '../../metadata/view';
import {Type} from '../../type';
import {stringify} from '../../util';
import {EMPTY_ARRAY} from '../definition';
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF} from '../fields';
import {R3DirectiveMetadataFacade, getCompilerFacade} from './compiler_facade';
import {R3ComponentMetadataFacade, R3QueryMetadataFacade} from './compiler_facade_interface';
import {angularCoreEnv} from './environment';
import {patchComponentDefWithScope, transitiveScopesFor} from './module';
import {getReflect, reflectDependencies} from './util';
type StringMap = {
[key: string]: string
};
/**
* Compile an Angular component according to its decorator metadata, and patch the resulting
@ -39,6 +38,7 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
maybeQueueResolutionOfComponentResources(metadata);
Object.defineProperty(type, NG_COMPONENT_DEF, {
get: () => {
const compiler = getCompilerFacade();
if (ngComponentDef === null) {
if (componentNeedsResolution(metadata)) {
const error = [`Component '${stringify(type)}' is not resolved:`];
@ -51,43 +51,20 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
error.push(`Did you run and wait for 'resolveComponentResources()'?`);
throw new Error(error.join('\n'));
}
// The ConstantPool is a requirement of the JIT'er.
const constantPool = new ConstantPool();
// Parse the template and check for errors.
const template = parseTemplate(
metadata.template !, `ng://${stringify(type)}/template.html`, {
preserveWhitespaces: metadata.preserveWhitespaces || false,
},
'');
if (template.errors !== undefined) {
const errors = template.errors.map(err => err.toString()).join(', ');
throw new Error(
`Errors during JIT compilation of template for ${stringify(type)}: ${errors}`);
}
const animations =
metadata.animations !== null ? new WrappedNodeExpr(metadata.animations) : null;
// Compile the component metadata, including template, into an expression.
const res = compileR3Component(
{
...directiveMetadata(type, metadata),
template,
directives: new Map(),
pipes: new Map(),
viewQueries: extractQueriesMetadata(getReflect().propMetadata(type), isViewQuery),
wrapDirectivesAndPipesInClosure: false,
styles: metadata.styles || [],
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated, animations,
viewProviders: metadata.viewProviders ? new WrappedNodeExpr(metadata.viewProviders) :
null
},
constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements];
ngComponentDef = jitExpression(
res.expression, angularCoreEnv, `ng://${type.name}/ngComponentDef.js`, preStatements);
const meta: R3ComponentMetadataFacade = {
...directiveMetadata(type, metadata),
template: metadata.template || '',
preserveWhitespaces: metadata.preserveWhitespaces || false,
styles: metadata.styles || EMPTY_ARRAY,
animations: metadata.animations,
viewQueries: extractQueriesMetadata(getReflect().propMetadata(type), isViewQuery),
directives: new Map(),
pipes: new Map(),
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated,
viewProviders: metadata.viewProviders || null,
};
ngComponentDef = compiler.compileComponent(
angularCoreEnv, `ng://${stringify(type)}/template.html`, meta);
// If component compilation is async, then the @NgModule annotation which declares the
// component may execute and set an ngSelectorScope property on the component type. This
@ -122,12 +99,9 @@ export function compileDirective(type: Type<any>, directive: Directive): void {
Object.defineProperty(type, NG_DIRECTIVE_DEF, {
get: () => {
if (ngDirectiveDef === null) {
const constantPool = new ConstantPool();
const sourceMapUrl = `ng://${type && type.name}/ngDirectiveDef.js`;
const res = compileR3Directive(
directiveMetadata(type, directive), constantPool, makeBindingParser());
const preStatements = [...constantPool.statements, ...res.statements];
ngDirectiveDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
const facade = directiveMetadata(type, directive);
ngDirectiveDef = getCompilerFacade().compileDirective(
angularCoreEnv, `ng://${type && type.name}/ngDirectiveDef.js`, facade);
}
return ngDirectiveDef;
},
@ -144,38 +118,20 @@ export function extendsDirectlyFromObject(type: Type<any>): boolean {
* Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
* `Component`).
*/
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadata {
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadataFacade {
// Reflect inputs and outputs.
const propMetadata = getReflect().propMetadata(type);
const host = extractHostBindings(metadata, propMetadata);
const inputsFromMetadata = parseInputOutputs(metadata.inputs || []);
const outputsFromMetadata = parseInputOutputs(metadata.outputs || []);
const inputsFromType: {[key: string]: string | string[]} = {};
const outputsFromType: StringMap = {};
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isInput(ann)) {
inputsFromType[field] =
ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field;
} else if (isOutput(ann)) {
outputsFromType[field] = ann.bindingPropertyName || field;
}
});
}
}
return {
name: type.name,
type: new WrappedNodeExpr(type),
type: type,
typeArgumentCount: 0,
selector: metadata.selector !,
deps: reflectDependencies(type), host,
inputs: {...inputsFromMetadata, ...inputsFromType},
outputs: {...outputsFromMetadata, ...outputsFromType},
deps: reflectDependencies(type),
host: metadata.host || EMPTY_OBJ,
propMetadata: propMetadata,
inputs: metadata.inputs || EMPTY_ARRAY,
outputs: metadata.outputs || EMPTY_ARRAY,
queries: extractQueriesMetadata(propMetadata, isContentQuery),
lifecycle: {
usesOnChanges: type.prototype.ngOnChanges !== undefined,
@ -183,57 +139,29 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
typeSourceSpan: null !,
usesInheritance: !extendsDirectlyFromObject(type),
exportAs: metadata.exportAs || null,
providers: metadata.providers ? new WrappedNodeExpr(metadata.providers) : null
providers: metadata.providers || null,
};
}
function extractHostBindings(metadata: Directive, propMetadata: {[key: string]: any[]}): {
attributes: StringMap,
listeners: StringMap,
properties: StringMap,
} {
// First parse the declarations from the metadata.
const {attributes, listeners, properties, animations} = parseHostBindings(metadata.host || {});
const EMPTY_OBJ = {};
if (Object.keys(animations).length > 0) {
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
}
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
if (isHostBinding(ann)) {
properties[ann.hostPropertyName || field] = field;
} else if (isHostListener(ann)) {
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
}
});
}
}
return {attributes, listeners, properties};
function convertToR3QueryPredicate(selector: any): any|string[] {
return typeof selector === 'string' ? splitByComma(selector) : selector;
}
function convertToR3QueryPredicate(selector: any): Expression|string[] {
return typeof selector === 'string' ? splitByComma(selector) : new WrappedNodeExpr(selector);
}
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadata {
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadataFacade {
return {
propertyName: propertyName,
predicate: convertToR3QueryPredicate(ann.selector),
descendants: ann.descendants,
first: ann.first,
read: ann.read ? new WrappedNodeExpr(ann.read) : null
read: ann.read ? ann.read : null
};
}
function extractQueriesMetadata(
propMetadata: {[key: string]: any[]},
isQueryAnn: (ann: any) => ann is Query): R3QueryMetadata[] {
const queriesMeta: R3QueryMetadata[] = [];
isQueryAnn: (ann: any) => ann is Query): R3QueryMetadataFacade[] {
const queriesMeta: R3QueryMetadataFacade[] = [];
for (const field in propMetadata) {
if (propMetadata.hasOwnProperty(field)) {
propMetadata[field].forEach(ann => {
@ -243,26 +171,9 @@ function extractQueriesMetadata(
});
}
}
return queriesMeta;
}
function isInput(value: any): value is Input {
return value.ngMetadataName === 'Input';
}
function isOutput(value: any): value is Output {
return value.ngMetadataName === 'Output';
}
function isHostBinding(value: any): value is HostBinding {
return value.ngMetadataName === 'HostBinding';
}
function isHostListener(value: any): value is HostListener {
return value.ngMetadataName === 'HostListener';
}
function isContentQuery(value: any): value is Query {
const name = value.ngMetadataName;
return name === 'ContentChild' || name === 'ContentChildren';
@ -276,13 +187,3 @@ function isViewQuery(value: any): value is Query {
function splitByComma(value: string): string[] {
return value.split(',').map(piece => piece.trim());
}
function parseInputOutputs(values: string[]): StringMap {
return values.reduce(
(map, value) => {
const [field, property] = splitByComma(value);
map[field] = property || field;
return map;
},
{} as StringMap);
}

View File

@ -6,14 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, LiteralExpr, R3DependencyMetadata, R3InjectableMetadata, WrappedNodeExpr, compileInjectable as compileR3Injectable, jitExpression} from '@angular/compiler';
import {Injectable} from '../../di/injectable';
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, StaticClassSansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
import {ClassSansProvider, ExistingSansProvider, FactorySansProvider, ValueProvider, ValueSansProvider} from '../../di/provider';
import {Type} from '../../type';
import {getClosureSafeProperty} from '../../util/property';
import {NG_INJECTABLE_DEF} from '../fields';
import {R3InjectableMetadataFacade, getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {convertDependencies, reflectDependencies} from './util';
@ -31,84 +30,60 @@ export function compileInjectable(type: Type<any>, srcMeta?: Injectable): void {
Object.defineProperty(type, NG_INJECTABLE_DEF, {
get: () => {
if (def === null) {
// Check whether the injectable metadata includes a provider specification.
const meta: Injectable = srcMeta || {providedIn: null};
const hasAProvider = isUseClassProvider(meta) || isUseFactoryProvider(meta) ||
isUseValueProvider(meta) || isUseExistingProvider(meta);
const ctorDeps = reflectDependencies(type);
let userDeps: R3DependencyMetadata[]|undefined = undefined;
const compilerMeta: R3InjectableMetadataFacade = {
name: type.name,
type: type,
providedIn: meta.providedIn,
ctorDeps: reflectDependencies(type),
userDeps: undefined
};
if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
userDeps = convertDependencies(meta.deps);
compilerMeta.userDeps = convertDependencies(meta.deps);
}
// Decide which flavor of factory to generate, based on the provider specified.
// Only one of the use* fields should be set.
let useClass: Expression|undefined = undefined;
let useFactory: Expression|undefined = undefined;
let useValue: Expression|undefined = undefined;
let useExisting: Expression|undefined = undefined;
if (!hasAProvider) {
// In the case the user specifies a type provider, treat it as {provide: X, useClass: X}.
// The deps will have been reflected above, causing the factory to create the class by
// calling
// its constructor with injected deps.
useClass = new WrappedNodeExpr(type);
compilerMeta.useClass = type;
} else if (isUseClassProvider(meta)) {
// The user explicitly specified useClass, and may or may not have provided deps.
useClass = new WrappedNodeExpr(meta.useClass);
compilerMeta.useClass = meta.useClass;
} else if (isUseValueProvider(meta)) {
// The user explicitly specified useValue.
useValue = new WrappedNodeExpr(meta.useValue);
compilerMeta.useValue = meta.useValue;
} else if (isUseFactoryProvider(meta)) {
// The user explicitly specified useFactory.
useFactory = new WrappedNodeExpr(meta.useFactory);
compilerMeta.useFactory = meta.useFactory;
} else if (isUseExistingProvider(meta)) {
// The user explicitly specified useExisting.
useExisting = new WrappedNodeExpr(meta.useExisting);
compilerMeta.useExisting = meta.useExisting;
} else {
// Can't happen - either hasAProvider will be false, or one of the providers will be set.
throw new Error(`Unreachable state.`);
}
const {expression, statements} = compileR3Injectable({
name: type.name,
type: new WrappedNodeExpr(type),
providedIn: computeProvidedIn(meta.providedIn),
useClass,
useFactory,
useValue,
useExisting,
ctorDeps,
userDeps,
});
def = jitExpression(
expression, angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, statements);
def = getCompilerFacade().compileInjectable(
angularCoreEnv, `ng://${type.name}/ngInjectableDef.js`, compilerMeta);
}
return def;
},
});
}
function computeProvidedIn(providedIn: Type<any>| string | null | undefined): Expression {
if (providedIn == null || typeof providedIn === 'string') {
return new LiteralExpr(providedIn);
} else {
return new WrappedNodeExpr(providedIn);
}
}
type UseClassProvider = Injectable & ClassSansProvider & {deps?: any[]};
const USE_VALUE =
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
function isUseClassProvider(meta: Injectable): meta is UseClassProvider {
return (meta as UseClassProvider).useClass !== undefined;
}
const USE_VALUE =
getClosureSafeProperty<ValueProvider>({provide: String, useValue: getClosureSafeProperty});
function isUseValueProvider(meta: Injectable): meta is Injectable&ValueSansProvider {
return USE_VALUE in meta;
}

View File

@ -6,14 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Expression, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, WrappedNodeExpr, compileInjector, compileNgModule as compileR3NgModule, jitExpression} from '@angular/compiler';
import {ModuleWithProviders, NgModule, NgModuleDef, NgModuleTransitiveScopes} from '../../metadata/ng_module';
import {Type} from '../../type';
import {getComponentDef, getDirectiveDef, getNgModuleDef, getPipeDef} from '../definition';
import {NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_INJECTOR_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from '../fields';
import {ComponentDef} from '../interfaces/definition';
import {R3InjectorMetadataFacade, getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {reflectDependencies} from './util';
@ -37,48 +36,39 @@ export function compileNgModuleDefs(moduleType: Type<any>, ngModule: NgModule):
let ngModuleDef: any = null;
Object.defineProperty(moduleType, NG_MODULE_DEF, {
configurable: true,
get: () => {
if (ngModuleDef === null) {
const meta: R3NgModuleMetadata = {
type: wrap(moduleType),
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(wrapReference),
declarations: declarations.map(wrapReference),
imports: flatten(ngModule.imports || EMPTY_ARRAY)
.map(expandModuleWithProviders)
.map(wrapReference),
exports: flatten(ngModule.exports || EMPTY_ARRAY)
.map(expandModuleWithProviders)
.map(wrapReference),
emitInline: true,
};
const res = compileR3NgModule(meta);
ngModuleDef = jitExpression(
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, []);
ngModuleDef = getCompilerFacade().compileNgModule(
angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, {
type: moduleType,
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY),
declarations: declarations,
imports: flatten(ngModule.imports || EMPTY_ARRAY).map(expandModuleWithProviders),
exports: flatten(ngModule.exports || EMPTY_ARRAY).map(expandModuleWithProviders),
emitInline: true,
});
}
return ngModuleDef;
},
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
}
});
let ngInjectorDef: any = null;
Object.defineProperty(moduleType, NG_INJECTOR_DEF, {
get: () => {
if (ngInjectorDef === null) {
const meta: R3InjectorMetadata = {
const meta: R3InjectorMetadataFacade = {
name: moduleType.name,
type: wrap(moduleType),
type: moduleType,
deps: reflectDependencies(moduleType),
providers: new WrappedNodeExpr(ngModule.providers || EMPTY_ARRAY),
imports: new WrappedNodeExpr([
providers: ngModule.providers || EMPTY_ARRAY,
imports: [
ngModule.imports || EMPTY_ARRAY,
ngModule.exports || EMPTY_ARRAY,
]),
],
};
const res = compileInjector(meta);
ngInjectorDef = jitExpression(
res.expression, angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`,
res.statements);
ngInjectorDef = getCompilerFacade().compileInjector(
angularCoreEnv, `ng://${moduleType.name}/ngInjectorDef.js`, meta);
}
return ngInjectorDef;
},
@ -235,15 +225,6 @@ function expandModuleWithProviders(value: Type<any>| ModuleWithProviders<{}>): T
return value;
}
function wrap(value: Type<any>): Expression {
return new WrappedNodeExpr(value);
}
function wrapReference(value: Type<any>): R3Reference {
const wrapped = wrap(value);
return {value: wrapped, type: wrapped};
}
function isModuleWithProviders(value: any): value is ModuleWithProviders<{}> {
return (value as{ngModule?: any}).ngModule !== undefined;
}

View File

@ -6,13 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
import {WrappedNodeExpr, compilePipeFromMetadata, jitExpression} from '@angular/compiler';
import {Pipe} from '../../metadata/directives';
import {Type} from '../../type';
import {NG_PIPE_DEF} from '../fields';
import {stringify} from '../util';
import {getCompilerFacade} from './compiler_facade';
import {angularCoreEnv} from './environment';
import {reflectDependencies} from './util';
@ -21,18 +20,14 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
Object.defineProperty(type, NG_PIPE_DEF, {
get: () => {
if (ngPipeDef === null) {
const sourceMapUrl = `ng://${stringify(type)}/ngPipeDef.js`;
const name = type.name;
const res = compilePipeFromMetadata({
name,
type: new WrappedNodeExpr(type),
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true,
});
ngPipeDef = jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
ngPipeDef = getCompilerFacade().compilePipe(
angularCoreEnv, `ng://${stringify(type)}/ngPipeDef.js`, {
type: type,
name: type.name,
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true
});
}
return ngPipeDef;
},

View File

@ -6,44 +6,41 @@
* found in the LICENSE file at https://angular.io/license
*/
import {LiteralExpr, R3DependencyMetadata, R3ResolvedDependencyType, WrappedNodeExpr} from '@angular/compiler';
import {Injector} from '../../di/injector';
import {Host, Inject, Optional, Self, SkipSelf} from '../../di/metadata';
import {ElementRef} from '../../linker/element_ref';
import {TemplateRef} from '../../linker/template_ref';
import {ViewContainerRef} from '../../linker/view_container_ref';
import {Attribute} from '../../metadata/di';
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
import {Type} from '../../type';
import {CompilerFacade, R3DependencyMetadataFacade, getCompilerFacade} from './compiler_facade';
let _reflect: ReflectionCapabilities|null = null;
export function getReflect(): ReflectionCapabilities {
return (_reflect = _reflect || new ReflectionCapabilities());
}
export function reflectDependencies(type: Type<any>): R3DependencyMetadata[] {
export function reflectDependencies(type: Type<any>): R3DependencyMetadataFacade[] {
return convertDependencies(getReflect().parameters(type));
}
export function convertDependencies(deps: any[]): R3DependencyMetadata[] {
return deps.map(dep => reflectDependency(dep));
export function convertDependencies(deps: any[]): R3DependencyMetadataFacade[] {
const compiler = getCompilerFacade();
return deps.map(dep => reflectDependency(compiler, dep));
}
function reflectDependency(dep: any | any[]): R3DependencyMetadata {
const meta: R3DependencyMetadata = {
token: new LiteralExpr(null),
function reflectDependency(compiler: CompilerFacade, dep: any | any[]): R3DependencyMetadataFacade {
const meta: R3DependencyMetadataFacade = {
token: null,
host: false,
optional: false,
resolved: R3ResolvedDependencyType.Token,
resolved: compiler.R3ResolvedDependencyType.Token,
self: false,
skipSelf: false,
};
function setTokenAndResolvedType(token: any): void {
meta.resolved = R3ResolvedDependencyType.Token;
meta.token = new WrappedNodeExpr(token);
meta.resolved = compiler.R3ResolvedDependencyType.Token;
meta.token = token;
}
if (Array.isArray(dep)) {
@ -61,13 +58,13 @@ function reflectDependency(dep: any | any[]): R3DependencyMetadata {
} else if (param instanceof Host || param.__proto__.ngMetadataName === 'Host') {
meta.host = true;
} else if (param instanceof Inject) {
meta.token = new WrappedNodeExpr(param.token);
meta.token = param.token;
} else if (param instanceof Attribute) {
if (param.attributeName === undefined) {
throw new Error(`Attribute name must be defined.`);
}
meta.token = new LiteralExpr(param.attributeName);
meta.resolved = R3ResolvedDependencyType.Attribute;
meta.token = param.attributeName;
meta.resolved = compiler.R3ResolvedDependencyType.Attribute;
} else {
setTokenAndResolvedType(param);
}