parent
800c8f196f
commit
8bea667a0b
|
@ -12,3 +12,5 @@ export 'package:angular2/src/web_workers/shared/service_message_broker.dart'
|
|||
show ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory;
|
||||
export 'package:angular2/src/web_workers/shared/serializer.dart' show PRIMITIVE;
|
||||
export 'package:angular2/src/web_workers/shared/message_bus.dart';
|
||||
export 'package:angular2/src/web_workers/worker/router_providers.dart'
|
||||
show WORKER_APP_ROUTER;
|
||||
|
|
|
@ -8,12 +8,13 @@ export {
|
|||
ClientMessageBrokerFactory,
|
||||
FnArg,
|
||||
UiArguments
|
||||
} from '../src/web_workers/shared/client_message_broker';
|
||||
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
export {
|
||||
ReceivedMessage,
|
||||
ServiceMessageBroker,
|
||||
ServiceMessageBrokerFactory
|
||||
} from '../src/web_workers/shared/service_message_broker';
|
||||
export {PRIMITIVE} from '../src/web_workers/shared/serializer';
|
||||
export * from '../src/web_workers/shared/message_bus';
|
||||
} from 'angular2/src/web_workers/shared/service_message_broker';
|
||||
export {PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
|
||||
export * from 'angular2/src/web_workers/shared/message_bus';
|
||||
export {AngularEntrypoint} from 'angular2/src/core/angular_entrypoint';
|
||||
export {WORKER_APP_ROUTER} from 'angular2/src/web_workers/worker/router_providers';
|
||||
|
|
|
@ -18,7 +18,9 @@ export '../src/web_workers/shared/service_message_broker.dart'
|
|||
|
||||
export '../src/web_workers/shared/serializer.dart' show PRIMITIVE;
|
||||
export '../src/web_workers/shared/message_bus.dart';
|
||||
export '../src/web_workers/ui/router_providers.dart' show WORKER_RENDER_ROUTER;
|
||||
|
||||
import 'package:angular2/src/platform/worker_render_common.dart';
|
||||
|
||||
const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION_COMMON;
|
||||
|
||||
|
|
|
@ -24,3 +24,4 @@ import {WORKER_RENDER_APPLICATION} from 'angular2/src/platform/worker_render';
|
|||
* @deprecated Use WORKER_RENDER_APPLICATION
|
||||
*/
|
||||
export const WORKER_RENDER_APP = WORKER_RENDER_APPLICATION;
|
||||
export {WORKER_RENDER_ROUTER} from 'angular2/src/web_workers/ui/router_providers';
|
||||
|
|
|
@ -20,18 +20,12 @@ export {OnActivate, OnDeactivate, OnReuse, CanDeactivate, CanReuse} from './src/
|
|||
export {CanActivate} from './src/router/lifecycle_annotations';
|
||||
export {Instruction, ComponentInstruction} from './src/router/instruction';
|
||||
export {OpaqueToken} from 'angular2/core';
|
||||
export {ROUTER_PROVIDERS_COMMON} from 'angular2/src/router/router_providers_common';
|
||||
export {ROUTER_PROVIDERS, ROUTER_BINDINGS} from 'angular2/src/router/router_providers';
|
||||
|
||||
import {PlatformLocation} from './src/router/platform_location';
|
||||
import {LocationStrategy} from './src/router/location_strategy';
|
||||
import {PathLocationStrategy} from './src/router/path_location_strategy';
|
||||
import {Router, RootRouter} from './src/router/router';
|
||||
import {RouterOutlet} from './src/router/router_outlet';
|
||||
import {RouterLink} from './src/router/router_link';
|
||||
import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from './src/router/route_registry';
|
||||
import {Location} from './src/router/location';
|
||||
import {ApplicationRef, provide, OpaqueToken, Provider} from 'angular2/core';
|
||||
import {CONST_EXPR} from './src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
/**
|
||||
* A list of directives. To use the router directives like {@link RouterOutlet} and
|
||||
|
@ -56,63 +50,3 @@ import {BaseException} from 'angular2/src/facade/exceptions';
|
|||
* ```
|
||||
*/
|
||||
export const ROUTER_DIRECTIVES: any[] = CONST_EXPR([RouterOutlet, RouterLink]);
|
||||
|
||||
/**
|
||||
* A list of {@link Provider}s. To use the router, you must add this to your application.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
|
||||
*
|
||||
* ```
|
||||
* import {Component} from 'angular2/core';
|
||||
* import {
|
||||
* ROUTER_DIRECTIVES,
|
||||
* ROUTER_PROVIDERS,
|
||||
* RouteConfig
|
||||
* } from 'angular2/router';
|
||||
*
|
||||
* @Component({directives: [ROUTER_DIRECTIVES]})
|
||||
* @RouteConfig([
|
||||
* {...},
|
||||
* ])
|
||||
* class AppCmp {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* bootstrap(AppCmp, [ROUTER_PROVIDERS]);
|
||||
* ```
|
||||
*/
|
||||
export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
|
||||
RouteRegistry,
|
||||
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
|
||||
PlatformLocation,
|
||||
Location,
|
||||
CONST_EXPR(new Provider(
|
||||
Router,
|
||||
{
|
||||
useFactory: routerFactory,
|
||||
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
|
||||
})),
|
||||
CONST_EXPR(new Provider(
|
||||
ROUTER_PRIMARY_COMPONENT,
|
||||
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
|
||||
]);
|
||||
|
||||
/**
|
||||
* Use {@link ROUTER_PROVIDERS} instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;
|
||||
|
||||
function routerFactory(registry, location, primaryComponent, appRef) {
|
||||
var rootRouter = new RootRouter(registry, location, primaryComponent);
|
||||
appRef.registerDisposeListener(() => rootRouter.dispose());
|
||||
return rootRouter;
|
||||
}
|
||||
|
||||
function routerPrimaryComponentFactory(app) {
|
||||
if (app.componentTypes.length == 0) {
|
||||
throw new BaseException("Bootstrap at least one component before injecting Router.");
|
||||
}
|
||||
return app.componentTypes[0];
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import {BrowserDomAdapter} from './browser/browser_adapter';
|
|||
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
|
||||
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
|
||||
import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl';
|
||||
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
|
||||
import {
|
||||
ServiceMessageBrokerFactory,
|
||||
ServiceMessageBrokerFactory_
|
||||
|
@ -59,6 +60,13 @@ export const WORKER_RENDER_PLATFORM: Array<any /*Type | Provider | any[]*/> = CO
|
|||
new Provider(PLATFORM_INITIALIZER, {useValue: initWebWorkerRenderPlatform, multi: true})
|
||||
]);
|
||||
|
||||
/**
|
||||
* A list of {@link Provider}s. To use the router in a Worker enabled application you must
|
||||
* include these providers when setting up the render thread.
|
||||
*/
|
||||
export const WORKER_RENDER_ROUTER: Array<any /*Type | Provider | any[]*/> =
|
||||
CONST_EXPR([BrowserPlatformLocation]);
|
||||
|
||||
export const WORKER_RENDER_APPLICATION_COMMON: Array<any /*Type | Provider | any[]*/> = CONST_EXPR([
|
||||
APPLICATION_COMMON_PROVIDERS,
|
||||
WORKER_RENDER_MESSAGING_PROVIDERS,
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import {Injectable} from 'angular2/core';
|
||||
import {History, Location} from 'angular2/src/facade/browser';
|
||||
import {UrlChangeListener} from './platform_location';
|
||||
import {PlatformLocation} from './platform_location';
|
||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
|
||||
/**
|
||||
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
|
||||
* This class should not be used directly by an application developer. Instead, use
|
||||
* {@link Location}.
|
||||
*/
|
||||
@Injectable()
|
||||
export class BrowserPlatformLocation extends PlatformLocation {
|
||||
private _location: Location;
|
||||
private _history: History;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._init();
|
||||
}
|
||||
|
||||
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
|
||||
/** @internal */
|
||||
_init() {
|
||||
this._location = DOM.getLocation();
|
||||
this._history = DOM.getHistory();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
get location(): Location { return this._location; }
|
||||
|
||||
getBaseHrefFromDOM(): string { return DOM.getBaseHref(); }
|
||||
|
||||
onPopState(fn: UrlChangeListener): void {
|
||||
DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false);
|
||||
}
|
||||
|
||||
onHashChange(fn: UrlChangeListener): void {
|
||||
DOM.getGlobalEventTarget('window').addEventListener('hashchange', fn, false);
|
||||
}
|
||||
|
||||
get pathname(): string { return this._location.pathname; }
|
||||
get search(): string { return this._location.search; }
|
||||
get hash(): string { return this._location.hash; }
|
||||
set pathname(newPath: string) { this._location.pathname = newPath; }
|
||||
|
||||
pushState(state: any, title: string, url: string): void {
|
||||
this._history.pushState(state, title, url);
|
||||
}
|
||||
|
||||
replaceState(state: any, title: string, url: string): void {
|
||||
this._history.replaceState(state, title, url);
|
||||
}
|
||||
|
||||
forward(): void { this._history.forward(); }
|
||||
|
||||
back(): void { this._history.back(); }
|
||||
}
|
|
@ -5,7 +5,7 @@ import {
|
|||
APP_BASE_HREF,
|
||||
normalizeQueryParams
|
||||
} from './location_strategy';
|
||||
import {EventListener} from 'angular2/src/facade/browser';
|
||||
import {UrlChangeListener} from './platform_location';
|
||||
import {isPresent} from 'angular2/src/facade/lang';
|
||||
import {PlatformLocation} from './platform_location';
|
||||
|
||||
|
@ -58,7 +58,7 @@ export class HashLocationStrategy extends LocationStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
onPopState(fn: EventListener): void {
|
||||
onPopState(fn: UrlChangeListener): void {
|
||||
this._platformLocation.onPopState(fn);
|
||||
this._platformLocation.onHashChange(fn);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {OpaqueToken} from 'angular2/core';
|
||||
import {UrlChangeListener} from './platform_location';
|
||||
|
||||
/**
|
||||
* `LocationStrategy` is responsible for representing and reading route state
|
||||
|
@ -24,7 +25,7 @@ export abstract class LocationStrategy {
|
|||
abstract replaceState(state: any, title: string, url: string, queryParams: string): void;
|
||||
abstract forward(): void;
|
||||
abstract back(): void;
|
||||
abstract onPopState(fn: (_: any) => any): void;
|
||||
abstract onPopState(fn: UrlChangeListener): void;
|
||||
abstract getBaseHref(): string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import {Injectable, Inject, Optional} from 'angular2/core';
|
||||
import {EventListener, History, Location} from 'angular2/src/facade/browser';
|
||||
import {isBlank} from 'angular2/src/facade/lang';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {
|
||||
|
@ -8,7 +7,7 @@ import {
|
|||
normalizeQueryParams,
|
||||
joinWithSlash
|
||||
} from './location_strategy';
|
||||
import {PlatformLocation} from './platform_location';
|
||||
import {PlatformLocation, UrlChangeListener} from './platform_location';
|
||||
|
||||
/**
|
||||
* `PathLocationStrategy` is a {@link LocationStrategy} used to configure the
|
||||
|
@ -75,7 +74,7 @@ export class PathLocationStrategy extends LocationStrategy {
|
|||
this._baseHref = href;
|
||||
}
|
||||
|
||||
onPopState(fn: EventListener): void {
|
||||
onPopState(fn: UrlChangeListener): void {
|
||||
this._platformLocation.onPopState(fn);
|
||||
this._platformLocation.onHashChange(fn);
|
||||
}
|
||||
|
|
|
@ -1,50 +1,48 @@
|
|||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
import {Injectable} from 'angular2/core';
|
||||
import {EventListener, History, Location} from 'angular2/src/facade/browser';
|
||||
|
||||
/**
|
||||
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
|
||||
* This class should not be used directly by an application developer. Instead, use
|
||||
* {@link Location}.
|
||||
*
|
||||
* `PlatformLocation` encapsulates all calls to DOM apis, which allows the Router to be platform
|
||||
* agnostic.
|
||||
* This means that we can have different implementation of `PlatformLocation` for the different
|
||||
* platforms
|
||||
* that angular supports. For example, the default `PlatformLocation` is {@link
|
||||
* BrowserPlatformLocation},
|
||||
* however when you run your app in a WebWorker you use {@link WebWorkerPlatformLocation}.
|
||||
*
|
||||
* The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}
|
||||
* when
|
||||
* they need to interact with the DOM apis like pushState, popState, etc...
|
||||
*
|
||||
* {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly
|
||||
* by
|
||||
* the {@link Router} in order to navigate between routes. Since all interactions between {@link
|
||||
* Router} /
|
||||
* {@link Location} / {@link LocationStrategy} and DOM apis flow through the `PlatformLocation`
|
||||
* class
|
||||
* they are all platform independent.
|
||||
*/
|
||||
@Injectable()
|
||||
export class PlatformLocation {
|
||||
private _location: Location;
|
||||
private _history: History;
|
||||
export abstract class PlatformLocation {
|
||||
abstract getBaseHrefFromDOM(): string;
|
||||
abstract onPopState(fn: UrlChangeListener): void;
|
||||
abstract onHashChange(fn: UrlChangeListener): void;
|
||||
|
||||
constructor() { this._init(); }
|
||||
pathname: string;
|
||||
search: string;
|
||||
hash: string;
|
||||
|
||||
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
|
||||
/** @internal */
|
||||
_init() {
|
||||
this._location = DOM.getLocation();
|
||||
this._history = DOM.getHistory();
|
||||
}
|
||||
abstract replaceState(state: any, title: string, url: string): void;
|
||||
|
||||
getBaseHrefFromDOM(): string { return DOM.getBaseHref(); }
|
||||
abstract pushState(state: any, title: string, url: string): void;
|
||||
|
||||
onPopState(fn: EventListener): void {
|
||||
DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false);
|
||||
}
|
||||
abstract forward(): void;
|
||||
|
||||
onHashChange(fn: EventListener): void {
|
||||
DOM.getGlobalEventTarget('window').addEventListener('hashchange', fn, false);
|
||||
}
|
||||
|
||||
get pathname(): string { return this._location.pathname; }
|
||||
get search(): string { return this._location.search; }
|
||||
get hash(): string { return this._location.hash; }
|
||||
set pathname(newPath: string) { this._location.pathname = newPath; }
|
||||
|
||||
pushState(state: any, title: string, url: string): void {
|
||||
this._history.pushState(state, title, url);
|
||||
}
|
||||
|
||||
replaceState(state: any, title: string, url: string): void {
|
||||
this._history.replaceState(state, title, url);
|
||||
}
|
||||
|
||||
forward(): void { this._history.forward(); }
|
||||
|
||||
back(): void { this._history.back(); }
|
||||
abstract back(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A serializable version of the event from onPopState or onHashChange
|
||||
*/
|
||||
export interface UrlChangeEvent { type: string; }
|
||||
|
||||
export interface UrlChangeListener { (e: UrlChangeEvent): any; }
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// import {ROUTER_PROVIDERS_COMMON} from './router_providers_common';
|
||||
import {ROUTER_PROVIDERS_COMMON} from 'angular2/router';
|
||||
import {Provider} from 'angular2/core';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {BrowserPlatformLocation} from './browser_platform_location';
|
||||
import {PlatformLocation} from './platform_location';
|
||||
|
||||
/**
|
||||
* A list of {@link Provider}s. To use the router, you must add this to your application.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/iRUP8B5OUbxCWQ3AcIDm))
|
||||
*
|
||||
* ```
|
||||
* import {Component} from 'angular2/core';
|
||||
* import {
|
||||
* ROUTER_DIRECTIVES,
|
||||
* ROUTER_PROVIDERS,
|
||||
* RouteConfig
|
||||
* } from 'angular2/router';
|
||||
*
|
||||
* @Component({directives: [ROUTER_DIRECTIVES]})
|
||||
* @RouteConfig([
|
||||
* {...},
|
||||
* ])
|
||||
* class AppCmp {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* bootstrap(AppCmp, [ROUTER_PROVIDERS]);
|
||||
* ```
|
||||
*/
|
||||
export const ROUTER_PROVIDERS: any[] = CONST_EXPR([
|
||||
ROUTER_PROVIDERS_COMMON,
|
||||
CONST_EXPR(new Provider(PlatformLocation, {useClass: BrowserPlatformLocation})),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Use {@link ROUTER_PROVIDERS} instead.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const ROUTER_BINDINGS = ROUTER_PROVIDERS;
|
|
@ -0,0 +1,40 @@
|
|||
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
||||
import {PathLocationStrategy} from 'angular2/src/router/path_location_strategy';
|
||||
import {Router, RootRouter} from 'angular2/src/router/router';
|
||||
import {RouteRegistry, ROUTER_PRIMARY_COMPONENT} from 'angular2/src/router/route_registry';
|
||||
import {Location} from 'angular2/src/router/location';
|
||||
import {CONST_EXPR, Type} from 'angular2/src/facade/lang';
|
||||
import {ApplicationRef, OpaqueToken, Provider} from 'angular2/core';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
|
||||
/**
|
||||
* The Platform agnostic ROUTER PROVIDERS
|
||||
*/
|
||||
export const ROUTER_PROVIDERS_COMMON: any[] = CONST_EXPR([
|
||||
RouteRegistry,
|
||||
CONST_EXPR(new Provider(LocationStrategy, {useClass: PathLocationStrategy})),
|
||||
Location,
|
||||
CONST_EXPR(new Provider(
|
||||
Router,
|
||||
{
|
||||
useFactory: routerFactory,
|
||||
deps: CONST_EXPR([RouteRegistry, Location, ROUTER_PRIMARY_COMPONENT, ApplicationRef])
|
||||
})),
|
||||
CONST_EXPR(new Provider(
|
||||
ROUTER_PRIMARY_COMPONENT,
|
||||
{useFactory: routerPrimaryComponentFactory, deps: CONST_EXPR([ApplicationRef])}))
|
||||
]);
|
||||
|
||||
function routerFactory(registry: RouteRegistry, location: Location, primaryComponent: Type,
|
||||
appRef: ApplicationRef): RootRouter {
|
||||
var rootRouter = new RootRouter(registry, location, primaryComponent);
|
||||
appRef.registerDisposeListener(() => rootRouter.dispose());
|
||||
return rootRouter;
|
||||
}
|
||||
|
||||
function routerPrimaryComponentFactory(app: ApplicationRef): Type {
|
||||
if (app.componentTypes.length == 0) {
|
||||
throw new BaseException("Bootstrap at least one component before injecting Router.");
|
||||
}
|
||||
return app.componentTypes[0];
|
||||
}
|
|
@ -4,4 +4,5 @@
|
|||
*/
|
||||
export const RENDERER_CHANNEL = "ng-Renderer";
|
||||
export const XHR_CHANNEL = "ng-XHR";
|
||||
export const EVENT_CHANNEL = "ng-events";
|
||||
export const EVENT_CHANNEL = "ng-Events";
|
||||
export const ROUTER_CHANNEL = "ng-Router";
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// This file contains interface versions of browser types that can be serialized to Plain Old
|
||||
// JavaScript Objects
|
||||
export class LocationType {
|
||||
constructor(public href: string, public protocol: string, public host: string,
|
||||
public hostname: string, public port: string, public pathname: string,
|
||||
public search: string, public hash: string, public origin: string) {}
|
||||
}
|
|
@ -6,6 +6,7 @@ import {RenderComponentType} from "angular2/src/core/render/api";
|
|||
import {Injectable} from "angular2/src/core/di";
|
||||
import {RenderStore} from 'angular2/src/web_workers/shared/render_store';
|
||||
import {ViewEncapsulation, VIEW_ENCAPSULATION_VALUES} from 'angular2/src/core/metadata/view';
|
||||
import {LocationType} from './serialized_types';
|
||||
|
||||
// PRIMITIVE is any type that does not need to be serialized (string, number, boolean)
|
||||
// We set it to String so that it is considered a Type.
|
||||
|
@ -31,6 +32,8 @@ export class Serializer {
|
|||
return this._serializeRenderComponentType(obj);
|
||||
} else if (type === ViewEncapsulation) {
|
||||
return serializeEnum(obj);
|
||||
} else if (type === LocationType) {
|
||||
return this._serializeLocation(obj);
|
||||
} else {
|
||||
throw new BaseException("No serializer for " + type.toString());
|
||||
}
|
||||
|
@ -55,6 +58,8 @@ export class Serializer {
|
|||
return this._deserializeRenderComponentType(map);
|
||||
} else if (type === ViewEncapsulation) {
|
||||
return VIEW_ENCAPSULATION_VALUES[map];
|
||||
} else if (type === LocationType) {
|
||||
return this._deserializeLocation(map);
|
||||
} else {
|
||||
throw new BaseException("No deserializer for " + type.toString());
|
||||
}
|
||||
|
@ -90,6 +95,25 @@ export class Serializer {
|
|||
}
|
||||
}
|
||||
|
||||
private _serializeLocation(loc: LocationType): Object {
|
||||
return {
|
||||
'href': loc.href,
|
||||
'protocol': loc.protocol,
|
||||
'host': loc.host,
|
||||
'hostname': loc.hostname,
|
||||
'port': loc.port,
|
||||
'pathname': loc.pathname,
|
||||
'search': loc.search,
|
||||
'hash': loc.hash,
|
||||
'origin': loc.origin
|
||||
};
|
||||
}
|
||||
|
||||
private _deserializeLocation(loc: {[key: string]: any}): LocationType {
|
||||
return new LocationType(loc['href'], loc['protocol'], loc['host'], loc['hostname'], loc['port'],
|
||||
loc['pathname'], loc['search'], loc['hash'], loc['origin']);
|
||||
}
|
||||
|
||||
private _serializeRenderComponentType(obj: RenderComponentType): Object {
|
||||
return {
|
||||
'id': obj.id,
|
||||
|
@ -106,4 +130,4 @@ export class Serializer {
|
|||
}
|
||||
|
||||
|
||||
export class RenderStoreObject {}
|
||||
export class RenderStoreObject {}
|
||||
|
|
|
@ -50,11 +50,13 @@ export class ServiceMessageBroker_ extends ServiceMessageBroker {
|
|||
ObservableWrapper.subscribe(source, (message) => this._handleMessage(message));
|
||||
}
|
||||
|
||||
registerMethod(methodName: string, signature: Type[], method: Function, returnType?: Type): void {
|
||||
registerMethod(methodName: string, signature: Type[], method: (..._: any[]) => Promise<any>| void,
|
||||
returnType?: Type): void {
|
||||
this._methods.set(methodName, (message: ReceivedMessage) => {
|
||||
var serializedArgs = message.args;
|
||||
var deserializedArgs: any[] = ListWrapper.createFixedSize(signature.length);
|
||||
for (var i = 0; i < signature.length; i++) {
|
||||
let numArgs = signature === null ? 0 : signature.length;
|
||||
var deserializedArgs: any[] = ListWrapper.createFixedSize(numArgs);
|
||||
for (var i = 0; i < numArgs; i++) {
|
||||
var serializedArg = serializedArgs[i];
|
||||
deserializedArgs[i] = this._serializer.deserialize(serializedArg, signature[i]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {ROUTER_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
|
||||
import {
|
||||
ServiceMessageBrokerFactory,
|
||||
ServiceMessageBroker
|
||||
} from 'angular2/src/web_workers/shared/service_message_broker';
|
||||
import {PRIMITIVE, Serializer} from 'angular2/src/web_workers/shared/serializer';
|
||||
import {bind} from './bind';
|
||||
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
|
||||
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
|
||||
import {Promise, EventEmitter, ObservableWrapper, PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {UrlChangeListener} from 'angular2/src/router/platform_location';
|
||||
|
||||
@Injectable()
|
||||
export class MessageBasedPlatformLocation {
|
||||
private _channelSink: EventEmitter<Object>;
|
||||
private _broker: ServiceMessageBroker;
|
||||
|
||||
constructor(private _brokerFactory: ServiceMessageBrokerFactory,
|
||||
private _platformLocation: BrowserPlatformLocation, bus: MessageBus,
|
||||
private _serializer: Serializer) {
|
||||
this._platformLocation.onPopState(<UrlChangeListener>bind(this._sendUrlChangeEvent, this));
|
||||
this._platformLocation.onHashChange(<UrlChangeListener>bind(this._sendUrlChangeEvent, this));
|
||||
this._broker = this._brokerFactory.createMessageBroker(ROUTER_CHANNEL);
|
||||
this._channelSink = bus.to(ROUTER_CHANNEL);
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this._broker.registerMethod("getLocation", null, bind(this._getLocation, this), LocationType);
|
||||
this._broker.registerMethod("setPathname", [PRIMITIVE], bind(this._setPathname, this));
|
||||
this._broker.registerMethod("pushState", [PRIMITIVE, PRIMITIVE, PRIMITIVE],
|
||||
bind(this._platformLocation.pushState, this._platformLocation));
|
||||
this._broker.registerMethod("replaceState", [PRIMITIVE, PRIMITIVE, PRIMITIVE],
|
||||
bind(this._platformLocation.replaceState, this._platformLocation));
|
||||
this._broker.registerMethod("forward", null,
|
||||
bind(this._platformLocation.forward, this._platformLocation));
|
||||
this._broker.registerMethod("back", null,
|
||||
bind(this._platformLocation.back, this._platformLocation));
|
||||
}
|
||||
|
||||
private _getLocation(): Promise<Location> {
|
||||
return PromiseWrapper.resolve(this._platformLocation.location);
|
||||
}
|
||||
|
||||
|
||||
private _sendUrlChangeEvent(e: Event): void {
|
||||
let loc = this._serializer.serialize(this._platformLocation.location, LocationType);
|
||||
let serializedEvent = {'type': e.type};
|
||||
ObservableWrapper.callEmit(this._channelSink, {'event': serializedEvent, 'location': loc});
|
||||
}
|
||||
|
||||
private _setPathname(pathname: string): void { this._platformLocation.pathname = pathname; }
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import {MessageBasedPlatformLocation} from './platform_location';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {BrowserPlatformLocation} from 'angular2/src/router/browser_platform_location';
|
||||
import {APP_INITIALIZER, Provider, Injector, NgZone} from 'angular2/core';
|
||||
|
||||
export const WORKER_RENDER_ROUTER = CONST_EXPR([
|
||||
MessageBasedPlatformLocation,
|
||||
BrowserPlatformLocation,
|
||||
CONST_EXPR(
|
||||
new Provider(APP_INITIALIZER,
|
||||
{useFactory: initRouterListeners, multi: true, deps: CONST_EXPR([Injector])}))
|
||||
]);
|
||||
|
||||
function initRouterListeners(injector: Injector): () => void {
|
||||
return () => {
|
||||
let zone = injector.get(NgZone);
|
||||
|
||||
zone.run(() => injector.get(MessageBasedPlatformLocation).start());
|
||||
};
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {
|
||||
PlatformLocation,
|
||||
UrlChangeEvent,
|
||||
UrlChangeListener
|
||||
} from 'angular2/src/router/platform_location';
|
||||
import {
|
||||
FnArg,
|
||||
UiArguments,
|
||||
ClientMessageBroker,
|
||||
ClientMessageBrokerFactory
|
||||
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
import {ROUTER_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
|
||||
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
|
||||
import {Promise, PromiseWrapper, EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
||||
import {PRIMITIVE, Serializer} from 'angular2/src/web_workers/shared/serializer';
|
||||
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
|
||||
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
||||
import {StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {deserializeGenericEvent} from './event_deserializer';
|
||||
|
||||
@Injectable()
|
||||
export class WebWorkerPlatformLocation extends PlatformLocation {
|
||||
private _broker: ClientMessageBroker;
|
||||
private _popStateListeners: Array<Function> = [];
|
||||
private _hashChangeListeners: Array<Function> = [];
|
||||
private _location: LocationType = null;
|
||||
private _channelSource: EventEmitter<Object>;
|
||||
|
||||
constructor(brokerFactory: ClientMessageBrokerFactory, bus: MessageBus,
|
||||
private _serializer: Serializer) {
|
||||
super();
|
||||
this._broker = brokerFactory.createMessageBroker(ROUTER_CHANNEL);
|
||||
|
||||
this._channelSource = bus.from(ROUTER_CHANNEL);
|
||||
ObservableWrapper.subscribe(this._channelSource, (msg: {[key: string]: any}) => {
|
||||
var listeners: Array<Function> = null;
|
||||
if (StringMapWrapper.contains(msg, 'event')) {
|
||||
let type: string = msg['event']['type'];
|
||||
if (StringWrapper.equals(type, "popstate")) {
|
||||
listeners = this._popStateListeners;
|
||||
} else if (StringWrapper.equals(type, "hashchange")) {
|
||||
listeners = this._hashChangeListeners;
|
||||
}
|
||||
|
||||
if (listeners !== null) {
|
||||
let e = deserializeGenericEvent(msg['event']);
|
||||
// There was a popState or hashChange event, so the location object thas been updated
|
||||
this._location = this._serializer.deserialize(msg['location'], LocationType);
|
||||
listeners.forEach((fn: Function) => fn(e));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal **/
|
||||
init(): Promise<boolean> {
|
||||
var args: UiArguments = new UiArguments("getLocation");
|
||||
|
||||
var locationPromise: Promise<LocationType> = this._broker.runOnService(args, LocationType);
|
||||
return PromiseWrapper.then(locationPromise, (val: LocationType): boolean => {
|
||||
this._location = val;
|
||||
return true;
|
||||
}, (err): boolean => { throw new BaseException(err); });
|
||||
}
|
||||
|
||||
getBaseHrefFromDOM(): string {
|
||||
throw new BaseException(
|
||||
"Attempt to get base href from DOM from WebWorker. You must either provide a value for the APP_BASE_HREF token through DI or use the hash location strategy.");
|
||||
}
|
||||
|
||||
onPopState(fn: UrlChangeListener): void { this._popStateListeners.push(fn); }
|
||||
|
||||
onHashChange(fn: UrlChangeListener): void { this._hashChangeListeners.push(fn); }
|
||||
|
||||
get pathname(): string {
|
||||
if (this._location === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._location.pathname;
|
||||
}
|
||||
|
||||
get search(): string {
|
||||
if (this._location === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._location.search;
|
||||
}
|
||||
|
||||
get hash(): string {
|
||||
if (this._location === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._location.hash;
|
||||
}
|
||||
|
||||
set pathname(newPath: string) {
|
||||
if (this._location === null) {
|
||||
throw new BaseException("Attempt to set pathname before value is obtained from UI");
|
||||
}
|
||||
|
||||
this._location.pathname = newPath;
|
||||
|
||||
var fnArgs = [new FnArg(newPath, PRIMITIVE)];
|
||||
var args = new UiArguments("setPathname", fnArgs);
|
||||
this._broker.runOnService(args, null);
|
||||
}
|
||||
|
||||
pushState(state: any, title: string, url: string): void {
|
||||
var fnArgs =
|
||||
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
|
||||
var args = new UiArguments("pushState", fnArgs);
|
||||
this._broker.runOnService(args, null);
|
||||
}
|
||||
|
||||
replaceState(state: any, title: string, url: string): void {
|
||||
var fnArgs =
|
||||
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
|
||||
var args = new UiArguments("replaceState", fnArgs);
|
||||
this._broker.runOnService(args, null);
|
||||
}
|
||||
|
||||
forward(): void {
|
||||
var args = new UiArguments("forward");
|
||||
this._broker.runOnService(args, null);
|
||||
}
|
||||
|
||||
back(): void {
|
||||
var args = new UiArguments("back");
|
||||
this._broker.runOnService(args, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import {ApplicationRef, Provider, NgZone, APP_INITIALIZER} from 'angular2/core';
|
||||
import {PlatformLocation} from 'angular2/src/router/platform_location';
|
||||
import {WebWorkerPlatformLocation} from './platform_location';
|
||||
import {ROUTER_PROVIDERS_COMMON} from 'angular2/src/router/router_providers_common';
|
||||
import {Promise} from 'angular2/src/facade/async';
|
||||
|
||||
export var WORKER_APP_ROUTER = [
|
||||
ROUTER_PROVIDERS_COMMON,
|
||||
new Provider(PlatformLocation, {useClass: WebWorkerPlatformLocation}),
|
||||
new Provider(APP_INITIALIZER,
|
||||
{
|
||||
useFactory: (platformLocation: WebWorkerPlatformLocation, zone: NgZone) => () =>
|
||||
initRouter(platformLocation, zone),
|
||||
multi: true,
|
||||
deps: [PlatformLocation, NgZone]
|
||||
})
|
||||
];
|
||||
|
||||
function initRouter(platformLocation: WebWorkerPlatformLocation, zone: NgZone): Promise<boolean> {
|
||||
return zone.run(() => { return platformLocation.init(); });
|
||||
}
|
|
@ -4,7 +4,8 @@ import 'package:angular2/src/platform/server/html_adapter.dart';
|
|||
import "package:angular2/testing_internal.dart";
|
||||
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
|
||||
import "package:angular2/src/core/reflection/reflection.dart";
|
||||
import "package:angular2/src/platform/worker_app_common.dart" show WORKER_APP_APPLICATION_COMMON;
|
||||
import "package:angular2/src/platform/worker_app_common.dart"
|
||||
show WORKER_APP_APPLICATION_COMMON;
|
||||
import "package:angular2/platform/worker_app.dart" show WORKER_APP_PLATFORM;
|
||||
import "package:angular2/core.dart";
|
||||
import "../shared/web_worker_test_util.dart";
|
||||
|
@ -19,7 +20,7 @@ main() {
|
|||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
var buses = createPairedMessageBuses();
|
||||
platform([WORKER_APP_PLATFORM])
|
||||
.application([WORKER_APP_APPLICATION_COMMON]);
|
||||
.application([WORKER_APP_APPLICATION_COMMON]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -217,7 +217,9 @@ SpySocketWrapper createSocket({Function messageHandler}) {
|
|||
var socket = new SpyWebSocket();
|
||||
if (messageHandler != null) {
|
||||
socket.spy("add").andCallFake(messageHandler);
|
||||
socket.spy("addStream").andCallFake((Stream stream) => stream.listen(messageHandler));
|
||||
socket
|
||||
.spy("addStream")
|
||||
.andCallFake((Stream stream) => stream.listen(messageHandler));
|
||||
}
|
||||
|
||||
var controller = new StreamController<String>.broadcast();
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||
import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
import {Type, isPresent} from 'angular2/src/facade/lang';
|
||||
import {SpyMessageBroker} from '../worker/spies';
|
||||
import {expect} from 'angular2/testing_internal';
|
||||
import {
|
||||
MessageBusSink,
|
||||
MessageBusSource,
|
||||
MessageBus
|
||||
} from 'angular2/src/web_workers/shared/message_bus';
|
||||
import {
|
||||
ClientMessageBroker,
|
||||
ClientMessageBrokerFactory_
|
||||
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
import {MockEventEmitter} from './mock_event_emitter';
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||
|
@ -25,6 +34,37 @@ export function createPairedMessageBuses(): PairedMessageBuses {
|
|||
new MockMessageBus(workerMessageBusSink, workerMessageBusSource));
|
||||
}
|
||||
|
||||
/**
|
||||
* Spies on the given {@link SpyMessageBroker} and expects a call with the given methodName
|
||||
* andvalues.
|
||||
* If a handler is provided it will be called to handle the request.
|
||||
* Only intended to be called on a given broker instance once.
|
||||
*/
|
||||
export function expectBrokerCall(broker: SpyMessageBroker, methodName: string, vals?: Array<any>,
|
||||
handler?: (..._: any[]) => Promise<any>| void): void {
|
||||
broker.spy("runOnService")
|
||||
.andCallFake((args: UiArguments, returnType: Type) => {
|
||||
expect(args.method).toEqual(methodName);
|
||||
if (isPresent(vals)) {
|
||||
expect(args.args.length).toEqual(vals.length);
|
||||
ListWrapper.forEachWithIndex(vals, (v, i) => {expect(v).toEqual(args.args[i].value)});
|
||||
}
|
||||
var promise = null;
|
||||
if (isPresent(handler)) {
|
||||
let givenValues = args.args.map((arg) => {arg.value});
|
||||
if (givenValues.length > 0) {
|
||||
promise = handler(givenValues);
|
||||
} else {
|
||||
promise = handler();
|
||||
}
|
||||
}
|
||||
if (promise == null) {
|
||||
promise = PromiseWrapper.wrap(() => {});
|
||||
}
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
export class PairedMessageBuses {
|
||||
constructor(public ui: MessageBus, public worker: MessageBus) {}
|
||||
}
|
||||
|
@ -85,3 +125,8 @@ export class MockMessageBus extends MessageBus {
|
|||
|
||||
attachToZone(zone: NgZone) {}
|
||||
}
|
||||
|
||||
export class MockMessageBrokerFactory extends ClientMessageBrokerFactory_ {
|
||||
constructor(private _messageBroker: ClientMessageBroker) { super(null, null); }
|
||||
createMessageBroker(channel: string, runInZone = true) { return this._messageBroker; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
import {
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
beforeEachProviders
|
||||
} from 'angular2/testing_internal';
|
||||
import {SpyMessageBroker} from './spies';
|
||||
import {WebWorkerPlatformLocation} from 'angular2/src/web_workers/worker/platform_location';
|
||||
import {LocationType} from 'angular2/src/web_workers/shared/serialized_types';
|
||||
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
|
||||
import {
|
||||
createPairedMessageBuses,
|
||||
MockMessageBrokerFactory,
|
||||
expectBrokerCall
|
||||
} from '../shared/web_worker_test_util';
|
||||
import {UiArguments} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
import {Type} from 'angular2/src/facade/lang';
|
||||
import {PromiseWrapper} from "angular2/src/facade/async";
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
export function main() {
|
||||
describe("WebWorkerPlatformLocation", () => {
|
||||
var uiBus: MessageBus = null;
|
||||
var workerBus: MessageBus = null;
|
||||
var broker: any = null;
|
||||
var TEST_LOCATION =
|
||||
new LocationType("http://www.example.com", "http", "example.com", "example.com", "80", "/",
|
||||
"", "", "http://www.example.com");
|
||||
|
||||
|
||||
function createWebWorkerPlatformLocation(loc: LocationType): WebWorkerPlatformLocation {
|
||||
broker.spy("runOnService")
|
||||
.andCallFake((args: UiArguments, returnType: Type) => {
|
||||
if (args.method === 'getLocation') {
|
||||
return PromiseWrapper.resolve(loc);
|
||||
}
|
||||
});
|
||||
var factory = new MockMessageBrokerFactory(broker);
|
||||
return new WebWorkerPlatformLocation(factory, workerBus, null);
|
||||
}
|
||||
|
||||
function testPushOrReplaceState(pushState: boolean) {
|
||||
let platformLocation = createWebWorkerPlatformLocation(null);
|
||||
const TITLE = "foo";
|
||||
const URL = "http://www.example.com/foo";
|
||||
expectBrokerCall(broker, pushState ? "pushState" : "replaceState", [null, TITLE, URL]);
|
||||
if (pushState) {
|
||||
platformLocation.pushState(null, TITLE, URL);
|
||||
} else {
|
||||
platformLocation.replaceState(null, TITLE, URL);
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
var buses = createPairedMessageBuses();
|
||||
uiBus = buses.ui;
|
||||
workerBus = buses.worker;
|
||||
workerBus.initChannel("ng-Router");
|
||||
uiBus.initChannel("ng-Router");
|
||||
broker = new SpyMessageBroker();
|
||||
});
|
||||
|
||||
it("should throw if getBaseHrefFromDOM is called", () => {
|
||||
let platformLocation = createWebWorkerPlatformLocation(null);
|
||||
expect(() => platformLocation.getBaseHrefFromDOM()).toThrowError();
|
||||
});
|
||||
|
||||
it("should get location on init", () => {
|
||||
let platformLocation = createWebWorkerPlatformLocation(null);
|
||||
expectBrokerCall(broker, "getLocation");
|
||||
platformLocation.init();
|
||||
});
|
||||
|
||||
it("should throw if set pathname is called before init finishes", () => {
|
||||
let platformLocation = createWebWorkerPlatformLocation(null);
|
||||
platformLocation.init();
|
||||
expect(() => platformLocation.pathname = "TEST").toThrowError();
|
||||
});
|
||||
|
||||
it("should send pathname to render thread", inject([AsyncTestCompleter], (async) => {
|
||||
let platformLocation = createWebWorkerPlatformLocation(TEST_LOCATION);
|
||||
platformLocation.init().then((_) => {
|
||||
let PATHNAME = "/test";
|
||||
expectBrokerCall(broker, "setPathname", [PATHNAME]);
|
||||
platformLocation.pathname = PATHNAME;
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it("should send pushState to render thread", () => { testPushOrReplaceState(true); });
|
||||
|
||||
it("should send replaceState to render thread", () => { testPushOrReplaceState(false); });
|
||||
});
|
||||
}
|
|
@ -8,15 +8,9 @@ import {
|
|||
beforeEachProviders
|
||||
} from 'angular2/testing_internal';
|
||||
import {SpyMessageBroker} from './spies';
|
||||
import {Type} from 'angular2/src/facade/lang';
|
||||
import {
|
||||
ClientMessageBroker,
|
||||
UiArguments,
|
||||
ClientMessageBrokerFactory,
|
||||
ClientMessageBrokerFactory_
|
||||
} from 'angular2/src/web_workers/shared/client_message_broker';
|
||||
import {WebWorkerXHRImpl} from "angular2/src/web_workers/worker/xhr_impl";
|
||||
import {PromiseWrapper} from "angular2/src/facade/async";
|
||||
import {MockMessageBrokerFactory, expectBrokerCall} from "../shared/web_worker_test_util";
|
||||
|
||||
export function main() {
|
||||
describe("WebWorkerXHRImpl", () => {
|
||||
|
@ -25,16 +19,10 @@ export function main() {
|
|||
const URL = "http://www.example.com/test";
|
||||
const RESPONSE = "Example response text";
|
||||
|
||||
var messageBroker: any = new SpyMessageBroker();
|
||||
messageBroker.spy("runOnService")
|
||||
.andCallFake((args: UiArguments, returnType: Type) => {
|
||||
expect(args.method).toEqual("get");
|
||||
expect(args.args.length).toEqual(1);
|
||||
expect(args.args[0].value).toEqual(URL);
|
||||
return PromiseWrapper.wrap(() => { return RESPONSE; });
|
||||
});
|
||||
|
||||
var xhrImpl = new WebWorkerXHRImpl(new MockMessageBrokerFactory(messageBroker));
|
||||
var messageBroker = new SpyMessageBroker();
|
||||
expectBrokerCall(messageBroker, "get", [URL],
|
||||
(_) => { return PromiseWrapper.wrap(() => { return RESPONSE; }); });
|
||||
var xhrImpl = new WebWorkerXHRImpl(new MockMessageBrokerFactory(<any>messageBroker));
|
||||
xhrImpl.get(URL).then((response) => {
|
||||
expect(response).toEqual(RESPONSE);
|
||||
async.done();
|
||||
|
@ -42,8 +30,3 @@ export function main() {
|
|||
}));
|
||||
});
|
||||
}
|
||||
|
||||
class MockMessageBrokerFactory extends ClientMessageBrokerFactory_ {
|
||||
constructor(private _messageBroker: ClientMessageBroker) { super(null, null); }
|
||||
createMessageBroker(channel: string, runInZone = true) { return this._messageBroker; }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
library playground.e2e_test.web_workers.router.router_spec;
|
||||
|
||||
main() {}
|
|
@ -0,0 +1,72 @@
|
|||
import {verifyNoBrowserErrors} from 'angular2/src/testing/e2e_util';
|
||||
|
||||
describe("WebWorker Router", () => {
|
||||
afterEach(() => {
|
||||
verifyNoBrowserErrors();
|
||||
browser.ignoreSynchronization = false;
|
||||
});
|
||||
|
||||
let contentSelector = "app main h1";
|
||||
let navSelector = "app nav ul";
|
||||
var baseUrl = "playground/src/web_workers/router/index.html";
|
||||
|
||||
it("should route on click", () => {
|
||||
// This test can't wait for Angular 2 as Testability is not available when using WebWorker
|
||||
browser.ignoreSynchronization = true;
|
||||
browser.get(baseUrl);
|
||||
|
||||
waitForElement(contentSelector);
|
||||
var content = element(by.css(contentSelector));
|
||||
expect(content.getText()).toEqual("Start");
|
||||
|
||||
let aboutBtn = element(by.css(navSelector + " .about"));
|
||||
aboutBtn.click();
|
||||
waitForUrl(/\/about/);
|
||||
waitForElement(contentSelector);
|
||||
content = element(by.css(contentSelector));
|
||||
waitForElementText(content, "About");
|
||||
expect(content.getText()).toEqual("About");
|
||||
expect(browser.getCurrentUrl()).toMatch(/\/about/);
|
||||
|
||||
let contactBtn = element(by.css(navSelector + " .contact"));
|
||||
contactBtn.click();
|
||||
waitForUrl(/\/contact/);
|
||||
waitForElement(contentSelector);
|
||||
content = element(by.css(contentSelector));
|
||||
waitForElementText(content, "Contact");
|
||||
expect(content.getText()).toEqual("Contact");
|
||||
expect(browser.getCurrentUrl()).toMatch(/\/contact/);
|
||||
});
|
||||
|
||||
it("should load the correct route from the URL", () => {
|
||||
// This test can't wait for Angular 2 as Testability is not available when using WebWorker
|
||||
browser.ignoreSynchronization = true;
|
||||
browser.get(baseUrl + "#/about");
|
||||
|
||||
waitForElement(contentSelector);
|
||||
let content = element(by.css(contentSelector));
|
||||
waitForElementText(content, "About");
|
||||
expect(content.getText()).toEqual("About");
|
||||
});
|
||||
|
||||
function waitForElement(selector: string): void {
|
||||
browser.wait(protractor.until.elementLocated(by.css(selector)), 15000);
|
||||
}
|
||||
|
||||
function waitForElementText(elem: protractor.ElementFinder, expected: string): void {
|
||||
browser.wait(() => {
|
||||
let deferred = protractor.promise.defer();
|
||||
elem.getText().then((text) => { return deferred.fulfill(text === expected); });
|
||||
return deferred.promise;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function waitForUrl(regex): void {
|
||||
browser.wait(() => {
|
||||
let deferred = protractor.promise.defer();
|
||||
browser.getCurrentUrl().then(
|
||||
(url) => { return deferred.fulfill(url.match(regex) !== null); });
|
||||
return deferred.promise;
|
||||
}, 5000);
|
||||
}
|
||||
});
|
|
@ -50,6 +50,8 @@ transformers:
|
|||
- web/src/web_workers/todo/background_index.dart
|
||||
- web/src/web_workers/todo/index.dart
|
||||
- web/src/web_workers/todo/server_index.dart
|
||||
- web/src/web_workers/router/index.dart
|
||||
- web/src/web_workers/router/background_index.dart
|
||||
- web/src/zippy_component/index.dart
|
||||
|
||||
- $dart2js:
|
||||
|
|
|
@ -9,7 +9,8 @@ import "package:angular2/src/core/reflection/reflection.dart";
|
|||
|
||||
main(List<String> args, SendPort replyTo) {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
platform([WORKER_APP_PLATFORM, new Provider(RENDER_SEND_PORT, useValue: replyTo)])
|
||||
.application([WORKER_APP_APPLICATION])
|
||||
.bootstrap(ImageDemo);
|
||||
platform([
|
||||
WORKER_APP_PLATFORM,
|
||||
new Provider(RENDER_SEND_PORT, useValue: replyTo)
|
||||
]).application([WORKER_APP_APPLICATION]).bootstrap(ImageDemo);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<nav>
|
||||
<ul>
|
||||
<li class="start" [routerLink]="['/Start']">Start</li>
|
||||
<li class="about" [routerLink]="['/About']">About</li>
|
||||
<li class="contact" [routerLink]="['/Contact']">Contact</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main>
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
library playground.src.web_workers.router.background_index;
|
||||
|
||||
import "index_common.dart" show App;
|
||||
import "dart:isolate";
|
||||
import "package:angular2/platform/worker_app.dart";
|
||||
import "package:angular2/core.dart";
|
||||
import "package:angular2/src/web_workers/worker/router_providers.dart";
|
||||
import "package:angular2/router.dart";
|
||||
|
||||
@AngularEntrypoint()
|
||||
main(List<String> args, SendPort replyTo) {
|
||||
platform([
|
||||
WORKER_APP_PLATFORM,
|
||||
new Provider(RENDER_SEND_PORT, useValue: replyTo)
|
||||
]).asyncApplication(null, [
|
||||
WORKER_APP_APPLICATION,
|
||||
WORKER_APP_ROUTER,
|
||||
new Provider(LocationStrategy, useClass: HashLocationStrategy)
|
||||
]).then((ref) => ref.bootstrap(App));
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import {platform, Provider, NgZone} from "angular2/core";
|
||||
import {
|
||||
WORKER_APP_PLATFORM,
|
||||
WORKER_APP_APPLICATION,
|
||||
WORKER_APP_ROUTER
|
||||
} from "angular2/platform/worker_app";
|
||||
import {App} from "./index_common";
|
||||
import {HashLocationStrategy, LocationStrategy} from "angular2/router";
|
||||
|
||||
export function main() {
|
||||
let refPromise = platform([WORKER_APP_PLATFORM])
|
||||
.asyncApplication(null, [
|
||||
WORKER_APP_APPLICATION,
|
||||
WORKER_APP_ROUTER,
|
||||
new Provider(LocationStrategy, {useClass: HashLocationStrategy})
|
||||
]);
|
||||
refPromise.then((ref) => ref.bootstrap(App));
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import {Component} from 'angular2/core';
|
||||
@Component({selector: 'about', template: '<h1>About</h1>'})
|
||||
export class About {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import {Component} from 'angular2/core';
|
||||
@Component({selector: 'contact', template: '<h1>Contact</h1>'})
|
||||
export class Contact {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
import {Component} from 'angular2/core';
|
||||
@Component({selector: 'start', template: '<h1>Start</h1>'})
|
||||
export class Start {
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
library angular2.examples.web_workers.router.index;
|
||||
|
||||
import "package:angular2/platform/worker_render.dart";
|
||||
import "package:angular2/core.dart";
|
||||
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
|
||||
import "package:angular2/src/core/reflection/reflection.dart";
|
||||
|
||||
@AngularEntrypoint()
|
||||
main() {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
platform([WORKER_RENDER_PLATFORM]).asyncApplication(
|
||||
initIsolate("background_index.dart"), [WORKER_RENDER_ROUTER]);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<title>Web Worker Router Example</title>
|
||||
<body>
|
||||
<app></app>
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
import {platform, Provider} from 'angular2/core';
|
||||
import {
|
||||
WORKER_RENDER_APP,
|
||||
WORKER_RENDER_PLATFORM,
|
||||
WORKER_SCRIPT,
|
||||
WORKER_RENDER_ROUTER
|
||||
} from 'angular2/platform/worker_render';
|
||||
import {BrowserPlatformLocation} from "angular2/src/router/browser_platform_location";
|
||||
import {MessageBasedPlatformLocation} from "angular2/src/web_workers/ui/platform_location";
|
||||
|
||||
let ref = platform([WORKER_RENDER_PLATFORM])
|
||||
.application([
|
||||
WORKER_RENDER_APP,
|
||||
new Provider(WORKER_SCRIPT, {useValue: "loader.js"}),
|
||||
WORKER_RENDER_ROUTER
|
||||
]);
|
|
@ -0,0 +1,14 @@
|
|||
import {Component, View} from 'angular2/core';
|
||||
import {Start} from './components/start';
|
||||
import {About} from './components/about';
|
||||
import {Contact} from './components/contact';
|
||||
import {ROUTER_DIRECTIVES, RouteConfig, Route} from 'angular2/router';
|
||||
|
||||
@Component({selector: 'app', directives: [ROUTER_DIRECTIVES], templateUrl: 'app.html'})
|
||||
@RouteConfig([
|
||||
new Route({path: '/', component: Start, name: "Start"}),
|
||||
new Route({path: '/contact', component: Contact, name: "Contact"}),
|
||||
new Route({path: '/about', component: About, name: "About"})
|
||||
])
|
||||
export class App {
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
$SCRIPTS$
|
||||
|
||||
System.config({
|
||||
baseURL: '/',
|
||||
defaultJSExtensions: true
|
||||
});
|
||||
|
||||
System.import("playground/src/web_workers/router/background_index")
|
||||
.then(
|
||||
function(m) {
|
||||
try {
|
||||
m.main();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
function(error) { console.error("error loading background", error); });
|
|
@ -10,7 +10,6 @@ main() {
|
|||
var webSocket = new WebSocket("ws://127.0.0.1:1337/ws");
|
||||
webSocket.onOpen.listen((e) {
|
||||
var bus = new WebSocketMessageBus.fromWebSocket(webSocket);
|
||||
|
||||
platform([WORKER_RENDER_PLATFORM])
|
||||
.application([WORKER_RENDER_APPLICATION_COMMON, new Provider(MessageBus, useValue: bus),
|
||||
new Provider(APP_INITIALIZER,
|
||||
|
|
|
@ -68,7 +68,8 @@ const kServedPaths = [
|
|||
'playground/src/web_workers/kitchen_sink',
|
||||
'playground/src/web_workers/todo',
|
||||
'playground/src/web_workers/images',
|
||||
'playground/src/web_workers/message_broker'
|
||||
'playground/src/web_workers/message_broker',
|
||||
'playground/src/web_workers/router'
|
||||
];
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue