refactor(core): support non reflective bootstrap.
This changes Angular so that it can be used without reflection (assuming a codegen for injectors).
BREAKIKNG CHANGE:
- Drops `APP_COMPONENT` provider. Instead, inject
`ApplicationRef` and read its `componentTypes` property.
- long form bootstrap has changed into the following:
```
var platform = createPlatform(ReflectiveInjector.resolveAndCreate(BROWSER_PROVIDERS));
var appInjector =
ReflectiveInjector.resolveAndCreate([BROWSER_APP_PROVIDERS, appProviders], platform.injector);
coreLoadAndBootstrap(appInjector, MyApp);
```
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
import {Type, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {provide, Provider, Injector, OpaqueToken} from 'angular2/src/core/di';
|
||||
import {
|
||||
APP_COMPONENT_REF_PROMISE,
|
||||
APP_COMPONENT,
|
||||
APP_ID_RANDOM_PROVIDER
|
||||
} from './application_tokens';
|
||||
import {APP_ID_RANDOM_PROVIDER} from './application_tokens';
|
||||
import {APPLICATION_CORE_PROVIDERS} from './application_ref';
|
||||
import {
|
||||
IterableDiffers,
|
||||
defaultIterableDiffers,
|
||||
@@ -24,6 +21,7 @@ var __unused: Type; // avoid unused import when Type union types are erased
|
||||
* application, regardless of the platform it runs onto.
|
||||
*/
|
||||
export const APPLICATION_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
|
||||
APPLICATION_CORE_PROVIDERS,
|
||||
new Provider(ComponentResolver, {useClass: ReflectorComponentResolver}),
|
||||
APP_ID_RANDOM_PROVIDER,
|
||||
ViewUtils,
|
||||
|
||||
@@ -5,20 +5,17 @@ import {
|
||||
isPresent,
|
||||
assertionsEnabled,
|
||||
print,
|
||||
IS_DART
|
||||
IS_DART,
|
||||
CONST_EXPR,
|
||||
lockMode,
|
||||
isPromise
|
||||
} from 'angular2/src/facade/lang';
|
||||
import {provide, Provider, Injector, ReflectiveInjector, OpaqueToken} from 'angular2/src/core/di';
|
||||
import {
|
||||
APP_COMPONENT_REF_PROMISE,
|
||||
APP_COMPONENT,
|
||||
APP_ID_RANDOM_PROVIDER,
|
||||
PLATFORM_INITIALIZER,
|
||||
APP_INITIALIZER
|
||||
} from './application_tokens';
|
||||
import {provide, Provider, Injector, Injectable} from 'angular2/src/core/di';
|
||||
import {APP_ID_RANDOM_PROVIDER, PLATFORM_INITIALIZER, APP_INITIALIZER} from './application_tokens';
|
||||
import {PromiseWrapper, PromiseCompleter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {TestabilityRegistry, Testability} from 'angular2/src/core/testability/testability';
|
||||
import {DynamicComponentLoader} from 'angular2/src/core/linker/dynamic_component_loader';
|
||||
import {ComponentResolver} from 'angular2/src/core/linker/component_resolver';
|
||||
import {ComponentRef} from 'angular2/src/core/linker/component_factory';
|
||||
import {
|
||||
BaseException,
|
||||
@@ -29,42 +26,7 @@ import {
|
||||
import {Console} from 'angular2/src/core/console';
|
||||
import {wtfLeave, wtfCreateScope, WtfScopeFn} from './profile/profile';
|
||||
import {ChangeDetectorRef} from 'angular2/src/core/change_detection/change_detector_ref';
|
||||
import {lockMode} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
* Construct providers specific to an individual root component.
|
||||
*/
|
||||
function _componentProviders(appComponentType: Type): Array<Type | Provider | any[]> {
|
||||
return [
|
||||
provide(APP_COMPONENT, {useValue: appComponentType}),
|
||||
provide(APP_COMPONENT_REF_PROMISE,
|
||||
{
|
||||
useFactory: (dynamicComponentLoader: DynamicComponentLoader, appRef: ApplicationRef_,
|
||||
injector: Injector) => {
|
||||
// Save the ComponentRef for disposal later.
|
||||
var ref: ComponentRef;
|
||||
// TODO(rado): investigate whether to support providers on root component.
|
||||
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector,
|
||||
() => { appRef._unloadComponent(ref); })
|
||||
.then((componentRef) => {
|
||||
ref = componentRef;
|
||||
var testability = injector.get(Testability, null);
|
||||
if (isPresent(testability)) {
|
||||
injector.get(TestabilityRegistry)
|
||||
.registerApplication(componentRef.location.nativeElement, testability);
|
||||
}
|
||||
return componentRef;
|
||||
});
|
||||
},
|
||||
deps: [DynamicComponentLoader, ApplicationRef, Injector]
|
||||
}),
|
||||
provide(appComponentType,
|
||||
{
|
||||
useFactory: (p: Promise<any>) => p.then(ref => ref.instance),
|
||||
deps: [APP_COMPONENT_REF_PROMISE]
|
||||
}),
|
||||
];
|
||||
}
|
||||
import {ComponentFactory} from 'angular2/src/core/linker/component_factory';
|
||||
|
||||
/**
|
||||
* Create an Angular zone.
|
||||
@@ -74,59 +36,86 @@ export function createNgZone(): NgZone {
|
||||
}
|
||||
|
||||
var _platform: PlatformRef;
|
||||
var _platformProviders: any[];
|
||||
var _inPlatformCreate: boolean = false;
|
||||
|
||||
/**
|
||||
* Initialize the Angular 'platform' on the page.
|
||||
*
|
||||
* See {@link PlatformRef} for details on the Angular platform.
|
||||
*
|
||||
* It is also possible to specify providers to be made in the new platform. These providers
|
||||
* will be shared between all applications on the page. For example, an abstraction for
|
||||
* the browser cookie jar should be bound at the platform level, because there is only one
|
||||
* cookie jar regardless of how many applications on the page will be accessing it.
|
||||
*
|
||||
* The platform function can be called multiple times as long as the same list of providers
|
||||
* is passed into each call. If the platform function is called with a different set of
|
||||
* provides, Angular will throw an exception.
|
||||
* Creates a platform.
|
||||
* Platforms have to be eagerly created via this function.
|
||||
*/
|
||||
export function platform(providers?: Array<Type | Provider | any[]>): PlatformRef {
|
||||
lockMode();
|
||||
if (isPresent(_platform)) {
|
||||
if (ListWrapper.equals(_platformProviders, providers)) {
|
||||
return _platform;
|
||||
} else {
|
||||
throw new BaseException("platform cannot be initialized with different sets of providers.");
|
||||
}
|
||||
} else {
|
||||
return _createPlatform(providers);
|
||||
export function createPlatform(injector: Injector): PlatformRef {
|
||||
if (_inPlatformCreate) {
|
||||
throw new BaseException('Already creating a platform...');
|
||||
}
|
||||
if (isPresent(_platform) && !_platform.disposed) {
|
||||
throw new BaseException(
|
||||
"There can be only one platform. Destroy the previous one to create a new one.");
|
||||
}
|
||||
lockMode();
|
||||
_inPlatformCreate = true;
|
||||
try {
|
||||
_platform = injector.get(PlatformRef);
|
||||
} finally {
|
||||
_inPlatformCreate = false;
|
||||
}
|
||||
return _platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that there currently is a platform
|
||||
* which contains the given token as a provider.
|
||||
*/
|
||||
export function assertPlatform(requiredToken: any): PlatformRef {
|
||||
var platform = getPlatform();
|
||||
if (isBlank(platform)) {
|
||||
throw new BaseException('Not platform exists!');
|
||||
}
|
||||
if (isPresent(platform) && isBlank(platform.injector.get(requiredToken, null))) {
|
||||
throw new BaseException(
|
||||
'A platform with a different configuration has been created. Please destroy it first.');
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the existing platform.
|
||||
*/
|
||||
export function disposePlatform(): void {
|
||||
if (isPresent(_platform)) {
|
||||
if (isPresent(_platform) && !_platform.disposed) {
|
||||
_platform.dispose();
|
||||
_platform = null;
|
||||
}
|
||||
}
|
||||
|
||||
function _createPlatform(providers?: Array<Type | Provider | any[]>): PlatformRef {
|
||||
_platformProviders = providers;
|
||||
let injector = ReflectiveInjector.resolveAndCreate(providers);
|
||||
_platform = new PlatformRef_(injector, () => {
|
||||
_platform = null;
|
||||
_platformProviders = null;
|
||||
});
|
||||
_runPlatformInitializers(injector);
|
||||
return _platform;
|
||||
/**
|
||||
* Returns the current platform.
|
||||
*/
|
||||
export function getPlatform(): PlatformRef {
|
||||
return isPresent(_platform) && !_platform.disposed ? _platform : null;
|
||||
}
|
||||
|
||||
function _runPlatformInitializers(injector: Injector): void {
|
||||
let inits: Function[] = <Function[]>injector.get(PLATFORM_INITIALIZER, null);
|
||||
if (isPresent(inits)) inits.forEach(init => init());
|
||||
/**
|
||||
* Shortcut for ApplicationRef.bootstrap.
|
||||
* Requires a platform the be created first.
|
||||
*/
|
||||
export function coreBootstrap(injector: Injector,
|
||||
componentFactory: ComponentFactory): ComponentRef {
|
||||
var appRef: ApplicationRef = injector.get(ApplicationRef);
|
||||
return appRef.bootstrap(componentFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the componentFactory for the given component,
|
||||
* waits for asynchronous initializers and bootstraps the component.
|
||||
* Requires a platform the be created first.
|
||||
*/
|
||||
export function coreLoadAndBootstrap(injector: Injector,
|
||||
componentType: Type): Promise<ComponentRef> {
|
||||
var appRef: ApplicationRef = injector.get(ApplicationRef);
|
||||
return appRef.run(() => {
|
||||
var componentResolver: ComponentResolver = injector.get(ComponentResolver);
|
||||
return PromiseWrapper
|
||||
.all([componentResolver.resolveComponent(componentType), appRef.waitForAsyncInitializers()])
|
||||
.then((arr) => appRef.bootstrap(arr[0]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +124,7 @@ function _runPlatformInitializers(injector: Injector): void {
|
||||
* to every Angular application running on the page are bound in its scope.
|
||||
*
|
||||
* A page's platform is initialized implicitly when {@link bootstrap}() is called, or
|
||||
* explicitly by calling {@link platform}().
|
||||
* explicitly by calling {@link createPlatform}().
|
||||
*/
|
||||
export abstract class PlatformRef {
|
||||
/**
|
||||
@@ -149,157 +138,50 @@ export abstract class PlatformRef {
|
||||
*/
|
||||
get injector(): Injector { throw unimplemented(); };
|
||||
|
||||
/**
|
||||
* Instantiate a new Angular application on the page.
|
||||
*
|
||||
* ### What is an application?
|
||||
*
|
||||
* Each Angular application has its own zone, change detection, compiler,
|
||||
* renderer, and other framework components. An application hosts one or more
|
||||
* root components, which can be initialized via `ApplicationRef.bootstrap()`.
|
||||
*
|
||||
* ### Application Providers
|
||||
*
|
||||
* Angular applications require numerous providers to be properly instantiated.
|
||||
* When using `application()` to create a new app on the page, these providers
|
||||
* must be provided. Fortunately, there are helper functions to configure
|
||||
* typical providers, as shown in the example below.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* {@example core/ts/platform/platform.ts region='longform'}
|
||||
* ### See Also
|
||||
*
|
||||
* See the {@link bootstrap} documentation for more details.
|
||||
*/
|
||||
abstract application(providers: Array<Type | Provider | any[]>): ApplicationRef;
|
||||
|
||||
/**
|
||||
* Instantiate a new Angular application on the page, using providers which
|
||||
* are only available asynchronously. One such use case is to initialize an
|
||||
* application running in a web worker.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* `bindingFn` is a function that will be called in the new application's zone.
|
||||
* It should return a `Promise` to a list of providers to be used for the
|
||||
* new application. Once this promise resolves, the application will be
|
||||
* constructed in the same manner as a normal `application()`.
|
||||
*/
|
||||
abstract asyncApplication(bindingFn: (zone: NgZone) => Promise<Array<Type | Provider | any[]>>,
|
||||
providers?: Array<Type | Provider | any[]>): Promise<ApplicationRef>;
|
||||
|
||||
/**
|
||||
* Destroy the Angular platform and all Angular applications on the page.
|
||||
*/
|
||||
abstract dispose(): void;
|
||||
|
||||
get disposed(): boolean { throw unimplemented(); }
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PlatformRef_ extends PlatformRef {
|
||||
/** @internal */
|
||||
_applications: ApplicationRef[] = [];
|
||||
/** @internal */
|
||||
_disposeListeners: Function[] = [];
|
||||
|
||||
constructor(private _injector: ReflectiveInjector, private _dispose: () => void) { super(); }
|
||||
private _disposed: boolean = false;
|
||||
|
||||
constructor(private _injector: Injector) {
|
||||
super();
|
||||
if (!_inPlatformCreate) {
|
||||
throw new BaseException('Platforms have to be created via `createPlatform`!');
|
||||
}
|
||||
let inits: Function[] = <Function[]>_injector.get(PLATFORM_INITIALIZER, null);
|
||||
if (isPresent(inits)) inits.forEach(init => init());
|
||||
}
|
||||
|
||||
registerDisposeListener(dispose: () => void): void { this._disposeListeners.push(dispose); }
|
||||
|
||||
get injector(): ReflectiveInjector { return this._injector; }
|
||||
get injector(): Injector { return this._injector; }
|
||||
|
||||
application(providers: Array<Type | Provider | any[]>): ApplicationRef {
|
||||
var app = this._initApp(createNgZone(), providers);
|
||||
if (PromiseWrapper.isPromise(app)) {
|
||||
throw new BaseException(
|
||||
"Cannot use asyncronous app initializers with application. Use asyncApplication instead.");
|
||||
}
|
||||
return <ApplicationRef>app;
|
||||
}
|
||||
get disposed() { return this._disposed; }
|
||||
|
||||
asyncApplication(bindingFn: (zone: NgZone) => Promise<Array<Type | Provider | any[]>>,
|
||||
additionalProviders?: Array<Type | Provider | any[]>): Promise<ApplicationRef> {
|
||||
var zone = createNgZone();
|
||||
var completer = PromiseWrapper.completer<ApplicationRef>();
|
||||
if (bindingFn === null) {
|
||||
completer.resolve(this._initApp(zone, additionalProviders));
|
||||
} else {
|
||||
zone.run(() => {
|
||||
PromiseWrapper.then(bindingFn(zone), (providers: Array<Type | Provider | any[]>) => {
|
||||
if (isPresent(additionalProviders)) {
|
||||
providers = ListWrapper.concat(providers, additionalProviders);
|
||||
}
|
||||
let promise = this._initApp(zone, providers);
|
||||
completer.resolve(promise);
|
||||
});
|
||||
});
|
||||
}
|
||||
return completer.promise;
|
||||
}
|
||||
|
||||
private _initApp(zone: NgZone,
|
||||
providers: Array<Type | Provider | any[]>): Promise<ApplicationRef>|
|
||||
ApplicationRef {
|
||||
var injector: ReflectiveInjector;
|
||||
var app: ApplicationRef;
|
||||
zone.run(() => {
|
||||
providers = ListWrapper.concat(providers, [
|
||||
provide(NgZone, {useValue: zone}),
|
||||
provide(ApplicationRef, {useFactory: (): ApplicationRef => app, deps: []})
|
||||
]);
|
||||
|
||||
var exceptionHandler: ExceptionHandler;
|
||||
try {
|
||||
injector = this.injector.resolveAndCreateChild(providers);
|
||||
exceptionHandler = injector.get(ExceptionHandler);
|
||||
ObservableWrapper.subscribe(zone.onError, (error: NgZoneError) => {
|
||||
exceptionHandler.call(error.error, error.stackTrace);
|
||||
});
|
||||
} catch (e) {
|
||||
if (isPresent(exceptionHandler)) {
|
||||
exceptionHandler.call(e, e.stack);
|
||||
} else {
|
||||
print(e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
app = new ApplicationRef_(this, zone, injector);
|
||||
this._applications.push(app);
|
||||
var promise = _runAppInitializers(injector);
|
||||
if (promise !== null) {
|
||||
return PromiseWrapper.then(promise, (_) => app);
|
||||
} else {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
addApplication(appRef: ApplicationRef) { this._applications.push(appRef); }
|
||||
|
||||
dispose(): void {
|
||||
ListWrapper.clone(this._applications).forEach((app) => app.dispose());
|
||||
this._disposeListeners.forEach((dispose) => dispose());
|
||||
this._dispose();
|
||||
this._disposed = true;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_applicationDisposed(app: ApplicationRef): void { ListWrapper.remove(this._applications, app); }
|
||||
}
|
||||
|
||||
function _runAppInitializers(injector: Injector): Promise<any> {
|
||||
let inits: Function[] = injector.get(APP_INITIALIZER, null);
|
||||
let promises: Promise<any>[] = [];
|
||||
if (isPresent(inits)) {
|
||||
inits.forEach(init => {
|
||||
var retVal = init();
|
||||
if (PromiseWrapper.isPromise(retVal)) {
|
||||
promises.push(retVal);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (promises.length > 0) {
|
||||
return PromiseWrapper.all(promises);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to an Angular application running on a page.
|
||||
*
|
||||
@@ -317,6 +199,18 @@ export abstract class ApplicationRef {
|
||||
*/
|
||||
abstract registerDisposeListener(dispose: () => void): void;
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves when all asynchronous application initializers
|
||||
* are done.
|
||||
*/
|
||||
abstract waitForAsyncInitializers(): Promise<any>;
|
||||
|
||||
/**
|
||||
* Runs the given callback in the zone and returns the result of the callback.
|
||||
* Exceptions will be forwarded to the ExceptionHandler and rethrown.
|
||||
*/
|
||||
abstract run(callback: Function): any;
|
||||
|
||||
/**
|
||||
* Bootstrap a new component at the root level of the application.
|
||||
*
|
||||
@@ -326,17 +220,10 @@ export abstract class ApplicationRef {
|
||||
* specified application component onto DOM elements identified by the [componentType]'s
|
||||
* selector and kicks off automatic change detection to finish initializing the component.
|
||||
*
|
||||
* ### Optional Providers
|
||||
*
|
||||
* Providers for the given component can optionally be overridden via the `providers`
|
||||
* parameter. These providers will only apply for the root component being added and any
|
||||
* child components under it.
|
||||
*
|
||||
* ### Example
|
||||
* {@example core/ts/platform/platform.ts region='longform'}
|
||||
*/
|
||||
abstract bootstrap(componentType: Type,
|
||||
providers?: Array<Type | Provider | any[]>): Promise<ComponentRef>;
|
||||
abstract bootstrap(componentFactory: ComponentFactory): ComponentRef;
|
||||
|
||||
/**
|
||||
* Retrieve the application {@link Injector}.
|
||||
@@ -371,6 +258,7 @@ export abstract class ApplicationRef {
|
||||
get componentTypes(): Type[] { return <Type[]>unimplemented(); };
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationRef_ extends ApplicationRef {
|
||||
/** @internal */
|
||||
static _tickScope: WtfScopeFn = wtfCreateScope('ApplicationRef#tick()');
|
||||
@@ -390,14 +278,43 @@ export class ApplicationRef_ extends ApplicationRef {
|
||||
/** @internal */
|
||||
private _enforceNoNewChanges: boolean = false;
|
||||
|
||||
constructor(private _platform: PlatformRef_, private _zone: NgZone,
|
||||
private _injector: ReflectiveInjector) {
|
||||
private _exceptionHandler: ExceptionHandler;
|
||||
|
||||
private _asyncInitDonePromise: Promise<any>;
|
||||
private _asyncInitDone: boolean;
|
||||
|
||||
constructor(private _platform: PlatformRef_, private _zone: NgZone, private _injector: Injector) {
|
||||
super();
|
||||
if (isPresent(this._zone)) {
|
||||
ObservableWrapper.subscribe(this._zone.onMicrotaskEmpty,
|
||||
(_) => { this._zone.run(() => { this.tick(); }); });
|
||||
}
|
||||
var zone: NgZone = _injector.get(NgZone);
|
||||
this._enforceNoNewChanges = assertionsEnabled();
|
||||
zone.run(() => { this._exceptionHandler = _injector.get(ExceptionHandler); });
|
||||
this._asyncInitDonePromise = this.run(() => {
|
||||
let inits: Function[] = _injector.get(APP_INITIALIZER, null);
|
||||
var asyncInitResults = [];
|
||||
var asyncInitDonePromise;
|
||||
if (isPresent(inits)) {
|
||||
for (var i = 0; i < inits.length; i++) {
|
||||
var initResult = inits[i]();
|
||||
if (isPromise(initResult)) {
|
||||
asyncInitResults.push(initResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (asyncInitResults.length > 0) {
|
||||
asyncInitDonePromise =
|
||||
PromiseWrapper.all(asyncInitResults).then((_) => this._asyncInitDone = true);
|
||||
this._asyncInitDone = false;
|
||||
} else {
|
||||
this._asyncInitDone = true;
|
||||
asyncInitDonePromise = PromiseWrapper.resolve(true);
|
||||
}
|
||||
return asyncInitDonePromise;
|
||||
});
|
||||
ObservableWrapper.subscribe(zone.onError, (error: NgZoneError) => {
|
||||
this._exceptionHandler.call(error.error, error.stackTrace);
|
||||
});
|
||||
ObservableWrapper.subscribe(this._zone.onMicrotaskEmpty,
|
||||
(_) => { this._zone.run(() => { this.tick(); }); });
|
||||
}
|
||||
|
||||
registerBootstrapListener(listener: (ref: ComponentRef) => void): void {
|
||||
@@ -414,42 +331,56 @@ export class ApplicationRef_ extends ApplicationRef {
|
||||
ListWrapper.remove(this._changeDetectorRefs, changeDetector);
|
||||
}
|
||||
|
||||
bootstrap(componentType: Type,
|
||||
providers?: Array<Type | Provider | any[]>): Promise<ComponentRef> {
|
||||
waitForAsyncInitializers(): Promise<any> { return this._asyncInitDonePromise; }
|
||||
|
||||
run(callback: Function): any {
|
||||
var zone = this.injector.get(NgZone);
|
||||
var result;
|
||||
// Note: Don't use zone.runGuarded as we want to know about
|
||||
// the thrown exception!
|
||||
// Note: the completer needs to be created outside
|
||||
// of `zone.run` as Dart swallows rejected promises
|
||||
// via the onError callback of the promise.
|
||||
var completer = PromiseWrapper.completer();
|
||||
this._zone.run(() => {
|
||||
var componentProviders = _componentProviders(componentType);
|
||||
if (isPresent(providers)) {
|
||||
componentProviders.push(providers);
|
||||
}
|
||||
var exceptionHandler = this._injector.get(ExceptionHandler);
|
||||
this._rootComponentTypes.push(componentType);
|
||||
zone.run(() => {
|
||||
try {
|
||||
var injector: Injector = this._injector.resolveAndCreateChild(componentProviders);
|
||||
var compRefToken: Promise<ComponentRef> = injector.get(APP_COMPONENT_REF_PROMISE);
|
||||
var tick = (componentRef: ComponentRef) => {
|
||||
this._loadComponent(componentRef);
|
||||
completer.resolve(componentRef);
|
||||
};
|
||||
|
||||
var tickResult = PromiseWrapper.then(compRefToken, tick);
|
||||
|
||||
PromiseWrapper.then(tickResult, null, (err, stackTrace) => {
|
||||
completer.reject(err, stackTrace);
|
||||
exceptionHandler.call(err, stackTrace);
|
||||
});
|
||||
result = callback();
|
||||
if (isPromise(result)) {
|
||||
PromiseWrapper.then(result, (ref) => { completer.resolve(ref); }, (err, stackTrace) => {
|
||||
completer.reject(err, stackTrace);
|
||||
this._exceptionHandler.call(err, stackTrace);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
exceptionHandler.call(e, e.stack);
|
||||
completer.reject(e, e.stack);
|
||||
this._exceptionHandler.call(e, e.stack);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
return completer.promise.then<ComponentRef>((ref: ComponentRef) => {
|
||||
return isPromise(result) ? completer.promise : result;
|
||||
}
|
||||
|
||||
bootstrap(componentFactory: ComponentFactory): ComponentRef {
|
||||
if (!this._asyncInitDone) {
|
||||
throw new BaseException(
|
||||
'Cannot bootstrap as there are still asynchronous initializers running. Wait for them using waitForAsyncInitializers().');
|
||||
}
|
||||
return this.run(() => {
|
||||
this._rootComponentTypes.push(componentFactory.componentType);
|
||||
var compRef = componentFactory.create(this._injector, [], componentFactory.selector);
|
||||
compRef.onDestroy(() => { this._unloadComponent(compRef); });
|
||||
var testability = compRef.injector.get(Testability, null);
|
||||
if (isPresent(testability)) {
|
||||
compRef.injector.get(TestabilityRegistry)
|
||||
.registerApplication(compRef.location.nativeElement, testability);
|
||||
}
|
||||
|
||||
this._loadComponent(compRef);
|
||||
let c = this._injector.get(Console);
|
||||
if (assertionsEnabled()) {
|
||||
c.log(
|
||||
"Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.");
|
||||
}
|
||||
return ref;
|
||||
return compRef;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -501,3 +432,18 @@ export class ApplicationRef_ extends ApplicationRef {
|
||||
|
||||
get componentTypes(): Type[] { return this._rootComponentTypes; }
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const PLATFORM_CORE_PROVIDERS =
|
||||
CONST_EXPR([PlatformRef_, CONST_EXPR(new Provider(PlatformRef, {useExisting: PlatformRef_}))]);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const APPLICATION_CORE_PROVIDERS = CONST_EXPR([
|
||||
CONST_EXPR(new Provider(NgZone, {useFactory: createNgZone, deps: CONST_EXPR([])})),
|
||||
ApplicationRef_,
|
||||
CONST_EXPR(new Provider(ApplicationRef, {useExisting: ApplicationRef_}))
|
||||
]);
|
||||
|
||||
@@ -1,29 +1,6 @@
|
||||
import {OpaqueToken, Provider} from 'angular2/src/core/di';
|
||||
import {CONST_EXPR, Math, StringWrapper} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const APP_COMPONENT_REF_PROMISE = CONST_EXPR(new OpaqueToken('Promise<ComponentRef>'));
|
||||
|
||||
/**
|
||||
* An {@link OpaqueToken-class.html} representing the application root type in the {@link
|
||||
* Injector}.
|
||||
*
|
||||
* ```
|
||||
* @Component(...)
|
||||
* class MyApp {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* bootstrap(MyApp).then((appRef:ApplicationRef) {
|
||||
* expect(appRef.injector.get(appComponentTypeToken)).toEqual(MyApp);
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
export const APP_COMPONENT: OpaqueToken = CONST_EXPR(new OpaqueToken('AppComponent'));
|
||||
|
||||
/**
|
||||
* A DI Token representing a unique string id assigned to the application by Angular and used
|
||||
* primarily for prefixing application attributes and CSS styles when
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import {AppElement} from './element';
|
||||
|
||||
/**
|
||||
* A wrapper around a native element inside of a View.
|
||||
*
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import {Injector} from 'angular2/src/core/di/injector';
|
||||
import {ReflectiveInjector} from 'angular2/src/core/di/reflective_injector';
|
||||
import {ResolvedReflectiveProvider} from 'angular2/src/core/di/reflective_provider';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
import {wtfCreateScope, wtfLeave, WtfScopeFn} from '../profile/profile';
|
||||
|
||||
@@ -75,8 +73,7 @@ export abstract class ViewContainerRef {
|
||||
*
|
||||
* 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 for the component.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ import {Console} from 'angular2/src/core/console';
|
||||
import {Reflector, reflector} from './reflection/reflection';
|
||||
import {ReflectorReader} from './reflection/reflector_reader';
|
||||
import {TestabilityRegistry} from 'angular2/src/core/testability/testability';
|
||||
import {PLATFORM_CORE_PROVIDERS} from './application_ref';
|
||||
|
||||
function _reflector(): Reflector {
|
||||
return reflector;
|
||||
@@ -13,6 +14,7 @@ function _reflector(): Reflector {
|
||||
* A default set of providers which should be included in any Angular platform.
|
||||
*/
|
||||
export const PLATFORM_COMMON_PROVIDERS: Array<Type | Provider | any[]> = CONST_EXPR([
|
||||
PLATFORM_CORE_PROVIDERS,
|
||||
new Provider(Reflector, {useFactory: _reflector, deps: []}),
|
||||
new Provider(ReflectorReader, {useExisting: Reflector}),
|
||||
TestabilityRegistry,
|
||||
|
||||
@@ -200,9 +200,17 @@ export class NgZone {
|
||||
*
|
||||
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
||||
* within the Angular zone.
|
||||
*
|
||||
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
||||
*/
|
||||
run(fn: () => any): any { return this._zoneImpl.runInner(fn); }
|
||||
|
||||
/**
|
||||
* Same as #run, except that synchronous errors are caught and forwarded
|
||||
* via `onError` and not rethrown.
|
||||
*/
|
||||
runGuarded(fn: () => any): any { return this._zoneImpl.runInnerGuarded(fn); }
|
||||
|
||||
/**
|
||||
* Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
|
||||
* the function.
|
||||
|
||||
@@ -122,10 +122,14 @@ class NgZoneImpl {
|
||||
);
|
||||
}
|
||||
|
||||
dynamic runInner(fn()) {
|
||||
dynamic runInnerGuarded(fn()) {
|
||||
return _innerZone.runGuarded(fn);
|
||||
}
|
||||
|
||||
dynamic runInner(fn()) {
|
||||
return _innerZone.run(fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs `fn` in the mount zone and returns whatever it returns.
|
||||
*
|
||||
|
||||
@@ -94,6 +94,7 @@ export class NgZoneImpl {
|
||||
}
|
||||
}
|
||||
|
||||
runInner(fn: () => any): any { return this.inner.runGuarded(fn); };
|
||||
runInner(fn: () => any): any { return this.inner.run(fn); };
|
||||
runInnerGuarded(fn: () => any): any { return this.inner.runGuarded(fn); };
|
||||
runOuter(fn: () => any): any { return this.outer.run(fn); };
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {ApplicationRef} from 'angular2/src/core/application_ref';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {Type} from 'angular2/src/facade/lang';
|
||||
import {ComponentRef} from 'angular2/src/core/linker/component_factory';
|
||||
import {Provider, Injector} from 'angular2/src/core/di';
|
||||
import {ComponentRef, ComponentFactory} from 'angular2/src/core/linker/component_factory';
|
||||
import {Injector} from 'angular2/src/core/di';
|
||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||
|
||||
/**
|
||||
@@ -14,14 +14,16 @@ export class MockApplicationRef extends ApplicationRef {
|
||||
|
||||
registerDisposeListener(dispose: () => void): void {}
|
||||
|
||||
bootstrap(componentType: Type, bindings?: Array<Type | Provider | any[]>): Promise<ComponentRef> {
|
||||
return null;
|
||||
}
|
||||
bootstrap(componentFactory: ComponentFactory): ComponentRef { return null; }
|
||||
|
||||
get injector(): Injector { return null; };
|
||||
|
||||
get zone(): NgZone { return null; };
|
||||
|
||||
run(callback: Function): any { return null; }
|
||||
|
||||
waitForAsyncInitializers(): Promise<any> { return null; }
|
||||
|
||||
dispose(): void {}
|
||||
|
||||
tick(): void {}
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
PLATFORM_DIRECTIVES,
|
||||
PLATFORM_PIPES,
|
||||
ComponentRef,
|
||||
platform,
|
||||
ExceptionHandler,
|
||||
Reflector,
|
||||
RootRenderer,
|
||||
@@ -48,12 +47,15 @@ export {BrowserDomAdapter} from './browser/browser_adapter';
|
||||
export {enableDebugTools, disableDebugTools} from 'angular2/src/platform/browser/tools/tools';
|
||||
export {HAMMER_GESTURE_CONFIG, HammerGestureConfig} from './dom/events/hammer_gestures';
|
||||
|
||||
export const BROWSER_PLATFORM_MARKER = CONST_EXPR(new OpaqueToken('BrowserPlatformMarker'));
|
||||
|
||||
/**
|
||||
* A set of providers to initialize the Angular platform in a web browser.
|
||||
*
|
||||
* Used automatically by `bootstrap`, or can be passed to {@link platform}.
|
||||
*/
|
||||
export const BROWSER_PROVIDERS: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
new Provider(BROWSER_PLATFORM_MARKER, {useValue: true}),
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
new Provider(PLATFORM_INITIALIZER, {useValue: initDomAdapter, multi: true}),
|
||||
]);
|
||||
|
||||
@@ -10,7 +10,7 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
||||
|
||||
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
|
||||
var zone = this.manager.getZone();
|
||||
var outsideHandler = (event) => zone.run(() => handler(event));
|
||||
var outsideHandler = (event) => zone.runGuarded(() => handler(event));
|
||||
return this.manager.getZone().runOutsideAngular(
|
||||
() => DOM.onAndCancel(element, eventName, outsideHandler));
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||
var element = DOM.getGlobalEventTarget(target);
|
||||
var zone = this.manager.getZone();
|
||||
var outsideHandler = (event) => zone.run(() => handler(event));
|
||||
var outsideHandler = (event) => zone.runGuarded(() => handler(event));
|
||||
return this.manager.getZone().runOutsideAngular(
|
||||
() => DOM.onAndCancel(element, eventName, outsideHandler));
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
||||
mc.callMethod('on', [
|
||||
eventName,
|
||||
(eventObj) {
|
||||
zone.run(() {
|
||||
zone.runGuarded(() {
|
||||
var dartEvent = new HammerEvent._fromJsEvent(eventObj);
|
||||
handler(dartEvent);
|
||||
});
|
||||
|
||||
@@ -52,7 +52,7 @@ export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
||||
return zone.runOutsideAngular(() => {
|
||||
// Creating the manager bind events, must be done outside of angular
|
||||
var mc = this._config.buildHammer(element);
|
||||
var callback = function(eventObj) { zone.run(function() { handler(eventObj); }); };
|
||||
var callback = function(eventObj) { zone.runGuarded(function() { handler(eventObj); }); };
|
||||
mc.on(eventName, callback);
|
||||
return () => { mc.off(eventName, callback); };
|
||||
});
|
||||
|
||||
@@ -95,7 +95,7 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
||||
zone: NgZone): Function {
|
||||
return (event) => {
|
||||
if (StringWrapper.equals(KeyEventsPlugin.getEventFullKey(event), fullKey)) {
|
||||
zone.run(() => handler(event));
|
||||
zone.runGuarded(() => handler(event));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ExceptionHandler,
|
||||
APPLICATION_COMMON_PROVIDERS,
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
OpaqueToken
|
||||
} from 'angular2/core';
|
||||
import {COMMON_DIRECTIVES, COMMON_PIPES, FORM_PROVIDERS} from "angular2/common";
|
||||
import {
|
||||
@@ -31,8 +32,12 @@ class PrintLogger {
|
||||
logGroupEnd() {}
|
||||
}
|
||||
|
||||
export const WORKER_APP_PLATFORM: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([PLATFORM_COMMON_PROVIDERS]);
|
||||
export const WORKER_APP_PLATFORM_MARKER = CONST_EXPR(new OpaqueToken('WorkerAppPlatformMarker'));
|
||||
|
||||
export const WORKER_APP_PLATFORM: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
CONST_EXPR(new Provider(WORKER_APP_PLATFORM_MARKER, {useValue: true}))
|
||||
]);
|
||||
|
||||
export const WORKER_APP_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
APPLICATION_COMMON_PROVIDERS,
|
||||
|
||||
@@ -10,26 +10,23 @@ import 'package:angular2/src/web_workers/shared/isolate_message_bus.dart';
|
||||
import 'package:angular2/src/web_workers/shared/message_bus.dart';
|
||||
import 'package:angular2/core.dart';
|
||||
import 'package:angular2/src/core/di.dart';
|
||||
import 'package:angular2/src/core/zone/ng_zone.dart';
|
||||
import 'dart:isolate';
|
||||
import 'dart:async';
|
||||
|
||||
const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;
|
||||
|
||||
initIsolate(String scriptUri) {
|
||||
return (NgZone zone) async {
|
||||
var instance = await spawnIsolate(Uri.parse(scriptUri));
|
||||
Future<List> initIsolate(String scriptUri) async {
|
||||
var instance = await spawnIsolate(Uri.parse(scriptUri));
|
||||
|
||||
return [
|
||||
WORKER_RENDER_APPLICATION_COMMON,
|
||||
new Provider(WebWorkerInstance, useValue: instance),
|
||||
new Provider(APP_INITIALIZER,
|
||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||
multi: true,
|
||||
deps: [Injector]),
|
||||
new Provider(MessageBus, useValue: instance.bus)
|
||||
];
|
||||
};
|
||||
return [
|
||||
WORKER_RENDER_APPLICATION_COMMON,
|
||||
new Provider(WebWorkerInstance, useValue: instance),
|
||||
new Provider(APP_INITIALIZER,
|
||||
useFactory: (injector) => () => initializeGenericWorkerRenderer(injector),
|
||||
multi: true,
|
||||
deps: [Injector]),
|
||||
new Provider(MessageBus, useValue: instance.bus)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
PLATFORM_DIRECTIVES,
|
||||
PLATFORM_PIPES,
|
||||
ComponentRef,
|
||||
platform,
|
||||
ExceptionHandler,
|
||||
Reflector,
|
||||
reflector,
|
||||
@@ -58,8 +57,12 @@ export const WORKER_SCRIPT: OpaqueToken = CONST_EXPR(new OpaqueToken("WebWorkerS
|
||||
export const WORKER_RENDER_MESSAGING_PROVIDERS: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([MessageBasedRenderer, MessageBasedXHRImpl]);
|
||||
|
||||
export const WORKER_RENDER_PLATFORM_MARKER =
|
||||
CONST_EXPR(new OpaqueToken('WorkerRenderPlatformMarker'));
|
||||
|
||||
export const WORKER_RENDER_PLATFORM: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
PLATFORM_COMMON_PROVIDERS,
|
||||
CONST_EXPR(new Provider(WORKER_RENDER_PLATFORM_MARKER, {useValue: true})),
|
||||
new Provider(PLATFORM_INITIALIZER, {useValue: initWebWorkerRenderPlatform, multi: true})
|
||||
]);
|
||||
|
||||
@@ -103,7 +106,7 @@ export function initializeGenericWorkerRenderer(injector: Injector) {
|
||||
let zone = injector.get(NgZone);
|
||||
bus.attachToZone(zone);
|
||||
|
||||
zone.run(() => {
|
||||
zone.runGuarded(() => {
|
||||
WORKER_RENDER_MESSAGING_PROVIDERS.forEach((token) => { injector.get(token).start(); });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {
|
||||
provide,
|
||||
platform,
|
||||
ApplicationRef,
|
||||
ComponentResolver,
|
||||
Injector,
|
||||
NgZone,
|
||||
PlatformRef,
|
||||
ReflectiveInjector,
|
||||
ComponentFactory,
|
||||
Provider,
|
||||
Type,
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from 'angular2/core';
|
||||
import {global} from 'angular2/src/facade/lang';
|
||||
import {ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS} from 'angular2/platform/browser';
|
||||
import {BROWSER_PROVIDERS, BROWSER_APP_PROVIDERS, browserPlatform} from 'angular2/platform/browser';
|
||||
|
||||
import {getComponentInfo, ComponentInfo} from './metadata';
|
||||
import {onError, controllerKey} from './util';
|
||||
@@ -294,13 +294,18 @@ export class UpgradeAdapter {
|
||||
config?: angular.IAngularBootstrapConfig): UpgradeAdapterRef {
|
||||
var upgrade = new UpgradeAdapterRef();
|
||||
var ng1Injector: angular.IInjectorService = null;
|
||||
var platformRef: PlatformRef = platform(BROWSER_PROVIDERS);
|
||||
var applicationRef: ApplicationRef = platformRef.application([
|
||||
BROWSER_APP_PROVIDERS,
|
||||
provide(NG1_INJECTOR, {useFactory: () => ng1Injector}),
|
||||
provide(NG1_COMPILE, {useFactory: () => ng1Injector.get(NG1_COMPILE)}),
|
||||
this.providers
|
||||
]);
|
||||
var platformRef: PlatformRef = browserPlatform();
|
||||
var applicationRef: ApplicationRef =
|
||||
ReflectiveInjector.resolveAndCreate(
|
||||
[
|
||||
BROWSER_APP_PROVIDERS,
|
||||
provide(NG1_INJECTOR, {useFactory: () => ng1Injector}),
|
||||
provide(NG1_COMPILE,
|
||||
{useFactory: () => ng1Injector.get(NG1_COMPILE)}),
|
||||
this.providers
|
||||
],
|
||||
platformRef.injector)
|
||||
.get(ApplicationRef);
|
||||
var injector: Injector = applicationRef.injector;
|
||||
var ngZone: NgZone = injector.get(NgZone);
|
||||
var compiler: ComponentResolver = injector.get(ComponentResolver);
|
||||
|
||||
@@ -17,6 +17,6 @@ function initRouterListeners(injector: Injector): () => void {
|
||||
return () => {
|
||||
let zone = injector.get(NgZone);
|
||||
|
||||
zone.run(() => injector.get(MessageBasedPlatformLocation).start());
|
||||
zone.runGuarded(() => injector.get(MessageBasedPlatformLocation).start());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@ export var WORKER_APP_ROUTER = [
|
||||
];
|
||||
|
||||
function initRouter(platformLocation: WebWorkerPlatformLocation, zone: NgZone): Promise<boolean> {
|
||||
return zone.run(() => { return platformLocation.init(); });
|
||||
return zone.runGuarded(() => { return platformLocation.init(); });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user