X Tutup
Skip to content

Commit 696edde

Browse files
committed
fix(WebWorker): Fix Todo Server demo and add test to ensure the demo can bootstrap.
Closes #3970
1 parent 3ff3214 commit 696edde

File tree

9 files changed

+134
-115
lines changed

9 files changed

+134
-115
lines changed
Lines changed: 56 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,8 @@
11
library angular2.src.web_workers.event_serializer;
22

3-
import 'package:angular2/src/core/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';
103
import 'dart:core';
114
import 'dart:html';
125

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-
final Map EVENT_PROPERTIES = {
56-
#bubbles: bool,
57-
#cancelable: bool,
58-
#defaultPrevented: bool,
59-
#eventPhase: int,
60-
#timeStamp: int,
61-
#type: String
62-
};
63-
646
// List of all elements with HTML value attribute.
657
// Taken from: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
668
final Set<String> NODES_WITH_VALUE = new Set<String>.from([
@@ -75,23 +17,74 @@ final Set<String> NODES_WITH_VALUE = new Set<String>.from([
7517
]);
7618

7719
Map<String, dynamic> serializeGenericEvent(dynamic e) {
78-
return serializeEvent(e, EVENT_PROPERTIES);
20+
var serialized = new Map<String, dynamic>();
21+
serialized['bubbles'] = e.bubbles;
22+
serialized['cancelable'] = e.cancelable;
23+
serialized['defaultPrevented'] = e.defaultPrevented;
24+
serialized['eventPhase'] = e.eventPhase;
25+
serialized['timeStamp'] = e.timeStamp;
26+
serialized['type'] = e.type;
27+
return serialized;
7928
}
8029

8130
// TODO(jteplitz602): Allow users to specify the properties they need rather than always
8231
// adding value #3374
8332
Map<String, dynamic> serializeEventWithTarget(dynamic e) {
84-
var serializedEvent = serializeEvent(e, EVENT_PROPERTIES);
33+
var serializedEvent = serializeGenericEvent(e);
8534
return addTarget(e, serializedEvent);
8635
}
8736

8837
Map<String, dynamic> serializeMouseEvent(dynamic e) {
89-
return serializeEvent(e, MOUSE_EVENT_PROPERTIES);
38+
var serialized = new Map<String, dynamic>();
39+
serialized['altKey'] = e.altKey;
40+
serialized['bubbles'] = e.bubbles;
41+
serialized['button'] = e.button;
42+
serialized['cancelable'] = e.cancelable;
43+
serialized['client'] = serializePoint(e.client);
44+
serialized['ctrlKey'] = e.ctrlKey;
45+
serialized['defaultPrevented'] = e.defaultPrevented;
46+
serialized['detail'] = e.detail;
47+
serialized['eventPhase'] = e.eventPhase;
48+
serialized['layer'] = serializePoint(e.layer);
49+
serialized['metaKey'] = e.metaKey;
50+
serialized['offset'] = serializePoint(e.offset);
51+
serialized['page'] = serializePoint(e.page);
52+
serialized['region'] = e.region;
53+
serialized['screen'] = serializePoint(e.screen);
54+
serialized['shiftKey'] = e.shiftKey;
55+
serialized['timeStamp'] = e.timeStamp;
56+
serialized['type'] = e.type;
57+
return serialized;
58+
}
59+
60+
Map<String, dynamic> serializePoint(Point point) {
61+
var serialized = new Map<String, dynamic>();
62+
serialized['magnitude'] = point.magnitude;
63+
serialized['x'] = point.x;
64+
serialized['y'] = point.y;
65+
return serialized;
9066
}
9167

9268
Map<String, dynamic> serializeKeyboardEvent(dynamic e) {
93-
var serializedEvent = serializeEvent(e, KEYBOARD_EVENT_PROPERTIES);
94-
return addTarget(e, serializedEvent);
69+
var serialized = new Map<String, dynamic>();
70+
serialized['altKey'] = e.altKey;
71+
serialized['bubbles'] = e.bubbles;
72+
serialized['cancelable'] = e.cancelable;
73+
serialized['charCode'] = e.charCode;
74+
serialized['ctrlKey'] = e.ctrlKey;
75+
serialized['defaultPrevented'] = e.defaultPrevented;
76+
serialized['detail'] = e.detail;
77+
serialized['eventPhase'] = e.eventPhase;
78+
serialized['keyCode'] = e.keyCode;
79+
serialized['keyLocation'] = e.keyLocation;
80+
serialized['layer'] = serializePoint(e.layer);
81+
serialized['location'] = e.location;
82+
serialized['repeat'] = e.repeat;
83+
serialized['shiftKey'] = e.shiftKey;
84+
serialized['timeStamp'] = e.timeStamp;
85+
serialized['type'] = e.type;
86+
//return addTarget(e, serialized);
87+
return serialized;
9588
}
9689

9790
// TODO(jteplitz602): #3374. See above.
@@ -105,24 +98,3 @@ Map<String, dynamic> addTarget(
10598
}
10699
return serializedEvent;
107100
}
108-
109-
Map<String, dynamic> serializeEvent(dynamic e, Map<Symbol, Type> PROPERTIES) {
110-
var serialized = StringMapWrapper.create();
111-
var mirror = reflect(e);
112-
PROPERTIES.forEach((property, type) {
113-
var value = mirror.getField(property).reflectee;
114-
var propertyName = MirrorSystem.getName(property);
115-
if (type == int || type == bool || type == String) {
116-
serialized[propertyName] = value;
117-
} else if (type == Point) {
118-
var point = reflect(value);
119-
serialized[propertyName] = {
120-
'magnitude': point.getField(#magnitude).reflectee,
121-
'x': point.getField(#x).reflectee,
122-
'y': point.getField(#y).reflectee
123-
};
124-
}
125-
});
126-
127-
return serialized;
128-
}

modules/angular2/src/web_workers/worker/application_common.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ function _injectorBindings(appComponentType, bus: MessageBus, initData: StringMa
9090
bind(APP_COMPONENT_REF_PROMISE)
9191
.toFactory(
9292
(dynamicComponentLoader, injector) => {
93-
9493
// TODO(rado): investigate whether to support bindings on root component.
9594
return dynamicComponentLoader.loadAsRoot(appComponentType, null, injector)
9695
.then((componentRef) => { return componentRef; });
@@ -150,32 +149,39 @@ export function bootstrapWebWorkerCommon(
150149
// index.html and main.js are possible.
151150
//
152151

153-
154152
var subscription: any;
155153
var emitter = bus.from(SETUP_CHANNEL);
156154
subscription = ObservableWrapper.subscribe(emitter, (message: StringMap<string, any>) => {
157-
var appInjector =
158-
_createAppInjector(appComponentType, componentInjectableBindings, zone, bus, message);
159-
var compRefToken = PromiseWrapper.wrap(() => {
160-
try {
161-
return appInjector.get(APP_COMPONENT_REF_PROMISE);
162-
} catch (e) {
163-
throw e;
164-
}
165-
});
166-
var tick = (componentRef) => {
167-
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
168-
// retrieve life cycle: may have already been created if injected in root component
169-
var lc = appInjector.get(LifeCycle);
170-
lc.registerWith(zone, appChangeDetector);
171-
lc.tick(); // the first tick that will bootstrap the app
155+
var exceptionHandler;
156+
try {
157+
var appInjector =
158+
_createAppInjector(appComponentType, componentInjectableBindings, zone, bus, message);
159+
exceptionHandler = appInjector.get(ExceptionHandler);
160+
zone.overrideOnErrorHandler((e, s) => exceptionHandler.call(e, s));
161+
var compRefToken: Promise<any> = appInjector.get(APP_COMPONENT_REF_PROMISE);
162+
var tick = (componentRef) => {
163+
var appChangeDetector = internalView(componentRef.hostView).changeDetector;
164+
// retrieve life cycle: may have already been created if injected in root component
165+
var lc = appInjector.get(LifeCycle);
166+
lc.registerWith(zone, appChangeDetector);
167+
lc.tick(); // the first tick that will bootstrap the app
172168

173-
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
174-
};
175-
PromiseWrapper.then(compRefToken, tick,
176-
(err, stackTrace) => { bootstrapProcess.reject(err, stackTrace); });
169+
bootstrapProcess.resolve(new ApplicationRef(componentRef, appComponentType, appInjector));
170+
};
177171

178-
ObservableWrapper.dispose(subscription);
172+
var tickResult = PromiseWrapper.then(compRefToken, tick);
173+
174+
PromiseWrapper.then(tickResult,
175+
(_) => {}); // required for Dart to trigger the default error handler
176+
PromiseWrapper.then(tickResult, null,
177+
(err, stackTrace) => { bootstrapProcess.reject(err, stackTrace); });
178+
ObservableWrapper.dispose(subscription);
179+
} catch (e) {
180+
if (isPresent(exceptionHandler)) {
181+
exceptionHandler.call(e, e.stack);
182+
}
183+
bootstrapProcess.reject(e, e.stack);
184+
}
179185
});
180186

181187
ObservableWrapper.callNext(bus.to(SETUP_CHANNEL), "ready");
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library angular2.test.web_workers.debug_tools.bootstrap;
2+
3+
import "package:angular2/test_lib.dart";
4+
import "package:angular2/src/core/reflection/reflection_capabilities.dart";
5+
import "package:angular2/src/core/reflection/reflection.dart";
6+
import "package:angular2/web_worker/worker.dart";
7+
import "package:angular2/src/web_workers/worker/application_common.dart";
8+
import "../shared/web_worker_test_util.dart";
9+
import "dart:convert";
10+
11+
main() {
12+
describe("bootstrapWebWorkerCommon", () {
13+
it ("should bootstrap on a Dart VM", () {
14+
reflector.reflectionCapabilities = new ReflectionCapabilities();
15+
var buses = createPairedMessageBuses();
16+
bootstrapWebWorkerCommon(App, buses.worker);
17+
});
18+
});
19+
}
20+
21+
@Component(selector: "app")
22+
@View(template: "<p>Hello {{name}}</p>")
23+
class App {
24+
String name = "Tester";
25+
}

modules/angular2/test/web_workers/shared/mock_event_emitter.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@ import 'dart:async';
55
import "package:angular2/src/core/facade/async.dart";
66

77
class MockEventEmitter extends EventEmitter {
8-
List<Function> _nextFns = new List();
8+
final controller = new StreamController.broadcast(sync: true);
99

1010
@override
1111
StreamSubscription listen(void onData(dynamic line),
1212
{void onError(Error error), void onDone(), bool cancelOnError}) {
13-
_nextFns.add(onData);
14-
return null;
13+
return controller.stream.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
1514
}
1615

1716
@override
1817
void add(value) {
19-
_nextFns.forEach((fn) => fn(value));
18+
controller.add(value);
2019
}
2120
}

modules/angular2/test/web_workers/shared/mock_event_emitter.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ export class MockEventEmitter extends EventEmitter {
99

1010
observer(generator: any): Rx.IDisposable {
1111
this._nextFns.push(generator.next);
12-
return null;
12+
return new MockDisposable();
1313
}
1414

1515
next(value: any) {
1616
ListWrapper.forEach(this._nextFns, (fn) => { fn(value); });
1717
}
1818
}
19+
20+
class MockDisposable implements Rx.IDisposable {
21+
dispose(): void {}
22+
}

modules/examples/pubspec.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ transformers:
3535
- web/src/observable_models/index.dart
3636
- web/src/person_management/index.dart
3737
- web/src/template_driven_forms/index.dart
38+
- web/src/web_workers/todo/server_index.dart
39+
- web/src/web_workers/todo/background_index.dart
40+
- web/src/web_workers/message_broker/background_index.dart
41+
- web/src/web_workers/kitchen_sink/background_index.dart
42+
43+
# These entrypoints are disabled untl the transformer supports UI bootstrap (issue #3971)
44+
# - web/src/web_workers/message_broker/index.dart
45+
# - web/src/web_workers/kitchen_sink/index.dart
46+
# - web/src/web_workers/todo/index.dart
3847
# These entrypoints are disabled until cross-package urls are working (issue #2982)
3948
# - web/src/material/button/index.dart
4049
# - web/src/material/checkbox/index.dart

modules/examples/src/web_workers/todo/index_common.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import {NgFor} from 'angular2/src/core/directives/ng_for';
2-
import {View, Component} from 'angular2/src/core/metadata';
3-
import {FORM_DIRECTIVES} from 'angular2/src/forms/directives';
1+
import {NgFor, View, Component, FORM_DIRECTIVES} from 'angular2/web_worker/worker';
42
import {Store, Todo, TodoFactory} from './services/TodoStore';
53

64
@Component({selector: 'todo-app', viewBindings: [Store, TodoFactory]})

modules/examples/src/web_workers/todo/services/TodoStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Injectable} from 'angular2/angular2';
1+
import {Injectable} from 'angular2/web_worker/worker';
22
import {ListWrapper, Predicate} from 'angular2/src/core/facade/collection';
33

44
// base model for RecordStore

modules_dart/transform/lib/src/transform/common/annotation_matcher.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const INJECTABLES = const [
1515
const ClassDescriptor('Injectable', 'package:angular2/di.dart'),
1616
const ClassDescriptor('Injectable', 'package:angular2/angular2.dart'),
1717
const ClassDescriptor('Injectable', 'package:angular2/bootstrap_static.dart'),
18+
const ClassDescriptor('Injectable', 'package:angular2/web_worker/worker.dart'),
1819
];
1920

2021
const DIRECTIVES = const [
@@ -30,6 +31,8 @@ const DIRECTIVES = const [
3031
superClass: 'Injectable'),
3132
const ClassDescriptor('Directive', 'package:angular2/bootstrap_static.dart',
3233
superClass: 'Injectable'),
34+
const ClassDescriptor('Directive', 'package:angular2/web_worker/worker.dart',
35+
superClass: 'Injectable'),
3336
];
3437

3538
const COMPONENTS = const [
@@ -45,10 +48,13 @@ const COMPONENTS = const [
4548
superClass: 'Directive'),
4649
const ClassDescriptor('Component', 'package:angular2/core.dart',
4750
superClass: '`Directive'),
51+
const ClassDescriptor('Component', 'package:angular2/web_worker/worker.dart',
52+
superClass: '`Directive'),
4853
];
4954

5055
const VIEWS = const [
5156
const ClassDescriptor('View', 'package:angular2/angular2.dart'),
57+
const ClassDescriptor('View', 'package:angular2/web_worker/worker.dart'),
5258
const ClassDescriptor('View', 'package:angular2/bootstrap_static.dart'),
5359
const ClassDescriptor('View', 'package:angular2/core.dart'),
5460
const ClassDescriptor('View', 'package:angular2/src/core/metadata/view.dart'),

0 commit comments

Comments
 (0)
X Tutup