feat(platform-webworker): renderer v2 integration
This commit is contained in:
parent
f38dbfbd64
commit
3517f28609
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
// This file is not used to build this module. It is only used during editing
|
||||
// by the TypeScript language serivce and during build for verifcation. `ngc`
|
||||
// by the TypeScript language service and during build for verification. `ngc`
|
||||
// replaces this file with production index.ts when it rewrites private symbol
|
||||
// names.
|
||||
|
||||
|
|
|
@ -344,23 +344,6 @@ export function splitNamespace(name: string): string[] {
|
|||
}
|
||||
|
||||
|
||||
let attrCache: Map<string, Attr>;
|
||||
|
||||
function createAttributeNode(name: string): Attr {
|
||||
if (!attrCache) {
|
||||
attrCache = new Map<string, Attr>();
|
||||
}
|
||||
if (attrCache.has(name)) {
|
||||
return attrCache.get(name);
|
||||
}
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<div ${name}>`;
|
||||
const attr: Attr = div.firstChild.attributes[0];
|
||||
attrCache.set(name, attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DomRendererFactoryV2 implements RendererFactoryV2 {
|
||||
private rendererByCompId = new Map<string, RendererV2>();
|
||||
|
|
|
@ -33,8 +33,8 @@ export const __platform_browser_private__: {
|
|||
setRootDomAdapter: typeof dom_adapter.setRootDomAdapter,
|
||||
_DomRootRenderer?: dom_renderer.DomRootRenderer,
|
||||
DomRootRenderer: typeof dom_renderer.DomRootRenderer,
|
||||
_DomRootRenderer_?: dom_renderer.DomRootRenderer,
|
||||
DomRootRenderer_: typeof dom_renderer.DomRootRenderer_,
|
||||
DomRendererFactoryV2: typeof dom_renderer.DomRendererFactoryV2,
|
||||
NAMESPACE_URIS: typeof dom_renderer.NAMESPACE_URIS,
|
||||
shimContentAttribute: typeof dom_renderer.shimContentAttribute,
|
||||
shimHostAttribute: typeof dom_renderer.shimHostAttribute,
|
||||
|
@ -64,6 +64,7 @@ export const __platform_browser_private__: {
|
|||
setRootDomAdapter: dom_adapter.setRootDomAdapter,
|
||||
DomRootRenderer_: dom_renderer.DomRootRenderer_,
|
||||
DomRootRenderer: dom_renderer.DomRootRenderer,
|
||||
DomRendererFactoryV2: dom_renderer.DomRendererFactoryV2,
|
||||
NAMESPACE_URIS: dom_renderer.NAMESPACE_URIS,
|
||||
shimContentAttribute: dom_renderer.shimContentAttribute,
|
||||
shimHostAttribute: dom_renderer.shimHostAttribute,
|
||||
|
|
|
@ -74,8 +74,7 @@ export class BrowserDetection {
|
|||
|
||||
BrowserDetection.setup();
|
||||
|
||||
export function dispatchEvent(
|
||||
element: any /** TODO #9100 */, eventType: any /** TODO #9100 */): void {
|
||||
export function dispatchEvent(element: any, eventType: any): void {
|
||||
getDOM().dispatchEvent(element, getDOM().createEvent(eventType));
|
||||
}
|
||||
|
||||
|
|
|
@ -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_},
|
||||
|
|
|
@ -42,7 +42,7 @@ export function createPairedMessageBuses(): PairedMessageBuses {
|
|||
export function expectBrokerCall(
|
||||
broker: SpyMessageBroker, methodName: string, vals?: Array<any>,
|
||||
handler?: (..._: any[]) => Promise<any>| void): void {
|
||||
broker.spy('runOnService').and.callFake((args: UiArguments, returnType: Type<any>) => {
|
||||
broker.spy('callUI').and.callFake((args: UiArguments, returnType: Type<any>) => {
|
||||
expect(args.method).toEqual(methodName);
|
||||
if (isPresent(vals)) {
|
||||
expect(args.args.length).toEqual(vals.length);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
import {Type} from '@angular/core';
|
||||
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/testing_internal';
|
||||
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';
|
||||
|
@ -75,16 +74,15 @@ export function main() {
|
|||
expect(() => platformLocation.pathname = 'TEST').toThrowError();
|
||||
});
|
||||
|
||||
it('should send pathname to render thread',
|
||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||
const platformLocation = createWebWorkerPlatformLocation(TEST_LOCATION);
|
||||
platformLocation.init().then((_) => {
|
||||
const PATHNAME = '/test';
|
||||
expectBrokerCall(broker, 'setPathname', [PATHNAME]);
|
||||
platformLocation.pathname = PATHNAME;
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
it('should send pathname to render thread', done => {
|
||||
const platformLocation = createWebWorkerPlatformLocation(TEST_LOCATION);
|
||||
platformLocation.init().then((_) => {
|
||||
const PATHNAME = '/test';
|
||||
expectBrokerCall(broker, 'setPathname', [PATHNAME]);
|
||||
platformLocation.pathname = PATHNAME;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should send pushState to render thread', () => { testPushOrReplaceState(true); });
|
||||
|
||||
|
|
|
@ -6,23 +6,23 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, ComponentRef, Injectable} from '@angular/core';
|
||||
import {Component, ComponentRef} from '@angular/core';
|
||||
import {DebugDomRootRenderer} from '@angular/core/src/debug/debug_renderer';
|
||||
import {RootRenderer} from '@angular/core/src/render/api';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {DomRootRenderer, DomRootRenderer_} from '@angular/platform-browser/src/dom/dom_renderer';
|
||||
import {BrowserTestingModule} from '@angular/platform-browser/testing';
|
||||
import {dispatchEvent} from '@angular/platform-browser/testing/browser_util';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from '@angular/platform-webworker/src/web_workers/shared/client_message_broker';
|
||||
import {RenderStore} from '@angular/platform-webworker/src/web_workers/shared/render_store';
|
||||
import {Serializer} from '@angular/platform-webworker/src/web_workers/shared/serializer';
|
||||
import {ServiceMessageBrokerFactory_} from '@angular/platform-webworker/src/web_workers/shared/service_message_broker';
|
||||
import {MessageBasedRenderer} from '@angular/platform-webworker/src/web_workers/ui/renderer';
|
||||
import {WebWorkerRootRenderer} from '@angular/platform-webworker/src/web_workers/worker/renderer';
|
||||
|
||||
import {platformBrowserDynamicTesting} from '../../../../platform-browser-dynamic/testing';
|
||||
import {dispatchEvent} from '../../../../platform-browser/testing/browser_util';
|
||||
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from '../../../src/web_workers/shared/client_message_broker';
|
||||
import {RenderStore} from '../../../src/web_workers/shared/render_store';
|
||||
import {Serializer} from '../../../src/web_workers/shared/serializer';
|
||||
import {ServiceMessageBrokerFactory_} from '../../../src/web_workers/shared/service_message_broker';
|
||||
import {MessageBasedRenderer} from '../../../src/web_workers/ui/renderer';
|
||||
import {WebWorkerRootRenderer} from '../../../src/web_workers/worker/renderer';
|
||||
import {PairedMessageBuses, createPairedMessageBuses} from '../shared/web_worker_test_util';
|
||||
|
||||
export function main() {
|
||||
|
@ -70,19 +70,23 @@ export function main() {
|
|||
testUiInjector.ngModule = BrowserTestingModule;
|
||||
testUiInjector.configureTestingModule({
|
||||
providers: [
|
||||
Serializer, {provide: RenderStore, useValue: uiRenderStore},
|
||||
Serializer,
|
||||
{provide: RenderStore, useValue: uiRenderStore},
|
||||
{provide: DomRootRenderer, useClass: DomRootRenderer_},
|
||||
{provide: RootRenderer, useExisting: DomRootRenderer}
|
||||
{provide: RootRenderer, useExisting: DomRootRenderer},
|
||||
]
|
||||
});
|
||||
const uiSerializer = testUiInjector.get(Serializer);
|
||||
const domRootRenderer = testUiInjector.get(DomRootRenderer);
|
||||
|
||||
workerRenderStore = new RenderStore();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MyComp2],
|
||||
providers: [
|
||||
Serializer, {provide: RenderStore, useValue: workerRenderStore}, {
|
||||
Serializer,
|
||||
{provide: RenderStore, useValue: workerRenderStore},
|
||||
{
|
||||
provide: RootRenderer,
|
||||
useFactory: (workerSerializer: Serializer) => {
|
||||
return createWorkerRenderer(
|
||||
|
@ -90,12 +94,12 @@ export function main() {
|
|||
workerRenderStore);
|
||||
},
|
||||
deps: [Serializer]
|
||||
}
|
||||
},
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
function getRenderElement(workerEl: any) {
|
||||
function getRenderElement(workerEl: any): any {
|
||||
const id = workerRenderStore.serialize(workerEl);
|
||||
return uiRenderStore.deserialize(id);
|
||||
}
|
||||
|
@ -122,26 +126,25 @@ export function main() {
|
|||
MyComp2, {set: {template: '<input [title]="y" style="position:absolute">'}});
|
||||
const fixture = TestBed.createComponent(MyComp2);
|
||||
|
||||
const checkSetters =
|
||||
(componentRef: any /** TODO #9100 */, workerEl: any /** TODO #9100 */) => {
|
||||
const renderer = getRenderer(componentRef);
|
||||
const el = getRenderElement(workerEl);
|
||||
renderer.setElementProperty(workerEl, 'tabIndex', 1);
|
||||
expect((<HTMLInputElement>el).tabIndex).toEqual(1);
|
||||
const checkSetters = (componentRef: ComponentRef<any>, workerEl: any) => {
|
||||
const renderer = getRenderer(componentRef);
|
||||
const el = getRenderElement(workerEl);
|
||||
renderer.setElementProperty(workerEl, 'tabIndex', 1);
|
||||
expect(el.tabIndex).toEqual(1);
|
||||
|
||||
renderer.setElementClass(workerEl, 'a', true);
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(true);
|
||||
renderer.setElementClass(workerEl, 'a', false);
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(false);
|
||||
renderer.setElementClass(workerEl, 'a', true);
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(true);
|
||||
renderer.setElementClass(workerEl, 'a', false);
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(false);
|
||||
|
||||
renderer.setElementStyle(workerEl, 'width', '10px');
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('10px');
|
||||
renderer.setElementStyle(workerEl, 'width', null);
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('');
|
||||
renderer.setElementStyle(workerEl, 'width', '10px');
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('10px');
|
||||
renderer.setElementStyle(workerEl, 'width', null);
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('');
|
||||
|
||||
renderer.setElementAttribute(workerEl, 'someattr', 'someValue');
|
||||
expect(getDOM().getAttribute(el, 'someattr')).toEqual('someValue');
|
||||
};
|
||||
renderer.setElementAttribute(workerEl, 'someattr', 'someValue');
|
||||
expect(getDOM().getAttribute(el, 'someattr')).toEqual('someValue');
|
||||
};
|
||||
|
||||
// root element
|
||||
checkSetters(fixture.componentRef, fixture.nativeElement);
|
||||
|
@ -150,12 +153,11 @@ export function main() {
|
|||
});
|
||||
|
||||
it('should update any template comment property/attributes', () => {
|
||||
|
||||
TestBed.overrideComponent(
|
||||
MyComp2, {set: {template: '<ng-container *ngIf="ctxBoolProp"></ng-container>'}});
|
||||
const fixture = TestBed.createComponent(MyComp2);
|
||||
|
||||
(<MyComp2>fixture.componentInstance).ctxBoolProp = true;
|
||||
fixture.componentInstance.ctxBoolProp = true;
|
||||
fixture.detectChanges();
|
||||
const el = getRenderElement(fixture.nativeElement);
|
||||
expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"');
|
||||
|
@ -183,6 +185,7 @@ export function main() {
|
|||
TestBed.overrideComponent(MyComp2, {set: {template: '<input [title]="y">'}});
|
||||
const fixture = TestBed.createComponent(MyComp2);
|
||||
const el = fixture.debugElement.children[0];
|
||||
|
||||
getRenderer(fixture.componentRef).invokeElementMethod(el.nativeElement, 'setAttribute', [
|
||||
'a', 'b'
|
||||
]);
|
||||
|
@ -207,16 +210,8 @@ export function main() {
|
|||
|
||||
|
||||
@Component({selector: 'my-comp'})
|
||||
@Injectable()
|
||||
class MyComp2 {
|
||||
ctxProp: string;
|
||||
ctxNumProp: any /** TODO #9100 */;
|
||||
ctxBoolProp: boolean;
|
||||
constructor() {
|
||||
this.ctxProp = 'initial value';
|
||||
this.ctxNumProp = 0;
|
||||
this.ctxBoolProp = false;
|
||||
}
|
||||
|
||||
throwError() { throw 'boom'; }
|
||||
ctxProp = 'initial value';
|
||||
ctxNumProp = 0;
|
||||
ctxBoolProp = false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
import {USE_VIEW_ENGINE} from '@angular/compiler/src/config';
|
||||
import {Component, ComponentRef, RendererFactoryV2, RendererTypeV2, RendererV2, RootRenderer} from '@angular/core';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {DomRendererFactoryV2, DomRootRenderer, DomRootRenderer_} from '@angular/platform-browser/src/dom/dom_renderer';
|
||||
import {BrowserTestingModule} from '@angular/platform-browser/testing';
|
||||
import {dispatchEvent} from '@angular/platform-browser/testing/browser_util';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
|
||||
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from '../../../src/web_workers/shared/client_message_broker';
|
||||
import {RenderStore} from '../../../src/web_workers/shared/render_store';
|
||||
import {Serializer} from '../../../src/web_workers/shared/serializer';
|
||||
import {ServiceMessageBrokerFactory_} from '../../../src/web_workers/shared/service_message_broker';
|
||||
import {MessageBasedRendererV2} from '../../../src/web_workers/ui/renderer';
|
||||
import {WebWorkerRendererFactoryV2} from '../../../src/web_workers/worker/renderer';
|
||||
import {PairedMessageBuses, createPairedMessageBuses} from '../shared/web_worker_test_util';
|
||||
|
||||
let lastCreatedRenderer: RendererV2;
|
||||
|
||||
export function main() {
|
||||
describe('Web Worker Renderer v2', () => {
|
||||
// Don't run on server...
|
||||
if (!getDOM().supportsDOMEvents()) return;
|
||||
|
||||
let uiRenderStore: RenderStore;
|
||||
let wwRenderStore: RenderStore;
|
||||
|
||||
beforeEach(() => {
|
||||
// UI side
|
||||
uiRenderStore = new RenderStore();
|
||||
const uiInjector = new TestBed();
|
||||
uiInjector.platform = platformBrowserDynamicTesting();
|
||||
uiInjector.ngModule = BrowserTestingModule;
|
||||
uiInjector.configureTestingModule({
|
||||
providers: [
|
||||
{provide: USE_VIEW_ENGINE, useValue: true}, Serializer,
|
||||
{provide: RenderStore, useValue: uiRenderStore}, DomRendererFactoryV2,
|
||||
{provide: RendererFactoryV2, useExisting: DomRendererFactoryV2},
|
||||
{provide: DomRootRenderer, useClass: DomRootRenderer_},
|
||||
{provide: RootRenderer, useExisting: DomRootRenderer}
|
||||
]
|
||||
});
|
||||
const uiSerializer = uiInjector.get(Serializer);
|
||||
const domRendererFactory = uiInjector.get(RendererFactoryV2);
|
||||
|
||||
// Worker side
|
||||
lastCreatedRenderer = null;
|
||||
|
||||
wwRenderStore = new RenderStore();
|
||||
|
||||
TestBed
|
||||
.configureCompiler({
|
||||
useJit: true,
|
||||
providers: [
|
||||
{provide: USE_VIEW_ENGINE, useValue: true},
|
||||
],
|
||||
})
|
||||
.configureTestingModule({
|
||||
declarations: [MyComp2],
|
||||
providers: [
|
||||
Serializer,
|
||||
{provide: RenderStore, useValue: wwRenderStore},
|
||||
{
|
||||
provide: RendererFactoryV2,
|
||||
useFactory: (wwSerializer: Serializer) => createWebWorkerRendererFactoryV2(
|
||||
wwSerializer, uiSerializer, domRendererFactory, uiRenderStore,
|
||||
wwRenderStore),
|
||||
deps: [Serializer],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
function getRenderElement(workerEl: any): any {
|
||||
const id = wwRenderStore.serialize(workerEl);
|
||||
return uiRenderStore.deserialize(id);
|
||||
}
|
||||
|
||||
it('should update text nodes', () => {
|
||||
const fixture =
|
||||
TestBed.overrideTemplate(MyComp2, '<div>{{ctxProp}}</div>').createComponent(MyComp2);
|
||||
const renderEl = getRenderElement(fixture.nativeElement);
|
||||
expect(renderEl).toHaveText('');
|
||||
|
||||
fixture.componentInstance.ctxProp = 'Hello World!';
|
||||
fixture.detectChanges();
|
||||
expect(renderEl).toHaveText('Hello World!');
|
||||
});
|
||||
|
||||
it('should update any element property/attributes/class/style(s) independent of the compilation on the root element and other elements',
|
||||
() => {
|
||||
const fixture =
|
||||
TestBed.overrideTemplate(MyComp2, '<input [title]="y" style="position:absolute">')
|
||||
.createComponent(MyComp2);
|
||||
|
||||
const checkSetters = (componentRef: ComponentRef<any>, workerEl: any) => {
|
||||
expect(lastCreatedRenderer).not.toEqual(null);
|
||||
|
||||
const el = getRenderElement(workerEl);
|
||||
lastCreatedRenderer.setProperty(workerEl, 'tabIndex', 1);
|
||||
expect(el.tabIndex).toEqual(1);
|
||||
|
||||
lastCreatedRenderer.addClass(workerEl, 'a');
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(true);
|
||||
|
||||
lastCreatedRenderer.removeClass(workerEl, 'a');
|
||||
expect(getDOM().hasClass(el, 'a')).toBe(false);
|
||||
|
||||
lastCreatedRenderer.setStyle(workerEl, 'width', '10px', false, false);
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('10px');
|
||||
|
||||
lastCreatedRenderer.removeStyle(workerEl, 'width', false);
|
||||
expect(getDOM().getStyle(el, 'width')).toEqual('');
|
||||
|
||||
lastCreatedRenderer.setAttribute(workerEl, 'someattr', 'someValue');
|
||||
expect(getDOM().getAttribute(el, 'someattr')).toEqual('someValue');
|
||||
};
|
||||
|
||||
// root element
|
||||
checkSetters(fixture.componentRef, fixture.nativeElement);
|
||||
// nested elements
|
||||
checkSetters(fixture.componentRef, fixture.debugElement.children[0].nativeElement);
|
||||
});
|
||||
|
||||
it('should update any template comment property/attributes', () => {
|
||||
const fixture =
|
||||
TestBed.overrideTemplate(MyComp2, '<ng-container *ngIf="ctxBoolProp"></ng-container>')
|
||||
.createComponent(MyComp2);
|
||||
fixture.componentInstance.ctxBoolProp = true;
|
||||
fixture.detectChanges();
|
||||
const el = getRenderElement(fixture.nativeElement);
|
||||
expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"');
|
||||
});
|
||||
|
||||
it('should add and remove fragments', () => {
|
||||
const fixture =
|
||||
TestBed
|
||||
.overrideTemplate(MyComp2, '<ng-container *ngIf="ctxBoolProp">hello</ng-container>')
|
||||
.createComponent(MyComp2);
|
||||
|
||||
const rootEl = getRenderElement(fixture.nativeElement);
|
||||
expect(rootEl).toHaveText('');
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = true;
|
||||
fixture.detectChanges();
|
||||
expect(rootEl).toHaveText('hello');
|
||||
|
||||
fixture.componentInstance.ctxBoolProp = false;
|
||||
fixture.detectChanges();
|
||||
expect(rootEl).toHaveText('');
|
||||
});
|
||||
|
||||
if (getDOM().supportsDOMEvents()) {
|
||||
it('should listen to events', () => {
|
||||
const fixture = TestBed.overrideTemplate(MyComp2, '<input (change)="ctxNumProp = 1">')
|
||||
.createComponent(MyComp2);
|
||||
|
||||
const el = fixture.debugElement.children[0];
|
||||
dispatchEvent(getRenderElement(el.nativeElement), 'change');
|
||||
expect(fixture.componentInstance.ctxNumProp).toBe(1);
|
||||
|
||||
fixture.destroy();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Component({selector: 'my-comp'})
|
||||
class MyComp2 {
|
||||
ctxProp = 'initial value';
|
||||
ctxNumProp = 0;
|
||||
ctxBoolProp = false;
|
||||
}
|
||||
|
||||
function createWebWorkerBrokerFactory(
|
||||
messageBuses: PairedMessageBuses, wwSerializer: Serializer, uiSerializer: Serializer,
|
||||
domRendererFactory: DomRendererFactoryV2,
|
||||
uiRenderStore: RenderStore): ClientMessageBrokerFactory {
|
||||
const uiMessageBus = messageBuses.ui;
|
||||
const wwMessageBus = messageBuses.worker;
|
||||
|
||||
// set up the worker side
|
||||
const wwBrokerFactory = new ClientMessageBrokerFactory_(wwMessageBus, wwSerializer);
|
||||
|
||||
// set up the ui side
|
||||
const uiBrokerFactory = new ServiceMessageBrokerFactory_(uiMessageBus, uiSerializer);
|
||||
const renderer = new MessageBasedRendererV2(
|
||||
uiBrokerFactory, uiMessageBus, uiSerializer, uiRenderStore, domRendererFactory);
|
||||
renderer.start();
|
||||
|
||||
return wwBrokerFactory;
|
||||
}
|
||||
|
||||
function createWebWorkerRendererFactoryV2(
|
||||
workerSerializer: Serializer, uiSerializer: Serializer,
|
||||
domRendererFactory: DomRendererFactoryV2, uiRenderStore: RenderStore,
|
||||
workerRenderStore: RenderStore): RendererFactoryV2 {
|
||||
const messageBuses = createPairedMessageBuses();
|
||||
const brokerFactory = createWebWorkerBrokerFactory(
|
||||
messageBuses, workerSerializer, uiSerializer, domRendererFactory, uiRenderStore);
|
||||
|
||||
const rendererFactory =
|
||||
new RenderFactory(brokerFactory, messageBuses.worker, workerSerializer, workerRenderStore);
|
||||
|
||||
return rendererFactory;
|
||||
}
|
||||
|
||||
class RenderFactory extends WebWorkerRendererFactoryV2 {
|
||||
createRenderer(element: any, type: RendererTypeV2): RendererV2 {
|
||||
lastCreatedRenderer = super.createRenderer(element, type);
|
||||
return lastCreatedRenderer;
|
||||
}
|
||||
}
|
|
@ -13,9 +13,9 @@ export declare abstract class ClientMessageBrokerFactory {
|
|||
|
||||
/** @experimental */
|
||||
export declare class FnArg {
|
||||
type: Type<any>;
|
||||
type: Type<any> | SerializerTypes;
|
||||
value: any;
|
||||
constructor(value: any, type: Type<any>);
|
||||
constructor(value: any, type?: Type<any> | SerializerTypes);
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
|
@ -60,6 +60,11 @@ export declare class ReceivedMessage {
|
|||
});
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
export declare const enum SerializerTypes {
|
||||
RENDERER_TYPE_V2 = 0,
|
||||
}
|
||||
|
||||
/** @experimental */
|
||||
export declare abstract class ServiceMessageBroker {
|
||||
abstract registerMethod(methodName: string, signature: Type<any>[], method: Function, returnType?: Type<any>): void;
|
||||
|
|
Loading…
Reference in New Issue