angular2
Version:
Angular 2 - a web framework for modern web apps
344 lines (343 loc) • 15.1 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { resolveForwardRef } from 'angular2/src/core/di';
import { Type, isBlank, isPresent, isArray, stringify, isString } from 'angular2/src/facade/lang';
import { StringMapWrapper } from 'angular2/src/facade/collection';
import { BaseException } from 'angular2/src/facade/exceptions';
import { NoAnnotationError } from 'angular2/src/core/di/reflective_exceptions';
import * as cpl from './compile_metadata';
import * as md from 'angular2/src/core/metadata/directives';
import * as dimd from 'angular2/src/core/metadata/di';
import { DirectiveResolver } from './directive_resolver';
import { PipeResolver } from './pipe_resolver';
import { ViewResolver } from './view_resolver';
import { hasLifecycleHook } from './directive_lifecycle_reflector';
import { LIFECYCLE_HOOKS_VALUES } from 'angular2/src/core/metadata/lifecycle_hooks';
import { reflector } from 'angular2/src/core/reflection/reflection';
import { Injectable, Inject, Optional } from 'angular2/src/core/di';
import { PLATFORM_DIRECTIVES, PLATFORM_PIPES } from 'angular2/src/core/platform_directives_and_pipes';
import { MODULE_SUFFIX, sanitizeIdentifier } from './util';
import { assertArrayOfStrings } from './assertions';
import { getUrlScheme } from 'angular2/src/compiler/url_resolver';
import { Provider } from 'angular2/src/core/di/provider';
import { constructDependencies } from 'angular2/src/core/di/reflective_provider';
import { SelfMetadata, HostMetadata, SkipSelfMetadata } from 'angular2/src/core/di/metadata';
import { ReflectorReader } from 'angular2/src/core/reflection/reflector_reader';
export let RuntimeMetadataResolver = class RuntimeMetadataResolver {
constructor(_directiveResolver, _pipeResolver, _viewResolver, _platformDirectives, _platformPipes, _reflector) {
this._directiveResolver = _directiveResolver;
this._pipeResolver = _pipeResolver;
this._viewResolver = _viewResolver;
this._platformDirectives = _platformDirectives;
this._platformPipes = _platformPipes;
this._directiveCache = new Map();
this._pipeCache = new Map();
this._anonymousTypes = new Map();
this._anonymousTypeIndex = 0;
if (isPresent(_reflector)) {
this._reflector = _reflector;
}
else {
this._reflector = reflector;
}
}
sanitizeTokenName(token) {
let identifier = stringify(token);
if (identifier.indexOf('(') >= 0) {
// case: anonymous functions!
let found = this._anonymousTypes.get(token);
if (isBlank(found)) {
this._anonymousTypes.set(token, this._anonymousTypeIndex++);
found = this._anonymousTypes.get(token);
}
identifier = `anonymous_token_${found}_`;
}
return sanitizeIdentifier(identifier);
}
getDirectiveMetadata(directiveType) {
var meta = this._directiveCache.get(directiveType);
if (isBlank(meta)) {
var dirMeta = this._directiveResolver.resolve(directiveType);
var moduleUrl = null;
var templateMeta = null;
var changeDetectionStrategy = null;
var viewProviders = [];
if (dirMeta instanceof md.ComponentMetadata) {
assertArrayOfStrings('styles', dirMeta.styles);
var cmpMeta = dirMeta;
moduleUrl = calcModuleUrl(this._reflector, directiveType, cmpMeta);
var viewMeta = this._viewResolver.resolve(directiveType);
assertArrayOfStrings('styles', viewMeta.styles);
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,
template: viewMeta.template,
templateUrl: viewMeta.templateUrl,
styles: viewMeta.styles,
styleUrls: viewMeta.styleUrls
});
changeDetectionStrategy = cmpMeta.changeDetection;
if (isPresent(dirMeta.viewProviders)) {
viewProviders = this.getProvidersMetadata(dirMeta.viewProviders);
}
}
var providers = [];
if (isPresent(dirMeta.providers)) {
providers = this.getProvidersMetadata(dirMeta.providers);
}
var queries = [];
var viewQueries = [];
if (isPresent(dirMeta.queries)) {
queries = this.getQueriesMetadata(dirMeta.queries, false);
viewQueries = this.getQueriesMetadata(dirMeta.queries, true);
}
meta = cpl.CompileDirectiveMetadata.create({
selector: dirMeta.selector,
exportAs: dirMeta.exportAs,
isComponent: isPresent(templateMeta),
type: this.getTypeMetadata(directiveType, moduleUrl),
template: templateMeta,
changeDetection: changeDetectionStrategy,
inputs: dirMeta.inputs,
outputs: dirMeta.outputs,
host: dirMeta.host,
lifecycleHooks: LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, directiveType)),
providers: providers,
viewProviders: viewProviders,
queries: queries,
viewQueries: viewQueries
});
this._directiveCache.set(directiveType, meta);
}
return meta;
}
getTypeMetadata(type, moduleUrl) {
return new cpl.CompileTypeMetadata({
name: this.sanitizeTokenName(type),
moduleUrl: moduleUrl,
runtime: type,
diDeps: this.getDependenciesMetadata(type, null)
});
}
getFactoryMetadata(factory, moduleUrl) {
return new cpl.CompileFactoryMetadata({
name: this.sanitizeTokenName(factory),
moduleUrl: moduleUrl,
runtime: factory,
diDeps: this.getDependenciesMetadata(factory, null)
});
}
getPipeMetadata(pipeType) {
var meta = this._pipeCache.get(pipeType);
if (isBlank(meta)) {
var pipeMeta = this._pipeResolver.resolve(pipeType);
var moduleUrl = this._reflector.importUri(pipeType);
meta = new cpl.CompilePipeMetadata({
type: this.getTypeMetadata(pipeType, moduleUrl),
name: pipeMeta.name,
pure: pipeMeta.pure,
lifecycleHooks: LIFECYCLE_HOOKS_VALUES.filter(hook => hasLifecycleHook(hook, pipeType)),
});
this._pipeCache.set(pipeType, meta);
}
return meta;
}
getViewDirectivesMetadata(component) {
var view = this._viewResolver.resolve(component);
var directives = flattenDirectives(view, this._platformDirectives);
for (var i = 0; i < directives.length; i++) {
if (!isValidType(directives[i])) {
throw new BaseException(`Unexpected directive value '${stringify(directives[i])}' on the View of component '${stringify(component)}'`);
}
}
return directives.map(type => this.getDirectiveMetadata(type));
}
getViewPipesMetadata(component) {
var view = this._viewResolver.resolve(component);
var pipes = flattenPipes(view, this._platformPipes);
for (var i = 0; i < pipes.length; i++) {
if (!isValidType(pipes[i])) {
throw new BaseException(`Unexpected piped value '${stringify(pipes[i])}' on the View of component '${stringify(component)}'`);
}
}
return pipes.map(type => this.getPipeMetadata(type));
}
getDependenciesMetadata(typeOrFunc, dependencies) {
var deps;
try {
deps = constructDependencies(typeOrFunc, dependencies);
}
catch (e) {
if (e instanceof NoAnnotationError) {
deps = [];
}
else {
throw e;
}
}
return deps.map((dep) => {
var compileToken;
var p = dep.properties.find(p => p instanceof dimd.AttributeMetadata);
var isAttribute = false;
if (isPresent(p)) {
compileToken = this.getTokenMetadata(p.attributeName);
isAttribute = true;
}
else {
compileToken = this.getTokenMetadata(dep.key.token);
}
var compileQuery = null;
var q = dep.properties.find(p => p instanceof dimd.QueryMetadata);
if (isPresent(q)) {
compileQuery = this.getQueryMetadata(q, null);
}
return new cpl.CompileDiDependencyMetadata({
isAttribute: isAttribute,
isHost: dep.upperBoundVisibility instanceof HostMetadata,
isSelf: dep.upperBoundVisibility instanceof SelfMetadata,
isSkipSelf: dep.lowerBoundVisibility instanceof SkipSelfMetadata,
isOptional: dep.optional,
query: isPresent(q) && !q.isViewQuery ? compileQuery : null,
viewQuery: isPresent(q) && q.isViewQuery ? compileQuery : null,
token: compileToken
});
});
}
getTokenMetadata(token) {
token = resolveForwardRef(token);
var compileToken;
if (isString(token)) {
compileToken = new cpl.CompileTokenMetadata({ value: token });
}
else {
compileToken = new cpl.CompileTokenMetadata({
identifier: new cpl.CompileIdentifierMetadata({ runtime: token, name: this.sanitizeTokenName(token) })
});
}
return compileToken;
}
getProvidersMetadata(providers) {
return providers.map((provider) => {
provider = resolveForwardRef(provider);
if (isArray(provider)) {
return this.getProvidersMetadata(provider);
}
else if (provider instanceof Provider) {
return this.getProviderMetadata(provider);
}
else {
return this.getTypeMetadata(provider, null);
}
});
}
getProviderMetadata(provider) {
var compileDeps;
if (isPresent(provider.useClass)) {
compileDeps = this.getDependenciesMetadata(provider.useClass, provider.dependencies);
}
else if (isPresent(provider.useFactory)) {
compileDeps = this.getDependenciesMetadata(provider.useFactory, provider.dependencies);
}
return new cpl.CompileProviderMetadata({
token: this.getTokenMetadata(provider.token),
useClass: isPresent(provider.useClass) ? this.getTypeMetadata(provider.useClass, null) : null,
useValue: isPresent(provider.useValue) ?
new cpl.CompileIdentifierMetadata({ runtime: provider.useValue }) :
null,
useFactory: isPresent(provider.useFactory) ?
this.getFactoryMetadata(provider.useFactory, null) :
null,
useExisting: isPresent(provider.useExisting) ? this.getTokenMetadata(provider.useExisting) :
null,
deps: compileDeps,
multi: provider.multi
});
}
getQueriesMetadata(queries, isViewQuery) {
var compileQueries = [];
StringMapWrapper.forEach(queries, (query, propertyName) => {
if (query.isViewQuery === isViewQuery) {
compileQueries.push(this.getQueryMetadata(query, propertyName));
}
});
return compileQueries;
}
getQueryMetadata(q, propertyName) {
var selectors;
if (q.isVarBindingQuery) {
selectors = q.varBindings.map(varName => this.getTokenMetadata(varName));
}
else {
selectors = [this.getTokenMetadata(q.selector)];
}
return new cpl.CompileQueryMetadata({
selectors: selectors,
first: q.first,
descendants: q.descendants,
propertyName: propertyName,
read: isPresent(q.read) ? this.getTokenMetadata(q.read) : null
});
}
};
RuntimeMetadataResolver = __decorate([
Injectable(),
__param(3, Optional()),
__param(3, Inject(PLATFORM_DIRECTIVES)),
__param(4, Optional()),
__param(4, Inject(PLATFORM_PIPES)),
__metadata('design:paramtypes', [DirectiveResolver, PipeResolver, ViewResolver, Array, Array, ReflectorReader])
], RuntimeMetadataResolver);
function flattenDirectives(view, platformDirectives) {
let directives = [];
if (isPresent(platformDirectives)) {
flattenArray(platformDirectives, directives);
}
if (isPresent(view.directives)) {
flattenArray(view.directives, directives);
}
return directives;
}
function flattenPipes(view, platformPipes) {
let pipes = [];
if (isPresent(platformPipes)) {
flattenArray(platformPipes, pipes);
}
if (isPresent(view.pipes)) {
flattenArray(view.pipes, pipes);
}
return pipes;
}
function flattenArray(tree, out) {
for (var i = 0; i < tree.length; i++) {
var item = resolveForwardRef(tree[i]);
if (isArray(item)) {
flattenArray(item, out);
}
else {
out.push(item);
}
}
}
function isValidType(value) {
return isPresent(value) && (value instanceof Type);
}
function calcModuleUrl(reflector, type, cmpMetadata) {
var moduleId = cmpMetadata.moduleId;
if (isPresent(moduleId)) {
var scheme = getUrlScheme(moduleId);
return isPresent(scheme) && scheme.length > 0 ? moduleId :
`package:${moduleId}${MODULE_SUFFIX}`;
}
else {
return reflector.importUri(type);
}
}