refactor(WebWorker): Abstract message passing and serialization to UIMessageBroker

closes #3703

Closes #3815
This commit is contained in:
Jason Teplitz
2015-08-21 16:55:50 -07:00
parent aeef19e2a6
commit 21f60c5dce
22 changed files with 319 additions and 248 deletions
@@ -0,0 +1,69 @@
import {
AsyncTestCompleter,
inject,
describe,
it,
expect,
beforeEach,
createTestInjector,
beforeEachBindings,
SpyObject,
proxy
} from 'angular2/test_lib';
import {createPairedMessageBuses} from '../shared/web_worker_test_util';
import {Serializer, PRIMITIVE} from 'angular2/src/web_workers/shared/serializer';
import {ServiceMessageBroker} from 'angular2/src/web_workers/shared/service_message_broker';
import {ObservableWrapper, PromiseWrapper} from 'angular2/src/facade/async';
import {bind} from 'angular2/di';
import {ON_WEB_WORKER} from 'angular2/src/web_workers/shared/api';
import {RenderProtoViewRefStore} from 'angular2/src/web_workers/shared/render_proto_view_ref_store';
import {
RenderViewWithFragmentsStore
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
export function main() {
const CHANNEL = "UIMessageBroker Test Channel";
const TEST_METHOD = "TEST_METHOD";
const PASSED_ARG_1 = 5;
const PASSED_ARG_2 = 'TEST';
const RESULT = 20;
const ID = "methodId";
beforeEachBindings(() => [
bind(ON_WEB_WORKER)
.toValue(true),
RenderProtoViewRefStore,
RenderViewWithFragmentsStore
]);
describe("UIMessageBroker", () => {
var messageBuses;
beforeEach(() => { messageBuses = createPairedMessageBuses(); });
it("should call registered method with correct arguments",
inject([Serializer], (serializer) => {
var broker = new ServiceMessageBroker(messageBuses.ui, serializer, CHANNEL);
broker.registerMethod(TEST_METHOD, [PRIMITIVE, PRIMITIVE], (arg1, arg2) => {
expect(arg1).toEqual(PASSED_ARG_1);
expect(arg2).toEqual(PASSED_ARG_2);
});
ObservableWrapper.callNext(messageBuses.worker.to(CHANNEL),
{'method': TEST_METHOD, 'args': [PASSED_ARG_1, PASSED_ARG_2]});
}));
it("should return promises to the worker", inject([Serializer], (serializer) => {
var broker = new ServiceMessageBroker(messageBuses.ui, serializer, CHANNEL);
broker.registerMethod(TEST_METHOD, [PRIMITIVE], (arg1) => {
expect(arg1).toEqual(PASSED_ARG_1);
return PromiseWrapper.wrap(() => { return RESULT; });
});
ObservableWrapper.callNext(messageBuses.worker.to(CHANNEL),
{'method': TEST_METHOD, 'id': ID, 'args': [PASSED_ARG_1]});
ObservableWrapper.subscribe(messageBuses.worker.from(CHANNEL), (data: any) => {
expect(data.type).toEqual("result");
expect(data.id).toEqual(ID);
expect(data.value).toEqual(RESULT);
});
}));
});
}
@@ -21,7 +21,7 @@ import {
WebWorkerRenderViewRef
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
import {RenderEventDispatcher, RenderViewRef} from 'angular2/src/render/api';
import {createPairedMessageBuses} from './worker_test_util';
import {createPairedMessageBuses} from '../shared/web_worker_test_util';
import {WebWorkerEventDispatcher} from 'angular2/src/web_workers/worker/event_dispatcher';
import {ObservableWrapper} from 'angular2/src/facade/async';
import {EVENT_CHANNEL} from 'angular2/src/web_workers/shared/messaging_api';
@@ -12,7 +12,11 @@ import {DOM} from 'angular2/src/dom/dom_adapter';
import {DomTestbed, TestRootView, elRef} from '../../render/dom/dom_testbed';
import {bind} from 'angular2/di';
import {WebWorkerCompiler, WebWorkerRenderer} from "angular2/src/web_workers/worker/renderer";
import {MessageBrokerFactory, UiArguments, FnArg} from "angular2/src/web_workers/worker/broker";
import {
ClientMessageBrokerFactory,
UiArguments,
FnArg
} from "angular2/src/web_workers/shared/client_message_broker";
import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {isPresent, isBlank, BaseException, Type} from "angular2/src/facade/lang";
import {MapWrapper, ListWrapper} from "angular2/src/facade/collection";
@@ -39,44 +43,44 @@ import {someComponent} from '../../render/dom/dom_renderer_integration_spec';
import {WebWorkerMain} from 'angular2/src/web_workers/ui/impl';
import {MessageBasedRenderCompiler} from 'angular2/src/web_workers/ui/render_compiler';
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
import {
createPairedMessageBuses
} from './worker_test_util'
import {createPairedMessageBuses} from '../shared/web_worker_test_util';
import {ServiceMessageBrokerFactory} from 'angular2/src/web_workers/shared/service_message_broker';
export function
main() {
function createBrokerFactory(workerSerializer: Serializer, uiSerializer: Serializer,
tb: DomTestbed, uiRenderViewStore: RenderViewWithFragmentsStore,
workerRenderViewStore: RenderViewWithFragmentsStore):
MessageBrokerFactory {
export function main() {
function createWebWorkerBrokerFactory(
workerSerializer: Serializer, uiSerializer: Serializer, tb: DomTestbed,
uiRenderViewStore: RenderViewWithFragmentsStore,
workerRenderViewStore: RenderViewWithFragmentsStore): ClientMessageBrokerFactory {
var messageBuses = createPairedMessageBuses();
var uiMessageBus = messageBuses.ui;
var workerMessageBus = messageBuses.worker;
// set up the worker side
var brokerFactory = new MessageBrokerFactory(workerMessageBus, workerSerializer);
var webWorkerBrokerFactory = new ClientMessageBrokerFactory(workerMessageBus, workerSerializer);
// set up the ui side
var renderCompiler = new MessageBasedRenderCompiler(uiMessageBus, uiSerializer, tb.compiler);
var renderer =
new MessageBasedRenderer(uiMessageBus, uiSerializer, uiRenderViewStore, tb.renderer);
var uiMessageBrokerFactory = new ServiceMessageBrokerFactory(uiMessageBus, uiSerializer);
var renderCompiler = new MessageBasedRenderCompiler(uiMessageBrokerFactory, tb.compiler);
var renderer = new MessageBasedRenderer(uiMessageBrokerFactory, uiMessageBus, uiSerializer,
uiRenderViewStore, tb.renderer);
new WebWorkerMain(renderCompiler, renderer, null, null);
return brokerFactory;
return webWorkerBrokerFactory;
}
function createWorkerRenderer(workerSerializer: Serializer, uiSerializer: Serializer,
tb: DomTestbed, uiRenderViewStore: RenderViewWithFragmentsStore,
workerRenderViewStore: RenderViewWithFragmentsStore):
WebWorkerRenderer {
var brokerFactory = createBrokerFactory(workerSerializer, uiSerializer, tb, uiRenderViewStore,
workerRenderViewStore);
var brokerFactory = createWebWorkerBrokerFactory(workerSerializer, uiSerializer, tb,
uiRenderViewStore, workerRenderViewStore);
return new WebWorkerRenderer(brokerFactory, workerRenderViewStore, null);
}
function createWorkerCompiler(workerSerializer: Serializer, uiSerializer: Serializer,
tb: DomTestbed): WebWorkerCompiler {
var brokerFactory = createBrokerFactory(workerSerializer, uiSerializer, tb, null, null);
var brokerFactory =
createWebWorkerBrokerFactory(workerSerializer, uiSerializer, tb, null, null);
return new WebWorkerCompiler(brokerFactory);
}
@@ -232,6 +236,34 @@ import {
});
}));
it('should add and remove fragments', inject([AsyncTestCompleter], (async) => {
tb.compileAndMerge(someComponent,
[
new ViewDefinition({
componentId: 'someComponent',
template: '<template>hello</template>',
directives: []
})
])
.then((protoViewMergeMappings) => {
protoViewMergeMappings =
serialize(protoViewMergeMappings, RenderProtoViewMergeMapping);
var rootViewWithFragments =
renderer.createView(protoViewMergeMappings.mergedProtoViewRef, 2);
var elr = elRef(rootViewWithFragments.viewRef, 1);
var rootView = new WorkerTestRootView(rootViewWithFragments, uiRenderViewStore);
expect(rootView.hostElement).toHaveText('');
var fragment = rootViewWithFragments.fragmentRefs[1];
renderer.attachFragmentAfterElement(elr, fragment);
expect(rootView.hostElement).toHaveText('hello');
renderer.detachFragment(fragment);
expect(rootView.hostElement).toHaveText('');
async.done();
});
}));
it('should add and remove empty fragments', inject([AsyncTestCompleter], (async) => {
tb.compileAndMerge(someComponent,
[
@@ -12,10 +12,10 @@ import {
} from 'angular2/test_lib';
import {IMPLEMENTS, Type} from 'angular2/src/facade/lang';
import {
MessageBroker,
ClientMessageBroker,
UiArguments,
MessageBrokerFactory
} from 'angular2/src/web_workers/worker/broker';
ClientMessageBrokerFactory
} from 'angular2/src/web_workers/shared/client_message_broker';
import {WebWorkerXHRImpl} from "angular2/src/web_workers/worker/xhr_impl";
import {PromiseWrapper} from "angular2/src/facade/async";
@@ -45,13 +45,13 @@ export function main() {
}
@proxy
@IMPLEMENTS(MessageBroker)
@IMPLEMENTS(ClientMessageBroker)
class SpyMessageBroker extends SpyObject {
constructor() { super(MessageBroker); }
constructor() { super(ClientMessageBroker); }
noSuchMethod(m) { return super.noSuchMethod(m); }
}
class MockMessageBrokerFactory extends MessageBrokerFactory {
constructor(private _messageBroker: MessageBroker) { super(null, null); }
class MockMessageBrokerFactory extends ClientMessageBrokerFactory {
constructor(private _messageBroker: ClientMessageBroker) { super(null, null); }
createMessageBroker(channel: string) { return this._messageBroker; }
}