@ -12,20 +12,22 @@ export class RenderViewWithFragmentsStore {
|
||||
|
||||
constructor(@Inject(ON_WEBWORKER) onWebWorker) {
|
||||
this._onWebWorker = onWebWorker;
|
||||
if (!onWebWorker) {
|
||||
this._lookupByIndex = new Map<number, RenderViewRef | RenderFragmentRef>();
|
||||
this._lookupByView = new Map<RenderViewRef | RenderFragmentRef, number>();
|
||||
}
|
||||
this._lookupByIndex = new Map<number, RenderViewRef | RenderFragmentRef>();
|
||||
this._lookupByView = new Map<RenderViewRef | RenderFragmentRef, number>();
|
||||
}
|
||||
|
||||
allocate(fragmentCount: number): RenderViewWithFragments {
|
||||
var initialIndex = this._nextIndex;
|
||||
|
||||
var viewRef = new WorkerRenderViewRef(this._nextIndex++);
|
||||
var fragmentRefs = ListWrapper.createGrowableSize(fragmentCount);
|
||||
|
||||
for (var i = 0; i < fragmentCount; i++) {
|
||||
fragmentRefs[i] = new WorkerRenderFragmentRef(this._nextIndex++);
|
||||
}
|
||||
return new RenderViewWithFragments(viewRef, fragmentRefs);
|
||||
var renderViewWithFragments = new RenderViewWithFragments(viewRef, fragmentRefs);
|
||||
this.store(renderViewWithFragments, initialIndex);
|
||||
return renderViewWithFragments;
|
||||
}
|
||||
|
||||
store(view: RenderViewWithFragments, startIndex: number) {
|
||||
@ -60,11 +62,7 @@ export class RenderViewWithFragmentsStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._onWebWorker) {
|
||||
return WorkerRenderViewRef.deserialize(ref);
|
||||
} else {
|
||||
return this.retreive(ref);
|
||||
}
|
||||
return this.retreive(ref);
|
||||
}
|
||||
|
||||
deserializeRenderFragmentRef(ref: number): RenderFragmentRef {
|
||||
@ -72,11 +70,7 @@ export class RenderViewWithFragmentsStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._onWebWorker) {
|
||||
return WorkerRenderFragmentRef.deserialize(ref);
|
||||
} else {
|
||||
return this.retreive(ref);
|
||||
}
|
||||
return this.retreive(ref);
|
||||
}
|
||||
|
||||
private _serializeRenderFragmentOrViewRef(ref: RenderViewRef | RenderFragmentRef): number {
|
||||
@ -114,20 +108,11 @@ export class RenderViewWithFragmentsStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
var viewRef: RenderViewRef | RenderFragmentRef;
|
||||
var fragments: List<RenderViewRef | RenderFragmentRef>;
|
||||
if (this._onWebWorker) {
|
||||
viewRef = WorkerRenderViewRef.deserialize(obj['viewRef']);
|
||||
fragments =
|
||||
ListWrapper.map(obj['fragmentRefs'], (val) => WorkerRenderFragmentRef.deserialize(val));
|
||||
var viewRef = this.deserializeRenderViewRef(obj['viewRef']);
|
||||
var fragments =
|
||||
ListWrapper.map(obj['fragmentRefs'], (val) => this.deserializeRenderFragmentRef(val));
|
||||
|
||||
return new RenderViewWithFragments(viewRef, fragments);
|
||||
} else {
|
||||
viewRef = this.retreive(obj['viewRef']);
|
||||
fragments = ListWrapper.map(obj['fragmentRefs'], (val) => this.retreive(val));
|
||||
|
||||
return new RenderViewWithFragments(viewRef, fragments);
|
||||
}
|
||||
return new RenderViewWithFragments(viewRef, fragments);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,19 @@
|
||||
import {Type, isArray, isPresent, serializeEnum, deserializeEnum} from "angular2/src/facade/lang";
|
||||
import {List, ListWrapper, Map, StringMapWrapper, MapWrapper} from "angular2/src/facade/collection";
|
||||
import {
|
||||
Type,
|
||||
isArray,
|
||||
isPresent,
|
||||
serializeEnum,
|
||||
deserializeEnum,
|
||||
BaseException
|
||||
} from "angular2/src/facade/lang";
|
||||
import {
|
||||
List,
|
||||
ListWrapper,
|
||||
Map,
|
||||
StringMap,
|
||||
StringMapWrapper,
|
||||
MapWrapper
|
||||
} from "angular2/src/facade/collection";
|
||||
import {
|
||||
ProtoViewDto,
|
||||
DirectiveMetadata,
|
||||
@ -13,7 +27,8 @@ import {
|
||||
RenderViewRef,
|
||||
RenderFragmentRef,
|
||||
RenderElementRef,
|
||||
ViewType
|
||||
ViewType,
|
||||
ViewEncapsulation
|
||||
} from "angular2/src/render/api";
|
||||
import {WorkerElementRef} from 'angular2/src/web-workers/shared/api';
|
||||
import {AST, ASTWithSource} from 'angular2/src/change_detection/change_detection';
|
||||
@ -30,11 +45,18 @@ export class Serializer {
|
||||
constructor(private _parser: Parser, private _protoViewStore: RenderProtoViewRefStore,
|
||||
private _renderViewStore: RenderViewWithFragmentsStore) {
|
||||
this._enumRegistry = new Map<any, Map<int, any>>();
|
||||
|
||||
var viewTypeMap = new Map<int, any>();
|
||||
viewTypeMap[0] = ViewType.HOST;
|
||||
viewTypeMap[1] = ViewType.COMPONENT;
|
||||
viewTypeMap[2] = ViewType.EMBEDDED;
|
||||
this._enumRegistry.set(ViewType, viewTypeMap);
|
||||
|
||||
var viewEncapsulationMap = new Map<int, any>();
|
||||
viewEncapsulationMap[0] = ViewEncapsulation.EMULATED;
|
||||
viewEncapsulationMap[1] = ViewEncapsulation.NATIVE;
|
||||
viewEncapsulationMap[2] = ViewEncapsulation.NONE;
|
||||
this._enumRegistry.set(ViewEncapsulation, viewEncapsulationMap);
|
||||
}
|
||||
|
||||
serialize(obj: any, type: Type): Object {
|
||||
@ -71,8 +93,10 @@ export class Serializer {
|
||||
return this._renderViewStore.serializeRenderFragmentRef(obj);
|
||||
} else if (type == WorkerElementRef) {
|
||||
return this._serializeWorkerElementRef(obj);
|
||||
} else if (type == EventBinding) {
|
||||
return this._serializeEventBinding(obj);
|
||||
} else {
|
||||
throw "No serializer for " + type.toString();
|
||||
throw new BaseException("No serializer for " + type.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,8 +135,10 @@ export class Serializer {
|
||||
return this._renderViewStore.deserializeRenderFragmentRef(map);
|
||||
} else if (type == WorkerElementRef) {
|
||||
return this._deserializeWorkerElementRef(map);
|
||||
} else if (type == EventBinding) {
|
||||
return this._deserializeEventBinding(map);
|
||||
} else {
|
||||
throw "No deserializer for " + type.toString();
|
||||
throw new BaseException("No deserializer for " + type.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,6 +174,15 @@ export class Serializer {
|
||||
|
||||
allocateRenderViews(fragmentCount: number) { this._renderViewStore.allocate(fragmentCount); }
|
||||
|
||||
private _serializeEventBinding(binding: EventBinding): StringMap<string, any> {
|
||||
return {'fullName': binding.fullName, 'source': this.serialize(binding.source, ASTWithSource)};
|
||||
}
|
||||
|
||||
private _deserializeEventBinding(map: StringMap<string, any>): EventBinding {
|
||||
return new EventBinding(map['fullName'],
|
||||
this.deserialize(map['source'], ASTWithSource, "binding"));
|
||||
}
|
||||
|
||||
private _serializeWorkerElementRef(elementRef: RenderElementRef): StringMap<string, any> {
|
||||
return {
|
||||
'renderView': this.serialize(elementRef.renderView, RenderViewRef),
|
||||
@ -214,7 +249,7 @@ export class Serializer {
|
||||
'directives': this.serialize(view.directives, DirectiveMetadata),
|
||||
'styleAbsUrls': view.styleAbsUrls,
|
||||
'styles': view.styles,
|
||||
'encapsulation': view.encapsulation
|
||||
'encapsulation': serializeEnum(view.encapsulation)
|
||||
};
|
||||
}
|
||||
|
||||
@ -225,7 +260,8 @@ export class Serializer {
|
||||
directives: this.deserialize(obj['directives'], DirectiveMetadata),
|
||||
styleAbsUrls: obj['styleAbsUrls'],
|
||||
styles: obj['styles'],
|
||||
encapsulation: obj['encapsulation']
|
||||
encapsulation:
|
||||
deserializeEnum(obj['encapsulation'], this._enumRegistry.get(ViewEncapsulation))
|
||||
});
|
||||
}
|
||||
|
||||
@ -293,7 +329,7 @@ export class Serializer {
|
||||
variableBindings: this.objectToMap(obj['variableBindings']),
|
||||
textBindings: this.deserialize(obj['textBindings'], ASTWithSource, "interpolation"),
|
||||
type: deserializeEnum(obj['type'], this._enumRegistry.get(ViewType)),
|
||||
transitiveNgContentCount: obj['transitivengContentCount']
|
||||
transitiveNgContentCount: obj['transitiveNgContentCount']
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// TODO: This whole file is nearly identical to core/application.ts.
|
||||
// There should be a way to refactor application so that this file is unnecessary
|
||||
// TODO (jteplitz602): This whole file is nearly identical to core/application.ts.
|
||||
// There should be a way to refactor application so that this file is unnecessary. See #3277
|
||||
import {Injector, bind, Binding} from "angular2/di";
|
||||
import {Type, isBlank, isPresent} from "angular2/src/facade/lang";
|
||||
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
|
||||
@ -21,6 +21,7 @@ import {KeyEventsPlugin} from 'angular2/src/render/dom/events/key_events';
|
||||
import {HammerGesturesPlugin} from 'angular2/src/render/dom/events/hammer_gestures';
|
||||
import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_pool';
|
||||
import {Renderer, RenderCompiler} from 'angular2/src/render/api';
|
||||
import {AppRootUrl} from 'angular2/src/services/app_root_url';
|
||||
import {
|
||||
DomRenderer,
|
||||
DOCUMENT_TOKEN,
|
||||
@ -28,6 +29,8 @@ import {
|
||||
DefaultDomCompiler,
|
||||
APP_ID_RANDOM_BINDING
|
||||
} from 'angular2/src/render/render';
|
||||
import {ElementSchemaRegistry} from 'angular2/src/render/dom/schema/element_schema_registry';
|
||||
import {DomElementSchemaRegistry} from 'angular2/src/render/dom/schema/dom_element_schema_registry';
|
||||
import {
|
||||
SharedStylesHost,
|
||||
DomSharedStylesHost
|
||||
@ -73,11 +76,6 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||
} else if (JitChangeDetection.isSupported()) {
|
||||
bestChangeDetection = JitChangeDetection;
|
||||
}
|
||||
// compute the root url to pass to AppRootUrl
|
||||
/*var rootUrl: string;
|
||||
var a = DOM.createElement('a');
|
||||
DOM.resolveAndSetHref(a, './', null);
|
||||
rootUrl = DOM.getHref(a);*/
|
||||
|
||||
return [
|
||||
bind(DOCUMENT_TOKEN)
|
||||
@ -100,6 +98,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
|
||||
Serializer,
|
||||
bind(ON_WEBWORKER).toValue(false),
|
||||
bind(ElementSchemaRegistry).toValue(new DomElementSchemaRegistry()),
|
||||
RenderViewWithFragmentsStore,
|
||||
RenderProtoViewRefStore,
|
||||
ProtoViewFactory,
|
||||
@ -117,7 +116,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||
DirectiveResolver,
|
||||
Parser,
|
||||
Lexer,
|
||||
ExceptionHandler,
|
||||
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(DOM), []),
|
||||
bind(XHR).toValue(new XHRImpl()),
|
||||
ComponentUrlMapper,
|
||||
UrlResolver,
|
||||
@ -126,6 +125,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
|
||||
DynamicComponentLoader,
|
||||
Testability,
|
||||
AnchorBasedAppRootUrl,
|
||||
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
|
||||
WebWorkerMain
|
||||
];
|
||||
}
|
||||
|
82
modules/angular2/src/web-workers/ui/event_serializer.dart
Normal file
82
modules/angular2/src/web-workers/ui/event_serializer.dart
Normal file
@ -0,0 +1,82 @@
|
||||
library angular2.src.web_workers.event_serializer;
|
||||
|
||||
import 'package:angular2/src/facade/collection.dart';
|
||||
// TODO(jteplitz602): Remove Mirrors from serialization #3348
|
||||
@MirrorsUsed(
|
||||
symbols: "altKey, bubbles, button, cancelable, client, ctrlKey, " +
|
||||
"defaultPrevented, detail, eventPhase, layer, metaKey, offset, page, region, screen, " +
|
||||
"shiftKey, timeStamp, type, magnitude, x, y, charCode, keyCode, keyLocation, location, repeat")
|
||||
import 'dart:mirrors';
|
||||
import 'dart:core';
|
||||
import 'dart:html';
|
||||
|
||||
// These Maps can't be const due to a dartj2 bug (see http://github.com/dart-lang/sdk/issues/21825)
|
||||
// Once that bug is fixed these should be const
|
||||
final Map MOUSE_EVENT_PROPERTIES = {
|
||||
#altKey: bool,
|
||||
#bubbles: bool,
|
||||
#button: int,
|
||||
#cancelable: bool,
|
||||
#client: Point,
|
||||
#ctrlKey: bool,
|
||||
#defaultPrevented: bool,
|
||||
#detail: int,
|
||||
#eventPhase: int,
|
||||
#layer: Point,
|
||||
#metaKey: bool,
|
||||
#offset: Point,
|
||||
#page: Point,
|
||||
#region: String,
|
||||
#screen: Point,
|
||||
#shiftKey: bool,
|
||||
#timeStamp: int,
|
||||
#type: String
|
||||
};
|
||||
|
||||
final Map KEYBOARD_EVENT_PROPERTIES = {
|
||||
#altKey: bool,
|
||||
#bubbles: bool,
|
||||
#cancelable: bool,
|
||||
#charCode: int,
|
||||
#ctrlKey: bool,
|
||||
#defaultPrevented: bool,
|
||||
#detail: int,
|
||||
#eventPhase: int,
|
||||
#keyCode: int,
|
||||
#keyLocation: int,
|
||||
#layer: Point,
|
||||
#location: int,
|
||||
#repeat: bool,
|
||||
#shiftKey: bool,
|
||||
#timeStamp: int,
|
||||
#type: String
|
||||
};
|
||||
|
||||
Map<String, dynamic> serializeMouseEvent(dynamic e) {
|
||||
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
|
||||
}
|
||||
|
||||
Map<String, dynamic> serializeKeyboardEvent(dynamic e) {
|
||||
return serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
|
||||
}
|
||||
|
||||
Map<String, dynamic> serializeEvent(dynamic e, Map<Symbol, Type> PROPERTIES) {
|
||||
var serialized = StringMapWrapper.create();
|
||||
var mirror = reflect(e);
|
||||
PROPERTIES.forEach((property, type) {
|
||||
var value = mirror.getField(property).reflectee;
|
||||
var propertyName = MirrorSystem.getName(property);
|
||||
if (type == int || type == bool || type == String) {
|
||||
serialized[propertyName] = value;
|
||||
} else if (type == Point) {
|
||||
var point = reflect(value);
|
||||
serialized[propertyName] = {
|
||||
'magnitude': point.getField(#magnitude).reflectee,
|
||||
'x': point.getField(#x).reflectee,
|
||||
'y': point.getField(#y).reflectee
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return serialized;
|
||||
}
|
49
modules/angular2/src/web-workers/ui/event_serializer.ts
Normal file
49
modules/angular2/src/web-workers/ui/event_serializer.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import {StringMap} from 'angular2/src/facade/collection';
|
||||
|
||||
const MOUSE_EVENT_PROPERTIES = [
|
||||
"altKey",
|
||||
"button",
|
||||
"clientX",
|
||||
"clientY",
|
||||
"metaKey",
|
||||
"movementX",
|
||||
"movementY",
|
||||
"offsetX",
|
||||
"offsetY",
|
||||
"region",
|
||||
"screenX",
|
||||
"screenY",
|
||||
"shiftKey"
|
||||
];
|
||||
|
||||
const KEYBOARD_EVENT_PROPERTIES = [
|
||||
'altkey',
|
||||
'charCode',
|
||||
'code',
|
||||
'ctrlKey',
|
||||
'isComposing',
|
||||
'key',
|
||||
'keyCode',
|
||||
'location',
|
||||
'metaKey',
|
||||
'repeat',
|
||||
'shiftKey',
|
||||
'which'
|
||||
];
|
||||
|
||||
export function serializeMouseEvent(e: MouseEvent): StringMap<string, any> {
|
||||
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
|
||||
}
|
||||
|
||||
export function serializeKeyboardEvent(e: KeyboardEvent): StringMap<string, any> {
|
||||
return serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
|
||||
}
|
||||
|
||||
function serializeEvent(e: any, properties: List<string>): StringMap<string, any> {
|
||||
var serialized = {};
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
var prop = properties[i];
|
||||
serialized[prop] = e[prop];
|
||||
}
|
||||
return serialized;
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
* It takes care of spawning the worker and sending it the initial init message
|
||||
* It also acts and the messenger between the worker thread and the renderer running on the UI
|
||||
* thread
|
||||
* TODO: This class might need to be refactored to match application.ts...
|
||||
*/
|
||||
|
||||
import {createInjector} from "./di_bindings";
|
||||
@ -16,12 +15,14 @@ import {
|
||||
RenderProtoViewRef,
|
||||
RenderProtoViewMergeMapping,
|
||||
RenderViewRef,
|
||||
RenderEventDispatcher,
|
||||
RenderFragmentRef
|
||||
} from "angular2/src/render/api";
|
||||
import {Type, print, BaseException} from "angular2/src/facade/lang";
|
||||
import {Type, print, BaseException, isFunction} from "angular2/src/facade/lang";
|
||||
import {Promise, PromiseWrapper} from "angular2/src/facade/async";
|
||||
import {StringMapWrapper, SetWrapper} from 'angular2/src/facade/collection';
|
||||
import {Serializer} from "angular2/src/web-workers/shared/serializer";
|
||||
import {MessageBus} from "angular2/src/web-workers/shared/message_bus";
|
||||
import {MessageBus, MessageBusSink} from "angular2/src/web-workers/shared/message_bus";
|
||||
import {
|
||||
RenderViewWithFragmentsStore
|
||||
} from 'angular2/src/web-workers/shared/render_view_with_fragments_store';
|
||||
@ -32,6 +33,10 @@ import {ExceptionHandler} from 'angular2/src/core/exception_handler';
|
||||
import {Injectable} from 'angular2/di';
|
||||
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {
|
||||
serializeMouseEvent,
|
||||
serializeKeyboardEvent
|
||||
} from 'angular2/src/web-workers/ui/event_serializer';
|
||||
|
||||
/**
|
||||
* Creates a zone, sets up the DI bindings
|
||||
@ -74,11 +79,11 @@ export class WebWorkerMain {
|
||||
* Sends an error back to the worker thread in response to an opeartion on the UI thread
|
||||
*/
|
||||
private _sendWorkerError(id: string, error: any) {
|
||||
this._sendWorkerMessage("error", {"id": id, "error": error});
|
||||
this._sendWorkerMessage("error", {"error": error}, id);
|
||||
}
|
||||
|
||||
private _sendWorkerMessage(type: string, data: StringMap<string, any>) {
|
||||
this._bus.sink.send({'type': type, 'value': data});
|
||||
private _sendWorkerMessage(type: string, value: StringMap<string, any>, id?: string) {
|
||||
this._bus.sink.send({'type': type, 'id': id, 'value': value});
|
||||
}
|
||||
|
||||
// TODO: Transfer the types with the serialized data so this can be automated?
|
||||
@ -190,12 +195,17 @@ export class WebWorkerMain {
|
||||
var methodArgs = args[2];
|
||||
this._renderer.invokeElementMethod(elementRef, methodName, methodArgs);
|
||||
break;
|
||||
case "setEventDispatcher":
|
||||
var viewRef = this._serializer.deserialize(args[0], RenderViewRef);
|
||||
var dispatcher = new EventDispatcher(viewRef, this._bus.sink, this._serializer);
|
||||
this._renderer.setEventDispatcher(viewRef, dispatcher);
|
||||
break;
|
||||
default:
|
||||
throw new BaseException("Not Implemented");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Create message type
|
||||
// TODO(jteplitz602): Create message type enum #3044
|
||||
private _handleWorkerMessage(message: StringMap<string, any>) {
|
||||
var data: ReceivedMessage = new ReceivedMessage(message['data']);
|
||||
switch (data.type) {
|
||||
@ -211,8 +221,7 @@ export class WebWorkerMain {
|
||||
private _wrapWorkerPromise(id: string, promise: Promise<any>, type: Type): void {
|
||||
PromiseWrapper.then(promise, (result: any) => {
|
||||
try {
|
||||
this._sendWorkerMessage("result",
|
||||
{"id": id, "value": this._serializer.serialize(result, type)});
|
||||
this._sendWorkerMessage("result", this._serializer.serialize(result, type), id);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
@ -220,6 +229,50 @@ export class WebWorkerMain {
|
||||
}
|
||||
}
|
||||
|
||||
class EventDispatcher implements RenderEventDispatcher {
|
||||
constructor(private _viewRef: RenderViewRef, private _sink: MessageBusSink,
|
||||
private _serializer: Serializer) {}
|
||||
|
||||
dispatchRenderEvent(elementIndex: number, eventName: string, locals: Map<string, any>) {
|
||||
var e = locals.get('$event');
|
||||
var serializedEvent;
|
||||
switch (eventName) {
|
||||
case "click":
|
||||
case "mouseup":
|
||||
case "mousedown":
|
||||
case "dblclick":
|
||||
case "contextmenu":
|
||||
case "mouseenter":
|
||||
case "mouseleave":
|
||||
case "mousemove":
|
||||
case "mouseout":
|
||||
case "mouseover":
|
||||
case "show":
|
||||
serializedEvent = serializeMouseEvent(e);
|
||||
break;
|
||||
case "keydown":
|
||||
case "keypress":
|
||||
case "keyup":
|
||||
serializedEvent = serializeKeyboardEvent(e);
|
||||
break;
|
||||
default:
|
||||
throw new BaseException(eventName + " not supported on WebWorkers");
|
||||
}
|
||||
var serializedLocals = StringMapWrapper.create();
|
||||
StringMapWrapper.set(serializedLocals, '$event', serializedEvent);
|
||||
|
||||
this._sink.send({
|
||||
"type": "event",
|
||||
"value": {
|
||||
"viewRef": this._serializer.serialize(this._viewRef, RenderViewRef),
|
||||
"elementIndex": elementIndex,
|
||||
"eventName": eventName,
|
||||
"locals": serializedLocals
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ReceivedMessage {
|
||||
method: string;
|
||||
args: List<any>;
|
||||
|
@ -101,7 +101,7 @@ function _injectorBindings(appComponentType, bus: WorkerMessageBus,
|
||||
Serializer,
|
||||
bind(WorkerMessageBus).toValue(bus),
|
||||
bind(MessageBroker)
|
||||
.toFactory((a, b) => new MessageBroker(a, b), [WorkerMessageBus, Serializer]),
|
||||
.toFactory((a, b, c) => new MessageBroker(a, b, c), [WorkerMessageBus, Serializer, NgZone]),
|
||||
WorkerRenderer,
|
||||
bind(Renderer).toAlias(WorkerRenderer),
|
||||
WorkerCompiler,
|
||||
@ -172,11 +172,6 @@ export function bootstrapWebworkerCommon(
|
||||
PromiseWrapper.then(compRefToken, tick,
|
||||
(err, stackTrace) => { bootstrapProcess.reject(err, stackTrace); });
|
||||
|
||||
PromiseWrapper.catchError(compRefToken, (err) => {
|
||||
print(err);
|
||||
bootstrapProcess.reject(err, err.stack);
|
||||
});
|
||||
|
||||
bus.source.removeListener(listenerId);
|
||||
});
|
||||
|
||||
|
@ -6,12 +6,17 @@ import {ListWrapper, StringMapWrapper, MapWrapper} from "../../facade/collection
|
||||
import {Serializer} from "angular2/src/web-workers/shared/serializer";
|
||||
import {Injectable} from "angular2/di";
|
||||
import {Type} from "angular2/src/facade/lang";
|
||||
import {RenderViewRef, RenderEventDispatcher} from 'angular2/src/render/api';
|
||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||
|
||||
@Injectable()
|
||||
export class MessageBroker {
|
||||
private _pending: Map<string, Function> = new Map<string, Function>();
|
||||
private _pending: Map<string, PromiseCompleter<any>> = new Map<string, PromiseCompleter<any>>();
|
||||
private _eventDispatchRegistry: Map<RenderViewRef, RenderEventDispatcher> =
|
||||
new Map<RenderViewRef, RenderEventDispatcher>();
|
||||
|
||||
constructor(private _messageBus: MessageBus, protected _serializer: Serializer) {
|
||||
constructor(private _messageBus: MessageBus, protected _serializer: Serializer,
|
||||
private _zone: NgZone) {
|
||||
this._messageBus.source.addListener((data) => this._handleMessage(data['data']));
|
||||
}
|
||||
|
||||
@ -43,17 +48,17 @@ export class MessageBroker {
|
||||
if (returnType != null) {
|
||||
var completer: PromiseCompleter<any> = PromiseWrapper.completer();
|
||||
id = this._generateMessageId(args.type + args.method);
|
||||
this._pending.set(id, completer.resolve);
|
||||
this._pending.set(id, completer);
|
||||
PromiseWrapper.catchError(completer.promise, (err, stack?) => {
|
||||
print(err);
|
||||
completer.reject(err, stack);
|
||||
});
|
||||
|
||||
promise = PromiseWrapper.then(completer.promise, (data: MessageResult) => {
|
||||
promise = PromiseWrapper.then(completer.promise, (value: any) => {
|
||||
if (this._serializer == null) {
|
||||
return data.value;
|
||||
return value;
|
||||
} else {
|
||||
return this._serializer.deserialize(data.value, returnType);
|
||||
return this._serializer.deserialize(value, returnType);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@ -73,35 +78,67 @@ export class MessageBroker {
|
||||
private _handleMessage(message: StringMap<string, any>): void {
|
||||
var data = new MessageData(message);
|
||||
// TODO(jteplitz602): replace these strings with messaging constants
|
||||
var id = data.value.id;
|
||||
if (this._pending.has(id)) {
|
||||
this._pending.get(id)(data.value);
|
||||
this._pending.delete(id);
|
||||
if (data.type === "event") {
|
||||
this._dispatchEvent(new RenderEventData(data.value, this._serializer));
|
||||
} else if (data.type === "result" || data.type === "error") {
|
||||
var id = data.id;
|
||||
if (this._pending.has(id)) {
|
||||
if (data.type === "result") {
|
||||
this._pending.get(id).resolve(data.value);
|
||||
} else {
|
||||
this._pending.get(id).reject(data.value, null);
|
||||
}
|
||||
this._pending.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _dispatchEvent(eventData: RenderEventData): void {
|
||||
var dispatcher = this._eventDispatchRegistry.get(eventData.viewRef);
|
||||
this._zone.run(() => {
|
||||
dispatcher.dispatchRenderEvent(eventData.elementIndex, eventData.eventName, eventData.locals);
|
||||
});
|
||||
}
|
||||
|
||||
registerEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher): void {
|
||||
this._eventDispatchRegistry.set(viewRef, dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
class RenderEventData {
|
||||
viewRef: RenderViewRef;
|
||||
elementIndex: number;
|
||||
eventName: string;
|
||||
locals: Map<string, any>;
|
||||
|
||||
constructor(message: StringMap<string, any>, serializer: Serializer) {
|
||||
this.viewRef = serializer.deserialize(message['viewRef'], RenderViewRef);
|
||||
this.elementIndex = message['elementIndex'];
|
||||
this.eventName = message['eventName'];
|
||||
this.locals = MapWrapper.createFromStringMap(message['locals']);
|
||||
}
|
||||
}
|
||||
|
||||
class MessageData {
|
||||
type: string;
|
||||
value: MessageResult;
|
||||
value: any;
|
||||
id: string;
|
||||
|
||||
constructor(data: StringMap<string, any>) {
|
||||
this.type = StringMapWrapper.get(data, "type");
|
||||
if (StringMapWrapper.contains(data, "value")) {
|
||||
this.value = new MessageResult(StringMapWrapper.get(data, "value"));
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
this.id = this._getValueIfPresent(data, "id");
|
||||
this.value = this._getValueIfPresent(data, "value");
|
||||
}
|
||||
}
|
||||
|
||||
class MessageResult {
|
||||
id: string;
|
||||
value: any;
|
||||
|
||||
constructor(result: StringMap<string, any>) {
|
||||
this.id = StringMapWrapper.get(result, "id");
|
||||
this.value = StringMapWrapper.get(result, "value");
|
||||
/**
|
||||
* Returns the value from the StringMap if present. Otherwise returns null
|
||||
*/
|
||||
_getValueIfPresent(data: StringMap<string, any>, key: string) {
|
||||
if (StringMapWrapper.contains(data, key)) {
|
||||
return StringMapWrapper.get(data, key);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,6 +255,9 @@ export class WorkerRenderer implements Renderer {
|
||||
* Sets the dispatcher for all events of the given view
|
||||
*/
|
||||
setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher) {
|
||||
// TODO(jteplitz602) support dom events in web worker. See #3046
|
||||
var fnArgs = [new FnArg(viewRef, RenderViewRef)];
|
||||
var args = new UiArguments("renderer", "setEventDispatcher", fnArgs);
|
||||
this._messageBroker.registerEventDispatcher(viewRef, dispatcher);
|
||||
this._messageBroker.runOnUiThread(args, null);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user