Skip to content

Commit

Permalink
feat(WebWorker): Expose MessageBroker API
Browse files Browse the repository at this point in the history
Closes #3942
  • Loading branch information
jteplitz committed Sep 1, 2015
1 parent 6532171 commit 358908e
Show file tree
Hide file tree
Showing 31 changed files with 267 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {ListWrapper, StringMapWrapper, MapWrapper} from "angular2/src/core/facad
import {Serializer} from "angular2/src/web_workers/shared/serializer";
import {Injectable} from "angular2/di";
import {Type, StringWrapper} from "angular2/src/core/facade/lang";
export {Type} from "angular2/src/core/facade/lang";

@Injectable()
export class ClientMessageBrokerFactory {
Expand All @@ -29,7 +30,8 @@ export class ClientMessageBroker {
constructor(messageBus: MessageBus, protected _serializer: Serializer, public channel) {
this._sink = messageBus.to(channel);
var source = messageBus.from(channel);
ObservableWrapper.subscribe(source, (message) => this._handleMessage(message));
ObservableWrapper.subscribe(source,
(message: StringMap<string, any>) => this._handleMessage(message));
}

private _generateMessageId(name: string): string {
Expand All @@ -43,7 +45,7 @@ export class ClientMessageBroker {
return id;
}

runOnUiThread(args: UiArguments, returnType: Type): Promise<any> {
runOnService(args: UiArguments, returnType: Type): Promise<any> {
var fnArgs = [];
if (isPresent(args.args)) {
ListWrapper.forEach(args.args, (argument) => {
Expand Down Expand Up @@ -128,7 +130,7 @@ class MessageData {
}

export class FnArg {
constructor(public value, public type) {}
constructor(public value, public type: Type) {}
}

export class UiArguments {
Expand Down
38 changes: 24 additions & 14 deletions modules/angular2/src/web_workers/ui/application.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'dart:async';
import 'dart:core';
import 'package:angular2/src/web_workers/shared/message_bus.dart'
show MessageBus;
import 'package:angular2/src/web_workers/ui/impl.dart' show bootstrapUICommon;
import 'package:angular2/src/web_workers/ui/impl.dart' show bootstrapUICommon, WebWorkerApplication;
import 'package:angular2/src/web_workers/shared/isolate_message_bus.dart';

/**
Expand All @@ -14,26 +14,24 @@ import 'package:angular2/src/web_workers/shared/isolate_message_bus.dart';
* You instantiate a WebWorker application by calling bootstrap with the URI of your worker's index script
* Note: The WebWorker script must call bootstrapWebworker once it is set up to complete the bootstrapping process
*/
Future<MessageBus> bootstrap(String uri) {
return spawnWebWorker(Uri.parse(uri)).then((bus) {
bootstrapUICommon(bus);
return bus;
});
Future<IsolateInstance> bootstrap(String uri) async {
var instance = await spawnWebWorker(Uri.parse(uri));
instance.app = bootstrapUICommon(instance.bus);
return instance;
}

/**
* To be called from the main thread to spawn and communicate with the worker thread
*/
Future<MessageBus> spawnWebWorker(Uri uri) {
Future<IsolateInstance> spawnWebWorker(Uri uri) async {
var receivePort = new ReceivePort();
var isolateEndSendPort = receivePort.sendPort;
return Isolate.spawnUri(uri, const [], isolateEndSendPort).then((_) {
var source = new UIMessageBusSource(receivePort);
return source.sink.then((sendPort) {
var sink = new IsolateMessageBusSink(sendPort);
return new IsolateMessageBus(sink, source);
});
});
var isolate = await Isolate.spawnUri(uri, const [], isolateEndSendPort);
var source = new UIMessageBusSource(receivePort);
var sendPort = await source.sink;
var sink = new IsolateMessageBusSink(sendPort);
var bus = new IsolateMessageBus(sink, source);
return new IsolateInstance(null, isolate, bus);
}

class UIMessageBusSource extends IsolateMessageBusSource {
Expand All @@ -43,3 +41,15 @@ class UIMessageBusSource extends IsolateMessageBusSource {
return message is SendPort;
});
}

/**
* Wrapper class that exposes the {@link WebWorkerApplication}
* Isolate instance and underyling {@link MessageBus} for lower level message passing.
*/
class IsolateInstance {
WebWorkerApplication app;
final Isolate isolate;
final MessageBus bus;

IsolateInstance(this.app, this.isolate, this.bus);
}
26 changes: 18 additions & 8 deletions modules/angular2/src/web_workers/ui/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
PostMessageBusSource
} from 'angular2/src/web_workers/shared/post_message_bus';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {BaseException} from "angular2/src/core/facade/lang";
import {bootstrapUICommon} from "angular2/src/web_workers/ui/impl";
import {BaseException} from 'angular2/src/core/facade/lang';
import {bootstrapUICommon, WebWorkerApplication} from 'angular2/src/web_workers/ui/impl';
export {WebWorkerApplication} from 'angular2/src/web_workers/ui/impl';
export * from 'angular2/src/web_workers/shared/message_bus';

/**
Expand All @@ -16,15 +17,24 @@ export * from 'angular2/src/web_workers/shared/message_bus';
* Note: The WebWorker script must call bootstrapWebworker once it is set up to complete the
* bootstrapping process
*/
export function bootstrap(uri: string): MessageBus {
var messageBus = spawnWebWorker(uri);
bootstrapUICommon(messageBus);
return messageBus;
export function bootstrap(uri: string): WebWorkerInstance {
var instance = spawnWebWorker(uri);
instance.app = bootstrapUICommon(instance.bus);
return instance;
}

export function spawnWebWorker(uri: string): MessageBus {
export function spawnWebWorker(uri: string): WebWorkerInstance {
var webWorker: Worker = new Worker(uri);
var sink = new PostMessageBusSink(webWorker);
var source = new PostMessageBusSource(webWorker);
return new PostMessageBus(sink, source);
var bus = new PostMessageBus(sink, source);
return new WebWorkerInstance(null, webWorker, bus);
}

/**
* Wrapper class that exposes the {@link WebWorkerApplication}
* Isolate instance and underyling {@link MessageBus} for lower level message passing.
*/
export class WebWorkerInstance {
constructor(public app: WebWorkerApplication, public worker: Worker, public bus: MessageBus) {}
}
9 changes: 5 additions & 4 deletions modules/angular2/src/web_workers/ui/di_bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// There should be a way to refactor application so that this file is unnecessary. See #3277
import {Injector, bind, Binding} from "angular2/di";
import {Reflector, reflector} from 'angular2/src/core/reflection/reflection';
import {ListWrapper} from 'angular2/src/core/facade/collection';
import {
Parser,
Lexer,
Expand Down Expand Up @@ -61,13 +60,14 @@ import {
RenderViewWithFragmentsStore
} from 'angular2/src/web_workers/shared/render_view_with_fragments_store';
import {AnchorBasedAppRootUrl} from 'angular2/src/core/services/anchor_based_app_root_url';
import {WebWorkerMain} from 'angular2/src/web_workers/ui/impl';
import {WebWorkerApplication} from 'angular2/src/web_workers/ui/impl';
import {MessageBus} from 'angular2/src/web_workers/shared/message_bus';
import {MessageBasedRenderCompiler} from 'angular2/src/web_workers/ui/render_compiler';
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl';
import {WebWorkerSetup} from 'angular2/src/web_workers/ui/setup';
import {ServiceMessageBrokerFactory} from 'angular2/src/web_workers/shared/service_message_broker';
import {ClientMessageBrokerFactory} from 'angular2/src/web_workers/shared/client_message_broker';

var _rootInjector: Injector;

Expand Down Expand Up @@ -134,12 +134,13 @@ function _injectorBindings(): any[] {
Testability,
AnchorBasedAppRootUrl,
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
WebWorkerMain,
WebWorkerApplication,
WebWorkerSetup,
MessageBasedRenderCompiler,
MessageBasedXHRImpl,
MessageBasedRenderer,
ServiceMessageBrokerFactory
ServiceMessageBrokerFactory,
ClientMessageBrokerFactory
];
}

Expand Down
34 changes: 26 additions & 8 deletions modules/angular2/src/web_workers/ui/impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,43 @@ import {WebWorkerSetup} from 'angular2/src/web_workers/ui/setup';
import {MessageBasedRenderCompiler} from 'angular2/src/web_workers/ui/render_compiler';
import {MessageBasedRenderer} from 'angular2/src/web_workers/ui/renderer';
import {MessageBasedXHRImpl} from 'angular2/src/web_workers/ui/xhr_impl';
import {
ClientMessageBrokerFactory,
ClientMessageBroker,
} from 'angular2/src/web_workers/shared/client_message_broker';
import {
ServiceMessageBrokerFactory,
ServiceMessageBroker
} from 'angular2/src/web_workers/shared/service_message_broker';

/**
* Creates a zone, sets up the DI bindings
* And then creates a new WebWorkerMain object to handle messages from the worker
*/
export function bootstrapUICommon(bus: MessageBus) {
export function bootstrapUICommon(bus: MessageBus): WebWorkerApplication {
BrowserDomAdapter.makeCurrent();
var zone = createNgZone();
wtfInit();
zone.run(() => {
return zone.run(() => {
var injector = createInjector(zone, bus);
// necessary to kick off all the message based components
injector.get(WebWorkerMain);
injector.get(MessageBasedRenderCompiler).start();
injector.get(MessageBasedRenderer).start();
injector.get(MessageBasedXHRImpl).start();
injector.get(WebWorkerSetup).start();
return injector.get(WebWorkerApplication);
});
}

@Injectable()
export class WebWorkerMain {
constructor(public renderCompiler: MessageBasedRenderCompiler,
public renderer: MessageBasedRenderer, public xhr: MessageBasedXHRImpl,
public setup: WebWorkerSetup) {}
export class WebWorkerApplication {
constructor(private _clientMessageBrokerFactory: ClientMessageBrokerFactory,
private _serviceMessageBrokerFactory: ServiceMessageBrokerFactory) {}

createClientMessageBroker(channel: string): ClientMessageBroker {
return this._clientMessageBrokerFactory.createMessageBroker(channel);
}

createServiceMessageBroker(channel: string): ServiceMessageBroker {
return this._serviceMessageBrokerFactory.createMessageBroker(channel);
}
}
7 changes: 5 additions & 2 deletions modules/angular2/src/web_workers/ui/render_compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import {ServiceMessageBrokerFactory} from 'angular2/src/web_workers/shared/servi

@Injectable()
export class MessageBasedRenderCompiler {
constructor(brokerFactory: ServiceMessageBrokerFactory, private _renderCompiler: RenderCompiler) {
var broker = brokerFactory.createMessageBroker(RENDER_COMPILER_CHANNEL);
constructor(private _brokerFactory: ServiceMessageBrokerFactory,
private _renderCompiler: RenderCompiler) {}

start(): void {
var broker = this._brokerFactory.createMessageBroker(RENDER_COMPILER_CHANNEL);
broker.registerMethod("compileHost", [RenderDirectiveMetadata],
bind(this._renderCompiler.compileHost, this._renderCompiler),
ProtoViewDto);
Expand Down
8 changes: 5 additions & 3 deletions modules/angular2/src/web_workers/ui/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import {ServiceMessageBrokerFactory} from 'angular2/src/web_workers/shared/servi

@Injectable()
export class MessageBasedRenderer {
constructor(brokerFactory: ServiceMessageBrokerFactory, private _bus: MessageBus,
constructor(private _brokerFactory: ServiceMessageBrokerFactory, private _bus: MessageBus,
private _serializer: Serializer,
private _renderViewWithFragmentsStore: RenderViewWithFragmentsStore,
private _renderer: Renderer) {
var broker = brokerFactory.createMessageBroker(RENDERER_CHANNEL);
private _renderer: Renderer) {}

start(): void {
var broker = this._brokerFactory.createMessageBroker(RENDERER_CHANNEL);
broker.registerMethod("createRootHostView",
[RenderProtoViewRef, PRIMITIVE, PRIMITIVE, PRIMITIVE],
bind(this._createRootHostView, this));
Expand Down
15 changes: 10 additions & 5 deletions modules/angular2/src/web_workers/ui/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ import {StringWrapper} from 'angular2/src/core/facade/lang';

@Injectable()
export class WebWorkerSetup {
constructor(bus: MessageBus, anchorBasedAppRootUrl: AnchorBasedAppRootUrl) {
var rootUrl = anchorBasedAppRootUrl.value;
var sink = bus.to(SETUP_CHANNEL);
var source = bus.from(SETUP_CHANNEL);
rootUrl: string;

constructor(private _bus: MessageBus, anchorBasedAppRootUrl: AnchorBasedAppRootUrl) {
this.rootUrl = anchorBasedAppRootUrl.value;
}

start(): void {
var sink = this._bus.to(SETUP_CHANNEL);
var source = this._bus.from(SETUP_CHANNEL);

ObservableWrapper.subscribe(source, (message: string) => {
if (StringWrapper.equals(message, "ready")) {
ObservableWrapper.callNext(sink, {"rootUrl": rootUrl});
ObservableWrapper.callNext(sink, {"rootUrl": this.rootUrl});
}
});
}
Expand Down
6 changes: 4 additions & 2 deletions modules/angular2/src/web_workers/ui/xhr_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import {bind} from './bind';

@Injectable()
export class MessageBasedXHRImpl {
constructor(brokerFactory: ServiceMessageBrokerFactory, private _xhr: XHR) {
var broker = brokerFactory.createMessageBroker(XHR_CHANNEL);
constructor(private _brokerFactory: ServiceMessageBrokerFactory, private _xhr: XHR) {}

start(): void {
var broker = this._brokerFactory.createMessageBroker(XHR_CHANNEL);
broker.registerMethod("get", [PRIMITIVE], bind(this._xhr.get, this._xhr), PRIMITIVE);
}
}
Loading

0 comments on commit 358908e

Please sign in to comment.