parent
8e960d4052
commit
7b834e02ec
|
@ -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
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import {
|
||||
AsyncTestCompleter,
|
||||
inject,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
createTestInjector,
|
||||
beforeEachBindings,
|
||||
SpyObject,
|
||||
proxy
|
||||
} from 'angular2/test_lib';
|
||||
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||
import {Serializer} from 'angular2/src/web-workers/shared/serializer';
|
||||
import {NgZone} from 'angular2/src/core/zone/ng_zone';
|
||||
import {MessageBroker} from 'angular2/src/web-workers/worker/broker';
|
||||
import {MockMessageBus, MockMessageBusSink, MockMessageBusSource} from './worker_test_util';
|
||||
import {ON_WEBWORKER} from 'angular2/src/web-workers/shared/api';
|
||||
import {bind} from 'angular2/di';
|
||||
import {RenderProtoViewRefStore} from 'angular2/src/web-workers/shared/render_proto_view_ref_store';
|
||||
import {
|
||||
RenderViewWithFragmentsStore,
|
||||
WorkerRenderViewRef
|
||||
} from 'angular2/src/web-workers/shared/render_view_with_fragments_store';
|
||||
import {RenderEventDispatcher, RenderViewRef} from 'angular2/src/render/api';
|
||||
|
||||
export function main() {
|
||||
describe("MessageBroker", () => {
|
||||
beforeEachBindings(() => [
|
||||
bind(ON_WEBWORKER)
|
||||
.toValue(true),
|
||||
RenderProtoViewRefStore,
|
||||
RenderViewWithFragmentsStore
|
||||
]);
|
||||
|
||||
it("should dispatch events", inject([Serializer, NgZone], (serializer, zone) => {
|
||||
var bus = new MockMessageBus(new MockMessageBusSink(), new MockMessageBusSource());
|
||||
var broker = new MessageBroker(bus, serializer, zone);
|
||||
|
||||
var eventDispatcher = new SpyEventDispatcher();
|
||||
var viewRef = new WorkerRenderViewRef(0);
|
||||
serializer.allocateRenderViews(0); // serialize the ref so it's in the store
|
||||
viewRef =
|
||||
serializer.deserialize(serializer.serialize(viewRef, RenderViewRef), RenderViewRef);
|
||||
broker.registerEventDispatcher(viewRef, eventDispatcher);
|
||||
|
||||
var elementIndex = 15;
|
||||
var eventName = 'click';
|
||||
|
||||
bus.source.receive({
|
||||
'data': {
|
||||
'type': 'event',
|
||||
'value': {
|
||||
'viewRef': viewRef.serialize(),
|
||||
'elementIndex': elementIndex,
|
||||
'eventName': eventName
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(eventDispatcher.wasDispatched).toBeTruthy();
|
||||
expect(eventDispatcher.elementIndex).toEqual(elementIndex);
|
||||
expect(eventDispatcher.eventName).toEqual(eventName);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
class SpyEventDispatcher implements RenderEventDispatcher {
|
||||
wasDispatched: boolean = false;
|
||||
elementIndex: number;
|
||||
eventName: string;
|
||||
|
||||
dispatchRenderEvent(elementIndex: number, eventName: string, locals: Map<string, any>) {
|
||||
this.wasDispatched = true;
|
||||
this.elementIndex = elementIndex;
|
||||
this.eventName = eventName;
|
||||
}
|
||||
}
|
|
@ -26,12 +26,6 @@ import {
|
|||
RenderViewRef,
|
||||
RenderFragmentRef
|
||||
} from "angular2/src/render/api";
|
||||
import {
|
||||
MessageBus,
|
||||
MessageBusSource,
|
||||
MessageBusSink,
|
||||
SourceListener
|
||||
} from "angular2/src/web-workers/shared/message_bus";
|
||||
import {
|
||||
RenderProtoViewRefStore,
|
||||
WebworkerRenderProtoViewRef
|
||||
|
@ -44,6 +38,7 @@ import {resolveInternalDomProtoView} from 'angular2/src/render/dom/view/proto_vi
|
|||
import {someComponent} from '../../render/dom/dom_renderer_integration_spec';
|
||||
import {WebWorkerMain} from 'angular2/src/web-workers/ui/impl';
|
||||
import {AnchorBasedAppRootUrl} from 'angular2/src/services/anchor_based_app_root_url';
|
||||
import {MockMessageBus, MockMessageBusSink, MockMessageBusSource} from './worker_test_util';
|
||||
|
||||
export function main() {
|
||||
function createBroker(workerSerializer: Serializer, uiSerializer: Serializer, tb: DomTestbed,
|
||||
|
@ -56,7 +51,7 @@ export function main() {
|
|||
workerMessageBus.attachToBus(uiMessageBus);
|
||||
|
||||
// set up the worker side
|
||||
var broker = new MessageBroker(workerMessageBus, workerSerializer);
|
||||
var broker = new MessageBroker(workerMessageBus, workerSerializer, null);
|
||||
|
||||
// set up the ui side
|
||||
var webWorkerMain = new WebWorkerMain(tb.compiler, tb.renderer, uiRenderViewStore, uiSerializer,
|
||||
|
@ -118,7 +113,6 @@ export function main() {
|
|||
});
|
||||
|
||||
describe("Web Worker Renderer", () => {
|
||||
beforeEachBindings(() => [DomTestbed]);
|
||||
var renderer: WorkerRenderer;
|
||||
var workerSerializer: Serializer;
|
||||
var workerRenderViewStore: RenderViewWithFragmentsStore;
|
||||
|
@ -145,7 +139,6 @@ export function main() {
|
|||
workerRenderViewStore);
|
||||
});
|
||||
|
||||
|
||||
it('should create and destroy root host views while using the given elements in place',
|
||||
inject([AsyncTestCompleter], (async) => {
|
||||
tb.compiler.compileHost(someComponent)
|
||||
|
@ -313,32 +306,3 @@ function createSerializer(protoViewRefStore: RenderProtoViewRefStore,
|
|||
]);
|
||||
return injector.get(Serializer);
|
||||
}
|
||||
|
||||
class MockMessageBusSource implements MessageBusSource {
|
||||
private _listenerStore: Map<int, SourceListener> = new Map<int, SourceListener>();
|
||||
private _numListeners: number = 0;
|
||||
|
||||
addListener(fn: SourceListener): int {
|
||||
this._listenerStore.set(++this._numListeners, fn);
|
||||
return this._numListeners;
|
||||
}
|
||||
|
||||
removeListener(index: int): void { MapWrapper.delete(this._listenerStore, index); }
|
||||
|
||||
receive(message: Object): void {
|
||||
MapWrapper.forEach(this._listenerStore, (fn: SourceListener, key: int) => { fn(message); });
|
||||
}
|
||||
}
|
||||
|
||||
class MockMessageBusSink implements MessageBusSink {
|
||||
private _sendTo: MockMessageBusSource;
|
||||
|
||||
send(message: Object): void { this._sendTo.receive({'data': message}); }
|
||||
|
||||
attachToSource(source: MockMessageBusSource) { this._sendTo = source; }
|
||||
}
|
||||
|
||||
class MockMessageBus implements MessageBus {
|
||||
constructor(public sink: MockMessageBusSink, public source: MockMessageBusSource) {}
|
||||
attachToBus(bus: MockMessageBus) { this.sink.attachToSource(bus.source); }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import {
|
||||
MessageBus,
|
||||
MessageBusSource,
|
||||
MessageBusSink,
|
||||
SourceListener
|
||||
} from "angular2/src/web-workers/shared/message_bus";
|
||||
import {MapWrapper} from "angular2/src/facade/collection";
|
||||
|
||||
export class MockMessageBusSource implements MessageBusSource {
|
||||
private _listenerStore: Map<int, SourceListener> = new Map<int, SourceListener>();
|
||||
private _numListeners: number = 0;
|
||||
|
||||
addListener(fn: SourceListener): int {
|
||||
this._listenerStore.set(++this._numListeners, fn);
|
||||
return this._numListeners;
|
||||
}
|
||||
|
||||
removeListener(index: int): void { MapWrapper.delete(this._listenerStore, index); }
|
||||
|
||||
receive(message: Object): void {
|
||||
MapWrapper.forEach(this._listenerStore, (fn: SourceListener, key: int) => { fn(message); });
|
||||
}
|
||||
}
|
||||
|
||||
export class MockMessageBusSink implements MessageBusSink {
|
||||
private _sendTo: MockMessageBusSource;
|
||||
|
||||
send(message: Object): void { this._sendTo.receive({'data': message}); }
|
||||
|
||||
attachToSource(source: MockMessageBusSource) { this._sendTo = source; }
|
||||
}
|
||||
|
||||
export class MockMessageBus implements MessageBus {
|
||||
constructor(public sink: MockMessageBusSink, public source: MockMessageBusSource) {}
|
||||
attachToBus(bus: MockMessageBus) { this.sink.attachToSource(bus.source); }
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import {verifyNoBrowserErrors} from 'angular2/src/test_lib/e2e_util';
|
||||
import {Promise} from 'angular2/src/facade/async';
|
||||
|
||||
function waitForElement(selector) {
|
||||
var EC = (<any>protractor).ExpectedConditions;
|
||||
|
@ -6,6 +7,12 @@ function waitForElement(selector) {
|
|||
browser.wait(EC.presenceOf($(selector)), 10000);
|
||||
}
|
||||
|
||||
// returns a promise that resolves in the given number of milliseconds
|
||||
function wait(time) {
|
||||
var promise = new Promise((resolve, reject) => { setTimeout(resolve, time); });
|
||||
return promise;
|
||||
}
|
||||
|
||||
describe('routing inbox-app', function() {
|
||||
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
|
@ -62,6 +69,7 @@ describe('routing inbox-app', function() {
|
|||
waitForElement('#item-10');
|
||||
element(by.css('#item-10')).click();
|
||||
waitForElement('#record-id');
|
||||
browser.wait(wait(500), 600);
|
||||
expect(element(by.css('#record-id')).getText()).toEqual('ID: 10');
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
library examples.e2e_test.web_workers.web_workers_spec;
|
||||
|
||||
main() {
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import {verifyNoBrowserErrors} from 'angular2/src/test_lib/e2e_util';
|
||||
import {Promise} from 'angular2/src/facade/async';
|
||||
|
||||
// returns a promise that resolves in the given number of milliseconds
|
||||
function wait(time) {
|
||||
var promise = new Promise((resolve, reject) => { setTimeout(resolve, time); });
|
||||
return promise;
|
||||
}
|
||||
|
||||
describe('WebWorkers', function() {
|
||||
afterEach(verifyNoBrowserErrors);
|
||||
var selector = "hello-app .greeting";
|
||||
var URL = "examples/src/web_workers/index.html";
|
||||
|
||||
it('should greet', () => {
|
||||
browser.get(URL);
|
||||
|
||||
browser.wait(protractor.until.elementLocated(by.css(selector)), 5000);
|
||||
expect(element.all(by.css(selector)).first().getText()).toEqual("hello world!");
|
||||
});
|
||||
|
||||
it('should change greeting', () => {
|
||||
browser.get(URL);
|
||||
|
||||
browser.wait(protractor.until.elementLocated(by.css(selector)), 5000);
|
||||
element.all(by.css(".changeButton")).first().click();
|
||||
browser.wait(wait(500), 600);
|
||||
expect(element.all(by.css(selector)).first().getText()).toEqual("howdy world!");
|
||||
});
|
||||
|
||||
it("should display correct key names", () => {
|
||||
browser.get(URL);
|
||||
browser.wait(protractor.until.elementLocated(by.css(".sample-area")), 5000);
|
||||
|
||||
var area = element.all(by.css(".sample-area")).first();
|
||||
expect(area.getText()).toEqual('(none)');
|
||||
browser.wait(wait(500), 600);
|
||||
|
||||
area.sendKeys('u');
|
||||
expect(area.getText()).toEqual("U");
|
||||
});
|
||||
});
|
|
@ -4,6 +4,7 @@ import "package:angular2/src/web-workers/worker/application.dart"
|
|||
show WorkerMessageBus, WorkerMessageBusSource, WorkerMessageBusSink;
|
||||
import "package:angular2/src/web-workers/worker/broker.dart"
|
||||
show MessageBroker, UiArguments;
|
||||
import "package:angular2/src/web-workers/shared/serializer.dart" show Serializer;
|
||||
|
||||
import "dart:isolate";
|
||||
|
||||
|
@ -17,7 +18,7 @@ main(List<String> args, SendPort replyTo) {
|
|||
}
|
||||
});
|
||||
|
||||
MessageBroker broker = new MessageBroker(bus, null);
|
||||
MessageBroker broker = new MessageBroker(bus, new Serializer(null, null, null), null);
|
||||
var args = new UiArguments("test", "tester");
|
||||
broker.runOnUiThread(args, String).then((data) {
|
||||
bus.sink.send({"type": "result", "value": data});
|
||||
|
|
|
@ -14,7 +14,7 @@ export function main() {
|
|||
}
|
||||
});
|
||||
|
||||
var broker = new MessageBroker(bus, new Serializer(null));
|
||||
var broker = new MessageBroker(bus, new Serializer(null, null, null), null);
|
||||
var args = new UiArguments("test", "tester");
|
||||
broker.runOnUiThread(args, String)
|
||||
.then((data: string) => { bus.sink.send({type: "result", value: data}); });
|
||||
|
|
|
@ -19,7 +19,7 @@ main() {
|
|||
.appendHtml("<span class='response'>${data['value']}</span>");
|
||||
} else if (identical(data['type'], "test")) {
|
||||
bus.sink.send(
|
||||
{'type': "result", 'value': {'id': data['id'], 'value': VALUE}});
|
||||
{'type': "result", 'id': data['id'], 'value': VALUE});
|
||||
} else if (identical(data['type'], "result")) {
|
||||
querySelector("#ui_result")
|
||||
.appendHtml("<span class='result'>${data['value']}</span>");
|
||||
|
|
|
@ -19,7 +19,7 @@ bus.source.addListener((message) => {
|
|||
document.getElementById("echo_result").innerHTML =
|
||||
`<span class='response'>${message.data.value}</span>`;
|
||||
} else if (message.data.type === "test") {
|
||||
bus.sink.send({type: "result", value: {id: message.data.id, value: VALUE}});
|
||||
bus.sink.send({type: "result", id: message.data.id, value: VALUE});
|
||||
} else if (message.data.type == "result") {
|
||||
document.getElementById("ui_result").innerHTML =
|
||||
`<span class='result'>${message.data.value}</span>`;
|
||||
|
|
|
@ -9,5 +9,5 @@ import "package:angular2/src/reflection/reflection.dart";
|
|||
|
||||
main(List<String> args, SendPort replyTo) {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
bootstrapWebworker(replyTo, HelloCmp);
|
||||
bootstrapWebworker(replyTo, HelloCmp).catchError((error) => throw error);
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<title>Hello Angular 2.0</title>
|
||||
<body>
|
||||
<hello-app>
|
||||
Loading...
|
||||
</hello-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<title>Hello Angular 2.0</title>
|
||||
<style>
|
||||
.sample-area {
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #d0d0d0;
|
||||
}
|
||||
.sample-area:focus {
|
||||
border: 1px solid blue;
|
||||
color: blue;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<hello-app>
|
||||
Loading...
|
||||
</hello-app>
|
||||
|
||||
$SCRIPTS$
|
||||
</body>
|
||||
</html>
|
|
@ -1,4 +1,5 @@
|
|||
import {ElementRef, Component, Directive, View, Injectable, Renderer} from 'angular2/angular2';
|
||||
import {StringWrapper} from 'angular2/src/facade/lang';
|
||||
|
||||
// A service available to the Injector, used by the HelloCmp component.
|
||||
@Injectable()
|
||||
|
@ -37,7 +38,8 @@ class RedDec {
|
|||
// Expressions in the template (like {{greeting}}) are evaluated in the
|
||||
// context of the HelloCmp class below.
|
||||
template: `<div class="greeting">{{greeting}} <span red>world</span>!</div>
|
||||
<button class="changeButton">change greeting</button>`,
|
||||
<button class="changeButton" (click)="changeGreeting()">change greeting</button>
|
||||
<div (keydown)="onKeyDown($event)" class="sample-area" tabindex="0">{{lastKey}}</div><br>`,
|
||||
// All directives used in the template need to be specified. This allows for
|
||||
// modularity (RedDec can only be used in this template)
|
||||
// and better tooling (the template can be invalidated if the attribute is
|
||||
|
@ -46,8 +48,11 @@ class RedDec {
|
|||
})
|
||||
export class HelloCmp {
|
||||
greeting: string;
|
||||
lastKey: string = '(none)';
|
||||
|
||||
constructor(service: GreetingService) { this.greeting = service.greeting; }
|
||||
|
||||
changeGreeting(): void { this.greeting = 'howdy'; }
|
||||
|
||||
onKeyDown(event): void { this.lastKey = StringWrapper.fromCharCode(event['keyCode']); }
|
||||
}
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
$SCRIPTS$
|
||||
$SCRIPTS$ window = {
|
||||
setTimeout: setTimeout,
|
||||
Map: Map,
|
||||
Set: Set,
|
||||
Array: Array,
|
||||
Reflect: Reflect,
|
||||
RegExp: RegExp,
|
||||
Promise: Promise,
|
||||
Date: Date,
|
||||
zone: zone
|
||||
};
|
||||
assert = function() {};
|
||||
|
||||
// TODO (jteplitz) Monkey patch this from within angular (#3207)
|
||||
window = {
|
||||
setTimeout: setTimeout,
|
||||
Map: Map,
|
||||
Set: Set,
|
||||
Array: Array,
|
||||
Reflect: Reflect,
|
||||
RegExp: RegExp,
|
||||
Promise: Promise,
|
||||
Date: Date
|
||||
};
|
||||
assert = function() {}
|
||||
|
||||
|
||||
System.import("examples/src/web_workers/background_index")
|
||||
.then(
|
||||
function(m) {
|
||||
console.log("running main");
|
||||
try {
|
||||
m.main();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
function(error) { console.error("error loading background", error); });
|
||||
System.import("examples/src/web_workers/background_index")
|
||||
.then(
|
||||
function(m) {
|
||||
console.log("running main");
|
||||
try {
|
||||
m.main();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
function(error) { console.error("error loading background", error); });
|
||||
|
|
Loading…
Reference in New Issue