feat(core): Add a long-form syntax for Angular bootstrapping.
This change adds a syntax for bootstrapping Angular on a page that allows more fine-grained control of the hierarchy created. platform() creates a platform injector (of which there can only be one). From the platform, .application() creates an Angular application including a Zone and all specified application bindings (e.g. for the DOM, HTTP, Compiler, Renderer, etc). At the application level, .bootstrap() will bootstrap the given component into that application. Closes #3852
This commit is contained in:
parent
193792c27f
commit
97d1844bfc
|
@ -5,9 +5,9 @@ export 'package:angular2/src/core/util.dart';
|
||||||
export 'package:angular2/src/core/di.dart';
|
export 'package:angular2/src/core/di.dart';
|
||||||
export 'package:angular2/src/core/pipes.dart';
|
export 'package:angular2/src/core/pipes.dart';
|
||||||
export 'package:angular2/src/core/facade.dart';
|
export 'package:angular2/src/core/facade.dart';
|
||||||
export 'package:angular2/src/core/application_ref.dart';
|
|
||||||
// Do not export application for dart. Must import from angular2/bootstrap
|
// Do not export application for dart. Must import from angular2/bootstrap
|
||||||
//export 'package:angular2/src/core/application.dart';
|
//export 'package:angular2/src/core/application.dart';
|
||||||
|
export 'package:angular2/src/core/application_ref.dart';
|
||||||
export 'package:angular2/src/core/services.dart';
|
export 'package:angular2/src/core/services.dart';
|
||||||
export 'package:angular2/src/core/compiler.dart';
|
export 'package:angular2/src/core/compiler.dart';
|
||||||
export 'package:angular2/src/core/lifecycle.dart';
|
export 'package:angular2/src/core/lifecycle.dart';
|
||||||
|
|
|
@ -6,9 +6,9 @@ import 'package:angular2/src/core/reflection/reflection.dart' show reflector;
|
||||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
|
import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
|
||||||
show ReflectionCapabilities;
|
show ReflectionCapabilities;
|
||||||
import 'application_common.dart';
|
import 'application_common.dart';
|
||||||
import 'application_ref.dart';
|
|
||||||
|
|
||||||
export 'application_ref.dart' show ApplicationRef;
|
import 'package:angular2/src/core/compiler/dynamic_component_loader.dart';
|
||||||
|
export 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show ComponentRef;
|
||||||
|
|
||||||
/// Starts an application from a root component. This implementation uses
|
/// Starts an application from a root component. This implementation uses
|
||||||
/// mirrors. Angular 2 transformer automatically replaces this method with a
|
/// mirrors. Angular 2 transformer automatically replaces this method with a
|
||||||
|
@ -16,7 +16,7 @@ export 'application_ref.dart' show ApplicationRef;
|
||||||
/// mirrors and produces a faster and more compact JS code.
|
/// mirrors and produces a faster and more compact JS code.
|
||||||
///
|
///
|
||||||
/// See [commonBootstrap] for detailed documentation.
|
/// See [commonBootstrap] for detailed documentation.
|
||||||
Future<ApplicationRef> bootstrap(Type appComponentType,
|
Future<ComponentRef> bootstrap(Type appComponentType,
|
||||||
[List componentInjectableBindings]) {
|
[List componentInjectableBindings]) {
|
||||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||||
return commonBootstrap(appComponentType, componentInjectableBindings);
|
return commonBootstrap(appComponentType, componentInjectableBindings);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
// Public API for Application
|
// Public API for Application
|
||||||
export {ApplicationRef} from './application_ref';
|
|
||||||
export {APP_COMPONENT} from './application_tokens';
|
export {APP_COMPONENT} from './application_tokens';
|
||||||
|
export {platform, commonBootstrap as bootstrap} from './application_common';
|
||||||
|
export {PlatformRef, ApplicationRef, rootBindings} from './application_ref';
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import {DEFAULT_PIPES} from 'angular2/src/core/pipes';
|
|
||||||
import {FORM_BINDINGS} from 'angular2/src/core/forms';
|
import {FORM_BINDINGS} from 'angular2/src/core/forms';
|
||||||
import {bind, Binding, Injector, OpaqueToken} from 'angular2/src/core/di';
|
import {bind, Binding, Injector, OpaqueToken} from 'angular2/src/core/di';
|
||||||
import {
|
import {
|
||||||
|
@ -10,37 +9,12 @@ import {
|
||||||
print,
|
print,
|
||||||
stringify
|
stringify
|
||||||
} from 'angular2/src/core/facade/lang';
|
} from 'angular2/src/core/facade/lang';
|
||||||
import {
|
|
||||||
BaseException,
|
|
||||||
WrappedException,
|
|
||||||
ExceptionHandler
|
|
||||||
} from 'angular2/src/core/facade/exceptions';
|
|
||||||
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
||||||
|
import {BrowserGetTestability} from 'angular2/src/core/testability/browser_testability';
|
||||||
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||||
import {Compiler, CompilerCache} from './compiler/compiler';
|
|
||||||
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
|
|
||||||
import {
|
|
||||||
Parser,
|
|
||||||
Lexer,
|
|
||||||
ChangeDetection,
|
|
||||||
DynamicChangeDetection,
|
|
||||||
JitChangeDetection,
|
|
||||||
PreGeneratedChangeDetection,
|
|
||||||
IterableDiffers,
|
|
||||||
defaultIterableDiffers,
|
|
||||||
KeyValueDiffers,
|
|
||||||
defaultKeyValueDiffers
|
|
||||||
} from 'angular2/src/core/change_detection/change_detection';
|
|
||||||
import {ViewLoader} from 'angular2/src/core/render/dom/compiler/view_loader';
|
import {ViewLoader} from 'angular2/src/core/render/dom/compiler/view_loader';
|
||||||
import {StyleUrlResolver} from 'angular2/src/core/render/dom/compiler/style_url_resolver';
|
|
||||||
import {StyleInliner} from 'angular2/src/core/render/dom/compiler/style_inliner';
|
import {StyleInliner} from 'angular2/src/core/render/dom/compiler/style_inliner';
|
||||||
import {ViewResolver} from './compiler/view_resolver';
|
|
||||||
import {DirectiveResolver} from './compiler/directive_resolver';
|
|
||||||
import {PipeResolver} from './compiler/pipe_resolver';
|
|
||||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
|
||||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
||||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
|
||||||
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
|
||||||
import {XHR} from 'angular2/src/core/render/xhr';
|
import {XHR} from 'angular2/src/core/render/xhr';
|
||||||
import {XHRImpl} from 'angular2/src/core/render/xhr_impl';
|
import {XHRImpl} from 'angular2/src/core/render/xhr_impl';
|
||||||
import {
|
import {
|
||||||
|
@ -50,8 +24,6 @@ import {
|
||||||
} from 'angular2/src/core/render/dom/events/event_manager';
|
} from 'angular2/src/core/render/dom/events/event_manager';
|
||||||
import {KeyEventsPlugin} from 'angular2/src/core/render/dom/events/key_events';
|
import {KeyEventsPlugin} from 'angular2/src/core/render/dom/events/key_events';
|
||||||
import {HammerGesturesPlugin} from 'angular2/src/core/render/dom/events/hammer_gestures';
|
import {HammerGesturesPlugin} from 'angular2/src/core/render/dom/events/hammer_gestures';
|
||||||
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
|
||||||
import {UrlResolver} from 'angular2/src/core/services/url_resolver';
|
|
||||||
import {AppRootUrl} from 'angular2/src/core/services/app_root_url';
|
import {AppRootUrl} from 'angular2/src/core/services/app_root_url';
|
||||||
import {AnchorBasedAppRootUrl} from 'angular2/src/core/services/anchor_based_app_root_url';
|
import {AnchorBasedAppRootUrl} from 'angular2/src/core/services/anchor_based_app_root_url';
|
||||||
import {
|
import {
|
||||||
|
@ -59,11 +31,6 @@ import {
|
||||||
DynamicComponentLoader
|
DynamicComponentLoader
|
||||||
} from 'angular2/src/core/compiler/dynamic_component_loader';
|
} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||||
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
||||||
import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_pool';
|
|
||||||
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
|
||||||
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
|
|
||||||
import {AppViewListener} from 'angular2/src/core/compiler/view_listener';
|
|
||||||
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
|
||||||
import {Renderer, RenderCompiler} from 'angular2/src/core/render/api';
|
import {Renderer, RenderCompiler} from 'angular2/src/core/render/api';
|
||||||
import {
|
import {
|
||||||
DomRenderer,
|
DomRenderer,
|
||||||
|
@ -81,46 +48,23 @@ import {
|
||||||
SharedStylesHost,
|
SharedStylesHost,
|
||||||
DomSharedStylesHost
|
DomSharedStylesHost
|
||||||
} from 'angular2/src/core/render/dom/view/shared_styles_host';
|
} from 'angular2/src/core/render/dom/view/shared_styles_host';
|
||||||
import {internalView} from 'angular2/src/core/compiler/view_ref';
|
|
||||||
import {APP_COMPONENT_REF_PROMISE, APP_COMPONENT} from './application_tokens';
|
|
||||||
import {wtfInit} from './profile/wtf_init';
|
|
||||||
import {EXCEPTION_BINDING} from './platform_bindings';
|
import {EXCEPTION_BINDING} from './platform_bindings';
|
||||||
import {ApplicationRef} from './application_ref';
|
|
||||||
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
||||||
import {BrowserDetails} from 'angular2/src/animate/browser_details';
|
import {BrowserDetails} from 'angular2/src/animate/browser_details';
|
||||||
|
import {wtfInit} from './profile/wtf_init';
|
||||||
|
import {platformCommon, PlatformRef, applicationCommonBindings} from './application_ref';
|
||||||
|
|
||||||
var _rootInjector: Injector;
|
/**
|
||||||
|
* A default set of bindings which apply only to an Angular application running on
|
||||||
// Contains everything that is safe to share between applications.
|
* the UI thread.
|
||||||
var _rootBindings = [bind(Reflector).toValue(reflector), TestabilityRegistry];
|
*/
|
||||||
|
export function applicationDomBindings(): Array<Type | Binding | any[]> {
|
||||||
function _injectorBindings(appComponentType): Array<Type | Binding | any[]> {
|
if (isBlank(DOM)) {
|
||||||
var bestChangeDetection = new DynamicChangeDetection();
|
throw "Must set a root DOM adapter first.";
|
||||||
if (PreGeneratedChangeDetection.isSupported()) {
|
|
||||||
bestChangeDetection = new PreGeneratedChangeDetection();
|
|
||||||
} else if (JitChangeDetection.isSupported()) {
|
|
||||||
bestChangeDetection = new JitChangeDetection();
|
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
bind(DOCUMENT)
|
bind(DOCUMENT)
|
||||||
.toValue(DOM.defaultDoc()),
|
.toValue(DOM.defaultDoc()),
|
||||||
bind(APP_COMPONENT).toValue(appComponentType),
|
|
||||||
bind(APP_COMPONENT_REF_PROMISE)
|
|
||||||
.toFactory(
|
|
||||||
(dynamicComponentLoader, injector, testability, registry) => {
|
|
||||||
// TODO(rado): investigate whether to support bindings on root component.
|
|
||||||
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector)
|
|
||||||
.then((componentRef) => {
|
|
||||||
registry.registerApplication(componentRef.location.nativeElement, testability);
|
|
||||||
return componentRef;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[DynamicComponentLoader, Injector, Testability, TestabilityRegistry]),
|
|
||||||
|
|
||||||
bind(appComponentType)
|
|
||||||
.toFactory((p: Promise<any>) => p.then(ref => ref.instance), [APP_COMPONENT_REF_PROMISE]),
|
|
||||||
bind(LifeCycle).toFactory((exceptionHandler) => new LifeCycle(null, assertionsEnabled()),
|
|
||||||
[ExceptionHandler]),
|
|
||||||
EventManager,
|
EventManager,
|
||||||
new Binding(EVENT_MANAGER_PLUGINS, {toClass: DomEventsPlugin, multi: true}),
|
new Binding(EVENT_MANAGER_PLUGINS, {toClass: DomEventsPlugin, multi: true}),
|
||||||
new Binding(EVENT_MANAGER_PLUGINS, {toClass: KeyEventsPlugin, multi: true}),
|
new Binding(EVENT_MANAGER_PLUGINS, {toClass: KeyEventsPlugin, multi: true}),
|
||||||
|
@ -135,31 +79,10 @@ function _injectorBindings(appComponentType): Array<Type | Binding | any[]> {
|
||||||
bind(RenderCompiler).toAlias(DefaultDomCompiler),
|
bind(RenderCompiler).toAlias(DefaultDomCompiler),
|
||||||
DomSharedStylesHost,
|
DomSharedStylesHost,
|
||||||
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
|
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
|
||||||
ProtoViewFactory,
|
|
||||||
AppViewPool,
|
|
||||||
bind(APP_VIEW_POOL_CAPACITY).toValue(10000),
|
|
||||||
AppViewManager,
|
|
||||||
AppViewManagerUtils,
|
|
||||||
AppViewListener,
|
|
||||||
Compiler,
|
|
||||||
CompilerCache,
|
|
||||||
ViewResolver,
|
|
||||||
DEFAULT_PIPES,
|
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
|
||||||
bind(ChangeDetection).toValue(bestChangeDetection),
|
|
||||||
ViewLoader,
|
ViewLoader,
|
||||||
DirectiveResolver,
|
|
||||||
PipeResolver,
|
|
||||||
Parser,
|
|
||||||
Lexer,
|
|
||||||
EXCEPTION_BINDING,
|
EXCEPTION_BINDING,
|
||||||
bind(XHR).toValue(new XHRImpl()),
|
bind(XHR).toValue(new XHRImpl()),
|
||||||
ComponentUrlMapper,
|
|
||||||
UrlResolver,
|
|
||||||
StyleUrlResolver,
|
|
||||||
StyleInliner,
|
StyleInliner,
|
||||||
DynamicComponentLoader,
|
|
||||||
Testability,
|
Testability,
|
||||||
AnchorBasedAppRootUrl,
|
AnchorBasedAppRootUrl,
|
||||||
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
|
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
|
||||||
|
@ -169,16 +92,28 @@ function _injectorBindings(appComponentType): Array<Type | Binding | any[]> {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNgZone(): NgZone {
|
|
||||||
return new NgZone({enableLongStackTrace: assertionsEnabled()});
|
|
||||||
|
/**
|
||||||
|
* Initialize the Angular context on the page.
|
||||||
|
*
|
||||||
|
* If no bindings are provided, calling {@link platform}() is idempotent,
|
||||||
|
* and will use the default platform bindings (which can be obtained from
|
||||||
|
* {@link rootBindings}).
|
||||||
|
*/
|
||||||
|
export function platform(bindings?: Array<Type | Binding | any[]>): PlatformRef {
|
||||||
|
return platformCommon(bindings, () => {
|
||||||
|
BrowserDomAdapter.makeCurrent();
|
||||||
|
wtfInit();
|
||||||
|
BrowserGetTestability.init();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrapping for Angular applications.
|
* Bootstrapping for Angular applications.
|
||||||
*
|
*
|
||||||
* You instantiate an Angular application by explicitly specifying a component to use as the root
|
* You instantiate an Angular application by explicitly specifying a component to use
|
||||||
* component for your
|
* as the root component for your application via the `bootstrap()` method.
|
||||||
* application via the `bootstrap()` method.
|
|
||||||
*
|
*
|
||||||
* ## Simple Example
|
* ## Simple Example
|
||||||
*
|
*
|
||||||
|
@ -193,15 +128,12 @@ export function createNgZone(): NgZone {
|
||||||
* </html>
|
* </html>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* An application is bootstrapped inside an existing browser DOM, typically `index.html`. Unlike
|
* An application is bootstrapped inside an existing browser DOM, typically `index.html`.
|
||||||
* Angular 1, Angular 2
|
* Unlike Angular 1, Angular 2 does not compile/process bindings in `index.html`. This is
|
||||||
* does not compile/process bindings in `index.html`. This is mainly for security reasons, as well
|
* mainly for security reasons, as well as architectural changes in Angular 2. This means
|
||||||
* as architectural
|
* that `index.html` can safely be processed using server-side technologies such as
|
||||||
* changes in Angular 2. This means that `index.html` can safely be processed using server-side
|
* bindings. Bindings can thus use double-curly `{{ syntax }}` without collision from
|
||||||
* technologies such as
|
* Angular 2 component double-curly `{{ syntax }}`.
|
||||||
* bindings. Bindings can thus use double-curly `{{ syntax }}` without collision from Angular 2
|
|
||||||
* component double-curly
|
|
||||||
* `{{ syntax }}`.
|
|
||||||
*
|
*
|
||||||
* We can use this script code:
|
* We can use this script code:
|
||||||
*
|
*
|
||||||
|
@ -225,134 +157,77 @@ export function createNgZone(): NgZone {
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* When the app developer invokes `bootstrap()` with the root component `MyApp` as its argument,
|
* When the app developer invokes `bootstrap()` with the root component `MyApp` as its
|
||||||
* Angular performs the
|
* argument, Angular performs the following tasks:
|
||||||
* following tasks:
|
|
||||||
*
|
*
|
||||||
* 1. It uses the component's `selector` property to locate the DOM element which needs to be
|
* 1. It uses the component's `selector` property to locate the DOM element which needs
|
||||||
* upgraded into
|
* to be upgraded into the angular component.
|
||||||
* the angular component.
|
* 2. It creates a new child injector (from the platform injector). Optionally, you can
|
||||||
* 2. It creates a new child injector (from the platform injector). Optionally, you can also
|
* also override the injector configuration for an app by invoking `bootstrap` with the
|
||||||
* override the injector configuration for an app by
|
* `componentInjectableBindings` argument.
|
||||||
* invoking `bootstrap` with the `componentInjectableBindings` argument.
|
* 3. It creates a new `Zone` and connects it to the angular application's change detection
|
||||||
* 3. It creates a new `Zone` and connects it to the angular application's change detection domain
|
* domain instance.
|
||||||
* instance.
|
* 4. It creates a shadow DOM on the selected component's host element and loads the
|
||||||
* 4. It creates a shadow DOM on the selected component's host element and loads the template into
|
* template into it.
|
||||||
* it.
|
|
||||||
* 5. It instantiates the specified component.
|
* 5. It instantiates the specified component.
|
||||||
* 6. Finally, Angular performs change detection to apply the initial data bindings for the
|
* 6. Finally, Angular performs change detection to apply the initial data bindings for the
|
||||||
* application.
|
* application.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ## Instantiating Multiple Applications on a Single Page
|
* ## Instantiating Multiple Applications on a Single Page
|
||||||
*
|
*
|
||||||
* There are two ways to do this.
|
* There are two ways to do this.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* ### Isolated Applications
|
* ### Isolated Applications
|
||||||
*
|
*
|
||||||
* Angular creates a new application each time that the `bootstrap()` method is invoked. When
|
* Angular creates a new application each time that the `bootstrap()` method is invoked.
|
||||||
* multiple applications
|
* When multiple applications are created for a page, Angular treats each application as
|
||||||
* are created for a page, Angular treats each application as independent within an isolated change
|
* independent within an isolated change detection and `Zone` domain. If you need to share
|
||||||
* detection and
|
* data between applications, use the strategy described in the next section, "Applications
|
||||||
* `Zone` domain. If you need to share data between applications, use the strategy described in the
|
* That Share Change Detection."
|
||||||
* next
|
|
||||||
* section, "Applications That Share Change Detection."
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ### Applications That Share Change Detection
|
* ### Applications That Share Change Detection
|
||||||
*
|
*
|
||||||
* If you need to bootstrap multiple applications that share common data, the applications must
|
* If you need to bootstrap multiple applications that share common data, the applications
|
||||||
* share a common
|
* must share a common change detection and zone. To do that, create a meta-component that
|
||||||
* change detection and zone. To do that, create a meta-component that lists the application
|
* lists the application components in its template.
|
||||||
* components in its template.
|
*
|
||||||
* By only invoking the `bootstrap()` method once, with the meta-component as its argument, you
|
* By only invoking the `bootstrap()` method once, with the meta-component as its argument,
|
||||||
* ensure that only a
|
* you ensure that only a single change detection zone is created and therefore data can be
|
||||||
* single change detection zone is created and therefore data can be shared across the applications.
|
* shared across the applications.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ## Platform Injector
|
* ## Platform Injector
|
||||||
*
|
*
|
||||||
* When working within a browser window, there are many singleton resources: cookies, title,
|
* When working within a browser window, there are many singleton resources: cookies, title,
|
||||||
* location, and others.
|
* location, and others. Angular services that represent these resources must likewise be
|
||||||
* Angular services that represent these resources must likewise be shared across all Angular
|
* shared across all Angular applications that occupy the same browser window. For this
|
||||||
* applications that
|
* reason, Angular creates exactly one global platform injector which stores all shared
|
||||||
* occupy the same browser window. For this reason, Angular creates exactly one global platform
|
* services, and each angular application injector has the platform injector as its parent.
|
||||||
* injector which stores
|
|
||||||
* all shared services, and each angular application injector has the platform injector as its
|
|
||||||
* parent.
|
|
||||||
*
|
*
|
||||||
* Each application has its own private injector as well. When there are multiple applications on a
|
* Each application has its own private injector as well. When there are multipl
|
||||||
* page, Angular treats
|
* applications on a page, Angular treats each application injector's services as private
|
||||||
* each application injector's services as private to that application.
|
* to that application.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* # API
|
* # API
|
||||||
* - `appComponentType`: The root component which should act as the application. This is a reference
|
* - `appComponentType`: The root component which should act as the application. This is
|
||||||
* to a `Type`
|
* a reference to a `Type` which is annotated with `@Component(...)`.
|
||||||
* which is annotated with `@Component(...)`.
|
* - `componentInjectableBindings`: An additional set of bindings that can be added to the
|
||||||
* - `componentInjectableBindings`: An additional set of bindings that can be added to the app
|
* app injector to override default injection behavior.
|
||||||
* injector
|
* - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter
|
||||||
* to override default injection behavior.
|
* for unhandled exceptions.
|
||||||
* - `errorReporter`: `function(exception:any, stackTrace:string)` a default error reporter for
|
|
||||||
* unhandled exceptions.
|
|
||||||
*
|
*
|
||||||
* Returns a `Promise` of {@link ApplicationRef}.
|
* Returns a `Promise` of {@link ApplicationRef}.
|
||||||
*/
|
*/
|
||||||
export function commonBootstrap(appComponentType: /*Type*/ any,
|
export function commonBootstrap(appComponentType: /*Type*/ any,
|
||||||
componentInjectableBindings: Array<Type | Binding | any[]> = null):
|
appBindings: Array<Type | Binding | any[]> = null):
|
||||||
Promise<ApplicationRef> {
|
Promise<ComponentRef> {
|
||||||
BrowserDomAdapter.makeCurrent();
|
var p = platform();
|
||||||
wtfInit();
|
var bindings = [applicationCommonBindings(), applicationDomBindings()];
|
||||||
var bootstrapProcess = PromiseWrapper.completer();
|
if (isPresent(appBindings)) {
|
||||||
var zone = createNgZone();
|
bindings.push(appBindings);
|
||||||
|
}
|
||||||
zone.run(() => {
|
return p.application(bindings).bootstrap(appComponentType);
|
||||||
var exceptionHandler;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var appInjector = _createAppInjector(appComponentType, componentInjectableBindings, zone);
|
|
||||||
exceptionHandler = appInjector.get(ExceptionHandler);
|
|
||||||
zone.overrideOnErrorHandler((e, s) => exceptionHandler.call(e, s));
|
|
||||||
|
|
||||||
var compRefToken: Promise<any> = appInjector.get(APP_COMPONENT_REF_PROMISE);
|
|
||||||
var tick = (componentRef) => {
|
|
||||||
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
|
|
||||||
// retrieve life cycle: may have already been created if injected in root component
|
|
||||||
var lc = appInjector.get(LifeCycle);
|
|
||||||
lc.registerWith(zone, appChangeDetector);
|
|
||||||
lc.tick(); // the first tick that will bootstrap the app
|
|
||||||
|
|
||||||
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
|
|
||||||
};
|
|
||||||
|
|
||||||
var tickResult = PromiseWrapper.then(compRefToken, tick);
|
|
||||||
|
|
||||||
PromiseWrapper.then(tickResult,
|
|
||||||
(_) => {}); // required for Dart to trigger the default error handler
|
|
||||||
PromiseWrapper.then(tickResult, null,
|
|
||||||
(err, stackTrace) => { bootstrapProcess.reject(err, stackTrace); });
|
|
||||||
} catch (e) {
|
|
||||||
if (isPresent(exceptionHandler)) {
|
|
||||||
exceptionHandler.call(e, e.stack);
|
|
||||||
} else {
|
|
||||||
// The error happened during the creation of an injector, most likely because of a bug in
|
|
||||||
// DI.
|
|
||||||
// We cannot use the provided exception handler, so we default to writing to the DOM.
|
|
||||||
DOM.logError(e);
|
|
||||||
}
|
|
||||||
bootstrapProcess.reject(e, e.stack);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return bootstrapProcess.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _createAppInjector(appComponentType: Type, bindings: Array<Type | Binding | any[]>,
|
|
||||||
zone: NgZone): Injector {
|
|
||||||
if (isBlank(_rootInjector)) _rootInjector = Injector.resolveAndCreate(_rootBindings);
|
|
||||||
var mergedBindings: any[] =
|
|
||||||
isPresent(bindings) ? ListWrapper.concat(_injectorBindings(appComponentType), bindings) :
|
|
||||||
_injectorBindings(appComponentType);
|
|
||||||
mergedBindings.push(bind(NgZone).toValue(zone));
|
|
||||||
return _rootInjector.resolveAndCreateChild(mergedBindings);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,320 @@
|
||||||
import {ComponentRef} from 'angular2/src/core/compiler/dynamic_component_loader';
|
|
||||||
import {Injector} from 'angular2/src/core/di';
|
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||||
import {Type} from 'angular2/src/core/facade/lang';
|
import {Type, isBlank, isPresent, assertionsEnabled} from 'angular2/src/core/facade/lang';
|
||||||
|
import {bind, Binding, Injector, OpaqueToken} from 'angular2/src/core/di';
|
||||||
|
import {APP_COMPONENT_REF_PROMISE, APP_COMPONENT} from './application_tokens';
|
||||||
|
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
||||||
|
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
||||||
|
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
|
||||||
|
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
||||||
|
import {
|
||||||
|
ComponentRef,
|
||||||
|
DynamicComponentLoader
|
||||||
|
} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||||
|
import {
|
||||||
|
BaseException,
|
||||||
|
WrappedException,
|
||||||
|
ExceptionHandler
|
||||||
|
} from 'angular2/src/core/facade/exceptions';
|
||||||
|
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||||
|
import {internalView} from 'angular2/src/core/compiler/view_ref';
|
||||||
|
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
||||||
|
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
||||||
|
import {
|
||||||
|
Parser,
|
||||||
|
Lexer,
|
||||||
|
ChangeDetection,
|
||||||
|
DynamicChangeDetection,
|
||||||
|
JitChangeDetection,
|
||||||
|
PreGeneratedChangeDetection,
|
||||||
|
IterableDiffers,
|
||||||
|
defaultIterableDiffers,
|
||||||
|
KeyValueDiffers,
|
||||||
|
defaultKeyValueDiffers
|
||||||
|
} from 'angular2/src/core/change_detection/change_detection';
|
||||||
|
import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_pool';
|
||||||
|
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||||
|
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
|
||||||
|
import {AppViewListener} from 'angular2/src/core/compiler/view_listener';
|
||||||
|
import {Compiler, CompilerCache} from './compiler/compiler';
|
||||||
|
import {DEFAULT_PIPES} from 'angular2/src/core/pipes';
|
||||||
|
import {ViewResolver} from './compiler/view_resolver';
|
||||||
|
import {DirectiveResolver} from './compiler/directive_resolver';
|
||||||
|
import {PipeResolver} from './compiler/pipe_resolver';
|
||||||
|
import {StyleUrlResolver} from 'angular2/src/core/render/dom/compiler/style_url_resolver';
|
||||||
|
import {UrlResolver} from 'angular2/src/core/services/url_resolver';
|
||||||
|
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Angular's representation of an Application.
|
* Contains everything that is safe to share between applications.
|
||||||
*
|
|
||||||
* `ApplicationRef` represents a running application instance. Use it to retrieve the host
|
|
||||||
* component, injector,
|
|
||||||
* or dispose of an application.
|
|
||||||
*/
|
*/
|
||||||
export class ApplicationRef {
|
export function rootBindings(): Array<Type | Binding | any[]> {
|
||||||
_hostComponent: ComponentRef;
|
return [bind(Reflector).toValue(reflector), TestabilityRegistry];
|
||||||
_injector: Injector;
|
}
|
||||||
_hostComponentType: Type;
|
|
||||||
|
/**
|
||||||
|
* Construct bindings specific to an individual root component.
|
||||||
|
*/
|
||||||
|
function _componentBindings(appComponentType: Type): Array<Type | Binding | any[]> {
|
||||||
|
return [
|
||||||
|
bind(APP_COMPONENT)
|
||||||
|
.toValue(appComponentType),
|
||||||
|
bind(APP_COMPONENT_REF_PROMISE)
|
||||||
|
.toFactory(
|
||||||
|
(dynamicComponentLoader, injector: Injector) => {
|
||||||
|
// TODO(rado): investigate whether to support bindings on root component.
|
||||||
|
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector)
|
||||||
|
.then((componentRef) => {
|
||||||
|
if (isPresent(componentRef.location.nativeElement)) {
|
||||||
|
injector.get(TestabilityRegistry)
|
||||||
|
.registerApplication(componentRef.location.nativeElement,
|
||||||
|
injector.get(Testability));
|
||||||
|
}
|
||||||
|
return componentRef;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[DynamicComponentLoader, Injector]),
|
||||||
|
|
||||||
|
bind(appComponentType)
|
||||||
|
.toFactory((p: Promise<any>) => p.then(ref => ref.instance), [APP_COMPONENT_REF_PROMISE]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a default set of bindings which should be included in any Angular
|
||||||
|
* application, regardless of whether it runs on the UI thread or in a web worker.
|
||||||
|
*/
|
||||||
|
export function applicationCommonBindings(): Array<Type | Binding | any[]> {
|
||||||
|
var bestChangeDetection = new DynamicChangeDetection();
|
||||||
|
if (PreGeneratedChangeDetection.isSupported()) {
|
||||||
|
bestChangeDetection = new PreGeneratedChangeDetection();
|
||||||
|
} else if (JitChangeDetection.isSupported()) {
|
||||||
|
bestChangeDetection = new JitChangeDetection();
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
ProtoViewFactory,
|
||||||
|
AppViewPool,
|
||||||
|
bind(APP_VIEW_POOL_CAPACITY).toValue(10000),
|
||||||
|
AppViewManager,
|
||||||
|
AppViewManagerUtils,
|
||||||
|
AppViewListener,
|
||||||
|
Compiler,
|
||||||
|
CompilerCache,
|
||||||
|
ViewResolver,
|
||||||
|
DEFAULT_PIPES,
|
||||||
|
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
||||||
|
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
||||||
|
bind(ChangeDetection).toValue(bestChangeDetection),
|
||||||
|
DirectiveResolver,
|
||||||
|
UrlResolver,
|
||||||
|
StyleUrlResolver,
|
||||||
|
PipeResolver,
|
||||||
|
ComponentUrlMapper,
|
||||||
|
Parser,
|
||||||
|
Lexer,
|
||||||
|
DynamicComponentLoader,
|
||||||
|
bind(LifeCycle).toFactory((exceptionHandler) => new LifeCycle(null, assertionsEnabled()),
|
||||||
|
[ExceptionHandler]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an Angular zone.
|
||||||
|
*/
|
||||||
|
export function createNgZone(): NgZone {
|
||||||
|
return new NgZone({enableLongStackTrace: assertionsEnabled()});
|
||||||
|
}
|
||||||
|
|
||||||
|
var _platform: PlatformRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
export function platformCommon(bindings?: Array<Type | Binding | any[]>, initializer?: () => void):
|
||||||
|
PlatformRef {
|
||||||
|
if (isPresent(_platform)) {
|
||||||
|
if (isBlank(bindings)) {
|
||||||
|
return _platform;
|
||||||
|
}
|
||||||
|
throw "platform() can only be called once per page";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPresent(initializer)) {
|
||||||
|
initializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlank(bindings)) {
|
||||||
|
bindings = rootBindings();
|
||||||
|
}
|
||||||
|
_platform = new PlatformRef(Injector.resolveAndCreate(bindings), () => { _platform = null; });
|
||||||
|
return _platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent the Angular context on a page, and is a true singleton.
|
||||||
|
*
|
||||||
|
* The platform {@link Injector} injects dependencies which are also
|
||||||
|
* truly singletons in the context of a page (such as the browser's
|
||||||
|
* cookie jar).
|
||||||
|
*/
|
||||||
|
export class PlatformRef {
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_applications: ApplicationRef[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
constructor(hostComponent: ComponentRef, hostComponentType: Type, injector: Injector) {
|
constructor(private _injector: Injector, private _dispose: () => void) {}
|
||||||
this._hostComponent = hostComponent;
|
|
||||||
this._injector = injector;
|
|
||||||
this._hostComponentType = hostComponentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current {@link ComponentMetadata} type.
|
* Get the platform {@link Injector}.
|
||||||
*/
|
|
||||||
get hostComponentType(): Type { return this._hostComponentType; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current {@link ComponentMetadata} instance.
|
|
||||||
*/
|
|
||||||
get hostComponent(): any { return this._hostComponent.instance; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispose (un-load) the application.
|
|
||||||
*/
|
|
||||||
dispose(): void {
|
|
||||||
// TODO: We also need to clean up the Zone, ... here!
|
|
||||||
this._hostComponent.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the root application {@link Injector}.
|
|
||||||
*/
|
*/
|
||||||
get injector(): Injector { return this._injector; }
|
get injector(): Injector { return this._injector; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new Angular application with the given bindings. The `ApplicationRef`
|
||||||
|
* returned can be used to bootstrap one or more root components within the
|
||||||
|
* application.
|
||||||
|
*/
|
||||||
|
application(bindings: Array<Type | Binding | any[]>): ApplicationRef {
|
||||||
|
var app = this._initApp(createNgZone(), bindings);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new Angular application from asynchronously provided bindings.
|
||||||
|
*
|
||||||
|
* Runs the `AsyncLoader` callback in the application `Zone` and constructs
|
||||||
|
* a new Application from the bindings provided by the `Promise` it returns.
|
||||||
|
*/
|
||||||
|
asyncApplication(bindingFn: (zone: NgZone) =>
|
||||||
|
Promise<Array<Type | Binding | any[]>>): Promise<ApplicationRef> {
|
||||||
|
var zone = createNgZone();
|
||||||
|
var completer = PromiseWrapper.completer();
|
||||||
|
zone.run(() => {
|
||||||
|
PromiseWrapper.then(bindingFn(zone), (bindings: Array<Type | Binding | any[]>) => {
|
||||||
|
completer.resolve(this._initApp(zone, bindings));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return completer.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initApp(zone: NgZone, bindings: Array<Type | Binding | any[]>): ApplicationRef {
|
||||||
|
var injector: Injector;
|
||||||
|
zone.run(() => {
|
||||||
|
bindings.push(bind(NgZone).toValue(zone));
|
||||||
|
bindings.push(bind(ApplicationRef).toValue(this));
|
||||||
|
|
||||||
|
var exceptionHandler;
|
||||||
|
try {
|
||||||
|
injector = this.injector.resolveAndCreateChild(bindings);
|
||||||
|
exceptionHandler = injector.get(ExceptionHandler);
|
||||||
|
zone.overrideOnErrorHandler((e, s) => exceptionHandler.call(e, s));
|
||||||
|
} catch (e) {
|
||||||
|
if (isPresent(exceptionHandler)) {
|
||||||
|
exceptionHandler.call(e, e.stack);
|
||||||
|
} else {
|
||||||
|
DOM.logError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var app = new ApplicationRef(this, zone, injector);
|
||||||
|
this._applications.push(app);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the Angular platform and all Angular applications on the page.
|
||||||
|
*/
|
||||||
|
dispose(): void {
|
||||||
|
this._applications.forEach((app) => app.dispose());
|
||||||
|
this._dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an Angular application.
|
||||||
|
*
|
||||||
|
* Use to retrieve the application {@link Injector} or to bootstrap new
|
||||||
|
* components at the root of the application. Can also be used to dispose
|
||||||
|
* of the entire application and all its loaded components.
|
||||||
|
*/
|
||||||
|
export class ApplicationRef {
|
||||||
|
private _bootstrapListeners: Function[] = [];
|
||||||
|
private _rootComponents: ComponentRef[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
constructor(private _platform: PlatformRef, private _zone: NgZone, private _injector: Injector) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener to be called each time a new root component type is bootstrapped.
|
||||||
|
*/
|
||||||
|
registerBootstrapListener(listener: (ref: ComponentRef) => void): void {
|
||||||
|
this._bootstrapListeners.push(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap a new component at the root level of the application, optionally with
|
||||||
|
* component specific bindings.
|
||||||
|
*/
|
||||||
|
bootstrap(componentType: Type, bindings?: Array<Type | Binding | any[]>): Promise<ComponentRef> {
|
||||||
|
var completer = PromiseWrapper.completer();
|
||||||
|
this._zone.run(() => {
|
||||||
|
var componentBindings = _componentBindings(componentType);
|
||||||
|
if (isPresent(bindings)) {
|
||||||
|
componentBindings.push(bindings);
|
||||||
|
}
|
||||||
|
var exceptionHandler = this._injector.get(ExceptionHandler);
|
||||||
|
try {
|
||||||
|
var injector: Injector = this._injector.resolveAndCreateChild(componentBindings);
|
||||||
|
var compRefToken: Promise<ComponentRef> = injector.get(APP_COMPONENT_REF_PROMISE);
|
||||||
|
var tick = (componentRef) => {
|
||||||
|
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
|
||||||
|
var lc = injector.get(LifeCycle);
|
||||||
|
lc.registerWith(this._zone, appChangeDetector);
|
||||||
|
lc.tick();
|
||||||
|
completer.resolve(componentRef);
|
||||||
|
this._rootComponents.push(componentRef);
|
||||||
|
this._bootstrapListeners.forEach((listener) => listener(componentRef));
|
||||||
|
};
|
||||||
|
|
||||||
|
var tickResult = PromiseWrapper.then(compRefToken, tick);
|
||||||
|
|
||||||
|
PromiseWrapper.then(tickResult, (_) => {});
|
||||||
|
PromiseWrapper.then(tickResult, null,
|
||||||
|
(err, stackTrace) => completer.reject(err, stackTrace));
|
||||||
|
} catch (e) {
|
||||||
|
exceptionHandler.call(e, e.stack);
|
||||||
|
completer.reject(e, e.stack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return completer.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the application {@link Injector}.
|
||||||
|
*/
|
||||||
|
get injector(): Injector { return this._injector; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the application {@link Zone}.
|
||||||
|
*/
|
||||||
|
get zone(): NgZone { return this._zone; }
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
// TODO(alxhub): Dispose of the NgZone.
|
||||||
|
this._rootComponents.forEach((ref) => ref.dispose());
|
||||||
|
this._platform._applicationDisposed(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@ library angular2.src.core.application_static;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'application_common.dart';
|
import 'application_common.dart';
|
||||||
import 'application_ref.dart';
|
import 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show ComponentRef;
|
||||||
|
|
||||||
/// Starts an application from a root component.
|
/// Starts an application from a root component.
|
||||||
///
|
///
|
||||||
/// See [commonBootstrap] for detailed documentation.
|
/// See [commonBootstrap] for detailed documentation.
|
||||||
Future<ApplicationRef> bootstrapStatic(Type appComponentType,
|
Future<ComponentRef> bootstrapStatic(Type appComponentType,
|
||||||
[List componentInjectableBindings, void initReflector()]) {
|
[List componentInjectableBindings, void initReflector()]) {
|
||||||
if (initReflector != null) {
|
if (initReflector != null) {
|
||||||
initReflector();
|
initReflector();
|
||||||
|
|
|
@ -2,7 +2,7 @@ library angular2.src.core.bootstrap;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'application_ref.dart';
|
import 'package:angular2/src/core/compiler/dynamic_component_loader.dart' show ComponentRef;
|
||||||
import 'package:angular2/src/core/reflection/reflection.dart' show reflector;
|
import 'package:angular2/src/core/reflection/reflection.dart' show reflector;
|
||||||
import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
|
import 'package:angular2/src/core/reflection/reflection_capabilities.dart'
|
||||||
show ReflectionCapabilities;
|
show ReflectionCapabilities;
|
||||||
|
@ -14,7 +14,7 @@ import 'application_common.dart';
|
||||||
/// mirrors and produces a faster and more compact JS code.
|
/// mirrors and produces a faster and more compact JS code.
|
||||||
///
|
///
|
||||||
/// See [commonBootstrap] for detailed documentation.
|
/// See [commonBootstrap] for detailed documentation.
|
||||||
Future<ApplicationRef> bootstrap(Type appComponentType,
|
Future<ComponentRef> bootstrap(Type appComponentType,
|
||||||
[List componentInjectableBindings]) {
|
[List componentInjectableBindings]) {
|
||||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||||
return commonBootstrap(appComponentType, componentInjectableBindings);
|
return commonBootstrap(appComponentType, componentInjectableBindings);
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import {Key, Injector, ResolvedBinding, Binding, bind, Injectable} from 'angular2/src/core/di';
|
import {Key, Injector, ResolvedBinding, Binding, bind, Injectable} from 'angular2/src/core/di';
|
||||||
import {Compiler} from './compiler';
|
import {Compiler} from './compiler';
|
||||||
import {Type, stringify, isPresent} from 'angular2/src/core/facade/lang';
|
import {isType, Type, stringify, isPresent} from 'angular2/src/core/facade/lang';
|
||||||
import {Promise} from 'angular2/src/core/facade/async';
|
import {Promise} from 'angular2/src/core/facade/async';
|
||||||
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
||||||
import {ElementRef} from './element_ref';
|
import {ElementRef} from './element_ref';
|
||||||
import {ViewRef, HostViewRef} from './view_ref';
|
import {ViewRef, HostViewRef} from './view_ref';
|
||||||
|
|
||||||
|
function _asType(typeOrBinding: Type | Binding): Type {
|
||||||
|
return isType(typeOrBinding) ? typeOrBinding : (<Binding>typeOrBinding).token;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Angular's reference to a component instance.
|
* Angular's reference to a component instance.
|
||||||
*
|
*
|
||||||
|
@ -22,12 +26,20 @@ export class ComponentRef {
|
||||||
*/
|
*/
|
||||||
instance: any;
|
instance: any;
|
||||||
|
|
||||||
|
componentType: Type;
|
||||||
|
|
||||||
|
|
||||||
|
injector: Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
constructor(location: ElementRef, instance: any, private _dispose: () => void) {
|
constructor(location: ElementRef, instance: any, componentType: Type, injector: Injector,
|
||||||
|
private _dispose: () => void) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
this.componentType = componentType;
|
||||||
|
this.injector = injector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,6 +47,10 @@ export class ComponentRef {
|
||||||
*/
|
*/
|
||||||
get hostView(): HostViewRef { return this.location.parentView; }
|
get hostView(): HostViewRef { return this.location.parentView; }
|
||||||
|
|
||||||
|
get hostComponentType(): Type { return this.componentType; }
|
||||||
|
|
||||||
|
get hostComponent(): any { return this.instance; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispose of the component instance.
|
* Dispose of the component instance.
|
||||||
*/
|
*/
|
||||||
|
@ -104,8 +120,8 @@ export class DynamicComponentLoader {
|
||||||
* </my-app>
|
* </my-app>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string,
|
loadAsRoot(typeOrBinding: Type | Binding, overrideSelector: string, injector: Injector,
|
||||||
injector: Injector): Promise<ComponentRef> {
|
onDispose?: () => void): Promise<ComponentRef> {
|
||||||
return this._compiler.compileInHost(typeOrBinding)
|
return this._compiler.compileInHost(typeOrBinding)
|
||||||
.then(hostProtoViewRef => {
|
.then(hostProtoViewRef => {
|
||||||
var hostViewRef =
|
var hostViewRef =
|
||||||
|
@ -113,8 +129,14 @@ export class DynamicComponentLoader {
|
||||||
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
var newLocation = this._viewManager.getHostElement(hostViewRef);
|
||||||
var component = this._viewManager.getComponent(newLocation);
|
var component = this._viewManager.getComponent(newLocation);
|
||||||
|
|
||||||
var dispose = () => { this._viewManager.destroyRootHostView(hostViewRef); };
|
var dispose = () => {
|
||||||
return new ComponentRef(newLocation, component, dispose);
|
this._viewManager.destroyRootHostView(hostViewRef);
|
||||||
|
if (isPresent(onDispose)) {
|
||||||
|
onDispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return new ComponentRef(newLocation, component, _asType(typeOrBinding), injector,
|
||||||
|
dispose);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +251,7 @@ export class DynamicComponentLoader {
|
||||||
viewContainer.remove(index);
|
viewContainer.remove(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return new ComponentRef(newLocation, component, dispose);
|
return new ComponentRef(newLocation, component, _asType(typeOrBinding), null, dispose);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
library testability.get_testability;
|
library testability.browser_testability;
|
||||||
|
|
||||||
import './testability.dart';
|
import './testability.dart';
|
||||||
|
|
||||||
|
@ -80,8 +80,14 @@ class PublicTestability implements _JsObjectProxyable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetTestability {
|
class BrowserGetTestability implements GetTestability {
|
||||||
static addToWindow(TestabilityRegistry registry) {
|
const BrowserGetTestability();
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
setTestabilityGetter(const BrowserGetTestability());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToWindow(TestabilityRegistry registry) {
|
||||||
var jsRegistry = js.context['ngTestabilityRegistries'];
|
var jsRegistry = js.context['ngTestabilityRegistries'];
|
||||||
if (jsRegistry == null) {
|
if (jsRegistry == null) {
|
||||||
js.context['ngTestabilityRegistries'] = jsRegistry = new js.JsArray();
|
js.context['ngTestabilityRegistries'] = jsRegistry = new js.JsArray();
|
||||||
|
@ -106,10 +112,10 @@ class GetTestability {
|
||||||
return _jsify(result);
|
return _jsify(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
jsRegistry.add(_createRegistry(registry));
|
jsRegistry.add(this._createRegistry(registry));
|
||||||
}
|
}
|
||||||
|
|
||||||
static js.JsObject _createRegistry(TestabilityRegistry registry) {
|
js.JsObject _createRegistry(TestabilityRegistry registry) {
|
||||||
var object = new js.JsObject(js.context['Object']);
|
var object = new js.JsObject(js.context['Object']);
|
||||||
object['getAngularTestability'] = _jsify((Element elem,
|
object['getAngularTestability'] = _jsify((Element elem,
|
||||||
bool findInAncestors) {
|
bool findInAncestors) {
|
|
@ -1,4 +1,9 @@
|
||||||
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
import {
|
||||||
|
TestabilityRegistry,
|
||||||
|
Testability,
|
||||||
|
GetTestability,
|
||||||
|
setTestabilityGetter
|
||||||
|
} from 'angular2/src/core/testability/testability';
|
||||||
import {global} from 'angular2/src/core/facade/lang';
|
import {global} from 'angular2/src/core/facade/lang';
|
||||||
|
|
||||||
class PublicTestability {
|
class PublicTestability {
|
||||||
|
@ -13,8 +18,10 @@ class PublicTestability {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetTestability {
|
export class BrowserGetTestability implements GetTestability {
|
||||||
static addToWindow(registry: TestabilityRegistry) {
|
static init() { setTestabilityGetter(new BrowserGetTestability()); }
|
||||||
|
|
||||||
|
addToWindow(registry: TestabilityRegistry): void {
|
||||||
global.getAngularTestability = function(elem: Element, findInAncestors: boolean = true):
|
global.getAngularTestability = function(elem: Element, findInAncestors: boolean = true):
|
||||||
PublicTestability {
|
PublicTestability {
|
||||||
var testability = registry.findTestabilityInTree(elem, findInAncestors);
|
var testability = registry.findTestabilityInTree(elem, findInAncestors);
|
|
@ -1,8 +1,8 @@
|
||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||||
import {Map, MapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
import {Map, MapWrapper, ListWrapper} from 'angular2/src/core/facade/collection';
|
||||||
|
import {CONST, CONST_EXPR} from 'angular2/src/core/facade/lang';
|
||||||
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
import {BaseException, WrappedException} from 'angular2/src/core/facade/exceptions';
|
||||||
import * as getTestabilityModule from './get_testability';
|
|
||||||
import {NgZone} from '../zone/ng_zone';
|
import {NgZone} from '../zone/ng_zone';
|
||||||
import {PromiseWrapper} from 'angular2/src/core/facade/async';
|
import {PromiseWrapper} from 'angular2/src/core/facade/async';
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ export class Testability {
|
||||||
export class TestabilityRegistry {
|
export class TestabilityRegistry {
|
||||||
_applications: Map<any, Testability> = new Map();
|
_applications: Map<any, Testability> = new Map();
|
||||||
|
|
||||||
constructor() { getTestabilityModule.GetTestability.addToWindow(this); }
|
constructor() { testabilityGetter.addToWindow(this); }
|
||||||
|
|
||||||
registerApplication(token: any, testability: Testability) {
|
registerApplication(token: any, testability: Testability) {
|
||||||
this._applications.set(token, testability);
|
this._applications.set(token, testability);
|
||||||
|
@ -99,3 +99,16 @@ export class TestabilityRegistry {
|
||||||
return this.findTestabilityInTree(DOM.parentElement(elem));
|
return this.findTestabilityInTree(DOM.parentElement(elem));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetTestability { addToWindow(registry: TestabilityRegistry): void; }
|
||||||
|
|
||||||
|
@CONST()
|
||||||
|
class NoopGetTestability implements GetTestability {
|
||||||
|
addToWindow(registry: TestabilityRegistry): void {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTestabilityGetter(getter: GetTestability): void {
|
||||||
|
testabilityGetter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
var testabilityGetter: GetTestability = CONST_EXPR(new NoopGetTestability());
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import {createInjector} from "./di_bindings";
|
import {createInjector} from "./di_bindings";
|
||||||
import {MessageBus, MessageBusSink} from "angular2/src/web_workers/shared/message_bus";
|
import {MessageBus, MessageBusSink} from "angular2/src/web_workers/shared/message_bus";
|
||||||
import {createNgZone} from 'angular2/src/core/application_common';
|
import {createNgZone} from 'angular2/src/core/application_ref';
|
||||||
import {Injectable} from 'angular2/src/core/di';
|
import {Injectable} from 'angular2/src/core/di';
|
||||||
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
import {BrowserDomAdapter} from 'angular2/src/core/dom/browser_adapter';
|
||||||
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
|
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
|
||||||
|
|
|
@ -4,8 +4,8 @@ import "package:angular2/src/web_workers/shared/isolate_message_bus.dart";
|
||||||
import "package:angular2/src/web_workers/worker/application_common.dart"
|
import "package:angular2/src/web_workers/worker/application_common.dart"
|
||||||
show bootstrapWebWorkerCommon;
|
show bootstrapWebWorkerCommon;
|
||||||
import "package:angular2/src/core/facade/async.dart" show Future;
|
import "package:angular2/src/core/facade/async.dart" show Future;
|
||||||
import "package:angular2/src/core/application_ref.dart" show ApplicationRef;
|
|
||||||
import "package:angular2/src/core/facade/lang.dart" show Type, BaseException;
|
import "package:angular2/src/core/facade/lang.dart" show Type, BaseException;
|
||||||
|
import "package:angular2/src/core/compiler/dynamic_component_loader.dart" show ComponentRef;
|
||||||
import "dart:isolate";
|
import "dart:isolate";
|
||||||
import "dart:async";
|
import "dart:async";
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
|
@ -21,7 +21,7 @@ import 'dart:core';
|
||||||
* bootstrap() in a regular Angular application
|
* bootstrap() in a regular Angular application
|
||||||
* See the bootstrap() docs for more details.
|
* See the bootstrap() docs for more details.
|
||||||
*/
|
*/
|
||||||
Future<ApplicationRef> bootstrapWebWorker(
|
Future<ComponentRef> bootstrapWebWorker(
|
||||||
SendPort replyTo, Type appComponentType,
|
SendPort replyTo, Type appComponentType,
|
||||||
[List<dynamic> componentInjectableBindings = null]) {
|
[List<dynamic> componentInjectableBindings = null]) {
|
||||||
ReceivePort rPort = new ReceivePort();
|
ReceivePort rPort = new ReceivePort();
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {Binding, Injectable} from "angular2/src/core/di";
|
||||||
import {Map} from 'angular2/src/core/facade/collection';
|
import {Map} from 'angular2/src/core/facade/collection';
|
||||||
import {Promise} from 'angular2/src/core/facade/async';
|
import {Promise} from 'angular2/src/core/facade/async';
|
||||||
import {bootstrapWebWorkerCommon} from "angular2/src/web_workers/worker/application_common";
|
import {bootstrapWebWorkerCommon} from "angular2/src/web_workers/worker/application_common";
|
||||||
import {ApplicationRef} from "angular2/src/core/application_ref";
|
import {ComponentRef} from "angular2/src/core/compiler/dynamic_component_loader";
|
||||||
export * from "angular2/src/web_workers/shared/message_bus";
|
export * from "angular2/src/web_workers/shared/message_bus";
|
||||||
|
|
||||||
// TODO(jteplitz602) remove this and compile with lib.webworker.d.ts (#3492)
|
// TODO(jteplitz602) remove this and compile with lib.webworker.d.ts (#3492)
|
||||||
|
@ -28,7 +28,7 @@ var _postMessage: PostMessageInterface = <any>postMessage;
|
||||||
*/
|
*/
|
||||||
export function bootstrapWebWorker(
|
export function bootstrapWebWorker(
|
||||||
appComponentType: Type, componentInjectableBindings: Array<Type | Binding | any[]> = null):
|
appComponentType: Type, componentInjectableBindings: Array<Type | Binding | any[]> = null):
|
||||||
Promise<ApplicationRef> {
|
Promise<ComponentRef> {
|
||||||
var sink = new PostMessageBusSink({
|
var sink = new PostMessageBusSink({
|
||||||
postMessage: (message: any, transferrables?:[ArrayBuffer]) => {
|
postMessage: (message: any, transferrables?:[ArrayBuffer]) => {
|
||||||
console.log("Sending", message);
|
console.log("Sending", message);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {Injector, bind, OpaqueToken, Binding} from 'angular2/src/core/di';
|
import {Injector, bind, OpaqueToken, Binding} from 'angular2/src/core/di';
|
||||||
import {DEFAULT_PIPES} from 'angular2/src/core/pipes';
|
|
||||||
import {FORM_BINDINGS} from 'angular2/src/core/forms';
|
import {FORM_BINDINGS} from 'angular2/src/core/forms';
|
||||||
import {
|
import {
|
||||||
NumberWrapper,
|
NumberWrapper,
|
||||||
|
@ -10,50 +9,21 @@ import {
|
||||||
print,
|
print,
|
||||||
stringify
|
stringify
|
||||||
} from 'angular2/src/core/facade/lang';
|
} from 'angular2/src/core/facade/lang';
|
||||||
import {Compiler, CompilerCache} from 'angular2/src/core/compiler/compiler';
|
|
||||||
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
|
|
||||||
import {
|
|
||||||
Parser,
|
|
||||||
Lexer,
|
|
||||||
ChangeDetection,
|
|
||||||
DynamicChangeDetection,
|
|
||||||
JitChangeDetection,
|
|
||||||
PreGeneratedChangeDetection,
|
|
||||||
IterableDiffers,
|
|
||||||
defaultIterableDiffers,
|
|
||||||
KeyValueDiffers,
|
|
||||||
defaultKeyValueDiffers
|
|
||||||
} from 'angular2/src/core/change_detection/change_detection';
|
|
||||||
import {ExceptionHandler} from 'angular2/src/core/facade/exceptions';
|
import {ExceptionHandler} from 'angular2/src/core/facade/exceptions';
|
||||||
import {DirectiveResolver} from 'angular2/src/core/compiler/directive_resolver';
|
|
||||||
import {StyleUrlResolver} from 'angular2/src/core/render/dom/compiler/style_url_resolver';
|
|
||||||
import {PipeResolver} from 'angular2/src/core/compiler/pipe_resolver';
|
|
||||||
import {ViewResolver} from 'angular2/src/core/compiler/view_resolver';
|
|
||||||
import {ListWrapper} from 'angular2/src/core/facade/collection';
|
|
||||||
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
import {Promise, PromiseWrapper, PromiseCompleter} from 'angular2/src/core/facade/async';
|
||||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
|
||||||
import {LifeCycle} from 'angular2/src/core/life_cycle/life_cycle';
|
|
||||||
import {XHR} from 'angular2/src/core/render/xhr';
|
import {XHR} from 'angular2/src/core/render/xhr';
|
||||||
import {WebWorkerXHRImpl} from 'angular2/src/web_workers/worker/xhr_impl';
|
import {WebWorkerXHRImpl} from 'angular2/src/web_workers/worker/xhr_impl';
|
||||||
import {ComponentUrlMapper} from 'angular2/src/core/compiler/component_url_mapper';
|
|
||||||
import {UrlResolver} from 'angular2/src/core/services/url_resolver';
|
|
||||||
import {AppRootUrl} from 'angular2/src/core/services/app_root_url';
|
import {AppRootUrl} from 'angular2/src/core/services/app_root_url';
|
||||||
import {
|
|
||||||
ComponentRef,
|
|
||||||
DynamicComponentLoader
|
|
||||||
} from 'angular2/src/core/compiler/dynamic_component_loader';
|
|
||||||
import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_pool';
|
|
||||||
import {AppViewManager} from 'angular2/src/core/compiler/view_manager';
|
|
||||||
import {AppViewManagerUtils} from 'angular2/src/core/compiler/view_manager_utils';
|
|
||||||
import {AppViewListener} from 'angular2/src/core/compiler/view_listener';
|
|
||||||
import {ProtoViewFactory} from 'angular2/src/core/compiler/proto_view_factory';
|
|
||||||
import {WebWorkerRenderer, WebWorkerCompiler} from './renderer';
|
import {WebWorkerRenderer, WebWorkerCompiler} from './renderer';
|
||||||
import {Renderer, RenderCompiler} from 'angular2/src/core/render/api';
|
import {Renderer, RenderCompiler} from 'angular2/src/core/render/api';
|
||||||
import {internalView} from 'angular2/src/core/compiler/view_ref';
|
|
||||||
import {ClientMessageBrokerFactory} from 'angular2/src/web_workers/shared/client_message_broker';
|
import {ClientMessageBrokerFactory} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||||
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
|
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
|
||||||
import {APP_COMPONENT_REF_PROMISE, APP_COMPONENT} from 'angular2/src/core/application_tokens';
|
import {
|
||||||
import {ApplicationRef} from 'angular2/src/core/application_ref';
|
platformCommon,
|
||||||
|
PlatformRef,
|
||||||
|
ApplicationRef,
|
||||||
|
applicationCommonBindings
|
||||||
|
} from 'angular2/src/core/application_ref';
|
||||||
import {Serializer} from "angular2/src/web_workers/shared/serializer";
|
import {Serializer} from "angular2/src/web_workers/shared/serializer";
|
||||||
import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api";
|
import {ON_WEB_WORKER} from "angular2/src/web_workers/shared/api";
|
||||||
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
|
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
|
||||||
|
@ -63,11 +33,12 @@ import {
|
||||||
import {ObservableWrapper} from 'angular2/src/core/facade/async';
|
import {ObservableWrapper} from 'angular2/src/core/facade/async';
|
||||||
import {SETUP_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
|
import {SETUP_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
|
||||||
import {WebWorkerEventDispatcher} from 'angular2/src/web_workers/worker/event_dispatcher';
|
import {WebWorkerEventDispatcher} from 'angular2/src/web_workers/worker/event_dispatcher';
|
||||||
|
import {ComponentRef} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||||
|
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||||
|
|
||||||
var _rootInjector: Injector;
|
export function platform(bindings?: Array<Type | Binding | any[]>): PlatformRef {
|
||||||
|
return platformCommon(bindings);
|
||||||
// Contains everything that is safe to share between applications.
|
}
|
||||||
var _rootBindings = [bind(Reflector).toValue(reflector)];
|
|
||||||
|
|
||||||
class PrintLogger {
|
class PrintLogger {
|
||||||
log = print;
|
log = print;
|
||||||
|
@ -76,29 +47,9 @@ class PrintLogger {
|
||||||
logGroupEnd() {}
|
logGroupEnd() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _injectorBindings(appComponentType, bus: MessageBus, initData: StringMap<string, any>):
|
function webWorkerBindings(appComponentType, bus: MessageBus, initData: StringMap<string, any>):
|
||||||
Array<Type | Binding | any[]> {
|
Array<Type | Binding | any[]> {
|
||||||
var bestChangeDetection = new DynamicChangeDetection();
|
|
||||||
if (PreGeneratedChangeDetection.isSupported()) {
|
|
||||||
bestChangeDetection = new PreGeneratedChangeDetection();
|
|
||||||
} else if (JitChangeDetection.isSupported()) {
|
|
||||||
bestChangeDetection = new JitChangeDetection();
|
|
||||||
}
|
|
||||||
return [
|
return [
|
||||||
bind(APP_COMPONENT)
|
|
||||||
.toValue(appComponentType),
|
|
||||||
bind(APP_COMPONENT_REF_PROMISE)
|
|
||||||
.toFactory(
|
|
||||||
(dynamicComponentLoader, injector) => {
|
|
||||||
// TODO(rado): investigate whether to support bindings on root component.
|
|
||||||
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector)
|
|
||||||
.then((componentRef) => { return componentRef; });
|
|
||||||
},
|
|
||||||
[DynamicComponentLoader, Injector]),
|
|
||||||
|
|
||||||
bind(appComponentType).toFactory((ref) => ref.instance, [APP_COMPONENT_REF_PROMISE]),
|
|
||||||
bind(LifeCycle).toFactory((exceptionHandler) => new LifeCycle(null, assertionsEnabled()),
|
|
||||||
[ExceptionHandler]),
|
|
||||||
Serializer,
|
Serializer,
|
||||||
bind(MessageBus).toValue(bus),
|
bind(MessageBus).toValue(bus),
|
||||||
ClientMessageBrokerFactory,
|
ClientMessageBrokerFactory,
|
||||||
|
@ -109,93 +60,40 @@ function _injectorBindings(appComponentType, bus: MessageBus, initData: StringMa
|
||||||
bind(ON_WEB_WORKER).toValue(true),
|
bind(ON_WEB_WORKER).toValue(true),
|
||||||
RenderViewWithFragmentsStore,
|
RenderViewWithFragmentsStore,
|
||||||
RenderProtoViewRefStore,
|
RenderProtoViewRefStore,
|
||||||
ProtoViewFactory,
|
|
||||||
AppViewPool,
|
|
||||||
bind(APP_VIEW_POOL_CAPACITY).toValue(10000),
|
|
||||||
AppViewManager,
|
|
||||||
AppViewManagerUtils,
|
|
||||||
AppViewListener,
|
|
||||||
Compiler,
|
|
||||||
CompilerCache,
|
|
||||||
ViewResolver,
|
|
||||||
DEFAULT_PIPES,
|
|
||||||
bind(IterableDiffers).toValue(defaultIterableDiffers),
|
|
||||||
bind(KeyValueDiffers).toValue(defaultKeyValueDiffers),
|
|
||||||
bind(ChangeDetection).toValue(bestChangeDetection),
|
|
||||||
DirectiveResolver,
|
|
||||||
UrlResolver,
|
|
||||||
StyleUrlResolver,
|
|
||||||
PipeResolver,
|
|
||||||
Parser,
|
|
||||||
Lexer,
|
|
||||||
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(new PrintLogger()), []),
|
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(new PrintLogger()), []),
|
||||||
WebWorkerXHRImpl,
|
WebWorkerXHRImpl,
|
||||||
bind(XHR).toAlias(WebWorkerXHRImpl),
|
bind(XHR).toAlias(WebWorkerXHRImpl),
|
||||||
ComponentUrlMapper,
|
|
||||||
DynamicComponentLoader,
|
|
||||||
bind(AppRootUrl).toValue(new AppRootUrl(initData['rootUrl'])),
|
bind(AppRootUrl).toValue(new AppRootUrl(initData['rootUrl'])),
|
||||||
WebWorkerEventDispatcher,
|
WebWorkerEventDispatcher,
|
||||||
FORM_BINDINGS
|
FORM_BINDINGS
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bootstrapWebWorkerCommon(
|
export function bootstrapWebWorkerCommon(appComponentType: Type, bus: MessageBus,
|
||||||
appComponentType: Type, bus: MessageBus,
|
appBindings: Array<Type | Binding | any[]> = null):
|
||||||
componentInjectableBindings: Array<Type | Binding | any[]> = null): Promise<ApplicationRef> {
|
Promise<ComponentRef> {
|
||||||
var bootstrapProcess: PromiseCompleter<any> = PromiseWrapper.completer();
|
var bootstrapProcess: PromiseCompleter<any> = PromiseWrapper.completer();
|
||||||
|
var appPromise = platform().asyncApplication((zone: NgZone) => {
|
||||||
|
// TODO(rado): prepopulate template cache, so applications with only
|
||||||
|
// index.html and main.js are possible.
|
||||||
|
//
|
||||||
|
bus.attachToZone(zone);
|
||||||
|
bus.initChannel(SETUP_CHANNEL, false);
|
||||||
|
|
||||||
var zone = new NgZone({enableLongStackTrace: assertionsEnabled()});
|
var subscription: any;
|
||||||
bus.attachToZone(zone);
|
var emitter = bus.from(SETUP_CHANNEL);
|
||||||
|
subscription = ObservableWrapper.subscribe(emitter, (message: StringMap<string, any>) => {
|
||||||
var subscription: any;
|
var bindings =
|
||||||
bus.initChannel(SETUP_CHANNEL, false);
|
[applicationCommonBindings(), webWorkerBindings(appComponentType, bus, message)];
|
||||||
var emitter = bus.from(SETUP_CHANNEL);
|
if (isPresent(appBindings)) {
|
||||||
subscription = ObservableWrapper.subscribe(emitter, (message: StringMap<string, any>) => {
|
bindings.push(appBindings);
|
||||||
zone.run(() => {
|
|
||||||
var exceptionHandler;
|
|
||||||
try {
|
|
||||||
var appInjector =
|
|
||||||
_createAppInjector(appComponentType, componentInjectableBindings, zone, bus, message);
|
|
||||||
exceptionHandler = appInjector.get(ExceptionHandler);
|
|
||||||
zone.overrideOnErrorHandler((e, s) => exceptionHandler.call(e, s));
|
|
||||||
var compRefToken: Promise<any> = appInjector.get(APP_COMPONENT_REF_PROMISE);
|
|
||||||
var tick = (componentRef) => {
|
|
||||||
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
|
|
||||||
// retrieve life cycle: may have already been created if injected in root component
|
|
||||||
var lc = appInjector.get(LifeCycle);
|
|
||||||
lc.registerWith(zone, appChangeDetector);
|
|
||||||
lc.tick(); // the first tick that will bootstrap the app
|
|
||||||
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
|
|
||||||
};
|
|
||||||
|
|
||||||
var tickResult = PromiseWrapper.then(compRefToken, tick);
|
|
||||||
|
|
||||||
PromiseWrapper.then(tickResult,
|
|
||||||
(_) => {}); // required for Dart to trigger the default error handler
|
|
||||||
PromiseWrapper.then(tickResult, null,
|
|
||||||
(err, stackTrace) => { bootstrapProcess.reject(err, stackTrace); });
|
|
||||||
ObservableWrapper.dispose(subscription);
|
|
||||||
} catch (e) {
|
|
||||||
if (isPresent(exceptionHandler)) {
|
|
||||||
exceptionHandler.call(e, e.stack);
|
|
||||||
}
|
|
||||||
bootstrapProcess.reject(e, e.stack);
|
|
||||||
}
|
}
|
||||||
|
bootstrapProcess.resolve(bindings);
|
||||||
|
ObservableWrapper.dispose(subscription);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ObservableWrapper.callNext(bus.to(SETUP_CHANNEL), "ready");
|
||||||
|
return bootstrapProcess.promise;
|
||||||
});
|
});
|
||||||
ObservableWrapper.callNext(bus.to(SETUP_CHANNEL), "ready");
|
return PromiseWrapper.then(appPromise, (app) => app.bootstrap(appComponentType));
|
||||||
|
|
||||||
return bootstrapProcess.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _createAppInjector(appComponentType: Type, bindings: Array<Type | Binding | any[]>,
|
|
||||||
zone: NgZone, bus: MessageBus, initData: StringMap<string, any>):
|
|
||||||
Injector {
|
|
||||||
if (isBlank(_rootInjector)) _rootInjector = Injector.resolveAndCreate(_rootBindings);
|
|
||||||
var mergedBindings: any[] =
|
|
||||||
isPresent(bindings) ?
|
|
||||||
ListWrapper.concat(_injectorBindings(appComponentType, bus, initData), bindings) :
|
|
||||||
_injectorBindings(appComponentType, bus, initData);
|
|
||||||
mergedBindings.push(bind(NgZone).toValue(zone));
|
|
||||||
return _rootInjector.resolveAndCreateChild(mergedBindings);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,12 @@ import {
|
||||||
} from 'angular2/test_lib';
|
} from 'angular2/test_lib';
|
||||||
import {isPresent, stringify} from 'angular2/src/core/facade/lang';
|
import {isPresent, stringify} from 'angular2/src/core/facade/lang';
|
||||||
import {bootstrap} from 'angular2/bootstrap';
|
import {bootstrap} from 'angular2/bootstrap';
|
||||||
import {Component, Directive, View} from 'angular2/src/core/metadata';
|
import {ApplicationRef} from 'angular2/src/core/application_ref';
|
||||||
|
import {Component, Directive, View} from 'angular2/core';
|
||||||
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
import {DOM} from 'angular2/src/core/dom/dom_adapter';
|
||||||
import {DOCUMENT} from 'angular2/render';
|
import {DOCUMENT} from 'angular2/render';
|
||||||
import {PromiseWrapper} from 'angular2/src/core/facade/async';
|
import {PromiseWrapper} from 'angular2/src/core/facade/async';
|
||||||
import {bind, Inject, Injector, LifeCycle} from 'angular2/core';
|
import {bind, Inject, Injector, LifeCycle} from 'angular2/core';
|
||||||
import {ApplicationRef} from 'angular2/src/core/application_ref';
|
|
||||||
import {ExceptionHandler} from 'angular2/src/core/facade/exceptions';
|
import {ExceptionHandler} from 'angular2/src/core/facade/exceptions';
|
||||||
import {Testability, TestabilityRegistry} from 'angular2/src/core/testability/testability';
|
import {Testability, TestabilityRegistry} from 'angular2/src/core/testability/testability';
|
||||||
import {IS_DART} from '../platform';
|
import {IS_DART} from '../platform';
|
||||||
|
|
Loading…
Reference in New Issue