Skip to content

Commit 7b834e0

Browse files
committed
feat(WebWorkers) Add DOM event support
closes angular#3046
1 parent 8e960d4 commit 7b834e0

27 files changed

Lines changed: 556 additions & 165 deletions

modules/angular2/src/web-workers/shared/render_view_with_fragments_store.ts

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,22 @@ export class RenderViewWithFragmentsStore {
1212

1313
constructor(@Inject(ON_WEBWORKER) onWebWorker) {
1414
this._onWebWorker = onWebWorker;
15-
if (!onWebWorker) {
16-
this._lookupByIndex = new Map<number, RenderViewRef | RenderFragmentRef>();
17-
this._lookupByView = new Map<RenderViewRef | RenderFragmentRef, number>();
18-
}
15+
this._lookupByIndex = new Map<number, RenderViewRef | RenderFragmentRef>();
16+
this._lookupByView = new Map<RenderViewRef | RenderFragmentRef, number>();
1917
}
2018

2119
allocate(fragmentCount: number): RenderViewWithFragments {
20+
var initialIndex = this._nextIndex;
21+
2222
var viewRef = new WorkerRenderViewRef(this._nextIndex++);
2323
var fragmentRefs = ListWrapper.createGrowableSize(fragmentCount);
2424

2525
for (var i = 0; i < fragmentCount; i++) {
2626
fragmentRefs[i] = new WorkerRenderFragmentRef(this._nextIndex++);
2727
}
28-
return new RenderViewWithFragments(viewRef, fragmentRefs);
28+
var renderViewWithFragments = new RenderViewWithFragments(viewRef, fragmentRefs);
29+
this.store(renderViewWithFragments, initialIndex);
30+
return renderViewWithFragments;
2931
}
3032

3133
store(view: RenderViewWithFragments, startIndex: number) {
@@ -60,23 +62,15 @@ export class RenderViewWithFragmentsStore {
6062
return null;
6163
}
6264

63-
if (this._onWebWorker) {
64-
return WorkerRenderViewRef.deserialize(ref);
65-
} else {
66-
return this.retreive(ref);
67-
}
65+
return this.retreive(ref);
6866
}
6967

7068
deserializeRenderFragmentRef(ref: number): RenderFragmentRef {
7169
if (ref == null) {
7270
return null;
7371
}
7472

75-
if (this._onWebWorker) {
76-
return WorkerRenderFragmentRef.deserialize(ref);
77-
} else {
78-
return this.retreive(ref);
79-
}
73+
return this.retreive(ref);
8074
}
8175

8276
private _serializeRenderFragmentOrViewRef(ref: RenderViewRef | RenderFragmentRef): number {
@@ -114,20 +108,11 @@ export class RenderViewWithFragmentsStore {
114108
return null;
115109
}
116110

117-
var viewRef: RenderViewRef | RenderFragmentRef;
118-
var fragments: List<RenderViewRef | RenderFragmentRef>;
119-
if (this._onWebWorker) {
120-
viewRef = WorkerRenderViewRef.deserialize(obj['viewRef']);
121-
fragments =
122-
ListWrapper.map(obj['fragmentRefs'], (val) => WorkerRenderFragmentRef.deserialize(val));
123-
124-
return new RenderViewWithFragments(viewRef, fragments);
125-
} else {
126-
viewRef = this.retreive(obj['viewRef']);
127-
fragments = ListWrapper.map(obj['fragmentRefs'], (val) => this.retreive(val));
111+
var viewRef = this.deserializeRenderViewRef(obj['viewRef']);
112+
var fragments =
113+
ListWrapper.map(obj['fragmentRefs'], (val) => this.deserializeRenderFragmentRef(val));
128114

129-
return new RenderViewWithFragments(viewRef, fragments);
130-
}
115+
return new RenderViewWithFragments(viewRef, fragments);
131116
}
132117
}
133118

modules/angular2/src/web-workers/shared/serializer.ts

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
1-
import {Type, isArray, isPresent, serializeEnum, deserializeEnum} from "angular2/src/facade/lang";
2-
import {List, ListWrapper, Map, StringMapWrapper, MapWrapper} from "angular2/src/facade/collection";
1+
import {
2+
Type,
3+
isArray,
4+
isPresent,
5+
serializeEnum,
6+
deserializeEnum,
7+
BaseException
8+
} from "angular2/src/facade/lang";
9+
import {
10+
List,
11+
ListWrapper,
12+
Map,
13+
StringMap,
14+
StringMapWrapper,
15+
MapWrapper
16+
} from "angular2/src/facade/collection";
317
import {
418
ProtoViewDto,
519
DirectiveMetadata,
@@ -13,7 +27,8 @@ import {
1327
RenderViewRef,
1428
RenderFragmentRef,
1529
RenderElementRef,
16-
ViewType
30+
ViewType,
31+
ViewEncapsulation
1732
} from "angular2/src/render/api";
1833
import {WorkerElementRef} from 'angular2/src/web-workers/shared/api';
1934
import {AST, ASTWithSource} from 'angular2/src/change_detection/change_detection';
@@ -30,11 +45,18 @@ export class Serializer {
3045
constructor(private _parser: Parser, private _protoViewStore: RenderProtoViewRefStore,
3146
private _renderViewStore: RenderViewWithFragmentsStore) {
3247
this._enumRegistry = new Map<any, Map<int, any>>();
48+
3349
var viewTypeMap = new Map<int, any>();
3450
viewTypeMap[0] = ViewType.HOST;
3551
viewTypeMap[1] = ViewType.COMPONENT;
3652
viewTypeMap[2] = ViewType.EMBEDDED;
3753
this._enumRegistry.set(ViewType, viewTypeMap);
54+
55+
var viewEncapsulationMap = new Map<int, any>();
56+
viewEncapsulationMap[0] = ViewEncapsulation.EMULATED;
57+
viewEncapsulationMap[1] = ViewEncapsulation.NATIVE;
58+
viewEncapsulationMap[2] = ViewEncapsulation.NONE;
59+
this._enumRegistry.set(ViewEncapsulation, viewEncapsulationMap);
3860
}
3961

4062
serialize(obj: any, type: Type): Object {
@@ -71,8 +93,10 @@ export class Serializer {
7193
return this._renderViewStore.serializeRenderFragmentRef(obj);
7294
} else if (type == WorkerElementRef) {
7395
return this._serializeWorkerElementRef(obj);
96+
} else if (type == EventBinding) {
97+
return this._serializeEventBinding(obj);
7498
} else {
75-
throw "No serializer for " + type.toString();
99+
throw new BaseException("No serializer for " + type.toString());
76100
}
77101
}
78102

@@ -111,8 +135,10 @@ export class Serializer {
111135
return this._renderViewStore.deserializeRenderFragmentRef(map);
112136
} else if (type == WorkerElementRef) {
113137
return this._deserializeWorkerElementRef(map);
138+
} else if (type == EventBinding) {
139+
return this._deserializeEventBinding(map);
114140
} else {
115-
throw "No deserializer for " + type.toString();
141+
throw new BaseException("No deserializer for " + type.toString());
116142
}
117143
}
118144

@@ -148,6 +174,15 @@ export class Serializer {
148174

149175
allocateRenderViews(fragmentCount: number) { this._renderViewStore.allocate(fragmentCount); }
150176

177+
private _serializeEventBinding(binding: EventBinding): StringMap<string, any> {
178+
return {'fullName': binding.fullName, 'source': this.serialize(binding.source, ASTWithSource)};
179+
}
180+
181+
private _deserializeEventBinding(map: StringMap<string, any>): EventBinding {
182+
return new EventBinding(map['fullName'],
183+
this.deserialize(map['source'], ASTWithSource, "binding"));
184+
}
185+
151186
private _serializeWorkerElementRef(elementRef: RenderElementRef): StringMap<string, any> {
152187
return {
153188
'renderView': this.serialize(elementRef.renderView, RenderViewRef),
@@ -214,7 +249,7 @@ export class Serializer {
214249
'directives': this.serialize(view.directives, DirectiveMetadata),
215250
'styleAbsUrls': view.styleAbsUrls,
216251
'styles': view.styles,
217-
'encapsulation': view.encapsulation
252+
'encapsulation': serializeEnum(view.encapsulation)
218253
};
219254
}
220255

@@ -225,7 +260,8 @@ export class Serializer {
225260
directives: this.deserialize(obj['directives'], DirectiveMetadata),
226261
styleAbsUrls: obj['styleAbsUrls'],
227262
styles: obj['styles'],
228-
encapsulation: obj['encapsulation']
263+
encapsulation:
264+
deserializeEnum(obj['encapsulation'], this._enumRegistry.get(ViewEncapsulation))
229265
});
230266
}
231267

@@ -293,7 +329,7 @@ export class Serializer {
293329
variableBindings: this.objectToMap(obj['variableBindings']),
294330
textBindings: this.deserialize(obj['textBindings'], ASTWithSource, "interpolation"),
295331
type: deserializeEnum(obj['type'], this._enumRegistry.get(ViewType)),
296-
transitiveNgContentCount: obj['transitivengContentCount']
332+
transitiveNgContentCount: obj['transitiveNgContentCount']
297333
});
298334
}
299335

modules/angular2/src/web-workers/ui/di_bindings.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// TODO: This whole file is nearly identical to core/application.ts.
2-
// There should be a way to refactor application so that this file is unnecessary
1+
// TODO (jteplitz602): This whole file is nearly identical to core/application.ts.
2+
// There should be a way to refactor application so that this file is unnecessary. See #3277
33
import {Injector, bind, Binding} from "angular2/di";
44
import {Type, isBlank, isPresent} from "angular2/src/facade/lang";
55
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
@@ -21,13 +21,16 @@ import {KeyEventsPlugin} from 'angular2/src/render/dom/events/key_events';
2121
import {HammerGesturesPlugin} from 'angular2/src/render/dom/events/hammer_gestures';
2222
import {AppViewPool, APP_VIEW_POOL_CAPACITY} from 'angular2/src/core/compiler/view_pool';
2323
import {Renderer, RenderCompiler} from 'angular2/src/render/api';
24+
import {AppRootUrl} from 'angular2/src/services/app_root_url';
2425
import {
2526
DomRenderer,
2627
DOCUMENT_TOKEN,
2728
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES,
2829
DefaultDomCompiler,
2930
APP_ID_RANDOM_BINDING
3031
} from 'angular2/src/render/render';
32+
import {ElementSchemaRegistry} from 'angular2/src/render/dom/schema/element_schema_registry';
33+
import {DomElementSchemaRegistry} from 'angular2/src/render/dom/schema/dom_element_schema_registry';
3134
import {
3235
SharedStylesHost,
3336
DomSharedStylesHost
@@ -73,11 +76,6 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
7376
} else if (JitChangeDetection.isSupported()) {
7477
bestChangeDetection = JitChangeDetection;
7578
}
76-
// compute the root url to pass to AppRootUrl
77-
/*var rootUrl: string;
78-
var a = DOM.createElement('a');
79-
DOM.resolveAndSetHref(a, './', null);
80-
rootUrl = DOM.getHref(a);*/
8179

8280
return [
8381
bind(DOCUMENT_TOKEN)
@@ -100,6 +98,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
10098
bind(SharedStylesHost).toAlias(DomSharedStylesHost),
10199
Serializer,
102100
bind(ON_WEBWORKER).toValue(false),
101+
bind(ElementSchemaRegistry).toValue(new DomElementSchemaRegistry()),
103102
RenderViewWithFragmentsStore,
104103
RenderProtoViewRefStore,
105104
ProtoViewFactory,
@@ -117,7 +116,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
117116
DirectiveResolver,
118117
Parser,
119118
Lexer,
120-
ExceptionHandler,
119+
bind(ExceptionHandler).toFactory(() => new ExceptionHandler(DOM), []),
121120
bind(XHR).toValue(new XHRImpl()),
122121
ComponentUrlMapper,
123122
UrlResolver,
@@ -126,6 +125,7 @@ function _injectorBindings(): List<Type | Binding | List<any>> {
126125
DynamicComponentLoader,
127126
Testability,
128127
AnchorBasedAppRootUrl,
128+
bind(AppRootUrl).toAlias(AnchorBasedAppRootUrl),
129129
WebWorkerMain
130130
];
131131
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
library angular2.src.web_workers.event_serializer;
2+
3+
import 'package:angular2/src/facade/collection.dart';
4+
// TODO(jteplitz602): Remove Mirrors from serialization #3348
5+
@MirrorsUsed(
6+
symbols: "altKey, bubbles, button, cancelable, client, ctrlKey, " +
7+
"defaultPrevented, detail, eventPhase, layer, metaKey, offset, page, region, screen, " +
8+
"shiftKey, timeStamp, type, magnitude, x, y, charCode, keyCode, keyLocation, location, repeat")
9+
import 'dart:mirrors';
10+
import 'dart:core';
11+
import 'dart:html';
12+
13+
// These Maps can't be const due to a dartj2 bug (see http://github.com/dart-lang/sdk/issues/21825)
14+
// Once that bug is fixed these should be const
15+
final Map MOUSE_EVENT_PROPERTIES = {
16+
#altKey: bool,
17+
#bubbles: bool,
18+
#button: int,
19+
#cancelable: bool,
20+
#client: Point,
21+
#ctrlKey: bool,
22+
#defaultPrevented: bool,
23+
#detail: int,
24+
#eventPhase: int,
25+
#layer: Point,
26+
#metaKey: bool,
27+
#offset: Point,
28+
#page: Point,
29+
#region: String,
30+
#screen: Point,
31+
#shiftKey: bool,
32+
#timeStamp: int,
33+
#type: String
34+
};
35+
36+
final Map KEYBOARD_EVENT_PROPERTIES = {
37+
#altKey: bool,
38+
#bubbles: bool,
39+
#cancelable: bool,
40+
#charCode: int,
41+
#ctrlKey: bool,
42+
#defaultPrevented: bool,
43+
#detail: int,
44+
#eventPhase: int,
45+
#keyCode: int,
46+
#keyLocation: int,
47+
#layer: Point,
48+
#location: int,
49+
#repeat: bool,
50+
#shiftKey: bool,
51+
#timeStamp: int,
52+
#type: String
53+
};
54+
55+
Map<String, dynamic> serializeMouseEvent(dynamic e) {
56+
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
57+
}
58+
59+
Map<String, dynamic> serializeKeyboardEvent(dynamic e) {
60+
return serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
61+
}
62+
63+
Map<String, dynamic> serializeEvent(dynamic e, Map<Symbol, Type> PROPERTIES) {
64+
var serialized = StringMapWrapper.create();
65+
var mirror = reflect(e);
66+
PROPERTIES.forEach((property, type) {
67+
var value = mirror.getField(property).reflectee;
68+
var propertyName = MirrorSystem.getName(property);
69+
if (type == int || type == bool || type == String) {
70+
serialized[propertyName] = value;
71+
} else if (type == Point) {
72+
var point = reflect(value);
73+
serialized[propertyName] = {
74+
'magnitude': point.getField(#magnitude).reflectee,
75+
'x': point.getField(#x).reflectee,
76+
'y': point.getField(#y).reflectee
77+
};
78+
}
79+
});
80+
81+
return serialized;
82+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {StringMap} from 'angular2/src/facade/collection';
2+
3+
const MOUSE_EVENT_PROPERTIES = [
4+
"altKey",
5+
"button",
6+
"clientX",
7+
"clientY",
8+
"metaKey",
9+
"movementX",
10+
"movementY",
11+
"offsetX",
12+
"offsetY",
13+
"region",
14+
"screenX",
15+
"screenY",
16+
"shiftKey"
17+
];
18+
19+
const KEYBOARD_EVENT_PROPERTIES = [
20+
'altkey',
21+
'charCode',
22+
'code',
23+
'ctrlKey',
24+
'isComposing',
25+
'key',
26+
'keyCode',
27+
'location',
28+
'metaKey',
29+
'repeat',
30+
'shiftKey',
31+
'which'
32+
];
33+
34+
export function serializeMouseEvent(e: MouseEvent): StringMap<string, any> {
35+
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
36+
}
37+
38+
export function serializeKeyboardEvent(e: KeyboardEvent): StringMap<string, any> {
39+
return serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
40+
}
41+
42+
function serializeEvent(e: any, properties: List<string>): StringMap<string, any> {
43+
var serialized = {};
44+
for (var i = 0; i < properties.length; i++) {
45+
var prop = properties[i];
46+
serialized[prop] = e[prop];
47+
}
48+
return serialized;
49+
}

0 commit comments

Comments
 (0)