refactor(platform-webworker): cleanup

This commit is contained in:
Victor Berchet 2017-02-19 00:23:45 -08:00
parent 3517f28609
commit cdf99cf68b
15 changed files with 301 additions and 314 deletions

View File

@ -13,16 +13,13 @@ import {WORKER_SCRIPT, platformWorkerUi} from './worker_render';
export {VERSION} from './version';
export {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from './web_workers/shared/client_message_broker';
export {MessageBus, MessageBusSink, MessageBusSource} from './web_workers/shared/message_bus';
export {SerializerTypes} from './web_workers/shared/serialized_types';
export {PRIMITIVE} from './web_workers/shared/serializer';
export {PRIMITIVE, SerializerTypes} from './web_workers/shared/serializer';
export {ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory} from './web_workers/shared/service_message_broker';
export {WORKER_UI_LOCATION_PROVIDERS} from './web_workers/ui/location_providers';
export {WORKER_APP_LOCATION_PROVIDERS} from './web_workers/worker/location_providers';
export {WorkerAppModule, platformWorkerApp} from './worker_app';
export {platformWorkerUi} from './worker_render';
/**
* Bootstraps the worker ui.
*

View File

@ -12,8 +12,7 @@ import {EventEmitter} from '../../facade/async';
import {stringify} from '../../facade/lang';
import {MessageBus} from './message_bus';
import {SerializerTypes} from './serialized_types';
import {Serializer} from './serializer';
import {Serializer, SerializerTypes} from './serializer';
/**
@ -48,7 +47,7 @@ export class ClientMessageBrokerFactory_ extends ClientMessageBrokerFactory {
* @experimental WebWorker support in Angular is experimental.
*/
export abstract class ClientMessageBroker {
abstract runOnService(args: UiArguments, returnType: Type<any>): Promise<any>;
abstract runOnService(args: UiArguments, returnType: Type<any>|SerializerTypes): Promise<any>;
}
interface PromiseCompleter {
@ -68,7 +67,7 @@ export class ClientMessageBroker_ extends ClientMessageBroker {
this._serializer = _serializer;
const source = messageBus.from(channel);
source.subscribe({next: (message: {[key: string]: any}) => this._handleMessage(message)});
source.subscribe({next: (message: MessageData) => this._handleMessage(message)});
}
private _generateMessageId(name: string): string {
@ -82,7 +81,7 @@ export class ClientMessageBroker_ extends ClientMessageBroker {
return id;
}
runOnService(args: UiArguments, returnType: Type<any>): Promise<any> {
runOnService(args: UiArguments, returnType: Type<any>|SerializerTypes): Promise<any> {
const fnArgs: any[] = [];
if (args.args) {
args.args.forEach(argument => {
@ -127,15 +126,14 @@ export class ClientMessageBroker_ extends ClientMessageBroker {
return promise;
}
private _handleMessage(message: {[key: string]: any}): void {
const data = new MessageData(message);
if (data.type === 'result' || data.type === 'error') {
const id = data.id;
private _handleMessage(message: MessageData): void {
if (message.type === 'result' || message.type === 'error') {
const id = message.id;
if (this._pending.has(id)) {
if (data.type === 'result') {
this._pending.get(id).resolve(data.value);
if (message.type === 'result') {
this._pending.get(id).resolve(message.value);
} else {
this._pending.get(id).reject(data.value);
this._pending.get(id).reject(message.value);
}
this._pending.delete(id);
}
@ -143,31 +141,18 @@ export class ClientMessageBroker_ extends ClientMessageBroker {
}
}
class MessageData {
type: string;
value: any;
id: string;
constructor(data: {[key: string]: any}) {
this.type = data['type'];
this.id = this._getValueIfPresent(data, 'id');
this.value = this._getValueIfPresent(data, 'value');
}
/**
* Returns the value if present, otherwise returns null
* @internal
*/
_getValueIfPresent(data: {[key: string]: any}, key: string) {
return data.hasOwnProperty(key) ? data[key] : null;
}
interface MessageData {
type: 'result'|'error';
value?: any;
id?: string;
}
/**
* @experimental WebWorker support in Angular is experimental.
*/
export class FnArg {
constructor(public value: any, public type: Type<any>|SerializerTypes = null) {}
constructor(
public value: any, public type: Type<any>|SerializerTypes = SerializerTypes.PRIMITIVE) {}
}
/**

View File

@ -1,24 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// 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) {}
}
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export const enum SerializerTypes {
// RendererTypeV2
RENDERER_TYPE_V2,
}

View File

@ -6,36 +6,52 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Injectable, RenderComponentType, RendererTypeV2, Type, ViewEncapsulation} from '@angular/core';
import {Injectable, RenderComponentType, RendererTypeV2, Type} from '@angular/core';
import {stringify} from '../../facade/lang';
import {RenderStore} from './render_store';
import {LocationType, SerializerTypes} 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.
/**
* Any type that does not need to be serialized (string, number, boolean)
*
* @experimental WebWorker support in Angular is currently experimental.
* @deprecated in v4. Use SerializerTypes.PRIMITIVE instead
*/
export const PRIMITIVE: Type<any> = String;
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) {}
}
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export const PRIMITIVE: Type<any> = String;
export const enum SerializerTypes {
// RendererTypeV2
RENDERER_TYPE_V2,
// Primitive types
PRIMITIVE,
// An object stored in a RenderStore
RENDER_STORE_OBJECT,
}
@Injectable()
export class Serializer {
constructor(private _renderStore: RenderStore) {}
serialize(obj: any, type: any): Object {
if (obj == null) {
return null;
serialize(obj: any, type: Type<any>|SerializerTypes = SerializerTypes.PRIMITIVE): Object {
if (obj == null || type === PRIMITIVE || type === SerializerTypes.PRIMITIVE) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(v => this.serialize(v, type));
}
if (type == PRIMITIVE) {
return obj;
}
if (type == RenderStoreObject) {
if (type === SerializerTypes.RENDER_STORE_OBJECT) {
return this._renderStore.serialize(obj);
}
if (type === RenderComponentType) {
@ -44,26 +60,21 @@ export class Serializer {
if (type === SerializerTypes.RENDERER_TYPE_V2) {
return this._serializeRendererTypeV2(obj);
}
if (type === ViewEncapsulation) {
return obj;
}
if (type === LocationType) {
return this._serializeLocation(obj);
}
throw new Error(`No serializer for type ${stringify(type)}`);
}
deserialize(map: any, type: any, data?: any): any {
if (map == null) {
return null;
deserialize(map: any, type: Type<any>|SerializerTypes = SerializerTypes.PRIMITIVE, data?: any):
any {
if (map == null || type === PRIMITIVE || type === SerializerTypes.PRIMITIVE) {
return map;
}
if (Array.isArray(map)) {
return map.map(val => this.deserialize(val, type, data));
}
if (type === PRIMITIVE) {
return map;
}
if (type === RenderStoreObject) {
if (type === SerializerTypes.RENDER_STORE_OBJECT) {
return this._renderStore.deserialize(map);
}
if (type === RenderComponentType) {
@ -72,9 +83,6 @@ export class Serializer {
if (type === SerializerTypes.RENDERER_TYPE_V2) {
return this._deserializeRendererTypeV2(map);
}
if (type === ViewEncapsulation) {
return map as ViewEncapsulation;
}
if (type === LocationType) {
return this._deserializeLocation(map);
}
@ -106,24 +114,23 @@ export class Serializer {
'id': type.id,
'templateUrl': type.templateUrl,
'slotCount': type.slotCount,
'encapsulation': this.serialize(type.encapsulation, ViewEncapsulation),
'styles': this.serialize(type.styles, PRIMITIVE),
'encapsulation': this.serialize(type.encapsulation),
'styles': this.serialize(type.styles),
};
}
private _deserializeRenderComponentType(props: {[key: string]: any}): RenderComponentType {
return new RenderComponentType(
props['id'], props['templateUrl'], props['slotCount'],
this.deserialize(props['encapsulation'], ViewEncapsulation),
this.deserialize(props['styles'], PRIMITIVE), {});
this.deserialize(props['encapsulation']), this.deserialize(props['styles']), {});
}
private _serializeRendererTypeV2(type: RendererTypeV2): {[key: string]: any} {
return {
'id': type.id,
'encapsulation': this.serialize(type.encapsulation, ViewEncapsulation),
'styles': this.serialize(type.styles, PRIMITIVE),
'data': this.serialize(type.data, PRIMITIVE),
'encapsulation': this.serialize(type.encapsulation),
'styles': this.serialize(type.styles),
'data': this.serialize(type.data),
};
}
@ -131,12 +138,10 @@ export class Serializer {
return {
id: props['id'],
encapsulation: props['encapsulation'],
styles: this.deserialize(props['styles'], PRIMITIVE),
data: this.deserialize(props['data'], PRIMITIVE)
styles: this.deserialize(props['styles']),
data: this.deserialize(props['data'])
};
}
}
export const ANIMATION_WORKER_PLAYER_PREFIX = 'AnimationPlayer.';
export class RenderStoreObject {}

View File

@ -9,9 +9,8 @@
import {Injectable, Type} from '@angular/core';
import {EventEmitter} from '../../facade/async';
import {isPresent} from '../../facade/lang';
import {MessageBus} from '../shared/message_bus';
import {Serializer} from '../shared/serializer';
import {Serializer, SerializerTypes} from '../shared/serializer';
/**
* @experimental WebWorker support in Angular is currently experimental.
@ -49,12 +48,13 @@ export class ServiceMessageBrokerFactory_ extends ServiceMessageBrokerFactory {
*/
export abstract class ServiceMessageBroker {
abstract registerMethod(
methodName: string, signature: Type<any>[], method: Function, returnType?: Type<any>): void;
methodName: string, signature: Array<Type<any>|SerializerTypes>, method: Function,
returnType?: Type<any>|SerializerTypes): void;
}
export class ServiceMessageBroker_ extends ServiceMessageBroker {
private _sink: EventEmitter<any>;
private _methods: Map<string, Function> = new Map<string, Function>();
private _methods = new Map<string, Function>();
constructor(messageBus: MessageBus, private _serializer: Serializer, public channel: string) {
super();
@ -64,11 +64,11 @@ export class ServiceMessageBroker_ extends ServiceMessageBroker {
}
registerMethod(
methodName: string, signature: Type<any>[], method: (..._: any[]) => Promise<any>| void,
returnType?: Type<any>): void {
methodName: string, signature: Array<Type<any>|SerializerTypes>,
method: (..._: any[]) => Promise<any>| void, returnType?: Type<any>|SerializerTypes): void {
this._methods.set(methodName, (message: ReceivedMessage) => {
const serializedArgs = message.args;
const numArgs = signature === null ? 0 : signature.length;
const numArgs = signature ? signature.length : 0;
const deserializedArgs = new Array(numArgs);
for (let i = 0; i < numArgs; i++) {
const serializedArg = serializedArgs[i];
@ -82,14 +82,14 @@ export class ServiceMessageBroker_ extends ServiceMessageBroker {
});
}
private _handleMessage(map: {[key: string]: any}): void {
const message = new ReceivedMessage(map);
private _handleMessage(message: ReceivedMessage): void {
if (this._methods.has(message.method)) {
this._methods.get(message.method)(message);
}
}
private _wrapWebWorkerPromise(id: string, promise: Promise<any>, type: Type<any>): void {
private _wrapWebWorkerPromise(id: string, promise: Promise<any>, type: Type<any>|SerializerTypes):
void {
promise.then((result: any) => {
this._sink.emit({
'type': 'result',
@ -103,16 +103,9 @@ export class ServiceMessageBroker_ extends ServiceMessageBroker {
/**
* @experimental WebWorker support in Angular is currently experimental.
*/
export class ReceivedMessage {
export interface ReceivedMessage {
method: string;
args: any[];
id: string;
type: string;
constructor(data: {[key: string]: any}) {
this.method = data['method'];
this.args = data['args'];
this.id = data['id'];
this.type = data['type'];
}
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {EventEmitter} from '../../facade/async';
import {RenderStoreObject, Serializer} from '../shared/serializer';
import {Serializer, SerializerTypes} from '../shared/serializer';
import {serializeEventWithTarget, serializeGenericEvent, serializeKeyboardEvent, serializeMouseEvent, serializeTransitionEvent} from './event_serializer';
@ -15,8 +15,8 @@ export class EventDispatcher {
dispatchAnimationEvent(player: any, phaseName: string, element: any): boolean {
this._sink.emit({
'element': this._serializer.serialize(element, RenderStoreObject),
'animationPlayer': this._serializer.serialize(player, RenderStoreObject),
'element': this._serializer.serialize(element, SerializerTypes.RENDER_STORE_OBJECT),
'animationPlayer': this._serializer.serialize(player, SerializerTypes.RENDER_STORE_OBJECT),
'phaseName': phaseName,
});
return true;
@ -107,7 +107,7 @@ export class EventDispatcher {
}
this._sink.emit({
'element': this._serializer.serialize(element, RenderStoreObject),
'element': this._serializer.serialize(element, SerializerTypes.RENDER_STORE_OBJECT),
'eventName': eventName,
'eventTarget': eventTarget,
'event': serializedEvent,

View File

@ -13,8 +13,7 @@ import {EventEmitter} from '../../facade/async';
import {BrowserPlatformLocation} from '../../private_import_platform-browser';
import {MessageBus} from '../shared/message_bus';
import {ROUTER_CHANNEL} from '../shared/messaging_api';
import {LocationType} from '../shared/serialized_types';
import {PRIMITIVE, Serializer} from '../shared/serializer';
import {LocationType, Serializer, SerializerTypes} from '../shared/serializer';
import {ServiceMessageBroker, ServiceMessageBrokerFactory} from '../shared/service_message_broker';
@Injectable()
@ -34,13 +33,14 @@ export class MessageBasedPlatformLocation {
}
start(): void {
const P = SerializerTypes.PRIMITIVE;
this._broker.registerMethod('getLocation', null, this._getLocation.bind(this), LocationType);
this._broker.registerMethod('setPathname', [PRIMITIVE], this._setPathname.bind(this));
this._broker.registerMethod('setPathname', [P], this._setPathname.bind(this));
this._broker.registerMethod(
'pushState', [PRIMITIVE, PRIMITIVE, PRIMITIVE],
this._platformLocation.pushState.bind(this._platformLocation));
'pushState', [P, P, P], this._platformLocation.pushState.bind(this._platformLocation));
this._broker.registerMethod(
'replaceState', [PRIMITIVE, PRIMITIVE, PRIMITIVE],
'replaceState', [P, P, P],
this._platformLocation.replaceState.bind(this._platformLocation));
this._broker.registerMethod(
'forward', null, this._platformLocation.forward.bind(this._platformLocation));
@ -52,11 +52,11 @@ export class MessageBasedPlatformLocation {
return Promise.resolve(this._platformLocation.location);
}
private _sendUrlChangeEvent(e: Event): void {
const loc = this._serializer.serialize(this._platformLocation.location, LocationType);
const serializedEvent = {'type': e.type};
this._channelSink.emit({'event': serializedEvent, 'location': loc});
this._channelSink.emit({
'event': {'type': e.type},
'location': this._serializer.serialize(this._platformLocation.location, LocationType),
});
}
private _setPathname(pathname: string): void { this._platformLocation.pathname = pathname; }

View File

@ -11,8 +11,7 @@ import {AnimationPlayer, Injectable, RenderComponentType, Renderer, RendererFact
import {MessageBus} from '../shared/message_bus';
import {EVENT_CHANNEL, EVENT_V2_CHANNEL, RENDERER_CHANNEL, RENDERER_V2_CHANNEL} from '../shared/messaging_api';
import {RenderStore} from '../shared/render_store';
import {SerializerTypes} from '../shared/serialized_types';
import {ANIMATION_WORKER_PLAYER_PREFIX, PRIMITIVE, RenderStoreObject, Serializer} from '../shared/serializer';
import {ANIMATION_WORKER_PLAYER_PREFIX, Serializer, SerializerTypes} from '../shared/serializer';
import {ServiceMessageBroker, ServiceMessageBrokerFactory} from '../shared/service_message_broker';
import {EventDispatcher} from '../ui/event_dispatcher';
@ -31,7 +30,11 @@ export class MessageBasedRenderer {
this._bus.initChannel(EVENT_CHANNEL);
this._eventDispatcher = new EventDispatcher(this._bus.to(EVENT_CHANNEL), this._serializer);
const [RCT, RSO, P] = [RenderComponentType, RenderStoreObject, PRIMITIVE];
const [RCT, RSO, P] = [
RenderComponentType,
SerializerTypes.RENDER_STORE_OBJECT,
SerializerTypes.PRIMITIVE,
];
const methods: any[][] = [
['renderComponent', this._renderComponent, RCT, P],
@ -65,52 +68,51 @@ export class MessageBasedRenderer {
}
private _bindAnimationPlayerMethods(broker: ServiceMessageBroker) {
const [P, RSO] = [SerializerTypes.PRIMITIVE, SerializerTypes.RENDER_STORE_OBJECT];
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'play', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'play', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.play());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'pause', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'pause', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.pause());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'init', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'init', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.init());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'restart', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'restart', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.restart());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'destroy', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'destroy', [RSO, RSO],
(player: AnimationPlayer, element: any) => {
player.destroy();
this._renderStore.remove(player);
});
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'finish', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'finish', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.finish());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'getPosition', [RenderStoreObject, RenderStoreObject],
ANIMATION_WORKER_PLAYER_PREFIX + 'getPosition', [RSO, RSO],
(player: AnimationPlayer, element: any) => player.getPosition());
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'onStart',
[RenderStoreObject, RenderStoreObject, PRIMITIVE],
ANIMATION_WORKER_PLAYER_PREFIX + 'onStart', [RSO, RSO, P],
(player: AnimationPlayer, element: any) =>
this._listenOnAnimationPlayer(player, element, 'onStart'));
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'onDone',
[RenderStoreObject, RenderStoreObject, PRIMITIVE],
ANIMATION_WORKER_PLAYER_PREFIX + 'onDone', [RSO, RSO, P],
(player: AnimationPlayer, element: any) =>
this._listenOnAnimationPlayer(player, element, 'onDone'));
broker.registerMethod(
ANIMATION_WORKER_PLAYER_PREFIX + 'setPosition',
[RenderStoreObject, RenderStoreObject, PRIMITIVE],
ANIMATION_WORKER_PLAYER_PREFIX + 'setPosition', [RSO, RSO, P],
(player: AnimationPlayer, element: any, position: number) => player.setPosition(position));
}
@ -254,7 +256,11 @@ export class MessageBasedRendererV2 {
this._bus.initChannel(EVENT_V2_CHANNEL);
this._eventDispatcher = new EventDispatcher(this._bus.to(EVENT_V2_CHANNEL), this._serializer);
const [RSO, P, CRT] = [RenderStoreObject, PRIMITIVE, SerializerTypes.RENDERER_TYPE_V2];
const [RSO, P, CRT] = [
SerializerTypes.RENDER_STORE_OBJECT,
SerializerTypes.PRIMITIVE,
SerializerTypes.RENDERER_TYPE_V2,
];
const methods: any[][] = [
['createRenderer', this.createRenderer, RSO, CRT, P],

View File

@ -13,8 +13,7 @@ import {EventEmitter} from '../../facade/async';
import {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
import {MessageBus} from '../shared/message_bus';
import {ROUTER_CHANNEL} from '../shared/messaging_api';
import {LocationType} from '../shared/serialized_types';
import {PRIMITIVE, Serializer} from '../shared/serializer';
import {LocationType, Serializer, SerializerTypes} from '../shared/serializer';
@Injectable()
export class WebWorkerPlatformLocation extends PlatformLocation {
@ -28,8 +27,8 @@ export class WebWorkerPlatformLocation extends PlatformLocation {
brokerFactory: ClientMessageBrokerFactory, bus: MessageBus, private _serializer: Serializer) {
super();
this._broker = brokerFactory.createMessageBroker(ROUTER_CHANNEL);
this._channelSource = bus.from(ROUTER_CHANNEL);
this._channelSource.subscribe({
next: (msg: {[key: string]: any}) => {
let listeners: Array<Function> = null;
@ -86,21 +85,27 @@ export class WebWorkerPlatformLocation extends PlatformLocation {
this._location.pathname = newPath;
const fnArgs = [new FnArg(newPath, PRIMITIVE)];
const fnArgs = [new FnArg(newPath, SerializerTypes.PRIMITIVE)];
const args = new UiArguments('setPathname', fnArgs);
this._broker.runOnService(args, null);
}
pushState(state: any, title: string, url: string): void {
const fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
const fnArgs = [
new FnArg(state, SerializerTypes.PRIMITIVE),
new FnArg(title, SerializerTypes.PRIMITIVE),
new FnArg(url, SerializerTypes.PRIMITIVE),
];
const args = new UiArguments('pushState', fnArgs);
this._broker.runOnService(args, null);
}
replaceState(state: any, title: string, url: string): void {
const fnArgs =
[new FnArg(state, PRIMITIVE), new FnArg(title, PRIMITIVE), new FnArg(url, PRIMITIVE)];
const fnArgs = [
new FnArg(state, SerializerTypes.PRIMITIVE),
new FnArg(title, SerializerTypes.PRIMITIVE),
new FnArg(url, SerializerTypes.PRIMITIVE),
];
const args = new UiArguments('replaceState', fnArgs);
this._broker.runOnService(args, null);
}

View File

@ -8,19 +8,50 @@
import {Injectable, RenderComponentType, Renderer, RendererFactoryV2, RendererTypeV2, RendererV2, RootRenderer, ViewEncapsulation} from '@angular/core';
import {ListWrapper} from '../../facade/collection';
import {AnimationKeyframe, AnimationPlayer, AnimationStyles, RenderDebugInfo} from '../../private_import_core';
import {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
import {MessageBus} from '../shared/message_bus';
import {EVENT_CHANNEL, EVENT_V2_CHANNEL, RENDERER_CHANNEL, RENDERER_V2_CHANNEL} from '../shared/messaging_api';
import {RenderStore} from '../shared/render_store';
import {SerializerTypes} from '../shared/serialized_types';
import {ANIMATION_WORKER_PLAYER_PREFIX, RenderStoreObject, Serializer} from '../shared/serializer';
import {ANIMATION_WORKER_PLAYER_PREFIX, Serializer, SerializerTypes} from '../shared/serializer';
export class NamedEventEmitter {
private _listeners: Map<string, Function[]>;
listen(eventName: string, callback: Function) { this._getListeners(eventName).push(callback); }
unlisten(eventName: string, listener: Function) {
const listeners = this._getListeners(eventName);
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
}
dispatchEvent(eventName: string, event: any) {
const listeners = this._getListeners(eventName);
for (let i = 0; i < listeners.length; i++) {
listeners[i](event);
}
}
private _getListeners(eventName: string): Function[] {
if (!this._listeners) {
this._listeners = new Map<string, Function[]>();
}
let listeners = this._listeners.get(eventName);
if (!listeners) {
listeners = [];
this._listeners.set(eventName, listeners);
}
return listeners;
}
}
const globalEvents = new NamedEventEmitter();
@Injectable()
export class WebWorkerRootRenderer implements RootRenderer {
globalEvents = new NamedEventEmitter();
private _messageBroker: ClientMessageBroker;
private _componentRenderers = new Map<string, WebWorkerRenderer>();
@ -34,20 +65,21 @@ export class WebWorkerRootRenderer implements RootRenderer {
}
private _dispatchEvent(message: {[key: string]: any}): void {
const element =
<WebWorkerRenderNode>this._serializer.deserialize(message['element'], RenderStoreObject);
const element: WebWorkerRenderNode =
this._serializer.deserialize(message['element'], SerializerTypes.RENDER_STORE_OBJECT);
const playerData = message['animationPlayer'];
if (playerData) {
const phaseName = message['phaseName'];
const player = <AnimationPlayer>this._serializer.deserialize(playerData, RenderStoreObject);
const player: AnimationPlayer =
this._serializer.deserialize(playerData, SerializerTypes.RENDER_STORE_OBJECT);
element.animationPlayerEvents.dispatchEvent(player, phaseName);
} else {
const eventName = message['eventName'];
const target = message['eventTarget'];
const event = message['event'];
if (target) {
this.globalEvents.dispatchEvent(eventNameWithTarget(target, eventName), event);
globalEvents.dispatchEvent(eventNameWithTarget(target, eventName), event);
} else {
element.events.dispatchEvent(eventName, event);
}
@ -63,7 +95,7 @@ export class WebWorkerRootRenderer implements RootRenderer {
this.renderStore.store(result, id);
this.runOnService('renderComponent', [
new FnArg(componentType, RenderComponentType),
new FnArg(result, RenderStoreObject),
new FnArg(result, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
return result;
@ -90,27 +122,30 @@ export class WebWorkerRootRenderer implements RootRenderer {
}
}
export class WebWorkerRenderer implements Renderer, RenderStoreObject {
export class WebWorkerRenderer implements Renderer {
constructor(
private _rootRenderer: WebWorkerRootRenderer, private _componentType: RenderComponentType) {}
private _runOnService(fnName: string, fnArgs: FnArg[]) {
const fnArgsWithRenderer = [new FnArg(this, RenderStoreObject)].concat(fnArgs);
const fnArgsWithRenderer = [new FnArg(this, SerializerTypes.RENDER_STORE_OBJECT), ...fnArgs];
this._rootRenderer.runOnService(fnName, fnArgsWithRenderer);
}
selectRootElement(selectorOrNode: string, debugInfo?: RenderDebugInfo): any {
const node = this._rootRenderer.allocateNode();
this._runOnService(
'selectRootElement', [new FnArg(selectorOrNode, null), new FnArg(node, RenderStoreObject)]);
this._runOnService('selectRootElement', [
new FnArg(selectorOrNode),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
createElement(parentElement: any, name: string, debugInfo?: RenderDebugInfo): any {
const node = this._rootRenderer.allocateNode();
this._runOnService('createElement', [
new FnArg(parentElement, RenderStoreObject), new FnArg(name, null),
new FnArg(node, RenderStoreObject)
new FnArg(parentElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
@ -119,121 +154,139 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
const viewRoot = this._componentType.encapsulation === ViewEncapsulation.Native ?
this._rootRenderer.allocateNode() :
hostElement;
this._runOnService(
'createViewRoot',
[new FnArg(hostElement, RenderStoreObject), new FnArg(viewRoot, RenderStoreObject)]);
this._runOnService('createViewRoot', [
new FnArg(hostElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(viewRoot, SerializerTypes.RENDER_STORE_OBJECT),
]);
return viewRoot;
}
createTemplateAnchor(parentElement: any, debugInfo?: RenderDebugInfo): any {
const node = this._rootRenderer.allocateNode();
this._runOnService(
'createTemplateAnchor',
[new FnArg(parentElement, RenderStoreObject), new FnArg(node, RenderStoreObject)]);
this._runOnService('createTemplateAnchor', [
new FnArg(parentElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
createText(parentElement: any, value: string, debugInfo?: RenderDebugInfo): any {
const node = this._rootRenderer.allocateNode();
this._runOnService('createText', [
new FnArg(parentElement, RenderStoreObject), new FnArg(value, null),
new FnArg(node, RenderStoreObject)
new FnArg(parentElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(value),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
projectNodes(parentElement: any, nodes: any[]) {
this._runOnService(
'projectNodes',
[new FnArg(parentElement, RenderStoreObject), new FnArg(nodes, RenderStoreObject)]);
this._runOnService('projectNodes', [
new FnArg(parentElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(nodes, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
attachViewAfter(node: any, viewRootNodes: any[]) {
this._runOnService(
'attachViewAfter',
[new FnArg(node, RenderStoreObject), new FnArg(viewRootNodes, RenderStoreObject)]);
this._runOnService('attachViewAfter', [
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(viewRootNodes, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
detachView(viewRootNodes: any[]) {
this._runOnService('detachView', [new FnArg(viewRootNodes, RenderStoreObject)]);
this._runOnService(
'detachView', [new FnArg(viewRootNodes, SerializerTypes.RENDER_STORE_OBJECT)]);
}
destroyView(hostElement: any, viewAllNodes: any[]) {
this._runOnService(
'destroyView',
[new FnArg(hostElement, RenderStoreObject), new FnArg(viewAllNodes, RenderStoreObject)]);
this._runOnService('destroyView', [
new FnArg(hostElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(viewAllNodes, SerializerTypes.RENDER_STORE_OBJECT),
]);
this._rootRenderer.destroyNodes(viewAllNodes);
}
setElementProperty(renderElement: any, propertyName: string, propertyValue: any) {
this._runOnService('setElementProperty', [
new FnArg(renderElement, RenderStoreObject), new FnArg(propertyName, null),
new FnArg(propertyValue, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(propertyName),
new FnArg(propertyValue),
]);
}
setElementAttribute(renderElement: any, attributeName: string, attributeValue: string) {
this._runOnService('setElementAttribute', [
new FnArg(renderElement, RenderStoreObject), new FnArg(attributeName, null),
new FnArg(attributeValue, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(attributeName),
new FnArg(attributeValue),
]);
}
setBindingDebugInfo(renderElement: any, propertyName: string, propertyValue: string) {
this._runOnService('setBindingDebugInfo', [
new FnArg(renderElement, RenderStoreObject), new FnArg(propertyName, null),
new FnArg(propertyValue, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(propertyName),
new FnArg(propertyValue),
]);
}
setElementClass(renderElement: any, className: string, isAdd: boolean) {
this._runOnService('setElementClass', [
new FnArg(renderElement, RenderStoreObject), new FnArg(className, null),
new FnArg(isAdd, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(className),
new FnArg(isAdd),
]);
}
setElementStyle(renderElement: any, styleName: string, styleValue: string) {
this._runOnService('setElementStyle', [
new FnArg(renderElement, RenderStoreObject), new FnArg(styleName, null),
new FnArg(styleValue, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(styleName),
new FnArg(styleValue),
]);
}
invokeElementMethod(renderElement: any, methodName: string, args?: any[]) {
this._runOnService('invokeElementMethod', [
new FnArg(renderElement, RenderStoreObject), new FnArg(methodName, null),
new FnArg(args, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(methodName),
new FnArg(args),
]);
}
setText(renderNode: any, text: string) {
this._runOnService(
'setText', [new FnArg(renderNode, RenderStoreObject), new FnArg(text, null)]);
this._runOnService('setText', [
new FnArg(renderNode, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(text),
]);
}
listen(renderElement: WebWorkerRenderNode, name: string, callback: Function): Function {
renderElement.events.listen(name, callback);
const unlistenCallbackId = this._rootRenderer.allocateId();
this._runOnService('listen', [
new FnArg(renderElement, RenderStoreObject), new FnArg(name, null),
new FnArg(unlistenCallbackId, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
new FnArg(unlistenCallbackId),
]);
return () => {
renderElement.events.unlisten(name, callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId)]);
};
}
listenGlobal(target: string, name: string, callback: Function): Function {
this._rootRenderer.globalEvents.listen(eventNameWithTarget(target, name), callback);
globalEvents.listen(eventNameWithTarget(target, name), callback);
const unlistenCallbackId = this._rootRenderer.allocateId();
this._runOnService(
'listenGlobal',
[new FnArg(target, null), new FnArg(name, null), new FnArg(unlistenCallbackId, null)]);
this._runOnService('listenGlobal', [
new FnArg(target),
new FnArg(name, null),
new FnArg(unlistenCallbackId),
]);
return () => {
this._rootRenderer.globalEvents.unlisten(eventNameWithTarget(target, name), callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId, null)]);
globalEvents.unlisten(eventNameWithTarget(target, name), callback);
this._runOnService('listenDone', [new FnArg(unlistenCallbackId)]);
};
}
@ -246,9 +299,14 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
previousPlayers.map(player => this._rootRenderer.renderStore.serialize(player));
this._runOnService('animate', [
new FnArg(renderElement, RenderStoreObject), new FnArg(startingStyles, null),
new FnArg(keyframes, null), new FnArg(duration, null), new FnArg(delay, null),
new FnArg(easing, null), new FnArg(previousPlayerIds, null), new FnArg(playerId, null)
new FnArg(renderElement, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(startingStyles),
new FnArg(keyframes),
new FnArg(duration),
new FnArg(delay),
new FnArg(easing),
new FnArg(previousPlayerIds),
new FnArg(playerId),
]);
const player = new _AnimationWorkerRendererPlayer(this._rootRenderer, renderElement);
@ -262,37 +320,6 @@ function eventNameWithTarget(target: string, eventName: string): string {
return `${target}:${eventName}`;
}
export class NamedEventEmitter {
private _listeners: Map<string, Function[]>;
listen(eventName: string, callback: Function) { this._getListeners(eventName).push(callback); }
unlisten(eventName: string, callback: Function) {
ListWrapper.remove(this._getListeners(eventName), callback);
}
dispatchEvent(eventName: string, event: any) {
const listeners = this._getListeners(eventName);
for (let i = 0; i < listeners.length; i++) {
listeners[i](event);
}
}
private _getListeners(eventName: string): Function[] {
if (!this._listeners) {
this._listeners = new Map<string, Function[]>();
}
let listeners = this._listeners.get(eventName);
if (!listeners) {
listeners = [];
this._listeners.set(eventName, listeners);
}
return listeners;
}
}
const globalEvents = new NamedEventEmitter();
@Injectable()
export class WebWorkerRendererFactoryV2 implements RendererFactoryV2 {
private _messageBroker: ClientMessageBroker;
@ -312,9 +339,9 @@ export class WebWorkerRendererFactoryV2 implements RendererFactoryV2 {
const id = this.renderStore.allocateId();
this.renderStore.store(renderer, id);
this.callUI('createRenderer', [
new FnArg(element, RenderStoreObject),
new FnArg(element, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(type, SerializerTypes.RENDERER_TYPE_V2),
new FnArg(renderer, RenderStoreObject),
new FnArg(renderer, SerializerTypes.RENDER_STORE_OBJECT),
]);
return renderer;
@ -336,7 +363,7 @@ export class WebWorkerRendererFactoryV2 implements RendererFactoryV2 {
private _dispatchEvent(message: {[key: string]: any}): void {
const element: WebWorkerRenderNode =
this._serializer.deserialize(message['element'], RenderStoreObject);
this._serializer.deserialize(message['element'], SerializerTypes.RENDER_STORE_OBJECT);
const eventName = message['eventName'];
const target = message['eventTarget'];
@ -355,7 +382,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
constructor(private _rendererFactory: WebWorkerRendererFactoryV2) {}
destroyNode: (node: any) => void | null = null;
private asFnArg = new FnArg(this, RenderStoreObject);
private asFnArg = new FnArg(this, SerializerTypes.RENDER_STORE_OBJECT);
// TODO(vicb): destroy the allocated nodes
destroy(): void { this.callUIWithRenderer('destroy'); }
@ -365,7 +392,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
this.callUIWithRenderer('createElement', [
new FnArg(name),
new FnArg(namespace),
new FnArg(node, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
@ -374,7 +401,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
const node = this._rendererFactory.allocateNode();
this.callUIWithRenderer('createComment', [
new FnArg(value),
new FnArg(node, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
@ -383,15 +410,15 @@ export class WebWorkerRendererV2 implements RendererV2 {
const node = this._rendererFactory.allocateNode();
this.callUIWithRenderer('createText', [
new FnArg(value),
new FnArg(node, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
appendChild(parent: any, newChild: any): void {
this.callUIWithRenderer('appendChild', [
new FnArg(parent, RenderStoreObject),
new FnArg(newChild, RenderStoreObject),
new FnArg(parent, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(newChild, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
@ -401,16 +428,16 @@ export class WebWorkerRendererV2 implements RendererV2 {
}
this.callUIWithRenderer('insertBefore', [
new FnArg(parent, RenderStoreObject),
new FnArg(newChild, RenderStoreObject),
new FnArg(refChild, RenderStoreObject),
new FnArg(parent, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(newChild, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(refChild, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
removeChild(parent: any, oldChild: any): void {
this.callUIWithRenderer('removeChild', [
new FnArg(parent, RenderStoreObject),
new FnArg(oldChild, RenderStoreObject),
new FnArg(parent, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(oldChild, SerializerTypes.RENDER_STORE_OBJECT),
]);
}
@ -418,7 +445,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
const node = this._rendererFactory.allocateNode();
this.callUIWithRenderer('selectRootElement', [
new FnArg(selectorOrNode),
new FnArg(node, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
]);
return node;
}
@ -426,8 +453,8 @@ export class WebWorkerRendererV2 implements RendererV2 {
parentNode(node: any): any {
const res = this._rendererFactory.allocateNode();
this.callUIWithRenderer('parentNode', [
new FnArg(node, RenderStoreObject),
new FnArg(res, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(res, SerializerTypes.RENDER_STORE_OBJECT),
]);
return res;
}
@ -435,15 +462,15 @@ export class WebWorkerRendererV2 implements RendererV2 {
nextSibling(node: any): any {
const res = this._rendererFactory.allocateNode();
this.callUIWithRenderer('nextSibling', [
new FnArg(node, RenderStoreObject),
new FnArg(res, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(res, SerializerTypes.RENDER_STORE_OBJECT),
]);
return res;
}
setAttribute(el: any, name: string, value: string, namespace?: string): void {
this.callUIWithRenderer('setAttribute', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
new FnArg(value),
new FnArg(namespace),
@ -452,7 +479,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
removeAttribute(el: any, name: string, namespace?: string): void {
this.callUIWithRenderer('removeAttribute', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
new FnArg(namespace),
]);
@ -460,14 +487,14 @@ export class WebWorkerRendererV2 implements RendererV2 {
addClass(el: any, name: string): void {
this.callUIWithRenderer('addClass', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
]);
}
removeClass(el: any, name: string): void {
this.callUIWithRenderer('removeClass', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
]);
}
@ -475,7 +502,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
void {
this.callUIWithRenderer('setStyle', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(style),
new FnArg(value),
new FnArg(hasVendorPrefix),
@ -485,7 +512,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
this.callUIWithRenderer('removeStyle', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(style),
new FnArg(hasVendorPrefix),
]);
@ -493,7 +520,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
setProperty(el: any, name: string, value: any): void {
this.callUIWithRenderer('setProperty', [
new FnArg(el, RenderStoreObject),
new FnArg(el, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(name),
new FnArg(value),
]);
@ -501,7 +528,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
setValue(node: any, value: string): void {
this.callUIWithRenderer('setValue', [
new FnArg(node, RenderStoreObject),
new FnArg(node, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(value),
]);
}
@ -522,7 +549,7 @@ export class WebWorkerRendererV2 implements RendererV2 {
}
this.callUIWithRenderer('listen', [
new FnArg(targetEl, RenderStoreObject),
new FnArg(targetEl, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(targetName),
new FnArg(eventName),
new FnArg(unlistenId),
@ -581,7 +608,7 @@ export class WebWorkerRenderNode {
animationPlayerEvents = new AnimationPlayerEmitter();
}
class _AnimationWorkerRendererPlayer implements RenderStoreObject {
class _AnimationWorkerRendererPlayer {
public parentPlayer: AnimationPlayer = null;
private _destroyed: boolean = false;
@ -592,8 +619,9 @@ class _AnimationWorkerRendererPlayer implements RenderStoreObject {
private _runOnService(fnName: string, fnArgs: FnArg[]) {
if (!this._destroyed) {
const fnArgsWithRenderer = [
new FnArg(this, RenderStoreObject), new FnArg(this._renderElement, RenderStoreObject)
].concat(fnArgs);
new FnArg(this, SerializerTypes.RENDER_STORE_OBJECT),
new FnArg(this._renderElement, SerializerTypes.RENDER_STORE_OBJECT), ...fnArgs
];
this._rootRenderer.runOnService(ANIMATION_WORKER_PLAYER_PREFIX + fnName, fnArgsWithRenderer);
}
}
@ -639,7 +667,7 @@ class _AnimationWorkerRendererPlayer implements RenderStoreObject {
reset(): void { this._runOnService('reset', []); }
setPosition(p: number): void { this._runOnService('setPosition', [new FnArg(p, null)]); }
setPosition(p: number): void { this._runOnService('setPosition', [new FnArg(p)]); }
getPosition(): number { return 0; }
}

View File

@ -9,10 +9,9 @@
import {beforeEach, beforeEachProviders, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
import {ON_WEB_WORKER} from '@angular/platform-webworker/src/web_workers/shared/api';
import {RenderStore} from '@angular/platform-webworker/src/web_workers/shared/render_store';
import {PRIMITIVE, Serializer} from '@angular/platform-webworker/src/web_workers/shared/serializer';
import {Serializer, SerializerTypes} from '@angular/platform-webworker/src/web_workers/shared/serializer';
import {ServiceMessageBroker_} from '@angular/platform-webworker/src/web_workers/shared/service_message_broker';
import {createPairedMessageBuses} from './web_worker_test_util';
export function main() {
@ -36,17 +35,20 @@ export function main() {
it('should call registered method with correct arguments',
inject([Serializer], (serializer: Serializer) => {
const broker = new ServiceMessageBroker_(messageBuses.ui, serializer, CHANNEL);
broker.registerMethod(TEST_METHOD, [PRIMITIVE, PRIMITIVE], (arg1, arg2) => {
broker.registerMethod(
TEST_METHOD, [SerializerTypes.PRIMITIVE, SerializerTypes.PRIMITIVE], (arg1, arg2) => {
expect(arg1).toEqual(PASSED_ARG_1);
expect(arg2).toEqual(PASSED_ARG_2);
});
messageBuses.worker.to(CHANNEL).emit(
{'method': TEST_METHOD, 'args': [PASSED_ARG_1, PASSED_ARG_2]});
messageBuses.worker.to(CHANNEL).emit({
'method': TEST_METHOD,
'args': [PASSED_ARG_1, PASSED_ARG_2],
});
}));
it('should return promises to the worker', inject([Serializer], (serializer: Serializer) => {
const broker = new ServiceMessageBroker_(messageBuses.ui, serializer, CHANNEL);
broker.registerMethod(TEST_METHOD, [PRIMITIVE], (arg1) => {
broker.registerMethod(TEST_METHOD, [SerializerTypes.PRIMITIVE], (arg1) => {
expect(arg1).toEqual(PASSED_ARG_1);
return new Promise((res, rej) => {
try {

View File

@ -9,7 +9,7 @@
import {Type} from '@angular/core';
import {UiArguments} from '@angular/platform-webworker/src/web_workers/shared/client_message_broker';
import {MessageBus} from '@angular/platform-webworker/src/web_workers/shared/message_bus';
import {LocationType} from '@angular/platform-webworker/src/web_workers/shared/serialized_types';
import {LocationType, SerializerTypes} from '@angular/platform-webworker/src/web_workers/shared/serializer';
import {WebWorkerPlatformLocation} from '@angular/platform-webworker/src/web_workers/worker/platform_location';
import {MockMessageBrokerFactory, createPairedMessageBuses, expectBrokerCall} from '../shared/web_worker_test_util';
@ -21,13 +21,15 @@ export function main() {
let uiBus: MessageBus = null;
let workerBus: MessageBus = null;
let broker: any = null;
const 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').and.callFake((args: UiArguments, returnType: Type<any>) => {
broker.spy('runOnService')
.and.callFake((args: UiArguments, returnType: Type<any>| SerializerTypes) => {
if (args.method === 'getLocation') {
return Promise.resolve(loc);
}

View File

@ -7,7 +7,7 @@
*/
import {PlatformRef} from '@angular/core';
import {ClientMessageBrokerFactory, FnArg, PRIMITIVE, UiArguments, bootstrapWorkerUi} from '@angular/platform-webworker';
import {ClientMessageBrokerFactory, FnArg, SerializerTypes, UiArguments, bootstrapWorkerUi} from '@angular/platform-webworker';
const ECHO_CHANNEL = 'ECHO';
@ -23,14 +23,10 @@ function afterBootstrap(ref: PlatformRef) {
const val = (<HTMLInputElement>document.getElementById('echo_input')).value;
// TODO(jteplitz602): Replace default constructors with real constructors
// once they're in the .d.ts file (#3926)
const args = new UiArguments('echo');
args.method = 'echo';
const fnArg = new FnArg(val, PRIMITIVE);
fnArg.value = val;
fnArg.type = PRIMITIVE;
args.args = [fnArg];
const fnArg = new FnArg(val);
const args = new UiArguments('echo', [fnArg]);
broker.runOnService(args, PRIMITIVE).then((echo_result: string) => {
broker.runOnService(args, SerializerTypes.PRIMITIVE).then((echo_result: string) => {
document.getElementById('echo_result').innerHTML =
`<span class='response'>${echo_result}</span>`;
});

View File

@ -7,7 +7,7 @@
*/
import {Component} from '@angular/core';
import {PRIMITIVE, ServiceMessageBrokerFactory} from '@angular/platform-webworker';
import {SerializerTypes, ServiceMessageBrokerFactory} from '@angular/platform-webworker';
const ECHO_CHANNEL = 'ECHO';
@ -15,16 +15,9 @@ const ECHO_CHANNEL = 'ECHO';
export class App {
constructor(private _serviceBrokerFactory: ServiceMessageBrokerFactory) {
const broker = _serviceBrokerFactory.createMessageBroker(ECHO_CHANNEL, false);
broker.registerMethod('echo', [PRIMITIVE], this._echo, PRIMITIVE);
broker.registerMethod(
'echo', [SerializerTypes.PRIMITIVE], this._echo, SerializerTypes.PRIMITIVE);
}
private _echo(val: string) {
return new Promise((res, rej) => {
try {
res(val);
} catch (e) {
rej(e);
}
});
}
private _echo(val: string) { return new Promise((res) => res(val)); }
}

View File

@ -3,7 +3,7 @@ export declare function bootstrapWorkerUi(workerScriptUri: string, customProvide
/** @experimental */
export declare abstract class ClientMessageBroker {
abstract runOnService(args: UiArguments, returnType: Type<any>): Promise<any>;
abstract runOnService(args: UiArguments, returnType: Type<any> | SerializerTypes): Promise<any>;
}
/** @experimental */
@ -50,24 +50,23 @@ export declare const platformWorkerUi: (extraProviders?: Provider[]) => Platform
export declare const PRIMITIVE: Type<any>;
/** @experimental */
export declare class ReceivedMessage {
export interface ReceivedMessage {
args: any[];
id: string;
method: string;
type: string;
constructor(data: {
[key: string]: any;
});
}
/** @experimental */
export declare const enum SerializerTypes {
RENDERER_TYPE_V2 = 0,
PRIMITIVE = 1,
RENDER_STORE_OBJECT = 2,
}
/** @experimental */
export declare abstract class ServiceMessageBroker {
abstract registerMethod(methodName: string, signature: Type<any>[], method: Function, returnType?: Type<any>): void;
abstract registerMethod(methodName: string, signature: Array<Type<any> | SerializerTypes>, method: Function, returnType?: Type<any> | SerializerTypes): void;
}
/** @experimental */