refactor: move angular source to /packages rather than modules/@angular
This commit is contained in:
123
packages/core/src/linker/compiler.ts
Normal file
123
packages/core/src/linker/compiler.ts
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @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 {Injectable, InjectionToken} from '../di';
|
||||
import {MissingTranslationStrategy} from '../i18n/tokens';
|
||||
import {ViewEncapsulation} from '../metadata';
|
||||
import {Type} from '../type';
|
||||
|
||||
import {ComponentFactory} from './component_factory';
|
||||
import {NgModuleFactory} from './ng_module_factory';
|
||||
|
||||
/**
|
||||
* Combination of NgModuleFactory and ComponentFactorys.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export class ModuleWithComponentFactories<T> {
|
||||
constructor(
|
||||
public ngModuleFactory: NgModuleFactory<T>,
|
||||
public componentFactories: ComponentFactory<any>[]) {}
|
||||
}
|
||||
|
||||
|
||||
function _throwError() {
|
||||
throw new Error(`Runtime compiler is not loaded`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Low-level service for running the angular compiler during runtime
|
||||
* to create {@link ComponentFactory}s, which
|
||||
* can later be used to create and render a Component instance.
|
||||
*
|
||||
* Each `@NgModule` provides an own `Compiler` to its injector,
|
||||
* that will use the directives/pipes of the ng module for compilation
|
||||
* of components.
|
||||
* @stable
|
||||
*/
|
||||
@Injectable()
|
||||
export class Compiler {
|
||||
/**
|
||||
* Compiles the given NgModule and all of its components. All templates of the components listed
|
||||
* in `entryComponents` have to be inlined.
|
||||
*/
|
||||
compileModuleSync<T>(moduleType: Type<T>): NgModuleFactory<T> { throw _throwError(); }
|
||||
|
||||
/**
|
||||
* Compiles the given NgModule and all of its components
|
||||
*/
|
||||
compileModuleAsync<T>(moduleType: Type<T>): Promise<NgModuleFactory<T>> { throw _throwError(); }
|
||||
|
||||
/**
|
||||
* Same as {@link compileModuleSync} but also creates ComponentFactories for all components.
|
||||
*/
|
||||
compileModuleAndAllComponentsSync<T>(moduleType: Type<T>): ModuleWithComponentFactories<T> {
|
||||
throw _throwError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link compileModuleAsync} but also creates ComponentFactories for all components.
|
||||
*/
|
||||
compileModuleAndAllComponentsAsync<T>(moduleType: Type<T>):
|
||||
Promise<ModuleWithComponentFactories<T>> {
|
||||
throw _throwError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the CSS-style selectors that have been used in `ngContent` directives within
|
||||
* the template of the given component.
|
||||
* This is used by the `upgrade` library to compile the appropriate transclude content
|
||||
* in the AngularJS wrapper component.
|
||||
*/
|
||||
getNgContentSelectors(component: Type<any>): string[] { throw _throwError(); }
|
||||
|
||||
/**
|
||||
* Clears all caches.
|
||||
*/
|
||||
clearCache(): void {}
|
||||
|
||||
/**
|
||||
* Clears the cache for the given component/ngModule.
|
||||
*/
|
||||
clearCacheFor(type: Type<any>) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating a compiler
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export type CompilerOptions = {
|
||||
/**
|
||||
* @deprecated since v4 this option has no effect anymore.
|
||||
*/
|
||||
useDebug?: boolean,
|
||||
useJit?: boolean,
|
||||
defaultEncapsulation?: ViewEncapsulation,
|
||||
providers?: any[],
|
||||
missingTranslation?: MissingTranslationStrategy,
|
||||
// Whether to support the `<template>` tag and the `template` attribute to define angular
|
||||
// templates. They have been deprecated in 4.x, `<ng-template>` should be used instead.
|
||||
enableLegacyTemplate?: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
* Token to provide CompilerOptions in the platform injector.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export const COMPILER_OPTIONS = new InjectionToken<CompilerOptions[]>('compilerOptions');
|
||||
|
||||
/**
|
||||
* A factory for creating a Compiler
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class CompilerFactory {
|
||||
abstract createCompiler(options?: CompilerOptions[]): Compiler;
|
||||
}
|
77
packages/core/src/linker/component_factory.ts
Normal file
77
packages/core/src/linker/component_factory.ts
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @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 {ChangeDetectorRef} from '../change_detection/change_detection';
|
||||
import {Injector} from '../di/injector';
|
||||
import {Type} from '../type';
|
||||
|
||||
import {ElementRef} from './element_ref';
|
||||
import {ViewRef} from './view_ref';
|
||||
|
||||
/**
|
||||
* Represents an instance of a Component created via a {@link ComponentFactory}.
|
||||
*
|
||||
* `ComponentRef` provides access to the Component Instance as well other objects related to this
|
||||
* Component Instance and allows you to destroy the Component Instance via the {@link #destroy}
|
||||
* method.
|
||||
* @stable
|
||||
*/
|
||||
export abstract class ComponentRef<C> {
|
||||
/**
|
||||
* Location of the Host Element of this Component Instance.
|
||||
*/
|
||||
abstract get location(): ElementRef;
|
||||
|
||||
/**
|
||||
* The injector on which the component instance exists.
|
||||
*/
|
||||
abstract get injector(): Injector;
|
||||
|
||||
/**
|
||||
* The instance of the Component.
|
||||
*/
|
||||
abstract get instance(): C;
|
||||
|
||||
/**
|
||||
* The {@link ViewRef} of the Host View of this Component instance.
|
||||
*/
|
||||
abstract get hostView(): ViewRef;
|
||||
|
||||
/**
|
||||
* The {@link ChangeDetectorRef} of the Component instance.
|
||||
*/
|
||||
abstract get changeDetectorRef(): ChangeDetectorRef;
|
||||
|
||||
/**
|
||||
* The component type.
|
||||
*/
|
||||
abstract get componentType(): Type<any>;
|
||||
|
||||
/**
|
||||
* Destroys the component instance and all of the data structures associated with it.
|
||||
*/
|
||||
abstract destroy(): void;
|
||||
|
||||
/**
|
||||
* Allows to register a callback that will be called when the component is destroyed.
|
||||
*/
|
||||
abstract onDestroy(callback: Function): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @stable
|
||||
*/
|
||||
export abstract class ComponentFactory<C> {
|
||||
abstract get selector(): string;
|
||||
abstract get componentType(): Type<any>;
|
||||
/**
|
||||
* Creates a new component.
|
||||
*/
|
||||
abstract create(injector: Injector, projectableNodes?: any[][], rootSelectorOrNode?: string|any):
|
||||
ComponentRef<C>;
|
||||
}
|
61
packages/core/src/linker/component_factory_resolver.ts
Normal file
61
packages/core/src/linker/component_factory_resolver.ts
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @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 {Type} from '../type';
|
||||
import {stringify} from '../util';
|
||||
|
||||
import {ComponentFactory} from './component_factory';
|
||||
|
||||
|
||||
|
||||
export function noComponentFactoryError(component: Function) {
|
||||
const error = Error(
|
||||
`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
|
||||
(error as any)[ERROR_COMPONENT] = component;
|
||||
return error;
|
||||
}
|
||||
|
||||
const ERROR_COMPONENT = 'ngComponent';
|
||||
|
||||
export function getComponent(error: Error): Type<any> {
|
||||
return (error as any)[ERROR_COMPONENT];
|
||||
}
|
||||
|
||||
|
||||
class _NullComponentFactoryResolver implements ComponentFactoryResolver {
|
||||
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
||||
throw noComponentFactoryError(component);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @stable
|
||||
*/
|
||||
export abstract class ComponentFactoryResolver {
|
||||
static NULL: ComponentFactoryResolver = new _NullComponentFactoryResolver();
|
||||
abstract resolveComponentFactory<T>(component: Type<T>): ComponentFactory<T>;
|
||||
}
|
||||
|
||||
export class CodegenComponentFactoryResolver implements ComponentFactoryResolver {
|
||||
private _factories = new Map<any, ComponentFactory<any>>();
|
||||
|
||||
constructor(factories: ComponentFactory<any>[], private _parent: ComponentFactoryResolver) {
|
||||
for (let i = 0; i < factories.length; i++) {
|
||||
const factory = factories[i];
|
||||
this._factories.set(factory.componentType, factory);
|
||||
}
|
||||
}
|
||||
|
||||
resolveComponentFactory<T>(component: {new (...args: any[]): T}): ComponentFactory<T> {
|
||||
let result = this._factories.get(component);
|
||||
if (!result) {
|
||||
result = this._parent.resolveComponentFactory(component);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
48
packages/core/src/linker/element_ref.ts
Normal file
48
packages/core/src/linker/element_ref.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @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 wrapper around a native element inside of a View.
|
||||
*
|
||||
* An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
|
||||
* element.
|
||||
*
|
||||
* @security Permitting direct access to the DOM can make your application more vulnerable to
|
||||
* XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
|
||||
* [Security Guide](http://g.co/ng/security).
|
||||
*
|
||||
* @stable
|
||||
*/
|
||||
// Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
|
||||
// i.e. users have to ask for what they need. With that, we can build better analysis tools
|
||||
// and could do better codegen in the future.
|
||||
export class ElementRef {
|
||||
/**
|
||||
* The underlying native element or `null` if direct access to native elements is not supported
|
||||
* (e.g. when the application runs in a web worker).
|
||||
*
|
||||
* <div class="callout is-critical">
|
||||
* <header>Use with caution</header>
|
||||
* <p>
|
||||
* Use this API as the last resort when direct access to DOM is needed. Use templating and
|
||||
* data-binding provided by Angular instead. Alternatively you take a look at {@link Renderer}
|
||||
* which provides API that can safely be used even when direct access to native elements is not
|
||||
* supported.
|
||||
* </p>
|
||||
* <p>
|
||||
* Relying on direct DOM access creates tight coupling between your application and rendering
|
||||
* layers which will make it impossible to separate the two and deploy your application into a
|
||||
* web worker.
|
||||
* </p>
|
||||
* </div>
|
||||
* @stable
|
||||
*/
|
||||
public nativeElement: any;
|
||||
|
||||
constructor(nativeElement: any) { this.nativeElement = nativeElement; }
|
||||
}
|
121
packages/core/src/linker/ng_module_factory.ts
Normal file
121
packages/core/src/linker/ng_module_factory.ts
Normal file
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @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 {Injector, THROW_IF_NOT_FOUND} from '../di/injector';
|
||||
import {Type} from '../type';
|
||||
import {stringify} from '../util';
|
||||
|
||||
import {ComponentFactory} from './component_factory';
|
||||
import {CodegenComponentFactoryResolver, ComponentFactoryResolver} from './component_factory_resolver';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Represents an instance of an NgModule created via a {@link NgModuleFactory}.
|
||||
*
|
||||
* `NgModuleRef` provides access to the NgModule Instance as well other objects related to this
|
||||
* NgModule Instance.
|
||||
*
|
||||
* @stable
|
||||
*/
|
||||
export abstract class NgModuleRef<T> {
|
||||
/**
|
||||
* The injector that contains all of the providers of the NgModule.
|
||||
*/
|
||||
abstract get injector(): Injector;
|
||||
|
||||
/**
|
||||
* The ComponentFactoryResolver to get hold of the ComponentFactories
|
||||
* declared in the `entryComponents` property of the module.
|
||||
*/
|
||||
abstract get componentFactoryResolver(): ComponentFactoryResolver;
|
||||
|
||||
/**
|
||||
* The NgModule instance.
|
||||
*/
|
||||
abstract get instance(): T;
|
||||
|
||||
/**
|
||||
* Destroys the module instance and all of the data structures associated with it.
|
||||
*/
|
||||
abstract destroy(): void;
|
||||
|
||||
/**
|
||||
* Allows to register a callback that will be called when the module is destroyed.
|
||||
*/
|
||||
abstract onDestroy(callback: () => void): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export class NgModuleFactory<T> {
|
||||
constructor(
|
||||
private _injectorClass: {new (parentInjector: Injector): NgModuleInjector<T>},
|
||||
private _moduleType: Type<T>) {}
|
||||
|
||||
get moduleType(): Type<T> { return this._moduleType; }
|
||||
|
||||
create(parentInjector: Injector): NgModuleRef<T> {
|
||||
if (!parentInjector) {
|
||||
parentInjector = Injector.NULL;
|
||||
}
|
||||
const instance = new this._injectorClass(parentInjector);
|
||||
instance.create();
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
const _UNDEFINED = new Object();
|
||||
|
||||
export abstract class NgModuleInjector<T> extends CodegenComponentFactoryResolver implements
|
||||
Injector,
|
||||
NgModuleRef<T> {
|
||||
private _destroyListeners: (() => void)[] = [];
|
||||
private _destroyed: boolean = false;
|
||||
|
||||
public instance: T;
|
||||
|
||||
constructor(
|
||||
public parent: Injector, factories: ComponentFactory<any>[],
|
||||
public bootstrapFactories: ComponentFactory<any>[]) {
|
||||
super(factories, parent.get(ComponentFactoryResolver, ComponentFactoryResolver.NULL));
|
||||
}
|
||||
|
||||
create() { this.instance = this.createInternal(); }
|
||||
|
||||
abstract createInternal(): T;
|
||||
|
||||
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND): any {
|
||||
if (token === Injector || token === ComponentFactoryResolver) {
|
||||
return this;
|
||||
}
|
||||
const result = this.getInternal(token, _UNDEFINED);
|
||||
return result === _UNDEFINED ? this.parent.get(token, notFoundValue) : result;
|
||||
}
|
||||
|
||||
abstract getInternal(token: any, notFoundValue: any): any;
|
||||
|
||||
get injector(): Injector { return this; }
|
||||
|
||||
get componentFactoryResolver(): ComponentFactoryResolver { return this; }
|
||||
|
||||
destroy(): void {
|
||||
if (this._destroyed) {
|
||||
throw new Error(
|
||||
`The ng module ${stringify(this.instance.constructor)} has already been destroyed.`);
|
||||
}
|
||||
this._destroyed = true;
|
||||
this.destroyInternal();
|
||||
this._destroyListeners.forEach((listener) => listener());
|
||||
}
|
||||
|
||||
onDestroy(callback: () => void): void { this._destroyListeners.push(callback); }
|
||||
|
||||
abstract destroyInternal(): void;
|
||||
}
|
48
packages/core/src/linker/ng_module_factory_loader.ts
Normal file
48
packages/core/src/linker/ng_module_factory_loader.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @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 {NgModuleFactory} from './ng_module_factory';
|
||||
|
||||
/**
|
||||
* Used to load ng module factories.
|
||||
* @stable
|
||||
*/
|
||||
export abstract class NgModuleFactoryLoader {
|
||||
abstract load(path: string): Promise<NgModuleFactory<any>>;
|
||||
}
|
||||
|
||||
let moduleFactories = new Map<string, NgModuleFactory<any>>();
|
||||
|
||||
/**
|
||||
* Registers a loaded module. Should only be called from generated NgModuleFactory code.
|
||||
* @experimental
|
||||
*/
|
||||
export function registerModuleFactory(id: string, factory: NgModuleFactory<any>) {
|
||||
const existing = moduleFactories.get(id);
|
||||
if (existing) {
|
||||
throw new Error(`Duplicate module registered for ${id
|
||||
} - ${existing.moduleType.name} vs ${factory.moduleType.name}`);
|
||||
}
|
||||
moduleFactories.set(id, factory);
|
||||
}
|
||||
|
||||
export function clearModulesForTest() {
|
||||
moduleFactories = new Map<string, NgModuleFactory<any>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the NgModuleFactory with the given id, if it exists and has been loaded.
|
||||
* Factories for modules that do not specify an `id` cannot be retrieved. Throws if the module
|
||||
* cannot be found.
|
||||
* @experimental
|
||||
*/
|
||||
export function getModuleFactory(id: string): NgModuleFactory<any> {
|
||||
const factory = moduleFactories.get(id);
|
||||
if (!factory) throw new Error(`No module with ID ${id} loaded`);
|
||||
return factory;
|
||||
}
|
115
packages/core/src/linker/query_list.ts
Normal file
115
packages/core/src/linker/query_list.ts
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @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 {Observable} from 'rxjs/Observable';
|
||||
|
||||
import {EventEmitter} from '../event_emitter';
|
||||
import {getSymbolIterator} from '../util';
|
||||
|
||||
|
||||
/**
|
||||
* An unmodifiable list of items that Angular keeps up to date when the state
|
||||
* of the application changes.
|
||||
*
|
||||
* The type of object that {@link Query} and {@link ViewQueryMetadata} provide.
|
||||
*
|
||||
* Implements an iterable interface, therefore it can be used in both ES6
|
||||
* javascript `for (var i of items)` loops as well as in Angular templates with
|
||||
* `*ngFor="let i of myList"`.
|
||||
*
|
||||
* Changes can be observed by subscribing to the changes `Observable`.
|
||||
*
|
||||
* NOTE: In the future this class will implement an `Observable` interface.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/RX8sJnQYl9FWuSCWme5z?p=preview))
|
||||
* ```typescript
|
||||
* @Component({...})
|
||||
* class Container {
|
||||
* @ViewChildren(Item) items:QueryList<Item>;
|
||||
* }
|
||||
* ```
|
||||
* @stable
|
||||
*/
|
||||
export class QueryList<T>/* implements Iterable<T> */ {
|
||||
private _dirty = true;
|
||||
private _results: Array<T> = [];
|
||||
private _emitter = new EventEmitter();
|
||||
|
||||
get changes(): Observable<any> { return this._emitter; }
|
||||
get length(): number { return this._results.length; }
|
||||
get first(): T { return this._results[0]; }
|
||||
get last(): T { return this._results[this.length - 1]; }
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
||||
*/
|
||||
map<U>(fn: (item: T, index: number, array: T[]) => U): U[] { return this._results.map(fn); }
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
|
||||
*/
|
||||
filter(fn: (item: T, index: number, array: T[]) => boolean): T[] {
|
||||
return this._results.filter(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
|
||||
*/
|
||||
find(fn: (item: T, index: number, array: T[]) => boolean): T { return this._results.find(fn); }
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
|
||||
*/
|
||||
reduce<U>(fn: (prevValue: U, curValue: T, curIndex: number, array: T[]) => U, init: U): U {
|
||||
return this._results.reduce(fn, init);
|
||||
}
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
|
||||
*/
|
||||
forEach(fn: (item: T, index: number, array: T[]) => void): void { this._results.forEach(fn); }
|
||||
|
||||
/**
|
||||
* See
|
||||
* [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
|
||||
*/
|
||||
some(fn: (value: T, index: number, array: T[]) => boolean): boolean {
|
||||
return this._results.some(fn);
|
||||
}
|
||||
|
||||
toArray(): T[] { return this._results.slice(); }
|
||||
|
||||
[getSymbolIterator()](): Iterator<T> { return (this._results as any)[getSymbolIterator()](); }
|
||||
|
||||
toString(): string { return this._results.toString(); }
|
||||
|
||||
reset(res: Array<T|any[]>): void {
|
||||
this._results = flatten(res);
|
||||
this._dirty = false;
|
||||
}
|
||||
|
||||
notifyOnChanges(): void { this._emitter.emit(this); }
|
||||
|
||||
/** internal */
|
||||
setDirty() { this._dirty = true; }
|
||||
|
||||
/** internal */
|
||||
get dirty() { return this._dirty; }
|
||||
}
|
||||
|
||||
function flatten<T>(list: Array<T|T[]>): T[] {
|
||||
return list.reduce((flat: any[], item: T | T[]): T[] => {
|
||||
const flatItem = Array.isArray(item) ? flatten(item) : item;
|
||||
return (<T[]>flat).concat(flatItem);
|
||||
}, []);
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @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 {Injectable, Optional} from '../di';
|
||||
|
||||
import {Compiler} from './compiler';
|
||||
import {NgModuleFactory} from './ng_module_factory';
|
||||
import {NgModuleFactoryLoader} from './ng_module_factory_loader';
|
||||
|
||||
const _SEPARATOR = '#';
|
||||
|
||||
const FACTORY_CLASS_SUFFIX = 'NgFactory';
|
||||
|
||||
/**
|
||||
* Configuration for SystemJsNgModuleLoader.
|
||||
* token.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class SystemJsNgModuleLoaderConfig {
|
||||
/**
|
||||
* Prefix to add when computing the name of the factory module for a given module name.
|
||||
*/
|
||||
factoryPathPrefix: string;
|
||||
|
||||
/**
|
||||
* Suffix to add when computing the name of the factory module for a given module name.
|
||||
*/
|
||||
factoryPathSuffix: string;
|
||||
}
|
||||
|
||||
const DEFAULT_CONFIG: SystemJsNgModuleLoaderConfig = {
|
||||
factoryPathPrefix: '',
|
||||
factoryPathSuffix: '.ngfactory',
|
||||
};
|
||||
|
||||
/**
|
||||
* NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
|
||||
* @experimental
|
||||
*/
|
||||
@Injectable()
|
||||
export class SystemJsNgModuleLoader implements NgModuleFactoryLoader {
|
||||
private _config: SystemJsNgModuleLoaderConfig;
|
||||
|
||||
constructor(private _compiler: Compiler, @Optional() config?: SystemJsNgModuleLoaderConfig) {
|
||||
this._config = config || DEFAULT_CONFIG;
|
||||
}
|
||||
|
||||
load(path: string): Promise<NgModuleFactory<any>> {
|
||||
const offlineMode = this._compiler instanceof Compiler;
|
||||
return offlineMode ? this.loadFactory(path) : this.loadAndCompile(path);
|
||||
}
|
||||
|
||||
private loadAndCompile(path: string): Promise<NgModuleFactory<any>> {
|
||||
let [module, exportName] = path.split(_SEPARATOR);
|
||||
if (exportName === undefined) {
|
||||
exportName = 'default';
|
||||
}
|
||||
|
||||
return System.import(module)
|
||||
.then((module: any) => module[exportName])
|
||||
.then((type: any) => checkNotEmpty(type, module, exportName))
|
||||
.then((type: any) => this._compiler.compileModuleAsync(type));
|
||||
}
|
||||
|
||||
private loadFactory(path: string): Promise<NgModuleFactory<any>> {
|
||||
let [module, exportName] = path.split(_SEPARATOR);
|
||||
let factoryClassSuffix = FACTORY_CLASS_SUFFIX;
|
||||
if (exportName === undefined) {
|
||||
exportName = 'default';
|
||||
factoryClassSuffix = '';
|
||||
}
|
||||
|
||||
return System.import(this._config.factoryPathPrefix + module + this._config.factoryPathSuffix)
|
||||
.then((module: any) => module[exportName + factoryClassSuffix])
|
||||
.then((factory: any) => checkNotEmpty(factory, module, exportName));
|
||||
}
|
||||
}
|
||||
|
||||
function checkNotEmpty(value: any, modulePath: string, exportName: string): any {
|
||||
if (!value) {
|
||||
throw new Error(`Cannot find '${exportName}' in '${modulePath}'`);
|
||||
}
|
||||
return value;
|
||||
}
|
42
packages/core/src/linker/template_ref.ts
Normal file
42
packages/core/src/linker/template_ref.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @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 {ElementRef} from './element_ref';
|
||||
import {EmbeddedViewRef} from './view_ref';
|
||||
|
||||
|
||||
/**
|
||||
* Represents an Embedded Template that can be used to instantiate Embedded Views.
|
||||
*
|
||||
* You can access a `TemplateRef`, in two ways. Via a directive placed on a `<ng-template>` element
|
||||
* (or directive prefixed with `*`) and have the `TemplateRef` for this Embedded View injected into
|
||||
* the constructor of the directive using the `TemplateRef` Token. Alternatively you can query for
|
||||
* the `TemplateRef` from a Component or a Directive via {@link Query}.
|
||||
*
|
||||
* To instantiate Embedded Views based on a Template, use
|
||||
* {@link ViewContainerRef#createEmbeddedView}, which will create the View and attach it to the
|
||||
* View Container.
|
||||
* @stable
|
||||
*/
|
||||
export abstract class TemplateRef<C> {
|
||||
/**
|
||||
* The location in the View where the Embedded View logically belongs to.
|
||||
*
|
||||
* The data-binding and injection contexts of Embedded Views created from this `TemplateRef`
|
||||
* inherit from the contexts of this location.
|
||||
*
|
||||
* Typically new Embedded Views are attached to the View Container of this location, but in
|
||||
* advanced use-cases, the View can be attached to a different container while keeping the
|
||||
* data-binding and injection context from the original location.
|
||||
*
|
||||
*/
|
||||
// TODO(i): rename to anchor or location
|
||||
abstract get elementRef(): ElementRef;
|
||||
|
||||
abstract createEmbeddedView(context: C): EmbeddedViewRef<C>;
|
||||
}
|
123
packages/core/src/linker/view_container_ref.ts
Normal file
123
packages/core/src/linker/view_container_ref.ts
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @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 {Injector} from '../di/injector';
|
||||
import {ComponentFactory, ComponentRef} from './component_factory';
|
||||
import {ElementRef} from './element_ref';
|
||||
import {TemplateRef} from './template_ref';
|
||||
import {EmbeddedViewRef, ViewRef} from './view_ref';
|
||||
|
||||
|
||||
/**
|
||||
* Represents a container where one or more Views can be attached.
|
||||
*
|
||||
* The container can contain two kinds of Views. Host Views, created by instantiating a
|
||||
* {@link Component} via {@link #createComponent}, and Embedded Views, created by instantiating an
|
||||
* {@link TemplateRef Embedded Template} via {@link #createEmbeddedView}.
|
||||
*
|
||||
* The location of the View Container within the containing View is specified by the Anchor
|
||||
* `element`. Each View Container can have only one Anchor Element and each Anchor Element can only
|
||||
* have a single View Container.
|
||||
*
|
||||
* Root elements of Views attached to this container become siblings of the Anchor Element in
|
||||
* the Rendered View.
|
||||
*
|
||||
* To access a `ViewContainerRef` of an Element, you can either place a {@link Directive} injected
|
||||
* with `ViewContainerRef` on the Element, or you obtain it via a {@link ViewChild} query.
|
||||
* @stable
|
||||
*/
|
||||
export abstract class ViewContainerRef {
|
||||
/**
|
||||
* Anchor element that specifies the location of this container in the containing View.
|
||||
* <!-- TODO: rename to anchorElement -->
|
||||
*/
|
||||
abstract get element(): ElementRef;
|
||||
|
||||
abstract get injector(): Injector;
|
||||
|
||||
abstract get parentInjector(): Injector;
|
||||
|
||||
/**
|
||||
* Destroys all Views in this container.
|
||||
*/
|
||||
abstract clear(): void;
|
||||
|
||||
/**
|
||||
* Returns the {@link ViewRef} for the View located in this container at the specified index.
|
||||
*/
|
||||
abstract get(index: number): ViewRef;
|
||||
|
||||
/**
|
||||
* Returns the number of Views currently attached to this container.
|
||||
*/
|
||||
abstract get length(): number;
|
||||
|
||||
/**
|
||||
* Instantiates an Embedded View based on the {@link TemplateRef `templateRef`} and inserts it
|
||||
* into this container at the specified `index`.
|
||||
*
|
||||
* If `index` is not specified, the new View will be inserted as the last View in the container.
|
||||
*
|
||||
* Returns the {@link ViewRef} for the newly created View.
|
||||
*/
|
||||
abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number):
|
||||
EmbeddedViewRef<C>;
|
||||
|
||||
/**
|
||||
* Instantiates a single {@link Component} and inserts its Host View into this container at the
|
||||
* specified `index`.
|
||||
*
|
||||
* The component is instantiated using its {@link ComponentFactory} which can be
|
||||
* obtained via {@link ComponentFactoryResolver#resolveComponentFactory}.
|
||||
*
|
||||
* If `index` is not specified, the new View will be inserted as the last View in the container.
|
||||
*
|
||||
* You can optionally specify the {@link Injector} that will be used as parent for the Component.
|
||||
*
|
||||
* Returns the {@link ComponentRef} of the Host View created for the newly instantiated Component.
|
||||
*/
|
||||
abstract createComponent<C>(
|
||||
componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
|
||||
projectableNodes?: any[][]): ComponentRef<C>;
|
||||
|
||||
/**
|
||||
* Inserts a View identified by a {@link ViewRef} into the container at the specified `index`.
|
||||
*
|
||||
* If `index` is not specified, the new View will be inserted as the last View in the container.
|
||||
*
|
||||
* Returns the inserted {@link ViewRef}.
|
||||
*/
|
||||
abstract insert(viewRef: ViewRef, index?: number): ViewRef;
|
||||
|
||||
/**
|
||||
* Moves a View identified by a {@link ViewRef} into the container at the specified `index`.
|
||||
*
|
||||
* Returns the inserted {@link ViewRef}.
|
||||
*/
|
||||
abstract move(viewRef: ViewRef, currentIndex: number): ViewRef;
|
||||
|
||||
/**
|
||||
* Returns the index of the View, specified via {@link ViewRef}, within the current container or
|
||||
* `-1` if this container doesn't contain the View.
|
||||
*/
|
||||
abstract indexOf(viewRef: ViewRef): number;
|
||||
|
||||
/**
|
||||
* Destroys a View attached to this container at the specified `index`.
|
||||
*
|
||||
* If `index` is not specified, the last View in the container will be removed.
|
||||
*/
|
||||
abstract remove(index?: number): void;
|
||||
|
||||
/**
|
||||
* Use along with {@link #insert} to move a View within the current container.
|
||||
*
|
||||
* If the `index` param is omitted, the last {@link ViewRef} is detached.
|
||||
*/
|
||||
abstract detach(index?: number): ViewRef;
|
||||
}
|
90
packages/core/src/linker/view_ref.ts
Normal file
90
packages/core/src/linker/view_ref.ts
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @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 {ApplicationRef} from '../application_ref';
|
||||
import {ChangeDetectorRef} from '../change_detection/change_detector_ref';
|
||||
|
||||
|
||||
/**
|
||||
* @stable
|
||||
*/
|
||||
export abstract class ViewRef extends ChangeDetectorRef {
|
||||
/**
|
||||
* Destroys the view and all of the data structures associated with it.
|
||||
*/
|
||||
abstract destroy(): void;
|
||||
|
||||
abstract get destroyed(): boolean;
|
||||
|
||||
abstract onDestroy(callback: Function): any /** TODO #9100 */;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an Angular View.
|
||||
*
|
||||
* <!-- TODO: move the next two paragraphs to the dev guide -->
|
||||
* A View is a fundamental building block of the application UI. It is the smallest grouping of
|
||||
* Elements which are created and destroyed together.
|
||||
*
|
||||
* Properties of elements in a View can change, but the structure (number and order) of elements in
|
||||
* a View cannot. Changing the structure of Elements can only be done by inserting, moving or
|
||||
* removing nested Views via a {@link ViewContainerRef}. Each View can contain many View Containers.
|
||||
* <!-- /TODO -->
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* Given this template...
|
||||
*
|
||||
* ```
|
||||
* Count: {{items.length}}
|
||||
* <ul>
|
||||
* <li *ngFor="let item of items">{{item}}</li>
|
||||
* </ul>
|
||||
* ```
|
||||
*
|
||||
* We have two {@link TemplateRef}s:
|
||||
*
|
||||
* Outer {@link TemplateRef}:
|
||||
* ```
|
||||
* Count: {{items.length}}
|
||||
* <ul>
|
||||
* <ng-template ngFor let-item [ngForOf]="items"></ng-template>
|
||||
* </ul>
|
||||
* ```
|
||||
*
|
||||
* Inner {@link TemplateRef}:
|
||||
* ```
|
||||
* <li>{{item}}</li>
|
||||
* ```
|
||||
*
|
||||
* Notice that the original template is broken down into two separate {@link TemplateRef}s.
|
||||
*
|
||||
* The outer/inner {@link TemplateRef}s are then assembled into views like so:
|
||||
*
|
||||
* ```
|
||||
* <!-- ViewRef: outer-0 -->
|
||||
* Count: 2
|
||||
* <ul>
|
||||
* <ng-template view-container-ref></ng-template>
|
||||
* <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 -->
|
||||
* <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 -->
|
||||
* </ul>
|
||||
* <!-- /ViewRef: outer-0 -->
|
||||
* ```
|
||||
* @experimental
|
||||
*/
|
||||
export abstract class EmbeddedViewRef<C> extends ViewRef {
|
||||
abstract get context(): C;
|
||||
|
||||
abstract get rootNodes(): any[];
|
||||
}
|
||||
|
||||
export interface InternalViewRef extends ViewRef {
|
||||
detachFromAppRef(): void;
|
||||
attachToAppRef(appRef: ApplicationRef): void;
|
||||
}
|
Reference in New Issue
Block a user