feat(platform-webworker): renderer v2 integration
This commit is contained in:
@ -13,6 +13,7 @@ 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 {ReceivedMessage, ServiceMessageBroker, ServiceMessageBrokerFactory} from './web_workers/shared/service_message_broker';
|
||||
export {WORKER_UI_LOCATION_PROVIDERS} from './web_workers/ui/location_providers';
|
||||
@ -21,6 +22,7 @@ export {WorkerAppModule, platformWorkerApp} from './worker_app';
|
||||
export {platformWorkerUi} from './worker_render';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bootstraps the worker ui.
|
||||
*
|
||||
|
@ -17,6 +17,8 @@ export const BrowserDomAdapter: typeof _.BrowserDomAdapter = _.BrowserDomAdapter
|
||||
export const BrowserGetTestability: typeof _.BrowserGetTestability = _.BrowserGetTestability;
|
||||
export const DomRootRenderer: typeof _.DomRootRenderer = _.DomRootRenderer;
|
||||
export const DomRootRenderer_: typeof _.DomRootRenderer_ = _.DomRootRenderer_;
|
||||
export const DomRendererFactoryV2: typeof _.DomRendererFactoryV2 = _.DomRendererFactoryV2;
|
||||
|
||||
export const DomEventsPlugin: typeof _.DomEventsPlugin = _.DomEventsPlugin;
|
||||
export const DomSharedStylesHost: typeof _.DomSharedStylesHost = _.DomSharedStylesHost;
|
||||
export const SharedStylesHost: typeof _.SharedStylesHost = _.SharedStylesHost;
|
||||
|
@ -12,8 +12,10 @@ import {EventEmitter} from '../../facade/async';
|
||||
import {stringify} from '../../facade/lang';
|
||||
|
||||
import {MessageBus} from './message_bus';
|
||||
import {SerializerTypes} from './serialized_types';
|
||||
import {Serializer} from './serializer';
|
||||
|
||||
|
||||
/**
|
||||
* @experimental WebWorker support in Angular is experimental.
|
||||
*/
|
||||
@ -165,7 +167,7 @@ class MessageData {
|
||||
* @experimental WebWorker support in Angular is experimental.
|
||||
*/
|
||||
export class FnArg {
|
||||
constructor(public value: any, public type: Type<any>) {}
|
||||
constructor(public value: any, public type: Type<any>|SerializerTypes = null) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,4 +12,8 @@
|
||||
*/
|
||||
export const RENDERER_CHANNEL = 'ng-Renderer';
|
||||
export const EVENT_CHANNEL = 'ng-Events';
|
||||
|
||||
export const RENDERER_V2_CHANNEL = 'v2.ng-Renderer';
|
||||
export const EVENT_V2_CHANNEL = 'v2.ng-Events';
|
||||
|
||||
export const ROUTER_CHANNEL = 'ng-Router';
|
||||
|
@ -14,3 +14,11 @@ export class LocationType {
|
||||
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,
|
||||
}
|
||||
|
@ -6,12 +6,13 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Injectable, RenderComponentType, Type, ViewEncapsulation} from '@angular/core';
|
||||
import {Injectable, RenderComponentType, RendererTypeV2, Type, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {stringify} from '../../facade/lang';
|
||||
|
||||
import {RenderStore} from './render_store';
|
||||
import {LocationType} from './serialized_types';
|
||||
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.
|
||||
@ -40,45 +41,44 @@ export class Serializer {
|
||||
if (type === RenderComponentType) {
|
||||
return this._serializeRenderComponentType(obj);
|
||||
}
|
||||
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}`);
|
||||
throw new Error(`No serializer for type ${stringify(type)}`);
|
||||
}
|
||||
|
||||
deserialize(map: any, type: any, data?: any): any {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(map)) {
|
||||
return map.map(val => this.deserialize(val, type, data));
|
||||
}
|
||||
|
||||
if (type === PRIMITIVE) {
|
||||
return map;
|
||||
}
|
||||
|
||||
if (type === RenderStoreObject) {
|
||||
return this._renderStore.deserialize(map);
|
||||
}
|
||||
|
||||
if (type === RenderComponentType) {
|
||||
return this._deserializeRenderComponentType(map);
|
||||
}
|
||||
|
||||
if (type === SerializerTypes.RENDERER_TYPE_V2) {
|
||||
return this._deserializeRendererTypeV2(map);
|
||||
}
|
||||
if (type === ViewEncapsulation) {
|
||||
return map as ViewEncapsulation;
|
||||
}
|
||||
|
||||
if (type === LocationType) {
|
||||
return this._deserializeLocation(map);
|
||||
}
|
||||
|
||||
throw new Error('No deserializer for ' + type.toString());
|
||||
throw new Error(`No deserializer for type ${stringify(type)}`);
|
||||
}
|
||||
|
||||
private _serializeLocation(loc: LocationType): Object {
|
||||
@ -101,21 +101,39 @@ export class Serializer {
|
||||
loc['search'], loc['hash'], loc['origin']);
|
||||
}
|
||||
|
||||
private _serializeRenderComponentType(obj: RenderComponentType): Object {
|
||||
private _serializeRenderComponentType(type: RenderComponentType): Object {
|
||||
return {
|
||||
'id': obj.id,
|
||||
'templateUrl': obj.templateUrl,
|
||||
'slotCount': obj.slotCount,
|
||||
'encapsulation': this.serialize(obj.encapsulation, ViewEncapsulation),
|
||||
'styles': this.serialize(obj.styles, PRIMITIVE),
|
||||
'id': type.id,
|
||||
'templateUrl': type.templateUrl,
|
||||
'slotCount': type.slotCount,
|
||||
'encapsulation': this.serialize(type.encapsulation, ViewEncapsulation),
|
||||
'styles': this.serialize(type.styles, PRIMITIVE),
|
||||
};
|
||||
}
|
||||
|
||||
private _deserializeRenderComponentType(map: {[key: string]: any}): RenderComponentType {
|
||||
private _deserializeRenderComponentType(props: {[key: string]: any}): RenderComponentType {
|
||||
return new RenderComponentType(
|
||||
map['id'], map['templateUrl'], map['slotCount'],
|
||||
this.deserialize(map['encapsulation'], ViewEncapsulation),
|
||||
this.deserialize(map['styles'], PRIMITIVE), {});
|
||||
props['id'], props['templateUrl'], props['slotCount'],
|
||||
this.deserialize(props['encapsulation'], ViewEncapsulation),
|
||||
this.deserialize(props['styles'], PRIMITIVE), {});
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
private _deserializeRendererTypeV2(props: {[key: string]: any}): RendererTypeV2 {
|
||||
return {
|
||||
id: props['id'],
|
||||
encapsulation: props['encapsulation'],
|
||||
styles: this.deserialize(props['styles'], PRIMITIVE),
|
||||
data: this.deserialize(props['data'], PRIMITIVE)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,7 @@ export class EventDispatcher {
|
||||
default:
|
||||
throw new Error(eventName + ' not supported on WebWorkers');
|
||||
}
|
||||
|
||||
this._sink.emit({
|
||||
'element': this._serializer.serialize(element, RenderStoreObject),
|
||||
'eventName': eventName,
|
||||
|
@ -6,10 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AnimationPlayer, Injectable, RenderComponentType, Renderer, RootRenderer} from '@angular/core';
|
||||
import {AnimationPlayer, Injectable, RenderComponentType, Renderer, RendererFactoryV2, RendererTypeV2, RendererV2, RootRenderer} from '@angular/core';
|
||||
|
||||
import {MessageBus} from '../shared/message_bus';
|
||||
import {EVENT_CHANNEL, RENDERER_CHANNEL} from '../shared/messaging_api';
|
||||
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 {ServiceMessageBroker, ServiceMessageBrokerFactory} from '../shared/service_message_broker';
|
||||
import {EventDispatcher} from '../ui/event_dispatcher';
|
||||
@ -25,73 +27,39 @@ export class MessageBasedRenderer {
|
||||
|
||||
start(): void {
|
||||
const broker = this._brokerFactory.createMessageBroker(RENDERER_CHANNEL);
|
||||
|
||||
this._bus.initChannel(EVENT_CHANNEL);
|
||||
this._eventDispatcher = new EventDispatcher(this._bus.to(EVENT_CHANNEL), this._serializer);
|
||||
|
||||
broker.registerMethod(
|
||||
'renderComponent', [RenderComponentType, PRIMITIVE], this._renderComponent.bind(this));
|
||||
const [RCT, RSO, P] = [RenderComponentType, RenderStoreObject, PRIMITIVE];
|
||||
|
||||
broker.registerMethod(
|
||||
'selectRootElement', [RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._selectRootElement.bind(this));
|
||||
broker.registerMethod(
|
||||
'createElement', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._createElement.bind(this));
|
||||
broker.registerMethod(
|
||||
'createViewRoot', [RenderStoreObject, RenderStoreObject, PRIMITIVE],
|
||||
this._createViewRoot.bind(this));
|
||||
broker.registerMethod(
|
||||
'createTemplateAnchor', [RenderStoreObject, RenderStoreObject, PRIMITIVE],
|
||||
this._createTemplateAnchor.bind(this));
|
||||
broker.registerMethod(
|
||||
'createText', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._createText.bind(this));
|
||||
broker.registerMethod(
|
||||
'projectNodes', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
|
||||
this._projectNodes.bind(this));
|
||||
broker.registerMethod(
|
||||
'attachViewAfter', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
|
||||
this._attachViewAfter.bind(this));
|
||||
broker.registerMethod(
|
||||
'detachView', [RenderStoreObject, RenderStoreObject], this._detachView.bind(this));
|
||||
broker.registerMethod(
|
||||
'destroyView', [RenderStoreObject, RenderStoreObject, RenderStoreObject],
|
||||
this._destroyView.bind(this));
|
||||
broker.registerMethod(
|
||||
'setElementProperty', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._setElementProperty.bind(this));
|
||||
broker.registerMethod(
|
||||
'setElementAttribute', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._setElementAttribute.bind(this));
|
||||
broker.registerMethod(
|
||||
'setBindingDebugInfo', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._setBindingDebugInfo.bind(this));
|
||||
broker.registerMethod(
|
||||
'setElementClass', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._setElementClass.bind(this));
|
||||
broker.registerMethod(
|
||||
'setElementStyle', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._setElementStyle.bind(this));
|
||||
broker.registerMethod(
|
||||
'invokeElementMethod', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._invokeElementMethod.bind(this));
|
||||
broker.registerMethod(
|
||||
'setText', [RenderStoreObject, RenderStoreObject, PRIMITIVE], this._setText.bind(this));
|
||||
broker.registerMethod(
|
||||
'listen', [RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE],
|
||||
this._listen.bind(this));
|
||||
broker.registerMethod(
|
||||
'listenGlobal', [RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE],
|
||||
this._listenGlobal.bind(this));
|
||||
broker.registerMethod(
|
||||
'listenDone', [RenderStoreObject, RenderStoreObject], this._listenDone.bind(this));
|
||||
broker.registerMethod(
|
||||
'animate',
|
||||
[
|
||||
RenderStoreObject, RenderStoreObject, PRIMITIVE, PRIMITIVE, PRIMITIVE, PRIMITIVE,
|
||||
PRIMITIVE, PRIMITIVE, PRIMITIVE
|
||||
],
|
||||
this._animate.bind(this));
|
||||
const methods: any[][] = [
|
||||
['renderComponent', this._renderComponent, RCT, P],
|
||||
['selectRootElement', this._selectRootElement, RSO, P, P],
|
||||
['createElement', this._createElement, RSO, RSO, P, P],
|
||||
['createViewRoot', this._createViewRoot, RSO, RSO, P],
|
||||
['createTemplateAnchor', this._createTemplateAnchor, RSO, RSO, P],
|
||||
['createText', this._createText, RSO, RSO, P, P],
|
||||
['projectNodes', this._projectNodes, RSO, RSO, RSO],
|
||||
['attachViewAfter', this._attachViewAfter, RSO, RSO, RSO],
|
||||
['detachView', this._detachView, RSO, RSO],
|
||||
['destroyView', this._destroyView, RSO, RSO, RSO],
|
||||
['setElementProperty', this._setElementProperty, RSO, RSO, P, P],
|
||||
['setElementAttribute', this._setElementAttribute, RSO, RSO, P, P],
|
||||
['setBindingDebugInfo', this._setBindingDebugInfo, RSO, RSO, P, P],
|
||||
['setElementClass', this._setElementClass, RSO, RSO, P, P],
|
||||
['setElementStyle', this._setElementStyle, RSO, RSO, P, P],
|
||||
['invokeElementMethod', this._invokeElementMethod, RSO, RSO, P, P],
|
||||
['setText', this._setText, RSO, RSO, P],
|
||||
['listen', this._listen, RSO, RSO, P, P],
|
||||
['listenGlobal', this._listenGlobal, RSO, P, P, P],
|
||||
['listenDone', this._listenDone, RSO, RSO],
|
||||
['animate', this._animate, RSO, RSO, P, P, P, P, P, P, P],
|
||||
];
|
||||
|
||||
methods.forEach(([name, method, ...argTypes]: any[]) => {
|
||||
broker.registerMethod(name, argTypes, method.bind(this));
|
||||
});
|
||||
|
||||
this._bindAnimationPlayerMethods(broker);
|
||||
}
|
||||
@ -270,3 +238,124 @@ export class MessageBasedRenderer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class MessageBasedRendererV2 {
|
||||
private _eventDispatcher: EventDispatcher;
|
||||
|
||||
constructor(
|
||||
private _brokerFactory: ServiceMessageBrokerFactory, private _bus: MessageBus,
|
||||
private _serializer: Serializer, private _renderStore: RenderStore,
|
||||
private _rendererFactory: RendererFactoryV2) {}
|
||||
|
||||
start(): void {
|
||||
const broker = this._brokerFactory.createMessageBroker(RENDERER_V2_CHANNEL);
|
||||
|
||||
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 methods: any[][] = [
|
||||
['createRenderer', this.createRenderer, RSO, CRT, P],
|
||||
['createElement', this.createElement, RSO, P, P, P],
|
||||
['createComment', this.createComment, RSO, P, P],
|
||||
['createText', this.createText, RSO, P, P],
|
||||
['appendChild', this.appendChild, RSO, RSO, RSO],
|
||||
['insertBefore', this.insertBefore, RSO, RSO, RSO, RSO],
|
||||
['removeChild', this.removeChild, RSO, RSO, RSO],
|
||||
['selectRootElement', this.selectRootElement, RSO, P, P],
|
||||
['parentNode', this.parentNode, RSO, RSO, P],
|
||||
['nextSibling', this.nextSibling, RSO, RSO, P],
|
||||
['setAttribute', this.setAttribute, RSO, RSO, P, P, P],
|
||||
['removeAttribute', this.removeAttribute, RSO, RSO, P, P],
|
||||
['addClass', this.addClass, RSO, RSO, P],
|
||||
['removeClass', this.removeClass, RSO, RSO, P],
|
||||
['setStyle', this.setStyle, RSO, RSO, P, P, P, P],
|
||||
['removeStyle', this.removeStyle, RSO, RSO, P, P],
|
||||
['setProperty', this.setProperty, RSO, RSO, P, P],
|
||||
['setValue', this.setValue, RSO, RSO, P],
|
||||
['listen', this.listen, RSO, RSO, P, P, P],
|
||||
['unlisten', this.unlisten, RSO, RSO],
|
||||
];
|
||||
|
||||
methods.forEach(([name, method, ...argTypes]: any[]) => {
|
||||
broker.registerMethod(name, argTypes, method.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
private createRenderer(el: any, type: RendererTypeV2, id: number) {
|
||||
this._renderStore.store(this._rendererFactory.createRenderer(el, type), id);
|
||||
}
|
||||
|
||||
private createElement(r: RendererV2, name: string, namespace: string, id: number) {
|
||||
this._renderStore.store(r.createElement(name, namespace), id);
|
||||
}
|
||||
|
||||
private createComment(r: RendererV2, value: string, id: number) {
|
||||
this._renderStore.store(r.createComment(value), id);
|
||||
}
|
||||
|
||||
private createText(r: RendererV2, value: string, id: number) {
|
||||
this._renderStore.store(r.createText(value), id);
|
||||
}
|
||||
|
||||
private appendChild(r: RendererV2, parent: any, child: any) { r.appendChild(parent, child); }
|
||||
|
||||
private insertBefore(r: RendererV2, parent: any, child: any, ref: any) {
|
||||
r.insertBefore(parent, child, ref);
|
||||
}
|
||||
|
||||
private removeChild(r: RendererV2, parent: any, child: any) { r.removeChild(parent, child); }
|
||||
|
||||
private selectRootElement(r: RendererV2, selector: string, id: number) {
|
||||
this._renderStore.store(r.selectRootElement(selector), id);
|
||||
}
|
||||
|
||||
private parentNode(r: RendererV2, node: any, id: number) {
|
||||
this._renderStore.store(r.parentNode(node), id);
|
||||
}
|
||||
|
||||
private nextSibling(r: RendererV2, node: any, id: number) {
|
||||
this._renderStore.store(r.nextSibling(node), id);
|
||||
}
|
||||
|
||||
private setAttribute(r: RendererV2, el: any, name: string, value: string, namespace: string) {
|
||||
r.setAttribute(el, name, value, namespace);
|
||||
}
|
||||
|
||||
private removeAttribute(r: RendererV2, el: any, name: string, namespace: string) {
|
||||
r.removeAttribute(el, name, namespace);
|
||||
}
|
||||
|
||||
private addClass(r: RendererV2, el: any, name: string) { r.addClass(el, name); }
|
||||
|
||||
private removeClass(r: RendererV2, el: any, name: string) { r.removeClass(el, name); }
|
||||
|
||||
private setStyle(
|
||||
r: RendererV2, el: any, style: string, value: any, hasVendorPrefix: boolean,
|
||||
hasImportant: boolean) {
|
||||
r.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
||||
}
|
||||
|
||||
private removeStyle(r: RendererV2, el: any, style: string, hasVendorPrefix: boolean) {
|
||||
r.removeStyle(el, style, hasVendorPrefix);
|
||||
}
|
||||
|
||||
private setProperty(r: RendererV2, el: any, name: string, value: any) {
|
||||
r.setProperty(el, name, value);
|
||||
}
|
||||
|
||||
private setValue(r: RendererV2, node: any, value: string) { r.setValue(node, value); }
|
||||
|
||||
private listen(r: RendererV2, el: any, elName: string, eventName: string, unlistenId: number) {
|
||||
const listener = (event: any) => {
|
||||
return this._eventDispatcher.dispatchRenderEvent(el, elName, eventName, event);
|
||||
};
|
||||
|
||||
const unlisten = r.listen(el || elName, eventName, listener);
|
||||
this._renderStore.store(unlisten, unlistenId);
|
||||
}
|
||||
|
||||
private unlisten(r: RendererV2, unlisten: () => boolean) { unlisten(); }
|
||||
}
|
||||
|
@ -1,13 +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
|
||||
*/
|
||||
// no deserialization is necessary in TS.
|
||||
// This is only here to match dart interface
|
||||
export function deserializeGenericEvent(serializedEvent: {[key: string]: any}):
|
||||
{[key: string]: any} {
|
||||
return serializedEvent;
|
||||
}
|
@ -7,10 +7,11 @@
|
||||
*/
|
||||
|
||||
import {PlatformLocation} from '@angular/common';
|
||||
import {APP_INITIALIZER, NgZone} from '@angular/core';
|
||||
import {APP_INITIALIZER, InjectionToken, NgZone} from '@angular/core';
|
||||
|
||||
import {WebWorkerPlatformLocation} from './platform_location';
|
||||
|
||||
|
||||
/**
|
||||
* Those providers should be added when the router is used in a worker context in addition to the
|
||||
* {@link ROUTER_PROVIDERS} and after them.
|
||||
@ -22,7 +23,7 @@ export const WORKER_APP_LOCATION_PROVIDERS = [
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: appInitFnFactory,
|
||||
multi: true,
|
||||
deps: [PlatformLocation, NgZone]
|
||||
deps: [PlatformLocation, NgZone],
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -16,8 +16,6 @@ import {ROUTER_CHANNEL} from '../shared/messaging_api';
|
||||
import {LocationType} from '../shared/serialized_types';
|
||||
import {PRIMITIVE, Serializer} from '../shared/serializer';
|
||||
|
||||
import {deserializeGenericEvent} from './event_deserializer';
|
||||
|
||||
@Injectable()
|
||||
export class WebWorkerPlatformLocation extends PlatformLocation {
|
||||
private _broker: ClientMessageBroker;
|
||||
@ -44,10 +42,9 @@ export class WebWorkerPlatformLocation extends PlatformLocation {
|
||||
}
|
||||
|
||||
if (listeners) {
|
||||
const 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));
|
||||
listeners.forEach((fn: Function) => fn(msg['event']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,24 +6,23 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Injectable, RenderComponentType, Renderer, RootRenderer, ViewEncapsulation} from '@angular/core';
|
||||
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 {ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
|
||||
import {ClientMessageBroker, ClientMessageBrokerFactory, FnArg, UiArguments} from '../shared/client_message_broker';
|
||||
import {MessageBus} from '../shared/message_bus';
|
||||
import {EVENT_CHANNEL, RENDERER_CHANNEL} from '../shared/messaging_api';
|
||||
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 {deserializeGenericEvent} from './event_deserializer';
|
||||
|
||||
@Injectable()
|
||||
export class WebWorkerRootRenderer implements RootRenderer {
|
||||
globalEvents = new NamedEventEmitter();
|
||||
|
||||
private _messageBroker: ClientMessageBroker;
|
||||
public globalEvents: NamedEventEmitter = new NamedEventEmitter();
|
||||
private _componentRenderers: Map<string, WebWorkerRenderer> =
|
||||
new Map<string, WebWorkerRenderer>();
|
||||
private _componentRenderers = new Map<string, WebWorkerRenderer>();
|
||||
|
||||
constructor(
|
||||
messageBrokerFactory: ClientMessageBrokerFactory, bus: MessageBus,
|
||||
@ -46,7 +45,7 @@ export class WebWorkerRootRenderer implements RootRenderer {
|
||||
} else {
|
||||
const eventName = message['eventName'];
|
||||
const target = message['eventTarget'];
|
||||
const event = deserializeGenericEvent(message['event']);
|
||||
const event = message['event'];
|
||||
if (target) {
|
||||
this.globalEvents.dispatchEvent(eventNameWithTarget(target, eventName), event);
|
||||
} else {
|
||||
@ -259,21 +258,13 @@ export class WebWorkerRenderer implements Renderer, RenderStoreObject {
|
||||
}
|
||||
}
|
||||
|
||||
function eventNameWithTarget(target: string, eventName: string): string {
|
||||
return `${target}:${eventName}`;
|
||||
}
|
||||
|
||||
export class NamedEventEmitter {
|
||||
private _listeners: Map<string, Function[]>;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
listen(eventName: string, callback: Function) { this._getListeners(eventName).push(callback); }
|
||||
|
||||
unlisten(eventName: string, callback: Function) {
|
||||
@ -286,6 +277,271 @@ export class NamedEventEmitter {
|
||||
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;
|
||||
|
||||
constructor(
|
||||
messageBrokerFactory: ClientMessageBrokerFactory, bus: MessageBus,
|
||||
private _serializer: Serializer, public renderStore: RenderStore) {
|
||||
this._messageBroker = messageBrokerFactory.createMessageBroker(RENDERER_V2_CHANNEL);
|
||||
bus.initChannel(EVENT_V2_CHANNEL);
|
||||
const source = bus.from(EVENT_V2_CHANNEL);
|
||||
source.subscribe({next: (message: any) => this._dispatchEvent(message)});
|
||||
}
|
||||
|
||||
createRenderer(element: any, type: RendererTypeV2): RendererV2 {
|
||||
const renderer = new WebWorkerRendererV2(this);
|
||||
|
||||
const id = this.renderStore.allocateId();
|
||||
this.renderStore.store(renderer, id);
|
||||
this.callUI('createRenderer', [
|
||||
new FnArg(element, RenderStoreObject),
|
||||
new FnArg(type, SerializerTypes.RENDERER_TYPE_V2),
|
||||
new FnArg(renderer, RenderStoreObject),
|
||||
]);
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
callUI(fnName: string, fnArgs: FnArg[]) {
|
||||
const args = new UiArguments(fnName, fnArgs);
|
||||
this._messageBroker.runOnService(args, null);
|
||||
}
|
||||
|
||||
allocateNode(): WebWorkerRenderNode {
|
||||
const result = new WebWorkerRenderNode();
|
||||
const id = this.renderStore.allocateId();
|
||||
this.renderStore.store(result, id);
|
||||
return result;
|
||||
}
|
||||
|
||||
allocateId(): number { return this.renderStore.allocateId(); }
|
||||
|
||||
private _dispatchEvent(message: {[key: string]: any}): void {
|
||||
const element: WebWorkerRenderNode =
|
||||
this._serializer.deserialize(message['element'], RenderStoreObject);
|
||||
|
||||
const eventName = message['eventName'];
|
||||
const target = message['eventTarget'];
|
||||
const event = message['event'];
|
||||
|
||||
if (target) {
|
||||
globalEvents.dispatchEvent(eventNameWithTarget(target, eventName), event);
|
||||
} else {
|
||||
element.events.dispatchEvent(eventName, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class WebWorkerRendererV2 implements RendererV2 {
|
||||
constructor(private _rendererFactory: WebWorkerRendererFactoryV2) {}
|
||||
destroyNode: (node: any) => void | null = null;
|
||||
|
||||
private asFnArg = new FnArg(this, RenderStoreObject);
|
||||
|
||||
// TODO(vicb): destroy the allocated nodes
|
||||
destroy(): void { this.callUIWithRenderer('destroy'); }
|
||||
|
||||
createElement(name: string, namespace?: string): any {
|
||||
const node = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('createElement', [
|
||||
new FnArg(name),
|
||||
new FnArg(namespace),
|
||||
new FnArg(node, RenderStoreObject),
|
||||
]);
|
||||
return node;
|
||||
}
|
||||
|
||||
createComment(value: string): any {
|
||||
const node = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('createComment', [
|
||||
new FnArg(value),
|
||||
new FnArg(node, RenderStoreObject),
|
||||
]);
|
||||
return node;
|
||||
}
|
||||
|
||||
createText(value: string): any {
|
||||
const node = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('createText', [
|
||||
new FnArg(value),
|
||||
new FnArg(node, RenderStoreObject),
|
||||
]);
|
||||
return node;
|
||||
}
|
||||
|
||||
appendChild(parent: any, newChild: any): void {
|
||||
this.callUIWithRenderer('appendChild', [
|
||||
new FnArg(parent, RenderStoreObject),
|
||||
new FnArg(newChild, RenderStoreObject),
|
||||
]);
|
||||
}
|
||||
|
||||
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.callUIWithRenderer('insertBefore', [
|
||||
new FnArg(parent, RenderStoreObject),
|
||||
new FnArg(newChild, RenderStoreObject),
|
||||
new FnArg(refChild, RenderStoreObject),
|
||||
]);
|
||||
}
|
||||
|
||||
removeChild(parent: any, oldChild: any): void {
|
||||
this.callUIWithRenderer('removeChild', [
|
||||
new FnArg(parent, RenderStoreObject),
|
||||
new FnArg(oldChild, RenderStoreObject),
|
||||
]);
|
||||
}
|
||||
|
||||
selectRootElement(selectorOrNode: string|any): any {
|
||||
const node = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('selectRootElement', [
|
||||
new FnArg(selectorOrNode),
|
||||
new FnArg(node, RenderStoreObject),
|
||||
]);
|
||||
return node;
|
||||
}
|
||||
|
||||
parentNode(node: any): any {
|
||||
const res = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('parentNode', [
|
||||
new FnArg(node, RenderStoreObject),
|
||||
new FnArg(res, RenderStoreObject),
|
||||
]);
|
||||
return res;
|
||||
}
|
||||
|
||||
nextSibling(node: any): any {
|
||||
const res = this._rendererFactory.allocateNode();
|
||||
this.callUIWithRenderer('nextSibling', [
|
||||
new FnArg(node, RenderStoreObject),
|
||||
new FnArg(res, RenderStoreObject),
|
||||
]);
|
||||
return res;
|
||||
}
|
||||
|
||||
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
||||
this.callUIWithRenderer('setAttribute', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(name),
|
||||
new FnArg(value),
|
||||
new FnArg(namespace),
|
||||
]);
|
||||
}
|
||||
|
||||
removeAttribute(el: any, name: string, namespace?: string): void {
|
||||
this.callUIWithRenderer('removeAttribute', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(name),
|
||||
new FnArg(namespace),
|
||||
]);
|
||||
}
|
||||
|
||||
addClass(el: any, name: string): void {
|
||||
this.callUIWithRenderer('addClass', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(name),
|
||||
]);
|
||||
}
|
||||
|
||||
removeClass(el: any, name: string): void {
|
||||
this.callUIWithRenderer('removeClass', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(name),
|
||||
]);
|
||||
}
|
||||
|
||||
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
|
||||
void {
|
||||
this.callUIWithRenderer('setStyle', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(style),
|
||||
new FnArg(value),
|
||||
new FnArg(hasVendorPrefix),
|
||||
new FnArg(hasImportant),
|
||||
]);
|
||||
}
|
||||
|
||||
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
|
||||
this.callUIWithRenderer('removeStyle', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(style),
|
||||
new FnArg(hasVendorPrefix),
|
||||
]);
|
||||
}
|
||||
|
||||
setProperty(el: any, name: string, value: any): void {
|
||||
this.callUIWithRenderer('setProperty', [
|
||||
new FnArg(el, RenderStoreObject),
|
||||
new FnArg(name),
|
||||
new FnArg(value),
|
||||
]);
|
||||
}
|
||||
|
||||
setValue(node: any, value: string): void {
|
||||
this.callUIWithRenderer('setValue', [
|
||||
new FnArg(node, RenderStoreObject),
|
||||
new FnArg(value),
|
||||
]);
|
||||
}
|
||||
|
||||
listen(
|
||||
target: 'window'|'document'|'body'|any, eventName: string,
|
||||
listener: (event: any) => boolean): () => void {
|
||||
const unlistenId = this._rendererFactory.allocateId();
|
||||
|
||||
const [targetEl, targetName, fullName]: [any, string, string] = typeof target === 'string' ?
|
||||
[null, target, `${target}:${eventName}`] :
|
||||
[target, null, null];
|
||||
|
||||
if (fullName) {
|
||||
globalEvents.listen(fullName, listener);
|
||||
} else {
|
||||
targetEl.events.listen(eventName, listener);
|
||||
}
|
||||
|
||||
this.callUIWithRenderer('listen', [
|
||||
new FnArg(targetEl, RenderStoreObject),
|
||||
new FnArg(targetName),
|
||||
new FnArg(eventName),
|
||||
new FnArg(unlistenId),
|
||||
]);
|
||||
|
||||
return () => {
|
||||
if (fullName) {
|
||||
globalEvents.unlisten(fullName, listener);
|
||||
} else {
|
||||
targetEl.events.unlisten(eventName, listener);
|
||||
}
|
||||
this.callUIWithRenderer('unlisten', [new FnArg(unlistenId)]);
|
||||
};
|
||||
}
|
||||
|
||||
private callUIWithRenderer(fnName: string, fnArgs: FnArg[] = []) {
|
||||
// always pass the renderer as the first arg
|
||||
this._rendererFactory.callUI(fnName, [this.asFnArg, ...fnArgs]);
|
||||
}
|
||||
}
|
||||
|
||||
export class AnimationPlayerEmitter {
|
||||
@ -320,10 +576,6 @@ export class AnimationPlayerEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function eventNameWithTarget(target: string, eventName: string): string {
|
||||
return `${target}:${eventName}`;
|
||||
}
|
||||
|
||||
export class WebWorkerRenderNode {
|
||||
events = new NamedEventEmitter();
|
||||
animationPlayerEvents = new AnimationPlayerEmitter();
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {APP_INITIALIZER, ApplicationModule, ErrorHandler, NgModule, NgZone, PlatformRef, Provider, RootRenderer, createPlatformFactory, platformCore} from '@angular/core';
|
||||
import {APP_INITIALIZER, ApplicationModule, ErrorHandler, NgModule, NgZone, PlatformRef, Provider, RendererFactoryV2, RootRenderer, createPlatformFactory, platformCore} from '@angular/core';
|
||||
import {DOCUMENT} from '@angular/platform-browser';
|
||||
|
||||
import {BROWSER_SANITIZATION_PROVIDERS} from './private_import_platform-browser';
|
||||
@ -18,7 +18,7 @@ import {PostMessageBus, PostMessageBusSink, PostMessageBusSource} from './web_wo
|
||||
import {RenderStore} from './web_workers/shared/render_store';
|
||||
import {Serializer} from './web_workers/shared/serializer';
|
||||
import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_workers/shared/service_message_broker';
|
||||
import {WebWorkerRootRenderer} from './web_workers/worker/renderer';
|
||||
import {WebWorkerRendererFactoryV2, WebWorkerRootRenderer} from './web_workers/worker/renderer';
|
||||
import {WorkerDomAdapter} from './web_workers/worker/worker_adapter';
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ const _postMessage = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export function createMessageBus(zone: NgZone): MessageBus {
|
||||
const sink = new PostMessageBusSink(_postMessage);
|
||||
const source = new PostMessageBusSource();
|
||||
@ -49,7 +48,6 @@ export function createMessageBus(zone: NgZone): MessageBus {
|
||||
return bus;
|
||||
}
|
||||
|
||||
|
||||
export function setupWebWorker(): void {
|
||||
WorkerDomAdapter.makeCurrent();
|
||||
}
|
||||
@ -68,6 +66,8 @@ export function setupWebWorker(): void {
|
||||
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
|
||||
WebWorkerRootRenderer,
|
||||
{provide: RootRenderer, useExisting: WebWorkerRootRenderer},
|
||||
WebWorkerRendererFactoryV2,
|
||||
{provide: RendererFactoryV2, useExisting: WebWorkerRendererFactoryV2},
|
||||
{provide: ON_WEB_WORKER, useValue: true},
|
||||
RenderStore,
|
||||
{provide: ErrorHandler, useFactory: errorHandler, deps: []},
|
||||
|
@ -6,11 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ErrorHandler, Injectable, InjectionToken, Injector, NgZone, PLATFORM_INITIALIZER, PlatformRef, Provider, RootRenderer, Testability, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
|
||||
import {ErrorHandler, Injectable, InjectionToken, Injector, NgZone, PLATFORM_INITIALIZER, PlatformRef, Provider, RendererFactoryV2, RootRenderer, Testability, createPlatformFactory, isDevMode, platformCore} from '@angular/core';
|
||||
import {AnimationDriver, DOCUMENT, EVENT_MANAGER_PLUGINS, EventManager, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from '@angular/platform-browser';
|
||||
|
||||
import {APP_ID_RANDOM_PROVIDER} from './private_import_core';
|
||||
import {BROWSER_SANITIZATION_PROVIDERS, BrowserDomAdapter, BrowserGetTestability, DomEventsPlugin, DomRootRenderer, DomRootRenderer_, DomSharedStylesHost, HammerGesturesPlugin, KeyEventsPlugin, SharedStylesHost, WebAnimationsDriver, getDOM} from './private_import_platform-browser';
|
||||
import {BROWSER_SANITIZATION_PROVIDERS, BrowserDomAdapter, BrowserGetTestability, DomEventsPlugin, DomRendererFactoryV2, DomRootRenderer, DomRootRenderer_, DomSharedStylesHost, HammerGesturesPlugin, KeyEventsPlugin, SharedStylesHost, WebAnimationsDriver, getDOM} from './private_import_platform-browser';
|
||||
import {ON_WEB_WORKER} from './web_workers/shared/api';
|
||||
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from './web_workers/shared/client_message_broker';
|
||||
import {MessageBus} from './web_workers/shared/message_bus';
|
||||
@ -20,8 +20,6 @@ import {Serializer} from './web_workers/shared/serializer';
|
||||
import {ServiceMessageBrokerFactory, ServiceMessageBrokerFactory_} from './web_workers/shared/service_message_broker';
|
||||
import {MessageBasedRenderer} from './web_workers/ui/renderer';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper class that exposes the Worker
|
||||
* and underlying {@link MessageBus} for lower level message passing.
|
||||
@ -71,6 +69,8 @@ export const _WORKER_UI_PLATFORM_PROVIDERS: Provider[] = [
|
||||
APP_ID_RANDOM_PROVIDER,
|
||||
{provide: DomRootRenderer, useClass: DomRootRenderer_},
|
||||
{provide: RootRenderer, useExisting: DomRootRenderer},
|
||||
DomRendererFactoryV2,
|
||||
{provide: RendererFactoryV2, useExisting: DomRendererFactoryV2},
|
||||
{provide: SharedStylesHost, useExisting: DomSharedStylesHost},
|
||||
{provide: ServiceMessageBrokerFactory, useClass: ServiceMessageBrokerFactory_},
|
||||
{provide: ClientMessageBrokerFactory, useClass: ClientMessageBrokerFactory_},
|
||||
|
Reference in New Issue
Block a user